aboutsummaryrefslogtreecommitdiff
path: root/src/fsk_demod.c
diff options
context:
space:
mode:
authordrowe67 <[email protected]>2023-07-14 12:36:50 +0930
committerDavid Rowe <[email protected]>2023-07-14 12:36:50 +0930
commitb86e88413d4c6ec428aaedb147f7675f28882fe4 (patch)
treece360925856e25d4343d59a37e2e6bac142d3752 /src/fsk_demod.c
parent0c2e969cfbe85548801eeb20ad8113969604892a (diff)
clang-format -i applied to src unittest misc
Diffstat (limited to 'src/fsk_demod.c')
-rw-r--r--src/fsk_demod.c811
1 files changed, 429 insertions, 382 deletions
diff --git a/src/fsk_demod.c b/src/fsk_demod.c
index 60b76c0..e533510 100644
--- a/src/fsk_demod.c
+++ b/src/fsk_demod.c
@@ -4,8 +4,8 @@
AUTHOR......: Brady O'Brien and David Rowe
DATE CREATED: 8 January 2016
- Command line FSK demodulator. Reads in FSK samples, writes demodulated
- output bits.
+ Command line FSK demodulator. Reads in FSK samples, writes demodulated
+ output bits.
\*---------------------------------------------------------------------------*/
@@ -26,423 +26,470 @@
along with this program; if not, see <http://www.gnu.org/licenses/>.
*/
-#define TEST_FRAME_SIZE 100 /* must match fsk_get_test_bits.c */
+#define TEST_FRAME_SIZE 100 /* must match fsk_get_test_bits.c */
#include <assert.h>
+#include <getopt.h>
+#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
-#include <getopt.h>
#include <time.h>
-#include <signal.h>
#include <unistd.h>
-#include "fsk.h"
#include "codec2_fdmdv.h"
-#include "mpdecode_core.h"
+#include "fsk.h"
#include "modem_stats.h"
+#include "mpdecode_core.h"
/* cleanly exit when we get a SIGTERM */
-void sig_handler(int signo)
-{
- if (signo == SIGTERM) {
- exit(0);
- }
+void sig_handler(int signo) {
+ if (signo == SIGTERM) {
+ exit(0);
+ }
}
-int main(int argc,char *argv[]){
- struct FSK *fsk;
- struct MODEM_STATS stats;
- int Fs,Rs,M,P,stats_ctr,stats_loop;
- float loop_time;
- int enable_stats = 0;
- FILE *fin,*fout;
- uint8_t *bitbuf = NULL;
- int16_t *rawbuf;
- COMP *modbuf;
- float *rx_filt = NULL;
- float *llrs = NULL;
- int i,j,Ndft;
- int soft_dec_mode = 0;
- stats_loop = 0;
- int complex_input = 1, bytes_per_sample = 2;
- int stats_rate = 8;
- int testframe_mode = 0;
- P = 8; /* default */
- M = 0;
- int fsk_lower = 0;
- int fsk_upper = 0;
- int user_fsk_lower = 0;
- int user_fsk_upper = 0;
- int nsym = FSK_DEFAULT_NSYM;
- int mask = 0;
- int tone_separation = 100;
-
- int o = 0;
- int opt_idx = 0;
- while( o != -1 ){
- static struct option long_opts[] = {
- {"help", no_argument, 0, 'h'},
- {"conv", required_argument, 0, 'p'},
- {"cs16", no_argument, 0, 'c'},
- {"cu8", no_argument, 0, 'd'},
- {"fsk_lower", required_argument, 0, 'b'},
- {"fsk_upper", required_argument, 0, 'u'},
- {"stats", optional_argument, 0, 't'},
- {"soft-dec", no_argument, 0, 's'},
- {"testframes",no_argument, 0, 'f'},
- {"nsym", required_argument, 0, 'n'},
- {"mask", required_argument, 0, 'm'},
- {0, 0, 0, 0}
- };
-
- o = getopt_long(argc,argv,"fhlp:cdt::sb:u:m",long_opts,&opt_idx);
-
- switch(o){
- case 'c':
- complex_input = 2;
- bytes_per_sample = 2;
- break;
- case 'd':
- complex_input = 2;
- bytes_per_sample = 1;
- break;
- case 'f':
- testframe_mode = 1;
- break;
- case 't':
- enable_stats = 1;
- if(optarg != NULL){
- stats_rate = atoi(optarg);
- if(stats_rate == 0){
- stats_rate = 8;
- }
- }
- break;
- case 's':
- soft_dec_mode = 1;
- break;
- case 'p':
- P = atoi(optarg);
- break;
- case 'b':
- if (optarg != NULL) {
- fsk_lower = atoi(optarg);
- user_fsk_lower = 1;
- }
- break;
- case 'u':
- if (optarg != NULL){
- fsk_upper = atoi(optarg);
- user_fsk_upper = 1;
- }
- break;
- case 'n':
- if (optarg != NULL) {
- nsym = atoi(optarg);
- }
- break;
- case 'm':
- mask = 1;
- tone_separation = atoi(optarg);
- break;
- case 'h':
- case '?':
- goto helpmsg;
- break;
+int main(int argc, char *argv[]) {
+ struct FSK *fsk;
+ struct MODEM_STATS stats;
+ int Fs, Rs, M, P, stats_ctr, stats_loop;
+ float loop_time;
+ int enable_stats = 0;
+ FILE *fin, *fout;
+ uint8_t *bitbuf = NULL;
+ int16_t *rawbuf;
+ COMP *modbuf;
+ float *rx_filt = NULL;
+ float *llrs = NULL;
+ int i, j, Ndft;
+ int soft_dec_mode = 0;
+ stats_loop = 0;
+ int complex_input = 1, bytes_per_sample = 2;
+ int stats_rate = 8;
+ int testframe_mode = 0;
+ P = 8; /* default */
+ M = 0;
+ int fsk_lower = 0;
+ int fsk_upper = 0;
+ int user_fsk_lower = 0;
+ int user_fsk_upper = 0;
+ int nsym = FSK_DEFAULT_NSYM;
+ int mask = 0;
+ int tone_separation = 100;
+
+ int o = 0;
+ int opt_idx = 0;
+ while (o != -1) {
+ static struct option long_opts[] = {
+ {"help", no_argument, 0, 'h'},
+ {"conv", required_argument, 0, 'p'},
+ {"cs16", no_argument, 0, 'c'},
+ {"cu8", no_argument, 0, 'd'},
+ {"fsk_lower", required_argument, 0, 'b'},
+ {"fsk_upper", required_argument, 0, 'u'},
+ {"stats", optional_argument, 0, 't'},
+ {"soft-dec", no_argument, 0, 's'},
+ {"testframes", no_argument, 0, 'f'},
+ {"nsym", required_argument, 0, 'n'},
+ {"mask", required_argument, 0, 'm'},
+ {0, 0, 0, 0}};
+
+ o = getopt_long(argc, argv, "fhlp:cdt::sb:u:m", long_opts, &opt_idx);
+
+ switch (o) {
+ case 'c':
+ complex_input = 2;
+ bytes_per_sample = 2;
+ break;
+ case 'd':
+ complex_input = 2;
+ bytes_per_sample = 1;
+ break;
+ case 'f':
+ testframe_mode = 1;
+ break;
+ case 't':
+ enable_stats = 1;
+ if (optarg != NULL) {
+ stats_rate = atoi(optarg);
+ if (stats_rate == 0) {
+ stats_rate = 8;
+ }
}
- }
- int dx = optind;
-
- if( (argc - dx) < 5) {
- fprintf(stderr, "Too few arguments\n");
- goto helpmsg;
- }
-
- if( (argc - dx) > 5) {
- fprintf(stderr, "Too many arguments\n");
- helpmsg:
- fprintf(stderr,"usage: %s [options] (2|4) SampleRate SymbolRate InputModemRawFile OutputFile\n",argv[0]);
- fprintf(stderr," -c --cs16 The raw input file will be in complex signed 16 bit format.\n");
- fprintf(stderr," -d --cu8 The raw input file will be in complex unsigned 8 bit format.\n");
- fprintf(stderr," If neither -c nor -d are used, the input should be in signed 16 bit format.\n");
- fprintf(stderr," -f --testframes Testframe mode, prints stats to stderr when a testframe is detected, if -t (JSON) \n");
- fprintf(stderr," is enabled stats will be in JSON format\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");
- fprintf(stderr," -s --soft-dec The output file will be in a soft-decision format, with one 32-bit float per bit.\n");
- fprintf(stderr," If -s is not used, the output will be in a 1 byte-per-bit format.\n");
- fprintf(stderr," -p P Number of timing offsets we have to choose from, default %d.\n", FSK_DEFAULT_P);
- fprintf(stderr," Fs/Rs/P must be an integer. Smaller values result in faster operation, but\n");
- fprintf(stderr," coarse sampling. Try to keep >= 8\n");
- fprintf(stderr," processing but lower demodulation performance. Default %d\n", FSK_DEFAULT_P);
- fprintf(stderr," --fsk_lower freq lower limit of freq estimator (default 0 for real input, -Fs/2 for complex input)\n");
- fprintf(stderr," --fsk_upper freq upper limit of freq estimator (default Fs/2)\n");
- fprintf(stderr," --nsym Nsym number of symbols used for estimators. Default %d\n", FSK_DEFAULT_NSYM);
- fprintf(stderr," --mask TxFreqSpace Use \"mask\" freq estimator (default is \"peak\" estimator)\n");
- exit(1);
- }
-
- /* Extract parameters */
- M = atoi(argv[dx]);
- Fs = atoi(argv[dx + 1]);
- Rs = atoi(argv[dx + 2]);
-
- if( (M!=2) && (M!=4) ){
- fprintf(stderr,"Mode %d is not valid. Mode must be 2 or 4.\n",M);
+ break;
+ case 's':
+ soft_dec_mode = 1;
+ break;
+ case 'p':
+ P = atoi(optarg);
+ break;
+ case 'b':
+ if (optarg != NULL) {
+ fsk_lower = atoi(optarg);
+ user_fsk_lower = 1;
+ }
+ break;
+ case 'u':
+ if (optarg != NULL) {
+ fsk_upper = atoi(optarg);
+ user_fsk_upper = 1;
+ }
+ break;
+ case 'n':
+ if (optarg != NULL) {
+ nsym = atoi(optarg);
+ }
+ break;
+ case 'm':
+ mask = 1;
+ tone_separation = atoi(optarg);
+ break;
+ case 'h':
+ case '?':
goto helpmsg;
+ break;
}
-
- /* Open files */
- if(strcmp(argv[dx + 3],"-")==0){
- fin = stdin;
- }else{
- fin = fopen(argv[dx + 3],"r");
- }
-
- if(strcmp(argv[dx + 4],"-")==0){
- fout = stdout;
- }else{
- fout = fopen(argv[dx + 4],"w");
+ }
+ int dx = optind;
+
+ if ((argc - dx) < 5) {
+ fprintf(stderr, "Too few arguments\n");
+ goto helpmsg;
+ }
+
+ if ((argc - dx) > 5) {
+ fprintf(stderr, "Too many arguments\n");
+ helpmsg:
+ fprintf(stderr,
+ "usage: %s [options] (2|4) SampleRate SymbolRate InputModemRawFile "
+ "OutputFile\n",
+ argv[0]);
+ fprintf(stderr,
+ " -c --cs16 The raw input file will be in complex signed "
+ "16 bit format.\n");
+ fprintf(stderr,
+ " -d --cu8 The raw input file will be in complex "
+ "unsigned 8 bit format.\n");
+ fprintf(stderr,
+ " If neither -c nor -d are used, the input "
+ "should be in signed 16 bit format.\n");
+ fprintf(stderr,
+ " -f --testframes Testframe mode, prints stats to stderr when a "
+ "testframe is detected, if -t (JSON) \n");
+ fprintf(stderr,
+ " is enabled stats will be in JSON format\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");
+ fprintf(stderr,
+ " -s --soft-dec The output file will be in a soft-decision "
+ "format, with one 32-bit float per bit.\n");
+ fprintf(stderr,
+ " If -s is not used, the output will be in a 1 "
+ "byte-per-bit format.\n");
+ fprintf(stderr,
+ " -p P Number of timing offsets we have to choose "
+ "from, default %d.\n",
+ FSK_DEFAULT_P);
+ fprintf(stderr,
+ " Fs/Rs/P must be an integer. Smaller values "
+ "result in faster operation, but\n");
+ fprintf(stderr, " coarse sampling. Try to keep >= 8\n");
+ fprintf(stderr,
+ " processing but lower demodulation "
+ "performance. Default %d\n",
+ FSK_DEFAULT_P);
+ fprintf(stderr,
+ " --fsk_lower freq lower limit of freq estimator (default 0 for "
+ "real input, -Fs/2 for complex input)\n");
+ fprintf(
+ stderr,
+ " --fsk_upper freq upper limit of freq estimator (default Fs/2)\n");
+ fprintf(stderr,
+ " --nsym Nsym number of symbols used for estimators. "
+ "Default %d\n",
+ FSK_DEFAULT_NSYM);
+ fprintf(stderr,
+ " --mask TxFreqSpace Use \"mask\" freq estimator (default is "
+ "\"peak\" estimator)\n");
+ exit(1);
+ }
+
+ /* Extract parameters */
+ M = atoi(argv[dx]);
+ Fs = atoi(argv[dx + 1]);
+ Rs = atoi(argv[dx + 2]);
+
+ if ((M != 2) && (M != 4)) {
+ fprintf(stderr, "Mode %d is not valid. Mode must be 2 or 4.\n", M);
+ goto helpmsg;
+ }
+
+ /* Open files */
+ if (strcmp(argv[dx + 3], "-") == 0) {
+ fin = stdin;
+ } else {
+ fin = fopen(argv[dx + 3], "r");
+ }
+
+ if (strcmp(argv[dx + 4], "-") == 0) {
+ fout = stdout;
+ } else {
+ fout = fopen(argv[dx + 4], "w");
+ }
+
+ /* set up FSK */
+ fsk = fsk_create_hbr(Fs, Rs, M, P, nsym, FSK_NONE, tone_separation);
+
+ /* set freq estimator limits */
+ if (!user_fsk_lower) {
+ if (complex_input == 1)
+ fsk_lower = 0;
+ else
+ fsk_lower = -Fs / 2;
+ }
+ if (!user_fsk_upper) {
+ fsk_upper = Fs / 2;
+ }
+ fprintf(stderr, "Setting estimator limits to %d to %d Hz.\n", fsk_lower,
+ fsk_upper);
+ fsk_set_freq_est_limits(fsk, fsk_lower, fsk_upper);
+
+ fsk_set_freq_est_alg(fsk, mask);
+
+ if (fin == NULL || fout == NULL || fsk == NULL) {
+ fprintf(stderr, "Couldn't open files\n");
+ exit(1);
+ }
+
+ /* set up testframe mode */
+
+ int testframecnt, bitcnt, biterr, testframe_detected;
+ uint8_t *bitbuf_tx = NULL, *bitbuf_rx = NULL;
+ if (testframe_mode) {
+ bitbuf_tx = (uint8_t *)malloc(sizeof(uint8_t) * TEST_FRAME_SIZE);
+ assert(bitbuf_tx != NULL);
+ bitbuf_rx = (uint8_t *)malloc(sizeof(uint8_t) * TEST_FRAME_SIZE);
+ assert(bitbuf_rx != NULL);
+
+ /* Generate known tx frame from known seed */
+
+ srand(158324);
+ for (i = 0; i < TEST_FRAME_SIZE; i++) {
+ bitbuf_tx[i] = rand() & 0x1;
+ bitbuf_rx[i] = 0;
}
- /* set up FSK */
- fsk = fsk_create_hbr(Fs,Rs,M,P,nsym,FSK_NONE,tone_separation);
-
- /* set freq estimator limits */
- if (!user_fsk_lower) {
- if (complex_input == 1)
- fsk_lower = 0;
- else
- fsk_lower = -Fs/2;
- }
- if (!user_fsk_upper) {
- fsk_upper = Fs/2;
+ testframecnt = 0;
+ bitcnt = 0;
+ biterr = 0;
+ }
+
+ if (enable_stats) {
+ loop_time = ((float)fsk_nin(fsk)) / ((float)Fs);
+ stats_loop = (int)(1 / (stats_rate * loop_time));
+ stats_ctr = 0;
+ }
+
+ /* allocate buffers for processing */
+ if (soft_dec_mode) {
+ rx_filt = (float *)malloc(sizeof(float) * fsk->mode * fsk->Nsym);
+ assert(rx_filt != NULL);
+ llrs = (float *)malloc(sizeof(float) * fsk->Nbits);
+ assert(llrs != NULL);
+ } else {
+ bitbuf = (uint8_t *)malloc(sizeof(uint8_t) * fsk->Nbits);
+ assert(bitbuf != NULL);
+ }
+ rawbuf = (int16_t *)malloc(bytes_per_sample * (fsk->N + fsk->Ts * 2) *
+ complex_input);
+ modbuf = (COMP *)malloc(sizeof(COMP) * (fsk->N + fsk->Ts * 2));
+
+ /* set up signal handler so we can terminate gracefully */
+
+ if (signal(SIGTERM, sig_handler) == SIG_ERR) {
+ printf("\ncan't catch SIGTERM\n");
+ }
+
+ /* Demodulate! */
+
+ while (fread(rawbuf, bytes_per_sample * complex_input, fsk_nin(fsk), fin) ==
+ fsk_nin(fsk)) {
+ /* convert input to a buffer of floats. Note scaling isn't really necessary
+ * for FSK */
+
+ if (complex_input == 1) {
+ /* S16 real input */
+ for (i = 0; i < fsk_nin(fsk); i++) {
+ modbuf[i].real = ((float)rawbuf[i]) / FDMDV_SCALE;
+ modbuf[i].imag = 0.0;
+ }
+ } else {
+ if (bytes_per_sample == 1) {
+ /* U8 complex */
+ uint8_t *rawbuf_u8 = (uint8_t *)rawbuf;
+ for (i = 0; i < fsk_nin(fsk); i++) {
+ modbuf[i].real = ((float)rawbuf_u8[2 * i] - 127.0) / 128.0;
+ modbuf[i].imag = ((float)rawbuf_u8[2 * i + 1] - 127.0) / 128.0;
+ }
+ } else {
+ /* S16 complex */
+ for (i = 0; i < fsk_nin(fsk); i++) {
+ modbuf[i].real = ((float)rawbuf[2 * i]) / FDMDV_SCALE;
+ modbuf[i].imag = ((float)rawbuf[2 * i + 1] / FDMDV_SCALE);
+ }
+ }
}
- fprintf(stderr,"Setting estimator limits to %d to %d Hz.\n", fsk_lower, fsk_upper);
- fsk_set_freq_est_limits(fsk,fsk_lower,fsk_upper);
-
- fsk_set_freq_est_alg(fsk, mask);
-
- if(fin==NULL || fout==NULL || fsk==NULL){
- fprintf(stderr,"Couldn't open files\n");
- exit(1);
+
+ if (soft_dec_mode) {
+ int bps = log2(fsk->mode);
+ assert(fsk->Nbits == bps * fsk->Nsym);
+ /* output bit LLRs */
+ fsk_demod_sd(fsk, rx_filt, modbuf);
+ fsk_rx_filt_to_llrs(llrs, rx_filt, fsk->v_est, fsk->SNRest, fsk->mode,
+ fsk->Nsym);
+ } else {
+ fsk_demod(fsk, bitbuf, modbuf);
}
- /* set up testframe mode */
-
- int testframecnt, bitcnt, biterr, testframe_detected;
- uint8_t *bitbuf_tx = NULL, *bitbuf_rx = NULL;
+ testframe_detected = 0;
if (testframe_mode) {
- bitbuf_tx = (uint8_t*)malloc(sizeof(uint8_t)*TEST_FRAME_SIZE); assert(bitbuf_tx != NULL);
- bitbuf_rx = (uint8_t*)malloc(sizeof(uint8_t)*TEST_FRAME_SIZE); assert(bitbuf_rx != NULL);
-
- /* Generate known tx frame from known seed */
-
- srand(158324);
- for(i=0; i<TEST_FRAME_SIZE; i++){
- bitbuf_tx[i] = rand()&0x1;
- bitbuf_rx[i] = 0;
+ assert(soft_dec_mode == 0);
+
+ /* attempt to find a testframe and update stats */
+ /* update silding window of input bits */
+
+ int errs;
+ for (j = 0; j < fsk->Nbits; j++) {
+ for (i = 0; i < TEST_FRAME_SIZE - 1; i++) {
+ bitbuf_rx[i] = bitbuf_rx[i + 1];
}
+ bitbuf_rx[TEST_FRAME_SIZE - 1] = bitbuf[j];
- testframecnt = 0;
- bitcnt = 0;
- biterr = 0;
- }
-
- if(enable_stats){
- loop_time = ((float)fsk_nin(fsk))/((float)Fs);
- stats_loop = (int)(1/(stats_rate*loop_time));
- stats_ctr = 0;
- }
-
- /* allocate buffers for processing */
- if (soft_dec_mode) {
- rx_filt = (float*)malloc(sizeof(float)*fsk->mode*fsk->Nsym); assert(rx_filt != NULL);
- llrs = (float*)malloc(sizeof(float)*fsk->Nbits); assert(llrs != NULL);
- } else {
- bitbuf = (uint8_t*)malloc(sizeof(uint8_t)*fsk->Nbits); assert(bitbuf != NULL);
- }
- rawbuf = (int16_t*)malloc(bytes_per_sample*(fsk->N+fsk->Ts*2)*complex_input);
- modbuf = (COMP*)malloc(sizeof(COMP)*(fsk->N+fsk->Ts*2));
+ /* compare to know tx frame. If they are time aligned, there
+ will be a fairly low bit error rate */
- /* set up signal handler so we can terminate gracefully */
-
- if (signal(SIGTERM, sig_handler) == SIG_ERR) {
- printf("\ncan't catch SIGTERM\n");
- }
-
- /* Demodulate! */
-
- while( fread(rawbuf,bytes_per_sample*complex_input,fsk_nin(fsk),fin) == fsk_nin(fsk) ){
- /* convert input to a buffer of floats. Note scaling isn't really necessary for FSK */
-
- if (complex_input == 1) {
- /* S16 real input */
- for(i=0;i<fsk_nin(fsk);i++){
- modbuf[i].real = ((float)rawbuf[i])/FDMDV_SCALE;
- modbuf[i].imag = 0.0;
- }
+ errs = 0;
+ for (i = 0; i < TEST_FRAME_SIZE; i++) {
+ if (bitbuf_rx[i] != bitbuf_tx[i]) {
+ errs++;
+ }
}
- else {
- if (bytes_per_sample == 1) {
- /* U8 complex */
- uint8_t *rawbuf_u8 = (uint8_t*)rawbuf;
- for(i=0;i<fsk_nin(fsk);i++){
- modbuf[i].real = ((float)rawbuf_u8[2*i]-127.0)/128.0;
- modbuf[i].imag = ((float)rawbuf_u8[2*i+1]-127.0)/128.0;
- }
- }
- else {
- /* S16 complex */
- for(i=0;i<fsk_nin(fsk);i++){
- modbuf[i].real = ((float)rawbuf[2*i])/FDMDV_SCALE;
- modbuf[i].imag = ((float)rawbuf[2*i+1]/FDMDV_SCALE);
- }
- }
+
+ if (errs < 0.1 * TEST_FRAME_SIZE) {
+ /* OK, we have a valid test frame sync, so lets count errors */
+ testframe_detected = 1;
+ testframecnt++;
+ bitcnt += TEST_FRAME_SIZE;
+ biterr += errs;
+ if (enable_stats == 0) {
+ fprintf(stderr,
+ "errs: %d FSK BER %f, bits tested %d, bit errors %d\n",
+ errs, ((float)biterr / (float)bitcnt), bitcnt, biterr);
+ }
}
+ }
+ } /* if (testframe_mode) ... */
+
+ if (enable_stats) {
+ if ((stats_ctr < 0) || testframe_detected) {
+ fsk_get_demod_stats(fsk, &stats);
- if (soft_dec_mode) {
- int bps = log2(fsk->mode);
- assert(fsk->Nbits == bps*fsk->Nsym);
- /* output bit LLRs */
- fsk_demod_sd(fsk, rx_filt, modbuf);
- fsk_rx_filt_to_llrs(llrs, rx_filt, fsk->v_est, fsk->SNRest, fsk->mode, fsk->Nsym);
- } else {
- fsk_demod(fsk,bitbuf,modbuf);
+ /* Print standard 2FSK stats */
+
+ fprintf(stderr, "{");
+ time_t seconds = time(NULL);
+
+ fprintf(stderr, "\"secs\": %ld, \"EbNodB\": %5.1f, \"ppm\": %4d,",
+ (long)seconds, stats.snr_est, (int)fsk->ppm);
+ float *f_est;
+ if (fsk->freq_est_type)
+ f_est = fsk->f2_est;
+ else
+ f_est = fsk->f_est;
+ fprintf(stderr, " \"f1_est\":%.1f, \"f2_est\":%.1f", f_est[0],
+ f_est[1]);
+
+ /* Print 4FSK stats if in 4FSK mode */
+
+ if (fsk->mode == 4) {
+ fprintf(stderr, ", \"f3_est\":%.1f, \"f4_est\":%.1f", f_est[2],
+ f_est[3]);
}
-
- testframe_detected = 0;
- if (testframe_mode) {
- assert(soft_dec_mode == 0);
-
- /* attempt to find a testframe and update stats */
- /* update silding window of input bits */
-
- int errs;
- for(j=0; j<fsk->Nbits; j++) {
- for(i=0; i<TEST_FRAME_SIZE-1; i++) {
- bitbuf_rx[i] = bitbuf_rx[i+1];
- }
- bitbuf_rx[TEST_FRAME_SIZE-1] = bitbuf[j];
-
- /* compare to know tx frame. If they are time aligned, there
- will be a fairly low bit error rate */
-
- errs = 0;
- for(i=0; i<TEST_FRAME_SIZE; i++) {
- if (bitbuf_rx[i] != bitbuf_tx[i]) {
- errs++;
- }
- }
-
- if (errs < 0.1*TEST_FRAME_SIZE) {
- /* OK, we have a valid test frame sync, so lets count errors */
- testframe_detected = 1;
- testframecnt++;
- bitcnt += TEST_FRAME_SIZE;
- biterr += errs;
- if (enable_stats == 0) {
- fprintf(stderr,"errs: %d FSK BER %f, bits tested %d, bit errors %d\n",
- errs, ((float)biterr/(float)bitcnt),bitcnt,biterr);
- }
- }
- }
- } /* if (testframe_mode) ... */
-
- if (enable_stats) {
- if ((stats_ctr < 0) || testframe_detected) {
- fsk_get_demod_stats(fsk,&stats);
-
- /* Print standard 2FSK stats */
-
- fprintf(stderr,"{");
- time_t seconds = time(NULL);
-
- fprintf(stderr,"\"secs\": %ld, \"EbNodB\": %5.1f, \"ppm\": %4d,",(long)seconds, stats.snr_est, (int)fsk->ppm);
- float *f_est;
- if (fsk->freq_est_type)
- f_est = fsk->f2_est;
- else
- f_est = fsk->f_est;
- fprintf(stderr," \"f1_est\":%.1f, \"f2_est\":%.1f",f_est[0],f_est[1]);
-
- /* Print 4FSK stats if in 4FSK mode */
-
- if(fsk->mode == 4){
- fprintf(stderr,", \"f3_est\":%.1f, \"f4_est\":%.1f",f_est[2],f_est[3]);
- }
-
- if (testframe_mode == 0) {
- /* Print the eye diagram */
-
- fprintf(stderr,",\t\"eye_diagram\":[");
- for(i=0;i<stats.neyetr;i++){
- fprintf(stderr,"[");
- for(j=0;j<stats.neyesamp;j++){
- fprintf(stderr,"%f ",stats.rx_eye[i][j]);
- if(j<stats.neyesamp-1) fprintf(stderr,",");
- }
- fprintf(stderr,"]");
- if(i<stats.neyetr-1) fprintf(stderr,",");
- }
- fprintf(stderr,"],");
-
- /* Print a sample of the FFT from the freq estimator */
- fprintf(stderr,"\"samp_fft\":[");
- Ndft = fsk->Ndft/2;
- for(i=0; i<Ndft; i++){
- fprintf(stderr,"%f ",(fsk->Sf)[i]);
- if(i<Ndft-1) fprintf(stderr,",");
- }
- fprintf(stderr,"]");
- }
-
- if (testframe_mode) {
- fprintf(stderr,", \"frames\":%d, \"bits\":%d, \"errs\":%d",testframecnt,bitcnt,biterr);
- }
-
- fprintf(stderr,"}\n");
-
- if (stats_ctr < 0) {
- stats_ctr = stats_loop;
- }
- }
- if (testframe_mode == 0) {
- stats_ctr--;
+
+ if (testframe_mode == 0) {
+ /* Print the eye diagram */
+
+ fprintf(stderr, ",\t\"eye_diagram\":[");
+ for (i = 0; i < stats.neyetr; i++) {
+ fprintf(stderr, "[");
+ for (j = 0; j < stats.neyesamp; j++) {
+ fprintf(stderr, "%f ", stats.rx_eye[i][j]);
+ if (j < stats.neyesamp - 1) fprintf(stderr, ",");
}
+ fprintf(stderr, "]");
+ if (i < stats.neyetr - 1) fprintf(stderr, ",");
+ }
+ fprintf(stderr, "],");
+
+ /* Print a sample of the FFT from the freq estimator */
+ fprintf(stderr, "\"samp_fft\":[");
+ Ndft = fsk->Ndft / 2;
+ for (i = 0; i < Ndft; i++) {
+ fprintf(stderr, "%f ", (fsk->Sf)[i]);
+ if (i < Ndft - 1) fprintf(stderr, ",");
+ }
+ fprintf(stderr, "]");
}
- if(soft_dec_mode){
- fwrite(llrs,sizeof(float),fsk->Nbits,fout);
- } else{
- fwrite(bitbuf,sizeof(uint8_t),fsk->Nbits,fout);
+ if (testframe_mode) {
+ fprintf(stderr, ", \"frames\":%d, \"bits\":%d, \"errs\":%d",
+ testframecnt, bitcnt, biterr);
}
- if(fout == stdin){
- fflush(fout);
- }
- } /* while(fread ...... */
+ fprintf(stderr, "}\n");
- if (testframe_mode) {
- free(bitbuf_tx);
- free(bitbuf_rx);
+ if (stats_ctr < 0) {
+ stats_ctr = stats_loop;
+ }
+ }
+ if (testframe_mode == 0) {
+ stats_ctr--;
+ }
}
-
+
if (soft_dec_mode) {
- free(rx_filt);
- free(llrs);
- } else{
- free(bitbuf);
+ fwrite(llrs, sizeof(float), fsk->Nbits, fout);
+ } else {
+ fwrite(bitbuf, sizeof(uint8_t), fsk->Nbits, fout);
}
-
- free(rawbuf);
- free(modbuf);
-
- fclose(fin);
- fclose(fout);
- fsk_destroy(fsk);
-
- return 0;
-}
+ if (fout == stdin) {
+ fflush(fout);
+ }
+ } /* while(fread ...... */
+
+ if (testframe_mode) {
+ free(bitbuf_tx);
+ free(bitbuf_rx);
+ }
+
+ if (soft_dec_mode) {
+ free(rx_filt);
+ free(llrs);
+ } else {
+ free(bitbuf);
+ }
+
+ free(rawbuf);
+ free(modbuf);
+
+ fclose(fin);
+ fclose(fout);
+ fsk_destroy(fsk);
+
+ return 0;
+}