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  bc_timer_delay(70);
270 
271  i = bc_gpio_get_input(channel);
272 
273  bc_timer_delay(410);
274 
275  return i == 0;
276 }
277 
278 static void _bc_onewire_write_byte(bc_gpio_channel_t channel, uint8_t byte)
279 {
280  for (uint8_t i = 0; i < 8; i++)
281  {
282  _bc_onewire_write_bit(channel, byte & 0x01);
283  byte >>= 1;
284  }
285 }
286 
287 static uint8_t _bc_onewire_read_byte(bc_gpio_channel_t channel)
288 {
289  uint8_t byte = 0;
290  for (uint8_t i = 0; i < 8; i++)
291  {
292  byte |= (_bc_onewire_read_bit(channel) << i);
293  }
294  return byte;
295 }
296 
297 static void _bc_onewire_write_bit(bc_gpio_channel_t channel, uint8_t bit)
298 {
299  bc_gpio_set_output(channel, 0);
301 
302  if (bit)
303  {
304  bc_irq_disable();
305 
306  bc_timer_delay(3);
307 
308  bc_irq_enable();
309 
311 
312  bc_timer_delay(60);
313 
314  }
315  else
316  {
317  bc_timer_delay(55);
318 
320 
321  bc_timer_delay(8);
322  }
323 }
324 
325 static uint8_t _bc_onewire_read_bit(bc_gpio_channel_t channel)
326 {
327  uint8_t bit = 0;
328 
329  bc_gpio_set_output(channel, 0);
330 
332 
333  bc_irq_disable();
334 
335  bc_timer_delay(3);
336 
337  bc_irq_enable();
338 
340 
341  bc_irq_disable();
342 
343  bc_timer_delay(8);
344 
345  bc_irq_enable();
346 
347  bit = bc_gpio_get_input(channel);
348 
349  bc_timer_delay(50);
350 
351  return bit;
352 }
353 
354 static void _bc_onewire_start(void)
355 {
356  if (_bc_onewire.transaction)
357  {
358  return;
359  }
360 
361  bc_system_pll_enable();
362 
363  bc_timer_init();
364 
365  bc_timer_start();
366 }
367 
368 static void _bc_onewire_stop(void)
369 {
370  if (_bc_onewire.transaction)
371  {
372  return;
373  }
374 
375  bc_timer_stop();
376 
377  bc_system_pll_disable();
378 }
379 
380 static void _bc_onewire_search_reset(void)
381 {
382  _bc_onewire.last_discrepancy = 0;
383  _bc_onewire.last_device_flag = false;
384  _bc_onewire.last_family_discrepancy = 0;
385 }
386 
387 static void _bc_onewire_search_target_setup(uint8_t family_code)
388 {
389  memset(_bc_onewire.last_rom_no, 0, sizeof(_bc_onewire.last_rom_no));
390  _bc_onewire.last_rom_no[0] = family_code;
391  _bc_onewire.last_discrepancy = 64;
392  _bc_onewire.last_family_discrepancy = 0;
393  _bc_onewire.last_device_flag = false;
394 }
395 
396 void bc_onewire_search_start(uint8_t family_code)
397 {
398  if (family_code != 0)
399  {
400  _bc_onewire_search_target_setup(family_code);
401  }
402  else
403  {
404  _bc_onewire_search_reset();
405  }
406 }
407 
408 bool bc_onewire_search_next(bc_gpio_channel_t channel, uint64_t *device_number)
409 {
410  bool search_result = false;
411  uint8_t id_bit_number;
412  uint8_t last_zero, rom_byte_number;
413  uint8_t id_bit, cmp_id_bit;
414  uint8_t rom_byte_mask, search_direction;
415 
416  /* Initialize for search */
417  id_bit_number = 1;
418  last_zero = 0;
419  rom_byte_number = 0;
420  rom_byte_mask = 1;
421 
422  if (!_bc_onewire.last_device_flag)
423  {
424 
425  _bc_onewire_start();
426 
427  if (!_bc_onewire_reset(channel))
428  {
429  _bc_onewire_search_reset();
430  _bc_onewire_stop();
431  return false;
432  }
433 
434  // issue the search command
435  _bc_onewire_write_byte(channel, 0xf0);
436 
437  // loop to do the search
438  do
439  {
440  id_bit = _bc_onewire_read_bit(channel);
441  cmp_id_bit = _bc_onewire_read_bit(channel);
442 
443  // check for no devices on 1-wire
444  if ((id_bit == 1) && (cmp_id_bit == 1))
445  {
446  break;
447  }
448  else
449  {
450  /* All devices coupled have 0 or 1 */
451  if (id_bit != cmp_id_bit)
452  {
453  /* Bit write value for search */
454  search_direction = id_bit;
455  }
456  else
457  {
458  /* If this discrepancy is before the Last Discrepancy on a previous next then pick the same as last time */
459  if (id_bit_number < _bc_onewire.last_discrepancy)
460  {
461  search_direction = ((_bc_onewire.last_rom_no[rom_byte_number] & rom_byte_mask) > 0);
462  }
463  else
464  {
465  /* If equal to last pick 1, if not then pick 0 */
466  search_direction = (id_bit_number == _bc_onewire.last_discrepancy);
467  }
468 
469  /* If 0 was picked then record its position in LastZero */
470  if (search_direction == 0)
471  {
472  last_zero = id_bit_number;
473 
474  /* Check for Last discrepancy in family */
475  if (last_zero < 9)
476  {
477  _bc_onewire.last_family_discrepancy = last_zero;
478  }
479  }
480  }
481 
482  /* Set or clear the bit in the ROM byte rom_byte_number with mask rom_byte_mask */
483  if (search_direction == 1)
484  {
485  _bc_onewire.last_rom_no[rom_byte_number] |= rom_byte_mask;
486  }
487  else
488  {
489  _bc_onewire.last_rom_no[rom_byte_number] &= ~rom_byte_mask;
490  }
491 
492  /* Serial number search direction write bit */
493  _bc_onewire_write_bit(channel, search_direction);
494 
495  /* Increment the byte counter id_bit_number and shift the mask rom_byte_mask */
496  id_bit_number++;
497  rom_byte_mask <<= 1;
498 
499  /* If the mask is 0 then go to new SerialNum byte rom_byte_number and reset mask */
500  if (rom_byte_mask == 0)
501  {
502  rom_byte_number++;
503  rom_byte_mask = 1;
504  }
505  }
506  }
507  while (rom_byte_number < 8);
508 
509  /* If the search was successful then */
510  if (!(id_bit_number < 65))
511  {
512  /* Search successful so set LastDiscrepancy, LastDeviceFlag, search_result */
513  _bc_onewire.last_discrepancy = last_zero;
514 
515  /* Check for last device */
516  if (_bc_onewire.last_discrepancy == 0)
517  {
518  _bc_onewire.last_device_flag = true;
519  }
520 
521  search_result = !_bc_onewire.last_rom_no[0] ? false : true;
522  }
523 
524  _bc_onewire_stop();
525  }
526 
527  if (search_result
528  && bc_onewire_crc8(_bc_onewire.last_rom_no, sizeof(_bc_onewire.last_rom_no), 0x00) != 0)
529  {
530  search_result = false;
531  }
532 
533  if (search_result)
534  {
535  memcpy(device_number, _bc_onewire.last_rom_no, sizeof(_bc_onewire.last_rom_no));
536  }
537  else
538  {
539  _bc_onewire_search_reset();
540  }
541 
542  return search_result;
543 }
544 
546 {
547  _bc_onewire.auto_ds28e17_sleep_mode = on;
548 }
549 
550 static int _bc_onewire_search_devices(bc_gpio_channel_t channel, uint64_t *device_list, size_t device_list_size)
551 {
552  int devices = 0;
553  int max_devices = device_list_size / sizeof(uint64_t);
554 
555  while ((devices < max_devices) && bc_onewire_search_next(channel, device_list))
556  {
557  device_list++;
558  devices++;
559  }
560 
561  return devices;
562 }
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:408
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:545
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:396
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