Skip to content

Commit

Permalink
Revised and much improved firmware update process.
Browse files Browse the repository at this point in the history
  • Loading branch information
gbevin committed Oct 13, 2016
1 parent 0993521 commit 55a6618
Show file tree
Hide file tree
Showing 7 changed files with 277 additions and 168 deletions.
26 changes: 24 additions & 2 deletions linnstrument-firmware.ino
Original file line number Diff line number Diff line change
Expand Up @@ -698,7 +698,6 @@ struct GlobalSettings {
struct PresetSettings {
GlobalSettings global;
SplitSettings split[NUMSPLITS];
SplitSettings sequencer[NUMSPLITS];
};

enum SequencerStepSize {
Expand Down Expand Up @@ -811,6 +810,25 @@ enum OperatingMode {
OperatingMode operatingMode = modePerformance;


/************************************** FLASH STORAGE LAYOUT *************************************/

static int alignToByteBoundary(int value) {
if (value % 4 == 0) {
return value;
}

return ((value / 4) + 1) * 4;
}

const int PROJECTS_OFFSET = 4;
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 SETTINGS_OFFSET = PROJECTS_OFFSET + alignToByteBoundary(ALL_PROJECTS_SIZE);


/**************************************** FIXED POINT MATH ***************************************/

#define FXD_FBITS 8
Expand Down Expand Up @@ -1274,6 +1292,9 @@ void setup() {

setupDone = true;

applySerialMode();
performContinuousTasks(micros());

// if the promo animation was running last time the LinnStrument was on, start it up automatically
if (Device.promoAnimationActive) {
playPromoAnimation();
Expand Down Expand Up @@ -1302,7 +1323,8 @@ void loop() {
inline void modeLoopPerformance() {
if (displayMode == displayReset) { // if reset is active, don't process any input data
if (calcTimeDelta(millis(), lastReset) > 3000) { // restore normal operations three seconds after the reset started
applyConfiguration();
applySystemState();

storeSettings();
setDisplayMode(displayNormal); // this should make the reset operation feel more predictable
updateDisplay();
Expand Down
1 change: 0 additions & 1 deletion ls_displayModes.ino
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@ displaySplitPoint : split point
displayGlobal : global settings
displayGlobalWithTempo : global settings with tempo
displayOsVersion : version number of the OS
displayOsVersionSUb : sub-version number of the OS
displayCalibration : calibration process
displayReset : global reset confirmation and wait for touch release
displayBendRange ; custom bend range selection for X expression
Expand Down
329 changes: 210 additions & 119 deletions ls_extstorage.ino

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions ls_midi.ino
Original file line number Diff line number Diff line change
Expand Up @@ -61,12 +61,12 @@ void applyMidiIo() {
}

if (isMidiUsingDIN()) {
digitalWrite(36, 0); // Set LOW for DIN jacks
digitalWrite(36, LOW); // Set LOW for DIN jacks
Serial.begin(31250); // set serial port at MIDI DIN speed 31250
Serial.flush(); // clear the serial port
}
else {
digitalWrite(36, 1); // Set HIGH for USB
digitalWrite(36, HIGH); // Set HIGH for USB
Serial.begin(115200); // set serial port at fastest speed 115200
Serial.flush(); // clear the serial port
}
Expand Down
3 changes: 2 additions & 1 deletion ls_rtos.ino
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ inline void performCheckAdvanceSequencer() {
}

inline void performContinuousTasks(unsigned long nowMicros) {
if (displayMode == displaySleep) {
if (!setupDone || displayMode == displaySleep) {
return;
}

Expand All @@ -70,6 +70,7 @@ inline void performContinuousTasks(unsigned long nowMicros) {
ledsRefreshed = checkRefreshLedColumn(nowMicros);
continuousRefreshLeds = false;
}

if (ledsRefreshed) {
unsigned long nowMillis = millis();

Expand Down
44 changes: 32 additions & 12 deletions ls_serial.ino
Original file line number Diff line number Diff line change
Expand Up @@ -141,25 +141,45 @@ void serialRestoreSettings() {
lastSerialMoment = millis();
}

int32_t confSize;
memcpy(&confSize, buff1, sizeof(int32_t));
int32_t settingsSize;
memcpy(&settingsSize, buff1, sizeof(int32_t));

Serial.write(ackCode);

// retrieve the actual settings
const uint8_t batchsize = 32;
byte buff2[batchsize];
lastSerialMoment = millis();
byte buff2[confSize];
for (int32_t j = 0; j < confSize; ++j) {
if (j % 32 == 0) {
Serial.write(ackCode);
int32_t j = 0;
while(j+batchsize < settingsSize) {
for (byte k = 0; k < batchsize; ++k) {
if (!serialWaitForMaximumTwoSeconds()) return;
// read the next byte of the configuration data
buff2[k] = Serial.read();
lastSerialMoment = millis();
}

if (!serialWaitForMaximumTwoSeconds()) return;

// read the next byte of the configuration data
buff2[j] = 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(SETTINGS_OFFSET + j, buff2, remaining);

Serial.write(ackCode);
}

boolean settingsApplied = upgradeConfigurationSettings(confSize, buff2);
boolean settingsApplied = upgradeConfigurationSettings(settingsSize, dueFlashStorage.readAddress(SETTINGS_OFFSET));

// activate the retrieved settings
if (settingsApplied) {
Expand Down
38 changes: 7 additions & 31 deletions ls_settings.ino
Original file line number Diff line number Diff line change
Expand Up @@ -70,15 +70,7 @@ void initializeStorage() {
byte bootblock = dueFlashStorage.read(0);

if (bootblock != 0) { // See if we need to boot from scratch
if (bootblock == 255) { // When a new firmware is uploaded, the first flash byte will be 255
switchSerialMode(true); // Start in serial mode after OS upgrade to be able to receive the settings
Device.serialMode = true;
firstTimeBoot = true;
}
else {
switchSerialMode(false); // Start in MIDI mode for all other bootblock values
Device.serialMode = false;
}
firstTimeBoot = true;

writeInitialProjectSettings();
writeSettingsToFlash(); // Store the initial default settings
Expand All @@ -93,8 +85,6 @@ void initializeStorage() {
else {
loadSettings(); // On subsequent startups, load settings from Flash
}

applyConfiguration();
}

void storeSettings() {
Expand All @@ -103,21 +93,6 @@ void storeSettings() {
}
}

static int alignToByteBoundary(int value) {
if (value % 4 == 0) {
return value;
}

return ((value / 4) + 1) * 4;
}
const int PROJECTS_OFFSET = 4;
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 SETTINGS_OFFSET = PROJECTS_OFFSET + alignToByteBoundary(ALL_PROJECTS_SIZE);

void writeAdaptivelyToFlash(uint32_t offset, byte* source, int length) {
// batch and slow down the flash storage in low power mode
if (Device.operatingLowPower) {
Expand Down Expand Up @@ -272,6 +247,10 @@ void applyPresetSettings(PresetSettings& preset) {

void applyConfiguration() {
applyPresetSettings(config.settings);
}

void applySystemState() {
applyConfiguration();
applySerialMode();
}

Expand All @@ -284,8 +263,8 @@ void storeSettingsToPreset(byte p) {
// The first time after new code is loaded into the Linnstrument, this sets the initial defaults of all settings.
// On subsequent startups, these values are overwritten by loading the settings stored in flash.
void initializeDeviceSettings() {
Device.version = 8;
Device.serialMode = false;
Device.version = 9;
Device.serialMode = true;
Device.promoAnimationActive = false;
Device.sleepActive = false;
Device.sleepDelay = 0;
Expand Down Expand Up @@ -545,9 +524,6 @@ void initializePresetSettings() {
p.split[RIGHT].colorPlayed = COLOR_MAGENTA;
p.split[RIGHT].lowRowMode = lowRowNormal;
p.split[RIGHT].sequencerView = sequencerDrums;

// we're initializing the sequencer settings with the split settings
memcpy(&p.sequencer, &p.split, sizeof(SplitSettings) * 2);
}

// we're initializing the current settings with preset 0
Expand Down

0 comments on commit 55a6618

Please sign in to comment.