From a3abb3a189e245825b4c7cef2c046ffb0aefdd3b Mon Sep 17 00:00:00 2001 From: Rutherther Date: Thu, 28 Nov 2024 08:52:40 +0100 Subject: [PATCH] feat(arm03): Update --- arm03/include/exti.h | 2 - arm03/include/timer.h | 5 +- arm03/src/main.c | 206 +++++++++++++++++------------------------- arm03/src/pin.c | 4 +- arm03/src/registers.c | 39 -------- arm03/src/timer.c | 34 ++++--- 6 files changed, 112 insertions(+), 178 deletions(-) delete mode 100644 arm03/src/registers.c diff --git a/arm03/include/exti.h b/arm03/include/exti.h index beaa14a..31d9a44 100644 --- a/arm03/include/exti.h +++ b/arm03/include/exti.h @@ -27,8 +27,6 @@ void exti_falling_interrupt(exti_t* exti); void exti_disable_interrupt(exti_t* exti); void exti_enable_interrupt(exti_t *exti); -void exti_nvic_setup(exti_t* exti, uint8_t line); - uint32_t exti_is_interrupt(exti_t* exti); void exti_clear_interrupt(exti_t* exti); diff --git a/arm03/include/timer.h b/arm03/include/timer.h index 9dd532f..a6e3173 100644 --- a/arm03/include/timer.h +++ b/arm03/include/timer.h @@ -4,13 +4,14 @@ #define TIMER_H typedef struct { - TIM_TypeDef* timer; + TIM_TypeDef* periph; uint8_t idx; } timer_t; void timer_init(timer_t* timer, TIM_TypeDef* peripheral, uint8_t timer_idx); void timer_enable(timer_t* timer); void timer_disable(timer_t* timer); +uint32_t timer_is_enabled(timer_t *timer); void timer_set_refresh(timer_t* timer, uint32_t refresh_value); void timer_set_counter(timer_t* timer, uint32_t counter); @@ -18,6 +19,8 @@ void timer_set_counter(timer_t* timer, uint32_t counter); // TODO: rest of parameters...? void timer_configure(timer_t* timer, uint8_t buffered_reload, uint16_t prescaler, uint8_t one_pulse_mode); +uint16_t timer_count(timer_t* timer); + void timer_enable_interrupt(timer_t* timer); void timer_disable_interrupt(timer_t* timer); uint32_t timer_is_interrupt(timer_t* timer); diff --git a/arm03/src/main.c b/arm03/src/main.c index da7a338..0725a2b 100644 --- a/arm03/src/main.c +++ b/arm03/src/main.c @@ -4,13 +4,8 @@ #include "pin.h" #include "timer.h" #include "registers.h" -#include "stm32f401xe.h" - -#define LED_PIN 5 -#define LED_GPIO GPIOA -#define BUTTON_PIN 13 -#define BUTTON_GPIO GPIOC -#define BUTTON_GPIO_ID 2 // A 0 B 1 C 2 +#include "display.h" +#include "delay.h" void hard_fault_handler() { while(1) {} @@ -70,143 +65,112 @@ void SystemCoreClockSetHSI(void) { while ((RCC->CFGR & RCC_CFGR_SWS) != RCC_CFGR_SWS_PLL); // Wait till PLL is system clock src } +display_t display; + +timer_t stopwatch_timer; +timer_t display_timer; + +exti_t startstop_button; +exti_t null_button; void main() { + // Setup SystemCoreClockSetHSI(); - RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN | RCC_AHB1ENR_GPIOCEN; + systick_configure(); + + RCC->AHB1ENR |= RCC_AHB1ENR_GPIOAEN | RCC_AHB1ENR_GPIOBEN | RCC_AHB1ENR_GPIOCEN; RCC->APB1ENR |= RCC_APB1ENR_TIM2EN | RCC_APB1ENR_TIM3EN; - RCC->APB2ENR |= RCC_APB2ENR_SYSCFGEN; + RCC->APB2ENR |= RCC_APB2ENR_SYSCFGEN | RCC_APB2ENR_TIM1EN; + + // The timer clocks are at 12 MHz. + // For 100 Hz, the prescaler would be 120 000. That is too big, + // so 200 Hz is chosen. From there it will have to be divided by 2 by application. + // For 6800 Hz, 1765 prescaler will be used, leading to 6798... Hz // Initialize timer for display at interrupt frequency // digit update frequency * digits * 34 - // aim for 100 Hz * 4 * 34 = 13 600 Hz + // aim for 100 Hz * 4 * 17 = 6 800 Hz - __enable_irq(); - while(1) { __WFI(); } -} + exti_init(&null_button, 4, EXTI, SYSCFG); + exti_external_interrupt(&null_button, EXTI_GPIOA); + exti_rising_interrupt(&null_button); + exti_enable_interrupt(&null_button); -#define CYCLES 17 -typedef struct { - // Display board configuration - uint16_t digits; - pin_t pin_data; - pin_t pin_sftclk; - pin_t pin_strobe; - - // Current application data - uint16_t number; - uint8_t digit_dots; - - // Current application state - uint8_t digits_en; - - // Current internal state of the display - uint16_t current_cycle; - uint32_t current_shifter; - uint8_t current_digit; - uint16_t max_value; -} display_t; - -typedef enum { - DISPLAY_UPDATE_NEW_DIGIT, - DISPLAY_UPDATE_DISPLAY_DIGIT, - DISPLAY_UPDATE_SHIFT, -} display_update_state_t; - -const char numbers_seven_segments[11] = { - 0x3F, /* 0 */ - 0x06, /* 1 */ - 0x5B, /* 2 */ - 0x4F, /* 3 */ - 0x66, /* 4 */ - 0x6D, /* 5 */ - 0x7D, /* 6 */ - 0x07, /* 7 */ - 0x7F, /* 8 */ - 0x6F, /* 9 */ - 0x40, /* - */ -}; - -/** - * @brief Convert a digit from a regular number to seven segments - * @param[in] number The number to convert - * @param[in] digit The digit from least significant, starting with 0 - * @return Description - */ -uint16_t seven_segment_convert(uint16_t number, uint16_t digit); - -/** - * @brief Converts a number to serial strem to send via the SIPO register. - * @param[in] number The number to convert to the values for shift register - * @param[in] digit The digit from the least significant, starting with 0 - * @return Description - */ -uint16_t convert_num_digit(uint16_t number, uint8_t digit); - -void display_number_set(display_t* display, uint16_t number); -void display_number_increment(display_t* display); - -void display_enable_digit(display_t* display, uint8_t digit, uint8_t enable); - -display_update_state_t display_update(display_t* display); - -uint16_t seven_segment_convert(uint16_t number, uint16_t digit) { - for (int i = 0; i < digit; i++) { - number /= 10; + exti_init(&startstop_button, 0, EXTI, SYSCFG); + exti_external_interrupt(&startstop_button, EXTI_GPIOB); + exti_rising_interrupt(&startstop_button); + exti_enable_interrupt(&startstop_button); + + { + pin_t pin_data; + pin_t pin_sftclk; + pin_t pin_strobe; + + pin_init(&pin_data, GPIOA, 9); + pin_init(&pin_sftclk, GPIOA, 8); + pin_init(&pin_strobe, GPIOB, 5); + + pin_into_output(&pin_data); + pin_into_output(&pin_sftclk); + pin_into_output(&pin_strobe); + + display_init(&display, 4, pin_data, pin_sftclk, pin_strobe); + display_dots(&display, 1 << 1); } - return numbers_seven_segments[number % 10]; -} -uint16_t convert_num_digit(uint16_t number, uint8_t digit) { - uint16_t seven_segments = seven_segment_convert(number, digit); - uint16_t digits = 1 << digit; + timer_init(&stopwatch_timer, TIM2, 2); + timer_configure(&stopwatch_timer, 0, 60000, 0); + timer_set_refresh(&stopwatch_timer, 10000*4); - return (seven_segments << 8) | digits; -} + timer_init(&display_timer, TIM3, 3); + timer_configure(&display_timer, 0, 500, 0); + timer_set_refresh(&display_timer, 4); + timer_enable_interrupt(&display_timer); + timer_enable(&display_timer); -void display_number_set(display_t *display, uint16_t number) { - display->number = number; -} + __enable_irq(); -void display_number_increment(display_t *display) { - display->number = (display->number + 1) % display->max_value; -} + // Application + while (1) { + uint32_t count = timer_count(&stopwatch_timer) >> 2; -void display_enable_digit(display_t *display, uint8_t digit, uint8_t enable) { - uint16_t digits = 1 << digit; - if (enable != 0) { - display->digits_en |= digits; - } else { - display->digits_en &= ~digits; + display_enable_digit(&display, 0, + (count % display.max_value) >= 1000); + display_number_set(&display, count); + + /* DELAY_US(100); */ } } -display_update_state_t display_update(display_t *display) { - display_update_state_t state = DISPLAY_UPDATE_SHIFT; +void null_timer(void) { + timer_set_counter(&stopwatch_timer, 0); +} - if (display->current_cycle == 0) { - // Set up. - state = DISPLAY_UPDATE_NEW_DIGIT; +void toggle_timer(void) { + if (timer_is_enabled(&stopwatch_timer)) { + timer_disable(&stopwatch_timer); + } else { + timer_enable(&stopwatch_timer); } +} - if (display->current_cycle < CYCLES - 1) { - pin_write(&display->pin_data, - reg_read_bits_pos(&display->current_shifter, - 16 - display->current_cycle, - 1)); - - pin_set(&display->pin_sftclk); - pin_reset(&display->pin_sftclk); - } else { - // Send strobe - pin_set(&display->pin_strobe); - pin_reset(&display->pin_strobe); +void EXTI0_handler(void) { + exti_clear_interrupt(&startstop_button); + toggle_timer(); + exti_clear_interrupt(&startstop_button); +} - state = DISPLAY_UPDATE_DISPLAY_DIGIT; - } +void EXTI4_handler(void) { + exti_clear_interrupt(&null_button); + null_timer(); +} - display->current_cycle = (display->current_cycle + 1) % CYCLES; +/* void TIM1_handler(void) { */ +/* // The stopwatch timer */ +/* } */ - return state; +void TIM3_handler(void) { + timer_clear_interrupt(&display_timer); + display_update(&display); } diff --git a/arm03/src/pin.c b/arm03/src/pin.c index a0f049f..4a59857 100644 --- a/arm03/src/pin.c +++ b/arm03/src/pin.c @@ -28,10 +28,10 @@ void pin_toggle(pin_t *pin) { reg_toggle_bits_pos(&pin->gpio->ODR, pin->pin, 1); } void pin_set(pin_t *pin) { - pin->gpio->ODR = 1 << pin->pin; + pin->gpio->BSRR = 1 << pin->pin; } void pin_reset(pin_t *pin) { - pin->gpio->ODR = 1 << (pin->pin + 15); + pin->gpio->BSRR = 1 << (pin->pin + GPIO_BSRR_BR0_Pos); } void pin_into_output(pin_t *pin) { diff --git a/arm03/src/registers.c b/arm03/src/registers.c deleted file mode 100644 index e6ec9bd..0000000 --- a/arm03/src/registers.c +++ /dev/null @@ -1,39 +0,0 @@ -/* #include */ - -/* void reg_write_bits_pos(volatile uint32_t *reg, uint32_t data, uint8_t pos, uint32_t mask) { */ -/* *reg &= ~(mask << pos); */ -/* *reg |= (data & mask) << pos; */ -/* } */ - -/* void reg_write_bits(volatile uint32_t *reg, uint32_t data, uint32_t mask) { */ -/* *reg &= ~(mask); */ -/* *reg |= (data & mask); */ -/* } */ - -/* void reg_set_bits_pos(volatile uint32_t *reg, uint8_t pos, uint32_t mask) { */ -/* *reg |= mask << pos; */ -/* } */ - -/* void reg_set_bits(volatile uint32_t *reg, uint32_t mask) { */ -/* *reg |= mask; */ -/* } */ - -/* void reg_toggle_bits_pos(volatile uint32_t *reg, uint8_t pos, uint32_t mask) { */ -/* *reg ^= (mask << pos); */ -/* } */ - -/* void reg_toggle_bits(volatile uint32_t *reg, uint32_t mask) { */ -/* *reg ^= mask; */ -/* } */ - -/* uint32_t reg_read_bits_pos(volatile uint32_t *reg, uint8_t pos, uint32_t mask) { */ -/* return ((*reg) >> pos) & mask; */ -/* } */ - -/* void reg_clear_bits_pos(volatile uint32_t *reg, uint8_t pos, uint32_t mask) { */ -/* *reg ^= ~(mask << pos); */ -/* } */ - -/* void reg_clear_bits(volatile uint32_t *reg, uint8_t pos, uint32_t mask) { */ -/* *reg &= ~mask; */ -/* } */ diff --git a/arm03/src/timer.c b/arm03/src/timer.c index 00529cc..823702f 100644 --- a/arm03/src/timer.c +++ b/arm03/src/timer.c @@ -1,32 +1,40 @@ #include "timer.h" -#include "stm32f401xe.h" +#include void timer_init(timer_t *timer, TIM_TypeDef *peripheral, uint8_t timer_idx) { - timer->timer = peripheral; + timer->periph = peripheral; timer->idx = timer_idx; } void timer_enable(timer_t *timer) { - timer->timer->CR1 |= TIM_CR1_CEN; + timer->periph->CR1 |= TIM_CR1_CEN; } void timer_disable(timer_t *timer) { - timer->timer->CR1 &= ~TIM_CR1_CEN; + timer->periph->CR1 &= ~TIM_CR1_CEN; +} + +uint32_t timer_is_enabled(timer_t *timer) { + return timer->periph->CR1 & TIM_CR1_CEN; } void timer_set_refresh(timer_t *timer, uint32_t refresh_value) { - timer->timer->ARR = refresh_value; + timer->periph->ARR = refresh_value; } void timer_set_counter(timer_t *timer, uint32_t counter) { - timer->timer->CNT = counter; + timer->periph->CNT = counter; +} + +uint16_t timer_count(timer_t *timer) { + return timer->periph->CNT; } // TODO: rest of parameters...? void timer_configure(timer_t *timer, uint8_t buffered_reload, uint16_t prescaler, uint8_t one_pulse_mode) { - timer->timer->CR1 = (0 << TIM_CR1_CKD_Pos) | (buffered_reload << TIM_CR1_ARPE_Pos) | + timer->periph->CR1 = (0 << TIM_CR1_CKD_Pos) | (buffered_reload << TIM_CR1_ARPE_Pos) | (0 << TIM_CR1_CMS_Pos) | (0 << TIM_CR1_DIR_Pos) | (one_pulse_mode << TIM_CR1_OPM_Pos) | (1 << TIM_CR1_URS_Pos); - timer->timer->CR2 = 0; - timer->timer->PSC = prescaler - 1; + timer->periph->CR2 = 0; + timer->periph->PSC = prescaler - 1; } IRQn_Type timer_irq_idx(uint8_t line) { @@ -48,17 +56,17 @@ IRQn_Type timer_irq_idx(uint8_t line) { void timer_enable_interrupt(timer_t *timer) { timer_clear_interrupt(timer); - timer->timer->DIER |= TIM_DIER_UIE; + timer->periph->DIER |= TIM_DIER_UIE; IRQn_Type irq = timer_irq_idx(timer->idx); NVIC_SetPriority(irq, 1); NVIC_EnableIRQ(irq); } void timer_disable_interrupt(timer_t *timer) { - timer->timer->DIER &= ~TIM_DIER_UIE; + timer->periph->DIER &= ~TIM_DIER_UIE; } uint32_t timer_is_interrupt(timer_t *timer) { - return timer->timer->SR & TIM_SR_UIF; + return timer->periph->SR & TIM_SR_UIF; } void timer_clear_interrupt(timer_t *timer) { - timer->timer->SR = ~TIM_SR_UIF; + timer->periph->SR = ~TIM_SR_UIF; } -- 2.48.1