tone-generator/data.cpp

113 lines
2.0 KiB
C++

#include <Arduino.h>
#include <SoftwareSerial.h>
#include <avr/pgmspace.h>
#include "midi_data.hpp"
#include "data.hpp"
const int SERIAL_RX = A4;
const int SERIAL_TX = A5;
enum Mode : uint8_t {
none,
ready,
local,
serial,
read,
jump,
};
static char buff[64];
static bool buff_full = false;
static unsigned buff_at = 0;
static unsigned address = 0;
static SoftwareSerial serial_dev(SERIAL_RX, SERIAL_TX);
static Mode mode = Mode::local;
void data::init() {
pinMode(SERIAL_RX, INPUT);
pinMode(SERIAL_TX, OUTPUT);
serial_dev.begin(57600);
serial_dev.listen();
serial_dev.write(Mode::ready);
unsigned long ts_end = millis() + 1000;
while(ts_end > millis()) {
if(check()) {
break;
}
}
}
bool data::check() {
if(serial_dev.available()) {
mode = serial_dev.read();
return true;
} else {
return false;
}
}
void data::jump(unsigned long loc) {
switch(mode) {
case Mode::local:
address = loc;
break;
case Mode::serial:
serial_dev.write(Mode::jump);
serial_dev.write(loc >> 24);
serial_dev.write(loc >> 16);
serial_dev.write(loc >> 8);
serial_dev.write(loc);
break;
}
}
inline uint8_t proc_len(uint8_t len) {
if(address + len >= sizeof(MIDI)) {
return sizeof(MIDI) - address;
} else {
return len;
}
}
static void fill_buffer() {
serial_dev.write(Mode::read);
serial_dev.write(sizeof(buff));
for(int i = 0; i < sizeof(buff); i++) {
while(!serial_dev.available()) {}
buff[i] = serial_dev.read();
}
buff_at = 0;
buff_full = true;
}
void data::read(void* data, uint8_t len) {
char* bytes = (char*)data;
switch(mode) {
case Mode::local:
len = proc_len(len);
memcpy_P(bytes, &MIDI[address], len);
address += len;
break;
case Mode::serial:
if(!buff_full) {
fill_buffer();
}
while(sizeof(buff) - buff_at < len) {
auto l = sizeof(buff) - buff_at;
memcpy(bytes, buff + buff_at, l);
bytes += l;
len -= l;
fill_buffer();
}
memcpy(bytes, buff + buff_at, len);
buff_at += len;
break;
}
}
void data::write(const void* data, uint8_t len) {
}