forked from g0orx/wdsp
-
Notifications
You must be signed in to change notification settings - Fork 0
/
TXA.c
924 lines (862 loc) · 35.8 KB
/
TXA.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
/* TXA.c
This file is part of a program that implements a Software-Defined Radio.
Copyright (C) 2013, 2014, 2016, 2017 Warren Pratt, NR0V
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
The author can be reached by email at
*/
#include "comm.h"
void create_txa (int channel)
{
txa[channel].mode = TXA_LSB;
txa[channel].f_low = -5000.0;
txa[channel].f_high = - 100.0;
txa[channel].inbuff = (double *) malloc0 (1 * ch[channel].dsp_insize * sizeof (complex));
txa[channel].outbuff = (double *) malloc0 (1 * ch[channel].dsp_outsize * sizeof (complex));
txa[channel].midbuff = (double *) malloc0 (2 * ch[channel].dsp_size * sizeof (complex));
txa[channel].rsmpin.p = create_resample (
0, // run - will be turned on below if needed
ch[channel].dsp_insize, // input buffer size
txa[channel].inbuff, // pointer to input buffer
txa[channel].midbuff, // pointer to output buffer
ch[channel].in_rate, // input sample rate
ch[channel].dsp_rate, // output sample rate
0.0, // select cutoff automatically
0, // select ncoef automatically
1.0); // gain
txa[channel].gen0.p = create_gen (
0, // run
ch[channel].dsp_size, // buffer size
txa[channel].midbuff, // input buffer
txa[channel].midbuff, // output buffer
ch[channel].dsp_rate, // sample rate
2); // mode
txa[channel].panel.p = create_panel (
channel, // channel number
1, // run
ch[channel].dsp_size, // size
txa[channel].midbuff, // pointer to input buffer
txa[channel].midbuff, // pointer to output buffer
1.0, // gain1
1.0, // gain2I
1.0, // gain2Q
2, // 1 to use Q, 2 to use I for input
0); // 0, no copy
txa[channel].phrot.p = create_phrot (
0, // run
ch[channel].dsp_size, // size
txa[channel].midbuff, // input buffer
txa[channel].midbuff, // output buffer
ch[channel].dsp_rate, // samplerate
338.0, // 1/2 of phase frequency
8); // number of stages
txa[channel].micmeter.p = create_meter (
1, // run
0, // optional pointer to another 'run'
ch[channel].dsp_size, // size
txa[channel].midbuff, // pointer to buffer
ch[channel].dsp_rate, // samplerate
0.100, // averaging time constant
0.100, // peak decay time constant
txa[channel].meter, // result vector
txa[channel].pmtupdate, // locks for meter access
TXA_MIC_AV, // index for average value
TXA_MIC_PK, // index for peak value
-1, // index for gain value
0); // pointer for gain computation
txa[channel].amsq.p = create_amsq (
0, // run
ch[channel].dsp_size, // size
txa[channel].midbuff, // input buffer
txa[channel].midbuff, // output buffer
txa[channel].midbuff, // trigger buffer
ch[channel].dsp_rate, // sample rate
0.010, // time constant for averaging signal
0.004, // up-slew time
0.004, // down-slew time
0.180, // signal level to initiate tail
0.200, // signal level to initiate unmute
0.000, // minimum tail length
0.025, // maximum tail length
0.200); // muted gain
{
double default_F[11] = {0.0, 32.0, 63.0, 125.0, 250.0, 500.0, 1000.0, 2000.0, 4000.0, 8000.0, 16000.0};
double default_G[11] = {0.0, -12.0, -12.0, -12.0, -1.0, +1.0, +4.0, +9.0, +12.0, -10.0, -10.0};
//double default_G[11] = {0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0};
txa[channel].eqp.p = create_eqp (
0, // run - OFF by default
ch[channel].dsp_size, // size
2048, // number of filter coefficients
0, // minimum phase flag
txa[channel].midbuff, // pointer to input buffer
txa[channel].midbuff, // pointer to output buffer
10, // nfreqs
default_F, // vector of frequencies
default_G, // vector of gain values
0, // cutoff mode
0, // wintype
ch[channel].dsp_rate); // samplerate
}
txa[channel].eqmeter.p = create_meter (
1, // run
&(txa[channel].eqp.p->run), // pointer to eqp 'run'
ch[channel].dsp_size, // size
txa[channel].midbuff, // pointer to buffer
ch[channel].dsp_rate, // samplerate
0.100, // averaging time constant
0.100, // peak decay time constant
txa[channel].meter, // result vector
txa[channel].pmtupdate, // locks for meter access
TXA_EQ_AV, // index for average value
TXA_EQ_PK, // index for peak value
-1, // index for gain value
0); // pointer for gain computation
txa[channel].preemph.p = create_emphp (
0, // run
1, // position
ch[channel].dsp_size, // size
2048, // number of filter coefficients
0, // minimum phase flag
txa[channel].midbuff, // input buffer
txa[channel].midbuff, // output buffer,
ch[channel].dsp_rate, // sample rate
0, // pre-emphasis type
300.0, // f_low
3000.0); // f_high
txa[channel].leveler.p = create_wcpagc (
0, // run - OFF by default
5, // mode
0, // 0 for max(I,Q), 1 for envelope
txa[channel].midbuff, // input buff pointer
txa[channel].midbuff, // output buff pointer
ch[channel].dsp_size, // io_buffsize
ch[channel].dsp_rate, // sample rate
0.001, // tau_attack
0.500, // tau_decay
6, // n_tau
1.778, // max_gain
1.0, // var_gain
1.0, // fixed_gain
1.0, // max_input
1.05, // out_targ
0.250, // tau_fast_backaverage
0.005, // tau_fast_decay
5.0, // pop_ratio
0, // hang_enable
0.500, // tau_hang_backmult
0.500, // hangtime
2.000, // hang_thresh
0.100); // tau_hang_decay
txa[channel].lvlrmeter.p = create_meter (
1, // run
&(txa[channel].leveler.p->run), // pointer to leveler 'run'
ch[channel].dsp_size, // size
txa[channel].midbuff, // pointer to buffer
ch[channel].dsp_rate, // samplerate
0.100, // averaging time constant
0.100, // peak decay time constant
txa[channel].meter, // result vector
txa[channel].pmtupdate, // locks for meter access
TXA_LVLR_AV, // index for average value
TXA_LVLR_PK, // index for peak value
TXA_LVLR_GAIN, // index for gain value
&txa[channel].leveler.p->gain); // pointer for gain computation
{
double default_F[5] = {200.0, 1000.0, 2000.0, 3000.0, 4000.0};
double default_G[5] = {0.0, 5.0, 10.0, 10.0, 5.0};
double default_E[5] = {7.0, 7.0, 7.0, 7.0, 7.0};
txa[channel].cfcomp.p = create_cfcomp (
0, // run
0, // position
0, // post-equalizer run
ch[channel].dsp_size, // size
txa[channel].midbuff, // input buffer
txa[channel].midbuff, // output buffer
2048, // fft size
4, // overlap
ch[channel].dsp_rate, // samplerate
1, // window type
0, // compression method
5, // nfreqs
0.0, // pre-compression
0.0, // pre-postequalization
default_F, // frequency array
default_G, // compression array
default_E, // eq array
0.25); // metering time constant
}
txa[channel].cfcmeter.p = create_meter (
1, // run
&(txa[channel].cfcomp.p->run), // pointer to eqp 'run'
ch[channel].dsp_size, // size
txa[channel].midbuff, // pointer to buffer
ch[channel].dsp_rate, // samplerate
0.100, // averaging time constant
0.100, // peak decay time constant
txa[channel].meter, // result vector
txa[channel].pmtupdate, // locks for meter access
TXA_CFC_AV, // index for average value
TXA_CFC_PK, // index for peak value
TXA_CFC_GAIN, // index for gain value
&txa[channel].cfcomp.p->gain); // pointer for gain computation
txa[channel].bp0.p = create_bandpass (
1, // always runs
0, // position
ch[channel].dsp_size, // size
2048, // number of coefficients
0, // flag for minimum phase
txa[channel].midbuff, // pointer to input buffer
txa[channel].midbuff, // pointer to output buffer
txa[channel].f_low, // low freq cutoff
txa[channel].f_high, // high freq cutoff
ch[channel].dsp_rate, // samplerate
1, // wintype
2.0); // gain
txa[channel].compressor.p = create_compressor (
0, // run - OFF by default
ch[channel].dsp_size, // size
txa[channel].midbuff, // pointer to input buffer
txa[channel].midbuff, // pointer to output buffer
3.0); // gain
txa[channel].bp1.p = create_bandpass (
0, // ONLY RUNS WHEN COMPRESSOR IS USED
0, // position
ch[channel].dsp_size, // size
2048, // number of coefficients
0, // flag for minimum phase
txa[channel].midbuff, // pointer to input buffer
txa[channel].midbuff, // pointer to output buffer
txa[channel].f_low, // low freq cutoff
txa[channel].f_high, // high freq cutoff
ch[channel].dsp_rate, // samplerate
1, // wintype
2.0); // gain
txa[channel].osctrl.p = create_osctrl (
0, // run
ch[channel].dsp_size, // size
txa[channel].midbuff, // input buffer
txa[channel].midbuff, // output buffer
ch[channel].dsp_rate, // sample rate
1.95); // gain for clippings
txa[channel].bp2.p = create_bandpass (
0, // ONLY RUNS WHEN COMPRESSOR IS USED
0, // position
ch[channel].dsp_size, // size
2048, // number of coefficients
0, // flag for minimum phase
txa[channel].midbuff, // pointer to input buffer
txa[channel].midbuff, // pointer to output buffer
txa[channel].f_low, // low freq cutoff
txa[channel].f_high, // high freq cutoff
ch[channel].dsp_rate, // samplerate
1, // wintype
1.0); // gain
txa[channel].compmeter.p = create_meter (
1, // run
&(txa[channel].compressor.p->run), // pointer to compressor 'run'
ch[channel].dsp_size, // size
txa[channel].midbuff, // pointer to buffer
ch[channel].dsp_rate, // samplerate
0.100, // averaging time constant
0.100, // peak decay time constant
txa[channel].meter, // result vector
txa[channel].pmtupdate, // locks for meter access
TXA_COMP_AV, // index for average value
TXA_COMP_PK, // index for peak value
-1, // index for gain value
0); // pointer for gain computation
txa[channel].alc.p = create_wcpagc (
1, // run - always ON
5, // mode
1, // 0 for max(I,Q), 1 for envelope
txa[channel].midbuff, // input buff pointer
txa[channel].midbuff, // output buff pointer
ch[channel].dsp_size, // io_buffsize
ch[channel].dsp_rate, // sample rate
0.001, // tau_attack
0.010, // tau_decay
6, // n_tau
1.0, // max_gain
1.0, // var_gain
1.0, // fixed_gain
1.0, // max_input
1.0, // out_targ
0.250, // tau_fast_backaverage
0.005, // tau_fast_decay
5.0, // pop_ratio
0, // hang_enable
0.500, // tau_hang_backmult
0.500, // hangtime
2.000, // hang_thresh
0.100); // tau_hang_decay
txa[channel].ammod.p = create_ammod (
0, // run - OFF by default
0, // mode: 0=>AM, 1=>DSB
ch[channel].dsp_size, // size
txa[channel].midbuff, // pointer to input buffer
txa[channel].midbuff, // pointer to output buffer
0.5); // carrier level
txa[channel].fmmod.p = create_fmmod (
0, // run - OFF by default
ch[channel].dsp_size, // size
txa[channel].midbuff, // pointer to input buffer
txa[channel].midbuff, // pointer to input buffer
ch[channel].dsp_rate, // samplerate
5000.0, // deviation
300.0, // low cutoff frequency
3000.0, // high cutoff frequency
1, // ctcss run control
0.10, // ctcss level
100.0, // ctcss frequency
1, // run bandpass filter
2048, // number coefficients for bandpass filter
0); // minimum phase flag
txa[channel].gen1.p = create_gen (
0, // run
ch[channel].dsp_size, // buffer size
txa[channel].midbuff, // input buffer
txa[channel].midbuff, // output buffer
ch[channel].dsp_rate, // sample rate
0); // mode
txa[channel].uslew.p = create_uslew (
channel, // channel
&ch[channel].iob.ch_upslew, // pointer to channel upslew flag
ch[channel].dsp_size, // buffer size
txa[channel].midbuff, // input buffer
txa[channel].midbuff, // output buffer
ch[channel].dsp_rate, // sample rate
0.000, // delay time
0.005); // upslew time
txa[channel].alcmeter.p = create_meter (
1, // run
0, // optional pointer to a 'run'
ch[channel].dsp_size, // size
txa[channel].midbuff, // pointer to buffer
ch[channel].dsp_rate, // samplerate
0.100, // averaging time constant
0.100, // peak decay time constant
txa[channel].meter, // result vector
txa[channel].pmtupdate, // locks for meter access
TXA_ALC_AV, // index for average value
TXA_ALC_PK, // index for peak value
TXA_ALC_GAIN, // index for gain value
&txa[channel].alc.p->gain); // pointer for gain computation
txa[channel].sip1.p = create_siphon (
1, // run
0, // position
0, // mode
0, // disp
ch[channel].dsp_size, // input buffer size
txa[channel].midbuff, // input buffer
16384, // number of samples to buffer
16384, // fft size for spectrum
1); // specmode
txa[channel].calcc.p = create_calcc (
channel, // channel number
1, // run calibration
1024, // input buffer size
ch[channel].in_rate, // samplerate
16, // ints
256, // spi
(1.0 / 0.4072), // hw_scale
0.1, // mox delay
0.0, // loop delay
0.8, // ptol
0, // mox
0, // solidmox
1, // pin mode
1, // map mode
0, // stbl mode
256, // pin samples
0.9); // alpha
txa[channel].iqc.p0 = txa[channel].iqc.p1 = create_iqc (
0, // run
ch[channel].dsp_size, // size
txa[channel].midbuff, // input buffer
txa[channel].midbuff, // output buffer
(double)ch[channel].dsp_rate, // sample rate
16, // ints
0.005, // changeover time
256); // spi
txa[channel].cfir.p = create_cfir(
0, // run
ch[channel].dsp_size, // size
2048, // number of filter coefficients
0, // minimum phase flag
txa[channel].midbuff, // input buffer
txa[channel].midbuff, // output buffer
ch[channel].dsp_rate, // input sample rate
ch[channel].out_rate, // CIC input sample rate
1, // CIC differential delay
640, // CIC interpolation factor
5, // CIC integrator-comb pairs
20000.0, // cutoff frequency
0, // fourth-power rolloff
0.0, // raised-cosine transition width
0); // window type
txa[channel].rsmpout.p = create_resample (
0, // run - will be turned ON below if needed
ch[channel].dsp_size, // input size
txa[channel].midbuff, // pointer to input buffer
txa[channel].outbuff, // pointer to output buffer
ch[channel].dsp_rate, // input sample rate
ch[channel].out_rate, // output sample rate
0.0, // select cutoff automatically
0, // select ncoef automatically
0.980); // gain
txa[channel].outmeter.p = create_meter (
1, // run
0, // optional pointer to another 'run'
ch[channel].dsp_outsize, // size
txa[channel].outbuff, // pointer to buffer
ch[channel].out_rate, // samplerate
0.100, // averaging time constant
0.100, // peak decay time constant
txa[channel].meter, // result vector
txa[channel].pmtupdate, // locks for meter access
TXA_OUT_AV, // index for average value
TXA_OUT_PK, // index for peak value
-1, // index for gain value
0); // pointer for gain computation
// turn OFF / ON resamplers as needed
TXAResCheck (channel);
}
void destroy_txa (int channel)
{
// in reverse order, free each item we created
destroy_meter (txa[channel].outmeter.p);
destroy_resample (txa[channel].rsmpout.p);
destroy_cfir(txa[channel].cfir.p);
destroy_iqc (txa[channel].iqc.p0);
destroy_calcc (txa[channel].calcc.p);
destroy_siphon (txa[channel].sip1.p);
destroy_meter (txa[channel].alcmeter.p);
destroy_uslew (txa[channel].uslew.p);
destroy_gen (txa[channel].gen1.p);
destroy_fmmod (txa[channel].fmmod.p);
destroy_ammod (txa[channel].ammod.p);
destroy_wcpagc (txa[channel].alc.p);
destroy_meter (txa[channel].compmeter.p);
destroy_bandpass (txa[channel].bp2.p);
destroy_osctrl (txa[channel].osctrl.p);
destroy_bandpass (txa[channel].bp1.p);
destroy_compressor (txa[channel].compressor.p);
destroy_bandpass (txa[channel].bp0.p);
destroy_meter (txa[channel].cfcmeter.p);
destroy_cfcomp (txa[channel].cfcomp.p);
destroy_meter (txa[channel].lvlrmeter.p);
destroy_wcpagc (txa[channel].leveler.p);
destroy_emphp (txa[channel].preemph.p);
destroy_meter (txa[channel].eqmeter.p);
destroy_eqp (txa[channel].eqp.p);
destroy_amsq (txa[channel].amsq.p);
destroy_meter (txa[channel].micmeter.p);
destroy_phrot (txa[channel].phrot.p);
destroy_panel (txa[channel].panel.p);
destroy_gen (txa[channel].gen0.p);
destroy_resample (txa[channel].rsmpin.p);
_aligned_free (txa[channel].midbuff);
_aligned_free (txa[channel].outbuff);
_aligned_free (txa[channel].inbuff);
}
void flush_txa (int channel)
{
memset (txa[channel].inbuff, 0, 1 * ch[channel].dsp_insize * sizeof (complex));
memset (txa[channel].outbuff, 0, 1 * ch[channel].dsp_outsize * sizeof (complex));
memset (txa[channel].midbuff, 0, 2 * ch[channel].dsp_size * sizeof (complex));
flush_resample (txa[channel].rsmpin.p);
flush_gen (txa[channel].gen0.p);
flush_panel (txa[channel].panel.p);
flush_phrot (txa[channel].phrot.p);
flush_meter (txa[channel].micmeter.p);
flush_amsq (txa[channel].amsq.p);
flush_eqp (txa[channel].eqp.p);
flush_meter (txa[channel].eqmeter.p);
flush_emphp (txa[channel].preemph.p);
flush_wcpagc (txa[channel].leveler.p);
flush_meter (txa[channel].lvlrmeter.p);
flush_cfcomp (txa[channel].cfcomp.p);
flush_meter (txa[channel].cfcmeter.p);
flush_bandpass (txa[channel].bp0.p);
flush_compressor (txa[channel].compressor.p);
flush_bandpass (txa[channel].bp1.p);
flush_osctrl (txa[channel].osctrl.p);
flush_bandpass (txa[channel].bp2.p);
flush_meter (txa[channel].compmeter.p);
flush_wcpagc (txa[channel].alc.p);
flush_ammod (txa[channel].ammod.p);
flush_fmmod (txa[channel].fmmod.p);
flush_gen (txa[channel].gen1.p);
flush_uslew (txa[channel].uslew.p);
flush_meter (txa[channel].alcmeter.p);
flush_siphon (txa[channel].sip1.p);
flush_iqc (txa[channel].iqc.p0);
flush_cfir(txa[channel].cfir.p);
flush_resample (txa[channel].rsmpout.p);
flush_meter (txa[channel].outmeter.p);
}
void xtxa (int channel)
{
xresample (txa[channel].rsmpin.p); // input resampler
xgen (txa[channel].gen0.p); // input signal generator
xpanel (txa[channel].panel.p); // includes MIC gain
xphrot (txa[channel].phrot.p); // phase rotator
xmeter (txa[channel].micmeter.p); // MIC meter
xamsqcap (txa[channel].amsq.p); // downward expander capture
xamsq (txa[channel].amsq.p); // downward expander action
xeqp (txa[channel].eqp.p); // pre-EQ
xmeter (txa[channel].eqmeter.p); // EQ meter
xemphp (txa[channel].preemph.p, 0); // FM pre-emphasis (first option)
xwcpagc (txa[channel].leveler.p); // Leveler
xmeter (txa[channel].lvlrmeter.p); // Leveler Meter
xcfcomp (txa[channel].cfcomp.p, 0); // Continuous Frequency Compressor with post-EQ
xmeter (txa[channel].cfcmeter.p); // CFC+PostEQ Meter
xbandpass (txa[channel].bp0.p, 0); // primary bandpass filter
xcompressor (txa[channel].compressor.p); // COMP compressor
xbandpass (txa[channel].bp1.p, 0); // aux bandpass (runs if COMP)
xosctrl (txa[channel].osctrl.p); // CESSB Overshoot Control
xbandpass (txa[channel].bp2.p, 0); // aux bandpass (runs if CESSB)
xmeter (txa[channel].compmeter.p); // COMP meter
xwcpagc (txa[channel].alc.p); // ALC
xammod (txa[channel].ammod.p); // AM Modulator
xemphp (txa[channel].preemph.p, 1); // FM pre-emphasis (second option)
xfmmod (txa[channel].fmmod.p); // FM Modulator
xgen (txa[channel].gen1.p); // output signal generator (TUN and Two-tone)
xuslew (txa[channel].uslew.p); // up-slew for AM, FM, and gens
xmeter (txa[channel].alcmeter.p); // ALC Meter
xsiphon (txa[channel].sip1.p, 0); // siphon data for display
xiqc (txa[channel].iqc.p0); // PureSignal correction
xcfir(txa[channel].cfir.p); // compensating FIR filter (used Protocol_2 only)
xresample (txa[channel].rsmpout.p); // output resampler
xmeter (txa[channel].outmeter.p); // output meter
// print_peak_env ("env_exception.txt", ch[channel].dsp_outsize, txa[channel].outbuff, 0.7);
}
void setInputSamplerate_txa (int channel)
{
// buffers
_aligned_free (txa[channel].inbuff);
txa[channel].inbuff = (double *)malloc0(1 * ch[channel].dsp_insize * sizeof(complex));
// input resampler
setBuffers_resample (txa[channel].rsmpin.p, txa[channel].inbuff, txa[channel].midbuff);
setSize_resample (txa[channel].rsmpin.p, ch[channel].dsp_insize);
setInRate_resample (txa[channel].rsmpin.p, ch[channel].in_rate);
TXAResCheck (channel);
}
void setOutputSamplerate_txa (int channel)
{
// buffers
_aligned_free (txa[channel].outbuff);
txa[channel].outbuff = (double *)malloc0(1 * ch[channel].dsp_outsize * sizeof(complex));
// cfir - needs to know input rate of firmware CIC
setOutRate_cfir (txa[channel].cfir.p, ch[channel].out_rate);
// output resampler
setBuffers_resample (txa[channel].rsmpout.p, txa[channel].midbuff, txa[channel].outbuff);
setOutRate_resample (txa[channel].rsmpout.p, ch[channel].out_rate);
TXAResCheck (channel);
// output meter
setBuffers_meter (txa[channel].outmeter.p, txa[channel].outbuff);
setSize_meter (txa[channel].outmeter.p, ch[channel].dsp_outsize);
setSamplerate_meter (txa[channel].outmeter.p, ch[channel].out_rate);
}
void setDSPSamplerate_txa (int channel)
{
// buffers
_aligned_free (txa[channel].inbuff);
txa[channel].inbuff = (double *)malloc0(1 * ch[channel].dsp_insize * sizeof(complex));
_aligned_free (txa[channel].outbuff);
txa[channel].outbuff = (double *)malloc0(1 * ch[channel].dsp_outsize * sizeof(complex));
// input resampler
setBuffers_resample (txa[channel].rsmpin.p, txa[channel].inbuff, txa[channel].midbuff);
setSize_resample (txa[channel].rsmpin.p, ch[channel].dsp_insize);
setOutRate_resample (txa[channel].rsmpin.p, ch[channel].dsp_rate);
// dsp_rate blocks
setSamplerate_gen (txa[channel].gen0.p, ch[channel].dsp_rate);
setSamplerate_panel (txa[channel].panel.p, ch[channel].dsp_rate);
setSamplerate_phrot (txa[channel].phrot.p, ch[channel].dsp_rate);
setSamplerate_meter (txa[channel].micmeter.p, ch[channel].dsp_rate);
setSamplerate_amsq (txa[channel].amsq.p, ch[channel].dsp_rate);
setSamplerate_eqp (txa[channel].eqp.p, ch[channel].dsp_rate);
setSamplerate_meter (txa[channel].eqmeter.p, ch[channel].dsp_rate);
setSamplerate_emphp (txa[channel].preemph.p, ch[channel].dsp_rate);
setSamplerate_wcpagc (txa[channel].leveler.p, ch[channel].dsp_rate);
setSamplerate_meter (txa[channel].lvlrmeter.p, ch[channel].dsp_rate);
setSamplerate_cfcomp (txa[channel].cfcomp.p, ch[channel].dsp_rate);
setSamplerate_meter (txa[channel].cfcmeter.p, ch[channel].dsp_rate);
setSamplerate_bandpass (txa[channel].bp0.p, ch[channel].dsp_rate);
setSamplerate_compressor (txa[channel].compressor.p, ch[channel].dsp_rate);
setSamplerate_bandpass (txa[channel].bp1.p, ch[channel].dsp_rate);
setSamplerate_osctrl (txa[channel].osctrl.p, ch[channel].dsp_rate);
setSamplerate_bandpass (txa[channel].bp2.p, ch[channel].dsp_rate);
setSamplerate_meter (txa[channel].compmeter.p, ch[channel].dsp_rate);
setSamplerate_wcpagc (txa[channel].alc.p, ch[channel].dsp_rate);
setSamplerate_ammod (txa[channel].ammod.p, ch[channel].dsp_rate);
setSamplerate_fmmod (txa[channel].fmmod.p, ch[channel].dsp_rate);
setSamplerate_gen (txa[channel].gen1.p, ch[channel].dsp_rate);
setSamplerate_uslew (txa[channel].uslew.p, ch[channel].dsp_rate);
setSamplerate_meter (txa[channel].alcmeter.p, ch[channel].dsp_rate);
setSamplerate_siphon (txa[channel].sip1.p, ch[channel].dsp_rate);
setSamplerate_iqc (txa[channel].iqc.p0, ch[channel].dsp_rate);
setSamplerate_cfir (txa[channel].cfir.p, ch[channel].dsp_rate);
// output resampler
setBuffers_resample (txa[channel].rsmpout.p, txa[channel].midbuff, txa[channel].outbuff);
setInRate_resample (txa[channel].rsmpout.p, ch[channel].dsp_rate);
TXAResCheck (channel);
// output meter
setBuffers_meter (txa[channel].outmeter.p, txa[channel].outbuff);
setSize_meter (txa[channel].outmeter.p, ch[channel].dsp_outsize);
}
void setDSPBuffsize_txa (int channel)
{
// buffers
_aligned_free (txa[channel].inbuff);
txa[channel].inbuff = (double *)malloc0(1 * ch[channel].dsp_insize * sizeof(complex));
_aligned_free (txa[channel].midbuff);
txa[channel].midbuff = (double *)malloc0(2 * ch[channel].dsp_size * sizeof(complex));
_aligned_free (txa[channel].outbuff);
txa[channel].outbuff = (double *)malloc0(1 * ch[channel].dsp_outsize * sizeof(complex));
// input resampler
setBuffers_resample (txa[channel].rsmpin.p, txa[channel].inbuff, txa[channel].midbuff);
setSize_resample (txa[channel].rsmpin.p, ch[channel].dsp_insize);
// dsp_size blocks
setBuffers_gen (txa[channel].gen0.p, txa[channel].midbuff, txa[channel].midbuff);
setSize_gen (txa[channel].gen0.p, ch[channel].dsp_size);
setBuffers_panel (txa[channel].panel.p, txa[channel].midbuff, txa[channel].midbuff);
setSize_panel (txa[channel].panel.p, ch[channel].dsp_size);
setBuffers_phrot (txa[channel].phrot.p, txa[channel].midbuff, txa[channel].midbuff);
setSize_phrot (txa[channel].phrot.p, ch[channel].dsp_size);
setBuffers_meter (txa[channel].micmeter.p, txa[channel].midbuff);
setSize_meter (txa[channel].micmeter.p, ch[channel].dsp_size);
setBuffers_amsq (txa[channel].amsq.p, txa[channel].midbuff, txa[channel].midbuff, txa[channel].midbuff);
setSize_amsq (txa[channel].amsq.p, ch[channel].dsp_size);
setBuffers_eqp (txa[channel].eqp.p, txa[channel].midbuff, txa[channel].midbuff);
setSize_eqp (txa[channel].eqp.p, ch[channel].dsp_size);
setBuffers_meter (txa[channel].eqmeter.p, txa[channel].midbuff);
setSize_meter (txa[channel].eqmeter.p, ch[channel].dsp_size);
setBuffers_emphp (txa[channel].preemph.p, txa[channel].midbuff, txa[channel].midbuff);
setSize_emphp (txa[channel].preemph.p, ch[channel].dsp_size);
setBuffers_wcpagc (txa[channel].leveler.p, txa[channel].midbuff, txa[channel].midbuff);
setSize_wcpagc (txa[channel].leveler.p, ch[channel].dsp_size);
setBuffers_meter (txa[channel].lvlrmeter.p, txa[channel].midbuff);
setSize_meter (txa[channel].lvlrmeter.p, ch[channel].dsp_size);
setBuffers_cfcomp (txa[channel].cfcomp.p, txa[channel].midbuff, txa[channel].midbuff);
setSize_cfcomp (txa[channel].cfcomp.p, ch[channel].dsp_size);
setBuffers_meter (txa[channel].cfcmeter.p, txa[channel].midbuff);
setSize_meter (txa[channel].cfcmeter.p, ch[channel].dsp_size);
setBuffers_bandpass (txa[channel].bp0.p, txa[channel].midbuff, txa[channel].midbuff);
setSize_bandpass (txa[channel].bp0.p, ch[channel].dsp_size);
setBuffers_compressor (txa[channel].compressor.p, txa[channel].midbuff, txa[channel].midbuff);
setSize_compressor (txa[channel].compressor.p, ch[channel].dsp_size);
setBuffers_bandpass (txa[channel].bp1.p, txa[channel].midbuff, txa[channel].midbuff);
setSize_bandpass (txa[channel].bp1.p, ch[channel].dsp_size);
setBuffers_osctrl (txa[channel].osctrl.p, txa[channel].midbuff, txa[channel].midbuff);
setSize_osctrl (txa[channel].osctrl.p, ch[channel].dsp_size);
setBuffers_bandpass (txa[channel].bp2.p, txa[channel].midbuff, txa[channel].midbuff);
setSize_bandpass (txa[channel].bp2.p, ch[channel].dsp_size);
setBuffers_meter (txa[channel].compmeter.p, txa[channel].midbuff);
setSize_meter (txa[channel].compmeter.p, ch[channel].dsp_size);
setBuffers_wcpagc (txa[channel].alc.p, txa[channel].midbuff, txa[channel].midbuff);
setSize_wcpagc (txa[channel].alc.p, ch[channel].dsp_size);
setBuffers_ammod (txa[channel].ammod.p, txa[channel].midbuff, txa[channel].midbuff);
setSize_ammod (txa[channel].ammod.p, ch[channel].dsp_size);
setBuffers_fmmod (txa[channel].fmmod.p, txa[channel].midbuff, txa[channel].midbuff);
setSize_fmmod (txa[channel].fmmod.p, ch[channel].dsp_size);
setBuffers_gen (txa[channel].gen1.p, txa[channel].midbuff, txa[channel].midbuff);
setSize_gen (txa[channel].gen1.p, ch[channel].dsp_size);
setBuffers_uslew (txa[channel].uslew.p, txa[channel].midbuff, txa[channel].midbuff);
setSize_uslew (txa[channel].uslew.p, ch[channel].dsp_size);
setBuffers_meter (txa[channel].alcmeter.p, txa[channel].midbuff);
setSize_meter (txa[channel].alcmeter.p, ch[channel].dsp_size);
setBuffers_siphon (txa[channel].sip1.p, txa[channel].midbuff);
setSize_siphon (txa[channel].sip1.p, ch[channel].dsp_size);
setBuffers_iqc (txa[channel].iqc.p0, txa[channel].midbuff, txa[channel].midbuff);
setSize_iqc (txa[channel].iqc.p0, ch[channel].dsp_size);
setBuffers_cfir (txa[channel].cfir.p, txa[channel].midbuff, txa[channel].midbuff);
setSize_cfir (txa[channel].cfir.p, ch[channel].dsp_size);
// output resampler
setBuffers_resample (txa[channel].rsmpout.p, txa[channel].midbuff, txa[channel].outbuff);
setSize_resample (txa[channel].rsmpout.p, ch[channel].dsp_size);
// output meter
setBuffers_meter (txa[channel].outmeter.p, txa[channel].outbuff);
setSize_meter (txa[channel].outmeter.p, ch[channel].dsp_outsize);
}
/********************************************************************************************************
* *
* TXA Properties *
* *
********************************************************************************************************/
PORT
void SetTXAMode (int channel, int mode)
{
if (txa[channel].mode != mode)
{
EnterCriticalSection (&ch[channel].csDSP);
txa[channel].mode = mode;
txa[channel].ammod.p->run = 0;
txa[channel].fmmod.p->run = 0;
txa[channel].preemph.p->run = 0;
switch (mode)
{
case TXA_AM:
case TXA_SAM:
txa[channel].ammod.p->run = 1;
txa[channel].ammod.p->mode = 0;
break;
case TXA_DSB:
txa[channel].ammod.p->run = 1;
txa[channel].ammod.p->mode = 1;
break;
case TXA_AM_LSB:
case TXA_AM_USB:
txa[channel].ammod.p->run = 1;
txa[channel].ammod.p->mode = 2;
break;
case TXA_FM:
txa[channel].fmmod.p->run = 1;
txa[channel].preemph.p->run = 1;
break;
default:
break;
}
TXASetupBPFilters (channel);
LeaveCriticalSection (&ch[channel].csDSP);
}
}
PORT
void SetTXABandpassFreqs (int channel, double f_low, double f_high)
{
if ((txa[channel].f_low != f_low) || (txa[channel].f_high != f_high))
{
txa[channel].f_low = f_low;
txa[channel].f_high = f_high;
TXASetupBPFilters (channel);
}
}
/********************************************************************************************************
* *
* TXA Internal Functions *
* *
********************************************************************************************************/
void TXAResCheck (int channel)
{
RESAMPLE a = txa[channel].rsmpin.p;
if (ch[channel].in_rate != ch[channel].dsp_rate) a->run = 1;
else a->run = 0;
a = txa[channel].rsmpout.p;
if (ch[channel].dsp_rate != ch[channel].out_rate) a->run = 1;
else a->run = 0;
}
int TXAUslewCheck (int channel)
{
return (txa[channel].ammod.p->run == 1) ||
(txa[channel].fmmod.p->run == 1) ||
(txa[channel].gen0.p->run == 1) ||
(txa[channel].gen1.p->run == 1);
}
void TXASetupBPFilters (int channel)
{
txa[channel].bp0.p->run = 1;
txa[channel].bp1.p->run = 0;
txa[channel].bp2.p->run = 0;
switch (txa[channel].mode)
{
case TXA_LSB:
case TXA_USB:
case TXA_CWL:
case TXA_CWU:
case TXA_DIGL:
case TXA_DIGU:
case TXA_SPEC:
case TXA_DRM:
CalcBandpassFilter (txa[channel].bp0.p, txa[channel].f_low, txa[channel].f_high, 2.0);
if (txa[channel].compressor.p->run)
{
CalcBandpassFilter (txa[channel].bp1.p, txa[channel].f_low, txa[channel].f_high, 2.0);
txa[channel].bp1.p->run = 1;
if (txa[channel].osctrl.p->run)
{
CalcBandpassFilter (txa[channel].bp2.p, txa[channel].f_low, txa[channel].f_high, 1.0);
txa[channel].bp2.p->run = 1;
}
}
break;
case TXA_DSB:
case TXA_AM:
case TXA_SAM:
case TXA_FM:
if (txa[channel].compressor.p->run)
{
CalcBandpassFilter (txa[channel].bp0.p, 0.0, txa[channel].f_high, 2.0);
CalcBandpassFilter (txa[channel].bp1.p, 0.0, txa[channel].f_high, 2.0);
txa[channel].bp1.p->run = 1;
if (txa[channel].osctrl.p->run)
{
CalcBandpassFilter (txa[channel].bp2.p, 0.0, txa[channel].f_high, 1.0);
txa[channel].bp2.p->run = 1;
}
}
else
{
CalcBandpassFilter (txa[channel].bp0.p, txa[channel].f_low, txa[channel].f_high, 1.0);
}
break;
case TXA_AM_LSB:
CalcBandpassFilter (txa[channel].bp0.p, -txa[channel].f_high, 0.0, 2.0);
if (txa[channel].compressor.p->run)
{
CalcBandpassFilter (txa[channel].bp1.p, -txa[channel].f_high, 0.0, 2.0);
txa[channel].bp1.p->run = 1;
if (txa[channel].osctrl.p->run)
{
CalcBandpassFilter (txa[channel].bp2.p, -txa[channel].f_high, 0.0, 1.0);
txa[channel].bp2.p->run = 1;
}
}
break;
case TXA_AM_USB:
CalcBandpassFilter (txa[channel].bp0.p, 0.0, txa[channel].f_high, 2.0);
if (txa[channel].compressor.p->run)
{
CalcBandpassFilter (txa[channel].bp1.p, 0.0, txa[channel].f_high, 2.0);
txa[channel].bp1.p->run = 1;
if (txa[channel].osctrl.p->run)
{
CalcBandpassFilter (txa[channel].bp2.p, 0.0, txa[channel].f_high, 1.0);
txa[channel].bp2.p->run = 1;
}
}
break;
}
}
/********************************************************************************************************
* *
* Collectives *
* *
********************************************************************************************************/
PORT
void TXASetNC (int channel, int nc)
{
int oldstate = SetChannelState (channel, 0, 1);
SetTXABandpassNC (channel, nc);
// SetTXAFMEmphNC (channel, nc);
// SetTXAEQNC (channel, nc);
SetTXAFMNC (channel, nc);
SetChannelState (channel, oldstate, 0);
}
PORT
void TXASetMP (int channel, int mp)
{
SetTXABandpassMP (channel, mp);
SetTXAFMEmphMP (channel, mp);
SetTXAEQMP (channel, mp);
SetTXAFMMP (channel, mp);
}