tone-generator/scheduler.cpp

118 lines
2.2 KiB
C++
Raw Normal View History

2024-08-19 22:43:24 +10:00
#include <Arduino.h>
#include "timing.hpp"
#include "scheduler.hpp"
#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
using namespace scheduler;
2024-08-25 13:55:43 +10:00
static uint32_t ts_init = 0;
static uint32_t ts_last = 0;
struct {
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 {
uint8_t index;
uint8_t amplitude;
2024-08-19 22:43:24 +10:00
uint16_t frequency;
2024-08-25 16:53:23 +10:00
bool active = false;
2024-08-19 22:43:24 +10:00
} next;
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-08-25 16:53:23 +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
if(next.active) {
2024-09-27 22:46:51 +10:00
if(state == State::play) {
tones::set(next.index, next.frequency, next.amplitude);
}
next.active = false;
2024-08-19 22:43:24 +10:00
}
2024-08-25 13:55:43 +10:00
uint64_t v = 0;
uint8_t buff[8];
data::read(buff, 1);
2024-08-25 13:55:43 +10:00
entry::Type type = buff[0] >> 5;
int entry_size = entry::get_size(type);
data::read(buff + 1, entry_size - 1);
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;
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;
next.frequency = v & bm(12);
v >>= 12;
next.index = v & bm(5);
next.amplitude = config.amplitude;
2024-08-25 16:53:23 +10:00
next.active = true;
2024-08-19 22:43:24 +10:00
break;
}
2024-08-25 13:55:43 +10:00
case entry::Type::set_ts: {
next.frequency = v & bm(12);
v >>= 12;
uint32_t ticks = v & bm(20);
v >>= 20;
next.index = v & bm(5);
next.amplitude = config.amplitude;
2024-08-25 16:53:23 +10:00
next.active = true;
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: {
next.index = v & bm(5);
next.frequency = 0;
next.amplitude = 0;
2024-08-25 16:53:23 +10:00
next.active = true;
2024-08-19 22:43:24 +10:00
break;
}
2024-08-25 13:55:43 +10:00
case entry::Type::clear_ts: {
v >>= 4;
uint32_t ticks = v & bm(20);
v >>= 20;
next.index = v & bm(5);
next.frequency = 0;
next.amplitude = 0;
2024-08-25 16:53:23 +10:00
next.active = true;
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
}