#include #include "system.h" #include "led.h" #include "timer.h" #include #include "settings.h" #define S_PER_MINUTE (60) extern uint32_t cpu_freq; void (*beat_callback)(uint32_t b) = NULL; void timer_set_beat_callback(void (*b_cb)(uint32_t)) { beat_callback = b_cb; } void timer_clear_beat_callback(void) { timer_set_beat_callback(NULL); } int timer_set_bpm(void) { uint32_t val = 0; uint32_t psc = 1; uint32_t err = 0; uint32_t reg = 0; uint32_t clock = (cpu_freq / (4 * Settings.bpm)) * (S_PER_MINUTE);; while (psc < 65535) { val = clock / psc; err = clock % psc; if ((val < 65535) && (err < (psc / 2))) { val--; break; } val = 0; psc++; } if (val == 0) return -1; TIM4_CR1 = 0; __asm__ volatile ("dmb"); TIM4_PSC = psc; TIM4_ARR = val; TIM4_CNT = val - 1; return 0; } int timer_start(void) { TIM4_CR1 |= TIM_CR1_CLOCK_ENABLE; TIM4_DIER |= TIM_DIER_UIE; } int timer_stop(void) { TIM4_CR1 &= ~TIM_CR1_CLOCK_ENABLE; TIM4_DIER &= ~TIM_DIER_UIE; } static void timer_irq_setup(void) { nvic_irq_enable(NVIC_TIM4_IRQN); nvic_irq_setprio(NVIC_TIM4_IRQN, 0); APB1_CLOCK_RST |= TIM4_APB1_CLOCK_ER_VAL; __asm__ volatile ("dmb"); APB1_CLOCK_RST &= ~TIM4_APB1_CLOCK_ER_VAL; APB1_CLOCK_ER |= TIM4_APB1_CLOCK_ER_VAL; } int timer_init(void) { timer_stop(); timer_irq_setup(); timer_set_bpm(); return 0; } static volatile uint32_t tim4_ticks = 0; static volatile int pending_cb = 0; void isr_tim1(void) { TIM1_SR &= ~TIM_SR_UIF; } void isr_tim3(void) { TIM3_SR &= ~TIM_SR_UIF; } static int beat = 1; int timer_get_beat(void) { return beat; } void timer_set_beat(int b) { beat = b; } void timer_poll(void) { if (beat_callback && (pending_cb > 0)) { pending_cb--; beat_callback(beat); beat++; } } void isr_tim4(void) { TIM4_SR &= ~TIM_SR_UIF; tim4_ticks++; if (beat_callback) { pending_cb++; } else { led_beat((beat % 8) + 1); } }