126 lines
2.1 KiB
C
126 lines
2.1 KiB
C
#include <stdint.h>
|
|
#include "system.h"
|
|
#include "led.h"
|
|
#include "timer.h"
|
|
#include <stdlib.h>
|
|
#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);
|
|
}
|
|
}
|
|
|
|
|