M arm03/include/exti.h => arm03/include/exti.h +0 -2
@@ 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);
M arm03/include/timer.h => arm03/include/timer.h +4 -1
@@ 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);
M arm03/src/main.c => arm03/src/main.c +85 -121
@@ 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);
}
M arm03/src/pin.c => arm03/src/pin.c +2 -2
@@ 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) {
D arm03/src/registers.c => arm03/src/registers.c +0 -39
@@ 1,39 0,0 @@
-/* #include <stdint.h> */
-
-/* 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; */
-/* } */
M arm03/src/timer.c => arm03/src/timer.c +21 -13
@@ 1,32 1,40 @@
#include "timer.h"
-#include "stm32f401xe.h"
+#include <stm32f4xx.h>
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;
}