Add more dynamic variables and fix command manging

Add variables for TX Freq (t30), RX Freq (t32), CPU Temp (t20), and
Location (t31) to Base MMDVM page.   These variables are available with
Layout ON7LDS L3 or higher.  This allows more dynamic info to be
displayed without having to use the optional NextionDriver.  Note, this
doesn't add touch support. For that, use the NextionDriver.
Fixed command mangling occuring during serial writes to Nextion due to
no ready-state monitoring of display readiness.   Added simple thread
sleep to pace the commands as they are sent.  Allows the display a
chance to process the command before another one is blasted in.
Prevents mangling of commands sent before display is ready to accept
them.   Hardwired to 10 msec--let's see if that's enough.
Added setting in mmdvm conf file, Section: [Nextion]  Setting:
DisplayTempInFahrenheit   Value= 0 (default) for C.  1=Fahrenheit  This
controls the value sent to t20.
This commit is contained in:
KD4Z 2018-09-05 16:12:12 -04:00
parent 000ef35c13
commit ca35121b44
6 changed files with 105 additions and 21 deletions

View file

@ -228,6 +228,7 @@ m_nextionDisplayClock(false),
m_nextionUTC(false), m_nextionUTC(false),
m_nextionIdleBrightness(20U), m_nextionIdleBrightness(20U),
m_nextionScreenLayout(0U), m_nextionScreenLayout(0U),
m_nextionTempInFahrenheit(false),
m_oledType(3U), m_oledType(3U),
m_oledBrightness(0U), m_oledBrightness(0U),
m_oledInvert(false), m_oledInvert(false),
@ -757,6 +758,8 @@ bool CConf::read()
m_nextionIdleBrightness = (unsigned int)::atoi(value); m_nextionIdleBrightness = (unsigned int)::atoi(value);
else if (::strcmp(key, "ScreenLayout") == 0) else if (::strcmp(key, "ScreenLayout") == 0)
m_nextionScreenLayout = (unsigned int)::atoi(value); m_nextionScreenLayout = (unsigned int)::atoi(value);
else if (::strcmp(key, "DisplayTempInFahrenheit") == 0)
m_nextionTempInFahrenheit = ::atoi(value) == 1;
} else if (section == SECTION_OLED) { } else if (section == SECTION_OLED) {
if (::strcmp(key, "Type") == 0) if (::strcmp(key, "Type") == 0)
m_oledType = (unsigned char)::atoi(value); m_oledType = (unsigned char)::atoi(value);
@ -1676,3 +1679,8 @@ bool CConf::getLCDprocDimOnIdle() const
{ {
return m_lcdprocDimOnIdle; return m_lcdprocDimOnIdle;
} }
bool CConf::getNextionTempInFahrenheit() const
{
return m_nextionTempInFahrenheit;
}

4
Conf.h
View file

@ -245,6 +245,7 @@ public:
bool getNextionUTC() const; bool getNextionUTC() const;
unsigned int getNextionIdleBrightness() const; unsigned int getNextionIdleBrightness() const;
unsigned int getNextionScreenLayout() const; unsigned int getNextionScreenLayout() const;
bool getNextionTempInFahrenheit() const;
// The OLED section // The OLED section
unsigned char getOLEDType() const; unsigned char getOLEDType() const;
@ -453,7 +454,8 @@ private:
bool m_nextionUTC; bool m_nextionUTC;
unsigned int m_nextionIdleBrightness; unsigned int m_nextionIdleBrightness;
unsigned int m_nextionScreenLayout; unsigned int m_nextionScreenLayout;
bool m_nextionTempInFahrenheit;
unsigned char m_oledType; unsigned char m_oledType;
unsigned char m_oledBrightness; unsigned char m_oledBrightness;
bool m_oledInvert; bool m_oledInvert;

View file

@ -458,6 +458,7 @@ void CDisplay::writeNXDNRSSIInt(unsigned char rssi)
void CDisplay::writeNXDNBERInt(float ber) void CDisplay::writeNXDNBERInt(float ber)
{ {
} }
/* Factory method extracted from MMDVMHost.cpp - BG5HHP */ /* Factory method extracted from MMDVMHost.cpp - BG5HHP */
CDisplay* CDisplay::createDisplay(const CConf& conf, CUMP* ump, CModem* modem) CDisplay* CDisplay::createDisplay(const CConf& conf, CUMP* ump, CModem* modem)
@ -491,6 +492,9 @@ CDisplay* CDisplay::createDisplay(const CConf& conf, CUMP* ump, CModem* modem)
bool utc = conf.getNextionUTC(); bool utc = conf.getNextionUTC();
unsigned int idleBrightness = conf.getNextionIdleBrightness(); unsigned int idleBrightness = conf.getNextionIdleBrightness();
unsigned int screenLayout = conf.getNextionScreenLayout(); unsigned int screenLayout = conf.getNextionScreenLayout();
unsigned int txFrequency = conf.getTXFrequency();
unsigned int rxFrequency = conf.getRXFrequency();
bool displayTempInF = conf.getNextionTempInFahrenheit();
LogInfo(" Port: %s", port.c_str()); LogInfo(" Port: %s", port.c_str());
LogInfo(" Brightness: %u", brightness); LogInfo(" Brightness: %u", brightness);
@ -498,7 +502,8 @@ CDisplay* CDisplay::createDisplay(const CConf& conf, CUMP* ump, CModem* modem)
if (displayClock) if (displayClock)
LogInfo(" Display UTC: %s", utc ? "yes" : "no"); LogInfo(" Display UTC: %s", utc ? "yes" : "no");
LogInfo(" Idle Brightness: %u", idleBrightness); LogInfo(" Idle Brightness: %u", idleBrightness);
LogInfo(" Temperature in Fahrenheit: %s ", displayTempInF ? "yes" : "no");
switch (screenLayout) { switch (screenLayout) {
case 0U: case 0U:
LogInfo(" Screen Layout: G4KLX (Default)"); LogInfo(" Screen Layout: G4KLX (Default)");
@ -519,18 +524,22 @@ CDisplay* CDisplay::createDisplay(const CConf& conf, CUMP* ump, CModem* modem)
if (port == "modem") { if (port == "modem") {
ISerialPort* serial = new CModemSerialPort(modem); ISerialPort* serial = new CModemSerialPort(modem);
display = new CNextion(conf.getCallsign(), dmrid, serial, brightness, displayClock, utc, idleBrightness, screenLayout); display = new CNextion(conf.getCallsign(), dmrid, serial, brightness, displayClock, utc, idleBrightness, screenLayout, txFrequency, rxFrequency, displayTempInF, conf.getLocation());
} else if (port == "ump") { } else if (port == "ump") {
if (ump != NULL) if (ump != NULL) {
display = new CNextion(conf.getCallsign(), dmrid, ump, brightness, displayClock, utc, idleBrightness, screenLayout); display = new CNextion(conf.getCallsign(), dmrid, ump, brightness, displayClock, utc, idleBrightness, screenLayout, txFrequency, rxFrequency, displayTempInF, conf.getLocation());
else } else {
LogInfo(" NullDisplay loaded");
display = new CNullDisplay; display = new CNullDisplay;
}
} else { } else {
SERIAL_SPEED baudrate = SERIAL_9600; SERIAL_SPEED baudrate = SERIAL_9600;
if (screenLayout==4U) if (screenLayout==4U)
baudrate = SERIAL_115200; baudrate = SERIAL_115200;
LogInfo(" Display baudrate: %u ",baudrate);
ISerialPort* serial = new CSerialController(port, baudrate); ISerialPort* serial = new CSerialController(port, baudrate);
display = new CNextion(conf.getCallsign(), dmrid, serial, brightness, displayClock, utc, idleBrightness, screenLayout); display = new CNextion(conf.getCallsign(), dmrid, serial, brightness, displayClock, utc, idleBrightness, screenLayout, txFrequency, rxFrequency, displayTempInF, conf.getLocation());
} }
} else if (type == "LCDproc") { } else if (type == "LCDproc") {
std::string address = conf.getLCDprocAddress(); std::string address = conf.getLCDprocAddress();

View file

@ -38,7 +38,7 @@ const unsigned int P25_BER_COUNT = 7U; // 7 * 180ms = 1260ms
const unsigned int NXDN_RSSI_COUNT = 28U; // 28 * 40ms = 1120ms const unsigned int NXDN_RSSI_COUNT = 28U; // 28 * 40ms = 1120ms
const unsigned int NXDN_BER_COUNT = 28U; // 28 * 40ms = 1120ms const unsigned int NXDN_BER_COUNT = 28U; // 28 * 40ms = 1120ms
CNextion::CNextion(const std::string& callsign, unsigned int dmrid, ISerialPort* serial, unsigned int brightness, bool displayClock, bool utc, unsigned int idleBrightness, unsigned int 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, const std::string& location) :
CDisplay(), CDisplay(),
m_callsign(callsign), m_callsign(callsign),
m_ipaddress("(ip unknown)"), m_ipaddress("(ip unknown)"),
@ -58,7 +58,11 @@ m_berAccum2(0.0F),
m_rssiCount1(0U), m_rssiCount1(0U),
m_rssiCount2(0U), m_rssiCount2(0U),
m_berCount1(0U), m_berCount1(0U),
m_berCount2(0U) m_berCount2(0U),
m_txFrequency(txFrequency),
m_rxFrequency(rxFrequency),
m_displayTempInF(displayTempInF),
m_location(location)
{ {
assert(serial != NULL); assert(serial != NULL);
assert(brightness >= 0U && brightness <= 100U); assert(brightness >= 0U && brightness <= 100U);
@ -86,8 +90,14 @@ bool CNextion::open()
m_ipaddress = (char*)info; m_ipaddress = (char*)info;
sendCommand("bkcmd=0"); sendCommand("bkcmd=0");
sendCommandAction(0); sendCommandAction(0U);
m_fl_txFrequency = m_txFrequency;
m_fl_txFrequency/=1000000U;
m_fl_rxFrequency = m_rxFrequency;
m_fl_rxFrequency/=1000000U;
setIdle(); setIdle();
return true; return true;
@ -96,23 +106,58 @@ bool CNextion::open()
void CNextion::setIdleInt() void CNextion::setIdleInt()
{ {
// a few bits borrowed from Lieven De Samblanx ON7LDS, NextionDriver
char command[100U];
sendCommand("page MMDVM"); sendCommand("page MMDVM");
sendCommandAction(1U); sendCommandAction(1U);
char command[100U];
::sprintf(command, "dim=%u", m_idleBrightness); ::sprintf(command, "dim=%u", m_idleBrightness);
sendCommand(command); sendCommand(command);
::sprintf(command, "t0.txt=\"%s/%u\"", m_callsign.c_str(), m_dmrid); ::sprintf(command, "t0.txt=\"%s/%u\"", m_callsign.c_str(), m_dmrid);
sendCommand(command); sendCommand(command);
if (m_screenLayout > 2U) { if (m_screenLayout > 2U) {
::sprintf(command, "t4.txt=\"%s\"", m_callsign.c_str()); ::sprintf(command, "t4.txt=\"%s\"", m_callsign.c_str());
sendCommand(command); sendCommand(command);
::sprintf(command, "t5.txt=\"%u\"", m_dmrid); ::sprintf(command, "t5.txt=\"%u\"", m_dmrid);
sendCommand(command); sendCommand(command);
} sendCommandAction(17U);
sendCommandAction(17U);
::sprintf(command, "t30.txt=\"%3.4f\"",m_fl_rxFrequency); // RX freq
sendCommand(command);
sendCommandAction(20U);
::sprintf(command, "t32.txt=\"%3.4f\"",m_fl_txFrequency); // TX freq
sendCommand(command);
sendCommandAction(21U);
FILE *deviceInfoFile;
double val;
//CPU temperature
deviceInfoFile = fopen ("/sys/class/thermal/thermal_zone0/temp", "r");
if (deviceInfoFile != NULL) {
fscanf (deviceInfoFile, "%lf", &val);
fclose(deviceInfoFile);
val /= 1000;
if( m_displayTempInF){
val = (1.8 * val) + 32;
::sprintf(command, "t20.txt=\"%2.1f %cF\"", val, 176);
} else {
::sprintf(command, "t20.txt=\"%2.1f %cC\"", val, 176);
}
sendCommand(command);
sendCommandAction(22U);
}
::sprintf(command, "t31.txt=\"%s\"", m_location.c_str()); // location
sendCommand(command);
sendCommandAction(23U);
} else {
sendCommandAction(17U);
}
sendCommand("t1.txt=\"MMDVM IDLE\""); sendCommand("t1.txt=\"MMDVM IDLE\"");
sendCommandAction(11U); sendCommandAction(11U);
@ -454,6 +499,7 @@ void CNextion::writeDMRBERInt(unsigned int slotNo, float ber)
void CNextion::clearDMRInt(unsigned int slotNo) void CNextion::clearDMRInt(unsigned int slotNo)
{ {
if (slotNo == 1U) { if (slotNo == 1U) {
sendCommand("t0.txt=\"1 Listening\""); sendCommand("t0.txt=\"1 Listening\"");
sendCommandAction(61U); sendCommandAction(61U);
@ -777,7 +823,8 @@ void CNextion::close()
void CNextion::sendCommandAction(unsigned int status) void CNextion::sendCommandAction(unsigned int status)
{ {
if (m_screenLayout<3U) return; if (m_screenLayout<3U)
return;
char text[30U]; char text[30U];
::sprintf(text, "MMDVM.status.val=%d", status); ::sprintf(text, "MMDVM.status.val=%d", status);
@ -785,11 +832,14 @@ void CNextion::sendCommandAction(unsigned int status)
sendCommand("click S0,1"); sendCommand("click S0,1");
} }
void CNextion::sendCommand(const char* command) void CNextion::sendCommand(const char* command)
{ {
assert(command != NULL); assert(command != NULL);
m_serial->write((unsigned char*)command, (unsigned int)::strlen(command)); m_serial->write((unsigned char*)command, (unsigned int)::strlen(command));
m_serial->write((unsigned char*)"\xFF\xFF\xFF", 3U); m_serial->write((unsigned char*)"\xFF\xFF\xFF", 3U);
} // Since we just firing commands at the display, and not listening for the response,
// we must add a bit of a delay to allow the display to process the commands, else some are getting mangled.
// 10 ms is just a guess, but seems to be sufficient.
CThread::sleep(10U);
}

View file

@ -23,13 +23,13 @@
#include "Defines.h" #include "Defines.h"
#include "SerialPort.h" #include "SerialPort.h"
#include "Timer.h" #include "Timer.h"
#include "Thread.h"
#include <string> #include <string>
class CNextion : public CDisplay class CNextion : public CDisplay
{ {
public: public:
CNextion(const std::string& callsign, unsigned int dmrid, ISerialPort* serial, unsigned int brightness, bool displayClock, bool utc, unsigned int idleBrightness, unsigned int screenLayout); 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, const std::string& location);
virtual ~CNextion(); virtual ~CNextion();
virtual bool open(); virtual bool open();
@ -97,7 +97,13 @@ private:
unsigned int m_rssiCount2; unsigned int m_rssiCount2;
unsigned int m_berCount1; unsigned int m_berCount1;
unsigned int m_berCount2; unsigned int m_berCount2;
unsigned int m_txFrequency;
unsigned int m_rxFrequency;
float m_fl_txFrequency=0;
float m_fl_rxFrequency=0;
bool m_displayTempInF;
std::string m_location;
void sendCommand(const char* command); void sendCommand(const char* command);
void sendCommandAction(unsigned int status); void sendCommandAction(unsigned int status);
}; };

View file

@ -104,6 +104,10 @@ changed field.
16 : IPaddress 16 : IPaddress
17 : ID/Call (t0 and t4,t5 are sent) 17 : ID/Call (t0 and t4,t5 are sent)
19 : END 19 : END
20 : RX Frequency
21 : TX Frequency
22 : Temperature
23 : Location
41 : D-Star listening 41 : D-Star listening
42 : type/my1/my2 42 : type/my1/my2
@ -161,10 +165,15 @@ t0 : owner call & ID / errortext LOCKOUT
t1 : status / ERROR t1 : status / ERROR
t2 : date & time t2 : date & time
screenLayout >1 :
screenLayout >2 :
t3 : ip address t3 : ip address
t4 : owner call t4 : owner call
t5 : owner ID t5 : owner ID
t20 : CPU Temperature in C. ( Can be changed to F in mmdmvhost config setting: [NEXTION] Section, Setting=DisplayTempInFahrenheit=1)
t30 : RX Frequency
t31 : Location
t32 : TX Frequency
D-Star D-Star