Created
September 28, 2015 00:57
-
-
Save NT7S/d196f61ade7f8009f2b7 to your computer and use it in GitHub Desktop.
JT9 Encoder in C
This file contains hidden or 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
#include <stdio.h> | |
#include <stdint.h> | |
#include <string.h> | |
#include <ctype.h> | |
uint8_t jt_code(char c) | |
{ | |
/* Validate the input then return the proper integer code */ | |
// Return 255 as an error code if the char is not allowed | |
if(isdigit(c)) | |
{ | |
return (uint8_t)(c - 48); | |
} | |
else if(c >= 'A' && c <= 'Z') | |
{ | |
return (uint8_t)(c - 55); | |
} | |
else if(c == ' ') | |
{ | |
return 36; | |
} | |
else if(c == '+') | |
{ | |
return 37; | |
} | |
else if(c == '-') | |
{ | |
return 38; | |
} | |
else if(c == '.') | |
{ | |
return 39; | |
} | |
else if(c == '/') | |
{ | |
return 40; | |
} | |
else if(c == '?') | |
{ | |
return 41; | |
} | |
else | |
{ | |
return 255; | |
} | |
} | |
uint8_t gray_code(uint8_t c) | |
{ | |
return (c >> 1) ^ c; | |
} | |
int main(int argc, char *argv[]) | |
{ | |
uint8_t i, j, k; | |
char message[14] = "NT7S CN85"; | |
// Convert all chars to uppercase | |
// Collapse multiple spaces down to one | |
// Pad the message with trailing spaces | |
uint8_t len = strlen(message); | |
if(len < 13) | |
{ | |
for(i = len; i < 13; i++) | |
{ | |
message[i] = ' '; | |
} | |
} | |
// Print the message | |
printf("Message:\n %s\n\n", message); | |
// Bit packing | |
// ----------- | |
uint8_t c[13]; | |
uint32_t n1, n2, n3; | |
// Find the N values | |
n1 = jt_code(message[0]); | |
n1 = n1 * 42 + jt_code(message[1]); | |
n1 = n1 * 42 + jt_code(message[2]); | |
n1 = n1 * 42 + jt_code(message[3]); | |
n1 = n1 * 42 + jt_code(message[4]); | |
n2 = jt_code(message[5]); | |
n2 = n2 * 42 + jt_code(message[6]); | |
n2 = n2 * 42 + jt_code(message[7]); | |
n2 = n2 * 42 + jt_code(message[8]); | |
n2 = n2 * 42 + jt_code(message[9]); | |
n3 = jt_code(message[10]); | |
n3 = n3 * 42 + jt_code(message[11]); | |
n3 = n3 * 42 + jt_code(message[12]); | |
// Pack bits 15 and 16 of N3 into N1 and N2, | |
// then mask reset of N3 bits | |
n1 = (n1 << 1) + ((n3 >> 15) & 1); | |
n2 = (n2 << 1) + ((n3 >> 16) & 1); | |
n3 = n3 & 0x7fff; | |
// Set the freeform message flag | |
n3 += 32768; | |
// 71 message bits to pack, plus 1 bit flag for freeform message. | |
// 31 zero bits appended to end. | |
// N1 and N2 are 28 bits each, N3 is 16 bits | |
// A little less work to start with the least-significant bits | |
c[3] = (uint8_t)((n1 & 0x0f) << 4); | |
n1 = n1 >> 4; | |
c[2] = (uint8_t)(n1 & 0xff); | |
n1 = n1 >> 8; | |
c[1] = (uint8_t)(n1 & 0xff); | |
n1 = n1 >> 8; | |
c[0] = (uint8_t)(n1 & 0xff); | |
c[6] = (uint8_t)(n2 & 0xff); | |
n2 = n2 >> 8; | |
c[5] = (uint8_t)(n2 & 0xff); | |
n2 = n2 >> 8; | |
c[4] = (uint8_t)(n2 & 0xff); | |
n2 = n2 >> 8; | |
c[3] |= (uint8_t)(n2 & 0x0f); | |
c[8] = (uint8_t)(n3 & 0xff); | |
n3 = n3 >> 8; | |
c[7] = (uint8_t)(n3 & 0xff); | |
c[9] = 0; | |
c[10] = 0; | |
c[11] = 0; | |
c[12] = 0; | |
// Print the 13 8-bit symbols for debugging | |
printf("Packed message, 8-bit symbols:\n "); | |
for(i = 0; i < 13; i++) | |
{ | |
printf("%4u", c[i]); | |
} | |
printf("\n\n"); | |
// Convolutional encoding | |
// ---------------------- | |
// Parity bits are generated from clocking our packed bits into | |
// a LFSR. | |
uint8_t s[206]; | |
uint32_t reg_0 = 0; | |
uint32_t reg_1 = 0; | |
uint32_t reg_temp = 0; | |
uint8_t input_bit, parity_bit; | |
uint8_t bit_count = 0; | |
for(i = 0; i < 13; i++) | |
{ | |
for(j = 0; j < 8; j++) | |
{ | |
// Set input bit according the MSB of current element | |
input_bit = (((c[i] << j) & 0x80) == 0x80) ? 1 : 0; | |
//printf("%d %d %x\n", i, j, input_bit); | |
// Shift both registers and put in the new input bit | |
reg_0 = reg_0 << 1; | |
reg_1 = reg_1 << 1; | |
reg_0 |= (uint32_t)input_bit; | |
reg_1 |= (uint32_t)input_bit; | |
// AND Register 0 with feedback taps, calculate parity | |
reg_temp = reg_0 & 0xf2d05351; | |
parity_bit = 0; | |
for(k = 0; k < 32; k++) | |
{ | |
parity_bit = parity_bit ^ (reg_temp & 0x01); | |
reg_temp = reg_temp >> 1; | |
} | |
s[bit_count] = parity_bit; | |
bit_count++; | |
// AND Register 1 with feedback taps, calculate parity | |
reg_temp = reg_1 & 0xe4613c47; | |
parity_bit = 0; | |
for(k = 0; k < 32; k++) | |
{ | |
parity_bit = parity_bit ^ (reg_temp & 0x01); | |
reg_temp = reg_temp >> 1; | |
} | |
s[bit_count] = parity_bit; | |
bit_count++; | |
if(bit_count >= 206) | |
{ | |
break; | |
} | |
} | |
} | |
// Interleaving | |
// ------------ | |
uint8_t d[206]; | |
uint8_t j0[206]; | |
uint8_t n; | |
k = 0; | |
//n = 0; | |
// Build the interleave table | |
for(i = 0; i < 255; i++) | |
{ | |
n = 0; | |
for(j = 0; j < 8; j++) | |
{ | |
n = (n << 1) + ((i >> j) & 1); | |
} | |
if(n < 206) | |
{ | |
j0[k] = n; | |
k++; | |
} | |
if(k >= 206) | |
{ | |
break; | |
} | |
} | |
// Now do the interleave | |
for(i = 0; i < 206; i++) | |
{ | |
d[j0[i]] = s[i]; | |
} | |
/* | |
printf("Interleaved:\n"); | |
for(i = 0; i < 206; i++) | |
{ | |
printf("%4u", d[i]); | |
} | |
printf("\n\n"); | |
*/ | |
// Pack bits into 3-bit symbols | |
// ---------------------------- | |
uint8_t a[69]; | |
k = 0; | |
memset(a, 0, 69); | |
for(i = 0; i < 69; i++) | |
{ | |
a[i] = (d[k] & 1) << 2; | |
k++; | |
a[i] |= ((d[k] & 1) << 1); | |
k++; | |
a[i] |= (d[k] & 1); | |
k++; | |
} | |
// Gray Code | |
// --------- | |
uint8_t g[69]; | |
for(i = 0; i < 69; i++) | |
{ | |
g[i] = gray_code(a[i]); | |
} | |
/* | |
printf("Gray Code:\n"); | |
for(i = 0; i < 69; i++) | |
{ | |
printf("%2u", g[i]); | |
} | |
printf("\n\n"); | |
*/ | |
/* Merge with sync vector */ | |
uint8_t o[85]; | |
const uint8_t sync_vector[85] = | |
{1, 1, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, | |
0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, | |
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 1, | |
0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, | |
0, 0, 1, 0, 1}; | |
j = 0; | |
for(i = 0; i < 85; i++) | |
{ | |
if(sync_vector[i]) | |
{ | |
o[i] = 0; | |
} | |
else | |
{ | |
o[i] = g[j] + 1; | |
j++; | |
} | |
} | |
printf("Channel Symbols:\n"); | |
for(i = 0; i < 85; i++) | |
{ | |
printf("%2u", o[i]); | |
} | |
printf("\n\n"); | |
return 0; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment