got pack/unpack working with crc

This commit is contained in:
Lewis Moten
2024-05-14 04:54:24 -04:00
parent 522a925009
commit f32380a301
2 changed files with 78 additions and 89 deletions

View File

@@ -6,10 +6,10 @@ let PACKET_SIZE_BITS = 8;
let DATA_SIZE_BITS = 8; let DATA_SIZE_BITS = 8;
let DATA_SIZE_CRC_BITS = 8; let DATA_SIZE_CRC_BITS = 8;
let DATA_CRC_BITS = 8; let DATA_CRC_BITS = 8;
let BITS_PER_SEGMENT = 1; let BITS_PER_SAMPLE = 1;
let PACKET_ENCODING = false; let IS_ENCODED = false;
let PACKET_ENCODING_SIZE = 7; let PACKET_ENCODED_BLOCK_SIZE = 1;
let PACKET_DECODING_SIZE = 4; let PACKET_DECODED_BLOCK_SIZE = 1;
let ENCODING; let ENCODING;
let PACKET_CRC_BIT_COUNT = 0; let PACKET_CRC_BIT_COUNT = 0;
let PACKET_SEQUENCE_NUMBER_BIT_COUNT = 0; let PACKET_SEQUENCE_NUMBER_BIT_COUNT = 0;
@@ -33,33 +33,38 @@ export const changeConfiguration = (config) => {
DATA_SIZE_BITS = dataSizeBitCount; DATA_SIZE_BITS = dataSizeBitCount;
DATA_SIZE_CRC_BITS = dataSizeCrcBitCount; DATA_SIZE_CRC_BITS = dataSizeCrcBitCount;
DATA_CRC_BITS = dataCrcBitCount; DATA_CRC_BITS = dataCrcBitCount;
BITS_PER_SEGMENT = bitsPerSegment; BITS_PER_SAMPLE = bitsPerSegment;
PACKET_ENCODING = packetEncoding; IS_ENCODED = packetEncoding;
PACKET_ENCODING_SIZE = packetEncodingBitCount; if(IS_ENCODED) {
PACKET_DECODING_SIZE = packetDecodingBitCount; PACKET_ENCODED_BLOCK_SIZE = packetEncodingBitCount;
PACKET_DECODED_BLOCK_SIZE = packetDecodingBitCount;
} else {
PACKET_ENCODED_BLOCK_SIZE = 1;
PACKET_DECODED_BLOCK_SIZE = 1;
}
PACKET_CRC_BIT_COUNT = packetCrcBitCount; PACKET_CRC_BIT_COUNT = packetCrcBitCount;
PACKET_SEQUENCE_NUMBER_BIT_COUNT = packetSequenceNumberBitCount; PACKET_SEQUENCE_NUMBER_BIT_COUNT = packetSequenceNumberBitCount;
} }
export const setEncoding = (encoding) => { export const setEncoding = (encoding) => {
ENCODING = encoding; ENCODING = encoding;
} }
const encodePacket = (packetBits) => isPacketEncoded() ? ENCODING.encode(packetBits) : packetBits; const encodePacket = (packetBits) => IS_ENCODED ? ENCODING.encode(packetBits) : packetBits;
const decodePacket = (packetBits) => isPacketEncoded() ? ENCODING.decode(packetBits) : packetBits; const decodePacket = (packetBits) => IS_ENCODED ? ENCODING.decode(packetBits) : packetBits;
export const getSegmentDurationMilliseconds = () => SEGMENT_DURATION; export const getSegmentDurationMilliseconds = () => SEGMENT_DURATION;
export const getPacketMaxByteCount = () => 2 ** PACKET_SIZE_BITS; export const getPacketMaxByteCount = () => 2 ** PACKET_SIZE_BITS;
export const getPacketMaxBitCount = () => (2 ** PACKET_SIZE_BITS) * 8;
export const getDataMaxByteCount = () => 2 ** DATA_SIZE_BITS; export const getDataMaxByteCount = () => 2 ** DATA_SIZE_BITS;
export const getBitsPerSegment = () => BITS_PER_SEGMENT; export const getPacketEncodedBitCount = () => getPacketEncodingBlockCount() * PACKET_ENCODED_BLOCK_SIZE;
export const isPacketEncoded = () => PACKET_ENCODING; export const getPacketEncodingBlockCount = () =>
export const packetEncodingBlockSize = () => isPacketEncoded() ? PACKET_ENCODING_SIZE : 0; IS_ENCODED ? Math.floor(getPacketMaxBitCount() / PACKET_ENCODED_BLOCK_SIZE) : getPacketMaxBitCount();
export const packetDecodingBlockSize = () => isPacketEncoded() ? PACKET_DECODING_SIZE : 0;
export const getPacketEncodedBitCount = () => {
if(isPacketEncoded()) return getPacketEncodingBlockCount() * PACKET_DECODING_SIZE;
return getPacketMaxBitCount();
}
export const getPacketDataByteCount = () => { export const getPacketDataByteCount = () => {
const availableBitCount = getPacketEncodedBitCount() - getPacketHeaderBitCount(); const availableBitCount = getPacketEncodedBitCount();
const blocks = Math.floor(availableBitCount / PACKET_ENCODED_BLOCK_SIZE);
let decodedBits = blocks * PACKET_DECODED_BLOCK_SIZE;
decodedBits -= getPacketHeaderBitCount()
// We only transfer full bytes within packets // We only transfer full bytes within packets
return Math.floor(availableBitCount / 8); return Math.floor(decodedBits / 8);
} }
export const getPacketDataBitCount = () => getPacketDataByteCount() * 8; export const getPacketDataBitCount = () => getPacketDataByteCount() * 8;
export function fromByteCountGetPacketLastUnusedBitCount(byteCount) { export function fromByteCountGetPacketLastUnusedBitCount(byteCount) {
@@ -69,40 +74,37 @@ export function fromByteCountGetPacketLastUnusedBitCount(byteCount) {
let bitsInLastPacket = bitCount % dataBitsPerPacket; let bitsInLastPacket = bitCount % dataBitsPerPacket;
let usedBits = bitsInLastPacket + getPacketHeaderBitCount() ; let usedBits = bitsInLastPacket + getPacketHeaderBitCount() ;
if(isPacketEncoded()) { if(IS_ENCODED) {
const blocks = Math.ceil(usedBits / packetDecodingBlockSize()) const blocks = Math.ceil(usedBits / PACKET_DECODED_BLOCK_SIZE)
usedBits = blocks * packetEncodingBlockSize(); usedBits = blocks * PACKET_ENCODED_BLOCK_SIZE;
} }
return availableBits - usedBits; return availableBits - usedBits;
} }
export function getPacketLastSegmentUnusedBitCount() { export function getPacketLastSegmentUnusedBitCount() {
return (BITS_PER_SEGMENT - (getPacketMaxBitCount() % BITS_PER_SEGMENT)); return (BITS_PER_SAMPLE - (getPacketMaxBitCount() % BITS_PER_SAMPLE));
} }
export const getBaud = () => { export const getBaud = () => {
return Math.floor(getBitsPerSegment() / getSegmentDurationSeconds()); return Math.floor(BITS_PER_SAMPLE / getSegmentDurationSeconds());
} }
export const getEffectiveBaud = () => { export const getEffectiveBaud = () => {
return Math.floor(getPacketDataBitCount() / getPacketDurationSeconds()); return Math.floor(getPacketDataBitCount() / getPacketDurationSeconds());
} }
export const getEncodedPacketDataBitCount = () => { export const getEncodedPacketDataBitCount = () => {
return isPacketEncoded() ? getPacketEncodingBitCount() : 0; return IS_ENCODED ? getPacketEncodedBitCount() : 0;
} }
export const getPacketUsedBitCount = () => export const getPacketUsedBitCount = () =>
isPacketEncoded() ? getPacketEncodingBitCount() : getPacketMaxBitCount(); IS_ENCODED ? getPacketEncodedBitCount() : getPacketMaxBitCount();
export const getPacketUnusedBitCount = () => getPacketMaxBitCount() - getPacketUsedBitCount(); export const getPacketUnusedBitCount = () => getPacketMaxBitCount() - getPacketUsedBitCount();
export const getMaxPackets = () => export const getMaxPackets = () =>
Math.ceil((getDataMaxByteCount() * 8) / getPacketUsedBitCount()); Math.ceil((getDataMaxByteCount() * 8) / getPacketUsedBitCount());
export const getMaxDurationMilliseconds = () => getMaxPackets() * getPacketDurationMilliseconds(); export const getMaxDurationMilliseconds = () => getMaxPackets() * getPacketDurationMilliseconds();
export const getPacketEncodingBitCount = () => getPacketEncodingBlockCount() * packetEncodingBlockSize();
export const canSendPacket = () => { export const canSendPacket = () => {
let maxBits = getPacketMaxBitCount(); let maxBits = getPacketMaxBitCount();
// Need to be able to send at least 1 data bit with each packet // Need to be able to send at least 1 data bit with each packet
if(maxBits - getPacketHeaderBitCount() < 1) return false; if(maxBits - getPacketHeaderBitCount() < 1) return false;
// Make sure we have enough encoding blocks within a packet // Make sure we have enough encoding blocks within a packet
return isPacketEncoded() ? maxBits >= packetEncodingBlockSize() : true; return IS_ENCODED ? maxBits >= PACKET_ENCODED_BLOCK_SIZE : true;
} }
export const getPacketEncodingBlockCount = () =>
isPacketEncoded() ? Math.floor(getPacketMaxBitCount() / packetEncodingBlockSize()) : 0;
export const getPacketizationHeaderBitCount = () => DATA_SIZE_BITS + DATA_SIZE_CRC_BITS + DATA_CRC_BITS; export const getPacketizationHeaderBitCount = () => DATA_SIZE_BITS + DATA_SIZE_CRC_BITS + DATA_CRC_BITS;
export const getPacketizationBitCountFromBitCount = (bitCount) => bitCount + getPacketizationHeaderBitCount(); export const getPacketizationBitCountFromBitCount = (bitCount) => bitCount + getPacketizationHeaderBitCount();
export const getPacketizationBitCountFromByteCount = (byteCount) => export const getPacketizationBitCountFromByteCount = (byteCount) =>
@@ -133,8 +135,7 @@ export const getDataTransferDurationMilliseconds = (bitCount) =>
getPacketCount(bitCount) * getPacketDurationMilliseconds(); getPacketCount(bitCount) * getPacketDurationMilliseconds();
export const getPacketDurationSeconds = () => getPacketDurationMilliseconds() / 1000; export const getPacketDurationSeconds = () => getPacketDurationMilliseconds() / 1000;
export const getSegmentDurationSeconds = () => getSegmentDurationMilliseconds() / 1000; export const getSegmentDurationSeconds = () => getSegmentDurationMilliseconds() / 1000;
export const getPacketMaxBitCount = () => getPacketMaxByteCount() * 8; export const getPacketSegmentCount = () => Math.ceil(getPacketMaxBitCount() / BITS_PER_SAMPLE);
export const getPacketSegmentCount = () => Math.ceil(getPacketMaxBitCount() / getBitsPerSegment());
export const getPacketDurationMilliseconds = () => export const getPacketDurationMilliseconds = () =>
getPacketSegmentCount() * getSegmentDurationMilliseconds(); getPacketSegmentCount() * getSegmentDurationMilliseconds();
export const getPacketIndex = (transferStartedMilliseconds, time) => export const getPacketIndex = (transferStartedMilliseconds, time) =>
@@ -188,9 +189,9 @@ export const pack = (bits) => ({
const startIndex = packetIndex * dataBitCount; const startIndex = packetIndex * dataBitCount;
const endIndex = startIndex + dataBitCount; const endIndex = startIndex + dataBitCount;
let packetBits = bits.slice(startIndex, endIndex); let packetBits = bits.slice(startIndex, endIndex);
if(packetBits.length % 8 !== 0) {
// add our headers throw new Error('Attempted to create a packet with extra bits.');
const unusedBits = new Array(getPacketHeaderUnusedBitCount()).fill(0); }
// data byte count // data byte count
let byteCount = Math.ceil(packetBits.length / 8); let byteCount = Math.ceil(packetBits.length / 8);
@@ -199,34 +200,37 @@ export const pack = (bits) => ({
// sequence number // sequence number
if(PACKET_SEQUENCE_NUMBER_BIT_COUNT !== 0) { if(PACKET_SEQUENCE_NUMBER_BIT_COUNT !== 0) {
sequenceNumberBits = numberToBits(packetIndex, PACKET_SEQUENCE_NUMBER_BIT_COUNT); sequenceNumberBits = numberToBits(packetIndex, PACKET_SEQUENCE_NUMBER_BIT_COUNT);
if(packetIndex < 3)
console.log('write sequence %s', packetIndex, packetIndex.toString(2));
} }
// add our headers
const headerBits = [ const headerBits = [
...sequenceNumberBits, ...sequenceNumberBits,
...dataLengthBits, ...dataLengthBits,
...unusedBits ...new Array(getPacketHeaderUnusedBitCount()).fill(0)
] ]
if(PACKET_CRC_BIT_COUNT !== 0) { if(PACKET_CRC_BIT_COUNT !== 0) {
// convert to bytes // convert to bytes
const bytes = bitsToBytes([...headerBits, ...packetBits]); const crcCheckBits = [...headerBits, ...packetBits];
console.log('crc check bits', crcCheckBits.length) // 136 bits
const bytes = bitsToBytes(crcCheckBits);
const crc = CRC.check(bytes, PACKET_CRC_BIT_COUNT); const crc = CRC.check(bytes, PACKET_CRC_BIT_COUNT);
const crcBits = numberToBits(crc, PACKET_CRC_BIT_COUNT); const crcBits = numberToBits(crc, PACKET_CRC_BIT_COUNT);
if(packetIndex < 3) if(packetIndex === 0) {
console.log('write packet %s crc 0b%s', packetIndex, crc.toString(2)); console.log('header without crc was', headerBits.length)
console.log('we did crc on this', crcCheckBits.join(''))
}
// CRC must be first // CRC must be first
headerBits.unshift(...crcBits); headerBits.unshift(...crcBits);
} }
packetBits.unshift(...headerBits); packetBits.unshift(...headerBits);
if(packetIndex < 3) {
console.log('WRITE packet %s bits', packetIndex, packetBits.slice(0, 20).join(''));
}
// encode our packet // encode our packet
const encodedBits = encodePacket(packetBits); const encodedBits = encodePacket(packetBits);
if(encodedBits.length > 2 ** PACKET_SIZE_BITS * 8) {
throw new Error(`Attempted to create packet exceeding ${2 ** PACKET_SIZE_BITS * 8} bits with ${encodedBits.length} bits.`);
}
return encodedBits; return encodedBits;
} }
}); });
@@ -247,63 +251,50 @@ export const unpack = (bits) => ({
packetBits = packetBits.slice(0, getPacketMaxBitCount()); packetBits = packetBits.slice(0, getPacketMaxBitCount());
// Remove extra bits not used by encoding // Remove extra bits not used by encoding
if(isPacketEncoded()) { if(IS_ENCODED) {
packetBits.splice(0, getPacketEncodedBitCount()); packetBits.splice(getPacketEncodedBitCount());// before or after... i thik we need encoded. 144 is too small for 256 available
packetBits = decodePacket(packetBits); packetBits = decodePacket(packetBits);
} }
if(packetIndex < 3) {
console.log('READ packet %s bits', packetIndex, packetBits.slice(0, 20).join(''));
}
const extraHeaderBitCount = getPacketHeaderUnusedBitCount();
const headerBitCount = getPacketHeaderBitCount(); const headerBitCount = getPacketHeaderBitCount();
// Detect data size // Get data size
const sizeBits = packetBits.slice(PACKET_CRC_BIT_COUNT + PACKET_SEQUENCE_NUMBER_BIT_COUNT, PACKET_SIZE_BITS); const sizeBits = packetBits.slice(
const dataSizeByteCount = numberToBytes(sizeBits, PACKET_SIZE_BITS); PACKET_CRC_BIT_COUNT + PACKET_SEQUENCE_NUMBER_BIT_COUNT,
unpacked.size = dataSizeByteCount PACKET_CRC_BIT_COUNT + PACKET_SEQUENCE_NUMBER_BIT_COUNT + PACKET_SIZE_BITS
);
const dataSizeByteCount = bitsToInt(sizeBits, PACKET_SIZE_BITS);
unpacked.size = dataSizeByteCount;
// Process CRC header FIRST (ensures all other headers are valid) // Get sequence number
if(PACKET_SEQUENCE_NUMBER_BIT_COUNT === 0) {
unpacked.sequence = packetIndex;
} else {
const sequenceBits = packetBits.slice(
PACKET_CRC_BIT_COUNT,
PACKET_CRC_BIT_COUNT + PACKET_SEQUENCE_NUMBER_BIT_COUNT
);
const sequence = bitsToInt(sequenceBits, PACKET_SEQUENCE_NUMBER_BIT_COUNT);
unpacked.sequence = sequence;
}
// Get CRC Header
if(PACKET_CRC_BIT_COUNT !== 0) { if(PACKET_CRC_BIT_COUNT !== 0) {
const crcBits = packetBits.slice(0, PACKET_CRC_BIT_COUNT); const crcBits = packetBits.slice(0, PACKET_CRC_BIT_COUNT);
const expectedCrc = bitsToInt(crcBits, PACKET_CRC_BIT_COUNT); const expectedCrc = bitsToInt(crcBits, PACKET_CRC_BIT_COUNT);
if(packetIndex < 3) {
console.log('read packet %s crc', packetIndex, numberToHex(PACKET_CRC_BIT_COUNT)(expectedCrc))
}
unpacked.crc = expectedCrc; unpacked.crc = expectedCrc;
// Run CRC on all bits except CRC header // Run CRC on all bits except CRC header
const crcLength = (headerBitCount - PACKET_CRC_BIT_COUNT) + (dataSizeByteCount * 8); const bitCountToCheck = (headerBitCount - PACKET_CRC_BIT_COUNT) + (dataSizeByteCount * 8);
const crcCopy = packetBits.slice(PACKET_CRC_BIT_COUNT, crcLength); const crcCopy = packetBits.slice(PACKET_CRC_BIT_COUNT, PACKET_CRC_BIT_COUNT + bitCountToCheck);
// check the crc is valid // check the crc is valid
const bytes = bitsToBytes(crcCopy); const bytes = bitsToBytes(crcCopy);
unpacked.actualCrc = CRC.check(bytes, PACKET_CRC_BIT_COUNT); unpacked.actualCrc = CRC.check(bytes, PACKET_CRC_BIT_COUNT);
// remove CRC header
packetBits.splice(0, PACKET_CRC_BIT_COUNT);
} }
// Process sequence header // Get data bits
if(PACKET_SEQUENCE_NUMBER_BIT_COUNT === 0) { packetBits = packetBits.slice(headerBitCount, headerBitCount + unpacked.size * 8);
unpacked.sequence = packetIndex;
} else {
const sequenceBits = packetBits.slice(0, PACKET_SEQUENCE_NUMBER_BIT_COUNT);
const sequence = bitsToInt(sequenceBits, PACKET_SEQUENCE_NUMBER_BIT_COUNT);
if(packetIndex < 3)
console.log('read packetIndex %s as sequence %s', packetIndex, sequence, sequenceBits.join(''))
unpacked.sequence = sequence;
// remove sequence number header
packetBits.splice(0, PACKET_SEQUENCE_NUMBER_BIT_COUNT);
}
// Remove packet size header
packetBits.splice(0, PACKET_SIZE_BITS);
// remove unused header bits
if(extraHeaderBitCount !== 0) packetBits.splice(0, extraHeaderBitCount);
// Reduce remaining data to proper size
packetBits.splice(0, unpacked.size * 8);
// convert to bytes // convert to bytes
unpacked.bytes = bitsToBytes(packetBits); unpacked.bytes = bitsToBytes(packetBits);
@@ -322,13 +313,12 @@ export const unpack = (bits) => ({
if(!canSendPacket()) return unpacked; if(!canSendPacket()) return unpacked;
// Get bits associated with the packet // Get bits associated with the packet
const packetBitCount = getPacketSegmentCount() + BITS_PER_SEGMENT; const packetBitCount = getPacketSegmentCount() + BITS_PER_SAMPLE;
const offset = packetIndex * packetBitCount; const offset = packetIndex * packetBitCount;
const packetBits = bits.slice(offset, offset + packetBitCount); const packetBits = bits.slice(offset, offset + packetBitCount);
if(packetBits.length === 0) return unpacked; if(packetBits.length === 0) return unpacked;
return this.getPacketFromBits(packetBits, packetIndex); return this.getPacketFromBits(packetBits, packetIndex);
} }
}); });

View File

@@ -65,7 +65,6 @@ export const applyPacket = ({
bytes, bytes,
size size
}) => { }) => {
console.log('apply packet %s (sequence %s) crc %s was %s', packetIndex, sequence, numberToHex(8)(crc), numberToHex(8)(actualCrc));
const dataSize = PacketUtils.getPacketDataByteCount(); const dataSize = PacketUtils.getPacketDataByteCount();
const offset = sequence * dataSize; const offset = sequence * dataSize;
const length = offset + dataSize; const length = offset + dataSize;