You've already forked TEF6686_ESP32
Fixed a bug where some RDS info was not parsed
This commit is contained in:
872
src/TEF6686.cpp
872
src/TEF6686.cpp
@@ -370,229 +370,227 @@ void TEF6686::readRDS(byte showrdserrors)
|
|||||||
if (bitStartTime == 0) bitStartTime = millis(); else if (millis() - bitStartTime >= 87) rds.hasRDS = false;
|
if (bitStartTime == 0) bitStartTime = millis(); else if (millis() - bitStartTime >= 87) rds.hasRDS = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rds.rdsB != rdsBprevious) {
|
rds.rdsAerror = (((rds.rdsErr >> 14) & 0x03) > 0);
|
||||||
rds.rdsAerror = (((rds.rdsErr >> 14) & 0x03) > 0);
|
rds.rdsBerror = (((rds.rdsErr >> 12) & 0x03) > 0);
|
||||||
rds.rdsBerror = (((rds.rdsErr >> 12) & 0x03) > 0);
|
rds.rdsCerror = (((rds.rdsErr >> 10) & 0x03) > 0);
|
||||||
rds.rdsCerror = (((rds.rdsErr >> 10) & 0x03) > 0);
|
rds.rdsDerror = (((rds.rdsErr >> 8) & 0x03) > 0);
|
||||||
rds.rdsDerror = (((rds.rdsErr >> 8) & 0x03) > 0);
|
|
||||||
|
|
||||||
rdsAerrorThreshold = (((rds.rdsErr >> 14) & 0x03) > showrdserrors);
|
rdsAerrorThreshold = (((rds.rdsErr >> 14) & 0x03) > showrdserrors);
|
||||||
rdsBerrorThreshold = (((rds.rdsErr >> 12) & 0x03) > showrdserrors);
|
rdsBerrorThreshold = (((rds.rdsErr >> 12) & 0x03) > showrdserrors);
|
||||||
rdsCerrorThreshold = (((rds.rdsErr >> 10) & 0x03) > showrdserrors);
|
rdsCerrorThreshold = (((rds.rdsErr >> 10) & 0x03) > showrdserrors);
|
||||||
rdsDerrorThreshold = (((rds.rdsErr >> 8) & 0x03) > showrdserrors);
|
rdsDerrorThreshold = (((rds.rdsErr >> 8) & 0x03) > showrdserrors);
|
||||||
|
|
||||||
if ((rdsStat & (1 << 15))) rdsReady = true;
|
if ((rdsStat & (1 << 15))) rdsReady = true;
|
||||||
|
|
||||||
if (rdsReady) { // We have all data to decode... let's go...
|
if (rdsReady) { // We have all data to decode... let's go...
|
||||||
|
|
||||||
//PI decoder
|
//PI decoder
|
||||||
if (!rdsAerrorThreshold && afreset) {
|
if (!rdsAerrorThreshold && afreset) {
|
||||||
rds.correctPI = rds.rdsA;
|
rds.correctPI = rds.rdsA;
|
||||||
afreset = false;
|
afreset = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rds.region != 1 && ((!rdsAerrorThreshold && !rdsBerrorThreshold && !rdsCerrorThreshold && !rdsDerrorThreshold) || (rds.pierrors && !errorfreepi))) {
|
||||||
|
if (rds.rdsA != piold) {
|
||||||
|
piold = rds.rdsA;
|
||||||
|
rds.picode[0] = (rds.rdsA >> 12) & 0xF;
|
||||||
|
rds.picode[1] = (rds.rdsA >> 8) & 0xF;
|
||||||
|
rds.picode[2] = (rds.rdsA >> 4) & 0xF;
|
||||||
|
rds.picode[3] = rds.rdsA & 0xF;
|
||||||
|
for (int i = 0; i < 4; i++) {
|
||||||
|
if (rds.picode[i] < 10) {
|
||||||
|
rds.picode[i] += '0'; // Add ASCII offset for decimal digits
|
||||||
|
} else {
|
||||||
|
rds.picode[i] += 'A' - 10; // Add ASCII offset for hexadecimal letters A-F
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rds.region != 1 && ((!rdsAerrorThreshold && !rdsBerrorThreshold && !rdsCerrorThreshold && !rdsDerrorThreshold) || (rds.pierrors && !errorfreepi))) {
|
if (!rdsAerrorThreshold && !rdsBerrorThreshold && !rdsCerrorThreshold && !rdsDerrorThreshold) errorfreepi = true;
|
||||||
if (rds.rdsA != piold) {
|
|
||||||
piold = rds.rdsA;
|
if (!errorfreepi) {
|
||||||
rds.picode[0] = (rds.rdsA >> 12) & 0xF;
|
if (((rds.rdsErr >> 14) & 0x03) > 2) rds.picode[5] = '?'; else rds.picode[5] = ' ';
|
||||||
rds.picode[1] = (rds.rdsA >> 8) & 0xF;
|
if (((rds.rdsErr >> 14) & 0x03) > 1) rds.picode[4] = '?'; else rds.picode[4] = ' '; // Not sure, add a ?
|
||||||
rds.picode[2] = (rds.rdsA >> 4) & 0xF;
|
} else {
|
||||||
rds.picode[3] = rds.rdsA & 0xF;
|
rds.picode[4] = ' ';
|
||||||
|
rds.picode[5] = ' ';
|
||||||
|
}
|
||||||
|
rds.picode[6] = '\0';
|
||||||
|
if (strncmp(rds.picode, "0000", 4) == 0) {
|
||||||
|
if (piold != 0) {
|
||||||
|
rds.picode[0] = (piold >> 12) & 0xF;
|
||||||
|
rds.picode[1] = (piold >> 8) & 0xF;
|
||||||
|
rds.picode[2] = (piold >> 4) & 0xF;
|
||||||
|
rds.picode[3] = piold & 0xF;
|
||||||
for (int i = 0; i < 4; i++) {
|
for (int i = 0; i < 4; i++) {
|
||||||
if (rds.picode[i] < 10) {
|
if (rds.picode[i] < 10) {
|
||||||
rds.picode[i] += '0'; // Add ASCII offset for decimal digits
|
rds.picode[i] += '0'; // Add ASCII offset for decimal digits
|
||||||
} else {
|
} else {
|
||||||
rds.picode[i] += 'A' - 10; // Add ASCII offset for hexadecimal letters A-F
|
rds.picode[i] += 'A' - 10; // Add ASCII offset for hexadecimal letters A-F
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (!rdsAerrorThreshold && !rdsBerrorThreshold && !rdsCerrorThreshold && !rdsDerrorThreshold) errorfreepi = true;
|
|
||||||
|
|
||||||
if (!errorfreepi) {
|
|
||||||
if (((rds.rdsErr >> 14) & 0x03) > 2) rds.picode[5] = '?'; else rds.picode[5] = ' ';
|
|
||||||
if (((rds.rdsErr >> 14) & 0x03) > 1) rds.picode[4] = '?'; else rds.picode[4] = ' '; // Not sure, add a ?
|
|
||||||
} else {
|
} else {
|
||||||
rds.picode[4] = ' ';
|
if (rds.stationName.length() == 0) {
|
||||||
rds.picode[5] = ' ';
|
|
||||||
}
|
|
||||||
rds.picode[6] = '\0';
|
|
||||||
if (strncmp(rds.picode, "0000", 4) == 0) {
|
|
||||||
if (piold != 0) {
|
|
||||||
rds.picode[0] = (piold >> 12) & 0xF;
|
|
||||||
rds.picode[1] = (piold >> 8) & 0xF;
|
|
||||||
rds.picode[2] = (piold >> 4) & 0xF;
|
|
||||||
rds.picode[3] = piold & 0xF;
|
|
||||||
for (int i = 0; i < 4; i++) {
|
|
||||||
if (rds.picode[i] < 10) {
|
|
||||||
rds.picode[i] += '0'; // Add ASCII offset for decimal digits
|
|
||||||
} else {
|
|
||||||
rds.picode[i] += 'A' - 10; // Add ASCII offset for hexadecimal letters A-F
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if (rds.stationName.length() == 0) {
|
|
||||||
memset(rds.picode, 0, sizeof(rds.picode));
|
|
||||||
}
|
|
||||||
|
|
||||||
memset(rds.picode, 0, sizeof(rds.picode));
|
memset(rds.picode, 0, sizeof(rds.picode));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
memset(rds.picode, 0, sizeof(rds.picode));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// USA Station callsign decoder
|
// USA Station callsign decoder
|
||||||
if (rds.region == 1) { // When ID was decoded correctly before, no need to decode again.
|
if (rds.region == 1) { // When ID was decoded correctly before, no need to decode again.
|
||||||
uint16_t stationID = rds.rdsA;
|
uint16_t stationID = rds.rdsA;
|
||||||
if (stationID > 4096) {
|
if (stationID > 4096) {
|
||||||
if (stationID > 21671 && (stationID & 0xF00U) >> 8 == 0) stationID = ((uint16_t)uint8_t(0xA0 + ((stationID & 0xF000U) >> 12)) << 8) + lowByte(stationID); // C0DE -> ACDE
|
if (stationID > 21671 && (stationID & 0xF00U) >> 8 == 0) stationID = ((uint16_t)uint8_t(0xA0 + ((stationID & 0xF000U) >> 12)) << 8) + lowByte(stationID); // C0DE -> ACDE
|
||||||
if (stationID > 21671 && lowByte(stationID) == 0) stationID = 0xAF00 + uint8_t(highByte(stationID)); // CD00 -> AFCD
|
if (stationID > 21671 && lowByte(stationID) == 0) stationID = 0xAF00 + uint8_t(highByte(stationID)); // CD00 -> AFCD
|
||||||
if (stationID < 39247) {
|
if (stationID < 39247) {
|
||||||
if (stationID > 21671) {
|
if (stationID > 21671) {
|
||||||
rds.picode[0] = 'W';
|
rds.picode[0] = 'W';
|
||||||
stationID -= 21672;
|
stationID -= 21672;
|
||||||
} else {
|
|
||||||
rds.picode[0] = 'K';
|
|
||||||
stationID -= 4096;
|
|
||||||
}
|
|
||||||
rds.picode[1] = char(stationID / 676 + 65);
|
|
||||||
rds.picode[2] = char((stationID - 676 * int(stationID / 676)) / 26 + 65);
|
|
||||||
rds.picode[3] = char(((stationID - 676 * int(stationID / 676)) % 26) + 65);
|
|
||||||
rds.picode[5] = '\0';
|
|
||||||
} else {
|
} else {
|
||||||
stationID -= 4835;
|
|
||||||
rds.picode[0] = 'K';
|
rds.picode[0] = 'K';
|
||||||
rds.picode[1] = char(stationID / 676 + 65);
|
stationID -= 4096;
|
||||||
rds.picode[2] = char((stationID - 676 * int(stationID / 676)) / 26 + 65);
|
|
||||||
rds.picode[3] = char(((stationID - 676 * int(stationID / 676)) % 26) + 65);
|
|
||||||
rds.picode[5] = '\0';
|
|
||||||
}
|
}
|
||||||
|
rds.picode[1] = char(stationID / 676 + 65);
|
||||||
|
rds.picode[2] = char((stationID - 676 * int(stationID / 676)) / 26 + 65);
|
||||||
|
rds.picode[3] = char(((stationID - 676 * int(stationID / 676)) % 26) + 65);
|
||||||
|
rds.picode[5] = '\0';
|
||||||
|
} else {
|
||||||
|
stationID -= 4835;
|
||||||
|
rds.picode[0] = 'K';
|
||||||
|
rds.picode[1] = char(stationID / 676 + 65);
|
||||||
|
rds.picode[2] = char((stationID - 676 * int(stationID / 676)) / 26 + 65);
|
||||||
|
rds.picode[3] = char(((stationID - 676 * int(stationID / 676)) % 26) + 65);
|
||||||
|
rds.picode[5] = '\0';
|
||||||
}
|
}
|
||||||
if (((rds.rdsErr >> 14) & 0x02) > 2) rds.picode[5] = '?';
|
|
||||||
if (((rds.rdsErr >> 14) & 0x01) > 1) rds.picode[4] = '?'; else rds.picode[4] = ' '; // Not sure, add a ?
|
|
||||||
rds.picode[6] = '\0';
|
|
||||||
}
|
}
|
||||||
|
if (((rds.rdsErr >> 14) & 0x02) > 2) rds.picode[5] = '?';
|
||||||
|
if (((rds.rdsErr >> 14) & 0x01) > 1) rds.picode[4] = '?'; else rds.picode[4] = ' '; // Not sure, add a ?
|
||||||
|
rds.picode[6] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
// TP Indicator
|
// TP Indicator
|
||||||
rds.hasTP = (bitRead(rds.rdsB, 10));
|
rds.hasTP = (bitRead(rds.rdsB, 10));
|
||||||
|
|
||||||
if (!rdsBerrorThreshold) rdsblock = rds.rdsB >> 11; else return;
|
if (!rdsBerrorThreshold) rdsblock = rds.rdsB >> 11; else return;
|
||||||
switch (rdsblock) {
|
switch (rdsblock) {
|
||||||
case RDS_GROUP_0A:
|
case RDS_GROUP_0A:
|
||||||
case RDS_GROUP_0B:
|
case RDS_GROUP_0B:
|
||||||
{
|
{
|
||||||
//PS decoder
|
//PS decoder
|
||||||
if (showrdserrors == 3 || (!rdsBerrorThreshold && !rdsDerrorThreshold)) {
|
if (showrdserrors == 3 || (!rdsBerrorThreshold && !rdsDerrorThreshold)) {
|
||||||
offset = rds.rdsB & 0x03; // Let's get the character offset for PS
|
offset = rds.rdsB & 0x03; // Let's get the character offset for PS
|
||||||
|
|
||||||
ps_buffer2[(offset * 2) + 0] = ps_buffer[(offset * 2) + 0]; // Make a copy of the PS buffer
|
ps_buffer2[(offset * 2) + 0] = ps_buffer[(offset * 2) + 0]; // Make a copy of the PS buffer
|
||||||
ps_buffer2[(offset * 2) + 1] = ps_buffer[(offset * 2) + 1];
|
ps_buffer2[(offset * 2) + 1] = ps_buffer[(offset * 2) + 1];
|
||||||
|
|
||||||
ps_buffer[(offset * 2) + 0] = rds.rdsD >> 8; // First character of segment
|
ps_buffer[(offset * 2) + 0] = rds.rdsD >> 8; // First character of segment
|
||||||
ps_buffer[(offset * 2) + 1] = rds.rdsD & 0xFF; // Second character of segment
|
ps_buffer[(offset * 2) + 1] = rds.rdsD & 0xFF; // Second character of segment
|
||||||
ps_buffer[(offset * 2) + 2] = '\0'; // Endmarker of segment
|
ps_buffer[(offset * 2) + 2] = '\0'; // Endmarker of segment
|
||||||
|
|
||||||
if (offset == 3 && ps_process) { // Last chars are received
|
if (offset == 3 && ps_process) { // Last chars are received
|
||||||
if (ps_buffer != ps_buffer2) { // When difference between old and new, let's go...
|
if (ps_buffer != ps_buffer2) { // When difference between old and new, let's go...
|
||||||
RDScharConverter(ps_buffer, PStext, sizeof(PStext) / sizeof(wchar_t), true); // Convert 8 bit ASCII to 16 bit ASCII
|
RDScharConverter(ps_buffer, PStext, sizeof(PStext) / sizeof(wchar_t), true); // Convert 8 bit ASCII to 16 bit ASCII
|
||||||
String utf8String = convertToUTF8(PStext); // Convert RDS characterset to 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
|
rds.stationName = extractUTF8Substring(utf8String, 0, 8, true); // Make sure PS does not exceed 8 characters
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!ps_process) { // Let's get 2 runs of 8 PS characters fast and without refresh
|
|
||||||
ps_counter ++; // Let's count each run
|
|
||||||
RDScharConverter(ps_buffer, 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);
|
|
||||||
if (ps_counter == 6) ps_process = true; // OK, we had 2 runs, now let's go the idle PS writing
|
|
||||||
}
|
|
||||||
|
|
||||||
if (offset == 0) rds.hasDynamicPTY = bitRead(rds.rdsB, 2) & 0x1F; // Dynamic PTY flag
|
|
||||||
if (offset == 1) rds.hasCompressed = bitRead(rds.rdsB, 2) & 0x1F; // Compressed flag
|
|
||||||
if (offset == 2) rds.hasArtificialhead = bitRead(rds.rdsB, 2) & 0x1F; // Artificial head flag
|
|
||||||
if (offset == 3) rds.hasStereo = bitRead(rds.rdsB, 2) & 0x1F; // Stereo flag
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// PTY decoder
|
if (!ps_process) { // Let's get 2 runs of 8 PS characters fast and without refresh
|
||||||
if (!rdsBerrorThreshold) {
|
ps_counter ++; // Let's count each run
|
||||||
rds.stationTypeCode = (rds.rdsB >> 5) & 0x1F; // Get 5 PTY bits from Block B
|
RDScharConverter(ps_buffer, PStext, sizeof(PStext) / sizeof(wchar_t), true); // Convert 8 bit ASCII to 16 bit ASCII
|
||||||
if (rds.region == 0) strcpy(rds.stationType, PTY_EU[rds.stationTypeCode]);
|
String utf8String = convertToUTF8(PStext); // Convert RDS characterset to ASCII
|
||||||
if (rds.region == 1) strcpy(rds.stationType, PTY_USA[rds.stationTypeCode]);
|
rds.stationName = extractUTF8Substring(utf8String, 0, 8, true);
|
||||||
|
if (ps_counter == 6) ps_process = true; // OK, we had 2 runs, now let's go the idle PS writing
|
||||||
//TA decoder
|
|
||||||
rds.hasTA = (bitRead(rds.rdsB, 4)) && (bitRead(rds.rdsB, 10)) & 0x1F; // Read TA flag
|
|
||||||
|
|
||||||
//MS decoder
|
|
||||||
if (((bitRead(rds.rdsB, 3)) & 0x1F) == 1) rds.MS = 1; else rds.MS = 2; // Read MS flag
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!rdsCerrorThreshold) {
|
if (offset == 0) rds.hasDynamicPTY = bitRead(rds.rdsB, 2) & 0x1F; // Dynamic PTY flag
|
||||||
//AF decoder
|
if (offset == 1) rds.hasCompressed = bitRead(rds.rdsB, 2) & 0x1F; // Compressed flag
|
||||||
if (rdsblock == 0) { // Only when in GROUP 0A
|
if (offset == 2) rds.hasArtificialhead = bitRead(rds.rdsB, 2) & 0x1F; // Artificial head flag
|
||||||
|
if (offset == 3) rds.hasStereo = bitRead(rds.rdsB, 2) & 0x1F; // Stereo flag
|
||||||
|
}
|
||||||
|
|
||||||
if ((rds.rdsC >> 8) > 224 && (rds.rdsC >> 8) < 250) {
|
// PTY decoder
|
||||||
if (afmethodcounter > 2) afmethodB = true;
|
if (!rdsBerrorThreshold) {
|
||||||
afmethodcounter = 0;
|
rds.stationTypeCode = (rds.rdsB >> 5) & 0x1F; // Get 5 PTY bits from Block B
|
||||||
}
|
if (rds.region == 0) strcpy(rds.stationType, PTY_EU[rds.stationTypeCode]);
|
||||||
|
if (rds.region == 1) strcpy(rds.stationType, PTY_USA[rds.stationTypeCode]);
|
||||||
|
|
||||||
if (((rds.rdsC >> 8) > 0 && (rds.rdsC >> 8) > 224) && ((rds.rdsC >> 8) > 0 && (rds.rdsC >> 8) < 250)) afinit = true;
|
//TA decoder
|
||||||
if (afinit) {
|
rds.hasTA = (bitRead(rds.rdsB, 4)) && (bitRead(rds.rdsB, 10)) & 0x1F; // Read TA flag
|
||||||
if ((rds.rdsB >> 11) == 0 && af_counter < 50) {
|
|
||||||
uint16_t buffer0;
|
|
||||||
uint16_t buffer1;
|
|
||||||
|
|
||||||
if ((rds.rdsC >> 8) > 0 && (rds.rdsC >> 8) < 205) buffer0 = (rds.rdsC >> 8) * 10 + 8750; else buffer0 = 0;
|
//MS decoder
|
||||||
if ((rds.rdsC & 0xFF) > 0 && (rds.rdsC & 0xFF) < 205) buffer1 = (rds.rdsC & 0xFF) * 10 + 8750; else buffer1 = 0;
|
if (((bitRead(rds.rdsB, 3)) & 0x1F) == 1) rds.MS = 1; else rds.MS = 2; // Read MS flag
|
||||||
if (buffer0 != 0 || buffer1 != 0) rds.hasAF = true;
|
}
|
||||||
if (buffer0 == currentfreq || buffer1 == currentfreq) afmethodcounter++;
|
|
||||||
|
|
||||||
bool isValuePresent = false;
|
if (!rdsCerrorThreshold) {
|
||||||
|
//AF decoder
|
||||||
|
if (rdsblock == 0) { // Only when in GROUP 0A
|
||||||
|
|
||||||
|
if ((rds.rdsC >> 8) > 224 && (rds.rdsC >> 8) < 250) {
|
||||||
|
if (afmethodcounter > 2) afmethodB = true;
|
||||||
|
afmethodcounter = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (((rds.rdsC >> 8) > 0 && (rds.rdsC >> 8) > 224) && ((rds.rdsC >> 8) > 0 && (rds.rdsC >> 8) < 250)) afinit = true;
|
||||||
|
if (afinit) {
|
||||||
|
if ((rds.rdsB >> 11) == 0 && af_counter < 50) {
|
||||||
|
uint16_t buffer0;
|
||||||
|
uint16_t buffer1;
|
||||||
|
|
||||||
|
if ((rds.rdsC >> 8) > 0 && (rds.rdsC >> 8) < 205) buffer0 = (rds.rdsC >> 8) * 10 + 8750; else buffer0 = 0;
|
||||||
|
if ((rds.rdsC & 0xFF) > 0 && (rds.rdsC & 0xFF) < 205) buffer1 = (rds.rdsC & 0xFF) * 10 + 8750; else buffer1 = 0;
|
||||||
|
if (buffer0 != 0 || buffer1 != 0) rds.hasAF = true;
|
||||||
|
if (buffer0 == currentfreq || buffer1 == currentfreq) afmethodcounter++;
|
||||||
|
|
||||||
|
bool isValuePresent = false;
|
||||||
|
for (int i = 0; i < 50; i++) {
|
||||||
|
if (rds.sortaf && (buffer0 == currentfreq) || buffer0 == 0 || af[i].frequency == buffer0) {
|
||||||
|
isValuePresent = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isValuePresent) {
|
||||||
|
af[af_counter].frequency = buffer0;
|
||||||
|
if (buffer1 == currentfreq && buffer0 > buffer1) af[af_counter].regional = true;
|
||||||
|
if (af_counter < 50) af_counter++;
|
||||||
|
}
|
||||||
|
|
||||||
|
isValuePresent = false;
|
||||||
|
for (int i = 0; i < 50; i++) {
|
||||||
|
if (rds.sortaf && (buffer1 == currentfreq) || buffer1 == 0 || af[i].frequency == buffer1) {
|
||||||
|
isValuePresent = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isValuePresent) {
|
||||||
|
af[af_counter].frequency = buffer1;
|
||||||
|
if (buffer0 == currentfreq && buffer0 < buffer1) af[af_counter].regional = true;
|
||||||
|
if (af_counter < 50) af_counter++;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rds.sortaf) {
|
||||||
for (int i = 0; i < 50; i++) {
|
for (int i = 0; i < 50; i++) {
|
||||||
if (rds.sortaf && (buffer0 == currentfreq) || buffer0 == 0 || af[i].frequency == buffer0) {
|
for (int j = 0; j < 50 - i; j++) {
|
||||||
isValuePresent = true;
|
if (af[j].frequency == 0) continue;
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!isValuePresent) {
|
if (af[j].frequency > af[j + 1].frequency && af[j + 1].frequency != 0) {
|
||||||
af[af_counter].frequency = buffer0;
|
uint16_t temp = af[j].frequency;
|
||||||
if (buffer1 == currentfreq && buffer0 > buffer1) af[af_counter].regional = true;
|
bool temp3 = af[j].afvalid;
|
||||||
if (af_counter < 50) af_counter++;
|
bool temp4 = af[j].checked;
|
||||||
}
|
bool temp5 = af[j].regional;
|
||||||
|
af[j].frequency = af[j + 1].frequency;
|
||||||
isValuePresent = false;
|
af[j].afvalid = af[j + 1].afvalid;
|
||||||
for (int i = 0; i < 50; i++) {
|
af[j].checked = af[j + 1].checked;
|
||||||
if (rds.sortaf && (buffer1 == currentfreq) || buffer1 == 0 || af[i].frequency == buffer1) {
|
af[j].regional = af[j + 1].regional;
|
||||||
isValuePresent = true;
|
af[j + 1].frequency = temp;
|
||||||
break;
|
af[j + 1].afvalid = temp3;
|
||||||
}
|
af[j + 1].checked = temp4;
|
||||||
}
|
af[j + 1].regional = temp5;
|
||||||
|
|
||||||
if (!isValuePresent) {
|
|
||||||
af[af_counter].frequency = buffer1;
|
|
||||||
if (buffer0 == currentfreq && buffer0 < buffer1) af[af_counter].regional = true;
|
|
||||||
if (af_counter < 50) af_counter++;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (rds.sortaf) {
|
|
||||||
for (int i = 0; i < 50; i++) {
|
|
||||||
for (int j = 0; j < 50 - i; j++) {
|
|
||||||
if (af[j].frequency == 0) continue;
|
|
||||||
|
|
||||||
if (af[j].frequency > af[j + 1].frequency && af[j + 1].frequency != 0) {
|
|
||||||
uint16_t temp = af[j].frequency;
|
|
||||||
bool temp3 = af[j].afvalid;
|
|
||||||
bool temp4 = af[j].checked;
|
|
||||||
bool temp5 = af[j].regional;
|
|
||||||
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 + 1].frequency = temp;
|
|
||||||
af[j + 1].afvalid = temp3;
|
|
||||||
af[j + 1].checked = temp4;
|
|
||||||
af[j + 1].regional = temp5;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -600,296 +598,294 @@ void TEF6686::readRDS(byte showrdserrors)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} break;
|
}
|
||||||
|
} break;
|
||||||
|
|
||||||
case RDS_GROUP_1A: {
|
case RDS_GROUP_1A: {
|
||||||
if (!rdsCerrorThreshold) {
|
Serial.println(rds.rdsC >> 12);
|
||||||
if (rds.rdsC >> 12 == 0) { // ECC code readout
|
if (!rdsCerrorThreshold) {
|
||||||
rds.ECC = rds.rdsC & 0xff;
|
if (rds.rdsC >> 12 == 0) { // ECC code readout
|
||||||
rds.hasECC = true;
|
rds.ECC = rds.rdsC & 0xff;
|
||||||
}
|
rds.hasECC = true;
|
||||||
|
|
||||||
if (rds.rdsC >> 12 == 3) { // LIC code readout
|
|
||||||
rds.LIC = rds.rdsC & 0xff;
|
|
||||||
rds.hasLIC = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!rdsDerrorThreshold) {
|
if (rds.rdsC >> 12 == 3) { // LIC code readout
|
||||||
if (rds.rdsD != 0) { // PIN decoder
|
rds.LIC = rds.rdsC & 0xff;
|
||||||
rds.hasPIN = true;
|
rds.hasLIC = true;
|
||||||
rds.pinMin = rds.rdsD & 0x3f;
|
|
||||||
rds.pinHour = rds.rdsD >> 6 & 0x1f;
|
|
||||||
rds.pinDay = rds.rdsD >> 11 & 0x1f;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
} break;
|
}
|
||||||
|
|
||||||
case RDS_GROUP_2A: {
|
if (!rdsDerrorThreshold) {
|
||||||
if (showrdserrors == 3 || (!rdsBerrorThreshold && !rdsCerrorThreshold && !rdsDerrorThreshold)) {
|
if (rds.rdsD != 0) { // PIN decoder
|
||||||
// RT decoder (64 characters)
|
rds.hasPIN = true;
|
||||||
rds.hasRT = true;
|
rds.pinMin = rds.rdsD & 0x3f;
|
||||||
rds.rtAB = (bitRead(rds.rdsB, 4)); // Get AB flag
|
rds.pinHour = rds.rdsD >> 6 & 0x1f;
|
||||||
|
rds.pinDay = rds.rdsD >> 11 & 0x1f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
|
||||||
if (initab) {
|
case RDS_GROUP_2A: {
|
||||||
rtABold = rds.rtAB;
|
if (showrdserrors == 3 || (!rdsBerrorThreshold && !rdsCerrorThreshold && !rdsDerrorThreshold)) {
|
||||||
initab = false;
|
// RT decoder (64 characters)
|
||||||
}
|
rds.hasRT = true;
|
||||||
|
rds.rtAB = (bitRead(rds.rdsB, 4)); // Get AB flag
|
||||||
|
|
||||||
if (rds.rtAB != rtABold) { // Erase old RT, because of AB change
|
if (initab) {
|
||||||
initrt = false;
|
rtABold = rds.rtAB;
|
||||||
if (rds.rtbuffer) {
|
initab = false;
|
||||||
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, 64, true); // Make sure RT does not exceed 64 characters
|
|
||||||
}
|
|
||||||
|
|
||||||
for (byte i = 0; i < 64; i++) {
|
if (rds.rtAB != rtABold) { // Erase old RT, because of AB change
|
||||||
rt_buffer[i] = 0x20;
|
initrt = false;
|
||||||
}
|
if (rds.rtbuffer) {
|
||||||
rt_buffer[64] = '\0';
|
|
||||||
rtABold = rds.rtAB;
|
|
||||||
}
|
|
||||||
|
|
||||||
offset = (rds.rdsB & 0xf) * 4; // Get RT character segment
|
|
||||||
rt_buffer[offset + 0] = rds.rdsC >> 8; // First character of segment
|
|
||||||
rt_buffer[offset + 1] = rds.rdsC & 0xff; // Second character of segment
|
|
||||||
rt_buffer[offset + 2] = rds.rdsD >> 8; // Thirth character of segment
|
|
||||||
rt_buffer[offset + 3] = rds.rdsD & 0xff; // Fourth character of segment
|
|
||||||
|
|
||||||
if (initrt || !rds.rtbuffer) {
|
|
||||||
wchar_t RTtext[65] = L""; // Create 16 bit char buffer for Extended ASCII
|
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
|
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 = convertToUTF8(RTtext); // Convert RDS characterset to ASCII
|
||||||
rds.stationText = extractUTF8Substring(rds.stationText, 0, 64, true); // Make sure RT does not exceed 64 characters
|
rds.stationText = extractUTF8Substring(rds.stationText, 0, 64, true); // Make sure RT does not exceed 64 characters
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int i = 0; i < 64; i++) rt_buffer2[i] = rt_buffer[i];
|
for (byte i = 0; i < 64; i++) {
|
||||||
}
|
rt_buffer[i] = 0x20;
|
||||||
} break;
|
|
||||||
|
|
||||||
case RDS_GROUP_2B: {
|
|
||||||
if (showrdserrors == 3 || (!rdsBerrorThreshold && !rdsDerrorThreshold)) {
|
|
||||||
// RT decoder (32 characters)
|
|
||||||
rds.hasRT = true;
|
|
||||||
rds.rtAB32 = (bitRead(rds.rdsB, 4)); // Get AB flag
|
|
||||||
|
|
||||||
if (rds.rtAB32 != rtAB32old) { // Erase old RT, because of AB change
|
|
||||||
for (byte i = 0; i < 33; i++) {
|
|
||||||
rt_buffer32[i] = 0x20;
|
|
||||||
}
|
|
||||||
rt_buffer32[32] = '\0';
|
|
||||||
rtAB32old = rds.rtAB32;
|
|
||||||
}
|
}
|
||||||
|
rt_buffer[64] = '\0';
|
||||||
offset = (rds.rdsB & 0xf) * 2; // Get RT character segment
|
rtABold = rds.rtAB;
|
||||||
rt_buffer32[offset + 0] = rds.rdsD >> 8; // First character of segment
|
|
||||||
rt_buffer32[offset + 1] = rds.rdsD & 0xff; // Second character of segment
|
|
||||||
|
|
||||||
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, 32, true); // Make sure RT does not exceed 32 characters
|
|
||||||
}
|
}
|
||||||
} break;
|
|
||||||
|
|
||||||
case RDS_GROUP_3A: {
|
offset = (rds.rdsB & 0xf) * 4; // Get RT character segment
|
||||||
if (!rdsDerrorThreshold) {
|
rt_buffer[offset + 0] = rds.rdsC >> 8; // First character of segment
|
||||||
// RT+ init
|
rt_buffer[offset + 1] = rds.rdsC & 0xff; // Second character of segment
|
||||||
if (rds.rdsD == 0x4BD7) { // Check for RT+ application
|
rt_buffer[offset + 2] = rds.rdsD >> 8; // Thirth character of segment
|
||||||
rds.hasRDSplus = true; // Set flag
|
rt_buffer[offset + 3] = rds.rdsD & 0xff; // Fourth character of segment
|
||||||
rtplusblock = ((rds.rdsB & 0x1F) >> 1) * 2; // Get RT+ Block
|
|
||||||
}
|
if (initrt || !rds.rtbuffer) {
|
||||||
|
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, 64, true); // Make sure RT does not exceed 64 characters
|
||||||
}
|
}
|
||||||
} break;
|
|
||||||
|
|
||||||
case RDS_GROUP_4A: {
|
for (int i = 0; i < 64; i++) rt_buffer2[i] = rt_buffer[i];
|
||||||
if (!rdsBerrorThreshold && !rdsCerrorThreshold && !rdsDerrorThreshold) {
|
|
||||||
// CT
|
|
||||||
uint32_t mjd;
|
|
||||||
mjd = (rds.rdsB & 0x03);
|
|
||||||
mjd <<= 15;
|
|
||||||
mjd += ((rds.rdsC >> 1) & 0x7FFF);
|
|
||||||
|
|
||||||
long J, C, Y, M;
|
|
||||||
J = mjd + 2400001 + 68569;
|
|
||||||
C = 4 * J / 146097;
|
|
||||||
J = J - (146097 * C + 3) / 4;
|
|
||||||
Y = 4000 * (J + 1) / 1461001;
|
|
||||||
J = J - 1461 * Y / 4 + 31;
|
|
||||||
M = 80 * (J + 0) / 2447;
|
|
||||||
|
|
||||||
rds.day = J - 2447 * M / 80;
|
|
||||||
J = M / 11;
|
|
||||||
|
|
||||||
rds.month = M + 2 - (12 * J);
|
|
||||||
rds.year = 100 * (C - 49) + Y + J;
|
|
||||||
rds.hour = ((rds.rdsD >> 12) & 0x0f);
|
|
||||||
rds.hour += ((rds.rdsC << 4) & 0x0010);
|
|
||||||
rds.minute = (rds.rdsD >> 6) & 0x3f;
|
|
||||||
rds.offsetplusmin = bitRead(rds.rdsD, 5);
|
|
||||||
rds.offset = (rds.rdsD & 0x3f);
|
|
||||||
rds.hasCT = true;
|
|
||||||
setTime(rds.hour, rds.minute, 0, rds.day, rds.month, rds.year);
|
|
||||||
adjustTime((((rds.offsetplusmin ? -rds.offset : rds.offset) / 2) * 3600));
|
|
||||||
}
|
|
||||||
} break;
|
|
||||||
|
|
||||||
case RDS_GROUP_10A: {
|
|
||||||
if (!rdsCerrorThreshold && !rdsDerrorThreshold) {
|
|
||||||
// PTYN
|
|
||||||
offset = bitRead(rds.rdsB, 0); // Get char offset
|
|
||||||
|
|
||||||
ptyn_buffer[(offset * 4) + 0] = rds.rdsC >> 8; // Get position 1 and 5
|
|
||||||
ptyn_buffer[(offset * 4) + 1] = rds.rdsC & 0xFF; // Get position 2 and 6
|
|
||||||
ptyn_buffer[(offset * 4) + 2] = rds.rdsD >> 8; // Get position 3 and 7
|
|
||||||
ptyn_buffer[(offset * 4) + 3] = rds.rdsD & 0xFF; // Get position 4 and 8
|
|
||||||
RDScharConverter(ptyn_buffer, PTYNtext, sizeof(PTYNtext) / sizeof(wchar_t), false); // Convert 8 bit ASCII to 16 bit ASCII
|
|
||||||
String utf8String = convertToUTF8(PTYNtext); // Convert RDS characterset to ASCII
|
|
||||||
rds.PTYN = extractUTF8Substring(utf8String, 0, 8, false); // Make sure text is not longer than 8 chars
|
|
||||||
}
|
|
||||||
} break;
|
|
||||||
|
|
||||||
case RDS_GROUP_5A:
|
|
||||||
case RDS_GROUP_6A:
|
|
||||||
case RDS_GROUP_7A:
|
|
||||||
case RDS_GROUP_8A:
|
|
||||||
case RDS_GROUP_9A:
|
|
||||||
case RDS_GROUP_11A:
|
|
||||||
case RDS_GROUP_12A:
|
|
||||||
case RDS_GROUP_13A: {
|
|
||||||
// RT+ decoding
|
|
||||||
if ((!rdsBerrorThreshold && !rdsCerrorThreshold && !rdsDerrorThreshold) && rtplusblock == rdsblock && rds.hasRDSplus) { // Are we in the right RT+ block and is all ok to go?
|
|
||||||
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;
|
|
||||||
uint16_t length_marker_1 = (rds.rdsC >> 1) & 0x3F;
|
|
||||||
uint16_t start_marker_2 = (rds.rdsD >> 5) & 0x3F;
|
|
||||||
uint16_t length_marker_2 = (rds.rdsD & 0x1F);
|
|
||||||
togglebit = bitRead(lowByte(rds.rdsB), 4);
|
|
||||||
runningbit = bitRead(lowByte(rds.rdsB), 3);
|
|
||||||
|
|
||||||
switch (rds.rdsplusTag1) {
|
|
||||||
case 0: rds.rdsplusTag1 = 169; break;
|
|
||||||
case 1 ... 53: rds.rdsplusTag1 += 111; break;
|
|
||||||
case 59 ... 63: rds.rdsplusTag1 += 105; break;
|
|
||||||
default: rds.rdsplusTag1 = 169; break;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (rds.rdsplusTag2) {
|
|
||||||
case 0: rds.rdsplusTag2 = 169; break;
|
|
||||||
case 1 ... 53: rds.rdsplusTag2 += 111; break;
|
|
||||||
case 59 ... 63: rds.rdsplusTag2 += 105; break;
|
|
||||||
default: rds.rdsplusTag2 = 169; break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (togglebit) {
|
|
||||||
for (int i = 0; i < 45; i++) {
|
|
||||||
RDSplus1[i] = 0;
|
|
||||||
RDSplus2[i] = 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (rds.rtAB == rtABold) {
|
|
||||||
for (int i = 0; i <= length_marker_1; i++)RDSplus1[i] = rt_buffer2[i + start_marker_1];
|
|
||||||
RDSplus1[length_marker_1 + 1] = 0;
|
|
||||||
|
|
||||||
for (int i = 0; i <= length_marker_2; i++)RDSplus2[i] = rt_buffer2[i + start_marker_2];
|
|
||||||
RDSplus2[length_marker_2 + 1] = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
wchar_t RTtext1[45] = L""; // Create 16 bit char buffer for Extended ASCII
|
|
||||||
RDScharConverter(RDSplus1, RTtext1, sizeof(RTtext1) / sizeof(wchar_t), false); // Convert 8 bit ASCII to 16 bit ASCII
|
|
||||||
rds.RTContent1 = convertToUTF8(RTtext1); // Convert RDS characterset to ASCII
|
|
||||||
rds.RTContent1 = extractUTF8Substring(rds.RTContent1, 0, 44, false); // Make sure RT does not exceed 32 characters
|
|
||||||
|
|
||||||
wchar_t RTtext2[45] = L""; // Create 16 bit char buffer for Extended ASCII
|
|
||||||
RDScharConverter(RDSplus2, RTtext2, sizeof(RTtext2) / sizeof(wchar_t), false); // Convert 8 bit ASCII to 16 bit ASCII
|
|
||||||
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
|
|
||||||
}
|
|
||||||
if (!rdsBerrorThreshold && rdsblock == 16 && (rds.rdsB & (1 << 4))) rds.hasTMC = true; // TMC flag
|
|
||||||
}
|
}
|
||||||
break;
|
} break;
|
||||||
|
|
||||||
case RDS_GROUP_14A: {
|
case RDS_GROUP_2B: {
|
||||||
// EON
|
if (showrdserrors == 3 || (!rdsBerrorThreshold && !rdsDerrorThreshold)) {
|
||||||
if (!rdsDerrorThreshold) {
|
// RT decoder (32 characters)
|
||||||
rds.hasEON = true; // Group is there, so we have EON
|
rds.hasRT = true;
|
||||||
|
rds.rtAB32 = (bitRead(rds.rdsB, 4)); // Get AB flag
|
||||||
|
|
||||||
bool isValuePresent = false;
|
if (rds.rtAB32 != rtAB32old) { // Erase old RT, because of AB change
|
||||||
for (int i = 0; i < 20; i++) {
|
for (byte i = 0; i < 33; i++) {
|
||||||
if (eon[i].pi == rds.rdsD) { // Check if EON is already in array
|
rt_buffer32[i] = 0x20;
|
||||||
isValuePresent = true;
|
}
|
||||||
|
rt_buffer32[32] = '\0';
|
||||||
|
rtAB32old = rds.rtAB32;
|
||||||
|
}
|
||||||
|
|
||||||
|
offset = (rds.rdsB & 0xf) * 2; // Get RT character segment
|
||||||
|
rt_buffer32[offset + 0] = rds.rdsD >> 8; // First character of segment
|
||||||
|
rt_buffer32[offset + 1] = rds.rdsD & 0xff; // Second character of segment
|
||||||
|
|
||||||
|
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, 32, true); // Make sure RT does not exceed 32 characters
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case RDS_GROUP_3A: {
|
||||||
|
if (!rdsDerrorThreshold) {
|
||||||
|
// RT+ init
|
||||||
|
if (rds.rdsD == 0x4BD7) { // Check for RT+ application
|
||||||
|
rds.hasRDSplus = true; // Set flag
|
||||||
|
rtplusblock = ((rds.rdsB & 0x1F) >> 1) * 2; // Get RT+ Block
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case RDS_GROUP_4A: {
|
||||||
|
if (!rdsBerrorThreshold && !rdsCerrorThreshold && !rdsDerrorThreshold) {
|
||||||
|
// CT
|
||||||
|
uint32_t mjd;
|
||||||
|
mjd = (rds.rdsB & 0x03);
|
||||||
|
mjd <<= 15;
|
||||||
|
mjd += ((rds.rdsC >> 1) & 0x7FFF);
|
||||||
|
|
||||||
|
long J, C, Y, M;
|
||||||
|
J = mjd + 2400001 + 68569;
|
||||||
|
C = 4 * J / 146097;
|
||||||
|
J = J - (146097 * C + 3) / 4;
|
||||||
|
Y = 4000 * (J + 1) / 1461001;
|
||||||
|
J = J - 1461 * Y / 4 + 31;
|
||||||
|
M = 80 * (J + 0) / 2447;
|
||||||
|
|
||||||
|
rds.day = J - 2447 * M / 80;
|
||||||
|
J = M / 11;
|
||||||
|
|
||||||
|
rds.month = M + 2 - (12 * J);
|
||||||
|
rds.year = 100 * (C - 49) + Y + J;
|
||||||
|
rds.hour = ((rds.rdsD >> 12) & 0x0f);
|
||||||
|
rds.hour += ((rds.rdsC << 4) & 0x0010);
|
||||||
|
rds.minute = (rds.rdsD >> 6) & 0x3f;
|
||||||
|
rds.offsetplusmin = bitRead(rds.rdsD, 5);
|
||||||
|
rds.offset = (rds.rdsD & 0x3f);
|
||||||
|
rds.hasCT = true;
|
||||||
|
setTime(rds.hour, rds.minute, 0, rds.day, rds.month, rds.year);
|
||||||
|
adjustTime((((rds.offsetplusmin ? -rds.offset : rds.offset) / 2) * 3600));
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case RDS_GROUP_10A: {
|
||||||
|
if (!rdsCerrorThreshold && !rdsDerrorThreshold) {
|
||||||
|
// PTYN
|
||||||
|
offset = bitRead(rds.rdsB, 0); // Get char offset
|
||||||
|
|
||||||
|
ptyn_buffer[(offset * 4) + 0] = rds.rdsC >> 8; // Get position 1 and 5
|
||||||
|
ptyn_buffer[(offset * 4) + 1] = rds.rdsC & 0xFF; // Get position 2 and 6
|
||||||
|
ptyn_buffer[(offset * 4) + 2] = rds.rdsD >> 8; // Get position 3 and 7
|
||||||
|
ptyn_buffer[(offset * 4) + 3] = rds.rdsD & 0xFF; // Get position 4 and 8
|
||||||
|
RDScharConverter(ptyn_buffer, PTYNtext, sizeof(PTYNtext) / sizeof(wchar_t), false); // Convert 8 bit ASCII to 16 bit ASCII
|
||||||
|
String utf8String = convertToUTF8(PTYNtext); // Convert RDS characterset to ASCII
|
||||||
|
rds.PTYN = extractUTF8Substring(utf8String, 0, 8, false); // Make sure text is not longer than 8 chars
|
||||||
|
}
|
||||||
|
} break;
|
||||||
|
|
||||||
|
case RDS_GROUP_5A:
|
||||||
|
case RDS_GROUP_6A:
|
||||||
|
case RDS_GROUP_7A:
|
||||||
|
case RDS_GROUP_8A:
|
||||||
|
case RDS_GROUP_9A:
|
||||||
|
case RDS_GROUP_11A:
|
||||||
|
case RDS_GROUP_12A:
|
||||||
|
case RDS_GROUP_13A: {
|
||||||
|
// RT+ decoding
|
||||||
|
if ((!rdsBerrorThreshold && !rdsCerrorThreshold && !rdsDerrorThreshold) && rtplusblock == rdsblock && rds.hasRDSplus) { // Are we in the right RT+ block and is all ok to go?
|
||||||
|
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;
|
||||||
|
uint16_t length_marker_1 = (rds.rdsC >> 1) & 0x3F;
|
||||||
|
uint16_t start_marker_2 = (rds.rdsD >> 5) & 0x3F;
|
||||||
|
uint16_t length_marker_2 = (rds.rdsD & 0x1F);
|
||||||
|
togglebit = bitRead(lowByte(rds.rdsB), 4);
|
||||||
|
runningbit = bitRead(lowByte(rds.rdsB), 3);
|
||||||
|
|
||||||
|
switch (rds.rdsplusTag1) {
|
||||||
|
case 0: rds.rdsplusTag1 = 169; break;
|
||||||
|
case 1 ... 53: rds.rdsplusTag1 += 111; break;
|
||||||
|
case 59 ... 63: rds.rdsplusTag1 += 105; break;
|
||||||
|
default: rds.rdsplusTag1 = 169; break;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (rds.rdsplusTag2) {
|
||||||
|
case 0: rds.rdsplusTag2 = 169; break;
|
||||||
|
case 1 ... 53: rds.rdsplusTag2 += 111; break;
|
||||||
|
case 59 ... 63: rds.rdsplusTag2 += 105; break;
|
||||||
|
default: rds.rdsplusTag2 = 169; break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (togglebit) {
|
||||||
|
for (int i = 0; i < 45; i++) {
|
||||||
|
RDSplus1[i] = 0;
|
||||||
|
RDSplus2[i] = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rds.rtAB == rtABold) {
|
||||||
|
for (int i = 0; i <= length_marker_1; i++)RDSplus1[i] = rt_buffer2[i + start_marker_1];
|
||||||
|
RDSplus1[length_marker_1 + 1] = 0;
|
||||||
|
|
||||||
|
for (int i = 0; i <= length_marker_2; i++)RDSplus2[i] = rt_buffer2[i + start_marker_2];
|
||||||
|
RDSplus2[length_marker_2 + 1] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
wchar_t RTtext1[45] = L""; // Create 16 bit char buffer for Extended ASCII
|
||||||
|
RDScharConverter(RDSplus1, RTtext1, sizeof(RTtext1) / sizeof(wchar_t), false); // Convert 8 bit ASCII to 16 bit ASCII
|
||||||
|
rds.RTContent1 = convertToUTF8(RTtext1); // Convert RDS characterset to ASCII
|
||||||
|
rds.RTContent1 = extractUTF8Substring(rds.RTContent1, 0, 44, false); // Make sure RT does not exceed 32 characters
|
||||||
|
|
||||||
|
wchar_t RTtext2[45] = L""; // Create 16 bit char buffer for Extended ASCII
|
||||||
|
RDScharConverter(RDSplus2, RTtext2, sizeof(RTtext2) / sizeof(wchar_t), false); // Convert 8 bit ASCII to 16 bit ASCII
|
||||||
|
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
|
||||||
|
}
|
||||||
|
if (!rdsBerrorThreshold && rdsblock == 16 && (rds.rdsB & (1 << 4))) rds.hasTMC = true; // TMC flag
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case RDS_GROUP_14A: {
|
||||||
|
// EON
|
||||||
|
if (!rdsDerrorThreshold) {
|
||||||
|
rds.hasEON = true; // Group is there, so we have EON
|
||||||
|
|
||||||
|
bool isValuePresent = false;
|
||||||
|
for (int i = 0; i < 20; i++) {
|
||||||
|
if (eon[i].pi == rds.rdsD) { // Check if EON is already in array
|
||||||
|
isValuePresent = true;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isValuePresent) {
|
||||||
|
eon[eon_counter].picode[0] = (rds.rdsD >> 12) & 0xF;
|
||||||
|
eon[eon_counter].picode[1] = (rds.rdsD >> 8) & 0xF;
|
||||||
|
eon[eon_counter].picode[2] = (rds.rdsD >> 4) & 0xF;
|
||||||
|
eon[eon_counter].picode[3] = rds.rdsD & 0xF;
|
||||||
|
for (int i = 0; i < 4; i++) {
|
||||||
|
if (eon[eon_counter].picode[i] < 10) {
|
||||||
|
eon[eon_counter].picode[i] += '0'; // Add ASCII offset for decimal digits
|
||||||
|
} else {
|
||||||
|
eon[eon_counter].picode[i] += 'A' - 10; // Add ASCII offset for hexadecimal letters A-F
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
eon[eon_counter].pi = rds.rdsD; // Store PI on next array
|
||||||
|
if (eon_counter < 20) eon_counter++;
|
||||||
|
}
|
||||||
|
|
||||||
|
offset = rds.rdsB & 0x0F; // Read offset
|
||||||
|
|
||||||
|
if (offset < 9) {
|
||||||
|
byte position;
|
||||||
|
for (position = 0; position < 20; position++) {
|
||||||
|
if (eon[position].pi == rds.rdsD) { // Find position in array
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isValuePresent) {
|
|
||||||
eon[eon_counter].picode[0] = (rds.rdsD >> 12) & 0xF;
|
|
||||||
eon[eon_counter].picode[1] = (rds.rdsD >> 8) & 0xF;
|
|
||||||
eon[eon_counter].picode[2] = (rds.rdsD >> 4) & 0xF;
|
|
||||||
eon[eon_counter].picode[3] = rds.rdsD & 0xF;
|
|
||||||
for (int i = 0; i < 4; i++) {
|
|
||||||
if (eon[eon_counter].picode[i] < 10) {
|
|
||||||
eon[eon_counter].picode[i] += '0'; // Add ASCII offset for decimal digits
|
|
||||||
} else {
|
|
||||||
eon[eon_counter].picode[i] += 'A' - 10; // Add ASCII offset for hexadecimal letters A-F
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
eon[eon_counter].pi = rds.rdsD; // Store PI on next array
|
if (offset < 4 && eon[position].pi == rds.rdsD) {
|
||||||
if (eon_counter < 20) eon_counter++;
|
for (int j = 0; j < 9; j++) EONPStext[position][j] = '\0'; // Clear buffer
|
||||||
|
eon_buffer[position][(offset * 2) + 0] = rds.rdsC >> 8; // First character of segment
|
||||||
|
eon_buffer[position][(offset * 2) + 1] = rds.rdsC & 0xFF; // Second character of segment
|
||||||
|
eon_buffer[position][(offset * 2) + 2] = '\0'; // Endmarker of segment
|
||||||
}
|
}
|
||||||
|
|
||||||
offset = rds.rdsB & 0x0F; // Read offset
|
if (offset > 3 && eon[position].pi == rds.rdsD) { // Last chars are received
|
||||||
|
RDScharConverter(eon_buffer[position], EONPStext[position], sizeof(EONPStext[position]) / sizeof(wchar_t), true); // 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, true); // Make sure PS does not exceed 8 characters
|
||||||
|
for (int j = 0; j < 9; j++) eon_buffer[position][j] = '\0'; // Clear buffer
|
||||||
|
}
|
||||||
|
|
||||||
if (offset < 9) {
|
if (offset > 4 && eon[position].pi == rds.rdsD) {
|
||||||
byte position;
|
if (((rds.rdsC >> 8) * 10 + 8750) == currentfreq) { // Check if mapped frequency belongs to current frequency
|
||||||
for (position = 0; position < 20; position++) {
|
if (eon[position].mappedfreq == 0) {
|
||||||
if (eon[position].pi == rds.rdsD) { // Find position in array
|
eon[position].mappedfreq = ((rds.rdsC & 0xFF) * 10 + 8750); // Add mapped frequency to array
|
||||||
break;
|
} else {
|
||||||
}
|
if (eon[position].mappedfreq2 == 0 && eon[position].mappedfreq != (rds.rdsC & 0xFF) * 10 + 8750) {
|
||||||
}
|
eon[position].mappedfreq2 = ((rds.rdsC & 0xFF) * 10 + 8750);
|
||||||
|
} else if (eon[position].mappedfreq3 == 0 && eon[position].mappedfreq != (rds.rdsC & 0xFF) * 10 + 8750 && eon[position].mappedfreq2 != (rds.rdsC & 0xFF) * 10 + 8750) {
|
||||||
|
eon[position].mappedfreq3 = ((rds.rdsC & 0xFF) * 10 + 8750);
|
||||||
if (offset < 4 && eon[position].pi == rds.rdsD) {
|
|
||||||
for (int j = 0; j < 9; j++) EONPStext[position][j] = '\0'; // Clear buffer
|
|
||||||
eon_buffer[position][(offset * 2) + 0] = rds.rdsC >> 8; // First character of segment
|
|
||||||
eon_buffer[position][(offset * 2) + 1] = rds.rdsC & 0xFF; // Second character of segment
|
|
||||||
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), true); // 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, true); // Make sure PS does not exceed 8 characters
|
|
||||||
for (int j = 0; j < 9; j++) eon_buffer[position][j] = '\0'; // Clear buffer
|
|
||||||
}
|
|
||||||
|
|
||||||
if (offset > 4 && eon[position].pi == rds.rdsD) {
|
|
||||||
if (((rds.rdsC >> 8) * 10 + 8750) == currentfreq) { // Check if mapped frequency belongs to current frequency
|
|
||||||
if (eon[position].mappedfreq == 0) {
|
|
||||||
eon[position].mappedfreq = ((rds.rdsC & 0xFF) * 10 + 8750); // Add mapped frequency to array
|
|
||||||
} else {
|
|
||||||
if (eon[position].mappedfreq2 == 0 && eon[position].mappedfreq != (rds.rdsC & 0xFF) * 10 + 8750) {
|
|
||||||
eon[position].mappedfreq2 = ((rds.rdsC & 0xFF) * 10 + 8750);
|
|
||||||
} else if (eon[position].mappedfreq3 == 0 && eon[position].mappedfreq != (rds.rdsC & 0xFF) * 10 + 8750 && eon[position].mappedfreq2 != (rds.rdsC & 0xFF) * 10 + 8750) {
|
|
||||||
eon[position].mappedfreq3 = ((rds.rdsC & 0xFF) * 10 + 8750);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
}
|
||||||
}
|
break;
|
||||||
}
|
}
|
||||||
rdsBprevious = rds.rdsB;
|
|
||||||
rdsCprevious = rds.rdsC;
|
|
||||||
rdsDprevious = rds.rdsD;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -275,9 +275,6 @@ class TEF6686 {
|
|||||||
bool ABold;
|
bool ABold;
|
||||||
bool afreset;
|
bool afreset;
|
||||||
char stationTextBuffer[65];
|
char stationTextBuffer[65];
|
||||||
uint16_t rdsBprevious;
|
|
||||||
uint16_t rdsCprevious;
|
|
||||||
uint16_t rdsDprevious;
|
|
||||||
uint16_t piold;
|
uint16_t piold;
|
||||||
bool rtABold;
|
bool rtABold;
|
||||||
bool rtAB32old;
|
bool rtAB32old;
|
||||||
|
|||||||
Reference in New Issue
Block a user