OneWire + DS18X20 Library
Basic functions for OneWire operations + specific DS18x20 operations
 All Functions Groups Pages
onewire.cpp
1 /*****************************************************************************
2 
3  OneWire (tm) library
4 
5  Copyright (C) 2016 Falk Brunner
6 
7 *****************************************************************************/
8 
9 /*
10 * ----------------------------------------------------------------------------
11 * "THE BEER-WARE LICENSE" (Revision 42):
12 * <Falk.Brunner@gmx.de> wrote this file. As long as you retain this notice you
13 * can do whatever you want with this stuff. If we meet some day, and you think
14 * this stuff is worth it, you can buy me a beer in return. Falk Brunner
15 * ----------------------------------------------------------------------------
16 */
17 
18 #include <string.h>
19 #include <avr/io.h>
20 #include <avr/pgmspace.h>
21 #include <util/delay.h>
22 #include <avr/interrupt.h>
23 #include <util/atomic.h>
24 
25 #include "onewire.h"
26 
27 uint8_t onewire_reset(void) {
28  uint8_t err=ONEWIRE_OK;
29 
30  ONEWIRE_PORT &= ~ONEWIRE_MASK; // low
31  ONEWIRE_DDR |= ONEWIRE_MASK; // switch to ouput
32  _delay_us(480);
33  ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
34  ONEWIRE_DDR &= ~ONEWIRE_MASK; // switch to input
35  _delay_us(66);
36  if( (ONEWIRE_PIN & ONEWIRE_MASK)) { // no presence pulse detect
37  err = ONEWIRE_NO_PRESENCE;
38  }
39  }
40 
41  _delay_us(480);
42  if( !(ONEWIRE_PIN & ONEWIRE_MASK)) { // bus short circuit to GND
43  err = ONEWIRE_GND_SHORT;
44  }
45  return err;
46 }
47 
48 void onewire_write_bit(uint8_t wrbit) {
49 
50  ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
51  if (!(wrbit & 1)) {
52  ONEWIRE_PORT &= ~ONEWIRE_MASK; // low
53  ONEWIRE_DDR |= ONEWIRE_MASK; // switch to ouput
54  _delay_us(80);
55  ONEWIRE_DDR &= ~ONEWIRE_MASK; // switch to input
56  _delay_us(20);
57  } else {
58  ONEWIRE_PORT &= ~ONEWIRE_MASK; // low
59  ONEWIRE_DDR |= ONEWIRE_MASK; // switch to ouput
60  _delay_us(3);
61  ONEWIRE_DDR &= ~ONEWIRE_MASK; // switch to input
62  _delay_us(97);
63  }
64  }
65 }
66 
67 uint8_t onewire_read_bit(void) {
68  uint8_t rebit;
69 
70  ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
71  ONEWIRE_PORT &= ~ONEWIRE_MASK; // low
72  ONEWIRE_DDR |= ONEWIRE_MASK; // switch to ouput
73  _delay_us(3);
74  ONEWIRE_DDR &= ~ONEWIRE_MASK; // switch to input
75  _delay_us(12);
76  rebit = ONEWIRE_PIN & ONEWIRE_MASK; // read bit
77  _delay_us(85);
78  }
79 
80  if (rebit) {
81  return 1;
82  } else {
83  return 0;
84  }
85 }
86 
87 uint8_t onewire_read_byte(void) {
88  uint8_t data=0;
89  uint8_t i;
90 
91  for (i=0; i<8; i++) {
92  data >>= 1; // LSB first on OneWire
93  if (onewire_read_bit()) {
94  data |= 0x80;
95  }
96  }
97  return data;
98 }
99 
100 void onewire_write_byte(uint8_t data) {
101  uint8_t i;
102 
103  for (i=0; i<8; i++) {
104  // LSB first on OneWire
105  // no need for masking, LSB is masked inside function
106  onewire_write_bit(data);
107  data >>= 1;
108  }
109 }
110 
111 void onewire_search_init(uint8_t buffer[8]) {
112  memset(buffer, 0, 8);
113  onewire_search(NULL, 0);
114 }
115 
116 uint8_t onewire_search_rom(uint8_t buffer[8]) {
117  return onewire_search(buffer, ONEWIRE_SEARCH_ROM);
118 }
119 
120 uint8_t onewire_alarm_search(uint8_t buffer[8]) {
121  return onewire_search(buffer, ONEWIRE_ALARM_SEARCH);
122 }
123 
124 uint8_t onewire_search(uint8_t buffer[8], uint8_t cmd) {
125  uint8_t mask, i, j, bit, rom_tmp;
126  uint8_t max_conf_zero=0; // last bit conflict that was resolved to zero
127  static uint8_t max_conf_old; // last bit conflict that was resolved to zero in last scan
128  uint8_t branch_flag=0; // indicate new scan branch, new ROM code found
129 
130  if (buffer == NULL) { // init search
131  max_conf_old=64;
132  return ONEWIRE_OK;
133  }
134 
135  if (onewire_reset()) {
136  return ONEWIRE_NO_PRESENCE;
137  } else {
138  onewire_write_byte(cmd);
139  rom_tmp = buffer[0];
140  i=0;
141  mask=1;
142  // scan all 64 ROM bits
143  for(j=0; j<64; j++) {
144  bit = onewire_read_bit(); // bit
145  bit |= onewire_read_bit()<<1; // inverted bit
146 
147  switch(bit) {
148  case 0: // bit conflict, more than one device with different bit
149  if (j < max_conf_old) { // below last zero branch conflict level, keep current bit
150  if (rom_tmp & mask) { // last bit was 1
151  bit = 1;
152  } else { // last bit was 0
153  bit = 0;
154  max_conf_zero = j;
155  branch_flag = 1;
156  }
157  } else if (j == max_conf_old) { // last zero branch conflict, now enter new path
158  bit = 1;
159  } else { // above last scan conflict level
160  bit = 0; // scan 0 branch first
161  max_conf_zero = j;
162  branch_flag = 1;
163  }
164  break;
165 
166  case 1:
167  // no break
168 
169  case 2: // no bit conflict
170  // do nothing, just go on with current bit
171  break;
172 
173  case 3: // no response
174  return ONEWIRE_SCAN_ERROR;
175  break;
176  }
177 
178  // write bit to OneWire and store code
179 
180  if (bit & 1) {
182  rom_tmp |= mask;
183  } else {
185  rom_tmp &= ~mask;
186  }
187 
188  mask <<= 1;
189  if (mask == 0) {
190  mask = 1;
191  buffer[i] = rom_tmp; // update tmp data
192  i++;
193  if (i<8) {
194  rom_tmp = buffer[i]; // read new data
195  }
196  }
197  }
198  }
199 
200  max_conf_old = max_conf_zero;
201 
202  if (onewire_crc(buffer, 8)) {
203  return ONEWIRE_CRC_ERROR;
204  } else if (branch_flag) {
205  return ONEWIRE_OK;
206  } else {
207  return ONEWIRE_LAST_CODE;
208  }
209 }
210 
211 uint8_t onewire_match_rom(const uint8_t rom[8]) {
212  uint8_t i, rc;
213 
214  rc = onewire_reset();
215  if (rc) {
216  return rc;
217  } else {
218  onewire_write_byte(ONEWIRE_MATCH_ROM);
219  for (i=0; i<8; i++) {
220  onewire_write_byte(rom[i]);
221  }
222  }
223  return ONEWIRE_OK;
224 }
225 
226 uint8_t onewire_skip_rom(void) {
227  uint8_t rc;
228 
229  rc = onewire_reset();
230  if (rc) {
231  return rc;
232  } else {
233  onewire_write_byte(ONEWIRE_SKIP_ROM);
234  }
235  return ONEWIRE_OK;
236 }
237 
238 uint8_t onewire_read_rom(uint8_t rom[8]) {
239  uint8_t i, rc;
240 
241  rc = onewire_reset();
242  if (rc) {
243  return rc;
244  } else {
245  onewire_write_byte(ONEWIRE_READ_ROM);
246  for (i=0; i<8; i++) {
247  rom[i] = onewire_read_byte();
248  }
249 
250  if(onewire_crc(rom, 8)) {
251  return ONEWIRE_CRC_ERROR;
252  }
253  }
254  return ONEWIRE_OK;
255 }
256 
257 /*-----------------------------------------------------------------------------
258 
259  calculate CRC over data array
260  nibble wide processing, ~3x faster than serial version
261  CRC calculation of 8 Bytes takes ~0.3ms@1MHz
262 
263  CRC polynon is x^8 + x^5 + x^4 + 1 = 0x8C
264  Attention! This CRC is reversed, CRC is shifted right with new data
265  comming in at the MSB! That's why the polynom is mirrored!
266 
267  return: CRC
268 
269  usage:
270 
271  check CRC of received data:
272 
273  When the array includes the received CRC (last byte), the calculated CRC
274  will be zero if no transmission error took place.
275 
276  When the array does not include the received CRC, the byte after the
277  last valid data must be zero. The calculated CRC will be returned and must
278  be compared to the received CRC.
279 
280  generate CRC for transmit data:
281 
282  When a CRC for transmission is to be calculated, add a zero after the last
283  valid data and copy the CRC value there after this functions returns.
284 
285 -----------------------------------------------------------------------------*/
286 
287 uint8_t onewire_crc(const uint8_t *data, uint8_t cnt) {
288 
289  static const uint8_t crc_table[16] PROGMEM =
290  {0x00, 0x9D, 0x23, 0xBE, 0x46, 0xDB, 0x65, 0xF8,
291  0x8C, 0x11, 0xAF, 0x32, 0xCA, 0x57, 0xE9, 0x74};
292 
293  uint8_t crc, i, tmp;
294 
295  // nibble based CRC calculation,
296  // good trade off between speed and memory usage
297 
298  // first byte is not changed, since CRC is initialized with 0
299  crc = *data++;
300  cnt--;
301 
302  for(; cnt>0; cnt--) {
303  tmp = *data++; // next byte
304 
305  i = crc & 0x0F;
306  crc = (crc >> 4) | (tmp << 4); // shift in next nibble
307  crc ^= pgm_read_byte(&crc_table[i]); // apply polynom
308 
309  i = crc & 0x0F;
310  crc = (crc >> 4) | (tmp & 0xF0); // shift in next nibble
311  crc ^= pgm_read_byte(&crc_table[i]); // apply polynom
312  }
313 
314  return crc;
315 }
316 
uint8_t onewire_reset(void)
OneWire reset.
Definition: onewire.cpp:27
uint8_t onewire_match_rom(const uint8_t rom[8])
select device on bus
Definition: onewire.cpp:211
void onewire_write_byte(uint8_t data)
write one byte
Definition: onewire.cpp:100
uint8_t onewire_read_rom(uint8_t rom[8])
read ROM ID of device
Definition: onewire.cpp:238
void onewire_search_init(uint8_t buffer[8])
init rom search buffer and internal variables
Definition: onewire.cpp:111
uint8_t onewire_crc(const uint8_t *data, uint8_t cnt)
calculate CRC over data array, fast version, 0.3ms for 8 bytes @1MHz
Definition: onewire.cpp:287
void onewire_write_bit(uint8_t wrbit)
write one bit to bus
Definition: onewire.cpp:48
uint8_t onewire_search(uint8_t buffer[8], uint8_t cmd)
scan OneWire bus for normal ROM or alarm search
Definition: onewire.cpp:124
uint8_t onewire_skip_rom(void)
select device on bus
Definition: onewire.cpp:226
uint8_t onewire_read_bit(void)
read one bit from bus
Definition: onewire.cpp:67
uint8_t onewire_read_byte(void)
read one byte
Definition: onewire.cpp:87
uint8_t onewire_alarm_search(uint8_t buffer[8])
scan OneWire bus for devices with active alarm flag
Definition: onewire.cpp:120
uint8_t onewire_search_rom(uint8_t buffer[8])
scan OneWire bus for ROMs
Definition: onewire.cpp:116