diff --git a/TEF6686_ESP32.ino b/TEF6686_ESP32.ino index 61b84e9..546d220 100644 --- a/TEF6686_ESP32.ino +++ b/TEF6686_ESP32.ino @@ -271,6 +271,7 @@ int xPos; int xPos2; int xPos3; int xPos4; +int xPos5; int16_t OStatus; int16_t SAvg; int16_t SAvg2; @@ -370,6 +371,8 @@ unsigned long eontickerhold; unsigned long flashingtimer; unsigned long lowsignaltimer; unsigned long peakholdmillis; +unsigned long pslongticker; +unsigned long pslongtickerhold; unsigned long rtplusticker; unsigned long rtplustickerhold; unsigned long rtticker; @@ -391,6 +394,7 @@ TFT_eSprite SquelchSprite = TFT_eSprite(&tft); TFT_eSprite FullLineSprite = TFT_eSprite(&tft); TFT_eSprite OneBigLineSprite = TFT_eSprite(&tft); TFT_eSprite SignalSprite = TFT_eSprite(&tft); +TFT_eSprite PSSprite = TFT_eSprite(&tft); WiFiConnect wc; WiFiServer Server(7373); @@ -619,6 +623,9 @@ void setup() { RDSSprite.createSprite(165, 19); RDSSprite.setTextDatum(TL_DATUM); + PSSprite.createSprite(150, 30); + PSSprite.setTextDatum(TL_DATUM); + SquelchSprite.createSprite(47, 19); SquelchSprite.setTextDatum(TL_DATUM); SquelchSprite.setSwapBytes(true); @@ -4217,9 +4224,11 @@ void UpdateFonts(bool mode) { if (language == LANGUAGE_CHS) { RadiotextSprite.loadFont(FONT16_CHS); RDSSprite.loadFont(FONT16_CHS); + PSSprite.loadFont(FONT28_CHS); } else { RadiotextSprite.loadFont(FONT16); RDSSprite.loadFont(FONT16); + PSSprite.loadFont(FONT28); } break; @@ -4240,6 +4249,7 @@ void UpdateFonts(bool mode) { OneBigLineSprite.unloadFont(); RadiotextSprite.unloadFont(); RDSSprite.unloadFont(); + PSSprite.unloadFont(); break; } } diff --git a/src/TEF6686.cpp b/src/TEF6686.cpp index 2a084dd..d11e44d 100644 --- a/src/TEF6686.cpp +++ b/src/TEF6686.cpp @@ -1443,11 +1443,11 @@ void TEF6686::readRDS(byte showrdserrors) { eon_buffer[position][(offset * 2) + 2] = '\0'; // Endmarker of segment } - if (offset > 3 && eon[position].pi == rds.rdsD) { // Last chars are received - RDScharConverter(eon_buffer[position], EONPStext[position], sizeof(EONPStext[position]) / sizeof(wchar_t), false); // Convert 8 bit ASCII to 16 bit ASCII - String utf8String = convertToUTF8(EONPStext[position]); // Convert RDS characterset to ASCII - eon[position].ps = extractUTF8Substring(utf8String, 0, 8, false); // Make sure PS does not exceed 8 characters - for (int j = 0; j < 9; j++) eon_buffer[position][j] = '\0'; // Clear buffer + if (offset > 3 && eon[position].pi == rds.rdsD) { // Last chars are received + RDScharConverter(eon_buffer[position], EONPStext[position], sizeof(EONPStext[position]) / sizeof(wchar_t), false); // Convert 8 bit ASCII to 16 bit ASCII + String utf8String = convertToUTF8(EONPStext[position]); // Convert RDS characterset to ASCII + eon[position].ps = extractUTF8Substring(utf8String, 0, 8, false); // Make sure PS does not exceed 8 characters + for (int j = 0; j < 9; j++) eon_buffer[position][j] = '\0'; // Clear buffer } if (offset == 13 && eon[position].pi == rds.rdsD) { @@ -1499,6 +1499,45 @@ void TEF6686::readRDS(byte showrdserrors) { } } break; + + case RDS_GROUP_15A: { + if (showrdserrors == 3 || (!rdsBerrorThreshold && !rdsCerrorThreshold && !rdsDerrorThreshold)) { + if (pslong_process) 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 + pslong_buffer2[offset + 1] = pslong_buffer[offset + 1]; + pslong_buffer2[offset + 2] = pslong_buffer[offset + 2]; + pslong_buffer2[offset + 3] = pslong_buffer[offset + 3]; + pslong_buffer2[32] = '\0'; + + pslong_buffer[offset + 0] = rds.rdsC >> 8; // First character of segment + pslong_buffer[offset + 1] = rds.rdsC & 0xff; // Second character of segment + pslong_buffer[offset + 2] = rds.rdsD >> 8; // Thirth character of segment + pslong_buffer[offset + 3] = rds.rdsD & 0xff; // Fourth character of segment + pslong_buffer[32] = '\0'; + + if (offset == 28 && (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... + 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, 32, true); // Make sure PS Long does not exceed 32 characters + } + } + + if (!pslong_process && rds.fastps) { // Let's get 2 runs of 32 PS characters fast and without refresh + if (offset == 0) packet0long = true; + 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 + rds.stationNameLong = extractUTF8Substring(utf8String, 0, 32, true); + if (packet0long && packet1long && packet2long && packet3long) pslong_process = true; // OK, we had one runs, now let's go the idle PS Long writing + } + } + } + break; } } } @@ -1508,6 +1547,7 @@ void TEF6686::clearRDS (bool fullsearchrds) { rds.piBuffer.clear(); rds.stationName = ""; rds.stationText = ""; + rds.stationNameLong = ""; rds.stationText32 = ""; rds.RTContent1 = ""; rds.RTContent2 = ""; @@ -1517,11 +1557,6 @@ void TEF6686::clearRDS (bool fullsearchrds) { rds.stationIDtext = ""; rds.stationStatetext = ""; - ps_buffer[8] = 0; - ptyn_buffer[8] = 0; - PStext[8] = L'\0'; - PTYNtext[8] = L'\0'; - uint8_t i; for (i = 0; i < 8; i++) { ps_buffer[i] = 0x20; @@ -1529,12 +1564,22 @@ void TEF6686::clearRDS (bool fullsearchrds) { ptyn_buffer[i] = 0x20; PTYNtext[i] = L'\0'; } + ps_buffer[8] = 0; + ptyn_buffer[8] = 0; + PStext[8] = L'\0'; + PTYNtext[8] = L'\0'; for (i = 0; i < 64; i++) rt_buffer[i] = 0x20; rt_buffer[64] = 0; - for (i = 0; i < 32; i++) rt_buffer32[i] = 0x20; + for (i = 0; i < 32; i++) { + rt_buffer32[i] = 0x20; + pslong_buffer[i] = 0x20; + PSLongtext[i] = L'\0'; + } rt_buffer32[32] = 0; + pslong_buffer[32] = 0; + PSLongtext[32] = L'\0'; for (i = 0; i < 17; i++) rds.stationType[i] = 0x20; rds.stationType[17] = 0; @@ -1611,10 +1656,12 @@ void TEF6686::clearRDS (bool fullsearchrds) { rds.hasCT = false; rds.hasTMC = false; rds.hasAID = false; + rds.hasLongPS = false; rds.hasRDSplus = false; rds.hasDABAF = false; rt_process = false; ps_process = false; + pslong_process = false; rds.rdsreset = true; rds.hasArtificialhead = false; rds.hasCompressed = false; @@ -1640,6 +1687,10 @@ void TEF6686::clearRDS (bool fullsearchrds) { packet1 = false; packet2 = false; packet3 = false; + packet0long = false; + packet1long = false; + packet2long = false; + packet3long = false; rds.aid_counter = 0; afmethodBprobe = false; afmethodBtrigger = false; diff --git a/src/TEF6686.h b/src/TEF6686.h index 2d461ef..fcdaa24 100644 --- a/src/TEF6686.h +++ b/src/TEF6686.h @@ -568,10 +568,12 @@ typedef struct _rds_ { String ECCtext; String LICtext; String stationIDtext; + String stationNameLong; String stationStatetext; char stationType[18]; char picode[7]; char stationID[9]; + char stationLongID[33]; char stationState[3]; char dabafeid[5]; char dabafchannel[4]; @@ -598,6 +600,7 @@ typedef struct _rds_ { bool hasECC; bool hasLIC; bool hasDABAF; + bool hasLongPS; bool hasRT; bool hasTP; bool hasTA; @@ -720,10 +723,13 @@ class TEF6686 { char ptyn_buffer[9]; char eon_buffer[20][9]; bool ps_process; + bool pslong_process; bool rt_process; char rt_buffer[65]; char rt_buffer2[65]; char rt_buffer32[33]; + char pslong_buffer[33]; + char pslong_buffer2[33]; bool useRTPlus = true; bool ABold; bool afreset; @@ -733,6 +739,7 @@ class TEF6686 { bool rtABold; bool rtAB32old; wchar_t PStext[9] = L""; + wchar_t PSLongtext[33] = L""; wchar_t EONPStext[20][9]; wchar_t PTYNtext[9] = L""; char RDSplus1[45]; @@ -749,10 +756,7 @@ class TEF6686 { bool rdsBerrorThreshold; bool rdsCerrorThreshold; bool rdsDerrorThreshold; - bool packet0; - bool packet1; - bool packet2; - bool packet3; + bool packet0, packet1, packet2, packet3, packet0long, packet1long, packet2long, packet3long; bool afmethodBprobe; uint16_t rdsCold; uint8_t af_counterb; @@ -765,4 +769,4 @@ class TEF6686 { uint8_t doublecounter; uint16_t doubletestfreq; }; -#endif +#endif \ No newline at end of file diff --git a/src/rds.cpp b/src/rds.cpp index 2e68378..1f8428e 100644 --- a/src/rds.cpp +++ b/src/rds.cpp @@ -7,6 +7,7 @@ int Radiotextlengthold; int RadiotextWidth; +int PSLongWidth; int AIDlengthold; int AIDWidth; int afstringlengthold; @@ -14,6 +15,7 @@ int afstringWidth; int eonstringlengthold; int eonstringWidth; int rtplusstringlengthold; +int PSLonglengthold; int rtplusstringWidth; void ShowAdvancedRDS() { @@ -315,16 +317,23 @@ void readRds() { } } - if (advancedRDS) { - tftPrint(-1, PSold, 36, 75, RDSDropoutColor, RDSDropoutColorSmooth, 28); - } else { - tftPrint(-1, PSold, 36, 187, RDSDropoutColor, RDSDropoutColorSmooth, 28); + PSSprite.fillSprite(BackgroundColor); + PSSprite.setTextColor(RDSDropoutColor, RDSDropoutColorSmooth, false); + PSSprite.drawString(PSold, 0, 0); + if (!radio.rds.hasLongPS) { + if (advancedRDS) { + PSSprite.pushSprite(36, 75); + } else { + PSSprite.pushSprite(36, 187); + } } + if (advancedRDS) { tftPrint(-1, PTYold, 36, 109, RDSDropoutColor, RDSDropoutColorSmooth, 16); } else { tftPrint(-1, PTYold, 36, 163, RDSDropoutColor, RDSDropoutColorSmooth, 16); } + if (advancedRDS) { tft.fillCircle(86, 41, 5, SignificantColor); tft.fillCircle(124, 41, 5, SignificantColor); @@ -363,16 +372,23 @@ void readRds() { } } - if (advancedRDS) { - tftPrint(-1, PSold, 36, 75, RDSColor, RDSColorSmooth, 28); - } else { - tftPrint(-1, PSold, 36, 187, RDSColor, RDSColorSmooth, 28); + PSSprite.fillSprite(BackgroundColor); + PSSprite.setTextColor(RDSColor, RDSColorSmooth, false); + PSSprite.drawString(PSold, 0, 0); + if (!radio.rds.hasLongPS) { + if (advancedRDS) { + PSSprite.pushSprite(36, 75); + } else { + PSSprite.pushSprite(36, 187); + } } + if (advancedRDS) { tftPrint(-1, PTYold, 36, 109, RDSColor, RDSColorSmooth, 16); } else { tftPrint(-1, PTYold, 36, 163, RDSColor, RDSColorSmooth, 16); } + if (!advancedRDS) { tft.fillCircle(314, 223, 2, GreyoutColor); tft.fillCircle(314, 234, 2, GreyoutColor); @@ -653,26 +669,53 @@ void showPTY() { } void showPS() { - if (radio.rds.stationName != PSold) { + if (radio.rds.stationName != PSold || radio.rds.hasLongPS) { if (!screenmute) { - if (advancedRDS) { - if (!RDSstatus) { - tftReplace(-1, PSold, radio.rds.stationName, 36, 75, RDSDropoutColor, RDSDropoutColorSmooth, BackgroundColor, 28); - } else { - tftReplace(-1, PSold, radio.rds.stationName, 36, 75, RDSColor, RDSColorSmooth, BackgroundColor, 28); - } - } else if (afscreen) { + if (afscreen) { tftReplace(0, PSold, radio.rds.stationName, 160, 201, BWAutoColor, BWAutoColorSmooth, BackgroundColor, 16); } else { - if (!RDSstatus) { - tftReplace(-1, PSold, radio.rds.stationName, 36, 187, RDSDropoutColor, RDSDropoutColorSmooth, BackgroundColor, 28); + if (radio.rds.hasLongPS) { + PSLongWidth = (String(radio.rds.stationNameLong).length() * (charwidth + 4)); + PSLonglengthold = String(radio.rds.stationNameLong).length(); + + if (millis() - pslongticker >= (advancedRDS ? 5 : 15)) { + if (xPos5 == 0) { + if (millis() - pslongtickerhold >= 1000) { + xPos5 --; + pslongtickerhold = millis(); + } + } else { + xPos5 --; + pslongtickerhold = millis(); + } + + PSSprite.setTextDatum(TL_DATUM); + if (xPos5 < -PSLongWidth) xPos5 = 0; + if (advancedRDS) { + PSSprite.fillSprite(BackgroundColor); + if (RDSstatus) PSSprite.setTextColor(RDSColor, RDSColorSmooth, false); else PSSprite.setTextColor(RDSDropoutColor, RDSDropoutColorSmooth, false); + PSSprite.drawString(radio.rds.stationNameLong, xPos5, 0); + PSSprite.drawString(radio.rds.stationNameLong, xPos5 + PSLongWidth, 0); + } else { + PSSprite.fillSprite(BackgroundColor); + if (RDSstatus) PSSprite.setTextColor(RDSColor, RDSColorSmooth, false); else PSSprite.setTextColor(RDSDropoutColor, RDSDropoutColorSmooth, false); + PSSprite.drawString(radio.rds.stationNameLong, xPos5, 0); + PSSprite.drawString(radio.rds.stationNameLong, xPos5 + PSLongWidth, 0); + } + pslongticker = millis(); + } } else { - tftReplace(-1, PSold, radio.rds.stationName, 36, 187, RDSColor, RDSColorSmooth, BackgroundColor, 28); + xPos5 = 0; + PSSprite.fillSprite(BackgroundColor); + if (!RDSstatus) PSSprite.setTextColor(RDSDropoutColor, RDSDropoutColorSmooth, false); else PSSprite.setTextColor(RDSColor, RDSColorSmooth, false); + PSSprite.drawString(radio.rds.stationName, 0, 0); } + if (advancedRDS) PSSprite.pushSprite(36, 75); else PSSprite.pushSprite(36, 187); } } PSold = radio.rds.stationName; - if (wifi) { + + if (wifi && PSold != radio.rds.stationName) { Udp.beginPacket(remoteip, 9030); Udp.print("from=TEF_tuner " + String(stationlistid, DEC) + ";PS="); char PShex[9]; diff --git a/src/rds.h b/src/rds.h index 50fa58a..9ef887a 100644 --- a/src/rds.h +++ b/src/rds.h @@ -86,6 +86,7 @@ extern int xPos; extern int xPos2; extern int xPos3; extern int xPos4; +extern int xPos5; extern int16_t SAvg3; extern IPAddress remoteip; extern String AIDString; @@ -114,6 +115,8 @@ extern unsigned long aftickerhold; extern unsigned long aftimer; extern unsigned long eonticker; extern unsigned long eontickerhold; +extern unsigned long pslongticker; +extern unsigned long pslongtickerhold; extern unsigned long rtplusticker; extern unsigned long rtplustickerhold; extern unsigned long rtticker; @@ -126,6 +129,7 @@ extern WiFiClient RemoteClient; extern WiFiUDP Udp; extern TFT_eSprite RadiotextSprite; extern TFT_eSprite RDSSprite; +extern TFT_eSprite PSSprite; void ShowAdvancedRDS(); void readRds();