From 3e9ced28a951b14434a55ffdea4be203d792afca Mon Sep 17 00:00:00 2001 From: drowe67 Date: Fri, 9 Dec 2022 07:23:04 +1030 Subject: [PATCH 01/52] first pass at datac4, but has acquisition problems on MPP, even at high SNRs, works at -8dB SNR on AWGN --- doc/modem_codec_frame_design.ods | Bin 36993 -> 42874 bytes octave/ofdm_lib.m | 17 ++++++++++++++++- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/doc/modem_codec_frame_design.ods b/doc/modem_codec_frame_design.ods index 449f10cf61ff18931ab629422a043fbae7f9ef6b..c49122e2b0ae90d2982a01c9f6e7c20809f67e6c 100644 GIT binary patch delta 39430 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 D01Gzu diff --git a/octave/ofdm_lib.m b/octave/ofdm_lib.m index 81bc1cbbe..4ee5137ac 100644 --- a/octave/ofdm_lib.m +++ b/octave/ofdm_lib.m @@ -377,6 +377,17 @@ config.amp_est_mode = 1; config.EsNodB = 3; config.state_machine = "data"; config.amp_scale = 300E3; config.clip_gain1 = 2.2; config.clip_gain2 = 0.8; + elseif strcmp(mode,"datac4") + Ns=5; config.Np=23; Tcp = 0.006; Ts = 0.016; Nc = 3; config.data_mode = "streaming"; + config.edge_pilots = 0; + config.Ntxtbits = 0; config.Nuwbits = 40; config.bad_uw_errors = 10; + config.ftwindow_width = 80; config.timing_mx_thresh = 0.08; + config.tx_uw = zeros(1,config.Nuwbits); + config.tx_uw(1:24) = [1 1 0 0 1 0 1 0 1 1 1 1 0 0 0 0 1 1 1 1 0 0 0 0]; + config.tx_uw(end-24+1:end) = [1 1 0 0 1 0 1 0 1 1 1 1 0 0 0 0 1 1 1 1 0 0 0 0]; + config.amp_est_mode = 1; config.EsNodB = 3; + config.state_machine = "data"; + config.amp_scale = 300E3; config.clip_gain1 = 2.2; config.clip_gain2 = 0.8; elseif strcmp(mode,"1") Ns=5; config.Np=10; Tcp=0; Tframe = 0.1; Ts = Tframe/Ns; Nc = 1; else @@ -1710,7 +1721,11 @@ function test_assemble_disassemble(states) load H_1024_2048_4f.mat code_param = ldpc_init_user(H, modulation, mod_order, mapping); end - if strcmp(mode, "datac0") || strcmp(mode, "datac1") || strcmp(mode, "datac3") || strcmp(mode, "qam16c1") || strcmp(mode, "qam16c2") + if strcmp(mode, "datac4") + load H_256_512_4.mat + code_param = ldpc_init_user(H, modulation, mod_order, mapping); + end + if strcmp(mode, "datac0") || strcmp(mode, "datac1") || strcmp(mode, "datac3") || strcmp(mode, "datac4") || strcmp(mode, "qam16c1") || strcmp(mode, "qam16c2") printf("ldpc_data_bits_per_frame = %d\n", code_param.ldpc_data_bits_per_frame); printf("ldpc_coded_bits_per_frame = %d\n", code_param.ldpc_coded_bits_per_frame); printf("ldpc_parity_bits_per_frame = %d\n", code_param.ldpc_parity_bits_per_frame); From 653d7a96dc6e9786f969cb994ac2259771a51fc8 Mon Sep 17 00:00:00 2001 From: drowe67 Date: Fri, 9 Dec 2022 09:04:10 +1030 Subject: [PATCH 02/52] prototyped datac5 in Octave: 1700 bits/s 7dB MPP, which is too close to datac1 - would rather higher throughput bit rate --- doc/modem_codec_frame_design.ods | Bin 42874 -> 44629 bytes octave/ofdm_lib.m | 15 ++++++++++++++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/doc/modem_codec_frame_design.ods b/doc/modem_codec_frame_design.ods index c49122e2b0ae90d2982a01c9f6e7c20809f67e6c..cff1d0954c624031c8f2237e152835558e69be14 100644 GIT binary patch delta 39947 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 z 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

=WDvgOP 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 X;s5*T=>N;`EF9%n#z#F;eyRN*E2(7k delta 38103 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 diff --git a/octave/ofdm_lib.m b/octave/ofdm_lib.m index 4ee5137ac..d8890c28a 100644 --- a/octave/ofdm_lib.m +++ b/octave/ofdm_lib.m @@ -353,6 +353,15 @@ config.tx_uw = zeros(1,config.Nuwbits); config.tx_uw(1:16) = [1 1 0 0 1 0 1 0 1 1 1 1 0 0 0 0]; config.amp_scale = 300E3; config.clip_gain1 = 2.2; config.clip_gain2 = 0.85; + elseif strcmp(mode,"datac5") + Ns=5; config.Np=58; Tcp = 0.004; Ts = 0.016; Nc = 35; config.data_mode = "streaming"; + config.Ntxtbits = 0; config.Nuwbits = 40; config.bad_uw_errors = 14; + config.state_machine = "data"; + config.ftwindow_width = 80; config.amp_est_mode = 1; config.EsNodB = 3; + config.amp_scale = 145E3; config.clip_gain1 = 2.7; config.clip_gain2 = 0.8; + config.edge_pilots = 0; config.timing_mx_thresh = 0.10; + config.tx_uw = zeros(1,config.Nuwbits); + config.tx_uw(1:16) = [1 1 0 0 1 0 1 0 1 1 1 1 0 0 0 0]; elseif strcmp(mode,"datac1") Ns=5; config.Np=38; Tcp = 0.006; Ts = 0.016; Nc = 27; config.data_mode = "streaming"; config.Ntxtbits = 0; config.Nuwbits = 16; config.bad_uw_errors = 6; @@ -1709,6 +1718,10 @@ function test_assemble_disassemble(states) framesize = 16200; rate = 0.6; code_param = ldpc_init_builtin("dvbs2", rate, framesize, modulation='QAM', mod_order=16, mapping="", reshape(states.qam16,1,16)); end + if strcmp(mode, "datac5") + framesize = 16200; rate = 0.6; + code_param = ldpc_init_builtin("dvbs2", rate, framesize, modulation='QPSK', mod_order=4, mapping=""); + end if strcmp(mode, "datac0") load H_128_256_5.mat code_param = ldpc_init_user(H, modulation, mod_order, mapping); @@ -1725,7 +1738,7 @@ function test_assemble_disassemble(states) load H_256_512_4.mat code_param = ldpc_init_user(H, modulation, mod_order, mapping); end - if strcmp(mode, "datac0") || strcmp(mode, "datac1") || strcmp(mode, "datac3") || strcmp(mode, "datac4") || strcmp(mode, "qam16c1") || strcmp(mode, "qam16c2") + if strcmp(mode, "datac0") || strcmp(mode, "datac1") || strcmp(mode, "datac3") || strcmp(mode, "datac4") || strcmp(mode, "qam16c1") || strcmp(mode, "qam16c2") || strcmp(mode, "datac5") printf("ldpc_data_bits_per_frame = %d\n", code_param.ldpc_data_bits_per_frame); printf("ldpc_coded_bits_per_frame = %d\n", code_param.ldpc_coded_bits_per_frame); printf("ldpc_parity_bits_per_frame = %d\n", code_param.ldpc_parity_bits_per_frame); From 1718fe34873ac1ac9ca8971320a6fdc2120f2521 Mon Sep 17 00:00:00 2001 From: drowe67 Date: Sat, 10 Dec 2022 06:09:38 +1030 Subject: [PATCH 03/52] tried a rate 0.75 code but much poorer performance, so back to rate 0.6 --- doc/modem_codec_frame_design.ods | Bin 44629 -> 44543 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/doc/modem_codec_frame_design.ods b/doc/modem_codec_frame_design.ods index cff1d0954c624031c8f2237e152835558e69be14..560e62ee7aaf376c76e0abdceb7c381b7971d257 100644 GIT binary patch delta 3517 zcmY*cc{mhY7as~Ul5NPY5ZM{8eP2d0OqfCRVq_3Sk!_?**(2-N8cWv6GWP6S_9eS4 z8EeIxoh(_KFZI3O(|7+kzkAO)cYE%+&-tCPX-YDQlFr!R+<6uN00;o+)Wp&uD1S;@ z*`E?eq~OQBD4?VL!)(hRyT$y=gC8eEan}3gWnK8E7w!>-;%|%m8GNBII|CI;m7h?7 zp;V(d8&;p=!Q$ejS%Sa+prxG&X}}Pi9MP7Nog<$RjOc8?0V`u zfZK@8U8~cFL0&!{VS9%it+gl@Qlo>!H>I+*3{UWL!n#%qFp}{FW42x#kQbClCF=+= zvfy6C9z^lqLJ$$1j1FP;dU2q{urO+I2PU}UHKp0o4%T?@(GCGQ&z<^ksfA;K*+8xCwW&9pTTZ+xT`hU#F003_1 z0D#|N1Ox(qhEYW!6%cs#%9R%-uwkxucRiJ9G*&-M(fUU!`0+z?FM@DES*Lqk#`VYx zJW#h)$;Q0!o*i}2!}JDU!P=9m(xD!3PT$po`^8)Oy=j_6a9evtNv(g0`;p-H^_6G? znKZnzI2Y7MJnT>;Fg1dI4Qkp&B!X4tbg4o=$x!s!JJ5-D_gYDTxjw(9k?`mDOq7a;lG zTE>}-yJ2ahCp}432P5rRRUbj?rMZB$^V1>7boy^YvInZbIyaN}FO3T&nMx@%2&s75 zZ@Q)@$P1HigyiQbIZ0I+Tu+itlv~kXWoXe~t6oarUm_PMYsCinXjLG4n$?*7XJ2FI zn4VheCfesSw@?()I|R*w9Um=_voi*wd<9SfWT3Ws#1jUTj+io5;dO?i0Im=)IPX0- z2#Or^Yg2TYgf^wLl-^4=>f(;#nzmm=2j1pO1&a-d+3`n%${te+9i*>QC8}+V3 za*>Fpc)P{Bj_=sYZ8fa|A%PnZKh=OMJlVYKO08tE$EGK#%O(W9;k~aFSI3Mzl{j?6 zIlxd*?0}5E@@@TI?Ht26@0hD;eXjc${&Po(iTX2E%^y6@tAIUKfT@&(A}Rge_o@ z5|*8GM~%j(0P9}F%qz)`(cD%P$f030BAK=;&(N~{ZS*bs*4<_{!ly1aLPhd|o{-^X z&E)c2D}v#6{PJ41)M7c^=x{G0ac{s>BwaKOyQ?R1;bTR-o|u89zX&eZ+F|)xDJ`4c zmZ}2*hV3eVLDKklNLCaYt1(lhK~z{fjst7|O6VE_PQNd=PY;deGIO{$@HMSZJfoE|p!%Tz)Iz&ftZ zaG)LMbf-}UmBf%)MqEsn2df5g}i+pZvyA zE7Ap=E4>^WXT_2O0Hd_r)~+uSfc;g%(jnj~JV zPicjE-<29bpsL&UC5%nSN`TJuf8h1pR+(3ZH~g4nwm0n&R2HGa!A(`JZ`c01ai5>p zfMRwbhc-s?Dn2w^>&d|iw{gaWH$>+5gcx7-*O+$mYM~+HWKbzk9-g8AoqyG8xRkOz z^?aWHsm`X|X6Ar8=I?_e3guP$Jp?ZKU>sXGD05k56?W%(ssB5 zP0{J@7*VC#O%znM6sLa^6P{o1JqMF^AG536+eYBopNdd*D#X~K7B_i_9$l}o#Yl)} zj9f>iUF8Qh7Q1eZeOH|zhU#|Ut4Z{OR#&iXp50p}NOaD-X@;3A>tPIhx2*!#wkf`i z26#%Q`D=*X;8)ENviJK~Pa~gm5hlK1IpBSy*y2sqdX8FZKvam@?nkX%@7`-)ecie~ zY?Pk0KM6@&J=O|;W9~!BrXP{O26^5(l*Z1qW{|K|tDj9mDeqsY^z*77Mb_*OSp#PW zKM(u(sn+d<)3Yv``))Lu7K!y*?bux0HmZOTrd)1l$U2yGBnYyn8++gal7M~0Mg(+^TidI|D*p98~)>Q;-%SR zeGiBN{&ZyWp0xGGoMA}hqQ&)r=***0cCVZlp-9}cH~dbu*@X3&h(uTa^ZT-Qb4j5a zk^VDxJ`c0Qp-L?~?k@S=r9*8s)nyAwNiC&;8-Bg;W|MrM#khF|#lKbxN>RfBt4dOx8-Zs5;YOoqV za`UeF2Ij|$u$oyA>SPSsZEl@#C=Fy`1%s*6Vu%ld;OII zeV#z9x4@bVBSXGGtQ_y{SzStW9JyZyn%P{iIG1|iHG>L-yz=lYg9kee=)9r<06b9t zX7Jxcup*Lm6Me?l{C$JZ_*yoVpE#B?vZN<;cjJK5eJ;pJT6;p93HEHrrP`O<`$QOg zcfLMgn&x&X&TfhcSz)dDLpRzXRX^y1WqR^6rxtozCx)2Ft>SlD0W@Vq`>vpjJ8}$r zQ6Xb%PO458aBvWh0)x5El7#_AzL-o6y+{<%y0w3P9AoU(m_emd^&}~bD1to)M@N*g zxF~JjKkhJPP9o6#c|YJ=0j+DIkYtYWx+*HViV<6i-+ZhTC`<56fT5hAnMx7g0jdFXEiUBeR@C z(w$lQ_fJEw4?D5+f7<=RMV+bi^mO6;G;@Ba>iU8xdnCde=9$-uosh)`LLf;W#~JAN z(sCQ&1Lb$WbM|kZ!<(57L4JyH!xBqf zyx9kg`SA0Vq!3m!kl4}D+Wj@PH)M+?>e8>PsTRAH+~q(n!fH)asA^Z0l~ErKCOS62 zw(y1HhM`~<${7n)dAX!mNwO&5vI^qy!Y?uAy2G=aFNLIwDUxGhk8ZJxj>_JPml}JS zyu3bE-WeDbqqq$0$%^uxepu2ZgB3pg)@E}MEFSI*BTmPU_ceo1BBLqNeTh;woo)4t zs5XprHkZH%u-x%x`Q{Iev+!KYf0GTD1OQB<&H;=s8c20Hct~PgU5x*Gmfw6g%4L_ah)v^QN&H@ s$BIj1<)r`r*|^~%ZVDINM$y&FXFLCS=L>(X1lYkrig~Gh^Usw30g>X3&j0`b delta 3621 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 From 5299fb324f47cad5cb4ebb47dac6f31dd2463466 Mon Sep 17 00:00:00 2001 From: drowe67 Date: Sat, 10 Dec 2022 09:16:14 +1030 Subject: [PATCH 04/52] cleaned up ofdm_acquisition a little --- CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 7a4f32918..2fb562087 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -470,7 +470,7 @@ endif() add_test(NAME test_OFDM_modem_octave_burst_acq COMMAND sh -c "cd ${CMAKE_CURRENT_SOURCE_DIR}/octave; - echo \"ofdm_acquisition; quit\" | DISPLAY=\"\" octave-cli") + echo \"ctest=1; ofdm_acquisition; quit\" | DISPLAY=\"\" octave-cli") set_tests_properties(test_OFDM_modem_octave_burst_acq PROPERTIES PASS_REGULAR_EXPRESSION "P.acq. = 1.00") add_test(NAME test_OFDM_modem_octave_datac0_postamble From 522bec24ffbe637a7c7d4712b64c0e6a99968dbd Mon Sep 17 00:00:00 2001 From: drowe67 Date: Sat, 10 Dec 2022 09:17:33 +1030 Subject: [PATCH 05/52] added an input BPF to datac4 acquisition, sensible results at -5dB MPP now, ofdm_ldpc_rx around 20% PER at -4dB MPP --- octave/ofdm_acquisition.m | 20 ++++++++++++++++---- octave/ofdm_ldpc_rx.m | 7 +++++-- octave/ofdm_lib.m | 2 +- 3 files changed, 22 insertions(+), 7 deletions(-) diff --git a/octave/ofdm_acquisition.m b/octave/ofdm_acquisition.m index c37df3c43..46d8d05a4 100644 --- a/octave/ofdm_acquisition.m +++ b/octave/ofdm_acquisition.m @@ -5,7 +5,7 @@ % % To run headless on a server: % -% DISPLAY=\"\" octave-cli --no-gui -qf ofdm_dev.m > 210218.txt & +% DISPLAY=\"\" octave-cli --no-gui -qf ofdm_acquisition.m > 210218.txt & ofdm_lib; channel_lib; @@ -39,7 +39,13 @@ mark_space_SNR_offset = 10*log10(burst_len/padded_burst_len); SNRdB_setpoint = sim_in.SNR3kdB + mark_space_SNR_offset; %printf("SNR3kdB: %f Burst offset: %f\n", sim_in.SNR3kdB, mark_space_SNR_offset) - rx = channel_simulate(Fs, SNRdB_setpoint, sim_in.foff_Hz, sim_in.channel, tx); + + % experimental BPF + if strcmp(sim_in.mode,"datac4") + rx = channel_simulate(Fs, SNRdB_setpoint, sim_in.foff_Hz, sim_in.channel, tx); + rx = filter(fir1(100,[1400 1600]/4000),1,rx); + l = length(rx); rx = [rx(50:l) zeros(1,50)]; + end endfunction @@ -227,5 +233,11 @@ function acquistion_curves_frame_by_frame_modes_channels_snr(Ntests=5, quick_tes % choose simulation to run here % --------------------------------------------------------- -frame_by_frame_acquisition_test("datac0", Ntests=5, 'mpp', SNR3kdB=5, foff_hz=0, verbose=1+8); -%acquistion_curves_frame_by_frame_modes_channels_snr(Ntests=50, quick_test=0) +if exist("ctest","var") + % simple tests to run as part of ctests + frame_by_frame_acquisition_test("datac0", Ntests=5, 'mpp', SNR3kdB=5, foff_hz=0, verbose=1+8); +else + % other development work here + frame_by_frame_acquisition_test("datac4", Ntests=20, 'mpp', SNR3kdB=-5, foff_hz=0, verbose=1+8); + %acquistion_curves_frame_by_frame_modes_channels_snr(Ntests=50, quick_test=0) +end diff --git a/octave/ofdm_ldpc_rx.m b/octave/ofdm_ldpc_rx.m index 83d115f63..9ff308dcf 100644 --- a/octave/ofdm_ldpc_rx.m +++ b/octave/ofdm_ldpc_rx.m @@ -54,7 +54,10 @@ function ofdm_ldpc_rx(filename, mode="700D", varargin) frx=fopen(filename,"rb"); rx = fread(frx, Inf, "short")/Ascale; fclose(frx); Nsam = length(rx); prx = 1; - + if strcmp(mode,"datac4") + rx = filter(fir1(100,[1400 1600]/4000),1,rx); + end + % Generate tx frame for BER calcs payload_bits = round(ofdm_rand(code_param.data_bits_per_frame)/32767); @@ -270,7 +273,7 @@ function ofdm_ldpc_rx(filename, mode="700D", varargin) end end - figure(9); clf; plot_specgram(rx); + figure(9); clf; plot_specgram(rx, Fs=8000, 0, 3000); if pass_packet_count > 0 if packet_count >= pass_packet_count printf("Pass!\n"); else printf("Fail!\n"); end; diff --git a/octave/ofdm_lib.m b/octave/ofdm_lib.m index d8890c28a..fd085f8fd 100644 --- a/octave/ofdm_lib.m +++ b/octave/ofdm_lib.m @@ -390,7 +390,7 @@ Ns=5; config.Np=23; Tcp = 0.006; Ts = 0.016; Nc = 3; config.data_mode = "streaming"; config.edge_pilots = 0; config.Ntxtbits = 0; config.Nuwbits = 40; config.bad_uw_errors = 10; - config.ftwindow_width = 80; config.timing_mx_thresh = 0.08; + config.ftwindow_width = 80; config.timing_mx_thresh = 0.25; config.tx_uw = zeros(1,config.Nuwbits); config.tx_uw(1:24) = [1 1 0 0 1 0 1 0 1 1 1 1 0 0 0 0 1 1 1 1 0 0 0 0]; config.tx_uw(end-24+1:end) = [1 1 0 0 1 0 1 0 1 1 1 1 0 0 0 0 1 1 1 1 0 0 0 0]; From 3705dfe0d55fefa2c2a940482e779fc9f351f23a Mon Sep 17 00:00:00 2001 From: drowe67 Date: Sat, 10 Dec 2022 09:39:30 +1030 Subject: [PATCH 06/52] fix ctest --- octave/ofdm_acquisition.m | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/octave/ofdm_acquisition.m b/octave/ofdm_acquisition.m index 46d8d05a4..b05bfb5a8 100644 --- a/octave/ofdm_acquisition.m +++ b/octave/ofdm_acquisition.m @@ -39,10 +39,10 @@ mark_space_SNR_offset = 10*log10(burst_len/padded_burst_len); SNRdB_setpoint = sim_in.SNR3kdB + mark_space_SNR_offset; %printf("SNR3kdB: %f Burst offset: %f\n", sim_in.SNR3kdB, mark_space_SNR_offset) + rx = channel_simulate(Fs, SNRdB_setpoint, sim_in.foff_Hz, sim_in.channel, tx); % experimental BPF if strcmp(sim_in.mode,"datac4") - rx = channel_simulate(Fs, SNRdB_setpoint, sim_in.foff_Hz, sim_in.channel, tx); rx = filter(fir1(100,[1400 1600]/4000),1,rx); l = length(rx); rx = [rx(50:l) zeros(1,50)]; end From 006c8228118e788f52babc77233a4b25b6c716d0 Mon Sep 17 00:00:00 2001 From: drowe67 Date: Sun, 11 Dec 2022 16:39:30 +1030 Subject: [PATCH 07/52] tweaks to support testing low rate FSK on MPP channels --- src/freedv_data_raw_rx.c | 37 ++++++++++++++++++++++++++++++++----- src/freedv_data_raw_tx.c | 4 ++-- 2 files changed, 34 insertions(+), 7 deletions(-) diff --git a/src/freedv_data_raw_rx.c b/src/freedv_data_raw_rx.c index ac1f22b4f..b36694d36 100644 --- a/src/freedv_data_raw_rx.c +++ b/src/freedv_data_raw_rx.c @@ -60,6 +60,8 @@ int main(int argc, char *argv[]) { int quiet = 0; int single_line_summary = 0; float snr_sum = 0.0; + int fsk_lower = 0, fsk_upper = 0; + int user_fsk_lower = 0, user_fsk_upper = 0; if (argc < 3) { helpmsg: @@ -75,7 +77,11 @@ int main(int argc, char *argv[]) { " -m 2|4 number of FSK tones\n" " --Fs FreqHz sample rate (default 8000)\n" " --Rs FreqHz symbol rate (default 100)\n" - " --mask shiftHz Use \"mask\" freq estimator (default is \"peak\" estimator)\n\n", argv[0]); + " --mask shiftHz Use \"mask\" freq estimator (default is \"peak\" estimator)\n\n" + " --shift FreqHz shift between tones (default 200)\n" + " --fsk_lower freq lower limit of freq estimator (default 0)\n" + " --fsk_upper freq upper limit of freq estimator (default Fs/2)\n" + "\n", argv[0]); fprintf(stderr, "example: %s --framesperburst 1 --testframes datac0 samples.s16 /dev/null\n\n", argv[0]); exit(1); @@ -89,13 +95,16 @@ int main(int argc, char *argv[]) { {"help", no_argument, 0, 'h'}, {"Fs", required_argument, 0, 'f'}, {"Rs", required_argument, 0, 'r'}, + {"shift", required_argument, 0, 's'}, {"vv", no_argument, 0, 'x'}, {"vvv", no_argument, 0, 'y'}, {"mask", required_argument, 0, 'k'}, - {"framesperburst", required_argument, 0, 's'}, + {"framesperburst", required_argument, 0, 'g'}, {"scatter", required_argument, 0, 'c'}, {"quiet", required_argument, 0, 'q'}, {"singleline", no_argument, 0, 'b'}, + {"fsk_lower", required_argument, 0, 'l'}, + {"fsk_upper", required_argument, 0, 'u'}, {0, 0, 0, 0} }; @@ -119,6 +128,14 @@ int main(int argc, char *argv[]) { case 'm': adv.M = atoi(optarg); break; + case 'l': + fsk_lower = atoi(optarg); + user_fsk_lower = 1; + break; + case 'u': + fsk_upper = atoi(optarg); + user_fsk_upper = 1; + break; case 'q': quiet = 1; break; @@ -126,6 +143,9 @@ int main(int argc, char *argv[]) { adv.Rs = atoi(optarg); break; case 's': + adv.tone_spacing = atoi(optarg); + break; + case 'g': framesperburst = atoi(optarg); break; case 't': @@ -177,12 +197,19 @@ int main(int argc, char *argv[]) { exit(1); } - if (mode != FREEDV_MODE_FSK_LDPC) - freedv = freedv_open(mode); - else { + if (mode == FREEDV_MODE_FSK_LDPC) { freedv = freedv_open_advanced(mode, &adv); struct FSK *fsk = freedv_get_fsk(freedv); fsk_set_freq_est_alg(fsk, mask); + + /* optionally set freq estimator limits */ + if (!user_fsk_lower) fsk_lower = 0; + if (!user_fsk_upper) fsk_upper = adv.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); + } + else { + freedv = freedv_open(mode); } assert(freedv != NULL); diff --git a/src/freedv_data_raw_tx.c b/src/freedv_data_raw_tx.c index a4b3ddd46..963b2dd48 100644 --- a/src/freedv_data_raw_tx.c +++ b/src/freedv_data_raw_tx.c @@ -230,8 +230,8 @@ int main(int argc, char *argv[]) { uint8_t bytes_in[bytes_per_modem_frame]; if (mode == FREEDV_MODE_FSK_LDPC) { - if (!quiet) fprintf(stderr, "Frequency: Fs: %4.1f kHz Rs: %4.1f kHz Tone1: %4.1f kHz Shift: %4.1f kHz M: %d \n", - (float)adv.Fs/1E3, (float)adv.Rs/1E3, (float)adv.first_tone/1E3, (float)adv.tone_spacing/1E3, adv.M); + if (!quiet) fprintf(stderr, "Frequency: Fs: %4.1f Hz Rs: %5.0f Hz Tone1: %5.0f Hz Shift: %5.0f Hz M: %d \n", + (float)adv.Fs, (float)adv.Rs, (float)adv.first_tone, (float)adv.tone_spacing, adv.M); if (adv.tone_spacing < adv.Rs) { fprintf(stderr, "Need shift: %d > Rs: %d\n", adv.tone_spacing, adv.Rs); From 6eee22fa35a2841c2115177fc8d7955dd12aefe3 Mon Sep 17 00:00:00 2001 From: drowe67 Date: Mon, 12 Dec 2022 06:55:56 +1030 Subject: [PATCH 08/52] ability to change LDPC code for FSK --- src/freedv_data_raw_rx.c | 67 ++++++++++++++++++++------------ src/freedv_data_raw_tx.c | 83 ++++++++++++++++++++++++---------------- 2 files changed, 92 insertions(+), 58 deletions(-) diff --git a/src/freedv_data_raw_rx.c b/src/freedv_data_raw_rx.c index b36694d36..96d66633e 100644 --- a/src/freedv_data_raw_rx.c +++ b/src/freedv_data_raw_rx.c @@ -38,6 +38,7 @@ #include "modem_stats.h" #include "octave.h" #include "fsk.h" +#include "ldpc_codes.h" /* other processes can end this program using signals */ @@ -49,7 +50,8 @@ void INThandler(int sig) { int main(int argc, char *argv[]) { FILE *fin, *fout; - struct freedv_advanced adv = {0,2,100,8000,1000,200, "H_256_512_4"}; + char codename[80] = "H_256_512_4"; + struct freedv_advanced adv = {0,2,100,8000,1000,200, codename}; struct freedv *freedv; int nin, nbytes, nbytes_out = 0, nframes_out = 0, buf = 0; int mode; @@ -63,30 +65,6 @@ int main(int argc, char *argv[]) { int fsk_lower = 0, fsk_upper = 0; int user_fsk_lower = 0, user_fsk_upper = 0; - if (argc < 3) { - helpmsg: - fprintf(stderr, "\nusage: %s [options] FSK_LDPC|DATAC0|DATAC1|DATAC3 InputModemSpeechFile BinaryDataFile\n" - " -v or --vv verbose options\n" - " --testframes count raw and coded errors in testframes sent by tx\n" - " --framesperburst N N frames per burst (default 1, must match Tx)\n" - " --scatter file write scatter diagram symbols to file (Octave text file format)\n" - " --singleline single line summary at end of test, used for logging\n" - " --quiet\n" - "\n" - "For FSK_LDPC only:\n\n" - " -m 2|4 number of FSK tones\n" - " --Fs FreqHz sample rate (default 8000)\n" - " --Rs FreqHz symbol rate (default 100)\n" - " --mask shiftHz Use \"mask\" freq estimator (default is \"peak\" estimator)\n\n" - " --shift FreqHz shift between tones (default 200)\n" - " --fsk_lower freq lower limit of freq estimator (default 0)\n" - " --fsk_upper freq upper limit of freq estimator (default Fs/2)\n" - "\n", argv[0]); - - fprintf(stderr, "example: %s --framesperburst 1 --testframes datac0 samples.s16 /dev/null\n\n", argv[0]); - exit(1); - } - int o = 0; int opt_idx = 0; while( o != -1 ){ @@ -105,6 +83,8 @@ int main(int argc, char *argv[]) { {"singleline", no_argument, 0, 'b'}, {"fsk_lower", required_argument, 0, 'l'}, {"fsk_upper", required_argument, 0, 'u'}, + {"code", required_argument, 0, 'o'}, + {"listcodes", no_argument, 0, 'i'}, {0, 0, 0, 0} }; @@ -160,6 +140,17 @@ int main(int argc, char *argv[]) { case 'y': verbose = 3; break; + case 'o': + if (ldpc_codes_find(optarg) == -1) { + fprintf(stderr, "%s not found, try --listcodes\n", optarg); + exit(1); + } + strcpy(codename, optarg); + break; + case 'i': + ldpc_codes_list(); + exit(0); + break; case 'h': case '?': goto helpmsg; @@ -168,6 +159,32 @@ int main(int argc, char *argv[]) { } int dx = optind; + if (argc < 3) { + helpmsg: + fprintf(stderr, "\nusage: %s [options] FSK_LDPC|DATAC0|DATAC1|DATAC3 InputModemSpeechFile BinaryDataFile\n" + " -v or --vv verbose options\n" + " --testframes count raw and coded errors in testframes sent by tx\n" + " --framesperburst N N frames per burst (default 1, must match Tx)\n" + " --scatter file write scatter diagram symbols to file (Octave text file format)\n" + " --singleline single line summary at end of test, used for logging\n" + " --quiet\n" + "\n" + "For FSK_LDPC only:\n\n" + " -m 2|4 number of FSK tones\n" + " --Fs FreqHz sample rate (default 8000)\n" + " --Rs FreqHz symbol rate (default 100)\n" + " --mask shiftHz Use \"mask\" freq estimator (default is \"peak\" estimator)\n\n" + " --shift FreqHz shift between tones (default 200)\n" + " --fsk_lower freq lower limit of freq estimator (default 0)\n" + " --fsk_upper freq upper limit of freq estimator (default Fs/2)\n" + " --code CodeName LDPC code (defaults (512,256)\n" + " --listcodes list available LDPC codes\n" + "\n", argv[0]); + + fprintf(stderr, "example: %s --framesperburst 1 --testframes datac0 samples.s16 /dev/null\n\n", argv[0]); + exit(1); + } + if( (argc - dx) < 3) { fprintf(stderr, "too few arguments.\n"); goto helpmsg; diff --git a/src/freedv_data_raw_tx.c b/src/freedv_data_raw_tx.c index 963b2dd48..b5eb11aae 100644 --- a/src/freedv_data_raw_tx.c +++ b/src/freedv_data_raw_tx.c @@ -37,6 +37,7 @@ #include "freedv_api.h" #include "fsk.h" #include "ofdm_internal.h" +#include "ldpc_codes.h" size_t send_preamble(struct freedv *freedv, FILE *fout, int use_complex, size_t n_mod_out); size_t send_modulated_data(struct freedv *freedv, FILE *fout, int use_complex, size_t n_mod_out, uint8_t bytes_in[]); @@ -46,7 +47,8 @@ void comp_to_short(short mod_out_short[], COMP mod_out_comp[], int n_mod_out); int main(int argc, char *argv[]) { FILE *fin, *fout; - struct freedv_advanced adv = {0,2,100,8000,1000,200, "H_256_512_4"}; + char codename[80] = "H_256_512_4"; + struct freedv_advanced adv = {0,2,100,8000,1000,200, codename}; struct freedv *freedv; int mode; int use_clip, use_txbpf, testframes, Ntestframes = 0; @@ -58,36 +60,6 @@ int main(int argc, char *argv[]) { int postdelay_ms = 0; uint8_t source_byte = 0; - if (argc < 4) { - helpmsg: - fprintf(stderr, "\nusage: %s [options] FSK_LDPC|DATAC0|DATAC1|DATAC3 InputBinaryDataFile OutputModemRawFile\n" - "\n" - " --testframes T send a total of T test frames (T should equal B*N)\n" - " --bursts B send B bursts of N testframes (default 1)\n" - " --framesperburst N burst mode, N frames per burst (default 1)\n" - " --delay ms testframe inter-burst delay in ms\n" - " --postdelay ms additional delay at end of run in ms\n" - " -c complex signed 16 bit output format (default real)\n" - " --clip 0|1 clipping for reduced PAPR\n" - " --txbpf 0|1 bandpass filter\n" - " --seq send packet sequence numbers (breaks testframe BER counting)\n" - " --source Byte insert a (non-zero) source address att byte[0]\n" - " --complexout complex sample output (default real)\n" - " --quiet\n" - "\n" - "For FSK_LDPC only:\n\n" - " -a amp maximum amplitude of FSK signal\n" - " -m 2|4 number of FSK tones\n" - " --Fs FreqHz sample rate (default 8000)\n" - " --Rs FreqHz symbol rate (default 100)\n" - " --tone1 FreqHz freq of first tone (default 1000)\n" - " --shift FreqHz shift between tones (default 200)\n\n" - , argv[0]); - fprintf(stderr, "example: $ %s --testframes 6 --bursts 3 --framesperburst 2 datac0 /dev/zero samples.s16\n", argv[0]); - fprintf(stderr, "example: $ %s -c --testframes 10 FSK_LDPC /dev/zero samples.iq16\n\n", argv[0]); - exit(1); - } - use_clip = -1; use_txbpf = -1; testframes = 0; int framesperburst = 1; int quiet = 0; @@ -113,11 +85,13 @@ int main(int argc, char *argv[]) { {"amp", required_argument, 0, 'a'}, {"quiet", no_argument, 0, 'q'}, {"complexout", no_argument, 0, 'c'}, + {"code", required_argument, 0, 'o'}, + {"listcodes", no_argument, 0, 'x'}, {0, 0, 0, 0} }; - o = getopt_long(argc,argv,"a:cdt:hb:l:e:f:g:r:1:s:m:qi:",long_opts,&opt_idx); - + o = getopt_long(argc,argv,"a:cdt:hb:l:e:f:g:r:1:s:m:qi:o:x",long_opts,&opt_idx); + switch(o) { case 'a': amp = atof(optarg)/2.0; @@ -173,6 +147,17 @@ int main(int argc, char *argv[]) { case 's': adv.tone_spacing = atoi(optarg); break; + case 'o': + if (ldpc_codes_find(optarg) == -1) { + fprintf(stderr, "%s not found, try --listcodes\n", optarg); + exit(1); + } + strcpy(codename, optarg); + break; + case 'x': + ldpc_codes_list(); + exit(0); + break; case 'h': case '?': goto helpmsg; @@ -181,6 +166,38 @@ int main(int argc, char *argv[]) { } int dx = optind; + if (argc < 4) { + helpmsg: + fprintf(stderr, "\nusage: %s [options] FSK_LDPC|DATAC0|DATAC1|DATAC3 InputBinaryDataFile OutputModemRawFile\n" + "\n" + " --testframes T send a total of T test frames (T should equal B*N)\n" + " --bursts B send B bursts of N testframes (default 1)\n" + " --framesperburst N burst mode, N frames per burst (default 1)\n" + " --delay ms testframe inter-burst delay in ms\n" + " --postdelay ms additional delay at end of run in ms\n" + " -c complex signed 16 bit output format (default real)\n" + " --clip 0|1 clipping for reduced PAPR\n" + " --txbpf 0|1 bandpass filter\n" + " --seq send packet sequence numbers (breaks testframe BER counting)\n" + " --source Byte insert a (non-zero) source address att byte[0]\n" + " --complexout complex sample output (default real)\n" + " --quiet\n" + "\n" + "For FSK_LDPC only:\n\n" + " -a amp maximum amplitude of FSK signal\n" + " -m 2|4 number of FSK tones\n" + " --Fs FreqHz sample rate (default 8000)\n" + " --Rs FreqHz symbol rate (default 100)\n" + " --tone1 FreqHz freq of first tone (default 1000)\n" + " --shift FreqHz shift between tones (default 200)\n\n" + " --code CodeName LDPC code (defaults (512,256)\n" + " --listcodes list available LDPC codes\n\n" + , argv[0]); + fprintf(stderr, "example: $ %s --testframes 6 --bursts 3 --framesperburst 2 datac0 /dev/zero samples.s16\n", argv[0]); + fprintf(stderr, "example: $ %s -c --testframes 10 FSK_LDPC /dev/zero samples.iq16\n\n", argv[0]); + exit(1); + } + if( (argc - dx) < 3) { fprintf(stderr, "too few arguments.\n"); goto helpmsg; From ae9c96482d6108068ba3f16138ca450b0d0c68ee Mon Sep 17 00:00:00 2001 From: drowe67 Date: Thu, 13 Apr 2023 12:29:46 +0930 Subject: [PATCH 09/52] trying rate 1/3 code --- doc/modem_codec_frame_design.ods | Bin 44543 -> 43647 bytes octave/ofdm_lib.m | 10 +++++----- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/doc/modem_codec_frame_design.ods b/doc/modem_codec_frame_design.ods index 560e62ee7aaf376c76e0abdceb7c381b7971d257..bba8bd8bb96483fe1d8808c56bf1f6d9bbb8a2f2 100644 GIT binary patch delta 38708 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 diff --git a/octave/ofdm_lib.m b/octave/ofdm_lib.m index 50ebdc653..4579acd82 100644 --- a/octave/ofdm_lib.m +++ b/octave/ofdm_lib.m @@ -387,10 +387,10 @@ config.state_machine = "data"; config.amp_scale = 300E3; config.clip_gain1 = 2.2; config.clip_gain2 = 0.8; elseif strcmp(mode,"datac4") - Ns=5; config.Np=23; Tcp = 0.006; Ts = 0.016; Nc = 3; config.data_mode = "streaming"; + Ns=5; config.Np=34; Tcp = 0.006; Ts = 0.016; Nc = 3; config.data_mode = "streaming"; config.edge_pilots = 0; - config.Ntxtbits = 0; config.Nuwbits = 40; config.bad_uw_errors = 10; - config.ftwindow_width = 80; config.timing_mx_thresh = 0.25; + config.Ntxtbits = 0; config.Nuwbits = 48; config.bad_uw_errors = 14; + config.ftwindow_width = 80; config.timing_mx_thresh = 0.3; config.tx_uw = zeros(1,config.Nuwbits); config.tx_uw(1:24) = [1 1 0 0 1 0 1 0 1 1 1 1 0 0 0 0 1 1 1 1 0 0 0 0]; config.tx_uw(end-24+1:end) = [1 1 0 0 1 0 1 0 1 1 1 1 0 0 0 0 1 1 1 1 0 0 0 0]; @@ -1735,8 +1735,8 @@ function test_assemble_disassemble(states) code_param = ldpc_init_user(H, modulation, mod_order, mapping); end if strcmp(mode, "datac4") - load H_256_512_4.mat - code_param = ldpc_init_user(H, modulation, mod_order, mapping); + load H_256_768_22.txt + code_param = ldpc_init_user(H_256_768_22, modulation, mod_order, mapping); end if strcmp(mode, "datac0") || strcmp(mode, "datac1") || strcmp(mode, "datac3") || strcmp(mode, "datac4") || strcmp(mode, "qam16c1") || strcmp(mode, "qam16c2") || strcmp(mode, "datac5") printf("ldpc_data_bits_per_frame = %d\n", code_param.ldpc_data_bits_per_frame); From 1fb0eba16ae8e9124fc1b0cb54e02af8f5cf8c0f Mon Sep 17 00:00:00 2001 From: drowe67 Date: Thu, 13 Apr 2023 13:59:45 +0930 Subject: [PATCH 10/52] trying rate 1/2 Wimax (1152,576) code --- octave/ofdm_lib.m | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/octave/ofdm_lib.m b/octave/ofdm_lib.m index 4579acd82..aa7c6cb1d 100644 --- a/octave/ofdm_lib.m +++ b/octave/ofdm_lib.m @@ -387,7 +387,7 @@ config.state_machine = "data"; config.amp_scale = 300E3; config.clip_gain1 = 2.2; config.clip_gain2 = 0.8; elseif strcmp(mode,"datac4") - Ns=5; config.Np=34; Tcp = 0.006; Ts = 0.016; Nc = 3; config.data_mode = "streaming"; + Ns=5; config.Np=50; Tcp = 0.006; Ts = 0.016; Nc = 3; config.data_mode = "streaming"; config.edge_pilots = 0; config.Ntxtbits = 0; config.Nuwbits = 48; config.bad_uw_errors = 14; config.ftwindow_width = 80; config.timing_mx_thresh = 0.3; @@ -1735,8 +1735,8 @@ function test_assemble_disassemble(states) code_param = ldpc_init_user(H, modulation, mod_order, mapping); end if strcmp(mode, "datac4") - load H_256_768_22.txt - code_param = ldpc_init_user(H_256_768_22, modulation, mod_order, mapping); + framesize = 576*2; rate = 0.5; + code_param = ldpc_init_builtin("wimax", rate, framesize, modulation, mod_order, mapping); end if strcmp(mode, "datac0") || strcmp(mode, "datac1") || strcmp(mode, "datac3") || strcmp(mode, "datac4") || strcmp(mode, "qam16c1") || strcmp(mode, "qam16c2") || strcmp(mode, "datac5") printf("ldpc_data_bits_per_frame = %d\n", code_param.ldpc_data_bits_per_frame); From f82b868981b81e2e409e6725c2f4207851f98d01 Mon Sep 17 00:00:00 2001 From: drowe67 Date: Thu, 13 Apr 2023 14:00:39 +0930 Subject: [PATCH 11/52] waveform used with rate 1/2 Wimax (1152,576) --- doc/modem_codec_frame_design.ods | Bin 43647 -> 43607 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/doc/modem_codec_frame_design.ods b/doc/modem_codec_frame_design.ods index bba8bd8bb96483fe1d8808c56bf1f6d9bbb8a2f2..a1d86aab92acbd2582f5e4c71ecf7a246e77dfb6 100644 GIT binary patch delta 14953 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 KH(T@%{Qm&I?Ua51 delta 15124 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

;U4Gi{yvWTQ~$~|O-UN)Gu+5~ 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 f2ncg$Cl5;}kAF1{7VfVe{q5`WR^dbG-?#q Date: Thu, 13 Apr 2023 18:54:38 +0930 Subject: [PATCH 12/52] first pass at datac13, shorter packet leads to decreased performance as expected --- doc/modem_codec_frame_design.ods | Bin 43607 -> 44271 bytes octave/ofdm_ldpc_rx.m | 2 +- octave/ofdm_lib.m | 23 +++++++++++++++++------ 3 files changed, 18 insertions(+), 7 deletions(-) diff --git a/doc/modem_codec_frame_design.ods b/doc/modem_codec_frame_design.ods index a1d86aab92acbd2582f5e4c71ecf7a246e77dfb6..1c26fd9a904cb10e7dc27979310cbe001e032cdf 100644 GIT binary patch delta 40274 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 ZsAoXvzlTgob-5ov`~(p#`cz-`{vWDMN=yI% delta 39404 zcmYhh19V_N&^KILTen-=wr!i+?bhDfy*0MBy|ry^ZQHi(umAUX-t&Gp=bq%;n@J|g zWb&KITrPtx&VeB)$$~?mgMh$*fb@{YA}B!pPbuCIlq8c8mR&D z|9id|0I@M~GGuVGv5r(7jhbUZX}`r#-b#B)EJ_^yfwEH#Lk1PLI%MQ3LSz(;XU6)* z?|#WJ21*^`)G{(ZpNWp#Bzwy5caEEnEC5?`>6awI-YW348Aa$n22gFH7nb6}>ftOK z2(@j2DY)gU0j}+hG7Zq5A�+Q%nfk-6BR-V$7z+5;9!h_}H1+?=}0$1fDwP*Fr0g zn=!GDn&a2>gzYfjQb!LPlXQmHPgYi4I8;!D;p2-%$;ixiH&!G*TNiPLZ}G;9zRzRV zp%pPCwd+Q}(BDsFm3>B5PuL>Wbar8L-HzI{sxH)~0BExC{~{xPW)LKx$8&Yt3k`oO z%IMEHAeJ`&r;^qO*_uz4uveB)3nB?>D2ZwxF-X}*musJfs*w}f*z9k)*8C)N@6uWJ zhT0)m8=c@q^1L{INH}3t@7Z9v$WBt68LGP8do6i;@iaO&O9eH6_ zbgAti1CU%oZaXy`P)dccI3#udC9%K&r_fINn_vu!rc7Qva!W&*!W>&p&(}tO@hZ92 z!Yq7KVtBI7rm|)5*+3~A!$M+1Tytq^V%^7FDHwRZXU{`LK|+6(vItt zraOx(+ATV`X+_j5rLbYdUyl`q&QoiqNd81;i8ETx?{#q+9wujk97lIyVYa#jMOmS~ z)hWFUU@#CZgc6pra|}8`8m!AkWSQVm1>mr zU#-e3iwt@82zl;nYo#1Em+hRqdmdlus|+qk;_x(nyfzh5W7%??S98Cm6P_Arcj%>| z>jXZpmpfbg!lPjNZK5m+(GA2m$8P#bwyC~V3T}et|RO)Y!nkOq)@c_mT`~ zQ(R-exDF(xGdOF(pxgTUQl0Nv5Vh_XfoX+%?H^^UyG0$Iz=Bn8b2Hdyg<7d#0-wFb z0|&F2LxPFf`3Y5(v(oT9>;}2kr13H!irX%$lcDh&myv_^>lD|^5lM+Vzj#c5X%gLw$#mU*iuaM5t#^rj>^fNFV^Yu?{*cP1GXutK&nMzn^hHAp>CVTR#9PteS= z{;BnaWE(xPKCmP8b|z4Ag1%0C^Y;9=_X+8}-&Z0T)rsdVDZc3%g~sUg!E_~?dQ2w$ zR_XAPN&kM+$5^y!F{4Pyx|(Ug1VcdePHQI7ts*0}5Ak*gn*z=Ry=4Iw1IQtqlB9fO zy^I*Nr0rhnT_;oea(^nM0(9?IS$v;2cbC@BgPIN>`)|DZA2`1L@b5y@KZC7&se38A zo;<-|#;SbxVEEi2l0F=B;E9*_{R$ide`Y~npkZ)>J3NGiX$QQDsc>k&P~5p(-#3W1OMa!JtH2KB-Zh}6YR1T*_t1`zFt zg*-T?9@0`%asn9(2)O&0&0~&}|4^^(h?#QY{bDig>5%<+ev>pgYCX;;h#qCW9x3Rx z9^1b&!*cWG45AV-O$A&H^?fQ=pkxVK`$BP+R2j&fVVKAkR$;zNvRv`Wt>?@d+5OU5 z3%q!PoEb&c+-A6}lEITj#z$-QT=oRxaMD4l(K2=iR>OCo`6{K{xBi`$wT6Ly2W(G7 z4mZUWM0gZ|$YAdk^+1&-Wsf6v@h;Xg;&l3!%5Jj0cZ5-OKPx0 zgBSRN$5nGTyXfHcoFgHW)_=O69i>z-tlVzwON`5#JK@ z+4(jBvC~_a>xCz-YX53Da(Sw1SXOj=RIdms(6x;Cc*pI%Qwn4OwaEJ z=>59}&-=&B%jRR}9h`r7V&WDbm{Cw>B?X^e$i=3ixA(Kpr%|PjFZfH~k@ta^fnIUG|_>Q-H)Rt=cbcHC6h6u3#DF zqt6!Xd@xwfc|d;m^vlX9++(+Pn?1fKb}^q;?>jU1YFa&58kMUVW_@(yD@y0A_c%lgIK#|yD*2J%qxDC)gYBTto z`6wHOQELrtQ!(~PJI%!1V5X@vphsN7)t`ydm-U^Cw5RoP{)=9a)#A00Zr{C-qw9So z(}y!-WcGfpevBqtSJ-j{HVdM*9cJ)>pQz1vQuvnw{i5z28oXJ%u!QV#XFRjKS+}s+ z-(=3bp1CG2e;a9nEiPK(@OJioWDL8Z7Mq+o?o{l>duF)%l5K$T3{yFZMUi=^nIuQK z$wiU1j(TB16gqu`zvlm{+QATfTaEs;CMeeO%=jNV*yIMa-h>7LQ8D=s9bo=HkQu2_ zrTp7`%K!vq%OL(1gBkd$06Giv1tLI(hMu=UK)@cAUounb7^@DFnh zNwx{eagNCIj4Sa@uJJR855xKnc%}MVrG+}@hS=nVJC($F)~5ksVWB}034h|!k|Tps zN0{#^HQ7h zBU*|Q^Yila3rqf%l$8|Zm6!Z2D=Yh3UjMhct-QLStgfxT{BK)bXZ11h@ooyUlE*;))Tz?)e4aBcte+NFU)(;O4_s;GP zu5Na3J`SEfPp|J!?%&Q{J|50@AFmGYug~6Z_FnH!Kc5diUQX}s?rtBRZ{I#%9&Vl< zpWa{ZK0ZFag!1$Avlfl39|VL5L|RN(&28n(+fxsHartwZb_ZFBl&ZPV{9E;3h;ROj zKTxlVG~^+SHnzfN$N)FeG)tv#WsDnXYGUG`>EX@b5jh_#X&ht2{A5?(-?z(HG0BVA!ywCMBH!wMw%F5lcYRUP-D@!9> zjt`VbXk?GtpvJBaV1CBlWUQ1APEv2%JDJC=ooe-a;V6qXL)h3q4z|}MI7;g$5*ZqP z<;rnV&q+^rby{{+Gt#7giT`#`Mz%LaD!iO2MULK$8j5skiQ&LrMdHgJNN2P;K~g&F z^{HJO;Nz{u0DdoF+Mjox0Ajw1gW2JVt#$2|QPy;Rl0Kc1F#@QDXI zSCcBTxPohce(1Fv_}MJ0Zj5EJRrrKMcf{;GLy4l_!j895Vh>!Ri`DNhUWKzm_(c+x zviOv_N^yFWTT=7oNA-&?1P79-JL*nEBe1n+NHb^VkOx!G9pa~0!1N@^SNkQ1`j`6Q z|6ujx1J*U);O}(k;VB4$4(QPk&^R{&lb+*~e+A7+tB#cPW*jryQacY?9d|tVT*IZX z{6IiRbp?CJu_0Qm{B=$Rz2KGj7HGpG1NmlL7r=fIjpj(;55r`2yY?p z7V*aBoyj63<7VHcTQ29wK!U@07}n6Vf3yOke2{!vRm7r|J*?#o@lKSqcP>8`V~&L9 zfWzllYP2KH_m2~iPkiDOLQw;hk^&)E$PIH_-8X7jBl#)XhGt8T8)bB3YrjCIF6+({ z9OH@J)f=2VmGM;_jd0(Y!eeAzVLXL@kcjdGM=C{=;22q#>Hqk{v8nNZ&d zW>Y7#eA;FRt2%5^-kIq^(RpKW#jQJp0K17(rQF_pnY>QlouR6~`MtyNO9!fZvL0T5 zR`j71;6F^GBUP2QWopK$yd zjJLFqKoS?UZ}fp=M(VRrX9q{pJ~D^0thCB*u+p3uTfas#it?nY#LU$eof>Zf(G4;6 z3B=7o7Ev@IgcB4@Y*HN2A9n}`AbD)Es5LNp7vujSTEUj0G|fCA^VZUHqb}Phhd2~3 z66;H~==$Tn6&9IyzzvP@gQx@b!FNhB@U0+8Dt)4sKK-il@>jGuYDK8vc%jwJ;NXuF zNt(m9d`x~bSrRh^e0%F|xD5oeK30m%(6#mgI3H(r;JqkA1TfcTGam&1xF zRjAL6N#Zs;p0L|Ah0eFL(>TFfNh@R7g@IQI<;G^q;2URa zJpvSYXyz0115P)A z*Sx^}V~^#j4AtUR0?Py5&-n?gqT@HX2Q17MWs+C7eS7ot9EXJo;VnwUw#Kf1(_!9n zlI~k5c=~(&n;OO{@NcDa0t!t_w=Zf>?ND9TVDZGffusJm_pS7r`5VDNlEq=5zIVFy zXnPY?R^1Ve%}Pmz!s)@qE@x9Gw-J-01IZeW6xegla-mqY#16_n3?7VHTMm3xH^=e4 zYIE(-dZXOrabP2=;@VNX4D-*46n~RE{%#a-TmlaFjHu%Sz}oV#Q4Zkm@P<*LBM^>M z+M@cNYU8xRqEkkRPpvT>$<>^`q@DfwyN{0E%Ia`dkB`#1E-keksg z|9Nb@K4vj?J9hp>&p`X-pH2gf;?h2AsWsW>%%Ej}gSn@L#)GX+}#M7<0cOPEj zZQqMp#P2Nd0YTkUVYQm3i!9_E&>3Fe3BT4YcVZ9Do%*UwMIQTlA-m+=8OX6nCf#7K zm4m!xotSfoZLHzLqYe^NRJm@!R(ods>TS{EcAnOimW?6=1Kzp>zBp3eX)VG+9W4d>Cr0nLr z_w6cp8zdoKQ_cd&wiT0k9$qprkhWg-v8!#qirjzH!d(()pk%9z1i@Ia}0?;msl9-b1NvwPr2yi5k4|Rxz9DS-+H~<#3;HAN&K4FK35Gir0Kmq%Hx< ze(4Mi;9l2KuSU{Z>Y(UFis&OF&=v?zq)JVDkBK06=*Q7Ml?}g|bAqZt|6HEH@rv_~ z&=1fR=&Sdb&Hb_S(jZ%NROLwcC-n#6L<3`4dK{*;$70qMI;9lY%| zf4hSEG3VLH$ugvFtxICdjr6IbV*PcayUmIg(Dqy!eli}KFk^KXnX*^*A&{cD-GhWi z=j~1RqD|%j%y*1&DgPP&HVMt~Y#rqKQp)4?J4P?@Lu>FO=T@74;>>GY zFevpIS-%Pb$AOs3g^GY#+I?rD@ulgnp4&W7;a9sahqy*6CdlPFhP z(~)#o*QPAanG>Um@Wq0c9U`7{1wXc?~dI&*I$`wO28DaXuJu|CJlmy^@L5o9fN zNzs~hs@;_WnAYny*#v756mFrui3_&iNr0IoLD0?+#SqNhM$?5Ga0-G~zaXqtKfE6ssH+3H|*9gNhf8+04p{1)Zm99>7n-l`pc^ z%TF9hw?7(GIXc0WaDCk?{%+zi5fHP#babhjCc?rP=ipnTYFMs04Z0qM8D56y5J59a zISX%ET8Pm;XW%C1)8Y{aNbm+eAi};+RgZGs6=C6Dy*S^H_mANC7l~wEBoyaLFj=vg zBY~D5QF=yrdFfbW)~Luy$n$q|TiVYhX&aSR-Oj}@1qwW%n^+TPsI!rfKI@uY8TePQ zGWt!bV(@zeVOjqUUI3jtKCl=~MLx{s=l;8$aiTR`urAeD$R~aWU^{OKLM#@Nf4D%) zx%m*3;~`4%JTv}n0O_Rz(9?8$}$fspA^BrMJ%Lj4#r9 z6(0viPpEJz@2d4W8Y-3X&j0zr?p3esh)Pr;2!E8jm|19xejI=RYIhaYX*x57!WjZ} zOd!;7Ap3_!yb)0kXbLZf40gb`ohhV7M=<$zGq)&4<+EUvF#)YyIp6G#;B0ovE-{W& z^7yjI?Vm{y{ZirqAaEo3OcYek7F4qA+_%O;iV|}tO_&eQAAkdiGV|OR@l3XKmNxj(X z0fMb2Ti>lSdX)sU)L-Pke>ZuOHz6=8VEtS6L5|3`+$Ah1+@&Y%DLO!#c`Z$dI7#5l zSVaUaeiiKpz*{Z>qGLiN>ZEdsKPUD-%!Pl+AXB0TuClNxf)U$S>w z9{%NOOfwTr67K7>zk6g8CePJmp%{5*(OaCFJs{|3Rt!q|B#}*EJRw9Ip%*UYo{pEI zL$c3JO9=bO>VkJ*2*HT@PO6q#Ez)ou%%N)Bcm{qtv~~y{0#n=Y3;&*3EH(8}W`0Im zxpfhM6!;;bJE6=uk4S*~+@AHaPg*-z?2OZ5js$lYfN2nMCKdLSdR27GPKd`Of(5FXOlli)?Xpue=YrNNG-#UYriJ4=lILfS zZq6p4)!@#sKJo;1Q66Oij;VuaTOLUhIQJfd>Wm?iM=BV{80~^9(Cnk~4(-mT)Ituh zSW>?K-a`E@a6?|ZV+?v>U6A~RKc?po=!1SAK3c!UG7GjUb*?;zckXC@?ZUdI*!Rs_ zw+JpCI7D1;VE0<+Y(i0ROndj0GbPJQp>q6#=AV8zEX5EoGH!E}SXol(vTA4ko$(m) z#l!`Zm@Y|-t`X9Q+a}35J)nNK;unxoo}{y4ql@~N@mX3dJQ4FcMC{qeR!aK#Jzg2I ziQu7LT@wTIlOQ-8E*t>%K{Wz+LC_Nt^Zs)&5qS{f2|670>)SRAEN(5@_&iMg@G@c|3`HkMrGFJsOxvRp{y`1Sg;sfheE`1 z{yyQ_3^7OBFr&<{QRTagKLTrfbnBP-tfdtA^yEsgXc$=w0!oU`)F#Odo8v$<960iP zLF)Q1wP+|NGlqBAh7ZliZv?hYWo=+rcJZz3V4Q$J8cft(b_gqmALy|enNLa%<+)1& zGh3vpA{||}dVudq6yujgGCK`j?K%DXse_NDJVIJ(A0O&CE56gbBz{jmMzl*2!}Q0& zo##DXl#jEGYcoUmZr6_Hw~N_m${10&T+kdE`pj{)f10y}<+s_pp2uQkoeyq@r->hL zCsTsT`|dsHe{MMDBmlRloQ)pge0^em&X>3Oo)};m6}fmqo;@%AT zxijzzlhR;8%}0-z@kV;G(fJ2Ed9);hIU8QMVJ2g5>d>!XPBa`ytL9KmBBtp_uIWU( zr%2=wa|jP*Tz-;tB8pXfwn#WfxFb*^^Rv%8zm@%S4t$B*M-fw){X|}DM&aD?sxu+7 zr%~NH!`+APS_K+y7}5TX>UT&}Me$L52)s~vp>!Z4Rf{=18+#1<@2wIMXkC4KFGX;` zVr1BJ>>8n$%r%vDVmW}-%2+Dye%@lWUU;S6|CY06o5jUy2q&E_k)VVW-)Bkou2G}^ z(HF$XLzk{J60lr5%(5A((nCD@vg1reMQdw!ygKX4285t; z_8y!a#C2uhdhxBOJ1@8LkoycW6%-|ZbBG>I5npwcNQA0;CGQLB+Quf&Uo^08eoH)# z!j0(X%CV$cELi?kPh<`BYY5KwGK?FncQ~OCK~Pl+W1D(KzL1`3??(BzUl=)^jlc`l z1`Z&qj`T10@uIPaAk0=$QEl3c4wBbL=V#S}uu3>h{L0ZFbfg}_nTXw+Nq)&4@E-Q6 z1@~tPXB$MK|wLi z`fTX+Fgt146dt!@vW&9J$vzqCfjeIWfd%L|gOuws?2CSDtgGd=f(bi8ZSFWo2|qI= zgeYWjO}`rBOVe~XmE>&bJSSU~=O+NX=MNe?BqKQi+{RRY#`7b}zwK9D%Hg8!TuiCu zb|8FMA|oTW9cy89jZII835iSnM#-rF{}Ub)gGAWxhP+5l7t}5DB8~Ty%%`rbP7NsX z_9-Dfv_c-LeTpQ!|EQvVFV()ret2U!c}@51(iuO!+msn+dGihXMuRAiZtcOV@QK_3 zim}Hi$C`cWUzfl$H$$w~Z|#m*vDEt5_%-^*vFVBhgiLHy)E#e}+R)VuX_ZF%FPyt0 zoS!SgX;OA-UhH_S%^OD6BZHp43D`F7CzguG=Q%MarrD=9v|=?P+*+$CHB!@;a29l> zqge<`zwus5FvQ&^vfG8N!BXiEhRNI|mgULRDZ>Ij=vCb+nbIClG5kd+w6-VnvLJBL z*JNMPSYuKkYj-_JW~XI!41Wep*LMD|B22s)Qo_WbBMhfsbmgrAP##xw^KE*Dr7mD^ z3p*SF%&1x3KP(AFTTD~XYQ=bU)|kDs_%RLY8?JcH?MHLPpf^47(QYDp%%!MDsc0cJ zw2f=sez4|m{~eFo5bQmm^Z8mYZe=AUFqE?^dvyzlV;*vgOorJBxAWFU1j}`X(R6$- zDeU&%TAIR?_&@hRRA)D)cFogq3OxEx`dw-UF#y$EsxbOR&T(Yv_EyJfaC_oSNX~k- z7D{yn%$g$tF!+Sbz$dXu625@wZAPosW+h9tF=g=-T>R{XC6NBeno?!x(?8qp*j5flR-WChREi&v@YU=Am8TQC6O830f_jLF zb_gg=4^3gP@zE{{qmESN)SHs)(vjuVEM4Xk2#F9(6N##~WT9o7wJSW1#)No&_?CbZ z4lIxDyec-NtnKH7;C~-b84##Lxg}pXQT)zc#8|u6)ax#@@(tz6%5wLv%n-U@e3atE z#p(zVuNodmD}yK&*4!Xw=fptML|TD_l~P`W_Xal^*a3R9-uz|nQP3@!7Yo-DVM!#0 zsEs(eL|2qnUNZ#_g+O`oF&VBB>W934XzEuw(^)!kiVSA+L)HN}{5-zEnw z>-Bnzty8brQ%aeH+MKfbq~>Q1hrtV!#x~qdpzFL5n9Ew857Ee zH@YDl)a3N0LKQ^&7No)(Yxy*&mQIpCr(BkDXsoJw0&__07}hlBn4Tc1)>(#%CZG1( zw7ir}uN|)lo;p(VZS#8Tw0uLuHj>M_H; zDnkJWbcAbTY@COm!N#M|M_W7w`Wu|q&&_AtBGpWo0Iu1!INWG+Uux-%&iE6g;Af&J zghJb3)K$~kg!(FTBy0*=Q}o>9O@s zG!%|vdYkp%r1Q(SYbbTKJS+3;YLnFd&qv@jozs@1?kSucQ*gA#T%D~msO6_JcVUDL z&hHeD#5o7S4(hHnQf*`0T#IS3kMaeBx-i{~A8AFab0> zj$)4MmZm9g$V0;qk`JRej-Cv3H8xG7HhFI(leUk)BR65TZGWlwsNNjxL|R0@(263$ zNa2g^LC5^%5<+KRhn_rXgOYGd*$ia3AlvMMaCH|x$zHT|eN<~zz9Yhzg&--cj3O14 zD|2t-uWLqT%+GXNZLjoV&wPbeQUHuh?p)qtjgVQ_m=SZ6ARO81@zYZKzP%CV=HDf0 z3HN470G?N-fP15)9O+k}Qcu6dH;G-vF*T*mbo#jG2o5G@%&u|1_$|5*!-*Zj0HVR- zT0C`CIB5pwWzgy#oXhBGlc7#Q3rzn_)am)ta5(*&0vv+JH@WBRKSthr@3zs?h|7!H;z zB0?kc;$1CnJrQnKLLn3+TXsdBWdPClZ)DE=YQ6#wuCS>x@{uWJ)b!mduHo}VSfw{)s=Ep^=}aS+tfAk?=I zR8ju$@d&$7|L`fQ>XwbXO0!mL6-#?wvC&D-FEat^2~O-Jjt6bs#y|abhjg7p^mOwl zMsWVYj^g;xJu1qQo>b$h6SXCFp`Z5Q7xy#cd-c;MM>D}}H_8_f9{J|*uwZVzyzc_-f=XEY zQm_Eshoww=07ylvD4+?C@j@$CQdH47ndikBzPY>^^vWbL9y8ltLnZL@BiQw) zoU++el!AEX%#7}MH3^07vS7ytTf*tZ*e`(iL4{7>arDSjZ&O5f-~t6sBbMBIiP5!Z zM>Sr-(cJe>to+>HbE*?#9P?}rVludgEnNy9_%HLjruuDk$$6j*H%GydPmx~l%M;M1 z3F33QY-aN{cmtKW>!8!(Vl>N&;&=#p@J~gww_uSC+^rU8|5K z_|M;A4~!Yx^==KFRS!Pvbx%{ZCJZzuYRfbyVn#s-JT0{DMVZGJQ{erNpTb>ZnUlY+ z?N7ye-U>Kz&a;_|P*h0s1=UTLWZdznR*kNOk!r9iFr4WuVK5sm^3uw8S|F7Fe->6M z)uF%S#^ro11L1xFw7op&tRRu2YP*$wv;mQWPb^YJ zbz9EC*V$u?RVk9LbX>uIJ2;bjx}+3DPwUWPOMjdDgA@Cy{@MEX<)d^T^@=VYR~S>9 zwydpOQW9;{C79#XAfZnJWci6(ZX{1LCKQf%{fbl)UAqf8VQ7eJBnLgUt zt*9G7FTe8Vr%~&t7A&#_v!8MyJ7;Z1=#(nkM;>;u5(5077?K$GVz1MQ)>^K*x3+Wmt>TWQ8sUELoXRDXS$*hY#g+3c1z8R-SJV-t`|c-&rz=`NE#G>T zft0RJ=v5ZzK0$PDE-!2F!aN!U_astw{>3gY+TpF;@WpLXq8?}{LM(lkpY%P&++ML6 zftc&UzD=(+sYDW+8aZB2R(Fo-vzwV)EkR6}SkN(E0}-ink#nL+ouE5jL_ONRn-5n0 z_r2RTf8W_d9&%1`Zqtgn`vc=FaeF>K=GKBpFwbz2Dx`&b-Z+zw|eF6uqRy^WNiQ225Ld2ZE8exh_$CvUneTAeC>NBQnWluM381@i?)8tR-wi*`{{UlbHiQ?%ba`g;4=sWC; z`l`cxq@sB;hg;pn|lPi z@=^)ux)WpWvCq?C14sEm%&e0i@PRNu7y5JvSa{RKU6+5HuCq}zy5TFD$OVamaW|g+ z>7n}mqf1@I<2%EHUP6x@4SSB0w}ti{bXwcL{)Yz{e@LgGWjMSQBNkMP?#R^GaeXxPLniTD&i@}Gh|dC#?5!vkBbPm8h64uly`V`fkjs13IvSKWS7?89d) z(TnE?!_c!1{>wghy(uEiJz2H)?N$*IWvtY~h=8E26_%jT@ES|@* zWxN(_aZXmaW4wK2Yp^83mKrSsC~|w{O=GN7X-_)W#vKR-UYv2D(eivP6KriMd=>h~ zhW0%%;km^qbq>2O2^Q<7wM>6ejuWi{_5yOEX;>L48na%uNm9>k;+fg!Vb+kh^RbNw zf&u!HCp-kGH{*7kFWICj67-K;^{cg=Mv~@O>}Mo?2GZKZcrN z8rFZUOVcb*IrsH|DsZ)-TM(@kol``JXVNoajb*eB;aIvhLAaEPw3ya(Fw&mb<}9 z_dP$^PYFYTSC|oe4dBadHxsYiNUgMH5(H&%fO(7%3Tj372Rj%pnJJR<1_QQZa zmhJk>2Qm&|x0X4?NwR3|^`7Tbxe_U_fnrhptb{jA>K%OYN$}2FXGhXHJ1$JN zr6`J68Pl;*83rq|lB%y#CU1h|74z;%eXx?qT%2|`-Wk*#vIzHT_HKOay>j=x7qBXx zl(#=XkJHcd4qzpn)nyC$fDU``T@+IrI)vl-fW`sr(3x~`&dm}o^Mff!6SQ5@iKm``qOC^1i zu*jzbIw6nbfxaPpjy}pcUFXJZk~!fI)+ebV`fT#sgZ7gP)f0z66Cy0=b6>98|9E^> zZ2ouU^XOaA0utvo^-+%bgLo&&~{fWFM zd;{-8Hn$@5GHF1`8LPIDJ%2|zhl{qi6R%IhZ0f;n6Kh*~u7Y`har&kWq!;)h2@AJ` zt7w;EUn2JmQ&R!RHgIs|f9M~<66oWXT*&ihgD89^VKXm@saC6>FtyFJQFR5@Pypt> zn65TW3rM1YQ6nkeNQ#e?eHSoDx!)6MzCI)-E(F2-j4^Z1bhFb7$2>-r`b~~YD?iuO zMz6EDe{9I0b(Kv$(@BnEp=ZgZW5Gp;&F5XDcIWJS(A z9qMQNGEVerM|M{t0}NkBGTk7xGzI&k8V zC;^bq?B+3xYD$Po;#t$Mp%_K^!@`qxt~5XJPb8qksMr#1E0z3+JAx|DC?5#hjFPr> zKYC*roqApu6g%>oyv9afb%_AA4G2|EDM8y=YtJT6t$35K{!Nh|57D+Rna3s|(x-M~ zG|vCGg5txui9zIWay0iA3K{t(8L)hfF)(dh^IPE_8tnziifUBwgm^ZD!w_$g$E)Av zk=YeQ3;21!n)rr&hP=${z5t{>9ZWqVrBAtoI_yn7r{$IE{#KrEQj)+FjJ&>qpEkO3 zs*eaNGVuoP#zShg{8!0Q*f3^}l(u=?<0H}7WUbk+x$_xACZbtFCYqp34qSsLnl3O> zT79xl-dA$xvrBfm6}5R*unb%tskf;XTiqD5#9Xl5{a0zPOCuAV9D$K4Jh+}p3IVgb z^RLNE7Cp3bX0*oPfG}}UxFb#wG!#sN?iTHT)BjC`y1U->95abaqbZqaie>1(S~jlR z`Sf_AMHMw5FNVW@O==?lRzNqjfyeVn1D^?~!~LI^)9~nRWoSeDcWzt zE?Qn}++qDy^@BUNDc-SzXIQ4zYvoz(7t$K z9m(j&0_e2gbk6O=p8I|(4(zB#zsga5ne{0A;plbQ`CY-xuh(>@21gOgf*CW}t$N`p z-mJZLXP{raE*d%Y@7y|fX;VdBw&JrFchlpGPcXwZwI5;|<1b+ldyW z5bEF^)~q^Eh6{$)JdGty8xcuNF(9p6D~7cK$VdV3DwVn#t(b#7Deq16efDF_uU~P~ zQx9yIwV&XBcKJ*bDzx74Ip{v1plLC)R~*vnrDZ=VFN_{0b;5U#SV)b74dTNPfEQ%y zsM{q^!GRqkC;m4l7^CY$o$4n6E6T4q9knMb5qSh#cN%MdO!3a=Hr=F)V$EQFWBdeS zzQ%%OLW|iY_UoECDeF;azRVc2tKIz;i{2{PK?I z@D|MBnus?YRTqC$Z9DiL6t5~1EeZUOLkV?6U*)B6F7t6E@V%PE>Y@uP*K08G+Y_sc zR`gh2&OsMsdIHZ|01?tJ+!xFV;V9%#N?FM7o5cPdn!XW=nFDq zi|-F zm+Aa3>|+HfDa0%g`(R2i9UO7?C>ul7aNftKaorDU?y7}p*l0z)@n0M&d3TafFG=o- zfy(1CVq{BQhotPbYP2 zyJu};YP-kWt}bxaiTeLAqLOWlfK#RiH|UB~^Y%IfwtcD=6OtOI?L~)^dh<Ac$%g zlP8wgl> zNS?ZHRx#g~=@O$~xPih?vs+)%m)MfMO)WHam^ML%8m@LzdeXzXeA4*bCs#MgB;&3) zI^Pr)S3=`1QZ_r`NN+yF`Ab`o>yx4A;_D)@_x#22>izqfK~;jwWe>O!u+GD|g>xWc z-13AjbX^>I10R-ho>TFB%*-me6T>D7`Y84W57}x|J(@kO=p^aiFtxaF3uDe&Zq8fr zNWk@R$wL5@%wBs_iNU>cf>m%!OAGgSn~lj|{p(}ayLyK)`nHGlw-VofJU>U@!Li9j zS`ioA;k?oIb>h@KsExMF)2q&Jk1K)MGB|;&Q?umz^E5|;?Nx4>s4pCD#k6r=eu8^* zJlh$d_-G_NIvEj+{zv0{6cNL8B5S^-<$)B16B_rIt>~B1>WYj{vy;@I2P*#cLAydY#T1)v956<*4XLtw=(Sc`~koA2wpH*bx`{-Jqg?~?+Jx0GUkXk*bbl|H0y zqKd{@t_$F6A)6Lmy|Gsq9rEIFF2wj+8y{@nYy}tM(in-#_i_I^z^t(y0&3dlIzmS3 zDo*KOlw8gVdVW>E=}|sm*j`{ufB5Nck@qcxfne;(NzYb(aYC0jCteX4FmwpzrKsRn zJdjXSvX9;tG(LY?UJ1}P-k`TEIW85qavoi>X|CiBYeG&2yZxKuowV7AoVON7(-Cg9 zg8J2H5`8T1^V%gau&}Ds?s3tnAi!^AwX=|EtrGWsGVp?od&xB6W1~j=*9U?6*47k# zniNY6e}Ay)%tSssz~wryku%qff#qJV@yMsGO2Irb09oKzgg2V(>#9;*d8Q7FhjMcP zD6rwH)c-K%jYP`pwf4JD&xO;y>qs=!F3PEw|35xSMSy1n-#a7abKCm)W7Ej8leS6P zJJG*Z?P4s8%YJ7sx;)rC?>s%a@TG0}vGk!03Kd?9RhOd%b0z2B@n8R1zTT`(ZhO$0 zLadc?tv8P5E$>D93aHb^Y0ft(Ar@&S;p)_SgG*{Es&sb*(1&8&Tw@FxY(kjH$TrjjqV-C^wnkHNo}3N?JbMFz!{E zsz^n6V}QI8nA>YjhO9Bx)-h)e6{pK?UTLWJ6dAwV#Vbl-Kla!BLJu#(^DT7{H8m~T zsR<+7nKJ=iir}aZKYz!eCQQ2oJ*I27m%ZOR5rv@6N0*FV!8|v zNVDO8Y&+{VCNunq?Oj4%d9SOETfT~v@7Vpx0HnJPn94HEvquDDcc8Oc z$43uw+y~f=->v@(ZlYe*=WRQ-LtjIUW#dfz`S^><2(PG2w2f|!tH!hTGp_H)i2gLm z8%tU))OU$?D}=#nPaa*aJIG6<-YJZvma>lOnu=VKO;uU+YI0n1Pe?^WuzS!y?^MvJ zuN``GG7&2mxbmRBfGJ{4%j7wgSp#^RGe3e{;;*WH1bo{;2eT zUmIgyU-F6-IYFGP>3&_44a`$(T7G0knOt_*L?liC0KkWCux5-}l z0^R~Lj;z$DWDgYyE+!}m;*9-jX8fZ52dLhbWLTTHjltOFoVM4+yrR^&yoIN>Q*(MH^PGESAg%9(6v zT1t>WVtzmEg?`_*ICYLzf|0S)EPcHz)WFR~{>LT-0@Gyd_wcD`Dz=mn@pVYiRKc6t zfS*VoL!z5Ya^+UuX0N&~QN-Bfz2HRXg7xK6khcb@R0cN6M8#)%%-O?efr`_=?Vh^< zf}SYmwt&Ysm}u7GB$uwJ@S2kX2S7Lzz7O&1{=-kAA_z4c*Hnd4C?vbK}q&=QyYf^cI(Ht4-ql$oCrv65rC##=~VP} zDMCZU-HfN^1Pc^>a7VFAeuF7&r(31OQsA69(wRaPYPk6OV=AsNUx~wx8L5Lq=(;8P z$V7wbKxX*WbNBZVPm2aZ)ujvFea?MmHaH?nl4?A~_csdRE15T&mB?mSk)vo?@&dWf zEndD{qcm9zrNa9Qw2IYI-he1W!Y#-3v}vE8xwKWXg^`asE2vZ zpEPMSEh{^pKc6N9A*O5kO27NSCk7FcciVYTCyit#xH6i=vvmJC1)w7UqR_3k-b(kY zXL?5^A_QAHyyBtgbN1`XAb8f(yI?-K%O>GL3jBJ=cdnQ`9f!W1Ewg!l3xSsX16J4N z5^@5=ZI(`@oLJ)*U)1LaKU#6=y#kuYWBt3KBMlErU_V%jzoL*(Ka7;}^8&P7U6}!* zySBpMfJWM;7zp@9Mwc zKAvwcDP^{PR;=hchx>B$di+s~7{!}5848eYAa|H6lM3jb71z*tOh6n%O`oL)(CvhLC`f>mYx46whhS) zoQxt6!~V^7*%~9R;O$P~?(y3BiR)qJ78?o^A|BHU@;-Fn!s0wWvY%#;YDETgZW5SR z5%2S;yPSY7@!xk;-6v~3yT=YBpf;F*{fT0L@5;daxTzBXP(BkrfSI=VEpecfcd>)R zRB+B^N~Y@Nz$aPq2s0o3NN^Ot+*Z)%omdcM)4uA>HirlNL9>15!kAB&0)b&iGHi&C z^6*YY(l?@*SL}Mo1WwErbpyn>nWZyAm3pkYYEwJ748aEJt}rD0-(LhQ;b+P4F|H3E zZZLtW?D(22y~1U~LX6IL_Sy^Gn}tMYx^J>7e2bY6!Qr{XM76bq`Rl|nuc#7gLv7aR zwHV|ygFBW8h%N-LhnjZUesB&4h$Km`6K{9dQigu(#0*@Ty8D|by@pMgl$nSSo`erM zQLJYT6ovhWe@&AAxR3ZNcTJ5`^H+u}13gfIA;DQCrOQfz%iPGq;pKR?z->1JtiVxN zy@1;~2|L4H7?lX#di@K0Qi{QwRe)(SLLz;GP-p*6R*^ii{X3nV#yNX1VH;*DZhNO` z$7C9Jz|!)q{BO*@fO}JzfwVW(@A^mO02M92y7U#7myn?yG5DA*y<5nkuYRd@9q@!p znLEHgV)#SbuYv|)+tb0L_Jcr-V*nY8wx9CO-ah+Y?K9ssx7oywWf>{RcCEU<|d* z$g`E2;@aW!Sa6iUPd@4Nv36aHdhEN^C~91Zk~+rHSY(RuUso4E0EphD!Pk~`Q`ifS z`|QaWECJGfR(dFL>)YX0=$sf71l;>}ERWj*R(KUspQB`n)T~Tgj^|xEF3Imd1j6U( z&GJr0{>ocg?C&SuXKjC%(kwZ5bwNLJ?92so*34vif&?wQC`+i35(C zToDM{g)7q&>EkR=*?7|PI>>qUfQ*8H33$KuxgPW+duajIb})9wZ7d!K2Bu%jo4$K3 z?jX3pyvByW<%nRqkWeVO>SIZQ{QcQ4thH?+jp_!5xlpHt#bDhBw^|{o{?s zjLyJQ`k)q|M6|NB5z0+Y3fqt9 z5t81BftC~L5*S|pzy?eKo!7250mong5lgU$ww93ko^zmd7MKiOd8{UbzX`vi`8*8JvhqK1hIuZv6l}be*yyN(z0uL?zFq(=`y>LwL zc!Zc50_ddH^ZqicSy>p5S>D5pfxbr7>+>*X9U08)W7#B zp9_v3Y}{{{pGyEu{FIVu(8UyMfr2X*W=@b;c=jf@o;aBD20?n`IK~RaRAxqICCFdB zbnK7mi!CK;j3dK;A|?8>mmf=Ssl_zjx4u%mAk7|FGJG3dxVd6#OpG5)n_UA|!Uqf| zeZ{oO9{2kX-Nk}nZh3@!E8U23%qI_B4I0q;d)6{90e+ItpJO&05Xr3FO`~n4)0fLt z;1~0Lw_20^%DMuoaLv27J^|xgg?F?NRyg3$P$65+L$BY-=1gYxDWq%eT8^C2H|b$% z^1Z)XvmJTN7R+B`>9;Fl5q;A|`BjAq!7{OIsYkY{!N8Ek{%1^(pn5M?u5STedwUVO zvhx8Ad1VF7jt~}6a`JJ?SmTE~ZNIycRYBfLr_~nwHK?qS5Qi@Rx4<8s3?uKJt@o&; zMge4(zhi$D-oc+^ZFGhPemHx9;p(3_FN3yZ41IAeI#N!U30Lt7eW1}Cu|#5dX6Wb$ z*cDq(dmgc83sb1MkA;JT1=QMKLbJ5ZRR03rG5naFm;^wF2mz3S5Hlq#o%_uMtT@I3 z6L9magpM&M3B{}wbKwHCIL6l7Snr?z|9j&;wi zeR@d!daM{jj5B9(X+Kwtd2Bu*Jp5cT5jzv?3=ZL`RQANWgH(D4ZTPNIe#Xcp<_2zZ zoy~~b|B}iP+g~5_-1qMwt<*y(b?YGl;vToGTC)5|^)S!%Q&pzmA)1)CiG%Hhj(}3o zJKbD54k2dCC}O}eptWq0?o1{6#4L@u)hVa#*}gOZ)xhN4b3w&Y^FUNo+?GwDC~0_t z8bVw2wz;5P#`h^!kA0`Jt<`OzTYweo6M_HT2$41I5D*I^tx2|*!%&w_LzZX@$1q(HS<4#%+js=sTU-EF zj%XZv#11lra@@R=C&QfMN6UEA-KHBxi@H?yO@qEhY1MC)!PGd?3?c^shz)Nv14oS73*v=<+7wh@)Md$96R@A z9opmR@6&AhYpHsE%znz~fiB8&IluctBz+jK$fl6?=;P#$7RqyP{D4->dWc9!1A(vL zXf*5p5-FdwgT()T#^isgyU{tM86{{>UlRh8IYq=OD;^0PUSB_#XRanp6q%NEcs zPkv4$TW4}qDgVc$#50%?i-(1Kt^Ry=(?p7+v&k_yUH{qbdCACtRfXA&Sdh=iUkdf4 zDW6TLT-7Rnz!rZ=8_uzJGPPB9z7b`NPor568U9M(omkfp;Et_EFMZJfl&MN!+9Lg~ zqjM?T@i0qa_+HZk9Br5859a)~9${l##Nx-aSzFRq3+gAlifjQ<&xB;oaO)m8YnUEy zN<2uOEA+CQ^nczLPYt5bI4!uEPLxA1yWrfU20>nK$f&aIB1G`^ouX$b zlC(dORp(HbvtQGd;z*_e7aMm^{{P63DKtiGY`$y8y-qXx*8e_eDk&8)212XmwhxPSf%{EBlW9E?W|!b=n!EoH~4$I=rvCJ;m$3@RTy zJlbNh$(T}3P`=g%$q;Y(kvLqu)KZN~%XgJ%XsQ?(SMRcrd$jMU1_kU_1dc0Dh6e2w zeWCs%uI3u?oh}hjc&n%-|4o!2`+)Q_C!7;h#l7Z2kNQh0MGD}GZ;Loyp;fC6iI8gj zH99vuJdhko!!>D1hdV}P-Zo8wEg>_(E%FCEu!R?LABAw^dI8_UWUeGgO>AR1_*oVn zV6eFMqNwa-yCLWf`%3YZ7uSF>BL$wJ%F_89n7@E7`3R}f;hwxQ3X5AVT>`W?-l(wc$%_MQW0uj@Bh*DF8wWU`9`U& zAocOMT{90M7;{f8 zQ>R0DfqLWew!xuFR>q?OzbG(PWNgixvmJrGG#IJ#E|~cGH?jX=;)mFe-Xu0Fp#cfs zzPNU`HRfHGlpF5nFVRUGpImA)+?V#eDNbcPF!vAbnuwJxLOe~M(*}dsnc?KVTPSW71ZJ)h z+*=7iw=)s^(8&K}{zz*15KW@ys)7n6d5LUM?_k)|qb+0L!>t$mA{78h2BwySN8;qD z?TQ^s1u&$D-PtVSL=%RJ1vwIC-ZiZz7+ zgdVUv2+d2TaW6vXQI8uL#`QUt>tY|wL&dUt0Tje(jLL)ij4VD_N(Z$;rVxOK!AZ=F zV5m&onas|b=Tu?pS7ta$y7?z(Qd}Q{8=|$=fP_7^Z0dE~YFm@Kgt+^&35s1V@#z|= zlVnap#^es~4%ZH?#66#p!g4>Ka`K)FW5%Sbc0(-c4v2zlVBBB(_too~>b2@cGOV`<)L8#1%}X@IWvZYYkSf>0J{aSsPnb(OI8Z8glf9&+zOQK;a#)kA>IzAjs(<4;c- zaOn(*hZN(Bc4V>Ilmd$yr6QYxng_*w!BcfJ3A{}b&0VIMM-wO`-T z>ta-+C9};J9&5$xwiNVN%{P3@AoKfl@ZQgLuH^5g74h04s{pdtp!27QeHe+eBQjt3 zpYx4zcp#Ko9U&y$bEpHjoYd(=%r2#Gav^h@kEYS{r(Q+AYW>@6?J_pA8iquypdYTJjR3rY-wg#V#0bx&XnA*W2Fn7t?da02z{B#|$Wfw1u zMuobiSsh=b0puyeBXy2?nd6q|Wl-wALgmBj9Y-o;l~n@nv*T_PIjL@v#nut$9E9S> z7(;igJiHcGTSs8kE^Bni2V@*lpJX+q^kL_a(53e(Fvb(0u*@$J7lpi;qA%fpJ7D*1 z{Ew+lxPP&l-f1grb4N#9KS&cw%=;zvbFW+kqr9Xn0A|E4c%LK==xs{+yt&v(kWp;@ zAeZN{Qt;_v!G$}ZyE(`)Y*J!~%9Z{_%{QO^&Z0g~V$Y)17P}SfbCdH8qW!};hM{i0 zx$3P-gb-*-c%$&u6ER^+$inM`-lg^R#hX_2@u~r1X}i=h>iv0M*XORRQZ|_=>p(Gm z>lqfadSFoHah13e=J+~s8GPt+)sqjQK)q%Mm)k1Ia7`I;Sa;(P)uIL)M(_shQg4+_ zup`q|(t#i52tld;=uW!SeNV)GsLHW`dU1>E8s?Xdgb(;4tJi$tMz>T5$!>5P_uo%W z&Rw;BK#0D6aR2dP7=%inJCZgs#{Gz<`9t(F0WcIta2Y1A#aZE9DuQ2_%B+0}Jg@D+ zrGKWbHSTbXvDn)iq26-|tdyDJT}AN5?va_#wpn;%l=!0)OQg##(_mhB($psalnC6mKq_16DCjRA|PC#_Xu2SWeU(sGhxgw{NTGjTdX#$=Q74 zKhOJU^ajg`Tt*6CG$Slo_-#x?mz(c@Ma4{Q@g0(Kfbof&HKxl&{4q3prhZMQeG=x7 zi69x6z50urz~#S=E6g;C1Hu&k5;(Tp)wA;Q*E7){lccBdDkgoj*>4bgP+_PMW_)1q z9`~n|t3Vv`T1(8lY2>F@UW!E#N-g>}fUIBcOFhIdzEB&v%e87-tW6bvxR_qRbXt5t zvpYvaQP-Efx{G}j zNsV-gYc9gtIwbiHM!k2drrRVM{gF_=E7PF6*e4WN>3oRrTw!|3KhQD_tl>uiAZ!fb zo!>j7G*{&|(N?3JN3Qv!_Pu zub0S8y*=7p_O;hmp#0YqJXTec27KZ+g!zpnAoT?u?bFB;cl>8Z@fEfX*Tt{&OsAcF zY4ypRrc)tZMt%w#{@ZDQqHp@Xu~M_XQ{VFYcSt?48|iRh)`d%{fMuz;dop; zM9~bpRRa4<%d}f^ocuxwp~jH79ub72;^x=@vl=s#lKIQXfy!5ZlYD=yOTgO7X%};& zm$3?lalEwGPt?o0>+nax+tS>J>uvO^j%#f#*Oee_Pra-gdrjxL^LS&B{7`X3{|+q= zwXC7N|IIK`PyV|}H}1{D#{2tkbXb#~@aa+{snA=G6p*%G%+@A)4Et*5ijnVF)?Q4Fv&#qr;1O3NZ!PjKE7f1kOTVkpk?&b2f< zS{q>fah#num6Ko#Yr?Ec@-r1<@r*s*VH^reD=l^}IjHixPN-hS&-QmwjJ^8Chg z&5QVIyYXZyCwkpjEvp69x|@VAy>-&i6!cxEtq(2!Ghy0lmfmFZCx9~mmPzqvcT24D z)c4lM_)Yt<*a1whv0o!8pl+UVjVQsXDFLUHrhOne*{dAb%Xqq`6?9+oWf;G_1wYq0 zMz5#U%=ucFWbUGVdlopHGO+hOn9!J*?O3}D7?rpr*4#47!s_HN7}t8XOcrkmA-QC` z+lg=EKK)pbEm1wv9DA9-u~D`J{n}Y#TJLi_fw=u(${Qi6uwz`H{pIDoE4cYcfOLZU zt`nIJL{tbU=Af(j&q=gC%3N^L5&)q7GBE|ZwTIn+q{Ai!&Avl3Lqz}1Ymj~B&^o2@ zS6d_wn3WHSQc1Fw0;sR~Kl3XhJ%3h_Kc}&bWr%pG$&|9Pec_cSNxdp_&qNADV`2+c$g?15F$AR1m37(Uu zuX{%dB6tZi#&LJC92Nd04y|5Ku0qK?$poypTcZOiKT8?j9?%HZw&dpyMBUZE&FkMj zVGn@Xe>M%@rX(Lg1*ci;nT4&VrUDpQr=1=aaGMOq%TwSZJPyD z&RaV*LTpPpyd<6g{)%7S~57De?&cFe?b5tY_7oD+xQG81(SOD=_2Ymo&VECMV3QW z;i+!G>*%2F^p&wX4`#=3Li{7qh2*cadTg!h1HmxtPL)Pz&dQ@aKeexD%paK$fNU??*jl3 zQwJG-UwRV(f4jc$=*(Wd(1`&)IC_--G>PsG_ost+Bu~L)@g%JgzM`a#kTy7ne_}BV zZ1oaS^{$-ASOjz364aiwHDiJnfGsI7dIjo{z_lz_kXXbrMkh|s+{Pn<>+wT2I!pZZ zP=0tgyXahO+{AZ>{6DLLN83m)z=q|_IUGI$@r#mvNa$aUncMkQ9z8iN$+p+na;Aiu zdIQOQizN<09ZJIVBKgGkEn_n_~%+FQt!;QFVd1Qafs&?@+jlTS~XAg82gI(UXBi4VF-B6UAc&*2%1~eo<9X40{ zTk}h`m*0k99*Og(#|v+dji-aNI_<(EuwV27EW@gv{Yacgrnen3i( z|Jor_r3t>(i(qnntJHTzyszL@?%-Fi%$W!bKNGLqZuz*RXuG|*5a@SxHAQQS*?&u$uRz^zC(3-rfQ|Yrl75=a){q{t zqhz4~x|EFCBDJ%`VxH_+3?^o}gM#mHqqyoJW6s_fJ5QV*{vu&VKzQHU3xd_m$jmJ( zTQO;<$#ucc}3E7ry zgm~0&Ci=dYkoCt;^_I{o+@Gvd5MJGPRu#b2GnXk?3aBTyxE1?;ax%Vr8(Lb%dY@i+ z8pqNG^{S9-8Um5A{*2d(4zMQQ)2&UD3kwp~d39Zo;n(YPAtWMm)>CFhg4Fb}@N5iU z{uwbqm?qcZ%mD$eXYA~W^2Dx)PmP?q0dWKDwfHc344C_%@BGdwATZJV_)X-9LI3h? zWpN`zbnuP*<<-$6F_FIG!J)D1Ph)FbwaI;x6gpfqQq|*S_UXju%N5cA;tw@=Vj!;L zt%emPagC#qp%xnE1HN8&J(OC8u4K^28yt%LW~d^a<_yG(4Peo*zq2bzZJrKSf$cct z74~KnE5X^+t#=Ym(t5^N)2=H@cjQ$hu-7(8_Df;>;(TLr_^k5>^MU+SP}o+sF{j$| zO(X3g>%3D~2uLa^X=F@M);7Kw!t5hSJ-p4c*R++g1cn8Nrxle6k|oeA(NGslmQMSv ziTMxmcR)MY4a}QqP1K`fh<4}l{f7aTItbU(6itF0)*85Y&Bs4DxNj&8Ft_!Z`X!Nu@vuwHDRB@2{w ze%L#+4pNL0lSfK!J+k9iX9hN`Hv=R5OPI(_2G%hK0Nxq$7CAllJkHxW)EG_@LzKlS zMj?(v(=Yy+oVPRIWqgT8hj-rKSZEebjF@B7WYU168B3?C#D;3nCfYuay;_08*RdM4 zx#c0F!+y7{LT>LJ@CHe)+75GUQcek&#F0K6gr ziJYP~Noe}Ix(HKFeDkc`v^f0Ttltdf)fNUZ$+!6v>ozFfx@LO^2S!8&ANx2Ikd*yLoN^Ov!Po}fL$mG7=1++?_PqpT;15;>k z2ESXAye^$w-^ML@t7#UJxX`Ri;7~IM?(ZMZ*a-5%V5ZyBcZtC)WjDieBDu&Rx3a}X z{!wL?Cm=CK)mQ(Yu`JLpAePRCqVKL|3H>{=wsddJwr35LE+fgZK&>+ekbv>6#2TB( zSI&!VW|8c&QVO`K6opIWn6cj6fq4LvqK_=bacl>)W(+3gCcJdwSrSoG2%0}R(X9<{ zfS`s8>M6VxU5pjNtj0_iK(fy=-6-r|RQ>%vCCI%PPtH@C$h}C_gB3;M%YYlkt*Flg zl%`-?11?E_i-{e_b^HA9z#Las^1!{p>ZE`--)Ct8;DaeR%W^218-4#FD7@%k#V(`v zu0uVXNt0THAeLLWX1bjED@T@&|LI$j&PQVSPZml-{y(C7eW9YS_4vx{TIU2|?FUxm zMy2&(x$#Dv-*N2}E!rg-Gw+Z)F!wKum-VNxo@)O~O}FyrKXB zB(~&`zja2UhL6sGb7ppbvjM?;U3!0-kO4)hVZD$`DU}2C)ikOVMu@reko33G=DV}V zSNOZ4DWI~Z<}w@ls2R8XUT!Q=!Y!1WYV4pTNI>!D;m#AsI%8mUfu&O@q^H@o|7+-rsPixa;tJAdM4|z#E+`KPnTM-2}kV;3ec{){}>LxZ(sIcKGS<%+8!8U ztT=KE#vBCR)f6Dj$a5(-mABnTN{J-E!8=UedLOi$O4 zplZt**I!sTVSD6JhO3&yIS>NaM7{7kF1|sS9}8pIx6_w9p~xNmcMMikxLR$5wNoJ8 zw*ZVWV-_I+27Xu5EaPlIVj>SWh{MUov?Ylt@4<4cK{`-Cq;6)9P z@+Tj?iYW%UB(V-)kGwm$h-y3d!}axWWi0GTJ9MI4hnu0CFcLsyKM0no*=I><@*%k7HoW#@JQn>F|N> zEhW_WZYIA%E?)ge4GpCG{;e=lOfmp}c}~%Ht)*Y38}E4h`DA-jpdW`J5(gtU+GIt_ zk9H(-y*Ju?egsp!#|0M+Pwu(kDf}ADx%u&2vDV4@m4=?}gM$*l^lo?0<{$Vauw!Yg zcWT8*`H`78ZgA}zZXXAdW{7ekLWiQV*Y!Zb;NhuVeG}rHKhV9UPat0yETgd7^XmU} z(DzR$8@|KpheeMYQMFARMNJcnA2CC6<4f|* z0G%D0R%TNg8l~L`2N7mErXhaLL^3Bk4+%!E^Khq^P`CddGJ{GAatCiuI?XZUZLVBJ z8I!YUD5}_0FRh6qf~mpz${_CI6YGS-kdgLv?`czmx-Ugl_Qt~=1gF}hkwQDbLR{*# zHvR!l$G}QIczVjj{MfC1b6VLXetThJ#%IGUO=McZH!-w9U}RC|;qbXIEv#jPCw>JF zH-YUqRHjKN7a#5AW)5GgIjGRS@`iOnC{3sE-H|>s6 zeQE3;z>bUYhl&Q_ulUb=GL*qg`rW@wSfb?%z~|QtuLR>eH(N`ik%YNF<7DdVJ1U&M zbz$Y~&aUyGGLTAHDDxGa&XxjHQ4k|?;n@<}c z828ahXSuB%LDqKTr&ZBG4bnABNr@iM8TgPTg5$LVtRK#45TLc`Aqv#ZKKKjg$>p)w zRCg_B&3vVot7nv(F@HXzK@Jh~A*9wtf$fZj&|RiLO~~?-6GIp;>P&`(*VXGs(24N@2@yq{LgDcj8>P znth3{tGxMdr@erSeIFq0{&;}u4Hc zO#*pY-48r%ny-GYrN%d@w;E9`%P~vFZtgjp{+=B9lu)OTL+j-jOKl$H!H(NiZ7xjn zRsElFpr*C@3L8%XyUWXg7~D2W^yE#J-zdH@Rh#A{IXe2q`Cmt-D~g3rppOGz}VYp3hQhT|3Jc~5~ll>9{__cIVz%W1j7TnS0TFjbW%Z2JwTuQv{@rrQK@MEbZ94uORP zsB?H35Y3K9@|60%CbQwvvewqT)z;K9i0A$DPM?e-v#_G>&3yzH=G4zXvPAK|p^-w% ziBk6gFOz8T5xLu65r7U#3AgE!gC~wGTv7}ojPEvDOwtE|Lr`;==eAE8G)S*cz(1+0 z4%%wh^;=o+9@CC#6chhy;wOa9=DHivQGb*op(Y2jIZV0#_^O`wm$@!Q*0c5V$Mmj^ccSG!(n3JYu4QHbdANnBTk*Ktrq9X;CKNlW(E!EjvdgcU(`7;@(L%zpe?x%%kaMW8*` z@^w3A83E>uR7!qmbLPtwRqAO7EBf!EjZFLK{Rdnju4ewPDF)4vX&*J;OYeqtv!r}8 zgGm-|eNpUo<#u&DTTEVCOPmZoPT}nVR`}4_wgxI3p?n#fh9B(_l0Qe+6Y0}8x(8wq z59amKlHG2Tn_hC2@&VGB`wdK|-R~OjFWg~bs*q#G0nM^1E`bt4InC zNd>W;%cuxmh!UoiADaqBN*uLnAHoSLZAUrp`H?(T@~*OivS!d`V=Xc!tOgYTAN>IC zGYg)+6>Cek8uIfDgH~40o4zhu%O%z^N{Z>?sbsCkNc10`QQ10yEz3`r!=fqewC!tu zoOj%ex2g*5F!^+x7cv|!9#pkoZjByKc{Kn}o!Iu`t^|;71)dhM#h8b)S_gL5)-TpR zmv%xoTUBFIWe3Jlp4+^aOHNVXRk~nc`5iAY2xaX##4HQhu0nE@gE40HxzH>tvkP(B zqM@j+scGUh(XIi3)H|&$|9%RpSZ^PW{z=wH(5}-K$_g@La%biJsIM`)98OR+V_PD< zreCsFO09|0J;%|iCS_w>-`-9aLSj4_GXLi#Q6u3CQDmPDjBU7zME!NAD zU*2&j*INgY$b-76f4Kl?o!{*m&`Cp@*NN;#K9696HcLU-o`DJ1#+D=wu2Vdt0-+xb zcI24M!zPfKOG7W|bYqQGVKoHlo~c$WVAowL^wNM7y9Q+4H2KuAD>1V*wEx{xeESzh z64NSzh+AKpSHj~y={lfk_>_lcQHnYd#O~y=LjV%ZLJqYh-joy*(9p zA-(pNSp)wR#0hp}-I&c13p^#H_~^&`&wjx3F%-@2e6H<-lc<$5i&XhoJHfS+tgh1* zsppN&bo;&WEn^n0fxY`&7W;zOAb6f*H^~H_HSmtvHNJX|c{_t%~fyTFftMz## zw#IEN^!%Q1bkCDk4v((_#|7H-jKvcO22~o}!#@CQ@v~U^@N?Lf7tF$)Jm}kjCJ62H z;hKaYo}8t>wri$GD(;W0+zP&6td6v)!-{bUESotqk&_Hrmn*#|vLSSvV(|h$-Cs^e zcwR0^OCZOfvT%ja(ja5m`7FAo&l#4r4ZJgnwaz%A7tkkg8{-unH%gNQE>q!gRzR%7A0$#4{IlJ!6Tj%l?bo{C|F#OJ$ zWPW!Z4DIemSMOm=Lss=er~O`o2ESJ0+O>$9Zi zjcE}Ridw3$hsl3u%Y&}TyLk#w$ez_S#G52{MmTLLlRa2H5mQ23;5K2P>La6H>T%B(9YA zjL2Vc!isLoc80C;WeUA%U}xj$QLybQh~+G@tZss`jWv{h#FsY7JMv_SDs2@XG3Fph zc$h9qWo(50#hcKgFJ>mJMZs&;$YAztDD-Xa4X#vHK~u++4OL|77O`?K7wSI(P>Ubc zE=7=avdXiwT_%+GO#5n&5l{dVOm|IGdTXX&c)L3lR1#btRQOg zx+RXDg>i7e3pv6Z_Nb^O}Tvgx+Kqa8hW!q|h zf8In%MVq3Lv>R%Z%B)-rU#IrFK#7FIPga|@F2aa<)}vtVp7oeK_rn@0|0Y&h!%$-|KG zr|RSF1xzfN-ILZ|dI&UZ!8`U`LVG}WWKpe_i19?+$08H zCj{eK0p^hzp2=R*6nz<{g4Za?wZQ$jxgIE|h_tfU*#~EzPyFA%3Pg#86>^2nVKgme zmDx-rvvGj3*by<9_2kCIrlwiqONe#83%`&rhbi^k7|D8Kddf2{04Bof#R%kqQ~|kR zEH3^&sR^jkHz|anMFTr73XRA1G$Qh{TBGr3h_y10&3{eD8X`}L*~0ZXCv8UJ1QGNB zS~UEC0D_V+ku$gcSX@N)-xwhqmB~W0RdvSR&Btf36z=7`uF;~3!LHJ1^?U49{9mG7 z!_(o4B=PVyddPf*fds&^JPj=o#mF7nKYieQ)yPs z(@uBblyDzDpXDXw0kf;q+}HY&xQkiENp^=)^5 z)nLsnQvFxuK|Wh3VlfTH@;jDm8&KC?MFBz)&KNDs5AoSJrmt<*T^R;lI&k`Bn<2~M zjCHIdv>MawJHX=TF;`oRJ9-=P3=f(NV~jG1f(#>C_!3N385o5F6~_ZCJF+{!|L#od zWCt6Lpi^PY-6@;Rp+{XvTAs2wcgDp%L0O1QX2$CA-taYtnvd*|n@4el)1*5uuKtw6 z9y}~}T#I&(>(euQGccS|cO|kse!d{;Txv`YKV@+&29$s&@W4Avc})$W4DMm7ok!$_ z)_<~R8m7+GQwjU*6w)hH2(FPVU1^eQ?Xa~Z6V*RY?&gvYgJRtCx>2Vy!`T1H6l%$_ zKO3H|-qcofxR0s`m4p~E;nDSQsORsWXrxMM+FQwXKe_ph;TLz5gHJD?tYE!JVb9SXbC-9RQ*gMY6X*OX3Ygcv5YQ{108hi6vw0iSS ztpa)N}h zpU@ybxkyBQVOU64C*oL+CK9pMT>6CX?{^vLA{dm7*tlwq|JYaf9IkCj(tnaA`Z59Z z6wq9Kb6<;^m&}F+HJkg{O4LdSdW(TI@U*(Rzk}F*g`ZBA4 zu}2j~Emq+5R!na7ZQFH355cQPMj-w*|IqdjSz|~DlSOz52ufSW&LX4E<{|Wn^`2!^ z7xLTPIVhA0M>bk_FG{O7Gj;*F249NRjCsVg)%HGt-$(Xv9e$3}jzH!Zi*lPFbz>lw z_XH+Jewt@5gVv4GoO5xut4JiT6yokskCv=&4uvJVxF5(~9-o%RAkq3IcK^JBzQQf# zVnVKkWeb&uRbCf)TRS$xqg7yy0tQ!eVlPd2@@A_n2{5<`>=X>~jrsvA=IqsEjrO$u zufxn6uAU#yF3`@v#9k4;$x%pu78h;5EYpCdhYPi&?!i!D>5uKf2Y* zjFHm>ccf!Qz9!q&L>FYH7aM5))Z*2_5~>B$9M~!iW*DW$r8DHXvzZwj25fWw-$w5^ z_Z@xs9=r4VQ9M-T=x6{%)Qj!CPn22~df!EzmtMOU6?DpG$av_u@N92JmshMyy@yP7 zy;5xgOdC=d{R=Ni$HZzOjP{S3A{vgn$YMh#6xo^gQB_%g%5nR6rOhjd!jG)N?DdKQnQ`8o zjecwG-h#vGsej@ZR^Q(XL`fO-#snrdGE2}92)^*0t(MJ_d#9qte@OeYwGvjv;jomJ zabGsyjOqVZQEN`qs{m&>Zz4FPA{y7;t0smcL zGD89{Kofrz`N8q6&deP;3jZd8 z=j`QZkQ;R*>xMrY6^IY=y>)VtiNU8Xj#knDR*nA#m3lL5C9;Wfkr}ta@kCxeHScDK zCQA1(^RA>QQysNjI}=P0flhmjyBZpGv%B4iqNbQ#jBDU*7&ycY37lh?iWaeR;7gqc z^~BTv)()Uea9fPd*t?O?>z)0ds;&d7iD!EUkS0Y+=)DC(QA$8Sn)DWWFA@kHEFisw zCej5$i9wJWdX**!O7A5UX(~$5&=C*>6#n78_dDGmzo7Kn+Qqs6%l44WcjF{!0J81(atz6QW-BitT&$ zl{!Mqs&mmlt+2n8f9J_IqeSMNqvcl1(Y=EO;Tef5h0}079MfKIz6Z_o+M-moNIh`X ztoyHX*;nC5>3d&pe`iT7TeFp4e{+!dxVrx$nK^bfI9ijZd26}KQ{xla(XEYjGS{9B z%ljzAp47za^N?PQl!j2N#|RGo;#jP=nIi_)8yHRzm*Cj!xuW#0Exw}t*BF)@9eZEi zu!m9PTZ`P`G9oB-)f+UCs@$uLNPlF zVA=%WWKvX9O`W)?J8g z=31ih$J`l#mF&?pxdsM5?ceXS;lIX-Wi}d&DxdYRmdSp#iq2jU}b zybnp``cH6VP4T-gYjr5uTH==m-&quInxkJ84TI6IroGACeRZY!j0EI}b+s}nMil`( zkj%X3s7FxI%{c|xggHY)9+lfS(n}DkO%7)0*VBIF9ud0t2i+rdgMH`!WU5BFM~o1V zn;w}$ls8mf8il->BD{#-b0Twjiv z&s18?QqV#PA1+ow^Pj>dw=Eu^it6=IOf}GYttI@;5q|19Hi$%vvpO zI+0E`MnP8F`{d*FiF($1&y}arqKSVWrNqnvd&J zr8x~_I3|g0em1!aG=LD>b>0e1WJYiqMkBa~3e-H3m0sYRpxGlKw<8H@u9$VMyHblhik zFw%{7^tadt&O5_z>P|v2BI-cLm=6k?)iA;S0%qe9;)CDE=E8^~ZFR5V8(y@%gkRbX z{?*916Ujt9RVBR*)Dj^j+G>fyQ9v;tsp+4nzJr3N4J9u$OcPHmk%wT7vvdY)A<8Sg ztxNgd=p{>w`JE~{2@P1H+Mac@%Yec`&|nVL>xb`e=sJ79N(Vuy3_Fh-E2^|pQqh0y$pMBsljNYaAUfN zo(ymHx08oXOFLWaJB0ItaAUosCZ)#o4;Bg#pC`>%hsf1~C-o6@8gwUH^1 z#qveEDd%F>_(I)A+OcHZ5+_t~e#p)@rKDg&oH5oJF|^%1T;*JuF1Fto7p>LN(pL^= z9kyCTdmKl)IY_0n1SY$(W(fw4Lxh3aDf)aqDU|6+xEcLo(%6bP59jZ0I7xN=afoNK z$?Py>gdnf>oko%b0jPZ{8tpL)P{a%F+R}_eruB>ez*pWW*n;#vt>c*F-FOG&a`&KcTiRx zxl!Ly$R$`IgKwfuf0cT^Pr{<}3P~3HfUu*{q}B!N-UUA@*inACNAZ3^&ilMD?oY_M zbr9qXvMod81Dpo#0P@z|xV`)DKrXRE&s37Vb;zAjYy6 zl?>h;adL^#H9XEHrKiEe1iRh&1p5FELWMgU0{1|%HaJN}(fHvEDRF6g%^4SnJ%+A5 zIo|$wW8bqkbrWzW$yH$6f+i&geBYczRj13kj84aH8vgskTr}g(!m2%~y(agUjl*)7 zLC_l{B-V3Nay1)j>Iy)I7yL$?w-rxU-Mq~w^*y;uCw`YD)dfyUbY@VU;W{ehGD>Ed zn<)hKUJ4(TQk*~Fn19xPh#D-iC@ZzbzmDmcQIwzA$!0y|w-E7wEgIhiwraVL2eDLK z=qlVoM%;$?5`g@I@bbvg>N8379lp^V$LE8Igr(+o>r0oxrbMo21W%kWffPve5W9n> zD&&+<%Z_JxsqX0A^UAi#u2sN7(s>{w(0=*G_cqLiJV@9d#lqrc3wPx_IPe-9J4wZ& zULLMLQh77xKHR>+sZO6C5=Jiw*5lFZ4OsbX!#Ak;>4cvld=dwNB}0Eq#LmLJn!3^Jb)Bd-j2X zfm)q7+&R3TKt{0c3s*6l@TrlrhaG8!=3-`4W5Zs7cRdgdkjllLgmdNg{c;R7#t#}m z$*zlLci%~mVye5tNVTP{;tart^F8mp0(KoaZ_w5arj8p_xId4t zXV`}rqP;sx0{LIfimaVHRyrxkiD%kdQMgRuk54c_*iD71%7Y4QhCub*CKqAlZ$TXi zOxnmA+jq|NUaA+a3`*h2t1?_QAVETfX#VEOo03gPIL3ms zP;!IM@X(a3F*0wxosV{edUUm70KULoku`L0QFVYhe)+kcTT-CDwg3-wk6gQC2PL^S zgkwY0&(K@c?=7C%GpCvaWCzj~9Xu5u8)zMp0)gduha_qKzUEnZcXRHsPk?IwEU zO0m|F_#PALfrN0sVovsJ3QFP9jrJjQWlYNINTad0`)phIJGF&26N&5yvSK+_yLxnS z!vI$H;s9C13`Gexct!M$NU)+^8_g-rogfIZw4u4?&b*N1xVL@oL)?c=y*K#lGI&@| zs85$f4&z!J%mnU3R0^xC&buH?r(&y%w^O~P7OHyilGZ&O4YDrLiku^(e zPax51ovO?*{-kdZcV+v85>IuvcrRdl9hOC4*n~>H7cx=W{b(zd6QTewd-EmaD+@x- zZ6d2RvlKwinvccz*9XbFY;07MR^3vwIJH~fYq#b&Q761rs5BoKspw7h!+_wxpvBo7 zt#-^=g(Eu6cuIm4I#ixuuX2~=t)&6T{M}>QuBh zoWA=uig+hkgaTQs(KF%3*FrQ_ENu3`nPB-%eKb_5%~UX&PAZV|rcs8@AMx?7x0gis zI2^O&K|ObWGN5l*-g{0M9fOK89DD^0ArG8q9O-sI;c{;}I z@!f9u&1N4v`TTsjFc--#Ul4jh!VgiIJGBWq3onyoS+Y3YMJE(WB>g^*mvVmBc*6F6 zmTQP}7U-L_s$vJRp=V7;Oxrw-dRE)0?ao)1?pTZAKs0qiDE|ox` z=enduUXj^)FtF)2I4$huy|pxtA_zsTYI4NIhL5CUaj64E@2w!`xdud(6|JM;{;R}5 z17Whj1;!vrLBY@Dgy0k3={$YUn*?864CMoJI!%_?85hB_%5lG*0djmZWh+Sy!t8U; zbW0|p?hah8enBn4A1>WdZdQ?J`SA>UHw?F!u>u8~t3N}=Fn(2fa254nNIfY4Z`{zW z9%M8LJC-igE(hi)*GnT_>@{1}kko|b-g+OyDs@YlUNeixw0HpGS*@h^#&Z^xNYQ#r zg)*yX0LI9(iB>FUmv&{Pm_-3iS>d>>)#iH%XNvw|msWlbp^DwQI<6qO$H}dF+uboM zrM~)TaR2L%C`gKq=?t6|iFv?7S+B~RaT9w12WpvN_z*ul`eB!hC+#48jaQJU zw~{Wr4%7nz4}1VCjy}^k>YWO1D(&TOjLpsGji8)zvkMZa)C@%G;l*t&sTni;9#mlN zH>sg8nf8l8KKNI}BGm6(9q)0d)W(qp_?EDEng^t~mNWPzyOs~zya2?Z+ayyTF>geg zE47G@{uFaUuu*%@$GZgbp$jq75ew7`bXAy<@Fb0FGU?F>O@v$^jc4}IlQ;Frnl|Ap zcM}rqoi0dZV5Y2i^IOv*)kp*j>3;5kHcN~yS`OOeqj&P=M1L6bwW)aIa-}rZ7Nu3@ z(9Wa=Z%<6h3yo9?lfBQStd|<~%TmUs!>C6fddrNNue?2`Kz>&^ddp?#ozvN)Q{OzT z{y$vv$fjJe{Q(H0rl>EwuBX~-_JmpW1W3%m&GOX!t z_G?YUW^G+o#kog3p2ud=tDnN!G!3&hYG!d@y!_v}v(fmg#-)O5T` zEi4lzHGCOPcog0k?eEoF<$<#M+?Ybw+;JN&BQ2FiOKQ{^@`BKytY^T|J-=~cEh;j} z3v64^)RTVdC}xIUhPDNmu8(P_$BI%c~%quxh+IOP2J6Lk&W}%l^YL+4LJJDb+3N?D-#c6ujx=)xp@_m6g zf+M0HrN0L=rjQ)4f zfXWkEkp&6bxo8^hdbm5UTcG^2&UpQzwAD1 z*^*v{21~30mGvLS&-c{9$_kGf>a!ea5r?87={9$AM0F#5NUC9<&v|-&_snS;A9L?d zuSt(hT+_NSM##gT6r;ddJICJ+lH>x^Mh>qgcEx9-m=dKDp*#jGS2a|~*ALx~Rpruq z`lsoC#+aPh$vjCi9Q8K~Vc=n@XV)PL-A2Hcxh$%@E?y_5Q}zsk1oXVE!gE9s_?hW7 z)h6?e7#Ww~T&#c(9rQ;jO>mN+`RShuI3>TNhu!3!?aAS-v0#2-k0_HU-u!x<H4`-6K;;3G zsz^NM<9&vrP`}wwVppI->fVajFu&a!yKva$DLrVm%VegLmM*rSBge*uLpu@Q0~P)~ z}ztK|MMr&o%`(DTgu)~ zIHJvwY8bL~_HuTP)q|UVFtY8Cv1XHS=G@-)1Y&WYixhoTc*bRW7s1W3hRBQ$j@(ka z)iQPLIoTL`bm;w(%ZD!{wpf{axKk`UY^1A9LBw%e*EFbQc*=Ksc*L(JeaHml*Xu^J za{6#kBK#J{sM-W6#suvyf8@>uAzn)+dS2}DFXpOp6*k2&2;1n)W}ehs36%AXL<902 z?-{X{?|-b(K6OMed+{fK@^l_9Vqxu{d4F}jpUk!J$z-l$qYHQ9X>DK4aKD*5pWUnf zSU*PAui^e|fRV)3B44esoy=E_PK|oI&?{<}exT34hjXnj>?i#b zyh0cJBlip}ssd8Nx}`pce#G5?_HgG3W)WBd!(O%?A@HmmVM|q&Mu+IypWNNHxLr@R z028)p=4J_MRWIRm5J<9)w zzVsWjJ;_d{nu*&-heh`w+K&T|gg&~ueMlZy8ghC#qB!|j>EriafA%B)7r`xrejN7p zbrbAX@raE^Bzi^y4J#&>IZOMJ2O~O#s>IN?GbS1lK6mXHUprXSdMQh^B2X`dXKs*A zOX+5B>{TvHViPM$fxk=?T7_+5 zg;sgU*9`D5;#X(BqEjEQ0^hehS)U7HZhKH4jo`5D(&PV_sfvlR{{b5fc38fH$*6~H ze07VI+zK?)rYfCm>+8X6=PrngQH0D0)y&E9$mA=nwfT8tYcOkPsZ<-~oJlr$*{<+2 zDbzyhyxa78FOYGde}C-A8UB{q93!SO1?#QfZBAg0PmyPAMvJ;Y3$Z{}XrV{T4ahSD zhQ+BoQcIM}C@SPvt|%W>QE*sT6##2xM3+)(3>lx2N-0|Gx|$MVO)0X@ z&kyV8f&6FO^~fwsU8+jY#xdQjjqm{9IJ>B5u1a zRZC&8#qMkK3%nyGjP`zh_pDjbd6s5%uT`pPM@ngXw+5!zV1~UCQhQ%|ToTdngYbv4 z&G6$mj6`u*sq3u%eN8Q-u0T$u z`gOhHww*z=FCJN5vG(`MEi+>^r=*{v!%wdWjPyv!u1Lc9E`EL< zkKCT#4tnVQPnQ4GSDo<__pc5B!1clWKbpNr)oQ`(a(Gp<6E6BA6RPp+bK&#)|Fuu? RKN=2!$gye;5^U);`hQ9e5P1Lq diff --git a/octave/ofdm_ldpc_rx.m b/octave/ofdm_ldpc_rx.m index 9ff308dcf..97b8b4485 100644 --- a/octave/ofdm_ldpc_rx.m +++ b/octave/ofdm_ldpc_rx.m @@ -54,7 +54,7 @@ function ofdm_ldpc_rx(filename, mode="700D", varargin) frx=fopen(filename,"rb"); rx = fread(frx, Inf, "short")/Ascale; fclose(frx); Nsam = length(rx); prx = 1; - if strcmp(mode,"datac4") + if strcmp(mode,"datac4") || strcmp(mode,"datac13") rx = filter(fir1(100,[1400 1600]/4000),1,rx); end diff --git a/octave/ofdm_lib.m b/octave/ofdm_lib.m index aa7c6cb1d..f93ea365b 100644 --- a/octave/ofdm_lib.m +++ b/octave/ofdm_lib.m @@ -387,7 +387,7 @@ config.state_machine = "data"; config.amp_scale = 300E3; config.clip_gain1 = 2.2; config.clip_gain2 = 0.8; elseif strcmp(mode,"datac4") - Ns=5; config.Np=50; Tcp = 0.006; Ts = 0.016; Nc = 3; config.data_mode = "streaming"; + Ns=5; config.Np=34; Tcp = 0.006; Ts = 0.016; Nc = 3; config.data_mode = "streaming"; config.edge_pilots = 0; config.Ntxtbits = 0; config.Nuwbits = 48; config.bad_uw_errors = 14; config.ftwindow_width = 80; config.timing_mx_thresh = 0.3; @@ -396,7 +396,18 @@ config.tx_uw(end-24+1:end) = [1 1 0 0 1 0 1 0 1 1 1 1 0 0 0 0 1 1 1 1 0 0 0 0]; config.amp_est_mode = 1; config.EsNodB = 3; config.state_machine = "data"; - config.amp_scale = 300E3; config.clip_gain1 = 2.2; config.clip_gain2 = 0.8; + config.amp_scale = 300*2.3E3; config.clip_gain1 = 1.5; config.clip_gain2 = 0.8; + elseif strcmp(mode,"datac13") + Ns=5; config.Np=12; Tcp = 0.006; Ts = 0.016; Nc = 3; config.data_mode = "streaming"; + config.edge_pilots = 0; + config.Ntxtbits = 0; config.Nuwbits = 32; config.bad_uw_errors = 8; + config.ftwindow_width = 80; config.timing_mx_thresh = 0.3; + config.tx_uw = zeros(1,config.Nuwbits); + config.tx_uw(1:24) = [1 1 0 0 1 0 1 0 1 1 1 1 0 0 0 0 1 1 1 1 0 0 0 0]; + config.tx_uw(end-24+1:end) = [1 1 0 0 1 0 1 0 1 1 1 1 0 0 0 0 1 1 1 1 0 0 0 0]; + config.amp_est_mode = 1; config.EsNodB = 3; + config.state_machine = "data"; + config.amp_scale = 300*2.3E3; config.clip_gain1 = 1.5; config.clip_gain2 = 0.8; elseif strcmp(mode,"1") Ns=5; config.Np=10; Tcp=0; Tframe = 0.1; Ts = Tframe/Ns; Nc = 1; else @@ -1722,7 +1733,7 @@ function test_assemble_disassemble(states) framesize = 16200; rate = 0.6; code_param = ldpc_init_builtin("dvbs2", rate, framesize, modulation='QPSK', mod_order=4, mapping=""); end - if strcmp(mode, "datac0") + if strcmp(mode, "datac0") || strcmp(mode, "datac13") load H_128_256_5.mat code_param = ldpc_init_user(H, modulation, mod_order, mapping); end @@ -1735,10 +1746,10 @@ function test_assemble_disassemble(states) code_param = ldpc_init_user(H, modulation, mod_order, mapping); end if strcmp(mode, "datac4") - framesize = 576*2; rate = 0.5; - code_param = ldpc_init_builtin("wimax", rate, framesize, modulation, mod_order, mapping); + load H_256_768_22.txt + code_param = ldpc_init_user(H_256_768_22, modulation, mod_order, mapping); end - if strcmp(mode, "datac0") || strcmp(mode, "datac1") || strcmp(mode, "datac3") || strcmp(mode, "datac4") || strcmp(mode, "qam16c1") || strcmp(mode, "qam16c2") || strcmp(mode, "datac5") + if strcmp(mode, "datac0") || strcmp(mode, "datac1") || strcmp(mode, "datac3") || strcmp(mode, "datac4") || strcmp(mode, "qam16c1") || strcmp(mode, "qam16c2") || strcmp(mode, "datac5") || strcmp(mode, "datac13") printf("ldpc_data_bits_per_frame = %d\n", code_param.ldpc_data_bits_per_frame); printf("ldpc_coded_bits_per_frame = %d\n", code_param.ldpc_coded_bits_per_frame); printf("ldpc_parity_bits_per_frame = %d\n", code_param.ldpc_parity_bits_per_frame); From 0c81296d9e84a70580355825adb778c539c364e6 Mon Sep 17 00:00:00 2001 From: drowe67 Date: Fri, 14 Apr 2023 13:35:36 +0930 Subject: [PATCH 13/52] printing edge pilots correctly in print_config(), raised UW threshold for datac13 --- octave/ofdm_lib.m | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/octave/ofdm_lib.m b/octave/ofdm_lib.m index f93ea365b..a029aa2f2 100644 --- a/octave/ofdm_lib.m +++ b/octave/ofdm_lib.m @@ -400,7 +400,7 @@ elseif strcmp(mode,"datac13") Ns=5; config.Np=12; Tcp = 0.006; Ts = 0.016; Nc = 3; config.data_mode = "streaming"; config.edge_pilots = 0; - config.Ntxtbits = 0; config.Nuwbits = 32; config.bad_uw_errors = 8; + config.Ntxtbits = 0; config.Nuwbits = 32; config.bad_uw_errors = 12; config.ftwindow_width = 80; config.timing_mx_thresh = 0.3; config.tx_uw = zeros(1,config.Nuwbits); config.tx_uw(1:24) = [1 1 0 0 1 0 1 0 1 1 1 1 0 0 0 0 1 1 1 1 0 0 0 0]; @@ -437,7 +437,15 @@ function print_config(states) for r=1:Ns for c=cr if r == 1 - sym="P"; + if (c==1) && states.edge_pilots + sym="P"; + elseif (c==Nc+1) && states.edge_pilots + sym="P"; + elseif c>1 && c <=(Nc+1) + sym="P"; + else + sym=" "; + end elseif c>1 && c <=(Nc+1) sym="."; if (u <= Nuwsyms) && (s == uw_ind_sym(u)) sym="U"; u++; end From 237ef593864e46bfe905238432829113ba10e5a6 Mon Sep 17 00:00:00 2001 From: drowe67 Date: Sat, 15 Apr 2023 06:16:45 +0930 Subject: [PATCH 14/52] datac13 prototyping spread_uw option, no clear advantage as yet. Adjusted timing_mx_thresh to detect more packets --- doc/modem_codec_frame_design.ods | Bin 44271 -> 30369 bytes octave/ofdm_lib.m | 11 ++++++++--- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/doc/modem_codec_frame_design.ods b/doc/modem_codec_frame_design.ods index 1c26fd9a904cb10e7dc27979310cbe001e032cdf..cdc4b8fca8f3084c6e0a58773e1670a4bafd0d8b 100644 GIT binary patch delta 28092 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 delta 42199 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

@ChDW0byiYB0P1s$VPeygWU^sty4-e)GYqo*k&` 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 PKLi;S#7y8(`B(Zs|CIJo diff --git a/octave/ofdm_lib.m b/octave/ofdm_lib.m index a029aa2f2..515458ee7 100644 --- a/octave/ofdm_lib.m +++ b/octave/ofdm_lib.m @@ -99,18 +99,23 @@ % encoded bits. states.uw_ind = states.uw_ind_sym = []; - uw_step = Nc+1; % default step for UW sym placement % lets see if all UW syms will fit in frame Nuwsyms = states.Nuwbits/bps; Ndatasymsperframe = (Ns-1)*Nc; + states.spread_uw = 0; + if states.spread_uw + uw_step = 1.8*floor(states.Nbitsperpacket/states.Nuwbits); + else + uw_step = Nc+1; % default step for UW sym placement + end last_sym = floor(Nuwsyms*uw_step/bps+1); if last_sym > states.Np*Ndatasymsperframe uw_step = Nc-1; % try a different step end last_sym = floor(Nuwsyms*uw_step/bps+1); assert(last_sym <= states.Np*Ndatasymsperframe); % we still can't fit them all - + % Place UW symbols in frame for i=1:Nuwsyms ind_sym = floor(i*uw_step/bps+1); @@ -401,7 +406,7 @@ Ns=5; config.Np=12; Tcp = 0.006; Ts = 0.016; Nc = 3; config.data_mode = "streaming"; config.edge_pilots = 0; config.Ntxtbits = 0; config.Nuwbits = 32; config.bad_uw_errors = 12; - config.ftwindow_width = 80; config.timing_mx_thresh = 0.3; + config.ftwindow_width = 80; config.timing_mx_thresh = 0.25; config.tx_uw = zeros(1,config.Nuwbits); config.tx_uw(1:24) = [1 1 0 0 1 0 1 0 1 1 1 1 0 0 0 0 1 1 1 1 0 0 0 0]; config.tx_uw(end-24+1:end) = [1 1 0 0 1 0 1 0 1 1 1 1 0 0 0 0 1 1 1 1 0 0 0 0]; From c5e1c2a9ae8117023ba990a7d2d2ee238f3e67d7 Mon Sep 17 00:00:00 2001 From: drowe67 Date: Sat, 15 Apr 2023 09:28:25 +0930 Subject: [PATCH 15/52] make H_256_512_4.mat compatible with ldpcut --- octave/H_256_512_4.mat | Bin 3241 -> 262525 bytes octave/ldpcut.m | 1 + 2 files changed, 1 insertion(+) diff --git a/octave/H_256_512_4.mat b/octave/H_256_512_4.mat index 143ae7321c3c80eab9e84b607dba6888528e6ef0..c17a2a7f2dba24abf30044186908963c4a6a5a06 100644 GIT binary patch literal 262525 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 Date: Sat, 15 Apr 2023 09:39:35 +0930 Subject: [PATCH 16/52] first pass at rate 1/3 datac17, PER=0.11 at -4dB --- octave/ldpc.m | 18 ++++++++++++++---- octave/ofdm_ldpc_rx.m | 5 ++--- octave/ofdm_lib.m | 35 +++++++++++++++++++++++++++-------- 3 files changed, 43 insertions(+), 15 deletions(-) diff --git a/octave/ldpc.m b/octave/ldpc.m index 1f308f8a4..0abb2892e 100644 --- a/octave/ldpc.m +++ b/octave/ldpc.m @@ -109,18 +109,28 @@ function init_cml() endfunction -function [detected_data paritychecks] = ldpc_dec(code_param, max_iterations, demod_type, decoder_type, r, EsNo, fading) +function [detected_data paritychecks] = ldpc_dec(code_param, max_iterations, ... + demod_type, decoder_type, r, ... + EsNo, fading) + % handle case where we don't use all data bits + Nunused = code_param.ldpc_data_bits_per_frame - code_param.data_bits_per_frame; + symbol_likelihood = Demod2D( r, code_param.S_matrix, EsNo, fading); % initialize the extrinsic decoder input - input_somap_c = zeros(1, code_param.ldpc_coded_bits_per_frame ); + input_somap_c = zeros(1, code_param.ldpc_coded_bits_per_frame - Nunused); bit_likelihood = Somap( symbol_likelihood, demod_type, input_somap_c ); - input_decoder_c = bit_likelihood(1:code_param.ldpc_coded_bits_per_frame); + input_decoder_c = bit_likelihood(1:(code_param.ldpc_coded_bits_per_frame-Nunused)); + + % handle case where we don't use all data bits + input_decoder_c = [input_decoder_c(1:code_param.data_bits_per_frame) ... + -100*ones(1,Nunused) ... + input_decoder_c(code_param.data_bits_per_frame+1:end)]; [x_hat paritychecks] = MpDecode( -input_decoder_c, code_param.H_rows, code_param.H_cols, ... - max_iterations, decoder_type, 1, 1); + max_iterations, decoder_type, 1, 1); [mx mx_ind] = max(paritychecks); detected_data = x_hat(mx_ind,:); endfunction diff --git a/octave/ofdm_ldpc_rx.m b/octave/ofdm_ldpc_rx.m index 97b8b4485..9bce133b0 100644 --- a/octave/ofdm_ldpc_rx.m +++ b/octave/ofdm_ldpc_rx.m @@ -154,9 +154,8 @@ function ofdm_ldpc_rx(filename, mode="700D", varargin) % TODO 2020 support for padding with known data bits - [rx_codeword paritychecks] = ldpc_dec(code_param, mx_iter=100, demod=0, dec=0, ... - payload_syms_de/mean_amp, EsNo, payload_amps_de/mean_amp); - rx_bits = rx_codeword(1:code_param.data_bits_per_frame); + [rx_bits paritychecks] = fec_decode(states, code_param, payload_syms_de,... + payload_amps_de, mean_amp, EsNo); errors = xor(payload_bits, rx_bits); Nerrs_coded = sum(errors); diff --git a/octave/ofdm_lib.m b/octave/ofdm_lib.m index 515458ee7..e9990d3f4 100644 --- a/octave/ofdm_lib.m +++ b/octave/ofdm_lib.m @@ -394,18 +394,18 @@ elseif strcmp(mode,"datac4") Ns=5; config.Np=34; Tcp = 0.006; Ts = 0.016; Nc = 3; config.data_mode = "streaming"; config.edge_pilots = 0; - config.Ntxtbits = 0; config.Nuwbits = 48; config.bad_uw_errors = 14; - config.ftwindow_width = 80; config.timing_mx_thresh = 0.3; + config.Ntxtbits = 0; config.Nuwbits = 48; config.bad_uw_errors = 18; + config.ftwindow_width = 80; config.timing_mx_thresh = 0.25; config.tx_uw = zeros(1,config.Nuwbits); config.tx_uw(1:24) = [1 1 0 0 1 0 1 0 1 1 1 1 0 0 0 0 1 1 1 1 0 0 0 0]; config.tx_uw(end-24+1:end) = [1 1 0 0 1 0 1 0 1 1 1 1 0 0 0 0 1 1 1 1 0 0 0 0]; config.amp_est_mode = 1; config.EsNodB = 3; - config.state_machine = "data"; + config.state_machine = "data"; config.amp_scale = 300*2.3E3; config.clip_gain1 = 1.5; config.clip_gain2 = 0.8; elseif strcmp(mode,"datac13") - Ns=5; config.Np=12; Tcp = 0.006; Ts = 0.016; Nc = 3; config.data_mode = "streaming"; + Ns=5; config.Np=18; Tcp = 0.006; Ts = 0.016; Nc = 3; config.data_mode = "streaming"; config.edge_pilots = 0; - config.Ntxtbits = 0; config.Nuwbits = 32; config.bad_uw_errors = 12; + config.Ntxtbits = 0; config.Nuwbits = 48; config.bad_uw_errors = 18; config.ftwindow_width = 80; config.timing_mx_thresh = 0.25; config.tx_uw = zeros(1,config.Nuwbits); config.tx_uw(1:24) = [1 1 0 0 1 0 1 0 1 1 1 1 0 0 0 0 1 1 1 1 0 0 0 0]; @@ -1762,7 +1762,16 @@ function test_assemble_disassemble(states) load H_256_768_22.txt code_param = ldpc_init_user(H_256_768_22, modulation, mod_order, mapping); end - if strcmp(mode, "datac0") || strcmp(mode, "datac1") || strcmp(mode, "datac3") || strcmp(mode, "datac4") || strcmp(mode, "qam16c1") || strcmp(mode, "qam16c2") || strcmp(mode, "datac5") || strcmp(mode, "datac13") + if strcmp(mode, "datac13") + load H_256_512_4.mat + code_param = ldpc_init_user(H, modulation, mod_order, mapping); + code_param.data_bits_per_frame = 128; + code_param.coded_bits_per_frame = code_param.data_bits_per_frame + code_param.ldpc_parity_bits_per_frame; + code_param.coded_syms_per_frame = code_param.coded_bits_per_frame/code_param.bits_per_symbol; + end + if strcmp(mode, "datac0") || strcmp(mode, "datac1") || strcmp(mode, "datac3") ... + || strcmp(mode, "datac4") || strcmp(mode, "qam16c1") ... + || strcmp(mode, "qam16c2") || strcmp(mode, "datac5") || strcmp(mode, "datac13") printf("ldpc_data_bits_per_frame = %d\n", code_param.ldpc_data_bits_per_frame); printf("ldpc_coded_bits_per_frame = %d\n", code_param.ldpc_coded_bits_per_frame); printf("ldpc_parity_bits_per_frame = %d\n", code_param.ldpc_parity_bits_per_frame); @@ -1777,13 +1786,13 @@ function test_assemble_disassemble(states) % ------------------------------------------------------------------------------ -% fec_encode - Handle FEC encoding +% Handle FEC encoding/decoding % ------------------------------------------------------------------------------ function [frame_bits bits_per_frame] = fec_encode(states, code_param, mode, payload_bits, ... Ncodecframespermodemframe, Nbitspercodecframe) ofdm_load_const; - if strcmp(mode, "2020") + if code_param.data_bits_per_frame != code_param.ldpc_data_bits_per_frame Nunused = code_param.ldpc_data_bits_per_frame - code_param.data_bits_per_frame; frame_bits = LdpcEncode([payload_bits zeros(1,Nunused)], code_param.H_rows, code_param.P_matrix); % remove unused data bits @@ -1795,6 +1804,16 @@ function test_assemble_disassemble(states) endfunction +function [rx_bits paritychecks] = fec_decode(states, code_param, ... + payload_syms_de, payload_amps_de, ... + mean_amp, EsNo) + ofdm_load_const; + [rx_codeword paritychecks] = ldpc_dec(code_param, mx_iter=100, demod=0, dec=0, ... + payload_syms_de/mean_amp, EsNo, + payload_amps_de/mean_amp); + rx_bits = rx_codeword(1:code_param.data_bits_per_frame); +endfunction + % test function, kind of like a CRC for QPSK symbols, to compare two vectors From a6f5a14bb7e7121c47bd1b33dd0ddb7711cfbfe1 Mon Sep 17 00:00:00 2001 From: drowe67 Date: Sat, 15 Apr 2023 10:02:41 +0930 Subject: [PATCH 17/52] datac4 on spreadsheet works out UW and Np automagically --- doc/modem_codec_frame_design.ods | Bin 30369 -> 29853 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/doc/modem_codec_frame_design.ods b/doc/modem_codec_frame_design.ods index cdc4b8fca8f3084c6e0a58773e1670a4bafd0d8b..d67e6f3cc12e11bb3a8e093d387a52b357bd332f 100644 GIT binary patch delta 27864 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 From e154f2a543b91c276d63a511d980288ba03ae8c6 Mon Sep 17 00:00:00 2001 From: drowe67 Date: Sat, 15 Apr 2023 10:42:33 +0930 Subject: [PATCH 18/52] trying datac4 with at (1472,448) code ... PER=0.16 at -4dB MPP --- doc/modem_codec_frame_design.ods | Bin 29853 -> 29843 bytes octave/ofdm_lib.m | 13 ++++++++----- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/doc/modem_codec_frame_design.ods b/doc/modem_codec_frame_design.ods index d67e6f3cc12e11bb3a8e093d387a52b357bd332f..837162a2b1c4899103207f4709f45dff2c77e4af 100644 GIT binary patch delta 15567 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 H3B~^hDY&+T delta 15554 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 diff --git a/octave/ofdm_lib.m b/octave/ofdm_lib.m index e9990d3f4..6aca46fad 100644 --- a/octave/ofdm_lib.m +++ b/octave/ofdm_lib.m @@ -392,10 +392,10 @@ config.state_machine = "data"; config.amp_scale = 300E3; config.clip_gain1 = 2.2; config.clip_gain2 = 0.8; elseif strcmp(mode,"datac4") - Ns=5; config.Np=34; Tcp = 0.006; Ts = 0.016; Nc = 3; config.data_mode = "streaming"; + Ns=5; config.Np=63; Tcp = 0.006; Ts = 0.016; Nc = 3; config.data_mode = "streaming"; config.edge_pilots = 0; - config.Ntxtbits = 0; config.Nuwbits = 48; config.bad_uw_errors = 18; - config.ftwindow_width = 80; config.timing_mx_thresh = 0.25; + config.Ntxtbits = 0; config.Nuwbits = 40; config.bad_uw_errors = 15; + config.ftwindow_width = 80; config.timing_mx_thresh = 0.30; config.tx_uw = zeros(1,config.Nuwbits); config.tx_uw(1:24) = [1 1 0 0 1 0 1 0 1 1 1 1 0 0 0 0 1 1 1 1 0 0 0 0]; config.tx_uw(end-24+1:end) = [1 1 0 0 1 0 1 0 1 1 1 1 0 0 0 0 1 1 1 1 0 0 0 0]; @@ -1759,8 +1759,11 @@ function test_assemble_disassemble(states) code_param = ldpc_init_user(H, modulation, mod_order, mapping); end if strcmp(mode, "datac4") - load H_256_768_22.txt - code_param = ldpc_init_user(H_256_768_22, modulation, mod_order, mapping); + load H_1024_2048_4f + code_param = ldpc_init_user(H, modulation, mod_order, mapping); + code_param.data_bits_per_frame = 448; + code_param.coded_bits_per_frame = code_param.data_bits_per_frame + code_param.ldpc_parity_bits_per_frame; + code_param.coded_syms_per_frame = code_param.coded_bits_per_frame/code_param.bits_per_symbol; end if strcmp(mode, "datac13") load H_256_512_4.mat From 4436af19b5627ccda83c882b1790b0e85ca361d2 Mon Sep 17 00:00:00 2001 From: drowe67 Date: Sat, 15 Apr 2023 11:01:03 +0930 Subject: [PATCH 19/52] trying 4 carriers for datac4, worked better, PER=0.1 at -4dB --- doc/modem_codec_frame_design.ods | Bin 29843 -> 29872 bytes octave/ofdm_ldpc_rx.m | 2 +- octave/ofdm_lib.m | 6 +++--- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/doc/modem_codec_frame_design.ods b/doc/modem_codec_frame_design.ods index 837162a2b1c4899103207f4709f45dff2c77e4af..e6cf1c746f10c636d1db7169125bbeb68d958110 100644 GIT binary patch delta 5193 zcmY*d1ys~c_ui#kSh^*bZUjL@I;27A?xk6B3CX2HQkD{=kr0H11*Ah71f&rK0qK?y zl<))n-v9Uh=Q(HYooDX+esku`nS0NJ+ybJufcTnfm{{Zh00;nR0>8l5#<=M%h5z)- zFB(a29OMfi^NW4*zZ8-k_=gh%>iwM(xiy18(fVKQHwOI-LlSs9e22+~ z;M|@5uGCJ$GolJ&B8-zMRQ~d2DwhCfwu;VP=UVdTqSv7K(8n#V^-4YXIu|Odv|^7Uo1UZ+~oRY0Uq9GCmTMC zi$tT0---Lb9U820*SrXo>Hd*#9Z?cf95aqN==aJ~|FJOC=oOlm?>m747q&$)FG7)3 zR#;N={bX1v>rganf$*qmt2Nvpd5DNA$!4R(csgVCD)dECFGur5^U2R>KR$|%$fySH zqmDy1>23mQ>Zut$qV3hCV;e?$Ez&iTmH^F?7KV<4T4*}fy^wFcpYk9QPX-oRo;b$N zO{_L8nj!*9-ZI+3+DN-n&rVe^NhKSEf(?V{MvZ{RZYo0qDGjAHpZsOyOw-P%6_!n; z6;AJHs@(waQwH#Y;Ff!z#3G=Y=!0sm_FH$L3f%gfQ#9?t*F z1-6%C=36L69(6EQy?OMbGBLkisJSF3a;Ex;H2IXVn;mvcq@%JZYs`V{_uu`am5=wUu`l=3LW-c zALu>fz>XH|(C1auI^p6*Fn5`0z16SiU7b8FiAe4zfbQ9jr6j05_tZ6Q5B?(NSMS`f zAMnx(cKZ9CybkxPs(!1s3q+}f!A0#QeDnThFBFdQ7Z>r-UNWm1F{PGFG`2EnDRoig z_twCw2ZRB?gLjBNz29JL&ZKyfR^7Y7Tus^@qLZFSCeY@5 zz&4{ND!cn2*^-DV8VG;eI`z=MgQ0-8bhG+uOx6OODIOl%On7KEbO`!2(%j)_r6y2S zX?t3i$t+6gya4MyLm1aTp=Mc}G2$wdVCtcDf2nRJMoAAOcYVW8WT@ap+({oFz7x0I zAGQ)DU+A;s+UJ5K#sc!cs)a;^p)pMY1qviX;65W{aa_#f*sYi|%p)`8kSuH1aP~d) z78^vk78te^a{#~^#2gHtJ+d4FT_Bca{Wby(k7SOPiVuwtT3L7WxoDX|>ozT^ASF`V zTgWLVvxPl=&y#FP(qDRZ=N0~43cR&1sC+y{!dUFs$fQJU6>ODA1IAa?5F&C?Mt?eZ_jY#8Qgd*vb?zV=MxE zG*rY!wffR-5L=MHZ0*ckAa(Vp9WIWM04P-U&?|2>Z1sIoJpbb%BK$X%)T}q?;l{ze z0h2%~8bdxu|gaavsEp8%0DERRlvp8t2hqN~~Cx8c5CIcnyRqg_W`g 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 >>Js|%MWJz zM|AmTi+_chB>mQZRf)F(&HtJrvJy^v`@=yv9mWR=f;s0NaB=VvIS|WM9SQ&4( X@b8lV|L;3D-a69Fivfq*{g(U>!~l4` delta 5162 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 Date: Sun, 16 Apr 2023 09:22:18 +0930 Subject: [PATCH 20/52] helper function and notes for setting UW thresholds --- octave/ofdm_lib.m | 31 +++++++++++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/octave/ofdm_lib.m b/octave/ofdm_lib.m index 9e3f12cbc..24b125857 100644 --- a/octave/ofdm_lib.m +++ b/octave/ofdm_lib.m @@ -138,7 +138,10 @@ if bps == 4 tx_uw_syms = [tx_uw_syms qam16_mod(states.qam16, states.tx_uw(b:b+bps-1))]; end end states.tx_uw_syms = tx_uw_syms; - % if the UW has this many errors it is "bad", the binomal cdf can be used to set this: + + % if the UW has this many errors it is "bad", the binomal cdf can be used to + % set this with the ofdm_determine_bad_uw_errors() function below + % % Nuw=12; plot(0:Nuw, binocdf(0:Nuw,Nuw,0.05)); hold on; plot(binocdf(0:Nuw,Nuw,0.5)); hold off; states.bad_uw_errors = bad_uw_errors; @@ -1909,8 +1912,32 @@ function test_assemble_disassemble(states) endfunction +% Helper function to help design UW error thresholds, in particular for raw +% data modes. See also https://www.rowetel.com/wordpress/?p=7467 +function ofdm_determine_bad_uw_errors(Nuw) + figure(1); clf; + + % Ideally the 10% and 50% BER cruves are a long way apart + + plot(0:Nuw, binocdf(0:Nuw,Nuw,0.1),';BER=0.1;'); hold on; + plot(binocdf(0:Nuw,Nuw,0.5),';BER=0.5;'); + + % Suggested threshold for raw data modes is the 5% probability + % level for the 50% BER curve. The pre/post-amble has a low chance + % of failure. If it does make an error, then we will have random + % bits presented as the UW (50% BER in UW). This threshold means + % there is only a 5% case of random bits being accepted as a valid UW + + bad_uw_errors = max(find(binocdf(0:Nuw,Nuw,0.5) <= 0.05))+1; + plot([bad_uw_errors bad_uw_errors],[0 1],';bad uw errors;'); hold off; grid + + xlabel('bits'); + printf("for Nuw = %d, suggest bad_uw_errors = %d\n", Nuw, bad_uw_errors); +end -% returns level threshold such that threshold_cdf of the tx magnitudes are beneath that level +% Returns level threshold such that threshold_cdf of the tx magnitudes are +% beneath that level. Helper function that can be used to design +% the clipper level. See also https://www.rowetel.com/?p=7596 function threshold_level = ofdm_determine_clip_threshold(tx, threshold_cdf) Nsteps = 25; mx = max(abs(tx)); From bbf491ea90f05d6f9a1026e2262412ddfa404055 Mon Sep 17 00:00:00 2001 From: drowe67 Date: Thu, 20 Apr 2023 11:35:28 +0930 Subject: [PATCH 21/52] zero stuffing: comments around use, and unittest at the ldpcut.m level, and ctest --- CMakeLists.txt | 7 ++++++- octave/ldpc.m | 16 ++++++++++++---- octave/ldpcut.m | 44 +++++++++++++++++++++++++++++++++++++------- octave/ofdm_lib.m | 15 ++++++++------- 4 files changed, 63 insertions(+), 19 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 459294813..c1d969daf 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -356,9 +356,13 @@ endif() set_tests_properties(test_fdmdv_48to8 PROPERTIES PASS_REGULAR_EXPRESSION "PASS") add_test(NAME test_CML_ldpcut - COMMAND sh -c "cd ${CMAKE_CURRENT_SOURCE_DIR}/octave; SHORT_VERSION_FOR_CTEST=1 octave-cli -qf ldpcut.m") + COMMAND sh -c "cd ${CMAKE_CURRENT_SOURCE_DIR}/octave; CTEST_SINGLE=1 octave-cli -qf ldpcut.m") set_tests_properties(test_CML_ldpcut PROPERTIES PASS_REGULAR_EXPRESSION "Nerr: 0") + add_test(NAME test_CML_ldpcut_zero_stuffing + COMMAND sh -c "cd ${CMAKE_CURRENT_SOURCE_DIR}/octave; CTEST_ZERO_STUFFING=1 octave-cli -qf ldpcut.m") + set_tests_properties(test_CML_ldpcut_zero_stuffing PROPERTIES PASS_REGULAR_EXPRESSION "Ferrs: 0") + # Golay (23,11) unit tests add_test(NAME test_golay23 COMMAND sh -c "${CMAKE_CURRENT_BINARY_DIR}/unittest/golay23") add_test(NAME test_golay23_runtime_tables COMMAND sh -c "${CMAKE_CURRENT_BINARY_DIR}/unittest/golay23_runtime_tables") @@ -1324,6 +1328,7 @@ endif(NOT APPLE) # Set common properties for tests that need Octave/CML set_tests_properties( test_CML_ldpcut + test_CML_ldpcut_zero_stuffing test_OFDM_modem_octave_port test_OFDM_modem_octave_port_Nc_31 test_OFDM_modem_octave_datac0_mpp_coded diff --git a/octave/ldpc.m b/octave/ldpc.m index 0abb2892e..b72351914 100644 --- a/octave/ldpc.m +++ b/octave/ldpc.m @@ -96,7 +96,7 @@ function init_cml() code_param.ldpc_parity_bits_per_frame = framesize - code_param.ldpc_data_bits_per_frame; code_param.ldpc_coded_bits_per_frame = framesize; - % these variables support underfilling frame + % these variables support zero stuffing (not using all data bits to lower code rate) code_param.data_bits_per_frame = code_param.ldpc_data_bits_per_frame; code_param.coded_bits_per_frame = code_param.ldpc_coded_bits_per_frame; code_param.coded_syms_per_frame = code_param.coded_bits_per_frame/code_param.bits_per_symbol; @@ -104,15 +104,23 @@ function init_cml() function [codeword s] = ldpc_enc(data, code_param) + if code_param.data_bits_per_frame != code_param.ldpc_data_bits_per_frame + % optionally lower the code rate by "zero stuffing" - setting Nunused data bits to 0 + Nunused = code_param.ldpc_data_bits_per_frame - code_param.data_bits_per_frame; + codeword = LdpcEncode([data zeros(1,Nunused)], code_param.H_rows, code_param.P_matrix); + % remove unused data bits from codeword, as they are known to the receiver and don't need to be transmitted + codeword = [ codeword(1:code_param.data_bits_per_frame) codeword(code_param.ldpc_data_bits_per_frame+1:end) ]; + else codeword = LdpcEncode( data, code_param.H_rows, code_param.P_matrix ); - s = Modulate( codeword, code_param.S_matrix ); + end + s = Modulate( codeword, code_param.S_matrix ); endfunction function [detected_data paritychecks] = ldpc_dec(code_param, max_iterations, ... demod_type, decoder_type, r, ... EsNo, fading) - % handle case where we don't use all data bits + % handle "zero stuffing" case where we don't use all data bits Nunused = code_param.ldpc_data_bits_per_frame - code_param.data_bits_per_frame; symbol_likelihood = Demod2D( r, code_param.S_matrix, EsNo, fading); @@ -124,7 +132,7 @@ function init_cml() input_decoder_c = bit_likelihood(1:(code_param.ldpc_coded_bits_per_frame-Nunused)); - % handle case where we don't use all data bits + % insert "very likley" zero LLRs for unsed data bits (in zero stuffing case) input_decoder_c = [input_decoder_c(1:code_param.data_bits_per_frame) ... -100*ones(1,Nunused) ... input_decoder_c(code_param.data_bits_per_frame+1:end)]; diff --git a/octave/ldpcut.m b/octave/ldpcut.m index 7e246a9f5..d1ce52a70 100644 --- a/octave/ldpcut.m +++ b/octave/ldpcut.m @@ -48,6 +48,18 @@ [code_param framesize rate] = ldpc_init_user(HRA, modulation, mod_order, mapping); end + % optional zero stuffing + if isfield(sim_in, "data_bits_per_frame") + code_param.data_bits_per_frame = sim_in.data_bits_per_frame; + code_param.coded_bits_per_frame = code_param.data_bits_per_frame + code_param.ldpc_parity_bits_per_frame; + code_param.coded_syms_per_frame = code_param.coded_bits_per_frame/code_param.bits_per_symbol; + rate = code_param.data_bits_per_frame/code_param.coded_bits_per_frame; + printf("data_bits_per_frame = %d\n", code_param.data_bits_per_frame); + printf("coded_bits_per_frame = %d\n", code_param.coded_bits_per_frame); + printf("coded_syms_per_frame = %d\n", code_param.coded_syms_per_frame); + printf("rate: %f\n",rate); + end + % ---------------------------------- % run simulation at each Eb/No point % ---------------------------------- @@ -149,7 +161,7 @@ % 1/ Simplest possible one frame simulation % --------------------------------------------------------------------------------- -function test1_single(code="wimax") +function test1_single(code="wimax", data_bits_per_frame) printf("\nTest 1:Single -----------------------------------\n"); mod_order = 4; @@ -163,16 +175,25 @@ function test1_single(code="wimax") if strcmp(code,'wimax') framesize = 576*2; rate = 0.5; end if strcmp(code,'dvbs2') framesize = 16200; rate = 0.6; end code_param = ldpc_init_builtin(code, rate, framesize, modulation, mod_order, mapping); - + + % optional zero stuffing + if nargin == 2 + code_param.data_bits_per_frame = data_bits_per_frame; + code_param.coded_bits_per_frame = code_param.data_bits_per_frame + code_param.ldpc_parity_bits_per_frame; + code_param.coded_syms_per_frame = code_param.coded_bits_per_frame/code_param.bits_per_symbol; + framesize = code_param.coded_bits_per_frame; + end + % find out what rate we actually obtained ... - rate = code_param.ldpc_data_bits_per_frame/code_param.ldpc_coded_bits_per_frame; + rate = code_param.data_bits_per_frame/code_param.coded_bits_per_frame; printf("Ndata_bits: %d Nparity_bits: %d Ncodeword_bits: %d rate: %3.2f\n", - code_param.ldpc_data_bits_per_frame, code_param.ldpc_parity_bits_per_frame, code_param.ldpc_coded_bits_per_frame, rate); + code_param.data_bits_per_frame, code_param.ldpc_parity_bits_per_frame, + code_param.coded_bits_per_frame, rate); % decoder needs an estimated channel EsNo (linear ratio, not dB) EsNo = 10; - tx_bits = round(rand(1, code_param.ldpc_data_bits_per_frame)); + tx_bits = round(rand(1, code_param.data_bits_per_frame)); [tx_codeword, qpsk_symbols] = ldpc_enc(tx_bits, code_param); rx_codeword = ldpc_dec(code_param, max_iterations, demod_type, decoder_type, qpsk_symbols, EsNo, ones(1,length(qpsk_symbols))); @@ -186,7 +207,7 @@ function test1_single(code="wimax") % 2/ Run a bunch of trials at just one EsNo point % --------------------------------------------------------------------------------- -function test2_multiple(code, Ntrials=100) +function test2_multiple(code, Ntrials=100, data_bits_per_frame) printf("\nTest 2: Multiple: %s ----------------------------\n", code); % these are inputs for Wimax mode, e.g. framesize defines code used @@ -195,6 +216,9 @@ function test2_multiple(code, Ntrials=100) sim_in.verbose = 2; sim_in.Ntrials = Ntrials; sim_in.EbNodBvec = 3; + if nargin == 3 + sim_in.data_bits_per_frame = data_bits_per_frame; + end run_simulation(sim_in); end @@ -241,11 +265,17 @@ function test3_curves(code,fg=1,Ntrials=100) init_cml(); -if getenv("SHORT_VERSION_FOR_CTEST") +% Ctest kicks off these tests using env variables +if getenv("CTEST_SINGLE") test1_single return; end +if getenv("CTEST_ZERO_STUFFING") + test2_multiple("wimax",10,576); + return; +end +% Uncomment and try some of these tests if you like .... %test3_curves("H_1024_2048_4f.mat",1) %test1_single("dvbs2") %test3_curves("dvbs2",1,10) diff --git a/octave/ofdm_lib.m b/octave/ofdm_lib.m index 24b125857..76a2c1812 100644 --- a/octave/ofdm_lib.m +++ b/octave/ofdm_lib.m @@ -432,7 +432,7 @@ %------------------------------------------------------------------------------ -% print_config - utility function to use ascsii-art to describe the modem frame +% print_config - utility function to use ascii-art to describe the modem frame %------------------------------------------------------------------------------ function print_config(states) @@ -1795,13 +1795,13 @@ function test_assemble_disassemble(states) % Handle FEC encoding/decoding % ------------------------------------------------------------------------------ -function [frame_bits bits_per_frame] = fec_encode(states, code_param, mode, payload_bits, ... - Ncodecframespermodemframe, Nbitspercodecframe) +function [frame_bits bits_per_frame] = fec_encode(states, code_param, mode, payload_bits) ofdm_load_const; if code_param.data_bits_per_frame != code_param.ldpc_data_bits_per_frame + % optionally lower the code rate by "zero stuffing" - setting Nunused data bits to 0 Nunused = code_param.ldpc_data_bits_per_frame - code_param.data_bits_per_frame; frame_bits = LdpcEncode([payload_bits zeros(1,Nunused)], code_param.H_rows, code_param.P_matrix); - % remove unused data bits + % remove unused data bits from codeword, as they are known to the receiver and don't need to be transmitted frame_bits = [ frame_bits(1:code_param.data_bits_per_frame) frame_bits(code_param.ldpc_data_bits_per_frame+1:end) ]; else frame_bits = LdpcEncode(payload_bits, code_param.H_rows, code_param.P_matrix); @@ -1811,9 +1811,10 @@ function test_assemble_disassemble(states) endfunction function [rx_bits paritychecks] = fec_decode(states, code_param, ... - payload_syms_de, payload_amps_de, ... - mean_amp, EsNo) + payload_syms_de, payload_amps_de, ... + mean_amp, EsNo) ofdm_load_const; + % note ldpc_dec() handles optional lower code rate zero-stuffing [rx_codeword paritychecks] = ldpc_dec(code_param, mx_iter=100, demod=0, dec=0, ... payload_syms_de/mean_amp, EsNo, payload_amps_de/mean_amp); @@ -1917,7 +1918,7 @@ function test_assemble_disassemble(states) function ofdm_determine_bad_uw_errors(Nuw) figure(1); clf; - % Ideally the 10% and 50% BER cruves are a long way apart + % Ideally the 10% and 50% BER curves are a long way apart plot(0:Nuw, binocdf(0:Nuw,Nuw,0.1),';BER=0.1;'); hold on; plot(binocdf(0:Nuw,Nuw,0.5),';BER=0.5;'); From b75e279d733ad647e34417b4d298030794d76eec Mon Sep 17 00:00:00 2001 From: drowe67 Date: Thu, 20 Apr 2023 12:07:45 +0930 Subject: [PATCH 22/52] refactored ofdm_lib into smaller files --- octave/ofdm_helper.m | 272 +++++++++++++++ octave/ofdm_lib.m | 776 +------------------------------------------ octave/ofdm_mode.m | 247 ++++++++++++++ octave/ofdm_state.m | 271 +++++++++++++++ src/ofdm_mode.c | 15 +- 5 files changed, 807 insertions(+), 774 deletions(-) create mode 100644 octave/ofdm_helper.m create mode 100644 octave/ofdm_mode.m create mode 100644 octave/ofdm_state.m diff --git a/octave/ofdm_helper.m b/octave/ofdm_helper.m new file mode 100644 index 000000000..b34ec2390 --- /dev/null +++ b/octave/ofdm_helper.m @@ -0,0 +1,272 @@ +% ofdm_helper.m +% +% Misc functions that are used to support OFDM modem development, that +% aren't required for modem operation + +1; + +%------------------------------------------------------------------------------ +% print_config - utility function to use ascii-art to describe the modem frame +%------------------------------------------------------------------------------ + +function print_config(states) + ofdm_load_const; + + % ASCII-art packet visualisation + s=1; u=1; Nuwsyms=length(uw_ind_sym); + cr = 1:Nc+2; + for f=1:Np + for r=1:Ns + for c=cr + if r == 1 + if (c==1) && states.edge_pilots + sym="P"; + elseif (c==Nc+1) && states.edge_pilots + sym="P"; + elseif c>1 && c <=(Nc+1) + sym="P"; + else + sym=" "; + end + elseif c>1 && c <=(Nc+1) + sym="."; + if (u <= Nuwsyms) && (s == uw_ind_sym(u)) sym="U"; u++; end + s++; + else + sym=" "; + end + printf("%s",sym); + end + printf("\n"); + end + end + + printf("Nc=%d Ts=%4.3f Tcp=%4.3f Ns: %d Np: %d\n", Nc, 1/Rs, Tcp, Ns, Np); + printf("Nsymperframe: %d Nbitsperpacket: %d Nsamperframe: %d Ntxtbits: %d Nuwbits: %d Nuwframes: %d\n", + Ns*Nc, Nbitsperpacket, Nsamperframe, Ntxtbits, Nuwbits, Nuwframes); + printf("uncoded bits/s: %4.1f\n", Nbitsperpacket*Fs/(Np*Nsamperframe)); +end + +%----------------------------------------------------------------------- +% create_ldpc_test_frame - generate a test frame of bits +%----------------------------------------------------------------------- + +function [tx_bits payload_data_bits codeword] = create_ldpc_test_frame(states, coded_frame=1) + ofdm_load_const; + ldpc; + gp_interleaver; + + if coded_frame + % Set up LDPC code + + mod_order = 4; bps = 2; modulation = 'QPSK'; mapping = 'gray'; + + init_cml(); % TODO: make this path sensible and portable + load HRA_112_112.txt + [code_param framesize rate] = ldpc_init_user(HRA_112_112, modulation, mod_order, mapping); + assert(Nbitsperframe == (code_param.coded_bits_per_frame + Nuwbits + Ntxtbits)); + + payload_data_bits = round(ofdm_rand(code_param.data_bits_per_frame)/32767); + codeword = LdpcEncode(payload_data_bits, code_param.H_rows, code_param.P_matrix); + Nsymbolsperframe = length(codeword)/bps; + + % need all these steps to get actual raw codeword bits at demod .. + + tx_symbols = []; + for s=1:Nsymbolsperframe + tx_symbols = [tx_symbols qpsk_mod( codeword(2*(s-1)+1:2*s) )]; + end + + tx_symbols = gp_interleave(tx_symbols); + + codeword_raw = []; + for s=1:Nsymbolsperframe + codeword_raw = [codeword_raw qpsk_demod(tx_symbols(s))]; + end + else + codeword_raw = round(ofdm_rand(Nbitsperpacket-(Nuwbits+Ntxtbits))/32767); + end + + % insert UW and txt bits + + tx_bits = assemble_modem_packet(states, codeword_raw, zeros(1,Ntxtbits)); + assert(Nbitsperpacket == length(tx_bits)); + +endfunction + +% automated test + +function test_assemble_disassemble(states) + ofdm_load_const; + + Nsymsperpacket = Nbitsperpacket/bps; + Ndatabitsperpacket = Nbitsperpacket-(Nuwbits+Ntxtbits); + Ndatasymsperpacket = Ndatabitsperpacket/bps; + codeword_bits = round(ofdm_rand(Ndatabitsperpacket)/32767); + tx_bits = assemble_modem_packet(states, codeword_bits, zeros(1,Ntxtbits)); + + tx_syms = zeros(1,Nsymsperpacket); + for s=1:Nsymsperpacket + if bps == 2 + tx_syms(s) = qpsk_mod(tx_bits(bps*(s-1)+1:bps*s)); + elseif bps == 4 + tx_syms(s) = qam16_mod(states.qam16,tx_bits(bps*(s-1)+1:bps*s)); + end + end + codeword_syms = zeros(1,Ndatasymsperpacket); + for s=1:Ndatasymsperpacket + if bps == 2 + codeword_syms(s) = qpsk_mod(codeword_bits(bps*(s-1)+1:bps*s)); + elseif bps == 4 + codeword_syms(s) = qam16_mod(states.qam16,codeword_bits(bps*(s-1)+1:bps*s)); + end + end + + [rx_uw rx_codeword_syms payload_amps txt_bits] = disassemble_modem_packet(states, tx_syms, ones(1,Nsymsperpacket)); + assert(rx_uw == states.tx_uw); + Ndatasymsperframe = (Nbitsperpacket-(Nuwbits+Ntxtbits))/bps; + assert(codeword_syms == rx_codeword_syms); +endfunction + +% test function, kind of like a CRC for QPSK symbols, to compare two vectors + +function acc = test_acc(v) + sre = 0; sim = 0; + for i=1:length(v) + x = v(i); + re = round(real(x)); im = round(imag(x)); + sre += re; sim += im; + %printf("%d %10f %10f %10f %10f\n", i, re, im, sre, sim); + end + acc = sre + j*sim; +end + + +% Save test bits frame to a text file in the form of a C array +% +% usage: +% ofdm_lib; test_bits_ofdm_file +% + +function test_bits_ofdm_file + Ts = 0.018; Tcp = 0.002; Rs = 1/Ts; bps = 2; Nc = 17; Ns = 8; + states = ofdm_init(bps, Rs, Tcp, Ns, Nc); + [test_bits_ofdm payload_data_bits codeword] = create_ldpc_test_frame(states); + printf("%d test bits\n", length(test_bits_ofdm)); + + f=fopen("../src/test_bits_ofdm.h","wt"); + fprintf(f,"/* Generated by test_bits_ofdm_file() Octave function */\n\n"); + fprintf(f,"const int test_bits_ofdm[]={\n"); + for m=1:length(test_bits_ofdm)-1 + fprintf(f," %d,\n",test_bits_ofdm(m)); + endfor + fprintf(f," %d\n};\n",test_bits_ofdm(end)); + + fprintf(f,"\nconst int payload_data_bits[]={\n"); + for m=1:length(payload_data_bits)-1 + fprintf(f," %d,\n",payload_data_bits(m)); + endfor + fprintf(f," %d\n};\n",payload_data_bits(end)); + + fprintf(f,"\nconst int test_codeword[]={\n"); + for m=1:length(codeword)-1 + fprintf(f," %d,\n",codeword(m)); + endfor + fprintf(f," %d\n};\n",codeword(end)); + + fclose(f); + +endfunction + + +% Get rid of nasty unfiltered stuff either side of OFDM signal +% This may need to be tweaked, or better yet made a function of Nc, if Nc changes +% +% usage: +% ofdm_lib; make_ofdm_bpf(1); + +function bpf_coeff = make_ofdm_bpf(write_c_header_file) + filt_n = 100; + Fs = 8000; + + bpf_coeff = fir2(filt_n,[0 900 1000 2000 2100 4000]/(Fs/2),[0.001 0.001 1 1 0.001 0.001]); + + if write_c_header_file + figure(1) + clf; + h = freqz(bpf_coeff,1,Fs/2); + plot(20*log10(abs(h))) + grid minor + + % save coeffs to a C header file + + f=fopen("../src/ofdm_bpf_coeff.h","wt"); + fprintf(f,"/* 1000 - 2000 Hz FIR filter coeffs */\n"); + fprintf(f,"/* Generated by make_ofdm_bpf() in ofdm_lib.m */\n"); + + fprintf(f,"\n#define OFDM_BPF_N %d\n\n", filt_n); + + fprintf(f,"float ofdm_bpf_coeff[]={\n"); + for r=1:filt_n + if r < filt_n + fprintf(f, " %f,\n", bpf_coeff(r)); + else + fprintf(f, " %f\n};", bpf_coeff(r)); + end + end + fclose(f); + end + +endfunction + +% Helper function to help design UW error thresholds, in particular for raw +% data modes. See also https://www.rowetel.com/wordpress/?p=7467 +function ofdm_determine_bad_uw_errors(Nuw) + figure(1); clf; + + % Ideally the 10% and 50% BER curves are a long way apart + + plot(0:Nuw, binocdf(0:Nuw,Nuw,0.1),';BER=0.1;'); hold on; + plot(binocdf(0:Nuw,Nuw,0.5),';BER=0.5;'); + + % Suggested threshold for raw data modes is the 5% probability + % level for the 50% BER curve. The pre/post-amble has a low chance + % of failure. If it does make an error, then we will have random + % bits presented as the UW (50% BER in UW). This threshold means + % there is only a 5% case of random bits being accepted as a valid UW + + bad_uw_errors = max(find(binocdf(0:Nuw,Nuw,0.5) <= 0.05))+1; + plot([bad_uw_errors bad_uw_errors],[0 1],';bad uw errors;'); hold off; grid + + xlabel('bits'); + printf("for Nuw = %d, suggest bad_uw_errors = %d\n", Nuw, bad_uw_errors); +end + +% Returns level threshold such that threshold_cdf of the tx magnitudes are +% beneath that level. Helper function that can be used to design +% the clipper level. See also https://www.rowetel.com/?p=7596 +function threshold_level = ofdm_determine_clip_threshold(tx, threshold_cdf) + Nsteps = 25; + mx = max(abs(tx)); + cdf = empirical_cdf(mx*(1:Nsteps)/Nsteps,abs(tx)); + threshold_level = find(cdf >= threshold_cdf)(1)*mx/25; + printf("threshold_cdf: %f threshold_level: %f\n", threshold_cdf, threshold_level); + figure(1); clf; [hh nn] = hist(abs(tx),Nsteps,1); + plotyy(nn,hh,mx*(1:Nsteps)/Nsteps,cdf); title('PDF and CDF Estimates'); grid; +end + + +% helper function that adds channel simulation and ensures we don't saturate int16 output samples +function [rx_real rx] = ofdm_channel(states, tx, SNR3kdB, channel, freq_offset_Hz) + [rx_real rx sigma] = channel_simulate(states.Fs, SNR3kdB, freq_offset_Hz, channel, tx, states.verbose); + + % multipath models can lead to clipping of int16 samples + num_clipped = length(find(abs(rx_real>32767))); + while num_clipped/length(rx_real) > 0.001 + rx_real /= 2; + num_clipped = length(find(abs(rx_real>32767))); + printf("WARNING: output samples clipped, reducing level\n") + end +endfunction + + diff --git a/octave/ofdm_lib.m b/octave/ofdm_lib.m index 76a2c1812..4289cc40f 100644 --- a/octave/ofdm_lib.m +++ b/octave/ofdm_lib.m @@ -8,6 +8,9 @@ 1; qam16; esno_est; +ofdm_mode; +ofdm_state; +ofdm_helper; %------------------------------------------------------------- % ofdm_init @@ -287,192 +290,6 @@ test_assemble_disassemble(states); endfunction - -%------------------------------------------------------------------------------ -% ofdm_init_mode - Helper function to set up modems for various FreeDV modes, -% and parse mode string. -%------------------------------------------------------------------------------ - -function config = ofdm_init_mode(mode="700D") - % defaults for 700D - - Tcp = 0.002; - Ns = 8; - Ts = 0.018; - Nc = 17; - config.bps = 2; - config.Np = 1; - config.Ntxtbits = 4; - config.Nuwbits = 5*config.bps; - config.ftwindow_width = 32; - config.timing_mx_thresh = 0.35; - config.bad_uw_errors = 3; - config.amp_scale = 245E3; - config.amp_est_mode = 0; - config.EsNo_est_all_symbols = 1; - config.EsNodB = 3; - config.state_machine = "voice1"; - config.edge_pilots = 1; - config.clip_gain1 = 2.5; - config.clip_gain2 = 0.8; - config.foff_limiter = 0; - config.txbpf_width_Hz = 2000; - config.data_mode = ""; - - if strcmp(mode,"700D") || strcmp(mode,"700d") - % defaults above - elseif strcmp(mode,"700E") || strcmp(mode,"700e") - Ts = 0.014; Tcp=0.006; Nc = 21; Ns=4; - config.edge_pilots = 0; config.state_machine = "voice2"; - config.Nuwbits = 12; config.bad_uw_errors = 3; config.Ntxtbits = 2; - config.amp_est_mode = 1; config.ftwindow_width = 80; - config.amp_scale = 155E3; config.clip_gain1 = 3; config.clip_gain2 = 0.8; - config.foff_limiter = 1; - elseif strcmp(mode,"2020") - Ts = 0.0205; Nc = 31; - config.amp_scale = 167E3; config.clip_gain1 = 2.5; config.clip_gain2 = 0.8; - elseif strcmp(mode,"2020B") - Ts = 0.014; Tcp = 0.004; Nc = 29; Ns=5; - config.Ntxtbits = 4; config.Nuwbits = 8*2; config.bad_uw_errors = 5; - config.amp_scale = 130E3; config.clip_gain1 = 2.5; config.clip_gain2 = 0.8; - config.edge_pilots = 0; config.state_machine = "voice2"; - config.foff_limiter = 1; config.ftwindow_width = 64; - config.txbpf_width_Hz = 2200; - elseif strcmp(mode,"qam16c1") - Ns=5; config.Np=5; Tcp = 0.004; Ts = 0.016; Nc = 33; config.data_mode = "streaming"; - config.bps=4; config.Ntxtbits = 0; config.Nuwbits = 15*4; config.bad_uw_errors = 5; - config.state_machine = "data"; - config.ftwindow_width = 32; config.amp_scale = 132E3; - config.EsNo_est_all_symbols = 0; config.amp_est_mode = 1; config.EsNodB = 10; - elseif strcmp(mode,"qam16c2") - Ns=5; config.Np=31; Tcp = 0.004; Ts = 0.016; Nc = 33; config.data_mode = "streaming"; - config.bps=4; config.Ntxtbits = 0; config.Nuwbits = 42*4; config.bad_uw_errors = 15; - config.ftwindow_width = 80; config.amp_scale = 135E3; config.state_machine = "data"; - config.EsNo_est_all_symbols = 0; config.amp_est_mode = 1; config.EsNodB = 10; - config.tx_uw = zeros(1,config.Nuwbits = 42*4); - config.tx_uw(1:24) = [1 1 0 0 1 0 1 0 1 1 1 1 0 0 0 0 1 1 1 1 0 0 0 0]; - config.tx_uw(end-24+1:end) = [1 1 0 0 1 0 1 0 1 1 1 1 0 0 0 0 1 1 1 1 0 0 0 0]; - elseif strcmp(mode,"datac0") - Ns=5; config.Np=4; Tcp = 0.006; Ts = 0.016; Nc = 9; config.data_mode = "streaming"; - config.Ntxtbits = 0; config.Nuwbits = 32; config.bad_uw_errors = 9; - config.state_machine = "data"; - config.ftwindow_width = 80; config.amp_est_mode = 1; config.EsNodB = 3; - config.edge_pilots = 0; config.timing_mx_thresh = 0.08; - config.tx_uw = zeros(1,config.Nuwbits); - config.tx_uw(1:16) = [1 1 0 0 1 0 1 0 1 1 1 1 0 0 0 0]; - config.amp_scale = 300E3; config.clip_gain1 = 2.2; config.clip_gain2 = 0.85; - elseif strcmp(mode,"datac5") - Ns=5; config.Np=58; Tcp = 0.004; Ts = 0.016; Nc = 35; config.data_mode = "streaming"; - config.Ntxtbits = 0; config.Nuwbits = 40; config.bad_uw_errors = 14; - config.state_machine = "data"; - config.ftwindow_width = 80; config.amp_est_mode = 1; config.EsNodB = 3; - config.amp_scale = 145E3; config.clip_gain1 = 2.7; config.clip_gain2 = 0.8; - config.edge_pilots = 0; config.timing_mx_thresh = 0.10; - config.tx_uw = zeros(1,config.Nuwbits); - config.tx_uw(1:16) = [1 1 0 0 1 0 1 0 1 1 1 1 0 0 0 0]; - elseif strcmp(mode,"datac1") - Ns=5; config.Np=38; Tcp = 0.006; Ts = 0.016; Nc = 27; config.data_mode = "streaming"; - config.Ntxtbits = 0; config.Nuwbits = 16; config.bad_uw_errors = 6; - config.state_machine = "data"; - config.ftwindow_width = 80; config.amp_est_mode = 1; config.EsNodB = 3; - % clipper/compression adjustment: - % 1. With clipper off increase amp_scale until peak just hit 16384 - % 2. With clipper on increase clip_gain1 until about 30% clipped - % 3. BPF will drop level beneath 16384, adjust clip_gain2 to just hit 16384 peak again - % 4. Clipped/unclipped operating point for same PER should be about 1dB apart - config.amp_scale = 145E3; config.clip_gain1 = 2.7; config.clip_gain2 = 0.8; - config.edge_pilots = 0; config.timing_mx_thresh = 0.10; - config.tx_uw = [1 1 0 0 1 0 1 0 1 1 1 1 0 0 0 0]; - elseif strcmp(mode,"datac3") - Ns=5; config.Np=29; Tcp = 0.006; Ts = 0.016; Nc = 9; config.data_mode = "streaming"; - config.edge_pilots = 0; - config.Ntxtbits = 0; config.Nuwbits = 40; config.bad_uw_errors = 10; - config.ftwindow_width = 80; config.timing_mx_thresh = 0.10; - config.tx_uw = zeros(1,config.Nuwbits); - config.tx_uw(1:24) = [1 1 0 0 1 0 1 0 1 1 1 1 0 0 0 0 1 1 1 1 0 0 0 0]; - config.tx_uw(end-24+1:end) = [1 1 0 0 1 0 1 0 1 1 1 1 0 0 0 0 1 1 1 1 0 0 0 0]; - config.amp_est_mode = 1; config.EsNodB = 3; - config.state_machine = "data"; - config.amp_scale = 300E3; config.clip_gain1 = 2.2; config.clip_gain2 = 0.8; - elseif strcmp(mode,"datac4") - Ns=5; config.Np=47; Tcp = 0.006; Ts = 0.016; Nc = 4; config.data_mode = "streaming"; - config.edge_pilots = 0; - config.Ntxtbits = 0; config.Nuwbits = 32; config.bad_uw_errors = 12; - config.ftwindow_width = 80; config.timing_mx_thresh = 0.25; - config.tx_uw = zeros(1,config.Nuwbits); - config.tx_uw(1:24) = [1 1 0 0 1 0 1 0 1 1 1 1 0 0 0 0 1 1 1 1 0 0 0 0]; - config.tx_uw(end-24+1:end) = [1 1 0 0 1 0 1 0 1 1 1 1 0 0 0 0 1 1 1 1 0 0 0 0]; - config.amp_est_mode = 1; config.EsNodB = 3; - config.state_machine = "data"; - config.amp_scale = 300*2.3E3; config.clip_gain1 = 1.5; config.clip_gain2 = 0.8; - elseif strcmp(mode,"datac13") - Ns=5; config.Np=18; Tcp = 0.006; Ts = 0.016; Nc = 3; config.data_mode = "streaming"; - config.edge_pilots = 0; - config.Ntxtbits = 0; config.Nuwbits = 48; config.bad_uw_errors = 18; - config.ftwindow_width = 80; config.timing_mx_thresh = 0.25; - config.tx_uw = zeros(1,config.Nuwbits); - config.tx_uw(1:24) = [1 1 0 0 1 0 1 0 1 1 1 1 0 0 0 0 1 1 1 1 0 0 0 0]; - config.tx_uw(end-24+1:end) = [1 1 0 0 1 0 1 0 1 1 1 1 0 0 0 0 1 1 1 1 0 0 0 0]; - config.amp_est_mode = 1; config.EsNodB = 3; - config.state_machine = "data"; - config.amp_scale = 300*2.3E3; config.clip_gain1 = 1.5; config.clip_gain2 = 0.8; - elseif strcmp(mode,"1") - Ns=5; config.Np=10; Tcp=0; Tframe = 0.1; Ts = Tframe/Ns; Nc = 1; - else - % try to parse mode string for user defined mode - vec = sscanf(mode, "Ts=%f Nc=%d Ncp=%f"); - Ts=vec(1); Nc=vec(2); Ncp=vec(3); - end - Rs=1/Ts; - config.Rs = Rs; config.Tcp = Tcp; config.Ns = Ns; config.Nc = Nc; - if !isfield(config,"tx_uw") - config.tx_uw = zeros(1,config.Nuwbits); - end -end - - -%------------------------------------------------------------------------------ -% print_config - utility function to use ascii-art to describe the modem frame -%------------------------------------------------------------------------------ - -function print_config(states) - ofdm_load_const; - - % ASCII-art packet visualisation - s=1; u=1; Nuwsyms=length(uw_ind_sym); - cr = 1:Nc+2; - for f=1:Np - for r=1:Ns - for c=cr - if r == 1 - if (c==1) && states.edge_pilots - sym="P"; - elseif (c==Nc+1) && states.edge_pilots - sym="P"; - elseif c>1 && c <=(Nc+1) - sym="P"; - else - sym=" "; - end - elseif c>1 && c <=(Nc+1) - sym="."; - if (u <= Nuwsyms) && (s == uw_ind_sym(u)) sym="U"; u++; end - s++; - else - sym=" "; - end - printf("%s",sym); - end - printf("\n"); - end - end - - printf("Nc=%d Ts=%4.3f Tcp=%4.3f Ns: %d Np: %d\n", Nc, 1/Rs, Tcp, Ns, Np); - printf("Nsymperframe: %d Nbitsperpacket: %d Nsamperframe: %d Ntxtbits: %d Nuwbits: %d Nuwframes: %d\n", - Ns*Nc, Nbitsperpacket, Nsamperframe, Ntxtbits, Nuwbits, Nuwframes); - printf("uncoded bits/s: %4.1f\n", Nbitsperpacket*Fs/(Np*Nsamperframe)); -end - % Gray coded QPSK modulation function function symbol = qpsk_mod(two_bits) two_bits_decimal = sum(two_bits .* [2 1]); @@ -1345,452 +1162,6 @@ Can be used for acquisition (coarse timing), and fine timing. Tends endfunction -%----------------------------------------------------------------------- -% create_ldpc_test_frame - generate a test frame of bits -%----------------------------------------------------------------------- - -function [tx_bits payload_data_bits codeword] = create_ldpc_test_frame(states, coded_frame=1) - ofdm_load_const; - ldpc; - gp_interleaver; - - if coded_frame - % Set up LDPC code - - mod_order = 4; bps = 2; modulation = 'QPSK'; mapping = 'gray'; - - init_cml(); % TODO: make this path sensible and portable - load HRA_112_112.txt - [code_param framesize rate] = ldpc_init_user(HRA_112_112, modulation, mod_order, mapping); - assert(Nbitsperframe == (code_param.coded_bits_per_frame + Nuwbits + Ntxtbits)); - - payload_data_bits = round(ofdm_rand(code_param.data_bits_per_frame)/32767); - codeword = LdpcEncode(payload_data_bits, code_param.H_rows, code_param.P_matrix); - Nsymbolsperframe = length(codeword)/bps; - - % need all these steps to get actual raw codeword bits at demod .. - - tx_symbols = []; - for s=1:Nsymbolsperframe - tx_symbols = [tx_symbols qpsk_mod( codeword(2*(s-1)+1:2*s) )]; - end - - tx_symbols = gp_interleave(tx_symbols); - - codeword_raw = []; - for s=1:Nsymbolsperframe - codeword_raw = [codeword_raw qpsk_demod(tx_symbols(s))]; - end - else - codeword_raw = round(ofdm_rand(Nbitsperpacket-(Nuwbits+Ntxtbits))/32767); - end - - % insert UW and txt bits - - tx_bits = assemble_modem_packet(states, codeword_raw, zeros(1,Ntxtbits)); - assert(Nbitsperpacket == length(tx_bits)); - -endfunction - -% automated test - -function test_assemble_disassemble(states) - ofdm_load_const; - - Nsymsperpacket = Nbitsperpacket/bps; - Ndatabitsperpacket = Nbitsperpacket-(Nuwbits+Ntxtbits); - Ndatasymsperpacket = Ndatabitsperpacket/bps; - codeword_bits = round(ofdm_rand(Ndatabitsperpacket)/32767); - tx_bits = assemble_modem_packet(states, codeword_bits, zeros(1,Ntxtbits)); - - tx_syms = zeros(1,Nsymsperpacket); - for s=1:Nsymsperpacket - if bps == 2 - tx_syms(s) = qpsk_mod(tx_bits(bps*(s-1)+1:bps*s)); - elseif bps == 4 - tx_syms(s) = qam16_mod(states.qam16,tx_bits(bps*(s-1)+1:bps*s)); - end - end - codeword_syms = zeros(1,Ndatasymsperpacket); - for s=1:Ndatasymsperpacket - if bps == 2 - codeword_syms(s) = qpsk_mod(codeword_bits(bps*(s-1)+1:bps*s)); - elseif bps == 4 - codeword_syms(s) = qam16_mod(states.qam16,codeword_bits(bps*(s-1)+1:bps*s)); - end - end - - [rx_uw rx_codeword_syms payload_amps txt_bits] = disassemble_modem_packet(states, tx_syms, ones(1,Nsymsperpacket)); - assert(rx_uw == states.tx_uw); - Ndatasymsperframe = (Nbitsperpacket-(Nuwbits+Ntxtbits))/bps; - assert(codeword_syms == rx_codeword_syms); -endfunction - -%------------------------------------------------------------------- -% sync_state_machine - calls mode-specific sync state state_machine -%------------------------------------------------------------------- - -function states = sync_state_machine(states, rx_uw) - if strcmp(states.state_machine, "voice1") - states = sync_state_machine_voice1(states, rx_uw); - elseif strcmp(states.state_machine, "data") - if strcmp(states.data_mode, "streaming") - states = sync_state_machine_data_streaming(states, rx_uw); - else - states = sync_state_machine_data_burst(states, rx_uw); - end - elseif strcmp(states.state_machine, "voice2") - states = sync_state_machine_voice2(states, rx_uw); - else - assert(0); - endif -endfunction - -%-------------------------------------------------------------------- -% Due to the low pilot symbol insertion rate and acquisition issues -% the earlier OFDM modem waveforms (700D and 2020) need a complex -% state machine to help them avoid false sync. -%-------------------------------------------------------------------- - -function states = sync_state_machine_voice1(states, rx_uw) - ofdm_load_const; - next_state = states.sync_state; - states.sync_start = states.sync_end = 0; - - if strcmp(states.sync_state,'search') - - if states.timing_valid - states.frame_count = 0; - states.sync_counter = 0; - states.modem_frame = 0; - states.sync_start = 1; - next_state = 'trial'; - end - end - - if strcmp(states.sync_state,'synced') || strcmp(states.sync_state,'trial') - - states.frame_count++; - - % UW occurs at the start of a packet - if states.modem_frame == 0 - states.uw_errors = sum(xor(tx_uw,rx_uw)); - - if strcmp(states.sync_state,'trial') - if states.uw_errors >= states.bad_uw_errors - states.sync_counter++; - states.frame_count = 0; - end - if states.sync_counter == 2 - next_state = "search"; - states.phase_est_bandwidth = "high"; - end - if states.frame_count == 4 - next_state = "synced"; - % change to low bandwidth, but more accurate phase estimation - states.phase_est_bandwidth = "low"; - end - if states.uw_errors < 2 - next_state = "synced"; - % change to low bandwidth, but more accurate phase estimation - states.phase_est_bandwidth = "low"; - else - next_state = "search"; - end - end - - if strcmp(states.sync_state,'synced') - if states.uw_errors > 2 - states.sync_counter++; - else - states.sync_counter = 0; - end - - if states.sync_counter == 6 - next_state = "search"; - states.phase_est_bandwidth = "high"; - end - end - end % if modem_frame == 0 .... - - % keep track of where we are up to in packet - states.modem_frame++; - if (states.modem_frame >= states.Np) states.modem_frame = 0; end - end - - states.last_sync_state = states.sync_state; - states.sync_state = next_state; -endfunction - - -%------------------------------------------------------- -% data (streaming mode) state machine -%------------------------------------------------------- - -function states = sync_state_machine_data_streaming(states, rx_uw) - ofdm_load_const; - next_state = states.sync_state; - states.sync_start = states.sync_end = 0; - - if strcmp(states.sync_state,'search') - if states.timing_valid - states.sync_start = 1; - states.sync_counter = 0; - next_state = 'trial'; - end - end - - states.uw_errors = sum(xor(tx_uw,rx_uw)); - - if strcmp(states.sync_state,'trial') - if states.uw_errors < states.bad_uw_errors; - next_state = "synced"; - states.packet_count = 0; - states.modem_frame = Nuwframes; - else - states.sync_counter++; - if states.sync_counter > Np - next_state = "search"; - end - end - end - - % Note packetsperburst==0 we don't ever lose sync, which is useful for - % stream based testing or external control of state machine - - if strcmp(states.sync_state,'synced') - states.modem_frame++; - if (states.modem_frame >= states.Np) - states.modem_frame = 0; - states.packet_count++; - if (states.packetsperburst) - if (states.packet_count >= states.packetsperburst) - next_state = "search"; - end - end - end - end - - states.last_sync_state = states.sync_state; - states.sync_state = next_state; -endfunction - -%------------------------------------------------------- -% data (burst mode) state machine -%------------------------------------------------------- - -function states = sync_state_machine_data_burst(states, rx_uw) - ofdm_load_const; - next_state = states.sync_state; - states.sync_start = states.sync_end = 0; - - if strcmp(states.sync_state,'search') - if states.timing_valid - states.sync_start = 1; - states.sync_counter = 0; - next_state = 'trial'; - end - end - - states.uw_errors = sum(xor(tx_uw,rx_uw)); - - % pre or post-amble has told us this is the start of the packet. Confirm we - % have a valid frame by checking the UW after the modem frames containing - % the UW have been received - if strcmp(states.sync_state,'trial') - states.sync_counter++; - if states.sync_counter == Nuwframes - if states.uw_errors < states.bad_uw_errors; - next_state = "synced"; - states.packet_count = 0; % number of packets in this burst - states.modem_frame = Nuwframes; % which modem frame we are up to in packet - else - next_state = "search"; - % reset rxbuf to make sure we only ever do a postamble loop once through same samples - states.rxbufst = states.Nrxbufhistory; - states.rxbuf = zeros(1, states.Nrxbuf); - end - end - end - - if strcmp(states.sync_state,'synced') - states.modem_frame++; - if (states.modem_frame >= states.Np) - states.modem_frame = 0; % start of new packet - states.packet_count++; - if (states.packetsperburst) - if (states.packet_count >= states.packetsperburst) - next_state = "search"; % we've finished this burst - % reset rxbuf to make sure we only ever do a postamble loop once through same samples - states.rxbufst = states.Nrxbufhistory; - states.rxbuf = zeros(1, states.Nrxbuf); - end - end - end - end - - states.last_sync_state = states.sync_state; - states.sync_state = next_state; -endfunction - -%------------------------------------------------------- -% fast sync voice state state_machine -%------------------------------------------------------- - -function states = sync_state_machine_voice2(states, rx_uw) - ofdm_load_const; - next_state = states.sync_state; - states.sync_start = states.sync_end = 0; - - if strcmp(states.sync_state,'search') - - if states.timing_valid - states.frame_count = 0; - states.sync_counter = 0; - states.modem_frame = 0; - states.sync_start = 1; - next_state = 'trial'; - end - end - - if strcmp(states.sync_state,'synced') || strcmp(states.sync_state,'trial') - - states.frame_count++; - - % UW occurs at the start of a packet - if states.modem_frame == 0 - states.uw_errors = sum(xor(tx_uw,rx_uw)); - - if strcmp(states.sync_state,'trial') - if states.uw_errors <= states.bad_uw_errors - next_state = "synced"; - else - next_state = "search"; - end - end - - if strcmp(states.sync_state,'synced') - if states.uw_errors > states.bad_uw_errors - states.sync_counter++; - else - states.sync_counter = 0; - end - - if states.sync_counter == 6 - next_state = "search"; - end - end - end - - % keep track of where we are up to in packet - states.modem_frame++; - if (states.modem_frame >= states.Np) states.modem_frame = 0; end - end - - states.last_sync_state = states.sync_state; - states.sync_state = next_state; -endfunction - - -% ------------------------------------------------------------------------------ -% codec_to_frame_packing - Set up a bunch of constants to support modem frame -% construction from LDPC codewords and codec source bits -% ------------------------------------------------------------------------------ - -function [code_param Nbitspercodecframe Ncodecframespermodemframe] = codec_to_frame_packing(states, mode) - ofdm_load_const; - mod_order = 4; bps = 2; modulation = 'QPSK'; mapping = 'gray'; - - init_cml(); - if strcmp(mode, "700D") - load HRA_112_112.txt - code_param = ldpc_init_user(HRA_112_112, modulation, mod_order, mapping); - assert(Nbitsperframe == (code_param.coded_bits_per_frame + Nuwbits + Ntxtbits)); - % unused for this mode - Nbitspercodecframe = Ncodecframespermodemframe = 0; - end - if strcmp(mode, "700E") - load HRA_56_56.txt - code_param = ldpc_init_user(HRA_56_56, modulation, mod_order, mapping); - assert(Nbitsperframe == (code_param.coded_bits_per_frame + Nuwbits + Ntxtbits)); - % unused for this mode - Nbitspercodecframe = Ncodecframespermodemframe = 0; - end - if strcmp(mode, "2020") - load HRA_504_396.txt - code_param = ldpc_init_user(HRA_504_396, modulation, mod_order, mapping); - code_param.data_bits_per_frame = 312; - code_param.coded_bits_per_frame = code_param.data_bits_per_frame + code_param.ldpc_parity_bits_per_frame; - code_param.coded_syms_per_frame = code_param.coded_bits_per_frame/code_param.bits_per_symbol; - printf("2020 mode\n"); - printf("ldpc_data_bits_per_frame = %d\n", code_param.ldpc_data_bits_per_frame); - printf("ldpc_coded_bits_per_frame = %d\n", code_param.ldpc_coded_bits_per_frame); - printf("ldpc_parity_bits_per_frame = %d\n", code_param.ldpc_parity_bits_per_frame); - printf("data_bits_per_frame = %d\n", code_param.data_bits_per_frame); - printf("coded_bits_per_frame = %d\n", code_param.coded_bits_per_frame); - printf("coded_syms_per_frame = %d\n", code_param.coded_syms_per_frame); - printf("ofdm_bits_per_frame = %d\n", Nbitsperframe); - Nbitspercodecframe = 52; Ncodecframespermodemframe = 6; - printf(" Nuwbits: %d Ntxtbits: %d\n", Nuwbits, Ntxtbits); - Nparity = code_param.ldpc_parity_bits_per_frame; - totalbitsperframe = code_param.data_bits_per_frame + Nparity + Nuwbits + Ntxtbits; - printf("Total bits per frame: %d\n", totalbitsperframe); - assert(totalbitsperframe == Nbitsperframe); - end - if strcmp(mode, "qam16c1") - load H2064_516_sparse.mat - code_param = ldpc_init_user(HRA, modulation='QAM', mod_order=16, mapping="", reshape(states.qam16,1,16)); - end - if strcmp(mode, "qam16c2") - framesize = 16200; rate = 0.6; - code_param = ldpc_init_builtin("dvbs2", rate, framesize, modulation='QAM', mod_order=16, mapping="", reshape(states.qam16,1,16)); - end - if strcmp(mode, "datac5") - framesize = 16200; rate = 0.6; - code_param = ldpc_init_builtin("dvbs2", rate, framesize, modulation='QPSK', mod_order=4, mapping=""); - end - if strcmp(mode, "datac0") || strcmp(mode, "datac13") - load H_128_256_5.mat - code_param = ldpc_init_user(H, modulation, mod_order, mapping); - end - if strcmp(mode, "datac1") - load H_4096_8192_3d.mat - code_param = ldpc_init_user(HRA, modulation, mod_order, mapping); - end - if strcmp(mode, "datac3") - load H_1024_2048_4f.mat - code_param = ldpc_init_user(H, modulation, mod_order, mapping); - end - if strcmp(mode, "datac4") - load H_1024_2048_4f - code_param = ldpc_init_user(H, modulation, mod_order, mapping); - code_param.data_bits_per_frame = 448; - code_param.coded_bits_per_frame = code_param.data_bits_per_frame + code_param.ldpc_parity_bits_per_frame; - code_param.coded_syms_per_frame = code_param.coded_bits_per_frame/code_param.bits_per_symbol; - end - if strcmp(mode, "datac13") - load H_256_512_4.mat - code_param = ldpc_init_user(H, modulation, mod_order, mapping); - code_param.data_bits_per_frame = 128; - code_param.coded_bits_per_frame = code_param.data_bits_per_frame + code_param.ldpc_parity_bits_per_frame; - code_param.coded_syms_per_frame = code_param.coded_bits_per_frame/code_param.bits_per_symbol; - end - if strcmp(mode, "datac0") || strcmp(mode, "datac1") || strcmp(mode, "datac3") ... - || strcmp(mode, "datac4") || strcmp(mode, "qam16c1") ... - || strcmp(mode, "qam16c2") || strcmp(mode, "datac5") || strcmp(mode, "datac13") - printf("ldpc_data_bits_per_frame = %d\n", code_param.ldpc_data_bits_per_frame); - printf("ldpc_coded_bits_per_frame = %d\n", code_param.ldpc_coded_bits_per_frame); - printf("ldpc_parity_bits_per_frame = %d\n", code_param.ldpc_parity_bits_per_frame); - printf("Nbitsperpacket = %d\n", Nbitsperpacket); - Nparity = code_param.ldpc_parity_bits_per_frame; - totalbitsperframe = code_param.data_bits_per_frame + Nparity + Nuwbits + Ntxtbits; - printf("totalbitsperframe = %d\n", totalbitsperframe); - assert(totalbitsperframe == Nbitsperpacket); - Nbitspercodecframe = Ncodecframespermodemframe = -1; - end -endfunction - - % ------------------------------------------------------------------------------ % Handle FEC encoding/decoding % ------------------------------------------------------------------------------ @@ -1822,134 +1193,6 @@ function test_assemble_disassemble(states) endfunction -% test function, kind of like a CRC for QPSK symbols, to compare two vectors - -function acc = test_acc(v) - sre = 0; sim = 0; - for i=1:length(v) - x = v(i); - re = round(real(x)); im = round(imag(x)); - sre += re; sim += im; - %printf("%d %10f %10f %10f %10f\n", i, re, im, sre, sim); - end - acc = sre + j*sim; -end - - -% Save test bits frame to a text file in the form of a C array -% -% usage: -% ofdm_lib; test_bits_ofdm_file -% - -function test_bits_ofdm_file - Ts = 0.018; Tcp = 0.002; Rs = 1/Ts; bps = 2; Nc = 17; Ns = 8; - states = ofdm_init(bps, Rs, Tcp, Ns, Nc); - [test_bits_ofdm payload_data_bits codeword] = create_ldpc_test_frame(states); - printf("%d test bits\n", length(test_bits_ofdm)); - - f=fopen("../src/test_bits_ofdm.h","wt"); - fprintf(f,"/* Generated by test_bits_ofdm_file() Octave function */\n\n"); - fprintf(f,"const int test_bits_ofdm[]={\n"); - for m=1:length(test_bits_ofdm)-1 - fprintf(f," %d,\n",test_bits_ofdm(m)); - endfor - fprintf(f," %d\n};\n",test_bits_ofdm(end)); - - fprintf(f,"\nconst int payload_data_bits[]={\n"); - for m=1:length(payload_data_bits)-1 - fprintf(f," %d,\n",payload_data_bits(m)); - endfor - fprintf(f," %d\n};\n",payload_data_bits(end)); - - fprintf(f,"\nconst int test_codeword[]={\n"); - for m=1:length(codeword)-1 - fprintf(f," %d,\n",codeword(m)); - endfor - fprintf(f," %d\n};\n",codeword(end)); - - fclose(f); - -endfunction - - -% Get rid of nasty unfiltered stuff either side of OFDM signal -% This may need to be tweaked, or better yet made a function of Nc, if Nc changes -% -% usage: -% ofdm_lib; make_ofdm_bpf(1); - -function bpf_coeff = make_ofdm_bpf(write_c_header_file) - filt_n = 100; - Fs = 8000; - - bpf_coeff = fir2(filt_n,[0 900 1000 2000 2100 4000]/(Fs/2),[0.001 0.001 1 1 0.001 0.001]); - - if write_c_header_file - figure(1) - clf; - h = freqz(bpf_coeff,1,Fs/2); - plot(20*log10(abs(h))) - grid minor - - % save coeffs to a C header file - - f=fopen("../src/ofdm_bpf_coeff.h","wt"); - fprintf(f,"/* 1000 - 2000 Hz FIR filter coeffs */\n"); - fprintf(f,"/* Generated by make_ofdm_bpf() in ofdm_lib.m */\n"); - - fprintf(f,"\n#define OFDM_BPF_N %d\n\n", filt_n); - - fprintf(f,"float ofdm_bpf_coeff[]={\n"); - for r=1:filt_n - if r < filt_n - fprintf(f, " %f,\n", bpf_coeff(r)); - else - fprintf(f, " %f\n};", bpf_coeff(r)); - end - end - fclose(f); - end - -endfunction - -% Helper function to help design UW error thresholds, in particular for raw -% data modes. See also https://www.rowetel.com/wordpress/?p=7467 -function ofdm_determine_bad_uw_errors(Nuw) - figure(1); clf; - - % Ideally the 10% and 50% BER curves are a long way apart - - plot(0:Nuw, binocdf(0:Nuw,Nuw,0.1),';BER=0.1;'); hold on; - plot(binocdf(0:Nuw,Nuw,0.5),';BER=0.5;'); - - % Suggested threshold for raw data modes is the 5% probability - % level for the 50% BER curve. The pre/post-amble has a low chance - % of failure. If it does make an error, then we will have random - % bits presented as the UW (50% BER in UW). This threshold means - % there is only a 5% case of random bits being accepted as a valid UW - - bad_uw_errors = max(find(binocdf(0:Nuw,Nuw,0.5) <= 0.05))+1; - plot([bad_uw_errors bad_uw_errors],[0 1],';bad uw errors;'); hold off; grid - - xlabel('bits'); - printf("for Nuw = %d, suggest bad_uw_errors = %d\n", Nuw, bad_uw_errors); -end - -% Returns level threshold such that threshold_cdf of the tx magnitudes are -% beneath that level. Helper function that can be used to design -% the clipper level. See also https://www.rowetel.com/?p=7596 -function threshold_level = ofdm_determine_clip_threshold(tx, threshold_cdf) - Nsteps = 25; - mx = max(abs(tx)); - cdf = empirical_cdf(mx*(1:Nsteps)/Nsteps,abs(tx)); - threshold_level = find(cdf >= threshold_cdf)(1)*mx/25; - printf("threshold_cdf: %f threshold_level: %f\n", threshold_cdf, threshold_level); - figure(1); clf; [hh nn] = hist(abs(tx),Nsteps,1); - plotyy(nn,hh,mx*(1:Nsteps)/Nsteps,cdf); title('PDF and CDF Estimates'); grid; -end - - function [tx nclipped] = ofdm_clip(states, tx, threshold_level, plot_en=0) ofdm_load_const; tx_ = tx; @@ -1999,19 +1242,6 @@ function ofdm_determine_bad_uw_errors(Nuw) endfunction -% helper function that adds channel simulation and ensures we don't saturate int16 output samples -function [rx_real rx] = ofdm_channel(states, tx, SNR3kdB, channel, freq_offset_Hz) - [rx_real rx sigma] = channel_simulate(states.Fs, SNR3kdB, freq_offset_Hz, channel, tx, states.verbose); - - % multipath models can lead to clipping of int16 samples - num_clipped = length(find(abs(rx_real>32767))); - while num_clipped/length(rx_real) > 0.001 - rx_real /= 2; - num_clipped = length(find(abs(rx_real>32767))); - printf("WARNING: output samples clipped, reducing level\n") - end -endfunction - % returns an unpacked CRC16 (array of 16 bits) calculated from an array of unpacked bits function unpacked_crc16 = crc16_unpacked(unpacked_bits) % pack into bytes diff --git a/octave/ofdm_mode.m b/octave/ofdm_mode.m new file mode 100644 index 000000000..64b856521 --- /dev/null +++ b/octave/ofdm_mode.m @@ -0,0 +1,247 @@ +% ofdm_mode.m +% +% Library of functions to help setting up OFDM modes + +%------------------------------------------------------------------------------ +% ofdm_init_mode - Helper function to set up modems for various FreeDV modes, +% and parse mode string. +%------------------------------------------------------------------------------ + +1; + +function config = ofdm_init_mode(mode="700D") + % defaults for 700D + + Tcp = 0.002; + Ns = 8; + Ts = 0.018; + Nc = 17; + config.bps = 2; + config.Np = 1; + config.Ntxtbits = 4; + config.Nuwbits = 5*config.bps; + config.ftwindow_width = 32; + config.timing_mx_thresh = 0.35; + config.bad_uw_errors = 3; + config.amp_scale = 245E3; + config.amp_est_mode = 0; + config.EsNo_est_all_symbols = 1; + config.EsNodB = 3; + config.state_machine = "voice1"; + config.edge_pilots = 1; + config.clip_gain1 = 2.5; + config.clip_gain2 = 0.8; + config.foff_limiter = 0; + config.txbpf_width_Hz = 2000; + config.data_mode = ""; + + if strcmp(mode,"700D") || strcmp(mode,"700d") + % defaults above + elseif strcmp(mode,"700E") || strcmp(mode,"700e") + Ts = 0.014; Tcp=0.006; Nc = 21; Ns=4; + config.edge_pilots = 0; config.state_machine = "voice2"; + config.Nuwbits = 12; config.bad_uw_errors = 3; config.Ntxtbits = 2; + config.amp_est_mode = 1; config.ftwindow_width = 80; + config.amp_scale = 155E3; config.clip_gain1 = 3; config.clip_gain2 = 0.8; + config.foff_limiter = 1; + elseif strcmp(mode,"2020") + Ts = 0.0205; Nc = 31; + config.amp_scale = 167E3; config.clip_gain1 = 2.5; config.clip_gain2 = 0.8; + elseif strcmp(mode,"2020B") + Ts = 0.014; Tcp = 0.004; Nc = 29; Ns=5; + config.Ntxtbits = 4; config.Nuwbits = 8*2; config.bad_uw_errors = 5; + config.amp_scale = 130E3; config.clip_gain1 = 2.5; config.clip_gain2 = 0.8; + config.edge_pilots = 0; config.state_machine = "voice2"; + config.foff_limiter = 1; config.ftwindow_width = 64; + config.txbpf_width_Hz = 2200; + elseif strcmp(mode,"qam16c1") + Ns=5; config.Np=5; Tcp = 0.004; Ts = 0.016; Nc = 33; config.data_mode = "streaming"; + config.bps=4; config.Ntxtbits = 0; config.Nuwbits = 15*4; config.bad_uw_errors = 5; + config.state_machine = "data"; + config.ftwindow_width = 32; config.amp_scale = 132E3; + config.EsNo_est_all_symbols = 0; config.amp_est_mode = 1; config.EsNodB = 10; + elseif strcmp(mode,"qam16c2") + Ns=5; config.Np=31; Tcp = 0.004; Ts = 0.016; Nc = 33; config.data_mode = "streaming"; + config.bps=4; config.Ntxtbits = 0; config.Nuwbits = 42*4; config.bad_uw_errors = 15; + config.ftwindow_width = 80; config.amp_scale = 135E3; config.state_machine = "data"; + config.EsNo_est_all_symbols = 0; config.amp_est_mode = 1; config.EsNodB = 10; + config.tx_uw = zeros(1,config.Nuwbits = 42*4); + config.tx_uw(1:24) = [1 1 0 0 1 0 1 0 1 1 1 1 0 0 0 0 1 1 1 1 0 0 0 0]; + config.tx_uw(end-24+1:end) = [1 1 0 0 1 0 1 0 1 1 1 1 0 0 0 0 1 1 1 1 0 0 0 0]; + elseif strcmp(mode,"datac0") + Ns=5; config.Np=4; Tcp = 0.006; Ts = 0.016; Nc = 9; config.data_mode = "streaming"; + config.Ntxtbits = 0; config.Nuwbits = 32; config.bad_uw_errors = 9; + config.state_machine = "data"; + config.ftwindow_width = 80; config.amp_est_mode = 1; config.EsNodB = 3; + config.edge_pilots = 0; config.timing_mx_thresh = 0.08; + config.tx_uw = zeros(1,config.Nuwbits); + config.tx_uw(1:16) = [1 1 0 0 1 0 1 0 1 1 1 1 0 0 0 0]; + config.amp_scale = 300E3; config.clip_gain1 = 2.2; config.clip_gain2 = 0.85; + elseif strcmp(mode,"datac5") + Ns=5; config.Np=58; Tcp = 0.004; Ts = 0.016; Nc = 35; config.data_mode = "streaming"; + config.Ntxtbits = 0; config.Nuwbits = 40; config.bad_uw_errors = 14; + config.state_machine = "data"; + config.ftwindow_width = 80; config.amp_est_mode = 1; config.EsNodB = 3; + config.amp_scale = 145E3; config.clip_gain1 = 2.7; config.clip_gain2 = 0.8; + config.edge_pilots = 0; config.timing_mx_thresh = 0.10; + config.tx_uw = zeros(1,config.Nuwbits); + config.tx_uw(1:16) = [1 1 0 0 1 0 1 0 1 1 1 1 0 0 0 0]; + elseif strcmp(mode,"datac1") + Ns=5; config.Np=38; Tcp = 0.006; Ts = 0.016; Nc = 27; config.data_mode = "streaming"; + config.Ntxtbits = 0; config.Nuwbits = 16; config.bad_uw_errors = 6; + config.state_machine = "data"; + config.ftwindow_width = 80; config.amp_est_mode = 1; config.EsNodB = 3; + % clipper/compression adjustment: + % 1. With clipper off increase amp_scale until peak just hit 16384 + % 2. With clipper on increase clip_gain1 until about 30% clipped + % 3. BPF will drop level beneath 16384, adjust clip_gain2 to just hit 16384 peak again + % 4. Clipped/unclipped operating point for same PER should be about 1dB apart + config.amp_scale = 145E3; config.clip_gain1 = 2.7; config.clip_gain2 = 0.8; + config.edge_pilots = 0; config.timing_mx_thresh = 0.10; + config.tx_uw = [1 1 0 0 1 0 1 0 1 1 1 1 0 0 0 0]; + elseif strcmp(mode,"datac3") + Ns=5; config.Np=29; Tcp = 0.006; Ts = 0.016; Nc = 9; config.data_mode = "streaming"; + config.edge_pilots = 0; + config.Ntxtbits = 0; config.Nuwbits = 40; config.bad_uw_errors = 10; + config.ftwindow_width = 80; config.timing_mx_thresh = 0.10; + config.tx_uw = zeros(1,config.Nuwbits); + config.tx_uw(1:24) = [1 1 0 0 1 0 1 0 1 1 1 1 0 0 0 0 1 1 1 1 0 0 0 0]; + config.tx_uw(end-24+1:end) = [1 1 0 0 1 0 1 0 1 1 1 1 0 0 0 0 1 1 1 1 0 0 0 0]; + config.amp_est_mode = 1; config.EsNodB = 3; + config.state_machine = "data"; + config.amp_scale = 300E3; config.clip_gain1 = 2.2; config.clip_gain2 = 0.8; + elseif strcmp(mode,"datac4") + Ns=5; config.Np=47; Tcp = 0.006; Ts = 0.016; Nc = 4; config.data_mode = "streaming"; + config.edge_pilots = 0; + config.Ntxtbits = 0; config.Nuwbits = 32; config.bad_uw_errors = 12; + config.ftwindow_width = 80; config.timing_mx_thresh = 0.25; + config.tx_uw = zeros(1,config.Nuwbits); + config.tx_uw(1:24) = [1 1 0 0 1 0 1 0 1 1 1 1 0 0 0 0 1 1 1 1 0 0 0 0]; + config.tx_uw(end-24+1:end) = [1 1 0 0 1 0 1 0 1 1 1 1 0 0 0 0 1 1 1 1 0 0 0 0]; + config.amp_est_mode = 1; config.EsNodB = 3; + config.state_machine = "data"; + config.amp_scale = 300*2.3E3; config.clip_gain1 = 1.5; config.clip_gain2 = 0.8; + elseif strcmp(mode,"datac13") + Ns=5; config.Np=18; Tcp = 0.006; Ts = 0.016; Nc = 3; config.data_mode = "streaming"; + config.edge_pilots = 0; + config.Ntxtbits = 0; config.Nuwbits = 48; config.bad_uw_errors = 18; + config.ftwindow_width = 80; config.timing_mx_thresh = 0.25; + config.tx_uw = zeros(1,config.Nuwbits); + config.tx_uw(1:24) = [1 1 0 0 1 0 1 0 1 1 1 1 0 0 0 0 1 1 1 1 0 0 0 0]; + config.tx_uw(end-24+1:end) = [1 1 0 0 1 0 1 0 1 1 1 1 0 0 0 0 1 1 1 1 0 0 0 0]; + config.amp_est_mode = 1; config.EsNodB = 3; + config.state_machine = "data"; + config.amp_scale = 300*2.3E3; config.clip_gain1 = 1.5; config.clip_gain2 = 0.8; + elseif strcmp(mode,"1") + Ns=5; config.Np=10; Tcp=0; Tframe = 0.1; Ts = Tframe/Ns; Nc = 1; + else + % try to parse mode string for user defined mode + vec = sscanf(mode, "Ts=%f Nc=%d Ncp=%f"); + Ts=vec(1); Nc=vec(2); Ncp=vec(3); + end + Rs=1/Ts; + config.Rs = Rs; config.Tcp = Tcp; config.Ns = Ns; config.Nc = Nc; + if !isfield(config,"tx_uw") + config.tx_uw = zeros(1,config.Nuwbits); + end +end + +% ------------------------------------------------------------------------------ +% codec_to_frame_packing - Set up a bunch of constants to support modem frame +% construction from LDPC codewords and codec source bits +% ------------------------------------------------------------------------------ + +function [code_param Nbitspercodecframe Ncodecframespermodemframe] = codec_to_frame_packing(states, mode) + ofdm_load_const; + mod_order = 4; bps = 2; modulation = 'QPSK'; mapping = 'gray'; + + init_cml(); + if strcmp(mode, "700D") + load HRA_112_112.txt + code_param = ldpc_init_user(HRA_112_112, modulation, mod_order, mapping); + assert(Nbitsperframe == (code_param.coded_bits_per_frame + Nuwbits + Ntxtbits)); + % unused for this mode + Nbitspercodecframe = Ncodecframespermodemframe = 0; + end + if strcmp(mode, "700E") + load HRA_56_56.txt + code_param = ldpc_init_user(HRA_56_56, modulation, mod_order, mapping); + assert(Nbitsperframe == (code_param.coded_bits_per_frame + Nuwbits + Ntxtbits)); + % unused for this mode + Nbitspercodecframe = Ncodecframespermodemframe = 0; + end + if strcmp(mode, "2020") + load HRA_504_396.txt + code_param = ldpc_init_user(HRA_504_396, modulation, mod_order, mapping); + code_param.data_bits_per_frame = 312; + code_param.coded_bits_per_frame = code_param.data_bits_per_frame + code_param.ldpc_parity_bits_per_frame; + code_param.coded_syms_per_frame = code_param.coded_bits_per_frame/code_param.bits_per_symbol; + printf("2020 mode\n"); + printf("ldpc_data_bits_per_frame = %d\n", code_param.ldpc_data_bits_per_frame); + printf("ldpc_coded_bits_per_frame = %d\n", code_param.ldpc_coded_bits_per_frame); + printf("ldpc_parity_bits_per_frame = %d\n", code_param.ldpc_parity_bits_per_frame); + printf("data_bits_per_frame = %d\n", code_param.data_bits_per_frame); + printf("coded_bits_per_frame = %d\n", code_param.coded_bits_per_frame); + printf("coded_syms_per_frame = %d\n", code_param.coded_syms_per_frame); + printf("ofdm_bits_per_frame = %d\n", Nbitsperframe); + Nbitspercodecframe = 52; Ncodecframespermodemframe = 6; + printf(" Nuwbits: %d Ntxtbits: %d\n", Nuwbits, Ntxtbits); + Nparity = code_param.ldpc_parity_bits_per_frame; + totalbitsperframe = code_param.data_bits_per_frame + Nparity + Nuwbits + Ntxtbits; + printf("Total bits per frame: %d\n", totalbitsperframe); + assert(totalbitsperframe == Nbitsperframe); + end + if strcmp(mode, "qam16c1") + load H2064_516_sparse.mat + code_param = ldpc_init_user(HRA, modulation='QAM', mod_order=16, mapping="", reshape(states.qam16,1,16)); + end + if strcmp(mode, "qam16c2") + framesize = 16200; rate = 0.6; + code_param = ldpc_init_builtin("dvbs2", rate, framesize, modulation='QAM', mod_order=16, mapping="", reshape(states.qam16,1,16)); + end + if strcmp(mode, "datac5") + framesize = 16200; rate = 0.6; + code_param = ldpc_init_builtin("dvbs2", rate, framesize, modulation='QPSK', mod_order=4, mapping=""); + end + if strcmp(mode, "datac0") || strcmp(mode, "datac13") + load H_128_256_5.mat + code_param = ldpc_init_user(H, modulation, mod_order, mapping); + end + if strcmp(mode, "datac1") + load H_4096_8192_3d.mat + code_param = ldpc_init_user(HRA, modulation, mod_order, mapping); + end + if strcmp(mode, "datac3") + load H_1024_2048_4f.mat + code_param = ldpc_init_user(H, modulation, mod_order, mapping); + end + if strcmp(mode, "datac4") + load H_1024_2048_4f + code_param = ldpc_init_user(H, modulation, mod_order, mapping); + code_param.data_bits_per_frame = 448; + code_param.coded_bits_per_frame = code_param.data_bits_per_frame + code_param.ldpc_parity_bits_per_frame; + code_param.coded_syms_per_frame = code_param.coded_bits_per_frame/code_param.bits_per_symbol; + end + if strcmp(mode, "datac13") + load H_256_512_4.mat + code_param = ldpc_init_user(H, modulation, mod_order, mapping); + code_param.data_bits_per_frame = 128; + code_param.coded_bits_per_frame = code_param.data_bits_per_frame + code_param.ldpc_parity_bits_per_frame; + code_param.coded_syms_per_frame = code_param.coded_bits_per_frame/code_param.bits_per_symbol; + end + if strcmp(mode, "datac0") || strcmp(mode, "datac1") || strcmp(mode, "datac3") ... + || strcmp(mode, "datac4") || strcmp(mode, "qam16c1") ... + || strcmp(mode, "qam16c2") || strcmp(mode, "datac5") || strcmp(mode, "datac13") + printf("ldpc_data_bits_per_frame = %d\n", code_param.ldpc_data_bits_per_frame); + printf("ldpc_coded_bits_per_frame = %d\n", code_param.ldpc_coded_bits_per_frame); + printf("ldpc_parity_bits_per_frame = %d\n", code_param.ldpc_parity_bits_per_frame); + printf("Nbitsperpacket = %d\n", Nbitsperpacket); + Nparity = code_param.ldpc_parity_bits_per_frame; + totalbitsperframe = code_param.data_bits_per_frame + Nparity + Nuwbits + Ntxtbits; + printf("totalbitsperframe = %d\n", totalbitsperframe); + assert(totalbitsperframe == Nbitsperpacket); + Nbitspercodecframe = Ncodecframespermodemframe = -1; + end +endfunction + + diff --git a/octave/ofdm_state.m b/octave/ofdm_state.m new file mode 100644 index 000000000..a2eca260b --- /dev/null +++ b/octave/ofdm_state.m @@ -0,0 +1,271 @@ +% ofdm_state.m +% +% Library of state machine functions for the OFDM modem + +1; + +%------------------------------------------------------------------- +% sync_state_machine - calls mode-specific sync state state_machine +%------------------------------------------------------------------- + +function states = sync_state_machine(states, rx_uw) + if strcmp(states.state_machine, "voice1") + states = sync_state_machine_voice1(states, rx_uw); + elseif strcmp(states.state_machine, "data") + if strcmp(states.data_mode, "streaming") + states = sync_state_machine_data_streaming(states, rx_uw); + else + states = sync_state_machine_data_burst(states, rx_uw); + end + elseif strcmp(states.state_machine, "voice2") + states = sync_state_machine_voice2(states, rx_uw); + else + assert(0); + endif +endfunction + +%-------------------------------------------------------------------- +% Due to the low pilot symbol insertion rate and acquisition issues +% the earlier OFDM modem waveforms (700D and 2020) need a complex +% state machine to help them avoid false sync. +%-------------------------------------------------------------------- + +function states = sync_state_machine_voice1(states, rx_uw) + ofdm_load_const; + next_state = states.sync_state; + states.sync_start = states.sync_end = 0; + + if strcmp(states.sync_state,'search') + + if states.timing_valid + states.frame_count = 0; + states.sync_counter = 0; + states.modem_frame = 0; + states.sync_start = 1; + next_state = 'trial'; + end + end + + if strcmp(states.sync_state,'synced') || strcmp(states.sync_state,'trial') + + states.frame_count++; + + % UW occurs at the start of a packet + if states.modem_frame == 0 + states.uw_errors = sum(xor(tx_uw,rx_uw)); + + if strcmp(states.sync_state,'trial') + if states.uw_errors >= states.bad_uw_errors + states.sync_counter++; + states.frame_count = 0; + end + if states.sync_counter == 2 + next_state = "search"; + states.phase_est_bandwidth = "high"; + end + if states.frame_count == 4 + next_state = "synced"; + % change to low bandwidth, but more accurate phase estimation + states.phase_est_bandwidth = "low"; + end + if states.uw_errors < 2 + next_state = "synced"; + % change to low bandwidth, but more accurate phase estimation + states.phase_est_bandwidth = "low"; + else + next_state = "search"; + end + end + + if strcmp(states.sync_state,'synced') + if states.uw_errors > 2 + states.sync_counter++; + else + states.sync_counter = 0; + end + + if states.sync_counter == 6 + next_state = "search"; + states.phase_est_bandwidth = "high"; + end + end + end % if modem_frame == 0 .... + + % keep track of where we are up to in packet + states.modem_frame++; + if (states.modem_frame >= states.Np) states.modem_frame = 0; end + end + + states.last_sync_state = states.sync_state; + states.sync_state = next_state; +endfunction + + +%------------------------------------------------------- +% data (streaming mode) state machine +%------------------------------------------------------- + +function states = sync_state_machine_data_streaming(states, rx_uw) + ofdm_load_const; + next_state = states.sync_state; + states.sync_start = states.sync_end = 0; + + if strcmp(states.sync_state,'search') + if states.timing_valid + states.sync_start = 1; + states.sync_counter = 0; + next_state = 'trial'; + end + end + + states.uw_errors = sum(xor(tx_uw,rx_uw)); + + if strcmp(states.sync_state,'trial') + if states.uw_errors < states.bad_uw_errors; + next_state = "synced"; + states.packet_count = 0; + states.modem_frame = Nuwframes; + else + states.sync_counter++; + if states.sync_counter > Np + next_state = "search"; + end + end + end + + % Note packetsperburst==0 we don't ever lose sync, which is useful for + % stream based testing or external control of state machine + + if strcmp(states.sync_state,'synced') + states.modem_frame++; + if (states.modem_frame >= states.Np) + states.modem_frame = 0; + states.packet_count++; + if (states.packetsperburst) + if (states.packet_count >= states.packetsperburst) + next_state = "search"; + end + end + end + end + + states.last_sync_state = states.sync_state; + states.sync_state = next_state; +endfunction + +%------------------------------------------------------- +% data (burst mode) state machine +%------------------------------------------------------- + +function states = sync_state_machine_data_burst(states, rx_uw) + ofdm_load_const; + next_state = states.sync_state; + states.sync_start = states.sync_end = 0; + + if strcmp(states.sync_state,'search') + if states.timing_valid + states.sync_start = 1; + states.sync_counter = 0; + next_state = 'trial'; + end + end + + states.uw_errors = sum(xor(tx_uw,rx_uw)); + + % pre or post-amble has told us this is the start of the packet. Confirm we + % have a valid frame by checking the UW after the modem frames containing + % the UW have been received + if strcmp(states.sync_state,'trial') + states.sync_counter++; + if states.sync_counter == Nuwframes + if states.uw_errors < states.bad_uw_errors; + next_state = "synced"; + states.packet_count = 0; % number of packets in this burst + states.modem_frame = Nuwframes; % which modem frame we are up to in packet + else + next_state = "search"; + % reset rxbuf to make sure we only ever do a postamble loop once through same samples + states.rxbufst = states.Nrxbufhistory; + states.rxbuf = zeros(1, states.Nrxbuf); + end + end + end + + if strcmp(states.sync_state,'synced') + states.modem_frame++; + if (states.modem_frame >= states.Np) + states.modem_frame = 0; % start of new packet + states.packet_count++; + if (states.packetsperburst) + if (states.packet_count >= states.packetsperburst) + next_state = "search"; % we've finished this burst + % reset rxbuf to make sure we only ever do a postamble loop once through same samples + states.rxbufst = states.Nrxbufhistory; + states.rxbuf = zeros(1, states.Nrxbuf); + end + end + end + end + + states.last_sync_state = states.sync_state; + states.sync_state = next_state; +endfunction + +%------------------------------------------------------- +% fast sync voice state state_machine +%------------------------------------------------------- + +function states = sync_state_machine_voice2(states, rx_uw) + ofdm_load_const; + next_state = states.sync_state; + states.sync_start = states.sync_end = 0; + + if strcmp(states.sync_state,'search') + + if states.timing_valid + states.frame_count = 0; + states.sync_counter = 0; + states.modem_frame = 0; + states.sync_start = 1; + next_state = 'trial'; + end + end + + if strcmp(states.sync_state,'synced') || strcmp(states.sync_state,'trial') + + states.frame_count++; + + % UW occurs at the start of a packet + if states.modem_frame == 0 + states.uw_errors = sum(xor(tx_uw,rx_uw)); + + if strcmp(states.sync_state,'trial') + if states.uw_errors <= states.bad_uw_errors + next_state = "synced"; + else + next_state = "search"; + end + end + + if strcmp(states.sync_state,'synced') + if states.uw_errors > states.bad_uw_errors + states.sync_counter++; + else + states.sync_counter = 0; + end + + if states.sync_counter == 6 + next_state = "search"; + end + end + end + + % keep track of where we are up to in packet + states.modem_frame++; + if (states.modem_frame >= states.Np) states.modem_frame = 0; end + end + + states.last_sync_state = states.sync_state; + states.sync_state = next_state; +endfunction + diff --git a/src/ofdm_mode.c b/src/ofdm_mode.c index 3c6fa7d5f..c05136b2f 100644 --- a/src/ofdm_mode.c +++ b/src/ofdm_mode.c @@ -110,7 +110,6 @@ void ofdm_init_mode(char mode[], struct OFDM_CONFIG *config) { config->txtbits = 0; config->state_machine = "data"; config->ftwindowwidth = 80; config->timing_mx_thresh = 0.10; config->codename = "H_1024_2048_4f"; config->amp_est_mode = 1; - /* custom UW - we use a longer UW with higher bad_uw_errors threshold due to high raw BER */ config->nuwbits = 40; config->bad_uw_errors = 10; uint8_t uw[] = {1,1,0,0, 1,0,1,0, 1,1,1,1, 0,0,0,0, 1,1,1,1, 0,0,0,0}; assert(sizeof(uw) <= MAX_UW_BITS); @@ -119,6 +118,20 @@ void ofdm_init_mode(char mode[], struct OFDM_CONFIG *config) { config->data_mode = "streaming"; config->amp_scale = 300E3; config->clip_gain1 = 2.2; config->clip_gain2 = 0.8; config->tx_bpf_en = true; config->clip_en = true; + } else if (strcmp(mode,"datac4") == 0) { + config->ns=5; config->np=47; config->tcp = 0.006; config->ts = 0.016; config->nc = 4; + config->edge_pilots = 0; + config->txtbits = 0; config->state_machine = "data"; + config->ftwindowwidth = 80; config->timing_mx_thresh = 0.25; + config->codename = "H_1024_2048_4f"; config->amp_est_mode = 1; + config->nuwbits = 32; config->bad_uw_errors = 12; + uint8_t uw[] = {1,1,0,0, 1,0,1,0, 1,1,1,1, 0,0,0,0, 1,1,1,1, 0,0,0,0}; + assert(sizeof(uw) <= MAX_UW_BITS); + memcpy(config->tx_uw, uw, sizeof(uw)); + memcpy(&config->tx_uw[config->nuwbits-sizeof(uw)], uw, sizeof(uw)); + config->data_mode = "streaming"; + config->amp_scale = 300*2.2E3; config->clip_gain1 = 1.5; config->clip_gain2 = 0.8; + config->tx_bpf_en = false; config->clip_en = true; } else { assert(0); From 20b9641140168bcc4f7b09ee9eddf8cfe96747e9 Mon Sep 17 00:00:00 2001 From: drowe67 Date: Thu, 20 Apr 2023 14:13:35 +0930 Subject: [PATCH 23/52] first pass at datac4 ofdm_mod Tx talking to Octave rx ok if we stuff with unused bits with 0's --- src/gp_interleaver.c | 3 ++- src/ofdm_mod.c | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/gp_interleaver.c b/src/gp_interleaver.c index 52a157a50..08a9d135d 100644 --- a/src/gp_interleaver.c +++ b/src/gp_interleaver.c @@ -50,7 +50,8 @@ static const int b_table[] = { 210, 131, /* 2020: HRAb_396_504 with 312 data bits used */ 1024, 641, /* datac3: H_1024_2048_4f */ 1290, 797, /* datac2: H2064_516_sparse */ - 4096, 2531 /* datac1: H_4096_8192_3d */ + 4096, 2531, /* datac1: H_4096_8192_3d */ + 736, 457 /* datac4: H_1024_2048_4f, 448 data bits used */ }; int choose_interleaver_b(int Nbits) diff --git a/src/ofdm_mod.c b/src/ofdm_mod.c index ffd4c51bd..08f96576f 100644 --- a/src/ofdm_mod.c +++ b/src/ofdm_mod.c @@ -265,6 +265,7 @@ int main(int argc, char *argv[]) { ldpc.protection_mode = LDPC_PROT_2020B; } if (!strcmp(mode,"2020C")) set_data_bits_per_frame(&ldpc, 156); + if (!strcmp(mode,"datac4")) set_data_bits_per_frame(&ldpc, 448); Ndatabitsperpacket = ldpc.data_bits_per_frame; if (verbose > 1) { From f369bef47a6e119d88b682cf43cde0257b777e03 Mon Sep 17 00:00:00 2001 From: drowe67 Date: Thu, 20 Apr 2023 15:07:16 +0930 Subject: [PATCH 24/52] changed Octave from zero stuffing -> 1's stuffing to match C code --- CMakeLists.txt | 8 ++++---- octave/ldpc.m | 12 ++++++------ octave/ldpcut.m | 6 +++--- octave/ofdm_lib.m | 4 ++-- 4 files changed, 15 insertions(+), 15 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index c1d969daf..468b7a533 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -359,9 +359,9 @@ endif() COMMAND sh -c "cd ${CMAKE_CURRENT_SOURCE_DIR}/octave; CTEST_SINGLE=1 octave-cli -qf ldpcut.m") set_tests_properties(test_CML_ldpcut PROPERTIES PASS_REGULAR_EXPRESSION "Nerr: 0") - add_test(NAME test_CML_ldpcut_zero_stuffing - COMMAND sh -c "cd ${CMAKE_CURRENT_SOURCE_DIR}/octave; CTEST_ZERO_STUFFING=1 octave-cli -qf ldpcut.m") - set_tests_properties(test_CML_ldpcut_zero_stuffing PROPERTIES PASS_REGULAR_EXPRESSION "Ferrs: 0") + add_test(NAME test_CML_ldpcut_one_stuffing + COMMAND sh -c "cd ${CMAKE_CURRENT_SOURCE_DIR}/octave; CTEST_ONE_STUFFING=1 octave-cli -qf ldpcut.m") + set_tests_properties(test_CML_ldpcut_one_stuffing PROPERTIES PASS_REGULAR_EXPRESSION "Ferrs: 0") # Golay (23,11) unit tests add_test(NAME test_golay23 COMMAND sh -c "${CMAKE_CURRENT_BINARY_DIR}/unittest/golay23") @@ -1328,7 +1328,7 @@ endif(NOT APPLE) # Set common properties for tests that need Octave/CML set_tests_properties( test_CML_ldpcut - test_CML_ldpcut_zero_stuffing + test_CML_ldpcut_one_stuffing test_OFDM_modem_octave_port test_OFDM_modem_octave_port_Nc_31 test_OFDM_modem_octave_datac0_mpp_coded diff --git a/octave/ldpc.m b/octave/ldpc.m index b72351914..0938b8dc7 100644 --- a/octave/ldpc.m +++ b/octave/ldpc.m @@ -96,7 +96,7 @@ function init_cml() code_param.ldpc_parity_bits_per_frame = framesize - code_param.ldpc_data_bits_per_frame; code_param.ldpc_coded_bits_per_frame = framesize; - % these variables support zero stuffing (not using all data bits to lower code rate) + % these variables support 1's stuffing (not using all data bits to lower code rate) code_param.data_bits_per_frame = code_param.ldpc_data_bits_per_frame; code_param.coded_bits_per_frame = code_param.ldpc_coded_bits_per_frame; code_param.coded_syms_per_frame = code_param.coded_bits_per_frame/code_param.bits_per_symbol; @@ -105,9 +105,9 @@ function init_cml() function [codeword s] = ldpc_enc(data, code_param) if code_param.data_bits_per_frame != code_param.ldpc_data_bits_per_frame - % optionally lower the code rate by "zero stuffing" - setting Nunused data bits to 0 + % optionally lower the code rate by "1's stuffing" - setting Nunused data bits to 1 Nunused = code_param.ldpc_data_bits_per_frame - code_param.data_bits_per_frame; - codeword = LdpcEncode([data zeros(1,Nunused)], code_param.H_rows, code_param.P_matrix); + codeword = LdpcEncode([data ones(1,Nunused)], code_param.H_rows, code_param.P_matrix); % remove unused data bits from codeword, as they are known to the receiver and don't need to be transmitted codeword = [ codeword(1:code_param.data_bits_per_frame) codeword(code_param.ldpc_data_bits_per_frame+1:end) ]; else @@ -120,7 +120,7 @@ function init_cml() function [detected_data paritychecks] = ldpc_dec(code_param, max_iterations, ... demod_type, decoder_type, r, ... EsNo, fading) - % handle "zero stuffing" case where we don't use all data bits + % handle "1's stuffing" case where we don't use all data bits Nunused = code_param.ldpc_data_bits_per_frame - code_param.data_bits_per_frame; symbol_likelihood = Demod2D( r, code_param.S_matrix, EsNo, fading); @@ -132,9 +132,9 @@ function init_cml() input_decoder_c = bit_likelihood(1:(code_param.ldpc_coded_bits_per_frame-Nunused)); - % insert "very likley" zero LLRs for unsed data bits (in zero stuffing case) + % insert "very likely" LLRs for unsed data bits (in 1's stuffing case) input_decoder_c = [input_decoder_c(1:code_param.data_bits_per_frame) ... - -100*ones(1,Nunused) ... + 100*ones(1,Nunused) ... input_decoder_c(code_param.data_bits_per_frame+1:end)]; [x_hat paritychecks] = MpDecode( -input_decoder_c, code_param.H_rows, code_param.H_cols, ... diff --git a/octave/ldpcut.m b/octave/ldpcut.m index d1ce52a70..4e8287a59 100644 --- a/octave/ldpcut.m +++ b/octave/ldpcut.m @@ -48,7 +48,7 @@ [code_param framesize rate] = ldpc_init_user(HRA, modulation, mod_order, mapping); end - % optional zero stuffing + % optional 1's stuffing if isfield(sim_in, "data_bits_per_frame") code_param.data_bits_per_frame = sim_in.data_bits_per_frame; code_param.coded_bits_per_frame = code_param.data_bits_per_frame + code_param.ldpc_parity_bits_per_frame; @@ -176,7 +176,7 @@ function test1_single(code="wimax", data_bits_per_frame) if strcmp(code,'dvbs2') framesize = 16200; rate = 0.6; end code_param = ldpc_init_builtin(code, rate, framesize, modulation, mod_order, mapping); - % optional zero stuffing + % optional 1's stuffing if nargin == 2 code_param.data_bits_per_frame = data_bits_per_frame; code_param.coded_bits_per_frame = code_param.data_bits_per_frame + code_param.ldpc_parity_bits_per_frame; @@ -270,7 +270,7 @@ function test3_curves(code,fg=1,Ntrials=100) test1_single return; end -if getenv("CTEST_ZERO_STUFFING") +if getenv("CTEST_ONE_STUFFING") test2_multiple("wimax",10,576); return; end diff --git a/octave/ofdm_lib.m b/octave/ofdm_lib.m index 4289cc40f..2b331d1fc 100644 --- a/octave/ofdm_lib.m +++ b/octave/ofdm_lib.m @@ -1169,9 +1169,9 @@ Can be used for acquisition (coarse timing), and fine timing. Tends function [frame_bits bits_per_frame] = fec_encode(states, code_param, mode, payload_bits) ofdm_load_const; if code_param.data_bits_per_frame != code_param.ldpc_data_bits_per_frame - % optionally lower the code rate by "zero stuffing" - setting Nunused data bits to 0 + % optionally lower the code rate by "one stuffing" - setting Nunused data bits to 1 Nunused = code_param.ldpc_data_bits_per_frame - code_param.data_bits_per_frame; - frame_bits = LdpcEncode([payload_bits zeros(1,Nunused)], code_param.H_rows, code_param.P_matrix); + frame_bits = LdpcEncode([payload_bits ones(1,Nunused)], code_param.H_rows, code_param.P_matrix); % remove unused data bits from codeword, as they are known to the receiver and don't need to be transmitted frame_bits = [ frame_bits(1:code_param.data_bits_per_frame) frame_bits(code_param.ldpc_data_bits_per_frame+1:end) ]; else From a0061018839d6760915e81ccf2911c71ef52449a Mon Sep 17 00:00:00 2001 From: drowe67 Date: Thu, 20 Apr 2023 18:24:44 +0930 Subject: [PATCH 25/52] adjusting levels, wider filter input to make a nicer high SNR scatter diagram. TBD to determine if this adversely affects acquisition performance --- octave/ofdm_ldpc_rx.m | 2 +- octave/ofdm_mode.m | 4 ++-- src/ofdm_mode.c | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/octave/ofdm_ldpc_rx.m b/octave/ofdm_ldpc_rx.m index 438e73e9f..8b42ebce9 100644 --- a/octave/ofdm_ldpc_rx.m +++ b/octave/ofdm_ldpc_rx.m @@ -55,7 +55,7 @@ function ofdm_ldpc_rx(filename, mode="700D", varargin) Nsam = length(rx); prx = 1; if strcmp(mode,"datac4") || strcmp(mode,"datac13") - rx = filter(fir1(100,[1350 1600]/4000),1,rx); + rx = filter(fir1(100,[1250 1700]/4000),1,rx); end % Generate tx frame for BER calcs diff --git a/octave/ofdm_mode.m b/octave/ofdm_mode.m index 64b856521..2b61b5701 100644 --- a/octave/ofdm_mode.m +++ b/octave/ofdm_mode.m @@ -120,7 +120,7 @@ config.tx_uw(end-24+1:end) = [1 1 0 0 1 0 1 0 1 1 1 1 0 0 0 0 1 1 1 1 0 0 0 0]; config.amp_est_mode = 1; config.EsNodB = 3; config.state_machine = "data"; - config.amp_scale = 300*2.3E3; config.clip_gain1 = 1.5; config.clip_gain2 = 0.8; + config.amp_scale = 2*300E3; config.clip_gain1 = 1.5; config.clip_gain2 = 0.8; elseif strcmp(mode,"datac13") Ns=5; config.Np=18; Tcp = 0.006; Ts = 0.016; Nc = 3; config.data_mode = "streaming"; config.edge_pilots = 0; @@ -131,7 +131,7 @@ config.tx_uw(end-24+1:end) = [1 1 0 0 1 0 1 0 1 1 1 1 0 0 0 0 1 1 1 1 0 0 0 0]; config.amp_est_mode = 1; config.EsNodB = 3; config.state_machine = "data"; - config.amp_scale = 300*2.3E3; config.clip_gain1 = 1.5; config.clip_gain2 = 0.8; + config.amp_scale = 2.5*300E3; config.clip_gain1 = 1.5; config.clip_gain2 = 0.8; elseif strcmp(mode,"1") Ns=5; config.Np=10; Tcp=0; Tframe = 0.1; Ts = Tframe/Ns; Nc = 1; else diff --git a/src/ofdm_mode.c b/src/ofdm_mode.c index c05136b2f..d8d3869b8 100644 --- a/src/ofdm_mode.c +++ b/src/ofdm_mode.c @@ -130,8 +130,8 @@ void ofdm_init_mode(char mode[], struct OFDM_CONFIG *config) { memcpy(config->tx_uw, uw, sizeof(uw)); memcpy(&config->tx_uw[config->nuwbits-sizeof(uw)], uw, sizeof(uw)); config->data_mode = "streaming"; - config->amp_scale = 300*2.2E3; config->clip_gain1 = 1.5; config->clip_gain2 = 0.8; - config->tx_bpf_en = false; config->clip_en = true; + config->amp_scale = 2*300E3; config->clip_gain1 = 1.5; config->clip_gain2 = 0.8; + config->tx_bpf_en = false; config->clip_en = false; } else { assert(0); From c183a444b28fd02cc77601da2d82568340623d3c Mon Sep 17 00:00:00 2001 From: drowe67 Date: Thu, 20 Apr 2023 19:09:24 +0930 Subject: [PATCH 26/52] subtle off by one error in nuwframes calculation --- src/ofdm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ofdm.c b/src/ofdm.c index 41e3d1548..da07a13fa 100644 --- a/src/ofdm.c +++ b/src/ofdm.c @@ -468,7 +468,7 @@ struct OFDM *ofdm_create(const struct OFDM_CONFIG *config) { // work out how many frames UW is spread over int symsperframe = ofdm->bitsperframe / ofdm->bps; - ofdm->nuwframes = (int) ceilf((float)ofdm->uw_ind_sym[nuwsyms-1]/symsperframe); + ofdm->nuwframes = (int) ceilf((float)(ofdm->uw_ind_sym[nuwsyms-1]+1)/symsperframe); ofdm->tx_uw_syms = MALLOC(sizeof (complex float) * (ofdm->nuwbits / ofdm->bps)); assert(ofdm->tx_uw_syms != NULL); From 1b14c7d009a2f16f9617037fc5ebfa62ec1309b4 Mon Sep 17 00:00:00 2001 From: drowe67 Date: Thu, 20 Apr 2023 19:11:48 +0930 Subject: [PATCH 27/52] added datac13, ofdm_demod working for datac4 and datac13 --- src/gp_interleaver.c | 5 +++-- src/ofdm_demod.c | 6 ++++-- src/ofdm_mod.c | 3 ++- src/ofdm_mode.c | 16 +++++++++++++++- 4 files changed, 24 insertions(+), 6 deletions(-) diff --git a/src/gp_interleaver.c b/src/gp_interleaver.c index 08a9d135d..26e74bf6e 100644 --- a/src/gp_interleaver.c +++ b/src/gp_interleaver.c @@ -47,11 +47,12 @@ static const int b_table[] = { 106, 67, /* 2020B: (112,56) partial protection */ 112, 71, /* 700D: HRA_112_112 */ 128, 83, /* datac0: H_128_256_5 */ + 192, 127, /* datac13: H_256_512_4, 128 data bits used */ 210, 131, /* 2020: HRAb_396_504 with 312 data bits used */ + 736, 457, /* datac4: H_1024_2048_4f, 448 data bits used */ 1024, 641, /* datac3: H_1024_2048_4f */ 1290, 797, /* datac2: H2064_516_sparse */ - 4096, 2531, /* datac1: H_4096_8192_3d */ - 736, 457 /* datac4: H_1024_2048_4f, 448 data bits used */ + 4096, 2531 /* datac1: H_4096_8192_3d */ }; int choose_interleaver_b(int Nbits) diff --git a/src/ofdm_demod.c b/src/ofdm_demod.c index 05e575a69..d12baa9f6 100644 --- a/src/ofdm_demod.c +++ b/src/ofdm_demod.c @@ -67,7 +67,7 @@ void opt_help() { fprintf(stderr, " --in filename Name of InputModemRawFile\n"); fprintf(stderr, " --out filename Name of OutputOneCharPerBitFile\n"); fprintf(stderr, " --log filename Octave log file for testing\n"); - fprintf(stderr, " --mode modeName Predefined mode e.g. 700D|2020|datac1\n"); + fprintf(stderr, " --mode modeName Predefined mode e.g. 700D|2020|datac1 etc\n"); fprintf(stderr, " --nc [17..62] Number of Carriers (17 default, 62 max)\n"); fprintf(stderr, " --np Number of packets\n"); fprintf(stderr, " --ns Nframes One pilot every ns symbols (8 default)\n"); @@ -329,7 +329,7 @@ int main(int argc, char *argv[]) { int Nsymsperframe = Nbitsperframe / ofdm_config->bps; int Nsymsperpacket = Nbitsperpacket / ofdm_config->bps; int Nmaxsamperframe = ofdm_get_max_samples_per_frame(ofdm); - int Npayloadbitsperframe = ofdm_bitsperframe - ofdm_nuwbits - ofdm_ntxtbits; + int Npayloadbitsperframe = ofdm_bitsperframe; int Npayloadbitsperpacket = Nbitsperpacket - ofdm_nuwbits - ofdm_ntxtbits; int Npayloadsymsperframe = Npayloadbitsperframe/ofdm_config->bps; int Npayloadsymsperpacket = Npayloadbitsperpacket/ofdm_config->bps; @@ -351,6 +351,8 @@ int main(int argc, char *argv[]) { ldpc.protection_mode = LDPC_PROT_2020B; } if (!strcmp(mode,"2020C")) set_data_bits_per_frame(&ldpc, 156); + if (!strcmp(mode,"datac4")) set_data_bits_per_frame(&ldpc, 448); + if (!strcmp(mode,"datac13")) set_data_bits_per_frame(&ldpc, 128); Ndatabitsperpacket = ldpc.data_bits_per_frame; if (verbose > 1) { diff --git a/src/ofdm_mod.c b/src/ofdm_mod.c index 08f96576f..9c6422f68 100644 --- a/src/ofdm_mod.c +++ b/src/ofdm_mod.c @@ -52,7 +52,7 @@ void opt_help() { fprintf(stderr, "\nusage: %s [options]\n\n", progname); fprintf(stderr, " --in filename Name of InputOneCharPerBitFile\n"); fprintf(stderr, " --out filename Name of OutputModemRawFile\n"); - fprintf(stderr, " --mode modeName Predefined mode 700D|700E|2020|2020B|datac0|datac1|datac3\n"); + fprintf(stderr, " --mode modeName Predefined mode 700D|700E|2020|2020B|datac0 ... etc\n"); fprintf(stderr, " --nc [17..62] Number of Carriers (17 default, 62 max)\n"); fprintf(stderr, " --ns symbols One pilot every ns symbols (8 default)\n"); fprintf(stderr, " --tcp Nsecs Cyclic Prefix Duration (.002 default)\n"); @@ -266,6 +266,7 @@ int main(int argc, char *argv[]) { } if (!strcmp(mode,"2020C")) set_data_bits_per_frame(&ldpc, 156); if (!strcmp(mode,"datac4")) set_data_bits_per_frame(&ldpc, 448); + if (!strcmp(mode,"datac13")) set_data_bits_per_frame(&ldpc, 128); Ndatabitsperpacket = ldpc.data_bits_per_frame; if (verbose > 1) { diff --git a/src/ofdm_mode.c b/src/ofdm_mode.c index d8d3869b8..c74ab7f08 100644 --- a/src/ofdm_mode.c +++ b/src/ofdm_mode.c @@ -132,7 +132,21 @@ void ofdm_init_mode(char mode[], struct OFDM_CONFIG *config) { config->data_mode = "streaming"; config->amp_scale = 2*300E3; config->clip_gain1 = 1.5; config->clip_gain2 = 0.8; config->tx_bpf_en = false; config->clip_en = false; - } +} else if (strcmp(mode,"datac13") == 0) { + config->ns=5; config->np=18; config->tcp = 0.006; config->ts = 0.016; config->nc = 3; + config->edge_pilots = 0; + config->txtbits = 0; config->state_machine = "data"; + config->ftwindowwidth = 80; config->timing_mx_thresh = 0.25; + config->codename = "H_256_512_4"; config->amp_est_mode = 1; + config->nuwbits = 48; config->bad_uw_errors = 18; + uint8_t uw[] = {1,1,0,0, 1,0,1,0, 1,1,1,1, 0,0,0,0, 1,1,1,1, 0,0,0,0}; + assert(sizeof(uw) <= MAX_UW_BITS); + memcpy(config->tx_uw, uw, sizeof(uw)); + memcpy(&config->tx_uw[config->nuwbits-sizeof(uw)], uw, sizeof(uw)); + config->data_mode = "streaming"; + config->amp_scale = 2.5*300E3; config->clip_gain1 = 1.5; config->clip_gain2 = 0.8; + config->tx_bpf_en = false; config->clip_en = false; + } else { assert(0); } From 8ac925758bad27cdf15fd9d943b1d0b3680a3041 Mon Sep 17 00:00:00 2001 From: drowe67 Date: Fri, 21 Apr 2023 10:08:46 +0930 Subject: [PATCH 28/52] first pass datac4/datac14 ctests to help QA next stages of C port --- CMakeLists.txt | 42 +++++++++++++++++++++++++++++++++++++++--- 1 file changed, 39 insertions(+), 3 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 468b7a533..2fe9c8bcc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -411,6 +411,10 @@ endif() DISPLAY=\"\" octave-cli -qf fdmdv_ut.m") set_tests_properties(test_FDMDV_modem_octave_c PROPERTIES PASS_REGULAR_EXPRESSION "errors......: 0") + # ------------------------------------------------------------------------- + # COHPSK Modem + # ------------------------------------------------------------------------- + add_test(NAME test_COHPSK_modem_octave_port COMMAND sh -c "$ && DISPLAY=\"\" octave-cli --no-gui -qf ${CMAKE_CURRENT_SOURCE_DIR}/octave/tcohpsk.m" WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/octave) @@ -592,8 +596,9 @@ endif() # ------------------------------------------------------------------------- # To integrate a new mode/waveform we prototype in Octave, get the core OFDM modem - # running in C, then the FreeDV API. Here we test Octave and the C versions of the - # OFDM modem working together, to help prevent any bit rot between them + # running in C (ofdm_mod & ofdm_demod), then the FreeDV API (frredv_tx & freedv_rx). + # Here we test Octave and the C versions of the OFDM modem working together, to help + # prevent any bit rot between them # DATAC0 burst mode Octave Tx, C Rx add_test(NAME test_OFDM_modem_datac0_octave_burst @@ -638,7 +643,36 @@ endif() ./ch - - --No -17 | ./ofdm_demod --mode datac0 --out /dev/null --testframes --ldpc --verbose 2 --packetsperburst 1") - # ------------------------------------------------------------------------- + # DATAC4 C Tx, Octave Rx, burst mode + add_test(NAME test_OFDM_modem_datac4_octave + COMMAND sh -c "cd ${CMAKE_CURRENT_BINARY_DIR}; + ./src/ofdm_mod --mode datac4 --in /dev/zero --testframes 1 --verbose 1 --ldpc --bursts 5 > test.raw; + cd ${CMAKE_CURRENT_SOURCE_DIR}/octave; + DISPLAY=\"\" octave-cli -qf --eval 'ofdm_ldpc_rx(\"${CMAKE_CURRENT_BINARY_DIR}/test.raw\",\"datac4\",\"packetsperburst\",1)'") + set_tests_properties(test_OFDM_modem_datac3_octave PROPERTIES PASS_REGULAR_EXPRESSION "Coded PER: 0.0000 Pckts: 5") + + # DATAC13 Octave Tx, C Rx, burst mode + add_test(NAME test_OFDM_modem_datac13_octave + COMMAND sh -c "cd ${CMAKE_CURRENT_SOURCE_DIR}/octave; + DISPLAY=\"\" octave-cli -qf --eval 'ofdm_ldpc_tx(\"${CMAKE_CURRENT_BINARY_DIR}/src/test.raw\",\"datac13\",1,3,\"awgn\",\"bursts\",5)'; + cd ${CMAKE_CURRENT_BINARY_DIR}/src; + cat test.raw | ./ofdm_demod --mode datac13 --out /dev/null --testframes --ldpc --verbose 2 --packetsperburst 1") + + # DATAC4 C Tx, C Rx, burst mode + add_test(NAME test_OFDM_modem_datac4_ldpc_burst + COMMAND sh -c "cd ${CMAKE_CURRENT_BINARY_DIR}/src; + ./ofdm_mod --mode datac4 --in /dev/zero --testframes 1 --verbose 1 --ldpc --bursts 10 | + ./ch - - --No -17 | + ./ofdm_demod --mode datac4 --out /dev/null --testframes --ldpc --verbose 2 --packetsperburst 1") + + # DATAC13 C Tx, C Rx, burst mode + add_test(NAME test_OFDM_modem_datac13_ldpc_burst + COMMAND sh -c "cd ${CMAKE_CURRENT_BINARY_DIR}/src; + ./ofdm_mod --mode datac13 --in /dev/zero --testframes 1 --verbose 1 --ldpc --bursts 10 | + ./ch - - --No -17 | + ./ofdm_demod --mode datac13 --out /dev/null --testframes --ldpc --verbose 2 --packetsperburst 1") + + # ------------------------------------------------------------------------- # LDPC # ------------------------------------------------------------------------- @@ -1335,6 +1369,8 @@ endif(NOT APPLE) test_OFDM_modem_datac0_octave_burst test_OFDM_modem_datac1_octave test_OFDM_modem_datac3_octave + test_OFDM_modem_datac4_octave + test_OFDM_modem_datac13_octave test_fsk_lib_4fsk_ldpc test_OFDM_modem_datac0_compression PROPERTIES From ac69d2e0f7f123c489d00369b104bba380eb7c12 Mon Sep 17 00:00:00 2001 From: drowe67 Date: Fri, 21 Apr 2023 10:32:51 +0930 Subject: [PATCH 29/52] moving mode specifc 1s stuffing out of ofdm_mod & ofdm_demod and into utility function --- src/interldpc.c | 13 +++++++++++++ src/interldpc.h | 1 + src/ofdm_demod.c | 13 ++----------- src/ofdm_mod.c | 13 ++----------- 4 files changed, 18 insertions(+), 22 deletions(-) diff --git a/src/interldpc.c b/src/interldpc.c index 5ca300b5c..b17e9b7eb 100644 --- a/src/interldpc.c +++ b/src/interldpc.c @@ -64,6 +64,19 @@ void set_data_bits_per_frame(struct LDPC *ldpc, int new_data_bits_per_frame) { ldpc->coded_bits_per_frame = ldpc->data_bits_per_frame + ldpc->NumberParityBits; } +/* 1' stuffing (code rate reduction) - tweak LDPC code setup for selected modes */ +void ldpc_mode_specific_setup(struct OFDM *ofdm, struct LDPC *ldpc) { + /* mode specific set up */ + if (!strcmp(ofdm->mode,"2020")) set_data_bits_per_frame(ldpc, 312); + if (!strcmp(ofdm->mode,"2020B")) { + set_data_bits_per_frame(ldpc, 156); + ldpc->protection_mode = LDPC_PROT_2020B; + } + if (!strcmp(ofdm->mode,"2020C")) set_data_bits_per_frame(ldpc, 156); + if (!strcmp(ofdm->mode,"datac4")) set_data_bits_per_frame(ldpc, 448); + if (!strcmp(ofdm->mode,"datac13")) set_data_bits_per_frame(ldpc, 128); +} + /* LDPC encode frame - generate parity bits and a codeword, applying the selected FEC protection scheme */ void ldpc_encode_frame(struct LDPC *ldpc, int codeword[], unsigned char tx_bits_char[]) { diff --git a/src/interldpc.h b/src/interldpc.h index 096f5b408..2c18f6283 100644 --- a/src/interldpc.h +++ b/src/interldpc.h @@ -41,6 +41,7 @@ void set_up_ldpc_constants(struct LDPC *ldpc, int code_length, int parity_bits); void set_data_bits_per_frame(struct LDPC *ldpc, int new_data_bits_per_frame); +void ldpc_mode_specific_setup(struct OFDM *ofdm, struct LDPC *ldpc); void ldpc_encode_frame(struct LDPC *ldpc, int codeword[], unsigned char tx_bits_char[]); void qpsk_modulate_frame(COMP tx_symbols[], int codeword[], int n); void ldpc_decode_frame(struct LDPC *ldpc, int *parityCheckCount, int *iter, uint8_t out_char[], float llr[]); diff --git a/src/ofdm_demod.c b/src/ofdm_demod.c index d12baa9f6..2b3307b63 100644 --- a/src/ofdm_demod.c +++ b/src/ofdm_demod.c @@ -342,20 +342,11 @@ int main(int argc, char *argv[]) { if (ldpc_en) { ldpc_codes_setup(&ldpc, ofdm->codename); - if (verbose > 1) { fprintf(stderr, "using: %s\n", ofdm->codename); } - - /* mode specific set up */ - if (!strcmp(mode,"2020")) set_data_bits_per_frame(&ldpc, 312); - if (!strcmp(mode,"2020B")) { - set_data_bits_per_frame(&ldpc, 156); - ldpc.protection_mode = LDPC_PROT_2020B; - } - if (!strcmp(mode,"2020C")) set_data_bits_per_frame(&ldpc, 156); - if (!strcmp(mode,"datac4")) set_data_bits_per_frame(&ldpc, 448); - if (!strcmp(mode,"datac13")) set_data_bits_per_frame(&ldpc, 128); + ldpc_mode_specific_setup(ofdm, &ldpc); Ndatabitsperpacket = ldpc.data_bits_per_frame; if (verbose > 1) { + fprintf(stderr, "using: %s\n", ofdm->codename); fprintf(stderr, "LDPC codeword data bits = %d\n", ldpc.ldpc_data_bits_per_frame); fprintf(stderr, "LDPC codeword total bits = %d\n", ldpc.ldpc_coded_bits_per_frame); fprintf(stderr, "LDPC codeword data bits used = %d\n", Ndatabitsperpacket); diff --git a/src/ofdm_mod.c b/src/ofdm_mod.c index 9c6422f68..8fe4d2d42 100644 --- a/src/ofdm_mod.c +++ b/src/ofdm_mod.c @@ -256,20 +256,11 @@ int main(int argc, char *argv[]) { struct LDPC ldpc; if (ldpc_en) { ldpc_codes_setup(&ldpc, ofdm->codename); - if (verbose > 1) { fprintf(stderr, "using: %s\n", ofdm->codename); } - - /* mode specific set up */ - if (!strcmp(mode,"2020")) set_data_bits_per_frame(&ldpc, 312); - if (!strcmp(mode,"2020B")) { - set_data_bits_per_frame(&ldpc, 156); - ldpc.protection_mode = LDPC_PROT_2020B; - } - if (!strcmp(mode,"2020C")) set_data_bits_per_frame(&ldpc, 156); - if (!strcmp(mode,"datac4")) set_data_bits_per_frame(&ldpc, 448); - if (!strcmp(mode,"datac13")) set_data_bits_per_frame(&ldpc, 128); + ldpc_mode_specific_setup(ofdm, &ldpc); Ndatabitsperpacket = ldpc.data_bits_per_frame; if (verbose > 1) { + fprintf(stderr, "using: %s\n", ofdm->codename); fprintf(stderr, "LDPC codeword data bits = %d\n", ldpc.ldpc_data_bits_per_frame); fprintf(stderr, "LDPC codeword total bits = %d\n", ldpc.ldpc_coded_bits_per_frame); fprintf(stderr, "LDPC codeword data bits used = %d\n", Ndatabitsperpacket); From 4d090c7dd82cbe395975d90f05efec26f0d7d8f6 Mon Sep 17 00:00:00 2001 From: drowe67 Date: Fri, 21 Apr 2023 10:50:49 +0930 Subject: [PATCH 30/52] hooks for mode-specific 1's stuffing --- src/freedv_2020.c | 10 ++-------- src/freedv_700.c | 1 + 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/src/freedv_2020.c b/src/freedv_2020.c index 2977ee9b3..d33390d65 100644 --- a/src/freedv_2020.c +++ b/src/freedv_2020.c @@ -4,7 +4,7 @@ AUTHOR......: David Rowe DATE CREATED: May 2020 - Functions that implement the FreeDV 2020 mode. + Functions that implement the FreeDV 2020 modes. \*---------------------------------------------------------------------------*/ @@ -62,29 +62,23 @@ void freedv_2020x_open(struct freedv *f) { assert(f->ldpc != NULL); ldpc_codes_setup(f->ldpc, f->ofdm->codename); - int data_bits_per_frame; + ldpc_mode_specific_setup(f->ofdm, f->ldpc); int vq_type; switch (f->mode) { case FREEDV_MODE_2020: - data_bits_per_frame = 312; vq_type = 1; /* vanilla VQ */ break; case FREEDV_MODE_2020B: - f->ldpc->protection_mode = LDPC_PROT_2020B; - data_bits_per_frame = 156; vq_type = 2; /* index optimised VQ for increased robustness to single bit errors */ break; case FREEDV_MODE_2020C: - data_bits_per_frame = 156; vq_type = 2; /* index optimised VQ for increased robustness to single bit errors */ break; default: assert(0); } - set_data_bits_per_frame(f->ldpc, data_bits_per_frame); int coded_syms_per_frame = f->ldpc->coded_bits_per_frame/f->ofdm->bps; - f->ofdm_bitsperframe = ofdm_get_bits_per_frame(f->ofdm); f->ofdm_nuwbits = f->ofdm->config.nuwbits; f->ofdm_ntxtbits = f->ofdm->config.txtbits; diff --git a/src/freedv_700.c b/src/freedv_700.c index 455268ceb..8ef73e8ee 100644 --- a/src/freedv_700.c +++ b/src/freedv_700.c @@ -117,6 +117,7 @@ void freedv_ofdm_voice_open(struct freedv *f, char *mode) { assert(f->ldpc != NULL); ldpc_codes_setup(f->ldpc, f->ofdm->codename); + ldpc_mode_specific_setup(f->ofdm, f->ldpc); #ifdef __EMBEDDED__ f->ldpc->max_iter = 10; /* limit LDPC decoder iterations to limit CPU load */ #endif From 08e6c6322aaf32214f6ff3a5179232bf425a86e3 Mon Sep 17 00:00:00 2001 From: drowe67 Date: Fri, 21 Apr 2023 10:58:26 +0930 Subject: [PATCH 31/52] bug fix for 2020 --- src/freedv_2020.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/freedv_2020.c b/src/freedv_2020.c index d33390d65..eaeec996a 100644 --- a/src/freedv_2020.c +++ b/src/freedv_2020.c @@ -89,7 +89,7 @@ void freedv_2020x_open(struct freedv *f) { fprintf(stderr, "vq_type = %d\n", vq_type); fprintf(stderr, "ldpc_data_bits_per_frame = %d\n", f->ldpc->ldpc_data_bits_per_frame); fprintf(stderr, "ldpc_coded_bits_per_frame = %d\n", f->ldpc->ldpc_coded_bits_per_frame); - fprintf(stderr, "data_bits_per_frame = %d\n", data_bits_per_frame); + fprintf(stderr, "data_bits_per_frame = %d\n", f->ldpc->data_bits_per_frame); fprintf(stderr, "coded_bits_per_frame = %d\n", f->ldpc->coded_bits_per_frame); fprintf(stderr, "coded_syms_per_frame = %d\n", f->ldpc->coded_bits_per_frame/f->ofdm->bps); fprintf(stderr, "ofdm_bits_per_frame = %d\n", f->ofdm_bitsperframe); From 4aa3250dddd753db9ef987635750cff31279c73d Mon Sep 17 00:00:00 2001 From: drowe67 Date: Fri, 21 Apr 2023 12:09:38 +0930 Subject: [PATCH 32/52] first pass FreeDV API support for datac4 & datac13, and ctests so QA next steps --- CMakeLists.txt | 32 ++++++++++++++++++++++++++++++++ src/freedv_700.c | 10 +++++++--- src/freedv_api.c | 28 +++++++++++++++++++++------- src/freedv_api.h | 8 ++++++++ src/freedv_data_raw_rx.c | 4 +++- src/freedv_data_raw_tx.c | 4 +++- src/modem_stats.h | 2 +- 7 files changed, 75 insertions(+), 13 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 2fe9c8bcc..79fc87437 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1049,6 +1049,24 @@ if (NOT APPLE) ./freedv_data_raw_tx --testframes 10 DATAC1 /dev/zero /dev/null") set_tests_properties(test_memory_leak_FreeDV_DATAC1_tx PROPERTIES PASS_REGULAR_EXPRESSION "ERROR SUMMARY: 0 errors") + add_test(NAME test_memory_leak_FreeDV_DATAC3_tx + COMMAND sh -c "cd ${CMAKE_CURRENT_BINARY_DIR}/src; + valgrind --leak-check=full --show-leak-kinds=all --track-origins=yes \ + ./freedv_data_raw_tx --testframes 10 DATAC3 /dev/zero /dev/null") + set_tests_properties(test_memory_leak_FreeDV_DATAC3_tx PROPERTIES PASS_REGULAR_EXPRESSION "ERROR SUMMARY: 0 errors") + + add_test(NAME test_memory_leak_FreeDV_DATAC4_tx + COMMAND sh -c "cd ${CMAKE_CURRENT_BINARY_DIR}/src; + valgrind --leak-check=full --show-leak-kinds=all --track-origins=yes \ + ./freedv_data_raw_tx --testframes 10 DATAC4 /dev/zero /dev/null") + set_tests_properties(test_memory_leak_FreeDV_DATAC4_tx PROPERTIES PASS_REGULAR_EXPRESSION "ERROR SUMMARY: 0 errors") + + add_test(NAME test_memory_leak_FreeDV_DATAC13_tx + COMMAND sh -c "cd ${CMAKE_CURRENT_BINARY_DIR}/src; + valgrind --leak-check=full --show-leak-kinds=all --track-origins=yes \ + ./freedv_data_raw_tx --testframes 10 DATAC13 /dev/zero /dev/null") + set_tests_properties(test_memory_leak_FreeDV_DATAC13_tx PROPERTIES PASS_REGULAR_EXPRESSION "ERROR SUMMARY: 0 errors") + add_test(NAME test_memory_leak_FreeDV_700E_tx COMMAND sh -c "cd ${CMAKE_CURRENT_BINARY_DIR}/src; valgrind --leak-check=full --show-leak-kinds=all --track-origins=yes \ @@ -1286,6 +1304,20 @@ endif(NOT APPLE) ./freedv_data_raw_rx DATAC3 - binaryOut.bin -v; diff binaryIn.bin binaryOut.bin") + add_test(NAME test_freedv_data_raw_ofdm_datac4_burst_file + COMMAND sh -c "cd ${CMAKE_CURRENT_BINARY_DIR}/src; + head -c $((54*10)) binaryIn.bin; + ./freedv_data_raw_tx DATAC4 binaryIn.bin - --bursts 10 | + ./freedv_data_raw_rx DATAC4 - binaryOut.bin -v; + diff binaryIn.bin binaryOut.bin") + + add_test(NAME test_freedv_data_raw_ofdm_datac13_burst_file + COMMAND sh -c "cd ${CMAKE_CURRENT_BINARY_DIR}/src; + head -c $((14*10)) binaryIn.bin; + ./freedv_data_raw_tx DATAC13 binaryIn.bin - --bursts 10 | + ./freedv_data_raw_rx DATAC13 - binaryOut.bin -v; + diff binaryIn.bin binaryOut.bin") + # FSK LDPC default 100 bit/s 2FSK, enough noise for several % raw BER to give # FEC/acquisition a work out, bursts of 1 frame as that stresses acquisition add_test(NAME test_freedv_data_raw_fsk_ldpc_100 diff --git a/src/freedv_700.c b/src/freedv_700.c index 8ef73e8ee..08787253c 100644 --- a/src/freedv_700.c +++ b/src/freedv_700.c @@ -172,6 +172,8 @@ void freedv_ofdm_data_open(struct freedv *f) { if (f->mode == FREEDV_MODE_DATAC0) strcpy(mode, "datac0"); if (f->mode == FREEDV_MODE_DATAC1) strcpy(mode, "datac1"); if (f->mode == FREEDV_MODE_DATAC3) strcpy(mode, "datac3"); + if (f->mode == FREEDV_MODE_DATAC4) strcpy(mode, "datac4"); + if (f->mode == FREEDV_MODE_DATAC13) strcpy(mode, "datac13"); ofdm_init_mode(mode, &ofdm_config); f->ofdm = ofdm_create(&ofdm_config); @@ -181,6 +183,7 @@ void freedv_ofdm_data_open(struct freedv *f) { f->ldpc = (struct LDPC*)MALLOC(sizeof(struct LDPC)); assert(f->ldpc != NULL); ldpc_codes_setup(f->ldpc, f->ofdm->codename); + ldpc_mode_specific_setup(f->ofdm, f->ldpc); #ifdef __EMBEDDED__ f->ldpc->max_iter = 10; /* limit LDPC decoder iterations to limit CPU load */ #endif @@ -454,7 +457,8 @@ int freedv_comp_short_rx_ofdm(struct freedv *f, void *demod_in_8kHz, int demod_i uint8_t decoded_codeword[Npayloadbitsperpacket]; symbols_to_llrs(llr, payload_syms_de, payload_amps_de, EsNo, ofdm->mean_amp, Npayloadsymsperpacket); - iter = run_ldpc_decoder(ldpc, decoded_codeword, llr, &parityCheckCount); + ldpc_decode_frame(ldpc, &parityCheckCount, &iter, decoded_codeword, llr); + //iter = run_ldpc_decoder(ldpc, decoded_codeword, llr, &parityCheckCount); memcpy(f->rx_payload_bits, decoded_codeword, Ndatabitsperpacket); if (strlen(ofdm->data_mode)) { @@ -535,7 +539,7 @@ int freedv_comp_short_rx_ofdm(struct freedv *f, void *demod_in_8kHz, int demod_i print_truncated = 1; if (print_full) { fprintf(stderr, "%3d nin: %4d st: %-6s euw: %2d %2d mf: %2d f: %5.1f pbw: %d snr: %4.1f eraw: %4d ecdd: %4d iter: %3d " - "pcc: %3d rxst: %s\n", + "pcc: %4d rxst: %s\n", f->frames++, ofdm->nin, ofdm_statemode[ofdm->last_sync_state], ofdm->uw_errors, @@ -546,7 +550,7 @@ int freedv_comp_short_rx_ofdm(struct freedv *f, void *demod_in_8kHz, int demod_i } if (print_truncated) { fprintf(stderr, "%3d nin: %4d st: %-6s euw: %2d %2d mf: %2d f: %5.1f pbw: %d " - " rxst: %s\n", + " rxst: %s\n", f->frames++, ofdm->nin, ofdm_statemode[ofdm->last_sync_state], ofdm->uw_errors, diff --git a/src/freedv_api.c b/src/freedv_api.c index 3fb5d0556..f17232c07 100644 --- a/src/freedv_api.c +++ b/src/freedv_api.c @@ -133,7 +133,9 @@ struct freedv *freedv_open_advanced(int mode, struct freedv_advanced *adv) { FDV_MODE_ACTIVE( FREEDV_MODE_FSK_LDPC, mode) || FDV_MODE_ACTIVE( FREEDV_MODE_DATAC0, mode) || FDV_MODE_ACTIVE( FREEDV_MODE_DATAC1, mode) || - FDV_MODE_ACTIVE( FREEDV_MODE_DATAC3, mode)) == false) return NULL; + FDV_MODE_ACTIVE( FREEDV_MODE_DATAC3, mode) || + FDV_MODE_ACTIVE( FREEDV_MODE_DATAC4, mode) || + FDV_MODE_ACTIVE( FREEDV_MODE_DATAC13, mode)) == false) return NULL; /* set everything to zero just in case */ f = (struct freedv*)CALLOC(1, sizeof(struct freedv)); @@ -158,6 +160,8 @@ struct freedv *freedv_open_advanced(int mode, struct freedv_advanced *adv) { if (FDV_MODE_ACTIVE( FREEDV_MODE_DATAC0, mode)) freedv_ofdm_data_open(f); if (FDV_MODE_ACTIVE( FREEDV_MODE_DATAC1, mode)) freedv_ofdm_data_open(f); if (FDV_MODE_ACTIVE( FREEDV_MODE_DATAC3, mode)) freedv_ofdm_data_open(f); + if (FDV_MODE_ACTIVE( FREEDV_MODE_DATAC4, mode)) freedv_ofdm_data_open(f); + if (FDV_MODE_ACTIVE( FREEDV_MODE_DATAC13, mode)) freedv_ofdm_data_open(f); varicode_decode_init(&f->varicode_dec_states, 1); @@ -237,13 +241,15 @@ void freedv_close(struct freedv *freedv) { if (FDV_MODE_ACTIVE( FREEDV_MODE_DATAC0, freedv->mode) || FDV_MODE_ACTIVE( FREEDV_MODE_DATAC1, freedv->mode) || - FDV_MODE_ACTIVE( FREEDV_MODE_DATAC3, freedv->mode)) + FDV_MODE_ACTIVE( FREEDV_MODE_DATAC3, freedv->mode) || + FDV_MODE_ACTIVE( FREEDV_MODE_DATAC4, freedv->mode) || + FDV_MODE_ACTIVE( FREEDV_MODE_DATAC13, freedv->mode)) { FREE(freedv->rx_syms); FREE(freedv->rx_amps); FREE(freedv->ldpc); ofdm_destroy(freedv->ofdm); - } + } FREE(freedv); } @@ -267,13 +273,17 @@ static int is_ofdm_mode(struct freedv *f) { FDV_MODE_ACTIVE( FREEDV_MODE_700E, f->mode) || FDV_MODE_ACTIVE( FREEDV_MODE_DATAC0, f->mode) || FDV_MODE_ACTIVE( FREEDV_MODE_DATAC1, f->mode) || - FDV_MODE_ACTIVE( FREEDV_MODE_DATAC3, f->mode); + FDV_MODE_ACTIVE( FREEDV_MODE_DATAC3, f->mode) || + FDV_MODE_ACTIVE( FREEDV_MODE_DATAC4, f->mode) || + FDV_MODE_ACTIVE( FREEDV_MODE_DATAC13, f->mode); } static int is_ofdm_data_mode(struct freedv *f) { return FDV_MODE_ACTIVE( FREEDV_MODE_DATAC0, f->mode) || FDV_MODE_ACTIVE( FREEDV_MODE_DATAC1, f->mode) || - FDV_MODE_ACTIVE( FREEDV_MODE_DATAC3, f->mode); + FDV_MODE_ACTIVE( FREEDV_MODE_DATAC3, f->mode) || + FDV_MODE_ACTIVE( FREEDV_MODE_DATAC4, f->mode) || + FDV_MODE_ACTIVE( FREEDV_MODE_DATAC13, f->mode); } /*---------------------------------------------------------------------------*\ @@ -452,7 +462,9 @@ void freedv_rawdatacomptx(struct freedv *f, COMP mod_out[], unsigned char *packe if (FDV_MODE_ACTIVE( FREEDV_MODE_700D, f->mode) || FDV_MODE_ACTIVE( FREEDV_MODE_DATAC0, f->mode) || FDV_MODE_ACTIVE( FREEDV_MODE_DATAC1, f->mode) || - FDV_MODE_ACTIVE( FREEDV_MODE_DATAC3, f->mode)) freedv_comptx_ofdm(f, mod_out); + FDV_MODE_ACTIVE( FREEDV_MODE_DATAC3, f->mode) || + FDV_MODE_ACTIVE( FREEDV_MODE_DATAC4, f->mode) || + FDV_MODE_ACTIVE( FREEDV_MODE_DATAC13, f->mode)) freedv_comptx_ofdm(f, mod_out); if (FDV_MODE_ACTIVE( FREEDV_MODE_FSK_LDPC, f->mode)) { freedv_tx_fsk_ldpc_data(f, mod_out); @@ -1014,7 +1026,9 @@ int freedv_rawdatacomprx(struct freedv *f, unsigned char *packed_payload_bits, C if (FDV_MODE_ACTIVE( FREEDV_MODE_700D, f->mode) || FDV_MODE_ACTIVE( FREEDV_MODE_DATAC0, f->mode) || FDV_MODE_ACTIVE( FREEDV_MODE_DATAC1, f->mode) || - FDV_MODE_ACTIVE( FREEDV_MODE_DATAC3, f->mode)) rx_status = freedv_comp_short_rx_ofdm(f, (void*)demod_in, 0, 1.0f); + FDV_MODE_ACTIVE( FREEDV_MODE_DATAC3, f->mode) || + FDV_MODE_ACTIVE( FREEDV_MODE_DATAC4, f->mode) || + FDV_MODE_ACTIVE( FREEDV_MODE_DATAC13, f->mode)) rx_status = freedv_comp_short_rx_ofdm(f, (void*)demod_in, 0, 1.0f); if (FDV_MODE_ACTIVE( FREEDV_MODE_FSK_LDPC, f->mode)) { rx_status = freedv_rx_fsk_ldpc_data(f, demod_in); } diff --git a/src/freedv_api.h b/src/freedv_api.h index 573ba7a3c..74ce49002 100644 --- a/src/freedv_api.h +++ b/src/freedv_api.h @@ -59,6 +59,8 @@ #define FREEDV_MODE_DATAC1 10 #define FREEDV_MODE_DATAC3 12 #define FREEDV_MODE_DATAC0 14 +#define FREEDV_MODE_DATAC4 18 +#define FREEDV_MODE_DATAC13 19 // Sample rates used #define FREEDV_FS_8000 8000 @@ -133,6 +135,12 @@ #if !defined(FREEDV_MODE_DATAC3_EN) #define FREEDV_MODE_DATAC3_EN FREEDV_MODE_EN_DEFAULT #endif +#if !defined(FREEDV_MODE_DATAC4_EN) + #define FREEDV_MODE_DATAC4_EN FREEDV_MODE_EN_DEFAULT +#endif +#if !defined(FREEDV_MODE_DATAC13_EN) + #define FREEDV_MODE_DATAC13_EN FREEDV_MODE_EN_DEFAULT +#endif #define FDV_MODE_ACTIVE(mode_name, var) ((mode_name##_EN) == 0 ? 0: (var) == mode_name) diff --git a/src/freedv_data_raw_rx.c b/src/freedv_data_raw_rx.c index 96d66633e..64ce1f128 100644 --- a/src/freedv_data_raw_rx.c +++ b/src/freedv_data_raw_rx.c @@ -161,7 +161,7 @@ int main(int argc, char *argv[]) { if (argc < 3) { helpmsg: - fprintf(stderr, "\nusage: %s [options] FSK_LDPC|DATAC0|DATAC1|DATAC3 InputModemSpeechFile BinaryDataFile\n" + fprintf(stderr, "\nusage: %s [options] FSK_LDPC|DATAC0|... InputModemSpeechFile BinaryDataFile\n" " -v or --vv verbose options\n" " --testframes count raw and coded errors in testframes sent by tx\n" " --framesperburst N N frames per burst (default 1, must match Tx)\n" @@ -195,6 +195,8 @@ int main(int argc, char *argv[]) { if (!strcmp(argv[dx],"DATAC0") || !strcmp(argv[dx],"datac0")) mode = FREEDV_MODE_DATAC0; if (!strcmp(argv[dx],"DATAC1") || !strcmp(argv[dx],"datac1")) mode = FREEDV_MODE_DATAC1; if (!strcmp(argv[dx],"DATAC3") || !strcmp(argv[dx],"datac3")) mode = FREEDV_MODE_DATAC3; + if (!strcmp(argv[dx],"DATAC4") || !strcmp(argv[dx],"datac4")) mode = FREEDV_MODE_DATAC4; + if (!strcmp(argv[dx],"DATAC13") || !strcmp(argv[dx],"datac13")) mode = FREEDV_MODE_DATAC13; if (mode == -1) { fprintf(stderr, "Error in mode: %s\n", argv[dx]); exit(1); diff --git a/src/freedv_data_raw_tx.c b/src/freedv_data_raw_tx.c index b5eb11aae..b2e47f879 100644 --- a/src/freedv_data_raw_tx.c +++ b/src/freedv_data_raw_tx.c @@ -168,7 +168,7 @@ int main(int argc, char *argv[]) { if (argc < 4) { helpmsg: - fprintf(stderr, "\nusage: %s [options] FSK_LDPC|DATAC0|DATAC1|DATAC3 InputBinaryDataFile OutputModemRawFile\n" + fprintf(stderr, "\nusage: %s [options] FSK_LDPC|DATAC0|... InputBinaryDataFile OutputModemRawFile\n" "\n" " --testframes T send a total of T test frames (T should equal B*N)\n" " --bursts B send B bursts of N testframes (default 1)\n" @@ -208,6 +208,8 @@ int main(int argc, char *argv[]) { if (!strcmp(argv[dx],"DATAC0") || !strcmp(argv[dx],"datac0")) mode = FREEDV_MODE_DATAC0; if (!strcmp(argv[dx],"DATAC1") || !strcmp(argv[dx],"datac1")) mode = FREEDV_MODE_DATAC1; if (!strcmp(argv[dx],"DATAC3") || !strcmp(argv[dx],"datac3")) mode = FREEDV_MODE_DATAC3; + if (!strcmp(argv[dx],"DATAC4") || !strcmp(argv[dx],"datac4")) mode = FREEDV_MODE_DATAC4; + if (!strcmp(argv[dx],"DATAC13") || !strcmp(argv[dx],"datac13")) mode = FREEDV_MODE_DATAC13; if (mode == -1) { fprintf(stderr, "Error: in mode: %s", argv[dx]); exit(1); diff --git a/src/modem_stats.h b/src/modem_stats.h index 604caee36..fbc80f744 100644 --- a/src/modem_stats.h +++ b/src/modem_stats.h @@ -35,7 +35,7 @@ #endif #define MODEM_STATS_NC_MAX 50 -#define MODEM_STATS_NR_MAX 160 +#define MODEM_STATS_NR_MAX 320 #define MODEM_STATS_ET_MAX 8 #define MODEM_STATS_EYE_IND_MAX 160 #define MODEM_STATS_NSPEC 512 From 89178a48f2011a2e963fcfb3b9816463d2b7c22d Mon Sep 17 00:00:00 2001 From: drowe67 Date: Fri, 21 Apr 2023 17:44:46 +0930 Subject: [PATCH 33/52] first pass at rx input BPF, but introducing some raw bit errors in datac4 --- octave/save_array_c_header.m | 2 +- src/filter.h | 2 +- src/filter_coef.h | 113 +++++++++++++++++++++++++++++++++++ src/ofdm.c | 73 ++++++++++++++++++---- src/ofdm_internal.h | 5 +- src/ofdm_mode.c | 2 + 6 files changed, 184 insertions(+), 13 deletions(-) diff --git a/octave/save_array_c_header.m b/octave/save_array_c_header.m index d51efeef8..1fd87bb10 100644 --- a/octave/save_array_c_header.m +++ b/octave/save_array_c_header.m @@ -5,7 +5,7 @@ function save_array_c_header(array, array_name, filename) f=fopen(filename,"wt"); fprintf(f,"/* Generated by save_array_c_header.m Octave function */\n\n"); - fprintf(f,"const int %s[]={\n", array_name); + fprintf(f,"const float %s[]={\n", array_name); for m=1:length(array)-1 fprintf(f," % .16f,\n",array(m)); endfor diff --git a/src/filter.h b/src/filter.h index 0a23162f2..ba484241e 100644 --- a/src/filter.h +++ b/src/filter.h @@ -42,7 +42,7 @@ extern float filtP550S750[160]; extern float filtP650S900[100]; extern float filtP900S1100[100]; extern float filtP1100S1300[100]; - +extern float filtP200S400[100]; extern float quiskFilt120t480[480]; #endif diff --git a/src/filter_coef.h b/src/filter_coef.h index b20b398e0..bbe3ead66 100644 --- a/src/filter_coef.h +++ b/src/filter_coef.h @@ -513,6 +513,119 @@ float filtP1100S1300[]={ 0.0002976192596492 }; +/* + Low pass filter, sample rate 8000 Hz, 60dB dB atten, pass 200 Hz, stop 400 Hz + Designed as an input BPF for datac4 and datac13 + + Generated using Octave: + octave:77> h = fir1(99, 300/4000); f=0:500; w=f*pi/4000; H=freqz(h,1,w); + octave:78> clf; plot(f,20*log10(abs(H))); grid; axis([0 500 -60 10]) + octave:79> save_array_c_header(h,"filtP200S400","t.h") +*/ + +float filtP200S400[]={ + -0.0004451300456841, + -0.0005073524058314, + -0.0005574343189633, + -0.0005917795871614, + -0.0006039913363378, + -0.0005851770087062, + -0.0005247593261891, + -0.0004117540200065, + -0.0002364188234407, + 0.0000078726198309, + 0.0003227185190862, + 0.0007029501441555, + 0.0011352850533254, + 0.0015975774725777, + 0.0020588370843795, + 0.0024801347836117, + 0.0028164457539694, + 0.0030194013565307, + 0.0030408378344080, + 0.0028369484909049, + 0.0023727737700520, + 0.0016267071788504, + 0.0005946599478435, + -0.0007064819796693, + -0.0022364561481532, + -0.0039305770555241, + -0.0057002708395526, + -0.0074353203964610, + -0.0090078367817707, + -0.0102778503408319, + -0.0111002921979132, + -0.0113330225538234, + -0.0108454655166747, + -0.0095273388161060, + -0.0072969270838895, + -0.0041083437106991, + 0.0000427395567291, + 0.0051153449639783, + 0.0110217680991424, + 0.0176286972088453, + 0.0247609340369461, + 0.0322076167621238, + 0.0397306857265216, + 0.0470751847135474, + 0.0539808648128491, + 0.0601944633375128, + 0.0654819737785736, + 0.0696402088327538, + 0.0725069887046084, + 0.0739693597497318, + 0.0739693597497318, + 0.0725069887046084, + 0.0696402088327538, + 0.0654819737785736, + 0.0601944633375128, + 0.0539808648128491, + 0.0470751847135474, + 0.0397306857265216, + 0.0322076167621238, + 0.0247609340369461, + 0.0176286972088453, + 0.0110217680991424, + 0.0051153449639783, + 0.0000427395567291, + -0.0041083437106991, + -0.0072969270838895, + -0.0095273388161060, + -0.0108454655166747, + -0.0113330225538234, + -0.0111002921979132, + -0.0102778503408319, + -0.0090078367817707, + -0.0074353203964610, + -0.0057002708395526, + -0.0039305770555241, + -0.0022364561481532, + -0.0007064819796693, + 0.0005946599478435, + 0.0016267071788504, + 0.0023727737700520, + 0.0028369484909049, + 0.0030408378344080, + 0.0030194013565307, + 0.0028164457539694, + 0.0024801347836117, + 0.0020588370843795, + 0.0015975774725777, + 0.0011352850533254, + 0.0007029501441555, + 0.0003227185190862, + 0.0000078726198309, + -0.0002364188234407, + -0.0004117540200065, + -0.0005247593261891, + -0.0005851770087062, + -0.0006039913363378, + -0.0005917795871614, + -0.0005574343189633, + -0.0005073524058314, + -0.0004451300456841 +}; + // FIR filter suitable for changing rates 7500 to/from 8000 // Sample 120000 Hz, pass 2700, stop 3730, ripple 0.1dB, atten 100 dB. Stop 0.03108. float quiskFilt120t480[480] = { diff --git a/src/ofdm.c b/src/ofdm.c index 1212da770..078108b93 100644 --- a/src/ofdm.c +++ b/src/ofdm.c @@ -52,6 +52,8 @@ static float cnormf(complex float); static void allocate_tx_bpf(struct OFDM *); static void deallocate_tx_bpf(struct OFDM *); +static void allocate_rx_bpf(struct OFDM *); +static void deallocate_rx_bpf(struct OFDM *); static void dft(struct OFDM *, complex float *, complex float *); static void idft(struct OFDM *, complex float *, complex float *); static complex float vector_sum(complex float *, int); @@ -213,6 +215,7 @@ struct OFDM *ofdm_create(const struct OFDM_CONFIG *config) { ofdm->codename = "HRA_112_112"; ofdm->amp_est_mode = 0; ofdm->tx_bpf_en = true; + ofdm->rx_bpf_en = false; ofdm->amp_scale = 245E3; ofdm->clip_gain1 = 2.0; ofdm->clip_gain2 = 0.9; @@ -247,6 +250,7 @@ struct OFDM *ofdm_create(const struct OFDM_CONFIG *config) { ofdm->codename = config->codename; ofdm->amp_est_mode = config->amp_est_mode; ofdm->tx_bpf_en = config->tx_bpf_en; + ofdm->rx_bpf_en = config->rx_bpf_en; ofdm->foff_limiter = config->foff_limiter; ofdm->amp_scale = config->amp_scale; ofdm->clip_gain1 = config->clip_gain1; @@ -294,6 +298,7 @@ struct OFDM *ofdm_create(const struct OFDM_CONFIG *config) { ofdm->config.codename = ofdm->codename; ofdm->config.amp_est_mode = ofdm->amp_est_mode; ofdm->config.tx_bpf_en = ofdm->tx_bpf_en; + ofdm->config.rx_bpf_en = ofdm->rx_bpf_en; ofdm->config.foff_limiter = ofdm->foff_limiter; ofdm->config.amp_scale = ofdm->amp_scale; ofdm->config.clip_gain1 = ofdm->clip_gain1; @@ -367,6 +372,9 @@ struct OFDM *ofdm_create(const struct OFDM_CONFIG *config) { ofdm->tx_bpf = NULL; if (ofdm->tx_bpf_en) allocate_tx_bpf(ofdm); + ofdm->rx_bpf = NULL; + if (ofdm->rx_bpf_en) + allocate_rx_bpf(ofdm); /* store complex BPSK pilot symbols */ @@ -576,6 +584,26 @@ static void deallocate_tx_bpf(struct OFDM *ofdm) { ofdm->tx_bpf = NULL; } +static void allocate_rx_bpf(struct OFDM *ofdm) { + ofdm->rx_bpf = MALLOC(sizeof(struct quisk_cfFilter)); + assert(ofdm->rx_bpf != NULL); + + /* Receive bandpass filter; complex coefficients, center frequency */ + + if (!strcmp(ofdm->mode, "datac4") || !strcmp(ofdm->mode, "datac13")) { + quisk_filt_cfInit(ofdm->rx_bpf, filtP200S400, sizeof (filtP200S400) / sizeof (float)); + quisk_cfTune(ofdm->rx_bpf, ofdm->rx_centre / ofdm->fs); + } + else assert(0); +} + +static void deallocate_rx_bpf(struct OFDM *ofdm) { + assert(ofdm->rx_bpf != NULL); + quisk_filt_destroy(ofdm->rx_bpf); + FREE(ofdm->rx_bpf); + ofdm->rx_bpf = NULL; +} + void ofdm_destroy(struct OFDM *ofdm) { int i; @@ -586,6 +614,9 @@ void ofdm_destroy(struct OFDM *ofdm) { if (ofdm->tx_bpf) { deallocate_tx_bpf(ofdm); } + if (ofdm->rx_bpf) { + deallocate_rx_bpf(ofdm); + } FREE(ofdm->pilot_samples); FREE(ofdm->rxbuf); @@ -1025,7 +1056,7 @@ void ofdm_hilbert_clipper(struct OFDM *ofdm, complex float *tx, size_t n) { for(int i=0; iamp_scale; if (ofdm->clip_en) { - // this gain set the drive into the Hilbert Clipper and sets PAPR + // this gain sets the drive into the Hilbert Clipper and sets PAPR for(int i=0; iclip_gain1; ofdm_clip(tx, OFDM_PEAK, n); } @@ -1404,18 +1435,25 @@ static int ofdm_sync_search_core(struct OFDM *ofdm) { */ /* - * This is a wrapper to maintain the older functionality with an - * array of COMPs as input + * This wrapper accepts an array of COMPs as input */ void ofdm_demod(struct OFDM *ofdm, int *rx_bits, COMP *rxbuf_in) { complex float *rx = (complex float *) &rxbuf_in[0]; // complex has same memory layout + complex float rx_filt[ofdm->nin]; int i, j; - /* shift the buffer left based on nin */ + /* shift the buffer left based on nin */ for (i = 0, j = ofdm->nin; i < (ofdm->nrxbuf - ofdm->nin); i++, j++) { ofdm->rxbuf[i] = ofdm->rxbuf[j]; } + /* Optional input BPF used by some modes (e.g. to improve acquisition) */ + if (ofdm->rx_bpf_en) { + assert(ofdm->rx_bpf != NULL); + quisk_ccfFilter(rx, rx_filt, ofdm->nin, ofdm->rx_bpf); + rx = rx_filt; + } + /* insert latest input samples onto tail of rxbuf */ for (j = 0, i = (ofdm->nrxbuf - ofdm->nin); i < ofdm->nrxbuf; j++, i++) { ofdm->rxbuf[i] = rx[j]; @@ -1425,7 +1463,7 @@ void ofdm_demod(struct OFDM *ofdm, int *rx_bits, COMP *rxbuf_in) { } /* - * This is a wrapper with a new interface to reduce memory allocated. + * This is a wrapper with a real short interface to minimise allocated memory. * This works with ofdm_demod and freedv_api. Gain is not used here. */ void ofdm_demod_shorts(struct OFDM *ofdm, int *rx_bits, short *rxbuf_in, float gain) { @@ -1437,12 +1475,26 @@ void ofdm_demod_shorts(struct OFDM *ofdm, int *rx_bits, short *rxbuf_in, float g ofdm->rxbuf[i] = ofdm->rxbuf[j]; } - /* insert latest input samples onto tail of rxbuf */ - - for (j = 0, i = (ofdm->nrxbuf - ofdm->nin); i < ofdm->nrxbuf; j++, i++) { - ofdm->rxbuf[i] = ((float)rxbuf_in[j] / 32767.0f); + /* Optional input BPF used by some modes (e.g. to improve acquisition) */ + if (ofdm->rx_bpf_en) { + assert(ofdm->rx_bpf != NULL); + complex float rx[ofdm->nin]; + complex float rx_filt[ofdm->nin]; + for(i=0; inin; i++) + rx[i] = rxbuf_in[i]; + quisk_ccfFilter(rx, rx_filt, ofdm->nin, ofdm->rx_bpf); + /* insert latest input samples onto tail of rxbuf */ + for (j = 0, i = (ofdm->nrxbuf - ofdm->nin); i < ofdm->nrxbuf; j++, i++) { + ofdm->rxbuf[i] = creal(rx_filt[j]) / 32767.0f; + } } - + else { + /* insert latest input samples onto tail of rxbuf */ + for (j = 0, i = (ofdm->nrxbuf - ofdm->nin); i < ofdm->nrxbuf; j++, i++) { + ofdm->rxbuf[i] = ((float)rxbuf_in[j] / 32767.0f); + } + } + ofdm_demod_core(ofdm, rx_bits); } @@ -2549,6 +2601,7 @@ void ofdm_print_info(struct OFDM *ofdm) { fprintf(stderr, "ofdm->foff_est_en = %s\n", ofdm->foff_est_en ? "true" : "false"); fprintf(stderr, "ofdm->phase_est_en = %s\n", ofdm->phase_est_en ? "true" : "false"); fprintf(stderr, "ofdm->tx_bpf_en = %s\n", ofdm->tx_bpf_en ? "true" : "false"); + fprintf(stderr, "ofdm->rx_bpf_en = %s\n", ofdm->rx_bpf_en ? "true" : "false"); fprintf(stderr, "ofdm->dpsk_en = %s\n", ofdm->dpsk_en ? "true" : "false"); fprintf(stderr, "ofdm->phase_est_bandwidth_mode = %s\n", phase_est_bandwidth_mode[ofdm->phase_est_bandwidth_mode]); } diff --git a/src/ofdm_internal.h b/src/ofdm_internal.h index dc3839d2d..caa7876ac 100644 --- a/src/ofdm_internal.h +++ b/src/ofdm_internal.h @@ -98,7 +98,8 @@ struct OFDM_CONFIG { char *codename; /* name of LDPC code used with this mode */ uint8_t tx_uw[MAX_UW_BITS]; /* user defined unique word */ int amp_est_mode; - bool tx_bpf_en; /* default clippedtx BPF state */ + bool tx_bpf_en; /* default tx (mod) hilbert clipper BPF enable */ + bool rx_bpf_en; /* default rx (demod) input BPF enable */ bool foff_limiter; /* tames freq offset updates in low SNR */ float amp_scale; /* used to scale Tx waveform to approx FREEDV_PEAK with clipper off */ float clip_gain1; /* gain we apply to Tx signal before clipping to control PAPR*/ @@ -174,6 +175,7 @@ struct OFDM { // Pointers struct quisk_cfFilter *tx_bpf; + struct quisk_cfFilter *rx_bpf; complex float *pilot_samples; complex float *rxbuf; @@ -236,6 +238,7 @@ struct OFDM { bool foff_est_en; bool phase_est_en; bool tx_bpf_en; + bool rx_bpf_en; bool dpsk_en; bool postambledetectoren; /* allows us to optionally disable the postamble detector */ diff --git a/src/ofdm_mode.c b/src/ofdm_mode.c index fa75234a1..3a5ae9caa 100644 --- a/src/ofdm_mode.c +++ b/src/ofdm_mode.c @@ -44,6 +44,7 @@ void ofdm_init_mode(char mode[], struct OFDM_CONFIG *config) { config->clip_gain2 = 0.8; config->clip_en = true; config->tx_bpf_en = true; + config->rx_bpf_en = false; config->amp_scale = 245E3; config->foff_limiter = false; memset(config->tx_uw, 0, MAX_UW_BITS); @@ -131,6 +132,7 @@ void ofdm_init_mode(char mode[], struct OFDM_CONFIG *config) { config->data_mode = "streaming"; config->amp_scale = 2*300E3; config->clip_gain1 = 1.5; config->clip_gain2 = 0.8; config->tx_bpf_en = false; config->clip_en = false; + config->rx_bpf_en = true; } else if (strcmp(mode,"datac13") == 0) { config->ns=5; config->np=18; config->tcp = 0.006; config->ts = 0.016; config->nc = 3; config->edge_pilots = 0; From c416cd442a4b713c3449023319804188fe2b11db Mon Sep 17 00:00:00 2001 From: drowe67 Date: Sat, 22 Apr 2023 07:29:20 +0930 Subject: [PATCH 34/52] datac13 had input BPF, also introducing bit errors --- src/ofdm_mode.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/ofdm_mode.c b/src/ofdm_mode.c index 3a5ae9caa..25e2f350b 100644 --- a/src/ofdm_mode.c +++ b/src/ofdm_mode.c @@ -133,7 +133,7 @@ void ofdm_init_mode(char mode[], struct OFDM_CONFIG *config) { config->amp_scale = 2*300E3; config->clip_gain1 = 1.5; config->clip_gain2 = 0.8; config->tx_bpf_en = false; config->clip_en = false; config->rx_bpf_en = true; -} else if (strcmp(mode,"datac13") == 0) { + } else if (strcmp(mode,"datac13") == 0) { config->ns=5; config->np=18; config->tcp = 0.006; config->ts = 0.016; config->nc = 3; config->edge_pilots = 0; config->txtbits = 0; config->state_machine = "data"; @@ -147,6 +147,7 @@ void ofdm_init_mode(char mode[], struct OFDM_CONFIG *config) { config->data_mode = "streaming"; config->amp_scale = 2.5*300E3; config->clip_gain1 = 1.5; config->clip_gain2 = 0.8; config->tx_bpf_en = false; config->clip_en = false; + config->rx_bpf_en = true; } else { assert(0); From e289fe1f7c79cc88b42be895fca8340debddbe95 Mon Sep 17 00:00:00 2001 From: drowe67 Date: Tue, 25 Apr 2023 11:34:04 +0930 Subject: [PATCH 35/52] wip Octave version of Jim's complex band pass filter --- octave/ofdm_ldpc_rx.m | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/octave/ofdm_ldpc_rx.m b/octave/ofdm_ldpc_rx.m index 8b42ebce9..f1db6429e 100644 --- a/octave/ofdm_ldpc_rx.m +++ b/octave/ofdm_ldpc_rx.m @@ -55,7 +55,13 @@ function ofdm_ldpc_rx(filename, mode="700D", varargin) Nsam = length(rx); prx = 1; if strcmp(mode,"datac4") || strcmp(mode,"datac13") - rx = filter(fir1(100,[1250 1700]/4000),1,rx); + % BPF, we actually shift the signal back down to baseband to filter, as per + % C version + ssbfilt_n = 100; + rxbpf_width_Hz = 600; + ssbfilt_coeff = fir1(ssbfilt_n, rxbpf_width_Hz/states.Fs); + lo = exp(j*2*pi*states.fcentre*(1:length(rx))/(states.Fs))'; + rx = conj(lo).*filter(ssbfilt_coeff,1,rx.*lo); end % Generate tx frame for BER calcs From d9eb3d7b0c0d287d1951034301f54c2544398fe2 Mon Sep 17 00:00:00 2001 From: drowe67 Date: Tue, 25 Apr 2023 11:58:47 +0930 Subject: [PATCH 36/52] Octave version on Jim's complex filter doing a reasonable job --- octave/ofdm_ldpc_rx.m | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/octave/ofdm_ldpc_rx.m b/octave/ofdm_ldpc_rx.m index f1db6429e..efb7fcb98 100644 --- a/octave/ofdm_ldpc_rx.m +++ b/octave/ofdm_ldpc_rx.m @@ -55,13 +55,15 @@ function ofdm_ldpc_rx(filename, mode="700D", varargin) Nsam = length(rx); prx = 1; if strcmp(mode,"datac4") || strcmp(mode,"datac13") - % BPF, we actually shift the signal back down to baseband to filter, as per - % C version - ssbfilt_n = 100; + % Complex bandpass filter as per src/filter.c + n_coeffs = 100; rxbpf_width_Hz = 600; - ssbfilt_coeff = fir1(ssbfilt_n, rxbpf_width_Hz/states.Fs); - lo = exp(j*2*pi*states.fcentre*(1:length(rx))/(states.Fs))'; - rx = conj(lo).*filter(ssbfilt_coeff,1,rx.*lo); + % note this designs a lowpass filter with cutoff rxbpf_width_Hz/2, as third + % argument is normalised to Fs/2 + lowpass_coeff = fir1(n_coeffs-1, rxbpf_width_Hz/states.Fs); + w = 2*pi*states.fcentre/states.Fs; k = (0:n_coeffs-1); + bandpass_coeff = lowpass_coeff .* exp(j*w*k); + rx = filter(bandpass_coeff,1,rx); end % Generate tx frame for BER calcs From 85da8e65ab26169c1ed2fc7616d3ee21615c4247 Mon Sep 17 00:00:00 2001 From: drowe67 Date: Tue, 25 Apr 2023 12:00:34 +0930 Subject: [PATCH 37/52] ofdm_demod --log & ofdm_demod_c.m working again --- octave/ofdm_demod_c.m | 5 ----- src/ofdm_demod.c | 4 ++-- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/octave/ofdm_demod_c.m b/octave/ofdm_demod_c.m index 4a397495d..531a649e1 100644 --- a/octave/ofdm_demod_c.m +++ b/octave/ofdm_demod_c.m @@ -40,9 +40,4 @@ function ofdm_demod_c(filename, mode="700D") axis([1 max(length(foff_hz_log_c),2) -mx mx]); title('Fine Freq'); ylabel('Hz') - - figure(5); clf; - plot(snr_est_log_c); - ylabel('SNR (dB)') - title('SNR Estimates') endfunction diff --git a/src/ofdm_demod.c b/src/ofdm_demod.c index ec6ca41b2..babe91ee0 100644 --- a/src/ofdm_demod.c +++ b/src/ofdm_demod.c @@ -386,8 +386,8 @@ int main(int argc, char *argv[]) { fprintf(stderr, "Warning EsNo: %f hard coded\n", EsNo); /* More logging */ - COMP payload_syms_log[NFRAMES][Npayloadsymsperframe]; - float payload_amps_log[NFRAMES][Npayloadsymsperframe]; + COMP payload_syms_log[NFRAMES][Npayloadsymsperpacket]; + float payload_amps_log[NFRAMES][Npayloadsymsperpacket]; for (i = 0; i < NFRAMES; i++) { for (j = 0; j < Npayloadsymsperframe; j++) { From 9201ff1c74ab01232bd94722e30c0f2e1a91bf18 Mon Sep 17 00:00:00 2001 From: drowe67 Date: Tue, 25 Apr 2023 12:01:34 +0930 Subject: [PATCH 38/52] use complex output of quisk_ccfFilter --- src/filter_coef.h | 8 +++++--- src/ofdm.c | 4 ++-- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/src/filter_coef.h b/src/filter_coef.h index bbe3ead66..04930c66f 100644 --- a/src/filter_coef.h +++ b/src/filter_coef.h @@ -514,11 +514,13 @@ float filtP1100S1300[]={ }; /* - Low pass filter, sample rate 8000 Hz, 60dB dB atten, pass 200 Hz, stop 400 Hz - Designed as an input BPF for datac4 and datac13 + Low pass prototype, sample rate 8000 Hz, 60dB dB atten, pass 200 Hz, stop 450 Hz, + note when used as BPF in modem this gives a flat passband 400 Hz wide. + + Used as an input BPF for datac4 and datac13 Generated using Octave: - octave:77> h = fir1(99, 300/4000); f=0:500; w=f*pi/4000; H=freqz(h,1,w); + octave:77> h = fir1(99, 600/8000); f=0:500; w=f*pi/4000; H=freqz(h,1,w); octave:78> clf; plot(f,20*log10(abs(H))); grid; axis([0 500 -60 10]) octave:79> save_array_c_header(h,"filtP200S400","t.h") */ diff --git a/src/ofdm.c b/src/ofdm.c index 078108b93..4c9c329d2 100644 --- a/src/ofdm.c +++ b/src/ofdm.c @@ -1481,11 +1481,11 @@ void ofdm_demod_shorts(struct OFDM *ofdm, int *rx_bits, short *rxbuf_in, float g complex float rx[ofdm->nin]; complex float rx_filt[ofdm->nin]; for(i=0; inin; i++) - rx[i] = rxbuf_in[i]; + rx[i] = rxbuf_in[i] / 32767.0f; quisk_ccfFilter(rx, rx_filt, ofdm->nin, ofdm->rx_bpf); /* insert latest input samples onto tail of rxbuf */ for (j = 0, i = (ofdm->nrxbuf - ofdm->nin); i < ofdm->nrxbuf; j++, i++) { - ofdm->rxbuf[i] = creal(rx_filt[j]) / 32767.0f; + ofdm->rxbuf[i] = rx_filt[j]; } } else { From 58db31094d132fbdfb1276d88e3f947954570746 Mon Sep 17 00:00:00 2001 From: drowe67 Date: Tue, 25 Apr 2023 12:55:39 +0930 Subject: [PATCH 39/52] unit test program for src/filter.c complex BPF --- unittest/CMakeLists.txt | 4 +++- unittest/tquisk_filter.c | 49 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+), 1 deletion(-) create mode 100644 unittest/tquisk_filter.c diff --git a/unittest/CMakeLists.txt b/unittest/CMakeLists.txt index 986ee3f62..080ebc5b2 100644 --- a/unittest/CMakeLists.txt +++ b/unittest/CMakeLists.txt @@ -90,13 +90,15 @@ target_link_libraries(t16_8 codec2) add_executable(t16_8_short t16_8_short.c ../src/fdmdv.c ../src/kiss_fft.c) target_link_libraries(t16_8_short codec2) - add_executable(t48_8 t48_8.c ../src/fdmdv.c ../src/kiss_fft.c) target_link_libraries(t48_8 codec2) add_executable(t48_8_short t48_8_short.c ../src/fdmdv.c ../src/kiss_fft.c) target_link_libraries(t48_8_short codec2) +add_executable(tquisk_filter tquisk_filter.c) +target_link_libraries(tquisk_filter codec2) + # Build CML as part of unit test setup find_program(OCTAVE_CMD octave-cli REQUIRED) message("Octave command: ${OCTAVE_CMD}") diff --git a/unittest/tquisk_filter.c b/unittest/tquisk_filter.c new file mode 100644 index 000000000..ed322b5c9 --- /dev/null +++ b/unittest/tquisk_filter.c @@ -0,0 +1,49 @@ +/* + tquisk_filter.c + + Unit test for complex band pass filters in src/filter.c + + cd codec2/build_linux + ./misc/mksine - 1500 2 | unittest/tquisk_filter | aplay + + By adjusting the frequency you can audibly test filter response. +*/ + +#include +#include +#include +#include +#include "filter.h" +#include "filter_coef.h" + +#define N 159 /* processing buffer size (odd number deliberate) */ +#define CENTRE 1500.0 +#define FS 8000.0 + +int main() { + short buf_short[N]; + complex float buf[N]; + struct quisk_cfFilter *bpf; + int i; + int n = 0; + + bpf = malloc(sizeof(struct quisk_cfFilter)); + assert(bpf != NULL); + quisk_filt_cfInit(bpf, filtP200S400, sizeof (filtP200S400) / sizeof (float)); + quisk_cfTune(bpf, CENTRE/FS); + + while(fread(buf_short, sizeof(short), N, stdin) == N) { + for(i=0; i Date: Tue, 25 Apr 2023 13:28:14 +0930 Subject: [PATCH 40/52] fixed issue with rx bpf introducing errors, we had to apply filter in acquisition code as well. Filter now moved to core functions --- src/ofdm.c | 40 ++++++++++++++-------------------------- unittest/tquisk_filter.c | 1 - 2 files changed, 14 insertions(+), 27 deletions(-) diff --git a/src/ofdm.c b/src/ofdm.c index 4c9c329d2..13e962d74 100644 --- a/src/ofdm.c +++ b/src/ofdm.c @@ -1422,6 +1422,11 @@ static int ofdm_sync_search_stream(struct OFDM *ofdm) { } static int ofdm_sync_search_core(struct OFDM *ofdm) { + if (ofdm->rx_bpf_en) { + assert(ofdm->rx_bpf != NULL); + complex float *rxbuf_in = &ofdm->rxbuf[(ofdm->nrxbuf - ofdm->nin)]; + quisk_ccfFilter(rxbuf_in, rxbuf_in, ofdm->nin, ofdm->rx_bpf); + } if (!strcmp(ofdm->data_mode, "burst")) return ofdm_sync_search_burst(ofdm); else @@ -1439,7 +1444,6 @@ static int ofdm_sync_search_core(struct OFDM *ofdm) { */ void ofdm_demod(struct OFDM *ofdm, int *rx_bits, COMP *rxbuf_in) { complex float *rx = (complex float *) &rxbuf_in[0]; // complex has same memory layout - complex float rx_filt[ofdm->nin]; int i, j; /* shift the buffer left based on nin */ @@ -1447,13 +1451,6 @@ void ofdm_demod(struct OFDM *ofdm, int *rx_bits, COMP *rxbuf_in) { ofdm->rxbuf[i] = ofdm->rxbuf[j]; } - /* Optional input BPF used by some modes (e.g. to improve acquisition) */ - if (ofdm->rx_bpf_en) { - assert(ofdm->rx_bpf != NULL); - quisk_ccfFilter(rx, rx_filt, ofdm->nin, ofdm->rx_bpf); - rx = rx_filt; - } - /* insert latest input samples onto tail of rxbuf */ for (j = 0, i = (ofdm->nrxbuf - ofdm->nin); i < ofdm->nrxbuf; j++, i++) { ofdm->rxbuf[i] = rx[j]; @@ -1475,24 +1472,9 @@ void ofdm_demod_shorts(struct OFDM *ofdm, int *rx_bits, short *rxbuf_in, float g ofdm->rxbuf[i] = ofdm->rxbuf[j]; } - /* Optional input BPF used by some modes (e.g. to improve acquisition) */ - if (ofdm->rx_bpf_en) { - assert(ofdm->rx_bpf != NULL); - complex float rx[ofdm->nin]; - complex float rx_filt[ofdm->nin]; - for(i=0; inin; i++) - rx[i] = rxbuf_in[i] / 32767.0f; - quisk_ccfFilter(rx, rx_filt, ofdm->nin, ofdm->rx_bpf); - /* insert latest input samples onto tail of rxbuf */ - for (j = 0, i = (ofdm->nrxbuf - ofdm->nin); i < ofdm->nrxbuf; j++, i++) { - ofdm->rxbuf[i] = rx_filt[j]; - } - } - else { - /* insert latest input samples onto tail of rxbuf */ - for (j = 0, i = (ofdm->nrxbuf - ofdm->nin); i < ofdm->nrxbuf; j++, i++) { - ofdm->rxbuf[i] = ((float)rxbuf_in[j] / 32767.0f); - } + /* insert latest input samples onto tail of rxbuf */ + for (j = 0, i = (ofdm->nrxbuf - ofdm->nin); i < ofdm->nrxbuf; j++, i++) { + ofdm->rxbuf[i] = ((float)rxbuf_in[j] / 32767.0f); } ofdm_demod_core(ofdm, rx_bits); @@ -1506,6 +1488,12 @@ static void ofdm_demod_core(struct OFDM *ofdm, int *rx_bits) { int prev_timing_est = ofdm->timing_est; int i, j, k, rr, st, en; + if (ofdm->rx_bpf_en) { + assert(ofdm->rx_bpf != NULL); + complex float *rxbuf_in = &ofdm->rxbuf[(ofdm->nrxbuf - ofdm->nin)]; + quisk_ccfFilter(rxbuf_in, rxbuf_in, ofdm->nin, ofdm->rx_bpf); + } + /* * get user and calculated freq offset */ diff --git a/unittest/tquisk_filter.c b/unittest/tquisk_filter.c index ed322b5c9..d6c752988 100644 --- a/unittest/tquisk_filter.c +++ b/unittest/tquisk_filter.c @@ -41,7 +41,6 @@ int main() { buf_short[i] = creal(buf[i]); n += fwrite(buf_short, sizeof(short), N, stdout); } - fprintf(stderr,"n = %d written\n", n); quisk_filt_destroy(bpf); free(bpf); From d6ba98a64244312c91f1f79e9e2a4e014e187e91 Mon Sep 17 00:00:00 2001 From: drowe67 Date: Tue, 25 Apr 2023 13:55:55 +0930 Subject: [PATCH 41/52] moved complex BPF into ofdm_lib.m, so it can be used by ofdm_ldpc_rx & ofdm_acquisition --- octave/ofdm_acquisition.m | 8 ++++---- octave/ofdm_ldpc_rx.m | 15 +++------------ octave/ofdm_lib.m | 17 +++++++++++++++++ 3 files changed, 24 insertions(+), 16 deletions(-) diff --git a/octave/ofdm_acquisition.m b/octave/ofdm_acquisition.m index b05bfb5a8..8e3dd6ff7 100644 --- a/octave/ofdm_acquisition.m +++ b/octave/ofdm_acquisition.m @@ -41,10 +41,10 @@ %printf("SNR3kdB: %f Burst offset: %f\n", sim_in.SNR3kdB, mark_space_SNR_offset) rx = channel_simulate(Fs, SNRdB_setpoint, sim_in.foff_Hz, sim_in.channel, tx); - % experimental BPF - if strcmp(sim_in.mode,"datac4") - rx = filter(fir1(100,[1400 1600]/4000),1,rx); - l = length(rx); rx = [rx(50:l) zeros(1,50)]; + % optional BPF + if strcmp(sim_in.mode,"datac4") || strcmp(mode,"datac13") + [rx delay_samples] = ofdm_complex_bandpass_filter(states, sim_in.mode, rx); + l = length(rx); rx = [rx(delay_samples:l) zeros(1,delay_samples)]; end endfunction diff --git a/octave/ofdm_ldpc_rx.m b/octave/ofdm_ldpc_rx.m index efb7fcb98..452730bdf 100644 --- a/octave/ofdm_ldpc_rx.m +++ b/octave/ofdm_ldpc_rx.m @@ -54,18 +54,7 @@ function ofdm_ldpc_rx(filename, mode="700D", varargin) frx=fopen(filename,"rb"); rx = fread(frx, Inf, "short")/Ascale; fclose(frx); Nsam = length(rx); prx = 1; - if strcmp(mode,"datac4") || strcmp(mode,"datac13") - % Complex bandpass filter as per src/filter.c - n_coeffs = 100; - rxbpf_width_Hz = 600; - % note this designs a lowpass filter with cutoff rxbpf_width_Hz/2, as third - % argument is normalised to Fs/2 - lowpass_coeff = fir1(n_coeffs-1, rxbpf_width_Hz/states.Fs); - w = 2*pi*states.fcentre/states.Fs; k = (0:n_coeffs-1); - bandpass_coeff = lowpass_coeff .* exp(j*w*k); - rx = filter(bandpass_coeff,1,rx); - end - + % Generate tx frame for BER calcs payload_bits = round(ofdm_rand(code_param.data_bits_per_frame)/32767); @@ -95,6 +84,8 @@ function ofdm_ldpc_rx(filename, mode="700D", varargin) % main loop ---------------------------------------------------------------- + rx = ofdm_complex_bandpass_filter(states, mode, rx); + f = 1; while(prx < Nsam) diff --git a/octave/ofdm_lib.m b/octave/ofdm_lib.m index 2b331d1fc..818333728 100644 --- a/octave/ofdm_lib.m +++ b/octave/ofdm_lib.m @@ -1242,6 +1242,23 @@ Can be used for acquisition (coarse timing), and fine timing. Tends endfunction +% Complex bandpass filter as per src/filter.c +function [rx delay_samples] = ofdm_complex_bandpass_filter(states, mode, rx) + delay_samples = 0; + if strcmp(mode,"datac4") || strcmp(mode,"datac13") + n_coeffs = 100; + rxbpf_width_Hz = 600; + % note this designs a lowpass filter with cutoff rxbpf_width_Hz/2, as third + % argument is normalised to Fs/2 + lowpass_coeff = fir1(n_coeffs-1, rxbpf_width_Hz/states.Fs); + w = 2*pi*states.fcentre/states.Fs; k = (0:n_coeffs-1); + bandpass_coeff = lowpass_coeff .* exp(j*w*k); + rx = filter(bandpass_coeff,1,rx); + delay_samples = n_coeffs/2; + end +endfunction + + % returns an unpacked CRC16 (array of 16 bits) calculated from an array of unpacked bits function unpacked_crc16 = crc16_unpacked(unpacked_bits) % pack into bytes From a993ca6a497e7f8a28379fe54cad4d917dfc24a6 Mon Sep 17 00:00:00 2001 From: drowe67 Date: Sat, 29 Apr 2023 10:30:56 +0930 Subject: [PATCH 42/52] ofdm_acquisition tweaks to use with datac4 & datac13 --- octave/ofdm_acquisition.m | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/octave/ofdm_acquisition.m b/octave/ofdm_acquisition.m index 8e3dd6ff7..fd56a99c9 100644 --- a/octave/ofdm_acquisition.m +++ b/octave/ofdm_acquisition.m @@ -42,7 +42,7 @@ rx = channel_simulate(Fs, SNRdB_setpoint, sim_in.foff_Hz, sim_in.channel, tx); % optional BPF - if strcmp(sim_in.mode,"datac4") || strcmp(mode,"datac13") + if strcmp(sim_in.mode,"datac4") || strcmp(sim_in.mode,"datac13") [rx delay_samples] = ofdm_complex_bandpass_filter(states, sim_in.mode, rx); l = length(rx); rx = [rx(delay_samples:l) zeros(1,delay_samples)]; end @@ -126,7 +126,7 @@ delta_foff_log = [delta_foff_log pre_eval.delta_foff]; ct_log = [ct_log w+pre_eval.ct_est]; if states.verbose - printf("Pre i: %2d n: %8d ct_est: %6d delta_ct: %6d foff_est: %5.1f timing_mx: %3.2f Acq: %d\n", + printf("Pre i: %2d n: %8d ct_est: %6d delta_ct: %6d foff_est: %5.1f timing_mx: %3.2f Acq: %2d\n", i, n, pre_eval.ct_est, pre_eval.delta_ct, pre.foff_est, pre.timing_mx, target_acq(i)); end end @@ -144,7 +144,7 @@ delta_foff_log = [delta_foff_log post_eval.delta_foff]; ct_log = [ct_log w+post_eval.ct_est]; if states.verbose - printf("Post i: %2d n: %8d ct_est: %6d delta_ct: %6d foff_est: %5.1f timing_mx: %3.2f Acq: %d\n", + printf("Post i: %2d n: %8d ct_est: %6d delta_ct: %6d foff_est: %5.1f timing_mx: %3.2f Acq: %2d\n", i, n, post_eval.ct_est, post_eval.delta_ct, post.foff_est, post.timing_mx, target_acq(i)); end end @@ -166,18 +166,24 @@ plot(timing_mx_log(1,:),'+-;preamble;'); hold on; plot(timing_mx_log(2,:),'o-;postamble;'); - plot(0.35+0.1*state_log,'-g;state;'); - title('mx log'); axis([0 length(timing_mx_log) 0 0.5]); grid; + plot(0.45+0.1*state_log,'-g;state;'); + title('mx log'); axis([0 length(timing_mx_log) 0 1.0]); grid; hold off; figure(4); clf; plot(real(rx)); axis([0 length(rx) -3E4 3E4]); hold on; plot(ct_log,zeros(1,length(ct_log)),'r+','markersize', 25, 'linewidth', 2); hold off; figure(5); clf; plot_specgram(rx, Fs, 500, 2500); + all_mx = [ timing_mx_log(1,:) timing_mx_log(2,:)]; + figure(6); clf; [nn xx] = hist(all_mx); semilogy(xx,nn+1); grid; + figure(7); clf; cdf = empirical_cdf(0:0.1:1,all_mx); plot(0:0.1:1, cdf); grid; + end - Pa = length(find(target_acq == 1))/Ntests; - printf("%s %s SNR: %3.1f foff: %3.1f P(acq) = %3.2f\n", mode, channel, SNR3kdB, foff_Hz, Pa); + Pacq = length(find(target_acq == 1))/Ntests; + Pfalse_acq = length(find(target_acq == -1))/Ntests; + printf("%s %s SNR: %3.1f foff: %3.1f P(acq) = %3.2f P(false_acq) = %3.2f\n", mode, channel, SNR3kdB, foff_Hz, + Pacq, Pfalse_acq); endfunction @@ -238,6 +244,6 @@ function acquistion_curves_frame_by_frame_modes_channels_snr(Ntests=5, quick_tes frame_by_frame_acquisition_test("datac0", Ntests=5, 'mpp', SNR3kdB=5, foff_hz=0, verbose=1+8); else % other development work here - frame_by_frame_acquisition_test("datac4", Ntests=20, 'mpp', SNR3kdB=-5, foff_hz=0, verbose=1+8); + frame_by_frame_acquisition_test("datac13", Ntests=100, 'mpp', SNR3kdB=-4, foff_hz=0, verbose=1+8); %acquistion_curves_frame_by_frame_modes_channels_snr(Ntests=50, quick_test=0) end From e7811cd6577493448aac96c3f8eb0ae242969eaa Mon Sep 17 00:00:00 2001 From: drowe67 Date: Sat, 29 Apr 2023 10:32:06 +0930 Subject: [PATCH 43/52] a few laps of ofdm_acquisition, 100 packet MPP -4dB ofdm_ldpc_rx tests, and filter bandwidth adjustments, PER about 0.1 at -4dB MPP for datac4 & c13 --- octave/ofdm_lib.m | 9 +++++---- octave/ofdm_mode.m | 4 ++-- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/octave/ofdm_lib.m b/octave/ofdm_lib.m index 818333728..ff429ae5b 100644 --- a/octave/ofdm_lib.m +++ b/octave/ofdm_lib.m @@ -512,7 +512,7 @@ Can be used for acquisition (coarse timing), and fine timing. Tends end % At each timing position, correlate with known samples at all possible freq offsets. Result - % is a column vector for each timing offset. Each matrix cell is s freq,timing coordinate + % is a column vector for each timing offset. Each matrix cell is a freq,timing coordinate corr = []; for t=1:tstep:Ncorr @@ -1246,13 +1246,14 @@ Can be used for acquisition (coarse timing), and fine timing. Tends function [rx delay_samples] = ofdm_complex_bandpass_filter(states, mode, rx) delay_samples = 0; if strcmp(mode,"datac4") || strcmp(mode,"datac13") + w_centre = mean(states.w); n_coeffs = 100; - rxbpf_width_Hz = 600; + rxbpf_width_Hz = 400; % note this designs a lowpass filter with cutoff rxbpf_width_Hz/2, as third % argument is normalised to Fs/2 lowpass_coeff = fir1(n_coeffs-1, rxbpf_width_Hz/states.Fs); - w = 2*pi*states.fcentre/states.Fs; k = (0:n_coeffs-1); - bandpass_coeff = lowpass_coeff .* exp(j*w*k); + k = (0:n_coeffs-1); + bandpass_coeff = lowpass_coeff .* exp(j*w_centre*k); rx = filter(bandpass_coeff,1,rx); delay_samples = n_coeffs/2; end diff --git a/octave/ofdm_mode.m b/octave/ofdm_mode.m index 2b61b5701..446fe2830 100644 --- a/octave/ofdm_mode.m +++ b/octave/ofdm_mode.m @@ -114,7 +114,7 @@ Ns=5; config.Np=47; Tcp = 0.006; Ts = 0.016; Nc = 4; config.data_mode = "streaming"; config.edge_pilots = 0; config.Ntxtbits = 0; config.Nuwbits = 32; config.bad_uw_errors = 12; - config.ftwindow_width = 80; config.timing_mx_thresh = 0.25; + config.ftwindow_width = 80; config.timing_mx_thresh = 0.5; config.tx_uw = zeros(1,config.Nuwbits); config.tx_uw(1:24) = [1 1 0 0 1 0 1 0 1 1 1 1 0 0 0 0 1 1 1 1 0 0 0 0]; config.tx_uw(end-24+1:end) = [1 1 0 0 1 0 1 0 1 1 1 1 0 0 0 0 1 1 1 1 0 0 0 0]; @@ -125,7 +125,7 @@ Ns=5; config.Np=18; Tcp = 0.006; Ts = 0.016; Nc = 3; config.data_mode = "streaming"; config.edge_pilots = 0; config.Ntxtbits = 0; config.Nuwbits = 48; config.bad_uw_errors = 18; - config.ftwindow_width = 80; config.timing_mx_thresh = 0.25; + config.ftwindow_width = 80; config.timing_mx_thresh = 0.45; config.tx_uw = zeros(1,config.Nuwbits); config.tx_uw(1:24) = [1 1 0 0 1 0 1 0 1 1 1 1 0 0 0 0 1 1 1 1 0 0 0 0]; config.tx_uw(end-24+1:end) = [1 1 0 0 1 0 1 0 1 1 1 1 0 0 0 0 1 1 1 1 0 0 0 0]; From 7264290c9a6520db395f7e653cf09fcaff5a0d75 Mon Sep 17 00:00:00 2001 From: drowe67 Date: Sat, 29 Apr 2023 11:07:19 +0930 Subject: [PATCH 44/52] C port of acquisition tuning --- octave/ofdm_lib.m | 1 + src/filter_coef.h | 205 +++++++++++++++++++++++----------------------- src/ofdm.c | 24 ++++-- src/ofdm_mode.c | 4 +- 4 files changed, 120 insertions(+), 114 deletions(-) diff --git a/octave/ofdm_lib.m b/octave/ofdm_lib.m index ff429ae5b..e9bd13f82 100644 --- a/octave/ofdm_lib.m +++ b/octave/ofdm_lib.m @@ -1247,6 +1247,7 @@ Can be used for acquisition (coarse timing), and fine timing. Tends delay_samples = 0; if strcmp(mode,"datac4") || strcmp(mode,"datac13") w_centre = mean(states.w); + %printf("f centre: %f\n", w_centre*states.Fs/(2*pi)); n_coeffs = 100; rxbpf_width_Hz = 400; % note this designs a lowpass filter with cutoff rxbpf_width_Hz/2, as third diff --git a/src/filter_coef.h b/src/filter_coef.h index 04930c66f..d5ad8b4cc 100644 --- a/src/filter_coef.h +++ b/src/filter_coef.h @@ -514,118 +514,117 @@ float filtP1100S1300[]={ }; /* - Low pass prototype, sample rate 8000 Hz, 60dB dB atten, pass 200 Hz, stop 450 Hz, - note when used as BPF in modem this gives a flat passband 400 Hz wide. + Low pass prototype, sample rate 8000 Hz, 60dB dB atten. Used as an input BPF for datac4 and datac13 Generated using Octave: - octave:77> h = fir1(99, 600/8000); f=0:500; w=f*pi/4000; H=freqz(h,1,w); + octave:77> h = fir1(99, 400/8000); f=0:500; w=f*pi/4000; H=freqz(h,1,w); octave:78> clf; plot(f,20*log10(abs(H))); grid; axis([0 500 -60 10]) octave:79> save_array_c_header(h,"filtP200S400","t.h") */ float filtP200S400[]={ - -0.0004451300456841, - -0.0005073524058314, - -0.0005574343189633, - -0.0005917795871614, - -0.0006039913363378, - -0.0005851770087062, - -0.0005247593261891, - -0.0004117540200065, - -0.0002364188234407, - 0.0000078726198309, - 0.0003227185190862, - 0.0007029501441555, - 0.0011352850533254, - 0.0015975774725777, - 0.0020588370843795, - 0.0024801347836117, - 0.0028164457539694, - 0.0030194013565307, - 0.0030408378344080, - 0.0028369484909049, - 0.0023727737700520, - 0.0016267071788504, - 0.0005946599478435, - -0.0007064819796693, - -0.0022364561481532, - -0.0039305770555241, - -0.0057002708395526, - -0.0074353203964610, - -0.0090078367817707, - -0.0102778503408319, - -0.0111002921979132, - -0.0113330225538234, - -0.0108454655166747, - -0.0095273388161060, - -0.0072969270838895, - -0.0041083437106991, - 0.0000427395567291, - 0.0051153449639783, - 0.0110217680991424, - 0.0176286972088453, - 0.0247609340369461, - 0.0322076167621238, - 0.0397306857265216, - 0.0470751847135474, - 0.0539808648128491, - 0.0601944633375128, - 0.0654819737785736, - 0.0696402088327538, - 0.0725069887046084, - 0.0739693597497318, - 0.0739693597497318, - 0.0725069887046084, - 0.0696402088327538, - 0.0654819737785736, - 0.0601944633375128, - 0.0539808648128491, - 0.0470751847135474, - 0.0397306857265216, - 0.0322076167621238, - 0.0247609340369461, - 0.0176286972088453, - 0.0110217680991424, - 0.0051153449639783, - 0.0000427395567291, - -0.0041083437106991, - -0.0072969270838895, - -0.0095273388161060, - -0.0108454655166747, - -0.0113330225538234, - -0.0111002921979132, - -0.0102778503408319, - -0.0090078367817707, - -0.0074353203964610, - -0.0057002708395526, - -0.0039305770555241, - -0.0022364561481532, - -0.0007064819796693, - 0.0005946599478435, - 0.0016267071788504, - 0.0023727737700520, - 0.0028369484909049, - 0.0030408378344080, - 0.0030194013565307, - 0.0028164457539694, - 0.0024801347836117, - 0.0020588370843795, - 0.0015975774725777, - 0.0011352850533254, - 0.0007029501441555, - 0.0003227185190862, - 0.0000078726198309, - -0.0002364188234407, - -0.0004117540200065, - -0.0005247593261891, - -0.0005851770087062, - -0.0006039913363378, - -0.0005917795871614, - -0.0005574343189633, - -0.0005073524058314, - -0.0004451300456841 + 0.0004961403001099, + 0.0004878954300076, + 0.0004773254753068, + 0.0004613755012320, + 0.0004356367390736, + 0.0003945564225800, + 0.0003317489139155, + 0.0002403980632049, + 0.0001137356780462, + -0.0000544235817172, + -0.0002691144005802, + -0.0005336465184803, + -0.0008490522002088, + -0.0012135843244779, + -0.0016222933008125, + -0.0020667090843560, + -0.0025346513768318, + -0.0030101867721908, + -0.0034737462756490, + -0.0039024104893224, + -0.0042703630503403, + -0.0045495058923843, + -0.0047102228630850, + -0.0047222714599590, + -0.0045557762351127, + -0.0041822920363898, + -0.0035759009450005, + -0.0027143037436366, + -0.0015798651637566, + -0.0001605721201941, + 0.0015491343107337, + 0.0035476892962647, + 0.0058259285585604, + 0.0083668321698320, + 0.0111455063209044, + 0.0141294135724972, + 0.0172788535145399, + 0.0205476868890766, + 0.0238842874108655, + 0.0272326970839423, + 0.0305339530892875, + 0.0337275476120884, + 0.0367529765550393, + 0.0395513291682391, + 0.0420668683822783, + 0.0442485511620683, + 0.0460514395405405, + 0.0474379561100668, + 0.0483789425435863, + 0.0488544860205982, + 0.0488544860205982, + 0.0483789425435863, + 0.0474379561100668, + 0.0460514395405405, + 0.0442485511620683, + 0.0420668683822783, + 0.0395513291682391, + 0.0367529765550394, + 0.0337275476120884, + 0.0305339530892875, + 0.0272326970839423, + 0.0238842874108655, + 0.0205476868890766, + 0.0172788535145399, + 0.0141294135724972, + 0.0111455063209044, + 0.0083668321698320, + 0.0058259285585604, + 0.0035476892962647, + 0.0015491343107337, + -0.0001605721201941, + -0.0015798651637566, + -0.0027143037436366, + -0.0035759009450005, + -0.0041822920363898, + -0.0045557762351127, + -0.0047222714599590, + -0.0047102228630850, + -0.0045495058923843, + -0.0042703630503403, + -0.0039024104893224, + -0.0034737462756490, + -0.0030101867721908, + -0.0025346513768318, + -0.0020667090843560, + -0.0016222933008125, + -0.0012135843244779, + -0.0008490522002088, + -0.0005336465184803, + -0.0002691144005802, + -0.0000544235817172, + 0.0001137356780462, + 0.0002403980632049, + 0.0003317489139155, + 0.0003945564225800, + 0.0004356367390736, + 0.0004613755012320, + 0.0004773254753068, + 0.0004878954300076, + 0.0004961403001099 }; // FIR filter suitable for changing rates 7500 to/from 8000 diff --git a/src/ofdm.c b/src/ofdm.c index 13e962d74..54eddb264 100644 --- a/src/ofdm.c +++ b/src/ofdm.c @@ -368,14 +368,6 @@ struct OFDM *ofdm_create(const struct OFDM_CONFIG *config) { ofdm->aphase_est_pilot_log = MALLOC(sizeof (float) * (ofdm->rowsperframe * ofdm->nc)); assert(ofdm->aphase_est_pilot_log != NULL); - /* Null pointers to unallocated buffers */ - ofdm->tx_bpf = NULL; - if (ofdm->tx_bpf_en) - allocate_tx_bpf(ofdm); - ofdm->rx_bpf = NULL; - if (ofdm->rx_bpf_en) - allocate_rx_bpf(ofdm); - /* store complex BPSK pilot symbols */ assert(sizeof (pilotvalues) >= (ofdm->nc + 2) * sizeof (int8_t)); @@ -395,6 +387,14 @@ struct OFDM *ofdm_create(const struct OFDM_CONFIG *config) { ofdm->tx_nlower = roundf((ofdm->tx_centre / ofdm->rs) - tval) - 1.0f; ofdm->rx_nlower = roundf((ofdm->rx_centre / ofdm->rs) - tval) - 1.0f; + /* Tx and Rx band pass filters */ + ofdm->tx_bpf = NULL; + if (ofdm->tx_bpf_en) + allocate_tx_bpf(ofdm); + ofdm->rx_bpf = NULL; + if (ofdm->rx_bpf_en) + allocate_rx_bpf(ofdm); + for (i = 0; i < ofdm->nrxbuf; i++) { ofdm->rxbuf[i] = 0.0f; } @@ -592,7 +592,13 @@ static void allocate_rx_bpf(struct OFDM *ofdm) { if (!strcmp(ofdm->mode, "datac4") || !strcmp(ofdm->mode, "datac13")) { quisk_filt_cfInit(ofdm->rx_bpf, filtP200S400, sizeof (filtP200S400) / sizeof (float)); - quisk_cfTune(ofdm->rx_bpf, ofdm->rx_centre / ofdm->fs); + // centre the filter on the mean carrier freq, allows a narrower filter to be used + float rx_centre = 0.0; + for(int c=0; cnc+2; c++) + rx_centre += (ofdm->rx_nlower + c) * ofdm->doc; + rx_centre = (ofdm->fs/TAU)*rx_centre/(ofdm->nc+2); + //fprintf(stderr, " rx_centre: %f\n", rx_centre); + quisk_cfTune(ofdm->rx_bpf, rx_centre / ofdm->fs); } else assert(0); } diff --git a/src/ofdm_mode.c b/src/ofdm_mode.c index 25e2f350b..2185ac38e 100644 --- a/src/ofdm_mode.c +++ b/src/ofdm_mode.c @@ -122,7 +122,7 @@ void ofdm_init_mode(char mode[], struct OFDM_CONFIG *config) { config->ns=5; config->np=47; config->tcp = 0.006; config->ts = 0.016; config->nc = 4; config->edge_pilots = 0; config->txtbits = 0; config->state_machine = "data"; - config->ftwindowwidth = 80; config->timing_mx_thresh = 0.25; + config->ftwindowwidth = 80; config->timing_mx_thresh = 0.5; config->codename = "H_1024_2048_4f"; config->amp_est_mode = 1; config->nuwbits = 32; config->bad_uw_errors = 12; uint8_t uw[] = {1,1,0,0, 1,0,1,0, 1,1,1,1, 0,0,0,0, 1,1,1,1, 0,0,0,0}; @@ -137,7 +137,7 @@ void ofdm_init_mode(char mode[], struct OFDM_CONFIG *config) { config->ns=5; config->np=18; config->tcp = 0.006; config->ts = 0.016; config->nc = 3; config->edge_pilots = 0; config->txtbits = 0; config->state_machine = "data"; - config->ftwindowwidth = 80; config->timing_mx_thresh = 0.25; + config->ftwindowwidth = 80; config->timing_mx_thresh = 0.45; config->codename = "H_256_512_4"; config->amp_est_mode = 1; config->nuwbits = 48; config->bad_uw_errors = 18; uint8_t uw[] = {1,1,0,0, 1,0,1,0, 1,1,1,1, 0,0,0,0, 1,1,1,1, 0,0,0,0}; From ff5f86b6cce0ea1a033ceedebc71dfdbf3067cf9 Mon Sep 17 00:00:00 2001 From: drowe67 Date: Sun, 30 Apr 2023 08:53:54 +0930 Subject: [PATCH 45/52] Octave: refactored complex BPF code so Tx and Rx can use same filter, tuned datac13 and datac4 tx BPF and clippers, about 1dB compression gain for no impact on MPP -4dB PER --- octave/ofdm_ldpc_rx.m | 2 +- octave/ofdm_lib.m | 39 +++++++++++++++++++++------------------ octave/ofdm_mode.m | 8 +++++--- 3 files changed, 27 insertions(+), 22 deletions(-) diff --git a/octave/ofdm_ldpc_rx.m b/octave/ofdm_ldpc_rx.m index 452730bdf..6ef15aa03 100644 --- a/octave/ofdm_ldpc_rx.m +++ b/octave/ofdm_ldpc_rx.m @@ -84,7 +84,7 @@ function ofdm_ldpc_rx(filename, mode="700D", varargin) % main loop ---------------------------------------------------------------- - rx = ofdm_complex_bandpass_filter(states, mode, rx); + rx = ofdm_rx_filter(states, mode, rx); f = 1; while(prx < Nsam) diff --git a/octave/ofdm_lib.m b/octave/ofdm_lib.m index e9bd13f82..2d3a16e7a 100644 --- a/octave/ofdm_lib.m +++ b/octave/ofdm_lib.m @@ -1217,13 +1217,11 @@ Can be used for acquisition (coarse timing), and fine timing. Tends end [tx nclipped] = ofdm_clip(states, tx*states.clip_gain1, states.ofdm_peak); - % BPF, we actually shift the signal back down to baseband to filter - ssbfilt_n = 100; - ssbfilt_coeff = fir1(ssbfilt_n, states.txbpf_width_Hz/states.Fs); - lo = exp(j*2*pi*states.fcentre*(1:length(tx))/(states.Fs)); - tx = lo.*filter(ssbfilt_coeff,1,tx.*conj(lo)); - - % filter messs up peak levels use this to get us back to approx 16384 + cutoff_norm = states.txbpf_width_Hz/states.Fs; + w_centre = mean(states.w); centre_norm = w_centre/(2*pi); + tx = ofdm_complex_bandpass_filter(cutoff_norm, centre_norm,100,tx); + + % filter messes up peak levels use this to get us back to approx 16384 tx *= states.clip_gain2; end @@ -1242,20 +1240,25 @@ Can be used for acquisition (coarse timing), and fine timing. Tends endfunction -% Complex bandpass filter as per src/filter.c -function [rx delay_samples] = ofdm_complex_bandpass_filter(states, mode, rx) +% Complex bandpass filter built from low pass prototype as per src/filter.c, +% cutoff_freq and center_freq are normalised such that cutoff_freq = 0.5 is Fs/2 +function out = ofdm_complex_bandpass_filter(cutoff_freq,center_freq,n_coeffs,in) + lowpass_coeff = fir1(n_coeffs-1, cutoff_freq); + k = (0:n_coeffs-1); + bandpass_coeff = lowpass_coeff .* exp(j*2*pi*center_freq*k); + out = filter(bandpass_coeff,1,in); +endfunction + + +% Complex bandpass filter for Rx - just used on the very low SNR modes to help +% with acquisition +function [rx delay_samples] = ofdm_rx_filter(states, mode, rx) delay_samples = 0; if strcmp(mode,"datac4") || strcmp(mode,"datac13") - w_centre = mean(states.w); - %printf("f centre: %f\n", w_centre*states.Fs/(2*pi)); + w_centre = mean(states.w); centre_norm = w_centre/(2*pi); n_coeffs = 100; - rxbpf_width_Hz = 400; - % note this designs a lowpass filter with cutoff rxbpf_width_Hz/2, as third - % argument is normalised to Fs/2 - lowpass_coeff = fir1(n_coeffs-1, rxbpf_width_Hz/states.Fs); - k = (0:n_coeffs-1); - bandpass_coeff = lowpass_coeff .* exp(j*w_centre*k); - rx = filter(bandpass_coeff,1,rx); + cutoff_Hz = 400; cutoff_norm = cutoff_Hz/states.Fs; + rx = ofdm_complex_bandpass_filter(cutoff_norm,centre_norm,n_coeffs,rx); delay_samples = n_coeffs/2; end endfunction diff --git a/octave/ofdm_mode.m b/octave/ofdm_mode.m index 446fe2830..074fd84f4 100644 --- a/octave/ofdm_mode.m +++ b/octave/ofdm_mode.m @@ -120,8 +120,9 @@ config.tx_uw(end-24+1:end) = [1 1 0 0 1 0 1 0 1 1 1 1 0 0 0 0 1 1 1 1 0 0 0 0]; config.amp_est_mode = 1; config.EsNodB = 3; config.state_machine = "data"; - config.amp_scale = 2*300E3; config.clip_gain1 = 1.5; config.clip_gain2 = 0.8; - elseif strcmp(mode,"datac13") + config.amp_scale = 2*300E3; config.clip_gain1 = 1.2; config.clip_gain2 = 1.0; + config.txbpf_width_Hz = 400; + elseif strcmp(mode,"datac13") Ns=5; config.Np=18; Tcp = 0.006; Ts = 0.016; Nc = 3; config.data_mode = "streaming"; config.edge_pilots = 0; config.Ntxtbits = 0; config.Nuwbits = 48; config.bad_uw_errors = 18; @@ -131,7 +132,8 @@ config.tx_uw(end-24+1:end) = [1 1 0 0 1 0 1 0 1 1 1 1 0 0 0 0 1 1 1 1 0 0 0 0]; config.amp_est_mode = 1; config.EsNodB = 3; config.state_machine = "data"; - config.amp_scale = 2.5*300E3; config.clip_gain1 = 1.5; config.clip_gain2 = 0.8; + config.amp_scale = 2.5*300E3; config.clip_gain1 = 1.2; config.clip_gain2 = 1.0; + config.txbpf_width_Hz = 400; elseif strcmp(mode,"1") Ns=5; config.Np=10; Tcp=0; Tframe = 0.1; Ts = Tframe/Ns; Nc = 1; else From e9f353350f7f2797c76f01e625cdb2697c7e82be Mon Sep 17 00:00:00 2001 From: drowe67 Date: Mon, 1 May 2023 18:31:49 +0930 Subject: [PATCH 46/52] ported tx BPF and clipper settings to C, doing sensible things but need to measure PAPR --- src/ofdm.c | 21 ++++++++++++++++----- src/ofdm_mode.c | 7 ++----- 2 files changed, 18 insertions(+), 10 deletions(-) diff --git a/src/ofdm.c b/src/ofdm.c index 54eddb264..552196c65 100644 --- a/src/ofdm.c +++ b/src/ofdm.c @@ -52,6 +52,7 @@ static float cnormf(complex float); static void allocate_tx_bpf(struct OFDM *); static void deallocate_tx_bpf(struct OFDM *); +static float find_carrier_centre(struct OFDM *ofdm); static void allocate_rx_bpf(struct OFDM *); static void deallocate_rx_bpf(struct OFDM *); static void dft(struct OFDM *, complex float *, complex float *); @@ -574,6 +575,12 @@ static void allocate_tx_bpf(struct OFDM *ofdm) { quisk_filt_cfInit(ofdm->tx_bpf, filtP400S600, sizeof (filtP400S600) / sizeof (float)); quisk_cfTune(ofdm->tx_bpf, ofdm->tx_centre / ofdm->fs); } + else if (!strcmp(ofdm->mode, "datac4") || !strcmp(ofdm->mode, "datac13")) { + quisk_filt_cfInit(ofdm->tx_bpf, filtP200S400, sizeof (filtP200S400) / sizeof (float)); + // centre the filter on the mean carrier freq, allows a narrower filter to be used + float tx_centre = find_carrier_centre(ofdm); + quisk_cfTune(ofdm->tx_bpf, tx_centre / ofdm->fs); + } else assert(0); } @@ -584,6 +591,13 @@ static void deallocate_tx_bpf(struct OFDM *ofdm) { ofdm->tx_bpf = NULL; } +static float find_carrier_centre(struct OFDM *ofdm) { + float rx_centre = 0.0; + for(int c=0; cnc+2; c++) + rx_centre += (ofdm->rx_nlower + c) * ofdm->doc; + return (ofdm->fs/TAU)*rx_centre/(ofdm->nc+2); +} + static void allocate_rx_bpf(struct OFDM *ofdm) { ofdm->rx_bpf = MALLOC(sizeof(struct quisk_cfFilter)); assert(ofdm->rx_bpf != NULL); @@ -593,11 +607,8 @@ static void allocate_rx_bpf(struct OFDM *ofdm) { if (!strcmp(ofdm->mode, "datac4") || !strcmp(ofdm->mode, "datac13")) { quisk_filt_cfInit(ofdm->rx_bpf, filtP200S400, sizeof (filtP200S400) / sizeof (float)); // centre the filter on the mean carrier freq, allows a narrower filter to be used - float rx_centre = 0.0; - for(int c=0; cnc+2; c++) - rx_centre += (ofdm->rx_nlower + c) * ofdm->doc; - rx_centre = (ofdm->fs/TAU)*rx_centre/(ofdm->nc+2); - //fprintf(stderr, " rx_centre: %f\n", rx_centre); + float rx_centre = find_carrier_centre(ofdm); + //fprintf(stderr, " rx_centre: %f\n", rx_centre); quisk_cfTune(ofdm->rx_bpf, rx_centre / ofdm->fs); } else assert(0); diff --git a/src/ofdm_mode.c b/src/ofdm_mode.c index 2185ac38e..13f6e8c5f 100644 --- a/src/ofdm_mode.c +++ b/src/ofdm_mode.c @@ -117,7 +117,6 @@ void ofdm_init_mode(char mode[], struct OFDM_CONFIG *config) { memcpy(&config->tx_uw[config->nuwbits-sizeof(uw)], uw, sizeof(uw)); config->data_mode = "streaming"; config->amp_scale = 300E3; config->clip_gain1 = 2.2; config->clip_gain2 = 0.8; - config->tx_bpf_en = true; config->clip_en = true; } else if (strcmp(mode,"datac4") == 0) { config->ns=5; config->np=47; config->tcp = 0.006; config->ts = 0.016; config->nc = 4; config->edge_pilots = 0; @@ -130,8 +129,7 @@ void ofdm_init_mode(char mode[], struct OFDM_CONFIG *config) { memcpy(config->tx_uw, uw, sizeof(uw)); memcpy(&config->tx_uw[config->nuwbits-sizeof(uw)], uw, sizeof(uw)); config->data_mode = "streaming"; - config->amp_scale = 2*300E3; config->clip_gain1 = 1.5; config->clip_gain2 = 0.8; - config->tx_bpf_en = false; config->clip_en = false; + config->amp_scale = 2*300E3; config->clip_gain1 = 1.2; config->clip_gain2 = 1.0; config->rx_bpf_en = true; } else if (strcmp(mode,"datac13") == 0) { config->ns=5; config->np=18; config->tcp = 0.006; config->ts = 0.016; config->nc = 3; @@ -145,8 +143,7 @@ void ofdm_init_mode(char mode[], struct OFDM_CONFIG *config) { memcpy(config->tx_uw, uw, sizeof(uw)); memcpy(&config->tx_uw[config->nuwbits-sizeof(uw)], uw, sizeof(uw)); config->data_mode = "streaming"; - config->amp_scale = 2.5*300E3; config->clip_gain1 = 1.5; config->clip_gain2 = 0.8; - config->tx_bpf_en = false; config->clip_en = false; + config->amp_scale = 2.5*300E3; config->clip_gain1 = 1.2; config->clip_gain2 = 1.0; config->rx_bpf_en = true; } else { From 1089b6b0c2ba616d732c9c0efdf47559bd1635fc Mon Sep 17 00:00:00 2001 From: drowe67 Date: Mon, 1 May 2023 18:52:24 +0930 Subject: [PATCH 47/52] updated check of peak levels to include datac4 & datac13 --- unittest/check_peak.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/unittest/check_peak.sh b/unittest/check_peak.sh index 38a2c4fef..6462d04ad 100755 --- a/unittest/check_peak.sh +++ b/unittest/check_peak.sh @@ -50,6 +50,8 @@ if [ "$1" == "LPCNet" ]; then data_test "datac0" data_test "datac1" data_test "datac3" + data_test "datac4" + data_test "datac13" fi exit 0 From 689fe3693be4fa602d4ca3f13b9cdd04482a75b4 Mon Sep 17 00:00:00 2001 From: drowe67 Date: Tue, 2 May 2023 16:33:41 +0930 Subject: [PATCH 48/52] some support for datac4 & datac13 on curves --- octave/snr_curves_plot.m | 18 +++++++++++++++--- unittest/raw_data_curves/Makefile | 16 ++++++++++++++-- unittest/raw_data_curves/snr_curves.sh | 18 +++++++++++++----- 3 files changed, 42 insertions(+), 10 deletions(-) diff --git a/octave/snr_curves_plot.m b/octave/snr_curves_plot.m index 0c277d510..aa28224b0 100644 --- a/octave/snr_curves_plot.m +++ b/octave/snr_curves_plot.m @@ -58,6 +58,8 @@ function snrest_snr_screen(source, channel) snr_scatter(source, 'datac0', channel,'b+-') snr_scatter(source, 'datac1', channel,'g+-') snr_scatter(source, 'datac3', channel,'r+-') + snr_scatter(source, 'datac4', channel,'r+-') + snr_scatter(source, 'datac13', channel,'r+-') xlabel('SNR (dB)'); ylabel('SNRest (dB)'); grid('minor'); axis([-5 12 -5 12]); a = axis; @@ -111,6 +113,8 @@ function thruput_v_snr(source, mode, channel, colour) if strcmp(mode,"datac0") Rb=291; end; if strcmp(mode,"datac1") Rb=980; end; if strcmp(mode,"datac3") Rb=321; end; + if strcmp(mode,"datac4") Rb=87; end; + if strcmp(mode,"datac13") Rb=65; end; if strcmp(channel,"awgn") plot(snr, Rb*(1-per), sprintf('%s;%s %s;', colour, mode, channel)); else @@ -199,12 +203,16 @@ function octave_c_tx_comp_print(channel) per_v_snr('ctxc','datac0','awgn','bo-') per_v_snr('ctxc','datac1','awgn','go-') per_v_snr('ctxc','datac3','awgn','ro-') + per_v_snr('ctxc','datac4','awgn','co-') + per_v_snr('ctxc','datac13','awgn','mo-') per_v_snr('ctxc','datac0','mpp','bx-') per_v_snr('ctxc','datac1','mpp','gx-') per_v_snr('ctxc','datac3','mpp','rx-') + per_v_snr('ctxc','datac4','mpp','cx-') + per_v_snr('ctxc','datac13','mpp','mx-') xlabel('SNR (dB)'); ylabel('PER'); grid; hold off; - axis([-5 10 1E-3 1]); + axis([-10 10 1E-3 1]); title('PER of C Raw Data Modes (with compression)'); endfunction @@ -220,14 +228,18 @@ function octave_c_tx_comp_print(channel) thruput_v_snr('ctxc','datac0','awgn','bo-') thruput_v_snr('ctxc','datac1','awgn','go-') thruput_v_snr('ctxc','datac3','awgn','ro-') + thruput_v_snr('ctxc','datac4','awgn','co-') + thruput_v_snr('ctxc','datac13','awgn','mo-') thruput_v_snr('ctxc','datac0','mpp','bx-') thruput_v_snr('ctxc','datac1','mpp','gx-') thruput_v_snr('ctxc','datac3','mpp','rx-') + thruput_v_snr('ctxc','datac4','mpp','cx-') + thruput_v_snr('ctxc','datac13','mpp','mx-') xlabel('SNR (dB)'); ylabel('bits/s'); grid; hold off; - axis([-6 12 0 1000]); + axis([-10 10 0 1000]); title(' Throughput for C Tx (with compression)'); - legend('location','east'); + legend('location','west'); endfunction function c_tx_comp_thruput_print; diff --git a/unittest/raw_data_curves/Makefile b/unittest/raw_data_curves/Makefile index 81b845576..9f13d1f63 100644 --- a/unittest/raw_data_curves/Makefile +++ b/unittest/raw_data_curves/Makefile @@ -20,7 +20,7 @@ all: test \ clean: rm -f *.txt *.png *.raw -# trap common setup error +# run this first, traps common CML setup error test: source snr_curves.sh; test_ldpc @@ -55,25 +55,37 @@ $(snr_ch_mpp): source snr_curves.sh; generate_ch_data datac1 mpp source snr_curves.sh; generate_ch_data datac3 mpp +# C without compression + $(snr_ctx): source snr_curves.sh; generate_snrest_v_snr_data datac0 awgn source snr_curves.sh; generate_snrest_v_snr_data datac1 awgn source snr_curves.sh; generate_snrest_v_snr_data datac3 awgn + source snr_curves.sh; generate_snrest_v_snr_data datac4 awgn + source snr_curves.sh; generate_snrest_v_snr_data datac13 awgn $(snr_ctx_mpp): source snr_curves.sh; generate_snrest_v_snr_data datac0 mpp source snr_curves.sh; generate_snrest_v_snr_data datac1 mpp source snr_curves.sh; generate_snrest_v_snr_data datac3 mpp + source snr_curves.sh; generate_snrest_v_snr_data datac4 mpp + source snr_curves.sh; generate_snrest_v_snr_data datac13 mpp + +# C with compression $(snr_ctxc): source snr_curves.sh; generate_snrest_v_snr_data datac0 awgn 1 source snr_curves.sh; generate_snrest_v_snr_data datac1 awgn 1 source snr_curves.sh; generate_snrest_v_snr_data datac3 awgn 1 + source snr_curves.sh; generate_snrest_v_snr_data datac4 awgn 1 + source snr_curves.sh; generate_snrest_v_snr_data datac13 awgn 1 $(snr_ctxc_mpp): source snr_curves.sh; generate_snrest_v_snr_data datac0 mpp 1 source snr_curves.sh; generate_snrest_v_snr_data datac1 mpp 1 source snr_curves.sh; generate_snrest_v_snr_data datac3 mpp 1 + source snr_curves.sh; generate_snrest_v_snr_data datac4 mpp 1 + source snr_curves.sh; generate_snrest_v_snr_data datac13 mpp 1 # Octave and C curves should be on top of each other, indicating Octave # and ch noise injection/SNR measurement are equivalent @@ -101,7 +113,7 @@ octave_c_tx_comp_mpp.png: $(snr_oct_mpp) $(snr_ctxc_mpp) echo "snr_curves_plot; octave_c_tx_comp_print('mpp'); quit" | \ octave-cli -p $(CODEC2)/octave -# composite AWGN and MPP from C Tx (compressed) - what end users would run +# combined AWGN and MPP from C Tx (compressed) - what end users would run c_tx_comp.png: $(snr_ctxc) $(snr_ctxc_mpp) echo "snr_curves_plot; c_tx_comp_print; quit" | \ octave-cli -p $(CODEC2)/octave diff --git a/unittest/raw_data_curves/snr_curves.sh b/unittest/raw_data_curves/snr_curves.sh index 6f8d1174f..6da671c58 100755 --- a/unittest/raw_data_curves/snr_curves.sh +++ b/unittest/raw_data_curves/snr_curves.sh @@ -106,12 +106,13 @@ function generate_snrest_v_snr_data { snr_nudge=0 aNo_list=$No_list + + # nudge SNR test range to get meaningful results for these tests if [ "$mode" == "datac1" ]; then - # nudge SNR test range to get meaningful results for this test snr_nudge=4 - else - # few extra points to test SNRest at high SNRs on low rate waveforms - aNo_list=$No_list" -28 -30" + fi + if [[ "$mode" == "datac4" || "$mode" == "datac13" ]]; then + snr_nudge=-6 fi ch_multipath='' @@ -158,6 +159,13 @@ function generate_snrest_v_snr_data { done echo ${SNRoffset} > offset_${id}_${mode}_${channel}.txt + + # trap not enough fading file samples (with mpp) + grep "Fading file finished" ${ch_log} + if [ $? -eq 0 ]; then + cat ${ch_log} + exit 1 + fi SNRch=$(cat ${ch_log} | grep SNR3k | tr -s ' ' | cut -d' ' -f3) echo ${SNRch} > snr_${id}_${mode}_${channel}.txt } @@ -166,7 +174,7 @@ function generate_snrest_v_snr_data { function test_ldpc { echo "ldpcut; quit" | DISPLAY="" octave-cli -p ${CODEC2}/octave if [ "$?" -ne 0 ]; then - echo "basic octave test failed, you may need to" + echo "basic octave test failed, you may need to" echo "(a) run ctests to create build_xxx/cml" echo "(b) set up ~/.octaverc as per octave/ldpc.m" exit 1 From 8cacde104bd4b0b2b3e10f96cc9193636d480824 Mon Sep 17 00:00:00 2001 From: drowe67 Date: Wed, 3 May 2023 08:35:30 +0930 Subject: [PATCH 49/52] updated README_data.md, have put raw data section at top as it is in more widespread use --- README_data.md | 258 +++++++++++++++++++------------------- doc/c_tx_comp.png | Bin 29482 -> 36292 bytes doc/c_tx_comp_thruput.png | Bin 26312 -> 32796 bytes doc/snrest_snr_ctxc.png | Bin 27625 -> 31398 bytes octave/snr_curves_plot.m | 6 +- 5 files changed, 133 insertions(+), 131 deletions(-) diff --git a/README_data.md b/README_data.md index cf9d10190..4bf467408 100644 --- a/README_data.md +++ b/README_data.md @@ -12,6 +12,16 @@ The VHF data channel was developed by Jeroen Vreeken. ## Quickstart +Raw modem frame API: + +1. Let's send a 128 byte frame containing some text over the modem: + ```sh + padding=$(head -c 115 < /dev/zero | tr '\0' '-'); echo "Hello World" $padding > in.txt + ./src/freedv_data_raw_tx --bursts 1 datac3 in.txt - | ./src/freedv_data_raw_rx --framesperburst 1 datac3 - - + Hello World -------- + ``` + Note we've padded the input frame to 126 bytes, the DATAC3 framesize (less CRC). + VHF packet data API: 1. Simple test using mode 2400A and VHF packet data @@ -41,129 +51,6 @@ VHF packet data API: $ ./src/freedv_data_tx 2400A - --callsign T3ST --ssid 15 --frames 15 | src/freedv_data_rx 2400A - ``` -Raw modem frame API: - -1. Let's send a 128 byte frame containing some text over the modem: - ```sh - padding=$(head -c 115 < /dev/zero | tr '\0' '-'); echo "Hello World" $padding > in.txt - ./src/freedv_data_raw_tx --bursts 1 datac3 in.txt - | ./src/freedv_data_raw_rx --framesperburst 1 datac3 - - - Hello World -------- - ``` - Note we've padded the input frame to 126 bytes, the DATAC3 framesize (less CRC). - -# VHF Packet Data Channel - -The FreeDV VHF data channel operates on a packet level. The FreeDV modems however typically operate on a fixed frame base. This means that data packets have to be sent in multiple frames. - -The packet format is modeled after Ethernet. As a result, any protocol that is compatible with Ethernet can potentially be used over a FreeDV data link. (There are of course practical limits. Browsing the world wide web with just a few hundred bits per second will not be a pleasant experience.) - -## Header optimization - -When there are no packets available for transmission a small 'filler' packet with just the sender's address will be sent. -When there is a packet available not all of the header needs to be sent. The sender's address can often be left out if it was already sent in a previous frame. Likewise when the packet has no specific destination but is targeted at a multicast address, this can also be transmitted in a single bit as opposed to a 6 byte broadcast address. - - -## Addressing - -Since the format is based on Ethernet, a 6 byte sender and destination address is used. It is possible to encode an ITU compatible callsign in these bytes. See http://dmlinking.net/eth_ar.html for more info. Or have a look at freedv_data_tx.c and freedv_data_rx.c for an actual implementation. - -## Packet types - -The 2 byte EtherType field is used to distinguish between various protocols. - -## Checks - -Not all channels are perfect, and especially since a packet is split up over multiple frames, bits might get lost. Each packet therefore has a CRC which is checked before it is accepted. Note there is No FEC on 2400A/2400B/800XA. - -## Available modes - -The data channel is available for modes 2400A, 2400B and 800XA. - -## API - -The data channel is part of the regular FreeDV API. - -### Initialization - -After creating a new freedv instance with freedv_open(), a few more calls need to be done before the data channel is usable. - - ``` - void freedv_set_data_header (struct freedv *freedv, unsigned char *header); - ``` - -The address that will be used for 'filler' packets must be set. The freedv_set_data_header() function must be called with a 6 byte header. - - ``` - typedef void (*freedv_callback_datarx)(void *, unsigned char *packet, size_t size); - typedef void (*freedv_callback_datatx)(void *, unsigned char *packet, size_t *size); - void freedv_set_callback_data (struct freedv *freedv, freedv_callback_datarx datarx, freedv_callback_datatx datatx, void *callback_state); - ``` - -Using freedv_set_callback_data() two callback functions can be provided. The datarx callback will be used whenever a new data packet has been successfully received. The datatx callback will be used when a new data packet is required for transmission. - -### Operation - - ``` - void freedv_datatx (struct freedv *f, short mod_out[]); - ``` - -During normal operation the freedv_datatx() function can be used whenever a data frame has to be sent. If no data is available it will request new data using the datatx callback. The callback function is allowed to set 'size' to zero if no data is available or if it wishes to send an address frame. - -For reception the regular freedv_rx() functions can be used as received data will automatically be reported using the datarx callback. Be aware that these functions return the actual number of received speech samples. When a data frame is received the return value will be zero. This may lead to 'gaps' in the audio stream which will have to be filled with silence. - -### Examples - -The freedv_data_tx and freedv_data_rx test programs implement the minimum needed to send and receive data packets. - -## Mixing voice and data - -Encoding only voice data is easy with the FreeDV API. Simply use the freedv_tx() function and provide it with speech samples. -Likewise encoding only data is also easy. Make sure to provide a source of data frames using the freedv_set_callback_data() function, and use the freedv_datatx() function to generate frames. - -However there are many use cases where one would like to transmit a mix of voice and data. For example one might want to transmit their callsign in a machine readable format, or a short position report. There are a few ways to do this: - -### Data bursts at start and/or end of transmission - -This method simply transmits voice frames during the transmission, except for a few moments. For example when the user keys the radio the software uses the freedv_datatx() function for a number of frames before switching to regular voice frames. -Likewise when the user releases the key the software may hold it for a number of frames to transmit data before it releases the actual radio. - -Be careful though: depending on your setup (radio, PC, soundcard, etc) the generated frames and the keying of your radio might not be perfectly in sync and the first or last frames might be lost in the actual transmission. Make sure to take this into account when using this method. - -### Data and voice interleaved - -Another method is to generate a mixed stream of frames. Compared to a small burst at the beginning or end a lot more data can be sent. We only need a way to choose between voice or data such that the recovered speech at the other side is not impacted. - -#### Detect voice activity - -When it is possible to determine activity in the voice signal (and it almost always is) this presence can be used to insert a data frame by calling freedv_datatx() instead of freedv_tx()/freedv_codectx(). This method is used in the freedv_mixed_tx demo program. When the option --codectx is given the codec2 library is used to determine the activity. - - ``` - $ ./src/freedv_mixed_tx 2400A ../raw/hts1a.raw - --codectx | src/freedv_data_rx 2400A - - $ ./src/freedv_mixed_tx 2400A ../raw/hts1a.raw - | src/freedv_data_rx 2400A - - ``` - -The advantage of this method is that the audio is not distorted, there was nothing (or near nothing) to distort. A drawback is that constant voice activity may mean there are insufficient frames for data. - -### Receiving mixed voice and data - -Receiving and decoding a mixed voice and data stream is (almost) as easy as receiving a regular voice-only transmission. -One simply uses the regular API calls for reception of speech samples. In addition, the callback functions are used for data. -There is one caveat though: when a data frame is received the API functions (like freedv_rx) will return zero as this is the amount of codec/voice data received. -For proper playback silence (or comfort noise) should be inserted for the duration of a frame to restore the timing of the original source speech samples. -An example of how this is done is provided in freedv_mixed_rx - - ``` - $ ./src/freedv_mixed_tx 2400A ../raw/hts1a.raw - | src/freedv_mixed_rx 2400A - ./hts1a_out.raw - ``` - -### Insert a data frame periodically - -This is a very simple method, simply insert a data frame every n frames, (e.g. once every 10 seconds). Since single FreeDV frames are relatively short (tens of milliseconds) the effect on received audio will be minor. The advantage of this method is that one can create a guaranteed amount of data bandwidth. A drawback is some interruption in the audio that may be noticed. - -### Combination of the above. - -A combination of the two methods may also be used. Send data when no voice is active and insert a frame when this does not occur for a long time. - # Raw Data using the FreeDV API The raw data API can be used to send frames of bytes over radio channels. The frames are protected with FEC and have a 16-bit checksum to verify correct transmission. However the raw data API may lose frames due to channel impairments, loss of sync, or acquisition delays. The caller must handle these situations. The caller is also responsible for segmentation/re-assembly of the modem frames into larger blocks of data. @@ -243,20 +130,22 @@ Some notes on this example: 1. Although the `ch` utility is designed for 8kHz sample rate operation, it just operates on sampled signals, so it's OK to use at higher sample rates. It does have some internal filtering so best to keep your signal well away from 0 and (sample rate)/2. The SNR measurement is calibrated to a 3000 Hz noise bandwidth, so won't make much sense at other sample rates. The third argument `-12` sets the noise level of the channel. 1. The `--mask` frequency offset algorithm is used, which gives better results on noisy channels, especially for 4FSK. -### Reading Further +## Reading Further 1. Examples in the [ctests](CMakeLists.txt). 1. [FSK_LDPC blog post](http://www.rowetel.com/?p=7467) -## OFDM Raw Data modes for HF Radio +# OFDM Raw Data modes for HF Radio These modes use an OFDM modem with powerful LDPC codes and are designed for sending data over HF radio channels with multipath fading. The current modes supported are: | FreeDV Mode | RF bandwidth (Hz) | Payload data rate bits/s | Payload bytes/frame | FEC | Duration (sec) | MPP test | Use case | | :-: | :-: | :-: | :-: | :-: | :-: | :-: | :-: | -| DATAC0 | 500 | 291 | 14 | (256,128) | 0.44 | 70/100 at 0dB | Reverse link ACK packets (all SNRs) | +| DATAC0 | 500 | 291 | 14 | (256,128) | 0.44 | 70/100 at 0dB | Reverse link ACK packets | | DATAC1 | 1700 | 980 | 510 | (8192,4096) | 4.18 | 92/100 at 5dB | Forward link data (medium SNR) | | DATAC3 | 500 | 321 | 126 | (2048,1024) | 3.19 | 74/100 at 0dB | Forward link data (low SNR) | +| DATAC4 | 250 | 87 | 56 | (1472,448) | 5.17 | 90/100 at -4dB | Forward link data (low SNR) | +| DATAC13 | 200 | 64 | 126 | (384,128) | 2.0 | 90/100 at -4dB | Reverse link ACK packets (low SNR) | Notes: 1. 16 bits (2 bytes) per frame are reserved for a 16 bit CRC, e.g. for `datac3` we have 128 byte frames, and 128-2=126 bytes/frame of payload data. @@ -340,7 +229,7 @@ The following curves illustrate the OFDM raw data mode performance and throughpu ![](doc/c_tx_comp.png) ![](doc/c_tx_comp_thruput.png) -`datac0` doesn't perform as well as `datac3` over the MPP channel due to it's short length compared to the fading period. The throughput curve can be used as a guide for "gear shifting" between modes. These curves were generated by [snr_curves.sh](../unittest/raw_data_curves/snr_curves.sh) +The signalling modes (`datac0` and `datac13`) tend to have a "long PER tail" at they are short in duration compared to the fading period. The throughput curve can be used as a guide for "gear shifting" between modes. These curves were generated by [snr_curves.sh](../unittest/raw_data_curves/snr_curves.sh) ## SNR estimation and clipping @@ -363,7 +252,6 @@ The following plots illustrate the SNR estimates versus actual channel SNR with ## Reading Further -Resources: 1. See the raw data example in Quickstart section above. 1. For simple examples of how use the FreeDV API, see the demo programs [freedv_datac1_tx.c](demo/freedv_datac1_tx.c) and [freedv_datac1_rx.c](demo/freedv_datac1_rx.c) 1. [freedv_data_raw_tx.c](src/freedv_data_raw_tx.c) and [freedv_data_raw_rx.c](src/freedv_data_raw_rx.c) are more full deatured example programs. @@ -371,3 +259,117 @@ Resources: 1. Examples in the [ctests](CMakeLists.txt) (look for "FreeDV API raw data") 1. [Codec 2 HF Data Modes Part 1 blog post](http://www.rowetel.com/?p=7167) 1. [HF Data Acquisition](https://github.com/drowe67/codec2/pull/171) GitHub Pull Request + +# VHF Packet Data Channel + +The FreeDV VHF data channel operates on a packet level. The FreeDV modems however typically operate on a fixed frame base. This means that data packets have to be sent in multiple frames. + +The packet format is modeled after Ethernet. As a result, any protocol that is compatible with Ethernet can potentially be used over a FreeDV data link. (There are of course practical limits. Browsing the world wide web with just a few hundred bits per second will not be a pleasant experience.) + +## Header optimization + +When there are no packets available for transmission a small 'filler' packet with just the sender's address will be sent. +When there is a packet available not all of the header needs to be sent. The sender's address can often be left out if it was already sent in a previous frame. Likewise when the packet has no specific destination but is targeted at a multicast address, this can also be transmitted in a single bit as opposed to a 6 byte broadcast address. + + +## Addressing + +Since the format is based on Ethernet, a 6 byte sender and destination address is used. It is possible to encode an ITU compatible callsign in these bytes. See http://dmlinking.net/eth_ar.html for more info. Or have a look at freedv_data_tx.c and freedv_data_rx.c for an actual implementation. + +## Packet types + +The 2 byte EtherType field is used to distinguish between various protocols. + +## Checks + +Not all channels are perfect, and especially since a packet is split up over multiple frames, bits might get lost. Each packet therefore has a CRC which is checked before it is accepted. Note there is No FEC on 2400A/2400B/800XA. + +## Available modes + +The data channel is available for modes 2400A, 2400B and 800XA. + +## API + +The data channel is part of the regular FreeDV API. + +### Initialization + +After creating a new freedv instance with freedv_open(), a few more calls need to be done before the data channel is usable. + + ``` + void freedv_set_data_header (struct freedv *freedv, unsigned char *header); + ``` + +The address that will be used for 'filler' packets must be set. The freedv_set_data_header() function must be called with a 6 byte header. + + ``` + typedef void (*freedv_callback_datarx)(void *, unsigned char *packet, size_t size); + typedef void (*freedv_callback_datatx)(void *, unsigned char *packet, size_t *size); + void freedv_set_callback_data (struct freedv *freedv, freedv_callback_datarx datarx, freedv_callback_datatx datatx, void *callback_state); + ``` + +Using freedv_set_callback_data() two callback functions can be provided. The datarx callback will be used whenever a new data packet has been successfully received. The datatx callback will be used when a new data packet is required for transmission. + +### Operation + + ``` + void freedv_datatx (struct freedv *f, short mod_out[]); + ``` + +During normal operation the freedv_datatx() function can be used whenever a data frame has to be sent. If no data is available it will request new data using the datatx callback. The callback function is allowed to set 'size' to zero if no data is available or if it wishes to send an address frame. + +For reception the regular freedv_rx() functions can be used as received data will automatically be reported using the datarx callback. Be aware that these functions return the actual number of received speech samples. When a data frame is received the return value will be zero. This may lead to 'gaps' in the audio stream which will have to be filled with silence. + +### Examples + +The freedv_data_tx and freedv_data_rx test programs implement the minimum needed to send and receive data packets. + +## Mixing voice and data + +Encoding only voice data is easy with the FreeDV API. Simply use the freedv_tx() function and provide it with speech samples. +Likewise encoding only data is also easy. Make sure to provide a source of data frames using the freedv_set_callback_data() function, and use the freedv_datatx() function to generate frames. + +However there are many use cases where one would like to transmit a mix of voice and data. For example one might want to transmit their callsign in a machine readable format, or a short position report. There are a few ways to do this: + +### Data bursts at start and/or end of transmission + +This method simply transmits voice frames during the transmission, except for a few moments. For example when the user keys the radio the software uses the freedv_datatx() function for a number of frames before switching to regular voice frames. +Likewise when the user releases the key the software may hold it for a number of frames to transmit data before it releases the actual radio. + +Be careful though: depending on your setup (radio, PC, soundcard, etc) the generated frames and the keying of your radio might not be perfectly in sync and the first or last frames might be lost in the actual transmission. Make sure to take this into account when using this method. + +### Data and voice interleaved + +Another method is to generate a mixed stream of frames. Compared to a small burst at the beginning or end a lot more data can be sent. We only need a way to choose between voice or data such that the recovered speech at the other side is not impacted. + +#### Detect voice activity + +When it is possible to determine activity in the voice signal (and it almost always is) this presence can be used to insert a data frame by calling freedv_datatx() instead of freedv_tx()/freedv_codectx(). This method is used in the freedv_mixed_tx demo program. When the option --codectx is given the codec2 library is used to determine the activity. + + ``` + $ ./src/freedv_mixed_tx 2400A ../raw/hts1a.raw - --codectx | src/freedv_data_rx 2400A - + $ ./src/freedv_mixed_tx 2400A ../raw/hts1a.raw - | src/freedv_data_rx 2400A - + ``` + +The advantage of this method is that the audio is not distorted, there was nothing (or near nothing) to distort. A drawback is that constant voice activity may mean there are insufficient frames for data. + +### Receiving mixed voice and data + +Receiving and decoding a mixed voice and data stream is (almost) as easy as receiving a regular voice-only transmission. +One simply uses the regular API calls for reception of speech samples. In addition, the callback functions are used for data. +There is one caveat though: when a data frame is received the API functions (like freedv_rx) will return zero as this is the amount of codec/voice data received. +For proper playback silence (or comfort noise) should be inserted for the duration of a frame to restore the timing of the original source speech samples. +An example of how this is done is provided in freedv_mixed_rx + + ``` + $ ./src/freedv_mixed_tx 2400A ../raw/hts1a.raw - | src/freedv_mixed_rx 2400A - ./hts1a_out.raw + ``` + +### Insert a data frame periodically + +This is a very simple method, simply insert a data frame every n frames, (e.g. once every 10 seconds). Since single FreeDV frames are relatively short (tens of milliseconds) the effect on received audio will be minor. The advantage of this method is that one can create a guaranteed amount of data bandwidth. A drawback is some interruption in the audio that may be noticed. + +### Combination of the above. + +A combination of the two methods may also be used. Send data when no voice is active and insert a frame when this does not occur for a long time. + diff --git a/doc/c_tx_comp.png b/doc/c_tx_comp.png index 8663ca07e79ef02e907a207d77cb7c3517feab04..5d781c059cc0ec2f2c398ff19870ba13c161b1f1 100644 GIT binary patch delta 33760 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Μ<$xoEz{ZdB^Z(vZh@EH(8`Uxh&Ma)HSVtT9)__5 zKE?6tvmZN#{v--1XVRbI7HZe}20DTNbCF9RSWqvW8~Pi5iUs!2VDaX4VzB}8i$PPs zaKQ@@``rjkrT1O{3j`TVQO0#9M4XucC$u6k=SnI9h~r(B;BW08tPsq*f8P!L2vhjN zFfH6uZXyb-zwC*n?RWn*M^*o)DqQ#gg7~tj%dOK{3_nMEJsH+BtlW1OSVb{r4 zcoF`O8Ban3&>rSNuV~XCC>X%00M|u#d(*$n8X~doDeTZOe)68jL)3mkvOFZLil3 zafTK}ZX1_Hn>V~HDhLZ^v+z($Z7nqgYnmI2V+gwvQf99a;1|? zcjKqY#q7u_UgLhN%QO0{KB#EsCdufHO>ilaJV}FtAXBF3O??KB)a7TK+B=7Y{ZQ(RS7w?-+Kc>qENiP-xU z=xtiMuoXT_)o|%ScgO<$(sr+)+(DBl!kUI%0NS;qy)|8Wv`7a-dCM#=#12eC{B(^kmClSAqnUHq z`?($k4#QoFPSjUF_4voYK_+GbOnd5y^0wQl@eMj(;}IyDb!%iXU?d2l&{pg;&U2;x zxt*@P68tUm{r&ww7#)oH0}*dlUH5px`Eh0mh|?dZ1AtS79|nRgh-BP(cl`6}Ws@fW zg^`Vi#9xC~z(R-qu~2PTCaDlg0q6g>Zd;f^@7H5xEHM*w?GSw;MfX;1efXN6o10A8 zeCjbstVi;U+*qc5e-H&N0Mbg`dG~Pn%|c+P{mloOvbbZf6@Q5nv3xD_fQJ9fJoRKe zOR%Gd8Z_DvvCr__%ZsxC8sM`62swW!-o=kw(mu(kz)FsrEqIU7`<-MCUlGvhfU#Ax z>5GD7RW@EhK>^ZYinIV=kYvQjcIcjxAmYm{DRA;M9mqe!UQm9_ULi5Dpaq*smXf2M zOSSBDt+FkX&M5S&vjg;=3X^mIZO44luy%;h(7+=>)}`AC2^+t|exwGOKIsL{sz?i1 zwuqg)W6!u6kA&y->)fvl&hYc>hW6;6cPN$=7<&7%_HhzwsDEC06E_|4!=myQTLb8*njva$szb$vih;Nk6?qaQISh@u;P;ehDZ^|U z%a?XVIye>7PuMfX{T`j0qR3=!yr!NiNGV}AD13wcGBUCS2{?e`3B;qczW_~xOen*H zgJFsuyotLTflO#uF#yQmTvk75uxf0v-@FU}W?g;p`}A zqoe2<;dlaJm>MK7%;XAeEawxC&R(st1+r`NKKMRm`?^fbgzaU6TZLaTbbV`B7`hcV zHyGmQS6N$|wOA=8Dyn+F(>MjvfgJr}QDzNLZLydDf~syuoST7+FWNFcHs;hDkS{Bk zfZ{zQm;ibF78e6x&6Bacafe1h$p>rNx^#Fh{mw*)Ppnt%jj*tF+AzLQ%rz=%8wkG5 zytDuf=t7M55Oo>2v_36e@Lerd_K8{XCIyE5)o+dQpr z34c;_i2KD&f&Q7^8&dgx{P%_c!co!CFVF>$7A*ric{FO9zI7br&8%pkVS*k8_=gNt zBY*x19MT!5T;9m{Ta+Bp@_jWhLx|XT1!OaC7Dqv_Z)Nf12{6{NwSqP|1(*?{!vbU| zhEYR`O=^&gSlwCK+1XjJXKgk0z%P!c+uVUw<58n=@$fDT308^lS$RR2jTr55u$_>f z#-L6XGwdM}iTBKv)Uz08zs>WA_7)jlp<}8@J_vkTF@>06Pt~{!8Eczs{#B&s)}<4X zldG#CnYqCwR(r|3Ky5WTXH_wf{$HC>H`fuN<42 zdg@RC(=7eTfYe2;(j7Nn@38pKAIdt%|9dn31N92OZYX0hkHNi$1n zdp9i~ydIcgNIV#nds+pWqv;-;bMHYQ>|J9Er1xC9ny<(xn$C)up7v#Pd=4CzvAx?> zSV-OT8N)^iwIVZROD0c%d2Kg5`!o}T2i~P0%kMNDNX|o$rT=%E`IjH}zq`->gUgt0 a=CPiZKiJzBF9Rb6Ica#tpj_WE`hNiS&8`&y diff --git a/doc/snrest_snr_ctxc.png b/doc/snrest_snr_ctxc.png index e3b194118ac6bac5e8099b276a646ea9ea20bcb3..326d1473d7042b2f889667a714a260a7218bc8c0 100644 GIT binary patch delta 28886 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 L_0)*L7YYJORuNGF$&v+W2~7}? zBq~9IG)V;nfo_7*WVp3>_c!()!3r*_Ck21mGgBWrZK8?s)B~1^dYK+bKTddelFg$u_IgxRu{RgVNFO9`o$`D!Tq|~ z{zTVIGN>ZgON(&=o9dn%yu|I=;{z|;duhnB9a?3y<1 zSDT~R1Ox;;cF)w)b19m3n3i>-OTs3qwOgtJ;8Dk}qPS?K*l}qS>Sr1MroVLZQ+M3JFrYB?Q9y!dOd22A?l# z!YSAglWntoEqywgyuAMT<{ubo>15uOv@51&W@{@8HiTjC?Q`bI6up1Kl;p=E$7A!h z*!m=4^Zn6R69Ag&sSuFR{D=P9H?aV^OgpDl|899<+|L~Ggv23iDc zF8i$h#pBP*954_(+Sk_?$}lrCv&i7+=qN7rcYSkd$tz#jk>*1Un#y~|!}EipWw*mQ zznYZ5@)Z9!Vbo@YePpr=VVLu8!+po@R|8J(%+AcbQq(JZ?U&Kt->;{qmzbD1fexz( zjJkJ^e}O*|pFUmN-0JRrv^h~eNP=Ars;jH69-3ReUiftE0X&vVF(6K>BZ~llc_`zFA-SOvE4X;-HqShkcnb3K5=L3sL%R}7{yU4NW z%$u<}+p)8#(eB#U`mlL7Ub~>HyO}>vcBD>ljcCPk25xN(+-7s!&GVtB=gDlp-{mXP zTgTR6LnzL(LpE%EQFr~B)yVZ*74mV_XSO#jMpB+XFMU@Tv{^M)RFlWOzAV(uJNOB9 zf3c|7EkWR`J$>KZg6%tWem}AuyOqg(vV)3xMq8RzbwL(1H!h9Q%C4e|uYBf4@TqF6 zd@OqkC5CYLSv?D3~c>4gA!nBThiRO9bEHHF6Qfe(ka4Hl-lGE|gGV^3U* zHC5vHo8;pv!b2MSw z(v|+eqLy)O$=qm;_PS#Uv6pg%*JrAZdM31;ab~-L6fRo4&u3d8FEGPyy2gDhta|45 zqTRsayJNHCjCNw;nlG$w4`yh^UcP*}z^88^zQTR185TV@CI+>2rdUbX3i|AE&`Pe4 zEU7!2!gV?SNWN2x(4*UfeT;?Wb5m2TYw-akeeEUQN9HA5iQV(z^jt$ZP1_mF^Rf2t z>D}Hlou3AeV8169rvuJ+@ZiCiu$LK9r|mN)BvX}8I*-pkVLK;Bi^Vs;O=cF>^%vG{ z&5hI$Dl31tqW9E72pJEiYW+Ptcw?=f|AKql(lA)oF|Qo`eMbfs;h2eBiwfntblcY1 zA$Nz4@8nf=ylYuNoALCb%xd49l9rZMUq0hIG$KyJ>}(&d)6aW|dh=`OQp6Y+^^n&- zp=Mf!p~5r63EE_+Yke**#z1RxjAeee{B-1j z6}nwC;gN=Sjd15!J(}01rW|hHHuR=0th9|huP*1XHn7%S+lw2n@n8P?x6HD*{erQa zO#Avod*Yx~Tg$|oich!eHWu3#7Z>r4{U0Y5`}&NHip#DD{`ITT%(%haOd2c)c#?6r zn97TCT<@Fl;t738`!wsLA(JhAUxRm=)rz*B?n?AK;WBTzsd1(QdszYoN#2CvTG&~6 z3zGNs6cL%Pr}c6-t2Lx&oQfs1#Z+i5Dz5ypST9xs_-12cYqIWI^J;j${Z5$OGjI2C zn`okc(9y=t1=x?eJzj_g+}QCF5fZpMD^4sNzcv`&iF zGVSHwBTH8P*m`vrgtFNhshQ%d9beMTpN{|i+k7!o>n7f$hMI(Yf&Te&*Fa+B}JW#Ny-Xs$kqrerF++-eB%4HmKXAyuh!e zoe$t5oA&KbJQ#fW(k0)b4rVfVOUDhPvmgI(>=6~l27dYsdd8wIXcJ-v0Uk0;@QG}) zF7AJP$jEWeK$>wrSeS_mV~ly*LVM!bXw5N*6A(=jt%5MfGdI@DKH1{;jl%ivr72B0 zf7!@z{W;>2Hf{*vi;#<01_UkFAZ1vo5}~5u%-`>QK?BYCBVya3QQ#SL;52 zMD4wirI~)ao_AloItad%7po2s`EB`Bvt&|&*t_gfj& z(>-SD4p%S)Yj!|Aq({Wp31iZs9Tqb+?`al{sNEWc2m z)h3PEG-FB0!cT)9?VYt?U}7a52Eq$(mT=>>B6lvCiYM}E?OgIfo8^`>Iq=mFG?A|n@oQzVkSVqIll&e6slj207_j^)kHSM|!jf8VWsLbS~rLS1*Lb%76 zaeB1%3QO8InL|fs5X7AiFYsXJaq(iDkL7n}Bg$$(IP&jZf_sV%>?BYs@x)`+J43kZ zCX{Ek^C_)Lh6Q!hM|kdg`dkaff8SHb^;2V4pvZ_e$?V3?C7cyUuS$6i#VbM#TOd`B z&bc~cKaj1g#Oy+Xe`%9gc`Nw5A=wyq(W+>)??`F#{4hK`Y+X`OTU%RIWp?^F;Jex} z8btXaOPC6-pRt~!K{V7k_>3Q*W@9+L7$X~~aEDaic#^~Y>IGfP%Mt0%J=_aebz+N9@WKaJFHLGCm<2Zj#u zau}@*B=q72P#C+El+=9&m^x%>!1KlL6H@VIWwxj_mYl(T9zTBUQ8}w{t@l_SH$n=1=rZEX*9 z->XI#=i~ACUL5}8ghxgfgDMJml9hFGK+aY2#eLQKKi4SVMdYSxEIWwr6~{)LB<*?> zWn|*{en)FI2B~*A%hOj?S399HeX$7AT8+aCyT%c{G~N0&$_KAnG*mzwXlS^X;6pML zJI*rTI#OL(TFU!%wbLH*yM%T-#}L07m%YotWagHE&=mJOmZO6y`h&OGIzlx4_ZIT= zZkun8Zf{zZ$eAWa_lb}XoQ@~ zTkmE2MGc^m1yswy9i^_^u1?O*H36#zlrAujhfV2(OqIbqoJLzcX1feHBdB~3W#a)u z|D3P-ru%n+4U0oC1=dtzy^OA{tpO9~7(B-s4TCKy;c?yLYg}VlE;+TlPC3b%lbt<& zNQQRoTEZk))|umxz^?nYt{3(Jn^%1a4*oaiMlpxl;UOMfiRUsbl@6a47fa7S;k9o$ zc)tO1#_8$l=H_NHxyanr-PyUYf2M6tW-;Jtmbu8F)SIebc+{-W^z_sA39~|efg6fJ z8-jI4y|O=FIq%~zD!L-XHM``OVzUPNNOB+*i-G?`(Xkl8^Q_VEZTo);co-}1`KMhG zOl%i7J;(#>2X9KHaZ5yew_wPqxQt^(;eNDvV%~;NBQuRI|#*Hs7@I{G*+F81 zFin3&v7K@7XHtfEvFBy(%T?&udERejT!+jKMj8ZP)K|g4xsx^8TYCotry_gk4r0)! zY?$f&4L$rX-nnx@WaT5PA;|aG9y;oKa@PG$lHenuasiatYXw@c5x}<7Qt6QQE3=8| zkBB_5<+L}L8<=Y?O#el<1(H$&AH}bxx3|}<@VM^<1liNFOMG74P3sAy_07$ig~r#- z%pNJs-F!PRv*hjL^WyU_GDZ004%q6W~r_1f=2I2-2cS5 z|5u0;B&4D{7?-Zwz2vt!KAveVLZI&l1eTIo->jvbNjWL=ZbAO_r)82imR&8pq z)~`9XXvl{hBwxIJ`?DGwW7-bpinjK`|4?bw?vM=mc{nY|D?JDEQ)_j zefe^hOg_NF8XdM7kupfDAP6y=4{sxQ&;L$o&erd*ImyY%0|VFAW1oNi_2I*Z;<_za z8JWuR^5yUKAvfQy{{3xuHH$x^7Y7=ass6XyH~t$O(U8Ue4|E*tlk`p*+#_@h3H~6; z8N&U{oqld*W#wy*o@&H{2m4!M0dSM$d~72FU0ldtlI7rM{}bB-5+Alzm88t$M+29W z8GZuK`jO(om2m4EE0FoXz|EV_w<4QIRm%pQmp@ci8+n4R$LdDEa(aE=VlyBOWGHrA zfi^ac5>M!f{H-cfNW}GABe=V?rd_&EP!Rdf`1)KOx-{K8Fp$*o%s{X>T*WZ!-uD3>;qT0zsjg zC;W!ImYsb0egm8&kTqOwqubU>i;}^EFgu!L;jT>Dz{?T*2@VEfof${gtv0Etsc|!1 zKSH(9jWMpPiLb;MZPwdStF1*yQfA0GdZ{;W-c$@+8~+p0`00~wg<5!!weEPjn3T&< zMbPFNXo#Sm=zgvK*Szc!H`kVC7V95BW?cRL%HEgkjl)et>biIv6Eadu-@I|#T=QD3 z7)rySFMv+CKUi=2Ws~4yY)gH;3dFaUA`}_UklX@J^;qcFG&U^j`bb%@?)`P-W*h*eK-7)+zxwYhYC2#c0 zm+?EOJ8-2uX6kKphl(Tqd0U;yF2uTVmpD!McTR<6e4fX&f&hdmn<2FNiXiQ#4&U{0V&>+K`}^zHFR+C1dlKDqb=yHReP`~U1hkx3 zF*b^N@SQW#uVw^?9}oRBGBUEhJjcYubd?F@^(Qyv_l?;Y@gE006GiKc^FM$2LY|!k zE(2?rD{=rqUaO!utrOtPcfjt(;@jHVq+Ca4Nu=b|R3+a>XAEG{((7Gg?$PGVf6<+G0%1&npX{{6~LST!;ILcMv6Gb z0g`?&O&sy?zZ}>G2G{m#3nx|3?>3T{?XCv}Fnb}E4KiucIO z5KL3N|CbAm{)5jP%HJGIB>LlLO6gCrWCmDz!}&tfV{N)~{|;LQq`mX?6r;_=7w zlo93Qal|yXdvc+ov^UmW4adRtK`Z+?h#LJ@Z~%1{`~2FSZ18cb^H7J!oVS-3-Z&p({C`J*k3WvD zLlhYEy;3;|kzdNx(sFBY;-dWIe&p5p^{m&K-cuMm0v#Z0M==iY^z>Y(kc{)~wr`b~ z4h;<*RV^qgasm2LT-;tT8`OtM%n!tMp%C#H{ok|NKd&g;vaT*JBBxKQ2i!vtq74;` zL*)0AGh@2dp?Ao=+vy}SIcQ^L0b<4#!B#C;3|Q9uUg5;{XiYVmE+(sbb|W75 z7MLAkzQ?qdnHAo@zxULE!5r(;;-#b2zPIh{H18Z(+f>@- z{5fBH(V#0KAptA}mfyOBdHx#Z(0DXdWfIR?nT?46NRY`ZuYi2{d3v7ce;iNmN13BS z2EaMY-sI8pqHoK}{!X+r%`A4pEjm(_yLb8KTbc9c?Of+~Bcwb#S;*KhxH=ON z0`cFW(%kaewMySV*#T~Wfq{;Wk+pJ&ZNd%a)7&ARH;ne_gG!4x`&`0ZWnN!%Mes?x z9ZSJ|2FPa2;)nlSO92TbKG_41(J8$>-(+T~>eE2q;Xt_W6fk2H=yE`3kj80*+a|9! z&+A1`Oc{3tpEV`B!btFFnC0m2|H(_=O)7>P??SZY!iez(`%+Cfp6Hxh{j8p0W@)J? zEgezKX{$EXaSXA2R?|Q7+w-XLJr&`Ehto&SX|z}{1!x`)cTh434-c1+kT^^hEpsW) zZ{tE)E@6=>?LPs)m&Lfa=Iie%H&sY_ya*P(C#NDK4XF@iio1}o_)g7HJSNTCb~gqu zwk)|ENjvm1Ndu?#)XiNOvNC=cn;1rBmG{LH;}v#(%NFH)jHofI(ipn=F>176ms00) zuxPd@pi4SgkEV|RLEV+hF`((DR~`})LbIIRTb}*<3YKyu3sWJ^@kB;$0ox&;q@)Y` zum@*yCZ_Y!V?fE>7`W{Ux#6DW{{_r2UaL!_4V*|1KZ9f&U|iGJ9HVl}}`v z6`GY_AeHcz+CQr2VgqZ-f~s5ZRR~#pr|>?q1@g?rxQRuk%yUJ5OmmHl5?=|)lB+s@ zNDxWhUVO47Hu&p>?10G9R~)3`!A@?H>i&Y|qFUE_rhHr`HmITY{l zOXn9*r|BYj13fy64Lu@W0sqx8_9{D5n(C>5+hAW2kzq9y-BOe>Pe|9m-?$4CnLvyZ z2#&mR`#z=+rMHx)^9K(+tHvT~a6~+DOw+bQVCQDEV`A<$lKeYK5;tom#l7`0I*Ae; z$|l*d`Kkx^aGv6o+k^cc72Ctfb<^gbotu=n2~A7WHm(=RC!QnT*jYuME{9n9y-e*D zV1md6brqv{4i`*WVt^#?VZb#-By2DDPZK6HSpezd+hIc`OLChJPT}90zMiiX6-q<(N_3wetYcJ-G^IpPI31 z7lO>I;bNaE;JMg2KYjYN;`H*Am6F3TMZ1s<6))f&%2tq~ULe_sht}g_Q)nAk50yeT z2J1Cqs?0A;ZoQ04975y4+w+7@9>SjZzD<afL|9ai;}9d2Eg7ryo&8NHf- zL$A_wMU%f?&6Pg*elH{IGt5u!-Fki#q#BEcy*t=!_(F${j?O62P31A8H4gKsXFED@ z`rzowN4;hSOHeVr+R4O3qdZZtHI2-lx1l9zjJRMIAIoR#cL0hXX zWP@2wCR?t8^r8Of2e(E}{LE$6!@h{cB5ko9(#I9k%Q?0(ZFuQTwM`gyZ|#$fqF~wF zS{Vv=iZ^G3C&MN!3g7Vhb7I1b@*2p`aba)8;%(v-ly+`Uo2w9kYKy2|`bVbKonhcl z7&eOMam0|;fDDBPj(TZan6c*8Us=DBd!6K-+0?m&D|s8^|8wVRwPpi<_KP&l{SGEu z2ZJr+Id%ZLlVeOwEvu-@g{6wQsy05^YlsoU3uVVlN?NIG*B5R%cI@h@Q~tRM#L6jJ zRGp$C@Zs`TpA?pV7pT*yIgFT*Ff#Bge*Q}%wlKjlrO%0cNs(WaGXh^b)sP}~LST)p zt31D|%&oE+kxRQ3k}&^K=F9ZvVsR{E3uCa>^g5O?|7nJtx>y-~2m>^WI3jhMX~wV; zGShnd(#O9wQ9bJ+)4NcJk_?%YdiH3FQI2q(pu#8!E4eh&9}+7{xvOv2zNOwKgk+k-Y!<`brky>Uz>fk zxcl~9Z2aPx-g-%uG+vp^1&?kR4bkJw9E*1D7t%vUpZ?HXf8`_n=srn}_4ZY*gsjP< zSXdPVENTCw@mh%4-Y5Evk6d#6L9eI=|I5vM2AG3Bf~1I!5_#qRRy3u4!DzYl%hepA z7Hk}CXHzQZtIS7m|ZNC zT0P8rcVq&*8zO49q4jfBnns3f(NKoPR9eq#>zWrV?VA;Lo^7p;E0+d48!o*o`=wMs z;>d1i?C}wM$HdU%E&am#$2^SrkKOJn*@`*ram745p84hwV`34S@v-2)@x&IRhlH=c z1q;+GaZTRBRmnK~&&q2#UoT~+#7pNTXc*^R<*6$X3{#VinYdCCSd{ttBTc;rf2BAqXATla`J&Q4m{t8) z;}@RD*|&y;Zqefga?zB|n>r_BwQjEpsWM=u(9mvx^Z7SU(WBoS>V_<1@pT-LqWfh1 z%CZP%n_*s*zboZ54iVVqYs+jK_vrHx_>cMw1TM;oV$3Kw-Y&PxrKDlGGt#gnDOz88 zOwq-bE9WoO!4fV`&gT*)l5HPz_Lux4qm3Y%kK1}UUvA@K{XB~QJR4%d)0y>(p{eXq zv6ynehqk)mxMastnj^1dut%}nYF3!XoqtZd$#)Eci9HEFdK8VO`H8)sO6i#&Tp0h> zx)W*d+HM*2K-5zAo{W*t>C!S~2nwy)<&8})tUUn76ryE!dM$@?hcFuwW;Rs1&U1Gs zVr{6O=X^XJgd5@WR~8ENiHBGR{=e_zpDP57KRrc?rISk`cgHc;oY%zlzg%mjJAu{s zg2P{j5wFd5@H}FCQ=9C_I2R}%&`{YMD1Vfya!kCuG61~BS9ZWLrd;Gxy8tj?Fj)3YA+>C9>;|3S@f z4#ig}y%vG;;NHaqVx9Q?T<79p>*ot6ZZy6Tm~+Wt9E=aHz}&U+@#7vB8nwm+=A@?z z9e(2R3L7`rv(~GRaATZ7x%S&xjnCe=a+enkvz~GXB1;|%$v*Jn9MpsLNE)M*ujbwIh97DYKTws(a=*B z!57KNn@jyxSDAJpl}|}MoL086wyxxXXRV!fT9${0Y}|u_6vf2SfZ((iJH@tS`bjod zv1P{=L&c<^`z{Rwd?O%0UT&vLr>3R`x<4qO3xn{T7r86AS};MUkK_b~$+tfBm`BCK zs}=QSu^Ln#V%1UOpI3xG)9?UAYMi_A>!a0i>hOiysw65@io-AY>gx1q#j{^avbGI} z&fnowVBt$%AN&%e8Yp-Oe68hvf0lu zEJ4JnY42H^RthCK#+Mv+RlIa+`bS;9%bHPon$qjF`#gh~(haJ-uRrSHu{cuWU$?!r zJ~EO*%tN>b3o5-?!g`J~@~AOW&WiQo(uYN@fp?b}R*urvq$xY>Sv~=khJ!p`Iy$gz z8n9*7#dxa9pa8gkd*$Ve@^y#))p)Vi=x z!eH&~ZET^BpmEo(StvIj9$30n79KOJsC&5a@>qtiZ>z{X|Gziw?U$FAt*Yd zaDO{c&_8qf^ll`+-4%iA@PEDba#gv-o4RPDIx0r*O;97nG0d#A1 za(Qlad%bQO)b_ky+}E#P^-|>ZEtnA7OU8x-uj_v_(e-BpiM=7S?;U`e9*>NS{PX9} z`uh4#c_H;aHx=?D)9$sx3USoTb6_{KQmIyr7WY{ivU?JA#-yg2SnNe?uTWS?#307$ zCaKV%8o40b;%{^NCGG|8^2In&=7nhk!qqVin#+0_3Loc$mxdDa|IoeX0*(>fqiumh zmvh=RUW<_L_p}h>ovns1hjYp?V1N@xH*k^E=Nu@aif?h6d~~+xD5s|u6M;}c>GAQp zg9Ks9ZlZ*mf$;p?}TijDLvZb$mqkx2)Q!kT9B&M^L>|9)Hcgs$E@O z5Awirkw@#SgcFV*Kc1q57FEe2t%;s(X%jw1zo2eb?lSx+zvWX$$7q$8qo1D{n(fW=VR;lqgMy06 zl#$lG>sJVQJ!EG0{hR6>H*JO@Yopu@SR|?cJ{<+Vpj_xAMLdf>`EJ{4I&*GKUZ%U7 zC4ov6Q>l(>d*S-s@GXKZ179iL$SNkwow)S4huk{aXOYUy$y?f@(9L0E8=K>KbLeiT z2geY&_S`61=Q?~`)zpW@jXL<5!y}?vr}ImTC8tJ zt%`-UR&57H#pAUGfjCL0#FJ0(`paiYjM0TY9sT~rAQp)eEi~|Vt2$3)v8VPpRfo9} zvqFna*p~_|kHff7zTvSjkS{WFW?)m7j8Ucbfh2c!AI2b#;|Od6x&kO!})w3KJdQE+F*9>fX>yAVwF5 zFI3NL7qt6*I?P702@DrTE=`n=xd<@1mqR7g&|p7e8~kNVOvRzsp`%$^E?B$Moe3Na z%n5|<@`kmAg#}bkY4ewwW(#v)vj1l22WsqP6R!iwCMO zT8E;3e!`(EKo*7#=SqYVurBEb9CXOf?~hTUT(V0k9z4$|Fo^iuJ6+xw|1O*a%zY-NR~H`-tA&OEY3n9kNa$@+0AYMowbV}4`x4-g6!Hmm>&hbLmWlv1GP zUn+`dA8r&asH9xZVGKx-yFuA&`=Q^gP*{2{2Ay}jaByp8ScUvjjT zZ|w8o`2gq!UJS^(1_)PEqp+SH2VDRV)so=UhbbrGaCv*L?FJuVET?bS;c*S0Q}|rz z;K|$Xs1u4N{11(*6onA%+_4{huVY9Y|8q3Qd$?-Wg~yN(l*6iQ4bdSu{?=CE>#U?l zUV{Rq*OeX#Sv9&9-;r#VeR*1~eVMiO7_i2F&dKIb;#o;;Q6ED;NXsEi@E*5dGLY_< z(JW;V1TJ2=U@DIq_7e!Vw6h_>Ke;8OF@#$$%1cIj{dqKBLGH6pvauQ6IY+qBQ5y2k z)jwFA_EExo5#q>)b}EG9cM?${@urDs?8#5PnLqlysNGJaOpPgL4U?o$@6q$6)}Dh9N&#v`wMaj_>#<$R8K zA5Msu`=#!UWVCv@q3GJ*T!x=er`lfYuN!wpf;Ac!o*A7ZHudfy*JP)=FJ(=+`%yWF z^w(Q>d}@SRG-+;5Pgi#ypNlN&miH7n+cMcm63(m#>n3VEc#H%0ue*Ey~4rsunsT`%){V}3`2S^ zZa>e~GP=DynTiI1&jDweo<_KDtz~*UGeyVmJF_C~;Am(b4PhSPqQlcs-r_SU-;rVlm*dG6$g2sWh1n@*I3sH=<=NN7efs0e;29UqzppgOG&8?>yoIrJsGpJ zev^}v;E;LwyMs>vj33kTZjmOmJe=W^ByzlOvWyO&2&6 z8UQ<*Z&EzHBzv$OY2D3XK=@_hE!O>Lrr--5me`2N$gD!Fb8&UOeo;ASdvh5YH3HU; z1j}DZA)bFYJ94VXO7Z)*k0GZZ<_+r@O;EKe+*`j7s5v$^2DUUXFaU7fJAo)4=?OZO zrx`zN@~Y=@B8Tz@4Ox|@q#P|@hTgzYblZYv0U8=$@nD0umx|HkmoJShSdkB^&KVY8 zTNNFeEi8>#-*l0QBJaoLkv$C_aX+CG1!6nQdi#&kwuGGAsZdjMb9p5tbpHF@>23t- z^A!En^TbuvlgI_0ipaW6k}K>7beUW;H-9pt`sMTI%_X!L9UdKpxNdC0fvD@=!1Zq& zOkh7)&erf``;X##N__XITK)Tt#6L zfM$yapM^3E4h{mU-SlNauBCJ1U-;2Cn@>CoSQu$&cykarHdPV%`}c3C4=X|4Sr1)% z%%JK$>N;GtG~UM8n?$JcacyA*f;13 z9U2^zQ&M75H68u12f39Pfa2^W_aWAgmcMWP3uvnfx#9)wE44K>!%mV=Z_cPvMrh9d zz%pN>+2u}>l79FjeGB@qRno8@MOo12>gdMQ0K=n@!7YS7y6&GlvAWWXCAv$dYJ*%f?F zXV$<-%XZFFEI{CjawyD>irePVZ@ipp9bc)Btc5@S({e9|GwZMh zXF56cmtuyeZeK<+F9&G>rM-AWoAldkvg?SaWSHO~Wq&O3uE8x?mklYE$~`Lg@^RQh z&pD9a`!PWvFJ+SM2}ejEV&Gp5L27wSbPZ;Xv8WD$vbbpy5 zr5_&7szzMSk+2=p>HV{C+2=bWhu*@#qNBpGIW^C!Exo9a8s_|9ou!YbriquIk7=b0 zMp?x^GNj79xYJsmy*TJ@Wp3VstJmUC%ouht3CCK@9SqR0&g@5xjg3i3EWKB0(mwA$ zoOg=FOTKyfNju$|-B|Tc{B1~Y`k#6ye`(t9ekM?QHYt8_I>$sFy;7p&{JtUDtRpYa6#^%T4kyP7!D`X|ebWNBLNum3tJwEqCuy8vp8Zf}kPbfS5ub_HK_r^VB+ z-7-5;Es-w4wwv1?z6@C5bcT8rR>jXn!eN31iRfL)9p)IgbYpGuPO`81-=mU5Lj!&! za6+mAygyHb3XzXWA_f}YVK0jz{E~<8m8i|WFOF^X5LvfucjuL<9`b;7Y&L(^Mzc-C zEaJhBr3RiTBiX=6jXB+8B3>mvuv3=orx{SE>A$PJVQ_AdZ5O~rpiCta?noYeg@+0lD^AGZl@BlCGYTZ3rP<>&y5o1zDW{^;NmiiPToFUA9P1OW1@QB+deo<@65mC6O%M#*y8Nas{*=#o?;NF-+-^h4_QhQ04H zq~0EES0Q?a1m`LY8j3w_e|b7eosERV9RU(G8nj;MCauWN5_|Db;__t{xB zQiuV;Uzq<&ncazkle*T0CF@f~= zCiI9xV=Tm>mX;Q9VRUoGY62ZQYgv5<&>J+r#{zmi#x&eE`?4sfE$*<|HV;2{z@n4p zqtO@wgSCsxmya_~A!>joA~8(IZAMO`RO7#$EQD2hRc=o0qer>mgG7Y#;q9eM*E=e% zM^jF9@BoC10tiRE*Er#&ai!6hD*JZYvx&zFBHy$=l4Z>9{iz8l4+ZXVdSl#IfkUG!Q0wN?_?-t zP{?Ck8-qeW(uK7LHW0+SomoweM~O+uwJJWbx$CVa3ZET*1+`V1%82P-y}zHaPa2`i zPP#!IdlB`A+Y}dQS^2k_0OV~RmIj7|cDbiLncj`_wQPAojd9W5gM4KJRNPnvY(U_} z&%>7srR!9LqH`4t#PL=mQkPoJ!ZD8ptd&KD1*EvQoWDKg-ud7BXh2}^@Ht(j`17JD zEl*VY1By$IS}M#B1Tr-E2fMFD>sAd*MSH6rZ>qp~y8k zmh2+%_j17`k(U6vsK@5wd_u0|8|1zg zQ8C=(a|ZfGLPB=;UX9pkIXd>Ajw7rU36+q@%V*%7-|v1o9X)3IZFtjs{q5}NL*eaH ztQ|U2D)*u2^jwW=O+4!E!LslXyE232YnOum?W)Z_qPU}}VpVS2zW#XUuYbtgDTZPp z2L1xdx6Q10ZVpYv)!EQXnjC*eFC$40RSh@lxN9+v7lsp`t~s6FwS{}ke2AXlrW#M)Hu{us#yMAEq zrq<-|zMIzTL)qSg2cOK5G(dfhiuYMhn>cESppPB3FM)I5+^Jdk3U$7l2? zt~g#+tDA+gpKqvBsy3p%&+7diB+=sukqWs5h6qzDR$SWPHzHK$cz=DH6u09LGz)PQ)PCUf=hzfCt`cB9Fc3+LEyGs0!_a|Z1X4yQ?3rBmyfhbY9lNN1bge2Zkw%eKcu7N)-roo~sa7-+Y$(IF( z&6-66?sQNr%e&_0(4m&9rA7le_)?rOX7GuTY1nGSc>xJ*tuQqtK-*TBey;J^xxIQM zcuzSGyVJG(wD^3k1k4R9K>~}rG*EZctLFiX;3FKD;0`%*k@Qj1u1J!2=!W?CE+h$s z>U`XJmO1=jpF?821x?p)&#O=OAllFbq@0aabj)yE^LQPznvc*Pc-C;l`?TDCgeDwN zgC%}bli+1&UR^a?qk{y~L-#`|cYChFp=j^O<1;q9lr^C@Db9~YkJNVw8@DS=;`h^m z9x|So0jnT)vm?Xwz9qWZKtbXx;4`7)Gv(=d>VP%h;j~9^*~go><>wAeuox|S{EqJa zjZHBCdfBv7ad_PD7c;0dbvwX;N;})>x$2&OMV-8Sq`N)^B%PQBo!N0GpQ*E|dEYFb z92;mExDk=zlOdfH!{T$$>hNCf3Z1OuqY3>tMv$(OaldpM~E z)d@VGK$eBwM;5?ew8IN59?Gup_Bd55BFf_x(&({ZvL{P) zQu*M6Y;WI!XE6=xpr&9oz3Hq810ytB^h1B=W!M)68F0h|adA!?W)tIh%)}y~%Q{&6 zLJlS0v07bR)UeQ4w;sEAKU|EnP3y<5isOc>_5zI0D94+>l)dwt89{zRK{Bqa$LgUh z`rR=Bn%bblNIAXq3Gu-!oWX?ohaR^6c4A45bPik_D~_JvxtKeA`}Z@`y07~Ygy#d7 z5fhwB>P{ve8WYFA$hP_Y>~cToXmw6|LDwy;8n@0`wl|86lV}6=?)Va@1>4}HK1Xg3%n?oeJe$2KFbEF*r~lVu zFi`H~{m1;4#Z0nZATQirNZlIX*PCRkayo zm@#Pc@g3@alJyBn93j;7mUTf2*fFPZkfKoP=t`^4YKdD5vFL}ZCq;Q@4E@~PxI+aK zZiX^I1|;mbD1LiM?{P-E$ib(B?40cCcg&sjXpl@eM;rxhz)elLZ3CmD<>}RfDw!<2 zFI~#7qtLc#!n2bKhIPI=;;7oZkYAg({fj={-humzE>e{Zr`Rq`{H&0gcyCvkx+<-%o{%@2gkP z9QVqMB&(5PtXMJB@dyLdQQdQygu6L3Jkz`<$w5y&=WDOs6c@xW@PesfN1v0P=q1cL zus&m7sqU=T5582ae`yYtd2PRBiz3Q8(787Ly!K#gMXg5LRxmpZj@yKWtbCaz>@Y80 zKy1t<)nS`;AY;|+WFK@GWU^$4D|6nG?crQ?f>tON;CCJZdvg^On9@q2dW3lwx0NUR zPN-EzAfU*kqZT-yGo9ouvy+#EIYL3JLLR_r?QvD3F)@7+>fdr~j2@}=v4ZK>=pOx- zLn%{kN%fEuIt|4DEP_?xOd$)CGcFdIU5W>ug+f?wR}qJPJMdEku`5dM%o zKoZ0+W?a-yil##Tae|S=2^QJtqIA&|o+qh{&?p0uxKuNv2gA(ZDfpjjbh}RC=_6<1 z*aGrCf`%NNDwudC)@oO-Lg)T2H%Wd;Xj*`$)N{1boDtE0#2-<1GHv0QXRI%sSdgIQ zE9oKosG1)vqrY?75Z(tzh5zxQ>XulKqLZX%Cq&MjL7+{K^hhz%ih?QjUJx3P`>?uZ zLUZ^Ryjo0YbP4%P2azlHzSCts%Dbqq&^)j=7Y26%`)_shD}!kvg+Mgmg6FR}Vv~dt zL{1&f-a!AKLasa>%I@vo3MFF=AzP6wg^)E%X%vMlkv-X!W#qADZV&ZT_Q+0)HQ6$f zk+M{xY-LHq2qEi?QrQOcUeojbKJWX_`+5KI;dalNbFOop>s-tC`f@@-_>XICA?fCm z(Ic#K&e`{=bK!Cs1ii?cSQsnjy;B3_!@WBI$zwv1TjJow73$a8)%qRG{@0#=8*e!t zcoP~=ZG_~SL`9v`{u_7QZ1yjJ)RF&Y<7v2J53bh8JuCMgks|IzEhm#TPrCwK4vf0+mF z8>_yF*M1-y;Uiu;h;NDQmE7ze2Y+UISF$la6_m3FfG$CN(0>$oY-A{Dg8G2sdy2n! zHgsWZ>_heVhnLVs|A?FXu=d(NCs^3qF>woMvC&nKVk<<)zj#S?`K%&oxULq=s!#vN z`aDp-ZUip91V2%OUu!Pt`EuF5Dc=KGy|@_-x!dx!5$S$Zme~pgxpmk{^AxY*GuAYAaLnzrYDRvqJBTZ06Y%BwbJ*k|j@S3VlhzVQm<@V9J`eo}S^97UC-j7P zTS766*>S@G-RVv4H-)`G3P7TG)-EFZ5kns{X+jOur%;3hR_eq~ZAMW5L9RmputD@B z8#u*gUvu+h0O$yS>Sy-+EN!sup!I0GLVF_w$qNKp2}-CUUn6)&lN_QU%}Ku1%P!;nAKg7ag6GC9E4h*JR8p(R!W$@= z{^A$LbrS8h^8BKYTKTTzqGuPn_3Pedl(Tr~Fz|u^&cVeDY=!3sLmTRm4o+}BPqm5Kv`Z7x&WMKW zM!{#jd)I|-ZM7(?{2We@K93ePio5cM;0kN;1IFuC`4frqsvM9si?zgKJn)rmAO_jrQocym8BV$FMO1eD|C zKVyj-0Gstef4x^TXi@_25|!ZTBu>O`bP^*9mtATWj-1~HLS_~XnUU#ybaqTuJn2Vf zvt#i28iVx@ZkfA~C=r;>HC*vBlVdQ+8d6^GY<5D=I&g!C-VjP-Q<}PZpq737*1{{* z5wl*m;M3x{+^_^_(h7sTO-9JsX-NS30W?%no)zPaie5nJ;j)h-bC85fhR>nBMtUc; z{aBTuc74Q^+!L@O!+=xPncrH~71<1k!jxCW6v=NUG`l+mdV4_x%FH2!_gu4Ew|38e zYBfFr1D9gKIz^XHP}}E=113WTFM*^GZx|#S<5QVatn5qf^tdVimJxWU)Gwk8qzMC~0Hj#zXvO5CH8h+c|T26W$VVdz4yxZo- zN?%QR5^CR1ni&1mv&MHWO4n^iorQd>&(0AQ1!w|ZJc{K3&y{nvZMuQxxro$ytiZNA`L>F%-`v)c>i=|le2zr0K82Wn8rDrSv2 z9kNxx9OX+lHs?$8P|b4weN#AYp(yS$A*m!7i8_Cfc=fn~kn?JAIy=X7O;0dOQSawc zvG=pZT(}gog{5i&4hw9hx3xz$L9wX*RI<&8_tDs z%zsQ6Zf@(=eLr9HZrZa14c4I|&BnXQS)SHTO`(#7!`ieL8s)I=3zt9P6t8!6-R#Ra z+!T^g`9!zqNp(e>mEM~09xfsKw#bM5_ylEv0Ci6mgs3b@-KemN&7XN!?m5kQ!?`HO zt=fF~V_-7rNPQ&M1G#9zMxFQDI@_mxEek6dx~0$f0%tq-PiTLCdZu~I`vEP3Z{k;N zZ91)N53H3wdOiNCfD&#CYnLKcWt4_(R<1v*;wPyqpQ&;ExEGL{?rmP zPo3Xuzk<;2%Uv=O=(8VO)4nfN1_K&URiyb4;2CU#*|0|o5#TGT*cFAJQUtVD&f{M1`VxenF2WFgL*C=m2H`5XqvOOjX>-D>}tUH<-1hW)$D zdDYGB2$`ux=c0V_U_qRvd0aZgn6U-{TxR1-;rMsU^63^E{rDJhPGn4tjoKpP;M7$8 zm7y+Qxyf+~Q7`ZnYTwsPD6VA|bBA^y++=n+c((mUUhFR9+y#2w!nVvyhibXdn<&cP zeNxWZ)+75jZ&XK{7lPM_np zb0>1Wg<1KX4)~)fOm#udpC<14`#3Ar?kQ>8l;hYykdV`5n2>gT7{Zr_Tt6mY|GWq$ zX)i^*8c|%^hMr^`PiP0Izj(L0W-Rh$I}{xevQ|r;{kO_T@af|L)1L&vTP13z$4mw@ zOmB#Bz_h@hUrfp{dmI2@Jzz?yBkD>c%_cjk1g@GJL)-0H?2RlF(X9H zmc023lx0CAYTJKKgwtHKI%;tShFmcV@O*Cj_cdQjn$~7H+ySh~nQtqXn}YyJ4}@aJ!gmk1s!uuo?yw27!N;J%T47@A3#}TCFRZ@ z&@D^VMYmoo@W!4g!{}K=;81wkciElRDPR)Zr`%u61$IWCY4!3$3`EjtDN|LRiU zoK~;cc7$6*l6v_R*t?x~cvg<)>ws(MU`QUk0V3d5ZHYY0kjcZ{WE+T#ktf@J5vw#T z&6yDEn6X9zih)qEoVP-`%m_Yz;Yc)X7h`Daq_IXH2qdD?3fm%!GC^mbJdP(;aWd@j z4I!K}%aALASl{DW88d>h=k)`)au{PvKYh=9ma$XoN?*m~7%x`{;<%C+yMEN|jgAsS z*T5he><1kyKir}tXaW2)&02jEVyuiAeaank3SzAM*3v0;CtHl3G{j00o(; zh6yxFNm4`hoAhZUYUi1zNCC4XkO5nib`FuOtPn)uJg>mwD+U$~%1Hp}vML(@QZ0oH zNb%GGZ|!CJp8`hMeg16-Umx_Nr#qfF&PENn9u7+Or6& ztTFf|ajbd0!@U}ADFivhfH_AYGq}`!;ru8$%6qL>HIlv+iSK~+aw?TdnETr(rscti zA02T0bl@i;-;H_|sCi)Lh@X0F{zk=K$qZWoNur{2iWE?pt{sL>c7NemNs~Sx4g;Dd z;3&g4jm`!EoN_v27t3UzF*hJ8McUTJsLCDD%qvr8Qlt_m08DhKfjhGj9q>u(n1a8o zt*cNWGN#) zEP!WFF<&5fBsu>5(96M8mH;#afWnc9g#^*ku%m}AKlWV zX=AVf(AV(n0F9z7h)Fl+?3@TRzU2V#k2PMyiReWvF97Hds+RQ4MYL>S4md~}7xKq= z4P#^^GAylccN|J(UZH)W1dF5ikkC*;>_-5|d2KT;vLFHX*)k=^eE%-_z0AV)?U>l+ zsk;MX${mNo$&2kpP{Q2ep57{iYw}Msp86O9 zglWSRDupsd`wVN(_qy^>=0ZBGF0ekg;(GGhG6jgW?JpTAp=lkme+Oo{?4|MR@c`1%@&?nA zJ}*^6dX|0J0JJGgsB^R)5yUVuaiDf>xT?Wn5-AKiG6-?evJR$fufBY70&Sql*LM;m zT4Y~xv&I}(3wz<90OWax8$>eq8>K8z)pYauvN~kP1GAnEkQgz=+e-K9ti zn1{(pDU-e{B%($lxC6R&)bHQFKN(##Q-~r${w*LNxxx|`7}z@-wA5oQmj=t$oX_*5 znN`Z=<;|_GhW_eZ^8~oUF)h#R;>FRX9!30)=A(kR9XkzDqyTH{o&6SfEg*oq4c9R8 zWpq@W0(=q?FP+K;gi-A$gYyaLYV@BydhjGyMG%wS<*{`vj8u~(rjvb5PJ3XcsOFWj zIiLGeDYKw08qfTlTFXEd*($zMcaLbf+rCK&}EGv^HDMw{92!XmsHDwjKs9lp4|o zpwo+{nJx-QQV|zH46AFM`#U>_C3`p$71j}JOYUm@FCQ#O8Ks=n9q_CB>D@R?VesDq zcZlnzS}Fn6+*q5wPpSh{hL$!GDyRed%3xj>W%o#a8Wle zm0oht|I=rXtvc@5v18=X(VlS9-UP#jk;Y%SaH7O~AyEo>-8dVTX2A+&#ATIIH<}^^ zBptSWVa0Y8i4^M!YXCw3sqwSAI?oXe9lfPUfGPOZ!9!`9TZ)uW-aeDQf`S6zOLX5< z0v04a`o>lKG*Gpmb#?0N&j#lK)GRkzT~l3+o7K=ku0p}V<@3KSB<~cK_Q7_*ppCuna~FNAD=%1AR1C#n(+bJbW6F9__5Fr zP%G6C!_qYpfom*U?+}v891@ibd*x{`K@yHb{}_Uw07`IeU;wKbiGLuDfu<$3uoNH> zjThr$jR97?rY3q5ebc{tehW+}u-kMW8qi4mx!V)24aKI7-YaT9_c9ULAdp}>o#FA<}vU|92Ar&VE$11yg18yH1A4VC{fy!#V zjIM((T|mzuQU(`KIo!_;g2*q1UJsPnfQ9_%<<@7RQsC}X9R6$OW4TlIiz}=?aBdoW z`@o`lt$P<)g#Dg7U+{5tw&Z@k4Divw?ykKn-o)$aO*3|906I46Hs+EMhx6VVA_@(x zh(KEL>?7v`i4$0=cR0G6f%=8wqoF*OlQrfFX6vz{4%nLY*%JE3v|j4G&9)~JP+`l0 zP7An_bJYF)@b{#Qq-~m*F5<$;Oqt%miK+J%^@U?saCD4`C diff --git a/octave/snr_curves_plot.m b/octave/snr_curves_plot.m index aa28224b0..8a2e23436 100644 --- a/octave/snr_curves_plot.m +++ b/octave/snr_curves_plot.m @@ -58,10 +58,10 @@ function snrest_snr_screen(source, channel) snr_scatter(source, 'datac0', channel,'b+-') snr_scatter(source, 'datac1', channel,'g+-') snr_scatter(source, 'datac3', channel,'r+-') - snr_scatter(source, 'datac4', channel,'r+-') - snr_scatter(source, 'datac13', channel,'r+-') + snr_scatter(source, 'datac4', channel,'c+-') + snr_scatter(source, 'datac13', channel,'m+-') xlabel('SNR (dB)'); ylabel('SNRest (dB)'); grid('minor'); - axis([-5 12 -5 12]); + axis([-12 12 -12 12]); a = axis; plot([a(1) a(2)],[a(1) a(2)],'bk-'); hold off; grid; From 652177364cfdecfd4dd73808d97941c733e8f1e1 Mon Sep 17 00:00:00 2001 From: drowe67 <45574645+drowe67@users.noreply.github.com> Date: Wed, 3 May 2023 08:38:17 +0930 Subject: [PATCH 50/52] Update README_data.md --- README_data.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README_data.md b/README_data.md index 4bf467408..9bdf91ad8 100644 --- a/README_data.md +++ b/README_data.md @@ -145,7 +145,7 @@ These modes use an OFDM modem with powerful LDPC codes and are designed for send | DATAC1 | 1700 | 980 | 510 | (8192,4096) | 4.18 | 92/100 at 5dB | Forward link data (medium SNR) | | DATAC3 | 500 | 321 | 126 | (2048,1024) | 3.19 | 74/100 at 0dB | Forward link data (low SNR) | | DATAC4 | 250 | 87 | 56 | (1472,448) | 5.17 | 90/100 at -4dB | Forward link data (low SNR) | -| DATAC13 | 200 | 64 | 126 | (384,128) | 2.0 | 90/100 at -4dB | Reverse link ACK packets (low SNR) | +| DATAC13 | 200 | 64 | 14 | (384,128) | 2.0 | 90/100 at -4dB | Reverse link ACK packets (low SNR) | Notes: 1. 16 bits (2 bytes) per frame are reserved for a 16 bit CRC, e.g. for `datac3` we have 128 byte frames, and 128-2=126 bytes/frame of payload data. From 605edcc98ad66d2b7f6ea6197e213627b0da7d34 Mon Sep 17 00:00:00 2001 From: drowe67 <45574645+drowe67@users.noreply.github.com> Date: Wed, 3 May 2023 08:41:14 +0930 Subject: [PATCH 51/52] Update README_data.md --- README_data.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README_data.md b/README_data.md index 9bdf91ad8..543398831 100644 --- a/README_data.md +++ b/README_data.md @@ -259,6 +259,8 @@ The following plots illustrate the SNR estimates versus actual channel SNR with 1. Examples in the [ctests](CMakeLists.txt) (look for "FreeDV API raw data") 1. [Codec 2 HF Data Modes Part 1 blog post](http://www.rowetel.com/?p=7167) 1. [HF Data Acquisition](https://github.com/drowe67/codec2/pull/171) GitHub Pull Request +1. [datac4 & datac13](https://github.com/drowe67/codec2/pull/364) GitHub Pull Request +1. [FreeDATA](https://freedata.app/) uses these modems # VHF Packet Data Channel From 30f2a61cebe31c90daea1a50ecfcb7ecfa82e59e Mon Sep 17 00:00:00 2001 From: drowe67 Date: Thu, 4 May 2023 06:14:28 +0930 Subject: [PATCH 52/52] ctest for quisk filter --- CMakeLists.txt | 12 ++++++++++++ octave/diff_fft_mag.m | 3 +++ 2 files changed, 15 insertions(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 3ca18e95a..c521a7edd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -355,6 +355,18 @@ endif() ") set_tests_properties(test_fdmdv_48to8 PROPERTIES PASS_REGULAR_EXPRESSION "PASS") + # Basic sanity check of Quisk complex band pass filter. Note complex filtering cosw(wn) gives + # just the +ve freq exp(jwn) so output power is 0.5 input power + add_test(NAME test_quisk_filter + COMMAND sh -c "cd ${CMAKE_CURRENT_SOURCE_DIR}/octave; + ${CMAKE_CURRENT_BINARY_DIR}/misc/mksine in.raw 1500 1; + cat in.raw | ${CMAKE_CURRENT_BINARY_DIR}/unittest/tquisk_filter | + sox -t .s16 -r 8000 -c 1 - -t .s16 out.raw vol 2; + cd ${CMAKE_CURRENT_SOURCE_DIR}/octave; + DISPLAY=\"\" echo \"diff_fft_mag('in.raw','out.raw'); quit;\" | octave-cli -qf + ") + set_tests_properties(test_quisk_filter PROPERTIES PASS_REGULAR_EXPRESSION "PASS") + add_test(NAME test_CML_ldpcut COMMAND sh -c "cd ${CMAKE_CURRENT_SOURCE_DIR}/octave; CTEST_SINGLE=1 octave-cli -qf ldpcut.m") set_tests_properties(test_CML_ldpcut PROPERTIES PASS_REGULAR_EXPRESSION "Nerr: 0") diff --git a/octave/diff_fft_mag.m b/octave/diff_fft_mag.m index 9bae333da..005be70e1 100644 --- a/octave/diff_fft_mag.m +++ b/octave/diff_fft_mag.m @@ -5,6 +5,9 @@ function diff_fft_mag(filename1, filename2, threshdB = -40, ignore=1000) s1 = s1(ignore:end); s2 = load_raw(filename2)'; s2 = s2(ignore:end); + + len = min([length(s1) length(s2)]); + s1 = s1(1:len); s2 = s2(1:len); S1 = abs(fft(s1.*hanning(length(s1))')); S2 = abs(fft(s2.*hanning(length(s2))'));