waveblender/timer.c

127 lines
2.1 KiB
C
Raw Normal View History

2020-04-06 21:08:01 +02:00
#include <stdint.h>
#include "system.h"
#include "led.h"
#include "timer.h"
#include <stdlib.h>
2020-04-13 11:11:17 +02:00
#include "settings.h"
2020-04-06 21:08:01 +02:00
#define S_PER_MINUTE (60)
2020-04-06 21:08:01 +02:00
extern uint32_t cpu_freq;
2020-04-06 21:08:01 +02:00
void (*beat_callback)(uint32_t b) = NULL;
2020-04-06 21:08:01 +02:00
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);
}
2020-04-13 11:11:17 +02:00
int timer_set_bpm(void)
2020-04-06 21:08:01 +02:00
{
uint32_t val = 0;
uint32_t psc = 1;
uint32_t err = 0;
uint32_t reg = 0;
2020-04-13 11:11:17 +02:00
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)
{
2020-04-13 11:11:17 +02:00
TIM4_CR1 &= ~TIM_CR1_CLOCK_ENABLE;
TIM4_DIER &= ~TIM_DIER_UIE;
}
2020-04-06 21:08:01 +02:00
static void timer_irq_setup(void)
{
2020-04-06 21:08:01 +02:00
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;
}
2020-04-06 21:08:01 +02:00
2020-04-13 11:11:17 +02:00
int timer_init(void)
{
timer_stop();
timer_irq_setup();
2020-04-13 11:11:17 +02:00
timer_set_bpm();
return 0;
2020-04-06 21:08:01 +02:00
}
static volatile uint32_t tim4_ticks = 0;
static volatile int pending_cb = 0;
2020-04-06 21:08:01 +02:00
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)
2020-04-06 21:08:01 +02:00
{
return beat;
}
void timer_set_beat(int b)
{
beat = b;
2020-04-06 21:08:01 +02:00
}
void timer_poll(void)
2020-04-06 21:08:01 +02:00
{
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);
}
2020-04-06 21:08:01 +02:00
}