Skip to content

Instantly share code, notes, and snippets.

@nikcorg
Last active July 31, 2020 07:17
Show Gist options
  • Save nikcorg/0490739e92f942c34c8a3d12cf95c694 to your computer and use it in GitHub Desktop.
Save nikcorg/0490739e92f942c34c8a3d12cf95c694 to your computer and use it in GitHub Desktop.
GSM 7 Bit Decoder
// This decoder is based on this answer https://stackoverflow.com/a/21115816
// It's not perfect, e.g. it does not accommodate the extended alphabet.
//
// Solution from SO answer paraphrased below:
//
// For input: C7F7FBCC2E03
// 1) Form tuples for hex numbers and reverse
// -> 03-2E-CC-FB-F7-C7
// 2) Convert hex to 8-bit binary octets
// -> 00000011-00101110-11001100-11111011-11110111-11000111
// 3) Make 7-bit binary septets
// -> 000000-1100101-1101100-1100111-1101111-1101111-1000111
// 4) Discard the first septet
// 5) Convert remaining binary septets to decimal
// 6) Map decimals to ASCII characters (doesn't work for extended alphabet)
// 1000111- 71-G
// 1101111-111-o
// 1101111-111-o
// 1100111-103-g
// 1101100-108-l
// 1100101-101-e
function fromGsm7Bit(s) {
// Split the string to tuples, reverse and join for hex numbers
const hex = aperture(2, s.replace(/\s+/g, "").split(""))
.reverse()
.map(xs => xs.join(""));
// Parse the hex numbers to base 10
const dec = hex.map(s => parseInt(s, 16));
// Map the base 10 numbers to base 2 numbers padded to 8 bits
const bin = dec.map(n => n.toString(2)).map(s => s.padStart(8, 0));
// Split the binary string to 7 bit septets,
// starting from the right side, which is
// the reason for all the reversing.
const bin7 = aperture(
7,
bin
.join("")
.split("")
.reverse()
).map(xs => xs.reverse().join(""));
return bin7
.map(bin => parseInt(bin, 2)) // Again to decimal
.filter(dec => dec > 0) // Omit null chars
.map(dec => String.fromCharCode(dec)) // Then finally to characters
.join("");
}
function aperture(len, xs) {
const ys = xs.slice(0, len);
const zs = xs.slice(len);
if (ys.length === 0) {
return ys;
} else if (ys.length < len) {
return [ys];
}
return [ys].concat(aperture(len, zs));
}
@nikcorg
Copy link
Author

nikcorg commented Dec 11, 2018

Ref: https://mobile.twitter.com/krp_poliisi/status/1072057880386437121

const s = `CB74DAED7ECFE9E1 F0FA0DA2E7F920797 AFD9ED3EBF475DAED0EBB41 797ABA5D9E CFF73F1 0325C06B5CB6936BB0CA2F3D3E8 B43B045A86E9F337889D9EEFF73A1 09A4E8 7CF75AFD7FD7E77C1 DFEC747A9E7699D3 AF7579BEAECFE5E9F57B0E7FB3D3E979FA 45CFBFE1 E1 F43A4C07`;
console.log(fromGsm7Bit(s));

// Output:
// ​​​​​Kiinnostaako ty| rikostutkinnan ytimess{? Hae meille t|ihin! Katso lis{{: https://www.poliisi.fi/keskusrikospoliisi/tyopaikat​​​​​

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment