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