fix graphics

This commit is contained in:
2026-01-08 18:03:51 +01:00
parent b66f821e84
commit 67109d544d
11 changed files with 79 additions and 115 deletions

View File

@@ -8,9 +8,6 @@ The version in the repository is an ongoing development. It could and will conta
Advanced Tuner software for NXP TEF668x tuners with ESP32 board Advanced Tuner software for NXP TEF668x tuners with ESP32 board
More information: https://www.pe5pvb.nl/tef6686/ More information: https://www.pe5pvb.nl/tef6686/
## TFT_eSPI
When compiling for the first time, please edit the User_Setup.h file in the lib/TFT_eSPI/
## Wiki ## Wiki
- [About the software & features](https://github.com/PE5PVB/TEF6686_ESP32/wiki) - [About the software & features](https://github.com/PE5PVB/TEF6686_ESP32/wiki)
- [Getting started](https://github.com/PE5PVB/TEF6686_ESP32/wiki#getting-started) - [Getting started](https://github.com/PE5PVB/TEF6686_ESP32/wiki#getting-started)

View File

@@ -478,7 +478,7 @@ typedef struct _rds_ {
bool hasEnhancedRT; bool hasEnhancedRT;
bool TP; bool TP;
bool hasTA; bool hasTA;
bool hasEON; Detector<bool, 1> hasEON{false};
bool hasAID; bool hasAID;
Detector<bool, 1> hasTMC{false}; Detector<bool, 1> hasTMC{false};
bool hasAF; bool hasAF;

View File

@@ -398,4 +398,5 @@ extern WebServer webserver;
extern ScrollingTextDisplay rtplusDisplay; extern ScrollingTextDisplay rtplusDisplay;
extern ScrollingTextDisplay eonDisplay; extern ScrollingTextDisplay eonDisplay;
extern ScrollingTextDisplay eccDisplay; extern ScrollingTextDisplay eccDisplay;
extern ScrollingTextDisplay rtDisplay;

View File

@@ -13,6 +13,7 @@ private:
unsigned long lastTick; unsigned long lastTick;
unsigned long holdTick; unsigned long holdTick;
bool isScrolling; bool isScrolling;
std::function<void(TFT_eSprite*, bool)> postDrawCallback;
static const unsigned long SCROLL_INTERVAL = 5; static const unsigned long SCROLL_INTERVAL = 5;
static const unsigned long HOLD_DURATION = 2000; static const unsigned long HOLD_DURATION = 2000;
@@ -20,11 +21,14 @@ private:
public: public:
ScrollingTextDisplay(TFT_eSprite* spr, int y, int maxW) ScrollingTextDisplay(TFT_eSprite* spr, int y, int maxW)
: sprite(spr), yPos(y), maxWidth(maxW), : sprite(spr), yPos(y), maxWidth(maxW),
xPos(0), textWidth(0), lastTick(0), holdTick(0), isScrolling(false) {} xPos(0), textWidth(0), lastTick(0), holdTick(0), isScrolling(false), postDrawCallback(nullptr) {}
// Update the display with new text void setPostDrawCallback(std::function<void(TFT_eSprite*, bool)> callback) {
void update(const String& text, int width, bool status, uint16_t activeColor, uint16_t activeSmooth, uint16_t dropoutColor, uint16_t dropoutSmooth, uint16_t backgroundColor) { postDrawCallback = callback;
textWidth = width; }
void update(const String& text, bool status, uint16_t activeColor, uint16_t activeSmooth, uint16_t dropoutColor, uint16_t dropoutSmooth, uint16_t backgroundColor) {
textWidth = sprite->textWidth(text);
if (textWidth < maxWidth) { if (textWidth < maxWidth) {
xPos = 0; xPos = 0;
@@ -70,7 +74,8 @@ private:
sprite->fillSprite(backgroundColor); sprite->fillSprite(backgroundColor);
if (status) sprite->setTextColor(activeColor, activeSmooth, false); if (status) sprite->setTextColor(activeColor, activeSmooth, false);
else sprite->setTextColor(dropoutColor, dropoutSmooth, false); else sprite->setTextColor(dropoutColor, dropoutSmooth, false);
sprite->drawString(text, xPos, 2); sprite->drawString(text, xPos, 0);
if (postDrawCallback) postDrawCallback(sprite, false);
sprite->pushSprite(35, yPos); sprite->pushSprite(35, yPos);
} }
@@ -78,8 +83,9 @@ private:
sprite->fillSprite(backgroundColor); sprite->fillSprite(backgroundColor);
if (status) sprite->setTextColor(activeColor, activeSmooth, false); if (status) sprite->setTextColor(activeColor, activeSmooth, false);
else sprite->setTextColor(dropoutColor, dropoutSmooth, false); else sprite->setTextColor(dropoutColor, dropoutSmooth, false);
sprite->drawString(text, xPos, 2); sprite->drawString(text, xPos, 0);
sprite->drawString(text, xPos + textWidth, 2); sprite->drawString(text, xPos + textWidth, 0);
if (postDrawCallback) postDrawCallback(sprite, true);
sprite->pushSprite(35, yPos); sprite->pushSprite(35, yPos);
} }
}; };

View File

@@ -1,6 +1,3 @@
//#define ARS // uncomment for BGR type display (ARS version)
#define DEEPELEC_DP_66X // uncomment for DEEPELEC Portable DP-66X build
#define ILI9341_DRIVER #define ILI9341_DRIVER
#define TFT_DMA_SUPPORT #define TFT_DMA_SUPPORT
#define TFT_CS 5 #define TFT_CS 5

View File

@@ -1,14 +1,7 @@
; PlatformIO Project Configuration File [platformio]
; default_envs = dp66x
; Build options: build flags, source filter
; Upload options: custom upload port, speed and extra flags
; Library options: dependencies, extra library storages
; Advanced options: extra scripting
;
; Please visit documentation for the other options and examples
; https://docs.platformio.org/page/projectconf.html
[env:esp32dev] [esp32dev]
platform = espressif32 platform = espressif32
upload_speed = 921600 upload_speed = 921600
board = esp32dev board = esp32dev
@@ -30,4 +23,22 @@ build_unflags =
-fexceptions -fexceptions
-frtti -frtti
extra_scripts = pre:extra_script.py extra_scripts = pre:extra_script.py
[env:dp66x]
platform = espressif32
extends = esp32dev
build_flags =
${esp32dev.build_flags}
-DDEEPELEC_DP_66X
[env:ars]
platform = espressif32
extends = esp32dev
build_flags =
${esp32dev.build_flags}
-DARS
[env:diy]
platform = espressif32
extends = esp32dev

View File

@@ -1386,7 +1386,7 @@ void TEF6686::readRDS(byte showrdserrors) {
case RDS_GROUP_14A: { case RDS_GROUP_14A: {
if (!rdsAerrorThreshold && !rdsBerrorThreshold && !rdsCerrorThreshold && !rdsDerrorThreshold) { if (!rdsAerrorThreshold && !rdsBerrorThreshold && !rdsCerrorThreshold && !rdsDerrorThreshold) {
rds.hasEON = true; rds.hasEON.set(true);
bool isValuePresent = false; bool isValuePresent = false;
int eonIndex = -1; int eonIndex = -1;
@@ -1602,10 +1602,11 @@ void TEF6686::clearRDS(bool fullsearchrds) {
rds.PTY.set(0); rds.PTY.set(0);
rds.hasECC = rds.hasRT = rds.hasRDS = false; rds.hasECC = rds.hasRT = rds.hasRDS = false;
rds.TP = rds.hasAF = rds.hasTA = false; rds.TP = rds.hasAF = rds.hasTA = false;
rds.hasEON = rds.hasCT = false; rds.hasCT = false;
rds.hasAID = rds.hasPTYN = rds.hasLongPS = false; rds.hasAID = rds.hasPTYN = rds.hasLongPS = false;
rds.hasRTplus.set(false); rds.hasRTplus.set(false);
rds.hasTMC.set(false); rds.hasTMC.set(false);
rds.hasEON.set(false);
rds.hasDABAF = rds.hasEnhancedRT = false; rds.hasDABAF = rds.hasEnhancedRT = false;
rt_process = ps_process = pslong_process = false; rt_process = ps_process = pslong_process = false;
rds.rdsreset = true; rds.rdsreset = true;

View File

@@ -362,6 +362,14 @@ mem presets[EE_PRESETS_CNT];
TEF6686 radio; TEF6686 radio;
ESP32Time rtc(0); ESP32Time rtc(0);
// FrequencySprite.createSprite(200, 50);
// RDSSprite.createSprite(165, 19);
// PSSprite.createSprite(150, 32);
// SquelchSprite.createSprite(27, 19);
// FullLineSprite.createSprite(308, 19);
// OneBigLineSprite.createSprite(270, 30);
TFT_eSprite FrequencySprite = TFT_eSprite(&tft); TFT_eSprite FrequencySprite = TFT_eSprite(&tft);
TFT_eSprite RDSSprite = TFT_eSprite(&tft); TFT_eSprite RDSSprite = TFT_eSprite(&tft);
TFT_eSprite SquelchSprite = TFT_eSprite(&tft); TFT_eSprite SquelchSprite = TFT_eSprite(&tft);
@@ -376,6 +384,7 @@ WiFiClient RemoteClient;
WiFiUDP Udp; WiFiUDP Udp;
WebServer webserver(80); WebServer webserver(80);
ScrollingTextDisplay rtplusDisplay(&RDSSprite, 146, 170); ScrollingTextDisplay rtplusDisplay(&RDSSprite, 147, 180);
ScrollingTextDisplay eonDisplay(&RDSSprite, 172, 170); ScrollingTextDisplay eonDisplay(&RDSSprite, 174, 180);
ScrollingTextDisplay eccDisplay(&FullLineSprite, 199, 270); ScrollingTextDisplay eccDisplay(&FullLineSprite, 198, 270);
ScrollingTextDisplay rtDisplay(&FullLineSprite, 220, 270);

View File

@@ -588,7 +588,7 @@ void BuildAFScreen() {
if (afpagenr == 1) { if (afpagenr == 1) {
if (!radio.rds.hasAF) tftPrint(ALEFT, textUI(87), 6, 48, PrimaryColor, PrimaryColorSmooth, 16); if (!radio.rds.hasAF) tftPrint(ALEFT, textUI(87), 6, 48, PrimaryColor, PrimaryColorSmooth, 16);
} else if (afpagenr == 2) { } else if (afpagenr == 2) {
if (!radio.rds.hasEON) tftPrint(ALEFT, textUI(88), 6, 48, PrimaryColor, PrimaryColorSmooth, 16); if (!radio.rds.hasEON.get()) tftPrint(ALEFT, textUI(88), 6, 48, PrimaryColor, PrimaryColorSmooth, 16);
} }
RDSstatusold = !RDSstatusold; RDSstatusold = !RDSstatusold;
ShowFreq(0); ShowFreq(0);
@@ -608,7 +608,6 @@ void BuildAFScreen() {
rds_clockold = ""; rds_clockold = "";
dropout = false; dropout = false;
rdsreset = true; rdsreset = true;
xPos = 0;
rtplusDisplay.reset(); rtplusDisplay.reset();
eonDisplay.reset(); eonDisplay.reset();
eccDisplay.reset(); eccDisplay.reset();
@@ -2993,10 +2992,11 @@ void BuildAdvancedRDS() {
rdsreset = true; rdsreset = true;
ShowMemoryPos(); ShowMemoryPos();
xPos = 0; xPos = 0;
xPos2 = 0;
rtplusDisplay.reset(); rtplusDisplay.reset();
eonDisplay.reset(); eonDisplay.reset();
eccDisplay.reset(); eccDisplay.reset();
xPos2 = 0; rtDisplay.reset();
} }
void BuildDisplay() { void BuildDisplay() {
@@ -3112,10 +3112,11 @@ void BuildDisplay() {
stationStateold = " "; stationStateold = " ";
BWreset = true; BWreset = true;
dropout = false; dropout = false;
xPos = 0;
rtplusDisplay.reset(); rtplusDisplay.reset();
eonDisplay.reset(); eonDisplay.reset();
eccDisplay.reset(); eccDisplay.reset();
rtDisplay.reset();
xPos = 0;
xPos2 = 0; xPos2 = 0;
MPold = 99; MPold = 99;
USold = 99; USold = 99;

View File

@@ -1721,6 +1721,19 @@ void setup() {
SelectBand(); SelectBand();
if (tunemode == TUNE_MEM) DoMemoryPosTune(); if (tunemode == TUNE_MEM) DoMemoryPosTune();
eccDisplay.setPostDrawCallback([&](TFT_eSprite* sprite, bool scrolling) {
sprite->fillRect(275, 0, 8, 19, BackgroundColor);
sprite->drawLine(284, 0, 284, 19, FrameColor);
});
rtDisplay.setPostDrawCallback([&](TFT_eSprite* sprite, bool scrolling) {
sprite->fillRect(275, 0, 8, 19, BackgroundColor);
sprite->drawLine(284, 0, 284, 19, FrameColor);
if (radio.rds.hasRT) {
FullLineSprite.fillCircle(278, 3, 2, radio.rds.rtAB ? GreyoutColor : InsignificantColor);
FullLineSprite.fillCircle(278, 14, 2, radio.rds.rtAB ? InsignificantColor : GreyoutColor);
}
});
setupmode = false; setupmode = false;
if (edgebeep) radio.tone(50, -5, 2000); if (edgebeep) radio.tone(50, -5, 2000);

View File

@@ -6,8 +6,8 @@
String HexStringold; String HexStringold;
float smoothBER = 0; float smoothBER = 0;
int RadiotextWidth, PSLongWidth, AIDWidth, afstringWidth, eccstringWidth, eonstringWidth, rtplusstringWidth, lengths[7]; int PSLongWidth, AIDWidth, lengths[7];
String afstringold, eonstringold, rtplusstringold, stationNameLongOld, AIDStringold; String stationNameLongOld, AIDStringold;
bool rtABold, ps12errorold, ps34errorold, ps56errorold, ps78errorold; bool rtABold, ps12errorold, ps34errorold, ps56errorold, ps78errorold;
void ShowAdvancedRDS() { void ShowAdvancedRDS() {
@@ -60,8 +60,6 @@ void ShowAdvancedRDS() {
if (radio.rds.ECC.changed(0)) { if (radio.rds.ECC.changed(0)) {
if (!screenmute) { if (!screenmute) {
if (radio.rds.hasECC) ECCString = (radio.rds.ECCtext.length() == 0 ? textUI(73) : radio.rds.ECCtext); else ECCString = "N/A"; if (radio.rds.hasECC) ECCString = (radio.rds.ECCtext.length() == 0 ? textUI(73) : radio.rds.ECCtext); else ECCString = "N/A";
tftPrint(ALEFT, "N/A", 35, 199, BackgroundColor, BackgroundColor, 16);
eccstringWidth = RDSSprite.textWidth(ECCString);
} }
if (wifi) { if (wifi) {
@@ -72,23 +70,17 @@ void ShowAdvancedRDS() {
Udp.endPacket(); Udp.endPacket();
} }
} }
if(!screenmute) eccDisplay.update(ECCString, eccstringWidth, RDSstatus, RDSColor, RDSColorSmooth, RDSDropoutColor, RDSDropoutColorSmooth, BackgroundColor); if(!screenmute) eccDisplay.update(ECCString, RDSstatus, RDSColor, RDSColorSmooth, RDSDropoutColor, RDSDropoutColorSmooth, BackgroundColor);
String eonstring; String eonstring;
if (radio.eon_counter > 0) for (byte i = 0; i < radio.eon_counter; i++) eonstring += String(radio.eon[i].picode) + (radio.eon[i].ps.length() > 0 ? String(": " + String(radio.eon[i].ps)) : "") + (radio.eon[i].mappedfreq > 0 ? String(" " + String(radio.eon[i].mappedfreq / 100) + "." + String((radio.eon[i].mappedfreq % 100) / 10)) : "") + (radio.eon[i].mappedfreq2 > 0 ? String(" / " + String(radio.eon[i].mappedfreq2 / 100) + "." + String((radio.eon[i].mappedfreq2 % 100) / 10)) : "") + (radio.eon[i].mappedfreq3 > 0 ? String(" / " + String(radio.eon[i].mappedfreq3 / 100) + "." + String((radio.eon[i].mappedfreq3 % 100) / 10)) : "") + (i == radio.eon_counter - 1 ? " " : " | "); else eonstring = textUI(88); if (radio.eon_counter > 0) for (byte i = 0; i < radio.eon_counter; i++) eonstring += String(radio.eon[i].picode) + (radio.eon[i].ps.length() > 0 ? String(": " + String(radio.eon[i].ps)) : "") + (radio.eon[i].mappedfreq > 0 ? String(" " + String(radio.eon[i].mappedfreq / 100) + "." + String((radio.eon[i].mappedfreq % 100) / 10)) : "") + (radio.eon[i].mappedfreq2 > 0 ? String(" / " + String(radio.eon[i].mappedfreq2 / 100) + "." + String((radio.eon[i].mappedfreq2 % 100) / 10)) : "") + (radio.eon[i].mappedfreq3 > 0 ? String(" / " + String(radio.eon[i].mappedfreq3 / 100) + "." + String((radio.eon[i].mappedfreq3 % 100) / 10)) : "") + (i == radio.eon_counter - 1 ? " " : " | "); else eonstring = textUI(88);
if (haseonold != radio.rds.hasEON) { if (radio.rds.hasEON.changed(0)) {
if (!screenmute) { if (!screenmute) {
if (radio.eon_counter > 0) tftPrint(ALEFT, "EON", 153, 51, RDSColor, RDSColorSmooth, 16); else tftPrint(ALEFT, "EON", 153, 51, GreyoutColor, BackgroundColor, 16); if (radio.eon_counter > 0) tftPrint(ALEFT, "EON", 153, 51, RDSColor, RDSColorSmooth, 16); else tftPrint(ALEFT, "EON", 153, 51, GreyoutColor, BackgroundColor, 16);
} }
haseonold = radio.rds.hasEON;
} }
if (eonstring != eonstringold) { if(!screenmute) eonDisplay.update(eonstring, RDSstatus, RDSColor, RDSColorSmooth, RDSDropoutColor, RDSDropoutColorSmooth, BackgroundColor);
eonstringWidth = RDSSprite.textWidth(eonstring);
eonstringold = eonstring;
}
if(!screenmute) eonDisplay.update(eonstring, eonstringWidth, RDSstatus, RDSColor, RDSColorSmooth, RDSDropoutColor, RDSDropoutColorSmooth, BackgroundColor);
String rtplusstring; String rtplusstring;
if (radio.rds.hasRTplus.get()) 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 (radio.rds.hasRTplus.get()) 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);
@@ -98,12 +90,7 @@ void ShowAdvancedRDS() {
} }
} }
if (rtplusstring != rtplusstringold) { if(!screenmute) rtplusDisplay.update(rtplusstring, RDSstatus, RDSColor, RDSColorSmooth, RDSDropoutColor, RDSDropoutColorSmooth, BackgroundColor);
rtplusstringWidth = RDSSprite.textWidth(rtplusstring);
rtplusstringold = rtplusstring;
}
if(!screenmute) rtplusDisplay.update(rtplusstring, rtplusstringWidth, RDSstatus, RDSColor, RDSColorSmooth, RDSDropoutColor, RDSDropoutColorSmooth, BackgroundColor);
if (TPold != radio.rds.TP) { if (TPold != radio.rds.TP) {
if (!screenmute) { if (!screenmute) {
@@ -610,73 +597,14 @@ void showRadioText() {
String RTString = String(radio.rds.stationText + (radio.rds.stationText.length() > 0 ? " " : "") + radio.rds.stationText32 + (radio.rds.hasEnhancedRT ? " eRT: " + String(radio.rds.enhancedRTtext) : "") + " "); String RTString = String(radio.rds.stationText + (radio.rds.stationText.length() > 0 ? " " : "") + radio.rds.stationText32 + (radio.rds.hasEnhancedRT ? " eRT: " + String(radio.rds.enhancedRTtext) : "") + " ");
if (radio.rds.hasRT && radio.rds.rtAB != rtABold) { if (radio.rds.hasRT && radio.rds.rtAB != rtABold) {
xPos = 0; rtDisplay.reset();
rttickerhold = millis(); rttickerhold = millis();
rtABold = radio.rds.rtAB; rtABold = radio.rds.rtAB;
} }
if (!screenmute) { if (!screenmute && radio.rds.hasRT && (radio.rds.stationText.length() > 0 || radio.rds.stationText32.length() > 0)) rtDisplay.update(RTString, RDSstatus, RDSColor, RDSColorSmooth, RDSDropoutColor, RDSDropoutColorSmooth, BackgroundColor);
if (radio.rds.hasRT &&
(radio.rds.stationText.length() > 0 || radio.rds.stationText32.length() > 0)) {
if (RDSSprite.textWidth(trimTrailingSpaces(RTString)) < 270) {
xPos = 0;
FullLineSprite.fillSprite(BackgroundColor);
FullLineSprite.setTextDatum(TL_DATUM);
FullLineSprite.setTextColor(
RDSstatus ? RDSColor : RDSDropoutColor,
RDSstatus ? RDSColorSmooth : RDSDropoutColorSmooth,
false
);
FullLineSprite.drawString(RTString, xPos, 2);
FullLineSprite.fillRect(275, 0, 8, 19, BackgroundColor);
FullLineSprite.drawLine(283, 0, 283, 19, FrameColor);
if (radio.rds.hasRT) {
FullLineSprite.fillCircle(278, 3, 2, radio.rds.rtAB ? GreyoutColor : InsignificantColor);
FullLineSprite.fillCircle(278, 14, 2, radio.rds.rtAB ? InsignificantColor : GreyoutColor);
}
FullLineSprite.pushSprite(36, 220);
} else {
// Handle scrolling text
if (millis() - rtticker >= 15) {
if (xPos == 0 && millis() - rttickerhold < 1000) {
// Wait for a moment before scrolling
} else {
xPos--;
rttickerhold = millis(); // Update hold time only when xPos changes
}
if (xPos < -RadiotextWidth) xPos = 0; // Reset position if scrolled off
FullLineSprite.fillSprite(BackgroundColor);
FullLineSprite.setTextDatum(TL_DATUM);
FullLineSprite.setTextColor(
RDSstatus ? RDSColor : RDSDropoutColor,
RDSstatus ? RDSColorSmooth : RDSDropoutColorSmooth,
false
);
FullLineSprite.drawString(RTString, xPos, 2);
FullLineSprite.drawString(RTString, xPos + RadiotextWidth, 2);
FullLineSprite.fillRect(275, 0, 8, 19, BackgroundColor);
FullLineSprite.drawLine(283, 0, 283, 19, FrameColor);
if (radio.rds.hasRT) {
FullLineSprite.fillCircle(278, 3, 2, radio.rds.rtAB ? GreyoutColor : InsignificantColor);
FullLineSprite.fillCircle(278, 14, 2, radio.rds.rtAB ? InsignificantColor : GreyoutColor);
}
FullLineSprite.pushSprite(36, 220);
rtticker = millis();
}
}
}
}
if (RTold != RTString) { if (RTold != RTString) {
RadiotextWidth = FullLineSprite.textWidth(RTString);
if (wifi) { if (wifi) {
Udp.beginPacket(remoteip, 9030); Udp.beginPacket(remoteip, 9030);
Udp.print("from=TEF_tuner_" + String(stationlistid, DEC) + ";RT1="); Udp.print("from=TEF_tuner_" + String(stationlistid, DEC) + ";RT1=");