-
Notifications
You must be signed in to change notification settings - Fork 35
/
SI4735_2.8_TFT_SI5351_V3.3.ino
3124 lines (2835 loc) · 119 KB
/
SI4735_2.8_TFT_SI5351_V3.3.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
// V3.3 02-11-2021
// V3.2.6b 29-10-2021 5351 calibration
// V3.2.4 03-10-2021 100 Hz & 10 Hz added in SSB. Many changes in control interface. Bug support.
// SI5351 added, replacing crystal and also used as BFO. All steps and bandwidth per modulation
// are now stored in memory.
// V3.2.3 29-09-2021 Added Sprite buttons from Jim Yasuda.
// This sketch is based on the si4735 Library of Ricardo PU2CLR. Thanks for the very nice work.
// This sketch uses a 2.8 inch 240*320 touch-screen with ILI9341, ESP32 WROOM-32 and Rotary Encoder.
// The radio is fully controlled by the (Touch)Screen and Rotary Encoder
// This sketch uses the Rotary Encoder Class implementation from Ben Buxton (the source code is included
// together with this sketch).
// For the touch-screen the library TFT_eSPI is used. The configuration setup-file: setup1_ILI9341 is also
// included.
// Also a schematic drawing is available.
// ABOUT SSB PATCH:
// This sketch will download a SSB patch to your SI4735 device (patch_init.h). It will take about 8KB of the Arduino memory.
// In this context, a patch is a piece of software used to change the behavior of the SI4735 device.
// There is little information available about patching the SI4735. The following information is the understanding of the author of
// this project and it is not necessarily correct. A patch is executed internally (run by internal MCU) of the device.
// Usually, patches are used to fixes bugs or add improvements and new features of the firmware installed in the internal ROM of the device.
// Patches to the SI4735 are distributed in binary form and have to be transferred to the internal RAM of the device by
// the host MCU (in this case Arduino). Since the RAM is volatile memory, the patch stored into the device gets lost when you turn off the system.
// Consequently, the content of the patch has to be transferred again to the device each time after turn on the system or reset the device.
// ATTENTION: The author of this project does not guarantee that procedures shown here will work in your development environment.
// Given this, it is at your own risk to continue with the procedures suggested here.
// This library works with the I2C communication protocol and it is designed to apply a SSB extension PATCH to CI SI4735-D60.
// Once again, the author disclaims any liability for any damage this procedure may cause to your SI4735 or other devices that you are using.
//
// Library TFT_eSPI you may download from here : https://github.com/Bodmer/TFT_eSPI
// Library Rotary is provided with the program
// Library SI4735 you may download from here : https://github.com/pu2clr/SI4735
//
// *********************************
// ** Display connections etc. **
// *********************************
// |------------|------------------|------------|------------|------------|
// |Display 2.8 | ESP32 | Si4735 | Encoder | Beeper |
// | ILI9341 | | | | | Encoder 1,2,3
// |------------|------------------|------------|------------|------------| Encoder switch 4,5
// | Vcc | 3V3 | 01 | Vcc | | | pin 33 with 18K to 3.3 volt and 18K to ground.
// | GND | GND | 02 | GND | 2,4 | | pin 32 (Beeper) via 2K to base V1 BC547
// | CS | 15 | 03 | | | | Collector via beeper to 5v
// | Reset | 4 | 04 | | | | Emmitor to ground
// | D/C | 2 | 05 | | | |
// | SDI | 23 | 06 | | | | Encoder 1,2,3
// | SCK | 18 | 07 | | | | Encoder switch 4,5
// | LED Coll.| 14 2K | 08 | | | | Display LED
// | SDO | | 09 | | | | Emmitor V2 BC557 to 3.3 V
// | T_CLK | 18 | 10 | | | | Base with 2K to pin 14 (Display_Led)
// | T_CS | 5 | 11 | | | | Collector to led pin display
// | T_DIN | 23 | 12 | | | |
// | T_DO | 19 | 13 | | | |
// | T_IRQ | 34 | 14 | | | |
// | | 12 | | Reset | | |
// | | 21 | | SDA | | |
// | | 22 | | SCL | | |
// | | 16 | | | 1 | |
// | | 17 | | | 3 | |
// | | 33 | | | 5 | |
// | | 32 2K | | | | In |
// | | 27 Mute | |see schematics | |
// |------------|-------------|----|------------|------------|------------|
#include <TFT_eSPI.h>
#include <SPI.h>
#include <SI4735.h>
#include "EEPROM.h"
#include "Rotary.h"
#include <si5351wire.h>
#include "DSEG7_Classic_Mini_Regular_34.h"
#include "TFT_Colors.h"
#include "Button.h"
// ==================Display========================
//#define IhaveVertTFT
#define IhaveHoriTFT
// =================================================
// ==================Oscillator=====================
//#define IhaveCrystal
#define IhaveSI5351
// =================================================
//#include "patch_init.h" // SSB patch for whole SSBRX initialization string
#include "patch_full.h" // SSB patch for whole SSBRX full download
const uint16_t size_content = sizeof ssb_patch_content; // see ssb_patch_content in patch_full.h or patch_init.h
#define ESP32_I2C_SDA 21 // I2C bus pin on ESP32
#define ESP32_I2C_SCL 22 // I2C bus pin on ESP32
#define RESET_PIN 12
#define ENCODER_PIN_A 17 // http://www.buxtronix.net/2011/10/rotary-encoders-done-properly.html
#define ENCODER_PIN_B 16
#define ENCODER_SWITCH 33
#define BEEPER 32
#define Display_Led 14
#define displayon 0
#define displayoff 1
#define beepOn 1
#define beepOff 0
#define AUDIO_MUTE 27
#define FM_BAND_TYPE 0
#define MW_BAND_TYPE 1
#define SW_BAND_TYPE 2
#define LW_BAND_TYPE 3
#define MIN_ELAPSED_TIME 100
#define MIN_ELAPSED_RSSI_TIME 150
#define MIN_ELAPSED_AudMut_TIME 0 // Noise surpression SSB in mSec. 0 mSec = off
#define MIN_ELAPSED_DISPL_TIME 1000
#define MIN_ELAPSED_RDS_TIME 5
#define DEFAULT_VOLUME 45 // change it for your favorite start sound volume
#define MIN_ELAPSED_VOLbut_TIME 1000
#define CLK_Xtal SI5351wire_CLK0
#define FM 0
#define LSB 1
#define USB 2
#define AM 3
#define CW 4
#define TFT_GREY 0x5AEB
bool bfoOn = false;
bool ssbLoaded = false;
bool FirstLayer = true;
bool FirstTime = true;
bool SecondLayer = false;
bool ThirdLayer = false;
bool ForthLayer = false;
bool HamBand = false;
bool Modebut = false;
bool FREQbut = false;
bool Decipoint = false;
bool STEPbut = false;
bool encsw = false;
bool BroadBand;
bool BandWidth;
bool MISCbut = false;
bool PRESbut = false;
bool VOLbut = false;
bool AudioMut = false;
bool DISplay = false;
bool Mutestat = false;
bool AGCgainbut = false;
bool writingEeprom = false;
bool pressed;
bool presStat;
bool audioMuteOn = true;
bool audioMuteOff = false;
bool RDS = true; // RDS on or off
bool SEEK = false;
bool bright = false;
bool CWShift = false;
bool fstShift = false;
bool calibratSI5351 = false;
int currentBFO;
int currentBFOmanu;
int previousBFO = 0;
int previousBFOmanu = 0;
int nrbox = 0;
int OldRSSI;
int NewRSSI;
int NewSNR;
int encBut;
int AGCgain = 0;
int PrevRSSI = 0;
int strongup = 0;
long elapsedRSSI = millis();
long elapsedAudMut = millis();
long elapsedRDS = millis();
long stationNameElapsed = millis();
long DisplayOnTime = millis();
long VOLbutOnTime = millis();
volatile int encoderCount = 0;
volatile int encoderButton = 0;
uint16_t previousFrequency;
uint8_t currentBFOStep = 25;
uint8_t currentPRES = 0;
uint8_t previousPRES = 0;
uint8_t currentPRESStep = 1;
uint8_t currentAGCgain = 1;
uint8_t previousAGCgain = 1;
uint8_t currentAGCgainStep = 1;
uint8_t MaxAGCgain;
uint8_t MaxAGCgainFM = 26;
uint8_t MaxAGCgainAM = 37;
uint8_t MinAGCgain = 1;
uint8_t currentVOL = 0;
uint8_t previousVOL = 0;
uint8_t currentVOLStep = 1;
uint8_t MaxVOL = 63;
uint8_t MinVOL = 20;
uint8_t currentAGCAtt = 0;
uint8_t bwIdxSSB;
uint8_t bwIdxAM;
uint8_t bwIdxFM;
uint8_t ssIdxMW;
uint8_t ssIdxAM;
uint8_t ssIdxFM;
uint8_t bandIdx;
uint8_t currentMode = FM;
uint8_t previousMode = 0;
uint16_t x = 0, y = 0; // To store the touch coordinates
uint8_t encoderStatus;
uint16_t freqstep;
uint8_t freqstepnr = 0; //1kHz
int freqDec = 0;
const int LedFreq = 5000;
const int LedResol = 8;
const int LedChannelforTFT = 0;
uint16_t currentBrightness;
uint16_t previousBrightness;
uint16_t MaxBrightness = 20;
uint16_t MinBrightness = 250;
uint8_t stepsizesynth = 10;
float Displayfreq = 0;
float currentFrequency = 0;
float dpfrq = 0;
float fact = 1;
float RSSIfact = 3;
String BWtext;
String Modtext;
String RDSbuttext;
String AGCgainbuttext;
//===============================================================================
const char *bandwidthSSB[] = {"1.2", "2.2", "3.0", "4.0", "0.5", "1.0"};
const char *bandwidthAM[] = {"6.0", "4.0", "3.0", "2.0", "1.0", "1.8", "2.5"};
const char *bandwidthFM[] = {"AUT","110","84","60","40"};
const char *stepsize[] = {"1","5","9","10"};
const char *stepsizeFM[] = {"100","10"};
const char *Keypathtext[] = {"1", "2", "3", "4", "5", "6", "7", "8", "9", ".", "0", "Send", "Clear"};
const char *bandModeDesc[] = {"FM ", "LSB", "USB", "AM ", "CW"};
char buffer[64]; // Useful to handle string
char buffer1[64];
char *stationName;
char bufferStatioName[40];
unsigned long FreqSI5351 = 3276800;
unsigned long calibratvalSI5351;
//======================================================= Buttons First and Third Layer ==========================
typedef struct // Buttons first layer
{
const char *ButtonNam;
uint8_t ButtonNum; // Button location at display from 0 to 11. To move around buttons freely at first layer.
const char *ButtonNam1;
uint8_t ButtonNum1; // Button location at display from 0 to 11. To move around buttons freely at third layer.
uint16_t XButos; // Xoffset
long YButos; // Yoffset
} Button;
int ytotoffset = 0;
// Button table
int Xbutst = 0; // X Start location Buttons
int Ybutst = 160 + ytotoffset; // Y Start location Buttons
int Xsmtr = 0;
int Ysmtr = 80 + ytotoffset; // S meter 85
int XVolInd = 0;
int YVolInd = 135 + ytotoffset; // Volume indicator
int XFreqDispl = 0;
int YFreqDispl = 0 + ytotoffset; // display
int Xbutsiz = 80; //size of buttons first & third layer
int Ybutsiz = 40;
#ifdef IhaveVertTFT
uint16_t Xbut0 = 0 * Xbutsiz ; uint16_t Ybut0 = 0 * Ybutsiz; // location calqualation for 12 first layer buttons
uint16_t Xbut1 = 1 * Xbutsiz ; uint16_t Ybut1 = 0 * Ybutsiz;
uint16_t Xbut2 = 2 * Xbutsiz ; uint16_t Ybut2 = 0 * Ybutsiz;
uint16_t Xbut3 = 0 * Xbutsiz ; uint16_t Ybut3 = 1 * Ybutsiz;
uint16_t Xbut4 = 1 * Xbutsiz ; uint16_t Ybut4 = 1 * Ybutsiz;
uint16_t Xbut5 = 2 * Xbutsiz ; uint16_t Ybut5 = 1 * Ybutsiz;
uint16_t Xbut6 = 0 * Xbutsiz ; uint16_t Ybut6 = 2 * Ybutsiz;
uint16_t Xbut7 = 1 * Xbutsiz ; uint16_t Ybut7 = 2 * Ybutsiz;
uint16_t Xbut8 = 2 * Xbutsiz ; uint16_t Ybut8 = 2 * Ybutsiz;
uint16_t Xbut9 = 0 * Xbutsiz ; uint16_t Ybut9 = 3 * Ybutsiz;
uint16_t Xbut10 = 1 * Xbutsiz ; uint16_t Ybut10 = 3 * Ybutsiz;
uint16_t Xbut11 = 2 * Xbutsiz ; uint16_t Ybut11 = 3 * Ybutsiz;
#endif
#ifdef IhaveHoriTFT
uint16_t Xbut0 = 0 * Xbutsiz ; uint16_t Ybut0 = 0 * Ybutsiz; // location calqualation for 12 first layer buttons
uint16_t Xbut1 = 1 * Xbutsiz ; uint16_t Ybut1 = 0 * Ybutsiz;
uint16_t Xbut2 = 2 * Xbutsiz ; uint16_t Ybut2 = 0 * Ybutsiz;
uint16_t Xbut3 = 3 * Xbutsiz ; uint16_t Ybut3 = 0 * Ybutsiz;
uint16_t Xbut4 = 0 * Xbutsiz ; uint16_t Ybut4 = 1 * Ybutsiz;
uint16_t Xbut5 = 1 * Xbutsiz ; uint16_t Ybut5 = 1 * Ybutsiz;
uint16_t Xbut6 = 2 * Xbutsiz ; uint16_t Ybut6 = 1 * Ybutsiz;
uint16_t Xbut7 = 3 * Xbutsiz ; uint16_t Ybut7 = 1 * Ybutsiz;
uint16_t Xbut8 = 3 * Xbutsiz ; long Ybut8 = -4 * Ybutsiz;
uint16_t Xbut9 = 3 * Xbutsiz ; long Ybut9 = -3 * Ybutsiz;
uint16_t Xbut10 = 3 * Xbutsiz ; long Ybut10 = -2 * Ybutsiz;
uint16_t Xbut11 = 3 * Xbutsiz ; long Ybut11 = -1 * Ybutsiz;
#endif
#define HAM 0
#define BFO 1
#define FREQ 2
#define AGC 3
#define MUTE 4
#define VOL 5
#define MODE 6
#define BANDW 7
#define STEP 8
#define BROAD 9
#define PRESET 10
#define NEXT 11
#define SEEKUP 0
#define SEEKDN 1
#define STATUS 2
#define RDSbut 3
#define AGCset 4
#define NR5 5
#define Displbut 6
#define NR7 7
#define ChipType 8 // |----|
#define NR10 9 // | 8 |
#define NR9 10 // |----|
#define PREV 11 // | 9 |
// |----|
// | 10 |
#ifdef IhaveHoriTFT // |----|
Button bt[] = { // | 11 |
{ "HAM" , 0 , "SEEKUP", 0 , Xbut0 , Ybut0 }, // |----|----|----|----|
{ "BFO" , 4 , "SEEKDN", 4 , Xbut1 , Ybut1 }, // | 0 | 1 | 2 | 3 |
{ "FREQ" , 2 , "STATUS", 6 , Xbut2 , Ybut2 }, // |----|----|----|----|
{ "AGC" , 9 , "RDS" , 8 , Xbut3 , Ybut3 }, // | 4 | 5 | 6 | 7 |
{ "MUTE" , 8 , "AGCset", 1 , Xbut4 , Ybut4 }, // |----|----|----|----|
{ "VOL" , 5 , "" , 10 , Xbut5 , Ybut5 },
{ "MODE" , 3 , "DISPL" , 2 , Xbut6 , Ybut6 },
{ "BANDW" , 6 , "" , 11 , Xbut7 , Ybut7 },
{ "STEP" , 11 , "CHIP" , 3 , Xbut8 , Ybut8 },
{ "BROAD" , 1 , "" , 5 , Xbut9 , Ybut9 },
{ "PRESET", 10 , "" , 9 , Xbut10, Ybut10 },
{ "NEXT" , 7 , "PREV" , 7 , Xbut11, Ybut11 }
};
#endif
#ifdef IhaveVertTFT
Button bt[] = {
{ "HAM" , 0 , "SEEKUP", 0 , Xbut0 , Ybut0 }, // |----|----|----|
{ "BFO" , 3 , "SEEKDN", 3 , Xbut1 , Ybut1 }, // | 0 | 1 | 2 |
{ "FREQ" , 2 , "STATUS",10 , Xbut2 , Ybut2 }, // |----|----|----|
{ "AGC" , 4 , "RDS" , 9 , Xbut3 , Ybut3 }, // | 3 | 4 | 5 |
{ "MUTE" , 8 , "AGCset", 2 , Xbut4 , Ybut4 }, // |----|----|----|
{ "VOL" , 7 , "" , 5 , Xbut5 , Ybut5 }, // | 6 | 7 | 8 |
{ "MODE" , 9 , "Displ" , 6 , Xbut6 , Ybut6 }, // |----|----|----|
{ "BANDW" , 5 , "" , 7 , Xbut7 , Ybut7 }, // | 9 | 10 | 11 |
{ "STEP" , 6 , "CHIP" , 8 , Xbut8 , Ybut8 }, // |----|----|----|
{ "BROAD" , 1 , "" , 1 , Xbut9 , Ybut9 },
{ "PRESET", 10 , "" , 4 , Xbut10, Ybut10 },
{ "NEXT" , 11 , "PREV" ,11 , Xbut11, Ybut11 }
};
#endif
// You may freely move around the button (blue) position on the display to your flavour by changing the position in ButtonNum and ButtonNum1
// You have to stay in the First or Third Layer
//======================================================= End Buttons First and Third Layer ======================
//======================================================= Tunings Steps ===============================
typedef struct // Tuning steps
{
uint8_t stepFreq;
double stepFreqFM;
uint16_t Xstepos; //Xoffset
uint16_t Xstepsr; //X size rectang
uint16_t Ystepos; //Yoffset
uint16_t Ystepsr; //Y size rectang
uint16_t Ystepnr; //Y next rectang
} Step;
// Tuning steps table
#ifdef IhaveHoriTFT
uint16_t Xfstep = 110;
uint16_t Yfstep = 60;
#endif
#ifdef IhaveVertTFT
uint16_t Xfstep = 70;
uint16_t Yfstep = 100;
#endif
Step sp[] = {
{ 1 , 10 ,Xfstep, 100, Yfstep, 30, 0},
{ 5 , 1 ,Xfstep, 100, Yfstep, 30, 30},
{ 9 , 0 ,Xfstep, 100, Yfstep, 30, 60},
{ 10, 0 ,Xfstep, 100, Yfstep, 30, 90}
};
//======================================================= End Tunings Steps ===============================
//======================================================= Modulation Types ================================
typedef struct // MODULATION
{
uint16_t Modenum;
uint16_t Xmodos; //Xoffset
uint16_t Xmodsr; //X size rectang
uint16_t Ymodos; //Yoffset
uint16_t Ymodsr; //Y size rectang
uint16_t Ymodnr; //Y next rectang
} Mode;
// Modulation table
#ifdef IhaveHoriTFT
uint16_t Xfmod = 110;
uint16_t Yfmod = 45;
#endif
#ifdef IhaveVertTFT
uint16_t Xfmod = 70;
uint16_t Yfmod = 90;
#endif
Mode md[] = {
{ 0 , Xfmod, 100, Yfmod, 30, 0},
{ 1 , Xfmod, 100, Yfmod, 30, 30},
{ 2 , Xfmod, 100, Yfmod, 30, 60},
{ 3 , Xfmod, 100, Yfmod, 30, 90},
{ 4 , Xfmod, 100, Yfmod, 30,120}
};
//======================================================= End Modulation Types ============================
//======================================================= Keypath =========================================
typedef struct // Keypath
{
uint16_t KeypNum;
uint16_t Xkeypos; //Xoffset
uint16_t Xkeypsr; //X size rectang
uint16_t Xkeypnr; //Y next rectang
uint16_t Ykeypos; //Yoffset
uint16_t Ykeypsr; //X size rectang
uint16_t Ykeypnr; //Y next rectang
} Keypath;
// Keypath table
#ifdef IhaveHoriTFT
uint16_t Xpath = 82;
uint16_t Ypath = 20;
Keypath kp[] = {
{ 0 , Xpath, 50 , 0 , Ypath , 50 , 0},
{ 1 , Xpath, 50 , 50 , Ypath , 50 , 0},
{ 2 , Xpath, 50 , 100 , Ypath , 50 , 0},
{ 3 , Xpath, 50 , 0 , Ypath , 50 , 50},
{ 4 , Xpath, 50 , 50 , Ypath , 50 , 50},
{ 5 , Xpath, 50 , 100 , Ypath , 50 , 50},
{ 6 , Xpath, 50 , 0 , Ypath , 50 , 100},
{ 7 , Xpath, 50 , 50 , Ypath , 50 , 100},
{ 8 , Xpath, 50 , 100 , Ypath , 50 , 100},
{ 9 , Xpath, 50 , 0 , Ypath , 50 , 150},
{ 10 , Xpath, 50 , 50 , Ypath , 50 , 150},
{ 11 , Xpath, 50 , 100 , Ypath , 50 , 150},
};
#endif
#ifdef IhaveVertTFT
uint16_t Xpath = 35;
uint16_t Ypath = 47;
Keypath kp[] = {
{ 0 , Xpath, 60 , 0 , Ypath , 60 , 0},
{ 1 , Xpath, 60 , 60 , Ypath , 60 , 0},
{ 2 , Xpath, 60 , 120 , Ypath , 60 , 0},
{ 3 , Xpath, 60 , 0 , Ypath , 60 , 60},
{ 4 , Xpath, 60 , 60 , Ypath , 60 , 60},
{ 5 , Xpath, 60 , 120 , Ypath , 60 , 60},
{ 6 , Xpath, 60 , 0 , Ypath , 60 , 120},
{ 7 , Xpath, 60 , 60 , Ypath , 60 , 120},
{ 8 , Xpath, 60 , 120 , Ypath , 60 , 120},
{ 9 , Xpath, 60 , 0 , Ypath , 60 , 180},
{ 10 , Xpath, 60 , 60 , Ypath , 60 , 180},
{ 11 , Xpath, 60 , 120 , Ypath , 60 , 180},
};
#endif
//======================================================= End Keypath =====================================
//======================================================= Bandwidth AM, SSB, FM ===============================
typedef struct // Bandwidth AM & SSB & FM
{
uint16_t BandWidthAM;
uint16_t BandWidthSSB;
uint16_t BandWidthFM;
uint16_t Xos; //Xoffset
uint16_t Xsr; //X size rectang
uint16_t Yos; //Yoffset
uint16_t Ysr; //X size rectang
uint16_t Ynr; //Y next rectang
} Bandwidth;
// Bandwidth table
#ifdef IhaveHoriTFT
uint16_t XfBW = 110;
uint16_t YfBW = 20;
#endif
#ifdef IhaveVertTFT
uint16_t XfBW = 70;
uint16_t YfBW = 40;
#endif
Bandwidth bw[] = { // AM SSB FM
{ 4 , 4 , 0 , XfBW, 100, YfBW, 30, 0}, // 1.0 0.5 Aut
{ 5 , 5 , 1 , XfBW, 100, YfBW, 30, 30}, // 1.8 1.0 110
{ 3 , 0 , 2 , XfBW, 100, YfBW, 30, 60}, // 2.0 1.2 84
{ 6 , 1 , 3 , XfBW, 100, YfBW, 30, 90}, // 2.5 2.2 60
{ 2 , 2 , 4 , XfBW, 100, YfBW, 30, 120}, // 3.0 3.0 40
{ 1 , 3 , 0 , XfBW, 100, YfBW, 30, 150}, // 4.0 4.0 ---
{ 0 , 0 , 0 , XfBW, 100, YfBW, 30, 180} // 6.0 --- ---
};
//======================================================= End Bandwidth AM & FM & SSB ===========================
//======================================================= Broad Band Definitions ==========================
typedef struct // Broad-Band switch
{
uint16_t BbandNum; // bandIdx
uint16_t Xbbandos; //Xoffset
uint16_t Xbbandsr; //X size rectang
uint16_t Xbbandnr; //X next rectang
uint16_t Ybbandos; //Yoffset
uint16_t Ybbandsr; //X size rectang
uint16_t Ybbandnr; //Y next rectang
} BBandnumber;
// Bandnumber table for the broad-bands
#ifdef IhaveVertTFT
uint16_t Xfbband = 0;
uint16_t Yfbband = 45;
#endif
#ifdef IhaveHoriTFT
uint16_t Xfbband = 40;
uint16_t Yfbband = 15;
#endif
BBandnumber bb[] = {
{ 0 , Xfbband, 80 , 0 , Yfbband , 30 , 0}, // 0
{ 1 , Xfbband, 80 , 0 , Yfbband , 30 , 30}, // 1
{ 2 , Xfbband, 80 , 0 , Yfbband , 30 , 60}, // 2
{ 6 , Xfbband, 80 , 0 , Yfbband , 30 , 90}, // 3
{ 7 , Xfbband, 80 , 0 , Yfbband , 30 , 120}, // 4
{ 9 , Xfbband, 80 , 0 , Yfbband , 30 , 150}, // 5
{ 11 , Xfbband, 80 , 0 , Yfbband , 30 , 180}, // 6
{ 13 , Xfbband, 80 , 80 , Yfbband , 30 , 0}, // 7
{ 14 , Xfbband, 80 , 80 , Yfbband , 30 , 30}, // 8
{ 16 , Xfbband, 80 , 80 , Yfbband , 30 , 60}, // 9
{ 17 , Xfbband, 80 , 80 , Yfbband , 30 , 90}, //10
{ 19 , Xfbband, 80 , 80 , Yfbband , 30 , 120}, //11
{ 21 , Xfbband, 80 , 80 , Yfbband , 30 , 150}, //12
{ 22 , Xfbband, 80 , 80 , Yfbband , 30 , 180}, //13
{ 24 , Xfbband, 80 , 160 , Yfbband , 30 , 0}, //14
{ 26 , Xfbband, 80 , 160 , Yfbband , 30 , 30}, //15
{ 27 , Xfbband, 80 , 160 , Yfbband , 30 , 60}, //16
{ 29 , Xfbband, 80 , 160 , Yfbband , 30 , 90} //17
};
//======================================================= End Broad Band Definitions ======================
//======================================================= Ham Band Definitions ============================
typedef struct // Ham Band switch
{
uint16_t BandNum; // bandIdx
uint16_t HamBandTxt;
uint16_t Xbandos; //Xoffset
uint16_t Xbandsr; //X size rectang
uint16_t Xbandnr; //X next rectang
uint16_t Ybandos; //Yoffset
uint16_t Ybandsr; //Y size rectang
uint16_t Ybandnr; //Y next rectang
} Bandnumber;
// Bandnumber table for the hambands
#ifdef IhaveVertTFT
uint16_t Xfband = 10;
uint16_t Yfband = 30;
#endif
#ifdef IhaveHoriTFT
uint16_t Xfband = 50;
uint16_t Yfband = 30;
#endif
Bandnumber bn[] = {
{ 3 , 0 , Xfband, 110 , 0 , Yfband , 30 , 0},
{ 4 , 1 , Xfband, 110 , 0 , Yfband , 30 , 30},
{ 5 , 2 , Xfband, 110 , 0 , Yfband , 30 , 60},
{ 8 , 3 , Xfband, 110 , 0 , Yfband , 30 , 90},
{ 10 , 4 , Xfband, 110 , 0 , Yfband , 30 , 120},
{ 12 , 5 , Xfband, 110 , 0 , Yfband , 30 , 150},
{ 15 , 6 , Xfband, 110 , 110 , Yfband , 30 , 0},
{ 18 , 7 , Xfband, 110 , 110 , Yfband , 30 , 30},
{ 20 , 8 , Xfband, 110 , 110 , Yfband , 30 , 60},
{ 23 , 9 , Xfband, 110 , 110 , Yfband , 30 , 90},
{ 25 , 10 , Xfband, 110 , 110 , Yfband , 30 , 120},
{ 28 , 11 , Xfband, 110 , 110 , Yfband , 30 , 150}
};
//======================================================= End Ham Band Definitions ========================
//======================================================= THE Band Definitions ============================
typedef struct // Band data
{
const char *bandName; // Bandname
uint8_t bandType; // Band type (FM, MW or SW)
uint16_t prefmod; // Pref. modulation
uint16_t minimumFreq; // Minimum frequency of the band
uint16_t maximumFreq; // maximum frequency of the band
uint16_t currentFreq; // Default frequency or current frequency
uint8_t currentStep; // Default step (increment and decrement)
int lastBFO ; // Last BFO per band
} Band;
// Band table
Band band[] = {
{ "FM", FM_BAND_TYPE, FM, 8750, 10800, 8930, 10, 0}, // FM 0
{ "LW", LW_BAND_TYPE, AM, 130, 279, 198, 9, 0}, // LW 1
{ "MW", MW_BAND_TYPE, AM, 522, 1701, 1395, 9, 0}, // MW 2
{"BACON", LW_BAND_TYPE, AM, 280, 470, 284, 1, 0}, // Ham 3
{ "630M", SW_BAND_TYPE, LSB, 472, 479, 475, 1, 0}, // Ham 630M 4
{ "160M", SW_BAND_TYPE, LSB, 1800, 1910, 1899, 1, 0}, // Ham 160M 5
{ "120M", SW_BAND_TYPE, AM, 2300, 2495, 2400, 5, 0}, // 120M 6
{ "90M", SW_BAND_TYPE, AM, 3200, 3400, 3300, 5, 0}, // 90M 7
{ "80M", SW_BAND_TYPE, LSB, 3500, 3800, 3630, 1, 0}, // Ham 80M 8
{ "75M", SW_BAND_TYPE, AM, 3900, 4000, 3950, 5, 0}, // 75M 9
{ "60M", SW_BAND_TYPE, USB, 5330, 5410, 5375, 1, 0}, // Ham 60M 10
{ "49M", SW_BAND_TYPE, AM, 5900, 6200, 6000, 5, 0}, // 49M 11
{ "40M", SW_BAND_TYPE, LSB, 7000, 7200, 7185, 1, 0}, // Ham 40M 12
{ "41M", SW_BAND_TYPE, AM, 7200, 7450, 7210, 5, 0}, // 41M 13
{ "31M", SW_BAND_TYPE, AM, 9400, 9900, 9600, 5, 0}, // 31M 14
{ "30M", SW_BAND_TYPE, USB, 10100, 10150, 10125, 1, 0}, // Ham 30M 15
{ "25M", SW_BAND_TYPE, AM, 11600, 12100, 11700, 5, 0}, // 25M 16
{ "22M", SW_BAND_TYPE, AM, 13570, 13870, 13700, 5, 0}, // 22M 17
{ "20M", SW_BAND_TYPE, USB, 14000, 14350, 14250, 1, 0}, // Ham 20M 18
{ "19M", SW_BAND_TYPE, AM, 15100, 15830, 15700, 5, 0}, // 19M 19
{ "17M", SW_BAND_TYPE, USB, 18068, 18168, 18100, 1, 0}, // Ham 17M 20
{ "16M", SW_BAND_TYPE, AM, 17480, 17900, 17600, 5, 0}, // 16M 21
{ "15M", SW_BAND_TYPE, AM, 18900, 19020, 18950, 5, 0}, // 15M 22
{ "15M", SW_BAND_TYPE, USB, 21000, 21450, 21350, 1, 0}, // Ham 15M 23
{ "13M", SW_BAND_TYPE, AM, 21450, 21850, 21500, 5, 0}, // 13M 24
{ "12M", SW_BAND_TYPE, USB, 24890, 24990, 24940, 1, 0}, // Ham 12M 25
{ "11M", SW_BAND_TYPE, AM, 25670, 26100, 25800, 5, 0}, // 11M 26
{ "CB", SW_BAND_TYPE, AM, 26200, 27990, 27200, 1, 0}, // CB band 27
{ "10M", SW_BAND_TYPE, USB, 28000, 30000, 28500, 1, 0}, // Ham 10M 28
{ "SW", SW_BAND_TYPE, AM, 1730, 30000, 15500, 5, 0} // Whole SW 29
};
//======================================================= End THE Band Definitions ========================
//======================================================= FM Presets ======================================
typedef struct // Preset data
{
float presetIdx;
const char *PresetName;
} FM_Preset ;
FM_Preset preset[] = {
8930 , "West", // 00 West
9890 , "NPO R1", // 01 NPO R1
9260 , "NPO R2", // 02 NPO R2
9680 , "NPO R3-FM", // 03 NPO R3-FM
9470 , "NPO R4", // 04 NPO R4
9340 , "RIJNMOND", // 05 RIJNMOND
9050 , "SUBLIME", // 06 SUBLIME
9130 , "BNR", // 07 BNR
9520 , "SLAM", // 08 SLAM
9620 , "ZFM", // 09 ZFM
9760 , "DECIBEL", // 10 DECIBEL
10040 , "QMUSIC", // 11 QMUSIC
10150 , "SKYRADIO", // 12 SKYRADIO
10270 , "RADIO 538", // 13 RADIO 538
10320 , "VERONICA", // 14 VERONICA
10380 , "RADIO 10", // 15 RADIO 10
10460 , "100% NL", // 16 100% NL
9220 , "L-FM", // 17 L-FM
10760 , "FEELGOOD" // 18 FEELGOOD Radio
};
//======================================================= END FM Presets ======================================
//======================================================= Tuning Digit selection ====================
typedef struct // Tuning digit
{
uint8_t digit;
uint16_t Xdignumos; //Xoffset
uint16_t Xdignumsr; //X size rectang
uint16_t Ydignumos; //Yoffset
uint16_t Ydignumsr; //Y size rectang
uint16_t Xdignumnr; //X next rectang
} DigNum;
uint8_t Xdignum = 139;
uint8_t Ydignum = 25;
// Tuning digit table
DigNum dn[] = {
{ 0 ,Xdignum, 21, Ydignum, 35, 0},
{ 1 ,Xdignum, 21, Ydignum, 35, 30},
{ 2 ,Xdignum, 21, Ydignum, 35, 59}
};
//======================================================= End Tuning Digit selection ===============================
const int lastButton = (sizeof bt / sizeof(Button)) - 1;
const int lastBand = (sizeof band / sizeof(Band)) - 1;
const int lastHam = (sizeof bn / sizeof(Bandnumber)) - 1;
const int lastBroad = (sizeof bb / sizeof(BBandnumber)) - 1;
const int lastMod = (sizeof md / sizeof(Mode)) - 1;
const int lastBW = (sizeof bw / sizeof(Bandwidth)) - 1;
const int lastStep = (sizeof sp / sizeof(Step)) - 1;
const int lastdignum = (sizeof dn / sizeof(DigNum)) - 1;
const int lastKPath = (sizeof kp / sizeof(Keypath)) - 1;
const int lastPreset = (sizeof preset / sizeof (FM_Preset)) - 1;
#define offsetEEPROM 0x20
#define EEPROM_SIZE 265
struct StoreStruct {
byte chkDigit;
byte bandIdx;
uint16_t Freq;
uint8_t currentMode;
uint8_t bwIdxSSB;
uint8_t bwIdxAM;
uint8_t bwIdxFM;
uint8_t ssIdxMW;
uint8_t ssIdxAM;
uint8_t ssIdxFM;
int currentBFO;
int currentBFOmanu;
uint8_t currentAGCAtt;
uint8_t currentVOL;
uint8_t currentBFOStep;
uint8_t RDS;
unsigned long FreqSI5351;
uint16_t currentBrightness;
uint8_t currentAGCgain;
unsigned long calibratvalSI5351;
};
StoreStruct storage = {
'A', //First time check
0, //bandIdx
8930, //Freq
0, //mode
1, //bwIdxSSB
1, //bwIdxAM
0, //bwIdxFM
9, //ssIdxMW
5, //ssIdxAM
10, //ssIdxFM
0, //currentBFO
0, //currentBFOmanu
2, //currentAGCAtt
45, //currentVOL
25, //currentBFOStep
1, //RDS
3276800, //FreqSI5351
20, //currentBrightness
1, //currentAGCgain
0 //calibratvalSI5351
};
uint8_t rssi = 0;
uint8_t stereo = 1;
uint8_t volume = DEFAULT_VOLUME;
// Devices class declarations
Rotary encoder = Rotary(ENCODER_PIN_A, ENCODER_PIN_B);
TFT_eSPI tft = TFT_eSPI();
TFT_eSprite spr = TFT_eSprite(&tft);
SI4735 si4735;
Si5351wire si5351wire;
//=======================================================================================
void IRAM_ATTR RotaryEncFreq() {
//=======================================================================================
// rotary encoder events
if (!writingEeprom) {
encoderStatus = encoder.process();
if (encoderStatus)
{
if (encoderStatus == DIR_CW)// Direction clockwise
{
encoderCount = 1;
}
else
{
encoderCount = -1;
}
}
}
}
//=======================================================================================
void setup() {
//=======================================================================================
Serial.begin(115200);
pinMode(Display_Led, OUTPUT);
pinMode(BEEPER, OUTPUT);
digitalWrite(Display_Led, displayon);
DISplay = true;
//Wire.begin(ESP32_I2C_SDA, ESP32_I2C_SCL); //I2C for SI4735
ledcSetup(LedChannelforTFT, LedFreq, LedResol);
ledcAttachPin(Display_Led, LedChannelforTFT);
int16_t si4735Addr = si4735.getDeviceI2CAddress(RESET_PIN);
Beep(1, 200);
tft.init();
//tft.setRotation(0); // Rotate 0
//tft.setRotation(1); // Rotate 90
//tft.setRotation(2); // Rotate 180
//tft.setRotation(3); // Rotate 270
#ifdef IhaveVertTFT
// Calibration code for touchscreen : for 2.8 inch & Rotation = 2
tft.setRotation(2);
uint16_t calData[5] = { 258, 3566, 413, 3512, 2 };
tft.setTouch(calData);
#endif
#ifdef IhaveHoriTFT
// Calibration code for touchscreen : Rotation = 1
tft.setRotation(1);
uint16_t calData[5] = { 387, 3530, 246, 3555, 7 };
tft.setTouch(calData);
#endif
#ifdef IhaveSI5351
si5351wire.output_enable(CLK_Xtal, 1);
if (si5351wire.init(SI5351wire_CRYSTAL_LOAD_8PF, CLK_Xtal, 0) == false)
{
Serial.println ( "SI5351 not found" );
}
//si5351wire.set_freq(1000000000UL, CLK_Xtal); // used for calibrating 10MHz
si5351wire.set_correction(0, SI5351wire_PLL_INPUT_XO);
//si5351wire.set_correction(26613UL, SI5351wire_PLL_INPUT_XO); // Calibration example with 10 MHz replace 26613UL with your figure.
si5351wire.set_freq(FreqSI5351, CLK_Xtal);
#endif
if (!EEPROM.begin(EEPROM_SIZE))
{
tft.fillScreen(TFT_BLACK);
tft.setCursor(0, 0);
tft.println(F("failed to initialise EEPROM"));
Serial.println(F("failed to initialise EEPROM"));
while (1);
}
if (EEPROM.read(offsetEEPROM) != storage.chkDigit) {
Serial.println(F("Writing defaults...."));
saveConfig();
}
loadConfig();
printConfig();
//Wire.begin(ESP32_I2C_SDA, ESP32_I2C_SCL); //I2C for SI4735
// Encoder pins
pinMode(ENCODER_PIN_A , INPUT_PULLUP); //Rotary encoder Freqency/bfo/preset
pinMode(ENCODER_PIN_B , INPUT_PULLUP);
// Encoder interrupt
attachInterrupt(digitalPinToInterrupt(ENCODER_PIN_A), RotaryEncFreq, CHANGE);
attachInterrupt(digitalPinToInterrupt(ENCODER_PIN_B), RotaryEncFreq, CHANGE);
si4735.setAudioMuteMcuPin(AUDIO_MUTE);
tft.fillScreen(TFT_BLACK);
delay(500);
tft.setCursor(7, 50);
tft.setTextSize(2);
tft.setTextColor(TFT_YELLOW, TFT_BLACK);
Serial.println(" SI4735/32 Radio");
Serial.println("Version 3.3 02-11-2021");
tft.println("SI4735/32 Radio");
tft.setCursor(7, 70);
tft.println(" Version 3.3");
tft.setCursor(7, 95);
tft.println(" 02-11-2021");
tft.setTextColor(TFT_BLUE, TFT_BLACK);
tft.setCursor(7, 170);
delay(1000);
tft.setTextColor(TFT_GREEN, TFT_BLACK);
if ( si4735Addr == 0 ) {
tft.setTextColor(TFT_RED, TFT_BLACK);
tft.print("Si4735 not detected");
Serial.println("Si4735 not detected");
while (1);
} else {
tft.setTextColor(TFT_GREEN, TFT_BLACK);
tft.print("Si473X addr : ");
tft.println(si4735Addr, HEX);
}
delay(1500);
if (si4735Addr == 17)
{
si4735.setDeviceI2CAddress(0);
}
else
{
si4735.setDeviceI2CAddress(1);
}
// Setup the radio from last setup in EEPROM
bandIdx = storage.bandIdx;
band[bandIdx].currentFreq = storage.Freq;
currentMode = storage.currentMode;
bwIdxSSB = storage.bwIdxSSB; // band width
bwIdxAM = storage.bwIdxAM;
bwIdxFM = storage.bwIdxFM;
ssIdxMW = storage.ssIdxMW; // step size
ssIdxAM = storage.ssIdxAM;
ssIdxFM = storage.ssIdxFM;
currentBFO = storage.currentBFO;
currentBFOmanu = storage.currentBFOmanu;
currentAGCAtt = storage.currentAGCAtt;
currentVOL = storage.currentVOL;
currentBFOStep = storage.currentBFOStep;
RDS = storage.RDS;
FreqSI5351 = storage.FreqSI5351;
currentBrightness = storage.currentBrightness;
currentAGCgain = storage.currentAGCgain;
calibratvalSI5351 = storage.calibratvalSI5351;
#ifdef IhaveCrystal
if (bandIdx == 0) si4735.setup(RESET_PIN, FM_BAND_TYPE); //Start in FM
else si4735.setup(RESET_PIN, 1);
if (bandIdx != 0) si4735.setAM(); // Start in AM
#endif
#ifdef IhaveSI5351
si5351wire.set_freq(FreqSI5351, CLK_Xtal);
si4735.setRefClock(32768);
si4735.setRefClockPrescaler(1); // will work with 32768 Hz
if (bandIdx == 0) si4735.setup(RESET_PIN, -1, POWER_UP_FM, SI473X_ANALOG_AUDIO, XOSCEN_RCLK); // Start in FM
else si4735.setup(RESET_PIN, -1, POWER_UP_AM, SI473X_ANALOG_AUDIO, XOSCEN_RCLK); // Start in AM
if (bandIdx != 0) si4735.setAM();
#endif
ledcWrite(LedChannelforTFT, currentBrightness);
freqstep = 1000;//hz
previousBFO = -1;
band[bandIdx].lastBFO = currentBFO;
freqDec = currentBFO;
band[bandIdx].prefmod = currentMode;
si4735.setVolume(currentVOL);
previousVOL = currentVOL;
previousAGCgain = currentAGCgain;
BandSet();
currentFrequency = previousFrequency = band[bandIdx].currentFreq;
Beep(2, 200);
encBut = 600;
x = y = 0;
DrawFila();
si4735.setSeekFmSpacing(10);
si4735.setSeekFmLimits(8750, 10800);
si4735.setSeekAmRssiThreshold(50);
si4735.setSeekAmSrnThreshold(20);
si4735.setSeekFmRssiThreshold(5);
si4735.setSeekFmSrnThreshold(5);