Firmware SDK
 All Data Structures Functions Variables Typedefs Enumerations Enumerator Groups Pages
bc_onewire.c
1 #include <stm32l0xx.h>
2 #include <bc_irq.h>
3 #include <bc_onewire.h>
4 #include <bc_system.h>
5 #include <bc_timer.h>
6 
7 typedef struct
8 {
9  bool initialized;
10 
11  uint8_t last_discrepancy;
12  uint8_t last_family_discrepancy;
13  bool last_device_flag;
14  uint8_t last_rom_no[8];
15 
16  bool transaction;
17  bc_gpio_channel_t channel;
18  bool auto_ds28e17_sleep_mode;
19 
21 
22 static _bc_onewire_t _bc_onewire = { .initialized = false };
23 
24 static bool _bc_onewire_reset(bc_gpio_channel_t channel);
25 static void _bc_onewire_write_byte(bc_gpio_channel_t channel, uint8_t byte);
26 static uint8_t _bc_onewire_read_byte(bc_gpio_channel_t channel);
27 static void _bc_onewire_write_bit(bc_gpio_channel_t channel, uint8_t bit);
28 static uint8_t _bc_onewire_read_bit(bc_gpio_channel_t channel);
29 static void _bc_onewire_start(void);
30 static void _bc_onewire_stop(void);
31 static void _bc_onewire_search_reset(void);
32 static void _bc_onewire_search_target_setup(uint8_t family_code);
33 static int _bc_onewire_search_devices(bc_gpio_channel_t channel, uint64_t *device_list, size_t device_list_size);
34 
36 {
37  if (!_bc_onewire.initialized)
38  {
39  memset(&_bc_onewire, 0, sizeof(_bc_onewire));
40 
41  _bc_onewire.initialized = true;
42  }
43 
44  bc_gpio_init(channel);
45 
47 
49 }
50 
52 {
53  if (_bc_onewire.transaction)
54  {
55  return false;
56  }
57 
58  _bc_onewire_start();
59 
60  _bc_onewire.transaction = true;
61 
62  _bc_onewire.channel = channel;
63 
64  return true;
65 }
66 
68 {
69  if (!_bc_onewire.transaction)
70  {
71  return false;
72  }
73 
74  if (_bc_onewire.auto_ds28e17_sleep_mode)
75  {
76  if (_bc_onewire_reset(channel))
77  {
78  _bc_onewire_write_byte(channel, 0xcc);
79 
80  _bc_onewire_write_byte(channel, 0x1e);
81  }
82  }
83 
84  _bc_onewire.transaction = false;
85 
86  _bc_onewire_stop();
87 
88  return true;
89 }
90 
92 {
93  bool state;
94 
95  _bc_onewire_start();
96 
97  state = _bc_onewire_reset(channel);
98 
99  _bc_onewire_stop();
100 
101  return state;
102 }
103 
104 void bc_onewire_select(bc_gpio_channel_t channel, uint64_t *device_number)
105 {
106  _bc_onewire_start();
107 
108  if (*device_number == BC_ONEWIRE_DEVICE_NUMBER_SKIP_ROM)
109  {
110  _bc_onewire_write_byte(channel, 0xCC);
111  }
112  else
113  {
114  _bc_onewire_write_byte(channel, 0x55);
115 
116  for (size_t i = 0; i < sizeof(uint64_t); i++)
117  {
118  _bc_onewire_write_byte(channel, ((uint8_t *) device_number)[i]);
119  }
120  }
121 
122  _bc_onewire_stop();
123 }
124 
126 {
127  _bc_onewire_start();
128  _bc_onewire_write_byte(channel, 0xCC);
129  _bc_onewire_stop();
130 }
131 
132 void bc_onewire_write(bc_gpio_channel_t channel, const void *buffer, size_t length)
133 {
134  _bc_onewire_start();
135  for (size_t i = 0; i < length; i++)
136  {
137  _bc_onewire_write_byte(channel, ((uint8_t *) buffer)[i]);
138  }
139  _bc_onewire_stop();
140 }
141 
142 void bc_onewire_read(bc_gpio_channel_t channel, void *buffer, size_t length)
143 {
144  _bc_onewire_start();
145  for (size_t i = 0; i < length; i++)
146  {
147  ((uint8_t *) buffer)[i] = _bc_onewire_read_byte(channel);
148  }
149  _bc_onewire_stop();
150 }
151 
152 void bc_onewire_write_8b(bc_gpio_channel_t channel, uint8_t byte)
153 {
154  _bc_onewire_start();
155  _bc_onewire_write_byte(channel, byte);
156  _bc_onewire_stop();
157 }
158 
160 {
161  _bc_onewire_start();
162  uint8_t data = _bc_onewire_read_byte(channel);
163  _bc_onewire_stop();
164  return data;
165 }
166 
168 {
169  _bc_onewire_start();
170  _bc_onewire_write_bit(channel, bit & 0x01);
171  _bc_onewire_stop();
172 }
173 
175 {
176  _bc_onewire_start();
177  int bit = _bc_onewire_read_bit(channel);
178  _bc_onewire_stop();
179  return bit;
180 }
181 
182 int bc_onewire_search_all(bc_gpio_channel_t channel, uint64_t *device_list, size_t device_list_size)
183 {
184  _bc_onewire_search_reset();
185 
186  return _bc_onewire_search_devices(channel, device_list, device_list_size);
187 }
188 
189 int bc_onewire_search_family(bc_gpio_channel_t channel, uint8_t family_code, uint64_t *device_list,
190  size_t device_list_size)
191 {
192  _bc_onewire_search_target_setup(family_code);
193 
194  return _bc_onewire_search_devices(channel, device_list, device_list_size);
195 }
196 
197 uint8_t bc_onewire_crc8(const void *buffer, size_t length, uint8_t crc)
198 {
199  uint8_t *_buffer = (uint8_t *) buffer;
200  uint8_t inbyte;
201  uint8_t i;
202 
203  while (length--)
204  {
205  inbyte = *_buffer++;
206  for (i = 8; i; i--)
207  {
208  if ((crc ^ inbyte) & 0x01)
209  {
210  crc >>= 1;
211  crc ^= 0x8C;
212  }
213  else
214  {
215  crc >>= 1;
216  }
217  inbyte >>= 1;
218  }
219  }
220 
221  return crc;
222 }
223 
224 uint16_t bc_onewire_crc16(const void *buffer, size_t length, uint16_t crc)
225 {
226  static const uint8_t oddparity[16] =
227  { 0, 1, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0 };
228 
229  uint16_t i;
230  for (i = 0; i < length; i++)
231  {
232  uint16_t cdata = ((uint8_t *) buffer)[i];
233  cdata = (cdata ^ crc) & 0xff;
234  crc >>= 8;
235 
236  if (oddparity[cdata & 0x0F] ^ oddparity[cdata >> 4]) crc ^= 0xC001;
237 
238  cdata <<= 6;
239  crc ^= cdata;
240  cdata <<= 1;
241  crc ^= cdata;
242  }
243  return crc;
244 }
245 
246 static bool _bc_onewire_reset(bc_gpio_channel_t channel)
247 {
248  int i;
249  uint8_t retries = 125;
250 
252 
253  do
254  {
255  if (retries-- == 0)
256  {
257  return false;
258  }
259  bc_timer_delay(2);
260  }
261  while (bc_gpio_get_input(channel) == 0);
262 
263  bc_gpio_set_output(channel, 0);
265 
266  bc_timer_delay(480);
267 
269 
270  // Some devices responds little bit later than expected 70us, be less strict in timing...
271  // Low state of data line (presence detect) should be definitely low between 60us and 75us from now
272  // According to datasheet: t_PDHIGH=15..60us ; t_PDLOW=60..240us
273  //
274  // t_PDHIGH t_PDLOW
275  // /----\ ... \ / ... /-----
276  // ___/ \ ... \____/ ... /
277  // ^ ^ ^ ^ ^
278  // now 15 60 75 300 us
279  //
280  bc_timer_delay(60);
281  retries = 4;
282  do {
283  i = bc_gpio_get_input(channel);
284  bc_timer_delay(4);
285  }
286  while (i && --retries);
287  bc_timer_delay(retries * 4);
288  //bc_log_debug("retries=%d",retries);
289 
290  bc_timer_delay(410);
291 
292  return i == 0;
293 }
294 
295 static void _bc_onewire_write_byte(bc_gpio_channel_t channel, uint8_t byte)
296 {
297  for (uint8_t i = 0; i < 8; i++)
298  {
299  _bc_onewire_write_bit(channel, byte & 0x01);
300  byte >>= 1;
301  }
302 }
303 
304 static uint8_t _bc_onewire_read_byte(bc_gpio_channel_t channel)
305 {
306  uint8_t byte = 0;
307  for (uint8_t i = 0; i < 8; i++)
308  {
309  byte |= (_bc_onewire_read_bit(channel) << i);
310  }
311  return byte;
312 }
313 
314 static void _bc_onewire_write_bit(bc_gpio_channel_t channel, uint8_t bit)
315 {
316  bc_gpio_set_output(channel, 0);
318 
319  if (bit)
320  {
321  bc_irq_disable();
322 
323  bc_timer_delay(3);
324 
325  bc_irq_enable();
326 
328 
329  bc_timer_delay(60);
330 
331  }
332  else
333  {
334  bc_timer_delay(55);
335 
337 
338  bc_timer_delay(8);
339  }
340 }
341 
342 static uint8_t _bc_onewire_read_bit(bc_gpio_channel_t channel)
343 {
344  uint8_t bit = 0;
345 
346  bc_gpio_set_output(channel, 0);
347 
349 
350  bc_irq_disable();
351 
352  bc_timer_delay(3);
353 
354  bc_irq_enable();
355 
357 
358  bc_irq_disable();
359 
360  bc_timer_delay(8);
361 
362  bc_irq_enable();
363 
364  bit = bc_gpio_get_input(channel);
365 
366  bc_timer_delay(50);
367 
368  return bit;
369 }
370 
371 static void _bc_onewire_start(void)
372 {
373  if (_bc_onewire.transaction)
374  {
375  return;
376  }
377 
378  bc_system_pll_enable();
379 
380  bc_timer_init();
381 
382  bc_timer_start();
383 }
384 
385 static void _bc_onewire_stop(void)
386 {
387  if (_bc_onewire.transaction)
388  {
389  return;
390  }
391 
392  bc_timer_stop();
393 
394  bc_system_pll_disable();
395 }
396 
397 static void _bc_onewire_search_reset(void)
398 {
399  _bc_onewire.last_discrepancy = 0;
400  _bc_onewire.last_device_flag = false;
401  _bc_onewire.last_family_discrepancy = 0;
402 }
403 
404 static void _bc_onewire_search_target_setup(uint8_t family_code)
405 {
406  memset(_bc_onewire.last_rom_no, 0, sizeof(_bc_onewire.last_rom_no));
407  _bc_onewire.last_rom_no[0] = family_code;
408  _bc_onewire.last_discrepancy = 64;
409  _bc_onewire.last_family_discrepancy = 0;
410  _bc_onewire.last_device_flag = false;
411 }
412 
413 void bc_onewire_search_start(uint8_t family_code)
414 {
415  if (family_code != 0)
416  {
417  _bc_onewire_search_target_setup(family_code);
418  }
419  else
420  {
421  _bc_onewire_search_reset();
422  }
423 }
424 
425 bool bc_onewire_search_next(bc_gpio_channel_t channel, uint64_t *device_number)
426 {
427  bool search_result = false;
428  uint8_t id_bit_number;
429  uint8_t last_zero, rom_byte_number;
430  uint8_t id_bit, cmp_id_bit;
431  uint8_t rom_byte_mask, search_direction;
432 
433  /* Initialize for search */
434  id_bit_number = 1;
435  last_zero = 0;
436  rom_byte_number = 0;
437  rom_byte_mask = 1;
438 
439  if (!_bc_onewire.last_device_flag)
440  {
441 
442  _bc_onewire_start();
443 
444  if (!_bc_onewire_reset(channel))
445  {
446  _bc_onewire_search_reset();
447  _bc_onewire_stop();
448  return false;
449  }
450 
451  // issue the search command
452  _bc_onewire_write_byte(channel, 0xf0);
453 
454  // loop to do the search
455  do
456  {
457  id_bit = _bc_onewire_read_bit(channel);
458  cmp_id_bit = _bc_onewire_read_bit(channel);
459 
460  // check for no devices on 1-wire
461  if ((id_bit == 1) && (cmp_id_bit == 1))
462  {
463  break;
464  }
465  else
466  {
467  /* All devices coupled have 0 or 1 */
468  if (id_bit != cmp_id_bit)
469  {
470  /* Bit write value for search */
471  search_direction = id_bit;
472  }
473  else
474  {
475  /* If this discrepancy is before the Last Discrepancy on a previous next then pick the same as last time */
476  if (id_bit_number < _bc_onewire.last_discrepancy)
477  {
478  search_direction = ((_bc_onewire.last_rom_no[rom_byte_number] & rom_byte_mask) > 0);
479  }
480  else
481  {
482  /* If equal to last pick 1, if not then pick 0 */
483  search_direction = (id_bit_number == _bc_onewire.last_discrepancy);
484  }
485 
486  /* If 0 was picked then record its position in LastZero */
487  if (search_direction == 0)
488  {
489  last_zero = id_bit_number;
490 
491  /* Check for Last discrepancy in family */
492  if (last_zero < 9)
493  {
494  _bc_onewire.last_family_discrepancy = last_zero;
495  }
496  }
497  }
498 
499  /* Set or clear the bit in the ROM byte rom_byte_number with mask rom_byte_mask */
500  if (search_direction == 1)
501  {
502  _bc_onewire.last_rom_no[rom_byte_number] |= rom_byte_mask;
503  }
504  else
505  {
506  _bc_onewire.last_rom_no[rom_byte_number] &= ~rom_byte_mask;
507  }
508 
509  /* Serial number search direction write bit */
510  _bc_onewire_write_bit(channel, search_direction);
511 
512  /* Increment the byte counter id_bit_number and shift the mask rom_byte_mask */
513  id_bit_number++;
514  rom_byte_mask <<= 1;
515 
516  /* If the mask is 0 then go to new SerialNum byte rom_byte_number and reset mask */
517  if (rom_byte_mask == 0)
518  {
519  rom_byte_number++;
520  rom_byte_mask = 1;
521  }
522  }
523  }
524  while (rom_byte_number < 8);
525 
526  /* If the search was successful then */
527  if (!(id_bit_number < 65))
528  {
529  /* Search successful so set LastDiscrepancy, LastDeviceFlag, search_result */
530  _bc_onewire.last_discrepancy = last_zero;
531 
532  /* Check for last device */
533  if (_bc_onewire.last_discrepancy == 0)
534  {
535  _bc_onewire.last_device_flag = true;
536  }
537 
538  search_result = !_bc_onewire.last_rom_no[0] ? false : true;
539  }
540 
541  _bc_onewire_stop();
542  }
543 
544  if (search_result
545  && bc_onewire_crc8(_bc_onewire.last_rom_no, sizeof(_bc_onewire.last_rom_no), 0x00) != 0)
546  {
547  search_result = false;
548  }
549 
550  if (search_result)
551  {
552  memcpy(device_number, _bc_onewire.last_rom_no, sizeof(_bc_onewire.last_rom_no));
553  }
554  else
555  {
556  _bc_onewire_search_reset();
557  }
558 
559  return search_result;
560 }
561 
563 {
564  _bc_onewire.auto_ds28e17_sleep_mode = on;
565 }
566 
567 static int _bc_onewire_search_devices(bc_gpio_channel_t channel, uint64_t *device_list, size_t device_list_size)
568 {
569  int devices = 0;
570  int max_devices = device_list_size / sizeof(uint64_t);
571 
572  while ((devices < max_devices) && bc_onewire_search_next(channel, device_list))
573  {
574  device_list++;
575  devices++;
576  }
577 
578  return devices;
579 }
void bc_irq_enable(void)
Enable interrupt requests globally (call can be nested)
Definition: bc_irq.c:21
GPIO channel has no pull-up/pull-down.
Definition: bc_gpio.h:84
bool bc_onewire_search_next(bc_gpio_channel_t channel, uint64_t *device_number)
Manual search of next device.
Definition: bc_onewire.c:425
int bc_onewire_read_bit(bc_gpio_channel_t channel)
Select device.
Definition: bc_onewire.c:174
int bc_onewire_search_all(bc_gpio_channel_t channel, uint64_t *device_list, size_t device_list_size)
Search for all devices on 1-Wire.
Definition: bc_onewire.c:182
void bc_timer_start(void)
Start timer.
Definition: bc_timer.c:24
void bc_timer_delay(uint16_t microseconds)
Relative delay.
Definition: bc_timer.c:40
void bc_gpio_set_output(bc_gpio_channel_t channel, int state)
Set output state for GPIO channel.
Definition: bc_gpio.c:442
bool bc_onewire_transaction_stop(bc_gpio_channel_t channel)
Stop transaction.
Definition: bc_onewire.c:67
void bc_gpio_set_mode(bc_gpio_channel_t channel, bc_gpio_mode_t mode)
Set mode of operation for GPIO channel.
Definition: bc_gpio.c:340
void bc_gpio_set_pull(bc_gpio_channel_t channel, bc_gpio_pull_t pull)
Set pull-up/pull-down configuration for GPIO channel.
Definition: bc_gpio.c:313
void bc_onewire_auto_ds28e17_sleep_mode(bool on)
Enable call sleep mode for all ds28e17 after transaction.
Definition: bc_onewire.c:562
void bc_timer_stop(void)
Stop timer.
Definition: bc_timer.c:55
void bc_onewire_write_bit(bc_gpio_channel_t channel, int bit)
Select device.
Definition: bc_onewire.c:167
int bc_gpio_get_input(bc_gpio_channel_t channel)
Get input state for GPIO channel.
Definition: bc_gpio.c:436
GPIO channel operates as input.
Definition: bc_gpio.h:99
void bc_onewire_write_8b(bc_gpio_channel_t channel, uint8_t byte)
Select device.
Definition: bc_onewire.c:152
void bc_onewire_search_start(uint8_t family_code)
Start of manual search, see also bc_onewire_search_next.
Definition: bc_onewire.c:413
bool bc_onewire_reset(bc_gpio_channel_t channel)
Reset the 1-Wire bus and return the presence of any device.
Definition: bc_onewire.c:91
void bc_onewire_init(bc_gpio_channel_t channel)
Initialize 1-Wire.
Definition: bc_onewire.c:35
void bc_onewire_select(bc_gpio_channel_t channel, uint64_t *device_number)
Select device.
Definition: bc_onewire.c:104
bool bc_onewire_transaction_start(bc_gpio_channel_t channel)
Start transaction, enable pll and run timer.
Definition: bc_onewire.c:51
uint8_t bc_onewire_crc8(const void *buffer, size_t length, uint8_t crc)
Calculate 8-bit CRC.
Definition: bc_onewire.c:197
uint16_t bc_onewire_crc16(const void *buffer, size_t length, uint16_t crc)
Calculate 16-bit CRC, polynomial 0x8005.
Definition: bc_onewire.c:224
bc_gpio_channel_t
GPIO channels.
Definition: bc_gpio.h:12
void bc_onewire_write(bc_gpio_channel_t channel, const void *buffer, size_t length)
Select device.
Definition: bc_onewire.c:132
void bc_onewire_skip_rom(bc_gpio_channel_t channel)
Skip ROM.
Definition: bc_onewire.c:125
int bc_onewire_search_family(bc_gpio_channel_t channel, uint8_t family_code, uint64_t *device_list, size_t device_list_size)
Search for all devices on 1-Wire with family code.
Definition: bc_onewire.c:189
void bc_irq_disable(void)
Disable interrupt requests globally (call can be nested)
Definition: bc_irq.c:7
void bc_timer_init(void)
Initialize timer.
Definition: bc_timer.c:18
void bc_onewire_read(bc_gpio_channel_t channel, void *buffer, size_t length)
Select device.
Definition: bc_onewire.c:142
uint8_t bc_onewire_read_8b(bc_gpio_channel_t channel)
Select device.
Definition: bc_onewire.c:159
void bc_gpio_init(bc_gpio_channel_t channel)
Initialize GPIO channel.
Definition: bc_gpio.c:301
GPIO channel operates as output.
Definition: bc_gpio.h:102