//==========================================================================
#include <assert.h>
+#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/*
output is an unpacked array of bits of maximum size max_out. Note
unpacked arrays are a more suitable form for modulator input.
+
+ longcode == 1 varicode table that covers entire ASCII char set
+ longcode == 0 is the short, more efficient table, which covers a subset of the ASCII char set. Unknown
+ chars are replaced with spaces. This mode works with two bits at a time.
*/
-int varicode_encode(short varicode_out[], char ascii_in[], int max_out, int n_in) {
- int n_out, index, n_zeros, v_len;
+int varicode_encode(short varicode_out[], char ascii_in[], int max_out, int n_in, int long_code) {
+ int n_out, index, n_zeros, v_len, i;
unsigned short byte1, byte2, packed;
n_out = 0;
while(n_in && (n_out < max_out)) {
- assert((unsigned int)(*ascii_in) < 128);
+ if (long_code) {
+ assert((unsigned int)(*ascii_in) < 128);
+
+ index = 2*(unsigned int)(*ascii_in);
+ byte1 = long_varicode_table[index];
+ byte2 = long_varicode_table[index+1];
+ packed = (byte1 << 8) + byte2;
+ }
+ else {
+
+ packed = short_varicode_table[0]; // default to space if char not found
+
+ // see if our character exists
+ for(i=0; i<sizeof(short_varicode_table); i+=2) {
+ if (short_varicode_table[i] == *ascii_in)
+ packed = (unsigned short)short_varicode_table[i+1] << 8;
+ }
+ }
- index = 2*(unsigned int)(*ascii_in);
- byte1 = varicode_table[index];
- byte2 = varicode_table[index+1];
- packed = (byte1 << 8) + byte2;
//printf("n_in: %d ascii_in: %c index: %d packed 0x%x\n", n_in, *ascii_in, index, packed);
ascii_in++;
n_zeros = 0;
v_len = 0;
while ((n_zeros < 2) && (n_out < max_out) && (v_len <= VARICODE_MAX_BITS)) {
- if (packed & 0x8000) {
- *varicode_out = 1;
- n_zeros = 0;
+ if (long_code) {
+ if (packed & 0x8000) {
+ *varicode_out = 1;
+ n_zeros = 0;
+ }
+ else {
+ *varicode_out = 0;
+ n_zeros++;
+ }
+ //printf("packed: 0x%x *varicode_out: %d n_zeros: %d v_len: %d\n", packed, *varicode_out, n_zeros,v_len );
+ packed <<= 1;
+ varicode_out++;
+ n_out++;
+ v_len++;
}
else {
- *varicode_out = 0;
- n_zeros++;
- }
- //printf("packed: 0x%x *varicode_out: %d n_zeros: %d v_len: %d\n", packed, *varicode_out, n_zeros,v_len );
- packed <<= 1;
- varicode_out++;
-
- n_out++;
- v_len++;
+ if (packed & 0x8000)
+ varicode_out[0] = 1;
+ else
+ varicode_out[0] = 0;
+
+ if (packed & 0x4000)
+ varicode_out[1] = 1;
+ else
+ varicode_out[1] = 0;
+
+ if (packed & 0xc000)
+ n_zeros = 0;
+ else
+ n_zeros += 2;
+
+ //printf("packed: 0x%x *varicode_out: %d n_zeros: %d v_len: %d\n", packed, *varicode_out, n_zeros,v_len );
+ packed <<= 2;
+ varicode_out +=2;
+ n_out += 2;
+ v_len += 2;
+ }
+
}
assert(v_len <= VARICODE_MAX_BITS);
- n_in--;
-
+ n_in--;
}
return n_out;
dec_states->packed = 0;
}
-static int decode_one_bit(struct VARICODE_DEC *s, char *single_ascii, short varicode_in)
+static int decode_one_bit(struct VARICODE_DEC *s, char *single_ascii, short varicode_in1, short varicode_in2, int long_code)
{
int found, i;
unsigned short byte1, byte2;
// s->state, varicode_in, s->packed, s->n_zeros);
if (s->state == 0) {
- if (!varicode_in)
- return 0;
- else
- s->state = 1;
+ if (long_code) {
+ if (!varicode_in1)
+ return 0;
+ else
+ s->state = 1;
+ }
+ else {
+ if (!(varicode_in1 || varicode_in2))
+ return 0;
+ else
+ s->state = 1;
+ }
+
}
if (s->state == 1) {
- if (varicode_in) {
- s->packed |= (0x8000 >> s->v_len);
- s->n_zeros = 0;
+ if (long_code) {
+ if (varicode_in1) {
+ s->packed |= (0x8000 >> s->v_len);
+ s->n_zeros = 0;
+ }
+ else {
+ s->n_zeros++;
+ }
+ s->v_len++;
}
else {
- s->n_zeros++;
+ if (varicode_in1)
+ s->packed |= (0x8000 >> s->v_len);
+ if (varicode_in2)
+ s->packed |= (0x4000 >> s->v_len);
+ if (varicode_in1 || varicode_in2)
+ s->n_zeros = 0;
+ else
+ s->n_zeros+=2;
+
+ s->v_len+=2;
}
- s->v_len++;
found = 0;
if (s->n_zeros == 2) {
if (s->v_len) {
- byte1 = s->packed >> 8;
- byte2 = s->packed & 0xff;
-
- /* run thru table but note with bit errors means we might
- not actually find a match */
+ /* run thru table but note with bit errors we might not actually find a match */
- for(i=0; i<128; i++) {
- if ((byte1 == varicode_table[2*i]) && (byte2 == varicode_table[2*i+1])) {
- found = 1;
- *single_ascii = i;
+ byte1 = s->packed >> 8;
+ //printf("looking for byte1 : 0x%x ... ", byte1);
+ if (long_code) {
+ byte2 = s->packed & 0xff;
+
+ for(i=0; i<128; i++) {
+ if ((byte1 == long_varicode_table[2*i]) && (byte2 == long_varicode_table[2*i+1])) {
+ found = 1;
+ *single_ascii = i;
+ }
+ }
+ }
+ else {
+ for(i=0; i<sizeof(short_varicode_table); i+=2) {
+ //printf("byte1: 0x%x 0x%x\n", byte1, (unsigned char)short_varicode_table[i+1]);
+ if (byte1 == (unsigned char)short_varicode_table[i+1]) {
+ found = 1;
+ *single_ascii = short_varicode_table[i];
+ //printf("found: %d i=%d char=%c ", found, i, *single_ascii);
+ }
}
}
+ //printf("\n");
}
varicode_decode_init(s);
}
return found;
}
-int varicode_decode(struct VARICODE_DEC *dec_states, char ascii_out[], short varicode_in[], int max_out, int n_in) {
+int varicode_decode(struct VARICODE_DEC *dec_states, char ascii_out[], short varicode_in[], int max_out, int n_in, int long_code) {
int output, n_out;
char single_ascii;
//printf("varicode_decode: n_in: %d\n", n_in);
while(n_in && (n_out < max_out)) {
- output = decode_one_bit(dec_states, &single_ascii, *varicode_in);
- varicode_in++;
- n_in--;
+ if (long_code) {
+ output = decode_one_bit(dec_states, &single_ascii, varicode_in[0], 0, long_code);
+ varicode_in++;
+ n_in--;
+ }
+ else {
+ output = decode_one_bit(dec_states, &single_ascii, varicode_in[0], varicode_in[1], long_code);
+ varicode_in +=2;
+ n_in -= 2;
+ }
+
if (output) {
*ascii_out++ = single_ascii;
n_out++;
#ifdef VARICODE_UNITTEST
-int main(void) {
+void test_varicode(int long_code) {
char *ascii_in;
short *varicode;
int i, n_varicode_bits_out, n_ascii_chars_out, length, half;
char *ascii_out;
struct VARICODE_DEC dec_states;
- length = sizeof(varicode_table)/2;
-
+ if (long_code) {
+ printf("long code:\n");
+ length = sizeof(long_varicode_table)/2;
+ }
+ else {
+ printf("short code:\n");
+ length = sizeof(short_varicode_table)/2;
+ }
+ //length = 10;
ascii_in = (char*)malloc(length);
varicode = (short*)malloc(VARICODE_MAX_BITS*sizeof(short)*length);
ascii_out = (char*)malloc(length);
-
+
// 1. test all Varicode codes -------------------------------------------------------------
- for(i=0; i<length; i++)
- ascii_in[i] = (char)i;
- n_varicode_bits_out = varicode_encode(varicode, ascii_in, VARICODE_MAX_BITS*length, length);
+ if (long_code) {
+ for(i=0; i<length; i++)
+ ascii_in[i] = (char)i;
+ }
+ else {
+ for(i=0; i<length; i++)
+ ascii_in[i] = short_varicode_table[2*i];
+ }
+ //printf(" ascii_in: %s\n", ascii_in);
+ n_varicode_bits_out = varicode_encode(varicode, ascii_in, VARICODE_MAX_BITS*length, length, long_code);
- //printf("n_varicode_bits_out: %d\n", n_varicode_bits_out);
+ printf(" n_varicode_bits_out: %d\n", n_varicode_bits_out);
+ //for(i=0; i<n_varicode_bits_out; i++) {
+ // printf("%d \n", varicode[i]);
+ //}
// split decode in half to test how it preseves state between calls
varicode_decode_init(&dec_states);
half = n_varicode_bits_out/2;
- n_ascii_chars_out = varicode_decode(&dec_states, ascii_out, varicode, length, half);
- //printf("n_ascii_chars_out: %d\n", n_ascii_chars_out);
+ n_ascii_chars_out = varicode_decode(&dec_states, ascii_out, varicode, length, half, long_code);
+ // printf(" n_ascii_chars_out: %d\n", n_ascii_chars_out);
n_ascii_chars_out += varicode_decode(&dec_states, &ascii_out[n_ascii_chars_out],
- &varicode[half], length-n_ascii_chars_out, n_varicode_bits_out - half);
+ &varicode[half], length-n_ascii_chars_out, n_varicode_bits_out - half, long_code);
//printf("n_ascii_chars_out: %d\n", n_ascii_chars_out);
assert(n_ascii_chars_out == length);
- //for(i=0; i<n_varicode_bits_out; i++) {
- // printf("%d \n", varicode[i]);
- //}
-
//printf("ascii_out: %s\n", ascii_out);
if (memcmp(ascii_in, ascii_out, length) == 0)
- printf("Test 1 Pass\n");
+ printf(" Test 1 Pass\n");
else
- printf("Test 1 Fail\n");
+ printf(" Test 1 Fail\n");
// 2. Test some ascii with a run of zeros -----------------------------------------------------
sprintf(ascii_in, "CQ CQ CQ, this is VK5DGR");
+
assert(strlen(ascii_in) < length);
+ if (long_code == 0)
+ for(i=0; i<strlen(ascii_in); i++)
+ ascii_in[i] = tolower(ascii_in[i]);
for(i=0; i<3; i++) {
- n_varicode_bits_out = varicode_encode(varicode, ascii_in, VARICODE_MAX_BITS*length, strlen(ascii_in));
- n_ascii_chars_out = varicode_decode(&dec_states, ascii_out, varicode, length, n_varicode_bits_out);
+ n_varicode_bits_out = varicode_encode(varicode, ascii_in, VARICODE_MAX_BITS*length, strlen(ascii_in), long_code);
+ n_ascii_chars_out = varicode_decode(&dec_states, ascii_out, varicode, length, n_varicode_bits_out, long_code);
ascii_out[n_ascii_chars_out] = 0;
printf("ascii_out: %s\n", ascii_out);
if (strcmp(ascii_in, ascii_out) == 0)
- printf("Test 2 Pass\n");
+ printf(" Test 2 Pass\n");
else
- printf("Test 2 Fail\n");
+ printf(" Test 2 Fail\n");
memset(varicode, 0, sizeof(short)*20);
- n_ascii_chars_out = varicode_decode(&dec_states, ascii_out, varicode, length, 20);
+ n_ascii_chars_out = varicode_decode(&dec_states, ascii_out, varicode, length, 20, long_code);
assert(n_ascii_chars_out == 0);
}
free(ascii_in);
free(ascii_out);
free(varicode);
+}
+int main(void) {
+ test_varicode(0);
+ test_varicode(1);
return 0;
}
#endif