Compare commits
2 Commits
42e6f7c79f
...
f71b07f499
Author | SHA1 | Date |
---|---|---|
Jay Robson | f71b07f499 | |
Jay Robson | 376a2ef6de |
17
buttons.cpp
17
buttons.cpp
|
@ -8,7 +8,8 @@
|
||||||
#include "indicator.hpp"
|
#include "indicator.hpp"
|
||||||
|
|
||||||
const int PIN_NEXT = 8;
|
const int PIN_NEXT = 8;
|
||||||
bool state_next = 1;
|
|
||||||
|
static uint32_t addr_next = 0;
|
||||||
|
|
||||||
void buttons::init() {
|
void buttons::init() {
|
||||||
pinMode(PIN_NEXT, INPUT_PULLUP);
|
pinMode(PIN_NEXT, INPUT_PULLUP);
|
||||||
|
@ -19,6 +20,7 @@ static void on_next() {
|
||||||
case scheduler::State::play:
|
case scheduler::State::play:
|
||||||
scheduler::state = scheduler::State::skip;
|
scheduler::state = scheduler::State::skip;
|
||||||
indicator::reset();
|
indicator::reset();
|
||||||
|
data::jump(addr_next);
|
||||||
tones::clear_all();
|
tones::clear_all();
|
||||||
dac::reset();
|
dac::reset();
|
||||||
break;
|
break;
|
||||||
|
@ -29,16 +31,15 @@ static void on_next() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void buttons::update() {
|
void buttons::update() {
|
||||||
|
if(!digitalRead(PIN_NEXT)) {
|
||||||
if(!digitalRead(PIN_NEXT) && state_next) {
|
|
||||||
delay(1);
|
delay(1);
|
||||||
state_next = 0;
|
while(!digitalRead(PIN_NEXT)) {}
|
||||||
}
|
|
||||||
|
|
||||||
else if(digitalRead(PIN_NEXT) && !state_next) {
|
|
||||||
delay(1);
|
delay(1);
|
||||||
on_next();
|
on_next();
|
||||||
state_next = 1;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void buttons::set_addr_next(uint32_t addr) {
|
||||||
|
addr_next = addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,5 +4,6 @@
|
||||||
namespace buttons {
|
namespace buttons {
|
||||||
void init();
|
void init();
|
||||||
void update();
|
void update();
|
||||||
|
void set_addr_next(uint32_t addr);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
22
data.cpp
22
data.cpp
|
@ -62,7 +62,7 @@ void data::update() {
|
||||||
scheduler::reset();
|
scheduler::reset();
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else if(mode != Mode::local) {
|
} else {
|
||||||
mode = Mode::local;
|
mode = Mode::local;
|
||||||
eeprom::jump(0);
|
eeprom::jump(0);
|
||||||
scheduler::state = scheduler::State::pause;
|
scheduler::state = scheduler::State::pause;
|
||||||
|
@ -87,3 +87,23 @@ unsigned data::read(char* data, unsigned len) {
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool data::jump(uint32_t addr) {
|
||||||
|
switch(mode) {
|
||||||
|
case Mode::local:
|
||||||
|
eeprom::jump(addr);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t data::get_addr() {
|
||||||
|
switch(mode) {
|
||||||
|
case Mode::local:
|
||||||
|
return eeprom::get_addr();
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
2
data.hpp
2
data.hpp
|
@ -12,5 +12,7 @@ namespace data {
|
||||||
|
|
||||||
void update();
|
void update();
|
||||||
unsigned read(char* data, unsigned len);
|
unsigned read(char* data, unsigned len);
|
||||||
|
bool jump(uint32_t addr);
|
||||||
|
uint32_t get_addr();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
22
eeprom.cpp
22
eeprom.cpp
|
@ -8,7 +8,8 @@ using namespace eeprom;
|
||||||
constexpr uint8_t WRITE_MS = 3;
|
constexpr uint8_t WRITE_MS = 3;
|
||||||
constexpr uint8_t ADDR = 0x50;
|
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) {
|
static bool is_responsive(uint8_t i2c_addr) {
|
||||||
bool s = mem.start_write(i2c_addr);
|
bool s = mem.start_write(i2c_addr);
|
||||||
|
@ -22,11 +23,7 @@ static void wait_for_responsive(uint8_t i2c_addr) {
|
||||||
}
|
}
|
||||||
|
|
||||||
static uint8_t get_i2c_addr(uint32_t at) {
|
static uint8_t get_i2c_addr(uint32_t at) {
|
||||||
uint8_t i2c_addr = ADDR;
|
return ADDR ^ (at >> 16);
|
||||||
if(at > 0xffff) {
|
|
||||||
i2c_addr |= 1;
|
|
||||||
}
|
|
||||||
return i2c_addr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void set_address(uint8_t i2c_addr, uint16_t at) {
|
static void set_address(uint8_t i2c_addr, uint16_t at) {
|
||||||
|
@ -41,6 +38,7 @@ void eeprom::init() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void eeprom::jump(uint32_t p_at) {
|
void eeprom::jump(uint32_t p_at) {
|
||||||
|
last_block_end = 0;
|
||||||
at = p_at;
|
at = p_at;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -48,11 +46,16 @@ void eeprom::read(char* data, uint16_t data_size) {
|
||||||
uint16_t recorded = 0;
|
uint16_t recorded = 0;
|
||||||
|
|
||||||
while(recorded < data_size && at < LENGTH) {
|
while(recorded < data_size && at < LENGTH) {
|
||||||
|
|
||||||
uint32_t block_end = at / BLOCK_SIZE * BLOCK_SIZE + BLOCK_SIZE;
|
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 read_len = min(min(block_end - at, data_size - recorded), 255);
|
||||||
uint8_t i2c_addr = get_i2c_addr(at);
|
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.start_read(i2c_addr);
|
||||||
mem.read(data + recorded, read_len, true);
|
mem.read(data + recorded, read_len, true);
|
||||||
recorded += read_len;
|
recorded += read_len;
|
||||||
|
@ -76,5 +79,10 @@ void eeprom::page_write(uint32_t at, const char* data) {
|
||||||
mem.write(data, PAGE_SIZE - (at % PAGE_SIZE));
|
mem.write(data, PAGE_SIZE - (at % PAGE_SIZE));
|
||||||
mem.end();
|
mem.end();
|
||||||
delay(WRITE_MS);
|
delay(WRITE_MS);
|
||||||
|
last_block_end = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t eeprom::get_addr() {
|
||||||
|
return at;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@ namespace eeprom {
|
||||||
|
|
||||||
constexpr uint8_t PAGE_SIZE = 128;
|
constexpr uint8_t PAGE_SIZE = 128;
|
||||||
constexpr uint32_t BLOCK_SIZE = 0x10000;
|
constexpr uint32_t BLOCK_SIZE = 0x10000;
|
||||||
constexpr uint32_t LENGTH = 0x20000;
|
constexpr uint32_t LENGTH = 0x80000;
|
||||||
|
|
||||||
inline SoftTWI mem(A4, A5);
|
inline SoftTWI mem(A4, A5);
|
||||||
|
|
||||||
|
@ -16,5 +16,6 @@ namespace eeprom {
|
||||||
void jump(uint32_t addr);
|
void jump(uint32_t addr);
|
||||||
void read(char* data, uint16_t len);
|
void read(char* data, uint16_t len);
|
||||||
void page_write(uint32_t at, const char* data);
|
void page_write(uint32_t at, const char* data);
|
||||||
|
uint32_t get_addr();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
60
entry.hpp
60
entry.hpp
|
@ -9,52 +9,30 @@ struct Checker {
|
||||||
namespace entry {
|
namespace entry {
|
||||||
|
|
||||||
enum Type : uint8_t {
|
enum Type : uint8_t {
|
||||||
stop,
|
stop = 0,
|
||||||
config,
|
config = 1,
|
||||||
set,
|
set = 2,
|
||||||
set_ts,
|
set_ts = 3,
|
||||||
clear,
|
clear = 4,
|
||||||
clear_ts,
|
clear_ts = 5,
|
||||||
|
tempo = 6,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Set {
|
enum NextType {
|
||||||
uint8_t index;
|
nt_none,
|
||||||
uint16_t frequency;
|
nt_tone,
|
||||||
};
|
nt_tempo,
|
||||||
|
|
||||||
struct Clear {
|
|
||||||
uint8_t index;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct SetTS {
|
|
||||||
uint8_t index;
|
|
||||||
uint32_t ticks;
|
|
||||||
uint16_t frequency;
|
|
||||||
};
|
|
||||||
|
|
||||||
struct ClearTS {
|
|
||||||
uint8_t index;
|
|
||||||
uint32_t ticks;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Stop {
|
struct Tone {
|
||||||
};
|
uint8_t index;
|
||||||
|
|
||||||
struct Config {
|
|
||||||
uint32_t us_per_tick;
|
|
||||||
uint8_t amplitude;
|
uint8_t amplitude;
|
||||||
|
uint16_t frequency;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct Generic {
|
struct Tempo {
|
||||||
Type type;
|
uint32_t ticks;
|
||||||
union {
|
uint32_t us_per_tick;
|
||||||
Set set;
|
|
||||||
SetTS set_ts;
|
|
||||||
Clear clear;
|
|
||||||
ClearTS clear_ts;
|
|
||||||
Stop stop;
|
|
||||||
Config config;
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
inline size_t get_size(Type type) {
|
inline size_t get_size(Type type) {
|
||||||
|
@ -68,7 +46,9 @@ namespace entry {
|
||||||
case Type::clear_ts:
|
case Type::clear_ts:
|
||||||
return 4;
|
return 4;
|
||||||
case Type::config:
|
case Type::config:
|
||||||
return 5;
|
return 8;
|
||||||
|
case Type::tempo:
|
||||||
|
return 7;
|
||||||
case Type::stop:
|
case Type::stop:
|
||||||
default:
|
default:
|
||||||
return 1;
|
return 1;
|
||||||
|
|
|
@ -6,45 +6,63 @@
|
||||||
#include "entry.hpp"
|
#include "entry.hpp"
|
||||||
#include "tones.hpp"
|
#include "tones.hpp"
|
||||||
#include "util.hpp"
|
#include "util.hpp"
|
||||||
|
#include "buttons.hpp"
|
||||||
|
|
||||||
using namespace scheduler;
|
using namespace scheduler;
|
||||||
|
|
||||||
static uint32_t ts_init = 0;
|
static uint32_t ts_init = 0;
|
||||||
static uint32_t ts_last = 0;
|
static uint32_t ts_last = 0;
|
||||||
|
static uint32_t tick_offset = 0;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
uint8_t amplitude = 1;
|
uint8_t amplitude = 1;
|
||||||
uint32_t us_per_tick = 1;
|
uint32_t us_per_tick = 1;
|
||||||
} config;
|
} config;
|
||||||
struct {
|
struct {
|
||||||
uint8_t index;
|
entry::NextType type = entry::nt_none;
|
||||||
uint8_t amplitude;
|
union {
|
||||||
uint16_t frequency;
|
entry::Tone tone;
|
||||||
bool active = false;
|
entry::Tempo tempo;
|
||||||
|
};
|
||||||
} next;
|
} next;
|
||||||
|
|
||||||
void scheduler::reset() {
|
void scheduler::reset() {
|
||||||
tones::clear_all();
|
tones::clear_all();
|
||||||
ts_init = timestamp = micros();
|
ts_init = timestamp = micros();
|
||||||
|
tick_offset = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void do_next() {
|
static void do_next() {
|
||||||
|
|
||||||
int i = 1;
|
int i = 1;
|
||||||
|
|
||||||
if(next.active) {
|
if(state == State::play) {
|
||||||
if(state == State::play) {
|
switch(next.type) {
|
||||||
tones::set(next.index, next.frequency, next.amplitude);
|
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;
|
uint64_t v = 0;
|
||||||
uint8_t buff[8];
|
uint8_t buff[8];
|
||||||
data::read(buff, 1);
|
|
||||||
|
if(data::read(buff, 1) != 1) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
entry::Type type = buff[0] >> 5;
|
entry::Type type = buff[0] >> 5;
|
||||||
int entry_size = entry::get_size(type);
|
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++) {
|
for(int i = 0; i < entry_size; i++) {
|
||||||
v = (v << 8) | buff[i];
|
v = (v << 8) | buff[i];
|
||||||
|
@ -52,6 +70,8 @@ static void do_next() {
|
||||||
|
|
||||||
switch(type) {
|
switch(type) {
|
||||||
case entry::Type::config: {
|
case entry::Type::config: {
|
||||||
|
buttons::set_addr_next((v & bm(24)) + data::get_addr());
|
||||||
|
v >>= 24;
|
||||||
config.amplitude = v & bm(8);
|
config.amplitude = v & bm(8);
|
||||||
v >>= 8;
|
v >>= 8;
|
||||||
config.us_per_tick = v & bm(29);
|
config.us_per_tick = v & bm(29);
|
||||||
|
@ -59,41 +79,50 @@ static void do_next() {
|
||||||
scheduler::reset();
|
scheduler::reset();
|
||||||
break;
|
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: {
|
case entry::Type::set: {
|
||||||
v >>= 4;
|
v >>= 4;
|
||||||
next.frequency = v & bm(12);
|
next.type = entry::nt_tone;
|
||||||
|
next.tone.frequency = v & bm(12);
|
||||||
v >>= 12;
|
v >>= 12;
|
||||||
next.index = v & bm(5);
|
next.tone.index = v & bm(5);
|
||||||
next.amplitude = config.amplitude;
|
next.tone.amplitude = config.amplitude;
|
||||||
next.active = true;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case entry::Type::set_ts: {
|
case entry::Type::set_ts: {
|
||||||
next.frequency = v & bm(12);
|
next.type = entry::nt_tone;
|
||||||
|
next.tone.frequency = v & bm(12);
|
||||||
v >>= 12;
|
v >>= 12;
|
||||||
uint32_t ticks = v & bm(20);
|
uint32_t ticks = (v & bm(20)) - tick_offset;
|
||||||
v >>= 20;
|
v >>= 20;
|
||||||
next.index = v & bm(5);
|
next.tone.index = v & bm(5);
|
||||||
next.amplitude = config.amplitude;
|
next.tone.amplitude = config.amplitude;
|
||||||
next.active = true;
|
|
||||||
timestamp = ticks * config.us_per_tick + ts_init;
|
timestamp = ticks * config.us_per_tick + ts_init;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case entry::Type::clear: {
|
case entry::Type::clear: {
|
||||||
next.index = v & bm(5);
|
next.type = entry::nt_tone;
|
||||||
next.frequency = 0;
|
next.tone.index = v & bm(5);
|
||||||
next.amplitude = 0;
|
next.tone.frequency = 0;
|
||||||
next.active = true;
|
next.tone.amplitude = 0;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case entry::Type::clear_ts: {
|
case entry::Type::clear_ts: {
|
||||||
v >>= 4;
|
v >>= 4;
|
||||||
uint32_t ticks = v & bm(20);
|
uint32_t ticks = (v & bm(20)) - tick_offset;
|
||||||
v >>= 20;
|
v >>= 20;
|
||||||
next.index = v & bm(5);
|
next.type = entry::nt_tone;
|
||||||
next.frequency = 0;
|
next.tone.index = v & bm(5);
|
||||||
next.amplitude = 0;
|
next.tone.frequency = 0;
|
||||||
next.active = true;
|
next.tone.amplitude = 0;
|
||||||
timestamp = ticks * config.us_per_tick + ts_init;
|
timestamp = ticks * config.us_per_tick + ts_init;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
13
util.hpp
13
util.hpp
|
@ -13,6 +13,17 @@ inline void swap(T& a, T& b) {
|
||||||
a = t;
|
a = t;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define bm(V) (((uint64_t)1 << V) - 1);
|
#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]))
|
#define size(V) (sizeof(V) / sizeof(V[0]))
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue