Skip to content

Instantly share code, notes, and snippets.

@NT7S NT7S/jt9_encode.c
Created Sep 28, 2015

Embed
What would you like to do?
JT9 Encoder in C
#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
You can’t perform that action at this time.