diff --git a/TEF6686_ESP32.ino b/TEF6686_ESP32.ino index b6c8326..87ce5d3 100644 --- a/TEF6686_ESP32.ino +++ b/TEF6686_ESP32.ino @@ -108,6 +108,7 @@ bool XDRGTKTCP; bool XDRGTKUSB; bool XDRMute; byte af_counterold; +byte aid_counterold; byte afpagenr; byte amnb; byte audiomode; @@ -248,6 +249,7 @@ int8_t VolSet; float batteryVold; IPAddress remoteip; String afstringold; +String AIDString; String cryptedpassword; String CurrentThemeString; String ECColdtxt; @@ -2280,6 +2282,7 @@ void ShowFreq(int mode) { licold = 254; ECCold = 253; afmethodBold = false; + aid_counterold = 0; if (wifi) { Udp.beginPacket(remoteip, 9030); diff --git a/src/TEF6686.cpp b/src/TEF6686.cpp index 9a075f4..21ef3ac 100644 --- a/src/TEF6686.cpp +++ b/src/TEF6686.cpp @@ -548,7 +548,7 @@ void TEF6686::readRDS(byte showrdserrors) if (af[x].frequency == buffer0 && !af[x].regional) { af[x].regional = true; af_updatecounter++; - break; + break; } } } else if (buffer1 == currentfreq && buffer0 < buffer1) { @@ -556,7 +556,7 @@ void TEF6686::readRDS(byte showrdserrors) if (af[x].frequency == buffer0 && !af[x].mixed) { af[x].mixed = true; af_updatecounter++; - break; + break; } } } @@ -566,7 +566,7 @@ void TEF6686::readRDS(byte showrdserrors) if (af[x].frequency == buffer1 && !af[x].regional) { af[x].regional = true; af_updatecounter++; - break; + break; } } } else if (buffer0 == currentfreq && buffer0 < buffer1) { @@ -574,7 +574,7 @@ void TEF6686::readRDS(byte showrdserrors) if (af[x].frequency == buffer0 && !af[x].mixed) { af[x].mixed = true; af_updatecounter++; - break; + break; } } } @@ -617,17 +617,17 @@ void TEF6686::readRDS(byte showrdserrors) bool temp3 = af[j].afvalid; bool temp4 = af[j].checked; bool temp5 = af[j].regional; - bool temp6 = af[j].mixed; + bool temp6 = af[j].mixed; af[j].frequency = af[j + 1].frequency; af[j].afvalid = af[j + 1].afvalid; af[j].checked = af[j + 1].checked; af[j].regional = af[j + 1].regional; - af[j].mixed = af[j + 1].mixed; + af[j].mixed = af[j + 1].mixed; af[j + 1].frequency = temp; af[j + 1].afvalid = temp3; af[j + 1].checked = temp4; af[j + 1].regional = temp5; - af[j + 1].mixed = temp6; + af[j + 1].mixed = temp6; } } } @@ -751,6 +751,21 @@ void TEF6686::readRDS(byte showrdserrors) case RDS_GROUP_3A: { if (!rdsDerrorThreshold) { + if (rds.rdsD != 0) rds.hasAID = true; + + bool isValuePresent = false; + for (int i = 0; i < 10; i++) { + if (rds.aid[i] == rds.rdsD) { + isValuePresent = true; + break; + } + } + + if (!isValuePresent) { + rds.aid[rds.aid_counter] = rds.rdsD; + rds.aid_counter++; + } + // RT+ init if (rds.rdsD == 0x4BD7) { // Check for RT+ application rds.hasRDSplus = true; // Set flag @@ -1006,6 +1021,8 @@ void TEF6686::clearRDS (bool fullsearchrds) RDSplus2[i] = 0; } + for (i = 0; i < 10; i++) rds.aid[i] = 0; + rdsblock = 254; piold = 0; rds.correctPI = 0; @@ -1026,6 +1043,7 @@ void TEF6686::clearRDS (bool fullsearchrds) rds.hasEON = false; rds.hasCT = false; rds.hasTMC = false; + rds.hasAID = false; rds.hasRDSplus = false; rt_process = false; ps_process = false; @@ -1054,6 +1072,7 @@ void TEF6686::clearRDS (bool fullsearchrds) packet1 = false; packet2 = false; packet3 = false; + rds.aid_counter = 0; } void TEF6686::tone(uint16_t time, int16_t amplitude, uint16_t frequency) { diff --git a/src/TEF6686.h b/src/TEF6686.h index d7dfa1e..8dd336b 100644 --- a/src/TEF6686.h +++ b/src/TEF6686.h @@ -84,6 +84,84 @@ static const char* const PTY_USA[] { " " }; +static const uint16_t oda_app_ids[] { + 0x0000, 0x0093, 0x0BCB, 0x0C24, 0x0CC1, 0x0D45, 0x0D8B, 0x0E2C, 0x0E31, 0x0F87, + 0x125F, 0x1BDA, 0x1C5E, 0x1C68, 0x1CB1, 0x1D47, 0x1DC2, 0x1DC5, 0x1E8F, 0x4400, + 0x4AA1, 0x4AB7, 0x4BA2, 0x4BD7, 0x4BD8, 0x4C59, 0x4D87, 0x4D95, 0x4D9A, 0x50DD, + 0x5757, 0x6363, 0x6365, 0x6552, 0x6A7A, 0x7373, 0xA112, 0xA911, 0xABCF, 0xC350, + 0xC3A1, 0xC3B0, 0xC3C3, 0xC4D4, 0xC549, 0xC563, 0xC6A7, 0xC737, 0xCB73, 0xCB97, + 0xCC21, 0xCD46, 0xCD47, 0xCD9E, 0xCE6B, 0xE123, 0xE1C1, 0xE319, 0xE411, 0xE440, + 0xE4A6, 0xE5D7, 0xE911, 0xFF7F, 0xFF80 +}; + +static const char* const oda_app_names[] { + "None", + "Cross referencing DAB within RDS", + "Leisure & Practical Info for Drivers", + "ELECTRABEL-DSM 7", + "Wireless Playground broadcast control signal", + "RDS-TMC: ALERT-C / EN ISO 14819-1", + "ELECTRABEL-DSM 18", + "ELECTRABEL-DSM 3", + "ELECTRABEL-DSM 13", + "ELECTRABEL-DSM 2", + "I-FM-RDS for fixed and mobile devices", + "ELECTRABEL-DSM 1", + "ELECTRABEL-DSM 20", + "ITIS In-vehicle data base", + "ELECTRABEL-DSM 10", + "ELECTRABEL-DSM 4", + "CITIBUS 4", + "Encrypted TTI using ALERT-Plus", + "ELECTRABEL-DSM 17", + "RDS-Light", + "RASANT", + "ELECTRABEL-DSM 9", + "ELECTRABEL-DSM 5", + "RadioText+ (RT+)", + "RadioText Plus / RT+for eRT", + "CITIBUS 2", + "Radio Commerce System (RCS)", + "ELECTRABEL-DSM 16", + "ELECTRABEL-DSM 11", + "To warn people in case of disasters or emergency", + "Personal weather station", + "Hybradio RDS-Net(for testing use, only)", + "RDS2 – 9 bit AF lists ODA", + "Enhanced RadioText (eRT)", + "Warning receiver", + "Enhanced early warning system", + "NL _ Alert system", + "Data FM Selective Multipoint Messaging", + "RF Power Monitoring", + "NRSC Song Title and Artist", + "Personal Radio Service", + "iTunes Tagging", + "NAVTEQ Traffic Plus", + "eEAS", + "Smart Grid Broadcast Channel", + "ID Logic", + "Veil Enabled Interactive Device", + "Utility Message Channel (UMC)", + "CITIBUS 1", + "ELECTRABEL-DSM 14", + "CITIBUS 3", + "RDS-TMC: ALERT-C", + "RDS-TMC: ALERT-C", + "ELECTRABEL-DSM 8", + "Encrypted TTI using ALERT-Plus", + "APS Gateway", + "Action code", + "ELECTRABEL-DSM 12", + "Beacon downlink", + "ELECTRABEL-DSM 15", + "ELECTRABEL-DSM 19", + "ELECTRABEL-DSM 6", + "EAS open protocol", + "RFT: Station logo", + "RFT+ (work title)" +}; + typedef struct _rds_ { byte region; byte stationTypeCode; @@ -97,6 +175,8 @@ typedef struct _rds_ { char stationType[18]; char picode[7]; uint16_t hour, minute, day, month, year, rdsA, rdsB, rdsC, rdsD, rdsErr, rdsStat, correctPI, rdsplusTag1, rdsplusTag2; + uint16_t aid[10]; + byte aid_counter; int8_t offset; unsigned int ECC; unsigned int LIC; @@ -119,6 +199,7 @@ typedef struct _rds_ { bool hasTP; bool hasTA; bool hasEON; + bool hasAID; bool hasTMC; bool hasAF; bool hasCT; diff --git a/src/gui.cpp b/src/gui.cpp index 05377ec..6c2906c 100644 --- a/src/gui.cpp +++ b/src/gui.cpp @@ -352,7 +352,6 @@ void BuildAFScreen() { programServicePrevious = ""; afmethodBold = false; for (byte i = 0; i < 11; i++) eonpsold[i] = ""; - } } diff --git a/src/language.h b/src/language.h index 34a67e4..82e56a1 100644 --- a/src/language.h +++ b/src/language.h @@ -1,6 +1,6 @@ // [number of languages][number of texts] -static const char* const myLanguage[16][204] = { +static const char* const myLanguage[16][205] = { { "English", // English "Rotary direction changed", // 1 "Please release button", // 2 @@ -204,7 +204,8 @@ static const char* const myLanguage[16][204] = { "Small", // 200 "Large", // 201 "All", // 202 - "Fast PS" // 203 + "Fast PS", // 203 + "Detected applications" // 204 }, { "Nederlands", // Dutch @@ -410,7 +411,8 @@ static const char* const myLanguage[16][204] = { "Laag", // 200 "Middel", // 201 "Alles", // 202 - "Snelle PS" // 203 + "Snelle PS", // 203 + "Gedetecteerde applicaties" // 204 }, { "Polski", // Polish @@ -616,7 +618,8 @@ static const char* const myLanguage[16][204] = { "Male", // 200 "Duze", // 201 "Wszystkie", // 202 - "Fast PS" // 203 + "Fast PS", // 203 + "Detected applications" // 204 }, { "Hrvatski", // Croatian @@ -822,7 +825,8 @@ static const char* const myLanguage[16][204] = { "Small", // 200 "Large", // 201 "All", // 202 - "Fast PS" // 203 + "Fast PS", // 203 + "Detected applications" // 204 }, { "Ελληνικά", // Greek @@ -1028,7 +1032,8 @@ static const char* const myLanguage[16][204] = { "Μικρό", // 200 "Μεγάλο", // 201 "Όλα", // 202 - "Fast PS" // 203 + "Fast PS", // 203 + "Detected applications" // 204 }, { "Romana", // Romanian @@ -1234,7 +1239,8 @@ static const char* const myLanguage[16][204] = { "Small", // 200 "Large", // 201 "All", // 202 - "Fast PS" // 203 + "Fast PS", // 203 + "Detected applications" // 204 }, { "Deutsch", // German @@ -1440,7 +1446,8 @@ static const char* const myLanguage[16][204] = { "Gering", // 200 "Groß", // 201 "Alles", // 202 - "Fast PS" // 203 + "Fast PS", // 203 + "Detected applications" // 204 }, { "Czech", // Czech @@ -1646,7 +1653,8 @@ static const char* const myLanguage[16][204] = { "Small", // 200 "Large", // 201 "All", // 202 - "Fast PS" // 203 + "Fast PS", // 203 + "Detected applications" // 204 }, { "Slovak", // Slovak @@ -1852,7 +1860,8 @@ static const char* const myLanguage[16][204] = { "Small", // 200 "Large", // 201 "All", // 202 - "Fast PS" // 203 + "Fast PS", // 203 + "Detected applications" // 204 }, { "Français", // French @@ -2058,7 +2067,8 @@ static const char* const myLanguage[16][204] = { "Small", // 200 "Large", // 201 "All", // 202 - "Fast PS" // 203 + "Fast PS", // 203 + "Detected applications" // 204 }, { "Български", // Bulgarian @@ -2264,7 +2274,8 @@ static const char* const myLanguage[16][204] = { "Small", // 200 "Large", // 201 "All", // 202 - "Fast PS" // 203 + "Fast PS", // 203 + "Detected applications" // 204 }, { "Русский", // Russian @@ -2470,7 +2481,8 @@ static const char* const myLanguage[16][204] = { "Small", // 200 "Large", // 201 "All", // 202 - "Fast PS" // 203 + "Fast PS", // 203 + "Detected applications" // 204 }, { "Українська", // Ukranian @@ -2676,7 +2688,8 @@ static const char* const myLanguage[16][204] = { "Small", // 200 "Large", // 201 "All", // 202 - "Fast PS" // 203 + "Fast PS", // 203 + "Detected applications" // 204 }, { "Italiano", // Italian @@ -2882,7 +2895,8 @@ static const char* const myLanguage[16][204] = { "Small", // 200 "Large", // 201 "All", // 202 - "Fast PS" // 203 + "Fast PS", // 203 + "Detected applications" // 204 }, { "Simplified Chinese", // Simplified Chinese @@ -3088,7 +3102,8 @@ static const char* const myLanguage[16][204] = { "少量", // 200 "大量", // 201 "全部", // 202 - "Fast PS" // 203 + "Fast PS", // 203 + "Detected applications" // 204 }, { "Norsk", // Norwegian @@ -3294,7 +3309,8 @@ static const char* const myLanguage[16][204] = { "Lite", // 200 "Mye", // 201 "Alt", // 202 - "Fast PS" // 203 + "Fast PS", // 203 + "Detected applications" // 204 } }; diff --git a/src/rds.cpp b/src/rds.cpp index 3a9dee0..850969d 100644 --- a/src/rds.cpp +++ b/src/rds.cpp @@ -810,7 +810,7 @@ void showRadioText() { void ShowAFEON() { if (radio.rds.hasAF) { - if (hasafold == false) { + if (!hasafold) { if (!screenmute) tftPrint(-1, myLanguage[language][87], 6, 54, BackgroundColor, BackgroundColor, 16); if (!screenmute) tftPrint(-1, "AF:", 4, 32, ActiveColor, ActiveColorSmooth, 16); hasafold = true; @@ -842,8 +842,8 @@ void ShowAFEON() { if (radio.af_counter > 10 + (afpagenr == 2 ? 30 : 0)) tft.drawLine(59, 54, 59, 191, SecondaryColor); if (radio.af_counter > 20 + (afpagenr == 2 ? 30 : 0)) tft.drawLine(113, 54, 113, 191, SecondaryColor); if (afpage && !screenmute) tftPrint(1, String(afpagenr) + "/2", 315, 222, SecondaryColor, SecondaryColorSmooth, 16); + af_counterold = radio.af_updatecounter; } - af_counterold = radio.af_updatecounter; } if (radio.rds.hasEON) { @@ -852,7 +852,9 @@ void ShowAFEON() { tftPrint(-1, "PI:", 170, 32, ActiveColor, ActiveColorSmooth, 16); } haseonold = true; - if (!screenmute) { + + if (!screenmute && millis() >= eonticker + 1000) { + eonticker = millis(); byte y = 0; if (afpagenr == 2) y = 10; for (byte i = 0; i < radio.eon_counter; i++) { @@ -878,4 +880,61 @@ void ShowAFEON() { } } } + + if (radio.rds.hasAID) { + if (aid_counterold != radio.rds.aid_counter) { + AIDString = ""; + char id[5]; + + for (int y = 0; y < radio.rds.aid_counter; y++) { + bool aidProcessed = false; + + for (int i = 0; i < 65; i++) { + if (radio.rds.aid[y] == oda_app_ids[i]) { + if (!aidProcessed) { + char id[5]; + for (int z = 0; z < 4; z++) { + uint8_t nibble = (radio.rds.aid[y] >> (4 * (3 - z))) & 0xF; + if (nibble < 10) { + id[z] = nibble + '0'; + } else { + id[z] = nibble - 10 + 'A'; + } + } + id[4] = '\0'; + + AIDString += String(id); + AIDString += ": "; + AIDString += oda_app_names[i]; + + aidProcessed = true; + } + break; + } + } + + if (!AIDString.isEmpty() && y < radio.rds.aid_counter - 1 && aidProcessed) { + AIDString += " | "; + } + } + aid_counterold = radio.rds.aid_counter; + } + + if (!screenmute) { + if (xPos == 0) { + if (millis() - rttickerhold >= 2000) { + xPos --; + rttickerhold = millis(); + } + } else { + xPos --; + rttickerhold = millis(); + } + if (xPos < -tft.textWidth(String(myLanguage[language][93]) + " - " + String(myLanguage[language][204]) + ": " + AIDString) + (charWidth * 14)) xPos = 0; + RadiotextSprite.fillSprite(BackgroundColor); + RadiotextSprite.setTextColor(ActiveColor, ActiveColorSmooth, false); + RadiotextSprite.drawString(String(myLanguage[language][93]) + " - " + String(myLanguage[language][204]) + ": " + AIDString, xPos, 2); + RadiotextSprite.pushSprite(38, 220); + } + } } \ No newline at end of file diff --git a/src/rds.h b/src/rds.h index 7dfe2b3..a7083e1 100644 --- a/src/rds.h +++ b/src/rds.h @@ -39,6 +39,7 @@ extern bool wifi; extern bool XDRGTKTCP; extern bool XDRGTKUSB; extern byte af_counterold; +extern byte aid_counterold; extern byte afpagenr; extern byte band; extern byte ECCold; @@ -70,6 +71,7 @@ extern int xPos3; extern int xPos4; extern IPAddress remoteip; extern String afstringold; +extern String AIDString; extern String ECColdtxt; extern String eonpsold[11]; extern String eonstringold; @@ -123,5 +125,4 @@ extern void ShowRDSLogo(bool RDSstatus); extern void DataPrint(String string); extern void tftPrint(int8_t offset, const String & text, int16_t x, int16_t y, int color, int smoothcolor, uint8_t fontsize); extern void tftReplace(int8_t offset, const String & textold, const String & text, int16_t x, int16_t y, int color, int smoothcolor, uint8_t fontsize); - #endif \ No newline at end of file