can now interface with eeprom; improved computer communication
This commit is contained in:
parent
3dda949846
commit
89aaa0c91a
5
dac.hpp
5
dac.hpp
|
@ -7,6 +7,11 @@ namespace dac {
|
||||||
|
|
||||||
inline void init() {
|
inline void init() {
|
||||||
DDRD = 0xff;
|
DDRD = 0xff;
|
||||||
|
PORTD = 127;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void reset() {
|
||||||
|
PORTD = 127;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline void set(int v) {
|
inline void set(int v) {
|
||||||
|
|
167
data.cpp
167
data.cpp
|
@ -1,112 +1,101 @@
|
||||||
|
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
#include <SoftwareSerial.h>
|
|
||||||
#include <avr/pgmspace.h>
|
#include <avr/pgmspace.h>
|
||||||
#include "midi_data.hpp"
|
|
||||||
#include "data.hpp"
|
#include "data.hpp"
|
||||||
|
#include "serial.hpp"
|
||||||
|
#include "eeprom.hpp"
|
||||||
|
#include "scheduler.hpp"
|
||||||
|
#include "indicator.hpp"
|
||||||
|
#include "dac.hpp"
|
||||||
|
|
||||||
const int SERIAL_RX = A4;
|
using namespace data;
|
||||||
const int SERIAL_TX = A5;
|
|
||||||
|
|
||||||
enum Mode : uint8_t {
|
static Mode mode = Mode::none;
|
||||||
none,
|
|
||||||
ready,
|
|
||||||
local,
|
|
||||||
serial,
|
|
||||||
read,
|
|
||||||
jump,
|
|
||||||
};
|
|
||||||
|
|
||||||
static char buff[64];
|
static void flash_data() {
|
||||||
static bool buff_full = false;
|
char buff[128];
|
||||||
static unsigned buff_at = 0;
|
unsigned count;
|
||||||
static unsigned address = 0;
|
unsigned at = 0;
|
||||||
static SoftwareSerial serial_dev(SERIAL_RX, SERIAL_TX);
|
unsigned max_len = eeprom::length();
|
||||||
static Mode mode = Mode::local;
|
|
||||||
|
|
||||||
void data::init() {
|
for(;;) {
|
||||||
pinMode(SERIAL_RX, INPUT);
|
unsigned count = sizeof(buff);
|
||||||
pinMode(SERIAL_TX, OUTPUT);
|
unsigned end = at + count;
|
||||||
serial_dev.begin(57600);
|
|
||||||
serial_dev.listen();
|
|
||||||
serial_dev.write(Mode::ready);
|
|
||||||
|
|
||||||
unsigned long ts_end = millis() + 1000;
|
if(end <= at) {
|
||||||
while(ts_end > millis()) {
|
break;
|
||||||
if(check()) {
|
}
|
||||||
|
if(end >= max_len) {
|
||||||
|
unsigned l = end - max_len;
|
||||||
|
if(count < l) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
count -= l;
|
||||||
|
}
|
||||||
|
|
||||||
|
count = serial::read(buff, count);
|
||||||
|
eeprom::write(at, buff, count);
|
||||||
|
at += count;
|
||||||
|
|
||||||
|
if(count != sizeof(buff)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
bool data::check() {
|
while(serial::read(buff, sizeof(buff) == sizeof(buff))) {
|
||||||
if(serial_dev.available()) {
|
|
||||||
mode = serial_dev.read();
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void data::jump(unsigned long loc) {
|
void data::update() {
|
||||||
|
static int last = 2;
|
||||||
|
int now = serial::is_connected() ? 1 : 0;
|
||||||
|
if(last == now) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
dac::reset();
|
||||||
|
indicator::reset();
|
||||||
|
last = now;
|
||||||
|
if(now) {
|
||||||
|
while(serial::dev.available()) {
|
||||||
|
serial::get();
|
||||||
|
}
|
||||||
|
delay(10);
|
||||||
|
serial::write("\x19\xc1\x6c\x19\x5b\x6f\xd2\x44", 8);
|
||||||
|
mode = serial::get();
|
||||||
|
switch(mode) {
|
||||||
|
case Mode::flash:
|
||||||
|
flash_data();
|
||||||
|
mode = Mode::none;
|
||||||
|
break;
|
||||||
|
case Mode::local:
|
||||||
|
eeprom::jump(0);
|
||||||
|
scheduler::reset();
|
||||||
|
break;
|
||||||
|
case Mode::stream:
|
||||||
|
scheduler::reset();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
mode = Mode::local;
|
||||||
|
eeprom::jump(0);
|
||||||
|
scheduler::reset();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned data::read(char* data, unsigned len) {
|
||||||
|
unsigned count = 0;
|
||||||
switch(mode) {
|
switch(mode) {
|
||||||
case Mode::local:
|
case Mode::local:
|
||||||
address = loc;
|
eeprom::read(data, len);
|
||||||
|
count = len;
|
||||||
break;
|
break;
|
||||||
case Mode::serial:
|
case Mode::stream:
|
||||||
serial_dev.write(Mode::jump);
|
count = serial::read(data, len);
|
||||||
serial_dev.write(loc >> 24);
|
|
||||||
serial_dev.write(loc >> 16);
|
|
||||||
serial_dev.write(loc >> 8);
|
|
||||||
serial_dev.write(loc);
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
for(unsigned i = count; i < len; i++) {
|
||||||
|
data[i] = 0;
|
||||||
inline uint8_t proc_len(uint8_t len) {
|
}
|
||||||
if(address + len >= sizeof(MIDI)) {
|
return count;
|
||||||
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) {
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
14
data.hpp
14
data.hpp
|
@ -3,10 +3,14 @@
|
||||||
|
|
||||||
namespace data {
|
namespace data {
|
||||||
|
|
||||||
void init();
|
enum Mode : uint8_t {
|
||||||
bool check();
|
none,
|
||||||
void jump(unsigned long loc = 0);
|
local,
|
||||||
void read(void* data, uint8_t len);
|
stream,
|
||||||
void write(const void* data, uint8_t len);
|
flash,
|
||||||
|
};
|
||||||
|
|
||||||
|
void update();
|
||||||
|
unsigned read(char* data, unsigned len);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,41 @@
|
||||||
|
|
||||||
|
#include <Wire.h>
|
||||||
|
#include <Arduino.h>
|
||||||
|
#include <SparkFun_External_EEPROM.h>
|
||||||
|
#include "eeprom.hpp"
|
||||||
|
|
||||||
|
constexpr uint8_t ADDR = 0x50;
|
||||||
|
constexpr unsigned DELAY = 100;
|
||||||
|
|
||||||
|
static ExternalEEPROM mem;
|
||||||
|
|
||||||
|
static unsigned at = 0;
|
||||||
|
|
||||||
|
void eeprom::init() {
|
||||||
|
Wire.setClock(400000);
|
||||||
|
Wire.begin();
|
||||||
|
mem.setMemoryType(1025);
|
||||||
|
mem.begin();
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned eeprom::length() {
|
||||||
|
return mem.length();
|
||||||
|
}
|
||||||
|
|
||||||
|
void eeprom::jump(unsigned loc) {
|
||||||
|
at = loc;
|
||||||
|
}
|
||||||
|
|
||||||
|
void eeprom::read(char* data, unsigned len) {
|
||||||
|
mem.read(at, data, len);
|
||||||
|
at += len;
|
||||||
|
}
|
||||||
|
|
||||||
|
void eeprom::read(unsigned loc, char* data, unsigned len) {
|
||||||
|
mem.read(loc, data, len);
|
||||||
|
}
|
||||||
|
|
||||||
|
void eeprom::write(unsigned loc, const char* data, unsigned len) {
|
||||||
|
mem.write(loc, data, len);
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,15 @@
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
namespace eeprom {
|
||||||
|
|
||||||
|
constexpr unsigned char PAGE_SIZE = 128;
|
||||||
|
|
||||||
|
void init();
|
||||||
|
void jump(unsigned addr);
|
||||||
|
void read(char* data, unsigned len);
|
||||||
|
void read(unsigned addr, char* data, unsigned len);
|
||||||
|
void write(unsigned addr, const char* data, unsigned len);
|
||||||
|
unsigned length();
|
||||||
|
};
|
||||||
|
|
|
@ -3,10 +3,14 @@
|
||||||
#include "indicator.hpp"
|
#include "indicator.hpp"
|
||||||
#include "tones.hpp"
|
#include "tones.hpp"
|
||||||
|
|
||||||
#define LED_INDICATOR 10
|
constexpr int PIN = 10;
|
||||||
|
|
||||||
void indicator::init() {
|
void indicator::init() {
|
||||||
pinMode(LED_INDICATOR, OUTPUT);
|
pinMode(PIN, OUTPUT);
|
||||||
|
}
|
||||||
|
|
||||||
|
void indicator::reset() {
|
||||||
|
analogWrite(PIN, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
void indicator::update() {
|
void indicator::update() {
|
||||||
|
@ -14,6 +18,6 @@ void indicator::update() {
|
||||||
for(int i = 0; i < tones::active; i++) {
|
for(int i = 0; i < tones::active; i++) {
|
||||||
v += tones::all[i].amplitude;
|
v += tones::all[i].amplitude;
|
||||||
}
|
}
|
||||||
analogWrite(LED_INDICATOR, min(v, 255));
|
analogWrite(PIN, min(v, 255));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
namespace indicator {
|
namespace indicator {
|
||||||
|
|
||||||
void init();
|
void init();
|
||||||
|
void reset();
|
||||||
void update();
|
void update();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,8 @@
|
||||||
#include "tones.hpp"
|
#include "tones.hpp"
|
||||||
#include "util.hpp"
|
#include "util.hpp"
|
||||||
|
|
||||||
|
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;
|
||||||
struct {
|
struct {
|
||||||
|
@ -24,25 +26,20 @@ constexpr uint64_t bm(int n) {
|
||||||
return ((uint64_t)1 << n) - 1;
|
return ((uint64_t)1 << n) - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
void scheduler::init() {
|
void scheduler::reset() {
|
||||||
data::jump(0);
|
|
||||||
tones::clear_all();
|
tones::clear_all();
|
||||||
ts_init = micros();
|
ts_init = micros();
|
||||||
running = true;
|
running = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void scheduler::do_next() {
|
static void do_next() {
|
||||||
|
|
||||||
int i = 1;
|
int i = 1;
|
||||||
|
|
||||||
if(running) {
|
|
||||||
if(next.active) {
|
if(next.active) {
|
||||||
tones::set(next.index, next.frequency, next.amplitude);
|
tones::set(next.index, next.frequency, next.amplitude);
|
||||||
next.active = false;
|
next.active = false;
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
init();
|
|
||||||
}
|
|
||||||
|
|
||||||
uint64_t v = 0;
|
uint64_t v = 0;
|
||||||
uint8_t buff[8];
|
uint8_t buff[8];
|
||||||
|
@ -117,8 +114,3 @@ void scheduler::do_all() {
|
||||||
tones::recalc();
|
tones::recalc();
|
||||||
}
|
}
|
||||||
|
|
||||||
void scheduler::clear() {
|
|
||||||
data::jump(0);
|
|
||||||
ts_last = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
|
@ -6,9 +6,7 @@ namespace scheduler {
|
||||||
inline uint32_t timestamp = 0;
|
inline uint32_t timestamp = 0;
|
||||||
inline bool running = false;
|
inline bool running = false;
|
||||||
|
|
||||||
void init();
|
void reset();
|
||||||
void do_next();
|
|
||||||
void do_all();
|
void do_all();
|
||||||
void clear();
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,72 @@
|
||||||
|
|
||||||
|
#include <Arduino.h>
|
||||||
|
#include <SoftwareSerial.h>
|
||||||
|
#include "serial.hpp"
|
||||||
|
|
||||||
|
constexpr int DTR = A0;
|
||||||
|
constexpr int CTS = A3;
|
||||||
|
|
||||||
|
struct CTSGuard {
|
||||||
|
CTSGuard() {
|
||||||
|
digitalWrite(CTS, 0);
|
||||||
|
}
|
||||||
|
~CTSGuard() {
|
||||||
|
digitalWrite(CTS, 1);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void serial::init() {
|
||||||
|
pinMode(DTR, INPUT_PULLUP);
|
||||||
|
pinMode(CTS, OUTPUT);
|
||||||
|
pinMode(RXD, INPUT_PULLUP);
|
||||||
|
pinMode(TXD, OUTPUT);
|
||||||
|
digitalWrite(CTS, 1);
|
||||||
|
dev.begin(57600);
|
||||||
|
dev.listen();
|
||||||
|
}
|
||||||
|
|
||||||
|
bool serial::is_connected() {
|
||||||
|
return digitalRead(DTR) == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool wait_until() {
|
||||||
|
while(!serial::dev.available()) {
|
||||||
|
if(!serial::is_connected()) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned serial::read(char* data, unsigned len) {
|
||||||
|
CTSGuard guard;
|
||||||
|
|
||||||
|
for(unsigned i = 0; i < len; i++) {
|
||||||
|
if(!wait_until()) {
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
data[i] = dev.read();
|
||||||
|
}
|
||||||
|
|
||||||
|
return len;
|
||||||
|
}
|
||||||
|
|
||||||
|
void serial::write(const char* data, unsigned len) {
|
||||||
|
for(unsigned i = 0; i < len; i++) {
|
||||||
|
dev.write(data[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void serial::put(char ch) {
|
||||||
|
dev.write(ch);
|
||||||
|
}
|
||||||
|
|
||||||
|
int serial::get() {
|
||||||
|
unsigned char ch;
|
||||||
|
if(read(&ch, 1)) {
|
||||||
|
return ch;
|
||||||
|
} else {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <SoftwareSerial.h>
|
||||||
|
#include <avr/pgmspace.h>
|
||||||
|
|
||||||
|
namespace serial {
|
||||||
|
|
||||||
|
constexpr int RXD = A2;
|
||||||
|
constexpr int TXD = A1;
|
||||||
|
|
||||||
|
inline SoftwareSerial dev(RXD, TXD);
|
||||||
|
|
||||||
|
void init();
|
||||||
|
bool is_connected();
|
||||||
|
bool wait_until_available();
|
||||||
|
unsigned read(char* data, unsigned len);
|
||||||
|
void write(const char* data, unsigned len);
|
||||||
|
void put(char ch);
|
||||||
|
int get();
|
||||||
|
};
|
||||||
|
|
|
@ -6,6 +6,8 @@
|
||||||
#include "util.hpp"
|
#include "util.hpp"
|
||||||
#include "scheduler.hpp"
|
#include "scheduler.hpp"
|
||||||
#include "indicator.hpp"
|
#include "indicator.hpp"
|
||||||
|
#include "serial.hpp"
|
||||||
|
#include "eeprom.hpp"
|
||||||
#include "data.hpp"
|
#include "data.hpp"
|
||||||
|
|
||||||
static unsigned long int micros_at = 0;
|
static unsigned long int micros_at = 0;
|
||||||
|
@ -21,23 +23,23 @@ inline unsigned long micros_diff() {
|
||||||
void setup() {
|
void setup() {
|
||||||
Tone::init();
|
Tone::init();
|
||||||
dac::init();
|
dac::init();
|
||||||
data::init();
|
serial::init();
|
||||||
|
eeprom::init();
|
||||||
tones::init();
|
tones::init();
|
||||||
scheduler::init();
|
|
||||||
indicator::init();
|
indicator::init();
|
||||||
|
scheduler::reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
void loop() {
|
void loop() {
|
||||||
|
|
||||||
if(scheduler::running) {
|
if(scheduler::running) {
|
||||||
if(timing::at >= scheduler::timestamp) {
|
if(timing::at >= scheduler::timestamp) {
|
||||||
|
data::update();
|
||||||
scheduler::do_all();
|
scheduler::do_all();
|
||||||
indicator::update();
|
indicator::update();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if(data::check()) {
|
data::update();
|
||||||
scheduler::do_next();
|
|
||||||
tones::recalc();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
timing::update();
|
timing::update();
|
||||||
|
|
Loading…
Reference in New Issue