Skip to content

Commit

Permalink
Add 1.6.0 changes
Browse files Browse the repository at this point in the history
  • Loading branch information
pcprince committed Nov 13, 2023
1 parent 6d705ef commit fff2d55
Show file tree
Hide file tree
Showing 5 changed files with 360 additions and 89 deletions.
53 changes: 51 additions & 2 deletions app.js
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,13 @@ const FIRMWARE_NAMES = ['AudioMoth-Firmware-Basic', 'AudioMoth-USB-Microphone',
/* Is overwrite bootloader option available */
let overwriteBootloaderOptionEnabled = false;

/* Should the user page be cleared of configuration when flashing */
let clearUserPageEnabled = true;

/* Counter for user page clear attempts */
let clearUserPageAttempts = 0;
const MAX_CLEAR_USER_PAGE_ATTEMPTS = 5;

/* Frequency of status check */
const STATUS_TIMEOUT_LENGTH = 500;

Expand Down Expand Up @@ -276,6 +283,29 @@ function getInfoText (version) {

}

function clearUserPage (successCallback) {

if (clearUserPageAttempts < MAX_CLEAR_USER_PAGE_ATTEMPTS) {

clearUserPageAttempts++;
electronLog.log('Attempting to clear user page. Attempt ' + clearUserPageAttempts);

comms.sendUserPageClear(() => {

clearUserPage(successCallback);

}, successCallback);

} else {

electronLog.error('Failed to clear user page after ' + MAX_CLEAR_USER_PAGE_ATTEMPTS + ' attempts.');
comms.displayError('Failed to clear user page after ' + MAX_CLEAR_USER_PAGE_ATTEMPTS + ' attempts.', 'Switch to USB/OFF, detach and reattach your device, and try again.');
comms.stopCommunicating();

}

}

/* Open file and write contents to serial port */

function serialWrite (firmwarePath, destructive, infoText, expectedCRC, successCallback) {
Expand All @@ -300,7 +330,20 @@ function serialWrite (firmwarePath, destructive, infoText, expectedCRC, successC

} else {

comms.sendFirmware(contents, destructive, expectedCRC, successCallback, infoText, maxBlocks);
if (clearUserPageEnabled) {

clearUserPage(() => {

electronLog.log('Successfully cleared user page');
comms.sendFirmware(contents, destructive, expectedCRC, successCallback, infoText, maxBlocks);

});

} else {

comms.sendFirmware(contents, destructive, expectedCRC, successCallback, infoText, maxBlocks);

}

}

Expand Down Expand Up @@ -871,7 +914,7 @@ async function selectBinary () {
}]
});

if (filenames) {
if (filenames && !filenames.canceled) {

/* Check if binary is a valid firmware file */
const isValid = await firmwareInterface.isFirmwareFile(filenames.filePaths[0]);
Expand Down Expand Up @@ -986,6 +1029,12 @@ electron.ipcRenderer.on('toggle-bootloader-overwrite', () => {

});

electron.ipcRenderer.on('toggle-clear-user-page', () => {

clearUserPageEnabled = !clearUserPageEnabled;

});

/* Prepare UI */

firmwareInterface.updateFirmwareDirectoryDisplay('');
Expand Down
189 changes: 179 additions & 10 deletions communication.js
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,11 @@ let responseTimeout;
/* Whether or not a message request has already timed out */
let timedOut;

/* Number of times checking the user page checksum has been attempted */
let userPageCheckCount;
const MAX_USER_PAGE_CHECK_COUNT = 5;
const USER_PAGE_CHECK_DELAY_LENGTH = 100;

/* Timeout for attempting another ready check */
let readyTimeout;

Expand Down Expand Up @@ -102,6 +107,10 @@ let upper = 0;
/* Array of buffers of length BLOCK_SIZE */
let splitBuffers;

/* Blank buffer for clearing the user page */

const blankBuffer = Buffer.alloc(128);

/* Device statuses */
exports.STATUS_USB_DRIVE_BOOTLOADER = 0;
exports.STATUS_SERIAL_BOOTLOADER = 1;
Expand Down Expand Up @@ -1113,9 +1122,13 @@ function sendFirmwareData (expectedCRC, isDestructive, successCallback) {

}

function readyCheck (sendBuffer, expectedCRC, isDestructive, successCallback, infoText, maxBlocks) {
function readyCheck (sendBuffer, updateProgressWindow, successCallback) {

if (updateProgressWindow) {

electron.ipcRenderer.send('set-bar-serial-ready-check', readyCheckCount);
electron.ipcRenderer.send('set-bar-serial-ready-check', readyCheckCount);

}

if (readyCheckCount >= MAX_READY_CHECK_COUNT) {

Expand Down Expand Up @@ -1144,7 +1157,7 @@ function readyCheck (sendBuffer, expectedCRC, isDestructive, successCallback, in

readyTimeout = setTimeout(function () {

readyCheck(sendBuffer, expectedCRC, isDestructive, successCallback, infoText, maxBlocks);
readyCheck(sendBuffer, updateProgressWindow, successCallback);

}, READY_CHECK_DELAY_LENGTH * Math.pow(2, readyCheckCount));

Expand All @@ -1155,12 +1168,7 @@ function readyCheck (sendBuffer, expectedCRC, isDestructive, successCallback, in
numberOfRepeats = 0;
blockNumber = 0;

/* Send information to main process to start progress bar */
electron.ipcRenderer.send('set-bar-flashing');
electron.ipcRenderer.send('set-bar-info', infoText, maxBlocks);

electronLog.log('AudioMoth is ready, sending firmware chunks');
sendFirmwareData(expectedCRC, isDestructive, successCallback);
successCallback();

}

Expand Down Expand Up @@ -1203,8 +1211,169 @@ function sendFirmware (buffer, isDestructive, expectedCRC, successCallback, info

readyCheckCount = 0;

readyCheck(sendBuffer, expectedCRC, isDestructive, successCallback, infoText, maxBlocks);
readyCheck(sendBuffer, true, () => {

/* Send information to main process to start progress bar */
electron.ipcRenderer.send('set-bar-flashing');
electron.ipcRenderer.send('set-bar-info', infoText, maxBlocks);

electronLog.log('AudioMoth is ready, sending firmware chunks');

sendFirmwareData(expectedCRC, isDestructive, successCallback);

});

}

exports.sendFirmware = sendFirmware;

function generateClearPageBuffer (n) {

const bn = n + 1;

/** Buffer format:
* Start of Header byte
* Block number
* Inverse block number (for error checking)
* Data
* CRC
*/
const sendBuffer = Buffer.concat([Buffer.from([SOH]),
Buffer.from([bn]),
Buffer.from([(0xFF - bn)]),
blankBuffer,
Buffer.from('0000', 'hex')
]);

return sendBuffer;

}

function sendUserPageClear (n, failureCallback, successCallback) {

const sendBuffer = generateClearPageBuffer(n);
const responseLength = 1;
const regex = new RegExp(String.fromCharCode(ACK));

send(sendBuffer, responseLength, regex, (err, response) => {

if (err) {

console.error('Failed to clear user page');
failureCallback();

} else {

n++;

if (n >= 16) {

const sendBuffer = Buffer.from([EOF]);
const responseLength = 1;
const regex = new RegExp(String.fromCharCode(ACK));

send(sendBuffer, responseLength, regex, (err, response) => {

if (err) {

electronLog.error('Did not receive ACK from AudioMoth after sending user page end of file');
displayError('Failed to flash device.', 'User page EOF acknowledgement was not received from AudioMoth. Switch to USB/OFF, detach and reattach your device, and try again.');
stopCommunicating();

} else {

electronLog.log('Successfully cleared user page and received EOF message');

clearTimeout(responseTimeout);

successCallback();

}

});

} else {

sendUserPageClear(n, failureCallback, successCallback);

}

}

});

}

/* Use a checksum to verify clearing user page was successful */

function checkUserPageClear (successCallback) {

if (userPageCheckCount > MAX_USER_PAGE_CHECK_COUNT) {

electronLog.error('Didn\'t receive expected checksum response after ' + MAX_USER_PAGE_CHECK_COUNT + ' attempts');
displayError('Failed to flash device.', 'User page checksum was not received from AudioMoth. Switch to USB/OFF, detach and reattach your device, and try again.');

stopCommunicating();

return;

}

userPageCheckCount++;

const sendBuffer = Buffer.from('n');

const responseLength = 18;
const regex = /CRC: 00000000/;

/* Send initial write message, signalling start of XMODEM process */
send(sendBuffer, responseLength, regex, (err, response) => {

if (err) {

electronLog.log('Didn\'t receive expected response, trying ready message again');

readyTimeout = setTimeout(() => {

checkUserPageClear(successCallback);

}, USER_PAGE_CHECK_DELAY_LENGTH * Math.pow(2, userPageCheckCount));

} else {

successCallback();

}

});

}

/* Send command to clear user page containing configuration and wait for ready response */

function startUserPageClear (failureCallback, successCallback) {

const sendBuffer = Buffer.from('t');

readyCheckCount = 0;

readyCheck(sendBuffer, false, () => {

/* Send information to main process to update progress bar */
electron.ipcRenderer.send('set-bar-info', 'Clearing user page');

electronLog.log('AudioMoth is ready, sending new user page data');

sendUserPageClear(0, failureCallback, () => {

userPageCheckCount = 0;

checkUserPageClear(successCallback);

});

});

}

exports.sendUserPageClear = startUserPageClear;
Loading

0 comments on commit fff2d55

Please sign in to comment.