now with sawtooth, square, and triangle waves :D

This commit is contained in:
Jay Robson 2024-10-03 02:27:58 +10:00
parent 16254662b9
commit ef747bad41
7 changed files with 65 additions and 43 deletions

View File

@ -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) |

View File

@ -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;

View File

@ -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;

View File

@ -2,6 +2,10 @@
#include <math.h>
#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);

View File

@ -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;
}
};

View File

@ -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;
}
}

View File

@ -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();
}