From 5f815a06cd9725e57bb4773060a0f6e67dfae13e Mon Sep 17 00:00:00 2001 From: baobrien Date: Fri, 22 Jan 2016 02:40:37 +0000 Subject: [PATCH] Further cleanup and documentation of FSK modem git-svn-id: https://svn.code.sf.net/p/freetel/code@2640 01035d8c-6547-0410-b346-abe4f91aad63 --- codec2-dev/octave/fsk_horus_2fsk.m | 64 +++++----------- codec2-dev/octave/tfsk.m | 114 +++++++++++------------------ codec2-dev/src/fsk.c | 68 ++++------------- codec2-dev/src/fsk.h | 53 ++++++++++---- codec2-dev/src/modem_probe.c | 5 +- codec2-dev/src/modem_probe.h | 51 +++++++++---- codec2-dev/unittest/tfsk.c | 2 +- 7 files changed, 158 insertions(+), 199 deletions(-) diff --git a/codec2-dev/octave/fsk_horus_2fsk.m b/codec2-dev/octave/fsk_horus_2fsk.m index 49637c21..4b92a00a 100644 --- a/codec2-dev/octave/fsk_horus_2fsk.m +++ b/codec2-dev/octave/fsk_horus_2fsk.m @@ -203,7 +203,6 @@ function [rx_bits states] = fsk_horus_demod(states, sf) states.f1 = f1; states.f2 = f2; - %printf("ESTF - f1 = %d, f2 = %d, twist = %f \n",f1,f2,twist); if bitand(verbose,0x1) printf("centre: %4.0f shift: %4.0f twist: %3.1f dB\n", (f2+f1)/2, f2-f1, twist); end @@ -248,8 +247,6 @@ function [rx_bits states] = fsk_horus_demod(states, sf) % symbols so we have extra samples for the fine timing re-sampler at either % end of the array. - - length(f1_dc); rx_bits = zeros(1, (nsym+1)*P); for i=1:(nsym+1)*P st = 1 + (i-1)*Ts/P; @@ -259,7 +256,7 @@ function [rx_bits states] = fsk_horus_demod(states, sf) end states.f1_int = f1_int; states.f2_int = f2_int; - length(f1_dc); + % fine timing estimation ----------------------------------------------- % Non linearity has a spectral line at Rs, with a phase @@ -270,10 +267,7 @@ function [rx_bits states] = fsk_horus_demod(states, sf) Np = length(f1_int); w = 2*pi*(Rs)/(P*Rs); - - %%# same as sum of ((abs(f1_int)-abs(f2_int)).^2) .* exp(-j*w*(0:Np-1)) x = ((abs(f1_int)-abs(f2_int)).^2) * exp(-j*w*(0:Np-1))'; - norm_rx_timing = angle(x)/(2*pi); rx_timing = norm_rx_timing*P; @@ -329,8 +323,6 @@ function [rx_bits states] = fsk_horus_demod(states, sf) %f1_int_resample(i) = f1_int(st+1); %f2_int_resample(i) = f2_int(st+1); rx_bits(i) = abs(f2_int_resample(i)) > abs(f1_int_resample(i)); - - rx_bits_sd(i) = abs(f2_int_resample(i)) - abs(f1_int_resample(i)); end @@ -342,7 +334,6 @@ function [rx_bits states] = fsk_horus_demod(states, sf) x = abs(abs(f1_int_resample) - abs(f2_int_resample)); states.EbNodB = 20*log10(1E-6+mean(x)/(1E-6+std(x))); - % printf("EbNodB %f\n",states.EbNodB); endfunction @@ -350,7 +341,7 @@ endfunction % UW found Sometimes there may be several matches, returns the % position of the best match to UW. -function [uw_start best_corr] = find_uw(states, start_bit, rx_bits) +function uw_start = find_uw(states, start_bit, rx_bits) uw = states.uw; mapped_rx_bits = 2*rx_bits - 1; @@ -494,21 +485,19 @@ function extract_and_print_rtty_packets(states, rx_bits_log, rx_bits_sd_log) if crc_ok == 0 [str_flipped crc_flipped_ok rx_bits_log] = sd_bit_flipping(states.rtty, rx_bits_log, rx_bits_sd_log, uw_loc, uw_loc+states.rtty.max_packet_len); + if crc_flipped_ok + str = sprintf("%s fixed", str_flipped); + end end % update memory of previous packet, we use this to guess where errors may be if crc_ok || crc_flipped_ok states.prev_pkt = rx_bits_log(uw_loc+length(states.rtty.uw):uw_loc+states.rtty.max_packet_len); end - if crc_ok str = sprintf("%s CRC OK", str); else - if crc_flipped_ok - str = sprintf("%s fixed", str_flipped); - else - str = sprintf("%s CRC BAD", str); - end + str = sprintf("%s CRC BAD", str); end printf("%s\n", str); end @@ -522,7 +511,7 @@ function extract_and_print_rtty_packets(states, rx_bits_log, rx_bits_sd_log) endfunction -% Extract as many binary packets as we can from a great big buffer of bits, +% Extract as many ASCII packets as we can from a great big buffer of bits, % and send them to the C decoder for FEC decoding. % horus_l2 can be compiled a bunch of different ways. You need to % compile with: @@ -641,7 +630,6 @@ function run_sim(test_frame_mode) states.f1_tx = 1200; states.f2_tx = 1600; states.tx_bits_file = "horus_tx_bits_rtty.txt"; % Octave file of bits we FSK modulate - end if test_frame_mode == 5 @@ -649,8 +637,7 @@ function run_sim(test_frame_mode) states = fsk_horus_init(8000, 100); states.f1_tx = 1200; states.f2_tx = 1600; - %%%states.tx_bits_file = "horus_tx_bits_binary.txt"; % Octave file of bits we FSK modulate - states.tx_bits_file = "horus_payload_rtty.txt" + states.tx_bits_file = "horus_tx_bits_binary.txt"; % Octave file of bits we FSK modulate end % ---------------------------------------------------------------------- @@ -845,7 +832,7 @@ function rx_bits_log = demod_file(filename, test_frame_mode, noplot) uwstates = fsk_horus_init_binary_uw; end - states.verbose = 0x1; + states.verbose = 0x1 + 0x8; N = states.N; P = states.P; @@ -863,8 +850,6 @@ function rx_bits_log = demod_file(filename, test_frame_mode, noplot) f2_int_resample_log = []; EbNodB_log = []; ppm_log = []; - f1_log = []; - f2_log = []; rx_bits_buf = zeros(1,2*nsym); % First extract raw bits from samples ------------------------------------------------------ @@ -902,8 +887,6 @@ function rx_bits_log = demod_file(filename, test_frame_mode, noplot) f2_int_resample_log = [f2_int_resample_log abs(states.f2_int_resample)]; EbNodB_log = [EbNodB_log states.EbNodB]; ppm_log = [ppm_log states.ppm]; - f1_log = [f1_log states.f1]; - f2_log = [f2_log states.f2]; if test_frame_mode == 1 states = ber_counter(states, test_frame, rx_bits_buf); @@ -921,18 +904,12 @@ function rx_bits_log = demod_file(filename, test_frame_mode, noplot) printf("plotting...\n"); figure(1); - plot(f1_log); - hold on; - plot(f2_log,'g'); - hold off; - - figure(2); plot(f1_int_resample_log,'+') hold on; plot(f2_int_resample_log,'g+') hold off; - figure(3) + figure(2) clf subplot(211) plot(norm_rx_timing_log) @@ -943,29 +920,28 @@ function rx_bits_log = demod_file(filename, test_frame_mode, noplot) plot(states.nerr_log) title('num bit errors each frame') - figure(4) + figure(3) clf plot(EbNodB_log); title('Eb/No estimate') - figure(5) + figure(4) clf - rx_nowave = rx(1000:length(rx)); subplot(211) - plot(rx_nowave(1:states.Fs)); + plot(rx(1:states.Fs)); title('input signal to demod (1 sec)') xlabel('Time (samples)'); axis([1 states.Fs -35000 35000]) - % normalise spectrum to 0dB full scale with a 32767 sine wave input + % normalise spectrum to 0dB full scale witha 32767 sine wave input subplot(212) - RxdBFS = 20*log10(abs(fft(rx_nowave(1:states.Fs)))) - 20*log10((states.Fs/2)*32767); + RxdBFS = 20*log10(abs(fft(rx(1:states.Fs)))) - 20*log10((states.Fs/2)*32767); plot(RxdBFS) axis([1 states.Fs/2 -80 0]) xlabel('Frequency (Hz)'); - figure(6); + figure(5); clf plot(ppm_log) title('Sample clock (baud rate) offset in PPM'); @@ -987,14 +963,10 @@ endfunction % run test functions from here during development if exist("fsk_horus_as_a_lib") == 0 - run_sim(5); + %run_sim(5); %rx_bits = demod_file("horus.raw",4); %rx_bits = demod_file("fsk_horus_100bd_binary.raw",5); - %rx_bits = demod_file("~/Desktop/phorus_binary_ascii.wav",4); - %rx_bits = demod_file("~/Desktop/binary/horus_160102_binary_rtty_2.wav",4); - - - %rx_bits = demod_file("~/Desktop/horus_160102_vk5ei_capture2.wav",4); + rx_bits = demod_file("~/Desktop/phorus_binary_ascii.wav",4); %rx_bits = demod_file("~/Desktop/horus_rtty_binary.wav",4); %rx_bits = demod_file("t.raw",5); %rx_bits = demod_file("~/Desktop/fsk_horus_10dB_1000ppm.wav",4); diff --git a/codec2-dev/octave/tfsk.m b/codec2-dev/octave/tfsk.m index 220529ac..0ad7a477 100644 --- a/codec2-dev/octave/tfsk.m +++ b/codec2-dev/octave/tfsk.m @@ -1,6 +1,24 @@ % tfsk.m -% Brady O'Brien 8 January 2016 +% Author: Brady O'Brien 8 January 2016 + + + +% Copyright 2016 David Rowe +% +% All rights reserved. +% +% This program is free software; you can redistribute it and/or modify +% it under the terms of the GNU Lesser General Public License version 2, 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 Lesser General Public License +% along with this program; if not, see . + + % Octave script to check c port of fsk_horus against the fsk_horus.m % % [X] - Functions to wrap around fsk_mod and fsk_demod executables @@ -10,19 +28,32 @@ % same dataset, compare outputs, and give clear go/no-go % [X] - fsk_mod_test % [X] - fsk_demod_test -% [.] - Port of run_sim and EbNodB curve test battery -% [ ] - Extract and compare more parameters from demod -% [ ] - Run some tests in parallel +% [X] - Port of run_sim and EbNodB curve test battery +% [X] - Extract and compare more parameters from demod +% [X] - Run some tests in parallel + +% +% FSK Modem test instructions -- +% 1 - Compile tfsk.c and fm_mod.c +% - tfsk.c is in unittest/, so build must not be configured for release +% 2 - Change tfsk_location and fsk_mod_location to point to tfsk and fsk_mod +% 3 - Ensure octave packages signal and parallel are installed +% 4 - run tfsk.m. It will take care of the rest. +% + + +global tfsk_location = '../build/unittest/tfsk'; +global fsk_mod_location = '../build/src/fsk_mod'; + fsk_horus_as_a_lib = 1; % make sure calls to test functions at bottom are disabled fsk_horus_2fsk; pkg load signal; - +pkg load parallel; graphics_toolkit('gnuplot'); global mod_pass_fail_maxdiff = 1e-3/50000; -global demod_pass_fail_maxdiff = .01; function mod = fsk_mod_c(Fs,Rs,f1,f2,bits) %Name of executable containing the modulator @@ -45,34 +76,6 @@ function mod = fsk_mod_c(Fs,Rs,f1,f2,bits) endfunction -function bits = fsk_demod_c(Fs,Rs,f1,f2,mod) - %Name of executable containing the modulator - fsk_demod_ex_file = '../build/unittest/tfsk'; - modvecfilename = sprintf('fsk_demod_ut_modvec_%d',getpid()); - bitvecfilename = sprintf('fsk_demod_ut_bitvec_%d',getpid()); - tvecfilename = sprintf('fsk_demod_ut_tracevec_%d.txt',getpid()); - - %command to be run by system to launch the demod - command = sprintf('%s %d %d %d %d %s %s %s',fsk_demod_ex_file,Fs,Rs,f1,f2,modvecfilename,bitvecfilename,tvecfilename); - - %save modulated input into a file - modvecfile = fopen(modvecfilename,'wb+'); - fwrite(modvecfile,mod,'single'); - fclose(modvecfile); - - %run the modulator - system(command); - - bitvecfile = fopen(bitvecfilename,'rb'); - bits = fread(bitvecfile,'uint8'); - fclose(bitvecfile); - bits = bits!=0; - - %Clean up files - delete(bitvecfilename); - delete(modvecfilename); - %delete(tvecfilename); -endfunction %Compare 2 vectors, fail if they are not close enough function pass = vcompare(va,vb,vname,tname,tol) @@ -138,12 +141,12 @@ function test_stats = fsk_demod_xt(Fs,Rs,f1,f2,mod,tname) delete(modvecfilename); delete(tvecfilename); - o_f1_dc = []; o_f2_dc = []; o_f1_int = []; o_f2_int = []; o_EbNodB = []; + o_ppm = []; o_rx_timing = []; %Run octave demod, dump some test vectors states = fsk_horus_init(Fs,Rs); @@ -167,15 +170,17 @@ function test_stats = fsk_demod_xt(Fs,Rs,f1,f2,mod,tname) o_f1_int = [o_f1_int states.f1_int]; o_f2_int = [o_f2_int states.f2_int]; o_EbNodB = [o_EbNodB states.EbNodB]; + o_ppm = [o_ppm states.ppm]; o_rx_timing = [o_rx_timing states.rx_timing]; end pass = vcompare(o_rx_timing, t_rx_timing,'rx_timing',tname,.011); pass = pass && vcompare(o_EbNodB, t_EbNodB, 'EbNodB', tname,.15); + pass = pass && vcompare(o_ppm , t_ppm, 'ppm', tname,.011); pass = pass && vcompare(o_f1_int, t_f1_int, 'f1_int', tname,.011); pass = pass && vcompare(o_f2_int, t_f2_int, 'f2_int', tname,.011); - pass = pass && vcompare(o_f1_dc(1:length(t_f1_dc)), t_f1_dc, 'f1_dc', tname,.001); - pass = pass && vcompare(o_f2_dc(1:length(t_f1_dc)), t_f2_dc, 'f2_dc', tname,.001); + pass = pass && vcompare(o_f1_dc, t_f1_dc, 'f1_dc', tname,.001); + pass = pass && vcompare(o_f2_dc, t_f2_dc, 'f2_dc', tname,.001); diffpass = sum(xor(obits,bits'))<3 @@ -213,39 +218,6 @@ function [dmod,cmod,omod,pass] = fsk_mod_test(Fs,Rs,f1,f2,bits,tname) end endfunction -function [cbits,obits,pass] = fsk_demod_test(Fs,Rs,f1,f2,mod,tname) - global pass_fail_maxdiff; - %Run the C demodulator - cbits = fsk_demod_c(Fs,Rs,f1,f2,mod)'; - %Set up and run the octave demodulator - states = fsk_horus_init(Fs,Rs); - states.f1_tx = f1; - states.f2_tx = f2; - states.dA = 1; - states.dF = 0; - - modin = mod; - obits = []; - while length(modin)>=states.nin - ninold = states.nin; - [bitbuf,states] = fsk_horus_demod(states, modin(1:states.nin)); - modin=modin(ninold+1:length(modin)); - obits = [obits bitbuf]; - end - - diff = sum(xor(obits,cbits)) - - %Allow 2 bit difference between model and C - pass = diff < 3 - if !pass - printf('Demod failed test %s!\n',tname); - figure(10); - plot((1:length(obits)),obits,(1:length(cbits)),cbits); - figure(11); - plot(xor(obits,cbits)); - end -endfunction - % Random bit modulator test % Pass random bits through the modulators and compare function pass = test_mod_horuscfg_randbits @@ -432,3 +404,5 @@ function pass = test_fsk_battery() printf("***** All tests passed! *****\n"); end endfunction + +test_fsk_battery diff --git a/codec2-dev/src/fsk.c b/codec2-dev/src/fsk.c index f767cc10..d37e7e74 100644 --- a/codec2-dev/src/fsk.c +++ b/codec2-dev/src/fsk.c @@ -113,8 +113,6 @@ struct FSK * fsk_create(int Fs, int Rs, int tx_f1,int tx_f2) fsk->nin = fsk->N; /* Set up rx state */ - fsk->phi1_d = 0; - fsk->phi2_d = 0; fsk->phi1_c.real = 1; fsk->phi1_c.imag = 0; fsk->phi2_c.real = 1; @@ -141,7 +139,6 @@ struct FSK * fsk_create(int Fs, int Rs, int tx_f1,int tx_f2) fsk->norm_rx_timing = 0; /* Set up tx state */ - fsk->tx_phase = 0; fsk->tx_phase_c.imag = 0; fsk->tx_phase_c.real = 1; @@ -269,7 +266,6 @@ void fsk_demod_freq_est(struct FSK *fsk, float fsk_in[],float *f1_est,float *f2_ *f1_est = (float)m1*(float)Fs/(float)Ndft; *f2_est = (float)m2*(float)Fs/(float)Ndft; *twist = 20*log10f(m1v/m2v); - //printf("ESTF - f1 = %f, f2 = %f, twist = %f \n",*f1_est,*f2_est,*twist); } @@ -330,12 +326,12 @@ void fsk_demod(struct FSK *fsk, uint8_t rx_bits[], float fsk_in[]){ COMP t1,t2; COMP phi1_c = fsk->phi1_c; COMP phi2_c = fsk->phi2_c; - COMP phi_ft; /* Phase of fine timing estimator */ + COMP phi_ft; int nold = Nmem-nin; COMP dphi1,dphi2; COMP dphift; float f1,f2; - float rx_timing,norm_rx_timing;//,old_norm_rx_timing;//,d_norm_rx_timing; + float rx_timing,norm_rx_timing,old_norm_rx_timing,d_norm_rx_timing,appm; int using_old_samps; float *sample_src; COMP *f1_intbuf,*f2_intbuf; @@ -417,12 +413,7 @@ void fsk_demod(struct FSK *fsk, uint8_t rx_bits[], float fsk_in[]){ if(cbuf_i>=Ts) cbuf_i = 0; /* Integrate over the integration buffers, save samples */ - /* This uses Kahan summation to reduce floating point funnyness */ t1 = t2 = comp0(); - f1_strc = f1_stic = 0; - f2_strc = f2_stic = 0; - f1_strs = f1_stis = 0; - f2_strs = f2_stis = 0; for(j=0; jnorm_rx_timing; + old_norm_rx_timing = fsk->norm_rx_timing; fsk->norm_rx_timing = norm_rx_timing; /* Estimate sample clock offset */ - //d_norm_rx_timing = norm_rx_timing - old_norm_rx_timing; + d_norm_rx_timing = norm_rx_timing - old_norm_rx_timing; /* Filter out big jumps in due to nin change */ - //if(fabsf(d_norm_rx_timing) < .2){ + if(fabsf(d_norm_rx_timing) < .2){ + appm = 1e6*d_norm_rx_timing/(float)nsym; + fsk->ppm = .9*fsk->ppm + .1*appm; + } /* Figure out how many samples are needed the next modem cycle */ if(norm_rx_timing > 0.25) @@ -494,6 +485,7 @@ void fsk_demod(struct FSK *fsk, uint8_t rx_bits[], float fsk_in[]){ #ifdef EST_EBNO meanebno = 0; + stdebno = 0; #endif /* FINALLY, THE BITS */ @@ -506,11 +498,14 @@ void fsk_demod(struct FSK *fsk, uint8_t rx_bits[], float fsk_in[]){ t2 = cadd(t2,fcmult( fract,f2_int[st+high_sample])); /* Accumulate resampled int magnitude for EbNodB estimation */ + /* Standard deviation is calculated by algorithm devised by crafty soviets */ #ifdef EST_EBNO + ft1 = sqrtf(t1.real*t1.real + t1.imag*t1.imag); ft2 = sqrtf(t2.real*t2.real + t2.imag*t2.imag); ft1 = fabsf(ft1-ft2); meanebno += ft1; + #endif /* THE BIT! */ @@ -546,6 +541,7 @@ void fsk_demod(struct FSK *fsk, uint8_t rx_bits[], float fsk_in[]){ /* Dump some internal samples */ modem_probe_samp_f("t_EbNodB",&(fsk->EbNodB),1); + modem_probe_samp_f("t_ppm",&(fsk->ppm),1); modem_probe_samp_f("t_f1",&f1,1); modem_probe_samp_f("t_f2",&f2,1); modem_probe_samp_c("t_f1_int",f1_int,(nsym+1)*P); @@ -553,42 +549,6 @@ void fsk_demod(struct FSK *fsk, uint8_t rx_bits[], float fsk_in[]){ modem_probe_samp_f("t_rx_timing",&(rx_timing),1);; } - -void fsk_mod_realphase(struct FSK *fsk,float fsk_out[],uint8_t tx_bits[]){ - float tx_phase = fsk->tx_phase; /* current TX phase */ - int f1_tx = fsk->f1_tx; /* '0' frequency */ - int f2_tx = fsk->f2_tx; /* '1' frequency */ - int Ts = fsk->Ts; /* samples-per-symbol */ - int Fs = fsk->Fs; /* sample freq */ - int i,j; - uint8_t bit; - - /* delta-phase per cycle for both symbol freqs */ - float dph_f1 = 2*M_PI*((float)(f1_tx)/(float)(Fs)); - float dph_f2 = 2*M_PI*((float)(f2_tx)/(float)(Fs)); - - /* Note: Right now, this mirrors fm.c and fsk_horus.m, but it - * ought to be possible to make it more efficent (one complex mul per - * cycle) by using a complex number for the phase. */ - - /* Outer loop through bits */ - for(i=0; iNsym; i++){ - bit = tx_bits[i]; - for(j=0; j2*M_PI) - tx_phase -= 2*M_PI; - fsk_out[i*Ts+j] = 2*cosf(tx_phase); - } - } - - /* save TX phase */ - fsk->tx_phase = tx_phase; - -} - void fsk_mod(struct FSK *fsk,float fsk_out[],uint8_t tx_bits[]){ COMP tx_phase_c = fsk->tx_phase_c; /* Current complex TX phase */ int f1_tx = fsk->f1_tx; /* '0' frequency */ diff --git a/codec2-dev/src/fsk.h b/codec2-dev/src/fsk.h index 35ef7b13..90dcdfd2 100644 --- a/codec2-dev/src/fsk.h +++ b/codec2-dev/src/fsk.h @@ -46,20 +46,17 @@ struct FSK { int f2_tx; /* f2 for modulator */ /* Parameters used by demod */ - float phi1_d; /* f1 oscillator for demod */ - float phi2_d; /* f2 oscillator for demod */ COMP phi1_c; COMP phi2_c; kiss_fftr_cfg fft_cfg; /* Config for KISS FFT, used in freq est */ float norm_rx_timing; /* Normalized RX timing */ - float *samp_old; /* Ass end of last batch of samples */ + float *samp_old; /* Tail end of last batch of samples */ int nstash; /* How many elements are in there */ /* Memory used by demod but not important between demod frames */ /* Parameters used by mod */ - float tx_phase; /* phase of modulator */ COMP tx_phase_c; /* TX phase, but complex */ /* Statistics generated by demod */ @@ -67,28 +64,58 @@ struct FSK { float f1_est; /* Estimated f1 freq. */ float f2_est; /* Estimated f2 freq. */ float twist_est; /* Estimaged 'twist' from freq est */ + float ppm; /* Estimated PPM clock offset */ /* Parameters used by mod/demod and driving code */ int nin; /* Number of samples to feed the next demod cycle */ }; +/* + * Create an FSK config/state struct from a set of config parameters + * + * int Fs - Sample frequency + * int Rs - Symbol rate + * int tx_f1 - '0' frequency + * int tx_f2 - '1' frequency + */ struct FSK * fsk_create(int Fs, int Rs, int tx_f1, int tx_f2); + +/* + * Destroy an FSK state struct and free it's memory + * + * struct FSK *fsk - FSK config/state struct to be destroyed + */ void fsk_destroy(struct FSK *fsk); -void fsk_mod(struct FSK *fsk, - float fsk_out[], /* N float output modulated FSK samples */ - uint8_t tx_bits[] /* Nsym unpacked input bits in LSB */ - ); +/* + * Modulates Nsym bits into N samples + * + * struct FSK *fsk - FSK config/state struct, set up by fsk_create + * float fsk_out[] - Buffer for N samples of modulated FSK + * uint8_t tx_bits[] - Buffer containing Nsym unpacked bits + */ +void fsk_mod(struct FSK *fsk, float fsk_out[], uint8_t tx_bits[]); -/* number of input samples required for next call to fsk_demod() */ +/* + * Returns the number of samples needed for the next fsk_demod() cycle + * + * struct FSK *fsk - FSK config/state struct, set up by fsk_create + * returns - number of samples to be fed into fsk_demod next cycle + */ uint32_t fsk_nin(struct FSK *fsk); -void fsk_demod(struct FSK *fsk, - uint8_t rx_bits[], /* Nsym unpacked output demodulated rx bits in each LSB */ - float fsk_in[] /* N input float modulated FSK samples */ - ); + +/* + * Demodulate some number of FSK samples. The number of samples to be + * demodulated can be found by calling fsk_nin(). + * + * struct FSK *fsk - FSK config/state struct, set up by fsk_create + * uint8_t rx_bits[] - Buffer for Nsym unpacked bits to be written + * float fsk_in[] - nin samples of modualted FSK + */ +void fsk_demod(struct FSK *fsk, uint8_t rx_bits[],float fsk_in[]); diff --git a/codec2-dev/src/modem_probe.c b/codec2-dev/src/modem_probe.c index 612d3350..884a1a85 100644 --- a/codec2-dev/src/modem_probe.c +++ b/codec2-dev/src/modem_probe.c @@ -4,7 +4,8 @@ AUTHOR......: Brady O'Brien DATE CREATED: 9 January 2016 - Library to easily extract debug traces from modems during development + Library to easily extract debug traces from modems during development and + verification \*---------------------------------------------------------------------------*/ @@ -110,7 +111,7 @@ void modem_probe_close_int(){ switch(cur->type){ case TRACE_I: octave_save_int(dumpfile,cur->name,(int32_t*)dbuf,1,len/sizeof(int32_t)); - break; + break; case TRACE_F: octave_save_float(dumpfile,cur->name,(float*)dbuf,1,len/sizeof(float),10); break; diff --git a/codec2-dev/src/modem_probe.h b/codec2-dev/src/modem_probe.h index 320acaae..2faada13 100644 --- a/codec2-dev/src/modem_probe.h +++ b/codec2-dev/src/modem_probe.h @@ -34,6 +34,7 @@ #ifdef MODEMPROBE_ENABLE +/* Internal functions */ void modem_probe_init_int(char *modname, char *runname); void modem_probe_close_int(); @@ -41,48 +42,72 @@ void modem_probe_samp_i_int(char * tracename,int samp[],size_t cnt); void modem_probe_samp_f_int(char * tracename,float samp[],size_t cnt); void modem_probe_samp_c_int(char * tracename,COMP samp[],size_t cnt); - +/* + * Init the probe library. + * char *modname - Name of the modem under test + * char *runname - Name/path of the file data is dumped to + */ static inline void modem_probe_init(char *modname,char *runname){ - modem_probe_init_int(modname,runname); + modem_probe_init_int(modname,runname); } +/* + * Dump traces to a file and clean up + */ static inline void modem_probe_close(){ - modem_probe_close_int(); + modem_probe_close_int(); } +/* + * Save some number of int samples to a named trace + * char *tracename - name of trace being saved to + * int samp[] - int samples + * size_t cnt - how many samples to save + */ static inline void modem_probe_samp_i(char *tracename,int samp[],size_t cnt){ - modem_probe_samp_i_int(tracename,samp,cnt); + modem_probe_samp_i_int(tracename,samp,cnt); } - +/* + * Save some number of float samples to a named trace + * char *tracename - name of trace being saved to + * float samp[] - int samples + * size_t cnt - how many samples to save + */ static inline void modem_probe_samp_f(char *tracename,float samp[],size_t cnt){ - modem_probe_samp_f_int(tracename,samp,cnt); -} + modem_probe_samp_f_int(tracename,samp,cnt); +} +/* + * Save some number of complex samples to a named trace + * char *tracename - name of trace being saved to + * COMP samp[] - int samples + * size_t cnt - how many samples to save + */ static inline void modem_probe_samp_c(char *tracename,COMP samp[],size_t cnt){ - modem_probe_samp_c_int(tracename,samp,cnt); + modem_probe_samp_c_int(tracename,samp,cnt); } #else static inline void modem_probe_init(char *modname,char *runname){ - return; + return; } static inline void modem_probe_close(){ - return; + return; } static inline void modem_probe_samp_i(char *name,int samp[],size_t sampcnt){ - return; + return; } static inline void modem_probe_samp_f(char *name,float samp[],size_t cnt){ - return; + return; } static inline void modem_probe_samp_c(char *name,COMP samp[],size_t cnt){ - return; + return; } #endif diff --git a/codec2-dev/unittest/tfsk.c b/codec2-dev/unittest/tfsk.c index ae852423..c31996c1 100644 --- a/codec2-dev/unittest/tfsk.c +++ b/codec2-dev/unittest/tfsk.c @@ -6,7 +6,7 @@ C test driver for fsk_mod and fsk_demod in fsk.c. Reads a file with input bits/rf and spits out modulated/demoduladed samples and a dump of internal - state + state. To run unit test, see octave/tfsk.m \*---------------------------------------------------------------------------*/ -- 2.25.1