/* ************************************************************************************
Radio TEF6686
pour la carte CYD (Cheap Yellow Display) ESP32 Wroom + afficheur 2.8" TFT 240x320
par Silicium628
CONCERNANT L'AFFICHAGE TFT
à placer dans le fichier User_Setup.h ( dans ~/Arduino/libraries/TFT_eSPI/ ):
#define ILI9341_2_DRIVER
************************************************************************************ */
#include <Arduino.h>
String version = "20.3";
#include "main.h"
#include "constantes_628.h"
#include "DSP_INIT_628.h"
#include "driverTEF6686_628.h"
#include <Free_Fonts.h>
#include "FS.h"
#include "SD.h"
#include "Wire.h"
#include <stdint.h>
#include "TFT_eSPI.h" // Hardware-specific library
#include "SPI.h"
#include "Free_Fonts.h"
#include "Digit_Font.h"
#include <XPT2046_Touchscreen.h>
#include <EEPROM.h>
// #define _SD_CARD // décommenter cette ligne pour utiliser une SDcard; commenter pour utiliser le Touchscreen
#define SPI_READ_FREQUENCY 16000000
// mem presets[EE_PRESETS_CNT];
#define EEPROM_SIZE 100+2000 //100 premiers bytes réservés, puis 5 groupes de 400 bytes = 100 + 2000 = 2100
#define EEPROM_adrs_couleur 0 // 2 octets pour un uint16_t
#define EEPROM_adrs_freq 2 // 4 octets pour un uint32_t
#define EEPROM_adrs_mode 6 // 1 octet pour un uint8_t
// 100 premiers bytes réservés pour sauvegarder diverses variables (Frq en cours par exemple...)
// reste 1200 bytes
// chaque fréquence est un uint_32 = 4 bytes
// 1200/4 = 300 fréquences mémorisée, c.a.d 3 bandes (SW, FM, AIR) de 100 freq chaque
// Remarque : il y a largement la possibilité d'en prévoir beaucoup plus !!
#define bande_SW (frequence > 1500) && (frequence < 28000)
#define bande_interdite1 (frequence > 28000) && (frequence < 88000)
#define bande_interdite2 (frequence > 108000) && (frequence < 118000)
#define bande_FM (frequence >= 88000) && (frequence < 108000)
#define bande_AIR (frequence >= 118000) && (frequence < 138000)
// XPT2046_Touchscreen // commenter cette ligne pour utiliser la fontion 'write_TFT_on_SDcard()'
#define XPT2046_IRQ 36
#define XPT2046_MOSI 32
#define XPT2046_MISO 39
#define XPT2046_CLK 25
#define XPT2046_CS 33
//sur le connecteur CN1 de la carte CYD sérigraphiée 'ESP32-2432S028';
//attention: ces valeurs ne sont pas celles par défaut pour SDA et SCL
const int GPIO_SDA = 27;
const int GPIO_SCL = 22;
const int analogPin = 35;
#define High_16bto8b(a) ((uint8_t)((a) >> 8))
#define Low_16bto8b(a) ((uint8_t)(a ))
#define Convert8bto16b(a) ((uint16_t)(((uint16_t)(*(a))) << 8 |((uint16_t)(*(a+1)))))
SPIClass mySpi = SPIClass(VSPI);
XPT2046_Touchscreen ts(XPT2046_CS, XPT2046_IRQ);
TFT_eSPI TFT = TFT_eSPI(); // Configurer le fichier User_Setup.h de la bibliothèque TFT_eSPI au préalable
TFT_eSprite sprite_frq = TFT_eSprite(&TFT);
//TFT_eSprite sprite_unit = TFT_eSprite(&TFT);
// pour afficheur TFT
const int _DX = 320;
const int _DY = 240;
float raddeg = M_PI/180.0;
float deg_to_rad = 2.0 * M_PI /360.0;
//***************************************************************************
//char var_array32[10];// 10 char + zero terminal - pour envoi par WiFi (because 2^32 -1 = 4294967295 -> 10 caractères)
// =====================================================================
TFT_eSprite Sprite_frq = TFT_eSprite(&TFT);
// la def de 'TFT_eSprite' se trouve dans ~/Arduino/libraries/TFT_eSPI/Extensions/Sprite.h
boolean test_touch_screen = false; // mettre true pour activer le test (qui est une boucle infinie au démarrage...)
// voir la foncion 'loop()'
uint16_t compteur1 = 0;
uint16_t compteur2 = 0;
uint16_t compteur3 = 0;
uint8_t SDcardOk=0;
uint8_t do_wr_ecran_on_sd=0;
uint32_t frequence=10000;
uint32_t saut_freq;
uint16_t seuil = 500;
uint16_t memo_seuil = 500;
//uint32_t image_EE[300]; // permet le tri en RAM des fréquences sans toucher à l'EEPROM
GROUPE_FREQUENCES groupe_SW;
GROUPE_FREQUENCES groupe_FM;
GROUPE_FREQUENCES groupe_AIR;
GROUPE_FREQUENCES groupe_SCAN;
uint32_t frq_preset_SW[8]; // 8 fréquences attribuées aux boutons [preset1] à [preset8] soit 8x4=32 octets
uint32_t frq_preset_FM[8]; // 8 fréquences attribuées aux boutons [preset1] à [preset8] soit 8x4=32 octets
uint32_t frq_preset_AIR[8];// 8 fréquences attribuées aux boutons [preset1] à [preset8] soit 8x4=32 octets total 32*3 = 96 octets
uint32_t memo_frequence_scan;
uint16_t frq_preset_adr_0;
String frequence_txt = "";
TOUCH_BOUTON bt_sleep;
TOUCH_BOUTON bt_mode_FRQ, bt_mode_MEM;
TOUCH_BOUTON bt_plus, bt_moins;
TOUCH_BOUTON bt_EE_RAZ, bt_EE_write, bt_erase_1F;
TOUCH_BOUTON bt_1, bt_2, bt_3, bt_4, bt_5, bt_6; // au dessus des chiffres de la fréquence
TOUCH_BOUTON bt_affi_saisie_couleur;
TOUCH_BOUTON bt_coul_to_EEPROM;
TOUCH_BOUTON bt_scan_frq, bt_scan_air;
TOUCH_BOUTON bt_RST_affi; // "ok"
//TOUCH_BOUTON bt_close1; // "x"
TOUCH_BOUTON bt_LEV, bt_SNR, bt_re_scan, bt_scan_suivant;
TOUCH_BOUTON bt_seuil_plus, bt_seuil_moins;
// ---------- numPad ------------
TOUCH_BOUTON bt_num0, bt_num1, bt_num2, bt_num3, bt_num4, bt_num5, bt_num6, bt_num7, bt_num8, bt_num9;
NUM_PAD numPad1;
// ---------- presetPad1 ------------
PRESET_PAD presetPad1;
// -------------------------------
TOUCH_BOUTON bt_SW, bt_FM, bt_AIR, bt_SCN;
TOUCH_BOUTON bt_mute;
TOUCH_BOUTON bt_reset;
TOUCH_BOUTON bt_stop_scan;
TOUCH_BOUTON bt_set; // attribtion d'une fréquence à un des 8 boutons preset
TOUCH_BOUTON bt_annuler; // "x"
boolean mute;
boolean vu_metre_actif;
enum MODE_AFFI {COUL, NORMAL, SCAN_F, SCAN_M, SET_F_PRESET}; //[couleur], [normal], [scan], [set 1F pour 1Bt]
MODE_AFFI mode_affi;
enum MODE_SELECT {_FRQ=0, _MEM=1} mode_s; // mode de mofif fréquence, en tapant les chiffres /ou en mémoire
//MODE_SELECT mode_s;
//#define _FRQ 0
//#define _MEM 1
//uint8_t mode_s; // _FRQ ou _MEM
enum MODUL {AM, WFM};
MODUL modulation_active;
enum BANDE {SW, FM, AIR, SCN}; // la bande SCN mémorise le résultat d'un scan FREQUENCE
BANDE bande_active;
enum MODE_SCAN {FREQUENCE, MEMOIRE};
MODE_SCAN mode_scan;
enum MODE_SEUIL {LEV, SNR}; // level ou signal/bruit
MODE_SEUIL mode_seuil;
uint16_t FRQ_x0;
uint16_t FRQ_y0;
uint16_t x0_box_EEPROM;
uint16_t y0_box_EEPROM;
uint16_t x0_box_PRESET;
uint16_t y0_box_PRESET;
uint16_t x0_box_GROUPE; // SW - FM - AIR
uint16_t y0_box_GROUPE;
uint16_t x0_box_boutons_scan;
uint16_t y0_box_boutons_scan;
uint16_t x0_box_SCAN; // grande surface d'affichage
uint16_t y0_box_SCAN;
uint16_t dx_box_SCAN;
uint16_t dy_box_SCAN;
uint16_t x0_numPad;
uint16_t y0_numPad;
uint16_t x0_vu_metre;
uint16_t y0_vu_metre;
uint16_t x0_box_info1;
uint16_t y0_box_info1;
uint16_t x0_box_info2 = x0_vu_metre;
uint16_t y0_box_info2 = y0_vu_metre;
uint16_t dx_box_info2;
uint16_t dy_box_info2;
uint16_t x0_saisie;
uint16_t y0_saisie;
uint16_t x0_choix_couleur;
uint16_t y0_choix_couleur;
uint8_t n_appui; // incrémenté à chaque appui sur une touche du numPad numérique
uint32_t total_saisi;
uint16_t x_touch, y_touch;
uint16_t status;
int16_t level;
uint16_t usn;
uint16_t wam;
int16_t offset;
uint16_t bandwidth;
uint16_t mod;
int8_t snr;
uint16_t A_block;
uint16_t B_block;
uint16_t C_block;
uint16_t D_block;
uint16_t dec_error;
float position_aiguille; // vu-metre
float valeur_affi;
float memo_valeur_affi;
float ltx; // aiguille
uint16_t osx;
uint16_t osy;
uint16_t couleur_traits = GRIS_5;
uint16_t JAUNE_chiffres = 65504;
uint16_t VERT_chiffres = 2016;
uint8_t cR = 0;
uint8_t cG = 0;
uint8_t cB = 0;
uint16_t couleur_fond_ecran = 0;
float degTOrad(float angle)
{
return (angle * M_PI / 180.0);
}
uint8_t decToBcd( int val )
{
return (uint8_t) ((val / 10 * 16) + (val % 10));
}
uint16_t Color_To_565(uint8_t r, uint8_t g, uint8_t b)
{
return ((r & 0xF8) << 8) | ((g & 0xFC) << 3) | ((b & 0xF8) >> 3);
}
void RGB565_to_888(uint16_t color565, uint8_t *R, uint8_t *G, uint8_t *B)
{
*R=(color565 & 0xF800) >> 8;
*G=(color565 & 0x7E0) >> 3;
*B=(color565 & 0x1F) << 3 ;
}
/** ***********************************************************************************
CAPTURE D'ECRAN vers SDcard
**************************************************************************************
ATTENTION : cette fonction est simultanément incompatible avec la fonction tactile (TOUCHSCREEN) de l'afficheur
pour des raisons d'attribution des bus spi.(il n'y a que deux bus SPI personnalisés DISPONIBLES sur
les 4 de l'ESP32 (2 sont à usage interne),
il en manque donc un troisième !)
SCREEN SPI : (tel que défini dans le fichier User_Setup.h)
TFT_MISO GPIO 12 // don't define this pin when using Touch and SD Card on the CYD
TFT_MOSI GPIO 13
TFT_SCLK GPIO 14
TFT_CS GPIO 15 // Chip select control pin
TFT_DC GPIO 2 // Data Command control pin
TFT_RST GPIO 4 // Reset pin (could connect to RST pin)
TFT_RST -1 // Set TFT_RST to -1 if display RESET is connected to ESP32 board RST
TOUCHSCREEN SPI :
IRQ (XPT2046_IRQ) GPIO 36
MOSI (XPT2046_MOSI) GPIO 32
MISO (XPT2046_MISO) GPIO 39
CLK (XPT2046_CLK) GPIO 25
CS (XPT2046_CS) GPIO 33
MicoSD card SPI :
MISO GPIO 19
MOSI GPIO 23
SCK GPIO 18
CS GPIO 5
Il est possible de partager un même bus SPI entre plusieurs composants, (one master and multi slaves)
mais ce n'est pas ce qui a été fait par les concepteurs de la CYD.
Les deux bus internes sont utilisés, il n'en reste plus de disponible.
voir l'URL très simple(!) suivante :
https://medium.com/@androidcrypto/how-to-use-touch-and-sd-card-at-the-same-time-on-an-esp32-cheap-yellow-display-cyd-45fa55d01ffe
*/
void init_variables_globales()
// je ne les initialise pas lors de leur déclaration sinon lors d'un reset logiciel (appel de la fonction 'setup()'
// par le boouton 'RST') elles ne seraient pas réinitialisées
{
mode_affi = NORMAL;
bande_active = FM;
modulation_active = WFM;
mode_s = _MEM;
mode_scan = FREQUENCE;
mode_seuil = LEV;
mute = false;
vu_metre_actif = true;
FRQ_x0 = 50;
FRQ_y0 = 30;
x0_box_EEPROM = 2;
y0_box_EEPROM = 150;
x0_box_PRESET =2;
y0_box_PRESET =87;
x0_box_GROUPE = 205; // SW - FM - AIR
y0_box_GROUPE = 115;
x0_box_boutons_scan = 2;
y0_box_boutons_scan = 105;
x0_box_SCAN = 2; // grande surface d'affichage
y0_box_SCAN = 90;
dx_box_SCAN = 315;
dy_box_SCAN = 148;
x0_numPad = 70;
y0_numPad = 115;
x0_vu_metre = 170;
y0_vu_metre = 145;
x0_box_info1 = 71;
y0_box_info1 = 220;
x0_box_info2 = x0_vu_metre;
y0_box_info2 = y0_vu_metre;
dx_box_info2 = 140;
dy_box_info2 = 70;
x0_saisie = 3;
y0_saisie = 0;
x0_choix_couleur = 170;
y0_choix_couleur = 145;
n_appui = 0; // incrémenté à chaque appui sur une touche du numPad numérique
total_saisi = 0;
position_aiguille = 0; // vu-metre
valeur_affi = 0;
memo_valeur_affi = 0;
ltx = 0; // aiguille
osx = x0_vu_metre;
osy = y0_vu_metre;
}
void init_SDcard()
{
Serial.println("init_SDcard()");
if(!SD.begin())
{
Serial.println("Card Mount Failed");
delay (1000);
return;
}
uint8_t cardType = SD.cardType();
if(cardType == CARD_NONE)
{
Serial.println("No SDcard");
delay (1000);
return;
}
SDcardOk=1;
Serial.print("SDcard Type: ");
if(cardType == CARD_SD) { Serial.println("SDSC"); }
else if(cardType == CARD_SDHC) { Serial.println("SDHC"); }
uint32_t cardSize = SD.cardSize() / (1024 * 1024);
String s1=(String)cardSize + " GB";
Serial.print("SDcard size: ");
Serial.println(s1);
delay (1000);
Serial.println("FIN init_SDcard()");
}
// Fonction optimisée pour la carte CYD 320x240px avec la library 'TFT_eSPI'
// ne convient PAS pour les ESP32 Wroom + afficheur 3.5" TFT 480x320
void write_TFT_on_SDcard() // enregistre image bmp 320x240 RGB888
{
do_wr_ecran_on_sd =0;
if (SDcardOk==0) {return;}
int32_t x, y;
uint16_t color565;
uint8_t octet_A;
uint8_t octet_B;
if( ! SD.exists("/bmp/320x240_565.bmp")) {return;}
File File1 = SD.open("/bmp/320x240_565.bmp", FILE_WRITE); // ouverture du fichier binaire (vierge) en écriture
if (File1)
{
/*
Les images en couleurs réelles BMP888 utilisent 24 bits par pixel:
Il faut 3 octets pour coder chaque pixel, en respectant l'ordre de l'alternance bleu, vert et rouge.
*/
uint16_t bmp_offset = 138;
File1.seek(bmp_offset);
TFT.setFreeFont(FF0);
TFT.setTextSize(1);
TFT.setTextColor(JAUNE, NOIR);
for (y=240; y>0; y--)
{
for (x=0; x<320; x++)
{
color565=TFT.readPixel(x, y); // BBBBBrrr rrrVVVVV
octet_B = (color565 & 0b1111111100000000) >> 8;
octet_A = (color565 & 0b0000000011111111);
File1.write(octet_A);
File1.write(octet_B);
}
String s1=String(y/10); TFT.drawString(s1, 170, 115); // affiche compte à rebour
}
File1.close(); // referme le fichier
TFT.fillRect(170, 115, 20, 8, GRIS_2); // efface le compte à rebours
}
}
// ***********************************************************************************************************
void affiche_index_frq() // 6 petits boutons juste au dessus de chaque chiffre pour indiquer celui à modifier
{
int x = FRQ_x0 +15;
int y = FRQ_y0 - 5;
uint16_t c1 = NOIR;
uint16_t c2 = VERT;
bt_1.init(x, y, 20, 5, 0); bt_1.affiche(c1, c2, 1); x+=31;
bt_2.init(x, y, 20, 5, 0); bt_2.affiche(c1, c2, 1); x+=31;
bt_3.init(x, y, 20, 5, 0); bt_3.affiche(c1, c2, 1); x+=46;
bt_4.init(x, y, 20, 5, 0); bt_4.affiche(c1, c2, 1); x+=31;
bt_5.init(x, y, 20, 5, 0); bt_5.affiche(c1, c2, 1); x+=31;
bt_6.init(x, y, 20, 5, 0); bt_6.affiche(c1, c2, 1);
}
void init_boutons_Plus_Moins()// boutons '<' et '>'
{
int x0 = 240;
int y0 = 90;
uint16_t c1 = GRIS_6;
uint16_t c2 = JAUNE;
bt_moins.init(x0, y0, 30, 15, 1);
bt_moins.cliked = false;
bt_moins.s=" <";
bt_plus.init(x0+35, y0, 30, 15, 1);
bt_plus.cliked = false;
bt_plus.s=" >";
}
// bt_SW
// bt_FM
// bt_AIR
void init_boutons_GROUPE() // groupe de fréquence (SW - FM - AIR - SCAN)
{
uint16_t x = x0_box_GROUPE+4;
uint16_t y = y0_box_GROUPE+5;
TFT.setFreeFont(FF0);
bt_SW.init(x, y, 20, 15, 3);
bt_SW.cliked = false;
bt_SW.selected = false;
bt_SW.s="SW";
x+=25;
bt_FM.init(x, y, 20, 15, 3);
bt_FM.cliked = false;
bt_FM.selected = false;
bt_FM.s="FM";
x+=25;
bt_AIR.init(x, y, 22, 15, 3);
bt_AIR.cliked = false;
bt_AIR.selected = false;
bt_AIR.s="AIR";
x+=27;
bt_SCN.init(x, y, 20, 15, 3);
bt_SCN.cliked = false;
bt_SCN.selected = false;
bt_SCN.s="SC";
}
void init_1_bouton(uint16_t xi, uint16_t yi, uint8_t dx, uint8_t dy, String si, TOUCH_BOUTON *bouton_i)
{
uint16_t c1 = GRIS_5;
uint16_t c2 = BLANC;
bouton_i->init(xi, yi, dx, dy, 3);
bouton_i->cliked = false;
bouton_i->selected = false;
bouton_i->s = si;
bouton_i->affiche(c1, c2, 1);
}
//init_1_bouton(202, 222, 32, 15, "", &);
void init_boutons_MODE()
{
uint16_t c1 = NOIR;
uint16_t c2 = VERT;
TFT.setFreeFont(FF0);
TFT.setTextColor(GRIS_3, NOIR);
TFT.drawString("mode", 6, 17);
TFT.drawFastVLine(45, 15, 72, couleur_traits);
bt_mode_FRQ.init(5, 35, 37, 20, 2);
bt_mode_FRQ.selected = false;
bt_mode_FRQ.s="FRQ";
bt_mode_FRQ.affiche(c1, c2, 2);
bt_mode_MEM.init(5, 60, 37, 20, 2);
bt_mode_MEM.selected = true;
bt_mode_MEM.s="MEM";
bt_mode_MEM.affiche(c1, c2, 2);
affiche_index_frq();
}
void affiche_1_bt_RGB(TOUCH_BOUTON *bouton_i, uint16_t x, uint16_t y, uint8_t dx, uint16_t couleur, String s_i)
{
uint16_t c1 = couleur;
uint16_t c2 = JAUNE;
bouton_i->init(x, y, dx, 14, 3);
bouton_i->cliked = false;
bouton_i->selected = false;
bouton_i->s = s_i;
bouton_i->affiche(c1, c2, 1);
}
void init_sprites()
{
sprite_frq.createSprite(220, 55);
sprite_frq.loadFont(digitfont1);
sprite_frq.setTextColor(JAUNE_2, NOIR);
sprite_frq.setTextDatum(MR_DATUM); // alignement du texte
}
void Tuner_Reset(void)
{
Wire.beginTransmission(0x64);
Wire.write(0x1e);
Wire.write(0x5a);
Wire.write(0x01);
Wire.write(0x5a);
Wire.write(0x5a);
Wire.endTransmission();
}
bool Tuner_Table_Write(const unsigned char *tab)
{
if (tab[1] == 0xff)
{
delay(tab[2]);
return 1;
}
else { return Tuner_WriteBuffer((unsigned char *)&tab[1], tab[0]); }
}
void Tuner_Init(const unsigned char *table)
{
uint16_t r;
const unsigned char *p = table;
for (uint16_t i = 0; i < sizeof(tuner_init_tab9216); i += (pgm_read_byte(p + i) + 1))
{
if (1 != (r = Tuner_Table_Write(p + i))) break;
}
}
void Tune_Frequence(uint32_t F)
{
TFT.setFreeFont(FF0);
TFT.setTextColor(BLEU, NOIR);
String s1 = String(F);
TFT.drawString(s1, 80, 2);
if (F == 1500)
{
efface_box_entete3();
//TFT.fillRect(130, 1, 70, 12, NOIR); // efface
TFT.setTextColor(ROUGE, NOIR);
TFT.drawString("MINIMUM ", 130, 2);
}
if (bande_SW)
{
modulation_active = AM;
Tune_Frequence_AM(F);
efface_box_entete3();
//TFT.fillRect(130, 1, 70, 12, NOIR); // efface
TFT.setTextColor(VERT, NOIR);
TFT.drawString("SW ", 130, 2);
}
if (bande_interdite1)
{
//Tune_Frequence_AM(F);
efface_box_entete3();
//TFT.fillRect(130, 1, 70, 12, NOIR); // efface
TFT.setTextColor(ROUGE, NOIR);
TFT.drawString("NON DISPONIBLE", 130, 2);
//bt_SW.selected = false;
//bt_FM.selected = false;
//bt_AIR.selected = false;
}
if (bande_FM)
{
modulation_active = WFM;
Tune_Frequence_FM(F/10);
efface_box_entete3();
//TFT.fillRect(130, 1, 70, 12, NOIR); // efface
TFT.setTextColor(VERT, NOIR);
TFT.drawString("bande FM", 130, 2);
}
if (bande_interdite2)
{
//Tune_Frequence_AM(F);
efface_box_entete3();
//TFT.fillRect(130, 1, 70, 12, NOIR); // efface
TFT.setTextColor(ROUGE, NOIR);
TFT.drawString("NON DISPONIBLE", 130, 2);
//bt_SW.selected = false;
//bt_FM.selected = false;
//bt_AIR.selected = false;
}
if (bande_AIR)
{
modulation_active = AM;
Tune_Frequence_AM(F-110000); // nécessite un convertisseur de fréquence 110MHz en entrée antenne
efface_box_entete3();
//TFT.fillRect(130, 1, 70, 12, NOIR); // efface
TFT.setTextColor(BLEU_CLAIR, NOIR);
TFT.drawString("AIR BAND", 130, 2);
}
if (F == 138000)
{
//TFT.fillRect(130, 1, 40, 12, NOIR); // efface
efface_box_entete3();
TFT.setTextColor(ROUGE, NOIR);
TFT.drawString("F MAX ", 130, 2);
}
}
void load_GRP_FREQ_EEPROM()
{
Serial.println("--- Frequences lues en EEPROM ---------------");
Serial.println(" ");
Serial.println("GROUPE SW");
groupe_SW.load_bloc(); // EEPROM -> RAM
groupe_SW.tri_bloc(); // en RAM
groupe_SW.bloc_to_serial();
Serial.println("---------------------------------------------");
Serial.println("GROUPE FM");
groupe_FM.load_bloc(); // EEPROM -> RAM
groupe_FM.tri_bloc(); // en RAM
groupe_FM.bloc_to_serial();
Serial.println("---------------------------------------------");
Serial.println("GROUPE AIR");
groupe_AIR.load_bloc(); // EEPROM -> RAM
groupe_AIR.tri_bloc(); // en RAM
groupe_AIR.bloc_to_serial();
Serial.println("---------------------------------------------");
// remarque : le groupe SCAN n'est jamais enregistré en EEPROM
}
uint16_t brightness(uint16_t couleur)
{
uint8_t r, g, b;
r = 0xFF & (couleur >> 16);
g = 0xFF & (couleur >> 8);
b = 0xFF & couleur;
return ( r + g + b );
}
void init_affichages()
{
//TFT.fillScreen(NOIR);
TFT.fillRect(0, 14, 319, 230, couleur_fond_ecran);
if (brightness(couleur_fond_ecran) > 500) {couleur_traits = NOIR;} else {couleur_traits = BLANC;}
TFT.setTextColor(JAUNE, NOIR);
TFT.drawRect(0, 0, 319, 240, couleur_traits); // cadre principal pourtour de l'écran
TFT.setFreeFont(FF0);
TFT.setTextColor(BLANC, BLEU);
String s1 = "v:" + version;
TFT.drawString(s1, 45, 15);
init_sprites();
while (!Serial && (millis() <= 1000));
init_boutons_MODE();
affiche_box_EEPROM();
init_1_bouton(x0_box_EEPROM+4, y0_box_EEPROM+16, 40, 15, "Raz", &bt_EE_RAZ);
init_1_bouton(x0_box_EEPROM+4, y0_box_EEPROM+33, 40, 15, "Write", &bt_EE_write);
TFT.setFreeFont(FF0);
init_boutons_Plus_Moins();
init_boutons_GROUPE(); // (SW - FM - AIR - SC)
init_1_bouton(5, 220, 40, 14, "Sleep", &bt_sleep);
init_1_bouton(237, 222, 30, 15, "RST", &bt_reset);
init_1_bouton(202, 222, 32, 15, "Mute", &bt_mute);
affiche_box_boutons_scan();
init_1_bouton(5, 118, 55, 15, "scan FRQ", &bt_scan_frq);
init_1_bouton(5, 135, 55, 15, "scan AIR", &bt_scan_air);
init_1_bouton(168, 97, 30, 15, "set", &bt_set);
init_1_bouton(x0_box_EEPROM+4, y0_box_EEPROM+33, 40, 15, "Write", &bt_EE_write);
init_1_bouton(x0_box_EEPROM+4, y0_box_EEPROM+50, 40, 15, "raz 1F", &bt_erase_1F);
numPad1.init(x0_numPad, y0_numPad, true);
affiche_box_presets(); // conteneur des 8 petits boutons
presetPad1.init(x0_box_PRESET +5, y0_box_PRESET +5);
efface_box_entete2();
efface_box_entete3();
init_box_info();
affiche_box_FRQ(GRIS_3); // autour de la fréquence (gros chiffres JAUNE ou VERT)
//init_boutons_presets();
if (mode_affi == NORMAL)
{
affiche_box_GROUPE();
bt_moins.affiche(GRIS_6, VERT ,1);
bt_plus.affiche(GRIS_6, VERT ,1);
bt_SW.affiche(GRIS_5, VERT, 1);
bt_FM.affiche(GRIS_5, VERT, 1);
bt_AIR.affiche(GRIS_5, VERT, 1);
bt_SCN.affiche(GRIS_5, VERT, 1);
}
bt_4.selected = true;
bt_4.cliked = true;
bt_4.affiche(NOIR, GRIS_2,1);
bt_mute.selected = false;
bt_mute.cliked = false;
bt_mute.affiche(NOIR, ROUGE, 1);
bt_sleep.affiche(NOIR, VERT, 1);
bt_reset.affiche(NOIR, VERT, 1);
affiche_frequence(frequence);
dessine_VuMetre();
init_1_bouton(268, 222, 50, 15, "Couleur", &bt_affi_saisie_couleur);
bt_affi_saisie_couleur.affiche(NOIR, VERT, 1);
}
void setup()
{
Serial.begin(115200);
init_variables_globales();
#ifdef _SD_CARD
init_SDcard(); // attention : incompatible avec le TOUCHPAD
//sauf modifs hard ou autre driver affi. Voir liens sur mon site.
#endif
Wire.begin(GPIO_SDA, GPIO_SCL, 100000);
Serial.println("display.init()");
#ifndef _SD_CARD
// Start the SPI for the touch screen and init the TS library
// attention : incompatible avec SD_card, sauf modifs hard ou autre driver affi. Voir liens sur mon site.
mySpi.begin(XPT2046_CLK, XPT2046_MISO, XPT2046_MOSI, XPT2046_CS);
ts.begin(mySpi);
ts.setRotation(3);
#endif
TFT.init();
TFT.setRotation(3); // 0..3 à voir, suivant disposition de l'afficheur et sa disposition
TFT.fillScreen(NOIR);
TFT.setTextColor(BLANC, NOIR);
TFT.setFreeFont(FF1);
uint16_t y=0;
Serial.println("Radio TEF6686");
TFT.drawString("Radio TEF6686", 0, y); y+=20;
String s1="version " + version;
TFT.drawString(s1, 0, y); y+=20;
TFT.drawString("Silicium628", 0, y); y+=40;
TFT.setFreeFont(FF0);
TFT.drawString("SW (AM) 1500kHz -- 28MHz", 0, y); y+=20;
TFT.drawString("bande FM (WFM) 88MHz -- 108MHz", 0, y); y+=20;
TFT.drawString("Civil Air band(AM) 118MHz -- 137MHz", 0, y); y+=20;
delay(1000);
// adresses physiques des blocs en EEPROM:
groupe_SW.adr_0 = 100; // je réserve les 100 premiers octets (0..99) pour des paramètres divers
groupe_FM.adr_0 = groupe_SW.adr_0 +400; // donc =500 (chaque fréquence occupe 4 octets (uint_32t))
groupe_AIR.adr_0 = groupe_FM.adr_0 +400; // donc =900
groupe_SCAN.adr_0 = groupe_AIR.adr_0 +400; //donc =1300
frq_preset_adr_0 = groupe_SCAN.adr_0 +400; // donc 1700
// addr de fin pour l'EEPROM = 1700 + 96 = 1796
// la limite physique (constatée) d'utilisation de cette "fausse" EEPROM (voir doc) se situe vers 11kB
groupe_SCAN.RAZ();
EEPROM.begin(EEPROM_SIZE); // <<< EEPROM - ATTENTION : tenir à jour la valeur EEPROM_SIZE au debut de ce code
presetPad1.set_frequences();
presetPad1.set_couleurs();
couleur_fond_ecran = EEPROM.readShort(0); // 2 octets = 16 bits
frequence = EEPROM.readUInt(EEPROM_adrs_freq); // 4 octets = 32 bits
//Serial.print("mode_s LU en EEPROM: "); Serial.println(mode_s);
boolean vu_metre_actif = true;
TFT.fillScreen(NOIR);
init_affichages();
Serial.println("---------------------------------------------");
saut_freq = 100;
Tuner_Init(tuner_init_tab9216);
//Serial.println(" ");
/*
The TEF668X consists of four modules:
-module 32 : FM = FM radio reception
-module 33 : AM = LW, MW and SW radio reception
-module 48 : AUDIO = Audio processing
-module 64 : APPL = System and application control
*/
load_GRP_FREQ_EEPROM();
Set_no_AM_gain_reduction();
byte md_s = EEPROM.readByte(EEPROM_adrs_mode); // 1 octet
if(md_s == _FRQ) {bt_mode_FRQ.selected = true; bt_mode_MEM.selected = false;} // bt en haut à gauche
if(md_s == _MEM) {bt_mode_FRQ.selected = false; bt_mode_MEM.selected = true;} // bt en haut à gauche
uint16_t c1 = GRIS_6;
uint16_t c2 = VERT;
uint16_t c3 = JAUNE;
bt_mode_FRQ.affiche(c1, c2, 2); // bt en haut à gauche
bt_mode_MEM.affiche(c1, c3, 2); // bt en haut à gauche
bt_FM.cliked = true;
bt_FM.selected = true;
bande_active = FM;
modulation_active = WFM;
frequence = presetPad1.bt_preset[0].frequence_FM;
affiche_frequence(frequence);
Tune_Frequence(frequence);
Set_Volume(+60);
delay(100);
//clic_logiciel_bouton(&bt_mode_MEM);
mode_s = _MEM;
bt_mode_MEM.selected = true;
bt_mode_FRQ.selected = false;
//affiche_frequence(frequence);
Serial.print("------------- FIN DU SETUP -----------------");
// FIN DU SETUP
}
void printTouchToDisplay()
{
TFT.fillScreen(NOIR);
TFT.setFreeFont(FM9);
TFT.setTextColor(VERT, NOIR);
TFT.drawString("TEST TOUCH SCREEN", 80, 120);
while(1)
{
if (ts.tirqTouched() && ts.touched())
{
TS_Point p = ts.getPoint();
// ajuster les paramètres ici et penser à les mettre à jour dans la fonction 'loop()'
x_touch = -30 + p.x /11; // -30 11
y_touch = -30 + p.y /14; // -30 14
TFT.drawRect(x_touch, y_touch, 1, 1, JAUNE);
// affiche force d'appui du stylet
/*
//int x = 320 / 2; // center of display
//int y = 100;
//int fontSize = 2;
//String temp = "P= " + String(p.z);
//TFT.drawCentreString(temp, x, y, fontSize);
*/
}
}
}
// -------------------------------------------------------------------------
// Le vu-metre est une variante perso du code : "/Arduino/libraries/TFT_eSPI/examples/480 x 320/TFT_Meters"
// voir le fichier licence.txt dans le dossier "/Arduino/libraries/TFT_eSPI/examples/"
void dessine_VuMetre()
{
if (vu_metre_actif == false) {return;}
uint16_t x0 = x0_vu_metre;
uint16_t y0 = y0_vu_metre;
uint16_t dx=140;
uint16_t dy=70;
uint8_t AA = 65; // 65
uint8_t BB = x0 +dx/2;// 120
uint8_t CC = y0 + dy+20; // 140
TFT.setFreeFont(FF0);
// cadre rectangulaire
TFT.fillRect(x0, y0, dx, dy, GRIS_3);
TFT.fillRect(x0+3, y0+3, dx-6, dy-6, BLANC);
TFT.setTextColor(NOIR);
// graduation chaque 5 deg entre -50 et +50 deg
for (int i = -50; i < 51; i += 10)
{
int tl = 5; // tiret plus long
// Coordonnées du tiret à dessiner
float sx = cos((i - 90) * deg_to_rad);
float sy = sin((i - 90) * deg_to_rad);
uint16_t tx0 = sx * (AA + tl) + BB;
uint16_t ty0 = sy * (AA + tl) + CC;
uint16_t tx1 = sx * AA + BB;
uint16_t ty1 = sy * AA + CC;
float sx2 = cos((i + 5 - 90) * deg_to_rad);
float sy2 = sin((i + 5 - 90) * deg_to_rad);
int tx2 = sx2 * (AA + tl) + BB;
int ty2 = sy2 * (AA + tl) + CC;
int tx3 = sx2 * AA + BB;
int ty3 = sy2 * AA + CC;
// zone verte
if (i >= 0 && i < 25)
{
TFT.fillTriangle(tx0, ty0, tx1, ty1, tx2, ty2, VERT);
TFT.fillTriangle(tx1, ty1, tx2, ty2, tx3, ty3, VERT);
}
// zone orange
if (i >= 25 && i < 50)
{
TFT.fillTriangle(tx0, ty0, tx1, ty1, tx2, ty2, ORANGE);
TFT.fillTriangle(tx1, ty1, tx2, ty2, tx3, ty3, ORANGE);
}
if (i % 25 != 0) tl = 8;
tx0 = sx * (AA + tl) + BB;
ty0 = sy * (AA + tl) + CC;
tx1 = sx * AA + BB;
ty1 = sy * AA + CC;
TFT.drawLine(tx0, ty0, tx1, ty1, NOIR);
if (i % 20 == 0)
{
tx0 = sx * (AA + tl + 10) + BB;
ty0 = sy * (AA + tl + 10) + CC;
switch (i / 20)
{
case -2: TFT.drawCentreString("0", tx0, ty0 - 6, 1); break;
case -1: TFT.drawCentreString("25", tx0, ty0 - 4, 1); break;
case 0: TFT.drawCentreString("50", tx0, ty0 - 6, 1); break;
case 1: TFT.drawCentreString("75", tx0, ty0 - 4, 1); break;
case 2: TFT.drawCentreString("100", tx0, ty0 - 6, 1); break;
}
}
sx = cos((i + 5 - 90) * deg_to_rad);
sy = sin((i + 5 - 90) * deg_to_rad);
tx0 = sx * AA + BB;
ty0 = sy * AA + CC;
if (i < 50) {TFT.drawLine(tx0, ty0, tx1, ty1, NOIR);}
}
}
void plotAiguille(float value)
{
if (vu_metre_actif == false) {return;}
uint16_t x0 = x0_vu_metre;
uint16_t y0 = y0_vu_metre;
uint16_t dx=140;
uint16_t dy=50;
uint8_t AA = dx/2; // 100
uint8_t BB = x0 +dx/2;// 120
uint8_t CC = y0 + dy+25; // 140
TFT.setTextColor(TFT_BLACK, BLANC);
char buf[8]; dtostrf(value, 4, 0, buf);
if (value < -10) value = -10;
if (value > 110) value = 110;
float sdeg = map(value, -10, 110, -150, -30);
float sx = cos(sdeg * deg_to_rad);
float sy = sin(sdeg * deg_to_rad);
float tx = tan((sdeg + 90) * deg_to_rad);
TFT.drawLine(BB + 20*ltx - 1, CC - 20, osx - 1, osy, BLANC); //efface
TFT.drawLine(BB + 20*ltx, CC - 20, osx, osy, BLANC);
TFT.drawLine(BB + 20*ltx + 1, CC - 20, osx + 1, osy, BLANC);
ltx = tx;
osx = sx*50 + BB;
osy = sy*50 + CC;
TFT.drawLine(BB + 20*ltx - 1, CC - 20, osx - 1, osy, ROUGE);
TFT.drawLine(BB + 20*ltx, CC - 20, osx, osy, VIOLET);
TFT.drawLine(BB + 20*ltx + 1, CC - 20, osx + 1, osy, ROUGE);
TFT.fillRect(x0, y0+dy+5, dx, 15, GRIS_2);
}
void init_box_info()
{
TFT.drawRect(x0_box_info1, y0_box_info1, 130, 16, NOIR);
TFT.setFreeFont(FF0);
TFT.setTextColor(JAUNE, couleur_fond_ecran);
TFT.drawString("RDS:", x0_box_info1 -24, y0_box_info1 + 4);
}
void affiche_unit(String s)
{
TFT.setTextColor(JAUNE, NOIR);
TFT.setFreeFont(FM9); //FM9 FMB9 FSS9... voir le fichier Free_Fonts.h
TFT.drawString(s, FRQ_x0 + 225, FRQ_y0 + 35);
}
void efface_numero_frq()
{
TFT.fillRect(FRQ_x0 + 225, FRQ_y0 + 20, 40, 12, couleur_fond_ecran);
}
void affiche_numero_frq(String s1, String s2)
{
//TFT.fillRect(FRQ_x0 + 225, FRQ_y0 + 5, 10, 10, BLEU);
TFT.setTextColor(BLANC, couleur_fond_ecran);
TFT.setFreeFont(FF0);
TFT.drawString(s1 + "/" + s2 + " ", FRQ_x0 + 225, FRQ_y0 + 20);
affiche_box_FRQ(GRIS_3); // pour retracer le côté droit du rectangle
}
void affiche_band(String s)
{
//TFT.fillRect(FRQ_x0 + 225, FRQ_y0 + 5, 10, 10, BLEU);
TFT.setTextColor(BLANC, NOIR);
TFT.setFreeFont(FM9);
String blancs;
if (s == "AIR") {blancs = " ";} else {blancs = " ";}
TFT.drawString(s + blancs, FRQ_x0 + 225, FRQ_y0);
affiche_box_FRQ(GRIS_3); // pour retracer le côté droit du rectangle
}
void efface_box_entete1()
{
TFT.fillRect(0, 1, 50, 12, NOIR);
}
void efface_box_entete2()
{
TFT.fillRect(50, 1, 180, 12, NOIR);
}
void efface_box_entete3()
{
TFT.fillRect(230, 1, 76, 12, NOIR);
memo_valeur_affi--; // pour réafficher tension batterie
}
void affiche_box_FRQ(uint16_t couleur) // autour de la fréquence (en gros chiffres JAUNE
{
TFT.drawRect(0, FRQ_y0 -17, 319, 74, couleur);
}
void affiche_box_presets() // boutons 1 2 3 4 5 6 7 8
{
TFT.fillRect(x0_box_PRESET, y0_box_PRESET, 164, 24, NOIR);
TFT.setTextColor(GRIS_3, NOIR);
//TFT.drawString("presets", 5, 90);
}
void affiche_box_GROUPE() // groupes de fréquences; contient 4 boutons SW, FM, AIR, SC
{
TFT.fillRect(x0_box_GROUPE, y0_box_GROUPE, 105, 23, NOIR);
//TFT.drawRect(x0_box_GROUPE, y0_box_GROUPE, 105, 25, couleur_traits);
TFT.setFreeFont(FF0);
TFT.setTextColor(GRIS_3, NOIR);
TFT.drawString("groupes Freq", x0_box_GROUPE+4, y0_box_GROUPE-6);
}
void efface_box_GROUPE()
{
TFT.fillRect(x0_box_GROUPE, y0_box_GROUPE-7, 110, 33, couleur_fond_ecran);
}
void affiche_box_EEPROM() // RAZ, WRITE, READ ...
{
TFT.fillRect(x0_box_EEPROM, y0_box_EEPROM + 10, 46, 58, NOIR);
TFT.setFreeFont(FF0);
TFT.setTextColor(GRIS_3, NOIR);
TFT.drawString("EEPROM", x0_box_EEPROM+6, y0_box_EEPROM+6);
}
void affiche_box_boutons_scan()
{
TFT.fillRect(x0_box_boutons_scan, y0_box_boutons_scan + 10, 60, 38, NOIR);
//TFT.setFreeFont(FF0);
//TFT.setTextColor(GRIS_3, NOIR);
//TFT.drawString("SCAN", x0_box_boutons_scan+6, y0_box_boutons_scan+6);
}
void affiche_box_scan()
{
TFT.fillRect(x0_box_SCAN, y0_box_SCAN, dx_box_SCAN, dy_box_SCAN, NOIR);
init_1_bouton(301, y0_box_SCAN+2, 15, 15, "x", &bt_stop_scan);
init_1_bouton(275, y0_box_SCAN+30, 40, 15, "rescan", &bt_re_scan);
init_1_bouton(275, y0_box_SCAN+50, 40, 15, " >>", &bt_scan_suivant);
init_1_bouton(250, y0_box_SCAN+10, 15, 15, "+", &bt_seuil_plus);
init_1_bouton(250, y0_box_SCAN+30, 15, 15, "-", &bt_seuil_moins);
init_1_bouton(4, y0_box_SCAN+3, 15, 15, "L", &bt_LEV);
init_1_bouton(4, y0_box_SCAN+20, 15, 15, "N", &bt_SNR);
}
void affi_boutons_SW_FM_AIR_SCN()
{
if((mode_affi == SCAN_F ) || (mode_affi == SCAN_M )) {return;}
uint16_t c1 = GRIS_5;
uint16_t c2 = VERT;
bt_SW.affiche(c1, c2, 1);
bt_FM.affiche(c1, c2, 1);
bt_AIR.affiche(c1, c2, 1);
bt_SCN.affiche(c1, BLEU_CLAIR, 1);
bt_mute.affiche(NOIR, ROUGE, 1);
}
void affiche_frequence(uint32_t frq)
{
uint16_t couleur_chiffres;
if(mode_s == _FRQ) {couleur_chiffres = VERT_chiffres;}
if(mode_s == _MEM) {couleur_chiffres = JAUNE_chiffres;}
if(bande_SW) // SW - 28 MHz = limite haute du module
{
affiche_band("SW");
modulation_active = AM;
bande_active = SW;
bt_SW.selected = true;
bt_FM.selected = false; // les boutons sont exclusifs
bt_AIR.selected = false;
//bt_SCN.selected = false;
affi_boutons_SW_FM_AIR_SCN();
String s1, sM, sK;
uint8_t L;
s1 = String(frq);
s1 = "000000" + s1;
L= s1.length();
sK = s1.substring(L-3); // kHz
sM = s1.substring(L-6, L-3); // Mhz
sprite_frq.fillRect(0, 0, 220, 60, NOIR); // efface
sprite_frq.setTextColor(couleur_chiffres, NOIR);
sprite_frq.drawString(sM + "." + sK + " ", 220+10, 32);
// remarque: le fait d'ajouter " " à la fin évite aux chiffres de se balader horizontalement !
sprite_frq.pushSprite(FRQ_x0, FRQ_y0);
affiche_unit("MHz");
Tune_Frequence(frq);
}
if(bande_FM) // bande FM, on efface les deux '0' de droite
{
affiche_band("FM");
modulation_active = WFM;
bande_active = FM;
//bt_FM.selected = true;
//bt_SW.selected = false; // les boutons sont exclusifs
//bt_AIR.selected = false;
//bt_SCN.selected = false;
affi_boutons_SW_FM_AIR_SCN();
String s1, sM, sK;
uint8_t L;
s1 = String(frq);
s1 = "000000" + s1;
L= s1.length();
sK = s1.substring(L-3, L-2); // kHz
if (frq < 100000) {sM = s1.substring(L-5, L-3); }// on ne retient que deux chiffres à gauche du point
else { sM = s1.substring(L-6, L-3); } // on garde 3 chiffres à gauche du point décimal
sprite_frq.fillRect(0, 0, 220, 60, NOIR); // efface
sprite_frq.setTextColor(couleur_chiffres, NOIR);
sprite_frq.drawString(sM + "." + sK + " ", 220-50, 32);
// remarque: le fait d'ajouter " " à la fin évite aux chiffres de se balader horizontalement !
sprite_frq.pushSprite(FRQ_x0, FRQ_y0);
affiche_unit("MHz");
Tune_Frequence(frq);
bt_mute.selected = false;
bt_mute.cliked = false;
}
if(bande_AIR) // bande AIR - 138000-110000 = 28MHz (limite haute de réception AM du module)
{
affiche_band("AIR");
modulation_active = AM;
bande_active = AIR;
bt_AIR.selected = true;
bt_SW.selected = false; // les boutons sont exclusifs
bt_FM.selected = false;
//bt_SCN.selected = false;
affi_boutons_SW_FM_AIR_SCN();
String s1, sM, sK;
uint8_t L;
s1 = String(frq);
s1 = "000000" + s1;
L= s1.length();
sK = s1.substring(L-3); // kHz
sM = s1.substring(L-6, L-3); // Mhz
sprite_frq.fillRect(0, 0, 220, 60, NOIR); // efface
sprite_frq.setTextColor(couleur_chiffres, NOIR);
sprite_frq.drawString(sM + "." + sK + " ", 220+10, 32);
// remarque: le fait d'ajouter " " à la fin évite aux chiffres de se balader horizontalement !
sprite_frq.pushSprite(FRQ_x0, FRQ_y0);
affiche_unit("MHz");
Tune_Frequence(frq);
}
if(bande_interdite1 || bande_interdite2) // bandes interdites par le module TEF6686
{
affiche_band("---");
String s1, sM, sK;
uint8_t L;
s1 = String(frq);
s1 = "000000" + s1;
L= s1.length();
sK = s1.substring(L-3); // kHz
sM = s1.substring(L-6, L-3); // Mhz
sprite_frq.fillRect(0, 0, 220, 60, NOIR); // efface
sprite_frq.setTextColor(couleur_chiffres, NOIR);
sprite_frq.drawString(sM + "." + sK + " ", 220+10, 32);
// remarque: le fait d'ajouter " " à la fin évite aux chiffres de se balader horizontalement !
sprite_frq.pushSprite(FRQ_x0, FRQ_y0);
affiche_unit("MHz");
//Tune_Frequence(frq);
}
if(frq==138000) { affiche_band("max"); }
if(frq>138000) { affiche_band("---"); }
}
void clic_logiciel_bouton(TOUCH_BOUTON *bouton_i)
{
uint16_t c1 = NOIR;
uint16_t c2 = JAUNE;
bouton_i->cliked = true;
bouton_i->selected = true;
bouton_i->affiche(c1, c2, 1);
}
void test_clic_boutons(TOUCH_BOUTON *bouton_i)
{
uint16_t c1 = NOIR;
uint16_t c2 = GRIS_2;
if ((x_touch > bouton_i->x0) && (x_touch < bouton_i->x0 + bouton_i->read_dx())
&& ( y_touch > bouton_i->y0-5) && (y_touch < bouton_i->y0 + bouton_i->read_dy() +5) )
{
bouton_i->cliked = true;
bouton_i->selected = true;
bouton_i->affiche(c1, c2, 1);
}
}
void test_clic_6_boutons_frq() //rectangles situés au dessus des gros chiffres de la fréquence
{
uint16_t c1 = NOIR;
uint16_t c2 = VERT;
if (( y_touch > (bt_1.y0-10)) && (y_touch < (bt_1.y0 + bt_1.read_dy()+10)) ) // zone des 6 boutons au dessus de la fréquence
{
bt_1.cliked = false; bt_1.selected = false; test_clic_boutons(&bt_1 ); bt_1.affiche(c1, c2,1);
bt_2.cliked = false; bt_2.selected = false; test_clic_boutons(&bt_2 ); bt_2.affiche(c1, c2,1);
bt_3.cliked = false; bt_3.selected = false; test_clic_boutons(&bt_3 ); bt_3.affiche(c1, c2,1);
bt_4.cliked = false; bt_4.selected = false; test_clic_boutons(&bt_4 ); bt_4.affiche(c1, c2,1);
bt_5.cliked = false; bt_5.selected = false; test_clic_boutons(&bt_5 ); bt_5.affiche(c1, c2,1);
bt_6.cliked = false; bt_6.selected = false; test_clic_boutons(&bt_6 ); bt_6.affiche(c1, c2,1);
if (bt_6.cliked) {saut_freq = 1;}
if (bt_5.cliked) {saut_freq = 10;}
if (bt_4.cliked) {saut_freq = 100;}
if (bt_3.cliked) {saut_freq = 1000;}
if (bt_2.cliked) {saut_freq = 10000;}
if (bt_1.cliked) {saut_freq = 100000;}
}
}
void affiche_saisie(String s1)
{
TFT.fillRect(x0_saisie+1, y0_saisie-1, 60, 12, NOIR); // efface
TFT.setFreeFont(FF0); TFT.setTextColor(VERT, NOIR);
TFT.drawString(s1, x0_saisie+5, y0_saisie+3);
}
void traite_touches_pad(uint8_t num_touche) // pavé numérique
{
if(num_touche == 253) {return;}
uint16_t c1 = GRIS_6;
uint16_t c2 = JAUNE;
uint16_t c3 = VERT;
int p1;
if (num_touche == 254) // bouton "."
{
frequence_txt += ".";
affiche_saisie(frequence_txt);
}
if (num_touche < 10)
{
frequence_txt += String(num_touche);
affiche_saisie(frequence_txt);
delay(300);
}
x_touch =0;
y_touch =0;
if (num_touche == 255) // bouton "ok"
{
Serial.println("touche ok");
affiche_saisie(""); // efface
mode_s = _FRQ;
bt_mode_MEM.selected = false;
bt_mode_FRQ.selected = true;
bt_mode_MEM.affiche(c1, c2, 2);
bt_mode_FRQ.affiche(c1, c3, 2);
double F = frequence_txt.toDouble();
p1 = frequence_txt.indexOf(".");
if (p1 != -1) {F *=1000;} // si présence du point décimal
frequence = F;
affiche_frequence(frequence); // 'Tune_Frequence(frq)' est appelée dans cette fonction 'affiche_frequence()'
n_appui = 0;
frequence_txt = "";
TFT.fillRect(250, 0, 60, 12, NOIR); // efface
n_appui = 0;
}
num_touche = 0;
}
void traite_boutons_presetPad(uint8_t n_bt)
{
if (n_bt > 7) {return;}
uint16_t c1 = GRIS_5;
uint16_t c2 = JAUNE;
uint32_t adr0, adr1, adr2, adr;
if (mode_affi == NORMAL)
{
// Lit la frequence dans le bouton concerné (VOIR: 'class TOUCH_BOUTON_PRESET')
if(bande_active == SW) {frequence = presetPad1.bt_preset[n_bt].frequence_SW;}
if(bande_active == FM) {frequence = presetPad1.bt_preset[n_bt].frequence_FM;}
if(bande_active == AIR) {frequence = presetPad1.bt_preset[n_bt].frequence_AIR;}
}
if (mode_affi == SET_F_PRESET)
{
/* Serial.println("----------------------");
Serial.println("mode_affi == SET_F_PRESET");
Serial.print("frequence="); Serial.println(frequence);
Serial.print("bande_active="); Serial.println(bande_active);
Serial.print("n_b= "); Serial.println(n_bt);
*/
adr0 = frq_preset_adr_0; // 1700
if(bande_active == SW)
{
presetPad1.bt_preset[n_bt].frequence_SW = frequence; // en RAM
adr = adr0 + 4*n_bt; // 4 octets par bouton
EEPROM.writeUInt(adr, frequence);
EEPROM.commit();
mode_affi = NORMAL;
delay(500);
}
if(bande_active == FM)
{
presetPad1.bt_preset[n_bt].frequence_FM = frequence;
adr = adr0 + 32 + 4*n_bt; // 8 boutons de 4 bytes -> 32 bytes
EEPROM.writeUInt(adr, frequence);
EEPROM.commit();
mode_affi = NORMAL;
delay(500);
}
if(bande_active == AIR)
{
presetPad1.bt_preset[n_bt].frequence_AIR = frequence;
adr = adr0 + 64 + 4*n_bt; // 8+8 boutons de 4 bytes -> 64 bytes
EEPROM.writeUInt(adr, frequence);
EEPROM.commit();
mode_affi = NORMAL;
delay(500);
}
mode_affi = NORMAL;
vu_metre_actif = true;
init_affichages();
}
if (mode_affi == COUL) // saisie couleur fond d'écran
{
couleur_fond_ecran = presetPad1.bt_preset[n_bt].couleur;
EEPROM.writeShort(EEPROM_adrs_couleur, couleur_fond_ecran); // write 1 mot de 16 bits soit 2 octets
EEPROM.commit();
mode_affi = NORMAL;
vu_metre_actif = true;
init_affichages();
}
affiche_frequence(frequence);
//efface_box_entete2();
TFT.setTextColor(JAUNE, NOIR);
TFT.setFreeFont(FF0);
Tune_Frequence(frequence);
}
uint32_t inc_Frq_in_groupe(GROUPE_FREQUENCES *groupe_Freq, int8_t di) // di = +/-1
{
if ((di<-1)||(di>1)) {return 0;}
uint16_t n_max = groupe_Freq->nb_freq;
uint16_t n = groupe_Freq->num_F_actuelle;
if(n_max > 99) {n_max = 99;}
if (di == 1)
{
if (n<n_max-1) { n++; }
else if (n >= (n_max-1)) {n=0;}
}
if (di == -1)
{
if (n>=1) { n--; }
else if (n==0) {n = n_max-1;}
}
if(n > 99) {n = 0;}
groupe_Freq->num_F_actuelle = n;
uint16_t adr = groupe_Freq->adr_1ere_frq + n;
uint8_t nb_F = groupe_Freq->nb_freq;
uint8_t num_1ere_F = groupe_Freq->adr_1ere_frq;
affiche_numero_frq(String(1 + adr - num_1ere_F), String(nb_F));
uint32_t valeur_lue = groupe_Freq->G_freq[adr];
return valeur_lue;
}
void test_clic_boutons_plus_moins()
{
Serial.print("bande_active = "); Serial.println(bande_active);
uint16_t c1 = GRIS_6;
uint16_t c2 = GRIS_3;
boolean bouton_cliked = false;
//uint16_t n=0;
//efface_box_entete(); // efface
efface_box_entete2();
//---------------------------------------------------------------------------------
if(mode_s == _FRQ) // on va modifier directement la fréquence
{
test_clic_boutons(&bt_plus );
bt_plus.affiche(c1, c2, 1);
if (bt_plus.cliked)
{
frequence += saut_freq;
bouton_cliked = true;
}
delay(20);
if (bt_plus.cliked && ((frequence + saut_freq) <= 138000 ))
{
Tune_Frequence(frequence);
}
bt_plus.cliked = false;
bt_plus.selected = false;
bt_plus.affiche(c1, c2, 1); // fugitif
test_clic_boutons(&bt_moins );
bt_moins.affiche(c1, c2, 1);
delay(20);
if (bt_moins.cliked)
{
if (frequence > saut_freq) // évite de se retrouver avec une F négative !
{
bouton_cliked = true;
frequence -= saut_freq;
}
}
if(bt_moins.cliked && frequence > saut_freq) { Tune_Frequence(frequence); }
bt_moins.cliked = false;
bt_moins.selected = false;
bt_moins.affiche(c1, c2, 1); // fugitif
if(bouton_cliked == true)
{
bouton_cliked = false;
affiche_frequence(frequence);
}
}
//---------------------------------------------------------------------------------
if(mode_s == _MEM) // on va parcourir les fréquences de la liste
{
test_clic_boutons(&bt_plus );
bt_plus.affiche(c1, c2, 1);
if (bt_plus.cliked)
{
bouton_cliked = true;
if(bande_active == SW) { frequence = inc_Frq_in_groupe(&groupe_SW, 1); }
if(bande_active == FM) { frequence = inc_Frq_in_groupe(&groupe_FM, 1); }
if(bande_active == AIR) { frequence = inc_Frq_in_groupe(&groupe_AIR, 1); }
if(bande_active == SCN) { frequence = inc_Frq_in_groupe(&groupe_SCAN, 1); }
Tune_Frequence(frequence);
delay(100);
}
bt_plus.cliked = false;
bt_plus.selected = false;
bt_plus.affiche(c1, c2, 1); // fugitif
test_clic_boutons(&bt_moins );
bt_moins.affiche(c1, c2, 1);
delay(20);
if (bt_moins.cliked)
{
bouton_cliked = true;
if(bande_active == SW) { frequence = inc_Frq_in_groupe(&groupe_SW, -1); }
if(bande_active == FM) { frequence = inc_Frq_in_groupe(&groupe_FM, -1); }
if(bande_active == AIR) { frequence = inc_Frq_in_groupe(&groupe_AIR, -1); }
if(bande_active == SCN) { frequence = inc_Frq_in_groupe(&groupe_SCAN, -1); }
Tune_Frequence(frequence);
delay(100);
}
bt_moins.cliked = false;
bt_moins.selected = false;
bt_moins.affiche(c1, c2, 1); // fugitif
if(bouton_cliked == true)
{
bouton_cliked = false;
affiche_frequence(frequence);
}
}
}
void test_clic_bt_RST_affi() // bouton "ok" de la box saisie couleur de fond ecran
{
if(mode_affi != COUL) {return;}
uint16_t c1 = GRIS_6;
uint16_t c2 = JAUNE;
test_clic_boutons(&bt_RST_affi );
//bt_sleep.affiche(NOIR, ROUGE, 1);
//delay(100);
if (bt_RST_affi.cliked)
{
bt_RST_affi.cliked = false;
bt_RST_affi.selected = true;
bt_RST_affi.affiche(NOIR, VERT, 1);
init_affichages();
}
}
void test_clic_bt_affi_saisie_couleur() // bouton au coin en bas à droite
{
uint16_t c1 = GRIS_6;
uint16_t c2 = JAUNE;
test_clic_boutons(&bt_affi_saisie_couleur );
//bt_sleep.affiche(NOIR, ROUGE, 1);
//delay(100);
if (bt_affi_saisie_couleur.cliked)
{
bt_affi_saisie_couleur.cliked = false;
bt_affi_saisie_couleur.selected = true;
bt_affi_saisie_couleur.affiche(NOIR, VERT, 1);
vu_metre_actif = false;
TFT.fillRect(x0_box_info2, y0_box_info2, dx_box_info2, dy_box_info2, NOIR);
TFT.setTextColor(VERT, NOIR);
TFT.setFreeFont(FF0);
TFT.drawString("Cliquez sur un des 8 bt", x0_box_info2+2, y0_box_info2+2);
TFT.drawString("'preset' pour choisir", x0_box_info2+2, y0_box_info2+12);
TFT.drawString("la couleur de fond", x0_box_info2+2, y0_box_info2+22);
mode_affi = COUL;
presetPad1.init(x0_box_PRESET +5, y0_box_PRESET +5);
}
}
void test_clic_bouton_mute()
{
test_clic_boutons(&bt_mute );
if (bt_mute.cliked)
{
bt_mute.affiche(NOIR, ROUGE, 1);
delay(100);
bt_mute.cliked = false;
if(mute == false) {mute = true;} else {mute = false;}
Set_Mute(mute); // fonction située dans le fichier 'driverTEF6686_628.h'
bt_mute.selected = mute;
bt_mute.affiche(NOIR, ROUGE, 1);
if (mute == false) {Tune_Frequence(frequence);}
delay(500);
}
}
void test_clic_bouton_Sleep()
{
test_clic_boutons(&bt_sleep );
//bt_sleep.affiche(NOIR, ROUGE, 1);
//delay(100);
if (bt_sleep.cliked)
{
bt_sleep.cliked = false;
bt_sleep.selected = true;
bt_sleep.affiche(NOIR, ROUGE, 1);
delay(100);
EEPROM.writeUInt(EEPROM_adrs_freq, frequence); // write 1 mot de 16 bits soit 2 octets
Serial.print("EEPROM.writeByte mode_s"); Serial.println(mode_s);
EEPROM.writeByte(EEPROM_adrs_mode, (byte)mode_s); // write 1 octet
EEPROM.commit();
delay(100);
esp_deep_sleep_start();
}
}
void test_clic_Bt_reset()
{
test_clic_boutons(&bt_reset );
bt_reset.affiche(GRIS_6, NOIR, 1);
delay(100);
if (bt_reset.cliked)
{
bt_reset.cliked = false;
bt_reset.selected = true;
bt_reset.affiche(GRIS_6, VERT, 1);
delay(100);
bt_reset.selected = false;
bt_reset.affiche(GRIS_6, VERT, 1);
setup();
}
}
void test_clic_bt_LEV()
{
test_clic_boutons(&bt_LEV);
if (bt_LEV.cliked)
{
bt_LEV.cliked = false;
bt_LEV.selected = true; bt_LEV.affiche(NOIR, VERT, 1);
bt_SNR.selected = false; bt_SNR.affiche(NOIR, VERT, 1);
mode_seuil = LEV;
}
}
void test_clic_bt_SNR()
{
test_clic_boutons(&bt_SNR);
if (bt_SNR.cliked)
{
bt_SNR.cliked = false;
bt_SNR.selected = true; bt_SNR.affiche(NOIR, VERT, 1);
bt_LEV.selected = false; bt_LEV.affiche(NOIR, VERT, 1);
mode_seuil = SNR;
}
}
void test_clic_bt_stop_scan()
{
test_clic_boutons(&bt_stop_scan);
if (bt_stop_scan.cliked)
{
Serial.println("STOP scan");
bt_stop_scan.affiche(NOIR, BLANC, 1);
mode_affi = NORMAL;
bt_stop_scan.cliked = false;
bt_stop_scan.affiche(NOIR, BLANC, 1);
}
}
void test_clic_bt_annuler() // sur la petite fenêtre surgissante d'info
{
test_clic_boutons(&bt_annuler);
if (bt_annuler.cliked)
{
bt_stop_scan.cliked = false;
bt_stop_scan.affiche(NOIR, BLANC, 1);
mode_affi = NORMAL; // ce qui repasse les boutons 'preset' en mode sélection et empêche l'écriture en EEPROM
vu_metre_actif = true;
init_affichages();
}
}
/*
MODES DE SCAN
1-scan_frq() : tt fréquences d'une bande (ex: FM). Mise en mémoire temporaire (en RAM) des stations actives.
2-scan_mem() : cannaux occupés (pour la bande aviation) - pas de mise en mémoire mais stop si message reçu
puis reprise auto du scan à la fin du message.
*/
//enum MODE_SEUIL {LEV, SNR}; // level ou signal/bruit
//MODE_SEUIL mode_seuil = LEV;
void scan_mem()
{
Serial.println("scan_mem()");
efface_box_GROUPE();
affiche_box_scan();
TFT.setFreeFont(FF0);
TFT.setTextColor(JAUNE, NOIR);
TFT.drawString("SCAN AIR BAND (mem)", x0_box_SCAN +110 , y0_box_SCAN + 5); // titre
String si;
uint16_t y;
uint16_t xi;
int16_t dy;
uint16_t yi;
int16_t attente =0;
mode_seuil = SNR; //2 types de détection possibles: LEV(level) et SNR(signal-to-noise ratio = signal/bruit)
bt_SNR.selected = true; bt_SNR.affiche(NOIR, VERT, 1);
bt_LEV.selected = false; bt_LEV.affiche(NOIR, VERT, 1);
int16_t signal_i;
uint16_t base = y0_box_SCAN + dy_box_SCAN -5; // bas du graphique
TFT.setFreeFont(FM9);
TFT.setTextColor(JAUNE, NOIR);
bande_active = AIR;
frequence = 124075;
Tune_Frequence(frequence);
affiche_frequence(frequence);
TFT.drawFastHLine(5, base -seuil/10, 320, GRIS_6); // seuil (trait horizontal sur toute la largeur)
while(mode_affi == SCAN_M)
{
y = y0_box_SCAN + 5;
uint8_t module;
if(bande_active == FM) {module = 32;} else {module = 33;}
Get_Quality( module, &status, &level, &usn, &wam, &offset, &bandwidth, &mod, &snr );
si = String(level);
TFT.drawString("level", x0_box_SCAN +25 , y);
TFT.drawString(si+" ", x0_box_SCAN +65 , y);
y+=15;
si = String(snr);
TFT.drawString("snr", x0_box_SCAN +25 , y);
TFT.drawString(si+" ", x0_box_SCAN +65 , y);
y+=20;
if (mode_seuil == LEV) { signal_i = level; } // attention! level peut être négatif (échelle log)
if (mode_seuil == SNR) { signal_i= 16 * snr; }
dy = signal_i/10;
if(dy<0) {dy=0;}
dy+=2;
// petites barres verticales
xi = (frequence - 120000)/50;
// xi(120MHz) = 0 px;
// xi(136MHz) = (136000 - 120000) /50 = 320 px
TFT.drawFastVLine(xi, base-95, 95, NOIR); //efface
uint16_t c0 = BLEU;
if(signal_i > seuil){c0 = JAUNE;}
TFT.drawFastVLine(xi, base -dy, dy, c0);
uint16_t c1 = GRIS_5;
uint16_t c2 = VERT;
if(signal_i > seuil)
{
TFT.fillRect(x0_box_SCAN +110, y0_box_SCAN + 20, 20, 20, c2); // carré coloré
attente = 2;
}
else attente --;
if (attente <=0)
{
TFT.fillRect(x0_box_SCAN +110, y0_box_SCAN + 20, 20, 20, c1); // carré coloré
frequence = inc_Frq_in_groupe(&groupe_AIR, 1);
Tune_Frequence(frequence);
affiche_frequence(frequence);
TFT.setFreeFont(FF0);
TFT.setTextColor(BLANC, NOIR);
TFT.drawString("120M", x0_box_SCAN +5 , base-10);
TFT.drawString("136M", x0_box_SCAN +dx_box_SCAN -28, base-10);
attente =0;
}
if(seuil != memo_seuil)
{
TFT.drawFastHLine(5, base -memo_seuil/10, 310, NOIR); // efface
TFT.drawFastHLine(5, base -seuil/10, 310, GRIS_6); // seuil (trait horizontal sur toute la largeur)
si = "seuil:" + String(seuil); TFT.drawString(si+" ", x0_box_SCAN +185 , y0_box_SCAN +23);
}
delay(50); // ne pas réduire, temps nécessaire pour accrocher la fréquence
if (ts.tirqTouched() && ts.touched())
{
TS_Point p = ts.getPoint();
x_touch = -30 + p.x /11;
y_touch = -30 + p.y /14;
test_clic_bt_stop_scan();
test_clic_boutons(&bt_seuil_plus);
if (bt_seuil_plus.cliked)
{
bt_seuil_plus.cliked = false;
memo_seuil = seuil;
seuil += 5;
}
test_clic_boutons(&bt_seuil_moins);
if (bt_seuil_moins.cliked)
{
bt_seuil_moins.cliked = false;
memo_seuil = seuil;
seuil -= 5;
si = String(seuil); TFT.drawString(si+" ", x0_box_SCAN +55 , y);
}
test_clic_bt_LEV();
test_clic_bt_SNR();
test_clic_boutons(&bt_stop_scan);
}
}
//delay(1000);
mode_s = _MEM;
mode_affi = NORMAL;
bande_active = FM;
bt_mode_MEM.selected = true; bt_mode_MEM.affiche(GRIS_6, VERT, 2);
bt_mode_FRQ.selected = false; bt_mode_FRQ.affiche(GRIS_6, VERT, 2);
//boutons_preset_set_frequences();
init_affichages();
frequence = 89400;
Tune_Frequence(frequence);
affiche_frequence(frequence);
bt_FM.selected = true; bt_FM.affiche(GRIS_6, VERT, 1);
bt_AIR.selected = false; bt_AIR.affiche(GRIS_6, VERT, 1);
}
void scan_frq()
{
Serial.println("scan_frq()");
String si;
String s1;
String sA, sB;
float xi=0;
uint32_t xi32;
uint16_t y;
int16_t dy;
uint16_t yi;
uint16_t memo_x_touch = 0;
uint16_t nb_F;
int16_t signal_i;
uint16_t base = y0_box_SCAN + dy_box_SCAN -5; // bas du graphique
uint16_t decal_x;
uint16_t decal_y;
int n_max;
memo_frequence_scan = frequence; // variables globales
mode_seuil = SNR; //2 types de détection possibles: LEV(level) et SNR(signal-to-noise ratio = signal/bruit)
bt_SNR.selected = true; bt_SNR.affiche(NOIR, VERT, 1);
bt_LEV.selected = false; bt_LEV.affiche(NOIR, VERT, 1);
groupe_SCAN.RAZ();
efface_box_GROUPE();
TFT.setFreeFont(FM9);
TFT.setTextColor(JAUNE, NOIR);
TFT.setFreeFont(FF0);
uint8_t module;
if(bande_active == FM)
{
TFT.drawString("SCAN bande FM", x0_box_SCAN +50 , y0_box_SCAN + 10); // titre
frequence = 88000;
saut_freq = 100; // kHz
module = 32;
n_max = 190;
}
else
{
TFT.drawString("SCAN bande SW", x0_box_SCAN +50 , y0_box_SCAN + 10);
//frequence = 12000; // 12MHz...
saut_freq = 5; // kHz
module = 33;
n_max = 200;
}
y = y0_box_SCAN + 5;
decal_x=0;
decal_y=0;
nb_F=0;
TFT.drawFastHLine(5, base -seuil/10, 320, GRIS_6); // seuil (trait horizontal sur toute la largeur)
sA = String(frequence);
sB = String(frequence + n_max * saut_freq);
TFT.drawString(sA, x0_box_SCAN +5 , base-5);
TFT.drawString(sB, x0_box_SCAN +dx_box_SCAN -32, base-5);
boolean rescan = false;
do
{
groupe_SCAN.RAZ();
nb_F = 0;
affiche_box_scan();
int n = n_max;
uint32_t freq_min = frequence;
while(n>0)
{
frequence += saut_freq;
affiche_frequence(frequence);
if( (frequence + saut_freq) <= 138000 )
{
Tune_Frequence(frequence);
delay(15);
}
if(bande_active == FM) {module = 32;} else {module = 33;}
Get_Quality( module, &status, &level, &usn, &wam, &offset, &bandwidth, &mod, &snr );
delay(50);
//if(bande_active == SW) {xi += 1.6;}
//if(bande_active == FM) {xi += 2;}
xi += 1.6;
if (mode_seuil == LEV) { signal_i = level; } // attention! level peut être négatif (échelle log)
if (mode_seuil == SNR) { signal_i= 16 * snr; }
dy = signal_i/10;
if(dy<0) {dy=0;}
dy+=2;
uint16_t c1 = VERT;
if(dy>30){c1 = JAUNE;}
if(dy>40){c1 = ORANGE;}
if(dy>50){c1 = BLEU_CLAIR;}
xi32 = x0_box_SCAN + (uint32_t)xi;
if (xi32 < 318) // limite d'affichage à droite pour ne pas abimer le cadre
{
//TFT.drawFastVLine(xi32, base-dy, dy, c1); // petites barres verticales
// on va les tracer point par point afin de pouvoir les coloriser
int a = base;
int b = a - dy;
for(int n=b; n<a; n++)
{
c1 = BLEU;
if(n>180){c1 = VERT;}
if(n>190){c1 = JAUNE;}
if(n>200){c1 = ORANGE;}
if(n>215){c1 = ROUGE;}
//c1 = 10 * n *n;
TFT.drawPixel(xi32, n, c1);
}
}
if(signal_i > seuil) // DETECTION
{
if (decal_y > 5) // concerne l'affichage des textes (fréquences trouvées)
{
decal_y = 0;
decal_x ++;
}
s1 = String(frequence);
TFT.setTextColor(BLANC, NOIR);
TFT.drawString(s1, x0_box_SCAN + 2 + 45*decal_x, y0_box_SCAN + 9*decal_y); // String data
nb_F++;
TFT.setFreeFont(FM9);
TFT.setTextColor(VERT, NOIR);
s1 = String(nb_F);
TFT.drawString(s1, x0_box_SCAN +200 , y0_box_SCAN + 10); // nb freq
TFT.setFreeFont(FF0);
groupe_SCAN.add_frq(frequence); // AJOUTE la fréquence trouvée au groupe spécial 'groupe_SCAN'
decal_y ++;
if(groupe_SCAN.nb_freq >= 100) {n=0;} // groupe plein (en RAM)
}
n--;
if(seuil != memo_seuil)
{
TFT.drawFastHLine(5, base -memo_seuil/10, 310, NOIR); // efface
TFT.drawFastHLine(5, base -seuil/10, 310, GRIS_6); // seuil (trait horizontal sur toute la largeur)
si = "seuil:" + String(seuil); TFT.drawString(si+" ", x0_box_SCAN +185 , y0_box_SCAN +23);
}
delay(10); // ne pas réduire, temps nécessaire pour accrocher la fréquence
//delay(300); // pour balayage lent
if (ts.tirqTouched() && ts.touched())
{
TS_Point p = ts.getPoint();
x_touch = -30 + p.x /11;
y_touch = -30 + p.y /14;
test_clic_boutons(&bt_seuil_plus);
if (bt_seuil_plus.cliked)
{
bt_seuil_plus.cliked = false;
memo_seuil = seuil;
seuil += 5;
}
test_clic_boutons(&bt_seuil_moins);
if (bt_seuil_moins.cliked)
{
bt_seuil_moins.cliked = false;
memo_seuil = seuil;
seuil -= 5;
si = String(seuil); TFT.drawString(si+" ", x0_box_SCAN +55 , y);
}
test_clic_bt_LEV();
test_clic_bt_SNR();
test_clic_boutons(&bt_re_scan);
if (bt_re_scan.cliked)
{
bt_re_scan.cliked = false;
affiche_box_scan(); // efface le tracé et re-dessine les boutons dans la boite
frequence = memo_frequence_scan; // on repart de ma même frequence
n = n_max;
xi =0; // départ tracé à gauche
decal_x=0; // textes fréquences trouvées
decal_y=0;
nb_F=0;
}
test_clic_boutons(&bt_stop_scan);
if (bt_stop_scan.cliked)
{
n=0; // force la sortie de la boucle while()
}
}
} // fin de la boucle while()
boolean stop = false;
while (! stop) // attend une action en fin de scan (par ex: clic sur bouton 'stop_scan' [x]) ou [re_scan]
{
if (ts.tirqTouched() && ts.touched())
{
TS_Point p = ts.getPoint();
x_touch = -30 + p.x /11;
y_touch = -30 + p.y /14;
if((x_touch != memo_x_touch) && (y_touch > 170)) // écoute de la fréquence pointée avec le stylet
{
TFT.drawFastVLine(memo_x_touch, base, 4, NOIR); // efface
TFT.drawFastVLine(x_touch, base, 4, BLANC);
TFT.drawFastVLine(memo_x_touch, base-50, 4, NOIR); // efface
TFT.drawFastVLine(x_touch, base-50, 4, BLANC);
memo_x_touch = x_touch ;
float dF = (x_touch - x0_box_SCAN) * saut_freq / 1.6;
uint32_t F1 = freq_min + uint32_t(dF);
frequence = F1;
affiche_frequence(frequence);
Tune_Frequence(frequence);
String sF1 = String(F1);
TFT.drawString(sF1, 200, 100);
}
test_clic_boutons(&bt_re_scan);
if (bt_re_scan.cliked)
{
bt_re_scan.cliked = false;
frequence = memo_frequence_scan; // on repart de ma même frequence
xi=0;
xi32 = x0_box_SCAN + (uint32_t)xi;
stop =true;
rescan = true; //pas d'appel RECURSIF de la fonction. Trop de pb !!
}
test_clic_boutons(&bt_scan_suivant);
if (bt_scan_suivant.cliked)
{
bt_re_scan.cliked = false;
affiche_box_scan(); // efface le tracé et re-dessine les boutons dans la boite
n = n_max;
xi =0; // départ tracé à gauche
decal_x=0; // textes fréquences trouvées
decal_y=0;
nb_F=0;
stop =true;
rescan = true;
}
test_clic_boutons(&bt_stop_scan);
if (bt_stop_scan.cliked)
{
stop =true;
rescan = false;
}
}
}
if (rescan == true) {memo_frequence_scan = frequence;}
} while (rescan == true);
Serial.println("-----------------------");
Serial.println("groupe_SCAN");
groupe_SCAN.bloc_to_serial(); // pour test avec moniteur série (CuteCom par exemple)
Serial.println("-----------------------");
Serial.println("STOP scan");
//bt_stop_scan.affiche(NOIR, BLANC, 1);
//bt_stop_scan.cliked = false;
//bt_stop_scan.affiche(NOIR, BLANC, 1);
mode_affi = NORMAL;
mode_s = _MEM;
bt_mode_FRQ.selected = false; bt_mode_FRQ.affiche(GRIS_6, VERT, 2);
bt_mode_MEM.selected = true; bt_mode_MEM.affiche(GRIS_6, VERT, 2);
//bt_mode_MEM.cliked = true;
init_affichages();
affiche_frequence(frequence);
}
void test_clic_Bt_scan_FRQ()
{
test_clic_boutons(&bt_scan_frq);
if (bt_scan_frq.cliked == true)
{
bt_scan_frq.affiche(NOIR, VERT, 1);
bt_scan_frq.cliked = false;
bt_scan_frq.affiche(GRIS_2, VERT, 1);
mode_affi = SCAN_F;
mode_s = _FRQ;
bt_mode_FRQ.selected = true; bt_mode_FRQ.affiche(GRIS_6, VERT, 2);
bt_mode_MEM.selected = false; bt_mode_MEM.affiche(GRIS_6, VERT, 2);
scan_frq();
bt_scan_frq.affiche(NOIR, VERT, 1);
}
delay(100);
}
void test_clic_bt_scan_air()
{
test_clic_boutons(&bt_scan_air);
if (bt_scan_air.cliked == true)
{
bt_scan_air.affiche(NOIR, VERT, 1);
bt_scan_air.cliked = false;
bt_scan_air.affiche(GRIS_2, VERT, 1);
mode_affi = SCAN_M;
bt_scan_air.selected = true;
scan_mem();
bt_scan_air.affiche(NOIR, VERT, 1);
mode_s = _MEM;
}
delay(100);
}
void EE_RAZ()
{
boolean valider = false; // <-- ecrire "= true" pour rendre l'effacement possible
// (évite tout effacement accidentel et donc perte de centaines de fréquences...)
if(valider == false)
{
TFT.fillScreen(NOIR);
TFT.setFreeFont(FM9);
TFT.drawString("FONCTION VOLONTAIREMENT", 50, 120);
TFT.drawString("INACTIVE", 50, 140);
TFT.drawString("VOIR LE CODE SOURCE", 50, 160);
TFT.drawString("void EE_RAZ()", 50, 180);
delay(3000);
init_affichages();
return;
}
// efface le contenu del'EEPROM, partie data fréquences, sans toucher aux 100 premiers octets
Serial.println("debut RAZ EEPROM");
for(uint16_t n = 0; n<1200; n+=4 ) // 300 x 4 bytes // OK
{
uint32_t valeur1;
valeur1 = 0;
EEPROM.writeUInt(100+n, valeur1); // les 100 premiers octets sont réservés (par moi)
}
EEPROM.commit();
Serial.println("fin RAZ EEPROM");
}
void test_clic_bouton_EE_RAZ()
{
uint16_t c1 = NOIR;
uint16_t c2 = VERT;
test_clic_boutons(&bt_EE_RAZ );
if(bt_EE_RAZ.cliked)
{
bt_EE_RAZ.cliked = false;
bt_EE_RAZ.selected = false;
bt_EE_RAZ.affiche(ROUGE, c1, 1);
EE_RAZ();
}
}
uint16_t EE_find_1ere_mem_libre(uint16_t adr0) // travaille directement sur l'EEPROM (en lecture uniquement!)
{
Serial.println("EE_find_1ere_mem_libre");
uint16_t n =0;
uint16_t adresse_lue;
uint32_t valeur_lue;
boolean ok = false;
while ((n<400) && (ok == false))
{
n += 4;
adresse_lue = adr0 + n;
valeur_lue = EEPROM.readUInt(adresse_lue); // 4 octets
Serial.print("valeur lue: "); Serial.println(valeur_lue);
if (valeur_lue == 0) {ok = true;}
}
Serial.print("trouve: "); Serial.println(n);
return adresse_lue;
}
uint16_t EE_find_if_present(uint16_t adr0, uint32_t F_i) // travaille directement sur l'EEPROM (en lecture uniquement!)
{
Serial.println("EE_find_if_present");
uint16_t n =0;
uint16_t adresse_lue;
uint32_t valeur_lue;
boolean ok = false;
while ((n<100) && (ok == false))
{
n += 4;
adresse_lue = adr0 + n;
valeur_lue = EEPROM.readUInt(adresse_lue); // 4 octets
if (valeur_lue == F_i) {return adresse_lue;} // si F est présente
}
return 0; // si F non présente
}
void test_clic_bouton_EE_write() // en EEPROM, dans un des groupes (groupe_SW, groupe_FM, groupe_AIR)
{
uint16_t c1 = GRIS_6;
uint16_t c2 = VERT;
test_clic_boutons(&bt_EE_write );
if(bt_EE_write.cliked)
{
Serial.println("--------------------------------");
Serial.println("bouton_EE_write clic");
bt_EE_write.cliked = false;
bt_EE_write.selected = false;
bt_EE_write.affiche(GRIS_3, c1, 1);
delay (300);
bt_EE_write.cliked = false;
bt_EE_write.selected = false;
bt_EE_write.affiche(c1, c2, 1); // fugitif
//TFT.drawString("WRITE !", 5, 120);
//TFT.fillRect(5, 120, 50, 30, NOIR); // efface
uint16_t adr0;
uint16_t m0;
if (bande_SW)
{
adr0 = groupe_SW.adr_0;
m0 = EE_find_1ere_mem_libre(adr0);
}
if (bande_FM)
{
adr0 = groupe_FM.adr_0;
m0 = EE_find_1ere_mem_libre(adr0);
}
if (bande_AIR)
{
adr0 = groupe_AIR.adr_0;
m0 = EE_find_1ere_mem_libre(adr0);
}
if( ! EE_find_if_present(adr0, frequence)) // pour éviter les doublons
{
Serial.println("EEPROM.writeUInt");
Serial.print("m0="); Serial.println(m0);
Serial.print("frequence="); Serial.println(frequence);
EEPROM.writeUInt(m0, frequence);
EEPROM.commit();
delay(500);
load_GRP_FREQ_EEPROM();
}
else
{
Serial.print("F=");
Serial.print(frequence);
Serial.println(" presente, NO write");
}
Serial.println("--------------------------------");
}
}
void test_clic_bt_erase_1F() // en EEPROM
{
uint16_t c1 = GRIS_6;
uint16_t c2 = VERT;
test_clic_boutons(&bt_erase_1F );
if(bt_erase_1F.cliked)
{
bt_erase_1F.cliked = false;
bt_erase_1F.selected = false;
bt_erase_1F.affiche(GRIS_3, c1, 1);
delay (300);
bt_erase_1F.cliked = false;
bt_erase_1F.selected = false;
bt_erase_1F.affiche(c1, c2, 1); // fugitif
uint16_t F;
//uint16_t EE_find_if_present(uint16_t adr0, uint32_t F_i)
uint16_t adr0, adri;
if (bande_SW) { adr0 = groupe_SW.adr_0; }
if (bande_FM) { adr0 = groupe_FM.adr_0; }
if (bande_AIR) { adr0 = groupe_AIR.adr_0;}
adri = EE_find_if_present(adr0, frequence);
if (adri !=0)
{
EEPROM.writeUInt(adri, 0);
EEPROM.commit();
load_GRP_FREQ_EEPROM();
}
}
}
void test_clic_boutons_MODE() // FREQ - MEM
{
uint16_t c1 = NOIR;
uint16_t c2 = VERT;
uint16_t c3 = JAUNE;
bt_mode_FRQ.cliked = false;
bt_mode_MEM.cliked = false;
test_clic_boutons(&bt_mode_FRQ );
if (bt_mode_FRQ.cliked) // les boutons sont exclusifs
{
mode_s = _FRQ;
bt_mode_FRQ.selected = true;
bt_mode_MEM.selected = false;
affiche_frequence(frequence);
efface_numero_frq();
}
test_clic_boutons(&bt_mode_MEM );
if (bt_mode_MEM.cliked)
{
mode_s = _MEM;
bt_mode_MEM.selected = true;
bt_mode_FRQ.selected = false;
//affiche_box_FRQ(JAUNE);
affiche_frequence(frequence);
}
bt_mode_FRQ.affiche(c1, c2, 2);
bt_mode_MEM.affiche(c1, c3, 2);
}
void test_clic_boutons_BANDE() // SW, FM, AIR, SCAN
{
uint16_t c1 = GRIS_5;
uint16_t c2 = VERT;
bt_SW.cliked = false;
bt_FM.cliked = false;
bt_AIR.cliked = false;
test_clic_boutons(&bt_SW );
if (bt_SW.cliked)
{
TFT.fillRect(x0_box_info1+2, y0_box_info1+2, 120, 12, couleur_fond_ecran); // efface
Serial.println("bt_SW.cliked");
bt_SW.cliked = false;
bande_active = SW;
modulation_active = AM;
bt_SW.selected = true;
bt_FM.selected = false; // les boutons sont exclusifs
bt_AIR.selected = false;
bt_SCN.selected = false;
clic_logiciel_bouton(&presetPad1.bt_preset[0]);
traite_boutons_presetPad(0);
uint8_t nb_F = groupe_SW.nb_freq;
affiche_numero_frq(String(1), String(nb_F));
}
test_clic_boutons(&bt_FM );
if (bt_FM.cliked)
{
Serial.println("bt_FM.cliked");
bt_FM.cliked = false;
bande_active = FM;
modulation_active = WFM;
bt_FM.selected = true;
bt_SW.selected = false;
bt_AIR.selected = false;
bt_SCN.selected = false;
clic_logiciel_bouton(&presetPad1.bt_preset[0]);
traite_boutons_presetPad(0);
uint8_t nb_F = groupe_FM.nb_freq;
affiche_numero_frq(String(1), String(nb_F));
}
test_clic_boutons(&bt_AIR );
if (bt_AIR.cliked)
{
TFT.fillRect(x0_box_info1+2, y0_box_info1+2, 120, 12, couleur_fond_ecran); // efface
Serial.println("bt_AIR.cliked");
bt_AIR.cliked = false;
bande_active = AIR;
modulation_active = AM;
bt_AIR.selected = true;
bt_SW.selected = false;
bt_FM.selected = false;
bt_SCN.selected = false;
clic_logiciel_bouton(&presetPad1.bt_preset[0]);
traite_boutons_presetPad(0);
uint8_t nb_F = groupe_AIR.nb_freq;
affiche_numero_frq(String(1), String(nb_F));
}
test_clic_boutons(&bt_SCN );
if (bt_SCN.cliked == true)
{
Serial.println("bt_SCN.cliked");
bt_SCN.cliked = false;
bande_active = SCN;
bt_SCN.selected = true;
bt_SW.selected = false;
bt_FM.selected = false;
bt_AIR.selected = false;
//clic_logiciel_bouton(&presetPad1.bt_preset[0]);
//traite_boutons_presetPad(0);
uint8_t nb_F = groupe_SCAN.nb_freq;
affiche_numero_frq(String(1), String(nb_F));
}
bt_SW.affiche(c1, c2, 1);
bt_FM.affiche(c1, c2, 1);
bt_AIR.affiche(c1, c2, 1);
bt_SCN.affiche(c1, CYAN, 1);
}
void test_clic_bouton_set() // bouton pour passer dans le mode d'écriture de la F en cours dans l'EEPROM
// L'écriture en question sera effectuée par la fonction 'traite_boutons_presetPad()'
{
test_clic_boutons(&bt_set);
if (bt_set.cliked)
{
bt_set.cliked = false;
vu_metre_actif = false;
TFT.fillRect(x0_box_info2, y0_box_info2, 140, 70, NOIR);
TFT.setTextColor(VERT, NOIR);
TFT.setFreeFont(FF0);
TFT.drawString("Cliquez sur un des 8 bt", x0_box_info2+2, y0_box_info2+2);
TFT.drawString("'preset' pour lui ", x0_box_info2+2, y0_box_info2+12);
TFT.drawString("attribuer la F en cours", x0_box_info2+2, y0_box_info2+22);
init_1_bouton(x0_box_info2+82, y0_box_info2+50, 50, 15, "annuler", &bt_annuler);
bt_annuler.affiche(NOIR, BLANC, 1);
mode_affi = SET_F_PRESET; // ce qui modifie le comportement de la fonction 'traite_boutons_presetPad()'
Serial.println("mode_affi == SET_F_PRESET");
delay (100);
bt_set.selected = false;
bt_set.affiche(NOIR, BLANC, 1);
}
}
void affiche_signal(uint16_t x, uint16_t y, uint16_t dx, int16_t valeur)
{
TFT.fillRect(x, y, dx, 8, NOIR); // efface
if(valeur<0) {valeur =0;}
if(valeur > dx) {valeur = dx;}
TFT.drawRect(x, y, dx, 5, couleur_traits);
TFT.fillRect(x, y, valeur, 5, JAUNE);
}
void affiche_tension_batt(uint16_t x, uint16_t y, uint16_t dx, int8_t valeur) // valeur en %
{
uint16_t c1;
c1 = ROUGE;
if(valeur>30){c1 = ORANGE;}
if(valeur>50){c1 = JAUNE;}
if(valeur>70){c1 = VERT;}
uint32_t v2 = valeur * dx / 100;
TFT.fillRect(x-20, y, dx, 8, NOIR); // efface
efface_box_entete3();
if(v2<0) {valeur =0;}
if(v2 > dx) {v2 = dx;}
TFT.drawRect(x, y, dx, 5, couleur_traits);
TFT.fillRect(x, y, v2, 5, c1);
String s1 = String(valeur) +"%";
TFT.setTextColor(BLANC, NOIR);
TFT.drawString(s1, x-20, y);
TFT.setFreeFont(FF0);
TFT.setTextColor(BLANC, NOIR);
TFT.drawString("bat", x + 10 , y+5);
}
void affiche_1_bargraph(uint16_t x, uint16_t y, uint16_t dx, int16_t valeur, uint16_t couleur)
{
TFT.fillRect(x, y, dx+40, 8, NOIR); // efface
TFT.drawString(String(valeur), x, y);
if(valeur<0) {valeur =0;}
if(valeur > dx) {valeur = dx;}
TFT.drawRect(x+40, y, dx, 5, couleur_traits);
TFT.drawRect(x+40, y, valeur, 5, couleur);
}
void affiche_bars_graph()
{
affiche_1_bargraph(170, 150, 100, level/10, VERT);
affiche_1_bargraph(170, 160, 100, usn, JAUNE);
affiche_1_bargraph(170, 170, 100, wam, BLEU_CLAIR);
affiche_1_bargraph(170, 180, 100, offset, BLANC);
}
String int_to_hex(uint16_t nb)
{
char symb[16] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
uint8_t A = (nb & 0b1111000000000000) >>12;
uint8_t B = (nb & 0b0000111100000000) >>8;
uint8_t C = (nb & 0b0000000011110000) >>4;
uint8_t D = (nb & 0b0000000000001111);
String s1 = String(symb[A]) + String(symb[B]) + String(symb[C]) + String(symb[D]) ;
return s1;
}
void traite_signal_RDS()
{
Get_RDS_Data ( &status, &A_block, &B_block, &C_block, &D_block, &dec_error);
/*
A_Block always contains the 16-bit program identifier.
The first 11 bits (bits 15–5) of block 2 are also the same in all groups.
La Liste des codes RDS autorisés se trouve ici : https://www.csa.fr/maradiofm/radiords_tableau
pour les autres blocks, voir :
https://en.wikipedia.org/wiki/Radio_Data_System
(c'est sans doute logique mais terriblement indigeste !!!)
*/
TFT.fillRect(x0_box_info1+2, y0_box_info1+2, 120, 12, couleur_fond_ecran); // efface
String s1 = int_to_hex(A_block);
String s2, s3;
TFT.setTextColor(BLANC, GRIS_5);
for(int n = 0; n<=nb_stations_RDS-1; n++)
{
s2 = codesRDS[n];
//Serial.println(s2);
s3 = s2.substring(0, 4);
if (s3 == s1)
{
TFT.drawString(s2, x0_box_info1+5, y0_box_info1 +4);
return; // on ne continue pas à boucler si trouvé
}
else if (n == nb_stations_RDS-1) // pas trouvé...
{
TFT.drawString(s1, x0_box_info1+5, y0_box_info1 +4);
return;
}
}
}
void affiche_force_signal()
{
//----------------------------------------------------------------------------------------------------------
// AFFICHE FORCE SIGNAL HF
compteur1 =0;
uint8_t module;
if(bande_active == FM) {module = 32;} else {module = 33;}
Get_Quality( module, &status, &level, &usn, &wam, &offset, &bandwidth, &mod, &snr );
//float signal_sur_bruit = level;// - 1.5 * usn; // marche à peu près bien pour la FM.
float diff = level - position_aiguille;
if(diff > 30.0) {diff = 30.0;}
if(diff < -30.0) {diff = -30.0;} // évite une trop grande réaction au sortir du mode 'mute'
// supprime les tremblements de l'aiguille
position_aiguille += diff / 6.0;
//affiche_bars_graph();
affiche_signal(170, 90, 60, mod/2);
if ((mode_affi == NORMAL) && (! mute) ) { plotAiguille(position_aiguille/6.0); }
if ((mode_affi == NORMAL) && (mute) ) { plotAiguille(0); }
}
void loop()
{
if (test_touch_screen == true) {printTouchToDisplay();}
if((mode_affi != SCAN_F) && (mode_affi != SCAN_M))// invalide les boutons situés derrière le panneau scan en modes SCAN
{
if (ts.tirqTouched() && ts.touched())
{
TS_Point p = ts.getPoint();
x_touch = -30 + p.x /11;
y_touch = -30 + p.y /14;
test_clic_6_boutons_frq(); // 6 rectangles situés au dessus des gros chiffres de la fréquence
test_clic_bouton_mute();
test_clic_bouton_EE_RAZ();
test_clic_bouton_EE_write();
test_clic_bt_erase_1F();
uint8_t n_touch1 = numPad1.test_clic(); // pavé numérique
if (n_touch1 != 253) { traite_touches_pad(n_touch1); } // pavé numérique
test_clic_boutons_plus_moins(); // boutons '<' et '>'
test_clic_bouton_Sleep();
test_clic_Bt_reset();
test_clic_Bt_scan_FRQ();
test_clic_bt_scan_air(); // Scan mémoires
test_clic_boutons_MODE(); // FREQ / MEM (tout en haut à gauche des gros chiffres)
test_clic_boutons_BANDE(); // SW, FM, AIR, SC; (SC = SCAN)
uint8_t num_bouton = presetPad1.test_clic(); // 8 petits boutons carrés de présélection de 8 fréquences
if (num_bouton != 253) { traite_boutons_presetPad(num_bouton); }
test_clic_bouton_set(); // attribution de la fréquence en cours à un des 8 boutons preset.
test_clic_bt_annuler();
test_clic_bt_affi_saisie_couleur();
test_clic_bt_RST_affi();
}
// la limitation SW max = 28MHz est due au module TEF6686 lui-même
if (frequence >= 138000) {frequence = 138000;} //138 MHz limite à cause SW max = 28MHz et conv AirBand = 110 MHz
if (frequence < 1500) {frequence = 1500;} // 1.5 MHz
if (compteur1 >= 5)
{
affiche_force_signal();
//----------------------------------------------------------------------------------------------------------
// AFFICHE TENSION BATTERIE
//----------------------------------------------------------------------------------------------------------
// voir la feuille de calcul 'Mesure de la tension de la batterie.ods' établie sur tests avec alim numérique
// voir aussi, sur le schéma, la valeur des résistances (diviseur analogique) sur l'entrée GPIO35 (analogPin = 35)
// Note: la valeur de la tension sur le pin GPIO35 ne doit jamais dépasser 3v3 (ce qui est lu = 4096)
int valeurLue = analogRead(analogPin);
//Serial.print("valeurLue = "); Serial.println(valeurLue);
float pourcent = ((float)valeurLue - 2570.0) / 10.0;
if (pourcent > 100.0) {pourcent = 100.0;}
if (pourcent < 0.0) {pourcent = 0.0;}
//Serial.print("pourcent = "); Serial.println(pourcent);
// intégration
float diff2 = pourcent - valeur_affi;
if(diff2 > 10.0) {diff2 = 10.0;}
if(diff2 < -10.0) {diff2 = -10.0;} // évite une trop grande réaction au sortir du mode 'mute'
valeur_affi += diff2 / 10.0;
if ( abs(valeur_affi - memo_valeur_affi) > 1.5 ) // pour éviter trop d'affichages inutiles (et clignotements à l'écran)
{
affiche_tension_batt(270, 4, 46, (int8_t) valeur_affi);
memo_valeur_affi = valeur_affi;
}
}
if (compteur2 >= 100)
{
compteur2 =0;
if(bande_active == FM) {traite_signal_RDS();}
/*
TFT.drawString(
String(A_block) + " " +
String(B_block) + " " +
String(C_block) + " " +
String(D_block) + " ", x0_box_info1+5, y0_box_info1 +4);
*/
}
#ifdef _SD_CARD
if (compteur3 == 2000)
{
write_TFT_on_SDcard(); // attention : incompatible avec le TOUCHPAD
}
#endif
delay(10);
compteur1++;
compteur2++;
}
}
/** ***************************************************************************************
CLASS TOUCH_BOUTON // affiche un nombre ou un petit texte dans un rectangle
ainsi que (en plus petit) deux valeurs supplémentaires, par ex: les valeurs mini et maxi
********************************************************************************************/
// Constructeur
TOUCH_BOUTON::TOUCH_BOUTON()
{
}
// Constructeur
TOUCH_BOUTON_PRESET::TOUCH_BOUTON_PRESET()
{
}
void TOUCH_BOUTON::init(uint16_t xi, uint16_t yi, uint8_t dxi, uint8_t dyi, uint8_t dri)
{
x0 = xi;
y0 = yi;
dx = dxi;
dy = dyi;
dr = dri;
cliked = false;
selected = false;
}
void TOUCH_BOUTON::affiche(uint16_t coul_fill_unselect, uint16_t coul_fill_select, uint8_t n_font)
{
//uint16_t c1 = NOIR;
uint16_t couleur_contour = GRIS_5;
uint16_t couleur_texte = BLANC;
if(selected)
{
TFT.fillRoundRect(x0, y0, dx, dy, dr, coul_fill_select);
TFT.setTextColor(NOIR);
}
else
{
TFT.fillRoundRect(x0, y0, dx, dy, dr, coul_fill_unselect); // efface
TFT.drawRoundRect(x0, y0, dx, dy, dr, couleur_contour); // retrace juste le contour
TFT.setTextColor(couleur_texte);
}
//uint8_t dy = 0;
//FM9 FMB9 FSS9... voir le fichier Free_Fonts.h
if (n_font == 1) { TFT.setFreeFont(FF0);}
if (n_font == 2) { TFT.setFreeFont(FM9);}
if (n_font == 3) { TFT.setFreeFont(FMB9);}
if (n_font == 4) { TFT.setFreeFont(FSS9);}
TFT.drawString(s, x0+3, y0 + 2);
}
uint8_t TOUCH_BOUTON::read_dx()
{
return dx;
}
uint8_t TOUCH_BOUTON::read_dy()
{
return dy;
}
/** ***************************************************************************************
CLASS NUMPAD
********************************************************************************************/
// Constructeur
NUM_PAD::NUM_PAD()
{
}
void NUM_PAD::init(uint16_t xi, uint16_t yi, boolean fond) // si fond =false, ne resessine que les boutons
{
x0 = xi;
y0 = yi;
uint16_t x, y;
uint8_t dxt = 25; // taille x d'une touche
uint8_t dyt = 23; // taille y d'une touche
if(fond == true) {TFT.fillRect(x0, y0, 3*dxt +6, 4*dyt +7, NOIR);}
if(fond == true) {TFT.fillRect(x0, y0, 3*dxt +6, 4*dyt +7, NOIR);}
uint16_t c1 = GRIS_5;
uint16_t c2 = JAUNE;
x = x0+2;
y = y0+2;
for(uint8_t n =1; n<10; n++)
{
bt_pad[n].init(x, y, dxt, dyt, 3);
bt_pad[n].s=String(n);
bt_pad[n].affiche(c1, c2, 2);
x += dxt+1;
if (x > (x0 + 3*dxt)) {x = x0+2; y += dyt+1; }
}
bt_pad[0].init(x, y, dxt, dyt, 3); bt_pad[0].s="0"; bt_pad[0].affiche(c1, c2, 2); x += dxt+1;
bt_point.init(x, y, dxt, dyt, 3); bt_point.s="."; bt_point.affiche(c1, c2, 2);
x += dxt+1;
bt_ok.init(x, y, dxt, dyt, 3); bt_ok.s="ok";
bt_ok.affiche(c1, c2, 1);
}
uint8_t NUM_PAD::test_clic()
{
// zone des boutons du clavier
if ( (( x_touch > x0) && (x_touch < x0 + 100)) && (( y_touch > y0) && (y_touch < y0 + 130)))
{
uint8_t num_touche =0;
for(uint8_t n = 0; n<10; n++)
{
test_clic_boutons(&bt_pad[n] ); if(bt_pad[n].cliked) {num_touche=n; n_appui ++;}
}
test_clic_boutons(&bt_point ); if(bt_point.cliked) {num_touche=254; } // bouton "."
test_clic_boutons(&bt_ok ); if(bt_ok.cliked) {num_touche=255; n_appui ++;} // bouton "ok"
delay(100);
init(x0, y0, false); // 'false' évite le clignotement lorsqu'on repeint le fond noir
return num_touche;
}
return 253;
}
/** ***************************************************************************************
CLASS PRESET_PAD
********************************************************************************************/
// Constructeur
PRESET_PAD::PRESET_PAD()
{
}
void PRESET_PAD::init(uint16_t xi, uint16_t yi)
{
x0 = xi;
y0 = yi;
uint16_t c1 = GRIS_5;
uint16_t c2 = JAUNE;
uint16_t x2, y2;
x2 = x0;
y2= y0;
for(uint8_t n=0; n<8; n++)
{
bt_preset[n].init(x2, y2, 15, 15, 3);
bt_preset[n].s=String(n+1);
if(mode_affi == COUL) {c1 = bt_preset[n].couleur;}
bt_preset[n].affiche(c1, c2, 1);
x2 += 20;
}
}
uint8_t PRESET_PAD::read_dx()
{
return dx;
}
uint8_t PRESET_PAD::read_dy()
{
return dy;
}
void PRESET_PAD::set_frequences() // lit les fréquences en EEPROM et les attribue à chaque bouton
{
Serial.println("");
Serial.println("void PRESET_PAD::set_frequences() // lit les frequences en EEPROM et les attribue a chaque bouton");
uint16_t decal=0;
uint8_t n=0;
Serial.println("SW ---------------------------");
for(int n=0; n<8; n++)
{
frequence = EEPROM.readUInt(frq_preset_adr_0 + decal); // uint32_ t frequence, soit 4 octets
Serial.print("f= "); Serial.println(frequence);
if (! (bande_SW)) {frequence = 2000;}
bt_preset[n].frequence_SW = frequence;
decal += 4;
}
Serial.println("FM ---------------------------");
for(int n=0; n<8; n++)
{
frequence = EEPROM.readUInt(frq_preset_adr_0 + decal); // uint32_ t frequence, soit 4 octets
Serial.print("f= "); Serial.println(frequence);
if (! (bande_FM)) {frequence = 88000;}
bt_preset[n].frequence_FM = frequence;
decal += 4;
}
Serial.println("AIR ---------------------------");
for(int n=0; n<8; n++)
{
frequence = EEPROM.readUInt(frq_preset_adr_0 + decal); // uint32_ t frequence, soit 4 octets
Serial.print("f= "); Serial.println(frequence);
if (! (bande_AIR)) {frequence = 118000;}
bt_preset[n].frequence_AIR= frequence;
//decal += 4;
}
}
void PRESET_PAD::set_couleurs()
{
bt_preset[0].couleur = 10240; // rouge sombre
bt_preset[1].couleur = 14528; // orange
bt_preset[2].couleur = 320; // vert
bt_preset[3].couleur = 14407; // violet
bt_preset[4].couleur = 26787; // rose
bt_preset[5].couleur = 260; // cyan
bt_preset[6].couleur = 267; // bleu ciel
bt_preset[7].couleur = 4; // bleu marine
}
void PRESET_PAD::deselect_boutons()
{
uint16_t c1 = GRIS_5;
uint16_t c2 = JAUNE;
for(int n =0; n<8; n++)
{
bt_preset[n].selected=false;
bt_preset[n].cliked=false;
bt_preset[n].affiche(c1, c2, 1);
}
}
uint8_t PRESET_PAD::test_clic()
{
if ( (( x_touch > x0) && (x_touch < (x0+155))) && (( y_touch > y0) && (y_touch < (y0+15))))
{
uint8_t num_bouton =0;
for(uint8_t n=0; n<8; n++)
{
test_clic_boutons(&bt_preset[n]);
if(bt_preset[n].cliked)
{
deselect_boutons(); // les autres
bt_preset[n].selected =true; // pour l'affichage de celui-ci
bt_preset[n].affiche(GRIS_5, VERT, 1);
num_bouton = n;
Serial.print("BB num_bouton= "); Serial.println(num_bouton);
}
}
return num_bouton;
}
return 253;
}
/** ***************************************************************************************
CLASS GROUPE_FREQUENCES // objet image d'un bloc mémoire en EEPROM
permet diverses manipulations en RAM (tri...) sans toucher à l'EEPROM
********************************************************************************************/
// Constructeur
GROUPE_FREQUENCES::GROUPE_FREQUENCES()
{
}
void GROUPE_FREQUENCES::RAZ() // en RAM uniquement
{
for(int n=0; n<100; n++)
{
G_freq[n]=0;
}
nb_freq = 0;
}
void GROUPE_FREQUENCES::load_bloc() // depuis l'EEPROM
{
// partie données de fréquences (adrs >100)
Serial.println("load_bloc()");
//Serial.print("adr_0= "); Serial.println(adr_0);
uint32_t valeur_lue;
for(uint16_t n = 0; n<100; n++ ) // chaque uint32_t lu = 4 Bytes
{
valeur_lue = EEPROM.readUInt(adr_0 + n*4); // 4 octets
G_freq[n]=valeur_lue;
}
}
void GROUPE_FREQUENCES::tri_bloc()
{
Serial.println("tri_block()");
// tri par bulles
uint32_t F1=0, F2=0;
uint32_t Fi;
uint16_t i_max = 100;
uint16_t p_max = 100;
for(uint16_t p=0; p<p_max; p++)
{
for(int n=0; n<i_max-1; n++)
{
F1=G_freq[n];
F2=G_freq[n+1];
if(F1 > F2)
{
Fi = G_freq[n];
G_freq[n] = G_freq[n+1];
G_freq[n+1] = Fi;
}
}
}
// compte le nombre de fréquences != 0
uint16_t nombre =0;
for(uint16_t n = 0; n<100; n++ )
{
F1 = G_freq[n];
if(F1 != 0) { nombre++; }
}
nb_freq = nombre;
// recherche première fréquence non nulle
uint16_t n2=0;
F1 =0;
while ((F1==0) && (n2<100))
{
F1=G_freq[n2];
n2++;
}
adr_1ere_frq = n2-1; // 1ere F non nulle
}
void GROUPE_FREQUENCES::bloc_to_serial() // pour tests, avec CuteCom sous Linux
{
Serial.println("bloc_to_serial()");
uint32_t valeur_lue;
uint16_t nombre =0;
for(uint16_t n = 0; n<100; n++ )
{
valeur_lue = G_freq[n];
if(valeur_lue != 0) // n'affiche pas les emplacements vides
{
nombre++;
Serial.println(valeur_lue);
}
}
Serial.print(nombre); Serial.println(" frequences");
Serial.print("adr 1ere Frq (dans le groupe) = "); Serial.println(adr_1ere_frq);
Serial.print("1ere Frq= "); Serial.println(G_freq[adr_1ere_frq]);
}
void GROUPE_FREQUENCES::add_frq(uint32_t Fi) // en RAM uniquement
{
if (nb_freq >= 100) {return;}
Serial.println("GROUPE_FREQUENCES::add_frq()");
tri_bloc(); // les F nulles se retrouvent en haut
Serial.print("Ajout frequence: "); Serial.println(Fi);
G_freq[0] = Fi; // la nouvelle fréquence est placée en haut
nb_freq++;
tri_bloc(); // la nouvelle fréquence se retrouve rangée dans l'ordre de F croissantes
}
void GROUPE_FREQUENCES::erase_1_freq(uint32_t Fi) // en RAM
{
Serial.println("GROUPE_FREQUENCES::erase_1_freq()");
uint32_t valeur_lue;
for(int n=0; n<100; n++)
{
valeur_lue = G_freq[n];
if(valeur_lue == Fi)
{
G_freq[n]=0;
}
}
tri_bloc();
}