Skip to content

Commit

Permalink
Added capability to send and receive sequencer projects over serial, …
Browse files Browse the repository at this point in the history
…which is now being used by the update application.

Made the serial transmission more robust.
  • Loading branch information
gbevin committed Oct 13, 2016
1 parent 55a6618 commit c7d0a3e
Show file tree
Hide file tree
Showing 4 changed files with 156 additions and 34 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
4 changes: 3 additions & 1 deletion linnstrument-firmware.ino
Original file line number Diff line number Diff line change
Expand Up @@ -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 ***************************************/

Expand Down
176 changes: 149 additions & 27 deletions ls_serial.ino
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@ boolean waitingForCommands = false;
enum linnCommands {
SendSettings = 's',
RestoreSettings = 'r',
LightLed = 'l'
LightLed = 'l',
SendProjects = 'p',
RestoreProject = 'q'
};

byte codePos = 0;
Expand Down Expand Up @@ -55,6 +57,18 @@ void handleSerialIO() {
break;
}

case SendProjects:
{
serialSendProjects();
break;
}

case RestoreProject:
{
serialRestoreProject();
break;
}

default:
{
waitingForCommands = false;
Expand Down Expand Up @@ -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);

Expand All @@ -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);
}
Expand Down Expand Up @@ -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);
}
Expand Down Expand Up @@ -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);
}
8 changes: 3 additions & 5 deletions ls_settings.ino
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand All @@ -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);
}
}
Expand Down Expand Up @@ -208,15 +206,15 @@ 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);

// 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);

Expand Down

0 comments on commit c7d0a3e

Please sign in to comment.