Compare commits

...

4 Commits

Author SHA1 Message Date
King Kévin 93cc46ba83 tm1637: port to STM32F4 2022-10-28 13:31:35 +02:00
King Kévin 624006500f tm1637: port to STM32F4 2022-10-28 13:31:35 +02:00
King Kévin 5c78aa498e app: fix menu compile error 2022-10-28 13:31:35 +02:00
King Kévin 485fcd186b app: remove UART printing 2022-10-28 13:31:35 +02:00
4 changed files with 13 additions and 15 deletions

View File

@ -29,7 +29,6 @@
/* own libraries */
#include "global.h" // board definitions
#include "print.h" // printing utilities
#include "uart.h" // USART utilities
#include "usb_cdcacm.h" // USB CDC ACM utilities
#include "terminal.h" // handle the terminal interface
#include "menu.h" // menu utilities
@ -56,12 +55,10 @@ size_t putc(char c)
static char last_c = 0; // to remember on which character we last sent
if ('\n' == c) { // send carriage return (CR) + line feed (LF) newline for each LF
if ('\r' != last_c) { // CR has not already been sent
uart_putchar_nonblocking('\r'); // send CR over USART
usb_cdcacm_putchar('\r'); // send CR over USB
length++; // remember we printed 1 character
}
}
uart_putchar_nonblocking(c); // send byte over USART
usb_cdcacm_putchar(c); // send byte over USB
length++; // remember we printed 1 character
last_c = c; // remember last character
@ -341,7 +338,7 @@ static void command_help(void* argument)
static void process_command(char* str)
{
// ensure actions are available
if (NULL == menu_commands || 0 == LENGTH(menu_commands)) {
if (0 == LENGTH(menu_commands)) {
return;
}
// don't handle empty lines
@ -378,7 +375,6 @@ void main(void)
#endif
board_setup(); // setup board
uart_setup(); // setup USART (for printing)
usb_cdcacm_setup(); // setup USB CDC ACM (for printing)
OTG_FS_GCCFG |= OTG_GCCFG_NOVBUSSENS | OTG_GCCFG_PWRDWN; // disable VBUS sensing
OTG_FS_GCCFG &= ~(OTG_GCCFG_VBUSBSEN | OTG_GCCFG_VBUSASEN); // force USB device mode

View File

@ -262,6 +262,7 @@ void board_setup(void)
// setup button
#if defined(BUTTON_PIN) && defined(BUTTON_PRESSED)
rcc_periph_clock_enable(RCC_SYSCFG); // for EXTI port mapping
rcc_periph_clock_enable(GPIO_RCC(BUTTON_PIN)); // enable clock for button
exti_select_source(GPIO_EXTI(BUTTON_PIN), GPIO_PORT(BUTTON_PIN)); // mask external interrupt of this pin only for this port
#if BUTTON_PRESSED // level goes high when pressed

View File

@ -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

View File

@ -2,12 +2,11 @@
* @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
* @warning all calls are blocking
*/
#pragma once
#error not converted for STM32F4
/** display brightness levels
*/