|
|
|
@ -2,7 +2,7 @@
|
|
|
|
|
* @file
|
|
|
|
|
* @author King Kévin <kingkevin@cuvoodoo.info>
|
|
|
|
|
* @copyright SPDX-License-Identifier: GPL-3.0-or-later
|
|
|
|
|
* @date 2017-2020
|
|
|
|
|
* @date 2017-2022
|
|
|
|
|
* @note peripherals used: GPIO @ref led_tm1637_gpio, timer @ref led_tm1637_timer
|
|
|
|
|
* @note the protocol is very similar to I2C but incompatible for the following reasons: the capacitance is too large for open-drain type output with weak pull-up resistors (push-pull needs to be used, preventing to get ACKs since no indication of the ACK timing is provided); the devices doesn't use addresses; the STM32 I2C will switch to receiver mode when the first sent byte (the I2C address) has last bit set to 1 (such as for address commands with B7=1 where B7 is transmitted last), preventing to send further bytes (the data byte after the address)
|
|
|
|
|
* @warning all calls are blocking
|
|
|
|
@ -173,18 +173,20 @@ void led_tm1637_setup(bool updown)
|
|
|
|
|
// configure GPIO for CLK and DIO signals
|
|
|
|
|
rcc_periph_clock_enable(GPIO_RCC(LED_TM1637_CLK_PIN)); // enable clock for GPIO peripheral
|
|
|
|
|
gpio_set(GPIO_PORT(LED_TM1637_CLK_PIN), GPIO_PIN(LED_TM1637_CLK_PIN)); // idle high
|
|
|
|
|
gpio_set_mode(GPIO_PORT(LED_TM1637_CLK_PIN), GPIO_MODE_OUTPUT_10_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, GPIO_PIN(LED_TM1637_CLK_PIN)); // master start the communication (capacitance is to large for open drain), only switch to input for ack from slave
|
|
|
|
|
gpio_set_output_options(GPIO_PORT(LED_TM1637_CLK_PIN), GPIO_OTYPE_PP, GPIO_OSPEED_2MHZ, GPIO_PIN(LED_TM1637_CLK_PIN)); // set pin output as push-pull (capacitance is to large for open drain)
|
|
|
|
|
gpio_mode_setup(GPIO_PORT(LED_TM1637_CLK_PIN), GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO_PIN(LED_TM1637_CLK_PIN)); // set pin as output, master start the communication
|
|
|
|
|
rcc_periph_clock_enable(GPIO_RCC(LED_TM1637_DIO_PIN)); // enable clock for GPIO peripheral
|
|
|
|
|
gpio_set(GPIO_PORT(LED_TM1637_DIO_PIN), GPIO_PIN(LED_TM1637_DIO_PIN)); // idle high
|
|
|
|
|
gpio_set_mode(GPIO_PORT(LED_TM1637_DIO_PIN), GPIO_MODE_OUTPUT_10_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, GPIO_PIN(LED_TM1637_DIO_PIN)); // master start the communication (capacitance is to large for open drain), only switch to input for ack from slave
|
|
|
|
|
gpio_set_output_options(GPIO_PORT(LED_TM1637_DIO_PIN), GPIO_OTYPE_PP, GPIO_OSPEED_2MHZ, GPIO_PIN(LED_TM1637_DIO_PIN)); // set pin output as push-pull (capacitance is to large for open drain)
|
|
|
|
|
gpio_mode_setup(GPIO_PORT(LED_TM1637_DIO_PIN), GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO_PIN(LED_TM1637_DIO_PIN)); // set pin as output, only switch to input for ack from slave
|
|
|
|
|
// first clock then data high also stands for stop condition
|
|
|
|
|
|
|
|
|
|
// setup timer to create signal timing (each tick is used for a single GPIO transition)
|
|
|
|
|
rcc_periph_clock_enable(RCC_TIM(LED_TM1637_TIMER)); // enable clock for timer block
|
|
|
|
|
rcc_periph_reset_pulse(RST_TIM(LED_TM1637_TIMER)); // reset timer state
|
|
|
|
|
timer_set_mode(TIM(LED_TM1637_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(LED_TM1637_TIMER), 0); // don't prescale to get most precise timing ( 1/(72E6/1/(2**16))=0.91 ms > 0.5 us )
|
|
|
|
|
timer_set_period(TIM(LED_TM1637_TIMER), 500); // set the clock frequency (empirical value until the signal starts to look bad)
|
|
|
|
|
timer_set_prescaler(TIM(LED_TM1637_TIMER), 0); // don't prescale to get most precise timing ( 1/(72E6/1/(2**16))=0.78 us > 0.5 us )
|
|
|
|
|
timer_set_period(TIM(LED_TM1637_TIMER), 600); // set the clock frequency (empirical value until the signal starts to look bad)
|
|
|
|
|
timer_clear_flag(TIM(LED_TM1637_TIMER), TIM_SR_UIF); // clear flag
|
|
|
|
|
timer_update_on_overflow(TIM(LED_TM1637_TIMER)); // only use counter overflow as UEV source (use overflow as start time or timeout)
|
|
|
|
|
}
|
|
|
|
@ -235,7 +237,7 @@ static bool led_tm1637_write(const uint8_t* data, size_t length)
|
|
|
|
|
led_tm1637_tick(); // wait for next tick (no DIO transition when CLK is high)
|
|
|
|
|
gpio_clear(GPIO_PORT(LED_TM1637_CLK_PIN), GPIO_PIN(LED_TM1637_CLK_PIN)); // put CLK low
|
|
|
|
|
}
|
|
|
|
|
gpio_set_mode(GPIO_PORT(LED_TM1637_DIO_PIN), GPIO_MODE_INPUT, GPIO_CNF_INPUT_FLOAT, GPIO_PIN(LED_TM1637_DIO_PIN)); // switch DIO as input to read ACK
|
|
|
|
|
gpio_mode_setup(GPIO_PORT(LED_TM1637_DIO_PIN), GPIO_MODE_INPUT, GPIO_PUPD_NONE, GPIO_PIN(LED_TM1637_DIO_PIN)); // switch DIO as input to read ACK
|
|
|
|
|
led_tm1637_tick(); // wait for next tick (when the slave should ACK)
|
|
|
|
|
gpio_set(GPIO_PORT(LED_TM1637_CLK_PIN), GPIO_PIN(LED_TM1637_CLK_PIN)); // put CLK high
|
|
|
|
|
if (gpio_get(GPIO_PORT(LED_TM1637_DIO_PIN), GPIO_PIN(LED_TM1637_DIO_PIN))) { // no ACK received
|
|
|
|
@ -244,11 +246,11 @@ static bool led_tm1637_write(const uint8_t* data, size_t length)
|
|
|
|
|
}
|
|
|
|
|
led_tm1637_tick(); // wait for next tick
|
|
|
|
|
gpio_clear(GPIO_PORT(LED_TM1637_CLK_PIN), GPIO_PIN(LED_TM1637_CLK_PIN)); // put CLK low
|
|
|
|
|
gpio_set_mode(GPIO_PORT(LED_TM1637_DIO_PIN), GPIO_MODE_OUTPUT_2_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, GPIO_PIN(LED_TM1637_DIO_PIN)); // switch DIO back to output to send next byte
|
|
|
|
|
gpio_mode_setup(GPIO_PORT(LED_TM1637_DIO_PIN), GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO_PIN(LED_TM1637_DIO_PIN)); // switch DIO back to output to send next byte
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// send stop condition
|
|
|
|
|
gpio_set_mode(GPIO_PORT(LED_TM1637_DIO_PIN), GPIO_MODE_OUTPUT_2_MHZ, GPIO_CNF_OUTPUT_PUSHPULL, GPIO_PIN(LED_TM1637_DIO_PIN)); // ensure DIO is output (in case no ACK as been received
|
|
|
|
|
gpio_mode_setup(GPIO_PORT(LED_TM1637_DIO_PIN), GPIO_MODE_OUTPUT, GPIO_PUPD_NONE, GPIO_PIN(LED_TM1637_DIO_PIN)); // ensure DIO is output (in case no ACK as been received
|
|
|
|
|
led_tm1637_tick(); // wait for next tick
|
|
|
|
|
gpio_set(GPIO_PORT(LED_TM1637_CLK_PIN), GPIO_PIN(LED_TM1637_CLK_PIN)); // put CLK high
|
|
|
|
|
led_tm1637_tick(); // wait for next tick
|
|
|
|
|