You've already forked TEF6686_ESP32
not or it but ADD IT? THIS WAS NOT WRITTEN BY AI, THIS IS CLOWN PRODUCTION
This commit is contained in:
597
src/TEF6686.cpp
597
src/TEF6686.cpp
@@ -159,7 +159,7 @@ void TEF6686::init(byte TEF) {
|
||||
|
||||
void TEF6686::getIdentification(uint16_t *device, uint16_t *hw_version, uint16_t *sw_version) {
|
||||
uint8_t buf[6];
|
||||
uint16_t r = devTEF_Get_Cmd(TEF_APPL, Cmd_Get_Identification, buf, sizeof(buf));
|
||||
devTEF_Get_Cmd(TEF_APPL, Cmd_Get_Identification, buf, sizeof(buf));
|
||||
|
||||
*device = Convert8bto16b(buf);
|
||||
*hw_version = Convert8bto16b(buf + 2);
|
||||
@@ -363,10 +363,8 @@ void TEF6686::getStatusAM(int16_t &level, uint16_t &noise, uint16_t &cochannel,
|
||||
}
|
||||
|
||||
void TEF6686::readRDS(byte showrdserrors) {
|
||||
uint8_t offset;
|
||||
if (rds.filter && ps_process) {
|
||||
devTEF_Radio_Get_RDS_Status(&rds.rdsStat, &rds.rdsA, &rds.rdsB, &rds.rdsC, &rds.rdsD, &rds.rdsErr);
|
||||
} else {
|
||||
if (rds.filter && ps_process) devTEF_Radio_Get_RDS_Status(&rds.rdsStat, &rds.rdsA, &rds.rdsB, &rds.rdsC, &rds.rdsD, &rds.rdsErr);
|
||||
else {
|
||||
if (millis() >= rdstimer + 87) {
|
||||
rdstimer += 87;
|
||||
devTEF_Radio_Get_RDS_Data(&rds.rdsStat, &rds.rdsA, &rds.rdsB, &rds.rdsC, &rds.rdsD, &rds.rdsErr);
|
||||
@@ -378,14 +376,11 @@ void TEF6686::readRDS(byte showrdserrors) {
|
||||
}
|
||||
|
||||
if (bitRead(rds.rdsStat, 9)) {
|
||||
rds.hasRDS = true; // RDS decoder synchronized and data available
|
||||
rds.hasRDS = true;
|
||||
bitStartTime = 0;
|
||||
} else {
|
||||
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;
|
||||
}
|
||||
|
||||
rdsAerrorThreshold = (((rds.rdsErr >> 14) & 0x03) > showrdserrors);
|
||||
@@ -394,12 +389,11 @@ void TEF6686::readRDS(byte showrdserrors) {
|
||||
rdsDerrorThreshold = (((rds.rdsErr >> 8) & 0x03) > showrdserrors);
|
||||
|
||||
if (bitRead(rds.rdsStat, 9) && (rds.rdsA != previous_rdsA || rds.rdsB != previous_rdsB || rds.rdsC != previous_rdsC || rds.rdsD != previous_rdsD)) {
|
||||
rds.rdsAerror = (((rds.rdsErr >> 14) & 0x03) > 1); // We have all data to decode... let's go...
|
||||
rds.rdsAerror = (((rds.rdsErr >> 14) & 0x03) > 1);
|
||||
rds.rdsBerror = (((rds.rdsErr >> 12) & 0x03) > 1);
|
||||
rds.rdsCerror = (((rds.rdsErr >> 10) & 0x03) > 1);
|
||||
rds.rdsDerror = (((rds.rdsErr >> 8) & 0x03) > 1);
|
||||
|
||||
//PI decoder
|
||||
if (!rdsAerrorThreshold && afreset) {
|
||||
rds.correctPI = rds.rdsA;
|
||||
afreset = false;
|
||||
@@ -413,11 +407,8 @@ void TEF6686::readRDS(byte showrdserrors) {
|
||||
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';
|
||||
} else {
|
||||
rds.picode[i] += 'A' - 10;
|
||||
}
|
||||
if (rds.picode[i] < 10) rds.picode[i] += '0';
|
||||
else rds.picode[i] += 'A' - 10;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -438,7 +429,6 @@ void TEF6686::readRDS(byte showrdserrors) {
|
||||
|
||||
if (strncmp(rds.picode, "0000", 4) == 0 && rds.rdsB == 0 && rds.stationName.length() == 0) memset(rds.picode, 0, sizeof(rds.picode));
|
||||
|
||||
|
||||
// USA Station callsign decoder
|
||||
if ((rds.region == 1 ? ps_process : true) && rds.correctPI != 0 && rds.region > 0 && correctPIold != rds.correctPI) {
|
||||
bool foundMatch = false;
|
||||
@@ -446,27 +436,16 @@ void TEF6686::readRDS(byte showrdserrors) {
|
||||
|
||||
if (rds.region == 1 && SPIFFS.begin(true)) {
|
||||
delay(5);
|
||||
if (currentfreq2 < 9000) {
|
||||
file = SPIFFS.open("/USA_87-90.csv");
|
||||
} else if (currentfreq2 > 9000 && currentfreq2 < 9200) {
|
||||
file = SPIFFS.open("/USA_90-92.csv");
|
||||
} else if (currentfreq2 > 9200 && currentfreq2 < 9400) {
|
||||
file = SPIFFS.open("/USA_92-94.csv");
|
||||
} else if (currentfreq2 > 9400 && currentfreq2 < 9600) {
|
||||
file = SPIFFS.open("/USA_94-96.csv");
|
||||
} else if (currentfreq2 > 9600 && currentfreq2 < 9800) {
|
||||
file = SPIFFS.open("/USA_96-98.csv");
|
||||
} else if (currentfreq2 > 9800 && currentfreq2 < 10000) {
|
||||
file = SPIFFS.open("/USA_98-100.csv");
|
||||
} else if (currentfreq2 > 10000 && currentfreq2 < 10200) {
|
||||
file = SPIFFS.open("/USA_100-102.csv");
|
||||
} else if (currentfreq2 > 10200 && currentfreq2 < 10400) {
|
||||
file = SPIFFS.open("/USA_102-104.csv");
|
||||
} else if (currentfreq2 > 10400 && currentfreq2 < 10600) {
|
||||
file = SPIFFS.open("/USA_104-106.csv");
|
||||
} else if (currentfreq2 > 10600) {
|
||||
file = SPIFFS.open("/USA_106-108.csv");
|
||||
}
|
||||
if (currentfreq2 < 9000) file = SPIFFS.open("/USA_87-90.csv");
|
||||
else if (currentfreq2 > 9000 && currentfreq2 < 9200) file = SPIFFS.open("/USA_90-92.csv");
|
||||
else if (currentfreq2 > 9200 && currentfreq2 < 9400) file = SPIFFS.open("/USA_92-94.csv");
|
||||
else if (currentfreq2 > 9400 && currentfreq2 < 9600) file = SPIFFS.open("/USA_94-96.csv");
|
||||
else if (currentfreq2 > 9600 && currentfreq2 < 9800) file = SPIFFS.open("/USA_96-98.csv");
|
||||
else if (currentfreq2 > 9800 && currentfreq2 < 10000) file = SPIFFS.open("/USA_98-100.csv");
|
||||
else if (currentfreq2 > 10000 && currentfreq2 < 10200) file = SPIFFS.open("/USA_100-102.csv");
|
||||
else if (currentfreq2 > 10200 && currentfreq2 < 10400) file = SPIFFS.open("/USA_102-104.csv");
|
||||
else if (currentfreq2 > 10400 && currentfreq2 < 10600) file = SPIFFS.open("/USA_104-106.csv");
|
||||
else if (currentfreq2 > 10600) file = SPIFFS.open("/USA_106-108.csv");
|
||||
|
||||
delay(5);
|
||||
if (file) {
|
||||
@@ -562,43 +541,48 @@ void TEF6686::readRDS(byte showrdserrors) {
|
||||
}
|
||||
}
|
||||
|
||||
if (!rds.rdsBerror || showrdserrors == 3) rdsblock = rds.rdsB >> 11; else return;
|
||||
rds.blockcounter[rdsblock]++;
|
||||
if(rdsBerrorThreshold) goto end;
|
||||
|
||||
rds.TP = (bitRead(rds.rdsB, 10));
|
||||
rds.PTY = (rds.rdsB >> 5) & 0x1F;
|
||||
strcpy(rds.stationType, rds.region == 0 ? PTY_EU[rds.PTY] : PTY_USA[rds.PTY]);
|
||||
|
||||
if (!rds.rdsBerror || showrdserrors == 3) rdsgroup = rds.rdsB >> 11; else return;
|
||||
rds.blockcounter[rdsgroup]++;
|
||||
processed_rdsblocks++;
|
||||
|
||||
switch (rdsblock) {
|
||||
switch (rdsgroup) {
|
||||
case RDS_GROUP_0A:
|
||||
case RDS_GROUP_0B:
|
||||
{
|
||||
//PS decoder
|
||||
if (showrdserrors == 3 || (!rdsBerrorThreshold && (!rdsDerrorThreshold))) {
|
||||
offset = rds.rdsB & 0x03; // Let's get the character offset for PS
|
||||
if (showrdserrors == 3 || !rdsDerrorThreshold) {
|
||||
uint8_t segment = rds.rdsB & 0x03;
|
||||
|
||||
switch (offset) {
|
||||
switch (segment) {
|
||||
case 0: if (((rds.rdsErr >> 8) & 0x03) > 1) rds.ps12error = true; else rds.ps12error = false; break;
|
||||
case 1: if (((rds.rdsErr >> 8) & 0x03) > 1) rds.ps34error = true; else rds.ps34error = false; break;
|
||||
case 2: if (((rds.rdsErr >> 8) & 0x03) > 1) rds.ps56error = true; else rds.ps56error = false; break;
|
||||
case 3: if (((rds.rdsErr >> 8) & 0x03) > 1) rds.ps78error = true; else rds.ps78error = false; break;
|
||||
}
|
||||
|
||||
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[(segment * 2) + 0] = ps_buffer[(segment * 2) + 0]; // Make a copy of the PS buffer
|
||||
ps_buffer2[(segment * 2) + 1] = ps_buffer[(segment * 2) + 1];
|
||||
ps_buffer2[8] = '\0'; // Endmarker
|
||||
|
||||
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[(segment * 2) + 0] = rds.rdsD >> 8; // First character of segment
|
||||
ps_buffer[(segment * 2) + 1] = rds.rdsD & 0xFF; // Second character of segment
|
||||
ps_buffer[8] = '\0'; // Endmarker
|
||||
|
||||
if (ps_process || rds.fastps == 0) {
|
||||
if (offset == 0) {
|
||||
if (segment == 0) {
|
||||
packet0 = true;
|
||||
packet1 = false;
|
||||
packet2 = false;
|
||||
packet3 = false;
|
||||
}
|
||||
if (offset == 1) packet1 = true;
|
||||
if (offset == 2) packet2 = true;
|
||||
if (offset == 3) packet3 = true;
|
||||
if (segment == 1) packet1 = true;
|
||||
if (segment == 2) packet2 = true;
|
||||
if (segment == 3) packet3 = true;
|
||||
}
|
||||
|
||||
if (packet0 && packet1 && packet2 && packet3 && (ps_process || (rds.fastps == 0 && rds.fastps != 2))) { // Last chars are received
|
||||
@@ -615,198 +599,186 @@ void TEF6686::readRDS(byte showrdserrors) {
|
||||
}
|
||||
|
||||
if ((!ps_process && rds.fastps > 0 && rds.fastps != 2) || rds.fastps == 2) { // Let's get 2 runs of 8 PS characters fast and without refresh
|
||||
if (offset == 0) packet0 = true;
|
||||
if (offset == 1) packet1 = true;
|
||||
if (offset == 2) packet2 = true;
|
||||
if (offset == 3) packet3 = true;
|
||||
if (segment == 0) packet0 = true;
|
||||
if (segment == 1) packet1 = true;
|
||||
if (segment == 2) packet2 = true;
|
||||
if (segment == 3) packet3 = true;
|
||||
RDScharConverter(ps_buffer, PStext, sizeof(PStext) / sizeof(wchar_t), (underscore > 0 ? true : false)); // Convert 8 bit ASCII to 16 bit ASCII
|
||||
String utf8String = convertToUTF8(PStext); // Convert RDS characterset to ASCII
|
||||
rds.stationName = extractUTF8Substring(utf8String, 0, 8, (underscore > 0 ? true : false));
|
||||
if (packet0 && packet1 && packet2 && packet3) ps_process = true; // OK, we had one 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
|
||||
if(segment == 0) rds.hasDynamicPTY = bitRead(rds.rdsB, 2) & 0x1F;
|
||||
else if(segment == 1) rds.hasCompressed = bitRead(rds.rdsB, 2) & 0x1F;
|
||||
else if(segment == 2) rds.hasArtificialhead = bitRead(rds.rdsB, 2) & 0x1F;
|
||||
else if(segment == 3) rds.hasStereo = bitRead(rds.rdsB, 2) & 0x1F;
|
||||
}
|
||||
|
||||
if (!rdsBerrorThreshold) {
|
||||
rds.stationTypeCode = (rds.rdsB >> 5) & 0x1F; // Get 5 PTY bits from Block B
|
||||
if (rds.region == 0) strcpy(rds.stationType, PTY_EU[rds.stationTypeCode]); else strcpy(rds.stationType, PTY_USA[rds.stationTypeCode]);
|
||||
rds.hasTA = (bitRead(rds.rdsB, 4));
|
||||
|
||||
rds.hasTA = (bitRead(rds.rdsB, 4)); // Read TA flag
|
||||
}
|
||||
|
||||
rds.hasTP = (bitRead(rds.rdsB, 10)); // Read TP flag
|
||||
|
||||
if (!rdsCerrorThreshold) {
|
||||
if (!rdsCerrorThreshold && rdsgroup == RDS_GROUP_0A && rds.rdsC != rdsCold) {
|
||||
//AF decoder
|
||||
if (rdsblock == 0 && rds.rdsC != rdsCold) { // Only when in GROUP 0A
|
||||
|
||||
if ((rds.rdsC >> 8) > 224 && (rds.rdsC >> 8) < 250) {
|
||||
afinit = true; // AF detected
|
||||
rds.hasAF = true;
|
||||
}
|
||||
|
||||
if (afinit) {
|
||||
if ((rds.rdsC >> 8) > 224 && (rds.rdsC >> 8) < 250 && ((rds.rdsC & 0xFF) * 10 + 8750) == currentfreq && rds.hasAF) {
|
||||
if (afmethodBtrigger) afmethodB = true; // Check for AF method B
|
||||
afmethodBprobe = true;
|
||||
af_counterb = (rds.rdsC >> 8) - 224;
|
||||
af_number = (rds.rdsC >> 8) - 224;
|
||||
af_counterbcheck = 1;
|
||||
doublecounter = 0;
|
||||
doubletestfreq = (rds.rdsC & 0xFF) * 10 + 8750;
|
||||
} else if ((rds.rdsC >> 8) > 224 && (rds.rdsC >> 8) < 250 && ((rds.rdsC & 0xFF) * 10 + 8750) != currentfreq && rds.hasAF) {
|
||||
afmethodBprobe = false;
|
||||
afmethodBtrigger = true;
|
||||
af_counterb = 0;
|
||||
af_number = (rds.rdsC >> 8) - 224;
|
||||
af_counterbcheck = 0;
|
||||
doublecounter = 0;
|
||||
doubletestfreq = (rds.rdsC & 0xFF) * 10 + 8750;
|
||||
}
|
||||
|
||||
if (((rds.rdsC >> 8) > 0 && (rds.rdsC >> 8) < 205) && ((rds.rdsC >> 8) > 0 && (rds.rdsC >> 8) < 205)) {
|
||||
if (afmethodBprobe) af_counterbcheck += 2;
|
||||
}
|
||||
|
||||
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 (((rds.rdsC >> 8) > 0 && (rds.rdsC >> 8) < 205) && (buffer0 == doubletestfreq || buffer1 == doubletestfreq)) doublecounter++;
|
||||
if (doublecounter > (af_number / 2)) afmethodB = true; // If signed frequency also appears more than once in the AF list, AF Method B detected
|
||||
|
||||
if (afmethodBprobe && af_counterbcheck > af_counterb) afmethodBprobe = false; // If more than counter received disable probe flag
|
||||
|
||||
if (afmethodBprobe) { // Check for Reg. flags
|
||||
if (buffer1 == currentfreq && buffer0 > buffer1) {
|
||||
for (int x = 0; x < af_counter; x++) {
|
||||
if (af[x].frequency == buffer0 && !af[x].regional) {
|
||||
af[x].regional = true;
|
||||
af_updatecounter++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (buffer1 == currentfreq && buffer0 < buffer1) {
|
||||
for (int x = 0; x < af_counter; x++) {
|
||||
if (af[x].frequency == buffer0 && !af[x].same) {
|
||||
af[x].same = true;
|
||||
af_updatecounter++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (buffer0 == currentfreq && buffer0 > buffer1) {
|
||||
for (int x = 0; x < af_counter; x++) {
|
||||
if (af[x].frequency == buffer1 && !af[x].regional) {
|
||||
af[x].regional = true;
|
||||
af_updatecounter++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (buffer0 == currentfreq && buffer0 < buffer1) {
|
||||
for (int x = 0; x < af_counter; x++) {
|
||||
if (af[x].frequency == buffer1 && !af[x].same) {
|
||||
af[x].same = true;
|
||||
af_updatecounter++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (buffer0 != currentfreq && buffer1 != currentfreq && afmethodB && afmethodBprobe) {
|
||||
afmethodBprobe = false; // Remove faulty Reg. flags
|
||||
for (int x = 0; x < af_counter; x++) {
|
||||
if (af[x].frequency == buffer0 || af[x].frequency == buffer1) {
|
||||
if (af[x].same) {
|
||||
af[x].same = false;
|
||||
af_updatecounter++;
|
||||
}
|
||||
if (af[x].regional) {
|
||||
af[x].regional = false;
|
||||
af_updatecounter++;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool isValuePresent = false;
|
||||
for (int i = 0; i < 50; i++) { // Check if already in list
|
||||
if ((rds.sortaf && (buffer0 == currentfreq)) || buffer0 == 0 || af[i].frequency == buffer0) {
|
||||
isValuePresent = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!isValuePresent) { // Add frequency to list
|
||||
af[af_counter].frequency = buffer0;
|
||||
if (af_counter < 50) af_counter++;
|
||||
af_updatecounter++;
|
||||
}
|
||||
|
||||
isValuePresent = false;
|
||||
for (int i = 0; i < 50; i++) { // Check if already in list
|
||||
if ((rds.sortaf && (buffer1 == currentfreq)) || buffer1 == 0 || af[i].frequency == buffer1) {
|
||||
isValuePresent = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!isValuePresent) {
|
||||
af[af_counter].frequency = buffer1; // Add frequency to list
|
||||
if (af_counter < 50) af_counter++;
|
||||
af_updatecounter++;
|
||||
}
|
||||
|
||||
if (rds.sortaf) { // Sort AF list (low to high)
|
||||
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;
|
||||
bool temp6 = af[j].same;
|
||||
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].same = af[j + 1].same;
|
||||
af[j + 1].frequency = temp;
|
||||
af[j + 1].afvalid = temp3;
|
||||
af[j + 1].checked = temp4;
|
||||
af[j + 1].regional = temp5;
|
||||
af[j + 1].same = temp6;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
rdsCold = rds.rdsC;
|
||||
if ((rds.rdsC >> 8) > 224 && (rds.rdsC >> 8) < 250) {
|
||||
afinit = true; // AF detected
|
||||
rds.hasAF = true;
|
||||
}
|
||||
|
||||
if (afinit) {
|
||||
if ((rds.rdsC >> 8) > 224 && (rds.rdsC >> 8) < 250 && ((rds.rdsC & 0xFF) * 10 + 8750) == currentfreq && rds.hasAF) {
|
||||
if (afmethodBtrigger) afmethodB = true;
|
||||
afmethodBprobe = true;
|
||||
af_counterb = (rds.rdsC >> 8) - 224;
|
||||
af_number = (rds.rdsC >> 8) - 224;
|
||||
af_counterbcheck = 1;
|
||||
doublecounter = 0;
|
||||
doubletestfreq = (rds.rdsC & 0xFF) * 10 + 8750;
|
||||
} else if ((rds.rdsC >> 8) > 224 && (rds.rdsC >> 8) < 250 && ((rds.rdsC & 0xFF) * 10 + 8750) != currentfreq && rds.hasAF) {
|
||||
afmethodBprobe = false;
|
||||
afmethodBtrigger = true;
|
||||
af_counterb = 0;
|
||||
af_number = (rds.rdsC >> 8) - 224;
|
||||
af_counterbcheck = 0;
|
||||
doublecounter = 0;
|
||||
doubletestfreq = (rds.rdsC & 0xFF) * 10 + 8750;
|
||||
}
|
||||
|
||||
if (((rds.rdsC >> 8) > 0 && (rds.rdsC >> 8) < 205) && ((rds.rdsC >> 8) > 0 && (rds.rdsC >> 8) < 205)) {
|
||||
if (afmethodBprobe) af_counterbcheck += 2;
|
||||
}
|
||||
|
||||
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 (((rds.rdsC >> 8) > 0 && (rds.rdsC >> 8) < 205) && (buffer0 == doubletestfreq || buffer1 == doubletestfreq)) doublecounter++;
|
||||
if (doublecounter > (af_number / 2)) afmethodB = true; // If signed frequency also appears more than once in the AF list, AF Method B detected
|
||||
|
||||
if (afmethodBprobe && af_counterbcheck > af_counterb) afmethodBprobe = false; // If more than counter received disable probe flag
|
||||
|
||||
if (afmethodBprobe) { // Check for Reg. flags
|
||||
if (buffer1 == currentfreq && buffer0 > buffer1) {
|
||||
for (int x = 0; x < af_counter; x++) {
|
||||
if (af[x].frequency == buffer0 && !af[x].regional) {
|
||||
af[x].regional = true;
|
||||
af_updatecounter++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (buffer1 == currentfreq && buffer0 < buffer1) {
|
||||
for (int x = 0; x < af_counter; x++) {
|
||||
if (af[x].frequency == buffer0 && !af[x].same) {
|
||||
af[x].same = true;
|
||||
af_updatecounter++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (buffer0 == currentfreq && buffer0 > buffer1) {
|
||||
for (int x = 0; x < af_counter; x++) {
|
||||
if (af[x].frequency == buffer1 && !af[x].regional) {
|
||||
af[x].regional = true;
|
||||
af_updatecounter++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (buffer0 == currentfreq && buffer0 < buffer1) {
|
||||
for (int x = 0; x < af_counter; x++) {
|
||||
if (af[x].frequency == buffer1 && !af[x].same) {
|
||||
af[x].same = true;
|
||||
af_updatecounter++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (buffer0 != currentfreq && buffer1 != currentfreq && afmethodB && afmethodBprobe) {
|
||||
afmethodBprobe = false; // Remove faulty Reg. flags
|
||||
for (int x = 0; x < af_counter; x++) {
|
||||
if (af[x].frequency == buffer0 || af[x].frequency == buffer1) {
|
||||
if (af[x].same) {
|
||||
af[x].same = false;
|
||||
af_updatecounter++;
|
||||
}
|
||||
if (af[x].regional) {
|
||||
af[x].regional = false;
|
||||
af_updatecounter++;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool isValuePresent = false;
|
||||
for (int i = 0; i < 50; i++) { // Check if already in list
|
||||
if ((rds.sortaf && (buffer0 == currentfreq)) || buffer0 == 0 || af[i].frequency == buffer0) {
|
||||
isValuePresent = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!isValuePresent) { // Add frequency to list
|
||||
af[af_counter].frequency = buffer0;
|
||||
if (af_counter < 50) af_counter++;
|
||||
af_updatecounter++;
|
||||
}
|
||||
|
||||
isValuePresent = false;
|
||||
for (int i = 0; i < 50; i++) { // Check if already in list
|
||||
if ((rds.sortaf && (buffer1 == currentfreq)) || buffer1 == 0 || af[i].frequency == buffer1) {
|
||||
isValuePresent = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!isValuePresent) {
|
||||
af[af_counter].frequency = buffer1; // Add frequency to list
|
||||
if (af_counter < 50) af_counter++;
|
||||
af_updatecounter++;
|
||||
}
|
||||
|
||||
if (rds.sortaf) { // Sort AF list (low to high)
|
||||
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;
|
||||
bool temp6 = af[j].same;
|
||||
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].same = af[j + 1].same;
|
||||
af[j + 1].frequency = temp;
|
||||
af[j + 1].afvalid = temp3;
|
||||
af[j + 1].checked = temp4;
|
||||
af[j + 1].regional = temp5;
|
||||
af[j + 1].same = temp6;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
rdsCold = rds.rdsC;
|
||||
}
|
||||
} break;
|
||||
} break;
|
||||
|
||||
case RDS_GROUP_1A:
|
||||
case RDS_GROUP_1B: {
|
||||
if (!rdsCerrorThreshold) {
|
||||
if (((rds.rdsC >> 12) & 0x07) == 0 && rdsblock == RDS_GROUP_1A) { // ECC code readout
|
||||
rds.ECC = rds.rdsC & 0xff;
|
||||
rds.hasECC = true;
|
||||
case RDS_GROUP_1A: {
|
||||
if (!rdsCerrorThreshold && ((rds.rdsC >> 12) & 0x07) == 0) {
|
||||
rds.ECC = rds.rdsC & 0xff;
|
||||
rds.hasECC = true;
|
||||
|
||||
switch (rds.picode[0]) {
|
||||
switch (rds.picode[0]) {
|
||||
case '1': {
|
||||
if (rds.ECC == 160) rds.ECCtext = ECCtext[226];
|
||||
if (rds.ECC == 162) rds.ECCtext = ECCtext[129];
|
||||
@@ -1114,17 +1086,13 @@ void TEF6686::readRDS(byte showrdserrors) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (rds.rdsC >> 12 == 1 && rdsblock == RDS_GROUP_1A) rds.hasTMC = true; // TMC flag
|
||||
} break;
|
||||
} break;
|
||||
|
||||
case RDS_GROUP_2A: {
|
||||
if (showrdserrors == 3 || (!rdsBerrorThreshold && !rdsCerrorThreshold && !rdsDerrorThreshold)) {
|
||||
// RT decoder (64 characters)
|
||||
if (showrdserrors == 3 || !(rdsCerrorThreshold && rdsDerrorThreshold)) {
|
||||
rds.hasRT = true;
|
||||
rds.rtAB = (bitRead(rds.rdsB, 4)); // Get AB flag
|
||||
rds.rtAB = (bitRead(rds.rdsB, 4));
|
||||
|
||||
if (initab) {
|
||||
rtABold = rds.rtAB;
|
||||
@@ -1139,19 +1107,16 @@ void TEF6686::readRDS(byte showrdserrors) {
|
||||
}
|
||||
}
|
||||
|
||||
if (rds.rtAB != rtABold) { // Erase old RT, because of AB change
|
||||
if (rds.rtAB != rtABold) {
|
||||
initrt = false;
|
||||
if (rds.rtbuffer) {
|
||||
char rt_buffer_temp[129];
|
||||
bool found = false;
|
||||
strcpy(rt_buffer_temp, rt_buffer);
|
||||
|
||||
for (int i = 0; i < 129; i++) {
|
||||
if (rt_buffer_temp[i] == 0x0D) {
|
||||
found = true;
|
||||
}
|
||||
if (found) {
|
||||
if (rt_buffer_temp[i] == '\r') {
|
||||
rt_buffer_temp[i] = '\0';
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1162,31 +1127,25 @@ void TEF6686::readRDS(byte showrdserrors) {
|
||||
rds.stationText = trimTrailingSpaces(rds.stationText); // Trim empty spaces at the end
|
||||
}
|
||||
|
||||
for (byte i = 0; i < 64; i++) {
|
||||
rt_buffer[i] = 0x20;
|
||||
}
|
||||
for (byte i = 0; i < 64; i++) rt_buffer[i] = 0x20;
|
||||
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
|
||||
|
||||
uint8_t segment = (rds.rdsB & 0xf) * 4;
|
||||
rt_buffer[segment + 0] = rds.rdsC >> 8;
|
||||
rt_buffer[segment + 1] = rds.rdsC & 0xff;
|
||||
rt_buffer[segment + 2] = rds.rdsD >> 8;
|
||||
rt_buffer[segment + 3] = rds.rdsD & 0xff;
|
||||
|
||||
if (initrt || !rds.rtbuffer) {
|
||||
char rt_buffer_temp[129];
|
||||
bool found = false;
|
||||
strcpy(rt_buffer_temp, rt_buffer);
|
||||
|
||||
for (int i = 0; i < 129; i++) {
|
||||
if (rt_buffer_temp[i] == 0x0D) {
|
||||
found = true;
|
||||
}
|
||||
if (found) {
|
||||
if (rt_buffer_temp[i] == '\r') {
|
||||
rt_buffer_temp[i] = '\0';
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1199,7 +1158,7 @@ void TEF6686::readRDS(byte showrdserrors) {
|
||||
|
||||
for (int i = 0; i < 64; i++) rt_buffer2[i] = rt_buffer[i];
|
||||
}
|
||||
} break;
|
||||
} break;
|
||||
|
||||
case RDS_GROUP_2B: {
|
||||
if (showrdserrors == 3 || (!rdsBerrorThreshold && !rdsDerrorThreshold)) {
|
||||
@@ -1215,9 +1174,9 @@ void TEF6686::readRDS(byte showrdserrors) {
|
||||
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
|
||||
uint16_t segment = (rds.rdsB & 0xf) * 2; // Get RT character segment
|
||||
rt_buffer32[segment + 0] = rds.rdsD >> 8; // First character of segment
|
||||
rt_buffer32[segment + 1] = rds.rdsD & 0xff; // Second character of segment
|
||||
|
||||
byte endmarkerRT32 = 32;
|
||||
for (byte i = 0; i < endmarkerRT32; i++) {
|
||||
@@ -1229,15 +1188,12 @@ void TEF6686::readRDS(byte showrdserrors) {
|
||||
|
||||
|
||||
char rt_buffer_temp[129];
|
||||
bool found = false;
|
||||
strcpy(rt_buffer_temp, rt_buffer32);
|
||||
|
||||
for (int i = 0; i < 129; i++) {
|
||||
if (rt_buffer_temp[i] == 0x0D) {
|
||||
found = true;
|
||||
}
|
||||
if (found) {
|
||||
if (rt_buffer_temp[i] == '\r') {
|
||||
rt_buffer_temp[i] = '\0';
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1266,25 +1222,22 @@ void TEF6686::readRDS(byte showrdserrors) {
|
||||
rds.aid_counter++;
|
||||
}
|
||||
|
||||
if (rds.rdsD == 0xCD46) { // Check for TMC application
|
||||
rds.hasTMC = true; // TMC flag
|
||||
if (rds.rdsD == 0xCD46) rds.hasTMC = true;
|
||||
|
||||
if (rds.rdsD == 0x4BD7) {
|
||||
rds.hasRTplus = true;
|
||||
rtplusblock = ((rds.rdsB & 0x1F) >> 1) * 2;
|
||||
}
|
||||
|
||||
// RT+ init
|
||||
if (rds.rdsD == 0x4BD7) { // Check for RT+ application
|
||||
rds.hasRDSplus = true; // Set flag
|
||||
rtplusblock = ((rds.rdsB & 0x1F) >> 1) * 2; // Get RT+ Block
|
||||
if (rds.rdsD == 0x0093) {
|
||||
rds.hasDABAF = true;
|
||||
DABAFblock = ((rds.rdsB & 0x1F) >> 1) * 2;
|
||||
}
|
||||
|
||||
if (rds.rdsD == 0x0093) { // Check for DAB+ AF application
|
||||
rds.hasDABAF = true; // Set flag
|
||||
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
|
||||
if (rds.rdsD == 0x6552) {
|
||||
_hasEnhancedRT = true;
|
||||
eRTblock = ((rds.rdsB & 0x1F) >> 1) * 2;
|
||||
eRTcoding = bitRead(rds.rdsC, 0);
|
||||
}
|
||||
}
|
||||
} break;
|
||||
@@ -1292,11 +1245,8 @@ void TEF6686::readRDS(byte showrdserrors) {
|
||||
case RDS_GROUP_4A: {
|
||||
if (!rdsBerrorThreshold && !rdsCerrorThreshold && !rdsDerrorThreshold && rds.ctupdate && (rds.PICTlock == rds.rdsA || rds.PICTlock == 0)) {
|
||||
// CT
|
||||
uint32_t mjd;
|
||||
mjd = (rds.rdsB & 0x03);
|
||||
mjd <<= 15;
|
||||
mjd += ((rds.rdsC >> 1) & 0x7FFF);
|
||||
uint16_t hour, minute, day = 1, month = 1, year = 2020; // Set default values for day, month, and year
|
||||
uint32_t mjd = (rds.rdsB & 0x03) << 15 | ((rds.rdsC >> 1) & 0x7FFF);;
|
||||
uint16_t hour, minute, day = 5, month = 1, year = 2026;
|
||||
int32_t timeoffset;
|
||||
|
||||
long J, C, Y, M;
|
||||
@@ -1313,14 +1263,13 @@ void TEF6686::readRDS(byte showrdserrors) {
|
||||
if ((M + 2 - (12 * J)) < 13) month = M + 2 - (12 * J);
|
||||
if ((100 * (C - 49) + Y + J) > 2022) year = 100 * (C - 49) + Y + J;
|
||||
|
||||
hour = ((rds.rdsD >> 12) & 0x000f);
|
||||
hour += ((rds.rdsC << 4) & 0x0010);
|
||||
hour = ((rds.rdsD >> 12) & 0xf) | ((rds.rdsC << 4) & 0x10);
|
||||
timeoffset = rds.rdsD & 0x001f;
|
||||
if (bitRead(rds.rdsD, 5)) timeoffset *= -1;
|
||||
timeoffset *= 1800;
|
||||
minute = (rds.rdsD & 0x0fc0) >> 6;
|
||||
|
||||
if (year < 2024 || hour > 23 || minute > 59 || timeoffset > 55800 || timeoffset < -55800) break;
|
||||
if (year < 2026 || hour > 23 || minute > 59 || timeoffset > 55800 || timeoffset < -55800) break;
|
||||
|
||||
struct tm tm;
|
||||
tm.tm_year = year - 1900;
|
||||
@@ -1340,9 +1289,7 @@ void TEF6686::readRDS(byte showrdserrors) {
|
||||
rds.hasCT = true;
|
||||
rds.time = rdstime;
|
||||
rds.offset = timeoffset;
|
||||
} else {
|
||||
rds.hasCT = false;
|
||||
}
|
||||
} else rds.hasCT = false;
|
||||
lastrdstime = rdstime;
|
||||
lasttimeoffset = timeoffset;
|
||||
}
|
||||
@@ -1351,16 +1298,16 @@ void TEF6686::readRDS(byte showrdserrors) {
|
||||
case RDS_GROUP_10A: {
|
||||
if (!rdsCerrorThreshold && !rdsDerrorThreshold) {
|
||||
// PTYN
|
||||
offset = bitRead(rds.rdsB, 0); // Get char offset
|
||||
uint8_t segment = bitRead(rds.rdsB, 0);
|
||||
if (rds.rdsC != 0 && rds.rdsD != 0) {
|
||||
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
|
||||
ptyn_buffer[(segment * 4) + 0] = rds.rdsC >> 8;
|
||||
ptyn_buffer[(segment * 4) + 1] = rds.rdsC & 0xFF;
|
||||
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] = L'\0';
|
||||
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
|
||||
RDScharConverter(ptyn_buffer, PTYNtext, sizeof(PTYNtext) / sizeof(wchar_t), false);
|
||||
String utf8String = convertToUTF8(PTYNtext);
|
||||
rds.PTYN = extractUTF8Substring(utf8String, 0, 8, false);
|
||||
rds.hasPTYN = true;
|
||||
}
|
||||
}
|
||||
@@ -1373,9 +1320,9 @@ void TEF6686::readRDS(byte showrdserrors) {
|
||||
case RDS_GROUP_9A:
|
||||
case RDS_GROUP_11A:
|
||||
case RDS_GROUP_12A:
|
||||
case RDS_GROUP_13A: {
|
||||
case RDS_GROUP_13A: {
|
||||
// RT+ decoding
|
||||
if ((!rdsBerrorThreshold && !rdsCerrorThreshold && !rdsDerrorThreshold) && rtplusblock == rdsblock && rds.hasRDSplus) {
|
||||
if ((!rdsBerrorThreshold && !rdsCerrorThreshold && !rdsDerrorThreshold) && rtplusblock == rdsgroup && rds.hasRTplus) {
|
||||
rds.rdsplusTag1 = ((rds.rdsB & 0x07) << 3) + (rds.rdsC >> 13); // Are we in the right RT+ block and is all ok to go?
|
||||
rds.rdsplusTag2 = ((rds.rdsC & 0x01) << 5) + (rds.rdsD >> 11);
|
||||
uint16_t start_marker_1 = (rds.rdsC >> 7) & 0x3F;
|
||||
@@ -1428,8 +1375,8 @@ void TEF6686::readRDS(byte showrdserrors) {
|
||||
}
|
||||
|
||||
// eRT decoding
|
||||
if ((!rdsBerrorThreshold && !rdsCerrorThreshold && !rdsDerrorThreshold) && eRTblock == rdsblock && _hasEnhancedRT) {
|
||||
offset = (rds.rdsB & 0x1f) * 4;
|
||||
if ((!rdsBerrorThreshold && !rdsCerrorThreshold && !rdsDerrorThreshold) && eRTblock == rdsgroup && _hasEnhancedRT) {
|
||||
uint8_t 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
|
||||
@@ -1454,9 +1401,9 @@ void TEF6686::readRDS(byte showrdserrors) {
|
||||
}
|
||||
|
||||
|
||||
if (!rdsBerrorThreshold && rdsblock == 16 && (bitRead(rds.rdsB, 15))) rds.hasTMC = true; // TMC flag
|
||||
if (!rdsBerrorThreshold && rdsgroup == 16 && (bitRead(rds.rdsB, 15))) rds.hasTMC = true; // TMC flag
|
||||
|
||||
if ((!rdsBerrorThreshold && !rdsCerrorThreshold && !rdsDerrorThreshold) && DABAFblock == rdsblock && rds.hasDABAF) {
|
||||
if ((!rdsBerrorThreshold && !rdsCerrorThreshold && !rdsDerrorThreshold) && DABAFblock == rdsgroup && rds.hasDABAF) {
|
||||
rds.dabaffreq = (rds.rdsC * 16);
|
||||
|
||||
for (size_t i = 0; i < sizeof(DABfrequencyTable) / sizeof(DABfrequencyTable[0]); ++i) {
|
||||
@@ -1468,11 +1415,8 @@ void TEF6686::readRDS(byte showrdserrors) {
|
||||
rds.dabafeid[2] = (rds.rdsD >> 4) & 0xF;
|
||||
rds.dabafeid[3] = rds.rdsD & 0xF;
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if (rds.dabafeid[i] < 10) {
|
||||
rds.dabafeid[i] += '0'; // Add ASCII offset for decimal digits
|
||||
} else {
|
||||
rds.dabafeid[i] += 'A' - 10; // Add ASCII offset for hexadecimal letters A-F
|
||||
}
|
||||
if (rds.dabafeid[i] < 10) rds.dabafeid[i] += '0';
|
||||
else rds.dabafeid[i] += 'A' - 10;
|
||||
}
|
||||
rds.dabafeid[4] = 0;
|
||||
}
|
||||
@@ -1501,21 +1445,16 @@ void TEF6686::readRDS(byte showrdserrors) {
|
||||
eon[eon_counter].picode[2] = (rds.rdsD >> 4) & 0xF;
|
||||
eon[eon_counter].picode[3] = rds.rdsD & 0xF;
|
||||
for (int j = 0; j < 4; j++) {
|
||||
if (eon[eon_counter].picode[j] < 10) {
|
||||
eon[eon_counter].picode[j] += '0'; // Add ASCII offset for decimal digits
|
||||
} else {
|
||||
eon[eon_counter].picode[j] += 'A' - 10; // Add ASCII offset for hexadecimal letters A-F
|
||||
}
|
||||
if (eon[eon_counter].picode[j] < 10) eon[eon_counter].picode[j] += '0';
|
||||
else eon[eon_counter].picode[j] += 'A' - 10;
|
||||
}
|
||||
|
||||
eon[eon_counter].pi = rds.rdsD; // Store PI on next array
|
||||
if (eon_counter < 20) eon_counter++;
|
||||
eonIndex = eon_counter - 1;
|
||||
} else {
|
||||
eonIndex = i;
|
||||
}
|
||||
} else eonIndex = i;
|
||||
|
||||
offset = rds.rdsB & 0x0F; // Read offset
|
||||
uint8_t offset = rds.rdsB & 0x0F; // Read offset
|
||||
|
||||
if (offset < 4 && eon[eonIndex].pi == rds.rdsD) {
|
||||
eon_buffer[eonIndex][(offset * 2) + 0] = rds.rdsC >> 8; // First character of segment
|
||||
@@ -1583,7 +1522,7 @@ void TEF6686::readRDS(byte showrdserrors) {
|
||||
case RDS_GROUP_15A: {
|
||||
if (showrdserrors == 3 || (!rdsBerrorThreshold && !rdsCerrorThreshold && !rdsDerrorThreshold)) {
|
||||
if (pslong_process && rds.stationNameLong.length() > 0) rds.hasLongPS = true;
|
||||
offset = (rds.rdsB & 0xf) * 4; // Get Long PS character segment
|
||||
uint8_t 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];
|
||||
@@ -1630,6 +1569,7 @@ void TEF6686::readRDS(byte showrdserrors) {
|
||||
}
|
||||
break;
|
||||
}
|
||||
end:
|
||||
previous_rdsA = rds.rdsA;
|
||||
previous_rdsB = rds.rdsB;
|
||||
previous_rdsC = rds.rdsC;
|
||||
@@ -1737,17 +1677,17 @@ void TEF6686::clearRDS(bool fullsearchrds) {
|
||||
|
||||
for (i = 0; i < 10; i++) rds.aid[i] = 0;
|
||||
|
||||
rdsblock = 254;
|
||||
rdsgroup = 254;
|
||||
processed_rdsblocks = 0;
|
||||
piold = 0;
|
||||
rds.correctPI = 0;
|
||||
rds.ECC = 254;
|
||||
rds.stationTypeCode = 32;
|
||||
rds.PTY = 32;
|
||||
rds.dabaffreq = 0;
|
||||
rds.hasECC = false;
|
||||
rds.hasRT = false;
|
||||
rds.hasRDS = false;
|
||||
rds.hasTP = false;
|
||||
rds.TP = false;
|
||||
rds.hasAF = false;
|
||||
rds.hasTA = false;
|
||||
rds.hasEON = false;
|
||||
@@ -1756,7 +1696,7 @@ void TEF6686::clearRDS(bool fullsearchrds) {
|
||||
rds.hasAID = false;
|
||||
rds.hasPTYN = false;
|
||||
rds.hasLongPS = false;
|
||||
rds.hasRDSplus = false;
|
||||
rds.hasRTplus = false;
|
||||
rds.hasDABAF = false;
|
||||
rds.hasEnhancedRT = false;
|
||||
rt_process = false;
|
||||
@@ -2040,6 +1980,7 @@ String TEF6686::ucs2ToUtf8(const char* ucs2Input) {
|
||||
return utf8Output;
|
||||
}
|
||||
|
||||
static const char* fixedCalls[] = {"CBLA", "CBFM", "CBOT"};
|
||||
bool TEF6686::isFixedCallsign(uint16_t stationID, char* stationIDStr) {
|
||||
for (int i = 0; i < sizeof(fixedPI) / sizeof(fixedPI[0]); i++) {
|
||||
if (stationID == fixedPI[i]) {
|
||||
|
||||
11
src/gui.cpp
11
src/gui.cpp
@@ -1296,7 +1296,7 @@ void ShowOneLine(byte position, byte item, bool selected) {
|
||||
FullLineSprite.setTextDatum(TR_DATUM);
|
||||
FullLineSprite.setTextColor(PrimaryColor, PrimaryColorSmooth, false);
|
||||
switch (scancancel) {
|
||||
case OFF: FullLineSprite.drawString(textUI(30), 298, 2); break;
|
||||
case SCAN_CANCEL: FullLineSprite.drawString(textUI(30), 298, 2); break;
|
||||
case CORRECTPI: FullLineSprite.drawString(textUI(220), 298, 2); break;
|
||||
case SIGNAL: FullLineSprite.drawString(textUI(221), 298, 2); break;
|
||||
}
|
||||
@@ -2408,7 +2408,7 @@ void ShowOneButton(byte position, byte item, bool selected) {
|
||||
|
||||
PSSprite.setTextColor(PrimaryColor, PrimaryColorSmooth, false);
|
||||
switch (scancancel) {
|
||||
case OFF: PSSprite.drawString(textUI(30), 75, 15); break;
|
||||
case 0: PSSprite.drawString(textUI(30), 75, 15); break;
|
||||
case CORRECTPI: PSSprite.drawString(textUI(220), 75, 15); break;
|
||||
case SIGNAL: PSSprite.drawString(textUI(221), 75, 15); break;
|
||||
}
|
||||
@@ -4375,7 +4375,7 @@ void MenuUpDown(bool dir) {
|
||||
}
|
||||
|
||||
switch (scancancel) {
|
||||
case OFF: OneBigLineSprite.drawString(textUI(30), 135, 0); break;
|
||||
case SCAN_CANCEL: OneBigLineSprite.drawString(textUI(30), 135, 0); break;
|
||||
case CORRECTPI: OneBigLineSprite.drawString(textUI(220), 135, 0); break;
|
||||
case SIGNAL: OneBigLineSprite.drawString(textUI(221), 135, 0); break;
|
||||
}
|
||||
@@ -4657,7 +4657,8 @@ void DoMenu() {
|
||||
tftPrint(ARIGHT, "marsel90-1", 145, 185, PrimaryColor, PrimaryColorSmooth, 16);
|
||||
tftPrint(ALEFT, "lawendel", 155, 185, PrimaryColor, PrimaryColorSmooth, 16);
|
||||
tftPrint(ARIGHT, "KB8U", 145, 200, PrimaryColor, PrimaryColorSmooth, 16);
|
||||
tftPrint(ACENTER, "github.com/PE5PVB/TEF6686_ESP32", 155, 215, ActiveColor, ActiveColorSmooth, 16);
|
||||
tftPrint(ALEFT, "KubaPro010", 155, 200, PrimaryColor, PrimaryColorSmooth, 16);
|
||||
tftPrint(ACENTER, "github.com/KubaPro010/TEF6686_ESP32", 155, 215, ActiveColor, ActiveColorSmooth, 16);
|
||||
if (hardwaremodel == PORTABLE_TOUCH_ILI9341) {
|
||||
tft.fillRoundRect(240, 36, 60, 40, 6, FrameColor);
|
||||
tft.drawRoundRect(240, 36, 60, 40, 6, ActiveColor);
|
||||
@@ -5470,7 +5471,7 @@ void DoMenu() {
|
||||
Infoboxprint(textUI(219));
|
||||
|
||||
switch (scancancel) {
|
||||
case OFF: OneBigLineSprite.drawString(textUI(30), 135, 0); break;
|
||||
case SCAN_CANCEL: OneBigLineSprite.drawString(textUI(30), 135, 0); break;
|
||||
case CORRECTPI: OneBigLineSprite.drawString(textUI(220), 135, 0); break;
|
||||
case SIGNAL: OneBigLineSprite.drawString(textUI(221), 135, 0); break;
|
||||
}
|
||||
|
||||
211
src/logbook.cpp
211
src/logbook.cpp
@@ -15,7 +15,6 @@ void handleRoot() {
|
||||
html += "<meta charset=\"UTF-8\">";
|
||||
html += "<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">";
|
||||
|
||||
// Add CSS styling
|
||||
html += "<style>";
|
||||
html += "body {background-color: rgb(32, 34, 40); color: white; font-family: 'Arial', sans-serif;}";
|
||||
html += "h1 {text-align: center; margin-top: 20px;font-size: 32px;}";
|
||||
@@ -39,7 +38,6 @@ void handleRoot() {
|
||||
html += "</style>";
|
||||
html += "</head><body>";
|
||||
|
||||
// Add logo as a clickable link
|
||||
html += "<a href=\"https://fmdx.org/\" target=\"_blank\">";
|
||||
html += "<img src=\"/logo.png\" alt=\"FMDX website\">";
|
||||
html += "</a>";
|
||||
@@ -130,7 +128,6 @@ void handleRoot() {
|
||||
if (endIndex == -1) endIndex = line.length();
|
||||
String cell = line.substring(startIndex, endIndex);
|
||||
|
||||
// Extract PI code and Frequency
|
||||
if (columnIndex == piCodeIndex) piCode = cell;
|
||||
if (columnIndex == frequencyIndex) frequency = cell;
|
||||
|
||||
@@ -139,23 +136,17 @@ void handleRoot() {
|
||||
columnIndex++;
|
||||
}
|
||||
|
||||
// Remove " MHz" from Frequency
|
||||
frequency.replace(" MHz", "");
|
||||
|
||||
// Make row clickable
|
||||
html += "<td><a href =\"https://maps.fmdx.org/#qth=&freq=" + frequency + "&findPi=" + piCode + "\"target=\"_blank\">🌐</a></td>";
|
||||
html += "</tr>";
|
||||
}
|
||||
}
|
||||
|
||||
file.close();
|
||||
} else {
|
||||
html += "<tr><td colspan=\"100%\" style=\"text-align: center; color: red;\">" + String(textUI(299)) + "</td></tr>";
|
||||
}
|
||||
} else html += "<tr><td colspan=\"100%\" style=\"text-align: center; color: red;\">" + String(textUI(299)) + "</td></tr>";
|
||||
|
||||
if (!hasData) {
|
||||
html += "<tr><td colspan=\"100%\" style=\"text-align: center; color: red;\">" + String(textUI(288)) + "</td></tr>";
|
||||
}
|
||||
if (!hasData) html += "<tr><td colspan=\"100%\" style=\"text-align: center; color: red;\">" + String(textUI(288)) + "</td></tr>";
|
||||
|
||||
html += "</table>";
|
||||
html += "</body></html>";
|
||||
@@ -164,45 +155,30 @@ void handleRoot() {
|
||||
}
|
||||
|
||||
void handleDownloadCSV() {
|
||||
// Attempt to open the CSV file from SPIFFS in read mode
|
||||
fs::File file = SPIFFS.open("/logbook.csv", "r");
|
||||
|
||||
// Check if the file was successfully opened
|
||||
if (!file) {
|
||||
// If the file could not be opened, send an error response
|
||||
webserver.send(500, "text/plain", "Failed to open logbook for download");
|
||||
return; // Exit the function if the file cannot be opened
|
||||
return;
|
||||
}
|
||||
|
||||
// Set the headers to specify that the response will be a CSV file for download
|
||||
webserver.sendHeader("Content-Type", "text/csv"); // Set MIME type for CSV files
|
||||
webserver.sendHeader("Content-Disposition", "attachment; filename=logbook.csv"); // Suggests the file name for download
|
||||
webserver.sendHeader("Content-Type", "text/csv");
|
||||
webserver.sendHeader("Content-Disposition", "attachment; filename=logbook.csv");
|
||||
|
||||
// Stream the CSV file content directly to the browser
|
||||
webserver.streamFile(file, "text/csv");
|
||||
|
||||
// Close the file after streaming the content to release resources
|
||||
file.close();
|
||||
}
|
||||
|
||||
bool handleCreateNewLogbook() {
|
||||
// Check if the file "logbook.csv" already exists
|
||||
if (SPIFFS.exists("/logbook.csv")) {
|
||||
// If it exists, delete the file
|
||||
if (!SPIFFS.remove("/logbook.csv")) {
|
||||
return false;
|
||||
}
|
||||
if (!SPIFFS.remove("/logbook.csv")) return false;
|
||||
}
|
||||
|
||||
// Create a new "logbook.csv" file in write mode
|
||||
fs::File file = SPIFFS.open("/logbook.csv", "w");
|
||||
if (!file) {
|
||||
return false;
|
||||
}
|
||||
if (!file) return false;
|
||||
|
||||
// Write the header to the new CSV file
|
||||
String header = "Date,Time,Frequency,PI,Signal,Stereo,TA,TP,PTY,ECC,PS,Radiotext\n";
|
||||
file.print(header);
|
||||
file.print("Date,Time,Frequency,PI,Signal,Stereo,TA,TP,PTY,ECC,PS,Radiotext\n");
|
||||
|
||||
file.flush();
|
||||
file.close();
|
||||
@@ -215,33 +191,18 @@ bool handleCreateNewLogbook() {
|
||||
}
|
||||
|
||||
byte addRowToCSV() {
|
||||
// Ensure there is at least 150 bytes of free space in SPIFFS before proceeding
|
||||
if (SPIFFS.totalBytes() - SPIFFS.usedBytes() < 150 || logcounter > 1500) {
|
||||
return 2; // Return 2 if insufficient free space is available
|
||||
}
|
||||
if (SPIFFS.totalBytes() - SPIFFS.usedBytes() < 150 || logcounter > 1500) return 2;
|
||||
|
||||
// Open the "logbook.csv" file in append mode
|
||||
fs::File file = SPIFFS.open("/logbook.csv", "a");
|
||||
|
||||
// Check if the file could not be opened
|
||||
if (!file) {
|
||||
return 1; // Return 1 if the file cannot be opened
|
||||
}
|
||||
if (!file) return 1;
|
||||
|
||||
// Fetch the current date and time as a string
|
||||
String currentDateTime = getCurrentDateTime(false);
|
||||
if (currentDateTime == "") currentDateTime = "-,-";
|
||||
|
||||
// Use a placeholder ("-,-") if the date and time could not be retrieved
|
||||
if (currentDateTime == "") {
|
||||
currentDateTime = "-,-";
|
||||
}
|
||||
|
||||
// Prepare the frequency in a formatted string (e.g., "XX.XX MHz")
|
||||
int freqInt = (band == BAND_OIRT) ? (int)frequency_OIRT : (int)frequency;
|
||||
int adjustedFreq = freqInt + (band != BAND_OIRT ? ConverterSet * 100 : 0);
|
||||
String frequencyFormatted = String(adjustedFreq / 100) + "." +
|
||||
((adjustedFreq % 100 < 10) ? "0" : "") +
|
||||
String(adjustedFreq % 100) + " MHz";
|
||||
String frequencyFormatted = String(adjustedFreq / 100) + "." + ((adjustedFreq % 100 < 10) ? "0" : "") + String(adjustedFreq % 100) + " MHz";
|
||||
|
||||
// Calculate signal strength based on the selected unit
|
||||
int SStatusPrint = 0;
|
||||
@@ -249,126 +210,87 @@ byte addRowToCSV() {
|
||||
else if (unit == 1) SStatusPrint = ((SStatus * 100) + 10875) / 100; // dBf
|
||||
else if (unit == 2) SStatusPrint = round((float(SStatus) / 10.0 - 10.0 * log10(75) - 90.0) * 10.0); // dBm
|
||||
|
||||
// Format the signal strength with appropriate decimal places and unit
|
||||
String signal = String(SStatusPrint / 10) + "." + String(abs(SStatusPrint % 10));
|
||||
if (unit == 0) signal += " dBμV";
|
||||
else if (unit == 1) signal += " dBf";
|
||||
else if (unit == 2) signal += " dBm";
|
||||
|
||||
// Prepare the radio text with station information, including enhanced options if available
|
||||
String radioText = String(radio.rds.stationText + " " + radio.rds.stationText32);
|
||||
if (radio.rds.hasEnhancedRT) {
|
||||
radioText += " eRT: " + String(radio.rds.enhancedRTtext);
|
||||
}
|
||||
if (radio.rds.hasEnhancedRT) radioText += " eRT: " + String(radio.rds.enhancedRTtext);
|
||||
|
||||
// Replace commas in the station name and radio text to avoid CSV conflicts
|
||||
String stationName = radio.rds.stationName;
|
||||
String radioTextModified = (scanhold > 4 ? radioText : "");
|
||||
stationName.replace(",", " "); // Replace commas in station name
|
||||
radioTextModified.replace(",", " "); // Replace commas in radio text
|
||||
stationName.replace(",", " ");
|
||||
radioTextModified.replace(",", " ");
|
||||
|
||||
// Handle ECC, PTY, TA, TP, and Stereo flag
|
||||
String TA = radio.rds.hasTA ? "•" : " ";
|
||||
String TP = radio.rds.hasTP ? "•" : " ";
|
||||
String TP = radio.rds.TP ? "•" : " ";
|
||||
String Stereo = radio.getStereoStatus() ? "•" : " ";
|
||||
String pty = String(radio.rds.stationTypeCode);
|
||||
String pty = String(radio.rds.PTY);
|
||||
String ECC = "--";
|
||||
if (radio.rds.hasECC) {
|
||||
char eccBuffer[3]; // Buffer to hold 2-digit hex value + null terminator
|
||||
char eccBuffer[3];
|
||||
snprintf(eccBuffer, sizeof(eccBuffer), "%02X", radio.rds.ECC); // Format ECC as uppercase 2-digit hex
|
||||
ECC = String(eccBuffer);
|
||||
}
|
||||
|
||||
// Construct the CSV row data
|
||||
String row = currentDateTime + "," +
|
||||
frequencyFormatted + "," +
|
||||
String(radio.rds.picode).substring(0, 4) + "," +
|
||||
signal + "," +
|
||||
Stereo + "," +
|
||||
TA + "," +
|
||||
TP + "," +
|
||||
pty + "," +
|
||||
ECC + "," +
|
||||
stationName + "," +
|
||||
radioTextModified + "\n";
|
||||
String row = currentDateTime + "," + frequencyFormatted + "," + String(radio.rds.picode).substring(0, 4) + "," + signal + "," + Stereo + "," + TA + "," + TP + "," + pty + "," + ECC + "," + stationName + "," + radioTextModified + "\n";
|
||||
|
||||
// Write the row to the file and close it
|
||||
if (file.print(row)) {
|
||||
file.close(); // Successfully wrote to the file
|
||||
file.close();
|
||||
logcounter++;
|
||||
EEPROM.writeUInt(EE_UINT16_LOGCOUNTER, logcounter);
|
||||
EEPROM.commit();
|
||||
return 0; // Return 0 to indicate success
|
||||
return 0;
|
||||
} else {
|
||||
file.close(); // Close the file if writing fails
|
||||
return 1; // Return 1 to indicate failure
|
||||
file.close();
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
String getCurrentDateTime(bool inUTC) {
|
||||
// Check if the RTC has been set
|
||||
if (!rtcset) {
|
||||
return "-,-"; // Return placeholder when the RTC is not set
|
||||
}
|
||||
if (!rtcset) return "-,-";
|
||||
|
||||
// Use the ESP32's time functions to retrieve the current time
|
||||
struct tm timeInfo;
|
||||
if (!getLocalTime(&timeInfo)) {
|
||||
return "-,-"; // Return placeholder if local time is unavailable
|
||||
}
|
||||
if (!getLocalTime(&timeInfo)) return "-,-";
|
||||
|
||||
// Convert struct tm to time_t format
|
||||
time_t currentEpoch = mktime(&timeInfo);
|
||||
|
||||
// Determine UTC offset as a number
|
||||
int utcOffsetHours = 0;
|
||||
|
||||
if (!inUTC) {
|
||||
// Adjust for time zone offset and DST if not in UTC
|
||||
currentEpoch += (NTPupdated ? NTPoffset * 3600 : radio.rds.offset); // Apply GMT offset if NTPupdated, else RDS offset
|
||||
|
||||
// Apply DST adjustment if NTPupdated and autoDST are true
|
||||
if (NTPupdated && autoDST) {
|
||||
struct tm tempTimeInfo;
|
||||
localtime_r(¤tEpoch, &tempTimeInfo); // Convert to struct tm for DST calculation
|
||||
if (isDST(mktime(&tempTimeInfo))) { // Check if DST is in effect
|
||||
currentEpoch += 3600; // Add 1-hour DST offset
|
||||
}
|
||||
localtime_r(¤tEpoch, &tempTimeInfo);
|
||||
if (isDST(mktime(&tempTimeInfo))) currentEpoch += 3600;
|
||||
}
|
||||
} else utcOffsetHours = (NTPupdated ? NTPoffset : radio.rds.offset / 3600);
|
||||
|
||||
// Convert adjusted (or original) time back to struct tm format
|
||||
localtime_r(¤tEpoch, &timeInfo);
|
||||
|
||||
// Buffer for formatted date-time string
|
||||
char buf[20];
|
||||
|
||||
if (clockampm) {
|
||||
// USA format: MM/DD/YYYY, HH:MM:SS AM/PM
|
||||
strftime(buf, sizeof(buf), "%m/%d/%Y", &timeInfo); // Format as MM/DD/YYYY
|
||||
strftime(buf, sizeof(buf), "%m/%d/%Y", &timeInfo);
|
||||
|
||||
// Format time in 12-hour format with AM/PM
|
||||
int hour = timeInfo.tm_hour;
|
||||
String ampm = (hour >= 12) ? "PM" : "AM"; // Determine AM or PM
|
||||
if (hour == 0) hour = 12; // Convert 0 hour to 12 AM
|
||||
else if (hour > 12) hour -= 12; // Convert to 12-hour format for PM
|
||||
String ampm = (hour >= 12) ? "PM" : "AM";
|
||||
if (hour == 0) hour = 12;
|
||||
else if (hour > 12) hour -= 12;
|
||||
|
||||
String timeWithAMPM = String(hour) + ":" + (timeInfo.tm_min < 10 ? "0" : "") + String(timeInfo.tm_min) + ":" + (timeInfo.tm_sec < 10 ? "0" : "") + String(timeInfo.tm_sec) + " " + ampm;
|
||||
|
||||
// Append UTC offset if inUTC
|
||||
if (inUTC) {
|
||||
String utcOffsetStr = ", " + String(utcOffsetHours) + ",";
|
||||
return String(buf) + "," + timeWithAMPM + utcOffsetStr;
|
||||
}
|
||||
|
||||
// Return the final formatted date and time for the USA region
|
||||
return String(buf) + "," + timeWithAMPM;
|
||||
} else {
|
||||
// European format: DD-MM-YYYY, HH:MM:SS
|
||||
strftime(buf, sizeof(buf), "%d-%m-%Y", &timeInfo); // Format as DD-MM-YYYY
|
||||
strftime(buf, sizeof(buf), "%d-%m-%Y", &timeInfo);
|
||||
String timeEuropean = String(timeInfo.tm_hour) + ":" + (timeInfo.tm_min < 10 ? "0" : "") + String(timeInfo.tm_min) + ":" + (timeInfo.tm_sec < 10 ? "0" : "") + String(timeInfo.tm_sec); // Format time with leading zero if needed
|
||||
|
||||
// Append UTC offset if inUTC
|
||||
if (inUTC) {
|
||||
String utcOffsetStr = ", " + String(utcOffsetHours) + ",";
|
||||
return String(buf) + "," + timeEuropean + utcOffsetStr;
|
||||
@@ -380,33 +302,24 @@ String getCurrentDateTime(bool inUTC) {
|
||||
|
||||
bool isDST(time_t t) {
|
||||
struct tm timeInfo;
|
||||
localtime_r(&t, &timeInfo); // Convert time_t to struct tm
|
||||
localtime_r(&t, &timeInfo);
|
||||
|
||||
int month = timeInfo.tm_mon + 1; // tm_mon is 0-based, so add 1
|
||||
int day = timeInfo.tm_mday; // tm_mday is the day of the month
|
||||
int hour = timeInfo.tm_hour; // tm_hour is the hour of the day
|
||||
int weekday = timeInfo.tm_wday; // tm_wday is the day of the week (0 = Sunday)
|
||||
int month = timeInfo.tm_mon + 1;
|
||||
int day = timeInfo.tm_mday;
|
||||
int hour = timeInfo.tm_hour;
|
||||
int weekday = timeInfo.tm_wday;
|
||||
|
||||
// DST starts last Sunday in March at 2:00 AM
|
||||
if (month == 3) {
|
||||
int lastSunday = 31 - ((weekday + 31 - day) % 7);
|
||||
if (day > lastSunday || (day == lastSunday && hour >= 2)) {
|
||||
return true;
|
||||
}
|
||||
if (day > lastSunday || (day == lastSunday && hour >= 2)) return true;
|
||||
}
|
||||
|
||||
// DST ends last Sunday in October at 3:00 AM
|
||||
if (month == 10) {
|
||||
int lastSunday = 31 - ((weekday + 31 - day) % 7);
|
||||
if (day < lastSunday || (day == lastSunday && hour < 3)) {
|
||||
return false;
|
||||
}
|
||||
if (day < lastSunday || (day == lastSunday && hour < 3)) return false;
|
||||
}
|
||||
|
||||
// DST is active from April to September
|
||||
if (month > 3 && month < 10) {
|
||||
return true;
|
||||
}
|
||||
if (month > 3 && month < 10) return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -422,48 +335,34 @@ void handleLogo() {
|
||||
}
|
||||
|
||||
void printLogbookCSV() {
|
||||
// Attempt to open the CSV file stored in SPIFFS
|
||||
fs::File file = SPIFFS.open("/logbook.csv", "r");
|
||||
|
||||
// Check if the file was successfully opened
|
||||
if (!file) {
|
||||
Serial.println("Failed to open logbook!");
|
||||
return;
|
||||
}
|
||||
|
||||
// Print a message indicating the start of the file content
|
||||
Serial.println("===== Start of logbook.csv =====");
|
||||
|
||||
// Read and print the contents of the file line by line
|
||||
while (file.available()) {
|
||||
String line = file.readStringUntil('\n'); // Read one line at a time
|
||||
Serial.println(line); // Print the line to the Serial Monitor
|
||||
String line = file.readStringUntil('\n');
|
||||
Serial.println(line);
|
||||
}
|
||||
|
||||
// Close the file after reading
|
||||
file.close();
|
||||
|
||||
// Print a message indicating the end of the file content
|
||||
Serial.println("===== End of logbook.csv =====");
|
||||
}
|
||||
|
||||
void sendUDPlog() {
|
||||
// Get the current date and time as a string
|
||||
String currentDateTime = getCurrentDateTime(true);
|
||||
|
||||
// Use a placeholder if the date and time could not be retrieved
|
||||
if (currentDateTime == "") {
|
||||
currentDateTime = "-,-";
|
||||
}
|
||||
if (currentDateTime == "") currentDateTime = "-,-";
|
||||
|
||||
// Format the frequency, adjusting based on the band and converter settings
|
||||
int freqInt = (band == BAND_OIRT) ? (int)frequency_OIRT : (int)frequency;
|
||||
int adjustedFreq = freqInt + (band != BAND_OIRT ? ConverterSet * 100 : 0);
|
||||
String frequencyFormatted = String(adjustedFreq / 100) + "." +
|
||||
((adjustedFreq % 100 < 10) ? "0" : "") +
|
||||
String(adjustedFreq % 100);
|
||||
String frequencyFormatted = String(adjustedFreq / 100) + "." + ((adjustedFreq % 100 < 10) ? "0" : "") + String(adjustedFreq % 100);
|
||||
|
||||
// Calculate signal strength and format it with the selected unit
|
||||
int SStatusPrint = 0;
|
||||
if (unit == 0) SStatusPrint = SStatus; // dBμV
|
||||
else if (unit == 1) SStatusPrint = ((SStatus * 100) + 10875) / 100; // dBf
|
||||
@@ -474,19 +373,14 @@ void sendUDPlog() {
|
||||
else if (unit == 1) signal += " dBf";
|
||||
else if (unit == 2) signal += " dBm";
|
||||
|
||||
// Prepare the radio text with RDS station information and enhanced options
|
||||
String radioText = String(radio.rds.stationText + " " + radio.rds.stationText32);
|
||||
if (radio.rds.hasEnhancedRT) {
|
||||
radioText += " eRT: " + String(radio.rds.enhancedRTtext);
|
||||
}
|
||||
if (radio.rds.hasEnhancedRT) radioText += " eRT: " + String(radio.rds.enhancedRTtext);
|
||||
|
||||
// Replace commas in the station name and radio text to avoid conflicts in the CSV format
|
||||
String stationName = radio.rds.stationName;
|
||||
stationName.replace(",", " ");
|
||||
String radioTextModified = radioText;
|
||||
radioTextModified.replace(",", " ");
|
||||
|
||||
// Extract and format ECC (Extended Country Code) if available
|
||||
String ECC = "";
|
||||
if (radio.rds.hasECC) {
|
||||
char eccBuffer[3];
|
||||
@@ -494,16 +388,13 @@ void sendUDPlog() {
|
||||
ECC = String(eccBuffer);
|
||||
}
|
||||
|
||||
// Format the list of Alternative Frequencies (AF) if available
|
||||
String AF = "";
|
||||
if (radio.rds.hasAF && radio.af_counter > 0) {
|
||||
for (byte i = 0; i < radio.af_counter; i++) {
|
||||
AF += String(radio.af[i].frequency / 100) + "." + String((radio.af[i].frequency % 100) / 10) +
|
||||
(i == radio.af_counter - 1 ? "" : ";");
|
||||
AF += String(radio.af[i].frequency / 100) + "." + String((radio.af[i].frequency % 100) / 10) + (i == radio.af_counter - 1 ? "" : ";");
|
||||
}
|
||||
}
|
||||
|
||||
// Format Enhanced Other Networks (EON) data if available
|
||||
String EON = "";
|
||||
if (radio.eon_counter > 0) {
|
||||
for (byte i = 0; i < radio.eon_counter; i++) {
|
||||
@@ -516,7 +407,6 @@ void sendUDPlog() {
|
||||
}
|
||||
}
|
||||
|
||||
// set Chipmodel
|
||||
String CHIP = "";
|
||||
switch (chipmodel) {
|
||||
case 0: CHIP = "TEF6686"; break;
|
||||
@@ -525,11 +415,8 @@ void sendUDPlog() {
|
||||
case 3: CHIP = "TEF6689"; break;
|
||||
}
|
||||
|
||||
// Extract RT+ (RadioText Plus) content if available
|
||||
String RTPLUS = "";
|
||||
if (radio.rds.hasRDSplus) {
|
||||
RTPLUS += radio.rds.RTContent1 + ";" + radio.rds.RTContent2;
|
||||
}
|
||||
if (radio.rds.hasRTplus) RTPLUS += radio.rds.RTContent1 + ";" + radio.rds.RTContent2;
|
||||
|
||||
// Construct the data row to send via UDP
|
||||
String row = CHIP + "," +
|
||||
@@ -541,9 +428,9 @@ void sendUDPlog() {
|
||||
signal + "," +
|
||||
String(radio.getStereoStatus()) + "," +
|
||||
String(radio.rds.hasTA) + "," +
|
||||
String(radio.rds.hasTP) + "," +
|
||||
String(radio.rds.TP) + "," +
|
||||
String(radio.rds.hasTMC) + "," +
|
||||
String(radio.rds.stationTypeCode) + "," +
|
||||
String(radio.rds.PTY) + "," +
|
||||
ECC + "," +
|
||||
stationName + "," +
|
||||
radioTextModified + "," +
|
||||
|
||||
42
src/main.cpp
42
src/main.cpp
@@ -5110,17 +5110,12 @@ void StoreMemoryPos(uint8_t _pos) {
|
||||
EEPROM.writeByte(_pos + EE_PRESETS_BAND_START, band);
|
||||
EEPROM.writeByte(_pos + EE_PRESET_BW_START, BWset);
|
||||
EEPROM.writeByte(_pos + EE_PRESET_MS_START, StereoToggle);
|
||||
if (band == BAND_FM) {//todo air
|
||||
EEPROM.writeUInt((_pos * 4) + EE_PRESETS_FREQUENCY_START, frequency);
|
||||
} else if (band == BAND_OIRT) {
|
||||
EEPROM.writeUInt((_pos * 4) + EE_PRESETS_FREQUENCY_START, frequency_OIRT);
|
||||
} else if (band == BAND_LW) {
|
||||
EEPROM.writeUInt((_pos * 4) + EE_PRESETS_FREQUENCY_START, frequency_LW);
|
||||
} else if (band == BAND_MW) {
|
||||
EEPROM.writeUInt((_pos * 4) + EE_PRESETS_FREQUENCY_START, frequency_MW);
|
||||
} else {
|
||||
EEPROM.writeUInt((_pos * 4) + EE_PRESETS_FREQUENCY_START, frequency_SW);
|
||||
}
|
||||
|
||||
if (band == BAND_FM) EEPROM.writeUInt((_pos * 4) + EE_PRESETS_FREQUENCY_START, frequency);
|
||||
else if (band == BAND_OIRT) EEPROM.writeUInt((_pos * 4) + EE_PRESETS_FREQUENCY_START, frequency_OIRT);
|
||||
else if (band == BAND_LW) EEPROM.writeUInt((_pos * 4) + EE_PRESETS_FREQUENCY_START, frequency_LW);
|
||||
else if (band == BAND_MW) EEPROM.writeUInt((_pos * 4) + EE_PRESETS_FREQUENCY_START, frequency_MW);
|
||||
else EEPROM.writeUInt((_pos * 4) + EE_PRESETS_FREQUENCY_START, frequency_SW);
|
||||
|
||||
presets[_pos].band = band;
|
||||
presets[_pos].bw = BWset;
|
||||
@@ -5144,17 +5139,11 @@ void StoreMemoryPos(uint8_t _pos) {
|
||||
|
||||
EEPROM.commit();
|
||||
|
||||
if (band == BAND_FM) {//todo air
|
||||
presets[_pos].frequency = frequency;
|
||||
} else if (band == BAND_OIRT) {
|
||||
presets[_pos].frequency = frequency_OIRT;
|
||||
} else if (band == BAND_LW) {
|
||||
presets[_pos].frequency = frequency_LW;
|
||||
} else if (band == BAND_MW) {
|
||||
presets[_pos].frequency = frequency_MW;
|
||||
} else {
|
||||
presets[_pos].frequency = frequency_SW;
|
||||
}
|
||||
if (band == BAND_FM) presets[_pos].frequency = frequency;
|
||||
else if (band == BAND_OIRT) presets[_pos].frequency = frequency_OIRT;
|
||||
else if (band == BAND_LW) presets[_pos].frequency = frequency_LW;
|
||||
else if (band == BAND_MW) presets[_pos].frequency = frequency_MW;
|
||||
else presets[_pos].frequency = frequency_SW;
|
||||
}
|
||||
|
||||
void ClearMemoryRange(uint8_t start, uint8_t stop) {
|
||||
@@ -5180,9 +5169,7 @@ void ClearMemoryRange(uint8_t start, uint8_t stop) {
|
||||
}
|
||||
}
|
||||
|
||||
byte numval[16] = {
|
||||
2, 3, 127, 5, 6, 0, 9, 13, 8, 7, 4, 1, 0, 0, 0, 0
|
||||
};
|
||||
byte numval[16] = {2, 3, 127, 5, 6, 0, 9, 13, 8, 7, 4, 1, 0, 0, 0, 0};
|
||||
|
||||
int GetNum() {
|
||||
int16_t temp;
|
||||
@@ -5201,12 +5188,11 @@ int GetNum() {
|
||||
for (int i = 0; i < 16; i++) {
|
||||
if ((temp & 0x01) == 0) {
|
||||
num = numval[i];
|
||||
cnt ++;
|
||||
cnt++;
|
||||
}
|
||||
temp >>= 1;
|
||||
}
|
||||
if (cnt == 1)
|
||||
return num;
|
||||
if (cnt == 1) return num;
|
||||
}
|
||||
|
||||
return -1;
|
||||
|
||||
28
src/rds.cpp
28
src/rds.cpp
@@ -132,12 +132,12 @@ void ShowAdvancedRDS() {
|
||||
}
|
||||
|
||||
String rtplusstring;
|
||||
if (radio.rds.hasRDSplus) rtplusstring = (radio.rds.rdsplusTag1 != 169 ? String(textUI(radio.rds.rdsplusTag1)) + ": " + String(radio.rds.RTContent1) : "") + (radio.rds.rdsplusTag2 != 169 ? " - " + String(textUI(radio.rds.rdsplusTag2)) + ": " + String(radio.rds.RTContent2) : "") + " "; else rtplusstring = textUI(89);
|
||||
if (hasrtplusold != radio.rds.hasRDSplus) {
|
||||
if (radio.rds.hasRTplus) rtplusstring = (radio.rds.rdsplusTag1 != 169 ? String(textUI(radio.rds.rdsplusTag1)) + ": " + String(radio.rds.RTContent1) : "") + (radio.rds.rdsplusTag2 != 169 ? " - " + String(textUI(radio.rds.rdsplusTag2)) + ": " + String(radio.rds.RTContent2) : "") + " "; else rtplusstring = textUI(89);
|
||||
if (hasrtplusold != radio.rds.hasRTplus) {
|
||||
if (!screenmute) {
|
||||
if (radio.rds.hasRDSplus) tftPrint(ALEFT, "RT+", 123, 51, RDSColor, RDSColorSmooth, 16); else tftPrint(ALEFT, "RT+", 123, 51, GreyoutColor, BackgroundColor, 16);
|
||||
if (radio.rds.hasRTplus) tftPrint(ALEFT, "RT+", 123, 51, RDSColor, RDSColorSmooth, 16); else tftPrint(ALEFT, "RT+", 123, 51, GreyoutColor, BackgroundColor, 16);
|
||||
}
|
||||
hasrtplusold = radio.rds.hasRDSplus;
|
||||
hasrtplusold = radio.rds.hasRTplus;
|
||||
}
|
||||
|
||||
if (rtplusstring != rtplusstringold) {
|
||||
@@ -172,11 +172,11 @@ void ShowAdvancedRDS() {
|
||||
}
|
||||
}
|
||||
|
||||
if (TPold != radio.rds.hasTP) {
|
||||
if (TPold != radio.rds.TP) {
|
||||
if (!screenmute) {
|
||||
if (radio.rds.hasTP) tftPrint(ALEFT, "TP", 2, 51, RDSColor, RDSColorSmooth, 16); else tftPrint(ALEFT, "TP", 2, 51, GreyoutColor, BackgroundColor, 16);
|
||||
if (radio.rds.TP) tftPrint(ALEFT, "TP", 2, 51, RDSColor, RDSColorSmooth, 16); else tftPrint(ALEFT, "TP", 2, 51, GreyoutColor, BackgroundColor, 16);
|
||||
}
|
||||
TPold = radio.rds.hasTP;
|
||||
TPold = radio.rds.TP;
|
||||
}
|
||||
|
||||
if (TAold != radio.rds.hasTA) {
|
||||
@@ -193,10 +193,10 @@ void ShowAdvancedRDS() {
|
||||
afmethodBold = radio.afmethodB;
|
||||
}
|
||||
|
||||
if (rdsblockold != radio.rdsblock) {
|
||||
if (rdsblockold != radio.rdsgroup) {
|
||||
if (rdsblockold < 33) tft.fillCircle((6 * rdsblockold) + 10, 133, 2, SignificantColor);
|
||||
if (radio.rdsblock < 33) tft.fillCircle((6 * radio.rdsblock) + 10, 133, 2, InsignificantColor);
|
||||
rdsblockold = radio.rdsblock;
|
||||
if (radio.rdsgroup < 33) tft.fillCircle((6 * radio.rdsgroup) + 10, 133, 2, InsignificantColor);
|
||||
rdsblockold = radio.rdsgroup;
|
||||
}
|
||||
|
||||
if (hastmcold != radio.rds.hasTMC) {
|
||||
@@ -527,9 +527,9 @@ void showPI() {
|
||||
|
||||
void showPTY() {
|
||||
if (strcmp(radio.rds.stationType, programTypePrevious)) {
|
||||
String PTYString = String(radio.rds.stationTypeCode) + "/" + (radio.rds.region != 0 ? radio.rds.stationType : textUI(228 + radio.rds.stationTypeCode));
|
||||
String PTYString = String(radio.rds.PTY) + "/" + (radio.rds.region != 0 ? radio.rds.stationType : textUI(228 + radio.rds.PTY));
|
||||
|
||||
if (radio.rds.stationTypeCode == 32) PTYString = "";
|
||||
if (radio.rds.PTY == 32) PTYString = "";
|
||||
|
||||
if (!screenmute) {
|
||||
if (advancedRDS) {
|
||||
@@ -545,7 +545,7 @@ void showPTY() {
|
||||
if (wifi) {
|
||||
Udp.beginPacket(remoteip, 9030);
|
||||
Udp.print("from=TEF_tuner_" + String(stationlistid, DEC) + ";PTY=");
|
||||
Udp.print(String(radio.rds.stationTypeCode, HEX));
|
||||
Udp.print(String(radio.rds.PTY, HEX));
|
||||
Udp.endPacket();
|
||||
}
|
||||
strcpy(programTypePrevious, radio.rds.stationType);
|
||||
@@ -1015,7 +1015,7 @@ void ShowRDSStatistics() {
|
||||
|
||||
const uint8_t rdsYpos[] PROGMEM = {56, 76, 96, 116, 136, 156, 176, 196};
|
||||
|
||||
uint8_t rb = radio.rdsblock;
|
||||
uint8_t rb = radio.rdsgroup;
|
||||
|
||||
uint16_t xpos, xposPct;
|
||||
if(rb <= RDS_GROUP_3B) {
|
||||
|
||||
Reference in New Issue
Block a user