#include #include "timing.hpp" #include "scheduler.hpp" #include "data.hpp" #include "entry.hpp" #include "tones.hpp" #include "util.hpp" #include "buttons.hpp" using namespace scheduler; static uint32_t ts_init = 0; static uint32_t ts_last = 0; struct { uint8_t amplitude = 1; uint32_t us_per_tick = 1; } config; struct { uint8_t index; uint8_t amplitude; uint16_t frequency; bool active = false; } next; void scheduler::reset() { tones::clear_all(); ts_init = timestamp = micros(); } static void do_next() { int i = 1; if(next.active) { if(state == State::play) { tones::set(next.index, next.frequency, next.amplitude); } next.active = false; } uint64_t v = 0; uint8_t buff[8]; data::read(buff, 1); entry::Type type = buff[0] >> 5; int entry_size = entry::get_size(type); data::read(buff + 1, entry_size - 1); for(int i = 0; i < entry_size; i++) { v = (v << 8) | buff[i]; } switch(type) { case entry::Type::config: { buttons::set_addr_next((v & bm(24)) + data::get_addr()); v >>= 24; config.amplitude = v & bm(8); v >>= 8; config.us_per_tick = v & bm(29); state = State::play; scheduler::reset(); break; } case entry::Type::set: { v >>= 4; next.frequency = v & bm(12); v >>= 12; next.index = v & bm(5); next.amplitude = config.amplitude; next.active = true; break; } 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; next.active = true; timestamp = ticks * config.us_per_tick + ts_init; break; } case entry::Type::clear: { next.index = v & bm(5); next.frequency = 0; next.amplitude = 0; next.active = true; break; } 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; next.active = true; timestamp = ticks * config.us_per_tick + ts_init; break; } default: { state = State::end; tones::clear_all(); break; } } } void scheduler::do_all() { do { do_next(); } while(should_update()); tones::recalc(); }