mirror of https://github.com/g4klx/MMDVMHost
Merge pull request #343 from on7lds/devel
DMR TA & GPS decoding; Nextion Displays refinements
This commit is contained in:
commit
4e6bfb3682
8
Conf.cpp
8
Conf.cpp
|
|
@ -184,6 +184,7 @@ m_nextionBrightness(50U),
|
|||
m_nextionDisplayClock(false),
|
||||
m_nextionUTC(false),
|
||||
m_nextionIdleBrightness(20U),
|
||||
m_nextionScreenLayout(0U),
|
||||
m_oledType(3U),
|
||||
m_oledBrightness(0U),
|
||||
m_oledInvert(false),
|
||||
|
|
@ -612,6 +613,8 @@ bool CConf::read()
|
|||
m_nextionUTC = ::atoi(value) == 1;
|
||||
else if (::strcmp(key, "IdleBrightness") == 0)
|
||||
m_nextionIdleBrightness = (unsigned int)::atoi(value);
|
||||
else if (::strcmp(key, "ScreenLayout") == 0)
|
||||
m_nextionScreenLayout = (unsigned int)::atoi(value);
|
||||
} else if (section == SECTION_OLED) {
|
||||
if (::strcmp(key, "Type") == 0)
|
||||
m_oledType = (unsigned char)::atoi(value);
|
||||
|
|
@ -1292,6 +1295,11 @@ unsigned int CConf::getNextionIdleBrightness() const
|
|||
return m_nextionIdleBrightness;
|
||||
}
|
||||
|
||||
unsigned int CConf::getNextionScreenLayout() const
|
||||
{
|
||||
return m_nextionScreenLayout;
|
||||
}
|
||||
|
||||
unsigned char CConf::getOLEDType() const
|
||||
{
|
||||
return m_oledType;
|
||||
|
|
|
|||
2
Conf.h
2
Conf.h
|
|
@ -195,6 +195,7 @@ public:
|
|||
bool getNextionDisplayClock() const;
|
||||
bool getNextionUTC() const;
|
||||
unsigned int getNextionIdleBrightness() const;
|
||||
unsigned int getNextionScreenLayout() const;
|
||||
|
||||
// The OLED section
|
||||
unsigned char getOLEDType() const;
|
||||
|
|
@ -359,6 +360,7 @@ private:
|
|||
bool m_nextionDisplayClock;
|
||||
bool m_nextionUTC;
|
||||
unsigned int m_nextionIdleBrightness;
|
||||
unsigned int m_nextionScreenLayout;
|
||||
|
||||
unsigned char m_oledType;
|
||||
unsigned char m_oledBrightness;
|
||||
|
|
|
|||
83
DMRSlot.cpp
83
DMRSlot.cpp
|
|
@ -77,6 +77,7 @@ m_rfEmbeddedData(NULL),
|
|||
m_rfEmbeddedReadN(0U),
|
||||
m_rfEmbeddedWriteN(1U),
|
||||
m_rfTalkerId(TALKER_ID_NONE),
|
||||
m_rfTalkerAlias(NULL),
|
||||
m_netEmbeddedLC(),
|
||||
m_netEmbeddedData(NULL),
|
||||
m_netEmbeddedReadN(0U),
|
||||
|
|
@ -113,6 +114,7 @@ m_aveRSSI(0U),
|
|||
m_rssiCount(0U),
|
||||
m_fp(NULL)
|
||||
{
|
||||
m_rfTalkerAlias = new unsigned char[32U];
|
||||
m_lastFrame = new unsigned char[DMR_FRAME_LENGTH_BYTES + 2U];
|
||||
|
||||
m_rfEmbeddedData = new CDMREmbeddedData[2U];
|
||||
|
|
@ -331,7 +333,7 @@ bool CDMRSlot::writeModem(unsigned char *data, unsigned int len)
|
|||
LogMessage("DMR Slot %u, received RF end of voice transmission, %.1f seconds, BER: %.1f%%, RSSI: -%u/-%u/-%u dBm", m_slotNo, float(m_rfFrames) / 16.667F, float(m_rfErrs * 100U) / float(m_rfBits), m_minRSSI, m_maxRSSI, m_aveRSSI / m_rssiCount);
|
||||
else
|
||||
LogMessage("DMR Slot %u, received RF end of voice transmission, %.1f seconds, BER: %.1f%%", m_slotNo, float(m_rfFrames) / 16.667F, float(m_rfErrs * 100U) / float(m_rfBits));
|
||||
|
||||
m_display->writeDMRTA(m_slotNo,NULL," ");
|
||||
if (m_rfTimeout) {
|
||||
writeEndRF();
|
||||
return false;
|
||||
|
|
@ -606,6 +608,7 @@ bool CDMRSlot::writeModem(unsigned char *data, unsigned int len)
|
|||
if (m_dumpTAData) {
|
||||
::sprintf(text, "DMR Slot %u, Embedded GPS Info", m_slotNo);
|
||||
CUtils::dump(2U, text, data, 9U);
|
||||
logGPSposition(data);
|
||||
}
|
||||
if (m_network != NULL)
|
||||
m_network->writePosition(m_rfLC->getSrcId(), data);
|
||||
|
|
@ -616,6 +619,9 @@ bool CDMRSlot::writeModem(unsigned char *data, unsigned int len)
|
|||
m_network->writeTalkerAlias(m_rfLC->getSrcId(), 0U, data);
|
||||
|
||||
if (!(m_rfTalkerId & TALKER_ID_HEADER)) {
|
||||
if (m_rfTalkerId==TALKER_ID_NONE) memset(m_rfTalkerAlias,0,32U);
|
||||
::memcpy(m_rfTalkerAlias, data, 6U);
|
||||
m_display->writeDMRTA(m_slotNo, m_rfTalkerAlias,"R");
|
||||
if (m_dumpTAData) {
|
||||
::sprintf(text, "DMR Slot %u, Embedded Talker Alias Header", m_slotNo);
|
||||
CUtils::dump(2U, text, data, 9U);
|
||||
|
|
@ -630,6 +636,9 @@ bool CDMRSlot::writeModem(unsigned char *data, unsigned int len)
|
|||
m_network->writeTalkerAlias(m_rfLC->getSrcId(), 1U, data);
|
||||
|
||||
if (!(m_rfTalkerId & TALKER_ID_BLOCK1)) {
|
||||
if (m_rfTalkerId==TALKER_ID_NONE) memset(m_rfTalkerAlias,0,32U);
|
||||
::memcpy(m_rfTalkerAlias+6U, data, 7U);
|
||||
m_display->writeDMRTA(m_slotNo, m_rfTalkerAlias,"R");
|
||||
if (m_dumpTAData) {
|
||||
::sprintf(text, "DMR Slot %u, Embedded Talker Alias Block 1", m_slotNo);
|
||||
CUtils::dump(2U, text, data, 9U);
|
||||
|
|
@ -644,6 +653,10 @@ bool CDMRSlot::writeModem(unsigned char *data, unsigned int len)
|
|||
m_network->writeTalkerAlias(m_rfLC->getSrcId(), 2U, data);
|
||||
|
||||
if (!(m_rfTalkerId & TALKER_ID_BLOCK2)) {
|
||||
if (m_rfTalkerId==TALKER_ID_NONE) memset(m_rfTalkerAlias,0,32U);
|
||||
m_rfTalkerId |= TALKER_ID_BLOCK2;
|
||||
::memcpy(m_rfTalkerAlias+6U+7U, data, 7U);
|
||||
m_display->writeDMRTA(m_slotNo, m_rfTalkerAlias,"R");
|
||||
if (m_dumpTAData) {
|
||||
::sprintf(text, "DMR Slot %u, Embedded Talker Alias Block 2", m_slotNo);
|
||||
CUtils::dump(2U, text, data, 9U);
|
||||
|
|
@ -658,6 +671,9 @@ bool CDMRSlot::writeModem(unsigned char *data, unsigned int len)
|
|||
m_network->writeTalkerAlias(m_rfLC->getSrcId(), 3U, data);
|
||||
|
||||
if (!(m_rfTalkerId & TALKER_ID_BLOCK3)) {
|
||||
if (m_rfTalkerId==TALKER_ID_NONE) ::memset(m_rfTalkerAlias,0,32U);
|
||||
::memcpy(m_rfTalkerAlias+6U+7U+7U, data, 7U);
|
||||
m_display->writeDMRTA(m_slotNo, m_rfTalkerAlias,"R");
|
||||
if (m_dumpTAData) {
|
||||
::sprintf(text, "DMR Slot %u, Embedded Talker Alias Block 3", m_slotNo);
|
||||
CUtils::dump(2U, text, data, 9U);
|
||||
|
|
@ -1170,7 +1186,7 @@ void CDMRSlot::writeNetwork(const CDMRData& dmrData)
|
|||
// We've received the voice header and terminator haven't we?
|
||||
m_netFrames += 2U;
|
||||
LogMessage("DMR Slot %u, received network end of voice transmission, %.1f seconds, %u%% packet loss, BER: %.1f%%", m_slotNo, float(m_netFrames) / 16.667F, (m_netLost * 100U) / m_netFrames, float(m_netErrs * 100U) / float(m_netBits));
|
||||
|
||||
m_display->writeDMRTA(m_slotNo,NULL," ");
|
||||
writeEndNet();
|
||||
} else if (dataType == DT_DATA_HEADER) {
|
||||
if (m_netState == RS_NET_DATA)
|
||||
|
|
@ -1377,10 +1393,14 @@ void CDMRSlot::writeNetwork(const CDMRData& dmrData)
|
|||
if (m_dumpTAData) {
|
||||
::sprintf(text, "DMR Slot %u, Embedded GPS Info", m_slotNo);
|
||||
CUtils::dump(2U, text, data, 9U);
|
||||
logGPSposition(data);
|
||||
}
|
||||
break;
|
||||
case FLCO_TALKER_ALIAS_HEADER:
|
||||
if (!(m_netTalkerId & TALKER_ID_HEADER)) {
|
||||
if (!m_netTalkerId) memset(m_rfTalkerAlias,0,32U);
|
||||
::memcpy(m_rfTalkerAlias, data+2U, 7U);
|
||||
m_display->writeDMRTA(m_slotNo, m_rfTalkerAlias,"N");
|
||||
if (m_dumpTAData) {
|
||||
::sprintf(text, "DMR Slot %u, Embedded Talker Alias Header", m_slotNo);
|
||||
CUtils::dump(2U, text, data, 9U);
|
||||
|
|
@ -1391,6 +1411,9 @@ void CDMRSlot::writeNetwork(const CDMRData& dmrData)
|
|||
break;
|
||||
case FLCO_TALKER_ALIAS_BLOCK1:
|
||||
if (!(m_netTalkerId & TALKER_ID_BLOCK1)) {
|
||||
if (!m_netTalkerId) memset(m_rfTalkerAlias,0,32U);
|
||||
::memcpy(m_rfTalkerAlias+7U, data+2U, 7U);
|
||||
m_display->writeDMRTA(m_slotNo, m_rfTalkerAlias,"N");
|
||||
if (m_dumpTAData) {
|
||||
::sprintf(text, "DMR Slot %u, Embedded Talker Alias Block 1", m_slotNo);
|
||||
CUtils::dump(2U, text, data, 9U);
|
||||
|
|
@ -1401,6 +1424,9 @@ void CDMRSlot::writeNetwork(const CDMRData& dmrData)
|
|||
break;
|
||||
case FLCO_TALKER_ALIAS_BLOCK2:
|
||||
if (!(m_netTalkerId & TALKER_ID_BLOCK2)) {
|
||||
if (!m_netTalkerId) ::memset(m_rfTalkerAlias,0,32U);
|
||||
::memcpy(m_rfTalkerAlias+7U+7U, data+2U, 7U);
|
||||
m_display->writeDMRTA(m_slotNo, m_rfTalkerAlias,"N");
|
||||
if (m_dumpTAData) {
|
||||
::sprintf(text, "DMR Slot %u, Embedded Talker Alias Block 2", m_slotNo);
|
||||
CUtils::dump(2U, text, data, 9U);
|
||||
|
|
@ -1411,6 +1437,9 @@ void CDMRSlot::writeNetwork(const CDMRData& dmrData)
|
|||
break;
|
||||
case FLCO_TALKER_ALIAS_BLOCK3:
|
||||
if (!(m_netTalkerId & TALKER_ID_BLOCK3)) {
|
||||
if (!m_netTalkerId) memset(m_rfTalkerAlias,0,32U);
|
||||
::memcpy(m_rfTalkerAlias+7U+7U+7U, data+2U, 7U);
|
||||
m_display->writeDMRTA(m_slotNo, m_rfTalkerAlias,"N");
|
||||
if (m_dumpTAData) {
|
||||
::sprintf(text, "DMR Slot %u, Embedded Talker Alias Block 3", m_slotNo);
|
||||
CUtils::dump(2U, text, data, 9U);
|
||||
|
|
@ -1587,6 +1616,56 @@ void CDMRSlot::writeNetwork(const CDMRData& dmrData)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
void CDMRSlot::logGPSposition(const unsigned char* data)
|
||||
{
|
||||
signed long longitudeI,latitudeI;
|
||||
unsigned int errorI;
|
||||
float longitude,latitude;
|
||||
char errorS[30];
|
||||
|
||||
errorI=((data[2U]&0x0E) >> 1U);
|
||||
switch (errorI) {
|
||||
case 0U:
|
||||
::sprintf(errorS, "< 2m");
|
||||
break;
|
||||
case 1U:
|
||||
::sprintf(errorS, "< 20m");
|
||||
break;
|
||||
case 2U:
|
||||
::sprintf(errorS, "< 200m");
|
||||
break;
|
||||
case 3U:
|
||||
::sprintf(errorS, "< 2km");
|
||||
break;
|
||||
case 4U:
|
||||
::sprintf(errorS, "< 20km");
|
||||
break;
|
||||
case 5U:
|
||||
::sprintf(errorS, "< 200km");
|
||||
break;
|
||||
case 6U:
|
||||
::sprintf(errorS, "> 200km");
|
||||
break;
|
||||
default:
|
||||
::sprintf(errorS, "not known or position invalid");
|
||||
break;
|
||||
}
|
||||
|
||||
longitudeI=(data[3U]<<16U)+(data[4U]<<8U)+(data[5U]);
|
||||
if ((data[2]&0x01U)==0x01U) longitudeI=-longitudeI;
|
||||
|
||||
latitudeI=((data[6U]&0x7FU)<<16U)+(data[7U]<<8U)+(data[8U]);
|
||||
if ((data[6U]&0x80U)==0x80U) latitudeI=-latitudeI;
|
||||
|
||||
longitude=(float)360/33554432; // 360/2^25 steps
|
||||
latitude=(float)180/16777216; // 180/2^24 steps
|
||||
|
||||
longitude*=longitudeI;
|
||||
latitude*=latitudeI;
|
||||
LogMessage("GPS position [%08f,%09f] (Position error %s)",latitude,longitude,errorS);
|
||||
}
|
||||
|
||||
void CDMRSlot::clock()
|
||||
{
|
||||
unsigned int ms = m_interval.elapsed();
|
||||
|
|
|
|||
|
|
@ -69,6 +69,7 @@ private:
|
|||
unsigned int m_rfEmbeddedReadN;
|
||||
unsigned int m_rfEmbeddedWriteN;
|
||||
unsigned char m_rfTalkerId;
|
||||
unsigned char* m_rfTalkerAlias;
|
||||
CDMREmbeddedData m_netEmbeddedLC;
|
||||
CDMREmbeddedData* m_netEmbeddedData;
|
||||
unsigned int m_netEmbeddedReadN;
|
||||
|
|
@ -131,6 +132,8 @@ private:
|
|||
static unsigned char m_id2;
|
||||
static ACTIVITY_TYPE m_activity2;
|
||||
|
||||
void logGPSposition(const unsigned char* data);
|
||||
|
||||
void writeQueueRF(const unsigned char* data);
|
||||
void writeQueueNet(const unsigned char* data);
|
||||
void writeNetworkRF(const unsigned char* data, unsigned char dataType, unsigned char errors = 0U);
|
||||
|
|
|
|||
56
Display.cpp
56
Display.cpp
|
|
@ -18,14 +18,15 @@
|
|||
|
||||
#include "Display.h"
|
||||
#include "Defines.h"
|
||||
#include "Log.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
|
||||
CDisplay::CDisplay() :
|
||||
m_timer1(1000U, 3U),
|
||||
m_timer2(1000U, 3U),
|
||||
m_timer1(3000U, 3U),
|
||||
m_timer2(3000U, 3U),
|
||||
m_mode1(MODE_IDLE),
|
||||
m_mode2(MODE_IDLE)
|
||||
{
|
||||
|
|
@ -117,7 +118,6 @@ void CDisplay::writeDMR(unsigned int slotNo, const std::string& src, bool group,
|
|||
m_timer2.start();
|
||||
m_mode2 = MODE_IDLE;
|
||||
}
|
||||
|
||||
writeDMRInt(slotNo, src, group, dst, type);
|
||||
}
|
||||
|
||||
|
|
@ -127,11 +127,55 @@ void CDisplay::writeDMRRSSI(unsigned int slotNo, unsigned char rssi)
|
|||
writeDMRRSSIInt(slotNo, rssi);
|
||||
}
|
||||
|
||||
void CDisplay::writeDMRTA(unsigned int slotNo, unsigned char* talkerAlias, const char* type)
|
||||
{
|
||||
char TA[32U];
|
||||
unsigned char *b;
|
||||
unsigned char c;
|
||||
int j;
|
||||
unsigned int i,t1,t2, TAsize, TAformat;
|
||||
|
||||
if (strcmp(type," ")==0) { writeDMRTAInt(slotNo, (unsigned char*)TA, type); return; }
|
||||
|
||||
TAformat=(talkerAlias[0]>>6U) & 0x03U;
|
||||
TAsize = (talkerAlias[0]>>1U) & 0x1FU;
|
||||
::strcpy(TA,"(could not decode)");
|
||||
switch (TAformat) {
|
||||
case 0U: // 7 bit
|
||||
::memset (&TA,0,32U);
|
||||
b=&talkerAlias[0];
|
||||
t1=0; t2=0; c=0;
|
||||
for (i=0;(i<32U)&&(t2<TAsize);i++) {
|
||||
for (j=7U;j>=0;j--) {
|
||||
c = (c<<1U) | (b[i] >> j);
|
||||
if (++t1==7U) { if (i>0) {TA[t2++]=c & 0x7FU; } t1=0; c=0; }
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 1U: // ISO 8 bit
|
||||
case 2U: // UTF8
|
||||
::strcpy(TA,(char*)talkerAlias+1U);
|
||||
break;
|
||||
case 3U: // UTF16 poor man's conversion
|
||||
t2=0;
|
||||
::memset (&TA,0,32U);
|
||||
for(i=0;(i<15)&&(t2<TAsize);i++) {
|
||||
if (talkerAlias[2U*i+1U]==0)
|
||||
TA[t2++]=talkerAlias[2U*i+2U]; else TA[t2++]='?';
|
||||
}
|
||||
TA[TAsize]=0;
|
||||
break;
|
||||
}
|
||||
LogMessage("DMR Talker Alias (Data Format %u, Received %u/%u char): '%s'", TAformat, ::strlen(TA), TAsize, TA);
|
||||
if (::strlen(TA)>TAsize) { if (strlen(TA)<29U) strcat(TA," ?"); else strcpy(TA+28U," ?"); }
|
||||
if (strlen((char*)TA)>=4U) writeDMRTAInt(slotNo, (unsigned char*)TA, type);
|
||||
|
||||
}
|
||||
|
||||
void CDisplay::writeDMRBER(unsigned int slotNo, float ber)
|
||||
{
|
||||
writeDMRBERInt(slotNo, ber);
|
||||
}
|
||||
|
||||
void CDisplay::clearDMR(unsigned int slotNo)
|
||||
{
|
||||
if (slotNo == 1U) {
|
||||
|
|
@ -293,6 +337,10 @@ void CDisplay::writeDMRRSSIInt(unsigned int slotNo, unsigned char rssi)
|
|||
{
|
||||
}
|
||||
|
||||
void CDisplay::writeDMRTAInt(unsigned int slotNo, unsigned char* talkerAlias, const char* type)
|
||||
{
|
||||
}
|
||||
|
||||
void CDisplay::writeDMRBERInt(unsigned int slotNo, float ber)
|
||||
{
|
||||
}
|
||||
|
|
|
|||
|
|
@ -43,6 +43,7 @@ public:
|
|||
void writeDMR(unsigned int slotNo, const std::string& src, bool group, const std::string& dst, const char* type);
|
||||
void writeDMRRSSI(unsigned int slotNo, unsigned char rssi);
|
||||
void writeDMRBER(unsigned int slotNo, float ber);
|
||||
void writeDMRTA(unsigned int slotNo, unsigned char* talkerAlias, const char* type);
|
||||
void clearDMR(unsigned int slotNo);
|
||||
|
||||
void writeFusion(const char* source, const char* dest, const char* type, const char* origin);
|
||||
|
|
@ -74,6 +75,7 @@ protected:
|
|||
|
||||
virtual void writeDMRInt(unsigned int slotNo, const std::string& src, bool group, const std::string& dst, const char* type) = 0;
|
||||
virtual void writeDMRRSSIInt(unsigned int slotNo, unsigned char rssi);
|
||||
virtual void writeDMRTAInt(unsigned int slotNo, unsigned char* talkerAlias, const char* type);
|
||||
virtual void writeDMRBERInt(unsigned int slotNo, float ber);
|
||||
virtual void clearDMRInt(unsigned int slotNo) = 0;
|
||||
|
||||
|
|
|
|||
|
|
@ -173,6 +173,8 @@ Port=/dev/ttyAMA0
|
|||
Brightness=50
|
||||
DisplayClock=1
|
||||
UTC=0
|
||||
#Screen Layout: 1=G4KLX 2=ON7LDS
|
||||
ScreenLayout=2
|
||||
IdleBrightness=20
|
||||
|
||||
[OLED]
|
||||
|
|
|
|||
|
|
@ -1099,6 +1099,7 @@ void CMMDVMHost::createDisplay()
|
|||
bool displayClock = m_conf.getNextionDisplayClock();
|
||||
bool utc = m_conf.getNextionUTC();
|
||||
unsigned int idleBrightness = m_conf.getNextionIdleBrightness();
|
||||
unsigned int screenLayout = m_conf.getNextionScreenLayout();
|
||||
|
||||
LogInfo(" Port: %s", port.c_str());
|
||||
LogInfo(" Brightness: %u", brightness);
|
||||
|
|
@ -1106,16 +1107,20 @@ void CMMDVMHost::createDisplay()
|
|||
if (displayClock)
|
||||
LogInfo(" Display UTC: %s", utc ? "yes" : "no");
|
||||
LogInfo(" Idle Brightness: %u", idleBrightness);
|
||||
if (screenLayout==0)
|
||||
LogInfo(" Screen Layout: Default (G4KLX)");
|
||||
else
|
||||
LogInfo(" Screen Layout: %u (ON7LDS)", screenLayout);
|
||||
|
||||
if (port == "modem") {
|
||||
ISerialPort* serial = new CModemSerialPort(m_modem);
|
||||
m_display = new CNextion(m_callsign, dmrid, serial, brightness, displayClock, utc, idleBrightness);
|
||||
m_display = new CNextion(m_callsign, dmrid, serial, brightness, displayClock, utc, idleBrightness, screenLayout);
|
||||
} else if (port == "ump") {
|
||||
if (m_ump != NULL)
|
||||
m_display = new CNextion(m_callsign, dmrid, m_ump, brightness, displayClock, utc, idleBrightness);
|
||||
m_display = new CNextion(m_callsign, dmrid, m_ump, brightness, displayClock, utc, idleBrightness, screenLayout);
|
||||
} else {
|
||||
ISerialPort* serial = new CSerialController(port, SERIAL_9600);
|
||||
m_display = new CNextion(m_callsign, dmrid, serial, brightness, displayClock, utc, idleBrightness);
|
||||
m_display = new CNextion(m_callsign, dmrid, serial, brightness, displayClock, utc, idleBrightness, screenLayout);
|
||||
}
|
||||
} else if (type == "LCDproc") {
|
||||
std::string address = m_conf.getLCDprocAddress();
|
||||
|
|
|
|||
|
|
@ -189,6 +189,7 @@
|
|||
<ClInclude Include="Modem.h" />
|
||||
<ClInclude Include="ModemSerialPort.h" />
|
||||
<ClInclude Include="Mutex.h" />
|
||||
<ClInclude Include="Network.h" />
|
||||
<ClInclude Include="Nextion.h" />
|
||||
<ClInclude Include="NullDisplay.h" />
|
||||
<ClInclude Include="P25Audio.h" />
|
||||
|
|
@ -258,6 +259,7 @@
|
|||
<ClCompile Include="Modem.cpp" />
|
||||
<ClCompile Include="ModemSerialPort.cpp" />
|
||||
<ClCompile Include="Mutex.cpp" />
|
||||
<ClCompile Include="Network.cpp" />
|
||||
<ClCompile Include="Nextion.cpp" />
|
||||
<ClCompile Include="NullDisplay.cpp" />
|
||||
<ClCompile Include="P25Audio.cpp" />
|
||||
|
|
|
|||
|
|
@ -221,6 +221,9 @@
|
|||
<ClInclude Include="RSSIInterpolator.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Network.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="BPTC19696.cpp">
|
||||
|
|
@ -412,5 +415,8 @@
|
|||
<ClCompile Include="RSSIInterpolator.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Network.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
2
Makefile
2
Makefile
|
|
@ -9,7 +9,7 @@ LDFLAGS = -g
|
|||
OBJECTS = \
|
||||
AMBEFEC.o BCH.o BPTC19696.o Conf.o CRC.o Display.o DMRControl.o DMRCSBK.o DMRData.o DMRDataHeader.o DMREMB.o DMREmbeddedData.o DMRFullLC.o DMRLookup.o DMRLC.o \
|
||||
DMRNetwork.o DMRShortLC.o DMRSlot.o DMRSlotType.o DMRAccessControl.o DMRTrellis.o DStarControl.o DStarHeader.o DStarNetwork.o DStarSlowData.o Golay2087.o \
|
||||
Golay24128.o Hamming.o LCDproc.o Log.o MMDVMHost.o Modem.o ModemSerialPort.o Mutex.o Nextion.o NullDisplay.o P25Audio.o P25Control.o P25Data.o P25LowSpeedData.o \
|
||||
Golay24128.o Hamming.o LCDproc.o Log.o MMDVMHost.o Modem.o ModemSerialPort.o Mutex.o Network.o Nextion.o NullDisplay.o P25Audio.o P25Control.o P25Data.o P25LowSpeedData.o \
|
||||
P25Network.o P25NID.o P25Utils.o QR1676.o RS129.o RS241213.o RSSIInterpolator.o SerialController.o SerialPort.o SHA256.o StopWatch.o Sync.o TFTSerial.o Thread.o \
|
||||
Timer.o UDPSocket.o UMP.o Utils.o YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,180 @@
|
|||
/*
|
||||
* Copyright (C) 2017 by Lieven De Samblanx ON7LDS
|
||||
*
|
||||
* 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
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include "Network.h"
|
||||
#include "Log.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
#include <ctime>
|
||||
#include <clocale>
|
||||
|
||||
#include <sys/types.h>
|
||||
#if !defined(_WIN32) && !defined(_WIN64)
|
||||
#include <ifaddrs.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netdb.h>
|
||||
#else
|
||||
#include <ws2tcpip.h>
|
||||
#include <iphlpapi.h>
|
||||
#pragma comment(lib, "iphlpapi.lib")
|
||||
#ifndef NO_ERROR
|
||||
#define NO_ERROR 0
|
||||
#endif
|
||||
#ifndef ERROR_BUFFER_OVERFLOW
|
||||
#define ERROR_BUFFER_OVERFLOW 111
|
||||
#endif
|
||||
#ifndef ERROR_INSUFFICIENT_BUFFER
|
||||
#define ERROR_INSUFFICIENT_BUFFER 122
|
||||
#endif
|
||||
#endif
|
||||
|
||||
void CNetworkInfo::getNetworkInterface(unsigned char* info)
|
||||
{
|
||||
LogInfo("Interfaces Info");
|
||||
::strcpy((char*)info, "(address unknown)");
|
||||
|
||||
|
||||
#if !defined(_WIN32) && !defined(_WIN64)
|
||||
|
||||
#define IFLISTSIZ 25
|
||||
|
||||
struct ifaddrs *ifaddr, *ifa;
|
||||
int family, s, n, ifnr;
|
||||
char host[NI_MAXHOST];
|
||||
char interfacelist[IFLISTSIZ][50+INET6_ADDRSTRLEN];
|
||||
char *dflt, *p;
|
||||
FILE *f;
|
||||
char line[100U];
|
||||
|
||||
dflt=NULL;
|
||||
f = fopen("/proc/net/route" , "r");
|
||||
while(fgets(line , 100U , f)) {
|
||||
dflt = strtok(line , " \t");
|
||||
p = strtok(NULL , " \t");
|
||||
if(dflt!=NULL && p!=NULL) {
|
||||
if(strcmp(p , "00000000") == 0) { break; }
|
||||
}
|
||||
}
|
||||
fclose(f);
|
||||
|
||||
|
||||
for(n=0;n<IFLISTSIZ;n++) {
|
||||
interfacelist[n][0]=0;
|
||||
}
|
||||
ifnr=0;
|
||||
if (getifaddrs(&ifaddr) == -1) {
|
||||
LogError("getifaddrs failure");
|
||||
} else {
|
||||
for (ifa = ifaddr, n = 0; ifa != NULL; ifa = ifa->ifa_next, n++) {
|
||||
if (ifa->ifa_addr == NULL) continue;
|
||||
family = ifa->ifa_addr->sa_family;
|
||||
if (family == AF_INET || family == AF_INET6) {
|
||||
s = getnameinfo(ifa->ifa_addr,(family == AF_INET) ? sizeof(struct sockaddr_in) : sizeof(struct sockaddr_in6), host, NI_MAXHOST, NULL, 0, NI_NUMERICHOST);
|
||||
if (s != 0) {
|
||||
LogError("getnameinfo() failed: %s\n", gai_strerror(s));
|
||||
continue;
|
||||
}
|
||||
if (family == AF_INET) {
|
||||
sprintf(interfacelist[ifnr], "%s: %s", ifa->ifa_name,host);
|
||||
LogInfo(" IPv4: %s", interfacelist[ifnr] );
|
||||
} else {
|
||||
sprintf(interfacelist[ifnr], "%s: %s", ifa->ifa_name,host);
|
||||
LogInfo(" IPv6: %s", interfacelist[ifnr] );
|
||||
}
|
||||
ifnr++;
|
||||
}
|
||||
}
|
||||
freeifaddrs(ifaddr);
|
||||
|
||||
LogInfo(" Default interface is : %s" , dflt);
|
||||
|
||||
for(n=0;n<(ifnr);n++) {
|
||||
p=strchr(interfacelist[n],'%');
|
||||
if (p!=NULL) *p=0;
|
||||
if(strstr(interfacelist[n], dflt) != 0) {
|
||||
::strcpy((char*)info,interfacelist[n]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
LogInfo(" IP to show: %s", info );
|
||||
}
|
||||
#else
|
||||
PMIB_IPFORWARDTABLE pIpForwardTable;
|
||||
DWORD dwSize = 0;
|
||||
DWORD dwRetVal = 0;
|
||||
int i, ifnr;
|
||||
|
||||
pIpForwardTable = (MIB_IPFORWARDTABLE *)malloc(sizeof(MIB_IPFORWARDTABLE));
|
||||
if (pIpForwardTable == NULL) {
|
||||
LogError("Error allocating memory");
|
||||
return;
|
||||
}
|
||||
if (GetIpForwardTable(pIpForwardTable, &dwSize, 0) == ERROR_INSUFFICIENT_BUFFER) {
|
||||
free(pIpForwardTable);
|
||||
pIpForwardTable = (MIB_IPFORWARDTABLE *)malloc(dwSize);
|
||||
if (pIpForwardTable == NULL) {
|
||||
LogError("Error allocating memory");
|
||||
return;
|
||||
}
|
||||
}
|
||||
if ((dwRetVal = GetIpForwardTable(pIpForwardTable, &dwSize, 0)) == NO_ERROR) {
|
||||
for (i = 0; i < (int)pIpForwardTable->dwNumEntries; i++) {
|
||||
if (pIpForwardTable->table[i].dwForwardDest == 0) break;
|
||||
}
|
||||
ifnr = pIpForwardTable->table[i].dwForwardIfIndex;
|
||||
free(pIpForwardTable);
|
||||
|
||||
PIP_ADAPTER_INFO pAdapterInfo;
|
||||
pAdapterInfo = (IP_ADAPTER_INFO *)malloc(sizeof(IP_ADAPTER_INFO));
|
||||
ULONG buflen = sizeof(IP_ADAPTER_INFO);
|
||||
|
||||
if (GetAdaptersInfo(pAdapterInfo, &buflen) == ERROR_BUFFER_OVERFLOW) {
|
||||
free(pAdapterInfo);
|
||||
pAdapterInfo = (IP_ADAPTER_INFO *)malloc(buflen);
|
||||
if (pAdapterInfo == NULL) {
|
||||
LogError("Error allocating memory");
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (GetAdaptersInfo(pAdapterInfo, &buflen) == NO_ERROR) {
|
||||
PIP_ADAPTER_INFO pAdapter = pAdapterInfo;
|
||||
while (pAdapter) {
|
||||
LogInfo(" IP : %s", pAdapter->IpAddressList.IpAddress.String);
|
||||
if (pAdapter->Index == ifnr) {
|
||||
::strcpy((char*)info, pAdapter->IpAddressList.IpAddress.String);
|
||||
}
|
||||
pAdapter = pAdapter->Next;
|
||||
}
|
||||
LogInfo(" IP to show: %s", info);
|
||||
|
||||
}
|
||||
else {
|
||||
LogError("Call to GetAdaptersInfo failed.");
|
||||
}
|
||||
return;
|
||||
}
|
||||
else {
|
||||
LogError("GetIpForwardTable failed.");
|
||||
free(pIpForwardTable);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* Copyright (C) 2017 by Lieven De Samblanx ON7LDS
|
||||
*
|
||||
* 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
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#if !defined(NETWORK_H)
|
||||
#define NETWORK_H
|
||||
|
||||
|
||||
class CNetworkInfo {
|
||||
public:
|
||||
|
||||
void getNetworkInterface(unsigned char* info);
|
||||
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
94
Nextion.cpp
94
Nextion.cpp
|
|
@ -18,12 +18,14 @@
|
|||
|
||||
#include "Nextion.h"
|
||||
#include "Log.h"
|
||||
#include "Network.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
#include <ctime>
|
||||
#include <clocale>
|
||||
//#include <unistd.h>
|
||||
|
||||
const unsigned int DSTAR_RSSI_COUNT = 3U; // 3 * 420ms = 1260ms
|
||||
const unsigned int DSTAR_BER_COUNT = 63U; // 63 * 20ms = 1260ms
|
||||
|
|
@ -34,9 +36,10 @@ const unsigned int YSF_BER_COUNT = 13U; // 13 * 100ms = 1300ms
|
|||
const unsigned int P25_RSSI_COUNT = 7U; // 7 * 180ms = 1260ms
|
||||
const unsigned int P25_BER_COUNT = 7U; // 7 * 180ms = 1260ms
|
||||
|
||||
CNextion::CNextion(const std::string& callsign, unsigned int dmrid, ISerialPort* serial, unsigned int brightness, bool displayClock, bool utc, unsigned int idleBrightness) :
|
||||
CNextion::CNextion(const std::string& callsign, unsigned int dmrid, ISerialPort* serial, unsigned int brightness, bool displayClock, bool utc, unsigned int idleBrightness, unsigned int screenLayout) :
|
||||
CDisplay(),
|
||||
m_callsign(callsign),
|
||||
m_ipaddress("(ip unknown)"),
|
||||
m_dmrid(dmrid),
|
||||
m_serial(serial),
|
||||
m_brightness(brightness),
|
||||
|
|
@ -44,6 +47,7 @@ m_mode(MODE_IDLE),
|
|||
m_displayClock(displayClock),
|
||||
m_utc(utc),
|
||||
m_idleBrightness(idleBrightness),
|
||||
m_screenLayout(screenLayout),
|
||||
m_clockDisplayTimer(1000U, 0U, 400U),
|
||||
m_rssiAccum1(0U),
|
||||
m_rssiAccum2(0U),
|
||||
|
|
@ -64,6 +68,9 @@ CNextion::~CNextion()
|
|||
|
||||
bool CNextion::open()
|
||||
{
|
||||
unsigned char info[100U];
|
||||
CNetworkInfo* m_network;
|
||||
|
||||
bool ret = m_serial->open();
|
||||
if (!ret) {
|
||||
LogError("Cannot open the port for the Nextion display");
|
||||
|
|
@ -71,6 +78,11 @@ bool CNextion::open()
|
|||
return false;
|
||||
}
|
||||
|
||||
info[0]=0;
|
||||
m_network = new CNetworkInfo;
|
||||
m_network->getNetworkInterface(info);
|
||||
m_ipaddress = (char*)info;
|
||||
|
||||
sendCommand("bkcmd=0");
|
||||
|
||||
setIdle();
|
||||
|
|
@ -78,19 +90,23 @@ bool CNextion::open()
|
|||
return true;
|
||||
}
|
||||
|
||||
|
||||
void CNextion::setIdleInt()
|
||||
{
|
||||
sendCommand("page MMDVM");
|
||||
|
||||
char command[30];
|
||||
char command[30U];
|
||||
::sprintf(command, "dim=%u", m_idleBrightness);
|
||||
sendCommand(command);
|
||||
|
||||
::sprintf(command, "t0.txt=\"%-6s / %u\"", m_callsign.c_str(), m_dmrid);
|
||||
|
||||
|
||||
::sprintf(command, "t0.txt=\"%s/%u\"", m_callsign.c_str(), m_dmrid);
|
||||
sendCommand(command);
|
||||
|
||||
sendCommand("t1.txt=\"MMDVM IDLE\"");
|
||||
|
||||
::sprintf(command, "t3.txt=\"%s\"", m_ipaddress.c_str());
|
||||
sendCommand(command);
|
||||
|
||||
m_clockDisplayTimer.start();
|
||||
|
||||
m_mode = MODE_IDLE;
|
||||
|
|
@ -226,10 +242,19 @@ void CNextion::writeDMRInt(unsigned int slotNo, const std::string& src, bool gro
|
|||
if (m_mode != MODE_DMR) {
|
||||
sendCommand("page DMR");
|
||||
|
||||
if (slotNo == 1U)
|
||||
if (slotNo == 1U) {
|
||||
if (m_screenLayout==2U) {
|
||||
sendCommand("t2.pco=0");
|
||||
sendCommand("t2.font=4");
|
||||
}
|
||||
sendCommand("t2.txt=\"2 Listening\"");
|
||||
else
|
||||
} else {
|
||||
if (m_screenLayout==2U) {
|
||||
sendCommand("t0.pco=0");
|
||||
sendCommand("t0.font=4");
|
||||
}
|
||||
sendCommand("t0.txt=\"1 Listening\"");
|
||||
}
|
||||
}
|
||||
|
||||
char text[30U];
|
||||
|
|
@ -238,12 +263,20 @@ void CNextion::writeDMRInt(unsigned int slotNo, const std::string& src, bool gro
|
|||
|
||||
if (slotNo == 1U) {
|
||||
::sprintf(text, "t0.txt=\"1 %s %s\"", type, src.c_str());
|
||||
if (m_screenLayout==2U) {
|
||||
sendCommand("t0.pco=0");
|
||||
sendCommand("t0.font=4");
|
||||
}
|
||||
sendCommand(text);
|
||||
|
||||
::sprintf(text, "t1.txt=\"%s%s\"", group ? "TG" : "", dst.c_str());
|
||||
sendCommand(text);
|
||||
} else {
|
||||
::sprintf(text, "t2.txt=\"2 %s %s\"", type, src.c_str());
|
||||
if (m_screenLayout==2U) {
|
||||
sendCommand("t2.pco=0");
|
||||
sendCommand("t2.font=4");
|
||||
}
|
||||
sendCommand(text);
|
||||
|
||||
::sprintf(text, "t3.txt=\"%s%s\"", group ? "TG" : "", dst.c_str());
|
||||
|
|
@ -306,6 +339,43 @@ void CNextion::writeDMRRSSIInt(unsigned int slotNo, unsigned char rssi)
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
void CNextion::writeDMRTAInt(unsigned int slotNo, unsigned char* talkerAlias, const char* type)
|
||||
{
|
||||
char text[40U];
|
||||
|
||||
if (m_screenLayout<2U) return;
|
||||
|
||||
if (type[0]==' ') {
|
||||
if (slotNo == 1U) {
|
||||
sendCommand("t0.pco=33808");
|
||||
} else {
|
||||
sendCommand("t2.pco=33808");
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (slotNo == 1U) {
|
||||
::sprintf(text, "t0.txt=\"1 %s %s\"",type,talkerAlias);
|
||||
if (m_screenLayout==2U) {
|
||||
if (::strlen((char*)talkerAlias)>(16U-4U)) sendCommand("t0.font=3");
|
||||
if (::strlen((char*)talkerAlias)>(20U-4U)) sendCommand("t0.font=2");
|
||||
if (::strlen((char*)talkerAlias)>(24U-4U)) sendCommand("t0.font=1");
|
||||
}
|
||||
sendCommand("t0.pco=1024");
|
||||
sendCommand(text);
|
||||
} else {
|
||||
::sprintf(text, "t2.txt=\"2 %s %s\"",type,talkerAlias);
|
||||
if (m_screenLayout==2U) {
|
||||
if (::strlen((char*)talkerAlias)>(16U-4U)) sendCommand("t2.font=3");
|
||||
if (::strlen((char*)talkerAlias)>(20U-4U)) sendCommand("t2.font=2");
|
||||
if (::strlen((char*)talkerAlias)>(24U-4U)) sendCommand("t2.font=1");
|
||||
}
|
||||
sendCommand("t2.pco=1024");
|
||||
sendCommand(text);
|
||||
}
|
||||
}
|
||||
|
||||
void CNextion::writeDMRBERInt(unsigned int slotNo, float ber)
|
||||
{
|
||||
if (slotNo == 1U) {
|
||||
|
|
@ -353,11 +423,19 @@ void CNextion::clearDMRInt(unsigned int slotNo)
|
|||
{
|
||||
if (slotNo == 1U) {
|
||||
sendCommand("t0.txt=\"1 Listening\"");
|
||||
if (m_screenLayout==2U) {
|
||||
sendCommand("t0.pco=0");
|
||||
sendCommand("t0.font=4");
|
||||
}
|
||||
sendCommand("t1.txt=\"\"");
|
||||
sendCommand("t4.txt=\"\"");
|
||||
sendCommand("t6.txt=\"\"");
|
||||
} else {
|
||||
sendCommand("t2.txt=\"2 Listening\"");
|
||||
if (m_screenLayout==2U) {
|
||||
sendCommand("t2.pco=0");
|
||||
sendCommand("t2.font=4");
|
||||
}
|
||||
sendCommand("t3.txt=\"\"");
|
||||
sendCommand("t5.txt=\"\"");
|
||||
sendCommand("t7.txt=\"\"");
|
||||
|
|
@ -568,6 +646,8 @@ void CNextion::clockInt(unsigned int ms)
|
|||
|
||||
void CNextion::close()
|
||||
{
|
||||
sendCommand("page MMDVM");
|
||||
sendCommand("t1.txt=\"MMDVM STOPPED\"");
|
||||
m_serial->close();
|
||||
delete m_serial;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -29,7 +29,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);
|
||||
CNextion(const std::string& callsign, unsigned int dmrid, ISerialPort* serial, unsigned int brightness, bool displayClock, bool utc, unsigned int idleBrightness, unsigned int screenLayout);
|
||||
virtual ~CNextion();
|
||||
|
||||
virtual bool open();
|
||||
|
|
@ -48,6 +48,7 @@ protected:
|
|||
|
||||
virtual void writeDMRInt(unsigned int slotNo, const std::string& src, bool group, const std::string& dst, const char* type);
|
||||
virtual void writeDMRRSSIInt(unsigned int slotNo, unsigned char rssi);
|
||||
virtual void writeDMRTAInt(unsigned int slotNo, unsigned char* talkerAlias, const char* type);
|
||||
virtual void writeDMRBERInt(unsigned int slotNo, float ber);
|
||||
virtual void clearDMRInt(unsigned int slotNo);
|
||||
|
||||
|
|
@ -68,6 +69,7 @@ protected:
|
|||
|
||||
private:
|
||||
std::string m_callsign;
|
||||
std::string m_ipaddress;
|
||||
unsigned int m_dmrid;
|
||||
ISerialPort* m_serial;
|
||||
unsigned int m_brightness;
|
||||
|
|
@ -75,6 +77,7 @@ private:
|
|||
bool m_displayClock;
|
||||
bool m_utc;
|
||||
unsigned int m_idleBrightness;
|
||||
unsigned int m_screenLayout;
|
||||
CTimer m_clockDisplayTimer;
|
||||
unsigned int m_rssiAccum1;
|
||||
unsigned int m_rssiAccum2;
|
||||
|
|
|
|||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -0,0 +1,29 @@
|
|||
The files in this directory are Nextion screen layouts with better fonts than
|
||||
the(rather ugly) standard Nextion fonts
|
||||
|
||||
There are some other changes:
|
||||
|
||||
* On the main screen there is a field to display the active ip address of the
|
||||
device. On Linux it is preceded with the network interface name.
|
||||
* DMR: if received, the Talker Alias is decoded and displayed. The TA will be
|
||||
in green, so the user knows it is a decoded TA displaying.
|
||||
This happens on-the-fly: as the parts of the TA arrive, they will immediately
|
||||
be shown.
|
||||
* If you want to change my screen layout, the only thing to keep in mind is
|
||||
that the MMDVMHost program will select following font numbers:
|
||||
default font for the TA field : font 4
|
||||
TA >16 characters : font 3
|
||||
TA >20 characters : font 2
|
||||
TA >24 characters : font 1
|
||||
There always have to be at least 5 fonts, of which font 1-4 are used for the
|
||||
TA. If your display is wide enough to show all characters in one font, you
|
||||
must copy this font to the lesser ('smaller') fonts.
|
||||
i.e. : the 3.2" the display can show more than 31 characters (the maximum
|
||||
TA length) in font 2, so this font is also copied to font 1.
|
||||
* The screenlayout has to be selected with the parameter ScreenLayout in the
|
||||
MMDVM.ini file under the Nextion section. This way, the extra function
|
||||
to automatically change the font size, is activated.
|
||||
0 = auto (future use, for now it's G4KLX layout)
|
||||
1 = G4KLX layout
|
||||
2 = ON7LDS layout
|
||||
|
||||
Loading…
Reference in New Issue