CuVoodoo STM32F1 firmware template
onewire_master.c
Go to the documentation of this file.
1 /* This program is free software: you can redistribute it and/or modify
2  * it under the terms of the GNU General Public License as published by
3  * the Free Software Foundation, either version 3 of the License, or
4  * (at your option) any later version.
5  *
6  * This program is distributed in the hope that it will be useful,
7  * but WITHOUT ANY WARRANTY; without even the implied warranty of
8  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9  * GNU General Public License for more details.
10  *
11  * You should have received a copy of the GNU General Public License
12  * along with this program. If not, see <http://www.gnu.org/licenses/>.
13  *
14  */
24 /* standard libraries */
25 #include <stdint.h> // standard integer types
26 #include <stdbool.h> // boolean type
27 #include <stddef.h> // NULL definition
28 
29 /* STM32 (including CM3) libraries */
30 #include <libopencmsis/core_cm3.h> // Cortex M3 utilities
31 #include <libopencm3/cm3/nvic.h> // interrupt handler
32 #include <libopencm3/stm32/rcc.h> // real-time control clock library
33 #include <libopencm3/stm32/gpio.h> // general purpose input output library
34 #include <libopencm3/stm32/timer.h> // timer library
35 
36 /* own libraries */
37 #include "global.h" // help macros
38 #include "interrupt.h" // runtime interrupt table
39 #include "onewire_master.h" // own definitions
40 
44 #define ONEWIRE_MASTER_TIMER 5
50 #define ONEWIRE_MASTER_TIMER_USE_INTERRUPT_TABLE false
51 
53 volatile enum {
63 
64 static volatile bool slave_presence = false;
65 static uint8_t* buffer = NULL;
66 static uint32_t buffer_size = 0;
67 static volatile uint32_t buffer_bit = 0;
68 #if defined(ONEWIRE_MASTER_TIMER_USE_INTERRUPT_TABLE) && ONEWIRE_MASTER_TIMER_USE_INTERRUPT_TABLE
69 static void (*isr_backup)(void) = NULL;
70 static bool irq_backup = false;
71 #endif
72 
74 #if defined(ONEWIRE_MASTER_TIMER_USE_INTERRUPT_TABLE) && ONEWIRE_MASTER_TIMER_USE_INTERRUPT_TABLE
75 static void onewire_master_timer_isr(void)
76 #else
78 #endif
79 {
80  if (timer_get_flag(TIM(ONEWIRE_MASTER_TIMER), TIM_SR_UIF)) { // overflow update event happened
81  timer_clear_flag(TIM(ONEWIRE_MASTER_TIMER), TIM_SR_UIF); // clear flag
82  switch (onewire_master_state) {
83  case ONEWIRE_STATE_MASTER_RESET: // reset pulse has been started
84  timer_clear_flag(TIM(ONEWIRE_MASTER_TIMER), TIM_SR_CC4IF); // clear output compare flag
85  timer_enable_irq(TIM(ONEWIRE_MASTER_TIMER), TIM_DIER_CC4IE); // enable compare interrupt for presence detection
86  gpio_set(GPIO(ONEWIRE_MASTER_PORT),GPIO(ONEWIRE_MASTER_PIN)); // set signal high again for slaves to respond
88  break;
89  case ONEWIRE_STATE_SLAVE_PRESENCE: // waiting for slave presence but none received
90  timer_disable_counter(TIM(ONEWIRE_MASTER_TIMER)); // disable timer
91  timer_disable_irq(TIM(ONEWIRE_MASTER_TIMER), TIM_DIER_CC4IE); // disable compare interrupt for presence detection
92  onewire_master_state = ONEWIRE_STATE_DONE; // go to next state
93  break;
94  case ONEWIRE_STATE_MASTER_READ: // end of time slot and recovery time for reading bit
95  case ONEWIRE_STATE_MASTER_WRITE: // end of time slot and recovery time for writing bit
96  if (buffer_bit<buffer_size) { // check if byte to read/write are remaining
97  gpio_clear(GPIO(ONEWIRE_MASTER_PORT),GPIO(ONEWIRE_MASTER_PIN)); // pull signal low to start next slot
98  } else { // all bytes read/written
99  timer_disable_counter(TIM(ONEWIRE_MASTER_TIMER)); // disable timer
100  timer_disable_irq(TIM(ONEWIRE_MASTER_TIMER), TIM_DIER_CC1IE); // disable compare interrupt for master pull low
101  timer_disable_irq(TIM(ONEWIRE_MASTER_TIMER), TIM_DIER_CC2IE); // disable compare interrupt for read/write bit
102  timer_disable_irq(TIM(ONEWIRE_MASTER_TIMER), TIM_DIER_CC3IE); // disable compare interrupt for end of slot
103  onewire_master_state = ONEWIRE_STATE_DONE; // set end state
104  }
105  break;
106  default: // unknown state for this stage
107  timer_disable_counter(TIM(ONEWIRE_MASTER_TIMER)); // disable timer
108  timer_disable_irq(TIM(ONEWIRE_MASTER_TIMER), TIM_DIER_CC1IE); // disable all compare interrupt
109  timer_disable_irq(TIM(ONEWIRE_MASTER_TIMER), TIM_DIER_CC2IE); // disable all compare interrupt
110  timer_disable_irq(TIM(ONEWIRE_MASTER_TIMER), TIM_DIER_CC3IE); // disable all compare interrupt
111  timer_disable_irq(TIM(ONEWIRE_MASTER_TIMER), TIM_DIER_CC4IE); // disable all compare interrupt
112  gpio_set(GPIO(ONEWIRE_MASTER_PORT),GPIO(ONEWIRE_MASTER_PIN)); // pull signal high (idle state)
113  onewire_master_state = ONEWIRE_STATE_ERROR; // indicate error
114  }
115  } else if (timer_get_flag(TIM(ONEWIRE_MASTER_TIMER), TIM_SR_CC1IF)) { // compare event happened for master pull low end for read
116  timer_clear_flag(TIM(ONEWIRE_MASTER_TIMER), TIM_SR_CC1IF); // clear flag
117  switch (onewire_master_state) {
118  case ONEWIRE_STATE_MASTER_READ: // master has to read a bit
119  gpio_set(GPIO(ONEWIRE_MASTER_PORT),GPIO(ONEWIRE_MASTER_PIN)); // pull signal high to end time slot
120  break;
121  default: // unknown state for this stage
122  break; // let the overflow handle the error if any
123  }
124  } else if (timer_get_flag(TIM(ONEWIRE_MASTER_TIMER), TIM_SR_CC2IF)) { // compare event happened for bit sampling/setting
125  timer_clear_flag(TIM(ONEWIRE_MASTER_TIMER), TIM_SR_CC2IF); // clear flag
126  switch (onewire_master_state) {
127  case ONEWIRE_STATE_MASTER_WRITE: // master has to write a bit
128  if (buffer_bit<buffer_size) { // check if byte to send are remaining
129  if (buffer[buffer_bit/8]&(1<<(buffer_bit%8))) { // check bit (LSb first)
130  gpio_set(GPIO(ONEWIRE_MASTER_PORT),GPIO(ONEWIRE_MASTER_PIN)); // set signal high again to write "1"
131  }
132  buffer_bit++; // got to next bit
133  } else {
134  timer_disable_irq(TIM(ONEWIRE_MASTER_TIMER), TIM_DIER_CC2IE); // disable compare interrupt
135  onewire_master_state = ONEWIRE_STATE_ERROR; // indicate error
136  }
137  break;
138  case ONEWIRE_STATE_MASTER_READ: // master has to read a bit set by slave
139  if (buffer_bit<buffer_size) { // check if byte to send are remaining
140  if (gpio_get(GPIO(ONEWIRE_MASTER_PORT),GPIO(ONEWIRE_MASTER_PIN))) { // check if the slave kept it low
141  buffer[buffer_bit/8] |= (1<<(buffer_bit%8)); // save bit "1"
142  } else {
143  buffer[buffer_bit/8] &= ~(1<<(buffer_bit%8)); // save bit "0"
144  }
145  buffer_bit++; // got to next bit
146  } else {
147  timer_disable_irq(TIM(ONEWIRE_MASTER_TIMER), TIM_DIER_CC2IE); // disable compare interrupt
148  onewire_master_state = ONEWIRE_STATE_ERROR; // indicate error
149  }
150  break;
151  default: // unknown state for this stage
152  break; // let the overflow handle the error if any
153  }
154  } else if (timer_get_flag(TIM(ONEWIRE_MASTER_TIMER), TIM_SR_CC3IF)) { // compare event happened for end to time slot
155  timer_clear_flag(TIM(ONEWIRE_MASTER_TIMER), TIM_SR_CC3IF); // clear flag
156  gpio_set(GPIO(ONEWIRE_MASTER_PORT),GPIO(ONEWIRE_MASTER_PIN)); // pull signal high to end time slot
157  } else if (timer_get_flag(TIM(ONEWIRE_MASTER_TIMER), TIM_SR_CC4IF)) { // compare event happened for slave presence detection
158  timer_clear_flag(TIM(ONEWIRE_MASTER_TIMER), TIM_SR_CC4IF); // clear flag
159  if (gpio_get(GPIO(ONEWIRE_MASTER_PORT),GPIO(ONEWIRE_MASTER_PIN))) { // check is a slave let its presence know by pulling low
160  slave_presence = false; // remember no slave(s) responded
161  } else {
162  slave_presence = true; // remember slave(s) responded
163  }
164  } else { // no other interrupt should occur
165  while (true); // unhandled exception: wait for the watchdog to bite
166  }
167 }
168 
170 {
171  // setup GPIO with external interrupt
172  rcc_periph_clock_enable(RCC_GPIO(ONEWIRE_MASTER_PORT)); // enable clock for GPIO peripheral
173  gpio_set(GPIO(ONEWIRE_MASTER_PORT),GPIO(ONEWIRE_MASTER_PIN)); // idle is high (using pull-up resistor)
174  gpio_set_mode(GPIO(ONEWIRE_MASTER_PORT), GPIO_MODE_OUTPUT_50_MHZ, GPIO_CNF_OUTPUT_OPENDRAIN, GPIO(ONEWIRE_MASTER_PIN)); // normal 1-Wire communication (only using external pull-up resistor)
175 
176  // setup timer to generate/measure signal timing
177  rcc_periph_clock_enable(RCC_TIM(ONEWIRE_MASTER_TIMER)); // enable clock for timer peripheral
178  timer_reset(TIM(ONEWIRE_MASTER_TIMER)); // reset timer state
179  timer_disable_counter(TIM(ONEWIRE_MASTER_TIMER)); // disable timer to configure it
180  timer_set_mode(TIM(ONEWIRE_MASTER_TIMER), TIM_CR1_CKD_CK_INT, TIM_CR1_CMS_EDGE, TIM_CR1_DIR_UP); // set timer mode, use undivided timer clock, edge alignment (simple count), and count up
181  timer_set_prescaler(TIM(ONEWIRE_MASTER_TIMER), 1-1); // don't use prescale since this 16 bits timer allows to wait > 480 us used for the reset pulse ( 1/(72E6/1/(2**16))=910us )
182 
183  // use comparator to time signal (without using the output), starting at slot start
184  timer_clear_flag(TIM(ONEWIRE_MASTER_TIMER), TIM_SR_CC1IF); // clear flag
185  timer_set_oc_value(TIM(ONEWIRE_MASTER_TIMER), TIM_OC1, 1*(rcc_ahb_frequency/1000000)-1); // use compare function to time master pulling low when reading (1 < Tlowr < 15)
186  timer_clear_flag(TIM(ONEWIRE_MASTER_TIMER), TIM_SR_CC2IF); // clear flag
187  timer_set_oc_value(TIM(ONEWIRE_MASTER_TIMER), TIM_OC2, 7*(rcc_ahb_frequency/1000000)-1); // use compare function to read or write 0 or 1 (1 < Trw < 15)
188  timer_clear_flag(TIM(ONEWIRE_MASTER_TIMER), TIM_SR_CC3IF); // clear flag
189  timer_set_oc_value(TIM(ONEWIRE_MASTER_TIMER), TIM_OC3, 62*(rcc_ahb_frequency/1000000)-1); // use compare function to end time slot (60 < Tslot < 120), this will be followed by a recovery time (end of timer)
190  timer_clear_flag(TIM(ONEWIRE_MASTER_TIMER), TIM_SR_CC4IF); // clear flag
191  timer_set_oc_value(TIM(ONEWIRE_MASTER_TIMER), TIM_OC4, (70-10)*(rcc_ahb_frequency/1000000)-1); // use compare function to detect slave presence (15 < Tpdh < 60 + 60 < Tpdl < 240), with hand tuning
192  timer_clear_flag(TIM(ONEWIRE_MASTER_TIMER), TIM_SR_UIF); // clear update (overflow) flag
193  timer_update_on_overflow(TIM(ONEWIRE_MASTER_TIMER)); // only use counter overflow as UEV source (use overflow as start time or timeout)
194  timer_enable_irq(TIM(ONEWIRE_MASTER_TIMER), TIM_DIER_UIE); // enable update interrupt for overflow
195 #if defined(ONEWIRE_MASTER_TIMER_USE_INTERRUPT_TABLE) && ONEWIRE_MASTER_TIMER_USE_INTERRUPT_TABLE
196  isr_backup = interrupt_table[NVIC_TIM_IRQ(ONEWIRE_MASTER_TIMER)]; // backup timer ISR
197  interrupt_table[NVIC_TIM_IRQ(ONEWIRE_MASTER_TIMER)] = &onewire_master_timer_isr; // set the 1-wire timer ISR
198  irq_backup = nvic_get_irq_enabled(NVIC_TIM_IRQ(ONEWIRE_MASTER_TIMER)); // backup timer IRQ setting
199 #endif
200  nvic_enable_irq(NVIC_TIM_IRQ(ONEWIRE_MASTER_TIMER)); // catch interrupt in service routine
201 
202  slave_presence = false; // reset state
203  onewire_master_state = ONEWIRE_STATE_IDLE; // reset state
204 }
205 
207 {
208  // release timer
209  timer_disable_counter(TIM(ONEWIRE_MASTER_TIMER)); // disable timer
210  timer_reset(TIM(ONEWIRE_MASTER_TIMER)); // reset timer state
211  rcc_periph_clock_disable(RCC_TIM(ONEWIRE_MASTER_TIMER)); // disable clock for timer peripheral
212 
213  // release GPIO
214  gpio_set_mode(GPIO(ONEWIRE_MASTER_PORT), GPIO_MODE_INPUT, GPIO_CNF_INPUT_FLOAT, GPIO(ONEWIRE_MASTER_PIN)); // put back to input floating
215 
216  // disable timer ISR
217 #if defined(ONEWIRE_MASTER_TIMER_USE_INTERRUPT_TABLE) && ONEWIRE_MASTER_TIMER_USE_INTERRUPT_TABLE
218  if (!irq_backup) { // don't disable the IRQ if there was already enabled
219  nvic_disable_irq(NVIC_TIM_IRQ(ONEWIRE_MASTER_TIMER)); // stop timer IRQ
220  }
221  interrupt_table[NVIC_TIM_IRQ(ONEWIRE_MASTER_TIMER)] = isr_backup; // set back original timer ISR
222 #else
223  nvic_disable_irq(NVIC_TIM_IRQ(ONEWIRE_MASTER_TIMER)); // stop timer IRQ
224 #endif
225 }
226 
228 {
229  // prepare timer
230  timer_disable_counter(TIM(ONEWIRE_MASTER_TIMER)); // disable timer to reconfigure it
231  timer_set_counter(TIM(ONEWIRE_MASTER_TIMER),0); // reset counter
232  timer_set_period(TIM(ONEWIRE_MASTER_TIMER), 490*(rcc_ahb_frequency/1000000)-1); // set timeout to > 480 us (480 < Trst)
233 
234  slave_presence = false; // reset state
236 
237  gpio_set_mode(GPIO(ONEWIRE_MASTER_PORT), GPIO_MODE_OUTPUT_50_MHZ, GPIO_CNF_OUTPUT_OPENDRAIN, GPIO(ONEWIRE_MASTER_PIN)); // normal 1-Wire communication (only using external pull-up resistor)
238  gpio_clear(GPIO(ONEWIRE_MASTER_PORT),GPIO(ONEWIRE_MASTER_PIN)); // pull signal low to start reset (it's not important if it was low in the first place since the reset pulse has no maximum time)
239  timer_enable_counter(TIM(ONEWIRE_MASTER_TIMER)); // start timer
240 
241  while (onewire_master_state!=ONEWIRE_STATE_DONE && onewire_master_state!=ONEWIRE_STATE_ERROR) { // wait until reset procedure completed
242  __WFI(); // go to sleep
243  }
244  if (ONEWIRE_STATE_ERROR==onewire_master_state) { // an error occurred
245  return false;
246  }
247 
248  return slave_presence;
249 }
250 
255 static bool onewire_master_write(void)
256 {
257  buffer_bit = 0; // reset bit index
259 
260  // prepare timer
261  timer_disable_counter(TIM(ONEWIRE_MASTER_TIMER)); // disable timer to reconfigure it
262  timer_set_counter(TIM(ONEWIRE_MASTER_TIMER), 0); // reset counter
263  timer_set_period(TIM(ONEWIRE_MASTER_TIMER), TIM_CCR3(TIM(ONEWIRE_MASTER_TIMER))+2*(rcc_ahb_frequency/1000000)); // set time for new time slot (recovery timer Trec>1, after time slot end )
264  timer_clear_flag(TIM(ONEWIRE_MASTER_TIMER), TIM_SR_CC2IF); // clear output compare flag
265  timer_enable_irq(TIM(ONEWIRE_MASTER_TIMER), TIM_DIER_CC2IE); // enable compare interrupt for bit setting
266  timer_clear_flag(TIM(ONEWIRE_MASTER_TIMER), TIM_SR_CC3IF); // clear output compare flag
267  timer_enable_irq(TIM(ONEWIRE_MASTER_TIMER), TIM_DIER_CC3IE); // enable compare interrupt for end of time slow
268 
269  // start writing
270  gpio_set_mode(GPIO(ONEWIRE_MASTER_PORT), GPIO_MODE_OUTPUT_50_MHZ, GPIO_CNF_OUTPUT_OPENDRAIN, GPIO(ONEWIRE_MASTER_PIN)); // normal 1-Wire communication (only using external pull-up resistor)
271  gpio_clear(GPIO(ONEWIRE_MASTER_PORT),GPIO(ONEWIRE_MASTER_PIN)); // pull signal low to start slot
272  timer_enable_counter(TIM(ONEWIRE_MASTER_TIMER)); // start timer
273  while (onewire_master_state!=ONEWIRE_STATE_DONE && onewire_master_state!=ONEWIRE_STATE_ERROR) { // wait until write procedure completed
274  __WFI(); // go to sleep
275  }
276  if (ONEWIRE_STATE_ERROR==onewire_master_state) { // an error occurred
277  return false;
278  }
279  return true;
280 }
281 
286 static bool onewire_master_read(void)
287 {
288  if (0==buffer_size) { // check input
289  return false;
290  }
291  buffer_bit = 0; // reset bit index
293 
294  // prepare timer
295  timer_disable_counter(TIM(ONEWIRE_MASTER_TIMER)); // disable timer to reconfigure it
296  timer_set_counter(TIM(ONEWIRE_MASTER_TIMER), 0); // reset counter
297  timer_set_period(TIM(ONEWIRE_MASTER_TIMER), TIM_CCR3(TIM(ONEWIRE_MASTER_TIMER))+2*(rcc_ahb_frequency/1000000)); // set time for new time slot (recovery timer Trec>1, after time slot end )
298  timer_clear_flag(TIM(ONEWIRE_MASTER_TIMER), TIM_SR_CC1IF); // clear output compare flag
299  timer_enable_irq(TIM(ONEWIRE_MASTER_TIMER), TIM_DIER_CC1IE); // enable compare interrupt for stop pulling low
300  timer_clear_flag(TIM(ONEWIRE_MASTER_TIMER), TIM_SR_CC2IF); // clear output compare flag
301  timer_enable_irq(TIM(ONEWIRE_MASTER_TIMER), TIM_DIER_CC2IE); // enable compare interrupt for bit setting
302  timer_clear_flag(TIM(ONEWIRE_MASTER_TIMER), TIM_SR_CC3IF); // clear output compare flag
303  timer_enable_irq(TIM(ONEWIRE_MASTER_TIMER), TIM_DIER_CC3IE); // enable compare interrupt for end of time slow
304 
305  // start reading
306  gpio_set_mode(GPIO(ONEWIRE_MASTER_PORT), GPIO_MODE_OUTPUT_50_MHZ, GPIO_CNF_OUTPUT_OPENDRAIN, GPIO(ONEWIRE_MASTER_PIN)); // normal 1-Wire communication (only using external pull-up resistor)
307  gpio_clear(GPIO(ONEWIRE_MASTER_PORT),GPIO(ONEWIRE_MASTER_PIN)); // pull signal low to start slot
308  timer_enable_counter(TIM(ONEWIRE_MASTER_TIMER)); // start timer
309  while (onewire_master_state!=ONEWIRE_STATE_DONE && onewire_master_state!=ONEWIRE_STATE_ERROR) { // wait until read procedure completed
310  __WFI(); // go to sleep
311  }
312  if (ONEWIRE_STATE_ERROR==onewire_master_state) { // an error occurred
313  return false;
314  }
315  return true;
316 }
317 
318 uint8_t onewire_master_crc(uint8_t* data, uint32_t length)
319 {
320  if (NULL==data || 0==length) { // check input
321  return 0; // wrong input
322  }
323 
324  uint8_t crc = 0x00; // initial value
325  for (uint8_t i=0; i<length; i++) { // go through every byte
326  crc ^= data[i]; // XOR byte
327  for (uint8_t b=0; b<8; b++) { // go through every bit
328  if (crc&0x01) { // least significant bit is set (we are using the reverse way)
329  crc = (crc>>1)^0x8C; // // shift to the right (for the next bit) and XOR with (reverse) polynomial
330  } else {
331  crc >>= 1; // just shift right (for the next bit)
332  }
333  }
334  }
335  return crc;
336 }
337 
338 bool onewire_master_read_byte(uint8_t* data)
339 {
340  if (NULL==data) { // check input
341  return false; // wrong input
342  }
343 
344  // read data
345  buffer_size = 8; // save number of bits to read (1 byte)
346  buffer = data; // set the buffer to the data to write
347  if (!onewire_master_read()) { // read bits from slave
348  return false; // an error occurred
349  }
350  return true;
351 }
352 
353 bool onewire_master_write_byte(uint8_t data)
354 {
355  // send data byte
356  buffer_size = 8; // function command is only one byte
357  buffer = &data; // set the buffer to the function code
358  if (!onewire_master_write()) { // send command
359  return false; // an error occurred
360  }
361  return true;
362 }
363 
364 bool onewire_master_function_read(uint8_t function, uint8_t* data, uint32_t bits)
365 {
366  // send function command
367  if (!onewire_master_write_byte(function)) {
368  return false; // an error occurred
369  }
370 
371  if (NULL==data || 0==bits) { // there is no data to read
372  return true; // operation completed
373  }
374 
375  // read data
376  buffer_size = bits; // save number of bits to read
377  buffer = data; // set the buffer to the data to write
378  if (!onewire_master_read()) { // read bits from slave
379  return false; // an error occurred
380  }
381 
382  return true;
383 }
384 
385 bool onewire_master_function_write(uint8_t function, uint8_t* data, uint32_t bits)
386 {
387  // send function command
388  if (!onewire_master_write_byte(function)) {
389  return false; // an error occurred
390  }
391 
392  if (NULL==data || 0==bits) { // there is no data to read
393  return true; // operation completed
394  }
395 
396  // copy data from user buffer
397  buffer_size = bits; // save number of bits to write
398  buffer = data; // set the buffer to the data to write
399  // write data
400  if (!onewire_master_write()) { // read bits from slave
401  return false; // an error occurred
402  }
403 
404  return true;
405 }
406 
408 {
409  uint8_t rom_code[8] = {0}; // to store 64 bits ROM code
410  if (!onewire_master_function_read(0x33, rom_code, 64)) { // read ROM code (I'm cheating because the ROM command isn't a function command, but it works the same way in the end)
411  return 0; // an error occurred
412  }
413  if (onewire_master_crc(rom_code, LENGTH(rom_code))) { // verify checksum
414  return 0; // checksum is wrong (not 0)
415  }
416 
417  // return ROM code
418  uint64_t code = 0;
419  for (uint32_t i=0; i<8; i++) {
420  code += (uint64_t)rom_code[i]<<(8*i); // add byte
421  }
422 
423  return code;
424 }
425 
426 bool onewire_master_rom_search(uint64_t* code, bool alarm)
427 {
428  static uint8_t conflict_last = 64; // on which bit has the conflict been detected (64 means there hasn't been)
429  uint8_t conflict_current = 64; // to remember on which bit the last unknown conflict has been detected
430  uint8_t bits[1] = {0}; // small buffer to store the bits used to search the ROM codes
431 
432  // send SEARCH ROM command
433  uint8_t command = 0xf0; // SEARCH ROM command
434  if (alarm) { // looking only for ROM codes for slaves in alarm state
435  command = 0xec; // use ALARM SEARCH ROM command instead
436  }
437  if (!onewire_master_function_read(command, NULL, 0)) { // send SEARCH ROM command
438  goto end; // an error occurred
439  }
440 
441  if (conflict_last>=64) { // no previous conflict has been detected
442  *code = 0; // restart search codes
443  }
444 
445  buffer = bits; // buffer to read up to two bits
446  for (uint8_t bit=0; bit<64; bit++) { // go through all 64 bits ROM code
447  buffer_size = 2; // read two first bits to detect conflict
448  if (!onewire_master_read()) { // read ROM ID from slave
449  goto end; // an error occurred
450  }
451  switch (buffer[0]&0x03) { // check 2 bits received
452  case 0: // collision detected
453  if (bit==conflict_last) { // this conflict is known
454  *code |= (((uint64_t)1)<<bit); // use 0 as next bit
455  } else { // unknown conflict
456  conflict_current = bit; // remember conflict
457  *code &= ~(((uint64_t)1)<<bit); // use 1 as next bit
458  }
459  break;
460  case 1: // no conflict, valid bit is 1
461  *code |= (((uint64_t)1)<<bit); // remember valid bit 1
462  break;
463  case 2: // no conflict, valid bit is 0
464  *code &= ~(((uint64_t)1)<<bit); // remember valid bit 0
465  break;
466  default: // two 1's indicate there is no slave
467  conflict_current = 64; // remember there was no conflict because there is no slave
468  goto end; // an error has occurred
469  }
470  buffer_size = 1; // to send next bit
471  buffer[0] = ((*code)>>bit); // set bit to send
472  if (!onewire_master_write()) { // send bit
473  goto end; // an error has occurred
474  }
475  }
476  // verify ROM code
477  uint8_t rom_code[8] = {0}; // to store ROM code
478  for (uint8_t i=0; i<LENGTH(rom_code); i++) {
479  rom_code[i] = (*code)>>(8*i); // split and save last code in ROM code
480  }
481  if (onewire_master_crc(rom_code, LENGTH(rom_code))) { // verify checksum
482  *code = 0; // return the last code found since it's valid
483  }
484 
485 end:
486  conflict_last = conflict_current; // update the last seen and unknown conflict
487  if (conflict_current<64) { // we have seen an unknown conflict
488  return true; // tell there are more slaves
489  } else { // no conflict seen
490  return false; // no more slaves
491  }
492 }
493 
495 {
496  if (!onewire_master_function_write(0xcc, NULL, 0)) { // send SKIP ROM command
497  return false; // an error occurred
498  }
499  return true;
500 }
501 
502 bool onewire_master_rom_match(uint64_t code)
503 {
504  uint8_t rom_code[8] = {0}; // to store ROM code
505  for (uint8_t i=0; i<LENGTH(rom_code); i++) {
506  rom_code[i] = code>>(8*i); // split and save code in ROM code
507  }
508  if (!onewire_master_function_write(0x55, rom_code, 64)) { // send MATCH ROM command with ROM code
509  return false; // an error occurred
510  }
511  return true;
512 }
513 
static volatile uint32_t buffer_bit
number of bits read/written
#define ONEWIRE_MASTER_PORT
GPIO port.
#define RCC_GPIO(x)
get RCC for GPIO based on GPIO identifier
Definition: global.h:105
reset pulse started
uint64_t onewire_master_rom_read(void)
send READ ROM command and read ROM code response
bool onewire_master_rom_search(uint64_t *code, bool alarm)
send SEARCH ROM command
#define NVIC_TIM_IRQ(x)
get NVIC IRQ for timer base on TIM identifier
Definition: global.h:111
bool onewire_master_function_write(uint8_t function, uint8_t *data, uint32_t bits)
issue function and write data
#define ONEWIRE_MASTER_PIN
GPIO pin.
communication error
waiting for slave response to reset pulse
void onewire_master_setup(void)
setup 1-wire peripheral
global definitions and methods (API)
#define GPIO(x)
get GPIO based on GPIO identifier
Definition: global.h:103
static bool onewire_master_read(void)
read bits on 1-Wire bus
#define RCC_TIM(x)
get RCC for timer based on TIM identifier
Definition: global.h:109
void TIM_ISR(2)
timer ISR to measure edge timing
library for 1-wire protocol as master
bool onewire_master_write_byte(uint8_t data)
write data byte
bool onewire_master_function_read(uint8_t function, uint8_t *data, uint32_t bits)
issue function and read data
bool onewire_master_rom_skip(void)
send SKIP ROM command (all slaves on the bus will be selected)
master is writing bits
static bool onewire_master_write(void)
write bits on 1-Wire bus
vector_table_entry_t interrupt_table[NVIC_IRQ_COUNT]
table of interrupts which can set to user functions
Definition: interrupt.c:21
to count the number of possible states
BusVoodoo runtime interrupt table.
static uint8_t * buffer
input/output buffer for read/write commands/functions
bool onewire_master_read_byte(uint8_t *data)
read data byte
static uint32_t buffer_size
size of buffer in bits
communication complete
#define LENGTH(x)
get the length of an array
Definition: global.h:26
bool onewire_master_rom_match(uint64_t code)
send MATCH ROM command to select a specific slave
#define TIM(x)
get TIM based on TIM identifier
Definition: global.h:107
void onewire_master_release(void)
release 1-wire peripheral
static volatile bool slave_presence
if slaves have been detected
uint8_t onewire_master_crc(uint8_t *data, uint32_t length)
compute CRC for 1-Wire
no current communication
master is reading bits
bool onewire_master_reset(void)
send reset pulse
enum @0 onewire_master_state
state of 1-Wire communication
#define ONEWIRE_MASTER_TIMER
timer ID