Last active
November 23, 2023 12:11
-
-
Save eurocat2k/5e4e4199a1ede407aeb4e21e43bef949 to your computer and use it in GitHub Desktop.
I5N six bit encoded message decoder in JS
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// An Asterix cat48 data from a PCAP file | |
// 0000 .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. | |
// 0010 .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. .. | |
// 0020 .. .. .. .. .. .. .. .. .. .. 30 00 1f fd c1 02 | |
// 0030 16 0d 6f 4c 75 a8 45 9c 28 c3 0f 93 06 18 4d 24 | |
// 0040 60 5d a6 b1 e3 48 20 00 fd | |
// in case we would like to use static code table - ignored characters replaced by hashtag | |
let sixbitstable = "#ABCDEFGHIJKLMNOPQRSTUVWXYZ##### ###############0123456789######"; | |
// the 6 bit encoded aircraft ID can be found in the line | |
// 0040 .. 5d a6 b1 e3 48 20 .. .. | |
let enc = [0x5d, 0xa6, 0xb1, 0xe3, 0x48, 0x20 ]; | |
let alen = enc.length; | |
let output = []; | |
let isStatic = false; | |
// decode | |
for (let i = 0, j = 0; i < alen; i += 3) { | |
// first sextet from a triple octets represents first octet of the quad word | |
// - first of second part of the 8 octets length aircraft ID | |
let v0 = enc[i] >> 2; | |
// second second sextet encodes second character of the first or second quad word | |
let v1 = ((enc[i] & 0x03) << 4) | (enc[i + 1] >> 4); | |
// third sectet encodes third character of the first or second quad word | |
let v2 = ((enc[i + 1] & 0x0f) << 2) | (enc[i + 2] >> 6); | |
// fourth sectet encodes third character of the first or second quad word | |
let v3 = (enc[i + 2] & 0x3f); | |
// | |
if (isStatic) { | |
// short form | |
console.log({v0: sixbitstable[v0], v1: sixbitstable[v1], v2: sixbitstable[v2], v3: sixbitstable[v3]}); | |
output[j] = sixbitstable[v0]; j += 1; | |
output[j] = sixbitstable[v1]; j += 1; | |
output[j] = sixbitstable[v2]; j += 1; | |
output[j] = sixbitstable[v3]; j += 1; | |
} else { | |
// descriptive form | |
if (v0 >= 1 && v0 <= 26) { // if sextet value is in range 1..26 (inclusively) - they are A-Z characters | |
v0 = String.fromCharCode(v0 + 64); // therefore we need to add 64 to each to obtain ASCII codes | |
} else if (v0 >= 48 && v0 <= 57) { // if sectet is in range 48..57, they are ASCII numbers, leave them | |
v0 = String.fromCharCode(v0); | |
} else if (v0 == 32) { // if sectet equals to 32, it is ASCII SPACE, leave it | |
v0 = String.fromCharCode(v0); | |
} else { | |
v0 = '#'; | |
} | |
output[j] = v0; j += 1; | |
if (v1 >= 1 && v1 <= 26) { | |
v1 = String.fromCharCode(v1 + 64); | |
} else if (v1 >= 48 && v1 <= 57) { | |
v1 = String.fromCharCode(v1); | |
} else if (v1 == 32) { | |
v1 = String.fromCharCode(v1); | |
} else { | |
v1 = '#'; | |
} | |
output[j] = v1; j += 1; | |
if (v2 >= 1 && v2 <= 26) { | |
v2 = String.fromCharCode(v2 + 64); | |
} else if (v2 >= 48 && v2 <= 57) { | |
v2 = String.fromCharCode(v2); | |
} else if (v2 == 32) { | |
v2 = String.fromCharCode(v2); | |
} else { | |
v2 = '#'; | |
} | |
output[j] = v2; j += 1; | |
if (v3 >= 1 && v3 <= 26) { | |
v3 = String.fromCharCode(v3 + 64); | |
} else if (v3 >= 48 && v3 <= 57) { | |
v3 = String.fromCharCode(v3); | |
} else if (v3 == 32) { | |
v3 = String.fromCharCode(v3); | |
} else { | |
v3 = '#'; | |
} | |
output[j] = v3; j += 1; | |
console.log({v0, v1, v2, v3, output: output.join('')}); | |
} | |
// print out | |
} | |
// print the output only | |
console.log({aircraft_Id: output.join('')}); | |
console.log({ | |
decodedLen: output.length, | |
decodedBits: output.length * 8, | |
extrabits: output.length * 2, | |
encodedbits: ((output.length * 8) - (output.length * 2)), | |
encodedLength: (((output.length * 8) - (output.length * 2)) / 8) | |
}); | |
// encode | |
let decodedLen, decodedBits, extrabits, encodedbits, encodedLength, encoded, tmp, input; | |
decodedLen = output.length; | |
decodedBits = output.length * 8; | |
extrabits = output.length * 2; | |
encodedbits = ((output.length * 8) - (output.length * 2)); | |
encodedLength = (((output.length * 8) - (output.length * 2)) / 8); | |
encoded = [], tmp = Array(3); | |
input = output.join(''); | |
for (let i = 0, j = 0; i < decodedLen; i += 4) { | |
let t0, t1, t2, t3; | |
t0 = sixbitstable.indexOf(input[j+i]); | |
t1 = sixbitstable.indexOf(input[j+1+i]); | |
t2 = sixbitstable.indexOf(input[j+2+i]); | |
t3 = sixbitstable.indexOf(input[j+3+i]); | |
// pack into six bits | |
tmp[0] = t0 << 2; | |
tmp[0] |= t1 >> 4 | |
tmp[1] = (t1 & 0x0f) << 4; | |
tmp[1] |= t2 >> 2; | |
tmp[2] = (t2 & 0x0f) << 4; | |
tmp[2] |= t3; | |
encoded = encoded.concat(tmp); | |
console.log({t0:`0x${t0.toString(16)}`, t1:`0x${t1.toString(16)}`, t2:`0x${t2.toString(16)}`, t3: `0x${t3.toString(16)}`, tmp: tmp.map(e => `0x${e.toString(16)}`)}); | |
} | |
console.log({ | |
decodedLen: output.length, | |
decodedBits: output.length * 8, | |
extrabits: output.length * 2, | |
encodedbits: ((output.length * 8) - (output.length * 2)), | |
encodedLength: (((output.length * 8) - (output.length * 2)) / 8), | |
encoded: encoded.map(e => `0x${e.toString(16)}`), | |
tmp: tmp.map(e => `0x${e.toString(16)}`) | |
}); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Simple way(s) to decode 6 bit encoded aircraft ID from ADSB or Asterix CAT048 radar data message.
We can use static method - using sixbittable - slightly straight forward, or the if,else if,else method. Latter describes the decoding well.
We would expect the following output:
or WZZ184 as callsign and its 6 bits encoded octets.