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 rc=ONEWIRE_OK;
29 
30  ONEWIRE_LOW
31  _delay_us(480);
32  ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
33  ONEWIRE_TRISTATE
34  _delay_us(66);
35  if(ONEWIRE_READ) { // no presence pulse detect
36  rc = ONEWIRE_NO_PRESENCE;
37  }
38  }
39 
40  _delay_us(480);
41  if(!ONEWIRE_READ) { // bus short circuit to GND
42  rc = ONEWIRE_GND_SHORT;
43  }
44  return rc;
45 }
46 
47 void onewire_write_bit(uint8_t wrbit) {
48 
49  ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
50  if ((wrbit & 1)) { // write 1
51  ONEWIRE_LOW
52  _delay_us(3);
53  ONEWIRE_TRISTATE
54  _delay_us(97);
55  } else { // write 0
56  ONEWIRE_LOW
57  _delay_us(80);
58  ONEWIRE_TRISTATE
59  _delay_us(20);
60  }
61  }
62 }
63 
64 uint8_t onewire_read_bit(void) {
65  uint8_t readbit;
66 
67  ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
68  ONEWIRE_LOW
69  _delay_us(3);
70  ONEWIRE_TRISTATE
71  _delay_us(12);
72  readbit = ONEWIRE_READ;
73  _delay_us(85);
74  }
75 
76  if (readbit) {
77  return 1;
78  } else {
79  return 0;
80  }
81 }
82 
83 uint8_t onewire_read_byte(void) {
84  uint8_t data=0;
85  uint8_t i;
86 
87  for (i=0; i<8; i++) {
88  data >>= 1; // LSB first on OneWire
89  if (onewire_read_bit()) {
90  data |= 0x80;
91  }
92  }
93  return data;
94 }
95 
96 void onewire_write_byte(uint8_t data) {
97  uint8_t i;
98 
99  for (i=0; i<8; i++) {
100  // LSB first on OneWire
101  // no need for masking, LSB is masked inside function
102  onewire_write_bit(data);
103  data >>= 1;
104  }
105 }
106 
107 void onewire_search_init(uint8_t buffer[8]) {
108  memset(buffer, 0, 8);
109  onewire_search(NULL, 0);
110 }
111 
112 uint8_t onewire_search_rom(uint8_t buffer[8]) {
113  return onewire_search(buffer, ONEWIRE_SEARCH_ROM);
114 }
115 
116 uint8_t onewire_alarm_search(uint8_t buffer[8]) {
117  return onewire_search(buffer, ONEWIRE_ALARM_SEARCH);
118 }
119 
120 uint8_t onewire_search(uint8_t buffer[8], uint8_t cmd) {
121  uint8_t mask, i, j, bit, rom_tmp, rc;
122  uint8_t max_conf_zero=0; // last bit conflict that was resolved to zero
123  static uint8_t max_conf_old; // last bit conflict that was resolved to zero in last scan
124  uint8_t branch_flag=0; // indicate new scan branch, new ROM code found
125 
126  if (buffer == NULL) { // init search
127  max_conf_old=64;
128  return ONEWIRE_OK;
129  }
130 
131  rc = onewire_reset();
132  if (rc) {
133  return rc;
134  } else {
135  onewire_write_byte(cmd);
136  rom_tmp = buffer[0];
137  i=0;
138  mask=1;
139  // scan all 64 ROM bits
140  for(j=0; j<64; j++) {
141  bit = onewire_read_bit(); // bit
142  bit |= onewire_read_bit()<<1; // inverted bit
143 
144  switch(bit) {
145  case 0: // bit conflict, more than one device with different bit
146  if (j < max_conf_old) { // below last zero branch conflict level, keep current bit
147  if (rom_tmp & mask) { // last bit was 1
148  bit = 1;
149  } else { // last bit was 0
150  bit = 0;
151  max_conf_zero = j;
152  branch_flag = 1;
153  }
154  } else if (j == max_conf_old) { // last zero branch conflict, now enter new path
155  bit = 1;
156  } else { // above last scan conflict level
157  bit = 0; // scan 0 branch first
158  max_conf_zero = j;
159  branch_flag = 1;
160  }
161  break;
162 
163  case 1:
164  // no break
165 
166  case 2: // no bit conflict
167  // do nothing, just go on with current bit
168  break;
169 
170  case 3: // no response
171  return ONEWIRE_SCAN_ERROR;
172  break;
173  }
174 
175  // write bit to OneWire and ROM code
176 
177  if (bit & 1) {
179  rom_tmp |= mask;
180  } else {
182  rom_tmp &= ~mask;
183  }
184 
185  mask <<= 1;
186  if (mask == 0) {
187  mask = 1;
188  buffer[i] = rom_tmp; // update tmp data
189  i++;
190  if (i<8) {
191  rom_tmp = buffer[i]; // read new data
192  }
193  }
194  }
195  }
196 
197  max_conf_old = max_conf_zero;
198 
199  if (onewire_crc(buffer, 8)) {
200  return ONEWIRE_CRC_ERROR;
201  } else if (branch_flag) {
202  return ONEWIRE_OK;
203  } else {
204  return ONEWIRE_LAST_CODE;
205  }
206 }
207 
208 uint8_t onewire_match_rom(const uint8_t rom[8]) {
209  uint8_t i, rc;
210 
211  rc = onewire_reset();
212  if (rc) {
213  return rc;
214  } else {
215  onewire_write_byte(ONEWIRE_MATCH_ROM);
216  for (i=0; i<8; i++) {
217  onewire_write_byte(rom[i]);
218  }
219  }
220  return ONEWIRE_OK;
221 }
222 
223 uint8_t onewire_skip_rom(void) {
224  uint8_t rc;
225 
226  rc = onewire_reset();
227  if (rc) {
228  return rc;
229  } else {
230  onewire_write_byte(ONEWIRE_SKIP_ROM);
231  }
232  return ONEWIRE_OK;
233 }
234 
235 uint8_t onewire_read_rom(uint8_t rom[8]) {
236  uint8_t i, rc;
237 
238  rc = onewire_reset();
239  if (rc) {
240  return rc;
241  } else {
242  onewire_write_byte(ONEWIRE_READ_ROM);
243  for (i=0; i<8; i++) {
244  rom[i] = onewire_read_byte();
245  }
246 
247  if(onewire_crc(rom, 8)) {
248  return ONEWIRE_CRC_ERROR;
249  }
250  }
251  return ONEWIRE_OK;
252 }
253 
254 /*-----------------------------------------------------------------------------
255 
256  calculate CRC over data array
257  nibble wide processing, ~3x faster than serial version
258  CRC calculation of 8 Bytes takes ~0.3ms@1MHz
259 
260  CRC polynon is x^8 + x^5 + x^4 + 1 = 0x31
261 
262  Attention! This CRC is reversed, CRC is shifted right with new data
263  comming in at the MSB! That's why the polynom is mirrored!
264  So the real polynom is 0x8C!!!
265 
266  return: CRC
267 
268  usage:
269 
270  check CRC of received data:
271 
272  When the array includes the received CRC (last byte), the calculated CRC
273  will be zero if no transmission error took place.
274 
275  When the array does not include the received CRC, the byte after the
276  last valid data must be zero. The calculated CRC will be returned and must
277  be compared to the received CRC.
278 
279  generate CRC for transmit data:
280 
281  When a CRC for transmission is to be calculated, add a zero after the last
282  valid data and copy the CRC value there after this functions returns.
283 
284 -----------------------------------------------------------------------------*/
285 
286 uint8_t onewire_crc(const uint8_t *data, uint8_t cnt) {
287 
288  static const uint8_t crc_table[16] PROGMEM =
289  {0x00, 0x9D, 0x23, 0xBE, 0x46, 0xDB, 0x65, 0xF8,
290  0x8C, 0x11, 0xAF, 0x32, 0xCA, 0x57, 0xE9, 0x74};
291 
292  uint8_t crc, i, tmp, zerocheck;
293 
294  // nibble based CRC calculation,
295  // good trade off between speed and memory usage
296 
297  // first byte is not changed, since CRC is initialized with 0
298  crc = *data++;
299  zerocheck = crc;
300  cnt--;
301 
302  for(; cnt>0; cnt--) {
303  tmp = *data++; // next byte
304  zerocheck |= tmp;
305 
306  i = crc & 0x0F;
307  crc = (crc >> 4) | (tmp << 4); // shift in next nibble
308  crc ^= pgm_read_byte(&crc_table[i]); // apply polynom
309 
310  i = crc & 0x0F;
311  crc = (crc >> 4) | (tmp & 0xF0); // shift in next nibble
312  crc ^= pgm_read_byte(&crc_table[i]); // apply polynom
313  }
314 
315  if (!zerocheck) { // all data was zero, this is an error!
316  return 0xFF;
317  } else {
318  return crc;
319  }
320 }
321 
322 /*-----------------------------------------------------------------------------
323 
324  calculate CRC over data array
325  serial processing, slower but slightly less programm memory usage
326  CRC calculation of 8 Bytes takes ~1ms@1MHz
327 
328  CRC polynon is x^8 + x^5 + x^4 + 1 = 0x31
329 
330  Attention! This CRC is reversed, CRC is shifted right with new data
331  comming in at the MSB! That's why the polynom is mirrored!
332  So the real polynom is 0x8C!!!
333 
334  return: CRC
335 
336  usage:
337 
338  check CRC of received data:
339 
340  When the array includes the received CRC (last byte), the calculated CRC
341  will be zero if no transmission error took place.
342 
343  When the array does not include the received CRC, the byte after the
344  last valid data must be zero. The calculated CRC will be returned and must
345  be compared to the received CRC.
346 
347  generate CRC for transmit data:
348 
349  When a CRC for transmission is to be calculated, add a zero after the last
350  valid data and copy the CRC value there after this functions returns.
351 
352 -----------------------------------------------------------------------------*/
353 
354 uint8_t onewire_crc_serial(const uint8_t *data, uint8_t cnt) {
355 
356  uint8_t crc, i, tmp, zerocheck;
357  const uint8_t poly=0x8C;
358 
359  // first byte is not changed, since CRC is initialized with 0
360  crc = *data++;
361  zerocheck = crc;
362  cnt--;
363 
364  for(; cnt>0; cnt--) {
365  tmp = *data++; // next byte
366  zerocheck |= tmp;
367  for (i=0; i<8; i++) {
368  if (crc & 1) {
369  crc >>= 1;
370  if (tmp & 1) crc |= 0x80; // copy LSB to MSB
371  crc ^= poly;
372  } else {
373  crc >>= 1;
374  if (tmp & 1) crc |= 0x80; // copy LSB to MSB
375  }
376  tmp >>=1;
377  }
378  }
379 
380  if (!zerocheck) { // all data was zero, this is an error!
381  return 0xFF;
382  } else {
383  return crc;
384  }
385 }
386 
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:208
void onewire_write_byte(uint8_t data)
write one byte
Definition: onewire.cpp:96
uint8_t onewire_read_rom(uint8_t rom[8])
read ROM ID of device
Definition: onewire.cpp:235
void onewire_search_init(uint8_t buffer[8])
init rom search buffer and internal variables
Definition: onewire.cpp:107
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:286
uint8_t onewire_crc_serial(const uint8_t *data, uint8_t cnt)
calculate CRC over data array, serial version, 1ms for 8 bytes @1MHz
Definition: onewire.cpp:354
void onewire_write_bit(uint8_t wrbit)
write one bit to bus
Definition: onewire.cpp:47
uint8_t onewire_search(uint8_t buffer[8], uint8_t cmd)
scan OneWire bus for normal ROM or alarm search
Definition: onewire.cpp:120
uint8_t onewire_skip_rom(void)
select device on bus
Definition: onewire.cpp:223
uint8_t onewire_read_bit(void)
read one bit from bus
Definition: onewire.cpp:64
uint8_t onewire_read_byte(void)
read one byte
Definition: onewire.cpp:83
uint8_t onewire_alarm_search(uint8_t buffer[8])
scan OneWire bus for devices with active alarm flag
Definition: onewire.cpp:116
uint8_t onewire_search_rom(uint8_t buffer[8])
scan OneWire bus for ROMs
Definition: onewire.cpp:112