From ef747bad41ac02ba141d57eee0da4065031bbb56 Mon Sep 17 00:00:00 2001 From: Jay Robson Date: Thu, 3 Oct 2024 02:27:58 +1000 Subject: [PATCH] now with sawtooth, square, and triangle waves :D --- README.md | 14 +++++++------- entry.hpp | 18 +++++++++--------- scheduler.cpp | 36 +++++++++++++++--------------------- tone.cpp | 4 ++++ tone.hpp | 28 ++++++++++++++++++++++++++-- tones.cpp | 5 +++-- tones.hpp | 3 +-- 7 files changed, 65 insertions(+), 43 deletions(-) diff --git a/README.md b/README.md index eeae974..8b6b442 100644 --- a/README.md +++ b/README.md @@ -20,12 +20,12 @@ This uses an AVR microcontroller (ATMega328P-PU). # Instruction Set -| ID | Name | Size | Layout | +| ID | Name | Size | Layout | |-|-|-|-| -| 0 | stop | 1 | id (3), empty (5) | -| 1 | setup | 8 | id (3), us_per_tick (29), amplitude (8), size (24) | -| 2 | set | 3 | id (3), index (5), frequency (12), empty (4) | -| 3 | set-ts | 5 | id (3), index (5), ticks (20), frequency (12) | -| 4 | clear | 1 | id (3), index (5) | -| 5 | clear-ts | 4 | id (3), index (5), ticks (20), empty (4) | +| 0 | stop | 1 | id (3), empty (5) | +| 1 | setup | 8 | id (3), us_per_tick (29), amplitude (8), size (24) | +| 2 | set | 3 | id (3), index (5), frequency (12), mode (2), empty (2) | +| 3 | set-ts | 5 | id (3), index (5), ticks (18), frequency (12), mode (2) | +| 4 | clear | 1 | id (3), index (5) | +| 5 | clear-ts | 4 | id (3), index (5), ticks (18), empty (6) | diff --git a/entry.hpp b/entry.hpp index 1026868..47fe8b0 100644 --- a/entry.hpp +++ b/entry.hpp @@ -9,13 +9,14 @@ struct Checker { namespace entry { enum Type : uint8_t { - stop = 0, - config = 1, - set = 2, - set_ts = 3, - clear = 4, - clear_ts = 5, - tempo = 6, + stop = 0, + config = 1, + set = 2, + set_ts = 3, + clear = 4, + clear_ts = 5, + set_saw = 6, + set_saw_ts = 7, }; enum NextType { @@ -28,6 +29,7 @@ namespace entry { uint8_t index; uint8_t amplitude; uint16_t frequency; + uint8_t mode; }; struct Tempo { @@ -47,8 +49,6 @@ 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 f6e6d12..521a52e 100644 --- a/scheduler.cpp +++ b/scheduler.cpp @@ -20,10 +20,7 @@ struct { } config; struct { entry::NextType type = entry::nt_none; - union { - entry::Tone tone; - entry::Tempo tempo; - }; + entry::Tone tone; } next; void scheduler::reset() { @@ -36,19 +33,12 @@ static void do_next() { int i = 1; - 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; + if(next.type == entry::nt_tone) { + if(state == State::play) { + tones::set(next.tone.index, next.tone.frequency, next.tone.amplitude, next.tone.mode); } + next.type = entry::nt_none; } - next.type = entry::nt_none; uint64_t v = 0; uint8_t buff[8]; @@ -80,7 +70,9 @@ static void do_next() { break; } case entry::Type::set: { - v >>= 4; + v >>= 2; + next.tone.mode = v & bm(2); + v >>= 2; next.type = entry::nt_tone; next.tone.frequency = v & bm(12); v >>= 12; @@ -90,10 +82,12 @@ static void do_next() { } case entry::Type::set_ts: { next.type = entry::nt_tone; + next.tone.mode = v & bm(2); + v >>= 2; next.tone.frequency = v & bm(12); v >>= 12; - uint32_t ticks = (v & bm(20)) - tick_offset; - v >>= 20; + uint32_t ticks = (v & bm(18)) - tick_offset; + v >>= 18; next.tone.index = v & bm(5); next.tone.amplitude = config.amplitude; timestamp = ticks * config.us_per_tick + ts_init; @@ -107,9 +101,9 @@ static void do_next() { break; } case entry::Type::clear_ts: { - v >>= 4; - uint32_t ticks = (v & bm(20)) - tick_offset; - v >>= 20; + v >>= 6; + uint32_t ticks = (v & bm(18)) - tick_offset; + v >>= 18; next.type = entry::nt_tone; next.tone.index = v & bm(5); next.tone.frequency = 0; diff --git a/tone.cpp b/tone.cpp index 378c85e..6aeccda 100644 --- a/tone.cpp +++ b/tone.cpp @@ -2,6 +2,10 @@ #include #include "tone.hpp" +static int8_t abs(int8_t v) { + return v >= 0 ? v : -v; +} + void Tone::init() { for(unsigned i = 0; i < sizeof(sin_lookup); i++) { sin_lookup[i] = round(sin((float)i / sizeof(sin_lookup) * M_PI * 2) * 127); diff --git a/tone.hpp b/tone.hpp index 87bf949..80db89f 100644 --- a/tone.hpp +++ b/tone.hpp @@ -5,9 +5,18 @@ #include "util.hpp" struct Tone { + + enum Type { + tt_sine = 0, + tt_saw = 1, + tt_square = 2, + tt_triangle = 3, + }; + uint32_t phase; uint16_t frequency; uint8_t amplitude; + Type mode; inline static int8_t sin_lookup[256]; @@ -22,8 +31,23 @@ struct Tone { } inline int get() const AW_IN { - uint8_t id = phase >> 12; - return (int)sin_lookup[id] * amplitude; + int v; + switch(mode) { + case tt_sine: + v = sin_lookup[(phase >> 12) & 255]; + break; + case tt_saw: + v = (int8_t)((phase >> 12) & 255); + break; + case tt_square: + v = phase & 0x80000 ? -127 : 127; + break; + case tt_triangle: + v = (phase >> 11) & 0x1ff; + v = (v > 0xff ? 1 : -1) * (int8_t)phase; + break; + } + return v * amplitude; } }; diff --git a/tones.cpp b/tones.cpp index 95cbc40..590962c 100644 --- a/tones.cpp +++ b/tones.cpp @@ -40,16 +40,17 @@ void tones::clear_all() { active = 0; } -void tones::set(uint8_t index, uint16_t frequency, float amplitude) { +void tones::set(uint8_t index, uint16_t frequency, float amplitude, Tone::Type mode) { if(index >= size(all)) { return; } Tone& t = all[lookup[index]]; if(amplitude == 0) { - t = {0, 0, 0}; + t = {0, 0, 0, Tone::tt_sine}; } else { t.frequency = frequency; t.amplitude = amplitude; + t.mode = mode; } } diff --git a/tones.hpp b/tones.hpp index 8b6fe1d..30ce42b 100644 --- a/tones.hpp +++ b/tones.hpp @@ -9,11 +9,10 @@ namespace tones { inline Tone all[32]; inline uint8_t lookup[size(all)]; inline uint8_t rlookup[size(all)]; - inline int active; void init(); - void set(uint8_t index, uint16_t frequency, float amplitude); + void set(uint8_t index, uint16_t frequency, float amplitude, Tone::Type mode); void clear_all(); void recalc(); }