diff --git a/lib/onewire_slave.c b/lib/onewire_slave.c new file mode 100644 index 0000000..039423b --- /dev/null +++ b/lib/onewire_slave.c @@ -0,0 +1,418 @@ +/* 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 . + * + */ +/** library for 1-wire protocol as master (code) + * @file onewire_slave.c + * @author King Kévin + * @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 // standard integer types +#include // boolean type +#include // NULL definition + +/* STM32 (including CM3) libraries */ +#include // Cortex M3 utilities +#include // interrupt handler +#include // real-time control clock library +#include // general purpose input output library +#include // timer library +#include // 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>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) + timer_set_oc_value(TIM(ONEWIRE_SLAVE_TIMER), TIM_OC4, 121*(rcc_ahb_frequency/1000000)-1); // time end of slot (60 < Tslot < 120) + timer_clear_flag(TIM(ONEWIRE_SLAVE_TIMER), TIM_SR_UIF | TIM_SR_CC1IF | TIM_SR_CC2IF | TIM_SR_CC3IF | TIM_SR_CC4IF); // clear all interrupt flags + 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 + +#define TIMDBG_PORT B +#define TIMDBG_PIN1 12 +#define TIMDBG_PIN2 13 +#define TIMDBG_PIN3 14 +#define TIMDBG_PIN4 15 +rcc_periph_clock_enable(RCC_GPIO(TIMDBG_PORT)); +gpio_set_mode(GPIO(TIMDBG_PORT), GPIO_MODE_OUTPUT_50_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, GPIO(TIMDBG_PIN1) | GPIO(TIMDBG_PIN2) | GPIO(TIMDBG_PIN3) | GPIO(TIMDBG_PIN4)); + + // 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 +} + +void onewire_slave_function_read(uint8_t* data, uint32_t bits) +{ + if (NULL==data || 0==bits) { // verify input + return; + } + if (onewire_slave_state!=ONEWIRE_STATE_FUNCTION_DATA) { // not in the right state to transfer data + return; + } + onewire_slave_transfer_data = data; // save buffer to write to + onewire_slave_transfer_bits = bits; // number of bits to read + onewire_slave_transfer_complete = false; // reset state + bits_bit = 0; // reset number of bits read + onewire_slave_state = ONEWIRE_STATE_FUNCTION_READ; // read data +} + +void onewire_slave_function_write(uint8_t* data, uint32_t bits) +{ + if (NULL==data || 0==bits) { // verify input + return; + } + if (onewire_slave_state!=ONEWIRE_STATE_FUNCTION_DATA) { // not in the right state to transfer data + return; + } + onewire_slave_transfer_data = data; // save buffer to read from + onewire_slave_transfer_bits = bits; // number of bits to write + 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 +} + +/** 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 + timer_disable_irq(TIM(ONEWIRE_SLAVE_TIMER), TIM_DIER_CC1IE | TIM_DIER_CC2IE | TIM_DIER_CC3IE | TIM_DIER_CC4IE); // disable all timers + 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 + } + timer_clear_flag(TIM(ONEWIRE_SLAVE_TIMER), TIM_SR_UIF | TIM_SR_CC1IF | TIM_SR_CC2IF | TIM_SR_CC3IF | TIM_SR_CC4IF); // clear all flags + 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 +gpio_toggle(GPIO(TIMDBG_PORT), GPIO(TIMDBG_PIN1) | GPIO(TIMDBG_PIN2) | GPIO(TIMDBG_PIN3) | GPIO(TIMDBG_PIN4)); + 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 + timer_disable_irq(TIM(ONEWIRE_SLAVE_TIMER), TIM_DIER_CC1IE | TIM_DIER_CC2IE | TIM_DIER_CC3IE | TIM_DIER_CC4IE); // disable all timers + timer_clear_flag(TIM(ONEWIRE_SLAVE_TIMER), TIM_SR_UIF | TIM_SR_CC1IF | TIM_SR_CC2IF | TIM_SR_CC3IF | TIM_SR_CC4IF); // clear all flag (I have no idea why the others are get too, even when the interrupt is not enabled) + } + if (timer_interrupt_source(TIM(ONEWIRE_SLAVE_TIMER), TIM_SR_CC1IF)) { // wait for presence pulse timer triggered +gpio_toggle(GPIO(TIMDBG_PORT), GPIO(TIMDBG_PIN1)); + 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 +gpio_toggle(GPIO(TIMDBG_PORT), GPIO(TIMDBG_PIN2)); + 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<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 +gpio_toggle(GPIO(TIMDBG_PORT), GPIO(TIMDBG_PIN3)); + 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 + } + } + if (timer_get_flag(TIM(ONEWIRE_SLAVE_TIMER), TIM_SR_CC4IF)) { // end of slot timer triggered (not used) +gpio_toggle(GPIO(TIMDBG_PORT), GPIO(TIMDBG_PIN4)); + timer_clear_flag(TIM(ONEWIRE_SLAVE_TIMER), TIM_SR_CC4IF); // clear flag + } +} diff --git a/lib/onewire_slave.h b/lib/onewire_slave.h new file mode 100644 index 0000000..0fe9d32 --- /dev/null +++ b/lib/onewire_slave.h @@ -0,0 +1,51 @@ +/* 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 . + * + */ +/** library for 1-wire protocol as slave (API) + * @file onewire_slave.h + * @author King Kévin + * @date 2017 + * @note peripherals used: timer @ref onewire_slave_timer, GPIO @ref onewire_slave_gpio + * @note overdrive mode is not supported + */ +#pragma once + +/** set when a function command code has been received + * @note needs to be cleared by user + */ +extern volatile bool onewire_slave_function_code_received; +/** last function command code received */ +extern volatile uint8_t onewire_slave_function_code; +/** set when data read/write transfer has been completed + * @note needs to be cleared by user + */ +extern volatile bool onewire_slave_transfer_complete; + +/** setup 1-wire peripheral + * @param[in] family family code for slave ROM code (8 bits) + * @param[in] serial serial number for slave ROM code (48 bits) + */ +void onewire_slave_setup(uint8_t family, uint64_t serial); +/** read data from master + * @param[out] data buffer to save read bits + * @param[in] bits number of bits to read + * @note onewire_slave_transfer_complete is set when transfer is completed + */ +void onewire_slave_function_read(uint8_t* data, uint32_t bits); +/** write data to master + * @param[in] data data to write + * @param[in] bits number of bits to write + * @note onewire_slave_transfer_complete is set when transfer is completed + */ +void onewire_slave_function_write(uint8_t* data, uint32_t bits);