Revert "Merge branch 'M17_AX25_FM'"

This reverts commit e1427e3e37, reversing
changes made to bcdba292eb.
This commit is contained in:
Jonathan Naylor 2020-12-15 15:52:27 +00:00
parent e1427e3e37
commit 135fd04e0d
115 changed files with 4808 additions and 9583 deletions

View File

@ -1,252 +0,0 @@
/*
* Copyright (C) 2020 Jonathan Naylor, G4KLX
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include "AX25Control.h"
#include "AX25Defines.h"
#include "Utils.h"
#include "Log.h"
#include <cstdio>
#include <cassert>
#include <cstring>
#include <ctime>
// #define DUMP_AX25
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])
CAX25Control::CAX25Control(CAX25Network* network, bool trace) :
m_network(network),
m_trace(trace),
m_enabled(true),
m_fp(NULL)
{
}
CAX25Control::~CAX25Control()
{
}
bool CAX25Control::writeModem(unsigned char *data, unsigned int len)
{
assert(data != NULL);
if (!m_enabled)
return false;
if (m_trace)
decode(data, len);
CUtils::dump(1U, "AX.25 received packet", data, len);
if (m_network == NULL)
return true;
return m_network->write(data, len);
}
unsigned int CAX25Control::readModem(unsigned char* data)
{
assert(data != NULL);
if (m_network == NULL)
return 0U;
if (!m_enabled)
return 0U;
unsigned int length = m_network->read(data, 500U);
if (length > 0U)
CUtils::dump(1U, "AX.25 transmitted packet", data, length);
return length;
}
bool CAX25Control::openFile()
{
if (m_fp != NULL)
return true;
time_t t;
::time(&t);
struct tm* tm = ::localtime(&t);
char name[100U];
::sprintf(name, "AX25_%04d%02d%02d_%02d%02d%02d.ambe", tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec);
m_fp = ::fopen(name, "wb");
if (m_fp == NULL)
return false;
::fwrite("AX25", 1U, 4U, m_fp);
return true;
}
bool CAX25Control::writeFile(const unsigned char* data, unsigned int length)
{
if (m_fp == NULL)
return false;
::fwrite(&length, 1U, sizeof(unsigned int), m_fp);
::fwrite(data, 1U, length, m_fp);
return true;
}
void CAX25Control::closeFile()
{
if (m_fp != NULL) {
::fclose(m_fp);
m_fp = NULL;
}
}
void CAX25Control::enable(bool enabled)
{
m_enabled = enabled;
}
void CAX25Control::decode(const unsigned char* data, unsigned int length)
{
assert(data != NULL);
assert(length >= 15U);
std::string text;
bool more = decodeAddress(data + 7U, text);
text += '>';
decodeAddress(data + 0U, text);
unsigned int n = 14U;
while (more && n < length) {
text += ',';
more = decodeAddress(data + n, text, true);
n += 7U;
}
text += ' ';
if ((data[n] & 0x01U) == 0x00U) {
// I frame
char t[20U];
::sprintf(t, "<I S%u R%u>", (data[n] >> 1) & 0x07U, (data[n] >> 5) & 0x07U);
text += t;
} else {
if ((data[n] & 0x02U) == 0x00U) {
// S frame
char t[20U];
switch (data[n] & 0x0FU) {
case 0x01U:
sprintf(t, "<RR R%u>", (data[n] >> 5) & 0x07U);
break;
case 0x05U:
sprintf(t, "<RNR R%u>", (data[n] >> 5) & 0x07U);
break;
case 0x09U:
sprintf(t, "<REJ R%u>", (data[n] >> 5) & 0x07U);
break;
case 0x0DU:
sprintf(t, "<SREJ R%u>", (data[n] >> 5) & 0x07U);
break;
default:
sprintf(t, "<Unknown R%u>", (data[n] >> 5) & 0x07U);
break;
}
text += t;
LogMessage("AX.25, %s", text.c_str());
return;
} else {
// U frame
switch (data[n] & 0xEFU) {
case 0x6FU:
text += "<SABME>";
break;
case 0x2FU:
text += "<SABM>";
break;
case 0x43U:
text += "<DISC>";
break;
case 0x0FU:
text += "<DM>";
break;
case 0x63U:
text += "<UA>";
break;
case 0x87U:
text += "<FRMR>";
break;
case 0x03U:
text += "<UI>";
break;
case 0xAFU:
text += "<XID>";
break;
case 0xE3U:
text += "<TEST>";
break;
default:
text += "<Unknown>";
break;
}
if ((data[n] & 0xEFU) != 0x03U) {
LogMessage("AX.25, %s", text.c_str());
return;
}
}
}
n += 2U;
LogMessage("AX.25, %s %.*s", text.c_str(), length - n, data + n);
}
bool CAX25Control::decodeAddress(const unsigned char* data, std::string& text, bool isDigi) const
{
assert(data != NULL);
for (unsigned int i = 0U; i < 6U; i++) {
char c = data[i] >> 1;
if (c != ' ')
text += c;
}
unsigned char ssid = (data[6U] >> 1) & 0x0FU;
if (ssid > 0U) {
text += '-';
if (ssid >= 10U) {
text += '1';
text += '0' + ssid - 10U;
}
else {
text += '0' + ssid;
}
}
if (isDigi) {
if ((data[6U] & 0x80U) == 0x80U)
text += '*';
}
return (data[6U] & 0x01U) == 0x00U;
}

View File

@ -1,50 +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(AX25Control_H)
#define AX25Control_H
#include "AX25Network.h"
#include <string>
class CAX25Control {
public:
CAX25Control(CAX25Network* network, bool trace);
~CAX25Control();
bool writeModem(unsigned char* data, unsigned int len);
unsigned int readModem(unsigned char* data);
void enable(bool enabled);
private:
CAX25Network* m_network;
bool m_trace;
bool m_enabled;
FILE* m_fp;
void decode(const unsigned char* data, unsigned int length);
bool decodeAddress(const unsigned char* data, std::string& text, bool isDigi = false) const;
bool openFile();
bool writeFile(const unsigned char* data, unsigned int length);
void closeFile();
};
#endif

View File

@ -1,39 +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(AX25Defines_H)
#define AX25Defines_H
const unsigned int AX25_CALLSIGN_TEXT_LENGTH = 6U;
const unsigned int AX25_SSID_LENGTH = 1U;
const unsigned int AX25_CALLSIGN_LENGTH = 7U;
const unsigned int AX25_MAX_DIGIPEATERS = 6U;
const unsigned char AX25_PID_NOL3 = 0xF0U;
const unsigned int AX25_MAX_FRAME_LENGTH_BYTES = 330U; // Callsign (7) + Callsign (7) + 8 Digipeaters (56) +
// Control (1) + PID (1) + Data (256) + Checksum (2)
const unsigned char AX25_KISS_DATA = 0x00U;
const unsigned char AX25_FEND = 0xC0U;
const unsigned char AX25_FESC = 0xDBU;
const unsigned char AX25_TFEND = 0xDCU;
const unsigned char AX25_TFESC = 0xDDU;
#endif

View File

@ -1,183 +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.
*/
#include "AX25Network.h"
#include "AX25Defines.h"
#include "Defines.h"
#include "Utils.h"
#include "Log.h"
#include <cstdio>
#include <cassert>
#include <cstring>
const unsigned int BUFFER_LENGTH = 500U;
CAX25Network::CAX25Network(const std::string& port, unsigned int speed, bool debug) :
m_serial(port, speed, false),
m_txData(NULL),
m_rxData(NULL),
m_rxLength(0U),
m_rxLastChar(0U),
m_debug(debug),
m_enabled(false)
{
assert(!port.empty());
assert(speed > 0U);
m_txData = new unsigned char[BUFFER_LENGTH];
m_rxData = new unsigned char[BUFFER_LENGTH];
}
CAX25Network::~CAX25Network()
{
delete[] m_txData;
delete[] m_rxData;
}
bool CAX25Network::open()
{
LogMessage("Opening AX25 network connection");
return m_serial.open();
}
bool CAX25Network::write(const unsigned char* data, unsigned int length)
{
assert(data != NULL);
if (!m_enabled)
return true;
unsigned int txLength = 0U;
m_txData[txLength++] = AX25_FEND;
m_txData[txLength++] = AX25_KISS_DATA;
for (unsigned int i = 0U; i < length; i++) {
unsigned char c = data[i];
switch (c) {
case AX25_FEND:
m_txData[txLength++] = AX25_FESC;
m_txData[txLength++] = AX25_TFEND;
break;
case AX25_FESC:
m_txData[txLength++] = AX25_FESC;
m_txData[txLength++] = AX25_TFESC;
break;
default:
m_txData[txLength++] = c;
break;
}
}
m_txData[txLength++] = AX25_FEND;
if (m_debug)
CUtils::dump(1U, "AX25 Network Data Sent", m_txData, txLength);
return m_serial.write(m_txData, txLength);
}
unsigned int CAX25Network::read(unsigned char* data, unsigned int length)
{
assert(data != NULL);
bool complete = false;
unsigned char c;
while (m_serial.read(&c, 1U) > 0) {
if (m_rxLength == 0U && c == AX25_FEND)
m_rxData[m_rxLength++] = c;
else if (m_rxLength > 0U)
m_rxData[m_rxLength++] = c;
if (m_rxLength > 1U && c == AX25_FEND) {
complete = true;
break;
}
}
if (!m_enabled)
return 0U;
if (!complete)
return 0U;
if (m_rxLength == 0U)
return 0U;
if (m_rxData[1U] != AX25_KISS_DATA) {
m_rxLength = 0U;
return 0U;
}
complete = false;
unsigned int dataLen = 0U;
for (unsigned int i = 2U; i < m_rxLength; i++) {
unsigned char c = m_rxData[i];
if (c == AX25_FEND) {
complete = true;
break;
} else if (c == AX25_TFEND && m_rxLastChar == AX25_FESC) {
data[dataLen++] = AX25_FEND;
} else if (c == AX25_TFESC && m_rxLastChar == AX25_FESC) {
data[dataLen++] = AX25_FESC;
} else {
data[dataLen++] = c;
}
m_rxLastChar = c;
}
if (!complete)
return 0U;
if (m_debug)
CUtils::dump(1U, "AX25 Network Data Received", m_rxData, m_rxLength);
m_rxLength = 0U;
m_rxLastChar = 0U;
return dataLen;
}
void CAX25Network::reset()
{
}
void CAX25Network::close()
{
m_serial.close();
LogMessage("Closing AX25 network connection");
}
void CAX25Network::enable(bool enabled)
{
m_enabled = enabled;
if (enabled != m_enabled) {
m_rxLastChar = 0U;
m_rxLength = 0U;
}
}

View File

@ -1,62 +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.
*/
#ifndef AX25Network_H
#define AX25Network_H
#if defined(_WIN32) || defined(_WIN64)
#include "SerialController.h"
#else
#include "PseudoTTYController.h"
#endif
#include <cstdint>
#include <string>
class CAX25Network {
public:
CAX25Network(const std::string& port, unsigned int speed, bool debug);
~CAX25Network();
bool open();
void enable(bool enabled);
bool write(const unsigned char* data, unsigned int length);
unsigned int read(unsigned char* data, unsigned int length);
void reset();
void close();
private:
#if defined(_WIN32) || defined(_WIN64)
CSerialController m_serial;
#else
CPseudoTTYController m_serial;
#endif
unsigned char* m_txData;
unsigned char* m_rxData;
unsigned int m_rxLength;
unsigned char m_rxLastChar;
bool m_debug;
bool m_enabled;
};
#endif

View File

@ -21,7 +21,7 @@
static bool networkInfoInitialized = false;
static unsigned char passCounter = 0;
CCASTInfo::CCASTInfo(IModem* modem) :
CCASTInfo::CCASTInfo(CModem* modem) :
CDisplay(),
m_modem(modem),
m_ipaddress()
@ -130,16 +130,6 @@ void CCASTInfo::clearNXDNInt()
{
}
void CCASTInfo::writeM17Int(const char* source, const char* dest, const char* type)
{
if (m_modem != NULL)
m_modem->writeM17Info(source, dest, type);
}
void CCASTInfo::clearM17Int()
{
}
void CCASTInfo::writePOCSAGInt(uint32_t ric, const std::string& message)
{
if (m_modem != NULL)

View File

@ -28,7 +28,7 @@
class CCASTInfo : public CDisplay
{
public:
CCASTInfo(IModem* modem);
CCASTInfo(CModem* modem);
virtual ~CCASTInfo();
virtual bool open();
@ -57,9 +57,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();
@ -67,7 +64,7 @@ protected:
virtual void clearCWInt();
private:
IModem* m_modem;
CModem* m_modem;
std::string m_ipaddress;
};

1705
Conf.cpp

File diff suppressed because it is too large Load Diff

96
Conf.h
View File

@ -72,7 +72,6 @@ public:
// The Modem section
std::string getModemPort() const;
std::string getModemProtocol() const;
unsigned int getModemSpeed() const;
unsigned int getModemAddress() const;
bool getModemRXInvert() const;
bool getModemTXInvert() const;
@ -91,10 +90,8 @@ public:
float getModemYSFTXLevel() const;
float getModemP25TXLevel() const;
float getModemNXDNTXLevel() const;
float getModemM17TXLevel() const;
float getModemPOCSAGTXLevel() const;
float getModemFMTXLevel() const;
float getModemAX25TXLevel() const;
std::string getModemRSSIMappingFile() const;
bool getModemUseCOSAsLockout() const;
bool getModemTrace() const;
@ -107,6 +104,10 @@ public:
unsigned int getTransparentLocalPort() const;
unsigned int getTransparentSendFrameType() const;
// The UMP section
bool getUMPEnabled() const;
std::string getUMPPort() const;
// The D-Star section
bool getDStarEnabled() const;
std::string getDStarModule() const;
@ -167,26 +168,10 @@ public:
unsigned int getNXDNTXHang() const;
unsigned int getNXDNModeHang() const;
// The M17 section
bool getM17Enabled() const;
unsigned int getM17ColorCode() 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;
// The AX.25 section
bool getAX25Enabled() const;
unsigned int getAX25TXDelay() const;
int getAX25RXTwist() const;
unsigned int getAX25SlotTime() const;
unsigned int getAX25PPersist() const;
bool getAX25Trace() const;
// The FM Section
bool getFMEnabled() const;
std::string getFMCallsign() const;
@ -216,13 +201,9 @@ public:
unsigned int getFMHangTime() const;
unsigned int getFMAccessMode() const;
bool getFMCOSInvert() const;
bool getFMNoiseSquelch() const;
unsigned int getFMSquelchHighThreshold() const;
unsigned int getFMSquelchLowThreshold() const;
unsigned int getFMRFAudioBoost() const;
float getFMMaxDevLevel() const;
unsigned int getFMExtAudioBoost() const;
unsigned int getFMModeHang() const;
// The D-Star Network section
bool getDStarNetworkEnabled() const;
@ -273,14 +254,6 @@ public:
unsigned int getNXDNNetworkModeHang() const;
bool getNXDNNetworkDebug() const;
// The M17 Network section
bool getM17NetworkEnabled() const;
std::string getM17GatewayAddress() const;
unsigned int getM17GatewayPort() const;
unsigned int getM17LocalPort() const;
unsigned int getM17NetworkModeHang() const;
bool getM17NetworkDebug() const;
// The POCSAG Network section
bool getPOCSAGNetworkEnabled() const;
std::string getPOCSAGGatewayAddress() const;
@ -290,22 +263,6 @@ public:
unsigned int getPOCSAGNetworkModeHang() const;
bool getPOCSAGNetworkDebug() const;
// The FM Network section
bool getFMNetworkEnabled() const;
std::string getFMGatewayAddress() const;
unsigned int getFMGatewayPort() const;
std::string getFMLocalAddress() const;
unsigned int getFMLocalPort() const;
unsigned int getFMSampleRate() const;
unsigned int getFMNetworkModeHang() const;
bool getFMNetworkDebug() const;
// The AX.25 Network section
bool getAX25NetworkEnabled() const;
std::string getAX25NetworkPort() const;
unsigned int getAX25NetworkSpeed() const;
bool getAX25NetworkDebug() const;
// The TFTSERIAL section
std::string getTFTSerialPort() const;
unsigned int getTFTSerialBrightness() const;
@ -393,7 +350,6 @@ private:
std::string m_modemPort;
std::string m_modemProtocol;
unsigned int m_modemSpeed;
unsigned int m_modemAddress;
bool m_modemRXInvert;
bool m_modemTXInvert;
@ -412,10 +368,8 @@ private:
float m_modemYSFTXLevel;
float m_modemP25TXLevel;
float m_modemNXDNTXLevel;
float m_modemM17TXLevel;
float m_modemPOCSAGTXLevel;
float m_modemFMTXLevel;
float m_modemAX25TXLevel;
std::string m_modemRSSIMappingFile;
bool m_modemUseCOSAsLockout;
bool m_modemTrace;
@ -427,6 +381,9 @@ private:
unsigned int m_transparentLocalPort;
unsigned int m_transparentSendFrameType;
bool m_umpEnabled;
std::string m_umpPort;
bool m_dstarEnabled;
std::string m_dstarModule;
bool m_dstarSelfOnly;
@ -482,13 +439,6 @@ private:
unsigned int m_nxdnTXHang;
unsigned int m_nxdnModeHang;
bool m_m17Enabled;
unsigned int m_m17ColorCode;
bool m_m17SelfOnly;
bool m_m17AllowEncryption;
unsigned int m_m17TXHang;
unsigned int m_m17ModeHang;
bool m_pocsagEnabled;
unsigned int m_pocsagFrequency;
@ -520,20 +470,9 @@ private:
unsigned int m_fmHangTime;
unsigned int m_fmAccessMode;
bool m_fmCOSInvert;
bool m_fmNoiseSquelch;
unsigned int m_fmSquelchHighThreshold;
unsigned int m_fmSquelchLowThreshold;
unsigned int m_fmRFAudioBoost;
float m_fmMaxDevLevel;
unsigned int m_fmExtAudioBoost;
unsigned int m_fmModeHang;
bool m_ax25Enabled;
unsigned int m_ax25TXDelay;
int m_ax25RXTwist;
unsigned int m_ax25SlotTime;
unsigned int m_ax25PPersist;
bool m_ax25Trace;
bool m_dstarNetworkEnabled;
std::string m_dstarGatewayAddress;
@ -579,13 +518,6 @@ private:
unsigned int m_nxdnNetworkModeHang;
bool m_nxdnNetworkDebug;
bool m_m17NetworkEnabled;
std::string m_m17GatewayAddress;
unsigned int m_m17GatewayPort;
unsigned int m_m17LocalPort;
unsigned int m_m17NetworkModeHang;
bool m_m17NetworkDebug;
bool m_pocsagNetworkEnabled;
std::string m_pocsagGatewayAddress;
unsigned int m_pocsagGatewayPort;
@ -594,20 +526,6 @@ private:
unsigned int m_pocsagNetworkModeHang;
bool m_pocsagNetworkDebug;
bool m_fmNetworkEnabled;
std::string m_fmGatewayAddress;
unsigned int m_fmGatewayPort;
std::string m_fmLocalAddress;
unsigned int m_fmLocalPort;
unsigned int m_fmSampleRate;
unsigned int m_fmNetworkModeHang;
bool m_fmNetworkDebug;
bool m_ax25NetworkEnabled;
std::string m_ax25NetworkPort;
unsigned int m_ax25NetworkSpeed;
bool m_ax25NetworkDebug;
std::string m_tftSerialPort;
unsigned int m_tftSerialBrightness;

View File

@ -21,7 +21,7 @@
#include <cassert>
#include <algorithm>
CDMRControl::CDMRControl(unsigned int id, unsigned int colorCode, unsigned int callHang, bool selfOnly, bool embeddedLCOnly, bool dumpTAData, const std::vector<unsigned int>& prefixes, const std::vector<unsigned int>& blacklist, const std::vector<unsigned int>& whitelist, const std::vector<unsigned int>& slot1TGWhitelist, const std::vector<unsigned int>& slot2TGWhitelist, unsigned int timeout, IModem* modem, IDMRNetwork* network, CDisplay* display, bool duplex, CDMRLookup* lookup, CRSSIInterpolator* rssi, unsigned int jitter, DMR_OVCM_TYPES ovcm) :
CDMRControl::CDMRControl(unsigned int id, unsigned int colorCode, unsigned int callHang, bool selfOnly, bool embeddedLCOnly, bool dumpTAData, const std::vector<unsigned int>& prefixes, const std::vector<unsigned int>& blacklist, const std::vector<unsigned int>& whitelist, const std::vector<unsigned int>& slot1TGWhitelist, const std::vector<unsigned int>& slot2TGWhitelist, unsigned int timeout, CModem* modem, IDMRNetwork* network, CDisplay* display, bool duplex, CDMRLookup* lookup, CRSSIInterpolator* rssi, unsigned int jitter, DMR_OVCM_TYPES ovcm) :
m_colorCode(colorCode),
m_modem(modem),
m_network(network),

View File

@ -31,7 +31,7 @@
class CDMRControl {
public:
CDMRControl(unsigned int id, unsigned int colorCode, unsigned int callHang, bool selfOnly, bool embeddedLCOnly, bool dumpTAData, const std::vector<unsigned int>& prefixes, const std::vector<unsigned int>& blacklist, const std::vector<unsigned int>& whitelist, const std::vector<unsigned int>& slot1TGWhitelist, const std::vector<unsigned int>& slot2TGWhitelist, unsigned int timeout, IModem* modem, IDMRNetwork* network, CDisplay* display, bool duplex, CDMRLookup* lookup, CRSSIInterpolator* rssi, unsigned int jitter, DMR_OVCM_TYPES ovcm);
CDMRControl(unsigned int id, unsigned int colorCode, unsigned int callHang, bool selfOnly, bool embeddedLCOnly, bool dumpTAData, const std::vector<unsigned int>& prefixes, const std::vector<unsigned int>& blacklist, const std::vector<unsigned int>& whitelist, const std::vector<unsigned int>& slot1TGWhitelist, const std::vector<unsigned int>& slot2TGWhitelist, unsigned int timeout, CModem* modem, IDMRNetwork* network, CDisplay* display, bool duplex, CDMRLookup* lookup, CRSSIInterpolator* rssi, unsigned int jitter, DMR_OVCM_TYPES ovcm);
~CDMRControl();
bool processWakeup(const unsigned char* data);
@ -50,7 +50,7 @@ public:
private:
unsigned int m_colorCode;
IModem* m_modem;
CModem* m_modem;
IDMRNetwork* m_network;
CDMRSlot m_slot1;
CDMRSlot m_slot2;

View File

@ -37,7 +37,7 @@ unsigned int CDMRSlot::m_colorCode = 0U;
bool CDMRSlot::m_embeddedLCOnly = false;
bool CDMRSlot::m_dumpTAData = true;
IModem* CDMRSlot::m_modem = NULL;
CModem* CDMRSlot::m_modem = NULL;
IDMRNetwork* CDMRSlot::m_network = NULL;
CDisplay* CDMRSlot::m_display = NULL;
bool CDMRSlot::m_duplex = true;
@ -1896,7 +1896,7 @@ void CDMRSlot::writeQueueNet(const unsigned char *data)
m_queue.addData(data, len);
}
void CDMRSlot::init(unsigned int colorCode, bool embeddedLCOnly, bool dumpTAData, unsigned int callHang, IModem* modem, IDMRNetwork* network, CDisplay* display, bool duplex, CDMRLookup* lookup, CRSSIInterpolator* rssiMapper, unsigned int jitter, DMR_OVCM_TYPES ovcm)
void CDMRSlot::init(unsigned int colorCode, bool embeddedLCOnly, bool dumpTAData, unsigned int callHang, CModem* modem, IDMRNetwork* network, CDisplay* display, bool duplex, CDMRLookup* lookup, CRSSIInterpolator* rssiMapper, unsigned int jitter, DMR_OVCM_TYPES ovcm)
{
assert(modem != NULL);
assert(display != NULL);

View File

@ -62,7 +62,7 @@ public:
void enable(bool enabled);
static void init(unsigned int colorCode, bool embeddedLCOnly, bool dumpTAData, unsigned int callHang, IModem* modem, IDMRNetwork* network, CDisplay* display, bool duplex, CDMRLookup* lookup, CRSSIInterpolator* rssiMapper, unsigned int jitter, DMR_OVCM_TYPES ovcm);
static void init(unsigned int colorCode, bool embeddedLCOnly, bool dumpTAData, unsigned int callHang, CModem* modem, IDMRNetwork* network, CDisplay* display, bool duplex, CDMRLookup* lookup, CRSSIInterpolator* rssiMapper, unsigned int jitter, DMR_OVCM_TYPES ovcm);
private:
unsigned int m_slotNo;
@ -117,7 +117,7 @@ private:
static bool m_embeddedLCOnly;
static bool m_dumpTAData;
static IModem* m_modem;
static CModem* m_modem;
static IDMRNetwork* m_network;
static CDisplay* m_display;
static bool m_duplex;

View File

@ -101,8 +101,8 @@ m_netSkipDTMFBlankingFrames(0U)
m_gateway = new unsigned char[DSTAR_LONG_CALLSIGN_LENGTH];
m_lastFrame = new unsigned char[DSTAR_FRAME_LENGTH_BYTES + 1U];
m_rfVoiceSyncData = new unsigned char[DSTAR_MODEM_DATA_LEN];
m_netVoiceSyncData = new unsigned char[DSTAR_MODEM_DATA_LEN];
m_rfVoiceSyncData = new unsigned char[MODEM_DATA_LEN];
m_netVoiceSyncData = new unsigned char[MODEM_DATA_LEN];
std::string call = callsign;
call.resize(DSTAR_LONG_CALLSIGN_LENGTH - 1U, ' ');
@ -149,7 +149,7 @@ unsigned int CDStarControl::maybeFixupVoiceFrame(
unsigned char mini_header_type = mini_header & DSTAR_SLOW_DATA_TYPE_MASK;
if (n == 0U) {
::memcpy(voice_sync_data, data, DSTAR_MODEM_DATA_LEN);
::memcpy(voice_sync_data, data, MODEM_DATA_LEN);
*voice_sync_data_len = len;
} else if ((n % 2U != 0U) &&
((mini_header_type == DSTAR_SLOW_DATA_TYPE_FASTDATA01) ||

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2015,2016,2017,2018,2020 by Jonathan Naylor G4KLX
* Copyright (C) 2015,2016,2017,2018 by Jonathan Naylor G4KLX
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -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;
@ -40,7 +39,7 @@ const unsigned char TAG_DATA = 0x01U;
const unsigned char TAG_LOST = 0x02U;
const unsigned char TAG_EOT = 0x03U;
const unsigned int DSTAR_MODEM_DATA_LEN = 220U;
const unsigned int MODEM_DATA_LEN = 220U;
enum HW_TYPE {
HWT_MMDVM,

View File

@ -21,12 +21,14 @@
#include "SerialController.h"
#include "ModemSerialPort.h"
#include "NullDisplay.h"
#include "TFTSerial.h"
#include "TFTSurenoo.h"
#include "LCDproc.h"
#include "Nextion.h"
#include "CASTInfo.h"
#include "Conf.h"
#include "Modem.h"
#include "UMP.h"
#include "Log.h"
#if defined(HD44780)
@ -333,40 +335,6 @@ void CDisplay::clearNXDN()
}
}
void CDisplay::writeM17(const char* source, const char* dest, const char* type)
{
assert(source != NULL);
assert(dest != NULL);
assert(type != NULL);
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();
@ -424,11 +392,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;
@ -519,14 +482,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() */
@ -535,17 +490,17 @@ int CDisplay::writeNXDNIntEx(const class CUserDBentry& source, bool group, unsig
/* Factory method extracted from MMDVMHost.cpp - BG5HHP */
CDisplay* CDisplay::createDisplay(const CConf& conf, IModem* modem)
CDisplay* CDisplay::createDisplay(const CConf& conf, CUMP* ump, CModem* modem)
{
CDisplay *display = NULL;
CDisplay *display = NULL;
std::string type = conf.getDisplay();
std::string type = conf.getDisplay();
unsigned int dmrid = conf.getDMRId();
LogInfo("Display Parameters");
LogInfo(" Type: %s", type.c_str());
if (type == "TFT Surenoo") {
if (type == "TFT Serial" || type == "TFT Surenoo") {
std::string port = conf.getTFTSerialPort();
unsigned int brightness = conf.getTFTSerialBrightness();
@ -554,11 +509,14 @@ CDisplay* CDisplay::createDisplay(const CConf& conf, IModem* modem)
ISerialPort* serial = NULL;
if (port == "modem")
serial = new IModemSerialPort(modem);
serial = new CModemSerialPort(modem);
else
serial = new CSerialController(port, 115200U);
serial = new CSerialController(port, (type == "TFT Serial") ? SERIAL_9600 : SERIAL_115200);
display = new CTFTSurenoo(conf.getCallsign(), dmrid, serial, brightness, conf.getDuplex());
if (type == "TFT Surenoo")
display = new CTFTSurenoo(conf.getCallsign(), dmrid, serial, brightness, conf.getDuplex());
else
display = new CTFTSerial(conf.getCallsign(), dmrid, serial, brightness);
} else if (type == "Nextion") {
std::string port = conf.getNextionPort();
unsigned int brightness = conf.getNextionBrightness();
@ -597,14 +555,21 @@ CDisplay* CDisplay::createDisplay(const CConf& conf, IModem* modem)
}
if (port == "modem") {
ISerialPort* serial = new IModemSerialPort(modem);
ISerialPort* serial = new CModemSerialPort(modem);
display = new CNextion(conf.getCallsign(), dmrid, serial, brightness, displayClock, utc, idleBrightness, screenLayout, txFrequency, rxFrequency, displayTempInF);
} else if (port == "ump") {
if (ump != NULL) {
display = new CNextion(conf.getCallsign(), dmrid, ump, brightness, displayClock, utc, idleBrightness, screenLayout, txFrequency, rxFrequency, displayTempInF);
} else {
LogInfo(" NullDisplay loaded");
display = new CNullDisplay;
}
} else {
unsigned int baudrate = 9600U;
if (screenLayout == 4U)
baudrate = 115200U;
SERIAL_SPEED baudrate = SERIAL_9600;
if (screenLayout&0x0cU)
baudrate = SERIAL_115200;
LogInfo(" Display baudrate: %u ", baudrate);
LogInfo(" Display baudrate: %u ",baudrate);
ISerialPort* serial = new CSerialController(port, baudrate);
display = new CNextion(conf.getCallsign(), dmrid, serial, brightness, displayClock, utc, idleBrightness, screenLayout, txFrequency, rxFrequency, displayTempInF);
}

View File

@ -21,14 +21,14 @@
#include "Timer.h"
#include "UserDBentry.h"
#include "Modem.h"
#include <string>
#include <cstdint>
class CConf;
class IModem;
class CModem;
class CUMP;
class CDisplay
{
@ -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();
@ -86,7 +81,7 @@ public:
void clock(unsigned int ms);
static CDisplay* createDisplay(const CConf& conf, IModem* modem);
static CDisplay* createDisplay(const CConf& conf, CUMP* ump, CModem* modem);
protected:
virtual void setIdleInt() = 0;
@ -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,179 +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.
*/
#include "FMControl.h"
#include <string>
#if defined(DUMP_RF_AUDIO)
#include <cstdio>
#endif
#define SWAP_BYTES_16(a) (((a >> 8) & 0x00FFU) | ((a << 8) & 0xFF00U))
const float DEEMPHASIS_GAIN_DB = 0.0F;
const float PREEMPHASIS_GAIN_DB = 13.0F;
const float FILTER_GAIN_DB = 0.0F;
const unsigned int FM_MASK = 0x00000FFFU;
CFMControl::CFMControl(CFMNetwork* network) :
m_network(network),
m_enabled(false),
m_incomingRFAudio(1600U, "Incoming RF FM Audio"),
m_preemphasis (NULL),
m_deemphasis (NULL),
m_filterStage1(NULL),
m_filterStage2(NULL),
m_filterStage3(NULL)
{
m_preemphasis = new CIIRDirectForm1Filter(8.315375384336983F,-7.03334621603483F,0.0F,1.0F,0.282029168302153F,0.0F, PREEMPHASIS_GAIN_DB);
m_deemphasis = new CIIRDirectForm1Filter(0.07708787090460224F,0.07708787090460224F,0.0F,1.0F,-0.8458242581907955F,0.0F, DEEMPHASIS_GAIN_DB);
//cheby type 1 0.2dB cheby type 1 3rd order 300-2700Hz fs=8000
m_filterStage1 = new CIIRDirectForm1Filter(0.29495028f, 0.0f, -0.29495028f, 1.0f, -0.61384624f, -0.057158668f, FILTER_GAIN_DB);
m_filterStage2 = new CIIRDirectForm1Filter(1.0f, 2.0f, 1.0f, 1.0f, 0.9946123f, 0.6050482f, FILTER_GAIN_DB);
m_filterStage3 = new CIIRDirectForm1Filter(1.0f, -2.0f, 1.0f, 1.0f, -1.8414584f, 0.8804949f, FILTER_GAIN_DB);
}
CFMControl::~CFMControl()
{
delete m_preemphasis ;
delete m_deemphasis ;
delete m_filterStage1;
delete m_filterStage2;
delete m_filterStage3;
}
bool CFMControl::writeModem(const unsigned char* data, unsigned int length)
{
assert(data != NULL);
assert(length > 0U);
if (m_network == NULL)
return true;
if (data[0U] == TAG_HEADER)
return true;
if (data[0U] == TAG_EOT)
return m_network->writeEOT();
if (data[0U] != TAG_DATA)
return false;
m_incomingRFAudio.addData(data + 1U, length - 1U);
unsigned int bufferLength = m_incomingRFAudio.dataSize();
if (bufferLength > 252U)//168 samples 12-bit
bufferLength = 252U;
if (bufferLength >= 3U) {
bufferLength = bufferLength - bufferLength % 3U; //round down to nearest multiple of 3
unsigned char bufferData[252U];
m_incomingRFAudio.getData(bufferData, bufferLength);
unsigned int pack = 0U;
unsigned char* packPointer = (unsigned char*)&pack;
float out[168U];
unsigned int nOut = 0U;
short unpackedSamples[2U];
for (unsigned int i = 0U; i < bufferLength; i += 3U) {
//extract unsigned 12 bit unsigned sample pairs packed into 3 bytes to 16 bit signed
packPointer[0U] = bufferData[i];
packPointer[1U] = bufferData[i + 1U];
packPointer[2U] = bufferData[i + 2U];
unpackedSamples[1U] = short(int(pack & FM_MASK) - 2048);
unpackedSamples[0U] = short(int(pack >> 12) - 2048);
//process unpacked sample pair
for (unsigned char j = 0U; j < 2U; j++) {
// Convert to float (-1.0 to +1.0)
float sampleFloat = float(unpackedSamples[j]) / 2048.0F;
// De-emphasise and remove CTCSS
sampleFloat = m_deemphasis->filter(sampleFloat);
out[nOut++] = m_filterStage3->filter(m_filterStage2->filter(m_filterStage1->filter(sampleFloat)));
}
}
#if defined(DUMP_RF_AUDIO)
FILE * audiofile = fopen("./audiodump.bin", "ab");
if(audiofile != NULL) {
fwrite(out, sizeof(float), nOut, audiofile);
fclose(audiofile);
}
#endif
return m_network->writeData(out, nOut);
}
return true;
}
unsigned int CFMControl::readModem(unsigned char* data, unsigned int space)
{
assert(data != NULL);
assert(space > 0U);
if (m_network == NULL)
return 0U;
if (space > 252U)
space = 252U;
float netData[168U]; // Modem can handle up to 168 samples at a time
unsigned int length = m_network->read(netData, 168U);
if (length == 0U)
return 0U;
unsigned int pack = 0U;
unsigned char* packPointer = (unsigned char*)&pack;
unsigned int nData = 0U;
for (unsigned int i = 0; i < length; i++) {
// Pre-emphasis
float sampleFloat = m_preemphasis->filter(netData[i]);
// Convert float to 12-bit samples (0 to 4095)
unsigned int sample12bit = (unsigned int)((sampleFloat + 1.0F) * 2048.0F + 0.5F);
// pack 2 samples onto 3 bytes
if((i & 1U) == 0) {
pack = 0U;
pack = sample12bit << 12;
} else {
pack |= sample12bit;
data[nData++] = packPointer[0U];
data[nData++] = packPointer[1U];
data[nData++] = packPointer[2U];
}
}
return nData;
}
void CFMControl::clock(unsigned int ms)
{
// May not be needed
}
void CFMControl::enable(bool enabled)
{
// May not be needed
}

View File

@ -1,55 +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(FMControl_H)
#define FMControl_H
#include "FMNetwork.h"
#include "Defines.h"
#include "IIRDirectForm1Filter.h"
// Uncomment this to dump audio to a raw audio file
// The file will be written in same folder as executable
// Toplay the file : ffplay -autoexit -f u16be -ar 8000 audiodump.bin
// #define DUMP_RF_AUDIO
class CFMControl {
public:
CFMControl(CFMNetwork* network);
~CFMControl();
bool writeModem(const unsigned char* data, unsigned int length);
unsigned int readModem(unsigned char* data, unsigned int space);
void clock(unsigned int ms);
void enable(bool enabled);
private:
CFMNetwork* m_network;
bool m_enabled;
CRingBuffer<unsigned char> m_incomingRFAudio;
CIIRDirectForm1Filter* m_preemphasis;
CIIRDirectForm1Filter* m_deemphasis;
CIIRDirectForm1Filter* m_filterStage1;
CIIRDirectForm1Filter* m_filterStage2;
CIIRDirectForm1Filter* m_filterStage3;
};
#endif

View File

@ -1,289 +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.
*/
#include "FMNetwork.h"
#include "Defines.h"
#include "Utils.h"
#include "Log.h"
#include <cstdio>
#include <cassert>
#include <cstring>
const unsigned int BUFFER_LENGTH = 500U;
CFMNetwork::CFMNetwork(const std::string& localAddress, unsigned int localPort, const std::string& gatewayAddress, unsigned int gatewayPort, unsigned int sampleRate, bool debug) :
m_socket(localAddress, localPort),
m_addr(),
m_addrLen(0U),
m_sampleRate(sampleRate),
m_debug(debug),
m_enabled(false),
m_buffer(2000U, "FM Network"),
m_pollTimer(1000U, 5U)
{
assert(gatewayPort > 0U);
assert(!gatewayAddress.empty());
assert(sampleRate > 0U);
if (CUDPSocket::lookup(gatewayAddress, gatewayPort, m_addr, m_addrLen) != 0)
m_addrLen = 0U;
#if !defined(_WIN32) && !defined(_WIN64)
int error;
m_incoming = ::src_new(SRC_SINC_FASTEST, 1, &error);
m_outgoing = ::src_new(SRC_SINC_FASTEST, 1, &error);
assert(m_incoming != NULL);
assert(m_outgoing != NULL);
#endif
}
CFMNetwork::~CFMNetwork()
{
#if !defined(_WIN32) && !defined(_WIN64)
::src_delete(m_incoming);
::src_delete(m_outgoing);
#endif
}
bool CFMNetwork::open()
{
if (m_addrLen == 0U) {
LogError("Unable to resolve the address of the FM Gateway");
return false;
}
LogMessage("Opening FM network connection");
m_pollTimer.start();
return m_socket.open(m_addr);
}
bool CFMNetwork::writeData(float* data, unsigned int nSamples)
{
assert(data != NULL);
assert(nSamples > 0U);
#if !defined(_WIN32) && !defined(_WIN64)
assert(m_outgoing != NULL);
float out[1000U];
SRC_DATA src;
if (m_sampleRate != 8000U) {
src.data_in = data;
src.data_out = out;
src.input_frames = nSamples;
src.output_frames = 1000;
src.end_of_input = 0;
src.src_ratio = double(m_sampleRate) / 8000.0;
int ret = ::src_process(m_outgoing, &src);
if (ret != 0) {
LogError("Error up/downsampling of the output audio has an error - %s", src_strerror(ret));
return false;
}
} else {
src.data_out = data;
src.output_frames_gen = nSamples;
}
#endif
unsigned int length = 3U;
unsigned char buffer[1500U];
::memset(buffer, 0x00U, 1500U);
buffer[0U] = 'F';
buffer[1U] = 'M';
buffer[2U] = 'D';
#if defined(_WIN32) || defined(_WIN64)
for (long i = 0L; i < nSamples; i++) {
unsigned short val = (unsigned short)((data[i] + 1.0F) * 32767.0F + 0.5F);
#else
for (long i = 0L; i < src.output_frames_gen; i++) {
unsigned short val = (unsigned short)((src.data_out[i] + 1.0F) * 32767.0F + 0.5F);
#endif
buffer[length++] = (val >> 8) & 0xFFU;
buffer[length++] = (val >> 0) & 0xFFU;
}
if (m_debug)
CUtils::dump(1U, "FM Network Data Sent", buffer, length);
return m_socket.write(buffer, length, m_addr, m_addrLen);
}
bool CFMNetwork::writeEOT()
{
unsigned char buffer[10U];
::memset(buffer, 0x00U, 10U);
buffer[0U] = 'F';
buffer[1U] = 'M';
buffer[2U] = 'E';
if (m_debug)
CUtils::dump(1U, "FM Network End of Transmission Sent", buffer, 3U);
return m_socket.write(buffer, 3U, m_addr, m_addrLen);
}
void CFMNetwork::clock(unsigned int ms)
{
m_pollTimer.clock(ms);
if (m_pollTimer.hasExpired()) {
writePoll();
m_pollTimer.start();
}
unsigned char buffer[BUFFER_LENGTH];
sockaddr_storage addr;
unsigned int addrlen;
int length = m_socket.read(buffer, BUFFER_LENGTH, addr, addrlen);
if (length <= 0)
return;
// Check if the data is for us
if (!CUDPSocket::match(addr, m_addr)) {
LogMessage("FM packet received from an invalid source");
return;
}
// Ignore incoming polls
if (::memcmp(buffer, "FMP", 3U) == 0)
return;
// Invalid packet type?
if (::memcmp(buffer, "FMD", 3U) != 0)
return;
if (!m_enabled)
return;
if (m_debug)
CUtils::dump(1U, "FM Network Data Received", buffer, length);
m_buffer.addData(buffer + 3U, length - 3U);
}
unsigned int CFMNetwork::read(float* data, unsigned int nSamples)
{
assert(data != NULL);
assert(nSamples > 0U);
unsigned int bytes = m_buffer.dataSize() / sizeof(unsigned short);
if (bytes == 0U)
return 0U;
if (bytes < nSamples)
nSamples = bytes;
unsigned char buffer[1500U];
m_buffer.getData(buffer, nSamples * sizeof(unsigned short));
#if !defined(_WIN32) && !defined(_WIN64)
assert(m_incoming != NULL);
SRC_DATA src;
if (m_sampleRate != 8000U) {
float in[750U];
for (unsigned int i = 0U; i < nSamples; i++) {
unsigned short val = ((buffer[i * 2U + 0U] & 0xFFU) << 8) +
((buffer[i * 2U + 1U] & 0xFFU) << 0);
in[i] = (float(val) - 32768.0F) / 32768.0F;
}
src.data_in = in;
src.data_out = data;
src.input_frames = nSamples;
src.output_frames = 750;
src.end_of_input = 0;
src.src_ratio = 8000.0 / double(m_sampleRate);
int ret = ::src_process(m_incoming, &src);
if (ret != 0) {
LogError("Error up/downsampling of the input audio has an error - %s", src_strerror(ret));
return 0U;
}
return src.output_frames_gen;
} else {
#endif
for (unsigned int i = 0U; i < nSamples; i++) {
unsigned short val = ((buffer[i * 2U + 0U] & 0xFFU) << 8) +
((buffer[i * 2U + 1U] & 0xFFU) << 0);
data[i] = (float(val) - 32768.0F) / 32768.0F;
}
return nSamples;
#if !defined(_WIN32) && !defined(_WIN64)
}
#endif
}
void CFMNetwork::reset()
{
#if !defined(_WIN32) && !defined(_WIN64)
assert(m_incoming != NULL);
assert(m_outgoing != NULL);
::src_reset(m_incoming);
::src_reset(m_outgoing);
#endif
m_buffer.clear();
}
void CFMNetwork::close()
{
m_socket.close();
LogMessage("Closing FM network connection");
}
void CFMNetwork::enable(bool enabled)
{
if (enabled && !m_enabled)
reset();
else if (!enabled && m_enabled)
reset();
m_enabled = enabled;
}
bool CFMNetwork::writePoll()
{
unsigned char buffer[3U];
buffer[0U] = 'F';
buffer[1U] = 'M';
buffer[2U] = 'P';
if (m_debug)
CUtils::dump(1U, "FM Network Poll Sent", buffer, 3U);
return m_socket.write(buffer, 3U, m_addr, m_addrLen);
}

View File

@ -1,71 +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.
*/
#ifndef FMNetwork_H
#define FMNetwork_H
#include "RingBuffer.h"
#include "UDPSocket.h"
#include "Timer.h"
#if !defined(_WIN32) && !defined(_WIN64)
#include <samplerate.h>
#endif
#include <cstdint>
#include <string>
class CFMNetwork {
public:
CFMNetwork(const std::string& myAddress, unsigned int myPort, const std::string& gatewayAddress, unsigned int gatewayPort, unsigned int sampleRate, bool debug);
~CFMNetwork();
bool open();
void enable(bool enabled);
bool writeData(float* data, unsigned int nSamples);
bool writeEOT();
unsigned int read(float* data, unsigned int nSamples);
void reset();
void close();
void clock(unsigned int ms);
private:
CUDPSocket m_socket;
sockaddr_storage m_addr;
unsigned int m_addrLen;
unsigned int m_sampleRate;
bool m_debug;
bool m_enabled;
CRingBuffer<unsigned char> m_buffer;
CTimer m_pollTimer;
#if !defined(_WIN32) && !defined(_WIN64)
SRC_STATE* m_incoming;
SRC_STATE* m_outgoing;
#endif
bool writePoll();
};
#endif

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2002-2004,2007-2011,2013,2014-2017,2020 by Jonathan Naylor G4KLX
* Copyright (C) 2002-2004,2007-2011,2013,2014-2017 by Jonathan Naylor G4KLX
* Copyright (C) 1999-2001 by Thomas Sailor HB9JNX
*
* This program is free software; you can redistribute it and/or modify
@ -17,8 +17,6 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#if defined(__linux__)
#include "I2CController.h"
#include "Log.h"
@ -26,18 +24,52 @@
#include <cassert>
#include <sys/types.h>
#if defined(_WIN32) || defined(_WIN64)
#include <setupapi.h>
#include <winioctl.h>
CI2CController::CI2CController(const std::string& device, SERIAL_SPEED speed, unsigned int address, bool assertRTS) :
CSerialController(device, speed, assertRTS),
m_address(address)
{
}
CI2CController::~CI2CController()
{
}
bool CI2CController::open()
{
return CSerialController::open();
}
int CI2CController::read(unsigned char* buffer, unsigned int length)
{
return CSerialController::read(buffer, length);
}
int CI2CController::write(const unsigned char* buffer, unsigned int length)
{
return CSerialController::write(buffer, length);
}
#else
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <cerrno>
#include <fcntl.h>
#include <unistd.h>
#include <termios.h>
#if defined(__linux__)
#include <linux/i2c-dev.h>
#endif
CI2CController::CI2CController(const std::string& device, unsigned int address) :
m_device(device),
m_address(address),
m_fd(-1)
CI2CController::CI2CController(const std::string& device, SERIAL_SPEED speed, unsigned int address, bool assertRTS) :
CSerialController(device, speed, assertRTS),
m_address(address)
{
}
@ -49,6 +81,7 @@ bool CI2CController::open()
{
assert(m_fd == -1);
#if defined(__linux__)
m_fd = ::open(m_device.c_str(), O_RDWR);
if (m_fd < 0) {
LogError("Cannot open device - %s", m_device.c_str());
@ -56,16 +89,19 @@ bool CI2CController::open()
}
if (::ioctl(m_fd, I2C_TENBIT, 0) < 0) {
LogError("I2C: failed to set 7bitaddress");
LogError("CI2C: failed to set 7bitaddress");
::close(m_fd);
return false;
}
if (::ioctl(m_fd, I2C_SLAVE, m_address) < 0) {
LogError("I2C: Failed to acquire bus access/talk to slave 0x%02X", m_address);
LogError("CI2C: Failed to acquire bus access/talk to slave 0x%02X", m_address);
::close(m_fd);
return false;
}
#else
#warning "I2C controller supports Linux only"
#endif
return true;
}
@ -81,6 +117,7 @@ int CI2CController::read(unsigned char* buffer, unsigned int length)
unsigned int offset = 0U;
while (offset < length) {
#if defined(__linux__)
ssize_t n = ::read(m_fd, buffer + offset, 1U);
if (n < 0) {
if (errno != EAGAIN) {
@ -91,6 +128,7 @@ int CI2CController::read(unsigned char* buffer, unsigned int length)
if (n > 0)
offset += n;
#endif
}
return length;
@ -106,7 +144,10 @@ int CI2CController::write(const unsigned char* buffer, unsigned int length)
unsigned int ptr = 0U;
while (ptr < length) {
ssize_t n = ::write(m_fd, buffer + ptr, 1U);
ssize_t n = 0U;
#if defined(__linux__)
n = ::write(m_fd, buffer + ptr, 1U);
#endif
if (n < 0) {
if (errno != EAGAIN) {
LogError("Error returned from write(), errno=%d", errno);
@ -121,12 +162,4 @@ int CI2CController::write(const unsigned char* buffer, unsigned int length)
return length;
}
void CI2CController::close()
{
assert(m_fd != -1);
::close(m_fd);
m_fd = -1;
}
#endif

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2002-2004,2007-2009,2011-2013,2015-2017,2020 by Jonathan Naylor G4KLX
* Copyright (C) 2002-2004,2007-2009,2011-2013,2015-2017 by Jonathan Naylor G4KLX
* Copyright (C) 1999-2001 by Thomas Sailor HB9JNX
*
* This program is free software; you can redistribute it and/or modify
@ -20,15 +20,11 @@
#ifndef I2CController_H
#define I2CController_H
#if defined(__linux__)
#include "SerialController.h"
#include "SerialPort.h"
#include <string>
class CI2CController : public ISerialPort {
class CI2CController : public CSerialController {
public:
CI2CController(const std::string& device, unsigned int address = 0x22U);
CI2CController(const std::string& device, SERIAL_SPEED speed, unsigned int address = 0x22U, bool assertRTS = false);
virtual ~CI2CController();
virtual bool open();
@ -37,14 +33,8 @@ public:
virtual int write(const unsigned char* buffer, unsigned int length);
virtual void close();
private:
std::string m_device;
unsigned int m_address;
int m_fd;
};
#endif
#endif

View File

@ -1,60 +0,0 @@
/*
* Copyright (C) 2015-2020 by Jonathan Naylor G4KLX
* Copyright (C) 2020 by Geoffrey Merck - F4FXL KC3FRA
*
* 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 "IIRDirectForm1Filter.h"
#include "math.h"
CIIRDirectForm1Filter::CIIRDirectForm1Filter(float b0, float b1, float b2, float , float a1, float a2, float addtionalGaindB) :
m_x2(0.0F),
m_y2(0.0F),
m_x1(0.0F),
m_y1(0.0F),
m_b0(b0),
m_b1(b1),
m_b2(b2),
m_a1(a1),
m_a2(a2),
m_additionalGainLin(0.0F)
{
m_additionalGainLin = ::powf(10.0F, addtionalGaindB / 20.0F);
}
float CIIRDirectForm1Filter::filter(float sample)
{
float output = m_b0 * sample
+ m_b1 * m_x1
+ m_b2 * m_x2
- m_a1 * m_y1
- m_a2 * m_y2;
m_x2 = m_x1;
m_y2 = m_y1;
m_x1 = sample;
m_y1 = output;
return output * m_additionalGainLin;
}
void CIIRDirectForm1Filter::reset()
{
m_x1 = 0.0f;
m_x2 = 0.0f;
m_y1 = 0.0f;
m_y2 = 0.0f;
}

View File

@ -1,50 +0,0 @@
/*
* Copyright (C) 2015-2020 by Jonathan Naylor G4KLX
* Copyright (C) 2020 by Geoffrey Merck - F4FXL KC3FRA
*
* 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(IIRDIRECTFORM1FILTER_H)
#define IIRDIRECTFORM1FILTER_H
class CIIRDirectForm1Filter
{
public:
CIIRDirectForm1Filter(float b0, float b1, float b2, float, float a1, float a2, float additionalGaindB);
float filter(float sample);
void reset();
private:
// delay line
float m_x2; // x[n-2]
float m_y2; // y[n-2]
float m_x1; // x[n-1]
float m_y1; // y[n-1]
// coefficients
// FIR
float m_b0;
float m_b1;
float m_b2;
// IIR
float m_a1;
float m_a2;
float m_additionalGainLin;
};
#endif

9
ISSUES.txt Normal file
View File

@ -0,0 +1,9 @@
D-Star: On some radios, the header is not decoded correctly. It looks like frequency drift at the beginning of the transmission.
DMR: DMO mode doesn't wake up older radios like other radios do.
YSF: No known issues.
P25: Upgrade the filters, processing power in the Due permiting.
NXDN: No known issues.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 57 KiB

View File

@ -95,7 +95,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 int localPort, const std::string& callsign, unsigned int dmrid, bool displayClock, bool utc, bool duplex, bool dimOnIdle) :
CDisplay(),
@ -189,7 +188,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
}
@ -209,7 +207,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
}
@ -227,7 +224,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
}
@ -247,7 +243,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
}
@ -265,7 +260,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
}
@ -562,51 +556,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 != NULL);
assert(dest != NULL);
assert(type != NULL);
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)
{
}
@ -901,21 +850,5 @@ void CLCDproc::defineScreens()
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

@ -62,10 +62,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,85 +0,0 @@
/*
* Copyright (C) 2018,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.
*/
#include "M17CRC.h"
#include <cstdio>
#include <cassert>
const uint16_t CRC_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::checkCRC(const unsigned char* in, unsigned int nBytes)
{
assert(in != NULL);
assert(nBytes > 2U);
uint16_t crc = createCRC(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::encodeCRC(unsigned char* in, unsigned int nBytes)
{
assert(in != NULL);
assert(nBytes > 2U);
uint16_t crc = createCRC(in, nBytes - 2U);
in[nBytes - 2U] = (crc >> 8) & 0xFFU;
in[nBytes - 1U] = (crc >> 0) & 0xFFU;
}
uint16_t CM17CRC::createCRC(const unsigned char* in, unsigned int nBytes)
{
assert(in != NULL);
uint16_t crc = 0xFFFFU;
for (unsigned int i = 0U; i < nBytes; i++)
crc = (crc << 8) ^ CRC_TABLE[((crc >> 8) ^ uint16_t(in[i])) & 0x00FFU];
return crc;
}

View File

@ -1,34 +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(M17CRC_H)
#define M17CRC_H
#include <cstdint>
class CM17CRC
{
public:
static bool checkCRC(const unsigned char* in, unsigned int nBytes);
static void encodeCRC(unsigned char* in, unsigned int nBytes);
private:
static uint16_t createCRC(const unsigned char* in, unsigned int nBytes);
};
#endif

View File

@ -1,802 +0,0 @@
/*
* Copyright (C) 2015-2020 Jonathan Naylor, G4KLX
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include "M17Control.h"
#include "M17Convolution.h"
#include "M17Utils.h"
#include "M17CRC.h"
#include "Golay24128.h"
#include "Utils.h"
#include "Sync.h"
#include "Log.h"
#include <cstdio>
#include <cassert>
#include <cstring>
#include <ctime>
const unsigned int INTERLEAVER[] = {
0U, 137U, 90U, 227U, 180U, 317U, 270U, 39U, 360U, 129U, 82U, 219U, 172U, 309U, 262U, 31U, 352U, 121U, 74U, 211U, 164U,
301U, 254U, 23U, 344U, 113U, 66U, 203U, 156U, 293U, 246U, 15U, 336U, 105U, 58U, 195U, 148U, 285U, 238U, 7U, 328U, 97U,
50U, 187U, 140U, 277U, 230U, 367U, 320U, 89U, 42U, 179U, 132U, 269U, 222U, 359U, 312U, 81U, 34U, 171U, 124U, 261U, 214U,
351U, 304U, 73U, 26U, 163U, 116U, 253U, 206U, 343U, 296U, 65U, 18U, 155U, 108U, 245U, 198U, 335U, 288U, 57U, 10U, 147U,
100U, 237U, 190U, 327U, 280U, 49U, 2U, 139U, 92U, 229U, 182U, 319U, 272U, 41U, 362U, 131U, 84U, 221U, 174U, 311U, 264U,
33U, 354U, 123U, 76U, 213U, 166U, 303U, 256U, 25U, 346U, 115U, 68U, 205U, 158U, 295U, 248U, 17U, 338U, 107U, 60U, 197U,
150U, 287U, 240U, 9U, 330U, 99U, 52U, 189U, 142U, 279U, 232U, 1U, 322U, 91U, 44U, 181U, 134U, 271U, 224U, 361U, 314U, 83U,
36U, 173U, 126U, 263U, 216U, 353U, 306U, 75U, 28U, 165U, 118U, 255U, 208U, 345U, 298U, 67U, 20U, 157U, 110U, 247U, 200U,
337U, 290U, 59U, 12U, 149U, 102U, 239U, 192U, 329U, 282U, 51U, 4U, 141U, 94U, 231U, 184U, 321U, 274U, 43U, 364U, 133U, 86U,
223U, 176U, 313U, 266U, 35U, 356U, 125U, 78U, 215U, 168U, 305U, 258U, 27U, 348U, 117U, 70U, 207U, 160U, 297U, 250U, 19U,
340U, 109U, 62U, 199U, 152U, 289U, 242U, 11U, 332U, 101U, 54U, 191U, 144U, 281U, 234U, 3U, 324U, 93U, 46U, 183U, 136U, 273U,
226U, 363U, 316U, 85U, 38U, 175U, 128U, 265U, 218U, 355U, 308U, 77U, 30U, 167U, 120U, 257U, 210U, 347U, 300U, 69U, 22U,
159U, 112U, 249U, 202U, 339U, 292U, 61U, 14U, 151U, 104U, 241U, 194U, 331U, 284U, 53U, 6U, 143U, 96U, 233U, 186U, 323U,
276U, 45U, 366U, 135U, 88U, 225U, 178U, 315U, 268U, 37U, 358U, 127U, 80U, 217U, 170U, 307U, 260U, 29U, 350U, 119U, 72U,
209U, 162U, 299U, 252U, 21U, 342U, 111U, 64U, 201U, 154U, 291U, 244U, 13U, 334U, 103U, 56U, 193U, 146U, 283U, 236U, 5U,
326U, 95U, 48U, 185U, 138U, 275U, 228U, 365U, 318U, 87U, 40U, 177U, 130U, 267U, 220U, 357U, 310U, 79U, 32U, 169U, 122U,
259U, 212U, 349U, 302U, 71U, 24U, 161U, 114U, 251U, 204U, 341U, 294U, 63U, 16U, 153U, 106U, 243U, 196U, 333U, 286U, 55U,
8U, 145U, 98U, 235U, 188U, 325U, 278U, 47U};
const unsigned char SCRAMBLER[] = {
0x00U, 0x00U, 0xD6U, 0xB5U, 0xE2U, 0x30U, 0x82U, 0xFFU, 0x84U, 0x62U, 0xBAU, 0x4EU, 0x96U, 0x90U, 0xD8U, 0x98U, 0xDDU,
0x5DU, 0x0CU, 0xC8U, 0x52U, 0x43U, 0x91U, 0x1DU, 0xF8U, 0x6EU, 0x68U, 0x2FU, 0x35U, 0xDAU, 0x14U, 0xEAU, 0xCDU, 0x76U,
0x19U, 0x8DU, 0xD5U, 0x80U, 0xD1U, 0x33U, 0x87U, 0x13U, 0x57U, 0x18U, 0x2DU, 0x29U, 0x78U, 0xC3U};
// #define DUMP_M17
const unsigned char BIT_MASK_TABLE[] = { 0x80U, 0x40U, 0x20U, 0x10U, 0x08U, 0x04U, 0x02U, 0x01U };
#define WRITE_BIT(p,i,b) p[(i)>>3] = (b) ? (p[(i)>>3] | BIT_MASK_TABLE[(i)&7]) : (p[(i)>>3] & ~BIT_MASK_TABLE[(i)&7])
#define READ_BIT(p,i) (p[(i)>>3] & BIT_MASK_TABLE[(i)&7])
CM17Control::CM17Control(const std::string& callsign, unsigned int colorCode, bool selfOnly, bool allowEncryption, CM17Network* network, CDisplay* display, unsigned int timeout, bool duplex, CRSSIInterpolator* rssiMapper) :
m_callsign(callsign),
m_colorCode(colorCode),
m_selfOnly(selfOnly),
m_allowEncryption(allowEncryption),
m_network(network),
m_display(display),
m_duplex(duplex),
m_queue(5000U, "M17 Control"),
m_rfState(RS_RF_LISTENING),
m_netState(RS_NET_IDLE),
m_rfTimeoutTimer(1000U, timeout),
m_netTimeoutTimer(1000U, timeout),
m_packetTimer(1000U, 0U, 200U),
m_networkWatchdog(1000U, 0U, 1500U),
m_elapsed(),
m_rfFrames(0U),
m_netFrames(0U),
m_rfFN(0U),
m_rfErrs(0U),
m_rfBits(1U),
m_rfLICH(),
m_rfLICHn(0U),
m_netLICH(),
m_netLICHn(0U),
m_rssiMapper(rssiMapper),
m_rssi(0U),
m_maxRSSI(0U),
m_minRSSI(0U),
m_aveRSSI(0U),
m_rssiCount(0U),
m_enabled(true),
m_fp(NULL)
{
assert(display != NULL);
assert(rssiMapper != NULL);
}
CM17Control::~CM17Control()
{
}
bool CM17Control::writeModem(unsigned char* data, unsigned int len)
{
assert(data != NULL);
if (!m_enabled)
return false;
unsigned char type = data[0U];
if (type == TAG_LOST && m_rfState == RS_RF_AUDIO) {
std::string source = m_rfLICH.getSource();
std::string dest = m_rfLICH.getDest();
if (m_rssi != 0U)
LogMessage("M17, transmission lost from %s to %s, %.1f seconds, BER: %.1f%%, RSSI: -%u/-%u/-%u dBm", source.c_str(), dest.c_str(), float(m_rfFrames) / 25.0F, float(m_rfErrs * 100U) / float(m_rfBits), m_minRSSI, m_maxRSSI, m_aveRSSI / m_rssiCount);
else
LogMessage("M17, transmission lost from %s to %s, %.1f seconds, BER: %.1f%%", source.c_str(), dest.c_str(), float(m_rfFrames) / 25.0F, float(m_rfErrs * 100U) / float(m_rfBits));
writeEndRF();
return false;
}
if (type == TAG_LOST && m_rfState == RS_RF_DATA) {
writeEndRF();
return false;
}
if (type == TAG_LOST) {
m_rfState = RS_RF_LISTENING;
return false;
}
// Have we got RSSI bytes on the end?
if (len == (M17_FRAME_LENGTH_BYTES + 4U)) {
uint16_t raw = 0U;
raw |= (data[50U] << 8) & 0xFF00U;
raw |= (data[51U] << 0) & 0x00FFU;
// Convert the raw RSSI to dBm
int rssi = m_rssiMapper->interpolate(raw);
if (rssi != 0)
LogDebug("M17, raw RSSI: %u, reported RSSI: %d dBm", raw, rssi);
// RSSI is always reported as positive
m_rssi = (rssi >= 0) ? rssi : -rssi;
if (m_rssi > m_minRSSI)
m_minRSSI = m_rssi;
if (m_rssi < m_maxRSSI)
m_maxRSSI = m_rssi;
m_aveRSSI += m_rssi;
m_rssiCount++;
}
unsigned char temp[M17_FRAME_LENGTH_BYTES];
decorrelator(data + 2U, temp);
interleaver(temp, data + 2U);
if (m_rfState == RS_RF_LISTENING && data[0U] == TAG_HEADER) {
m_rfLICH.reset();
CM17Convolution conv;
unsigned char frame[M17_LICH_LENGTH_BYTES];
conv.decodeLinkSetup(data + 2U + M17_SYNC_LENGTH_BYTES, frame);
bool valid = CM17CRC::checkCRC(frame, M17_LICH_LENGTH_BYTES);
if (valid) {
m_rfFrames = 0U;
m_rfErrs = 0U;
m_rfBits = 1U;
m_rfTimeoutTimer.start();
m_minRSSI = m_rssi;
m_maxRSSI = m_rssi;
m_aveRSSI = m_rssi;
m_rssiCount = 1U;
m_rfLICHn = 0U;
m_rfFN = 0U;
#if defined(DUMP_M17)
openFile();
#endif
m_rfLICH.setLinkSetup(frame);
m_rfState = RS_RF_LATE_ENTRY;
return true;
} else {
m_rfState = RS_RF_LATE_ENTRY;
}
}
if (m_rfState == RS_RF_LATE_ENTRY && data[0U] == TAG_DATA) {
unsigned int frag1, frag2, frag3, frag4;
CM17Utils::splitFragmentLICHFEC(data + 2U + M17_SYNC_LENGTH_BYTES, frag1, frag2, frag3, frag4);
unsigned int lich1 = CGolay24128::decode24128(frag1);
unsigned int lich2 = CGolay24128::decode24128(frag2);
unsigned int lich3 = CGolay24128::decode24128(frag3);
unsigned int lich4 = CGolay24128::decode24128(frag4);
unsigned int colorCode = (lich4 >> 7) & 0x1FU;
if (colorCode != m_colorCode)
return false;
bool lateEntry = false;
if (!m_rfLICH.isValid()) {
unsigned char lich[M17_LICH_FRAGMENT_LENGTH_BYTES];
CM17Utils::combineFragmentLICH(lich1, lich2, lich3, lich4, lich);
unsigned int n = (lich4 >> 4) & 0x07U;
m_rfLICH.setFragment(lich, n);
lateEntry = true;
}
bool valid = m_rfLICH.isValid();
if (valid) {
m_rfFrames = 0U;
m_rfErrs = 0U;
m_rfBits = 1U;
m_rfTimeoutTimer.start();
m_minRSSI = m_rssi;
m_maxRSSI = m_rssi;
m_aveRSSI = m_rssi;
m_rssiCount = 1U;
m_rfLICHn = 0U;
#if defined(DUMP_M17)
openFile();
#endif
std::string source = m_rfLICH.getSource();
std::string dest = m_rfLICH.getDest();
if (m_selfOnly) {
bool ret = checkCallsign(source);
if (!ret) {
LogMessage("M17, invalid access attempt from %s to %s", source.c_str(), dest.c_str());
m_rfState = RS_RF_REJECTED;
return false;
}
}
unsigned char dataType = m_rfLICH.getDataType();
switch (dataType) {
case 1U:
LogMessage("M17, received RF %s data transmission from %s to %s", lateEntry ? "late entry" : "", source.c_str(), dest.c_str());
m_rfState = RS_RF_DATA;
break;
case 2U:
LogMessage("M17, received RF %s voice transmission from %s to %s", lateEntry ? "late entry" : "", source.c_str(), dest.c_str());
m_rfState = RS_RF_AUDIO;
break;
case 3U:
LogMessage("M17, received RF %s voice + data transmission from %s to %s", lateEntry ? "late entry" : "", source.c_str(), dest.c_str());
m_rfState = RS_RF_AUDIO;
break;
default:
LogMessage("M17, received RF %s unknown transmission from %s to %s", lateEntry ? "late entry" : "", source.c_str(), dest.c_str());
m_rfState = RS_RF_DATA;
break;
}
m_display->writeM17(source.c_str(), dest.c_str(), "R");
if (m_duplex) {
// Create a Link Setup frame
data[0U] = TAG_HEADER;
data[1U] = 0x00U;
// Generate the sync
CSync::addM17HeaderSync(data + 2U);
unsigned char setup[M17_LICH_LENGTH_BYTES];
m_rfLICH.getLinkSetup(setup);
// Add the convolution FEC
CM17Convolution conv;
conv.encodeLinkSetup(setup, data + 2U + M17_SYNC_LENGTH_BYTES);
unsigned char temp[M17_FRAME_LENGTH_BYTES];
interleaver(data + 2U, temp);
decorrelator(temp, data + 2U);
writeQueueRF(data);
}
// Fall through to the next section
}
}
if ((m_rfState == RS_RF_AUDIO || m_rfState == RS_RF_DATA) && data[0U] == TAG_DATA) {
#if defined(DUMP_M17)
writeFile(data + 2U);
#endif
CM17Convolution conv;
unsigned char frame[M17_FN_LENGTH_BYTES + M17_PAYLOAD_LENGTH_BYTES + M17_CRC_LENGTH_BYTES];
conv.decodeData(data + 2U + M17_SYNC_LENGTH_BYTES + M17_LICH_FRAGMENT_FEC_LENGTH_BYTES, frame);
bool valid = CM17CRC::checkCRC(frame, M17_FN_LENGTH_BYTES + M17_PAYLOAD_LENGTH_BYTES + M17_CRC_LENGTH_BYTES);
if (valid) {
m_rfFN = (frame[0U] << 8) + (frame[1U] << 0);
} else {
// Create a silence frame
m_rfFN++;
// The new FN
frame[0U] = m_rfFN >> 8;
frame[1U] = m_rfFN >> 0;
// Add silent audio
unsigned char dataType = m_rfLICH.getDataType();
switch (dataType) {
case 2U:
::memcpy(frame + M17_FN_LENGTH_BYTES + 0U, M17_3200_SILENCE, 8U);
::memcpy(frame + M17_FN_LENGTH_BYTES + 8U, M17_3200_SILENCE, 8U);
break;
case 3U:
::memcpy(frame + M17_FN_LENGTH_BYTES + 0U, M17_1600_SILENCE, 8U);
break;
default:
break;
}
// Add the CRC
CM17CRC::encodeCRC(frame, M17_FN_LENGTH_BYTES + M17_PAYLOAD_LENGTH_BYTES + M17_CRC_LENGTH_BYTES);
}
unsigned char rfData[2U + M17_FRAME_LENGTH_BYTES];
rfData[0U] = TAG_DATA;
rfData[1U] = 0x00U;
// Generate the sync
CSync::addM17DataSync(rfData + 2U);
unsigned char lich[M17_LICH_FRAGMENT_LENGTH_BYTES];
m_netLICH.getFragment(lich, m_rfLICHn);
unsigned int frag1, frag2, frag3, frag4;
CM17Utils::splitFragmentLICH(lich, frag1, frag2, frag3, frag4);
// Add the Color Code and fragment number
frag4 |= (m_rfLICHn & 0x07U) << 4;
frag4 |= (m_colorCode & 0x1FU) << 7;
// Add Golay to the LICH fragment here
unsigned int lich1 = CGolay24128::encode24128(frag1);
unsigned int lich2 = CGolay24128::encode24128(frag2);
unsigned int lich3 = CGolay24128::encode24128(frag3);
unsigned int lich4 = CGolay24128::encode24128(frag4);
CM17Utils::combineFragmentLICHFEC(lich1, lich2, lich3, lich4, rfData + 2U + M17_SYNC_LENGTH_BYTES);
// Add the Convolution FEC
conv.encodeData(frame, rfData + 2U + M17_SYNC_LENGTH_BYTES + M17_LICH_FRAGMENT_FEC_LENGTH_BYTES);
// Calculate the BER
if (valid) {
unsigned int errors = 0U;
for (unsigned int i = 2U; i < (M17_FRAME_LENGTH_BYTES + 2U); i++)
errors += countBits(rfData[i] ^ data[i]);
LogDebug("M17, FN: %u, errs: %u/384 (%.1f%%)", m_rfFN, errors, float(errors) / 3.84F);
m_rfBits += M17_FRAME_LENGTH_BITS;
m_rfErrs += errors;
float ber = float(m_rfErrs) / float(m_rfBits);
m_display->writeM17BER(ber);
}
unsigned char temp[M17_FRAME_LENGTH_BYTES];
interleaver(rfData + 2U, temp);
decorrelator(rfData, data + 2U);
if (m_duplex)
writeQueueRF(rfData);
unsigned char netData[M17_LICH_LENGTH_BYTES + M17_FN_LENGTH_BYTES + M17_PAYLOAD_LENGTH_BYTES + M17_CRC_LENGTH_BYTES];
m_rfLICH.getNetwork(netData + 0U);
// Copy the FN and payload from the frame
::memcpy(netData + M17_LICH_LENGTH_BYTES - M17_CRC_LENGTH_BYTES, frame, M17_FN_LENGTH_BYTES + M17_PAYLOAD_LENGTH_BYTES);
// The CRC is added in the networking code
writeNetwork(netData);
m_rfFrames++;
m_rfLICHn++;
if (m_rfLICHn >= 6U)
m_rfLICHn = 0U;
// EOT?
if ((m_rfFN & 0x8000U) == 0x8000U) {
std::string source = m_rfLICH.getSource();
std::string dest = m_rfLICH.getDest();
if (m_rssi != 0U)
LogMessage("M17, received RF end of transmission from %s to %s, %.1f seconds, BER: %.1f%%, RSSI: -%u/-%u/-%u dBm", source.c_str(), dest.c_str(), float(m_rfFrames) / 25.0F, float(m_rfErrs * 100U) / float(m_rfBits), m_minRSSI, m_maxRSSI, m_aveRSSI / m_rssiCount);
else
LogMessage("M17, received RF end of transmission from %s to %s, %.1f seconds, BER: %.1f%%", source.c_str(), dest.c_str(), float(m_rfFrames) / 25.0F, float(m_rfErrs * 100U) / float(m_rfBits));
writeEndRF();
}
return true;
}
if (m_rfState == RS_RF_REJECTED && data[0U] == TAG_DATA) {
CM17Convolution conv;
unsigned char frame[M17_FN_LENGTH_BYTES + M17_PAYLOAD_LENGTH_BYTES + M17_CRC_LENGTH_BYTES];
conv.decodeData(data + 2U + M17_SYNC_LENGTH_BYTES + M17_LICH_FRAGMENT_FEC_LENGTH_BYTES, frame);
bool valid = CM17CRC::checkCRC(frame, M17_FN_LENGTH_BYTES + M17_PAYLOAD_LENGTH_BYTES + M17_CRC_LENGTH_BYTES);
if (valid) {
// Handle the EOT for rejected frames
unsigned int fn = (frame[0U] << 8) + (frame[1U] << 0);
if ((fn & 0x8000U) == 0x8000U)
writeEndRF();
}
return false;
}
return false;
}
unsigned int CM17Control::readModem(unsigned char* data)
{
assert(data != NULL);
if (m_queue.isEmpty())
return 0U;
unsigned char len = 0U;
m_queue.getData(&len, 1U);
m_queue.getData(data, len);
return len;
}
void CM17Control::writeEndRF()
{
m_rfState = RS_RF_LISTENING;
m_rfTimeoutTimer.stop();
m_rfLICH.reset();
if (m_netState == RS_NET_IDLE) {
m_display->clearM17();
if (m_network != NULL)
m_network->reset();
}
#if defined(DUMP_M17)
closeFile();
#endif
}
void CM17Control::writeEndNet()
{
m_netState = RS_NET_IDLE;
m_netTimeoutTimer.stop();
m_networkWatchdog.stop();
m_packetTimer.stop();
m_netLICH.reset();
m_display->clearM17();
if (m_network != NULL)
m_network->reset();
}
void CM17Control::writeNetwork()
{
unsigned char netData[100U];
bool exists = m_network->read(netData);
if (!exists)
return;
if (!m_enabled)
return;
if (m_rfState != RS_RF_LISTENING && m_netState == RS_NET_IDLE)
return;
m_networkWatchdog.start();
m_netLICH.setNetwork(netData);
if (!m_allowEncryption) {
bool ret = m_rfLICH.isNONCENull();
if (!ret)
return;
}
if (m_netState == RS_NET_IDLE) {
std::string source = m_netLICH.getSource();
std::string dest = m_netLICH.getDest();
unsigned char dataType = m_netLICH.getDataType();
switch (dataType) {
case 1U:
LogMessage("M17, received network data transmission from %s to %s", source.c_str(), dest.c_str());
m_netState = RS_NET_DATA;
break;
case 2U:
LogMessage("M17, received network voice transmission from %s to %s", source.c_str(), dest.c_str());
m_netState = RS_NET_AUDIO;
break;
case 3U:
LogMessage("M17, received network voice + data transmission from %s to %s", source.c_str(), dest.c_str());
m_netState = RS_NET_AUDIO;
break;
default:
LogMessage("M17, received network unknown transmission from %s to %s", source.c_str(), dest.c_str());
m_netState = RS_NET_DATA;
break;
}
m_display->writeM17(source.c_str(), dest.c_str(), "N");
m_netTimeoutTimer.start();
m_packetTimer.start();
m_elapsed.start();
m_netFrames = 0U;
m_netLICHn = 0U;
// Create a dummy start message
unsigned char start[M17_FRAME_LENGTH_BYTES + 2U];
start[0U] = TAG_HEADER;
start[1U] = 0x00U;
// Generate the sync
CSync::addM17HeaderSync(start + 2U);
unsigned char setup[M17_LICH_LENGTH_BYTES];
m_netLICH.getLinkSetup(setup);
// Add the convolution FEC
CM17Convolution conv;
conv.encodeLinkSetup(setup, start + 2U + M17_SYNC_LENGTH_BYTES);
unsigned char temp[M17_FRAME_LENGTH_BYTES];
interleaver(start + 2U, temp);
decorrelator(temp, start + 2U);
writeQueueNet(start);
}
unsigned char data[M17_FRAME_LENGTH_BYTES + 2U];
data[0U] = TAG_DATA;
data[1U] = 0x00U;
// Generate the sync
CSync::addM17DataSync(data + 2U);
m_netFrames++;
// Add the fragment LICH
unsigned char lich[M17_LICH_FRAGMENT_LENGTH_BYTES];
m_netLICH.getFragment(lich, m_netLICHn);
unsigned int frag1, frag2, frag3, frag4;
CM17Utils::splitFragmentLICH(lich, frag1, frag2, frag3, frag4);
// Add the Color Code and fragment number
frag4 |= (m_netLICHn & 0x07U) << 4;
frag4 |= (m_colorCode & 0x1FU) << 7;
// Add Golay to the LICH fragment here
unsigned int lich1 = CGolay24128::encode24128(frag1);
unsigned int lich2 = CGolay24128::encode24128(frag2);
unsigned int lich3 = CGolay24128::encode24128(frag3);
unsigned int lich4 = CGolay24128::encode24128(frag4);
CM17Utils::combineFragmentLICHFEC(lich1, lich2, lich3, lich4, data + 2U + M17_SYNC_LENGTH_BYTES);
// Add the FN and the data/audio
unsigned char payload[M17_FN_LENGTH_BYTES + M17_PAYLOAD_LENGTH_BYTES + M17_CRC_LENGTH_BYTES];
::memcpy(payload, netData + 28U, M17_FN_LENGTH_BYTES + M17_PAYLOAD_LENGTH_BYTES);
// Add the CRC
CM17CRC::encodeCRC(payload, M17_FN_LENGTH_BYTES + M17_PAYLOAD_LENGTH_BYTES + M17_CRC_LENGTH_BYTES);
// Add the Convolution FEC
CM17Convolution conv;
conv.encodeData(payload, data + 2U + M17_SYNC_LENGTH_BYTES + M17_LICH_FRAGMENT_FEC_LENGTH_BYTES);
unsigned char temp[M17_FRAME_LENGTH_BYTES];
interleaver(data + 2U, temp);
decorrelator(temp, data + 2U);
writeQueueNet(data);
m_netLICHn++;
if (m_netLICHn >= 6U)
m_netLICHn = 0U;
// EOT handling
uint16_t fn = (netData[28U] << 8) + (netData[29U] << 0);
if ((fn & 0x8000U) == 0x8000U) {
std::string source = m_netLICH.getSource();
std::string dest = m_netLICH.getDest();
LogMessage("M17, received network end of transmission from %s to %s, %.1f seconds", source.c_str(), dest.c_str(), float(m_netFrames) / 25.0F);
writeEndNet();
}
}
void CM17Control::clock(unsigned int ms)
{
if (m_network != NULL)
writeNetwork();
m_rfTimeoutTimer.clock(ms);
m_netTimeoutTimer.clock(ms);
if (m_netState == RS_NET_AUDIO) {
m_networkWatchdog.clock(ms);
if (m_networkWatchdog.hasExpired()) {
LogMessage("M17, network watchdog has expired, %.1f seconds", float(m_netFrames) / 25.0F);
writeEndNet();
}
}
}
void CM17Control::writeQueueRF(const unsigned char *data)
{
assert(data != NULL);
if (m_netState != RS_NET_IDLE)
return;
if (m_rfTimeoutTimer.isRunning() && m_rfTimeoutTimer.hasExpired())
return;
unsigned char len = M17_FRAME_LENGTH_BYTES + 2U;
unsigned int space = m_queue.freeSpace();
if (space < (len + 1U)) {
LogError("M17, overflow in the M17 RF queue");
return;
}
m_queue.addData(&len, 1U);
m_queue.addData(data, len);
}
void CM17Control::writeQueueNet(const unsigned char *data)
{
assert(data != NULL);
if (m_netTimeoutTimer.isRunning() && m_netTimeoutTimer.hasExpired())
return;
unsigned char len = M17_FRAME_LENGTH_BYTES + 2U;
unsigned int space = m_queue.freeSpace();
if (space < (len + 1U)) {
LogError("M17, overflow in the M17 RF queue");
return;
}
m_queue.addData(&len, 1U);
m_queue.addData(data, len);
}
void CM17Control::writeNetwork(const unsigned char *data)
{
assert(data != NULL);
if (m_network == NULL)
return;
if (m_rfTimeoutTimer.isRunning() && m_rfTimeoutTimer.hasExpired())
return;
m_network->write(data);
}
void CM17Control::interleaver(const unsigned char* in, unsigned char* out) const
{
assert(in != NULL);
assert(out != NULL);
for (unsigned int i = 0U; i < (M17_FRAME_LENGTH_BITS - M17_SYNC_LENGTH_BITS); i++) {
unsigned int n1 = i + M17_SYNC_LENGTH_BITS;
bool b = READ_BIT(in, n1) != 0U;
unsigned int n2 = INTERLEAVER[i] + M17_SYNC_LENGTH_BITS;
WRITE_BIT(out, n2, b);
}
}
void CM17Control::decorrelator(const unsigned char* in, unsigned char* out) const
{
assert(in != NULL);
assert(out != NULL);
for (unsigned int i = M17_SYNC_LENGTH_BYTES; i < M17_FRAME_LENGTH_BYTES; i++) {
out[i] = in[i] ^ SCRAMBLER[i];
}
}
bool CM17Control::checkCallsign(const std::string& callsign) const
{
size_t len = m_callsign.size();
return m_callsign.compare(0U, len, callsign, 0U, len) == 0;
}
bool CM17Control::openFile()
{
if (m_fp != NULL)
return true;
time_t t;
::time(&t);
struct tm* tm = ::localtime(&t);
char name[100U];
::sprintf(name, "M17_%04d%02d%02d_%02d%02d%02d.ambe", tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec);
m_fp = ::fopen(name, "wb");
if (m_fp == NULL)
return false;
::fwrite("M17", 1U, 3U, m_fp);
return true;
}
bool CM17Control::writeFile(const unsigned char* data)
{
if (m_fp == NULL)
return false;
::fwrite(data, 1U, M17_FRAME_LENGTH_BYTES, m_fp);
return true;
}
void CM17Control::closeFile()
{
if (m_fp != NULL) {
::fclose(m_fp);
m_fp = NULL;
}
}
bool CM17Control::isBusy() const
{
return m_rfState != RS_RF_LISTENING || m_netState != RS_NET_IDLE;
}
void CM17Control::enable(bool enabled)
{
if (!enabled && m_enabled) {
m_queue.clear();
// Reset the RF section
m_rfState = RS_RF_LISTENING;
m_rfTimeoutTimer.stop();
// Reset the networking section
m_netState = RS_NET_IDLE;
m_netTimeoutTimer.stop();
m_networkWatchdog.stop();
m_packetTimer.stop();
}
m_enabled = enabled;
}
unsigned int CM17Control::countBits(unsigned char byte)
{
unsigned int count = 0U;
const unsigned char* p = &byte;
for (unsigned int i = 0U; i < 8U; i++) {
if (READ_BIT(p, i) != 0U)
count++;
}
return count;
}

View File

@ -1,104 +0,0 @@
/*
* Copyright (C) 2015-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(M17Control_H)
#define M17Control_H
#include "RSSIInterpolator.h"
#include "M17Network.h"
#include "M17Defines.h"
#include "RingBuffer.h"
#include "StopWatch.h"
#include "M17LICH.h"
#include "Display.h"
#include "Defines.h"
#include "Timer.h"
#include "Modem.h"
#include <string>
class CM17Control {
public:
CM17Control(const std::string& callsign, unsigned int colorCode, 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_colorCode;
bool m_selfOnly;
bool m_allowEncryption;
CM17Network* m_network;
CDisplay* m_display;
bool m_duplex;
CRingBuffer<unsigned char> m_queue;
RPT_RF_STATE m_rfState;
RPT_NET_STATE m_netState;
CTimer m_rfTimeoutTimer;
CTimer m_netTimeoutTimer;
CTimer m_packetTimer;
CTimer m_networkWatchdog;
CStopWatch m_elapsed;
unsigned int m_rfFrames;
unsigned int m_netFrames;
unsigned int m_rfFN;
unsigned int m_rfErrs;
unsigned int m_rfBits;
CM17LICH m_rfLICH;
unsigned int m_rfLICHn;
CM17LICH m_netLICH;
unsigned int m_netLICHn;
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;
void writeQueueRF(const unsigned char* data);
void writeQueueNet(const unsigned char* data);
void writeNetwork(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;
unsigned int countBits(unsigned char byte);
void writeEndRF();
void writeEndNet();
bool openFile();
bool writeFile(const unsigned char* data);
void closeFile();
};
#endif

View File

@ -1,275 +0,0 @@
/*
* Copyright (C) 2009-2016,2018,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.
*/
#include "M17Convolution.h"
#include <cstdio>
#include <cassert>
#include <cstring>
#include <cstdlib>
const unsigned int PUNCTURE_LIST_LINK_SETUP[] = {
3U, 6U, 9U, 12U, 19U, 22U, 25U, 28U, 35U, 38U, 41U, 44U, 51U, 54U, 57U, 64U, 67U, 70U, 73U, 80U, 83U, 86U, 89U, 96U, 99U, 102U,
105U, 112U, 115U, 118U, 125U, 128U, 131U, 134U, 141U, 144U, 147U, 150U, 157U, 160U, 163U, 166U, 173U, 176U, 179U, 186U, 189U,
192U, 195U, 202U, 205U, 208U, 211U, 218U, 221U, 224U, 227U, 234U, 237U, 240U, 247U, 250U, 253U, 256U, 263U, 266U, 269U, 272U,
279U, 282U, 285U, 288U, 295U, 298U, 301U, 308U, 311U, 314U, 317U, 324U, 327U, 330U, 333U, 340U, 343U, 346U, 349U, 356U, 359U,
362U, 369U, 372U, 375U, 378U, 385U, 388U, 391U, 394U, 401U, 404U, 407U, 410U, 417U, 420U, 423U, 430U, 433U, 436U, 439U, 446U,
449U, 452U, 455U, 462U, 465U, 468U, 471U, 478U, 481U, 484U};
const unsigned int PUNCTURE_LIST_DATA[] = {
5U, 11U, 17U, 20U, 23U, 29U, 35U, 46U, 52U, 58U, 61U, 64U, 70U, 76U, 87U, 93U, 99U, 102U, 105U, 111U, 117U, 128U, 134U, 140U,
143U, 146U, 152U, 158U, 169U, 175U, 181U, 184U, 187U, 193U, 199U, 210U, 216U, 222U, 225U, 228U, 234U, 240U, 251U, 257U, 263U,
266U, 269U, 275U, 281U, 292U, 298U, 304U, 307U, 310U, 316U, 322U};
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(NULL),
m_metrics2(NULL),
m_oldMetrics(NULL),
m_newMetrics(NULL),
m_decisions(NULL),
m_dp(NULL)
{
m_metrics1 = new uint16_t[16U];
m_metrics2 = new uint16_t[16U];
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 != NULL);
assert(out != NULL);
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 != NULL);
assert(out != NULL);
unsigned char temp1[21U];
::memset(temp1, 0x00U, 21U);
::memcpy(temp1, in, 20U);
unsigned char temp2[41U];
encode(temp1, temp2, 164U);
unsigned int n = 0U;
unsigned int index = 0U;
for (unsigned int i = 0U; i < 328U; i++) {
if (i != PUNCTURE_LIST_DATA[index]) {
bool b = READ_BIT1(temp2, i);
WRITE_BIT1(out, n, b);
n++;
} else {
index++;
}
}
}
void CM17Convolution::decodeLinkSetup(const unsigned char* in, unsigned char* out)
{
assert(in != NULL);
assert(out != NULL);
uint8_t temp[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;
}
for (unsigned int i = 0U; i < 8U; i++)
temp[n++] = 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);
}
chainback(out, 240U);
}
void CM17Convolution::decodeData(const unsigned char* in, unsigned char* out)
{
assert(in != NULL);
assert(out != NULL);
uint8_t temp[350U];
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;
}
for (unsigned int i = 0U; i < 8U; i++)
temp[n++] = 0U;
start();
n = 0U;
for (unsigned int i = 0U; i < 164U; i++) {
uint8_t s0 = temp[n++];
uint8_t s1 = temp[n++];
decode(s0, s1);
}
chainback(out, 160U);
}
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;
}
void CM17Convolution::chainback(unsigned char* out, unsigned int nBits)
{
assert(out != NULL);
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);
}
}
void CM17Convolution::encode(const unsigned char* in, unsigned char* out, unsigned int nBits) const
{
assert(in != NULL);
assert(out != NULL);
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,50 +0,0 @@
/*
* Copyright (C) 2015,2016,2018,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(M17Convolution_H)
#define M17Convolution_H
#include <cstdint>
class CM17Convolution {
public:
CM17Convolution();
~CM17Convolution();
void decodeLinkSetup(const unsigned char* in, unsigned char* out);
void 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);
void chainback(unsigned char* out, unsigned int nBits);
void encode(const unsigned char* in, unsigned char* out, unsigned int nBits) const;
};
#endif

View File

@ -1,58 +0,0 @@
/*
* Copyright (C) 2016,2017,2018,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(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_HEADER_SYNC_BYTES[] = {0x5DU, 0xDDU};
const unsigned char M17_DATA_SYNC_BYTES[] = {0xDDU, 0xDDU};
const unsigned int M17_SYNC_LENGTH_BITS = 16U;
const unsigned int M17_SYNC_LENGTH_BYTES = M17_SYNC_LENGTH_BITS / 8U;
const unsigned int M17_LICH_LENGTH_BITS = 240U;
const unsigned int M17_LICH_LENGTH_BYTES = M17_LICH_LENGTH_BITS / 8U;
const unsigned int M17_LICH_FRAGMENT_LENGTH_BITS = M17_LICH_LENGTH_BITS / 6U;
const unsigned int M17_LICH_FRAGMENT_LENGTH_BYTES = M17_LICH_FRAGMENT_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_NONCE_LENGTH_BITS = 112U;
const unsigned int M17_NONCE_LENGTH_BYTES = M17_NONCE_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[] = {0x01U, 0x00U, 0x04U, 0x00U, 0x25U, 0x75U, 0xDDU, 0xF2U};
#endif

View File

@ -1,143 +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.
*/
#include "M17LICH.h"
#include "M17Utils.h"
#include "M17Defines.h"
#include "M17CRC.h"
#include <cassert>
#include <cstring>
CM17LICH::CM17LICH() :
m_lich(NULL),
m_valid(false)
{
m_lich = new unsigned char[M17_LICH_LENGTH_BYTES];
}
CM17LICH::~CM17LICH()
{
delete[] m_lich;
}
void CM17LICH::getNetwork(unsigned char* data) const
{
assert(data != NULL);
::memcpy(data, m_lich, M17_LICH_LENGTH_BYTES);
}
void CM17LICH::setNetwork(const unsigned char* data)
{
assert(data != NULL);
::memcpy(m_lich, data, M17_LICH_LENGTH_BYTES);
m_valid = true;
}
std::string CM17LICH::getSource() const
{
std::string callsign;
CM17Utils::decodeCallsign(m_lich + 6U, callsign);
return callsign;
}
void CM17LICH::setSource(const std::string& callsign)
{
CM17Utils::encodeCallsign(callsign, m_lich + 6U);
}
std::string CM17LICH::getDest() const
{
std::string callsign;
CM17Utils::decodeCallsign(m_lich + 0U, callsign);
return callsign;
}
void CM17LICH::setDest(const std::string& callsign)
{
CM17Utils::encodeCallsign(callsign, m_lich + 0U);
}
unsigned char CM17LICH::getDataType() const
{
return (m_lich[13U] >> 1) & 0x03U;
}
void CM17LICH::setDataType(unsigned char type)
{
m_lich[13U] &= 0xF9U;
m_lich[13U] |= (type << 1) & 0x06U;
}
bool CM17LICH::isNONCENull() const
{
return ::memcmp(m_lich + 14U, M17_NULL_NONCE, M17_NONCE_LENGTH_BYTES) == 0;
}
void CM17LICH::reset()
{
::memset(m_lich, 0x00U, 30U);
m_valid = false;
}
bool CM17LICH::isValid() const
{
return m_valid;
}
void CM17LICH::getLinkSetup(unsigned char* data) const
{
assert(data != NULL);
::memcpy(data, m_lich, M17_LICH_LENGTH_BYTES);
CM17CRC::encodeCRC(data, M17_LICH_LENGTH_BYTES);
}
void CM17LICH::setLinkSetup(const unsigned char* data)
{
assert(data != NULL);
::memcpy(m_lich, data, M17_LICH_LENGTH_BYTES);
m_valid = CM17CRC::checkCRC(m_lich, M17_LICH_LENGTH_BYTES);
}
void CM17LICH::getFragment(unsigned char* data, unsigned int n) const
{
assert(data != NULL);
CM17CRC::encodeCRC(m_lich, M17_LICH_LENGTH_BYTES);
::memcpy(data, m_lich + (n * M17_LICH_FRAGMENT_LENGTH_BYTES), M17_LICH_FRAGMENT_LENGTH_BYTES);
}
void CM17LICH::setFragment(const unsigned char* data, unsigned int n)
{
assert(data != NULL);
::memcpy(m_lich + (n * M17_LICH_FRAGMENT_LENGTH_BYTES), data, M17_LICH_FRAGMENT_LENGTH_BYTES);
m_valid = CM17CRC::checkCRC(m_lich, M17_LICH_LENGTH_BYTES);
}

View File

@ -1,57 +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(M17LICH_H)
#define M17LICH_H
#include <string>
class CM17LICH {
public:
CM17LICH();
~CM17LICH();
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 getDataType() const;
void setDataType(unsigned char type);
bool isNONCENull() const;
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);
private:
unsigned char* m_lich;
bool m_valid;
};
#endif

View File

@ -1,210 +0,0 @@
/*
* Copyright (C) 2009-2014,2016,2019,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.
*/
#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(unsigned int localPort, const std::string& gwyAddress, unsigned int gwyPort, bool debug) :
m_socket(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(gwyAddress, gwyPort, 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 != NULL);
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 data 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 Data 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 != NULL);
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)
m_buffer.clear();
m_enabled = enabled;
}
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 data transmitted", buffer, 4U);
m_socket.write(buffer, 4U, m_addr, m_addrLen);
}

View File

@ -1,64 +0,0 @@
/*
* Copyright (C) 2009-2014,2016,2018,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.
*/
#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(unsigned int localPort, const std::string& gwyAddress, unsigned int gwyPort, 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);
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,209 +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.
*/
#include "M17Utils.h"
#include "M17Defines.h"
#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 != NULL);
unsigned int len = callsign.size();
if (len > 9U)
len = 9U;
uint64_t enc = 0ULL;
for (int i = len - 1; i >= 0; i--) {
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 != NULL);
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 >= 262144000000000ULL) // 40^9
return;
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 != NULL);
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 != NULL);
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 != NULL);
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 != NULL);
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

@ -44,10 +44,9 @@ Time=24
[Modem]
# Port=/dev/ttyACM0
Port=/dev/ttyAMA0
# Port=\\.\COM4
# Port=/dev/ttyAMA0
Port=\\.\COM4
Protocol=uart
Speed=460800
# Address=0x22
TXInvert=1
RXInvert=0
@ -67,10 +66,8 @@ RFLevel=100
# YSFTXLevel=50
# P25TXLevel=50
# NXDNTXLevel=50
# M17TXLevel-50
# POCSAGTXLevel=50
# FMTXLevel=50
# AX25TXLevel=50
RSSIMappingFile=RSSI.dat
UseCOSAsLockout=0
Trace=0
@ -83,6 +80,11 @@ RemotePort=40094
LocalPort=40095
# SendFrameType=0
[UMP]
Enable=0
# Port=\\.\COM4
Port=/dev/ttyACM1
[D-Star]
Enable=1
Module=C
@ -138,13 +140,6 @@ RemoteGateway=0
TXHang=5
# ModeHang=10
[M17]
Enable=1
ColorCode=3
SelfOnly=0
TXHang=5
# ModeHang=10
[POCSAG]
Enable=1
Frequency=439987500
@ -179,22 +174,9 @@ KerchunkTime=0
HangTime=7
AccessMode=1
COSInvert=0
NoiseSquelch=0
SquelchThreshold=30
# SquelchHighThreshold=30
# SquelchLowThreshold=20
RFAudioBoost=1
MaxDevLevel=90
ExtAudioBoost=1
# ModeHang=10
[AX.25]
Enable=1
TXDelay=300
RXTwist=6
SlotTime=30
PPersist=128
Trace=1
[D-Star Network]
Enable=1
@ -247,14 +229,6 @@ GatewayPort=14020
# ModeHang=3
Debug=0
[M17 Network]
Enable=1
GatewayAddress=127.0.0.1
GatewayPort=17010
LocalPort=17011
# ModeHang=3
Debug=0
[POCSAG Network]
Enable=1
LocalAddress=127.0.0.1
@ -264,22 +238,6 @@ GatewayPort=4800
# ModeHang=3
Debug=0
[FM Network]
Enable=1
LocalAddress=127.0.0.1
LocalPort=3810
GatewayAddress=127.0.0.1
GatewayPort=4810
SampleRate=8000
# ModeHang=3
Debug=0
[AX.25 Network]
Enable=1
Port=/dev/ttyp7
Speed=9600
Debug=0
[TFT Serial]
# Port=modem
Port=/dev/ttyAMA0

File diff suppressed because it is too large Load Diff

View File

@ -23,27 +23,22 @@
#include "POCSAGNetwork.h"
#include "POCSAGControl.h"
#include "DStarNetwork.h"
#include "AX25Network.h"
#include "NXDNNetwork.h"
#include "DStarControl.h"
#include "AX25Control.h"
#include "DMRControl.h"
#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"
#include "Display.h"
#include "Timer.h"
#include "Modem.h"
#include "Conf.h"
#include "UMP.h"
#include <string>
@ -58,42 +53,33 @@ public:
private:
CConf m_conf;
IModem* m_modem;
CModem* m_modem;
CDStarControl* m_dstar;
CDMRControl* m_dmr;
CYSFControl* m_ysf;
CP25Control* m_p25;
CNXDNControl* m_nxdn;
CM17Control* m_m17;
CPOCSAGControl* m_pocsag;
CFMControl* m_fm;
CAX25Control* m_ax25;
CDStarNetwork* m_dstarNetwork;
IDMRNetwork* m_dmrNetwork;
CYSFNetwork* m_ysfNetwork;
CP25Network* m_p25Network;
INXDNNetwork* m_nxdnNetwork;
CM17Network* m_m17Network;
CPOCSAGNetwork* m_pocsagNetwork;
CFMNetwork* m_fmNetwork;
CAX25Network* m_ax25Network;
CDisplay* m_display;
CUMP* m_ump;
unsigned char m_mode;
unsigned int m_dstarRFModeHang;
unsigned int m_dmrRFModeHang;
unsigned int m_ysfRFModeHang;
unsigned int m_p25RFModeHang;
unsigned int m_nxdnRFModeHang;
unsigned int m_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;
CTimer m_dmrTXTimer;
CTimer m_cwIdTimer;
@ -104,10 +90,8 @@ private:
bool m_ysfEnabled;
bool m_p25Enabled;
bool m_nxdnEnabled;
bool m_m17Enabled;
bool m_pocsagEnabled;
bool m_fmEnabled;
bool m_ax25Enabled;
unsigned int m_cwIdTime;
CDMRLookup* m_dmrLookup;
CNXDNLookup* m_nxdnLookup;
@ -126,10 +110,7 @@ private:
bool createYSFNetwork();
bool createP25Network();
bool createNXDNNetwork();
bool createM17Network();
bool createPOCSAGNetwork();
bool createFMNetwork();
bool createAX25Network();
void remoteControl();
void processModeCommand(unsigned char mode, unsigned int timeout);

View File

@ -153,9 +153,6 @@
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="AMBEFEC.h" />
<ClInclude Include="AX25Control.h" />
<ClInclude Include="AX25Defines.h" />
<ClInclude Include="AX25Network.h" />
<ClInclude Include="BCH.h" />
<ClInclude Include="BPTC19696.h" />
<ClInclude Include="CASTInfo.h" />
@ -186,22 +183,13 @@
<ClInclude Include="DStarHeader.h" />
<ClInclude Include="DStarNetwork.h" />
<ClInclude Include="DStarSlowData.h" />
<ClInclude Include="FMControl.h" />
<ClInclude Include="FMNetwork.h" />
<ClInclude Include="Golay2087.h" />
<ClInclude Include="Golay24128.h" />
<ClInclude Include="Hamming.h" />
<ClInclude Include="DMRLookup.h" />
<ClInclude Include="IIRDirectForm1Filter.h" />
<ClInclude Include="I2CController.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="M17LICH.h" />
<ClInclude Include="M17Network.h" />
<ClInclude Include="M17Utils.h" />
<ClInclude Include="MMDVMHost.h" />
<ClInclude Include="Modem.h" />
<ClInclude Include="ModemSerialPort.h" />
@ -235,7 +223,6 @@
<ClInclude Include="POCSAGControl.h" />
<ClInclude Include="POCSAGDefines.h" />
<ClInclude Include="POCSAGNetwork.h" />
<ClInclude Include="PseudoTTYController.h" />
<ClInclude Include="QR1676.h" />
<ClInclude Include="RemoteControl.h" />
<ClInclude Include="RingBuffer.h" />
@ -244,15 +231,16 @@
<ClInclude Include="RSSIInterpolator.h" />
<ClInclude Include="NXDNSACCH.h" />
<ClInclude Include="SerialController.h" />
<ClInclude Include="SerialModem.h" />
<ClInclude Include="SerialPort.h" />
<ClInclude Include="SHA256.h" />
<ClInclude Include="StopWatch.h" />
<ClInclude Include="Sync.h" />
<ClInclude Include="TFTSerial.h" />
<ClInclude Include="TFTSurenoo.h" />
<ClInclude Include="Thread.h" />
<ClInclude Include="Timer.h" />
<ClInclude Include="UDPSocket.h" />
<ClInclude Include="UMP.h" />
<ClInclude Include="UserDB.h" />
<ClInclude Include="UserDBentry.h" />
<ClInclude Include="Utils.h" />
@ -266,8 +254,6 @@
</ItemGroup>
<ItemGroup>
<ClCompile Include="AMBEFEC.cpp" />
<ClCompile Include="AX25Control.cpp" />
<ClCompile Include="AX25Network.cpp" />
<ClCompile Include="BCH.cpp" />
<ClCompile Include="BPTC19696.cpp" />
<ClCompile Include="CASTInfo.cpp" />
@ -296,20 +282,12 @@
<ClCompile Include="DStarHeader.cpp" />
<ClCompile Include="DStarNetwork.cpp" />
<ClCompile Include="DStarSlowData.cpp" />
<ClCompile Include="FMControl.cpp" />
<ClCompile Include="FMNetwork.cpp" />
<ClCompile Include="Golay2087.cpp" />
<ClCompile Include="Golay24128.cpp" />
<ClCompile Include="Hamming.cpp" />
<ClCompile Include="IIRDirectForm1Filter.cpp" />
<ClCompile Include="I2CController.cpp" />
<ClCompile Include="LCDproc.cpp" />
<ClCompile Include="Log.cpp" />
<ClCompile Include="M17Control.cpp" />
<ClCompile Include="M17Convolution.cpp" />
<ClCompile Include="M17CRC.cpp" />
<ClCompile Include="M17LICH.cpp" />
<ClCompile Include="M17Network.cpp" />
<ClCompile Include="M17Utils.cpp" />
<ClCompile Include="MMDVMHost.cpp" />
<ClCompile Include="Modem.cpp" />
<ClCompile Include="ModemSerialPort.cpp" />
@ -341,22 +319,22 @@
<ClCompile Include="P25Utils.cpp" />
<ClCompile Include="POCSAGControl.cpp" />
<ClCompile Include="POCSAGNetwork.cpp" />
<ClCompile Include="PseudoTTYController.cpp" />
<ClCompile Include="QR1676.cpp" />
<ClCompile Include="RemoteControl.cpp" />
<ClCompile Include="RS129.cpp" />
<ClCompile Include="RS241213.cpp" />
<ClCompile Include="RSSIInterpolator.cpp" />
<ClCompile Include="SerialController.cpp" />
<ClCompile Include="SerialModem.cpp" />
<ClCompile Include="SerialPort.cpp" />
<ClCompile Include="SHA256.cpp" />
<ClCompile Include="StopWatch.cpp" />
<ClCompile Include="Sync.cpp" />
<ClCompile Include="TFTSerial.cpp" />
<ClCompile Include="TFTSurenoo.cpp" />
<ClCompile Include="Thread.cpp" />
<ClCompile Include="Timer.cpp" />
<ClCompile Include="UDPSocket.cpp" />
<ClCompile Include="UMP.cpp" />
<ClCompile Include="UserDB.cpp" />
<ClCompile Include="UserDBentry.cpp" />
<ClCompile Include="Utils.cpp" />

View File

@ -80,6 +80,9 @@
<ClInclude Include="StopWatch.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="TFTSerial.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Timer.h">
<Filter>Header Files</Filter>
</ClInclude>
@ -212,6 +215,9 @@
<ClInclude Include="LCDproc.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="UMP.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="RSSIInterpolator.h">
<Filter>Header Files</Filter>
</ClInclude>
@ -266,6 +272,9 @@
<ClInclude Include="POCSAGDefines.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="I2CController.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="NullModem.h">
<Filter>Header Files</Filter>
</ClInclude>
@ -284,57 +293,12 @@
<ClInclude Include="UserDBentry.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="AX25Control.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="AX25Network.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="NXDNIcomNetwork.h">
<Filter>Header Files</Filter>
</ClInclude>
<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="M17LICH.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>
<ClInclude Include="FMNetwork.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="FMControl.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="IIRDirectForm1Filter.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="PseudoTTYController.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="SerialModem.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="DMRDirectNetwork.h">
<Filter>Header Files</Filter>
</ClInclude>
@ -403,6 +367,9 @@
<ClCompile Include="StopWatch.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="TFTSerial.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Timer.cpp">
<Filter>Source Files</Filter>
</ClCompile>
@ -526,6 +493,9 @@
<ClCompile Include="LCDproc.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="UMP.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="RSSIInterpolator.cpp">
<Filter>Source Files</Filter>
</ClCompile>
@ -574,6 +544,9 @@
<ClCompile Include="POCSAGControl.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="I2CController.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="NullModem.cpp">
<Filter>Source Files</Filter>
</ClCompile>
@ -592,51 +565,12 @@
<ClCompile Include="UserDBentry.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="AX25Control.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="AX25Network.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="NXDNIcomNetwork.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<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="M17LICH.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="M17Convolution.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="FMNetwork.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="FMControl.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="IIRDirectForm1Filter.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="PseudoTTYController.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="SerialModem.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="DMRDirectNetwork.cpp">
<Filter>Source Files</Filter>
</ClCompile>

View File

@ -2,20 +2,19 @@
CC = cc
CXX = c++
CFLAGS = -g -O3 -Wall -std=c++0x -pthread -DHAVE_LOG_H -I/usr/local/include
LIBS = -lpthread -lsamplerate -lutil
LDFLAGS = -g -L/usr/local/lib
CFLAGS = -g -O3 -Wall -std=c++0x -pthread -DHAVE_LOG_H
LIBS = -lpthread
LDFLAGS = -g
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 M17LICH.o M17Network.o M17Utils.o MMDVMHost.o \
Modem.o ModemSerialPort.o Mutex.o NetworkInfo.o Nextion.o NullDisplay.o NullModem.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 POCSAGNetwork.o QR1676.o RemoteControl.o RS129.o \
RS241213.o RSSIInterpolator.o SerialController.o SerialModem.o SerialPort.o StopWatch.o Sync.o SHA256.o TFTSurenoo.o Thread.o Timer.o UDPSocket.o \
UserDB.o UserDBentry.o Utils.o YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o
AMBEFEC.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 Golay2087.o Golay24128.o Hamming.o I2CController.o LCDproc.o Log.o \
MMDVMHost.o Modem.o ModemSerialPort.o Mutex.o NetworkInfo.o Nextion.o NullDisplay.o NullModem.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 POCSAGControl.o POCSAGNetwork.o QR1676.o RemoteControl.o RS129.o RS241213.o \
RSSIInterpolator.o SerialController.o SerialPort.o StopWatch.o Sync.o SHA256.o TFTSerial.o TFTSurenoo.o Thread.o Timer.o UDPSocket.o UMP.o UserDB.o \
UserDBentry.o Utils.o YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o
all: MMDVMHost RemoteCommand
@ -28,33 +27,10 @@ RemoteCommand: Log.o RemoteCommand.o UDPSocket.o
%.o: %.cpp
$(CXX) $(CFLAGS) -c -o $@ $<
.PHONY install:
install: all
install:
install -m 755 MMDVMHost /usr/local/bin/
install -m 755 RemoteCommand /usr/local/bin/
.PHONY install-service:
install-service: install /etc/MMDVM.ini
@useradd --user-group -M --system mmdvm --shell /bin/false || true
@usermod --groups dialout --append mmdvm || true
@mkdir /var/log/mmdvm || true
@chown mmdvm:mmdvm /var/log/mmdvm
@cp ./linux/systemd/mmdvmhost.service /lib/systemd/system/
@systemctl enable mmdvmhost.service
/etc/MMDVM.ini:
@cp -n MMDVM.ini /etc/MMDVM.ini
@sed -i 's/FilePath=./FilePath=\/var\/log\/mmdvm\//' /etc/MMDVM.ini
@sed -i 's/Daemon=0/Daemon=1/' /etc/MMDVM.ini
@chown mmdvm:mmdvm /etc/MMDVM.ini
.PHONY uninstall-service:
uninstall-service:
@systemctl stop mmdvmhost.service || true
@systemctl disable mmdvmhost.service || true
@rm -f /usr/local/bin/MMDVMHost || true
@rm -f /lib/systemd/system/mmdvmhost.service || true
clean:
$(RM) MMDVMHost RemoteCommand *.o *.d *.bak *~ GitVersion.h

View File

@ -3,19 +3,19 @@
CC = cc
CXX = c++
CFLAGS = -g -O3 -Wall -std=c++0x -pthread -DHAVE_LOG_H -DRASPBERRY_PI -I/usr/local/include
LIBS = -lwiringPi -lwiringPiDev -lpthread -lsamplerate -lutil
LIBS = -lwiringPi -lwiringPiDev -lpthread
LDFLAGS = -g -L/usr/local/lib
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 M17LICH.o M17Network.o M17Utils.o MMDVMHost.o \
Modem.o ModemSerialPort.o Mutex.o NetworkInfo.o Nextion.o NullDisplay.o NullModem.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 POCSAGNetwork.o QR1676.o RemoteControl.o RS129.o \
RS241213.o RSSIInterpolator.o SerialController.o SerialModem.o SerialPort.o StopWatch.o Sync.o SHA256.o TFTSurenoo.o Thread.o Timer.o UDPSocket.o \
UserDB.o UserDBentry.o Utils.o YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o
AMBEFEC.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 Golay2087.o Golay24128.o Hamming.o I2CController.o LCDproc.o Log.o \
MMDVMHost.o Modem.o ModemSerialPort.o Mutex.o NetworkInfo.o Nextion.o NullDisplay.o NullModem.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 POCSAGControl.o POCSAGNetwork.o QR1676.o RemoteControl.o RS129.o RS241213.o \
RSSIInterpolator.o SerialController.o SerialPort.o StopWatch.o Sync.o SHA256.o TFTSerial.o TFTSurenoo.o Thread.o Timer.o UDPSocket.o UMP.o UserDB.o \
UserDBentry.o Utils.o YSFControl.o YSFConvolution.o \
YSFFICH.o YSFNetwork.o YSFPayload.o
all: MMDVMHost RemoteCommand
@ -28,33 +28,10 @@ RemoteCommand: Log.o RemoteCommand.o UDPSocket.o
%.o: %.cpp
$(CXX) $(CFLAGS) -c -o $@ $<
.PHONY install:
install: all
install:
install -m 755 MMDVMHost /usr/local/bin/
install -m 755 RemoteCommand /usr/local/bin/
.PHONY install-service:
install-service: install /etc/MMDVM.ini
@useradd --user-group -M --system mmdvm --shell /bin/false || true
@usermod --groups dialout --append mmdvm || true
@mkdir /var/log/mmdvm || true
@chown mmdvm:mmdvm /var/log/mmdvm
@cp ./linux/systemd/mmdvmhost.service /lib/systemd/system/
@systemctl enable mmdvmhost.service
/etc/MMDVM.ini:
@cp -n MMDVM.ini /etc/MMDVM.ini
@sed -i 's/FilePath=./FilePath=\/var\/log\/mmdvm\//' /etc/MMDVM.ini
@sed -i 's/Daemon=0/Daemon=1/' /etc/MMDVM.ini
@chown mmdvm:mmdvm /etc/MMDVM.ini
.PHONY uninstall-service:
uninstall-service:
@systemctl stop mmdvmhost.service || true
@systemctl disable mmdvmhost.service || true
@rm -f /usr/local/bin/MMDVMHost || true
@rm -f /lib/systemd/system/mmdvmhost.service || true
clean:
$(RM) MMDVMHost RemoteCommand *.o *.d *.bak *~ GitVersion.h

View File

@ -4,19 +4,18 @@
CC = cc
CXX = c++
CFLAGS = -g -O3 -Wall -std=c++0x -pthread -DHAVE_LOG_H -DHD44780 -DADAFRUIT_DISPLAY -I/usr/local/include
LIBS = -lwiringPi -lwiringPiDev -lpthread -lsamplerate -lutil
LIBS = -lwiringPi -lwiringPiDev -lpthread
LDFLAGS = -g -L/usr/local/lib
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 M17LICH.o M17Network.o M17Utils.o \
AMBEFEC.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 Golay2087.o Golay24128.o Hamming.o HD44780.o I2CController.o LCDproc.o Log.o \
MMDVMHost.o Modem.o ModemSerialPort.o Mutex.o NetworkInfo.o Nextion.o NullDisplay.o NullModem.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 POCSAGNetwork.o QR1676.o \
RemoteControl.o RS129.o RS241213.o RSSIInterpolator.o SerialController.o SerialModem.o SerialPort.o StopWatch.o Sync.o SHA256.o TFTSurenoo.o Thread.o \
Timer.o UDPSocket.o UserDB.o UserDBentry.o Utils.o YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o
P25Data.o P25LowSpeedData.o P25Network.o P25NID.o P25Trellis.o P25Utils.o POCSAGControl.o POCSAGNetwork.o QR1676.o RemoteControl.o RS129.o RS241213.o \
RSSIInterpolator.o SerialController.o SerialPort.o StopWatch.o Sync.o SHA256.o TFTSerial.o TFTSurenoo.o Thread.o Timer.o UDPSocket.o UMP.o UserDB.o \
UserDBentry.o Utils.o YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o
all: MMDVMHost RemoteCommand
@ -29,33 +28,10 @@ RemoteCommand: Log.o RemoteCommand.o UDPSocket.o
%.o: %.cpp
$(CXX) $(CFLAGS) -c -o $@ $<
.PHONY install:
install: all
install:
install -m 755 MMDVMHost /usr/local/bin/
install -m 755 RemoteCommand /usr/local/bin/
.PHONY install-service:
install-service: install /etc/MMDVM.ini
@useradd --user-group -M --system mmdvm --shell /bin/false || true
@usermod --groups dialout --append mmdvm || true
@mkdir /var/log/mmdvm || true
@chown mmdvm:mmdvm /var/log/mmdvm
@cp ./linux/systemd/mmdvmhost.service /lib/systemd/system/
@systemctl enable mmdvmhost.service
/etc/MMDVM.ini:
@cp -n MMDVM.ini /etc/MMDVM.ini
@sed -i 's/FilePath=./FilePath=\/var\/log\/mmdvm\//' /etc/MMDVM.ini
@sed -i 's/Daemon=0/Daemon=1/' /etc/MMDVM.ini
@chown mmdvm:mmdvm /etc/MMDVM.ini
.PHONY uninstall-service:
uninstall-service:
@systemctl stop mmdvmhost.service || true
@systemctl disable mmdvmhost.service || true
@rm -f /usr/local/bin/MMDVMHost || true
@rm -f /lib/systemd/system/mmdvmhost.service || true
clean:
$(RM) MMDVMHost RemoteCommand *.o *.d *.bak *~ GitVersion.h

View File

@ -3,19 +3,18 @@
CC = cc
CXX = c++
CFLAGS = -g -O3 -Wall -std=c++0x -pthread -DHAVE_LOG_H -DHD44780 -I/usr/local/include
LIBS = -lwiringPi -lwiringPiDev -lpthread -lsamplerate -lutil
LIBS = -lwiringPi -lwiringPiDev -lpthread
LDFLAGS = -g -L/usr/local/lib
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 M17LICH.o M17Network.o M17Utils.o \
AMBEFEC.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 Golay2087.o Golay24128.o Hamming.o HD44780.o I2CController.o LCDproc.o Log.o \
MMDVMHost.o Modem.o ModemSerialPort.o Mutex.o NetworkInfo.o Nextion.o NullDisplay.o NullModem.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 POCSAGNetwork.o QR1676.o \
RemoteControl.o RS129.o RS241213.o RSSIInterpolator.o SerialController.o SerialModem.o SerialPort.o StopWatch.o Sync.o SHA256.o TFTSurenoo.o Thread.o \
Timer.o UDPSocket.o UserDB.o UserDBentry.o Utils.o YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o
P25Data.o P25LowSpeedData.o P25Network.o P25NID.o P25Trellis.o P25Utils.o POCSAGControl.o POCSAGNetwork.o QR1676.o RemoteControl.o RS129.o RS241213.o \
RSSIInterpolator.o SerialController.o SerialPort.o StopWatch.o Sync.o SHA256.o TFTSerial.o TFTSurenoo.o Thread.o Timer.o UDPSocket.o UMP.o UserDB.o \
UserDBentry.o Utils.o YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o
all: MMDVMHost RemoteCommand
@ -28,33 +27,10 @@ RemoteCommand: Log.o RemoteCommand.o UDPSocket.o
%.o: %.cpp
$(CXX) $(CFLAGS) -c -o $@ $<
.PHONY install:
install: all
install:
install -m 755 MMDVMHost /usr/local/bin/
install -m 755 RemoteCommand /usr/local/bin/
.PHONY install-service:
install-service: install /etc/MMDVM.ini
@useradd --user-group -M --system mmdvm --shell /bin/false || true
@usermod --groups dialout --append mmdvm || true
@mkdir /var/log/mmdvm || true
@chown mmdvm:mmdvm /var/log/mmdvm
@cp ./linux/systemd/mmdvmhost.service /lib/systemd/system/
@systemctl enable mmdvmhost.service
/etc/MMDVM.ini:
@cp -n MMDVM.ini /etc/MMDVM.ini
@sed -i 's/FilePath=./FilePath=\/var\/log\/mmdvm\//' /etc/MMDVM.ini
@sed -i 's/Daemon=0/Daemon=1/' /etc/MMDVM.ini
@chown mmdvm:mmdvm /etc/MMDVM.ini
.PHONY uninstall-service:
uninstall-service:
@systemctl stop mmdvmhost.service || true
@systemctl disable mmdvmhost.service || true
@rm -f /usr/local/bin/MMDVMHost || true
@rm -f /lib/systemd/system/mmdvmhost.service || true
clean:
$(RM) MMDVMHost RemoteCommand *.o *.d *.bak *~ GitVersion.h

View File

@ -3,7 +3,7 @@
CC = cc
CXX = c++
CFLAGS = -g -O3 -Wall -std=c++0x -pthread -DHAVE_LOG_H -DOLED -I/usr/local/include
LIBS = -lArduiPi_OLED -lpthread -lsamplerate -lutil
LIBS = -lArduiPi_OLED -lpthread
# If you use NetBSD, add following CFLAGS
#CFLAGS += -L/usr/local/lib -Wl,-rpath=/usr/local/lib
@ -11,15 +11,14 @@ LIBS = -lArduiPi_OLED -lpthread -lsamplerate -lutil
LDFLAGS = -g -L/usr/local/lib
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 M17LICH.o M17Network.o M17Utils.o MMDVMHost.o \
Modem.o ModemSerialPort.o Mutex.o NetworkInfo.o Nextion.o NullDisplay.o NullModem.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 POCSAGControl.o POCSAGNetwork.o QR1676.o \
RemoteControl.o RS129.o RS241213.o RSSIInterpolator.o SerialController.o SerialModem.o SerialPort.o StopWatch.o Sync.o SHA256.o TFTSurenoo.o Thread.o \
Timer.o UDPSocket.o UserDB.o UserDBentry.o Utils.o YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o
AMBEFEC.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 Golay2087.o Golay24128.o Hamming.o I2CController.o OLED.o LCDproc.o Log.o \
MMDVMHost.o Modem.o ModemSerialPort.o Mutex.o NetworkInfo.o Nextion.o NullDisplay.o NullModem.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 POCSAGControl.o POCSAGNetwork.o QR1676.o RemoteControl.o RS129.o RS241213.o \
RSSIInterpolator.o SerialController.o SerialPort.o StopWatch.o Sync.o SHA256.o TFTSerial.o TFTSurenoo.o Thread.o Timer.o UDPSocket.o UMP.o UserDB.o \
UserDBentry.o Utils.o YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o
all: MMDVMHost RemoteCommand
@ -32,33 +31,10 @@ RemoteCommand: Log.o RemoteCommand.o UDPSocket.o
%.o: %.cpp
$(CXX) $(CFLAGS) -c -o $@ $<
.PHONY install:
install: all
install:
install -m 755 MMDVMHost /usr/local/bin/
install -m 755 RemoteCommand /usr/local/bin/
.PHONY install-service:
install-service: install /etc/MMDVM.ini
@useradd --user-group -M --system mmdvm --shell /bin/false || true
@usermod --groups dialout --append mmdvm || true
@mkdir /var/log/mmdvm || true
@chown mmdvm:mmdvm /var/log/mmdvm
@cp ./linux/systemd/mmdvmhost.service /lib/systemd/system/
@systemctl enable mmdvmhost.service
/etc/MMDVM.ini:
@cp -n MMDVM.ini /etc/MMDVM.ini
@sed -i 's/FilePath=./FilePath=\/var\/log\/mmdvm\//' /etc/MMDVM.ini
@sed -i 's/Daemon=0/Daemon=1/' /etc/MMDVM.ini
@chown mmdvm:mmdvm /etc/MMDVM.ini
.PHONY uninstall-service:
uninstall-service:
@systemctl stop mmdvmhost.service || true
@systemctl disable mmdvmhost.service || true
@rm -f /usr/local/bin/MMDVMHost || true
@rm -f /lib/systemd/system/mmdvmhost.service || true
clean:
$(RM) MMDVMHost RemoteCommand *.o *.d *.bak *~ GitVersion.h

View File

@ -4,19 +4,18 @@
CC = cc
CXX = c++
CFLAGS = -g -O3 -Wall -std=c++0x -pthread -DHAVE_LOG_H -DHD44780 -DPCF8574_DISPLAY -I/usr/local/include
LIBS = -lwiringPi -lwiringPiDev -lpthread -lsamplerate -lutil
LIBS = -lwiringPi -lwiringPiDev -lpthread
LDFLAGS = -g -L/usr/local/lib
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 M17LICH.o M17Network.o M17Utils.o \
AMBEFEC.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 Golay2087.o Golay24128.o Hamming.o HD44780.o I2CController.o LCDproc.o Log.o \
MMDVMHost.o Modem.o ModemSerialPort.o Mutex.o NetworkInfo.o Nextion.o NullDisplay.o NullModem.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 POCSAGNetwork.o QR1676.o \
RemoteControl.o RS129.o RS241213.o RSSIInterpolator.o SerialController.o SerialModem.o SerialPort.o StopWatch.o Sync.o SHA256.o TFTSurenoo.o Thread.o \
Timer.o UDPSocket.o UserDB.o UserDBentry.o Utils.o YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o
P25Data.o P25LowSpeedData.o P25Network.o P25NID.o P25Trellis.o P25Utils.o POCSAGControl.o POCSAGNetwork.o QR1676.o RemoteControl.o RS129.o RS241213.o \
RSSIInterpolator.o SerialController.o SerialPort.o StopWatch.o Sync.o SHA256.o TFTSerial.o TFTSurenoo.o Thread.o Timer.o UDPSocket.o UMP.o UserDB.o \
UserDBentry.o Utils.o YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o
all: MMDVMHost RemoteCommand
@ -29,33 +28,10 @@ RemoteCommand: Log.o RemoteCommand.o UDPSocket.o
%.o: %.cpp
$(CXX) $(CFLAGS) -c -o $@ $<
.PHONY install:
install: all
install:
install -m 755 MMDVMHost /usr/local/bin/
install -m 755 RemoteCommand /usr/local/bin/
.PHONY install-service:
install-service: install /etc/MMDVM.ini
@useradd --user-group -M --system mmdvm --shell /bin/false || true
@usermod --groups dialout --append mmdvm || true
@mkdir /var/log/mmdvm || true
@chown mmdvm:mmdvm /var/log/mmdvm
@cp ./linux/systemd/mmdvmhost.service /lib/systemd/system/
@systemctl enable mmdvmhost.service
/etc/MMDVM.ini:
@cp -n MMDVM.ini /etc/MMDVM.ini
@sed -i 's/FilePath=./FilePath=\/var\/log\/mmdvm\//' /etc/MMDVM.ini
@sed -i 's/Daemon=0/Daemon=1/' /etc/MMDVM.ini
@chown mmdvm:mmdvm /etc/MMDVM.ini
.PHONY uninstall-service:
uninstall-service:
@systemctl stop mmdvmhost.service || true
@systemctl disable mmdvmhost.service || true
@rm -f /usr/local/bin/MMDVMHost || true
@rm -f /lib/systemd/system/mmdvmhost.service || true
clean:
$(RM) MMDVMHost RemoteCommand *.o *.d *.bak *~ GitVersion.h

2147
Modem.cpp

File diff suppressed because it is too large Load Diff

260
Modem.h
View File

@ -19,103 +19,217 @@
#ifndef MODEM_H
#define MODEM_H
#include "SerialController.h"
#include "RingBuffer.h"
#include "Defines.h"
#include "Timer.h"
#include <string>
class IModem {
enum RESP_TYPE_MMDVM {
RTM_OK,
RTM_TIMEOUT,
RTM_ERROR
};
class CModem {
public:
virtual ~IModem() = 0;
CModem(const std::string& port, bool duplex, bool rxInvert, bool txInvert, bool pttInvert, unsigned int txDelay, unsigned int dmrDelay, bool useCOSAsLockout, bool trace, bool debug);
virtual ~CModem();
virtual void setSerialParams(const std::string& protocol, unsigned int address, unsigned int speed) = 0;
virtual void setRFParams(unsigned int rxFrequency, int rxOffset, unsigned int txFrequency, int txOffset, int txDCOffset, int rxDCOffset, float rfLevel, unsigned int pocsagFrequency) = 0;
virtual void setModeParams(bool dstarEnabled, bool dmrEnabled, bool ysfEnabled, bool p25Enabled, bool nxdnEnabled, bool m17ENabled, bool pocsagEnabled, bool fmEnabled, bool ax25Enabled) = 0;
virtual void setLevels(float rxLevel, float cwIdTXLevel, float dstarTXLevel, float dmrTXLevel, float ysfTXLevel, float p25TXLevel, float nxdnTXLevel, float m17TXLevel, float pocsagLevel, float fmTXLevel, float ax25TXLevel) = 0;
virtual void setDMRParams(unsigned int colorCode) = 0;
virtual void setYSFParams(bool loDev, unsigned int txHang) = 0;
virtual void setP25Params(unsigned int txHang) = 0;
virtual void setNXDNParams(unsigned int txHang) = 0;
virtual void setM17Params(unsigned int txHang) = 0;
virtual void setAX25Params(int rxTwist, unsigned int txDelay, unsigned int slotTime, unsigned int pPersist) = 0;
virtual void setTransparentDataParams(unsigned int sendFrameType) = 0;
virtual void setSerialParams(const std::string& protocol, unsigned int address);
virtual void setRFParams(unsigned int rxFrequency, int rxOffset, unsigned int txFrequency, int txOffset, int txDCOffset, int rxDCOffset, float rfLevel, unsigned int pocsagFrequency);
virtual void setModeParams(bool dstarEnabled, bool dmrEnabled, bool ysfEnabled, bool p25Enabled, bool nxdnEnabled, bool pocsagEnabled, bool fmEnabled);
virtual void setLevels(float rxLevel, float cwIdTXLevel, float dstarTXLevel, float dmrTXLevel, float ysfTXLevel, float p25TXLevel, float nxdnTXLevel, float pocsagLevel, float fmTXLevel);
virtual void setDMRParams(unsigned int colorCode);
virtual void setYSFParams(bool loDev, unsigned int txHang);
virtual void setP25Params(unsigned int txHang);
virtual void setNXDNParams(unsigned int txHang);
virtual void setTransparentDataParams(unsigned int sendFrameType);
virtual void setFMCallsignParams(const std::string& callsign, unsigned int callsignSpeed, unsigned int callsignFrequency, unsigned int callsignTime, unsigned int callsignHoldoff, float callsignHighLevel, float callsignLowLevel, bool callsignAtStart, bool callsignAtEnd, bool callsignAtLatch) = 0;
virtual void setFMAckParams(const std::string& rfAck, unsigned int ackSpeed, unsigned int ackFrequency, unsigned int ackMinTime, unsigned int ackDelay, float ackLevel) = 0;
virtual void setFMMiscParams(unsigned int timeout, float timeoutLevel, float ctcssFrequency, unsigned int ctcssHighThreshold, unsigned int ctcssLowThreshold, float ctcssLevel, unsigned int kerchunkTime, unsigned int hangTime, unsigned int accessMode, bool cosInvert, bool noiseSquelch, unsigned int squelchHighThreshold, unsigned int squelchLowThreshold, unsigned int rfAudioBoost, float maxDevLevel) = 0;
virtual void setFMExtParams(const std::string& ack, unsigned int audioBoost) = 0;
virtual void setFMCallsignParams(const std::string& callsign, unsigned int callsignSpeed, unsigned int callsignFrequency, unsigned int callsignTime, unsigned int callsignHoldoff, float callsignHighLevel, float callsignLowLevel, bool callsignAtStart, bool callsignAtEnd, bool callsignAtLatch);
virtual void setFMAckParams(const std::string& rfAck, unsigned int ackSpeed, unsigned int ackFrequency, unsigned int ackMinTime, unsigned int ackDelay, float ackLevel);
virtual void setFMMiscParams(unsigned int timeout, float timeoutLevel, float ctcssFrequency, unsigned int ctcssHighThreshold, unsigned int ctcssLowThreshold, float ctcssLevel, unsigned int kerchunkTime, unsigned int hangTime, unsigned int accessMode, bool cosInvert, unsigned int rfAudioBoost, float maxDevLevel);
virtual bool open() = 0;
virtual bool open();
virtual unsigned int readDStarData(unsigned char* data) = 0;
virtual unsigned int readDMRData1(unsigned char* data) = 0;
virtual unsigned int readDMRData2(unsigned char* data) = 0;
virtual unsigned int readYSFData(unsigned char* data) = 0;
virtual unsigned int readP25Data(unsigned char* data) = 0;
virtual unsigned int readNXDNData(unsigned char* data) = 0;
virtual unsigned int readM17Data(unsigned char* data) = 0;
virtual unsigned int readFMData(unsigned char* data) = 0;
virtual unsigned int readAX25Data(unsigned char* data) = 0;
virtual unsigned int readDStarData(unsigned char* data);
virtual unsigned int readDMRData1(unsigned char* data);
virtual unsigned int readDMRData2(unsigned char* data);
virtual unsigned int readYSFData(unsigned char* data);
virtual unsigned int readP25Data(unsigned char* data);
virtual unsigned int readNXDNData(unsigned char* data);
virtual unsigned int readTransparentData(unsigned char* data);
virtual bool hasDStarSpace() const = 0;
virtual bool hasDMRSpace1() const = 0;
virtual bool hasDMRSpace2() const = 0;
virtual bool hasYSFSpace() const = 0;
virtual bool hasP25Space() const = 0;
virtual bool hasNXDNSpace() const = 0;
virtual bool hasM17Space() const = 0;
virtual bool hasPOCSAGSpace() const = 0;
virtual unsigned int getFMSpace() const = 0;
virtual bool hasAX25Space() const = 0;
virtual unsigned int readSerial(unsigned char* data, unsigned int length);
virtual bool hasTX() const = 0;
virtual bool hasCD() const = 0;
virtual bool hasDStarSpace() const;
virtual bool hasDMRSpace1() const;
virtual bool hasDMRSpace2() const;
virtual bool hasYSFSpace() const;
virtual bool hasP25Space() const;
virtual bool hasNXDNSpace() const;
virtual bool hasPOCSAGSpace() const;
virtual bool hasLockout() const = 0;
virtual bool hasError() const = 0;
virtual bool hasTX() const;
virtual bool hasCD() const;
virtual bool writeConfig() = 0;
virtual bool writeDStarData(const unsigned char* data, unsigned int length) = 0;
virtual bool writeDMRData1(const unsigned char* data, unsigned int length) = 0;
virtual bool writeDMRData2(const unsigned char* data, unsigned int length) = 0;
virtual bool writeYSFData(const unsigned char* data, unsigned int length) = 0;
virtual bool writeP25Data(const unsigned char* data, unsigned int length) = 0;
virtual bool writeNXDNData(const unsigned char* data, unsigned int length) = 0;
virtual bool writeM17Data(const unsigned char* data, unsigned int length) = 0;
virtual bool writePOCSAGData(const unsigned char* data, unsigned int length) = 0;
virtual bool writeFMData(const unsigned char* data, unsigned int length) = 0;
virtual bool writeAX25Data(const unsigned char* data, unsigned int length) = 0;
virtual bool hasLockout() const;
virtual bool hasError() const;
virtual bool writeDStarInfo(const char* my1, const char* my2, const char* your, const char* type, const char* reflector) = 0;
virtual bool writeDMRInfo(unsigned int slotNo, const std::string& src, bool group, const std::string& dst, const char* type) = 0;
virtual bool writeYSFInfo(const char* source, const char* dest, unsigned char dgid, const char* type, const char* origin) = 0;
virtual bool writeP25Info(const char* source, bool group, unsigned int dest, const char* type) = 0;
virtual bool writeNXDNInfo(const char* source, bool group, unsigned int dest, const char* type) = 0;
virtual bool writeM17Info(const char* source, const char* dest, const char* type) = 0;
virtual bool writePOCSAGInfo(unsigned int ric, const std::string& message) = 0;
virtual bool writeIPInfo(const std::string& address) = 0;
virtual bool writeConfig();
virtual bool writeDStarData(const unsigned char* data, unsigned int length);
virtual bool writeDMRData1(const unsigned char* data, unsigned int length);
virtual bool writeDMRData2(const unsigned char* data, unsigned int length);
virtual bool writeYSFData(const unsigned char* data, unsigned int length);
virtual bool writeP25Data(const unsigned char* data, unsigned int length);
virtual bool writeNXDNData(const unsigned char* data, unsigned int length);
virtual bool writePOCSAGData(const unsigned char* data, unsigned int length);
virtual bool writeDMRStart(bool tx) = 0;
virtual bool writeDMRShortLC(const unsigned char* lc) = 0;
virtual bool writeDMRAbort(unsigned int slotNo) = 0;
virtual bool writeTransparentData(const unsigned char* data, unsigned int length);
virtual bool writeTransparentData(const unsigned char* data, unsigned int length) = 0;
virtual unsigned int readTransparentData(unsigned char* data) = 0;
virtual bool writeDStarInfo(const char* my1, const char* my2, const char* your, const char* type, const char* reflector);
virtual bool writeDMRInfo(unsigned int slotNo, const std::string& src, bool group, const std::string& dst, const char* type);
virtual bool writeYSFInfo(const char* source, const char* dest, unsigned char dgid, const char* type, const char* origin);
virtual bool writeP25Info(const char* source, bool group, unsigned int dest, const char* type);
virtual bool writeNXDNInfo(const char* source, bool group, unsigned int dest, const char* type);
virtual bool writePOCSAGInfo(unsigned int ric, const std::string& message);
virtual bool writeIPInfo(const std::string& address);
virtual bool writeSerial(const unsigned char* data, unsigned int length) = 0;
virtual unsigned int readSerial(unsigned char* data, unsigned int length) = 0;
virtual bool writeDMRStart(bool tx);
virtual bool writeDMRShortLC(const unsigned char* lc);
virtual bool writeDMRAbort(unsigned int slotNo);
virtual unsigned char getMode() const = 0;
virtual bool setMode(unsigned char mode) = 0;
virtual bool writeSerial(const unsigned char* data, unsigned int length);
virtual bool sendCWId(const std::string& callsign) = 0;
virtual unsigned char getMode() const;
virtual bool setMode(unsigned char mode);
virtual HW_TYPE getHWType() const = 0;
virtual bool sendCWId(const std::string& callsign);
virtual void clock(unsigned int ms) = 0;
virtual HW_TYPE getHWType() const;
virtual void close() = 0;
virtual void clock(unsigned int ms);
virtual void close();
static CModem* createModem(const std::string& port, bool duplex, bool rxInvert, bool txInvert, bool pttInvert, unsigned int txDelay, unsigned int dmrDelay, bool useCOSAsLockout, bool trace, bool debug);
private:
std::string m_port;
unsigned int m_dmrColorCode;
bool m_ysfLoDev;
unsigned int m_ysfTXHang;
unsigned int m_p25TXHang;
unsigned int m_nxdnTXHang;
bool m_duplex;
bool m_rxInvert;
bool m_txInvert;
bool m_pttInvert;
unsigned int m_txDelay;
unsigned int m_dmrDelay;
float m_rxLevel;
float m_cwIdTXLevel;
float m_dstarTXLevel;
float m_dmrTXLevel;
float m_ysfTXLevel;
float m_p25TXLevel;
float m_nxdnTXLevel;
float m_pocsagTXLevel;
float m_fmTXLevel;
float m_rfLevel;
bool m_useCOSAsLockout;
bool m_trace;
bool m_debug;
unsigned int m_rxFrequency;
unsigned int m_txFrequency;
unsigned int m_pocsagFrequency;
bool m_dstarEnabled;
bool m_dmrEnabled;
bool m_ysfEnabled;
bool m_p25Enabled;
bool m_nxdnEnabled;
bool m_pocsagEnabled;
bool m_fmEnabled;
int m_rxDCOffset;
int m_txDCOffset;
CSerialController* m_serial;
unsigned char* m_buffer;
unsigned int m_length;
unsigned int m_offset;
CRingBuffer<unsigned char> m_rxDStarData;
CRingBuffer<unsigned char> m_txDStarData;
CRingBuffer<unsigned char> m_rxDMRData1;
CRingBuffer<unsigned char> m_rxDMRData2;
CRingBuffer<unsigned char> m_txDMRData1;
CRingBuffer<unsigned char> m_txDMRData2;
CRingBuffer<unsigned char> m_rxYSFData;
CRingBuffer<unsigned char> m_txYSFData;
CRingBuffer<unsigned char> m_rxP25Data;
CRingBuffer<unsigned char> m_txP25Data;
CRingBuffer<unsigned char> m_rxNXDNData;
CRingBuffer<unsigned char> m_txNXDNData;
CRingBuffer<unsigned char> m_txPOCSAGData;
CRingBuffer<unsigned char> m_rxTransparentData;
CRingBuffer<unsigned char> m_txTransparentData;
unsigned int m_sendTransparentDataFrameType;
CTimer m_statusTimer;
CTimer m_inactivityTimer;
CTimer m_playoutTimer;
unsigned int m_dstarSpace;
unsigned int m_dmrSpace1;
unsigned int m_dmrSpace2;
unsigned int m_ysfSpace;
unsigned int m_p25Space;
unsigned int m_nxdnSpace;
unsigned int m_pocsagSpace;
bool m_tx;
bool m_cd;
bool m_lockout;
bool m_error;
unsigned char m_mode;
HW_TYPE m_hwType;
std::string m_fmCallsign;
unsigned int m_fmCallsignSpeed;
unsigned int m_fmCallsignFrequency;
unsigned int m_fmCallsignTime;
unsigned int m_fmCallsignHoldoff;
float m_fmCallsignHighLevel;
float m_fmCallsignLowLevel;
bool m_fmCallsignAtStart;
bool m_fmCallsignAtEnd;
bool m_fmCallsignAtLatch;
std::string m_fmRfAck;
unsigned int m_fmAckSpeed;
unsigned int m_fmAckFrequency;
unsigned int m_fmAckMinTime;
unsigned int m_fmAckDelay;
float m_fmAckLevel;
unsigned int m_fmTimeout;
float m_fmTimeoutLevel;
float m_fmCtcssFrequency;
unsigned int m_fmCtcssHighThreshold;
unsigned int m_fmCtcssLowThreshold;
float m_fmCtcssLevel;
unsigned int m_fmKerchunkTime;
unsigned int m_fmHangTime;
unsigned int m_fmAccessMode;
bool m_fmCOSInvert;
unsigned int m_fmRFAudioBoost;
float m_fmMaxDevLevel;
bool readVersion();
bool readStatus();
bool setConfig();
bool setFrequency();
bool setFMCallsignParams();
bool setFMAckParams();
bool setFMMiscParams();
void printDebug();
RESP_TYPE_MMDVM getResponse();
};
#endif

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2016,2020 by Jonathan Naylor G4KLX
* Copyright (C) 2016 by Jonathan Naylor G4KLX
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -21,22 +21,22 @@
#include <cstdio>
#include <cassert>
IModemSerialPort::IModemSerialPort(IModem* modem) :
CModemSerialPort::CModemSerialPort(CModem* modem) :
m_modem(modem)
{
assert(modem != NULL);
}
IModemSerialPort::~IModemSerialPort()
CModemSerialPort::~CModemSerialPort()
{
}
bool IModemSerialPort::open()
bool CModemSerialPort::open()
{
return true;
}
int IModemSerialPort::write(const unsigned char* data, unsigned int length)
int CModemSerialPort::write(const unsigned char* data, unsigned int length)
{
assert(data != NULL);
assert(length > 0U);
@ -46,7 +46,7 @@ int IModemSerialPort::write(const unsigned char* data, unsigned int length)
return ret ? int(length) : -1;
}
int IModemSerialPort::read(unsigned char* data, unsigned int length)
int CModemSerialPort::read(unsigned char* data, unsigned int length)
{
assert(data != NULL);
assert(length > 0U);
@ -54,6 +54,6 @@ int IModemSerialPort::read(unsigned char* data, unsigned int length)
return m_modem->readSerial(data, length);
}
void IModemSerialPort::close()
void CModemSerialPort::close()
{
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2016,2020 by Jonathan Naylor G4KLX
* Copyright (C) 2016 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
@ -22,10 +22,10 @@
#include "SerialPort.h"
#include "Modem.h"
class IModemSerialPort : public ISerialPort {
class CModemSerialPort : public ISerialPort {
public:
IModemSerialPort(IModem* modem);
virtual ~IModemSerialPort();
CModemSerialPort(CModem* modem);
virtual ~CModemSerialPort();
virtual bool open();
@ -36,7 +36,7 @@ public:
virtual void close();
private:
IModem* m_modem;
CModem* m_modem;
};
#endif

View File

@ -737,7 +737,7 @@ void CNXDNControl::writeEndNet()
void CNXDNControl::writeNetwork()
{
unsigned char netData[100U];
unsigned char netData[40U];
bool exists = m_network->read(netData);
if (!exists)
return;

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
@ -824,79 +822,6 @@ void CNextion::clearNXDNInt()
sendCommand("t3.txt=\"\"");
}
void CNextion::writeM17Int(const char* source, const char* dest, const char* type)
{
assert(source != NULL);
assert(dest != NULL);
assert(type != NULL);
if (m_mode != MODE_M17) {
sendCommand("page M17");
sendCommandAction(6U);
}
char text[30U];
if (m_brightness > 0) {
::sprintf(text, "dim=%u", m_brightness);
sendCommand(text);
}
::sprintf(text, "t0.txt=\"%s %.10s\"", type, source);
sendCommand(text);
sendCommandAction(122U);
::sprintf(text, "t1.txt=\"%s\"", dest);
sendCommand(text);
sendCommandAction(123U);
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(124U);
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(125U);
m_berAccum1 = 0.0F;
m_berCount1 = 0U;
}
}
void CNextion::clearM17Int()
{
sendCommand("t0.txt=\"Listening\"");
sendCommandAction(121U);
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

@ -70,11 +70,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();

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

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

@ -19,7 +19,9 @@
#include "NullModem.h"
#include "Log.h"
CNullModem::CNullModem()
CNullModem::CNullModem(const std::string& port, bool duplex, bool rxInvert, bool txInvert, bool pttInvert, unsigned int txDelay, unsigned int dmrDelay, bool useCOSAsLockout, bool trace, bool debug) :
CModem(port, duplex,rxInvert, txInvert,pttInvert,txDelay, dmrDelay, useCOSAsLockout, trace, debug),
m_hwType(HWT_MMDVM)
{
}
@ -27,9 +29,7 @@ CNullModem::~CNullModem()
{
}
bool CNullModem::open()
{
bool CNullModem::open(){
::LogMessage("Opening the MMDVM Null Modem");
return true;
}
}

View File

@ -24,100 +24,82 @@
#include <string>
class CNullModem : public IModem {
class CNullModem : public CModem {
public:
CNullModem();
CNullModem(const std::string& port, bool duplex, bool rxInvert, bool txInvert, bool pttInvert, unsigned int txDelay, unsigned int dmrDelay, bool useCOSAsLockout, bool trace, bool debug);
virtual ~CNullModem();
virtual void setSerialParams(const std::string& protocol, unsigned int address, unsigned int speed) {};
virtual void setRFParams(unsigned int rxFrequency, int rxOffset, unsigned int txFrequency, int txOffset, int txDCOffset, int rxDCOffset, float rfLevel, unsigned int pocsagFrequency) {};
virtual void setModeParams(bool dstarEnabled, bool dmrEnabled, bool ysfEnabled, bool p25Enabled, bool nxdnEnabled, bool m17Enabled, bool pocsagEnabled, bool fmEnabled, bool ax25Enabled) {};
virtual void setLevels(float rxLevel, float cwIdTXLevel, float dstarTXLevel, float dmrTXLevel, float ysfTXLevel, float p25TXLevel, float nxdnTXLevel, float m17TXLevel, float pocsagLevel, float fmTXLevel, float ax25TXLevel) {};
virtual void setDMRParams(unsigned int colorCode) {};
virtual void setYSFParams(bool loDev, unsigned int txHang) {};
virtual void setP25Params(unsigned int txHang) {};
virtual void setNXDNParams(unsigned int txHang) {};
virtual void setM17Params(unsigned int txHang) {};
virtual void setAX25Params(int rxTwist, unsigned int txDelay, unsigned int slotTime, unsigned int pPersist) {};
virtual void setTransparentDataParams(unsigned int sendFrameType) {};
virtual void setFMCallsignParams(const std::string& callsign, unsigned int callsignSpeed, unsigned int callsignFrequency, unsigned int callsignTime, unsigned int callsignHoldoff, float callsignHighLevel, float callsignLowLevel, bool callsignAtStart, bool callsignAtEnd, bool callsignAtLatch) {};
virtual void setFMAckParams(const std::string& rfAck, unsigned int ackSpeed, unsigned int ackFrequency, unsigned int ackMinTime, unsigned int ackDelay, float ackLevel) {};
virtual void setFMMiscParams(unsigned int timeout, float timeoutLevel, float ctcssFrequency, unsigned int ctcssHighThreshold, unsigned int ctcssLowThreshold, float ctcssLevel, unsigned int kerchunkTime, unsigned int hangTime, unsigned int accessMode, bool cosInvert, bool noiseSquelch, unsigned int squelchHighThreshold, unsigned int squelchLowThreshold, unsigned int rfAudioBoost, float maxDevLevel) {};
virtual void setFMExtParams(const std::string& ack, unsigned int audioBoost) {};
virtual void setSerialParams(const std::string& protocol, unsigned int address){};
virtual void setRFParams(unsigned int rxFrequency, int rxOffset, unsigned int txFrequency, int txOffset, int txDCOffset, int rxDCOffset, float rfLevel, unsigned int pocsagFrequency){};
virtual void setModeParams(bool dstarEnabled, bool dmrEnabled, bool ysfEnabled, bool p25Enabled, bool nxdnEnabled, bool pocsagEnabled, bool fmEnabled){};
virtual void setLevels(float rxLevel, float cwIdTXLevel, float dstarTXLevel, float dmrTXLevel, float ysfTXLevel, float p25TXLevel, float nxdnTXLevel, float pocsagLevel, float fmTXLevel){};
virtual void setDMRParams(unsigned int colorCode){};
virtual void setYSFParams(bool loDev, unsigned int txHang){};
virtual void setTransparentDataParams(unsigned int sendFrameType){};
virtual bool open();
virtual unsigned int readDStarData(unsigned char* data) { return 0U; };
virtual unsigned int readDMRData1(unsigned char* data) { return 0U; };
virtual unsigned int readDMRData2(unsigned char* data) { return 0U; };
virtual unsigned int readYSFData(unsigned char* data) { return 0U; };
virtual unsigned int readP25Data(unsigned char* data) { return 0U; };
virtual unsigned int readNXDNData(unsigned char* data) { return 0U; };
virtual unsigned int readM17Data(unsigned char* data) { return 0U; };
virtual unsigned int readFMData(unsigned char* data) { return 0U; };
virtual unsigned int readAX25Data(unsigned char* data) { return 0U; };
virtual unsigned int readDStarData(unsigned char* data){return 0;};
virtual unsigned int readDMRData1(unsigned char* data){return 0;};
virtual unsigned int readDMRData2(unsigned char* data){return 0;};
virtual unsigned int readYSFData(unsigned char* data){return 0;};
virtual unsigned int readP25Data(unsigned char* data){return 0;};
virtual unsigned int readNXDNData(unsigned char* data){return 0;};
virtual unsigned int readTransparentData(unsigned char* data){return 0;};
virtual bool hasDStarSpace()const { return true; };
virtual bool hasDMRSpace1() const { return true; };
virtual bool hasDMRSpace2() const { return true; };
virtual bool hasYSFSpace() const { return true; };
virtual bool hasP25Space() const { return true; };
virtual bool hasNXDNSpace() const { return true; };
virtual bool hasM17Space() const { return true; };
virtual bool hasPOCSAGSpace() const { return true; };
virtual unsigned int getFMSpace() const { return true; };
virtual bool hasAX25Space() const { return true; };
virtual unsigned int readSerial(unsigned char* data, unsigned int length){return 0;};
virtual bool hasTX() const { return false; };
virtual bool hasCD() const { return false; };
virtual bool hasDStarSpace()const {return true;};
virtual bool hasDMRSpace1() const {return true;};
virtual bool hasDMRSpace2() const {return true;};
virtual bool hasYSFSpace() const {return true;};
virtual bool hasP25Space() const {return true;};
virtual bool hasNXDNSpace() const {return true;};
virtual bool hasPOCSAGSpace() const{return true;};
virtual bool hasLockout() const { return false; };
virtual bool hasError() const { return false; };
virtual bool hasTX() const {return false;};
virtual bool hasCD() const {return false;};
virtual bool writeDStarData(const unsigned char* data, unsigned int length) { return true; };
virtual bool writeDMRData1(const unsigned char* data, unsigned int length) { return true; };
virtual bool writeDMRData2(const unsigned char* data, unsigned int length) { return true; };
virtual bool writeYSFData(const unsigned char* data, unsigned int length) { return true; };
virtual bool writeP25Data(const unsigned char* data, unsigned int length) { return true; };
virtual bool writeNXDNData(const unsigned char* data, unsigned int length) { return true; };
virtual bool writeM17Data(const unsigned char* data, unsigned int length) { return true; };
virtual bool writePOCSAGData(const unsigned char* data, unsigned int length) { return true; };
virtual bool writeFMData(const unsigned char* data, unsigned int length) { return true; };
virtual bool writeAX25Data(const unsigned char* data, unsigned int length) { return true; };
virtual bool hasLockout() const {return false;};
virtual bool hasError() const {return false;};
virtual bool writeConfig() { return true; };
virtual bool writeDStarInfo(const char* my1, const char* my2, const char* your, const char* type, const char* reflector) { return true; };
virtual bool writeDMRInfo(unsigned int slotNo, const std::string& src, bool group, const std::string& dst, const char* type) { return true; };
virtual bool writeYSFInfo(const char* source, const char* dest, unsigned char dgid, const char* type, const char* origin) { return true; };
virtual bool writeP25Info(const char* source, bool group, unsigned int dest, const char* type) { return true; };
virtual bool writeNXDNInfo(const char* source, bool group, unsigned int dest, const char* type) { return true; };
virtual bool writeM17Info(const char* source, const char* dest, const char* type) { return true; };
virtual bool writePOCSAGInfo(unsigned int ric, const std::string& message) { return true; };
virtual bool writeIPInfo(const std::string& address) { return true; };
virtual bool writeDStarData(const unsigned char* data, unsigned int length){return true;};
virtual bool writeDMRData1(const unsigned char* data, unsigned int length){return true;};
virtual bool writeDMRData2(const unsigned char* data, unsigned int length){return true;};
virtual bool writeYSFData(const unsigned char* data, unsigned int length){return true;};
virtual bool writeP25Data(const unsigned char* data, unsigned int length){return true;};
virtual bool writeNXDNData(const unsigned char* data, unsigned int length){return true;};
virtual bool writePOCSAGData(const unsigned char* data, unsigned int length){return true;};
virtual bool writeDMRStart(bool tx) { return true; };
virtual bool writeDMRShortLC(const unsigned char* lc) { return true; };
virtual bool writeDMRAbort(unsigned int slotNo) { return true; };
virtual bool writeTransparentData(const unsigned char* data, unsigned int length){return true;};
virtual bool writeTransparentData(const unsigned char* data, unsigned int length) { return true; };
virtual unsigned int readTransparentData(unsigned char* data) { return 0U; };
virtual bool writeDStarInfo(const char* my1, const char* my2, const char* your, const char* type, const char* reflector){return true;};
virtual bool writeDMRInfo(unsigned int slotNo, const std::string& src, bool group, const std::string& dst, const char* type){return true;};
virtual bool writeYSFInfo(const char* source, const char* dest, const char* type, const char* origin){return true;};
virtual bool writeP25Info(const char* source, bool group, unsigned int dest, const char* type){return true;};
virtual bool writeNXDNInfo(const char* source, bool group, unsigned int dest, const char* type){return true;};
virtual bool writePOCSAGInfo(unsigned int ric, const std::string& message){return true;};
virtual bool writeIPInfo(const std::string& address){return true;};
virtual bool writeSerial(const unsigned char* data, unsigned int length) { return true; };
virtual unsigned int readSerial(unsigned char* data, unsigned int length) { return 0U; };
virtual bool writeDMRStart(bool tx){return true;};
virtual bool writeDMRShortLC(const unsigned char* lc){return true;};
virtual bool writeDMRAbort(unsigned int slotNo){return true;};
virtual unsigned char getMode() const { return MODE_IDLE; };
virtual bool setMode(unsigned char mode) { return true; };
virtual bool writeSerial(const unsigned char* data, unsigned int length){return true;};
virtual bool sendCWId(const std::string& callsign) { return true; };
virtual bool setMode(unsigned char mode){return true;};
virtual HW_TYPE getHWType() const { return HWT_MMDVM; };
virtual bool sendCWId(const std::string& callsign){return true;};
virtual void clock(unsigned int ms) {};
virtual HW_TYPE getHWType() const {return m_hwType;};
virtual void close() {};
virtual void clock(unsigned int ms){};
virtual void close(){};
private:
HW_TYPE m_hwType;
};
#endif

View File

@ -148,28 +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
// XXX FIXME This is the NXDN logo, it needs replacing with the M17 logo
const unsigned char logo_M17_bmp [] =
{
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xf0, 0x1f, 0xf8, 0x0f, 0x00, 0xff, 0x80, 0x7c, 0x00, 0x0f, 0xff, 0x80, 0x7f, 0xe0, 0x7f,
0xff, 0xe0, 0x0f, 0xf0, 0x1f, 0x80, 0x7e, 0x01, 0xf8, 0x00, 0x00, 0x7f, 0x00, 0x3f, 0xc0, 0x7f,
0xff, 0xc0, 0x07, 0xe0, 0x3f, 0x80, 0x38, 0x07, 0xf0, 0x00, 0x00, 0x3e, 0x00, 0x3f, 0x80, 0xff,
0xff, 0x80, 0x03, 0xc0, 0x3f, 0xc0, 0x00, 0x3f, 0xe0, 0x1f, 0x80, 0x3e, 0x00, 0x1f, 0x01, 0xff,
0xff, 0x00, 0x03, 0x80, 0x7f, 0xe0, 0x00, 0xff, 0xc0, 0x3f, 0x80, 0x3c, 0x00, 0x0e, 0x03, 0xff,
0xfe, 0x00, 0x01, 0x00, 0xff, 0xe0, 0x03, 0xff, 0x80, 0x7f, 0x80, 0x78, 0x08, 0x04, 0x03, 0xff,
0xfc, 0x03, 0x00, 0x01, 0xff, 0x80, 0x01, 0xff, 0x00, 0xff, 0x00, 0xf0, 0x1c, 0x00, 0x07, 0xff,
0xfc, 0x07, 0x80, 0x03, 0xfc, 0x00, 0x01, 0xfe, 0x01, 0xfc, 0x01, 0xe0, 0x1e, 0x00, 0x0f, 0xff,
0xf8, 0x0f, 0xc0, 0x07, 0xf0, 0x0e, 0x00, 0xfc, 0x00, 0x00, 0x07, 0xc0, 0x3f, 0x00, 0x1f, 0xff,
0xf0, 0x1f, 0xe0, 0x0f, 0x80, 0x3f, 0x00, 0x7c, 0x00, 0x00, 0x3f, 0xc0, 0x7f, 0x80, 0x3f, 0xff,
0xe0, 0x3f, 0xf0, 0x0e, 0x01, 0xff, 0x80, 0x38, 0x00, 0x07, 0xff, 0x80, 0xff, 0x80, 0x7f, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
};
// Logo POCASG/DAPNET, 128x16px
const unsigned char logo_POCSAG_bmp [] =
{
@ -368,6 +346,7 @@ void COLED::writeDStarInt(const char* my1, const char* my2, const char* your, co
OLED_statusbar();
m_display.display();
}
void COLED::clearDStarInt()
@ -521,6 +500,7 @@ void COLED::writeP25Int(const char* source, bool group, unsigned int dest, const
OLED_statusbar();
m_display.display();
}
void COLED::clearP25Int()
@ -586,36 +566,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("%s %s", type, source);
m_display.setCursor(0,OLED_LINE4);
m_display.printf(" %s", dest);
OLED_statusbar();
m_display.display();
}
void COLED::clearM17Int()
{
m_display.fillRect(0, OLED_LINE2, m_display.width(), m_display.height(), BLACK);
m_display.setCursor(40,OLED_LINE4);
m_display.print("Listening");
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)
{
m_mode = MODE_POCSAG;
@ -644,6 +594,7 @@ void COLED::writePOCSAGInt(uint32_t ric, const std::string& message)
OLED_statusbar();
m_display.display();
}
void COLED::clearPOCSAGInt()
@ -718,8 +669,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)

6
OLED.h
View File

@ -66,16 +66,10 @@ public:
virtual void writeP25Int(const char* source, bool group, unsigned int dest, const char* type);
virtual void clearP25Int();
virtual void writeM17Int(const char* source, const char* dest, const char* type);
virtual void clearM17Int();
virtual void writeNXDNInt(const char* source, bool group, unsigned int dest, const char* type);
virtual int writeNXDNIntEx(const class 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,86 +0,0 @@
/*
* Copyright (C) 2002-2004,2007-2011,2013,2014-2017,2019,2020 by Jonathan Naylor G4KLX
* Copyright (C) 1999-2001 by Thomas Sailor HB9JNX
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#if !defined(_WIN32) && !defined(_WIN64)
#include "PseudoTTYController.h"
#include "Log.h"
#include <cstring>
#include <cassert>
#include <cstdlib>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <cerrno>
#include <fcntl.h>
#include <unistd.h>
#include <termios.h>
#include <pty.h>
CPseudoTTYController::CPseudoTTYController(const std::string& symlink, unsigned int speed, bool assertRTS) :
CSerialController(speed, assertRTS),
m_symlink(symlink)
{
}
CPseudoTTYController::~CPseudoTTYController()
{
}
bool CPseudoTTYController::open()
{
assert(m_fd == -1);
int slavefd;
char slave[300];
int result = ::openpty(&m_fd, &slavefd, slave, NULL, NULL);
if (result < 0) {
LogError("Cannot open the pseudo tty - errno : %d", errno);
return false;
}
// Remove any previous stale symlink
::unlink(m_symlink.c_str());
int ret = ::symlink(slave, m_symlink.c_str());
if (ret != 0) {
LogError("Cannot make symlink to %s with %s", slave, m_symlink.c_str());
close();
return false;
}
LogMessage("Made symbolic link from %s to %s", slave, m_symlink.c_str());
m_device = std::string(::ttyname(m_fd));
return setRaw();
}
void CPseudoTTYController::close()
{
CSerialController::close();
::unlink(m_symlink.c_str());
}
#endif

View File

@ -1,43 +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.
*/
#ifndef PseudoTTYController_H
#define PseudoTTYController_H
#if !defined(_WIN32) && !defined(_WIN64)
#include <cstring>
#include "SerialController.h"
class CPseudoTTYController : public CSerialController {
public:
CPseudoTTYController(const std::string& symlink, unsigned int speed, bool assertRTS = false);
virtual ~CPseudoTTYController();
virtual bool open();
virtual void close();
protected:
std::string m_symlink;
};
#endif
#endif

View File

@ -1,15 +1,14 @@
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,
POCSAG, FM, and AX.25 on the MMDVM, and D-Star, DMR, and System Fusion on the DVMega.
the other. It supports D-Star, DMR, P25 Phase 1, NXDN, System Fusion,
POCSAG, and FM 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
connects to the DMR Gateway to allow for connection to multiple DMR networks,
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.
@ -27,7 +26,8 @@ these are:
The Nextion displays can connect to the UART on the Raspberry Pi, or via a USB
to TTL serial converter like the FT-232RL. It may also be connected to the UART
output of the MMDVM modem (Arduino Due, STM32, Teensy).
output of the MMDVM modem (Arduino Due, STM32, Teensy), or to the UART output
on the UMP.
The HD44780 displays are integrated with wiringPi for Raspberry Pi based
platforms.

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2019,2020 by Jonathan Naylor G4KLX
* Copyright (C) 2019 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
@ -89,8 +89,6 @@ REMOTE_COMMAND CRemoteControl::getCommand()
m_command = RCD_MODE_P25;
else if (m_args.at(1U) == "nxdn")
m_command = RCD_MODE_NXDN;
else if (m_args.at(1U) == "m17")
m_command = RCD_MODE_M17;
} else if (m_args.at(0U) == "enable" && m_args.size() >= ENABLE_ARGS) {
if (m_args.at(1U) == "dstar")
m_command = RCD_ENABLE_DSTAR;
@ -102,12 +100,8 @@ REMOTE_COMMAND CRemoteControl::getCommand()
m_command = RCD_ENABLE_P25;
else if (m_args.at(1U) == "nxdn")
m_command = RCD_ENABLE_NXDN;
else if (m_args.at(1U) == "m17")
m_command = RCD_ENABLE_M17;
else if (m_args.at(1U) == "fm")
m_command = RCD_ENABLE_FM;
else if (m_args.at(1U) == "ax25")
m_command = RCD_ENABLE_AX25;
} else if (m_args.at(0U) == "disable" && m_args.size() >= DISABLE_ARGS) {
if (m_args.at(1U) == "dstar")
m_command = RCD_DISABLE_DSTAR;
@ -119,12 +113,8 @@ REMOTE_COMMAND CRemoteControl::getCommand()
m_command = RCD_DISABLE_P25;
else if (m_args.at(1U) == "nxdn")
m_command = RCD_DISABLE_NXDN;
else if (m_args.at(1U) == "m17")
m_command = RCD_DISABLE_M17;
else if (m_args.at(1U) == "fm")
m_command = RCD_DISABLE_FM;
else if (m_args.at(1U) == "ax25")
m_command = RCD_DISABLE_AX25;
} else if (m_args.at(0U) == "page" && m_args.size() >= PAGE_ARGS) {
// Page command is in the form of "page <ric> <message>"
m_command = RCD_PAGE;
@ -154,7 +144,6 @@ unsigned int CRemoteControl::getArgCount() const
case RCD_MODE_YSF:
case RCD_MODE_P25:
case RCD_MODE_NXDN:
case RCD_MODE_M17:
return m_args.size() - SET_MODE_ARGS;
case RCD_PAGE:
return m_args.size() - 1U;
@ -175,15 +164,14 @@ std::string CRemoteControl::getArgString(unsigned int n) const
case RCD_MODE_YSF:
case RCD_MODE_P25:
case RCD_MODE_NXDN:
case RCD_MODE_M17:
n += SET_MODE_ARGS;
break;
case RCD_PAGE:
n += 1U;
break;
case RCD_CW:
n += 1U;
break;
n += 1U;
break;
default:
return "";
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2019,2020 by Jonathan Naylor G4KLX
* Copyright (C) 2019 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,24 +33,19 @@ enum REMOTE_COMMAND {
RCD_MODE_YSF,
RCD_MODE_P25,
RCD_MODE_NXDN,
RCD_MODE_M17,
RCD_MODE_FM,
RCD_ENABLE_DSTAR,
RCD_ENABLE_DMR,
RCD_ENABLE_YSF,
RCD_ENABLE_P25,
RCD_ENABLE_NXDN,
RCD_ENABLE_M17,
RCD_ENABLE_FM,
RCD_ENABLE_AX25,
RCD_DISABLE_DSTAR,
RCD_DISABLE_DMR,
RCD_DISABLE_YSF,
RCD_DISABLE_P25,
RCD_DISABLE_NXDN,
RCD_DISABLE_M17,
RCD_DISABLE_FM,
RCD_DISABLE_AX25,
RCD_PAGE,
RCD_CW
};

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2002-2004,2007-2011,2013,2014-2017,2019,2020 by Jonathan Naylor G4KLX
* Copyright (C) 2002-2004,2007-2011,2013,2014-2017,2019 by Jonathan Naylor G4KLX
* Copyright (C) 1999-2001 by Thomas Sailor HB9JNX
*
* This program is free software; you can redistribute it and/or modify
@ -23,11 +23,12 @@
#include <cstring>
#include <cassert>
#include <sys/types.h>
#if defined(_WIN32) || defined(_WIN64)
#include <setupapi.h>
#include <winioctl.h>
#else
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <cerrno>
@ -39,7 +40,7 @@
#if defined(_WIN32) || defined(_WIN64)
CSerialController::CSerialController(const std::string& device, unsigned int speed, bool assertRTS) :
CSerialController::CSerialController(const std::string& device, SERIAL_SPEED speed, bool assertRTS) :
m_device(device),
m_speed(speed),
m_assertRTS(assertRTS),
@ -48,14 +49,6 @@ m_handle(INVALID_HANDLE_VALUE)
assert(!device.empty());
}
CSerialController::CSerialController(unsigned int speed, bool assertRTS) :
m_device(),
m_speed(speed),
m_assertRTS(assertRTS),
m_handle(INVALID_HANDLE_VALUE)
{
}
CSerialController::~CSerialController()
{
}
@ -228,7 +221,7 @@ void CSerialController::close()
#else
CSerialController::CSerialController(const std::string& device, unsigned int speed, bool assertRTS) :
CSerialController::CSerialController(const std::string& device, SERIAL_SPEED speed, bool assertRTS) :
m_device(device),
m_speed(speed),
m_assertRTS(assertRTS),
@ -237,14 +230,6 @@ m_fd(-1)
assert(!device.empty());
}
CSerialController::CSerialController(unsigned int speed, bool assertRTS) :
m_device(),
m_speed(speed),
m_assertRTS(assertRTS),
m_fd(-1)
{
}
CSerialController::~CSerialController()
{
}
@ -263,106 +248,96 @@ bool CSerialController::open()
return false;
}
if (::isatty(m_fd))
return setRaw();
return true;
}
if (::isatty(m_fd)) {
termios termios;
if (::tcgetattr(m_fd, &termios) < 0) {
LogError("Cannot get the attributes for %s", m_device.c_str());
::close(m_fd);
return false;
}
bool CSerialController::setRaw()
{
termios termios;
if (::tcgetattr(m_fd, &termios) < 0) {
LogError("Cannot get the attributes for %s", m_device.c_str());
::close(m_fd);
return false;
}
termios.c_iflag &= ~(IGNBRK | BRKINT | IGNPAR | PARMRK | INPCK);
termios.c_iflag &= ~(ISTRIP | INLCR | IGNCR | ICRNL);
termios.c_iflag &= ~(IXON | IXOFF | IXANY);
termios.c_oflag &= ~(OPOST);
termios.c_cflag &= ~(CSIZE | CSTOPB | PARENB | CRTSCTS);
termios.c_cflag |= (CS8 | CLOCAL | CREAD);
termios.c_lflag &= ~(ISIG | ICANON | IEXTEN);
termios.c_lflag &= ~(ECHO | ECHOE | ECHOK | ECHONL);
termios.c_iflag &= ~(IGNBRK | BRKINT | IGNPAR | PARMRK | INPCK);
termios.c_iflag &= ~(ISTRIP | INLCR | IGNCR | ICRNL);
termios.c_iflag &= ~(IXON | IXOFF | IXANY);
termios.c_oflag &= ~(OPOST);
termios.c_cflag &= ~(CSIZE | CSTOPB | PARENB | CRTSCTS);
termios.c_cflag |= (CS8 | CLOCAL | CREAD);
termios.c_lflag &= ~(ISIG | ICANON | IEXTEN);
termios.c_lflag &= ~(ECHO | ECHOE | ECHOK | ECHONL);
#if defined(__APPLE__)
termios.c_cc[VMIN] = 1;
termios.c_cc[VTIME] = 1;
termios.c_cc[VMIN] = 1;
termios.c_cc[VTIME] = 1;
#else
termios.c_cc[VMIN] = 0;
termios.c_cc[VTIME] = 10;
termios.c_cc[VMIN] = 0;
termios.c_cc[VTIME] = 10;
#endif
switch (m_speed) {
case 1200U:
::cfsetospeed(&termios, B1200);
::cfsetispeed(&termios, B1200);
break;
case 2400U:
::cfsetospeed(&termios, B2400);
::cfsetispeed(&termios, B2400);
break;
case 4800U:
::cfsetospeed(&termios, B4800);
::cfsetispeed(&termios, B4800);
break;
case 9600U:
::cfsetospeed(&termios, B9600);
::cfsetispeed(&termios, B9600);
break;
case 19200U:
::cfsetospeed(&termios, B19200);
::cfsetispeed(&termios, B19200);
break;
case 38400U:
::cfsetospeed(&termios, B38400);
::cfsetispeed(&termios, B38400);
break;
case 115200U:
::cfsetospeed(&termios, B115200);
::cfsetispeed(&termios, B115200);
break;
case 230400U:
::cfsetospeed(&termios, B230400);
::cfsetispeed(&termios, B230400);
break;
case 460800U:
::cfsetospeed(&termios, B460800);
::cfsetispeed(&termios, B460800);
break;
default:
LogError("Unsupported serial port speed - %u", m_speed);
::close(m_fd);
return false;
}
switch (m_speed) {
case SERIAL_1200:
::cfsetospeed(&termios, B1200);
::cfsetispeed(&termios, B1200);
break;
case SERIAL_2400:
::cfsetospeed(&termios, B2400);
::cfsetispeed(&termios, B2400);
break;
case SERIAL_4800:
::cfsetospeed(&termios, B4800);
::cfsetispeed(&termios, B4800);
break;
case SERIAL_9600:
::cfsetospeed(&termios, B9600);
::cfsetispeed(&termios, B9600);
break;
case SERIAL_19200:
::cfsetospeed(&termios, B19200);
::cfsetispeed(&termios, B19200);
break;
case SERIAL_38400:
::cfsetospeed(&termios, B38400);
::cfsetispeed(&termios, B38400);
break;
case SERIAL_115200:
::cfsetospeed(&termios, B115200);
::cfsetispeed(&termios, B115200);
break;
case SERIAL_230400:
::cfsetospeed(&termios, B230400);
::cfsetispeed(&termios, B230400);
break;
default:
LogError("Unsupported serial port speed - %d", int(m_speed));
::close(m_fd);
return false;
}
if (::tcsetattr(m_fd, TCSANOW, &termios) < 0) {
LogError("Cannot set the attributes for %s", m_device.c_str());
::close(m_fd);
return false;
}
if (m_assertRTS) {
unsigned int y;
if (::ioctl(m_fd, TIOCMGET, &y) < 0) {
LogError("Cannot get the control attributes for %s", m_device.c_str());
if (::tcsetattr(m_fd, TCSANOW, &termios) < 0) {
LogError("Cannot set the attributes for %s", m_device.c_str());
::close(m_fd);
return false;
}
y |= TIOCM_RTS;
if (m_assertRTS) {
unsigned int y;
if (::ioctl(m_fd, TIOCMGET, &y) < 0) {
LogError("Cannot get the control attributes for %s", m_device.c_str());
::close(m_fd);
return false;
}
if (::ioctl(m_fd, TIOCMSET, &y) < 0) {
LogError("Cannot set the control attributes for %s", m_device.c_str());
::close(m_fd);
return false;
y |= TIOCM_RTS;
if (::ioctl(m_fd, TIOCMSET, &y) < 0) {
LogError("Cannot set the control attributes for %s", m_device.c_str());
::close(m_fd);
return false;
}
}
}
#if defined(__APPLE__)
setNonblock(false);
setNonblock(false);
#endif
}
return true;
}

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2002-2004,2007-2009,2011-2013,2015-2017,2020 by Jonathan Naylor G4KLX
* Copyright (C) 2002-2004,2007-2009,2011-2013,2015-2017 by Jonathan Naylor G4KLX
* Copyright (C) 1999-2001 by Thomas Sailor HB9JNX
*
* This program is free software; you can redistribute it and/or modify
@ -28,9 +28,21 @@
#include <windows.h>
#endif
enum SERIAL_SPEED {
SERIAL_1200 = 1200,
SERIAL_2400 = 2400,
SERIAL_4800 = 4800,
SERIAL_9600 = 9600,
SERIAL_19200 = 19200,
SERIAL_38400 = 38400,
SERIAL_76800 = 76800,
SERIAL_115200 = 115200,
SERIAL_230400 = 230400
};
class CSerialController : public ISerialPort {
public:
CSerialController(const std::string& device, unsigned int speed, bool assertRTS = false);
CSerialController(const std::string& device, SERIAL_SPEED speed, bool assertRTS = false);
virtual ~CSerialController();
virtual bool open();
@ -46,10 +58,8 @@ public:
#endif
protected:
CSerialController(unsigned int speed, bool assertRTS = false);
std::string m_device;
unsigned int m_speed;
SERIAL_SPEED m_speed;
bool m_assertRTS;
#if defined(_WIN32) || defined(_WIN64)
HANDLE m_handle;
@ -61,7 +71,6 @@ protected:
int readNonblock(unsigned char* buffer, unsigned int length);
#else
bool canWrite();
bool setRaw();
#endif
};

File diff suppressed because it is too large Load Diff

View File

@ -1,286 +0,0 @@
/*
* Copyright (C) 2011-2018,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.
*/
#ifndef SERIALMODEM_H
#define SERIALMODEM_H
#include "Modem.h"
#include "SerialPort.h"
#include "RingBuffer.h"
#include "Defines.h"
#include "Timer.h"
#include <string>
enum RESP_TYPE_MMDVM {
RTM_OK,
RTM_TIMEOUT,
RTM_ERROR
};
enum SERIAL_STATE {
SS_START,
SS_LENGTH1,
SS_LENGTH2,
SS_TYPE,
SS_DATA
};
class CSerialModem : public IModem {
public:
CSerialModem(const std::string& port, bool duplex, bool rxInvert, bool txInvert, bool pttInvert, unsigned int txDelay, unsigned int dmrDelay, bool useCOSAsLockout, bool trace, bool debug);
virtual ~CSerialModem();
virtual void setSerialParams(const std::string& protocol, unsigned int address, unsigned int speed);
virtual void setRFParams(unsigned int rxFrequency, int rxOffset, unsigned int txFrequency, int txOffset, int txDCOffset, int rxDCOffset, float rfLevel, unsigned int pocsagFrequency);
virtual void setModeParams(bool dstarEnabled, bool dmrEnabled, bool ysfEnabled, bool p25Enabled, bool nxdnEnabled, bool m17Enabled, bool pocsagEnabled, bool fmEnabled, bool ax25Enabled);
virtual void setLevels(float rxLevel, float cwIdTXLevel, float dstarTXLevel, float dmrTXLevel, float ysfTXLevel, float p25TXLevel, float nxdnTXLevel, float m17TXLevel, float pocsagLevel, float fmTXLevel, float ax25TXLevel);
virtual void setDMRParams(unsigned int colorCode);
virtual void setYSFParams(bool loDev, unsigned int txHang);
virtual void setP25Params(unsigned int txHang);
virtual void setNXDNParams(unsigned int txHang);
virtual void setM17Params(unsigned int txHang);
virtual void setAX25Params(int rxTwist, unsigned int txDelay, unsigned int slotTime, unsigned int pPersist);
virtual void setTransparentDataParams(unsigned int sendFrameType);
virtual void setFMCallsignParams(const std::string& callsign, unsigned int callsignSpeed, unsigned int callsignFrequency, unsigned int callsignTime, unsigned int callsignHoldoff, float callsignHighLevel, float callsignLowLevel, bool callsignAtStart, bool callsignAtEnd, bool callsignAtLatch);
virtual void setFMAckParams(const std::string& rfAck, unsigned int ackSpeed, unsigned int ackFrequency, unsigned int ackMinTime, unsigned int ackDelay, float ackLevel);
virtual void setFMMiscParams(unsigned int timeout, float timeoutLevel, float ctcssFrequency, unsigned int ctcssHighThreshold, unsigned int ctcssLowThreshold, float ctcssLevel, unsigned int kerchunkTime, unsigned int hangTime, unsigned int accessMode, bool cosInvert, bool noiseSquelch, unsigned int squelchHighThreshold, unsigned int squelchLowThreshold, unsigned int rfAudioBoost, float maxDevLevel);
virtual void setFMExtParams(const std::string& ack, unsigned int audioBoost);
virtual bool open();
virtual unsigned int readDStarData(unsigned char* data);
virtual unsigned int readDMRData1(unsigned char* data);
virtual unsigned int readDMRData2(unsigned char* data);
virtual unsigned int readYSFData(unsigned char* data);
virtual unsigned int readP25Data(unsigned char* data);
virtual unsigned int readNXDNData(unsigned char* data);
virtual unsigned int readM17Data(unsigned char* data);
virtual unsigned int readFMData(unsigned char* data);
virtual unsigned int readAX25Data(unsigned char* data);
virtual bool hasDStarSpace() const;
virtual bool hasDMRSpace1() const;
virtual bool hasDMRSpace2() const;
virtual bool hasYSFSpace() const;
virtual bool hasP25Space() const;
virtual bool hasNXDNSpace() const;
virtual bool hasM17Space() const;
virtual bool hasPOCSAGSpace() const;
virtual unsigned int getFMSpace() const;
virtual bool hasAX25Space() const;
virtual bool hasTX() const;
virtual bool hasCD() const;
virtual bool hasLockout() const;
virtual bool hasError() const;
virtual bool writeConfig();
virtual bool writeDStarData(const unsigned char* data, unsigned int length);
virtual bool writeDMRData1(const unsigned char* data, unsigned int length);
virtual bool writeDMRData2(const unsigned char* data, unsigned int length);
virtual bool writeYSFData(const unsigned char* data, unsigned int length);
virtual bool writeP25Data(const unsigned char* data, unsigned int length);
virtual bool writeNXDNData(const unsigned char* data, unsigned int length);
virtual bool writeM17Data(const unsigned char* data, unsigned int length);
virtual bool writePOCSAGData(const unsigned char* data, unsigned int length);
virtual bool writeFMData(const unsigned char* data, unsigned int length);
virtual bool writeAX25Data(const unsigned char* data, unsigned int length);
virtual bool writeDStarInfo(const char* my1, const char* my2, const char* your, const char* type, const char* reflector);
virtual bool writeDMRInfo(unsigned int slotNo, const std::string& src, bool group, const std::string& dst, const char* type);
virtual bool writeYSFInfo(const char* source, const char* dest, unsigned char dgid, const char* type, const char* origin);
virtual bool writeP25Info(const char* source, bool group, unsigned int dest, const char* type);
virtual bool writeNXDNInfo(const char* source, bool group, unsigned int dest, const char* type);
virtual bool writeM17Info(const char* source, const char* dest, const char* type);
virtual bool writePOCSAGInfo(unsigned int ric, const std::string& message);
virtual bool writeIPInfo(const std::string& address);
virtual bool writeDMRStart(bool tx);
virtual bool writeDMRShortLC(const unsigned char* lc);
virtual bool writeDMRAbort(unsigned int slotNo);
virtual bool writeTransparentData(const unsigned char* data, unsigned int length);
virtual unsigned int readTransparentData(unsigned char* data);
virtual bool writeSerial(const unsigned char* data, unsigned int length);
virtual unsigned int readSerial(unsigned char* data, unsigned int length);
virtual unsigned char getMode() const;
virtual bool setMode(unsigned char mode);
virtual bool sendCWId(const std::string& callsign);
virtual HW_TYPE getHWType() const;
virtual void clock(unsigned int ms);
virtual void close();
private:
std::string m_port;
unsigned int m_protocolVersion;
unsigned int m_dmrColorCode;
bool m_ysfLoDev;
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;
bool m_pttInvert;
unsigned int m_txDelay;
unsigned int m_dmrDelay;
float m_rxLevel;
float m_cwIdTXLevel;
float m_dstarTXLevel;
float m_dmrTXLevel;
float m_ysfTXLevel;
float m_p25TXLevel;
float m_nxdnTXLevel;
float m_m17TXLevel;
float m_pocsagTXLevel;
float m_fmTXLevel;
float m_ax25TXLevel;
float m_rfLevel;
bool m_useCOSAsLockout;
bool m_trace;
bool m_debug;
unsigned int m_rxFrequency;
unsigned int m_txFrequency;
unsigned int m_pocsagFrequency;
bool m_dstarEnabled;
bool m_dmrEnabled;
bool m_ysfEnabled;
bool m_p25Enabled;
bool m_nxdnEnabled;
bool m_m17Enabled;
bool m_pocsagEnabled;
bool m_fmEnabled;
bool m_ax25Enabled;
int m_rxDCOffset;
int m_txDCOffset;
ISerialPort* m_serial;
unsigned char* m_buffer;
unsigned int m_length;
unsigned int m_offset;
SERIAL_STATE m_state;
unsigned char m_type;
CRingBuffer<unsigned char> m_rxDStarData;
CRingBuffer<unsigned char> m_txDStarData;
CRingBuffer<unsigned char> m_rxDMRData1;
CRingBuffer<unsigned char> m_rxDMRData2;
CRingBuffer<unsigned char> m_txDMRData1;
CRingBuffer<unsigned char> m_txDMRData2;
CRingBuffer<unsigned char> m_rxYSFData;
CRingBuffer<unsigned char> m_txYSFData;
CRingBuffer<unsigned char> m_rxP25Data;
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;
CRingBuffer<unsigned char> m_rxAX25Data;
CRingBuffer<unsigned char> m_txAX25Data;
CRingBuffer<unsigned char> m_rxSerialData;
CRingBuffer<unsigned char> m_txSerialData;
CRingBuffer<unsigned char> m_rxTransparentData;
CRingBuffer<unsigned char> m_txTransparentData;
unsigned int m_sendTransparentDataFrameType;
CTimer m_statusTimer;
CTimer m_inactivityTimer;
CTimer m_playoutTimer;
unsigned int m_dstarSpace;
unsigned int m_dmrSpace1;
unsigned int m_dmrSpace2;
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;
bool m_tx;
bool m_cd;
bool m_lockout;
bool m_error;
unsigned char m_mode;
HW_TYPE m_hwType;
int m_ax25RXTwist;
unsigned int m_ax25TXDelay;
unsigned int m_ax25SlotTime;
unsigned int m_ax25PPersist;
std::string m_fmCallsign;
unsigned int m_fmCallsignSpeed;
unsigned int m_fmCallsignFrequency;
unsigned int m_fmCallsignTime;
unsigned int m_fmCallsignHoldoff;
float m_fmCallsignHighLevel;
float m_fmCallsignLowLevel;
bool m_fmCallsignAtStart;
bool m_fmCallsignAtEnd;
bool m_fmCallsignAtLatch;
std::string m_fmRfAck;
std::string m_fmExtAck;
unsigned int m_fmAckSpeed;
unsigned int m_fmAckFrequency;
unsigned int m_fmAckMinTime;
unsigned int m_fmAckDelay;
float m_fmAckLevel;
unsigned int m_fmTimeout;
float m_fmTimeoutLevel;
float m_fmCtcssFrequency;
unsigned int m_fmCtcssHighThreshold;
unsigned int m_fmCtcssLowThreshold;
float m_fmCtcssLevel;
unsigned int m_fmKerchunkTime;
unsigned int m_fmHangTime;
unsigned int m_fmAccessMode;
bool m_fmCOSInvert;
bool m_fmNoiseSquelch;
unsigned int m_fmSquelchHighThreshold;
unsigned int m_fmSquelchLowThreshold;
unsigned int m_fmRFAudioBoost;
unsigned int m_fmExtAudioBoost;
float m_fmMaxDevLevel;
bool m_fmExtEnable;
bool readVersion();
bool readStatus();
bool setConfig1();
bool setConfig2();
bool setFrequency();
bool setFMCallsignParams();
bool setFMAckParams();
bool setFMMiscParams();
bool setFMExtParams();
void printDebug();
RESP_TYPE_MMDVM getResponse();
};
#endif

View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2015,2016,2018,2020 by Jonathan Naylor G4KLX
* Copyright (C) 2015,2016,2018 by Jonathan Naylor G4KLX
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -23,7 +23,6 @@
#include "YSFDefines.h"
#include "P25Defines.h"
#include "NXDNDefines.h"
#include "M17Defines.h"
#include <cstdio>
#include <cassert>
@ -84,17 +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::addM17HeaderSync(unsigned char* data)
{
assert(data != NULL);
::memcpy(data, M17_HEADER_SYNC_BYTES, M17_SYNC_LENGTH_BYTES);
}
void CSync::addM17DataSync(unsigned char* data)
{
assert(data != NULL);
::memcpy(data, M17_DATA_SYNC_BYTES, M17_SYNC_LENGTH_BYTES);
}

5
Sync.h
View File

@ -1,5 +1,5 @@
/*
* Copyright (C) 2015,2016,2018,2020 by Jonathan Naylor G4KLX
* Copyright (C) 2015,2016,2018 by Jonathan Naylor G4KLX
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -33,9 +33,6 @@ public:
static void addNXDNSync(unsigned char* data);
static void addM17HeaderSync(unsigned char* data);
static void addM17DataSync(unsigned char* data);
private:
};

588
TFTSerial.cpp Normal file
View File

@ -0,0 +1,588 @@
/*
* Copyright (C) 2015,2016,2018,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.
*/
#include "TFTSerial.h"
#include "Log.h"
#include <cstdio>
#include <cassert>
#include <cstring>
const unsigned char ROTATION_PORTRAIT_LEFT = 0U;
const unsigned char ROTATION_LANDSCAPE_UD = 1U;
const unsigned char ROTATION_PORTRAIT_RIGHT = 2U;
const unsigned char ROTATION_LANDSCAPE = 3U;
const unsigned char COLOUR_BLACK = 0U;
const unsigned char COLOUR_BLUE = 1U;
const unsigned char COLOUR_RED = 2U;
const unsigned char COLOUR_GREEN = 3U;
const unsigned char COLOUR_CYAN = 4U;
const unsigned char COLOUR_MAGENTA = 5U;
const unsigned char COLOUR_YELLOW = 6U;
const unsigned char COLOUR_WHITE = 7U;
const unsigned char FONT_SMALL = 1U;
const unsigned char FONT_MEDIUM = 2U;
const unsigned char FONT_LARGE = 3U;
// x = 0 to 159, y = 0 to 127 - Landscape
// x = 0 to 127, y = 0 to 159 - Portrait
CTFTSerial::CTFTSerial(const std::string& callsign, unsigned int dmrid, ISerialPort* serial, unsigned int brightness) :
CDisplay(),
m_callsign(callsign),
m_dmrid(dmrid),
m_serial(serial),
m_brightness(brightness),
m_mode(MODE_IDLE)
{
assert(serial != NULL);
assert(brightness >= 0U && brightness <= 100U);
}
CTFTSerial::~CTFTSerial()
{
}
bool CTFTSerial::open()
{
bool ret = m_serial->open();
if (!ret) {
LogError("Cannot open the port for the TFT Serial");
delete m_serial;
return false;
}
setRotation(ROTATION_LANDSCAPE);
setBrightness(m_brightness);
setBackground(COLOUR_WHITE);
setForeground(COLOUR_BLACK);
setIdle();
return true;
}
void CTFTSerial::setIdleInt()
{
// Clear the screen
clearScreen();
setFontSize(FONT_LARGE);
// Draw MMDVM logo
displayBitmap(0U, 0U, "MMDVM_sm.bmp");
char text[30];
::sprintf(text, "%-6s / %u", m_callsign.c_str(), m_dmrid);
gotoPosPixel(18U, 55U);
displayText(text);
gotoPosPixel(45U, 90U);
displayText("IDLE");
m_mode = MODE_IDLE;
}
void CTFTSerial::setErrorInt(const char* text)
{
assert(text != NULL);
// Clear the screen
clearScreen();
setFontSize(FONT_MEDIUM);
// Draw MMDVM logo
displayBitmap(0U, 0U, "MMDVM_sm.bmp");
setForeground(COLOUR_RED);
gotoPosPixel(18U, 55U);
displayText(text);
gotoPosPixel(18U, 90U);
displayText("ERROR");
setForeground(COLOUR_BLACK);
m_mode = MODE_ERROR;
}
void CTFTSerial::setLockoutInt()
{
// Clear the screen
clearScreen();
setFontSize(FONT_LARGE);
// Draw MMDVM logo
displayBitmap(0U, 0U, "MMDVM_sm.bmp");
gotoPosPixel(20U, 60U);
displayText("LOCKOUT");
m_mode = MODE_LOCKOUT;
}
void CTFTSerial::setQuitInt()
{
// Clear the screen
clearScreen();
setFontSize(FONT_LARGE);
// Draw MMDVM logo
displayBitmap(0U, 0U, "MMDVM_sm.bmp");
gotoPosPixel(20U, 60U);
displayText("STOPPED");
m_mode = MODE_QUIT;
}
void CTFTSerial::setFMInt()
{
// Clear the screen
clearScreen();
setFontSize(FONT_LARGE);
// Draw MMDVM logo
displayBitmap(0U, 0U, "MMDVM_sm.bmp");
gotoPosPixel(20U, 60U);
displayText("FM");
m_mode = MODE_FM;
}
void CTFTSerial::writeDStarInt(const char* my1, const char* my2, const char* your, const char* type, const char* reflector)
{
assert(my1 != NULL);
assert(my2 != NULL);
assert(your != NULL);
assert(type != NULL);
assert(reflector != NULL);
if (m_mode != MODE_DSTAR) {
// Clear the screen
clearScreen();
setFontSize(FONT_MEDIUM);
// Draw D-Star insignia
displayBitmap(0U, 0U, "DStar_sm.bmp");
}
char text[30U];
::sprintf(text, "%s %.8s/%4.4s", type, my1, my2);
gotoPosPixel(5U, 70U);
displayText(text);
::sprintf(text, "%.8s", your);
gotoPosPixel(5U, 90U);
displayText(text);
if (::strcmp(reflector, " ") != 0) {
::sprintf(text, "via %.8s", reflector);
gotoPosPixel(5U, 110U);
displayText(text);
} else {
gotoPosPixel(5U, 110U);
displayText(" ");
}
m_mode = MODE_DSTAR;
}
void CTFTSerial::clearDStarInt()
{
gotoPosPixel(5U, 70U);
displayText(" Listening ");
gotoPosPixel(5U, 90U);
displayText(" ");
gotoPosPixel(5U, 110U);
displayText(" ");
}
void CTFTSerial::writeDMRInt(unsigned int slotNo, const std::string& src, bool group, const std::string& dst, const char* type)
{
assert(type != NULL);
if (m_mode != MODE_DMR) {
// Clear the screen
clearScreen();
setFontSize(FONT_MEDIUM);
// Draw DMR insignia
displayBitmap(0U, 0U, "DMR_sm.bmp");
if (slotNo == 1U) {
gotoPosPixel(5U, 90U);
displayText("2 Listening");
} else {
gotoPosPixel(5U, 55U);
displayText("1 Listening");
}
}
if (slotNo == 1U) {
char text[30U];
::sprintf(text, "1 %s %s", type, src.c_str());
gotoPosPixel(5U, 55U);
displayText(text);
::sprintf(text, "%s%s", group ? "TG" : "", dst.c_str());
gotoPosPixel(65U, 72U);
displayText(text);
} else {
char text[30U];
::sprintf(text, "2 %s %s", type, src.c_str());
gotoPosPixel(5U, 90U);
displayText(text);
::sprintf(text, "%s%s", group ? "TG" : "", dst.c_str());
gotoPosPixel(65U, 107U);
displayText(text);
}
m_mode = MODE_DMR;
}
void CTFTSerial::clearDMRInt(unsigned int slotNo)
{
if (slotNo == 1U) {
gotoPosPixel(5U, 55U);
displayText("1 Listening ");
gotoPosPixel(65U, 72U);
displayText(" ");
} else {
gotoPosPixel(5U, 90U);
displayText("2 Listening ");
gotoPosPixel(65U, 107U);
displayText(" ");
}
}
void CTFTSerial::writeFusionInt(const char* source, const char* dest, unsigned char dgid, const char* type, const char* origin)
{
assert(source != NULL);
assert(dest != NULL);
assert(type != NULL);
assert(origin != NULL);
if (m_mode != MODE_YSF) {
// Clear the screen
clearScreen();
setFontSize(FONT_MEDIUM);
// Draw the System Fusion insignia
displayBitmap(0U, 0U, "YSF_sm.bmp");
}
char text[30U];
::sprintf(text, "%s %.10s", type, source);
gotoPosPixel(5U, 70U);
displayText(text);
::sprintf(text, " DG-ID %u", dgid);
gotoPosPixel(5U, 90U);
displayText(text);
if (::strcmp(origin, " ") != 0) {
::sprintf(text, "at %.10s", origin);
gotoPosPixel(5U, 110U);
displayText(text);
} else {
gotoPosPixel(5U, 110U);
displayText(" ");
}
m_mode = MODE_YSF;
}
void CTFTSerial::clearFusionInt()
{
gotoPosPixel(5U, 70U);
displayText(" Listening ");
gotoPosPixel(5U, 90U);
displayText(" ");
gotoPosPixel(5U, 110U);
displayText(" ");
}
void CTFTSerial::writeP25Int(const char* source, bool group, unsigned int dest, const char* type)
{
assert(source != NULL);
assert(type != NULL);
if (m_mode != MODE_P25) {
// Clear the screen
clearScreen();
setFontSize(FONT_MEDIUM);
// Draw the P25 insignia
displayBitmap(0U, 0U, "P25_sm.bmp");
}
char text[30U];
::sprintf(text, "%s %.10s", type, source);
gotoPosPixel(5U, 70U);
displayText(text);
::sprintf(text, " %s%u", group ? "TG" : "", dest);
gotoPosPixel(5U, 90U);
displayText(text);
m_mode = MODE_P25;
}
void CTFTSerial::clearP25Int()
{
gotoPosPixel(5U, 70U);
displayText(" Listening ");
gotoPosPixel(5U, 90U);
displayText(" ");
gotoPosPixel(5U, 110U);
displayText(" ");
}
void CTFTSerial::writeNXDNInt(const char* source, bool group, unsigned int dest, const char* type)
{
assert(source != NULL);
assert(type != NULL);
if (m_mode != MODE_NXDN) {
// Clear the screen
clearScreen();
setFontSize(FONT_MEDIUM);
// Draw the P25 insignia
displayBitmap(0U, 0U, "NXDN_sm.bmp");
}
char text[30U];
::sprintf(text, "%s %.10s", type, source);
gotoPosPixel(5U, 70U);
displayText(text);
::sprintf(text, " %s%u", group ? "TG" : "", dest);
gotoPosPixel(5U, 90U);
displayText(text);
m_mode = MODE_NXDN;
}
void CTFTSerial::clearNXDNInt()
{
gotoPosPixel(5U, 70U);
displayText(" Listening ");
gotoPosPixel(5U, 90U);
displayText(" ");
gotoPosPixel(5U, 110U);
displayText(" ");
}
void CTFTSerial::writePOCSAGInt(uint32_t ric, const std::string& message)
{
gotoPosPixel(15U, 90U);
displayText("POCSAG TX");
m_mode = MODE_CW;
}
void CTFTSerial::clearPOCSAGInt()
{
gotoPosPixel(45U, 90U);
displayText("IDLE");
}
void CTFTSerial::writeCWInt()
{
gotoPosPixel(45U, 90U);
displayText("CW TX");
m_mode = MODE_CW;
}
void CTFTSerial::clearCWInt()
{
gotoPosPixel(45U, 90U);
displayText("IDLE");
}
void CTFTSerial::close()
{
m_serial->close();
delete m_serial;
}
void CTFTSerial::clearScreen()
{
m_serial->write((unsigned char*)"\x1B\x00\xFF", 3U);
}
void CTFTSerial::setForeground(unsigned char colour)
{
assert(colour >= 0U && colour <= 7U);
m_serial->write((unsigned char*)"\x1B\x01", 2U);
m_serial->write(&colour, 1U);
m_serial->write((unsigned char*)"\xFF", 1U);
}
void CTFTSerial::setBackground(unsigned char colour)
{
assert(colour >= 0U && colour <= 7U);
m_serial->write((unsigned char*)"\x1B\x02", 2U);
m_serial->write(&colour, 1U);
m_serial->write((unsigned char*)"\xFF", 1U);
}
void CTFTSerial::setRotation(unsigned char rotation)
{
assert(rotation >= 0U && rotation <= 3U);
m_serial->write((unsigned char*)"\x1B\x03", 2U);
m_serial->write(&rotation, 1U);
m_serial->write((unsigned char*)"\xFF", 1U);
}
void CTFTSerial::setFontSize(unsigned char size)
{
assert(size >= 1U && size <= 3U);
m_serial->write((unsigned char*)"\x1B\x04", 2U);
m_serial->write(&size, 1U);
m_serial->write((unsigned char*)"\xFF", 1U);
}
void CTFTSerial::gotoBegOfLine()
{
m_serial->write((unsigned char*)"\x1B\x05\xFF", 3U);
}
void CTFTSerial::gotoPosText(unsigned char x, unsigned char y)
{
m_serial->write((unsigned char*)"\x1B\x06", 2U);
m_serial->write(&x, 1U);
m_serial->write(&y, 1U);
m_serial->write((unsigned char*)"\xFF", 1U);
}
void CTFTSerial::gotoPosPixel(unsigned char x, unsigned char y)
{
m_serial->write((unsigned char*)"\x1B\x07", 2U);
m_serial->write(&x, 1U);
m_serial->write(&y, 1U);
m_serial->write((unsigned char*)"\xFF", 1U);
}
void CTFTSerial::drawLine(unsigned char x1, unsigned char y1, unsigned char x2, unsigned char y2)
{
m_serial->write((unsigned char*)"\x1B\x08", 2U);
m_serial->write(&x1, 1U);
m_serial->write(&y1, 1U);
m_serial->write(&x2, 1U);
m_serial->write(&y2, 1U);
m_serial->write((unsigned char*)"\xFF", 1U);
}
void CTFTSerial::drawBox(unsigned char x1, unsigned char y1, unsigned char x2, unsigned char y2, bool filled)
{
if (filled)
m_serial->write((unsigned char*)"\x1B\x0A", 2U);
else
m_serial->write((unsigned char*)"\x1B\x09", 2U);
m_serial->write(&x1, 1U);
m_serial->write(&y1, 1U);
m_serial->write(&x2, 1U);
m_serial->write(&y2, 1U);
m_serial->write((unsigned char*)"\xFF", 1U);
}
void CTFTSerial::drawCircle(unsigned char x, unsigned char y, unsigned char radius, bool filled)
{
if (filled)
m_serial->write((unsigned char*)"\x1B\x0C", 2U);
else
m_serial->write((unsigned char*)"\x1B\x0B", 2U);
m_serial->write(&x, 1U);
m_serial->write(&y, 1U);
m_serial->write(&radius, 1U);
m_serial->write((unsigned char*)"\xFF", 1U);
}
void CTFTSerial::displayBitmap(unsigned char x, unsigned char y, const char* filename)
{
assert(filename != NULL);
m_serial->write((unsigned char*)"\x1B\x0D", 2U);
m_serial->write(&x, 1U);
m_serial->write(&y, 1U);
m_serial->write((unsigned char*)filename, (unsigned int)::strlen(filename));
m_serial->write((unsigned char*)"\xFF", 1U);
}
void CTFTSerial::setBrightness(unsigned char brightness)
{
assert(brightness >= 0U && brightness <= 100U);
m_serial->write((unsigned char*)"\x1B\x0E", 2U);
m_serial->write(&brightness, 1U);
m_serial->write((unsigned char*)"\xFF", 1U);
}
void CTFTSerial::displayText(const char* text)
{
assert(text != NULL);
m_serial->write((unsigned char*)text, (unsigned int)::strlen(text));
}

89
TFTSerial.h Normal file
View File

@ -0,0 +1,89 @@
/*
* Copyright (C) 2015,2016,2018,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(TFTSERIAL_H)
#define TFTSERIAL_H
#include "Display.h"
#include "Defines.h"
#include "SerialPort.h"
#include <string>
class CTFTSerial : public CDisplay
{
public:
CTFTSerial(const std::string& callsign, unsigned int dmrid, ISerialPort* serial, unsigned int brightness);
virtual ~CTFTSerial();
virtual bool open();
virtual void close();
protected:
virtual void setIdleInt();
virtual void setErrorInt(const char* text);
virtual void setLockoutInt();
virtual void setQuitInt();
virtual void setFMInt();
virtual void writeDStarInt(const char* my1, const char* my2, const char* your, const char* type, const char* reflector);
virtual void clearDStarInt();
virtual void writeDMRInt(unsigned int slotNo, const std::string& src, bool group, const std::string& dst, const char* type);
virtual void clearDMRInt(unsigned int slotNo);
virtual void writeFusionInt(const char* source, const char* dest, unsigned char dgid, const char* type, const char* origin);
virtual void clearFusionInt();
virtual void writeP25Int(const char* source, bool group, unsigned int dest, const char* type);
virtual void clearP25Int();
virtual void writeNXDNInt(const char* source, bool group, unsigned int dest, const char* type);
virtual void clearNXDNInt();
virtual void writePOCSAGInt(uint32_t ric, const std::string& message);
virtual void clearPOCSAGInt();
virtual void writeCWInt();
virtual void clearCWInt();
private:
std::string m_callsign;
unsigned int m_dmrid;
ISerialPort* m_serial;
unsigned int m_brightness;
unsigned char m_mode;
void clearScreen();
void setBackground(unsigned char colour);
void setForeground(unsigned char colour);
void setRotation(unsigned char rotation);
void setFontSize(unsigned char size);
void gotoBegOfLine();
void gotoPosText(unsigned char x, unsigned char y);
void gotoPosPixel(unsigned char x, unsigned char y);
void drawLine(unsigned char x1, unsigned char y1, unsigned char x2, unsigned char y2);
void drawBox(unsigned char x1, unsigned char y1, unsigned char x2, unsigned char y2, bool filled);
void drawCircle(unsigned char x, unsigned char y, unsigned char radius, bool filled);
void displayBitmap(unsigned char x, unsigned char y, const char* filename);
void setBrightness(unsigned char brightness);
void displayText(const char* text);
};
#endif

BIN
TFTSerial/DMR_sm.bmp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

BIN
TFTSerial/DStar_sm.bmp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

BIN
TFTSerial/MMDVM_sm.bmp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 25 KiB

BIN
TFTSerial/NXDN_sm.bmp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 23 KiB

BIN
TFTSerial/P25_sm.bmp Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 24 KiB

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