From f71b07f4993f7d400cf4b3322ad39412772b6d3e Mon Sep 17 00:00:00 2001 From: Jay Robson Date: Mon, 30 Sep 2024 23:25:16 +1000 Subject: [PATCH] improvements --- buttons.cpp | 8 ++--- eeprom.cpp | 12 ++++++-- entry.hpp | 59 ++++++++++++------------------------ scheduler.cpp | 82 +++++++++++++++++++++++++++++++++------------------ util.hpp | 11 +++++++ 5 files changed, 96 insertions(+), 76 deletions(-) diff --git a/buttons.cpp b/buttons.cpp index d1d7cc9..ed65027 100644 --- a/buttons.cpp +++ b/buttons.cpp @@ -9,7 +9,6 @@ const int PIN_NEXT = 8; -static bool state_next = 1; static uint32_t addr_next = 0; void buttons::init() { @@ -32,14 +31,11 @@ static void on_next() { } void buttons::update() { - if(!digitalRead(PIN_NEXT) && state_next) { + if(!digitalRead(PIN_NEXT)) { delay(1); - state_next = 0; - } - else if(digitalRead(PIN_NEXT) && !state_next) { + while(!digitalRead(PIN_NEXT)) {} delay(1); on_next(); - state_next = 1; } } diff --git a/eeprom.cpp b/eeprom.cpp index 4799515..3fbe556 100644 --- a/eeprom.cpp +++ b/eeprom.cpp @@ -8,7 +8,8 @@ using namespace eeprom; constexpr uint8_t WRITE_MS = 3; constexpr uint8_t ADDR = 0x50; -uint32_t at = 0; +static uint32_t at = 0; +static uint32_t last_block_end = 0; static bool is_responsive(uint8_t i2c_addr) { bool s = mem.start_write(i2c_addr); @@ -37,6 +38,7 @@ void eeprom::init() { } void eeprom::jump(uint32_t p_at) { + last_block_end = 0; at = p_at; } @@ -44,11 +46,16 @@ void eeprom::read(char* data, uint16_t data_size) { uint16_t recorded = 0; while(recorded < data_size && at < LENGTH) { + uint32_t block_end = at / BLOCK_SIZE * BLOCK_SIZE + BLOCK_SIZE; uint8_t read_len = min(min(block_end - at, data_size - recorded), 255); uint8_t i2c_addr = get_i2c_addr(at); - set_address(i2c_addr, at); + if(block_end != last_block_end) { + set_address(i2c_addr, at); + last_block_end = block_end; + } + mem.start_read(i2c_addr); mem.read(data + recorded, read_len, true); recorded += read_len; @@ -72,6 +79,7 @@ void eeprom::page_write(uint32_t at, const char* data) { mem.write(data, PAGE_SIZE - (at % PAGE_SIZE)); mem.end(); delay(WRITE_MS); + last_block_end = 0; } uint32_t eeprom::get_addr() { diff --git a/entry.hpp b/entry.hpp index 7cabef9..1026868 100644 --- a/entry.hpp +++ b/entry.hpp @@ -9,53 +9,30 @@ struct Checker { namespace entry { enum Type : uint8_t { - stop, - config, - set, - set_ts, - clear, - clear_ts, + stop = 0, + config = 1, + set = 2, + set_ts = 3, + clear = 4, + clear_ts = 5, + tempo = 6, }; - struct Set { - uint8_t index; - uint16_t frequency; - }; - - struct Clear { - uint8_t index; - }; - - struct SetTS { - uint8_t index; - uint32_t ticks; - uint16_t frequency; - }; - - struct ClearTS { - uint8_t index; - uint32_t ticks; + enum NextType { + nt_none, + nt_tone, + nt_tempo, }; - struct Stop { - }; - - struct Config { - uint32_t us_per_tick; + struct Tone { + uint8_t index; uint8_t amplitude; - uint32_t jump_addr; + uint16_t frequency; }; - struct Generic { - Type type; - union { - Set set; - SetTS set_ts; - Clear clear; - ClearTS clear_ts; - Stop stop; - Config config; - }; + struct Tempo { + uint32_t ticks; + uint32_t us_per_tick; }; inline size_t get_size(Type type) { @@ -70,6 +47,8 @@ namespace entry { return 4; case Type::config: return 8; + case Type::tempo: + return 7; case Type::stop: default: return 1; diff --git a/scheduler.cpp b/scheduler.cpp index d27310c..19d11d3 100644 --- a/scheduler.cpp +++ b/scheduler.cpp @@ -12,40 +12,57 @@ using namespace scheduler; static uint32_t ts_init = 0; static uint32_t ts_last = 0; +static uint32_t tick_offset = 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; + entry::NextType type = entry::nt_none; + union { + entry::Tone tone; + entry::Tempo tempo; + }; } next; void scheduler::reset() { tones::clear_all(); ts_init = timestamp = micros(); + tick_offset = 0; } static void do_next() { int i = 1; - if(next.active) { - if(state == State::play) { - tones::set(next.index, next.frequency, next.amplitude); + 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; } - next.active = false; } + next.type = entry::nt_none; uint64_t v = 0; uint8_t buff[8]; - data::read(buff, 1); + + if(data::read(buff, 1) != 1) { + return; + } entry::Type type = buff[0] >> 5; int entry_size = entry::get_size(type); - data::read(buff + 1, entry_size - 1); + + if(data::read(buff + 1, entry_size - 1) != entry_size - 1) { + return; + } for(int i = 0; i < entry_size; i++) { v = (v << 8) | buff[i]; @@ -62,41 +79,50 @@ static void do_next() { scheduler::reset(); break; } + case entry::Type::tempo: { + next.type = entry::nt_tempo; + v >>= 4; + next.tempo.ticks = (v & bm(20)) - tick_offset; + v >>= 20; + next.tempo.us_per_tick = v & bm(29); + timestamp = next.tempo.ticks * config.us_per_tick + ts_init; + break; + } case entry::Type::set: { v >>= 4; - next.frequency = v & bm(12); + next.type = entry::nt_tone; + next.tone.frequency = v & bm(12); v >>= 12; - next.index = v & bm(5); - next.amplitude = config.amplitude; - next.active = true; + next.tone.index = v & bm(5); + next.tone.amplitude = config.amplitude; break; } case entry::Type::set_ts: { - next.frequency = v & bm(12); + next.type = entry::nt_tone; + next.tone.frequency = v & bm(12); v >>= 12; - uint32_t ticks = v & bm(20); + uint32_t ticks = (v & bm(20)) - tick_offset; v >>= 20; - next.index = v & bm(5); - next.amplitude = config.amplitude; - next.active = true; + next.tone.index = v & bm(5); + next.tone.amplitude = config.amplitude; 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; + next.type = entry::nt_tone; + next.tone.index = v & bm(5); + next.tone.frequency = 0; + next.tone.amplitude = 0; break; } case entry::Type::clear_ts: { v >>= 4; - uint32_t ticks = v & bm(20); + uint32_t ticks = (v & bm(20)) - tick_offset; v >>= 20; - next.index = v & bm(5); - next.frequency = 0; - next.amplitude = 0; - next.active = true; + next.type = entry::nt_tone; + next.tone.index = v & bm(5); + next.tone.frequency = 0; + next.tone.amplitude = 0; timestamp = ticks * config.us_per_tick + ts_init; break; } diff --git a/util.hpp b/util.hpp index f969979..d99ad73 100644 --- a/util.hpp +++ b/util.hpp @@ -13,6 +13,17 @@ inline void swap(T& a, T& b) { a = t; } +#ifdef DEBUG_BLINK +inline void debug_blink() { + digitalWrite(9, 0); + delay(120); + digitalWrite(9, 1); + delay(10); + digitalWrite(9, 0); + delay(120); +} +#endif + #define bm(V) (((uint64_t)1 << V) - 1) #define size(V) (sizeof(V) / sizeof(V[0]))