--- /dev/null
+//==========================================================================
+// Name: varicode.h
+// Purpose: Varicode encoded and decode functions
+// Created: Nov 24, 2012
+// Authors: David Rowe
+//
+// To test:
+// $ gcc varicode.c -o varicode -DVARICODE_UNITTEST -Wall
+// $ ./varicode
+//
+// License:
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2.1,
+// as published by the Free Software Foundation. This program is
+// distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+// License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, see <http://www.gnu.org/licenses/>.
+//
+//==========================================================================
+
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "varicode.h"
+#include "varicode_table.h"
+
+#define VARICODE_MAX_BITS (10+2) /* 10 bits for code plus 2 0 bits for inter-character space */
+
+/*
+ output is an unpacked array of bits of maximum size max_out. Note
+ unpacked arrays are a more suitable form for modulator input.
+*/
+
+int varicode_encode(int varicode_out[], char ascii_in[], int max_out, int n_in) {
+ int n_out, index, n_zeros, v_len;
+ unsigned short byte1, byte2, packed;
+
+ n_out = 0;
+
+ while(n_in && (n_out < max_out)) {
+
+ assert((unsigned int)(*ascii_in) < 128);
+
+ 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;
+ }
+ 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++;
+ }
+ assert(v_len <= VARICODE_MAX_BITS);
+
+ n_in--;
+
+ }
+
+ return n_out;
+}
+
+int varicode_decode(char ascii_out[], int varicode_in[], int max_out, int n_in) {
+ int i, n_out, n_zeros, found, v_len;
+ unsigned short byte1, byte2, packed;
+
+ n_out = 0;
+
+ //printf("max_out: %d n_in: %d\n", max_out, n_in);
+ while(n_in && (n_out < max_out)) {
+
+ n_zeros = 0;
+ v_len = 0;
+ packed = 0;
+ while ((n_zeros < 2) && n_in && (v_len <= VARICODE_MAX_BITS)) {
+ if (*varicode_in++) {
+ packed |= (0x8000 >> v_len);
+ n_zeros = 0;
+ }
+ else {
+ n_zeros++;
+ }
+ n_in--;
+ v_len++;
+ }
+
+ //printf("packed: 0x%x n_zeros: %d v_len: %d n_in: %d\n", packed, n_zeros, v_len, n_in);
+
+ /* v_len might be > VARICODE_MAX_BITS is an error condition */
+
+ if (v_len && (v_len <= VARICODE_MAX_BITS)) {
+ byte1 = packed >> 8;
+ byte2 = packed & 0xff;
+
+ found = 0;
+ for(i=0; i<128; i++) {
+ if ((byte1 == varicode_table[2*i]) && (byte2 == varicode_table[2*i+1])) {
+ found = 1;
+ //printf("%c\n", (char)i);
+ *ascii_out++ = i;
+ }
+ }
+ if (found == 1)
+ n_out++;
+ }
+ //printf("n_out: %d n_in: %d\n", n_out, n_in);
+ }
+
+ return n_out;
+}
+
+#ifdef VARICODE_UNITTEST
+int main(void) {
+ char *ascii_in;
+ int *varicode;
+ int i, n_varicode_bits_out, n_ascii_chars_out;
+ char *ascii_out;
+
+ ascii_in = (char*)malloc(sizeof(varicode_table)/2);
+ varicode = (int*)malloc(VARICODE_MAX_BITS*sizeof(int)*strlen(ascii_in));
+ ascii_out = (char*)malloc(strlen(ascii_in)+1);
+
+ for(i=0; i<sizeof(varicode_table)/2; i++)
+ ascii_in[i] = (char)i;
+ n_varicode_bits_out = varicode_encode(varicode, ascii_in, VARICODE_MAX_BITS*strlen(ascii_in), strlen(ascii_in));
+ n_ascii_chars_out = varicode_decode(ascii_out, varicode, strlen(ascii_in), n_varicode_bits_out);
+ assert(n_ascii_chars_out == strlen(ascii_in));
+ ascii_out[n_ascii_chars_out] = 0;
+
+ //for(i=0; i<n_varicode_bits_out; i++) {
+ // printf("%d \n", varicode[i]);
+ //}
+
+ //printf("ascii_out: %s\n", ascii_out);
+ if (strcmp(ascii_in, ascii_out) == 0)
+ printf("Pass\n");
+ else
+ printf("Fail\n");
+
+ free(ascii_in);
+ free(ascii_out);
+ free(varicode);
+ return 0;
+}
+#endif
--- /dev/null
+//==========================================================================
+// Name: varicode.h
+// Purpose: Varicode encoded and decode functions
+// Created: Nov 24, 2012
+// Authors: David Rowe
+//
+// License:
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2.1,
+// as published by the Free Software Foundation. This program is
+// distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+// License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, see <http://www.gnu.org/licenses/>.
+//
+//==========================================================================
+
+#ifndef __VARICODE__
+#define __VARICODE__
+
+#ifdef __cplusplus
+extern "C" {
+
+#endif
+int varicode_encode(int varicode_out[], char ascii_in[], int max_out, int n_in);
+int varicode_decode(char ascii_out[], int varicode_in[], int max_out, int n_in);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
--- /dev/null
+//==========================================================================
+// Name: varicode_table.h
+// Purpose: Varicode look up table
+// Created: Nov 24, 2012
+// Authors: Clint Turner, KA7OEI, Peter Martinez, G3PLX
+//
+// License:
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License version 2.1,
+// as published by the Free Software Foundation. This program is
+// distributed in the hope that it will be useful, but WITHOUT ANY
+// WARRANTY; without even the implied warranty of MERCHANTABILITY or
+// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
+// License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, see <http://www.gnu.org/licenses/>.
+//
+//==========================================================================
+
+/* The following table defines the PKS31 varicode. There are 128 entries,
+corresponding to ASCII characters 0-127 with two bytes for each entry. The bits
+for the varicode are to be shifted out MSB-first for both bytes, with the first byte
+in the table being the first one to be sent.
+
+More than one zero in sequence signifies the end of the character (i.e.
+two zeroes are the intercharacter sequence, so at least two zeroes should always be
+sent before the next character is sent.
+
+This file is constructed with information from the article "PSK31 Fundamentals"
+by Peter Martinez, G3PLX by Clint Turner, KA7OEI
+*/
+unsigned char const varicode_table[256] = {
+0b10101010,
+0b11000000, // 0 NUL
+0b10110110,
+0b11000000, // 1 SOH
+0b10111011,
+0b01000000, // 2 STX
+0b11011101,
+0b11000000, // 3 ETX
+0b10111010,
+0b11000000, // 4 EOT
+0b11010111,
+0b11000000, // 5 ENQ
+0b10111011,
+0b11000000, // 6 ACK
+0b10111111,
+0b01000000, // 7 BEL
+0b10111111,
+0b11000000, // 8 BS
+0b11101111,
+0b00000000, // 9 HT
+0b11101000,
+0b00000000, // 10 LF
+0b11011011,
+0b11000000, // 11 VT
+0b10110111,
+0b01000000, // 12 FF
+0b11111000,
+0b00000000, // 13 CR
+0b11011101,
+0b01000000, // 14 SO
+0b11101010,
+0b11000000, // 15 SI
+0b10111101,
+0b11000000, // 16 DLE
+0b10111101,
+0b01000000, // 17 DC1
+0b11101011,
+0b01000000, // 18 DC2
+0b11101011,
+0b11000000, // 19 DC3
+0b11010110,
+0b11000000, // 20 DC4
+0b11011010,
+0b11000000, // 21 NAK
+0b11011011,
+0b01000000, // 22 SYN
+0b11010101,
+0b11000000, // 23 ETB
+0b11011110,
+0b11000000, // 24 CAN
+0b11011111,
+0b01000000, // 25 EM
+0b11101101,
+0b11000000, // 26 SUB
+0b11010101,
+0b01000000, // 27 ESC
+0b11010111,
+0b01000000, // 28 FS
+0b11101110,
+0b11000000, // 29 GS
+0b10111110,
+0b11000000, // 30 RS
+0b11011111,
+0b11000000, // 31 US
+0b10000000,
+0b00000000, // 32 SP
+0b11111111,
+0b10000000, // 33 !
+0b10101111,
+0b10000000, // 34 "
+0b11111010,
+0b10000000, // 35 #
+0b11101101,
+0b10000000, // 36 $
+0b10110101,
+0b01000000, // 37 %
+0b10101110,
+0b11000000, // 38 &
+0b10111111,
+0b10000000, // 39 '
+0b11111011,
+0b00000000, // 40 (
+0b11110111,
+0b00000000, // 41 )
+0b10110111,
+0b10000000, // 42 *
+0b11101111,
+0b10000000, // 43 +
+0b11101010,
+0b00000000, // 44 ,
+0b11010100,
+0b00000000, // 45 -
+0b10101110,
+0b00000000, // 46 .
+0b11010111,
+0b10000000, // 47 /
+0b10110111,
+0b00000000, // 48 0
+0b10111101,
+0b00000000, // 49 1
+0b11101101,
+0b00000000, // 50 2
+0b11111111,
+0b00000000, // 51 3
+0b10111011,
+0b10000000, // 52 4
+0b10101101,
+0b10000000, // 53 5
+0b10110101,
+0b10000000, // 54 6
+0b11010110,
+0b10000000, // 55 7
+0b11010101,
+0b10000000, // 56 8
+0b11011011,
+0b10000000, // 57 9
+0b11110101,
+0b00000000, // 58 :
+0b11011110,
+0b10000000, // 59 ;
+0b11110110,
+0b10000000, // 60 <
+0b10101010,
+0b00000000, // 61 =
+0b11101011,
+0b10000000, // 62 >
+0b10101011,
+0b11000000, // 63 ?
+0b10101111,
+0b01000000, // 64 @
+0b11111010,
+0b00000000, // 65 A
+0b11101011,
+0b00000000, // 66 B
+0b10101101,
+0b00000000, // 67 C
+0b10110101,
+0b00000000, // 68 D
+0b11101110,
+0b00000000, // 69 E
+0b11011011,
+0b00000000, // 70 F
+0b11111101,
+0b00000000, // 71 G
+0b10101010,
+0b10000000, // 72 H
+0b11111110,
+0b00000000, // 73 I
+0b11111110,
+0b10000000, // 74 J
+0b10111110,
+0b10000000, // 75 K
+0b11010111,
+0b00000000, // 76 L
+0b10111011,
+0b00000000, // 77 M
+0b11011101,
+0b00000000, // 78 N
+0b10101011,
+0b00000000, // 79 O
+0b11010101,
+0b00000000, // 80 P
+0b11101110,
+0b10000000, // 81 Q
+0b10101111,
+0b00000000, // 82 R
+0b11011110,
+0b00000000, // 83 S
+0b11011010,
+0b00000000, // 84 T
+0b10101011,
+0b10000000, // 85 U
+0b11011010,
+0b10000000, // 86 V
+0b10101110,
+0b10000000, // 87 W
+0b10111010,
+0b10000000, // 88 X
+0b10111101,
+0b10000000, // 89 Y
+0b10101011,
+0b01000000, // 90 Z
+0b11111011,
+0b10000000, // 91 [
+0b11110111,
+0b10000000, // 92 "\"
+0b11111101,
+0b10000000, // 93 ]
+0b10101111,
+0b11000000, // 94 ^
+0b10110110,
+0b10000000, // 95 _ (underline)
+0b10110111,
+0b11000000, // 96 `
+0b10110000,
+0b00000000, // 97 a
+0b10111110,
+0b00000000, // 98 b
+0b10111100,
+0b00000000, // 99 c
+0b10110100,
+0b00000000, // 100 d
+0b11000000,
+0b00000000, // 101 e
+0b11110100,
+0b00000000, // 102 f
+0b10110110,
+0b00000000, // 103 g
+0b10101100,
+0b00000000, // 104 h
+0b11010000,
+0b00000000, // 105 i
+0b11110101,
+0b10000000, // 106 j
+0b10111111,
+0b00000000, // 107 k
+0b11011000,
+0b00000000, // 108 l
+0b11101100,
+0b00000000, // 109 m
+0b11110000,
+0b00000000, // 110 n
+0b11100000,
+0b00000000, // 111 o
+0b11111100,
+0b00000000, // 112 p
+0b11011111,
+0b10000000, // 113 q
+0b10101000,
+0b00000000, // 114 r
+0b10111000,
+0b00000000, // 115 s
+0b10100000,
+0b00000000, // 116 t
+0b11011100,
+0b00000000, // 117 u
+0b11110110,
+0b00000000, // 118 v
+0b11010110,
+0b00000000, // 119 w
+0b11011111,
+0b00000000, // 120 x
+0b10111010,
+0b00000000, // 121 y
+0b11101010,
+0b10000000, // 122 z
+0b10101101,
+0b11000000, // 123 {
+0b11011101,
+0b10000000, // 124 |
+0b10101101,
+0b01000000, // 125 }
+0b10110101,
+0b11000000, // 126 ~
+0b11101101,
+0b01000000, // 127 (del)
+};