From 5f8d26dad912fab19f787e653b58c938815226a5 Mon Sep 17 00:00:00 2001 From: KubaPro010 Date: Fri, 16 Jan 2026 19:07:12 +0100 Subject: [PATCH] improve rtc handling and make rds decoding with bad signal a lot better --- include/TEF6686.h | 1 - src/TEF6686.cpp | 151 ++++++++++++++++++++++++---------------------- src/rtc.cpp | 23 ++++--- 3 files changed, 94 insertions(+), 81 deletions(-) diff --git a/include/TEF6686.h b/include/TEF6686.h index d134b37..840ae3e 100644 --- a/include/TEF6686.h +++ b/include/TEF6686.h @@ -450,7 +450,6 @@ typedef struct _rds_ { unsigned long blockcounter[33]; uint16_t rdsA, rdsB, rdsC, rdsD, rdsErr, rdsStat, correctPI, rdsplusTag1, rdsplusTag2, PICTlock = 0; bool ps12error, ps34error, ps56error, ps78error; - int32_t clock_correction; int32_t offset; uint16_t aid[10]; uint32_t dabaffreq; diff --git a/src/TEF6686.cpp b/src/TEF6686.cpp index 8f20a0b..1dfe1d3 100644 --- a/src/TEF6686.cpp +++ b/src/TEF6686.cpp @@ -544,7 +544,7 @@ void TEF6686::readRDS(byte showrdserrors) { // B errors mean we can't reliably tell what this is, don't risk it. // And also make sure we have data in the first place, then the decoder first starts it could send just the pi code with nothing more - if ((rds.rdsBerror && showrdserrors != 3) && bitRead(rds.rdsStat, 13) == 0) goto end; + if ((rdsBerrorThreshold && showrdserrors != 3) && bitRead(rds.rdsStat, 13) == 0) goto end; rdsgroup = rds.rdsB >> 11; // Includes version bit as LSB, better for the switch statement if(bitRead(rds.rdsStat, 12) && (rdsgroup & 1) == 0) goto end; // Modulation says type B, but data says otherwise? Dunno what to treat it as, thus skip @@ -1077,17 +1077,52 @@ void TEF6686::readRDS(byte showrdserrors) { } break; case RDS_GROUP_2A: { - if (showrdserrors == 3 || !(rdsCerrorThreshold && rdsDerrorThreshold)) { - rds.hasRT = true; - rds.rtAB = bitRead(rds.rdsB, 4); + rds.hasRT = true; + rds.rtAB = bitRead(rds.rdsB, 4); - if (initab) { - rtABold = rds.rtAB; - initab = false; + if (initab) { + rtABold = rds.rtAB; + initab = false; + } + + if (rds.rtAB != rtABold) { + if (rds.rtbuffer) { + char rt_buffer_temp[129]; + strcpy(rt_buffer_temp, rt_buffer); + + byte endmarkerRT64 = 64; + for (byte i = 0; i < endmarkerRT64; i++) { + if (rt_buffer_temp[i] == 0x0d) { endmarkerRT64 = i; break; } + } + rt_buffer_temp[endmarkerRT64] = '\0'; + + wchar_t RTtext[65] = L""; + RDScharConverter(rt_buffer_temp, RTtext, sizeof(RTtext) / sizeof(wchar_t), (underscore > 1 ? true : false)); + rds.stationText = trimTrailingSpaces(convertToUTF8(RTtext)); } - if (rds.rtAB != rtABold) { - if (rds.rtbuffer) { + memset(rt_buffer, 0x20, 64); + rt_buffer[64] = '\0'; + memset(segments_received, 99, sizeof(segments_received)); + rtABold = rds.rtAB; + } + + uint8_t segment_address = (rds.rdsB & 0xf); + + if(segments_received[segment_address] >= (rds.rdsCerror + rds.rdsBerror)) { + segments_received[segment_address] = rds.rdsCerror + rds.rdsBerror; + + uint8_t offset = segment_address * 4; + if(rdsCerrorThreshold) { + rt_buffer[offset + 0] = rds.rdsC >> 8; + rt_buffer[offset + 1] = rds.rdsC & 0xff; + } + if(rdsDerrorThreshold) { + rt_buffer[offset + 2] = rds.rdsD >> 8; + rt_buffer[offset + 3] = rds.rdsD & 0xff; + } + + if (!rds.rtbuffer) { char rt_buffer_temp[129]; strcpy(rt_buffer_temp, rt_buffer); @@ -1100,45 +1135,12 @@ void TEF6686::readRDS(byte showrdserrors) { wchar_t RTtext[65] = L""; RDScharConverter(rt_buffer_temp, RTtext, sizeof(RTtext) / sizeof(wchar_t), (underscore > 1 ? true : false)); rds.stationText = trimTrailingSpaces(convertToUTF8(RTtext)); - } - - memset(rt_buffer, 0x20, 64); - rt_buffer[64] = '\0'; - memset(segments_received, 99, sizeof(segments_received)); - rtABold = rds.rtAB; - } - - uint8_t segment_address = (rds.rdsB & 0xf); - - if(segments_received[segment_address] >= (rds.rdsCerror + rds.rdsBerror)) { - segments_received[segment_address] = rds.rdsCerror + rds.rdsBerror; - - uint8_t offset = segment_address * 4; - rt_buffer[offset + 0] = rds.rdsC >> 8; - rt_buffer[offset + 1] = rds.rdsC & 0xff; - rt_buffer[offset + 2] = rds.rdsD >> 8; - rt_buffer[offset + 3] = rds.rdsD & 0xff; - - if (!rds.rtbuffer) { - char rt_buffer_temp[129]; - strcpy(rt_buffer_temp, rt_buffer); - - byte endmarkerRT64 = 64; - for (byte i = 0; i < endmarkerRT64; i++) { - if (rt_buffer_temp[i] == 0x0d) { endmarkerRT64 = i; break; } - } - rt_buffer_temp[endmarkerRT64] = '\0'; - - wchar_t RTtext[65] = L""; - RDScharConverter(rt_buffer_temp, RTtext, sizeof(RTtext) / sizeof(wchar_t), (underscore > 1 ? true : false)); - rds.stationText = trimTrailingSpaces(convertToUTF8(RTtext)); - } } } } break; case RDS_GROUP_2B: { - if (showrdserrors == 3 || (!rdsBerrorThreshold && !rdsDerrorThreshold)) { + if (showrdserrors == 3 || !rdsDerrorThreshold) { rds.hasRT = true; rds.rtAB32 = (bitRead(rds.rdsB, 4)); @@ -1180,7 +1182,7 @@ void TEF6686::readRDS(byte showrdserrors) { case RDS_GROUP_3A: { if (!rdsDerrorThreshold) { - if (rds.rdsD != 0) rds.hasAID = true; + rds.hasAID = true; bool isValuePresent = false; for (int i = 0; i < 10; i++) { @@ -1207,7 +1209,7 @@ void TEF6686::readRDS(byte showrdserrors) { DABAFblock = rds.rdsB & 0x1E; } - if (rds.rdsD == 0x6552) { + if (rds.rdsD == 0x6552 && rdsCerrorThreshold) { _hasEnhancedRT = true; eRTblock = rds.rdsB & 0x1E; eRTcoding = rds.rdsC & 1; @@ -1215,8 +1217,7 @@ void TEF6686::readRDS(byte showrdserrors) { } } break; case RDS_GROUP_4A: { - if (!rdsBerrorThreshold && !rdsCerrorThreshold && !rdsDerrorThreshold && rds.ctupdate && (rds.PICTlock == pi || rds.PICTlock == 0)) { - auto rtc_time = rtc.getEpoch(); + if (!rdsCerrorThreshold && !rdsDerrorThreshold && rds.ctupdate && (rds.PICTlock == pi || rds.PICTlock == 0)) { uint32_t mjd = (rds.rdsB & 0x03) << 15 | ((rds.rdsC >> 1) & 0x7FFF); uint16_t hour, minute, day = 5, month = 1, year = 2026; int32_t timeoffset; @@ -1257,11 +1258,7 @@ void TEF6686::readRDS(byte showrdserrors) { rds.offset = timeoffset; rtcset = true; - time_t rds_utc_time = rdstime + timeoffset; - int32_t current_correction = rtc_time - rds_utc_time; - rds.clock_correction = current_correction; - - if (!NTPupdated) set_time(rds_utc_time - (current_correction / 2)); + if (!NTPupdated) set_time(rdstime + timeoffset); } else rds.hasCT = false; lastrdstime = rdstime; lasttimeoffset = timeoffset; @@ -1270,16 +1267,18 @@ void TEF6686::readRDS(byte showrdserrors) { case RDS_GROUP_10A: { if (!rdsCerrorThreshold && !rdsDerrorThreshold) { uint8_t segment = bitRead(rds.rdsB, 0); - if (rds.rdsC != 0 && rds.rdsD != 0) { + if(rdsCerrorThreshold) { ptyn_buffer[(segment * 4) + 0] = rds.rdsC >> 8; ptyn_buffer[(segment * 4) + 1] = rds.rdsC & 0xFF; + } + if(rdsDerrorThreshold) { ptyn_buffer[(segment * 4) + 2] = rds.rdsD >> 8; ptyn_buffer[(segment * 4) + 3] = rds.rdsD & 0xFF; - for (byte i = 0; i < 8; i++) PTYNtext[i] = 0; - RDScharConverter(ptyn_buffer, PTYNtext, sizeof(PTYNtext) / sizeof(wchar_t), false); - rds.PTYN = extractUTF8Substring(convertToUTF8(PTYNtext), 0, 8, false); - rds.hasPTYN = true; } + for (byte i = 0; i < 8; i++) PTYNtext[i] = 0; + RDScharConverter(ptyn_buffer, PTYNtext, sizeof(PTYNtext) / sizeof(wchar_t), false); + rds.PTYN = extractUTF8Substring(convertToUTF8(PTYNtext), 0, 8, false); + rds.hasPTYN = true; } } break; @@ -1291,7 +1290,7 @@ void TEF6686::readRDS(byte showrdserrors) { case RDS_GROUP_11A: case RDS_GROUP_12A: case RDS_GROUP_13A: { - if ((!rdsBerrorThreshold && !rdsCerrorThreshold && !rdsDerrorThreshold) && rtplusblock == rdsgroup && rds.hasRTplus) { + if ((!rdsCerrorThreshold && !rdsDerrorThreshold) && rtplusblock == rdsgroup && rds.hasRTplus) { rds.rdsplusTag1 = ((rds.rdsB & 0x07) << 3) + (rds.rdsC >> 13); rds.rdsplusTag2 = ((rds.rdsC & 0x01) << 5) + (rds.rdsD >> 11); uint16_t start_marker_1 = (rds.rdsC >> 7) & 0x3F; @@ -1343,12 +1342,16 @@ void TEF6686::readRDS(byte showrdserrors) { rds.RTContent2 = extractUTF8Substring(rds.RTContent2, 0, 44, false); } - if ((!rdsBerrorThreshold && !rdsCerrorThreshold && !rdsDerrorThreshold) && eRTblock == rdsgroup && _hasEnhancedRT) { + if (eRTblock == rdsgroup && _hasEnhancedRT) { uint8_t offset = (rds.rdsB & 0x1f) * 4; - eRT_buffer[offset + 0] = rds.rdsC >> 8; - eRT_buffer[offset + 1] = rds.rdsC & 0xff; - eRT_buffer[offset + 2] = rds.rdsD >> 8; - eRT_buffer[offset + 3] = rds.rdsD & 0xff; + if(rdsCerrorThreshold) { + eRT_buffer[offset + 0] = rds.rdsC >> 8; + eRT_buffer[offset + 1] = rds.rdsC & 0xff; + } + if(rdsDerrorThreshold) { + eRT_buffer[offset + 2] = rds.rdsD >> 8; + eRT_buffer[offset + 3] = rds.rdsD & 0xff; + } eRT_buffer[127] = '\0'; byte endmarkereRT = 127; @@ -1368,9 +1371,9 @@ void TEF6686::readRDS(byte showrdserrors) { } } - if (!rdsBerrorThreshold && rdsgroup == RDS_GROUP_8A && (bitRead(rds.rdsB, 15))) rds.hasTMC = true; + if (rdsgroup == RDS_GROUP_8A && (bitRead(rds.rdsB, 15))) rds.hasTMC = true; - if ((!rdsBerrorThreshold && !rdsCerrorThreshold && !rdsDerrorThreshold) && DABAFblock == rdsgroup && rds.hasDABAF) { + if ((!rdsCerrorThreshold && !rdsDerrorThreshold) && DABAFblock == rdsgroup && rds.hasDABAF) { rds.dabaffreq = (rds.rdsC * 16); for (size_t i = 0; i < sizeof(DABfrequencyTable) / sizeof(DABfrequencyTable[0]); ++i) { @@ -1391,14 +1394,14 @@ void TEF6686::readRDS(byte showrdserrors) { break; case RDS_GROUP_14A: { - if (!rdsAerrorThreshold && !rdsBerrorThreshold && !rdsCerrorThreshold && !rdsDerrorThreshold) { + if (!rdsCerrorThreshold && !rdsDerrorThreshold && pi != 0) { rds.hasEON = true; bool isValuePresent = false; int eonIndex = -1; int i = 0; for (; i < 20; i++) { - if (eon[i].pi == rds.rdsD || rds.rdsA == rds.rdsD) { + if (eon[i].pi == rds.rdsD || pi == rds.rdsD) { isValuePresent = true; eonIndex = i; break; @@ -1484,7 +1487,7 @@ void TEF6686::readRDS(byte showrdserrors) { break; case RDS_GROUP_15A: { - if (showrdserrors == 3 || (!rdsBerrorThreshold && !rdsCerrorThreshold && !rdsDerrorThreshold)) { + if (showrdserrors == 3 || (!rdsCerrorThreshold && !rdsDerrorThreshold)) { if (pslong_process && rds.stationNameLong.length() > 0) rds.hasLongPS = true; uint8_t offset = (rds.rdsB & 7) * 4; @@ -1494,10 +1497,14 @@ void TEF6686::readRDS(byte showrdserrors) { pslong_buffer2[offset + 3] = pslong_buffer[offset + 3]; pslong_buffer2[32] = '\0'; - pslong_buffer[offset + 0] = rds.rdsC >> 8; - pslong_buffer[offset + 1] = rds.rdsC & 0xff; - pslong_buffer[offset + 2] = rds.rdsD >> 8; - pslong_buffer[offset + 3] = rds.rdsD & 0xff; + if(rdsCerrorThreshold) { + pslong_buffer[offset + 0] = rds.rdsC >> 8; + pslong_buffer[offset + 1] = rds.rdsC & 0xff; + } + if(rdsDerrorThreshold) { + pslong_buffer[offset + 2] = rds.rdsD >> 8; + pslong_buffer[offset + 3] = rds.rdsD & 0xff; + } pslong_buffer[32] = '\0'; byte endmarkerLPS = 32; diff --git a/src/rtc.cpp b/src/rtc.cpp index 94f1586..c1c3054 100644 --- a/src/rtc.cpp +++ b/src/rtc.cpp @@ -8,11 +8,11 @@ bool NTPupdated; ESP32Time rtc(0); bool rx_rtc_avail = false; -inline byte readFromModule(byte address) { +inline int16_t readFromModule(byte address) { Wire.beginTransmission(RX8010SJ_ADDRESS); Wire.write(address); - Wire.endTransmission(); - Wire.requestFrom(RX8010SJ_ADDRESS, 1); + if (Wire.endTransmission() != 0) return -1; + if (Wire.requestFrom(RX8010SJ_ADDRESS, 1) != 1) return -1; if (Wire.available()) return Wire.read(); return -1; } @@ -45,20 +45,22 @@ inline byte sumValueFromBinary(byte binary, byte length) { void sync_from_rx_rtc(int32_t offset = 0) { if(!rx_rtc_avail) return; - struct tm timeinfo; + struct tm timeinfo = {0}; Wire.beginTransmission(RX8010SJ_ADDRESS); Wire.write(0x10); Wire.endTransmission(); - Wire.requestFrom(RX8010SJ_ADDRESS, 7); - if (Wire.available()) { + if (Wire.requestFrom(RX8010SJ_ADDRESS, 7) == 7) { timeinfo.tm_sec = sumValueFromBinary(Wire.read(), 7); timeinfo.tm_min = sumValueFromBinary(Wire.read(), 7); timeinfo.tm_hour = sumValueFromBinary(Wire.read(), 6); auto dayOfWeekBin = Wire.read(); for (int i = 0; i < 7; i++) { - if (dayOfWeekBin & (1u << i)) timeinfo.tm_wday += i; + if (dayOfWeekBin & (1u << i)) { + timeinfo.tm_wday = i; + break; + } } timeinfo.tm_mday = sumValueFromBinary(Wire.read(), 6); @@ -71,7 +73,12 @@ void sync_from_rx_rtc(int32_t offset = 0) { bool init_rtc() { rtc.setTime(0); - byte flagregister = readFromModule(0x1E); + if(!rx_rtc_avail) return false; + auto flagregister = readFromModule(0x1E); + if(flagregister < 0) { + rx_rtc_avail = false; + return false; + } if((flagregister >> 1) & 1) { while((flagregister >> 1) & 1) { writeToModule(0x1E, 0); // clear VLF