#define HORUS_BINARY_NUM_PAYLOAD_BYTES 22 /* fixed number of bytes in binary payload */
struct horus {
- int mode;
+ int mode;
+ int verbose;
struct FSK *fsk; /* states for FSK modem */
int Fs; /* sample rate in Hz */
int mFSK; /* number of FSK tones */
struct horus *hstates = (struct horus *)malloc(sizeof(struct horus));
assert(hstates != NULL);
- hstates->Fs = 48000; hstates->Rs = 100;
+ hstates->Fs = 48000; hstates->Rs = 100; hstates->verbose = 0; hstates->mode = mode;
if (mode == HORUS_MODE_RTTY) {
hstates->mFSK = 2;
return nin;
}
-int horus_find_uw(struct horus *hstates) {
+int horus_find_uw(struct horus *hstates, int n) {
int i, j, corr, mx, mx_ind;
- int rx_bits_mapped[hstates->rx_bits_len];
+ int rx_bits_mapped[n+hstates->uw_len];
/* map rx_bits to +/-1 for UW search */
- for(i=0; i<hstates->max_packet_len; i++) {
+ for(i=0; i<n+hstates->uw_len; i++) {
rx_bits_mapped[i] = 2*hstates->rx_bits[i] - 1;
}
/* look for UW */
mx = 0; mx_ind = 0;
- for(i=0; i<hstates->fsk->Nbits; i++) {
+ for(i=0; i<n; i++) {
/* calculate correlation between bit stream and UW */
char *pout, *ptx_crc;
uint16_t rx_crc, tx_crc;
- pout = ascii_out; nout = 0; crc_ok = 0; endpacket = 0;
+ pout = ascii_out; nout = 0; crc_ok = 0; endpacket = 0; rx_crc = tx_crc = 0;
for (i=st; i<en; i+=nfield+npad) {
char_dec = 0;
for(j=0; j<nfield; j++) {
- assert(hstates->rx_bits[i] <= 1);
- char_dec |= hstates->rx_bits[i] * (1<<j);
+ assert(hstates->rx_bits[i+j] <= 1);
+ char_dec |= hstates->rx_bits[i+j] * (1<<j);
}
-
+ if (hstates->verbose) {
+ fprintf(stderr, "i: %4d 0x%02x %c ", i, char_dec, char_dec);
+ if ((nout % 6) == 0) {
+ fprintf(stderr, "\n");
+ }
+ }
+
/* if we find a '*' that's the end of the packet for RX CRC calculations */
if (!endpacket && (char_dec == 42)) {
endpacket = 1;
rx_crc = horus_l2_gen_crc16((uint8_t*)ascii_out, nout);
- ptx_crc = pout + 2; /* start of tx CRC */
+ ptx_crc = pout + 1; /* start of tx CRC */
}
/* build up output array, really only need up to tx crc but
}
- /* if we found the end of packet flag and have enough chars to computer checksum ... */
-
+ /* if we found the end of packet flag and have enough chars to compute checksum ... */
+
+ //fprintf(stderr, "\n\ntx CRC...\n");
if (endpacket && (pout > (ptx_crc+3))) {
tx_crc = 0;
for(i=0; i<4; i++) {
tx_crc <<= 4;
- tx_crc += hex2int(ptx_crc[i]);
+ tx_crc |= hex2int(ptx_crc[i]);
+ //fprintf(stderr, "ptx_crc[%d] %c 0x%02X tx_crc: 0x%04X\n", i, ptx_crc[i], hex2int(ptx_crc[i]), tx_crc);
}
crc_ok = (tx_crc == rx_crc);
*(ptx_crc-1) = 0; /* terminate ASCII string */
*ascii_out = 0;
}
+ if (hstates->verbose) {
+ fprintf(stderr, "\n endpacket: %d nout: %d tx_crc: 0x%04x rx_crc: 0x%04x\n",
+ endpacket, nout, tx_crc, rx_crc);
+ }
+
/* make sure we don't overrun storage */
assert(nout <= horus_get_max_ascii_out_len(hstates));
int st = uw_loc + hstates->uw_len; /* first bit of first char */
int en = uw_loc + hstates->max_packet_len - nfield; /* last bit of max length packet */
- int i, j, nout;
+ int j, b, nout;
uint8_t rxpacket[hstates->max_packet_len];
uint8_t rxbyte, *pout;
pout = rxpacket; nout = 0;
- for (i=st; i<en; i+=nfield) {
+ for (b=st; b<en; b+=nfield) {
/* assemble bytes MSB to LSB */
rxbyte = 0;
for(j=0; j<nfield; j++) {
- assert(hstates->rx_bits[i] <= 1);
+ assert(hstates->rx_bits[b+j] <= 1);
rxbyte <<= 1;
- rxbyte |= hstates->rx_bits[i];
+ rxbyte |= hstates->rx_bits[b+j];
}
/* build up output array */
assert(hstates != NULL);
valid_packet = 0;
+
+ int Nbits = hstates->fsk->Nbits;
+ int rx_bits_len = hstates->rx_bits_len;
+
+ if (hstates->verbose) {
+ fprintf(stderr, "max_packet_len: %d rx_bits_len: %d Nbits: %d\n",
+ hstates->max_packet_len, rx_bits_len, Nbits);
+ }
/* shift buffer of bits to make room for new bits */
- int Nbits = hstates->fsk->Nbits;
- int max_packet_len = hstates->max_packet_len;
- for(i=0,j=max_packet_len-Nbits; i<Nbits; i++,j++) {
+ for(i=0,j=Nbits; j<rx_bits_len; i++,j++) {
hstates->rx_bits[i] = hstates->rx_bits[j];
}
demod_in_comp[i].real = demod_in[i];
demod_in_comp[i].imag = 0;
}
- fsk_demod(hstates->fsk, &hstates->rx_bits[max_packet_len-Nbits], demod_in_comp);
+ fsk_demod(hstates->fsk, &hstates->rx_bits[rx_bits_len-Nbits], demod_in_comp);
/* UW search to see if we can find the start of a packet in the buffer */
- if ((uw_loc = horus_find_uw(hstates)) != -1) {
+ if ((uw_loc = horus_find_uw(hstates, Nbits)) != -1) {
+ if (hstates->verbose) {
+ fprintf(stderr, "uw_loc: %d mode: %d\n", uw_loc, hstates->mode);
+ }
+
/* OK we have found a unique word, and therefore the start of
a packet, so lets try to extract valid packets */
}
}
+void horus_set_verbose(struct horus *hstates, int verbose) {
+ assert(hstates != NULL);
+ hstates->verbose = verbose;
+}
+
Can operate in Horus RTTY or Binary mode.
+ Testing with a 8000Hz sample rate wave file:
+
+ $ sox ~/Desktop/horus.wav -r 48000 -t raw - | ./horus_demod -m RTTY -v - /dev/nul/
+
\*---------------------------------------------------------------------------*/
/*
struct MODEM_STATS stats;
FILE *fin,*fout;
int i,j,Ndft,mode;
- int stats_ctr,stats_loop, stats_rate;
+ int stats_ctr,stats_loop, stats_rate, verbose;
float loop_time;
int enable_stats = 0;
stats_loop = 0;
stats_rate = 8;
mode = -1;
-
+ verbose = 0;
+
int o = 0;
int opt_idx = 0;
while ( o != -1 ) {
{0, 0, 0, 0}
};
- o = getopt_long(argc,argv,"hm:t::",long_opts,&opt_idx);
+ o = getopt_long(argc,argv,"hvm:t::",long_opts,&opt_idx);
switch(o) {
case 'm':
}
}
break;
+ case 'v':
+ verbose = 1;
+ break;
case 'h':
case '?':
goto helpmsg;
break;
}
-
- int dx = optind;
+ }
- if( (argc - dx) < 1) {
- fprintf(stderr, "Too few arguments\n");
- goto helpmsg;
- }
+ int dx = optind;
- if( (argc - dx) > 5){
- fprintf(stderr, "Too many arguments\n");
- helpmsg:
- fprintf(stderr,"usage: %s -m RTTY|binary [-t [r]] InputModemRawFile OutputAsciiFile\n",argv[0]);
- fprintf(stderr,"\n");
- fprintf(stderr,"InputModemRawFile - 48 kHz 16 bit shorts real modem signal from radio\n");
- fprintf(stderr," -m RTTY|binary\n");
- fprintf(stderr,"--mode=RTTY|binary[r] - RTTY or binary Horus protcols\n");
- fprintf(stderr," -t[r] --stats=[r] - Print out modem statistics to stderr in JSON.\n");
- fprintf(stderr," r, if provided, sets the number of modem frames"
- "between statistic printouts\n");
- exit(1);
- }
+ if( (argc - dx) < 1) {
+ fprintf(stderr, "Too few arguments\n");
+ goto helpmsg;
+ }
+
+ if( (argc - dx) > 5){
+ fprintf(stderr, "Too many arguments\n");
+ helpmsg:
+ fprintf(stderr,"usage: %s -m RTTY|binary [-v] [-t [r]] InputModemRawFile OutputAsciiFile\n",argv[0]);
+ fprintf(stderr,"\n");
+ fprintf(stderr,"InputModemRawFile 48 kHz 16 bit shorts real modem signal from radio\n");
+ fprintf(stderr," -m RTTY|binary\n");
+ fprintf(stderr,"--mode=RTTY|binary[r] RTTY or binary Horus protcols\n");
+ fprintf(stderr," -t[r] --stats=[r] Print out modem statistics to stderr in JSON.\n");
+ fprintf(stderr," r, if provided, sets the number of modem frames\n"
+ " between statistic printouts\n");
+ fprintf(stderr," -v verbose debug info\n");
+ exit(1);
+ }
- /* Open files */
+ /* Open files */
- if (strcmp(argv[dx + 1],"-")==0) {
- fin = stdin;
- } else {
- fin = fopen(argv[dx + 1],"rb");
- }
+ if (verbose) {
+ fprintf(stderr, "mode: %d verbose: %d stats_loop: %d stats_rate: %d\n",mode, verbose, stats_loop, stats_rate);
+ }
+ if (strcmp(argv[dx],"-")==0) {
+ fin = stdin;
+ } else {
+ fin = fopen(argv[dx],"rb");
+ }
- if (strcmp(argv[dx + 2],"-")==0) {
- fout = stdout;
- } else {
- fout = fopen(argv[dx + 4],"w");
- }
+ if (strcmp(argv[dx + 1],"-")==0) {
+ fout = stdout;
+ } else {
+ fout = fopen(argv[dx + 1],"w");
+ }
- if ((fin==NULL) || (fout==NULL)) {
- fprintf(stderr,"Couldn't open test vector files\n");
- exit(1);
- }
+ if ((fin==NULL) || (fout==NULL)) {
+ fprintf(stderr,"Couldn't open test vector files\n");
+ exit(1);
}
/* end command line processing */
hstates = horus_open(mode);
+ horus_set_verbose(hstates, verbose);
+
if (hstates == NULL) {
fprintf(stderr, "Couldn't open Horus API\n");
exit(1);
/* Main loop ----------------------------------------------------------------------- */
while( fread(demod_in, sizeof(short), horus_nin(hstates), fin) == horus_nin(hstates) ) {
-
+
+ if (verbose) {
+ fprintf(stderr, "read nin %d\n", horus_nin(hstates));
+ }
if (horus_rx(hstates, ascii_out, demod_in)) {
fprintf(stdout, "%s\n", ascii_out);
}