mirror of
https://github.com/g4klx/MMDVMHost.git
synced 2026-01-01 22:20:01 +01:00
Merge remote-tracking branch 'refs/remotes/g4klx/master'
This commit is contained in:
commit
000ef35c13
124
Conf.cpp
124
Conf.cpp
|
|
@ -43,11 +43,13 @@ enum SECTION {
|
|||
SECTION_FUSION,
|
||||
SECTION_P25,
|
||||
SECTION_NXDN,
|
||||
SECTION_POCSAG,
|
||||
SECTION_DSTAR_NETWORK,
|
||||
SECTION_DMR_NETWORK,
|
||||
SECTION_FUSION_NETWORK,
|
||||
SECTION_P25_NETWORK,
|
||||
SECTION_NXDN_NETWORK,
|
||||
SECTION_POCSAG_NETWORK,
|
||||
SECTION_TFTSERIAL,
|
||||
SECTION_HD44780,
|
||||
SECTION_NEXTION,
|
||||
|
|
@ -85,6 +87,8 @@ m_dmrIdLookupTime(0U),
|
|||
m_nxdnIdLookupFile(),
|
||||
m_nxdnIdLookupTime(0U),
|
||||
m_modemPort(),
|
||||
m_modemProtocol("uart"),
|
||||
m_modemAddress(0x22),
|
||||
m_modemRXInvert(false),
|
||||
m_modemTXInvert(false),
|
||||
m_modemPTTInvert(false),
|
||||
|
|
@ -102,6 +106,7 @@ m_modemDMRTXLevel(50.0F),
|
|||
m_modemYSFTXLevel(50.0F),
|
||||
m_modemP25TXLevel(50.0F),
|
||||
m_modemNXDNTXLevel(50.0F),
|
||||
m_modemPOCSAGTXLevel(50.0F),
|
||||
m_modemRSSIMappingFile(),
|
||||
m_modemTrace(false),
|
||||
m_modemDebug(false),
|
||||
|
|
@ -109,6 +114,7 @@ m_transparentEnabled(false),
|
|||
m_transparentRemoteAddress(),
|
||||
m_transparentRemotePort(0U),
|
||||
m_transparentLocalPort(0U),
|
||||
m_transparentSendFrameType(0U),
|
||||
m_umpEnabled(false),
|
||||
m_umpPort(),
|
||||
m_dstarEnabled(false),
|
||||
|
|
@ -141,6 +147,7 @@ m_fusionEnabled(false),
|
|||
m_fusionLowDeviation(false),
|
||||
m_fusionRemoteGateway(false),
|
||||
m_fusionSelfOnly(false),
|
||||
m_fusionTXHang(4U),
|
||||
m_fusionSQLEnabled(false),
|
||||
m_fusionSQL(0U),
|
||||
m_fusionModeHang(10U),
|
||||
|
|
@ -157,6 +164,8 @@ m_nxdnRAN(1U),
|
|||
m_nxdnSelfOnly(false),
|
||||
m_nxdnRemoteGateway(false),
|
||||
m_nxdnModeHang(10U),
|
||||
m_pocsagEnabled(false),
|
||||
m_pocsagFrequency(0U),
|
||||
m_dstarNetworkEnabled(false),
|
||||
m_dstarGatewayAddress(),
|
||||
m_dstarGatewayPort(0U),
|
||||
|
|
@ -170,7 +179,7 @@ m_dmrNetworkLocal(0U),
|
|||
m_dmrNetworkPassword(),
|
||||
m_dmrNetworkOptions(),
|
||||
m_dmrNetworkDebug(false),
|
||||
m_dmrNetworkJitter(300U),
|
||||
m_dmrNetworkJitter(360U),
|
||||
m_dmrNetworkSlot1(true),
|
||||
m_dmrNetworkSlot2(true),
|
||||
m_dmrNetworkModeHang(3U),
|
||||
|
|
@ -194,6 +203,13 @@ m_nxdnLocalAddress(),
|
|||
m_nxdnLocalPort(0U),
|
||||
m_nxdnNetworkModeHang(3U),
|
||||
m_nxdnNetworkDebug(false),
|
||||
m_pocsagNetworkEnabled(false),
|
||||
m_pocsagGatewayAddress(),
|
||||
m_pocsagGatewayPort(0U),
|
||||
m_pocsagLocalAddress(),
|
||||
m_pocsagLocalPort(0U),
|
||||
m_pocsagNetworkModeHang(3U),
|
||||
m_pocsagNetworkDebug(false),
|
||||
m_tftSerialPort("/dev/ttyAMA0"),
|
||||
m_tftSerialBrightness(50U),
|
||||
m_hd44780Rows(2U),
|
||||
|
|
@ -272,6 +288,8 @@ bool CConf::read()
|
|||
section = SECTION_P25;
|
||||
else if (::strncmp(buffer, "[NXDN]", 6U) == 0)
|
||||
section = SECTION_NXDN;
|
||||
else if (::strncmp(buffer, "[POCSAG]", 8U) == 0)
|
||||
section = SECTION_POCSAG;
|
||||
else if (::strncmp(buffer, "[D-Star Network]", 16U) == 0)
|
||||
section = SECTION_DSTAR_NETWORK;
|
||||
else if (::strncmp(buffer, "[DMR Network]", 13U) == 0)
|
||||
|
|
@ -282,6 +300,8 @@ bool CConf::read()
|
|||
section = SECTION_P25_NETWORK;
|
||||
else if (::strncmp(buffer, "[NXDN Network]", 14U) == 0)
|
||||
section = SECTION_NXDN_NETWORK;
|
||||
else if (::strncmp(buffer, "[POCSAG Network]", 16U) == 0)
|
||||
section = SECTION_POCSAG_NETWORK;
|
||||
else if (::strncmp(buffer, "[TFT Serial]", 12U) == 0)
|
||||
section = SECTION_TFTSERIAL;
|
||||
else if (::strncmp(buffer, "[HD44780]", 9U) == 0)
|
||||
|
|
@ -338,7 +358,7 @@ bool CConf::read()
|
|||
m_daemon = ::atoi(value) == 1;
|
||||
} else if (section == SECTION_INFO) {
|
||||
if (::strcmp(key, "TXFrequency") == 0)
|
||||
m_txFrequency = (unsigned int)::atoi(value);
|
||||
m_pocsagFrequency = m_txFrequency = (unsigned int)::atoi(value);
|
||||
else if (::strcmp(key, "RXFrequency") == 0)
|
||||
m_rxFrequency = (unsigned int)::atoi(value);
|
||||
else if (::strcmp(key, "Power") == 0)
|
||||
|
|
@ -388,6 +408,10 @@ bool CConf::read()
|
|||
} else if (section == SECTION_MODEM) {
|
||||
if (::strcmp(key, "Port") == 0)
|
||||
m_modemPort = value;
|
||||
else if (::strcmp(key, "Protocol") == 0)
|
||||
m_modemProtocol = value;
|
||||
else if (::strcmp(key, "Address") == 0)
|
||||
m_modemAddress = (unsigned int)::strtoul(value, NULL, 16);
|
||||
else if (::strcmp(key, "RXInvert") == 0)
|
||||
m_modemRXInvert = ::atoi(value) == 1;
|
||||
else if (::strcmp(key, "TXInvert") == 0)
|
||||
|
|
@ -424,6 +448,8 @@ bool CConf::read()
|
|||
m_modemP25TXLevel = float(::atof(value));
|
||||
else if (::strcmp(key, "NXDNTXLevel") == 0)
|
||||
m_modemNXDNTXLevel = float(::atof(value));
|
||||
else if (::strcmp(key, "POCSAGTXLevel") == 0)
|
||||
m_modemPOCSAGTXLevel = float(::atof(value));
|
||||
else if (::strcmp(key, "RSSIMappingFile") == 0)
|
||||
m_modemRSSIMappingFile = value;
|
||||
else if (::strcmp(key, "Trace") == 0)
|
||||
|
|
@ -439,6 +465,8 @@ bool CConf::read()
|
|||
m_transparentRemotePort = (unsigned int)::atoi(value);
|
||||
else if (::strcmp(key, "LocalPort") == 0)
|
||||
m_transparentLocalPort = (unsigned int)::atoi(value);
|
||||
else if (::strcmp(key, "SendFrameType") == 0)
|
||||
m_transparentSendFrameType = (unsigned int)::atoi(value);
|
||||
} else if (section == SECTION_UMP) {
|
||||
if (::strcmp(key, "Enable") == 0)
|
||||
m_umpEnabled = ::atoi(value) == 1;
|
||||
|
|
@ -553,6 +581,8 @@ bool CConf::read()
|
|||
m_fusionRemoteGateway = ::atoi(value) == 1;
|
||||
else if (::strcmp(key, "SelfOnly") == 0)
|
||||
m_fusionSelfOnly = ::atoi(value) == 1;
|
||||
else if (::strcmp(key, "TXHang") == 0)
|
||||
m_fusionTXHang = (unsigned int)::atoi(value);
|
||||
else if (::strcmp(key, "ModeHang") == 0)
|
||||
m_fusionModeHang = (unsigned int)::atoi(value);
|
||||
} else if (section == SECTION_P25) {
|
||||
|
|
@ -583,6 +613,11 @@ bool CConf::read()
|
|||
m_nxdnRemoteGateway = ::atoi(value) == 1;
|
||||
else if (::strcmp(key, "ModeHang") == 0)
|
||||
m_nxdnModeHang = (unsigned int)::atoi(value);
|
||||
} else if (section == SECTION_POCSAG) {
|
||||
if (::strcmp(key, "Enable") == 0)
|
||||
m_pocsagEnabled = ::atoi(value) == 1;
|
||||
else if (::strcmp(key, "Frequency") == 0)
|
||||
m_pocsagFrequency = (unsigned int)::atoi(value);
|
||||
} else if (section == SECTION_DSTAR_NETWORK) {
|
||||
if (::strcmp(key, "Enable") == 0)
|
||||
m_dstarNetworkEnabled = ::atoi(value) == 1;
|
||||
|
|
@ -662,6 +697,21 @@ bool CConf::read()
|
|||
m_nxdnNetworkModeHang = (unsigned int)::atoi(value);
|
||||
else if (::strcmp(key, "Debug") == 0)
|
||||
m_nxdnNetworkDebug = ::atoi(value) == 1;
|
||||
} else if (section == SECTION_POCSAG_NETWORK) {
|
||||
if (::strcmp(key, "Enable") == 0)
|
||||
m_pocsagNetworkEnabled = ::atoi(value) == 1;
|
||||
else if (::strcmp(key, "LocalAddress") == 0)
|
||||
m_pocsagLocalAddress = value;
|
||||
else if (::strcmp(key, "LocalPort") == 0)
|
||||
m_pocsagLocalPort = (unsigned int)::atoi(value);
|
||||
else if (::strcmp(key, "GatewayAddress") == 0)
|
||||
m_pocsagGatewayAddress = value;
|
||||
else if (::strcmp(key, "GatewayPort") == 0)
|
||||
m_pocsagGatewayPort = (unsigned int)::atoi(value);
|
||||
else if (::strcmp(key, "ModeHang") == 0)
|
||||
m_pocsagNetworkModeHang = (unsigned int)::atoi(value);
|
||||
else if (::strcmp(key, "Debug") == 0)
|
||||
m_pocsagNetworkDebug = ::atoi(value) == 1;
|
||||
} else if (section == SECTION_TFTSERIAL) {
|
||||
if (::strcmp(key, "Port") == 0)
|
||||
m_tftSerialPort = value;
|
||||
|
|
@ -872,6 +922,16 @@ std::string CConf::getModemPort() const
|
|||
return m_modemPort;
|
||||
}
|
||||
|
||||
std::string CConf::getModemProtocol() const
|
||||
{
|
||||
return m_modemProtocol;
|
||||
}
|
||||
|
||||
unsigned int CConf::getModemAddress() const
|
||||
{
|
||||
return m_modemAddress;
|
||||
}
|
||||
|
||||
bool CConf::getModemRXInvert() const
|
||||
{
|
||||
return m_modemRXInvert;
|
||||
|
|
@ -957,6 +1017,11 @@ float CConf::getModemNXDNTXLevel() const
|
|||
return m_modemNXDNTXLevel;
|
||||
}
|
||||
|
||||
float CConf::getModemPOCSAGTXLevel() const
|
||||
{
|
||||
return m_modemPOCSAGTXLevel;
|
||||
}
|
||||
|
||||
std::string CConf::getModemRSSIMappingFile () const
|
||||
{
|
||||
return m_modemRSSIMappingFile;
|
||||
|
|
@ -992,6 +1057,11 @@ unsigned int CConf::getTransparentLocalPort() const
|
|||
return m_transparentLocalPort;
|
||||
}
|
||||
|
||||
unsigned int CConf::getTransparentSendFrameType() const
|
||||
{
|
||||
return m_transparentSendFrameType;
|
||||
}
|
||||
|
||||
bool CConf::getUMPEnabled() const
|
||||
{
|
||||
return m_umpEnabled;
|
||||
|
|
@ -1147,6 +1217,11 @@ bool CConf::getFusionRemoteGateway() const
|
|||
return m_fusionRemoteGateway;
|
||||
}
|
||||
|
||||
unsigned int CConf::getFusionTXHang() const
|
||||
{
|
||||
return m_fusionTXHang;
|
||||
}
|
||||
|
||||
bool CConf::getFusionSelfOnly() const
|
||||
{
|
||||
return m_fusionSelfOnly;
|
||||
|
|
@ -1232,6 +1307,16 @@ unsigned int CConf::getNXDNModeHang() const
|
|||
return m_nxdnModeHang;
|
||||
}
|
||||
|
||||
bool CConf::getPOCSAGEnabled() const
|
||||
{
|
||||
return m_pocsagEnabled;
|
||||
}
|
||||
|
||||
unsigned int CConf::getPOCSAGFrequency() const
|
||||
{
|
||||
return m_pocsagFrequency;
|
||||
}
|
||||
|
||||
bool CConf::getDStarNetworkEnabled() const
|
||||
{
|
||||
return m_dstarNetworkEnabled;
|
||||
|
|
@ -1417,6 +1502,41 @@ bool CConf::getNXDNNetworkDebug() const
|
|||
return m_nxdnNetworkDebug;
|
||||
}
|
||||
|
||||
bool CConf::getPOCSAGNetworkEnabled() const
|
||||
{
|
||||
return m_pocsagNetworkEnabled;
|
||||
}
|
||||
|
||||
std::string CConf::getPOCSAGGatewayAddress() const
|
||||
{
|
||||
return m_pocsagGatewayAddress;
|
||||
}
|
||||
|
||||
unsigned int CConf::getPOCSAGGatewayPort() const
|
||||
{
|
||||
return m_pocsagGatewayPort;
|
||||
}
|
||||
|
||||
std::string CConf::getPOCSAGLocalAddress() const
|
||||
{
|
||||
return m_pocsagLocalAddress;
|
||||
}
|
||||
|
||||
unsigned int CConf::getPOCSAGLocalPort() const
|
||||
{
|
||||
return m_pocsagLocalPort;
|
||||
}
|
||||
|
||||
unsigned int CConf::getPOCSAGNetworkModeHang() const
|
||||
{
|
||||
return m_pocsagNetworkModeHang;
|
||||
}
|
||||
|
||||
bool CConf::getPOCSAGNetworkDebug() const
|
||||
{
|
||||
return m_pocsagNetworkDebug;
|
||||
}
|
||||
|
||||
std::string CConf::getTFTSerialPort() const
|
||||
{
|
||||
return m_tftSerialPort;
|
||||
|
|
|
|||
34
Conf.h
34
Conf.h
|
|
@ -70,6 +70,8 @@ public:
|
|||
|
||||
// The Modem section
|
||||
std::string getModemPort() const;
|
||||
std::string getModemProtocol() const;
|
||||
unsigned int getModemAddress() const;
|
||||
bool getModemRXInvert() const;
|
||||
bool getModemTXInvert() const;
|
||||
bool getModemPTTInvert() const;
|
||||
|
|
@ -87,6 +89,7 @@ public:
|
|||
float getModemYSFTXLevel() const;
|
||||
float getModemP25TXLevel() const;
|
||||
float getModemNXDNTXLevel() const;
|
||||
float getModemPOCSAGTXLevel() const;
|
||||
std::string getModemRSSIMappingFile() const;
|
||||
bool getModemTrace() const;
|
||||
bool getModemDebug() const;
|
||||
|
|
@ -96,6 +99,7 @@ public:
|
|||
std::string getTransparentRemoteAddress() const;
|
||||
unsigned int getTransparentRemotePort() const;
|
||||
unsigned int getTransparentLocalPort() const;
|
||||
unsigned int getTransparentSendFrameType() const;
|
||||
|
||||
// The UMP section
|
||||
bool getUMPEnabled() const;
|
||||
|
|
@ -136,6 +140,7 @@ public:
|
|||
bool getFusionLowDeviation() const;
|
||||
bool getFusionRemoteGateway() const;
|
||||
bool getFusionSelfOnly() const;
|
||||
unsigned int getFusionTXHang() const;
|
||||
bool getFusionSQLEnabled() const;
|
||||
unsigned char getFusionSQL() const;
|
||||
unsigned int getFusionModeHang() const;
|
||||
|
|
@ -157,6 +162,10 @@ public:
|
|||
bool getNXDNRemoteGateway() const;
|
||||
unsigned int getNXDNModeHang() const;
|
||||
|
||||
// The POCSAG section
|
||||
bool getPOCSAGEnabled() const;
|
||||
unsigned int getPOCSAGFrequency() const;
|
||||
|
||||
// The D-Star Network section
|
||||
bool getDStarNetworkEnabled() const;
|
||||
std::string getDStarGatewayAddress() const;
|
||||
|
|
@ -204,6 +213,15 @@ public:
|
|||
unsigned int getNXDNNetworkModeHang() const;
|
||||
bool getNXDNNetworkDebug() const;
|
||||
|
||||
// The POCSAG Network section
|
||||
bool getPOCSAGNetworkEnabled() const;
|
||||
std::string getPOCSAGGatewayAddress() const;
|
||||
unsigned int getPOCSAGGatewayPort() const;
|
||||
std::string getPOCSAGLocalAddress() const;
|
||||
unsigned int getPOCSAGLocalPort() const;
|
||||
unsigned int getPOCSAGNetworkModeHang() const;
|
||||
bool getPOCSAGNetworkDebug() const;
|
||||
|
||||
// The TFTSERIAL section
|
||||
std::string getTFTSerialPort() const;
|
||||
unsigned int getTFTSerialBrightness() const;
|
||||
|
|
@ -277,6 +295,8 @@ private:
|
|||
unsigned int m_nxdnIdLookupTime;
|
||||
|
||||
std::string m_modemPort;
|
||||
std::string m_modemProtocol;
|
||||
unsigned int m_modemAddress;
|
||||
bool m_modemRXInvert;
|
||||
bool m_modemTXInvert;
|
||||
bool m_modemPTTInvert;
|
||||
|
|
@ -294,6 +314,7 @@ private:
|
|||
float m_modemYSFTXLevel;
|
||||
float m_modemP25TXLevel;
|
||||
float m_modemNXDNTXLevel;
|
||||
float m_modemPOCSAGTXLevel;
|
||||
std::string m_modemRSSIMappingFile;
|
||||
bool m_modemTrace;
|
||||
bool m_modemDebug;
|
||||
|
|
@ -302,6 +323,7 @@ private:
|
|||
std::string m_transparentRemoteAddress;
|
||||
unsigned int m_transparentRemotePort;
|
||||
unsigned int m_transparentLocalPort;
|
||||
unsigned int m_transparentSendFrameType;
|
||||
|
||||
bool m_umpEnabled;
|
||||
std::string m_umpPort;
|
||||
|
|
@ -338,6 +360,7 @@ private:
|
|||
bool m_fusionLowDeviation;
|
||||
bool m_fusionRemoteGateway;
|
||||
bool m_fusionSelfOnly;
|
||||
unsigned int m_fusionTXHang;
|
||||
bool m_fusionSQLEnabled;
|
||||
unsigned char m_fusionSQL;
|
||||
unsigned int m_fusionModeHang;
|
||||
|
|
@ -357,6 +380,9 @@ private:
|
|||
bool m_nxdnRemoteGateway;
|
||||
unsigned int m_nxdnModeHang;
|
||||
|
||||
bool m_pocsagEnabled;
|
||||
unsigned int m_pocsagFrequency;
|
||||
|
||||
bool m_dstarNetworkEnabled;
|
||||
std::string m_dstarGatewayAddress;
|
||||
unsigned int m_dstarGatewayPort;
|
||||
|
|
@ -399,6 +425,14 @@ private:
|
|||
unsigned int m_nxdnNetworkModeHang;
|
||||
bool m_nxdnNetworkDebug;
|
||||
|
||||
bool m_pocsagNetworkEnabled;
|
||||
std::string m_pocsagGatewayAddress;
|
||||
unsigned int m_pocsagGatewayPort;
|
||||
std::string m_pocsagLocalAddress;
|
||||
unsigned int m_pocsagLocalPort;
|
||||
unsigned int m_pocsagNetworkModeHang;
|
||||
bool m_pocsagNetworkDebug;
|
||||
|
||||
std::string m_tftSerialPort;
|
||||
unsigned int m_tftSerialBrightness;
|
||||
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@
|
|||
#include <cstdio>
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
#include <cstdlib>
|
||||
|
||||
const unsigned int BUFFER_LENGTH = 500U;
|
||||
|
||||
|
|
@ -33,6 +34,7 @@ const unsigned int HOMEBREW_DATA_PACKET_LENGTH = 55U;
|
|||
|
||||
|
||||
CDMRNetwork::CDMRNetwork(const std::string& address, unsigned int port, unsigned int local, unsigned int id, const std::string& password, bool duplex, const char* version, bool debug, bool slot1, bool slot2, HW_TYPE hwType) :
|
||||
m_addressStr(address),
|
||||
m_address(),
|
||||
m_port(port),
|
||||
m_id(NULL),
|
||||
|
|
@ -122,6 +124,9 @@ bool CDMRNetwork::open()
|
|||
{
|
||||
LogMessage("DMR, Opening DMR Network");
|
||||
|
||||
if (m_address.s_addr == INADDR_NONE)
|
||||
m_address = CUDPSocket::lookup(m_addressStr);
|
||||
|
||||
m_status = WAITING_CONNECT;
|
||||
m_timeoutTimer.stop();
|
||||
m_retryTimer.start();
|
||||
|
|
@ -544,6 +549,9 @@ bool CDMRNetwork::writeConfig()
|
|||
case HWT_MMDVM_HS_DUAL_HAT:
|
||||
software = "MMDVM_MMDVM_HS_Dual_Hat";
|
||||
break;
|
||||
case HWT_NANO_HOTSPOT:
|
||||
software = "MMDVM_Nano_hotSPOT";
|
||||
break;
|
||||
default:
|
||||
software = "MMDVM_Unknown";
|
||||
break;
|
||||
|
|
@ -570,6 +578,9 @@ bool CDMRNetwork::writeConfig()
|
|||
case HWT_NANO_HOTSPOT:
|
||||
software = "MMDVM_Nano_hotSPOT";
|
||||
break;
|
||||
case HWT_NANO_DV:
|
||||
software = "MMDVM_Nano_DV";
|
||||
break;
|
||||
case HWT_MMDVM_HS:
|
||||
software = "MMDVM_MMDVM_HS";
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -57,6 +57,7 @@ public:
|
|||
void close();
|
||||
|
||||
private:
|
||||
std::string m_addressStr;
|
||||
in_addr m_address;
|
||||
unsigned int m_port;
|
||||
uint8_t* m_id;
|
||||
|
|
|
|||
12
DMRSlot.cpp
12
DMRSlot.cpp
|
|
@ -89,6 +89,7 @@ m_rfLC(NULL),
|
|||
m_netLC(NULL),
|
||||
m_rfSeqNo(0U),
|
||||
m_rfN(0U),
|
||||
m_lastrfN(0U),
|
||||
m_netN(0U),
|
||||
m_networkWatchdog(1000U, 0U, 1500U),
|
||||
m_rfTimeoutTimer(1000U, timeout),
|
||||
|
|
@ -529,6 +530,7 @@ bool CDMRSlot::writeModem(unsigned char *data, unsigned int len)
|
|||
}
|
||||
} else if (audioSync) {
|
||||
if (m_rfState == RS_RF_AUDIO) {
|
||||
m_lastrfN = 0;
|
||||
// Convert the Audio Sync to be from the BS or MS as needed
|
||||
CSync::addDMRAudioSync(data + 2U, m_duplex);
|
||||
|
||||
|
|
@ -574,6 +576,11 @@ bool CDMRSlot::writeModem(unsigned char *data, unsigned int len)
|
|||
m_rfN = data[1U] & 0x0FU;
|
||||
if (m_rfN > 5U)
|
||||
return false;
|
||||
if (m_rfN == m_lastrfN)
|
||||
return false;
|
||||
if (m_rfN != (m_lastrfN + 1U))
|
||||
return false;
|
||||
m_lastrfN = m_rfN;
|
||||
|
||||
unsigned int errors = 0U;
|
||||
unsigned char fid = m_rfLC->getFID();
|
||||
|
|
@ -816,6 +823,11 @@ bool CDMRSlot::writeModem(unsigned char *data, unsigned int len)
|
|||
m_rfN = data[1U] & 0x0FU;
|
||||
if (m_rfN > 5U)
|
||||
return false;
|
||||
if (m_rfN == m_lastrfN)
|
||||
return false;
|
||||
if (m_rfN != (m_lastrfN + 1U))
|
||||
return false;
|
||||
m_lastrfN = m_rfN;
|
||||
|
||||
// Regenerate the EMB
|
||||
emb.getData(data + 2U);
|
||||
|
|
|
|||
|
|
@ -79,6 +79,7 @@ private:
|
|||
CDMRLC* m_netLC;
|
||||
unsigned char m_rfSeqNo;
|
||||
unsigned char m_rfN;
|
||||
unsigned char m_lastrfN;
|
||||
unsigned char m_netN;
|
||||
CTimer m_networkWatchdog;
|
||||
CTimer m_rfTimeoutTimer;
|
||||
|
|
|
|||
|
|
@ -26,6 +26,7 @@
|
|||
#include <cstdio>
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
#include <cstdlib>
|
||||
|
||||
const unsigned int BUFFER_LENGTH = 100U;
|
||||
|
||||
|
|
|
|||
|
|
@ -25,9 +25,11 @@ const unsigned char MODE_DMR = 2U;
|
|||
const unsigned char MODE_YSF = 3U;
|
||||
const unsigned char MODE_P25 = 4U;
|
||||
const unsigned char MODE_NXDN = 5U;
|
||||
const unsigned char MODE_POCSAG = 6U;
|
||||
const unsigned char MODE_CW = 98U;
|
||||
const unsigned char MODE_LOCKOUT = 99U;
|
||||
const unsigned char MODE_ERROR = 100U;
|
||||
const unsigned char MODE_QUIT = 110U;
|
||||
|
||||
const unsigned char TAG_HEADER = 0x00U;
|
||||
const unsigned char TAG_DATA = 0x01U;
|
||||
|
|
@ -41,6 +43,7 @@ enum HW_TYPE {
|
|||
HWT_MMDVM_HS_HAT,
|
||||
HWT_MMDVM_HS_DUAL_HAT,
|
||||
HWT_NANO_HOTSPOT,
|
||||
HWT_NANO_DV,
|
||||
HWT_MMDVM_HS,
|
||||
HWT_UNKNOWN
|
||||
};
|
||||
|
|
|
|||
208
Display.cpp
208
Display.cpp
|
|
@ -18,8 +18,25 @@
|
|||
|
||||
#include "Display.h"
|
||||
#include "Defines.h"
|
||||
#include "SerialController.h"
|
||||
#include "ModemSerialPort.h"
|
||||
#include "NullDisplay.h"
|
||||
#include "TFTSerial.h"
|
||||
#include "LCDproc.h"
|
||||
#include "Nextion.h"
|
||||
#include "Conf.h"
|
||||
#include "Modem.h"
|
||||
#include "UMP.h"
|
||||
#include "Log.h"
|
||||
|
||||
#if defined(HD44780)
|
||||
#include "HD44780.h"
|
||||
#endif
|
||||
|
||||
#if defined(OLED)
|
||||
#include "OLED.h"
|
||||
#endif
|
||||
|
||||
#include <cstdio>
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
|
|
@ -71,6 +88,17 @@ void CDisplay::setError(const char* text)
|
|||
setErrorInt(text);
|
||||
}
|
||||
|
||||
void CDisplay::setQuit()
|
||||
{
|
||||
m_timer1.stop();
|
||||
m_timer2.stop();
|
||||
|
||||
m_mode1 = MODE_QUIT;
|
||||
m_mode2 = MODE_QUIT;
|
||||
|
||||
setQuitInt();
|
||||
}
|
||||
|
||||
void CDisplay::writeDStar(const char* my1, const char* my2, const char* your, const char* type, const char* reflector)
|
||||
{
|
||||
assert(my1 != NULL);
|
||||
|
|
@ -298,6 +326,25 @@ void CDisplay::clearNXDN()
|
|||
}
|
||||
}
|
||||
|
||||
void CDisplay::writePOCSAG(uint32_t ric, const std::string& message)
|
||||
{
|
||||
m_timer1.start();
|
||||
m_mode1 = MODE_POCSAG;
|
||||
|
||||
writePOCSAGInt(ric, message);
|
||||
}
|
||||
|
||||
void CDisplay::clearPOCSAG()
|
||||
{
|
||||
if (m_timer1.hasExpired()) {
|
||||
clearPOCSAGInt();
|
||||
m_timer1.stop();
|
||||
m_mode1 = MODE_IDLE;
|
||||
} else {
|
||||
m_mode1 = MODE_POCSAG;
|
||||
}
|
||||
}
|
||||
|
||||
void CDisplay::writeCW()
|
||||
{
|
||||
m_timer1.start();
|
||||
|
|
@ -336,6 +383,11 @@ void CDisplay::clock(unsigned int ms)
|
|||
m_mode1 = MODE_IDLE;
|
||||
m_timer1.stop();
|
||||
break;
|
||||
case MODE_POCSAG:
|
||||
clearPOCSAGInt();
|
||||
m_mode1 = MODE_IDLE;
|
||||
m_timer1.stop();
|
||||
break;
|
||||
case MODE_CW:
|
||||
clearCWInt();
|
||||
m_mode1 = MODE_IDLE;
|
||||
|
|
@ -406,3 +458,159 @@ void CDisplay::writeNXDNRSSIInt(unsigned char rssi)
|
|||
void CDisplay::writeNXDNBERInt(float ber)
|
||||
{
|
||||
}
|
||||
|
||||
/* Factory method extracted from MMDVMHost.cpp - BG5HHP */
|
||||
CDisplay* CDisplay::createDisplay(const CConf& conf, CUMP* ump, CModem* modem)
|
||||
{
|
||||
CDisplay *display = NULL;
|
||||
|
||||
std::string type = conf.getDisplay();
|
||||
unsigned int dmrid = conf.getDMRId();
|
||||
|
||||
LogInfo("Display Parameters");
|
||||
LogInfo(" Type: %s", type.c_str());
|
||||
|
||||
if (type == "TFT Serial") {
|
||||
std::string port = conf.getTFTSerialPort();
|
||||
unsigned int brightness = conf.getTFTSerialBrightness();
|
||||
|
||||
LogInfo(" Port: %s", port.c_str());
|
||||
LogInfo(" Brightness: %u", brightness);
|
||||
|
||||
ISerialPort* serial = NULL;
|
||||
if (port == "modem")
|
||||
serial = new CModemSerialPort(modem);
|
||||
else
|
||||
serial = new CSerialController(port, SERIAL_9600);
|
||||
|
||||
display = new CTFTSerial(conf.getCallsign(), dmrid, serial, brightness);
|
||||
} else if (type == "Nextion") {
|
||||
std::string port = conf.getNextionPort();
|
||||
unsigned int brightness = conf.getNextionBrightness();
|
||||
bool displayClock = conf.getNextionDisplayClock();
|
||||
bool utc = conf.getNextionUTC();
|
||||
unsigned int idleBrightness = conf.getNextionIdleBrightness();
|
||||
unsigned int screenLayout = conf.getNextionScreenLayout();
|
||||
|
||||
LogInfo(" Port: %s", port.c_str());
|
||||
LogInfo(" Brightness: %u", brightness);
|
||||
LogInfo(" Clock Display: %s", displayClock ? "yes" : "no");
|
||||
if (displayClock)
|
||||
LogInfo(" Display UTC: %s", utc ? "yes" : "no");
|
||||
LogInfo(" Idle Brightness: %u", idleBrightness);
|
||||
|
||||
switch (screenLayout) {
|
||||
case 0U:
|
||||
LogInfo(" Screen Layout: G4KLX (Default)");
|
||||
break;
|
||||
case 2U:
|
||||
LogInfo(" Screen Layout: ON7LDS");
|
||||
break;
|
||||
case 3U:
|
||||
LogInfo(" Screen Layout: DIY by ON7LDS");
|
||||
break;
|
||||
case 4U:
|
||||
LogInfo(" Screen Layout: DIY by ON7LDS (High speed)");
|
||||
break;
|
||||
default:
|
||||
LogInfo(" Screen Layout: %u (Unknown)", screenLayout);
|
||||
break;
|
||||
}
|
||||
|
||||
if (port == "modem") {
|
||||
ISerialPort* serial = new CModemSerialPort(modem);
|
||||
display = new CNextion(conf.getCallsign(), dmrid, serial, brightness, displayClock, utc, idleBrightness, screenLayout);
|
||||
} else if (port == "ump") {
|
||||
if (ump != NULL)
|
||||
display = new CNextion(conf.getCallsign(), dmrid, ump, brightness, displayClock, utc, idleBrightness, screenLayout);
|
||||
else
|
||||
display = new CNullDisplay;
|
||||
} else {
|
||||
SERIAL_SPEED baudrate = SERIAL_9600;
|
||||
if (screenLayout==4U)
|
||||
baudrate = SERIAL_115200;
|
||||
ISerialPort* serial = new CSerialController(port, baudrate);
|
||||
display = new CNextion(conf.getCallsign(), dmrid, serial, brightness, displayClock, utc, idleBrightness, screenLayout);
|
||||
}
|
||||
} else if (type == "LCDproc") {
|
||||
std::string address = conf.getLCDprocAddress();
|
||||
unsigned int port = conf.getLCDprocPort();
|
||||
unsigned int localPort = conf.getLCDprocLocalPort();
|
||||
bool displayClock = conf.getLCDprocDisplayClock();
|
||||
bool utc = conf.getLCDprocUTC();
|
||||
bool dimOnIdle = conf.getLCDprocDimOnIdle();
|
||||
|
||||
LogInfo(" Address: %s", address.c_str());
|
||||
LogInfo(" Port: %u", port);
|
||||
|
||||
if (localPort == 0 )
|
||||
LogInfo(" Local Port: random");
|
||||
else
|
||||
LogInfo(" Local Port: %u", localPort);
|
||||
|
||||
LogInfo(" Dim Display on Idle: %s", dimOnIdle ? "yes" : "no");
|
||||
LogInfo(" Clock Display: %s", displayClock ? "yes" : "no");
|
||||
|
||||
if (displayClock)
|
||||
LogInfo(" Display UTC: %s", utc ? "yes" : "no");
|
||||
|
||||
display = new CLCDproc(address.c_str(), port, localPort, conf.getCallsign(), dmrid, displayClock, utc, conf.getDuplex(), dimOnIdle);
|
||||
#if defined(HD44780)
|
||||
} else if (type == "HD44780") {
|
||||
unsigned int rows = conf.getHD44780Rows();
|
||||
unsigned int columns = conf.getHD44780Columns();
|
||||
std::vector<unsigned int> pins = conf.getHD44780Pins();
|
||||
unsigned int i2cAddress = conf.getHD44780i2cAddress();
|
||||
bool pwm = conf.getHD44780PWM();
|
||||
unsigned int pwmPin = conf.getHD44780PWMPin();
|
||||
unsigned int pwmBright = conf.getHD44780PWMBright();
|
||||
unsigned int pwmDim = conf.getHD44780PWMDim();
|
||||
bool displayClock = conf.getHD44780DisplayClock();
|
||||
bool utc = conf.getHD44780UTC();
|
||||
|
||||
if (pins.size() == 6U) {
|
||||
LogInfo(" Rows: %u", rows);
|
||||
LogInfo(" Columns: %u", columns);
|
||||
|
||||
#if defined(ADAFRUIT_DISPLAY) || defined(PCF8574_DISPLAY)
|
||||
LogInfo(" Device Address: %#x", i2cAddress);
|
||||
#else
|
||||
LogInfo(" Pins: %u,%u,%u,%u,%u,%u", pins.at(0U), pins.at(1U), pins.at(2U), pins.at(3U), pins.at(4U), pins.at(5U));
|
||||
#endif
|
||||
|
||||
LogInfo(" PWM Backlight: %s", pwm ? "yes" : "no");
|
||||
if (pwm) {
|
||||
LogInfo(" PWM Pin: %u", pwmPin);
|
||||
LogInfo(" PWM Bright: %u", pwmBright);
|
||||
LogInfo(" PWM Dim: %u", pwmDim);
|
||||
}
|
||||
|
||||
LogInfo(" Clock Display: %s", displayClock ? "yes" : "no");
|
||||
if (displayClock)
|
||||
LogInfo(" Display UTC: %s", utc ? "yes" : "no");
|
||||
|
||||
display = new CHD44780(rows, columns, conf.getCallsign(), dmrid, pins, i2cAddress, pwm, pwmPin, pwmBright, pwmDim, displayClock, utc, conf.getDuplex());
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(OLED)
|
||||
} else if (type == "OLED") {
|
||||
unsigned char type = conf.getOLEDType();
|
||||
unsigned char brightness = conf.getOLEDBrightness();
|
||||
bool invert = conf.getOLEDInvert();
|
||||
bool scroll = conf.getOLEDScroll();
|
||||
display = new COLED(type, brightness, invert, scroll, conf.getDMRNetworkSlot1(), conf.getDMRNetworkSlot2());
|
||||
#endif
|
||||
} else {
|
||||
LogWarning("No valid display found, disabling");
|
||||
display = new CNullDisplay;
|
||||
}
|
||||
|
||||
bool ret = display->open();
|
||||
if (!ret) {
|
||||
delete display;
|
||||
display = new CNullDisplay;
|
||||
}
|
||||
|
||||
return display;
|
||||
}
|
||||
|
|
|
|||
17
Display.h
17
Display.h
|
|
@ -23,6 +23,12 @@
|
|||
|
||||
#include <string>
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
class CConf;
|
||||
class CModem;
|
||||
class CUMP;
|
||||
|
||||
class CDisplay
|
||||
{
|
||||
public:
|
||||
|
|
@ -34,6 +40,7 @@ public:
|
|||
void setIdle();
|
||||
void setLockout();
|
||||
void setError(const char* text);
|
||||
void setQuit();
|
||||
|
||||
void writeDStar(const char* my1, const char* my2, const char* your, const char* type, const char* reflector);
|
||||
void writeDStarRSSI(unsigned char rssi);
|
||||
|
|
@ -61,17 +68,22 @@ public:
|
|||
void writeNXDNBER(float ber);
|
||||
void clearNXDN();
|
||||
|
||||
void writePOCSAG(uint32_t ric, const std::string& message);
|
||||
void clearPOCSAG();
|
||||
|
||||
void writeCW();
|
||||
void clearCW();
|
||||
|
||||
virtual void close() = 0;
|
||||
|
||||
void clock(unsigned int ms);
|
||||
|
||||
static CDisplay* createDisplay(const CConf& conf, CUMP* ump, CModem* modem);
|
||||
|
||||
protected:
|
||||
virtual void setIdleInt() = 0;
|
||||
virtual void setLockoutInt() = 0;
|
||||
virtual void setErrorInt(const char* text) = 0;
|
||||
virtual void setQuitInt() = 0;
|
||||
|
||||
virtual void writeDStarInt(const char* my1, const char* my2, const char* your, const char* type, const char* reflector) = 0;
|
||||
virtual void writeDStarRSSIInt(unsigned char rssi);
|
||||
|
|
@ -99,6 +111,9 @@ protected:
|
|||
virtual void writeNXDNBERInt(float ber);
|
||||
virtual void clearNXDNInt() = 0;
|
||||
|
||||
virtual void writePOCSAGInt(uint32_t ric, const std::string& message) = 0;
|
||||
virtual void clearPOCSAGInt() = 0;
|
||||
|
||||
virtual void writeCWInt() = 0;
|
||||
virtual void clearCWInt() = 0;
|
||||
|
||||
|
|
|
|||
37
HD44780.cpp
37
HD44780.cpp
|
|
@ -374,6 +374,31 @@ void CHD44780::setLockoutInt()
|
|||
m_dmr = false;
|
||||
}
|
||||
|
||||
void CHD44780::setQuitInt()
|
||||
{
|
||||
#ifdef ADAFRUIT_DISPLAY
|
||||
adafruitLCDColour(AC_RED);
|
||||
#endif
|
||||
|
||||
m_clockDisplayTimer.stop(); // Stop the clock display
|
||||
::lcdClear(m_fd);
|
||||
|
||||
if (m_pwm) {
|
||||
if (m_pwmPin != 1U)
|
||||
::softPwmWrite(m_pwmPin, m_pwmBright);
|
||||
else
|
||||
::pwmWrite(m_pwmPin, (m_pwmBright / 100) * 1024);
|
||||
}
|
||||
|
||||
::lcdPosition(m_fd, 0, 0);
|
||||
::lcdPuts(m_fd, "MMDVM");
|
||||
|
||||
::lcdPosition(m_fd, 0, 1);
|
||||
::lcdPuts(m_fd, "STOPPED");
|
||||
|
||||
m_dmr = false;
|
||||
}
|
||||
|
||||
void CHD44780::writeDStarInt(const char* my1, const char* my2, const char* your, const char* type, const char* reflector)
|
||||
{
|
||||
assert(my1 != NULL);
|
||||
|
|
@ -995,6 +1020,18 @@ void CHD44780::clearNXDNInt()
|
|||
}
|
||||
}
|
||||
|
||||
void CHD44780::writePOCSAGInt(uint32_t ric, const std::string& message)
|
||||
{
|
||||
::lcdPosition(m_fd, m_cols - 5, m_rows - 1);
|
||||
::lcdPuts(m_fd, "POCSAG TX");
|
||||
}
|
||||
|
||||
void CHD44780::clearPOCSAGInt()
|
||||
{
|
||||
::lcdPosition(m_fd, m_cols - 5, m_rows - 1);
|
||||
::lcdPuts(m_fd, " Idle");
|
||||
}
|
||||
|
||||
void CHD44780::writeCWInt()
|
||||
{
|
||||
::lcdPosition(m_fd, m_cols - 5, m_rows - 1);
|
||||
|
|
|
|||
|
|
@ -100,6 +100,7 @@ protected:
|
|||
virtual void setIdleInt();
|
||||
virtual void setErrorInt(const char* text);
|
||||
virtual void setLockoutInt();
|
||||
virtual void setQuitInt();
|
||||
|
||||
virtual void writeDStarInt(const char* my1, const char* my2, const char* your, const char* type, const char* reflector);
|
||||
virtual void writeDStarRSSIInt(unsigned char rssi);
|
||||
|
|
@ -121,6 +122,9 @@ protected:
|
|||
virtual void writeNXDNRSSIInt(unsigned char rssi);
|
||||
virtual void clearNXDNInt();
|
||||
|
||||
virtual void writePOCSAGInt(uint32_t ric, const std::string& message);
|
||||
virtual void clearPOCSAGInt();
|
||||
|
||||
virtual void writeCWInt();
|
||||
virtual void clearCWInt();
|
||||
|
||||
|
|
|
|||
165
I2CController.cpp
Normal file
165
I2CController.cpp
Normal file
|
|
@ -0,0 +1,165 @@
|
|||
/*
|
||||
* Copyright (C) 2002-2004,2007-2011,2013,2014-2017 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 1999-2001 by Thomas Sailor HB9JNX
|
||||
*
|
||||
* 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 "I2CController.h"
|
||||
#include "Log.h"
|
||||
|
||||
#include <cstring>
|
||||
#include <cassert>
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
|
||||
#include <setupapi.h>
|
||||
#include <winioctl.h>
|
||||
|
||||
CI2CController::CI2CController(const std::string& device, SERIAL_SPEED speed, unsigned int address, bool assertRTS) :
|
||||
CSerialController(device, speed, assertRTS),
|
||||
m_address(address)
|
||||
{
|
||||
}
|
||||
|
||||
CI2CController::~CI2CController()
|
||||
{
|
||||
}
|
||||
|
||||
bool CI2CController::open()
|
||||
{
|
||||
return CSerialController::open();
|
||||
}
|
||||
|
||||
int CI2CController::read(unsigned char* buffer, unsigned int length)
|
||||
{
|
||||
return CSerialController::read(buffer, length);
|
||||
}
|
||||
|
||||
int CI2CController::write(const unsigned char* buffer, unsigned int length)
|
||||
{
|
||||
return CSerialController::write(buffer, length);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/stat.h>
|
||||
#include <cerrno>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <termios.h>
|
||||
#if !defined(__APPLE__)
|
||||
#include <linux/i2c-dev.h>
|
||||
#endif
|
||||
|
||||
CI2CController::CI2CController(const std::string& device, SERIAL_SPEED speed, unsigned int address, bool assertRTS) :
|
||||
CSerialController(device, speed, assertRTS),
|
||||
m_address(address)
|
||||
{
|
||||
}
|
||||
|
||||
CI2CController::~CI2CController()
|
||||
{
|
||||
}
|
||||
|
||||
bool CI2CController::open()
|
||||
{
|
||||
assert(m_fd == -1);
|
||||
|
||||
#if !defined(__APPLE__)
|
||||
m_fd = ::open(m_device.c_str(), O_RDWR);
|
||||
if (m_fd < 0) {
|
||||
LogError("Cannot open device - %s", m_device.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
if (::ioctl(m_fd, I2C_TENBIT, 0) < 0) {
|
||||
LogError("CI2C: failed to set 7bitaddress");
|
||||
::close(m_fd);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (::ioctl(m_fd, I2C_SLAVE, m_address) < 0) {
|
||||
LogError("CI2C: Failed to acquire bus access/talk to slave 0x%02X", m_address);
|
||||
::close(m_fd);
|
||||
return false;
|
||||
}
|
||||
#else
|
||||
#warning "I2C controller does not support OSX"
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
int CI2CController::read(unsigned char* buffer, unsigned int length)
|
||||
{
|
||||
assert(buffer != NULL);
|
||||
assert(m_fd != -1);
|
||||
|
||||
if (length == 0U)
|
||||
return 0;
|
||||
|
||||
unsigned int offset = 0U;
|
||||
|
||||
while (offset < length) {
|
||||
#if !defined(__APPLE__)
|
||||
ssize_t n = ::read(m_fd, buffer + offset, 1U);
|
||||
if (n < 0) {
|
||||
if (errno != EAGAIN) {
|
||||
LogError("Error returned from read(), errno=%d", errno);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (n > 0)
|
||||
offset += n;
|
||||
#endif
|
||||
}
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
int CI2CController::write(const unsigned char* buffer, unsigned int length)
|
||||
{
|
||||
assert(buffer != NULL);
|
||||
assert(m_fd != -1);
|
||||
|
||||
if (length == 0U)
|
||||
return 0;
|
||||
|
||||
unsigned int ptr = 0U;
|
||||
while (ptr < length) {
|
||||
ssize_t n = 0U;
|
||||
#if !defined(__APPLE__)
|
||||
n = ::write(m_fd, buffer + ptr, 1U);
|
||||
#endif
|
||||
if (n < 0) {
|
||||
if (errno != EAGAIN) {
|
||||
LogError("Error returned from write(), errno=%d", errno);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
if (n > 0)
|
||||
ptr += n;
|
||||
}
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
#endif
|
||||
40
I2CController.h
Normal file
40
I2CController.h
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* Copyright (C) 2002-2004,2007-2009,2011-2013,2015-2017 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 1999-2001 by Thomas Sailor HB9JNX
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef I2CController_H
|
||||
#define I2CController_H
|
||||
|
||||
#include "SerialController.h"
|
||||
|
||||
class CI2CController : public CSerialController {
|
||||
public:
|
||||
CI2CController(const std::string& device, SERIAL_SPEED speed, unsigned int address = 0x22U, bool assertRTS = false);
|
||||
virtual ~CI2CController();
|
||||
|
||||
virtual bool open();
|
||||
|
||||
virtual int read(unsigned char* buffer, unsigned int length);
|
||||
|
||||
virtual int write(const unsigned char* buffer, unsigned int length);
|
||||
|
||||
private:
|
||||
unsigned int m_address;
|
||||
};
|
||||
|
||||
#endif
|
||||
BIN
Images/POCSAG.bmp
Normal file
BIN
Images/POCSAG.bmp
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 659 KiB |
BIN
Images/YSF.bmp
BIN
Images/YSF.bmp
Binary file not shown.
|
Before Width: | Height: | Size: 66 KiB After Width: | Height: | Size: 30 KiB |
25
LCDproc.cpp
25
LCDproc.cpp
|
|
@ -224,6 +224,23 @@ void CLCDproc::setLockoutInt()
|
|||
|
||||
// LED 4 Green 8 Red 128 Yellow 136
|
||||
|
||||
void CLCDproc::setQuitInt()
|
||||
{
|
||||
m_clockDisplayTimer.stop(); // Stop the clock display
|
||||
|
||||
if (m_screensDefined) {
|
||||
socketPrintf(m_socketfd, "screen_set DStar -priority hidden");
|
||||
socketPrintf(m_socketfd, "screen_set DMR -priority hidden");
|
||||
socketPrintf(m_socketfd, "screen_set YSF -priority hidden");
|
||||
socketPrintf(m_socketfd, "screen_set P25 -priority hidden");
|
||||
socketPrintf(m_socketfd, "screen_set NXDN -priority hidden");
|
||||
socketPrintf(m_socketfd, "widget_set Status Status %u %u Stopped", m_cols - 6, m_rows);
|
||||
socketPrintf(m_socketfd, "output 0"); // Clear all LEDs
|
||||
}
|
||||
|
||||
m_dmr = false;
|
||||
}
|
||||
|
||||
void CLCDproc::writeDStarInt(const char* my1, const char* my2, const char* your, const char* type, const char* reflector)
|
||||
{
|
||||
assert(my1 != NULL);
|
||||
|
|
@ -514,6 +531,14 @@ void CLCDproc::clearNXDNInt()
|
|||
socketPrintf(m_socketfd, "output 16"); // Set LED5 color green
|
||||
}
|
||||
|
||||
void CLCDproc::writePOCSAGInt(uint32_t ric, const std::string& message)
|
||||
{
|
||||
}
|
||||
|
||||
void CLCDproc::clearPOCSAGInt()
|
||||
{
|
||||
}
|
||||
|
||||
void CLCDproc::writeCWInt()
|
||||
{
|
||||
}
|
||||
|
|
|
|||
|
|
@ -39,6 +39,8 @@ protected:
|
|||
virtual void setIdleInt();
|
||||
virtual void setErrorInt(const char* text);
|
||||
virtual void setLockoutInt();
|
||||
virtual void setQuitInt();
|
||||
|
||||
|
||||
virtual void writeDStarInt(const char* my1, const char* my2, const char* your, const char* type, const char* reflector);
|
||||
virtual void writeDStarRSSIInt(unsigned char rssi);
|
||||
|
|
@ -60,6 +62,9 @@ protected:
|
|||
virtual void writeNXDNRSSIInt(unsigned char rssi);
|
||||
virtual void clearNXDNInt();
|
||||
|
||||
virtual void writePOCSAGInt(uint32_t ric, const std::string& message);
|
||||
virtual void clearPOCSAGInt();
|
||||
|
||||
virtual void writeCWInt();
|
||||
virtual void clearCWInt();
|
||||
|
||||
|
|
|
|||
18
MMDVM.ini
18
MMDVM.ini
|
|
@ -44,6 +44,8 @@ Time=24
|
|||
# Port=/dev/ttyACM0
|
||||
# Port=/dev/ttyAMA0
|
||||
Port=\\.\COM3
|
||||
Protocol=uart
|
||||
# Address=0x22
|
||||
TXInvert=1
|
||||
RXInvert=0
|
||||
PTTInvert=0
|
||||
|
|
@ -62,6 +64,7 @@ RFLevel=100
|
|||
# YSFTXLevel=50
|
||||
# P25TXLevel=50
|
||||
# NXDNTXLevel=50
|
||||
# POCSAGTXLevel=50
|
||||
RSSIMappingFile=RSSI.dat
|
||||
Trace=0
|
||||
Debug=0
|
||||
|
|
@ -71,6 +74,7 @@ Enable=0
|
|||
RemoteAddress=127.0.0.1
|
||||
RemotePort=40094
|
||||
LocalPort=40095
|
||||
# SendFrameType=0
|
||||
|
||||
[UMP]
|
||||
Enable=0
|
||||
|
|
@ -107,6 +111,7 @@ TXHang=4
|
|||
Enable=1
|
||||
LowDeviation=0
|
||||
SelfOnly=0
|
||||
TXHang=4
|
||||
#DGID=1
|
||||
RemoteGateway=0
|
||||
# ModeHang=10
|
||||
|
|
@ -126,6 +131,10 @@ SelfOnly=0
|
|||
RemoteGateway=0
|
||||
# ModeHang=10
|
||||
|
||||
[POCSAG]
|
||||
Enable=1
|
||||
Frequency=439987500
|
||||
|
||||
[D-Star Network]
|
||||
Enable=1
|
||||
GatewayAddress=127.0.0.1
|
||||
|
|
@ -173,6 +182,15 @@ GatewayPort=14020
|
|||
# ModeHang=3
|
||||
Debug=0
|
||||
|
||||
[POCSAG Network]
|
||||
Enable=1
|
||||
LocalAddress=127.0.0.1
|
||||
LocalPort=3800
|
||||
GatewayAddress=127.0.0.1
|
||||
GatewayPort=4800
|
||||
# ModeHang=3
|
||||
Debug=0
|
||||
|
||||
[TFT Serial]
|
||||
# Port=modem
|
||||
Port=/dev/ttyAMA0
|
||||
|
|
|
|||
456
MMDVMHost.cpp
456
MMDVMHost.cpp
|
|
@ -19,34 +19,24 @@
|
|||
#include "MMDVMHost.h"
|
||||
#include "RSSIInterpolator.h"
|
||||
#include "SerialController.h"
|
||||
#include "ModemSerialPort.h"
|
||||
#include "Version.h"
|
||||
#include "StopWatch.h"
|
||||
#include "Defines.h"
|
||||
#include "DStarControl.h"
|
||||
#include "DMRControl.h"
|
||||
#include "TFTSerial.h"
|
||||
#include "NullDisplay.h"
|
||||
#include "YSFControl.h"
|
||||
#include "P25Control.h"
|
||||
#include "NXDNControl.h"
|
||||
#include "Nextion.h"
|
||||
#include "LCDproc.h"
|
||||
#include "POCSAGControl.h"
|
||||
#include "Thread.h"
|
||||
#include "Log.h"
|
||||
#include "GitVersion.h"
|
||||
|
||||
#if defined(HD44780)
|
||||
#include "HD44780.h"
|
||||
#endif
|
||||
|
||||
#if defined(OLED)
|
||||
#include "OLED.h"
|
||||
#endif
|
||||
|
||||
#include <cstdio>
|
||||
#include <vector>
|
||||
|
||||
#include <cstdlib>
|
||||
|
||||
#if !defined(_WIN32) && !defined(_WIN64)
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
|
|
@ -134,6 +124,7 @@ m_dmrNetwork(NULL),
|
|||
m_ysfNetwork(NULL),
|
||||
m_p25Network(NULL),
|
||||
m_nxdnNetwork(NULL),
|
||||
m_pocsagNetwork(NULL),
|
||||
m_display(NULL),
|
||||
m_ump(NULL),
|
||||
m_mode(MODE_IDLE),
|
||||
|
|
@ -147,6 +138,7 @@ m_dmrNetModeHang(3U),
|
|||
m_ysfNetModeHang(3U),
|
||||
m_p25NetModeHang(3U),
|
||||
m_nxdnNetModeHang(3U),
|
||||
m_pocsagNetModeHang(3U),
|
||||
m_modeTimer(1000U),
|
||||
m_dmrTXTimer(1000U),
|
||||
m_cwIdTimer(1000U),
|
||||
|
|
@ -157,6 +149,7 @@ m_dmrEnabled(false),
|
|||
m_ysfEnabled(false),
|
||||
m_p25Enabled(false),
|
||||
m_nxdnEnabled(false),
|
||||
m_pocsagEnabled(false),
|
||||
m_cwIdTime(0U),
|
||||
m_dmrLookup(NULL),
|
||||
m_nxdnLookup(NULL),
|
||||
|
|
@ -178,19 +171,13 @@ int CMMDVMHost::run()
|
|||
return 1;
|
||||
}
|
||||
|
||||
ret = ::LogInitialise(m_conf.getLogFilePath(), m_conf.getLogFileRoot(), m_conf.getLogFileLevel(), m_conf.getLogDisplayLevel());
|
||||
if (!ret) {
|
||||
::fprintf(stderr, "MMDVMHost: unable to open the log file\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
#if !defined(_WIN32) && !defined(_WIN64)
|
||||
bool m_daemon = m_conf.getDaemon();
|
||||
if (m_daemon) {
|
||||
// Create new process
|
||||
pid_t pid = ::fork();
|
||||
if (pid == -1) {
|
||||
LogWarning("Couldn't fork() , exiting");
|
||||
::fprintf(stderr, "Couldn't fork() , exiting\n");
|
||||
return -1;
|
||||
} else if (pid != 0) {
|
||||
exit(EXIT_SUCCESS);
|
||||
|
|
@ -198,56 +185,66 @@ int CMMDVMHost::run()
|
|||
|
||||
// Create new session and process group
|
||||
if (::setsid() == -1){
|
||||
LogWarning("Couldn't setsid(), exiting");
|
||||
::fprintf(stderr, "Couldn't setsid(), exiting\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// Set the working directory to the root directory
|
||||
if (::chdir("/") == -1){
|
||||
LogWarning("Couldn't cd /, exiting");
|
||||
::fprintf(stderr, "Couldn't cd /, exiting\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
::close(STDIN_FILENO);
|
||||
::close(STDOUT_FILENO);
|
||||
::close(STDERR_FILENO);
|
||||
|
||||
#if !defined(HD44780) && !defined(OLED)
|
||||
//If we are currently root...
|
||||
#if !defined(HD44780) && !defined(OLED) && !defined(_OPENWRT)
|
||||
// If we are currently root...
|
||||
if (getuid() == 0) {
|
||||
struct passwd* user = ::getpwnam("mmdvm");
|
||||
if (user == NULL) {
|
||||
LogError("Could not get the mmdvm user, exiting");
|
||||
::fprintf(stderr, "Could not get the mmdvm user, exiting\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
uid_t mmdvm_uid = user->pw_uid;
|
||||
gid_t mmdvm_gid = user->pw_gid;
|
||||
|
||||
//Set user and group ID's to mmdvm:mmdvm
|
||||
// Set user and group ID's to mmdvm:mmdvm
|
||||
if (::setgid(mmdvm_gid) != 0) {
|
||||
LogWarning("Could not set mmdvm GID, exiting");
|
||||
::fprintf(stderr, "Could not set mmdvm GID, exiting\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (::setuid(mmdvm_uid) != 0) {
|
||||
LogWarning("Could not set mmdvm UID, exiting");
|
||||
::fprintf(stderr, "Could not set mmdvm UID, exiting\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
//Double check it worked (AKA Paranoia)
|
||||
// Double check it worked (AKA Paranoia)
|
||||
if (::setuid(0) != -1){
|
||||
LogWarning("It's possible to regain root - something is wrong!, exiting");
|
||||
::fprintf(stderr, "It's possible to regain root - something is wrong!, exiting\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
#else
|
||||
LogWarning("Dropping root permissions in daemon mode is disabled with HD44780 display");
|
||||
::fprintf(stderr, "Dropping root permissions in daemon mode is disabled.\n");
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
ret = ::LogInitialise(m_conf.getLogFilePath(), m_conf.getLogFileRoot(), m_conf.getLogFileLevel(), m_conf.getLogDisplayLevel());
|
||||
if (!ret) {
|
||||
::fprintf(stderr, "MMDVMHost: unable to open the log file\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
#if !defined(_WIN32) && !defined(_WIN64)
|
||||
if (m_daemon) {
|
||||
::close(STDIN_FILENO);
|
||||
::close(STDOUT_FILENO);
|
||||
::close(STDERR_FILENO);
|
||||
}
|
||||
#endif
|
||||
|
||||
LogInfo(HEADER1);
|
||||
LogInfo(HEADER2);
|
||||
LogInfo(HEADER3);
|
||||
|
|
@ -276,7 +273,7 @@ int CMMDVMHost::run()
|
|||
}
|
||||
}
|
||||
|
||||
createDisplay();
|
||||
m_display = CDisplay::createDisplay(m_conf,m_ump,m_modem);
|
||||
|
||||
if (m_dstarEnabled && m_conf.getDStarNetworkEnabled()) {
|
||||
ret = createDStarNetwork();
|
||||
|
|
@ -308,19 +305,28 @@ int CMMDVMHost::run()
|
|||
return 1;
|
||||
}
|
||||
|
||||
if (m_pocsagEnabled && m_conf.getPOCSAGNetworkEnabled()) {
|
||||
ret = createPOCSAGNetwork();
|
||||
if (!ret)
|
||||
return 1;
|
||||
}
|
||||
|
||||
in_addr transparentAddress;
|
||||
unsigned int transparentPort = 0U;
|
||||
CUDPSocket* transparentSocket = NULL;
|
||||
|
||||
unsigned int sendFrameType = 0U;
|
||||
if (m_conf.getTransparentEnabled()) {
|
||||
std::string remoteAddress = m_conf.getTransparentRemoteAddress();
|
||||
unsigned int remotePort = m_conf.getTransparentRemotePort();
|
||||
unsigned int localPort = m_conf.getTransparentLocalPort();
|
||||
sendFrameType = m_conf.getTransparentSendFrameType();
|
||||
|
||||
LogInfo("Transparent Data");
|
||||
LogInfo(" Remote Address: %s", remoteAddress.c_str());
|
||||
LogInfo(" Remote Port: %u", remotePort);
|
||||
LogInfo(" Local Port: %u", localPort);
|
||||
LogInfo(" Send Frame Type: %u", sendFrameType);
|
||||
|
||||
transparentAddress = CUDPSocket::lookup(remoteAddress);
|
||||
transparentPort = remotePort;
|
||||
|
|
@ -440,7 +446,7 @@ int CMMDVMHost::run()
|
|||
LogInfo(" Embedded LC Only: %s", embeddedLCOnly ? "yes" : "no");
|
||||
LogInfo(" Dump Talker Alias Data: %s", dumpTAData ? "yes" : "no");
|
||||
LogInfo(" Prefixes: %u", prefixes.size());
|
||||
|
||||
|
||||
if (blackList.size() > 0U)
|
||||
LogInfo(" Source ID Black List: %u", blackList.size());
|
||||
if (whiteList.size() > 0U)
|
||||
|
|
@ -474,16 +480,18 @@ int CMMDVMHost::run()
|
|||
|
||||
CYSFControl* ysf = NULL;
|
||||
if (m_ysfEnabled) {
|
||||
bool lowDeviation = m_conf.getFusionLowDeviation();
|
||||
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();
|
||||
bool lowDeviation = m_conf.getFusionLowDeviation();
|
||||
bool remoteGateway = m_conf.getFusionRemoteGateway();
|
||||
unsigned int txHang = m_conf.getFusionTXHang();
|
||||
bool selfOnly = m_conf.getFusionSelfOnly();
|
||||
bool sqlEnabled = m_conf.getFusionSQLEnabled();
|
||||
unsigned char sql = m_conf.getFusionSQL();
|
||||
m_ysfRFModeHang = m_conf.getFusionModeHang();
|
||||
|
||||
LogInfo("YSF RF Parameters");
|
||||
LogInfo(" Low Deviation: %s", lowDeviation ? "yes" : "no");
|
||||
LogInfo(" Remote Gateway: %s", remoteGateway ? "yes" : "no");
|
||||
LogInfo(" TX Hang: %us", txHang);
|
||||
LogInfo(" Self Only: %s", selfOnly ? "yes" : "no");
|
||||
LogInfo(" DSQ: %s", sqlEnabled ? "yes" : "no");
|
||||
if (sqlEnabled)
|
||||
|
|
@ -543,6 +551,20 @@ int CMMDVMHost::run()
|
|||
nxdn = new CNXDNControl(ran, id, selfOnly, m_nxdnNetwork, m_display, m_timeout, m_duplex, remoteGateway, m_nxdnLookup, rssi);
|
||||
}
|
||||
|
||||
CTimer pocsagTimer(1000U, 30U);
|
||||
|
||||
CPOCSAGControl* pocsag = NULL;
|
||||
if (m_pocsagEnabled) {
|
||||
unsigned int frequency = m_conf.getPOCSAGFrequency();
|
||||
|
||||
LogInfo("POCSAG RF Parameters");
|
||||
LogInfo(" Frequency: %uHz", frequency);
|
||||
|
||||
pocsag = new CPOCSAGControl(m_pocsagNetwork, m_display);
|
||||
|
||||
pocsagTimer.start();
|
||||
}
|
||||
|
||||
setMode(MODE_IDLE);
|
||||
|
||||
LogMessage("MMDVMHost-%s is running", VERSION);
|
||||
|
|
@ -841,12 +863,31 @@ int CMMDVMHost::run()
|
|||
}
|
||||
}
|
||||
|
||||
if (pocsag != NULL) {
|
||||
ret = m_modem->hasPOCSAGSpace();
|
||||
if (ret) {
|
||||
len = pocsag->readModem(data);
|
||||
if (len > 0U) {
|
||||
if (m_mode == MODE_IDLE) {
|
||||
m_modeTimer.setTimeout(m_pocsagNetModeHang);
|
||||
setMode(MODE_POCSAG);
|
||||
}
|
||||
if (m_mode == MODE_POCSAG) {
|
||||
m_modem->writePOCSAGData(data, len);
|
||||
m_modeTimer.start();
|
||||
} else if (m_mode != MODE_LOCKOUT) {
|
||||
LogWarning("POCSAG data received when in mode %u", m_mode);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (transparentSocket != NULL) {
|
||||
in_addr address;
|
||||
unsigned int port = 0U;
|
||||
len = transparentSocket->read(data, 200U, address, port);
|
||||
if (len > 0U)
|
||||
m_modem->writeTransparentData(data, len);
|
||||
m_modem->writeTransparentData(data, len, sendFrameType);
|
||||
}
|
||||
|
||||
unsigned int ms = stopWatch.elapsed();
|
||||
|
|
@ -867,6 +908,8 @@ int CMMDVMHost::run()
|
|||
p25->clock(ms);
|
||||
if (nxdn != NULL)
|
||||
nxdn->clock(ms);
|
||||
if (pocsag != NULL)
|
||||
pocsag->clock(ms);
|
||||
|
||||
if (m_dstarNetwork != NULL)
|
||||
m_dstarNetwork->clock(ms);
|
||||
|
|
@ -878,6 +921,8 @@ int CMMDVMHost::run()
|
|||
m_p25Network->clock(ms);
|
||||
if (m_nxdnNetwork != NULL)
|
||||
m_nxdnNetwork->clock(ms);
|
||||
if (m_pocsagNetwork != NULL)
|
||||
m_pocsagNetwork->clock(ms);
|
||||
|
||||
m_cwIdTimer.clock(ms);
|
||||
if (m_cwIdTimer.isRunning() && m_cwIdTimer.hasExpired()) {
|
||||
|
|
@ -912,6 +957,13 @@ int CMMDVMHost::run()
|
|||
m_dmrTXTimer.stop();
|
||||
}
|
||||
|
||||
pocsagTimer.clock(ms);
|
||||
if (pocsagTimer.isRunning() && pocsagTimer.hasExpired()) {
|
||||
assert(m_pocsagNetwork != NULL);
|
||||
m_pocsagNetwork->enable(m_mode == MODE_IDLE || m_mode == MODE_POCSAG);
|
||||
pocsagTimer.start();
|
||||
}
|
||||
|
||||
if (m_ump != NULL)
|
||||
m_ump->clock(ms);
|
||||
|
||||
|
|
@ -919,7 +971,7 @@ int CMMDVMHost::run()
|
|||
CThread::sleep(5U);
|
||||
}
|
||||
|
||||
setMode(MODE_IDLE);
|
||||
setMode(MODE_QUIT);
|
||||
|
||||
m_modem->close();
|
||||
delete m_modem;
|
||||
|
|
@ -963,6 +1015,11 @@ int CMMDVMHost::run()
|
|||
delete m_nxdnNetwork;
|
||||
}
|
||||
|
||||
if (m_pocsagNetwork != NULL) {
|
||||
m_pocsagNetwork->close();
|
||||
delete m_pocsagNetwork;
|
||||
}
|
||||
|
||||
if (transparentSocket != NULL) {
|
||||
transparentSocket->close();
|
||||
delete transparentSocket;
|
||||
|
|
@ -973,39 +1030,48 @@ int CMMDVMHost::run()
|
|||
delete ysf;
|
||||
delete p25;
|
||||
delete nxdn;
|
||||
delete pocsag;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool CMMDVMHost::createModem()
|
||||
{
|
||||
std::string port = m_conf.getModemPort();
|
||||
bool rxInvert = m_conf.getModemRXInvert();
|
||||
bool txInvert = m_conf.getModemTXInvert();
|
||||
bool pttInvert = m_conf.getModemPTTInvert();
|
||||
unsigned int txDelay = m_conf.getModemTXDelay();
|
||||
unsigned int dmrDelay = m_conf.getModemDMRDelay();
|
||||
float rxLevel = m_conf.getModemRXLevel();
|
||||
float cwIdTXLevel = m_conf.getModemCWIdTXLevel();
|
||||
float dstarTXLevel = m_conf.getModemDStarTXLevel();
|
||||
float dmrTXLevel = m_conf.getModemDMRTXLevel();
|
||||
float ysfTXLevel = m_conf.getModemYSFTXLevel();
|
||||
float p25TXLevel = m_conf.getModemP25TXLevel();
|
||||
float nxdnTXLevel = m_conf.getModemNXDNTXLevel();
|
||||
bool trace = m_conf.getModemTrace();
|
||||
bool debug = m_conf.getModemDebug();
|
||||
unsigned int colorCode = m_conf.getDMRColorCode();
|
||||
bool lowDeviation = m_conf.getFusionLowDeviation();
|
||||
unsigned int rxFrequency = m_conf.getRXFrequency();
|
||||
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();
|
||||
float rfLevel = m_conf.getModemRFLevel();
|
||||
std::string port = m_conf.getModemPort();
|
||||
std::string protocol = m_conf.getModemProtocol();
|
||||
unsigned int address = m_conf.getModemAddress();
|
||||
bool rxInvert = m_conf.getModemRXInvert();
|
||||
bool txInvert = m_conf.getModemTXInvert();
|
||||
bool pttInvert = m_conf.getModemPTTInvert();
|
||||
unsigned int txDelay = m_conf.getModemTXDelay();
|
||||
unsigned int dmrDelay = m_conf.getModemDMRDelay();
|
||||
float rxLevel = m_conf.getModemRXLevel();
|
||||
float cwIdTXLevel = m_conf.getModemCWIdTXLevel();
|
||||
float dstarTXLevel = m_conf.getModemDStarTXLevel();
|
||||
float dmrTXLevel = m_conf.getModemDMRTXLevel();
|
||||
float ysfTXLevel = m_conf.getModemYSFTXLevel();
|
||||
float p25TXLevel = m_conf.getModemP25TXLevel();
|
||||
float nxdnTXLevel = m_conf.getModemNXDNTXLevel();
|
||||
float pocsagTXLevel = m_conf.getModemPOCSAGTXLevel();
|
||||
bool trace = m_conf.getModemTrace();
|
||||
bool debug = m_conf.getModemDebug();
|
||||
unsigned int colorCode = m_conf.getDMRColorCode();
|
||||
bool lowDeviation = m_conf.getFusionLowDeviation();
|
||||
unsigned int txHang = m_conf.getFusionTXHang();
|
||||
unsigned int rxFrequency = m_conf.getRXFrequency();
|
||||
unsigned int txFrequency = m_conf.getTXFrequency();
|
||||
unsigned int pocsagFrequency = m_conf.getPOCSAGFrequency();
|
||||
int rxOffset = m_conf.getModemRXOffset();
|
||||
int txOffset = m_conf.getModemTXOffset();
|
||||
int rxDCOffset = m_conf.getModemRXDCOffset();
|
||||
int txDCOffset = m_conf.getModemTXDCOffset();
|
||||
float rfLevel = m_conf.getModemRFLevel();
|
||||
|
||||
LogInfo("Modem Parameters");
|
||||
LogInfo(" Port: %s", port.c_str());
|
||||
LogInfo(" Protocol: %s", protocol.c_str());
|
||||
if (protocol == "i2c")
|
||||
LogInfo(" i2c Address: %02X", address);
|
||||
LogInfo(" RX Invert: %s", rxInvert ? "yes" : "no");
|
||||
LogInfo(" TX Invert: %s", txInvert ? "yes" : "no");
|
||||
LogInfo(" PTT Invert: %s", pttInvert ? "yes" : "no");
|
||||
|
|
@ -1023,15 +1089,17 @@ bool CMMDVMHost::createModem()
|
|||
LogInfo(" YSF TX Level: %.1f%%", ysfTXLevel);
|
||||
LogInfo(" P25 TX Level: %.1f%%", p25TXLevel);
|
||||
LogInfo(" NXDN TX Level: %.1f%%", nxdnTXLevel);
|
||||
LogInfo(" POCSAG TX Level: %.1f%%", pocsagTXLevel);
|
||||
LogInfo(" RX Frequency: %uHz (%uHz)", rxFrequency, rxFrequency + rxOffset);
|
||||
LogInfo(" TX Frequency: %uHz (%uHz)", txFrequency, txFrequency + txOffset);
|
||||
|
||||
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_nxdnEnabled);
|
||||
m_modem->setLevels(rxLevel, cwIdTXLevel, dstarTXLevel, dmrTXLevel, ysfTXLevel, p25TXLevel, nxdnTXLevel);
|
||||
m_modem->setRFParams(rxFrequency, rxOffset, txFrequency, txOffset, txDCOffset, rxDCOffset, rfLevel);
|
||||
m_modem->setSerialParams(protocol,address);
|
||||
m_modem->setModeParams(m_dstarEnabled, m_dmrEnabled, m_ysfEnabled, m_p25Enabled, m_nxdnEnabled, m_pocsagEnabled);
|
||||
m_modem->setLevels(rxLevel, cwIdTXLevel, dstarTXLevel, dmrTXLevel, ysfTXLevel, p25TXLevel, nxdnTXLevel, pocsagTXLevel);
|
||||
m_modem->setRFParams(rxFrequency, rxOffset, txFrequency, txOffset, txDCOffset, rxDCOffset, rfLevel, pocsagFrequency);
|
||||
m_modem->setDMRParams(colorCode);
|
||||
m_modem->setYSFParams(lowDeviation);
|
||||
m_modem->setYSFParams(lowDeviation, txHang);
|
||||
|
||||
bool ret = m_modem->open();
|
||||
if (!ret) {
|
||||
|
|
@ -1230,17 +1298,48 @@ bool CMMDVMHost::createNXDNNetwork()
|
|||
return true;
|
||||
}
|
||||
|
||||
bool CMMDVMHost::createPOCSAGNetwork()
|
||||
{
|
||||
std::string gatewayAddress = m_conf.getPOCSAGGatewayAddress();
|
||||
unsigned int gatewayPort = m_conf.getPOCSAGGatewayPort();
|
||||
std::string localAddress = m_conf.getPOCSAGLocalAddress();
|
||||
unsigned int localPort = m_conf.getPOCSAGLocalPort();
|
||||
m_pocsagNetModeHang = m_conf.getPOCSAGNetworkModeHang();
|
||||
bool debug = m_conf.getPOCSAGNetworkDebug();
|
||||
|
||||
LogInfo("POCSAG Network Parameters");
|
||||
LogInfo(" Gateway Address: %s", gatewayAddress.c_str());
|
||||
LogInfo(" Gateway Port: %u", gatewayPort);
|
||||
LogInfo(" Local Address: %s", localAddress.c_str());
|
||||
LogInfo(" Local Port: %u", localPort);
|
||||
LogInfo(" Mode Hang: %us", m_pocsagNetModeHang);
|
||||
|
||||
m_pocsagNetwork = new CPOCSAGNetwork(localAddress, localPort, gatewayAddress, gatewayPort, debug);
|
||||
|
||||
bool ret = m_pocsagNetwork->open();
|
||||
if (!ret) {
|
||||
delete m_pocsagNetwork;
|
||||
m_pocsagNetwork = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
m_pocsagNetwork->enable(true);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CMMDVMHost::readParams()
|
||||
{
|
||||
m_dstarEnabled = m_conf.getDStarEnabled();
|
||||
m_dmrEnabled = m_conf.getDMREnabled();
|
||||
m_ysfEnabled = m_conf.getFusionEnabled();
|
||||
m_p25Enabled = m_conf.getP25Enabled();
|
||||
m_nxdnEnabled = m_conf.getNXDNEnabled();
|
||||
m_duplex = m_conf.getDuplex();
|
||||
m_callsign = m_conf.getCallsign();
|
||||
m_id = m_conf.getId();
|
||||
m_timeout = m_conf.getTimeout();
|
||||
m_dstarEnabled = m_conf.getDStarEnabled();
|
||||
m_dmrEnabled = m_conf.getDMREnabled();
|
||||
m_ysfEnabled = m_conf.getFusionEnabled();
|
||||
m_p25Enabled = m_conf.getP25Enabled();
|
||||
m_nxdnEnabled = m_conf.getNXDNEnabled();
|
||||
m_pocsagEnabled = m_conf.getPOCSAGEnabled();
|
||||
m_duplex = m_conf.getDuplex();
|
||||
m_callsign = m_conf.getCallsign();
|
||||
m_id = m_conf.getId();
|
||||
m_timeout = m_conf.getTimeout();
|
||||
|
||||
LogInfo("General Parameters");
|
||||
LogInfo(" Callsign: %s", m_callsign.c_str());
|
||||
|
|
@ -1252,160 +1351,7 @@ void CMMDVMHost::readParams()
|
|||
LogInfo(" YSF: %s", m_ysfEnabled ? "enabled" : "disabled");
|
||||
LogInfo(" P25: %s", m_p25Enabled ? "enabled" : "disabled");
|
||||
LogInfo(" NXDN: %s", m_nxdnEnabled ? "enabled" : "disabled");
|
||||
}
|
||||
|
||||
void CMMDVMHost::createDisplay()
|
||||
{
|
||||
std::string type = m_conf.getDisplay();
|
||||
unsigned int dmrid = m_conf.getDMRId();
|
||||
|
||||
LogInfo("Display Parameters");
|
||||
LogInfo(" Type: %s", type.c_str());
|
||||
|
||||
if (type == "TFT Serial") {
|
||||
std::string port = m_conf.getTFTSerialPort();
|
||||
unsigned int brightness = m_conf.getTFTSerialBrightness();
|
||||
|
||||
LogInfo(" Port: %s", port.c_str());
|
||||
LogInfo(" Brightness: %u", brightness);
|
||||
|
||||
ISerialPort* serial = NULL;
|
||||
if (port == "modem")
|
||||
serial = new CModemSerialPort(m_modem);
|
||||
else
|
||||
serial = new CSerialController(port, SERIAL_9600);
|
||||
|
||||
m_display = new CTFTSerial(m_callsign, dmrid, serial, brightness);
|
||||
} else if (type == "Nextion") {
|
||||
std::string port = m_conf.getNextionPort();
|
||||
unsigned int brightness = m_conf.getNextionBrightness();
|
||||
bool displayClock = m_conf.getNextionDisplayClock();
|
||||
bool utc = m_conf.getNextionUTC();
|
||||
unsigned int idleBrightness = m_conf.getNextionIdleBrightness();
|
||||
unsigned int screenLayout = m_conf.getNextionScreenLayout();
|
||||
|
||||
LogInfo(" Port: %s", port.c_str());
|
||||
LogInfo(" Brightness: %u", brightness);
|
||||
LogInfo(" Clock Display: %s", displayClock ? "yes" : "no");
|
||||
if (displayClock)
|
||||
LogInfo(" Display UTC: %s", utc ? "yes" : "no");
|
||||
LogInfo(" Idle Brightness: %u", idleBrightness);
|
||||
|
||||
switch (screenLayout) {
|
||||
case 0U:
|
||||
LogInfo(" Screen Layout: G4KLX (Default)");
|
||||
break;
|
||||
case 2U:
|
||||
LogInfo(" Screen Layout: ON7LDS");
|
||||
break;
|
||||
case 3U:
|
||||
LogInfo(" Screen Layout: DIY by ON7LDS");
|
||||
break;
|
||||
case 4U:
|
||||
LogInfo(" Screen Layout: DIY by ON7LDS (High speed)");
|
||||
break;
|
||||
default:
|
||||
LogInfo(" Screen Layout: %u (Unknown)", screenLayout);
|
||||
break;
|
||||
}
|
||||
|
||||
if (port == "modem") {
|
||||
ISerialPort* serial = new CModemSerialPort(m_modem);
|
||||
m_display = new CNextion(m_callsign, dmrid, serial, brightness, displayClock, utc, idleBrightness, screenLayout);
|
||||
} else if (port == "ump") {
|
||||
if (m_ump != NULL)
|
||||
m_display = new CNextion(m_callsign, dmrid, m_ump, brightness, displayClock, utc, idleBrightness, screenLayout);
|
||||
} else {
|
||||
SERIAL_SPEED baudrate = SERIAL_9600;
|
||||
if (screenLayout==4U)
|
||||
baudrate = SERIAL_115200;
|
||||
ISerialPort* serial = new CSerialController(port, baudrate);
|
||||
m_display = new CNextion(m_callsign, dmrid, serial, brightness, displayClock, utc, idleBrightness, screenLayout);
|
||||
}
|
||||
} else if (type == "LCDproc") {
|
||||
std::string address = m_conf.getLCDprocAddress();
|
||||
unsigned int port = m_conf.getLCDprocPort();
|
||||
unsigned int localPort = m_conf.getLCDprocLocalPort();
|
||||
bool displayClock = m_conf.getLCDprocDisplayClock();
|
||||
bool utc = m_conf.getLCDprocUTC();
|
||||
bool dimOnIdle = m_conf.getLCDprocDimOnIdle();
|
||||
|
||||
LogInfo(" Address: %s", address.c_str());
|
||||
LogInfo(" Port: %u", port);
|
||||
|
||||
if (localPort == 0 )
|
||||
LogInfo(" Local Port: random");
|
||||
else
|
||||
LogInfo(" Local Port: %u", localPort);
|
||||
|
||||
LogInfo(" Dim Display on Idle: %s", dimOnIdle ? "yes" : "no");
|
||||
LogInfo(" Clock Display: %s", displayClock ? "yes" : "no");
|
||||
|
||||
if (displayClock)
|
||||
LogInfo(" Display UTC: %s", utc ? "yes" : "no");
|
||||
|
||||
m_display = new CLCDproc(address.c_str(), port, localPort, m_callsign, dmrid, displayClock, utc, m_duplex, dimOnIdle);
|
||||
#if defined(HD44780)
|
||||
} else if (type == "HD44780") {
|
||||
unsigned int rows = m_conf.getHD44780Rows();
|
||||
unsigned int columns = m_conf.getHD44780Columns();
|
||||
std::vector<unsigned int> pins = m_conf.getHD44780Pins();
|
||||
unsigned int i2cAddress = m_conf.getHD44780i2cAddress();
|
||||
bool pwm = m_conf.getHD44780PWM();
|
||||
unsigned int pwmPin = m_conf.getHD44780PWMPin();
|
||||
unsigned int pwmBright = m_conf.getHD44780PWMBright();
|
||||
unsigned int pwmDim = m_conf.getHD44780PWMDim();
|
||||
bool displayClock = m_conf.getHD44780DisplayClock();
|
||||
bool utc = m_conf.getHD44780UTC();
|
||||
|
||||
if (pins.size() == 6U) {
|
||||
LogInfo(" Rows: %u", rows);
|
||||
LogInfo(" Columns: %u", columns);
|
||||
|
||||
#if defined(ADAFRUIT_DISPLAY) || defined(PCF8574_DISPLAY)
|
||||
LogInfo(" Device Address: %#x", i2cAddress);
|
||||
#else
|
||||
LogInfo(" Pins: %u,%u,%u,%u,%u,%u", pins.at(0U), pins.at(1U), pins.at(2U), pins.at(3U), pins.at(4U), pins.at(5U));
|
||||
#endif
|
||||
|
||||
LogInfo(" PWM Backlight: %s", pwm ? "yes" : "no");
|
||||
if (pwm) {
|
||||
LogInfo(" PWM Pin: %u", pwmPin);
|
||||
LogInfo(" PWM Bright: %u", pwmBright);
|
||||
LogInfo(" PWM Dim: %u", pwmDim);
|
||||
}
|
||||
|
||||
LogInfo(" Clock Display: %s", displayClock ? "yes" : "no");
|
||||
if (displayClock)
|
||||
LogInfo(" Display UTC: %s", utc ? "yes" : "no");
|
||||
|
||||
m_display = new CHD44780(rows, columns, m_callsign, dmrid, pins, i2cAddress, pwm, pwmPin, pwmBright, pwmDim, displayClock, utc, m_duplex);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(OLED)
|
||||
} else if (type == "OLED") {
|
||||
unsigned char type = m_conf.getOLEDType();
|
||||
unsigned char brightness = m_conf.getOLEDBrightness();
|
||||
bool invert = m_conf.getOLEDInvert();
|
||||
bool scroll = m_conf.getOLEDScroll();
|
||||
m_display = new COLED(type, brightness, invert, scroll, m_conf.getDMRNetworkSlot1(), m_conf.getDMRNetworkSlot2());
|
||||
#endif
|
||||
} else {
|
||||
m_display = new CNullDisplay;
|
||||
}
|
||||
|
||||
if (m_display == NULL) {
|
||||
LogWarning("No valid display found, disabling");
|
||||
m_display = new CNullDisplay;
|
||||
return;
|
||||
}
|
||||
|
||||
bool ret = m_display->open();
|
||||
if (!ret) {
|
||||
delete m_display;
|
||||
m_display = new CNullDisplay;
|
||||
}
|
||||
LogInfo(" POCSAG: %s", m_pocsagEnabled ? "enabled" : "disabled");
|
||||
}
|
||||
|
||||
void CMMDVMHost::setMode(unsigned char mode)
|
||||
|
|
@ -1423,6 +1369,8 @@ void CMMDVMHost::setMode(unsigned char mode)
|
|||
m_p25Network->enable(false);
|
||||
if (m_nxdnNetwork != NULL)
|
||||
m_nxdnNetwork->enable(false);
|
||||
if (m_pocsagNetwork != NULL)
|
||||
m_pocsagNetwork->enable(false);
|
||||
m_modem->setMode(MODE_DSTAR);
|
||||
if (m_ump != NULL)
|
||||
m_ump->setMode(MODE_DSTAR);
|
||||
|
|
@ -1440,6 +1388,8 @@ void CMMDVMHost::setMode(unsigned char mode)
|
|||
m_p25Network->enable(false);
|
||||
if (m_nxdnNetwork != NULL)
|
||||
m_nxdnNetwork->enable(false);
|
||||
if (m_pocsagNetwork != NULL)
|
||||
m_pocsagNetwork->enable(false);
|
||||
m_modem->setMode(MODE_DMR);
|
||||
if (m_ump != NULL)
|
||||
m_ump->setMode(MODE_DMR);
|
||||
|
|
@ -1461,6 +1411,8 @@ void CMMDVMHost::setMode(unsigned char mode)
|
|||
m_p25Network->enable(false);
|
||||
if (m_nxdnNetwork != NULL)
|
||||
m_nxdnNetwork->enable(false);
|
||||
if (m_pocsagNetwork != NULL)
|
||||
m_pocsagNetwork->enable(false);
|
||||
m_modem->setMode(MODE_YSF);
|
||||
if (m_ump != NULL)
|
||||
m_ump->setMode(MODE_YSF);
|
||||
|
|
@ -1478,6 +1430,8 @@ void CMMDVMHost::setMode(unsigned char mode)
|
|||
m_ysfNetwork->enable(false);
|
||||
if (m_nxdnNetwork != NULL)
|
||||
m_nxdnNetwork->enable(false);
|
||||
if (m_pocsagNetwork != NULL)
|
||||
m_pocsagNetwork->enable(false);
|
||||
m_modem->setMode(MODE_P25);
|
||||
if (m_ump != NULL)
|
||||
m_ump->setMode(MODE_P25);
|
||||
|
|
@ -1495,6 +1449,8 @@ void CMMDVMHost::setMode(unsigned char mode)
|
|||
m_ysfNetwork->enable(false);
|
||||
if (m_p25Network != NULL)
|
||||
m_p25Network->enable(false);
|
||||
if (m_pocsagNetwork != NULL)
|
||||
m_pocsagNetwork->enable(false);
|
||||
m_modem->setMode(MODE_NXDN);
|
||||
if (m_ump != NULL)
|
||||
m_ump->setMode(MODE_NXDN);
|
||||
|
|
@ -1503,6 +1459,25 @@ void CMMDVMHost::setMode(unsigned char mode)
|
|||
m_cwIdTimer.stop();
|
||||
break;
|
||||
|
||||
case MODE_POCSAG:
|
||||
if (m_dstarNetwork != NULL)
|
||||
m_dstarNetwork->enable(false);
|
||||
if (m_dmrNetwork != NULL)
|
||||
m_dmrNetwork->enable(false);
|
||||
if (m_ysfNetwork != NULL)
|
||||
m_ysfNetwork->enable(false);
|
||||
if (m_p25Network != NULL)
|
||||
m_p25Network->enable(false);
|
||||
if (m_nxdnNetwork != NULL)
|
||||
m_nxdnNetwork->enable(false);
|
||||
m_modem->setMode(MODE_POCSAG);
|
||||
if (m_ump != NULL)
|
||||
m_ump->setMode(MODE_POCSAG);
|
||||
m_mode = MODE_POCSAG;
|
||||
m_modeTimer.start();
|
||||
m_cwIdTimer.stop();
|
||||
break;
|
||||
|
||||
case MODE_LOCKOUT:
|
||||
LogMessage("Mode set to Lockout");
|
||||
if (m_dstarNetwork != NULL)
|
||||
|
|
@ -1515,6 +1490,8 @@ void CMMDVMHost::setMode(unsigned char mode)
|
|||
m_p25Network->enable(false);
|
||||
if (m_nxdnNetwork != NULL)
|
||||
m_nxdnNetwork->enable(false);
|
||||
if (m_pocsagNetwork != NULL)
|
||||
m_pocsagNetwork->enable(false);
|
||||
if (m_mode == MODE_DMR && m_duplex && m_modem->hasTX()) {
|
||||
m_modem->writeDMRStart(false);
|
||||
m_dmrTXTimer.stop();
|
||||
|
|
@ -1540,6 +1517,8 @@ void CMMDVMHost::setMode(unsigned char mode)
|
|||
m_p25Network->enable(false);
|
||||
if (m_nxdnNetwork != NULL)
|
||||
m_nxdnNetwork->enable(false);
|
||||
if (m_pocsagNetwork != NULL)
|
||||
m_pocsagNetwork->enable(false);
|
||||
if (m_mode == MODE_DMR && m_duplex && m_modem->hasTX()) {
|
||||
m_modem->writeDMRStart(false);
|
||||
m_dmrTXTimer.stop();
|
||||
|
|
@ -1563,6 +1542,8 @@ void CMMDVMHost::setMode(unsigned char mode)
|
|||
m_p25Network->enable(true);
|
||||
if (m_nxdnNetwork != NULL)
|
||||
m_nxdnNetwork->enable(true);
|
||||
if (m_pocsagNetwork != NULL)
|
||||
m_pocsagNetwork->enable(true);
|
||||
if (m_mode == MODE_DMR && m_duplex && m_modem->hasTX()) {
|
||||
m_modem->writeDMRStart(false);
|
||||
m_dmrTXTimer.stop();
|
||||
|
|
@ -1579,6 +1560,9 @@ void CMMDVMHost::setMode(unsigned char mode)
|
|||
m_cwIdTimer.start();
|
||||
}
|
||||
m_display->setIdle();
|
||||
if (mode==MODE_QUIT) {
|
||||
m_display->setQuit();
|
||||
}
|
||||
m_mode = MODE_IDLE;
|
||||
m_modeTimer.stop();
|
||||
break;
|
||||
|
|
|
|||
78
MMDVMHost.h
78
MMDVMHost.h
|
|
@ -19,6 +19,7 @@
|
|||
#if !defined(MMDVMHOST_H)
|
||||
#define MMDVMHOST_H
|
||||
|
||||
#include "POCSAGNetwork.h"
|
||||
#include "DStarNetwork.h"
|
||||
#include "NXDNNetwork.h"
|
||||
#include "NXDNLookup.h"
|
||||
|
|
@ -43,42 +44,45 @@ public:
|
|||
int run();
|
||||
|
||||
private:
|
||||
CConf m_conf;
|
||||
CModem* m_modem;
|
||||
CDStarNetwork* m_dstarNetwork;
|
||||
CDMRNetwork* m_dmrNetwork;
|
||||
CYSFNetwork* m_ysfNetwork;
|
||||
CP25Network* m_p25Network;
|
||||
CNXDNNetwork* m_nxdnNetwork;
|
||||
CDisplay* m_display;
|
||||
CUMP* m_ump;
|
||||
unsigned char m_mode;
|
||||
unsigned int m_dstarRFModeHang;
|
||||
unsigned int m_dmrRFModeHang;
|
||||
unsigned int m_ysfRFModeHang;
|
||||
unsigned int m_p25RFModeHang;
|
||||
unsigned int m_nxdnRFModeHang;
|
||||
unsigned int m_dstarNetModeHang;
|
||||
unsigned int m_dmrNetModeHang;
|
||||
unsigned int m_ysfNetModeHang;
|
||||
unsigned int m_p25NetModeHang;
|
||||
unsigned int m_nxdnNetModeHang;
|
||||
CTimer m_modeTimer;
|
||||
CTimer m_dmrTXTimer;
|
||||
CTimer m_cwIdTimer;
|
||||
bool m_duplex;
|
||||
unsigned int m_timeout;
|
||||
bool m_dstarEnabled;
|
||||
bool m_dmrEnabled;
|
||||
bool m_ysfEnabled;
|
||||
bool m_p25Enabled;
|
||||
bool m_nxdnEnabled;
|
||||
unsigned int m_cwIdTime;
|
||||
CDMRLookup* m_dmrLookup;
|
||||
CNXDNLookup* m_nxdnLookup;
|
||||
std::string m_callsign;
|
||||
unsigned int m_id;
|
||||
std::string m_cwCallsign;
|
||||
CConf m_conf;
|
||||
CModem* m_modem;
|
||||
CDStarNetwork* m_dstarNetwork;
|
||||
CDMRNetwork* m_dmrNetwork;
|
||||
CYSFNetwork* m_ysfNetwork;
|
||||
CP25Network* m_p25Network;
|
||||
CNXDNNetwork* m_nxdnNetwork;
|
||||
CPOCSAGNetwork* m_pocsagNetwork;
|
||||
CDisplay* m_display;
|
||||
CUMP* m_ump;
|
||||
unsigned char m_mode;
|
||||
unsigned int m_dstarRFModeHang;
|
||||
unsigned int m_dmrRFModeHang;
|
||||
unsigned int m_ysfRFModeHang;
|
||||
unsigned int m_p25RFModeHang;
|
||||
unsigned int m_nxdnRFModeHang;
|
||||
unsigned int m_dstarNetModeHang;
|
||||
unsigned int m_dmrNetModeHang;
|
||||
unsigned int m_ysfNetModeHang;
|
||||
unsigned int m_p25NetModeHang;
|
||||
unsigned int m_nxdnNetModeHang;
|
||||
unsigned int m_pocsagNetModeHang;
|
||||
CTimer m_modeTimer;
|
||||
CTimer m_dmrTXTimer;
|
||||
CTimer m_cwIdTimer;
|
||||
bool m_duplex;
|
||||
unsigned int m_timeout;
|
||||
bool m_dstarEnabled;
|
||||
bool m_dmrEnabled;
|
||||
bool m_ysfEnabled;
|
||||
bool m_p25Enabled;
|
||||
bool m_nxdnEnabled;
|
||||
bool m_pocsagEnabled;
|
||||
unsigned int m_cwIdTime;
|
||||
CDMRLookup* m_dmrLookup;
|
||||
CNXDNLookup* m_nxdnLookup;
|
||||
std::string m_callsign;
|
||||
unsigned int m_id;
|
||||
std::string m_cwCallsign;
|
||||
|
||||
void readParams();
|
||||
bool createModem();
|
||||
|
|
@ -87,7 +91,7 @@ private:
|
|||
bool createYSFNetwork();
|
||||
bool createP25Network();
|
||||
bool createNXDNNetwork();
|
||||
void createDisplay();
|
||||
bool createPOCSAGNetwork();
|
||||
|
||||
void setMode(unsigned char mode);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -183,6 +183,7 @@
|
|||
<ClInclude Include="Golay24128.h" />
|
||||
<ClInclude Include="Hamming.h" />
|
||||
<ClInclude Include="DMRLookup.h" />
|
||||
<ClInclude Include="I2CController.h" />
|
||||
<ClInclude Include="LCDproc.h" />
|
||||
<ClInclude Include="Log.h" />
|
||||
<ClInclude Include="MMDVMHost.h" />
|
||||
|
|
@ -212,6 +213,9 @@
|
|||
<ClInclude Include="P25NID.h" />
|
||||
<ClInclude Include="P25Trellis.h" />
|
||||
<ClInclude Include="P25Utils.h" />
|
||||
<ClInclude Include="POCSAGControl.h" />
|
||||
<ClInclude Include="POCSAGDefines.h" />
|
||||
<ClInclude Include="POCSAGNetwork.h" />
|
||||
<ClInclude Include="QR1676.h" />
|
||||
<ClInclude Include="RingBuffer.h" />
|
||||
<ClInclude Include="RS129.h" />
|
||||
|
|
@ -266,6 +270,7 @@
|
|||
<ClCompile Include="Golay2087.cpp" />
|
||||
<ClCompile Include="Golay24128.cpp" />
|
||||
<ClCompile Include="Hamming.cpp" />
|
||||
<ClCompile Include="I2CController.cpp" />
|
||||
<ClCompile Include="LCDproc.cpp" />
|
||||
<ClCompile Include="Log.cpp" />
|
||||
<ClCompile Include="MMDVMHost.cpp" />
|
||||
|
|
@ -294,6 +299,8 @@
|
|||
<ClCompile Include="P25NID.cpp" />
|
||||
<ClCompile Include="P25Trellis.cpp" />
|
||||
<ClCompile Include="P25Utils.cpp" />
|
||||
<ClCompile Include="POCSAGControl.cpp" />
|
||||
<ClCompile Include="POCSAGNetwork.cpp" />
|
||||
<ClCompile Include="QR1676.cpp" />
|
||||
<ClCompile Include="RS129.cpp" />
|
||||
<ClCompile Include="RS241213.cpp" />
|
||||
|
|
|
|||
|
|
@ -263,6 +263,18 @@
|
|||
<ClInclude Include="NXDNAudio.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="POCSAGNetwork.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="POCSAGControl.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="POCSAGDefines.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="I2CController.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="BPTC19696.cpp">
|
||||
|
|
@ -493,5 +505,14 @@
|
|||
<ClCompile Include="NXDNAudio.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="POCSAGNetwork.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="POCSAGControl.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="I2CController.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
</Project>
|
||||
10
Makefile
10
Makefile
|
|
@ -9,11 +9,11 @@ LDFLAGS = -g
|
|||
OBJECTS = \
|
||||
AMBEFEC.o BCH.o BPTC19696.o Conf.o CRC.o Display.o DMRControl.o DMRCSBK.o DMRData.o DMRDataHeader.o DMREMB.o DMREmbeddedData.o DMRFullLC.o \
|
||||
DMRLookup.o DMRLC.o DMRNetwork.o DMRShortLC.o DMRSlot.o DMRSlotType.o DMRAccessControl.o DMRTrellis.o DStarControl.o DStarHeader.o DStarNetwork.o \
|
||||
DStarSlowData.o Golay2087.o Golay24128.o Hamming.o LCDproc.o Log.o MMDVMHost.o Modem.o ModemSerialPort.o Mutex.o NetworkInfo.o Nextion.o \
|
||||
NullDisplay.o NXDNAudio.o NXDNControl.o NXDNConvolution.o NXDNCRC.o NXDNFACCH1.o NXDNLayer3.o NXDNLICH.o NXDNLookup.o NXDNNetwork.o NXDNSACCH.o \
|
||||
NXDNUDCH.o P25Audio.o P25Control.o P25Data.o P25LowSpeedData.o P25Network.o P25NID.o P25Trellis.o P25Utils.o QR1676.o RS129.o RS241213.o \
|
||||
RSSIInterpolator.o SerialController.o SerialPort.o SHA256.o StopWatch.o Sync.o TFTSerial.o Thread.o Timer.o UDPSocket.o UMP.o Utils.o YSFControl.o \
|
||||
YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o
|
||||
DStarSlowData.o Golay2087.o Golay24128.o Hamming.o I2CController.o LCDproc.o Log.o MMDVMHost.o Modem.o ModemSerialPort.o Mutex.o NetworkInfo.o \
|
||||
Nextion.o NullDisplay.o NXDNAudio.o NXDNControl.o NXDNConvolution.o NXDNCRC.o NXDNFACCH1.o NXDNLayer3.o NXDNLICH.o NXDNLookup.o NXDNNetwork.o \
|
||||
NXDNSACCH.o NXDNUDCH.o P25Audio.o P25Control.o P25Data.o P25LowSpeedData.o P25Network.o P25NID.o P25Trellis.o P25Utils.o POCSAGControl.o \
|
||||
POCSAGNetwork.o QR1676.o RS129.o RS241213.o RSSIInterpolator.o SerialController.o SerialPort.o SHA256.o StopWatch.o Sync.o TFTSerial.o Thread.o \
|
||||
Timer.o UDPSocket.o UMP.o Utils.o YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o
|
||||
|
||||
all: MMDVMHost
|
||||
|
||||
|
|
|
|||
|
|
@ -9,11 +9,11 @@ LDFLAGS = -g -L/usr/local/lib
|
|||
OBJECTS = \
|
||||
AMBEFEC.o BCH.o BPTC19696.o Conf.o CRC.o Display.o DMRControl.o DMRCSBK.o DMRData.o DMRDataHeader.o DMREMB.o DMREmbeddedData.o DMRFullLC.o \
|
||||
DMRLookup.o DMRLC.o DMRNetwork.o DMRShortLC.o DMRSlot.o DMRSlotType.o DMRAccessControl.o DMRTrellis.o DStarControl.o DStarHeader.o DStarNetwork.o \
|
||||
DStarSlowData.o Golay2087.o Golay24128.o Hamming.o LCDproc.o Log.o MMDVMHost.o Modem.o ModemSerialPort.o Mutex.o NetworkInfo.o Nextion.o \
|
||||
DStarSlowData.o Golay2087.o Golay24128.o Hamming.o I2CController.o LCDproc.o Log.o MMDVMHost.o Modem.o ModemSerialPort.o Mutex.o NetworkInfo.o Nextion.o \
|
||||
NullDisplay.o NXDNAudio.o NXDNControl.o NXDNConvolution.o NXDNCRC.o NXDNFACCH1.o NXDNLayer3.o NXDNLICH.o NXDNLookup.o NXDNNetwork.o NXDNSACCH.o \
|
||||
NXDNUDCH.o P25Audio.o P25Control.o P25Data.o P25LowSpeedData.o P25Network.o P25NID.o P25Trellis.o P25Utils.o QR1676.o RS129.o RS241213.o \
|
||||
RSSIInterpolator.o SerialController.o SerialPort.o SHA256.o StopWatch.o Sync.o TFTSerial.o Thread.o Timer.o UDPSocket.o UMP.o Utils.o YSFControl.o \
|
||||
YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o
|
||||
NXDNUDCH.o P25Audio.o P25Control.o P25Data.o P25LowSpeedData.o P25Network.o P25NID.o P25Trellis.o P25Utils.o POCSAGControl.o POCSAGNetwork.o \
|
||||
QR1676.o RS129.o RS241213.o RSSIInterpolator.o SerialController.o SerialPort.o SHA256.o StopWatch.o Sync.o TFTSerial.o Thread.o Timer.o UDPSocket.o \
|
||||
UMP.o Utils.o YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o
|
||||
|
||||
all: MMDVMHost
|
||||
|
||||
|
|
|
|||
|
|
@ -9,11 +9,11 @@ LDFLAGS = -g -L/usr/local/lib
|
|||
OBJECTS = \
|
||||
AMBEFEC.o BCH.o BPTC19696.o Conf.o CRC.o Display.o DMRControl.o DMRCSBK.o DMRData.o DMRDataHeader.o DMREMB.o DMREmbeddedData.o DMRFullLC.o \
|
||||
DMRLookup.o DMRLC.o DMRNetwork.o DMRShortLC.o DMRSlot.o DMRSlotType.o DMRAccessControl.o DMRTrellis.o DStarControl.o DStarHeader.o DStarNetwork.o \
|
||||
DStarSlowData.o Golay2087.o Golay24128.o Hamming.o HD44780.o LCDproc.o Log.o MMDVMHost.o Modem.o ModemSerialPort.o Mutex.o NetworkInfo.o \
|
||||
DStarSlowData.o Golay2087.o Golay24128.o Hamming.o HD44780.o I2CController.o LCDproc.o Log.o MMDVMHost.o Modem.o ModemSerialPort.o Mutex.o NetworkInfo.o \
|
||||
Nextion.o NullDisplay.o NXDNAudio.o NXDNControl.o NXDNConvolution.o NXDNCRC.o NXDNFACCH1.o NXDNLayer3.o NXDNLICH.o NXDNLookup.o NXDNNetwork.o \
|
||||
NXDNSACCH.o NXDNUDCH.o P25Audio.o P25Control.o P25Data.o P25LowSpeedData.o P25Network.o P25NID.o P25Trellis.o P25Utils.o QR1676.o RS129.o RS241213.o \
|
||||
RSSIInterpolator.o SerialController.o SerialPort.o SHA256.o StopWatch.o Sync.o TFTSerial.o Thread.o Timer.o UDPSocket.o UMP.o Utils.o YSFControl.o \
|
||||
YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o
|
||||
NXDNSACCH.o NXDNUDCH.o P25Audio.o P25Control.o P25Data.o P25LowSpeedData.o P25Network.o P25NID.o P25Trellis.o P25Utils.o POCSAGControl.o \
|
||||
POCSAGNetwork.o QR1676.o RS129.o RS241213.o RSSIInterpolator.o SerialController.o SerialPort.o SHA256.o StopWatch.o Sync.o TFTSerial.o Thread.o \
|
||||
Timer.o UDPSocket.o UMP.o Utils.o YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o
|
||||
|
||||
all: MMDVMHost
|
||||
|
||||
|
|
|
|||
|
|
@ -9,11 +9,11 @@ LDFLAGS = -g -L/usr/local/lib
|
|||
OBJECTS = \
|
||||
AMBEFEC.o BCH.o BPTC19696.o Conf.o CRC.o Display.o DMRControl.o DMRCSBK.o DMRData.o DMRDataHeader.o DMREMB.o DMREmbeddedData.o DMRFullLC.o \
|
||||
DMRLookup.o DMRLC.o DMRNetwork.o DMRShortLC.o DMRSlot.o DMRSlotType.o DMRAccessControl.o DMRTrellis.o DStarControl.o DStarHeader.o DStarNetwork.o \
|
||||
DStarSlowData.o Golay2087.o Golay24128.o Hamming.o HD44780.o LCDproc.o Log.o MMDVMHost.o Modem.o ModemSerialPort.o Mutex.o NetworkInfo.o \
|
||||
DStarSlowData.o Golay2087.o Golay24128.o Hamming.o HD44780.o I2CController.o LCDproc.o Log.o MMDVMHost.o Modem.o ModemSerialPort.o Mutex.o NetworkInfo.o \
|
||||
Nextion.o NullDisplay.o NXDNAudio.o NXDNControl.o NXDNConvolution.o NXDNCRC.o NXDNFACCH1.o NXDNLayer3.o NXDNLICH.o NXDNLookup.o NXDNNetwork.o \
|
||||
NXDNSACCH.o NXDNUDCH.o P25Audio.o P25Control.o P25Data.o P25LowSpeedData.o P25Network.o P25NID.o P25Trellis.o P25Utils.o QR1676.o RS129.o RS241213.o \
|
||||
RSSIInterpolator.o SerialController.o SerialPort.o SHA256.o StopWatch.o Sync.o TFTSerial.o Thread.o Timer.o UDPSocket.o UMP.o Utils.o YSFControl.o \
|
||||
YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o
|
||||
NXDNSACCH.o NXDNUDCH.o P25Audio.o P25Control.o P25Data.o P25LowSpeedData.o P25Network.o P25NID.o P25Trellis.o P25Utils.o POCSAGControl.o \
|
||||
POCSAGNetwork.o QR1676.o RS129.o RS241213.o RSSIInterpolator.o SerialController.o SerialPort.o SHA256.o StopWatch.o Sync.o TFTSerial.o Thread.o \
|
||||
Timer.o UDPSocket.o UMP.o Utils.o YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o
|
||||
|
||||
all: MMDVMHost
|
||||
|
||||
|
|
|
|||
|
|
@ -9,11 +9,11 @@ LDFLAGS = -g -L/usr/local/lib
|
|||
OBJECTS = \
|
||||
AMBEFEC.o BCH.o BPTC19696.o Conf.o CRC.o Display.o DMRControl.o DMRCSBK.o DMRData.o DMRDataHeader.o DMREMB.o DMREmbeddedData.o DMRFullLC.o \
|
||||
DMRLookup.o DMRLC.o DMRNetwork.o DMRShortLC.o DMRSlot.o DMRSlotType.o DMRAccessControl.o DMRTrellis.o DStarControl.o DStarHeader.o DStarNetwork.o \
|
||||
DStarSlowData.o Golay2087.o Golay24128.o Hamming.o OLED.o LCDproc.o Log.o MMDVMHost.o Modem.o ModemSerialPort.o Mutex.o NetworkInfo.o \
|
||||
DStarSlowData.o Golay2087.o Golay24128.o Hamming.o I2CController.o OLED.o LCDproc.o Log.o MMDVMHost.o Modem.o ModemSerialPort.o Mutex.o NetworkInfo.o \
|
||||
Nextion.o NullDisplay.o NXDNAudio.o NXDNControl.o NXDNConvolution.o NXDNCRC.o NXDNFACCH1.o NXDNLayer3.o NXDNLICH.o NXDNLookup.o NXDNNetwork.o \
|
||||
NXDNSACCH.o NXDNUDCH.o P25Audio.o P25Control.o P25Data.o P25LowSpeedData.o P25Network.o P25NID.o P25Trellis.o P25Utils.o QR1676.o RS129.o RS241213.o \
|
||||
RSSIInterpolator.o SerialController.o SerialPort.o SHA256.o StopWatch.o Sync.o TFTSerial.o Thread.o Timer.o UDPSocket.o UMP.o Utils.o YSFControl.o \
|
||||
YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o
|
||||
NXDNSACCH.o NXDNUDCH.o P25Audio.o P25Control.o P25Data.o P25LowSpeedData.o P25Network.o P25NID.o P25Trellis.o P25Utils.o POCSAGControl.o \
|
||||
POCSAGNetwork.o QR1676.o RS129.o RS241213.o RSSIInterpolator.o SerialController.o SerialPort.o SHA256.o StopWatch.o Sync.o TFTSerial.o Thread.o \
|
||||
Timer.o UDPSocket.o UMP.o Utils.o YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o
|
||||
|
||||
all: MMDVMHost
|
||||
|
||||
|
|
|
|||
|
|
@ -9,11 +9,11 @@ LDFLAGS = -g -L/usr/local/lib
|
|||
OBJECTS = \
|
||||
AMBEFEC.o BCH.o BPTC19696.o Conf.o CRC.o Display.o DMRControl.o DMRCSBK.o DMRData.o DMRDataHeader.o DMREMB.o DMREmbeddedData.o DMRFullLC.o \
|
||||
DMRLookup.o DMRLC.o DMRNetwork.o DMRShortLC.o DMRSlot.o DMRSlotType.o DMRAccessControl.o DMRTrellis.o DStarControl.o DStarHeader.o DStarNetwork.o \
|
||||
DStarSlowData.o Golay2087.o Golay24128.o Hamming.o HD44780.o LCDproc.o Log.o MMDVMHost.o Modem.o ModemSerialPort.o Mutex.o NetworkInfo.o \
|
||||
DStarSlowData.o Golay2087.o Golay24128.o Hamming.o HD44780.o I2CController.o LCDproc.o Log.o MMDVMHost.o Modem.o ModemSerialPort.o Mutex.o NetworkInfo.o \
|
||||
Nextion.o NullDisplay.o NXDNAudio.o NXDNControl.o NXDNConvolution.o NXDNCRC.o NXDNFACCH1.o NXDNLayer3.o NXDNLICH.o NXDNLookup.o NXDNNetwork.o \
|
||||
NXDNSACCH.o NXDNUDCH.o P25Audio.o P25Control.o P25Data.o P25LowSpeedData.o P25Network.o P25NID.o P25Trellis.o P25Utils.o QR1676.o RS129.o RS241213.o \
|
||||
RSSIInterpolator.o SerialController.o SerialPort.o SHA256.o StopWatch.o Sync.o TFTSerial.o Thread.o Timer.o UDPSocket.o UMP.o Utils.o YSFControl.o \
|
||||
YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o
|
||||
NXDNSACCH.o NXDNUDCH.o P25Audio.o P25Control.o P25Data.o P25LowSpeedData.o P25Network.o P25NID.o P25Trellis.o P25Utils.o POCSAGControl.o \
|
||||
POCSAGNetwork.o QR1676.o RS129.o RS241213.o RSSIInterpolator.o SerialController.o SerialPort.o SHA256.o StopWatch.o Sync.o TFTSerial.o Thread.o \
|
||||
Timer.o UDPSocket.o UMP.o Utils.o YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o
|
||||
|
||||
all: MMDVMHost
|
||||
|
||||
|
|
|
|||
|
|
@ -11,9 +11,9 @@ OBJECTS = \
|
|||
DMRLookup.o DMRLC.o DMRNetwork.o DMRShortLC.o DMRSlot.o DMRSlotType.o DMRAccessControl.o DMRTrellis.o DStarControl.o DStarHeader.o DStarNetwork.o \
|
||||
DStarSlowData.o Golay2087.o Golay24128.o Hamming.o LCDproc.o Log.o MMDVMHost.o Modem.o ModemSerialPort.o Mutex.o NetworkInfo.o Nextion.o \
|
||||
NullDisplay.o NXDNAudio.o NXDNControl.o NXDNConvolution.o NXDNCRC.o NXDNFACCH1.o NXDNLayer3.o NXDNLICH.o NXDNLookup.o NXDNNetwork.o NXDNSACCH.o \
|
||||
NXDNUDCH.o P25Audio.o P25Control.o P25Data.o P25LowSpeedData.o P25Network.o P25NID.o P25Trellis.o P25Utils.o QR1676.o RS129.o RS241213.o \
|
||||
RSSIInterpolator.o SerialController.o SerialPort.o SHA256.o StopWatch.o Sync.o TFTSerial.o Thread.o Timer.o UDPSocket.o UMP.o Utils.o YSFControl.o \
|
||||
YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o
|
||||
NXDNUDCH.o P25Audio.o P25Control.o P25Data.o P25LowSpeedData.o P25Network.o P25NID.o P25Trellis.o P25Utils.o POCSAGControl.o POCSAGNetwork.o \
|
||||
QR1676.o RS129.o RS241213.o RSSIInterpolator.o SerialController.o SerialPort.o SHA256.o StopWatch.o Sync.o TFTSerial.o Thread.o Timer.o UDPSocket.o \
|
||||
UMP.o Utils.o YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o
|
||||
|
||||
all: MMDVMHost
|
||||
|
||||
|
|
|
|||
269
Modem.cpp
269
Modem.cpp
|
|
@ -16,11 +16,13 @@
|
|||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include "I2CController.h"
|
||||
#include "DStarDefines.h"
|
||||
#include "DMRDefines.h"
|
||||
#include "YSFDefines.h"
|
||||
#include "P25Defines.h"
|
||||
#include "NXDNDefines.h"
|
||||
#include "POCSAGDefines.h"
|
||||
#include "Thread.h"
|
||||
#include "Modem.h"
|
||||
#include "Utils.h"
|
||||
|
|
@ -71,6 +73,8 @@ const unsigned char MMDVM_P25_LOST = 0x32U;
|
|||
const unsigned char MMDVM_NXDN_DATA = 0x40U;
|
||||
const unsigned char MMDVM_NXDN_LOST = 0x41U;
|
||||
|
||||
const unsigned char MMDVM_POCSAG_DATA = 0x50U;
|
||||
|
||||
const unsigned char MMDVM_ACK = 0x70U;
|
||||
const unsigned char MMDVM_NAK = 0x7FU;
|
||||
|
||||
|
|
@ -93,6 +97,7 @@ CModem::CModem(const std::string& port, bool duplex, bool rxInvert, bool txInver
|
|||
m_port(port),
|
||||
m_dmrColorCode(0U),
|
||||
m_ysfLoDev(false),
|
||||
m_ysfTXHang(4U),
|
||||
m_duplex(duplex),
|
||||
m_rxInvert(rxInvert),
|
||||
m_txInvert(txInvert),
|
||||
|
|
@ -106,18 +111,21 @@ m_dmrTXLevel(0U),
|
|||
m_ysfTXLevel(0U),
|
||||
m_p25TXLevel(0U),
|
||||
m_nxdnTXLevel(0U),
|
||||
m_pocsagTXLevel(0U),
|
||||
m_trace(trace),
|
||||
m_debug(debug),
|
||||
m_rxFrequency(0U),
|
||||
m_txFrequency(0U),
|
||||
m_pocsagFrequency(0U),
|
||||
m_dstarEnabled(false),
|
||||
m_dmrEnabled(false),
|
||||
m_ysfEnabled(false),
|
||||
m_p25Enabled(false),
|
||||
m_nxdnEnabled(false),
|
||||
m_pocsagEnabled(false),
|
||||
m_rxDCOffset(0),
|
||||
m_txDCOffset(0),
|
||||
m_serial(port, SERIAL_115200, true),
|
||||
m_serial(NULL),
|
||||
m_buffer(NULL),
|
||||
m_length(0U),
|
||||
m_offset(0U),
|
||||
|
|
@ -133,6 +141,7 @@ m_rxP25Data(1000U, "Modem RX P25"),
|
|||
m_txP25Data(1000U, "Modem TX P25"),
|
||||
m_rxNXDNData(1000U, "Modem RX NXDN"),
|
||||
m_txNXDNData(1000U, "Modem TX NXDN"),
|
||||
m_txPOCSAGData(1000U, "Modem TX POCSAG"),
|
||||
m_rxTransparentData(1000U, "Modem RX Transparent"),
|
||||
m_txTransparentData(1000U, "Modem TX Transparent"),
|
||||
m_statusTimer(1000U, 0U, 250U),
|
||||
|
|
@ -144,6 +153,7 @@ m_dmrSpace2(0U),
|
|||
m_ysfSpace(0U),
|
||||
m_p25Space(0U),
|
||||
m_nxdnSpace(0U),
|
||||
m_pocsagSpace(0U),
|
||||
m_tx(false),
|
||||
m_cd(false),
|
||||
m_lockout(false),
|
||||
|
|
@ -157,36 +167,49 @@ m_hwType(HWT_UNKNOWN)
|
|||
|
||||
CModem::~CModem()
|
||||
{
|
||||
delete m_serial;
|
||||
delete[] m_buffer;
|
||||
}
|
||||
|
||||
void CModem::setRFParams(unsigned int rxFrequency, int rxOffset, unsigned int txFrequency, int txOffset, int txDCOffset, int rxDCOffset, float rfLevel)
|
||||
void CModem::setSerialParams(const std::string& protocol, unsigned int address)
|
||||
{
|
||||
m_rxFrequency = rxFrequency + rxOffset;
|
||||
m_txFrequency = txFrequency + txOffset;
|
||||
m_txDCOffset = txDCOffset;
|
||||
m_rxDCOffset = rxDCOffset;
|
||||
m_rfLevel = rfLevel;
|
||||
// Create the serial controller instance according the protocol specified in conf.
|
||||
if (protocol == "i2c")
|
||||
m_serial = new CI2CController(m_port, SERIAL_115200, address, true);
|
||||
else
|
||||
m_serial = new CSerialController(m_port, SERIAL_115200, true);
|
||||
}
|
||||
|
||||
void CModem::setModeParams(bool dstarEnabled, bool dmrEnabled, bool ysfEnabled, bool p25Enabled, bool nxdnEnabled)
|
||||
void CModem::setRFParams(unsigned int rxFrequency, int rxOffset, unsigned int txFrequency, int txOffset, int txDCOffset, int rxDCOffset, float rfLevel, unsigned int pocsagFrequency)
|
||||
{
|
||||
m_dstarEnabled = dstarEnabled;
|
||||
m_dmrEnabled = dmrEnabled;
|
||||
m_ysfEnabled = ysfEnabled;
|
||||
m_p25Enabled = p25Enabled;
|
||||
m_nxdnEnabled = nxdnEnabled;
|
||||
m_rxFrequency = rxFrequency + rxOffset;
|
||||
m_txFrequency = txFrequency + txOffset;
|
||||
m_txDCOffset = txDCOffset;
|
||||
m_rxDCOffset = rxDCOffset;
|
||||
m_rfLevel = rfLevel;
|
||||
m_pocsagFrequency = pocsagFrequency + txOffset;
|
||||
}
|
||||
|
||||
void CModem::setLevels(float rxLevel, float cwIdTXLevel, float dstarTXLevel, float dmrTXLevel, float ysfTXLevel, float p25TXLevel, float nxdnTXLevel)
|
||||
void CModem::setModeParams(bool dstarEnabled, bool dmrEnabled, bool ysfEnabled, bool p25Enabled, bool nxdnEnabled, bool pocsagEnabled)
|
||||
{
|
||||
m_rxLevel = rxLevel;
|
||||
m_cwIdTXLevel = cwIdTXLevel;
|
||||
m_dstarTXLevel = dstarTXLevel;
|
||||
m_dmrTXLevel = dmrTXLevel;
|
||||
m_ysfTXLevel = ysfTXLevel;
|
||||
m_p25TXLevel = p25TXLevel;
|
||||
m_nxdnTXLevel = nxdnTXLevel;
|
||||
m_dstarEnabled = dstarEnabled;
|
||||
m_dmrEnabled = dmrEnabled;
|
||||
m_ysfEnabled = ysfEnabled;
|
||||
m_p25Enabled = p25Enabled;
|
||||
m_nxdnEnabled = nxdnEnabled;
|
||||
m_pocsagEnabled = pocsagEnabled;
|
||||
}
|
||||
|
||||
void CModem::setLevels(float rxLevel, float cwIdTXLevel, float dstarTXLevel, float dmrTXLevel, float ysfTXLevel, float p25TXLevel, float nxdnTXLevel, float pocsagTXLevel)
|
||||
{
|
||||
m_rxLevel = rxLevel;
|
||||
m_cwIdTXLevel = cwIdTXLevel;
|
||||
m_dstarTXLevel = dstarTXLevel;
|
||||
m_dmrTXLevel = dmrTXLevel;
|
||||
m_ysfTXLevel = ysfTXLevel;
|
||||
m_p25TXLevel = p25TXLevel;
|
||||
m_nxdnTXLevel = nxdnTXLevel;
|
||||
m_pocsagTXLevel = pocsagTXLevel;
|
||||
}
|
||||
|
||||
void CModem::setDMRParams(unsigned int colorCode)
|
||||
|
|
@ -196,22 +219,25 @@ void CModem::setDMRParams(unsigned int colorCode)
|
|||
m_dmrColorCode = colorCode;
|
||||
}
|
||||
|
||||
void CModem::setYSFParams(bool loDev)
|
||||
void CModem::setYSFParams(bool loDev, unsigned int txHang)
|
||||
{
|
||||
m_ysfLoDev = loDev;
|
||||
m_ysfLoDev = loDev;
|
||||
m_ysfTXHang = txHang;
|
||||
}
|
||||
|
||||
bool CModem::open()
|
||||
{
|
||||
::LogMessage("Opening the MMDVM");
|
||||
|
||||
bool ret = m_serial.open();
|
||||
bool ret = m_serial->open();
|
||||
if (!ret)
|
||||
return false;
|
||||
|
||||
ret = readVersion();
|
||||
if (!ret) {
|
||||
m_serial.close();
|
||||
m_serial->close();
|
||||
delete m_serial;
|
||||
m_serial = NULL;
|
||||
return false;
|
||||
} else {
|
||||
/* Stopping the inactivity timer here when a firmware version has been
|
||||
|
|
@ -221,13 +247,17 @@ bool CModem::open()
|
|||
|
||||
ret = setFrequency();
|
||||
if (!ret) {
|
||||
m_serial.close();
|
||||
m_serial->close();
|
||||
delete m_serial;
|
||||
m_serial = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
ret = setConfig();
|
||||
if (!ret) {
|
||||
m_serial.close();
|
||||
m_serial->close();
|
||||
delete m_serial;
|
||||
m_serial = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -241,6 +271,8 @@ bool CModem::open()
|
|||
|
||||
void CModem::clock(unsigned int ms)
|
||||
{
|
||||
assert(m_serial != NULL);
|
||||
|
||||
// Poll the modem status every 250ms
|
||||
m_statusTimer.clock(ms);
|
||||
if (m_statusTimer.hasExpired()) {
|
||||
|
|
@ -474,6 +506,10 @@ void CModem::clock(unsigned int ms)
|
|||
// if (m_trace)
|
||||
// CUtils::dump(1U, "GET_STATUS", m_buffer, m_length);
|
||||
|
||||
m_p25Space = 0U;
|
||||
m_nxdnSpace = 0U;
|
||||
m_pocsagSpace = 0U;
|
||||
|
||||
m_tx = (m_buffer[5U] & 0x01U) == 0x01U;
|
||||
|
||||
bool adcOverflow = (m_buffer[5U] & 0x02U) == 0x02U;
|
||||
|
|
@ -493,18 +529,23 @@ void CModem::clock(unsigned int ms)
|
|||
bool dacOverflow = (m_buffer[5U] & 0x20U) == 0x20U;
|
||||
if (dacOverflow)
|
||||
LogError("MMDVM DAC levels have overflowed");
|
||||
|
||||
|
||||
m_cd = (m_buffer[5U] & 0x40U) == 0x40U;
|
||||
|
||||
m_dstarSpace = m_buffer[6U];
|
||||
m_dmrSpace1 = m_buffer[7U];
|
||||
m_dmrSpace2 = m_buffer[8U];
|
||||
m_ysfSpace = m_buffer[9U];
|
||||
m_p25Space = m_buffer[10U];
|
||||
m_nxdnSpace = m_buffer[11U];
|
||||
m_dstarSpace = m_buffer[6U];
|
||||
m_dmrSpace1 = m_buffer[7U];
|
||||
m_dmrSpace2 = m_buffer[8U];
|
||||
m_ysfSpace = m_buffer[9U];
|
||||
|
||||
if (m_length > 10U)
|
||||
m_p25Space = m_buffer[10U];
|
||||
if (m_length > 11U)
|
||||
m_nxdnSpace = m_buffer[11U];
|
||||
if (m_length > 12U)
|
||||
m_pocsagSpace = m_buffer[12U];
|
||||
|
||||
m_inactivityTimer.start();
|
||||
// LogMessage("status=%02X, tx=%d, space=%u,%u,%u,%u,%u lockout=%d, cd=%d", m_buffer[5U], int(m_tx), m_dstarSpace, m_dmrSpace1, m_dmrSpace2, m_ysfSpace, m_p25Space, int(m_lockout), int(m_cd));
|
||||
// LogMessage("status=%02X, tx=%d, space=%u,%u,%u,%u,%u,%u,%u lockout=%d, cd=%d", m_buffer[5U], int(m_tx), m_dstarSpace, m_dmrSpace1, m_dmrSpace2, m_ysfSpace, m_p25Space, m_nxdnSpace, m_pocsagSpace, int(m_lockout), int(m_cd));
|
||||
}
|
||||
break;
|
||||
|
||||
|
|
@ -577,7 +618,7 @@ void CModem::clock(unsigned int ms)
|
|||
break;
|
||||
}
|
||||
|
||||
int ret = m_serial.write(m_buffer, len);
|
||||
int ret = m_serial->write(m_buffer, len);
|
||||
if (ret != int(len))
|
||||
LogWarning("Error when writing D-Star data to the MMDVM");
|
||||
|
||||
|
|
@ -593,7 +634,7 @@ void CModem::clock(unsigned int ms)
|
|||
if (m_trace)
|
||||
CUtils::dump(1U, "TX DMR Data 1", m_buffer, len);
|
||||
|
||||
int ret = m_serial.write(m_buffer, len);
|
||||
int ret = m_serial->write(m_buffer, len);
|
||||
if (ret != int(len))
|
||||
LogWarning("Error when writing DMR data to the MMDVM");
|
||||
|
||||
|
|
@ -610,7 +651,7 @@ void CModem::clock(unsigned int ms)
|
|||
if (m_trace)
|
||||
CUtils::dump(1U, "TX DMR Data 2", m_buffer, len);
|
||||
|
||||
int ret = m_serial.write(m_buffer, len);
|
||||
int ret = m_serial->write(m_buffer, len);
|
||||
if (ret != int(len))
|
||||
LogWarning("Error when writing DMR data to the MMDVM");
|
||||
|
||||
|
|
@ -627,7 +668,7 @@ void CModem::clock(unsigned int ms)
|
|||
if (m_trace)
|
||||
CUtils::dump(1U, "TX YSF Data", m_buffer, len);
|
||||
|
||||
int ret = m_serial.write(m_buffer, len);
|
||||
int ret = m_serial->write(m_buffer, len);
|
||||
if (ret != int(len))
|
||||
LogWarning("Error when writing YSF data to the MMDVM");
|
||||
|
||||
|
|
@ -648,7 +689,7 @@ void CModem::clock(unsigned int ms)
|
|||
CUtils::dump(1U, "TX P25 LDU", m_buffer, len);
|
||||
}
|
||||
|
||||
int ret = m_serial.write(m_buffer, len);
|
||||
int ret = m_serial->write(m_buffer, len);
|
||||
if (ret != int(len))
|
||||
LogWarning("Error when writing P25 data to the MMDVM");
|
||||
|
||||
|
|
@ -665,7 +706,7 @@ void CModem::clock(unsigned int ms)
|
|||
if (m_trace)
|
||||
CUtils::dump(1U, "TX NXDN Data", m_buffer, len);
|
||||
|
||||
int ret = m_serial.write(m_buffer, len);
|
||||
int ret = m_serial->write(m_buffer, len);
|
||||
if (ret != int(len))
|
||||
LogWarning("Error when writing NXDN data to the MMDVM");
|
||||
|
||||
|
|
@ -674,6 +715,23 @@ void CModem::clock(unsigned int ms)
|
|||
m_nxdnSpace--;
|
||||
}
|
||||
|
||||
if (m_pocsagSpace > 1U && !m_txPOCSAGData.isEmpty()) {
|
||||
unsigned char len = 0U;
|
||||
m_txPOCSAGData.getData(&len, 1U);
|
||||
m_txPOCSAGData.getData(m_buffer, len);
|
||||
|
||||
if (m_trace)
|
||||
CUtils::dump(1U, "TX POCSAG Data", m_buffer, len);
|
||||
|
||||
int ret = m_serial->write(m_buffer, len);
|
||||
if (ret != int(len))
|
||||
LogWarning("Error when writing POCSAG data to the MMDVM");
|
||||
|
||||
m_playoutTimer.start();
|
||||
|
||||
m_pocsagSpace--;
|
||||
}
|
||||
|
||||
if (!m_txTransparentData.isEmpty()) {
|
||||
unsigned char len = 0U;
|
||||
m_txTransparentData.getData(&len, 1U);
|
||||
|
|
@ -682,7 +740,7 @@ void CModem::clock(unsigned int ms)
|
|||
if (m_trace)
|
||||
CUtils::dump(1U, "TX Transparent Data", m_buffer, len);
|
||||
|
||||
int ret = m_serial.write(m_buffer, len);
|
||||
int ret = m_serial->write(m_buffer, len);
|
||||
if (ret != int(len))
|
||||
LogWarning("Error when writing Transparent data to the MMDVM");
|
||||
}
|
||||
|
|
@ -690,9 +748,11 @@ void CModem::clock(unsigned int ms)
|
|||
|
||||
void CModem::close()
|
||||
{
|
||||
assert(m_serial != NULL);
|
||||
|
||||
::LogMessage("Closing the MMDVM");
|
||||
|
||||
m_serial.close();
|
||||
m_serial->close();
|
||||
}
|
||||
|
||||
unsigned int CModem::readDStarData(unsigned char* data)
|
||||
|
|
@ -993,7 +1053,34 @@ bool CModem::writeNXDNData(const unsigned char* data, unsigned int length)
|
|||
return true;
|
||||
}
|
||||
|
||||
bool CModem::writeTransparentData(const unsigned char* data, unsigned int length)
|
||||
bool CModem::hasPOCSAGSpace() const
|
||||
{
|
||||
unsigned int space = m_txPOCSAGData.freeSpace() / (POCSAG_FRAME_LENGTH_BYTES + 4U);
|
||||
|
||||
return space > 1U;
|
||||
}
|
||||
|
||||
bool CModem::writePOCSAGData(const unsigned char* data, unsigned int length)
|
||||
{
|
||||
assert(data != NULL);
|
||||
assert(length > 0U);
|
||||
|
||||
unsigned char buffer[130U];
|
||||
|
||||
buffer[0U] = MMDVM_FRAME_START;
|
||||
buffer[1U] = length + 3U;
|
||||
buffer[2U] = MMDVM_POCSAG_DATA;
|
||||
|
||||
::memcpy(buffer + 3U, data, length);
|
||||
|
||||
unsigned char len = length + 3U; // XXX Check lengths
|
||||
m_txPOCSAGData.addData(&len, 1U);
|
||||
m_txPOCSAGData.addData(buffer, len);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CModem::writeTransparentData(const unsigned char* data, unsigned int length, unsigned int sendFrameType)
|
||||
{
|
||||
assert(data != NULL);
|
||||
assert(length > 0U);
|
||||
|
|
@ -1004,7 +1091,19 @@ bool CModem::writeTransparentData(const unsigned char* data, unsigned int length
|
|||
buffer[1U] = length + 3U;
|
||||
buffer[2U] = MMDVM_TRANSPARENT;
|
||||
|
||||
::memcpy(buffer + 3U, data, length);
|
||||
if (sendFrameType>0) {
|
||||
::memcpy(buffer + 2U, data, length);
|
||||
length--;
|
||||
buffer[1U]--;
|
||||
//when sendFrameType==1 , only 0x80 and 0x90 (MMDVM_SERIAL and MMDVM_TRANSPARENT) are allowed
|
||||
// and reverted to default (MMDVM_TRANSPARENT) for any other value
|
||||
//when >1, frame type is not checked
|
||||
if (sendFrameType==1) {
|
||||
if ((buffer[2U] & 0xE0) != 0x80) buffer[2U] = MMDVM_TRANSPARENT;
|
||||
}
|
||||
} else {
|
||||
::memcpy(buffer + 3U, data, length);
|
||||
}
|
||||
|
||||
unsigned char len = length + 3U;
|
||||
m_txTransparentData.addData(&len, 1U);
|
||||
|
|
@ -1015,6 +1114,7 @@ bool CModem::writeTransparentData(const unsigned char* data, unsigned int length
|
|||
|
||||
bool CModem::writeSerial(const unsigned char* data, unsigned int length)
|
||||
{
|
||||
assert(m_serial != NULL);
|
||||
assert(data != NULL);
|
||||
assert(length > 0U);
|
||||
|
||||
|
|
@ -1026,7 +1126,7 @@ bool CModem::writeSerial(const unsigned char* data, unsigned int length)
|
|||
|
||||
::memcpy(buffer + 3U, data, length);
|
||||
|
||||
int ret = m_serial.write(buffer, length + 3U);
|
||||
int ret = m_serial->write(buffer, length + 3U);
|
||||
|
||||
return ret != int(length + 3U);
|
||||
}
|
||||
|
|
@ -1053,6 +1153,8 @@ bool CModem::hasError() const
|
|||
|
||||
bool CModem::readVersion()
|
||||
{
|
||||
assert(m_serial != NULL);
|
||||
|
||||
CThread::sleep(2000U); // 2s
|
||||
|
||||
for (unsigned int i = 0U; i < 6U; i++) {
|
||||
|
|
@ -1064,12 +1166,12 @@ bool CModem::readVersion()
|
|||
|
||||
// CUtils::dump(1U, "Written", buffer, 3U);
|
||||
|
||||
int ret = m_serial.write(buffer, 3U);
|
||||
int ret = m_serial->write(buffer, 3U);
|
||||
if (ret != 3)
|
||||
return false;
|
||||
|
||||
#if defined(__APPLE__)
|
||||
m_serial.setNonblock(true);
|
||||
m_serial->setNonblock(true);
|
||||
#endif
|
||||
|
||||
for (unsigned int count = 0U; count < MAX_RESPONSES; count++) {
|
||||
|
|
@ -1088,6 +1190,8 @@ bool CModem::readVersion()
|
|||
m_hwType = HWT_MMDVM_HS_DUAL_HAT;
|
||||
else if (::memcmp(m_buffer + 4U, "Nano_hotSPOT", 12U) == 0)
|
||||
m_hwType = HWT_NANO_HOTSPOT;
|
||||
else if (::memcmp(m_buffer + 4U, "Nano_DV", 7U) == 0)
|
||||
m_hwType = HWT_NANO_DV;
|
||||
else if (::memcmp(m_buffer + 4U, "MMDVM_HS-", 9U) == 0)
|
||||
m_hwType = HWT_MMDVM_HS;
|
||||
|
||||
|
|
@ -1106,6 +1210,8 @@ bool CModem::readVersion()
|
|||
|
||||
bool CModem::readStatus()
|
||||
{
|
||||
assert(m_serial != NULL);
|
||||
|
||||
unsigned char buffer[3U];
|
||||
|
||||
buffer[0U] = MMDVM_FRAME_START;
|
||||
|
|
@ -1114,16 +1220,18 @@ bool CModem::readStatus()
|
|||
|
||||
// CUtils::dump(1U, "Written", buffer, 3U);
|
||||
|
||||
return m_serial.write(buffer, 3U) == 3;
|
||||
return m_serial->write(buffer, 3U) == 3;
|
||||
}
|
||||
|
||||
bool CModem::setConfig()
|
||||
{
|
||||
unsigned char buffer[20U];
|
||||
assert(m_serial != NULL);
|
||||
|
||||
unsigned char buffer[30U];
|
||||
|
||||
buffer[0U] = MMDVM_FRAME_START;
|
||||
|
||||
buffer[1U] = 19U;
|
||||
buffer[1U] = 21U;
|
||||
|
||||
buffer[2U] = MMDVM_SET_CONFIG;
|
||||
|
||||
|
|
@ -1152,6 +1260,8 @@ bool CModem::setConfig()
|
|||
buffer[4U] |= 0x08U;
|
||||
if (m_nxdnEnabled)
|
||||
buffer[4U] |= 0x10U;
|
||||
if (m_pocsagEnabled)
|
||||
buffer[4U] |= 0x20U;
|
||||
|
||||
buffer[5U] = m_txDelay / 10U; // In 10ms units
|
||||
|
||||
|
|
@ -1177,10 +1287,14 @@ bool CModem::setConfig()
|
|||
|
||||
buffer[18U] = (unsigned char)(m_nxdnTXLevel * 2.55F + 0.5F);
|
||||
|
||||
// CUtils::dump(1U, "Written", buffer, 19U);
|
||||
buffer[19U] = (unsigned char)m_ysfTXHang;
|
||||
|
||||
int ret = m_serial.write(buffer, 19U);
|
||||
if (ret != 19)
|
||||
buffer[20U] = (unsigned char)(m_pocsagTXLevel * 2.55F + 0.5F);
|
||||
|
||||
// CUtils::dump(1U, "Written", buffer, 21U);
|
||||
|
||||
int ret = m_serial->write(buffer, 21U);
|
||||
if (ret != 21)
|
||||
return false;
|
||||
|
||||
unsigned int count = 0U;
|
||||
|
|
@ -1212,14 +1326,22 @@ bool CModem::setConfig()
|
|||
|
||||
bool CModem::setFrequency()
|
||||
{
|
||||
unsigned char buffer[16U];
|
||||
assert(m_serial != NULL);
|
||||
|
||||
unsigned char buffer[20U];
|
||||
unsigned char len;
|
||||
|
||||
|
||||
if (m_hwType == HWT_DVMEGA)
|
||||
len = 12U;
|
||||
else {
|
||||
buffer[12U] = (unsigned char)(m_rfLevel * 2.55F + 0.5F);
|
||||
len = 13U;
|
||||
|
||||
buffer[13U] = (m_pocsagFrequency >> 0) & 0xFFU;
|
||||
buffer[14U] = (m_pocsagFrequency >> 8) & 0xFFU;
|
||||
buffer[15U] = (m_pocsagFrequency >> 16) & 0xFFU;
|
||||
buffer[16U] = (m_pocsagFrequency >> 24) & 0xFFU;
|
||||
|
||||
len = 17U;
|
||||
}
|
||||
|
||||
buffer[0U] = MMDVM_FRAME_START;
|
||||
|
|
@ -1242,7 +1364,7 @@ bool CModem::setFrequency()
|
|||
|
||||
// CUtils::dump(1U, "Written", buffer, len);
|
||||
|
||||
int ret = m_serial.write(buffer, len);
|
||||
int ret = m_serial->write(buffer, len);
|
||||
if (ret != len)
|
||||
return false;
|
||||
|
||||
|
|
@ -1273,9 +1395,11 @@ bool CModem::setFrequency()
|
|||
|
||||
RESP_TYPE_MMDVM CModem::getResponse()
|
||||
{
|
||||
assert(m_serial != NULL);
|
||||
|
||||
if (m_offset == 0U) {
|
||||
// Get the start of the frame or nothing at all
|
||||
int ret = m_serial.read(m_buffer + 0U, 1U);
|
||||
int ret = m_serial->read(m_buffer + 0U, 1U);
|
||||
if (ret < 0) {
|
||||
LogError("Error when reading from the modem");
|
||||
return RTM_ERROR;
|
||||
|
|
@ -1292,7 +1416,7 @@ RESP_TYPE_MMDVM CModem::getResponse()
|
|||
|
||||
if (m_offset == 1U) {
|
||||
// Get the length of the frame
|
||||
int ret = m_serial.read(m_buffer + 1U, 1U);
|
||||
int ret = m_serial->read(m_buffer + 1U, 1U);
|
||||
if (ret < 0) {
|
||||
LogError("Error when reading from the modem");
|
||||
m_offset = 0U;
|
||||
|
|
@ -1314,7 +1438,7 @@ RESP_TYPE_MMDVM CModem::getResponse()
|
|||
|
||||
if (m_offset == 2U) {
|
||||
// Get the frame type
|
||||
int ret = m_serial.read(m_buffer + 2U, 1U);
|
||||
int ret = m_serial->read(m_buffer + 2U, 1U);
|
||||
if (ret < 0) {
|
||||
LogError("Error when reading from the modem");
|
||||
m_offset = 0U;
|
||||
|
|
@ -1330,7 +1454,7 @@ RESP_TYPE_MMDVM CModem::getResponse()
|
|||
if (m_offset >= 3U) {
|
||||
// Use later two byte length field
|
||||
if (m_length == 0U) {
|
||||
int ret = m_serial.read(m_buffer + 3U, 2U);
|
||||
int ret = m_serial->read(m_buffer + 3U, 2U);
|
||||
if (ret < 0) {
|
||||
LogError("Error when reading from the modem");
|
||||
m_offset = 0U;
|
||||
|
|
@ -1345,7 +1469,7 @@ RESP_TYPE_MMDVM CModem::getResponse()
|
|||
}
|
||||
|
||||
while (m_offset < m_length) {
|
||||
int ret = m_serial.read(m_buffer + m_offset, m_length - m_offset);
|
||||
int ret = m_serial->read(m_buffer + m_offset, m_length - m_offset);
|
||||
if (ret < 0) {
|
||||
LogError("Error when reading from the modem");
|
||||
m_offset = 0U;
|
||||
|
|
@ -1374,6 +1498,8 @@ HW_TYPE CModem::getHWType() const
|
|||
|
||||
bool CModem::setMode(unsigned char mode)
|
||||
{
|
||||
assert(m_serial != NULL);
|
||||
|
||||
unsigned char buffer[4U];
|
||||
|
||||
buffer[0U] = MMDVM_FRAME_START;
|
||||
|
|
@ -1383,11 +1509,13 @@ bool CModem::setMode(unsigned char mode)
|
|||
|
||||
// CUtils::dump(1U, "Written", buffer, 4U);
|
||||
|
||||
return m_serial.write(buffer, 4U) == 4;
|
||||
return m_serial->write(buffer, 4U) == 4;
|
||||
}
|
||||
|
||||
bool CModem::sendCWId(const std::string& callsign)
|
||||
{
|
||||
assert(m_serial != NULL);
|
||||
|
||||
unsigned int length = callsign.length();
|
||||
if (length > 200U)
|
||||
length = 200U;
|
||||
|
|
@ -1403,11 +1531,13 @@ bool CModem::sendCWId(const std::string& callsign)
|
|||
|
||||
// CUtils::dump(1U, "Written", buffer, length + 3U);
|
||||
|
||||
return m_serial.write(buffer, length + 3U) == int(length + 3U);
|
||||
return m_serial->write(buffer, length + 3U) == int(length + 3U);
|
||||
}
|
||||
|
||||
bool CModem::writeDMRStart(bool tx)
|
||||
{
|
||||
assert(m_serial != NULL);
|
||||
|
||||
if (tx && m_tx)
|
||||
return true;
|
||||
if (!tx && !m_tx)
|
||||
|
|
@ -1422,11 +1552,13 @@ bool CModem::writeDMRStart(bool tx)
|
|||
|
||||
// CUtils::dump(1U, "Written", buffer, 4U);
|
||||
|
||||
return m_serial.write(buffer, 4U) == 4;
|
||||
return m_serial->write(buffer, 4U) == 4;
|
||||
}
|
||||
|
||||
bool CModem::writeDMRAbort(unsigned int slotNo)
|
||||
{
|
||||
assert(m_serial != NULL);
|
||||
|
||||
if (slotNo == 1U)
|
||||
m_txDMRData1.clear();
|
||||
else
|
||||
|
|
@ -1441,11 +1573,12 @@ bool CModem::writeDMRAbort(unsigned int slotNo)
|
|||
|
||||
// CUtils::dump(1U, "Written", buffer, 4U);
|
||||
|
||||
return m_serial.write(buffer, 4U) == 4;
|
||||
return m_serial->write(buffer, 4U) == 4;
|
||||
}
|
||||
|
||||
bool CModem::writeDMRShortLC(const unsigned char* lc)
|
||||
{
|
||||
assert(m_serial != NULL);
|
||||
assert(lc != NULL);
|
||||
|
||||
unsigned char buffer[12U];
|
||||
|
|
@ -1465,7 +1598,7 @@ bool CModem::writeDMRShortLC(const unsigned char* lc)
|
|||
|
||||
// CUtils::dump(1U, "Written", buffer, 12U);
|
||||
|
||||
return m_serial.write(buffer, 12U) == 12;
|
||||
return m_serial->write(buffer, 12U) == 12;
|
||||
}
|
||||
|
||||
void CModem::printDebug()
|
||||
|
|
|
|||
21
Modem.h
21
Modem.h
|
|
@ -37,11 +37,12 @@ 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();
|
||||
|
||||
void setRFParams(unsigned int rxFrequency, int rxOffset, unsigned int txFrequency, int txOffset, int txDCOffset, int rxDCOffset, float rfLevel);
|
||||
void setModeParams(bool dstarEnabled, bool dmrEnabled, bool ysfEnabled, bool p25Enabled, bool nxdnEnabled);
|
||||
void setLevels(float rxLevel, float cwIdTXLevel, float dstarTXLevel, float dmrTXLevel, float ysfTXLevel, float p25TXLevel, float nxdnTXLevel);
|
||||
void setSerialParams(const std::string& protocol, unsigned int address);
|
||||
void setRFParams(unsigned int rxFrequency, int rxOffset, unsigned int txFrequency, int txOffset, int txDCOffset, int rxDCOffset, float rfLevel, unsigned int pocsagFrequency);
|
||||
void setModeParams(bool dstarEnabled, bool dmrEnabled, bool ysfEnabled, bool p25Enabled, bool nxdnEnabled, bool pocsagEnabled);
|
||||
void setLevels(float rxLevel, float cwIdTXLevel, float dstarTXLevel, float dmrTXLevel, float ysfTXLevel, float p25TXLevel, float nxdnTXLevel, float pocsagLevel);
|
||||
void setDMRParams(unsigned int colorCode);
|
||||
void setYSFParams(bool loDev);
|
||||
void setYSFParams(bool loDev, unsigned int txHang);
|
||||
|
||||
bool open();
|
||||
|
||||
|
|
@ -61,6 +62,7 @@ public:
|
|||
bool hasYSFSpace() const;
|
||||
bool hasP25Space() const;
|
||||
bool hasNXDNSpace() const;
|
||||
bool hasPOCSAGSpace() const;
|
||||
|
||||
bool hasTX() const;
|
||||
bool hasCD() const;
|
||||
|
|
@ -74,7 +76,8 @@ public:
|
|||
bool writeYSFData(const unsigned char* data, unsigned int length);
|
||||
bool writeP25Data(const unsigned char* data, unsigned int length);
|
||||
bool writeNXDNData(const unsigned char* data, unsigned int length);
|
||||
bool writeTransparentData(const unsigned char* data, unsigned int length);
|
||||
bool writePOCSAGData(const unsigned char* data, unsigned int length);
|
||||
bool writeTransparentData(const unsigned char* data, unsigned int length, unsigned int sendFrameType);
|
||||
|
||||
bool writeDMRStart(bool tx);
|
||||
bool writeDMRShortLC(const unsigned char* lc);
|
||||
|
|
@ -96,6 +99,7 @@ private:
|
|||
std::string m_port;
|
||||
unsigned int m_dmrColorCode;
|
||||
bool m_ysfLoDev;
|
||||
unsigned int m_ysfTXHang;
|
||||
bool m_duplex;
|
||||
bool m_rxInvert;
|
||||
bool m_txInvert;
|
||||
|
|
@ -109,19 +113,22 @@ private:
|
|||
float m_ysfTXLevel;
|
||||
float m_p25TXLevel;
|
||||
float m_nxdnTXLevel;
|
||||
float m_pocsagTXLevel;
|
||||
float m_rfLevel;
|
||||
bool m_trace;
|
||||
bool m_debug;
|
||||
unsigned int m_rxFrequency;
|
||||
unsigned int m_txFrequency;
|
||||
unsigned int m_pocsagFrequency;
|
||||
bool m_dstarEnabled;
|
||||
bool m_dmrEnabled;
|
||||
bool m_ysfEnabled;
|
||||
bool m_p25Enabled;
|
||||
bool m_nxdnEnabled;
|
||||
bool m_pocsagEnabled;
|
||||
int m_rxDCOffset;
|
||||
int m_txDCOffset;
|
||||
CSerialController m_serial;
|
||||
CSerialController* m_serial;
|
||||
unsigned char* m_buffer;
|
||||
unsigned int m_length;
|
||||
unsigned int m_offset;
|
||||
|
|
@ -137,6 +144,7 @@ private:
|
|||
CRingBuffer<unsigned char> m_txP25Data;
|
||||
CRingBuffer<unsigned char> m_rxNXDNData;
|
||||
CRingBuffer<unsigned char> m_txNXDNData;
|
||||
CRingBuffer<unsigned char> m_txPOCSAGData;
|
||||
CRingBuffer<unsigned char> m_rxTransparentData;
|
||||
CRingBuffer<unsigned char> m_txTransparentData;
|
||||
CTimer m_statusTimer;
|
||||
|
|
@ -148,6 +156,7 @@ private:
|
|||
unsigned int m_ysfSpace;
|
||||
unsigned int m_p25Space;
|
||||
unsigned int m_nxdnSpace;
|
||||
unsigned int m_pocsagSpace;
|
||||
bool m_tx;
|
||||
bool m_cd;
|
||||
bool m_lockout;
|
||||
|
|
|
|||
|
|
@ -227,6 +227,7 @@ bool CNXDNControl::processVoice(unsigned char usc, unsigned char option, unsigne
|
|||
lich.setDirection(m_remoteGateway || !m_duplex ? NXDN_LICH_DIRECTION_INBOUND : NXDN_LICH_DIRECTION_OUTBOUND);
|
||||
lich.encode(data + 2U);
|
||||
|
||||
lich.setDirection(NXDN_LICH_DIRECTION_INBOUND);
|
||||
netData[0U] = lich.getRaw();
|
||||
|
||||
CNXDNSACCH sacch;
|
||||
|
|
@ -245,7 +246,7 @@ bool CNXDNControl::processVoice(unsigned char usc, unsigned char option, unsigne
|
|||
|
||||
scrambler(data + 2U);
|
||||
|
||||
writeNetwork(netData, true);
|
||||
writeNetwork(netData, data[0U] == TAG_EOT ? NNMT_VOICE_TRAILER : NNMT_VOICE_HEADER);
|
||||
|
||||
#if defined(DUMP_NXDN)
|
||||
writeFile(data + 2U);
|
||||
|
|
@ -402,6 +403,7 @@ bool CNXDNControl::processVoice(unsigned char usc, unsigned char option, unsigne
|
|||
lich.setDirection(m_remoteGateway || !m_duplex ? NXDN_LICH_DIRECTION_INBOUND : NXDN_LICH_DIRECTION_OUTBOUND);
|
||||
lich.encode(start + 2U);
|
||||
|
||||
lich.setDirection(NXDN_LICH_DIRECTION_INBOUND);
|
||||
netData[0U] = lich.getRaw();
|
||||
|
||||
CNXDNSACCH sacch;
|
||||
|
|
@ -424,7 +426,7 @@ bool CNXDNControl::processVoice(unsigned char usc, unsigned char option, unsigne
|
|||
|
||||
scrambler(start + 2U);
|
||||
|
||||
writeNetwork(netData, true);
|
||||
writeNetwork(netData, NNMT_VOICE_HEADER);
|
||||
|
||||
#if defined(DUMP_NXDN)
|
||||
writeFile(start + 2U);
|
||||
|
|
@ -446,6 +448,7 @@ bool CNXDNControl::processVoice(unsigned char usc, unsigned char option, unsigne
|
|||
lich.setDirection(m_remoteGateway || !m_duplex ? NXDN_LICH_DIRECTION_INBOUND : NXDN_LICH_DIRECTION_OUTBOUND);
|
||||
lich.encode(data + 2U);
|
||||
|
||||
lich.setDirection(NXDN_LICH_DIRECTION_INBOUND);
|
||||
netData[0U] = lich.getRaw();
|
||||
|
||||
// Regenerate SACCH if it's valid
|
||||
|
|
@ -529,7 +532,7 @@ bool CNXDNControl::processVoice(unsigned char usc, unsigned char option, unsigne
|
|||
|
||||
scrambler(data + 2U);
|
||||
|
||||
writeNetwork(netData, false);
|
||||
writeNetwork(netData, NNMT_VOICE_BODY);
|
||||
|
||||
#if defined(DUMP_NXDN)
|
||||
writeFile(data + 2U);
|
||||
|
|
@ -614,12 +617,15 @@ bool CNXDNControl::processData(unsigned char option, unsigned char *data)
|
|||
lich.setDirection(m_remoteGateway || !m_duplex ? NXDN_LICH_DIRECTION_INBOUND : NXDN_LICH_DIRECTION_OUTBOUND);
|
||||
lich.encode(data + 2U);
|
||||
|
||||
lich.setDirection(NXDN_LICH_DIRECTION_INBOUND);
|
||||
netData[0U] = lich.getRaw();
|
||||
|
||||
udch.getRaw(netData + 1U);
|
||||
|
||||
unsigned char type = NXDN_MESSAGE_TYPE_DCALL_DATA;
|
||||
|
||||
if (validUDCH) {
|
||||
unsigned char type = layer3.getMessageType();
|
||||
type = layer3.getMessageType();
|
||||
data[0U] = type == NXDN_MESSAGE_TYPE_TX_REL ? TAG_EOT : TAG_DATA;
|
||||
|
||||
udch.setRAN(m_ran);
|
||||
|
|
@ -631,7 +637,17 @@ bool CNXDNControl::processData(unsigned char option, unsigned char *data)
|
|||
|
||||
scrambler(data + 2U);
|
||||
|
||||
writeNetwork(netData, true);
|
||||
switch (type) {
|
||||
case NXDN_MESSAGE_TYPE_DCALL_HDR:
|
||||
writeNetwork(netData, NNMT_DATA_HEADER);
|
||||
break;
|
||||
case NXDN_MESSAGE_TYPE_TX_REL:
|
||||
writeNetwork(netData, NNMT_DATA_TRAILER);
|
||||
break;
|
||||
default:
|
||||
writeNetwork(netData, NNMT_DATA_BODY);
|
||||
break;
|
||||
}
|
||||
|
||||
if (m_duplex)
|
||||
writeQueueRF(data);
|
||||
|
|
@ -1005,7 +1021,7 @@ void CNXDNControl::writeQueueNet(const unsigned char *data)
|
|||
m_queue.addData(data, len);
|
||||
}
|
||||
|
||||
void CNXDNControl::writeNetwork(const unsigned char *data, bool single)
|
||||
void CNXDNControl::writeNetwork(const unsigned char *data, NXDN_NETWORK_MESSAGE_TYPE type)
|
||||
{
|
||||
assert(data != NULL);
|
||||
|
||||
|
|
@ -1015,7 +1031,7 @@ void CNXDNControl::writeNetwork(const unsigned char *data, bool single)
|
|||
if (m_rfTimeoutTimer.isRunning() && m_rfTimeoutTimer.hasExpired())
|
||||
return;
|
||||
|
||||
m_network->write(data, single);
|
||||
m_network->write(data, type);
|
||||
}
|
||||
|
||||
void CNXDNControl::scrambler(unsigned char* data) const
|
||||
|
|
@ -1043,7 +1059,7 @@ bool CNXDNControl::openFile()
|
|||
if (m_fp == NULL)
|
||||
return false;
|
||||
|
||||
::fwrite("NXDN", 1U, 3U, m_fp);
|
||||
::fwrite("NXDN", 1U, 4U, m_fp);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -84,7 +84,7 @@ private:
|
|||
|
||||
void writeQueueRF(const unsigned char* data);
|
||||
void writeQueueNet(const unsigned char* data);
|
||||
void writeNetwork(const unsigned char* data, bool single);
|
||||
void writeNetwork(const unsigned char* data, NXDN_NETWORK_MESSAGE_TYPE type);
|
||||
void writeNetwork();
|
||||
|
||||
void scrambler(unsigned char* data) const;
|
||||
|
|
|
|||
0
NXDNConvolution.cpp
Executable file → Normal file
0
NXDNConvolution.cpp
Executable file → Normal file
|
|
@ -89,7 +89,7 @@ bool CNXDNLayer3::getIsGroup() const
|
|||
|
||||
unsigned char CNXDNLayer3::getDataBlocks() const
|
||||
{
|
||||
return m_data[8U] & 0x0FU;
|
||||
return (m_data[8U] & 0x0FU) + 1U;
|
||||
}
|
||||
|
||||
void CNXDNLayer3::getData(unsigned char* data) const
|
||||
|
|
|
|||
|
|
@ -56,7 +56,7 @@ bool CNXDNNetwork::open()
|
|||
return m_socket.open();
|
||||
}
|
||||
|
||||
bool CNXDNNetwork::write(const unsigned char* data, bool single)
|
||||
bool CNXDNNetwork::write(const unsigned char* data, NXDN_NETWORK_MESSAGE_TYPE type)
|
||||
{
|
||||
assert(data != NULL);
|
||||
|
||||
|
|
@ -72,9 +72,28 @@ bool CNXDNNetwork::write(const unsigned char* data, bool single)
|
|||
buffer[6U] = 0x08U;
|
||||
buffer[7U] = 0xE0U;
|
||||
|
||||
buffer[37U] = 0x23U;
|
||||
buffer[38U] = single ? 0x1CU : 0x10U;
|
||||
buffer[39U] = 0x21U;
|
||||
switch (type) {
|
||||
case NNMT_VOICE_HEADER:
|
||||
case NNMT_VOICE_TRAILER:
|
||||
buffer[37U] = 0x23U;
|
||||
buffer[38U] = 0x1CU;
|
||||
buffer[39U] = 0x21U;
|
||||
break;
|
||||
case NNMT_VOICE_BODY:
|
||||
buffer[37U] = 0x23U;
|
||||
buffer[38U] = 0x10U;
|
||||
buffer[39U] = 0x21U;
|
||||
break;
|
||||
case NNMT_DATA_HEADER:
|
||||
case NNMT_DATA_BODY:
|
||||
case NNMT_DATA_TRAILER:
|
||||
buffer[37U] = 0x23U;
|
||||
buffer[38U] = 0x02U;
|
||||
buffer[39U] = 0x18U;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
::memcpy(buffer + 40U, data, 33U);
|
||||
|
||||
|
|
|
|||
|
|
@ -27,6 +27,15 @@
|
|||
#include <cstdint>
|
||||
#include <string>
|
||||
|
||||
enum NXDN_NETWORK_MESSAGE_TYPE {
|
||||
NNMT_VOICE_HEADER,
|
||||
NNMT_VOICE_BODY,
|
||||
NNMT_VOICE_TRAILER,
|
||||
NNMT_DATA_HEADER,
|
||||
NNMT_DATA_BODY,
|
||||
NNMT_DATA_TRAILER
|
||||
};
|
||||
|
||||
class CNXDNNetwork {
|
||||
public:
|
||||
CNXDNNetwork(const std::string& localAddress, unsigned int localPort, const std::string& gatewayAddress, unsigned int gatewayPort, bool debug);
|
||||
|
|
@ -36,7 +45,7 @@ public:
|
|||
|
||||
void enable(bool enabled);
|
||||
|
||||
bool write(const unsigned char* data, bool single);
|
||||
bool write(const unsigned char* data, NXDN_NETWORK_MESSAGE_TYPE type);
|
||||
|
||||
bool read(unsigned char* data);
|
||||
|
||||
|
|
|
|||
0
NXDNSACCH.cpp
Executable file → Normal file
0
NXDNSACCH.cpp
Executable file → Normal file
|
|
@ -187,8 +187,6 @@ void CNXDNUDCH::getRaw(unsigned char* data) const
|
|||
|
||||
::memset(data, 0x00U, 25U);
|
||||
::memcpy(data, m_data, 23U);
|
||||
|
||||
CNXDNCRC::encodeCRC15(data, 184U);
|
||||
}
|
||||
|
||||
void CNXDNUDCH::setRAN(unsigned char ran)
|
||||
|
|
|
|||
66
Nextion.cpp
66
Nextion.cpp
|
|
@ -99,7 +99,7 @@ void CNextion::setIdleInt()
|
|||
sendCommand("page MMDVM");
|
||||
sendCommandAction(1U);
|
||||
|
||||
char command[30U];
|
||||
char command[100U];
|
||||
::sprintf(command, "dim=%u", m_idleBrightness);
|
||||
sendCommand(command);
|
||||
|
||||
|
|
@ -165,6 +165,27 @@ void CNextion::setLockoutInt()
|
|||
m_mode = MODE_LOCKOUT;
|
||||
}
|
||||
|
||||
void CNextion::setQuitInt()
|
||||
{
|
||||
sendCommand("page MMDVM");
|
||||
sendCommandAction(1U);
|
||||
|
||||
char command[100];
|
||||
::sprintf(command, "dim=%u", m_idleBrightness);
|
||||
sendCommand(command);
|
||||
|
||||
::sprintf(command, "t3.txt=\"%s\"", m_ipaddress.c_str());
|
||||
sendCommand(command);
|
||||
sendCommandAction(16U);
|
||||
|
||||
sendCommand("t0.txt=\"MMDVM STOPPED\"");
|
||||
sendCommandAction(19U);
|
||||
|
||||
m_clockDisplayTimer.stop();
|
||||
|
||||
m_mode = MODE_QUIT;
|
||||
}
|
||||
|
||||
void CNextion::writeDStarInt(const char* my1, const char* my2, const char* your, const char* type, const char* reflector)
|
||||
{
|
||||
assert(my1 != NULL);
|
||||
|
|
@ -178,7 +199,7 @@ void CNextion::writeDStarInt(const char* my1, const char* my2, const char* your,
|
|||
sendCommandAction(2U);
|
||||
}
|
||||
|
||||
char text[30U];
|
||||
char text[50U];
|
||||
::sprintf(text, "dim=%u", m_brightness);
|
||||
sendCommand(text);
|
||||
|
||||
|
|
@ -273,7 +294,7 @@ void CNextion::writeDMRInt(unsigned int slotNo, const std::string& src, bool gro
|
|||
}
|
||||
}
|
||||
|
||||
char text[30U];
|
||||
char text[50U];
|
||||
::sprintf(text, "dim=%u", m_brightness);
|
||||
sendCommand(text);
|
||||
|
||||
|
|
@ -367,7 +388,7 @@ void CNextion::writeDMRTAInt(unsigned int slotNo, unsigned char* talkerAlias, co
|
|||
}
|
||||
|
||||
if (slotNo == 1U) {
|
||||
char text[40U];
|
||||
char text[50U];
|
||||
::sprintf(text, "t0.txt=\"1 %s %s\"", type, talkerAlias);
|
||||
|
||||
if (m_screenLayout == 2U) {
|
||||
|
|
@ -384,7 +405,7 @@ void CNextion::writeDMRTAInt(unsigned int slotNo, unsigned char* talkerAlias, co
|
|||
sendCommand(text);
|
||||
sendCommandAction(63U);
|
||||
} else {
|
||||
char text[40U];
|
||||
char text[50U];
|
||||
::sprintf(text, "t2.txt=\"2 %s %s\"", type, talkerAlias);
|
||||
|
||||
if (m_screenLayout == 2U) {
|
||||
|
|
@ -679,6 +700,37 @@ void CNextion::clearNXDNInt()
|
|||
sendCommand("t3.txt=\"\"");
|
||||
}
|
||||
|
||||
void CNextion::writePOCSAGInt(uint32_t ric, const std::string& message)
|
||||
{
|
||||
if (m_mode != MODE_POCSAG) {
|
||||
sendCommand("page POCSAG");
|
||||
sendCommandAction(7U);
|
||||
}
|
||||
|
||||
char text[200U];
|
||||
::sprintf(text, "dim=%u", m_brightness);
|
||||
sendCommand(text);
|
||||
|
||||
::sprintf(text, "t0.txt=\"RIC: %u\"", ric);
|
||||
sendCommand(text);
|
||||
sendCommandAction(132U);
|
||||
|
||||
::sprintf(text, "t1.txt=\"%s\"", message.c_str());
|
||||
sendCommand(text);
|
||||
sendCommandAction(133U);
|
||||
|
||||
m_clockDisplayTimer.stop();
|
||||
|
||||
m_mode = MODE_POCSAG;
|
||||
}
|
||||
|
||||
void CNextion::clearPOCSAGInt()
|
||||
{
|
||||
sendCommand("t0.txt=\"Waiting\"");
|
||||
sendCommandAction(134U);
|
||||
sendCommand("t1.txt=\"\"");
|
||||
}
|
||||
|
||||
void CNextion::writeCWInt()
|
||||
{
|
||||
sendCommand("t1.txt=\"Sending CW Ident\"");
|
||||
|
|
@ -719,10 +771,6 @@ void CNextion::clockInt(unsigned int ms)
|
|||
|
||||
void CNextion::close()
|
||||
{
|
||||
sendCommand("page MMDVM");
|
||||
sendCommandAction(1U);
|
||||
sendCommand("t1.txt=\"MMDVM STOPPED\"");
|
||||
sendCommandAction(19U);
|
||||
m_serial->close();
|
||||
delete m_serial;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -40,6 +40,7 @@ protected:
|
|||
virtual void setIdleInt();
|
||||
virtual void setErrorInt(const char* text);
|
||||
virtual void setLockoutInt();
|
||||
virtual void setQuitInt();
|
||||
|
||||
virtual void writeDStarInt(const char* my1, const char* my2, const char* your, const char* type, const char* reflector);
|
||||
virtual void writeDStarRSSIInt(unsigned char rssi);
|
||||
|
|
@ -68,6 +69,9 @@ protected:
|
|||
virtual void writeNXDNBERInt(float ber);
|
||||
virtual void clearNXDNInt();
|
||||
|
||||
virtual void writePOCSAGInt(uint32_t ric, const std::string& message);
|
||||
virtual void clearPOCSAGInt();
|
||||
|
||||
virtual void writeCWInt();
|
||||
virtual void clearCWInt();
|
||||
|
||||
|
|
|
|||
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.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
|
|
@ -15,8 +15,8 @@ are activated.
|
|||
0 = auto (future use, for now it's G4KLX layout)
|
||||
1 = G4KLX layout
|
||||
2 = ON7LDS layout (see README-L2)
|
||||
3 = ON7LDS DIY layout (this README file)
|
||||
4 = ON7LDS DIY layout High Speed (this README file)
|
||||
3 = ON7LDS DIY layout (this README file)
|
||||
4 = ON7LDS DIY layout High Speed (this README file)
|
||||
|
||||
screenLayout 3 and 4 are the same, but selecting 3, MMDVMHost will communicate
|
||||
at 9600bps with the display and selecting 4 will set the baudrate to 115200.
|
||||
|
|
@ -69,7 +69,7 @@ Check the NextionDriver program and the display layouts there to see
|
|||
|
||||
NOTE: it might be good to *not* remove fields from the display when you do not
|
||||
need them, but make them small (i.e. 10 x 10 pixels) and put them aside:
|
||||
Give them the same font color and background color as where you put them
|
||||
Give them the same font colour and background colour as where you put them
|
||||
OR
|
||||
Put them behind some picture: put them on top of the picture, then select the
|
||||
picture and click the 'Bring Top' button to put it on top of all those fields
|
||||
|
|
@ -94,6 +94,7 @@ changed field.
|
|||
4 : page YSF
|
||||
5 : page P25
|
||||
6 : page NXDN
|
||||
7 : page POCSAG
|
||||
|
||||
11 : IDLE
|
||||
12 : CW
|
||||
|
|
@ -147,6 +148,9 @@ changed field.
|
|||
124 : RSSI
|
||||
125 : ber
|
||||
|
||||
132 : RIC
|
||||
133 : message text
|
||||
134 : waiting
|
||||
|
||||
|
||||
Fields (and their numbers) on the pages, used by MMDVMHost
|
||||
|
|
@ -154,7 +158,7 @@ Fields (and their numbers) on the pages, used by MMDVMHost
|
|||
|
||||
MMDVM
|
||||
t0 : owner call & ID / errortext LOCKOUT
|
||||
t1 : status / ERROR
|
||||
t1 : status / ERROR
|
||||
t2 : date & time
|
||||
|
||||
screenLayout >1 :
|
||||
|
|
@ -211,3 +215,6 @@ t1 : dst
|
|||
t2 : rssi
|
||||
t3 : ber
|
||||
|
||||
POCSAG
|
||||
t0 : waiting / RIC
|
||||
t1 : message
|
||||
|
|
|
|||
|
|
@ -16,8 +16,8 @@ Layout 2 is a no-nonsense layout. It is the original (G4KLX) layout with the Tal
|
|||
Layout 3 (as is 4) is a layout without any predefined layout options (color, fonts). It sends the fields **and** information about what was sent to the display, so all layout processing can and should be done in the display itself.
|
||||
|
||||
More information about the layouts can be found in
|
||||
* README-L2 for the screenLayout 2 setting
|
||||
* README-L2 for the screenLayout 3 and 4 settings
|
||||
* README-L2 for the screenLayout 2 setting (list of field names : see README-L3)
|
||||
* README-L3 for the screenLayout 3 and 4 settings
|
||||
|
||||
|
||||
When you want extra control over what has to be sent to the Nextion display, you could consider the program 'NextionDriver' at https://github.com/on7lds/NextionDriver as a companion to MMDVMHost.
|
||||
|
|
|
|||
|
|
@ -56,6 +56,10 @@ void CNullDisplay::setLockoutInt()
|
|||
{
|
||||
}
|
||||
|
||||
void CNullDisplay::setQuitInt()
|
||||
{
|
||||
}
|
||||
|
||||
void CNullDisplay::writeDStarInt(const char* my1, const char* my2, const char* your, const char* type, const char* reflector)
|
||||
{
|
||||
#if defined(RASPBERRY_PI)
|
||||
|
|
@ -126,6 +130,20 @@ void CNullDisplay::clearNXDNInt()
|
|||
#endif
|
||||
}
|
||||
|
||||
void CNullDisplay::writePOCSAGInt(uint32_t ric, const std::string& message)
|
||||
{
|
||||
#if defined(RASPBERRY_PI)
|
||||
::digitalWrite(LED_STATUS, 1);
|
||||
#endif
|
||||
}
|
||||
|
||||
void CNullDisplay::clearPOCSAGInt()
|
||||
{
|
||||
#if defined(RASPBERRY_PI)
|
||||
::digitalWrite(LED_STATUS, 0);
|
||||
#endif
|
||||
}
|
||||
|
||||
void CNullDisplay::writeCWInt()
|
||||
{
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,6 +37,7 @@ protected:
|
|||
virtual void setIdleInt();
|
||||
virtual void setErrorInt(const char* text);
|
||||
virtual void setLockoutInt();
|
||||
virtual void setQuitInt();
|
||||
|
||||
virtual void writeDStarInt(const char* my1, const char* my2, const char* your, const char* type, const char* reflector);
|
||||
virtual void clearDStarInt();
|
||||
|
|
@ -53,6 +54,9 @@ protected:
|
|||
virtual void writeNXDNInt(const char* source, bool group, unsigned int dest, const char* type);
|
||||
virtual void clearNXDNInt();
|
||||
|
||||
virtual void writePOCSAGInt(uint32_t ric, const std::string& message);
|
||||
virtual void clearPOCSAGInt();
|
||||
|
||||
virtual void writeCWInt();
|
||||
virtual void clearCWInt();
|
||||
|
||||
|
|
|
|||
363
OLED.cpp
363
OLED.cpp
|
|
@ -106,45 +106,66 @@ const unsigned char logo_fusion_bmp [] =
|
|||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
|
||||
//Logo P25 128x16px
|
||||
const unsigned char logo_P25_bmp [] =
|
||||
{
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xf8, 0x00, 0x00, 0x00, 0x7f, 0xff, 0xfc, 0x00, 0x00, 0x3f, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x7f,
|
||||
0xf8, 0x00, 0x00, 0x00, 0x03, 0xff, 0xc0, 0x00, 0x00, 0x03, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x7f,
|
||||
0xf8, 0x00, 0xe0, 0x00, 0x00, 0xff, 0x00, 0x07, 0xc0, 0x00, 0xff, 0xe0, 0x00, 0x00, 0x00, 0xff,
|
||||
0xf0, 0x01, 0xff, 0xfc, 0x00, 0x7e, 0x00, 0x3f, 0xf8, 0x00, 0xff, 0xe0, 0x0f, 0xff, 0xff, 0xff,
|
||||
0xf0, 0x01, 0xff, 0xfe, 0x00, 0x7c, 0x00, 0x7f, 0xfc, 0x00, 0x7f, 0xe0, 0x0f, 0xff, 0xff, 0xff,
|
||||
0xf0, 0x01, 0xff, 0xfe, 0x00, 0x7e, 0x00, 0x7f, 0xf8, 0x00, 0xff, 0xe0, 0x00, 0x00, 0x01, 0xff,
|
||||
0xf0, 0x01, 0xff, 0xc0, 0x00, 0xff, 0xff, 0xff, 0xe0, 0x01, 0xff, 0xe0, 0x00, 0x00, 0x00, 0x1f,
|
||||
0xf0, 0x00, 0x00, 0x00, 0x03, 0xff, 0xff, 0xff, 0x00, 0x07, 0xff, 0xff, 0x9f, 0xff, 0x80, 0x07,
|
||||
0xf0, 0x00, 0x00, 0x00, 0x3f, 0xff, 0xff, 0xf8, 0x00, 0x3f, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x03,
|
||||
0xf0, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0x80, 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xe0, 0x03,
|
||||
0xf0, 0x01, 0xff, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x1f, 0xff, 0xff, 0xc0, 0xff, 0xff, 0xc0, 0x03,
|
||||
0xf0, 0x01, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x7f, 0xff, 0xfe, 0x00, 0x0f, 0xfe, 0x00, 0x0f,
|
||||
0xf0, 0x01, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x7f, 0x80, 0x00, 0x00, 0x00, 0x3f,
|
||||
0xf0, 0x01, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xf8, 0x00, 0x00, 0x03, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
|
||||
};
|
||||
|
||||
//Logo P25 128x16px
|
||||
const unsigned char logo_P25_bmp [] =
|
||||
{
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
||||
0x01, 0xff, 0xff, 0xff, 0xf0, 0x00, 0x03, 0xff, 0xff, 0xc0, 0x01, 0xff, 0xff, 0xff, 0xf8, 0x00,
|
||||
0x01, 0xff, 0xff, 0xff, 0xff, 0x80, 0x3f, 0xff, 0xff, 0xfc, 0x01, 0xff, 0xff, 0xff, 0xf8, 0x00,
|
||||
0x01, 0xff, 0xff, 0xff, 0xff, 0xe0, 0xff, 0xf8, 0x3f, 0xff, 0x01, 0xff, 0xff, 0xff, 0xf8, 0x00,
|
||||
0x01, 0xff, 0xc0, 0x00, 0x7f, 0xf1, 0xff, 0xc0, 0x07, 0xff, 0x01, 0xff, 0x00, 0x00, 0x00, 0x00,
|
||||
0x01, 0xff, 0xc0, 0x00, 0x3f, 0xf3, 0xff, 0x80, 0x03, 0xff, 0x81, 0xff, 0x00, 0x00, 0x00, 0x00,
|
||||
0x01, 0xff, 0xc0, 0x00, 0x3f, 0xf1, 0xff, 0x80, 0x07, 0xff, 0x01, 0xff, 0xff, 0xff, 0xe0, 0x00,
|
||||
0x01, 0xff, 0xc0, 0x07, 0xff, 0xe0, 0x00, 0x00, 0x1f, 0xfe, 0x01, 0xff, 0xff, 0xff, 0xfe, 0x00,
|
||||
0x01, 0xff, 0xff, 0xff, 0xff, 0x80, 0x00, 0x00, 0xff, 0xf8, 0x00, 0x00, 0x00, 0x07, 0xff, 0x80,
|
||||
0x01, 0xff, 0xff, 0xff, 0xf8, 0x00, 0x00, 0x07, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x01, 0xff, 0xc0,
|
||||
0x01, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x7f, 0xfe, 0x00, 0x00, 0x00, 0x00, 0x01, 0xff, 0xc0,
|
||||
0x01, 0xff, 0xc0, 0x00, 0x00, 0x00, 0x07, 0xff, 0xe0, 0x00, 0x03, 0xf0, 0x00, 0x03, 0xff, 0xc0,
|
||||
0x01, 0xff, 0xc0, 0x00, 0x00, 0x00, 0xff, 0xff, 0x80, 0x00, 0x1f, 0xff, 0x00, 0x1f, 0xff, 0x00,
|
||||
0x01, 0xff, 0xc0, 0x00, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0x87, 0xff, 0xff, 0xff, 0xfc, 0x00,
|
||||
0x01, 0xff, 0xc0, 0x00, 0x00, 0x07, 0xff, 0xff, 0xff, 0xff, 0x80, 0x7f, 0xff, 0xff, 0xc0, 0x00,
|
||||
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
|
||||
};
|
||||
|
||||
// Logo NXDN_sm, 128x16px
|
||||
const unsigned char logo_NXDN_bmp [] =
|
||||
{
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xf0, 0x1f, 0xf8, 0x0f, 0x00, 0xff, 0x80, 0x7c, 0x00, 0x0f, 0xff, 0x80, 0x7f, 0xe0, 0x7f,
|
||||
0xff, 0xe0, 0x0f, 0xf0, 0x1f, 0x80, 0x7e, 0x01, 0xf8, 0x00, 0x00, 0x7f, 0x00, 0x3f, 0xc0, 0x7f,
|
||||
0xff, 0xc0, 0x07, 0xe0, 0x3f, 0x80, 0x38, 0x07, 0xf0, 0x00, 0x00, 0x3e, 0x00, 0x3f, 0x80, 0xff,
|
||||
0xff, 0x80, 0x03, 0xc0, 0x3f, 0xc0, 0x00, 0x3f, 0xe0, 0x1f, 0x80, 0x3e, 0x00, 0x1f, 0x01, 0xff,
|
||||
0xff, 0x00, 0x03, 0x80, 0x7f, 0xe0, 0x00, 0xff, 0xc0, 0x3f, 0x80, 0x3c, 0x00, 0x0e, 0x03, 0xff,
|
||||
0xfe, 0x00, 0x01, 0x00, 0xff, 0xe0, 0x03, 0xff, 0x80, 0x7f, 0x80, 0x78, 0x08, 0x04, 0x03, 0xff,
|
||||
0xfc, 0x03, 0x00, 0x01, 0xff, 0x80, 0x01, 0xff, 0x00, 0xff, 0x00, 0xf0, 0x1c, 0x00, 0x07, 0xff,
|
||||
0xfc, 0x07, 0x80, 0x03, 0xfc, 0x00, 0x01, 0xfe, 0x01, 0xfc, 0x01, 0xe0, 0x1e, 0x00, 0x0f, 0xff,
|
||||
0xf8, 0x0f, 0xc0, 0x07, 0xf0, 0x0e, 0x00, 0xfc, 0x00, 0x00, 0x07, 0xc0, 0x3f, 0x00, 0x1f, 0xff,
|
||||
0xf0, 0x1f, 0xe0, 0x0f, 0x80, 0x3f, 0x00, 0x7c, 0x00, 0x00, 0x3f, 0xc0, 0x7f, 0x80, 0x3f, 0xff,
|
||||
0xe0, 0x3f, 0xf0, 0x0e, 0x01, 0xff, 0x80, 0x38, 0x00, 0x07, 0xff, 0x80, 0xff, 0x80, 0x7f, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
{
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xf0, 0x1f, 0xf8, 0x0f, 0x00, 0xff, 0x80, 0x7c, 0x00, 0x0f, 0xff, 0x80, 0x7f, 0xe0, 0x7f,
|
||||
0xff, 0xe0, 0x0f, 0xf0, 0x1f, 0x80, 0x7e, 0x01, 0xf8, 0x00, 0x00, 0x7f, 0x00, 0x3f, 0xc0, 0x7f,
|
||||
0xff, 0xc0, 0x07, 0xe0, 0x3f, 0x80, 0x38, 0x07, 0xf0, 0x00, 0x00, 0x3e, 0x00, 0x3f, 0x80, 0xff,
|
||||
0xff, 0x80, 0x03, 0xc0, 0x3f, 0xc0, 0x00, 0x3f, 0xe0, 0x1f, 0x80, 0x3e, 0x00, 0x1f, 0x01, 0xff,
|
||||
0xff, 0x00, 0x03, 0x80, 0x7f, 0xe0, 0x00, 0xff, 0xc0, 0x3f, 0x80, 0x3c, 0x00, 0x0e, 0x03, 0xff,
|
||||
0xfe, 0x00, 0x01, 0x00, 0xff, 0xe0, 0x03, 0xff, 0x80, 0x7f, 0x80, 0x78, 0x08, 0x04, 0x03, 0xff,
|
||||
0xfc, 0x03, 0x00, 0x01, 0xff, 0x80, 0x01, 0xff, 0x00, 0xff, 0x00, 0xf0, 0x1c, 0x00, 0x07, 0xff,
|
||||
0xfc, 0x07, 0x80, 0x03, 0xfc, 0x00, 0x01, 0xfe, 0x01, 0xfc, 0x01, 0xe0, 0x1e, 0x00, 0x0f, 0xff,
|
||||
0xf8, 0x0f, 0xc0, 0x07, 0xf0, 0x0e, 0x00, 0xfc, 0x00, 0x00, 0x07, 0xc0, 0x3f, 0x00, 0x1f, 0xff,
|
||||
0xf0, 0x1f, 0xe0, 0x0f, 0x80, 0x3f, 0x00, 0x7c, 0x00, 0x00, 0x3f, 0xc0, 0x7f, 0x80, 0x3f, 0xff,
|
||||
0xe0, 0x3f, 0xf0, 0x0e, 0x01, 0xff, 0x80, 0x38, 0x00, 0x07, 0xff, 0x80, 0xff, 0x80, 0x7f, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
|
||||
};
|
||||
|
||||
// Logo POCASG/DAPNET, 128x16px
|
||||
const unsigned char logo_POCSAG_bmp [] =
|
||||
{
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xf8, 0x7f, 0xfe, 0x03, 0xfe, 0xfe, 0x03, 0xdf, 0xf6, 0x00, 0x00, 0x1f, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0x7f, 0xfe, 0xfc, 0xfc, 0xfe, 0xfc, 0xcf, 0xf6, 0xff, 0xfb, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0x7f, 0xfe, 0xfe, 0x7d, 0x7e, 0xfe, 0xc7, 0xf6, 0xff, 0xfb, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xfb, 0x7a, 0x7e, 0xff, 0x79, 0x7e, 0xfe, 0xd3, 0xf6, 0xff, 0xfb, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xf7, 0xbe, 0xff, 0x7b, 0xbe, 0xfe, 0xdb, 0xf6, 0xff, 0xfb, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xbe, 0xff, 0xbb, 0xbe, 0xfe, 0xdd, 0xf6, 0xff, 0xfb, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xf9, 0xff, 0xbe, 0xff, 0xb7, 0xde, 0xfe, 0xde, 0xf6, 0x01, 0xfb, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xee, 0x77, 0xbe, 0xff, 0xb7, 0xde, 0x81, 0xde, 0x76, 0xff, 0xfb, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xdf, 0xb7, 0x7e, 0xff, 0xa0, 0x1e, 0xff, 0xdf, 0x36, 0xff, 0xfb, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xdf, 0xbc, 0xfe, 0xff, 0x6f, 0xee, 0xff, 0xdf, 0xb6, 0xff, 0xfb, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xdf, 0xbf, 0xfe, 0xff, 0x6f, 0xee, 0xff, 0xdf, 0xd6, 0xff, 0xfb, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xdf, 0xbf, 0xfe, 0xfe, 0xdf, 0xf6, 0xff, 0xdf, 0xe6, 0xff, 0xfb, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xdf, 0x7f, 0xfe, 0xf9, 0xdf, 0xf6, 0xff, 0xdf, 0xe6, 0xff, 0xfb, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xe6, 0x7f, 0xfe, 0x07, 0xff, 0xf6, 0xff, 0xdf, 0xf6, 0x00, 0xfb, 0xff, 0xff,
|
||||
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
|
||||
};
|
||||
|
||||
|
|
@ -176,10 +197,10 @@ bool COLED::open()
|
|||
{
|
||||
// I2C change parameters to fit to your LCD
|
||||
if ( !display.init(OLED_I2C_RESET, m_displayType) )
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
display.begin();
|
||||
|
||||
display.invertDisplay(m_displayInvert ? 1 : 0);
|
||||
|
|
@ -200,7 +221,7 @@ bool COLED::open()
|
|||
|
||||
void COLED::setIdleInt()
|
||||
{
|
||||
m_mode = MODE_IDLE;
|
||||
m_mode = MODE_IDLE;
|
||||
|
||||
display.clearDisplay();
|
||||
OLED_statusbar();
|
||||
|
|
@ -212,26 +233,26 @@ void COLED::setIdleInt()
|
|||
// display.setTextSize(1);
|
||||
display.startscrolldiagright(0x00,0x0f); //the MMDVM logo scrolls the whole screen
|
||||
display.display();
|
||||
|
||||
unsigned char info[100U];
|
||||
CNetworkInfo* m_network;
|
||||
|
||||
passCounter ++;
|
||||
if (passCounter > 253U)
|
||||
networkInfoInitialized = false;
|
||||
|
||||
if (! networkInfoInitialized) {
|
||||
//LogMessage("Initialize CNetworkInfo");
|
||||
info[0]=0;
|
||||
m_network = new CNetworkInfo;
|
||||
m_network->getNetworkInterface(info);
|
||||
m_ipaddress = (char*)info;
|
||||
delete m_network;
|
||||
|
||||
networkInfoInitialized = true;
|
||||
passCounter = 0;
|
||||
}
|
||||
|
||||
|
||||
unsigned char info[100U];
|
||||
CNetworkInfo* m_network;
|
||||
|
||||
passCounter ++;
|
||||
if (passCounter > 253U)
|
||||
networkInfoInitialized = false;
|
||||
|
||||
if (! networkInfoInitialized) {
|
||||
//LogMessage("Initialize CNetworkInfo");
|
||||
info[0]=0;
|
||||
m_network = new CNetworkInfo;
|
||||
m_network->getNetworkInterface(info);
|
||||
m_ipaddress = (char*)info;
|
||||
delete m_network;
|
||||
|
||||
networkInfoInitialized = true;
|
||||
passCounter = 0;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void COLED::setErrorInt(const char* text)
|
||||
|
|
@ -262,6 +283,21 @@ void COLED::setLockoutInt()
|
|||
display.display();
|
||||
}
|
||||
|
||||
void COLED::setQuitInt()
|
||||
{
|
||||
m_mode = MODE_QUIT;
|
||||
|
||||
display.clearDisplay();
|
||||
OLED_statusbar();
|
||||
|
||||
display.setCursor(0,30);
|
||||
display.setTextSize(3);
|
||||
display.print("Stopped");
|
||||
|
||||
display.setTextSize(1);
|
||||
display.display();
|
||||
}
|
||||
|
||||
void COLED::writeDStarInt(const char* my1, const char* my2, const char* your, const char* type, const char* reflector)
|
||||
{
|
||||
m_mode = MODE_DSTAR;
|
||||
|
|
@ -277,9 +313,9 @@ void COLED::writeDStarInt(const char* my1, const char* my2, const char* your, co
|
|||
|
||||
display.setCursor(0,OLED_LINE5);
|
||||
display.printf("via %.8s",reflector);
|
||||
|
||||
display.setCursor(0,OLED_LINE6);
|
||||
display.printf("%s",m_ipaddress.c_str());
|
||||
|
||||
display.setCursor(0,OLED_LINE6);
|
||||
display.printf("%s",m_ipaddress.c_str());
|
||||
|
||||
OLED_statusbar();
|
||||
display.display();
|
||||
|
|
@ -291,9 +327,9 @@ void COLED::clearDStarInt()
|
|||
|
||||
display.setCursor(40,OLED_LINE3);
|
||||
display.print("Listening");
|
||||
|
||||
display.setCursor(0,OLED_LINE5);
|
||||
display.printf("%s",m_ipaddress.c_str());
|
||||
|
||||
display.setCursor(0,OLED_LINE5);
|
||||
display.printf("%s",m_ipaddress.c_str());
|
||||
|
||||
display.display();
|
||||
}
|
||||
|
|
@ -302,77 +338,74 @@ void COLED::writeDMRInt(unsigned int slotNo,const std::string& src,bool group,co
|
|||
{
|
||||
|
||||
if (m_mode != MODE_DMR) {
|
||||
display.clearDisplay();
|
||||
m_mode = MODE_DMR;
|
||||
clearDMRInt(slotNo);
|
||||
}
|
||||
// if both slots, use lines 2-3 for slot 1, lines 4-5 for slot 2
|
||||
// if single slot, use lines 3-4
|
||||
if ( m_slot1Enabled && m_slot2Enabled ) {
|
||||
display.clearDisplay();
|
||||
m_mode = MODE_DMR;
|
||||
clearDMRInt(slotNo);
|
||||
}
|
||||
// if both slots, use lines 2-3 for slot 1, lines 4-5 for slot 2
|
||||
// if single slot, use lines 3-4
|
||||
if ( m_slot1Enabled && m_slot2Enabled ) {
|
||||
|
||||
if (slotNo == 1U) {
|
||||
display.fillRect(0,OLED_LINE2,display.width(),40,BLACK);
|
||||
display.setCursor(0,OLED_LINE2);
|
||||
display.printf("%s",src.c_str());
|
||||
display.setCursor(0,OLED_LINE3);
|
||||
display.printf("Slot: %i %s %s%s",slotNo,type,group ? "TG: " : "",dst.c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
display.fillRect(0,OLED_LINE4,display.width(),40,BLACK);
|
||||
display.setCursor(0,OLED_LINE4);
|
||||
display.printf("%s",src.c_str());
|
||||
display.setCursor(0,OLED_LINE5);
|
||||
display.printf("Slot: %i %s %s%s",slotNo,type,group ? "TG: " : "",dst.c_str());
|
||||
}
|
||||
if (slotNo == 1U) {
|
||||
display.fillRect(0,OLED_LINE2,display.width(),40,BLACK);
|
||||
display.setCursor(0,OLED_LINE2);
|
||||
display.printf("%s",src.c_str());
|
||||
display.setCursor(0,OLED_LINE3);
|
||||
display.printf("Slot: %i %s %s%s",slotNo,type,group ? "TG: " : "",dst.c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
display.fillRect(0,OLED_LINE4,display.width(),40,BLACK);
|
||||
display.setCursor(0,OLED_LINE4);
|
||||
display.printf("%s",src.c_str());
|
||||
display.setCursor(0,OLED_LINE5);
|
||||
display.printf("Slot: %i %s %s%s",slotNo,type,group ? "TG: " : "",dst.c_str());
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
display.fillRect(0,OLED_LINE3,display.width(),20,BLACK);
|
||||
display.setCursor(0,OLED_LINE3);
|
||||
display.printf("%s",src.c_str());
|
||||
display.setCursor(0,OLED_LINE4);
|
||||
display.printf("Slot: %i %s %s%s",slotNo,type,group ? "TG: " : "",dst.c_str());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
display.fillRect(0,OLED_LINE3,display.width(),20,BLACK);
|
||||
display.setCursor(0,OLED_LINE3);
|
||||
display.printf("%s",src.c_str());
|
||||
display.setCursor(0,OLED_LINE4);
|
||||
display.printf("Slot: %i %s %s%s",slotNo,type,group ? "TG: " : "",dst.c_str());
|
||||
}
|
||||
|
||||
display.fillRect(0,OLED_LINE6,display.width(),20,BLACK);
|
||||
display.setCursor(0,OLED_LINE6);
|
||||
display.printf("%s",m_ipaddress.c_str());
|
||||
|
||||
display.fillRect(0,OLED_LINE6,display.width(),20,BLACK);
|
||||
display.setCursor(0,OLED_LINE6);
|
||||
display.printf("%s",m_ipaddress.c_str());
|
||||
|
||||
OLED_statusbar();
|
||||
display.display();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void COLED::clearDMRInt(unsigned int slotNo)
|
||||
{
|
||||
// if both slots, use lines 2-3 for slot 1, lines 4-5 for slot 2
|
||||
// if single slot, use lines 3-4
|
||||
if ( m_slot1Enabled && m_slot2Enabled ){
|
||||
if (slotNo == 1U)
|
||||
{
|
||||
display.fillRect(0, OLED_LINE3, display.width(), 40, BLACK);
|
||||
display.setCursor(0,OLED_LINE3);
|
||||
display.print("Slot: 1 Listening");
|
||||
}
|
||||
else
|
||||
{
|
||||
display.fillRect(0, OLED_LINE5, display.width(), 40, BLACK);
|
||||
display.setCursor(0, OLED_LINE5);
|
||||
display.print("Slot: 2 Listening");
|
||||
}
|
||||
}
|
||||
else {
|
||||
display.fillRect(0, OLED_LINE4, display.width(), 40, BLACK);
|
||||
display.setCursor(0,OLED_LINE4);
|
||||
display.printf("Slot: %i Listening",slotNo);
|
||||
}
|
||||
// if both slots, use lines 2-3 for slot 1, lines 4-5 for slot 2
|
||||
// if single slot, use lines 3-4
|
||||
if ( m_slot1Enabled && m_slot2Enabled ){
|
||||
if (slotNo == 1U) {
|
||||
display.fillRect(0, OLED_LINE3, display.width(), 40, BLACK);
|
||||
display.setCursor(0,OLED_LINE3);
|
||||
display.print("Slot: 1 Listening");
|
||||
}
|
||||
else {
|
||||
display.fillRect(0, OLED_LINE5, display.width(), 40, BLACK);
|
||||
display.setCursor(0, OLED_LINE5);
|
||||
display.print("Slot: 2 Listening");
|
||||
}
|
||||
}
|
||||
else {
|
||||
display.fillRect(0, OLED_LINE4, display.width(), 40, BLACK);
|
||||
display.setCursor(0,OLED_LINE4);
|
||||
display.printf("Slot: %i Listening",slotNo);
|
||||
}
|
||||
|
||||
|
||||
display.fillRect(0, OLED_LINE6, display.width(), 20, BLACK);
|
||||
display.setCursor(0,OLED_LINE6);
|
||||
display.printf("%s",m_ipaddress.c_str());
|
||||
display.fillRect(0, OLED_LINE6, display.width(), 20, BLACK);
|
||||
display.setCursor(0,OLED_LINE6);
|
||||
display.printf("%s",m_ipaddress.c_str());
|
||||
display.display();
|
||||
}
|
||||
|
||||
|
|
@ -400,9 +433,9 @@ void COLED::clearFusionInt()
|
|||
|
||||
display.setCursor(40,OLED_LINE4);
|
||||
display.print("Listening");
|
||||
|
||||
display.setCursor(0,OLED_LINE6);
|
||||
display.printf("%s",m_ipaddress.c_str());
|
||||
|
||||
display.setCursor(0,OLED_LINE6);
|
||||
display.printf("%s",m_ipaddress.c_str());
|
||||
|
||||
display.display();
|
||||
}
|
||||
|
|
@ -412,7 +445,7 @@ void COLED::writeP25Int(const char* source, bool group, unsigned int dest, const
|
|||
m_mode = MODE_P25;
|
||||
|
||||
display.clearDisplay();
|
||||
display.fillRect(0, OLED_LINE1, display.width(), display.height(), BLACK);
|
||||
display.fillRect(0, OLED_LINE2, display.width(), display.height(), BLACK);
|
||||
|
||||
display.setCursor(0,OLED_LINE3);
|
||||
display.printf("%s %.10s", type, source);
|
||||
|
|
@ -426,13 +459,13 @@ void COLED::writeP25Int(const char* source, bool group, unsigned int dest, const
|
|||
|
||||
void COLED::clearP25Int()
|
||||
{
|
||||
display.fillRect(0, OLED_LINE1, display.width(), display.height(), BLACK);
|
||||
display.fillRect(0, OLED_LINE2, display.width(), display.height(), BLACK);
|
||||
|
||||
display.setCursor(40,OLED_LINE4);
|
||||
display.print("Listening");
|
||||
|
||||
display.setCursor(0,OLED_LINE6);
|
||||
display.printf("%s",m_ipaddress.c_str());
|
||||
|
||||
display.setCursor(0,OLED_LINE6);
|
||||
display.printf("%s",m_ipaddress.c_str());
|
||||
|
||||
display.display();
|
||||
}
|
||||
|
|
@ -442,7 +475,7 @@ void COLED::writeNXDNInt(const char* source, bool group, unsigned int dest, cons
|
|||
m_mode = MODE_NXDN;
|
||||
|
||||
display.clearDisplay();
|
||||
display.fillRect(0, OLED_LINE1, display.width(), display.height(), BLACK);
|
||||
display.fillRect(0, OLED_LINE2, display.width(), display.height(), BLACK);
|
||||
|
||||
display.setCursor(0,OLED_LINE3);
|
||||
display.printf("%s %.10s", type, source);
|
||||
|
|
@ -455,14 +488,44 @@ void COLED::writeNXDNInt(const char* source, bool group, unsigned int dest, cons
|
|||
}
|
||||
|
||||
void COLED::clearNXDNInt()
|
||||
{
|
||||
display.fillRect(0, OLED_LINE2, display.width(), display.height(), BLACK);
|
||||
|
||||
display.setCursor(40,OLED_LINE4);
|
||||
display.print("Listening");
|
||||
|
||||
display.setCursor(0,OLED_LINE6);
|
||||
display.printf("%s",m_ipaddress.c_str());
|
||||
|
||||
display.display();
|
||||
}
|
||||
|
||||
void COLED::writePOCSAGInt(uint32_t ric, const std::string& message)
|
||||
{
|
||||
m_mode = MODE_POCSAG;
|
||||
|
||||
display.clearDisplay();
|
||||
display.fillRect(0, OLED_LINE1, display.width(), display.height(), BLACK);
|
||||
|
||||
display.setCursor(0,OLED_LINE3);
|
||||
display.printf("RIC: %u", ric);
|
||||
|
||||
display.setCursor(0,OLED_LINE5);
|
||||
display.printf("MSG: %s", message.c_str());
|
||||
|
||||
OLED_statusbar();
|
||||
display.display();
|
||||
}
|
||||
|
||||
void COLED::clearPOCSAGInt()
|
||||
{
|
||||
display.fillRect(0, OLED_LINE1, display.width(), display.height(), BLACK);
|
||||
|
||||
display.setCursor(40,OLED_LINE4);
|
||||
display.print("Listening");
|
||||
|
||||
display.setCursor(0,OLED_LINE6);
|
||||
display.printf("%s",m_ipaddress.c_str());
|
||||
|
||||
display.setCursor(0,OLED_LINE6);
|
||||
display.printf("%s",m_ipaddress.c_str());
|
||||
|
||||
display.display();
|
||||
}
|
||||
|
|
@ -496,13 +559,13 @@ void COLED::clearCWInt()
|
|||
void COLED::close()
|
||||
{
|
||||
display.clearDisplay();
|
||||
display.fillRect(0, 0, display.width(), 16, BLACK);
|
||||
display.startscrollright(0x00,0x01);
|
||||
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();
|
||||
}
|
||||
|
||||
|
|
@ -514,18 +577,20 @@ void COLED::OLED_statusbar()
|
|||
|
||||
display.setCursor(0,0);
|
||||
if (m_mode == MODE_DMR)
|
||||
display.drawBitmap(0, 0, logo_dmr_bmp, 128, 16, WHITE);
|
||||
display.drawBitmap(0, 0, logo_dmr_bmp, 128, 16, WHITE);
|
||||
else if (m_mode == MODE_DSTAR)
|
||||
display.drawBitmap(0, 0, logo_dstar_bmp, 128, 16, WHITE);
|
||||
display.drawBitmap(0, 0, logo_dstar_bmp, 128, 16, WHITE);
|
||||
else if (m_mode == MODE_YSF)
|
||||
display.drawBitmap(0, 0, logo_fusion_bmp, 128, 16, WHITE);
|
||||
display.drawBitmap(0, 0, logo_fusion_bmp, 128, 16, WHITE);
|
||||
else if (m_mode == MODE_P25)
|
||||
display.drawBitmap(0, 0, logo_P25_bmp, 128, 16, WHITE);
|
||||
display.drawBitmap(0, 0, logo_P25_bmp, 128, 16, WHITE);
|
||||
else if (m_mode == MODE_NXDN)
|
||||
display.drawBitmap(0, 0, logo_NXDN_bmp, 128, 16, WHITE);
|
||||
display.drawBitmap(0, 0, logo_NXDN_bmp, 128, 16, WHITE);
|
||||
else if (m_mode == MODE_POCSAG)
|
||||
display.drawBitmap(0, 0, logo_POCSAG_bmp, 128, 16, WHITE);
|
||||
else
|
||||
display.drawBitmap(0, 0, logo_glcd_bmp, 128, 16, WHITE);
|
||||
display.drawBitmap(0, 0, logo_glcd_bmp, 128, 16, WHITE);
|
||||
|
||||
if (m_displayScroll)
|
||||
display.startscrollright(0x00,0x02);
|
||||
display.startscrollright(0x00,0x02);
|
||||
}
|
||||
|
|
|
|||
5
OLED.h
5
OLED.h
|
|
@ -49,6 +49,8 @@ public:
|
|||
|
||||
virtual void setErrorInt(const char* text);
|
||||
virtual void setLockoutInt();
|
||||
virtual void setQuitInt();
|
||||
|
||||
|
||||
virtual void writeDStarInt(const char* my1, const char* my2, const char* your, const char* type, const char* reflector);
|
||||
virtual void clearDStarInt();
|
||||
|
|
@ -65,6 +67,9 @@ public:
|
|||
virtual void writeNXDNInt(const char* source, bool group, unsigned int dest, const char* type);
|
||||
virtual void clearNXDNInt();
|
||||
|
||||
virtual void writePOCSAGInt(uint32_t ric, const std::string& message);
|
||||
virtual void clearPOCSAGInt();
|
||||
|
||||
virtual void writeCWInt();
|
||||
virtual void clearCWInt();
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
/*
|
||||
* Copyright (C) 2016,2017,2018 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2018 by Bryan Biedenkapp <gatekeep@gmail.com>
|
||||
*
|
||||
* 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
|
||||
|
|
@ -176,6 +177,9 @@ bool CP25Control::writeModem(unsigned char* data, unsigned int len)
|
|||
case P25_DUID_PDU:
|
||||
duid = P25_DUID_PDU;
|
||||
break;
|
||||
case P25_DUID_TSDU:
|
||||
duid = P25_DUID_TSDU;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
@ -346,6 +350,85 @@ bool CP25Control::writeModem(unsigned char* data, unsigned int len)
|
|||
|
||||
return true;
|
||||
}
|
||||
} else if (duid == P25_DUID_TSDU) {
|
||||
if (m_rfState != RS_RF_DATA) {
|
||||
m_rfPDUCount = 0U;
|
||||
m_rfPDUBits = 0U;
|
||||
m_rfState = RS_RF_DATA;
|
||||
m_rfDataFrames = 0U;
|
||||
}
|
||||
|
||||
bool ret = m_rfData.decodeTSDU(data + 2U);
|
||||
if (!ret) {
|
||||
m_lastDUID = duid;
|
||||
return false;
|
||||
}
|
||||
|
||||
unsigned int srcId = m_rfData.getSrcId();
|
||||
unsigned int dstId = m_rfData.getDstId();
|
||||
|
||||
unsigned char data[P25_TSDU_FRAME_LENGTH_BYTES + 2U];
|
||||
|
||||
switch (m_rfData.getLCF()) {
|
||||
case P25_LCF_TSBK_CALL_ALERT:
|
||||
LogMessage("P25, received RF TSDU transmission, CALL ALERT from %u to %u", srcId, dstId);
|
||||
::memset(data + 2U, 0x00U, P25_TSDU_FRAME_LENGTH_BYTES);
|
||||
|
||||
// Regenerate Sync
|
||||
CSync::addP25Sync(data + 2U);
|
||||
|
||||
// Regenerate NID
|
||||
m_nid.encode(data + 2U, P25_DUID_TSDU);
|
||||
|
||||
// Regenerate TDULC Data
|
||||
m_rfData.encodeTSDU(data + 2U);
|
||||
|
||||
// Add busy bits
|
||||
addBusyBits(data + 2U, P25_TSDU_FRAME_LENGTH_BITS, true, false);
|
||||
|
||||
// Set first busy bits to 1,1
|
||||
setBusyBits(data + 2U, P25_SS0_START, true, true);
|
||||
|
||||
if (m_duplex) {
|
||||
data[0U] = TAG_DATA;
|
||||
data[1U] = 0x00U;
|
||||
|
||||
writeQueueRF(data, P25_TSDU_FRAME_LENGTH_BYTES + 2U);
|
||||
}
|
||||
break;
|
||||
case P25_LCF_TSBK_ACK_RSP_FNE:
|
||||
LogMessage("P25, received RF TSDU transmission, ACK RESPONSE FNE from %u to %u", srcId, dstId);
|
||||
::memset(data + 2U, 0x00U, P25_TSDU_FRAME_LENGTH_BYTES);
|
||||
|
||||
// Regenerate Sync
|
||||
CSync::addP25Sync(data + 2U);
|
||||
|
||||
// Regenerate NID
|
||||
m_nid.encode(data + 2U, P25_DUID_TSDU);
|
||||
|
||||
// Regenerate TDULC Data
|
||||
m_rfData.encodeTSDU(data + 2U);
|
||||
|
||||
// Add busy bits
|
||||
addBusyBits(data + 2U, P25_TSDU_FRAME_LENGTH_BITS, true, false);
|
||||
|
||||
// Set first busy bits to 1,1
|
||||
setBusyBits(data + 2U, P25_SS0_START, true, true);
|
||||
|
||||
if (m_duplex) {
|
||||
data[0U] = TAG_DATA;
|
||||
data[1U] = 0x00U;
|
||||
|
||||
writeQueueRF(data, P25_TSDU_FRAME_LENGTH_BYTES + 2U);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
LogMessage("P25, recieved RF TSDU transmission, unhandled LCF $%02X", m_rfData.getLCF());
|
||||
break;
|
||||
}
|
||||
|
||||
m_rfState = RS_RF_LISTENING;
|
||||
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);
|
||||
|
|
@ -512,6 +595,10 @@ unsigned int CP25Control::readModem(unsigned char* data)
|
|||
void CP25Control::writeNetwork()
|
||||
{
|
||||
unsigned char data[100U];
|
||||
|
||||
if (m_network == NULL)
|
||||
return;
|
||||
|
||||
unsigned int length = m_network->read(data, 100U);
|
||||
if (length == 0U)
|
||||
return;
|
||||
|
|
@ -693,6 +780,14 @@ void CP25Control::writeNetwork(const unsigned char *data, unsigned char type, bo
|
|||
}
|
||||
}
|
||||
|
||||
void CP25Control::setBusyBits(unsigned char* data, unsigned int ssOffset, bool b1, bool b2)
|
||||
{
|
||||
assert(data != NULL);
|
||||
|
||||
WRITE_BIT(data, ssOffset, b1);
|
||||
WRITE_BIT(data, ssOffset + 1U, b2);
|
||||
}
|
||||
|
||||
void CP25Control::addBusyBits(unsigned char* data, unsigned int length, bool b1, bool b2)
|
||||
{
|
||||
assert(data != NULL);
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
/*
|
||||
* Copyright (C) 2016,2017,2018 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2018 by Bryan Biedenkapp <gatekeep@gmail.com>
|
||||
*
|
||||
* 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
|
||||
|
|
@ -94,6 +95,7 @@ private:
|
|||
void writeNetwork(const unsigned char *data, unsigned char type, bool end);
|
||||
void writeNetwork();
|
||||
|
||||
void setBusyBits(unsigned char* data, unsigned int ssOffset, bool b1, bool b2);
|
||||
void addBusyBits(unsigned char* data, unsigned int length, bool b1, bool b2);
|
||||
|
||||
void checkNetLDU1();
|
||||
|
|
|
|||
125
P25Data.cpp
125
P25Data.cpp
|
|
@ -1,5 +1,6 @@
|
|||
/*
|
||||
* Copyright (C) 2016,2017 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2018 by Bryan Biedenkapp <gatekeep@gmail.com>
|
||||
*
|
||||
* 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
|
||||
|
|
@ -19,6 +20,7 @@
|
|||
#include "P25Data.h"
|
||||
#include "P25Defines.h"
|
||||
#include "P25Utils.h"
|
||||
#include "CRC.h"
|
||||
#include "Hamming.h"
|
||||
#include "Utils.h"
|
||||
#include "Log.h"
|
||||
|
|
@ -54,7 +56,8 @@ m_lcf(0x00U),
|
|||
m_emergency(false),
|
||||
m_srcId(0U),
|
||||
m_dstId(0U),
|
||||
m_rs241213()
|
||||
m_rs241213(),
|
||||
m_trellis()
|
||||
{
|
||||
m_mi = new unsigned char[P25_MI_LENGTH_BYTES];
|
||||
}
|
||||
|
|
@ -206,6 +209,116 @@ void CP25Data::encodeLDU2(unsigned char* data)
|
|||
CP25Utils::encode(raw, data, 1356U, 1398U);
|
||||
}
|
||||
|
||||
bool CP25Data::decodeTSDU(const unsigned char* data)
|
||||
{
|
||||
assert(data != NULL);
|
||||
|
||||
// deinterleave
|
||||
unsigned char tsbk[12U];
|
||||
unsigned char raw[25U];
|
||||
CP25Utils::decode(data, raw, 114U, 318U);
|
||||
|
||||
// decode 1/2 rate Trellis & check CRC-CCITT 16
|
||||
try {
|
||||
bool ret = m_trellis.decode12(raw, tsbk);
|
||||
if (ret)
|
||||
ret = CCRC::checkCCITT162(tsbk, 12U);
|
||||
if (!ret)
|
||||
return false;
|
||||
}
|
||||
catch (...) {
|
||||
CUtils::dump(2U, "P25, CRC failed with input data", tsbk, 12U);
|
||||
return false;
|
||||
}
|
||||
|
||||
m_lcf = tsbk[0U] & 0x3F;
|
||||
m_mfId = tsbk[1U];
|
||||
|
||||
unsigned long long tsbkValue = 0U;
|
||||
|
||||
// combine bytes into rs value
|
||||
tsbkValue = tsbk[2U];
|
||||
tsbkValue = (tsbkValue << 8) + tsbk[3U];
|
||||
tsbkValue = (tsbkValue << 8) + tsbk[4U];
|
||||
tsbkValue = (tsbkValue << 8) + tsbk[5U];
|
||||
tsbkValue = (tsbkValue << 8) + tsbk[6U];
|
||||
tsbkValue = (tsbkValue << 8) + tsbk[7U];
|
||||
tsbkValue = (tsbkValue << 8) + tsbk[8U];
|
||||
tsbkValue = (tsbkValue << 8) + tsbk[9U];
|
||||
|
||||
switch (m_lcf) {
|
||||
case P25_LCF_TSBK_CALL_ALERT:
|
||||
m_dstId = (unsigned int)((tsbkValue >> 24) & 0xFFFFFFU); // Target Radio Address
|
||||
m_srcId = (unsigned int)(tsbkValue & 0xFFFFFFU); // Source Radio Address
|
||||
break;
|
||||
case P25_LCF_TSBK_ACK_RSP_FNE:
|
||||
m_serviceType = (unsigned char)((tsbkValue >> 56) & 0xFFU); // Service Type
|
||||
m_dstId = (unsigned int)((tsbkValue >> 24) & 0xFFFFFFU); // Target Radio Address
|
||||
m_srcId = (unsigned int)(tsbkValue & 0xFFFFFFU); // Source Radio Address
|
||||
break;
|
||||
default:
|
||||
LogMessage("P25, unknown LCF value in TSDU - $%02X", m_lcf);
|
||||
break;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CP25Data::encodeTSDU(unsigned char* data)
|
||||
{
|
||||
assert(data != NULL);
|
||||
|
||||
unsigned char tsbk[12U];
|
||||
::memset(tsbk, 0x00U, 12U);
|
||||
|
||||
unsigned long long tsbkValue = 0U;
|
||||
tsbk[0U] = m_lcf;
|
||||
tsbk[0U] |= 0x80;
|
||||
|
||||
tsbk[1U] = m_mfId;
|
||||
|
||||
switch (m_lcf) {
|
||||
case P25_LCF_TSBK_CALL_ALERT:
|
||||
tsbkValue = 0U;
|
||||
tsbkValue = (tsbkValue << 16) + 0U;
|
||||
tsbkValue = (tsbkValue << 24) + m_dstId; // Target Radio Address
|
||||
tsbkValue = (tsbkValue << 24) + m_srcId; // Source Radio Address
|
||||
break;
|
||||
case P25_LCF_TSBK_ACK_RSP_FNE:
|
||||
tsbkValue = 0U; // Additional Info. Flag
|
||||
tsbkValue = (tsbkValue << 1) + 0U; // Extended Address Flag
|
||||
tsbkValue = (tsbkValue << 16) + (m_serviceType & 0xFF); // Service Type
|
||||
tsbkValue = (tsbkValue << 32) + m_dstId; // Target Radio Address
|
||||
tsbkValue = (tsbkValue << 24) + m_srcId; // Source Radio Address
|
||||
break;
|
||||
default:
|
||||
LogMessage("P25, unknown LCF value in TSDU - $%02X", m_lcf);
|
||||
break;
|
||||
}
|
||||
|
||||
// split rs value into bytes
|
||||
tsbk[2U] = (unsigned char)((tsbkValue >> 56) & 0xFFU);
|
||||
tsbk[3U] = (unsigned char)((tsbkValue >> 48) & 0xFFU);
|
||||
tsbk[4U] = (unsigned char)((tsbkValue >> 40) & 0xFFU);
|
||||
tsbk[5U] = (unsigned char)((tsbkValue >> 32) & 0xFFU);
|
||||
tsbk[6U] = (unsigned char)((tsbkValue >> 24) & 0xFFU);
|
||||
tsbk[7U] = (unsigned char)((tsbkValue >> 16) & 0xFFU);
|
||||
tsbk[8U] = (unsigned char)((tsbkValue >> 8) & 0xFFU);
|
||||
tsbk[9U] = (unsigned char)((tsbkValue >> 0) & 0xFFU);
|
||||
|
||||
// compute CRC-CCITT 16
|
||||
CCRC::addCCITT162(tsbk, 12U);
|
||||
|
||||
unsigned char raw[25U];
|
||||
::memset(raw, 0x00U, 25U);
|
||||
|
||||
// encode 1/2 rate Trellis
|
||||
m_trellis.encode12(tsbk, raw);
|
||||
|
||||
// interleave
|
||||
CP25Utils::encode(raw, data, 114U, 318U);
|
||||
}
|
||||
|
||||
void CP25Data::setMI(const unsigned char* mi)
|
||||
{
|
||||
assert(mi != NULL);
|
||||
|
|
@ -290,6 +403,16 @@ unsigned int CP25Data::getDstId() const
|
|||
return m_dstId;
|
||||
}
|
||||
|
||||
void CP25Data::setServiceType(unsigned char type)
|
||||
{
|
||||
m_serviceType = type;
|
||||
}
|
||||
|
||||
unsigned char CP25Data::getServiceType() const
|
||||
{
|
||||
return m_serviceType;
|
||||
}
|
||||
|
||||
void CP25Data::reset()
|
||||
{
|
||||
::memset(m_mi, 0x00U, P25_MI_LENGTH_BYTES);
|
||||
|
|
|
|||
10
P25Data.h
10
P25Data.h
|
|
@ -1,5 +1,6 @@
|
|||
/*
|
||||
* Copyright (C) 2016,2017 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2018 by Bryan Biedenkapp <gatekeep@gmail.com>
|
||||
*
|
||||
* 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
|
||||
|
|
@ -20,6 +21,7 @@
|
|||
#define P25Data_H
|
||||
|
||||
#include "RS241213.h"
|
||||
#include "P25Trellis.h"
|
||||
|
||||
class CP25Data {
|
||||
public:
|
||||
|
|
@ -33,6 +35,9 @@ public:
|
|||
|
||||
void encodeLDU2(unsigned char* data);
|
||||
|
||||
bool decodeTSDU(const unsigned char* data);
|
||||
void encodeTSDU(unsigned char* data);
|
||||
|
||||
void setMI(const unsigned char* mi);
|
||||
void getMI(unsigned char* mi) const;
|
||||
|
||||
|
|
@ -57,6 +62,9 @@ public:
|
|||
void setDstId(unsigned int id);
|
||||
unsigned int getDstId() const;
|
||||
|
||||
void setServiceType(unsigned char type);
|
||||
unsigned char getServiceType() const;
|
||||
|
||||
void reset();
|
||||
|
||||
private:
|
||||
|
|
@ -68,7 +76,9 @@ private:
|
|||
bool m_emergency;
|
||||
unsigned int m_srcId;
|
||||
unsigned int m_dstId;
|
||||
unsigned char m_serviceType;
|
||||
CRS241213 m_rs241213;
|
||||
CP25Trellis m_trellis;
|
||||
|
||||
void decodeLDUHamming(const unsigned char* raw, unsigned char* data);
|
||||
void encodeLDUHamming(unsigned char* data, const unsigned char* raw);
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
/*
|
||||
* Copyright (C) 2016 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2018 by Bryan Biedenkapp <gatekeep@gmail.com>
|
||||
*
|
||||
* 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
|
||||
|
|
@ -31,6 +32,9 @@ const unsigned int P25_TERM_FRAME_LENGTH_BITS = P25_TERM_FRAME_LENGTH_BYTES * 8
|
|||
const unsigned int P25_TERMLC_FRAME_LENGTH_BYTES = 54U;
|
||||
const unsigned int P25_TERMLC_FRAME_LENGTH_BITS = P25_TERMLC_FRAME_LENGTH_BYTES * 8U;
|
||||
|
||||
const unsigned int P25_TSDU_FRAME_LENGTH_BYTES = 45U;
|
||||
const unsigned int P25_TSDU_FRAME_LENGTH_BITS = P25_TSDU_FRAME_LENGTH_BYTES * 8U;
|
||||
|
||||
const unsigned int P25_SYNC_LENGTH_BYTES = 6U;
|
||||
const unsigned int P25_SYNC_LENGTH_BITS = P25_SYNC_LENGTH_BYTES * 8U;
|
||||
|
||||
|
|
@ -54,6 +58,9 @@ const unsigned int P25_MI_LENGTH_BYTES = 9U;
|
|||
const unsigned char P25_LCF_GROUP = 0x00U;
|
||||
const unsigned char P25_LCF_PRIVATE = 0x03U;
|
||||
|
||||
const unsigned char P25_LCF_TSBK_CALL_ALERT = 0x1FU;
|
||||
const unsigned char P25_LCF_TSBK_ACK_RSP_FNE = 0x20U;
|
||||
|
||||
const unsigned int P25_SS0_START = 70U;
|
||||
const unsigned int P25_SS1_START = 71U;
|
||||
const unsigned int P25_SS_INCREMENT = 72U;
|
||||
|
|
@ -61,6 +68,7 @@ const unsigned int P25_SS_INCREMENT = 72U;
|
|||
const unsigned char P25_DUID_HEADER = 0x00U;
|
||||
const unsigned char P25_DUID_TERM = 0x03U;
|
||||
const unsigned char P25_DUID_LDU1 = 0x05U;
|
||||
const unsigned char P25_DUID_TSDU = 0x07U;
|
||||
const unsigned char P25_DUID_LDU2 = 0x0AU;
|
||||
const unsigned char P25_DUID_PDU = 0x0CU;
|
||||
const unsigned char P25_DUID_TERM_LC = 0x0FU;
|
||||
|
|
|
|||
19
P25NID.cpp
19
P25NID.cpp
|
|
@ -1,5 +1,6 @@
|
|||
/*
|
||||
* Copyright (C) 2016,2018 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2018 by Bryan Biedenkapp <gatekeep@gmail.com>
|
||||
*
|
||||
* 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
|
||||
|
|
@ -33,6 +34,7 @@ m_ldu1(NULL),
|
|||
m_ldu2(NULL),
|
||||
m_termlc(NULL),
|
||||
m_term(NULL),
|
||||
m_tsdu(NULL),
|
||||
m_pdu(NULL)
|
||||
{
|
||||
CBCH bch;
|
||||
|
|
@ -72,6 +74,13 @@ m_pdu(NULL)
|
|||
bch.encode(m_term);
|
||||
m_term[7U] &= 0xFEU; // Clear the parity bit
|
||||
|
||||
m_tsdu = new unsigned char[P25_NID_LENGTH_BYTES];
|
||||
m_tsdu[0U] = (nac >> 4) & 0xFFU;
|
||||
m_tsdu[1U] = (nac << 4) & 0xF0U;
|
||||
m_tsdu[1U] |= P25_DUID_TSDU;
|
||||
bch.encode(m_tsdu);
|
||||
m_tsdu[7U] &= 0xFEU; // Clear the parity bit
|
||||
|
||||
m_pdu = new unsigned char[P25_NID_LENGTH_BYTES];
|
||||
m_pdu[0U] = (nac >> 4) & 0xFFU;
|
||||
m_pdu[1U] = (nac << 4) & 0xF0U;
|
||||
|
|
@ -87,6 +96,7 @@ CP25NID::~CP25NID()
|
|||
delete[] m_ldu2;
|
||||
delete[] m_termlc;
|
||||
delete[] m_term;
|
||||
delete[] m_tsdu;
|
||||
delete[] m_pdu;
|
||||
}
|
||||
|
||||
|
|
@ -127,6 +137,12 @@ bool CP25NID::decode(const unsigned char* data)
|
|||
return true;
|
||||
}
|
||||
|
||||
errs = CP25Utils::compare(nid, m_tsdu, P25_NID_LENGTH_BYTES);
|
||||
if (errs < MAX_NID_ERRS) {
|
||||
m_duid = P25_DUID_TSDU;
|
||||
return true;
|
||||
}
|
||||
|
||||
errs = CP25Utils::compare(nid, m_pdu, P25_NID_LENGTH_BYTES);
|
||||
if (errs < MAX_NID_ERRS) {
|
||||
m_duid = P25_DUID_PDU;
|
||||
|
|
@ -156,6 +172,9 @@ void CP25NID::encode(unsigned char* data, unsigned char duid) const
|
|||
case P25_DUID_TERM_LC:
|
||||
CP25Utils::encode(m_termlc, data, 48U, 114U);
|
||||
break;
|
||||
case P25_DUID_TSDU:
|
||||
CP25Utils::encode(m_tsdu, data, 48U, 114U);
|
||||
break;
|
||||
case P25_DUID_PDU:
|
||||
CP25Utils::encode(m_pdu, data, 48U, 114U);
|
||||
break;
|
||||
|
|
|
|||
2
P25NID.h
2
P25NID.h
|
|
@ -1,5 +1,6 @@
|
|||
/*
|
||||
* Copyright (C) 2016,2018 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2018 by Bryan Biedenkapp <gatekeep@gmail.com>
|
||||
*
|
||||
* 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
|
||||
|
|
@ -37,6 +38,7 @@ private:
|
|||
unsigned char* m_ldu2;
|
||||
unsigned char* m_termlc;
|
||||
unsigned char* m_term;
|
||||
unsigned char* m_tsdu;
|
||||
unsigned char* m_pdu;
|
||||
};
|
||||
|
||||
|
|
|
|||
416
POCSAGControl.cpp
Normal file
416
POCSAGControl.cpp
Normal file
|
|
@ -0,0 +1,416 @@
|
|||
/*
|
||||
* Copyright (C) 2018 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; version 2 of the License.
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include "POCSAGControl.h"
|
||||
#include "Utils.h"
|
||||
#include "Log.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
#include <ctime>
|
||||
|
||||
// #define DUMP_POCSAG
|
||||
|
||||
const struct BCD {
|
||||
char m_c;
|
||||
uint32_t m_bcd[5U];
|
||||
} BCD_VALUES[] = {
|
||||
{ '0', {0x00000000U, 0x00000000U, 0x00000000U, 0x00000000U, 0x00000000U}},
|
||||
{ '1', {0x40000000U, 0x04000000U, 0x00400000U, 0x00040000U, 0x00004000U}},
|
||||
{ '2', {0x20000000U, 0x02000000U, 0x00200000U, 0x00020000U, 0x00002000U}},
|
||||
{ '3', {0x60000000U, 0x06000000U, 0x00600000U, 0x00060000U, 0x00006000U}},
|
||||
{ '4', {0x10000000U, 0x01000000U, 0x00100000U, 0x00010000U, 0x00001000U}},
|
||||
{ '5', {0x50000000U, 0x05000000U, 0x00500000U, 0x00050000U, 0x00005000U}},
|
||||
{ '6', {0x30000000U, 0x03000000U, 0x00300000U, 0x00030000U, 0x00003000U}},
|
||||
{ '7', {0x70000000U, 0x07000000U, 0x00700000U, 0x00070000U, 0x00007000U}},
|
||||
{ '8', {0x08000000U, 0x00800000U, 0x00080000U, 0x00008000U, 0x00000800U}},
|
||||
{ '9', {0x48000000U, 0x04800000U, 0x00480000U, 0x00048000U, 0x00004800U}},
|
||||
{ 'U', {0x68000000U, 0x06800000U, 0x00680000U, 0x00068000U, 0x00006800U}},
|
||||
{ ' ', {0x18000000U, 0x01800000U, 0x00180000U, 0x00018000U, 0x00001800U}},
|
||||
{ '-', {0x58000000U, 0x05800000U, 0x00580000U, 0x00058000U, 0x00005800U}},
|
||||
{ ')', {0x38000000U, 0x03800000U, 0x00380000U, 0x00038000U, 0x00003800U}},
|
||||
{ '(', {0x78000000U, 0x07800000U, 0x00780000U, 0x00078000U, 0x00007800U}},
|
||||
{ 0, {0x00000000U, 0x00000000U, 0x00000000U, 0x00000000U, 0x00000000U}}
|
||||
};
|
||||
|
||||
const uint32_t BCD_SPACES[] = {0x19999800U, 0x01999800U, 0x00199800U, 0x00019800U, 0x00001800U};
|
||||
|
||||
const uint32_t DATA_MASK[] = { 0x40000000U, 0x20000000U, 0x10000000U,
|
||||
0x08000000U, 0x04000000U, 0x02000000U, 0x01000000U,
|
||||
0x00800000U, 0x00400000U, 0x00200000U, 0x00100000U,
|
||||
0x00080000U, 0x00040000U, 0x00020000U, 0x00010000U,
|
||||
0x00008000U, 0x00004000U, 0x00002000U, 0x00001000U,
|
||||
0x00000800U};
|
||||
|
||||
const unsigned char FUNCTIONAL_NUMERIC = 0U;
|
||||
const unsigned char FUNCTIONAL_ALERT1 = 1U;
|
||||
const unsigned char FUNCTIONAL_ALERT2 = 2U;
|
||||
const unsigned char FUNCTIONAL_ALPHANUMERIC = 3U;
|
||||
|
||||
CPOCSAGControl::CPOCSAGControl(CPOCSAGNetwork* network, CDisplay* display) :
|
||||
m_network(network),
|
||||
m_display(display),
|
||||
m_queue(5000U, "POCSAG Control"),
|
||||
m_frames(0U),
|
||||
m_count(0U),
|
||||
m_output(),
|
||||
m_buffer(),
|
||||
m_ric(0U),
|
||||
m_text(),
|
||||
m_state(PS_NONE),
|
||||
m_fp(NULL)
|
||||
{
|
||||
assert(display != NULL);
|
||||
}
|
||||
|
||||
CPOCSAGControl::~CPOCSAGControl()
|
||||
{
|
||||
m_output.clear();
|
||||
m_buffer.clear();
|
||||
}
|
||||
|
||||
unsigned int CPOCSAGControl::readModem(unsigned char* data)
|
||||
{
|
||||
assert(data != NULL);
|
||||
|
||||
if (m_queue.isEmpty())
|
||||
return 0U;
|
||||
|
||||
unsigned char len = 0U;
|
||||
m_queue.getData(&len, 1U);
|
||||
|
||||
m_queue.getData(data, len);
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
bool CPOCSAGControl::processData()
|
||||
{
|
||||
if (m_network == NULL)
|
||||
return false;
|
||||
|
||||
unsigned char data[300U];
|
||||
unsigned int length = m_network->read(data);
|
||||
if (length == 0U)
|
||||
return false;
|
||||
|
||||
m_ric = 0U;
|
||||
m_ric |= (data[0U] << 16) & 0x00FF0000U;
|
||||
m_ric |= (data[1U] << 8) & 0x0000FF00U;
|
||||
m_ric |= (data[2U] << 0) & 0x000000FFU;
|
||||
|
||||
unsigned char functional = data[3U];
|
||||
|
||||
m_buffer.clear();
|
||||
addAddress(functional);
|
||||
|
||||
switch (functional) {
|
||||
case FUNCTIONAL_ALPHANUMERIC:
|
||||
m_text = std::string((char*)(data + 4U), length - 4U);
|
||||
LogDebug("Message to %07u, func Alphanumeric: \"%s\"", m_ric, m_text.c_str());
|
||||
packASCII();
|
||||
break;
|
||||
case FUNCTIONAL_NUMERIC:
|
||||
m_text = std::string((char*)(data + 4U), length - 4U);
|
||||
LogDebug("Message to %07u, func Numeric: \"%s\"", m_ric, m_text.c_str());
|
||||
packNumeric();
|
||||
break;
|
||||
case FUNCTIONAL_ALERT1:
|
||||
m_text.clear();
|
||||
LogDebug("Message to %07u, func Alert 1", m_ric);
|
||||
break;
|
||||
case FUNCTIONAL_ALERT2:
|
||||
m_text = std::string((char*)(data + 4U), length - 4U);
|
||||
LogDebug("Message to %07u, func Alert 2: \"%s\"", m_ric, m_text.c_str());
|
||||
packASCII();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
// Ensure data is an even number of words
|
||||
if ((m_buffer.size() % 2U) == 1U)
|
||||
m_buffer.push_back(POCSAG_IDLE_WORD);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CPOCSAGControl::clock(unsigned int ms)
|
||||
{
|
||||
if (m_state == PS_NONE) {
|
||||
bool ret = processData();
|
||||
if (!ret)
|
||||
return;
|
||||
|
||||
m_display->writePOCSAG(m_ric, m_text);
|
||||
m_state = PS_WAITING;
|
||||
m_frames = 0U;
|
||||
m_count = 1U;
|
||||
|
||||
#if defined(DUMP_POCSAG)
|
||||
openFile();
|
||||
#endif
|
||||
}
|
||||
|
||||
m_output.clear();
|
||||
m_output.push_back(POCSAG_SYNC_WORD);
|
||||
|
||||
for (unsigned int i = 0U; i < POCSAG_FRAME_ADDRESSES; i++) {
|
||||
if (m_state == PS_WAITING) {
|
||||
if (i == (m_ric % POCSAG_FRAME_ADDRESSES)) {
|
||||
uint32_t w1 = m_buffer.front();
|
||||
m_buffer.pop_front();
|
||||
uint32_t w2 = m_buffer.front();
|
||||
m_buffer.pop_front();
|
||||
|
||||
m_output.push_back(w1);
|
||||
m_output.push_back(w2);
|
||||
|
||||
m_state = PS_SENDING;
|
||||
} else {
|
||||
m_output.push_back(POCSAG_IDLE_WORD);
|
||||
m_output.push_back(POCSAG_IDLE_WORD);
|
||||
}
|
||||
} else if (m_state == PS_SENDING) {
|
||||
if (m_buffer.empty()) {
|
||||
m_output.push_back(POCSAG_IDLE_WORD);
|
||||
m_output.push_back(POCSAG_IDLE_WORD);
|
||||
|
||||
bool ret = processData();
|
||||
if (ret) {
|
||||
m_display->writePOCSAG(m_ric, m_text);
|
||||
m_state = PS_WAITING;
|
||||
m_count++;
|
||||
} else {
|
||||
m_state = PS_ENDING;
|
||||
}
|
||||
} else {
|
||||
uint32_t w1 = m_buffer.front();
|
||||
m_buffer.pop_front();
|
||||
uint32_t w2 = m_buffer.front();
|
||||
m_buffer.pop_front();
|
||||
|
||||
m_output.push_back(w1);
|
||||
m_output.push_back(w2);
|
||||
}
|
||||
} else { // PS_ENDING
|
||||
m_output.push_back(POCSAG_IDLE_WORD);
|
||||
m_output.push_back(POCSAG_IDLE_WORD);
|
||||
}
|
||||
}
|
||||
|
||||
writeQueue();
|
||||
m_frames++;
|
||||
|
||||
if (m_state == PS_ENDING) {
|
||||
LogMessage("POCSAG, transmitted %u frame(s) of data from %u message(s)", m_frames, m_count);
|
||||
m_display->clearPOCSAG();
|
||||
m_state = PS_NONE;
|
||||
|
||||
#if defined(DUMP_POCSAG)
|
||||
closeFile();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
void CPOCSAGControl::addAddress(unsigned char functional)
|
||||
{
|
||||
uint32_t word = 0x00000000U;
|
||||
|
||||
switch (functional) {
|
||||
case FUNCTIONAL_ALPHANUMERIC:
|
||||
word = 0x00001800U;
|
||||
break;
|
||||
case FUNCTIONAL_ALERT1:
|
||||
word = 0x00000800U;
|
||||
break;
|
||||
case FUNCTIONAL_ALERT2:
|
||||
word = 0x00001000U;
|
||||
break;
|
||||
case FUNCTIONAL_NUMERIC:
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
word |= (m_ric / POCSAG_FRAME_ADDRESSES) << 13;
|
||||
|
||||
addBCHAndParity(word);
|
||||
|
||||
m_buffer.push_back(word);
|
||||
}
|
||||
|
||||
void CPOCSAGControl::packASCII()
|
||||
{
|
||||
const unsigned char MASK = 0x01U;
|
||||
|
||||
uint32_t word = 0x80000000U;
|
||||
unsigned int n = 0U;
|
||||
|
||||
for (std::string::const_iterator it = m_text.cbegin(); it != m_text.cend(); ++it) {
|
||||
unsigned char c = *it;
|
||||
for (unsigned int j = 0U; j < 7U; j++, c >>= 1) {
|
||||
bool b = (c & MASK) == MASK;
|
||||
if (b)
|
||||
word |= DATA_MASK[n];
|
||||
n++;
|
||||
|
||||
if (n == 20U) {
|
||||
addBCHAndParity(word);
|
||||
m_buffer.push_back(word);
|
||||
word = 0x80000000U;
|
||||
n = 0U;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (n > 0U) {
|
||||
addBCHAndParity(word);
|
||||
m_buffer.push_back(word);
|
||||
}
|
||||
}
|
||||
|
||||
void CPOCSAGControl::packNumeric()
|
||||
{
|
||||
uint32_t word = 0x80000000U;
|
||||
unsigned int n = 0U;
|
||||
|
||||
for (std::string::const_iterator it = m_text.cbegin(); it != m_text.cend(); ++it) {
|
||||
char c = *it;
|
||||
|
||||
const BCD* bcd = NULL;
|
||||
for (unsigned int i = 0U; BCD_VALUES[i].m_c != 0; i++) {
|
||||
if (BCD_VALUES[i].m_c == c) {
|
||||
bcd = BCD_VALUES + i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (bcd != NULL) {
|
||||
word |= bcd->m_bcd[n];
|
||||
n++;
|
||||
|
||||
if (n == 5U) {
|
||||
addBCHAndParity(word);
|
||||
m_buffer.push_back(word);
|
||||
word = 0x80000000U;
|
||||
n = 0U;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Pack the remainder of the word with BCD spaces.
|
||||
if (n != 0U) {
|
||||
word |= BCD_SPACES[n];
|
||||
|
||||
addBCHAndParity(word);
|
||||
m_buffer.push_back(word);
|
||||
}
|
||||
}
|
||||
|
||||
void CPOCSAGControl::addBCHAndParity(uint32_t& word) const
|
||||
{
|
||||
uint32_t temp = word;
|
||||
|
||||
for (unsigned int i = 0U; i < 21U; i++, temp <<= 1) {
|
||||
if (temp & 0x80000000U)
|
||||
temp ^= 0xED200000U;
|
||||
}
|
||||
|
||||
word |= (temp >> 21);
|
||||
|
||||
temp = word;
|
||||
|
||||
unsigned int parity = 0U;
|
||||
for (unsigned int i = 0U; i < 32U; i++, temp <<= 1) {
|
||||
if (temp & 0x80000000U)
|
||||
parity++;
|
||||
}
|
||||
|
||||
if ((parity % 2U) == 1U)
|
||||
word |= 0x00000001U;
|
||||
}
|
||||
|
||||
void CPOCSAGControl::writeQueue()
|
||||
{
|
||||
// Convert 32-bit words to bytes
|
||||
unsigned char data[POCSAG_FRAME_LENGTH_BYTES];
|
||||
unsigned char len = 0U;
|
||||
for (std::deque<uint32_t>::const_iterator it = m_output.cbegin(); it != m_output.cend(); ++it) {
|
||||
uint32_t word = *it;
|
||||
|
||||
data[len++] = word >> 24;
|
||||
data[len++] = word >> 16;
|
||||
data[len++] = word >> 8;
|
||||
data[len++] = word >> 0;
|
||||
}
|
||||
|
||||
m_output.clear();
|
||||
|
||||
#if defined(DUMP_POCSAG)
|
||||
writeFile(data);
|
||||
#endif
|
||||
|
||||
CUtils::dump(1U, "Data to MMDVM", data, len);
|
||||
|
||||
assert(len == POCSAG_FRAME_LENGTH_BYTES);
|
||||
|
||||
unsigned int space = m_queue.freeSpace();
|
||||
if (space < (len + 1U)) {
|
||||
LogError("POCSAG, overflow in the POCSAG RF queue");
|
||||
return;
|
||||
}
|
||||
|
||||
m_queue.addData(&len, 1U);
|
||||
m_queue.addData(data, len);
|
||||
}
|
||||
|
||||
bool CPOCSAGControl::openFile()
|
||||
{
|
||||
if (m_fp != NULL)
|
||||
return true;
|
||||
|
||||
time_t t;
|
||||
::time(&t);
|
||||
|
||||
struct tm* tm = ::localtime(&t);
|
||||
|
||||
char name[100U];
|
||||
::sprintf(name, "POCSAG_%04d%02d%02d_%02d%02d%02d.ambe", tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec);
|
||||
|
||||
m_fp = ::fopen(name, "wb");
|
||||
if (m_fp == NULL)
|
||||
return false;
|
||||
|
||||
::fwrite("POCSAG", 1U, 6U, m_fp);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CPOCSAGControl::writeFile(const unsigned char* data)
|
||||
{
|
||||
if (m_fp == NULL)
|
||||
return false;
|
||||
|
||||
::fwrite(data, 1U, POCSAG_FRAME_LENGTH_BYTES, m_fp);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CPOCSAGControl::closeFile()
|
||||
{
|
||||
if (m_fp != NULL) {
|
||||
::fclose(m_fp);
|
||||
m_fp = NULL;
|
||||
}
|
||||
}
|
||||
74
POCSAGControl.h
Normal file
74
POCSAGControl.h
Normal file
|
|
@ -0,0 +1,74 @@
|
|||
/*
|
||||
* Copyright (C) 2018 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(POCSAGControl_H)
|
||||
#define POCSAGControl_H
|
||||
|
||||
#include "POCSAGNetwork.h"
|
||||
#include "POCSAGDefines.h"
|
||||
#include "RingBuffer.h"
|
||||
#include "Display.h"
|
||||
#include "Defines.h"
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
#include <string>
|
||||
#include <deque>
|
||||
|
||||
class CPOCSAGControl {
|
||||
public:
|
||||
CPOCSAGControl(CPOCSAGNetwork* network, CDisplay* display);
|
||||
~CPOCSAGControl();
|
||||
|
||||
unsigned int readModem(unsigned char* data);
|
||||
|
||||
void clock(unsigned int ms);
|
||||
|
||||
private:
|
||||
CPOCSAGNetwork* m_network;
|
||||
CDisplay* m_display;
|
||||
CRingBuffer<unsigned char> m_queue;
|
||||
unsigned int m_frames;
|
||||
unsigned int m_count;
|
||||
|
||||
enum POCSAG_STATE {
|
||||
PS_NONE,
|
||||
PS_WAITING,
|
||||
PS_SENDING,
|
||||
PS_ENDING
|
||||
};
|
||||
|
||||
std::deque<uint32_t> m_output;
|
||||
std::deque<uint32_t> m_buffer;
|
||||
uint32_t m_ric;
|
||||
std::string m_text;
|
||||
POCSAG_STATE m_state;
|
||||
FILE* m_fp;
|
||||
|
||||
bool processData();
|
||||
void writeQueue();
|
||||
void addAddress(unsigned char functional);
|
||||
void packASCII();
|
||||
void packNumeric();
|
||||
void addBCHAndParity(uint32_t& word) const;
|
||||
bool openFile();
|
||||
bool writeFile(const unsigned char* data);
|
||||
void closeFile();
|
||||
};
|
||||
|
||||
#endif
|
||||
35
POCSAGDefines.h
Normal file
35
POCSAGDefines.h
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
* Copyright (C) 2018 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(POCSAGDEFINES_H)
|
||||
#define POCSAGDEFINES_H
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
const unsigned int POCSAG_RADIO_SYMBOL_LENGTH = 20U; // At 24 kHz sample rate
|
||||
|
||||
const unsigned int POCSAG_FRAME_LENGTH_WORDS = 17U;
|
||||
const unsigned int POCSAG_FRAME_LENGTH_BYTES = POCSAG_FRAME_LENGTH_WORDS * sizeof(uint32_t);
|
||||
|
||||
const unsigned int POCSAG_FRAME_ADDRESSES = 8U;
|
||||
|
||||
const uint32_t POCSAG_SYNC_WORD = 0x7CD215D8U;
|
||||
|
||||
const uint32_t POCSAG_IDLE_WORD = 0x7A89C197U;
|
||||
|
||||
#endif
|
||||
122
POCSAGNetwork.cpp
Normal file
122
POCSAGNetwork.cpp
Normal file
|
|
@ -0,0 +1,122 @@
|
|||
/*
|
||||
* Copyright (C) 2018 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 "POCSAGDefines.h"
|
||||
#include "POCSAGNetwork.h"
|
||||
#include "Defines.h"
|
||||
#include "Utils.h"
|
||||
#include "Log.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
|
||||
const unsigned int BUFFER_LENGTH = 200U;
|
||||
|
||||
CPOCSAGNetwork::CPOCSAGNetwork(const std::string& myAddress, unsigned int myPort, const std::string& gatewayAddress, unsigned int gatewayPort, bool debug) :
|
||||
m_socket(myAddress, myPort),
|
||||
m_address(),
|
||||
m_port(gatewayPort),
|
||||
m_debug(debug),
|
||||
m_enabled(false),
|
||||
m_buffer(1000U, "POCSAG Network")
|
||||
{
|
||||
m_address = CUDPSocket::lookup(gatewayAddress);
|
||||
}
|
||||
|
||||
CPOCSAGNetwork::~CPOCSAGNetwork()
|
||||
{
|
||||
}
|
||||
|
||||
bool CPOCSAGNetwork::open()
|
||||
{
|
||||
LogMessage("Opening POCSAG network connection");
|
||||
|
||||
if (m_address.s_addr == INADDR_NONE)
|
||||
return false;
|
||||
|
||||
return m_socket.open();
|
||||
}
|
||||
|
||||
void CPOCSAGNetwork::clock(unsigned int ms)
|
||||
{
|
||||
unsigned char buffer[BUFFER_LENGTH];
|
||||
|
||||
in_addr address;
|
||||
unsigned int port;
|
||||
int length = m_socket.read(buffer, BUFFER_LENGTH, address, port);
|
||||
if (length <= 0)
|
||||
return;
|
||||
|
||||
// Check if the data is for us
|
||||
if (m_address.s_addr != address.s_addr || m_port != port) {
|
||||
LogMessage("POCSAG packet received from an invalid source, %08X != %08X and/or %u != %u", m_address.s_addr, address.s_addr, m_port, port);
|
||||
return;
|
||||
}
|
||||
|
||||
// Invalid packet type?
|
||||
if (::memcmp(buffer, "POCSAG", 6U) != 0)
|
||||
return;
|
||||
|
||||
if (!m_enabled)
|
||||
return;
|
||||
|
||||
if (m_debug)
|
||||
CUtils::dump(1U, "POCSAG Network Data Received", buffer, length);
|
||||
|
||||
unsigned char len = length - 6U;
|
||||
m_buffer.addData(&len, 1U);
|
||||
m_buffer.addData(buffer + 6U, length - 6U);
|
||||
}
|
||||
|
||||
unsigned int CPOCSAGNetwork::read(unsigned char* data)
|
||||
{
|
||||
assert(data != NULL);
|
||||
|
||||
if (m_buffer.isEmpty())
|
||||
return 0U;
|
||||
|
||||
unsigned char len = 0U;
|
||||
m_buffer.getData(&len, 1U);
|
||||
m_buffer.getData(data, len);
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
void CPOCSAGNetwork::reset()
|
||||
{
|
||||
}
|
||||
|
||||
void CPOCSAGNetwork::close()
|
||||
{
|
||||
m_socket.close();
|
||||
|
||||
LogMessage("Closing POCSAG network connection");
|
||||
}
|
||||
|
||||
void CPOCSAGNetwork::enable(bool enabled)
|
||||
{
|
||||
if (enabled && !m_enabled)
|
||||
reset();
|
||||
|
||||
unsigned char c = enabled ? 0x00U : 0xFFU;
|
||||
|
||||
m_socket.write(&c, 1U, m_address, m_port);
|
||||
|
||||
m_enabled = enabled;
|
||||
}
|
||||
56
POCSAGNetwork.h
Normal file
56
POCSAGNetwork.h
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
/*
|
||||
* Copyright (C) 2018 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.
|
||||
*/
|
||||
|
||||
#ifndef POCSAGNetwork_H
|
||||
#define POCSAGNetwork_H
|
||||
|
||||
#include "POCSAGDefines.h"
|
||||
#include "RingBuffer.h"
|
||||
#include "UDPSocket.h"
|
||||
#include "Timer.h"
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
|
||||
class CPOCSAGNetwork {
|
||||
public:
|
||||
CPOCSAGNetwork(const std::string& myAddress, unsigned int myPort, const std::string& gatewayAddress, unsigned int gatewayPort, bool debug);
|
||||
~CPOCSAGNetwork();
|
||||
|
||||
bool open();
|
||||
|
||||
void enable(bool enabled);
|
||||
|
||||
unsigned int read(unsigned char* data);
|
||||
|
||||
void reset();
|
||||
|
||||
void close();
|
||||
|
||||
void clock(unsigned int ms);
|
||||
|
||||
private:
|
||||
CUDPSocket m_socket;
|
||||
in_addr m_address;
|
||||
unsigned int m_port;
|
||||
bool m_debug;
|
||||
bool m_enabled;
|
||||
CRingBuffer<unsigned char> m_buffer;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
@ -1,6 +1,6 @@
|
|||
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, NXDN, and System Fusion on the MMDVM, and D-Star, DMR, and System Fusion on the DVMega.
|
||||
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, NXDN, System Fusion, and POCSAG paging on the MMDVM, and D-Star, DMR, and System Fusion on the DVMega.
|
||||
|
||||
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.
|
||||
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 to allow access to the FCS and YSF networks. On P25 it connects to the P25 Gateway. On NXDN it connects to the NXDN Gateway which provides access to the NXDN and NXCore talk groups. Finally it uses the DAPNET Gateway to access DAPNET to receive paging messages.
|
||||
|
||||
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:
|
||||
|
||||
|
|
@ -8,7 +8,7 @@ It builds on 32-bit and 64-bit Linux as well as on Windows using Visual Studio 2
|
|||
- Support for HD44780 via 4 bit GPIO connection (user selectable pins)
|
||||
- Adafruit 16x2 LCD+Keypad Kits (I2C)
|
||||
- Connection via PCF8574 GPIO Extender (I2C)
|
||||
- Nextion TFTs (sizes 2.4", 2.8", 3.2" and 3.5")
|
||||
- Nextion TFTs (all sizes, both Basic and Enhanced versions)
|
||||
- TFT display sold by Hobbytronics in UK
|
||||
- OLED 128x64 (SSD1306)
|
||||
- LCDproc
|
||||
|
|
|
|||
|
|
@ -35,6 +35,9 @@
|
|||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <termios.h>
|
||||
#if !defined(__APPLE__)
|
||||
#include <linux/i2c-dev.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
|
|
@ -237,119 +240,120 @@ CSerialController::~CSerialController()
|
|||
bool CSerialController::open()
|
||||
{
|
||||
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*/
|
||||
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) {
|
||||
LogError("Cannot open device - %s", m_device.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
if (::isatty(m_fd) == 0) {
|
||||
LogError("%s is not a TTY device", m_device.c_str());
|
||||
::close(m_fd);
|
||||
return false;
|
||||
}
|
||||
|
||||
termios termios;
|
||||
if (::tcgetattr(m_fd, &termios) < 0) {
|
||||
LogError("Cannot get the attributes for %s", m_device.c_str());
|
||||
::close(m_fd);
|
||||
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_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON | IXOFF | IXANY);
|
||||
termios.c_cflag &= ~(CSIZE | CSTOPB | PARENB | CRTSCTS);
|
||||
termios.c_cflag |= CS8;
|
||||
termios.c_oflag &= ~(OPOST);
|
||||
termios.c_cc[VMIN] = 0;
|
||||
termios.c_cc[VTIME] = 10;
|
||||
#endif
|
||||
|
||||
switch (m_speed) {
|
||||
case SERIAL_1200:
|
||||
::cfsetospeed(&termios, B1200);
|
||||
::cfsetispeed(&termios, B1200);
|
||||
break;
|
||||
case SERIAL_2400:
|
||||
::cfsetospeed(&termios, B2400);
|
||||
::cfsetispeed(&termios, B2400);
|
||||
break;
|
||||
case SERIAL_4800:
|
||||
::cfsetospeed(&termios, B4800);
|
||||
::cfsetispeed(&termios, B4800);
|
||||
break;
|
||||
case SERIAL_9600:
|
||||
::cfsetospeed(&termios, B9600);
|
||||
::cfsetispeed(&termios, B9600);
|
||||
break;
|
||||
case SERIAL_19200:
|
||||
::cfsetospeed(&termios, B19200);
|
||||
::cfsetispeed(&termios, B19200);
|
||||
break;
|
||||
case SERIAL_38400:
|
||||
::cfsetospeed(&termios, B38400);
|
||||
::cfsetispeed(&termios, B38400);
|
||||
break;
|
||||
case SERIAL_115200:
|
||||
::cfsetospeed(&termios, B115200);
|
||||
::cfsetispeed(&termios, B115200);
|
||||
break;
|
||||
case SERIAL_230400:
|
||||
::cfsetospeed(&termios, B230400);
|
||||
::cfsetispeed(&termios, B230400);
|
||||
break;
|
||||
default:
|
||||
LogError("Unsupported serial port speed - %d", int(m_speed));
|
||||
::close(m_fd);
|
||||
if (m_fd < 0) {
|
||||
LogError("Cannot open device - %s", m_device.c_str());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (::tcsetattr(m_fd, TCSANOW, &termios) < 0) {
|
||||
LogError("Cannot set the attributes for %s", m_device.c_str());
|
||||
::close(m_fd);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (m_assertRTS) {
|
||||
unsigned int y;
|
||||
if (::ioctl(m_fd, TIOCMGET, &y) < 0) {
|
||||
LogError("Cannot get the control attributes for %s", m_device.c_str());
|
||||
if (::isatty(m_fd) == 0) {
|
||||
LogError("%s is not a TTY device", m_device.c_str());
|
||||
::close(m_fd);
|
||||
return false;
|
||||
}
|
||||
|
||||
y |= TIOCM_RTS;
|
||||
|
||||
if (::ioctl(m_fd, TIOCMSET, &y) < 0) {
|
||||
LogError("Cannot set the control attributes for %s", m_device.c_str());
|
||||
termios termios;
|
||||
if (::tcgetattr(m_fd, &termios) < 0) {
|
||||
LogError("Cannot get the attributes for %s", m_device.c_str());
|
||||
::close(m_fd);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(__APPLE__)
|
||||
setNonblock(false);
|
||||
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_iflag &= ~(BRKINT | ICRNL | INPCK | ISTRIP | IXON | IXOFF | IXANY);
|
||||
termios.c_cflag &= ~(CSIZE | CSTOPB | PARENB | CRTSCTS);
|
||||
termios.c_cflag |= CS8;
|
||||
termios.c_oflag &= ~(OPOST);
|
||||
termios.c_cc[VMIN] = 0;
|
||||
termios.c_cc[VTIME] = 10;
|
||||
#endif
|
||||
|
||||
switch (m_speed) {
|
||||
case SERIAL_1200:
|
||||
::cfsetospeed(&termios, B1200);
|
||||
::cfsetispeed(&termios, B1200);
|
||||
break;
|
||||
case SERIAL_2400:
|
||||
::cfsetospeed(&termios, B2400);
|
||||
::cfsetispeed(&termios, B2400);
|
||||
break;
|
||||
case SERIAL_4800:
|
||||
::cfsetospeed(&termios, B4800);
|
||||
::cfsetispeed(&termios, B4800);
|
||||
break;
|
||||
case SERIAL_9600:
|
||||
::cfsetospeed(&termios, B9600);
|
||||
::cfsetispeed(&termios, B9600);
|
||||
break;
|
||||
case SERIAL_19200:
|
||||
::cfsetospeed(&termios, B19200);
|
||||
::cfsetispeed(&termios, B19200);
|
||||
break;
|
||||
case SERIAL_38400:
|
||||
::cfsetospeed(&termios, B38400);
|
||||
::cfsetispeed(&termios, B38400);
|
||||
break;
|
||||
case SERIAL_115200:
|
||||
::cfsetospeed(&termios, B115200);
|
||||
::cfsetispeed(&termios, B115200);
|
||||
break;
|
||||
case SERIAL_230400:
|
||||
::cfsetospeed(&termios, B230400);
|
||||
::cfsetispeed(&termios, B230400);
|
||||
break;
|
||||
default:
|
||||
LogError("Unsupported serial port speed - %d", int(m_speed));
|
||||
::close(m_fd);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (::tcsetattr(m_fd, TCSANOW, &termios) < 0) {
|
||||
LogError("Cannot set the attributes for %s", m_device.c_str());
|
||||
::close(m_fd);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (m_assertRTS) {
|
||||
unsigned int y;
|
||||
if (::ioctl(m_fd, TIOCMGET, &y) < 0) {
|
||||
LogError("Cannot get the control attributes for %s", m_device.c_str());
|
||||
::close(m_fd);
|
||||
return false;
|
||||
}
|
||||
|
||||
y |= TIOCM_RTS;
|
||||
|
||||
if (::ioctl(m_fd, TIOCMSET, &y) < 0) {
|
||||
LogError("Cannot set the control attributes for %s", m_device.c_str());
|
||||
::close(m_fd);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(__APPLE__)
|
||||
setNonblock(false);
|
||||
#endif
|
||||
|
||||
return true;
|
||||
|
|
@ -380,6 +384,7 @@ int CSerialController::read(unsigned char* buffer, unsigned int length)
|
|||
unsigned int offset = 0U;
|
||||
|
||||
while (offset < length) {
|
||||
|
||||
fd_set fds;
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(m_fd, &fds);
|
||||
|
|
|
|||
|
|
@ -57,7 +57,7 @@ public:
|
|||
virtual int setNonblock(bool nonblock);
|
||||
#endif
|
||||
|
||||
private:
|
||||
protected:
|
||||
std::string m_device;
|
||||
SERIAL_SPEED m_speed;
|
||||
bool m_assertRTS;
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2015,2016 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2015,2016,2018 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
|
||||
|
|
@ -21,21 +21,32 @@
|
|||
#if defined(_WIN32) || defined(_WIN64)
|
||||
|
||||
CStopWatch::CStopWatch() :
|
||||
m_frequency(),
|
||||
m_frequencyS(),
|
||||
m_frequencyMS(),
|
||||
m_start()
|
||||
{
|
||||
::QueryPerformanceFrequency(&m_frequency);
|
||||
::QueryPerformanceFrequency(&m_frequencyS);
|
||||
|
||||
m_frequencyMS.QuadPart = m_frequencyS.QuadPart / 1000ULL;
|
||||
}
|
||||
|
||||
CStopWatch::~CStopWatch()
|
||||
{
|
||||
}
|
||||
|
||||
unsigned long CStopWatch::start()
|
||||
unsigned long long CStopWatch::time() const
|
||||
{
|
||||
LARGE_INTEGER now;
|
||||
::QueryPerformanceCounter(&now);
|
||||
|
||||
return (unsigned long long)(now.QuadPart / m_frequencyMS.QuadPart);
|
||||
}
|
||||
|
||||
unsigned long long CStopWatch::start()
|
||||
{
|
||||
::QueryPerformanceCounter(&m_start);
|
||||
|
||||
return (unsigned long)(m_start.QuadPart / m_frequency.QuadPart);
|
||||
return (unsigned long long)(m_start.QuadPart / m_frequencyS.QuadPart);
|
||||
}
|
||||
|
||||
unsigned int CStopWatch::elapsed()
|
||||
|
|
@ -46,15 +57,16 @@ unsigned int CStopWatch::elapsed()
|
|||
LARGE_INTEGER temp;
|
||||
temp.QuadPart = (now.QuadPart - m_start.QuadPart) * 1000;
|
||||
|
||||
return (unsigned int)(temp.QuadPart / m_frequency.QuadPart);
|
||||
return (unsigned int)(temp.QuadPart / m_frequencyS.QuadPart);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#include <cstdio>
|
||||
#include <ctime>
|
||||
|
||||
CStopWatch::CStopWatch() :
|
||||
m_start()
|
||||
m_startMS(0ULL)
|
||||
{
|
||||
}
|
||||
|
||||
|
|
@ -62,23 +74,32 @@ CStopWatch::~CStopWatch()
|
|||
{
|
||||
}
|
||||
|
||||
unsigned long CStopWatch::start()
|
||||
{
|
||||
::gettimeofday(&m_start, NULL);
|
||||
|
||||
return m_start.tv_usec;
|
||||
}
|
||||
|
||||
unsigned int CStopWatch::elapsed()
|
||||
unsigned long long CStopWatch::time() const
|
||||
{
|
||||
struct timeval now;
|
||||
::gettimeofday(&now, NULL);
|
||||
|
||||
unsigned int elapsed = (now.tv_sec - m_start.tv_sec) * 1000U;
|
||||
elapsed += now.tv_usec / 1000U;
|
||||
elapsed -= m_start.tv_usec / 1000U;
|
||||
return now.tv_sec * 1000ULL + now.tv_usec / 1000ULL;
|
||||
}
|
||||
|
||||
return elapsed;
|
||||
unsigned long long CStopWatch::start()
|
||||
{
|
||||
struct timespec now;
|
||||
::clock_gettime(CLOCK_MONOTONIC, &now);
|
||||
|
||||
m_startMS = now.tv_sec * 1000ULL + now.tv_nsec / 1000000ULL;
|
||||
|
||||
return m_startMS;
|
||||
}
|
||||
|
||||
unsigned int CStopWatch::elapsed()
|
||||
{
|
||||
struct timespec now;
|
||||
::clock_gettime(CLOCK_MONOTONIC, &now);
|
||||
|
||||
unsigned long long nowMS = now.tv_sec * 1000ULL + now.tv_nsec / 1000000ULL;
|
||||
|
||||
return nowMS - m_startMS;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
|||
13
StopWatch.h
13
StopWatch.h
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2015,2016 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2015,2016,2018 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
|
||||
|
|
@ -31,15 +31,18 @@ public:
|
|||
CStopWatch();
|
||||
~CStopWatch();
|
||||
|
||||
unsigned long start();
|
||||
unsigned int elapsed();
|
||||
unsigned long long time() const;
|
||||
|
||||
unsigned long long start();
|
||||
unsigned int elapsed();
|
||||
|
||||
private:
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
LARGE_INTEGER m_frequency;
|
||||
LARGE_INTEGER m_frequencyS;
|
||||
LARGE_INTEGER m_frequencyMS;
|
||||
LARGE_INTEGER m_start;
|
||||
#else
|
||||
struct timeval m_start;
|
||||
unsigned long long m_startMS;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -145,6 +145,22 @@ void CTFTSerial::setLockoutInt()
|
|||
m_mode = MODE_LOCKOUT;
|
||||
}
|
||||
|
||||
void CTFTSerial::setQuitInt()
|
||||
{
|
||||
// Clear the screen
|
||||
clearScreen();
|
||||
|
||||
setFontSize(FONT_LARGE);
|
||||
|
||||
// Draw MMDVM logo
|
||||
displayBitmap(0U, 0U, "MMDVM_sm.bmp");
|
||||
|
||||
gotoPosPixel(20U, 60U);
|
||||
displayText("STOPPED");
|
||||
|
||||
m_mode = MODE_QUIT;
|
||||
}
|
||||
|
||||
void CTFTSerial::writeDStarInt(const char* my1, const char* my2, const char* your, const char* type, const char* reflector)
|
||||
{
|
||||
assert(my1 != NULL);
|
||||
|
|
@ -395,6 +411,20 @@ void CTFTSerial::clearNXDNInt()
|
|||
displayText(" ");
|
||||
}
|
||||
|
||||
void CTFTSerial::writePOCSAGInt(uint32_t ric, const std::string& message)
|
||||
{
|
||||
gotoPosPixel(15U, 90U);
|
||||
displayText("POCSAG TX");
|
||||
|
||||
m_mode = MODE_CW;
|
||||
}
|
||||
|
||||
void CTFTSerial::clearPOCSAGInt()
|
||||
{
|
||||
gotoPosPixel(45U, 90U);
|
||||
displayText("IDLE");
|
||||
}
|
||||
|
||||
void CTFTSerial::writeCWInt()
|
||||
{
|
||||
gotoPosPixel(45U, 90U);
|
||||
|
|
|
|||
|
|
@ -39,6 +39,7 @@ protected:
|
|||
virtual void setIdleInt();
|
||||
virtual void setErrorInt(const char* text);
|
||||
virtual void setLockoutInt();
|
||||
virtual void setQuitInt();
|
||||
|
||||
virtual void writeDStarInt(const char* my1, const char* my2, const char* your, const char* type, const char* reflector);
|
||||
virtual void clearDStarInt();
|
||||
|
|
@ -55,6 +56,9 @@ protected:
|
|||
virtual void writeNXDNInt(const char* source, bool group, unsigned int dest, const char* type);
|
||||
virtual void clearNXDNInt();
|
||||
|
||||
virtual void writePOCSAGInt(uint32_t ric, const std::string& message);
|
||||
virtual void clearPOCSAGInt();
|
||||
|
||||
virtual void writeCWInt();
|
||||
virtual void clearCWInt();
|
||||
|
||||
|
|
|
|||
29
UMP/UMP.ino
29
UMP/UMP.ino
|
|
@ -29,6 +29,7 @@
|
|||
#define PIN_YSF 5
|
||||
#define PIN_P25 6
|
||||
#define PIN_NXDN 7
|
||||
#define PIN_POCSAG 8
|
||||
|
||||
#define PIN_TX 10
|
||||
#define PIN_CD 11
|
||||
|
|
@ -64,17 +65,19 @@ void setup()
|
|||
pinMode(PIN_YSF, OUTPUT);
|
||||
pinMode(PIN_P25, OUTPUT);
|
||||
pinMode(PIN_NXDN, OUTPUT);
|
||||
pinMode(PIN_POCSAG, OUTPUT);
|
||||
pinMode(PIN_TX, OUTPUT);
|
||||
pinMode(PIN_CD, OUTPUT);
|
||||
pinMode(PIN_LOCKOUT, INPUT);
|
||||
|
||||
digitalWrite(PIN_DSTAR, LOW);
|
||||
digitalWrite(PIN_DMR, LOW);
|
||||
digitalWrite(PIN_YSF, LOW);
|
||||
digitalWrite(PIN_P25, LOW);
|
||||
digitalWrite(PIN_NXDN, LOW);
|
||||
digitalWrite(PIN_TX, LOW);
|
||||
digitalWrite(PIN_CD, LOW);
|
||||
digitalWrite(PIN_DSTAR, LOW);
|
||||
digitalWrite(PIN_DMR, LOW);
|
||||
digitalWrite(PIN_YSF, LOW);
|
||||
digitalWrite(PIN_P25, LOW);
|
||||
digitalWrite(PIN_NXDN, LOW);
|
||||
digitalWrite(PIN_POCSAG, LOW);
|
||||
digitalWrite(PIN_TX, LOW);
|
||||
digitalWrite(PIN_CD, LOW);
|
||||
}
|
||||
|
||||
#define UMP_FRAME_START 0xF0U
|
||||
|
|
@ -95,6 +98,7 @@ void setup()
|
|||
#define MODE_YSF 3U
|
||||
#define MODE_P25 4U
|
||||
#define MODE_NXDN 5U
|
||||
#define MODE_POCSAG 6U
|
||||
|
||||
bool m_started = false;
|
||||
uint32_t m_count = 0U;
|
||||
|
|
@ -129,11 +133,12 @@ void loop()
|
|||
m_started = true;
|
||||
break;
|
||||
case UMP_SET_MODE:
|
||||
digitalWrite(PIN_DSTAR, m_buffer[3U] == MODE_DSTAR ? HIGH : LOW);
|
||||
digitalWrite(PIN_DMR, m_buffer[3U] == MODE_DMR ? HIGH : LOW);
|
||||
digitalWrite(PIN_YSF, m_buffer[3U] == MODE_YSF ? HIGH : LOW);
|
||||
digitalWrite(PIN_P25, m_buffer[3U] == MODE_P25 ? HIGH : LOW);
|
||||
digitalWrite(PIN_NXDN, m_buffer[3U] == MODE_NXDN ? HIGH : LOW);
|
||||
digitalWrite(PIN_DSTAR, m_buffer[3U] == MODE_DSTAR ? HIGH : LOW);
|
||||
digitalWrite(PIN_DMR, m_buffer[3U] == MODE_DMR ? HIGH : LOW);
|
||||
digitalWrite(PIN_YSF, m_buffer[3U] == MODE_YSF ? HIGH : LOW);
|
||||
digitalWrite(PIN_P25, m_buffer[3U] == MODE_P25 ? HIGH : LOW);
|
||||
digitalWrite(PIN_NXDN, m_buffer[3U] == MODE_NXDN ? HIGH : LOW);
|
||||
digitalWrite(PIN_POCSAG, m_buffer[3U] == MODE_POCSAG ? HIGH : LOW);
|
||||
break;
|
||||
case UMP_SET_TX:
|
||||
digitalWrite(PIN_TX, m_buffer[3U] == 0x01U ? HIGH : LOW);
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2015,2016,2017 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2015,2016,2017,2018 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
|
||||
|
|
@ -19,6 +19,6 @@
|
|||
#if !defined(VERSION_H)
|
||||
#define VERSION_H
|
||||
|
||||
const char* VERSION = "20180327";
|
||||
const char* VERSION = "20180723";
|
||||
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -52,8 +52,8 @@
|
|||
DMRIDPATH=/path/to/DMR/ID/file
|
||||
DMRIDFILE=${DMRIDPATH}/DMRIds.dat
|
||||
|
||||
# DMR-MARC.net has discontinued real time access. Now they offer a nightly dump instead.
|
||||
DATABASEURL='https://www.dmr-marc.net/static/users.csv'
|
||||
# DMR IDs now served by RadioID.net
|
||||
DATABASEURL='https://ham-digital.org/status/users.csv'
|
||||
|
||||
#
|
||||
# How many DMR ID files do you want backed up (0 = do not keep backups)
|
||||
|
|
|
|||
Loading…
Reference in a new issue