diff --git a/README.md b/README.md index a7de5110..eac9900b 100644 --- a/README.md +++ b/README.md @@ -3,5 +3,5 @@ LinnStrument This is the firmware for LinnStrument, running on an Arduino Due processor. -These sources assume that you're using Arduino IDE with SAM boards v1.6.4. +These sources assume that you're using Arduino IDE v1.6.12 with SAM boards v1.6.4. Different versions of this package might create unknown build and execution problems. \ No newline at end of file diff --git a/linnstrument-firmware.ino b/linnstrument-firmware.ino index 016edb02..498e6fee 100644 --- a/linnstrument-firmware.ino +++ b/linnstrument-firmware.ino @@ -825,9 +825,11 @@ const int PROJECT_VERSION_MARKER_SIZE = 4; const int PROJECT_INDEXES_COUNT = 20; const int PROJECTS_MARKERS_SIZE = alignToByteBoundary(PROJECT_VERSION_MARKER_SIZE + 2 * PROJECT_INDEXES_COUNT); // one version marker, two series on indexes for project references const int SINGLE_PROJECT_SIZE = alignToByteBoundary(sizeof(SequencerProject)); -const int ALL_PROJECTS_SIZE = PROJECTS_MARKERS_SIZE + 17*SINGLE_PROJECT_SIZE; +const int ALL_PROJECTS_SIZE = PROJECTS_MARKERS_SIZE + (MAX_PROJECTS + 1)*SINGLE_PROJECT_SIZE; const int SETTINGS_OFFSET = PROJECTS_OFFSET + alignToByteBoundary(ALL_PROJECTS_SIZE); +#define PROJECT_INDEX_OFFSET(marker, index) (PROJECTS_OFFSET + PROJECT_VERSION_MARKER_SIZE + marker * PROJECT_INDEXES_COUNT + index) + /**************************************** FIXED POINT MATH ***************************************/ diff --git a/ls_serial.ino b/ls_serial.ino index ca98dd20..84671798 100644 --- a/ls_serial.ino +++ b/ls_serial.ino @@ -19,7 +19,9 @@ boolean waitingForCommands = false; enum linnCommands { SendSettings = 's', RestoreSettings = 'r', - LightLed = 'l' + LightLed = 'l', + SendProjects = 'p', + RestoreProject = 'q' }; byte codePos = 0; @@ -55,6 +57,18 @@ void handleSerialIO() { break; } + case SendProjects: + { + serialSendProjects(); + break; + } + + case RestoreProject: + { + serialRestoreProject(); + break; + } + default: { waitingForCommands = false; @@ -89,6 +103,13 @@ void handleSerialIO() { } } +boolean waitForSerialAck() { + if (!serialWaitForMaximumTwoSeconds()) return false; + char ack = Serial.read(); + if (ack != 'a') return false; + return true; +} + void serialSendSettings() { Serial.write(ackCode); @@ -98,14 +119,22 @@ void serialSendSettings() { int32_t confSize = sizeof(Configuration); // send the size of the settings - byte buff1[sizeof(int32_t)]; - memcpy(buff1, &confSize, sizeof(int32_t)); - Serial.write(buff1, sizeof(int32_t)); + Serial.write((byte*)&confSize, sizeof(int32_t)); // send the actual settings - byte buff2[confSize]; - memcpy(buff2, &config, confSize); - Serial.write(buff2, confSize); + const uint8_t batchsize = 96; + byte* src = (byte*)&config; + lastSerialMoment = millis(); + while (confSize > 0) { + int actual = min(confSize, batchsize); + Serial.write(src, actual); + + confSize -= actual; + src += actual; + + if (!waitForSerialAck()) return; + lastSerialMoment = millis(); + } Serial.write(ackCode); } @@ -146,35 +175,25 @@ void serialRestoreSettings() { Serial.write(ackCode); - // retrieve the actual settings - const uint8_t batchsize = 32; + // restore the actual settings + uint32_t projectOffset = SETTINGS_OFFSET; + const uint8_t batchsize = 96; byte buff2[batchsize]; lastSerialMoment = millis(); - int32_t j = 0; - while(j+batchsize < settingsSize) { - for (byte k = 0; k < batchsize; ++k) { + int32_t remaining = settingsSize; + while (remaining > 0) { + int actual = min(remaining, batchsize); + for (byte k = 0; k < actual; ++k) { if (!serialWaitForMaximumTwoSeconds()) return; // read the next byte of the configuration data buff2[k] = Serial.read(); lastSerialMoment = millis(); } - dueFlashStorage.write(SETTINGS_OFFSET + j, buff2, batchsize); - - j += batchsize; - Serial.write(ackCode); - } - - size_t remaining = settingsSize - j; - if (remaining > 0) { - for (byte k = 0; k < remaining; ++k) { - if (!serialWaitForMaximumTwoSeconds()) return; - // read the next byte of the configuration data - buff2[k] = Serial.read(); - lastSerialMoment = millis(); - } + dueFlashStorage.write(projectOffset, buff2, actual); - dueFlashStorage.write(SETTINGS_OFFSET + j, buff2, remaining); + remaining -= actual; + projectOffset += actual; Serial.write(ackCode); } @@ -228,3 +247,106 @@ void serialLightLed() { updateDisplay(); } + +void serialSendProjects() { + Serial.write(ackCode); + + clearDisplayImmediately(); + delayUsec(1000); + + // send the count of projects + Serial.write((byte)MAX_PROJECTS); + + // send the size of a project + int32_t projectSize = sizeof(SequencerProject); + Serial.write((byte*)&projectSize, sizeof(int32_t)); + + // send the actual projects + byte marker = dueFlashStorage.read(PROJECTS_OFFSET); + + lastSerialMoment = millis(); + + // send the actual settings + const uint8_t batchsize = 96; + + for (byte p = 0; p < MAX_PROJECTS; ++p) { + byte prjIndex = dueFlashStorage.read(PROJECT_INDEX_OFFSET(marker, p)); + uint32_t projectOffset = PROJECTS_OFFSET + PROJECTS_MARKERS_SIZE + prjIndex * SINGLE_PROJECT_SIZE; + int32_t remaining = projectSize; + + byte* src = (byte*)dueFlashStorage.readAddress(projectOffset); + while (remaining > 0) { + int actual = min(remaining, batchsize); + Serial.write(src, actual); + + remaining -= actual; + src += actual; + + if (!waitForSerialAck()) return; + lastSerialMoment = millis(); + } + } + + Serial.write(ackCode); +} + +void serialRestoreProject() { + Serial.write(ackCode); + + clearDisplayImmediately(); + delayUsec(1000); + + // retrieve the size of a project + lastSerialMoment = millis(); + + byte buff1[sizeof(int32_t)]; + for (byte i = 0; i < 4; ++i) { + if (!serialWaitForMaximumTwoSeconds()) return; + + // read the next byte of the configuration size + buff1[i] = Serial.read(); + lastSerialMoment = millis(); + } + + int32_t projectSize; + memcpy(&projectSize, buff1, sizeof(int32_t)); + + if (projectSize != sizeof(SequencerProject)) return; + + Serial.write(ackCode); + + if (!serialWaitForMaximumTwoSeconds()) return; + + uint8_t p = Serial.read(); + Serial.write(ackCode); + + // write the actual project + byte marker = dueFlashStorage.read(PROJECTS_OFFSET); + byte prjIndex = dueFlashStorage.read(PROJECT_INDEX_OFFSET(marker, p)); + uint32_t projectOffset = PROJECTS_OFFSET + PROJECTS_MARKERS_SIZE + prjIndex * SINGLE_PROJECT_SIZE; + + const uint8_t batchsize = 96; + byte buff2[batchsize]; + lastSerialMoment = millis(); + int32_t remaining = projectSize; + while (remaining > 0) { + int actual = min(remaining, batchsize); + for (byte k = 0; k < actual; ++k) { + if (!serialWaitForMaximumTwoSeconds()) return; + // read the next byte of the configuration data + buff2[k] = Serial.read(); + lastSerialMoment = millis(); + } + + dueFlashStorage.write(projectOffset, buff2, actual); + + remaining -= actual; + projectOffset += actual; + + Serial.write(ackCode); + } + + // finished + Serial.write(ackCode); + delayUsec(500000); +} diff --git a/ls_settings.ino b/ls_settings.ino index 7ddbd4ac..e8421795 100644 --- a/ls_settings.ino +++ b/ls_settings.ino @@ -170,8 +170,6 @@ void loadSettings() { memcpy(&config, dueFlashStorage.readAddress(SETTINGS_OFFSET+sizeof(unsigned long)+configOffset), sizeof(Configuration)); } -#define PROJECT_INDEX_OFFSET(marker, index) (PROJECTS_OFFSET + PROJECT_VERSION_MARKER_SIZE + marker * PROJECT_INDEXES_COUNT + index) - void writeInitialProjectSettings() { dueFlashStorage.write(PROJECTS_OFFSET, 0); @@ -180,7 +178,7 @@ void writeInitialProjectSettings() { dueFlashStorage.write(PROJECT_INDEX_OFFSET(1, i), i); } - for (byte p = 0; p < 17; ++p) { + for (byte p = 0; p <= MAX_PROJECTS; ++p) { writeProjectToFlashRaw(p); } } @@ -208,7 +206,7 @@ void writeProjectToFlash(byte project) { // read the location of the temporary project storage byte previousIndexes[PROJECT_INDEXES_COUNT]; memcpy(&previousIndexes, dueFlashStorage.readAddress(PROJECT_INDEX_OFFSET(marker, 0)), PROJECT_INDEXES_COUNT); - byte tmpIndex = previousIndexes[16]; + byte tmpIndex = previousIndexes[MAX_PROJECTS]; byte prjIndex = previousIndexes[project]; writeProjectToFlashRaw(tmpIndex); @@ -216,7 +214,7 @@ void writeProjectToFlash(byte project) { // write the marker after the project data so that this version becomes to latest coherent one byte newMarker = 1 - marker; previousIndexes[project] = tmpIndex; - previousIndexes[16] = prjIndex; + previousIndexes[MAX_PROJECTS] = prjIndex; dueFlashStorage.write(PROJECT_INDEX_OFFSET(newMarker, 0), previousIndexes, PROJECT_INDEXES_COUNT); dueFlashStorage.write(PROJECTS_OFFSET, newMarker);