Make space for dPMR.

This commit is contained in:
Jonathan Naylor 2025-07-09 13:38:55 +01:00
parent 994bff73ba
commit 9720c7a40d
52 changed files with 38 additions and 3684 deletions

View file

@ -128,16 +128,6 @@ void CCASTInfo::clearNXDNInt()
{
}
void CCASTInfo::writeM17Int(const char* source, const char* dest, const char* type)
{
if (m_modem != nullptr)
m_modem->writeM17Info(source, dest, type);
}
void CCASTInfo::clearM17Int()
{
}
void CCASTInfo::writePOCSAGInt(uint32_t ric, const std::string& message)
{
if (m_modem != nullptr)

View file

@ -1,5 +1,5 @@
/*
* Copyright (C) 2016,2018,2020,2021 by Jonathan Naylor G4KLX
* Copyright (C) 2016,2018,2020,2021,2025 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
@ -58,9 +58,6 @@ protected:
virtual void writeNXDNInt(const char* source, bool group, unsigned int dest, const char* type);
virtual void clearNXDNInt();
virtual void writeM17Int(const char* source, const char* dest, const char* type);
virtual void clearM17Int();
virtual void writePOCSAGInt(uint32_t ric, const std::string& message);
virtual void clearPOCSAGInt();

130
Conf.cpp
View file

@ -42,7 +42,6 @@ enum class SECTION {
FUSION,
P25,
NXDN,
M17,
POCSAG,
FM,
AX25,
@ -51,7 +50,6 @@ enum class SECTION {
FUSION_NETWORK,
P25_NETWORK,
NXDN_NETWORK,
M17_NETWORK,
POCSAG_NETWORK,
FM_NETWORK,
AX25_NETWORK,
@ -119,7 +117,6 @@ m_modemDMRTXLevel(50.0F),
m_modemYSFTXLevel(50.0F),
m_modemP25TXLevel(50.0F),
m_modemNXDNTXLevel(50.0F),
m_modemM17TXLevel(50.0F),
m_modemPOCSAGTXLevel(50.0F),
m_modemFMTXLevel(50.0F),
m_modemAX25TXLevel(50.0F),
@ -183,12 +180,6 @@ m_nxdnSelfOnly(false),
m_nxdnRemoteGateway(false),
m_nxdnTXHang(5U),
m_nxdnModeHang(10U),
m_m17Enabled(false),
m_m17CAN(0U),
m_m17SelfOnly(false),
m_m17AllowEncryption(false),
m_m17TXHang(5U),
m_m17ModeHang(10U),
m_pocsagEnabled(false),
m_pocsagFrequency(0U),
m_fmEnabled(false),
@ -275,13 +266,6 @@ m_nxdnLocalAddress(),
m_nxdnLocalPort(0U),
m_nxdnNetworkModeHang(3U),
m_nxdnNetworkDebug(false),
m_m17NetworkEnabled(false),
m_m17GatewayAddress(),
m_m17GatewayPort(0U),
m_m17LocalAddress(),
m_m17LocalPort(0U),
m_m17NetworkModeHang(3U),
m_m17NetworkDebug(false),
m_pocsagNetworkEnabled(false),
m_pocsagGatewayAddress(),
m_pocsagGatewayPort(0U),
@ -395,8 +379,6 @@ bool CConf::read()
section = SECTION::P25;
else if (::strncmp(buffer, "[NXDN]", 6U) == 0)
section = SECTION::NXDN;
else if (::strncmp(buffer, "[M17]", 5U) == 0)
section = SECTION::M17;
else if (::strncmp(buffer, "[POCSAG]", 8U) == 0)
section = SECTION::POCSAG;
else if (::strncmp(buffer, "[FM]", 4U) == 0)
@ -413,8 +395,6 @@ bool CConf::read()
section = SECTION::P25_NETWORK;
else if (::strncmp(buffer, "[NXDN Network]", 14U) == 0)
section = SECTION::NXDN_NETWORK;
else if (::strncmp(buffer, "[M17 Network]", 13U) == 0)
section = SECTION::M17_NETWORK;
else if (::strncmp(buffer, "[POCSAG Network]", 16U) == 0)
section = SECTION::POCSAG_NETWORK;
else if (::strncmp(buffer, "[FM Network]", 12U) == 0)
@ -479,12 +459,12 @@ bool CConf::read()
else if (::strcmp(key, "Duplex") == 0)
m_duplex = ::atoi(value) == 1;
else if (::strcmp(key, "ModeHang") == 0)
m_dstarNetworkModeHang = m_dmrNetworkModeHang = m_fusionNetworkModeHang = m_p25NetworkModeHang = m_nxdnNetworkModeHang = m_m17NetworkModeHang = m_fmNetworkModeHang =
m_dstarModeHang = m_dmrModeHang = m_fusionModeHang = m_p25ModeHang = m_nxdnModeHang = m_m17ModeHang = m_fmModeHang = (unsigned int)::atoi(value);
m_dstarNetworkModeHang = m_dmrNetworkModeHang = m_fusionNetworkModeHang = m_p25NetworkModeHang = m_nxdnNetworkModeHang = m_fmNetworkModeHang =
m_dstarModeHang = m_dmrModeHang = m_fusionModeHang = m_p25ModeHang = m_nxdnModeHang = m_fmModeHang = (unsigned int)::atoi(value);
else if (::strcmp(key, "RFModeHang") == 0)
m_dstarModeHang = m_dmrModeHang = m_fusionModeHang = m_p25ModeHang = m_nxdnModeHang = m_m17ModeHang = m_fmModeHang = (unsigned int)::atoi(value);
m_dstarModeHang = m_dmrModeHang = m_fusionModeHang = m_p25ModeHang = m_nxdnModeHang = m_fmModeHang = (unsigned int)::atoi(value);
else if (::strcmp(key, "NetModeHang") == 0)
m_dstarNetworkModeHang = m_dmrNetworkModeHang = m_fusionNetworkModeHang = m_p25NetworkModeHang = m_nxdnNetworkModeHang = m_m17NetworkModeHang = m_fmNetworkModeHang = (unsigned int)::atoi(value);
m_dstarNetworkModeHang = m_dmrNetworkModeHang = m_fusionNetworkModeHang = m_p25NetworkModeHang = m_nxdnNetworkModeHang = m_fmNetworkModeHang = (unsigned int)::atoi(value);
else if (::strcmp(key, "Display") == 0)
m_display = value;
else if (::strcmp(key, "Daemon") == 0)
@ -582,7 +562,7 @@ bool CConf::read()
else if (::strcmp(key, "RXLevel") == 0)
m_modemRXLevel = float(::atof(value));
else if (::strcmp(key, "TXLevel") == 0)
m_modemAX25TXLevel = m_modemFMTXLevel = m_modemCWIdTXLevel = m_modemDStarTXLevel = m_modemDMRTXLevel = m_modemYSFTXLevel = m_modemP25TXLevel = m_modemNXDNTXLevel = m_modemM17TXLevel = m_modemPOCSAGTXLevel = float(::atof(value));
m_modemAX25TXLevel = m_modemFMTXLevel = m_modemCWIdTXLevel = m_modemDStarTXLevel = m_modemDMRTXLevel = m_modemYSFTXLevel = m_modemP25TXLevel = m_modemNXDNTXLevel = m_modemPOCSAGTXLevel = float(::atof(value));
else if (::strcmp(key, "CWIdTXLevel") == 0)
m_modemCWIdTXLevel = float(::atof(value));
else if (::strcmp(key, "D-StarTXLevel") == 0)
@ -595,8 +575,6 @@ bool CConf::read()
m_modemP25TXLevel = float(::atof(value));
else if (::strcmp(key, "NXDNTXLevel") == 0)
m_modemNXDNTXLevel = float(::atof(value));
else if (::strcmp(key, "M17TXLevel") == 0)
m_modemM17TXLevel = float(::atof(value));
else if (::strcmp(key, "POCSAGTXLevel") == 0)
m_modemPOCSAGTXLevel = float(::atof(value));
else if (::strcmp(key, "FMTXLevel") == 0)
@ -801,19 +779,6 @@ bool CConf::read()
m_nxdnTXHang = (unsigned int)::atoi(value);
else if (::strcmp(key, "ModeHang") == 0)
m_nxdnModeHang = (unsigned int)::atoi(value);
} else if (section == SECTION::M17) {
if (::strcmp(key, "Enable") == 0)
m_m17Enabled = ::atoi(value) == 1;
else if (::strcmp(key, "CAN") == 0)
m_m17CAN = (unsigned int)::atoi(value);
else if (::strcmp(key, "SelfOnly") == 0)
m_m17SelfOnly = ::atoi(value) == 1;
else if (::strcmp(key, "AllowEncryption") == 0)
m_m17AllowEncryption = ::atoi(value) == 1;
else if (::strcmp(key, "TXHang") == 0)
m_m17TXHang = (unsigned int)::atoi(value);
else if (::strcmp(key, "ModeHang") == 0)
m_m17ModeHang = (unsigned int)::atoi(value);
} else if (section == SECTION::POCSAG) {
if (::strcmp(key, "Enable") == 0)
m_pocsagEnabled = ::atoi(value) == 1;
@ -1007,21 +972,6 @@ bool CConf::read()
m_nxdnNetworkModeHang = (unsigned int)::atoi(value);
else if (::strcmp(key, "Debug") == 0)
m_nxdnNetworkDebug = ::atoi(value) == 1;
} else if (section == SECTION::M17_NETWORK) {
if (::strcmp(key, "Enable") == 0)
m_m17NetworkEnabled = ::atoi(value) == 1;
else if (::strcmp(key, "LocalAddress") == 0)
m_m17LocalAddress = value;
else if (::strcmp(key, "LocalPort") == 0)
m_m17LocalPort = (unsigned short)::atoi(value);
else if (::strcmp(key, "GatewayAddress") == 0)
m_m17GatewayAddress = value;
else if (::strcmp(key, "GatewayPort") == 0)
m_m17GatewayPort = (unsigned short)::atoi(value);
else if (::strcmp(key, "ModeHang") == 0)
m_m17NetworkModeHang = (unsigned int)::atoi(value);
else if (::strcmp(key, "Debug") == 0)
m_m17NetworkDebug = ::atoi(value) == 1;
} else if (section == SECTION::POCSAG_NETWORK) {
if (::strcmp(key, "Enable") == 0)
m_pocsagNetworkEnabled = ::atoi(value) == 1;
@ -1437,11 +1387,6 @@ float CConf::getModemNXDNTXLevel() const
return m_modemNXDNTXLevel;
}
float CConf::getModemM17TXLevel() const
{
return m_modemM17TXLevel;
}
float CConf::getModemPOCSAGTXLevel() const
{
return m_modemPOCSAGTXLevel;
@ -1757,36 +1702,6 @@ unsigned int CConf::getNXDNModeHang() const
return m_nxdnModeHang;
}
bool CConf::getM17Enabled() const
{
return m_m17Enabled;
}
unsigned int CConf::getM17CAN() const
{
return m_m17CAN;
}
bool CConf::getM17SelfOnly() const
{
return m_m17SelfOnly;
}
bool CConf::getM17AllowEncryption() const
{
return m_m17AllowEncryption;
}
unsigned int CConf::getM17TXHang() const
{
return m_m17TXHang;
}
unsigned int CConf::getM17ModeHang() const
{
return m_m17ModeHang;
}
bool CConf::getPOCSAGEnabled() const
{
return m_pocsagEnabled;
@ -2217,41 +2132,6 @@ bool CConf::getNXDNNetworkDebug() const
return m_nxdnNetworkDebug;
}
bool CConf::getM17NetworkEnabled() const
{
return m_m17NetworkEnabled;
}
std::string CConf::getM17GatewayAddress() const
{
return m_m17GatewayAddress;
}
unsigned short CConf::getM17GatewayPort() const
{
return m_m17GatewayPort;
}
std::string CConf::getM17LocalAddress() const
{
return m_m17LocalAddress;
}
unsigned short CConf::getM17LocalPort() const
{
return m_m17LocalPort;
}
unsigned int CConf::getM17NetworkModeHang() const
{
return m_m17NetworkModeHang;
}
bool CConf::getM17NetworkDebug() const
{
return m_m17NetworkDebug;
}
bool CConf::getPOCSAGNetworkEnabled() const
{
return m_pocsagNetworkEnabled;

34
Conf.h
View file

@ -96,7 +96,6 @@ public:
float getModemYSFTXLevel() const;
float getModemP25TXLevel() const;
float getModemNXDNTXLevel() const;
float getModemM17TXLevel() const;
float getModemPOCSAGTXLevel() const;
float getModemFMTXLevel() const;
float getModemAX25TXLevel() const;
@ -173,14 +172,6 @@ public:
unsigned int getNXDNTXHang() const;
unsigned int getNXDNModeHang() const;
// The M17 section
bool getM17Enabled() const;
unsigned int getM17CAN() const;
bool getM17SelfOnly() const;
bool getM17AllowEncryption() const;
unsigned int getM17TXHang() const;
unsigned int getM17ModeHang() const;
// The POCSAG section
bool getPOCSAGEnabled() const;
unsigned int getPOCSAGFrequency() const;
@ -283,15 +274,6 @@ public:
unsigned int getNXDNNetworkModeHang() const;
bool getNXDNNetworkDebug() const;
// The M17 Network section
bool getM17NetworkEnabled() const;
std::string getM17GatewayAddress() const;
unsigned short getM17GatewayPort() const;
std::string getM17LocalAddress() const;
unsigned short getM17LocalPort() const;
unsigned int getM17NetworkModeHang() const;
bool getM17NetworkDebug() const;
// The POCSAG Network section
bool getPOCSAGNetworkEnabled() const;
std::string getPOCSAGGatewayAddress() const;
@ -437,7 +419,6 @@ private:
float m_modemYSFTXLevel;
float m_modemP25TXLevel;
float m_modemNXDNTXLevel;
float m_modemM17TXLevel;
float m_modemPOCSAGTXLevel;
float m_modemFMTXLevel;
float m_modemAX25TXLevel;
@ -508,13 +489,6 @@ private:
unsigned int m_nxdnTXHang;
unsigned int m_nxdnModeHang;
bool m_m17Enabled;
unsigned int m_m17CAN;
bool m_m17SelfOnly;
bool m_m17AllowEncryption;
unsigned int m_m17TXHang;
unsigned int m_m17ModeHang;
bool m_pocsagEnabled;
unsigned int m_pocsagFrequency;
@ -609,14 +583,6 @@ private:
unsigned int m_nxdnNetworkModeHang;
bool m_nxdnNetworkDebug;
bool m_m17NetworkEnabled;
std::string m_m17GatewayAddress;
unsigned short m_m17GatewayPort;
std::string m_m17LocalAddress;
unsigned short m_m17LocalPort;
unsigned int m_m17NetworkModeHang;
bool m_m17NetworkDebug;
bool m_pocsagNetworkEnabled;
std::string m_pocsagGatewayAddress;
unsigned short m_pocsagGatewayPort;

View file

@ -26,7 +26,6 @@ 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_M17 = 7U;
const unsigned char MODE_FM = 10U;

View file

@ -339,40 +339,6 @@ void CDisplay::clearNXDN()
}
}
void CDisplay::writeM17(const char* source, const char* dest, const char* type)
{
assert(source != nullptr);
assert(dest != nullptr);
assert(type != nullptr);
m_timer1.start();
m_mode1 = MODE_IDLE;
writeM17Int(source, dest, type);
}
void CDisplay::writeM17RSSI(unsigned char rssi)
{
if (rssi != 0U)
writeM17RSSIInt(rssi);
}
void CDisplay::writeM17BER(float ber)
{
writeM17BERInt(ber);
}
void CDisplay::clearM17()
{
if (m_timer1.hasExpired()) {
clearM17Int();
m_timer1.stop();
m_mode1 = MODE_IDLE;
} else {
m_mode1 = MODE_M17;
}
}
void CDisplay::writePOCSAG(uint32_t ric, const std::string& message)
{
m_timer1.start();
@ -430,11 +396,6 @@ void CDisplay::clock(unsigned int ms)
m_mode1 = MODE_IDLE;
m_timer1.stop();
break;
case MODE_M17:
clearM17Int();
m_mode1 = MODE_IDLE;
m_timer1.stop();
break;
case MODE_POCSAG:
clearPOCSAGInt();
m_mode1 = MODE_IDLE;
@ -525,14 +486,6 @@ void CDisplay::writeNXDNBERInt(float ber)
{
}
void CDisplay::writeM17RSSIInt(unsigned char rssi)
{
}
void CDisplay::writeM17BERInt(float ber)
{
}
int CDisplay::writeNXDNIntEx(const class CUserDBentry& source, bool group, unsigned int dest, const char* type)
{
/* return value definition is same as writeDMRIntEx() */

View file

@ -1,5 +1,5 @@
/*
* Copyright (C) 2016,2017,2018,2020,2021,2023 by Jonathan Naylor G4KLX
* Copyright (C) 2016,2017,2018,2020,2021,2023,2025 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
@ -72,11 +72,6 @@ public:
void writeNXDNBER(float ber);
void clearNXDN();
void writeM17(const char* source, const char* dest, const char* type);
void writeM17RSSI(unsigned char rssi);
void writeM17BER(float ber);
void clearM17();
void writePOCSAG(uint32_t ric, const std::string& message);
void clearPOCSAG();
@ -123,11 +118,6 @@ protected:
virtual void writeNXDNBERInt(float ber);
virtual void clearNXDNInt() = 0;
virtual void writeM17Int(const char* source, const char* dest, const char* type) = 0;
virtual void writeM17RSSIInt(unsigned char rssi);
virtual void writeM17BERInt(float ber);
virtual void clearM17Int() = 0;
virtual void writePOCSAGInt(uint32_t ric, const std::string& message) = 0;
virtual void clearPOCSAGInt() = 0;

View file

@ -1,5 +1,5 @@
/*
* Copyright (C) 2016,2017,2018,2020,2021 by Jonathan Naylor G4KLX & Tony Corbett G0WFV
* Copyright (C) 2016,2017,2018,2020,2021,2025 by Jonathan Naylor G4KLX & Tony Corbett G0WFV
*
* 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
@ -41,7 +41,6 @@ const unsigned int DMR_RSSI_COUNT = 4U; // 4 * 360ms = 1440ms
const unsigned int YSF_RSSI_COUNT = 13U; // 13 * 100ms = 1300ms
const unsigned int P25_RSSI_COUNT = 7U; // 7 * 180ms = 1260ms
const unsigned int NXDN_RSSI_COUNT = 28U; // 28 * 40ms = 1120ms
const unsigned int M17_RSSI_COUNT = 28U; // 28 * 40ms = 1120ms
CHD44780::CHD44780(unsigned int rows, unsigned int cols, const std::string& callsign, unsigned int dmrid, const std::vector<unsigned int>& pins, unsigned int i2cAddress, bool pwm, unsigned int pwmPin, unsigned int pwmBright, unsigned int pwmDim, bool displayClock, bool utc, bool duplex) :
CDisplay(),
@ -1032,105 +1031,6 @@ void CHD44780::clearNXDNInt()
}
}
void CHD44780::writeM17Int(const char* source, const char* dest, const char* type)
{
assert(source != NULL);
assert(dest != NULL);
assert(type != NULL);
#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, "M17");
::sprintf(m_buffer1, "%.9s", source);
::sprintf(m_buffer2, "%.9s", dest);
if (m_rows == 2U && m_cols == 16U) {
::lcdPosition(m_fd, 5, 0);
::lcdPrintf(m_fd, "%.*s", m_cols - 5, m_buffer1);
::lcdPosition(m_fd, 5, 1);
::lcdPrintf(m_fd, "%.*s", m_cols - 5, m_buffer2);
} else if (m_rows == 4U && m_cols == 16U) {
::lcdPosition(m_fd, 0, 1);
::lcdPrintf(m_fd, "%.*s", m_cols, m_buffer1);
::lcdPosition(m_fd, 0, 2);
::lcdPrintf(m_fd, "%.*s", m_cols, m_buffer2);
} else if (m_rows == 4U && m_cols == 20U) {
::lcdPosition(m_fd, 0, 1);
::lcdPrintf(m_fd, "%.*s", m_cols, m_buffer1);
::lcdPosition(m_fd, 0, 2);
::lcdPrintf(m_fd, "%.*s", m_cols, m_buffer1);
} else if (m_rows == 2 && m_cols == 40U) {
::sprintf(m_buffer1, "%.9s > %.9s", source, dest);
::lcdPosition(m_fd, 0, 1);
::lcdPrintf(m_fd, "%.*s", m_cols, m_buffer1);
}
m_dmr = false;
m_rssiCount1 = 0U;
}
void CHD44780::writeM17RSSIInt(unsigned char rssi)
{
if (m_rssiCount1 == 0U && m_rows > 2) {
::lcdPosition(m_fd, 0, 3);
::lcdPrintf(m_fd, "-%3udBm", rssi);
}
m_rssiCount1++;
if (m_rssiCount1 >= M17_RSSI_COUNT)
m_rssiCount1 = 0U;
}
void CHD44780::clearM17Int()
{
#ifdef ADAFRUIT_DISPLAY
adafruitLCDColour(AC_PURPLE);
#endif
m_clockDisplayTimer.stop(); // Stop the clock display
if (m_rows == 2U && m_cols == 16U) {
::lcdPosition(m_fd, 5, 0);
::lcdPrintf(m_fd, "%.*s", m_cols - 5, LISTENING);
::lcdPosition(m_fd, 5, 1);
::lcdPrintf(m_fd, "%.*s", m_cols - 5, " ");
} else if (m_rows == 4U && m_cols == 16U) {
::lcdPosition(m_fd, 0, 1);
::lcdPrintf(m_fd, "%.*s", m_cols, LISTENING);
::lcdPosition(m_fd, 0, 2);
::lcdPrintf(m_fd, "%.*s", m_cols, " ");
::lcdPosition(m_fd, 0, 3);
::lcdPrintf(m_fd, "%.*s", m_cols, " ");
} else if (m_rows == 4U && m_cols == 20U) {
::lcdPosition(m_fd, 0, 1);
::lcdPrintf(m_fd, "%.*s", m_cols, LISTENING);
::lcdPosition(m_fd, 0, 2);
::lcdPrintf(m_fd, "%.*s", m_cols, " ");
::lcdPosition(m_fd, 0, 3);
::lcdPrintf(m_fd, "%.*s", m_cols, " ");
} else if (m_rows == 2 && m_cols == 40U) {
::lcdPosition(m_fd, 0, 1);
::lcdPrintf(m_fd, "%.*s", m_cols, LISTENING);
}
}
void CHD44780::writePOCSAGInt(uint32_t ric, const std::string& message)
{
::lcdPosition(m_fd, m_cols - 5, m_rows - 1);

View file

@ -1,5 +1,5 @@
/*
* Copyright (C) 2016,2017,2018,2020,2021 by Jonathan Naylor G4KLX & Tony Corbett G0WFV
* Copyright (C) 2016,2017,2018,2020,2021,2025 by Jonathan Naylor G4KLX & Tony Corbett G0WFV
*
* 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
@ -123,10 +123,6 @@ protected:
virtual void writeNXDNRSSIInt(unsigned char rssi);
virtual void clearNXDNInt();
virtual void writeM17Int(const char* source, const char* dest, const char* type);
virtual void writeM17RSSIInt(unsigned char rssi);
virtual void clearM17Int();
virtual void writePOCSAGInt(uint32_t ric, const std::string& message);
virtual void clearPOCSAGInt();

Binary file not shown.

Before

Width:  |  Height:  |  Size: 57 KiB

View file

@ -100,7 +100,6 @@ const unsigned int DMR_RSSI_COUNT = 4U; // 4 * 360ms = 1440ms
const unsigned int YSF_RSSI_COUNT = 13U; // 13 * 100ms = 1300ms
const unsigned int P25_RSSI_COUNT = 7U; // 7 * 180ms = 1260ms
const unsigned int NXDN_RSSI_COUNT = 28U; // 28 * 40ms = 1120ms
const unsigned int M17_RSSI_COUNT = 28U; // 28 * 40ms = 1120ms
CLCDproc::CLCDproc(std::string address, unsigned int port, unsigned short localPort, const std::string& callsign, unsigned int dmrid, bool displayClock, bool utc, bool duplex, bool dimOnIdle) :
CDisplay(),
@ -198,7 +197,6 @@ void CLCDproc::setIdleInt()
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, "screen_set M17 -priority hidden");
socketPrintf(m_socketfd, "widget_set Status Status %u %u Idle", m_cols - 3, m_rows);
socketPrintf(m_socketfd, "output 0"); // Clear all LEDs
}
@ -218,7 +216,6 @@ void CLCDproc::setErrorInt(const char* text)
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, "screen_set M17 -priority hidden");
socketPrintf(m_socketfd, "widget_set Status Status %u %u Error", m_cols - 4, m_rows);
socketPrintf(m_socketfd, "output 0"); // Clear all LEDs
}
@ -236,7 +233,6 @@ void CLCDproc::setLockoutInt()
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, "screen_set M17 -priority hidden");
socketPrintf(m_socketfd, "widget_set Status Status %u %u Lockout", m_cols - 6, m_rows);
socketPrintf(m_socketfd, "output 0"); // Clear all LEDs
}
@ -256,7 +252,6 @@ void CLCDproc::setQuitInt()
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, "screen_set M17 -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
}
@ -274,7 +269,6 @@ void CLCDproc::setFMInt()
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, "screen_set M17 -priority hidden");
socketPrintf(m_socketfd, "widget_set Status Status %u %u FM", m_cols - 6, m_rows);
socketPrintf(m_socketfd, "output 0"); // Clear all LEDs
}
@ -571,51 +565,6 @@ void CLCDproc::clearNXDNInt()
socketPrintf(m_socketfd, "output 16"); // Set LED5 color green
}
void CLCDproc::writeM17Int(const char* source, const char* dest, const char* type)
{
assert(source != nullptr);
assert(dest != nullptr);
assert(type != nullptr);
m_clockDisplayTimer.stop(); // Stop the clock display
socketPrintf(m_socketfd, "screen_set M17 -priority foreground");
socketPrintf(m_socketfd, "widget_set M17 Mode 1 1 M17");
if (m_rows == 2U) {
socketPrintf(m_socketfd, "widget_set M17 Line2 1 2 15 2 h 3 \"%.9s > %.9s\"", source, dest);
}
else {
socketPrintf(m_socketfd, "widget_set M17 Line2 1 2 15 2 h 3 \"%.9s >\"", source);
socketPrintf(m_socketfd, "widget_set M17 Line3 1 3 15 3 h 3 \"%.9ss\"", dest);
socketPrintf(m_socketfd, "output 255"); // Set LED5 color red
}
m_dmr = false;
m_rssiCount1 = 0U;
}
void CLCDproc::writeM17RSSIInt(unsigned char rssi)
{
if (m_rssiCount1 == 0U) {
socketPrintf(m_socketfd, "widget_set M17 Line4 1 4 %u 4 h 3 \"-%3udBm\"", m_cols - 1, rssi);
}
m_rssiCount1++;
if (m_rssiCount1 >= M17_RSSI_COUNT)
m_rssiCount1 = 0U;
}
void CLCDproc::clearM17Int()
{
m_clockDisplayTimer.stop(); // Stop the clock display
socketPrintf(m_socketfd, "widget_set M17 Line2 1 2 15 2 h 3 \"Listening\"");
socketPrintf(m_socketfd, "widget_set M17 Line3 1 3 15 3 h 3 \"\"");
socketPrintf(m_socketfd, "widget_set M17 Line4 1 4 15 4 h 3 \"\"");
socketPrintf(m_socketfd, "output 16"); // Set LED5 color green
}
void CLCDproc::writePOCSAGInt(uint32_t ric, const std::string& message)
{
}
@ -917,22 +866,5 @@ void CLCDproc::defineScreens()
socketPrintf(m_socketfd, "widget_set NXDN Line3 3 1 15 1 h 3 \" \"");
socketPrintf(m_socketfd, "widget_set NXDN Line4 4 2 15 2 h 3 \" \"");
*/
// The M17 Screen
socketPrintf(m_socketfd, "screen_add M17");
socketPrintf(m_socketfd, "screen_set M17 -name M17 -heartbeat on -priority hidden -backlight on");
socketPrintf(m_socketfd, "widget_add M17 Mode string");
socketPrintf(m_socketfd, "widget_add M17 Line2 scroller");
socketPrintf(m_socketfd, "widget_add M17 Line3 scroller");
socketPrintf(m_socketfd, "widget_add M17 Line4 scroller");
/* Do we need to pre-populate the values??
socketPrintf(m_socketfd, "widget_set M17 Line3 2 1 15 1 h 3 \"Listening\"");
socketPrintf(m_socketfd, "widget_set M17 Line3 3 1 15 1 h 3 \" \"");
socketPrintf(m_socketfd, "widget_set M17 Line4 4 2 15 2 h 3 \" \"");
*/
m_screensDefined = true;
}

View file

@ -67,10 +67,6 @@ protected:
virtual void writeNXDNRSSIInt(unsigned char rssi);
virtual void clearNXDNInt();
virtual void writeM17Int(const char* source, const char* dest, const char* type);
virtual void writeM17RSSIInt(unsigned char rssi);
virtual void clearM17Int();
virtual void writePOCSAGInt(uint32_t ric, const std::string& message);
virtual void clearPOCSAGInt();

View file

@ -1,84 +0,0 @@
/*
* Copyright (C) 2020,2021,2025 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 "M17CRC.h"
#include <cstdio>
#include <cassert>
const uint16_t CRC16_TABLE[] = {0x0000U, 0x5935U, 0xB26AU, 0xEB5FU, 0x3DE1U, 0x64D4U, 0x8F8BU, 0xD6BEU, 0x7BC2U, 0x22F7U, 0xC9A8U,
0x909DU, 0x4623U, 0x1F16U, 0xF449U, 0xAD7CU, 0xF784U, 0xAEB1U, 0x45EEU, 0x1CDBU, 0xCA65U, 0x9350U,
0x780FU, 0x213AU, 0x8C46U, 0xD573U, 0x3E2CU, 0x6719U, 0xB1A7U, 0xE892U, 0x03CDU, 0x5AF8U, 0xB63DU,
0xEF08U, 0x0457U, 0x5D62U, 0x8BDCU, 0xD2E9U, 0x39B6U, 0x6083U, 0xCDFFU, 0x94CAU, 0x7F95U, 0x26A0U,
0xF01EU, 0xA92BU, 0x4274U, 0x1B41U, 0x41B9U, 0x188CU, 0xF3D3U, 0xAAE6U, 0x7C58U, 0x256DU, 0xCE32U,
0x9707U, 0x3A7BU, 0x634EU, 0x8811U, 0xD124U, 0x079AU, 0x5EAFU, 0xB5F0U, 0xECC5U, 0x354FU, 0x6C7AU,
0x8725U, 0xDE10U, 0x08AEU, 0x519BU, 0xBAC4U, 0xE3F1U, 0x4E8DU, 0x17B8U, 0xFCE7U, 0xA5D2U, 0x736CU,
0x2A59U, 0xC106U, 0x9833U, 0xC2CBU, 0x9BFEU, 0x70A1U, 0x2994U, 0xFF2AU, 0xA61FU, 0x4D40U, 0x1475U,
0xB909U, 0xE03CU, 0x0B63U, 0x5256U, 0x84E8U, 0xDDDDU, 0x3682U, 0x6FB7U, 0x8372U, 0xDA47U, 0x3118U,
0x682DU, 0xBE93U, 0xE7A6U, 0x0CF9U, 0x55CCU, 0xF8B0U, 0xA185U, 0x4ADAU, 0x13EFU, 0xC551U, 0x9C64U,
0x773BU, 0x2E0EU, 0x74F6U, 0x2DC3U, 0xC69CU, 0x9FA9U, 0x4917U, 0x1022U, 0xFB7DU, 0xA248U, 0x0F34U,
0x5601U, 0xBD5EU, 0xE46BU, 0x32D5U, 0x6BE0U, 0x80BFU, 0xD98AU, 0x6A9EU, 0x33ABU, 0xD8F4U, 0x81C1U,
0x577FU, 0x0E4AU, 0xE515U, 0xBC20U, 0x115CU, 0x4869U, 0xA336U, 0xFA03U, 0x2CBDU, 0x7588U, 0x9ED7U,
0xC7E2U, 0x9D1AU, 0xC42FU, 0x2F70U, 0x7645U, 0xA0FBU, 0xF9CEU, 0x1291U, 0x4BA4U, 0xE6D8U, 0xBFEDU,
0x54B2U, 0x0D87U, 0xDB39U, 0x820CU, 0x6953U, 0x3066U, 0xDCA3U, 0x8596U, 0x6EC9U, 0x37FCU, 0xE142U,
0xB877U, 0x5328U, 0x0A1DU, 0xA761U, 0xFE54U, 0x150BU, 0x4C3EU, 0x9A80U, 0xC3B5U, 0x28EAU, 0x71DFU,
0x2B27U, 0x7212U, 0x994DU, 0xC078U, 0x16C6U, 0x4FF3U, 0xA4ACU, 0xFD99U, 0x50E5U, 0x09D0U, 0xE28FU,
0xBBBAU, 0x6D04U, 0x3431U, 0xDF6EU, 0x865BU, 0x5FD1U, 0x06E4U, 0xEDBBU, 0xB48EU, 0x6230U, 0x3B05U,
0xD05AU, 0x896FU, 0x2413U, 0x7D26U, 0x9679U, 0xCF4CU, 0x19F2U, 0x40C7U, 0xAB98U, 0xF2ADU, 0xA855U,
0xF160U, 0x1A3FU, 0x430AU, 0x95B4U, 0xCC81U, 0x27DEU, 0x7EEBU, 0xD397U, 0x8AA2U, 0x61FDU, 0x38C8U,
0xEE76U, 0xB743U, 0x5C1CU, 0x0529U, 0xE9ECU, 0xB0D9U, 0x5B86U, 0x02B3U, 0xD40DU, 0x8D38U, 0x6667U,
0x3F52U, 0x922EU, 0xCB1BU, 0x2044U, 0x7971U, 0xAFCFU, 0xF6FAU, 0x1DA5U, 0x4490U, 0x1E68U, 0x475DU,
0xAC02U, 0xF537U, 0x2389U, 0x7ABCU, 0x91E3U, 0xC8D6U, 0x65AAU, 0x3C9FU, 0xD7C0U, 0x8EF5U, 0x584BU,
0x017EU, 0xEA21U, 0xB314U};
bool CM17CRC::checkCRC16(const unsigned char* in, unsigned int nBytes)
{
assert(in != nullptr);
assert(nBytes > 2U);
uint16_t crc = createCRC16(in, nBytes - 2U);
uint8_t temp[2U];
temp[0U] = (crc >> 8) & 0xFFU;
temp[1U] = (crc >> 0) & 0xFFU;
return temp[0U] == in[nBytes - 2U] && temp[1U] == in[nBytes - 1U];
}
void CM17CRC::encodeCRC16(unsigned char* in, unsigned int nBytes)
{
assert(in != nullptr);
assert(nBytes > 2U);
uint16_t crc = createCRC16(in, nBytes - 2U);
in[nBytes - 2U] = (crc >> 8) & 0xFFU;
in[nBytes - 1U] = (crc >> 0) & 0xFFU;
}
uint16_t CM17CRC::createCRC16(const unsigned char* in, unsigned int nBytes)
{
assert(in != nullptr);
uint16_t crc = 0xFFFFU;
for (unsigned int i = 0U; i < nBytes; i++)
crc = (crc << 8) ^ CRC16_TABLE[((crc >> 8) ^ uint16_t(in[i])) & 0x00FFU];
return crc;
}

View file

@ -1,34 +0,0 @@
/*
* Copyright (C) 2020,2021 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(M17CRC_H)
#define M17CRC_H
#include <cstdint>
class CM17CRC
{
public:
static bool checkCRC16(const unsigned char* in, unsigned int nBytes);
static void encodeCRC16(unsigned char* in, unsigned int nBytes);
private:
static uint16_t createCRC16(const unsigned char* in, unsigned int nBytes);
};
#endif

File diff suppressed because it is too large Load diff

View file

@ -1,115 +0,0 @@
/*
* Copyright (C) 2020,2021 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(M17Control_H)
#define M17Control_H
#include "RSSIInterpolator.h"
#include "M17Network.h"
#include "M17Defines.h"
#include "RingBuffer.h"
#include "StopWatch.h"
#include "Display.h"
#include "Defines.h"
#include "M17LSF.h"
#include "Timer.h"
#include "Modem.h"
#include <string>
class CM17Control {
public:
CM17Control(const std::string& callsign, unsigned int can, bool selfOnly, bool allowEncryption, CM17Network* network, CDisplay* display, unsigned int timeout, bool duplex, CRSSIInterpolator* rssiMapper);
~CM17Control();
bool writeModem(unsigned char* data, unsigned int len);
unsigned int readModem(unsigned char* data);
void clock(unsigned int ms);
bool isBusy() const;
void enable(bool enabled);
private:
std::string m_callsign;
unsigned int m_can;
bool m_selfOnly;
bool m_allowEncryption;
CM17Network* m_network;
CDisplay* m_display;
bool m_duplex;
CRingBuffer<unsigned char> m_queue;
std::string m_source;
std::string m_dest;
RPT_RF_STATE m_rfState;
RPT_NET_STATE m_netState;
CTimer m_rfTimeoutTimer;
CTimer m_netTimeoutTimer;
CTimer m_networkWatchdog;
CStopWatch m_elapsed;
unsigned int m_rfFrames;
unsigned int m_netFrames;
unsigned int m_rfErrs;
unsigned int m_rfBits;
unsigned int m_rfLSFCount;
CM17LSF m_rfCurrentRFLSF;
CM17LSF m_rfCurrentNetLSF;
CM17LSF m_rfCollectingLSF;
CM17LSF m_rfCollectedLSF;
unsigned int m_rfLSFn;
CM17LSF m_netLSF;
unsigned int m_netLSFn;
unsigned char m_rfTextBits;
unsigned char m_netTextBits;
char* m_rfText;
char* m_netText;
CRSSIInterpolator* m_rssiMapper;
unsigned char m_rssi;
unsigned char m_maxRSSI;
unsigned char m_minRSSI;
unsigned int m_aveRSSI;
unsigned int m_rssiCount;
bool m_enabled;
FILE* m_fp;
bool processRFHeader(bool lateEntry);
void writeQueueRF(const unsigned char* data);
void writeQueueNet(const unsigned char* data);
void writeNetwork();
void interleaver(const unsigned char* in, unsigned char* out) const;
void decorrelator(const unsigned char* in, unsigned char* out) const;
bool checkCallsign(const std::string& source) const;
void createRFLSF(bool addCallsign);
void writeEndRF();
void writeEndNet();
bool openFile();
bool writeFile(const unsigned char* data);
void closeFile();
};
#endif

View file

@ -1,283 +0,0 @@
/*
* Copyright (C) 2020,2021,2025 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 "M17Convolution.h"
#include <cstdio>
#include <cassert>
#include <cstring>
#include <cstdlib>
const unsigned int PUNCTURE_LIST_LINK_SETUP_COUNT = 60U;
const unsigned int PUNCTURE_LIST_LINK_SETUP[] = {
2U, 6U, 10U, 14U, 18U, 22U, 26U, 30U, 34U, 38U, 42U, 46U, 50U, 54U, 58U, 63U, 67U, 71U, 75U, 79U, 83U,
87U, 91U, 95U, 99U, 103U, 107U, 111U, 115U, 119U, 124U, 128U, 132U, 136U, 140U, 144U, 148U, 152U, 156U, 160U, 164U, 168U,
172U, 176U, 180U, 185U, 189U, 193U, 197U, 201U, 205U, 209U, 213U, 217U, 221U, 225U, 229U, 233U, 237U, 241U, 246U, 250U, 254U,
258U, 262U, 266U, 270U, 274U, 278U, 282U, 286U, 290U, 294U, 298U, 302U, 307U, 311U, 315U, 319U, 323U, 327U, 331U, 335U, 339U,
343U, 347U, 351U, 355U, 359U, 363U, 368U, 372U, 376U, 380U, 384U, 388U, 392U, 396U, 400U, 404U, 408U, 412U, 416U, 420U, 424U,
429U, 433U, 437U, 441U, 445U, 449U, 453U, 457U, 461U, 465U, 469U, 473U, 477U, 481U, 485U};
const unsigned int PUNCTURE_LIST_DATA_COUNT = 12U;
const unsigned int PUNCTURE_LIST_DATA[] = {
11U, 23U, 35U, 47U, 59U, 71U, 83U, 95U, 107U, 119U, 131U, 143U, 155U, 167U, 179U, 191U, 203U, 215U, 227U, 239U, 251U,
263U, 275U, 287U};
const unsigned char BIT_MASK_TABLE[] = {0x80U, 0x40U, 0x20U, 0x10U, 0x08U, 0x04U, 0x02U, 0x01U};
#define WRITE_BIT1(p,i,b) p[(i)>>3] = (b) ? (p[(i)>>3] | BIT_MASK_TABLE[(i)&7]) : (p[(i)>>3] & ~BIT_MASK_TABLE[(i)&7])
#define READ_BIT1(p,i) (p[(i)>>3] & BIT_MASK_TABLE[(i)&7])
const uint8_t BRANCH_TABLE1[] = {0U, 0U, 0U, 0U, 2U, 2U, 2U, 2U};
const uint8_t BRANCH_TABLE2[] = {0U, 2U, 2U, 0U, 0U, 2U, 2U, 0U};
const unsigned int NUM_OF_STATES_D2 = 8U;
const unsigned int NUM_OF_STATES = 16U;
const uint32_t M = 4U;
const unsigned int K = 5U;
CM17Convolution::CM17Convolution() :
m_metrics1(nullptr),
m_metrics2(nullptr),
m_oldMetrics(nullptr),
m_newMetrics(nullptr),
m_decisions(nullptr),
m_dp(nullptr)
{
m_metrics1 = new uint16_t[20U];
m_metrics2 = new uint16_t[20U];
m_decisions = new uint64_t[300U];
}
CM17Convolution::~CM17Convolution()
{
delete[] m_metrics1;
delete[] m_metrics2;
delete[] m_decisions;
}
void CM17Convolution::encodeLinkSetup(const unsigned char* in, unsigned char* out) const
{
assert(in != nullptr);
assert(out != nullptr);
unsigned char temp1[31U];
::memset(temp1, 0x00U, 31U);
::memcpy(temp1, in, 30U);
unsigned char temp2[61U];
encode(temp1, temp2, 244U);
unsigned int n = 0U;
unsigned int index = 0U;
for (unsigned int i = 0U; i < 488U; i++) {
if (i != PUNCTURE_LIST_LINK_SETUP[index]) {
bool b = READ_BIT1(temp2, i);
WRITE_BIT1(out, n, b);
n++;
} else {
index++;
}
}
}
void CM17Convolution::encodeData(const unsigned char* in, unsigned char* out) const
{
assert(in != nullptr);
assert(out != nullptr);
unsigned char temp1[19U];
::memset(temp1, 0x00U, 19U);
::memcpy(temp1, in, 18U);
unsigned char temp2[37U];
encode(temp1, temp2, 148U);
unsigned int n = 0U;
unsigned int index = 0U;
for (unsigned int i = 0U; i < 296U; i++) {
if (i != PUNCTURE_LIST_DATA[index]) {
bool b = READ_BIT1(temp2, i);
WRITE_BIT1(out, n, b);
n++;
} else {
index++;
}
}
}
unsigned int CM17Convolution::decodeLinkSetup(const unsigned char* in, unsigned char* out)
{
assert(in != nullptr);
assert(out != nullptr);
uint8_t temp[500U];
::memset(temp, 0x00U, 500U);
unsigned int n = 0U;
unsigned int index = 0U;
for (unsigned int i = 0U; i < 368U; i++) {
if (n == PUNCTURE_LIST_LINK_SETUP[index]) {
temp[n++] = 1U;
index++;
}
bool b = READ_BIT1(in, i);
temp[n++] = b ? 2U : 0U;
}
start();
n = 0U;
for (unsigned int i = 0U; i < 244U; i++) {
uint8_t s0 = temp[n++];
uint8_t s1 = temp[n++];
decode(s0, s1);
}
return chainback(out, 240U) - PUNCTURE_LIST_LINK_SETUP_COUNT;
}
unsigned int CM17Convolution::decodeData(const unsigned char* in, unsigned char* out)
{
assert(in != nullptr);
assert(out != nullptr);
uint8_t temp[300U];
::memset(temp, 0x00U, 300U);
unsigned int n = 0U;
unsigned int index = 0U;
for (unsigned int i = 0U; i < 272U; i++) {
if (n == PUNCTURE_LIST_DATA[index]) {
temp[n++] = 1U;
index++;
}
bool b = READ_BIT1(in, i);
temp[n++] = b ? 2U : 0U;
}
start();
n = 0U;
for (unsigned int i = 0U; i < 148U; i++) {
uint8_t s0 = temp[n++];
uint8_t s1 = temp[n++];
decode(s0, s1);
}
return chainback(out, 144U) - PUNCTURE_LIST_DATA_COUNT;
}
void CM17Convolution::start()
{
::memset(m_metrics1, 0x00U, NUM_OF_STATES * sizeof(uint16_t));
::memset(m_metrics2, 0x00U, NUM_OF_STATES * sizeof(uint16_t));
m_oldMetrics = m_metrics1;
m_newMetrics = m_metrics2;
m_dp = m_decisions;
}
void CM17Convolution::decode(uint8_t s0, uint8_t s1)
{
*m_dp = 0U;
for (uint8_t i = 0U; i < NUM_OF_STATES_D2; i++) {
uint8_t j = i * 2U;
uint16_t metric = std::abs(BRANCH_TABLE1[i] - s0) + std::abs(BRANCH_TABLE2[i] - s1);
uint16_t m0 = m_oldMetrics[i] + metric;
uint16_t m1 = m_oldMetrics[i + NUM_OF_STATES_D2] + (M - metric);
uint8_t decision0 = (m0 >= m1) ? 1U : 0U;
m_newMetrics[j + 0U] = decision0 != 0U ? m1 : m0;
m0 = m_oldMetrics[i] + (M - metric);
m1 = m_oldMetrics[i + NUM_OF_STATES_D2] + metric;
uint8_t decision1 = (m0 >= m1) ? 1U : 0U;
m_newMetrics[j + 1U] = decision1 != 0U ? m1 : m0;
*m_dp |= (uint64_t(decision1) << (j + 1U)) | (uint64_t(decision0) << (j + 0U));
}
++m_dp;
assert((m_dp - m_decisions) <= 300);
uint16_t* tmp = m_oldMetrics;
m_oldMetrics = m_newMetrics;
m_newMetrics = tmp;
}
unsigned int CM17Convolution::chainback(unsigned char* out, unsigned int nBits)
{
assert(out != nullptr);
uint32_t state = 0U;
while (nBits-- > 0) {
--m_dp;
uint32_t i = state >> (9 - K);
uint8_t bit = uint8_t(*m_dp >> i) & 1;
state = (bit << 7) | (state >> 1);
WRITE_BIT1(out, nBits, bit != 0U);
}
unsigned int minCost = m_oldMetrics[0];
for (unsigned int i = 0U; i < NUM_OF_STATES; i++) {
if (m_oldMetrics[i] < minCost)
minCost = m_oldMetrics[i];
}
return minCost / (M >> 1);
}
void CM17Convolution::encode(const unsigned char* in, unsigned char* out, unsigned int nBits) const
{
assert(in != nullptr);
assert(out != nullptr);
assert(nBits > 0U);
uint8_t d1 = 0U, d2 = 0U, d3 = 0U, d4 = 0U;
uint32_t k = 0U;
for (unsigned int i = 0U; i < nBits; i++) {
uint8_t d = READ_BIT1(in, i) ? 1U : 0U;
uint8_t g1 = (d + d3 + d4) & 1;
uint8_t g2 = (d + d1 + d2 + d4) & 1;
d4 = d3;
d3 = d2;
d2 = d1;
d1 = d;
WRITE_BIT1(out, k, g1 != 0U);
k++;
WRITE_BIT1(out, k, g2 != 0U);
k++;
}
}

View file

@ -1,51 +0,0 @@
/*
* Copyright (C) 2020,2021 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(M17Convolution_H)
#define M17Convolution_H
#include <cstdint>
class CM17Convolution {
public:
CM17Convolution();
~CM17Convolution();
unsigned int decodeLinkSetup(const unsigned char* in, unsigned char* out);
unsigned int decodeData(const unsigned char* in, unsigned char* out);
void encodeLinkSetup(const unsigned char* in, unsigned char* out) const;
void encodeData(const unsigned char* in, unsigned char* out) const;
private:
uint16_t* m_metrics1;
uint16_t* m_metrics2;
uint16_t* m_oldMetrics;
uint16_t* m_newMetrics;
uint64_t* m_decisions;
uint64_t* m_dp;
void start();
void decode(uint8_t s0, uint8_t s1);
unsigned int chainback(unsigned char* out, unsigned int nBits);
void encode(const unsigned char* in, unsigned char* out, unsigned int nBits) const;
};
#endif

View file

@ -1,80 +0,0 @@
/*
* Copyright (C) 2020,2021,2025 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(M17DEFINES_H)
#define M17DEFINES_H
const unsigned int M17_RADIO_SYMBOL_LENGTH = 5U; // At 24 kHz sample rate
const unsigned int M17_FRAME_LENGTH_BITS = 384U;
const unsigned int M17_FRAME_LENGTH_BYTES = M17_FRAME_LENGTH_BITS / 8U;
const unsigned char M17_LINK_SETUP_SYNC_BYTES[] = {0x55U, 0xF7U};
const unsigned char M17_STREAM_SYNC_BYTES[] = {0xFFU, 0x5DU};
const unsigned char M17_EOT_SYNC_BYTES[] = {0x55U, 0x5DU};
const unsigned int M17_SYNC_LENGTH_BITS = 16U;
const unsigned int M17_SYNC_LENGTH_BYTES = M17_SYNC_LENGTH_BITS / 8U;
const unsigned int M17_LSF_LENGTH_BITS = 240U;
const unsigned int M17_LSF_LENGTH_BYTES = M17_LSF_LENGTH_BITS / 8U;
const unsigned int M17_LSF_FRAGMENT_LENGTH_BITS = M17_LSF_LENGTH_BITS / 6U;
const unsigned int M17_LSF_FRAGMENT_LENGTH_BYTES = M17_LSF_FRAGMENT_LENGTH_BITS / 8U;
const unsigned int M17_LICH_FRAGMENT_LENGTH_BITS = M17_LSF_FRAGMENT_LENGTH_BITS + 8U;
const unsigned int M17_LICH_FRAGMENT_LENGTH_BYTES = M17_LICH_FRAGMENT_LENGTH_BITS / 8U;
const unsigned int M17_LSF_FRAGMENT_FEC_LENGTH_BITS = M17_LSF_FRAGMENT_LENGTH_BITS * 2U;
const unsigned int M17_LSF_FRAGMENT_FEC_LENGTH_BYTES = M17_LSF_FRAGMENT_FEC_LENGTH_BITS / 8U;
const unsigned int M17_LICH_FRAGMENT_FEC_LENGTH_BITS = M17_LICH_FRAGMENT_LENGTH_BITS * 2U;
const unsigned int M17_LICH_FRAGMENT_FEC_LENGTH_BYTES = M17_LICH_FRAGMENT_FEC_LENGTH_BITS / 8U;
const unsigned int M17_PAYLOAD_LENGTH_BITS = 128U;
const unsigned int M17_PAYLOAD_LENGTH_BYTES = M17_PAYLOAD_LENGTH_BITS / 8U;
const unsigned char M17_NULL_NONCE[] = {0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U};
const unsigned int M17_META_LENGTH_BITS = 112U;
const unsigned int M17_META_LENGTH_BYTES = M17_META_LENGTH_BITS / 8U;
const unsigned int M17_FN_LENGTH_BITS = 16U;
const unsigned int M17_FN_LENGTH_BYTES = M17_FN_LENGTH_BITS / 8U;
const unsigned int M17_CRC_LENGTH_BITS = 16U;
const unsigned int M17_CRC_LENGTH_BYTES = M17_CRC_LENGTH_BITS / 8U;
const unsigned char M17_3200_SILENCE[] = {0x01U, 0x00U, 0x09U, 0x43U, 0x9CU, 0xE4U, 0x21U, 0x08U};
const unsigned char M17_1600_SILENCE[] = {0x0CU, 0x41U, 0x09U, 0x03U, 0x0CU, 0x41U, 0x09U, 0x03U};
const unsigned char M17_PACKET_TYPE = 0U;
const unsigned char M17_STREAM_TYPE = 1U;
const unsigned char M17_DATA_TYPE_DATA = 0x01U;
const unsigned char M17_DATA_TYPE_VOICE = 0x02U;
const unsigned char M17_DATA_TYPE_VOICE_DATA = 0x03U;
const unsigned char M17_ENCRYPTION_TYPE_NONE = 0x00U;
const unsigned char M17_ENCRYPTION_TYPE_AES = 0x01U;
const unsigned char M17_ENCRYPTION_TYPE_SCRAMBLE = 0x02U;
const unsigned char M17_ENCRYPTION_SUB_TYPE_TEXT = 0x00U;
const unsigned char M17_ENCRYPTION_SUB_TYPE_GPS = 0x01U;
const unsigned char M17_ENCRYPTION_SUB_TYPE_CALLSIGNS = 0x02U;
#endif

View file

@ -1,220 +0,0 @@
/*
* Copyright (C) 2020,2021,2023,2025 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 "M17LSF.h"
#include "M17Utils.h"
#include "M17Defines.h"
#include "M17CRC.h"
#include <cassert>
#include <cstring>
CM17LSF::CM17LSF(const CM17LSF& lsf) :
m_lsf(nullptr),
m_valid(lsf.m_valid)
{
m_lsf = new unsigned char[M17_LSF_LENGTH_BYTES];
::memcpy(m_lsf, lsf.m_lsf, M17_LSF_LENGTH_BYTES);
}
CM17LSF::CM17LSF() :
m_lsf(nullptr),
m_valid(false)
{
m_lsf = new unsigned char[M17_LSF_LENGTH_BYTES];
::memset(m_lsf, 0x00U, M17_LSF_LENGTH_BYTES);
}
CM17LSF::~CM17LSF()
{
delete[] m_lsf;
}
void CM17LSF::getNetwork(unsigned char* data) const
{
assert(data != nullptr);
::memcpy(data, m_lsf, M17_LSF_LENGTH_BYTES);
}
void CM17LSF::setNetwork(const unsigned char* data)
{
assert(data != nullptr);
::memcpy(m_lsf, data, M17_LSF_LENGTH_BYTES);
m_valid = true;
}
std::string CM17LSF::getSource() const
{
std::string callsign;
CM17Utils::decodeCallsign(m_lsf + 6U, callsign);
return callsign;
}
void CM17LSF::setSource(const std::string& callsign)
{
CM17Utils::encodeCallsign(callsign, m_lsf + 6U);
}
std::string CM17LSF::getDest() const
{
std::string callsign;
CM17Utils::decodeCallsign(m_lsf + 0U, callsign);
return callsign;
}
void CM17LSF::setDest(const std::string& callsign)
{
CM17Utils::encodeCallsign(callsign, m_lsf + 0U);
}
unsigned char CM17LSF::getPacketStream() const
{
return m_lsf[13U] & 0x01U;
}
void CM17LSF::setPacketStream(unsigned char ps)
{
m_lsf[13U] &= 0xF7U;
m_lsf[13U] |= ps & 0x01U;
}
unsigned char CM17LSF::getDataType() const
{
return (m_lsf[13U] >> 1) & 0x03U;
}
void CM17LSF::setDataType(unsigned char type)
{
m_lsf[13U] &= 0xF9U;
m_lsf[13U] |= (type << 1) & 0x06U;
}
unsigned char CM17LSF::getEncryptionType() const
{
return (m_lsf[13U] >> 3) & 0x03U;
}
void CM17LSF::setEncryptionType(unsigned char type)
{
m_lsf[13U] &= 0xE7U;
m_lsf[13U] |= (type << 3) & 0x18U;
}
unsigned char CM17LSF::getEncryptionSubType() const
{
return (m_lsf[13U] >> 5) & 0x03U;
}
void CM17LSF::setEncryptionSubType(unsigned char type)
{
m_lsf[13U] &= 0x9FU;
m_lsf[13U] |= (type << 5) & 0x60U;
}
unsigned char CM17LSF::getCAN() const
{
return ((m_lsf[12U] << 1) & 0x0EU) | ((m_lsf[13U] >> 7) & 0x01U);
}
void CM17LSF::setCAN(unsigned char can)
{
m_lsf[13U] &= 0x7FU;
m_lsf[13U] |= (can << 7) & 0x80U;
m_lsf[12U] &= 0xF8U;
m_lsf[12U] |= (can >> 1) & 0x07U;
}
void CM17LSF::getMeta(unsigned char* data) const
{
assert(data != nullptr);
::memcpy(data, m_lsf + 14U, M17_META_LENGTH_BYTES);
}
void CM17LSF::setMeta(const unsigned char* data)
{
assert(data != nullptr);
::memcpy(m_lsf + 14U, data, M17_META_LENGTH_BYTES);
}
void CM17LSF::reset()
{
::memset(m_lsf, 0x00U, M17_LSF_LENGTH_BYTES);
m_valid = false;
}
bool CM17LSF::isValid() const
{
return m_valid;
}
void CM17LSF::getLinkSetup(unsigned char* data) const
{
assert(data != nullptr);
::memcpy(data, m_lsf, M17_LSF_LENGTH_BYTES);
CM17CRC::encodeCRC16(data, M17_LSF_LENGTH_BYTES);
}
void CM17LSF::setLinkSetup(const unsigned char* data)
{
assert(data != nullptr);
::memcpy(m_lsf, data, M17_LSF_LENGTH_BYTES);
m_valid = CM17CRC::checkCRC16(m_lsf, M17_LSF_LENGTH_BYTES);
}
void CM17LSF::getFragment(unsigned char* data, unsigned int n) const
{
assert(data != nullptr);
CM17CRC::encodeCRC16(m_lsf, M17_LSF_LENGTH_BYTES);
::memcpy(data, m_lsf + (n * M17_LSF_FRAGMENT_LENGTH_BYTES), M17_LSF_FRAGMENT_LENGTH_BYTES);
}
void CM17LSF::setFragment(const unsigned char* data, unsigned int n)
{
assert(data != nullptr);
::memcpy(m_lsf + (n * M17_LSF_FRAGMENT_LENGTH_BYTES), data, M17_LSF_FRAGMENT_LENGTH_BYTES);
m_valid = CM17CRC::checkCRC16(m_lsf, M17_LSF_LENGTH_BYTES);
}
CM17LSF& CM17LSF::operator=(const CM17LSF& lsf)
{
if (&lsf != this) {
::memcpy(m_lsf, lsf.m_lsf, M17_LSF_LENGTH_BYTES);
m_valid = lsf.m_valid;
}
return *this;
}

View file

@ -1,73 +0,0 @@
/*
* Copyright (C) 2020,2021 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(M17LSF_H)
#define M17LSF_H
#include <string>
class CM17LSF {
public:
CM17LSF(const CM17LSF& lsf);
CM17LSF();
~CM17LSF();
void getNetwork(unsigned char* data) const;
void setNetwork(const unsigned char* data);
std::string getSource() const;
void setSource(const std::string& callsign);
std::string getDest() const;
void setDest(const std::string& callsign);
unsigned char getPacketStream() const;
void setPacketStream(unsigned char ps);
unsigned char getDataType() const;
void setDataType(unsigned char type);
unsigned char getEncryptionType() const;
void setEncryptionType(unsigned char type);
unsigned char getEncryptionSubType() const;
void setEncryptionSubType(unsigned char type);
unsigned char getCAN() const;
void setCAN(unsigned char can);
void getMeta(unsigned char* data) const;
void setMeta(const unsigned char* data);
void reset();
bool isValid() const;
void getLinkSetup(unsigned char* data) const;
void setLinkSetup(const unsigned char* data);
void getFragment(unsigned char* data, unsigned int n) const;
void setFragment(const unsigned char* data, unsigned int n);
CM17LSF& operator=(const CM17LSF& lsf);
private:
unsigned char* m_lsf;
bool m_valid;
};
#endif

View file

@ -1,217 +0,0 @@
/*
* Copyright (C) 2020,2021,2023,2025 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 "M17Network.h"
#include "M17Defines.h"
#include "M17Utils.h"
#include "Defines.h"
#include "Utils.h"
#include "Log.h"
#include <cstdio>
#include <cassert>
#include <cstring>
const unsigned int BUFFER_LENGTH = 200U;
CM17Network::CM17Network(const std::string& localAddress, unsigned short localPort, const std::string& gatewayAddress, unsigned short gatewayPort, bool debug) :
m_socket(localAddress, localPort),
m_addr(),
m_addrLen(0U),
m_debug(debug),
m_enabled(false),
m_outId(0U),
m_inId(0U),
m_buffer(1000U, "M17 Network"),
m_random(),
m_timer(1000U, 5U)
{
if (CUDPSocket::lookup(gatewayAddress, gatewayPort, m_addr, m_addrLen) != 0) {
m_addrLen = 0U;
return;
}
std::random_device rd;
std::mt19937 mt(rd());
m_random = mt;
}
CM17Network::~CM17Network()
{
}
bool CM17Network::open()
{
if (m_addrLen == 0U) {
LogError("M17, unable to resolve the gateway address");
return false;
}
LogMessage("Opening M17 network connection");
bool ret = m_socket.open(m_addr);
if (ret) {
m_timer.start();
return true;
} else {
return false;
}
}
bool CM17Network::write(const unsigned char* data)
{
if (m_addrLen == 0U)
return false;
assert(data != nullptr);
unsigned char buffer[100U];
buffer[0U] = 'M';
buffer[1U] = '1';
buffer[2U] = '7';
buffer[3U] = ' ';
// Create a random id for this transmission if needed
if (m_outId == 0U) {
std::uniform_int_distribution<uint16_t> dist(0x0001, 0xFFFE);
m_outId = dist(m_random);
}
buffer[4U] = m_outId / 256U; // Unique session id
buffer[5U] = m_outId % 256U;
::memcpy(buffer + 6U, data, 46U);
// Dummy CRC
buffer[52U] = 0x00U;
buffer[53U] = 0x00U;
if (m_debug)
CUtils::dump(1U, "M17 Network Transmitted", buffer, 54U);
return m_socket.write(buffer, 54U, m_addr, m_addrLen);
}
void CM17Network::clock(unsigned int ms)
{
m_timer.clock(ms);
if (m_timer.isRunning() && m_timer.hasExpired()) {
sendPing();
m_timer.start();
}
unsigned char buffer[BUFFER_LENGTH];
sockaddr_storage address;
unsigned int addrLen;
int length = m_socket.read(buffer, BUFFER_LENGTH, address, addrLen);
if (length <= 0)
return;
if (!CUDPSocket::match(m_addr, address)) {
LogMessage("M17, packet received from an invalid source");
return;
}
if (m_debug)
CUtils::dump(1U, "M17 Network Received", buffer, length);
if (!m_enabled)
return;
if (::memcmp(buffer + 0U, "PING", 4U) == 0)
return;
if (::memcmp(buffer + 0U, "M17 ", 4U) != 0) {
CUtils::dump(2U, "M17, received unknown packet", buffer, length);
return;
}
uint16_t id = (buffer[4U] << 8) + (buffer[5U] << 0);
if (m_inId == 0U) {
m_inId = id;
} else {
if (id != m_inId)
return;
}
unsigned char c = length - 6U;
m_buffer.addData(&c, 1U);
m_buffer.addData(buffer + 6U, length - 6U);
}
bool CM17Network::read(unsigned char* data)
{
assert(data != nullptr);
if (m_buffer.isEmpty())
return false;
unsigned char c = 0U;
m_buffer.getData(&c, 1U);
m_buffer.getData(data, c);
return true;
}
void CM17Network::close()
{
m_socket.close();
LogMessage("Closing M17 network connection");
}
void CM17Network::reset()
{
m_outId = 0U;
m_inId = 0U;
}
void CM17Network::enable(bool enabled)
{
if (enabled && !m_enabled)
reset();
else if (!enabled && m_enabled)
m_buffer.clear();
m_enabled = enabled;
}
bool CM17Network::isConnected() const
{
return (m_addrLen != 0);
}
void CM17Network::sendPing()
{
unsigned char buffer[5U];
buffer[0U] = 'P';
buffer[1U] = 'I';
buffer[2U] = 'N';
buffer[3U] = 'G';
if (m_debug)
CUtils::dump(1U, "M17 Network Transmitted", buffer, 4U);
m_socket.write(buffer, 4U, m_addr, m_addrLen);
}

View file

@ -1,66 +0,0 @@
/*
* Copyright (C) 2020,2021 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 M17Network_H
#define M17Network_H
#include "M17Defines.h"
#include "RingBuffer.h"
#include "UDPSocket.h"
#include "Timer.h"
#include <random>
#include <cstdint>
class CM17Network {
public:
CM17Network(const std::string& localAddress, unsigned short localPort, const std::string& gatewayAddress, unsigned short gatewayPort, bool debug);
~CM17Network();
bool open();
void enable(bool enabled);
bool write(const unsigned char* data);
bool read(unsigned char* data);
void reset();
void close();
void clock(unsigned int ms);
bool isConnected() const;
private:
CUDPSocket m_socket;
sockaddr_storage m_addr;
unsigned int m_addrLen;
bool m_debug;
bool m_enabled;
uint16_t m_outId;
uint16_t m_inId;
CRingBuffer<unsigned char> m_buffer;
std::mt19937 m_random;
CTimer m_timer;
void sendPing();
};
#endif

View file

@ -1,236 +0,0 @@
/*
* Copyright (C) 2020,2021,2024,2025 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 "M17Utils.h"
#include "M17Defines.h"
#include <cstdint>
#include <cassert>
const std::string M17_CHARS = " ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-/.";
const unsigned char BIT_MASK_TABLE[] = { 0x80U, 0x40U, 0x20U, 0x10U, 0x08U, 0x04U, 0x02U, 0x01U };
#define WRITE_BIT1(p,i,b) p[(i)>>3] = (b) ? (p[(i)>>3] | BIT_MASK_TABLE[(i)&7]) : (p[(i)>>3] & ~BIT_MASK_TABLE[(i)&7])
#define READ_BIT1(p,i) (p[(i)>>3] & BIT_MASK_TABLE[(i)&7])
void CM17Utils::encodeCallsign(const std::string& callsign, unsigned char* encoded)
{
assert(encoded != nullptr);
if (callsign == "ALL" || callsign == "ALL ") {
encoded[0U] = 0xFFU;
encoded[1U] = 0xFFU;
encoded[2U] = 0xFFU;
encoded[3U] = 0xFFU;
encoded[4U] = 0xFFU;
encoded[5U] = 0xFFU;
return;
}
unsigned int len = (unsigned int)callsign.size();
if (len > 9U)
len = 9U;
uint64_t enc = 0ULL;
for (int i = len - 1; i >= 0; i--) {
if ((i == 0) && (callsign[i] == '#')) {
enc += 262144000000000ULL;
} else {
size_t pos = M17_CHARS.find(callsign[i]);
if (pos == std::string::npos)
pos = 0ULL;
enc *= 40ULL;
enc += pos;
}
}
encoded[0U] = (enc >> 40) & 0xFFU;
encoded[1U] = (enc >> 32) & 0xFFU;
encoded[2U] = (enc >> 24) & 0xFFU;
encoded[3U] = (enc >> 16) & 0xFFU;
encoded[4U] = (enc >> 8) & 0xFFU;
encoded[5U] = (enc >> 0) & 0xFFU;
}
void CM17Utils::decodeCallsign(const unsigned char* encoded, std::string& callsign)
{
assert(encoded != nullptr);
callsign.clear();
uint64_t enc = (uint64_t(encoded[0U]) << 40) +
(uint64_t(encoded[1U]) << 32) +
(uint64_t(encoded[2U]) << 24) +
(uint64_t(encoded[3U]) << 16) +
(uint64_t(encoded[4U]) << 8) +
(uint64_t(encoded[5U]) << 0);
if (enc == 281474976710655ULL) {
callsign = "ALL";
return;
}
if (enc >= 268697600000000ULL) {
callsign = "Invalid";
return;
}
if (enc >= 262144000000000ULL) {
callsign = "#";
enc -= 262144000000000ULL;
}
while (enc > 0ULL) {
callsign += " ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-/."[enc % 40ULL];
enc /= 40ULL;
}
}
void CM17Utils::splitFragmentLICH(const unsigned char* data, unsigned int& frag1, unsigned int& frag2, unsigned int& frag3, unsigned int& frag4)
{
assert(data != nullptr);
frag1 = frag2 = frag3 = frag4 = 0x00U;
unsigned int offset = 0U;
unsigned int MASK = 0x800U;
for (unsigned int i = 0U; i < (M17_LICH_FRAGMENT_LENGTH_BITS / 4U); i++, offset++, MASK >>= 1) {
bool b = READ_BIT1(data, offset) != 0x00U;
if (b)
frag1 |= MASK;
}
MASK = 0x800U;
for (unsigned int i = 0U; i < (M17_LICH_FRAGMENT_LENGTH_BITS / 4U); i++, offset++, MASK >>= 1) {
bool b = READ_BIT1(data, offset) != 0x00U;
if (b)
frag2 |= MASK;
}
MASK = 0x800U;
for (unsigned int i = 0U; i < (M17_LICH_FRAGMENT_LENGTH_BITS / 4U); i++, offset++, MASK >>= 1) {
bool b = READ_BIT1(data, offset) != 0x00U;
if (b)
frag3 |= MASK;
}
MASK = 0x800U;
for (unsigned int i = 0U; i < (M17_LICH_FRAGMENT_LENGTH_BITS / 4U); i++, offset++, MASK >>= 1) {
bool b = READ_BIT1(data, offset) != 0x00U;
if (b)
frag4 |= MASK;
}
}
void CM17Utils::splitFragmentLICHFEC(const unsigned char* data, unsigned int& frag1, unsigned int& frag2, unsigned int& frag3, unsigned int& frag4)
{
assert(data != nullptr);
frag1 = frag2 = frag3 = frag4 = 0x00U;
unsigned int offset = 0U;
unsigned int MASK = 0x800000U;
for (unsigned int i = 0U; i < (M17_LICH_FRAGMENT_FEC_LENGTH_BITS / 4U); i++, offset++, MASK >>= 1) {
bool b = READ_BIT1(data, offset) != 0x00U;
if (b)
frag1 |= MASK;
}
MASK = 0x800000U;
for (unsigned int i = 0U; i < (M17_LICH_FRAGMENT_FEC_LENGTH_BITS / 4U); i++, offset++, MASK >>= 1) {
bool b = READ_BIT1(data, offset) != 0x00U;
if (b)
frag2 |= MASK;
}
MASK = 0x800000U;
for (unsigned int i = 0U; i < (M17_LICH_FRAGMENT_FEC_LENGTH_BITS / 4U); i++, offset++, MASK >>= 1) {
bool b = READ_BIT1(data, offset) != 0x00U;
if (b)
frag3 |= MASK;
}
MASK = 0x800000U;
for (unsigned int i = 0U; i < (M17_LICH_FRAGMENT_FEC_LENGTH_BITS / 4U); i++, offset++, MASK >>= 1) {
bool b = READ_BIT1(data, offset) != 0x00U;
if (b)
frag4 |= MASK;
}
}
void CM17Utils::combineFragmentLICH(unsigned int frag1, unsigned int frag2, unsigned int frag3, unsigned int frag4, unsigned char* data)
{
assert(data != nullptr);
unsigned int offset = 0U;
unsigned int MASK = 0x800U;
for (unsigned int i = 0U; i < (M17_LICH_FRAGMENT_LENGTH_BITS / 4U); i++, offset++, MASK >>= 1) {
bool b = (frag1 & MASK) == MASK;
WRITE_BIT1(data, offset, b);
}
MASK = 0x800U;
for (unsigned int i = 0U; i < (M17_LICH_FRAGMENT_LENGTH_BITS / 4U); i++, offset++, MASK >>= 1) {
bool b = (frag2 & MASK) == MASK;
WRITE_BIT1(data, offset, b);
}
MASK = 0x800U;
for (unsigned int i = 0U; i < (M17_LICH_FRAGMENT_LENGTH_BITS / 4U); i++, offset++, MASK >>= 1) {
bool b = (frag3 & MASK) == MASK;
WRITE_BIT1(data, offset, b);
}
MASK = 0x800U;
for (unsigned int i = 0U; i < (M17_LICH_FRAGMENT_LENGTH_BITS / 4U); i++, offset++, MASK >>= 1) {
bool b = (frag4 & MASK) == MASK;
WRITE_BIT1(data, offset, b);
}
}
void CM17Utils::combineFragmentLICHFEC(unsigned int frag1, unsigned int frag2, unsigned int frag3, unsigned int frag4, unsigned char* data)
{
assert(data != nullptr);
unsigned int offset = 0U;
unsigned int MASK = 0x800000U;
for (unsigned int i = 0U; i < (M17_LICH_FRAGMENT_FEC_LENGTH_BITS / 4U); i++, offset++, MASK >>= 1) {
bool b = (frag1 & MASK) == MASK;
WRITE_BIT1(data, offset, b);
}
MASK = 0x800000U;
for (unsigned int i = 0U; i < (M17_LICH_FRAGMENT_FEC_LENGTH_BITS / 4U); i++, offset++, MASK >>= 1) {
bool b = (frag2 & MASK) == MASK;
WRITE_BIT1(data, offset, b);
}
MASK = 0x800000U;
for (unsigned int i = 0U; i < (M17_LICH_FRAGMENT_FEC_LENGTH_BITS / 4U); i++, offset++, MASK >>= 1) {
bool b = (frag3 & MASK) == MASK;
WRITE_BIT1(data, offset, b);
}
MASK = 0x800000U;
for (unsigned int i = 0U; i < (M17_LICH_FRAGMENT_FEC_LENGTH_BITS / 4U); i++, offset++, MASK >>= 1) {
bool b = (frag4 & MASK) == MASK;
WRITE_BIT1(data, offset, b);
}
}

View file

@ -1,41 +0,0 @@
/*
* Copyright (C) 2020 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(M17Utils_H)
#define M17Utils_H
#include <string>
class CM17Utils {
public:
CM17Utils();
~CM17Utils();
static void encodeCallsign(const std::string& callsign, unsigned char* encoded);
static void decodeCallsign(const unsigned char* encoded, std::string& callsign);
static void splitFragmentLICH(const unsigned char* data, unsigned int& frag1, unsigned int& frag2, unsigned int& frag3, unsigned int& frag4);
static void splitFragmentLICHFEC(const unsigned char* data, unsigned int& frag1, unsigned int& frag2, unsigned int& frag3, unsigned int& frag4);
static void combineFragmentLICH(unsigned int frag1, unsigned int frag2, unsigned int frag3, unsigned int frag4, unsigned char* data);
static void combineFragmentLICHFEC(unsigned int frag1, unsigned int frag2, unsigned int frag3, unsigned int frag4, unsigned char* data);
private:
};
#endif

View file

@ -77,7 +77,6 @@ RFLevel=100
# YSFTXLevel=50
# P25TXLevel=50
# NXDNTXLevel=50
# M17TXLevel=50
# POCSAGTXLevel=50
# FMTXLevel=50
# AX25TXLevel=50
@ -148,13 +147,6 @@ RemoteGateway=0
TXHang=5
# ModeHang=10
[M17]
Enable=1
CAN=0
SelfOnly=0
TXHang=5
# ModeHang=10
[POCSAG]
Enable=1
Frequency=439987500
@ -267,15 +259,6 @@ GatewayPort=14020
# ModeHang=3
Debug=0
[M17 Network]
Enable=1
LocalAddress=127.0.0.1
LocalPort=17011
GatewayAddress=127.0.0.1
GatewayPort=17010
# ModeHang=3
Debug=0
[POCSAG Network]
Enable=1
LocalAddress=127.0.0.1

View file

@ -139,7 +139,6 @@ m_dmr(nullptr),
m_ysf(nullptr),
m_p25(nullptr),
m_nxdn(nullptr),
m_m17(nullptr),
m_pocsag(nullptr),
m_fm(nullptr),
m_ax25(nullptr),
@ -148,7 +147,6 @@ m_dmrNetwork(nullptr),
m_ysfNetwork(nullptr),
m_p25Network(nullptr),
m_nxdnNetwork(nullptr),
m_m17Network(nullptr),
m_pocsagNetwork(nullptr),
m_fmNetwork(nullptr),
m_ax25Network(nullptr),
@ -159,14 +157,12 @@ m_dmrRFModeHang(10U),
m_ysfRFModeHang(10U),
m_p25RFModeHang(10U),
m_nxdnRFModeHang(10U),
m_m17RFModeHang(10U),
m_fmRFModeHang(10U),
m_dstarNetModeHang(3U),
m_dmrNetModeHang(3U),
m_ysfNetModeHang(3U),
m_p25NetModeHang(3U),
m_nxdnNetModeHang(3U),
m_m17NetModeHang(3U),
m_pocsagNetModeHang(3U),
m_fmNetModeHang(3U),
m_modeTimer(1000U),
@ -179,7 +175,6 @@ m_dmrEnabled(false),
m_ysfEnabled(false),
m_p25Enabled(false),
m_nxdnEnabled(false),
m_m17Enabled(false),
m_pocsagEnabled(false),
m_fmEnabled(false),
m_ax25Enabled(false),
@ -326,11 +321,6 @@ int CMMDVMHost::run()
m_nxdnEnabled = false;
}
if (m_m17Enabled && !m_modem->hasM17()) {
LogWarning("M17 enabled in the host but not in the modem firmware, disabling");
m_m17Enabled = false;
}
if (m_fmEnabled && !m_modem->hasFM()) {
LogWarning("FM enabled in the host but not in the modem firmware, disabling");
m_fmEnabled = false;
@ -380,12 +370,6 @@ int CMMDVMHost::run()
return 1;
}
if (m_m17Enabled && m_conf.getM17NetworkEnabled()) {
ret = createM17Network();
if (!ret)
return 1;
}
if (m_pocsagEnabled && m_conf.getPOCSAGNetworkEnabled()) {
ret = createPOCSAGNetwork();
if (!ret)
@ -690,23 +674,6 @@ int CMMDVMHost::run()
m_nxdn = new CNXDNControl(ran, id, selfOnly, m_nxdnNetwork, m_display, m_timeout, m_duplex, remoteGateway, m_nxdnLookup, rssi);
}
if (m_m17Enabled) {
bool selfOnly = m_conf.getM17SelfOnly();
unsigned int can = m_conf.getM17CAN();
bool allowEncryption = m_conf.getM17AllowEncryption();
unsigned int txHang = m_conf.getM17TXHang();
m_m17RFModeHang = m_conf.getM17ModeHang();
LogInfo("M17 RF Parameters");
LogInfo(" Self Only: %s", selfOnly ? "yes" : "no");
LogInfo(" CAN: %u", can);
LogInfo(" Allow Encryption: %s", allowEncryption ? "yes" : "no");
LogInfo(" TX Hang: %us", txHang);
LogInfo(" Mode Hang: %us", m_m17RFModeHang);
m_m17 = new CM17Control(m_callsign, can, selfOnly, allowEncryption, m_m17Network, m_display, m_timeout, m_duplex, rssi);
}
CTimer pocsagTimer(1000U, 30U);
if (m_pocsagEnabled) {
@ -930,23 +897,6 @@ int CMMDVMHost::run()
}
}
len = m_modem->readM17Data(data);
if (m_m17 != nullptr && m_m17Enabled && len > 0U) {
if (m_mode == MODE_IDLE) {
bool ret = m_m17->writeModem(data, len);
if (ret) {
m_modeTimer.setTimeout(m_m17RFModeHang);
setMode(MODE_M17);
}
} else if (m_mode == MODE_M17) {
bool ret = m_m17->writeModem(data, len);
if (ret)
m_modeTimer.start();
} else if (m_mode != MODE_LOCKOUT) {
LogWarning("M17 modem data received when in mode %u", m_mode);
}
}
len = m_modem->readFMData(data);
if (m_fm != nullptr && m_fmEnabled && len > 0U) {
if (m_mode == MODE_IDLE) {
@ -1104,25 +1054,6 @@ int CMMDVMHost::run()
}
}
if (m_m17 != nullptr && m_m17Enabled) {
ret = m_modem->hasM17Space();
if (ret) {
len = m_m17->readModem(data);
if (len > 0U) {
if (m_mode == MODE_IDLE) {
m_modeTimer.setTimeout(m_m17NetModeHang);
setMode(MODE_M17);
}
if (m_mode == MODE_M17) {
m_modem->writeM17Data(data, len);
m_modeTimer.start();
} else if (m_mode != MODE_LOCKOUT) {
LogWarning("M17 data received when in mode %u", m_mode);
}
}
}
}
if (m_pocsag != nullptr && m_pocsagEnabled) {
ret = m_modem->hasPOCSAGSpace();
if (ret) {
@ -1216,8 +1147,6 @@ int CMMDVMHost::run()
m_p25->clock(ms);
if (m_nxdn != nullptr)
m_nxdn->clock(ms);
if (m_m17 != nullptr)
m_m17->clock(ms);
if (m_pocsag != nullptr)
m_pocsag->clock(ms);
if (m_fm != nullptr)
@ -1233,8 +1162,6 @@ int CMMDVMHost::run()
m_p25Network->clock(ms);
if (m_nxdnNetwork != nullptr)
m_nxdnNetwork->clock(ms);
if (m_m17Network != nullptr)
m_m17Network->clock(ms);
if (m_pocsagNetwork != nullptr)
m_pocsagNetwork->clock(ms);
if (m_fmNetwork != nullptr)
@ -1343,11 +1270,6 @@ int CMMDVMHost::run()
delete m_nxdnNetwork;
}
if (m_m17Network != nullptr) {
m_m17Network->close();
delete m_m17Network;
}
if (m_pocsagNetwork != nullptr) {
m_pocsagNetwork->close();
delete m_pocsagNetwork;
@ -1380,7 +1302,6 @@ int CMMDVMHost::run()
delete m_ysf;
delete m_p25;
delete m_nxdn;
delete m_m17;
delete m_pocsag;
delete m_fm;
delete m_ax25;
@ -1421,7 +1342,6 @@ bool CMMDVMHost::createModem()
float ysfTXLevel = m_conf.getModemYSFTXLevel();
float p25TXLevel = m_conf.getModemP25TXLevel();
float nxdnTXLevel = m_conf.getModemNXDNTXLevel();
float m17TXLevel = m_conf.getModemM17TXLevel();
float pocsagTXLevel = m_conf.getModemPOCSAGTXLevel();
float fmTXLevel = m_conf.getModemFMTXLevel();
float ax25TXLevel = m_conf.getModemAX25TXLevel();
@ -1432,7 +1352,6 @@ bool CMMDVMHost::createModem()
unsigned int ysfTXHang = m_conf.getFusionTXHang();
unsigned int p25TXHang = m_conf.getP25TXHang();
unsigned int nxdnTXHang = m_conf.getNXDNTXHang();
unsigned int m17TXHang = m_conf.getM17TXHang();
unsigned int rxFrequency = m_conf.getRXFrequency();
unsigned int txFrequency = m_conf.getTXFrequency();
unsigned int pocsagFrequency = m_conf.getPOCSAGFrequency();
@ -1483,7 +1402,6 @@ bool CMMDVMHost::createModem()
LogInfo(" YSF TX Level: %.1f%%", ysfTXLevel);
LogInfo(" P25 TX Level: %.1f%%", p25TXLevel);
LogInfo(" NXDN TX Level: %.1f%%", nxdnTXLevel);
LogInfo(" M17 TX Level: %.1f%%", m17TXLevel);
LogInfo(" POCSAG TX Level: %.1f%%", pocsagTXLevel);
LogInfo(" FM TX Level: %.1f%%", fmTXLevel);
LogInfo(" AX.25 TX Level: %.1f%%", ax25TXLevel);
@ -1507,14 +1425,13 @@ bool CMMDVMHost::createModem()
return false;
m_modem->setPort(port);
m_modem->setModeParams(m_dstarEnabled, m_dmrEnabled, m_ysfEnabled, m_p25Enabled, m_nxdnEnabled, m_m17Enabled, m_pocsagEnabled, m_fmEnabled, m_ax25Enabled);
m_modem->setLevels(rxLevel, cwIdTXLevel, dstarTXLevel, dmrTXLevel, ysfTXLevel, p25TXLevel, nxdnTXLevel, m17TXLevel, pocsagTXLevel, fmTXLevel, ax25TXLevel);
m_modem->setModeParams(m_dstarEnabled, m_dmrEnabled, m_ysfEnabled, m_p25Enabled, m_nxdnEnabled, m_pocsagEnabled, m_fmEnabled, m_ax25Enabled);
m_modem->setLevels(rxLevel, cwIdTXLevel, dstarTXLevel, dmrTXLevel, ysfTXLevel, p25TXLevel, nxdnTXLevel, pocsagTXLevel, fmTXLevel, ax25TXLevel);
m_modem->setRFParams(rxFrequency, rxOffset, txFrequency, txOffset, txDCOffset, rxDCOffset, rfLevel, pocsagFrequency);
m_modem->setDMRParams(colorCode);
m_modem->setYSFParams(lowDeviation, ysfTXHang);
m_modem->setP25Params(p25TXHang);
m_modem->setNXDNParams(nxdnTXHang);
m_modem->setM17Params(m17TXHang);
m_modem->setAX25Params(rxTwist, ax25TXDelay, ax25SlotTime, ax25PPersist);
if (m_fmEnabled) {
@ -1824,35 +1741,6 @@ bool CMMDVMHost::createNXDNNetwork()
return true;
}
bool CMMDVMHost::createM17Network()
{
std::string gatewayAddress = m_conf.getM17GatewayAddress();
unsigned short gatewayPort = m_conf.getM17GatewayPort();
std::string localAddress = m_conf.getM17LocalAddress();
unsigned short localPort = m_conf.getM17LocalPort();
m_m17NetModeHang = m_conf.getM17NetworkModeHang();
bool debug = m_conf.getM17NetworkDebug();
LogInfo("M17 Network Parameters");
LogInfo(" Gateway Address: %s", gatewayAddress.c_str());
LogInfo(" Gateway Port: %hu", gatewayPort);
LogInfo(" Local Address: %s", localAddress.c_str());
LogInfo(" Local Port: %hu", localPort);
LogInfo(" Mode Hang: %us", m_m17NetModeHang);
m_m17Network = new CM17Network(localAddress, localPort, gatewayAddress, gatewayPort, debug);
bool ret = m_m17Network->open();
if (!ret) {
delete m_m17Network;
m_m17Network = nullptr;
return false;
}
m_m17Network->enable(true);
return true;
}
bool CMMDVMHost::createPOCSAGNetwork()
{
std::string gatewayAddress = m_conf.getPOCSAGGatewayAddress();
@ -1961,7 +1849,6 @@ void CMMDVMHost::readParams()
m_ysfEnabled = m_conf.getFusionEnabled();
m_p25Enabled = m_conf.getP25Enabled();
m_nxdnEnabled = m_conf.getNXDNEnabled();
m_m17Enabled = m_conf.getM17Enabled();
m_pocsagEnabled = m_conf.getPOCSAGEnabled();
m_fmEnabled = m_conf.getFMEnabled();
m_ax25Enabled = m_conf.getAX25Enabled();
@ -1980,7 +1867,6 @@ void CMMDVMHost::readParams()
LogInfo(" YSF: %s", m_ysfEnabled ? "enabled" : "disabled");
LogInfo(" P25: %s", m_p25Enabled ? "enabled" : "disabled");
LogInfo(" NXDN: %s", m_nxdnEnabled ? "enabled" : "disabled");
LogInfo(" M17: %s", m_m17Enabled ? "enabled" : "disabled");
LogInfo(" POCSAG: %s", m_pocsagEnabled ? "enabled" : "disabled");
LogInfo(" FM: %s", m_fmEnabled ? "enabled" : "disabled");
LogInfo(" AX.25: %s", m_ax25Enabled ? "enabled" : "disabled");
@ -1992,7 +1878,7 @@ void CMMDVMHost::enableModemMode(bool& mode, bool enabled)
mode = enabled;
m_modem->setModeParams(m_dstarEnabled, m_dmrEnabled, m_ysfEnabled, m_p25Enabled, m_nxdnEnabled, m_m17Enabled, m_pocsagEnabled, m_fmEnabled, m_ax25Enabled);
m_modem->setModeParams(m_dstarEnabled, m_dmrEnabled, m_ysfEnabled, m_p25Enabled, m_nxdnEnabled, m_pocsagEnabled, m_fmEnabled, m_ax25Enabled);
if (!m_modem->writeConfig())
LogError("Cannot write Config to MMDVM");
}
@ -2033,11 +1919,6 @@ void CMMDVMHost::processEnableModeCommand(unsigned char mode, bool hasController
m_nxdnNetwork->enable(enableMode);
m_nxdn->enable(enableMode);
break;
case MODE_M17:
if (m_m17Network != nullptr)
m_m17Network->enable(enableMode);
m_m17->enable(enableMode);
break;
case MODE_FM:
if (isAX25)
m_ax25->enable(enableMode);
@ -2066,9 +1947,6 @@ void CMMDVMHost::processEnableModeCommand(unsigned char mode, bool hasController
case MODE_NXDN:
while (m_modem->readNXDNData(data) > 0U);
break;
case MODE_M17:
while (m_modem->readM17Data(data) > 0U);
break;
case MODE_FM:
while ((isAX25 ? m_modem->readAX25Data(data) : m_modem->readFMData(data)) > 0U);
break;
@ -2100,8 +1978,6 @@ void CMMDVMHost::setMode(unsigned char mode)
m_p25Network->enable(false);
if (m_nxdnNetwork != nullptr)
m_nxdnNetwork->enable(false);
if (m_m17Network != nullptr)
m_m17Network->enable(false);
if (m_pocsagNetwork != nullptr)
m_pocsagNetwork->enable(false);
if (m_fmNetwork != nullptr)
@ -2118,8 +1994,6 @@ void CMMDVMHost::setMode(unsigned char mode)
m_p25->enable(false);
if (m_nxdn != nullptr)
m_nxdn->enable(false);
if (m_m17 != nullptr)
m_m17->enable(false);
if (m_pocsag != nullptr)
m_pocsag->enable(false);
if (m_fm != nullptr)
@ -2147,8 +2021,6 @@ void CMMDVMHost::setMode(unsigned char mode)
m_p25Network->enable(false);
if (m_nxdnNetwork != nullptr)
m_nxdnNetwork->enable(false);
if (m_m17Network != nullptr)
m_m17Network->enable(false);
if (m_pocsagNetwork != nullptr)
m_pocsagNetwork->enable(false);
if (m_fmNetwork != nullptr)
@ -2165,8 +2037,6 @@ void CMMDVMHost::setMode(unsigned char mode)
m_p25->enable(false);
if (m_nxdn != nullptr)
m_nxdn->enable(false);
if (m_m17 != nullptr)
m_m17->enable(false);
if (m_pocsag != nullptr)
m_pocsag->enable(false);
if (m_fm != nullptr)
@ -2198,8 +2068,6 @@ void CMMDVMHost::setMode(unsigned char mode)
m_p25Network->enable(false);
if (m_nxdnNetwork != nullptr)
m_nxdnNetwork->enable(false);
if (m_m17Network != nullptr)
m_m17Network->enable(false);
if (m_pocsagNetwork != nullptr)
m_pocsagNetwork->enable(false);
if (m_fmNetwork != nullptr)
@ -2216,8 +2084,6 @@ void CMMDVMHost::setMode(unsigned char mode)
m_p25->enable(false);
if (m_nxdn != nullptr)
m_nxdn->enable(false);
if (m_m17 != nullptr)
m_m17->enable(false);
if (m_pocsag != nullptr)
m_pocsag->enable(false);
if (m_fm != nullptr)
@ -2245,8 +2111,6 @@ void CMMDVMHost::setMode(unsigned char mode)
m_p25Network->enable(true);
if (m_nxdnNetwork != nullptr)
m_nxdnNetwork->enable(false);
if (m_m17Network != nullptr)
m_m17Network->enable(false);
if (m_pocsagNetwork != nullptr)
m_pocsagNetwork->enable(false);
if (m_fmNetwork != nullptr)
@ -2263,8 +2127,6 @@ void CMMDVMHost::setMode(unsigned char mode)
m_p25->enable(true);
if (m_nxdn != nullptr)
m_nxdn->enable(false);
if (m_m17 != nullptr)
m_m17->enable(false);
if (m_pocsag != nullptr)
m_pocsag->enable(false);
if (m_fm != nullptr)
@ -2292,8 +2154,6 @@ void CMMDVMHost::setMode(unsigned char mode)
m_p25Network->enable(false);
if (m_nxdnNetwork != nullptr && m_nxdnEnabled)
m_nxdnNetwork->enable(true);
if (m_m17Network != nullptr)
m_m17Network->enable(false);
if (m_pocsagNetwork != nullptr)
m_pocsagNetwork->enable(false);
if (m_fmNetwork != nullptr)
@ -2310,8 +2170,6 @@ void CMMDVMHost::setMode(unsigned char mode)
m_p25->enable(false);
if (m_nxdn != nullptr && m_nxdnEnabled)
m_nxdn->enable(true);
if (m_m17 != nullptr)
m_m17->enable(false);
if (m_pocsag != nullptr)
m_pocsag->enable(false);
if (m_fm != nullptr)
@ -2328,53 +2186,6 @@ void CMMDVMHost::setMode(unsigned char mode)
}
break;
case MODE_M17:
if (m_dstarNetwork != nullptr)
m_dstarNetwork->enable(false);
if (m_dmrNetwork != nullptr)
m_dmrNetwork->enable(false);
if (m_ysfNetwork != nullptr)
m_ysfNetwork->enable(false);
if (m_p25Network != nullptr)
m_p25Network->enable(false);
if (m_nxdnNetwork != nullptr)
m_nxdnNetwork->enable(false);
if (m_m17Network != nullptr && m_m17Enabled)
m_m17Network->enable(true);
if (m_pocsagNetwork != nullptr)
m_pocsagNetwork->enable(false);
if (m_fmNetwork != nullptr)
m_fmNetwork->enable(false);
if (m_ax25Network != nullptr)
m_ax25Network->enable(false);
if (m_dstar != nullptr)
m_dstar->enable(false);
if (m_dmr != nullptr)
m_dmr->enable(false);
if (m_ysf != nullptr)
m_ysf->enable(false);
if (m_p25 != nullptr)
m_p25->enable(false);
if (m_nxdn != nullptr)
m_nxdn->enable(false);
if (m_m17 != nullptr && m_m17Enabled)
m_m17->enable(true);
if (m_pocsag != nullptr)
m_pocsag->enable(false);
if (m_fm != nullptr)
m_fm->enable(false);
if (m_ax25 != nullptr)
m_ax25->enable(false);
if (m_m17Enabled) {
m_modem->setMode(MODE_M17);
m_mode = MODE_M17;
m_modeTimer.start();
m_cwIdTimer.stop();
createLockFile("M17");
LogMessage("Mode set to M17");
}
break;
case MODE_POCSAG:
if (m_dstarNetwork != nullptr)
m_dstarNetwork->enable(false);
@ -2386,8 +2197,6 @@ void CMMDVMHost::setMode(unsigned char mode)
m_p25Network->enable(false);
if (m_nxdnNetwork != nullptr)
m_nxdnNetwork->enable(false);
if (m_m17Network != nullptr)
m_m17Network->enable(false);
if (m_pocsagNetwork != nullptr && m_pocsagEnabled)
m_pocsagNetwork->enable(true);
if (m_fmNetwork != nullptr)
@ -2404,8 +2213,6 @@ void CMMDVMHost::setMode(unsigned char mode)
m_p25->enable(false);
if (m_nxdn != nullptr)
m_nxdn->enable(false);
if (m_m17 != nullptr)
m_m17->enable(false);
if (m_pocsag != nullptr && m_pocsagEnabled)
m_pocsag->enable(true);
if (m_fm != nullptr)
@ -2431,8 +2238,6 @@ void CMMDVMHost::setMode(unsigned char mode)
m_p25Network->enable(false);
if (m_nxdnNetwork != nullptr)
m_nxdnNetwork->enable(false);
if (m_m17Network != nullptr)
m_m17Network->enable(false);
if (m_pocsagNetwork != nullptr)
m_pocsagNetwork->enable(false);
if (m_fmNetwork != nullptr && m_fmEnabled)
@ -2449,8 +2254,6 @@ void CMMDVMHost::setMode(unsigned char mode)
m_p25->enable(false);
if (m_nxdn != nullptr)
m_nxdn->enable(false);
if (m_m17 != nullptr)
m_m17->enable(false);
if (m_pocsag != nullptr)
m_pocsag->enable(false);
if (m_fm != nullptr && m_fmEnabled)
@ -2483,8 +2286,6 @@ void CMMDVMHost::setMode(unsigned char mode)
m_p25Network->enable(false);
if (m_nxdnNetwork != nullptr)
m_nxdnNetwork->enable(false);
if (m_m17Network != nullptr)
m_m17Network->enable(false);
if (m_pocsagNetwork != nullptr)
m_pocsagNetwork->enable(false);
if (m_fmNetwork != nullptr)
@ -2501,8 +2302,6 @@ void CMMDVMHost::setMode(unsigned char mode)
m_p25->enable(false);
if (m_nxdn != nullptr)
m_nxdn->enable(false);
if (m_m17 != nullptr)
m_m17->enable(false);
if (m_pocsag != nullptr)
m_pocsag->enable(false);
if (m_fm != nullptr)
@ -2534,8 +2333,6 @@ void CMMDVMHost::setMode(unsigned char mode)
m_p25Network->enable(false);
if (m_nxdnNetwork != nullptr)
m_nxdnNetwork->enable(false);
if (m_m17Network != nullptr)
m_m17Network->enable(false);
if (m_pocsagNetwork != nullptr)
m_pocsagNetwork->enable(false);
if (m_fmNetwork != nullptr)
@ -2552,8 +2349,6 @@ void CMMDVMHost::setMode(unsigned char mode)
m_p25->enable(false);
if (m_nxdn != nullptr)
m_nxdn->enable(false);
if (m_m17 != nullptr)
m_m17->enable(false);
if (m_pocsag != nullptr)
m_pocsag->enable(false);
if (m_fm != nullptr)
@ -2583,8 +2378,6 @@ void CMMDVMHost::setMode(unsigned char mode)
m_p25Network->enable(true);
if (m_nxdnNetwork != nullptr && m_nxdnEnabled)
m_nxdnNetwork->enable(true);
if (m_m17Network != nullptr && m_m17Enabled)
m_m17Network->enable(true);
if (m_pocsagNetwork != nullptr && m_pocsagEnabled)
m_pocsagNetwork->enable(true);
if (m_fmNetwork != nullptr && m_fmEnabled)
@ -2601,8 +2394,6 @@ void CMMDVMHost::setMode(unsigned char mode)
m_p25->enable(true);
if (m_nxdn != nullptr && m_nxdnEnabled)
m_nxdn->enable(true);
if (m_m17 != nullptr && m_m17Enabled)
m_m17->enable(true);
if (m_pocsag != nullptr && m_pocsagEnabled)
m_pocsag->enable(true);
if (m_fm != nullptr && m_fmEnabled)
@ -2685,10 +2476,6 @@ void CMMDVMHost::remoteControl()
if (m_nxdn != nullptr)
processModeCommand(MODE_NXDN, m_nxdnRFModeHang);
break;
case REMOTE_COMMAND::MODE_M17:
if (m_m17 != nullptr)
processModeCommand(MODE_M17, m_m17RFModeHang);
break;
case REMOTE_COMMAND::MODE_FM:
if (m_fmEnabled)
processModeCommand(MODE_FM, 0);
@ -2708,9 +2495,6 @@ void CMMDVMHost::remoteControl()
case REMOTE_COMMAND::ENABLE_NXDN:
processEnableModeCommand(MODE_NXDN, (m_nxdn != nullptr), m_nxdnEnabled, true);
break;
case REMOTE_COMMAND::ENABLE_M17:
processEnableModeCommand(MODE_M17, (m_m17 != nullptr), m_m17Enabled, true);
break;
case REMOTE_COMMAND::ENABLE_FM:
processEnableModeCommand(MODE_FM, (m_fm != nullptr), m_fmEnabled, true);
break;
@ -2732,9 +2516,6 @@ void CMMDVMHost::remoteControl()
case REMOTE_COMMAND::DISABLE_NXDN:
processEnableModeCommand(MODE_NXDN, (m_nxdn != nullptr), m_nxdnEnabled, false);
break;
case REMOTE_COMMAND::DISABLE_M17:
processEnableModeCommand(MODE_M17, (m_m17 != nullptr), m_m17Enabled, false);
break;
case REMOTE_COMMAND::DISABLE_FM:
processEnableModeCommand(MODE_FM, (m_fm != nullptr), m_fmEnabled, false);
break;
@ -2830,7 +2611,6 @@ void CMMDVMHost::buildNetworkStatusString(std::string &str)
str += std::string(" ysf:") + (((m_ysfNetwork == nullptr) || (m_ysfEnabled == false)) ? "n/a" : (m_ysfNetwork->isConnected() ? "conn" : "disc"));
str += std::string(" p25:") + (((m_p25Network == nullptr) || (m_p25Enabled == false)) ? "n/a" : (m_p25Network->isConnected() ? "conn" : "disc"));
str += std::string(" nxdn:") + (((m_nxdnNetwork == nullptr) || (m_nxdnEnabled == false)) ? "n/a" : (m_nxdnNetwork->isConnected() ? "conn" : "disc"));
str += std::string(" m17:") + (((m_m17Network == nullptr) || (m_m17Enabled == false)) ? "n/a" : (m_m17Network->isConnected() ? "conn" : "disc"));
str += std::string(" fm:") + (m_fmEnabled ? "conn" : "n/a");
}
@ -2864,6 +2644,5 @@ void CMMDVMHost::buildNetworkHostsString(std::string &str)
str += std::string(" ysf:\"") + ((m_ysfEnabled && (m_ysfNetwork != nullptr)) ? m_conf.getFusionNetworkGatewayAddress() : "NONE") + "\"";
str += std::string(" p25:\"") + ((m_p25Enabled && (m_p25Network != nullptr)) ? m_conf.getP25GatewayAddress() : "NONE") + "\"";
str += std::string(" nxdn:\"") + ((m_nxdnEnabled && (m_nxdnNetwork != nullptr)) ? m_conf.getNXDNGatewayAddress() : "NONE") + "\"";
str += std::string(" m17:\"") + ((m_m17Enabled && (m_m17Network != nullptr)) ? m_conf.getM17GatewayAddress() : "NONE") + "\"";
str += std::string(" fm:\"") + ((m_fmEnabled && (m_fmNetwork != nullptr)) ? m_conf.getFMGatewayAddress() : "NONE") + "\"";
}

View file

@ -1,5 +1,5 @@
/*
* Copyright (C) 2015-2021 by Jonathan Naylor G4KLX
* Copyright (C) 2015-2021,2025 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,12 +31,10 @@
#include "YSFControl.h"
#include "P25Control.h"
#include "NXDNControl.h"
#include "M17Control.h"
#include "NXDNLookup.h"
#include "YSFNetwork.h"
#include "P25Network.h"
#include "DMRNetwork.h"
#include "M17Network.h"
#include "FMNetwork.h"
#include "DMRLookup.h"
#include "FMControl.h"
@ -67,7 +65,6 @@ private:
CYSFControl* m_ysf;
CP25Control* m_p25;
CNXDNControl* m_nxdn;
CM17Control* m_m17;
CPOCSAGControl* m_pocsag;
CFMControl* m_fm;
CAX25Control* m_ax25;
@ -76,7 +73,6 @@ private:
CYSFNetwork* m_ysfNetwork;
CP25Network* m_p25Network;
INXDNNetwork* m_nxdnNetwork;
CM17Network* m_m17Network;
CPOCSAGNetwork* m_pocsagNetwork;
CFMNetwork* m_fmNetwork;
CAX25Network* m_ax25Network;
@ -87,14 +83,12 @@ private:
unsigned int m_ysfRFModeHang;
unsigned int m_p25RFModeHang;
unsigned int m_nxdnRFModeHang;
unsigned int m_m17RFModeHang;
unsigned int m_fmRFModeHang;
unsigned int m_dstarNetModeHang;
unsigned int m_dmrNetModeHang;
unsigned int m_ysfNetModeHang;
unsigned int m_p25NetModeHang;
unsigned int m_nxdnNetModeHang;
unsigned int m_m17NetModeHang;
unsigned int m_pocsagNetModeHang;
unsigned int m_fmNetModeHang;
CTimer m_modeTimer;
@ -107,7 +101,6 @@ private:
bool m_ysfEnabled;
bool m_p25Enabled;
bool m_nxdnEnabled;
bool m_m17Enabled;
bool m_pocsagEnabled;
bool m_fmEnabled;
bool m_ax25Enabled;
@ -129,7 +122,6 @@ private:
bool createYSFNetwork();
bool createP25Network();
bool createNXDNNetwork();
bool createM17Network();
bool createPOCSAGNetwork();
bool createFMNetwork();
bool createAX25Network();

View file

@ -207,13 +207,6 @@
<ClInclude Include="IIRDirectForm1Filter.h" />
<ClInclude Include="LCDproc.h" />
<ClInclude Include="Log.h" />
<ClInclude Include="M17Control.h" />
<ClInclude Include="M17Convolution.h" />
<ClInclude Include="M17CRC.h" />
<ClInclude Include="M17Defines.h" />
<ClInclude Include="M17LSF.h" />
<ClInclude Include="M17Network.h" />
<ClInclude Include="M17Utils.h" />
<ClInclude Include="MMDVMHost.h" />
<ClInclude Include="ModemPort.h" />
<ClInclude Include="ModemSerialPort.h" />
@ -319,12 +312,6 @@
<ClCompile Include="IIRDirectForm1Filter.cpp" />
<ClCompile Include="LCDproc.cpp" />
<ClCompile Include="Log.cpp" />
<ClCompile Include="M17Control.cpp" />
<ClCompile Include="M17Convolution.cpp" />
<ClCompile Include="M17CRC.cpp" />
<ClCompile Include="M17LSF.cpp" />
<ClCompile Include="M17Network.cpp" />
<ClCompile Include="M17Utils.cpp" />
<ClCompile Include="MMDVMHost.cpp" />
<ClCompile Include="ModemPort.cpp" />
<ClCompile Include="ModemSerialPort.cpp" />

View file

@ -284,27 +284,6 @@
<ClInclude Include="NXDNKenwoodNetwork.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="M17Defines.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="M17Control.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="M17Network.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="M17LSF.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="M17CRC.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="M17Convolution.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="M17Utils.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="AX25Defines.h">
<Filter>Header Files</Filter>
</ClInclude>
@ -601,24 +580,6 @@
<ClCompile Include="NXDNKenwoodNetwork.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="M17Control.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="M17Network.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="M17CRC.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="M17Utils.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="M17LSF.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="M17Convolution.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="FMNetwork.cpp">
<Filter>Source Files</Filter>
</ClCompile>

View file

@ -12,7 +12,7 @@ OBJECTS = \
AMBEFEC.o BCH.o AX25Control.o AX25Network.o BPTC19696.o CASTInfo.o Conf.o CRC.o Display.o DMRControl.o DMRCSBK.o DMRData.o DMRDataHeader.o \
DMRDirectNetwork.o DMREMB.o DMREmbeddedData.o DMRFullLC.o DMRGatewayNetwork.o DMRLookup.o DMRLC.o DMRNetwork.o DMRShortLC.o DMRSlot.o DMRSlotType.o \
DMRAccessControl.o DMRTA.o DMRTrellis.o DStarControl.o DStarHeader.o DStarNetwork.o DStarSlowData.o FMControl.o FMNetwork.o Golay2087.o Golay24128.o \
Hamming.o I2CController.o IIRDirectForm1Filter.o LCDproc.o Log.o M17Control.o M17Convolution.o M17CRC.o M17LSF.o M17Network.o M17Utils.o MMDVMHost.o \
Hamming.o I2CController.o IIRDirectForm1Filter.o LCDproc.o Log.o MMDVMHost.o \
Modem.o ModemPort.o ModemSerialPort.o Mutex.o NetworkInfo.o Nextion.o NullController.o NullDisplay.o NXDNAudio.o NXDNControl.o \
NXDNConvolution.o NXDNCRC.o NXDNFACCH1.o NXDNIcomNetwork.o NXDNKenwoodNetwork.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 PseudoTTYController.o POCSAGControl.o \

View file

@ -13,7 +13,7 @@ OBJECTS = \
AMBEFEC.o AX25Control.o AX25Network.o BCH.o BPTC19696.o CASTInfo.o Conf.o CRC.o Display.o DMRControl.o DMRCSBK.o DMRData.o DMRDataHeader.o \
DMRDirectNetwork.o DMREMB.o DMREmbeddedData.o DMRFullLC.o DMRGatewayNetwork.o DMRLookup.o DMRLC.o DMRNetwork.o DMRShortLC.o DMRSlot.o DMRSlotType.o \
DMRAccessControl.o DMRTA.o DMRTrellis.o DStarControl.o DStarHeader.o DStarNetwork.o DStarSlowData.o FMControl.o FMNetwork.o Golay2087.o Golay24128.o \
Hamming.o HD44780.o I2CController.o IIRDirectForm1Filter.o LCDproc.o Log.o M17Control.o M17Convolution.o M17CRC.o M17LSF.o M17Network.o M17Utils.o \
Hamming.o HD44780.o I2CController.o IIRDirectForm1Filter.o LCDproc.o Log.o \
MMDVMHost.o Modem.o ModemPort.o ModemSerialPort.o Mutex.o NetworkInfo.o Nextion.o NullController.o NullDisplay.o NXDNAudio.o \
NXDNControl.o NXDNConvolution.o NXDNCRC.o NXDNFACCH1.o NXDNIcomNetwork.o NXDNKenwoodNetwork.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 PseudoTTYController.o \

View file

@ -12,7 +12,7 @@ OBJECTS = \
AMBEFEC.o AX25Control.o AX25Network.o BCH.o BPTC19696.o CASTInfo.o Conf.o CRC.o Display.o DMRControl.o DMRCSBK.o DMRData.o DMRDataHeader.o \
DMRDirectNetwork.o DMREMB.o DMREmbeddedData.o DMRFullLC.o DMRGatewayNetwork.o DMRLookup.o DMRLC.o DMRNetwork.o DMRShortLC.o DMRSlot.o DMRSlotType.o \
DMRAccessControl.o DMRTA.o DMRTrellis.o DStarControl.o DStarHeader.o DStarNetwork.o DStarSlowData.o FMControl.o FMNetwork.o Golay2087.o Golay24128.o \
Hamming.o HD44780.o I2CController.o IIRDirectForm1Filter.o LCDproc.o Log.o M17Control.o M17Convolution.o M17CRC.o M17LSF.o M17Network.o M17Utils.o \
Hamming.o HD44780.o I2CController.o IIRDirectForm1Filter.o LCDproc.o Log.o \
MMDVMHost.o Modem.o ModemPort.o ModemSerialPort.o Mutex.o NetworkInfo.o Nextion.o NullController.o NullDisplay.o NXDNAudio.o \
NXDNControl.o NXDNConvolution.o NXDNCRC.o NXDNFACCH1.o NXDNIcomNetwork.o NXDNKenwoodNetwork.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 PseudoTTYController.o \

View file

@ -12,7 +12,7 @@ OBJECTS = \
AMBEFEC.o AX25Control.o AX25Network.o BCH.o BPTC19696.o CASTInfo.o Conf.o CRC.o Display.o DMRControl.o DMRCSBK.o DMRData.o DMRDataHeader.o \
DMRDirectNetwork.o DMREMB.o DMREmbeddedData.o DMRFullLC.o DMRGatewayNetwork.o DMRLookup.o DMRLC.o DMRNetwork.o DMRShortLC.o DMRSlot.o DMRSlotType.o \
DMRAccessControl.o DMRTA.o DMRTrellis.o DStarControl.o DStarHeader.o DStarNetwork.o DStarSlowData.o FMControl.o FMNetwork.o Golay2087.o Golay24128.o \
Hamming.o I2CController.o IIRDirectForm1Filter.o LCDproc.o Log.o M17Control.o M17Convolution.o M17CRC.o M17LSF.o M17Network.o M17Utils.o MMDVMHost.o \
Hamming.o I2CController.o IIRDirectForm1Filter.o LCDproc.o Log.o MMDVMHost.o \
Modem.o ModemPort.o ModemSerialPort.o Mutex.o NetworkInfo.o Nextion.o NullController.o NullDisplay.o NXDNAudio.o NXDNControl.o \
NXDNConvolution.o NXDNCRC.o NXDNFACCH1.o NXDNIcomNetwork.o NXDNKenwoodNetwork.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 PseudoTTYController.o POCSAGControl.o \

View file

@ -16,7 +16,7 @@ OBJECTS = \
AMBEFEC.o AX25Control.o AX25Network.o BCH.o BPTC19696.o CASTInfo.o Conf.o CRC.o Display.o DMRControl.o DMRCSBK.o DMRData.o DMRDataHeader.o \
DMRDirectNetwork.o DMREMB.o DMREmbeddedData.o DMRFullLC.o DMRGatewayNetwork.o DMRLookup.o DMRLC.o DMRNetwork.o DMRShortLC.o DMRSlot.o DMRSlotType.o \
DMRAccessControl.o DMRTA.o DMRTrellis.o DStarControl.o DStarHeader.o DStarNetwork.o DStarSlowData.o FMControl.o FMNetwork.o Golay2087.o Golay24128.o \
Hamming.o I2CController.o IIRDirectForm1Filter.o LCDproc.o Log.o M17Control.o M17Convolution.o M17CRC.o M17LSF.o M17Network.o M17Utils.o MMDVMHost.o \
Hamming.o I2CController.o IIRDirectForm1Filter.o LCDproc.o Log.o MMDVMHost.o \
Modem.o ModemPort.o ModemSerialPort.o Mutex.o NetworkInfo.o Nextion.o NullController.o NullDisplay.o NXDNAudio.o NXDNControl.o \
NXDNConvolution.o NXDNCRC.o NXDNFACCH1.o NXDNIcomNetwork.o NXDNKenwoodNetwork.o NXDNLayer3.o NXDNLICH.o NXDNLookup.o NXDNNetwork.o NXDNSACCH.o \
NXDNUDCH.o OLED.o P25Audio.o P25Control.o P25Data.o P25LowSpeedData.o P25Network.o P25NID.o P25Trellis.o P25Utils.o PseudoTTYController.o \

View file

@ -13,7 +13,7 @@ OBJECTS = \
AMBEFEC.o AX25Control.o AX25Network.o BCH.o BPTC19696.o CASTInfo.o Conf.o CRC.o Display.o DMRControl.o DMRCSBK.o DMRData.o DMRDataHeader.o \
DMRDirectNetwork.o DMREMB.o DMREmbeddedData.o DMRFullLC.o DMRGatewayNetwork.o DMRLookup.o DMRLC.o DMRNetwork.o DMRShortLC.o DMRSlot.o DMRSlotType.o \
DMRAccessControl.o DMRTA.o DMRTrellis.o DStarControl.o DStarHeader.o DStarNetwork.o DStarSlowData.o FMControl.o FMNetwork.o Golay2087.o Golay24128.o \
Hamming.o HD44780.o I2CController.o IIRDirectForm1Filter.o LCDproc.o Log.o M17Control.o M17Convolution.o M17CRC.o M17LSF.o M17Network.o M17Utils.o \
Hamming.o HD44780.o I2CController.o IIRDirectForm1Filter.o LCDproc.o Log.o \
MMDVMHost.o Modem.o ModemPort.o ModemSerialPort.o Mutex.o NetworkInfo.o Nextion.o NullController.o NullDisplay.o NXDNAudio.o \
NXDNControl.o NXDNConvolution.o NXDNCRC.o NXDNFACCH1.o NXDNIcomNetwork.o NXDNKenwoodNetwork.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 PseudoTTYController.o \

212
Modem.cpp
View file

@ -23,7 +23,6 @@
#include "NXDNDefines.h"
#include "AX25Defines.h"
#include "POCSAGDefines.h"
#include "M17Defines.h"
#include "Thread.h"
#include "Modem.h"
#include "Utils.h"
@ -74,12 +73,6 @@ 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_M17_LINK_SETUP = 0x45U;
const unsigned char MMDVM_M17_STREAM = 0x46U;
const unsigned char MMDVM_M17_PACKET = 0x47U;
const unsigned char MMDVM_M17_LOST = 0x48U;
const unsigned char MMDVM_M17_EOT = 0x49U;
const unsigned char MMDVM_POCSAG_DATA = 0x50U;
const unsigned char MMDVM_AX25_DATA = 0x55U;
@ -116,7 +109,6 @@ const unsigned char CAP1_DMR = 0x02U;
const unsigned char CAP1_YSF = 0x04U;
const unsigned char CAP1_P25 = 0x08U;
const unsigned char CAP1_NXDN = 0x10U;
const unsigned char CAP1_M17 = 0x20U;
const unsigned char CAP1_FM = 0x40U;
const unsigned char CAP2_POCSAG = 0x01U;
const unsigned char CAP2_AX25 = 0x02U;
@ -129,7 +121,6 @@ m_ysfLoDev(false),
m_ysfTXHang(4U),
m_p25TXHang(5U),
m_nxdnTXHang(5U),
m_m17TXHang(5U),
m_duplex(duplex),
m_rxInvert(rxInvert),
m_txInvert(txInvert),
@ -143,7 +134,6 @@ m_dmrTXLevel(0.0F),
m_ysfTXLevel(0.0F),
m_p25TXLevel(0.0F),
m_nxdnTXLevel(0.0F),
m_m17TXLevel(0.0F),
m_pocsagTXLevel(0.0F),
m_fmTXLevel(0.0F),
m_ax25TXLevel(0.0F),
@ -159,7 +149,6 @@ m_dmrEnabled(false),
m_ysfEnabled(false),
m_p25Enabled(false),
m_nxdnEnabled(false),
m_m17Enabled(false),
m_pocsagEnabled(false),
m_fmEnabled(false),
m_ax25Enabled(false),
@ -183,8 +172,6 @@ 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_rxM17Data(1000U, "Modem RX M17"),
m_txM17Data(1000U, "Modem TX M17"),
m_txPOCSAGData(1000U, "Modem TX POCSAG"),
m_rxFMData(5000U, "Modem RX FM"),
m_txFMData(5000U, "Modem TX FM"),
@ -204,7 +191,6 @@ m_dmrSpace2(0U),
m_ysfSpace(0U),
m_p25Space(0U),
m_nxdnSpace(0U),
m_m17Space(0U),
m_pocsagSpace(0U),
m_fmSpace(0U),
m_ax25Space(0U),
@ -282,20 +268,19 @@ void CModem::setRFParams(unsigned int rxFrequency, int rxOffset, unsigned int tx
m_pocsagFrequency = pocsagFrequency + txOffset;
}
void CModem::setModeParams(bool dstarEnabled, bool dmrEnabled, bool ysfEnabled, bool p25Enabled, bool nxdnEnabled, bool m17Enabled, bool pocsagEnabled, bool fmEnabled, bool ax25Enabled)
void CModem::setModeParams(bool dstarEnabled, bool dmrEnabled, bool ysfEnabled, bool p25Enabled, bool nxdnEnabled, bool pocsagEnabled, bool fmEnabled, bool ax25Enabled)
{
m_dstarEnabled = dstarEnabled;
m_dmrEnabled = dmrEnabled;
m_ysfEnabled = ysfEnabled;
m_p25Enabled = p25Enabled;
m_nxdnEnabled = nxdnEnabled;
m_m17Enabled = m17Enabled;
m_pocsagEnabled = pocsagEnabled;
m_fmEnabled = fmEnabled;
m_ax25Enabled = ax25Enabled;
}
void CModem::setLevels(float rxLevel, float cwIdTXLevel, float dstarTXLevel, float dmrTXLevel, float ysfTXLevel, float p25TXLevel, float nxdnTXLevel, float m17TXLevel, float pocsagTXLevel, float fmTXLevel, float ax25TXLevel)
void CModem::setLevels(float rxLevel, float cwIdTXLevel, float dstarTXLevel, float dmrTXLevel, float ysfTXLevel, float p25TXLevel, float nxdnTXLevel, float pocsagTXLevel, float fmTXLevel, float ax25TXLevel)
{
m_rxLevel = rxLevel;
m_cwIdTXLevel = cwIdTXLevel;
@ -304,7 +289,6 @@ void CModem::setLevels(float rxLevel, float cwIdTXLevel, float dstarTXLevel, flo
m_ysfTXLevel = ysfTXLevel;
m_p25TXLevel = p25TXLevel;
m_nxdnTXLevel = nxdnTXLevel;
m_m17TXLevel = m17TXLevel;
m_pocsagTXLevel = pocsagTXLevel;
m_fmTXLevel = fmTXLevel;
m_ax25TXLevel = ax25TXLevel;
@ -333,11 +317,6 @@ void CModem::setNXDNParams(unsigned int txHang)
m_nxdnTXHang = txHang;
}
void CModem::setM17Params(unsigned int txHang)
{
m_m17TXHang = txHang;
}
void CModem::setAX25Params(int rxTwist, unsigned int txDelay, unsigned int slotTime, unsigned int pPersist)
{
m_ax25RXTwist = rxTwist;
@ -664,58 +643,6 @@ void CModem::clock(unsigned int ms)
}
break;
case MMDVM_M17_LINK_SETUP: {
if (m_trace)
CUtils::dump(1U, "RX M17 Link Setup", m_buffer, m_length);
unsigned char data = m_length - 2U;
m_rxM17Data.addData(&data, 1U);
data = TAG_HEADER;
m_rxM17Data.addData(&data, 1U);
m_rxM17Data.addData(m_buffer + 3U, m_length - 3U);
}
break;
case MMDVM_M17_STREAM: {
if (m_trace)
CUtils::dump(1U, "RX M17 Stream Data", m_buffer, m_length);
unsigned char data = m_length - 2U;
m_rxM17Data.addData(&data, 1U);
data = TAG_DATA;
m_rxM17Data.addData(&data, 1U);
m_rxM17Data.addData(m_buffer + 3U, m_length - 3U);
}
break;
case MMDVM_M17_EOT: {
if (m_trace)
CUtils::dump(1U, "RX M17 EOT", m_buffer, m_length);
unsigned char data = 1U;
m_rxM17Data.addData(&data, 1U);
data = TAG_EOT;
m_rxM17Data.addData(&data, 1U);
}
break;
case MMDVM_M17_LOST: {
if (m_trace)
CUtils::dump(1U, "RX M17 Lost", m_buffer, m_length);
unsigned char data = 1U;
m_rxM17Data.addData(&data, 1U);
data = TAG_LOST;
m_rxM17Data.addData(&data, 1U);
}
break;
case MMDVM_FM_DATA: {
if (m_trace)
CUtils::dump(1U, "RX FM Data", m_buffer, m_length);
@ -795,7 +722,6 @@ void CModem::clock(unsigned int ms)
m_p25Space = 0U;
m_nxdnSpace = 0U;
m_m17Space = 0U;
m_pocsagSpace = 0U;
m_fmSpace = 0U;
m_ax25Space = 0U;
@ -812,8 +738,6 @@ void CModem::clock(unsigned int ms)
m_nxdnSpace = m_buffer[m_offset + 8U];
if (m_length > (m_offset + 9U))
m_pocsagSpace = m_buffer[m_offset + 9U];
if (m_length > (m_offset + 10U))
m_m17Space = m_buffer[m_offset + 10U];
}
break;
@ -842,7 +766,6 @@ void CModem::clock(unsigned int ms)
m_ysfSpace = m_buffer[m_offset + 6U];
m_p25Space = m_buffer[m_offset + 7U];
m_nxdnSpace = m_buffer[m_offset + 8U];
m_m17Space = m_buffer[m_offset + 9U];
m_fmSpace = m_buffer[m_offset + 10U];
m_pocsagSpace = m_buffer[m_offset + 11U];
m_ax25Space = m_buffer[m_offset + 12U];
@ -856,7 +779,6 @@ void CModem::clock(unsigned int ms)
m_ysfSpace = 0U;
m_p25Space = 0U;
m_nxdnSpace = 0U;
m_m17Space = 0U;
m_pocsagSpace = 0U;
m_fmSpace = 0U;
m_ax25Space = 0U;
@ -864,7 +786,7 @@ void CModem::clock(unsigned int ms)
}
m_inactivityTimer.start();
// LogMessage("status=%02X, tx=%d, space=%u,%u,%u,%u,%u,%u,%u,%u,%u,%u lockout=%d, cd=%d", m_buffer[m_offset + 2U], int(m_tx), m_dstarSpace, m_dmrSpace1, m_dmrSpace2, m_ysfSpace, m_p25Space, m_nxdnSpace, m_m17Space, m_pocsagSpace, m_fmSpace, m_ax25Space, int(m_lockout), int(m_cd));
// LogMessage("status=%02X, tx=%d, space=%u,%u,%u,%u,%u,%u,%u,%u,%u lockout=%d, cd=%d", m_buffer[m_offset + 2U], int(m_tx), m_dstarSpace, m_dmrSpace1, m_dmrSpace2, m_ysfSpace, m_p25Space, m_nxdnSpace, m_pocsagSpace, m_fmSpace, m_ax25Space, int(m_lockout), int(m_cd));
break;
case MMDVM_TRANSPARENT: {
@ -1042,34 +964,6 @@ void CModem::clock(unsigned int ms)
m_nxdnSpace--;
}
if (m_m17Space > 1U && !m_txM17Data.isEmpty()) {
unsigned char len = 0U;
m_txM17Data.getData(&len, 1U);
m_txM17Data.getData(m_buffer, len);
if (m_trace) {
switch (m_buffer[2U]) {
case MMDVM_M17_LINK_SETUP:
CUtils::dump(1U, "TX M17 Link Setup", m_buffer, len);
break;
case MMDVM_M17_STREAM:
CUtils::dump(1U, "TX M17 Stream Data", m_buffer, len);
break;
case MMDVM_M17_EOT:
CUtils::dump(1U, "TX M17 EOT", m_buffer, len);
break;
}
}
int ret = m_port->write(m_buffer, len);
if (ret != int(len))
LogWarning("Error when writing M17 data to the MMDVM");
m_playoutTimer.start();
m_m17Space--;
}
if (m_pocsagSpace > 1U && !m_txPOCSAGData.isEmpty()) {
unsigned char len = 0U;
m_txPOCSAGData.getData(&len, 1U);
@ -1245,20 +1139,6 @@ unsigned int CModem::readNXDNData(unsigned char* data)
return len;
}
unsigned int CModem::readM17Data(unsigned char* data)
{
assert(data != nullptr);
if (m_rxM17Data.isEmpty())
return 0U;
unsigned char len = 0U;
m_rxM17Data.getData(&len, 1U);
m_rxM17Data.getData(data, len);
return len;
}
unsigned int CModem::readFMData(unsigned char* data)
{
assert(data != nullptr);
@ -1506,47 +1386,6 @@ bool CModem::writeNXDNData(const unsigned char* data, unsigned int length)
return true;
}
bool CModem::hasM17Space() const
{
unsigned int space = m_txM17Data.freeSpace() / (M17_FRAME_LENGTH_BYTES + 4U);
return space > 1U;
}
bool CModem::writeM17Data(const unsigned char* data, unsigned int length)
{
assert(data != nullptr);
assert(length > 0U);
unsigned char buffer[130U];
buffer[0U] = MMDVM_FRAME_START;
buffer[1U] = length + 2U;
switch (data[0U]) {
case TAG_HEADER:
buffer[2U] = MMDVM_M17_LINK_SETUP;
::memcpy(buffer + 3U, data + 1U, length - 1U);
break;
case TAG_DATA:
buffer[2U] = MMDVM_M17_STREAM;
::memcpy(buffer + 3U, data + 1U, length - 1U);
break;
case TAG_EOT:
buffer[2U] = MMDVM_M17_EOT;
::memcpy(buffer + 3U, data + 1U, length - 1U);
break;
default:
return false;
}
unsigned char len = length + 2U;
m_txM17Data.addData(&len, 1U);
m_txM17Data.addData(buffer, len);
return true;
}
bool CModem::hasPOCSAGSpace() const
{
unsigned int space = m_txPOCSAGData.freeSpace() / (POCSAG_FRAME_LENGTH_BYTES + 4U);
@ -1811,30 +1650,6 @@ bool CModem::writeNXDNInfo(const char* source, bool group, unsigned int dest, co
return m_port->write(buffer, 31U) != 31;
}
bool CModem::writeM17Info(const char* source, const char* dest, const char* type)
{
assert(m_port != nullptr);
assert(source != nullptr);
assert(dest != nullptr);
assert(type != nullptr);
unsigned char buffer[40U];
buffer[0U] = MMDVM_FRAME_START;
buffer[1U] = 31U;
buffer[2U] = MMDVM_QSO_INFO;
buffer[3U] = MODE_M17;
::sprintf((char*)(buffer + 4U), "%9.9s", source);
::sprintf((char*)(buffer + 13U), "%9.9s", dest);
::memcpy(buffer + 22U, type, 1U);
return m_port->write(buffer, 23U) != 23;
}
bool CModem::writePOCSAGInfo(unsigned int ric, const std::string& message)
{
assert(m_port != nullptr);
@ -1945,11 +1760,6 @@ bool CModem::hasNXDN() const
return (m_capabilities1 & CAP1_NXDN) == CAP1_NXDN;
}
bool CModem::hasM17() const
{
return (m_capabilities1 & CAP1_M17) == CAP1_M17;
}
bool CModem::hasFM() const
{
return (m_capabilities1 & CAP1_FM) == CAP1_FM;
@ -2027,7 +1837,7 @@ bool CModem::readVersion()
switch (m_protocolVersion) {
case 1U:
LogInfo("MMDVM protocol version: 1, description: %.*s", m_length - 4U, m_buffer + 4U);
m_capabilities1 = CAP1_DSTAR | CAP1_DMR | CAP1_YSF | CAP1_P25 | CAP1_NXDN | CAP1_M17;
m_capabilities1 = CAP1_DSTAR | CAP1_DMR | CAP1_YSF | CAP1_P25 | CAP1_NXDN;
m_capabilities2 = CAP2_POCSAG;
return true;
@ -2061,8 +1871,6 @@ bool CModem::readVersion()
::strcat(modeText, " P25");
if (hasNXDN())
::strcat(modeText, " NXDN");
if (hasM17())
::strcat(modeText, " M17");
if (hasFM())
::strcat(modeText, " FM");
if (hasPOCSAG())
@ -2157,8 +1965,6 @@ bool CModem::setConfig1()
buffer[4U] |= 0x10U;
if (m_pocsagEnabled)
buffer[4U] |= 0x20U;
if (m_m17Enabled)
buffer[4U] |= 0x40U;
buffer[5U] = m_txDelay / 10U; // In 10ms units
@ -2194,9 +2000,9 @@ bool CModem::setConfig1()
buffer[23U] = (unsigned char)m_nxdnTXHang;
buffer[24U] = (unsigned char)(m_m17TXLevel * 2.55F + 0.5F);
buffer[24U] = 0x00U;
buffer[25U] = (unsigned char)m_m17TXHang;
buffer[25U] = 0x00U;
// CUtils::dump(1U, "Written", buffer, 26U);
@ -2272,8 +2078,6 @@ bool CModem::setConfig2()
buffer[4U] |= 0x10U;
if (m_fmEnabled)
buffer[4U] |= 0x20U;
if (m_m17Enabled)
buffer[4U] |= 0x40U;
buffer[5U] = 0x00U;
if (m_pocsagEnabled)
@ -2296,7 +2100,7 @@ bool CModem::setConfig2()
buffer[14U] = (unsigned char)(m_ysfTXLevel * 2.55F + 0.5F);
buffer[15U] = (unsigned char)(m_p25TXLevel * 2.55F + 0.5F);
buffer[16U] = (unsigned char)(m_nxdnTXLevel * 2.55F + 0.5F);
buffer[17U] = (unsigned char)(m_m17TXLevel * 2.55F + 0.5F);
buffer[17U] = 0x00U;
buffer[18U] = (unsigned char)(m_pocsagTXLevel * 2.55F + 0.5F);
buffer[19U] = (unsigned char)(m_fmTXLevel * 2.55F + 0.5F);
buffer[20U] = (unsigned char)(m_ax25TXLevel * 2.55F + 0.5F);
@ -2306,7 +2110,7 @@ bool CModem::setConfig2()
buffer[23U] = (unsigned char)m_ysfTXHang;
buffer[24U] = (unsigned char)m_p25TXHang;
buffer[25U] = (unsigned char)m_nxdnTXHang;
buffer[26U] = (unsigned char)m_m17TXHang;
buffer[26U] = 0x00U;
buffer[27U] = 0x00U;
buffer[28U] = 0x00U;

16
Modem.h
View file

@ -47,13 +47,12 @@ public:
void setPort(IModemPort* port);
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 m17Enabled, bool pocsagEnabled, bool fmEnabled, bool ax25Enabled);
void setLevels(float rxLevel, float cwIdTXLevel, float dstarTXLevel, float dmrTXLevel, float ysfTXLevel, float p25TXLevel, float nxdnTXLevel, float m17TXLevel, float pocsagLevel, float fmTXLevel, float ax25TXLevel);
void setModeParams(bool dstarEnabled, bool dmrEnabled, bool ysfEnabled, bool p25Enabled, bool nxdnEnabled, bool pocsagEnabled, bool fmEnabled, bool ax25Enabled);
void setLevels(float rxLevel, float cwIdTXLevel, float dstarTXLevel, float dmrTXLevel, float ysfTXLevel, float p25TXLevel, float nxdnTXLevel, float pocsagLevel, float fmTXLevel, float ax25TXLevel);
void setDMRParams(unsigned int colorCode);
void setYSFParams(bool loDev, unsigned int txHang);
void setP25Params(unsigned int txHang);
void setNXDNParams(unsigned int txHang);
void setM17Params(unsigned int txHang);
void setAX25Params(int rxTwist, unsigned int txDelay, unsigned int slotTime, unsigned int pPersist);
void setTransparentDataParams(unsigned int sendFrameType);
@ -69,7 +68,6 @@ public:
bool hasYSF() const;
bool hasP25() const;
bool hasNXDN() const;
bool hasM17() const;
bool hasPOCSAG() const;
bool hasFM() const;
bool hasAX25() const;
@ -82,7 +80,6 @@ public:
unsigned int readYSFData(unsigned char* data);
unsigned int readP25Data(unsigned char* data);
unsigned int readNXDNData(unsigned char* data);
unsigned int readM17Data(unsigned char* data);
unsigned int readFMData(unsigned char* data);
unsigned int readAX25Data(unsigned char* data);
@ -92,7 +89,6 @@ public:
bool hasYSFSpace() const;
bool hasP25Space() const;
bool hasNXDNSpace() const;
bool hasM17Space() const;
bool hasPOCSAGSpace() const;
unsigned int getFMSpace() const;
bool hasAX25Space() const;
@ -110,7 +106,6 @@ 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 writeM17Data(const unsigned char* data, unsigned int length);
bool writePOCSAGData(const unsigned char* data, unsigned int length);
bool writeFMData(const unsigned char* data, unsigned int length);
bool writeAX25Data(const unsigned char* data, unsigned int length);
@ -120,7 +115,6 @@ public:
bool writeYSFInfo(const char* source, const char* dest, unsigned char dgid, const char* type, const char* origin);
bool writeP25Info(const char* source, bool group, unsigned int dest, const char* type);
bool writeNXDNInfo(const char* source, bool group, unsigned int dest, const char* type);
bool writeM17Info(const char* source, const char* dest, const char* type);
bool writePOCSAGInfo(unsigned int ric, const std::string& message);
bool writeIPInfo(const std::string& address);
@ -152,7 +146,6 @@ private:
unsigned int m_ysfTXHang;
unsigned int m_p25TXHang;
unsigned int m_nxdnTXHang;
unsigned int m_m17TXHang;
bool m_duplex;
bool m_rxInvert;
bool m_txInvert;
@ -166,7 +159,6 @@ private:
float m_ysfTXLevel;
float m_p25TXLevel;
float m_nxdnTXLevel;
float m_m17TXLevel;
float m_pocsagTXLevel;
float m_fmTXLevel;
float m_ax25TXLevel;
@ -182,7 +174,6 @@ private:
bool m_ysfEnabled;
bool m_p25Enabled;
bool m_nxdnEnabled;
bool m_m17Enabled;
bool m_pocsagEnabled;
bool m_fmEnabled;
bool m_ax25Enabled;
@ -206,8 +197,6 @@ private:
CRingBuffer<unsigned char> m_txP25Data;
CRingBuffer<unsigned char> m_rxNXDNData;
CRingBuffer<unsigned char> m_txNXDNData;
CRingBuffer<unsigned char> m_rxM17Data;
CRingBuffer<unsigned char> m_txM17Data;
CRingBuffer<unsigned char> m_txPOCSAGData;
CRingBuffer<unsigned char> m_rxFMData;
CRingBuffer<unsigned char> m_txFMData;
@ -227,7 +216,6 @@ private:
unsigned int m_ysfSpace;
unsigned int m_p25Space;
unsigned int m_nxdnSpace;
unsigned int m_m17Space;
unsigned int m_pocsagSpace;
unsigned int m_fmSpace;
unsigned int m_ax25Space;

View file

@ -36,8 +36,6 @@ const unsigned int P25_RSSI_COUNT = 7U; // 7 * 180ms = 1260ms
const unsigned int P25_BER_COUNT = 7U; // 7 * 180ms = 1260ms
const unsigned int NXDN_RSSI_COUNT = 28U; // 28 * 40ms = 1120ms
const unsigned int NXDN_BER_COUNT = 28U; // 28 * 40ms = 1120ms
const unsigned int M17_RSSI_COUNT = 28U; // 28 * 40ms = 1120ms
const unsigned int M17_BER_COUNT = 28U; // 28 * 40ms = 1120ms
#define LAYOUT_COMPAT_MASK (7 << 0) // compatibility for old setting
#define LAYOUT_TA_ENABLE (1 << 4) // enable Talker Alias (TA) display
@ -882,79 +880,6 @@ void CNextion::clearNXDNInt()
sendCommand("t3.txt=\"\"");
}
void CNextion::writeM17Int(const char* source, const char* dest, const char* type)
{
assert(source != nullptr);
assert(dest != nullptr);
assert(type != nullptr);
if (m_mode != MODE_M17) {
sendCommand("page M17");
sendCommandAction(8U);
}
char text[30U];
if (m_brightness > 0U) {
::sprintf(text, "dim=%u", m_brightness);
sendCommand(text);
}
::sprintf(text, "t0.txt=\"%s %.10s\"", type, source);
sendCommand(text);
sendCommandAction(142U);
::sprintf(text, "t1.txt=\"%s\"", dest);
sendCommand(text);
sendCommandAction(143U);
m_clockDisplayTimer.stop();
m_mode = MODE_M17;
m_rssiAccum1 = 0U;
m_berAccum1 = 0.0F;
m_rssiCount1 = 0U;
m_berCount1 = 0U;
}
void CNextion::writeM17RSSIInt(unsigned char rssi)
{
m_rssiAccum1 += rssi;
m_rssiCount1++;
if (m_rssiCount1 == M17_RSSI_COUNT) {
char text[25U];
::sprintf(text, "t2.txt=\"-%udBm\"", m_rssiAccum1 / M17_RSSI_COUNT);
sendCommand(text);
sendCommandAction(144U);
m_rssiAccum1 = 0U;
m_rssiCount1 = 0U;
}
}
void CNextion::writeM17BERInt(float ber)
{
m_berAccum1 += ber;
m_berCount1++;
if (m_berCount1 == M17_BER_COUNT) {
char text[25U];
::sprintf(text, "t3.txt=\"%.1f%%\"", m_berAccum1 / float(M17_BER_COUNT));
sendCommand(text);
sendCommandAction(145U);
m_berAccum1 = 0.0F;
m_berCount1 = 0U;
}
}
void CNextion::clearM17Int()
{
sendCommand("t0.txt=\"Listening\"");
sendCommandAction(141U);
sendCommand("t1.txt=\"\"");
sendCommand("t2.txt=\"\"");
sendCommand("t3.txt=\"\"");
}
void CNextion::writePOCSAGInt(uint32_t ric, const std::string& message)
{
if (m_mode != MODE_POCSAG) {

View file

@ -1,5 +1,5 @@
/*
* Copyright (C) 2016,2017,2018,2020,2023,2024 by Jonathan Naylor G4KLX
* Copyright (C) 2016,2017,2018,2020,2023,2024,2025 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
@ -71,11 +71,6 @@ protected:
virtual void writeNXDNBERInt(float ber);
virtual void clearNXDNInt();
virtual void writeM17Int(const char* source, const char* dest, const char* type);
virtual void writeM17RSSIInt(unsigned char rssi);
virtual void writeM17BERInt(float ber);
virtual void clearM17Int();
virtual void writePOCSAGInt(uint32_t ric, const std::string& message);
virtual void clearPOCSAGInt();

View file

@ -1,5 +1,5 @@
/*
* Copyright (C) 2016,2018,2020 by Jonathan Naylor G4KLX
* Copyright (C) 2016,2018,2020,2025 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
@ -134,20 +134,6 @@ void CNullDisplay::clearNXDNInt()
#endif
}
void CNullDisplay::writeM17Int(const char* source, const char* dest, const char* type)
{
#if defined(RASPBERRY_PI)
::digitalWrite(LED_STATUS, 1);
#endif
}
void CNullDisplay::clearM17Int()
{
#if defined(RASPBERRY_PI)
::digitalWrite(LED_STATUS, 0);
#endif
}
void CNullDisplay::writePOCSAGInt(uint32_t ric, const std::string& message)
{
#if defined(RASPBERRY_PI)

View file

@ -55,9 +55,6 @@ protected:
virtual void writeNXDNInt(const char* source, bool group, unsigned int dest, const char* type);
virtual void clearNXDNInt();
virtual void writeM17Int(const char* source, const char* dest, const char* type);
virtual void clearM17Int();
virtual void writePOCSAGInt(uint32_t ric, const std::string& message);
virtual void clearPOCSAGInt();

View file

@ -1,5 +1,5 @@
/*
* Copyright (C) 2016,2017,2018,2020,2023 by Jonathan Naylor G4KLX
* Copyright (C) 2016,2017,2018,2020,2023,2025 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
@ -148,27 +148,6 @@ const unsigned char logo_NXDN_bmp[] =
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
};
// Logo M17_sm, 128x16px
const unsigned char logo_M17_bmp[] =
{
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x62, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x67, 0x37, 0xf0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe7, 0x33, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xef, 0x70, 0xe0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0xee, 0xf0, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0xff, 0xf1, 0xc0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x7f, 0x31, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x77, 0x33, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x77, 0x37, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0e, 0x67, 0x36, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x60, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
};
// Logo POCASG/DAPNET, 128x16px
const unsigned char logo_POCSAG_bmp[] =
{
@ -654,40 +633,6 @@ void COLED::clearNXDNInt()
m_display.display();
}
void COLED::writeM17Int(const char* source, const char* dest, const char* type)
{
m_mode = MODE_M17;
m_display.clearDisplay();
m_display.fillRect(0, OLED_LINE2, m_display.width(), m_display.height(), BLACK);
m_display.setCursor(0, OLED_LINE3);
m_display.printf("from: %s %s", type, source);
m_display.setCursor(0, OLED_LINE4);
m_display.printf("to: %s", dest);
m_display.setCursor(0, OLED_LINE6);
m_display.printf("%s", m_ipaddress.c_str());
OLED_statusbar();
m_display.display();
}
void COLED::clearM17Int()
{
m_display.fillRect(0, OLED_LINE2, m_display.width(), m_display.height(), BLACK);
m_display.setCursor(37, OLED_LINE4);
m_display.print("Standby");
m_display.setCursor(0, OLED_LINE6);
m_display.printf("%s", m_ipaddress.c_str());
m_display.display();
}
void COLED::writePOCSAGInt(uint32_t ric, const std::string& message)
{
int pos;
@ -838,8 +783,6 @@ void COLED::OLED_statusbar()
m_display.drawBitmap(0, 0, logo_P25_bmp, 128, 16, WHITE);
else if (m_mode == MODE_NXDN)
m_display.drawBitmap(0, 0, logo_NXDN_bmp, 128, 16, WHITE);
else if (m_mode == MODE_M17)
m_display.drawBitmap(0, 0, logo_M17_bmp, 128, 16, WHITE);
else if (m_mode == MODE_POCSAG)
m_display.drawBitmap(0, 0, logo_POCSAG_bmp, 128, 16, WHITE);
else if (m_displayLogoScreensaver)
@ -848,4 +791,3 @@ void COLED::OLED_statusbar()
if (m_displayScroll)
m_display.startscrollleft(0x00, 0x01);
}

5
OLED.h
View file

@ -1,5 +1,5 @@
/*
* Copyright (C) 2016,2017,2018,2020,2023 by Jonathan Naylor G4KLX
* Copyright (C) 2016,2017,2018,2020,2023,2025 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
@ -76,9 +76,6 @@ protected:
virtual int writeNXDNIntEx(const CUserDBentry& source, bool group, unsigned int dest, const char* type);
virtual void clearNXDNInt();
virtual void writeM17Int(const char* source, const char* dest, const char* type);
virtual void clearM17Int();
virtual void writePOCSAGInt(uint32_t ric, const std::string& message);
virtual void clearPOCSAGInt();

View file

@ -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, System Fusion, M17,
the other. It supports D-Star, DMR, P25 Phase 1, NXDN, System Fusion,
POCSAG, FM, and AX.25 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
@ -8,8 +8,7 @@ connects to the DMR Gateway to allow for connection to multiple DMR networks,
or a single network directly. 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. On M17 it uses the M17 Gateway to access the M17 reflector system.
It uses the DAPNET Gateway to access DAPNET to receive
NXCore talk groups. It uses the DAPNET Gateway to access DAPNET to receive
paging messages. Finally it uses the FM Gateway to interface to existing FM
networks.

View file

@ -102,8 +102,6 @@ REMOTE_COMMAND CRemoteControl::getCommand()
m_command = REMOTE_COMMAND::MODE_P25;
else if (m_args.at(1U) == "nxdn")
m_command = REMOTE_COMMAND::MODE_NXDN;
else if (m_args.at(1U) == "m17")
m_command = REMOTE_COMMAND::MODE_M17;
else
replyStr = "KO";
} else if (m_args.at(0U) == "enable" && m_args.size() >= ENABLE_ARGS) {
@ -117,8 +115,6 @@ REMOTE_COMMAND CRemoteControl::getCommand()
m_command = REMOTE_COMMAND::ENABLE_P25;
else if (m_args.at(1U) == "nxdn")
m_command = REMOTE_COMMAND::ENABLE_NXDN;
else if (m_args.at(1U) == "m17")
m_command = REMOTE_COMMAND::ENABLE_M17;
else if (m_args.at(1U) == "fm")
m_command = REMOTE_COMMAND::ENABLE_FM;
else if (m_args.at(1U) == "ax25")
@ -136,8 +132,6 @@ REMOTE_COMMAND CRemoteControl::getCommand()
m_command = REMOTE_COMMAND::DISABLE_P25;
else if (m_args.at(1U) == "nxdn")
m_command = REMOTE_COMMAND::DISABLE_NXDN;
else if (m_args.at(1U) == "m17")
m_command = REMOTE_COMMAND::DISABLE_M17;
else if (m_args.at(1U) == "fm")
m_command = REMOTE_COMMAND::DISABLE_FM;
else if (m_args.at(1U) == "ax25")
@ -208,7 +202,6 @@ unsigned int CRemoteControl::getArgCount() const
case REMOTE_COMMAND::MODE_YSF:
case REMOTE_COMMAND::MODE_P25:
case REMOTE_COMMAND::MODE_NXDN:
case REMOTE_COMMAND::MODE_M17:
return (unsigned int)m_args.size() - SET_MODE_ARGS;
case REMOTE_COMMAND::PAGE:
case REMOTE_COMMAND::PAGE_BCD:
@ -232,7 +225,6 @@ std::string CRemoteControl::getArgString(unsigned int n) const
case REMOTE_COMMAND::MODE_YSF:
case REMOTE_COMMAND::MODE_P25:
case REMOTE_COMMAND::MODE_NXDN:
case REMOTE_COMMAND::MODE_M17:
n += SET_MODE_ARGS;
break;
case REMOTE_COMMAND::PAGE:

View file

@ -35,14 +35,12 @@ enum class REMOTE_COMMAND {
MODE_YSF,
MODE_P25,
MODE_NXDN,
MODE_M17,
MODE_FM,
ENABLE_DSTAR,
ENABLE_DMR,
ENABLE_YSF,
ENABLE_P25,
ENABLE_NXDN,
ENABLE_M17,
ENABLE_FM,
ENABLE_AX25,
DISABLE_DSTAR,
@ -50,7 +48,6 @@ enum class REMOTE_COMMAND {
DISABLE_YSF,
DISABLE_P25,
DISABLE_NXDN,
DISABLE_M17,
DISABLE_FM,
DISABLE_AX25,
PAGE,

View file

@ -23,7 +23,6 @@
#include "YSFDefines.h"
#include "P25Defines.h"
#include "NXDNDefines.h"
#include "M17Defines.h"
#include <cstdio>
#include <cassert>
@ -84,25 +83,3 @@ void CSync::addNXDNSync(unsigned char* data)
for (unsigned int i = 0U; i < NXDN_FSW_BYTES_LENGTH; i++)
data[i] = (data[i] & ~NXDN_FSW_BYTES_MASK[i]) | NXDN_FSW_BYTES[i];
}
void CSync::addM17LinkSetupSync(unsigned char* data)
{
assert(data != nullptr);
::memcpy(data, M17_LINK_SETUP_SYNC_BYTES, M17_SYNC_LENGTH_BYTES);
}
void CSync::addM17StreamSync(unsigned char* data)
{
assert(data != nullptr);
::memcpy(data, M17_STREAM_SYNC_BYTES, M17_SYNC_LENGTH_BYTES);
}
void CSync::addM17EOTSync(unsigned char* data)
{
assert(data != nullptr);
::memcpy(data, M17_EOT_SYNC_BYTES, M17_SYNC_LENGTH_BYTES);
}

6
Sync.h
View file

@ -1,5 +1,5 @@
/*
* Copyright (C) 2015,2016,2018,2020,2021 by Jonathan Naylor G4KLX
* Copyright (C) 2015,2016,2018,2020,2021,2025 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
@ -33,10 +33,6 @@ public:
static void addNXDNSync(unsigned char* data);
static void addM17LinkSetupSync(unsigned char* data);
static void addM17StreamSync(unsigned char* data);
static void addM17EOTSync(unsigned char* data);
private:
};

View file

@ -101,7 +101,6 @@ static const struct layoutdef Layout[] = {
#define STR_DSTAR "D-STAR"
#define STR_MMDVM "MMDVM"
#define STR_NXDN "NXDN"
#define STR_M17 "M17"
#define STR_P25 "P25"
#define STR_YSF "SystemFusion"
@ -375,29 +374,6 @@ void CTFTSurenoo::clearNXDNInt()
clearDStarInt();
}
void CTFTSurenoo::writeM17Int(const char* source, const char* dest, const char* type)
{
assert(source != nullptr);
assert(dest != nullptr);
assert(type != nullptr);
if (m_mode != MODE_M17)
setModeLine(STR_M17);
::snprintf(m_temp, sizeof(m_temp), "%s %s", type, source);
setStatusLine(statusLineNo(0), m_temp);
::snprintf(m_temp, sizeof(m_temp), "%s", dest);
setStatusLine(statusLineNo(1), m_temp);
m_mode = MODE_M17;
}
void CTFTSurenoo::clearM17Int()
{
clearDStarInt();
}
void CTFTSurenoo::writePOCSAGInt(uint32_t ric, const std::string& message)
{
setStatusLine(statusLineNo(1), "POCSAG TX");

View file

@ -1,6 +1,6 @@
/*
* Copyright (C) 2019 by SASANO Takayoshi JG1UAA
* Copyright (C) 2015,2016,2018,2020 by Jonathan Naylor G4KLX
* Copyright (C) 2015,2016,2018,2020,2025 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
@ -61,9 +61,6 @@ protected:
virtual int writeNXDNIntEx(const CUserDBentry& source, bool group, unsigned int dest, const char* type);
virtual void clearNXDNInt();
virtual void writeM17Int(const char* source, const char* dest, const char* type);
virtual void clearM17Int();
virtual void writePOCSAGInt(uint32_t ric, const std::string& message);
virtual void clearPOCSAGInt();

View file

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