diff --git a/DMRLookup.cpp b/DMRLookup.cpp index d41df5d..8fc67c3 100644 --- a/DMRLookup.cpp +++ b/DMRLookup.cpp @@ -81,7 +81,7 @@ void CDMRLookup::stop() wait(); } -std::string CDMRLookup::find(unsigned int id) +std::string CDMRLookup::findWithName(unsigned int id) { std::string callsign; @@ -92,6 +92,40 @@ std::string CDMRLookup::find(unsigned int id) try { callsign = m_table.at(id); + LogDebug("FindWithName =%s",callsign.c_str()); + + } catch (...) { + char text[10U]; + ::sprintf(text, "%u", id); + callsign = std::string(text); + } + + m_mutex.unlock(); + + return callsign; +} +std::string CDMRLookup::find(unsigned int id) +{ + std::string callsign; + std::string b; + + + if (id == 0xFFFFFFU) + return std::string("ALL"); + + m_mutex.lock(); + + try { + b = m_table.at(id); + size_t n = b.find(" "); + if (n > 0) { + callsign = b.substr(0,n); + + } else { + LogDebug("b=%s",b.c_str()); + callsign = b; + } + } catch (...) { char text[10U]; ::sprintf(text, "%u", id); @@ -133,13 +167,19 @@ bool CDMRLookup::load() continue; char* p1 = ::strtok(buffer, " \t\r\n"); - char* p2 = ::strtok(NULL, " \t\r\n"); + char* p2 = ::strtok(NULL, " \r\n"); // tokenize to eol to capture name as well if (p1 != NULL && p2 != NULL) { unsigned int id = (unsigned int)::atoi(p1); - for (char* p = p2; *p != 0x00U; p++) - *p = ::toupper(*p); - + for (char* p = p2; *p != 0x00U; p++) { + + if(*p == 0x09U) + *p = 0x20U; + + else + *p = ::toupper(*p); + + } m_table[id] = std::string(p2); } } diff --git a/DMRLookup.h b/DMRLookup.h index ed09ac2..1156270 100644 --- a/DMRLookup.h +++ b/DMRLookup.h @@ -35,6 +35,7 @@ public: virtual void entry(); std::string find(unsigned int id); + std::string findWithName(unsigned int id); bool exists(unsigned int id); diff --git a/DMRSlot.cpp b/DMRSlot.cpp index 001c6f4..f50a783 100644 --- a/DMRSlot.cpp +++ b/DMRSlot.cpp @@ -1067,16 +1067,16 @@ void CDMRSlot::writeNetwork(const CDMRData& dmrData) m_netState = RS_NET_AUDIO; setShortLC(m_slotNo, dstId, flco, ACTIVITY_VOICE); - std::string src = m_lookup->find(srcId); std::string dst = m_lookup->find(dstId); - - m_display->writeDMR(m_slotNo, src, flco == FLCO_GROUP, dst, "N"); + std::string cn = m_lookup->findWithName(srcId); + m_display->writeDMR(m_slotNo, cn, flco == FLCO_GROUP, dst, "N"); #if defined(DUMP_DMR) openFile(); writeFile(data); #endif + LogMessage("DMR Slot %u, received network voice header from %s to %s%s", m_slotNo, src.c_str(), flco == FLCO_GROUP ? "TG " : "", dst.c_str()); } else if (dataType == DT_VOICE_PI_HEADER) { if (m_netState != RS_NET_AUDIO) { diff --git a/MMDVMHost.cpp b/MMDVMHost.cpp index 3ad78b0..0cf02a9 100644 --- a/MMDVMHost.cpp +++ b/MMDVMHost.cpp @@ -1389,7 +1389,7 @@ void CMMDVMHost::createDisplay() unsigned char brightness = m_conf.getOLEDBrightness(); bool invert = m_conf.getOLEDInvert(); bool scroll = m_conf.getOLEDScroll(); - m_display = new COLED(type, brightness, invert, scroll); + m_display = new COLED(type, brightness, invert, scroll, m_conf.getDMRNetworkSlot1(), m_conf.getDMRNetworkSlot2()); #endif } else { m_display = new CNullDisplay; diff --git a/NetworkInfo.cpp b/NetworkInfo.cpp index 1f97866..eb3ed6e 100644 --- a/NetworkInfo.cpp +++ b/NetworkInfo.cpp @@ -116,10 +116,10 @@ void CNetworkInfo::getNetworkInterface(unsigned char* info) } if (family == AF_INET) { - ::sprintf(interfacelist[ifnr], "%s: %s", ifa->ifa_name, host); + ::sprintf(interfacelist[ifnr], "%s:%s", ifa->ifa_name, host); LogInfo(" IPv4: %s", interfacelist[ifnr]); } else { - ::sprintf(interfacelist[ifnr], "%s: %s", ifa->ifa_name, host); + ::sprintf(interfacelist[ifnr], "%s:%s", ifa->ifa_name, host); LogInfo(" IPv6: %s", interfacelist[ifnr]); } diff --git a/OLED.cpp b/OLED.cpp index 1c64ec9..d718a2a 100644 --- a/OLED.cpp +++ b/OLED.cpp @@ -17,6 +17,10 @@ */ #include "OLED.h" +#include "Log.h" + +static bool networkInfoInitialized = false; +static unsigned char passCounter = 0; //Logo MMDVM for Idle Screen static unsigned char logo_glcd_bmp[] = @@ -102,12 +106,55 @@ const unsigned char logo_fusion_bmp [] = 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + //Logo P25 128x16px + const unsigned char logo_P25_bmp [] = + { +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xf8, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xfc, 0x00, 0x00, 0x3f, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x7f, +0xf8, 0x00, 0x00, 0x00, 0x03, 0xff, 0xc0, 0x00, 0x00, 0x03, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x7f, +0xf8, 0x00, 0xe0, 0x00, 0x00, 0xff, 0x00, 0x07, 0xc0, 0x00, 0xff, 0xe0, 0x00, 0x00, 0x00, 0xff, +0xf0, 0x01, 0xff, 0xfc, 0x00, 0x7e, 0x00, 0x3f, 0xf8, 0x00, 0xff, 0xe0, 0x0f, 0xff, 0xff, 0xff, +0xf0, 0x01, 0xff, 0xfe, 0x00, 0x7c, 0x00, 0x7f, 0xfc, 0x00, 0x7f, 0xe0, 0x0f, 0xff, 0xff, 0xff, +0xf0, 0x01, 0xff, 0xfe, 0x00, 0x7e, 0x00, 0x7f, 0xf8, 0x00, 0xff, 0xe0, 0x00, 0x00, 0x01, 0xff, +0xf0, 0x01, 0xff, 0xc0, 0x00, 0xff, 0xff, 0xff, 0xe0, 0x01, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x1f, +0xf0, 0x00, 0x00, 0x00, 0x03, 0xff, 0xff, 0xff, 0x00, 0x07, 0xff, 0xff, 0x9f, 0xff, 0x80, 0x07, +0xf0, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xf8, 0x00, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x03, +0xf0, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x03, +0xf0, 0x01, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x1f, 0xff, 0xff, 0xc0, 0xff, 0xff, 0xc0, 0x03, +0xf0, 0x01, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x7f, 0xff, 0xfe, 0x00, 0x0f, 0xfe, 0x00, 0x0f, +0xf0, 0x01, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x80, 0x00, 0x00, 0x00, 0x3f, +0xf0, 0x01, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xf8, 0x00, 0x00, 0x03, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff + }; + +// Logo NXDN_sm, 128x16px +const unsigned char logo_NXDN_bmp [] = + { +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xf0, 0x1f, 0xf8, 0x0f, 0x00, 0xff, 0x80, 0x7c, 0x00, 0x0f, 0xff, 0x80, 0x7f, 0xe0, 0x7f, +0xff, 0xe0, 0x0f, 0xf0, 0x1f, 0x80, 0x7e, 0x01, 0xf8, 0x00, 0x00, 0x7f, 0x00, 0x3f, 0xc0, 0x7f, +0xff, 0xc0, 0x07, 0xe0, 0x3f, 0x80, 0x38, 0x07, 0xf0, 0x00, 0x00, 0x3e, 0x00, 0x3f, 0x80, 0xff, +0xff, 0x80, 0x03, 0xc0, 0x3f, 0xc0, 0x00, 0x3f, 0xe0, 0x1f, 0x80, 0x3e, 0x00, 0x1f, 0x01, 0xff, +0xff, 0x00, 0x03, 0x80, 0x7f, 0xe0, 0x00, 0xff, 0xc0, 0x3f, 0x80, 0x3c, 0x00, 0x0e, 0x03, 0xff, +0xfe, 0x00, 0x01, 0x00, 0xff, 0xe0, 0x03, 0xff, 0x80, 0x7f, 0x80, 0x78, 0x08, 0x04, 0x03, 0xff, +0xfc, 0x03, 0x00, 0x01, 0xff, 0x80, 0x01, 0xff, 0x00, 0xff, 0x00, 0xf0, 0x1c, 0x00, 0x07, 0xff, +0xfc, 0x07, 0x80, 0x03, 0xfc, 0x00, 0x01, 0xfe, 0x01, 0xfc, 0x01, 0xe0, 0x1e, 0x00, 0x0f, 0xff, +0xf8, 0x0f, 0xc0, 0x07, 0xf0, 0x0e, 0x00, 0xfc, 0x00, 0x00, 0x07, 0xc0, 0x3f, 0x00, 0x1f, 0xff, +0xf0, 0x1f, 0xe0, 0x0f, 0x80, 0x3f, 0x00, 0x7c, 0x00, 0x00, 0x3f, 0xc0, 0x7f, 0x80, 0x3f, 0xff, +0xe0, 0x3f, 0xf0, 0x0e, 0x01, 0xff, 0x80, 0x38, 0x00, 0x07, 0xff, 0x80, 0xff, 0x80, 0x7f, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, +0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff +}; -COLED::COLED(unsigned char displayType, unsigned char displayBrightness, bool displayInvert, bool displayScroll) : +COLED::COLED(unsigned char displayType, unsigned char displayBrightness, bool displayInvert, bool displayScroll, bool slot1Enabled, bool slot2Enabled) : m_displayType(displayType), m_displayBrightness(displayBrightness), m_displayInvert(displayInvert), -m_displayScroll(displayScroll) +m_displayScroll(displayScroll), +m_slot1Enabled(slot1Enabled), +m_slot2Enabled(slot2Enabled) { } @@ -117,6 +164,7 @@ COLED::~COLED() bool COLED::open() { + // SPI if (display.oled_is_spi_proto(m_displayType)) { @@ -131,6 +179,7 @@ bool COLED::open() return false; } + display.begin(); display.invertDisplay(m_displayInvert ? 1 : 0); @@ -142,7 +191,7 @@ bool COLED::open() display.display(); // display it (clear display) OLED_statusbar(); - display.setCursor(0,OLED_LINE1); + display.setCursor(0,OLED_LINE3); display.print("Startup"); display.display(); @@ -163,6 +212,26 @@ void COLED::setIdleInt() // display.setTextSize(1); display.startscrolldiagright(0x00,0x0f); //the MMDVM logo scrolls the whole screen display.display(); + + unsigned char info[100U]; + CNetworkInfo* m_network; + + passCounter ++; + if (passCounter > 253U) + networkInfoInitialized = false; + + if (! networkInfoInitialized) { + //LogMessage("Initialize CNetworkInfo"); + info[0]=0; + m_network = new CNetworkInfo; + m_network->getNetworkInterface(info); + m_ipaddress = (char*)info; + delete m_network; + + networkInfoInitialized = true; + passCounter = 0; + } + } void COLED::setErrorInt(const char* text) @@ -198,16 +267,19 @@ void COLED::writeDStarInt(const char* my1, const char* my2, const char* your, co m_mode = MODE_DSTAR; display.clearDisplay(); - display.fillRect(0,OLED_LINE1,display.width(),display.height(),BLACK); //clear everything beneath logo - - display.setCursor(0,OLED_LINE2); - display.printf("%s %.8s/%4.4s",type,my1,my2); + display.fillRect(0,OLED_LINE3,display.width(),display.height(),BLACK); //clear everything beneath logo display.setCursor(0,OLED_LINE3); + display.printf("%s %.8s/%4.4s",type,my1,my2); + + display.setCursor(0,OLED_LINE4); display.printf("-> %.8s",your); display.setCursor(0,OLED_LINE5); display.printf("via %.8s",reflector); + + display.setCursor(0,OLED_LINE6); + display.printf("%s",m_ipaddress.c_str()); OLED_statusbar(); display.display(); @@ -215,10 +287,13 @@ void COLED::writeDStarInt(const char* my1, const char* my2, const char* your, co void COLED::clearDStarInt() { - display.fillRect(0,OLED_LINE1, display.width(),display.height(),BLACK); //clear everything beneath the logo + display.fillRect(0,OLED_LINE3, display.width(),display.height(),BLACK); //clear everything beneath the logo - display.setCursor(40,38); + display.setCursor(40,OLED_LINE3); display.print("Listening"); + + display.setCursor(0,OLED_LINE5); + display.printf("%s",m_ipaddress.c_str()); display.display(); } @@ -227,62 +302,77 @@ void COLED::writeDMRInt(unsigned int slotNo,const std::string& src,bool group,co { if (m_mode != MODE_DMR) { + display.clearDisplay(); + m_mode = MODE_DMR; + clearDMRInt(slotNo); + } + // if both slots, use lines 2-3 for slot 1, lines 4-5 for slot 2 + // if single slot, use lines 3-4 + if ( m_slot1Enabled && m_slot2Enabled ) { - display.clearDisplay(); + if (slotNo == 1U) { + display.fillRect(0,OLED_LINE2,display.width(),40,BLACK); + display.setCursor(0,OLED_LINE2); + display.printf("%s",src.c_str()); + display.setCursor(0,OLED_LINE3); + display.printf("Slot: %i %s %s%s",slotNo,type,group ? "TG: " : "",dst.c_str()); + } + else + { + display.fillRect(0,OLED_LINE4,display.width(),40,BLACK); + display.setCursor(0,OLED_LINE4); + display.printf("%s",src.c_str()); + display.setCursor(0,OLED_LINE5); + display.printf("Slot: %i %s %s%s",slotNo,type,group ? "TG: " : "",dst.c_str()); + } - m_mode = MODE_DMR; - - if (slotNo == 1U) - { - display.fillRect(0,OLED_LINE4,display.width(),20,BLACK); //20=> clear 2 lines - display.setCursor(0,OLED_LINE4); - display.print("2 Listening"); - } - else - { - display.fillRect(0,OLED_LINE2,display.width(),20,BLACK); //20=> clear 2 lines - display.setCursor(0,OLED_LINE2); - display.print("1 Listening"); - - } - } - - if (slotNo == 1U) - { - display.fillRect(0,OLED_LINE2,display.width(),20,BLACK); - display.setCursor(0,OLED_LINE2); - display.printf("%i %s %s",slotNo,type,src.c_str()); - display.setCursor(0,OLED_LINE3); - display.printf("%s%s",group ? "TG" : "",dst.c_str()); - } - else - { - display.fillRect(0,OLED_LINE4,display.width(),20,BLACK); - display.setCursor(0,OLED_LINE4); - display.printf("%i %s %s",slotNo,type,src.c_str()); - display.setCursor(0,OLED_LINE5); - display.printf("%s%s", group ? "TG" : "", dst.c_str()); - } + } + else + { + display.fillRect(0,OLED_LINE3,display.width(),20,BLACK); + display.setCursor(0,OLED_LINE3); + display.printf("%s",src.c_str()); + display.setCursor(0,OLED_LINE4); + display.printf("Slot: %i %s %s%s",slotNo,type,group ? "TG: " : "",dst.c_str()); + } + display.fillRect(0,OLED_LINE6,display.width(),20,BLACK); + display.setCursor(0,OLED_LINE6); + display.printf("%s",m_ipaddress.c_str()); + OLED_statusbar(); display.display(); -} + + } void COLED::clearDMRInt(unsigned int slotNo) { - if (slotNo == 1U) - { - display.fillRect(0, OLED_LINE2, display.width(), 20, BLACK); - display.setCursor(0,OLED_LINE2); - display.print("1 Listening"); - } - else - { - display.fillRect(0, OLED_LINE4, display.width(), 20, BLACK); - display.setCursor(0, OLED_LINE4); - display.print("2 Listening"); - } + // if both slots, use lines 2-3 for slot 1, lines 4-5 for slot 2 + // if single slot, use lines 3-4 + if ( m_slot1Enabled && m_slot2Enabled ){ + if (slotNo == 1U) + { + display.fillRect(0, OLED_LINE3, display.width(), 40, BLACK); + display.setCursor(0,OLED_LINE3); + display.print("Slot: 1 Listening"); + } + else + { + display.fillRect(0, OLED_LINE5, display.width(), 40, BLACK); + display.setCursor(0, OLED_LINE5); + display.print("Slot: 2 Listening"); + } + } + else { + display.fillRect(0, OLED_LINE4, display.width(), 40, BLACK); + display.setCursor(0,OLED_LINE4); + display.printf("Slot: %i Listening",slotNo); + } + + display.fillRect(0, OLED_LINE6, display.width(), 20, BLACK); + display.setCursor(0,OLED_LINE6); + display.printf("%s",m_ipaddress.c_str()); display.display(); } @@ -292,12 +382,12 @@ void COLED::writeFusionInt(const char* source, const char* dest, const char* typ m_mode = MODE_YSF; display.clearDisplay(); - display.fillRect(0,OLED_LINE1,display.width(),display.height(),BLACK); + display.fillRect(0,OLED_LINE2,display.width(),display.height(),BLACK); - display.setCursor(0,OLED_LINE2); + display.setCursor(0,OLED_LINE4); display.printf("%s %.10s", type, source); - display.setCursor(0,OLED_LINE3); + display.setCursor(0,OLED_LINE5); display.printf(" %.10s", dest); OLED_statusbar(); @@ -306,10 +396,13 @@ void COLED::writeFusionInt(const char* source, const char* dest, const char* typ void COLED::clearFusionInt() { - display.fillRect(0, OLED_LINE1, display.width(), display.height(), BLACK); + display.fillRect(0, OLED_LINE2, display.width(), display.height(), BLACK); - display.setCursor(40,38); + display.setCursor(40,OLED_LINE4); display.print("Listening"); + + display.setCursor(0,OLED_LINE6); + display.printf("%s",m_ipaddress.c_str()); display.display(); } @@ -321,10 +414,10 @@ void COLED::writeP25Int(const char* source, bool group, unsigned int dest, const display.clearDisplay(); display.fillRect(0, OLED_LINE1, display.width(), display.height(), BLACK); - display.setCursor(0,OLED_LINE2); + display.setCursor(0,OLED_LINE3); display.printf("%s %.10s", type, source); - display.setCursor(0,OLED_LINE3); + display.setCursor(0,OLED_LINE4); display.printf(" %s%u", group ? "TG" : "", dest); OLED_statusbar(); @@ -335,8 +428,11 @@ void COLED::clearP25Int() { display.fillRect(0, OLED_LINE1, display.width(), display.height(), BLACK); - display.setCursor(40,38); + display.setCursor(40,OLED_LINE4); display.print("Listening"); + + display.setCursor(0,OLED_LINE6); + display.printf("%s",m_ipaddress.c_str()); display.display(); } @@ -348,10 +444,10 @@ void COLED::writeNXDNInt(const char* source, bool group, unsigned int dest, cons display.clearDisplay(); display.fillRect(0, OLED_LINE1, display.width(), display.height(), BLACK); - display.setCursor(0,OLED_LINE2); + display.setCursor(0,OLED_LINE3); display.printf("%s %.10s", type, source); - display.setCursor(0,OLED_LINE3); + display.setCursor(0,OLED_LINE5); display.printf(" %s%u", group ? "TG" : "", dest); OLED_statusbar(); @@ -362,8 +458,11 @@ void COLED::clearNXDNInt() { display.fillRect(0, OLED_LINE1, display.width(), display.height(), BLACK); - display.setCursor(40,38); + display.setCursor(40,OLED_LINE4); display.print("Listening"); + + display.setCursor(0,OLED_LINE6); + display.printf("%s",m_ipaddress.c_str()); display.display(); } @@ -421,9 +520,9 @@ void COLED::OLED_statusbar() else if (m_mode == MODE_YSF) display.drawBitmap(0, 0, logo_fusion_bmp, 128, 16, WHITE); else if (m_mode == MODE_P25) - display.print("P25"); + display.drawBitmap(0, 0, logo_P25_bmp, 128, 16, WHITE); else if (m_mode == MODE_NXDN) - display.print("NXDN"); + display.drawBitmap(0, 0, logo_NXDN_bmp, 128, 16, WHITE); else display.drawBitmap(0, 0, logo_glcd_bmp, 128, 16, WHITE); diff --git a/OLED.h b/OLED.h index 06c4739..0379acd 100644 --- a/OLED.h +++ b/OLED.h @@ -20,11 +20,12 @@ #define OLED_H #define OLED_STATUSBAR 0 -#define OLED_LINE1 16 -#define OLED_LINE2 26 -#define OLED_LINE3 36 -#define OLED_LINE4 46 -#define OLED_LINE5 56 +#define OLED_LINE1 8 //16 +#define OLED_LINE2 18 //26 +#define OLED_LINE3 28 //36 +#define OLED_LINE4 37 //46 +#define OLED_LINE5 47 //56 +#define OLED_LINE6 57 #include "Display.h" #include "Defines.h" @@ -34,11 +35,12 @@ #include "ArduiPi_OLED_lib.h" #include "Adafruit_GFX.h" #include "ArduiPi_OLED.h" +#include "NetworkInfo.h" class COLED : public CDisplay { public: - COLED(unsigned char displayType, unsigned char displayBrighness, bool displayInvert, bool displayScroll); + COLED(unsigned char displayType, unsigned char displayBrighness, bool displayInvert, bool displayScroll, bool slot1Enabled, bool slot2Enabled); virtual ~COLED(); virtual bool open(); @@ -76,7 +78,10 @@ private: unsigned char m_displayBrightness; bool m_displayInvert; bool m_displayScroll; - + bool m_slot1Enabled; + bool m_slot2Enabled; + std::string m_ipaddress; + ArduiPi_OLED display; void OLED_statusbar(); };