Récepteur radio à TEF6686 + ILI9341 + SDcard.

Soit l'équivalent d'une CYD (Cheap Yellow Card) MAIS avec lecteur SDcard utilisable et 14 GPIO disponibles !

1 Le pourquoi de cette étude :

Comme je vous l'ai expliqué ( dans un précédent article ), la carte CYD bien que qualifiée de "formidable" et "merveilleuse" par nombre d'utilisateurs souffre de plusieurs défauts assez rédibitoires :
  • Le fait de ne pas pouvoir utiliser facilement le lecteur SDcard, l'afficheur et le Touchscreen ensembles dans un même programme.
  • La difficulté pour récupérer une capture d'écran sur le PC (download des fichiers SPIFFS -> PC problématique; éventuellement par hébergement d'une interface web(?)
  • Le manque cruel de ports GPIO libres sur l'ESP32 (je voudrais en particulier pouvoir utiliser des encodeurs rotatifs pas à pas)
  • Le fait de devoir utiliser l'application VScode/Platformio pour simplement mettre à jour les fichiers en mémoire SPIFFS; Insérer une SDcard compatible avec n'importe quel PC / Smartphone serait très appréciable. (on pourrait toutefois passer par une liaison WiFi / Bluetooth avec l'ESP32,)
Ce sont les raisons qui me font entreprendre le développement d'une carte personnalisée, en fait un simple circuit imprimé, reliant une Carte "ESP32 USB-C WROOM Devkit V1" et un "afficheur ILI9341 + Ecran tactile et lecteur de carte SD", avec partage optimisé des bus SPI ! J'ai passé une commande de 5 exemplaires à JLCPCB (pour 4 € les 5 , port compris).

Et voici le description d'un récepteur radio à TEF6686 qui utilise cette nouvelle carte.

2 Le schéma de ma carte ESP32 + ILI9341 2.8

Cette carte perso ressemble et remplace la célèbre carte jaune "CYD" mais avec des fonctions inutiles en moins et beaucoup de ports GPIO libres en plus.

3 Animation


Un gif animé composé avec quelques captures d'écran de l'afficheur, montrant la réception de stations dans la bande FM, la surveillance de fréquences présélectionnées de la bande aviation (qui nécessite l'ajout d'un convertisseur de fréquence (-110MHz) VHF->SW sur l'entrée antenne), le scan de toutes les fréquences de la bande FM, la saisie de la couleur de fond d'écran au moyen d'une palette de 32 couleurs, 16 claires et 16 sombres...

4 Le schéma de ma carte ESP32 + ILI9341 2.8

Cette nouvelle carte remplace donc la carte jaune "CYD" avec des fonctions inutiles en moins mais beaucoup de ports GPIO libres en plus.

5 Le circuit imprimé de ma carte ESP32 + ILI9341 2.8

C'est un double face. Je l'ai fait fabriquer par JLCPCB. Mais on peut tout à fait le réaliser soit même en simple face (F.cu) et remplacer la face (B.cu) par quelques bouts de fils de câblage, en prenant soin d'augmenter au préalable le diamètre des vias.

Tous les documents Kicad sont disponibles dans le fichier "Documents.zip" au bas de cet article (schema, board, fichiers de production gerber...)

6 Le contrôle qualité :

C'est Ok, je te la rends !

7 Le schéma du récepteur radio SW - FM - Air band

Schéma de l'ensemble de la radio, avec la carte en question dans la partie basse, dans le cadre en tirets bleus. Où l'on voit de suite les nombreux ports GPIO disponibles pour les périphériques à venir.

Le pont de résistances R1-R2 permet de mesurer (et d'afficher) la tension de la batterie, en amont du régulaeur 5V.

Le bouton-poussoir S1 et la résistance de pullup R3 sont facultatifs, ils me servent à faire des captures d'écran destinées à cet article ! si vous les supprimez, il faudra aussi commenter ces deux lignes dans le fichier main.cpp (dans la fonction 'void setup()' )

pinMode(26, INPUT_PULLUP); //26
attachInterrupt(26, INT26, FALLING); // GPIO26 -> pin P15 de ma carte


8 Le module TEF6686 de chez MPX

Voir la documentation du module TEF6686 dans le fichier "documents.zip" au bas de cet article.

9 Le module ampli BF et la batterie 2s

Voir le lien plus bas.

La batterie 2s est obtenue en câblant en série deux accus Lipo 103450, placées à plat au fond du boîtier. Il faut choisir une taille (et donc capacité) compatible avec le boîtier.

10 En video




09 mars 2026 :

J'ai fait fabriquer le PCB double face par JLCPCB. (C'est la partie dans le cadre en pointillés bleu). J'attendais de le recevoir pour vous montrer le résultat, qui confirme le bon fonctionnement de cette carte. J'utilise un adaptateur SD -> microSD court (en blanc sur la partie haute) moins moche que les adaptateurs classiques. La TFcard s'insère dedans par le côté. Il me reste à connecter le module TEF6686, l'ampli BF et l'alim 5V et placer le tout dans un joli boîtier. (La vidéo ci-dessus a été prise alors que le module récepteur TEF6686 et l'ampli BF n'étaient pas encore reliés à la carte. Mais depuis j'ai testé le tout ensemble et je peux vous confirmer que ça marche).

Je vais peut être ajouter un condensateur ou deux de 1000uF sue les alim de l'afficheur et de la carte, et même utiliser deux régulateurs 5V distincts parce que j'ai constaté quelque plantages du module lorsqu'on augmente brusquement le volume sonore avec la carte alimentée uniquement par le câble usb C (sur la version câblée sur platine de prototypage (Breadboard), qui comprend le module. Soit dit en passant, oui la radio fonctionne !

11 Le récepteur dans son boîtier

J'ai plaqué une feuille de vinyle bleu, préalablement découpée avec une découpeuse 'Silhouette Portrait 3', sur la face avant.
La plaque blanche en bas à droite est gravéee au laser (NEJE Master 2s 20W).

Sur le dessus on aperçoit l'adaptateur de micro SDcard qui dépasse à peine du boîtier, ainsi qu'un interrupteur à glissière marche-arrêt et un connecteur de charge de la batterie.

12 Exemple de réception de quelques stations

Vidéos + audio ok (Il s'agit du récepteur en fonctionnement réel)

Quelques stations dans la bande FM :




Quelques stations SW ("ondes courtes"): (prévoir une antenne adaptée à la bande de fréquence). Les stations SW n'émettent qu'à certaines heures et la propagation sur de longues distances est très variable. Voir les liens au bas de cet article.




Le scan de la bande Aviation civile, avec arrêt auto sur réception signal. Les échanges radio entre les avions et le contrôle aérien sont toujours très brefs. Ce récepteur scanne toutes les fréquences préalablement inscrites dans le fichier FRQ_AIR.txt sur la SDcard. A mettre à jour en fonction des installations aéro présentes dans votre secteur (par exemple avec une clé usb RTL-SDR 802T2 et le logiciel Gqrx). Le balayage s'arrête lorsqu'un signal est reçu, puis reprend dès la fin du message. Le niveau de détection est réglable. Nécessite convertisseur VHF->SW (-110MHz) sur l'entrée antenne.




13 Le code source main.cpp

CODE SOURCE en C++
  1. /* ************************************************************************************
  2. Radio TEF6686 par Silicium628
  3. pour ma carte (fab : JLCPCB) ESP32 Wroom + afficheur 2.8" TFT 240x320 + SDcard
  4.  
  5. Cette version utilise la SDcard
  6.  
  7. ************************************************************************************ */
  8.  
  9. // REMARQUES:
  10. // 1) lorsque la carte est connectée sur un bus USB de l'ordinateur,
  11. // un terminal série tel que CuteCom affichera beaucoup de choses en temps réel.
  12. // 2) Pour s'y retrouver dans le code, le plus simple est de partir de la fonction 'loop()' qui appelle les autres
  13. // 3) Le fichier User_Setup dans le dossier 'lib/TFT_eSPI' est spécifique à cette configuration
  14. // pour ce qui concerne les connexions mais aussi les limitations de fréquence du bus SPI
  15.  
  16. #include <Arduino.h>
  17. #include "main.h"
  18. //#include "Tuner_Patch_Lithio_V102_p224.h" // voir la fonction 'Tuner_Patch()' dans la fonction 'setup()'
  19.  
  20. String version = "1.15.1"; // (avec enregistrement sur SD card)
  21. // 2026-07-03
  22.  
  23.  
  24. #include "FS.h"
  25. #include "SD.h"
  26. #include "Wire.h"
  27. #include <stdint.h>
  28.  
  29. #include <Free_Fonts.h>
  30. #include "TFT_eSPI.h" // Hardware-specific library
  31. #include "SPI.h"
  32. #include "Digit_Font.h"
  33. #include <XPT2046_Touchscreen.h>
  34.  
  35.  
  36. #include "constantes_628.h"
  37. #include "Couleurs_AEC.h"
  38. #include "DSP_INIT_628.h"
  39. #include "driverTEF6686_628.h"
  40.  
  41. #define SPI_READ_FREQUENCY 16000000
  42.  
  43. #define bande_SW (frequence > 1500) && (frequence < 28000)
  44. #define bande_interdite1 (frequence > 28000) && (frequence < 88000)
  45. #define bande_interdite2 (frequence > 108000) && (frequence < 118000)
  46. #define bande_FM (frequence >= 88000) && (frequence < 108000)
  47. #define bande_AIR (frequence >= 118000) && (frequence < 138000)
  48.  
  49. #define XPT2046_IRQ 36
  50. #define XPT2046_MOSI 32 //T_DI 32
  51. #define XPT2046_MISO 39 //T_DO 39
  52. #define XPT2046_CLK 25
  53. #define XPT2046_CS 33
  54.  
  55.  
  56. //attention: ces valeurs ne sont pas celles par défaut pour SDA et SCL
  57. const int GPIO_SDA = 21;
  58. const int GPIO_SCL = 22;
  59.  
  60. const int analogPin = 35;
  61.  
  62. const int GPIO_BL = 4; // pour LED backlight ILI9341
  63.  
  64. const int _DX = 320;
  65. const int _DY = 240;
  66.  
  67. #define High_16bto8b(a) ((uint8_t)((a) >> 8))
  68. #define Low_16bto8b(a) ((uint8_t)(a ))
  69. #define Convert8bto16b(a) ((uint16_t)(((uint16_t)(*(a))) << 8 |((uint16_t)(*(a+1)))))
  70.  
  71. SPIClass mySpi = SPIClass(VSPI);
  72. XPT2046_Touchscreen ts(XPT2046_CS, XPT2046_IRQ);
  73.  
  74. SPIClass mySpi2 = SPIClass(HSPI);
  75.  
  76. TFT_eSPI TFT = TFT_eSPI(); // Configurer le fichier User_Setup.h de la bibliothèque TFT_eSPI au préalable
  77.  
  78.  
  79. TFT_eSprite sprite_frq = TFT_eSprite(&TFT);
  80. TFT_eSprite sprite_ligne1 = TFT_eSprite(&TFT);
  81.  
  82.  
  83. struct ETALON_TS // etalon touch screen
  84. {
  85. int16_t x0;
  86. int16_t dx;
  87. int16_t y0;
  88. int16_t dy;
  89. };
  90.  
  91. ETALON_TS eTS;
  92.  
  93.  
  94. struct POINT
  95. {
  96. uint16_t x;
  97. uint16_t y;
  98. };
  99.  
  100. // coordonnées des points de calibrage de l'écran tactile
  101. // (calibration ? étalonnage ?? ajustage ??? boaf, m'enfin !!)
  102. POINT A, B;
  103.  
  104. uint16_t x_touch, y_touch;
  105. uint16_t memo_x_touch, memo_y_touch;
  106. uint16_t memo_tiret_H[20];
  107. uint16_t memo_tiret_V[20];
  108. uint16_t valeur_bargraph=0;
  109.  
  110. uint8_t SDcardOk=0;
  111. uint16_t color565px;
  112. boolean stop = false;
  113. boolean do_capt_screen = false;
  114. boolean affi_AB = false;
  115.  
  116. float raddeg = M_PI/180.0;
  117. float deg_to_rad = 2.0 * M_PI /360.0;
  118.  
  119. boolean test_touch_screen = false; // mettre true pour activer le test
  120.  
  121. uint16_t compteur1 = 0;
  122. uint16_t compteur2 = 0;
  123. uint16_t compteur3 = 0;
  124. uint8_t num_capture = 0;
  125.  
  126. uint32_t frequence=10000;
  127. uint32_t saut_freq;
  128. uint16_t seuil = 50;
  129. uint16_t memo_seuil = 50;
  130.  
  131. GROUPE_FREQUENCES groupe_SW;
  132. GROUPE_FREQUENCES groupe_FM;
  133. GROUPE_FREQUENCES groupe_AIR;
  134. GROUPE_FREQUENCES groupe_SCAN;
  135.  
  136. uint32_t frq_preset_SW[8]; // 8 fréquences attribuées aux boutons [preset1] à [preset8] soit 8x4=32 octets
  137. uint32_t frq_preset_FM[8]; // 8 fréquences attribuées aux boutons [preset1] à [preset8] soit 8x4=32 octets
  138. uint32_t frq_preset_AIR[8];// 8 fréquences attribuées aux boutons [preset1] à [preset8] soit 8x4=32 octets total 32*3 = 96 octets
  139.  
  140. uint32_t memo_freq;
  141. uint16_t frq_preset_adr_0;
  142. String frequence_txt = "";
  143.  
  144. TOUCH_BOUTON bt_info;
  145. TOUCH_BOUTON bt_sleep;
  146. TOUCH_BOUTON bt_quiet; // calme (anti-parasites)
  147. TOUCH_BOUTON bt_TEST;
  148.  
  149. TOUCH_BOUTON bt_mode_FRQ, bt_mode_MEM;
  150. TOUCH_BOUTON bt_plus, bt_moins;
  151.  
  152. TOUCH_BOUTON bt_SD_write, bt_erase_1F, bt_LST; //, bt_SD_LST, bt_SD_RAZ;
  153. //TOUCH_BOUTON bt_1, bt_2, bt_3, bt_4, bt_5, bt_6; // 6 boutons au dessus des chiffres de la fréquence
  154. TOUCH_BOUTON bt_coul;
  155. TOUCH_BOUTON bt_coul_to_SD;
  156.  
  157. TOUCH_BOUTON Bt_SCAN, bt_scan_air;
  158. TOUCH_BOUTON bt_scan_SW, bt_scan_FM;
  159.  
  160. TOUCH_BOUTON bt_RST_affi; // "ok"
  161.  
  162. TOUCH_BOUTON bt_LEV, bt_SNR, bt_re_scan, bt_scan_suivant;
  163. TOUCH_BOUTON bt_seuil_plus, bt_seuil_moins;
  164.  
  165.  
  166. GRID_PAD gridPad1;
  167.  
  168. NUM_PAD numPad1;
  169.  
  170. PRESET_PAD presetPad1;
  171.  
  172. SW_PAD swPad1;
  173.  
  174. CHF_PAD chf_pad1;
  175.  
  176. // -------------------------------
  177. TOUCH_BOUTON bt_SW, bt_FM, bt_AIR, bt_SCN;
  178. TOUCH_BOUTON bt_LED;
  179. TOUCH_BOUTON bt_mute;
  180. TOUCH_BOUTON bt_reset;
  181. TOUCH_BOUTON bt_cal;
  182. TOUCH_BOUTON bt_stop_scan;
  183.  
  184. TOUCH_BOUTON bt_set; // attribtion d'une fréquence à un des 8 boutons preset
  185. TOUCH_BOUTON bt_annuler; // "x"
  186. TOUCH_BOUTON bt_close; // "x"
  187.  
  188. //les variables globales sont le Mal, et il faut éviter à tous prix de s'en servir, m'enfin!
  189. boolean mute;
  190. boolean vu_metre_actif;
  191.  
  192. enum MODE_AFFI {COUL, NORMAL, SCAN_F, SCAN_M, SET_F_PRESET}; //[couleur], [normal], [scan], [set 1F pour 1Bt]
  193. MODE_AFFI mode_affi;
  194.  
  195. enum MODE_SELECT {_FRQ=0, _MEM=1} mode_s; // mode de mofif fréquence, en tapant les chiffres /ou en mémoire
  196.  
  197. enum MODUL {AM, WFM};
  198. MODUL modulation_active;
  199.  
  200. enum BANDE {SW, FM, AIR, SCN}; //fréquences;
  201. BANDE bande_active;
  202.  
  203. enum GRP_ACT {gSW, gFM, gAIR, gSCN}; // groupes mémoire SW, FM, AIR, SCN; le grp SCN mémorise le résultat d'un scan FREQUENCE
  204. GRP_ACT groupe_actif;
  205.  
  206. enum MODE_SCAN {FREQUENCE, MEMOIRE};
  207. MODE_SCAN mode_scan;
  208.  
  209. enum MODE_SEUIL {LEV, SNR}; // level ou signal/bruit
  210. MODE_SEUIL mode_seuil;
  211.  
  212. boolean quiet = false;
  213.  
  214. uint16_t FRQ_x0;
  215. uint16_t FRQ_y0;
  216.  
  217. uint16_t x0_box_SD;
  218. uint16_t y0_box_SD;
  219.  
  220. uint16_t x0_box_PRESET;
  221. uint16_t y0_box_PRESET;
  222.  
  223. uint16_t x0_box_GROUPE; // SW - FM - AIR
  224. uint16_t y0_box_GROUPE;
  225.  
  226. uint16_t x0_box_boutons_scan;
  227. uint16_t y0_box_boutons_scan;
  228.  
  229. uint16_t x0_box_SCAN; // grande surface d'affichage
  230. uint16_t y0_box_SCAN;
  231. uint16_t dx_box_SCAN;
  232. uint16_t dy_box_SCAN;
  233.  
  234. uint16_t x0_numPad;
  235. uint16_t y0_numPad;
  236.  
  237. uint16_t x0_vu_metre;
  238. uint16_t y0_vu_metre;
  239.  
  240. uint16_t x0_box_info1; // en bas à gauche pour afficher les infos RDS
  241. uint16_t y0_box_info1;
  242.  
  243. uint16_t x0_box_info2; // à la place du vu-metre
  244. uint16_t y0_box_info2;
  245. uint16_t dx_box_info2;
  246. uint16_t dy_box_info2;
  247.  
  248. uint16_t x0_gridPad;
  249. uint16_t y0_gridPad;
  250. uint16_t dx_gridPad;
  251. uint16_t dy_gridPad;
  252.  
  253. uint16_t x0_saisie;
  254. uint16_t y0_saisie;
  255.  
  256. uint16_t x0_choix_couleur;
  257. uint16_t y0_choix_couleur;
  258.  
  259. uint8_t n_appui; // incrémenté à chaque appui sur une touche du numPad numérique
  260. uint32_t total_saisi;
  261.  
  262.  
  263. uint16_t status;
  264. int16_t level;
  265. uint16_t usn;
  266. uint16_t wam;
  267. int16_t offset;
  268. uint16_t bandwidth;
  269. uint16_t mod;
  270. int8_t snr;
  271.  
  272. uint16_t A_block;
  273. uint16_t B_block;
  274. uint16_t C_block;
  275. uint16_t D_block;
  276. uint16_t dec_error;
  277.  
  278. float position_aiguille; // vu-metre
  279. float valeur_affi;
  280. float memo_valeur_affi;
  281. float ltx; // aiguille
  282. uint16_t osx;
  283. uint16_t osy;
  284.  
  285. uint16_t couleur_traits = GRIS_5;
  286. uint16_t JAUNE_chiffres = 65504;
  287. uint16_t VERT_chiffres = 2016;
  288.  
  289. uint8_t cR = 0;
  290. uint8_t cG = 0;
  291. uint8_t cB = 0;
  292. uint16_t couleur_fond_ecran = VERT_FONCE;
  293.  
  294. String s_recue;
  295. String memo_s_recue="";
  296.  
  297.  
  298.  
  299. float degTOrad(float angle)
  300. {
  301. return (angle * M_PI / 180.0);
  302. }
  303.  
  304.  
  305. uint8_t decToBcd( int val )
  306. {
  307. return (uint8_t) ((val / 10 * 16) + (val % 10));
  308. }
  309.  
  310.  
  311. uint16_t Color_To_565(uint8_t r, uint8_t g, uint8_t b)
  312. {
  313. return ((r & 0xF8) << 8) | ((g & 0xFC) << 3) | ((b & 0xF8) >> 3);
  314. }
  315.  
  316.  
  317. void RGB565_to_888(uint16_t color565, uint8_t *R, uint8_t *G, uint8_t *B)
  318. {
  319. *R=(color565 & 0xF800) >> 8;
  320. *G=(color565 & 0x7E0) >> 3;
  321. *B=(color565 & 0x1F) << 3 ;
  322. }
  323.  
  324.  
  325.  
  326. void init_variables_globales()
  327. // je ne les initialise pas lors de leur déclaration sinon lors d'un reset logiciel (appel de la fonction 'setup()'
  328. // par le boouton 'RST') elles ne seraient pas réinitialisées
  329. {
  330. // étalonnage touch screen
  331. eTS.x0 = -30; eTS.y0 = -30;
  332. eTS.dx = 11; eTS.dy = 14;
  333.  
  334. mode_affi = NORMAL;
  335. bande_active = FM;
  336. modulation_active = WFM;
  337. mode_s = _MEM;
  338. mode_scan = FREQUENCE;
  339. mode_seuil = LEV;
  340. mute = false;
  341. vu_metre_actif = true;
  342.  
  343. FRQ_x0 = 50; FRQ_y0 = 30;
  344. x0_box_SD = 2; y0_box_SD = 150;
  345. x0_box_PRESET =2; y0_box_PRESET =87;
  346. x0_box_GROUPE = 205; y0_box_GROUPE = 115;
  347. x0_box_boutons_scan = 2; y0_box_boutons_scan = 105;
  348.  
  349. // grande surface d'affichage
  350. x0_box_SCAN = 2; y0_box_SCAN = 90;
  351. dx_box_SCAN = 315; dy_box_SCAN = 148;
  352.  
  353. x0_numPad = 70; y0_numPad = 115;
  354. x0_vu_metre = 170; y0_vu_metre = 140;
  355. x0_box_info1 = 2; y0_box_info1 = 220;
  356.  
  357. x0_box_info2 = x0_vu_metre; y0_box_info2 = y0_vu_metre;
  358. dx_box_info2 = 140; dy_box_info2 = 70;
  359.  
  360. x0_gridPad = x0_vu_metre;
  361. y0_gridPad = y0_vu_metre;
  362. dx_gridPad = 140; dy_gridPad = 70;
  363.  
  364. x0_saisie = 2; y0_saisie = 2;
  365. x0_choix_couleur = 170; y0_choix_couleur = 145;
  366.  
  367. n_appui = 0; // incrémenté à chaque appui sur une touche du numPad numérique
  368. total_saisi = 0;
  369.  
  370. valeur_bargraph=0;
  371.  
  372. position_aiguille = 0; // vu-metre
  373. valeur_affi = 0;
  374. memo_valeur_affi = 0;
  375. ltx = 0; // aiguille
  376. osx = x0_vu_metre;
  377. osy = y0_vu_metre;
  378. }
  379.  
  380.  
  381. //uint16_t bmp_offset = 0;
  382. uint16_t bmp_width;
  383. uint16_t bmp_heigh;
  384.  
  385.  
  386.  
  387.  
  388. void draw_bmp565(uint16_t x0, uint16_t y0, uint8_t sens, File* fp)
  389. {
  390. uint16_t i,j;
  391. uint16_t y1;
  392. uint8_t bmp_data[2]={0};
  393. uint16_t bmp_color[2];
  394.  
  395. fp->seek(0);
  396. for(i=0; i<bmp_heigh; i++)
  397. {
  398. for(j=0; j<(bmp_width); j++)
  399. {
  400. fp->read(bmp_data, 2); // lit les 2 octets constituant la valeur rgb565 et les place dans bmp_data[]
  401. if (sens == 0) {y1 = y0+bmp_heigh-i;}
  402. else {y1 = y0+i;}
  403. TFT.drawPixel(x0+j, y1, bmp_data[0] + (bmp_data[1] << 8) );
  404. }
  405. }
  406. }
  407.  
  408.  
  409.  
  410. // Fonction optimisée pour l'afficheur ILI9341 320x240 avec la library 'TFT_eSPI'
  411. // ne convient PAS pour les ESP32 Wroom + afficheur 3.5" TFT 480x320
  412. void write_TFT_on_SDcard() // enregistre image bmp 320x240 RGB565 (5+6+5 = 16bits/px)
  413. {
  414. Serial.println("write_TFT_on_SDcard()");
  415.  
  416. if (SDcardOk==0)
  417. {
  418. affi_message ( "SDcard absente", "Capture ecran impossible", "", "", "");
  419. return;
  420. }
  421. int32_t x, y;
  422. uint16_t color565;
  423.  
  424. uint8_t lineBuffer8[(320*2)];
  425. uint16_t lineBuffer16[320];
  426. uint8_t octet_A, octet_B;
  427. String s1, s2;
  428.  
  429. s1 +="/bmp565/capture";
  430. s1 += String(num_capture);
  431. s1 += ".bmp" ;
  432.  
  433. File file1 = SD.open(s1, FILE_WRITE); // crée le fichier si pas présent
  434. if (file1)
  435. {
  436. // création entête bmp565 - 138 octets; voir bmp565_header[] dans le fichier main.h
  437. for(uint8_t i=0; i<138; i++) { file1.write(bmp565_header[i]); }
  438.  
  439. TFT.setTextColor(VERT, NOIR);
  440. for (int16_t y=239; y>=0; y--)
  441. {
  442. TFT.readRect(0, y, 320, 1, lineBuffer16); // lit une ligne
  443. s2=String(y/24);
  444. TFT.drawString(s2, 2, 2); // pour terminer par une écriture
  445.  
  446. uint16_t i=0;
  447. for (int16_t x=0; x<320; x++) //320
  448. {
  449. color565px = lineBuffer16[x]; // BBBBBrrr rrrVVVVV
  450. octet_A = (color565px & 0b1111111100000000) >> 8;
  451. octet_B = (color565px & 0b0000000011111111);
  452.  
  453. lineBuffer8[i] = octet_A;
  454. lineBuffer8[i+1] = octet_B;
  455. i+=2;
  456. }
  457. file1.write(lineBuffer8, sizeof(lineBuffer8));
  458. }
  459. num_capture ++;
  460.  
  461. }
  462. }
  463.  
  464.  
  465.  
  466. void init_boutons_Plus_Moins()// boutons '<' et '>'
  467. {
  468. int x0 = 240;
  469. int y0 = 90;
  470.  
  471. String s1, s2;
  472.  
  473. uint16_t c1 = GRIS_6;
  474. uint16_t c2 = JAUNE;
  475.  
  476. if(mode_s == _FRQ) { s1 = " -"; s2 = " +"; }
  477. if(mode_s == _MEM) { s1 = " <"; s2 = " >"; }
  478.  
  479. bt_moins.init(x0, y0, 30, 15, 3, GRIS_5);
  480. bt_moins.cliked = false;
  481. bt_moins.label= s1;
  482.  
  483. bt_plus.init(x0+35, y0, 30, 15, 3, GRIS_5);
  484. bt_plus.cliked = false;
  485. bt_plus.label= s2;
  486. }
  487.  
  488.  
  489. void init_boutons_GROUPE() // groupe de fréquence (SW - FM - AIR - SCAN)
  490. {
  491. uint16_t x = x0_box_GROUPE+4;
  492. uint16_t y = y0_box_GROUPE+5;
  493.  
  494. TFT.setFreeFont(FF0);
  495.  
  496. bt_SW.init(x, y, 20, 15, 3, GRIS_5);
  497. bt_SW.cliked = false;
  498. bt_SW.selected = false;
  499. bt_SW.label="SW";
  500. x+=25;
  501.  
  502. bt_FM.init(x, y, 20, 15, 3, GRIS_5);
  503. bt_FM.cliked = false;
  504. bt_FM.selected = false;
  505. bt_FM.label="FM";
  506. x+=25;
  507.  
  508. bt_AIR.init(x, y, 22, 15, 3, GRIS_5);
  509. bt_AIR.cliked = false;
  510. bt_AIR.selected = false;
  511. bt_AIR.label="AIR";
  512. x+=27;
  513.  
  514. bt_SCN.init(x, y, 20, 15, 3, GRIS_5);
  515. bt_SCN.cliked = false;
  516. bt_SCN.selected = false;
  517. bt_SCN.label="SC";
  518.  
  519. }
  520.  
  521.  
  522. void init_1_bouton(uint8_t n_font, uint16_t xi, uint16_t yi, uint8_t dx, uint8_t dy, String si, TOUCH_BOUTON *bouton_i)
  523. {
  524. //uint16_t c1 = GRIS_5;
  525. uint16_t c2 = BLANC;
  526.  
  527. bouton_i->init(xi, yi, dx, dy, 3, GRIS_5);
  528. bouton_i->cliked = false;
  529. bouton_i->selected = false;
  530. bouton_i->label = si;
  531. bouton_i->affiche(c2, n_font);
  532. }
  533.  
  534.  
  535. void init_1_bouton_rouge(uint8_t n_font, uint16_t xi, uint16_t yi, uint8_t dx, uint8_t dy, String si, TOUCH_BOUTON *bouton_i)
  536. {
  537. uint16_t c2 = BLANC;
  538.  
  539. bouton_i->init(xi, yi, dx, dy, 3, ROUGE);
  540. bouton_i->cliked = false;
  541. bouton_i->selected = false;
  542. bouton_i->label = si;
  543. bouton_i->affiche(c2, n_font);
  544. }
  545.  
  546.  
  547. void init_boutons_MODE() // en haut à gauche
  548. {
  549. uint16_t c1 = NOIR;
  550. uint16_t c2 = VERT;
  551.  
  552. TFT.setFreeFont(FF0);
  553. TFT.setTextColor(GRIS_3, NOIR);
  554. TFT.drawString("mode", 6, 24);
  555.  
  556. TFT.drawFastVLine(45, 15, 72, couleur_traits);
  557.  
  558. bt_mode_FRQ.init(5, 35, 37, 20, 2, GRIS_5);
  559. bt_mode_FRQ.selected = false;
  560. bt_mode_FRQ.label="FRQ";
  561. bt_mode_FRQ.affiche(c2, 2);
  562.  
  563. bt_mode_MEM.init(5, 60, 37, 20, 2, GRIS_5);
  564. bt_mode_MEM.selected = true;
  565. bt_mode_MEM.label="MEM";
  566. bt_mode_MEM.affiche(c2, 2);
  567.  
  568. }
  569.  
  570.  
  571. void affiche_1_bt_RGB(TOUCH_BOUTON *bouton_i, uint16_t x, uint16_t y, uint8_t dx, uint16_t couleur, String s_i)
  572. {
  573. uint16_t c1 = couleur;
  574. uint16_t c2 = JAUNE;
  575.  
  576. bouton_i->init(x, y, dx, 14, 3, GRIS_5);
  577. bouton_i->cliked = false;
  578. bouton_i->selected = false;
  579. bouton_i->label = s_i;
  580. bouton_i->affiche(c2, 1);
  581. }
  582.  
  583.  
  584. void init_sprites()
  585. {
  586. sprite_frq.createSprite(220, 55);
  587. sprite_frq.loadFont(digitfont1);
  588. sprite_frq.setTextColor(JAUNE_2, NOIR);
  589. sprite_frq.setTextDatum(MR_DATUM); // alignement du texte
  590.  
  591. }
  592.  
  593.  
  594. void Tuner_Reset(void)
  595. {
  596. Wire.beginTransmission(0x64);
  597. Wire.write(0x1e);
  598. Wire.write(0x5a);
  599. Wire.write(0x01);
  600. Wire.write(0x5a);
  601. Wire.write(0x5a);
  602. Wire.endTransmission();
  603. }
  604.  
  605.  
  606.  
  607.  
  608. bool Tuner_Table_Write(const unsigned char *tab)
  609. {
  610. if (tab[1] == 0xff)
  611. {
  612. delay(tab[2]);
  613. return 1;
  614. }
  615. else { return Tuner_WriteBuffer((unsigned char *)&tab[1], tab[0]); }
  616. }
  617.  
  618.  
  619. void Tuner_Init(const unsigned char *table)
  620. {
  621. uint16_t r;
  622. const unsigned char *p = table;
  623.  
  624. for (uint16_t i = 0; i < sizeof(tuner_init_tab9216); i += (pgm_read_byte(p + i) + 1))
  625. {
  626. if (1 != (r = Tuner_Table_Write(p + i))) break;
  627. }
  628. }
  629.  
  630.  
  631. void Tune_Frequence(uint32_t Fi)
  632. {
  633. TFT.setFreeFont(FF0);
  634. //TFT.setTextColor(BLEU, NOIR);
  635. String s1 = String(Fi);
  636. //TFT.drawString(s1, 80, 2);
  637.  
  638. quiet = false; // stop l'anti-parasites
  639.  
  640. if((mode_affi != SCAN_F) && (mode_affi != SCAN_M))
  641. {
  642. bt_quiet.selected = false;
  643. bt_quiet.affiche(VERT, 1);
  644. bt_mute.selected = false;
  645. bt_mute.affiche(VERT, 1);
  646. }
  647. mute = false;
  648.  
  649. frequence = Fi;
  650.  
  651. if (Fi == 1500)
  652. {
  653. TFT.setTextColor(ROUGE, NOIR);
  654. TFT.drawString("MINIMUM ", 130, 2);
  655. }
  656.  
  657. if (bande_SW)
  658. {
  659. modulation_active = AM;
  660. Tune_Frequence_AM(Fi);
  661. TFT.setTextColor(VERT, NOIR);
  662. efface_box_entete2();
  663. TFT.drawString("SW ", 130, 2);
  664. }
  665.  
  666. if (bande_interdite1)
  667. {
  668. efface_box_entete2();
  669. TFT.setTextColor(ROUGE, NOIR);
  670. TFT.drawString("FRQ non disponible", 80, 2);
  671. }
  672.  
  673. if (bande_FM)
  674. {
  675. modulation_active = WFM;
  676. Tune_Frequence_FM(Fi/10); // envoi les data au TEF6686
  677. efface_box_entete2();
  678. TFT.setTextColor(VERT, NOIR);
  679. TFT.drawString("bande FM", 130, 2);
  680. }
  681.  
  682. if (bande_interdite2)
  683. {
  684. efface_box_entete2();
  685. TFT.setTextColor(ROUGE, NOIR);
  686. TFT.drawString("FRQ NON DISPONIBLE", 80, 2);
  687. }
  688.  
  689. if (bande_AIR)
  690. {
  691. modulation_active = AM;
  692. Tune_Frequence_AM(Fi-110000); // nécessite un convertisseur de fréquence 110MHz en entrée antenne
  693.  
  694. if(! affi_AB)
  695. {
  696. TFT.setTextColor(BLEU_CLAIR, NOIR);
  697. efface_box_entete2();
  698. TFT.drawString("AIR BAND", 130, 2);
  699. affi_AB = true;
  700. }
  701. }
  702.  
  703. if (Fi == 138000)
  704. {
  705. TFT.setTextColor(ROUGE, NOIR);
  706. efface_box_entete2();
  707. TFT.drawString("F MAX ", 130, 2);
  708. }
  709. }
  710.  
  711.  
  712. void load_GRP_FREQ_SD() // SD --> to RAM
  713. {
  714. Serial.println("--- Frequences lues sur la SDcard ---------------");
  715. Serial.println(" ");
  716.  
  717. Serial.println("GROUPE SW");
  718. groupe_SW.RAZ(); // important, sinon les fréquences se trouvent dédoublées lors d'un soft-reset
  719. groupe_SW.load_bloc(); // SD --> RAM
  720. groupe_SW.tri_bloc(); // en RAM
  721. groupe_SW.bloc_to_serial();
  722.  
  723. Serial.println("---------------------------------------------");
  724.  
  725. Serial.println("GROUPE FM");
  726. groupe_FM.RAZ();
  727. groupe_FM.load_bloc();
  728. groupe_FM.tri_bloc();
  729. groupe_FM.bloc_to_serial();
  730.  
  731. Serial.println("---------------------------------------------");
  732.  
  733. Serial.println("GROUPE AIR");
  734. groupe_AIR.RAZ();
  735. groupe_AIR.load_bloc();
  736. groupe_AIR.tri_bloc();
  737. groupe_AIR.bloc_to_serial();
  738.  
  739. Serial.println("---------------------------------------------");
  740.  
  741. // remarque : le groupe SCAN n'est jamais enregistré
  742. }
  743.  
  744.  
  745. uint16_t brightness(uint16_t couleur)
  746. {
  747. uint8_t r, g, b;
  748.  
  749. r = 0xFF & (couleur >> 16);
  750. g = 0xFF & (couleur >> 8);
  751. b = 0xFF & couleur;
  752.  
  753. return ( r + g + b );
  754. }
  755.  
  756.  
  757. void init_SDcard()
  758. {
  759. Serial.println("---------------------");
  760. Serial.println("init_SDcard()");
  761. String s1;
  762.  
  763. TFT.fillRect(0, 0, 480, 320, NOIR); // efface
  764. TFT.setTextColor(BLANC, NOIR);
  765. TFT.setFreeFont(FF1);
  766.  
  767. if(!SD.begin(5, mySpi2))
  768. {
  769. Serial.println("Card Mount Failed");
  770. SDcardOk=0;
  771. }
  772. else
  773. {
  774. Serial.println("SDcard OK");
  775. SDcardOk=1;
  776. TFT.fillRect(0, 0, 480, 320, VERT);
  777. delay(100);
  778. }
  779.  
  780. uint8_t cardType = SD.cardType();
  781.  
  782. if(cardType == CARD_NONE)
  783. {
  784. Serial.println("NO SDcard");
  785. SDcardOk=0;
  786. return;
  787. }
  788.  
  789. Serial.print("SDcard Type: ");
  790. if(cardType == CARD_SD) {Serial.print("SDSC");}
  791. else if(cardType == CARD_SDHC) {Serial.println("SDHC");}
  792.  
  793. uint32_t cardSize = SD.cardSize() / (1024 * 1024);
  794. s1=(String)cardSize + " GB";
  795. Serial.println(s1); Serial.println();
  796.  
  797. delay (100);
  798. TFT.fillRect(0, 0, 480, 320, NOIR); // efface
  799. }
  800.  
  801.  
  802. void init_affichages()
  803. {
  804. Serial.println("init_affichages()");
  805. TFT.fillRect(0, 0, 319, 239, couleur_fond_ecran);
  806. efface_box_entete1();
  807. efface_box_entete2();
  808. efface_box_entete3();
  809. if (brightness(couleur_fond_ecran) > 500) {couleur_traits = NOIR;} else {couleur_traits = BLANC;}
  810.  
  811. TFT.setTextColor(JAUNE, NOIR);
  812.  
  813. TFT.drawRect(0, 0, 319, 240, couleur_traits); // cadre principal pourtour de l'écran
  814. TFT.setFreeFont(FF0);
  815. TFT.setTextColor(BLANC, BLEU);
  816. String s1 = "v:" + version;
  817. TFT.drawString(s1, 45, 15);
  818.  
  819.  
  820. while (!Serial && (millis() <= 1000));
  821. init_boutons_MODE();
  822.  
  823. affiche_box_SD();
  824. init_1_bouton(1, x0_box_SD+4, y0_box_SD+16, 40, 15, " LST", &bt_LST);
  825. init_1_bouton(1, x0_box_SD+4, y0_box_SD+33, 40, 15, "Write", &bt_SD_write);
  826.  
  827. TFT.setFreeFont(FF0);
  828.  
  829. init_boutons_Plus_Moins();
  830. init_boutons_GROUPE(); // (SW - FM - AIR - SC)
  831.  
  832. init_1_bouton(1, 305, 15, 15, 15, "?", &bt_info);
  833.  
  834. uint16_t xi, yi, dx, dy;
  835.  
  836. //1ere ligne, celle du dessus
  837. xi = 167; yi = 212; dx = 35; dy = 11;
  838. init_1_bouton(1, xi, yi, dx, dy, " LED", &bt_LED); xi+=3*dx+3*2; // LED backlight
  839. init_1_bouton(1, xi, yi, dx, dy, " CAL", &bt_cal); xi+=dx+2;
  840.  
  841.  
  842. //2eme ligne, en dessous
  843. xi = 130; yi = 224; dx = 35; dy = 11;
  844. init_1_bouton(1, xi, yi, dx, dy, "Mute", &bt_mute); xi+=dx+2;
  845. init_1_bouton(1, xi, yi, dx, dy, "sleep", &bt_sleep); xi+=dx+2;
  846. init_1_bouton(1, xi, yi-dy-2, dx, 2*dy+2, "QUIET", &bt_quiet); xi+=dx+2;
  847. init_1_bouton(1, xi, yi, dx, dy, " RST", &bt_reset); xi+=dx+2;
  848. init_1_bouton(1, xi, yi, dx, dy, "Color", &bt_coul); xi+=dx+2;
  849.  
  850. init_1_bouton(1, 160, 120, 40, 14, "TEST", &bt_TEST);
  851.  
  852. TFT.fillRect(x0_box_boutons_scan, y0_box_boutons_scan + 10, 60, 25, NOIR);
  853. init_1_bouton(2, 5, 118, 55, 20, "SCAN", &Bt_SCAN);
  854. //init_1_bouton(1, 5, 135, 55, 15, "scan AIR", &bt_scan_air);
  855.  
  856. init_1_bouton(1, 168, 97, 30, 15, "set", &bt_set);
  857.  
  858. init_1_bouton(1, x0_box_SD+4, y0_box_SD+33, 40, 15, "Write", &bt_SD_write);
  859. init_1_bouton(1, x0_box_SD+4, y0_box_SD+50, 40, 15, "raz 1F", &bt_erase_1F);
  860.  
  861. numPad1.init(x0_numPad, y0_numPad, true);
  862.  
  863. affiche_box_presets(); // conteneur des 8 petits boutons
  864. presetPad1.init(x0_box_PRESET +5, y0_box_PRESET +5);
  865.  
  866. efface_box_entete2();
  867. efface_box_entete3();
  868.  
  869.  
  870. affiche_box_FRQ(GRIS_3); // autour de la fréquence (gros chiffres JAUNE ou VERT)
  871.  
  872. if (mode_affi == NORMAL)
  873. {
  874. init_box_info();
  875. affiche_box_GROUPE();
  876. bt_moins.affiche(VERT ,1);
  877. bt_plus.affiche(VERT ,1);
  878. bt_SW.affiche(VERT, 1);
  879. bt_FM.affiche(VERT, 1);
  880. bt_AIR.affiche(VERT, 1);
  881. bt_SCN.affiche(VERT, 1);
  882. bt_quiet.affiche(VERT, 1);
  883. bt_mute.selected = false;
  884. bt_mute.cliked = false;
  885. bt_mute.affiche(ROUGE, 1);
  886.  
  887. //bt_4.selected = true;
  888. //bt_4.cliked = true;
  889. //bt_4.affiche(JAUNE,1);
  890.  
  891. bt_sleep.affiche(VERT, 1);
  892. bt_LED.affiche(VERT, 1);
  893. bt_cal.affiche(VERT, 1);
  894. bt_TEST.affiche(VERT, 1);
  895. bt_coul.affiche(VERT, 1);
  896.  
  897. }
  898.  
  899. bt_reset.affiche(VERT, 1);
  900.  
  901. affiche_frequence(frequence);
  902.  
  903. valeur_bargraph=0;
  904. if (vu_metre_actif)
  905. {
  906. dessine_VuMetre();
  907. }
  908. else
  909. {
  910. //affi_image_from_SD("/bmp565/montagne170x140.bmp", x0_vu_metre, y0_vu_metre);
  911. }
  912.  
  913.  
  914. TFT.drawRect(0, 0, 319, 240, couleur_traits); // cadre principal pourtour de l'écran
  915. }
  916.  
  917.  
  918. void read_FRQ_File(FS &fs, String filename, String cible) // en mémoire SD
  919. {
  920. Serial.print("Reading file: "); Serial.println(filename);
  921. File file = fs.open(filename);
  922. if (!file ) { Serial.println("failed to open file for reading"); return; }
  923. String s;
  924. uint8_t n =0;
  925.  
  926. while (file.available())
  927. {
  928. char c;
  929. c = char(file.read());
  930. if ((c !='<') && (c !='>')) {s += c;}
  931. if(c=='>')
  932. {
  933. uint32_t frq;
  934. frq = s.toInt();
  935. Serial.println(frq);
  936. s="";
  937. if(cible == "SW") {presetPad1.bt_preset[n].frequence_SW = frq;}
  938. if(cible == "FM") {presetPad1.bt_preset[n].frequence_FM = frq;}
  939. if(cible == "AIR") {presetPad1.bt_preset[n].frequence_AIR = frq;}
  940. n++;
  941. }
  942. }
  943. file.close();
  944. }
  945.  
  946.  
  947. String read_line_params(uint16_t line_num)
  948. {
  949. int i = 1;
  950. char buffer[64];
  951. String s;
  952.  
  953. File file = SD.open("/params.txt", "r");
  954.  
  955. while (file.available())
  956. {
  957. int l = file.readBytesUntil('\n', buffer, sizeof(buffer));
  958. buffer[l] = 0;
  959. if (line_num == i)
  960. {
  961. s = buffer;
  962. file.close();
  963. return(s);
  964. }
  965. i++;
  966. }
  967. return "";
  968. }
  969.  
  970.  
  971. int32_t extract_params(String ligne, String label)
  972. {
  973. String s2;
  974. uint32_t valeur = 0;
  975. int p1, p2;
  976.  
  977. p1 = ligne.indexOf('['); p2 = ligne.indexOf(']');
  978. s2 = ligne.substring(p1+1, p2);
  979.  
  980. if (s2 == label)
  981. {
  982. p1 = ligne.indexOf('<'); p2 = ligne.indexOf('>');
  983. s2 = ligne.substring(p1+1, p2);
  984. valeur = s2.toInt();
  985. return valeur;
  986. }
  987. return -1;
  988. }
  989.  
  990.  
  991. void read_params()
  992. {
  993. Serial.println("---------------------------------------------");
  994. // lecture du fichier '/params.txt' en SD
  995. Serial.println("lecture du fichier '/params.txt' en SD");
  996. String s1;
  997. int valeur;
  998. //Serial.println("read params() ");
  999.  
  1000. //for(uint8_t n=1; n<=6; n++) // lit toutes(6) lignes du fichier
  1001. s1 = "Z";
  1002. uint8_t n=1;
  1003. while (s1 !="")
  1004. {
  1005. s1 = read_line_params(n); // retourne(par exemple): [couleur_fond]<267>
  1006. Serial.print(n); Serial.println(" " + s1);
  1007.  
  1008. valeur = extract_params(s1, "couleur_fond"); // extrait la valeur correspondant au label
  1009. if(valeur != -1) {couleur_fond_ecran = valeur;}
  1010.  
  1011. //couleur_fond_ecran = VERT_FONCE; // pour TEST
  1012.  
  1013. valeur = extract_params(s1, "frequence");
  1014. if(valeur != -1) {frequence = valeur;}
  1015.  
  1016. valeur = extract_params(s1, "Ax");
  1017. if(valeur != -1) {A.x = valeur;}
  1018.  
  1019. valeur = extract_params(s1, "Ay");
  1020. if(valeur != -1) {A.y = valeur;}
  1021.  
  1022. valeur = extract_params(s1, "Bx");
  1023. if(valeur != -1) {B.x = valeur;}
  1024.  
  1025. valeur = extract_params(s1, "By");
  1026. if(valeur != -1) {B.y = valeur;}
  1027.  
  1028. n++;
  1029. }
  1030. Serial.print("---------------------------------------------");
  1031. }
  1032.  
  1033.  
  1034. void draw_AEC(uint16_t x0, uint16_t y0, uint16_t L, uint8_t sens)
  1035. {
  1036. // ligne arc-en-ciel
  1037. // affiche une ligne de pixels colorés à partir de la variable 'couleurs_aec' mémorisée en PROGMEM (voir fichier Couleurs_AEC.h)
  1038. // L = longueur de la ligne
  1039.  
  1040. //Serial.println("draw_draw_AEC()");
  1041. uint16_t x, i, j;
  1042. uint16_t y1;
  1043. uint16_t couleur_i;
  1044.  
  1045. for (int16_t i=0; i<L; i++)
  1046. {
  1047. float f = 470.0/L * i; // pour balayer toute l'échelle des couleurs disponibles
  1048. j=uint16_t(f);
  1049.  
  1050. couleur_i = couleurs_aec[2*j] | couleurs_aec[2*j+1]<<8;
  1051.  
  1052. if (sens==0){x=i;} else {x=L-i;}
  1053. TFT.drawPixel(x0+x, y0, couleur_i);
  1054. }
  1055. }
  1056.  
  1057.  
  1058.  
  1059. void set_frq_default()
  1060. {
  1061. presetPad1.bt_preset[0].frequence_FM = 88000;
  1062. presetPad1.bt_preset[1].frequence_FM = 90000;
  1063. presetPad1.bt_preset[2].frequence_FM = 92000;
  1064. presetPad1.bt_preset[3].frequence_FM = 94000;
  1065. presetPad1.bt_preset[4].frequence_FM = 96000;
  1066. presetPad1.bt_preset[5].frequence_FM = 100000;
  1067. presetPad1.bt_preset[6].frequence_FM = 104000;
  1068. presetPad1.bt_preset[7].frequence_FM = 108000;
  1069.  
  1070. }
  1071.  
  1072. void INT26() // appelé par la ligne 'attachInterrupt(26, INT26, FALLING);', voir dans le setup ci-dessous
  1073. {
  1074. do_capt_screen = true; // La capture se fera en dehors de l'interruption (depuis la boucle principale ou secondaire)
  1075. //write_TFT_on_SDcard(); // non, interdit ici !!
  1076. }
  1077.  
  1078.  
  1079. void setup()
  1080. {
  1081. // étalonnage touch screen; ces valeurs peuvent varier d'un afficheur à l'autre
  1082. // pour l'instant il faut les fixer ici à la main...
  1083. eTS.x0 = -30; eTS.y0 = -30;
  1084. eTS.dx = 11; eTS.dy = 14;
  1085.  
  1086. // La capture d'écran nécessite la présence d'un switch temporaire (bouton poussoir) entre le PIO26 de l'ESP32 et GND
  1087. // Je conseille aussi l'ajout d'une R=4k7 de pullup externe au +3V3, celle de pullup interne étant de trop grande valeur
  1088. // ***** décommenter les deux lignes suivante pour permettre ces captures d'écran *******
  1089. //pinMode(26, INPUT_PULLUP); //26
  1090. //attachInterrupt(26, INT26, FALLING); // GPIO26 -> pin P15 de ma carte
  1091. //***************************************************************************************
  1092.  
  1093. Serial.begin(115200);
  1094. delay(20);
  1095.  
  1096. pinMode(GPIO_BL, OUTPUT);
  1097. digitalWrite(GPIO_BL, HIGH);
  1098.  
  1099. init_variables_globales();
  1100.  
  1101. Wire.begin(GPIO_SDA, GPIO_SCL, 2000000);
  1102. Tuner_Init(tuner_init_tab9216);
  1103. //affiche_frequence(frequence);
  1104.  
  1105. // Start the SPI for the touch screen and init the TS library
  1106. mySpi.begin(XPT2046_CLK, XPT2046_MISO, XPT2046_MOSI, XPT2046_CS);
  1107. ts.begin(mySpi);
  1108. ts.setRotation(3);
  1109.  
  1110. // mySpi2 -> pour le lecteur de SDcard
  1111. // mySpi2 -> partage du bus SPI - mêmes valeurs de GPIO (sck=14, miso=12)
  1112. // que pour l'afficheur ILI9341 , sauf CS=5. Voir sur le schéma ainsi que le fichier User_Setup.h
  1113. mySpi2.begin(14, 12, 13, 5);
  1114.  
  1115. init_SDcard();
  1116. delay(20);
  1117.  
  1118. TFT.init();
  1119. TFT.setRotation(3); // 0..3 à voir, suivant disposition de l'afficheur
  1120. TFT.fillScreen(NOIR);
  1121.  
  1122. affi_page_info();
  1123. delay(300);
  1124.  
  1125. affi_image_from_SD("/bmp565/7.bmp", 0, 0); // IMAGE D'ACCEUIL
  1126. delay(300);
  1127.  
  1128. if (SDcardOk == false)
  1129. {
  1130. affi_message
  1131. (
  1132. "SDcard absente",
  1133. "Des parametres et fonctions",
  1134. "vont manquer: freq preset,",
  1135. "couleurs, capture ecran,",
  1136. "calibrage Touch Screen..."
  1137. );
  1138. }
  1139.  
  1140. init_sprites();
  1141.  
  1142. if (SDcardOk == true)
  1143. {
  1144. read_params(); // sur la SDcard
  1145. }
  1146. else
  1147. {
  1148. frequence = 88000;
  1149. }
  1150.  
  1151. // si les coordonnées des points de calibrage sont aux fraises...
  1152. if ( (A.x <300) || (A.x >700) || (A.y <200) || (A.y >600) ||
  1153. (B.x < 3500) || (B.x > 3900) || (B.y <3400) || (A.y >3800) )
  1154. {
  1155. TS_calibrate();
  1156. }
  1157.  
  1158. groupe_SW.filename = "/FRQ_SW.txt"; // nom du fichier sur la SDcard
  1159. groupe_FM.filename = "/FRQ_FM.txt";
  1160. groupe_AIR.filename = "/FRQ_AIR.txt";
  1161.  
  1162. if (SDcardOk == true)
  1163. {
  1164. load_GRP_FREQ_SD();
  1165. groupe_SCAN.RAZ();
  1166. presetPad1.set_frequences_PRST();
  1167. presetPad1.set_couleurs();
  1168. } // -> to RAM
  1169. else
  1170. {
  1171. set_frq_default();
  1172. }
  1173.  
  1174. init_affichages();
  1175.  
  1176. saut_freq = 100;
  1177.  
  1178. //Tuner_Patch(); // envoi une tartine (6000 bytes) de code, non documentée; Je ne constate aucun effet bénéfique...
  1179. /*
  1180. Le PDF de NXP précise : "Use of these I2C transmissions is required for proper and full function and performance
  1181. as described in this user manual". (une sorte de vaccin anti-Covid donc...)
  1182. Toutefois si quelqu'un a réussi à déchiffrer le truc et peut me donner la liste des fonctions améliorées
  1183. je serais très heureux de le publier ici. Vous avez mon e-mail sur mon site www.silicium628.fr
  1184. */
  1185. //delay(50);
  1186.  
  1187. Tuner_Init(tuner_init_tab9216);
  1188. delay(50);
  1189.  
  1190. // Set_no_AM_gain_reduction();
  1191.  
  1192. bt_mode_FRQ.selected = false;
  1193. bt_mode_MEM.selected = true;
  1194.  
  1195. uint16_t c1 = GRIS_6;
  1196. uint16_t c2 = VERT;
  1197. uint16_t c3 = JAUNE;
  1198. bt_mode_FRQ.affiche(c2, 2); // bt en haut à gauche
  1199. bt_mode_MEM.affiche(c3, 2); // bt en haut à gauche
  1200.  
  1201. groupe_actif = gFM;
  1202. bande_active = FM;
  1203. modulation_active = WFM;
  1204. bt_FM.selected = true;
  1205. bt_SW.selected = false;
  1206. bt_AIR.selected = false;
  1207. bt_SCN.selected = false;
  1208.  
  1209. bt_SW.affiche(c2, 1);
  1210. bt_FM.affiche(c3, 1);
  1211.  
  1212. //clic_logiciel_bouton(&presetPad1.bt_preset[0]);
  1213. //traite_boutons_presetPad(0);
  1214.  
  1215. uint8_t nb_F = groupe_FM.nb_freq;
  1216. affiche_numero_frq(String(1), String(nb_F));
  1217.  
  1218. //couleur_fond_ecran = VERT_FONCE;
  1219.  
  1220. Serial.print("frequence="); Serial.println(frequence);
  1221. affiche_frequence(frequence);
  1222. Tune_Frequence(frequence);
  1223.  
  1224. Set_Volume(+70); // +60
  1225. delay(20);
  1226.  
  1227. //clic_logiciel_bouton(&bt_mode_MEM);
  1228. mode_s = _MEM;
  1229.  
  1230. if (test_touch_screen == true) {printTouchToDisplay();}
  1231.  
  1232. // TS_calibrate(); pour forcer le calibrage
  1233.  
  1234. chf_pad1.init();
  1235.  
  1236. Serial.print("- FIN DU SETUP -----------------");
  1237. // FIN DU SETUP
  1238. }
  1239.  
  1240.  
  1241. void get_XY_touch()
  1242. {
  1243. TS_Point p = ts.getPoint();
  1244. float dx = B.x - A.x;
  1245. float ech_x = 300.0 / dx;
  1246. float x0 = A.x;
  1247.  
  1248. float dy = B.y - A.y;
  1249. float ech_y = 220.0 / dy;
  1250. float y0 = A.y;
  1251.  
  1252. memo_x_touch = x_touch;
  1253. memo_y_touch = y_touch;
  1254.  
  1255. x_touch = 10 + uint16_t( (p.x - x0) * ech_x);
  1256. y_touch = 10 + uint16_t( (p.y - y0) * ech_y);
  1257.  
  1258. /*
  1259. TFT.pushRect(memo_x_touch, memo_y_touch-10, 1, 20, memo_tiret_V); // efface avec l'image enregistrée
  1260. TFT.pushRect(memo_x_touch-10, memo_y_touch, 20, 1, memo_tiret_H); // efface avec l'image enregistrée
  1261.  
  1262. TFT.readRect(x_touch, y_touch-10, 1, 20, memo_tiret_V); // mémorise le segment avant de tracer
  1263. TFT.readRect(x_touch-10, y_touch, 20, 1, memo_tiret_H); // mémorise le segment avant de tracerfloat sy = sin((i - 90) * deg_to_rad);
  1264.  
  1265. TFT.drawFastVLine(x_touch, y_touch-10, 20, NOIR); // tiret vertical
  1266. TFT.drawFastHLine(x_touch-10, y_touch, 20, NOIR); // tiret horizontal
  1267. */
  1268.  
  1269. }
  1270.  
  1271.  
  1272. void printTouchToDisplay() // pour TEST
  1273. {
  1274. TFT.fillScreen(NOIR);
  1275.  
  1276. TFT.setFreeFont(FM9);
  1277. TFT.setTextColor(BLEU_CLAIR, NOIR);
  1278. TFT.drawString("TEST TOUCH screen", 80, 120);
  1279.  
  1280. while(1)
  1281. {
  1282. if (ts.tirqTouched() && ts.touched())
  1283. {
  1284. get_XY_touch();
  1285. TFT.drawRect(x_touch, y_touch, 1, 1, JAUNE);
  1286. }
  1287. }
  1288. }
  1289.  
  1290.  
  1291. // -------------------------------------------------------------------------
  1292. // Le vu-metre est une variante perso du code : "/Arduino/libraries/TFT_eSPI/examples/480 x 320/TFT_Meters"
  1293. // voir le fichier licence.txt dans le dossier "/Arduino/libraries/TFT_eSPI/examples/"
  1294. void dessine_VuMetre()
  1295. {
  1296. if (vu_metre_actif == false) {return;}
  1297.  
  1298. uint16_t x0 = x0_vu_metre;
  1299. uint16_t y0 = y0_vu_metre;
  1300.  
  1301. uint16_t dx=140;
  1302. uint16_t dy=70;
  1303.  
  1304. uint8_t AA = 65; // 65
  1305. uint8_t BB = x0 +dx/2;// 120
  1306. uint8_t CC = y0 + dy+20; // 140
  1307.  
  1308. TFT.setFreeFont(FF0);
  1309. // cadre rectangulaire
  1310. TFT.fillRect(x0, y0, dx, dy, GRIS_3);
  1311. TFT.fillRect(x0+3, y0+3, dx-6, dy-6, BLANC);
  1312.  
  1313. TFT.setTextColor(NOIR);
  1314.  
  1315. // graduation chaque 5 deg entre -50 et +50 deg
  1316. for (int i = -50; i < 51; i += 10)
  1317. {
  1318. int tl = 5; // tiret plus long
  1319. // Coordonnées du tiret à dessiner
  1320. float sx = cos((i - 90) * deg_to_rad);
  1321. float sy = sin((i - 90) * deg_to_rad);
  1322. uint16_t tx0 = sx * (AA + tl) + BB;
  1323. uint16_t ty0 = sy * (AA + tl) + CC;
  1324. uint16_t tx1 = sx * AA + BB;
  1325. uint16_t ty1 = sy * AA + CC;
  1326.  
  1327. float sx2 = cos((i + 5 - 90) * deg_to_rad);
  1328. float sy2 = sin((i + 5 - 90) * deg_to_rad);
  1329. int tx2 = sx2 * (AA + tl) + BB;
  1330. int ty2 = sy2 * (AA + tl) + CC;
  1331. int tx3 = sx2 * AA + BB;
  1332. int ty3 = sy2 * AA + CC;
  1333.  
  1334. // zone verte
  1335. if (i >= 0 && i < 25)
  1336. {
  1337. TFT.fillTriangle(tx0, ty0, tx1, ty1, tx2, ty2, VERT);
  1338. TFT.fillTriangle(tx1, ty1, tx2, ty2, tx3, ty3, VERT);
  1339. }
  1340.  
  1341. // zone orange
  1342. if (i >= 25 && i < 50)
  1343. {
  1344. TFT.fillTriangle(tx0, ty0, tx1, ty1, tx2, ty2, ORANGE);
  1345. TFT.fillTriangle(tx1, ty1, tx2, ty2, tx3, ty3, ORANGE);
  1346. }
  1347.  
  1348. if (i % 25 != 0) tl = 8;
  1349.  
  1350. tx0 = sx * (AA + tl) + BB;
  1351. ty0 = sy * (AA + tl) + CC;
  1352. tx1 = sx * AA + BB;
  1353. ty1 = sy * AA + CC;
  1354.  
  1355. TFT.drawLine(tx0, ty0, tx1, ty1, NOIR);
  1356.  
  1357. if (i % 20 == 0)
  1358. {
  1359. tx0 = sx * (AA + tl + 10) + BB;
  1360. ty0 = sy * (AA + tl + 10) + CC;
  1361. switch (i / 20)
  1362. {
  1363. case -2: TFT.drawCentreString("0", tx0, ty0 - 6, 1); break;
  1364. case -1: TFT.drawCentreString("25", tx0, ty0 - 4, 1); break;
  1365. case 0: TFT.drawCentreString("50", tx0, ty0 - 6, 1); break;
  1366. case 1: TFT.drawCentreString("75", tx0, ty0 - 4, 1); break;
  1367. case 2: TFT.drawCentreString("100", tx0, ty0 - 6, 1); break;
  1368. }
  1369. }
  1370. sx = cos((i + 5 - 90) * deg_to_rad);
  1371. sy = sin((i + 5 - 90) * deg_to_rad);
  1372. tx0 = sx * AA + BB;
  1373. ty0 = sy * AA + CC;
  1374. if (i < 50) {TFT.drawLine(tx0, ty0, tx1, ty1, NOIR);}
  1375. }
  1376. }
  1377.  
  1378.  
  1379.  
  1380. void plotAiguille(float value)
  1381. {
  1382. if (vu_metre_actif == false) {return;}
  1383.  
  1384. uint16_t x0 = x0_vu_metre;
  1385. uint16_t y0 = y0_vu_metre;
  1386. uint16_t dx=140;
  1387. uint16_t dy=50;
  1388.  
  1389. uint8_t AA = dx/2; // 100
  1390. uint8_t BB = x0 +dx/2;// 120
  1391. uint8_t CC = y0 + dy+25; // 140
  1392.  
  1393. TFT.setTextColor(TFT_BLACK, BLANC);
  1394. char buf[8]; dtostrf(value, 4, 0, buf);
  1395.  
  1396. if (value < -10) value = -10;
  1397. if (value > 110) value = 110;
  1398.  
  1399. float sdeg = map(value, -10, 110, -150, -30);
  1400. float sx = cos(sdeg * deg_to_rad);
  1401. float sy = sin(sdeg * deg_to_rad);
  1402.  
  1403. float tx = tan((sdeg + 90) * deg_to_rad);
  1404.  
  1405. TFT.drawLine(BB + 20*ltx - 1, CC - 20, osx - 1, osy, BLANC); //efface
  1406. TFT.drawLine(BB + 20*ltx, CC - 20, osx, osy, BLANC);
  1407. TFT.drawLine(BB + 20*ltx + 1, CC - 20, osx + 1, osy, BLANC);
  1408.  
  1409. ltx = tx;
  1410. osx = sx*50 + BB;
  1411. osy = sy*50 + CC;
  1412.  
  1413. TFT.drawLine(BB + 20*ltx - 1, CC - 20, osx - 1, osy, ROUGE);
  1414. TFT.drawLine(BB + 20*ltx, CC - 20, osx, osy, VIOLET);
  1415. TFT.drawLine(BB + 20*ltx + 1, CC - 20, osx + 1, osy, ROUGE);
  1416.  
  1417. TFT.fillRect(x0, y0+dy+5, dx, 15, GRIS_2);
  1418. }
  1419.  
  1420.  
  1421.  
  1422. void init_box_info() // en bas à gauche
  1423. {
  1424. TFT.fillRect(x0_box_info1+1, y0_box_info1+1, 118, 16, NOIR); // efface
  1425. TFT.setFreeFont(FF0);
  1426. TFT.setTextColor(JAUNE, couleur_fond_ecran);
  1427. //TFT.drawString("RDS", x0_box_info1 -20, y0_box_info1 + 4);
  1428. }
  1429.  
  1430.  
  1431. void affiche_unit(String s)
  1432. {
  1433. TFT.setTextColor(JAUNE, NOIR);
  1434. TFT.setFreeFont(FM9); //FM9 FMB9 FSS9... voir le fichier FrSD_Fonts.h
  1435. TFT.drawString(s, FRQ_x0 + 225, FRQ_y0 + 35);
  1436. }
  1437.  
  1438.  
  1439. void efface_numero_frq()
  1440. {
  1441. TFT.fillRect(FRQ_x0 + 225, FRQ_y0 + 20, 40, 12, couleur_fond_ecran);
  1442. }
  1443.  
  1444.  
  1445. void affiche_numero_frq(String s1, String s2)
  1446. {
  1447. //TFT.fillRect(FRQ_x0 + 225, FRQ_y0 + 5, 10, 10, BLEU);
  1448. TFT.setTextColor(BLANC, couleur_fond_ecran);
  1449. TFT.setFreeFont(FF0);
  1450. TFT.drawString(s1 + "/" + s2 + " ", FRQ_x0 + 225, FRQ_y0 + 20);
  1451. affiche_box_FRQ(GRIS_3); // pour retracer le côté droit du rectangle
  1452. }
  1453.  
  1454.  
  1455. void affiche_band(String s) // à droite des gros chiffres
  1456. {
  1457. //TFT.fillRect(FRQ_x0 + 225, FRQ_y0 + 5, 10, 10, BLEU);
  1458. TFT.setTextColor(BLANC, NOIR);
  1459. TFT.setFreeFont(FM9);
  1460. String blancs;
  1461. if (s == "AIR") {blancs = " ";} else {blancs = " ";}
  1462.  
  1463. TFT.drawString(s + blancs, FRQ_x0 + 225, FRQ_y0);
  1464. affiche_box_FRQ(GRIS_3); // pour retracer le côté droit du rectangle
  1465. }
  1466.  
  1467.  
  1468. void efface_box_entete1() // tout en haut à gauche
  1469. {
  1470. TFT.fillRect(1, 1, 50, 12, NOIR);
  1471. TFT.drawFastVLine(50, 0, 12, BLANC);
  1472. }
  1473.  
  1474.  
  1475. void efface_box_entete2() // tout en haut au centre
  1476. {
  1477. TFT.fillRect(50, 1, 180, 12, NOIR);
  1478. TFT.drawFastVLine(50, 0, 12, BLANC);
  1479. TFT.drawFastVLine(230, 0, 12, BLANC);
  1480. }
  1481.  
  1482.  
  1483. void efface_box_entete3() // tout en haut à droite
  1484. {
  1485. TFT.fillRect(230, 1, 89, 12, BLEU);
  1486. TFT.drawFastVLine(230, 0, 12, BLANC);
  1487. memo_valeur_affi--; // pour réafficher tension batterie
  1488. }
  1489.  
  1490.  
  1491. void affiche_box_FRQ(uint16_t couleur) // autour de la fréquence (en gros chiffres JAUNE
  1492. {
  1493. TFT.drawRect(0, FRQ_y0 -17, 319, 74, couleur);
  1494. }
  1495.  
  1496.  
  1497. void affiche_box_presets() // boutons 1 2 3 4 5 6 7 8
  1498. {
  1499. TFT.fillRect(x0_box_PRESET, y0_box_PRESET, 164, 24, NOIR);
  1500. TFT.setTextColor(GRIS_3, NOIR);
  1501.  
  1502. }
  1503.  
  1504.  
  1505. void affiche_box_GROUPE() // groupes de fréquences; contient 4 boutons SW, FM, AIR, SC
  1506. {
  1507. TFT.fillRect(x0_box_GROUPE, y0_box_GROUPE, 105, 23, NOIR);
  1508. //TFT.drawRect(x0_box_GROUPE, y0_box_GROUPE, 105, 25, couleur_traits);
  1509. TFT.setFreeFont(FF0);
  1510. TFT.setTextColor(GRIS_3, NOIR);
  1511. TFT.drawString("groupes Freq", x0_box_GROUPE+4, y0_box_GROUPE-6);
  1512. }
  1513.  
  1514.  
  1515. void efface_box_GROUPE()
  1516. {
  1517. //TFT.fillRect(x0_box_GROUPE, y0_box_GROUPE-7, 110, 33, couleur_fond_ecran);
  1518. //TFT.fillRect(x0_box_SCAN, y0_box_SCAN, dx_box_SCAN, dy_box_SCAN, NOIR);
  1519. }
  1520.  
  1521.  
  1522. void affiche_box_SD() // Raz, Write, Raz 1F, LST
  1523. {
  1524. TFT.fillRect(x0_box_SD, y0_box_SD + 10, 46, 58, NOIR);
  1525. TFT.setFreeFont(FF0);
  1526. TFT.setTextColor(GRIS_3, NOIR);
  1527. TFT.drawString("SD", x0_box_SD+6, y0_box_SD+6);
  1528. }
  1529.  
  1530.  
  1531. void affiche_box_scan(uint16_t dy)
  1532. {
  1533. init_1_bouton_rouge(1, 295, y0_box_SCAN+1, 20, 20, "x", &bt_stop_scan);
  1534. if (bande_active != AIR)
  1535. {
  1536. init_1_bouton(1, 275, y0_box_SCAN+40, 40, 15, "rescan", &bt_re_scan);
  1537. init_1_bouton(1, 275, y0_box_SCAN+58, 40, 14, " >>", &bt_scan_suivant);
  1538. }
  1539. init_1_bouton(1, 255, y0_box_SCAN+1, 25, 15, "+", &bt_seuil_plus);
  1540. init_1_bouton(1, 255, y0_box_SCAN+20, 25, 15, "-", &bt_seuil_moins);
  1541. init_1_bouton(1, 4, y0_box_SCAN+3, 15, 15, "L", &bt_LEV);
  1542. init_1_bouton(1, 4, y0_box_SCAN+20, 15, 15, "N", &bt_SNR);
  1543. }
  1544.  
  1545.  
  1546. void affi_boutons_SW_FM_AIR_SCN()
  1547. {
  1548. if((mode_affi == SCAN_F ) || (mode_affi == SCAN_M )) {return;}
  1549.  
  1550. uint16_t c1 = GRIS_5;
  1551. uint16_t c2 = VERT;
  1552. bt_SW.affiche(c2, 1);
  1553. bt_FM.affiche(c2, 1);
  1554. bt_AIR.affiche(c2, 1);
  1555. bt_SCN.affiche(BLEU_CLAIR, 1);
  1556. bt_mute.affiche(ROUGE, 1);
  1557.  
  1558. }
  1559.  
  1560.  
  1561. void affiche_frequence(uint32_t frq)
  1562. {
  1563. Serial.println("affiche_frequence()");
  1564.  
  1565. if((mode_affi != SCAN_F) && (mode_affi != SCAN_M))
  1566. {
  1567. TFT.fillRect(x0_box_info1+2, y0_box_info1, 118, 16, NOIR); // efface (en bas à gauche)
  1568. }
  1569.  
  1570. uint16_t couleur_chiffres;
  1571.  
  1572. if(mode_s == _FRQ) {couleur_chiffres = VERT_chiffres;}
  1573. if(mode_s == _MEM) {couleur_chiffres = JAUNE_chiffres;}
  1574.  
  1575.  
  1576. if(bande_SW) // d'après la fréquence; SW - 28 MHz = limite haute du module
  1577. {
  1578. modulation_active = AM;
  1579. if (groupe_actif != gSCN)
  1580. {
  1581. affiche_band("SW");
  1582. bande_active = SW; groupe_actif == gSW;
  1583. bt_SW.selected = true;
  1584. bt_SCN.selected = false;
  1585. }
  1586.  
  1587. bt_FM.selected = false; // les boutons sont exclusifs
  1588. bt_AIR.selected = false;
  1589.  
  1590. affi_boutons_SW_FM_AIR_SCN();
  1591.  
  1592. String s1, sM, sK;
  1593. uint8_t L;
  1594.  
  1595. s1 = String(frq);
  1596. s1 = "000000" + s1;
  1597. L= s1.length();
  1598.  
  1599. sK = s1.substring(L-3); // kHz
  1600. sM = s1.substring(L-6, L-3); // Mhz
  1601.  
  1602. sprite_frq.fillRect(0, 0, 220, 60, NOIR); // efface
  1603.  
  1604. sprite_frq.setTextColor(couleur_chiffres, NOIR);
  1605. sprite_frq.drawString(sM + "." + sK + " ", 220+10, 32);
  1606. // remarque: le fait d'ajouter " " à la fin évite aux chiffres de se balader horizontalement !
  1607. sprite_frq.pushSprite(FRQ_x0, FRQ_y0);
  1608. affiche_unit("MHz");
  1609. Tune_Frequence(frq);
  1610. }
  1611.  
  1612. else if(bande_FM) // bande FM, on efface les deux '0' de droite (si == 0 sinon on affiche quand même)
  1613. {
  1614. affiche_band("FM");
  1615. modulation_active = WFM;
  1616. if (groupe_actif != gSCN) {bande_active = FM; groupe_actif == gFM;}
  1617.  
  1618. affi_boutons_SW_FM_AIR_SCN();
  1619.  
  1620. String s1, sM, sK1, sK2, sK3;
  1621. String decimales;
  1622. uint8_t x0 = 0;
  1623. uint8_t L;
  1624.  
  1625. s1 = String(frq);
  1626. s1 = "000000" + s1;
  1627. L= s1.length();
  1628.  
  1629. sK1 = s1.substring(L-3, L-2); // 1ere décimale
  1630. sK2 = s1.substring(L-2, L-1); // 2eme décimale
  1631. sK3 = s1.substring(L-1, L); // 3eme décimale
  1632.  
  1633. if ((sK2 == "0") && (sK3 == "0"))
  1634. {
  1635. decimales = sK1;
  1636. x0=170;
  1637. }
  1638. else
  1639. {
  1640. decimales = sK1 + sK2 + sK3;
  1641. x0=232;
  1642. }
  1643.  
  1644. if (frq < 100000) {sM = s1.substring(L-5, L-3); }// on ne retient que deux chiffres à gauche du point
  1645. else { sM = s1.substring(L-6, L-3); } // on garde 3 chiffres à gauche du point décimal
  1646.  
  1647. sprite_frq.fillRect(0, 0, 220, 60, NOIR); // efface
  1648. sprite_frq.setTextColor(couleur_chiffres, NOIR);
  1649. sprite_frq.drawString(sM + "." + decimales + " ", x0, 32);
  1650. // remarque: le fait d'ajouter " " à la fin évite aux chiffres de se balader horizontalement !
  1651. sprite_frq.pushSprite(FRQ_x0, FRQ_y0);
  1652. affiche_unit("MHz");
  1653.  
  1654. Tune_Frequence(frq);
  1655. bt_mute.selected = false;
  1656. bt_mute.cliked = false;
  1657.  
  1658. }
  1659.  
  1660. else if(bande_AIR) // bande AIR - 138000-110000 = 28MHz (limite haute de réception AM du module)
  1661. {
  1662. affiche_band("AIR");
  1663. modulation_active = AM;
  1664. if (groupe_actif != gSCN) {bande_active = AIR; groupe_actif == gAIR;}
  1665.  
  1666. bt_AIR.selected = true;
  1667. bt_SW.selected = false; // les boutons sont exclusifs
  1668. bt_FM.selected = false;
  1669. bt_SCN.selected = false;
  1670. affi_boutons_SW_FM_AIR_SCN();
  1671.  
  1672. String s1, sM, sK;
  1673. uint8_t L;
  1674.  
  1675. s1 = String(frq);
  1676. s1 = "000000" + s1;
  1677. L= s1.length();
  1678.  
  1679. sK = s1.substring(L-3); // kHz
  1680. sM = s1.substring(L-6, L-3); // Mhz
  1681.  
  1682. sprite_frq.fillRect(0, 0, 220, 60, NOIR); // efface
  1683. sprite_frq.setTextColor(couleur_chiffres, NOIR);
  1684. sprite_frq.drawString(sM + "." + sK + " ", 220+10, 32);
  1685. sprite_frq.pushSprite(FRQ_x0, FRQ_y0);
  1686. affiche_unit("MHz");
  1687. Tune_Frequence(frq);
  1688. }
  1689.  
  1690. else if(bande_interdite1 || bande_interdite2) // bandes interdites par le module TEF6686
  1691. {
  1692. affiche_band("---");
  1693. TFT.setTextColor(ROUGE, NOIR);
  1694. TFT.setFreeFont(FF0);
  1695. TFT.drawString("FRQ non disponible", 80, 2);
  1696. //delay(2000);
  1697.  
  1698. String s1, sM, sK;
  1699. uint8_t L;
  1700.  
  1701. s1 = String(frq);
  1702. s1 = "000000" + s1;
  1703. L= s1.length();
  1704.  
  1705. sK = s1.substring(L-3); // kHz
  1706. sM = s1.substring(L-6, L-3); // Mhz
  1707.  
  1708. sprite_frq.fillRect(0, 0, 220, 60, NOIR); // efface
  1709. sprite_frq.setTextColor(GRIS_1, NOIR);
  1710. sprite_frq.drawString(sM + "." + sK + " ", 220+10, 32);
  1711. // remarque: le fait d'ajouter " " à la fin évite aux chiffres de se balader horizontalement !
  1712. sprite_frq.pushSprite(FRQ_x0, FRQ_y0);
  1713. affiche_unit("MHz");
  1714.  
  1715. bt_mute.selected = true;
  1716. bt_mute.affiche(ROUGE, 1);
  1717. bt_mute.selected = false;
  1718. mute = true;
  1719. Set_Mute(mute); // fonction située dans le fichier 'driverTEF6686_628.h'
  1720.  
  1721. }
  1722. else
  1723. {
  1724. affiche_band("---");
  1725. TFT.setTextColor(ROUGE, NOIR);
  1726. TFT.setFreeFont(FF0);
  1727. TFT.drawString("FRQ non disponible", 80, 2);
  1728. //delay(2000);
  1729.  
  1730. String s1, sM, sK;
  1731. uint8_t L;
  1732.  
  1733. s1 = String(frq);
  1734. s1 = "000000" + s1;
  1735. L= s1.length();
  1736.  
  1737. sK = s1.substring(L-3); // kHz
  1738. sM = s1.substring(L-6, L-3); // Mhz
  1739.  
  1740. sprite_frq.fillRect(0, 0, 220, 60, NOIR); // efface
  1741. sprite_frq.setTextColor(GRIS_1, NOIR);
  1742. sprite_frq.drawString(sM + "." + sK + " ", 220+10, 32);
  1743. // remarque: le fait d'ajouter " " à la fin évite aux chiffres de se balader horizontalement !
  1744. sprite_frq.pushSprite(FRQ_x0, FRQ_y0);
  1745. affiche_unit("MHz");
  1746.  
  1747. bt_mute.selected = true;
  1748. bt_mute.affiche(ROUGE, 1);
  1749. bt_mute.selected = false;
  1750. mute = true;
  1751. Set_Mute(mute); // fonction située dans le fichier 'driverTEF6686_628.h
  1752. }
  1753.  
  1754. if(frq==138000) { affiche_band("max"); }
  1755. if(frq>138000) { affiche_band("---"); }
  1756. }
  1757.  
  1758.  
  1759. void clic_logiciel_bouton(TOUCH_BOUTON *bouton_i)
  1760. {
  1761. uint16_t c1 = NOIR;
  1762. uint16_t c2 = JAUNE;
  1763.  
  1764. bouton_i->cliked = true;
  1765. bouton_i->selected = true;
  1766. bouton_i->affiche(c2, 1);
  1767. }
  1768.  
  1769.  
  1770.  
  1771. void test_clic_boutons(TOUCH_BOUTON *bouton_i)
  1772. {
  1773. uint16_t c1 = NOIR;
  1774. uint16_t c2 = GRIS_2;
  1775.  
  1776. if ((x_touch > bouton_i->x0) && (x_touch < (bouton_i->x0 )+ bouton_i->read_dx())
  1777. && ( y_touch > ((bouton_i->y0) -5) ) && (y_touch < ((bouton_i->y0) + (bouton_i->read_dy())+5) ) )
  1778. {
  1779. bouton_i->cliked = true;
  1780. bouton_i->selected = true;
  1781. //bouton_i->affiche(c2, 1);
  1782. delay(100);
  1783. }
  1784. }
  1785.  
  1786.  
  1787.  
  1788.  
  1789. int test_clic_boutons_inc_dec() // boutons invisibles placés derrière les chiffres de la fréquence
  1790. {
  1791. int8_t num_bouton = -1;
  1792. uint64_t dF;
  1793.  
  1794. TOUCH_BOUTON bt_Hi, bt_Li;
  1795. for(uint8_t n=0; n<6; n++)
  1796. {
  1797. bt_Hi = chf_pad1.bt_pad_H[n];
  1798. test_clic_boutons(&bt_Hi);
  1799. if(bt_Hi.cliked)
  1800. {
  1801. bt_Hi.cliked=false;
  1802. mode_s = _FRQ;
  1803. bt_mode_FRQ.selected = true;
  1804. bt_mode_MEM.selected = false;
  1805. affiche_frequence(frequence);
  1806. efface_numero_frq();
  1807. num_bouton = n;
  1808. }
  1809.  
  1810. bt_Li = chf_pad1.bt_pad_L[n];
  1811. test_clic_boutons(&bt_Li);
  1812. if(bt_Li.cliked)
  1813. {
  1814. bt_Li.cliked=false;
  1815. mode_s = _FRQ;
  1816. bt_mode_FRQ.selected = true;
  1817. bt_mode_MEM.selected = false;
  1818. affiche_frequence(frequence);
  1819. efface_numero_frq();
  1820. num_bouton = n+6;
  1821. }
  1822. }
  1823.  
  1824. if(num_bouton != -1)
  1825. {
  1826. if (num_bouton<6) // boutons du haut -> inc F
  1827. {
  1828. dF = pow(10, 5-num_bouton);
  1829. frequence += dF;
  1830. }
  1831. if ((num_bouton>=6) && (num_bouton<12)) // boutons du bas -> dec F
  1832. {
  1833. dF = pow(10, 11-num_bouton);
  1834. if (frequence > dF) {frequence -= dF;}
  1835. else {frequence = 1;}
  1836. }
  1837.  
  1838. if (frequence == 0) {frequence = 1;}
  1839. //if (frequence > 4400000000) {frequence = 4400000000;}
  1840. //if (frequence < F_min_AD9850) {frequence = F_min_AD9850;}
  1841.  
  1842. affiche_frequence(frequence);
  1843. delay(100);
  1844. }
  1845. return num_bouton;
  1846. }
  1847.  
  1848.  
  1849.  
  1850. void affiche_saisie(String s1)
  1851. {
  1852. efface_box_entete1();
  1853. TFT.setFreeFont(FF0); TFT.setTextColor(VERT, NOIR);
  1854. TFT.drawString(s1, x0_saisie+2, y0_saisie);
  1855. }
  1856.  
  1857.  
  1858. void traite_touches_pad(uint8_t num_touche) // pavé numérique
  1859. {
  1860. if(num_touche == 253) {return;}
  1861.  
  1862. uint16_t c1 = GRIS_6;
  1863. uint16_t c2 = JAUNE;
  1864. uint16_t c3 = VERT;
  1865.  
  1866. int p1;
  1867.  
  1868. if (num_touche == 254) // bouton "."
  1869. {
  1870. frequence_txt += ".";
  1871. affiche_saisie(frequence_txt);
  1872. }
  1873.  
  1874. if (num_touche < 10)
  1875. {
  1876. frequence_txt += String(num_touche);
  1877. affiche_saisie(frequence_txt);
  1878. delay(300);
  1879. }
  1880.  
  1881. x_touch =0;
  1882. y_touch =0;
  1883.  
  1884. if (num_touche == 255) // bouton "ok"
  1885. {
  1886. Serial.println("touche ok");
  1887.  
  1888. efface_box_entete1();
  1889. efface_box_entete2();
  1890. //affiche_saisie(""); // efface
  1891.  
  1892. mode_s = _FRQ;
  1893. bt_mode_MEM.selected = false;
  1894. bt_mode_FRQ.selected = true;
  1895.  
  1896. bt_mode_MEM.affiche(c2, 2);
  1897. bt_mode_FRQ.affiche(c3, 2);
  1898.  
  1899. double F = frequence_txt.toDouble();
  1900. p1 = frequence_txt.indexOf(".");
  1901. if (p1 != -1) {F *=1000;} // si présence du point décimal
  1902.  
  1903. frequence = F;
  1904. affiche_frequence(frequence); // 'Tune_Frequence(frq)' est appelée dans cette fonction 'affiche_frequence()'
  1905.  
  1906. n_appui = 0;
  1907. frequence_txt = "";
  1908. n_appui = 0;
  1909.  
  1910. }
  1911. num_touche = 0;
  1912. }
  1913.  
  1914.  
  1915. void write_fichier_params() // sur la SDcard
  1916. {
  1917. Serial.println("write fichier '/params.txt'");
  1918.  
  1919. File file1 = SD.open("/params.txt", FILE_WRITE);
  1920. String s1;
  1921.  
  1922. s1 ="[couleur_fond]";
  1923. s1 += "<";
  1924. s1 += String(couleur_fond_ecran);
  1925. s1 +=">";
  1926. file1.println(s1);
  1927.  
  1928. s1 ="[frequence]";
  1929. s1 += "<";
  1930. s1 += String(frequence);
  1931. s1 +=">";
  1932. file1.println(s1);
  1933.  
  1934. s1 ="[Ax]";
  1935. s1 += "<";
  1936. s1 += String(A.x);
  1937. s1 +=">";
  1938. file1.println(s1);
  1939.  
  1940. s1 ="[Ay]";
  1941. s1 += "<";
  1942. s1 += String(A.y);
  1943. s1 +=">";
  1944. file1.println(s1);
  1945.  
  1946. s1 ="[Bx]";
  1947. s1 += "<";
  1948. s1 += String(B.x);
  1949. s1 +=">";
  1950. file1.println(s1);
  1951.  
  1952. s1 ="[By]";
  1953. s1 += "<";
  1954. s1 += String(B.y);
  1955. s1 +=">";
  1956. file1.println(s1);
  1957.  
  1958.  
  1959. file1.close();
  1960. delay(100);
  1961. }
  1962.  
  1963.  
  1964. void record_fichier_FRQ_SW_PRST()
  1965. {
  1966. Serial.println("record_fichier_FRQ_SW_PRST()");
  1967.  
  1968. File file1 = SD.open("FRQ_FM_PRST.txt", FILE_WRITE);
  1969. String s1;
  1970.  
  1971. for(uint8_t n=0; n<8; n++)
  1972. {
  1973. s1 = "<";
  1974. s1 += String(presetPad1.bt_preset[n].frequence_SW);
  1975. s1 +=">";
  1976. file1.println(s1);
  1977. }
  1978.  
  1979. file1.close();
  1980. }
  1981.  
  1982.  
  1983.  
  1984. void record_fichier_FRQ_FM_PRST()
  1985. {
  1986. Serial.println("record_fichier_FRQ_FM_PRST()");
  1987.  
  1988. File file1 = SD.open("FRQ_FM_PRST.txt", FILE_WRITE);
  1989. String s1;
  1990.  
  1991. for(uint8_t n=0; n<8; n++)
  1992. {
  1993. s1 = "<";
  1994. s1 += String(presetPad1.bt_preset[n].frequence_FM);
  1995. s1 +=">";
  1996. file1.println(s1);
  1997. }
  1998. file1.close();
  1999. }
  2000.  
  2001.  
  2002. void record_fichier_FRQ_AIR_PRST()
  2003. {
  2004. Serial.println("record_fichier_FRQ_AIR_PRST()");
  2005.  
  2006. File file1 = SD.open("FRQ_AIR_PRST.txt", FILE_WRITE);
  2007. String s1;
  2008.  
  2009. for(uint8_t n=0; n<8; n++)
  2010. {
  2011. s1 = "<";
  2012. s1 += String(presetPad1.bt_preset[n].frequence_AIR);
  2013. s1 +=">";
  2014. file1.println(s1);
  2015. }
  2016. file1.close();
  2017. }
  2018.  
  2019.  
  2020. void traite_boutons_presetPad(uint8_t n_bt)
  2021. {
  2022. if (n_bt > 7) {return;}
  2023.  
  2024. uint16_t c1 = GRIS_5;
  2025. uint16_t c2 = JAUNE;
  2026. uint32_t adr0, adr1, adr2, adr;
  2027.  
  2028. if (mode_affi == NORMAL)
  2029. {
  2030. if(bande_active == SCN)
  2031. {
  2032. bande_active = FM; // afin de pouvoir traiter les fréquences preset attribuées aux boutons
  2033. groupe_actif = gFM;
  2034. modulation_active = WFM;
  2035. bt_FM.selected = true;
  2036. bt_SW.selected = false;
  2037. bt_AIR.selected = false;
  2038. bt_SCN.selected = false;
  2039. affi_boutons_SW_FM_AIR_SCN();
  2040. }
  2041. mode_s = _MEM;
  2042. bt_mode_MEM.selected = true;
  2043. bt_mode_FRQ.selected = false;
  2044. bt_mode_MEM.affiche(c2, 2);
  2045. bt_mode_FRQ.affiche(c2, 2);
  2046. affiche_frequence(frequence);
  2047.  
  2048. // Lit la frequence dans le bouton concerné (VOIR: 'class TOUCH_BOUTON_PRESET')
  2049. if(bande_active == SW) {frequence = presetPad1.bt_preset[n_bt].frequence_SW;}
  2050. if(bande_active == FM) {frequence = presetPad1.bt_preset[n_bt].frequence_FM;}
  2051. if(bande_active == AIR) {frequence = presetPad1.bt_preset[n_bt].frequence_AIR;}
  2052. }
  2053.  
  2054. if (mode_affi == SET_F_PRESET)
  2055. {
  2056. if(bande_active == SW)
  2057. {
  2058. presetPad1.bt_preset[n_bt].frequence_SW = frequence; // en RAM
  2059. record_fichier_FRQ_SW_PRST();
  2060. mode_affi = NORMAL;
  2061. delay(100);
  2062. }
  2063. if(bande_active == FM)
  2064. {
  2065. presetPad1.bt_preset[n_bt].frequence_FM = frequence;
  2066. record_fichier_FRQ_FM_PRST();
  2067. mode_affi = NORMAL;
  2068. delay(100);
  2069. }
  2070. if(bande_active == AIR)
  2071. {
  2072. presetPad1.bt_preset[n_bt].frequence_AIR = frequence;
  2073. record_fichier_FRQ_AIR_PRST();
  2074. mode_affi = NORMAL;
  2075. delay(100);
  2076. }
  2077.  
  2078. mode_affi = NORMAL;
  2079. vu_metre_actif = true;
  2080. init_affichages();
  2081. }
  2082.  
  2083. vu_metre_actif = true;
  2084. dessine_VuMetre();
  2085. affiche_frequence(frequence);
  2086. TFT.setTextColor(JAUNE, NOIR);
  2087. TFT.setFreeFont(FF0);
  2088. Tune_Frequence(frequence);
  2089. write_fichier_params();
  2090. }
  2091.  
  2092.  
  2093.  
  2094. uint32_t inc_Frq_in_groupe(GROUPE_FREQUENCES *groupe_Freq, int8_t di) // di = +/-1
  2095. {
  2096. if ((di<-1)||(di>1)) {return 0;}
  2097.  
  2098. uint16_t n_max = groupe_Freq->nb_freq;
  2099.  
  2100. uint16_t n = groupe_Freq->num_F_actuelle;
  2101.  
  2102. if(n_max > 99) {n_max = 99;}
  2103.  
  2104. if (di == 1)
  2105. {
  2106. if (n<n_max-1) { n++; }
  2107. else if (n >= (n_max-1)) {n=0;}
  2108. }
  2109.  
  2110. if (di == -1)
  2111. {
  2112. if (n>=1) { n--; }
  2113. else if (n==0) {n = n_max-1;}
  2114. }
  2115.  
  2116. if(n > 99) {n = 0;}
  2117.  
  2118. groupe_Freq->num_F_actuelle = n;
  2119. uint16_t adr = groupe_Freq->adr_1ere_frq + n;
  2120.  
  2121. uint8_t nb_F = groupe_Freq->nb_freq;
  2122. uint8_t num_1ere_F = groupe_Freq->adr_1ere_frq;
  2123. affiche_numero_frq(String(1 + adr - num_1ere_F), String(nb_F));
  2124.  
  2125. uint32_t valeur_lue = groupe_Freq->G_freq[adr];
  2126. return valeur_lue;
  2127.  
  2128. }
  2129.  
  2130.  
  2131.  
  2132. void test_clic_boutons_plus_moins() // boutons '<' et '>'
  2133. {
  2134. uint16_t c1 = GRIS_6;
  2135. uint16_t c2 = GRIS_3;
  2136.  
  2137. boolean bouton_cliked = false;
  2138.  
  2139. //--------------------------------------------------------------------
  2140. if(mode_s == _FRQ) // on va modifier directement la fréquence
  2141. {
  2142. test_clic_boutons(&bt_plus );
  2143. bt_plus.affiche(c2, 1);
  2144. if (bt_plus.cliked)
  2145. {
  2146. efface_box_entete2();
  2147. presetPad1.deselect_boutons();
  2148. frequence += saut_freq;
  2149. bouton_cliked = true;
  2150. }
  2151.  
  2152. delay(100);
  2153. if (bt_plus.cliked && ((frequence + saut_freq) <= 138000 ))
  2154. {
  2155. Tune_Frequence(frequence);
  2156. }
  2157.  
  2158. bt_plus.cliked = false;
  2159. bt_plus.selected = false;
  2160. bt_plus.affiche(c2, 1); // fugitif
  2161.  
  2162. test_clic_boutons(&bt_moins );
  2163. bt_moins.affiche(c2, 1);
  2164. delay(100);
  2165. if (bt_moins.cliked)
  2166. {
  2167. efface_box_entete2();
  2168. if (frequence > saut_freq) // évite de se retrouver avec une F négative !
  2169. {
  2170. presetPad1.deselect_boutons();
  2171. bouton_cliked = true;
  2172. frequence -= saut_freq;
  2173. }
  2174. }
  2175.  
  2176. if(bt_moins.cliked && frequence > saut_freq) { Tune_Frequence(frequence); }
  2177. bt_moins.cliked = false;
  2178. bt_moins.selected = false;
  2179. bt_moins.affiche(c2, 1); // fugitif
  2180.  
  2181. if(bouton_cliked == true)
  2182. {
  2183. bouton_cliked = false;
  2184. affiche_frequence(frequence);
  2185. }
  2186. }
  2187.  
  2188. //-------------------------------------------------------------------------
  2189.  
  2190. if(mode_s == _MEM) // on va parcourir les fréquences de la liste
  2191. {
  2192. test_clic_boutons(&bt_plus );
  2193. bt_plus.affiche(c2, 1);
  2194. if (bt_plus.cliked)
  2195. {
  2196. bouton_cliked = true;
  2197.  
  2198. //Serial.println("bt_plus.cliked");
  2199.  
  2200. if(groupe_actif == gSW) { frequence = inc_Frq_in_groupe(&groupe_SW, 1); }
  2201. if(groupe_actif == gFM) { frequence = inc_Frq_in_groupe(&groupe_FM, 1); }
  2202. if(groupe_actif == gAIR) { frequence = inc_Frq_in_groupe(&groupe_AIR, 1); }
  2203. if(groupe_actif == gSCN) { frequence = inc_Frq_in_groupe(&groupe_SCAN, 1); }
  2204.  
  2205. Tune_Frequence(frequence);
  2206. if(vu_metre_actif == false)
  2207. {
  2208. quiet = false;
  2209. vu_metre_actif = true;
  2210. dessine_VuMetre();
  2211. affiche_force_signal();
  2212. delay(100);
  2213. }
  2214.  
  2215. }
  2216.  
  2217. bt_plus.cliked = false;
  2218. bt_plus.selected = false;
  2219. bt_plus.affiche(c2, 1); // fugitif
  2220.  
  2221. test_clic_boutons(&bt_moins );
  2222. bt_moins.affiche(c2, 1);
  2223. delay(100);
  2224. if (bt_moins.cliked)
  2225. {
  2226. bouton_cliked = true;
  2227.  
  2228. //-Serial.println("bt_moins.cliked");
  2229.  
  2230. if(groupe_actif == gSW) { frequence = inc_Frq_in_groupe(&groupe_SW, -1); }
  2231. if(groupe_actif == gFM) { frequence = inc_Frq_in_groupe(&groupe_FM, -1); }
  2232. if(groupe_actif == gAIR) { frequence = inc_Frq_in_groupe(&groupe_AIR, -1); }
  2233. if(groupe_actif == gSCN) { frequence = inc_Frq_in_groupe(&groupe_SCAN, -1); }
  2234.  
  2235. Tune_Frequence(frequence);
  2236. if(vu_metre_actif == false)
  2237. {
  2238. quiet = false;
  2239. vu_metre_actif = true;
  2240. dessine_VuMetre();
  2241. affiche_force_signal();
  2242. delay(100);
  2243. }
  2244. }
  2245.  
  2246. bt_moins.cliked = false;
  2247. bt_moins.selected = false;
  2248. bt_moins.affiche(c2, 1); // fugitif
  2249.  
  2250. if(bouton_cliked == true)
  2251. {
  2252. bouton_cliked = false;
  2253. affiche_frequence(frequence);
  2254. }
  2255. }
  2256. }
  2257.  
  2258.  
  2259. void test_clic_bt_RST_affi() // bouton "ok" de la box saisie couleur de fond ecran
  2260. {
  2261. if(mode_affi != COUL) {return;}
  2262.  
  2263. uint16_t c1 = GRIS_6;
  2264. uint16_t c2 = JAUNE;
  2265.  
  2266. test_clic_boutons(&bt_RST_affi );
  2267.  
  2268. if (bt_RST_affi.cliked)
  2269. {
  2270. bt_RST_affi.cliked = false;
  2271. bt_RST_affi.selected = true;
  2272. bt_RST_affi.affiche(VERT, 1);
  2273.  
  2274. init_affichages();
  2275. }
  2276. }
  2277.  
  2278.  
  2279. void test_clic_bt_coul() // bouton au coin en bas à droite
  2280. {
  2281. uint16_t c1 = GRIS_5;
  2282. uint16_t c2 = BLANC;
  2283.  
  2284. uint8_t n;
  2285.  
  2286. test_clic_boutons(&bt_coul );
  2287.  
  2288. if (bt_coul.cliked)
  2289. {
  2290. bt_coul.cliked = false;
  2291. bt_coul.selected = true;
  2292. bt_coul.affiche(VERT, 1);
  2293.  
  2294. vu_metre_actif = false;
  2295.  
  2296. //delay(1000);
  2297. TFT.fillRect(x0_gridPad, y0_gridPad, dx_gridPad, dy_gridPad, NOIR);
  2298.  
  2299. gridPad1.init(x0_gridPad, y0_gridPad);
  2300. gridPad1.set_couleurs();
  2301. gridPad1.affiche();
  2302.  
  2303. boolean ok = false;
  2304.  
  2305. while(! ok)
  2306. {
  2307. if (ts.tirqTouched() && ts.touched())
  2308. {
  2309. get_XY_touch();
  2310. delay(100);
  2311. n = gridPad1.test_clic();
  2312. if (n != 253)
  2313. {
  2314. Serial.println(n);
  2315. if ((n != 32) && (n != 255))
  2316. {
  2317. couleur_fond_ecran = gridPad1.bt_grid[n].couleur;
  2318. write_fichier_params();
  2319. }
  2320. ok = true;
  2321. mode_affi = NORMAL;
  2322. vu_metre_actif = true;
  2323. init_affichages();
  2324. }
  2325. }
  2326. }
  2327. }
  2328. }
  2329.  
  2330.  
  2331.  
  2332. void test_clic_bouton_mute()
  2333. {
  2334. test_clic_boutons(&bt_mute );
  2335.  
  2336. if (bt_mute.cliked)
  2337. {
  2338. bt_mute.affiche(ROUGE, 1);
  2339. delay(10);
  2340.  
  2341. bt_mute.cliked = false;
  2342. if(mute == false) {mute = true;} else {mute = false;}
  2343. Set_Mute(mute); // fonction située dans le fichier 'driverTEF6686_628.h'
  2344. bt_mute.selected = mute;
  2345. bt_mute.affiche(ROUGE, 1);
  2346. if (mute == false) {Tune_Frequence(frequence);}
  2347. delay(10);
  2348. }
  2349. }
  2350.  
  2351.  
  2352. void test_clic_bt_quiet()
  2353. {
  2354. test_clic_boutons(&bt_quiet );
  2355. if (bt_quiet.cliked)
  2356. {
  2357. bt_quiet.cliked = false;
  2358. bt_quiet.selected = true;
  2359. bt_quiet.affiche(VERT, 1);
  2360.  
  2361. if(quiet==false)
  2362. {
  2363. quiet = true; // anti-parasites
  2364. vu_metre_actif = false;
  2365. affi_image_from_SD("/bmp565/montagne170x140b.bmp", x0_vu_metre, y0_vu_metre);
  2366. }
  2367. else
  2368. {
  2369. quiet = false;
  2370. vu_metre_actif = true;
  2371. dessine_VuMetre();
  2372. }
  2373.  
  2374. bt_quiet.cliked = false;
  2375. bt_quiet.selected = quiet;
  2376. bt_quiet.affiche(VERT, 1);
  2377. delay(300);
  2378. }
  2379. }
  2380.  
  2381.  
  2382. void affi_page_info()
  2383. {
  2384. // affiche une page d'information:
  2385.  
  2386. TFT.fillScreen(NOIR);
  2387. TFT.setTextColor(JAUNE, NOIR);
  2388. TFT.setFreeFont(FF1);
  2389. uint16_t y=0;
  2390. TFT.drawString("Radio TEF6686", 0, y); y+=20;
  2391. String s1="version " + version;
  2392. TFT.drawString(s1, 0, y); y+=20;
  2393.  
  2394. TFT.setTextColor(CYAN, NOIR);
  2395. TFT.drawString("Silicium628", 0, y); y+=40;
  2396.  
  2397. TFT.setTextColor(BLANC, NOIR);
  2398. TFT.setFreeFont(FF0);
  2399. TFT.drawString("SW (AM): 1500kHz -- 28MHz", 0, y); y+=20;
  2400. TFT.drawString("bande FM (WFM): 88MHz -- 108MHz", 0, y); y+=20;
  2401. TFT.drawString("bande Aviation Civile: 118MHz -- 137MHz (AM)", 0, y); y+=20;
  2402.  
  2403. }
  2404.  
  2405.  
  2406.  
  2407. void test_clic_bouton_info()
  2408. {
  2409. test_clic_boutons(&bt_info);
  2410. if (bt_info.cliked)
  2411. {
  2412. bt_info.cliked = false;
  2413. bt_info.selected = true;
  2414. bt_info.affiche(VERT, 1);
  2415. delay(10);
  2416.  
  2417. affi_page_info();
  2418.  
  2419. //delay(10);
  2420.  
  2421. attente_clic();
  2422.  
  2423. }
  2424. }
  2425.  
  2426.  
  2427.  
  2428. void affi_message(String L1, String L2, String L3, String L4, String L5)
  2429. {
  2430. TFT.fillScreen(NOIR);
  2431. TFT.setTextColor(BLANC, NOIR);
  2432. TFT.setFreeFont(FF1);
  2433. uint16_t y = 50;
  2434. uint16_t dy = 20;
  2435. TFT.drawString(L1, 10, y); y+=dy;
  2436. TFT.drawString(L2, 10, y); y+=dy;
  2437. TFT.drawString(L3, 10, y); y+=dy;
  2438. TFT.drawString(L4, 10, y); y+=dy;
  2439. TFT.drawString(L5, 10, y);
  2440.  
  2441. delay(10);
  2442. attente_clic();
  2443.  
  2444. }
  2445.  
  2446.  
  2447.  
  2448.  
  2449. void test_clic_bouton_Sleep()
  2450. {
  2451. test_clic_boutons(&bt_sleep );
  2452.  
  2453. if (bt_sleep.cliked)
  2454. {
  2455. bt_sleep.cliked = false;
  2456. bt_sleep.selected = true;
  2457. bt_sleep.affiche(ROUGE, 1);
  2458. delay(10);
  2459.  
  2460. //todo: save en SD
  2461. TFT.fillScreen(NOIR);
  2462. TFT.setTextColor(BLANC, NOIR);
  2463. TFT.setFreeFont(FF1);
  2464. TFT.drawString("Cliquez pour MODE SLEEP", 20, 50);
  2465. TFT.drawString("de l'ESP32", 20, 70);
  2466. TFT.drawString("Eteindre pour quitter", 20, 90);
  2467. TFT.drawString("ce mode SLEEP", 20, 110);
  2468.  
  2469. delay(10);
  2470.  
  2471. attente_clic();
  2472.  
  2473. esp_deep_sleep_start();
  2474. }
  2475. }
  2476.  
  2477.  
  2478. void test_clic_bt_LED()
  2479. {
  2480. test_clic_boutons(&bt_LED );
  2481.  
  2482. if (bt_LED.cliked)
  2483. {
  2484. bt_LED.cliked = false;
  2485. bt_LED.selected = true;
  2486. bt_LED.affiche(ROUGE, 1);
  2487. delay(10);
  2488.  
  2489. TFT.fillScreen(NOIR);
  2490. TFT.setTextColor(BLANC, NOIR);
  2491. TFT.setFreeFont(FF1);
  2492. TFT.drawString("ECRAN NOIR", 20, 50);
  2493. TFT.drawString("Clic pour rallumer", 20, 90);
  2494.  
  2495. for(int n=10; n>0; n--)
  2496. {
  2497. TFT.drawString(String(n) + " ", 20, 110);
  2498. delay(500);
  2499. }
  2500.  
  2501. digitalWrite(GPIO_BL, LOW);
  2502. attente_clic();
  2503. digitalWrite(GPIO_BL, HIGH);
  2504. }
  2505. }
  2506.  
  2507.  
  2508. void test_clic_bt_CAL()
  2509. {
  2510. test_clic_boutons(&bt_cal );
  2511.  
  2512. if (bt_cal.cliked)
  2513. {
  2514. bt_cal.cliked = false;
  2515. bt_cal.selected = true;
  2516. bt_cal.affiche(BLEU, 1);
  2517. delay(10);
  2518.  
  2519. TFT.fillScreen(NOIR);
  2520. TS_calibrate();
  2521. }
  2522. }
  2523.  
  2524.  
  2525.  
  2526. uint16_t read_16(File fp)
  2527. {
  2528. uint8_t low;
  2529. uint16_t high;
  2530. low = fp.read();
  2531. high = fp.read();
  2532. return (high<<8)|low;
  2533. }
  2534.  
  2535.  
  2536. uint32_t read_32(File fp)
  2537. {
  2538. uint16_t low;
  2539. uint32_t high;
  2540. low = read_16(fp);
  2541. high = read_16(fp);
  2542. return (high<<8)|low;
  2543. }
  2544.  
  2545.  
  2546. void affi_image_from_SD(String filename, uint16_t x0, uint16_t y0)
  2547. {
  2548. Serial.println("----------------------------");
  2549. Serial.println("affi_image_from_SD()");
  2550.  
  2551. uint8_t bmp_data[2]={0,0};
  2552. uint8_t a, b;
  2553. uint16_t x=0;
  2554. uint16_t y=0;
  2555. int16_t xmax;
  2556.  
  2557. uint32_t seekOffset;
  2558. uint16_t w, h, row, col;
  2559.  
  2560.  
  2561. File fp = SD.open(filename, "r");
  2562. if (!fp) { Serial.println("ERREUR open file on SD"); return; }
  2563.  
  2564. uint16_t etiq1 = read_16(fp);
  2565.  
  2566. // test bmp_header
  2567. if (etiq1 == 0x4D42)
  2568. {
  2569. read_32(fp);
  2570. read_32(fp);
  2571. seekOffset = read_32(fp);
  2572. Serial.print("seekOffset ="); Serial.println(seekOffset); // 138
  2573.  
  2574. Serial.print("seekOffset= "); Serial.println(seekOffset);
  2575. read_32(fp);
  2576. w = read_32(fp);
  2577. h = read_32(fp);
  2578. Serial.print("w= "); Serial.println(w); // 75
  2579. Serial.print("h= "); Serial.println(h); // 50
  2580. Serial.println(read_16(fp)); // 1
  2581. Serial.println(read_16(fp)); // 16
  2582. Serial.println(read_16(fp)); // 3
  2583. fp.seek(seekOffset);
  2584. }
  2585.  
  2586. y += h;
  2587. xmax = w;
  2588. if(xmax%2 == 1) {xmax +=1;}
  2589.  
  2590. uint16_t padding = (4 - ((w * 2) & 2)) & 2;
  2591. uint8_t lineBuffer[(w*2) + padding];
  2592.  
  2593. for (row = 0; row < h; row++)
  2594. {
  2595. fp.read(lineBuffer, sizeof(lineBuffer));
  2596. uint8_t* bptr = lineBuffer;
  2597. uint16_t* tptr = (uint16_t*)lineBuffer;
  2598.  
  2599. for (uint16_t col = 0; col < w; col++)
  2600. {
  2601. a = *bptr++;
  2602. b = *bptr++;
  2603. *tptr++ = (a <<8 | b);
  2604. }
  2605. TFT.pushImage(x0 + x, y0 + y, w, 1, (uint16_t*)lineBuffer);
  2606. y--;
  2607. }
  2608. fp.close();
  2609. }
  2610.  
  2611. /*
  2612. void ajout_1_freq()
  2613. {
  2614. // AJOUT d'une fréquence en fin d'une liste de fréquences. Travaille directement sur la mémoire SD
  2615. File file = SD.open("/FRQ_FM.txt", FILE_APPEND);
  2616. file.print("<88800>"); // ok ; attention à ne pas oublier les < >
  2617. file.close(); // enregistre CE fichier en mémoire SD, sans toucher aux autres
  2618. delay(100);
  2619. }
  2620. */
  2621.  
  2622.  
  2623. void affi_nuances_de_gris()
  2624. {
  2625. TFT.fillScreen(NOIR);
  2626. uint16_t x, dx, y;
  2627. x=30;
  2628. dx=21;
  2629. y=100;
  2630. TFT.fillRect(x, y, dx, dx, BLANC); x+=dx;
  2631. TFT.fillRect(x, y, dx, dx, GRIS_1); x+=dx;
  2632. TFT.fillRect(x, y, dx, dx, GRIS_2); x+=dx;
  2633. TFT.fillRect(x, y, dx, dx, GRIS_3); x+=dx;
  2634. TFT.fillRect(x, y, dx, dx, GRIS_4); x+=dx;
  2635. TFT.fillRect(x, y, dx, dx, GRIS_5); x+=dx;
  2636. TFT.fillRect(x, y, dx, dx, GRIS_6); x+=dx;
  2637.  
  2638. attente_clic();
  2639.  
  2640. }
  2641.  
  2642.  
  2643. void TS_verif()
  2644. {
  2645. TFT.fillScreen(BLANC);
  2646. TFT.setTextColor(NOIR, BLANC);
  2647. TFT.setFreeFont(FF1);
  2648. TFT.drawString("VERIF CALIBRATION", 10, 50);
  2649.  
  2650. init_1_bouton(1, 280, 20, 20, 20, "X", &bt_close);
  2651. boolean stop = false;
  2652. while(! stop)
  2653. {
  2654. get_XY_touch();
  2655. test_clic_boutons(&bt_close );
  2656. if (bt_close.cliked)
  2657. {
  2658. bt_close.cliked = false;
  2659. stop = true;
  2660. }
  2661. delay(10);
  2662. }
  2663. TFT.fillScreen(NOIR);
  2664. init_affichages();
  2665. }
  2666.  
  2667.  
  2668. void TS_calibrate() // calibrage de l'écran tactile
  2669. {
  2670. uint8_t L = 20;
  2671. boolean ok;
  2672. String s1;
  2673.  
  2674. TFT.setTextColor(BLANC, NOIR);
  2675. TFT.setFreeFont(FF1);
  2676.  
  2677. // traitement point A
  2678. TFT.fillScreen(NOIR);
  2679. TFT.drawString("Cliquez sur le point A", 20, 50);
  2680. delay(300);
  2681. TFT.drawFastVLine(10, 0, L, JAUNE);
  2682. TFT.drawFastHLine(0, 10, L, JAUNE);
  2683. ok = false;
  2684. while (! ok)
  2685. {
  2686. if (ts.tirqTouched() && ts.touched())
  2687. {
  2688. memo_y_touch = y_touch;
  2689. TS_Point p = ts.getPoint();
  2690. s1 = "Ax=" + String(p.x) + " "; TFT.drawString(s1, 50, 100);
  2691. s1 = "Ay=" + String(p.y) + " "; TFT.drawString(s1, 50, 120);
  2692. delay(100);
  2693.  
  2694. if( (p.x<600) && (p.y < 600)) // évite de valider une position irréaliste
  2695. {
  2696. A.x = p.x; // point A : variable globale
  2697. A.y = p.y;
  2698. ok = true;
  2699. }
  2700. }
  2701. }
  2702.  
  2703. // traitement point B
  2704. TFT.fillScreen(NOIR);
  2705. delay(300);
  2706. TFT.drawString("Cliquez sur le point B", 20, 70);
  2707. TFT.drawFastVLine(310, 230-L/2, L, JAUNE);
  2708. TFT.drawFastHLine(310-L/2, 230, L, JAUNE);
  2709. ok = false;
  2710. while (! ok)
  2711. {
  2712. if (ts.tirqTouched() && ts.touched())
  2713. {
  2714. memo_y_touch = y_touch;
  2715. TS_Point p = ts.getPoint();
  2716. s1 = "Bx=" + String(p.x) + " "; TFT.drawString(s1, 50, 150);
  2717. s1 = "By=" + String(p.y) + " "; TFT.drawString(s1, 50, 170);
  2718. delay(100);
  2719.  
  2720. if( (p.x>3600) && (p.y > 3400)) // évite de valider une position irréaliste
  2721. {
  2722. B.x = p.x;
  2723. B.y = p.y;
  2724. ok = true;
  2725. }
  2726. }
  2727. }
  2728. if(SDcardOk==1)
  2729. {
  2730. TFT.fillScreen(NOIR);
  2731. TFT.drawString("Ok", 20, 60);
  2732. TFT.setFreeFont(FF0);
  2733. TFT.drawString("Write fichier params sur la SD", 10, 90);
  2734. write_fichier_params();
  2735. delay(1000);
  2736. }
  2737.  
  2738. TFT.fillScreen(NOIR);
  2739. init_affichages();
  2740.  
  2741. //TS_verif();
  2742. //printTouchToDisplay(); // POUR TESTER LA CALIBRATION DE L'ECRAN TACTILE
  2743. }
  2744.  
  2745.  
  2746. void affi_lst_codes_PI_RDS() // lecture directement sur la SDcard, pas de mise en mémoire RAM
  2747. {
  2748. Serial.println("liste_codes_RDS()");
  2749. int i = 1;
  2750. char buffer1[64];
  2751.  
  2752. //uint32_t valeur_lue;
  2753. uint16_t line_num;
  2754. uint16_t nombre =0;
  2755. uint16_t y=0;
  2756. String s1;
  2757. boolean stop = false;
  2758.  
  2759. TFT.fillScreen(NOIR);
  2760. TFT.setTextColor(BLANC, NOIR);
  2761. TFT.setFreeFont(FF0);
  2762. TFT.drawString("Liste codes PI RDS (en memoire SD)", 0, y);
  2763. y+=30;
  2764.  
  2765. init_1_bouton(1, 280, 20, 50, 15, "stop", &bt_annuler);
  2766. bt_annuler.affiche(BLANC, 1);
  2767.  
  2768. File file1 = SD.open("/RDS_codes_PI.lst", "r");
  2769. while (file1.available() && stop == false )
  2770. {
  2771. int nb_bytes = file1.readBytesUntil('\n', buffer1, sizeof(buffer1));
  2772. buffer1[nb_bytes] = 0; // zéro terminal afin d'obtenir un string
  2773. //if (line_num == i)
  2774. {
  2775. //if(s1 != "") // n'affiche pas les emplacements vides
  2776. {
  2777. nombre++;
  2778. s1 = String(nombre);
  2779. TFT.setTextColor(BLEU, NOIR);
  2780. TFT.drawString(s1, 5, y);
  2781.  
  2782. s1 = buffer1;
  2783. //s1 += " ";
  2784. TFT.setTextColor(BLANC, NOIR);
  2785. TFT.drawString(s1, 30, y);
  2786. y+=10;
  2787.  
  2788. if(y>230)
  2789. {
  2790. delay(500); //300
  2791. if (ts.tirqTouched() && ts.touched())
  2792. {
  2793. stop = true;
  2794. TFT.fillScreen(NOIR);
  2795. TFT.drawString("STOP", 100, 100);
  2796. return;
  2797. }
  2798. else
  2799. {
  2800. delay(300); //200
  2801. TFT.fillScreen(NOIR);
  2802. y=0;
  2803. TFT.drawString("Liste codes PI RDS (en memoire SD)", 0, y);
  2804. bt_annuler.affiche(BLANC, 1);
  2805. y+=30; //30
  2806. }
  2807. }
  2808. }
  2809. }
  2810. i++;
  2811.  
  2812. }
  2813. file1.close();
  2814. attente_clic2();
  2815. }
  2816.  
  2817. void affi_deroulant(String titre, String filename)
  2818. {
  2819. //decale le texte fichier texte vers le haut et le complète en bas comme dans un générique de film
  2820.  
  2821. delay(300);
  2822. uint16_t memo_line_H[1920]; // 1280
  2823. char buffer1[64];
  2824. String s1, s2, s3, s4;
  2825.  
  2826. TFT.setFreeFont(FF0);
  2827. TFT.fillScreen(NOIR);
  2828. TFT.drawRect(1, 0, 319, 165, BLANC);
  2829.  
  2830. TFT.setTextColor(JAUNE, NOIR);
  2831. TFT.drawString(titre, 10, 5);
  2832. TFT.drawFastHLine(1, 14, 318, GRIS_5);
  2833. TFT.setTextColor(BLANC, NOIR);
  2834.  
  2835.  
  2836. init_1_bouton(1, 280, 220, 50, 15, "stop", &bt_annuler);
  2837. bt_annuler.affiche(BLANC, 1);
  2838.  
  2839. File file1 = SD.open(filename, "r");
  2840. int n=0;
  2841. boolean stop = false;
  2842. while (file1.available() && stop == false )
  2843. {
  2844. if(do_capt_screen== true) { do_capt_screen = false; write_TFT_on_SDcard(); }
  2845.  
  2846. for(int y=22; y<160; y+=6) // 4
  2847. {
  2848. TFT.readRect(2, y, 317, 6, memo_line_H); // 4 mémorise la ligne
  2849. TFT.pushRect(2, y-4, 317, 6, memo_line_H); // la recopie un ligne au dessus
  2850. }
  2851. if(n%3 == 0) // 2
  2852. {
  2853. int nb_bytes = file1.readBytesUntil('\n', buffer1, sizeof(buffer1));
  2854. buffer1[nb_bytes] = 0; // zéro terminal afin d'obtenir un string
  2855.  
  2856. s1 = String(n/3); // 2
  2857. s2 = buffer1;
  2858. s3 = s2.substring(0, 4);
  2859. s4 = s2.substring(5);
  2860. //TFT.fillRect(10, 148, 339, 8, NOIR);
  2861. TFT.setTextColor(BLEU, NOIR);
  2862. TFT.drawString(s1, 10, 148);
  2863. TFT.setTextColor(JAUNE, NOIR);
  2864. TFT.drawString(s3, 40, 148);
  2865. TFT.setTextColor(GRIS_3, NOIR);
  2866. TFT.drawString(s4, 70, 148);
  2867.  
  2868. }
  2869. n++;
  2870. if ((ts.tirqTouched() && ts.touched()))
  2871. {
  2872. get_XY_touch();
  2873. test_clic_boutons(&bt_annuler);
  2874. if (bt_annuler.cliked)
  2875. {
  2876. bt_annuler.cliked = false;
  2877. TFT.fillScreen(NOIR);
  2878. x_touch = 0;
  2879. y_touch = 0;
  2880. delay(500);
  2881. stop = true;
  2882. }
  2883. }
  2884. }
  2885. file1.close();
  2886. }
  2887.  
  2888.  
  2889.  
  2890. void test_clic_bouton_TEST()
  2891. {
  2892. test_clic_boutons(&bt_TEST );
  2893. bt_TEST.affiche(ROUGE, 1);
  2894. if (bt_TEST.cliked)
  2895. {
  2896. delay(10);
  2897. Serial.println("-------------------------------");
  2898. Serial.println("bt_TEST.cliked");
  2899. bt_TEST.cliked = false;
  2900. bt_TEST.selected = true;
  2901. bt_TEST.affiche(ROUGE, 1);
  2902.  
  2903. //TFT.fillscreen(GRIS_3); // effface
  2904. //affi_image_from_SD("/7.bmp");
  2905. //ajout_1_freq();
  2906. /*
  2907. uint16_t dx= 40;
  2908. uint16_t dy =30;
  2909. uint16_t memo_line_H[dx*dy];
  2910. TFT.readRect(20, 20 , dx, dy, memo_line_H);
  2911. TFT.pushRect(100, 100, dx, dy, memo_line_H);
  2912. */
  2913. /*
  2914. String s1;
  2915. for (int n=0; n<10; n++)
  2916. {
  2917. s1 = read_line_params(n);
  2918. Serial.println(s1);
  2919. }
  2920. */
  2921. //TS_calibrate();
  2922.  
  2923. //affi_nuances_de_gris();
  2924.  
  2925. //TFT.fillScreen(NOIR); // effface
  2926. //draw_AEC(0, 100, 320, 1);
  2927.  
  2928. //affi_lst_codes_PI_RDS();
  2929. //TFT.fillScreen(GRIS_3); // effface
  2930.  
  2931. //affi_deroulant("Liste codes PI RDS", "/RDS_codes_PI.lst");
  2932.  
  2933. //TFT.drawString("Lecture faite", 10, 90);
  2934. //attente_clic2();
  2935.  
  2936. bt_TEST.cliked = false;
  2937. bt_TEST.selected = false;
  2938. bt_TEST.affiche(ROUGE, 1);
  2939.  
  2940. init_affichages();
  2941. Serial.println("-------------------------------");
  2942. }
  2943. }
  2944.  
  2945.  
  2946. void test_clic_Bt_reset()
  2947. {
  2948. test_clic_boutons(&bt_reset );
  2949. bt_reset.affiche(NOIR, 1);
  2950. if (bt_reset.cliked)
  2951. {
  2952. delay(10);
  2953. bt_reset.cliked = false;
  2954. bt_reset.selected = true;
  2955. bt_reset.affiche(VERT, 1);
  2956.  
  2957. delay(10);
  2958. bt_reset.selected = false;
  2959. bt_reset.affiche(VERT, 1);
  2960.  
  2961. setup();
  2962. }
  2963. }
  2964.  
  2965.  
  2966. void test_clic_bt_LEV()
  2967. {
  2968. test_clic_boutons(&bt_LEV);
  2969. if (bt_LEV.cliked)
  2970. {
  2971. bt_LEV.cliked = false;
  2972. bt_LEV.selected = true; bt_LEV.affiche(VERT, 1);
  2973. bt_SNR.selected = false; bt_SNR.affiche(VERT, 1);
  2974. mode_seuil = LEV;
  2975. }
  2976. }
  2977.  
  2978.  
  2979. void test_clic_bt_SNR()
  2980. {
  2981. test_clic_boutons(&bt_SNR);
  2982. if (bt_SNR.cliked)
  2983. {
  2984. bt_SNR.cliked = false;
  2985. bt_SNR.selected = true; bt_SNR.affiche(VERT, 1);
  2986. bt_LEV.selected = false; bt_LEV.affiche(VERT, 1);
  2987. mode_seuil = SNR;
  2988. }
  2989. }
  2990.  
  2991.  
  2992.  
  2993. void test_clic_bt_stop_scan()
  2994. {
  2995. test_clic_boutons(&bt_stop_scan);
  2996. if (bt_stop_scan.cliked)
  2997. {
  2998. Serial.println("STOP scan");
  2999. bt_stop_scan.affiche(BLANC, 1);
  3000. mode_affi = NORMAL;
  3001. bt_stop_scan.cliked = false;
  3002. bt_stop_scan.affiche(BLANC, 1);
  3003. }
  3004. }
  3005.  
  3006.  
  3007. void test_clic_bt_annuler()
  3008. {
  3009. test_clic_boutons(&bt_annuler);
  3010. if (bt_annuler.cliked)
  3011. {
  3012. bt_annuler.cliked = false;
  3013. bt_annuler.affiche(BLANC, 1);
  3014.  
  3015. mode_affi = NORMAL; // ce qui repasse les boutons 'preset' en mode sélection et empêche l'écriture en SD
  3016. vu_metre_actif = true;
  3017. init_affichages();
  3018. }
  3019. }
  3020.  
  3021.  
  3022. /*
  3023. MODES DE SCAN
  3024. 1-scan_frq() : tt fréquences d'une bande (ex: FM). Mise en mémoire temporaire (en RAM) des stations actives.
  3025. 2-scan_mem_AIR() : cannaux occupés (pour la bande aviation) - pas de mise en mémoire mais stop si message reçu
  3026. puis reprise auto du scan à la fin du message.
  3027. */
  3028.  
  3029. //enum MODE_SEUIL {LEV, SNR}; // level ou signal/bruit
  3030. //MODE_SEUIL mode_seuil = LEV;
  3031.  
  3032.  
  3033.  
  3034.  
  3035. void scan_mem_AIR()
  3036. {
  3037. // le scan de la bande aviation civile nécessite un convertisseur de fréquence 110MHz en entrée antenne
  3038. // le scan_AIR ne teste pas toutes les fréquences de la gamme mais seulement celles prédéfinies
  3039. // dans le fichier 'FRQ_AIR.txt' (sur la SDcard)
  3040. // ces fréquences peuvent avoir été écrites par le programme (touche 'Write') ou manuellement
  3041. // avec un éditeur de texte en respectant la syntaxe, par exemple <123500>
  3042.  
  3043. Serial.println("scan_mem_AIR()");
  3044. bande_active = AIR;
  3045. affi_AB = false;
  3046.  
  3047. efface_box_GROUPE();
  3048. TFT.fillScreen(couleur_fond_ecran);
  3049.  
  3050. uint16_t couleur_ciel = 10739;
  3051.  
  3052. TFT.fillRect(x0_box_SCAN, y0_box_SCAN, dx_box_SCAN, dy_box_SCAN, GRIS_6);
  3053. affi_image_from_SD("/bmp565/avion1.bmp", 1, 80);
  3054.  
  3055. affiche_box_scan(dy_box_SCAN);
  3056.  
  3057. TFT.setFreeFont(FF0);
  3058. TFT.setTextColor(JAUNE, NOIR);
  3059.  
  3060. TFT.fillRect(2, 2, 42, 80, couleur_ciel); // efface
  3061.  
  3062. affi_image_from_SD("/bmp565/avion3.bmp", 1, 15);
  3063. affi_image_from_SD("/bmp565/PFD42x28.bmp", 1, 40);
  3064.  
  3065. String si;
  3066. uint16_t y;
  3067. uint16_t xi, yi;
  3068. int16_t dy, memo_dy;
  3069.  
  3070. int16_t attente =0;
  3071. int16_t signal_i;
  3072. uint16_t base = y0_box_SCAN + dy_box_SCAN -5; // bas du graphique
  3073. uint16_t memo_line_H[320];
  3074.  
  3075. mode_seuil = SNR; //2 types de détection possibles: LEV(level) et SNR(signal-to-noise ratio = signal/bruit)
  3076. bt_SNR.selected = true; bt_SNR.affiche(VERT, 1);
  3077. bt_LEV.selected = false; bt_LEV.affiche(VERT, 1);
  3078.  
  3079. TFT.setFreeFont(FM9);
  3080. TFT.setTextColor(JAUNE, NOIR);
  3081.  
  3082. frequence = 124075;
  3083. Tune_Frequence(frequence);
  3084. affiche_frequence(frequence);
  3085. memo_dy = 0;
  3086.  
  3087. TFT.readRect(0, base - seuil , 319, 1, memo_line_H); // mémorise la ligne avant de tracer
  3088. TFT.drawFastHLine(0, base -seuil, 319, JAUNE); // seuil (trait horizontal sur toute la largeur)
  3089.  
  3090. while(mode_affi == SCAN_M)
  3091. {
  3092. y = y0_box_SCAN + 5;
  3093. uint8_t module;
  3094. if(bande_active == FM) {module = 32;} else {module = 33;}
  3095. Get_Quality( module, &status, &level, &usn, &wam, &offset, &bandwidth, &mod, &snr );
  3096.  
  3097. si = String(level);
  3098. TFT.drawString("level", x0_box_SCAN +25 , y);
  3099. TFT.drawString(si+" ", x0_box_SCAN +65 , y);
  3100. y+=15;
  3101.  
  3102. si = String(snr);
  3103. TFT.drawString("snr", x0_box_SCAN +25 , y);
  3104. TFT.drawString(si+" ", x0_box_SCAN +65 , y);
  3105. y+=20;
  3106.  
  3107. if (mode_seuil == LEV) { signal_i = level; } // attention! level peut être négatif (échelle log)
  3108. if (mode_seuil == SNR) { signal_i= 16 * snr; }
  3109.  
  3110. dy = signal_i/10;
  3111. if(dy<0) {dy=0;}
  3112. dy+=2;
  3113.  
  3114.  
  3115. // petites barres verticales
  3116. xi = (frequence - 120000)/50;
  3117. // xi(120MHz) = 0 px;
  3118. // xi(136MHz) = (136000 - 120000) /50 = 320 px
  3119.  
  3120. //TFT.drawFastVLine(xi, base-50, 50, couleur_ciel); // 95 efface
  3121. uint16_t c0 = GRIS_3;
  3122. if(signal_i > seuil*10){c0 = JAUNE;}
  3123. TFT.drawFastVLine(xi, base -dy, dy, c0);
  3124.  
  3125.  
  3126. if(signal_i > seuil*10)
  3127. {
  3128. TFT.fillRect(x0_box_SCAN +100, y0_box_SCAN + 20, 20, 20, VERT); // carré coloré
  3129. memo_dy = dy;
  3130. attente = 2;
  3131. }
  3132. else attente --;
  3133.  
  3134. if (attente <=0)
  3135. {
  3136. TFT.drawFastVLine(xi, base -memo_dy, memo_dy, GRIS_3);
  3137. memo_dy = 0;
  3138. TFT.fillRect(x0_box_SCAN +100, y0_box_SCAN + 20, 20, 20, GRIS_5); // carré coloré
  3139. frequence = inc_Frq_in_groupe(&groupe_AIR, 1);
  3140. Tune_Frequence(frequence);
  3141. affiche_frequence(frequence);
  3142. TFT.setFreeFont(FF0);
  3143. TFT.setTextColor(BLANC, NOIR);
  3144. TFT.drawString("120MHz", x0_box_SCAN +5 , base-10);
  3145. TFT.drawString("136", x0_box_SCAN +dx_box_SCAN -22, base-10);
  3146.  
  3147. attente =0;
  3148. }
  3149.  
  3150. delay(50); // ne pas réduire, temps nécessaire pour accrocher la fréquence
  3151.  
  3152. if (ts.tirqTouched() && ts.touched())
  3153. {
  3154. get_XY_touch();
  3155. test_clic_bt_stop_scan();
  3156.  
  3157. test_clic_boutons(&bt_seuil_plus);
  3158. if (bt_seuil_plus.cliked)
  3159. {
  3160. bt_seuil_plus.cliked = false;
  3161. TFT.pushRect(0, base - memo_seuil, 319, 1, memo_line_H); // efface avec l'image enregistrée
  3162. memo_seuil = seuil;
  3163. seuil += 1;
  3164. if (seuil > 120) {seuil = 120;}
  3165. TFT.readRect(0, base - seuil , 319, 1, memo_line_H); // mémorise la ligne avant de tracer
  3166. TFT.drawFastHLine(0, base -seuil, 319, JAUNE); // seuil (trait horizontal sur toute la largeur)
  3167. TFT.setFreeFont(FF0); TFT.setTextColor(JAUNE, NOIR);
  3168. si = "seuil:" + String(seuil*10); TFT.drawString(si+" ", x0_box_SCAN +190 , y0_box_SCAN +15);
  3169. }
  3170.  
  3171. test_clic_boutons(&bt_seuil_moins);
  3172. if (bt_seuil_moins.cliked)
  3173. {
  3174. bt_seuil_moins.cliked = false;
  3175. TFT.pushRect(0, base - memo_seuil, 319, 1, memo_line_H); // efface avec l'image enregistrée
  3176. memo_seuil = seuil;
  3177. seuil -= 1;
  3178. if (seuil < 5) {seuil = 5;}
  3179. TFT.readRect(0, base - seuil , 319, 1, memo_line_H); // mémorise la ligne avant de tracer
  3180. TFT.drawFastHLine(0, base -seuil, 319, JAUNE); // seuil (trait horizontal sur toute la largeur)
  3181. TFT.setFreeFont(FF0); TFT.setTextColor(JAUNE, NOIR);
  3182. si = "seuil:" + String(seuil*10); TFT.drawString(si+" ", x0_box_SCAN +190 , y0_box_SCAN +15);
  3183. }
  3184.  
  3185. test_clic_bt_LEV();
  3186. test_clic_bt_SNR();
  3187.  
  3188. test_clic_boutons(&bt_stop_scan);
  3189. }
  3190. }
  3191.  
  3192. //delay(1000);
  3193.  
  3194. mode_s = _MEM;
  3195. mode_affi = NORMAL;
  3196. bande_active = FM;
  3197. bt_mode_MEM.selected = true; bt_mode_MEM.affiche(VERT, 2);
  3198. bt_mode_FRQ.selected = false; bt_mode_FRQ.affiche(VERT, 2);
  3199.  
  3200. //boutons_preset_set_frequences();
  3201. init_affichages();
  3202. frequence = 89400;
  3203. Tune_Frequence(frequence);
  3204. affiche_frequence(frequence);
  3205.  
  3206. bt_FM.selected = true; bt_FM.affiche(VERT, 1);
  3207. bt_AIR.selected = false; bt_AIR.affiche(VERT, 1);
  3208. }
  3209.  
  3210.  
  3211. void affi_passes(String band_name, int num_passe, int nb_passes)
  3212. {
  3213. TFT.setTextColor(NOIR, BLANC); TFT.setFreeFont(FMB9);
  3214. String s1 = "SW bande" + band_name;
  3215. s1 += "_";
  3216. TFT.drawString(s1, 2, 14);
  3217. s1 = String(num_passe);
  3218. s1 += "/";
  3219. s1 += String(nb_passes);
  3220. TFT.drawString(s1, 284, 14); // en haut à droite
  3221. TFT.drawString(s1, 10, 200); // en bas à gauche
  3222. }
  3223.  
  3224.  
  3225. void scan_frq(uint32_t freq_iA, uint32_t freq_iB, String band_name) // toutes les fréquences de la bande, incrémental, saut_freq = constant
  3226. {
  3227. Serial.println("scan_frq()");
  3228. Serial.print("freq_iA = "); Serial.println(freq_iA);
  3229. Serial.print("freq_iB = "); Serial.println(freq_iB);
  3230.  
  3231. if(bande_active == SCN) {bande_active = FM;}
  3232.  
  3233. String si;
  3234. String s1;
  3235. String sA, sB;
  3236. float xi=0;
  3237. uint32_t xi32;
  3238. uint16_t y;
  3239. int16_t dy;
  3240. uint16_t yi;
  3241. uint32_t freq;
  3242. uint32_t largeur_bande = freq_iB - freq_iA;
  3243. uint16_t nb_F;
  3244. int n_max;
  3245. int nb_passes = 1;
  3246. int num_passe = 1;
  3247.  
  3248. int16_t signal_i;
  3249. uint16_t base = y0_box_SCAN + dy_box_SCAN -5; // bas du graphique
  3250. uint16_t memo_line_H[320];
  3251.  
  3252. uint16_t decal_x;
  3253. uint16_t decal_y;
  3254.  
  3255.  
  3256. TFT.fillScreen(couleur_fond_ecran);
  3257. TFT.fillRect(x0_box_SCAN, y0_box_SCAN, dx_box_SCAN, dy_box_SCAN, NOIR);
  3258. memo_freq = freq_iA; // variables globales
  3259.  
  3260. mode_seuil = SNR; //2 types de détection possibles: LEV(level) et SNR(signal-to-noise ratio = signal/bruit)
  3261. bt_SNR.selected = true; bt_SNR.affiche(VERT, 1);
  3262. bt_LEV.selected = false; bt_LEV.affiche(VERT, 1);
  3263.  
  3264. groupe_SCAN.RAZ();
  3265. efface_box_GROUPE();
  3266.  
  3267. //TFT.setFreeFont(FM9);
  3268. TFT.setTextColor(JAUNE, NOIR);
  3269. TFT.setFreeFont(FF0);
  3270.  
  3271. freq = freq_iA;
  3272.  
  3273. uint8_t module;
  3274. if(bande_active == FM)
  3275. {
  3276. saut_freq = 100; // kHz
  3277. module = 32;
  3278. n_max = 190;
  3279. nb_passes = 1;
  3280. }
  3281. else
  3282. {
  3283. saut_freq = 5; // kHz
  3284. module = 33;
  3285. n_max = largeur_bande / saut_freq;
  3286. nb_passes = 1 + n_max / 200;
  3287. if(nb_passes < 1) {nb_passes=1;}
  3288. }
  3289.  
  3290. y = y0_box_SCAN + 5;
  3291. decal_x=0;
  3292. decal_y=0;
  3293. nb_F=0;
  3294.  
  3295. // sA = String(freq);
  3296. // sB = String(freq + n_max * saut_freq);
  3297. // TFT.drawString(sA, x0_box_SCAN +5 , base-5);
  3298. // TFT.drawString(sB, x0_box_SCAN +dx_box_SCAN -40, base-5);
  3299.  
  3300. sA = String(freq_iA + (num_passe-1) * 200 * saut_freq);
  3301. sB = String(freq_iA + num_passe * 200 * saut_freq);
  3302. TFT.setTextColor(JAUNE, NOIR);
  3303. TFT.setFreeFont(FF0);
  3304. TFT.drawString(sA, x0_box_SCAN +5 , base-5);
  3305. TFT.drawString(sB, x0_box_SCAN +dx_box_SCAN -40, base-5);
  3306.  
  3307. TFT.readRect(0, base - seuil , 319, 1, memo_line_H); // mémorise la ligne avant de tracer
  3308. TFT.drawFastHLine(0, base -seuil, 319, VIOLET); // seuil (trait horizontal sur toute la largeur)
  3309.  
  3310. TFT.setTextColor(VIOLET, NOIR);
  3311. TFT.setFreeFont(FF0);
  3312. si = "seuil:" + String(seuil*10); TFT.drawString(si+" ", x0_box_SCAN +190 , y0_box_SCAN +15);
  3313.  
  3314. boolean scan_complet;
  3315. boolean rescan = false;
  3316.  
  3317. do
  3318. {
  3319. groupe_SCAN.RAZ();
  3320. nb_F = 0;
  3321. affiche_box_scan(dy_box_SCAN);
  3322. uint32_t freq_min = freq;
  3323.  
  3324. if(bande_active == SW)
  3325. {
  3326. affi_passes(band_name, num_passe, nb_passes);
  3327. s1 = "[" + String(freq_iA) + "-" + String(freq_iB) + "]";
  3328. TFT.setTextColor(BLANC, couleur_fond_ecran); TFT.setFreeFont(FF1);
  3329. TFT.drawString(s1, 145, 14);
  3330. }
  3331. //......................................................................
  3332. int n = n_max;
  3333.  
  3334. while((n>0) && !(bande_interdite1 || bande_interdite2))
  3335. {
  3336. if (ts.tirqTouched() && ts.touched()) // écran tactile
  3337. {
  3338. get_XY_touch();
  3339. test_clic_boutons(&bt_stop_scan);
  3340. if (bt_stop_scan.cliked)
  3341. {
  3342. //bt_stop_scan.cliked = false;
  3343. n=0; // force la sortie de la boucle while()
  3344. }
  3345. }
  3346.  
  3347. freq += saut_freq;
  3348.  
  3349. affiche_frequence(freq);
  3350.  
  3351. if( (freq + saut_freq) <= 138000 )
  3352. {
  3353. Tune_Frequence(freq);
  3354. delay(15);
  3355. }
  3356.  
  3357. if(bande_active == FM) {module = 32;} else {module = 33;}
  3358. Get_Quality( module, &status, &level, &usn, &wam, &offset, &bandwidth, &mod, &snr );
  3359.  
  3360. delay(50);
  3361. //if(bande_active == SW) {xi += 1.6;}
  3362. //if(bande_active == FM) {xi += 2;}
  3363. xi += 1.6;
  3364.  
  3365. if (mode_seuil == LEV) { signal_i = level; } // attention! level peut être négatif (échelle log)
  3366. if (mode_seuil == SNR) { signal_i= 16 * snr; }
  3367.  
  3368. dy = signal_i/10;
  3369. dy-=5;
  3370. if(dy<1) {dy=1;} // 1 et pas 0 afin d'afficher au moins 1 point en cas de signal très faible
  3371.  
  3372. Serial.print("dy"); Serial.println(dy);
  3373.  
  3374. //uint16_t c1;
  3375. xi32 = x0_box_SCAN + (uint32_t)xi;
  3376.  
  3377. // BARRES VERTICALES ----------------------------
  3378.  
  3379. if (xi32 < 318) // limite d'affichage à droite
  3380. {
  3381. // on va les tracer les barres verticales point par point afin de pouvoir les coloriser
  3382. int a = base;
  3383. int b = a - dy;
  3384.  
  3385. uint16_t x, y1, j, L;
  3386. uint16_t couleur_i;
  3387. L = dy; // longueur (verticale) de la barre
  3388. for (int16_t i=0; i<L; i++)
  3389. {
  3390. float f = 10.0 * i; // pour balayer toute l'échelle des 470 couleurs disponibles
  3391. j=uint16_t(f);
  3392. if(j>460){j=460;}
  3393. couleur_i = couleurs_aec[2*j] | couleurs_aec[2*j+1]<<8; //couleurs arc-en-ciel, voir fichier Couleurs_AEC.h
  3394. y1=225-i;
  3395. TFT.drawPixel(xi32, y1, couleur_i);
  3396. }
  3397. }
  3398. else // on arrive en bout d'affichage à droite, on passe à la plage suivante si necessaire...
  3399. {
  3400. TFT.fillRect(x0_box_SCAN, y0_box_SCAN, dx_box_SCAN, dy_box_SCAN, NOIR);
  3401. affiche_box_scan(dy_box_SCAN); // efface le tracé et re-dessine les boutons dans la boite
  3402. TFT.readRect(0, base - seuil , 319, 1, memo_line_H); // mémorise la ligne avant de tracer
  3403. TFT.drawFastHLine(0, base -seuil, 319, VIOLET); // seuil (trait horizontal sur toute la largeur)
  3404. si = "seuil:" + String(seuil*10); TFT.drawString(si+" ", x0_box_SCAN +190 , y0_box_SCAN +15);
  3405. xi = 0;
  3406. num_passe ++;
  3407. if(bande_active == SW)
  3408. {
  3409. affi_passes(band_name, num_passe, nb_passes);
  3410. sA = String(freq_iA + (num_passe-1) * 200 * saut_freq);
  3411. sB = String(freq_iA + num_passe * 200 * saut_freq);
  3412. TFT.setTextColor(JAUNE, NOIR);
  3413. TFT.setFreeFont(FF0);
  3414. TFT.drawString(sA, x0_box_SCAN +5 , base-5);
  3415. TFT.drawString(sB, x0_box_SCAN +dx_box_SCAN -40, base-5);
  3416. }
  3417. }
  3418.  
  3419.  
  3420. // --------------------------------------------------
  3421. if(signal_i > seuil*10) // DETECTION
  3422. {
  3423. if (decal_y > 5) // concerne l'affichage des textes (fréquences trouvées)
  3424. {
  3425. decal_y = 0;
  3426. decal_x ++;
  3427. }
  3428.  
  3429. if((nb_F % 25) == 0) // limite le nb de freq affichées simultanément à 25
  3430. {
  3431. affiche_box_scan(dy_box_SCAN/2);
  3432. decal_x = 0;
  3433. decal_y = 0;
  3434. }
  3435.  
  3436. s1 = String(freq);
  3437. TFT.setTextColor(BLANC, NOIR);
  3438. TFT.drawString(s1, x0_box_SCAN + 20 + 45*decal_x, y0_box_SCAN + 9*decal_y); // affiche FREQUENCE
  3439. nb_F++;
  3440.  
  3441. TFT.setFreeFont(FF0);
  3442. TFT.setTextColor(VERT, NOIR);
  3443. s1 = String(nb_F);
  3444. TFT.drawString(s1, x0_box_SCAN +3 , y0_box_SCAN + 45); // nb freq
  3445. TFT.setFreeFont(FF0);
  3446.  
  3447. groupe_SCAN.add_frq(freq); // AJOUTE la fréquence trouvée au groupe spécial 'groupe_SCAN'
  3448. decal_y ++;
  3449.  
  3450. if(groupe_SCAN.nb_freq >= 100) // groupe plein (en RAM)
  3451. {
  3452. s1 = String(freq);
  3453. TFT.setTextColor(ROUGE, NOIR);
  3454. TFT.drawString(s1+" groupe SC plein", x0_box_SCAN +80 , y0_box_SCAN + 60);
  3455. TFT.setTextColor(BLANC, NOIR);
  3456. n=0;
  3457. }
  3458. }
  3459. n--;
  3460. //if (n<10) {scan_complet = true;}
  3461. delay(10); // ne pas réduire, temps nécessaire pour accrocher la fréquence
  3462. //delay(300); // pour balayage lent
  3463.  
  3464. if (ts.tirqTouched() && ts.touched()) // écran tactile
  3465. {
  3466. get_XY_touch();
  3467.  
  3468. test_clic_boutons(&bt_seuil_plus);
  3469. if (bt_seuil_plus.cliked)
  3470. {
  3471. bt_seuil_plus.cliked = false;
  3472. TFT.pushRect(0, base - memo_seuil, 319, 1, memo_line_H); // efface avec l'image enregistrée
  3473. memo_seuil = seuil;
  3474. seuil += 1;
  3475. if (seuil > 120) {seuil = 120;}
  3476. TFT.readRect(0, base - seuil , 319, 1, memo_line_H); // mémorise la ligne avant de tracer
  3477. TFT.drawFastHLine(0, base -seuil, 319, VIOLET); // seuil (trait horizontal sur toute la largeur)
  3478. TFT.setFreeFont(FF0); TFT.setTextColor(VIOLET, NOIR);
  3479. si = "seuil:" + String(seuil*10); TFT.drawString(si+" ", x0_box_SCAN +190 , y0_box_SCAN +15);
  3480. }
  3481.  
  3482. test_clic_boutons(&bt_seuil_moins);
  3483. if (bt_seuil_moins.cliked)
  3484. {
  3485. bt_seuil_moins.cliked = false;
  3486. TFT.pushRect(0, base - memo_seuil, 319, 1, memo_line_H); // efface avec l'image enregistrée
  3487. memo_seuil = seuil;
  3488. seuil -= 1;
  3489. if (seuil < 5) {seuil = 5;}
  3490. TFT.readRect(0, base - seuil , 319, 1, memo_line_H); // mémorise la ligne avant de tracer
  3491. TFT.drawFastHLine(0, base -seuil, 319, VIOLET); // seuil (trait horizontal sur toute la largeur)
  3492. TFT.setFreeFont(FF0); TFT.setTextColor(VIOLET, NOIR);
  3493. si = "seuil:" + String(seuil*10); TFT.drawString(si+" ", x0_box_SCAN +190 , y0_box_SCAN +15);
  3494. }
  3495.  
  3496. // modes de détection :
  3497. test_clic_bt_LEV(); // mode Level
  3498. test_clic_bt_SNR(); // mode Signal / bruit
  3499.  
  3500. test_clic_boutons(&bt_re_scan);
  3501. if (bt_re_scan.cliked)
  3502. {
  3503. bt_re_scan.cliked = false;
  3504. TFT.fillRect(x0_box_SCAN, y0_box_SCAN, dx_box_SCAN, dy_box_SCAN, NOIR);
  3505. affiche_box_scan(dy_box_SCAN); // efface le tracé et re-dessine les boutons dans la boite
  3506. freq = memo_freq; // on repart de ma même frequence
  3507. n = n_max;
  3508. xi =0; // départ tracé à gauche
  3509. decal_x=0; // textes fréquences trouvées
  3510. decal_y=0;
  3511. nb_F=0;
  3512. TFT.readRect(0, base - seuil , 319, 1, memo_line_H); // mémorise la ligne avant de tracer
  3513. TFT.drawFastHLine(0, base -seuil, 319, VIOLET); // seuil (trait horizontal sur toute la largeur)
  3514. si = "seuil:" + String(seuil*10); TFT.drawString(si+" ", x0_box_SCAN +190 , y0_box_SCAN +15);
  3515. }
  3516. }
  3517. } // fin de la boucle while()
  3518.  
  3519. //.......................................................................
  3520.  
  3521.  
  3522. if(nb_passes == 1) // because la fonction d'écoute au stylet incorrecte si spectre partiel
  3523. {
  3524. TFT.setTextColor(CYAN, NOIR);
  3525. TFT.setFreeFont(FF0);
  3526. TFT.drawString("On peut ecouter les freq", 10, 145);
  3527. TFT.drawString("en deplacant le stylet sur le spectre", 10, 155);
  3528. }
  3529.  
  3530. boolean stop = false;
  3531. while (! stop) // attend une action en fin de scan (par ex: clic sur bouton 'stop_scan' [x]) ou [re_scan]
  3532. {
  3533. if(do_capt_screen== true) { do_capt_screen = false; write_TFT_on_SDcard(); }
  3534.  
  3535. if (ts.tirqTouched() && ts.touched())
  3536. {
  3537. get_XY_touch();
  3538.  
  3539. if((x_touch != memo_x_touch) && (y_touch > 170)) // écoute de la fréquence pointée avec le stylet
  3540. {
  3541. TFT.drawFastVLine(memo_x_touch, base, 4, NOIR); // efface
  3542. TFT.drawFastVLine(x_touch, base, 4, BLANC);
  3543.  
  3544. TFT.drawFastVLine(memo_x_touch, base-50, 4, NOIR); // efface
  3545. TFT.drawFastVLine(x_touch, base-50, 4, BLANC);
  3546.  
  3547. memo_x_touch = x_touch ;
  3548.  
  3549. float dF = (x_touch - x0_box_SCAN) * saut_freq / 1.6;
  3550. uint32_t F1 = freq_min + uint32_t(dF);
  3551. freq = F1;
  3552. affiche_frequence(freq);
  3553. Tune_Frequence(freq);
  3554. String sF1 = String(F1);
  3555. TFT.drawString(sF1, 200, 100);
  3556. }
  3557.  
  3558. test_clic_boutons(&bt_re_scan);
  3559. if (bt_re_scan.cliked)
  3560. {
  3561. bt_re_scan.cliked = false;
  3562. freq = memo_freq; // on repart de ma même frequence
  3563. xi=0;
  3564. xi32 = x0_box_SCAN + (uint32_t)xi;
  3565. stop =true;
  3566. rescan = true; //pas d'appel RECURSIF de la fonction. Trop de pb !!
  3567. }
  3568.  
  3569. test_clic_boutons(&bt_scan_suivant);
  3570. if (bt_scan_suivant.cliked)
  3571. {
  3572. bt_re_scan.cliked = false;
  3573. TFT.fillRect(x0_box_SCAN, y0_box_SCAN, dx_box_SCAN, dy_box_SCAN, NOIR);
  3574. affiche_box_scan(dy_box_SCAN); // efface le tracé et re-dessine les boutons dans la boite
  3575.  
  3576. n = n_max;
  3577. xi =0; // départ tracé à gauche
  3578. decal_x=0; // textes fréquences trouvées
  3579. decal_y=0;
  3580. nb_F=0;
  3581. memo_freq = freq;
  3582. stop =true; // sortira de la boucle while()
  3583. rescan = true; // bouclera dans la boucle do()
  3584. }
  3585.  
  3586. test_clic_boutons(&bt_stop_scan);
  3587. if (bt_stop_scan.cliked)
  3588. {
  3589. n=0;
  3590. stop =true; // sortira de la boucle while()
  3591. rescan = false; // ne rebouclera PAS dans la boucle do()
  3592. }
  3593. }
  3594. }
  3595.  
  3596.  
  3597. } while (rescan == true); // Fin de la boucle do()
  3598.  
  3599. groupe_SCAN.bloc_to_serial(); // pour test avec moniteur série (CuteCom par exemple)
  3600. mode_affi = NORMAL;
  3601. mode_s = _MEM;
  3602. bt_mode_FRQ.selected = false; bt_mode_FRQ.affiche(VERT, 2);
  3603. bt_mode_MEM.selected = true; bt_mode_MEM.affiche(VERT, 2);
  3604.  
  3605. write_fichier_params();
  3606.  
  3607. if (bt_stop_scan.cliked == false)
  3608. {
  3609. // si on est sorti de la boucle normalement, (pas par clic sur bouton stop), on passe ici
  3610. uint16_t ya = 20;
  3611. uint8_t dya = 15;
  3612. TFT.fillScreen(NOIR);
  3613. TFT.setTextColor(BLANC, NOIR);
  3614. TFT.setFreeFont(FF0);
  3615. TFT.drawString("Les Freq. detectees sont memo en RAM", 5, ya); ya += dya;
  3616. TFT.drawString("accessibles par le bouton 'SC'", 5, ya); ya += dya;
  3617. TFT.drawString("On peut les enregistrer en SD", 5, ya); ya += dya;
  3618. TFT.drawString("une a une avec le bouton 'Write'", 5, ya); ya += dya;
  3619. TFT.drawString("sinon -> perdues si stop radio", 5, ya); ya += dya;
  3620. attente_clic();
  3621. delay(300);
  3622. }
  3623. }
  3624.  
  3625.  
  3626. void choix_type_scan()
  3627. {
  3628. TFT.fillScreen(NOIR);
  3629. TFT.setTextColor(BLANC, NOIR);
  3630. TFT.setFreeFont(FF1);
  3631. TFT.drawString("CHOIX TYPE SCAN", 50, 5);
  3632.  
  3633. init_1_bouton(2, 10, 70, 85, 20, "scan SW", &bt_scan_SW);
  3634. init_1_bouton(2, 120, 70, 85, 20, "scan FM", &bt_scan_FM);
  3635. init_1_bouton(2, 60, 100, 95, 20, "scan AIR", &bt_scan_air);
  3636.  
  3637. boolean ok1 = false;
  3638. while (! ok1)
  3639. {
  3640. if(do_capt_screen== true) { do_capt_screen = false; write_TFT_on_SDcard(); }
  3641.  
  3642. if ((ts.tirqTouched() && ts.touched()))
  3643. {
  3644. get_XY_touch();
  3645. test_clic_boutons(&bt_scan_SW);
  3646. if (bt_scan_SW.cliked == true)
  3647. {
  3648. ok1 = true;
  3649. // -------------------------- BANDES SW choisies ----------------
  3650. bt_scan_SW.cliked = false;
  3651. TFT.fillScreen(NOIR);
  3652. TFT.setTextColor(JAUNE, NOIR);
  3653. TFT.setFreeFont(FF0);
  3654. TFT.drawString("CHOIX BANDE SW", 230, 2);
  3655. swPad1.init(5, 2); // initialise et affiche les 14 boutons des 14 bandes d'ondes courtes (SW)
  3656. swPad1.set_frequences_SW();// voir la fonction 'void SW_PAD::set_frequences_SW()' pour les fréquences SW
  3657.  
  3658. affi_image_from_SD("/bmp565/3r.bmp", 150, 60);
  3659.  
  3660. boolean ok2 = false;
  3661. while (! ok2)
  3662. {
  3663. if(do_capt_screen== true) { do_capt_screen = false; write_TFT_on_SDcard(); }
  3664.  
  3665. if ((ts.tirqTouched() && ts.touched()))
  3666. {
  3667. // ---------------- choix de la bande AM SW (impose la fréquence de départ) ---------------
  3668. get_XY_touch();
  3669. uint8_t n = swPad1.test_clic();
  3670.  
  3671. uint32_t FA = swPad1.bt_SW[n].freq_A; // fréquence de départ du scan AM
  3672. uint32_t FB = swPad1.bt_SW[n].freq_B; // fréquence de fin du scan AM
  3673.  
  3674. if (FA != 0) // si on n'a pas cliqué en dehors des clous...
  3675. {
  3676. String band_name = " "; // espace à gauche
  3677. uint16_t L = swPad1.bt_SW[n].lambda;
  3678. band_name += String(L)+"m";
  3679. TFT.setTextColor(NOIR, BLANC);
  3680. TFT.setFreeFont(FMB12);
  3681. TFT.drawString(band_name + " ", 150, 10);
  3682.  
  3683. String s2 = String(FA) + ".." + String(FB)+ " kHz";
  3684. TFT.setTextColor(JAUNE, NOIR);
  3685. TFT.setFreeFont(FF1);
  3686. TFT.drawString(s2, 140, 35);
  3687.  
  3688. bande_active = SW;
  3689. ok2=true;
  3690. mode_affi = SCAN_F;
  3691. mode_s = _FRQ;
  3692. delay(1000);
  3693. scan_frq(FA, FB, band_name); // scanner (AM-SW ou FM )
  3694. }
  3695. }
  3696. }
  3697. }
  3698.  
  3699. if ((ts.tirqTouched() && ts.touched()))
  3700. {
  3701. get_XY_touch();
  3702. test_clic_boutons(&bt_scan_FM);
  3703. if (bt_scan_FM.cliked == true)
  3704. {
  3705. // ------------------------------ BANDE FM choisie -----------------
  3706. bt_scan_FM.cliked = false;
  3707. bande_active = FM;
  3708. ok1=true;
  3709. mode_affi = SCAN_F;
  3710. mode_s = _FRQ;
  3711. scan_frq(88000, 108000, "bande FM");
  3712. }
  3713. }
  3714.  
  3715. test_clic_boutons(&bt_scan_air);
  3716. if (bt_scan_air.cliked == true)
  3717. {
  3718. // ------------------------------ BANDE AIR ----------------
  3719. bt_scan_air.cliked = false;
  3720. mode_affi = SCAN_M;
  3721. bande_active == AIR;
  3722. ok1=true;
  3723. scan_mem_AIR();
  3724. mode_s = _MEM;
  3725. }
  3726. }
  3727. }
  3728. }
  3729.  
  3730.  
  3731.  
  3732. void test_clic_Bt_SCAN()
  3733. {
  3734. if ((ts.tirqTouched() && ts.touched()))
  3735. {
  3736. get_XY_touch();
  3737. test_clic_boutons(&Bt_SCAN);
  3738. if (Bt_SCAN.cliked == true)
  3739. {
  3740. Bt_SCAN.cliked = false;
  3741. choix_type_scan(); // choix bande à scanner (SW - FM) et type FRQ ou AIR (puis déclenche le scan)
  3742.  
  3743. init_affichages();
  3744.  
  3745. groupe_actif = gSCN;
  3746. bande_active = SCN;
  3747.  
  3748. //bt_SCN.selected = true; bt_SCN.affiche(CYAN, 1);
  3749. bt_SW.selected = false; bt_SW.affiche(VERT, 1);
  3750. bt_FM.selected = false; bt_FM.affiche(VERT, 1);
  3751. bt_AIR.selected = false;bt_AIR.affiche(VERT, 1);
  3752.  
  3753. //affiche_numero_frq(String(1), String(nb_F));
  3754. affiche_frequence(frequence);
  3755. }
  3756. }
  3757. }
  3758.  
  3759.  
  3760.  
  3761. void retour_normal()
  3762. {
  3763. TFT.fillScreen(NOIR);
  3764. init_affichages();
  3765. //bt_SW.selected = false;
  3766. //bt_FM.selected = true;
  3767. //bande_active = FM;
  3768. //modulation_active = WFM;
  3769. //frequence = presetPad1.bt_preset[0].frequence_FM;
  3770. //bt_SW.affiche(VERT, 1);
  3771. //bt_FM.affiche(VERT, 1);
  3772. }
  3773.  
  3774.  
  3775. void attente_clic()
  3776. {
  3777. delay(300);
  3778. init_1_bouton(1, 300, 5, 20, 20, "X", &bt_close);
  3779. while ( !(ts.tirqTouched() && ts.touched()) ) {;}
  3780. retour_normal();
  3781.  
  3782. }
  3783.  
  3784.  
  3785.  
  3786. void attente_clic2() // et anti-parasite !!!
  3787. {
  3788. delay(300);
  3789. while ( !(ts.tirqTouched() && ts.touched()) )
  3790. {
  3791. if(do_capt_screen== true) { do_capt_screen = false; write_TFT_on_SDcard(); }
  3792. }
  3793. }
  3794.  
  3795.  
  3796.  
  3797. void SD_listFiles()
  3798. {
  3799. uint16_t y=0;
  3800. String s1;
  3801.  
  3802. TFT.fillScreen(NOIR);
  3803. TFT.setTextColor(BLANC, NOIR);
  3804. TFT.setFreeFont(FF0);
  3805. TFT.drawString("Liste des fichiers (en memoire SD)", 0, y); y+=30;
  3806.  
  3807.  
  3808. File root = SD.open("/");
  3809. File file = root.openNextFile();
  3810. while (file)
  3811. {
  3812. s1 = String(file.name());
  3813. TFT.setTextColor(VERT, NOIR);
  3814. TFT.drawString(s1, 0, y);
  3815.  
  3816. s1 = "size:";
  3817. TFT.setTextColor(BLANC, NOIR);
  3818. TFT.drawString(s1, 100, y);
  3819.  
  3820. s1 = file.size();
  3821. TFT.setTextColor(JAUNE, NOIR);
  3822. TFT.drawString(s1, 140, y);
  3823.  
  3824. y+=10;
  3825. file = root.openNextFile();
  3826. }
  3827. }
  3828.  
  3829.  
  3830.  
  3831. void SD_RAZ()
  3832. {
  3833. boolean valider = false; // <-- ecrire "= true" pour rendre l'effacement possible
  3834. // (évite tout effacement accidentel et donc perte de centaines de fréquences...)
  3835.  
  3836. if(valider == false)
  3837. {
  3838. TFT.fillScreen(NOIR);
  3839. TFT.setFreeFont(FM9);
  3840. TFT.drawString("FONCTION VOLONTAIREMENT", 50, 120);
  3841. TFT.drawString("INACTIVE", 50, 140);
  3842. TFT.drawString("VOIR LE CODE SOURCE", 50, 160);
  3843. TFT.drawString("void SD_RAZ()", 50, 180);
  3844. delay(3000);
  3845. init_affichages();
  3846. return;
  3847. }
  3848.  
  3849. SD.remove("FRQ_SW.txt");
  3850. SD.remove("FRQ_SW_PRST.txt");
  3851. SD.remove("FRQ_FM.txt");
  3852. SD.remove("FRQ_FM_PRST.txt");
  3853. SD.remove("FRQ_AIR.txt");
  3854. SD.remove("FRQ_AIR_PRST.txt");
  3855.  
  3856. Serial.println("fin RAZ SD");
  3857. }
  3858.  
  3859.  
  3860.  
  3861. void test_clic_bouton_LST()
  3862. {
  3863. uint16_t c1 = NOIR;
  3864. uint16_t c2 = VERT;
  3865.  
  3866. test_clic_boutons(&bt_LST );
  3867. if(bt_LST.cliked)
  3868. {
  3869. if (SDcardOk == false) { affi_message ( "SDcard absente", "...", "", "", "" ); return; }
  3870.  
  3871. bt_LST.cliked = false;
  3872. bt_LST.selected = false;
  3873. bt_LST.affiche( c1, 1);
  3874.  
  3875. SD_listFiles();
  3876. init_1_bouton(1, 300, 5, 15, 15, "OK", &bt_annuler);
  3877. attente_clic2();
  3878.  
  3879. TFT.fillScreen(NOIR);
  3880. groupe_SW.affiche_bloc("SW",0);
  3881. groupe_FM.affiche_bloc("FM",100);
  3882. groupe_AIR.affiche_bloc("AIR",200);
  3883. init_1_bouton(1, 300, 5, 15, 15, "OK", &bt_annuler);
  3884. attente_clic2();
  3885.  
  3886. mute = true;
  3887. Set_Mute(true); // fonction située dans le fichier 'driverTEF6686_628.h'
  3888. delay(50);
  3889. bt_mute.selected = true;
  3890. bt_mute.affiche(ROUGE, 1);
  3891. delay(500);
  3892. affi_deroulant("Liste codes PI RDS", "/RDS_codes_PI.lst");
  3893. retour_normal();
  3894. }
  3895. }
  3896.  
  3897.  
  3898.  
  3899. void test_clic_bouton_SD_write() // en SD, dans un des fichiers ("/FRQ_SW.txt" ...)
  3900. {
  3901. uint16_t c1 = GRIS_6;
  3902. uint16_t c2 = VERT;
  3903. String s1;
  3904.  
  3905. test_clic_boutons(&bt_SD_write );
  3906. if(bt_SD_write.cliked)
  3907. {
  3908.  
  3909. bt_SD_write.cliked=false;
  3910. bt_SD_write.selected=false;
  3911. bt_SD_write.affiche( GRIS_5, 1);
  3912.  
  3913. Serial.println("--------------------------------");
  3914. Serial.println("bouton_SD_write clic");
  3915.  
  3916. //attention à ne pas oublier ces < >
  3917. s1 = "<";
  3918. s1 += String(frequence); // // fréquence en cours
  3919. s1 += ">";
  3920.  
  3921. boolean ok = false;
  3922. if (bande_SW)
  3923. {
  3924. if (! groupe_SW.test_Frq_presente(frequence)) // test effectué sur le groupe en RAM
  3925. {
  3926. // AJOUTE la fréquence en fin d'une liste de fréquences. Travaille directement sur la mémoire SD
  3927. File file = SD.open("/FRQ_SW.txt", FILE_APPEND);
  3928. file.print(s1);
  3929. file.print('\n');
  3930. file.close(); // enregistre CE fichier en mémoire SD, sans toucher aux autres
  3931. delay(300);
  3932. ok = true;
  3933. }
  3934. }
  3935.  
  3936. if (bande_FM)
  3937. {
  3938. if (! groupe_FM.test_Frq_presente(frequence))
  3939. {
  3940. File file = SD.open("/FRQ_FM.txt", FILE_APPEND);
  3941. file.print(s1);
  3942. file.close();
  3943. delay(300);
  3944. ok = true;
  3945. }
  3946. }
  3947.  
  3948. if (bande_AIR)
  3949. {
  3950. if (! groupe_AIR.test_Frq_presente(frequence))
  3951. {
  3952. File file = SD.open("/FRQ_AIR.txt", FILE_APPEND);
  3953. file.print(s1);
  3954. file.close();
  3955. delay(300);
  3956. ok = true;
  3957. }
  3958. }
  3959.  
  3960. String s1, s2;
  3961. if (ok) {s1 = "Enregistrement OK"; s2 = ""; }
  3962. else {s1 = "Freq. deja presente"; s2 = "NOT SAVE";}
  3963. Serial.println(s1);
  3964.  
  3965. if (ok) {load_GRP_FREQ_SD();} // recharge les listes de fréquences depuis la SD pour être à jour
  3966.  
  3967. TFT.fillScreen(NOIR);
  3968. TFT.setTextColor(JAUNE, NOIR);
  3969. TFT.setFreeFont(FF1);
  3970. TFT.drawString(s1, 5, 40);
  3971. TFT.drawString(s2, 5, 60);
  3972. delay(1000);
  3973. retour_normal();
  3974. }
  3975. }
  3976.  
  3977.  
  3978.  
  3979. void test_clic_bt_erase_1F() // en SD
  3980. {
  3981. uint16_t c1 = GRIS_6;
  3982. uint16_t c2 = VERT;
  3983.  
  3984. test_clic_boutons(&bt_erase_1F );
  3985. if(bt_erase_1F.cliked)
  3986. {
  3987. bt_erase_1F.cliked = false;
  3988. bt_erase_1F.selected = false;
  3989. bt_erase_1F.affiche(c1, 1);
  3990.  
  3991. delay (100);
  3992. bt_erase_1F.cliked = false;
  3993. bt_erase_1F.selected = false;
  3994. bt_erase_1F.affiche(c2, 1); // fugitif
  3995.  
  3996. uint16_t F;
  3997.  
  3998. //todo: en SD
  3999.  
  4000. }
  4001. }
  4002.  
  4003.  
  4004. void test_clic_boutons_MODE() // FREQ - MEM
  4005. {
  4006. uint16_t c1 = NOIR;
  4007. uint16_t c2 = VERT;
  4008. uint16_t c3 = JAUNE;
  4009.  
  4010. bt_mode_FRQ.cliked = false;
  4011. bt_mode_MEM.cliked = false;
  4012.  
  4013. test_clic_boutons(&bt_mode_FRQ );
  4014. if (bt_mode_FRQ.cliked) // les boutons sont exclusifs
  4015. {
  4016. presetPad1.deselect_boutons();
  4017. mode_s = _FRQ;
  4018. //affiche_index_frq();
  4019. //bt_4.selected=true; // 100kHz
  4020. //bt_4.affiche(c2, 1);
  4021. bt_mode_FRQ.selected = true;
  4022. bt_mode_MEM.selected = false;
  4023. affiche_frequence(frequence);
  4024. efface_numero_frq();
  4025. }
  4026.  
  4027. test_clic_boutons(&bt_mode_MEM );
  4028. if (bt_mode_MEM.cliked)
  4029. {
  4030. mode_s = _MEM;
  4031. bt_mode_MEM.selected = true;
  4032. bt_mode_FRQ.selected = false;
  4033. affiche_frequence(frequence);
  4034. }
  4035.  
  4036. bt_mode_FRQ.affiche(c2, 2);
  4037. bt_mode_MEM.affiche(c3, 2);
  4038. init_boutons_Plus_Moins(); //ce qui va changer le symbole affiché en '-' et '+' ou '<' et '>' en fonction du 'mode_s'
  4039. if (mode_affi == NORMAL)
  4040. {
  4041. bt_moins.affiche(VERT ,1);
  4042. bt_plus.affiche(VERT ,1);
  4043. }
  4044.  
  4045. }
  4046.  
  4047.  
  4048. void test_clic_boutons_BANDE() // SW, FM, AIR, SCAN
  4049. {
  4050. uint16_t c1 = GRIS_5;
  4051. uint16_t c2 = VERT;
  4052.  
  4053. bt_SW.cliked = false;
  4054. bt_FM.cliked = false;
  4055. bt_AIR.cliked = false;
  4056.  
  4057. test_clic_boutons(&bt_SW );
  4058. if (bt_SW.cliked)
  4059. {
  4060. TFT.fillRect(x0_box_info1+2, y0_box_info1+1, 118, 12, NOIR); // efface
  4061. efface_box_entete2();
  4062. //Serial.println("bt_SW.cliked");
  4063. bt_SW.cliked = false;
  4064.  
  4065. groupe_actif = gSW;
  4066. bande_active = SW;
  4067. modulation_active = AM;
  4068. bt_SW.selected = true;
  4069. bt_FM.selected = false; // les boutons sont exclusifs
  4070. bt_AIR.selected = false;
  4071. bt_SCN.selected = false;
  4072.  
  4073. //clic_logiciel_bouton(&presetPad1.bt_preset[0]);
  4074. //traite_boutons_presetPad(0);
  4075.  
  4076. frequence = 15000; // 15MHz
  4077. Tune_Frequence(frequence);
  4078. affiche_frequence(frequence);
  4079.  
  4080. uint8_t nb_F = groupe_SW.nb_freq;
  4081. affiche_numero_frq(String(1), String(nb_F));
  4082. }
  4083.  
  4084.  
  4085. test_clic_boutons(&bt_FM );
  4086. if (bt_FM.cliked)
  4087. {
  4088. //Serial.println("bt_FM.cliked");
  4089. efface_box_entete2();
  4090. bt_FM.cliked = false;
  4091.  
  4092. groupe_actif = gFM;
  4093. bande_active = FM;
  4094. modulation_active = WFM;
  4095. bt_FM.selected = true;
  4096. bt_SW.selected = false;
  4097. bt_AIR.selected = false;
  4098. bt_SCN.selected = false;
  4099. affi_boutons_SW_FM_AIR_SCN();
  4100.  
  4101. //traite_boutons_presetPad(0);
  4102. frequence = presetPad1.bt_preset[0].frequence_FM;
  4103. Tune_Frequence(frequence);
  4104. affiche_frequence(frequence);
  4105. clic_logiciel_bouton(&presetPad1.bt_preset[0]);
  4106.  
  4107. uint8_t nb_F = groupe_FM.nb_freq;
  4108. affiche_numero_frq(String(1), String(nb_F));
  4109. }
  4110.  
  4111.  
  4112. test_clic_boutons(&bt_AIR );
  4113. if (bt_AIR.cliked)
  4114. {
  4115. TFT.fillRect(x0_box_info1+2, y0_box_info1+1, 118, 12, NOIR); // efface
  4116. efface_box_entete2();
  4117. //Serial.println("bt_AIR.cliked");
  4118. bt_AIR.cliked = false;
  4119.  
  4120. groupe_actif = gAIR;
  4121. bande_active = AIR;
  4122. modulation_active = AM;
  4123. bt_AIR.selected = true;
  4124. bt_SW.selected = false;
  4125. bt_FM.selected = false;
  4126. bt_SCN.selected = false;
  4127. affi_boutons_SW_FM_AIR_SCN();
  4128.  
  4129. frequence = 123500;
  4130. Tune_Frequence(frequence);
  4131. affiche_frequence(frequence);
  4132.  
  4133. //clic_logiciel_bouton(&presetPad1.bt_preset[0]);
  4134. //traite_boutons_presetPad(0);
  4135.  
  4136.  
  4137. uint8_t nb_F = groupe_AIR.nb_freq;
  4138. affiche_numero_frq(String(1), String(nb_F));
  4139. }
  4140.  
  4141.  
  4142. test_clic_boutons(&bt_SCN );
  4143. if (bt_SCN.cliked == true)
  4144. {
  4145. efface_box_entete2();
  4146. Serial.println("bt_SCN.cliked");
  4147. bt_SCN.cliked = false;
  4148.  
  4149. groupe_actif = gSCN;
  4150. bande_active = SCN;
  4151. bt_SCN.selected = true;
  4152. bt_SW.selected = false;
  4153. bt_FM.selected = false;
  4154. bt_AIR.selected = false;
  4155. affi_boutons_SW_FM_AIR_SCN();
  4156.  
  4157. presetPad1.deselect_boutons();
  4158.  
  4159. uint8_t nb_F = groupe_SCAN.nb_freq;
  4160. affiche_numero_frq(String(1), String(nb_F));
  4161. }
  4162.  
  4163. Serial.print("groupe actif = "); Serial.println(groupe_actif);
  4164.  
  4165. }
  4166.  
  4167.  
  4168. void test_clic_bouton_set() // bouton pour passer dans le mode d'écriture de la F en cours en SD
  4169. // L'écriture en question sera effectuée par la fonction 'traite_boutons_presetPad()'
  4170. {
  4171. test_clic_boutons(&bt_set);
  4172. if (bt_set.cliked)
  4173. {
  4174. bt_set.cliked = false;
  4175. vu_metre_actif = false;
  4176. TFT.fillRect(x0_box_info2, y0_box_info2, 140, 70, NOIR);
  4177.  
  4178. TFT.setTextColor(VERT, NOIR);
  4179. TFT.setFreeFont(FF0);
  4180. TFT.drawString("Cliquez sur un des 8 bt", x0_box_info2+2, y0_box_info2+2);
  4181. TFT.drawString("'preset' pour lui ", x0_box_info2+2, y0_box_info2+12);
  4182. TFT.drawString("attribuer la F en cours", x0_box_info2+2, y0_box_info2+22);
  4183.  
  4184. init_1_bouton(1, x0_box_info2+82, y0_box_info2+50, 50, 15, "annuler", &bt_annuler);
  4185. bt_annuler.affiche(BLANC, 1);
  4186.  
  4187. mode_affi = SET_F_PRESET; // ce qui modifie le comportement de la fonction 'traite_boutons_presetPad()'
  4188. Serial.println("mode_affi == SET_F_PRESET");
  4189.  
  4190. delay (100);
  4191. bt_set.selected = false;
  4192. bt_set.affiche(BLANC, 1);
  4193. }
  4194. }
  4195.  
  4196.  
  4197. void affi_bargraph(uint16_t x, uint16_t y, uint16_t dx, int16_t vi)
  4198. {
  4199. if(! quiet)
  4200. {
  4201. //TFT.fillRect(x, y, dx, 8, NOIR); // efface
  4202. if (valeur_bargraph < vi) {valeur_bargraph ++;} // pour déplassements progressifs
  4203. if (valeur_bargraph > vi) {valeur_bargraph --;} // pour déplassements progressifs
  4204.  
  4205. if(valeur_bargraph<0) {valeur_bargraph =0;}
  4206. if(valeur_bargraph > dx-1) {valeur_bargraph = dx-1;}
  4207. TFT.drawRect(x, y, dx, 5, couleur_traits);
  4208. //TFT.fillRect(x, y, valeur_bargraph, 5, JAUNE);
  4209. TFT.fillRect(x + valeur_bargraph, y, 1, 5, VERT); // affiche juste l'extrémité
  4210. TFT.fillRect(x + valeur_bargraph+1, y, 1, 5, NOIR); // efface juste l'extrémité +1
  4211. }
  4212. else
  4213. {
  4214. TFT.fillRect(x, y, dx, 5, couleur_fond_ecran); // efface le bargraph
  4215. }
  4216. }
  4217.  
  4218.  
  4219. void affiche_tension_batt(uint16_t x, uint16_t y, uint16_t dx, int8_t valeur) // valeur en %
  4220. {
  4221. uint16_t c1;
  4222. c1 = ROUGE;
  4223. if(valeur>30){c1 = ORANGE;}
  4224. if(valeur>50){c1 = JAUNE;}
  4225. if(valeur>70){c1 = VERT;}
  4226.  
  4227. uint32_t v2 = valeur * dx / 100;
  4228. TFT.fillRect(x-20, y, dx, 8, NOIR); // efface
  4229. efface_box_entete3();
  4230. if(v2<0) {valeur =0;}
  4231. if(v2 > dx) {v2 = dx;}
  4232. TFT.drawRect(x, y, dx, 5, couleur_traits);
  4233. TFT.fillRect(x, y, v2, 5, c1);
  4234.  
  4235. String s1 = String(valeur) +"%";
  4236. TFT.setTextColor(BLANC, NOIR);
  4237. TFT.setFreeFont(FF0);
  4238. TFT.drawString(s1, x-20, y);
  4239. TFT.drawString("bat", x + 10 , y+5);
  4240.  
  4241. TFT.drawRect(0, 0, 319, 240, couleur_traits); // cadre principal pourtour de l'écran
  4242. }
  4243.  
  4244.  
  4245. /*
  4246. void affiche_1_bargraph(uint16_t x, uint16_t y, uint16_t dx, int16_t valeur, uint16_t couleur)
  4247. {
  4248. TFT.fillRect(x, y, dx+40, 8, NOIR); // efface
  4249. TFT.drawString(String(valeur), x, y);
  4250.  
  4251. if(valeur<0) {valeur =0;}
  4252. if(valeur > dx) {valeur = dx;}
  4253. TFT.drawRect(x+40, y, dx, 5, couleur_traits);
  4254. TFT.drawRect(x+40, y, valeur, 5, couleur);
  4255. }
  4256.  
  4257. void affiche_bars_graph()
  4258. {
  4259. affiche_1_bargraph(170, 150, 100, level/10, VERT);
  4260. affiche_1_bargraph(170, 160, 100, usn, JAUNE);
  4261. affiche_1_bargraph(170, 170, 100, wam, BLEU_CLAIR);
  4262. affiche_1_bargraph(170, 180, 100, offset, BLANC);
  4263. }
  4264. */
  4265.  
  4266. String int_to_hex(uint16_t nb)
  4267. {
  4268. char symb[16] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
  4269. uint8_t A = (nb & 0b1111000000000000) >>12;
  4270. uint8_t B = (nb & 0b0000111100000000) >>8;
  4271. uint8_t C = (nb & 0b0000000011110000) >>4;
  4272. uint8_t D = (nb & 0b0000000000001111);
  4273. String s1 = String(symb[A]) + String(symb[B]) + String(symb[C]) + String(symb[D]) ;
  4274. return s1;
  4275. }
  4276.  
  4277.  
  4278.  
  4279. void traite_signal_RDS()
  4280. {
  4281. Get_RDS_Data(&status, &A_block, &B_block, &C_block, &D_block, &dec_error);
  4282. /*
  4283. A_Block always contains the 16-bit program identifier.
  4284. The first 11 bits (bits 15–5) of block 2 are also the same in all groups.
  4285.  
  4286. La Liste des codes RDS autorisés se trouve ici : https://www.csa.fr/maradiofm/radiords_tableau
  4287.  
  4288. Pour les autres blocks, voir :
  4289. https://en.wikipedia.org/wiki/Radio_Data_System
  4290. (c'est sans doute logique mais terriblement indigeste !!!)
  4291. */
  4292. char buffer1[64];
  4293. uint16_t nombre =0;
  4294. String s_recue, s1, s2, s3;
  4295.  
  4296. s_recue = int_to_hex(A_block); // exemple: 'F201' ; mis à jour par le 'Get_RDS_Data()'
  4297. if (s_recue == memo_s_recue) {return; } // puisque rien de nouveau à traiter
  4298. memo_s_recue = s_recue;
  4299.  
  4300. TFT.fillRect(x0_box_info1+2, y0_box_info1, 118, 16, NOIR); // efface (en bas à gauche)
  4301. TFT.setTextColor(BLEU_CLAIR, GRIS_6);
  4302. TFT.setFreeFont(FF0);
  4303.  
  4304. File file1 = SD.open("/RDS_codes_PI.lst", "r");
  4305. while (file1.available())
  4306. {
  4307. int nb_bytes = file1.readBytesUntil('\n', buffer1, sizeof(buffer1));
  4308. buffer1[nb_bytes] = 0; // zéro terminal afin d'obtenir un string
  4309. s1 = buffer1;
  4310.  
  4311. s2 = s1.substring(0, 4); // exemple: 'F218'
  4312. s3 = s1.substring(4); // la suite
  4313.  
  4314.  
  4315. if (s_recue == s2) // la station reçue figure dans la liste
  4316. {
  4317. TFT.setTextColor(JAUNE, GRIS_6);
  4318. TFT.drawString(s2, x0_box_info1+5, y0_box_info1 +4);
  4319.  
  4320. TFT.setTextColor(BLEU_CLAIR, GRIS_6);
  4321. TFT.drawString(s3, x0_box_info1+30, y0_box_info1 +4);
  4322.  
  4323. return; // on ne continue pas à boucler si trouvé
  4324. }
  4325. }
  4326. }
  4327.  
  4328.  
  4329.  
  4330. void affiche_force_signal()
  4331. {
  4332. //----------------------------------------------------------------------------------------------------------
  4333. // AFFICHE FORCE SIGNAL HF
  4334. compteur1 =0;
  4335.  
  4336. //float signal_sur_bruit = level;// - 1.5 * usn; // marche à peu près bien pour la FM.
  4337.  
  4338. float diff = level - position_aiguille;
  4339. if(diff > 60.0) {diff = 60.0;}
  4340. if(diff < -60.0) {diff = -60.0;} // évite une trop grande réaction au sortir du mode 'mute'
  4341. // supprime les tremblements de l'aiguille
  4342. position_aiguille += diff / 4.0;
  4343.  
  4344. //affi_bargraph(170, 90, 60, mod/2);
  4345.  
  4346. if ((mode_affi == NORMAL) && (! mute) && (! quiet))
  4347. {
  4348. plotAiguille(position_aiguille/6.0); // génère des parasites audibles !
  4349. }
  4350. }
  4351.  
  4352.  
  4353.  
  4354. void loop()
  4355. {
  4356. if((mode_affi != SCAN_F) && (mode_affi != SCAN_M))// invalide les boutons situés derrière le panneau scan en modes SCAN
  4357. {
  4358. if (ts.tirqTouched() && ts.touched())
  4359. {
  4360. memo_y_touch = y_touch;
  4361. get_XY_touch();
  4362.  
  4363. test_clic_boutons_inc_dec(); // 6 boutons (invisibles) placés sous les chiffres de la fréquence
  4364.  
  4365. test_clic_bouton_mute();
  4366. //test_clic_bouton_SD_RAZ();
  4367. test_clic_bouton_SD_write();
  4368. test_clic_bouton_LST();
  4369. test_clic_bt_erase_1F();
  4370. uint8_t n_touch1 = numPad1.test_clic(); // pavé numérique
  4371. if (n_touch1 != 253) { traite_touches_pad(n_touch1); } // pavé numérique
  4372.  
  4373. test_clic_boutons_plus_moins(); // boutons '<' et '>'
  4374. test_clic_bouton_Sleep();
  4375. test_clic_bt_LED();
  4376. test_clic_bt_CAL(); // calibration de l'écran tactile
  4377. test_clic_bt_quiet();
  4378. test_clic_bouton_TEST();
  4379. test_clic_bouton_info();
  4380. test_clic_Bt_reset();
  4381. test_clic_Bt_SCAN(); // choix bande à scanner (SW - FM) et type FRQ ou AIR (puis déclenche le scan)
  4382. test_clic_boutons_MODE(); // FREQ / MEM (tout en haut à gauche des gros chiffres)
  4383. test_clic_boutons_BANDE(); // SW, FM, AIR, SC; (SC = SCAN)
  4384.  
  4385. uint8_t num_bouton = presetPad1.test_clic(); // 8 petits boutons carrés de présélection de 8 fréquences
  4386. if (num_bouton != 253) { traite_boutons_presetPad(num_bouton); }
  4387.  
  4388. test_clic_bouton_set(); // attribution de la fréquence en cours à un des 8 boutons preset.
  4389. test_clic_bt_annuler();
  4390.  
  4391. test_clic_bt_coul();
  4392. test_clic_bt_RST_affi();
  4393. }
  4394.  
  4395. // la limitation SW max = 28MHz est imposée par le module TEF6686 lui-même
  4396. if (frequence >= 138000) {frequence = 138000;} //138 MHz limite à cause SW max = 28MHz et conv AirBand = 110 MHz
  4397. if (frequence < 1500) {frequence = 1500;} // 1.5 MHz
  4398.  
  4399. uint8_t module;
  4400. if(bande_active == FM) {module = 32;} else {module = 33;}
  4401. Get_Quality( module, &status, &level, &usn, &wam, &offset, &bandwidth, &mod, &snr );
  4402.  
  4403. affi_bargraph(170, 90, 60, mod/2);
  4404.  
  4405. if (compteur1 >= 20)
  4406. {
  4407. affiche_force_signal();
  4408.  
  4409. //----------------------------------------------------------------------------------------------------------
  4410. // AFFICHE TENSION BATTERIE
  4411. //----------------------------------------------------------------------------------------------------------
  4412. // voir la feuille de calcul 'Mesure de la tension de la batterie.ods' établie sur tests avec alim numérique
  4413. // voir aussi, sur le schéma, la valeur des résistances (diviseur analogique) sur l'entrée GPIO35 (analogPin = 35)
  4414. // Note: la valeur de la tension sur le pin GPIO35 ne doit jamais dépasser 3v3 (ce qui est lu = 4096)
  4415. int valeurLue;
  4416. valeurLue = analogRead(analogPin);
  4417. //Serial.print("valeurLue = "); Serial.println(valeurLue);
  4418. float pourcent = ((float)valeurLue - 2570.0) / 7.5;
  4419. if (pourcent > 100.0) {pourcent = 100.0;}
  4420. if (pourcent < 0.0) {pourcent = 0.0;}
  4421.  
  4422. // intégration
  4423. float diff2 = pourcent - valeur_affi;
  4424. if(diff2 > 10.0) {diff2 = 10.0;}
  4425. if(diff2 < -10.0) {diff2 = -10.0;} // évite une trop grande réaction au sortir du mode 'mute'
  4426. valeur_affi += diff2 / 10.0;
  4427.  
  4428. if ( abs(valeur_affi - memo_valeur_affi) > 1.5 ) // pour éviter trop d'affichages inutiles (et clignotements à l'écran)
  4429. {
  4430. affiche_tension_batt(270, 4, 46, (int8_t) valeur_affi);
  4431. memo_valeur_affi = valeur_affi;
  4432. }
  4433. }
  4434.  
  4435. if (compteur2 >= 100)
  4436. {
  4437. compteur2 =0;
  4438.  
  4439. if(bande_active == FM) {traite_signal_RDS();}
  4440. }
  4441.  
  4442. if (quiet == true)
  4443. {
  4444. // quiet (anti-parasites audio, surtout pour les stations faibles)
  4445. // inconvéniants: fige les affichages (vu_metre, bargraph signal audio...)
  4446. affi_image_from_SD("/bmp565/montagne140x70.bmp", x0_vu_metre, y0_vu_metre);
  4447.  
  4448. attente_clic2(); // quiet (anti-parasites)
  4449. }
  4450.  
  4451. if(do_capt_screen== true) { do_capt_screen = false; write_TFT_on_SDcard(); }
  4452.  
  4453. /*
  4454. if (compteur3 >= 1000)
  4455. {
  4456. // passe en mode quiet automatiquement, avec ses inconvéniants !
  4457. compteur3 =0;
  4458.  
  4459. quiet = true;
  4460.  
  4461. bt_quiet.cliked = false;
  4462. bt_quiet.selected = true;
  4463. bt_quiet.affiche(VERT, 1);
  4464. }
  4465. */
  4466.  
  4467. delay(5); // détermine la réactivité du bargraph
  4468. compteur1++;
  4469. compteur2++;
  4470. compteur3++;
  4471. }
  4472. }
  4473.  
  4474.  
  4475.  
  4476. /** ***************************************************************************************
  4477. CLASS TOUCH_BOUTON // affiche un nombre ou un petit texte dans un rectangle
  4478. ainsi que (en plus petit) deux valeurs supplémentaires, par ex: les valeurs mini et maxi
  4479. ********************************************************************************************/
  4480.  
  4481. // Constructeur
  4482. TOUCH_BOUTON::TOUCH_BOUTON()
  4483. {
  4484.  
  4485. }
  4486.  
  4487. // Constructeur
  4488. TOUCH_BOUTON_PRESET::TOUCH_BOUTON_PRESET()
  4489. {
  4490.  
  4491. }
  4492.  
  4493.  
  4494. // Constructeur
  4495. TOUCH_BOUTON_SW::TOUCH_BOUTON_SW()
  4496. {
  4497.  
  4498. }
  4499.  
  4500.  
  4501. void TOUCH_BOUTON::init(uint16_t x_i, uint16_t y_i, uint8_t dx_i, uint8_t dy_i, uint8_t dr_i, uint16_t couleur_i)
  4502. {
  4503. x0 = x_i;
  4504. y0 = y_i;
  4505. dx = dx_i;
  4506. dy = dy_i;
  4507. dr = dr_i;
  4508. couleur = couleur_i;
  4509.  
  4510. cliked = false;
  4511. selected = false;
  4512. }
  4513.  
  4514.  
  4515.  
  4516. void TOUCH_BOUTON::affiche(uint16_t coul_fill_select, uint8_t n_font)
  4517. {
  4518. uint16_t couleur_contour = GRIS_5;
  4519. uint16_t couleur_texte = BLANC;
  4520.  
  4521. if(selected)
  4522. {
  4523. TFT.fillRoundRect(x0, y0, dx, dy, dr, coul_fill_select);
  4524. TFT.setTextColor(NOIR);
  4525. }
  4526. else
  4527. {
  4528. TFT.fillRoundRect(x0, y0, dx, dy, dr, couleur); // efface
  4529. TFT.drawRoundRect(x0, y0, dx, dy, dr, couleur_contour); // retrace juste le contour
  4530. TFT.setTextColor(couleur_texte);
  4531. }
  4532.  
  4533. //FM9 FMB9 FSS9... voir le fichier FrSD_Fonts.h
  4534. if (n_font == 1) { TFT.setFreeFont(FF0);}
  4535. if (n_font == 2) { TFT.setFreeFont(FM9);}
  4536. if (n_font == 3) { TFT.setFreeFont(FMB9);}
  4537. if (n_font == 4) { TFT.setFreeFont(FSS9);}
  4538.  
  4539. TFT.drawString(label, x0+3, y0 - (2*n_font) + (dy-4)/2);
  4540. }
  4541.  
  4542.  
  4543. uint8_t TOUCH_BOUTON::read_dx()
  4544. {
  4545. return dx;
  4546. }
  4547.  
  4548.  
  4549. uint8_t TOUCH_BOUTON::read_dy()
  4550. {
  4551. return dy;
  4552. }
  4553.  
  4554. /** ***************************************************************************************
  4555. CLASS grid_PAD
  4556. ********************************************************************************************/
  4557. // Constructeur
  4558. GRID_PAD::GRID_PAD()
  4559. {
  4560.  
  4561. }
  4562.  
  4563.  
  4564. void GRID_PAD::init(uint16_t xi, uint16_t yi)
  4565. {
  4566. x0 = xi;
  4567. y0 = yi;
  4568. uint16_t x, y;
  4569.  
  4570.  
  4571. x = x0+2;
  4572. y = y0+1;
  4573.  
  4574. for(uint8_t n =1; n <= nb_t; n++)
  4575. {
  4576. bt_grid[n].init(x, y, dxt, dyt, 3, n * 100);
  4577. bt_grid[n].label="";
  4578. //bt_grid[n].affiche(BLEU, 1);
  4579. x += dxt+1;
  4580. if (x > (x0 + nb_bt_x * dxt)) {x = x0+2; y += dyt+1; }
  4581. }
  4582. }
  4583.  
  4584.  
  4585. void GRID_PAD::affiche()
  4586. {
  4587. for(uint8_t n =1; n <= nb_t; n++)
  4588. {
  4589. bt_grid[n].affiche(BLEU, 1);
  4590. }
  4591. }
  4592.  
  4593.  
  4594. void GRID_PAD::set_couleurs() // F = facteur d'assombrissement
  4595. {
  4596. /*
  4597. voir la page:
  4598. https://rgbcolorpicker.com/565
  4599. qui permet de reconfigurer les couleurs RGB565 (5+6+5 = 16 bits) très simplement
  4600. */
  4601. uint16_t c565i, c565i2;
  4602. uint8_t R, G, B;
  4603. int16_t j, k;
  4604.  
  4605.  
  4606. // les deux premières lignes couleurs arc-en-ciel
  4607. k=-16;
  4608. uint8_t F=1;
  4609. for(uint8_t n=0; n<32; n++)
  4610. {
  4611. j=30*(32-n);
  4612. c565i = couleurs_aec[2*j] | couleurs_aec[2*j+1]<<8;
  4613.  
  4614. RGB565_to_888(c565i, &R, &G, &B);
  4615. R /= F;
  4616. G /= F;
  4617. B /= F;
  4618. c565i2 = Color_To_565(R, G, B);
  4619. if((k>=0) && (k<16)) {bt_grid[k].couleur = c565i2;}
  4620. k++;
  4621. }
  4622.  
  4623. // les lignes 3 et 4 couleurs plus sombres
  4624. k=0;
  4625. F=3;
  4626. for(uint8_t n=0; n<32; n++)
  4627. {
  4628. j=30*(32-n);
  4629. c565i = couleurs_aec[2*j] | couleurs_aec[2*j+1]<<8;
  4630.  
  4631. RGB565_to_888(c565i, &R, &G, &B);
  4632. R /= F;
  4633. G /= F;
  4634. B /= F;
  4635. c565i2 = Color_To_565(R, G, B);
  4636. if((k>=16) && (k<32)) {bt_grid[k].couleur = c565i2;}
  4637. k++;
  4638. }
  4639.  
  4640. bt_grid[16].couleur = 49174; // violet
  4641.  
  4642. //bt_grid[25].couleur = 0b1111100000000000; // R
  4643. //bt_grid[26].couleur = 0b0000011111100000; // V
  4644. //bt_grid[27].couleur = 0b0000000000011111; // B
  4645. //bt_grid[28].couleur = 0xFFFF;
  4646. //bt_grid[29].couleur = 0;
  4647.  
  4648. bt_grid[32].couleur = GRIS_4;
  4649. bt_grid[32].label="X";
  4650. }
  4651.  
  4652.  
  4653.  
  4654. uint8_t GRID_PAD::test_clic()
  4655. {
  4656. if ( (( x_touch > x0) && (x_touch < (x0 + dxt*nb_bt_x +20))) && (( y_touch > y0) && (y_touch < (y0 + dyt*nb_bt_y +10))))
  4657. {
  4658. uint8_t num_bouton =255;
  4659.  
  4660. for(uint8_t n = 0; n<nb_t; n++)
  4661. {
  4662. test_clic_boutons(&bt_grid[n] );
  4663. if(bt_grid[n].cliked)
  4664. {
  4665. num_bouton = n;
  4666. }
  4667. }
  4668.  
  4669. delay(100);
  4670. return num_bouton;
  4671. }
  4672. return 253;
  4673. }
  4674.  
  4675.  
  4676. /** ***************************************************************************************
  4677. CLASS NUMPAD
  4678. ********************************************************************************************/
  4679. // Constructeur
  4680. NUM_PAD::NUM_PAD()
  4681. {
  4682.  
  4683. }
  4684.  
  4685.  
  4686. void NUM_PAD::init(uint16_t xi, uint16_t yi, boolean fond) // si fond =false, ne resessine que les boutons
  4687. {
  4688. x0 = xi;
  4689. y0 = yi;
  4690. uint16_t x, y;
  4691. uint8_t dxt = 25; // taille x d'une touche
  4692. uint8_t dyt = 23; // taille y d'une touche
  4693.  
  4694. if(fond == true) {TFT.fillRect(x0, y0, 3*dxt +6, 4*dyt +7, NOIR);}
  4695.  
  4696. if(fond == true) {TFT.fillRect(x0, y0, 3*dxt +6, 4*dyt +7, NOIR);}
  4697.  
  4698. uint16_t c1 = GRIS_5;
  4699. uint16_t c2 = JAUNE;
  4700.  
  4701. x = x0+2;
  4702. y = y0+2;
  4703.  
  4704. for(uint8_t n =1; n<10; n++)
  4705. {
  4706. bt_pad[n].init(x, y, dxt, dyt, 3, GRIS_5);
  4707. bt_pad[n].label=String(n);
  4708. bt_pad[n].affiche(c2, 2);
  4709. x += dxt+1;
  4710. if (x > (x0 + 3*dxt)) {x = x0+2; y += dyt+1; }
  4711. }
  4712. bt_pad[0].init(x, y, dxt, dyt, 3, GRIS_5); bt_pad[0].label="0"; bt_pad[0].affiche(c2, 2); x += dxt+1;
  4713. bt_point.init(x, y, dxt, dyt, 3, GRIS_5); bt_point.label="."; bt_point.affiche(c2, 2);
  4714.  
  4715. x += dxt+1;
  4716. bt_ok.init(x, y, dxt, dyt, 3, GRIS_5); bt_ok.label="ok";
  4717. bt_ok.affiche(c2, 1);
  4718. }
  4719.  
  4720.  
  4721. uint8_t NUM_PAD::test_clic()
  4722. {
  4723. // zone des boutons du clavier
  4724. if ( (( x_touch > x0) && (x_touch < x0 + 100)) && (( y_touch > y0) && (y_touch < y0 + 130)))
  4725. {
  4726. uint8_t num_touche =0;
  4727.  
  4728. for(uint8_t n = 0; n<10; n++)
  4729. {
  4730. test_clic_boutons(&bt_pad[n] ); if(bt_pad[n].cliked) {num_touche=n; n_appui ++;}
  4731. }
  4732.  
  4733. test_clic_boutons(&bt_point ); if(bt_point.cliked) {num_touche=254; } // bouton "."
  4734. test_clic_boutons(&bt_ok ); if(bt_ok.cliked) {num_touche=255; n_appui ++;} // bouton "ok"
  4735. delay(100);
  4736. init(x0, y0, false); // 'false' évite le clignotement lorsqu'on repeint le fond noir
  4737.  
  4738. return num_touche;
  4739. }
  4740. return 253;
  4741. }
  4742.  
  4743. /** ***************************************************************************************
  4744. CLASS PRESET_PAD
  4745. ********************************************************************************************/
  4746.  
  4747. // Constructeur
  4748. PRESET_PAD::PRESET_PAD()
  4749. {
  4750.  
  4751. }
  4752.  
  4753.  
  4754. void PRESET_PAD::init(uint16_t xi, uint16_t yi)
  4755. {
  4756. x0 = xi;
  4757. y0 = yi;
  4758.  
  4759. uint16_t c1 = GRIS_5;
  4760. uint16_t c2 = JAUNE;
  4761.  
  4762. uint16_t x2, y2;
  4763. x2 = x0;
  4764. y2= y0;
  4765.  
  4766. for(uint8_t n=0; n<8; n++)
  4767. {
  4768. bt_preset[n].init(x2, y2, 15, 15, 3, GRIS_5);
  4769. bt_preset[n].label=String(n+1);
  4770. if(mode_affi == COUL) {c1 = bt_preset[n].couleur;}
  4771. bt_preset[n].affiche(c2, 1);
  4772. x2 += 20;
  4773. }
  4774. }
  4775.  
  4776.  
  4777. uint8_t PRESET_PAD::read_dx()
  4778. {
  4779. return dx;
  4780. }
  4781.  
  4782.  
  4783. uint8_t PRESET_PAD::read_dy()
  4784. {
  4785. return dy;
  4786. }
  4787.  
  4788.  
  4789.  
  4790. void PRESET_PAD::set_frequences_PRST() // lit les fréquences en SD et les attribue à chaque bouton PRESET
  4791. {
  4792. Serial.println("void PRESET_PAD::set_frequences()");
  4793.  
  4794. uint8_t n=0;
  4795.  
  4796. read_FRQ_File(SD, "/FRQ_SW_PRST.txt", "SW");
  4797. read_FRQ_File(SD, "/FRQ_FM_PRST.txt", "FM");
  4798. read_FRQ_File(SD, "/FRQ_AIR_PRST.txt", "AIR");
  4799. }
  4800.  
  4801.  
  4802. void PRESET_PAD::set_couleurs()
  4803. {
  4804. /*
  4805. voir la page:
  4806. https://rgbcolorpicker.com/565
  4807. qui permet de reconfigurer les couleurs RGB565 (5+6+5 = 16 bits) très simplement
  4808. */
  4809.  
  4810. bt_preset[0].couleur = 28672; // rouge sombre
  4811. bt_preset[1].couleur = 43584; // orange
  4812. bt_preset[2].couleur = 832; // vert
  4813. bt_preset[3].couleur = 14407; // violet
  4814. bt_preset[4].couleur = 58157; // rose
  4815. bt_preset[5].couleur = 975; // cyan
  4816. bt_preset[6].couleur = 21819; // bleu ciel
  4817. bt_preset[7].couleur = 12; // bleu marine
  4818. }
  4819.  
  4820.  
  4821.  
  4822. void PRESET_PAD::deselect_boutons()
  4823. {
  4824. uint16_t c1 = GRIS_5;
  4825. uint16_t c2 = JAUNE;
  4826.  
  4827. for(int n =0; n<8; n++)
  4828. {
  4829. bt_preset[n].selected=false;
  4830. bt_preset[n].cliked=false;
  4831. bt_preset[n].affiche(c2, 1);
  4832. }
  4833. }
  4834.  
  4835.  
  4836. uint8_t PRESET_PAD::test_clic()
  4837. {
  4838. if ( (( x_touch > x0) && (x_touch < (x0+155))) && (( y_touch > y0) && (y_touch < (y0+15))))
  4839. {
  4840. uint8_t num_bouton =0;
  4841. for(uint8_t n=0; n<8; n++)
  4842. {
  4843. test_clic_boutons(&bt_preset[n]);
  4844. if(bt_preset[n].cliked)
  4845. {
  4846. deselect_boutons(); // les autres
  4847. bt_preset[n].selected =true; // pour l'affichage de celui-ci
  4848. bt_preset[n].affiche(JAUNE, 1);
  4849. num_bouton = n;
  4850. //Serial.print("BB num_bouton= "); Serial.println(num_bouton);
  4851. }
  4852. }
  4853. delay(300);
  4854. return num_bouton;
  4855. }
  4856. return 253;
  4857. }
  4858.  
  4859.  
  4860.  
  4861. /** ***************************************************************************************
  4862. CLASS SW_PAD
  4863. ********************************************************************************************/
  4864. // Constructeur
  4865. SW_PAD::SW_PAD()
  4866. {
  4867.  
  4868. }
  4869.  
  4870.  
  4871. void SW_PAD::init(uint16_t xi, uint16_t yi)
  4872. {
  4873. x0 = xi;
  4874. y0 = yi;
  4875.  
  4876. uint16_t x2, y2;
  4877. x2 = x0;
  4878. y2 = y0;
  4879.  
  4880. set_frequences_SW();
  4881.  
  4882. for(uint8_t n=0; n<14; n++)
  4883. {
  4884. bt_SW[n].init(x2, y2, 30, 12, 3, GRIS_5);
  4885. String sA = String(bt_SW[n].freq_A);
  4886. String sB = String(bt_SW[n].freq_B);
  4887. bt_SW[n].affiche(JAUNE, 1);
  4888. TFT.setTextColor(CYAN, NOIR);
  4889. TFT.setFreeFont(FF0);
  4890. TFT.drawString(sA + "..", x2+35, y2);
  4891. TFT.drawString(sB, x2+80, y2);
  4892. if (n==0) {TFT.drawString("kHz", x2+110, y0);}
  4893. y2 += 16;
  4894. }
  4895. }
  4896.  
  4897.  
  4898. void SW_PAD::set_frequences_SW()
  4899. {
  4900. // bandes plus larges que les 'bandes officielles de radiodiffusion' afin de couvrir tt les frq sans trous
  4901. bt_SW[0].freq_A=2300; bt_SW[0].freq_B=3200; bt_SW[0].lambda=120;
  4902. bt_SW[1].freq_A=3200; bt_SW[1].freq_B=3900; bt_SW[1].lambda=90;
  4903. bt_SW[2].freq_A=3900; bt_SW[2].freq_B=4750; bt_SW[2].lambda=75;
  4904. bt_SW[3].freq_A=4750; bt_SW[3].freq_B=5950; bt_SW[3].lambda=60;
  4905. bt_SW[4].freq_A=5950; bt_SW[4].freq_B=7100; bt_SW[4].lambda=49;
  4906. bt_SW[5].freq_A=7100; bt_SW[5].freq_B=9500; bt_SW[5].lambda=41;
  4907. bt_SW[6].freq_A=9500; bt_SW[6].freq_B=11650; bt_SW[6].lambda=31;
  4908. bt_SW[7].freq_A=11650; bt_SW[7].freq_B=13600; bt_SW[7].lambda=25;
  4909. bt_SW[8].freq_A=13600; bt_SW[8].freq_B=15100; bt_SW[8].lambda=22;
  4910. bt_SW[9].freq_A=15100; bt_SW[9].freq_B=17550; bt_SW[9].lambda=19;
  4911. bt_SW[10].freq_A=17550; bt_SW[10].freq_B=18900; bt_SW[10].lambda=16;
  4912. bt_SW[11].freq_A=18900; bt_SW[11].freq_B=21450; bt_SW[11].lambda=15;
  4913. bt_SW[12].freq_A=21450; bt_SW[12].freq_B=25670; bt_SW[12].lambda=13;
  4914. bt_SW[13].freq_A=25670; bt_SW[13].freq_B=27900; bt_SW[13].lambda=11;
  4915.  
  4916. for(int n =0; n<=13; n++)
  4917. {
  4918. bt_SW[n].label = String(bt_SW[n].lambda) + "m";
  4919. }
  4920. }
  4921.  
  4922.  
  4923. uint8_t SW_PAD::test_clic()
  4924. {
  4925. if ( (( x_touch > x0) && (x_touch < (x0+40))) && (( y_touch > y0) && (y_touch < 240)))
  4926. {
  4927. uint8_t num_bouton =0;
  4928. for(uint8_t n=0; n<=13; n++)
  4929. {
  4930. test_clic_boutons(&bt_SW[n]);
  4931. if(bt_SW[n].cliked)
  4932. {
  4933. deselect_boutons(); // les autres
  4934. bt_SW[n].selected =true; // pour l'affichage de celui-ci
  4935. bt_SW[n].affiche(JAUNE, 1);
  4936. num_bouton = n;
  4937. }
  4938. }
  4939. delay(300);
  4940. return num_bouton;
  4941. }
  4942. return 253;
  4943. }
  4944.  
  4945.  
  4946. void SW_PAD::deselect_boutons()
  4947. {
  4948. uint16_t c1 = GRIS_5;
  4949. uint16_t c2 = JAUNE;
  4950.  
  4951. for(int n =0; n<=13; n++)
  4952. {
  4953. bt_SW[n].selected=false;
  4954. bt_SW[n].cliked=false;
  4955. bt_SW[n].affiche(c2, 1);
  4956. }
  4957. }
  4958.  
  4959. /** ***************************************************************************************
  4960. CLASS GROUPE_FREQUENCES // objet image d'un bloc mémoire en SD
  4961. permet diverses manipulations en RAM (tri...) sans toucher à la SD (évite usure mémoire flash)
  4962. ********************************************************************************************/
  4963.  
  4964. // Constructeur
  4965. GROUPE_FREQUENCES::GROUPE_FREQUENCES()
  4966. {
  4967.  
  4968. }
  4969.  
  4970.  
  4971. void GROUPE_FREQUENCES::RAZ() // en RAM uniquement
  4972. {
  4973. for(int n=0; n<100; n++)
  4974. {
  4975. G_freq[n]=0;
  4976. }
  4977. nb_freq = 0;
  4978. }
  4979.  
  4980.  
  4981. void GROUPE_FREQUENCES::load_bloc() // depuis la SDcard --> vers groupe en RAM
  4982. {
  4983. Serial.println("--------------------------");
  4984. Serial.println("GROUPE_FREQUENCES::load_bloc()");
  4985. Serial.print("Reading file: "); Serial.println(filename);
  4986. File file = SD.open(filename);
  4987. if (!file ) { Serial.println("failed to open file for reading"); return; }
  4988. String s;
  4989. uint8_t n =0;
  4990.  
  4991. while (file.available())
  4992. {
  4993. char c;
  4994. c = char(file.read());
  4995. if ((c !='<') && (c !='>')) {s += c;}
  4996. if(c=='>')
  4997. {
  4998. uint32_t frq;
  4999. frq = s.toInt();
  5000. Serial.println(frq);
  5001. s="";
  5002. G_freq[n] = frq;
  5003. n++;
  5004. }
  5005. }
  5006. file.close();
  5007. Serial.print(n); Serial.println(" frequences");
  5008. }
  5009.  
  5010.  
  5011. boolean GROUPE_FREQUENCES::test_Frq_presente(uint32_t F_i) // travaille en RAM
  5012. {
  5013. Serial.println("--------------------------");
  5014. Serial.println("test_Frq_presente()");
  5015. uint16_t n =0;
  5016. uint16_t adresse_lue;
  5017. uint32_t valeur_lue;
  5018. boolean ok = false;
  5019. for (n=0; n<100; n++)
  5020. {
  5021. valeur_lue = G_freq[n];
  5022. if (valeur_lue == F_i) {return true;} // si F est présente
  5023. }
  5024. return false; // si F non présente
  5025. }
  5026.  
  5027.  
  5028. void GROUPE_FREQUENCES::tri_bloc()
  5029. {
  5030. Serial.println("--------------------------");
  5031. Serial.println("tri_block()");
  5032. // tri par bulles
  5033.  
  5034. uint32_t F1=0, F2=0;
  5035. uint32_t Fi;
  5036. uint16_t i_max = 100;
  5037. uint16_t p_max = 100;
  5038.  
  5039.  
  5040. for(uint16_t p=0; p<p_max; p++)
  5041. {
  5042. //for(int n=0; n<i_max-1; n++)
  5043. uint16_t n =0;
  5044. while(n<i_max-1)
  5045. {
  5046. F1=G_freq[n];
  5047. F2=G_freq[n+1];
  5048.  
  5049. if(F1 > F2)
  5050. {
  5051. Fi = G_freq[n];
  5052. G_freq[n] = G_freq[n+1];
  5053. G_freq[n+1] = Fi;
  5054. }
  5055. n++;
  5056. }
  5057. }
  5058.  
  5059. // ici les freq sont dédoublées !!!!!!!!!!!!
  5060.  
  5061. // compte le nombre de fréquences != 0
  5062. uint16_t nombre =0;
  5063. for(uint16_t n = 0; n<100; n++ )
  5064. {
  5065. F1 = G_freq[n];
  5066. if(F1 != 0) { nombre++;}
  5067. }
  5068. nb_freq = nombre;
  5069.  
  5070. // recherche première fréquence non nulle
  5071. uint16_t n2=0;
  5072. F1 =0;
  5073. while ((F1==0) && (n2<100))
  5074. {
  5075. F1=G_freq[n2];
  5076. n2++;
  5077. }
  5078. adr_1ere_frq = n2-1; // 1ere F non nulle
  5079.  
  5080. }
  5081.  
  5082.  
  5083. void GROUPE_FREQUENCES::bloc_to_serial()
  5084. {
  5085. // pour tests, avec CuteCom sous Linux
  5086. // travaille en RAM uniquement, sans toucher aux fichiers SD
  5087. Serial.println("--------------------------");
  5088. Serial.println("bloc_to_serial()");
  5089. uint32_t valeur_lue;
  5090. uint16_t nombre =0;
  5091. for(uint16_t n = 0; n<100; n++ )
  5092. {
  5093. valeur_lue = G_freq[n];
  5094. if(valeur_lue != 0) // n'affiche pas les emplacements vides
  5095. {
  5096. nombre++;
  5097. Serial.println(valeur_lue);
  5098. }
  5099. }
  5100. Serial.print(nombre); Serial.println(" frequences");
  5101. //Serial.print("1ere Frq= "); Serial.println(G_freq[adr_1ere_frq]);
  5102. }
  5103.  
  5104.  
  5105. // voir la fonction 'void affi_liste()// des aérodromes' du ND.ino
  5106. void GROUPE_FREQUENCES::affiche_bloc(String nom, uint16_t x)
  5107. {
  5108. // travaille en RAM uniquement, sans toucher aux fichiers SD
  5109. uint32_t valeur_lue;
  5110. uint16_t nombre =0;
  5111. uint16_t y;
  5112. String s1;
  5113.  
  5114. TFT.setTextColor(BLANC, NOIR);
  5115. TFT.setFreeFont(FF0);
  5116. TFT.drawString(nom, x, 0);
  5117. y=20;
  5118. for(uint16_t n = 0; n<100; n++ )
  5119. {
  5120. valeur_lue = G_freq[n];
  5121. if(valeur_lue != 0) // n'affiche pas les emplacements vides
  5122. {
  5123. nombre++;
  5124.  
  5125. s1 = String(nombre);
  5126. TFT.setTextColor(BLEU, NOIR);
  5127. TFT.drawString(s1, x, y);
  5128.  
  5129. s1 = valeur_lue;
  5130. TFT.setTextColor(BLANC, NOIR);
  5131. TFT.drawString(s1, x+20, y);
  5132.  
  5133. y+=10;
  5134. }
  5135. }
  5136. Serial.print(nombre); Serial.println(" frequences");
  5137.  
  5138. }
  5139.  
  5140.  
  5141.  
  5142. void GROUPE_FREQUENCES::add_frq(uint32_t Fi) // en RAM uniquement
  5143. {
  5144. Serial.println("--------------------------");
  5145. if (nb_freq >= 100) {return;}
  5146. Serial.println("GROUPE_FREQUENCES::add_frq()");
  5147.  
  5148. if (test_Frq_presente(Fi) == true)
  5149. {
  5150. Serial.println("Frq presente, pas d'ajout");
  5151. return;
  5152. }
  5153. tri_bloc(); // les F nulles se retrouvent en haut
  5154. Serial.print("Ajout frequence: "); Serial.println(Fi);
  5155. G_freq[0] = Fi; // la nouvelle fréquence est placée en haut
  5156. nb_freq++;
  5157. tri_bloc(); // la nouvelle fréquence se retrouve rangée dans l'ordre de F croissantes
  5158. }
  5159.  
  5160.  
  5161.  
  5162. void GROUPE_FREQUENCES::erase_1_freq(uint32_t Fi) // en RAM
  5163. {
  5164. Serial.println("--------------------------");
  5165. Serial.println("GROUPE_FREQUENCES::erase_1_freq()");
  5166. uint32_t valeur_lue;
  5167. for(int n=0; n<100; n++)
  5168. {
  5169. valeur_lue = G_freq[n];
  5170. if(valeur_lue == Fi)
  5171. {
  5172. G_freq[n]=0;
  5173. }
  5174. }
  5175. tri_bloc();
  5176. }
  5177.  
  5178.  
  5179. /** ***************************************************************************************
  5180. CLASS CHF_PAD // boutons invisibles pour incrémenter/décrémenter les chiffres de la fréquence
  5181. ********************************************************************************************/
  5182. // Constructeur
  5183. CHF_PAD::CHF_PAD()
  5184. {
  5185.  
  5186. }
  5187.  
  5188. void CHF_PAD::init()
  5189. {
  5190. for(uint8_t n=0; n<6; n++) //
  5191. {
  5192. bt_pad_H[n].init(x_ch[n], 34, 25, 22, 3, GRIS_3);
  5193. //bt_pad_H[n].affiche(BLANC, 1); // pour visualiser la position des boutons (pour test)
  5194.  
  5195. bt_pad_L[n].init(x_ch[n], 59, 25, 22, 3, GRIS_3);
  5196. //bt_pad_L[n].affiche(BLANC, 1); // pour visualiser la position des boutons (pour test)
  5197. }
  5198.  
  5199. }
  5200.  
  5201.  

Mises à jour quasi-quotidiennes...

Vous trouverez dans le fichier 'documents.zip' au bas de cet article le code source complet ainsi que des fichiers à placer sur la SDcard. Cette carte SD contenant ces fichiers est absolumnent nécessaire au bon fonctionnemant de cet appareil (images, fréquences des touches preset, étalonnage de l'écran tactile...) Ils seront mis à jours lors du fonctionnement de la radio mais ils doivent être présents au préalable.

14 Le fichier d'entêtes main.h

Le fichier main.h :
CODE SOURCE en C++
  1. #include <Arduino.h>
  2.  
  3. #pragma once
  4.  
  5. uint16_t x_ch[6] = {62, 92, 122, 170, 200, 232}; // positions des chiffres et des boutons d'incrémentation attachés
  6.  
  7.  
  8. // pour obtenir ces valeurs simplement, ouvrir une image bmp565 320x240 (ok) avec l'éditeur Hexa ImHex (Linux)
  9. // sélectionner la partie entête, puis File/export/Text Formatted Bytes/C++ Array
  10. // ce qui est vachement pratique !
  11. const uint8_t bmp565_header[] PROGMEM =
  12. {
  13. 0x42, 0x4D, 0x8A, 0x58, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x8A, 0x00, 0x00, 0x00, 0x7C, 0x00,
  14. 0x00, 0x00, 0x40, 0x01, 0x00, 0x00, 0xF0, 0x00, 0x00, 0x00, 0x01, 0x00, 0x10, 0x00, 0x03, 0x00,
  15. 0x00, 0x00, 0x00, 0x58, 0x02, 0x00, 0x23, 0x2E, 0x00, 0x00, 0x23, 0x2E, 0x00, 0x00, 0x00, 0x00,
  16. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF8, 0x00, 0x00, 0xE0, 0x07, 0x00, 0x00, 0x1F, 0x00,
  17. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x42, 0x47, 0x52, 0x73, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  18. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  19. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  20. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00,
  21. 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
  22. };
  23. // soit 138 octets
  24.  
  25.  
  26. /** ***********************************************************************************
  27. CLASS
  28. ***************************************************************************************/
  29.  
  30. class TOUCH_BOUTON
  31. {
  32. protected:
  33. uint8_t dx;
  34. uint8_t dy;
  35. uint8_t dr; // rayon de courbure des angles
  36.  
  37. public:
  38. uint16_t x0;
  39. uint16_t y0;
  40. uint16_t couleur;
  41.  
  42. String label;
  43. boolean cliked;
  44. boolean selected;
  45.  
  46. uint8_t read_dx();
  47. uint8_t read_dy();
  48.  
  49. TOUCH_BOUTON(); // constructeur
  50.  
  51. void init(uint16_t x_i, uint16_t y_i, uint8_t dx_i, uint8_t dy_i, uint8_t dr_i, uint16_t couleur_i);
  52. void affiche(uint16_t coul_fill_select, uint8_t n_font);
  53.  
  54. private:
  55.  
  56. };
  57.  
  58.  
  59.  
  60. class TOUCH_BOUTON_PRESET : public TOUCH_BOUTON
  61. {
  62. public:
  63. uint32_t frequence_SW; // 4 octets
  64. uint32_t frequence_FM; // 4 octets
  65. uint32_t frequence_AIR;// 4 octets
  66. // String nom;
  67.  
  68. TOUCH_BOUTON_PRESET(); // constructeur
  69.  
  70. private:
  71. };
  72.  
  73.  
  74.  
  75. class TOUCH_BOUTON_SW : public TOUCH_BOUTON
  76. {
  77. public:
  78. uint32_t freq_A; // 4 octets - fréquence de départ
  79. uint32_t freq_B; // fréquence de fin de la bande, sans trou
  80. uint16_t lambda; // longueur d'onde en m
  81.  
  82. TOUCH_BOUTON_SW(); // constructeur
  83.  
  84. private:
  85. };
  86.  
  87.  
  88.  
  89. /** ***************************************************************************************
  90. CLASS PRESET_PAD // objet 8 touches d'accès rapide à 8 fréquences favorites adns chaque gamme
  91. ********************************************************************************************/
  92. class PRESET_PAD
  93. {
  94. protected:
  95. uint8_t dx;
  96. uint8_t dy;
  97.  
  98. public:
  99. uint8_t x0;
  100. uint8_t y0;
  101.  
  102. TOUCH_BOUTON_PRESET bt_preset[8];
  103.  
  104. PRESET_PAD(); // constructeur
  105.  
  106. void init(uint16_t x0, uint16_t y0);
  107. uint8_t read_dx();
  108. uint8_t read_dy();
  109. void set_frequences_PRST();
  110. void set_couleurs();
  111.  
  112. void deselect_boutons();
  113. uint8_t test_clic();
  114. //void traite_presetPad(uint8_t n_touch);
  115.  
  116. private:
  117.  
  118. };
  119.  
  120. /** ***************************************************************************************
  121. CLASS SW_PAD // objet 14 boutons de sélection de bandes SW (ondes courtes)
  122. ********************************************************************************************/
  123. class SW_PAD
  124. {
  125. protected:
  126. uint8_t dx;
  127. uint8_t dy;
  128.  
  129. public:
  130. uint8_t x0;
  131. uint8_t y0;
  132.  
  133. TOUCH_BOUTON_SW bt_SW[14];
  134.  
  135. SW_PAD(); // constructeur
  136.  
  137. void init(uint16_t x0, uint16_t y0);
  138. void set_frequences_SW();
  139.  
  140. void deselect_boutons();
  141. uint8_t test_clic();
  142.  
  143. private:
  144.  
  145. };
  146.  
  147. /** ***************************************************************************************
  148. CLASS NUM_PAD // objet clavier numérique
  149. ********************************************************************************************/
  150.  
  151. class NUM_PAD
  152. {
  153. protected:
  154.  
  155.  
  156. public:
  157. uint8_t x0;
  158. uint8_t y0;
  159.  
  160. TOUCH_BOUTON bt_pad[10];
  161.  
  162. TOUCH_BOUTON bt_point;
  163. TOUCH_BOUTON bt_ok;
  164.  
  165. NUM_PAD(); // constructeur
  166.  
  167. void init(uint16_t x0, uint16_t y0, boolean fond);
  168. uint8_t test_clic();
  169.  
  170. private:
  171.  
  172. };
  173.  
  174. /** ***************************************************************************************
  175. CLASS GRID_PAD // objet grille de boutons
  176. ********************************************************************************************/
  177.  
  178. class GRID_PAD
  179. {
  180. protected:
  181.  
  182.  
  183. public:
  184. uint8_t x0;
  185. uint8_t y0;
  186. uint8_t dxt = 16; // taille x d'un bouton
  187. uint8_t dyt = 16; // taille y d'un bouton
  188. static const uint8_t nb_bt_x = 8; // nombre de boutons x
  189. static const uint8_t nb_bt_y = 4; // nombre de boutons y
  190. static const uint8_t nb_t = nb_bt_x * nb_bt_y; //total nombre de boutons
  191.  
  192. TOUCH_BOUTON bt_grid[nb_t];
  193.  
  194. GRID_PAD(); // constructeur
  195.  
  196. void init(uint16_t x0, uint16_t y0);
  197. void set_couleurs();
  198. void affiche();
  199. uint8_t test_clic();
  200.  
  201. private:
  202.  
  203. };
  204.  
  205.  
  206. /** ***************************************************************************************
  207. CLASS CHF_PAD // boutons invisibles pour incrémenter/décrémenter les chiffres de la fréquence
  208. ********************************************************************************************/
  209. class CHF_PAD
  210. {
  211. protected:
  212.  
  213. public:
  214. uint8_t x0;
  215. uint8_t y0;
  216.  
  217. TOUCH_BOUTON bt_pad_H[6]; // boutons dans le haut de chaque chiffre servant à l'incrémenter
  218. TOUCH_BOUTON bt_pad_L[6]; // boutons dans le BAS de chaque chiffre servant à le décrémenter
  219.  
  220. CHF_PAD(); // constructeur
  221.  
  222. void init();
  223. //uint8_t test_clic();
  224.  
  225. private:
  226.  
  227. };
  228.  
  229.  
  230.  
  231.  
  232. /** ***************************************************************************************
  233. CLASS GROUPE_FREQUENCES // objet image d'un bloc mémoire en SD
  234. permet diverses manipulations en RAM (tri...) sans toucher à la mémoire SD (qui est en mémoire flash)
  235. ********************************************************************************************/
  236. class GROUPE_FREQUENCES
  237. {
  238. public:
  239. uint32_t G_freq[100];
  240. 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
  241. uint16_t nb_freq; // nombre de fréquences !=0 enregistées
  242. uint16_t num_F_actuelle;
  243. String filename; // du fichier en mémoire SD (par exemple "/FRQ_FM.txt")
  244.  
  245. GROUPE_FREQUENCES(); // constructeur
  246.  
  247. void RAZ();
  248. void load_bloc(); // depuis SD
  249. void bloc_to_serial(); // pour tests
  250. void affiche_bloc(String nom, uint16_t x);
  251. void tri_bloc(); // par valeur numérique des fréquences
  252. void add_frq(uint32_t Fi);
  253. void erase_1_freq(uint32_t Fi);
  254.  
  255. boolean test_Frq_presente(uint32_t F_i);
  256.  
  257. private:
  258.  
  259. };
  260.  
  261.  
  262. // ************************************************************************************
  263.  
  264.  
  265. void setup();
  266. void loop();
  267. void printTouchToDisplay();
  268. void init_sprites();
  269. void efface_box_entete1();
  270. void efface_box_entete2();
  271. void efface_box_entete3();
  272. void init_affichages();
  273. void affi_image_from_SD(String filename, uint16_t x0, uint16_t y0);
  274. void write_fichier_params();
  275. void load_GRP_FREQ_SD();
  276. String read_line_params(uint16_t line_num);
  277. int32_t extract_params(String ligne, String label);
  278. void affiche_unit(String s);
  279. void affiche_band(String s);
  280. void affiche_numero_frq(String s1, String s2);
  281. void efface_box_entete2();
  282. void efface_box_entete3();
  283. //void affiche_box_choix_couleur();
  284. //void affi_valeurs_RGB();
  285. void affiche_box_FRQ(uint16_t couleur);
  286. void affiche_box_presets();
  287. //void deselect_boutons_presets();
  288. void traite_boutons_presetPad(uint8_t n_bt);
  289. void affi_message(String L1, String L2, String L3, String L4, String L5);
  290. void affiche_box_GROUPE();
  291. void efface_box_GROUPE();
  292. void affiche_box_SD();
  293. void affiche_box_FRQ(uint16_t couleur);
  294. void affiche_frequence(uint32_t frq); // en kHz
  295. //void affiche_index_frq();
  296. void affiche_force_signal();
  297. void clic_logiciel_bouton(TOUCH_BOUTON *bouton_i);
  298. void dessine_VuMetre();
  299. void affi_page_info();
  300. void init_box_info();
  301. void test_clic_boutons_BANDE();
  302. void test_clic_bouton_TEST();
  303. //void read_FRQ_File(); // en mémoire SD
  304. void scan_frq(uint32_t freq_iA, uint32_t freq_iB, String band_name);
  305. void attente_clic();
  306. void attente_clic2();
  307. void Set_Volume(int v);
  308. void get_XY_touch();
  309. void TS_calibrate();
  310. //void liste_codes_PI_RDS();
  311. void retour_normal();

15 documents

Code source complet en C++
Version du code source adaptée à l’éditeur VScode/PlatformIO

Vous trouverez dans ce fichier 'documents.zip' le code source complet ainsi que des fichiers à placer sur la SDcard. Cette carte SD contenant ces fichiers est absolumnent nécessaire au bon fonctionnemant de cet appareil (images, fréquences des touches preset, étalonnage de l'écran tactile...) Ils seront mis à jours lors du fonctionnement de la radio mais ils doivent être présents au préalable.

16 -

Liens...
Pour me joindre : silicium628@free.fr
Un site complémentaire à celui-ci ; Electro & Robot

1513