Dallas' 1-Wire bus protocol library

Dependents:   DS1825 DISCO-F746-Dessiccateur-V1 watersenor_and_temp_code DS1820 ... more

Committer:
hudakz
Date:
Tue Dec 29 16:06:46 2020 +0000
Revision:
17:bbe8bf32e8bc
Parent:
16:4c3edd30ad6e
1-wre bus: Modified.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
hudakz 0:acf75feb0947 1 /*
hudakz 0:acf75feb0947 2 Copyright (c) 2007, Jim Studt (original old version - many contributors since)
hudakz 0:acf75feb0947 3
hudakz 0:acf75feb0947 4 The latest version of this library may be found at:
hudakz 9:4af0015b0f47 5 http://www.pjrc.com/teensy/td_libs_Onehtml
hudakz 0:acf75feb0947 6
hudakz 0:acf75feb0947 7 OneWire has been maintained by Paul Stoffregen (paul@pjrc.com) since
hudakz 0:acf75feb0947 8 January 2010. At the time, it was in need of many bug fixes, but had
hudakz 0:acf75feb0947 9 been abandoned the original author (Jim Studt). None of the known
hudakz 9:4af0015b0f47 10 contributors were interested in maintaining One Paul typically
hudakz 0:acf75feb0947 11 works on OneWire every 6 to 12 months. Patches usually wait that
hudakz 0:acf75feb0947 12 long. If anyone is interested in more actively maintaining OneWire,
hudakz 0:acf75feb0947 13 please contact Paul.
hudakz 0:acf75feb0947 14
hudakz 0:acf75feb0947 15 Version 2.2:
hudakz 0:acf75feb0947 16 Teensy 3.0 compatibility, Paul Stoffregen, paul@pjrc.com
hudakz 0:acf75feb0947 17 Arduino Due compatibility, http://arduino.cc/forum/index.php?topic=141030
hudakz 0:acf75feb0947 18 Fix DS18B20 example negative temperature
hudakz 0:acf75feb0947 19 Fix DS18B20 example's low res modes, Ken Butcher
hudakz 0:acf75feb0947 20 Improve reset timing, Mark Tillotson
hudakz 0:acf75feb0947 21 Add const qualifiers, Bertrik Sikken
hudakz 0:acf75feb0947 22 Add initial value input to crc16, Bertrik Sikken
hudakz 0:acf75feb0947 23 Add target_search() function, Scott Roberts
hudakz 0:acf75feb0947 24
hudakz 0:acf75feb0947 25 Version 2.1:
hudakz 0:acf75feb0947 26 Arduino 1.0 compatibility, Paul Stoffregen
hudakz 0:acf75feb0947 27 Improve temperature example, Paul Stoffregen
hudakz 0:acf75feb0947 28 DS250x_PROM example, Guillermo Lovato
hudakz 0:acf75feb0947 29 PIC32 (chipKit) compatibility, Jason Dangel, dangel.jason AT gmail.com
hudakz 0:acf75feb0947 30 Improvements from Glenn Trewitt:
hudakz 0:acf75feb0947 31 - crc16() now works
hudakz 0:acf75feb0947 32 - check_crc16() does all of calculation/checking work.
hudakz 0:acf75feb0947 33 - Added read_bytes() and write_bytes(), to reduce tedious loops.
hudakz 0:acf75feb0947 34 - Added ds2408 example.
hudakz 0:acf75feb0947 35 Delete very old, out-of-date readme file (info is here)
hudakz 0:acf75feb0947 36
hudakz 0:acf75feb0947 37 Version 2.0: Modifications by Paul Stoffregen, January 2010:
hudakz 9:4af0015b0f47 38 http://www.pjrc.com/teensy/td_libs_Onehtml
hudakz 0:acf75feb0947 39 Search fix from Robin James
hudakz 0:acf75feb0947 40 http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1238032295/27#27
hudakz 0:acf75feb0947 41 Use direct optimized I/O in all cases
hudakz 0:acf75feb0947 42 Disable interrupts during timing critical sections
hudakz 0:acf75feb0947 43 (this solves many random communication errors)
hudakz 0:acf75feb0947 44 Disable interrupts during read-modify-write I/O
hudakz 0:acf75feb0947 45 Reduce RAM consumption by eliminating unnecessary
hudakz 0:acf75feb0947 46 variables and trimming many to 8 bits
hudakz 0:acf75feb0947 47 Optimize both crc8 - table version moved to flash
hudakz 0:acf75feb0947 48
hudakz 0:acf75feb0947 49 Modified to work with larger numbers of devices - avoids loop.
hudakz 0:acf75feb0947 50 Tested in Arduino 11 alpha with 12 sensors.
hudakz 0:acf75feb0947 51 26 Sept 2008 -- Robin James
hudakz 0:acf75feb0947 52 http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1238032295/27#27
hudakz 0:acf75feb0947 53
hudakz 0:acf75feb0947 54 Updated to work with arduino-0008 and to include skip() as of
hudakz 0:acf75feb0947 55 2007/07/06. --RJL20
hudakz 0:acf75feb0947 56
hudakz 0:acf75feb0947 57 Modified to calculate the 8-bit CRC directly, avoiding the need for
hudakz 0:acf75feb0947 58 the 256-byte lookup table to be loaded in RAM. Tested in arduino-0010
hudakz 0:acf75feb0947 59 -- Tom Pollard, Jan 23, 2008
hudakz 0:acf75feb0947 60
hudakz 0:acf75feb0947 61 Jim Studt's original library was modified by Josh Larios.
hudakz 0:acf75feb0947 62
hudakz 0:acf75feb0947 63 Tom Pollard, pollard@alum.mit.edu, contributed around May 20, 2008
hudakz 0:acf75feb0947 64
hudakz 0:acf75feb0947 65 Permission is hereby granted, free of charge, to any person obtaining
hudakz 0:acf75feb0947 66 a copy of this software and associated documentation files (the
hudakz 0:acf75feb0947 67 "Software"), to deal in the Software without restriction, including
hudakz 0:acf75feb0947 68 without limitation the rights to use, copy, modify, merge, publish,
hudakz 0:acf75feb0947 69 distribute, sublicense, and/or sell copies of the Software, and to
hudakz 0:acf75feb0947 70 permit persons to whom the Software is furnished to do so, subject to
hudakz 0:acf75feb0947 71 the following conditions:
hudakz 0:acf75feb0947 72
hudakz 0:acf75feb0947 73 The above copyright notice and this permission notice shall be
hudakz 0:acf75feb0947 74 included in all copies or substantial portions of the Software.
hudakz 0:acf75feb0947 75
hudakz 0:acf75feb0947 76 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
hudakz 0:acf75feb0947 77 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
hudakz 0:acf75feb0947 78 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
hudakz 0:acf75feb0947 79 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
hudakz 0:acf75feb0947 80 LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
hudakz 0:acf75feb0947 81 OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
hudakz 0:acf75feb0947 82 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
hudakz 0:acf75feb0947 83
hudakz 0:acf75feb0947 84 Much of the code was inspired by Derek Yerger's code, though I don't
hudakz 0:acf75feb0947 85 think much of that remains. In any event that was..
hudakz 0:acf75feb0947 86 (copyleft) 2006 by Derek Yerger - Free to distribute freely.
hudakz 0:acf75feb0947 87
hudakz 0:acf75feb0947 88 The CRC code was excerpted and inspired by the Dallas Semiconductor
hudakz 0:acf75feb0947 89 sample code bearing this copyright.
hudakz 0:acf75feb0947 90 //---------------------------------------------------------------------------
hudakz 0:acf75feb0947 91 // Copyright (C) 2000 Dallas Semiconductor Corporation, All Rights Reserved.
hudakz 0:acf75feb0947 92 //
hudakz 0:acf75feb0947 93 // Permission is hereby granted, free of charge, to any person obtaining a
hudakz 0:acf75feb0947 94 // copy of this software and associated documentation files (the "Software"),
hudakz 0:acf75feb0947 95 // to deal in the Software without restriction, including without limitation
hudakz 0:acf75feb0947 96 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
hudakz 0:acf75feb0947 97 // and/or sell copies of the Software, and to permit persons to whom the
hudakz 0:acf75feb0947 98 // Software is furnished to do so, subject to the following conditions:
hudakz 0:acf75feb0947 99 //
hudakz 0:acf75feb0947 100 // The above copyright notice and this permission notice shall be included
hudakz 0:acf75feb0947 101 // in all copies or substantial portions of the Software.
hudakz 0:acf75feb0947 102 //
hudakz 0:acf75feb0947 103 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
hudakz 0:acf75feb0947 104 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
hudakz 0:acf75feb0947 105 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
hudakz 0:acf75feb0947 106 // IN NO EVENT SHALL DALLAS SEMICONDUCTOR BE LIABLE FOR ANY CLAIM, DAMAGES
hudakz 0:acf75feb0947 107 // OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
hudakz 0:acf75feb0947 108 // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
hudakz 0:acf75feb0947 109 // OTHER DEALINGS IN THE SOFTWARE.
hudakz 0:acf75feb0947 110 //
hudakz 0:acf75feb0947 111 // Except as contained in this notice, the name of Dallas Semiconductor
hudakz 0:acf75feb0947 112 // shall not be used except as stated in the Dallas Semiconductor
hudakz 0:acf75feb0947 113 // Branding Policy.
hudakz 0:acf75feb0947 114 //--------------------------------------------------------------------------
hudakz 0:acf75feb0947 115 */
hudakz 0:acf75feb0947 116 #include "OneWire.h"
hudakz 0:acf75feb0947 117
hudakz 8:87fbdaba5535 118 /**
hudakz 10:c89b9ad6097c 119 * @brief Constructs a OneWire object.
hudakz 10:c89b9ad6097c 120 * @note GPIO is configured as output and an internal pull up resistor is connected.
hudakz 17:bbe8bf32e8bc 121 * An addition 4.7k Ohm resistor can connected between the 1-wire data bus/line
hudakz 17:bbe8bf32e8bc 122 * and the +3.3V pin,
hudakz 17:bbe8bf32e8bc 123 *
hudakz 17:bbe8bf32e8bc 124 * ----------------
hudakz 17:bbe8bf32e8bc 125 * | | -----------------------> +3.3V
hudakz 17:bbe8bf32e8bc 126 * | MBED BOARD | |
hudakz 17:bbe8bf32e8bc 127 * | | | ------
hudakz 17:bbe8bf32e8bc 128 * | +3.3V |--o--| 4.7k |-------
hudakz 17:bbe8bf32e8bc 129 * | | ------ |
hudakz 17:bbe8bf32e8bc 130 * | | |
hudakz 17:bbe8bf32e8bc 131 * | | |
hudakz 17:bbe8bf32e8bc 132 * | | |
hudakz 17:bbe8bf32e8bc 133 * | | |
hudakz 17:bbe8bf32e8bc 134 * | GPIO |--------------------o-----> 1-wire bus/line
hudakz 17:bbe8bf32e8bc 135 * | |
hudakz 17:bbe8bf32e8bc 136 * | |
hudakz 17:bbe8bf32e8bc 137 * | GND |--------------------------> GND
hudakz 17:bbe8bf32e8bc 138 * | |
hudakz 17:bbe8bf32e8bc 139 * ----------------
hudakz 17:bbe8bf32e8bc 140 *
hudakz 17:bbe8bf32e8bc 141 * @param gpioPin GPIO pin to be used as 1-wire bus/line
hudakz 8:87fbdaba5535 142 * @retval
hudakz 8:87fbdaba5535 143 */
hudakz 16:4c3edd30ad6e 144 OneWire::OneWire(PinName gpioPin, int samplePoint_us /*= 13*/) :
hudakz 16:4c3edd30ad6e 145 _gpio(new DigitalInOut(gpioPin)),
hudakz 16:4c3edd30ad6e 146 _uart(NULL),
hudakz 16:4c3edd30ad6e 147 _samplePoint_us(samplePoint_us)
hudakz 7:acf3f0ee66d2 148 {
hudakz 16:4c3edd30ad6e 149 Timer timer;
hudakz 15:7f7759008807 150
hudakz 16:4c3edd30ad6e 151 MODE(); // set mode to either OpenDrain for STM or PullUp for others
hudakz 15:7f7759008807 152
hudakz 15:7f7759008807 153 // Measure bus transition time from ouput to input
hudakz 15:7f7759008807 154 timer.reset();
hudakz 16:4c3edd30ad6e 155 OUTPUT(); // set as output
hudakz 16:4c3edd30ad6e 156 WRITE(0); // pull the line down
hudakz 15:7f7759008807 157 timer.start();
hudakz 16:4c3edd30ad6e 158 INPUT(); // set as input (and release the bus)
hudakz 15:7f7759008807 159 timer.stop();
hudakz 16:4c3edd30ad6e 160 #if (MBED_MAJOR_VERSION > 5)
hudakz 16:4c3edd30ad6e 161 _outToInTransition_us = timer.elapsed_time().count();
hudakz 16:4c3edd30ad6e 162 #else
hudakz 16:4c3edd30ad6e 163 _outToInTransition_us = timer.read_us();
hudakz 16:4c3edd30ad6e 164 #endif
hudakz 15:7f7759008807 165
hudakz 16:4c3edd30ad6e 166 MBED_ASSERT(_outToInTransition_us < _samplePoint_us);
hudakz 15:7f7759008807 167
hudakz 12:27a1b359b95c 168 INIT_WAIT;
hudakz 0:acf75feb0947 169 #if ONEWIRE_SEARCH
hudakz 0:acf75feb0947 170 reset_search();
hudakz 0:acf75feb0947 171 #endif
hudakz 0:acf75feb0947 172 }
hudakz 0:acf75feb0947 173
hudakz 10:c89b9ad6097c 174 /**
hudakz 16:4c3edd30ad6e 175 * @brief Constructs a OneWire object.
hudakz 17:bbe8bf32e8bc 176 * @note UART is used to implement a 1-Wire Bus Master according to Maxim Integrated application note
hudakz 17:bbe8bf32e8bc 177 *
hudakz 16:4c3edd30ad6e 178 * https://www.maximintegrated.com/en/design/technical-documents/tutorials/2/214.html
hudakz 17:bbe8bf32e8bc 179 *
hudakz 17:bbe8bf32e8bc 180 * In addition to the 4.7k Ohm resistor between the 1-wire data bus/line and the +3.3V pin,
hudakz 17:bbe8bf32e8bc 181 * a 470 Ohm resistor shall be tied to the UART's tx and rx pin. UART's rx pin is then used
hudakz 16:4c3edd30ad6e 182 * as 1-wire data bus/line.
hudakz 17:bbe8bf32e8bc 183 *
hudakz 16:4c3edd30ad6e 184 * ----------------
hudakz 16:4c3edd30ad6e 185 * | | -----------------------> +3.3V
hudakz 16:4c3edd30ad6e 186 * | MBED BOARD | |
hudakz 16:4c3edd30ad6e 187 * | | | ------
hudakz 17:bbe8bf32e8bc 188 * | +3.3V |--o--| 4.7k |-------
hudakz 16:4c3edd30ad6e 189 * | | ------ |
hudakz 16:4c3edd30ad6e 190 * | | ------ |
hudakz 17:bbe8bf32e8bc 191 * | UART TX |-----| 470 |--- |
hudakz 16:4c3edd30ad6e 192 * | | ------ | |
hudakz 16:4c3edd30ad6e 193 * | | | |
hudakz 17:bbe8bf32e8bc 194 * | UART RX |----------------o---o-----> 1-wire bus/line
hudakz 16:4c3edd30ad6e 195 * | |
hudakz 16:4c3edd30ad6e 196 * | |
hudakz 16:4c3edd30ad6e 197 * | GND |--------------------------> GND
hudakz 16:4c3edd30ad6e 198 * | |
hudakz 16:4c3edd30ad6e 199 * ----------------
hudakz 17:bbe8bf32e8bc 200 *
hudakz 17:bbe8bf32e8bc 201 * @param txPin UART's Tx pin name
hudakz 17:bbe8bf32e8bc 202 * @param rxPin UART's Rx pin name
hudakz 16:4c3edd30ad6e 203 * @retval
hudakz 16:4c3edd30ad6e 204 */
hudakz 16:4c3edd30ad6e 205 OneWire::OneWire(PinName txPin, PinName rxPin, int baud /*=115200*/) :
hudakz 16:4c3edd30ad6e 206 _gpio(NULL),
hudakz 16:4c3edd30ad6e 207 _uart(new UART(txPin, rxPin, baud))
hudakz 16:4c3edd30ad6e 208 {
hudakz 16:4c3edd30ad6e 209 #if ONEWIRE_SEARCH
hudakz 16:4c3edd30ad6e 210 reset_search();
hudakz 16:4c3edd30ad6e 211 #endif
hudakz 16:4c3edd30ad6e 212 }
hudakz 16:4c3edd30ad6e 213
hudakz 16:4c3edd30ad6e 214 OneWire::~OneWire()
hudakz 16:4c3edd30ad6e 215 {
hudakz 16:4c3edd30ad6e 216 if (_gpio != NULL)
hudakz 16:4c3edd30ad6e 217 delete _gpio;
hudakz 16:4c3edd30ad6e 218 if (_uart != NULL)
hudakz 16:4c3edd30ad6e 219 delete _uart;
hudakz 16:4c3edd30ad6e 220 }
hudakz 16:4c3edd30ad6e 221
hudakz 16:4c3edd30ad6e 222 /**
hudakz 10:c89b9ad6097c 223 * @brief Performs the onewire reset function.
hudakz 16:4c3edd30ad6e 224 * @note We will wait up to 250uS for the bus to come high,
hudakz 10:c89b9ad6097c 225 * if it doesn't then it is broken or shorted and we return a 0;
hudakz 10:c89b9ad6097c 226 * @param
hudakz 10:c89b9ad6097c 227 * @retval 1 if a device asserted a presence pulse, 0 otherwise.
hudakz 10:c89b9ad6097c 228 */
hudakz 0:acf75feb0947 229 uint8_t OneWire::reset(void)
hudakz 0:acf75feb0947 230 {
hudakz 12:27a1b359b95c 231 uint8_t present;
hudakz 0:acf75feb0947 232
hudakz 16:4c3edd30ad6e 233 if (_gpio != NULL) {
hudakz 16:4c3edd30ad6e 234 OUTPUT();
hudakz 16:4c3edd30ad6e 235 WRITE(0); // pull down the 1-wire bus do create reset pulse
hudakz 16:4c3edd30ad6e 236 WAIT_US(500); // wait at least 480 us
hudakz 16:4c3edd30ad6e 237 INPUT(); // release the 1-wire bus and go into receive mode
hudakz 16:4c3edd30ad6e 238 WAIT_US(90); // DS1820 waits about 15 to 60 us and generates a 60 to 240 us presence pulse
hudakz 16:4c3edd30ad6e 239 present = !READ(); // read the presence pulse
hudakz 16:4c3edd30ad6e 240 WAIT_US(420);
hudakz 16:4c3edd30ad6e 241 }
hudakz 16:4c3edd30ad6e 242 else {
hudakz 16:4c3edd30ad6e 243 _uart->baud(9600);
hudakz 16:4c3edd30ad6e 244 #if (MBED_MAJOR_VERSION > 5)
hudakz 16:4c3edd30ad6e 245 ThisThread::sleep_for(10ms);
hudakz 16:4c3edd30ad6e 246 #else
hudakz 16:4c3edd30ad6e 247 wait_ms(10);
hudakz 16:4c3edd30ad6e 248 #endif
hudakz 16:4c3edd30ad6e 249 _uart->_base_putc(0xF0);
hudakz 16:4c3edd30ad6e 250 present = _uart->_base_getc();
hudakz 16:4c3edd30ad6e 251 wait_us(420);
hudakz 16:4c3edd30ad6e 252 _uart->baud(115200);
hudakz 16:4c3edd30ad6e 253 #if (MBED_MAJOR_VERSION > 5)
hudakz 16:4c3edd30ad6e 254 ThisThread::sleep_for(10ms);
hudakz 16:4c3edd30ad6e 255 #else
hudakz 16:4c3edd30ad6e 256 wait_ms(10);
hudakz 16:4c3edd30ad6e 257 #endif
hudakz 16:4c3edd30ad6e 258 present = (present >= 0x10);
hudakz 16:4c3edd30ad6e 259 }
hudakz 16:4c3edd30ad6e 260
hudakz 12:27a1b359b95c 261 return present;
hudakz 0:acf75feb0947 262 }
hudakz 0:acf75feb0947 263
hudakz 10:c89b9ad6097c 264 /**
hudakz 10:c89b9ad6097c 265 * @brief Writes a bit.
hudakz 10:c89b9ad6097c 266 * @note GPIO registers are used for STM chips to cut time.
hudakz 10:c89b9ad6097c 267 * @param
hudakz 10:c89b9ad6097c 268 * @retval
hudakz 10:c89b9ad6097c 269 */
hudakz 0:acf75feb0947 270 void OneWire::write_bit(uint8_t v)
hudakz 0:acf75feb0947 271 {
hudakz 0:acf75feb0947 272 if (v & 1) {
hudakz 16:4c3edd30ad6e 273 if (_gpio != NULL) {
hudakz 16:4c3edd30ad6e 274 OUTPUT();
hudakz 16:4c3edd30ad6e 275 WRITE(0); // drive output low
hudakz 16:4c3edd30ad6e 276 WAIT_US(1);
hudakz 16:4c3edd30ad6e 277 WRITE(1); // drive output high
hudakz 16:4c3edd30ad6e 278 WAIT_US(60);
hudakz 16:4c3edd30ad6e 279 }
hudakz 16:4c3edd30ad6e 280 else {
hudakz 16:4c3edd30ad6e 281 _uart->_base_putc(0xFF);
hudakz 16:4c3edd30ad6e 282 }
hudakz 8:87fbdaba5535 283 }
hudakz 8:87fbdaba5535 284 else {
hudakz 16:4c3edd30ad6e 285 if (_gpio != NULL) {
hudakz 16:4c3edd30ad6e 286 OUTPUT();
hudakz 16:4c3edd30ad6e 287 WRITE(0); // drive output low
hudakz 16:4c3edd30ad6e 288 WAIT_US(60);
hudakz 16:4c3edd30ad6e 289 WRITE(1); // drive output high
hudakz 16:4c3edd30ad6e 290 WAIT_US(1);
hudakz 16:4c3edd30ad6e 291 }
hudakz 16:4c3edd30ad6e 292 else {
hudakz 16:4c3edd30ad6e 293 _uart->_base_putc(0x00);
hudakz 16:4c3edd30ad6e 294 }
hudakz 0:acf75feb0947 295 }
hudakz 0:acf75feb0947 296 }
hudakz 0:acf75feb0947 297
hudakz 10:c89b9ad6097c 298 /**
hudakz 10:c89b9ad6097c 299 * @brief Reads a bit.
hudakz 10:c89b9ad6097c 300 * @note GPIO registers are used for STM chips to cut time.
hudakz 10:c89b9ad6097c 301 * @param
hudakz 10:c89b9ad6097c 302 * @retval
hudakz 10:c89b9ad6097c 303 */
hudakz 0:acf75feb0947 304 uint8_t OneWire::read_bit(void)
hudakz 0:acf75feb0947 305 {
hudakz 0:acf75feb0947 306 uint8_t r;
hudakz 0:acf75feb0947 307
hudakz 16:4c3edd30ad6e 308 if (_gpio != NULL) {
hudakz 16:4c3edd30ad6e 309 OUTPUT();
hudakz 16:4c3edd30ad6e 310 WRITE(0);
hudakz 16:4c3edd30ad6e 311 INPUT();
hudakz 16:4c3edd30ad6e 312 wait_us(_samplePoint_us - _outToInTransition_us); // wait till sample point
hudakz 16:4c3edd30ad6e 313 r = READ();
hudakz 16:4c3edd30ad6e 314 WAIT_US(55);
hudakz 16:4c3edd30ad6e 315 }
hudakz 16:4c3edd30ad6e 316 else {
hudakz 16:4c3edd30ad6e 317 _uart->_base_putc(0xFF);
hudakz 16:4c3edd30ad6e 318 do {
hudakz 16:4c3edd30ad6e 319 r = _uart->_base_getc();
hudakz 16:4c3edd30ad6e 320 wait_us(100);
hudakz 16:4c3edd30ad6e 321 } while(_uart->readable());
hudakz 16:4c3edd30ad6e 322
hudakz 16:4c3edd30ad6e 323 r = r & 0x01;
hudakz 16:4c3edd30ad6e 324 }
hudakz 16:4c3edd30ad6e 325
hudakz 0:acf75feb0947 326 return r;
hudakz 0:acf75feb0947 327 }
hudakz 0:acf75feb0947 328
hudakz 10:c89b9ad6097c 329 /**
hudakz 10:c89b9ad6097c 330 * @brief Writes a byte.
hudakz 10:c89b9ad6097c 331 * @note The writing code uses the active drivers to raise the
hudakz 10:c89b9ad6097c 332 pin high, if you need power after the write (e.g. DS18S20 in
hudakz 10:c89b9ad6097c 333 parasite power mode) then set 'power' to 1, otherwise the pin will
hudakz 10:c89b9ad6097c 334 go tri-state at the end of the write to avoid heating in a short or
hudakz 10:c89b9ad6097c 335 other mishap.
hudakz 10:c89b9ad6097c 336 * @param
hudakz 10:c89b9ad6097c 337 * @retval
hudakz 10:c89b9ad6097c 338 */
hudakz 9:4af0015b0f47 339 void OneWire::write_byte(uint8_t v, uint8_t power /* = 0 */ )
hudakz 8:87fbdaba5535 340 {
hudakz 0:acf75feb0947 341 uint8_t bitMask;
hudakz 0:acf75feb0947 342
hudakz 9:4af0015b0f47 343 for (bitMask = 0x01; bitMask; bitMask <<= 1)
hudakz 9:4af0015b0f47 344 write_bit((bitMask & v) ? 1 : 0);
hudakz 16:4c3edd30ad6e 345 if ((!power) && (_gpio != NULL))
hudakz 9:4af0015b0f47 346 INPUT();
hudakz 0:acf75feb0947 347 }
hudakz 0:acf75feb0947 348
hudakz 8:87fbdaba5535 349 /**
hudakz 10:c89b9ad6097c 350 * @brief Writes bytes.
hudakz 8:87fbdaba5535 351 * @note
hudakz 8:87fbdaba5535 352 * @param
hudakz 8:87fbdaba5535 353 * @retval
hudakz 8:87fbdaba5535 354 */
hudakz 8:87fbdaba5535 355 void OneWire::write_bytes(const uint8_t* buf, uint16_t count, bool power /* = 0 */ )
hudakz 8:87fbdaba5535 356 {
hudakz 8:87fbdaba5535 357 for (uint16_t i = 0; i < count; i++)
hudakz 9:4af0015b0f47 358 write_byte(buf[i]);
hudakz 16:4c3edd30ad6e 359 if ((!power) && (_gpio != NULL))
hudakz 9:4af0015b0f47 360 INPUT();
hudakz 0:acf75feb0947 361 }
hudakz 0:acf75feb0947 362
hudakz 10:c89b9ad6097c 363 /**
hudakz 10:c89b9ad6097c 364 * @brief Reads a byte.
hudakz 10:c89b9ad6097c 365 * @note
hudakz 10:c89b9ad6097c 366 * @param
hudakz 10:c89b9ad6097c 367 * @retval
hudakz 10:c89b9ad6097c 368 */
hudakz 9:4af0015b0f47 369 uint8_t OneWire::read_byte()
hudakz 8:87fbdaba5535 370 {
hudakz 0:acf75feb0947 371 uint8_t bitMask;
hudakz 0:acf75feb0947 372 uint8_t r = 0;
hudakz 0:acf75feb0947 373
hudakz 0:acf75feb0947 374 for (bitMask = 0x01; bitMask; bitMask <<= 1) {
hudakz 9:4af0015b0f47 375 if (read_bit())
hudakz 8:87fbdaba5535 376 r |= bitMask;
hudakz 0:acf75feb0947 377 }
hudakz 8:87fbdaba5535 378
hudakz 0:acf75feb0947 379 return r;
hudakz 0:acf75feb0947 380 }
hudakz 0:acf75feb0947 381
hudakz 8:87fbdaba5535 382 /**
hudakz 10:c89b9ad6097c 383 * @brief Reads bytes.
hudakz 8:87fbdaba5535 384 * @note
hudakz 8:87fbdaba5535 385 * @param
hudakz 8:87fbdaba5535 386 * @retval
hudakz 8:87fbdaba5535 387 */
hudakz 8:87fbdaba5535 388 void OneWire::read_bytes(uint8_t* buf, uint16_t count)
hudakz 8:87fbdaba5535 389 {
hudakz 8:87fbdaba5535 390 for (uint16_t i = 0; i < count; i++)
hudakz 9:4af0015b0f47 391 buf[i] = read_byte();
hudakz 0:acf75feb0947 392 }
hudakz 0:acf75feb0947 393
hudakz 10:c89b9ad6097c 394 /**
hudakz 10:c89b9ad6097c 395 * @brief Selects ROM.
hudakz 10:c89b9ad6097c 396 * @note
hudakz 10:c89b9ad6097c 397 * @param
hudakz 10:c89b9ad6097c 398 * @retval
hudakz 10:c89b9ad6097c 399 */
hudakz 0:acf75feb0947 400 void OneWire::select(const uint8_t rom[8])
hudakz 0:acf75feb0947 401 {
hudakz 0:acf75feb0947 402 uint8_t i;
hudakz 0:acf75feb0947 403
hudakz 10:c89b9ad6097c 404 write_byte(0x55); // Choose ROM
hudakz 8:87fbdaba5535 405 for (i = 0; i < 8; i++)
hudakz 9:4af0015b0f47 406 write_byte(rom[i]);
hudakz 0:acf75feb0947 407 }
hudakz 0:acf75feb0947 408
hudakz 10:c89b9ad6097c 409 /**
hudakz 10:c89b9ad6097c 410 * @brief Skips ROM select.
hudakz 10:c89b9ad6097c 411 * @note
hudakz 10:c89b9ad6097c 412 * @param
hudakz 10:c89b9ad6097c 413 * @retval
hudakz 10:c89b9ad6097c 414 */
hudakz 0:acf75feb0947 415 void OneWire::skip()
hudakz 0:acf75feb0947 416 {
hudakz 10:c89b9ad6097c 417 write_byte(0xCC); // Skip ROM
hudakz 0:acf75feb0947 418 }
hudakz 0:acf75feb0947 419
hudakz 8:87fbdaba5535 420 /**
hudakz 10:c89b9ad6097c 421 * @brief Unpowers the chip.
hudakz 8:87fbdaba5535 422 * @note
hudakz 8:87fbdaba5535 423 * @param
hudakz 8:87fbdaba5535 424 * @retval
hudakz 8:87fbdaba5535 425 */
hudakz 0:acf75feb0947 426 void OneWire::depower()
hudakz 0:acf75feb0947 427 {
hudakz 16:4c3edd30ad6e 428 if (_gpio != NULL)
hudakz 16:4c3edd30ad6e 429 INPUT();
hudakz 0:acf75feb0947 430 }
hudakz 0:acf75feb0947 431
hudakz 0:acf75feb0947 432 #if ONEWIRE_SEARCH
hudakz 8:87fbdaba5535 433 //
hudakz 0:acf75feb0947 434
hudakz 10:c89b9ad6097c 435 /**
hudakz 10:c89b9ad6097c 436 * @brief Resets the search state.
hudakz 10:c89b9ad6097c 437 * @note We need to use this function to start a search again from the beginning.
hudakz 10:c89b9ad6097c 438 * We do not need to do it for the first search, though we could.
hudakz 10:c89b9ad6097c 439 * @param
hudakz 10:c89b9ad6097c 440 * @retval
hudakz 10:c89b9ad6097c 441 */
hudakz 0:acf75feb0947 442 void OneWire::reset_search()
hudakz 0:acf75feb0947 443 {
hudakz 8:87fbdaba5535 444 // reset the search state
hudakz 16:4c3edd30ad6e 445
hudakz 8:87fbdaba5535 446 LastDiscrepancy = 0;
hudakz 8:87fbdaba5535 447 LastDeviceFlag = false;
hudakz 8:87fbdaba5535 448 LastFamilyDiscrepancy = 0;
hudakz 8:87fbdaba5535 449 for (int i = 7;; i--) {
hudakz 8:87fbdaba5535 450 ROM_NO[i] = 0;
hudakz 8:87fbdaba5535 451 if (i == 0)
hudakz 8:87fbdaba5535 452 break;
hudakz 8:87fbdaba5535 453 }
hudakz 0:acf75feb0947 454 }
hudakz 0:acf75feb0947 455
hudakz 10:c89b9ad6097c 456 /**
hudakz 10:c89b9ad6097c 457 * @brief Sets the search state to find SearchFamily type devices.
hudakz 10:c89b9ad6097c 458 * @note
hudakz 10:c89b9ad6097c 459 * @param
hudakz 10:c89b9ad6097c 460 * @retval
hudakz 10:c89b9ad6097c 461 */
hudakz 0:acf75feb0947 462 void OneWire::target_search(uint8_t family_code)
hudakz 0:acf75feb0947 463 {
hudakz 8:87fbdaba5535 464 // set the search state to find SearchFamily type devices
hudakz 16:4c3edd30ad6e 465
hudakz 8:87fbdaba5535 466 ROM_NO[0] = family_code;
hudakz 8:87fbdaba5535 467 for (uint8_t i = 1; i < 8; i++)
hudakz 8:87fbdaba5535 468 ROM_NO[i] = 0;
hudakz 8:87fbdaba5535 469 LastDiscrepancy = 64;
hudakz 8:87fbdaba5535 470 LastFamilyDiscrepancy = 0;
hudakz 8:87fbdaba5535 471 LastDeviceFlag = false;
hudakz 0:acf75feb0947 472 }
hudakz 0:acf75feb0947 473
hudakz 10:c89b9ad6097c 474 /**
hudakz 10:c89b9ad6097c 475 * @brief Performs a search.
hudakz 10:c89b9ad6097c 476 * @note Perform a search. If this function returns a '1' then it has
hudakz 10:c89b9ad6097c 477 enumerated the next device and you may retrieve the ROM from the
hudakz 10:c89b9ad6097c 478 OneWire::address variable. If there are no devices, no further
hudakz 10:c89b9ad6097c 479 devices, or something horrible happens in the middle of the
hudakz 10:c89b9ad6097c 480 enumeration then a 0 is returned. If a new device is found then
hudakz 10:c89b9ad6097c 481 its address is copied to newAddr. Use OneWire::reset_search() to
hudakz 10:c89b9ad6097c 482 start over.
hudakz 16:4c3edd30ad6e 483
hudakz 10:c89b9ad6097c 484 --- Replaced by the one from the Dallas Semiconductor web site ---
hudakz 10:c89b9ad6097c 485 -------------------------------------------------------------------------
hudakz 10:c89b9ad6097c 486 Perform the 1-Wire Search Algorithm on the 1-Wire bus using the existing
hudakz 10:c89b9ad6097c 487 search state.
hudakz 10:c89b9ad6097c 488 * @param
hudakz 10:c89b9ad6097c 489 * @retval true : device found, ROM number in ROM_NO buffer
hudakz 10:c89b9ad6097c 490 * false : device not found, end of search
hudakz 10:c89b9ad6097c 491 */
hudakz 8:87fbdaba5535 492 uint8_t OneWire::search(uint8_t* newAddr)
hudakz 0:acf75feb0947 493 {
hudakz 8:87fbdaba5535 494 uint8_t id_bit_number;
hudakz 8:87fbdaba5535 495 uint8_t last_zero, rom_byte_number, search_result;
hudakz 8:87fbdaba5535 496 uint8_t id_bit, cmp_id_bit;
hudakz 0:acf75feb0947 497
hudakz 8:87fbdaba5535 498 unsigned char rom_byte_mask, search_direction;
hudakz 0:acf75feb0947 499
hudakz 8:87fbdaba5535 500 // initialize for search
hudakz 16:4c3edd30ad6e 501
hudakz 8:87fbdaba5535 502 id_bit_number = 1;
hudakz 8:87fbdaba5535 503 last_zero = 0;
hudakz 8:87fbdaba5535 504 rom_byte_number = 0;
hudakz 8:87fbdaba5535 505 rom_byte_mask = 1;
hudakz 8:87fbdaba5535 506 search_result = 0;
hudakz 16:4c3edd30ad6e 507
hudakz 8:87fbdaba5535 508 // if the last call was not the last one
hudakz 8:87fbdaba5535 509 if (!LastDeviceFlag) {
hudakz 8:87fbdaba5535 510 // 1-Wire reset
hudakz 8:87fbdaba5535 511 if (!reset()) {
hudakz 8:87fbdaba5535 512 // reset the search
hudakz 8:87fbdaba5535 513 LastDiscrepancy = 0;
hudakz 8:87fbdaba5535 514 LastDeviceFlag = false;
hudakz 8:87fbdaba5535 515 LastFamilyDiscrepancy = 0;
hudakz 8:87fbdaba5535 516 return false;
hudakz 8:87fbdaba5535 517 }
hudakz 0:acf75feb0947 518
hudakz 8:87fbdaba5535 519 // issue the search command
hudakz 9:4af0015b0f47 520 write_byte(0xF0);
hudakz 0:acf75feb0947 521
hudakz 8:87fbdaba5535 522 // loop to do the search
hudakz 16:4c3edd30ad6e 523 do
hudakz 16:4c3edd30ad6e 524 {
hudakz 8:87fbdaba5535 525 // read a bit and its complement
hudakz 8:87fbdaba5535 526 id_bit = read_bit();
hudakz 8:87fbdaba5535 527 cmp_id_bit = read_bit();
hudakz 0:acf75feb0947 528
hudakz 8:87fbdaba5535 529 // check for no devices on 1-wire
hudakz 8:87fbdaba5535 530 if ((id_bit == 1) && (cmp_id_bit == 1))
hudakz 8:87fbdaba5535 531 break;
hudakz 8:87fbdaba5535 532 else {
hudakz 8:87fbdaba5535 533 // all devices coupled have 0 or 1
hudakz 8:87fbdaba5535 534 if (id_bit != cmp_id_bit)
hudakz 8:87fbdaba5535 535 search_direction = id_bit; // bit write value for search
hudakz 8:87fbdaba5535 536 else {
hudakz 8:87fbdaba5535 537 // if this discrepancy if before the Last Discrepancy
hudakz 8:87fbdaba5535 538 // on a previous next then pick the same as last time
hudakz 8:87fbdaba5535 539 if (id_bit_number < LastDiscrepancy)
hudakz 8:87fbdaba5535 540 search_direction = ((ROM_NO[rom_byte_number] & rom_byte_mask) > 0);
hudakz 8:87fbdaba5535 541 else
hudakz 8:87fbdaba5535 542 // if equal to last pick 1, if not then pick 0
hudakz 8:87fbdaba5535 543 search_direction = (id_bit_number == LastDiscrepancy);
hudakz 0:acf75feb0947 544
hudakz 8:87fbdaba5535 545 // if 0 was picked then record its position in LastZero
hudakz 8:87fbdaba5535 546 if (search_direction == 0) {
hudakz 8:87fbdaba5535 547 last_zero = id_bit_number;
hudakz 0:acf75feb0947 548
hudakz 8:87fbdaba5535 549 // check for Last discrepancy in family
hudakz 8:87fbdaba5535 550 if (last_zero < 9)
hudakz 8:87fbdaba5535 551 LastFamilyDiscrepancy = last_zero;
hudakz 8:87fbdaba5535 552 }
hudakz 8:87fbdaba5535 553 }
hudakz 0:acf75feb0947 554
hudakz 8:87fbdaba5535 555 // set or clear the bit in the ROM byte rom_byte_number
hudakz 8:87fbdaba5535 556 // with mask rom_byte_mask
hudakz 8:87fbdaba5535 557 if (search_direction == 1)
hudakz 8:87fbdaba5535 558 ROM_NO[rom_byte_number] |= rom_byte_mask;
hudakz 8:87fbdaba5535 559 else
hudakz 8:87fbdaba5535 560 ROM_NO[rom_byte_number] &= ~rom_byte_mask;
hudakz 0:acf75feb0947 561
hudakz 8:87fbdaba5535 562 // serial number search direction write bit
hudakz 8:87fbdaba5535 563 write_bit(search_direction);
hudakz 0:acf75feb0947 564
hudakz 8:87fbdaba5535 565 // increment the byte counter id_bit_number
hudakz 8:87fbdaba5535 566 // and shift the mask rom_byte_mask
hudakz 8:87fbdaba5535 567 id_bit_number++;
hudakz 8:87fbdaba5535 568 rom_byte_mask <<= 1;
hudakz 0:acf75feb0947 569
hudakz 8:87fbdaba5535 570 // if the mask is 0 then go to new SerialNum byte rom_byte_number and reset mask
hudakz 8:87fbdaba5535 571 if (rom_byte_mask == 0) {
hudakz 8:87fbdaba5535 572 rom_byte_number++;
hudakz 8:87fbdaba5535 573 rom_byte_mask = 1;
hudakz 8:87fbdaba5535 574 }
hudakz 0:acf75feb0947 575 }
hudakz 8:87fbdaba5535 576 } while (rom_byte_number < 8);
hudakz 16:4c3edd30ad6e 577
hudakz 8:87fbdaba5535 578 // loop until through all ROM bytes 0-7
hudakz 8:87fbdaba5535 579 // if the search was successful then
hudakz 8:87fbdaba5535 580 if (!(id_bit_number < 65)) {
hudakz 8:87fbdaba5535 581 // search successful so set LastDiscrepancy,LastDeviceFlag,search_result
hudakz 8:87fbdaba5535 582 LastDiscrepancy = last_zero;
hudakz 0:acf75feb0947 583
hudakz 8:87fbdaba5535 584 // check for last device
hudakz 8:87fbdaba5535 585 if (LastDiscrepancy == 0)
hudakz 8:87fbdaba5535 586 LastDeviceFlag = true;
hudakz 0:acf75feb0947 587
hudakz 8:87fbdaba5535 588 search_result = true;
hudakz 8:87fbdaba5535 589 }
hudakz 8:87fbdaba5535 590 }
hudakz 0:acf75feb0947 591
hudakz 8:87fbdaba5535 592 // if no device found then reset counters so next 'search' will be like a first
hudakz 8:87fbdaba5535 593 if (!search_result || !ROM_NO[0]) {
hudakz 8:87fbdaba5535 594 LastDiscrepancy = 0;
hudakz 8:87fbdaba5535 595 LastDeviceFlag = false;
hudakz 8:87fbdaba5535 596 LastFamilyDiscrepancy = 0;
hudakz 8:87fbdaba5535 597 search_result = false;
hudakz 8:87fbdaba5535 598 }
hudakz 0:acf75feb0947 599
hudakz 8:87fbdaba5535 600 for (int i = 0; i < 8; i++)
hudakz 8:87fbdaba5535 601 newAddr[i] = ROM_NO[i];
hudakz 8:87fbdaba5535 602 return search_result;
hudakz 8:87fbdaba5535 603 }
hudakz 0:acf75feb0947 604 #endif
hudakz 10:c89b9ad6097c 605 //
hudakz 0:acf75feb0947 606 #if ONEWIRE_CRC
hudakz 0:acf75feb0947 607 //
hudakz 16:4c3edd30ad6e 608
hudakz 10:c89b9ad6097c 609 /**
hudakz 10:c89b9ad6097c 610 * @brief Computes a Dallas Semiconductor 8 bit CRC directly.
hudakz 10:c89b9ad6097c 611 * @note The 1-Wire CRC scheme is described in Maxim Application Note 27:
hudakz 10:c89b9ad6097c 612 "Understanding and Using Cyclic Redundancy Checks with Maxim iButton Products"
hudakz 10:c89b9ad6097c 613 * @param
hudakz 10:c89b9ad6097c 614 * @retval
hudakz 10:c89b9ad6097c 615 */
hudakz 8:87fbdaba5535 616 uint8_t OneWire::crc8(const uint8_t* addr, uint8_t len)
hudakz 0:acf75feb0947 617 {
hudakz 0:acf75feb0947 618 uint8_t crc = 0;
hudakz 8:87fbdaba5535 619
hudakz 0:acf75feb0947 620 while (len--) {
hudakz 0:acf75feb0947 621 uint8_t inbyte = *addr++;
hudakz 0:acf75feb0947 622 for (uint8_t i = 8; i; i--) {
hudakz 0:acf75feb0947 623 uint8_t mix = (crc ^ inbyte) & 0x01;
hudakz 0:acf75feb0947 624 crc >>= 1;
hudakz 8:87fbdaba5535 625 if (mix)
hudakz 8:87fbdaba5535 626 crc ^= 0x8C;
hudakz 0:acf75feb0947 627 inbyte >>= 1;
hudakz 0:acf75feb0947 628 }
hudakz 0:acf75feb0947 629 }
hudakz 8:87fbdaba5535 630
hudakz 0:acf75feb0947 631 return crc;
hudakz 0:acf75feb0947 632 }
hudakz 0:acf75feb0947 633 #endif