waveblender/timer.c
2020-04-13 11:11:17 +02:00

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);
}
}