├── library.properties ├── README.md ├── keywords.txt ├── library.json ├── examples ├── DS2408_Switch │ └── DS2408_Switch.pde ├── DS18x20_Temperature │ └── DS18x20_Temperature.pde └── DS250x_PROM │ └── DS250x_PROM.pde ├── OneWire.h └── OneWire.cpp /library.properties: -------------------------------------------------------------------------------- 1 | name=OneWire 2 | version=2.3.3 3 | author=Jim Studt, Tom Pollard, Robin James, Glenn Trewitt, Jason Dangel, Guillermo Lovato, Paul Stoffregen, Scott Roberts, Bertrik Sikken, Mark Tillotson, Ken Butcher, Roger Clark, Love Nystrom 4 | maintainer=Paul Stoffregen 5 | sentence=Access 1-wire temperature sensors, memory and other chips. 6 | paragraph= Mod of Paul Stoffregen code to support ESP32 7 | category=Communication 8 | url=http://www.pjrc.com/teensy/td_libs_OneWire.html 9 | architectures=esp32 10 | 11 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # OneWire library 2 | A modification of the Arduino OneWire library maintained by @PaulStoffregen. This modifications supports the ESP32 under the Arduino-esp32 Environment. 3 | 4 | No changes are required for compatibility with Arduino coding. 5 | 6 | Original Source is Paul's 2.3 version. Forked 28DEC2017 7 | 8 | @stickbreaker 9 | V2.3.1 30APR2018 add IRAM_ATTR to read_bit() write_bit() to solve ICache miss timing failure. 10 | thanks @everslick re: https://github.com/espressif/arduino-esp32/issues/1335 11 | V2.3 28DEC2017 original mods to support ESP32 12 | -------------------------------------------------------------------------------- /keywords.txt: -------------------------------------------------------------------------------- 1 | ####################################### 2 | # Syntax Coloring Map For OneWire 3 | ####################################### 4 | 5 | ####################################### 6 | # Datatypes (KEYWORD1) 7 | ####################################### 8 | 9 | OneWire KEYWORD1 10 | 11 | ####################################### 12 | # Methods and Functions (KEYWORD2) 13 | ####################################### 14 | 15 | reset KEYWORD2 16 | write_bit KEYWORD2 17 | read_bit KEYWORD2 18 | write KEYWORD2 19 | write_bytes KEYWORD2 20 | read KEYWORD2 21 | read_bytes KEYWORD2 22 | select KEYWORD2 23 | skip KEYWORD2 24 | depower KEYWORD2 25 | reset_search KEYWORD2 26 | search KEYWORD2 27 | crc8 KEYWORD2 28 | crc16 KEYWORD2 29 | check_crc16 KEYWORD2 30 | 31 | ####################################### 32 | # Instances (KEYWORD2) 33 | ####################################### 34 | 35 | 36 | ####################################### 37 | # Constants (LITERAL1) 38 | ####################################### 39 | -------------------------------------------------------------------------------- /library.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "OneWire", 3 | "description": "Control 1-Wire protocol (DS18S20, DS18B20, DS2408 and etc)", 4 | "keywords": "onewire, 1-wire, bus, sensor, temperature, ibutton", 5 | "authors": [ 6 | { 7 | "name": "Paul Stoffregen", 8 | "email": "paul@pjrc.com", 9 | "url": "http://www.pjrc.com", 10 | "maintainer": true 11 | }, 12 | { 13 | "name": "Jim Studt" 14 | }, 15 | { 16 | "name": "Tom Pollard", 17 | "email": "pollard@alum.mit.edu" 18 | }, 19 | { 20 | "name": "Derek Yerger" 21 | }, 22 | { 23 | "name": "Josh Larios" 24 | }, 25 | { 26 | "name": "Robin James" 27 | }, 28 | { 29 | "name": "Glenn Trewitt" 30 | }, 31 | { 32 | "name": "Jason Dangel", 33 | "email": "dangel.jason AT gmail.com" 34 | }, 35 | { 36 | "name": "Guillermo Lovato" 37 | }, 38 | { 39 | "name": "Ken Butcher" 40 | }, 41 | { 42 | "name": "Mark Tillotson" 43 | }, 44 | { 45 | "name": "Bertrik Sikken" 46 | }, 47 | { 48 | "name": "Scott Roberts" 49 | } 50 | ], 51 | "repository": { 52 | "type": "git", 53 | "url": "https://github.com/PaulStoffregen/OneWire" 54 | }, 55 | "version": "2.3.2", 56 | "homepage": "https://www.pjrc.com/teensy/td_libs_OneWire.html", 57 | "frameworks": "Arduino", 58 | "examples": [ 59 | "examples/*/*.pde" 60 | ] 61 | } 62 | -------------------------------------------------------------------------------- /examples/DS2408_Switch/DS2408_Switch.pde: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | /* 4 | * DS2408 8-Channel Addressable Switch 5 | * 6 | * Writte by Glenn Trewitt, glenn at trewitt dot org 7 | * 8 | * Some notes about the DS2408: 9 | * - Unlike most input/output ports, the DS2408 doesn't have mode bits to 10 | * set whether the pins are input or output. If you issue a read command, 11 | * they're inputs. If you write to them, they're outputs. 12 | * - For reading from a switch, you should use 10K pull-up resisters. 13 | */ 14 | 15 | OneWire net(10); // on pin 10 16 | 17 | 18 | void PrintBytes(const uint8_t* addr, uint8_t count, bool newline=false) { 19 | for (uint8_t i = 0; i < count; i++) { 20 | Serial.print(addr[i]>>4, HEX); 21 | Serial.print(addr[i]&0x0f, HEX); 22 | } 23 | if (newline) 24 | Serial.println(); 25 | } 26 | 27 | 28 | void setup(void) { 29 | Serial.begin(9600); 30 | } 31 | 32 | void loop(void) { 33 | byte addr[8]; 34 | 35 | if (!net.search(addr)) { 36 | Serial.print("No more addresses.\n"); 37 | net.reset_search(); 38 | delay(1000); 39 | return; 40 | } 41 | 42 | if (OneWire::crc8(addr, 7) != addr[7]) { 43 | Serial.print("CRC is not valid!\n"); 44 | return; 45 | } 46 | 47 | if (addr[0] != 0x29) { 48 | PrintBytes(addr, 8); 49 | Serial.print(" is not a DS2408.\n"); 50 | return; 51 | } 52 | 53 | Serial.print(" Reading DS2408 "); 54 | PrintBytes(addr, 8); 55 | Serial.println(); 56 | 57 | uint8_t buf[13]; // Put everything in the buffer so we can compute CRC easily. 58 | buf[0] = 0xF0; // Read PIO Registers 59 | buf[1] = 0x88; // LSB address 60 | buf[2] = 0x00; // MSB address 61 | net.write_bytes(buf, 3); 62 | net.read_bytes(buf+3, 10); // 3 cmd bytes, 6 data bytes, 2 0xFF, 2 CRC16 63 | net.reset(); 64 | 65 | if (!OneWire::check_crc16(buf, 11, &buf[11])) { 66 | Serial.print("CRC failure in DS2408 at "); 67 | PrintBytes(addr, 8, true); 68 | return; 69 | } 70 | Serial.print(" DS2408 data = "); 71 | // First 3 bytes contain command, register address. 72 | Serial.println(buf[3], BIN); 73 | } 74 | 75 | -------------------------------------------------------------------------------- /examples/DS18x20_Temperature/DS18x20_Temperature.pde: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | // OneWire DS18S20, DS18B20, DS1822 Temperature Example 4 | // 5 | // http://www.pjrc.com/teensy/td_libs_OneWire.html 6 | // 7 | // The DallasTemperature library can do all this work for you! 8 | // http://milesburton.com/Dallas_Temperature_Control_Library 9 | 10 | OneWire ds(10); // on pin 10 (a 4.7K resistor is necessary) 11 | 12 | void setup(void) { 13 | Serial.begin(9600); 14 | } 15 | 16 | void loop(void) { 17 | byte i; 18 | byte present = 0; 19 | byte type_s; 20 | byte data[12]; 21 | byte addr[8]; 22 | float celsius, fahrenheit; 23 | 24 | if ( !ds.search(addr)) { 25 | Serial.println("No more addresses."); 26 | Serial.println(); 27 | ds.reset_search(); 28 | delay(250); 29 | return; 30 | } 31 | 32 | Serial.print("ROM ="); 33 | for( i = 0; i < 8; i++) { 34 | Serial.write(' '); 35 | Serial.print(addr[i], HEX); 36 | } 37 | 38 | if (OneWire::crc8(addr, 7) != addr[7]) { 39 | Serial.println("CRC is not valid!"); 40 | return; 41 | } 42 | Serial.println(); 43 | 44 | // the first ROM byte indicates which chip 45 | switch (addr[0]) { 46 | case 0x10: 47 | Serial.println(" Chip = DS18S20"); // or old DS1820 48 | type_s = 1; 49 | break; 50 | case 0x28: 51 | Serial.println(" Chip = DS18B20"); 52 | type_s = 0; 53 | break; 54 | case 0x22: 55 | Serial.println(" Chip = DS1822"); 56 | type_s = 0; 57 | break; 58 | default: 59 | Serial.println("Device is not a DS18x20 family device."); 60 | return; 61 | } 62 | 63 | ds.reset(); 64 | ds.select(addr); 65 | ds.write(0x44, 1); // start conversion, with parasite power on at the end 66 | 67 | delay(1000); // maybe 750ms is enough, maybe not 68 | // we might do a ds.depower() here, but the reset will take care of it. 69 | 70 | present = ds.reset(); 71 | ds.select(addr); 72 | ds.write(0xBE); // Read Scratchpad 73 | 74 | Serial.print(" Data = "); 75 | Serial.print(present, HEX); 76 | Serial.print(" "); 77 | for ( i = 0; i < 9; i++) { // we need 9 bytes 78 | data[i] = ds.read(); 79 | Serial.print(data[i], HEX); 80 | Serial.print(" "); 81 | } 82 | Serial.print(" CRC="); 83 | Serial.print(OneWire::crc8(data, 8), HEX); 84 | Serial.println(); 85 | 86 | // Convert the data to actual temperature 87 | // because the result is a 16 bit signed integer, it should 88 | // be stored to an "int16_t" type, which is always 16 bits 89 | // even when compiled on a 32 bit processor. 90 | int16_t raw = (data[1] << 8) | data[0]; 91 | if (type_s) { 92 | raw = raw << 3; // 9 bit resolution default 93 | if (data[7] == 0x10) { 94 | // "count remain" gives full 12 bit resolution 95 | raw = (raw & 0xFFF0) + 12 - data[6]; 96 | } 97 | } else { 98 | byte cfg = (data[4] & 0x60); 99 | // at lower res, the low bits are undefined, so let's zero them 100 | if (cfg == 0x00) raw = raw & ~7; // 9 bit resolution, 93.75 ms 101 | else if (cfg == 0x20) raw = raw & ~3; // 10 bit res, 187.5 ms 102 | else if (cfg == 0x40) raw = raw & ~1; // 11 bit res, 375 ms 103 | //// default is 12 bit resolution, 750 ms conversion time 104 | } 105 | celsius = (float)raw / 16.0; 106 | fahrenheit = celsius * 1.8 + 32.0; 107 | Serial.print(" Temperature = "); 108 | Serial.print(celsius); 109 | Serial.print(" Celsius, "); 110 | Serial.print(fahrenheit); 111 | Serial.println(" Fahrenheit"); 112 | } 113 | -------------------------------------------------------------------------------- /examples/DS250x_PROM/DS250x_PROM.pde: -------------------------------------------------------------------------------- 1 | /* 2 | DS250x add-only programmable memory reader w/SKIP ROM. 3 | 4 | The DS250x is a 512/1024bit add-only PROM(you can add data but cannot change the old one) that's used mainly for device identification purposes 5 | like serial number, mfgr data, unique identifiers, etc. It uses the Maxim 1-wire bus. 6 | 7 | This sketch will use the SKIP ROM function that skips the 1-Wire search phase since we only have one device connected in the bus on digital pin 6. 8 | If more than one device is connected to the bus, it will fail. 9 | Sketch will not verify if device connected is from the DS250x family since the skip rom function effectively skips the family-id byte readout. 10 | thus it is possible to run this sketch with any Maxim OneWire device in which case the command CRC will most likely fail. 11 | Sketch will only read the first page of memory(32bits) starting from the lower address(0000h), if more than 1 device is present, then use the sketch with search functions. 12 | Remember to put a 4.7K pullup resistor between pin 6 and +Vcc 13 | 14 | To change the range or ammount of data to read, simply change the data array size, LSB/MSB addresses and for loop iterations 15 | 16 | This example code is in the public domain and is provided AS-IS. 17 | 18 | Built with Arduino 0022 and PJRC OneWire 2.0 library http://www.pjrc.com/teensy/td_libs_OneWire.html 19 | 20 | created by Guillermo Lovato 21 | march/2011 22 | 23 | */ 24 | 25 | #include 26 | OneWire ds(6); // OneWire bus on digital pin 6 27 | void setup() { 28 | Serial.begin (9600); 29 | } 30 | 31 | void loop() { 32 | byte i; // This is for the for loops 33 | boolean present; // device present var 34 | byte data[32]; // container for the data from device 35 | byte leemem[3] = { // array with the commands to initiate a read, DS250x devices expect 3 bytes to start a read: command,LSB&MSB adresses 36 | 0xF0 , 0x00 , 0x00 }; // 0xF0 is the Read Data command, followed by 00h 00h as starting address(the beginning, 0000h) 37 | byte ccrc; // Variable to store the command CRC 38 | byte ccrc_calc; 39 | 40 | present = ds.reset(); // OneWire bus reset, always needed to start operation on the bus, returns a 1/TRUE if there's a device present. 41 | ds.skip(); // Skip ROM search 42 | 43 | if (present == TRUE){ // We only try to read the data if there's a device present 44 | Serial.println("DS250x device present"); 45 | ds.write(leemem[0],1); // Read data command, leave ghost power on 46 | ds.write(leemem[1],1); // LSB starting address, leave ghost power on 47 | ds.write(leemem[2],1); // MSB starting address, leave ghost power on 48 | 49 | ccrc = ds.read(); // DS250x generates a CRC for the command we sent, we assign a read slot and store it's value 50 | ccrc_calc = OneWire::crc8(leemem, 3); // We calculate the CRC of the commands we sent using the library function and store it 51 | 52 | if ( ccrc_calc != ccrc) { // Then we compare it to the value the ds250x calculated, if it fails, we print debug messages and abort 53 | Serial.println("Invalid command CRC!"); 54 | Serial.print("Calculated CRC:"); 55 | Serial.println(ccrc_calc,HEX); // HEX makes it easier to observe and compare 56 | Serial.print("DS250x readback CRC:"); 57 | Serial.println(ccrc,HEX); 58 | return; // Since CRC failed, we abort the rest of the loop and start over 59 | } 60 | Serial.println("Data is: "); // For the printout of the data 61 | for ( i = 0; i < 32; i++) { // Now it's time to read the PROM data itself, each page is 32 bytes so we need 32 read commands 62 | data[i] = ds.read(); // we store each read byte to a different position in the data array 63 | Serial.print(data[i]); // printout in ASCII 64 | Serial.print(" "); // blank space 65 | } 66 | Serial.println(); 67 | delay(5000); // Delay so we don't saturate the serial output 68 | } 69 | else { // Nothing is connected in the bus 70 | Serial.println("Nothing connected"); 71 | delay(3000); 72 | } 73 | } 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | -------------------------------------------------------------------------------- /OneWire.h: -------------------------------------------------------------------------------- 1 | #ifndef OneWire_h 2 | #define OneWire_h 3 | 4 | #include 5 | 6 | #if defined(__AVR__) 7 | #include 8 | #endif 9 | 10 | #if ARDUINO >= 100 11 | #include "Arduino.h" // for delayMicroseconds, digitalPinToBitMask, etc 12 | #else 13 | #include "WProgram.h" // for delayMicroseconds 14 | #include "pins_arduino.h" // for digitalPinToBitMask, etc 15 | #endif 16 | 17 | // You can exclude certain features from OneWire. In theory, this 18 | // might save some space. In practice, the compiler automatically 19 | // removes unused code (technically, the linker, using -fdata-sections 20 | // and -ffunction-sections when compiling, and Wl,--gc-sections 21 | // when linking), so most of these will not result in any code size 22 | // reduction. Well, unless you try to use the missing features 23 | // and redesign your program to not need them! ONEWIRE_CRC8_TABLE 24 | // is the exception, because it selects a fast but large algorithm 25 | // or a small but slow algorithm. 26 | 27 | // you can exclude onewire_search by defining that to 0 28 | #ifndef ONEWIRE_SEARCH 29 | #define ONEWIRE_SEARCH 1 30 | #endif 31 | 32 | // You can exclude CRC checks altogether by defining this to 0 33 | #ifndef ONEWIRE_CRC 34 | #define ONEWIRE_CRC 1 35 | #endif 36 | 37 | // Select the table-lookup method of computing the 8-bit CRC 38 | // by setting this to 1. The lookup table enlarges code size by 39 | // about 250 bytes. It does NOT consume RAM (but did in very 40 | // old versions of OneWire). If you disable this, a slower 41 | // but very compact algorithm is used. 42 | #ifndef ONEWIRE_CRC8_TABLE 43 | #define ONEWIRE_CRC8_TABLE 1 44 | #endif 45 | 46 | // You can allow 16-bit CRC checks by defining this to 1 47 | // (Note that ONEWIRE_CRC must also be 1.) 48 | #ifndef ONEWIRE_CRC16 49 | #define ONEWIRE_CRC16 1 50 | #endif 51 | 52 | #ifndef FALSE 53 | #define FALSE 0 54 | #endif 55 | #ifndef TRUE 56 | #define TRUE 1 57 | #endif 58 | 59 | // Platform specific I/O definitions 60 | 61 | #if defined(__AVR__) 62 | #define PIN_TO_BASEREG(pin) (portInputRegister(digitalPinToPort(pin))) 63 | #define PIN_TO_BITMASK(pin) (digitalPinToBitMask(pin)) 64 | #define IO_REG_TYPE uint8_t 65 | #define IO_REG_BASE_ATTR asm("r30") 66 | #define IO_REG_MASK_ATTR 67 | #define DIRECT_READ(base, mask) (((*(base)) & (mask)) ? 1 : 0) 68 | #define DIRECT_MODE_INPUT(base, mask) ((*((base)+1)) &= ~(mask)) 69 | #define DIRECT_MODE_OUTPUT(base, mask) ((*((base)+1)) |= (mask)) 70 | #define DIRECT_WRITE_LOW(base, mask) ((*((base)+2)) &= ~(mask)) 71 | #define DIRECT_WRITE_HIGH(base, mask) ((*((base)+2)) |= (mask)) 72 | 73 | #elif defined(__MK20DX128__) || defined(__MK20DX256__) || defined(__MK66FX1M0__) || defined(__MK64FX512__) 74 | #define PIN_TO_BASEREG(pin) (portOutputRegister(pin)) 75 | #define PIN_TO_BITMASK(pin) (1) 76 | #define IO_REG_TYPE uint8_t 77 | #define IO_REG_BASE_ATTR 78 | #define IO_REG_MASK_ATTR __attribute__ ((unused)) 79 | #define DIRECT_READ(base, mask) (*((base)+512)) 80 | #define DIRECT_MODE_INPUT(base, mask) (*((base)+640) = 0) 81 | #define DIRECT_MODE_OUTPUT(base, mask) (*((base)+640) = 1) 82 | #define DIRECT_WRITE_LOW(base, mask) (*((base)+256) = 1) 83 | #define DIRECT_WRITE_HIGH(base, mask) (*((base)+128) = 1) 84 | 85 | #elif defined(__MKL26Z64__) 86 | #define PIN_TO_BASEREG(pin) (portOutputRegister(pin)) 87 | #define PIN_TO_BITMASK(pin) (digitalPinToBitMask(pin)) 88 | #define IO_REG_TYPE uint8_t 89 | #define IO_REG_BASE_ATTR 90 | #define IO_REG_MASK_ATTR 91 | #define DIRECT_READ(base, mask) ((*((base)+16) & (mask)) ? 1 : 0) 92 | #define DIRECT_MODE_INPUT(base, mask) (*((base)+20) &= ~(mask)) 93 | #define DIRECT_MODE_OUTPUT(base, mask) (*((base)+20) |= (mask)) 94 | #define DIRECT_WRITE_LOW(base, mask) (*((base)+8) = (mask)) 95 | #define DIRECT_WRITE_HIGH(base, mask) (*((base)+4) = (mask)) 96 | 97 | #elif defined(__SAM3X8E__) || defined(__SAM3A8C__) || defined(__SAM3A4C__) 98 | // Arduino 1.5.1 may have a bug in delayMicroseconds() on Arduino Due. 99 | // http://arduino.cc/forum/index.php/topic,141030.msg1076268.html#msg1076268 100 | // If you have trouble with OneWire on Arduino Due, please check the 101 | // status of delayMicroseconds() before reporting a bug in OneWire! 102 | #define PIN_TO_BASEREG(pin) (&(digitalPinToPort(pin)->PIO_PER)) 103 | #define PIN_TO_BITMASK(pin) (digitalPinToBitMask(pin)) 104 | #define IO_REG_TYPE uint32_t 105 | #define IO_REG_BASE_ATTR 106 | #define IO_REG_MASK_ATTR 107 | #define DIRECT_READ(base, mask) (((*((base)+15)) & (mask)) ? 1 : 0) 108 | #define DIRECT_MODE_INPUT(base, mask) ((*((base)+5)) = (mask)) 109 | #define DIRECT_MODE_OUTPUT(base, mask) ((*((base)+4)) = (mask)) 110 | #define DIRECT_WRITE_LOW(base, mask) ((*((base)+13)) = (mask)) 111 | #define DIRECT_WRITE_HIGH(base, mask) ((*((base)+12)) = (mask)) 112 | #ifndef PROGMEM 113 | #define PROGMEM 114 | #endif 115 | #ifndef pgm_read_byte 116 | #define pgm_read_byte(addr) (*(const uint8_t *)(addr)) 117 | #endif 118 | 119 | #elif defined(__PIC32MX__) 120 | #define PIN_TO_BASEREG(pin) (portModeRegister(digitalPinToPort(pin))) 121 | #define PIN_TO_BITMASK(pin) (digitalPinToBitMask(pin)) 122 | #define IO_REG_TYPE uint32_t 123 | #define IO_REG_BASE_ATTR 124 | #define IO_REG_MASK_ATTR 125 | #define DIRECT_READ(base, mask) (((*(base+4)) & (mask)) ? 1 : 0) //PORTX + 0x10 126 | #define DIRECT_MODE_INPUT(base, mask) ((*(base+2)) = (mask)) //TRISXSET + 0x08 127 | #define DIRECT_MODE_OUTPUT(base, mask) ((*(base+1)) = (mask)) //TRISXCLR + 0x04 128 | #define DIRECT_WRITE_LOW(base, mask) ((*(base+8+1)) = (mask)) //LATXCLR + 0x24 129 | #define DIRECT_WRITE_HIGH(base, mask) ((*(base+8+2)) = (mask)) //LATXSET + 0x28 130 | 131 | #elif defined(ARDUINO_ARCH_ESP8266) 132 | // Special note: I depend on the ESP community to maintain these definitions and 133 | // submit good pull requests. I can not answer any ESP questions or help you 134 | // resolve any problems related to ESP chips. Please do not contact me and please 135 | // DO NOT CREATE GITHUB ISSUES for ESP support. All ESP questions must be asked 136 | // on ESP community forums. 137 | #define PIN_TO_BASEREG(pin) ((volatile uint32_t*) GPO) 138 | #define PIN_TO_BITMASK(pin) (1 << pin) 139 | #define IO_REG_TYPE uint32_t 140 | #define IO_REG_BASE_ATTR 141 | #define IO_REG_MASK_ATTR 142 | #define DIRECT_READ(base, mask) ((GPI & (mask)) ? 1 : 0) //GPIO_IN_ADDRESS 143 | #define DIRECT_MODE_INPUT(base, mask) (GPE &= ~(mask)) //GPIO_ENABLE_W1TC_ADDRESS 144 | #define DIRECT_MODE_OUTPUT(base, mask) (GPE |= (mask)) //GPIO_ENABLE_W1TS_ADDRESS 145 | #define DIRECT_WRITE_LOW(base, mask) (GPOC = (mask)) //GPIO_OUT_W1TC_ADDRESS 146 | #define DIRECT_WRITE_HIGH(base, mask) (GPOS = (mask)) //GPIO_OUT_W1TS_ADDRESS 147 | 148 | #elif defined(ARDUINO_ARCH_ESP32) 149 | #include 150 | #define PIN_TO_BASEREG(pin) (0) 151 | #define PIN_TO_BITMASK(pin) (pin) 152 | #define IO_REG_TYPE uint32_t 153 | #define IO_REG_BASE_ATTR 154 | #define IO_REG_MASK_ATTR 155 | 156 | static inline __attribute__((always_inline)) 157 | IO_REG_TYPE directRead(IO_REG_TYPE pin) 158 | { 159 | if ( pin < 32 ) 160 | return (GPIO.in >> pin) & 0x1; 161 | else if ( pin < 40 ) 162 | return (GPIO.in1.val >> (pin - 32)) & 0x1; 163 | 164 | return 0; 165 | } 166 | 167 | static inline __attribute__((always_inline)) 168 | void directWriteLow(IO_REG_TYPE pin) 169 | { 170 | if ( pin < 32 ) 171 | GPIO.out_w1tc = ((uint32_t)1 << pin); 172 | else if ( pin < 34 ) 173 | GPIO.out1_w1tc.val = ((uint32_t)1 << (pin - 32)); 174 | } 175 | 176 | static inline __attribute__((always_inline)) 177 | void directWriteHigh(IO_REG_TYPE pin) 178 | { 179 | if ( pin < 32 ) 180 | GPIO.out_w1ts = ((uint32_t)1 << pin); 181 | else if ( pin < 34 ) 182 | GPIO.out1_w1ts.val = ((uint32_t)1 << (pin - 32)); 183 | } 184 | 185 | static inline __attribute__((always_inline)) 186 | void directModeInput(IO_REG_TYPE pin) 187 | { 188 | if ( digitalPinIsValid(pin) ) 189 | { 190 | uint32_t rtc_reg(rtc_gpio_desc[pin].reg); 191 | 192 | if ( rtc_reg ) // RTC pins PULL settings 193 | { 194 | ESP_REG(rtc_reg) = ESP_REG(rtc_reg) & ~(rtc_gpio_desc[pin].mux); 195 | ESP_REG(rtc_reg) = ESP_REG(rtc_reg) & ~(rtc_gpio_desc[pin].pullup | rtc_gpio_desc[pin].pulldown); 196 | } 197 | 198 | if ( pin < 32 ) 199 | GPIO.enable_w1tc = ((uint32_t)1 << pin); 200 | else 201 | GPIO.enable1_w1tc.val = ((uint32_t)1 << (pin - 32)); 202 | 203 | uint32_t pinFunction((uint32_t)2 << FUN_DRV_S); // what are the drivers? 204 | pinFunction |= FUN_IE; // input enable but required for output as well? 205 | pinFunction |= ((uint32_t)2 << MCU_SEL_S); 206 | 207 | ESP_REG(DR_REG_IO_MUX_BASE + esp32_gpioMux[pin].reg) = pinFunction; 208 | 209 | GPIO.pin[pin].val = 0; 210 | } 211 | } 212 | 213 | static inline __attribute__((always_inline)) 214 | void directModeOutput(IO_REG_TYPE pin) 215 | { 216 | if ( digitalPinIsValid(pin) && pin <= 33 ) // pins above 33 can be only inputs 217 | { 218 | uint32_t rtc_reg(rtc_gpio_desc[pin].reg); 219 | 220 | if ( rtc_reg ) // RTC pins PULL settings 221 | { 222 | ESP_REG(rtc_reg) = ESP_REG(rtc_reg) & ~(rtc_gpio_desc[pin].mux); 223 | ESP_REG(rtc_reg) = ESP_REG(rtc_reg) & ~(rtc_gpio_desc[pin].pullup | rtc_gpio_desc[pin].pulldown); 224 | } 225 | 226 | if ( pin < 32 ) 227 | GPIO.enable_w1ts = ((uint32_t)1 << pin); 228 | else // already validated to pins <= 33 229 | GPIO.enable1_w1ts.val = ((uint32_t)1 << (pin - 32)); 230 | 231 | uint32_t pinFunction((uint32_t)2 << FUN_DRV_S); // what are the drivers? 232 | pinFunction |= FUN_IE; // input enable but required for output as well? 233 | pinFunction |= ((uint32_t)2 << MCU_SEL_S); 234 | 235 | ESP_REG(DR_REG_IO_MUX_BASE + esp32_gpioMux[pin].reg) = pinFunction; 236 | 237 | GPIO.pin[pin].val = 0; 238 | } 239 | } 240 | 241 | #define DIRECT_READ(base, pin) directRead(pin) 242 | #define DIRECT_WRITE_LOW(base, pin) directWriteLow(pin) 243 | #define DIRECT_WRITE_HIGH(base, pin) directWriteHigh(pin) 244 | #define DIRECT_MODE_INPUT(base, pin) directModeInput(pin) 245 | #define DIRECT_MODE_OUTPUT(base, pin) directModeOutput(pin) 246 | #warning "ESP32 OneWire testing" 247 | 248 | #elif defined(__SAMD21G18A__) 249 | #define PIN_TO_BASEREG(pin) portModeRegister(digitalPinToPort(pin)) 250 | #define PIN_TO_BITMASK(pin) (digitalPinToBitMask(pin)) 251 | #define IO_REG_TYPE uint32_t 252 | #define IO_REG_BASE_ATTR 253 | #define IO_REG_MASK_ATTR 254 | #define DIRECT_READ(base, mask) (((*((base)+8)) & (mask)) ? 1 : 0) 255 | #define DIRECT_MODE_INPUT(base, mask) ((*((base)+1)) = (mask)) 256 | #define DIRECT_MODE_OUTPUT(base, mask) ((*((base)+2)) = (mask)) 257 | #define DIRECT_WRITE_LOW(base, mask) ((*((base)+5)) = (mask)) 258 | #define DIRECT_WRITE_HIGH(base, mask) ((*((base)+6)) = (mask)) 259 | 260 | #elif defined(RBL_NRF51822) 261 | #define PIN_TO_BASEREG(pin) (0) 262 | #define PIN_TO_BITMASK(pin) (pin) 263 | #define IO_REG_TYPE uint32_t 264 | #define IO_REG_BASE_ATTR 265 | #define IO_REG_MASK_ATTR 266 | #define DIRECT_READ(base, pin) nrf_gpio_pin_read(pin) 267 | #define DIRECT_WRITE_LOW(base, pin) nrf_gpio_pin_clear(pin) 268 | #define DIRECT_WRITE_HIGH(base, pin) nrf_gpio_pin_set(pin) 269 | #define DIRECT_MODE_INPUT(base, pin) nrf_gpio_cfg_input(pin, NRF_GPIO_PIN_NOPULL) 270 | #define DIRECT_MODE_OUTPUT(base, pin) nrf_gpio_cfg_output(pin) 271 | 272 | #elif defined(__arc__) /* Arduino101/Genuino101 specifics */ 273 | 274 | #include "scss_registers.h" 275 | #include "portable.h" 276 | #include "avr/pgmspace.h" 277 | 278 | #define GPIO_ID(pin) (g_APinDescription[pin].ulGPIOId) 279 | #define GPIO_TYPE(pin) (g_APinDescription[pin].ulGPIOType) 280 | #define GPIO_BASE(pin) (g_APinDescription[pin].ulGPIOBase) 281 | #define DIR_OFFSET_SS 0x01 282 | #define DIR_OFFSET_SOC 0x04 283 | #define EXT_PORT_OFFSET_SS 0x0A 284 | #define EXT_PORT_OFFSET_SOC 0x50 285 | 286 | /* GPIO registers base address */ 287 | #define PIN_TO_BASEREG(pin) ((volatile uint32_t *)g_APinDescription[pin].ulGPIOBase) 288 | #define PIN_TO_BITMASK(pin) pin 289 | #define IO_REG_TYPE uint32_t 290 | #define IO_REG_BASE_ATTR 291 | #define IO_REG_MASK_ATTR 292 | 293 | static inline __attribute__((always_inline)) 294 | IO_REG_TYPE directRead(volatile IO_REG_TYPE *base, IO_REG_TYPE pin) 295 | { 296 | IO_REG_TYPE ret; 297 | if (SS_GPIO == GPIO_TYPE(pin)) { 298 | ret = READ_ARC_REG(((IO_REG_TYPE)base + EXT_PORT_OFFSET_SS)); 299 | } else { 300 | ret = MMIO_REG_VAL_FROM_BASE((IO_REG_TYPE)base, EXT_PORT_OFFSET_SOC); 301 | } 302 | return ((ret >> GPIO_ID(pin)) & 0x01); 303 | } 304 | 305 | static inline __attribute__((always_inline)) 306 | void directModeInput(volatile IO_REG_TYPE *base, IO_REG_TYPE pin) 307 | { 308 | if (SS_GPIO == GPIO_TYPE(pin)) { 309 | WRITE_ARC_REG(READ_ARC_REG((((IO_REG_TYPE)base) + DIR_OFFSET_SS)) & ~(0x01 << GPIO_ID(pin)), 310 | ((IO_REG_TYPE)(base) + DIR_OFFSET_SS)); 311 | } else { 312 | MMIO_REG_VAL_FROM_BASE((IO_REG_TYPE)base, DIR_OFFSET_SOC) &= ~(0x01 << GPIO_ID(pin)); 313 | } 314 | } 315 | 316 | static inline __attribute__((always_inline)) 317 | void directModeOutput(volatile IO_REG_TYPE *base, IO_REG_TYPE pin) 318 | { 319 | if (SS_GPIO == GPIO_TYPE(pin)) { 320 | WRITE_ARC_REG(READ_ARC_REG(((IO_REG_TYPE)(base) + DIR_OFFSET_SS)) | (0x01 << GPIO_ID(pin)), 321 | ((IO_REG_TYPE)(base) + DIR_OFFSET_SS)); 322 | } else { 323 | MMIO_REG_VAL_FROM_BASE((IO_REG_TYPE)base, DIR_OFFSET_SOC) |= (0x01 << GPIO_ID(pin)); 324 | } 325 | } 326 | 327 | static inline __attribute__((always_inline)) 328 | void directWriteLow(volatile IO_REG_TYPE *base, IO_REG_TYPE pin) 329 | { 330 | if (SS_GPIO == GPIO_TYPE(pin)) { 331 | WRITE_ARC_REG(READ_ARC_REG(base) & ~(0x01 << GPIO_ID(pin)), base); 332 | } else { 333 | MMIO_REG_VAL(base) &= ~(0x01 << GPIO_ID(pin)); 334 | } 335 | } 336 | 337 | static inline __attribute__((always_inline)) 338 | void directWriteHigh(volatile IO_REG_TYPE *base, IO_REG_TYPE pin) 339 | { 340 | if (SS_GPIO == GPIO_TYPE(pin)) { 341 | WRITE_ARC_REG(READ_ARC_REG(base) | (0x01 << GPIO_ID(pin)), base); 342 | } else { 343 | MMIO_REG_VAL(base) |= (0x01 << GPIO_ID(pin)); 344 | } 345 | } 346 | 347 | #define DIRECT_READ(base, pin) directRead(base, pin) 348 | #define DIRECT_MODE_INPUT(base, pin) directModeInput(base, pin) 349 | #define DIRECT_MODE_OUTPUT(base, pin) directModeOutput(base, pin) 350 | #define DIRECT_WRITE_LOW(base, pin) directWriteLow(base, pin) 351 | #define DIRECT_WRITE_HIGH(base, pin) directWriteHigh(base, pin) 352 | 353 | #elif defined(__riscv) 354 | 355 | /* 356 | * Tested on highfive1 357 | * 358 | * Stable results are achieved operating in the 359 | * two high speed modes of the highfive1. It 360 | * seems to be less reliable in slow mode. 361 | */ 362 | #define PIN_TO_BASEREG(pin) (0) 363 | #define PIN_TO_BITMASK(pin) digitalPinToBitMask(pin) 364 | #define IO_REG_TYPE uint32_t 365 | #define IO_REG_BASE_ATTR 366 | #define IO_REG_MASK_ATTR 367 | 368 | static inline __attribute__((always_inline)) 369 | IO_REG_TYPE directRead(IO_REG_TYPE mask) 370 | { 371 | return ((GPIO_REG(GPIO_INPUT_VAL) & mask) != 0) ? 1 : 0; 372 | } 373 | 374 | static inline __attribute__((always_inline)) 375 | void directModeInput(IO_REG_TYPE mask) 376 | { 377 | GPIO_REG(GPIO_OUTPUT_XOR) &= ~mask; 378 | GPIO_REG(GPIO_IOF_EN) &= ~mask; 379 | 380 | GPIO_REG(GPIO_INPUT_EN) |= mask; 381 | GPIO_REG(GPIO_OUTPUT_EN) &= ~mask; 382 | } 383 | 384 | static inline __attribute__((always_inline)) 385 | void directModeOutput(IO_REG_TYPE mask) 386 | { 387 | GPIO_REG(GPIO_OUTPUT_XOR) &= ~mask; 388 | GPIO_REG(GPIO_IOF_EN) &= ~mask; 389 | 390 | GPIO_REG(GPIO_INPUT_EN) &= ~mask; 391 | GPIO_REG(GPIO_OUTPUT_EN) |= mask; 392 | } 393 | 394 | static inline __attribute__((always_inline)) 395 | void directWriteLow(IO_REG_TYPE mask) 396 | { 397 | GPIO_REG(GPIO_OUTPUT_VAL) &= ~mask; 398 | } 399 | 400 | static inline __attribute__((always_inline)) 401 | void directWriteHigh(IO_REG_TYPE mask) 402 | { 403 | GPIO_REG(GPIO_OUTPUT_VAL) |= mask; 404 | } 405 | 406 | #define DIRECT_READ(base, mask) directRead(mask) 407 | #define DIRECT_WRITE_LOW(base, mask) directWriteLow(mask) 408 | #define DIRECT_WRITE_HIGH(base, mask) directWriteHigh(mask) 409 | #define DIRECT_MODE_INPUT(base, mask) directModeInput(mask) 410 | #define DIRECT_MODE_OUTPUT(base, mask) directModeOutput(mask) 411 | 412 | #else 413 | #define PIN_TO_BASEREG(pin) (0) 414 | #define PIN_TO_BITMASK(pin) (pin) 415 | #define IO_REG_TYPE unsigned int 416 | #define IO_REG_BASE_ATTR 417 | #define IO_REG_MASK_ATTR 418 | #define DIRECT_READ(base, pin) digitalRead(pin) 419 | #define DIRECT_WRITE_LOW(base, pin) digitalWrite(pin, LOW) 420 | #define DIRECT_WRITE_HIGH(base, pin) digitalWrite(pin, HIGH) 421 | #define DIRECT_MODE_INPUT(base, pin) pinMode(pin,INPUT) 422 | #define DIRECT_MODE_OUTPUT(base, pin) pinMode(pin,OUTPUT) 423 | #warning "OneWire. Fallback mode. Using API calls for pinMode,digitalRead and digitalWrite. Operation of this library is not guaranteed on this architecture." 424 | 425 | #endif 426 | 427 | 428 | class OneWire 429 | { 430 | private: 431 | IO_REG_TYPE bitmask; 432 | volatile IO_REG_TYPE *baseReg; 433 | 434 | #if ONEWIRE_SEARCH 435 | // global search state 436 | unsigned char ROM_NO[8]; 437 | uint8_t LastDiscrepancy; 438 | uint8_t LastFamilyDiscrepancy; 439 | uint8_t LastDeviceFlag; 440 | #endif 441 | 442 | public: 443 | OneWire( uint8_t pin); 444 | 445 | // Perform a 1-Wire reset cycle. Returns 1 if a device responds 446 | // with a presence pulse. Returns 0 if there is no device or the 447 | // bus is shorted or otherwise held low for more than 250uS 448 | uint8_t reset(void); 449 | 450 | // Issue a 1-Wire rom select command, you do the reset first. 451 | void select(const uint8_t rom[8]); 452 | 453 | // Issue a 1-Wire rom skip command, to address all on bus. 454 | void skip(void); 455 | 456 | // Write a byte. If 'power' is one then the wire is held high at 457 | // the end for parasitically powered devices. You are responsible 458 | // for eventually depowering it by calling depower() or doing 459 | // another read or write. 460 | void write(uint8_t v, uint8_t power = 0); 461 | 462 | void write_bytes(const uint8_t *buf, uint16_t count, bool power = 0); 463 | 464 | // Read a byte. 465 | uint8_t read(void); 466 | 467 | void read_bytes(uint8_t *buf, uint16_t count); 468 | 469 | // Write a bit. The bus is always left powered at the end, see 470 | // note in write() about that. 471 | void write_bit(uint8_t v); 472 | 473 | // Read a bit. 474 | uint8_t read_bit(void); 475 | 476 | // Stop forcing power onto the bus. You only need to do this if 477 | // you used the 'power' flag to write() or used a write_bit() call 478 | // and aren't about to do another read or write. You would rather 479 | // not leave this powered if you don't have to, just in case 480 | // someone shorts your bus. 481 | void depower(void); 482 | 483 | #if ONEWIRE_SEARCH 484 | // Clear the search state so that if will start from the beginning again. 485 | void reset_search(); 486 | 487 | // Setup the search to find the device type 'family_code' on the next call 488 | // to search(*newAddr) if it is present. 489 | void target_search(uint8_t family_code); 490 | 491 | // Look for the next device. Returns 1 if a new address has been 492 | // returned. A zero might mean that the bus is shorted, there are 493 | // no devices, or you have already retrieved all of them. It 494 | // might be a good idea to check the CRC to make sure you didn't 495 | // get garbage. The order is deterministic. You will always get 496 | // the same devices in the same order. 497 | uint8_t search(uint8_t *newAddr, bool search_mode = true); 498 | #endif 499 | 500 | #if ONEWIRE_CRC 501 | // Compute a Dallas Semiconductor 8 bit CRC, these are used in the 502 | // ROM and scratchpad registers. 503 | static uint8_t crc8(const uint8_t *addr, uint8_t len); 504 | 505 | #if ONEWIRE_CRC16 506 | // Compute the 1-Wire CRC16 and compare it against the received CRC. 507 | // Example usage (reading a DS2408): 508 | // // Put everything in a buffer so we can compute the CRC easily. 509 | // uint8_t buf[13]; 510 | // buf[0] = 0xF0; // Read PIO Registers 511 | // buf[1] = 0x88; // LSB address 512 | // buf[2] = 0x00; // MSB address 513 | // WriteBytes(net, buf, 3); // Write 3 cmd bytes 514 | // ReadBytes(net, buf+3, 10); // Read 6 data bytes, 2 0xFF, 2 CRC16 515 | // if (!CheckCRC16(buf, 11, &buf[11])) { 516 | // // Handle error. 517 | // } 518 | // 519 | // @param input - Array of bytes to checksum. 520 | // @param len - How many bytes to use. 521 | // @param inverted_crc - The two CRC16 bytes in the received data. 522 | // This should just point into the received data, 523 | // *not* at a 16-bit integer. 524 | // @param crc - The crc starting value (optional) 525 | // @return True, iff the CRC matches. 526 | static bool check_crc16(const uint8_t* input, uint16_t len, const uint8_t* inverted_crc, uint16_t crc = 0); 527 | 528 | // Compute a Dallas Semiconductor 16 bit CRC. This is required to check 529 | // the integrity of data received from many 1-Wire devices. Note that the 530 | // CRC computed here is *not* what you'll get from the 1-Wire network, 531 | // for two reasons: 532 | // 1) The CRC is transmitted bitwise inverted. 533 | // 2) Depending on the endian-ness of your processor, the binary 534 | // representation of the two-byte return value may have a different 535 | // byte order than the two bytes you get from 1-Wire. 536 | // @param input - Array of bytes to checksum. 537 | // @param len - How many bytes to use. 538 | // @param crc - The crc starting value (optional) 539 | // @return The CRC16, as defined by Dallas Semiconductor. 540 | static uint16_t crc16(const uint8_t* input, uint16_t len, uint16_t crc = 0); 541 | #endif 542 | #endif 543 | }; 544 | 545 | #endif 546 | -------------------------------------------------------------------------------- /OneWire.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright (c) 2007, Jim Studt (original old version - many contributors since) 3 | 4 | The latest version of this library may be found at: 5 | http://www.pjrc.com/teensy/td_libs_OneWire.html 6 | 7 | OneWire has been maintained by Paul Stoffregen (paul@pjrc.com) since 8 | January 2010. 9 | 10 | DO NOT EMAIL for technical support, especially not for ESP chips! 11 | All project support questions must be posted on public forums 12 | relevant to the board or chips used. If using Arduino, post on 13 | Arduino's forum. If using ESP, post on the ESP community forums. 14 | There is ABSOLUTELY NO TECH SUPPORT BY PRIVATE EMAIL! 15 | 16 | Github's issue tracker for OneWire should be used only to report 17 | specific bugs. DO NOT request project support via Github. All 18 | project and tech support questions must be posted on forums, not 19 | github issues. If you experience a problem and you are not 20 | absolutely sure it's an issue with the library, ask on a forum 21 | first. Only use github to report issues after experts have 22 | confirmed the issue is with OneWire rather than your project. 23 | 24 | Back in 2010, OneWire was in need of many bug fixes, but had 25 | been abandoned the original author (Jim Studt). None of the known 26 | contributors were interested in maintaining OneWire. Paul typically 27 | works on OneWire every 6 to 12 months. Patches usually wait that 28 | long. If anyone is interested in more actively maintaining OneWire, 29 | please contact Paul (this is pretty much the only reason to use 30 | private email about OneWire). 31 | 32 | OneWire is now very mature code. No changes other than adding 33 | definitions for newer hardware support are anticipated. 34 | 35 | ======= 36 | Version 2.3.3 ESP32 Stickbreaker 06MAY2019 37 | Add a #ifdef to isolate ESP32 mods 38 | Version 2.3.1 ESP32 everslick 30APR2018 39 | add IRAM_ATTR attribute to write_bit/read_bit to fix icache miss delay 40 | https://github.com/espressif/arduino-esp32/issues/1335 41 | 42 | Version 2.3 ESP32 stickbreaker 28DEC2017 43 | adjust to use portENTER_CRITICAL(&mux) instead of noInterrupts(); 44 | adjust to use portEXIT_CRITICAL(&mux) instead of Interrupts(); 45 | 46 | Version 2.3: 47 | Unknown chip fallback mode, Roger Clark 48 | Teensy-LC compatibility, Paul Stoffregen 49 | Search bug fix, Love Nystrom 50 | 51 | Version 2.2: 52 | Teensy 3.0 compatibility, Paul Stoffregen, paul@pjrc.com 53 | Arduino Due compatibility, http://arduino.cc/forum/index.php?topic=141030 54 | Fix DS18B20 example negative temperature 55 | Fix DS18B20 example's low res modes, Ken Butcher 56 | Improve reset timing, Mark Tillotson 57 | Add const qualifiers, Bertrik Sikken 58 | Add initial value input to crc16, Bertrik Sikken 59 | Add target_search() function, Scott Roberts 60 | 61 | Version 2.1: 62 | Arduino 1.0 compatibility, Paul Stoffregen 63 | Improve temperature example, Paul Stoffregen 64 | DS250x_PROM example, Guillermo Lovato 65 | PIC32 (chipKit) compatibility, Jason Dangel, dangel.jason AT gmail.com 66 | Improvements from Glenn Trewitt: 67 | - crc16() now works 68 | - check_crc16() does all of calculation/checking work. 69 | - Added read_bytes() and write_bytes(), to reduce tedious loops. 70 | - Added ds2408 example. 71 | Delete very old, out-of-date readme file (info is here) 72 | 73 | Version 2.0: Modifications by Paul Stoffregen, January 2010: 74 | http://www.pjrc.com/teensy/td_libs_OneWire.html 75 | Search fix from Robin James 76 | http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1238032295/27#27 77 | Use direct optimized I/O in all cases 78 | Disable interrupts during timing critical sections 79 | (this solves many random communication errors) 80 | Disable interrupts during read-modify-write I/O 81 | Reduce RAM consumption by eliminating unnecessary 82 | variables and trimming many to 8 bits 83 | Optimize both crc8 - table version moved to flash 84 | 85 | Modified to work with larger numbers of devices - avoids loop. 86 | Tested in Arduino 11 alpha with 12 sensors. 87 | 26 Sept 2008 -- Robin James 88 | http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1238032295/27#27 89 | 90 | Updated to work with arduino-0008 and to include skip() as of 91 | 2007/07/06. --RJL20 92 | 93 | Modified to calculate the 8-bit CRC directly, avoiding the need for 94 | the 256-byte lookup table to be loaded in RAM. Tested in arduino-0010 95 | -- Tom Pollard, Jan 23, 2008 96 | 97 | Jim Studt's original library was modified by Josh Larios. 98 | 99 | Tom Pollard, pollard@alum.mit.edu, contributed around May 20, 2008 100 | 101 | Permission is hereby granted, free of charge, to any person obtaining 102 | a copy of this software and associated documentation files (the 103 | "Software"), to deal in the Software without restriction, including 104 | without limitation the rights to use, copy, modify, merge, publish, 105 | distribute, sublicense, and/or sell copies of the Software, and to 106 | permit persons to whom the Software is furnished to do so, subject to 107 | the following conditions: 108 | 109 | The above copyright notice and this permission notice shall be 110 | included in all copies or substantial portions of the Software. 111 | 112 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 113 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 114 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 115 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 116 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 117 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 118 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 119 | 120 | Much of the code was inspired by Derek Yerger's code, though I don't 121 | think much of that remains. In any event that was.. 122 | (copyleft) 2006 by Derek Yerger - Free to distribute freely. 123 | 124 | The CRC code was excerpted and inspired by the Dallas Semiconductor 125 | sample code bearing this copyright. 126 | //--------------------------------------------------------------------------- 127 | // Copyright (C) 2000 Dallas Semiconductor Corporation, All Rights Reserved. 128 | // 129 | // Permission is hereby granted, free of charge, to any person obtaining a 130 | // copy of this software and associated documentation files (the "Software"), 131 | // to deal in the Software without restriction, including without limitation 132 | // the rights to use, copy, modify, merge, publish, distribute, sublicense, 133 | // and/or sell copies of the Software, and to permit persons to whom the 134 | // Software is furnished to do so, subject to the following conditions: 135 | // 136 | // The above copyright notice and this permission notice shall be included 137 | // in all copies or substantial portions of the Software. 138 | // 139 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 140 | // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 141 | // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 142 | // IN NO EVENT SHALL DALLAS SEMICONDUCTOR BE LIABLE FOR ANY CLAIM, DAMAGES 143 | // OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 144 | // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 145 | // OTHER DEALINGS IN THE SOFTWARE. 146 | // 147 | // Except as contained in this notice, the name of Dallas Semiconductor 148 | // shall not be used except as stated in the Dallas Semiconductor 149 | // Branding Policy. 150 | //-------------------------------------------------------------------------- 151 | */ 152 | 153 | #include "OneWire.h" 154 | 155 | #ifdef ARDUINO_ARCH_ESP32 156 | #define noInterrupts() {portMUX_TYPE mux = portMUX_INITIALIZER_UNLOCKED;portENTER_CRITICAL(&mux) 157 | #define interrupts() portEXIT_CRITICAL(&mux);} 158 | #endif 159 | 160 | OneWire::OneWire(uint8_t pin) 161 | { 162 | pinMode(pin, INPUT); 163 | bitmask = PIN_TO_BITMASK(pin); 164 | baseReg = PIN_TO_BASEREG(pin); 165 | #if ONEWIRE_SEARCH 166 | reset_search(); 167 | #endif 168 | } 169 | 170 | 171 | // Perform the onewire reset function. We will wait up to 250uS for 172 | // the bus to come high, if it doesn't then it is broken or shorted 173 | // and we return a 0; 174 | // 175 | // Returns 1 if a device asserted a presence pulse, 0 otherwise. 176 | // 177 | #ifdef ARDUINO_ARCH_ESP32 178 | uint8_t IRAM_ATTR OneWire::reset(void) 179 | #else 180 | uint8_t OneWire::reset(void) 181 | #endif 182 | { 183 | IO_REG_TYPE mask IO_REG_MASK_ATTR = bitmask; 184 | volatile IO_REG_TYPE *reg IO_REG_BASE_ATTR = baseReg; 185 | uint8_t r; 186 | uint8_t retries = 125; 187 | noInterrupts(); 188 | DIRECT_MODE_INPUT(reg, mask); 189 | interrupts(); 190 | // wait until the wire is high... just in case 191 | do { 192 | if (--retries == 0) return 0; 193 | delayMicroseconds(2); 194 | } while ( !DIRECT_READ(reg, mask)); 195 | 196 | noInterrupts(); 197 | DIRECT_WRITE_LOW(reg, mask); 198 | DIRECT_MODE_OUTPUT(reg, mask); // drive output low 199 | delayMicroseconds(480); 200 | DIRECT_MODE_INPUT(reg, mask); // allow it to float 201 | delayMicroseconds(70); 202 | r = !DIRECT_READ(reg, mask); 203 | interrupts(); 204 | delayMicroseconds(410); 205 | return r; 206 | } 207 | 208 | // 209 | // Write a bit. Port and bit is used to cut lookup time and provide 210 | // more certain timing. 211 | // 212 | #ifdef ARDUINO_ARCH_ESP32 213 | void IRAM_ATTR OneWire::write_bit(uint8_t v) 214 | #else 215 | void OneWire::write_bit(uint8_t v) 216 | #endif 217 | { 218 | IO_REG_TYPE mask IO_REG_MASK_ATTR = bitmask; 219 | volatile IO_REG_TYPE *reg IO_REG_BASE_ATTR = baseReg; 220 | 221 | if (v & 1) { 222 | noInterrupts(); 223 | DIRECT_WRITE_LOW(reg, mask); 224 | DIRECT_MODE_OUTPUT(reg, mask); // drive output low 225 | delayMicroseconds(10); 226 | DIRECT_WRITE_HIGH(reg, mask); // drive output high 227 | interrupts(); 228 | delayMicroseconds(55); 229 | } else { 230 | noInterrupts(); 231 | DIRECT_WRITE_LOW(reg, mask); 232 | DIRECT_MODE_OUTPUT(reg, mask); // drive output low 233 | delayMicroseconds(65); 234 | DIRECT_WRITE_HIGH(reg, mask); // drive output high 235 | interrupts(); 236 | delayMicroseconds(5); 237 | } 238 | } 239 | 240 | // 241 | // Read a bit. Port and bit is used to cut lookup time and provide 242 | // more certain timing. 243 | // 244 | #ifdef ARDUINO_ARCH_ESP32 245 | uint8_t IRAM_ATTR OneWire::read_bit(void) 246 | #else 247 | uint8_t OneWire::read_bit(void) 248 | #endif 249 | { 250 | IO_REG_TYPE mask IO_REG_MASK_ATTR = bitmask; 251 | volatile IO_REG_TYPE *reg IO_REG_BASE_ATTR = baseReg; 252 | uint8_t r; 253 | 254 | noInterrupts(); 255 | DIRECT_MODE_OUTPUT(reg, mask); 256 | DIRECT_WRITE_LOW(reg, mask); 257 | delayMicroseconds(3); 258 | DIRECT_MODE_INPUT(reg, mask); // let pin float, pull up will raise 259 | delayMicroseconds(10); 260 | r = DIRECT_READ(reg, mask); 261 | interrupts(); 262 | delayMicroseconds(53); 263 | return r; 264 | } 265 | 266 | // 267 | // Write a byte. The writing code uses the active drivers to raise the 268 | // pin high, if you need power after the write (e.g. DS18S20 in 269 | // parasite power mode) then set 'power' to 1, otherwise the pin will 270 | // go tri-state at the end of the write to avoid heating in a short or 271 | // other mishap. 272 | // 273 | void OneWire::write(uint8_t v, uint8_t power /* = 0 */) { 274 | uint8_t bitMask; 275 | 276 | for (bitMask = 0x01; bitMask; bitMask <<= 1) { 277 | OneWire::write_bit( (bitMask & v)?1:0); 278 | } 279 | if ( !power) { 280 | noInterrupts(); 281 | DIRECT_MODE_INPUT(baseReg, bitmask); 282 | DIRECT_WRITE_LOW(baseReg, bitmask); 283 | interrupts(); 284 | } 285 | } 286 | 287 | void OneWire::write_bytes(const uint8_t *buf, uint16_t count, bool power /* = 0 */) { 288 | for (uint16_t i = 0 ; i < count ; i++) 289 | write(buf[i]); 290 | if (!power) { 291 | noInterrupts(); 292 | DIRECT_MODE_INPUT(baseReg, bitmask); 293 | DIRECT_WRITE_LOW(baseReg, bitmask); 294 | interrupts(); 295 | } 296 | } 297 | 298 | // 299 | // Read a byte 300 | // 301 | uint8_t OneWire::read() { 302 | uint8_t bitMask; 303 | uint8_t r = 0; 304 | 305 | for (bitMask = 0x01; bitMask; bitMask <<= 1) { 306 | if ( OneWire::read_bit()) r |= bitMask; 307 | } 308 | return r; 309 | } 310 | 311 | void OneWire::read_bytes(uint8_t *buf, uint16_t count) { 312 | for (uint16_t i = 0 ; i < count ; i++) 313 | buf[i] = read(); 314 | } 315 | 316 | // 317 | // Do a ROM select 318 | // 319 | void OneWire::select(const uint8_t rom[8]) 320 | { 321 | uint8_t i; 322 | 323 | write(0x55); // Choose ROM 324 | 325 | for (i = 0; i < 8; i++) write(rom[i]); 326 | } 327 | 328 | // 329 | // Do a ROM skip 330 | // 331 | void OneWire::skip() 332 | { 333 | write(0xCC); // Skip ROM 334 | } 335 | 336 | void OneWire::depower() 337 | { 338 | noInterrupts(); 339 | DIRECT_MODE_INPUT(baseReg, bitmask); 340 | interrupts(); 341 | } 342 | 343 | #if ONEWIRE_SEARCH 344 | 345 | // 346 | // You need to use this function to start a search again from the beginning. 347 | // You do not need to do it for the first search, though you could. 348 | // 349 | void OneWire::reset_search() 350 | { 351 | // reset the search state 352 | LastDiscrepancy = 0; 353 | LastDeviceFlag = FALSE; 354 | LastFamilyDiscrepancy = 0; 355 | for(int i = 7; ; i--) { 356 | ROM_NO[i] = 0; 357 | if ( i == 0) break; 358 | } 359 | } 360 | 361 | // Setup the search to find the device type 'family_code' on the next call 362 | // to search(*newAddr) if it is present. 363 | // 364 | void OneWire::target_search(uint8_t family_code) 365 | { 366 | // set the search state to find SearchFamily type devices 367 | ROM_NO[0] = family_code; 368 | for (uint8_t i = 1; i < 8; i++) 369 | ROM_NO[i] = 0; 370 | LastDiscrepancy = 64; 371 | LastFamilyDiscrepancy = 0; 372 | LastDeviceFlag = FALSE; 373 | } 374 | 375 | // 376 | // Perform a search. If this function returns a '1' then it has 377 | // enumerated the next device and you may retrieve the ROM from the 378 | // OneWire::address variable. If there are no devices, no further 379 | // devices, or something horrible happens in the middle of the 380 | // enumeration then a 0 is returned. If a new device is found then 381 | // its address is copied to newAddr. Use OneWire::reset_search() to 382 | // start over. 383 | // 384 | // --- Replaced by the one from the Dallas Semiconductor web site --- 385 | //-------------------------------------------------------------------------- 386 | // Perform the 1-Wire Search Algorithm on the 1-Wire bus using the existing 387 | // search state. 388 | // Return TRUE : device found, ROM number in ROM_NO buffer 389 | // FALSE : device not found, end of search 390 | // 391 | uint8_t OneWire::search(uint8_t *newAddr, bool search_mode /* = true */) 392 | { 393 | uint8_t id_bit_number; 394 | uint8_t last_zero, rom_byte_number, search_result; 395 | uint8_t id_bit, cmp_id_bit; 396 | 397 | unsigned char rom_byte_mask, search_direction; 398 | 399 | // initialize for search 400 | id_bit_number = 1; 401 | last_zero = 0; 402 | rom_byte_number = 0; 403 | rom_byte_mask = 1; 404 | search_result = 0; 405 | 406 | // if the last call was not the last one 407 | if (!LastDeviceFlag) 408 | { 409 | // 1-Wire reset 410 | if (!reset()) 411 | { 412 | // reset the search 413 | LastDiscrepancy = 0; 414 | LastDeviceFlag = FALSE; 415 | LastFamilyDiscrepancy = 0; 416 | return FALSE; 417 | } 418 | // issue the search command 419 | if (search_mode == true) { 420 | write(0xF0); // NORMAL SEARCH 421 | } else { 422 | write(0xEC); // CONDITIONAL SEARCH 423 | } 424 | 425 | // loop to do the search 426 | do 427 | { 428 | // read a bit and its complement 429 | id_bit = read_bit(); 430 | cmp_id_bit = read_bit(); 431 | 432 | // check for no devices on 1-wire 433 | if ((id_bit == 1) && (cmp_id_bit == 1)) 434 | break; 435 | else 436 | { 437 | // all devices coupled have 0 or 1 438 | if (id_bit != cmp_id_bit) 439 | search_direction = id_bit; // bit write value for search 440 | else 441 | { 442 | // if this discrepancy if before the Last Discrepancy 443 | // on a previous next then pick the same as last time 444 | if (id_bit_number < LastDiscrepancy) 445 | search_direction = ((ROM_NO[rom_byte_number] & rom_byte_mask) > 0); 446 | else 447 | // if equal to last pick 1, if not then pick 0 448 | search_direction = (id_bit_number == LastDiscrepancy); 449 | 450 | // if 0 was picked then record its position in LastZero 451 | if (search_direction == 0) 452 | { 453 | last_zero = id_bit_number; 454 | 455 | // check for Last discrepancy in family 456 | if (last_zero < 9) 457 | LastFamilyDiscrepancy = last_zero; 458 | } 459 | } 460 | 461 | // set or clear the bit in the ROM byte rom_byte_number 462 | // with mask rom_byte_mask 463 | if (search_direction == 1) 464 | ROM_NO[rom_byte_number] |= rom_byte_mask; 465 | else 466 | ROM_NO[rom_byte_number] &= ~rom_byte_mask; 467 | 468 | // serial number search direction write bit 469 | write_bit(search_direction); 470 | 471 | // increment the byte counter id_bit_number 472 | // and shift the mask rom_byte_mask 473 | id_bit_number++; 474 | rom_byte_mask <<= 1; 475 | 476 | // if the mask is 0 then go to new SerialNum byte rom_byte_number and reset mask 477 | if (rom_byte_mask == 0) 478 | { 479 | rom_byte_number++; 480 | rom_byte_mask = 1; 481 | } 482 | } 483 | } 484 | while(rom_byte_number < 8); // loop until through all ROM bytes 0-7 485 | // if the search was successful then 486 | if (!(id_bit_number < 65)) 487 | { 488 | // search successful so set LastDiscrepancy,LastDeviceFlag,search_result 489 | LastDiscrepancy = last_zero; 490 | 491 | // check for last device 492 | if (LastDiscrepancy == 0) 493 | LastDeviceFlag = TRUE; 494 | 495 | search_result = TRUE; 496 | } 497 | } 498 | 499 | // if no device found then reset counters so next 'search' will be like a first 500 | if (!search_result || !ROM_NO[0]) 501 | { 502 | LastDiscrepancy = 0; 503 | LastDeviceFlag = FALSE; 504 | LastFamilyDiscrepancy = 0; 505 | search_result = FALSE; 506 | } else { 507 | for (int i = 0; i < 8; i++) newAddr[i] = ROM_NO[i]; 508 | } 509 | return search_result; 510 | } 511 | 512 | #endif 513 | 514 | #if ONEWIRE_CRC 515 | // The 1-Wire CRC scheme is described in Maxim Application Note 27: 516 | // "Understanding and Using Cyclic Redundancy Checks with Maxim iButton Products" 517 | // 518 | 519 | #if ONEWIRE_CRC8_TABLE 520 | // This table comes from Dallas sample code where it is freely reusable, 521 | // though Copyright (C) 2000 Dallas Semiconductor Corporation 522 | static const uint8_t PROGMEM dscrc_table[] = { 523 | 0, 94,188,226, 97, 63,221,131,194,156,126, 32,163,253, 31, 65, 524 | 157,195, 33,127,252,162, 64, 30, 95, 1,227,189, 62, 96,130,220, 525 | 35,125,159,193, 66, 28,254,160,225,191, 93, 3,128,222, 60, 98, 526 | 190,224, 2, 92,223,129, 99, 61,124, 34,192,158, 29, 67,161,255, 527 | 70, 24,250,164, 39,121,155,197,132,218, 56,102,229,187, 89, 7, 528 | 219,133,103, 57,186,228, 6, 88, 25, 71,165,251,120, 38,196,154, 529 | 101, 59,217,135, 4, 90,184,230,167,249, 27, 69,198,152,122, 36, 530 | 248,166, 68, 26,153,199, 37,123, 58,100,134,216, 91, 5,231,185, 531 | 140,210, 48,110,237,179, 81, 15, 78, 16,242,172, 47,113,147,205, 532 | 17, 79,173,243,112, 46,204,146,211,141,111, 49,178,236, 14, 80, 533 | 175,241, 19, 77,206,144,114, 44,109, 51,209,143, 12, 82,176,238, 534 | 50,108,142,208, 83, 13,239,177,240,174, 76, 18,145,207, 45,115, 535 | 202,148,118, 40,171,245, 23, 73, 8, 86,180,234,105, 55,213,139, 536 | 87, 9,235,181, 54,104,138,212,149,203, 41,119,244,170, 72, 22, 537 | 233,183, 85, 11,136,214, 52,106, 43,117,151,201, 74, 20,246,168, 538 | 116, 42,200,150, 21, 75,169,247,182,232, 10, 84,215,137,107, 53}; 539 | 540 | // 541 | // Compute a Dallas Semiconductor 8 bit CRC. These show up in the ROM 542 | // and the registers. (note: this might better be done without to 543 | // table, it would probably be smaller and certainly fast enough 544 | // compared to all those delayMicrosecond() calls. But I got 545 | // confused, so I use this table from the examples.) 546 | // 547 | uint8_t OneWire::crc8(const uint8_t *addr, uint8_t len) 548 | { 549 | uint8_t crc = 0; 550 | 551 | while (len--) { 552 | crc = pgm_read_byte(dscrc_table + (crc ^ *addr++)); 553 | } 554 | return crc; 555 | } 556 | #else 557 | // 558 | // Compute a Dallas Semiconductor 8 bit CRC directly. 559 | // this is much slower, but much smaller, than the lookup table. 560 | // 561 | uint8_t OneWire::crc8(const uint8_t *addr, uint8_t len) 562 | { 563 | uint8_t crc = 0; 564 | 565 | while (len--) { 566 | #if defined(__AVR__) 567 | crc = _crc_ibutton_update(crc, *addr++); 568 | #else 569 | uint8_t inbyte = *addr++; 570 | for (uint8_t i = 8; i; i--) { 571 | uint8_t mix = (crc ^ inbyte) & 0x01; 572 | crc >>= 1; 573 | if (mix) crc ^= 0x8C; 574 | inbyte >>= 1; 575 | } 576 | #endif 577 | } 578 | return crc; 579 | } 580 | #endif 581 | 582 | #if ONEWIRE_CRC16 583 | bool OneWire::check_crc16(const uint8_t* input, uint16_t len, const uint8_t* inverted_crc, uint16_t crc) 584 | { 585 | crc = ~crc16(input, len, crc); 586 | return (crc & 0xFF) == inverted_crc[0] && (crc >> 8) == inverted_crc[1]; 587 | } 588 | 589 | uint16_t OneWire::crc16(const uint8_t* input, uint16_t len, uint16_t crc) 590 | { 591 | #if defined(__AVR__) 592 | for (uint16_t i = 0 ; i < len ; i++) { 593 | crc = _crc16_update(crc, input[i]); 594 | } 595 | #else 596 | static const uint8_t oddparity[16] = 597 | { 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0 }; 598 | 599 | for (uint16_t i = 0 ; i < len ; i++) { 600 | // Even though we're just copying a byte from the input, 601 | // we'll be doing 16-bit computation with it. 602 | uint16_t cdata = input[i]; 603 | cdata = (cdata ^ crc) & 0xff; 604 | crc >>= 8; 605 | 606 | if (oddparity[cdata & 0x0F] ^ oddparity[cdata >> 4]) 607 | crc ^= 0xC001; 608 | 609 | cdata <<= 6; 610 | crc ^= cdata; 611 | cdata <<= 1; 612 | crc ^= cdata; 613 | } 614 | #endif 615 | return crc; 616 | } 617 | #endif 618 | 619 | 620 | #ifdef ARDUINO_ARCH_ESP32 621 | #undef noInterrupts() 622 | #undef interrupts() 623 | #endif 624 | 625 | #endif 626 | --------------------------------------------------------------------------------