Config management mode, to send/receive config via usb midi sysex
This commit is contained in:
parent
db4e4ac2f7
commit
2741ff5a27
8 changed files with 316 additions and 28 deletions
|
@ -236,6 +236,8 @@ byte subOctaveDouble = 0;
|
||||||
Adafruit_MPR121 touchSensor = Adafruit_MPR121(); // This is the 12-input touch sensor
|
Adafruit_MPR121 touchSensor = Adafruit_MPR121(); // This is the 12-input touch sensor
|
||||||
FilterOnePole breathFilter;
|
FilterOnePole breathFilter;
|
||||||
|
|
||||||
|
bool configManagementMode = false;
|
||||||
|
|
||||||
|
|
||||||
//_______________________________________________________________________________________________ SETUP
|
//_______________________________________________________________________________________________ SETUP
|
||||||
|
|
||||||
|
@ -260,9 +262,19 @@ void setup() {
|
||||||
pinMode(biteJumperGndPin, OUTPUT); //PBITE
|
pinMode(biteJumperGndPin, OUTPUT); //PBITE
|
||||||
digitalWrite(biteJumperGndPin, LOW); //PBITE
|
digitalWrite(biteJumperGndPin, LOW); //PBITE
|
||||||
|
|
||||||
|
bool factoryReset = !digitalRead(ePin) && !digitalRead(mPin);
|
||||||
|
configManagementMode = !factoryReset && !digitalRead(uPin) && !digitalRead(dPin);
|
||||||
|
|
||||||
|
initDisplay(); //Start up display and show logo
|
||||||
|
|
||||||
|
//If going into config management mode, stop here before we even touch the EEPROM.
|
||||||
|
if(configManagementMode) {
|
||||||
|
configModeSetup();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
//Read eeprom data into global vars
|
//Read eeprom data into global vars
|
||||||
readEEPROM();
|
readEEPROM(factoryReset);
|
||||||
|
|
||||||
activePatch = patch;
|
activePatch = patch;
|
||||||
|
|
||||||
|
@ -274,8 +286,6 @@ void setup() {
|
||||||
|
|
||||||
breathFilter.setFilter(LOWPASS, filterFreq, 0.0); // create a one pole (RC) lowpass filter
|
breathFilter.setFilter(LOWPASS, filterFreq, 0.0); // create a one pole (RC) lowpass filter
|
||||||
|
|
||||||
initDisplay(); //Start up display and show logo
|
|
||||||
|
|
||||||
biteJumper = !digitalRead(biteJumperPin);
|
biteJumper = !digitalRead(biteJumperPin);
|
||||||
if (biteJumper){
|
if (biteJumper){
|
||||||
pinMode(bitePin, INPUT);
|
pinMode(bitePin, INPUT);
|
||||||
|
@ -329,6 +339,13 @@ void setup() {
|
||||||
//_______________________________________________________________________________________________ MAIN LOOP
|
//_______________________________________________________________________________________________ MAIN LOOP
|
||||||
|
|
||||||
void loop() {
|
void loop() {
|
||||||
|
|
||||||
|
//If in config mgmt loop, do that and nothing else
|
||||||
|
if(configManagementMode) {
|
||||||
|
configModeLoop();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
breathFilter.input(analogRead(breathSensorPin));
|
breathFilter.input(analogRead(breathSensorPin));
|
||||||
pressureSensor = constrain((int) breathFilter.output(), 0, 4095); // Get the filtered pressure sensor reading from analog pin A0, input from sensor MP3V5004GP
|
pressureSensor = constrain((int) breathFilter.output(), 0, 4095); // Get the filtered pressure sensor reading from analog pin A0, input from sensor MP3V5004GP
|
||||||
readSwitches();
|
readSwitches();
|
||||||
|
|
|
@ -141,6 +141,7 @@ void dinMIDIsendProgramChange(uint8_t value, uint8_t ch) {
|
||||||
midiSend2B((0xC0 | ch), value);
|
midiSend2B((0xC0 | ch), value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Send sysex commands to wireless module
|
||||||
void dinMIDIsendSysex(const uint8_t data[], const uint8_t length) {
|
void dinMIDIsendSysex(const uint8_t data[], const uint8_t length) {
|
||||||
MIDI_SERIAL.write(0xF0); //Sysex command
|
MIDI_SERIAL.write(0xF0); //Sysex command
|
||||||
for(int i=0; i<length; ++i) {
|
for(int i=0; i<length; ++i) {
|
||||||
|
@ -149,7 +150,6 @@ void dinMIDIsendSysex(const uint8_t data[], const uint8_t length) {
|
||||||
MIDI_SERIAL.write(0xF7); //Sysex end
|
MIDI_SERIAL.write(0xF7); //Sysex end
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void sendWLPower(const uint8_t level) {
|
void sendWLPower(const uint8_t level) {
|
||||||
uint8_t buf[6] = {
|
uint8_t buf[6] = {
|
||||||
0x00, 0x21, 0x11, //Manufacturer id
|
0x00, 0x21, 0x11, //Manufacturer id
|
||||||
|
@ -165,7 +165,6 @@ void sendWLPower(const uint8_t level) {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void sendWLChannel(const uint8_t channel) {
|
void sendWLChannel(const uint8_t channel) {
|
||||||
uint8_t buf[6] = {
|
uint8_t buf[6] = {
|
||||||
0x00, 0x21, 0x11, //Manufacturer id
|
0x00, 0x21, 0x11, //Manufacturer id
|
||||||
|
@ -180,3 +179,26 @@ void sendWLChannel(const uint8_t channel) {
|
||||||
dinMIDIsendSysex(buf, 6);
|
dinMIDIsendSysex(buf, 6);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Translate between "midi data" (only use 7 LSB per byte, big endian) and "teensy data" (little endian)
|
||||||
|
//Only 14 LSB of int value are used (2MSB are discarded), so only works for unsigned data 0-16383
|
||||||
|
|
||||||
|
//NOTE: This assumes code is running on a little-endian CPU, both for real device (Teensy) and simulator.
|
||||||
|
uint16_t midi16to14(uint16_t realdata) {
|
||||||
|
return (realdata & 0x3F80) >>7 | (realdata & 0x007F) <<8;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint16_t midi14to16(uint16_t mididata) {
|
||||||
|
return (mididata & 0x7F00) >> 8 | (mididata & 0x007F) <<7 ;
|
||||||
|
}
|
||||||
|
|
||||||
|
//This is a bit different. MSB of each byte is just discarded (instead of discarding MSB for whole value). Just used for CRC (easier to compare)
|
||||||
|
uint32_t midi32to28(uint32_t realdata) {
|
||||||
|
uint8_t* p = (uint8_t*)&realdata;
|
||||||
|
|
||||||
|
uint32_t r=0;
|
||||||
|
for(int i=0; i<4; ++i) {
|
||||||
|
r = r<<8 | (p[i] & 0x7F);
|
||||||
|
}
|
||||||
|
return r;
|
||||||
|
}
|
||||||
|
|
|
@ -1,6 +1,9 @@
|
||||||
#ifndef __MIDI_H
|
#ifndef __MIDI_H
|
||||||
#define __MIDI_H
|
#define __MIDI_H
|
||||||
|
|
||||||
|
//This is a completely made up "European" SysEx manufacturer ID.
|
||||||
|
static const char sysex_id[] = { 0x00, 0x3e, 0x7f };
|
||||||
|
|
||||||
//Enable use of USB and serial MIDI
|
//Enable use of USB and serial MIDI
|
||||||
#define USE_MIDI_USB
|
#define USE_MIDI_USB
|
||||||
#define USE_MIDI_SERIAL
|
#define USE_MIDI_SERIAL
|
||||||
|
@ -33,4 +36,10 @@ void dinMIDIsendSysex(const uint8_t data[], const uint8_t length);
|
||||||
void sendWLPower(const uint8_t level);
|
void sendWLPower(const uint8_t level);
|
||||||
void sendWLChannel(const uint8_t channel);
|
void sendWLChannel(const uint8_t channel);
|
||||||
|
|
||||||
|
|
||||||
|
//Convert things between "regular data" and MIDI data (byte order and 7-bits-per-byte)
|
||||||
|
uint16_t midi16to14(uint16_t realdata);
|
||||||
|
uint16_t midi14to16(uint16_t mididata);
|
||||||
|
uint32_t midi32to28(uint32_t realdata);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -1,15 +1,18 @@
|
||||||
#include <Arduino.h>
|
#include <Arduino.h>
|
||||||
#include <EEPROM.h>
|
#include <EEPROM.h>
|
||||||
|
#include <Adafruit_SSD1306.h>
|
||||||
|
|
||||||
|
|
||||||
#include "settings.h"
|
#include "settings.h"
|
||||||
#include "globals.h"
|
#include "globals.h"
|
||||||
#include "menu.h"
|
#include "menu.h"
|
||||||
#include "hardware.h"
|
#include "hardware.h"
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
|
#include "midi.h"
|
||||||
|
#include "led.h"
|
||||||
|
|
||||||
//Read settings from eeprom. Returns wether or not anything was written (due to factory reset or upgrade)
|
//Read settings from eeprom. Returns wether or not anything was written (due to factory reset or upgrade)
|
||||||
void readEEPROM() {
|
void readEEPROM(bool factoryReset) {
|
||||||
bool factoryReset = !digitalRead(ePin) && !digitalRead(mPin);
|
|
||||||
|
|
||||||
// if stored settings are not for current version, or Enter+Menu are pressed at startup, they are replaced by factory settings
|
// if stored settings are not for current version, or Enter+Menu are pressed at startup, they are replaced by factory settings
|
||||||
uint16_t settingsVersion = readSetting(VERSION_ADDR);
|
uint16_t settingsVersion = readSetting(VERSION_ADDR);
|
||||||
|
@ -199,3 +202,199 @@ uint16_t readSettingBounded(uint16_t address, uint16_t min, uint16_t max, uint16
|
||||||
}
|
}
|
||||||
return val;
|
return val;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//Functions to send and receive config (and other things) via USB MIDI SysEx messages
|
||||||
|
uint32_t crc32(uint8_t *message, size_t length) {
|
||||||
|
size_t pos=0;
|
||||||
|
uint32_t crc=0xFFFFFFFF;
|
||||||
|
|
||||||
|
while (pos<length) {
|
||||||
|
crc ^= message[pos++]; //Get next byte and increment position
|
||||||
|
for (uint8_t j=0; j<8; ++j) { //Mask off 8 next bits
|
||||||
|
crc = (crc >> 1) ^ (0xEDB88320 & -(crc & 1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ~crc;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
Send EEPROM config dump as sysex message. Message format is structured like this:
|
||||||
|
|
||||||
|
+------------------------------------------------------------------------------------+
|
||||||
|
| vendor(3) | "NuEVIc01" (8) | Payload size (2) | EEPROM data (variable) | crc32 (4) |
|
||||||
|
+------------------------------------------------------------------------------------+
|
||||||
|
|
||||||
|
Payload size is for the EEPROM data chunk (not including anything else before or after
|
||||||
|
CRC32 covers the entire buffer up to and including the eeprom data (but not the checksum itself)
|
||||||
|
|
||||||
|
This currently operates under the assumption that the whole EEPROM chunk only consists of unsigned 16 bit ints, only using the range 0-16383
|
||||||
|
|
||||||
|
*/
|
||||||
|
void sendSysexSettings() {
|
||||||
|
const char *header = "NuEVIc01"; //NuEVI config dump 01
|
||||||
|
|
||||||
|
//Build a send buffer of all the things
|
||||||
|
size_t sysex_size = 3 + strlen(header) + 2 + EEPROM_SIZE + 4;
|
||||||
|
uint8_t *sysex_data = (uint8_t*)malloc(sysex_size);
|
||||||
|
|
||||||
|
//Positions (offsets) of parts in send buffer
|
||||||
|
int header_pos = 3;
|
||||||
|
int size_pos = header_pos + strlen(header);
|
||||||
|
int payload_pos = size_pos + 2;
|
||||||
|
int checksum_pos = payload_pos + EEPROM_SIZE;
|
||||||
|
|
||||||
|
//SysEX manufacturer ID
|
||||||
|
memcpy(sysex_data, sysex_id, 3);
|
||||||
|
|
||||||
|
//Header with command code
|
||||||
|
memcpy(sysex_data+header_pos, header, strlen(header));
|
||||||
|
|
||||||
|
//Payload length
|
||||||
|
*(uint16_t*)(sysex_data+size_pos) = midi16to14(EEPROM_SIZE);
|
||||||
|
|
||||||
|
//Config data
|
||||||
|
uint16_t* config_buffer_start = (uint16_t*)(sysex_data+payload_pos);
|
||||||
|
|
||||||
|
//Read one settings item at a time, change data format, and put in send buffer
|
||||||
|
for(uint16_t idx=0; idx<EEPROM_SIZE/2; idx++) {
|
||||||
|
uint16_t eepromval = readSetting(idx*2);
|
||||||
|
config_buffer_start[idx] = midi16to14(eepromval);
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t checksum = crc32(sysex_data, checksum_pos);
|
||||||
|
|
||||||
|
/*
|
||||||
|
printf("CRC len: %d\n", checksum_pos);
|
||||||
|
printf("CRC32: %X | %u\n", checksum, checksum);
|
||||||
|
*/
|
||||||
|
|
||||||
|
*(uint32_t*)(sysex_data+checksum_pos) = midi32to28(checksum);
|
||||||
|
|
||||||
|
usbMIDI.sendSysEx(sysex_size, sysex_data);
|
||||||
|
|
||||||
|
free(sysex_data);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Send a simple 3-byte message code as sysex
|
||||||
|
void sendSysexMessage(const char* messageCode) {
|
||||||
|
char sysexMessage[] = "vvvNuEVIccc"; //Placeholders for vendor and code
|
||||||
|
|
||||||
|
memcpy(sysexMessage, sysex_id, 3);
|
||||||
|
memcpy(sysexMessage+8, messageCode, 3);
|
||||||
|
|
||||||
|
usbMIDI.sendSysEx(11, (const uint8_t *)sysexMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Send EEPROM and firmware versions
|
||||||
|
void sendSysexVersion() {
|
||||||
|
char sysexMessage[] = "vvvNuEVIc04eevvvvvvvv"; //Placeholders for vendor and code
|
||||||
|
|
||||||
|
memcpy(sysexMessage, sysex_id, 3);
|
||||||
|
memcpy(sysexMessage+13, FIRMWARE_VERSION, min(strlen(FIRMWARE_VERSION), 8));
|
||||||
|
|
||||||
|
*(uint16_t*)(sysexMessage+11) = midi16to14(EEPROM_VERSION);
|
||||||
|
|
||||||
|
uint8_t message_length = 13+strlen(FIRMWARE_VERSION);
|
||||||
|
|
||||||
|
usbMIDI.sendSysEx(message_length, (const uint8_t *)sysexMessage);
|
||||||
|
}
|
||||||
|
|
||||||
|
extern Adafruit_SSD1306 display;
|
||||||
|
|
||||||
|
void configShowMessage(const char* message) {
|
||||||
|
display.fillRect(0,32,128,64,BLACK);
|
||||||
|
display.setCursor(0,32);
|
||||||
|
display.setTextColor(WHITE);
|
||||||
|
|
||||||
|
display.print(message);
|
||||||
|
|
||||||
|
display.display();
|
||||||
|
}
|
||||||
|
|
||||||
|
uint8_t* sysex_rcv_buffer = NULL;
|
||||||
|
|
||||||
|
void handleSysexChunk(const uint8_t *data, uint16_t length, bool last) {
|
||||||
|
size_t pos = 0;
|
||||||
|
|
||||||
|
if(!sysex_rcv_buffer) {
|
||||||
|
//Start out with an empty buffer
|
||||||
|
sysex_rcv_buffer = (uint8_t *)malloc(length);
|
||||||
|
} else {
|
||||||
|
//Increase size of current buffer
|
||||||
|
size_t pos = sizeof(sysex_rcv_buffer);
|
||||||
|
sysex_rcv_buffer = (uint8_t *)realloc(sysex_rcv_buffer, pos + length);
|
||||||
|
}
|
||||||
|
|
||||||
|
//Append this chunk to buffer
|
||||||
|
memcpy(sysex_rcv_buffer + pos, data, length);
|
||||||
|
|
||||||
|
//If it's the last one, call the regular handler to process it
|
||||||
|
if(last) {
|
||||||
|
handleSysex(sysex_rcv_buffer, pos+length);
|
||||||
|
free(sysex_rcv_buffer);
|
||||||
|
sysex_rcv_buffer = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void handleSysex(const uint8_t *data, uint8_t length) {
|
||||||
|
|
||||||
|
//Too short to even contain a 3-byte vendor id is not for us.
|
||||||
|
if(length<3) return;
|
||||||
|
|
||||||
|
//Verify vendor
|
||||||
|
if(strncmp((char*)data, sysex_id, 3)) return; //Silently ignore different vendor id
|
||||||
|
|
||||||
|
//Verify header. Min length is 3+5+3 bytes (vendor+header+message code)
|
||||||
|
if(length<11 || strncmp((char*)(data+3), "NuEVI", 3)) {
|
||||||
|
configShowMessage("Invalid message received.");
|
||||||
|
sendSysexMessage("e00");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Get message code
|
||||||
|
char messageCode[3];
|
||||||
|
strncpy(messageCode, (char*)(data+8), 3);
|
||||||
|
|
||||||
|
if(!strncmp(messageCode, "c00", 3)) { //Config dump request
|
||||||
|
configShowMessage("Sending config...");
|
||||||
|
sendSysexSettings();
|
||||||
|
configShowMessage("Config sent.");
|
||||||
|
} else if(!strncmp(messageCode, "c03", 3)) { //Version info request
|
||||||
|
configShowMessage("Sending version.");
|
||||||
|
sendSysexVersion();
|
||||||
|
} else {
|
||||||
|
configShowMessage("Unknown message.");
|
||||||
|
sendSysexMessage("e01"); //Unimplemented message code
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void configModeSetup() {
|
||||||
|
statusLedFlash(500);
|
||||||
|
|
||||||
|
display.clearDisplay();
|
||||||
|
display.setCursor(0,0);
|
||||||
|
display.setTextColor(WHITE);
|
||||||
|
display.setTextSize(0);
|
||||||
|
|
||||||
|
display.println("Config mgmt");
|
||||||
|
display.println("Power off NuEVI");
|
||||||
|
display.println("to exit");
|
||||||
|
display.display();
|
||||||
|
|
||||||
|
usbMIDI.setHandleSystemExclusive(handleSysexChunk);
|
||||||
|
|
||||||
|
statusLedFlash(500);
|
||||||
|
|
||||||
|
configShowMessage("Ready.");
|
||||||
|
}
|
||||||
|
|
||||||
|
//"Main loop". Just sits and wait for midi messages and lets the sysex handler do all the work.
|
||||||
|
void configModeLoop() {
|
||||||
|
usbMIDI.read();
|
||||||
|
}
|
||||||
|
|
|
@ -56,6 +56,7 @@
|
||||||
#define TRILL3_INTERVAL_ADDR 98
|
#define TRILL3_INTERVAL_ADDR 98
|
||||||
#define DAC_MODE_ADDR 100
|
#define DAC_MODE_ADDR 100
|
||||||
|
|
||||||
|
#define EEPROM_SIZE 102
|
||||||
|
|
||||||
|
|
||||||
//DAC output modes
|
//DAC output modes
|
||||||
|
@ -121,11 +122,24 @@
|
||||||
#define DAC_MODE_FACTORY DAC_MODE_BREATH
|
#define DAC_MODE_FACTORY DAC_MODE_BREATH
|
||||||
|
|
||||||
|
|
||||||
void readEEPROM();
|
void readEEPROM(bool factoryReset);
|
||||||
void setBit(uint16_t &bitfield, const uint8_t pos, const uint16_t value);
|
void setBit(uint16_t &bitfield, const uint8_t pos, const uint16_t value);
|
||||||
uint16_t readSetting(uint16_t address);
|
uint16_t readSetting(uint16_t address);
|
||||||
void writeSetting(uint16_t address, uint16_t value);
|
void writeSetting(uint16_t address, uint16_t value);
|
||||||
uint16_t readSettingBounded(uint16_t address, uint16_t min, uint16_t max, uint16_t defaultValue);
|
uint16_t readSettingBounded(uint16_t address, uint16_t min, uint16_t max, uint16_t defaultValue);
|
||||||
|
|
||||||
|
//Functions for config management mode
|
||||||
|
void sendSysexSettings();
|
||||||
|
void sendSysexMessage(const char* messageCode);
|
||||||
|
void sendSysexVersion();
|
||||||
|
|
||||||
|
void handleSysex(uint8_t *data, uint8_t length);
|
||||||
|
uint32_t crc32(uint8_t *message, size_t length);
|
||||||
|
|
||||||
|
void configInitScreen();
|
||||||
|
void configShowMessage(const char* message);
|
||||||
|
|
||||||
|
void configModeSetup();
|
||||||
|
void configModeLoop();
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -85,6 +85,8 @@ public:
|
||||||
void sendPitchBend(int value, uint8_t channel, uint8_t cable=0);
|
void sendPitchBend(int value, uint8_t channel, uint8_t cable=0);
|
||||||
void sendSysEx(uint16_t length, const uint8_t *data, bool hasTerm=false, uint8_t cable=0);
|
void sendSysEx(uint16_t length, const uint8_t *data, bool hasTerm=false, uint8_t cable=0);
|
||||||
bool read(uint8_t channel=0);
|
bool read(uint8_t channel=0);
|
||||||
|
void setHandleSystemExclusive(__unused void (*fptr) (const uint8_t *array, uint8_t size));
|
||||||
|
void setHandleSystemExclusive(__unused void (*fptr) (const uint8_t *data, uint16_t length, bool complete));
|
||||||
};
|
};
|
||||||
|
|
||||||
extern SimSerial Serial;
|
extern SimSerial Serial;
|
||||||
|
|
|
@ -21,7 +21,7 @@
|
||||||
// Forward declarations
|
// Forward declarations
|
||||||
static void SimQuit(void);
|
static void SimQuit(void);
|
||||||
static int SimInit(void);
|
static int SimInit(void);
|
||||||
static int SimRun(std::string eepromFile, bool eepromWrite, bool factoryReset);
|
static int SimRun(std::string eepromFile, bool eepromWrite, bool factoryReset, bool ConfigMode);
|
||||||
static void SimLoop(std::function<bool()>, std::function<void()>);
|
static void SimLoop(std::function<bool()>, std::function<void()>);
|
||||||
|
|
||||||
|
|
||||||
|
@ -39,6 +39,8 @@ static const int scale = 3;
|
||||||
|
|
||||||
static SDL_Window *window;
|
static SDL_Window *window;
|
||||||
|
|
||||||
|
bool no_delay = false;
|
||||||
|
|
||||||
void _reboot_Teensyduino_()
|
void _reboot_Teensyduino_()
|
||||||
{
|
{
|
||||||
// TODO: reboot
|
// TODO: reboot
|
||||||
|
@ -81,6 +83,8 @@ uint8_t digitalRead(uint8_t pin) {
|
||||||
|
|
||||||
void delay(unsigned int ms)
|
void delay(unsigned int ms)
|
||||||
{
|
{
|
||||||
|
if(no_delay) return;
|
||||||
|
|
||||||
uint32_t endTick = SDL_GetTicks() + ms;
|
uint32_t endTick = SDL_GetTicks() + ms;
|
||||||
auto checktime = [endTick]() -> bool { return endTick > SDL_GetTicks(); };
|
auto checktime = [endTick]() -> bool { return endTick > SDL_GetTicks(); };
|
||||||
SimLoop(checktime,NULL);
|
SimLoop(checktime,NULL);
|
||||||
|
@ -508,7 +512,7 @@ static void SimLoop(std::function<bool()> continue_predicate, std::function<void
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int SimRun(std::string eepromFile, bool eepromWrite, bool factoryReset)
|
static int SimRun(std::string eepromFile, bool eepromWrite, bool factoryReset, bool configMode)
|
||||||
{
|
{
|
||||||
if( 0 != SimInit() ) { return 1; }
|
if( 0 != SimInit() ) { return 1; }
|
||||||
|
|
||||||
|
@ -523,11 +527,19 @@ static int SimRun(std::string eepromFile, bool eepromWrite, bool factoryReset)
|
||||||
digitalInputs[ePin] = 0;
|
digitalInputs[ePin] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Go into config management mode. This should not happen (in NuEVI) if factory reset is done
|
||||||
|
if(configMode) {
|
||||||
|
digitalInputs[uPin] = 0;
|
||||||
|
digitalInputs[dPin] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
setup();
|
setup();
|
||||||
|
|
||||||
//Let it go, let it go, not resetting any more
|
//Let it go, let it go, not resetting any more
|
||||||
digitalInputs[mPin] = 1;
|
digitalInputs[mPin] = 1;
|
||||||
digitalInputs[ePin] = 1;
|
digitalInputs[ePin] = 1;
|
||||||
|
digitalInputs[uPin] = 1;
|
||||||
|
digitalInputs[dPin] = 1;
|
||||||
|
|
||||||
SimLoop( []() -> bool { return true; }, loop );
|
SimLoop( []() -> bool { return true; }, loop );
|
||||||
SimQuit();
|
SimQuit();
|
||||||
|
@ -616,6 +628,8 @@ int main(int argc, const char** argv)
|
||||||
args::ValueFlag<std::string> eepromFile(parser, "eeprom-write", "File to use for EEPROM data", {'e', "eeprom-file"});
|
args::ValueFlag<std::string> eepromFile(parser, "eeprom-write", "File to use for EEPROM data", {'e', "eeprom-file"});
|
||||||
args::Flag eepromWrite(parser, "eeprom-write", "Write EEPROM changes to file", {'w', "eeprom-write"});
|
args::Flag eepromWrite(parser, "eeprom-write", "Write EEPROM changes to file", {'w', "eeprom-write"});
|
||||||
args::Flag factoryReset(parser, "factory-reset", "Trigger factory reset", {'r', "factory-reset"});
|
args::Flag factoryReset(parser, "factory-reset", "Trigger factory reset", {'r', "factory-reset"});
|
||||||
|
args::Flag configMode(parser, "config-mode", "Trigger config-management mode", {'c', "config-mode"});
|
||||||
|
args::Flag nodelay(parser, "nodelay", "Skip all delays when running", {'n', "nodelay"});
|
||||||
|
|
||||||
parser.ParseCLI(argc, argv);
|
parser.ParseCLI(argc, argv);
|
||||||
|
|
||||||
|
@ -628,5 +642,7 @@ int main(int argc, const char** argv)
|
||||||
eepromFileName += "eeprom.bin";
|
eepromFileName += "eeprom.bin";
|
||||||
}
|
}
|
||||||
|
|
||||||
return SimRun(eepromFileName, args::get(eepromWrite), args::get(factoryReset));
|
no_delay = args::get(nodelay);
|
||||||
|
|
||||||
|
return SimRun(eepromFileName, args::get(eepromWrite), args::get(factoryReset), args::get(configMode));
|
||||||
}
|
}
|
||||||
|
|
|
@ -58,3 +58,12 @@ bool SimUsbMidi::read(uint8_t __unused channel) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Regular sysex handler
|
||||||
|
void SimUsbMidi::setHandleSystemExclusive(__unused void (*fptr) (const uint8_t *array, uint8_t size)) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
//"Chunked" sysex handler (teensy extension), for large messages
|
||||||
|
void SimUsbMidi::setHandleSystemExclusive(__unused void (*fptr) (const uint8_t *array, uint16_t size, bool last)) {
|
||||||
|
|
||||||
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue