Merge remote-tracking branch 'g4klx/master'

This commit is contained in:
Andy CA6JAU 2017-12-26 18:06:50 -03:00
commit bafa100e66
110 changed files with 20544 additions and 1430 deletions

290
Conf.cpp
View file

@ -55,10 +55,9 @@ enum SECTION {
CConf::CConf(const std::string& file) : CConf::CConf(const std::string& file) :
m_file(file), m_file(file),
m_callsign(), m_callsign(),
m_id(0U),
m_timeout(120U), m_timeout(120U),
m_duplex(true), m_duplex(true),
m_rfModeHang(10U),
m_netModeHang(3U),
m_display(), m_display(),
m_daemon(false), m_daemon(false),
m_rxFrequency(0U), m_rxFrequency(0U),
@ -85,12 +84,16 @@ m_modemTXInvert(false),
m_modemPTTInvert(false), m_modemPTTInvert(false),
m_modemTXDelay(100U), m_modemTXDelay(100U),
m_modemDMRDelay(0U), m_modemDMRDelay(0U),
m_modemRXLevel(50U), m_modemTXOffset(0),
m_modemCWIdTXLevel(50U), m_modemRXOffset(0),
m_modemDStarTXLevel(50U), m_modemRXDCOffset(0),
m_modemDMRTXLevel(50U), m_modemTXDCOffset(0),
m_modemYSFTXLevel(50U), m_modemRXLevel(50.0F),
m_modemP25TXLevel(50U), m_modemCWIdTXLevel(50.0F),
m_modemDStarTXLevel(50.0F),
m_modemDMRTXLevel(50.0F),
m_modemYSFTXLevel(50.0F),
m_modemP25TXLevel(50.0F),
m_modemRSSIMappingFile(), m_modemRSSIMappingFile(),
m_modemTrace(false), m_modemTrace(false),
m_modemDebug(false), m_modemDebug(false),
@ -100,7 +103,11 @@ m_dstarEnabled(false),
m_dstarModule("C"), m_dstarModule("C"),
m_dstarSelfOnly(false), m_dstarSelfOnly(false),
m_dstarBlackList(), m_dstarBlackList(),
m_dstarAckReply(true),
m_dstarAckTime(750U),
m_dstarErrorReply(true), m_dstarErrorReply(true),
m_dstarRemoteGateway(false),
m_dstarModeHang(10U),
m_dmrEnabled(false), m_dmrEnabled(false),
m_dmrBeacons(false), m_dmrBeacons(false),
m_dmrId(0U), m_dmrId(0U),
@ -115,15 +122,26 @@ m_dmrSlot1TGWhiteList(),
m_dmrSlot2TGWhiteList(), m_dmrSlot2TGWhiteList(),
m_dmrCallHang(3U), m_dmrCallHang(3U),
m_dmrTXHang(4U), m_dmrTXHang(4U),
m_dmrModeHang(10U),
m_fusionEnabled(false), m_fusionEnabled(false),
m_fusionLowDeviation(false), m_fusionLowDeviation(false),
m_fusionRemoteGateway(false), m_fusionRemoteGateway(false),
m_fusionSelfOnly(false),
m_fusionSQLEnabled(false),
m_fusionSQL(0U),
m_fusionModeHang(10U),
m_p25Enabled(false), m_p25Enabled(false),
m_p25Id(0U),
m_p25NAC(0x293U), m_p25NAC(0x293U),
m_p25SelfOnly(false),
m_p25OverrideUID(false),
m_p25RemoteGateway(false),
m_p25ModeHang(10U),
m_dstarNetworkEnabled(false), m_dstarNetworkEnabled(false),
m_dstarGatewayAddress(), m_dstarGatewayAddress(),
m_dstarGatewayPort(0U), m_dstarGatewayPort(0U),
m_dstarLocalPort(0U), m_dstarLocalPort(0U),
m_dstarNetworkModeHang(3U),
m_dstarNetworkDebug(false), m_dstarNetworkDebug(false),
m_dmrNetworkEnabled(false), m_dmrNetworkEnabled(false),
m_dmrNetworkAddress(), m_dmrNetworkAddress(),
@ -135,18 +153,20 @@ m_dmrNetworkDebug(false),
m_dmrNetworkJitter(300U), m_dmrNetworkJitter(300U),
m_dmrNetworkSlot1(true), m_dmrNetworkSlot1(true),
m_dmrNetworkSlot2(true), m_dmrNetworkSlot2(true),
m_dmrNetworkModeHang(3U),
m_fusionNetworkEnabled(false), m_fusionNetworkEnabled(false),
m_fusionNetworkMyAddress(), m_fusionNetworkMyAddress(),
m_fusionNetworkMyPort(0U), m_fusionNetworkMyPort(0U),
m_fusionNetworkGwyAddress(), m_fusionNetworkGatewayAddress(),
m_fusionNetworkGwyPort(0U), m_fusionNetworkGatewayPort(0U),
m_fusionNetworkModeHang(3U),
m_fusionNetworkDebug(false), m_fusionNetworkDebug(false),
m_p25NetworkEnabled(false), m_p25NetworkEnabled(false),
m_p25GatewayAddress(), m_p25GatewayAddress(),
m_p25GatewayPort(0U), m_p25GatewayPort(0U),
m_p25LocalPort(0U), m_p25LocalPort(0U),
m_p25NetworkModeHang(3U),
m_p25NetworkDebug(false), m_p25NetworkDebug(false),
m_p25OverrideUID(false),
m_tftSerialPort("/dev/ttyAMA0"), m_tftSerialPort("/dev/ttyAMA0"),
m_tftSerialBrightness(50U), m_tftSerialBrightness(50U),
m_hd44780Rows(2U), m_hd44780Rows(2U),
@ -164,9 +184,11 @@ m_nextionBrightness(50U),
m_nextionDisplayClock(false), m_nextionDisplayClock(false),
m_nextionUTC(false), m_nextionUTC(false),
m_nextionIdleBrightness(20U), m_nextionIdleBrightness(20U),
m_nextionScreenLayout(0U),
m_oledType(3U), m_oledType(3U),
m_oledBrightness(0U), m_oledBrightness(0U),
m_oledInvert(false), m_oledInvert(false),
m_oledScroll(false),
m_lcdprocAddress(), m_lcdprocAddress(),
m_lcdprocPort(0U), m_lcdprocPort(0U),
m_lcdprocLocalPort(0U), m_lcdprocLocalPort(0U),
@ -255,16 +277,19 @@ bool CConf::read()
for (unsigned int i = 0U; value[i] != 0; i++) for (unsigned int i = 0U; value[i] != 0; i++)
value[i] = ::toupper(value[i]); value[i] = ::toupper(value[i]);
m_cwIdCallsign = m_callsign = value; m_cwIdCallsign = m_callsign = value;
} else if (::strcmp(key, "Timeout") == 0) } else if (::strcmp(key, "Id") == 0)
m_id = m_p25Id = m_dmrId = (unsigned int)::atoi(value);
else if (::strcmp(key, "Timeout") == 0)
m_timeout = (unsigned int)::atoi(value); m_timeout = (unsigned int)::atoi(value);
else if (::strcmp(key, "Duplex") == 0) else if (::strcmp(key, "Duplex") == 0)
m_duplex = ::atoi(value) == 1; m_duplex = ::atoi(value) == 1;
else if (::strcmp(key, "ModeHang") == 0) else if (::strcmp(key, "ModeHang") == 0)
m_rfModeHang = m_netModeHang = (unsigned int)::atoi(value); m_dstarNetworkModeHang = m_dmrNetworkModeHang = m_fusionNetworkModeHang = m_p25NetworkModeHang =
m_dstarModeHang = m_dmrModeHang = m_fusionModeHang = m_p25ModeHang = (unsigned int)::atoi(value);
else if (::strcmp(key, "RFModeHang") == 0) else if (::strcmp(key, "RFModeHang") == 0)
m_rfModeHang = (unsigned int)::atoi(value); m_dstarModeHang = m_dmrModeHang = m_fusionModeHang = m_p25ModeHang = (unsigned int)::atoi(value);
else if (::strcmp(key, "NetModeHang") == 0) else if (::strcmp(key, "NetModeHang") == 0)
m_netModeHang = (unsigned int)::atoi(value); m_dstarNetworkModeHang = m_dmrNetworkModeHang = m_fusionNetworkModeHang = m_p25NetworkModeHang = (unsigned int)::atoi(value);
else if (::strcmp(key, "Display") == 0) else if (::strcmp(key, "Display") == 0)
m_display = value; m_display = value;
else if (::strcmp(key, "Daemon") == 0) else if (::strcmp(key, "Daemon") == 0)
@ -326,20 +351,28 @@ bool CConf::read()
m_modemTXDelay = (unsigned int)::atoi(value); m_modemTXDelay = (unsigned int)::atoi(value);
else if (::strcmp(key, "DMRDelay") == 0) else if (::strcmp(key, "DMRDelay") == 0)
m_modemDMRDelay = (unsigned int)::atoi(value); m_modemDMRDelay = (unsigned int)::atoi(value);
else if (::strcmp(key, "RXOffset") == 0)
m_modemRXOffset = ::atoi(value);
else if (::strcmp(key, "TXOffset") == 0)
m_modemTXOffset = ::atoi(value);
else if (::strcmp(key, "RXDCOffset") == 0)
m_modemRXDCOffset = ::atoi(value);
else if (::strcmp(key, "TXDCOffset") == 0)
m_modemTXDCOffset = ::atoi(value);
else if (::strcmp(key, "RXLevel") == 0) else if (::strcmp(key, "RXLevel") == 0)
m_modemRXLevel = (unsigned int)::atoi(value); m_modemRXLevel = float(::atof(value));
else if (::strcmp(key, "TXLevel") == 0) else if (::strcmp(key, "TXLevel") == 0)
m_modemCWIdTXLevel = m_modemDStarTXLevel = m_modemDMRTXLevel = m_modemYSFTXLevel = m_modemP25TXLevel = (unsigned int)::atoi(value); m_modemCWIdTXLevel = m_modemDStarTXLevel = m_modemDMRTXLevel = m_modemYSFTXLevel = m_modemP25TXLevel = float(::atof(value));
else if (::strcmp(key, "CWIdTXLevel") == 0) else if (::strcmp(key, "CWIdTXLevel") == 0)
m_modemCWIdTXLevel = (unsigned int)::atoi(value); m_modemCWIdTXLevel = float(::atof(value));
else if (::strcmp(key, "D-StarTXLevel") == 0) else if (::strcmp(key, "D-StarTXLevel") == 0)
m_modemDStarTXLevel = (unsigned int)::atoi(value); m_modemDStarTXLevel = float(::atof(value));
else if (::strcmp(key, "DMRTXLevel") == 0) else if (::strcmp(key, "DMRTXLevel") == 0)
m_modemDMRTXLevel = (unsigned int)::atoi(value); m_modemDMRTXLevel = float(::atof(value));
else if (::strcmp(key, "YSFTXLevel") == 0) else if (::strcmp(key, "YSFTXLevel") == 0)
m_modemYSFTXLevel = (unsigned int)::atoi(value); m_modemYSFTXLevel = float(::atof(value));
else if (::strcmp(key, "P25TXLevel") == 0) else if (::strcmp(key, "P25TXLevel") == 0)
m_modemP25TXLevel = (unsigned int)::atoi(value); m_modemP25TXLevel = float(::atof(value));
else if (::strcmp(key, "RSSIMappingFile") == 0) else if (::strcmp(key, "RSSIMappingFile") == 0)
m_modemRSSIMappingFile = value; m_modemRSSIMappingFile = value;
else if (::strcmp(key, "Trace") == 0) else if (::strcmp(key, "Trace") == 0)
@ -373,8 +406,16 @@ bool CConf::read()
} }
p = ::strtok(NULL, ",\r\n"); p = ::strtok(NULL, ",\r\n");
} }
} else if (::strcmp(key, "ErrorReply") == 0) } else if (::strcmp(key, "AckReply") == 0)
m_dstarAckReply = ::atoi(value) == 1;
else if (::strcmp(key, "AckTime") == 0)
m_dstarAckTime = (unsigned int)::atoi(value);
else if (::strcmp(key, "ErrorReply") == 0)
m_dstarErrorReply = ::atoi(value) == 1; m_dstarErrorReply = ::atoi(value) == 1;
else if (::strcmp(key, "RemoteGateway") == 0)
m_dstarRemoteGateway = ::atoi(value) == 1;
else if (::strcmp(key, "ModeHang") == 0)
m_dstarModeHang = (unsigned int)::atoi(value);
} else if (section == SECTION_DMR) { } else if (section == SECTION_DMR) {
if (::strcmp(key, "Enable") == 0) if (::strcmp(key, "Enable") == 0)
m_dmrEnabled = ::atoi(value) == 1; m_dmrEnabled = ::atoi(value) == 1;
@ -434,20 +475,37 @@ bool CConf::read()
m_dmrTXHang = (unsigned int)::atoi(value); m_dmrTXHang = (unsigned int)::atoi(value);
else if (::strcmp(key, "CallHang") == 0) else if (::strcmp(key, "CallHang") == 0)
m_dmrCallHang = (unsigned int)::atoi(value); m_dmrCallHang = (unsigned int)::atoi(value);
else if (::strcmp(key, "ModeHang") == 0)
m_dmrModeHang = (unsigned int)::atoi(value);
} else if (section == SECTION_FUSION) { } else if (section == SECTION_FUSION) {
if (::strcmp(key, "Enable") == 0) if (::strcmp(key, "Enable") == 0)
m_fusionEnabled = ::atoi(value) == 1; m_fusionEnabled = ::atoi(value) == 1;
else if (::strcmp(key, "LowDeviation") == 0) else if (::strcmp(key, "LowDeviation") == 0)
m_fusionLowDeviation = ::atoi(value) == 1; m_fusionLowDeviation = ::atoi(value) == 1;
else if (::strcmp(key, "RemoteGateway") == 0) else if (::strcmp(key, "DSQ") == 0) {
m_fusionSQLEnabled = true;
m_fusionSQL = (unsigned int)::atoi(value);
} else if (::strcmp(key, "RemoteGateway") == 0)
m_fusionRemoteGateway = ::atoi(value) == 1; m_fusionRemoteGateway = ::atoi(value) == 1;
else if (::strcmp(key, "SelfOnly") == 0)
m_fusionSelfOnly = ::atoi(value) == 1;
else if (::strcmp(key, "ModeHang") == 0)
m_fusionModeHang = (unsigned int)::atoi(value);
} else if (section == SECTION_P25) { } else if (section == SECTION_P25) {
if (::strcmp(key, "Enable") == 0) if (::strcmp(key, "Enable") == 0)
m_p25Enabled = ::atoi(value) == 1; m_p25Enabled = ::atoi(value) == 1;
else if (::strcmp(key, "Id") == 0)
m_p25Id = (unsigned int)::atoi(value);
else if (::strcmp(key, "NAC") == 0) else if (::strcmp(key, "NAC") == 0)
m_p25NAC = (unsigned int)::strtoul(value, NULL, 16); m_p25NAC = (unsigned int)::strtoul(value, NULL, 16);
else if (::strcmp(key, "OverrideUIDCheck") == 0) else if (::strcmp(key, "OverrideUIDCheck") == 0)
m_p25OverrideUID = ::atoi(value) == 1; m_p25OverrideUID = ::atoi(value) == 1;
else if (::strcmp(key, "SelfOnly") == 0)
m_p25SelfOnly = ::atoi(value) == 1;
else if (::strcmp(key, "RemoteGateway") == 0)
m_p25RemoteGateway = ::atoi(value) == 1;
else if (::strcmp(key, "ModeHang") == 0)
m_p25ModeHang = (unsigned int)::atoi(value);
} else if (section == SECTION_DSTAR_NETWORK) { } else if (section == SECTION_DSTAR_NETWORK) {
if (::strcmp(key, "Enable") == 0) if (::strcmp(key, "Enable") == 0)
m_dstarNetworkEnabled = ::atoi(value) == 1; m_dstarNetworkEnabled = ::atoi(value) == 1;
@ -457,6 +515,8 @@ bool CConf::read()
m_dstarGatewayPort = (unsigned int)::atoi(value); m_dstarGatewayPort = (unsigned int)::atoi(value);
else if (::strcmp(key, "LocalPort") == 0) else if (::strcmp(key, "LocalPort") == 0)
m_dstarLocalPort = (unsigned int)::atoi(value); m_dstarLocalPort = (unsigned int)::atoi(value);
else if (::strcmp(key, "ModeHang") == 0)
m_dstarNetworkModeHang = (unsigned int)::atoi(value);
else if (::strcmp(key, "Debug") == 0) else if (::strcmp(key, "Debug") == 0)
m_dstarNetworkDebug = ::atoi(value) == 1; m_dstarNetworkDebug = ::atoi(value) == 1;
} else if (section == SECTION_DMR_NETWORK) { } else if (section == SECTION_DMR_NETWORK) {
@ -480,6 +540,8 @@ bool CConf::read()
m_dmrNetworkSlot1 = ::atoi(value) == 1; m_dmrNetworkSlot1 = ::atoi(value) == 1;
else if (::strcmp(key, "Slot2") == 0) else if (::strcmp(key, "Slot2") == 0)
m_dmrNetworkSlot2 = ::atoi(value) == 1; m_dmrNetworkSlot2 = ::atoi(value) == 1;
else if (::strcmp(key, "ModeHang") == 0)
m_dmrNetworkModeHang = (unsigned int)::atoi(value);
} else if (section == SECTION_FUSION_NETWORK) { } else if (section == SECTION_FUSION_NETWORK) {
if (::strcmp(key, "Enable") == 0) if (::strcmp(key, "Enable") == 0)
m_fusionNetworkEnabled = ::atoi(value) == 1; m_fusionNetworkEnabled = ::atoi(value) == 1;
@ -487,10 +549,12 @@ bool CConf::read()
m_fusionNetworkMyAddress = value; m_fusionNetworkMyAddress = value;
else if (::strcmp(key, "LocalPort") == 0) else if (::strcmp(key, "LocalPort") == 0)
m_fusionNetworkMyPort = (unsigned int)::atoi(value); m_fusionNetworkMyPort = (unsigned int)::atoi(value);
else if (::strcmp(key, "GwyAddress") == 0) else if (::strcmp(key, "GatewayAddress") == 0)
m_fusionNetworkGwyAddress = value; m_fusionNetworkGatewayAddress = value;
else if (::strcmp(key, "GwyPort") == 0) else if (::strcmp(key, "GatewayPort") == 0)
m_fusionNetworkGwyPort = (unsigned int)::atoi(value); m_fusionNetworkGatewayPort = (unsigned int)::atoi(value);
else if (::strcmp(key, "ModeHang") == 0)
m_fusionNetworkModeHang = (unsigned int)::atoi(value);
else if (::strcmp(key, "Debug") == 0) else if (::strcmp(key, "Debug") == 0)
m_fusionNetworkDebug = ::atoi(value) == 1; m_fusionNetworkDebug = ::atoi(value) == 1;
} else if (section == SECTION_P25_NETWORK) { } else if (section == SECTION_P25_NETWORK) {
@ -502,6 +566,8 @@ bool CConf::read()
m_p25GatewayPort = (unsigned int)::atoi(value); m_p25GatewayPort = (unsigned int)::atoi(value);
else if (::strcmp(key, "LocalPort") == 0) else if (::strcmp(key, "LocalPort") == 0)
m_p25LocalPort = (unsigned int)::atoi(value); m_p25LocalPort = (unsigned int)::atoi(value);
else if (::strcmp(key, "ModeHang") == 0)
m_p25NetworkModeHang = (unsigned int)::atoi(value);
else if (::strcmp(key, "Debug") == 0) else if (::strcmp(key, "Debug") == 0)
m_p25NetworkDebug = ::atoi(value) == 1; m_p25NetworkDebug = ::atoi(value) == 1;
} else if (section == SECTION_TFTSERIAL) { } else if (section == SECTION_TFTSERIAL) {
@ -547,6 +613,8 @@ bool CConf::read()
m_nextionUTC = ::atoi(value) == 1; m_nextionUTC = ::atoi(value) == 1;
else if (::strcmp(key, "IdleBrightness") == 0) else if (::strcmp(key, "IdleBrightness") == 0)
m_nextionIdleBrightness = (unsigned int)::atoi(value); m_nextionIdleBrightness = (unsigned int)::atoi(value);
else if (::strcmp(key, "ScreenLayout") == 0)
m_nextionScreenLayout = (unsigned int)::atoi(value);
} 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);
@ -554,6 +622,8 @@ bool CConf::read()
m_oledBrightness = (unsigned char)::atoi(value); m_oledBrightness = (unsigned char)::atoi(value);
else if (::strcmp(key, "Invert") == 0) else if (::strcmp(key, "Invert") == 0)
m_oledInvert = ::atoi(value) == 1; m_oledInvert = ::atoi(value) == 1;
else if (::strcmp(key, "Scroll") == 0)
m_oledScroll = ::atoi(value) == 1;
} else if (section == SECTION_LCDPROC) { } else if (section == SECTION_LCDPROC) {
if (::strcmp(key, "Address") == 0) if (::strcmp(key, "Address") == 0)
m_lcdprocAddress = value; m_lcdprocAddress = value;
@ -580,6 +650,11 @@ std::string CConf::getCallsign() const
return m_callsign; return m_callsign;
} }
unsigned int CConf::getId() const
{
return m_id;
}
unsigned int CConf::getTimeout() const unsigned int CConf::getTimeout() const
{ {
return m_timeout; return m_timeout;
@ -590,16 +665,6 @@ bool CConf::getDuplex() const
return m_duplex; return m_duplex;
} }
unsigned int CConf::getRFModeHang() const
{
return m_rfModeHang;
}
unsigned int CConf::getNetModeHang() const
{
return m_netModeHang;
}
std::string CConf::getDisplay() const std::string CConf::getDisplay() const
{ {
return m_display; return m_display;
@ -610,12 +675,12 @@ bool CConf::getDaemon() const
return m_daemon; return m_daemon;
} }
unsigned int CConf::getRxFrequency() const unsigned int CConf::getRXFrequency() const
{ {
return m_rxFrequency; return m_rxFrequency;
} }
unsigned int CConf::getTxFrequency() const unsigned int CConf::getTXFrequency() const
{ {
return m_txFrequency; return m_txFrequency;
} }
@ -730,32 +795,52 @@ unsigned int CConf::getModemDMRDelay() const
return m_modemDMRDelay; return m_modemDMRDelay;
} }
unsigned int CConf::getModemRXLevel() const int CConf::getModemRXOffset() const
{
return m_modemRXOffset;
}
int CConf::getModemTXOffset() const
{
return m_modemTXOffset;
}
int CConf::getModemRXDCOffset() const
{
return m_modemRXDCOffset;
}
int CConf::getModemTXDCOffset() const
{
return m_modemTXDCOffset;
}
float CConf::getModemRXLevel() const
{ {
return m_modemRXLevel; return m_modemRXLevel;
} }
unsigned int CConf::getModemCWIdTXLevel() const float CConf::getModemCWIdTXLevel() const
{ {
return m_modemCWIdTXLevel; return m_modemCWIdTXLevel;
} }
unsigned int CConf::getModemDStarTXLevel() const float CConf::getModemDStarTXLevel() const
{ {
return m_modemDStarTXLevel; return m_modemDStarTXLevel;
} }
unsigned int CConf::getModemDMRTXLevel() const float CConf::getModemDMRTXLevel() const
{ {
return m_modemDMRTXLevel; return m_modemDMRTXLevel;
} }
unsigned int CConf::getModemYSFTXLevel() const float CConf::getModemYSFTXLevel() const
{ {
return m_modemYSFTXLevel; return m_modemYSFTXLevel;
} }
unsigned int CConf::getModemP25TXLevel() const float CConf::getModemP25TXLevel() const
{ {
return m_modemP25TXLevel; return m_modemP25TXLevel;
} }
@ -805,11 +890,31 @@ std::vector<std::string> CConf::getDStarBlackList() const
return m_dstarBlackList; return m_dstarBlackList;
} }
bool CConf::getDStarAckReply() const
{
return m_dstarAckReply;
}
unsigned int CConf::getDStarAckTime() const
{
return m_dstarAckTime;
}
bool CConf::getDStarErrorReply() const bool CConf::getDStarErrorReply() const
{ {
return m_dstarErrorReply; return m_dstarErrorReply;
} }
bool CConf::getDStarRemoteGateway() const
{
return m_dstarRemoteGateway;
}
unsigned int CConf::getDStarModeHang() const
{
return m_dstarModeHang;
}
bool CConf::getDMREnabled() const bool CConf::getDMREnabled() const
{ {
return m_dmrEnabled; return m_dmrEnabled;
@ -880,6 +985,11 @@ unsigned int CConf::getDMRTXHang() const
return m_dmrTXHang; return m_dmrTXHang;
} }
unsigned int CConf::getDMRModeHang() const
{
return m_dmrModeHang;
}
bool CConf::getFusionEnabled() const bool CConf::getFusionEnabled() const
{ {
return m_fusionEnabled; return m_fusionEnabled;
@ -895,16 +1005,61 @@ bool CConf::getFusionRemoteGateway() const
return m_fusionRemoteGateway; return m_fusionRemoteGateway;
} }
bool CConf::getFusionSelfOnly() const
{
return m_fusionSelfOnly;
}
bool CConf::getFusionSQLEnabled() const
{
return m_fusionSQLEnabled;
}
unsigned char CConf::getFusionSQL() const
{
return m_fusionSQL;
}
unsigned int CConf::getFusionModeHang() const
{
return m_fusionModeHang;
}
bool CConf::getP25Enabled() const bool CConf::getP25Enabled() const
{ {
return m_p25Enabled; return m_p25Enabled;
} }
unsigned int CConf::getP25Id() const
{
return m_p25Id;
}
unsigned int CConf::getP25NAC() const unsigned int CConf::getP25NAC() const
{ {
return m_p25NAC; return m_p25NAC;
} }
bool CConf::getP25OverrideUID() const
{
return m_p25OverrideUID;
}
bool CConf::getP25SelfOnly() const
{
return m_p25SelfOnly;
}
bool CConf::getP25RemoteGateway() const
{
return m_p25RemoteGateway;
}
unsigned int CConf::getP25ModeHang() const
{
return m_p25ModeHang;
}
bool CConf::getDStarNetworkEnabled() const bool CConf::getDStarNetworkEnabled() const
{ {
return m_dstarNetworkEnabled; return m_dstarNetworkEnabled;
@ -925,6 +1080,11 @@ unsigned int CConf::getDStarLocalPort() const
return m_dstarLocalPort; return m_dstarLocalPort;
} }
unsigned int CConf::getDStarNetworkModeHang() const
{
return m_dstarNetworkModeHang;
}
bool CConf::getDStarNetworkDebug() const bool CConf::getDStarNetworkDebug() const
{ {
return m_dstarNetworkDebug; return m_dstarNetworkDebug;
@ -960,6 +1120,11 @@ std::string CConf::getDMRNetworkOptions() const
return m_dmrNetworkOptions; return m_dmrNetworkOptions;
} }
unsigned int CConf::getDMRNetworkModeHang() const
{
return m_dmrNetworkModeHang;
}
bool CConf::getDMRNetworkDebug() const bool CConf::getDMRNetworkDebug() const
{ {
return m_dmrNetworkDebug; return m_dmrNetworkDebug;
@ -995,14 +1160,19 @@ unsigned int CConf::getFusionNetworkMyPort() const
return m_fusionNetworkMyPort; return m_fusionNetworkMyPort;
} }
std::string CConf::getFusionNetworkGwyAddress() const std::string CConf::getFusionNetworkGatewayAddress() const
{ {
return m_fusionNetworkGwyAddress; return m_fusionNetworkGatewayAddress;
} }
unsigned int CConf::getFusionNetworkGwyPort() const unsigned int CConf::getFusionNetworkGatewayPort() const
{ {
return m_fusionNetworkGwyPort; return m_fusionNetworkGatewayPort;
}
unsigned int CConf::getFusionNetworkModeHang() const
{
return m_fusionNetworkModeHang;
} }
bool CConf::getFusionNetworkDebug() const bool CConf::getFusionNetworkDebug() const
@ -1030,16 +1200,16 @@ unsigned int CConf::getP25LocalPort() const
return m_p25LocalPort; return m_p25LocalPort;
} }
unsigned int CConf::getP25NetworkModeHang() const
{
return m_p25NetworkModeHang;
}
bool CConf::getP25NetworkDebug() const bool CConf::getP25NetworkDebug() const
{ {
return m_p25NetworkDebug; return m_p25NetworkDebug;
} }
bool CConf::getP25OverrideUID() const
{
return m_p25OverrideUID;
}
std::string CConf::getTFTSerialPort() const std::string CConf::getTFTSerialPort() const
{ {
return m_tftSerialPort; return m_tftSerialPort;
@ -1125,6 +1295,11 @@ unsigned int CConf::getNextionIdleBrightness() const
return m_nextionIdleBrightness; return m_nextionIdleBrightness;
} }
unsigned int CConf::getNextionScreenLayout() const
{
return m_nextionScreenLayout;
}
unsigned char CConf::getOLEDType() const unsigned char CConf::getOLEDType() const
{ {
return m_oledType; return m_oledType;
@ -1140,6 +1315,11 @@ bool CConf::getOLEDInvert() const
return m_oledInvert; return m_oledInvert;
} }
bool CConf::getOLEDScroll() const
{
return m_oledScroll;
}
std::string CConf::getLCDprocAddress() const std::string CConf::getLCDprocAddress() const
{ {
return m_lcdprocAddress; return m_lcdprocAddress;

92
Conf.h
View file

@ -32,16 +32,15 @@ public:
// The General section // The General section
std::string getCallsign() const; std::string getCallsign() const;
unsigned int getId() const;
unsigned int getTimeout() const; unsigned int getTimeout() const;
bool getDuplex() const; bool getDuplex() const;
unsigned int getRFModeHang() const;
unsigned int getNetModeHang() const;
std::string getDisplay() const; std::string getDisplay() const;
bool getDaemon() const; bool getDaemon() const;
// The Info section // The Info section
unsigned int getRxFrequency() const; unsigned int getRXFrequency() const;
unsigned int getTxFrequency() const; unsigned int getTXFrequency() const;
unsigned int getPower() const; unsigned int getPower() const;
float getLatitude() const; float getLatitude() const;
float getLongitude() const; float getLongitude() const;
@ -72,12 +71,16 @@ public:
bool getModemPTTInvert() const; bool getModemPTTInvert() const;
unsigned int getModemTXDelay() const; unsigned int getModemTXDelay() const;
unsigned int getModemDMRDelay() const; unsigned int getModemDMRDelay() const;
unsigned int getModemRXLevel() const; int getModemTXOffset() const;
unsigned int getModemCWIdTXLevel() const; int getModemRXOffset() const;
unsigned int getModemDStarTXLevel() const; int getModemRXDCOffset() const;
unsigned int getModemDMRTXLevel() const; int getModemTXDCOffset() const;
unsigned int getModemYSFTXLevel() const; float getModemRXLevel() const;
unsigned int getModemP25TXLevel() const; float getModemCWIdTXLevel() const;
float getModemDStarTXLevel() const;
float getModemDMRTXLevel() const;
float getModemYSFTXLevel() const;
float getModemP25TXLevel() const;
std::string getModemRSSIMappingFile() const; std::string getModemRSSIMappingFile() const;
bool getModemTrace() const; bool getModemTrace() const;
bool getModemDebug() const; bool getModemDebug() const;
@ -91,7 +94,11 @@ public:
std::string getDStarModule() const; std::string getDStarModule() const;
bool getDStarSelfOnly() const; bool getDStarSelfOnly() const;
std::vector<std::string> getDStarBlackList() const; std::vector<std::string> getDStarBlackList() const;
bool getDStarAckReply() const;
unsigned int getDStarAckTime() const;
bool getDStarErrorReply() const; bool getDStarErrorReply() const;
bool getDStarRemoteGateway() const;
unsigned int getDStarModeHang() const;
// The DMR section // The DMR section
bool getDMREnabled() const; bool getDMREnabled() const;
@ -108,21 +115,32 @@ public:
std::vector<unsigned int> getDMRSlot2TGWhiteList() const; std::vector<unsigned int> getDMRSlot2TGWhiteList() const;
unsigned int getDMRCallHang() const; unsigned int getDMRCallHang() const;
unsigned int getDMRTXHang() const; unsigned int getDMRTXHang() const;
unsigned int getDMRModeHang() const;
// The System Fusion section // The System Fusion section
bool getFusionEnabled() const; bool getFusionEnabled() const;
bool getFusionLowDeviation() const; bool getFusionLowDeviation() const;
bool getFusionRemoteGateway() const; bool getFusionRemoteGateway() const;
bool getFusionSelfOnly() const;
bool getFusionSQLEnabled() const;
unsigned char getFusionSQL() const;
unsigned int getFusionModeHang() const;
// The P25 section // The P25 section
bool getP25Enabled() const; bool getP25Enabled() const;
unsigned int getP25Id() const;
unsigned int getP25NAC() const; unsigned int getP25NAC() const;
bool getP25SelfOnly() const;
bool getP25OverrideUID() const;
bool getP25RemoteGateway() const;
unsigned int getP25ModeHang() const;
// The D-Star Network section // The D-Star Network section
bool getDStarNetworkEnabled() const; bool getDStarNetworkEnabled() const;
std::string getDStarGatewayAddress() const; std::string getDStarGatewayAddress() const;
unsigned int getDStarGatewayPort() const; unsigned int getDStarGatewayPort() const;
unsigned int getDStarLocalPort() const; unsigned int getDStarLocalPort() const;
unsigned int getDStarNetworkModeHang() const;
bool getDStarNetworkDebug() const; bool getDStarNetworkDebug() const;
// The DMR Network section // The DMR Network section
@ -136,13 +154,15 @@ public:
unsigned int getDMRNetworkJitter() const; unsigned int getDMRNetworkJitter() const;
bool getDMRNetworkSlot1() const; bool getDMRNetworkSlot1() const;
bool getDMRNetworkSlot2() const; bool getDMRNetworkSlot2() const;
unsigned int getDMRNetworkModeHang() const;
// The System Fusion Network section // The System Fusion Network section
bool getFusionNetworkEnabled() const; bool getFusionNetworkEnabled() const;
std::string getFusionNetworkMyAddress() const; std::string getFusionNetworkMyAddress() const;
unsigned int getFusionNetworkMyPort() const; unsigned int getFusionNetworkMyPort() const;
std::string getFusionNetworkGwyAddress() const; std::string getFusionNetworkGatewayAddress() const;
unsigned int getFusionNetworkGwyPort() const; unsigned int getFusionNetworkGatewayPort() const;
unsigned int getFusionNetworkModeHang() const;
bool getFusionNetworkDebug() const; bool getFusionNetworkDebug() const;
// The P25 Network section // The P25 Network section
@ -150,8 +170,8 @@ public:
std::string getP25GatewayAddress() const; std::string getP25GatewayAddress() const;
unsigned int getP25GatewayPort() const; unsigned int getP25GatewayPort() const;
unsigned int getP25LocalPort() const; unsigned int getP25LocalPort() const;
unsigned int getP25NetworkModeHang() const;
bool getP25NetworkDebug() const; bool getP25NetworkDebug() const;
bool getP25OverrideUID() const;
// The TFTSERIAL section // The TFTSERIAL section
std::string getTFTSerialPort() const; std::string getTFTSerialPort() const;
@ -175,11 +195,13 @@ public:
bool getNextionDisplayClock() const; bool getNextionDisplayClock() const;
bool getNextionUTC() const; bool getNextionUTC() const;
unsigned int getNextionIdleBrightness() const; unsigned int getNextionIdleBrightness() const;
unsigned int getNextionScreenLayout() const;
// The OLED section // The OLED section
unsigned char getOLEDType() const; unsigned char getOLEDType() const;
unsigned char getOLEDBrightness() const; unsigned char getOLEDBrightness() const;
bool getOLEDInvert() const; bool getOLEDInvert() const;
bool getOLEDScroll() const;
// The LCDproc section // The LCDproc section
std::string getLCDprocAddress() const; std::string getLCDprocAddress() const;
@ -192,10 +214,9 @@ public:
private: private:
std::string m_file; std::string m_file;
std::string m_callsign; std::string m_callsign;
unsigned int m_id;
unsigned int m_timeout; unsigned int m_timeout;
bool m_duplex; bool m_duplex;
unsigned int m_rfModeHang;
unsigned int m_netModeHang;
std::string m_display; std::string m_display;
bool m_daemon; bool m_daemon;
@ -227,12 +248,16 @@ private:
bool m_modemPTTInvert; bool m_modemPTTInvert;
unsigned int m_modemTXDelay; unsigned int m_modemTXDelay;
unsigned int m_modemDMRDelay; unsigned int m_modemDMRDelay;
unsigned int m_modemRXLevel; int m_modemTXOffset;
unsigned int m_modemCWIdTXLevel; int m_modemRXOffset;
unsigned int m_modemDStarTXLevel; int m_modemRXDCOffset;
unsigned int m_modemDMRTXLevel; int m_modemTXDCOffset;
unsigned int m_modemYSFTXLevel; float m_modemRXLevel;
unsigned int m_modemP25TXLevel; float m_modemCWIdTXLevel;
float m_modemDStarTXLevel;
float m_modemDMRTXLevel;
float m_modemYSFTXLevel;
float m_modemP25TXLevel;
std::string m_modemRSSIMappingFile; std::string m_modemRSSIMappingFile;
bool m_modemTrace; bool m_modemTrace;
bool m_modemDebug; bool m_modemDebug;
@ -244,7 +269,11 @@ private:
std::string m_dstarModule; std::string m_dstarModule;
bool m_dstarSelfOnly; bool m_dstarSelfOnly;
std::vector<std::string> m_dstarBlackList; std::vector<std::string> m_dstarBlackList;
bool m_dstarAckReply;
unsigned int m_dstarAckTime;
bool m_dstarErrorReply; bool m_dstarErrorReply;
bool m_dstarRemoteGateway;
unsigned int m_dstarModeHang;
bool m_dmrEnabled; bool m_dmrEnabled;
bool m_dmrBeacons; bool m_dmrBeacons;
@ -260,18 +289,29 @@ private:
std::vector<unsigned int> m_dmrSlot2TGWhiteList; std::vector<unsigned int> m_dmrSlot2TGWhiteList;
unsigned int m_dmrCallHang; unsigned int m_dmrCallHang;
unsigned int m_dmrTXHang; unsigned int m_dmrTXHang;
unsigned int m_dmrModeHang;
bool m_fusionEnabled; bool m_fusionEnabled;
bool m_fusionLowDeviation; bool m_fusionLowDeviation;
bool m_fusionRemoteGateway; bool m_fusionRemoteGateway;
bool m_fusionSelfOnly;
bool m_fusionSQLEnabled;
unsigned char m_fusionSQL;
unsigned int m_fusionModeHang;
bool m_p25Enabled; bool m_p25Enabled;
unsigned int m_p25Id;
unsigned int m_p25NAC; unsigned int m_p25NAC;
bool m_p25SelfOnly;
bool m_p25OverrideUID;
bool m_p25RemoteGateway;
unsigned int m_p25ModeHang;
bool m_dstarNetworkEnabled; bool m_dstarNetworkEnabled;
std::string m_dstarGatewayAddress; std::string m_dstarGatewayAddress;
unsigned int m_dstarGatewayPort; unsigned int m_dstarGatewayPort;
unsigned int m_dstarLocalPort; unsigned int m_dstarLocalPort;
unsigned int m_dstarNetworkModeHang;
bool m_dstarNetworkDebug; bool m_dstarNetworkDebug;
bool m_dmrNetworkEnabled; bool m_dmrNetworkEnabled;
@ -284,20 +324,22 @@ private:
unsigned int m_dmrNetworkJitter; unsigned int m_dmrNetworkJitter;
bool m_dmrNetworkSlot1; bool m_dmrNetworkSlot1;
bool m_dmrNetworkSlot2; bool m_dmrNetworkSlot2;
unsigned int m_dmrNetworkModeHang;
bool m_fusionNetworkEnabled; bool m_fusionNetworkEnabled;
std::string m_fusionNetworkMyAddress; std::string m_fusionNetworkMyAddress;
unsigned int m_fusionNetworkMyPort; unsigned int m_fusionNetworkMyPort;
std::string m_fusionNetworkGwyAddress; std::string m_fusionNetworkGatewayAddress;
unsigned int m_fusionNetworkGwyPort; unsigned int m_fusionNetworkGatewayPort;
unsigned int m_fusionNetworkModeHang;
bool m_fusionNetworkDebug; bool m_fusionNetworkDebug;
bool m_p25NetworkEnabled; bool m_p25NetworkEnabled;
std::string m_p25GatewayAddress; std::string m_p25GatewayAddress;
unsigned int m_p25GatewayPort; unsigned int m_p25GatewayPort;
unsigned int m_p25LocalPort; unsigned int m_p25LocalPort;
unsigned int m_p25NetworkModeHang;
bool m_p25NetworkDebug; bool m_p25NetworkDebug;
bool m_p25OverrideUID;
std::string m_tftSerialPort; std::string m_tftSerialPort;
unsigned int m_tftSerialBrightness; unsigned int m_tftSerialBrightness;
@ -318,10 +360,12 @@ private:
bool m_nextionDisplayClock; bool m_nextionDisplayClock;
bool m_nextionUTC; bool m_nextionUTC;
unsigned int m_nextionIdleBrightness; unsigned int m_nextionIdleBrightness;
unsigned int m_nextionScreenLayout;
unsigned char m_oledType; unsigned char m_oledType;
unsigned char m_oledBrightness; unsigned char m_oledBrightness;
bool m_oledInvert; bool m_oledInvert;
bool m_oledScroll;
std::string m_lcdprocAddress; std::string m_lcdprocAddress;
unsigned int m_lcdprocPort; unsigned int m_lcdprocPort;

View file

@ -48,8 +48,14 @@ void CDMRAccessControl::init(const std::vector<unsigned int>& blacklist, const s
bool CDMRAccessControl::validateSrcId(unsigned int id) bool CDMRAccessControl::validateSrcId(unsigned int id)
{ {
if (m_selfOnly) if (m_selfOnly) {
if (m_id > 99999999U) // Check that the Config DMR-ID is bigger than 8 digits
return id == m_id / 100U; // Does RF ID match Config ID / 100
else if (m_id > 9999999U) // Check that the Config DMR-ID is bigger than 7 digits
return id == m_id / 10U; // Does RF ID match Config ID / 10
else
return id == m_id; return id == m_id;
}
if (std::find(m_blackList.begin(), m_blackList.end(), id) != m_blackList.end()) if (std::find(m_blackList.begin(), m_blackList.end(), id) != m_blackList.end())
return false; return false;

View file

@ -22,7 +22,6 @@
#include <algorithm> #include <algorithm>
CDMRControl::CDMRControl(unsigned int id, unsigned int colorCode, unsigned int callHang, bool selfOnly, bool embeddedLCOnly, bool dumpTAData, const std::vector<unsigned int>& prefixes, const std::vector<unsigned int>& blacklist, const std::vector<unsigned int>& whitelist, const std::vector<unsigned int>& slot1TGWhitelist, const std::vector<unsigned int>& slot2TGWhitelist, unsigned int timeout, CModem* modem, CDMRNetwork* network, CDisplay* display, bool duplex, CDMRLookup* lookup, CRSSIInterpolator* rssi, unsigned int jitter) : CDMRControl::CDMRControl(unsigned int id, unsigned int colorCode, unsigned int callHang, bool selfOnly, bool embeddedLCOnly, bool dumpTAData, const std::vector<unsigned int>& prefixes, const std::vector<unsigned int>& blacklist, const std::vector<unsigned int>& whitelist, const std::vector<unsigned int>& slot1TGWhitelist, const std::vector<unsigned int>& slot2TGWhitelist, unsigned int timeout, CModem* modem, CDMRNetwork* network, CDisplay* display, bool duplex, CDMRLookup* lookup, CRSSIInterpolator* rssi, unsigned int jitter) :
m_id(id),
m_colorCode(colorCode), m_colorCode(colorCode),
m_modem(modem), m_modem(modem),
m_network(network), m_network(network),
@ -64,25 +63,17 @@ bool CDMRControl::processWakeup(const unsigned char* data)
return false; return false;
unsigned int srcId = csbk.getSrcId(); unsigned int srcId = csbk.getSrcId();
unsigned int bsId = csbk.getBSId();
std::string src = m_lookup->find(srcId); std::string src = m_lookup->find(srcId);
bool ret = CDMRAccessControl::validateSrcId(srcId); bool ret = CDMRAccessControl::validateSrcId(srcId);
if (!ret) { if (!ret) {
LogMessage("Invalid CSBK BS_Dwn_Act received from %s", src.c_str()); LogMessage("Invalid Downlink Activate received from %s", src.c_str());
return false; return false;
} }
if (bsId == 0xFFFFFFU) { LogMessage("Downlink Activate received from %s", src.c_str());
LogMessage("CSBK BS_Dwn_Act for ANY received from %s", src.c_str());
return true;
} else if (bsId == m_id) {
LogMessage("CSBK BS_Dwn_Act for %u received from %s", bsId, src.c_str());
return true;
}
return false; return true;
} }
bool CDMRControl::writeModemSlot1(unsigned char *data, unsigned int len) bool CDMRControl::writeModemSlot1(unsigned char *data, unsigned int len)

View file

@ -45,7 +45,6 @@ public:
void clock(); void clock();
private: private:
unsigned int m_id;
unsigned int m_colorCode; unsigned int m_colorCode;
CModem* m_modem; CModem* m_modem;
CDMRNetwork* m_network; CDMRNetwork* m_network;

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2015,2016 Jonathan Naylor, G4KLX * Copyright (C) 2015,2016,2017 Jonathan Naylor, G4KLX
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -29,6 +29,7 @@ m_dstId(data.m_dstId),
m_flco(data.m_flco), m_flco(data.m_flco),
m_dataType(data.m_dataType), m_dataType(data.m_dataType),
m_seqNo(data.m_seqNo), m_seqNo(data.m_seqNo),
m_missing(data.m_missing),
m_n(data.m_n), m_n(data.m_n),
m_ber(data.m_ber), m_ber(data.m_ber),
m_rssi(data.m_rssi) m_rssi(data.m_rssi)
@ -45,6 +46,7 @@ m_dstId(0U),
m_flco(FLCO_GROUP), m_flco(FLCO_GROUP),
m_dataType(0U), m_dataType(0U),
m_seqNo(0U), m_seqNo(0U),
m_missing(false),
m_n(0U), m_n(0U),
m_ber(0U), m_ber(0U),
m_rssi(0U) m_rssi(0U)
@ -68,6 +70,7 @@ CDMRData& CDMRData::operator=(const CDMRData& data)
m_flco = data.m_flco; m_flco = data.m_flco;
m_dataType = data.m_dataType; m_dataType = data.m_dataType;
m_seqNo = data.m_seqNo; m_seqNo = data.m_seqNo;
m_missing = data.m_missing;
m_n = data.m_n; m_n = data.m_n;
m_ber = data.m_ber; m_ber = data.m_ber;
m_rssi = data.m_rssi; m_rssi = data.m_rssi;
@ -138,6 +141,16 @@ void CDMRData::setSeqNo(unsigned char seqNo)
m_seqNo = seqNo; m_seqNo = seqNo;
} }
bool CDMRData::isMissing() const
{
return m_missing;
}
void CDMRData::setMissing(bool missing)
{
m_missing = missing;
}
unsigned char CDMRData::getN() const unsigned char CDMRData::getN() const
{ {
return m_n; return m_n;

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2015,2016 by Jonathan Naylor, G4KLX * Copyright (C) 2015,2016,2017 by Jonathan Naylor, G4KLX
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -45,11 +45,14 @@ public:
unsigned char getDataType() const; unsigned char getDataType() const;
void setDataType(unsigned char dataType); void setDataType(unsigned char dataType);
bool isMissing() const;
void setMissing(bool missing);
unsigned char getBER() const; unsigned char getBER() const;
void setBER(unsigned char ber); void setBER(unsigned char ber);
unsigned char getRSSI() const; unsigned char getRSSI() const;
void setRSSI(unsigned char ber); void setRSSI(unsigned char rssi);
void setData(const unsigned char* buffer); void setData(const unsigned char* buffer);
unsigned int getData(unsigned char* buffer) const; unsigned int getData(unsigned char* buffer) const;
@ -62,6 +65,7 @@ private:
FLCO m_flco; FLCO m_flco;
unsigned char m_dataType; unsigned char m_dataType;
unsigned char m_seqNo; unsigned char m_seqNo;
bool m_missing;
unsigned char m_n; unsigned char m_n;
unsigned char m_ber; unsigned char m_ber;
unsigned char m_rssi; unsigned char m_rssi;

18007
DMRIds.dat

File diff suppressed because it is too large Load diff

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2016 by Jonathan Naylor G4KLX * Copyright (C) 2016,2017 by Jonathan Naylor G4KLX
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -103,6 +103,17 @@ std::string CDMRLookup::find(unsigned int id)
return callsign; return callsign;
} }
bool CDMRLookup::exists(unsigned int id)
{
m_mutex.lock();
bool found = m_table.count(id) == 1U;
m_mutex.unlock();
return found;
}
bool CDMRLookup::load() bool CDMRLookup::load()
{ {
FILE* fp = ::fopen(m_filename.c_str(), "rt"); FILE* fp = ::fopen(m_filename.c_str(), "rt");

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2016 by Jonathan Naylor G4KLX * Copyright (C) 2016,2017 by Jonathan Naylor G4KLX
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -36,6 +36,8 @@ public:
std::string find(unsigned int id); std::string find(unsigned int id);
bool exists(unsigned int id);
void stop(); void stop();
private: private:

View file

@ -383,7 +383,7 @@ void CDMRNetwork::clock(unsigned int ms)
} }
} else if (::memcmp(m_buffer, "MSTNAK", 6U) == 0) { } else if (::memcmp(m_buffer, "MSTNAK", 6U) == 0) {
if (m_status == RUNNING) { if (m_status == RUNNING) {
LogWarning("DMR, The master is restarting, logging back in"); LogWarning("DMR, Login to the master has failed, retrying login ...");
m_status = WAITING_LOGIN; m_status = WAITING_LOGIN;
m_timeoutTimer.start(); m_timeoutTimer.start();
m_retryTimer.start(); m_retryTimer.start();
@ -391,7 +391,7 @@ void CDMRNetwork::clock(unsigned int ms)
/* Once the modem death spiral has been prevented in Modem.cpp /* Once the modem death spiral has been prevented in Modem.cpp
the Network sometimes times out and reaches here. the Network sometimes times out and reaches here.
We want it to reconnect so... */ We want it to reconnect so... */
LogError("DMR, Login to the master has failed, retrying ..."); LogError("DMR, Login to the master has failed, retrying network ...");
close(); close();
open(); open();
return; return;
@ -543,6 +543,9 @@ bool CDMRNetwork::writeConfig()
case HWT_DVMEGA: case HWT_DVMEGA:
software = "MMDVM_DVMega"; software = "MMDVM_DVMega";
break; break;
case HWT_MMDVM_HS:
software = "MMDVM_HS";
break;
default: default:
software = "MMDVM_Unknown"; software = "MMDVM_Unknown";
break; break;

View file

@ -29,6 +29,7 @@
#include <cassert> #include <cassert>
#include <ctime> #include <ctime>
#include <algorithm> #include <algorithm>
#include <cstdint>
unsigned int CDMRSlot::m_colorCode = 0U; unsigned int CDMRSlot::m_colorCode = 0U;
@ -51,10 +52,10 @@ unsigned char* CDMRSlot::m_idle = NULL;
FLCO CDMRSlot::m_flco1; FLCO CDMRSlot::m_flco1;
unsigned char CDMRSlot::m_id1 = 0U; unsigned char CDMRSlot::m_id1 = 0U;
bool CDMRSlot::m_voice1 = true; ACTIVITY_TYPE CDMRSlot::m_activity1 = ACTIVITY_NONE;
FLCO CDMRSlot::m_flco2; FLCO CDMRSlot::m_flco2;
unsigned char CDMRSlot::m_id2 = 0U; unsigned char CDMRSlot::m_id2 = 0U;
bool CDMRSlot::m_voice2 = true; ACTIVITY_TYPE CDMRSlot::m_activity2 = ACTIVITY_NONE;
const unsigned char TALKER_ID_NONE = 0x00U; const unsigned char TALKER_ID_NONE = 0x00U;
const unsigned char TALKER_ID_HEADER = 0x01U; const unsigned char TALKER_ID_HEADER = 0x01U;
@ -77,6 +78,7 @@ m_rfEmbeddedData(NULL),
m_rfEmbeddedReadN(0U), m_rfEmbeddedReadN(0U),
m_rfEmbeddedWriteN(1U), m_rfEmbeddedWriteN(1U),
m_rfTalkerId(TALKER_ID_NONE), m_rfTalkerId(TALKER_ID_NONE),
m_rfTalkerAlias(NULL),
m_netEmbeddedLC(), m_netEmbeddedLC(),
m_netEmbeddedData(NULL), m_netEmbeddedData(NULL),
m_netEmbeddedReadN(0U), m_netEmbeddedReadN(0U),
@ -113,6 +115,7 @@ m_aveRSSI(0U),
m_rssiCount(0U), m_rssiCount(0U),
m_fp(NULL) m_fp(NULL)
{ {
m_rfTalkerAlias = new unsigned char[32U];
m_lastFrame = new unsigned char[DMR_FRAME_LENGTH_BYTES + 2U]; m_lastFrame = new unsigned char[DMR_FRAME_LENGTH_BYTES + 2U];
m_rfEmbeddedData = new CDMREmbeddedData[2U]; m_rfEmbeddedData = new CDMREmbeddedData[2U];
@ -126,6 +129,7 @@ CDMRSlot::~CDMRSlot()
delete[] m_rfEmbeddedData; delete[] m_rfEmbeddedData;
delete[] m_netEmbeddedData; delete[] m_netEmbeddedData;
delete[] m_lastFrame; delete[] m_lastFrame;
delete[] m_rfTalkerAlias;
} }
bool CDMRSlot::writeModem(unsigned char *data, unsigned int len) bool CDMRSlot::writeModem(unsigned char *data, unsigned int len)
@ -267,7 +271,7 @@ bool CDMRSlot::writeModem(unsigned char *data, unsigned int len)
std::string dst = m_lookup->find(dstId); std::string dst = m_lookup->find(dstId);
if (m_netState == RS_NET_IDLE) { if (m_netState == RS_NET_IDLE) {
setShortLC(m_slotNo, dstId, flco, true); setShortLC(m_slotNo, dstId, flco, ACTIVITY_VOICE);
m_display->writeDMR(m_slotNo, src, flco == FLCO_GROUP, dst, "R"); m_display->writeDMR(m_slotNo, src, flco == FLCO_GROUP, dst, "R");
m_display->writeDMRRSSI(m_slotNo, m_rssi); m_display->writeDMRRSSI(m_slotNo, m_rssi);
} }
@ -332,6 +336,8 @@ bool CDMRSlot::writeModem(unsigned char *data, unsigned int len)
else 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)); 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) { if (m_rfTimeout) {
writeEndRF(); writeEndRF();
return false; return false;
@ -391,7 +397,7 @@ bool CDMRSlot::writeModem(unsigned char *data, unsigned int len)
std::string dst = m_lookup->find(dstId); std::string dst = m_lookup->find(dstId);
if (m_netState == RS_NET_IDLE) { if (m_netState == RS_NET_IDLE) {
setShortLC(m_slotNo, dstId, gi ? FLCO_GROUP : FLCO_USER_USER, false); setShortLC(m_slotNo, dstId, gi ? FLCO_GROUP : FLCO_USER_USER, ACTIVITY_DATA);
m_display->writeDMR(m_slotNo, src, gi, dst, "R"); m_display->writeDMR(m_slotNo, src, gi, dst, "R");
m_display->writeDMRRSSI(m_slotNo, m_rssi); m_display->writeDMRRSSI(m_slotNo, m_rssi);
} }
@ -470,6 +476,13 @@ bool CDMRSlot::writeModem(unsigned char *data, unsigned int len)
break; break;
} }
// If data preamble, signal its existence
if (m_netState == RS_NET_IDLE && csbko == CSBKO_PRECCSBK && csbk.getDataContent()) {
setShortLC(m_slotNo, dstId, gi ? FLCO_GROUP : FLCO_USER_USER, ACTIVITY_DATA);
m_display->writeDMR(m_slotNo, src, gi, dst, "R");
m_display->writeDMRRSSI(m_slotNo, m_rssi);
}
return true; return true;
} else if (dataType == DT_RATE_12_DATA || dataType == DT_RATE_34_DATA || dataType == DT_RATE_1_DATA) { } else if (dataType == DT_RATE_12_DATA || dataType == DT_RATE_34_DATA || dataType == DT_RATE_1_DATA) {
if (m_rfState != RS_RF_DATA || m_rfFrames == 0U) if (m_rfState != RS_RF_DATA || m_rfFrames == 0U)
@ -599,6 +612,7 @@ bool CDMRSlot::writeModem(unsigned char *data, unsigned int len)
if (m_dumpTAData) { if (m_dumpTAData) {
::sprintf(text, "DMR Slot %u, Embedded GPS Info", m_slotNo); ::sprintf(text, "DMR Slot %u, Embedded GPS Info", m_slotNo);
CUtils::dump(2U, text, data, 9U); CUtils::dump(2U, text, data, 9U);
logGPSPosition(data);
} }
if (m_network != NULL) if (m_network != NULL)
m_network->writePosition(m_rfLC->getSrcId(), data); m_network->writePosition(m_rfLC->getSrcId(), data);
@ -609,6 +623,11 @@ bool CDMRSlot::writeModem(unsigned char *data, unsigned int len)
m_network->writeTalkerAlias(m_rfLC->getSrcId(), 0U, data); m_network->writeTalkerAlias(m_rfLC->getSrcId(), 0U, data);
if (!(m_rfTalkerId & TALKER_ID_HEADER)) { 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) { if (m_dumpTAData) {
::sprintf(text, "DMR Slot %u, Embedded Talker Alias Header", m_slotNo); ::sprintf(text, "DMR Slot %u, Embedded Talker Alias Header", m_slotNo);
CUtils::dump(2U, text, data, 9U); CUtils::dump(2U, text, data, 9U);
@ -623,6 +642,11 @@ bool CDMRSlot::writeModem(unsigned char *data, unsigned int len)
m_network->writeTalkerAlias(m_rfLC->getSrcId(), 1U, data); m_network->writeTalkerAlias(m_rfLC->getSrcId(), 1U, data);
if (!(m_rfTalkerId & TALKER_ID_BLOCK1)) { 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) { if (m_dumpTAData) {
::sprintf(text, "DMR Slot %u, Embedded Talker Alias Block 1", m_slotNo); ::sprintf(text, "DMR Slot %u, Embedded Talker Alias Block 1", m_slotNo);
CUtils::dump(2U, text, data, 9U); CUtils::dump(2U, text, data, 9U);
@ -637,6 +661,11 @@ bool CDMRSlot::writeModem(unsigned char *data, unsigned int len)
m_network->writeTalkerAlias(m_rfLC->getSrcId(), 2U, data); m_network->writeTalkerAlias(m_rfLC->getSrcId(), 2U, data);
if (!(m_rfTalkerId & TALKER_ID_BLOCK2)) { if (!(m_rfTalkerId & TALKER_ID_BLOCK2)) {
if (m_rfTalkerId == TALKER_ID_NONE)
::memset(m_rfTalkerAlias, 0, 32U);
::memcpy(m_rfTalkerAlias + 6U + 7U, data, 7U);
m_display->writeDMRTA(m_slotNo, m_rfTalkerAlias, "R");
if (m_dumpTAData) { if (m_dumpTAData) {
::sprintf(text, "DMR Slot %u, Embedded Talker Alias Block 2", m_slotNo); ::sprintf(text, "DMR Slot %u, Embedded Talker Alias Block 2", m_slotNo);
CUtils::dump(2U, text, data, 9U); CUtils::dump(2U, text, data, 9U);
@ -651,6 +680,11 @@ bool CDMRSlot::writeModem(unsigned char *data, unsigned int len)
m_network->writeTalkerAlias(m_rfLC->getSrcId(), 3U, data); m_network->writeTalkerAlias(m_rfLC->getSrcId(), 3U, data);
if (!(m_rfTalkerId & TALKER_ID_BLOCK3)) { 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) { if (m_dumpTAData) {
::sprintf(text, "DMR Slot %u, Embedded Talker Alias Block 3", m_slotNo); ::sprintf(text, "DMR Slot %u, Embedded Talker Alias Block 3", m_slotNo);
CUtils::dump(2U, text, data, 9U); CUtils::dump(2U, text, data, 9U);
@ -810,7 +844,7 @@ bool CDMRSlot::writeModem(unsigned char *data, unsigned int len)
std::string dst = m_lookup->find(dstId); std::string dst = m_lookup->find(dstId);
if (m_netState == RS_NET_IDLE) { if (m_netState == RS_NET_IDLE) {
setShortLC(m_slotNo, dstId, flco, true); setShortLC(m_slotNo, dstId, flco, ACTIVITY_VOICE);
m_display->writeDMR(m_slotNo, src, flco == FLCO_GROUP, dst, "R"); m_display->writeDMR(m_slotNo, src, flco == FLCO_GROUP, dst, "R");
m_display->writeDMRRSSI(m_slotNo, m_rssi); m_display->writeDMRRSSI(m_slotNo, m_rssi);
m_display->writeDMRBER(m_slotNo, float(errors) / 1.41F); m_display->writeDMRBER(m_slotNo, float(errors) / 1.41F);
@ -1025,7 +1059,7 @@ void CDMRSlot::writeNetwork(const CDMRData& dmrData)
m_netState = RS_NET_AUDIO; m_netState = RS_NET_AUDIO;
setShortLC(m_slotNo, dstId, flco, true); setShortLC(m_slotNo, dstId, flco, ACTIVITY_VOICE);
std::string src = m_lookup->find(srcId); std::string src = m_lookup->find(srcId);
std::string dst = m_lookup->find(dstId); std::string dst = m_lookup->find(dstId);
@ -1093,7 +1127,7 @@ void CDMRSlot::writeNetwork(const CDMRData& dmrData)
m_netState = RS_NET_AUDIO; m_netState = RS_NET_AUDIO;
setShortLC(m_slotNo, dstId, m_netLC->getFLCO(), true); setShortLC(m_slotNo, dstId, m_netLC->getFLCO(), ACTIVITY_VOICE);
std::string src = m_lookup->find(srcId); std::string src = m_lookup->find(srcId);
std::string dst = m_lookup->find(dstId); std::string dst = m_lookup->find(dstId);
@ -1163,7 +1197,7 @@ void CDMRSlot::writeNetwork(const CDMRData& dmrData)
// We've received the voice header and terminator haven't we? // We've received the voice header and terminator haven't we?
m_netFrames += 2U; 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)); 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(); writeEndNet();
} else if (dataType == DT_DATA_HEADER) { } else if (dataType == DT_DATA_HEADER) {
if (m_netState == RS_NET_DATA) if (m_netState == RS_NET_DATA)
@ -1205,7 +1239,7 @@ void CDMRSlot::writeNetwork(const CDMRData& dmrData)
m_netState = RS_NET_DATA; m_netState = RS_NET_DATA;
setShortLC(m_slotNo, dstId, gi ? FLCO_GROUP : FLCO_USER_USER, false); setShortLC(m_slotNo, dstId, gi ? FLCO_GROUP : FLCO_USER_USER, ACTIVITY_DATA);
std::string src = m_lookup->find(srcId); std::string src = m_lookup->find(srcId);
std::string dst = m_lookup->find(dstId); std::string dst = m_lookup->find(dstId);
@ -1283,7 +1317,7 @@ void CDMRSlot::writeNetwork(const CDMRData& dmrData)
m_netState = RS_NET_AUDIO; m_netState = RS_NET_AUDIO;
setShortLC(m_slotNo, dstId, m_netLC->getFLCO(), true); setShortLC(m_slotNo, dstId, m_netLC->getFLCO(), ACTIVITY_VOICE);
std::string src = m_lookup->find(srcId); std::string src = m_lookup->find(srcId);
std::string dst = m_lookup->find(dstId); std::string dst = m_lookup->find(dstId);
@ -1370,10 +1404,16 @@ void CDMRSlot::writeNetwork(const CDMRData& dmrData)
if (m_dumpTAData) { if (m_dumpTAData) {
::sprintf(text, "DMR Slot %u, Embedded GPS Info", m_slotNo); ::sprintf(text, "DMR Slot %u, Embedded GPS Info", m_slotNo);
CUtils::dump(2U, text, data, 9U); CUtils::dump(2U, text, data, 9U);
logGPSPosition(data);
} }
break; break;
case FLCO_TALKER_ALIAS_HEADER: case FLCO_TALKER_ALIAS_HEADER:
if (!(m_netTalkerId & TALKER_ID_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) { if (m_dumpTAData) {
::sprintf(text, "DMR Slot %u, Embedded Talker Alias Header", m_slotNo); ::sprintf(text, "DMR Slot %u, Embedded Talker Alias Header", m_slotNo);
CUtils::dump(2U, text, data, 9U); CUtils::dump(2U, text, data, 9U);
@ -1384,6 +1424,11 @@ void CDMRSlot::writeNetwork(const CDMRData& dmrData)
break; break;
case FLCO_TALKER_ALIAS_BLOCK1: case FLCO_TALKER_ALIAS_BLOCK1:
if (!(m_netTalkerId & TALKER_ID_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) { if (m_dumpTAData) {
::sprintf(text, "DMR Slot %u, Embedded Talker Alias Block 1", m_slotNo); ::sprintf(text, "DMR Slot %u, Embedded Talker Alias Block 1", m_slotNo);
CUtils::dump(2U, text, data, 9U); CUtils::dump(2U, text, data, 9U);
@ -1394,6 +1439,11 @@ void CDMRSlot::writeNetwork(const CDMRData& dmrData)
break; break;
case FLCO_TALKER_ALIAS_BLOCK2: case FLCO_TALKER_ALIAS_BLOCK2:
if (!(m_netTalkerId & TALKER_ID_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) { if (m_dumpTAData) {
::sprintf(text, "DMR Slot %u, Embedded Talker Alias Block 2", m_slotNo); ::sprintf(text, "DMR Slot %u, Embedded Talker Alias Block 2", m_slotNo);
CUtils::dump(2U, text, data, 9U); CUtils::dump(2U, text, data, 9U);
@ -1404,6 +1454,11 @@ void CDMRSlot::writeNetwork(const CDMRData& dmrData)
break; break;
case FLCO_TALKER_ALIAS_BLOCK3: case FLCO_TALKER_ALIAS_BLOCK3:
if (!(m_netTalkerId & TALKER_ID_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) { if (m_dumpTAData) {
::sprintf(text, "DMR Slot %u, Embedded Talker Alias Block 3", m_slotNo); ::sprintf(text, "DMR Slot %u, Embedded Talker Alias Block 3", m_slotNo);
CUtils::dump(2U, text, data, 9U); CUtils::dump(2U, text, data, 9U);
@ -1523,6 +1578,12 @@ void CDMRSlot::writeNetwork(const CDMRData& dmrData)
LogWarning("DMR Slot %u, unhandled network CSBK type - 0x%02X", m_slotNo, csbko); LogWarning("DMR Slot %u, unhandled network CSBK type - 0x%02X", m_slotNo, csbko);
break; break;
} }
// If data preamble, signal its existence
if (csbko == CSBKO_PRECCSBK && csbk.getDataContent()) {
setShortLC(m_slotNo, dstId, gi ? FLCO_GROUP : FLCO_USER_USER, ACTIVITY_DATA);
m_display->writeDMR(m_slotNo, src, gi, dst, "N");
}
} else if (dataType == DT_RATE_12_DATA || dataType == DT_RATE_34_DATA || dataType == DT_RATE_1_DATA) { } else if (dataType == DT_RATE_12_DATA || dataType == DT_RATE_34_DATA || dataType == DT_RATE_1_DATA) {
if (m_netState != RS_NET_DATA || m_netFrames == 0U) if (m_netState != RS_NET_DATA || m_netFrames == 0U)
return; return;
@ -1574,6 +1635,54 @@ void CDMRSlot::writeNetwork(const CDMRData& dmrData)
} }
} }
void CDMRSlot::logGPSPosition(const unsigned char* data)
{
unsigned int errorI = (data[2U] & 0x0E) >> 1U;
const char* error;
switch (errorI) {
case 0U:
error = "< 2m";
break;
case 1U:
error = "< 20m";
break;
case 2U:
error = "< 200m";
break;
case 3U:
error = "< 2km";
break;
case 4U:
error = "< 20km";
break;
case 5U:
error = "< 200km";
break;
case 6U:
error = "> 200km";
break;
default:
error = "not known";
break;
}
int32_t longitudeI = ((data[2U] & 0x01U) << 31) | (data[3U] << 23) | (data[4U] << 15) | (data[5U] << 7);
longitudeI >>= 7;
int32_t latitudeI = (data[6U] << 24) | (data[7U] << 16) | (data[8U] << 8);
latitudeI >>= 8;
float longitude = 360.0F / 33554432.0F; // 360/2^25 steps
float latitude = 180.0F / 16777216.0F; // 180/2^24 steps
longitude *= float(longitudeI);
latitude *= float(latitudeI);
LogMessage("GPS position [%f,%f] (Position error %s)", latitude, longitude, error);
}
void CDMRSlot::clock() void CDMRSlot::clock()
{ {
unsigned int ms = m_interval.elapsed(); unsigned int ms = m_interval.elapsed();
@ -1737,7 +1846,7 @@ void CDMRSlot::init(unsigned int colorCode, bool embeddedLCOnly, bool dumpTAData
} }
void CDMRSlot::setShortLC(unsigned int slotNo, unsigned int id, FLCO flco, bool voice) void CDMRSlot::setShortLC(unsigned int slotNo, unsigned int id, FLCO flco, ACTIVITY_TYPE type)
{ {
assert(m_modem != NULL); assert(m_modem != NULL);
@ -1745,7 +1854,7 @@ void CDMRSlot::setShortLC(unsigned int slotNo, unsigned int id, FLCO flco, bool
case 1U: case 1U:
m_id1 = 0U; m_id1 = 0U;
m_flco1 = flco; m_flco1 = flco;
m_voice1 = voice; m_activity1 = type;
if (id != 0U) { if (id != 0U) {
unsigned char buffer[3U]; unsigned char buffer[3U];
buffer[0U] = (id << 16) & 0xFFU; buffer[0U] = (id << 16) & 0xFFU;
@ -1757,7 +1866,7 @@ void CDMRSlot::setShortLC(unsigned int slotNo, unsigned int id, FLCO flco, bool
case 2U: case 2U:
m_id2 = 0U; m_id2 = 0U;
m_flco2 = flco; m_flco2 = flco;
m_voice2 = voice; m_activity2 = type;
if (id != 0U) { if (id != 0U) {
unsigned char buffer[3U]; unsigned char buffer[3U];
buffer[0U] = (id << 16) & 0xFFU; buffer[0U] = (id << 16) & 0xFFU;
@ -1783,32 +1892,42 @@ void CDMRSlot::setShortLC(unsigned int slotNo, unsigned int id, FLCO flco, bool
if (m_id1 != 0U) { if (m_id1 != 0U) {
lc[2U] = m_id1; lc[2U] = m_id1;
if (m_voice1) { if (m_activity1 == ACTIVITY_VOICE && m_flco1 == FLCO_GROUP)
if (m_flco1 == FLCO_GROUP) lc[1U] |= 0x08U;
lc[1U] |= 0x80U; else if (m_activity1 == ACTIVITY_VOICE && m_flco1 == FLCO_USER_USER)
else lc[1U] |= 0x09U;
lc[1U] |= 0x90U; else if (m_activity1 == ACTIVITY_DATA && m_flco1 == FLCO_GROUP)
} else { lc[1U] |= 0x0BU;
if (m_flco1 == FLCO_GROUP) else if (m_activity1 == ACTIVITY_DATA && m_flco1 == FLCO_USER_USER)
lc[1U] |= 0xB0U; lc[1U] |= 0x0AU;
else else if (m_activity1 == ACTIVITY_CSBK && m_flco1 == FLCO_GROUP)
lc[1U] |= 0xA0U; lc[1U] |= 0x02U;
} else if (m_activity1 == ACTIVITY_CSBK && m_flco1 == FLCO_USER_USER)
lc[1U] |= 0x03U;
else if (m_activity1 == ACTIVITY_EMERG && m_flco1 == FLCO_GROUP)
lc[1U] |= 0x0CU;
else if (m_activity1 == ACTIVITY_EMERG && m_flco1 == FLCO_USER_USER)
lc[1U] |= 0x0DU;
} }
if (m_id2 != 0U) { if (m_id2 != 0U) {
lc[3U] = m_id2; lc[3U] = m_id2;
if (m_voice2) { if (m_activity2 == ACTIVITY_VOICE && m_flco2 == FLCO_GROUP)
if (m_flco2 == FLCO_GROUP) lc[1U] |= 0x80U;
lc[1U] |= 0x08U; else if (m_activity2 == ACTIVITY_VOICE && m_flco2 == FLCO_USER_USER)
else lc[1U] |= 0x90U;
lc[1U] |= 0x09U; else if (m_activity2 == ACTIVITY_DATA && m_flco2 == FLCO_GROUP)
} else { lc[1U] |= 0xB0U;
if (m_flco2 == FLCO_GROUP) else if (m_activity2 == ACTIVITY_DATA && m_flco2 == FLCO_USER_USER)
lc[1U] |= 0x0BU; lc[1U] |= 0xA0U;
else else if (m_activity2 == ACTIVITY_CSBK && m_flco2 == FLCO_GROUP)
lc[1U] |= 0x0AU; lc[1U] |= 0x20U;
} else if (m_activity2 == ACTIVITY_CSBK && m_flco2 == FLCO_USER_USER)
lc[1U] |= 0x30U;
else if (m_activity2 == ACTIVITY_EMERG && m_flco2 == FLCO_GROUP)
lc[1U] |= 0xC0U;
else if (m_activity2 == ACTIVITY_EMERG && m_flco2 == FLCO_USER_USER)
lc[1U] |= 0xD0U;
} }
lc[4U] = CCRC::crc8(lc, 4U); lc[4U] = CCRC::crc8(lc, 4U);

View file

@ -36,6 +36,14 @@
#include <vector> #include <vector>
enum ACTIVITY_TYPE {
ACTIVITY_NONE,
ACTIVITY_VOICE,
ACTIVITY_DATA,
ACTIVITY_CSBK,
ACTIVITY_EMERG
};
class CDMRSlot { class CDMRSlot {
public: public:
CDMRSlot(unsigned int slotNo, unsigned int timeout); CDMRSlot(unsigned int slotNo, unsigned int timeout);
@ -61,6 +69,7 @@ private:
unsigned int m_rfEmbeddedReadN; unsigned int m_rfEmbeddedReadN;
unsigned int m_rfEmbeddedWriteN; unsigned int m_rfEmbeddedWriteN;
unsigned char m_rfTalkerId; unsigned char m_rfTalkerId;
unsigned char* m_rfTalkerAlias;
CDMREmbeddedData m_netEmbeddedLC; CDMREmbeddedData m_netEmbeddedLC;
CDMREmbeddedData* m_netEmbeddedData; CDMREmbeddedData* m_netEmbeddedData;
unsigned int m_netEmbeddedReadN; unsigned int m_netEmbeddedReadN;
@ -118,10 +127,12 @@ private:
static FLCO m_flco1; static FLCO m_flco1;
static unsigned char m_id1; static unsigned char m_id1;
static bool m_voice1; static ACTIVITY_TYPE m_activity1;
static FLCO m_flco2; static FLCO m_flco2;
static unsigned char m_id2; static unsigned char m_id2;
static bool m_voice2; static ACTIVITY_TYPE m_activity2;
void logGPSPosition(const unsigned char* data);
void writeQueueRF(const unsigned char* data); void writeQueueRF(const unsigned char* data);
void writeQueueNet(const unsigned char* data); void writeQueueNet(const unsigned char* data);
@ -138,7 +149,7 @@ private:
bool insertSilence(const unsigned char* data, unsigned char seqNo); bool insertSilence(const unsigned char* data, unsigned char seqNo);
void insertSilence(unsigned int count); void insertSilence(unsigned int count);
static void setShortLC(unsigned int slotNo, unsigned int id, FLCO flco = FLCO_GROUP, bool voice = true); static void setShortLC(unsigned int slotNo, unsigned int id, FLCO flco = FLCO_GROUP, ACTIVITY_TYPE type = ACTIVITY_NONE);
}; };
#endif #endif

View file

@ -36,11 +36,13 @@ bool CallsignCompare(const std::string& arg, const unsigned char* my)
// #define DUMP_DSTAR // #define DUMP_DSTAR
CDStarControl::CDStarControl(const std::string& callsign, const std::string& module, bool selfOnly, bool errorReply, const std::vector<std::string>& blackList, CDStarNetwork* network, CDisplay* display, unsigned int timeout, bool duplex, CRSSIInterpolator* rssiMapper) : CDStarControl::CDStarControl(const std::string& callsign, const std::string& module, bool selfOnly, bool ackReply, unsigned int ackTime, bool errorReply, const std::vector<std::string>& blackList, CDStarNetwork* network, CDisplay* display, unsigned int timeout, bool duplex, bool remoteGateway, CRSSIInterpolator* rssiMapper) :
m_callsign(NULL), m_callsign(NULL),
m_gateway(NULL), m_gateway(NULL),
m_selfOnly(selfOnly), m_selfOnly(selfOnly),
m_ackReply(ackReply),
m_errorReply(errorReply), m_errorReply(errorReply),
m_remoteGateway(remoteGateway),
m_blackList(blackList), m_blackList(blackList),
m_network(network), m_network(network),
m_display(display), m_display(display),
@ -58,8 +60,8 @@ m_networkWatchdog(1000U, 0U, 1500U),
m_rfTimeoutTimer(1000U, timeout), m_rfTimeoutTimer(1000U, timeout),
m_netTimeoutTimer(1000U, timeout), m_netTimeoutTimer(1000U, timeout),
m_packetTimer(1000U, 0U, 300U), m_packetTimer(1000U, 0U, 300U),
m_ackTimer(1000U, 0U, 750U), m_ackTimer(1000U, 0U, ackTime),
m_errTimer(1000U, 0U, 750U), m_errTimer(1000U, 0U, ackTime),
m_interval(), m_interval(),
m_elapsed(), m_elapsed(),
m_rfFrames(0U), m_rfFrames(0U),
@ -523,6 +525,7 @@ void CDStarControl::writeEndRF()
if (m_netState == RS_NET_IDLE) { if (m_netState == RS_NET_IDLE) {
m_display->clearDStar(); m_display->clearDStar();
m_ackTimer.start(); m_ackTimer.start();
if (m_network != NULL) if (m_network != NULL)
@ -587,7 +590,6 @@ void CDStarControl::writeNetwork()
m_netTimeoutTimer.start(); m_netTimeoutTimer.start();
m_packetTimer.start(); m_packetTimer.start();
//m_elapsed.start(); // commented out and placed lower down due to delay introduced somewhere below here.
m_ackTimer.stop(); m_ackTimer.stop();
m_errTimer.stop(); m_errTimer.stop();
@ -601,6 +603,13 @@ void CDStarControl::writeNetwork()
m_netBits = 1U; m_netBits = 1U;
m_netErrs = 0U; m_netErrs = 0U;
if (m_remoteGateway) {
header.setRepeater(true);
header.setRPTCall1(m_callsign);
header.setRPTCall2(m_callsign);
header.get(data + 1U);
}
writeQueueHeaderNet(data); writeQueueHeaderNet(data);
#if defined(DUMP_DSTAR) #if defined(DUMP_DSTAR)
@ -1011,6 +1020,9 @@ void CDStarControl::sendAck()
{ {
m_rfTimeoutTimer.stop(); m_rfTimeoutTimer.stop();
if (!m_ackReply)
return;
unsigned char user[DSTAR_LONG_CALLSIGN_LENGTH]; unsigned char user[DSTAR_LONG_CALLSIGN_LENGTH];
m_rfHeader.getMyCall1(user); m_rfHeader.getMyCall1(user);

View file

@ -37,7 +37,7 @@
class CDStarControl { class CDStarControl {
public: public:
CDStarControl(const std::string& callsign, const std::string& module, bool selfOnly, bool errorReply, const std::vector<std::string>& blackList, CDStarNetwork* network, CDisplay* display, unsigned int timeout, bool duplex, CRSSIInterpolator* rssiMapper); CDStarControl(const std::string& callsign, const std::string& module, bool selfOnly, bool ackReply, unsigned int ackTime, bool errorReply, const std::vector<std::string>& blackList, CDStarNetwork* network, CDisplay* display, unsigned int timeout, bool duplex, bool remoteGateway, CRSSIInterpolator* rssiMapper);
~CDStarControl(); ~CDStarControl();
bool writeModem(unsigned char* data, unsigned int len); bool writeModem(unsigned char* data, unsigned int len);
@ -50,7 +50,9 @@ private:
unsigned char* m_callsign; unsigned char* m_callsign;
unsigned char* m_gateway; unsigned char* m_gateway;
bool m_selfOnly; bool m_selfOnly;
bool m_ackReply;
bool m_errorReply; bool m_errorReply;
bool m_remoteGateway;
std::vector<std::string> m_blackList; std::vector<std::string> m_blackList;
CDStarNetwork* m_network; CDStarNetwork* m_network;
CDisplay* m_display; CDisplay* m_display;

View file

@ -36,6 +36,7 @@ const unsigned char TAG_EOT = 0x03U;
enum HW_TYPE { enum HW_TYPE {
HWT_MMDVM, HWT_MMDVM,
HWT_DVMEGA, HWT_DVMEGA,
HWT_MMDVM_HS,
HWT_UNKNOWN HWT_UNKNOWN
}; };

View file

@ -18,14 +18,15 @@
#include "Display.h" #include "Display.h"
#include "Defines.h" #include "Defines.h"
#include "Log.h"
#include <cstdio> #include <cstdio>
#include <cassert> #include <cassert>
#include <cstring> #include <cstring>
CDisplay::CDisplay() : CDisplay::CDisplay() :
m_timer1(1000U, 3U), m_timer1(3000U, 3U),
m_timer2(1000U, 3U), m_timer2(3000U, 3U),
m_mode1(MODE_IDLE), m_mode1(MODE_IDLE),
m_mode2(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_timer2.start();
m_mode2 = MODE_IDLE; m_mode2 = MODE_IDLE;
} }
writeDMRInt(slotNo, src, group, dst, type); writeDMRInt(slotNo, src, group, dst, type);
} }
@ -127,11 +127,55 @@ void CDisplay::writeDMRRSSI(unsigned int slotNo, unsigned char rssi)
writeDMRRSSIInt(slotNo, 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) void CDisplay::writeDMRBER(unsigned int slotNo, float ber)
{ {
writeDMRBERInt(slotNo, ber); writeDMRBERInt(slotNo, ber);
} }
void CDisplay::clearDMR(unsigned int slotNo) void CDisplay::clearDMR(unsigned int slotNo)
{ {
if (slotNo == 1U) { 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) void CDisplay::writeDMRBERInt(unsigned int slotNo, float ber)
{ {
} }

View file

@ -43,6 +43,7 @@ public:
void writeDMR(unsigned int slotNo, const std::string& src, bool group, const std::string& dst, const char* type); 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 writeDMRRSSI(unsigned int slotNo, unsigned char rssi);
void writeDMRBER(unsigned int slotNo, float ber); void writeDMRBER(unsigned int slotNo, float ber);
void writeDMRTA(unsigned int slotNo, unsigned char* talkerAlias, const char* type);
void clearDMR(unsigned int slotNo); void clearDMR(unsigned int slotNo);
void writeFusion(const char* source, const char* dest, const char* type, const char* origin); 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 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 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 writeDMRBERInt(unsigned int slotNo, float ber);
virtual void clearDMRInt(unsigned int slotNo) = 0; virtual void clearDMRInt(unsigned int slotNo) = 0;

187
JitterBuffer.cpp Normal file
View file

@ -0,0 +1,187 @@
/*
* Copyright (C) 2017 by Jonathan Naylor G4KLX
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* 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 "JitterBuffer.h"
#include "Log.h"
#include <cstdio>
#include <cassert>
#include <cstring>
CJitterBuffer::CJitterBuffer(unsigned int blockSize, unsigned int blockTime, unsigned int jitterTime, unsigned int topSequenceNumber, bool debug) :
m_blockSize(blockSize),
m_blockTime(blockTime),
m_topSequenceNumber(topSequenceNumber),
m_debug(debug),
m_blockCount(0U),
m_timer(1000U, 0U, jitterTime),
m_stopWatch(),
m_running(false),
m_buffer(NULL),
m_headSequenceNumber(0U),
m_lastData(NULL),
m_lastDataLength(0U)
{
assert(blockSize > 0U);
assert(blockTime > 0U);
assert(jitterTime > 0U);
assert(topSequenceNumber > 0U);
m_blockCount = (jitterTime / blockTime) * 2U + 1U;
m_buffer = new JitterEntry[m_blockCount];
for (unsigned int i = 0U; i < m_blockCount; i++)
m_buffer[i].m_data = new unsigned char[m_blockSize];
m_lastData = new unsigned char[m_blockSize];
reset();
}
CJitterBuffer::~CJitterBuffer()
{
for (unsigned int i = 0U; i < m_blockCount; i++)
delete[] m_buffer[i].m_data;
delete[] m_buffer;
delete[] m_lastData;
}
bool CJitterBuffer::addData(const unsigned char* data, unsigned int length, unsigned int sequenceNumber)
{
assert(data != NULL);
assert(length > 0U);
assert(length <= m_blockSize);
unsigned int headSequenceNumber = m_headSequenceNumber % m_topSequenceNumber;
unsigned int tailSequenceNumber = (m_headSequenceNumber + m_blockCount) % m_topSequenceNumber;
// Is the data out of sequence?
if (headSequenceNumber < tailSequenceNumber) {
if (sequenceNumber < headSequenceNumber || sequenceNumber >= tailSequenceNumber) {
if (m_debug)
LogDebug("JitterBuffer: rejecting frame with seqNo=%u, raw=%u, head=%u, tail=%u", sequenceNumber, m_headSequenceNumber, headSequenceNumber, tailSequenceNumber);
return false;
}
} else {
if (sequenceNumber >= tailSequenceNumber && sequenceNumber < headSequenceNumber) {
if (m_debug)
LogDebug("JitterBuffer: rejecting frame with seqNo=%u, raw=%u, head=%u, tail=%u", sequenceNumber, m_headSequenceNumber, headSequenceNumber, tailSequenceNumber);
return false;
}
}
unsigned int number;
if (sequenceNumber >= headSequenceNumber)
number = sequenceNumber - headSequenceNumber;
else
number = (sequenceNumber + m_blockCount) - headSequenceNumber;;
unsigned int index = (m_headSequenceNumber + number) % m_blockCount;
// Do we already have the data?
if (m_buffer[index].m_length > 0U) {
if (m_debug)
LogDebug("JitterBuffer: rejecting duplicate frame with seqNo=%u, raw=%u, head=%u, tail=%u", sequenceNumber, m_headSequenceNumber, headSequenceNumber, tailSequenceNumber);
return false;
}
LogDebug("JitterBuffer: adding frame with seqNo=%u, raw=%u, head=%u, tail=%u", sequenceNumber, m_headSequenceNumber, headSequenceNumber, tailSequenceNumber);
::memcpy(m_buffer[index].m_data, data, length);
m_buffer[index].m_length = length;
if (!m_timer.isRunning()) {
LogDebug("JitterBuffer: starting the timer");
m_timer.start();
}
return true;
}
JB_STATUS CJitterBuffer::getData(unsigned char* data, unsigned int& length)
{
assert(data != NULL);
if (!m_running)
return JBS_NO_DATA;
unsigned int sequenceNumber = m_stopWatch.elapsed() / m_blockTime + 3U;
if (m_headSequenceNumber > sequenceNumber)
return JBS_NO_DATA;
unsigned int head = m_headSequenceNumber % m_blockCount;
m_headSequenceNumber++;
if (m_buffer[head].m_length > 0U) {
LogDebug("JitterBuffer: returning data, elapsed=%ums, raw=%u, head=%u", m_stopWatch.elapsed(), m_headSequenceNumber - 1U, head);
::memcpy(data, m_buffer[head].m_data, m_buffer[head].m_length);
length = m_buffer[head].m_length;
// Save this data in case no more data is available next time
::memcpy(m_lastData, m_buffer[head].m_data, m_buffer[head].m_length);
m_lastDataLength = m_buffer[head].m_length;
m_buffer[head].m_length = 0U;
return JBS_DATA;
}
if (m_debug)
LogDebug("JitterBuffer: no data available, elapsed=%ums, raw=%u, head=%u", m_stopWatch.elapsed(), m_headSequenceNumber - 1U, head);
// Return the last data frame if we have it
if (m_lastDataLength > 0U) {
LogDebug("JitterBuffer: returning the last received frame");
::memcpy(data, m_lastData, m_lastDataLength);
length = m_lastDataLength;
return JBS_MISSING;
}
return JBS_NO_DATA;
}
void CJitterBuffer::reset()
{
for (unsigned int i = 0U; i < m_blockCount; i++)
m_buffer[i].m_length = 0U;
m_headSequenceNumber = 0U;
m_lastDataLength = 0U;
m_timer.stop();
m_running = false;
}
void CJitterBuffer::clock(unsigned int ms)
{
m_timer.clock(ms);
if (m_timer.isRunning() && m_timer.hasExpired()) {
if (!m_running) {
m_stopWatch.start();
m_running = true;
}
}
}

67
JitterBuffer.h Normal file
View file

@ -0,0 +1,67 @@
/*
* Copyright (C) 2017 by Jonathan Naylor G4KLX
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* 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(JITTERBUFFER_H)
#define JITTERBUFFER_H
#include "StopWatch.h"
#include "Timer.h"
enum JB_STATUS {
JBS_NO_DATA,
JBS_DATA,
JBS_MISSING
};
class CJitterBuffer {
public:
CJitterBuffer(unsigned int blockSize, unsigned int blockTime, unsigned int jitterTime, unsigned int topSequenceNumber, bool debug);
~CJitterBuffer();
bool addData(const unsigned char* data, unsigned int length, unsigned int sequenceNumber);
JB_STATUS getData(unsigned char* data, unsigned int& length);
void reset();
void clock(unsigned int ms);
private:
unsigned int m_blockSize;
unsigned int m_blockTime;
unsigned int m_topSequenceNumber;
bool m_debug;
unsigned int m_blockCount;
CTimer m_timer;
CStopWatch m_stopWatch;
bool m_running;
struct JitterEntry
{
unsigned char* m_data;
unsigned int m_length;
};
JitterEntry* m_buffer;
unsigned int m_headSequenceNumber;
unsigned char* m_lastData;
unsigned int m_lastDataLength;
};
#endif

View file

@ -1,5 +1,6 @@
[General] [General]
Callsign=G9BF Callsign=G9BF
Id=123456
Timeout=180 Timeout=180
Duplex=1 Duplex=1
# ModeHang=10 # ModeHang=10
@ -42,9 +43,13 @@ TXInvert=1
RXInvert=0 RXInvert=0
PTTInvert=0 PTTInvert=0
TXDelay=100 TXDelay=100
RXOffset=0
TXOffset=0
DMRDelay=0 DMRDelay=0
RXLevel=50 RXLevel=50
TXLevel=50 TXLevel=50
RXDCOffset=0
TXDCOffset=0
# CWIdTXLevel=50 # CWIdTXLevel=50
# D-StarTXLevel=50 # D-StarTXLevel=50
# DMRTXLevel=50 # DMRTXLevel=50
@ -63,12 +68,15 @@ Port=/dev/ttyACM1
Enable=1 Enable=1
Module=C Module=C
SelfOnly=0 SelfOnly=0
AckReply=1
AckTime=750
ErrorReply=1 ErrorReply=1
RemoteGateway=0
# ModeHang=10
[DMR] [DMR]
Enable=1 Enable=1
Beacons=1 Beacons=1
Id=123456
ColorCode=1 ColorCode=1
SelfOnly=0 SelfOnly=0
EmbeddedLCOnly=0 EmbeddedLCOnly=0
@ -78,22 +86,30 @@ DumpTAData=1
# Slot2TGWhiteList= # Slot2TGWhiteList=
CallHang=3 CallHang=3
TXHang=4 TXHang=4
# ModeHang=10
[System Fusion] [System Fusion]
Enable=1 Enable=1
LowDeviation=0 LowDeviation=0
SelfOnly=0
#DSQ=1
RemoteGateway=0 RemoteGateway=0
# ModeHang=10
[P25] [P25]
Enable=1 Enable=1
NAC=293 NAC=293
SelfOnly=0
OverrideUIDCheck=0 OverrideUIDCheck=0
RemoteGateway=0
# ModeHang=10
[D-Star Network] [D-Star Network]
Enable=1 Enable=1
GatewayAddress=127.0.0.1 GatewayAddress=127.0.0.1
GatewayPort=20010 GatewayPort=20010
LocalPort=20011 LocalPort=20011
# ModeHang=3
Debug=0 Debug=0
[DMR Network] [DMR Network]
@ -101,19 +117,21 @@ Enable=1
Address=44.131.4.1 Address=44.131.4.1
Port=62031 Port=62031
Jitter=300 Jitter=300
# Local=3350 # Local=62032
Password=PASSWORD Password=PASSWORD
# Options= # Options=
Slot1=1 Slot1=1
Slot2=1 Slot2=1
# ModeHang=3
Debug=0 Debug=0
[System Fusion Network] [System Fusion Network]
Enable=1 Enable=1
LocalAddress=127.0.0.1 LocalAddress=127.0.0.1
LocalPort=3200 LocalPort=3200
GwyAddress=127.0.0.1 GatewayAddress=127.0.0.1
GwyPort=4200 GatewayPort=4200
# ModeHang=3
Debug=0 Debug=0
[P25 Network] [P25 Network]
@ -121,6 +139,7 @@ Enable=1
GatewayAddress=127.0.0.1 GatewayAddress=127.0.0.1
GatewayPort=42020 GatewayPort=42020
LocalPort=32010 LocalPort=32010
# ModeHang=3
Debug=0 Debug=0
[TFT Serial] [TFT Serial]
@ -154,12 +173,15 @@ Port=/dev/ttyAMA0
Brightness=50 Brightness=50
DisplayClock=1 DisplayClock=1
UTC=0 UTC=0
#Screen Layout: 0=G4KLX 2=ON7LDS
ScreenLayout=2
IdleBrightness=20 IdleBrightness=20
[OLED] [OLED]
Type=3 Type=3
Brightness=0 Brightness=0
Invert=0 Invert=0
Scroll=1
[LCDproc] [LCDproc]
Address=localhost Address=localhost

View file

@ -95,6 +95,7 @@ int main(int argc, char** argv)
} }
#if !defined(_WIN32) && !defined(_WIN64) #if !defined(_WIN32) && !defined(_WIN64)
::signal(SIGINT, sigHandler);
::signal(SIGTERM, sigHandler); ::signal(SIGTERM, sigHandler);
::signal(SIGHUP, sigHandler); ::signal(SIGHUP, sigHandler);
#endif #endif
@ -109,11 +110,14 @@ int main(int argc, char** argv)
delete host; delete host;
if (m_signal == 2)
::LogInfo("MMDVMHost-%s exited on receipt of SIGINT", VERSION);
if (m_signal == 15) if (m_signal == 15)
::LogInfo("Caught SIGTERM, exiting"); ::LogInfo("MMDVMHost-%s exited on receipt of SIGTERM", VERSION);
if (m_signal == 1) if (m_signal == 1)
::LogInfo("Caught SIGHUP, restarting"); ::LogInfo("MMDVMHost-%s is restarting on receipt of SIGHUP", VERSION);
} while (m_signal == 1); } while (m_signal == 1);
::LogFinalise(); ::LogFinalise();
@ -131,8 +135,14 @@ m_p25Network(NULL),
m_display(NULL), m_display(NULL),
m_ump(NULL), m_ump(NULL),
m_mode(MODE_IDLE), m_mode(MODE_IDLE),
m_rfModeHang(10U), m_dstarRFModeHang(10U),
m_netModeHang(3U), m_dmrRFModeHang(10U),
m_ysfRFModeHang(10U),
m_p25RFModeHang(10U),
m_dstarNetModeHang(3U),
m_dmrNetModeHang(3U),
m_ysfNetModeHang(3U),
m_p25NetModeHang(3U),
m_modeTimer(1000U), m_modeTimer(1000U),
m_dmrTXTimer(1000U), m_dmrTXTimer(1000U),
m_cwIdTimer(1000U), m_cwIdTimer(1000U),
@ -145,6 +155,7 @@ m_p25Enabled(false),
m_cwIdTime(0U), m_cwIdTime(0U),
m_lookup(NULL), m_lookup(NULL),
m_callsign(), m_callsign(),
m_id(0U),
m_cwCallsign() m_cwCallsign()
{ {
} }
@ -334,17 +345,25 @@ int CMMDVMHost::run()
std::string module = m_conf.getDStarModule(); std::string module = m_conf.getDStarModule();
bool selfOnly = m_conf.getDStarSelfOnly(); bool selfOnly = m_conf.getDStarSelfOnly();
std::vector<std::string> blackList = m_conf.getDStarBlackList(); std::vector<std::string> blackList = m_conf.getDStarBlackList();
bool ackReply = m_conf.getDStarAckReply();
unsigned int ackTime = m_conf.getDStarAckTime();
bool errorReply = m_conf.getDStarErrorReply(); bool errorReply = m_conf.getDStarErrorReply();
bool remoteGateway = m_conf.getDStarRemoteGateway();
m_dstarRFModeHang = m_conf.getDStarModeHang();
LogInfo("D-Star Parameters"); LogInfo("D-Star RF Parameters");
LogInfo(" Module: %s", module.c_str()); LogInfo(" Module: %s", module.c_str());
LogInfo(" Self Only: %s", selfOnly ? "yes" : "no"); LogInfo(" Self Only: %s", selfOnly ? "yes" : "no");
LogInfo(" Ack Reply: %s", ackReply ? "yes" : "no");
LogInfo(" Ack Time: %ums", ackTime);
LogInfo(" Error Reply: %s", errorReply ? "yes" : "no"); LogInfo(" Error Reply: %s", errorReply ? "yes" : "no");
LogInfo(" Remote Gateway: %s", remoteGateway ? "yes" : "no");
LogInfo(" Mode Hang: %us", m_dstarRFModeHang);
if (blackList.size() > 0U) if (blackList.size() > 0U)
LogInfo(" Black List: %u", blackList.size()); LogInfo(" Black List: %u", blackList.size());
dstar = new CDStarControl(m_callsign, module, selfOnly, errorReply, blackList, m_dstarNetwork, m_display, m_timeout, m_duplex, rssi); dstar = new CDStarControl(m_callsign, module, selfOnly, ackReply, ackTime, errorReply, blackList, m_dstarNetwork, m_display, m_timeout, m_duplex, remoteGateway, rssi);
} }
CDMRControl* dmr = NULL; CDMRControl* dmr = NULL;
@ -362,16 +381,20 @@ int CMMDVMHost::run()
unsigned int callHang = m_conf.getDMRCallHang(); unsigned int callHang = m_conf.getDMRCallHang();
unsigned int txHang = m_conf.getDMRTXHang(); unsigned int txHang = m_conf.getDMRTXHang();
unsigned int jitter = m_conf.getDMRNetworkJitter(); unsigned int jitter = m_conf.getDMRNetworkJitter();
m_dmrRFModeHang = m_conf.getDMRModeHang();
if (txHang > m_rfModeHang) if (txHang > m_dmrRFModeHang)
txHang = m_rfModeHang; txHang = m_dmrRFModeHang;
if (txHang > m_netModeHang)
txHang = m_netModeHang; if (m_conf.getDMRNetworkEnabled()) {
if (txHang > m_dmrNetModeHang)
txHang = m_dmrNetModeHang;
}
if (callHang > txHang) if (callHang > txHang)
callHang = txHang; callHang = txHang;
LogInfo("DMR Parameters"); LogInfo("DMR RF Parameters");
LogInfo(" Id: %u", id); LogInfo(" Id: %u", id);
LogInfo(" Color Code: %u", colorCode); LogInfo(" Color Code: %u", colorCode);
LogInfo(" Self Only: %s", selfOnly ? "yes" : "no"); LogInfo(" Self Only: %s", selfOnly ? "yes" : "no");
@ -390,6 +413,7 @@ int CMMDVMHost::run()
LogInfo(" Call Hang: %us", callHang); LogInfo(" Call Hang: %us", callHang);
LogInfo(" TX Hang: %us", txHang); LogInfo(" TX Hang: %us", txHang);
LogInfo(" Mode Hang: %us", m_dmrRFModeHang);
dmr = new CDMRControl(id, colorCode, callHang, selfOnly, embeddedLCOnly, dumpTAData, prefixes, blackList, whiteList, slot1TGWhiteList, slot2TGWhiteList, m_timeout, m_modem, m_dmrNetwork, m_display, m_duplex, m_lookup, rssi, jitter); dmr = new CDMRControl(id, colorCode, callHang, selfOnly, embeddedLCOnly, dumpTAData, prefixes, blackList, whiteList, slot1TGWhiteList, slot2TGWhiteList, m_timeout, m_modem, m_dmrNetwork, m_display, m_duplex, m_lookup, rssi, jitter);
@ -400,24 +424,42 @@ int CMMDVMHost::run()
if (m_ysfEnabled) { if (m_ysfEnabled) {
bool lowDeviation = m_conf.getFusionLowDeviation(); bool lowDeviation = m_conf.getFusionLowDeviation();
bool remoteGateway = m_conf.getFusionRemoteGateway(); bool remoteGateway = m_conf.getFusionRemoteGateway();
bool selfOnly = m_conf.getFusionSelfOnly();
bool sqlEnabled = m_conf.getFusionSQLEnabled();
unsigned char sql = m_conf.getFusionSQL();
m_ysfRFModeHang = m_conf.getFusionModeHang();
LogInfo("YSF Parameters"); LogInfo("YSF RF Parameters");
LogInfo(" Low Deviation: %s", lowDeviation ? "yes" : "no"); LogInfo(" Low Deviation: %s", lowDeviation ? "yes" : "no");
LogInfo(" Remote Gateway: %s", remoteGateway ? "yes" : "no"); LogInfo(" Remote Gateway: %s", remoteGateway ? "yes" : "no");
LogInfo(" Self Only: %s", selfOnly ? "yes" : "no");
LogInfo(" DSQ: %s", sqlEnabled ? "yes" : "no");
if (sqlEnabled)
LogInfo(" DSQ Value: %u", sql);
LogInfo(" Mode Hang: %us", m_ysfRFModeHang);
ysf = new CYSFControl(m_callsign, m_ysfNetwork, m_display, m_timeout, m_duplex, lowDeviation, remoteGateway, rssi); ysf = new CYSFControl(m_callsign, selfOnly, m_ysfNetwork, m_display, m_timeout, m_duplex, lowDeviation, remoteGateway, rssi);
ysf->setSQL(sqlEnabled, sql);
} }
CP25Control* p25 = NULL; CP25Control* p25 = NULL;
if (m_p25Enabled) { if (m_p25Enabled) {
unsigned int id = m_conf.getP25Id();
unsigned int nac = m_conf.getP25NAC(); unsigned int nac = m_conf.getP25NAC();
bool uidOverride = m_conf.getP25OverrideUID(); bool uidOverride = m_conf.getP25OverrideUID();
bool selfOnly = m_conf.getP25SelfOnly();
bool remoteGateway = m_conf.getP25RemoteGateway();
m_p25RFModeHang = m_conf.getP25ModeHang();
LogInfo("P25 Parameters"); LogInfo("P25 RF Parameters");
LogInfo(" Id: %u", id);
LogInfo(" NAC: $%03X", nac); LogInfo(" NAC: $%03X", nac);
LogInfo(" UID Override: %s", uidOverride ? "yes" : "no"); LogInfo(" UID Override: %s", uidOverride ? "yes" : "no");
LogInfo(" Self Only: %s", selfOnly ? "yes" : "no");
LogInfo(" Remote Gateway: %s", remoteGateway ? "yes" : "no");
LogInfo(" Mode Hang: %us", m_p25RFModeHang);
p25 = new CP25Control(nac, uidOverride, m_p25Network, m_display, m_timeout, m_duplex, m_lookup, rssi); p25 = new CP25Control(nac, id, selfOnly, uidOverride, m_p25Network, m_display, m_timeout, m_duplex, m_lookup, remoteGateway, rssi);
} }
setMode(MODE_IDLE); setMode(MODE_IDLE);
@ -456,7 +498,7 @@ int CMMDVMHost::run()
if (m_mode == MODE_IDLE) { if (m_mode == MODE_IDLE) {
bool ret = dstar->writeModem(data, len); bool ret = dstar->writeModem(data, len);
if (ret) { if (ret) {
m_modeTimer.setTimeout(m_rfModeHang); m_modeTimer.setTimeout(m_dstarRFModeHang);
setMode(MODE_DSTAR); setMode(MODE_DSTAR);
} }
} else if (m_mode == MODE_DSTAR) { } else if (m_mode == MODE_DSTAR) {
@ -473,12 +515,12 @@ int CMMDVMHost::run()
if (m_duplex) { if (m_duplex) {
bool ret = dmr->processWakeup(data); bool ret = dmr->processWakeup(data);
if (ret) { if (ret) {
m_modeTimer.setTimeout(m_rfModeHang); m_modeTimer.setTimeout(m_dmrRFModeHang);
setMode(MODE_DMR); setMode(MODE_DMR);
dmrBeaconTimer.stop(); dmrBeaconTimer.stop();
} }
} else { } else {
m_modeTimer.setTimeout(m_rfModeHang); m_modeTimer.setTimeout(m_dmrRFModeHang);
setMode(MODE_DMR); setMode(MODE_DMR);
dmr->writeModemSlot1(data, len); dmr->writeModemSlot1(data, len);
dmrBeaconTimer.stop(); dmrBeaconTimer.stop();
@ -510,12 +552,12 @@ int CMMDVMHost::run()
if (m_duplex) { if (m_duplex) {
bool ret = dmr->processWakeup(data); bool ret = dmr->processWakeup(data);
if (ret) { if (ret) {
m_modeTimer.setTimeout(m_rfModeHang); m_modeTimer.setTimeout(m_dmrRFModeHang);
setMode(MODE_DMR); setMode(MODE_DMR);
dmrBeaconTimer.stop(); dmrBeaconTimer.stop();
} }
} else { } else {
m_modeTimer.setTimeout(m_rfModeHang); m_modeTimer.setTimeout(m_dmrRFModeHang);
setMode(MODE_DMR); setMode(MODE_DMR);
dmr->writeModemSlot2(data, len); dmr->writeModemSlot2(data, len);
dmrBeaconTimer.stop(); dmrBeaconTimer.stop();
@ -546,7 +588,7 @@ int CMMDVMHost::run()
if (m_mode == MODE_IDLE) { if (m_mode == MODE_IDLE) {
bool ret = ysf->writeModem(data, len); bool ret = ysf->writeModem(data, len);
if (ret) { if (ret) {
m_modeTimer.setTimeout(m_rfModeHang); m_modeTimer.setTimeout(m_ysfRFModeHang);
setMode(MODE_YSF); setMode(MODE_YSF);
} }
} else if (m_mode == MODE_YSF) { } else if (m_mode == MODE_YSF) {
@ -562,7 +604,7 @@ int CMMDVMHost::run()
if (m_mode == MODE_IDLE) { if (m_mode == MODE_IDLE) {
bool ret = p25->writeModem(data, len); bool ret = p25->writeModem(data, len);
if (ret) { if (ret) {
m_modeTimer.setTimeout(m_rfModeHang); m_modeTimer.setTimeout(m_p25RFModeHang);
setMode(MODE_P25); setMode(MODE_P25);
} }
} else if (m_mode == MODE_P25) { } else if (m_mode == MODE_P25) {
@ -582,7 +624,7 @@ int CMMDVMHost::run()
len = dstar->readModem(data); len = dstar->readModem(data);
if (len > 0U) { if (len > 0U) {
if (m_mode == MODE_IDLE) { if (m_mode == MODE_IDLE) {
m_modeTimer.setTimeout(m_netModeHang); m_modeTimer.setTimeout(m_dstarNetModeHang);
setMode(MODE_DSTAR); setMode(MODE_DSTAR);
} }
if (m_mode == MODE_DSTAR) { if (m_mode == MODE_DSTAR) {
@ -601,7 +643,7 @@ int CMMDVMHost::run()
len = dmr->readModemSlot1(data); len = dmr->readModemSlot1(data);
if (len > 0U) { if (len > 0U) {
if (m_mode == MODE_IDLE) { if (m_mode == MODE_IDLE) {
m_modeTimer.setTimeout(m_netModeHang); m_modeTimer.setTimeout(m_dmrNetModeHang);
setMode(MODE_DMR); setMode(MODE_DMR);
} }
if (m_mode == MODE_DMR) { if (m_mode == MODE_DMR) {
@ -623,7 +665,7 @@ int CMMDVMHost::run()
len = dmr->readModemSlot2(data); len = dmr->readModemSlot2(data);
if (len > 0U) { if (len > 0U) {
if (m_mode == MODE_IDLE) { if (m_mode == MODE_IDLE) {
m_modeTimer.setTimeout(m_netModeHang); m_modeTimer.setTimeout(m_dmrNetModeHang);
setMode(MODE_DMR); setMode(MODE_DMR);
} }
if (m_mode == MODE_DMR) { if (m_mode == MODE_DMR) {
@ -647,7 +689,7 @@ int CMMDVMHost::run()
len = ysf->readModem(data); len = ysf->readModem(data);
if (len > 0U) { if (len > 0U) {
if (m_mode == MODE_IDLE) { if (m_mode == MODE_IDLE) {
m_modeTimer.setTimeout(m_netModeHang); m_modeTimer.setTimeout(m_ysfNetModeHang);
setMode(MODE_YSF); setMode(MODE_YSF);
} }
if (m_mode == MODE_YSF) { if (m_mode == MODE_YSF) {
@ -666,14 +708,13 @@ int CMMDVMHost::run()
len = p25->readModem(data); len = p25->readModem(data);
if (len > 0U) { if (len > 0U) {
if (m_mode == MODE_IDLE) { if (m_mode == MODE_IDLE) {
m_modeTimer.setTimeout(m_netModeHang); m_modeTimer.setTimeout(m_p25NetModeHang);
setMode(MODE_P25); setMode(MODE_P25);
} }
if (m_mode == MODE_P25) { if (m_mode == MODE_P25) {
m_modem->writeP25Data(data, len); m_modem->writeP25Data(data, len);
m_modeTimer.start(); m_modeTimer.start();
} } else if (m_mode != MODE_LOCKOUT) {
else if (m_mode != MODE_LOCKOUT) {
LogWarning("P25 data received when in mode %u", m_mode); LogWarning("P25 data received when in mode %u", m_mode);
} }
} }
@ -745,8 +786,6 @@ int CMMDVMHost::run()
CThread::sleep(5U); CThread::sleep(5U);
} }
LogMessage("MMDVMHost-%s is exiting on receipt of SIGHUP1", VERSION);
setMode(MODE_IDLE); setMode(MODE_IDLE);
m_modem->close(); m_modem->close();
@ -799,18 +838,22 @@ bool CMMDVMHost::createModem()
bool pttInvert = m_conf.getModemPTTInvert(); bool pttInvert = m_conf.getModemPTTInvert();
unsigned int txDelay = m_conf.getModemTXDelay(); unsigned int txDelay = m_conf.getModemTXDelay();
unsigned int dmrDelay = m_conf.getModemDMRDelay(); unsigned int dmrDelay = m_conf.getModemDMRDelay();
unsigned int rxLevel = m_conf.getModemRXLevel(); float rxLevel = m_conf.getModemRXLevel();
unsigned int cwIdTXLevel = m_conf.getModemCWIdTXLevel(); float cwIdTXLevel = m_conf.getModemCWIdTXLevel();
unsigned int dstarTXLevel = m_conf.getModemDStarTXLevel(); float dstarTXLevel = m_conf.getModemDStarTXLevel();
unsigned int dmrTXLevel = m_conf.getModemDMRTXLevel(); float dmrTXLevel = m_conf.getModemDMRTXLevel();
unsigned int ysfTXLevel = m_conf.getModemYSFTXLevel(); float ysfTXLevel = m_conf.getModemYSFTXLevel();
unsigned int p25TXLevel = m_conf.getModemP25TXLevel(); float p25TXLevel = m_conf.getModemP25TXLevel();
bool trace = m_conf.getModemTrace(); bool trace = m_conf.getModemTrace();
bool debug = m_conf.getModemDebug(); bool debug = m_conf.getModemDebug();
unsigned int colorCode = m_conf.getDMRColorCode(); unsigned int colorCode = m_conf.getDMRColorCode();
bool lowDeviation = m_conf.getFusionLowDeviation(); bool lowDeviation = m_conf.getFusionLowDeviation();
unsigned int rxFrequency = m_conf.getRxFrequency(); unsigned int rxFrequency = m_conf.getRXFrequency();
unsigned int txFrequency = m_conf.getTxFrequency(); unsigned int txFrequency = m_conf.getTXFrequency();
int rxOffset = m_conf.getModemRXOffset();
int txOffset = m_conf.getModemTXOffset();
int rxDCOffset = m_conf.getModemRXDCOffset();
int txDCOffset = m_conf.getModemTXDCOffset();
LogInfo("Modem Parameters"); LogInfo("Modem Parameters");
LogInfo(" Port: %s", port.c_str()); LogInfo(" Port: %s", port.c_str());
@ -818,20 +861,24 @@ bool CMMDVMHost::createModem()
LogInfo(" TX Invert: %s", txInvert ? "yes" : "no"); LogInfo(" TX Invert: %s", txInvert ? "yes" : "no");
LogInfo(" PTT Invert: %s", pttInvert ? "yes" : "no"); LogInfo(" PTT Invert: %s", pttInvert ? "yes" : "no");
LogInfo(" TX Delay: %ums", txDelay); LogInfo(" TX Delay: %ums", txDelay);
LogInfo(" RX Offset: %dHz", rxOffset);
LogInfo(" TX Offset: %dHz", txOffset);
LogInfo(" RX DC Offset: %d", rxDCOffset);
LogInfo(" TX DC Offset: %d", txDCOffset);
LogInfo(" DMR Delay: %u (%.1fms)", dmrDelay, float(dmrDelay) * 0.0416666F); LogInfo(" DMR Delay: %u (%.1fms)", dmrDelay, float(dmrDelay) * 0.0416666F);
LogInfo(" RX Level: %u%%", rxLevel); LogInfo(" RX Level: %.1f%%", rxLevel);
LogInfo(" CW Id TX Level: %u%%", cwIdTXLevel); LogInfo(" CW Id TX Level: %.1f%%", cwIdTXLevel);
LogInfo(" D-Star TX Level: %u%%", dstarTXLevel); LogInfo(" D-Star TX Level: %.1f%%", dstarTXLevel);
LogInfo(" DMR TX Level: %u%%", dmrTXLevel); LogInfo(" DMR TX Level: %.1f%%", dmrTXLevel);
LogInfo(" YSF TX Level: %u%%", ysfTXLevel); LogInfo(" YSF TX Level: %.1f%%", ysfTXLevel);
LogInfo(" P25 TX Level: %u%%", p25TXLevel); LogInfo(" P25 TX Level: %.1f%%", p25TXLevel);
LogInfo(" RX Frequency: %uHz", rxFrequency); LogInfo(" RX Frequency: %uHz (%uHz)", rxFrequency, rxFrequency + rxOffset);
LogInfo(" TX Frequency: %uHz", txFrequency); LogInfo(" TX Frequency: %uHz (%uHz)", txFrequency, txFrequency + txOffset);
m_modem = new CModem(port, m_duplex, rxInvert, txInvert, pttInvert, txDelay, dmrDelay, trace, debug); m_modem = new CModem(port, m_duplex, rxInvert, txInvert, pttInvert, txDelay, dmrDelay, trace, debug);
m_modem->setModeParams(m_dstarEnabled, m_dmrEnabled, m_ysfEnabled, m_p25Enabled); m_modem->setModeParams(m_dstarEnabled, m_dmrEnabled, m_ysfEnabled, m_p25Enabled);
m_modem->setLevels(rxLevel, cwIdTXLevel, dstarTXLevel, dmrTXLevel, ysfTXLevel, p25TXLevel); m_modem->setLevels(rxLevel, cwIdTXLevel, dstarTXLevel, dmrTXLevel, ysfTXLevel, p25TXLevel);
m_modem->setRFParams(rxFrequency, txFrequency); m_modem->setRFParams(rxFrequency, rxOffset, txFrequency, txOffset, txDCOffset, rxDCOffset);
m_modem->setDMRParams(colorCode); m_modem->setDMRParams(colorCode);
m_modem->setYSFParams(lowDeviation); m_modem->setYSFParams(lowDeviation);
@ -851,11 +898,13 @@ bool CMMDVMHost::createDStarNetwork()
unsigned int gatewayPort = m_conf.getDStarGatewayPort(); unsigned int gatewayPort = m_conf.getDStarGatewayPort();
unsigned int localPort = m_conf.getDStarLocalPort(); unsigned int localPort = m_conf.getDStarLocalPort();
bool debug = m_conf.getDStarNetworkDebug(); bool debug = m_conf.getDStarNetworkDebug();
m_dstarNetModeHang = m_conf.getDStarNetworkModeHang();
LogInfo("D-Star Network Parameters"); LogInfo("D-Star Network Parameters");
LogInfo(" Gateway Address: %s", gatewayAddress.c_str()); LogInfo(" Gateway Address: %s", gatewayAddress.c_str());
LogInfo(" Gateway Port: %u", gatewayPort); LogInfo(" Gateway Port: %u", gatewayPort);
LogInfo(" Local Port: %u", localPort); LogInfo(" Local Port: %u", localPort);
LogInfo(" Mode Hang: %us", m_dstarNetModeHang);
m_dstarNetwork = new CDStarNetwork(gatewayAddress, gatewayPort, localPort, m_duplex, VERSION, debug); m_dstarNetwork = new CDStarNetwork(gatewayAddress, gatewayPort, localPort, m_duplex, VERSION, debug);
@ -883,6 +932,7 @@ bool CMMDVMHost::createDMRNetwork()
bool slot1 = m_conf.getDMRNetworkSlot1(); bool slot1 = m_conf.getDMRNetworkSlot1();
bool slot2 = m_conf.getDMRNetworkSlot2(); bool slot2 = m_conf.getDMRNetworkSlot2();
HW_TYPE hwType = m_modem->getHWType(); HW_TYPE hwType = m_modem->getHWType();
m_dmrNetModeHang = m_conf.getDMRNetworkModeHang();
LogInfo("DMR Network Parameters"); LogInfo("DMR Network Parameters");
LogInfo(" Address: %s", address.c_str()); LogInfo(" Address: %s", address.c_str());
@ -894,6 +944,7 @@ bool CMMDVMHost::createDMRNetwork()
LogInfo(" Jitter: %ums", jitter); LogInfo(" Jitter: %ums", jitter);
LogInfo(" Slot 1: %s", slot1 ? "enabled" : "disabled"); LogInfo(" Slot 1: %s", slot1 ? "enabled" : "disabled");
LogInfo(" Slot 2: %s", slot2 ? "enabled" : "disabled"); LogInfo(" Slot 2: %s", slot2 ? "enabled" : "disabled");
LogInfo(" Mode Hang: %us", m_dmrNetModeHang);
m_dmrNetwork = new CDMRNetwork(address, port, local, id, password, m_duplex, VERSION, debug, slot1, slot2, hwType); m_dmrNetwork = new CDMRNetwork(address, port, local, id, password, m_duplex, VERSION, debug, slot1, slot2, hwType);
@ -903,8 +954,8 @@ bool CMMDVMHost::createDMRNetwork()
m_dmrNetwork->setOptions(options); m_dmrNetwork->setOptions(options);
} }
unsigned int rxFrequency = m_conf.getRxFrequency(); unsigned int rxFrequency = m_conf.getRXFrequency();
unsigned int txFrequency = m_conf.getTxFrequency(); unsigned int txFrequency = m_conf.getTXFrequency();
unsigned int power = m_conf.getPower(); unsigned int power = m_conf.getPower();
unsigned int colorCode = m_conf.getDMRColorCode(); unsigned int colorCode = m_conf.getDMRColorCode();
float latitude = m_conf.getLatitude(); float latitude = m_conf.getLatitude();
@ -944,17 +995,19 @@ bool CMMDVMHost::createYSFNetwork()
{ {
std::string myAddress = m_conf.getFusionNetworkMyAddress(); std::string myAddress = m_conf.getFusionNetworkMyAddress();
unsigned int myPort = m_conf.getFusionNetworkMyPort(); unsigned int myPort = m_conf.getFusionNetworkMyPort();
std::string gwyAddress = m_conf.getFusionNetworkGwyAddress(); std::string gatewayAddress = m_conf.getFusionNetworkGatewayAddress();
unsigned int gwyPort = m_conf.getFusionNetworkGwyPort(); unsigned int gatewayPort = m_conf.getFusionNetworkGatewayPort();
m_ysfNetModeHang = m_conf.getFusionNetworkModeHang();
bool debug = m_conf.getFusionNetworkDebug(); bool debug = m_conf.getFusionNetworkDebug();
LogInfo("System Fusion Network Parameters"); LogInfo("System Fusion Network Parameters");
LogInfo(" Local Address: %s", myAddress.c_str()); LogInfo(" Local Address: %s", myAddress.c_str());
LogInfo(" Local Port: %u", myPort); LogInfo(" Local Port: %u", myPort);
LogInfo(" Gateway Address: %s", gwyAddress.c_str()); LogInfo(" Gateway Address: %s", gatewayAddress.c_str());
LogInfo(" Gateway Port: %u", gwyPort); LogInfo(" Gateway Port: %u", gatewayPort);
LogInfo(" Mode Hang: %us", m_ysfNetModeHang);
m_ysfNetwork = new CYSFNetwork(myAddress, myPort, gwyAddress, gwyPort, m_callsign, debug); m_ysfNetwork = new CYSFNetwork(myAddress, myPort, gatewayAddress, gatewayPort, m_callsign, debug);
bool ret = m_ysfNetwork->open(); bool ret = m_ysfNetwork->open();
if (!ret) { if (!ret) {
@ -973,12 +1026,14 @@ bool CMMDVMHost::createP25Network()
std::string gatewayAddress = m_conf.getP25GatewayAddress(); std::string gatewayAddress = m_conf.getP25GatewayAddress();
unsigned int gatewayPort = m_conf.getP25GatewayPort(); unsigned int gatewayPort = m_conf.getP25GatewayPort();
unsigned int localPort = m_conf.getP25LocalPort(); unsigned int localPort = m_conf.getP25LocalPort();
m_p25NetModeHang = m_conf.getP25NetworkModeHang();
bool debug = m_conf.getP25NetworkDebug(); bool debug = m_conf.getP25NetworkDebug();
LogInfo("P25 Network Parameters"); LogInfo("P25 Network Parameters");
LogInfo(" Gateway Address: %s", gatewayAddress.c_str()); LogInfo(" Gateway Address: %s", gatewayAddress.c_str());
LogInfo(" Gateway Port: %u", gatewayPort); LogInfo(" Gateway Port: %u", gatewayPort);
LogInfo(" Local Port: %u", localPort); LogInfo(" Local Port: %u", localPort);
LogInfo(" Mode Hang: %us", m_p25NetModeHang);
m_p25Network = new CP25Network(gatewayAddress, gatewayPort, localPort, debug); m_p25Network = new CP25Network(gatewayAddress, gatewayPort, localPort, debug);
@ -1002,17 +1057,14 @@ void CMMDVMHost::readParams()
m_p25Enabled = m_conf.getP25Enabled(); m_p25Enabled = m_conf.getP25Enabled();
m_duplex = m_conf.getDuplex(); m_duplex = m_conf.getDuplex();
m_callsign = m_conf.getCallsign(); m_callsign = m_conf.getCallsign();
m_id = m_conf.getId();
m_timeout = m_conf.getTimeout(); m_timeout = m_conf.getTimeout();
m_rfModeHang = m_conf.getRFModeHang();
m_netModeHang = m_conf.getNetModeHang();
LogInfo("General Parameters"); LogInfo("General Parameters");
LogInfo(" Callsign: %s", m_callsign.c_str()); LogInfo(" Callsign: %s", m_callsign.c_str());
LogInfo(" Id: %u", m_id);
LogInfo(" Duplex: %s", m_duplex ? "yes" : "no"); LogInfo(" Duplex: %s", m_duplex ? "yes" : "no");
LogInfo(" Timeout: %us", m_timeout); LogInfo(" Timeout: %us", m_timeout);
LogInfo(" RF Mode Hang: %us", m_rfModeHang);
LogInfo(" Net Mode Hang: %us", m_netModeHang);
LogInfo(" D-Star: %s", m_dstarEnabled ? "enabled" : "disabled"); LogInfo(" D-Star: %s", m_dstarEnabled ? "enabled" : "disabled");
LogInfo(" DMR: %s", m_dmrEnabled ? "enabled" : "disabled"); LogInfo(" DMR: %s", m_dmrEnabled ? "enabled" : "disabled");
LogInfo(" YSF: %s", m_ysfEnabled ? "enabled" : "disabled"); LogInfo(" YSF: %s", m_ysfEnabled ? "enabled" : "disabled");
@ -1047,6 +1099,7 @@ void CMMDVMHost::createDisplay()
bool displayClock = m_conf.getNextionDisplayClock(); bool displayClock = m_conf.getNextionDisplayClock();
bool utc = m_conf.getNextionUTC(); bool utc = m_conf.getNextionUTC();
unsigned int idleBrightness = m_conf.getNextionIdleBrightness(); unsigned int idleBrightness = m_conf.getNextionIdleBrightness();
unsigned int screenLayout = m_conf.getNextionScreenLayout();
LogInfo(" Port: %s", port.c_str()); LogInfo(" Port: %s", port.c_str());
LogInfo(" Brightness: %u", brightness); LogInfo(" Brightness: %u", brightness);
@ -1055,15 +1108,27 @@ void CMMDVMHost::createDisplay()
LogInfo(" Display UTC: %s", utc ? "yes" : "no"); LogInfo(" Display UTC: %s", utc ? "yes" : "no");
LogInfo(" Idle Brightness: %u", idleBrightness); LogInfo(" Idle Brightness: %u", idleBrightness);
switch (screenLayout) {
case 0U:
LogInfo(" Screen Layout: G4KLX (Default)");
break;
case 2U:
LogInfo(" Screen Layout: ON7LDS");
break;
default:
LogInfo(" Screen Layout: %u (Unknown)", screenLayout);
break;
}
if (port == "modem") { if (port == "modem") {
ISerialPort* serial = new CModemSerialPort(m_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") { } else if (port == "ump") {
if (m_ump != NULL) 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 { } else {
ISerialPort* serial = new CSerialController(port, SERIAL_9600); 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") { } else if (type == "LCDproc") {
std::string address = m_conf.getLCDprocAddress(); std::string address = m_conf.getLCDprocAddress();
@ -1131,7 +1196,8 @@ void CMMDVMHost::createDisplay()
unsigned char type = m_conf.getOLEDType(); unsigned char type = m_conf.getOLEDType();
unsigned char brightness = m_conf.getOLEDBrightness(); unsigned char brightness = m_conf.getOLEDBrightness();
bool invert = m_conf.getOLEDInvert(); bool invert = m_conf.getOLEDInvert();
m_display = new COLED(type, brightness, invert); bool scroll = m_conf.getOLEDScroll();
m_display = new COLED(type, brightness, invert, scroll);
#endif #endif
} else { } else {
m_display = new CNullDisplay; m_display = new CNullDisplay;

View file

@ -50,8 +50,14 @@ private:
CDisplay* m_display; CDisplay* m_display;
CUMP* m_ump; CUMP* m_ump;
unsigned char m_mode; unsigned char m_mode;
unsigned int m_rfModeHang; unsigned int m_dstarRFModeHang;
unsigned int m_netModeHang; unsigned int m_dmrRFModeHang;
unsigned int m_ysfRFModeHang;
unsigned int m_p25RFModeHang;
unsigned int m_dstarNetModeHang;
unsigned int m_dmrNetModeHang;
unsigned int m_ysfNetModeHang;
unsigned int m_p25NetModeHang;
CTimer m_modeTimer; CTimer m_modeTimer;
CTimer m_dmrTXTimer; CTimer m_dmrTXTimer;
CTimer m_cwIdTimer; CTimer m_cwIdTimer;
@ -64,6 +70,7 @@ private:
unsigned int m_cwIdTime; unsigned int m_cwIdTime;
CDMRLookup* m_lookup; CDMRLookup* m_lookup;
std::string m_callsign; std::string m_callsign;
unsigned int m_id;
std::string m_cwCallsign; std::string m_cwCallsign;
void readParams(); void readParams();

View file

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> <Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations"> <ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32"> <ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration> <Configuration>Debug</Configuration>
@ -22,32 +22,32 @@
<ProjectGuid>{1D34E8C1-CFA5-4D60-B509-9DB58DC4AE92}</ProjectGuid> <ProjectGuid>{1D34E8C1-CFA5-4D60-B509-9DB58DC4AE92}</ProjectGuid>
<Keyword>Win32Proj</Keyword> <Keyword>Win32Proj</Keyword>
<RootNamespace>MMDVMHost</RootNamespace> <RootNamespace>MMDVMHost</RootNamespace>
<WindowsTargetPlatformVersion>8.1</WindowsTargetPlatformVersion> <WindowsTargetPlatformVersion>10.0.15063.0</WindowsTargetPlatformVersion>
</PropertyGroup> </PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType> <ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries> <UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset> <PlatformToolset>v141</PlatformToolset>
<CharacterSet>Unicode</CharacterSet> <CharacterSet>Unicode</CharacterSet>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType> <ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries> <UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset> <PlatformToolset>v141</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization> <WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet> <CharacterSet>Unicode</CharacterSet>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType> <ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries> <UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset> <PlatformToolset>v141</PlatformToolset>
<CharacterSet>Unicode</CharacterSet> <CharacterSet>Unicode</CharacterSet>
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration"> <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType> <ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries> <UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v140</PlatformToolset> <PlatformToolset>v141</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization> <WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet> <CharacterSet>Unicode</CharacterSet>
</PropertyGroup> </PropertyGroup>
@ -183,12 +183,14 @@
<ClInclude Include="Golay24128.h" /> <ClInclude Include="Golay24128.h" />
<ClInclude Include="Hamming.h" /> <ClInclude Include="Hamming.h" />
<ClInclude Include="DMRLookup.h" /> <ClInclude Include="DMRLookup.h" />
<ClInclude Include="JitterBuffer.h" />
<ClInclude Include="LCDproc.h" /> <ClInclude Include="LCDproc.h" />
<ClInclude Include="Log.h" /> <ClInclude Include="Log.h" />
<ClInclude Include="MMDVMHost.h" /> <ClInclude Include="MMDVMHost.h" />
<ClInclude Include="Modem.h" /> <ClInclude Include="Modem.h" />
<ClInclude Include="ModemSerialPort.h" /> <ClInclude Include="ModemSerialPort.h" />
<ClInclude Include="Mutex.h" /> <ClInclude Include="Mutex.h" />
<ClInclude Include="NetworkInfo.h" />
<ClInclude Include="Nextion.h" /> <ClInclude Include="Nextion.h" />
<ClInclude Include="NullDisplay.h" /> <ClInclude Include="NullDisplay.h" />
<ClInclude Include="P25Audio.h" /> <ClInclude Include="P25Audio.h" />
@ -252,12 +254,14 @@
<ClCompile Include="Golay2087.cpp" /> <ClCompile Include="Golay2087.cpp" />
<ClCompile Include="Golay24128.cpp" /> <ClCompile Include="Golay24128.cpp" />
<ClCompile Include="Hamming.cpp" /> <ClCompile Include="Hamming.cpp" />
<ClCompile Include="JitterBuffer.cpp" />
<ClCompile Include="LCDproc.cpp" /> <ClCompile Include="LCDproc.cpp" />
<ClCompile Include="Log.cpp" /> <ClCompile Include="Log.cpp" />
<ClCompile Include="MMDVMHost.cpp" /> <ClCompile Include="MMDVMHost.cpp" />
<ClCompile Include="Modem.cpp" /> <ClCompile Include="Modem.cpp" />
<ClCompile Include="ModemSerialPort.cpp" /> <ClCompile Include="ModemSerialPort.cpp" />
<ClCompile Include="Mutex.cpp" /> <ClCompile Include="Mutex.cpp" />
<ClCompile Include="NetworkInfo.cpp" />
<ClCompile Include="Nextion.cpp" /> <ClCompile Include="Nextion.cpp" />
<ClCompile Include="NullDisplay.cpp" /> <ClCompile Include="NullDisplay.cpp" />
<ClCompile Include="P25Audio.cpp" /> <ClCompile Include="P25Audio.cpp" />

View file

@ -221,6 +221,12 @@
<ClInclude Include="RSSIInterpolator.h"> <ClInclude Include="RSSIInterpolator.h">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="NetworkInfo.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="JitterBuffer.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClCompile Include="BPTC19696.cpp"> <ClCompile Include="BPTC19696.cpp">
@ -412,5 +418,11 @@
<ClCompile Include="RSSIInterpolator.cpp"> <ClCompile Include="RSSIInterpolator.cpp">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="NetworkInfo.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="JitterBuffer.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
</Project> </Project>

View file

@ -9,9 +9,9 @@ LDFLAGS = -g
OBJECTS = \ 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 \ 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 \ 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 JitterBuffer.o LCDproc.o Log.o MMDVMHost.o Modem.o ModemSerialPort.o Mutex.o NetworkInfo.o Nextion.o NullDisplay.o P25Audio.o P25Control.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 \ 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 \
Timer.o UDPSocket.o UMP.o Utils.o YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.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
all: MMDVMHost all: MMDVMHost

View file

@ -9,9 +9,9 @@ LDFLAGS = -g -L/usr/local/lib
OBJECTS = \ 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 \ 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 \ 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 JitterBuffer.o LCDproc.o Log.o MMDVMHost.o Modem.o ModemSerialPort.o Mutex.o NetworkInfo.o Nextion.o NullDisplay.o P25Audio.o P25Control.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 \ 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 \
Timer.o UDPSocket.o UMP.o Utils.o YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.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
all: MMDVMHost all: MMDVMHost

View file

@ -9,9 +9,9 @@ LDFLAGS = -g -L/usr/local/lib
OBJECTS = \ 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 \ 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 \ 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 HD44780.o LCDproc.o Log.o MMDVMHost.o Modem.o ModemSerialPort.o Mutex.o Nextion.o NullDisplay.o P25Audio.o P25Control.o P25Data.o \ Golay24128.o Hamming.o HD44780.o JitterBuffer.o LCDproc.o Log.o MMDVMHost.o Modem.o ModemSerialPort.o Mutex.o NetworkInfo.o Nextion.o NullDisplay.o P25Audio.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 \ 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 \
TFTSerial.o Thread.o Timer.o UDPSocket.o UMP.o Utils.o YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.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
all: MMDVMHost all: MMDVMHost

View file

@ -9,9 +9,9 @@ LDFLAGS = -g -L/usr/local/lib
OBJECTS = \ 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 \ 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 \ 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 HD44780.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 HD44780.o JitterBuffer.o LCDproc.o Log.o MMDVMHost.o Modem.o ModemSerialPort.o Mutex.o NetworkInfo.o Nextion.o NullDisplay.o P25Audio.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 \ 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 \
Timer.o UDPSocket.o UMP.o Utils.o YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.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
all: MMDVMHost all: MMDVMHost

View file

@ -9,9 +9,9 @@ LDFLAGS = -g -L/usr/local/lib
OBJECTS = \ 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 \ 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 \ 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 OLED.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 JitterBuffer.o OLED.o LCDproc.o Log.o MMDVMHost.o Modem.o ModemSerialPort.o Mutex.o NetworkInfo.o Nextion.o NullDisplay.o P25Audio.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 \ P25Control.o P25Data.o P25LowSpeedData.o P25Network.o P25NID.o P25Utils.o QR1676.o RS129.o RS241213.o RSSIInterpolator.o SerialController.o SerialPort.o \
Timer.o UDPSocket.o UMP.o Utils.o YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.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
all: MMDVMHost all: MMDVMHost

View file

@ -9,9 +9,9 @@ LDFLAGS = -g -L/usr/local/lib
OBJECTS = \ 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 \ 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 \ 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 HD44780.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 HD44780.o JitterBuffer.o LCDproc.o Log.o MMDVMHost.o Modem.o ModemSerialPort.o Mutex.o NetworkInfo.o Nextion.o NullDisplay.o P25Audio.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 \ 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 \
Timer.o UDPSocket.o UMP.o Utils.o YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.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
all: MMDVMHost all: MMDVMHost

View file

@ -9,9 +9,9 @@ LDFLAGS = -g
OBJECTS = \ 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 \ 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 \ 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 JitterBuffer.o LCDproc.o Log.o MMDVMHost.o Modem.o ModemSerialPort.o Mutex.o NetworkInfo.o Nextion.o NullDisplay.o P25Audio.o P25Control.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 \ 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 \
Timer.o UDPSocket.o UMP.o Utils.o YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.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
all: MMDVMHost all: MMDVMHost

View file

@ -107,6 +107,8 @@ m_dstarEnabled(false),
m_dmrEnabled(false), m_dmrEnabled(false),
m_ysfEnabled(false), m_ysfEnabled(false),
m_p25Enabled(false), m_p25Enabled(false),
m_rxDCOffset(0),
m_txDCOffset(0),
m_serial(port, SERIAL_115200, true), m_serial(port, SERIAL_115200, true),
m_buffer(NULL), m_buffer(NULL),
m_length(0U), m_length(0U),
@ -145,10 +147,12 @@ CModem::~CModem()
delete[] m_buffer; delete[] m_buffer;
} }
void CModem::setRFParams(unsigned int rxFrequency, unsigned int txFrequency) void CModem::setRFParams(unsigned int rxFrequency, int rxOffset, unsigned int txFrequency, int txOffset, int txDCOffset, int rxDCOffset)
{ {
m_rxFrequency = rxFrequency; m_rxFrequency = rxFrequency + rxOffset;
m_txFrequency = txFrequency; m_txFrequency = txFrequency + txOffset;
m_txDCOffset = txDCOffset;
m_rxDCOffset = rxDCOffset;
} }
void CModem::setModeParams(bool dstarEnabled, bool dmrEnabled, bool ysfEnabled, bool p25Enabled) void CModem::setModeParams(bool dstarEnabled, bool dmrEnabled, bool ysfEnabled, bool p25Enabled)
@ -159,7 +163,7 @@ void CModem::setModeParams(bool dstarEnabled, bool dmrEnabled, bool ysfEnabled,
m_p25Enabled = p25Enabled; m_p25Enabled = p25Enabled;
} }
void CModem::setLevels(unsigned int rxLevel, unsigned int cwIdTXLevel, unsigned int dstarTXLevel, unsigned int dmrTXLevel, unsigned int ysfTXLevel, unsigned int p25TXLevel) void CModem::setLevels(float rxLevel, float cwIdTXLevel, float dstarTXLevel, float dmrTXLevel, float ysfTXLevel, float p25TXLevel)
{ {
m_rxLevel = rxLevel; m_rxLevel = rxLevel;
m_cwIdTXLevel = cwIdTXLevel; m_cwIdTXLevel = cwIdTXLevel;
@ -902,6 +906,10 @@ bool CModem::readVersion()
if (ret != 3) if (ret != 3)
return false; return false;
#if defined(__APPLE__)
m_serial.setNonblock(true);
#endif
for (unsigned int count = 0U; count < MAX_RESPONSES; count++) { for (unsigned int count = 0U; count < MAX_RESPONSES; count++) {
CThread::sleep(10U); CThread::sleep(10U);
RESP_TYPE_MMDVM resp = getResponse(); RESP_TYPE_MMDVM resp = getResponse();
@ -910,6 +918,8 @@ bool CModem::readVersion()
m_hwType = HWT_MMDVM; m_hwType = HWT_MMDVM;
else if (::memcmp(m_buffer + 4U, "DVMEGA", 6U) == 0) else if (::memcmp(m_buffer + 4U, "DVMEGA", 6U) == 0)
m_hwType = HWT_DVMEGA; m_hwType = HWT_DVMEGA;
else if (::memcmp(m_buffer + 4U, "ZUMspot", 7U) == 0)
m_hwType = HWT_MMDVM_HS;
LogInfo("MMDVM protocol version: %u, description: %.*s", m_buffer[3U], m_length - 4U, m_buffer + 4U); LogInfo("MMDVM protocol version: %u, description: %.*s", m_buffer[3U], m_length - 4U, m_buffer + 4U);
return true; return true;
@ -943,7 +953,7 @@ bool CModem::setConfig()
buffer[0U] = MMDVM_FRAME_START; buffer[0U] = MMDVM_FRAME_START;
buffer[1U] = 16U; buffer[1U] = 18U;
buffer[2U] = MMDVM_SET_CONFIG; buffer[2U] = MMDVM_SET_CONFIG;
@ -975,9 +985,9 @@ bool CModem::setConfig()
buffer[6U] = MODE_IDLE; buffer[6U] = MODE_IDLE;
buffer[7U] = (m_rxLevel * 255U) / 100U; buffer[7U] = (unsigned char)(m_rxLevel * 2.55F + 0.5F);
buffer[8U] = (m_cwIdTXLevel * 255U) / 100U; buffer[8U] = (unsigned char)(m_cwIdTXLevel * 2.55F + 0.5F);
buffer[9U] = m_dmrColorCode; buffer[9U] = m_dmrColorCode;
@ -985,15 +995,18 @@ bool CModem::setConfig()
buffer[11U] = 128U; // Was OscOffset buffer[11U] = 128U; // Was OscOffset
buffer[12U] = (m_dstarTXLevel * 255U) / 100U; buffer[12U] = (unsigned char)(m_dstarTXLevel * 2.55F + 0.5F);
buffer[13U] = (m_dmrTXLevel * 255U) / 100U; buffer[13U] = (unsigned char)(m_dmrTXLevel * 2.55F + 0.5F);
buffer[14U] = (m_ysfTXLevel * 255U) / 100U; buffer[14U] = (unsigned char)(m_ysfTXLevel * 2.55F + 0.5F);
buffer[15U] = (m_p25TXLevel * 255U) / 100U; buffer[15U] = (unsigned char)(m_p25TXLevel * 2.55F + 0.5F);
// CUtils::dump(1U, "Written", buffer, 16U); buffer[16U] = (unsigned char)(m_txDCOffset + 128);
buffer[17U] = (unsigned char)(m_rxDCOffset + 128);
int ret = m_serial.write(buffer, 16U); // CUtils::dump(1U, "Written", buffer, 18U);
if (ret != 16)
int ret = m_serial.write(buffer, 18U);
if (ret != 18)
return false; return false;
unsigned int count = 0U; unsigned int count = 0U;

18
Modem.h
View file

@ -37,9 +37,9 @@ public:
CModem(const std::string& port, bool duplex, bool rxInvert, bool txInvert, bool pttInvert, unsigned int txDelay, unsigned int dmrDelay, bool trace, bool debug); CModem(const std::string& port, bool duplex, bool rxInvert, bool txInvert, bool pttInvert, unsigned int txDelay, unsigned int dmrDelay, bool trace, bool debug);
~CModem(); ~CModem();
void setRFParams(unsigned int rxFrequency, unsigned int txFrequency); void setRFParams(unsigned int rxFrequency, int rxOffset, unsigned int txFrequency, int txOffset, int txDCOffset, int rxDCOffset);
void setModeParams(bool dstarEnabled, bool dmrEnabled, bool ysfEnabled, bool p25Enabled); void setModeParams(bool dstarEnabled, bool dmrEnabled, bool ysfEnabled, bool p25Enabled);
void setLevels(unsigned int rxLevel, unsigned int cwIdTXLevel, unsigned int dstarTXLevel, unsigned int dmrTXLevel, unsigned int ysfTXLevel, unsigned int p25Enabled); void setLevels(float rxLevel, float cwIdTXLevel, float dstarTXLevel, float dmrTXLevel, float ysfTXLevel, float p25Enabled);
void setDMRParams(unsigned int colorCode); void setDMRParams(unsigned int colorCode);
void setYSFParams(bool loDev); void setYSFParams(bool loDev);
@ -97,12 +97,12 @@ private:
bool m_pttInvert; bool m_pttInvert;
unsigned int m_txDelay; unsigned int m_txDelay;
unsigned int m_dmrDelay; unsigned int m_dmrDelay;
unsigned int m_rxLevel; float m_rxLevel;
unsigned int m_cwIdTXLevel; float m_cwIdTXLevel;
unsigned int m_dstarTXLevel; float m_dstarTXLevel;
unsigned int m_dmrTXLevel; float m_dmrTXLevel;
unsigned int m_ysfTXLevel; float m_ysfTXLevel;
unsigned int m_p25TXLevel; float m_p25TXLevel;
bool m_trace; bool m_trace;
bool m_debug; bool m_debug;
unsigned int m_rxFrequency; unsigned int m_rxFrequency;
@ -111,6 +111,8 @@ private:
bool m_dmrEnabled; bool m_dmrEnabled;
bool m_ysfEnabled; bool m_ysfEnabled;
bool m_p25Enabled; bool m_p25Enabled;
int m_rxDCOffset;
int m_txDCOffset;
CSerialController m_serial; CSerialController m_serial;
unsigned char* m_buffer; unsigned char* m_buffer;
unsigned int m_length; unsigned int m_length;

222
NetworkInfo.cpp Normal file
View file

@ -0,0 +1,222 @@
/*
* 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 "NetworkInfo.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
CNetworkInfo::CNetworkInfo()
{
}
CNetworkInfo::~CNetworkInfo()
{
}
void CNetworkInfo::getNetworkInterface(unsigned char* info)
{
LogInfo("Interfaces Info");
::strcpy((char*)info, "(address unknown)");
#if !defined(_WIN32) && !defined(_WIN64)
const unsigned int IFLISTSIZ = 25U;
FILE* fp = ::fopen("/proc/net/route" , "r");
if (fp == NULL) {
LogError("Unabled to open /proc/route");
return;
}
char* dflt = NULL;
char line[100U];
while (::fgets(line, 100U, fp)) {
char* p1 = strtok(line , " \t");
char* p2 = strtok(NULL , " \t");
if (p1 != NULL && p2 != NULL) {
if (::strcmp(p2, "00000000") == 0) {
dflt = p1;
break;
}
}
}
::fclose(fp);
if (dflt == NULL) {
LogError("Unable to find the default route");
return;
}
char interfacelist[IFLISTSIZ][50+INET6_ADDRSTRLEN];
for (unsigned int n = 0U; n < IFLISTSIZ; n++)
interfacelist[n][0] = 0;
struct ifaddrs* ifaddr;
if (::getifaddrs(&ifaddr) == -1) {
LogError("getifaddrs failure");
return;
}
unsigned int ifnr = 0U;
for (struct ifaddrs* ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
if (ifa->ifa_addr == NULL)
continue;
int family = ifa->ifa_addr->sa_family;
if (family == AF_INET || family == AF_INET6) {
char host[NI_MAXHOST];
int 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 (unsigned int n = 0U; n < ifnr; n++) {
char* 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 = (MIB_IPFORWARDTABLE *)::malloc(sizeof(MIB_IPFORWARDTABLE));
if (pIpForwardTable == NULL) {
LogError("Error allocating memory");
return;
}
DWORD dwSize = 0U;
if (::GetIpForwardTable(pIpForwardTable, &dwSize, 0) == ERROR_INSUFFICIENT_BUFFER) {
::free(pIpForwardTable);
pIpForwardTable = (MIB_IPFORWARDTABLE *)::malloc(dwSize);
if (pIpForwardTable == NULL) {
LogError("Error allocating memory");
return;
}
}
DWORD ret = ::GetIpForwardTable(pIpForwardTable, &dwSize, 0);
if (ret != NO_ERROR) {
::free(pIpForwardTable);
LogError("GetIpForwardTable failed.");
return;
}
DWORD found = 999U;
for (DWORD i = 0U; i < pIpForwardTable->dwNumEntries; i++) {
if (pIpForwardTable->table[i].dwForwardDest == 0U) {
found = i;
break;
}
}
if (found == 999U) {
::free(pIpForwardTable);
LogError("Unable to find the default destination in the routing table.");
return;
}
DWORD ifnr = pIpForwardTable->table[found].dwForwardIfIndex;
::free(pIpForwardTable);
PIP_ADAPTER_INFO pAdapterInfo = (IP_ADAPTER_INFO *)::malloc(sizeof(IP_ADAPTER_INFO));
if (pAdapterInfo == NULL) {
LogError("Error allocating memory");
return;
}
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) {
::free(pAdapterInfo);
LogError("Call to GetAdaptersInfo failed.");
return;
}
PIP_ADAPTER_INFO pAdapter = pAdapterInfo;
while (pAdapter != NULL) {
LogInfo(" IP : %s", pAdapter->IpAddressList.IpAddress.String);
if (pAdapter->Index == ifnr)
::strcpy((char*)info, pAdapter->IpAddressList.IpAddress.String);
pAdapter = pAdapter->Next;
}
::free(pAdapterInfo);
LogInfo(" IP to show: %s", info);
#endif
}

32
NetworkInfo.h Normal file
View file

@ -0,0 +1,32 @@
/*
* 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(NETWORKINFO_H)
#define NETWORKINFO_H
class CNetworkInfo {
public:
CNetworkInfo();
~CNetworkInfo();
void getNetworkInterface(unsigned char* info);
private:
};
#endif

View file

@ -16,6 +16,7 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/ */
#include "NetworkInfo.h"
#include "Nextion.h" #include "Nextion.h"
#include "Log.h" #include "Log.h"
@ -24,6 +25,7 @@
#include <cstring> #include <cstring>
#include <ctime> #include <ctime>
#include <clocale> #include <clocale>
//#include <unistd.h>
const unsigned int DSTAR_RSSI_COUNT = 3U; // 3 * 420ms = 1260ms const unsigned int DSTAR_RSSI_COUNT = 3U; // 3 * 420ms = 1260ms
const unsigned int DSTAR_BER_COUNT = 63U; // 63 * 20ms = 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_RSSI_COUNT = 7U; // 7 * 180ms = 1260ms
const unsigned int P25_BER_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(), CDisplay(),
m_callsign(callsign), m_callsign(callsign),
m_ipaddress("(ip unknown)"),
m_dmrid(dmrid), m_dmrid(dmrid),
m_serial(serial), m_serial(serial),
m_brightness(brightness), m_brightness(brightness),
@ -44,6 +47,7 @@ m_mode(MODE_IDLE),
m_displayClock(displayClock), m_displayClock(displayClock),
m_utc(utc), m_utc(utc),
m_idleBrightness(idleBrightness), m_idleBrightness(idleBrightness),
m_screenLayout(screenLayout),
m_clockDisplayTimer(1000U, 0U, 400U), m_clockDisplayTimer(1000U, 0U, 400U),
m_rssiAccum1(0U), m_rssiAccum1(0U),
m_rssiAccum2(0U), m_rssiAccum2(0U),
@ -64,6 +68,9 @@ CNextion::~CNextion()
bool CNextion::open() bool CNextion::open()
{ {
unsigned char info[100U];
CNetworkInfo* m_network;
bool ret = m_serial->open(); bool ret = m_serial->open();
if (!ret) { if (!ret) {
LogError("Cannot open the port for the Nextion display"); LogError("Cannot open the port for the Nextion display");
@ -71,6 +78,11 @@ bool CNextion::open()
return false; return false;
} }
info[0]=0;
m_network = new CNetworkInfo;
m_network->getNetworkInterface(info);
m_ipaddress = (char*)info;
sendCommand("bkcmd=0"); sendCommand("bkcmd=0");
setIdle(); setIdle();
@ -78,19 +90,23 @@ bool CNextion::open()
return true; return true;
} }
void CNextion::setIdleInt() void CNextion::setIdleInt()
{ {
sendCommand("page MMDVM"); sendCommand("page MMDVM");
char command[30]; char command[30U];
::sprintf(command, "dim=%u", m_idleBrightness); ::sprintf(command, "dim=%u", m_idleBrightness);
sendCommand(command); 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(command);
sendCommand("t1.txt=\"MMDVM IDLE\""); sendCommand("t1.txt=\"MMDVM IDLE\"");
::sprintf(command, "t3.txt=\"%s\"", m_ipaddress.c_str());
sendCommand(command);
m_clockDisplayTimer.start(); m_clockDisplayTimer.start();
m_mode = MODE_IDLE; m_mode = MODE_IDLE;
@ -226,11 +242,22 @@ void CNextion::writeDMRInt(unsigned int slotNo, const std::string& src, bool gro
if (m_mode != MODE_DMR) { if (m_mode != MODE_DMR) {
sendCommand("page 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\""); sendCommand("t2.txt=\"2 Listening\"");
else } else {
if (m_screenLayout == 2U) {
sendCommand("t0.pco=0");
sendCommand("t0.font=4");
}
sendCommand("t0.txt=\"1 Listening\""); sendCommand("t0.txt=\"1 Listening\"");
} }
}
char text[30U]; char text[30U];
::sprintf(text, "dim=%u", m_brightness); ::sprintf(text, "dim=%u", m_brightness);
@ -238,12 +265,24 @@ void CNextion::writeDMRInt(unsigned int slotNo, const std::string& src, bool gro
if (slotNo == 1U) { if (slotNo == 1U) {
::sprintf(text, "t0.txt=\"1 %s %s\"", type, src.c_str()); ::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); sendCommand(text);
::sprintf(text, "t1.txt=\"%s%s\"", group ? "TG" : "", dst.c_str()); ::sprintf(text, "t1.txt=\"%s%s\"", group ? "TG" : "", dst.c_str());
sendCommand(text); sendCommand(text);
} else { } else {
::sprintf(text, "t2.txt=\"2 %s %s\"", type, src.c_str()); ::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); sendCommand(text);
::sprintf(text, "t3.txt=\"%s%s\"", group ? "TG" : "", dst.c_str()); ::sprintf(text, "t3.txt=\"%s%s\"", group ? "TG" : "", dst.c_str());
@ -306,6 +345,52 @@ void CNextion::writeDMRRSSIInt(unsigned int slotNo, unsigned char rssi)
} }
} }
void CNextion::writeDMRTAInt(unsigned int slotNo, unsigned char* talkerAlias, const char* type)
{
if (m_screenLayout < 2U)
return;
if (type[0] == ' ') {
if (slotNo == 1U)
sendCommand("t0.pco=33808");
else
sendCommand("t2.pco=33808");
return;
}
if (slotNo == 1U) {
char text[40U];
::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 {
char text[40U];
::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) void CNextion::writeDMRBERInt(unsigned int slotNo, float ber)
{ {
if (slotNo == 1U) { if (slotNo == 1U) {
@ -353,11 +438,23 @@ void CNextion::clearDMRInt(unsigned int slotNo)
{ {
if (slotNo == 1U) { if (slotNo == 1U) {
sendCommand("t0.txt=\"1 Listening\""); sendCommand("t0.txt=\"1 Listening\"");
if (m_screenLayout == 2U) {
sendCommand("t0.pco=0");
sendCommand("t0.font=4");
}
sendCommand("t1.txt=\"\""); sendCommand("t1.txt=\"\"");
sendCommand("t4.txt=\"\""); sendCommand("t4.txt=\"\"");
sendCommand("t6.txt=\"\""); sendCommand("t6.txt=\"\"");
} else { } else {
sendCommand("t2.txt=\"2 Listening\""); sendCommand("t2.txt=\"2 Listening\"");
if (m_screenLayout == 2U) {
sendCommand("t2.pco=0");
sendCommand("t2.font=4");
}
sendCommand("t3.txt=\"\""); sendCommand("t3.txt=\"\"");
sendCommand("t5.txt=\"\""); sendCommand("t5.txt=\"\"");
sendCommand("t7.txt=\"\""); sendCommand("t7.txt=\"\"");
@ -568,6 +665,8 @@ void CNextion::clockInt(unsigned int ms)
void CNextion::close() void CNextion::close()
{ {
sendCommand("page MMDVM");
sendCommand("t1.txt=\"MMDVM STOPPED\"");
m_serial->close(); m_serial->close();
delete m_serial; delete m_serial;
} }

View file

@ -29,7 +29,7 @@
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); 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 ~CNextion();
virtual bool open(); 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 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 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 writeDMRBERInt(unsigned int slotNo, float ber);
virtual void clearDMRInt(unsigned int slotNo); virtual void clearDMRInt(unsigned int slotNo);
@ -68,6 +69,7 @@ protected:
private: private:
std::string m_callsign; std::string m_callsign;
std::string m_ipaddress;
unsigned int m_dmrid; unsigned int m_dmrid;
ISerialPort* m_serial; ISerialPort* m_serial;
unsigned int m_brightness; unsigned int m_brightness;
@ -75,6 +77,7 @@ private:
bool m_displayClock; bool m_displayClock;
bool m_utc; bool m_utc;
unsigned int m_idleBrightness; unsigned int m_idleBrightness;
unsigned int m_screenLayout;
CTimer m_clockDisplayTimer; CTimer m_clockDisplayTimer;
unsigned int m_rssiAccum1; unsigned int m_rssiAccum1;
unsigned int m_rssiAccum2; 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.

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.

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.

29
Nextion_ON7LDS/README Normal file
View file

@ -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

314
OLED.cpp
View file

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2016 by Jonathan Naylor G4KLX * Copyright (C) 2016,2017 by Jonathan Naylor G4KLX
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -18,68 +18,96 @@
#include "OLED.h" #include "OLED.h"
//Logo MMDVM for Idle Screen
static unsigned char logo_glcd_bmp[] = static unsigned char logo_glcd_bmp[] =
{ 0b00101011, 0b11010100, {
0b01010111, 0b11101010, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0b01010111, 0b11101010, 0x01, 0xF8, 0x03, 0xFC, 0x7F, 0x80, 0x3F, 0xC7, 0xFF, 0xFC, 0xF8, 0x00, 0xF9, 0xFC, 0x01, 0xFE,
0b00101011, 0b11010100, 0x01, 0xFC, 0x07, 0xFC, 0x7F, 0xC0, 0x7F, 0xC4, 0x00, 0x02, 0x48, 0x00, 0x91, 0xFE, 0x03, 0xFE,
0b00000001, 0b10000000, 0x03, 0xFC, 0x07, 0xFC, 0x7F, 0xC0, 0x7F, 0xC5, 0xFF, 0xF1, 0x24, 0x01, 0x23, 0xFE, 0x03, 0xFE,
0b00000001, 0b10000000, 0x03, 0xFE, 0x0F, 0xBC, 0x7B, 0xE0, 0xFB, 0xC5, 0x00, 0x09, 0x24, 0x01, 0x23, 0xDF, 0x07, 0xDE,
0b00000001, 0b10000000, 0x07, 0xDE, 0x0F, 0x3C, 0x79, 0xE0, 0xF3, 0xC5, 0x00, 0x05, 0x12, 0x02, 0x47, 0xCF, 0x07, 0x9E,
0b00000001, 0b10000000, 0x07, 0x9F, 0x1F, 0x3C, 0x79, 0xF1, 0xF3, 0xC5, 0x00, 0x05, 0x12, 0x02, 0x47, 0x8F, 0x8F, 0x9E,
0b00000001, 0b10000000, 0x0F, 0x8F, 0x1E, 0x3C, 0x78, 0xF1, 0xE3, 0xC5, 0x00, 0x05, 0x09, 0x04, 0x8F, 0x87, 0x8F, 0x1E,
0b00000001, 0b10000000, 0x0F, 0x0F, 0xBE, 0x3C, 0x78, 0xFB, 0xE3, 0xC5, 0x00, 0x05, 0x09, 0x04, 0x8F, 0x07, 0xDF, 0x1E,
0b00000001, 0b10000000, 0x1F, 0x07, 0xFC, 0x3C, 0x78, 0x7F, 0xC3, 0xC5, 0x00, 0x05, 0x04, 0x89, 0x1F, 0x03, 0xFE, 0x1E,
0b00000001, 0b10000000, 0x1E, 0x03, 0xFC, 0x3C, 0x78, 0x7F, 0xC3, 0xC5, 0x00, 0x09, 0x04, 0x89, 0x1E, 0x01, 0xFE, 0x1E,
0b00000001, 0b10000000, 0x3E, 0x03, 0xF8, 0x3C, 0x78, 0x3F, 0x83, 0xC5, 0xFF, 0xF1, 0x02, 0x72, 0x3E, 0x01, 0xFC, 0x1E,
0b00000001, 0b10000000, 0x3C, 0x01, 0xF0, 0x3C, 0x78, 0x1F, 0x03, 0xC4, 0x00, 0x02, 0x02, 0x02, 0x3C, 0x00, 0xF8, 0x1E,
0b00000001, 0b10000000, 0x7C, 0x01, 0xF0, 0x3C, 0x78, 0x1F, 0x03, 0xC7, 0xFF, 0xFC, 0x01, 0xFC, 0x7C, 0x00, 0xF8, 0x1E,
0b00000000, 0b00000000 }; 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
//DMR 48x16 px //Logo D-Star 128x16 px
static unsigned char logo_dmr_bmp[] =
{ 0b11111111, 0b11111111, 0b11111111, 0b11111111, 0b11111111, 0b11111111,
0b10000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000001,
0b10111111, 0b11111000, 0b01111000, 0b00011110, 0b01111111, 0b11100001,
0b10111111, 0b11111110, 0b01111100, 0b00111110, 0b01100000, 0b00011001,
0b10110000, 0b00001110, 0b01100110, 0b01100110, 0b01100000, 0b00011001,
0b10110000, 0b00000110, 0b01100011, 0b11000110, 0b01100000, 0b00011001,
0b10110000, 0b00000110, 0b01100001, 0b10000110, 0b01100000, 0b00011001,
0b10110000, 0b00000110, 0b01100000, 0b00000110, 0b01111111, 0b11111001,
0b10110000, 0b00000110, 0b01100000, 0b00000110, 0b01111000, 0b00000001,
0b10110000, 0b00000110, 0b01100000, 0b00000110, 0b01101100, 0b00000001,
0b10110000, 0b00000110, 0b01100000, 0b00000110, 0b01100110, 0b00000001,
0b10110000, 0b00001110, 0b01100000, 0b00000110, 0b01100011, 0b00000001,
0b10111111, 0b11111110, 0b01100000, 0b00000110, 0b01100001, 0b10000001,
0b10011111, 0b11111000, 0b01100000, 0b00000110, 0b01100000, 0b11000001,
0b10000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000001,
0b11111111, 0b11111111, 0b11111111, 0b11111111, 0b11111111, 0b11111111
};
//D-Star 64x16 px
static unsigned char logo_dstar_bmp[] = static unsigned char logo_dstar_bmp[] =
{ 0b11111111, 0b11111111, 0b11111111, 0b11111111, 0b11111111, 0b11111111, 0b11111111, 0b11111111, {
0b10000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000001, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0b10000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000001, 0x00, 0x00, 0x60, 0x03, 0xFF, 0xC0, 0x00, 0x00, 0x1F, 0xF0, 0xFF, 0xFE, 0x07, 0x80, 0x3F, 0xF8,
0b10000001, 0b11111100, 0b00000000, 0b00111100, 0b00000000, 0b00000000, 0b00000000, 0b01000001, 0x00, 0x00, 0xC0, 0x07, 0xC1, 0xE0, 0x00, 0x00, 0x78, 0x7C, 0xFF, 0xFE, 0x0F, 0xC0, 0x3F, 0xFC,
0b10000001, 0b00000010, 0b00000000, 0b01000010, 0b01000000, 0b00000000, 0b00000000, 0b01000001, 0x00, 0x01, 0xC0, 0x07, 0x80, 0xF0, 0x00, 0x00, 0xE0, 0x3C, 0x07, 0x80, 0x0F, 0xC0, 0x78, 0x0E,
0b10000001, 0b00000010, 0b00000000, 0b01000000, 0b01000000, 0b00000000, 0b00000000, 0b01000001, 0x00, 0x03, 0xC0, 0x07, 0x80, 0x70, 0x00, 0x00, 0xE0, 0x38, 0x07, 0x00, 0x1B, 0xC0, 0x78, 0x0E,
0b10000001, 0b00000010, 0b00000000, 0b01000000, 0b01000000, 0b00000000, 0b00000000, 0b01000001, 0x00, 0x07, 0xC0, 0x07, 0x80, 0x70, 0x00, 0x01, 0xE0, 0x00, 0x07, 0x00, 0x33, 0xC0, 0x70, 0x1E,
0b10000001, 0b00000010, 0b01111111, 0b00111100, 0b01111000, 0b00111100, 0b00111100, 0b01000001, 0x07, 0xFF, 0xFE, 0x07, 0x00, 0x70, 0x00, 0x01, 0xF8, 0x00, 0x07, 0x00, 0x63, 0xC0, 0x70, 0x3C,
0b10000001, 0b00000010, 0b00000000, 0b00000010, 0b01000000, 0b00000010, 0b01000010, 0b01000001, 0x01, 0xFF, 0xF8, 0x0F, 0x00, 0x71, 0xFF, 0xE0, 0xFF, 0xF0, 0x0E, 0x00, 0xE1, 0xE0, 0xFF, 0xE0,
0b10000001, 0b00000010, 0b00000000, 0b00000010, 0b01000000, 0b00111110, 0b01000000, 0b01000001, 0x00, 0x7F, 0xE0, 0x0F, 0x00, 0x60, 0x00, 0x00, 0x03, 0xF8, 0x0E, 0x00, 0xC1, 0xE0, 0xFF, 0xE0,
0b10000001, 0b00000010, 0b00000000, 0b00000010, 0b01000000, 0b01000010, 0b01000000, 0b00000001, 0x00, 0x3F, 0x80, 0x0E, 0x00, 0xE0, 0x00, 0x00, 0x00, 0xF0, 0x0E, 0x01, 0xFF, 0xE0, 0xE0, 0x70,
0b10000001, 0b00000010, 0b00000000, 0b01000010, 0b01000010, 0b01000010, 0b01000000, 0b01000001, 0x00, 0x7F, 0x00, 0x1E, 0x00, 0xE0, 0x00, 0x03, 0x80, 0x70, 0x0C, 0x03, 0xFC, 0xE0, 0xE0, 0x30,
0b10000001, 0b11111100, 0b00000000, 0b00111100, 0b00111100, 0b00111100, 0b01000000, 0b01000001, 0x00, 0xFF, 0x00, 0x1E, 0x01, 0xC0, 0x00, 0x07, 0x80, 0xE0, 0x1C, 0x07, 0x00, 0xE1, 0xE0, 0x38,
0b10000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000001, 0x01, 0xEF, 0x00, 0x1C, 0x07, 0x80, 0x00, 0x07, 0xC1, 0xE0, 0x1C, 0x06, 0x00, 0xF1, 0xC0, 0x38,
0b10000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000000, 0b00000001, 0x03, 0x87, 0x00, 0x3F, 0xFF, 0x00, 0x00, 0x03, 0xFF, 0x80, 0x1C, 0x0C, 0x00, 0xF3, 0xC0, 0x38,
0b11111111, 0b11111111, 0b11111111, 0b11111111, 0b11111111, 0b11111111, 0b11111111, 0b11111111 0x06, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x3C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
}; 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
COLED::COLED(unsigned char displayType, unsigned char displayBrightness, bool displayInvert) : //Logo DMR 128x16 px
static unsigned char logo_dmr_bmp[] =
{
0x00, 0x01, 0xFF, 0xFF, 0xF8, 0x01, 0xF8, 0x00, 0x00, 0x1F, 0x1F, 0xFF, 0xFF, 0xFC, 0x00, 0x00,
0x00, 0x01, 0xFF, 0xFF, 0xFF, 0x81, 0xFC, 0x00, 0x00, 0x3F, 0x1F, 0xFF, 0xFF, 0xFF, 0x00, 0x00,
0x00, 0x01, 0xFF, 0xFF, 0xFF, 0xE1, 0xFE, 0x00, 0x00, 0xFF, 0x1F, 0xFF, 0xFF, 0xFF, 0x00, 0x00,
0x00, 0x01, 0xF8, 0x00, 0x0F, 0xF1, 0xFF, 0x80, 0x01, 0xFF, 0x1F, 0x80, 0x00, 0x1F, 0x00, 0x00,
0x00, 0x01, 0xF8, 0x00, 0x03, 0xF9, 0xFF, 0xC0, 0x03, 0xFF, 0x1F, 0x80, 0x00, 0x0F, 0x00, 0x00,
0x00, 0x01, 0xF8, 0x00, 0x01, 0xF9, 0xFF, 0xE0, 0x07, 0xFF, 0x1F, 0x80, 0x00, 0x0F, 0x00, 0x00,
0x00, 0x01, 0xF8, 0x00, 0x01, 0xFD, 0xF3, 0xF0, 0x1F, 0x9F, 0x1F, 0x80, 0x00, 0x1F, 0x00, 0x00,
0x00, 0x01, 0xF8, 0x00, 0x00, 0xFD, 0xF1, 0xFC, 0x3F, 0x1F, 0x1F, 0xFF, 0xFF, 0xFF, 0x00, 0x00,
0x00, 0x01, 0xF8, 0x00, 0x00, 0xFD, 0xF0, 0xFE, 0x7E, 0x1F, 0x1F, 0xFF, 0xFF, 0xFF, 0x00, 0x00,
0x00, 0x01, 0xF8, 0x00, 0x01, 0xFD, 0xF0, 0x7F, 0xFC, 0x1F, 0x1F, 0xFF, 0xFF, 0xFC, 0x00, 0x00,
0x00, 0x01, 0xF8, 0x00, 0x01, 0xF9, 0xF0, 0x1F, 0xF0, 0x1F, 0x1F, 0x81, 0xFC, 0x00, 0x00, 0x00,
0x00, 0x01, 0xF8, 0x00, 0x07, 0xF9, 0xF0, 0x0F, 0xE0, 0x1F, 0x1F, 0x80, 0x7F, 0x00, 0x00, 0x00,
0x00, 0x01, 0xF8, 0x00, 0x3F, 0xF1, 0xF0, 0x07, 0xC0, 0x1F, 0x1F, 0x80, 0x3F, 0xC0, 0x00, 0x00,
0x00, 0x01, 0xFF, 0xFF, 0xFF, 0xC1, 0xF0, 0x03, 0x80, 0x1F, 0x1F, 0x80, 0x0F, 0xF0, 0x00, 0x00,
0x00, 0x01, 0xFF, 0xFF, 0xFF, 0x01, 0xF0, 0x00, 0x00, 0x1F, 0x1F, 0x80, 0x03, 0xFC, 0x00, 0x00,
0x00, 0x01, 0xFF, 0xFF, 0xF0, 0x01, 0xF0, 0x00, 0x00, 0x1F, 0x1F, 0x80, 0x01, 0xFF, 0x00, 0x00
};
//Logo Fusion 128x16
const unsigned char logo_fusion_bmp [] =
{
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xF8, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0xFF, 0xFF, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0xFF, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0xE0, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x01, 0xFE, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x03, 0xFC, 0x00, 0x1F, 0xE1, 0xFE, 0x1F, 0xFF, 0xF8, 0x7F, 0xC3, 0xFF, 0xFF, 0x1F, 0xFF, 0xFE,
0x03, 0xFC, 0x00, 0x3F, 0xC3, 0xFC, 0x3F, 0x80, 0x00, 0x7F, 0x87, 0xF0, 0xFF, 0x0F, 0xF1, 0xFF,
0x07, 0xFF, 0xFC, 0x7F, 0x83, 0xF8, 0x7F, 0x80, 0x00, 0xFF, 0x0F, 0xF0, 0xFF, 0x1F, 0xE1, 0xFE,
0x0F, 0xFF, 0xF0, 0x7F, 0x07, 0xF0, 0xFF, 0xFF, 0xC1, 0xFF, 0x1F, 0xE1, 0xFE, 0x3F, 0xC3, 0xFC,
0x0F, 0xF0, 0x00, 0xFE, 0x0F, 0xE0, 0x7F, 0xFF, 0xE1, 0xFE, 0x3F, 0xC3, 0xFC, 0x3F, 0xC3, 0xFC,
0x1F, 0xE0, 0x01, 0xFC, 0x1F, 0xE0, 0x1F, 0xFF, 0xE3, 0xFC, 0x3F, 0xC3, 0xF8, 0x7F, 0x87, 0xF8,
0x3F, 0xC0, 0x03, 0xFC, 0x3F, 0xC0, 0x00, 0x3F, 0xC7, 0xF8, 0x7F, 0x87, 0xF8, 0xFF, 0x0F, 0xF0,
0x7F, 0xC0, 0x03, 0xFF, 0xFF, 0xE0, 0x00, 0x7F, 0x07, 0xF8, 0x7F, 0xCF, 0xE1, 0xFF, 0x1F, 0xF8,
0x7F, 0x80, 0x01, 0xFF, 0xFF, 0xC7, 0xFF, 0xFC, 0x0F, 0xF0, 0x3F, 0xFF, 0x81, 0xFE, 0x1F, 0xF0,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
COLED::COLED(unsigned char displayType, unsigned char displayBrightness, bool displayInvert, bool displayScroll) :
m_displayType(displayType), m_displayType(displayType),
m_displayBrightness(displayBrightness), m_displayBrightness(displayBrightness),
m_displayInvert(displayInvert) m_displayInvert(displayInvert),
m_displayScroll(displayScroll)
{ {
} }
@ -127,12 +155,14 @@ void COLED::setIdleInt()
display.clearDisplay(); display.clearDisplay();
OLED_statusbar(); OLED_statusbar();
display.setCursor(0,display.height()/2);
display.setTextSize(2); // display.setCursor(0,30);
display.print("Idle"); // display.setTextSize(3);
display.setTextSize(1); // display.print("Idle");
// display.setTextSize(1);
display.startscrolldiagright(0x00,0x0f); //the MMDVM logo scrolls the whole screen
display.display(); display.display();
display.startscrollright(0x02,0x0f);
} }
void COLED::setErrorInt(const char* text) void COLED::setErrorInt(const char* text)
@ -141,8 +171,10 @@ void COLED::setErrorInt(const char* text)
display.clearDisplay(); display.clearDisplay();
OLED_statusbar(); OLED_statusbar();
display.setCursor(0,OLED_LINE1); display.setCursor(0,OLED_LINE1);
display.printf("%s\n", text); display.printf("%s\n",text);
display.display(); display.display();
} }
@ -152,151 +184,171 @@ void COLED::setLockoutInt()
display.clearDisplay(); display.clearDisplay();
OLED_statusbar(); OLED_statusbar();
display.setCursor(0,OLED_LINE1);
display.setCursor(0,30);
display.setTextSize(3);
display.print("Lockout"); display.print("Lockout");
display.setTextSize(1);
display.display(); display.display();
} }
void COLED::writeDStarInt(const char* my1, const char* my2, const char* your, const char* type, const char* reflector) void COLED::writeDStarInt(const char* my1, const char* my2, const char* your, const char* type, const char* reflector)
{ {
m_mode = MODE_DSTAR; m_mode = MODE_DSTAR;
display.fillRect(0, OLED_LINE1, display.width(), 10, BLACK);
display.setCursor(0,OLED_LINE1); display.clearDisplay();
display.printf("%s %.8s/%4.4s", type, my1, my2); display.fillRect(0,OLED_LINE1,display.width(),display.height(),BLACK); //clear everything beneath logo
display.fillRect(0, OLED_LINE2, display.width(), 10, BLACK);
display.setCursor(0,OLED_LINE2); display.setCursor(0,OLED_LINE2);
display.printf("via %.8s", reflector); display.printf("%s %.8s/%4.4s",type,my1,my2);
display.fillRect(0, OLED_LINE3, display.width(), 10, BLACK);
display.setCursor(0,OLED_LINE3); display.setCursor(0,OLED_LINE3);
display.printf("%.8s <- %-8s", your, reflector); display.printf("-> %.8s",your);
display.setCursor(0,OLED_LINE5);
display.printf("via %.8s",reflector);
OLED_statusbar(); OLED_statusbar();
display.display(); display.display();
} }
void COLED::clearDStarInt() void COLED::clearDStarInt()
{ {
display.fillRect(0, OLED_LINE1, display.width(), 10, BLACK); display.fillRect(0,OLED_LINE1, display.width(),display.height(),BLACK); //clear everything beneath the logo
display.setCursor(0,OLED_LINE1);
display.setCursor(40,38);
display.print("Listening"); display.print("Listening");
display.fillRect(0, OLED_LINE2, display.width(), 10, BLACK);
display.fillRect(0, OLED_LINE3, display.width(), 10, BLACK);
OLED_statusbar();
display.display(); display.display();
} }
void COLED::writeDMRInt(unsigned int slotNo, const std::string& src, bool group, const std::string& dst, const char* type) void COLED::writeDMRInt(unsigned int slotNo,const std::string& src,bool group,const std::string& dst,const char* type)
{ {
if (m_mode != MODE_DMR) { if (m_mode != MODE_DMR) {
display.clearDisplay(); display.clearDisplay();
m_mode = MODE_DMR; m_mode = MODE_DMR;
if (slotNo == 1U) if (slotNo == 1U)
{ {
display.fillRect(0, OLED_LINE3, display.width(), 10, BLACK); display.fillRect(0,OLED_LINE4,display.width(),20,BLACK); //20=> clear 2 lines
display.setCursor(0,OLED_LINE3); display.setCursor(0,OLED_LINE4);
display.print("2 Listening"); display.print("2 Listening");
display.fillRect(0, OLED_LINE4, display.width(), 10, BLACK);
} }
else else
{ {
display.fillRect(0, OLED_LINE1, display.width(), 10, BLACK); display.fillRect(0,OLED_LINE2,display.width(),20,BLACK); //20=> clear 2 lines
display.setCursor(0,OLED_LINE1); display.setCursor(0,OLED_LINE2);
display.print("1 Listening"); display.print("1 Listening");
display.fillRect(0, OLED_LINE2, display.width(), 10, BLACK);
} }
} }
if (slotNo == 1U) { if (slotNo == 1U)
display.fillRect(0, OLED_LINE1, display.width(), 10, BLACK); {
display.setCursor(0,OLED_LINE1); display.fillRect(0,OLED_LINE2,display.width(),20,BLACK);
display.printf("%i %s %s", slotNo, type, src.c_str());
display.fillRect(0, OLED_LINE2, display.width(), 10, BLACK);
display.setCursor(0,OLED_LINE2); display.setCursor(0,OLED_LINE2);
display.printf("%s%s", group ? "TG" : "", dst.c_str()); display.printf("%i %s %s",slotNo,type,src.c_str());
} else {
display.fillRect(0, OLED_LINE3, display.width(), 10, BLACK);
display.setCursor(0,OLED_LINE3); display.setCursor(0,OLED_LINE3);
display.printf("%i %s %s", slotNo, type, src.c_str()); display.printf("%s%s",group ? "TG" : "",dst.c_str());
display.fillRect(0, OLED_LINE4, display.width(), 10, BLACK); }
else
{
display.fillRect(0,OLED_LINE4,display.width(),20,BLACK);
display.setCursor(0,OLED_LINE4); 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()); display.printf("%s%s", group ? "TG" : "", dst.c_str());
} }
OLED_statusbar(); OLED_statusbar();
display.display(); display.display();
} }
void COLED::clearDMRInt(unsigned int slotNo) void COLED::clearDMRInt(unsigned int slotNo)
{ {
OLED_statusbar();
if (slotNo == 1U) if (slotNo == 1U)
{ {
display.fillRect(0, OLED_LINE1, display.width(), 10, BLACK); display.fillRect(0, OLED_LINE2, display.width(), 20, BLACK);
display.setCursor(0,OLED_LINE1); display.setCursor(0,OLED_LINE2);
display.print("1 Listening"); display.print("1 Listening");
display.fillRect(0, OLED_LINE2, display.width(), 10, BLACK);
} }
else else
{ {
display.fillRect(0, OLED_LINE3, display.width(), 10, BLACK); display.fillRect(0, OLED_LINE4, display.width(), 20, BLACK);
display.setCursor(0,OLED_LINE3); display.setCursor(0, OLED_LINE4);
display.print("2 Listening"); display.print("2 Listening");
display.fillRect(0, OLED_LINE4, display.width(), 10, BLACK);
} }
display.display(); display.display();
} }
void COLED::writeFusionInt(const char* source, const char* dest, const char* type, const char* origin) void COLED::writeFusionInt(const char* source, const char* dest, const char* type, const char* origin)
{ {
m_mode = MODE_YSF; m_mode = MODE_YSF;
display.fillRect(0, OLED_LINE1, display.width(), 10, BLACK);
display.setCursor(0,OLED_LINE1); display.clearDisplay();
display.printf("%s %.10s", type, source); display.fillRect(0,OLED_LINE1,display.width(),display.height(),BLACK);
display.fillRect(0, OLED_LINE2, display.width(), 10, BLACK);
display.setCursor(0,OLED_LINE2); display.setCursor(0,OLED_LINE2);
display.printf("%s %.10s", type, source);
display.setCursor(0,OLED_LINE3);
display.printf(" %.10s", dest); display.printf(" %.10s", dest);
OLED_statusbar(); OLED_statusbar();
display.display(); display.display();
} }
void COLED::clearFusionInt() void COLED::clearFusionInt()
{ {
display.fillRect(0, OLED_LINE1, display.width(), 10, BLACK); display.fillRect(0, OLED_LINE1, display.width(), display.height(), BLACK);
display.setCursor(0,OLED_LINE1);
display.setCursor(40,38);
display.print("Listening"); display.print("Listening");
display.fillRect(0, OLED_LINE2, display.width(), 10, BLACK);
OLED_statusbar();
display.display(); display.display();
} }
void COLED::writeP25Int(const char* source, bool group, unsigned int dest, const char* type) void COLED::writeP25Int(const char* source, bool group, unsigned int dest, const char* type)
{ {
m_mode = MODE_P25; m_mode = MODE_P25;
display.fillRect(0, OLED_LINE1, display.width(), 10, BLACK);
display.setCursor(0,OLED_LINE1); display.clearDisplay();
display.printf("%s %.10s", type, source); display.fillRect(0, OLED_LINE1, display.width(), display.height(), BLACK);
display.fillRect(0, OLED_LINE2, display.width(), 10, BLACK);
display.setCursor(0,OLED_LINE2); display.setCursor(0,OLED_LINE2);
display.printf("%s %.10s", type, source);
display.setCursor(0,OLED_LINE3);
display.printf(" %s%u", group ? "TG" : "", dest); display.printf(" %s%u", group ? "TG" : "", dest);
OLED_statusbar(); OLED_statusbar();
display.display(); display.display();
} }
void COLED::clearP25Int() void COLED::clearP25Int()
{ {
display.fillRect(0, OLED_LINE1, display.width(), 10, BLACK); display.fillRect(0, OLED_LINE1, display.width(), display.height(), BLACK);
display.setCursor(0,OLED_LINE1);
display.setCursor(40,38);
display.print("Listening"); display.print("Listening");
display.fillRect(0, OLED_LINE2, display.width(), 10, BLACK);
OLED_statusbar();
display.display(); display.display();
} }
void COLED::writeCWInt() void COLED::writeCWInt()
{ {
display.clearDisplay(); display.clearDisplay();
display.setCursor(0,display.height()/2);
display.setCursor(0,30);
display.setTextSize(3); display.setTextSize(3);
display.print("CW TX"); display.print("CW TX");
display.setTextSize(1); display.setTextSize(1);
display.display(); display.display();
display.startscrollright(0x02,0x0f); display.startscrollright(0x02,0x0f);
@ -305,16 +357,26 @@ void COLED::writeCWInt()
void COLED::clearCWInt() void COLED::clearCWInt()
{ {
display.clearDisplay(); display.clearDisplay();
display.setCursor(0,display.height()/2);
display.setTextSize(2); display.setCursor(0,30);
display.setTextSize(3);
display.print("Idle"); display.print("Idle");
display.setTextSize(1); display.setTextSize(1);
display.display(); display.display();
display.startscrollright(0x02,0x0f); display.startscrollleft(0x02,0x0f);
} }
void COLED::close() void COLED::close()
{ {
display.clearDisplay();
display.fillRect(0, 0, display.width(), 16, BLACK);
display.startscrollright(0x00,0x01);
display.setCursor(0,00);
display.setTextSize(2);
display.print("-CLOSE-");
display.display();
display.close(); display.close();
} }
@ -323,15 +385,19 @@ void COLED::OLED_statusbar()
display.stopscroll(); display.stopscroll();
display.fillRect(0, 0, display.width(), 16, BLACK); display.fillRect(0, 0, display.width(), 16, BLACK);
display.setTextColor(WHITE); display.setTextColor(WHITE);
display.setCursor(0,0); display.setCursor(0,0);
if (m_mode == MODE_DMR) if (m_mode == MODE_DMR)
display.drawBitmap(0, 0, logo_dmr_bmp, 48, 16, WHITE); display.drawBitmap(0, 0, logo_dmr_bmp, 128, 16, WHITE);
else if (m_mode == MODE_DSTAR) else if (m_mode == MODE_DSTAR)
display.drawBitmap(0, 0, logo_dstar_bmp, 64, 16, WHITE); display.drawBitmap(0, 0, logo_dstar_bmp, 128, 16, WHITE);
else if (m_mode == MODE_YSF) else if (m_mode == MODE_YSF)
display.print("Fusion"); display.drawBitmap(0, 0, logo_fusion_bmp, 128, 16, WHITE);
else if (m_mode == MODE_P25) else if (m_mode == MODE_P25)
display.print("P25"); display.print("P25");
else else
display.drawBitmap(0, 0, logo_glcd_bmp, 16, 15, WHITE); display.drawBitmap(0, 0, logo_glcd_bmp, 128, 16, WHITE);
if (m_displayScroll)
display.startscrollright(0x00,0x02);
} }

6
OLED.h
View file

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2016 by Jonathan Naylor G4KLX * Copyright (C) 2016,2017 by Jonathan Naylor G4KLX
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -24,6 +24,7 @@
#define OLED_LINE2 26 #define OLED_LINE2 26
#define OLED_LINE3 36 #define OLED_LINE3 36
#define OLED_LINE4 46 #define OLED_LINE4 46
#define OLED_LINE5 56
#include "Display.h" #include "Display.h"
#include "Defines.h" #include "Defines.h"
@ -37,7 +38,7 @@
class COLED : public CDisplay class COLED : public CDisplay
{ {
public: public:
COLED(unsigned char displayType, unsigned char displayBrighness, bool displayInvert); COLED(unsigned char displayType, unsigned char displayBrighness, bool displayInvert, bool displayScroll);
virtual ~COLED(); virtual ~COLED();
virtual bool open(); virtual bool open();
@ -71,6 +72,7 @@ private:
unsigned char m_displayType; unsigned char m_displayType;
unsigned char m_displayBrightness; unsigned char m_displayBrightness;
bool m_displayInvert; bool m_displayInvert;
bool m_displayScroll;
ArduiPi_OLED display; ArduiPi_OLED display;
void OLED_statusbar(); void OLED_statusbar();

View file

@ -35,9 +35,12 @@ const unsigned char BIT_MASK_TABLE[] = {0x80U, 0x40U, 0x20U, 0x10U, 0x08U, 0x04U
#define WRITE_BIT(p,i,b) p[(i)>>3] = (b) ? (p[(i)>>3] | BIT_MASK_TABLE[(i)&7]) : (p[(i)>>3] & ~BIT_MASK_TABLE[(i)&7]) #define WRITE_BIT(p,i,b) p[(i)>>3] = (b) ? (p[(i)>>3] | BIT_MASK_TABLE[(i)&7]) : (p[(i)>>3] & ~BIT_MASK_TABLE[(i)&7])
#define READ_BIT(p,i) (p[(i)>>3] & BIT_MASK_TABLE[(i)&7]) #define READ_BIT(p,i) (p[(i)>>3] & BIT_MASK_TABLE[(i)&7])
CP25Control::CP25Control(unsigned int nac, bool uidOverride, CP25Network* network, CDisplay* display, unsigned int timeout, bool duplex, CDMRLookup* lookup, CRSSIInterpolator* rssiMapper) : CP25Control::CP25Control(unsigned int nac, unsigned int id, bool selfOnly, bool uidOverride, CP25Network* network, CDisplay* display, unsigned int timeout, bool duplex, CDMRLookup* lookup, bool remoteGateway, CRSSIInterpolator* rssiMapper) :
m_nac(nac), m_nac(nac),
m_id(id),
m_selfOnly(selfOnly),
m_uidOverride(uidOverride), m_uidOverride(uidOverride),
m_remoteGateway(remoteGateway),
m_network(network), m_network(network),
m_display(display), m_display(display),
m_duplex(duplex), m_duplex(duplex),
@ -101,14 +104,9 @@ bool CP25Control::writeModem(unsigned char* data, unsigned int len)
{ {
assert(data != NULL); assert(data != NULL);
// CUtils::dump(1U, "P25 Data", data, len);
bool sync = data[1U] == 0x01U; bool sync = data[1U] == 0x01U;
if (data[0U] == TAG_LOST && m_rfState == RS_RF_LISTENING) if (data[0U] == TAG_LOST && m_rfState == RS_RF_AUDIO) {
return false;
if (data[0U] == TAG_LOST) {
if (m_rssi != 0U) if (m_rssi != 0U)
LogMessage("P25, transmission lost, %.1f seconds, BER: %.1f%%, RSSI: -%u/-%u/-%u dBm", float(m_rfFrames) / 5.56F, float(m_rfErrs * 100U) / float(m_rfBits), m_minRSSI, m_maxRSSI, m_aveRSSI / m_rssiCount); LogMessage("P25, transmission lost, %.1f seconds, BER: %.1f%%, RSSI: -%u/-%u/-%u dBm", float(m_rfFrames) / 5.56F, float(m_rfErrs * 100U) / float(m_rfBits), m_minRSSI, m_maxRSSI, m_aveRSSI / m_rssiCount);
else else
@ -128,6 +126,11 @@ bool CP25Control::writeModem(unsigned char* data, unsigned int len)
return false; return false;
} }
if (data[0U] == TAG_LOST) {
m_rfState = RS_RF_LISTENING;
return false;
}
if (!sync && m_rfState == RS_RF_LISTENING) if (!sync && m_rfState == RS_RF_LISTENING)
return false; return false;
@ -177,12 +180,45 @@ bool CP25Control::writeModem(unsigned char* data, unsigned int len)
if (duid == P25_DUID_LDU1) { if (duid == P25_DUID_LDU1) {
if (m_rfState == RS_RF_LISTENING) { if (m_rfState == RS_RF_LISTENING) {
m_rfData.reset(); m_rfData.reset();
bool ret = m_rfData.decodeLDU1(data + 2U, m_network != NULL, m_uidOverride); bool ret = m_rfData.decodeLDU1(data + 2U);
if (!ret) { if (!ret) {
m_lastDUID = duid; m_lastDUID = duid;
return false; return false;
} }
unsigned int srcId = m_rfData.getSrcId();
if (m_selfOnly) {
if (m_id > 99999999U) { // Check that the Config DMR-ID is bigger than 8 digits
if (srcId != m_id / 100U)
return false;
}
else if (m_id > 9999999U) { // Check that the Config DMR-ID is bigger than 7 digits
if (srcId != m_id / 10U)
return false;
}
else if (srcId != m_id) { // All other cases
return false;
}
}
if (!m_uidOverride) {
bool found = m_lookup->exists(srcId);
if (!found)
return false;
}
bool grp = m_rfData.getLCF() == P25_LCF_GROUP;
unsigned int dstId = m_rfData.getDstId();
std::string source = m_lookup->find(srcId);
LogMessage("P25, received RF transmission from %s to %s%u", source.c_str(), grp ? "TG " : "", dstId);
m_display->writeP25(source.c_str(), grp, dstId, "R");
m_rfState = RS_RF_AUDIO;
m_minRSSI = m_rssi; m_minRSSI = m_rssi;
m_maxRSSI = m_rssi; m_maxRSSI = m_rssi;
m_aveRSSI = m_rssi; m_aveRSSI = m_rssi;
@ -190,10 +226,11 @@ bool CP25Control::writeModem(unsigned char* data, unsigned int len)
createRFHeader(); createRFHeader();
writeNetwork(data + 2U, P25_DUID_HEADER, false); writeNetwork(data + 2U, P25_DUID_HEADER, false);
} else { } else if (m_rfState == RS_RF_AUDIO) {
writeNetwork(m_rfLDU, m_lastDUID, false); writeNetwork(m_rfLDU, m_lastDUID, false);
} }
if (m_rfState == RS_RF_AUDIO) {
// Regenerate Sync // Regenerate Sync
CSync::addP25Sync(data + 2U); CSync::addP25Sync(data + 2U);
@ -232,21 +269,12 @@ bool CP25Control::writeModem(unsigned char* data, unsigned int len)
writeQueueRF(data, P25_LDU_FRAME_LENGTH_BYTES + 2U); writeQueueRF(data, P25_LDU_FRAME_LENGTH_BYTES + 2U);
} }
if (m_rfState == RS_RF_LISTENING) {
unsigned int srcId = m_rfData.getSrcId();
bool grp = m_rfData.getLCF() == P25_LCF_GROUP;
unsigned int dstId = m_rfData.getDstId();
std::string source = m_lookup->find(srcId);
LogMessage("P25, received RF transmission from %s to %s%u", source.c_str(), grp ? "TG " : "", dstId);
m_display->writeP25(source.c_str(), grp, dstId, "R");
m_rfState = RS_RF_AUDIO;
}
m_display->writeP25RSSI(m_rssi); m_display->writeP25RSSI(m_rssi);
} else if (duid == P25_DUID_LDU2) {
if (m_rfState == RS_RF_LISTENING)
return false;
return true;
}
} else if (duid == P25_DUID_LDU2) {
if (m_rfState == RS_RF_AUDIO) {
writeNetwork(m_rfLDU, m_lastDUID, false); writeNetwork(m_rfLDU, m_lastDUID, false);
// Regenerate Sync // Regenerate Sync
@ -288,10 +316,11 @@ bool CP25Control::writeModem(unsigned char* data, unsigned int len)
} }
m_display->writeP25RSSI(m_rssi); m_display->writeP25RSSI(m_rssi);
} else if (duid == P25_DUID_TERM || duid == P25_DUID_TERM_LC) {
if (m_rfState == RS_RF_LISTENING)
return false;
return true;
}
} else if (duid == P25_DUID_TERM || duid == P25_DUID_TERM_LC) {
if (m_rfState == RS_RF_AUDIO) {
writeNetwork(m_rfLDU, m_lastDUID, true); writeNetwork(m_rfLDU, m_lastDUID, true);
::memset(data + 2U, 0x00U, P25_TERM_FRAME_LENGTH_BYTES); ::memset(data + 2U, 0x00U, P25_TERM_FRAME_LENGTH_BYTES);
@ -328,11 +357,10 @@ bool CP25Control::writeModem(unsigned char* data, unsigned int len)
data[1U] = 0x00U; data[1U] = 0x00U;
writeQueueRF(data, P25_TERM_FRAME_LENGTH_BYTES + 2U); writeQueueRF(data, P25_TERM_FRAME_LENGTH_BYTES + 2U);
} }
} else { }
return false;
} }
return true; return false;
} }
unsigned int CP25Control::readModem(unsigned char* data) unsigned int CP25Control::readModem(unsigned char* data)
@ -725,6 +753,9 @@ void CP25Control::createNetHeader()
m_netData.encodeHeader(buffer + 2U); m_netData.encodeHeader(buffer + 2U);
// Add busy bits // Add busy bits
if (m_remoteGateway)
addBusyBits(buffer + 2U, P25_HDR_FRAME_LENGTH_BITS, true, false);
else
addBusyBits(buffer + 2U, P25_HDR_FRAME_LENGTH_BITS, false, true); addBusyBits(buffer + 2U, P25_HDR_FRAME_LENGTH_BITS, false, true);
writeQueueNet(buffer, P25_HDR_FRAME_LENGTH_BYTES + 2U); writeQueueNet(buffer, P25_HDR_FRAME_LENGTH_BYTES + 2U);
@ -766,6 +797,9 @@ void CP25Control::createNetLDU1()
m_netLSD.encode(buffer + 2U); m_netLSD.encode(buffer + 2U);
// Add busy bits // Add busy bits
if (m_remoteGateway)
addBusyBits(buffer + 2U, P25_LDU_FRAME_LENGTH_BITS, true, false);
else
addBusyBits(buffer + 2U, P25_LDU_FRAME_LENGTH_BITS, false, true); addBusyBits(buffer + 2U, P25_LDU_FRAME_LENGTH_BITS, false, true);
writeQueueNet(buffer, P25_LDU_FRAME_LENGTH_BYTES + 2U); writeQueueNet(buffer, P25_LDU_FRAME_LENGTH_BYTES + 2U);
@ -811,6 +845,9 @@ void CP25Control::createNetLDU2()
m_netLSD.encode(buffer + 2U); m_netLSD.encode(buffer + 2U);
// Add busy bits // Add busy bits
if (m_remoteGateway)
addBusyBits(buffer + 2U, P25_LDU_FRAME_LENGTH_BITS, true, false);
else
addBusyBits(buffer + 2U, P25_LDU_FRAME_LENGTH_BITS, false, true); addBusyBits(buffer + 2U, P25_LDU_FRAME_LENGTH_BITS, false, true);
writeQueueNet(buffer, P25_LDU_FRAME_LENGTH_BYTES + 2U); writeQueueNet(buffer, P25_LDU_FRAME_LENGTH_BYTES + 2U);
@ -835,6 +872,9 @@ void CP25Control::createNetTerminator()
m_nid.encode(buffer + 2U, P25_DUID_TERM); m_nid.encode(buffer + 2U, P25_DUID_TERM);
// Add busy bits // Add busy bits
if (m_remoteGateway)
addBusyBits(buffer + 2U, P25_TERM_FRAME_LENGTH_BITS, true, false);
else
addBusyBits(buffer + 2U, P25_TERM_FRAME_LENGTH_BITS, false, true); addBusyBits(buffer + 2U, P25_TERM_FRAME_LENGTH_BITS, false, true);
writeQueueNet(buffer, P25_TERM_FRAME_LENGTH_BYTES + 2U); writeQueueNet(buffer, P25_TERM_FRAME_LENGTH_BYTES + 2U);

View file

@ -36,7 +36,7 @@
class CP25Control { class CP25Control {
public: public:
CP25Control(unsigned int nac, bool uidOverride, CP25Network* network, CDisplay* display, unsigned int timeout, bool duplex, CDMRLookup* lookup, CRSSIInterpolator* rssiMapper); CP25Control(unsigned int nac, unsigned int id, bool selfOly, bool uidOverride, CP25Network* network, CDisplay* display, unsigned int timeout, bool duplex, CDMRLookup* lookup, bool remoteGateway, CRSSIInterpolator* rssiMapper);
~CP25Control(); ~CP25Control();
bool writeModem(unsigned char* data, unsigned int len); bool writeModem(unsigned char* data, unsigned int len);
@ -47,7 +47,10 @@ public:
private: private:
unsigned int m_nac; unsigned int m_nac;
unsigned int m_id;
bool m_selfOnly;
bool m_uidOverride; bool m_uidOverride;
bool m_remoteGateway;
CP25Network* m_network; CP25Network* m_network;
CDisplay* m_display; CDisplay* m_display;
bool m_duplex; bool m_duplex;

View file

@ -71,7 +71,7 @@ void CP25Data::encodeHeader(unsigned char* data)
CP25Utils::encode(DUMMY_HEADER, data, 114U, 780U); CP25Utils::encode(DUMMY_HEADER, data, 114U, 780U);
} }
bool CP25Data::decodeLDU1(const unsigned char* data, bool m_network, bool m_uidOverride) bool CP25Data::decodeLDU1(const unsigned char* data)
{ {
assert(data != NULL); assert(data != NULL);
@ -105,12 +105,7 @@ bool CP25Data::decodeLDU1(const unsigned char* data, bool m_network, bool m_uidO
return false; return false;
} }
// Simple validation of the source id - does not check if no network
unsigned int srcId = (rs[6U] << 16) + (rs[7U] << 8) + rs[8U]; unsigned int srcId = (rs[6U] << 16) + (rs[7U] << 8) + rs[8U];
if (m_network || (!m_network && !m_uidOverride)) {
if (srcId < 1000000U)
return false;
}
switch (rs[0U]) { switch (rs[0U]) {
case P25_LCF_GROUP: case P25_LCF_GROUP:

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2016 by Jonathan Naylor G4KLX * Copyright (C) 2016,2017 by Jonathan Naylor G4KLX
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -28,7 +28,7 @@ public:
void encodeHeader(unsigned char* data); void encodeHeader(unsigned char* data);
bool decodeLDU1(const unsigned char* data, bool m_network, bool m_uidOverride); bool decodeLDU1(const unsigned char* data);
void encodeLDU1(unsigned char* data); void encodeLDU1(unsigned char* data);
void encodeLDU2(unsigned char* data); void encodeLDU2(unsigned char* data);

View file

@ -27,11 +27,11 @@
#include <cstring> #include <cstring>
const unsigned char REC62[] = { const unsigned char REC62[] = {
0x62U, 0x02U, 0x02U, 0x0CU, 0x0BU, 0x1BU, 0x5AU, 0x1AU, 0x2BU, 0x80U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x62U, 0x02U, 0x02U, 0x0CU, 0x0BU, 0x12U, 0x64U, 0x00U, 0x00U, 0x80U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U,
0x00U, 0x00U, 0x00U, 0x00U, 0x02U}; 0x00U, 0x00U, 0x00U, 0x00U, 0x00U};
const unsigned char REC63[] = { const unsigned char REC63[] = {
0x63U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x7AU}; 0x63U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x02U};
const unsigned char REC64[] = { const unsigned char REC64[] = {
0x64U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x02U}; 0x64U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x02U};
@ -43,23 +43,23 @@ const unsigned char REC66[] = {
0x66U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x02U}; 0x66U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x02U};
const unsigned char REC67[] = { const unsigned char REC67[] = {
0x67U, 0xC4U, 0x52U, 0x9BU, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x02U}; 0x67U, 0xF0U, 0x9DU, 0x6AU, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x02U};
const unsigned char REC68[] = { const unsigned char REC68[] = {
0x68U, 0x9AU, 0xECU, 0xBAU, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x02U}; 0x68U, 0x19U, 0xD4U, 0x26U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x02U};
const unsigned char REC69[] = { const unsigned char REC69[] = {
0x69U, 0xB9U, 0xD8U, 0x16U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x02U}; 0x69U, 0xE0U, 0xEBU, 0x7BU, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x02U};
const unsigned char REC6A[] = { const unsigned char REC6A[] = {
0x6AU, 0x00U, 0x00U, 0x06U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x02U}; 0x6AU, 0x00U, 0x00U, 0x02U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U};
const unsigned char REC6B[] = { const unsigned char REC6B[] = {
0x6BU, 0x02U, 0x02U, 0x0CU, 0x0BU, 0x1BU, 0x5AU, 0x1AU, 0x2BU, 0xACU, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x6BU, 0x02U, 0x02U, 0x0CU, 0x0BU, 0x12U, 0x64U, 0x00U, 0x00U, 0x80U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U,
0x00U, 0x00U, 0x00U, 0x00U, 0x02U}; 0x00U, 0x00U, 0x00U, 0x00U, 0x00U};
const unsigned char REC6C[] = { const unsigned char REC6C[] = {
0x6CU, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0xD6U}; 0x6CU, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x02U};
const unsigned char REC6D[] = { const unsigned char REC6D[] = {
0x6DU, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x02U}; 0x6DU, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x02U};
@ -80,7 +80,7 @@ const unsigned char REC72[] = {
0x72U, 0x9BU, 0xDCU, 0x75U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x02U}; 0x72U, 0x9BU, 0xDCU, 0x75U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x02U};
const unsigned char REC73[] = { const unsigned char REC73[] = {
0x73U, 0x00U, 0x00U, 0x06U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x02U}; 0x73U, 0x00U, 0x00U, 0x02U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U};
const unsigned char REC80[] = { const unsigned char REC80[] = {
0x80U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U}; 0x80U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U};

View file

@ -1,8 +1,8 @@
These are the source files for building the MMDVMHost, the program that interfaces to the MMDVM or DVMega on the one side, and a suitable network on the other. It supports D-Star, DMR, P25 Phase 1, and System Fusion. These are the source files for building the MMDVMHost, the program that interfaces to the MMDVM or DVMega on the one side, and a suitable network on the other. It supports D-Star, DMR, P25 Phase 1, and System Fusion.
On the D-Star side the MMDVMHost interfaces with the ircDDB Gateway, on DMR it can connect to BrandMeister, DMR+, or HB Link, on System Fusion it connects to the YSF Gateway. On P25 it connects to the P25 Gateway. On the D-Star side the MMDVMHost interfaces with the ircDDB Gateway, on DMR it can connect to BrandMeister, DMR+, HB Link, XLX or [DMRGateway](https://github.com/g4klx/DMRGateway) (to connect to multiple DMR networks at once) on System Fusion it connects to the YSF Gateway. On P25 it connects to the P25 Gateway.
It builds on 32-bit and 64-bit Linux as well as on Windows using VS2015 on x86 and x64. It can optionally control various Displays. Currently these are: It builds on 32-bit and 64-bit Linux as well as on Windows using Visual Studio 2017 on x86 and x64. It can optionally control various Displays. Currently these are:
- HD44780 (sizes 2x16, 2x40, 4x16, 4x20) - HD44780 (sizes 2x16, 2x40, 4x16, 4x20)
- Support for HD44780 via 4 bit GPIO connection (user selectable pins) - Support for HD44780 via 4 bit GPIO connection (user selectable pins)
@ -11,6 +11,7 @@ It builds on 32-bit and 64-bit Linux as well as on Windows using VS2015 on x86 a
- Nextion TFTs (sizes 2.4", 2.8", 3.2" and 3.5") - Nextion TFTs (sizes 2.4", 2.8", 3.2" and 3.5")
- TFT display sold by Hobbytronics in UK - TFT display sold by Hobbytronics in UK
- OLED 128x64 (SSD1306) - OLED 128x64 (SSD1306)
- LCDproc
The Nextion displays can connect to the UART on the Raspberry Pi, or via a USB to TTL serial converter like the FT-232RL. It may also be connected to the UART output of the MMDVM modem (Arduino Due, STM32, Teensy), or to the UART output on the UMP. The Nextion displays can connect to the UART on the Raspberry Pi, or via a USB to TTL serial converter like the FT-232RL. It may also be connected to the UART output of the MMDVM modem (Arduino Due, STM32, Teensy), or to the UART output on the UMP.
@ -20,4 +21,6 @@ The Hobbytronics TFT Display, which is a Pi-Hat, connects to the UART on the Ras
The OLED display needs a extra library see OLED.md The OLED display needs a extra library see OLED.md
The LCDproc support enables the use of a multitude of other LCD screens. See the [supported devices](http://lcdproc.omnipotent.net/hardware.php3) page on the LCDproc website for more info.
This software is licenced under the GPL v2 and is intended for amateur and educational use only. Use of this software for commercial purposes is strictly forbidden. This software is licenced under the GPL v2 and is intended for amateur and educational use only. Use of this software for commercial purposes is strictly forbidden.

View file

@ -0,0 +1,23 @@
# This file maps the raw RSSI values to dBm values to send to the DMR network. A number of data
# points should be entered and the software will use those to work out the in-between values.
#
# The format of the file is:
# Raw RSSI Value dBm Value
#
# provided by Wilm DL4OCH
# Data taken with F0DEI MMDVM v1.2 and 47k/27k divider in RSSI input
2263 -43
2235 -53
2108 -63
1910 -73
1809 -83
1649 -93 # S9
1514 -99 # S8
1389 -105 # S7
1287 -111 # S6
1153 -117 # S5
1041 -123 # S4
977 -129 # S3
940 -135 # S2
934 -141 # S1

View file

@ -237,8 +237,11 @@ CSerialController::~CSerialController()
bool CSerialController::open() bool CSerialController::open()
{ {
assert(m_fd == -1); assert(m_fd == -1);
#if defined(__APPLE__)
m_fd = ::open(m_device.c_str(), O_RDWR | O_NOCTTY | O_NONBLOCK); /*open in block mode under OSX*/
#else
m_fd = ::open(m_device.c_str(), O_RDWR | O_NOCTTY | O_NDELAY, 0); m_fd = ::open(m_device.c_str(), O_RDWR | O_NOCTTY | O_NDELAY, 0);
#endif
if (m_fd < 0) { if (m_fd < 0) {
LogError("Cannot open device - %s", m_device.c_str()); LogError("Cannot open device - %s", m_device.c_str());
return false; return false;
@ -257,6 +260,23 @@ bool CSerialController::open()
return false; return false;
} }
#if defined(__APPLE__)
termios.c_cflag |= (CLOCAL | CREAD); /* ignore modem controls */
termios.c_cflag &= ~CSIZE;
termios.c_cflag |= CS8; /* 8-bit characters */
termios.c_cflag &= ~PARENB; /* no parity bit */
termios.c_cflag &= ~CSTOPB; /* only need 1 stop bit */
termios.c_cflag &= ~CRTSCTS; /* no hardware flowcontrol */
/* setup for non-canonical mode */
termios.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP | INLCR | IGNCR | ICRNL | IXON);
termios.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
termios.c_oflag &= ~OPOST;
/* fetch bytes as they become available */
termios.c_cc[VMIN] = 1;
termios.c_cc[VTIME] = 1;
#else
termios.c_lflag &= ~(ECHO | ECHOE | ICANON | IEXTEN | ISIG); termios.c_lflag &= ~(ECHO | ECHOE | ICANON | IEXTEN | ISIG);
termios.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON | IXOFF | IXANY); termios.c_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON | IXOFF | IXANY);
termios.c_cflag &= ~(CSIZE | CSTOPB | PARENB | CRTSCTS); termios.c_cflag &= ~(CSIZE | CSTOPB | PARENB | CRTSCTS);
@ -264,6 +284,7 @@ bool CSerialController::open()
termios.c_oflag &= ~(OPOST); termios.c_oflag &= ~(OPOST);
termios.c_cc[VMIN] = 0; termios.c_cc[VMIN] = 0;
termios.c_cc[VTIME] = 10; termios.c_cc[VTIME] = 10;
#endif
switch (m_speed) { switch (m_speed) {
case SERIAL_1200: case SERIAL_1200:
@ -327,9 +348,27 @@ bool CSerialController::open()
} }
} }
#if defined(__APPLE__)
setNonblock(false);
#endif
return true; return true;
} }
#if defined(__APPLE__)
int CSerialController::setNonblock(bool nonblock)
{
int flag = ::fcntl(m_fd, F_GETFD, 0);
if (nonblock)
flag |= O_NONBLOCK;
else
flag &= ~O_NONBLOCK;
return ::fcntl(m_fd, F_SETFL, flag);
}
#endif
int CSerialController::read(unsigned char* buffer, unsigned int length) int CSerialController::read(unsigned char* buffer, unsigned int length)
{ {
assert(buffer != NULL); assert(buffer != NULL);
@ -344,13 +383,11 @@ int CSerialController::read(unsigned char* buffer, unsigned int length)
fd_set fds; fd_set fds;
FD_ZERO(&fds); FD_ZERO(&fds);
FD_SET(m_fd, &fds); FD_SET(m_fd, &fds);
int n; int n;
if (offset == 0U) { if (offset == 0U) {
struct timeval tv; struct timeval tv;
tv.tv_sec = 0; tv.tv_sec = 0;
tv.tv_usec = 0; tv.tv_usec = 0;
n = ::select(m_fd + 1, &fds, NULL, NULL, &tv); n = ::select(m_fd + 1, &fds, NULL, NULL, &tv);
if (n == 0) if (n == 0)
return 0; return 0;
@ -380,6 +417,26 @@ int CSerialController::read(unsigned char* buffer, unsigned int length)
return length; return length;
} }
bool CSerialController::canWrite(){
#if defined(__APPLE__)
fd_set wset;
FD_ZERO(&wset);
FD_SET(m_fd, &wset);
struct timeval timeo;
timeo.tv_sec = 0;
timeo.tv_usec = 0;
int rc = select(m_fd + 1, NULL, &wset, NULL, &timeo);
if (rc >0 && FD_ISSET(m_fd, &wset))
return true;
return false;
#else
return true;
#endif
}
int CSerialController::write(const unsigned char* buffer, unsigned int length) int CSerialController::write(const unsigned char* buffer, unsigned int length)
{ {
assert(buffer != NULL); assert(buffer != NULL);
@ -389,9 +446,10 @@ int CSerialController::write(const unsigned char* buffer, unsigned int length)
return 0; return 0;
unsigned int ptr = 0U; unsigned int ptr = 0U;
while (ptr < length) { while (ptr < length) {
ssize_t n = ::write(m_fd, buffer + ptr, length - ptr); ssize_t n = 0U;
if (canWrite())
n = ::write(m_fd, buffer + ptr, length - ptr);
if (n < 0) { if (n < 0) {
if (errno != EAGAIN) { if (errno != EAGAIN) {
LogError("Error returned from write(), errno=%d", errno); LogError("Error returned from write(), errno=%d", errno);

View file

@ -53,6 +53,10 @@ public:
virtual void close(); virtual void close();
#if defined(__APPLE__)
virtual int setNonblock(bool nonblock);
#endif
private: private:
std::string m_device; std::string m_device;
SERIAL_SPEED m_speed; SERIAL_SPEED m_speed;
@ -65,6 +69,8 @@ private:
#if defined(_WIN32) || defined(_WIN64) #if defined(_WIN32) || defined(_WIN64)
int readNonblock(unsigned char* buffer, unsigned int length); int readNonblock(unsigned char* buffer, unsigned int length);
#else
bool canWrite();
#endif #endif
}; };

View file

@ -19,6 +19,6 @@
#if !defined(VERSION_H) #if !defined(VERSION_H)
#define VERSION_H #define VERSION_H
const char* VERSION = "20170501"; const char* VERSION = "20170719";
#endif #endif

File diff suppressed because it is too large Load diff

View file

@ -25,6 +25,7 @@
#include "YSFPayload.h" #include "YSFPayload.h"
#include "RingBuffer.h" #include "RingBuffer.h"
#include "StopWatch.h" #include "StopWatch.h"
#include "YSFFICH.h"
#include "Display.h" #include "Display.h"
#include "Defines.h" #include "Defines.h"
#include "Timer.h" #include "Timer.h"
@ -34,9 +35,11 @@
class CYSFControl { class CYSFControl {
public: public:
CYSFControl(const std::string& callsign, CYSFNetwork* network, CDisplay* display, unsigned int timeout, bool duplex, bool lowDeviation, bool remoteGateway, CRSSIInterpolator* rssiMapper); CYSFControl(const std::string& callsign, bool selfOnly, CYSFNetwork* network, CDisplay* display, unsigned int timeout, bool duplex, bool lowDeviation, bool remoteGateway, CRSSIInterpolator* rssiMapper);
~CYSFControl(); ~CYSFControl();
void setSQL(bool on, unsigned char value);
bool writeModem(unsigned char* data, unsigned int len); bool writeModem(unsigned char* data, unsigned int len);
unsigned int readModem(unsigned char* data); unsigned int readModem(unsigned char* data);
@ -45,11 +48,15 @@ public:
private: private:
unsigned char* m_callsign; unsigned char* m_callsign;
unsigned char* m_selfCallsign;
bool m_selfOnly;
CYSFNetwork* m_network; CYSFNetwork* m_network;
CDisplay* m_display; CDisplay* m_display;
bool m_duplex; bool m_duplex;
bool m_lowDeviation; bool m_lowDeviation;
bool m_remoteGateway; bool m_remoteGateway;
bool m_sqlEnabled;
unsigned char m_sqlValue;
CRingBuffer<unsigned char> m_queue; CRingBuffer<unsigned char> m_queue;
RPT_RF_STATE m_rfState; RPT_RF_STATE m_rfState;
RPT_NET_STATE m_netState; RPT_NET_STATE m_netState;
@ -69,10 +76,7 @@ private:
unsigned char* m_rfDest; unsigned char* m_rfDest;
unsigned char* m_netSource; unsigned char* m_netSource;
unsigned char* m_netDest; unsigned char* m_netDest;
unsigned char* m_lastFrame; CYSFFICH m_lastFICH;
bool m_lastFrameValid;
unsigned char m_lastMode;
unsigned char m_lastMR;
unsigned char m_netN; unsigned char m_netN;
CYSFPayload m_rfPayload; CYSFPayload m_rfPayload;
CYSFPayload m_netPayload; CYSFPayload m_netPayload;
@ -84,6 +88,10 @@ private:
unsigned int m_rssiCount; unsigned int m_rssiCount;
FILE* m_fp; FILE* m_fp;
bool processVWData(bool valid, unsigned char *data);
bool processDNData(bool valid, unsigned char *data);
bool processFRData(bool valid, unsigned char *data);
void writeQueueRF(const unsigned char* data); void writeQueueRF(const unsigned char* data);
void writeQueueNet(const unsigned char* data); void writeQueueNet(const unsigned char* data);
void writeNetwork(const unsigned char* data, unsigned int count); void writeNetwork(const unsigned char* data, unsigned int count);
@ -96,8 +104,7 @@ private:
bool writeFile(const unsigned char* data); bool writeFile(const unsigned char* data);
void closeFile(); void closeFile();
bool insertSilence(const unsigned char* data, unsigned char n); bool checkCallsign(const unsigned char* callsign) const;
void insertSilence(unsigned int count);
}; };
#endif #endif

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2015,2016 by Jonathan Naylor G4KLX * Copyright (C) 2015,2016,2017 by Jonathan Naylor G4KLX
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -42,7 +42,8 @@ const unsigned char YSF_DT_DATA_FR_MODE = 0x01U;
const unsigned char YSF_DT_VD_MODE2 = 0x02U; const unsigned char YSF_DT_VD_MODE2 = 0x02U;
const unsigned char YSF_DT_VOICE_FR_MODE = 0x03U; const unsigned char YSF_DT_VOICE_FR_MODE = 0x03U;
const unsigned char YSF_CM_GROUP = 0x00U; const unsigned char YSF_CM_GROUP1 = 0x00U;
const unsigned char YSF_CM_GROUP2 = 0x01U;
const unsigned char YSF_CM_INDIVIDUAL = 0x03U; const unsigned char YSF_CM_INDIVIDUAL = 0x03U;
const unsigned char YSF_MR_NOT_BUSY = 0x01U; const unsigned char YSF_MR_NOT_BUSY = 0x01U;

Some files were not shown because too many files have changed in this diff Show more