From fd5a9292f77f65c59c3fd59321a9f6349d3b69c7 Mon Sep 17 00:00:00 2001 From: marsel90-1 <60916643+marsel90-1@users.noreply.github.com> Date: Sun, 19 May 2024 20:32:49 +0300 Subject: [PATCH 1/8] Update language.h Romanian language update! --- src/language.h | 208 ++++++++++++++++++++++++------------------------- 1 file changed, 104 insertions(+), 104 deletions(-) diff --git a/src/language.h b/src/language.h index 6ce8aea..75c71cd 100644 --- a/src/language.h +++ b/src/language.h @@ -1157,23 +1157,23 @@ static const char* const myLanguage[18][228] PROGMEM = { }, { "Română", // Romanian - "Directia rotirii schimbata", // 1 - "Eliberati butonul", // 2 - "Display rasturnat", // 3 - "Calibrati instrumentul analog", // 4 - "Eliberati butonul la gata", // 5 - "encoderul setat pe optic", // 6 - "encoderul setat pe standard", // 7 - "FM/AM receptor", // 8 - "Lipsa: !Tuner!", // 9 + "Direcția rotirii schimbată", // 1 + "Eliberați butonul", // 2 + "Ecran întors", // 3 + "Calibrați instrumentul analog", // 4 + "Eliberați butonul când este gata", // 5 + "encoderul setat optic", // 6 + "encoderul setat standard", // 7 + "Receptor FM/AM", // 8 + "Lipsă: !Tuner!", // 9 "Volum", // 10 "Convertor", // 11 "Marginea de jos a benzii", // 12 "Marginea de sus a benzii", // 13 - "FM RF Nivel offset", // 14 + "Calibrare nivel RF FM", // 14 "Pragul ptr Stereo", // 15 - "Limita taiere inalte", // 16 - "Prag taiere inalte", // 17 + "Limită tăiere înalte", // 16 + "Prag tăiere înalte", // 17 "Prag nivel joase", // 18 "Contrast", // 19 "Setare volum", // 20 @@ -1182,80 +1182,80 @@ static const char* const myLanguage[18][228] PROGMEM = { "Setarea limitei de sus a benzii", // 23 "Setare nivel decalaj", // 24 "Setarea pragului sep. Stereo ", // 25 - "Setare taiere frecv, inalte ", // 26 - "Setare prag taiere inalte", // 27 - "Setarea pragului joase", // 28 - "Setare luminozitate display", // 29 + "Setare tăiere frecv, înalte ", // 26 + "Setare prag tăiere înalte", // 27 + "Setarea pragului la joase", // 28 + "Setare luminozitate ecran", // 29 "Oprit", // 30 "Ecran blocat!", // 31 - "ptr deblocare debifati RF+ box", // 32 + "ptr deblocare debifati RF+", // 32 "Oprit", // 33 "SCANEZ...", // 34 "Tunerul nu este prezent", // 35 - "AM Antenna gain", // 36 + "Reglare nivel antenă AM", // 36 "FM AGC", // 37 - "Arata erorile RDS", // 38 - "Limba", // 39 - "Alegeti Limba", // 40 - "Apasati MODE ptr MEMORARE si iesire", // 41 + "Arată erorile RDS", // 38 + "Limbă", // 39 + "Alegeți Limba", // 40 + "Apasați MODE ptr MEMORARE și ieșire", // 41 "Pornit", // 42 - "lipsa zgomot FM", // 43 - "lipsa zgomot AM", // 44 - "Beep la capatul benzii", // 45 + "lipsă zgomot FM", // 43 + "lipsă zgomot AM", // 44 + "Beep la capătul benzii", // 45 "Regiune", // 46 "Europa", // 47 "America", // 48 - "Afiseaza subliniere in RDS", // 49 + "Afișează subliniere la RDS", // 49 "Mod USB", // 50 "Wi-Fi activ", // 51 "Configurare Wi-Fi", // 52 "Conectare la: ", // 53 "ptr configurare Wi-Fi", // 54 "Incerc conectarea la Wi-Fi", // 55 - "Fara succes!", // 56 + "Fară succes!", // 56 "Conectat!", // 57 - "Lista adrese IP", // 58 - "Arat? lungimea de unda SW", // 59 + "Listă adrese IP", // 58 + "Arată lungimea de undă SW", // 59 "Filtru RDS", // 60 - "Arata erorile PI", // 61 - "foloseste squelch", // 62 - "Contor modulatie", // 63 + "Arată erorile PI", // 61 + "folosește squelch", // 62 + "Contor modulație", // 63 "Eliminator de zgomot AM", // 64 "Eliminator de zgomot FM", // 65 - "Revenire setari implicite", // 66 - "iesire Audio", // 67 - "Permite reglarea in timpul screensaverului", // 68 + "Revenire la setările de fabrică", // 66 + "ieșire Audio", // 67 + "Permite reglarea in timp ce ecranul este oprit", // 68 "Ecran inversat", // 69 - "Despresoftware", // 70 + "Despre software", // 70 "cod principal:", // 71 "Contribuitori:", // 72 "Necunoscut", // 73 - "Optiuni Screensaver", // 74 - "Pauza temporizator", // 75 + "Opțiuni economizor ecran", // 74 + "Pauză temporizator", // 75 "Ecran oprit", // 76 - "Tema", // 77 + "Temă", // 77 "Mod vizualizare", // 78 - "Aplicatii detectate", // 79 + "Aplicații detectate", // 79 "Min.", // 80 - "Viteza SPI dinamica", // 81 - "Sensibilitatea scanarii", // 82 + "Viteză SPI dinamică", // 81 + "Sensibilitatea scanării", // 82 "NICI UNUL", // 83 " versiune Software", // 84 - "Font Frecventa", // 85 + "Font Frecvență", // 85 "Auto", // 86 "AF nu este disponibil", // 87 "EON nu este disponibil", // 88 "RT+ nu este disponibil", // 89 - "Marime pasi FM", // 90 + "Mărime pași FM", // 90 "Screensaver", // 91 "Sec", // 92 - "Apasati BAND pentru inchidere", // 93 + "Apăsați BAND pentru inchidere", // 93 "luminozitate 1%", // 94 "luminozitate 25%", // 95 "luminozitate 50%", // 96 "Decalaj de nivel AM RF", // 97 - "unitati S-metru", // 98 - "folosesti AF", // 99 + "unitați S-metru", // 98 + "folosești AF", // 99 "Selectare banda FM", // 100 "Selectare banda AM", // 101 "LW", // 102 @@ -1263,30 +1263,30 @@ static const char* const myLanguage[18][228] PROGMEM = { "SW", // 104 "FM", // 105 "OIRT", // 106 - "Rotire timp ce ecranul este oprit", // 107 + "Rotire când ecranul este oprit", // 107 " selectare Model", // 108 - "Baza (ILI9341)", // 109 + "Bază (ILI9341)", // 109 "Portabil (ILI9341)", // 110 "Portabil touch (ILI9341)", // 111 "Titlu", // 112 "Album", // 113 - "Banda", // 114 + "Bandă", // 114 "Artist", // 115 - "Compozitie", // 116 - "Miscare", // 117 - "Dirijir", // 118 + "Compoziție", // 116 + "Mișcare", // 117 + "Dirijor", // 118 "Compozitor", // 119 - "Formatia", // 120 + "Formație", // 120 "Comentarii", // 121 "Gen", // 122 - "Stiri", // 123 - "Stiri Locale", // 124 + "Știri", // 123 + "Știri Locale", // 124 "Bursa de Valori", // 125 "Sport", // 126 "Loto", // 127 "Horoscop", // 128 "Info zilnice", // 129 - "Sanatate", // 130 + "Sănătate", // 130 "Evenimente", // 131 "Teatru", // 132 "Cinema", // 133 @@ -1294,18 +1294,18 @@ static const char* const myLanguage[18][228] PROGMEM = { "Data/ora", // 135 "Meteo", // 136 "Trafic", // 137 - "Alarma", // 138 - "Reclamet", // 139 + "Alarmă", // 138 + "Reclame", // 139 "Website", // 140 "Altele", // 141 "PS scurt", // 142 "PS lung", // 143 "Acum", // 144 - "Urmeaza", // 145 + "Urmează", // 145 "Parte", // 146 - "Gazda", // 147 + "Gazdă", // 147 "Editor", // 148 - "Frecventa", // 149 + "Frecvența", // 149 "Pagina start", // 150 "Sub canal", // 151 "Linia fierbinte", // 152 @@ -1316,35 +1316,35 @@ static const char* const myLanguage[18][228] PROGMEM = { "Email Linie fierbinte", // 157 "Email studio", // 158 "Email", // 159 - "Discutii", // 160 - "Centru discutii", // 161 + "Discuții", // 160 + "Centru discuții", // 161 "Intrebare la vot", // 162 "Centru votare", // 163 "Loc", // 164 - "Intalnire", // 165 + "Intâlnire", // 165 "Identificare", // 166 - "Cumpara", // 167 + "Cumpără", // 167 "Preiau date", // 168 - "pasi MW impliciti", // 169 + "pași MW impliciți", // 169 "Tangerine", // 170 "Ocean", // 171 "Indigo", // 172 - "Optiuni Baterie", // 173 - "Arata tensiunea", // 174 - "Arata procente", // 175 - "portiune RT", // 176 - "Setari de baza", // 177 - "Setari Audio", // 178 - "Setari ecran", // 179 - "Setari RDS", // 180 - "Setari FM", // 181 - "Setari AM ", // 182 + "Opțiuni Baterie", // 173 + "Arată tensiunea", // 174 + "Arată procente", // 175 + "porțiune RT", // 176 + "Setări de bază", // 177 + "Setări Audio", // 178 + "Setări ecran", // 179 + "Setări RDS", // 180 + "Setări FM", // 181 + "Setări AM ", // 182 "Conectivitate", // 183 - "Apasa MODE ptr revenire", // 184 + "Apasă MODE ptr revenire", // 184 "Detector CoChannel", // 185 - "Detectie in sensibilitate CoChannel ", // 186 - "Detectie prag CoChannel", // 187 - "Detector in contor CoChannel", // 188 + "Detecție sensibilitate CoChannel ", // 186 + "Detecție prag CoChannel", // 187 + "Detector contor CoChannel", // 188 "PRINCIPAL", // 189 "AUDIO", // 190 "ECRAN", // 191 @@ -1352,8 +1352,8 @@ static const char* const myLanguage[18][228] PROGMEM = { "FM", // 193 "AM", // 194 "CONECTARE", // 195 - "DX MODE", // 196 - "ID Lista posturi", // 197 + "MOD DX", // 196 + "Listă ID posturi", // 197 "AGC AM", // 198 "FM deemphasis", // 199 "Mic", // 200 @@ -1361,29 +1361,29 @@ static const char* const myLanguage[18][228] PROGMEM = { "Tot", // 202 "PS rapid", // 203 "Mod implicit", // 204 - "Mute screen on\nXDRGTK connection", // 205 - "FMSI stereo\nimprovement", // 206 - "Function only available\non TEF6687/6689!", // 207 - "Function not available\non selected skin!", // 208 - "Begin scanning\nmemory channels", // 209 - "Stop scanning\nmemory channels", // 210 - "Wait time", // 211 - "Start DX scanning", // 212 - "FM DX Options", // 213 - "Abort! The start channel\nis marked as skipped.", // 214 - "Sortare automata AF", // 215 - "Memory channels", // 216 + "Ecran oprit, conectat la XDRGTK", // 205 + "FMSI stereo imbunătățit", // 206 + "Funcție activă doar la\nTEF6687/6689!", // 207 + "Funcție indisponibilă\nla acest skin!", // 208 + "Scanare incepută\nmemorare posturi", // 209 + "Scanare terminată\nmemorare posturi", // 210 + "Așteaptă", // 211 + "Începe scanarea DX", // 212 + "FM DX Opțiuni", // 213 + "Terminat! Programul de pornire\neste ignorat.", // 214 + "Sortare automată AF", // 215 + "Memorare programe", // 216 "Exclude", // 217 - "Only", // 218 - "Auto cancel scan", // 219 - "Correct PI", // 220 - "Signal", // 221 - "Mute audio\nwhile scanning", // 222 + "Doar", // 218 + "Auto oprire scanare", // 219 + "PI corect", // 220 + "Semnal", // 221 + "Audio oprit\ncand scanează", // 222 "AIR", // 223 - "5 sec. bandbutton press", // 224 - "Power off", // 225 - "Mute screen", // 226 - "Disabled" // 227 + "Apasaă 5 sec. butonul bandă", // 224 + "Oprit", // 225 + "Ecran oprit", // 226 + "Dezactivat" // 227 }, { "Deutsch", // German From b61a1cd70b6fe5256db0a19a6563c0af7315c22e Mon Sep 17 00:00:00 2001 From: marsel90-1 <60916643+marsel90-1@users.noreply.github.com> Date: Tue, 21 May 2024 12:55:18 +0300 Subject: [PATCH 2/8] Update language.h Little language update ! --- src/language.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/language.h b/src/language.h index 75c71cd..98ab0e5 100644 --- a/src/language.h +++ b/src/language.h @@ -1182,7 +1182,7 @@ static const char* const myLanguage[18][228] PROGMEM = { "Setarea limitei de sus a benzii", // 23 "Setare nivel decalaj", // 24 "Setarea pragului sep. Stereo ", // 25 - "Setare tăiere frecv, înalte ", // 26 + "Setare tăiere frecv. înalte ", // 26 "Setare prag tăiere înalte", // 27 "Setarea pragului la joase", // 28 "Setare luminozitate ecran", // 29 @@ -1264,7 +1264,7 @@ static const char* const myLanguage[18][228] PROGMEM = { "FM", // 105 "OIRT", // 106 "Rotire când ecranul este oprit", // 107 - " selectare Model", // 108 + "selectare Model", // 108 "Bază (ILI9341)", // 109 "Portabil (ILI9341)", // 110 "Portabil touch (ILI9341)", // 111 @@ -1362,10 +1362,10 @@ static const char* const myLanguage[18][228] PROGMEM = { "PS rapid", // 203 "Mod implicit", // 204 "Ecran oprit, conectat la XDRGTK", // 205 - "FMSI stereo imbunătățit", // 206 + "FMSI stereo îmbunătățit", // 206 "Funcție activă doar la\nTEF6687/6689!", // 207 "Funcție indisponibilă\nla acest skin!", // 208 - "Scanare incepută\nmemorare posturi", // 209 + "Scanare începută\nmemorare posturi", // 209 "Scanare terminată\nmemorare posturi", // 210 "Așteaptă", // 211 "Începe scanarea DX", // 212 @@ -1378,9 +1378,9 @@ static const char* const myLanguage[18][228] PROGMEM = { "Auto oprire scanare", // 219 "PI corect", // 220 "Semnal", // 221 - "Audio oprit\ncand scanează", // 222 + "Audio oprit\ncând scanează", // 222 "AIR", // 223 - "Apasaă 5 sec. butonul bandă", // 224 + "Apasă 5sec. butonul bandă", // 224 "Oprit", // 225 "Ecran oprit", // 226 "Dezactivat" // 227 From 0390251b0091cca88c5cbad293f22b6aa5cab515 Mon Sep 17 00:00:00 2001 From: Sjef Verhoeven PE5PVB Date: Tue, 21 May 2024 12:16:35 +0200 Subject: [PATCH 3/8] Added OIRT to FM DX scan --- TEF6686_ESP32.ino | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/TEF6686_ESP32.ino b/TEF6686_ESP32.ino index 4986f30..af93310 100644 --- a/TEF6686_ESP32.ino +++ b/TEF6686_ESP32.ino @@ -804,7 +804,7 @@ void loop() { if (scanmem) { memorypos++; if (memorypos > scanstop) memorypos = scanstart; - while (IsStationEmpty() || presets[memorypos].band != BAND_FM) { + while (IsStationEmpty() || (presets[memorypos].band != BAND_FM && presets[memorypos].band != BAND_OIRT)) { memorypos++; if (memorypos > scanstop) { memorypos = scanstart; From 19aa5168903b555342666c83faac25f54839ca8b Mon Sep 17 00:00:00 2001 From: Sjef Verhoeven PE5PVB Date: Tue, 21 May 2024 12:40:44 +0200 Subject: [PATCH 4/8] Fixed 0x0d handling on LPS RDS parsing --- src/TEF6686.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/TEF6686.cpp b/src/TEF6686.cpp index f6109f8..b24fff7 100644 --- a/src/TEF6686.cpp +++ b/src/TEF6686.cpp @@ -1518,8 +1518,10 @@ void TEF6686::readRDS(byte showrdserrors) { pslong_buffer[32] = '\0'; byte endmarker = 32; + bool foundendmarker = false; for (byte i = 0; i < 33; i++) { if (pslong_buffer[i] == 0x0d) { + foundendmarker = true; endmarker = i; break; } @@ -1529,7 +1531,7 @@ void TEF6686::readRDS(byte showrdserrors) { if (strcmp(pslong_buffer, pslong_buffer2) == 0) { // When no difference between current and buffer, let's go... RDScharConverter(pslong_buffer, PSLongtext, sizeof(PSLongtext) / sizeof(wchar_t), true); // Convert 8 bit ASCII to 16 bit ASCII String utf8String = convertToUTF8(PSLongtext); // Convert RDS characterset to ASCII - rds.stationNameLong = extractUTF8Substring(utf8String, 0, endmarker, true); // Make sure PS Long does not exceed 32 characters + rds.stationNameLong = extractUTF8Substring(utf8String, 0, endmarker, true); // Make sure PS Long does not exceed 32 characters } } @@ -1538,10 +1540,10 @@ void TEF6686::readRDS(byte showrdserrors) { if (offset == 4) packet1long = true; if (offset == 8) packet2long = true; if (offset == 16) packet3long = true; - RDScharConverter(pslong_buffer, PSLongtext, sizeof(PSLongtext) / sizeof(wchar_t), true); // Convert 8 bit ASCII to 16 bit ASCII - String utf8String = convertToUTF8(PSLongtext); // Convert RDS characterset to ASCII + RDScharConverter(pslong_buffer, PSLongtext, sizeof(PSLongtext) / sizeof(wchar_t), true); // Convert 8 bit ASCII to 16 bit ASCII + String utf8String = convertToUTF8(PSLongtext); // Convert RDS characterset to ASCII rds.stationNameLong = extractUTF8Substring(utf8String, 0, endmarker, true); - if (packet0long && packet1long && packet2long && packet3long) pslong_process = true; // OK, we had one runs, now let's go the idle PS Long writing + if ((packet0long && packet1long && packet2long && packet3long) || foundendmarker) pslong_process = true; // OK, we had one runs, now let's go the idle PS Long writing } } } From 5e1c2af819ea7987880f1ccc33da5ae20c6d8d9c Mon Sep 17 00:00:00 2001 From: Sjef Verhoeven PE5PVB Date: Tue, 21 May 2024 13:06:43 +0200 Subject: [PATCH 5/8] Trim spaces at the end of RT when transmitter is not using 0x0d as end command --- src/TEF6686.cpp | 9 +++++++++ src/TEF6686.h | 1 + 2 files changed, 10 insertions(+) diff --git a/src/TEF6686.cpp b/src/TEF6686.cpp index b24fff7..1ddf699 100644 --- a/src/TEF6686.cpp +++ b/src/TEF6686.cpp @@ -1167,6 +1167,7 @@ void TEF6686::readRDS(byte showrdserrors) { RDScharConverter(rt_buffer, RTtext, sizeof(RTtext) / sizeof(wchar_t), true); // Convert 8 bit ASCII to 16 bit ASCII rds.stationText = convertToUTF8(RTtext); // Convert RDS characterset to ASCII rds.stationText = extractUTF8Substring(rds.stationText, 0, endmarker, true); // Make sure RT does not exceed 64 characters + rds.stationText = trimTrailingSpaces(rds.stationText); // Trim empty spaces at the end } for (byte i = 0; i < 64; i++) { @@ -1188,6 +1189,7 @@ void TEF6686::readRDS(byte showrdserrors) { RDScharConverter(rt_buffer, RTtext, sizeof(RTtext) / sizeof(wchar_t), true); // Convert 8 bit ASCII to 16 bit ASCII rds.stationText = convertToUTF8(RTtext); // Convert RDS characterset to ASCII rds.stationText = extractUTF8Substring(rds.stationText, 0, endmarker, true); // Make sure RT does not exceed 64 characters + rds.stationText = trimTrailingSpaces(rds.stationText); // Trim empty spaces at the end } for (int i = 0; i < 64; i++) rt_buffer2[i] = rt_buffer[i]; @@ -1224,6 +1226,7 @@ void TEF6686::readRDS(byte showrdserrors) { RDScharConverter(rt_buffer32, RTtext, sizeof(RTtext) / sizeof(wchar_t), true); // Convert 8 bit ASCII to 16 bit ASCII rds.stationText32 = convertToUTF8(RTtext); // Convert RDS characterset to ASCII rds.stationText32 = extractUTF8Substring(rds.stationText32, 0, endmarker, true); // Make sure RT does not exceed 32 characters + rds.stationText = trimTrailingSpaces(rds.stationText); // Trim empty spaces at the end } } break; @@ -1925,4 +1928,10 @@ void TEF6686::RDScharConverter(const char* input, wchar_t* output, size_t size, } } output[size - 1] = L'\0'; +} + +String TEF6686::trimTrailingSpaces(String str) { + int end = str.length() - 1; + while (end >= 0 && isspace(str[end])) end--; + return str.substring(0, end + 1); } \ No newline at end of file diff --git a/src/TEF6686.h b/src/TEF6686.h index fcdaa24..5c92d9f 100644 --- a/src/TEF6686.h +++ b/src/TEF6686.h @@ -718,6 +718,7 @@ class TEF6686 { void RDScharConverter(const char* input, wchar_t* output, size_t size, bool under); String convertToUTF8(const wchar_t* input); String extractUTF8Substring(const String& utf8String, size_t start, size_t length, bool under); + String trimTrailingSpaces(String str); char ps_buffer[9]; char ps_buffer2[9]; char ptyn_buffer[9]; From 7388de7a2e2189e26b9f52d404128a7ce0145900 Mon Sep 17 00:00:00 2001 From: Sjef Verhoeven PE5PVB Date: Tue, 21 May 2024 21:53:22 +0200 Subject: [PATCH 6/8] Bugfix on Long PS decoder --- src/TEF6686.cpp | 35 +++++++++++++++++++---------------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/src/TEF6686.cpp b/src/TEF6686.cpp index 1ddf699..3c0a8cc 100644 --- a/src/TEF6686.cpp +++ b/src/TEF6686.cpp @@ -608,6 +608,7 @@ void TEF6686::readRDS(byte showrdserrors) { if (offset == 3 && (ps_process || !rds.fastps)) { // Last chars are received if (strcmp(ps_buffer, ps_buffer2) == 0) { // When no difference between current and buffer, let's go... + ps_process = true; RDScharConverter(ps_buffer2, PStext, sizeof(PStext) / sizeof(wchar_t), true); // Convert 8 bit ASCII to 16 bit ASCII String utf8String = convertToUTF8(PStext); // Convert RDS characterset to ASCII rds.stationName = extractUTF8Substring(utf8String, 0, 8, true); // Make sure PS does not exceed 8 characters @@ -1152,10 +1153,10 @@ void TEF6686::readRDS(byte showrdserrors) { initab = false; } - byte endmarker = 64; - for (byte i = 0; i < endmarker; i++) { + byte endmarkerRT64 = 64; + for (byte i = 0; i < endmarkerRT64; i++) { if (rt_buffer[i] == 0x0d) { - endmarker = i; + endmarkerRT64 = i; break; } } @@ -1166,7 +1167,7 @@ void TEF6686::readRDS(byte showrdserrors) { wchar_t RTtext[65] = L""; // Create 16 bit char buffer for Extended ASCII RDScharConverter(rt_buffer, RTtext, sizeof(RTtext) / sizeof(wchar_t), true); // Convert 8 bit ASCII to 16 bit ASCII rds.stationText = convertToUTF8(RTtext); // Convert RDS characterset to ASCII - rds.stationText = extractUTF8Substring(rds.stationText, 0, endmarker, true); // Make sure RT does not exceed 64 characters + rds.stationText = extractUTF8Substring(rds.stationText, 0, endmarkerRT64, true);// Make sure RT does not exceed 64 characters rds.stationText = trimTrailingSpaces(rds.stationText); // Trim empty spaces at the end } @@ -1188,7 +1189,7 @@ void TEF6686::readRDS(byte showrdserrors) { wchar_t RTtext[65] = L""; // Create 16 bit char buffer for Extended ASCII RDScharConverter(rt_buffer, RTtext, sizeof(RTtext) / sizeof(wchar_t), true); // Convert 8 bit ASCII to 16 bit ASCII rds.stationText = convertToUTF8(RTtext); // Convert RDS characterset to ASCII - rds.stationText = extractUTF8Substring(rds.stationText, 0, endmarker, true); // Make sure RT does not exceed 64 characters + rds.stationText = extractUTF8Substring(rds.stationText, 0, endmarkerRT64, true); // Make sure RT does not exceed 64 characters rds.stationText = trimTrailingSpaces(rds.stationText); // Trim empty spaces at the end } @@ -1214,10 +1215,10 @@ void TEF6686::readRDS(byte showrdserrors) { rt_buffer32[offset + 0] = rds.rdsD >> 8; // First character of segment rt_buffer32[offset + 1] = rds.rdsD & 0xff; // Second character of segment - byte endmarker = 32; - for (byte i = 0; i < endmarker; i++) { + byte endmarkerRT32 = 32; + for (byte i = 0; i < endmarkerRT32; i++) { if (rt_buffer[i] == 0x0d) { - endmarker = i; + endmarkerRT32 = i; break; } } @@ -1225,7 +1226,7 @@ void TEF6686::readRDS(byte showrdserrors) { wchar_t RTtext[33] = L""; // Create 16 bit char buffer for Extended ASCII RDScharConverter(rt_buffer32, RTtext, sizeof(RTtext) / sizeof(wchar_t), true); // Convert 8 bit ASCII to 16 bit ASCII rds.stationText32 = convertToUTF8(RTtext); // Convert RDS characterset to ASCII - rds.stationText32 = extractUTF8Substring(rds.stationText32, 0, endmarker, true); // Make sure RT does not exceed 32 characters + rds.stationText32 = extractUTF8Substring(rds.stationText32, 0, endmarkerRT32, true);// Make sure RT does not exceed 32 characters rds.stationText = trimTrailingSpaces(rds.stationText); // Trim empty spaces at the end } } break; @@ -1505,7 +1506,7 @@ void TEF6686::readRDS(byte showrdserrors) { case RDS_GROUP_15A: { if (showrdserrors == 3 || (!rdsBerrorThreshold && !rdsCerrorThreshold && !rdsDerrorThreshold)) { - if (pslong_process) rds.hasLongPS = true; + if (pslong_process && rds.stationNameLong.length() > 0) rds.hasLongPS = true; offset = (rds.rdsB & 0xf) * 4; // Get Long PS character segment pslong_buffer2[offset + 0] = pslong_buffer[offset + 0]; // Copy PS long buffer @@ -1520,21 +1521,22 @@ void TEF6686::readRDS(byte showrdserrors) { pslong_buffer[offset + 3] = rds.rdsD & 0xff; // Fourth character of segment pslong_buffer[32] = '\0'; - byte endmarker = 32; + byte endmarkerLPS = 32; bool foundendmarker = false; - for (byte i = 0; i < 33; i++) { + for (byte i = 0; i < endmarkerLPS; i++) { if (pslong_buffer[i] == 0x0d) { foundendmarker = true; - endmarker = i; + endmarkerLPS = i; break; } } - if (offset == 28 && (pslong_process || !rds.fastps)) { // Last chars are received + if ((offset == 28 || foundendmarker) && (pslong_process || !rds.fastps)) { // Last chars are received if (strcmp(pslong_buffer, pslong_buffer2) == 0) { // When no difference between current and buffer, let's go... + pslong_process = true; RDScharConverter(pslong_buffer, PSLongtext, sizeof(PSLongtext) / sizeof(wchar_t), true); // Convert 8 bit ASCII to 16 bit ASCII String utf8String = convertToUTF8(PSLongtext); // Convert RDS characterset to ASCII - rds.stationNameLong = extractUTF8Substring(utf8String, 0, endmarker, true); // Make sure PS Long does not exceed 32 characters + rds.stationNameLong = extractUTF8Substring(utf8String, 0, endmarkerLPS, true); // Make sure PS Long does not exceed 32 characters } } @@ -1545,7 +1547,7 @@ void TEF6686::readRDS(byte showrdserrors) { if (offset == 16) packet3long = true; RDScharConverter(pslong_buffer, PSLongtext, sizeof(PSLongtext) / sizeof(wchar_t), true); // Convert 8 bit ASCII to 16 bit ASCII String utf8String = convertToUTF8(PSLongtext); // Convert RDS characterset to ASCII - rds.stationNameLong = extractUTF8Substring(utf8String, 0, endmarker, true); + rds.stationNameLong = extractUTF8Substring(utf8String, 0, endmarkerLPS, true); if ((packet0long && packet1long && packet2long && packet3long) || foundendmarker) pslong_process = true; // OK, we had one runs, now let's go the idle PS Long writing } } @@ -1588,6 +1590,7 @@ void TEF6686::clearRDS (bool fullsearchrds) { for (i = 0; i < 32; i++) { rt_buffer32[i] = 0x20; pslong_buffer[i] = 0x20; + pslong_buffer2[i] = 0x20; PSLongtext[i] = L'\0'; } rt_buffer32[32] = 0; From 53ed1cbcaccfb7213260be160050c2e688a1482c Mon Sep 17 00:00:00 2001 From: Sjef Verhoeven PE5PVB Date: Tue, 21 May 2024 23:40:39 +0200 Subject: [PATCH 7/8] Added enhanced Radiotext --- src/TEF6686.cpp | 79 +++++++++++++++++++++++++++++++++++++++++++++++-- src/TEF6686.h | 8 +++++ src/rds.cpp | 18 +++++------ 3 files changed, 94 insertions(+), 11 deletions(-) diff --git a/src/TEF6686.cpp b/src/TEF6686.cpp index 3c0a8cc..8b463ba 100644 --- a/src/TEF6686.cpp +++ b/src/TEF6686.cpp @@ -1260,7 +1260,13 @@ void TEF6686::readRDS(byte showrdserrors) { if (rds.rdsD == 0x0093) { // Check for DAB+ AF application rds.hasDABAF = true; // Set flag - DABAFblock = ((rds.rdsB & 0x1F) >> 1) * 2; // Get RT+ Block + DABAFblock = ((rds.rdsB & 0x1F) >> 1) * 2; // Get DAB AF Block + } + + if (rds.rdsD == 0x6552) { // Check for Enhanced RT application + _hasEnhancedRT = true; // Set flag + eRTblock = ((rds.rdsB & 0x1F) >> 1) * 2; // Get eRT block + eRTcoding = bitRead(rds.rdsC, 0); // 0 = UCS-2, 1 = UTF-8 } } } break; @@ -1375,6 +1381,34 @@ void TEF6686::readRDS(byte showrdserrors) { rds.RTContent2 = convertToUTF8(RTtext2); // Convert RDS characterset to ASCII rds.RTContent2 = extractUTF8Substring(rds.RTContent2, 0, 44, false); // Make sure RT does not exceed 32 characters } + + // eRT decoding + if ((!rdsBerrorThreshold && !rdsCerrorThreshold && !rdsDerrorThreshold) && eRTblock == rdsblock && _hasEnhancedRT) { + offset = (rds.rdsB & 0x1f) * 4; + eRT_buffer[offset + 0] = rds.rdsC >> 8; // First character of segment + eRT_buffer[offset + 1] = rds.rdsC & 0xff; // Second character of segment + eRT_buffer[offset + 2] = rds.rdsD >> 8; // Thirth character of segment + eRT_buffer[offset + 3] = rds.rdsD & 0xff; // Fourth character of segment + eRT_buffer[127] = '\0'; + + byte endmarkereRT = 127; + bool foundendmarker = false; + for (byte i = 0; i < endmarkereRT; i++) { + if (eRT_buffer[i] == 0x0d) { + foundendmarker = true; + endmarkereRT = i; + break; + } + } + + if (offset == 0 || foundendmarker) { + if (eRTcoding) rds.enhancedRTtext = eRT_buffer; else rds.enhancedRTtext = utf8ToUcs2String(eRT_buffer); // Convert to UTF-8 or UCS-2 + rds.enhancedRTtext = trimTrailingSpaces(rds.enhancedRTtext); + if (rds.enhancedRTtext.length() > 0) rds.hasEnhancedRT = true; + } + } + + if (!rdsBerrorThreshold && rdsblock == 16 && (bitRead(rds.rdsB, 15))) rds.hasTMC = true; // TMC flag if ((!rdsBerrorThreshold && !rdsCerrorThreshold && !rdsDerrorThreshold) && DABAFblock == rdsblock && rds.hasDABAF) { @@ -1531,7 +1565,7 @@ void TEF6686::readRDS(byte showrdserrors) { } } - if ((offset == 28 || foundendmarker) && (pslong_process || !rds.fastps)) { // Last chars are received + if ((offset == 0 || foundendmarker) && (pslong_process || !rds.fastps)) { // Last chars are received if (strcmp(pslong_buffer, pslong_buffer2) == 0) { // When no difference between current and buffer, let's go... pslong_process = true; RDScharConverter(pslong_buffer, PSLongtext, sizeof(PSLongtext) / sizeof(wchar_t), true); // Convert 8 bit ASCII to 16 bit ASCII @@ -1548,6 +1582,7 @@ void TEF6686::readRDS(byte showrdserrors) { RDScharConverter(pslong_buffer, PSLongtext, sizeof(PSLongtext) / sizeof(wchar_t), true); // Convert 8 bit ASCII to 16 bit ASCII String utf8String = convertToUTF8(PSLongtext); // Convert RDS characterset to ASCII rds.stationNameLong = extractUTF8Substring(utf8String, 0, endmarkerLPS, true); + rds.stationNameLong = trimTrailingSpaces(rds.stationNameLong); if ((packet0long && packet1long && packet2long && packet3long) || foundendmarker) pslong_process = true; // OK, we had one runs, now let's go the idle PS Long writing } } @@ -1571,6 +1606,7 @@ void TEF6686::clearRDS (bool fullsearchrds) { rds.LICtext = ""; rds.stationIDtext = ""; rds.stationStatetext = ""; + rds.enhancedRTtext = ""; uint8_t i; for (i = 0; i < 8; i++) { @@ -1587,6 +1623,9 @@ void TEF6686::clearRDS (bool fullsearchrds) { for (i = 0; i < 64; i++) rt_buffer[i] = 0x20; rt_buffer[64] = 0; + for (i = 0; i < 128; i++) eRT_buffer[i] = 0x20; + eRT_buffer[128] = '\0'; + for (i = 0; i < 32; i++) { rt_buffer32[i] = 0x20; pslong_buffer[i] = 0x20; @@ -1675,6 +1714,7 @@ void TEF6686::clearRDS (bool fullsearchrds) { rds.hasLongPS = false; rds.hasRDSplus = false; rds.hasDABAF = false; + rds.hasEnhancedRT = false; rt_process = false; ps_process = false; pslong_process = false; @@ -1712,6 +1752,7 @@ void TEF6686::clearRDS (bool fullsearchrds) { afmethodBtrigger = false; correctPIold = 0; af_number = 0; + _hasEnhancedRT = false; } void TEF6686::tone(uint16_t time, int16_t amplitude, uint16_t frequency) { @@ -1937,4 +1978,38 @@ String TEF6686::trimTrailingSpaces(String str) { int end = str.length() - 1; while (end >= 0 && isspace(str[end])) end--; return str.substring(0, end + 1); +} + +String TEF6686::utf8ToUcs2String(const char* utf8) { + String ucs2; + while (*utf8) { + uint32_t codepoint = 0; + int extraBytes = 0; + + if ((*utf8 & 0x80) == 0) { + codepoint = *utf8++; + } else if ((*utf8 & 0xE0) == 0xC0) { + codepoint = *utf8++ & 0x1F; + extraBytes = 1; + } else if ((*utf8 & 0xF0) == 0xE0) { + codepoint = *utf8++ & 0x0F; + extraBytes = 2; + } else if ((*utf8 & 0xF8) == 0xF0) { + codepoint = *utf8++ & 0x07; + extraBytes = 3; + } else { + continue; + } + + for (int i = 0; i < extraBytes; i++) { + if ((*utf8 & 0xC0) != 0x80) break; + codepoint = (codepoint << 6) | (*utf8++ & 0x3F); + } + + if (codepoint <= 0xFFFF) { + ucs2 += (char)(codepoint >> 8); // High byte + ucs2 += (char)(codepoint & 0xFF); // Low byte + } + } + return ucs2; } \ No newline at end of file diff --git a/src/TEF6686.h b/src/TEF6686.h index 5c92d9f..c75f989 100644 --- a/src/TEF6686.h +++ b/src/TEF6686.h @@ -570,6 +570,7 @@ typedef struct _rds_ { String stationIDtext; String stationNameLong; String stationStatetext; + String enhancedRTtext; char stationType[18]; char picode[7]; char stationID[9]; @@ -602,6 +603,7 @@ typedef struct _rds_ { bool hasDABAF; bool hasLongPS; bool hasRT; + bool hasEnhancedRT; bool hasTP; bool hasTA; bool hasEON; @@ -719,12 +721,15 @@ class TEF6686 { String convertToUTF8(const wchar_t* input); String extractUTF8Substring(const String& utf8String, size_t start, size_t length, bool under); String trimTrailingSpaces(String str); + String eRTconverter(const wchar_t* input); + String utf8ToUcs2String(const char* utf8); char ps_buffer[9]; char ps_buffer2[9]; char ptyn_buffer[9]; char eon_buffer[20][9]; bool ps_process; bool pslong_process; + char eRT_buffer[129]; bool rt_process; char rt_buffer[65]; char rt_buffer2[65]; @@ -735,6 +740,7 @@ class TEF6686 { bool ABold; bool afreset; bool mpxmode; + bool _hasEnhancedRT; char stationTextBuffer[65]; uint16_t piold; bool rtABold; @@ -759,6 +765,7 @@ class TEF6686 { bool rdsDerrorThreshold; bool packet0, packet1, packet2, packet3, packet0long, packet1long, packet2long, packet3long; bool afmethodBprobe; + bool eRTcoding; uint16_t rdsCold; uint8_t af_counterb; uint8_t af_number; @@ -767,6 +774,7 @@ class TEF6686 { uint16_t correctPIold; uint8_t rtplusblock; uint8_t DABAFblock; + uint8_t eRTblock; uint8_t doublecounter; uint16_t doubletestfreq; }; diff --git a/src/rds.cpp b/src/rds.cpp index 2724314..b625903 100644 --- a/src/rds.cpp +++ b/src/rds.cpp @@ -777,23 +777,23 @@ void showCT() { void showRadioText() { if (!screenmute) { if (radio.rds.hasRT && radio.rds.stationText.length() > 0) { - if (String(radio.rds.stationText + radio.rds.stationText32).length() != Radiotextlengthold) { - RadiotextWidth = (String(radio.rds.stationText + " " + radio.rds.stationText32).length() * charwidth) + 3 * charwidth; - Radiotextlengthold = String(radio.rds.stationText + radio.rds.stationText32).length(); + if (String(radio.rds.stationText + radio.rds.stationText32 + (radio.rds.hasEnhancedRT ? " eRT: " + String(radio.rds.enhancedRTtext) : "")).length() != Radiotextlengthold) { + RadiotextWidth = (String(radio.rds.stationText + " " + radio.rds.stationText32 + (radio.rds.hasEnhancedRT ? " eRT: " + String(radio.rds.enhancedRTtext) : "")).length() * charwidth) + 3 * charwidth; + Radiotextlengthold = String(radio.rds.stationText + radio.rds.stationText32 + (radio.rds.hasEnhancedRT ? " eRT: " + String(radio.rds.enhancedRTtext) : "")).length(); } if (advancedRDS && radio.rds.stationText.length() < 20) { xPos = 0; RDSSprite.fillSprite(BackgroundColor); RadiotextSprite.setTextDatum(TL_DATUM); if (RDSstatus) RDSSprite.setTextColor(RDSColor, RDSColorSmooth, false); else RDSSprite.setTextColor(RDSDropoutColor, RDSDropoutColorSmooth, false); - RDSSprite.drawString(radio.rds.stationText + " " + radio.rds.stationText32, xPos, 2); + RDSSprite.drawString(radio.rds.stationText + " " + radio.rds.stationText32 + (radio.rds.hasEnhancedRT ? " eRT: " + String(radio.rds.enhancedRTtext) : ""), xPos, 2); RDSSprite.pushSprite(36, 220); } else if (!advancedRDS && radio.rds.stationText.length() < 29) { xPos = 0; RadiotextSprite.fillSprite(BackgroundColor); RadiotextSprite.setTextDatum(TL_DATUM); if (RDSstatus) RadiotextSprite.setTextColor(RDSColor, RDSColorSmooth, false); else RadiotextSprite.setTextColor(RDSDropoutColor, RDSDropoutColorSmooth, false); - RadiotextSprite.drawString(radio.rds.stationText + " " + radio.rds.stationText32, xPos, 2); + RadiotextSprite.drawString(radio.rds.stationText + " " + radio.rds.stationText32 + (radio.rds.hasEnhancedRT ? " eRT: " + String(radio.rds.enhancedRTtext) : ""), xPos, 2); RadiotextSprite.pushSprite(36, 220); } else { if (millis() - rtticker >= (advancedRDS ? 5 : 15)) { @@ -812,14 +812,14 @@ void showRadioText() { if (advancedRDS) { RDSSprite.fillSprite(BackgroundColor); if (RDSstatus) RDSSprite.setTextColor(RDSColor, RDSColorSmooth, false); else RDSSprite.setTextColor(RDSDropoutColor, RDSDropoutColorSmooth, false); - RDSSprite.drawString(radio.rds.stationText + " " + radio.rds.stationText32, xPos, 2); - RDSSprite.drawString(radio.rds.stationText + " " + radio.rds.stationText32, xPos + RadiotextWidth, 2); + RDSSprite.drawString(radio.rds.stationText + " " + radio.rds.stationText32 + (radio.rds.hasEnhancedRT ? " eRT: " + String(radio.rds.enhancedRTtext) : ""), xPos, 2); + RDSSprite.drawString(radio.rds.stationText + " " + radio.rds.stationText32 + (radio.rds.hasEnhancedRT ? " eRT: " + String(radio.rds.enhancedRTtext) : ""), xPos + RadiotextWidth, 2); RDSSprite.pushSprite(36, 220); } else { RadiotextSprite.fillSprite(BackgroundColor); if (RDSstatus) RadiotextSprite.setTextColor(RDSColor, RDSColorSmooth, false); else RadiotextSprite.setTextColor(RDSDropoutColor, RDSDropoutColorSmooth, false); - RadiotextSprite.drawString(radio.rds.stationText + " " + radio.rds.stationText32, xPos, 2); - RadiotextSprite.drawString(radio.rds.stationText + " " + radio.rds.stationText32, xPos + RadiotextWidth, 2); + RadiotextSprite.drawString(radio.rds.stationText + " " + radio.rds.stationText32 + (radio.rds.hasEnhancedRT ? " eRT: " + String(radio.rds.enhancedRTtext) : ""), xPos, 2); + RadiotextSprite.drawString(radio.rds.stationText + " " + radio.rds.stationText32 + (radio.rds.hasEnhancedRT ? " eRT: " + String(radio.rds.enhancedRTtext) : ""), xPos + RadiotextWidth, 2); RadiotextSprite.pushSprite(36, 220); } rtticker = millis(); From 1e40c7e7dcfa27cc93ee6c04b077f84c6825e725 Mon Sep 17 00:00:00 2001 From: Sjef Verhoeven PE5PVB Date: Tue, 21 May 2024 23:41:46 +0200 Subject: [PATCH 8/8] Versioning --- src/language.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/language.h b/src/language.h index 98ab0e5..0374dc4 100644 --- a/src/language.h +++ b/src/language.h @@ -1,7 +1,7 @@ #ifndef LANGUAGE_H #define LANGUAGE_H -#define VERSION "v2.10 RC3" +#define VERSION "v2.10 RC4" // [number of languages][number of texts] // *** means the text is the same as in English