From 444534e214081e1179d49d63742597aa70a6a826 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?King=20K=C3=A9vin?= Date: Wed, 9 May 2018 21:27:00 +0200 Subject: [PATCH] 1-Wire: remove misleading parasitic power function, add byte function --- lib/onewire_master.c | 119 ++++++++++++++++++++----------------------- lib/onewire_master.h | 32 +++++++++--- 2 files changed, 81 insertions(+), 70 deletions(-) diff --git a/lib/onewire_master.c b/lib/onewire_master.c index e307091..a0b962b 100644 --- a/lib/onewire_master.c +++ b/lib/onewire_master.c @@ -15,7 +15,7 @@ /** library for 1-wire protocol as master (code) * @file onewire_master.c * @author King Kévin - * @date 2017 + * @date 2017-2018 * @note peripherals used: timer @ref onewire_master_timer, GPIO @ref onewire_master_gpio * @note overdrive mode is not provided * @implements 1-Wire protocol description from Book of iButton Standards @@ -43,14 +43,6 @@ #define ONEWIRE_MASTER_TIMER 2 /**< timer ID */ /** @} */ -/** @defgroup onewire_master_gpio GPIO used for 1-wire signal - * @note external pull-up resistor on pin is required (< 5 kOhm) - * @{ - */ -#define ONEWIRE_MASTER_PORT A /**< GPIO port */ -#define ONEWIRE_MASTER_PIN 4 /**< GPIO pin */ -/** @} */ - /** state of 1-Wire communication */ volatile enum { ONEWIRE_STATE_IDLE, /**< no current communication */ @@ -67,43 +59,30 @@ static volatile bool slave_presence = false; /**< if slaves have been detected * static uint8_t* buffer = NULL; /**< input/output buffer for read/write commands/functions */ static uint32_t buffer_size = 0; /**< size of buffer in bits */ static volatile uint32_t buffer_bit = 0; /**< number of bits read/written */ -static bool onewire_master_parasite = false; /**< if parasite power should be provided whenever the is no communication */ -static uint16_t onewire_master_recovery = 0; /**< the recovery time in us (1 < Trec) */ -void onewire_master_setup(bool parasite, uint16_t recovery) +void onewire_master_setup(void) { // setup GPIO with external interrupt rcc_periph_clock_enable(RCC_GPIO(ONEWIRE_MASTER_PORT)); // enable clock for GPIO peripheral gpio_set(GPIO(ONEWIRE_MASTER_PORT),GPIO(ONEWIRE_MASTER_PIN)); // idle is high (using pull-up resistor) - onewire_master_parasite = parasite; // save if we should provide parasite power - // setup GPIO pin as output (master starts communication before slave replies) - if (onewire_master_parasite) { - gpio_set_mode(GPIO(ONEWIRE_MASTER_PORT), GPIO_MODE_OUTPUT_50_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, GPIO(ONEWIRE_MASTER_PIN)); // provide parasite power (external pull-up resistor is still require for communication) - } else { - 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) - } + 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) // setup timer to generate/measure signal timing rcc_periph_clock_enable(RCC_TIM(ONEWIRE_MASTER_TIMER)); // enable clock for timer peripheral timer_reset(TIM(ONEWIRE_MASTER_TIMER)); // reset timer state + timer_disable_counter(TIM(ONEWIRE_MASTER_TIMER)); // disable timer to configure it 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 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 ) // use comparator to time signal (without using the output), starting at slot start + timer_clear_flag(TIM(ONEWIRE_MASTER_TIMER), TIM_SR_CC1IF); // clear flag 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) + timer_clear_flag(TIM(ONEWIRE_MASTER_TIMER), TIM_SR_CC2IF); // clear flag 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) + timer_clear_flag(TIM(ONEWIRE_MASTER_TIMER), TIM_SR_CC3IF); // clear flag 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) - 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 tunig - onewire_master_recovery = 5; // set minimum recovery time - if (recovery>onewire_master_recovery) { - onewire_master_recovery = recovery; // save desired recovery time - } - if (UINT16_MAX/onewire_master_recovery<(rcc_ahb_frequency/1000000)) { // catch integer overflow - onewire_master_recovery = UINT16_MAX; // save maximum value - } else { - onewire_master_recovery *= (rcc_ahb_frequency/1000000); // save actual recovery time value - } - + timer_clear_flag(TIM(ONEWIRE_MASTER_TIMER), TIM_SR_CC4IF); // clear flag + 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 timer_clear_flag(TIM(ONEWIRE_MASTER_TIMER), TIM_SR_UIF); // clear update (overflow) flag timer_update_on_overflow(TIM(ONEWIRE_MASTER_TIMER)); // only use counter overflow as UEV source (use overflow as start time or timeout) timer_enable_irq(TIM(ONEWIRE_MASTER_TIMER), TIM_DIER_UIE); // enable update interrupt for overflow @@ -113,6 +92,17 @@ void onewire_master_setup(bool parasite, uint16_t recovery) onewire_master_state = ONEWIRE_STATE_IDLE; // reset state } +void onewire_master_release(void) +{ + // release timer + timer_disable_counter(TIM(ONEWIRE_MASTER_TIMER)); // disable timer + timer_reset(TIM(ONEWIRE_MASTER_TIMER)); // reset timer state + rcc_periph_clock_disable(RCC_TIM(ONEWIRE_MASTER_TIMER)); // disable clock for timer peripheral + + // release GPIO + gpio_set_mode(GPIO(ONEWIRE_MASTER_PORT), GPIO_MODE_INPUT, GPIO_CNF_INPUT_FLOAT, GPIO(ONEWIRE_MASTER_PIN)); // put back to input floating +} + bool onewire_master_reset(void) { // prepare timer @@ -148,14 +138,8 @@ static bool onewire_master_write(void) // prepare timer timer_disable_counter(TIM(ONEWIRE_MASTER_TIMER)); // disable timer to reconfigure it - timer_set_counter(TIM(ONEWIRE_MASTER_TIMER),0); // reset counter - uint16_t timeout = TIM_CCR3(TIM(ONEWIRE_MASTER_TIMER)); // time until new slot (= end of slot+recovery) - if (UINT16_MAX-timeout1, after time slot end and recovery time) + timer_set_counter(TIM(ONEWIRE_MASTER_TIMER), 0); // reset counter + 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 ) timer_clear_flag(TIM(ONEWIRE_MASTER_TIMER), TIM_SR_CC2IF); // clear output compare flag timer_enable_irq(TIM(ONEWIRE_MASTER_TIMER), TIM_DIER_CC2IE); // enable compare interrupt for bit setting timer_clear_flag(TIM(ONEWIRE_MASTER_TIMER), TIM_SR_CC3IF); // clear output compare flag @@ -188,14 +172,8 @@ static bool onewire_master_read(void) // prepare timer timer_disable_counter(TIM(ONEWIRE_MASTER_TIMER)); // disable timer to reconfigure it - timer_set_counter(TIM(ONEWIRE_MASTER_TIMER),0); // reset counter - uint16_t timeout = TIM_CCR3(TIM(ONEWIRE_MASTER_TIMER)); // time until new slot (= end of slot+recovery) - if (UINT16_MAX-timeout1, after time slot end and recovery time) + timer_set_counter(TIM(ONEWIRE_MASTER_TIMER), 0); // reset counter + 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 ) timer_clear_flag(TIM(ONEWIRE_MASTER_TIMER), TIM_SR_CC1IF); // clear output compare flag timer_enable_irq(TIM(ONEWIRE_MASTER_TIMER), TIM_DIER_CC1IE); // enable compare interrupt for stop pulling low timer_clear_flag(TIM(ONEWIRE_MASTER_TIMER), TIM_SR_CC2IF); // clear output compare flag @@ -221,7 +199,7 @@ uint8_t onewire_master_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>bit); // set bit to send + buffer[0] = ((*code)>>bit); // set bit to send if (!onewire_master_write()) { // send bit goto end; // an error has occurred } @@ -354,7 +354,7 @@ bool onewire_master_rom_search(uint64_t* code, bool alarm) // verify ROM code uint8_t rom_code[8] = {0}; // to store ROM code for (uint8_t i=0; i>(8*i); // split and save last code in ROM code + rom_code[i] = (*code)>>(8*i); // split and save last code in ROM code } if (onewire_master_crc(rom_code, LENGTH(rom_code))) { // verify checksum *code = 0; // return the last code found since it's valid @@ -389,7 +389,6 @@ bool onewire_master_rom_match(uint64_t code) return true; } - /** interrupt service routine called for timer */ void TIM_ISR(ONEWIRE_MASTER_TIMER)(void) { @@ -428,11 +427,6 @@ void TIM_ISR(ONEWIRE_MASTER_TIMER)(void) gpio_set(GPIO(ONEWIRE_MASTER_PORT),GPIO(ONEWIRE_MASTER_PIN)); // pull signal high (idle state) onewire_master_state = ONEWIRE_STATE_ERROR; // indicate error } - if (onewire_master_parasite && (ONEWIRE_STATE_ERROR==onewire_master_state || ONEWIRE_STATE_DONE==onewire_master_state)) { - gpio_set_mode(GPIO(ONEWIRE_MASTER_PORT), GPIO_MODE_OUTPUT_50_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, GPIO(ONEWIRE_MASTER_PIN)); // provide parasite power - } else { - 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) - } } else if (timer_get_flag(TIM(ONEWIRE_MASTER_TIMER), TIM_SR_CC1IF)) { // compare event happened for master pull low end for read timer_clear_flag(TIM(ONEWIRE_MASTER_TIMER), TIM_SR_CC1IF); // clear flag switch (onewire_master_state) { @@ -475,9 +469,6 @@ void TIM_ISR(ONEWIRE_MASTER_TIMER)(void) } else if (timer_get_flag(TIM(ONEWIRE_MASTER_TIMER), TIM_SR_CC3IF)) { // compare event happened for end to time slot timer_clear_flag(TIM(ONEWIRE_MASTER_TIMER), TIM_SR_CC3IF); // clear flag gpio_set(GPIO(ONEWIRE_MASTER_PORT),GPIO(ONEWIRE_MASTER_PIN)); // pull signal high to end time slot - if (onewire_master_parasite) { // provide power during recovery time - gpio_set_mode(GPIO(ONEWIRE_MASTER_PORT), GPIO_MODE_OUTPUT_50_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, GPIO(ONEWIRE_MASTER_PIN)); // provide parasite power - } } else if (timer_get_flag(TIM(ONEWIRE_MASTER_TIMER), TIM_SR_CC4IF)) { // compare event happened for slave presence detection timer_clear_flag(TIM(ONEWIRE_MASTER_TIMER), TIM_SR_CC4IF); // clear flag if (gpio_get(GPIO(ONEWIRE_MASTER_PORT),GPIO(ONEWIRE_MASTER_PIN))) { // check is a slave let its presence know by pulling low diff --git a/lib/onewire_master.h b/lib/onewire_master.h index 7fc6266..3f740a3 100644 --- a/lib/onewire_master.h +++ b/lib/onewire_master.h @@ -15,18 +15,26 @@ /** library for 1-wire protocol as master (API) * @file onewire_master.h * @author King Kévin - * @date 2017 + * @date 2017-2018 * @note peripherals used: timer @ref onewire_master_timer, GPIO @ref onewire_master_gpio * @note overdrive mode is not provided */ #pragma once -/** setup 1-wire peripheral - * @param[in] parasite enable parasite power (provide power over 1-Wire line when not communicating) - * @warning multiple masters and interrupts are prevented when parasite power is used - * @param[in] recovery recovery time in us between timeslot, e.g. to ensure enough parasite power is provided (0 if not required) +/** @defgroup onewire_master_gpio GPIO used for 1-wire signal + * @note external pull-up resistor on pin is required (< 5 kOhm) + * @{ */ -void onewire_master_setup(bool parasite, uint16_t recovery); +#define ONEWIRE_MASTER_PORT C /**< GPIO port */ +#define ONEWIRE_MASTER_PIN 9 /**< GPIO pin */ +/** @} */ + +/** setup 1-wire peripheral + */ +void onewire_master_setup(void); +/** release 1-wire peripheral + */ +void onewire_master_release(void); /** send reset pulse * @return if slaves have indicated their presence */ @@ -62,6 +70,18 @@ bool onewire_master_rom_skip(void); * @return if operation succeeded */ bool onewire_master_rom_match(uint64_t code); +/** read data byte + * @note it is up to the user to send the reset pulse + * @param[out] data buffer to save data read + * @return if operation succeeded + */ +bool onewire_master_read_byte(uint8_t* data); +/** write data byte + * @note it is up to the user to send the reset pulse + * @param[in] data byte to write + * @return if operation succeeded + */ +bool onewire_master_write_byte(uint8_t data); /** issue function and read data * @note user needs to send a ROM command before * @param[in] function function command to send