refactor(frontend): clean up and standardize code formatting across various JavaScript files and HTML templates

This commit is contained in:
2026-01-02 19:40:33 -06:00
parent 7aa1560523
commit fe55ec349b
19 changed files with 63967 additions and 16219 deletions

View File

File diff suppressed because it is too large Load Diff

View File

File diff suppressed because it is too large Load Diff

View File

@@ -1,5 +1,4 @@
class Codec2Lib {
static arrayBufferToBase64(buffer) {
let binary = "";
let bytes = new Uint8Array(buffer);
@@ -97,19 +96,7 @@ class Codec2Lib {
static audioFileToRaw(buffer, filename) {
return new Promise((resolve, reject) => {
const module = {
arguments: [
filename,
"-r",
"8000",
"-L",
"-e",
"signed-integer",
"-b",
"16",
"-c",
"1",
"output.raw",
],
arguments: [filename, "-r", "8000", "-L", "-e", "signed-integer", "-b", "16", "-c", "1", "output.raw"],
preRun: () => {
module.FS.writeFile(filename, new Uint8Array(buffer));
},
@@ -123,5 +110,4 @@ class Codec2Lib {
SOXModule(module);
});
}
}

View File

@@ -2,9 +2,7 @@
* A simple class for recording microphone input and returning the audio encoded in codec2
*/
class Codec2MicrophoneRecorder {
constructor() {
this.sampleRate = 8000;
this.codec2Mode = "1200";
this.audioChunks = [];
@@ -13,16 +11,14 @@ class Codec2MicrophoneRecorder {
this.audioWorkletNode = null;
this.microphoneMediaStream = null;
this.mediaStreamSource = null;
}
async start() {
try {
// load audio worklet module
this.audioContext = new AudioContext({ sampleRate: this.sampleRate });
await this.audioContext.audioWorklet.addModule('assets/js/codec2-emscripten/processor.js');
this.audioWorkletNode = new AudioWorkletNode(this.audioContext, 'audio-processor');
await this.audioContext.audioWorklet.addModule("assets/js/codec2-emscripten/processor.js");
this.audioWorkletNode = new AudioWorkletNode(this.audioContext, "audio-processor");
// handle audio received from audio worklet
this.audioWorkletNode.port.onmessage = async (event) => {
@@ -40,42 +36,37 @@ class Codec2MicrophoneRecorder {
// successfully started recording
return true;
} catch(e) {
} catch (e) {
console.log(e);
return false;
}
}
async stop() {
// disconnect media stream source
if(this.mediaStreamSource){
if (this.mediaStreamSource) {
this.mediaStreamSource.disconnect();
}
// stop using microphone
if(this.microphoneMediaStream){
this.microphoneMediaStream.getTracks().forEach(track => track.stop());
if (this.microphoneMediaStream) {
this.microphoneMediaStream.getTracks().forEach((track) => track.stop());
}
// disconnect the audio worklet node
if(this.audioWorkletNode){
if (this.audioWorkletNode) {
this.audioWorkletNode.disconnect();
}
// close audio context
if(this.audioContext && this.audioContext.state !== "closed"){
if (this.audioContext && this.audioContext.state !== "closed") {
this.audioContext.close();
}
// concatenate all audio chunks into a single array
var fullAudio = [];
for(const chunk of this.audioChunks){
fullAudio = [
...fullAudio,
...chunk,
]
for (const chunk of this.audioChunks) {
fullAudio = [...fullAudio, ...chunk];
}
// convert audio to wav
@@ -86,7 +77,5 @@ class Codec2MicrophoneRecorder {
const encoded = await Codec2Lib.runEncode(this.codec2Mode, rawBuffer);
return encoded;
}
}

View File

@@ -1,127 +1,117 @@
<html>
<body>
<div>
<body>
<div>
<div style="margin-bottom: 1rem">
<div>Select a *.wav audio file.</div>
<input id="file-input" type="file" accept="audio/wav" />
</div>
<div style="margin-bottom:1rem;">
<div>Select a *.wav audio file.</div>
<input id="file-input" type="file" accept="audio/wav"/>
</div>
<div style="margin-bottom: 1rem">
<span>Select Codec2 Mode:</span>
<select id="codec-mode">
<option value="3200">3200</option>
<option value="2400">2400</option>
<option value="1600">1600</option>
<option value="1400">1400</option>
<option value="1300">1300</option>
<option value="1200">1200</option>
<option value="700C" selected>700C</option>
<option value="450">450</option>
<option value="450PWB">450PWB</option>
</select>
</div>
<div style="margin-bottom:1rem;">
<span>Select Codec2 Mode:</span>
<select id="codec-mode">
<option value="3200">3200</option>
<option value="2400">2400</option>
<option value="1600">1600</option>
<option value="1400">1400</option>
<option value="1300">1300</option>
<option value="1200">1200</option>
<option value="700C" selected>700C</option>
<option value="450">450</option>
<option value="450PWB">450PWB</option>
</select>
</div>
<div style="margin-bottom: 1rem">
<div>Click to encode audio file as Codec2</div>
<button type="submit" onclick="encode()">Encode</button>
</div>
<div style="margin-bottom:1rem;">
<div>Click to encode audio file as Codec2</div>
<button type="submit" onclick="encode()">Encode</button>
</div>
<div style="margin-bottom: 1rem">
<div>Codec2 audio represented as Base64</div>
<textarea id="encoded-output" style="width: 500px" rows="8"></textarea>
</div>
<div style="margin-bottom:1rem;">
<div>Codec2 audio represented as Base64</div>
<textarea id="encoded-output" style="width:500px" rows="8"></textarea>
</div>
<div style="margin-bottom: 1rem">
<div>Click to decode Codec2 audio back to WAVE audio</div>
<button type="submit" onclick="decode()">Decode</button>
</div>
<div style="margin-bottom:1rem;">
<div>Click to decode Codec2 audio back to WAVE audio</div>
<button type="submit" onclick="decode()">Decode</button>
</div>
<div style="margin-bottom: 1rem">
<div>Decoded audio available to listen to</div>
<audio id="decoded-audio" controls></audio>
</div>
<div style="margin-bottom:1rem;">
<div>Decoded audio available to listen to</div>
<audio id="decoded-audio" controls></audio>
</div>
<div style="margin-bottom: 1rem">
<div>Input File Size: <span id="input-size">0 Bytes</span></div>
<div>Encoded Data Size: <span id="encoded-size">0 Bytes</span></div>
<div>Decoded Data Size: <span id="decoded-size">0 Bytes</span></div>
</div>
</div>
<script src="c2enc.js"></script>
<script src="c2dec.js"></script>
<script src="sox.js"></script>
<script src="codec2-lib.js"></script>
<script>
// find elements
const codecModeElement = document.getElementById("codec-mode");
const encodedOutputElement = document.getElementById("encoded-output");
const fileInputElement = document.getElementById("file-input");
const decodedAudioElement = document.getElementById("decoded-audio");
const inputSizeElement = document.getElementById("input-size");
const encodedSizeElement = document.getElementById("encoded-size");
const decodedSizeElement = document.getElementById("decoded-size");
<div style="margin-bottom:1rem;">
<div>Input File Size: <span id="input-size">0 Bytes</span></div>
<div>Encoded Data Size: <span id="encoded-size">0 Bytes</span></div>
<div>Decoded Data Size: <span id="decoded-size">0 Bytes</span></div>
</div>
// update file size stats on change
fileInputElement.onchange = function () {
if (fileInputElement.files.length > 0) {
const file = fileInputElement.files[0];
inputSizeElement.innerText = formatBytes(file.size);
}
};
</div>
<script src="c2enc.js"></script>
<script src="c2dec.js"></script>
<script src="sox.js"></script>
<script src="codec2-lib.js"></script>
<script>
async function encode() {
const file = fileInputElement.files[0];
if (!file) {
alert("select a file first");
return;
}
// find elements
const codecModeElement = document.getElementById("codec-mode");
const encodedOutputElement = document.getElementById("encoded-output");
const fileInputElement = document.getElementById("file-input");
const decodedAudioElement = document.getElementById("decoded-audio");
const inputSizeElement = document.getElementById("input-size");
const encodedSizeElement = document.getElementById("encoded-size");
const decodedSizeElement = document.getElementById("decoded-size");
const mode = codecModeElement.value;
// update file size stats on change
fileInputElement.onchange = function() {
if(fileInputElement.files.length > 0){
const file = fileInputElement.files[0];
inputSizeElement.innerText = formatBytes(file.size);
}
}
const buffer = await Codec2Lib.readFileAsArrayBuffer(file);
const rawBuffer = await Codec2Lib.audioFileToRaw(buffer, file.name || "input.wav");
const encoded = await Codec2Lib.runEncode(mode, rawBuffer);
async function encode() {
encodedOutputElement.value = Codec2Lib.arrayBufferToBase64(encoded);
inputSizeElement.innerText = formatBytes(file.size);
encodedSizeElement.innerText = formatBytes(encoded.length);
}
const file = fileInputElement.files[0];
if(!file){
alert("select a file first");
return;
}
async function decode() {
const mode = codecModeElement.value;
const input = encodedOutputElement.value;
const mode = codecModeElement.value;
const encoded = Codec2Lib.base64ToArrayBuffer(input);
const decodedRaw = await Codec2Lib.runDecode(mode, encoded);
const decodedWav = await Codec2Lib.rawToWav(decodedRaw);
const buffer = await Codec2Lib.readFileAsArrayBuffer(file);
const rawBuffer = await Codec2Lib.audioFileToRaw(buffer, file.name || "input.wav");
const encoded = await Codec2Lib.runEncode(mode, rawBuffer);
decodedAudioElement.src = URL.createObjectURL(new Blob([decodedWav], { type: "audio/wav" }));
decodedSizeElement.innerText = formatBytes(decodedWav.length);
}
encodedOutputElement.value = Codec2Lib.arrayBufferToBase64(encoded);
inputSizeElement.innerText = formatBytes(file.size);
encodedSizeElement.innerText = formatBytes(encoded.length);
function formatBytes(bytes) {
if (bytes === 0) {
return "0 Bytes";
}
}
const k = 1024;
const decimals = 0;
const sizes = ["Bytes", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"];
async function decode() {
const i = Math.floor(Math.log(bytes) / Math.log(k));
const mode = codecModeElement.value;
const input = encodedOutputElement.value;
const encoded = Codec2Lib.base64ToArrayBuffer(input);
const decodedRaw = await Codec2Lib.runDecode(mode, encoded);
const decodedWav = await Codec2Lib.rawToWav(decodedRaw);
decodedAudioElement.src = URL.createObjectURL(new Blob([decodedWav], { type: "audio/wav" }));
decodedSizeElement.innerText = formatBytes(decodedWav.length);
}
function formatBytes(bytes) {
if(bytes === 0){
return '0 Bytes';
}
const k = 1024;
const decimals = 0;
const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
const i = Math.floor(Math.log(bytes) / Math.log(k));
return parseFloat((bytes / Math.pow(k, i)).toFixed(decimals)) + ' ' + sizes[i];
}
</script>
</body>
</html>
return parseFloat((bytes / Math.pow(k, i)).toFixed(decimals)) + " " + sizes[i];
}
</script>
</body>
</html>

View File

@@ -1,5 +1,4 @@
class AudioProcessor extends AudioWorkletProcessor {
constructor() {
super();
this.bufferSize = 4096; // Adjust the buffer size as needed
@@ -52,4 +51,4 @@ class AudioProcessor extends AudioWorkletProcessor {
}
}
registerProcessor('audio-processor', AudioProcessor);
registerProcessor("audio-processor", AudioProcessor);

View File

File diff suppressed because it is too large Load Diff

View File

@@ -1,17 +1,15 @@
class WavEncoder {
static encodeWAV(samples, sampleRate = 8000, numChannels = 1) {
const buffer = new ArrayBuffer(44 + samples.length * 2);
const view = new DataView(buffer);
// RIFF chunk descriptor
this.writeString(view, 0, 'RIFF');
this.writeString(view, 0, "RIFF");
view.setUint32(4, 36 + samples.length * 2, true); // file length
this.writeString(view, 8, 'WAVE');
this.writeString(view, 8, "WAVE");
// fmt sub-chunk
this.writeString(view, 12, 'fmt ');
this.writeString(view, 12, "fmt ");
view.setUint32(16, 16, true); // sub-chunk size
view.setUint16(20, 1, true); // audio format (1 = PCM)
view.setUint16(22, numChannels, true); // number of channels
@@ -21,27 +19,25 @@ class WavEncoder {
view.setUint16(34, 16, true); // bits per sample
// data sub-chunk
this.writeString(view, 36, 'data');
this.writeString(view, 36, "data");
view.setUint32(40, samples.length * 2, true); // data chunk length
// write the PCM samples
this.floatTo16BitPCM(view, 44, samples);
return buffer;
}
static writeString(view, offset, string) {
for(let i = 0; i < string.length; i++){
for (let i = 0; i < string.length; i++) {
view.setUint8(offset + i, string.charCodeAt(i));
}
}
static floatTo16BitPCM(output, offset, input) {
for(let i = 0; i < input.length; i++, offset += 2){
for (let i = 0; i < input.length; i++, offset += 2) {
const s = Math.max(-1, Math.min(1, input[i]));
output.setInt16(offset, s < 0 ? s * 0x8000 : s * 0x7FFF, true);
output.setInt16(offset, s < 0 ? s * 0x8000 : s * 0x7fff, true);
}
}
}

View File

File diff suppressed because one or more lines are too long

View File

@@ -1,17 +1,17 @@
{
"name": "MeshChat",
"short_name": "MeshChat",
"description": "A simple mesh network communications app powered by the Reticulum Network Stack.",
"scope": "/",
"start_url": "/",
"icons": [
{
"src": "/favicons/favicon-512x512.png",
"sizes": "512x512",
"type": "image/png"
}
],
"display": "standalone",
"theme_color": "#FFFFFF",
"background_color": "#FFFFFF"
"name": "MeshChat",
"short_name": "MeshChat",
"description": "A simple mesh network communications app powered by the Reticulum Network Stack.",
"scope": "/",
"start_url": "/",
"icons": [
{
"src": "/favicons/favicon-512x512.png",
"sizes": "512x512",
"type": "image/png"
}
],
"display": "standalone",
"theme_color": "#FFFFFF",
"background_color": "#FFFFFF"
}

View File

@@ -53,11 +53,11 @@ Once the firmware is flashed to the device, you will need to provision the EEPRO
- Set firmware hash in eeprom
- Collect device info
- `product`
- `model`
- `hardware_revision`
- `serial_number`
- `made` (unix timestamp of device creation)
- `product`
- `model`
- `hardware_revision`
- `serial_number`
- `made` (unix timestamp of device creation)
- Write device info to eeprom
- Create an MD5 checksum of the device info
- Write 16 byte device info checksum to eeprom

View File

File diff suppressed because it is too large Load Diff

View File

File diff suppressed because it is too large Load Diff

View File

@@ -1,268 +1,256 @@
;(function (root, factory) {
if (typeof exports === "object") {
// CommonJS
module.exports = exports = factory(require("./core"));
}
else if (typeof define === "function" && define.amd) {
// AMD
define(["./core"], factory);
}
else {
// Global (browser)
factory(root.CryptoJS);
}
}(this, function (CryptoJS) {
(function (root, factory) {
if (typeof exports === "object") {
// CommonJS
module.exports = exports = factory(require("./core"));
} else if (typeof define === "function" && define.amd) {
// AMD
define(["./core"], factory);
} else {
// Global (browser)
factory(root.CryptoJS);
}
})(this, function (CryptoJS) {
(function (Math) {
// Shortcuts
var C = CryptoJS;
var C_lib = C.lib;
var WordArray = C_lib.WordArray;
var Hasher = C_lib.Hasher;
var C_algo = C.algo;
(function (Math) {
// Shortcuts
var C = CryptoJS;
var C_lib = C.lib;
var WordArray = C_lib.WordArray;
var Hasher = C_lib.Hasher;
var C_algo = C.algo;
// Constants table
var T = [];
// Constants table
var T = [];
// Compute constants
(function () {
for (var i = 0; i < 64; i++) {
T[i] = (Math.abs(Math.sin(i + 1)) * 0x100000000) | 0;
}
})();
// Compute constants
(function () {
for (var i = 0; i < 64; i++) {
T[i] = (Math.abs(Math.sin(i + 1)) * 0x100000000) | 0;
}
}());
/**
* MD5 hash algorithm.
*/
var MD5 = (C_algo.MD5 = Hasher.extend({
_doReset: function () {
this._hash = new WordArray.init([0x67452301, 0xefcdab89, 0x98badcfe, 0x10325476]);
},
/**
* MD5 hash algorithm.
*/
var MD5 = C_algo.MD5 = Hasher.extend({
_doReset: function () {
this._hash = new WordArray.init([
0x67452301, 0xefcdab89,
0x98badcfe, 0x10325476
]);
},
_doProcessBlock: function (M, offset) {
// Swap endian
for (var i = 0; i < 16; i++) {
// Shortcuts
var offset_i = offset + i;
var M_offset_i = M[offset_i];
_doProcessBlock: function (M, offset) {
// Swap endian
for (var i = 0; i < 16; i++) {
// Shortcuts
var offset_i = offset + i;
var M_offset_i = M[offset_i];
M[offset_i] =
(((M_offset_i << 8) | (M_offset_i >>> 24)) & 0x00ff00ff) |
(((M_offset_i << 24) | (M_offset_i >>> 8)) & 0xff00ff00);
}
M[offset_i] = (
(((M_offset_i << 8) | (M_offset_i >>> 24)) & 0x00ff00ff) |
(((M_offset_i << 24) | (M_offset_i >>> 8)) & 0xff00ff00)
);
}
// Shortcuts
var H = this._hash.words;
// Shortcuts
var H = this._hash.words;
var M_offset_0 = M[offset + 0];
var M_offset_1 = M[offset + 1];
var M_offset_2 = M[offset + 2];
var M_offset_3 = M[offset + 3];
var M_offset_4 = M[offset + 4];
var M_offset_5 = M[offset + 5];
var M_offset_6 = M[offset + 6];
var M_offset_7 = M[offset + 7];
var M_offset_8 = M[offset + 8];
var M_offset_9 = M[offset + 9];
var M_offset_10 = M[offset + 10];
var M_offset_11 = M[offset + 11];
var M_offset_12 = M[offset + 12];
var M_offset_13 = M[offset + 13];
var M_offset_14 = M[offset + 14];
var M_offset_15 = M[offset + 15];
var M_offset_0 = M[offset + 0];
var M_offset_1 = M[offset + 1];
var M_offset_2 = M[offset + 2];
var M_offset_3 = M[offset + 3];
var M_offset_4 = M[offset + 4];
var M_offset_5 = M[offset + 5];
var M_offset_6 = M[offset + 6];
var M_offset_7 = M[offset + 7];
var M_offset_8 = M[offset + 8];
var M_offset_9 = M[offset + 9];
var M_offset_10 = M[offset + 10];
var M_offset_11 = M[offset + 11];
var M_offset_12 = M[offset + 12];
var M_offset_13 = M[offset + 13];
var M_offset_14 = M[offset + 14];
var M_offset_15 = M[offset + 15];
// Working varialbes
var a = H[0];
var b = H[1];
var c = H[2];
var d = H[3];
// Working varialbes
var a = H[0];
var b = H[1];
var c = H[2];
var d = H[3];
// Computation
a = FF(a, b, c, d, M_offset_0, 7, T[0]);
d = FF(d, a, b, c, M_offset_1, 12, T[1]);
c = FF(c, d, a, b, M_offset_2, 17, T[2]);
b = FF(b, c, d, a, M_offset_3, 22, T[3]);
a = FF(a, b, c, d, M_offset_4, 7, T[4]);
d = FF(d, a, b, c, M_offset_5, 12, T[5]);
c = FF(c, d, a, b, M_offset_6, 17, T[6]);
b = FF(b, c, d, a, M_offset_7, 22, T[7]);
a = FF(a, b, c, d, M_offset_8, 7, T[8]);
d = FF(d, a, b, c, M_offset_9, 12, T[9]);
c = FF(c, d, a, b, M_offset_10, 17, T[10]);
b = FF(b, c, d, a, M_offset_11, 22, T[11]);
a = FF(a, b, c, d, M_offset_12, 7, T[12]);
d = FF(d, a, b, c, M_offset_13, 12, T[13]);
c = FF(c, d, a, b, M_offset_14, 17, T[14]);
b = FF(b, c, d, a, M_offset_15, 22, T[15]);
// Computation
a = FF(a, b, c, d, M_offset_0, 7, T[0]);
d = FF(d, a, b, c, M_offset_1, 12, T[1]);
c = FF(c, d, a, b, M_offset_2, 17, T[2]);
b = FF(b, c, d, a, M_offset_3, 22, T[3]);
a = FF(a, b, c, d, M_offset_4, 7, T[4]);
d = FF(d, a, b, c, M_offset_5, 12, T[5]);
c = FF(c, d, a, b, M_offset_6, 17, T[6]);
b = FF(b, c, d, a, M_offset_7, 22, T[7]);
a = FF(a, b, c, d, M_offset_8, 7, T[8]);
d = FF(d, a, b, c, M_offset_9, 12, T[9]);
c = FF(c, d, a, b, M_offset_10, 17, T[10]);
b = FF(b, c, d, a, M_offset_11, 22, T[11]);
a = FF(a, b, c, d, M_offset_12, 7, T[12]);
d = FF(d, a, b, c, M_offset_13, 12, T[13]);
c = FF(c, d, a, b, M_offset_14, 17, T[14]);
b = FF(b, c, d, a, M_offset_15, 22, T[15]);
a = GG(a, b, c, d, M_offset_1, 5, T[16]);
d = GG(d, a, b, c, M_offset_6, 9, T[17]);
c = GG(c, d, a, b, M_offset_11, 14, T[18]);
b = GG(b, c, d, a, M_offset_0, 20, T[19]);
a = GG(a, b, c, d, M_offset_5, 5, T[20]);
d = GG(d, a, b, c, M_offset_10, 9, T[21]);
c = GG(c, d, a, b, M_offset_15, 14, T[22]);
b = GG(b, c, d, a, M_offset_4, 20, T[23]);
a = GG(a, b, c, d, M_offset_9, 5, T[24]);
d = GG(d, a, b, c, M_offset_14, 9, T[25]);
c = GG(c, d, a, b, M_offset_3, 14, T[26]);
b = GG(b, c, d, a, M_offset_8, 20, T[27]);
a = GG(a, b, c, d, M_offset_13, 5, T[28]);
d = GG(d, a, b, c, M_offset_2, 9, T[29]);
c = GG(c, d, a, b, M_offset_7, 14, T[30]);
b = GG(b, c, d, a, M_offset_12, 20, T[31]);
a = GG(a, b, c, d, M_offset_1, 5, T[16]);
d = GG(d, a, b, c, M_offset_6, 9, T[17]);
c = GG(c, d, a, b, M_offset_11, 14, T[18]);
b = GG(b, c, d, a, M_offset_0, 20, T[19]);
a = GG(a, b, c, d, M_offset_5, 5, T[20]);
d = GG(d, a, b, c, M_offset_10, 9, T[21]);
c = GG(c, d, a, b, M_offset_15, 14, T[22]);
b = GG(b, c, d, a, M_offset_4, 20, T[23]);
a = GG(a, b, c, d, M_offset_9, 5, T[24]);
d = GG(d, a, b, c, M_offset_14, 9, T[25]);
c = GG(c, d, a, b, M_offset_3, 14, T[26]);
b = GG(b, c, d, a, M_offset_8, 20, T[27]);
a = GG(a, b, c, d, M_offset_13, 5, T[28]);
d = GG(d, a, b, c, M_offset_2, 9, T[29]);
c = GG(c, d, a, b, M_offset_7, 14, T[30]);
b = GG(b, c, d, a, M_offset_12, 20, T[31]);
a = HH(a, b, c, d, M_offset_5, 4, T[32]);
d = HH(d, a, b, c, M_offset_8, 11, T[33]);
c = HH(c, d, a, b, M_offset_11, 16, T[34]);
b = HH(b, c, d, a, M_offset_14, 23, T[35]);
a = HH(a, b, c, d, M_offset_1, 4, T[36]);
d = HH(d, a, b, c, M_offset_4, 11, T[37]);
c = HH(c, d, a, b, M_offset_7, 16, T[38]);
b = HH(b, c, d, a, M_offset_10, 23, T[39]);
a = HH(a, b, c, d, M_offset_13, 4, T[40]);
d = HH(d, a, b, c, M_offset_0, 11, T[41]);
c = HH(c, d, a, b, M_offset_3, 16, T[42]);
b = HH(b, c, d, a, M_offset_6, 23, T[43]);
a = HH(a, b, c, d, M_offset_9, 4, T[44]);
d = HH(d, a, b, c, M_offset_12, 11, T[45]);
c = HH(c, d, a, b, M_offset_15, 16, T[46]);
b = HH(b, c, d, a, M_offset_2, 23, T[47]);
a = HH(a, b, c, d, M_offset_5, 4, T[32]);
d = HH(d, a, b, c, M_offset_8, 11, T[33]);
c = HH(c, d, a, b, M_offset_11, 16, T[34]);
b = HH(b, c, d, a, M_offset_14, 23, T[35]);
a = HH(a, b, c, d, M_offset_1, 4, T[36]);
d = HH(d, a, b, c, M_offset_4, 11, T[37]);
c = HH(c, d, a, b, M_offset_7, 16, T[38]);
b = HH(b, c, d, a, M_offset_10, 23, T[39]);
a = HH(a, b, c, d, M_offset_13, 4, T[40]);
d = HH(d, a, b, c, M_offset_0, 11, T[41]);
c = HH(c, d, a, b, M_offset_3, 16, T[42]);
b = HH(b, c, d, a, M_offset_6, 23, T[43]);
a = HH(a, b, c, d, M_offset_9, 4, T[44]);
d = HH(d, a, b, c, M_offset_12, 11, T[45]);
c = HH(c, d, a, b, M_offset_15, 16, T[46]);
b = HH(b, c, d, a, M_offset_2, 23, T[47]);
a = II(a, b, c, d, M_offset_0, 6, T[48]);
d = II(d, a, b, c, M_offset_7, 10, T[49]);
c = II(c, d, a, b, M_offset_14, 15, T[50]);
b = II(b, c, d, a, M_offset_5, 21, T[51]);
a = II(a, b, c, d, M_offset_12, 6, T[52]);
d = II(d, a, b, c, M_offset_3, 10, T[53]);
c = II(c, d, a, b, M_offset_10, 15, T[54]);
b = II(b, c, d, a, M_offset_1, 21, T[55]);
a = II(a, b, c, d, M_offset_8, 6, T[56]);
d = II(d, a, b, c, M_offset_15, 10, T[57]);
c = II(c, d, a, b, M_offset_6, 15, T[58]);
b = II(b, c, d, a, M_offset_13, 21, T[59]);
a = II(a, b, c, d, M_offset_4, 6, T[60]);
d = II(d, a, b, c, M_offset_11, 10, T[61]);
c = II(c, d, a, b, M_offset_2, 15, T[62]);
b = II(b, c, d, a, M_offset_9, 21, T[63]);
a = II(a, b, c, d, M_offset_0, 6, T[48]);
d = II(d, a, b, c, M_offset_7, 10, T[49]);
c = II(c, d, a, b, M_offset_14, 15, T[50]);
b = II(b, c, d, a, M_offset_5, 21, T[51]);
a = II(a, b, c, d, M_offset_12, 6, T[52]);
d = II(d, a, b, c, M_offset_3, 10, T[53]);
c = II(c, d, a, b, M_offset_10, 15, T[54]);
b = II(b, c, d, a, M_offset_1, 21, T[55]);
a = II(a, b, c, d, M_offset_8, 6, T[56]);
d = II(d, a, b, c, M_offset_15, 10, T[57]);
c = II(c, d, a, b, M_offset_6, 15, T[58]);
b = II(b, c, d, a, M_offset_13, 21, T[59]);
a = II(a, b, c, d, M_offset_4, 6, T[60]);
d = II(d, a, b, c, M_offset_11, 10, T[61]);
c = II(c, d, a, b, M_offset_2, 15, T[62]);
b = II(b, c, d, a, M_offset_9, 21, T[63]);
// Intermediate hash value
H[0] = (H[0] + a) | 0;
H[1] = (H[1] + b) | 0;
H[2] = (H[2] + c) | 0;
H[3] = (H[3] + d) | 0;
},
// Intermediate hash value
H[0] = (H[0] + a) | 0;
H[1] = (H[1] + b) | 0;
H[2] = (H[2] + c) | 0;
H[3] = (H[3] + d) | 0;
},
_doFinalize: function () {
// Shortcuts
var data = this._data;
var dataWords = data.words;
_doFinalize: function () {
// Shortcuts
var data = this._data;
var dataWords = data.words;
var nBitsTotal = this._nDataBytes * 8;
var nBitsLeft = data.sigBytes * 8;
var nBitsTotal = this._nDataBytes * 8;
var nBitsLeft = data.sigBytes * 8;
// Add padding
dataWords[nBitsLeft >>> 5] |= 0x80 << (24 - (nBitsLeft % 32));
// Add padding
dataWords[nBitsLeft >>> 5] |= 0x80 << (24 - nBitsLeft % 32);
var nBitsTotalH = Math.floor(nBitsTotal / 0x100000000);
var nBitsTotalL = nBitsTotal;
dataWords[(((nBitsLeft + 64) >>> 9) << 4) + 15] =
(((nBitsTotalH << 8) | (nBitsTotalH >>> 24)) & 0x00ff00ff) |
(((nBitsTotalH << 24) | (nBitsTotalH >>> 8)) & 0xff00ff00);
dataWords[(((nBitsLeft + 64) >>> 9) << 4) + 14] =
(((nBitsTotalL << 8) | (nBitsTotalL >>> 24)) & 0x00ff00ff) |
(((nBitsTotalL << 24) | (nBitsTotalL >>> 8)) & 0xff00ff00);
var nBitsTotalH = Math.floor(nBitsTotal / 0x100000000);
var nBitsTotalL = nBitsTotal;
dataWords[(((nBitsLeft + 64) >>> 9) << 4) + 15] = (
(((nBitsTotalH << 8) | (nBitsTotalH >>> 24)) & 0x00ff00ff) |
(((nBitsTotalH << 24) | (nBitsTotalH >>> 8)) & 0xff00ff00)
);
dataWords[(((nBitsLeft + 64) >>> 9) << 4) + 14] = (
(((nBitsTotalL << 8) | (nBitsTotalL >>> 24)) & 0x00ff00ff) |
(((nBitsTotalL << 24) | (nBitsTotalL >>> 8)) & 0xff00ff00)
);
data.sigBytes = (dataWords.length + 1) * 4;
data.sigBytes = (dataWords.length + 1) * 4;
// Hash final blocks
this._process();
// Hash final blocks
this._process();
// Shortcuts
var hash = this._hash;
var H = hash.words;
// Shortcuts
var hash = this._hash;
var H = hash.words;
// Swap endian
for (var i = 0; i < 4; i++) {
// Shortcut
var H_i = H[i];
// Swap endian
for (var i = 0; i < 4; i++) {
// Shortcut
var H_i = H[i];
H[i] = (((H_i << 8) | (H_i >>> 24)) & 0x00ff00ff) | (((H_i << 24) | (H_i >>> 8)) & 0xff00ff00);
}
H[i] = (((H_i << 8) | (H_i >>> 24)) & 0x00ff00ff) |
(((H_i << 24) | (H_i >>> 8)) & 0xff00ff00);
}
// Return final computed hash
return hash;
},
// Return final computed hash
return hash;
},
clone: function () {
var clone = Hasher.clone.call(this);
clone._hash = this._hash.clone();
clone: function () {
var clone = Hasher.clone.call(this);
clone._hash = this._hash.clone();
return clone;
},
}));
return clone;
}
});
function FF(a, b, c, d, x, s, t) {
var n = a + ((b & c) | (~b & d)) + x + t;
return ((n << s) | (n >>> (32 - s))) + b;
}
function FF(a, b, c, d, x, s, t) {
var n = a + ((b & c) | (~b & d)) + x + t;
return ((n << s) | (n >>> (32 - s))) + b;
}
function GG(a, b, c, d, x, s, t) {
var n = a + ((b & d) | (c & ~d)) + x + t;
return ((n << s) | (n >>> (32 - s))) + b;
}
function GG(a, b, c, d, x, s, t) {
var n = a + ((b & d) | (c & ~d)) + x + t;
return ((n << s) | (n >>> (32 - s))) + b;
}
function HH(a, b, c, d, x, s, t) {
var n = a + (b ^ c ^ d) + x + t;
return ((n << s) | (n >>> (32 - s))) + b;
}
function HH(a, b, c, d, x, s, t) {
var n = a + (b ^ c ^ d) + x + t;
return ((n << s) | (n >>> (32 - s))) + b;
}
function II(a, b, c, d, x, s, t) {
var n = a + (c ^ (b | ~d)) + x + t;
return ((n << s) | (n >>> (32 - s))) + b;
}
function II(a, b, c, d, x, s, t) {
var n = a + (c ^ (b | ~d)) + x + t;
return ((n << s) | (n >>> (32 - s))) + b;
}
/**
* Shortcut function to the hasher's object interface.
*
* @param {WordArray|string} message The message to hash.
*
* @return {WordArray} The hash.
*
* @static
*
* @example
*
* var hash = CryptoJS.MD5('message');
* var hash = CryptoJS.MD5(wordArray);
*/
C.MD5 = Hasher._createHelper(MD5);
/**
* Shortcut function to the hasher's object interface.
*
* @param {WordArray|string} message The message to hash.
*
* @return {WordArray} The hash.
*
* @static
*
* @example
*
* var hash = CryptoJS.MD5('message');
* var hash = CryptoJS.MD5(wordArray);
*/
C.MD5 = Hasher._createHelper(MD5);
/**
* Shortcut function to the HMAC's object interface.
*
* @param {WordArray|string} message The message to hash.
* @param {WordArray|string} key The secret key.
*
* @return {WordArray} The HMAC.
*
* @static
*
* @example
*
* var hmac = CryptoJS.HmacMD5(message, key);
*/
C.HmacMD5 = Hasher._createHmacHelper(MD5);
})(Math);
/**
* Shortcut function to the HMAC's object interface.
*
* @param {WordArray|string} message The message to hash.
* @param {WordArray|string} key The secret key.
*
* @return {WordArray} The HMAC.
*
* @static
*
* @example
*
* var hmac = CryptoJS.HmacMD5(message, key);
*/
C.HmacMD5 = Hasher._createHmacHelper(MD5);
}(Math));
return CryptoJS.MD5;
}));
return CryptoJS.MD5;
});

View File

File diff suppressed because one or more lines are too long

View File

@@ -3,7 +3,6 @@
* https://github.com/adafruit/Adafruit_nRF52_nrfutil/blob/master/nordicsemi/dfu/dfu_transport_serial.py
*/
class Nrf52DfuFlasher {
DFU_TOUCH_BAUD = 1200;
SERIAL_PORT_OPEN_WAIT_TIME = 0.1;
TOUCH_RESET_WAIT_TIME = 1.5;
@@ -23,8 +22,8 @@ class Nrf52DfuFlasher {
FLASH_PAGE_SIZE = 4096;
FLASH_PAGE_ERASE_TIME = 0.0897;
FLASH_WORD_WRITE_TIME = 0.000100;
FLASH_PAGE_WRITE_TIME = (this.FLASH_PAGE_SIZE/4) * this.FLASH_WORD_WRITE_TIME;
FLASH_WORD_WRITE_TIME = 0.0001;
FLASH_PAGE_WRITE_TIME = (this.FLASH_PAGE_SIZE / 4) * this.FLASH_WORD_WRITE_TIME;
// The DFU packet max size
DFU_PACKET_MAX_SIZE = 512;
@@ -66,7 +65,6 @@ class Nrf52DfuFlasher {
* @returns {Promise<void>}
*/
async enterDfuMode() {
// open port
await this.serialPort.open({
baudRate: this.DFU_TOUCH_BAUD,
@@ -80,7 +78,6 @@ class Nrf52DfuFlasher {
// wait TOUCH_RESET_WAIT_TIME for device to enter into DFU mode
await this.sleepMillis(this.TOUCH_RESET_WAIT_TIME * 1000);
}
/**
@@ -90,7 +87,6 @@ class Nrf52DfuFlasher {
* @returns {Promise<void>}
*/
async flash(firmwareZipBlob, progressCallback) {
// read zip file
const blobReader = new window.zip.BlobReader(firmwareZipBlob);
const zipReader = new window.zip.ZipReader(blobReader);
@@ -98,7 +94,7 @@ class Nrf52DfuFlasher {
// find manifest file
const manifestFile = zipEntries.find((zipEntry) => zipEntry.filename === "manifest.json");
if(!manifestFile){
if (!manifestFile) {
throw "manifest.json not found in firmware file!";
}
@@ -122,10 +118,9 @@ class Nrf52DfuFlasher {
// self._dfu_send_image(HexType.BOOTLOADER, self.manifest.bootloader)
// flash application image
if(manifest.application){
if (manifest.application) {
await this.dfuSendImage(this.HEX_TYPE_APPLICATION, zipEntries, manifest.application, progressCallback);
}
}
/**
@@ -137,7 +132,6 @@ class Nrf52DfuFlasher {
* @returns {Promise<void>}
*/
async dfuSendImage(programMode, zipEntries, firmwareManifest, progressCallback) {
// open port
await this.serialPort.open({
baudRate: this.FLASH_BAUD,
@@ -147,9 +141,9 @@ class Nrf52DfuFlasher {
await this.sleepMillis(this.SERIAL_PORT_OPEN_WAIT_TIME * 1000);
// file sizes
var softdeviceSize = 0
var bootloaderSize = 0
var applicationSize = 0
var softdeviceSize = 0;
var bootloaderSize = 0;
var applicationSize = 0;
// read bin file (firmware)
const binFile = zipEntries.find((zipEntry) => zipEntry.filename === firmwareManifest.bin_file);
@@ -160,12 +154,12 @@ class Nrf52DfuFlasher {
const init_packet = await datFile.getData(new window.zip.Uint8ArrayWriter());
// only support flashing application for now
if(programMode !== this.HEX_TYPE_APPLICATION){
if (programMode !== this.HEX_TYPE_APPLICATION) {
throw "not implemented";
}
// determine application size
if(programMode === this.HEX_TYPE_APPLICATION){
if (programMode === this.HEX_TYPE_APPLICATION) {
applicationSize = firmware.length;
}
@@ -180,7 +174,6 @@ class Nrf52DfuFlasher {
// todo
// sleep(self.dfu_transport.get_activate_wait_time())
}
/**
@@ -190,21 +183,19 @@ class Nrf52DfuFlasher {
* @return {number} - Calculated CRC value of binaryData
*/
calcCrc16(binaryData, crc = 0xffff) {
if(!(binaryData instanceof Uint8Array)){
if (!(binaryData instanceof Uint8Array)) {
throw new Error("calcCrc16 requires Uint8Array input");
}
for(let b of binaryData){
crc = (crc >> 8 & 0x00FF) | (crc << 8 & 0xFF00);
for (let b of binaryData) {
crc = ((crc >> 8) & 0x00ff) | ((crc << 8) & 0xff00);
crc ^= b;
crc ^= (crc & 0x00FF) >> 4;
crc ^= (crc & 0x00ff) >> 4;
crc ^= (crc << 8) << 4;
crc ^= ((crc & 0x00FF) << 4) << 1;
crc ^= ((crc & 0x00ff) << 4) << 1;
}
return crc & 0xFFFF;
return crc & 0xffff;
}
/**
@@ -214,24 +205,22 @@ class Nrf52DfuFlasher {
* @returns {*[]}
*/
slipEncodeEscChars(dataIn) {
let result = [];
for(let i = 0; i < dataIn.length; i++){
for (let i = 0; i < dataIn.length; i++) {
let char = dataIn[i];
if(char === 0xC0){
result.push(0xDB);
result.push(0xDC);
} else if(char === 0xDB) {
result.push(0xDB);
result.push(0xDD);
if (char === 0xc0) {
result.push(0xdb);
result.push(0xdc);
} else if (char === 0xdb) {
result.push(0xdb);
result.push(0xdd);
} else {
result.push(char);
}
}
return result;
}
/**
@@ -241,7 +230,6 @@ class Nrf52DfuFlasher {
* @returns {*[]}
*/
createHciPacketFromFrame(frame) {
// increase sequence number, but roll over at 8
this.sequenceNumber = (this.sequenceNumber + 1) % 8;
@@ -251,27 +239,19 @@ class Nrf52DfuFlasher {
this.DATA_INTEGRITY_CHECK_PRESENT,
this.RELIABLE_PACKET,
this.HCI_PACKET_TYPE,
frame.length,
frame.length
);
// create packet data
let data = [
...slipHeaderBytes,
...frame,
];
let data = [...slipHeaderBytes, ...frame];
// add crc of data
const crc = this.calcCrc16(new Uint8Array(data), 0xffff);
data.push(crc & 0xFF);
data.push((crc & 0xFF00) >> 8);
data.push(crc & 0xff);
data.push((crc & 0xff00) >> 8);
// add escape characters
return [
0xc0,
...this.slipEncodeEscChars(data),
0xc0,
];
return [0xc0, ...this.slipEncodeEscChars(data), 0xc0];
}
/**
@@ -280,7 +260,7 @@ class Nrf52DfuFlasher {
*/
getEraseWaitTime() {
// always wait at least 0.5 seconds
return Math.max(0.5, ((this.total_size / this.FLASH_PAGE_SIZE) + 1) * this.FLASH_PAGE_ERASE_TIME);
return Math.max(0.5, (this.total_size / this.FLASH_PAGE_SIZE + 1) * this.FLASH_PAGE_ERASE_TIME);
}
/**
@@ -306,8 +286,7 @@ class Nrf52DfuFlasher {
* @param app_size
* @returns {Promise<void>}
*/
async sendStartDfu(mode, softdevice_size = 0, bootloader_size = 0, app_size = 0){
async sendStartDfu(mode, softdevice_size = 0, bootloader_size = 0, app_size = 0) {
// create frame
const frame = [
...this.int32ToBytes(this.DFU_START_PACKET),
@@ -324,7 +303,6 @@ class Nrf52DfuFlasher {
// wait for initial erase
await this.sleepMillis(this.getEraseWaitTime() * 1000);
}
/**
@@ -332,8 +310,7 @@ class Nrf52DfuFlasher {
* @param initPacket
* @returns {Promise<void>}
*/
async sendInitPacket(initPacket){
async sendInitPacket(initPacket) {
// create frame
const frame = [
...this.int32ToBytes(this.DFU_INIT_PACKET),
@@ -343,7 +320,6 @@ class Nrf52DfuFlasher {
// send hci packet
await this.sendPacket(this.createHciPacketFromFrame(frame));
}
/**
@@ -353,26 +329,26 @@ class Nrf52DfuFlasher {
* @returns {Promise<void>}
*/
async sendFirmware(firmware, progressCallback) {
const packets = [];
var packetsSent = 0;
// chunk firmware into separate packets
for(let i = 0; i < firmware.length; i += this.DFU_PACKET_MAX_SIZE){
packets.push(this.createHciPacketFromFrame([
...this.int32ToBytes(this.DFU_DATA_PACKET),
...firmware.slice(i, i + this.DFU_PACKET_MAX_SIZE),
]));
for (let i = 0; i < firmware.length; i += this.DFU_PACKET_MAX_SIZE) {
packets.push(
this.createHciPacketFromFrame([
...this.int32ToBytes(this.DFU_DATA_PACKET),
...firmware.slice(i, i + this.DFU_PACKET_MAX_SIZE),
])
);
}
// send initial progress
if(progressCallback){
if (progressCallback) {
progressCallback(0);
}
// send each packet one after the other
for(var i = 0; i < packets.length; i++){
for (var i = 0; i < packets.length; i++) {
// send packet
await this.sendPacket(packets[i]);
@@ -381,18 +357,14 @@ class Nrf52DfuFlasher {
// update progress
packetsSent++;
if(progressCallback){
if (progressCallback) {
const progress = Math.floor((packetsSent / packets.length) * 100);
progressCallback(progress);
}
}
// finished sending firmware, send DFU Stop Data packet
await this.sendPacket(this.createHciPacketFromFrame([
...this.int32ToBytes(this.DFU_STOP_DATA_PACKET),
]));
await this.sendPacket(this.createHciPacketFromFrame([...this.int32ToBytes(this.DFU_STOP_DATA_PACKET)]));
}
/**
@@ -411,9 +383,9 @@ class Nrf52DfuFlasher {
createSlipHeader(seq, dip, rp, pktType, pktLen) {
let ints = [0, 0, 0, 0];
ints[0] = seq | (((seq + 1) % 8) << 3) | (dip << 6) | (rp << 7);
ints[1] = pktType | ((pktLen & 0x000F) << 4);
ints[2] = (pktLen & 0x0FF0) >> 4;
ints[3] = (~(ints[0] + ints[1] + ints[2]) + 1) & 0xFF;
ints[1] = pktType | ((pktLen & 0x000f) << 4);
ints[2] = (pktLen & 0x0ff0) >> 4;
ints[3] = (~(ints[0] + ints[1] + ints[2]) + 1) & 0xff;
return new Uint8Array(ints);
}
@@ -422,13 +394,8 @@ class Nrf52DfuFlasher {
* @param num
* @returns {number[]}
*/
int32ToBytes(num){
return [
(num & 0x000000ff),
(num & 0x0000ff00) >> 8,
(num & 0x00ff0000) >> 16,
(num & 0xff000000) >> 24,
];
int32ToBytes(num) {
return [num & 0x000000ff, (num & 0x0000ff00) >> 8, (num & 0x00ff0000) >> 16, (num & 0xff000000) >> 24];
}
/**
@@ -436,11 +403,7 @@ class Nrf52DfuFlasher {
* @param num
* @returns {number[]}
*/
int16ToBytes(num){
return [
(num & 0x00FF),
(num & 0xFF00) >> 8,
];
int16ToBytes(num) {
return [num & 0x00ff, (num & 0xff00) >> 8];
}
}

View File

File diff suppressed because it is too large Load Diff

View File

File diff suppressed because one or more lines are too long

View File

File diff suppressed because one or more lines are too long