introduce interlacing
This commit is contained in:
68
index.js
68
index.js
@@ -30,6 +30,7 @@ var SMOOTHING_TIME_CONSTANT = 0;
|
|||||||
var HAMMING_ERROR_CORRECTION = true;
|
var HAMMING_ERROR_CORRECTION = true;
|
||||||
let PERIODIC_INTERLEAVING = true;
|
let PERIODIC_INTERLEAVING = true;
|
||||||
|
|
||||||
|
const ERROR_CORRECTION_BLOCK_SIZE = 7;
|
||||||
let CHANNEL_OVER = -1;
|
let CHANNEL_OVER = -1;
|
||||||
let CHANNEL_SELECTED = -1;
|
let CHANNEL_SELECTED = -1;
|
||||||
let SEGMENT_OVER = -1;
|
let SEGMENT_OVER = -1;
|
||||||
@@ -203,7 +204,7 @@ function showSpeed() {
|
|||||||
document.getElementById('data-transfer-speed-bits-per-second').innerText = baud.toFixed(2);
|
document.getElementById('data-transfer-speed-bits-per-second').innerText = baud.toFixed(2);
|
||||||
document.getElementById('data-transfer-speed-bytes-per-second').innerText = bytes.toFixed(2);
|
document.getElementById('data-transfer-speed-bytes-per-second').innerText = bytes.toFixed(2);
|
||||||
if(HAMMING_ERROR_CORRECTION) {
|
if(HAMMING_ERROR_CORRECTION) {
|
||||||
const effectiveBaud = baud * 4 / 7;
|
const effectiveBaud = baud * 4 / ERROR_CORRECTION_BLOCK_SIZE;
|
||||||
const effectiveBytes = effectiveBaud / 8;
|
const effectiveBytes = effectiveBaud / 8;
|
||||||
document.getElementById('effective-speed-bits-per-second').innerText = effectiveBaud.toFixed(2);
|
document.getElementById('effective-speed-bits-per-second').innerText = effectiveBaud.toFixed(2);
|
||||||
document.getElementById('effective-speed-bytes-per-second').innerText = effectiveBytes.toFixed(2);
|
document.getElementById('effective-speed-bytes-per-second').innerText = effectiveBytes.toFixed(2);
|
||||||
@@ -295,7 +296,7 @@ function nibbleToHamming(nibble) {
|
|||||||
]
|
]
|
||||||
}
|
}
|
||||||
function hammingToNibble(hamming) {
|
function hammingToNibble(hamming) {
|
||||||
if(hamming.length !== 7) return [];
|
if(hamming.length !== ERROR_CORRECTION_BLOCK_SIZE) return [];
|
||||||
const error_1 = hamming[0] ^ hamming[2] ^ hamming[4] ^ hamming[6];
|
const error_1 = hamming[0] ^ hamming[2] ^ hamming[4] ^ hamming[6];
|
||||||
const error_2 = hamming[1] ^ hamming[2] ^ hamming[5] ^ hamming[6];
|
const error_2 = hamming[1] ^ hamming[2] ^ hamming[5] ^ hamming[6];
|
||||||
const error_3 = hamming[3] ^ hamming[4] ^ hamming[5] ^ hamming[6];
|
const error_3 = hamming[3] ^ hamming[4] ^ hamming[5] ^ hamming[6];
|
||||||
@@ -317,17 +318,24 @@ function getFrequency(bit) {
|
|||||||
return bit ? MAXIMUM_FREQUENCY : MINIMUM_FREQUENCY;
|
return bit ? MAXIMUM_FREQUENCY : MINIMUM_FREQUENCY;
|
||||||
}
|
}
|
||||||
function removeInterleaving(bits) {
|
function removeInterleaving(bits) {
|
||||||
return applyInterleaving(bits);
|
return applyInterleaving(bits, true);
|
||||||
}
|
}
|
||||||
function applyInterleaving(bits) {
|
function applyInterleaving(bits, undo = false) {
|
||||||
|
// Not turned on
|
||||||
if(!PERIODIC_INTERLEAVING) return bits;
|
if(!PERIODIC_INTERLEAVING) return bits;
|
||||||
|
|
||||||
|
// Only applicable for error correction
|
||||||
|
if(!HAMMING_ERROR_CORRECTION) return bits;
|
||||||
|
|
||||||
const channels = getChannels();
|
const channels = getChannels();
|
||||||
const channelCount = channels.length;
|
const channelCount = channels.length;
|
||||||
// We need at least 4 channels to swap odd numbered bits
|
|
||||||
if(channelCount < 4) return bits;
|
// We need at least 1 extra channel for one bit to escape the block
|
||||||
// Determine what the center channel index is
|
if(channelCount < ERROR_CORRECTION_BLOCK_SIZE + 1) return bits;
|
||||||
const centerIndex = Math.floor(channelCount / 2);
|
|
||||||
if(centerIndex % 2 === 1) centerIndex++;
|
const blockCount = Math.ceil(channelCount / ERROR_CORRECTION_BLOCK_SIZE);
|
||||||
|
// need another block to swap bits with
|
||||||
|
if(blockCount < 2) return bits;
|
||||||
|
|
||||||
// ensure last segment has enough bits to swap
|
// ensure last segment has enough bits to swap
|
||||||
while(bits.length % channelCount !== 0) bits.push(0);
|
while(bits.length % channelCount !== 0) bits.push(0);
|
||||||
@@ -336,26 +344,34 @@ function applyInterleaving(bits) {
|
|||||||
for(let i = 0; i < bits.length; i+= channelCount) {
|
for(let i = 0; i < bits.length; i+= channelCount) {
|
||||||
|
|
||||||
// Grab the bits for the segment
|
// Grab the bits for the segment
|
||||||
const segment = bits.slice(i, i + channelCount);
|
let segment = bits.slice(i, i + channelCount);
|
||||||
|
segment = staggerValues(segment, ERROR_CORRECTION_BLOCK_SIZE, undo);
|
||||||
|
|
||||||
// Loop through the odd bits up to the center channel
|
|
||||||
for(let fromIndex = 1; fromIndex < centerIndex; fromIndex += 2) {
|
|
||||||
// Identify the target bit to swap
|
|
||||||
const targetIndex = (fromIndex + centerIndex);
|
|
||||||
|
|
||||||
// remember the bits
|
|
||||||
const bitA = segment[fromIndex];
|
|
||||||
const bitB = segment[targetIndex];
|
|
||||||
|
|
||||||
// swap the bits
|
|
||||||
segment[targetIndex] = bitA;
|
|
||||||
segment[fromIndex] = bitB;
|
|
||||||
}
|
|
||||||
// update the bits with the modified segment
|
// update the bits with the modified segment
|
||||||
bits.splice(i, channelCount, ...segment);
|
bits.splice(i, channelCount, ...segment);
|
||||||
}
|
}
|
||||||
return bits;
|
return bits;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function staggerValues(values, blockSize, undo) {
|
||||||
|
// loop through bit indexes of a block
|
||||||
|
for(let blockMovement = 1; blockMovement < blockSize; blockMovement++) {
|
||||||
|
values.filter((_, i) =>
|
||||||
|
// values to be moved to different blocks
|
||||||
|
i % blockSize === blockMovement
|
||||||
|
).map((_,i,a) => {
|
||||||
|
// bit values moved N blocks
|
||||||
|
if(undo) i -= blockMovement; else i += blockMovement;
|
||||||
|
i = ((i % a.length) + a.length) % a.length;
|
||||||
|
return a[i];
|
||||||
|
}).forEach((v, i) => {
|
||||||
|
// replace with new values
|
||||||
|
values[blockMovement + (i * blockSize)] = v;
|
||||||
|
})
|
||||||
|
};
|
||||||
|
return values;
|
||||||
|
}
|
||||||
|
|
||||||
function applyErrorCorrection(bits) {
|
function applyErrorCorrection(bits) {
|
||||||
if(!HAMMING_ERROR_CORRECTION) return bits;
|
if(!HAMMING_ERROR_CORRECTION) return bits;
|
||||||
const encodedBits = [];
|
const encodedBits = [];
|
||||||
@@ -637,11 +653,11 @@ if((sampleDuration / SEGMENT_DURATION) < LAST_SEGMENT_PERCENT) return;
|
|||||||
packetReceivedBits.push(...bitValues);
|
packetReceivedBits.push(...bitValues);
|
||||||
packetUninterlievedBits.push(...removeInterleaving(bitValues));
|
packetUninterlievedBits.push(...removeInterleaving(bitValues));
|
||||||
|
|
||||||
const encodingRatio = HAMMING_ERROR_CORRECTION ? 7/4 : 1;
|
const encodingRatio = HAMMING_ERROR_CORRECTION ? ERROR_CORRECTION_BLOCK_SIZE/4 : 1;
|
||||||
if(HAMMING_ERROR_CORRECTION) {
|
if(HAMMING_ERROR_CORRECTION) {
|
||||||
packetDecodedBits.length = 0;
|
packetDecodedBits.length = 0;
|
||||||
for(let i = 0; i < packetUninterlievedBits.length; i += 7) {
|
for(let i = 0; i < packetUninterlievedBits.length; i += ERROR_CORRECTION_BLOCK_SIZE) {
|
||||||
const hamming = packetUninterlievedBits.slice(i, i + 7);
|
const hamming = packetUninterlievedBits.slice(i, i + ERROR_CORRECTION_BLOCK_SIZE);
|
||||||
const nibble = hammingToNibble(hamming);
|
const nibble = hammingToNibble(hamming);
|
||||||
packetDecodedBits.push(...nibble);
|
packetDecodedBits.push(...nibble);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user