2017-08-03 20:49:20 +02:00
/* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation , either version 3 of the License , or
* ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
* along with this program . If not , see < http : //www.gnu.org/licenses/>.
*
*/
/** library for 1-wire protocol as master (code)
* @ file onewire_slave . c
* @ author King Kévin < kingkevin @ cuvoodoo . info >
* @ date 2017
* @ note peripherals used : GPIO and timer @ ref onewire_slave_timer , GPIO @ ref onewire_slave_gpio
* @ note overdrive mode is not supported
* @ implements 1 - Wire protocol description from Book of iButton Standards
*/
/* standard libraries */
# include <stdint.h> // standard integer types
# include <stdbool.h> // boolean type
# include <stddef.h> // NULL definition
/* STM32 (including CM3) libraries */
# include <libopencmsis/core_cm3.h> // Cortex M3 utilities
# include <libopencm3/cm3/nvic.h> // interrupt handler
# include <libopencm3/stm32/rcc.h> // real-time control clock library
# include <libopencm3/stm32/gpio.h> // general purpose input output library
# include <libopencm3/stm32/timer.h> // timer library
# include <libopencm3/stm32/exti.h> // external interrupt library
/* own libraries */
# include "global.h" // help macros
# include "onewire_slave.h" // own definitions
/** @defgroup onewire_slave_timer timer used to measure 1-wire signal timing
* @ {
*/
# define ONEWIRE_SLAVE_TIMER 2 /**< timer ID */
/** @} */
/** @defgroup onewire_slave_gpio GPIO used for 1-wire signal
* @ warning ensure no same pin number on other parts are used for external interrupts
* @ note external pull - up resistor on pin is required ( < 5 kOhm ) , generally provided by the master
* @ {
*/
# define ONEWIRE_SLAVE_PORT A /**< GPIO port */
# define ONEWIRE_SLAVE_PIN 4 /**< GPIO pin */
/** @} */
/** state of 1-Wire communication */
static volatile enum {
ONEWIRE_STATE_IDLE , /**< no current communication */
ONEWIRE_STATE_RESET , /**< reset pulse has been detected */
ONEWIRE_STATE_WAIT_PRESENCE , /**< waiting before sending the presence pulse */
ONEWIRE_STATE_PULSE_PRESENCE , /**< sending the presence pulse */
ONEWIRE_STATE_ROM_COMMAND , /**< slave is reading ROM command bits */
ONEWIRE_STATE_ROM_READ , /**< slave is sending ROM code in response to ROM command READ ROM */
ONEWIRE_STATE_ROM_MATCH , /**< master is sending ROM code to select slave */
ONEWIRE_STATE_ROM_SEARCH_TRUE , /**< master is searching ROM code, slave will send first bit (not negated) */
ONEWIRE_STATE_ROM_SEARCH_FALSE , /**< master is searching ROM code, slave will send first bit (not negated) */
ONEWIRE_STATE_ROM_SEARCH_SELECT , /**< master is searching ROM code, slave will read selected bit */
ONEWIRE_STATE_FUNCTION_COMMAND , /**< slave is reading function command bits */
ONEWIRE_STATE_FUNCTION_DATA , /**< waiting for user to provide data to transfer */
ONEWIRE_STATE_FUNCTION_READ , /**< slave is reading bits */
ONEWIRE_STATE_FUNCTION_WRITE , /**< slave is writing bits */
ONEWIRE_MAX /** to count the number of possible states */
} onewire_slave_state = ONEWIRE_STATE_IDLE ;
static uint8_t onewire_slave_rom_code [ 8 ] = { 0 } ; /**< slave ROM code */
volatile bool onewire_slave_function_code_received = false ;
volatile uint8_t onewire_slave_function_code = 0 ;
volatile bool onewire_slave_transfer_complete = false ;
static volatile uint8_t bits_buffer = 0 ; /**< buffer for the incoming bits (up to one byte) */
static volatile uint32_t bits_bit = 0 ; /**< number of incoming bits */
static volatile uint8_t * onewire_slave_transfer_data = NULL ; /**< data to transfer (read or write) */
static volatile uint32_t onewire_slave_transfer_bits = 0 ; /**< number of bits to transfer */
/** compute CRC for 1-Wire
* @ note this CRC - 8 uses normal polynomial 0x31 , reverse polynomial 0x8C , start value 0x00
* @ param [ in ] data bytes on which to calculate CRC checksum on
* @ param [ in ] length number of bytes in data
* @ return computed CRC checksum
*/
static uint8_t onewire_slave_crc ( uint8_t * data , uint32_t length )
{
if ( NULL = = data | | 0 = = length ) { // check input
return 0 ; // wrong input
}
uint8_t crc = 0x00 ; // initial value
for ( uint8_t i = 0 ; i < length ; i + + ) { // go through every byte
crc ^ = data [ i ] ; // XOR byte
for ( uint8_t b = 0 ; b < 8 ; b + + ) { // go through every bit
if ( crc & 0x01 ) { // least significant bit is set (we are using the reverse way)
crc = ( crc > > 1 ) ^ 0x8C ; // // shift to the right (for the next bit) and XOR with (reverse) polynomial
} else {
crc > > = 1 ; // just shift right (for the next bit)
}
}
}
return crc ;
}
void onewire_slave_setup ( uint8_t family , uint64_t serial )
{
// save ROM code (LSB first)
onewire_slave_rom_code [ 0 ] = family ;
onewire_slave_rom_code [ 1 ] = serial > > 40 ;
onewire_slave_rom_code [ 2 ] = serial > > 32 ;
onewire_slave_rom_code [ 3 ] = serial > > 24 ;
onewire_slave_rom_code [ 4 ] = serial > > 16 ;
onewire_slave_rom_code [ 5 ] = serial > > 8 ;
onewire_slave_rom_code [ 6 ] = serial > > 0 ;
onewire_slave_rom_code [ 7 ] = onewire_slave_crc ( onewire_slave_rom_code , 7 ) ; // calculate CRC
// setup timer to generate/measure signal timing
rcc_periph_clock_enable ( RCC_TIM ( ONEWIRE_SLAVE_TIMER ) ) ; // enable clock for timer peripheral
timer_reset ( TIM ( ONEWIRE_SLAVE_TIMER ) ) ; // reset timer state
timer_set_mode ( TIM ( ONEWIRE_SLAVE_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
timer_set_prescaler ( TIM ( ONEWIRE_SLAVE_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 )
// use comparator to time signal (without using the output), starting at slot start
timer_set_period ( TIM ( ONEWIRE_SLAVE_TIMER ) , 480 * ( rcc_ahb_frequency / 1000000 ) - 1 - 1300 ) ; // minimum time needed for a reset pulse (480 < Trst), plus hand tuning
timer_set_oc_mode ( TIM ( ONEWIRE_SLAVE_TIMER ) , TIM_OC1 , TIM_OCM_FROZEN ) ;
timer_set_oc_value ( TIM ( ONEWIRE_SLAVE_TIMER ) , TIM_OC1 , 16 * ( rcc_ahb_frequency / 1000000 ) - 1 ) ; // time to wait before sending the presence pulse, after the rising edge of the reset pulse (15 < Tpdh < 60)
timer_set_oc_mode ( TIM ( ONEWIRE_SLAVE_TIMER ) , TIM_OC2 , TIM_OCM_FROZEN ) ;
timer_set_oc_value ( TIM ( ONEWIRE_SLAVE_TIMER ) , TIM_OC2 , 45 * ( rcc_ahb_frequency / 1000000 ) - 1 - 350 ) ; // time to sample the bit after being set (1 < Tlow1 < 15, 60 < Tslot < 120), or stop sending the bit use compare function to detect slave presence (15 = Trdv + 0 < Trelease < 45), plus hand tuning
timer_set_oc_value ( TIM ( ONEWIRE_SLAVE_TIMER ) , TIM_OC3 , 90 * ( rcc_ahb_frequency / 1000000 ) - 1 ) ; // time to stop the presence pulse (60 < Tpdl < 120)
2017-08-04 07:43:05 +02:00
timer_clear_flag ( TIM ( ONEWIRE_SLAVE_TIMER ) , TIM_SR_UIF | TIM_SR_CC1IF | TIM_SR_CC2IF | TIM_SR_CC3IF ) ; // clear all interrupt flags
2017-08-03 20:49:20 +02:00
timer_update_on_overflow ( TIM ( ONEWIRE_SLAVE_TIMER ) ) ; // only use counter overflow as UEV source (use overflow as start time or timeout)
timer_enable_irq ( TIM ( ONEWIRE_SLAVE_TIMER ) , TIM_DIER_UIE ) ; // enable update interrupt for overflow
nvic_enable_irq ( NVIC_TIM_IRQ ( ONEWIRE_SLAVE_TIMER ) ) ; // catch interrupt in service routine
onewire_slave_function_code_received = false ; // reset state
onewire_slave_state = ONEWIRE_STATE_IDLE ; // reset state
onewire_slave_transfer_complete = false ; // reset state
// setup GPIO with external interrupt
rcc_periph_clock_enable ( RCC_GPIO ( ONEWIRE_SLAVE_PORT ) ) ; // enable clock for GPIO peripheral
gpio_set ( GPIO ( ONEWIRE_SLAVE_PORT ) , GPIO ( ONEWIRE_SLAVE_PIN ) ) ; // idle is high (using pull-up resistor)
gpio_set_mode ( GPIO ( ONEWIRE_SLAVE_PORT ) , GPIO_MODE_OUTPUT_50_MHZ , GPIO_CNF_OUTPUT_OPENDRAIN , GPIO ( ONEWIRE_SLAVE_PIN ) ) ; // control output using open drain (this mode also allows to read the input signal)
rcc_periph_clock_enable ( RCC_AFIO ) ; // enable alternate function clock for external interrupt
exti_select_source ( EXTI ( ONEWIRE_SLAVE_PIN ) , GPIO ( ONEWIRE_SLAVE_PORT ) ) ; // mask external interrupt of this pin only for this port
exti_set_trigger ( EXTI ( ONEWIRE_SLAVE_PIN ) , EXTI_TRIGGER_BOTH ) ; // trigger on signal change
exti_enable_request ( EXTI ( ONEWIRE_SLAVE_PIN ) ) ; // enable external interrupt
nvic_enable_irq ( NVIC_EXTI_IRQ ( ONEWIRE_SLAVE_PIN ) ) ; // enable interrupt
}
2017-08-07 23:15:16 +02:00
bool onewire_slave_function_read ( uint8_t * data , size_t size )
2017-08-03 20:49:20 +02:00
{
2017-08-07 23:15:16 +02:00
if ( NULL = = data | | 0 = = size ) { // verify input
return false ;
}
if ( UINT32_MAX / 8 < size ) { // too many bits to transfer
return false ;
2017-08-03 20:49:20 +02:00
}
if ( onewire_slave_state ! = ONEWIRE_STATE_FUNCTION_DATA ) { // not in the right state to transfer data
2017-08-07 23:15:16 +02:00
return false ;
2017-08-03 20:49:20 +02:00
}
onewire_slave_transfer_data = data ; // save buffer to write to
2017-08-07 23:15:16 +02:00
onewire_slave_transfer_bits = size * 8 ; // number of bits to read
2017-08-03 20:49:20 +02:00
onewire_slave_transfer_complete = false ; // reset state
bits_bit = 0 ; // reset number of bits read
onewire_slave_state = ONEWIRE_STATE_FUNCTION_READ ; // read data
2017-08-07 23:15:16 +02:00
return true ;
2017-08-03 20:49:20 +02:00
}
2017-08-07 23:15:16 +02:00
bool onewire_slave_function_write ( const uint8_t * data , size_t size )
2017-08-03 20:49:20 +02:00
{
2017-08-07 23:15:16 +02:00
if ( NULL = = data | | 0 = = size ) { // verify input
return false ;
2017-08-03 20:49:20 +02:00
}
if ( onewire_slave_state ! = ONEWIRE_STATE_FUNCTION_DATA ) { // not in the right state to transfer data
2017-08-07 23:15:16 +02:00
return false ;
}
if ( UINT32_MAX / 8 < size ) { // too many bits to transfer
return false ;
2017-08-03 20:49:20 +02:00
}
2017-08-07 23:15:16 +02:00
onewire_slave_transfer_data = ( uint8_t * ) data ; // save buffer to read from
onewire_slave_transfer_bits = size * 8 ; // number of bits to write
2017-08-03 20:49:20 +02:00
onewire_slave_transfer_complete = false ; // reset state
bits_bit = 0 ; // reset number of bits written
bits_buffer = onewire_slave_transfer_data [ 0 ] ; // prepare byte to write
onewire_slave_state = ONEWIRE_STATE_FUNCTION_WRITE ; // write data
2017-08-07 23:15:16 +02:00
return true ;
2017-08-03 20:49:20 +02:00
}
/** interrupt service routine called when 1-Wire signal changes */
void EXTI_ISR ( ONEWIRE_SLAVE_PIN ) ( void )
{
exti_reset_request ( EXTI ( ONEWIRE_SLAVE_PIN ) ) ; // reset interrupt
if ( gpio_get ( GPIO ( ONEWIRE_SLAVE_PORT ) , GPIO ( ONEWIRE_SLAVE_PIN ) ) ) { // it's a rising edge
switch ( onewire_slave_state ) {
case ONEWIRE_STATE_RESET : // reset pulse has ended
timer_disable_counter ( TIM ( ONEWIRE_SLAVE_TIMER ) ) ; // stop timer for reconfiguration
timer_set_counter ( TIM ( ONEWIRE_SLAVE_TIMER ) , 0 ) ; // reset timer counter
timer_clear_flag ( TIM ( ONEWIRE_SLAVE_TIMER ) , TIM_SR_CC1IF ) ; // clear flag
timer_enable_irq ( TIM ( ONEWIRE_SLAVE_TIMER ) , TIM_DIER_CC1IE ) ; // enable compare interrupt for presence pulse
timer_enable_counter ( TIM ( ONEWIRE_SLAVE_TIMER ) ) ; // start timer to generate timing
onewire_slave_state = ONEWIRE_STATE_WAIT_PRESENCE ; // set new stated
break ;
case ONEWIRE_STATE_PULSE_PRESENCE : // we stopped sending the presence pulse
onewire_slave_state = ONEWIRE_STATE_ROM_COMMAND ; // we now expect a ROM command
bits_bit = 0 ; // reset buffer bit count
break ; // no need to stop the time, the reset will be checked correctly
default : // rising edge is not important is the other cases
break ; // nothing to do
}
} else { // it's a falling edge, the beginning of a new signal
timer_disable_counter ( TIM ( ONEWIRE_SLAVE_TIMER ) ) ; // stop timer for reconfiguration
timer_set_counter ( TIM ( ONEWIRE_SLAVE_TIMER ) , 0 ) ; // reset timer counter
2017-08-04 07:43:05 +02:00
timer_disable_irq ( TIM ( ONEWIRE_SLAVE_TIMER ) , TIM_DIER_CC1IE | TIM_DIER_CC2IE | TIM_DIER_CC3IE ) ; // disable all timers
2017-08-03 20:49:20 +02:00
switch ( onewire_slave_state ) {
case ONEWIRE_STATE_PULSE_PRESENCE : // we started sending the presence pulse
timer_enable_irq ( TIM ( ONEWIRE_SLAVE_TIMER ) , TIM_DIER_CC3IE ) ; // enable timer for end of pulse
break ;
case ONEWIRE_STATE_ROM_COMMAND : // read ROM command bits
case ONEWIRE_STATE_ROM_MATCH : // read ROM code bits
case ONEWIRE_STATE_FUNCTION_COMMAND : // read function command bits
case ONEWIRE_STATE_ROM_SEARCH_SELECT : // read selected ROM code bit
case ONEWIRE_STATE_FUNCTION_READ : // read function data bit
timer_enable_irq ( TIM ( ONEWIRE_SLAVE_TIMER ) , TIM_DIER_CC2IE ) ; // enable timer for reading bit
break ;
case ONEWIRE_STATE_ROM_READ : // send ROM code bit
case ONEWIRE_STATE_ROM_SEARCH_TRUE : // send ROM code bit while searching ROM, not negated
case ONEWIRE_STATE_ROM_SEARCH_FALSE : // send ROM code bit while searching ROM, already negated
case ONEWIRE_STATE_FUNCTION_WRITE : // write function data bit
timer_enable_irq ( TIM ( ONEWIRE_SLAVE_TIMER ) , TIM_DIER_CC2IE ) ; // enable timer for reading bit
if ( 0 = = ( bits_buffer & ( 1 < < ( bits_bit % 8 ) ) ) ) { // need to send a 0 bit
gpio_clear ( GPIO ( ONEWIRE_SLAVE_PORT ) , GPIO ( ONEWIRE_SLAVE_PIN ) ) ; // hold low to send 0 bit
}
break ;
case ONEWIRE_STATE_IDLE : // we only expect a reset
default : // we don't expect any falling edge in other states
onewire_slave_state = ONEWIRE_STATE_IDLE ; // unexpected signal, reset to idle state
break ; // the timer overflow will confirm detect reset pulses
}
2017-08-04 07:43:05 +02:00
timer_clear_flag ( TIM ( ONEWIRE_SLAVE_TIMER ) , TIM_SR_UIF | TIM_SR_CC1IF | TIM_SR_CC2IF | TIM_SR_CC3IF ) ; // clear all flags
2017-08-03 20:49:20 +02:00
timer_enable_counter ( TIM ( ONEWIRE_SLAVE_TIMER ) ) ; // start timer to measure the configured timeouts
}
}
/** interrupt service routine called for timer */
void TIM_ISR ( ONEWIRE_SLAVE_TIMER ) ( void )
{
if ( timer_interrupt_source ( TIM ( ONEWIRE_SLAVE_TIMER ) , TIM_SR_UIF ) ) { // reset timer triggered, verify if it's a reset
if ( 0 = = gpio_get ( GPIO ( ONEWIRE_SLAVE_PORT ) , GPIO ( ONEWIRE_SLAVE_PIN ) ) ) { // signal it still low, thus it must be a reset
onewire_slave_state = ONEWIRE_STATE_RESET ; // update state
}
timer_disable_counter ( TIM ( ONEWIRE_SLAVE_TIMER ) ) ; // stop timer since there is nothing more to measure
2017-08-04 07:43:05 +02:00
timer_disable_irq ( TIM ( ONEWIRE_SLAVE_TIMER ) , TIM_DIER_CC1IE | TIM_DIER_CC2IE | TIM_DIER_CC3IE ) ; // disable all timers
timer_clear_flag ( TIM ( ONEWIRE_SLAVE_TIMER ) , TIM_SR_UIF | TIM_SR_CC1IF | TIM_SR_CC2IF | TIM_SR_CC3IF ) ; // clear all flag (I have no idea why the others are get too, even when the interrupt is not enabled)
2017-08-03 20:49:20 +02:00
}
if ( timer_interrupt_source ( TIM ( ONEWIRE_SLAVE_TIMER ) , TIM_SR_CC1IF ) ) { // wait for presence pulse timer triggered
timer_clear_flag ( TIM ( ONEWIRE_SLAVE_TIMER ) , TIM_SR_CC1IF ) ; // clear flag
if ( ONEWIRE_STATE_WAIT_PRESENCE = = onewire_slave_state ) { // we can now send the pulse
onewire_slave_state = ONEWIRE_STATE_PULSE_PRESENCE ; // save new state
gpio_clear ( GPIO ( ONEWIRE_SLAVE_PORT ) , GPIO ( ONEWIRE_SLAVE_PIN ) ) ; // send presence pulse (will also trigger the timer start)
}
}
if ( timer_interrupt_source ( TIM ( ONEWIRE_SLAVE_TIMER ) , TIM_SR_CC2IF ) ) { // time to read the bit, or stop writing it
// read/write bit depending on bit
switch ( onewire_slave_state ) {
case ONEWIRE_STATE_ROM_COMMAND : // read ROM command code bit
case ONEWIRE_STATE_ROM_MATCH : // read ROM code
case ONEWIRE_STATE_FUNCTION_COMMAND : // read function command code bit
case ONEWIRE_STATE_ROM_SEARCH_SELECT : // read selected ROM code bit
case ONEWIRE_STATE_FUNCTION_READ : // read function data bit
if ( gpio_get ( GPIO ( ONEWIRE_SLAVE_PORT ) , GPIO ( ONEWIRE_SLAVE_PIN ) ) ) { // bit is set to 1
bits_buffer | = ( 1 < < ( bits_bit % 8 ) ) ; // set bit
} else { // bit is set to 0
bits_buffer & = ~ ( 1 < < ( bits_bit % 8 ) ) ; // clear bit
}
bits_bit + + ; // go to next bit
break ;
case ONEWIRE_STATE_ROM_READ : // write ROM code
case ONEWIRE_STATE_FUNCTION_WRITE : // write function data bit
gpio_set ( GPIO ( ONEWIRE_SLAVE_PORT ) , GPIO ( ONEWIRE_SLAVE_PIN ) ) ; // stop sending bit
bits_bit + + ; // go to next bit
break ;
case ONEWIRE_STATE_ROM_SEARCH_TRUE : // ROM code bit is sent
case ONEWIRE_STATE_ROM_SEARCH_FALSE : // ROM code bit is sent
gpio_set ( GPIO ( ONEWIRE_SLAVE_PORT ) , GPIO ( ONEWIRE_SLAVE_PIN ) ) ; // stop sending bit
break ;
default : // these states don't need read/write
break ;
}
static uint8_t rom_code_byte ; // which byte of the ROM code is processed
// act on bit count
switch ( onewire_slave_state ) {
case ONEWIRE_STATE_ROM_COMMAND : // read ROM command
if ( bits_bit > 7 ) { // complete ROM command code received
bits_bit = 0 ; // reset buffer
rom_code_byte = 0 ; // reset ROM code byte index
switch ( bits_buffer ) { // act depending on ROM command code
case 0x33 : // READ ROM
bits_buffer = onewire_slave_rom_code [ rom_code_byte ] ; // prepare to send the first byte
onewire_slave_state = ONEWIRE_STATE_ROM_READ ; // write ROM code
break ;
case 0xcc : // SKIP ROM
onewire_slave_state = ONEWIRE_STATE_FUNCTION_COMMAND ; // now read function command code
break ;
case 0x55 : // MATCH ROM
onewire_slave_state = ONEWIRE_STATE_ROM_MATCH ; // read ROM code
break ;
case 0xf0 : // SEARCH ROM
bits_buffer = onewire_slave_rom_code [ rom_code_byte ] ; // prepare to search code
onewire_slave_state = ONEWIRE_STATE_ROM_SEARCH_TRUE ; // prepare to start sending first new bit
break ;
default : // unknown ROM code
onewire_slave_state = ONEWIRE_STATE_IDLE ; // go back to default idle state
break ;
}
}
break ;
case ONEWIRE_STATE_ROM_READ : // send ROM code
if ( bits_bit > 7 ) { // complete byte transmitted
rom_code_byte + + ; // go to next ROM code byte
if ( rom_code_byte > LENGTH ( onewire_slave_rom_code ) ) { // complete ROM code send
onewire_slave_state = ONEWIRE_STATE_IDLE ; // go back to default idle state
} else {
bits_bit = 0 ; // reset buffer
bits_buffer = onewire_slave_rom_code [ rom_code_byte ] ; // send next ROM code byte
}
}
break ;
case ONEWIRE_STATE_ROM_MATCH : // compare ROM code
if ( bits_bit > 7 ) { // complete byte received
if ( bits_buffer = = onewire_slave_rom_code [ rom_code_byte ] ) { // ROM code byte matches
bits_bit = 0 ; // reset buffer
rom_code_byte + + ; // go to next ROM code byte
if ( rom_code_byte > = LENGTH ( onewire_slave_rom_code ) ) { // complete ROM code matches
onewire_slave_state = ONEWIRE_STATE_FUNCTION_COMMAND ; // now read function command code
}
} else { // ROM code does not match
onewire_slave_state = ONEWIRE_STATE_IDLE ; // stop comparing and go back to idle
}
}
break ;
case ONEWIRE_STATE_ROM_SEARCH_TRUE : // ROM code bit is send, prepare to send negated version
bits_buffer ^ = ( 1 < < bits_bit ) ; // negate bit
onewire_slave_state = ONEWIRE_STATE_ROM_SEARCH_FALSE ; // send negated version
break ;
case ONEWIRE_STATE_ROM_SEARCH_FALSE : // negated ROM code bit is send, prepare to read selected bit
onewire_slave_state = ONEWIRE_STATE_ROM_SEARCH_SELECT ; // read selected
break ;
case ONEWIRE_STATE_ROM_SEARCH_SELECT : // check if we are selected
if ( ( bits_buffer & ( 1 < < ( bits_bit - 1 ) ) ) = = ( onewire_slave_rom_code [ rom_code_byte ] & ( 1 < < ( bits_bit - 1 ) ) ) ) { // we have been selected
onewire_slave_state = ONEWIRE_STATE_ROM_SEARCH_TRUE ; // prepare to compare next bit
} else { // we are no selected
onewire_slave_state = ONEWIRE_STATE_IDLE ; // go back to idle
}
if ( bits_bit > 7 ) { // complete byte searched
bits_bit = 0 ; // reset buffer
rom_code_byte + + ; // go to next ROM code byte
if ( rom_code_byte > = LENGTH ( onewire_slave_rom_code ) ) { // complete ROM code search
onewire_slave_state = ONEWIRE_STATE_FUNCTION_COMMAND ; // now read function command code
} else {
bits_buffer = onewire_slave_rom_code [ rom_code_byte ] ; // prepare next ROM code byte
}
}
break ;
case ONEWIRE_STATE_FUNCTION_COMMAND : // read function command
if ( bits_bit > 7 ) { // complete function command code received
onewire_slave_function_code = bits_buffer ; // save function command code to user buffer
onewire_slave_state = ONEWIRE_STATE_FUNCTION_DATA ; // let the user transfer data
onewire_slave_function_code_received = true ; // notify user
}
break ;
case ONEWIRE_STATE_FUNCTION_READ : // save function data bit
if ( 0 = = bits_bit % 8 ) { // complete byte received
onewire_slave_transfer_data [ ( bits_bit - 1 ) / 8 ] = bits_buffer ; // save received bytes
}
if ( bits_bit > = onewire_slave_transfer_bits ) { // read transfer complete
onewire_slave_transfer_data [ ( bits_bit - 1 ) / 8 ] = bits_buffer ; // save last bits
onewire_slave_state = ONEWIRE_STATE_FUNCTION_DATA ; // let the user transfer more data
onewire_slave_transfer_complete = true ; // notify user
}
break ;
case ONEWIRE_STATE_FUNCTION_WRITE : // update function data bit to write
if ( 0 = = bits_bit % 8 ) { // complete byte transfer
bits_buffer = onewire_slave_transfer_data [ bits_bit / 8 ] ; // prepare next byte to write
}
if ( bits_bit > = onewire_slave_transfer_bits ) { // write transfer complete
onewire_slave_state = ONEWIRE_STATE_FUNCTION_DATA ; // let the user transfer more data
onewire_slave_transfer_complete = true ; // notify user
}
break ;
default : // no action needed
break ;
}
timer_clear_flag ( TIM ( ONEWIRE_SLAVE_TIMER ) , TIM_SR_CC2IF ) ; // clear flag
}
if ( timer_interrupt_source ( TIM ( ONEWIRE_SLAVE_TIMER ) , TIM_SR_CC3IF ) ) { // end of presence pulse timer triggered
timer_clear_flag ( TIM ( ONEWIRE_SLAVE_TIMER ) , TIM_SR_CC3IF ) ; // clear flag
if ( ONEWIRE_STATE_PULSE_PRESENCE = = onewire_slave_state ) {
gpio_set ( GPIO ( ONEWIRE_SLAVE_PORT ) , GPIO ( ONEWIRE_SLAVE_PIN ) ) ; // stop sending presence pulse
// if the pin stays low the reset timer will catch it
}
}
}