-
Notifications
You must be signed in to change notification settings - Fork 3
/
usdx_t32.ino
3044 lines (2602 loc) · 111 KB
/
usdx_t32.ino
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
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/*
* uSDX with a Teensy 3.2
*
* K1URC
*
* Hardware is a qrp-labs QCX+, starting with the original AM modulator connected to the BS170 drains.
* Current plan is to provide a provision to convert between the original uSDX processor and the Teensy
* by swapping a few parts in and out, with the Teensy mounted on the QRP-LABS development board.
* Will try using a Nokia display, daylight readable, fun to program, fast SPI operation.
* Alternate display: OLED 128x64 I2C.
* To compile both together need to have just one copy of current fonts as both
* libraries are based on the same code from Rinky Dink Electronics.
*
*
* Change/Progress log:
* Version 1.0 Initial testing with a Weaver receiver.
* Version 1.2 Added provision for AGC and AM detector. Renamed some audio objects.
* Version 1.21 New AM decoder.
* Version 1.3 Baseband phasing version. I think this version will have more reusable audio objects when transmitting.
* Version 1.31 Adding Mode Select object gets the volume control out of the AGC loop.
* Version 1.32 Moved AGC amps out of the phasing path as it degraded the audio image suppression. The Weaver version also has
* this problem. Not sure I know what I am talking about here. Figured it out, mixer default gain is 1, not zero.
* Version 1.33 Design changes with transmitting in mind. Abandoning AM mode.
* Version 1.34 Back to a Weaver decoder with FIR front end filters. Then back to Bi-quads.
* Version 1.35 Completed audio design. USB objects commented out for now. Still need to cut VUSB etch on the Teensy 3.2
* Version 1.36 Changed I2C to a non-blocking DMA driven ( or ISR ) library i2c_t3. My polling code commented out.
* This required changing the 7 audio library .ccp control files to use i2c_t3 instead of Wire to correct link errors.
* A Teensyduino update will remove these changes ( duplicate wire definitions result ). Also edited i2c_t3.h to
* allow only 1 I2C bus to run. This is a user option as noted in the file.
* Version 1.37 Added a Audio Library object for an AM decoder as an exercise in learning how to add a custom audio object.
* Version 1.38 Added Hilberts for AM decoding, Tx magnitude and phase, and FFT analysis. Some redundant elements in design now.
* Removed the AM decoder Library object test. Added AM detector at about 11k IF frequency. Hilberts are multi
* purpose. Can have only one of TX, FFT, AM running at any one time as each will need different filters.
* Version 1.39 Continuing with a Hilbert only version. Having issues with I and Q out of sync it seems. No decode of SSB
* unless move some patchcords around or remove objects. Rectify object was misbehaving. Updated my
* Teensyduino install to fix.
* Version 1.40 Wrote MagPhase object to extract data from the Audio library stream to use for transmitting. Set _UA at
* 44117/8 for initial testing.
* Version 1.41 I2C did not support sample rate 1/4 of 44k ( 11k ) for TX. Changed MagPhase to use 1/6 rate or 7352. It does
* not divide evenly into 128 size buffer, but seems to be working ok.
* Version 1.42 Added another custom audio block ( SSB_AM ) to process receive signals at 1/4 rate with classic Hilbert.
* The upsample/filter seems to lose quite a bit of audio power. Adjusted agc, and more volume is required.
* Version 1.43 Replaced the FIR filters with Bi-quad and changed SSB_AM to run at 1/3 rate ( 1/3 of 44117 ). Forming the
* opinion that Hilberts do not work well at baseband with a high sample rate.
* Version 1.44 Since the RX hilberts could not be used for transmitting, returning to the Weaver receive method. The custom
* audio object SSB_AM is no longer needed. No AM mode for now.
* Version 1.45 Added an AM detector. Double reset the Si5351 on band/mode changes as sometimes it seems out of sync. Think
* this issue started when I added the dividers to the bandstack ( to run the Si5351 in spec for bands other than 80).
* Version 1.46 CAT control using Argonaut V emulation. Added USA band limits indication. Made some changes to MagPhase, phase
* may or may not be better, magnitude is better. Added CW decoder. Added Digi mode that filters magnitude and phase
* on TX. Changed _UA to be the TX sample rate as that seems simplest overall. Added S meter. CW decoder needs help.
* Version 1.47 RIT added that works as described below in encoder switch usage. Changed swapping sidebands to the SSB adder
* rather than in the Si5351.
* Version 1.48 Wired DIT, DAH, RX, KEYOUT signals to the Teensy 3.2. First transmit test sucessful. Added CW keyer code. Added
* attenuator ( tx/rx FET ).
* Version 1.49 Many little changes with menu and cw keyer, speed, practice mode, sidetone, etc.
* Version 1.50 CW keying had pops on one side of the paddle only, probably due to the 1uf I put in place of the 220nf. Added a
* manual jumper to isolate the nets when in CW mode and connect them in SSB mode. Moved the Si5351 code into
* a separate file. Added a BandWidth object for CW but signals for all modes pass through it, so the Weaver lowpass
* filters are set as a roofing type filter and the new Bandwidth object is used for the final bandwidth control.
* Added a tone control that changes the Q of the Bandwidth object to vary the tone.
* Version 1.51 Adding a gain of 10 in front of the CW tone detect object greatly improved the CW decoder. Added a test to just
* load 4 registers in SendPLLBRegisterBulk when register 3 was the same as last time.
* Version 1.52 Using a Goertzel filter as a simple FFT scope. Seems to work ok although update rate is slow. Cleaned up some of
* the old code that was commented out as we seem to have settled upon a design. For DIGI mode, increased Weaver
* bandwidth to put the hole in the audio at 3000 hz. Cut in some low pass filters for other bands in series with the
* 17 meter lowpass. Noticed I now get some interference lines on the WSJT waterfall. Removed the alternate low pass
* filters provision as transmit current was excessive on some bands. So back to 17 meters tx/rx and just rx on the
* lower bands. Using a total of 4 Goertzel filters in the bandscope which makes it run 4 times faster than before.
* Version 1.53 Found a dynamic cassette style microphone in my junk collection. It has a mono plug so am adding an option to detect
* if DIT is shorted on power up and disable the hardware keyer and PTT. The idea is to use capacitive touch as the
* keyer/PTT when this condition is detected. Building a microphone preamp circuit in the footprint of IC10 and
* abandon the existing DVM circuit for the Teensy version. ( the DVM curcuit remains on the QCX board if I ever wish to
* use the ATMega328 again ). Preamp design from http://www.zen22142.zen.co.uk/Circuits/Audio/lf071_mic.htm with a few of
* the 10uf caps changed to 1uf. Decided to move the microphone to the CAT jack, and wired the Teensy version separate
* from the original uSDX design with the microphone and paddle using the same jack. Worked on the magnitude and phase
* some more attempting to suppress spikes in phase when amplitude is low. Mic Tx audio is terrible at this point.
* Version 1.54 Reducing USB audio gain below 1.0 as a potential fix for strange program hangup. ( voice audio on USB with max PC
* microphone volume. Doesn't hang when PC microphone volume is less than 100 ) Reducing agc1 volume below 1.0 to make
* sure the following IIR filters do not get overdriven ( voice mode using microphone ). Trying 0.98 for a value.
* Add a feature to allow delaying the phase changes with respect to the amplitude changes. uSDX has a delay of 1 sample,
* allow a choice of delay of up to 7 samples. Implemented tx_drive after the MagPhase calculation rather than before.
* Added some RF bypass caps and more gain to the microphone preamp and that seems to clear up much of the static hash on
* voice transmit. Ending this version with SSB voice not working well and the EER function in a state of flux.
* Added AM transmit.
* Version 1.55 Added 15, 12, and 10 meters to the band selection. Added cross modes UDSB and LDSB where the receiver works on SSB
* and the transmitter sends double sideband controlled carrier ( AM in other words ). Re-wrote the EER function separating
* out the different versions of transmit logic into their own functions. It should be easier to experiment without
* breaking something that works. Changed the modes order to match Argonaut V modes ( DIGI reports as FM in HRD program ).
* Version 1.56 Have SSB voice working well. Moved tx_drive back to the TxSelect mux and implemented audio clipping. Did not like how
* the audio clipping sounded and added ALC. Can now run the mic gain double what is was before and still have a nice
* sounding signal. Added a FIR filter after the TxSelect mux for clip filtering and more anti alias filtering.
*
*
*
*
*
*/
#define VERSION 1.56
// Paddle jack has Dah on the Tip and Dit on Ring. Swap probably needed for most paddles.
// Mic should have Mic on Tip, PTT on Ring for this radio.
/*
* The encoder switch works like this:
* A tap changes the tuning step with 1k, 100, 10 in rotation.
* To change to a larger tuning step, first tap then double tap within 1.5 seconds and select 5k, 50k, 500k steps with double taps.
* Normally a double tap brings up the multi function control. When done adjusting, double tap back to normal tuning.
* Or single tap for RF gain control ( actually gain in the agc amps ), another tap for CW decoder level, etc.
* Long Press normally brings up the menu. You can make selections with a tap. Double tap exits. And see sticky menus option below for
* different behavior. If RIT is active, Long Press cancels RIT.
*
* RIT is automatically enabled upon transmit. Cancel with a long press to return to normal frequency tuning. RIT is not tracked in
* the usual sense, instead Si5351 PLLB is not updated with new frequency changes when RIT is active. ( A hidden vfo B )
*
*
* *********** OR you can think of the encode switch this way
* There are 3 actions: tap, double tap, and long press.
*
* The primary use of tap is to cycle through tuning step sizes.
* Secondary use of tap is to make selections in the menu and to cycle through multi function selections.
* The primary use of double tap is to bring up the multi function control and to exit.
* Secondary use of double tap is to increase the tuning step higher than 1k. ( tap then double tap, double tap etc. )
* Secondary use of double tap is to escape out of the menu when using the sticky menu complile option.
* The primary use of long press is to bring up the menu system.
* Seconday use of long press is to turn off RIT.
*/
// Issues / to do
// Fix the cap in the mic pre-amp that I cut during testing.
// On first power up the Si5351 phasing is not correct and one needs to change the mode or band before it is corrected.
// Perhaps PLL reset is skipped? Should a proper Si5351 initialization be done as outlined in the datasheet?
// C4 C7 - does adding them cause processor noise in the front end. They are currently uninstalled.
// Measure audio image response, and alias images at +-44k away.
// Cut Vusb etch on the Teensy.
// Cap touch keyer/ptt inputs wired.
// Investigate the filter method used in usdx code for the morse decode signal level. Exponential averaging?
// Check if on frequency, may be about 20hz high on 14 mhz TX. ( or maybe both radios used needed to warm up some ).
//
// If a PC is used as a microphone driving the transmitter in USB mode and the PC microphone volume is at max, the program hangs when
// returning to rx mode. Seems to be when the AGC is releasing.
// This is accomplished by using the PC feature "listen to this device" with microphone in and Teensy USB out.
// This fault was during a transmit test and not how the radio would normally be used.
// Have reduced some gains below 1.0 in the transmit audio path as a potential fix.
// Is there an OLED write that is not suppressed with the transmitting variable if statements? That would cause a hang.
//
// QCX pin definitions mega328 to Teensy 3.2
/*
#define LCD_D4 0 //PD0 (pin 2) N/C
#define LCD_D5 1 //PD1 (pin 3) N/C
#define LCD_D6 2 //PD2 (pin 4) N/C
#define LCD_D7 3 //PD3 (pin 5) N/C
#define LCD_EN 4 //PD4 (pin 6) N/C
#define FREQCNT 5 //PD5 (pin 11) PULLUP ( @ 3.x k ) not needed, installed when debugging an issue
#define ROT_A 6 //PD6 (pin 12) 6
#define ROT_B 7 //PD7 (pin 13) 7
#define RX 8 //PB0 (pin 14) 4 + PullUp R36 installed
#define SIDETONE 9 //PB1 (pin 15) A14 DAC wired seperately from SIDETONE net
#define KEY_OUT 10 //PB2 (pin 16) 5 + PullDown 10k ( need PWM pin )
#define SIG_OUT 11 //PB3 (pin 17) PullDown 10k, no Teensy connection to SIG_OUT net
#define DAH 12 //PB4 (pin 18) 22 on jack it is tip
#define DIT 13 //PB5 (pin 19) 23 on jack it is ring
#define AUDIO1 14 //PC0/A0 (pin 23) A2
#define AUDIO2 15 //PC1/A1 (pin 24) A3
#define DVM 16 //PC2/A2 (pin 25) goes to source of a BS170, drain to A3 ( Q audio2 ), gate switched by 14
#define BUTTONS 17 //PC3/A3 (pin 26) 12 single digital encoder switch, active low
#define LCD_RS 18 //PC4 (pin 27) N/C
#define SDA 18 //PC4 (pin 27) A4
#define SCL 19 //PC5 (pin 28) A5
// Nokia Display
RST 8
CS 10
D/C 9
MOSI 11
CLK 13 ?? does switching the LED generate noise, swap with pin 8?
Capacitance keyer pins 0 and 1
*/
#define RX 4
#define ATTN2 4
#define KEYOUT 5 //20
#define DAHpin 22
#define DITpin 23
#define PTT 23
#define TXAUDIO_EN 14 // switches a FET to put DVM mic signal on Q audio input A3.
// Pick a screen: Nokia LCD or I2C 128x64 OLED
// Running both together yields redefinition warnings as they are basically the same library, but it works.
#define USE_OLED
#define USE_LCD
#define DEBUG_MP 0 // This is for testing the EER transmitter, and printing to arduino plotter. Set 0 for normal use.
//#define TWO_TONE_TEST // comment this out for normal use
// Nokia library uses soft SPI as the D/C pin needs to be held during data transfer.
// 84 x 48 pixels or 6 lines by 14 characters in text mode
#ifdef USE_LCD
// I bypassed the pin to port code in this copy of the library as it didn't compile for ARM
// and changed to use digitalWriteFast on the signals and renamed to _t version.
#include <LCD5110_Basic_t.h>
#endif
#ifdef USE_OLED
#include <OLED1306_Basic.h> // this is the LCD5110 library modified to use I2C for OLED 1306.
#endif
#include <i2c_t3.h> // non-blocking wire library
#include "MagPhase.h" // transmitting audio object
#include "AM_decode.h" // the simplest complex IQ decoder that I tried
#include "my_morse.h" // my morse table, designed for sending but used also for receive
#include "FFT_Scope.h" // A simple FFT type of display using a Goertzel filter.
#include "ParksLPF36.h" // Transmit bandwidth filter
extern unsigned char SmallFont[];
extern unsigned char MediumNumbers[];
//extern unsigned char BigNumbers[];
#define ROW0 0 // text based rows
#define ROW1 8
#define ROW2 16
#define ROW3 24
#define ROW4 32
#define ROW5 40 // end of LCD
#define ROW6 48
#define ROW7 56 // OLED has two more text rows
#ifdef USE_LCD
// ( sclk mosi d/c rst cs )
LCD5110 LCD( 13,11,9,8,10 );
#endif
#ifdef USE_OLED
OLED1306 OLD;
#endif
// transmit interval timer
IntervalTimer EER_timer;
#define EN_A 7 // encoder pins assignment
#define EN_B 6
#define EN_SW 12
/* button states */
#define IDLE_ 0
#define ARM 1
#define DTDELAY 2
#define DONE 3
#define TAP 4
#define DTAP 5
#define LONGPRESS 6
#define DBOUNCE 50 // 60
// encoder users
#define FREQ 0
#define MENUS 1
#define MULTI_FUN 2
int encoder_user;
// volume users - general use of volume code
#define MAX_VUSERS 8
#define VOLUME_U 0
#define AGC_GAIN_U 1
#define CW_DET_U 2
#define SIDE_VOL_U 3
#define WPM_U 4
#define TONE_U 5
#define TX_DRIVE_U 6
#define TX_PHASE_U 7
int multi_user;
// screen users of the bottom part not used by freq display and status line
#define INFO 0
#define CW_DECODE 1
#define FFT_SCOPE 2
int screen_user = INFO;
#define MIC 0
#define USBc 1 // universal serial bus, conflicts with upper side band def USB, so be careful here.
#define SIDETONE 2
int tx_source = USBc; // starting on 17 meters FT8 with USBc audio in and out.
#define DIT 1
#define DAH 2
int key_mask = DIT + DAH; // feature to disable hardware keyer/PTT if jack is shorted upon power up.
// Menus: Long press to enter
// STICKY_MENU 0 : Tap makes a selection and exits. Double tap exits without a selection.
// STICKY_MENU 1 : Tap makes a selection. Double tap makes a selection and exits.
// Sticky on is good for making a bunch of menu setups all at once, off is good for making just one change.
#define STICKY_MENU 0
struct BAND_STACK{
int mode;
uint32_t freq;
int stp;
int d; // pre-calculated divider for each band. Can run Si5351 in spec except on 80 meters.
int tx_src;
int fltr;
};
// modes
#define CW 3
#define LSB 2
#define USB 1
#define DIGI 4 // single tone slow baud rate mode, FT8, wspr, etc
#define AM 0
#define LDSB 6 // rx lower ssb, tx AM
#define UDSB 5 // rx upper ssb, tx AM
struct BAND_STACK bandstack[] = { // index is the band
{ LSB , 3928000, 1000, 126, MIC, 4 },
{ USB , 5330500, 500, 126, MIC, 5 }, // special 500 step for this band, not reachable in the normal step changes.
{ LSB , 7163000, 1000, 100, MIC, 3 },
{ CW , 10105000, 100, 68, USBc, 1 },
{ DIGI, 14074000, 1000, 54, USBc, 3 },
{ DIGI, 18100000, 1000, 40, USBc, 3 },
{ DIGI, 21074000, 1000, 34, USBc, 3 },
{ USB , 24930000, 1000, 30, MIC, 3 },
{ USB , 28300000, 1000, 26, MIC, 3 }
};
uint32_t freq = 18100000L; // probably should init these vars from the bandstack
int rit_enabled;
int step_ = 1000;
int band = 5;
int mode = DIGI;
int filter = 3;
int bfo;
int magp; // tx drive display on the LCD only
int magpmax; // max tx drive display on OLED after return to rx mode. Can't write to OLED during transmit.
int php; // !!! testing phase print
int32_t rav_df; // digi mode tx filters
int32_t rav_mag;
int trigger_; // !!! testing for debug using arduino plotter
int step_timer; // allows double tap to backup the freq step to 500k , command times out
// and returns to the normal double tap command ( volume )
float af_gain = 0.3;
float agc_gain = 1.0;
float side_gain = 0.1; // side tone volume, also af_gain affects side tone volume. agc_gain doesn't.
float sig_rms;
int transmitting;
float cw_det_val = 1.3; // mark space detect, adjust in volume options ( double tap, single tap )
float agc_sig = 0.3; // made global so can set it after tx and have rx process bring up the af gain
int attn2; // attenuator using T/R switch, very large decrease in volume
int wpm = 14; // keyer speed, adjust with "Volume" routines
float tone_; // tone control, adjust Q of the bandwidth object
float tx_drive = 7.0; // Adjust for some ALC action on normal voice. For my mic and voice, 4.0 is about right for no ALC.
// and use this for the microphone level only
int phase_delay = -1; // sample delay between modulation change and phase change, -7 to 7
float alc = 1.0; // tx ALC when using the microphone
#define STRAIGHT 0 // CW keyer modes
#define ULTIMATIC 1
#define MODE_A 2
#define MODE_B 3
#define PRACTICE_T 4 // last options toggle practice and use of the touch keyer, and swap
#define TOUCH_T 5 // put them in this menu as special cases to avoid more yes/no menu's
#define KEY_SWAP 6
int key_mode = ULTIMATIC;
int touch_key = 1; // 0 !!!
int cw_practice = 1;
int key_swap = 1; // jack wired with tip = DAH, needs swap from most of my other radio's
#define stage(c) Serial.write(c)
/******************************** Teensy Audio Library **********************************/
#include <Audio.h>
//#include <Wire.h> // edits have been made to audio library to use i2c_t3 instead of wire library. See version notes above.
//#include <SPI.h>
//#include <SD.h>
//#include <SerialFlash.h>
// FIR transmit filter instead of BiQuads
// GUItool: begin automatically generated code
AudioInputAnalogStereo adcs1; //xy=318.5714416503906,351.1428589820862
AudioAnalyzePeak peak1; //xy=428.5714416503906,211.14285898208618
AudioAmplifier agc2; //xy=473.5714416503906,378.1428589820862
AudioAmplifier agc1; //xy=476.5714416503906,328.1428589820862
AudioInputUSB usb2; //xy=477.1428565979004,516.8571624755859
AudioFilterFIR TXLow; //xy=487.1428909301758,477.14284324645996
AudioFilterBiquad QLow; //xy=503.28573989868164,427.1428394317627
AudioFilterBiquad ILow; //xy=513.5714416503906,275.1428589820862
AudioFFT_Scope2 Scope2; //xy=545.7142857142857,98.57142857142856
AudioMixer4 TxSelect; //xy=653.5714416503906,512.1428589820862
AudioSynthWaveformSine sinBFO; //xy=657.5714416503906,374.1428589820862
AudioSynthWaveformSine cosBFO; //xy=659.5714416503906,337.1428589820862
AudioEffectMultiply Q_mixer; //xy=691.5714416503906,430.1428589820862
AudioAMdecode2 AMdet; //xy=694.2857398986816,230.00000190734863
AudioEffectMultiply I_mixer; //xy=694.5714416503906,281.1428589820862
AudioAnalyzeToneDetect Scope_det4; //xy=726.1427993774414,139.9999542236328
AudioAnalyzeToneDetect Scope_det2; //xy=727.571403503418,71.42853736877441
AudioAnalyzeToneDetect Scope_det3; //xy=727.5713348388672,105.71429061889648
AudioAnalyzeToneDetect Scope_det1; //xy=728.9999542236328,38.571428298950195
AudioSynthWaveformSine SideTone; //xy=848.5714416503906,414.1428589820862
AudioMagPhase1 MagPhase; //xy=848.5714874267578,521.4285278320312
AudioMixer4 SSB; //xy=864.5714416503906,345.1428589820862
AudioFilterBiquad BandWidth; //xy=981.5714416503906,271.1428589820862
AudioAnalyzeRMS rms1; //xy=1030.5714416503906,216.14285898208618
AudioMixer4 Volume; //xy=1058.5714416503906,345.1428589820862
AudioAmplifier amp1; //xy=1144.5714416503906,269.1428589820862
AudioAnalyzeToneDetect CWdet; //xy=1188.5714416503906,206.14285898208618
AudioOutputAnalog dac1; //xy=1198.7142753601074,332.8571243286133
AudioOutputUSB usb1; //xy=1202.5714416503906,380.1428589820862
#ifdef TWO_TONE_TEST
AudioSynthWaveformSine SideTone2; //xy=483.14290618896484,555.7143478393555
AudioConnection patchCord9(SideTone2, 0, TxSelect, 3);
#endif
AudioConnection patchCord1(adcs1, 0, peak1, 0);
AudioConnection patchCord2(adcs1, 0, agc1, 0);
AudioConnection patchCord3(adcs1, 0, Scope2, 0);
AudioConnection patchCord4(adcs1, 1, agc2, 0);
AudioConnection patchCord5(adcs1, 1, Scope2, 1);
AudioConnection patchCord6(agc2, QLow);
AudioConnection patchCord7(agc1, ILow);
AudioConnection patchCord8(usb2, 0, TxSelect, 1);
//AudioConnection patchCord9(SideTone2, 0, TxSelect, 3);
AudioConnection patchCord10(QLow, 0, Q_mixer, 0);
AudioConnection patchCord11(QLow, 0, AMdet, 1);
AudioConnection patchCord12(QLow, 0, TxSelect, 0);
AudioConnection patchCord13(ILow, 0, I_mixer, 0);
AudioConnection patchCord14(ILow, 0, AMdet, 0);
AudioConnection patchCord15(Scope2, Scope_det1);
AudioConnection patchCord16(Scope2, Scope_det2);
AudioConnection patchCord17(Scope2, Scope_det3);
AudioConnection patchCord18(Scope2, Scope_det4);
AudioConnection patchCord19(TxSelect, TXLow);
AudioConnection patchCord20(sinBFO, 0, Q_mixer, 1);
AudioConnection patchCord21(cosBFO, 0, I_mixer, 1);
AudioConnection patchCord22(Q_mixer, 0, SSB, 2);
AudioConnection patchCord23(AMdet, 0, SSB, 0);
AudioConnection patchCord24(I_mixer, 0, SSB, 1);
AudioConnection patchCord25(TXLow, 0, MagPhase, 0);
AudioConnection patchCord26(SideTone, 0, Volume, 3);
AudioConnection patchCord27(SideTone, 0, TxSelect, 2);
AudioConnection patchCord28(SSB, BandWidth);
AudioConnection patchCord29(BandWidth, 0, Volume, 0);
AudioConnection patchCord30(BandWidth, rms1);
AudioConnection patchCord31(BandWidth, amp1);
AudioConnection patchCord32(Volume, dac1);
AudioConnection patchCord33(Volume, 0, usb1, 0);
AudioConnection patchCord34(Volume, 0, usb1, 1);
AudioConnection patchCord35(amp1, CWdet);
/*
AudioConnection patchCord1(adcs1, 0, peak1, 0);
AudioConnection patchCord2(adcs1, 0, agc1, 0);
AudioConnection patchCord3(adcs1, 0, Scope2, 0);
AudioConnection patchCord4(adcs1, 1, agc2, 0);
AudioConnection patchCord5(adcs1, 1, Scope2, 3);
AudioConnection patchCord6(agc2, QLow);
AudioConnection patchCord7(QLow, TXLow); // was agc2 in design but need to cut 60 hz hum
AudioConnection patchCord8(agc1, ILow);
AudioConnection patchCord9(usb2, 0, TxSelect, 1);
AudioConnection patchCord11(TXLow, 0, TxSelect, 0);
AudioConnection patchCord12(QLow, 0, Q_mixer, 0);
AudioConnection patchCord13(QLow, 0, AMdet, 3);
AudioConnection patchCord14(ILow, 0, I_mixer, 0);
AudioConnection patchCord15(ILow, 0, AMdet, 0);
AudioConnection patchCord16(Scope2, Scope_det1);
AudioConnection patchCord17(Scope2, Scope_det2);
AudioConnection patchCord18(Scope2, Scope_det3);
AudioConnection patchCord19(Scope2, Scope_det4);
AudioConnection patchCord20(TxSelect, 0, MagPhase, 0);
AudioConnection patchCord21(sinBFO, 0, Q_mixer, 1);
AudioConnection patchCord22(cosBFO, 0, I_mixer, 1);
AudioConnection patchCord23(Q_mixer, 0, SSB, 2);
AudioConnection patchCord24(AMdet, 0, SSB, 0);
AudioConnection patchCord25(I_mixer, 0, SSB, 1);
AudioConnection patchCord26(SideTone, 0, Volume, 3);
AudioConnection patchCord27(SideTone, 0, TxSelect, 2);
AudioConnection patchCord28(SSB, BandWidth);
AudioConnection patchCord29(BandWidth, 0, Volume, 0);
AudioConnection patchCord30(BandWidth, rms1);
AudioConnection patchCord31(BandWidth, amp1);
AudioConnection patchCord32(Volume, dac1);
AudioConnection patchCord33(Volume, 0, usb1, 0);
AudioConnection patchCord34(Volume, 0, usb1, 1);
AudioConnection patchCord35(amp1, CWdet);
// GUItool: end automatically generated code
*/
/*
// Scope added
// GUItool: begin automatically generated code
AudioInputAnalogStereo adcs1; //xy=234.99997329711914,284.9999809265137
AudioAnalyzePeak peak1; //xy=344.3332977294922,144.3333396911621
AudioInputUSB usb2; //xy=344.047607421875,444.61907958984375
AudioAmplifier agc2; //xy=389,311.6667175292969
AudioAmplifier agc1; //xy=392.8333740234375,261.33331298828125
AudioFilterBiquad QLow; //xy=413.83331298828125,360.25
AudioFilterBiquad ILow; //xy=429.4999694824219,208.41665649414062
AudioFilterBiquad TXLow;
AudioFFT_Scope2 Scope2; //xy=450,510
AudioMixer4 TxSelect; //xy=569.3333740234375,445.61907958984375
AudioSynthWaveformSine sinBFO; //xy=573.083251953125,307.41668701171875
AudioSynthWaveformSine cosBFO; //xy=575.9166259765625,270.75
AudioAnalyzeToneDetect Scope_det1; //xy=603.75,510
AudioAnalyzeToneDetect Scope_det2; //xy=603.75,510
AudioAnalyzeToneDetect Scope_det3; //xy=603.75,510
AudioAnalyzeToneDetect Scope_det4; //xy=603.75,510
AudioEffectMultiply Q_mixer; //xy=607.9999389648438,363.66668701171875
AudioEffectMultiply I_mixer; //xy=610.8333129882812,214.58334350585938
AudioAMdecode2 AMdet; //xy=620.714183807373,145.71428680419922
AudioSynthWaveformSine SideTone; //xy=764.0000343322754,347.95239448547363
AudioMagPhase1 MagPhase; //xy=779.2856788635254,445.4761657714844
AudioMixer4 SSB; //xy=780.7618827819824,278.4762382507324
AudioFilterBiquad BandWidth; //xy=897.5000610351562,204.52377319335938
AudioAnalyzeRMS rms1; //xy=946.6665649414062,149.21426391601562
AudioMixer4 Volume; //xy=974.7619171142578,278.7619285583496
AudioAmplifier amp1; //xy=1060,202
AudioOutputAnalog dac1; //xy=1097.190330505371,250.61907577514648
AudioAnalyzeToneDetect CWdet; //xy=1104.7025146484375,139.3571014404297
AudioOutputUSB usb1; //xy=1118.6191940307617,313.61904525756836
#ifdef TWO_TONE_TEST
AudioSynthWaveformSine SideTone2;
AudioConnection patchCord34(SideTone2, 0, TxSelect, 3);
#endif
AudioConnection patchCord1(adcs1, 0, peak1, 0);
AudioConnection patchCord2(adcs1, 0, agc1, 0);
AudioConnection patchCord3(adcs1, 0, Scope2, 0);
AudioConnection patchCord4(adcs1, 1, agc2, 0);
AudioConnection patchCord5(adcs1, 1, Scope2, 1);
AudioConnection patchCord6(usb2, 0, TxSelect, 1);
AudioConnection patchCord7(agc2, QLow);
AudioConnection patchCord8(agc1, ILow);
AudioConnection patchCord9(QLow, 0, Q_mixer, 0);
//AudioConnection patchCord10(QLow, 0, TxSelect, 0);
AudioConnection patchCord10(QLow, 0, TXLow, 0);
AudioConnection patchCord34(TXLow,0, TxSelect,0);
AudioConnection patchCord11(QLow, 0, AMdet, 1);
AudioConnection patchCord12(ILow, 0, I_mixer, 0);
AudioConnection patchCord13(ILow, 0, AMdet, 0);
AudioConnection patchCord14(Scope2, Scope_det1 );
AudioConnection patchCord31(Scope2, Scope_det2 );
AudioConnection patchCord32(Scope2, Scope_det3 );
AudioConnection patchCord33(Scope2, Scope_det4 );
AudioConnection patchCord15(TxSelect, 0, MagPhase, 0);
AudioConnection patchCord16(sinBFO, 0, Q_mixer, 1);
AudioConnection patchCord17(cosBFO, 0, I_mixer, 1);
AudioConnection patchCord18(Q_mixer, 0, SSB, 2);
AudioConnection patchCord19(I_mixer, 0, SSB, 1);
AudioConnection patchCord20(AMdet, 0, SSB, 0);
AudioConnection patchCord21(SideTone, 0, Volume, 3);
AudioConnection patchCord22(SideTone, 0, TxSelect, 2);
AudioConnection patchCord23(SSB, BandWidth);
AudioConnection patchCord24(BandWidth, 0, Volume, 0);
AudioConnection patchCord25(BandWidth, rms1);
AudioConnection patchCord26(BandWidth, amp1);
AudioConnection patchCord27(Volume, dac1);
AudioConnection patchCord28(Volume, 0, usb1, 0);
AudioConnection patchCord29(Volume, 0, usb1, 1);
AudioConnection patchCord30(amp1, CWdet);
// GUItool: end automatically generated code
*/
// I2C functions that the OLED library expects to use.
void i2init(){
Wire.begin(I2C_OP_MODE_DMA); // use mode DMA or ISR
Wire.setClock(800000); // I2C0_F 40 = 100k , 25 = 400k. 800000 seems to work, returns 818, 600k returns 600
// clock stretching may produce reduced speed if clock is way to fast for the devices.
// Calc'd that 700k speed could maybe support a tx bandwidth of 5.5k at 11029 sample rate.
// It doesn't. Nor does 800k or 1000k.
// At 1/8 rate: 500k works. Use 700k for some margin of error. 1/8 of 44117.
// At 1/6 rate get some errors at 700k. Use 800k. Should have better TX quality at 1/6 rate.
// At 1/5 rate get some errors at 1000k. Think we should stay at 1/6 rate, ( 1/6 of 44117 )
// and 800k clock on I2C.
}
void i2start( unsigned char adr ){
while( Wire.done() == 0 ); // still busy with last transmission. Need to block while still busy.
Wire.beginTransmission( adr );
}
void i2send( unsigned int data ){
Wire.write( data );
}
void i2stop( ){
Wire.sendTransmission(); // non-blocking
// Wire.endTransmission(); // blocking
}
// this include seems to need to be here. If at top of file with other includes, get a compiler bug error.
#include "si5351_usdx.cpp" // the si5351 code from the uSDX project, modified slightly for RIT and dividers used.
SI5351 si5351; // maybe it should be done this way.
// the transmit process uses I2C in an interrupt context. Must prevent other users from writing on I2C.
// No frequency changes or any OLED writes. transmitting variable is used to disable large parts of the system.
#define DRATE 6 // decimation rate used in MagPhase
#define F_SAMP_TX (44117/DRATE) // ! setting _UA and sample rate the same, removed scaling calculation
#define _UA (44117/DRATE) // match definition in MagPhase.cpp
int eer_count;
int eer_mode;
//int temp_count; // !!! debug
int eer_adj; // !!! debug
int overs; // I2C not ready for the next set of register data
// int saves; // short write bulk
// float eer_time = 90.680; //90.668; // us for each sample deci rate 4
float eer_time = 136.0; // 1/6 rate ( 1/6 of 44117 )
//float eer_time = 113.335; // 1/5 rate
struct EER {
int32_t m; // in mag and phase
int32_t p;
int32_t mag; // out mag and delta phase
int32_t dp;
};
void EER_function(){ // EER transmit interrupt function. Interval timer.
int c;
// static int prev_phase;
static int last_dp;
// static int dline[8]; // phase change delay
// static int din; // delay index
// int phase_;
int mag;
int dp;
//static int mod;
struct EER e;
if( MagPhase.available() == 0 ){ // start with 6 ms of buffered data( more now with 1/6 sample rate )
eer_count = 0;
last_dp = -1;
return;
}
// process Mag and Phase
e.m = MagPhase.mvalue(eer_count);
e.p = MagPhase.pvalue(eer_count);
e.mag = 0;
e.dp = 0;
// if( tx_source == MIC ) e.m = (float)e.m * tx_drive; moved this to TXSource to implement speech clipping
if( mode == DIGI ) eer_digi( &e );
else if( eer_mode == 1 ) eer_ssb( &e );
else eer_am( &e );
mag = constrain(e.mag,0,1024);
magp = mag;
if( DEBUG_MP != 1 ) analogWrite( KEYOUT, mag );
dp = constrain(e.dp, -3200, 3200 );
if( Wire.done() ){ // crash all: can't wait for I2C while in ISR
if( last_dp != dp ){ // save I2C bandwidth if same dp as last time
si5351.freq_calc_fast(dp);
si5351.SendPLLBRegisterBulk();
last_dp = dp;
}
}
else ++overs; // Out of time on I2C bus, count skipped I2C transactions
++eer_count;
eer_count &= ( AUDIO_BLOCK_SAMPLES - 1 );
// adjust timing. MagPhase data counter reported will be 0, 32, 64, 96.
// we want to be reading out the data two blocks behind ( we decimated by 4, these blocks are 32 in length )
// testing at eer_count == zero, this test happens once per 12ms.
// that is how it used to work. Now decimating by 6 and each 3ms block of 128 results in 21 or 22 samples.
// So we are 3 blocks behind but that doesn't really matter for this sync routine. We should still hit an index of 64
// in the middle of the buffered data. I2C couldn't keep up with decimation rates of 4 or 5, so using 6.
int u = 0;
if( eer_count == 0 ){
c = MagPhase.read_count();
//temp_count = c; // !!! debug
//if( c == 64 ) ; // two blocks delay is the goal
if( c < 64-8 ) eer_time += 0.0001, ++eer_adj, ++u; // slow down 64-8 for 1/4 1/6 versions. 76-8 for 1/5 rate.
if( c > 64+8 ) eer_time -= 0.0001, --eer_adj, ++u; // speed up 64-8 rates 1/4 and 1/6
// leak timer toward what we think is correct
if( eer_time > 136.01 ) eer_time -= 0.00001, ++u; // rate 1/6 version. version at 1/4 rate use 90.67 to 90.68.
if( eer_time < 135.99 ) eer_time += 0.00001, ++u;
//if( eer_time > 113.34 ) eer_time -= 0.00001, ++u; // rate 1/5 version
//if( eer_time < 113.33 ) eer_time += 0.00001, ++u; // use 76 +-8 as index to sync
if( u ) EER_timer.update( eer_time);
}
if( DEBUG_MP == 1 ){ // serial writes in an interrupt function
static int mod; // may cause other unintended issues. Loss of sync maybe.
++mod;
if( mod > 0 && mod < 50 /*|| trigger_ */){
Serial.print( last_dp ); Serial.write(' '); // testing, get a small slice of data
// Serial.print( rav_df ); Serial.write(' ');
// //Serial.print( php ); Serial.write(' ');
Serial.print( magp );
Serial.println();
}
if( mod > 2000 ) mod = 0;
}
}
void eer_ssb( struct EER *e ){
static int32_t prev_phase;
static int dline[8]; // phase change delay
static int din; // delay index
int32_t mag, dp;
static int rav_mag;
static int tx_stat;
mag = e->mag = e->m >> 5; // 10 bits
rav_mag = 27853 * rav_mag + 4915 * e->m;
rav_mag >>= 15;
dp = e->p - prev_phase;
prev_phase = e->p;
php = prev_phase; // testing variable only
if( dp < -_UA/2 ) dp += _UA;
// if( dp < -500 ) dp = 0; // fail safe, some audio image is normal
if( (rav_mag >> 5) < 40 ){ // avoid wideband hash when no audio to transmit
if( tx_stat == 1 ) --overs, tx_stat = 0, si5351.SendRegister(3, 0b11111111); // disable clock 2
}
else if( tx_stat == 0 ) --overs, tx_stat = 1, si5351.SendRegister(3, 0b11111011); // Enable clock 2
// implement the delay line for phasing
if( phase_delay > 0 ){
dline[din] = dp;
dp = dline[ (din + (8-phase_delay)) & 7 ];
++din;
din &= 7;
}
// delay mag to phase
if( phase_delay < 0 ){
dline[din] = mag;
e->mag = dline[ (din + (8+phase_delay)) & 7];
++din;
din &= 7;
}
if( mode == USB ) dp -= bfo; // weaver mode offset USB
else dp = -dp + bfo; // LSB
e->dp = dp;
}
/*
void eer_ssb( struct EER *e ){
static int32_t prev_phase;
static int32_t last_dp;
static int dline[8]; // phase change delay
static int din; // delay index
int32_t mag, dp;
static int rav_mag;
static int tx_stat;
mag = e->mag = e->m >> 5; // 10 bits
rav_mag = 27853 * rav_mag + 4915 * e->m;
rav_mag >>= 15;
dp = e->p - prev_phase;
prev_phase = e->p;
php = prev_phase; // !!! testing variable only
if( dp < -1000 ) dp += _UA; // allow some audio image to transmit, hilbert not perfect. -300
if( dp < _UA/2 ){ // avoid sending any large positive spikes that result from previous statement
if( (rav_mag >> 5) < 40 ){ // avoid wideband hash when no audio to transmit
// if( last_dp > 0 ) last_dp >>= 1; // move toward a low level carrier at zero freq
// if( last_dp < 0 ) ++last_dp;
//if( last_dp > 10 ) last_dp -= 10;
// if( last_dp < 3000 ) last_dp += 10;
dp = last_dp;
if( tx_stat == 1 ) --overs, tx_stat = 0, si5351.SendRegister(3, 0b11111111); // disable clock 2
}
else if( tx_stat == 0 ) --overs, tx_stat = 1, si5351.SendRegister(3, 0b11111011); // Enable clock 2
last_dp = dp;
}
//else dp = last_dp, mag = 0; // avoid large spikes that get through
else dp = 0; // what to do with stuff that is out of band
// implement the delay line for phasing
if( phase_delay > 0 ){
dline[din] = dp;
dp = dline[ (din + (8-phase_delay)) & 7 ];
++din;
din &= 7;
}
// delay mag to phase
if( phase_delay < 0 ){
dline[din] = mag;
e->mag = dline[ (din + (8+phase_delay)) & 7];
++din;
din &= 7;
}
if( mode == USB ) dp -= bfo; // weaver mode offset USB
else dp = -dp + bfo; // LSB
e->dp = dp;
}
*/
void eer_digi( struct EER *e ){
static int32_t rav_mag;
static int32_t rav_dp;
static int32_t prev_phase;
int dp;
rav_mag = 27853 * rav_mag + 4915 * e->m;
rav_mag >>= 15;
e->mag = rav_mag >> 5; // 10 bits
dp = e->p - prev_phase;
prev_phase = e->p;
php = prev_phase; // !!! testing printing phase
if( dp < 0 ) dp += _UA;
if( dp > 3200 ) dp = rav_dp;
rav_dp = 27853 * rav_dp + 4940 * dp; // r/c time constant recursive filter .85 .15, increased gain from 4915 to be on frequency
rav_dp >>= 15;
e->dp = rav_dp - bfo; // weaver tx offset for USB
}
void eer_am( struct EER *e ){ // modes AM UDSB LDSB
static int32_t rav_mag;
int32_t mag;
static int mod;
if( mode == AM ) e->dp = -2500; // AM was received +2500 off frequency
else if( mode == UDSB ) e->dp = -bfo; // Listen USB, tx AM
else e->dp = bfo; // Listen LSB, tx AM
//mag = e->m >> 6; // 1/2 signal level, when added below have 10 bits
mag = e->m >> 5; // AM seems to need more gain though
// controlled carrier AM
if( (rav_mag + mag) < 0 ) rav_mag = abs(mag);
rav_mag = constrain(rav_mag,0,512); // max carrier level is 1/2
++mod;
mod &= 15;
if( mod == 0 ) --rav_mag; // decay carrier level
mag = mag + rav_mag; // add signal to carrier level
mag = constrain(mag,0,1024);
e->mag = mag;
}
void setup() {
int contrast = 68;
pinMode( KEYOUT, OUTPUT );
digitalWriteFast( KEYOUT, LOW );
//pinMode( RX, OUTPUT );
//digitalWriteFast( RX, HIGH );
pinMode( RX, INPUT ); // let the 10k pullup to 5 volts as opposed to holding at 3.3 with output pin
pinMode( TXAUDIO_EN, OUTPUT );
digitalWriteFast( TXAUDIO_EN, LOW );
// A microphone jack and pre-amp have been added making the paddle inputs simpler than before. DAHpin no longer goes to the
// previous microphone circuit and no longer has a 10k pullup
pinMode( DAHpin, INPUT_PULLUP );
pinMode( DITpin, INPUT_PULLUP );
delay(1);
if( read_paddles() != 0 ){
key_mask = 0; // disable the hardware keyer and hardware PTT as there is a short on the paddle jack
pinMode( DAHpin, INPUT ); // remove any current through whatever is connnected
pinMode( DITpin, INPUT );
touch_key = 1; // turn on touch keyer/ptt
}
Serial.begin(1200); // usb serial, baud rate makes no difference. Argo V baud rate is 1200.
pinMode(EN_A,INPUT_PULLUP);
pinMode(EN_B,INPUT_PULLUP);
pinMode(EN_SW,INPUT_PULLUP);
analogWriteResolution(10);
i2init();
#ifdef USE_LCD
LCD.InitLCD(contrast);
LCD.setFont(SmallFont);
LCD.print((char *)("Version "),0,ROW5);
LCD.printNumF(VERSION,2,6*8,ROW5);
LCD.print((char*)("MIC PDL Phones"),0,ROW0);
#endif
#ifdef USE_OLED
OLD.InitLCD();
OLD.clrScr();
OLD.setFont(SmallFont);
OLD.print((char *)("Version "),0,ROW7);
OLD.printNumF(VERSION,2,6*8,ROW7);
OLD.print((char*)("MIC Paddles Phones"),0,ROW0);
//OLD.printNumI( Wire.getClock()/1000,0,ROW4);
#endif
delay( 4000 ); // jack wiring help screen will display
#ifdef USE_LCD
LCD.clrRow(0);
#endif
#ifdef USE_OLED
OLD.clrRow(0);
#endif
freq_display();
status_display();
encoder(); // pick up current position
// Audio Library setup
AudioNoInterrupts();
AudioMemory(40);
SSB.gain(1,1.0); // sub for USB
SSB.gain(2,-1.0);
SSB.gain(0,0.0);
SSB.gain(3,0.0);
set_tx_source();
set_af_gain(af_gain);
set_agc_gain(agc_gain);
filter = 3;
set_bandwidth();
CWdet.frequency(700,7); // 600,6 1000,10 etc... aim for 10ms sample times. Higher tones will be more accurate.(more samples)
amp1.gain(10.0); // more signal into the CW detector
Scope_det1.frequency(300);
Scope_det2.frequency(300*16);
Scope_det3.frequency(300*32);
Scope_det4.frequency(300*48);
AudioInterrupts();
if( screen_user == INFO ){
delay( 2000 ); // let version stay on screen for 2 seconds
menu_cleanup(); // erase and display again
info_headers();
}
if( screen_user == FFT_SCOPE ) Scope2.setmode( 1 );
}
// 0.54119610 butterworth Q's two cascade
// 1.3065630
// 0.51763809 butterworth Q's 3 cascade
// 0.70710678
// 1.9318517
void set_bandwidth( ){
int bw;
int hp; // where the hipass cutoff should be
int wv; // where we will put the weaver lowpass
bw = 3300; // remove warning uninitialized variable
switch( filter ){
case 0: bw = 300; break; // data duplicated from menu strings. Could be improved so that
case 1: bw = 900; break; // one doesn't need to maintain data in two places if changes are made.
case 2: bw = 2700; break;
case 3: bw = 3000; break;
case 4: bw = 3300; break;
case 5: bw = 3600; break;
}
if( mode == CW ){
wv = 2500;
hp = ( bw > 1000 ) ? 200 : 700 - bw/2;
bw = ( bw > 1000 ) ? bw : 700 + bw/2 ;
}
else if( mode == AM || mode == DIGI ) wv = 6000, hp = 100; // for digi mode, set weaver hole at 3k hz
else hp = 200, wv = 4000; // SSB
BandWidth.setHighpass(0,hp,0.70710678);
BandWidth.setLowpass(1,bw,0.51763809 + tone_);
BandWidth.setLowpass(2,bw,0.70710678 + tone_);
BandWidth.setLowpass(3,bw,1.9318517 + tone_/2);
set_Weaver_bandwidth(wv);
}
void set_attn2(){
if( attn2 == 0 ){
pinMode( ATTN2, INPUT ); // off RX high with pullup enables to receive normally