From 0e8788bdbec3314695fe367b4d9a85c7ba4b9738 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Fri, 23 Feb 2024 15:44:54 +0000 Subject: [PATCH] Insert a back channel to Nextion displays running via the modem. --- Conf.cpp | 26 +++++++++++++++---- Conf.h | 32 +++++++++++++---------- Display.cpp | 34 ++++++++++++++++++++++--- MMDVM.ini | 3 +++ Nextion.cpp | 73 +++++++++++++++++++++++++++++++++++++++++++++++++++-- Nextion.h | 7 ++++- Version.h | 2 +- 7 files changed, 151 insertions(+), 26 deletions(-) diff --git a/Conf.cpp b/Conf.cpp index ca686dbb..03e881ac 100644 --- a/Conf.cpp +++ b/Conf.cpp @@ -326,6 +326,8 @@ m_nextionUTC(false), m_nextionIdleBrightness(20U), m_nextionScreenLayout(0U), m_nextionTempInFahrenheit(false), +m_nextionOutput(false), +m_nextionUDPPort(6759), m_oledType(3U), m_oledBrightness(0U), m_oledInvert(false), @@ -1118,6 +1120,10 @@ bool CConf::read() m_nextionScreenLayout = (unsigned int)::strtoul(value, NULL, 0); else if (::strcmp(key, "DisplayTempInFahrenheit") == 0) m_nextionTempInFahrenheit = ::atoi(value) == 1; + else if (::strcmp(key, "NextionOutput") == 0) + m_nextionOutput = ::atoi(value) == 1; + else if (::strcmp(key, "NextionUDPPort") == 0) + m_nextionUDPPort = (unsigned short)::atoi(value); } else if (section == SECTION_OLED) { if (::strcmp(key, "Type") == 0) m_oledType = (unsigned char)::atoi(value); @@ -2457,6 +2463,21 @@ unsigned int CConf::getNextionScreenLayout() const return m_nextionScreenLayout; } +bool CConf::getNextionTempInFahrenheit() const +{ + return m_nextionTempInFahrenheit; +} + +bool CConf::getNextionOutput() const +{ + return m_nextionOutput; +} + +unsigned short CConf::getNextionUDPPort() const +{ + return m_nextionUDPPort; +} + unsigned char CConf::getOLEDType() const { return m_oledType; @@ -2517,11 +2538,6 @@ bool CConf::getLCDprocDimOnIdle() const return m_lcdprocDimOnIdle; } -bool CConf::getNextionTempInFahrenheit() const -{ - return m_nextionTempInFahrenheit; -} - bool CConf::getLockFileEnabled() const { return m_lockFileEnabled; diff --git a/Conf.h b/Conf.h index 2cd756b2..e3d9d1ef 100644 --- a/Conf.h +++ b/Conf.h @@ -340,13 +340,15 @@ class CConf bool getHD44780UTC() const; // The Nextion section - std::string getNextionPort() const; - unsigned int getNextionBrightness() const; - bool getNextionDisplayClock() const; - bool getNextionUTC() const; - unsigned int getNextionIdleBrightness() const; - unsigned int getNextionScreenLayout() const; - bool getNextionTempInFahrenheit() const; + std::string getNextionPort() const; + unsigned int getNextionBrightness() const; + bool getNextionDisplayClock() const; + bool getNextionUTC() const; + unsigned int getNextionIdleBrightness() const; + unsigned int getNextionScreenLayout() const; + bool getNextionTempInFahrenheit() const; + bool getNextionOutput() const; + unsigned short getNextionUDPPort() const; // The OLED section unsigned char getOLEDType() const; @@ -656,13 +658,15 @@ class CConf bool m_hd44780DisplayClock; bool m_hd44780UTC; - std::string m_nextionPort; - unsigned int m_nextionBrightness; - bool m_nextionDisplayClock; - bool m_nextionUTC; - unsigned int m_nextionIdleBrightness; - unsigned int m_nextionScreenLayout; - bool m_nextionTempInFahrenheit; + std::string m_nextionPort; + unsigned int m_nextionBrightness; + bool m_nextionDisplayClock; + bool m_nextionUTC; + unsigned int m_nextionIdleBrightness; + unsigned int m_nextionScreenLayout; + bool m_nextionTempInFahrenheit; + bool m_nextionOutput; + unsigned short m_nextionUDPPort; unsigned char m_oledType; unsigned char m_oledBrightness; diff --git a/Display.cpp b/Display.cpp index 9d20773f..ab0c0bb8 100644 --- a/Display.cpp +++ b/Display.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2016,2017,2018,2020,2021,2023 by Jonathan Naylor G4KLX + * Copyright (C) 2016,2017,2018,2020,2021,2023,2024 by Jonathan Naylor G4KLX * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -22,6 +22,7 @@ #include "ModemSerialPort.h" #include "NullDisplay.h" #include "TFTSurenoo.h" +#include "UDPSocket.h" #include "LCDproc.h" #include "Nextion.h" #include "CASTInfo.h" @@ -604,8 +605,35 @@ CDisplay* CDisplay::createDisplay(const CConf& conf, CModem* modem) } if (port == "modem") { - ISerialPort* serial = new IModemSerialPort(modem); - display = new CNextion(conf.getCallsign(), dmrid, serial, brightness, displayClock, utc, idleBrightness, screenLayout, txFrequency, rxFrequency, displayTempInF); + CUDPSocket* socket = NULL; + struct sockaddr_storage addr; + unsigned int addrLength = 0U; + + bool nextionOutput = conf.getNextionOutput(); + if (nextionOutput) { + unsigned short nextionUDPPort = conf.getNextionUDPPort(); + + LogInfo(" Output Port: %u", nextionUDPPort); + + CUDPSocket::lookup("127.0.0.1", nextionUDPPort, addr, addrLength); + + if (addrLength > 0U) { + socket = new CUDPSocket("127.0.0.1", nextionUDPPort - 1U); + bool ret = socket->open(addr); + if (!ret) { + delete socket; + socket = NULL; + } + } + } + + if (socket == NULL) { + ISerialPort* serial = new IModemSerialPort(modem); + display = new CNextion(conf.getCallsign(), dmrid, serial, brightness, displayClock, utc, idleBrightness, screenLayout, txFrequency, rxFrequency, displayTempInF); + } else { + ISerialPort* serial = new IModemSerialPort(modem); + display = new CNextion(conf.getCallsign(), dmrid, serial, brightness, displayClock, utc, idleBrightness, screenLayout, txFrequency, rxFrequency, displayTempInF, socket, addr, addrLength); + } } else { unsigned int baudrate = 9600U; if (screenLayout == 4U) diff --git a/MMDVM.ini b/MMDVM.ini index 7883cf48..6b5697eb 100644 --- a/MMDVM.ini +++ b/MMDVM.ini @@ -345,6 +345,9 @@ UTC=0 #Screen Layout: 0=G4KLX 2=ON7LDS ScreenLayout=2 IdleBrightness=20 +# Output data from the Nextion +NextionOutput=0 +NextionPort=6759 [OLED] Type=3 diff --git a/Nextion.cpp b/Nextion.cpp index a48aa71d..8956304c 100644 --- a/Nextion.cpp +++ b/Nextion.cpp @@ -1,5 +1,5 @@ /* - * Copyright (C) 2016,2017,2018,2020,2023 by Jonathan Naylor G4KLX + * Copyright (C) 2016,2017,2018,2020,2023,2024 by Jonathan Naylor G4KLX * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -49,6 +49,59 @@ const unsigned int M17_BER_COUNT = 28U; // 28 * 40ms = 1120ms // 00:low, others:high-speed. bit[2] is overlapped with LAYOUT_COMPAT_MASK. #define LAYOUT_HIGHSPEED (3 << 2) +CNextion::CNextion(const std::string& callsign, unsigned int dmrid, ISerialPort* serial, unsigned int brightness, bool displayClock, bool utc, unsigned int idleBrightness, unsigned int screenLayout, unsigned int txFrequency, unsigned int rxFrequency, bool displayTempInF, CUDPSocket* socket, struct sockaddr_storage& addr, unsigned int addrLength) : +CDisplay(), +m_callsign(callsign), +m_ipaddress("(ip unknown)"), +m_dmrid(dmrid), +m_serial(serial), +m_brightness(brightness), +m_mode(MODE_IDLE), +m_displayClock(displayClock), +m_utc(utc), +m_idleBrightness(idleBrightness), +m_screenLayout(0), +m_clockDisplayTimer(1000U, 0U, 400U), +m_rssiAccum1(0U), +m_rssiAccum2(0U), +m_berAccum1(0.0F), +m_berAccum2(0.0F), +m_rssiCount1(0U), +m_rssiCount2(0U), +m_berCount1(0U), +m_berCount2(0U), +m_txFrequency(txFrequency), +m_rxFrequency(rxFrequency), +m_fl_txFrequency(0.0F), +m_fl_rxFrequency(0.0F), +m_displayTempInF(displayTempInF), +m_socket(socket), +m_addr(addr), +m_addrLength(addrLength) +{ + assert(serial != NULL); + assert(brightness >= 0U && brightness <= 100U); + assert(socket != NULL); + assert(addrLength > 0U); + + static const unsigned int feature_set[] = { + 0, // 0: G4KLX + 0, // 1: (reserved, low speed) + // 2: ON7LDS + LAYOUT_TA_ENABLE | LAYOUT_TA_COLOUR | LAYOUT_TA_FONTSIZE, + LAYOUT_TA_ENABLE | LAYOUT_DIY, // 3: ON7LDS-DIY + LAYOUT_TA_ENABLE | LAYOUT_DIY, // 4: ON7LDS-DIY (high speed) + 0, // 5: (reserved, high speed) + 0, // 6: (reserved, high speed) + 0, // 7: (reserved, high speed) + }; + + if (screenLayout & ~LAYOUT_COMPAT_MASK) + m_screenLayout = screenLayout & ~LAYOUT_COMPAT_MASK; + else + m_screenLayout = feature_set[screenLayout]; +} + CNextion::CNextion(const std::string& callsign, unsigned int dmrid, ISerialPort* serial, unsigned int brightness, bool displayClock, bool utc, unsigned int idleBrightness, unsigned int screenLayout, unsigned int txFrequency, unsigned int rxFrequency, bool displayTempInF) : CDisplay(), m_callsign(callsign), @@ -74,7 +127,10 @@ m_txFrequency(txFrequency), m_rxFrequency(rxFrequency), m_fl_txFrequency(0.0F), m_fl_rxFrequency(0.0F), -m_displayTempInF(displayTempInF) +m_displayTempInF(displayTempInF), +m_socket(NULL), +m_addr(), +m_addrLength(0U) { assert(serial != NULL); assert(brightness >= 0U && brightness <= 100U); @@ -968,12 +1024,25 @@ void CNextion::clockInt(unsigned int ms) m_clockDisplayTimer.start(); // restart the clock display timer } + + if (m_socket != NULL) { + unsigned char buffer[200U]; + + int len = m_serial->read(buffer, 200U); + if (len > 0) + m_socket->write(buffer, len, m_addr, m_addrLength); + } } void CNextion::close() { m_serial->close(); delete m_serial; + + if (m_socket != NULL) { + m_socket->close(); + delete m_socket; + } } void CNextion::sendCommandAction(unsigned int status) diff --git a/Nextion.h b/Nextion.h index 27820972..d488c8eb 100644 --- a/Nextion.h +++ b/Nextion.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2016,2017,2018,2020,2023 by Jonathan Naylor G4KLX + * Copyright (C) 2016,2017,2018,2020,2023,2024 by Jonathan Naylor G4KLX * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -22,6 +22,7 @@ #include "Display.h" #include "Defines.h" #include "SerialPort.h" +#include "UDPSocket.h" #include "Timer.h" #include "Thread.h" #include @@ -29,6 +30,7 @@ class CNextion : public CDisplay { public: + CNextion(const std::string& callsign, unsigned int dmrid, ISerialPort* serial, unsigned int brightness, bool displayClock, bool utc, unsigned int idleBrightness, unsigned int screenLayout, unsigned int txFrequency, unsigned int rxFrequency, bool displayTempInF, CUDPSocket* socket, struct sockaddr_storage& addr, unsigned int addrLength); CNextion(const std::string& callsign, unsigned int dmrid, ISerialPort* serial, unsigned int brightness, bool displayClock, bool utc, unsigned int idleBrightness, unsigned int screenLayout, unsigned int txFrequency, unsigned int rxFrequency, bool displayTempInF); virtual ~CNextion(); @@ -107,6 +109,9 @@ class CNextion : public CDisplay double m_fl_txFrequency; double m_fl_rxFrequency; bool m_displayTempInF; + CUDPSocket* m_socket; + struct sockaddr_storage m_addr; + unsigned int m_addrLength; void sendCommand(const char* command); void sendCommandAction(unsigned int status); diff --git a/Version.h b/Version.h index 85c1d9f2..20b0fc67 100644 --- a/Version.h +++ b/Version.h @@ -19,6 +19,6 @@ #if !defined(VERSION_H) #define VERSION_H -const char* VERSION = "20240207"; +const char* VERSION = "20240223"; #endif