113 lines
2.0 KiB
C++
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) {
|
||
|
}
|
||
|
|