#include "XRConfig.h" #include "XRDisplay.h" #include "XRSequenceInstrumentTrack.h" #include "XRSequenceInstrumentTrackProgram.h" #include <Arduino.h> EXTMEM ILI9341_t3n tft = ILI9341_t3n(TFT_CS, TFT_DC, TFT_RST); EXTMEM elapsedMillis runtime; DMAMEM DynamicJsonDocument doc(10000); std::vector<SequenceInstrumentTrack *> unmarshalInstrumentTracks(); SequenceInstrumentTrack * unmarshalInstrumentTrack(); SequenceInstrumentTrackProgram * unmarshalInstrumentTrackProgram(); void handleDisplayState(int displayState); void setup() { Serial.begin(BAUD_RATE); Serial5.begin(250000); delay(2000); Serial.println("Display intro..."); Display::init(tft); // set backlight pinMode(7, OUTPUT); analogWrite(7, 30); Display::drawIntroScreen(tft); } void loop() { if (Serial5.available()) { Serial.println("command received"); DeserializationError err = deserializeJson(doc, Serial5); if (err == DeserializationError::Ok) { Serial.println("command OK"); int drawDisplayState = doc["drawDisplayState"].as<int>(); Serial.print("JSON doc memory usage: "); Serial.println(doc.memoryUsage()); handleDisplayState(drawDisplayState); doc.clear(); } else { // Print error to the "debug" serial port Serial.print("deserializeJson() returned "); Serial.println(err.c_str()); // Flush all bytes in the "TX" serial port buffer while (Serial5.available() > 0) { Serial5.read(); } } } } void handleDisplayState (int displayState) { Serial.print("displayState: "); Serial.println(displayState); switch (displayState) { case DISPLAY_STATE_MAIN: case DISPLAY_STATE_MAIN_REFRESH_PRG: case DISPLAY_STATE_MAIN_REFRESH_PRG_CURSOR: case DISPLAY_STATE_MAIN_REFRESH_PRG_CURSOR_RUNNING: { std::vector<SequenceInstrumentTrack *> trks = unmarshalInstrumentTracks(); Display::drawMainScreen( tft, doc["currInstrument"].as<unsigned int>(), trks, (displayState == DISPLAY_STATE_MAIN_REFRESH_PRG || displayState == DISPLAY_STATE_MAIN_REFRESH_PRG_CURSOR || displayState == DISPLAY_STATE_MAIN_REFRESH_PRG_CURSOR_RUNNING), doc["tempo"].as<uint16_t>(), doc["selProgram"].as<unsigned int>(), (displayState == DISPLAY_STATE_MAIN_REFRESH_PRG_CURSOR), doc["isSequencerRunning"].as<bool>() ); for (auto trk : trks) { delete trk; } break; } case DISPLAY_STATE_INSTRUMENT_CONFIG_OPEN: { SequenceInstrumentTrack *trk = unmarshalInstrumentTrack(); Display::drawInstrumentConfigWindow( tft, trk, doc["currConfigPropIdx"].as<unsigned int>() ); delete trk; break; } case DISPLAY_STATE_INSTRUMENT_CONFIG_PAGE_RIGHT: { SequenceInstrumentTrack *trk = unmarshalInstrumentTrack(); Display::drawInstrumentConfigPropWindow( tft, trk, doc["currConfigPropIdx"].as<unsigned int>(), doc["currConfigPropSettingIdx"].as<unsigned int>() ); delete trk; break; } case DISPLAY_STATE_PROGRAM_CONFIG_OPEN: { SequenceInstrumentTrackProgram *prg = unmarshalInstrumentTrackProgram(); Display::drawProgramConfigWindow( tft, prg, doc["currInstrument"].as<unsigned int>(), doc["currCursoredProgramIdx"].as<unsigned int>(), doc["currPrgConfigPropIdx"].as<unsigned int>() ); delete prg; break; } case DISPLAY_STATE_PROGRAM_CONFIG_PAGE_RIGHT: { SequenceInstrumentTrackProgram *prg = unmarshalInstrumentTrackProgram(); Display::drawProgramConfigPropWindow( tft, prg, doc["currPrgConfigPropIdx"].as<unsigned int>(), doc["currPrgConfigPropSettingIdx"].as<unsigned int>() ); delete prg; break; } case DISPLAY_STATE_TEMPO_SCREEN: Display::drawTempoScreen(tft, doc["tempo"].as<uint16_t>()); break; case DISPLAY_STATE_WARN: Display::drawWarn(tft, doc["warnMsg"].as<const char*>()); break; default: break; } } std::vector<SequenceInstrumentTrack *> unmarshalInstrumentTracks() { std::vector<SequenceInstrumentTrack *> instrumentTracks; if (!doc["instrumentTracks"].isNull()) { JsonArray instrumentTracksArr = doc["instrumentTracks"].as<JsonArray>(); instrumentTracks.reserve(INSTRUMENT_TRACK_LIMIT); int idx = 1; for (unsigned int i = 0; i < instrumentTracksArr.size(); ++i) { std::vector<SequenceInstrumentTrackProgram *> instrumentTrackPrograms; JsonObject instrumentTrackObj = instrumentTracksArr.getElement(i); auto *instrumentTrack = new SequenceInstrumentTrack (idx); instrumentTrack->deviceActive = instrumentTrackObj["deviceActive"]; instrumentTrack->stopped = instrumentTrackObj["stopped"]; instrumentTrack->barsElapsed = instrumentTrackObj["barsElapsed"]; instrumentTrack->device = instrumentTrackObj["device"]; instrumentTrack->loop = instrumentTrackObj["loop"]; instrumentTrack->currentTrackProgramNum = instrumentTrackObj["currentTrackProgramNum"]; instrumentTrack->currentTrackProgramIndex = instrumentTrackObj["currentTrackProgramIndex"]; if (!instrumentTrackObj["instrumentTrackPrograms"].isNull()) { JsonArray instrumentTrackProgramsArr = instrumentTrackObj["instrumentTrackPrograms"]; instrumentTrackPrograms.reserve(instrumentTrackProgramsArr.size()); int prIdx = 1; for (int j = 0; j < instrumentTrackProgramsArr.size(); ++j) { JsonObject instrumentTrackProgramObj = instrumentTrackProgramsArr.getElement(j); auto *instrumentTrackProgram = new SequenceInstrumentTrackProgram (idx, prIdx); instrumentTrackProgram->trackIndex = instrumentTrackProgramObj["trackIndex"]; instrumentTrackProgram->pIndex = instrumentTrackProgramObj["pIndex"]; instrumentTrackProgram->bankNumber = instrumentTrackProgramObj["bankNumber"]; instrumentTrackProgram->programNumber = instrumentTrackProgramObj["programNumber"]; instrumentTrackProgram->barLength = instrumentTrackProgramObj["barLength"]; instrumentTrackProgram->state = instrumentTrackProgramObj["state"]; //instrumentTrackProgram->lastStep = instrumentTrackProgramObj["lastStep"]; instrumentTrackPrograms.push_back(instrumentTrackProgram); ++prIdx; } } instrumentTrack->instrumentTrackPrograms = instrumentTrackPrograms; // TODO: remove this, used for debugging // Serial.print("instrumentTrackPrograms size: "); // Serial.println(instrumentTrack->instrumentTrackPrograms.size()); instrumentTracks.push_back(instrumentTrack); ++idx; } // TODO: remove this, used for debugging // Serial.print("instrumentTracksArr size (get element count): "); // Serial.println(instrumentTracksArr.size()); } return instrumentTracks; } SequenceInstrumentTrack* unmarshalInstrumentTrack() { auto instrumentTrack = new SequenceInstrumentTrack(doc["instrumentTrack"]["tIndex"].as<unsigned int>()); // Serial.print("instrumentTrack->tIndex: "); // Serial.println(instrumentTrack->tIndex); std::vector<SequenceInstrumentTrackProgram *> instrumentTrackPrograms; if (!doc["instrumentTrack"].isNull()) { JsonObject instrumentTrackObj = doc["instrumentTrack"]; instrumentTrack->deviceActive = instrumentTrackObj["deviceActive"]; instrumentTrack->trackActive = instrumentTrackObj["trackActive"]; instrumentTrack->stopped = instrumentTrackObj["stopped"]; instrumentTrack->barsElapsed = instrumentTrackObj["barsElapsed"]; instrumentTrack->currLastStep = instrumentTrackObj["currLastStep"]; instrumentTrack->device = instrumentTrackObj["device"]; instrumentTrack->channel = instrumentTrackObj["channel"]; instrumentTrack->cue = instrumentTrackObj["cue"]; instrumentTrack->loop = instrumentTrackObj["loop"]; instrumentTrack->force = instrumentTrackObj["force"]; instrumentTrack->currentTrackProgramNum = instrumentTrackObj["currentTrackProgramNum"]; instrumentTrack->currentTrackProgramIndex = instrumentTrackObj["currentTrackProgramIndex"]; instrumentTrack->currentTrackStepIndex = instrumentTrackObj["currentTrackStepIndex"]; instrumentTrack->currentTrackStepPreciseIndex = instrumentTrackObj["currentTrackStepPreciseIndex"]; if (!instrumentTrackObj["instrumentTrackPrograms"].isNull()) { JsonArray instrumentTrackProgramsArr = instrumentTrackObj["instrumentTrackPrograms"]; instrumentTrackPrograms.reserve(instrumentTrackProgramsArr.size()); int prIdx = 1; for (int j = 0; j < instrumentTrackProgramsArr.size(); ++j) { JsonObject instrumentTrackProgramObj = instrumentTrackProgramsArr.getElement(j); auto *instrumentTrackProgram = new SequenceInstrumentTrackProgram( instrumentTrackObj["tIndex"], prIdx ); instrumentTrackProgram->trackIndex = instrumentTrackProgramObj["trackIndex"]; instrumentTrackProgram->pIndex = instrumentTrackProgramObj["pIndex"]; instrumentTrackProgram->bankNumber = instrumentTrackProgramObj["bankNumber"]; instrumentTrackProgram->programNumber = instrumentTrackProgramObj["programNumber"]; instrumentTrackProgram->barLength = instrumentTrackProgramObj["barLength"]; instrumentTrackProgram->state = instrumentTrackProgramObj["state"]; instrumentTrackProgram->lastStep = instrumentTrackProgramObj["lastStep"]; instrumentTrackPrograms.push_back(instrumentTrackProgram); ++prIdx; } // TODO: remove this, used for debugging // Serial.print("instrumentTrackProgramsArr size (get element count): "); // Serial.println(instrumentTrackProgramsArr.size()); } } return instrumentTrack; } SequenceInstrumentTrackProgram* unmarshalInstrumentTrackProgram() { auto instrumentTrackProgram = new SequenceInstrumentTrackProgram( doc["trackIdx"].as<unsigned int>(), doc["prgIdx"].as<unsigned int>() ); if (!doc["instrumentTrackProgram"].isNull()) { JsonObject instrumentTrackProgramObj = doc["instrumentTrackProgram"]; instrumentTrackProgram->trackIndex = instrumentTrackProgramObj["trackIndex"]; instrumentTrackProgram->pIndex = instrumentTrackProgramObj["pIndex"]; instrumentTrackProgram->bankNumber = instrumentTrackProgramObj["bankNumber"]; instrumentTrackProgram->programNumber = instrumentTrackProgramObj["programNumber"]; instrumentTrackProgram->barLength = instrumentTrackProgramObj["barLength"]; instrumentTrackProgram->state = instrumentTrackProgramObj["state"]; instrumentTrackProgram->lastStep = instrumentTrackProgramObj["lastStep"]; } return instrumentTrackProgram; }