2024-08-19 22:43:24 +10:00
|
|
|
|
|
|
|
#include <Arduino.h>
|
|
|
|
#include "timing.hpp"
|
|
|
|
#include "scheduler.hpp"
|
2024-08-26 13:02:17 +10:00
|
|
|
#include "data.hpp"
|
2024-08-19 22:43:24 +10:00
|
|
|
#include "entry.hpp"
|
|
|
|
#include "tones.hpp"
|
|
|
|
#include "util.hpp"
|
2024-09-29 18:07:58 +10:00
|
|
|
#include "buttons.hpp"
|
2024-08-19 22:43:24 +10:00
|
|
|
|
2024-08-28 13:10:57 +10:00
|
|
|
using namespace scheduler;
|
|
|
|
|
2024-08-25 13:55:43 +10:00
|
|
|
static uint32_t ts_init = 0;
|
|
|
|
static uint32_t ts_last = 0;
|
2024-09-30 23:25:16 +10:00
|
|
|
static uint32_t tick_offset = 0;
|
|
|
|
|
2024-08-25 13:55:43 +10:00
|
|
|
struct {
|
2024-08-26 13:02:17 +10:00
|
|
|
uint8_t amplitude = 1;
|
2024-08-25 13:55:43 +10:00
|
|
|
uint32_t us_per_tick = 1;
|
|
|
|
} config;
|
2024-08-19 22:43:24 +10:00
|
|
|
struct {
|
2024-09-30 23:25:16 +10:00
|
|
|
entry::NextType type = entry::nt_none;
|
|
|
|
union {
|
|
|
|
entry::Tone tone;
|
|
|
|
entry::Tempo tempo;
|
|
|
|
};
|
2024-08-19 22:43:24 +10:00
|
|
|
} next;
|
|
|
|
|
2024-08-28 13:10:57 +10:00
|
|
|
void scheduler::reset() {
|
2024-08-25 16:53:23 +10:00
|
|
|
tones::clear_all();
|
2024-09-27 22:46:51 +10:00
|
|
|
ts_init = timestamp = micros();
|
2024-09-30 23:25:16 +10:00
|
|
|
tick_offset = 0;
|
2024-08-25 16:53:23 +10:00
|
|
|
}
|
|
|
|
|
2024-08-28 13:10:57 +10:00
|
|
|
static void do_next() {
|
2024-08-25 13:55:43 +10:00
|
|
|
|
|
|
|
int i = 1;
|
2024-08-19 22:43:24 +10:00
|
|
|
|
2024-09-30 23:25:16 +10:00
|
|
|
if(state == State::play) {
|
|
|
|
switch(next.type) {
|
|
|
|
case entry::nt_tone:
|
|
|
|
tones::set(next.tone.index, next.tone.frequency, next.tone.amplitude);
|
|
|
|
break;
|
|
|
|
case entry::nt_tempo:
|
|
|
|
ts_init += next.tempo.ticks * config.us_per_tick;
|
|
|
|
tick_offset = next.tempo.ticks;
|
|
|
|
config.us_per_tick = next.tempo.us_per_tick;
|
|
|
|
break;
|
2024-09-27 22:46:51 +10:00
|
|
|
}
|
2024-08-19 22:43:24 +10:00
|
|
|
}
|
2024-09-30 23:25:16 +10:00
|
|
|
next.type = entry::nt_none;
|
2024-08-19 22:43:24 +10:00
|
|
|
|
2024-08-25 13:55:43 +10:00
|
|
|
uint64_t v = 0;
|
|
|
|
uint8_t buff[8];
|
2024-09-30 23:25:16 +10:00
|
|
|
|
|
|
|
if(data::read(buff, 1) != 1) {
|
|
|
|
return;
|
|
|
|
}
|
2024-08-25 13:55:43 +10:00
|
|
|
|
|
|
|
entry::Type type = buff[0] >> 5;
|
|
|
|
int entry_size = entry::get_size(type);
|
2024-09-30 23:25:16 +10:00
|
|
|
|
|
|
|
if(data::read(buff + 1, entry_size - 1) != entry_size - 1) {
|
|
|
|
return;
|
|
|
|
}
|
2024-08-25 13:55:43 +10:00
|
|
|
|
|
|
|
for(int i = 0; i < entry_size; i++) {
|
|
|
|
v = (v << 8) | buff[i];
|
|
|
|
}
|
|
|
|
|
2024-08-19 22:43:24 +10:00
|
|
|
switch(type) {
|
2024-08-25 13:55:43 +10:00
|
|
|
case entry::Type::config: {
|
2024-09-29 18:07:58 +10:00
|
|
|
buttons::set_addr_next((v & bm(24)) + data::get_addr());
|
|
|
|
v >>= 24;
|
2024-08-26 13:02:17 +10:00
|
|
|
config.amplitude = v & bm(8);
|
|
|
|
v >>= 8;
|
2024-08-25 13:55:43 +10:00
|
|
|
config.us_per_tick = v & bm(29);
|
2024-09-27 22:46:51 +10:00
|
|
|
state = State::play;
|
|
|
|
scheduler::reset();
|
2024-08-19 22:43:24 +10:00
|
|
|
break;
|
|
|
|
}
|
2024-08-25 13:55:43 +10:00
|
|
|
case entry::Type::set: {
|
|
|
|
v >>= 4;
|
2024-09-30 23:25:16 +10:00
|
|
|
next.type = entry::nt_tone;
|
|
|
|
next.tone.frequency = v & bm(12);
|
2024-08-25 13:55:43 +10:00
|
|
|
v >>= 12;
|
2024-09-30 23:25:16 +10:00
|
|
|
next.tone.index = v & bm(5);
|
|
|
|
next.tone.amplitude = config.amplitude;
|
2024-08-19 22:43:24 +10:00
|
|
|
break;
|
|
|
|
}
|
2024-08-25 13:55:43 +10:00
|
|
|
case entry::Type::set_ts: {
|
2024-09-30 23:25:16 +10:00
|
|
|
next.type = entry::nt_tone;
|
|
|
|
next.tone.frequency = v & bm(12);
|
2024-08-25 13:55:43 +10:00
|
|
|
v >>= 12;
|
2024-09-30 23:25:16 +10:00
|
|
|
uint32_t ticks = (v & bm(20)) - tick_offset;
|
2024-08-25 13:55:43 +10:00
|
|
|
v >>= 20;
|
2024-09-30 23:25:16 +10:00
|
|
|
next.tone.index = v & bm(5);
|
|
|
|
next.tone.amplitude = config.amplitude;
|
2024-08-25 13:55:43 +10:00
|
|
|
timestamp = ticks * config.us_per_tick + ts_init;
|
2024-08-19 22:43:24 +10:00
|
|
|
break;
|
|
|
|
}
|
2024-08-25 13:55:43 +10:00
|
|
|
case entry::Type::clear: {
|
2024-09-30 23:25:16 +10:00
|
|
|
next.type = entry::nt_tone;
|
|
|
|
next.tone.index = v & bm(5);
|
|
|
|
next.tone.frequency = 0;
|
|
|
|
next.tone.amplitude = 0;
|
2024-08-19 22:43:24 +10:00
|
|
|
break;
|
|
|
|
}
|
2024-08-25 13:55:43 +10:00
|
|
|
case entry::Type::clear_ts: {
|
|
|
|
v >>= 4;
|
2024-09-30 23:25:16 +10:00
|
|
|
uint32_t ticks = (v & bm(20)) - tick_offset;
|
2024-08-25 13:55:43 +10:00
|
|
|
v >>= 20;
|
2024-09-30 23:25:16 +10:00
|
|
|
next.type = entry::nt_tone;
|
|
|
|
next.tone.index = v & bm(5);
|
|
|
|
next.tone.frequency = 0;
|
|
|
|
next.tone.amplitude = 0;
|
2024-08-25 13:55:43 +10:00
|
|
|
timestamp = ticks * config.us_per_tick + ts_init;
|
2024-08-19 22:43:24 +10:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
default: {
|
2024-09-27 22:46:51 +10:00
|
|
|
state = State::end;
|
2024-08-25 13:55:43 +10:00
|
|
|
tones::clear_all();
|
2024-08-19 22:43:24 +10:00
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2024-08-25 16:53:23 +10:00
|
|
|
}
|
2024-08-25 13:55:43 +10:00
|
|
|
|
2024-08-25 16:53:23 +10:00
|
|
|
void scheduler::do_all() {
|
2024-09-27 22:46:51 +10:00
|
|
|
do {
|
2024-08-25 16:53:23 +10:00
|
|
|
do_next();
|
2024-09-27 22:46:51 +10:00
|
|
|
} while(should_update());
|
2024-08-25 16:53:23 +10:00
|
|
|
tones::recalc();
|
2024-08-19 22:43:24 +10:00
|
|
|
}
|
|
|
|
|