diff --git a/Conf.cpp b/Conf.cpp index e4cec6e..97cedbe 100644 --- a/Conf.cpp +++ b/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; diff --git a/Conf.h b/Conf.h index 9e8b8a6..b79186f 100644 --- a/Conf.h +++ b/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; diff --git a/DMRSlot.cpp b/DMRSlot.cpp index 1308941..81337ca 100644 --- a/DMRSlot.cpp +++ b/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(); diff --git a/DMRSlot.h b/DMRSlot.h index 04485f1..38e4a5b 100644 --- a/DMRSlot.h +++ b/DMRSlot.h @@ -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); diff --git a/Display.cpp b/Display.cpp index 18c8100..8e8822a 100644 --- a/Display.cpp +++ b/Display.cpp @@ -18,14 +18,15 @@ #include "Display.h" #include "Defines.h" +#include "Log.h" #include #include #include 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=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)&&(t2TAsize) { 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) { } diff --git a/Display.h b/Display.h index 9e3d884..b8f2763 100644 --- a/Display.h +++ b/Display.h @@ -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; diff --git a/MMDVM.ini b/MMDVM.ini index bdefdfd..853398a 100644 --- a/MMDVM.ini +++ b/MMDVM.ini @@ -173,6 +173,8 @@ Port=/dev/ttyAMA0 Brightness=50 DisplayClock=1 UTC=0 +#Screen Layout: 1=G4KLX 2=ON7LDS +ScreenLayout=2 IdleBrightness=20 [OLED] diff --git a/MMDVMHost.cpp b/MMDVMHost.cpp index ba7a473..0979ad0 100644 --- a/MMDVMHost.cpp +++ b/MMDVMHost.cpp @@ -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(); diff --git a/MMDVMHost.vcxproj b/MMDVMHost.vcxproj index b146e70..caf9d63 100644 --- a/MMDVMHost.vcxproj +++ b/MMDVMHost.vcxproj @@ -189,6 +189,7 @@ + @@ -258,6 +259,7 @@ + diff --git a/MMDVMHost.vcxproj.filters b/MMDVMHost.vcxproj.filters index f01b170..9128703 100644 --- a/MMDVMHost.vcxproj.filters +++ b/MMDVMHost.vcxproj.filters @@ -221,6 +221,9 @@ Header Files + + Header Files + @@ -412,5 +415,8 @@ Source Files + + Source Files + \ No newline at end of file diff --git a/Makefile b/Makefile index 90346af..7b7c26e 100644 --- a/Makefile +++ b/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 diff --git a/Network.cpp b/Network.cpp new file mode 100644 index 0000000..084492c --- /dev/null +++ b/Network.cpp @@ -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 +#include +#include +#include +#include + +#include +#if !defined(_WIN32) && !defined(_WIN64) +#include +#include +#include +#include +#else +#include +#include +#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;nifa_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 +} diff --git a/Network.h b/Network.h new file mode 100644 index 0000000..0d639b6 --- /dev/null +++ b/Network.h @@ -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 diff --git a/Nextion.cpp b/Nextion.cpp index a41dd59..f4a3f63 100644 --- a/Nextion.cpp +++ b/Nextion.cpp @@ -18,12 +18,14 @@ #include "Nextion.h" #include "Log.h" +#include "Network.h" #include #include #include #include #include +//#include 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; } diff --git a/Nextion.h b/Nextion.h index c5a931b..bde7c5d 100644 --- a/Nextion.h +++ b/Nextion.h @@ -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; diff --git a/Nextion_ON7LDS/NX3224T024-L2.HMI b/Nextion_ON7LDS/NX3224T024-L2.HMI new file mode 100644 index 0000000..2053193 Binary files /dev/null and b/Nextion_ON7LDS/NX3224T024-L2.HMI differ diff --git a/Nextion_ON7LDS/NX3224T024-L2.tft b/Nextion_ON7LDS/NX3224T024-L2.tft new file mode 100644 index 0000000..8a35f3f Binary files /dev/null and b/Nextion_ON7LDS/NX3224T024-L2.tft differ diff --git a/Nextion_ON7LDS/NX3224T028-L2.HMI b/Nextion_ON7LDS/NX3224T028-L2.HMI new file mode 100644 index 0000000..4e46f9d Binary files /dev/null and b/Nextion_ON7LDS/NX3224T028-L2.HMI differ diff --git a/Nextion_ON7LDS/NX3224T028-L2.tft b/Nextion_ON7LDS/NX3224T028-L2.tft new file mode 100644 index 0000000..1109cbe Binary files /dev/null and b/Nextion_ON7LDS/NX3224T028-L2.tft differ diff --git a/Nextion_ON7LDS/NX4024T032-L2.HMI b/Nextion_ON7LDS/NX4024T032-L2.HMI new file mode 100644 index 0000000..0c2fe27 Binary files /dev/null and b/Nextion_ON7LDS/NX4024T032-L2.HMI differ diff --git a/Nextion_ON7LDS/NX4024T032-L2.tft b/Nextion_ON7LDS/NX4024T032-L2.tft new file mode 100644 index 0000000..7c8779a Binary files /dev/null and b/Nextion_ON7LDS/NX4024T032-L2.tft differ diff --git a/Nextion_ON7LDS/NX4832T035-L2.HMI b/Nextion_ON7LDS/NX4832T035-L2.HMI new file mode 100644 index 0000000..7cd8aeb Binary files /dev/null and b/Nextion_ON7LDS/NX4832T035-L2.HMI differ diff --git a/Nextion_ON7LDS/NX4832T035-L2.tft b/Nextion_ON7LDS/NX4832T035-L2.tft new file mode 100644 index 0000000..d4a4245 Binary files /dev/null and b/Nextion_ON7LDS/NX4832T035-L2.tft differ diff --git a/Nextion_ON7LDS/README b/Nextion_ON7LDS/README new file mode 100644 index 0000000..25542b9 --- /dev/null +++ b/Nextion_ON7LDS/README @@ -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 +