Récepteur radio à TEF6686 et carte CYD

Ecran tactile. Utilisation simple. Code source extrêmement simple pour VisualCode & PlatformIO; Je suis reparti directement du PDF de NXP. Bandes SW, FM, aviation civile.
Album :

1 Description

On trouve sur Internet de nombreuses réalisations basées sur ce module récepteur TEF6686.Certaines réalisations sont commerciales, d'autres pas. Toutefois elles reprennent la plupart du temps le code source très complet et performant de PE5PVB disponible sur github.

Je me suis donc penché dans un premier temps sur ce code source. Et là.. Panique ! Des centaines de conditions "if, else, else if, break..." imbriquées rendant la compréhension très délicate, du moins pour moi. Je ne critique pas ce code, je dis juste qu'il ne me convient pas.

Je suis donc reparti de zéro : le document "User_Manual_TEF6686.pdf" de NXP Semiconductors. Bon d'accord il est caviardé d'un grand "CONFIDENTIAL" en travers des 100 pages, mais vu qu'il est largement divulgué sur Internet... Et puis le fait de comprendre comment ça marche leur fera sans doute vendre des modules... Sachant que ledit module est déjà présent dans des milliers d'autoradios.

Mon code source fait environ 180 ko contre environ 9 Mo pour certains autres plus complets.

Pour ma part, j'ai permis l'accès de toutes les fonctions de gestion de fréquences avec l'écran tactile de la carte CYD, le plus simplement possible :
  • Choix d'une station parmis 8 près enregistrées ("presets") dans le code source.
  • Saisie de la fréquence directement par le pavé numérique.
  • Mise en mémoire EEPROM de la fréquence en cours (100 freq pour SW, 100 freq pour FM, et 100 freq pour la bande aviation).
  • Sélection des station en EEPROM par les boutons (+) et (-).
  • Sélection de la bande de fréquence par trois boutons SW, FM, AIR.
  • Modification de la fréquence en sélectionnant le digit par les petits boutons situés au dessus des chiffres, puis boutons (+) et (+).
  • Fonctions "Mute" (pour répondre au téléphone...) et "Sleep".. Cette fonction Sleep réduit la consommation de la carte CYD à quelques uA et réduit aussi le bruit HF de la carte, tout en laissant fonctionner le module. Pour réveiller l'ESP32 il faut reseter. (à voir...)
  • Vu-mètre du niveau de la porteuse HF, et bar-graphe sur le signal BF.
  • Choix de la couleur du fond d'écran : parmi 8 présets ou en ajustant manuellement les composantes R, G, et B.
Bandes de réception :
  • SW : 1500kHz .. 28 MHz
  • FM : 88 MHz .. 108 MHz
  • AIR: 108 MHz .. 138 MHz (avec convertisseur 110 MHz en entrée antenne)
Remarque : 138 MHz = 28 + 110 MHz. Pour aller plus haut, il faut utiliser un autre convertisseur (120 MHz...) et modifier le code (affichage) en conséquence... Les limites des fréquences sont celles imposées par le module TEF6686 lui même. Mais je compte bien ne pas en rester là, et étudier un autre module...

2 VIDEO bande FM



Réception bande FM

Réception bande FM

3 VIDEO bande aviation civile



Réception AIR BAND : Scan de fréquences de la bande aviation civile (fréquences préalablement enregistrées). La détection et le maintien des fréquences actives se fait au choix par le niveau VHF (Level) ou par le rapport signal sur bruit (SNR). Un convertisseur VHF - SW dit être utilisé sur l'entrée antenne (-110 MHz).

Réception AIR BAND : Scan de fréquences de la bande aviation civile (fréquences préalablement enregistrées). La détection et le maintien des fréquences actives se fait au choix par le niveau VHF (Level) ou par le rapport signal sur bruit (SNR). Un convertisseur VHF - SW dit être utilisé sur l'entrée antenne (-110 MHz).

4 Le schéma :

La carte ESP32 Cheap Yellow Display Board (CYD) est celle sérigraphiée ESP-322432S028 avec un afficheur 2.8 pouces 320x240PX; C'est la plus courante. Il en existe d'autres modèles pour lesquels il faudrait modifier cetaines parties du code source...

5 Détail connecteurs de la carte

La numérotation en vert est arbitraire (perso). En revanche l'attribution des ports (en noir) est exacte. On remarque que le GPIO22 est présent sur les deux connecteurs. En conséquence, si on retire les trois alims, nous n'avons pas cinq ports mais seulement quatre à notre disposition (GPIO 21, 22, 27, 35).

J'utilise les GPIO 22 et 27 du connecteur CN1 pour communiquer avec le module TEF6686 (SCL et SDA). Quant au GPIO21, je lis dans la documentation de la carte CYD qu'il est employé en interne pour piloter le backlight de l'afficheur. Il ne reste donc plus que le GPIO 35 de disponible. Je compte l'utiliser pour mesurer la tension de la batterie (en amont du régulateur LM7805) par l'intermédiaire d'un diviseur à résistances, pour éviter la décharge profonde de cette batterie LiPo.

6 Le bus SPI 3V3 et l'alimentation des modules en 5V

Sur la carte CYD il y a deux régulateurs 3v3

Et un sur le module TEF6686 (dont le blindage a été dessoudé pour la photo.
Remarque: Ce n'est pas MON module, photo trouvée sur Internet)

L'alimentation de la carte jaune CYD se fait en 5V. Celle du module TEF6686 se fait en 5V également. Toutefois les puces présentes sur ces cartes, à savoir l'ESP32 et la puce TEF6686 sont alimentées en 3v3. En effet, les cartes sont équipées chacune d'un régulateur 3V3 lowdrop (LD1117). Et donc le bus SPI peut se passer d'un adaptateur de tension 3v3-5V.

7 Le module TEF6686 de chez MPX

.

8 Le module ampli BF

Voir le lien plus bas.

9 Les mini Haut Parleurs

Voir le lien plus bas...

10 C'est dans la boite !

Les découpes dans le couvercle pour l'afficheur de la carte CYD et le HP ont été faites à la CNC. Je vais rajouter un joli bouton sur le potentiomètre de l'ampli BF.

11 Disposition des éléments

La face interne du couvercle est bien remplie.

La boite elle même contient la batterie (immobilisée par une pièce faite à l'imprimante 3D) + connecteur de charge + fusible (sous gaine thermo transparente).

12 Fichier source main.cpp :

CODE SOURCE en C++
  1. /* ************************************************************************************
  2. Radio TEF6686
  3. pour la carte CYD (Cheap Yellow Display) ESP32 Wroom + afficheur 2.8" TFT 240x320
  4. par Silicium628
  5.  
  6. CONCERNANT L'AFFICHAGE TFT
  7. à placer dans le fichier User_Setup.h ( dans ~/Arduino/libraries/TFT_eSPI/ ):
  8. #define ILI9341_2_DRIVER
  9.  
  10. ************************************************************************************ */
  11. #include <Arduino.h>
  12.  
  13. String version = "20.3";
  14.  
  15. #include "main.h"
  16. #include "constantes_628.h"
  17. #include "DSP_INIT_628.h"
  18. #include "driverTEF6686_628.h"
  19. #include <Free_Fonts.h>
  20.  
  21. #include "FS.h"
  22. #include "SD.h"
  23. #include "Wire.h"
  24.  
  25. #include <stdint.h>
  26.  
  27. #include "TFT_eSPI.h" // Hardware-specific library
  28. #include "SPI.h"
  29. #include "Free_Fonts.h"
  30. #include "Digit_Font.h"
  31. #include <XPT2046_Touchscreen.h>
  32.  
  33. #include <EEPROM.h>
  34.  
  35.  
  36.  
  37. // #define _SD_CARD // décommenter cette ligne pour utiliser une SDcard; commenter pour utiliser le Touchscreen
  38.  
  39. #define SPI_READ_FREQUENCY 16000000
  40.  
  41. // mem presets[EE_PRESETS_CNT];
  42.  
  43. #define EEPROM_SIZE 100+2000 //100 premiers bytes réservés, puis 5 groupes de 400 bytes = 100 + 2000 = 2100
  44. #define EEPROM_adrs_couleur 0 // 2 octets pour un uint16_t
  45. #define EEPROM_adrs_freq 2 // 4 octets pour un uint32_t
  46. #define EEPROM_adrs_mode 6 // 1 octet pour un uint8_t
  47.  
  48. // 100 premiers bytes réservés pour sauvegarder diverses variables (Frq en cours par exemple...)
  49. // reste 1200 bytes
  50. // chaque fréquence est un uint_32 = 4 bytes
  51. // 1200/4 = 300 fréquences mémorisée, c.a.d 3 bandes (SW, FM, AIR) de 100 freq chaque
  52. // Remarque : il y a largement la possibilité d'en prévoir beaucoup plus !!
  53.  
  54. #define bande_SW (frequence > 1500) && (frequence < 28000)
  55. #define bande_interdite1 (frequence > 28000) && (frequence < 88000)
  56. #define bande_interdite2 (frequence > 108000) && (frequence < 118000)
  57. #define bande_FM (frequence >= 88000) && (frequence < 108000)
  58. #define bande_AIR (frequence >= 118000) && (frequence < 138000)
  59.  
  60.  
  61. // XPT2046_Touchscreen // commenter cette ligne pour utiliser la fontion 'write_TFT_on_SDcard()'
  62. #define XPT2046_IRQ 36
  63. #define XPT2046_MOSI 32
  64. #define XPT2046_MISO 39
  65. #define XPT2046_CLK 25
  66. #define XPT2046_CS 33
  67.  
  68. //sur le connecteur CN1 de la carte CYD sérigraphiée 'ESP32-2432S028';
  69. //attention: ces valeurs ne sont pas celles par défaut pour SDA et SCL
  70. const int GPIO_SDA = 27;
  71. const int GPIO_SCL = 22;
  72.  
  73. const int analogPin = 35;
  74.  
  75. #define High_16bto8b(a) ((uint8_t)((a) >> 8))
  76. #define Low_16bto8b(a) ((uint8_t)(a ))
  77. #define Convert8bto16b(a) ((uint16_t)(((uint16_t)(*(a))) << 8 |((uint16_t)(*(a+1)))))
  78.  
  79.  
  80. SPIClass mySpi = SPIClass(VSPI);
  81. XPT2046_Touchscreen ts(XPT2046_CS, XPT2046_IRQ);
  82.  
  83. TFT_eSPI TFT = TFT_eSPI(); // Configurer le fichier User_Setup.h de la bibliothèque TFT_eSPI au préalable
  84. TFT_eSprite sprite_frq = TFT_eSprite(&TFT);
  85. //TFT_eSprite sprite_unit = TFT_eSprite(&TFT);
  86.  
  87.  
  88. // pour afficheur TFT
  89. const int _DX = 320;
  90. const int _DY = 240;
  91.  
  92.  
  93. float raddeg = M_PI/180.0;
  94. float deg_to_rad = 2.0 * M_PI /360.0;
  95.  
  96. //***************************************************************************
  97. //char var_array32[10];// 10 char + zero terminal - pour envoi par WiFi (because 2^32 -1 = 4294967295 -> 10 caractères)
  98. // =====================================================================
  99.  
  100.  
  101. TFT_eSprite Sprite_frq = TFT_eSprite(&TFT);
  102. // la def de 'TFT_eSprite' se trouve dans ~/Arduino/libraries/TFT_eSPI/Extensions/Sprite.h
  103.  
  104.  
  105. boolean test_touch_screen = false; // mettre true pour activer le test (qui est une boucle infinie au démarrage...)
  106. // voir la foncion 'loop()'
  107.  
  108. uint16_t compteur1 = 0;
  109. uint16_t compteur2 = 0;
  110. uint16_t compteur3 = 0;
  111. uint8_t SDcardOk=0;
  112. uint8_t do_wr_ecran_on_sd=0;
  113.  
  114. uint32_t frequence=10000;
  115. uint32_t saut_freq;
  116. uint16_t seuil = 500;
  117. uint16_t memo_seuil = 500;
  118. //uint32_t image_EE[300]; // permet le tri en RAM des fréquences sans toucher à l'EEPROM
  119.  
  120. GROUPE_FREQUENCES groupe_SW;
  121. GROUPE_FREQUENCES groupe_FM;
  122. GROUPE_FREQUENCES groupe_AIR;
  123. GROUPE_FREQUENCES groupe_SCAN;
  124.  
  125. uint32_t frq_preset_SW[8]; // 8 fréquences attribuées aux boutons [preset1] à [preset8] soit 8x4=32 octets
  126. uint32_t frq_preset_FM[8]; // 8 fréquences attribuées aux boutons [preset1] à [preset8] soit 8x4=32 octets
  127. uint32_t frq_preset_AIR[8];// 8 fréquences attribuées aux boutons [preset1] à [preset8] soit 8x4=32 octets total 32*3 = 96 octets
  128.  
  129. uint32_t memo_frequence_scan;
  130. uint16_t frq_preset_adr_0;
  131. String frequence_txt = "";
  132.  
  133. TOUCH_BOUTON bt_sleep;
  134.  
  135. TOUCH_BOUTON bt_mode_FRQ, bt_mode_MEM;
  136. TOUCH_BOUTON bt_plus, bt_moins;
  137.  
  138. TOUCH_BOUTON bt_EE_RAZ, bt_EE_write, bt_erase_1F;
  139. TOUCH_BOUTON bt_1, bt_2, bt_3, bt_4, bt_5, bt_6; // au dessus des chiffres de la fréquence
  140.  
  141. TOUCH_BOUTON bt_affi_saisie_couleur;
  142. TOUCH_BOUTON bt_coul_to_EEPROM;
  143.  
  144. TOUCH_BOUTON bt_scan_frq, bt_scan_air;
  145.  
  146. TOUCH_BOUTON bt_RST_affi; // "ok"
  147. //TOUCH_BOUTON bt_close1; // "x"
  148.  
  149. TOUCH_BOUTON bt_LEV, bt_SNR, bt_re_scan, bt_scan_suivant;
  150. TOUCH_BOUTON bt_seuil_plus, bt_seuil_moins;
  151.  
  152. // ---------- numPad ------------
  153. TOUCH_BOUTON bt_num0, bt_num1, bt_num2, bt_num3, bt_num4, bt_num5, bt_num6, bt_num7, bt_num8, bt_num9;
  154. NUM_PAD numPad1;
  155.  
  156. // ---------- presetPad1 ------------
  157. PRESET_PAD presetPad1;
  158.  
  159. // -------------------------------
  160. TOUCH_BOUTON bt_SW, bt_FM, bt_AIR, bt_SCN;
  161. TOUCH_BOUTON bt_mute;
  162. TOUCH_BOUTON bt_reset;
  163. TOUCH_BOUTON bt_stop_scan;
  164.  
  165. TOUCH_BOUTON bt_set; // attribtion d'une fréquence à un des 8 boutons preset
  166. TOUCH_BOUTON bt_annuler; // "x"
  167.  
  168. boolean mute;
  169. boolean vu_metre_actif;
  170.  
  171. enum MODE_AFFI {COUL, NORMAL, SCAN_F, SCAN_M, SET_F_PRESET}; //[couleur], [normal], [scan], [set 1F pour 1Bt]
  172. MODE_AFFI mode_affi;
  173.  
  174. enum MODE_SELECT {_FRQ=0, _MEM=1} mode_s; // mode de mofif fréquence, en tapant les chiffres /ou en mémoire
  175. //MODE_SELECT mode_s;
  176.  
  177. //#define _FRQ 0
  178. //#define _MEM 1
  179. //uint8_t mode_s; // _FRQ ou _MEM
  180.  
  181. enum MODUL {AM, WFM};
  182. MODUL modulation_active;
  183.  
  184. enum BANDE {SW, FM, AIR, SCN}; // la bande SCN mémorise le résultat d'un scan FREQUENCE
  185. BANDE bande_active;
  186.  
  187. enum MODE_SCAN {FREQUENCE, MEMOIRE};
  188. MODE_SCAN mode_scan;
  189.  
  190. enum MODE_SEUIL {LEV, SNR}; // level ou signal/bruit
  191. MODE_SEUIL mode_seuil;
  192.  
  193. uint16_t FRQ_x0;
  194. uint16_t FRQ_y0;
  195.  
  196. uint16_t x0_box_EEPROM;
  197. uint16_t y0_box_EEPROM;
  198.  
  199. uint16_t x0_box_PRESET;
  200. uint16_t y0_box_PRESET;
  201.  
  202. uint16_t x0_box_GROUPE; // SW - FM - AIR
  203. uint16_t y0_box_GROUPE;
  204.  
  205. uint16_t x0_box_boutons_scan;
  206. uint16_t y0_box_boutons_scan;
  207.  
  208. uint16_t x0_box_SCAN; // grande surface d'affichage
  209. uint16_t y0_box_SCAN;
  210. uint16_t dx_box_SCAN;
  211. uint16_t dy_box_SCAN;
  212.  
  213. uint16_t x0_numPad;
  214. uint16_t y0_numPad;
  215.  
  216. uint16_t x0_vu_metre;
  217. uint16_t y0_vu_metre;
  218.  
  219. uint16_t x0_box_info1;
  220. uint16_t y0_box_info1;
  221.  
  222. uint16_t x0_box_info2 = x0_vu_metre;
  223. uint16_t y0_box_info2 = y0_vu_metre;
  224. uint16_t dx_box_info2;
  225. uint16_t dy_box_info2;
  226.  
  227. uint16_t x0_saisie;
  228. uint16_t y0_saisie;
  229.  
  230. uint16_t x0_choix_couleur;
  231. uint16_t y0_choix_couleur;
  232.  
  233. uint8_t n_appui; // incrémenté à chaque appui sur une touche du numPad numérique
  234. uint32_t total_saisi;
  235.  
  236. uint16_t x_touch, y_touch;
  237.  
  238. uint16_t status;
  239. int16_t level;
  240. uint16_t usn;
  241. uint16_t wam;
  242. int16_t offset;
  243. uint16_t bandwidth;
  244. uint16_t mod;
  245. int8_t snr;
  246.  
  247. uint16_t A_block;
  248. uint16_t B_block;
  249. uint16_t C_block;
  250. uint16_t D_block;
  251. uint16_t dec_error;
  252.  
  253. float position_aiguille; // vu-metre
  254. float valeur_affi;
  255. float memo_valeur_affi;
  256. float ltx; // aiguille
  257. uint16_t osx;
  258. uint16_t osy;
  259.  
  260. uint16_t couleur_traits = GRIS_5;
  261. uint16_t JAUNE_chiffres = 65504;
  262. uint16_t VERT_chiffres = 2016;
  263.  
  264. uint8_t cR = 0;
  265. uint8_t cG = 0;
  266. uint8_t cB = 0;
  267. uint16_t couleur_fond_ecran = 0;
  268.  
  269.  
  270. float degTOrad(float angle)
  271. {
  272. return (angle * M_PI / 180.0);
  273. }
  274.  
  275.  
  276. uint8_t decToBcd( int val )
  277. {
  278. return (uint8_t) ((val / 10 * 16) + (val % 10));
  279. }
  280.  
  281.  
  282. uint16_t Color_To_565(uint8_t r, uint8_t g, uint8_t b)
  283. {
  284. return ((r & 0xF8) << 8) | ((g & 0xFC) << 3) | ((b & 0xF8) >> 3);
  285. }
  286.  
  287.  
  288. void RGB565_to_888(uint16_t color565, uint8_t *R, uint8_t *G, uint8_t *B)
  289. {
  290. *R=(color565 & 0xF800) >> 8;
  291. *G=(color565 & 0x7E0) >> 3;
  292. *B=(color565 & 0x1F) << 3 ;
  293. }
  294.  
  295.  
  296. /** ***********************************************************************************
  297. CAPTURE D'ECRAN vers SDcard
  298. **************************************************************************************
  299.  
  300. ATTENTION : cette fonction est simultanément incompatible avec la fonction tactile (TOUCHSCREEN) de l'afficheur
  301. pour des raisons d'attribution des bus spi.(il n'y a que deux bus SPI personnalisés DISPONIBLES sur
  302. les 4 de l'ESP32 (2 sont à usage interne),
  303. il en manque donc un troisième !)
  304.  
  305. SCREEN SPI : (tel que défini dans le fichier User_Setup.h)
  306. TFT_MISO GPIO 12 // don't define this pin when using Touch and SD Card on the CYD
  307. TFT_MOSI GPIO 13
  308. TFT_SCLK GPIO 14
  309. TFT_CS GPIO 15 // Chip select control pin
  310. TFT_DC GPIO 2 // Data Command control pin
  311. TFT_RST GPIO 4 // Reset pin (could connect to RST pin)
  312. TFT_RST -1 // Set TFT_RST to -1 if display RESET is connected to ESP32 board RST
  313.  
  314. TOUCHSCREEN SPI :
  315. IRQ (XPT2046_IRQ) GPIO 36
  316. MOSI (XPT2046_MOSI) GPIO 32
  317. MISO (XPT2046_MISO) GPIO 39
  318. CLK (XPT2046_CLK) GPIO 25
  319. CS (XPT2046_CS) GPIO 33
  320.  
  321. MicoSD card SPI :
  322. MISO GPIO 19
  323. MOSI GPIO 23
  324. SCK GPIO 18
  325. CS GPIO 5
  326.  
  327. Il est possible de partager un même bus SPI entre plusieurs composants, (one master and multi slaves)
  328. mais ce n'est pas ce qui a été fait par les concepteurs de la CYD.
  329. Les deux bus internes sont utilisés, il n'en reste plus de disponible.
  330.  
  331. voir l'URL très simple(!) suivante :
  332. https://medium.com/@androidcrypto/how-to-use-touch-and-sd-card-at-the-same-time-on-an-esp32-cheap-yellow-display-cyd-45fa55d01ffe
  333.  
  334. */
  335.  
  336. void init_variables_globales()
  337. // je ne les initialise pas lors de leur déclaration sinon lors d'un reset logiciel (appel de la fonction 'setup()'
  338. // par le boouton 'RST') elles ne seraient pas réinitialisées
  339. {
  340. mode_affi = NORMAL;
  341. bande_active = FM;
  342. modulation_active = WFM;
  343. mode_s = _MEM;
  344. mode_scan = FREQUENCE;
  345. mode_seuil = LEV;
  346. mute = false;
  347. vu_metre_actif = true;
  348.  
  349. FRQ_x0 = 50;
  350. FRQ_y0 = 30;
  351.  
  352. x0_box_EEPROM = 2;
  353. y0_box_EEPROM = 150;
  354.  
  355. x0_box_PRESET =2;
  356. y0_box_PRESET =87;
  357.  
  358. x0_box_GROUPE = 205; // SW - FM - AIR
  359. y0_box_GROUPE = 115;
  360.  
  361. x0_box_boutons_scan = 2;
  362. y0_box_boutons_scan = 105;
  363.  
  364. x0_box_SCAN = 2; // grande surface d'affichage
  365. y0_box_SCAN = 90;
  366. dx_box_SCAN = 315;
  367. dy_box_SCAN = 148;
  368.  
  369. x0_numPad = 70;
  370. y0_numPad = 115;
  371.  
  372. x0_vu_metre = 170;
  373. y0_vu_metre = 145;
  374.  
  375. x0_box_info1 = 71;
  376. y0_box_info1 = 220;
  377.  
  378. x0_box_info2 = x0_vu_metre;
  379. y0_box_info2 = y0_vu_metre;
  380. dx_box_info2 = 140;
  381. dy_box_info2 = 70;
  382.  
  383. x0_saisie = 3;
  384. y0_saisie = 0;
  385.  
  386. x0_choix_couleur = 170;
  387. y0_choix_couleur = 145;
  388.  
  389. n_appui = 0; // incrémenté à chaque appui sur une touche du numPad numérique
  390. total_saisi = 0;
  391.  
  392. position_aiguille = 0; // vu-metre
  393. valeur_affi = 0;
  394. memo_valeur_affi = 0;
  395. ltx = 0; // aiguille
  396. osx = x0_vu_metre;
  397. osy = y0_vu_metre;
  398. }
  399.  
  400.  
  401.  
  402. void init_SDcard()
  403. {
  404. Serial.println("init_SDcard()");
  405.  
  406.  
  407. if(!SD.begin())
  408. {
  409. Serial.println("Card Mount Failed");
  410. delay (1000);
  411. return;
  412. }
  413.  
  414. uint8_t cardType = SD.cardType();
  415.  
  416. if(cardType == CARD_NONE)
  417. {
  418. Serial.println("No SDcard");
  419. delay (1000);
  420. return;
  421. }
  422.  
  423. SDcardOk=1;
  424.  
  425. Serial.print("SDcard Type: ");
  426. if(cardType == CARD_SD) { Serial.println("SDSC"); }
  427. else if(cardType == CARD_SDHC) { Serial.println("SDHC"); }
  428.  
  429. uint32_t cardSize = SD.cardSize() / (1024 * 1024);
  430. String s1=(String)cardSize + " GB";
  431. Serial.print("SDcard size: ");
  432. Serial.println(s1);
  433.  
  434. delay (1000);
  435.  
  436. Serial.println("FIN init_SDcard()");
  437. }
  438.  
  439.  
  440.  
  441. // Fonction optimisée pour la carte CYD 320x240px avec la library 'TFT_eSPI'
  442. // ne convient PAS pour les ESP32 Wroom + afficheur 3.5" TFT 480x320
  443. void write_TFT_on_SDcard() // enregistre image bmp 320x240 RGB888
  444. {
  445. do_wr_ecran_on_sd =0;
  446. if (SDcardOk==0) {return;}
  447. int32_t x, y;
  448. uint16_t color565;
  449.  
  450. uint8_t octet_A;
  451. uint8_t octet_B;
  452.  
  453. if( ! SD.exists("/bmp/320x240_565.bmp")) {return;}
  454. File File1 = SD.open("/bmp/320x240_565.bmp", FILE_WRITE); // ouverture du fichier binaire (vierge) en écriture
  455. if (File1)
  456. {
  457. /*
  458. Les images en couleurs réelles BMP888 utilisent 24 bits par pixel:
  459. Il faut 3 octets pour coder chaque pixel, en respectant l'ordre de l'alternance bleu, vert et rouge.
  460. */
  461. uint16_t bmp_offset = 138;
  462. File1.seek(bmp_offset);
  463.  
  464. TFT.setFreeFont(FF0);
  465. TFT.setTextSize(1);
  466. TFT.setTextColor(JAUNE, NOIR);
  467.  
  468. for (y=240; y>0; y--)
  469. {
  470. for (x=0; x<320; x++)
  471. {
  472. color565=TFT.readPixel(x, y); // BBBBBrrr rrrVVVVV
  473.  
  474. octet_B = (color565 & 0b1111111100000000) >> 8;
  475. octet_A = (color565 & 0b0000000011111111);
  476.  
  477. File1.write(octet_A);
  478. File1.write(octet_B);
  479. }
  480. String s1=String(y/10); TFT.drawString(s1, 170, 115); // affiche compte à rebour
  481. }
  482.  
  483. File1.close(); // referme le fichier
  484. TFT.fillRect(170, 115, 20, 8, GRIS_2); // efface le compte à rebours
  485. }
  486. }
  487. // ***********************************************************************************************************
  488.  
  489.  
  490. void affiche_index_frq() // 6 petits boutons juste au dessus de chaque chiffre pour indiquer celui à modifier
  491. {
  492. int x = FRQ_x0 +15;
  493. int y = FRQ_y0 - 5;
  494. uint16_t c1 = NOIR;
  495. uint16_t c2 = VERT;
  496.  
  497. bt_1.init(x, y, 20, 5, 0); bt_1.affiche(c1, c2, 1); x+=31;
  498. bt_2.init(x, y, 20, 5, 0); bt_2.affiche(c1, c2, 1); x+=31;
  499. bt_3.init(x, y, 20, 5, 0); bt_3.affiche(c1, c2, 1); x+=46;
  500. bt_4.init(x, y, 20, 5, 0); bt_4.affiche(c1, c2, 1); x+=31;
  501. bt_5.init(x, y, 20, 5, 0); bt_5.affiche(c1, c2, 1); x+=31;
  502. bt_6.init(x, y, 20, 5, 0); bt_6.affiche(c1, c2, 1);
  503. }
  504.  
  505.  
  506.  
  507.  
  508. void init_boutons_Plus_Moins()// boutons '<' et '>'
  509. {
  510. int x0 = 240;
  511. int y0 = 90;
  512.  
  513. uint16_t c1 = GRIS_6;
  514. uint16_t c2 = JAUNE;
  515.  
  516. bt_moins.init(x0, y0, 30, 15, 1);
  517. bt_moins.cliked = false;
  518. bt_moins.s=" <";
  519.  
  520. bt_plus.init(x0+35, y0, 30, 15, 1);
  521. bt_plus.cliked = false;
  522. bt_plus.s=" >";
  523. }
  524.  
  525. // bt_SW
  526. // bt_FM
  527. // bt_AIR
  528.  
  529.  
  530. void init_boutons_GROUPE() // groupe de fréquence (SW - FM - AIR - SCAN)
  531. {
  532. uint16_t x = x0_box_GROUPE+4;
  533. uint16_t y = y0_box_GROUPE+5;
  534.  
  535. TFT.setFreeFont(FF0);
  536.  
  537. bt_SW.init(x, y, 20, 15, 3);
  538. bt_SW.cliked = false;
  539. bt_SW.selected = false;
  540. bt_SW.s="SW";
  541. x+=25;
  542.  
  543. bt_FM.init(x, y, 20, 15, 3);
  544. bt_FM.cliked = false;
  545. bt_FM.selected = false;
  546. bt_FM.s="FM";
  547. x+=25;
  548.  
  549. bt_AIR.init(x, y, 22, 15, 3);
  550. bt_AIR.cliked = false;
  551. bt_AIR.selected = false;
  552. bt_AIR.s="AIR";
  553. x+=27;
  554.  
  555. bt_SCN.init(x, y, 20, 15, 3);
  556. bt_SCN.cliked = false;
  557. bt_SCN.selected = false;
  558. bt_SCN.s="SC";
  559.  
  560. }
  561.  
  562. void init_1_bouton(uint16_t xi, uint16_t yi, uint8_t dx, uint8_t dy, String si, TOUCH_BOUTON *bouton_i)
  563. {
  564. uint16_t c1 = GRIS_5;
  565. uint16_t c2 = BLANC;
  566.  
  567. bouton_i->init(xi, yi, dx, dy, 3);
  568. bouton_i->cliked = false;
  569. bouton_i->selected = false;
  570. bouton_i->s = si;
  571. bouton_i->affiche(c1, c2, 1);
  572. }
  573. //init_1_bouton(202, 222, 32, 15, "", &);
  574.  
  575.  
  576. void init_boutons_MODE()
  577. {
  578. uint16_t c1 = NOIR;
  579. uint16_t c2 = VERT;
  580.  
  581. TFT.setFreeFont(FF0);
  582. TFT.setTextColor(GRIS_3, NOIR);
  583. TFT.drawString("mode", 6, 17);
  584.  
  585. TFT.drawFastVLine(45, 15, 72, couleur_traits);
  586.  
  587. bt_mode_FRQ.init(5, 35, 37, 20, 2);
  588. bt_mode_FRQ.selected = false;
  589. bt_mode_FRQ.s="FRQ";
  590. bt_mode_FRQ.affiche(c1, c2, 2);
  591.  
  592. bt_mode_MEM.init(5, 60, 37, 20, 2);
  593. bt_mode_MEM.selected = true;
  594. bt_mode_MEM.s="MEM";
  595. bt_mode_MEM.affiche(c1, c2, 2);
  596.  
  597. affiche_index_frq();
  598. }
  599.  
  600.  
  601.  
  602. void affiche_1_bt_RGB(TOUCH_BOUTON *bouton_i, uint16_t x, uint16_t y, uint8_t dx, uint16_t couleur, String s_i)
  603. {
  604. uint16_t c1 = couleur;
  605. uint16_t c2 = JAUNE;
  606.  
  607. bouton_i->init(x, y, dx, 14, 3);
  608. bouton_i->cliked = false;
  609. bouton_i->selected = false;
  610. bouton_i->s = s_i;
  611. bouton_i->affiche(c1, c2, 1);
  612.  
  613. }
  614.  
  615. void init_sprites()
  616. {
  617. sprite_frq.createSprite(220, 55);
  618. sprite_frq.loadFont(digitfont1);
  619. sprite_frq.setTextColor(JAUNE_2, NOIR);
  620. sprite_frq.setTextDatum(MR_DATUM); // alignement du texte
  621. }
  622.  
  623.  
  624. void Tuner_Reset(void)
  625. {
  626. Wire.beginTransmission(0x64);
  627. Wire.write(0x1e);
  628. Wire.write(0x5a);
  629. Wire.write(0x01);
  630. Wire.write(0x5a);
  631. Wire.write(0x5a);
  632. Wire.endTransmission();
  633. }
  634.  
  635.  
  636. bool Tuner_Table_Write(const unsigned char *tab)
  637. {
  638. if (tab[1] == 0xff)
  639. {
  640. delay(tab[2]);
  641. return 1;
  642. }
  643. else { return Tuner_WriteBuffer((unsigned char *)&tab[1], tab[0]); }
  644. }
  645.  
  646.  
  647. void Tuner_Init(const unsigned char *table)
  648. {
  649. uint16_t r;
  650. const unsigned char *p = table;
  651.  
  652. for (uint16_t i = 0; i < sizeof(tuner_init_tab9216); i += (pgm_read_byte(p + i) + 1))
  653. {
  654. if (1 != (r = Tuner_Table_Write(p + i))) break;
  655. }
  656. }
  657.  
  658.  
  659. void Tune_Frequence(uint32_t F)
  660. {
  661.  
  662. TFT.setFreeFont(FF0);
  663. TFT.setTextColor(BLEU, NOIR);
  664. String s1 = String(F);
  665. TFT.drawString(s1, 80, 2);
  666.  
  667.  
  668. if (F == 1500)
  669. {
  670. efface_box_entete3();
  671. //TFT.fillRect(130, 1, 70, 12, NOIR); // efface
  672. TFT.setTextColor(ROUGE, NOIR);
  673. TFT.drawString("MINIMUM ", 130, 2);
  674. }
  675.  
  676. if (bande_SW)
  677. {
  678. modulation_active = AM;
  679. Tune_Frequence_AM(F);
  680. efface_box_entete3();
  681. //TFT.fillRect(130, 1, 70, 12, NOIR); // efface
  682. TFT.setTextColor(VERT, NOIR);
  683. TFT.drawString("SW ", 130, 2);
  684. }
  685.  
  686. if (bande_interdite1)
  687. {
  688. //Tune_Frequence_AM(F);
  689. efface_box_entete3();
  690. //TFT.fillRect(130, 1, 70, 12, NOIR); // efface
  691. TFT.setTextColor(ROUGE, NOIR);
  692. TFT.drawString("NON DISPONIBLE", 130, 2);
  693. //bt_SW.selected = false;
  694. //bt_FM.selected = false;
  695. //bt_AIR.selected = false;
  696. }
  697.  
  698. if (bande_FM)
  699. {
  700. modulation_active = WFM;
  701. Tune_Frequence_FM(F/10);
  702. efface_box_entete3();
  703. //TFT.fillRect(130, 1, 70, 12, NOIR); // efface
  704. TFT.setTextColor(VERT, NOIR);
  705. TFT.drawString("bande FM", 130, 2);
  706. }
  707.  
  708. if (bande_interdite2)
  709. {
  710. //Tune_Frequence_AM(F);
  711. efface_box_entete3();
  712. //TFT.fillRect(130, 1, 70, 12, NOIR); // efface
  713. TFT.setTextColor(ROUGE, NOIR);
  714. TFT.drawString("NON DISPONIBLE", 130, 2);
  715. //bt_SW.selected = false;
  716. //bt_FM.selected = false;
  717. //bt_AIR.selected = false;
  718. }
  719.  
  720. if (bande_AIR)
  721. {
  722. modulation_active = AM;
  723. Tune_Frequence_AM(F-110000); // nécessite un convertisseur de fréquence 110MHz en entrée antenne
  724. efface_box_entete3();
  725. //TFT.fillRect(130, 1, 70, 12, NOIR); // efface
  726. TFT.setTextColor(BLEU_CLAIR, NOIR);
  727. TFT.drawString("AIR BAND", 130, 2);
  728. }
  729.  
  730. if (F == 138000)
  731. {
  732. //TFT.fillRect(130, 1, 40, 12, NOIR); // efface
  733. efface_box_entete3();
  734. TFT.setTextColor(ROUGE, NOIR);
  735. TFT.drawString("F MAX ", 130, 2);
  736. }
  737. }
  738.  
  739.  
  740. void load_GRP_FREQ_EEPROM()
  741. {
  742. Serial.println("--- Frequences lues en EEPROM ---------------");
  743. Serial.println(" ");
  744. Serial.println("GROUPE SW");
  745. groupe_SW.load_bloc(); // EEPROM -> RAM
  746. groupe_SW.tri_bloc(); // en RAM
  747. groupe_SW.bloc_to_serial();
  748.  
  749. Serial.println("---------------------------------------------");
  750.  
  751. Serial.println("GROUPE FM");
  752. groupe_FM.load_bloc(); // EEPROM -> RAM
  753. groupe_FM.tri_bloc(); // en RAM
  754. groupe_FM.bloc_to_serial();
  755.  
  756. Serial.println("---------------------------------------------");
  757.  
  758. Serial.println("GROUPE AIR");
  759. groupe_AIR.load_bloc(); // EEPROM -> RAM
  760. groupe_AIR.tri_bloc(); // en RAM
  761. groupe_AIR.bloc_to_serial();
  762.  
  763. Serial.println("---------------------------------------------");
  764.  
  765. // remarque : le groupe SCAN n'est jamais enregistré en EEPROM
  766.  
  767. }
  768.  
  769.  
  770. uint16_t brightness(uint16_t couleur)
  771. {
  772. uint8_t r, g, b;
  773.  
  774. r = 0xFF & (couleur >> 16);
  775. g = 0xFF & (couleur >> 8);
  776. b = 0xFF & couleur;
  777.  
  778. return ( r + g + b );
  779. }
  780.  
  781.  
  782.  
  783. void init_affichages()
  784. {
  785. //TFT.fillScreen(NOIR);
  786. TFT.fillRect(0, 14, 319, 230, couleur_fond_ecran);
  787. if (brightness(couleur_fond_ecran) > 500) {couleur_traits = NOIR;} else {couleur_traits = BLANC;}
  788.  
  789. TFT.setTextColor(JAUNE, NOIR);
  790.  
  791. TFT.drawRect(0, 0, 319, 240, couleur_traits); // cadre principal pourtour de l'écran
  792. TFT.setFreeFont(FF0);
  793. TFT.setTextColor(BLANC, BLEU);
  794. String s1 = "v:" + version;
  795. TFT.drawString(s1, 45, 15);
  796.  
  797. init_sprites();
  798. while (!Serial && (millis() <= 1000));
  799. init_boutons_MODE();
  800.  
  801. affiche_box_EEPROM();
  802. init_1_bouton(x0_box_EEPROM+4, y0_box_EEPROM+16, 40, 15, "Raz", &bt_EE_RAZ);
  803. init_1_bouton(x0_box_EEPROM+4, y0_box_EEPROM+33, 40, 15, "Write", &bt_EE_write);
  804.  
  805. TFT.setFreeFont(FF0);
  806.  
  807. init_boutons_Plus_Moins();
  808. init_boutons_GROUPE(); // (SW - FM - AIR - SC)
  809.  
  810. init_1_bouton(5, 220, 40, 14, "Sleep", &bt_sleep);
  811. init_1_bouton(237, 222, 30, 15, "RST", &bt_reset);
  812. init_1_bouton(202, 222, 32, 15, "Mute", &bt_mute);
  813.  
  814. affiche_box_boutons_scan();
  815. init_1_bouton(5, 118, 55, 15, "scan FRQ", &bt_scan_frq);
  816. init_1_bouton(5, 135, 55, 15, "scan AIR", &bt_scan_air);
  817.  
  818. init_1_bouton(168, 97, 30, 15, "set", &bt_set);
  819.  
  820.  
  821. init_1_bouton(x0_box_EEPROM+4, y0_box_EEPROM+33, 40, 15, "Write", &bt_EE_write);
  822. init_1_bouton(x0_box_EEPROM+4, y0_box_EEPROM+50, 40, 15, "raz 1F", &bt_erase_1F);
  823.  
  824. numPad1.init(x0_numPad, y0_numPad, true);
  825.  
  826. affiche_box_presets(); // conteneur des 8 petits boutons
  827. presetPad1.init(x0_box_PRESET +5, y0_box_PRESET +5);
  828.  
  829. efface_box_entete2();
  830. efface_box_entete3();
  831.  
  832. init_box_info();
  833. affiche_box_FRQ(GRIS_3); // autour de la fréquence (gros chiffres JAUNE ou VERT)
  834.  
  835.  
  836. //init_boutons_presets();
  837.  
  838. if (mode_affi == NORMAL)
  839. {
  840. affiche_box_GROUPE();
  841. bt_moins.affiche(GRIS_6, VERT ,1);
  842. bt_plus.affiche(GRIS_6, VERT ,1);
  843. bt_SW.affiche(GRIS_5, VERT, 1);
  844. bt_FM.affiche(GRIS_5, VERT, 1);
  845. bt_AIR.affiche(GRIS_5, VERT, 1);
  846. bt_SCN.affiche(GRIS_5, VERT, 1);
  847. }
  848.  
  849. bt_4.selected = true;
  850. bt_4.cliked = true;
  851. bt_4.affiche(NOIR, GRIS_2,1);
  852.  
  853. bt_mute.selected = false;
  854. bt_mute.cliked = false;
  855. bt_mute.affiche(NOIR, ROUGE, 1);
  856. bt_sleep.affiche(NOIR, VERT, 1);
  857. bt_reset.affiche(NOIR, VERT, 1);
  858.  
  859. affiche_frequence(frequence);
  860.  
  861. dessine_VuMetre();
  862.  
  863. init_1_bouton(268, 222, 50, 15, "Couleur", &bt_affi_saisie_couleur);
  864. bt_affi_saisie_couleur.affiche(NOIR, VERT, 1);
  865.  
  866. }
  867.  
  868.  
  869.  
  870.  
  871. void setup()
  872. {
  873. Serial.begin(115200);
  874.  
  875. init_variables_globales();
  876.  
  877.  
  878.  
  879. #ifdef _SD_CARD
  880. init_SDcard(); // attention : incompatible avec le TOUCHPAD
  881. //sauf modifs hard ou autre driver affi. Voir liens sur mon site.
  882. #endif
  883.  
  884. Wire.begin(GPIO_SDA, GPIO_SCL, 100000);
  885.  
  886. Serial.println("display.init()");
  887.  
  888. #ifndef _SD_CARD
  889. // Start the SPI for the touch screen and init the TS library
  890. // attention : incompatible avec SD_card, sauf modifs hard ou autre driver affi. Voir liens sur mon site.
  891. mySpi.begin(XPT2046_CLK, XPT2046_MISO, XPT2046_MOSI, XPT2046_CS);
  892. ts.begin(mySpi);
  893. ts.setRotation(3);
  894. #endif
  895.  
  896. TFT.init();
  897. TFT.setRotation(3); // 0..3 à voir, suivant disposition de l'afficheur et sa disposition
  898. TFT.fillScreen(NOIR);
  899.  
  900. TFT.setTextColor(BLANC, NOIR);
  901. TFT.setFreeFont(FF1);
  902. uint16_t y=0;
  903. Serial.println("Radio TEF6686");
  904. TFT.drawString("Radio TEF6686", 0, y); y+=20;
  905. String s1="version " + version;
  906. TFT.drawString(s1, 0, y); y+=20;
  907. TFT.drawString("Silicium628", 0, y); y+=40;
  908. TFT.setFreeFont(FF0);
  909. TFT.drawString("SW (AM) 1500kHz -- 28MHz", 0, y); y+=20;
  910. TFT.drawString("bande FM (WFM) 88MHz -- 108MHz", 0, y); y+=20;
  911. TFT.drawString("Civil Air band(AM) 118MHz -- 137MHz", 0, y); y+=20;
  912. delay(1000);
  913.  
  914. // adresses physiques des blocs en EEPROM:
  915. groupe_SW.adr_0 = 100; // je réserve les 100 premiers octets (0..99) pour des paramètres divers
  916. groupe_FM.adr_0 = groupe_SW.adr_0 +400; // donc =500 (chaque fréquence occupe 4 octets (uint_32t))
  917. groupe_AIR.adr_0 = groupe_FM.adr_0 +400; // donc =900
  918. groupe_SCAN.adr_0 = groupe_AIR.adr_0 +400; //donc =1300
  919. frq_preset_adr_0 = groupe_SCAN.adr_0 +400; // donc 1700
  920. // addr de fin pour l'EEPROM = 1700 + 96 = 1796
  921. // la limite physique (constatée) d'utilisation de cette "fausse" EEPROM (voir doc) se situe vers 11kB
  922.  
  923. groupe_SCAN.RAZ();
  924.  
  925. EEPROM.begin(EEPROM_SIZE); // <<< EEPROM - ATTENTION : tenir à jour la valeur EEPROM_SIZE au debut de ce code
  926.  
  927. presetPad1.set_frequences();
  928. presetPad1.set_couleurs();
  929.  
  930. couleur_fond_ecran = EEPROM.readShort(0); // 2 octets = 16 bits
  931. frequence = EEPROM.readUInt(EEPROM_adrs_freq); // 4 octets = 32 bits
  932.  
  933. //Serial.print("mode_s LU en EEPROM: "); Serial.println(mode_s);
  934.  
  935. boolean vu_metre_actif = true;
  936. TFT.fillScreen(NOIR);
  937. init_affichages();
  938.  
  939.  
  940. Serial.println("---------------------------------------------");
  941.  
  942. saut_freq = 100;
  943. Tuner_Init(tuner_init_tab9216);
  944.  
  945. //Serial.println(" ");
  946. /*
  947. The TEF668X consists of four modules:
  948. -module 32 : FM = FM radio reception
  949. -module 33 : AM = LW, MW and SW radio reception
  950. -module 48 : AUDIO = Audio processing
  951. -module 64 : APPL = System and application control
  952. */
  953.  
  954. load_GRP_FREQ_EEPROM();
  955.  
  956. Set_no_AM_gain_reduction();
  957.  
  958. byte md_s = EEPROM.readByte(EEPROM_adrs_mode); // 1 octet
  959. if(md_s == _FRQ) {bt_mode_FRQ.selected = true; bt_mode_MEM.selected = false;} // bt en haut à gauche
  960. if(md_s == _MEM) {bt_mode_FRQ.selected = false; bt_mode_MEM.selected = true;} // bt en haut à gauche
  961. uint16_t c1 = GRIS_6;
  962. uint16_t c2 = VERT;
  963. uint16_t c3 = JAUNE;
  964. bt_mode_FRQ.affiche(c1, c2, 2); // bt en haut à gauche
  965. bt_mode_MEM.affiche(c1, c3, 2); // bt en haut à gauche
  966.  
  967. bt_FM.cliked = true;
  968. bt_FM.selected = true;
  969.  
  970. bande_active = FM;
  971. modulation_active = WFM;
  972. frequence = presetPad1.bt_preset[0].frequence_FM;
  973.  
  974. affiche_frequence(frequence);
  975. Tune_Frequence(frequence);
  976.  
  977. Set_Volume(+60);
  978.  
  979. delay(100);
  980.  
  981. //clic_logiciel_bouton(&bt_mode_MEM);
  982. mode_s = _MEM;
  983. bt_mode_MEM.selected = true;
  984. bt_mode_FRQ.selected = false;
  985. //affiche_frequence(frequence);
  986.  
  987. Serial.print("------------- FIN DU SETUP -----------------");
  988. // FIN DU SETUP
  989. }
  990.  
  991.  
  992. void printTouchToDisplay()
  993. {
  994. TFT.fillScreen(NOIR);
  995.  
  996. TFT.setFreeFont(FM9);
  997. TFT.setTextColor(VERT, NOIR);
  998. TFT.drawString("TEST TOUCH SCREEN", 80, 120);
  999.  
  1000. while(1)
  1001. {
  1002. if (ts.tirqTouched() && ts.touched())
  1003. {
  1004. TS_Point p = ts.getPoint();
  1005. // ajuster les paramètres ici et penser à les mettre à jour dans la fonction 'loop()'
  1006. x_touch = -30 + p.x /11; // -30 11
  1007. y_touch = -30 + p.y /14; // -30 14
  1008. TFT.drawRect(x_touch, y_touch, 1, 1, JAUNE);
  1009.  
  1010. // affiche force d'appui du stylet
  1011. /*
  1012. //int x = 320 / 2; // center of display
  1013. //int y = 100;
  1014. //int fontSize = 2;
  1015. //String temp = "P= " + String(p.z);
  1016. //TFT.drawCentreString(temp, x, y, fontSize);
  1017. */
  1018. }
  1019. }
  1020. }
  1021.  
  1022.  
  1023. // -------------------------------------------------------------------------
  1024. // Le vu-metre est une variante perso du code : "/Arduino/libraries/TFT_eSPI/examples/480 x 320/TFT_Meters"
  1025. // voir le fichier licence.txt dans le dossier "/Arduino/libraries/TFT_eSPI/examples/"
  1026. void dessine_VuMetre()
  1027. {
  1028. if (vu_metre_actif == false) {return;}
  1029.  
  1030. uint16_t x0 = x0_vu_metre;
  1031. uint16_t y0 = y0_vu_metre;
  1032.  
  1033. uint16_t dx=140;
  1034. uint16_t dy=70;
  1035.  
  1036. uint8_t AA = 65; // 65
  1037. uint8_t BB = x0 +dx/2;// 120
  1038. uint8_t CC = y0 + dy+20; // 140
  1039.  
  1040. TFT.setFreeFont(FF0);
  1041. // cadre rectangulaire
  1042. TFT.fillRect(x0, y0, dx, dy, GRIS_3);
  1043. TFT.fillRect(x0+3, y0+3, dx-6, dy-6, BLANC);
  1044.  
  1045. TFT.setTextColor(NOIR);
  1046.  
  1047. // graduation chaque 5 deg entre -50 et +50 deg
  1048. for (int i = -50; i < 51; i += 10)
  1049. {
  1050. int tl = 5; // tiret plus long
  1051. // Coordonnées du tiret à dessiner
  1052. float sx = cos((i - 90) * deg_to_rad);
  1053. float sy = sin((i - 90) * deg_to_rad);
  1054. uint16_t tx0 = sx * (AA + tl) + BB;
  1055. uint16_t ty0 = sy * (AA + tl) + CC;
  1056. uint16_t tx1 = sx * AA + BB;
  1057. uint16_t ty1 = sy * AA + CC;
  1058.  
  1059. float sx2 = cos((i + 5 - 90) * deg_to_rad);
  1060. float sy2 = sin((i + 5 - 90) * deg_to_rad);
  1061. int tx2 = sx2 * (AA + tl) + BB;
  1062. int ty2 = sy2 * (AA + tl) + CC;
  1063. int tx3 = sx2 * AA + BB;
  1064. int ty3 = sy2 * AA + CC;
  1065.  
  1066. // zone verte
  1067. if (i >= 0 && i < 25)
  1068. {
  1069. TFT.fillTriangle(tx0, ty0, tx1, ty1, tx2, ty2, VERT);
  1070. TFT.fillTriangle(tx1, ty1, tx2, ty2, tx3, ty3, VERT);
  1071. }
  1072.  
  1073. // zone orange
  1074. if (i >= 25 && i < 50)
  1075. {
  1076. TFT.fillTriangle(tx0, ty0, tx1, ty1, tx2, ty2, ORANGE);
  1077. TFT.fillTriangle(tx1, ty1, tx2, ty2, tx3, ty3, ORANGE);
  1078. }
  1079.  
  1080. if (i % 25 != 0) tl = 8;
  1081.  
  1082. tx0 = sx * (AA + tl) + BB;
  1083. ty0 = sy * (AA + tl) + CC;
  1084. tx1 = sx * AA + BB;
  1085. ty1 = sy * AA + CC;
  1086.  
  1087. TFT.drawLine(tx0, ty0, tx1, ty1, NOIR);
  1088.  
  1089. if (i % 20 == 0)
  1090. {
  1091. tx0 = sx * (AA + tl + 10) + BB;
  1092. ty0 = sy * (AA + tl + 10) + CC;
  1093. switch (i / 20)
  1094. {
  1095. case -2: TFT.drawCentreString("0", tx0, ty0 - 6, 1); break;
  1096. case -1: TFT.drawCentreString("25", tx0, ty0 - 4, 1); break;
  1097. case 0: TFT.drawCentreString("50", tx0, ty0 - 6, 1); break;
  1098. case 1: TFT.drawCentreString("75", tx0, ty0 - 4, 1); break;
  1099. case 2: TFT.drawCentreString("100", tx0, ty0 - 6, 1); break;
  1100. }
  1101. }
  1102. sx = cos((i + 5 - 90) * deg_to_rad);
  1103. sy = sin((i + 5 - 90) * deg_to_rad);
  1104. tx0 = sx * AA + BB;
  1105. ty0 = sy * AA + CC;
  1106. if (i < 50) {TFT.drawLine(tx0, ty0, tx1, ty1, NOIR);}
  1107. }
  1108. }
  1109.  
  1110.  
  1111.  
  1112. void plotAiguille(float value)
  1113. {
  1114. if (vu_metre_actif == false) {return;}
  1115.  
  1116. uint16_t x0 = x0_vu_metre;
  1117. uint16_t y0 = y0_vu_metre;
  1118. uint16_t dx=140;
  1119. uint16_t dy=50;
  1120.  
  1121. uint8_t AA = dx/2; // 100
  1122. uint8_t BB = x0 +dx/2;// 120
  1123. uint8_t CC = y0 + dy+25; // 140
  1124.  
  1125. TFT.setTextColor(TFT_BLACK, BLANC);
  1126. char buf[8]; dtostrf(value, 4, 0, buf);
  1127.  
  1128. if (value < -10) value = -10;
  1129. if (value > 110) value = 110;
  1130.  
  1131. float sdeg = map(value, -10, 110, -150, -30);
  1132. float sx = cos(sdeg * deg_to_rad);
  1133. float sy = sin(sdeg * deg_to_rad);
  1134.  
  1135. float tx = tan((sdeg + 90) * deg_to_rad);
  1136.  
  1137. TFT.drawLine(BB + 20*ltx - 1, CC - 20, osx - 1, osy, BLANC); //efface
  1138. TFT.drawLine(BB + 20*ltx, CC - 20, osx, osy, BLANC);
  1139. TFT.drawLine(BB + 20*ltx + 1, CC - 20, osx + 1, osy, BLANC);
  1140.  
  1141. ltx = tx;
  1142. osx = sx*50 + BB;
  1143. osy = sy*50 + CC;
  1144.  
  1145. TFT.drawLine(BB + 20*ltx - 1, CC - 20, osx - 1, osy, ROUGE);
  1146. TFT.drawLine(BB + 20*ltx, CC - 20, osx, osy, VIOLET);
  1147. TFT.drawLine(BB + 20*ltx + 1, CC - 20, osx + 1, osy, ROUGE);
  1148.  
  1149. TFT.fillRect(x0, y0+dy+5, dx, 15, GRIS_2);
  1150. }
  1151.  
  1152.  
  1153.  
  1154. void init_box_info()
  1155. {
  1156. TFT.drawRect(x0_box_info1, y0_box_info1, 130, 16, NOIR);
  1157. TFT.setFreeFont(FF0);
  1158. TFT.setTextColor(JAUNE, couleur_fond_ecran);
  1159. TFT.drawString("RDS:", x0_box_info1 -24, y0_box_info1 + 4);
  1160. }
  1161.  
  1162.  
  1163. void affiche_unit(String s)
  1164. {
  1165. TFT.setTextColor(JAUNE, NOIR);
  1166. TFT.setFreeFont(FM9); //FM9 FMB9 FSS9... voir le fichier Free_Fonts.h
  1167. TFT.drawString(s, FRQ_x0 + 225, FRQ_y0 + 35);
  1168. }
  1169.  
  1170.  
  1171. void efface_numero_frq()
  1172. {
  1173. TFT.fillRect(FRQ_x0 + 225, FRQ_y0 + 20, 40, 12, couleur_fond_ecran);
  1174. }
  1175.  
  1176.  
  1177. void affiche_numero_frq(String s1, String s2)
  1178. {
  1179. //TFT.fillRect(FRQ_x0 + 225, FRQ_y0 + 5, 10, 10, BLEU);
  1180. TFT.setTextColor(BLANC, couleur_fond_ecran);
  1181. TFT.setFreeFont(FF0);
  1182. TFT.drawString(s1 + "/" + s2 + " ", FRQ_x0 + 225, FRQ_y0 + 20);
  1183. affiche_box_FRQ(GRIS_3); // pour retracer le côté droit du rectangle
  1184. }
  1185.  
  1186.  
  1187. void affiche_band(String s)
  1188. {
  1189. //TFT.fillRect(FRQ_x0 + 225, FRQ_y0 + 5, 10, 10, BLEU);
  1190. TFT.setTextColor(BLANC, NOIR);
  1191. TFT.setFreeFont(FM9);
  1192. String blancs;
  1193. if (s == "AIR") {blancs = " ";} else {blancs = " ";}
  1194.  
  1195. TFT.drawString(s + blancs, FRQ_x0 + 225, FRQ_y0);
  1196. affiche_box_FRQ(GRIS_3); // pour retracer le côté droit du rectangle
  1197. }
  1198.  
  1199. void efface_box_entete1()
  1200. {
  1201. TFT.fillRect(0, 1, 50, 12, NOIR);
  1202. }
  1203.  
  1204.  
  1205. void efface_box_entete2()
  1206. {
  1207. TFT.fillRect(50, 1, 180, 12, NOIR);
  1208. }
  1209.  
  1210.  
  1211. void efface_box_entete3()
  1212. {
  1213. TFT.fillRect(230, 1, 76, 12, NOIR);
  1214. memo_valeur_affi--; // pour réafficher tension batterie
  1215. }
  1216.  
  1217.  
  1218. void affiche_box_FRQ(uint16_t couleur) // autour de la fréquence (en gros chiffres JAUNE
  1219. {
  1220. TFT.drawRect(0, FRQ_y0 -17, 319, 74, couleur);
  1221. }
  1222.  
  1223.  
  1224. void affiche_box_presets() // boutons 1 2 3 4 5 6 7 8
  1225. {
  1226. TFT.fillRect(x0_box_PRESET, y0_box_PRESET, 164, 24, NOIR);
  1227. TFT.setTextColor(GRIS_3, NOIR);
  1228. //TFT.drawString("presets", 5, 90);
  1229. }
  1230.  
  1231.  
  1232. void affiche_box_GROUPE() // groupes de fréquences; contient 4 boutons SW, FM, AIR, SC
  1233. {
  1234. TFT.fillRect(x0_box_GROUPE, y0_box_GROUPE, 105, 23, NOIR);
  1235. //TFT.drawRect(x0_box_GROUPE, y0_box_GROUPE, 105, 25, couleur_traits);
  1236. TFT.setFreeFont(FF0);
  1237. TFT.setTextColor(GRIS_3, NOIR);
  1238. TFT.drawString("groupes Freq", x0_box_GROUPE+4, y0_box_GROUPE-6);
  1239. }
  1240.  
  1241.  
  1242. void efface_box_GROUPE()
  1243. {
  1244. TFT.fillRect(x0_box_GROUPE, y0_box_GROUPE-7, 110, 33, couleur_fond_ecran);
  1245. }
  1246.  
  1247.  
  1248. void affiche_box_EEPROM() // RAZ, WRITE, READ ...
  1249. {
  1250. TFT.fillRect(x0_box_EEPROM, y0_box_EEPROM + 10, 46, 58, NOIR);
  1251. TFT.setFreeFont(FF0);
  1252. TFT.setTextColor(GRIS_3, NOIR);
  1253. TFT.drawString("EEPROM", x0_box_EEPROM+6, y0_box_EEPROM+6);
  1254. }
  1255.  
  1256.  
  1257. void affiche_box_boutons_scan()
  1258. {
  1259. TFT.fillRect(x0_box_boutons_scan, y0_box_boutons_scan + 10, 60, 38, NOIR);
  1260. //TFT.setFreeFont(FF0);
  1261. //TFT.setTextColor(GRIS_3, NOIR);
  1262. //TFT.drawString("SCAN", x0_box_boutons_scan+6, y0_box_boutons_scan+6);
  1263.  
  1264. }
  1265.  
  1266.  
  1267. void affiche_box_scan()
  1268. {
  1269. TFT.fillRect(x0_box_SCAN, y0_box_SCAN, dx_box_SCAN, dy_box_SCAN, NOIR);
  1270. init_1_bouton(301, y0_box_SCAN+2, 15, 15, "x", &bt_stop_scan);
  1271. init_1_bouton(275, y0_box_SCAN+30, 40, 15, "rescan", &bt_re_scan);
  1272. init_1_bouton(275, y0_box_SCAN+50, 40, 15, " >>", &bt_scan_suivant);
  1273. init_1_bouton(250, y0_box_SCAN+10, 15, 15, "+", &bt_seuil_plus);
  1274. init_1_bouton(250, y0_box_SCAN+30, 15, 15, "-", &bt_seuil_moins);
  1275. init_1_bouton(4, y0_box_SCAN+3, 15, 15, "L", &bt_LEV);
  1276. init_1_bouton(4, y0_box_SCAN+20, 15, 15, "N", &bt_SNR);
  1277.  
  1278. }
  1279.  
  1280.  
  1281. void affi_boutons_SW_FM_AIR_SCN()
  1282. {
  1283. if((mode_affi == SCAN_F ) || (mode_affi == SCAN_M )) {return;}
  1284.  
  1285. uint16_t c1 = GRIS_5;
  1286. uint16_t c2 = VERT;
  1287. bt_SW.affiche(c1, c2, 1);
  1288. bt_FM.affiche(c1, c2, 1);
  1289. bt_AIR.affiche(c1, c2, 1);
  1290. bt_SCN.affiche(c1, BLEU_CLAIR, 1);
  1291. bt_mute.affiche(NOIR, ROUGE, 1);
  1292.  
  1293. }
  1294.  
  1295.  
  1296. void affiche_frequence(uint32_t frq)
  1297. {
  1298. uint16_t couleur_chiffres;
  1299.  
  1300. if(mode_s == _FRQ) {couleur_chiffres = VERT_chiffres;}
  1301. if(mode_s == _MEM) {couleur_chiffres = JAUNE_chiffres;}
  1302.  
  1303. if(bande_SW) // SW - 28 MHz = limite haute du module
  1304. {
  1305. affiche_band("SW");
  1306. modulation_active = AM;
  1307. bande_active = SW;
  1308. bt_SW.selected = true;
  1309. bt_FM.selected = false; // les boutons sont exclusifs
  1310. bt_AIR.selected = false;
  1311. //bt_SCN.selected = false;
  1312. affi_boutons_SW_FM_AIR_SCN();
  1313.  
  1314. String s1, sM, sK;
  1315. uint8_t L;
  1316.  
  1317. s1 = String(frq);
  1318. s1 = "000000" + s1;
  1319. L= s1.length();
  1320.  
  1321. sK = s1.substring(L-3); // kHz
  1322. sM = s1.substring(L-6, L-3); // Mhz
  1323.  
  1324. sprite_frq.fillRect(0, 0, 220, 60, NOIR); // efface
  1325.  
  1326. sprite_frq.setTextColor(couleur_chiffres, NOIR);
  1327. sprite_frq.drawString(sM + "." + sK + " ", 220+10, 32);
  1328. // remarque: le fait d'ajouter " " à la fin évite aux chiffres de se balader horizontalement !
  1329. sprite_frq.pushSprite(FRQ_x0, FRQ_y0);
  1330. affiche_unit("MHz");
  1331. Tune_Frequence(frq);
  1332. }
  1333.  
  1334. if(bande_FM) // bande FM, on efface les deux '0' de droite
  1335. {
  1336. affiche_band("FM");
  1337. modulation_active = WFM;
  1338. bande_active = FM;
  1339.  
  1340. //bt_FM.selected = true;
  1341. //bt_SW.selected = false; // les boutons sont exclusifs
  1342. //bt_AIR.selected = false;
  1343. //bt_SCN.selected = false;
  1344. affi_boutons_SW_FM_AIR_SCN();
  1345.  
  1346. String s1, sM, sK;
  1347. uint8_t L;
  1348.  
  1349. s1 = String(frq);
  1350. s1 = "000000" + s1;
  1351. L= s1.length();
  1352.  
  1353. sK = s1.substring(L-3, L-2); // kHz
  1354.  
  1355. if (frq < 100000) {sM = s1.substring(L-5, L-3); }// on ne retient que deux chiffres à gauche du point
  1356. else { sM = s1.substring(L-6, L-3); } // on garde 3 chiffres à gauche du point décimal
  1357.  
  1358. sprite_frq.fillRect(0, 0, 220, 60, NOIR); // efface
  1359. sprite_frq.setTextColor(couleur_chiffres, NOIR);
  1360. sprite_frq.drawString(sM + "." + sK + " ", 220-50, 32);
  1361. // remarque: le fait d'ajouter " " à la fin évite aux chiffres de se balader horizontalement !
  1362. sprite_frq.pushSprite(FRQ_x0, FRQ_y0);
  1363. affiche_unit("MHz");
  1364.  
  1365. Tune_Frequence(frq);
  1366. bt_mute.selected = false;
  1367. bt_mute.cliked = false;
  1368.  
  1369. }
  1370.  
  1371. if(bande_AIR) // bande AIR - 138000-110000 = 28MHz (limite haute de réception AM du module)
  1372. {
  1373. affiche_band("AIR");
  1374. modulation_active = AM;
  1375. bande_active = AIR;
  1376.  
  1377. bt_AIR.selected = true;
  1378. bt_SW.selected = false; // les boutons sont exclusifs
  1379. bt_FM.selected = false;
  1380. //bt_SCN.selected = false;
  1381. affi_boutons_SW_FM_AIR_SCN();
  1382.  
  1383. String s1, sM, sK;
  1384. uint8_t L;
  1385.  
  1386. s1 = String(frq);
  1387. s1 = "000000" + s1;
  1388. L= s1.length();
  1389.  
  1390. sK = s1.substring(L-3); // kHz
  1391. sM = s1.substring(L-6, L-3); // Mhz
  1392.  
  1393. sprite_frq.fillRect(0, 0, 220, 60, NOIR); // efface
  1394. sprite_frq.setTextColor(couleur_chiffres, NOIR);
  1395. sprite_frq.drawString(sM + "." + sK + " ", 220+10, 32);
  1396. // remarque: le fait d'ajouter " " à la fin évite aux chiffres de se balader horizontalement !
  1397. sprite_frq.pushSprite(FRQ_x0, FRQ_y0);
  1398. affiche_unit("MHz");
  1399. Tune_Frequence(frq);
  1400. }
  1401.  
  1402. if(bande_interdite1 || bande_interdite2) // bandes interdites par le module TEF6686
  1403. {
  1404. affiche_band("---");
  1405.  
  1406. String s1, sM, sK;
  1407. uint8_t L;
  1408.  
  1409. s1 = String(frq);
  1410. s1 = "000000" + s1;
  1411. L= s1.length();
  1412.  
  1413. sK = s1.substring(L-3); // kHz
  1414. sM = s1.substring(L-6, L-3); // Mhz
  1415.  
  1416. sprite_frq.fillRect(0, 0, 220, 60, NOIR); // efface
  1417. sprite_frq.setTextColor(couleur_chiffres, NOIR);
  1418. sprite_frq.drawString(sM + "." + sK + " ", 220+10, 32);
  1419. // remarque: le fait d'ajouter " " à la fin évite aux chiffres de se balader horizontalement !
  1420. sprite_frq.pushSprite(FRQ_x0, FRQ_y0);
  1421. affiche_unit("MHz");
  1422. //Tune_Frequence(frq);
  1423.  
  1424. }
  1425.  
  1426. if(frq==138000) { affiche_band("max"); }
  1427. if(frq>138000) { affiche_band("---"); }
  1428. }
  1429.  
  1430.  
  1431. void clic_logiciel_bouton(TOUCH_BOUTON *bouton_i)
  1432. {
  1433. uint16_t c1 = NOIR;
  1434. uint16_t c2 = JAUNE;
  1435.  
  1436. bouton_i->cliked = true;
  1437. bouton_i->selected = true;
  1438. bouton_i->affiche(c1, c2, 1);
  1439. }
  1440.  
  1441.  
  1442.  
  1443. void test_clic_boutons(TOUCH_BOUTON *bouton_i)
  1444. {
  1445. uint16_t c1 = NOIR;
  1446. uint16_t c2 = GRIS_2;
  1447.  
  1448. if ((x_touch > bouton_i->x0) && (x_touch < bouton_i->x0 + bouton_i->read_dx())
  1449. && ( y_touch > bouton_i->y0-5) && (y_touch < bouton_i->y0 + bouton_i->read_dy() +5) )
  1450. {
  1451. bouton_i->cliked = true;
  1452. bouton_i->selected = true;
  1453. bouton_i->affiche(c1, c2, 1);
  1454. }
  1455. }
  1456.  
  1457.  
  1458.  
  1459. void test_clic_6_boutons_frq() //rectangles situés au dessus des gros chiffres de la fréquence
  1460. {
  1461. uint16_t c1 = NOIR;
  1462. uint16_t c2 = VERT;
  1463.  
  1464. if (( y_touch > (bt_1.y0-10)) && (y_touch < (bt_1.y0 + bt_1.read_dy()+10)) ) // zone des 6 boutons au dessus de la fréquence
  1465. {
  1466. bt_1.cliked = false; bt_1.selected = false; test_clic_boutons(&bt_1 ); bt_1.affiche(c1, c2,1);
  1467. bt_2.cliked = false; bt_2.selected = false; test_clic_boutons(&bt_2 ); bt_2.affiche(c1, c2,1);
  1468. bt_3.cliked = false; bt_3.selected = false; test_clic_boutons(&bt_3 ); bt_3.affiche(c1, c2,1);
  1469. bt_4.cliked = false; bt_4.selected = false; test_clic_boutons(&bt_4 ); bt_4.affiche(c1, c2,1);
  1470. bt_5.cliked = false; bt_5.selected = false; test_clic_boutons(&bt_5 ); bt_5.affiche(c1, c2,1);
  1471. bt_6.cliked = false; bt_6.selected = false; test_clic_boutons(&bt_6 ); bt_6.affiche(c1, c2,1);
  1472.  
  1473. if (bt_6.cliked) {saut_freq = 1;}
  1474. if (bt_5.cliked) {saut_freq = 10;}
  1475. if (bt_4.cliked) {saut_freq = 100;}
  1476. if (bt_3.cliked) {saut_freq = 1000;}
  1477. if (bt_2.cliked) {saut_freq = 10000;}
  1478. if (bt_1.cliked) {saut_freq = 100000;}
  1479. }
  1480. }
  1481.  
  1482.  
  1483. void affiche_saisie(String s1)
  1484. {
  1485. TFT.fillRect(x0_saisie+1, y0_saisie-1, 60, 12, NOIR); // efface
  1486. TFT.setFreeFont(FF0); TFT.setTextColor(VERT, NOIR);
  1487. TFT.drawString(s1, x0_saisie+5, y0_saisie+3);
  1488. }
  1489.  
  1490.  
  1491. void traite_touches_pad(uint8_t num_touche) // pavé numérique
  1492. {
  1493. if(num_touche == 253) {return;}
  1494.  
  1495. uint16_t c1 = GRIS_6;
  1496. uint16_t c2 = JAUNE;
  1497. uint16_t c3 = VERT;
  1498.  
  1499. int p1;
  1500.  
  1501. if (num_touche == 254) // bouton "."
  1502. {
  1503. frequence_txt += ".";
  1504. affiche_saisie(frequence_txt);
  1505. }
  1506.  
  1507. if (num_touche < 10)
  1508. {
  1509. frequence_txt += String(num_touche);
  1510. affiche_saisie(frequence_txt);
  1511. delay(300);
  1512. }
  1513.  
  1514. x_touch =0;
  1515. y_touch =0;
  1516.  
  1517. if (num_touche == 255) // bouton "ok"
  1518. {
  1519. Serial.println("touche ok");
  1520.  
  1521. affiche_saisie(""); // efface
  1522.  
  1523. mode_s = _FRQ;
  1524. bt_mode_MEM.selected = false;
  1525. bt_mode_FRQ.selected = true;
  1526.  
  1527. bt_mode_MEM.affiche(c1, c2, 2);
  1528. bt_mode_FRQ.affiche(c1, c3, 2);
  1529.  
  1530. double F = frequence_txt.toDouble();
  1531. p1 = frequence_txt.indexOf(".");
  1532. if (p1 != -1) {F *=1000;} // si présence du point décimal
  1533.  
  1534. frequence = F;
  1535. affiche_frequence(frequence); // 'Tune_Frequence(frq)' est appelée dans cette fonction 'affiche_frequence()'
  1536.  
  1537. n_appui = 0;
  1538. frequence_txt = "";
  1539. TFT.fillRect(250, 0, 60, 12, NOIR); // efface
  1540.  
  1541. n_appui = 0;
  1542.  
  1543. }
  1544. num_touche = 0;
  1545. }
  1546.  
  1547.  
  1548. void traite_boutons_presetPad(uint8_t n_bt)
  1549. {
  1550. if (n_bt > 7) {return;}
  1551.  
  1552. uint16_t c1 = GRIS_5;
  1553. uint16_t c2 = JAUNE;
  1554. uint32_t adr0, adr1, adr2, adr;
  1555.  
  1556. if (mode_affi == NORMAL)
  1557. {
  1558. // Lit la frequence dans le bouton concerné (VOIR: 'class TOUCH_BOUTON_PRESET')
  1559. if(bande_active == SW) {frequence = presetPad1.bt_preset[n_bt].frequence_SW;}
  1560. if(bande_active == FM) {frequence = presetPad1.bt_preset[n_bt].frequence_FM;}
  1561. if(bande_active == AIR) {frequence = presetPad1.bt_preset[n_bt].frequence_AIR;}
  1562. }
  1563.  
  1564. if (mode_affi == SET_F_PRESET)
  1565. {
  1566. /* Serial.println("----------------------");
  1567. Serial.println("mode_affi == SET_F_PRESET");
  1568. Serial.print("frequence="); Serial.println(frequence);
  1569. Serial.print("bande_active="); Serial.println(bande_active);
  1570. Serial.print("n_b= "); Serial.println(n_bt);
  1571. */
  1572.  
  1573. adr0 = frq_preset_adr_0; // 1700
  1574.  
  1575. if(bande_active == SW)
  1576. {
  1577. presetPad1.bt_preset[n_bt].frequence_SW = frequence; // en RAM
  1578. adr = adr0 + 4*n_bt; // 4 octets par bouton
  1579. EEPROM.writeUInt(adr, frequence);
  1580. EEPROM.commit();
  1581. mode_affi = NORMAL;
  1582. delay(500);
  1583. }
  1584. if(bande_active == FM)
  1585. {
  1586. presetPad1.bt_preset[n_bt].frequence_FM = frequence;
  1587. adr = adr0 + 32 + 4*n_bt; // 8 boutons de 4 bytes -> 32 bytes
  1588. EEPROM.writeUInt(adr, frequence);
  1589. EEPROM.commit();
  1590. mode_affi = NORMAL;
  1591. delay(500);
  1592. }
  1593. if(bande_active == AIR)
  1594. {
  1595. presetPad1.bt_preset[n_bt].frequence_AIR = frequence;
  1596.  
  1597. adr = adr0 + 64 + 4*n_bt; // 8+8 boutons de 4 bytes -> 64 bytes
  1598. EEPROM.writeUInt(adr, frequence);
  1599. EEPROM.commit();
  1600. mode_affi = NORMAL;
  1601. delay(500);
  1602. }
  1603.  
  1604. mode_affi = NORMAL;
  1605. vu_metre_actif = true;
  1606. init_affichages();
  1607. }
  1608.  
  1609. if (mode_affi == COUL) // saisie couleur fond d'écran
  1610. {
  1611. couleur_fond_ecran = presetPad1.bt_preset[n_bt].couleur;
  1612. EEPROM.writeShort(EEPROM_adrs_couleur, couleur_fond_ecran); // write 1 mot de 16 bits soit 2 octets
  1613. EEPROM.commit();
  1614. mode_affi = NORMAL;
  1615. vu_metre_actif = true;
  1616. init_affichages();
  1617. }
  1618.  
  1619.  
  1620. affiche_frequence(frequence);
  1621. //efface_box_entete2();
  1622. TFT.setTextColor(JAUNE, NOIR);
  1623. TFT.setFreeFont(FF0);
  1624. Tune_Frequence(frequence);
  1625. }
  1626.  
  1627.  
  1628.  
  1629. uint32_t inc_Frq_in_groupe(GROUPE_FREQUENCES *groupe_Freq, int8_t di) // di = +/-1
  1630. {
  1631. if ((di<-1)||(di>1)) {return 0;}
  1632.  
  1633. uint16_t n_max = groupe_Freq->nb_freq;
  1634. uint16_t n = groupe_Freq->num_F_actuelle;
  1635.  
  1636. if(n_max > 99) {n_max = 99;}
  1637.  
  1638. if (di == 1)
  1639. {
  1640. if (n<n_max-1) { n++; }
  1641. else if (n >= (n_max-1)) {n=0;}
  1642. }
  1643.  
  1644. if (di == -1)
  1645. {
  1646. if (n>=1) { n--; }
  1647. else if (n==0) {n = n_max-1;}
  1648. }
  1649.  
  1650. if(n > 99) {n = 0;}
  1651.  
  1652. groupe_Freq->num_F_actuelle = n;
  1653. uint16_t adr = groupe_Freq->adr_1ere_frq + n;
  1654.  
  1655. uint8_t nb_F = groupe_Freq->nb_freq;
  1656. uint8_t num_1ere_F = groupe_Freq->adr_1ere_frq;
  1657. affiche_numero_frq(String(1 + adr - num_1ere_F), String(nb_F));
  1658.  
  1659. uint32_t valeur_lue = groupe_Freq->G_freq[adr];
  1660. return valeur_lue;
  1661. }
  1662.  
  1663.  
  1664.  
  1665. void test_clic_boutons_plus_moins()
  1666. {
  1667. Serial.print("bande_active = "); Serial.println(bande_active);
  1668.  
  1669. uint16_t c1 = GRIS_6;
  1670. uint16_t c2 = GRIS_3;
  1671.  
  1672. boolean bouton_cliked = false;
  1673. //uint16_t n=0;
  1674. //efface_box_entete(); // efface
  1675. efface_box_entete2();
  1676.  
  1677.  
  1678. //---------------------------------------------------------------------------------
  1679. if(mode_s == _FRQ) // on va modifier directement la fréquence
  1680. {
  1681. test_clic_boutons(&bt_plus );
  1682. bt_plus.affiche(c1, c2, 1);
  1683. if (bt_plus.cliked)
  1684. {
  1685. frequence += saut_freq;
  1686. bouton_cliked = true;
  1687. }
  1688.  
  1689. delay(20);
  1690. if (bt_plus.cliked && ((frequence + saut_freq) <= 138000 ))
  1691. {
  1692. Tune_Frequence(frequence);
  1693. }
  1694.  
  1695. bt_plus.cliked = false;
  1696. bt_plus.selected = false;
  1697. bt_plus.affiche(c1, c2, 1); // fugitif
  1698.  
  1699. test_clic_boutons(&bt_moins );
  1700. bt_moins.affiche(c1, c2, 1);
  1701. delay(20);
  1702. if (bt_moins.cliked)
  1703. {
  1704. if (frequence > saut_freq) // évite de se retrouver avec une F négative !
  1705. {
  1706. bouton_cliked = true;
  1707. frequence -= saut_freq;
  1708. }
  1709. }
  1710.  
  1711.  
  1712. if(bt_moins.cliked && frequence > saut_freq) { Tune_Frequence(frequence); }
  1713. bt_moins.cliked = false;
  1714. bt_moins.selected = false;
  1715. bt_moins.affiche(c1, c2, 1); // fugitif
  1716.  
  1717. if(bouton_cliked == true)
  1718. {
  1719. bouton_cliked = false;
  1720. affiche_frequence(frequence);
  1721. }
  1722. }
  1723.  
  1724. //---------------------------------------------------------------------------------
  1725.  
  1726. if(mode_s == _MEM) // on va parcourir les fréquences de la liste
  1727. {
  1728. test_clic_boutons(&bt_plus );
  1729. bt_plus.affiche(c1, c2, 1);
  1730. if (bt_plus.cliked)
  1731. {
  1732. bouton_cliked = true;
  1733.  
  1734. if(bande_active == SW) { frequence = inc_Frq_in_groupe(&groupe_SW, 1); }
  1735. if(bande_active == FM) { frequence = inc_Frq_in_groupe(&groupe_FM, 1); }
  1736. if(bande_active == AIR) { frequence = inc_Frq_in_groupe(&groupe_AIR, 1); }
  1737. if(bande_active == SCN) { frequence = inc_Frq_in_groupe(&groupe_SCAN, 1); }
  1738.  
  1739. Tune_Frequence(frequence);
  1740. delay(100);
  1741. }
  1742.  
  1743. bt_plus.cliked = false;
  1744. bt_plus.selected = false;
  1745. bt_plus.affiche(c1, c2, 1); // fugitif
  1746.  
  1747. test_clic_boutons(&bt_moins );
  1748. bt_moins.affiche(c1, c2, 1);
  1749. delay(20);
  1750. if (bt_moins.cliked)
  1751. {
  1752. bouton_cliked = true;
  1753.  
  1754. if(bande_active == SW) { frequence = inc_Frq_in_groupe(&groupe_SW, -1); }
  1755. if(bande_active == FM) { frequence = inc_Frq_in_groupe(&groupe_FM, -1); }
  1756. if(bande_active == AIR) { frequence = inc_Frq_in_groupe(&groupe_AIR, -1); }
  1757. if(bande_active == SCN) { frequence = inc_Frq_in_groupe(&groupe_SCAN, -1); }
  1758.  
  1759. Tune_Frequence(frequence);
  1760. delay(100);
  1761. }
  1762.  
  1763. bt_moins.cliked = false;
  1764. bt_moins.selected = false;
  1765. bt_moins.affiche(c1, c2, 1); // fugitif
  1766.  
  1767. if(bouton_cliked == true)
  1768. {
  1769. bouton_cliked = false;
  1770. affiche_frequence(frequence);
  1771. }
  1772. }
  1773. }
  1774.  
  1775.  
  1776. void test_clic_bt_RST_affi() // bouton "ok" de la box saisie couleur de fond ecran
  1777. {
  1778. if(mode_affi != COUL) {return;}
  1779.  
  1780. uint16_t c1 = GRIS_6;
  1781. uint16_t c2 = JAUNE;
  1782.  
  1783. test_clic_boutons(&bt_RST_affi );
  1784. //bt_sleep.affiche(NOIR, ROUGE, 1);
  1785. //delay(100);
  1786. if (bt_RST_affi.cliked)
  1787. {
  1788. bt_RST_affi.cliked = false;
  1789. bt_RST_affi.selected = true;
  1790. bt_RST_affi.affiche(NOIR, VERT, 1);
  1791.  
  1792. init_affichages();
  1793. }
  1794. }
  1795.  
  1796.  
  1797. void test_clic_bt_affi_saisie_couleur() // bouton au coin en bas à droite
  1798. {
  1799. uint16_t c1 = GRIS_6;
  1800. uint16_t c2 = JAUNE;
  1801.  
  1802. test_clic_boutons(&bt_affi_saisie_couleur );
  1803. //bt_sleep.affiche(NOIR, ROUGE, 1);
  1804. //delay(100);
  1805. if (bt_affi_saisie_couleur.cliked)
  1806. {
  1807. bt_affi_saisie_couleur.cliked = false;
  1808. bt_affi_saisie_couleur.selected = true;
  1809. bt_affi_saisie_couleur.affiche(NOIR, VERT, 1);
  1810.  
  1811. vu_metre_actif = false;
  1812. TFT.fillRect(x0_box_info2, y0_box_info2, dx_box_info2, dy_box_info2, NOIR);
  1813.  
  1814. TFT.setTextColor(VERT, NOIR);
  1815. TFT.setFreeFont(FF0);
  1816. TFT.drawString("Cliquez sur un des 8 bt", x0_box_info2+2, y0_box_info2+2);
  1817. TFT.drawString("'preset' pour choisir", x0_box_info2+2, y0_box_info2+12);
  1818. TFT.drawString("la couleur de fond", x0_box_info2+2, y0_box_info2+22);
  1819.  
  1820. mode_affi = COUL;
  1821.  
  1822. presetPad1.init(x0_box_PRESET +5, y0_box_PRESET +5);
  1823. }
  1824. }
  1825.  
  1826.  
  1827.  
  1828. void test_clic_bouton_mute()
  1829. {
  1830. test_clic_boutons(&bt_mute );
  1831.  
  1832. if (bt_mute.cliked)
  1833. {
  1834. bt_mute.affiche(NOIR, ROUGE, 1);
  1835. delay(100);
  1836.  
  1837. bt_mute.cliked = false;
  1838. if(mute == false) {mute = true;} else {mute = false;}
  1839. Set_Mute(mute); // fonction située dans le fichier 'driverTEF6686_628.h'
  1840. bt_mute.selected = mute;
  1841. bt_mute.affiche(NOIR, ROUGE, 1);
  1842. if (mute == false) {Tune_Frequence(frequence);}
  1843. delay(500);
  1844. }
  1845. }
  1846.  
  1847.  
  1848. void test_clic_bouton_Sleep()
  1849. {
  1850. test_clic_boutons(&bt_sleep );
  1851. //bt_sleep.affiche(NOIR, ROUGE, 1);
  1852. //delay(100);
  1853. if (bt_sleep.cliked)
  1854. {
  1855. bt_sleep.cliked = false;
  1856. bt_sleep.selected = true;
  1857. bt_sleep.affiche(NOIR, ROUGE, 1);
  1858. delay(100);
  1859.  
  1860. EEPROM.writeUInt(EEPROM_adrs_freq, frequence); // write 1 mot de 16 bits soit 2 octets
  1861.  
  1862. Serial.print("EEPROM.writeByte mode_s"); Serial.println(mode_s);
  1863. EEPROM.writeByte(EEPROM_adrs_mode, (byte)mode_s); // write 1 octet
  1864. EEPROM.commit();
  1865.  
  1866. delay(100);
  1867. esp_deep_sleep_start();
  1868. }
  1869. }
  1870.  
  1871.  
  1872. void test_clic_Bt_reset()
  1873. {
  1874. test_clic_boutons(&bt_reset );
  1875. bt_reset.affiche(GRIS_6, NOIR, 1);
  1876. delay(100);
  1877. if (bt_reset.cliked)
  1878. {
  1879. bt_reset.cliked = false;
  1880. bt_reset.selected = true;
  1881. bt_reset.affiche(GRIS_6, VERT, 1);
  1882.  
  1883. delay(100);
  1884. bt_reset.selected = false;
  1885. bt_reset.affiche(GRIS_6, VERT, 1);
  1886.  
  1887. setup();
  1888. }
  1889. }
  1890.  
  1891.  
  1892. void test_clic_bt_LEV()
  1893. {
  1894. test_clic_boutons(&bt_LEV);
  1895. if (bt_LEV.cliked)
  1896. {
  1897. bt_LEV.cliked = false;
  1898. bt_LEV.selected = true; bt_LEV.affiche(NOIR, VERT, 1);
  1899. bt_SNR.selected = false; bt_SNR.affiche(NOIR, VERT, 1);
  1900. mode_seuil = LEV;
  1901. }
  1902. }
  1903.  
  1904.  
  1905.  
  1906.  
  1907. void test_clic_bt_SNR()
  1908. {
  1909. test_clic_boutons(&bt_SNR);
  1910. if (bt_SNR.cliked)
  1911. {
  1912. bt_SNR.cliked = false;
  1913. bt_SNR.selected = true; bt_SNR.affiche(NOIR, VERT, 1);
  1914. bt_LEV.selected = false; bt_LEV.affiche(NOIR, VERT, 1);
  1915. mode_seuil = SNR;
  1916. }
  1917. }
  1918.  
  1919.  
  1920.  
  1921.  
  1922. void test_clic_bt_stop_scan()
  1923. {
  1924. test_clic_boutons(&bt_stop_scan);
  1925. if (bt_stop_scan.cliked)
  1926. {
  1927. Serial.println("STOP scan");
  1928. bt_stop_scan.affiche(NOIR, BLANC, 1);
  1929. mode_affi = NORMAL;
  1930. bt_stop_scan.cliked = false;
  1931. bt_stop_scan.affiche(NOIR, BLANC, 1);
  1932. }
  1933. }
  1934.  
  1935.  
  1936. void test_clic_bt_annuler() // sur la petite fenêtre surgissante d'info
  1937. {
  1938. test_clic_boutons(&bt_annuler);
  1939. if (bt_annuler.cliked)
  1940. {
  1941. bt_stop_scan.cliked = false;
  1942. bt_stop_scan.affiche(NOIR, BLANC, 1);
  1943.  
  1944. mode_affi = NORMAL; // ce qui repasse les boutons 'preset' en mode sélection et empêche l'écriture en EEPROM
  1945. vu_metre_actif = true;
  1946. init_affichages();
  1947. }
  1948. }
  1949.  
  1950.  
  1951. /*
  1952. MODES DE SCAN
  1953. 1-scan_frq() : tt fréquences d'une bande (ex: FM). Mise en mémoire temporaire (en RAM) des stations actives.
  1954. 2-scan_mem() : cannaux occupés (pour la bande aviation) - pas de mise en mémoire mais stop si message reçu
  1955. puis reprise auto du scan à la fin du message.
  1956. */
  1957.  
  1958. //enum MODE_SEUIL {LEV, SNR}; // level ou signal/bruit
  1959. //MODE_SEUIL mode_seuil = LEV;
  1960.  
  1961. void scan_mem()
  1962. {
  1963. Serial.println("scan_mem()");
  1964.  
  1965. efface_box_GROUPE();
  1966. affiche_box_scan();
  1967.  
  1968. TFT.setFreeFont(FF0);
  1969. TFT.setTextColor(JAUNE, NOIR);
  1970. TFT.drawString("SCAN AIR BAND (mem)", x0_box_SCAN +110 , y0_box_SCAN + 5); // titre
  1971.  
  1972. String si;
  1973. uint16_t y;
  1974. uint16_t xi;
  1975. int16_t dy;
  1976. uint16_t yi;
  1977. int16_t attente =0;
  1978.  
  1979. mode_seuil = SNR; //2 types de détection possibles: LEV(level) et SNR(signal-to-noise ratio = signal/bruit)
  1980. bt_SNR.selected = true; bt_SNR.affiche(NOIR, VERT, 1);
  1981. bt_LEV.selected = false; bt_LEV.affiche(NOIR, VERT, 1);
  1982.  
  1983. int16_t signal_i;
  1984.  
  1985. uint16_t base = y0_box_SCAN + dy_box_SCAN -5; // bas du graphique
  1986.  
  1987. TFT.setFreeFont(FM9);
  1988. TFT.setTextColor(JAUNE, NOIR);
  1989.  
  1990. bande_active = AIR;
  1991. frequence = 124075;
  1992. Tune_Frequence(frequence);
  1993. affiche_frequence(frequence);
  1994.  
  1995. TFT.drawFastHLine(5, base -seuil/10, 320, GRIS_6); // seuil (trait horizontal sur toute la largeur)
  1996.  
  1997. while(mode_affi == SCAN_M)
  1998. {
  1999. y = y0_box_SCAN + 5;
  2000. uint8_t module;
  2001. if(bande_active == FM) {module = 32;} else {module = 33;}
  2002. Get_Quality( module, &status, &level, &usn, &wam, &offset, &bandwidth, &mod, &snr );
  2003.  
  2004. si = String(level);
  2005. TFT.drawString("level", x0_box_SCAN +25 , y);
  2006. TFT.drawString(si+" ", x0_box_SCAN +65 , y);
  2007. y+=15;
  2008.  
  2009. si = String(snr);
  2010. TFT.drawString("snr", x0_box_SCAN +25 , y);
  2011. TFT.drawString(si+" ", x0_box_SCAN +65 , y);
  2012. y+=20;
  2013.  
  2014. if (mode_seuil == LEV) { signal_i = level; } // attention! level peut être négatif (échelle log)
  2015. if (mode_seuil == SNR) { signal_i= 16 * snr; }
  2016.  
  2017. dy = signal_i/10;
  2018. if(dy<0) {dy=0;}
  2019. dy+=2;
  2020.  
  2021. // petites barres verticales
  2022. xi = (frequence - 120000)/50;
  2023. // xi(120MHz) = 0 px;
  2024. // xi(136MHz) = (136000 - 120000) /50 = 320 px
  2025.  
  2026. TFT.drawFastVLine(xi, base-95, 95, NOIR); //efface
  2027. uint16_t c0 = BLEU;
  2028. if(signal_i > seuil){c0 = JAUNE;}
  2029. TFT.drawFastVLine(xi, base -dy, dy, c0);
  2030.  
  2031. uint16_t c1 = GRIS_5;
  2032. uint16_t c2 = VERT;
  2033.  
  2034. if(signal_i > seuil)
  2035. {
  2036. TFT.fillRect(x0_box_SCAN +110, y0_box_SCAN + 20, 20, 20, c2); // carré coloré
  2037. attente = 2;
  2038. }
  2039. else attente --;
  2040. if (attente <=0)
  2041. {
  2042. TFT.fillRect(x0_box_SCAN +110, y0_box_SCAN + 20, 20, 20, c1); // carré coloré
  2043. frequence = inc_Frq_in_groupe(&groupe_AIR, 1);
  2044. Tune_Frequence(frequence);
  2045. affiche_frequence(frequence);
  2046. TFT.setFreeFont(FF0);
  2047. TFT.setTextColor(BLANC, NOIR);
  2048. TFT.drawString("120M", x0_box_SCAN +5 , base-10);
  2049. TFT.drawString("136M", x0_box_SCAN +dx_box_SCAN -28, base-10);
  2050.  
  2051. attente =0;
  2052. }
  2053.  
  2054. if(seuil != memo_seuil)
  2055. {
  2056. TFT.drawFastHLine(5, base -memo_seuil/10, 310, NOIR); // efface
  2057. TFT.drawFastHLine(5, base -seuil/10, 310, GRIS_6); // seuil (trait horizontal sur toute la largeur)
  2058. si = "seuil:" + String(seuil); TFT.drawString(si+" ", x0_box_SCAN +185 , y0_box_SCAN +23);
  2059. }
  2060.  
  2061. delay(50); // ne pas réduire, temps nécessaire pour accrocher la fréquence
  2062.  
  2063. if (ts.tirqTouched() && ts.touched())
  2064. {
  2065. TS_Point p = ts.getPoint();
  2066. x_touch = -30 + p.x /11;
  2067. y_touch = -30 + p.y /14;
  2068. test_clic_bt_stop_scan();
  2069.  
  2070. test_clic_boutons(&bt_seuil_plus);
  2071. if (bt_seuil_plus.cliked)
  2072. {
  2073. bt_seuil_plus.cliked = false;
  2074. memo_seuil = seuil;
  2075. seuil += 5;
  2076. }
  2077.  
  2078. test_clic_boutons(&bt_seuil_moins);
  2079. if (bt_seuil_moins.cliked)
  2080. {
  2081. bt_seuil_moins.cliked = false;
  2082. memo_seuil = seuil;
  2083. seuil -= 5;
  2084. si = String(seuil); TFT.drawString(si+" ", x0_box_SCAN +55 , y);
  2085. }
  2086.  
  2087. test_clic_bt_LEV();
  2088. test_clic_bt_SNR();
  2089.  
  2090. test_clic_boutons(&bt_stop_scan);
  2091. }
  2092. }
  2093.  
  2094. //delay(1000);
  2095.  
  2096. mode_s = _MEM;
  2097. mode_affi = NORMAL;
  2098. bande_active = FM;
  2099. bt_mode_MEM.selected = true; bt_mode_MEM.affiche(GRIS_6, VERT, 2);
  2100. bt_mode_FRQ.selected = false; bt_mode_FRQ.affiche(GRIS_6, VERT, 2);
  2101.  
  2102. //boutons_preset_set_frequences();
  2103. init_affichages();
  2104. frequence = 89400;
  2105. Tune_Frequence(frequence);
  2106. affiche_frequence(frequence);
  2107.  
  2108. bt_FM.selected = true; bt_FM.affiche(GRIS_6, VERT, 1);
  2109. bt_AIR.selected = false; bt_AIR.affiche(GRIS_6, VERT, 1);
  2110. }
  2111.  
  2112.  
  2113.  
  2114. void scan_frq()
  2115. {
  2116. Serial.println("scan_frq()");
  2117.  
  2118. String si;
  2119. String s1;
  2120. String sA, sB;
  2121. float xi=0;
  2122. uint32_t xi32;
  2123. uint16_t y;
  2124. int16_t dy;
  2125. uint16_t yi;
  2126. uint16_t memo_x_touch = 0;
  2127. uint16_t nb_F;
  2128. int16_t signal_i;
  2129. uint16_t base = y0_box_SCAN + dy_box_SCAN -5; // bas du graphique
  2130.  
  2131. uint16_t decal_x;
  2132. uint16_t decal_y;
  2133. int n_max;
  2134.  
  2135. memo_frequence_scan = frequence; // variables globales
  2136.  
  2137. mode_seuil = SNR; //2 types de détection possibles: LEV(level) et SNR(signal-to-noise ratio = signal/bruit)
  2138. bt_SNR.selected = true; bt_SNR.affiche(NOIR, VERT, 1);
  2139. bt_LEV.selected = false; bt_LEV.affiche(NOIR, VERT, 1);
  2140.  
  2141. groupe_SCAN.RAZ();
  2142. efface_box_GROUPE();
  2143.  
  2144. TFT.setFreeFont(FM9);
  2145. TFT.setTextColor(JAUNE, NOIR);
  2146. TFT.setFreeFont(FF0);
  2147.  
  2148. uint8_t module;
  2149. if(bande_active == FM)
  2150. {
  2151. TFT.drawString("SCAN bande FM", x0_box_SCAN +50 , y0_box_SCAN + 10); // titre
  2152. frequence = 88000;
  2153. saut_freq = 100; // kHz
  2154. module = 32;
  2155. n_max = 190;
  2156. }
  2157. else
  2158. {
  2159. TFT.drawString("SCAN bande SW", x0_box_SCAN +50 , y0_box_SCAN + 10);
  2160. //frequence = 12000; // 12MHz...
  2161. saut_freq = 5; // kHz
  2162. module = 33;
  2163. n_max = 200;
  2164. }
  2165.  
  2166. y = y0_box_SCAN + 5;
  2167. decal_x=0;
  2168. decal_y=0;
  2169. nb_F=0;
  2170.  
  2171. TFT.drawFastHLine(5, base -seuil/10, 320, GRIS_6); // seuil (trait horizontal sur toute la largeur)
  2172.  
  2173. sA = String(frequence);
  2174. sB = String(frequence + n_max * saut_freq);
  2175. TFT.drawString(sA, x0_box_SCAN +5 , base-5);
  2176. TFT.drawString(sB, x0_box_SCAN +dx_box_SCAN -32, base-5);
  2177.  
  2178. boolean rescan = false;
  2179. do
  2180. {
  2181. groupe_SCAN.RAZ();
  2182. nb_F = 0;
  2183. affiche_box_scan();
  2184. int n = n_max;
  2185.  
  2186. uint32_t freq_min = frequence;
  2187. while(n>0)
  2188. {
  2189. frequence += saut_freq;
  2190. affiche_frequence(frequence);
  2191.  
  2192. if( (frequence + saut_freq) <= 138000 )
  2193. {
  2194. Tune_Frequence(frequence);
  2195. delay(15);
  2196. }
  2197.  
  2198. if(bande_active == FM) {module = 32;} else {module = 33;}
  2199. Get_Quality( module, &status, &level, &usn, &wam, &offset, &bandwidth, &mod, &snr );
  2200.  
  2201. delay(50);
  2202.  
  2203. //if(bande_active == SW) {xi += 1.6;}
  2204. //if(bande_active == FM) {xi += 2;}
  2205. xi += 1.6;
  2206.  
  2207. if (mode_seuil == LEV) { signal_i = level; } // attention! level peut être négatif (échelle log)
  2208. if (mode_seuil == SNR) { signal_i= 16 * snr; }
  2209.  
  2210. dy = signal_i/10;
  2211. if(dy<0) {dy=0;}
  2212. dy+=2;
  2213.  
  2214. uint16_t c1 = VERT;
  2215. if(dy>30){c1 = JAUNE;}
  2216. if(dy>40){c1 = ORANGE;}
  2217. if(dy>50){c1 = BLEU_CLAIR;}
  2218.  
  2219. xi32 = x0_box_SCAN + (uint32_t)xi;
  2220.  
  2221. if (xi32 < 318) // limite d'affichage à droite pour ne pas abimer le cadre
  2222. {
  2223. //TFT.drawFastVLine(xi32, base-dy, dy, c1); // petites barres verticales
  2224. // on va les tracer point par point afin de pouvoir les coloriser
  2225. int a = base;
  2226. int b = a - dy;
  2227. for(int n=b; n<a; n++)
  2228. {
  2229. c1 = BLEU;
  2230. if(n>180){c1 = VERT;}
  2231. if(n>190){c1 = JAUNE;}
  2232. if(n>200){c1 = ORANGE;}
  2233. if(n>215){c1 = ROUGE;}
  2234. //c1 = 10 * n *n;
  2235. TFT.drawPixel(xi32, n, c1);
  2236. }
  2237. }
  2238.  
  2239. if(signal_i > seuil) // DETECTION
  2240. {
  2241. if (decal_y > 5) // concerne l'affichage des textes (fréquences trouvées)
  2242. {
  2243. decal_y = 0;
  2244. decal_x ++;
  2245. }
  2246.  
  2247. s1 = String(frequence);
  2248. TFT.setTextColor(BLANC, NOIR);
  2249. TFT.drawString(s1, x0_box_SCAN + 2 + 45*decal_x, y0_box_SCAN + 9*decal_y); // String data
  2250. nb_F++;
  2251.  
  2252. TFT.setFreeFont(FM9);
  2253. TFT.setTextColor(VERT, NOIR);
  2254. s1 = String(nb_F);
  2255. TFT.drawString(s1, x0_box_SCAN +200 , y0_box_SCAN + 10); // nb freq
  2256. TFT.setFreeFont(FF0);
  2257.  
  2258. groupe_SCAN.add_frq(frequence); // AJOUTE la fréquence trouvée au groupe spécial 'groupe_SCAN'
  2259. decal_y ++;
  2260.  
  2261. if(groupe_SCAN.nb_freq >= 100) {n=0;} // groupe plein (en RAM)
  2262. }
  2263. n--;
  2264.  
  2265. if(seuil != memo_seuil)
  2266. {
  2267. TFT.drawFastHLine(5, base -memo_seuil/10, 310, NOIR); // efface
  2268. TFT.drawFastHLine(5, base -seuil/10, 310, GRIS_6); // seuil (trait horizontal sur toute la largeur)
  2269. si = "seuil:" + String(seuil); TFT.drawString(si+" ", x0_box_SCAN +185 , y0_box_SCAN +23);
  2270. }
  2271.  
  2272.  
  2273. delay(10); // ne pas réduire, temps nécessaire pour accrocher la fréquence
  2274. //delay(300); // pour balayage lent
  2275.  
  2276. if (ts.tirqTouched() && ts.touched())
  2277. {
  2278. TS_Point p = ts.getPoint();
  2279. x_touch = -30 + p.x /11;
  2280. y_touch = -30 + p.y /14;
  2281.  
  2282. test_clic_boutons(&bt_seuil_plus);
  2283. if (bt_seuil_plus.cliked)
  2284. {
  2285. bt_seuil_plus.cliked = false;
  2286. memo_seuil = seuil;
  2287. seuil += 5;
  2288. }
  2289.  
  2290. test_clic_boutons(&bt_seuil_moins);
  2291. if (bt_seuil_moins.cliked)
  2292. {
  2293. bt_seuil_moins.cliked = false;
  2294. memo_seuil = seuil;
  2295. seuil -= 5;
  2296. si = String(seuil); TFT.drawString(si+" ", x0_box_SCAN +55 , y);
  2297. }
  2298.  
  2299. test_clic_bt_LEV();
  2300. test_clic_bt_SNR();
  2301.  
  2302. test_clic_boutons(&bt_re_scan);
  2303. if (bt_re_scan.cliked)
  2304. {
  2305. bt_re_scan.cliked = false;
  2306. affiche_box_scan(); // efface le tracé et re-dessine les boutons dans la boite
  2307. frequence = memo_frequence_scan; // on repart de ma même frequence
  2308. n = n_max;
  2309. xi =0; // départ tracé à gauche
  2310. decal_x=0; // textes fréquences trouvées
  2311. decal_y=0;
  2312. nb_F=0;
  2313. }
  2314.  
  2315. test_clic_boutons(&bt_stop_scan);
  2316. if (bt_stop_scan.cliked)
  2317. {
  2318. n=0; // force la sortie de la boucle while()
  2319. }
  2320.  
  2321. }
  2322. } // fin de la boucle while()
  2323.  
  2324.  
  2325. boolean stop = false;
  2326. while (! stop) // attend une action en fin de scan (par ex: clic sur bouton 'stop_scan' [x]) ou [re_scan]
  2327. {
  2328. if (ts.tirqTouched() && ts.touched())
  2329. {
  2330. TS_Point p = ts.getPoint();
  2331. x_touch = -30 + p.x /11;
  2332. y_touch = -30 + p.y /14;
  2333.  
  2334. if((x_touch != memo_x_touch) && (y_touch > 170)) // écoute de la fréquence pointée avec le stylet
  2335. {
  2336. TFT.drawFastVLine(memo_x_touch, base, 4, NOIR); // efface
  2337. TFT.drawFastVLine(x_touch, base, 4, BLANC);
  2338.  
  2339. TFT.drawFastVLine(memo_x_touch, base-50, 4, NOIR); // efface
  2340. TFT.drawFastVLine(x_touch, base-50, 4, BLANC);
  2341.  
  2342. memo_x_touch = x_touch ;
  2343.  
  2344. float dF = (x_touch - x0_box_SCAN) * saut_freq / 1.6;
  2345. uint32_t F1 = freq_min + uint32_t(dF);
  2346. frequence = F1;
  2347. affiche_frequence(frequence);
  2348. Tune_Frequence(frequence);
  2349. String sF1 = String(F1);
  2350. TFT.drawString(sF1, 200, 100);
  2351. }
  2352.  
  2353. test_clic_boutons(&bt_re_scan);
  2354. if (bt_re_scan.cliked)
  2355. {
  2356. bt_re_scan.cliked = false;
  2357. frequence = memo_frequence_scan; // on repart de ma même frequence
  2358. xi=0;
  2359. xi32 = x0_box_SCAN + (uint32_t)xi;
  2360. stop =true;
  2361. rescan = true; //pas d'appel RECURSIF de la fonction. Trop de pb !!
  2362. }
  2363.  
  2364. test_clic_boutons(&bt_scan_suivant);
  2365. if (bt_scan_suivant.cliked)
  2366. {
  2367. bt_re_scan.cliked = false;
  2368. affiche_box_scan(); // efface le tracé et re-dessine les boutons dans la boite
  2369.  
  2370. n = n_max;
  2371. xi =0; // départ tracé à gauche
  2372. decal_x=0; // textes fréquences trouvées
  2373. decal_y=0;
  2374. nb_F=0;
  2375. stop =true;
  2376. rescan = true;
  2377. }
  2378.  
  2379. test_clic_boutons(&bt_stop_scan);
  2380. if (bt_stop_scan.cliked)
  2381. {
  2382. stop =true;
  2383. rescan = false;
  2384. }
  2385. }
  2386. }
  2387.  
  2388. if (rescan == true) {memo_frequence_scan = frequence;}
  2389.  
  2390. } while (rescan == true);
  2391.  
  2392. Serial.println("-----------------------");
  2393. Serial.println("groupe_SCAN");
  2394. groupe_SCAN.bloc_to_serial(); // pour test avec moniteur série (CuteCom par exemple)
  2395. Serial.println("-----------------------");
  2396.  
  2397. Serial.println("STOP scan");
  2398. //bt_stop_scan.affiche(NOIR, BLANC, 1);
  2399. //bt_stop_scan.cliked = false;
  2400. //bt_stop_scan.affiche(NOIR, BLANC, 1);
  2401.  
  2402. mode_affi = NORMAL;
  2403. mode_s = _MEM;
  2404. bt_mode_FRQ.selected = false; bt_mode_FRQ.affiche(GRIS_6, VERT, 2);
  2405. bt_mode_MEM.selected = true; bt_mode_MEM.affiche(GRIS_6, VERT, 2);
  2406. //bt_mode_MEM.cliked = true;
  2407.  
  2408. init_affichages();
  2409. affiche_frequence(frequence);
  2410.  
  2411. }
  2412.  
  2413.  
  2414. void test_clic_Bt_scan_FRQ()
  2415. {
  2416. test_clic_boutons(&bt_scan_frq);
  2417.  
  2418. if (bt_scan_frq.cliked == true)
  2419. {
  2420. bt_scan_frq.affiche(NOIR, VERT, 1);
  2421. bt_scan_frq.cliked = false;
  2422. bt_scan_frq.affiche(GRIS_2, VERT, 1);
  2423.  
  2424. mode_affi = SCAN_F;
  2425. mode_s = _FRQ;
  2426. bt_mode_FRQ.selected = true; bt_mode_FRQ.affiche(GRIS_6, VERT, 2);
  2427. bt_mode_MEM.selected = false; bt_mode_MEM.affiche(GRIS_6, VERT, 2);
  2428.  
  2429. scan_frq();
  2430.  
  2431. bt_scan_frq.affiche(NOIR, VERT, 1);
  2432. }
  2433. delay(100);
  2434. }
  2435.  
  2436.  
  2437. void test_clic_bt_scan_air()
  2438. {
  2439. test_clic_boutons(&bt_scan_air);
  2440.  
  2441. if (bt_scan_air.cliked == true)
  2442. {
  2443. bt_scan_air.affiche(NOIR, VERT, 1);
  2444. bt_scan_air.cliked = false;
  2445. bt_scan_air.affiche(GRIS_2, VERT, 1);
  2446. mode_affi = SCAN_M;
  2447. bt_scan_air.selected = true;
  2448.  
  2449. scan_mem();
  2450. bt_scan_air.affiche(NOIR, VERT, 1);
  2451. mode_s = _MEM;
  2452. }
  2453. delay(100);
  2454. }
  2455.  
  2456.  
  2457.  
  2458. void EE_RAZ()
  2459. {
  2460. boolean valider = false; // <-- ecrire "= true" pour rendre l'effacement possible
  2461. // (évite tout effacement accidentel et donc perte de centaines de fréquences...)
  2462.  
  2463. if(valider == false)
  2464. {
  2465. TFT.fillScreen(NOIR);
  2466. TFT.setFreeFont(FM9);
  2467. TFT.drawString("FONCTION VOLONTAIREMENT", 50, 120);
  2468. TFT.drawString("INACTIVE", 50, 140);
  2469. TFT.drawString("VOIR LE CODE SOURCE", 50, 160);
  2470. TFT.drawString("void EE_RAZ()", 50, 180);
  2471. delay(3000);
  2472. init_affichages();
  2473. return;
  2474. }
  2475.  
  2476. // efface le contenu del'EEPROM, partie data fréquences, sans toucher aux 100 premiers octets
  2477. Serial.println("debut RAZ EEPROM");
  2478. for(uint16_t n = 0; n<1200; n+=4 ) // 300 x 4 bytes // OK
  2479. {
  2480. uint32_t valeur1;
  2481. valeur1 = 0;
  2482. EEPROM.writeUInt(100+n, valeur1); // les 100 premiers octets sont réservés (par moi)
  2483. }
  2484. EEPROM.commit();
  2485. Serial.println("fin RAZ EEPROM");
  2486. }
  2487.  
  2488.  
  2489.  
  2490. void test_clic_bouton_EE_RAZ()
  2491. {
  2492. uint16_t c1 = NOIR;
  2493. uint16_t c2 = VERT;
  2494.  
  2495. test_clic_boutons(&bt_EE_RAZ );
  2496. if(bt_EE_RAZ.cliked)
  2497. {
  2498. bt_EE_RAZ.cliked = false;
  2499. bt_EE_RAZ.selected = false;
  2500. bt_EE_RAZ.affiche(ROUGE, c1, 1);
  2501.  
  2502. EE_RAZ();
  2503. }
  2504. }
  2505.  
  2506.  
  2507. uint16_t EE_find_1ere_mem_libre(uint16_t adr0) // travaille directement sur l'EEPROM (en lecture uniquement!)
  2508. {
  2509. Serial.println("EE_find_1ere_mem_libre");
  2510. uint16_t n =0;
  2511. uint16_t adresse_lue;
  2512. uint32_t valeur_lue;
  2513. boolean ok = false;
  2514. while ((n<400) && (ok == false))
  2515. {
  2516. n += 4;
  2517. adresse_lue = adr0 + n;
  2518. valeur_lue = EEPROM.readUInt(adresse_lue); // 4 octets
  2519. Serial.print("valeur lue: "); Serial.println(valeur_lue);
  2520. if (valeur_lue == 0) {ok = true;}
  2521. }
  2522. Serial.print("trouve: "); Serial.println(n);
  2523. return adresse_lue;
  2524. }
  2525.  
  2526.  
  2527. uint16_t EE_find_if_present(uint16_t adr0, uint32_t F_i) // travaille directement sur l'EEPROM (en lecture uniquement!)
  2528. {
  2529. Serial.println("EE_find_if_present");
  2530. uint16_t n =0;
  2531. uint16_t adresse_lue;
  2532. uint32_t valeur_lue;
  2533. boolean ok = false;
  2534. while ((n<100) && (ok == false))
  2535. {
  2536. n += 4;
  2537. adresse_lue = adr0 + n;
  2538. valeur_lue = EEPROM.readUInt(adresse_lue); // 4 octets
  2539. if (valeur_lue == F_i) {return adresse_lue;} // si F est présente
  2540. }
  2541. return 0; // si F non présente
  2542. }
  2543.  
  2544.  
  2545.  
  2546. void test_clic_bouton_EE_write() // en EEPROM, dans un des groupes (groupe_SW, groupe_FM, groupe_AIR)
  2547. {
  2548. uint16_t c1 = GRIS_6;
  2549. uint16_t c2 = VERT;
  2550.  
  2551. test_clic_boutons(&bt_EE_write );
  2552. if(bt_EE_write.cliked)
  2553. {
  2554. Serial.println("--------------------------------");
  2555. Serial.println("bouton_EE_write clic");
  2556.  
  2557. bt_EE_write.cliked = false;
  2558. bt_EE_write.selected = false;
  2559. bt_EE_write.affiche(GRIS_3, c1, 1);
  2560. delay (300);
  2561. bt_EE_write.cliked = false;
  2562. bt_EE_write.selected = false;
  2563. bt_EE_write.affiche(c1, c2, 1); // fugitif
  2564.  
  2565. //TFT.drawString("WRITE !", 5, 120);
  2566. //TFT.fillRect(5, 120, 50, 30, NOIR); // efface
  2567.  
  2568. uint16_t adr0;
  2569. uint16_t m0;
  2570. if (bande_SW)
  2571. {
  2572. adr0 = groupe_SW.adr_0;
  2573. m0 = EE_find_1ere_mem_libre(adr0);
  2574. }
  2575. if (bande_FM)
  2576. {
  2577. adr0 = groupe_FM.adr_0;
  2578. m0 = EE_find_1ere_mem_libre(adr0);
  2579. }
  2580. if (bande_AIR)
  2581. {
  2582. adr0 = groupe_AIR.adr_0;
  2583. m0 = EE_find_1ere_mem_libre(adr0);
  2584. }
  2585.  
  2586. if( ! EE_find_if_present(adr0, frequence)) // pour éviter les doublons
  2587. {
  2588. Serial.println("EEPROM.writeUInt");
  2589. Serial.print("m0="); Serial.println(m0);
  2590. Serial.print("frequence="); Serial.println(frequence);
  2591.  
  2592. EEPROM.writeUInt(m0, frequence);
  2593. EEPROM.commit();
  2594. delay(500);
  2595. load_GRP_FREQ_EEPROM();
  2596. }
  2597. else
  2598. {
  2599. Serial.print("F=");
  2600. Serial.print(frequence);
  2601. Serial.println(" presente, NO write");
  2602. }
  2603. Serial.println("--------------------------------");
  2604. }
  2605. }
  2606.  
  2607.  
  2608.  
  2609. void test_clic_bt_erase_1F() // en EEPROM
  2610. {
  2611. uint16_t c1 = GRIS_6;
  2612. uint16_t c2 = VERT;
  2613.  
  2614. test_clic_boutons(&bt_erase_1F );
  2615. if(bt_erase_1F.cliked)
  2616. {
  2617. bt_erase_1F.cliked = false;
  2618. bt_erase_1F.selected = false;
  2619. bt_erase_1F.affiche(GRIS_3, c1, 1);
  2620.  
  2621. delay (300);
  2622. bt_erase_1F.cliked = false;
  2623. bt_erase_1F.selected = false;
  2624. bt_erase_1F.affiche(c1, c2, 1); // fugitif
  2625.  
  2626. uint16_t F;
  2627. //uint16_t EE_find_if_present(uint16_t adr0, uint32_t F_i)
  2628.  
  2629. uint16_t adr0, adri;
  2630. if (bande_SW) { adr0 = groupe_SW.adr_0; }
  2631. if (bande_FM) { adr0 = groupe_FM.adr_0; }
  2632. if (bande_AIR) { adr0 = groupe_AIR.adr_0;}
  2633. adri = EE_find_if_present(adr0, frequence);
  2634. if (adri !=0)
  2635. {
  2636. EEPROM.writeUInt(adri, 0);
  2637. EEPROM.commit();
  2638. load_GRP_FREQ_EEPROM();
  2639. }
  2640. }
  2641. }
  2642.  
  2643.  
  2644. void test_clic_boutons_MODE() // FREQ - MEM
  2645. {
  2646. uint16_t c1 = NOIR;
  2647. uint16_t c2 = VERT;
  2648. uint16_t c3 = JAUNE;
  2649.  
  2650. bt_mode_FRQ.cliked = false;
  2651. bt_mode_MEM.cliked = false;
  2652.  
  2653. test_clic_boutons(&bt_mode_FRQ );
  2654. if (bt_mode_FRQ.cliked) // les boutons sont exclusifs
  2655. {
  2656. mode_s = _FRQ;
  2657. bt_mode_FRQ.selected = true;
  2658. bt_mode_MEM.selected = false;
  2659. affiche_frequence(frequence);
  2660. efface_numero_frq();
  2661. }
  2662.  
  2663. test_clic_boutons(&bt_mode_MEM );
  2664. if (bt_mode_MEM.cliked)
  2665. {
  2666. mode_s = _MEM;
  2667. bt_mode_MEM.selected = true;
  2668. bt_mode_FRQ.selected = false;
  2669. //affiche_box_FRQ(JAUNE);
  2670. affiche_frequence(frequence);
  2671. }
  2672.  
  2673. bt_mode_FRQ.affiche(c1, c2, 2);
  2674. bt_mode_MEM.affiche(c1, c3, 2);
  2675. }
  2676.  
  2677.  
  2678. void test_clic_boutons_BANDE() // SW, FM, AIR, SCAN
  2679. {
  2680. uint16_t c1 = GRIS_5;
  2681. uint16_t c2 = VERT;
  2682.  
  2683. bt_SW.cliked = false;
  2684. bt_FM.cliked = false;
  2685. bt_AIR.cliked = false;
  2686.  
  2687. test_clic_boutons(&bt_SW );
  2688. if (bt_SW.cliked)
  2689. {
  2690. TFT.fillRect(x0_box_info1+2, y0_box_info1+2, 120, 12, couleur_fond_ecran); // efface
  2691. Serial.println("bt_SW.cliked");
  2692. bt_SW.cliked = false;
  2693.  
  2694. bande_active = SW;
  2695. modulation_active = AM;
  2696. bt_SW.selected = true;
  2697. bt_FM.selected = false; // les boutons sont exclusifs
  2698. bt_AIR.selected = false;
  2699. bt_SCN.selected = false;
  2700.  
  2701. clic_logiciel_bouton(&presetPad1.bt_preset[0]);
  2702. traite_boutons_presetPad(0);
  2703.  
  2704.  
  2705. uint8_t nb_F = groupe_SW.nb_freq;
  2706. affiche_numero_frq(String(1), String(nb_F));
  2707. }
  2708.  
  2709. test_clic_boutons(&bt_FM );
  2710. if (bt_FM.cliked)
  2711. {
  2712. Serial.println("bt_FM.cliked");
  2713. bt_FM.cliked = false;
  2714.  
  2715. bande_active = FM;
  2716. modulation_active = WFM;
  2717. bt_FM.selected = true;
  2718. bt_SW.selected = false;
  2719. bt_AIR.selected = false;
  2720. bt_SCN.selected = false;
  2721.  
  2722. clic_logiciel_bouton(&presetPad1.bt_preset[0]);
  2723. traite_boutons_presetPad(0);
  2724.  
  2725. uint8_t nb_F = groupe_FM.nb_freq;
  2726. affiche_numero_frq(String(1), String(nb_F));
  2727. }
  2728.  
  2729. test_clic_boutons(&bt_AIR );
  2730. if (bt_AIR.cliked)
  2731. {
  2732. TFT.fillRect(x0_box_info1+2, y0_box_info1+2, 120, 12, couleur_fond_ecran); // efface
  2733. Serial.println("bt_AIR.cliked");
  2734. bt_AIR.cliked = false;
  2735.  
  2736. bande_active = AIR;
  2737. modulation_active = AM;
  2738. bt_AIR.selected = true;
  2739. bt_SW.selected = false;
  2740. bt_FM.selected = false;
  2741. bt_SCN.selected = false;
  2742.  
  2743. clic_logiciel_bouton(&presetPad1.bt_preset[0]);
  2744. traite_boutons_presetPad(0);
  2745.  
  2746. uint8_t nb_F = groupe_AIR.nb_freq;
  2747. affiche_numero_frq(String(1), String(nb_F));
  2748. }
  2749.  
  2750. test_clic_boutons(&bt_SCN );
  2751. if (bt_SCN.cliked == true)
  2752. {
  2753. Serial.println("bt_SCN.cliked");
  2754. bt_SCN.cliked = false;
  2755.  
  2756. bande_active = SCN;
  2757. bt_SCN.selected = true;
  2758. bt_SW.selected = false;
  2759. bt_FM.selected = false;
  2760. bt_AIR.selected = false;
  2761.  
  2762. //clic_logiciel_bouton(&presetPad1.bt_preset[0]);
  2763. //traite_boutons_presetPad(0);
  2764.  
  2765. uint8_t nb_F = groupe_SCAN.nb_freq;
  2766. affiche_numero_frq(String(1), String(nb_F));
  2767. }
  2768.  
  2769. bt_SW.affiche(c1, c2, 1);
  2770. bt_FM.affiche(c1, c2, 1);
  2771. bt_AIR.affiche(c1, c2, 1);
  2772. bt_SCN.affiche(c1, CYAN, 1);
  2773.  
  2774. }
  2775.  
  2776.  
  2777. void test_clic_bouton_set() // bouton pour passer dans le mode d'écriture de la F en cours dans l'EEPROM
  2778. // L'écriture en question sera effectuée par la fonction 'traite_boutons_presetPad()'
  2779. {
  2780. test_clic_boutons(&bt_set);
  2781. if (bt_set.cliked)
  2782. {
  2783. bt_set.cliked = false;
  2784. vu_metre_actif = false;
  2785. TFT.fillRect(x0_box_info2, y0_box_info2, 140, 70, NOIR);
  2786.  
  2787. TFT.setTextColor(VERT, NOIR);
  2788. TFT.setFreeFont(FF0);
  2789. TFT.drawString("Cliquez sur un des 8 bt", x0_box_info2+2, y0_box_info2+2);
  2790. TFT.drawString("'preset' pour lui ", x0_box_info2+2, y0_box_info2+12);
  2791. TFT.drawString("attribuer la F en cours", x0_box_info2+2, y0_box_info2+22);
  2792.  
  2793. init_1_bouton(x0_box_info2+82, y0_box_info2+50, 50, 15, "annuler", &bt_annuler);
  2794. bt_annuler.affiche(NOIR, BLANC, 1);
  2795.  
  2796. mode_affi = SET_F_PRESET; // ce qui modifie le comportement de la fonction 'traite_boutons_presetPad()'
  2797. Serial.println("mode_affi == SET_F_PRESET");
  2798.  
  2799. delay (100);
  2800. bt_set.selected = false;
  2801. bt_set.affiche(NOIR, BLANC, 1);
  2802. }
  2803. }
  2804.  
  2805.  
  2806. void affiche_signal(uint16_t x, uint16_t y, uint16_t dx, int16_t valeur)
  2807. {
  2808. TFT.fillRect(x, y, dx, 8, NOIR); // efface
  2809. if(valeur<0) {valeur =0;}
  2810. if(valeur > dx) {valeur = dx;}
  2811. TFT.drawRect(x, y, dx, 5, couleur_traits);
  2812. TFT.fillRect(x, y, valeur, 5, JAUNE);
  2813. }
  2814.  
  2815.  
  2816. void affiche_tension_batt(uint16_t x, uint16_t y, uint16_t dx, int8_t valeur) // valeur en %
  2817. {
  2818. uint16_t c1;
  2819. c1 = ROUGE;
  2820. if(valeur>30){c1 = ORANGE;}
  2821. if(valeur>50){c1 = JAUNE;}
  2822. if(valeur>70){c1 = VERT;}
  2823.  
  2824. uint32_t v2 = valeur * dx / 100;
  2825. TFT.fillRect(x-20, y, dx, 8, NOIR); // efface
  2826. efface_box_entete3();
  2827. if(v2<0) {valeur =0;}
  2828. if(v2 > dx) {v2 = dx;}
  2829. TFT.drawRect(x, y, dx, 5, couleur_traits);
  2830. TFT.fillRect(x, y, v2, 5, c1);
  2831. String s1 = String(valeur) +"%";
  2832. TFT.setTextColor(BLANC, NOIR);
  2833. TFT.drawString(s1, x-20, y);
  2834.  
  2835. TFT.setFreeFont(FF0);
  2836. TFT.setTextColor(BLANC, NOIR);
  2837. TFT.drawString("bat", x + 10 , y+5);
  2838. }
  2839.  
  2840.  
  2841.  
  2842. void affiche_1_bargraph(uint16_t x, uint16_t y, uint16_t dx, int16_t valeur, uint16_t couleur)
  2843. {
  2844. TFT.fillRect(x, y, dx+40, 8, NOIR); // efface
  2845. TFT.drawString(String(valeur), x, y);
  2846.  
  2847. if(valeur<0) {valeur =0;}
  2848. if(valeur > dx) {valeur = dx;}
  2849. TFT.drawRect(x+40, y, dx, 5, couleur_traits);
  2850. TFT.drawRect(x+40, y, valeur, 5, couleur);
  2851. }
  2852.  
  2853.  
  2854. void affiche_bars_graph()
  2855. {
  2856. affiche_1_bargraph(170, 150, 100, level/10, VERT);
  2857. affiche_1_bargraph(170, 160, 100, usn, JAUNE);
  2858. affiche_1_bargraph(170, 170, 100, wam, BLEU_CLAIR);
  2859. affiche_1_bargraph(170, 180, 100, offset, BLANC);
  2860. }
  2861.  
  2862.  
  2863. String int_to_hex(uint16_t nb)
  2864. {
  2865. char symb[16] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
  2866. uint8_t A = (nb & 0b1111000000000000) >>12;
  2867. uint8_t B = (nb & 0b0000111100000000) >>8;
  2868. uint8_t C = (nb & 0b0000000011110000) >>4;
  2869. uint8_t D = (nb & 0b0000000000001111);
  2870. String s1 = String(symb[A]) + String(symb[B]) + String(symb[C]) + String(symb[D]) ;
  2871. return s1;
  2872. }
  2873.  
  2874.  
  2875.  
  2876. void traite_signal_RDS()
  2877. {
  2878. Get_RDS_Data ( &status, &A_block, &B_block, &C_block, &D_block, &dec_error);
  2879. /*
  2880. A_Block always contains the 16-bit program identifier.
  2881. The first 11 bits (bits 15–5) of block 2 are also the same in all groups.
  2882. La Liste des codes RDS autorisés se trouve ici : https://www.csa.fr/maradiofm/radiords_tableau
  2883. pour les autres blocks, voir :
  2884. https://en.wikipedia.org/wiki/Radio_Data_System
  2885. (c'est sans doute logique mais terriblement indigeste !!!)
  2886. */
  2887.  
  2888. TFT.fillRect(x0_box_info1+2, y0_box_info1+2, 120, 12, couleur_fond_ecran); // efface
  2889. String s1 = int_to_hex(A_block);
  2890.  
  2891. String s2, s3;
  2892. TFT.setTextColor(BLANC, GRIS_5);
  2893.  
  2894. for(int n = 0; n<=nb_stations_RDS-1; n++)
  2895. {
  2896. s2 = codesRDS[n];
  2897. //Serial.println(s2);
  2898. s3 = s2.substring(0, 4);
  2899.  
  2900. if (s3 == s1)
  2901. {
  2902. TFT.drawString(s2, x0_box_info1+5, y0_box_info1 +4);
  2903. return; // on ne continue pas à boucler si trouvé
  2904. }
  2905. else if (n == nb_stations_RDS-1) // pas trouvé...
  2906. {
  2907. TFT.drawString(s1, x0_box_info1+5, y0_box_info1 +4);
  2908. return;
  2909. }
  2910. }
  2911. }
  2912.  
  2913.  
  2914.  
  2915.  
  2916. void affiche_force_signal()
  2917. {
  2918. //----------------------------------------------------------------------------------------------------------
  2919. // AFFICHE FORCE SIGNAL HF
  2920. compteur1 =0;
  2921. uint8_t module;
  2922. if(bande_active == FM) {module = 32;} else {module = 33;}
  2923. Get_Quality( module, &status, &level, &usn, &wam, &offset, &bandwidth, &mod, &snr );
  2924.  
  2925. //float signal_sur_bruit = level;// - 1.5 * usn; // marche à peu près bien pour la FM.
  2926.  
  2927. float diff = level - position_aiguille;
  2928. if(diff > 30.0) {diff = 30.0;}
  2929. if(diff < -30.0) {diff = -30.0;} // évite une trop grande réaction au sortir du mode 'mute'
  2930. // supprime les tremblements de l'aiguille
  2931. position_aiguille += diff / 6.0;
  2932.  
  2933. //affiche_bars_graph();
  2934. affiche_signal(170, 90, 60, mod/2);
  2935. if ((mode_affi == NORMAL) && (! mute) ) { plotAiguille(position_aiguille/6.0); }
  2936. if ((mode_affi == NORMAL) && (mute) ) { plotAiguille(0); }
  2937. }
  2938.  
  2939.  
  2940. void loop()
  2941. {
  2942. if (test_touch_screen == true) {printTouchToDisplay();}
  2943.  
  2944. if((mode_affi != SCAN_F) && (mode_affi != SCAN_M))// invalide les boutons situés derrière le panneau scan en modes SCAN
  2945. {
  2946. if (ts.tirqTouched() && ts.touched())
  2947. {
  2948. TS_Point p = ts.getPoint();
  2949. x_touch = -30 + p.x /11;
  2950. y_touch = -30 + p.y /14;
  2951.  
  2952. test_clic_6_boutons_frq(); // 6 rectangles situés au dessus des gros chiffres de la fréquence
  2953. test_clic_bouton_mute();
  2954. test_clic_bouton_EE_RAZ();
  2955. test_clic_bouton_EE_write();
  2956. test_clic_bt_erase_1F();
  2957. uint8_t n_touch1 = numPad1.test_clic(); // pavé numérique
  2958. if (n_touch1 != 253) { traite_touches_pad(n_touch1); } // pavé numérique
  2959.  
  2960. test_clic_boutons_plus_moins(); // boutons '<' et '>'
  2961. test_clic_bouton_Sleep();
  2962. test_clic_Bt_reset();
  2963. test_clic_Bt_scan_FRQ();
  2964. test_clic_bt_scan_air(); // Scan mémoires
  2965. test_clic_boutons_MODE(); // FREQ / MEM (tout en haut à gauche des gros chiffres)
  2966. test_clic_boutons_BANDE(); // SW, FM, AIR, SC; (SC = SCAN)
  2967.  
  2968. uint8_t num_bouton = presetPad1.test_clic(); // 8 petits boutons carrés de présélection de 8 fréquences
  2969. if (num_bouton != 253) { traite_boutons_presetPad(num_bouton); }
  2970.  
  2971. test_clic_bouton_set(); // attribution de la fréquence en cours à un des 8 boutons preset.
  2972. test_clic_bt_annuler();
  2973.  
  2974. test_clic_bt_affi_saisie_couleur();
  2975. test_clic_bt_RST_affi();
  2976. }
  2977.  
  2978. // la limitation SW max = 28MHz est due au module TEF6686 lui-même
  2979. if (frequence >= 138000) {frequence = 138000;} //138 MHz limite à cause SW max = 28MHz et conv AirBand = 110 MHz
  2980. if (frequence < 1500) {frequence = 1500;} // 1.5 MHz
  2981.  
  2982.  
  2983. if (compteur1 >= 5)
  2984. {
  2985. affiche_force_signal();
  2986.  
  2987. //----------------------------------------------------------------------------------------------------------
  2988. // AFFICHE TENSION BATTERIE
  2989. //----------------------------------------------------------------------------------------------------------
  2990. // voir la feuille de calcul 'Mesure de la tension de la batterie.ods' établie sur tests avec alim numérique
  2991. // voir aussi, sur le schéma, la valeur des résistances (diviseur analogique) sur l'entrée GPIO35 (analogPin = 35)
  2992. // Note: la valeur de la tension sur le pin GPIO35 ne doit jamais dépasser 3v3 (ce qui est lu = 4096)
  2993.  
  2994. int valeurLue = analogRead(analogPin);
  2995. //Serial.print("valeurLue = "); Serial.println(valeurLue);
  2996. float pourcent = ((float)valeurLue - 2570.0) / 10.0;
  2997. if (pourcent > 100.0) {pourcent = 100.0;}
  2998. if (pourcent < 0.0) {pourcent = 0.0;}
  2999.  
  3000. //Serial.print("pourcent = "); Serial.println(pourcent);
  3001.  
  3002. // intégration
  3003. float diff2 = pourcent - valeur_affi;
  3004. if(diff2 > 10.0) {diff2 = 10.0;}
  3005. if(diff2 < -10.0) {diff2 = -10.0;} // évite une trop grande réaction au sortir du mode 'mute'
  3006. valeur_affi += diff2 / 10.0;
  3007.  
  3008. if ( abs(valeur_affi - memo_valeur_affi) > 1.5 ) // pour éviter trop d'affichages inutiles (et clignotements à l'écran)
  3009. {
  3010. affiche_tension_batt(270, 4, 46, (int8_t) valeur_affi);
  3011. memo_valeur_affi = valeur_affi;
  3012. }
  3013. }
  3014.  
  3015. if (compteur2 >= 100)
  3016. {
  3017. compteur2 =0;
  3018.  
  3019. if(bande_active == FM) {traite_signal_RDS();}
  3020.  
  3021. /*
  3022. TFT.drawString(
  3023. String(A_block) + " " +
  3024. String(B_block) + " " +
  3025. String(C_block) + " " +
  3026. String(D_block) + " ", x0_box_info1+5, y0_box_info1 +4);
  3027. */
  3028. }
  3029.  
  3030. #ifdef _SD_CARD
  3031. if (compteur3 == 2000)
  3032. {
  3033. write_TFT_on_SDcard(); // attention : incompatible avec le TOUCHPAD
  3034. }
  3035. #endif
  3036.  
  3037. delay(10);
  3038. compteur1++;
  3039. compteur2++;
  3040. }
  3041.  
  3042. }
  3043.  
  3044.  
  3045. /** ***************************************************************************************
  3046. CLASS TOUCH_BOUTON // affiche un nombre ou un petit texte dans un rectangle
  3047. ainsi que (en plus petit) deux valeurs supplémentaires, par ex: les valeurs mini et maxi
  3048. ********************************************************************************************/
  3049.  
  3050. // Constructeur
  3051. TOUCH_BOUTON::TOUCH_BOUTON()
  3052. {
  3053.  
  3054. }
  3055.  
  3056. // Constructeur
  3057. TOUCH_BOUTON_PRESET::TOUCH_BOUTON_PRESET()
  3058. {
  3059.  
  3060. }
  3061.  
  3062.  
  3063.  
  3064. void TOUCH_BOUTON::init(uint16_t xi, uint16_t yi, uint8_t dxi, uint8_t dyi, uint8_t dri)
  3065. {
  3066. x0 = xi;
  3067. y0 = yi;
  3068. dx = dxi;
  3069. dy = dyi;
  3070. dr = dri;
  3071.  
  3072. cliked = false;
  3073. selected = false;
  3074. }
  3075.  
  3076.  
  3077.  
  3078. void TOUCH_BOUTON::affiche(uint16_t coul_fill_unselect, uint16_t coul_fill_select, uint8_t n_font)
  3079. {
  3080. //uint16_t c1 = NOIR;
  3081. uint16_t couleur_contour = GRIS_5;
  3082. uint16_t couleur_texte = BLANC;
  3083.  
  3084. if(selected)
  3085. {
  3086. TFT.fillRoundRect(x0, y0, dx, dy, dr, coul_fill_select);
  3087. TFT.setTextColor(NOIR);
  3088. }
  3089. else
  3090. {
  3091. TFT.fillRoundRect(x0, y0, dx, dy, dr, coul_fill_unselect); // efface
  3092. TFT.drawRoundRect(x0, y0, dx, dy, dr, couleur_contour); // retrace juste le contour
  3093. TFT.setTextColor(couleur_texte);
  3094. }
  3095.  
  3096. //uint8_t dy = 0;
  3097. //FM9 FMB9 FSS9... voir le fichier Free_Fonts.h
  3098. if (n_font == 1) { TFT.setFreeFont(FF0);}
  3099. if (n_font == 2) { TFT.setFreeFont(FM9);}
  3100. if (n_font == 3) { TFT.setFreeFont(FMB9);}
  3101. if (n_font == 4) { TFT.setFreeFont(FSS9);}
  3102.  
  3103. TFT.drawString(s, x0+3, y0 + 2);
  3104. }
  3105.  
  3106. uint8_t TOUCH_BOUTON::read_dx()
  3107. {
  3108. return dx;
  3109. }
  3110.  
  3111. uint8_t TOUCH_BOUTON::read_dy()
  3112. {
  3113. return dy;
  3114. }
  3115.  
  3116.  
  3117.  
  3118.  
  3119. /** ***************************************************************************************
  3120. CLASS NUMPAD
  3121. ********************************************************************************************/
  3122. // Constructeur
  3123. NUM_PAD::NUM_PAD()
  3124. {
  3125.  
  3126. }
  3127.  
  3128.  
  3129.  
  3130. void NUM_PAD::init(uint16_t xi, uint16_t yi, boolean fond) // si fond =false, ne resessine que les boutons
  3131. {
  3132. x0 = xi;
  3133. y0 = yi;
  3134. uint16_t x, y;
  3135. uint8_t dxt = 25; // taille x d'une touche
  3136. uint8_t dyt = 23; // taille y d'une touche
  3137.  
  3138. if(fond == true) {TFT.fillRect(x0, y0, 3*dxt +6, 4*dyt +7, NOIR);}
  3139.  
  3140. if(fond == true) {TFT.fillRect(x0, y0, 3*dxt +6, 4*dyt +7, NOIR);}
  3141.  
  3142. uint16_t c1 = GRIS_5;
  3143. uint16_t c2 = JAUNE;
  3144.  
  3145. x = x0+2;
  3146. y = y0+2;
  3147.  
  3148. for(uint8_t n =1; n<10; n++)
  3149. {
  3150. bt_pad[n].init(x, y, dxt, dyt, 3);
  3151. bt_pad[n].s=String(n);
  3152. bt_pad[n].affiche(c1, c2, 2);
  3153. x += dxt+1;
  3154. if (x > (x0 + 3*dxt)) {x = x0+2; y += dyt+1; }
  3155. }
  3156. bt_pad[0].init(x, y, dxt, dyt, 3); bt_pad[0].s="0"; bt_pad[0].affiche(c1, c2, 2); x += dxt+1;
  3157. bt_point.init(x, y, dxt, dyt, 3); bt_point.s="."; bt_point.affiche(c1, c2, 2);
  3158.  
  3159. x += dxt+1;
  3160. bt_ok.init(x, y, dxt, dyt, 3); bt_ok.s="ok";
  3161. bt_ok.affiche(c1, c2, 1);
  3162. }
  3163.  
  3164.  
  3165. uint8_t NUM_PAD::test_clic()
  3166. {
  3167. // zone des boutons du clavier
  3168. if ( (( x_touch > x0) && (x_touch < x0 + 100)) && (( y_touch > y0) && (y_touch < y0 + 130)))
  3169. {
  3170. uint8_t num_touche =0;
  3171.  
  3172. for(uint8_t n = 0; n<10; n++)
  3173. {
  3174. test_clic_boutons(&bt_pad[n] ); if(bt_pad[n].cliked) {num_touche=n; n_appui ++;}
  3175. }
  3176.  
  3177. test_clic_boutons(&bt_point ); if(bt_point.cliked) {num_touche=254; } // bouton "."
  3178. test_clic_boutons(&bt_ok ); if(bt_ok.cliked) {num_touche=255; n_appui ++;} // bouton "ok"
  3179. delay(100);
  3180. init(x0, y0, false); // 'false' évite le clignotement lorsqu'on repeint le fond noir
  3181.  
  3182. return num_touche;
  3183. }
  3184. return 253;
  3185. }
  3186.  
  3187. /** ***************************************************************************************
  3188. CLASS PRESET_PAD
  3189. ********************************************************************************************/
  3190.  
  3191. // Constructeur
  3192. PRESET_PAD::PRESET_PAD()
  3193. {
  3194.  
  3195. }
  3196.  
  3197.  
  3198. void PRESET_PAD::init(uint16_t xi, uint16_t yi)
  3199. {
  3200. x0 = xi;
  3201. y0 = yi;
  3202.  
  3203.  
  3204. uint16_t c1 = GRIS_5;
  3205. uint16_t c2 = JAUNE;
  3206.  
  3207. uint16_t x2, y2;
  3208. x2 = x0;
  3209. y2= y0;
  3210.  
  3211. for(uint8_t n=0; n<8; n++)
  3212. {
  3213. bt_preset[n].init(x2, y2, 15, 15, 3);
  3214. bt_preset[n].s=String(n+1);
  3215. if(mode_affi == COUL) {c1 = bt_preset[n].couleur;}
  3216. bt_preset[n].affiche(c1, c2, 1);
  3217. x2 += 20;
  3218. }
  3219. }
  3220.  
  3221.  
  3222. uint8_t PRESET_PAD::read_dx()
  3223. {
  3224. return dx;
  3225. }
  3226.  
  3227.  
  3228. uint8_t PRESET_PAD::read_dy()
  3229. {
  3230. return dy;
  3231. }
  3232.  
  3233.  
  3234. void PRESET_PAD::set_frequences() // lit les fréquences en EEPROM et les attribue à chaque bouton
  3235. {
  3236. Serial.println("");
  3237. Serial.println("void PRESET_PAD::set_frequences() // lit les frequences en EEPROM et les attribue a chaque bouton");
  3238. uint16_t decal=0;
  3239. uint8_t n=0;
  3240.  
  3241. Serial.println("SW ---------------------------");
  3242. for(int n=0; n<8; n++)
  3243. {
  3244. frequence = EEPROM.readUInt(frq_preset_adr_0 + decal); // uint32_ t frequence, soit 4 octets
  3245. Serial.print("f= "); Serial.println(frequence);
  3246. if (! (bande_SW)) {frequence = 2000;}
  3247. bt_preset[n].frequence_SW = frequence;
  3248. decal += 4;
  3249. }
  3250.  
  3251. Serial.println("FM ---------------------------");
  3252. for(int n=0; n<8; n++)
  3253. {
  3254. frequence = EEPROM.readUInt(frq_preset_adr_0 + decal); // uint32_ t frequence, soit 4 octets
  3255. Serial.print("f= "); Serial.println(frequence);
  3256. if (! (bande_FM)) {frequence = 88000;}
  3257. bt_preset[n].frequence_FM = frequence;
  3258. decal += 4;
  3259. }
  3260.  
  3261. Serial.println("AIR ---------------------------");
  3262. for(int n=0; n<8; n++)
  3263. {
  3264. frequence = EEPROM.readUInt(frq_preset_adr_0 + decal); // uint32_ t frequence, soit 4 octets
  3265. Serial.print("f= "); Serial.println(frequence);
  3266. if (! (bande_AIR)) {frequence = 118000;}
  3267. bt_preset[n].frequence_AIR= frequence;
  3268. //decal += 4;
  3269. }
  3270. }
  3271.  
  3272.  
  3273. void PRESET_PAD::set_couleurs()
  3274. {
  3275. bt_preset[0].couleur = 10240; // rouge sombre
  3276. bt_preset[1].couleur = 14528; // orange
  3277. bt_preset[2].couleur = 320; // vert
  3278. bt_preset[3].couleur = 14407; // violet
  3279. bt_preset[4].couleur = 26787; // rose
  3280. bt_preset[5].couleur = 260; // cyan
  3281. bt_preset[6].couleur = 267; // bleu ciel
  3282. bt_preset[7].couleur = 4; // bleu marine
  3283. }
  3284.  
  3285.  
  3286.  
  3287. void PRESET_PAD::deselect_boutons()
  3288. {
  3289. uint16_t c1 = GRIS_5;
  3290. uint16_t c2 = JAUNE;
  3291.  
  3292. for(int n =0; n<8; n++)
  3293. {
  3294. bt_preset[n].selected=false;
  3295. bt_preset[n].cliked=false;
  3296. bt_preset[n].affiche(c1, c2, 1);
  3297. }
  3298. }
  3299.  
  3300.  
  3301. uint8_t PRESET_PAD::test_clic()
  3302. {
  3303. if ( (( x_touch > x0) && (x_touch < (x0+155))) && (( y_touch > y0) && (y_touch < (y0+15))))
  3304. {
  3305. uint8_t num_bouton =0;
  3306. for(uint8_t n=0; n<8; n++)
  3307. {
  3308. test_clic_boutons(&bt_preset[n]);
  3309. if(bt_preset[n].cliked)
  3310. {
  3311. deselect_boutons(); // les autres
  3312. bt_preset[n].selected =true; // pour l'affichage de celui-ci
  3313. bt_preset[n].affiche(GRIS_5, VERT, 1);
  3314. num_bouton = n;
  3315. Serial.print("BB num_bouton= "); Serial.println(num_bouton);
  3316. }
  3317. }
  3318. return num_bouton;
  3319. }
  3320. return 253;
  3321. }
  3322.  
  3323.  
  3324.  
  3325.  
  3326.  
  3327.  
  3328. /** ***************************************************************************************
  3329. CLASS GROUPE_FREQUENCES // objet image d'un bloc mémoire en EEPROM
  3330. permet diverses manipulations en RAM (tri...) sans toucher à l'EEPROM
  3331. ********************************************************************************************/
  3332.  
  3333. // Constructeur
  3334. GROUPE_FREQUENCES::GROUPE_FREQUENCES()
  3335. {
  3336.  
  3337. }
  3338.  
  3339.  
  3340. void GROUPE_FREQUENCES::RAZ() // en RAM uniquement
  3341. {
  3342. for(int n=0; n<100; n++)
  3343. {
  3344. G_freq[n]=0;
  3345. }
  3346. nb_freq = 0;
  3347. }
  3348.  
  3349.  
  3350. void GROUPE_FREQUENCES::load_bloc() // depuis l'EEPROM
  3351. {
  3352. // partie données de fréquences (adrs >100)
  3353. Serial.println("load_bloc()");
  3354. //Serial.print("adr_0= "); Serial.println(adr_0);
  3355. uint32_t valeur_lue;
  3356. for(uint16_t n = 0; n<100; n++ ) // chaque uint32_t lu = 4 Bytes
  3357. {
  3358. valeur_lue = EEPROM.readUInt(adr_0 + n*4); // 4 octets
  3359. G_freq[n]=valeur_lue;
  3360. }
  3361. }
  3362.  
  3363.  
  3364. void GROUPE_FREQUENCES::tri_bloc()
  3365. {
  3366. Serial.println("tri_block()");
  3367. // tri par bulles
  3368.  
  3369. uint32_t F1=0, F2=0;
  3370. uint32_t Fi;
  3371. uint16_t i_max = 100;
  3372. uint16_t p_max = 100;
  3373.  
  3374. for(uint16_t p=0; p<p_max; p++)
  3375. {
  3376. for(int n=0; n<i_max-1; n++)
  3377. {
  3378. F1=G_freq[n];
  3379. F2=G_freq[n+1];
  3380.  
  3381. if(F1 > F2)
  3382. {
  3383. Fi = G_freq[n];
  3384. G_freq[n] = G_freq[n+1];
  3385. G_freq[n+1] = Fi;
  3386. }
  3387. }
  3388. }
  3389.  
  3390. // compte le nombre de fréquences != 0
  3391. uint16_t nombre =0;
  3392. for(uint16_t n = 0; n<100; n++ )
  3393. {
  3394. F1 = G_freq[n];
  3395. if(F1 != 0) { nombre++; }
  3396. }
  3397. nb_freq = nombre;
  3398.  
  3399. // recherche première fréquence non nulle
  3400. uint16_t n2=0;
  3401. F1 =0;
  3402. while ((F1==0) && (n2<100))
  3403. {
  3404. F1=G_freq[n2];
  3405. n2++;
  3406. }
  3407. adr_1ere_frq = n2-1; // 1ere F non nulle
  3408. }
  3409.  
  3410.  
  3411. void GROUPE_FREQUENCES::bloc_to_serial() // pour tests, avec CuteCom sous Linux
  3412. {
  3413. Serial.println("bloc_to_serial()");
  3414. uint32_t valeur_lue;
  3415. uint16_t nombre =0;
  3416. for(uint16_t n = 0; n<100; n++ )
  3417. {
  3418. valeur_lue = G_freq[n];
  3419. if(valeur_lue != 0) // n'affiche pas les emplacements vides
  3420. {
  3421. nombre++;
  3422. Serial.println(valeur_lue);
  3423. }
  3424. }
  3425. Serial.print(nombre); Serial.println(" frequences");
  3426. Serial.print("adr 1ere Frq (dans le groupe) = "); Serial.println(adr_1ere_frq);
  3427. Serial.print("1ere Frq= "); Serial.println(G_freq[adr_1ere_frq]);
  3428.  
  3429. }
  3430.  
  3431.  
  3432. void GROUPE_FREQUENCES::add_frq(uint32_t Fi) // en RAM uniquement
  3433. {
  3434. if (nb_freq >= 100) {return;}
  3435. Serial.println("GROUPE_FREQUENCES::add_frq()");
  3436.  
  3437. tri_bloc(); // les F nulles se retrouvent en haut
  3438. Serial.print("Ajout frequence: "); Serial.println(Fi);
  3439. G_freq[0] = Fi; // la nouvelle fréquence est placée en haut
  3440. nb_freq++;
  3441. tri_bloc(); // la nouvelle fréquence se retrouve rangée dans l'ordre de F croissantes
  3442.  
  3443. }
  3444.  
  3445.  
  3446.  
  3447. void GROUPE_FREQUENCES::erase_1_freq(uint32_t Fi) // en RAM
  3448. {
  3449. Serial.println("GROUPE_FREQUENCES::erase_1_freq()");
  3450. uint32_t valeur_lue;
  3451. for(int n=0; n<100; n++)
  3452. {
  3453. valeur_lue = G_freq[n];
  3454. if(valeur_lue == Fi)
  3455. {
  3456. G_freq[n]=0;
  3457. }
  3458. }
  3459. tri_bloc();
  3460. }
  3461.  
  3462.  

Voir plus bas "Documents" le code source complet comprenant les 'includes' et 'library' pour PlatformIO.
Remarque : Lorsque le module tuner TEF6686 n'est pas présent, n'est pas connecté physiquement à la carte CYD, le programme tourne très lentement, l'ESP32 passant son temps à attendre des réponses aux requêtes qu'il envoie sur le bus SPI.

13 Fichier source driver TEF6686_628.cpp

CODE SOURCE en C++
  1. /*************************************************************************************
  2. NOTE Silicium628
  3.  
  4. Les fonctions ci-dessous sont inspirées le plus directement possible de la lecture du pdf "TEF668X User Manuel" (NPX)
  5. Je n'utilise pas l'opérateur conditionnel ternaire ((condition) ? a : b) qui, bien que de haut niveau
  6. et permettant une écriture concise, ne facilite pas la lisibilité du programme.
  7.  
  8. **************************************************************************************/
  9.  
  10.  
  11. #include <Arduino.h>
  12. #include "Wire.h"
  13. #include "driverTEF6686_628.h"
  14.  
  15. byte addr_ISP = 0x64; // adresse du module TEF6686
  16.  
  17. #define conv8to16(a) ((uint16_t)(((uint16_t)(*(a))) << 8 |((uint16_t)(*(a+1)))))
  18.  
  19.  
  20. void Write2(uint8_t *buf, uint8_t len)
  21. {
  22. Wire.beginTransmission(addr_ISP);
  23. for (int i = 0; i < len; i++)
  24. {
  25. Wire.write(*buf++);
  26. }
  27. Wire.endTransmission();
  28. }
  29.  
  30.  
  31. void Set_Cmd(uint8_t module, uint8_t cmd, int len, ...)
  32. {
  33. uint8_t i;
  34. uint8_t buf[31];
  35. uint16_t temp;
  36. va_list vArgs;
  37. va_start(vArgs, len);
  38. buf[0] = module;
  39. buf[1] = cmd;
  40. buf[2] = 1;
  41. for (i = 0; i < len; i++)
  42. {
  43. temp = va_arg(vArgs, int);
  44. buf[3 + i * 2] = (uint8_t)(temp >> 8);
  45. buf[4 + i * 2] = (uint8_t)temp;
  46. }
  47.  
  48. va_end(vArgs);
  49. Write2(buf, len * 2 + 3);
  50. }
  51.  
  52.  
  53. void Set_Volume(int v)
  54. {
  55. Set_Cmd(48, 11, 1, 0); //unmute (IMPORTANT sinon débute en mode MUTE...)
  56. int MapVolume = map(v, 0, 100, -599, 50);
  57. Set_Cmd(48, 10, 1, MapVolume); // module 48 : AUDIO = Audio processing
  58. }
  59.  
  60.  
  61.  
  62. void Tune_Frequence_FM(uint16_t F)
  63. {
  64. uint8_t octet_L, octet_H;
  65.  
  66. octet_L = F%256;
  67. octet_H = F/256;
  68.  
  69. Wire.beginTransmission(addr_ISP);
  70. Wire.write(0x20);
  71. Wire.write(0x01);
  72. Wire.write(0x01);
  73. Wire.write(0x00);
  74. Wire.write(0x01);
  75. Wire.write(octet_H);
  76. Wire.write(octet_L);
  77. Wire.endTransmission();
  78. }
  79.  
  80.  
  81. void Tune_Frequence_AM(uint16_t F)
  82. {
  83. uint8_t octet_L, octet_H;
  84.  
  85. octet_L = F%256;
  86. octet_H = F/256;
  87.  
  88. Wire.beginTransmission(addr_ISP);
  89. Wire.write(0x21);
  90. Wire.write(0x01);
  91. Wire.write(0x01);
  92. Wire.write(0x00);
  93. Wire.write(0x01);
  94. Wire.write(octet_H);
  95. Wire.write(octet_L);
  96. Wire.endTransmission();
  97. }
  98.  
  99.  
  100.  
  101. void Set_Mute(boolean M)
  102. {
  103. if (M == true) //radio standby mode (low-power mode without radio functionality)
  104. {
  105. Wire.beginTransmission(addr_ISP);
  106. Wire.write(0x40);
  107. Wire.write(0x01);
  108. Wire.write(0x01);
  109. Wire.endTransmission();
  110. }
  111. else // normal operation
  112. {
  113. Wire.beginTransmission(addr_ISP);
  114. Wire.write(0x40);
  115. Wire.write(0x01);
  116. Wire.write(0x00);
  117. Wire.endTransmission();
  118. }
  119. }
  120.  
  121.  
  122. void Set_no_AM_gain_reduction()
  123. {
  124. Wire.beginTransmission(addr_ISP);
  125. Wire.write(0x21); // 33
  126. Wire.write(0x0C); // 12
  127. Wire.write(0x01);
  128. Wire.write(0x00);
  129. Wire.write(0x00);
  130. Wire.endTransmission();
  131. }
  132.  
  133.  
  134. bool Tuner_WriteBuffer(uint8_t *buf, uint16_t len)
  135. {
  136. Wire.beginTransmission(0x64);
  137. for (uint16_t i = 0; i < len; i++) {Wire.write(buf[i]);}
  138. uint8_t r = Wire.endTransmission();
  139. delay(2);
  140. if(r==0) {return 1;}
  141. else {return 0;} // l'opérateur conditionnel ternaire (?) c'est pas mon truc !
  142. }
  143.  
  144.  
  145. bool Tuner_ReadBuffer(uint8_t *buf, uint16_t len)
  146. {
  147. Wire.requestFrom(0x64, len);
  148. if (Wire.available() == len)
  149. {
  150. for (uint16_t i = 0; i < len; i++) { buf[i] = Wire.read(); }
  151. return 1;
  152. }
  153. else {return 0;}
  154. }
  155.  
  156.  
  157. bool Tuner_Get_Cmd(uint8_t module, uint8_t cmd, uint8_t *receive, uint16_t len)
  158. {
  159. uint8_t buf[3];
  160. buf[0] = module;
  161. buf[1] = cmd;
  162. buf[2] = 1;
  163.  
  164. Tuner_WriteBuffer(buf, 3);
  165. return Tuner_ReadBuffer(receive, len); // 1 si ok, 0 si erreur
  166. }
  167.  
  168.  
  169. void Get_Quality (
  170. // paramètres passés par adresse (donc variables), tous actualisés par cette fonction
  171. // tous des uint16_t ou int16_t sauf le dernier int8_t
  172. //ce qui nous fait 7*2 +1 = 15 octets lus dans le module
  173. uint8_t module,
  174. uint16_t *status,
  175. int16_t *level,
  176. uint16_t *usn,
  177. uint16_t *wam,
  178. int16_t *offset,
  179. uint16_t *bandwidth,
  180. uint16_t *mod,
  181. int8_t *snr )
  182. {
  183. uint8_t buf[14];
  184.  
  185. uint16_t r = Tuner_Get_Cmd(module, 129, buf, sizeof(buf));
  186.  
  187. // voir datasheet du TEF6686
  188. // actualisation des paramètres
  189. *status = conv8to16(buf);
  190. *level = conv8to16(buf + 2);
  191. *usn = conv8to16(buf + 4); // noise
  192. *wam = conv8to16(buf + 6); // ‘wideband-AM’
  193. *offset = conv8to16(buf + 8); //radio frequency offset
  194. *bandwidth = conv8to16(buf + 10) / 10; // IF bandwidth
  195. *mod = conv8to16(buf + 12) / 10; // modulation detector
  196. if (*level < -200) *level = -200;
  197. if (*level > 1200) *level = 1200;
  198. *snr = int(0.46222375 * (float)(*level) / 10 - 0.082495118 * (float)(*usn) / 10) + 10;
  199. }
  200.  
  201.  
  202. bool Get_RDS_Data (
  203. uint16_t *status,
  204. uint16_t *A_block,
  205. uint16_t *B_block,
  206. uint16_t *C_block,
  207. uint16_t *D_block,
  208. uint16_t *dec_error)
  209. {
  210. uint8_t buf[12];
  211. uint8_t r = Tuner_Get_Cmd(32, 131, buf, sizeof(buf));
  212. *status = conv8to16(buf);
  213. *A_block = conv8to16(buf + 2);
  214. *B_block = conv8to16(buf + 4);
  215. *C_block = conv8to16(buf + 6);
  216. *D_block = conv8to16(buf + 8);
  217. *dec_error = conv8to16(buf + 10);
  218. return r;
  219. }

14 Fichier source main.h

CODE SOURCE en C++
  1. #include <Arduino.h>
  2.  
  3.  
  4. /** ***********************************************************************************
  5. CLASS
  6. ***************************************************************************************/
  7.  
  8. class TOUCH_BOUTON
  9. {
  10. protected:
  11. uint8_t dx;
  12. uint8_t dy;
  13. uint8_t dr; // rayon de courbure des angles
  14.  
  15. public:
  16. uint16_t x0;
  17. uint16_t y0;
  18.  
  19. String s;
  20. boolean cliked;
  21. boolean selected;
  22.  
  23. uint8_t read_dx();
  24. uint8_t read_dy();
  25.  
  26. TOUCH_BOUTON(); // constructeur
  27.  
  28. void init(uint16_t xi, uint16_t yi, uint8_t dxi, uint8_t dyi, uint8_t dri);
  29. void affiche(uint16_t coul_fill_unselect, uint16_t coul_fill_select, uint8_t n_font);
  30.  
  31. private:
  32.  
  33. };
  34.  
  35.  
  36. class TOUCH_BOUTON_PRESET : public TOUCH_BOUTON
  37. {
  38. public:
  39. uint32_t frequence_SW; // 4 octets
  40. uint32_t frequence_FM; // 4 octets
  41. uint32_t frequence_AIR;// 4 octets
  42. String nom;
  43. uint16_t couleur;
  44.  
  45. TOUCH_BOUTON_PRESET(); // constructeur
  46.  
  47. private:
  48.  
  49. };
  50.  
  51.  
  52. /** ***************************************************************************************
  53. CLASS PRESET_PAD // objet 8 touches d'accès rapide à 8 fréquences favorites adns chaque gamme
  54. ********************************************************************************************/
  55. class PRESET_PAD
  56. {
  57. protected:
  58. uint8_t dx;
  59. uint8_t dy;
  60.  
  61. public:
  62. uint8_t x0;
  63. uint8_t y0;
  64.  
  65. TOUCH_BOUTON_PRESET bt_preset[8];
  66.  
  67. PRESET_PAD(); // constructeur
  68.  
  69. void init(uint16_t x0, uint16_t y0);
  70. uint8_t read_dx();
  71. uint8_t read_dy();
  72. void set_frequences();
  73. void set_couleurs();
  74.  
  75. void deselect_boutons();
  76. uint8_t test_clic();
  77. //void traite_presetPad(uint8_t n_touch);
  78.  
  79. private:
  80.  
  81. };
  82.  
  83. /** ***************************************************************************************
  84. CLASS NUM_PAD // objet clavier numérique
  85. ********************************************************************************************/
  86.  
  87.  
  88. class NUM_PAD
  89. {
  90. protected:
  91.  
  92.  
  93. public:
  94. uint8_t x0;
  95. uint8_t y0;
  96.  
  97. TOUCH_BOUTON bt_pad[10];
  98.  
  99. TOUCH_BOUTON bt_point;
  100. TOUCH_BOUTON bt_ok;
  101.  
  102. NUM_PAD(); // constructeur
  103.  
  104. void init(uint16_t x0, uint16_t y0, boolean fond);
  105. uint8_t test_clic();
  106.  
  107. private:
  108.  
  109. };
  110.  
  111.  
  112. /** ***************************************************************************************
  113. CLASS GROUPE_FREQUENCES // objet image d'un bloc mémoire en EEPROM
  114. permet diverses manipulations en RAM (tri...) sans toucher à l'EEPROM
  115. ********************************************************************************************/
  116. class GROUPE_FREQUENCES
  117. {
  118. public:
  119. uint32_t G_freq[100];
  120. uint16_t adr_0; // adresse du groupe en EEPROM
  121. uint16_t adr_1ere_frq; // après un tri les F=0 se retrouvent en haut de liste. La 1ere F se retrouve donc bien plus bas
  122. uint16_t nb_freq; // nombre de fréquences !=0 enregistées
  123. uint16_t num_F_actuelle;
  124.  
  125. GROUPE_FREQUENCES(); // constructeur
  126.  
  127. void RAZ();
  128. void load_bloc(); // depuis l'EEPROM
  129. void bloc_to_serial(); // pour tests
  130. void tri_bloc(); // par valeur numérique des fréquences
  131. void add_frq(uint32_t Fi);
  132. void erase_1_freq(uint32_t Fi);
  133.  
  134. private:
  135.  
  136. };
  137.  
  138.  
  139.  
  140. // ************************************************************************************
  141.  
  142.  
  143. void setup();
  144. void loop();
  145. void init_sprites();
  146. void affiche_unit(String s);
  147. void affiche_band(String s);
  148. void efface_box_entete2();
  149. void efface_box_entete3();
  150. //void affiche_box_choix_couleur();
  151. //void affi_valeurs_RGB();
  152. void affiche_box_FRQ(uint16_t couleur);
  153. void affiche_box_presets();
  154. void deselect_boutons_presets();
  155. void affiche_box_GROUPE();
  156. void efface_box_GROUPE();
  157. void affiche_box_boutons_scan();
  158. void affiche_box_EEPROM();
  159. void affiche_box_FRQ(uint16_t couleur);
  160. void affiche_frequence(uint32_t frq); // en kHz
  161. void affiche_index_frq();
  162. void affiche_force_signal();
  163. void clic_logiciel_bouton(TOUCH_BOUTON *bouton_i);
  164. void dessine_VuMetre();
  165. void init_box_info();
  166. void test_clic_boutons_BANDE();
  167. void scan_frq();
  168.  
  169. //void Tune_Frequence_FM(uint16_t F);
  170. void Set_Volume(int v);

15 à suivre...

16 décembre 2025 :
en cours : Scanner (en particulier pour les messages ultra-courts de la bande aviation).

Il reste encore des choses à faire :
  • Règlage numérique du volume.
  • règler les paramètres de la CAG (gain)
  • Scanner (avec, et aussi sans mise en mémoire des stations), pas le genre de truc qui efface toute la mémoire à la moindre erreur de manip !!!!
  • Utiliser les fonctions WiFi de l'ESP32 pour récupérer et gérer les stations depuis l'ordinateur et éventuellement le téléphone.
  • Ajouter un bouton de sélection pas à pas rotatif. (difficulté: trouver 2 ports GPIO libres !)
  • Connecter une interface matérielle (comprenant un ESP32 classique) pleine de boutons par WiFi (Bluetooth), voire même une souris !
  • ...
29 décembre 2025 :
Le scan de fréquences fonctionne correctement pour la bande FM. (mémorisation des stations détectées dans un groupe de fréquence à part (pas directement dans le groupe FM, ceci afin de ne pas modifier ce groupe. On peut alors parcourir les stations une à une dans ce groupe "SCAN" et éventuellement les enregistrer dans le groupe FM le cas échéant).

Le scan de la bande aviation (en fait des fréquences précedemment enregistrées dans le groupe de fréquences AIR BAND) avec arrêt sur les fréquences actives et reprise du scan auto à la fin des messages est également fonctionnel comme vous pouvez le voir sur une des vidéos plus haut.

Je vais maintenant implémenter la liaison WiFi / Bluetooth pour gérer les fréquences extérieurement.

Un scoop au passage : J'ai commandé une puce Si4684 dans le but de réaliser un récepteur de radio numérique DAB+ : Un nouvel article vous décrira l'évolution de cette étude.

05 janvier 2026 :
Bonne année à toutes et à tous !

Je viens de publier la version 19.0 du firmware :
- programmation davantage orienté objet (avec de nouvelles "class") ce qui rend la structure générale plus solide et en facilite la compréhension (oui, même pour moi qui en suis l'auteur, il m'arrive de chercher plusieurs minutes tel ou tel détail, malgré toutes les possibilités de recherche que nous offre l'éditeur PlatformIO).

- Dans cette version 19.0 il est possible d'attribuer (et enregistrer en EEPROM) les fréquences des 8 boutons 'preset' par un simple clic. Par défaut les 8 boutons pointent sur 2.000 MHz en SW, 88.0 MHz en FM et 118 MHz en bande aviation. A vous de configurer tout ça, sans être obligé de modifier le code source.

Cet article est en cours de rédaction permanente, je publie les avancées pratiquement chaque jour, avec bien entendu mise à jour du logiciel.

16 Documents

Un aperçu du code en cours de rédaction dans l'éditeur de VScode + PlatformIO

Code source en C++
30 novembre 2025 : Version du code source adaptée à l’éditeur VScode/PlatformIO
L'avantage par rapport à l'EDI Arduino c'est que ça encapsule toutes les dépendances et les bibliothèques nécessaires et dans la bonne version.

17 -

Liens...

914