-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathSI4735_2.8_TFT_SI5351_V.5.2b.ino
6453 lines (6040 loc) · 250 KB
/
SI4735_2.8_TFT_SI5351_V.5.2b.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
// V.5.2b 17.09.2022 Added a squelch function By Lyle Hancock. Replaced the "CHIP" button with "SQLCH"
// V.5.2a 15.05.2022 Fully RDS services - RDS Station name - RDS News & info - RDS Time station Mod.by IU4ALH ;
// led colors on S-Meter bar
// V4.0 23-02-2022 Binns MOD full rebuilding design and functionaly. See owerview on youtube channel:
// V3.4 24-11-2021 Bug support.
// V3.4 24-11-2021 Memory added for BFO in each band when crystal is in use.
// 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:
// First of all, it is important to say that the SSB patch content is not part of this library. The paches used here were made available by Mr.
// Vadim Afonkin on his Dropbox repository. It is important to note that the author of the SI473x library does not encourage anyone to use the SSB patches
// content for commercial purposes. In other words, this library only supports SSB patches, the patches themselves are not part of this library.
// 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, like an ATS-25 that you are using.
// This sketch SHOULD work with the Chinese KIT ATS-25 sold on AliExpress, eBay etc.
// The author of this sketch and Arduino Library does not know the seller of this kit and does not have a commercial relationship with any commercial product that uses the Arduino Library.
// It is important you understand that there is no guarantee that this sketch will work correctly in your current product.
// SO, DO NOT TRY IT IF YOU DON'T KNOW WHAT ARE YOU DOING. YOU MUST BE ABLE TO GO BACK TO THE PREVIOUS VERSION IF THIS SKETCH DOES NOT WORK FOR YOU.
// 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 | |
// |------------|-------------|----|------------|------------|------------|
// =====================PINS========================
#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 BAT_INFO 35
#define BEEPER 32
#define DISPLAY_LED 14
#define AUDIO_MUTE 27
// =================================================
// ====================Display======================
// Rotate 0 // vertical 0 // Calibration code for touchscreen : for 2.8 inch // { 387, 3530, 246, 3555, 4 }
// Rotate 90 // horizontal 1 // Calibration code for touchscreen : for 2.8 inch // { 387, 3530, 246, 3555, 7 }
// Rotate 180 // vertical 2 // Calibration code for touchscreen : for 2.8 inch // { 258, 3566, 413, 3512, 2 }
// Rotate 270 // horizontal 3 // Calibration code for touchscreen : for 2.8 inch // { 387, 3530, 246, 3555, 1 }
// #define SCREEN_V 0
#define SCREEN_H 1
uint16_t calDataV[5] = { 258, 3566, 413, 3512, 4 };
uint16_t calDataH[5] = { 387, 3530, 246, 3555, 7 };
// =================================================
// ==================Oscillator=====================
#define IhaveCrystal
//#define IhaveSI5351
// =================================================
//---------------------------------TFT RUS-------------------------------
#include "Tahoma_10x12_ru.h"
#include "Tahoma_15x16_ru.h"
//tftRusColor
#define TFT_TRANS -1 //прозрачный цвет
//tftRusDatum
#define BL_T -1 //выравнивание влево
#define BC_T 0 //выравнивание по центру
#define BR_T 1 //вравнивание вправо
//tftRusStyle
#define REG_T 0 //обычный
#define BOL_T 1 //жирный
#define NRG_T 2 //плотный
#define NBL_T 3 //плотный жирный
#define CUR_T 4 //курсив
#define CUB_T 5 //жирный курсив
#define NCR_T 6 //плотный курсив
#define NCB_T 7 //плотный жирный курсив
//tftRusFont
#define T1012_T 0 //шрифт Tahoma_10x12_ru
#define T1516_T 1 //шрифт Tahoma_15x16_ru
//по умолчанию
float tftRusSize = 1; //размер шрифта
uint16_t tftRusColor = 0xFFFF; //цвет шрифта белый
int32_t tftRusBack = 0x0000; //цвет фона черный
int tftRusDatum = 0; //выравнивание по центру
int tftRusStyle = 0; //обычный шрифт
int tftRusFont = 0; //шрифт
int tftRusBeginChar = 0; //начать вывод с символа номер
int tftRusContChar = 0; //количество символов для вывода. 0 - все
int tftRusWidth = 10; //текущая ширина символоа
bool tftRusBottomCut = false; //отрез ниже линии письма
int tftRusCursiveLevel = 4; //степень наклона курсива 1 - сильный, 2 - средний, 4 - слабый
//-----------------------------END TFT RUS-------------------------------
#include <TFT_eSPI.h>
#include <SPI.h>
#include <SI4735.h>
#include "EEPROM.h"
#include "Rotary.h"
#ifdef IhaveSI5351
//#include <si5351wire.h>
#endif
#include "DSEG7_Classic_Mini_Regular_34.h"
#include "TFT_Colors.h"
#include "Button.h"
#include "logo.h"
//======================================================= BUTTON ===========================================
#define B_NORMAL 0
#define B_JAM 1
#define B_SELECT 2
#define B_BLOCK 3
struct But {
const uint8_t num;
const uint8_t layout;
const uint8_t type;
const char *Name;
const uint16_t xPosV;
const uint16_t yPosV;
const uint16_t xPosH;
const uint16_t yPosH;
};
#include "key.h"
const int lastBut = (sizeof but / sizeof(But)) - 1;
bool butBlock[lastBut + 1];
//======================================================= Retro Bands ===================================
typedef struct // Retro bands data
{
const char *BandName;
const char *BandNameRU;
const char *RetroBandTime;
const char *RetroBandTimeRU;
const uint16_t xPosV;
const uint16_t yPosV;
const uint16_t xPosH;
const uint16_t yPosH;
const int band;
const float minimumFreq;
const float maximumFreq;
float currentFreq;
const float scale; //pixels in one freq
const float mark; //digit marks on scale in one freq
const float hardStep;
const float softStep;
} RetroBand ;
RetroBand bandRetro[] {
"FM", "FM", "", "", 10, 40, 240,200, 0, 87.50, 108.00, 87.50, 50, 1, 10, 10,
"VHF", "VHF", "", "", 10, 80, 240,150, 0, 64.00, 87.00, 64.00, 50, 1, 10, 1,
"LW", "DV", "", "", 150, 40, 240, 40, 1, 153, 279, 153, 10, 9, 1, 1,
"MW", "СВ", "", "", 150, 80, 240, 90, 2, 522, 1701, 522, 1, 90, 9, 1,
"SW1", "КВ1", "NIGHT WINTER", "Notte Inverno", 10,120, 0, 40, 29, 1800, 5060, 2300, 1, 100, 5, 1,
"SW2", "КВ2", "NIGHT", "Notte", 10,160, 0, 80, 29, 5300, 7600, 5900, 1, 100, 5, 1,
"SW3", "КВ3", "MOSTLY NIGHT", "Soprattutto Notte", 10,200, 0,120, 29, 9400, 12160, 9400, 1, 100, 5, 1,
"SW4", "КВ4", "MOSTLY DAY", "Soprattutto Giorno", 10,240, 0,160, 29, 13570, 18168, 13570, 1, 100, 5, 1,
"SW5", "КВ5", "DAY", "Giorno", 10,280, 0,200, 29, 18900, 26100, 18900, 1, 100, 5, 1,
};
const int lastBandRetro = (sizeof bandRetro / sizeof (RetroBand)) - 1;
//======================================================= END Retro Bands ==============================
typedef struct // Group data
{
const uint16_t groupIdx;
const char *PresetName;
} Group ;
typedef struct // Preset data
{
const float memoryIdx;
char *MemoryName;
char *memoryGroup;
} Memory ;
#include "Preset.h"
const int lastGroup = (sizeof group / sizeof (Group)) - 1;
const int lastMemory = (sizeof memory / sizeof (Memory)) - 1;
uint16_t PresetId; //CITY ID
uint16_t prevPresetId;
int lastPreset;
typedef struct // Preset data
{
float presetIdx;
char *PresetName;
int presetPos;
} Preset ;
// SCROLL TEXT
int textScroll;
long elapsedScroll;
int directScroll = 0;
//==========================================================================================================
//#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 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_RDS_TIME 5
#define DEFAULT_VOLUME 15 // 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
#define TFT_LIGTHYELLOW 0xFF10
bool bfoTr = false;
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 Mutestat = false;
bool AGCgainbut = false;
bool writingEeprom = false;
// =============== Squelch Functionality ============ LWH
bool SquelchUsesRSSI = true; // When true, the squelch uses RSSI, when false the squelch uses SNR
bool SQUELCHbut = false;
long SQUELCHbutOnTime = millis();
int previousSquelch;
int currentSquelch;
int SignalQuality = 0;
long squelchDecay = 0;
#define squelchDecayTime 500 // 1000
bool squelch = false;
uint8_t currentSQUELCHStep = 1;
uint8_t MaxSQUELCH = 50;
uint8_t MinSQUELCH = 0;
uint8_t encoderBtnState = 0;
#define MIN_ELAPSED_SQUELCHbut_TIME 1000
// ==================================================
//Battery info
bool batVolt = true;
long elapsedBat = 0;
//SCAN
bool SCANbut = false;
int currentScanFreq;
int posScanFreq;
int posScan;
int posScanLast;
float SCANstep;
bool SCANpause = true; // LWH - SCANpause must be initialized to a value else the squelch function will not work correctly.
float currentScanLine;
int ScanValueRSSI[320];
int ScanValueSNR[320];
bool ScanMark[320];
uint8_t ScanScaleLine[320];
uint8_t ScanMarkSNR = 3;
int ScanBeginBand;
int ScanEndBand;
uint8_t ScanAGC;
bool ScanEmpty = true;
float deltaScanLine = 0;
float currentMinScanStep;
float currentMaxScanStep;
int countScanSignal = 3;
float signalScale;
bool prevScaleLine = false;
//===========================================
//RETRO
bool RETRObut = false;
float currentRetroFreq;
float currentRetroScale;
const uint8_t RetroStationPos[] = {43, 55, 67, 79, 91, 103, 131, 143, 155, 167, 179, 191};
uint8_t RETROband = 0;
bool bandRETRObut = false;
bool cityRETRObut = false;
int cityRetroRotary = 0;
int scrollRetro = 0;
int bandHamRetro;
//===========================================
//MEMO
bool MEMObut = false;
int currentMemo = 0;
bool MEMOadd = false;
bool MEMOdel = false;
char addMemoName[21];
uint16_t addMemoFreq;
uint8_t addMemoBand;
uint8_t addMemoMode;
uint8_t posMemoName;
uint8_t charMemoName;
long elapsedCursor = millis();
bool presetBank = false;
//===========================================
//SETUP
bool SETUPbut = false;
int pageSetup = 0;
uint8_t maxPageSetup = 5;
//===========================================
//PRE
bool PREtap = false;
bool PRE = false;
uint16_t PREfreq;
uint8_t PREband;
uint8_t PREmode;
int PREbfo;
uint8_t PREstep;
uint8_t PREbw;
long elapsedPRE = millis();
//===========================================
//OPTIONS
bool VHFon;
bool langRetroEN;
bool digitLigth;
bool beeperOn;
bool memoPreset;
bool batShow;
bool loadMemory;
bool loadDefault;
bool saverOn;
uint8_t saverTime;
bool displayOff;
float minSCANstep;
float maxSCANstep;
bool autoSCANstep;
int SCANscale;
bool SCANaccuracy;
bool screenV;
bool displayPower;
uint16_t boolOpt;
bool RDSalways;
bool seekAccuracy;
bool prevdigitLigth;
bool prevlangRetroEN;
bool prevVHFon;
bool prevbeeperOn;
bool prevloadMemory;
bool prevbatShow;
bool prevmemoPreset;
bool prevloadDefault;
bool prevsaverOn;
uint8_t prevsaverTime;
bool prevdisplayOff;
float prevminSCANstep;
float prevmaxSCANstep;
bool prevautoSCANstep;
bool prevSCANaccuracy;
bool prevscreenV;
bool prevdisplayPower;
bool prevRDSalways;
bool prevseekAccuracy;
//===========================================
//SCREEN SAVER
long elapsedSaver = millis();
bool Saver = false;
int saverX;
int saverY;
int posSaver = 0;
//===========================================
bool pressed;
bool presStat;
bool audioMuteOn = true;
bool audioMuteOff = false;
bool RDS = true; // RDS on / 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 OldRSSI;
int NewRSSI;
int NewSNR;
int encBut;
uint8_t AGCgain;
int PrevRSSI = 0;
int strongup = 0;
long elapsedRSSI = millis();
long elapsedAudMut = millis();
long stationNameElapsed = millis();
long VOLbutOnTime = millis();
volatile int encoderCount = 0;
volatile int encoderButton = 0;
bool volDisp = false;
bool squelchDisp = false;
uint16_t previousFrequency;
uint8_t currentBFOStep = 25;
uint8_t currentPRES = 0;
int previousPRES;
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;
int currentVOL = 0;
int previousVOL = 0;
uint8_t currentVOLStep = 1;
uint8_t MaxVOL = 63;
uint8_t MinVOL = 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 = 65535;
uint16_t MaxBrightness = 16;
uint16_t MinBrightness = 256;
uint8_t stepsizesynth = 10;
float DisplayfreqNew = 0;
float Displayfreq = 0;
float currentFrequency = 0;
float dpfrq = 0;
float fact = 1;
float RSSIfact = 3;
String BWtext;
String Modtext;
String AGCgainbuttext;
//===========================
// Time
// String tM="ww";
struct tm timeinfo;
//===============================================================================
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[] = {"AUTO", "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", "OK", "DEL", "CLS", "X"};
const char *bandModeDesc[] = {"FM", "LSB", "USB", "AM", "CW"};
char buffer[64]; // Useful to handle string
char buffer1[64];
char *stationName;
char bufferStatioName[50]; // 40
char *rdsMsg;
char bufferRdsMsg[100]; // 100
char *rdsTime;
char bufferRdsTime[32]; // 32
unsigned long FreqSI5351 = 3276800;
unsigned long calibratvalSI5351;
int Xsmtr = 0;
int Ysmtr = 80; // S meter
int XVolInd = 0;
int YVolInd = 135; // Volume indicator
int XFreqDispl = 0;
int YFreqDispl = 0; // display
#define B_HAM 0
#define B_BFO 1
#define B_FREQ 2
#define B_AGC 3
#define B_MUTE 4
#define B_VOL 5
#define B_MODE 6
#define B_BANDW 7
#define B_STEP 8
#define B_BAND 9
#define B_ATT 10
#define B_NEXT 11
#define B_SEEKUP 0
#define B_SEEKDN 1
#define B_INFO 2
#define B_RDS 3
#define B_FM 4
#define B_MEMO 5
#define B_LIGHT 6
#define B_SETUP 7
#define B_SQUELCH 8 // LWH - was B_CHIP
#define B_SCAN 9
#define B_RETRO 10
#define B_BACK 11
//======================================================= 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
int lastmanuBFO; // Last Manual BFO per band using X-Tal
} Band;
// Band table
Band band[] = {
{ "FM", FM_BAND_TYPE, FM, 6400, 10800, 9920, 10, 0, 0}, // FM 0
{ "LW", LW_BAND_TYPE, AM, 100, 514, 198, 9, 0, 0}, // LW 1
{ "MW", MW_BAND_TYPE, AM, 514, 1800, 1395, 9, 0, 0}, // MW 2
{ "800M", LW_BAND_TYPE, AM, 280, 470, 284, 1, 0, 0}, // Ham 800M 3 // LWH - was "BACON"
{ "630M", SW_BAND_TYPE, LSB, 470, 480, 475, 1, 0, 0}, // Ham 630M 4
{ "160M", SW_BAND_TYPE, LSB, 1800, 2000, 1850, 1, 0, 0}, // Ham 160M 5
{ "120M", SW_BAND_TYPE, AM, 2000, 3200, 2400, 5, 0, 0}, // 120M 6
{ "90M", SW_BAND_TYPE, AM, 3200, 3500, 3300, 5, 0, 0}, // 90M 7
{ "80M", SW_BAND_TYPE, LSB, 3500, 3900, 3630, 1, 0, 0}, // Ham 80M 8
{ "75M", SW_BAND_TYPE, AM, 3900, 5300, 3950, 5, 0, 0}, // 75M 9
{ "60M", SW_BAND_TYPE, USB, 5300, 5900, 5375, 1, 0, 0}, // Ham 60M 10
{ "49M", SW_BAND_TYPE, AM, 5900, 7000, 6000, 5, 0, 0}, // 49M 11
{ "40M", SW_BAND_TYPE, LSB, 7000, 7500, 7074, 1, 0, 0}, // Ham 40M 12
{ "41M", SW_BAND_TYPE, AM, 7200, 9000, 7210, 5, 0, 0}, // 41M 13
{ "31M", SW_BAND_TYPE, AM, 9000, 10000, 9600, 5, 0, 0}, // 31M 14
{ "30M", SW_BAND_TYPE, USB, 10000, 10200, 10099, 1, 0, 0}, // Ham 30M 15
{ "25M", SW_BAND_TYPE, AM, 10200, 13500, 11700, 5, 0, 0}, // 25M 16
{ "22M", SW_BAND_TYPE, AM, 13500, 14000, 13700, 5, 0, 0}, // 22M 17
{ "20M", SW_BAND_TYPE, USB, 14000, 14500, 14074, 1, 0, 0}, // Ham 20M 18
{ "19M", SW_BAND_TYPE, AM, 14500, 17500, 15700, 5, 0, 0}, // 19M 19
{ "17M", SW_BAND_TYPE, AM, 17500, 18000, 17600, 5, 0, 0}, // 17M 20
{ "16M", SW_BAND_TYPE, USB, 18000, 18500, 18100, 1, 0, 0}, // Ham 16M 21
{ "15M", SW_BAND_TYPE, AM, 18500, 21000, 18950, 5, 0, 0}, // 15M 22
{ "14M", SW_BAND_TYPE, USB, 21000, 21500, 21074, 1, 0, 0}, // Ham 14M 23
{ "13M", SW_BAND_TYPE, AM, 21500, 24000, 21500, 5, 0, 0}, // 13M 24
{ "12M", SW_BAND_TYPE, USB, 24000, 25500, 24940, 1, 0, 0}, // Ham 12M 25
{ "11M", SW_BAND_TYPE, AM, 25500, 26100, 25800, 5, 0, 0}, // 11M 26
{ "CB", SW_BAND_TYPE, AM, 26100, 28000, 27200, 1, 0, 0}, // CB band 27
{ "10M", SW_BAND_TYPE, USB, 28000, 30000, 28500, 1, 0, 0}, // Ham 10M 28
{ "SW", SW_BAND_TYPE, AM, 100, 30000, 15500, 5, 0, 0} // Whole SW 29
};
#define BAND_FM 0
#define BAND_LW 1
#define BAND_MW 2
#define BAND_800M 3 // LWH - was BAND_BACON
#define BAND_630M 4
#define BAND_160M 5
#define BAND_120M 6
#define BAND_90M 7
#define BAND_80M 8
#define BAND_75M 9
#define BAND_60M 10
#define BAND_49M 11
#define BAND_40M 12
#define BAND_41M 13
#define BAND_31M 14
#define BAND_30M 15
#define BAND_25M 16
#define BAND_22M 17
#define BAND_20M 18
#define BAND_19M 19
#define BAND_17M 20
#define BAND_16M 21
#define BAND_15M 22
#define BAND_14M 23
#define BAND_13M 24
#define BAND_12M 25
#define BAND_11M 26
#define BAND_CB 27
#define BAND_10M 28
#define BAND_SW 29
//======================================================= End THE Band Definitions ========================
//======================================================= 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 lastBand = (sizeof band / sizeof(Band)) - 1;
const int lastdignum = (sizeof dn / sizeof(DigNum)) - 1;
uint16_t bandMode[(lastBand + 1)];
#define offsetEEPROM 32
#define EEPROM_SIZE 2048
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 AGCgain;
uint8_t currentVOL;
uint8_t currentBFOStep;
uint8_t RDS;
unsigned long FreqSI5351;
uint16_t currentBrightness;
uint8_t currentAGCgain;
unsigned long calibratvalSI5351;
int BFOLW;
int BFOMW;
int BFO600M;
int BFO630M;
int BFO160M;
int BFO120M;
int BFO90M;
int BFO80M;
int BFO75M;
int BFO60M;
int BFO49M;
int BFO40M;
int BFO41M;
int BFO31M;
int BFO30M;
int BFO25M;
int BFO22M;
int BFO20M;
int BFO19M;
int BFO17M;
int BFO16M;
int BFO15M;
int BFO15H;
int BFO13M;
int BFO12M;
int BFO11M;
int BFOCB;
int BFO10M;
int BFOSW;
//V4
byte chk4;
uint16_t PresetId;
uint8_t currentPRES;
uint16_t currentFreqRetro0;
uint16_t currentFreqRetro1;
uint16_t currentFreqRetro2;
uint16_t currentFreqRetro3;
uint16_t currentFreqRetro4;
uint16_t currentFreqRetro5;
uint16_t currentFreqRetro6;
uint16_t currentFreqRetro7;
uint16_t currentFreqRetro8;
uint8_t saverTime;
uint8_t RETROband;
uint8_t SCANscale;
uint16_t boolOpt;
//V5 by LWH
byte chk5;
int SquelchVal;
};
StoreStruct storage = {
'@', //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
0, //AGCgain
45, //currentVOL
25, //currentBFOStep
1, //RDS
3276800, //FreqSI5351
0, //currentBrightness
1, //currentAGCgain
0, //calibratvalSI5351
0, //BFOLW;
0, //BFOMW
0, //BFO600M
0, //BFO630M
0, //BFO160M
0, //BFO120M
0, //BFO90M
0, //BFO80M
0, //BFO75M
0, //BFO60M
0, //BFO49M
0, //BFO40M
0, //BFO41M
0, //BFO31M
0, //BFO30M
0, //BFO25M
0, //BFO22M
0, //BFO20M
0, //BFO19M
0, //BFO17M
0, //BFO16M
0, //BFO15M
0, //BFO15H
0, //BFO13M
0, //BFO12M
0, //BFO11M
0, //BFOCB
0, //BFO10M
0, //BFOSW
'@', //V4 or higer bild first time check
777,//PresetId
0, //currentPRES
8750, //currentFreqRetro0
6400, //currentFreqRetro1
153, //currentFreqRetro2
522, //currentFreqRetro3
2300, //currentFreqRetro4
5900, //currentFreqRetro5
9400, //currentFreqRetro6
13570,//currentFreqRetro7
18900,//currentFreqRetro8
10, //saverTime
0, //RETROband
193, //SCANscale
1181, //boolOpt
// ========================================== LWH
'@', //V5 or higher build first time check
0, // SquelchVal
// ==========================================
};
//MEMO BANK===============================================================
#define offsetMemoEEPROM 248
typedef struct // MemoBank data
{
uint16_t freq;
uint8_t band;
char Name[21];
} MemoryBank;
MemoryBank MemoBank[75]; // 75 slots for Memory Station
const int lastMemoBank = (sizeof MemoBank / sizeof(MemoryBank)) - 1;
Preset preset [lastMemory + lastMemoBank + 1];
typedef struct // MemoBank data for Memory.h file
{
uint16_t freq;
uint8_t band;
uint8_t mode;
char *Name;
} MemoryBankFile;
#include "Memory.h"
const int lastMemoBankFile = (sizeof MemoBankFile / sizeof(MemoryBankFile)) - 1;
//========================================================================
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;
#ifdef IhaveSI5351
Si5351wire si5351wire;
#endif
//=======================================================================================
void IRAM_ATTR RotaryEncFreq() {
//=======================================================================================
// rotary encoder events
if (!writingEeprom) {
encoderStatus = encoder.process();
if (encoderStatus) {
if (encoderStatus == DIR_CW) encoderCount = 1; else encoderCount = -1; // Direction clockwise
}
}
}
//=======================================================================================
void OPTpack() {
//=======================================================================================
boolOpt = 0;
boolOpt += digitLigth * 1;
boolOpt += batShow * 2;
boolOpt += langRetroEN * 4;
boolOpt += beeperOn * 8;
boolOpt += VHFon * 16;
boolOpt += loadMemory * 32;
boolOpt += memoPreset * 64;
boolOpt += saverOn * 128;
boolOpt += screenV * 256;
boolOpt += displayOff * 512;
boolOpt += SCANaccuracy * 1024;
boolOpt += displayPower * 2048;
boolOpt += RDSalways * 4096;
boolOpt += seekAccuracy * 8192;
}
//=======================================================================================
void OPTunpack() {
//=======================================================================================
digitLigth = bool((boolOpt >> 0) & 1);
batShow = bool((boolOpt >> 1) & 1);
langRetroEN = bool((boolOpt >> 2) & 1);
beeperOn = bool((boolOpt >> 3) & 1);
VHFon = bool((boolOpt >> 4) & 1);
loadMemory = bool((boolOpt >> 5) & 1);
memoPreset = bool((boolOpt >> 6) & 1);
saverOn = bool((boolOpt >> 7) & 1);
screenV = bool((boolOpt >> 8) & 1);
displayOff = bool((boolOpt >> 9) & 1);
SCANaccuracy = bool((boolOpt >> 10) & 1);
displayPower = bool((boolOpt >> 11) & 1);
RDSalways = bool((boolOpt >> 12) & 1);
seekAccuracy = bool((boolOpt >> 13) & 1);
}
//=======================================================================================
void scanOPTpack() {
//=======================================================================================
SCANscale = uint8_t((autoSCANstep * 128) + (maxSCANstep * 8) + (minSCANstep * 8));
if (countScanSignal == 3) SCANaccuracy = true; else SCANaccuracy = false;
}
//=======================================================================================
void scanOPTunpack() {
//=======================================================================================
if (SCANscale > 128) autoSCANstep = true; else autoSCANstep = false;
minSCANstep = float(SCANscale & 0x07) / 8;
maxSCANstep = float(SCANscale & 0x78) / 8;
if (SCANaccuracy) countScanSignal = 3; else countScanSignal = 1;
}
//=======================================================================================
void setup() {
//=======================================================================================
Serial.begin(115200);
pinMode(DISPLAY_LED, OUTPUT);
pinMode(BEEPER, OUTPUT);
digitalWrite(DISPLAY_LED, 0);
//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();
// Calibration code for touchscreen : for 2.8 inch & Rotation = 1
tft.setRotation(1);
uint16_t calData[5] = { 387, 3530, 246, 3555, 7 };
tft.setTouch(calData);
#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);
}
tft.fillScreen(TFT_BLACK);