Merge branch 'AX25_FM' into M17_AX25_FM

This commit is contained in:
Jonathan Naylor 2020-11-06 15:43:12 +00:00
commit a57397e274
59 changed files with 6401 additions and 3612 deletions

252
AX25Control.cpp Normal file
View file

@ -0,0 +1,252 @@
/*
* 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;
}

50
AX25Control.h Normal file
View file

@ -0,0 +1,50 @@
/*
* 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

39
AX25Defines.h Normal file
View file

@ -0,0 +1,39 @@
/*
* 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

183
AX25Network.cpp Normal file
View file

@ -0,0 +1,183 @@
/*
* 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;
}
}

62
AX25Network.h Normal file
View file

@ -0,0 +1,62 @@
/*
* 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(CModem* modem) :
CCASTInfo::CCASTInfo(IModem* modem) :
CDisplay(),
m_modem(modem),
m_ipaddress()

View file

@ -28,7 +28,7 @@
class CCASTInfo : public CDisplay
{
public:
CCASTInfo(CModem* modem);
CCASTInfo(IModem* modem);
virtual ~CCASTInfo();
virtual bool open();
@ -67,7 +67,7 @@ protected:
virtual void clearCWInt();
private:
CModem* m_modem;
IModem* m_modem;
std::string m_ipaddress;
};

1620
Conf.cpp

File diff suppressed because it is too large Load diff

57
Conf.h
View file

@ -66,6 +66,7 @@ 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;
@ -87,6 +88,7 @@ public:
float getModemM17TXLevel() const;
float getModemPOCSAGTXLevel() const;
float getModemFMTXLevel() const;
float getModemAX25TXLevel() const;
std::string getModemRSSIMappingFile() const;
bool getModemUseCOSAsLockout() const;
bool getModemTrace() const;
@ -174,6 +176,14 @@ public:
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;
@ -203,9 +213,13 @@ 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;
@ -272,6 +286,22 @@ 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;
@ -353,6 +383,7 @@ private:
std::string m_modemPort;
std::string m_modemProtocol;
unsigned int m_modemSpeed;
unsigned int m_modemAddress;
bool m_modemRXInvert;
bool m_modemTXInvert;
@ -374,6 +405,7 @@ private:
float m_modemM17TXLevel;
float m_modemPOCSAGTXLevel;
float m_modemFMTXLevel;
float m_modemAX25TXLevel;
std::string m_modemRSSIMappingFile;
bool m_modemUseCOSAsLockout;
bool m_modemTrace;
@ -480,9 +512,20 @@ 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;
@ -542,6 +585,20 @@ 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, CModem* modem, CDMRNetwork* 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, IModem* modem, CDMRNetwork* 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, CModem* modem, CDMRNetwork* 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, IModem* modem, CDMRNetwork* 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;
CModem* m_modem;
IModem* m_modem;
CDMRNetwork* 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;
CModem* CDMRSlot::m_modem = NULL;
IModem* CDMRSlot::m_modem = NULL;
CDMRNetwork* 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, CModem* modem, CDMRNetwork* 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, IModem* modem, CDMRNetwork* network, CDisplay* display, bool duplex, CDMRLookup* lookup, CRSSIInterpolator* rssiMapper, unsigned int jitter, DMR_OVCM_TYPES ovcm)
{
assert(modem != NULL);
assert(display != NULL);

View file

@ -1,5 +1,5 @@
/*
* Copyright (C) 2015-2019 by Jonathan Naylor G4KLX
* 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
@ -62,7 +62,7 @@ public:
void enable(bool enabled);
static void init(unsigned int colorCode, bool embeddedLCOnly, bool dumpTAData, unsigned int callHang, CModem* modem, CDMRNetwork* 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, IModem* modem, CDMRNetwork* 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 CModem* m_modem;
static IModem* m_modem;
static CDMRNetwork* m_network;
static CDisplay* m_display;
static bool m_duplex;

View file

@ -537,7 +537,7 @@ int CDisplay::writeNXDNIntEx(const class CUserDBentry& source, bool group, unsig
/* Factory method extracted from MMDVMHost.cpp - BG5HHP */
CDisplay* CDisplay::createDisplay(const CConf& conf, CUMP* ump, CModem* modem)
CDisplay* CDisplay::createDisplay(const CConf& conf, CUMP* ump, IModem* modem)
{
CDisplay *display = NULL;
@ -556,9 +556,9 @@ CDisplay* CDisplay::createDisplay(const CConf& conf, CUMP* ump, CModem* modem)
ISerialPort* serial = NULL;
if (port == "modem")
serial = new CModemSerialPort(modem);
serial = new IModemSerialPort(modem);
else
serial = new CSerialController(port, (type == "TFT Serial") ? SERIAL_9600 : SERIAL_115200);
serial = new CSerialController(port, (type == "TFT Serial") ? 9600U : 115200U);
if (type == "TFT Surenoo")
display = new CTFTSurenoo(conf.getCallsign(), dmrid, serial, brightness, conf.getDuplex());
@ -602,7 +602,7 @@ CDisplay* CDisplay::createDisplay(const CConf& conf, CUMP* ump, CModem* modem)
}
if (port == "modem") {
ISerialPort* serial = new CModemSerialPort(modem);
ISerialPort* serial = new IModemSerialPort(modem);
display = new CNextion(conf.getCallsign(), dmrid, serial, brightness, displayClock, utc, idleBrightness, screenLayout, txFrequency, rxFrequency, displayTempInF);
} else if (port == "ump") {
if (ump != NULL) {
@ -612,11 +612,11 @@ CDisplay* CDisplay::createDisplay(const CConf& conf, CUMP* ump, CModem* modem)
display = new CNullDisplay;
}
} else {
SERIAL_SPEED baudrate = SERIAL_9600;
if (screenLayout&0x0cU)
baudrate = SERIAL_115200;
unsigned int baudrate = 9600U;
if (screenLayout == 4U)
baudrate = 115200U;
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,13 +21,14 @@
#include "Timer.h"
#include "UserDBentry.h"
#include "Modem.h"
#include <string>
#include <cstdint>
class CConf;
class CModem;
class IModem;
class CUMP;
class CDisplay
@ -86,7 +87,7 @@ public:
void clock(unsigned int ms);
static CDisplay* createDisplay(const CConf& conf, CUMP* ump, CModem* modem);
static CDisplay* createDisplay(const CConf& conf, CUMP* ump, IModem* modem);
protected:
virtual void setIdleInt() = 0;

179
FMControl.cpp Normal file
View file

@ -0,0 +1,179 @@
/*
* 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
}

55
FMControl.h Normal file
View file

@ -0,0 +1,55 @@
/*
* 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

271
FMNetwork.cpp Normal file
View file

@ -0,0 +1,271 @@
/*
* 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;
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);
}
CFMNetwork::~CFMNetwork()
{
::src_delete(m_incoming);
::src_delete(m_outgoing);
}
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(m_outgoing != NULL);
assert(data != NULL);
assert(nSamples > 0U);
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;
}
unsigned int length = 3U;
unsigned char buffer[1500U];
::memset(buffer, 0x00U, 1500U);
buffer[0U] = 'F';
buffer[1U] = 'M';
buffer[2U] = 'D';
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);
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(m_incoming != NULL);
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));
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 {
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;
}
}
void CFMNetwork::reset()
{
assert(m_incoming != NULL);
assert(m_outgoing != NULL);
m_buffer.clear();
::src_reset(m_incoming);
::src_reset(m_outgoing);
}
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);
}

67
FMNetwork.h Normal file
View file

@ -0,0 +1,67 @@
/*
* 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"
#include <samplerate.h>
#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;
SRC_STATE* m_incoming;
SRC_STATE* m_outgoing;
bool writePoll();
};
#endif

View file

@ -1,5 +1,5 @@
/*
* Copyright (C) 2002-2004,2007-2011,2013,2014-2017 by Jonathan Naylor G4KLX
* Copyright (C) 2002-2004,2007-2011,2013,2014-2017,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
@ -17,6 +17,8 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#if defined(__linux__)
#include "I2CController.h"
#include "Log.h"
@ -24,52 +26,18 @@
#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, SERIAL_SPEED speed, unsigned int address, bool assertRTS) :
CSerialController(device, speed, assertRTS),
m_address(address)
CI2CController::CI2CController(const std::string& device, unsigned int address) :
m_device(device),
m_address(address),
m_fd(-1)
{
}
@ -81,7 +49,6 @@ 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());
@ -89,19 +56,16 @@ bool CI2CController::open()
}
if (::ioctl(m_fd, I2C_TENBIT, 0) < 0) {
LogError("CI2C: failed to set 7bitaddress");
LogError("I2C: failed to set 7bitaddress");
::close(m_fd);
return false;
}
if (::ioctl(m_fd, I2C_SLAVE, m_address) < 0) {
LogError("CI2C: Failed to acquire bus access/talk to slave 0x%02X", m_address);
LogError("I2C: 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;
}
@ -117,7 +81,6 @@ 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) {
@ -128,7 +91,6 @@ int CI2CController::read(unsigned char* buffer, unsigned int length)
if (n > 0)
offset += n;
#endif
}
return length;
@ -144,10 +106,7 @@ int CI2CController::write(const unsigned char* buffer, unsigned int length)
unsigned int ptr = 0U;
while (ptr < length) {
ssize_t n = 0U;
#if defined(__linux__)
n = ::write(m_fd, buffer + ptr, 1U);
#endif
ssize_t n = ::write(m_fd, buffer + ptr, 1U);
if (n < 0) {
if (errno != EAGAIN) {
LogError("Error returned from write(), errno=%d", errno);
@ -162,4 +121,12 @@ 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 by Jonathan Naylor G4KLX
* Copyright (C) 2002-2004,2007-2009,2011-2013,2015-2017,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
@ -20,11 +20,15 @@
#ifndef I2CController_H
#define I2CController_H
#include "SerialController.h"
#if defined(__linux__)
class CI2CController : public CSerialController {
#include "SerialPort.h"
#include <string>
class CI2CController : public ISerialPort {
public:
CI2CController(const std::string& device, SERIAL_SPEED speed, unsigned int address = 0x22U, bool assertRTS = false);
CI2CController(const std::string& device, unsigned int address = 0x22U);
virtual ~CI2CController();
virtual bool open();
@ -33,8 +37,14 @@ 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

60
IIRDirectForm1Filter.cpp Normal file
View file

@ -0,0 +1,60 @@
/*
* 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;
}

50
IIRDirectForm1Filter.h Normal file
View file

@ -0,0 +1,50 @@
/*
* 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

View file

@ -40,6 +40,7 @@ Time=24
# Port=/dev/ttyAMA0
Port=\\.\COM4
Protocol=uart
Speed=115200
# Address=0x22
TXInvert=1
RXInvert=0
@ -62,6 +63,7 @@ RFLevel=100
# M17TXLevel-50
# POCSAGTXLevel=50
# FMTXLevel=50
# AX25TXLevel=50
RSSIMappingFile=RSSI.dat
UseCOSAsLockout=0
Trace=0
@ -174,9 +176,22 @@ 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
@ -241,6 +256,22 @@ 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

View file

@ -21,6 +21,8 @@
#include "NXDNIcomNetwork.h"
#include "RSSIInterpolator.h"
#include "SerialController.h"
#include "SerialModem.h"
#include "NullModem.h"
#include "Version.h"
#include "StopWatch.h"
#include "Defines.h"
@ -122,6 +124,8 @@ m_p25(NULL),
m_nxdn(NULL),
m_m17(NULL),
m_pocsag(NULL),
m_fm(NULL),
m_ax25(NULL),
m_dstarNetwork(NULL),
m_dmrNetwork(NULL),
m_ysfNetwork(NULL),
@ -129,6 +133,8 @@ m_p25Network(NULL),
m_nxdnNetwork(NULL),
m_m17Network(NULL),
m_pocsagNetwork(NULL),
m_fmNetwork(NULL),
m_ax25Network(NULL),
m_display(NULL),
m_ump(NULL),
m_mode(MODE_IDLE),
@ -138,6 +144,7 @@ m_ysfRFModeHang(10U),
m_p25RFModeHang(10U),
m_nxdnRFModeHang(10U),
m_m17RFModeHang(10U),
m_fmRFModeHang(10U),
m_dstarNetModeHang(3U),
m_dmrNetModeHang(3U),
m_ysfNetModeHang(3U),
@ -145,6 +152,7 @@ m_p25NetModeHang(3U),
m_nxdnNetModeHang(3U),
m_m17NetModeHang(3U),
m_pocsagNetModeHang(3U),
m_fmNetModeHang(3U),
m_modeTimer(1000U),
m_dmrTXTimer(1000U),
m_cwIdTimer(1000U),
@ -158,6 +166,7 @@ m_nxdnEnabled(false),
m_m17Enabled(false),
m_pocsagEnabled(false),
m_fmEnabled(false),
m_ax25Enabled(false),
m_cwIdTime(0U),
m_dmrLookup(NULL),
m_nxdnLookup(NULL),
@ -334,6 +343,18 @@ int CMMDVMHost::run()
return 1;
}
if (m_fmEnabled && m_conf.getFMNetworkEnabled()) {
ret = createFMNetwork();
if (!ret)
return 1;
}
if (m_ax25Enabled && m_conf.getAX25NetworkEnabled()) {
ret = createAX25Network();
if (!ret)
return 1;
}
sockaddr_storage transparentAddress;
unsigned int transparentAddrLen;
CUDPSocket* transparentSocket = NULL;
@ -641,6 +662,29 @@ int CMMDVMHost::run()
pocsagTimer.start();
}
if (m_ax25Enabled) {
unsigned int txDelay = m_conf.getAX25TXDelay();
int rxTwist = m_conf.getAX25RXTwist();
unsigned int slotTime = m_conf.getAX25SlotTime();
unsigned int pPersist = m_conf.getAX25PPersist();
bool trace = m_conf.getAX25Trace();
LogInfo("AX.25 RF Parameters");
LogInfo(" TX Delay: %ums", txDelay);
LogInfo(" RX Twist: %d", rxTwist);
LogInfo(" Slot Time: %ums", slotTime);
LogInfo(" P-Persist: %u", pPersist);
LogInfo(" Trace: %s", trace ? "yes" : "no");
m_ax25 = new CAX25Control(m_ax25Network, trace);
}
if (m_fmEnabled) {
m_fmRFModeHang = m_conf.getFMModeHang();
m_fm = new CFMControl(m_fmNetwork);
}
bool remoteControlEnabled = m_conf.getRemoteControlEnabled();
if (remoteControlEnabled) {
std::string address = m_conf.getRemoteControlAddress();
@ -680,12 +724,6 @@ int CMMDVMHost::run()
else if (!error && m_mode == MODE_ERROR)
setMode(MODE_IDLE);
unsigned char mode = m_modem->getMode();
if (mode == MODE_FM && m_mode != MODE_FM)
setMode(mode);
else if (mode != MODE_FM && m_mode == MODE_FM)
setMode(mode);
if (m_ump != NULL) {
bool tx = m_modem->hasTX();
m_ump->setTX(tx);
@ -693,7 +731,7 @@ int CMMDVMHost::run()
m_ump->setCD(cd);
}
unsigned char data[220U];
unsigned char data[500U];
unsigned int len;
bool ret;
@ -851,6 +889,31 @@ int CMMDVMHost::run()
}
}
len = m_modem->readFMData(data);
if (m_fm != NULL && len > 0U) {
if (m_mode == MODE_IDLE) {
bool ret = m_fm->writeModem(data, len);
if (ret) {
m_modeTimer.setTimeout(m_fmRFModeHang);
setMode(MODE_FM);
}
} else if (m_mode == MODE_FM) {
m_fm->writeModem(data, len);
m_modeTimer.start();
} else if (m_mode != MODE_LOCKOUT) {
LogWarning("FM modem data received when in mode %u", m_mode);
}
}
len = m_modem->readAX25Data(data);
if (m_ax25 != NULL && len > 0U) {
if (m_mode == MODE_IDLE || m_mode == MODE_FM) {
m_ax25->writeModem(data, len);
} else if (m_mode != MODE_LOCKOUT) {
LogWarning("NXDN modem data received when in mode %u", m_mode);
}
}
len = m_modem->readTransparentData(data);
if (transparentSocket != NULL && len > 0U)
transparentSocket->write(data, len, transparentAddress, transparentAddrLen);
@ -1020,6 +1083,40 @@ int CMMDVMHost::run()
}
}
if (m_fm != NULL) {
unsigned int space = m_modem->getFMSpace();
if (space > 0U) {
len = m_fm->readModem(data, space);
if (len > 0U) {
if (m_mode == MODE_IDLE) {
m_modeTimer.setTimeout(m_fmNetModeHang);
setMode(MODE_FM);
}
if (m_mode == MODE_FM) {
m_modem->writeFMData(data, len);
m_modeTimer.start();
} else if (m_mode != MODE_LOCKOUT) {
LogWarning("FM data received when in mode %u", m_mode);
}
}
}
}
if (m_ax25 != NULL) {
ret = m_modem->hasAX25Space();
if (ret) {
len = m_ax25->readModem(data);
if (len > 0U) {
if (m_mode == MODE_IDLE || m_mode == MODE_FM) {
m_modem->writeAX25Data(data, len);
}
else if (m_mode != MODE_LOCKOUT) {
LogWarning("AX.25 data received when in mode %u", m_mode);
}
}
}
}
if (transparentSocket != NULL) {
sockaddr_storage address;
unsigned int addrlen;
@ -1054,6 +1151,8 @@ int CMMDVMHost::run()
m_m17->clock(ms);
if (m_pocsag != NULL)
m_pocsag->clock(ms);
if (m_fm != NULL)
m_fm->clock(ms);
if (m_dstarNetwork != NULL)
m_dstarNetwork->clock(ms);
@ -1069,6 +1168,8 @@ int CMMDVMHost::run()
m_m17Network->clock(ms);
if (m_pocsagNetwork != NULL)
m_pocsagNetwork->clock(ms);
if (m_fmNetwork != NULL)
m_fmNetwork->clock(ms);
m_cwIdTimer.clock(ms);
if (m_cwIdTimer.isRunning() && m_cwIdTimer.hasExpired()) {
@ -1191,6 +1292,16 @@ int CMMDVMHost::run()
delete m_pocsagNetwork;
}
if (m_fmNetwork != NULL) {
m_fmNetwork->close();
delete m_fmNetwork;
}
if (m_ax25Network != NULL) {
m_ax25Network->close();
delete m_ax25Network;
}
if (transparentSocket != NULL) {
transparentSocket->close();
delete transparentSocket;
@ -1208,6 +1319,8 @@ int CMMDVMHost::run()
delete m_nxdn;
delete m_m17;
delete m_pocsag;
delete m_fm;
delete m_ax25;
return 0;
}
@ -1216,6 +1329,7 @@ bool CMMDVMHost::createModem()
{
std::string port = m_conf.getModemPort();
std::string protocol = m_conf.getModemProtocol();
unsigned int speed = m_conf.getModemSpeed();
unsigned int address = m_conf.getModemAddress();
bool rxInvert = m_conf.getModemRXInvert();
bool txInvert = m_conf.getModemTXInvert();
@ -1232,6 +1346,7 @@ bool CMMDVMHost::createModem()
float m17TXLevel = m_conf.getModemM17TXLevel();
float pocsagTXLevel = m_conf.getModemPOCSAGTXLevel();
float fmTXLevel = m_conf.getModemFMTXLevel();
float ax25TXLevel = m_conf.getModemAX25TXLevel();
bool trace = m_conf.getModemTrace();
bool debug = m_conf.getModemDebug();
unsigned int colorCode = m_conf.getDMRColorCode();
@ -1248,13 +1363,21 @@ bool CMMDVMHost::createModem()
int rxDCOffset = m_conf.getModemRXDCOffset();
int txDCOffset = m_conf.getModemTXDCOffset();
float rfLevel = m_conf.getModemRFLevel();
int rxTwist = m_conf.getAX25RXTwist();
unsigned int ax25TXDelay = m_conf.getAX25TXDelay();
unsigned int ax25SlotTime = m_conf.getAX25SlotTime();
unsigned int ax25PPersist = m_conf.getAX25PPersist();
bool useCOSAsLockout = m_conf.getModemUseCOSAsLockout();
LogInfo("Modem Parameters");
LogInfo(" Port: %s", port.c_str());
#if defined(__linux__)
LogInfo(" Protocol: %s", protocol.c_str());
if (protocol == "i2c")
LogInfo(" i2c Address: %02X", address);
LogInfo(" I2C Address: %02X", address);
else
#endif
LogInfo(" Speed: %u", speed);
LogInfo(" RX Invert: %s", rxInvert ? "yes" : "no");
LogInfo(" TX Invert: %s", txInvert ? "yes" : "no");
LogInfo(" PTT Invert: %s", pttInvert ? "yes" : "no");
@ -1275,51 +1398,58 @@ bool CMMDVMHost::createModem()
LogInfo(" M17 TX Level: %.1f%%", m17TXLevel);
LogInfo(" POCSAG TX Level: %.1f%%", pocsagTXLevel);
LogInfo(" FM TX Level: %.1f%%", fmTXLevel);
LogInfo(" AX.25 TX Level: %.1f%%", ax25TXLevel);
LogInfo(" TX Frequency: %uHz (%uHz)", txFrequency, txFrequency + txOffset);
LogInfo(" Use COS as Lockout: %s", useCOSAsLockout ? "yes" : "no");
m_modem = CModem::createModem(port, m_duplex, rxInvert, txInvert, pttInvert, txDelay, dmrDelay, useCOSAsLockout, trace, debug);
m_modem->setSerialParams(protocol, address);
m_modem->setModeParams(m_dstarEnabled, m_dmrEnabled, m_ysfEnabled, m_p25Enabled, m_nxdnEnabled, m_m17Enabled, m_pocsagEnabled, m_fmEnabled);
m_modem->setLevels(rxLevel, cwIdTXLevel, dstarTXLevel, dmrTXLevel, ysfTXLevel, p25TXLevel, nxdnTXLevel, m17TXLevel, pocsagTXLevel, fmTXLevel);
if (port == "NullModem")
m_modem = new CNullModem;
else
m_modem = new CSerialModem(port, m_duplex, rxInvert, txInvert, pttInvert, txDelay, dmrDelay, useCOSAsLockout, trace, debug);
m_modem->setSerialParams(protocol, address, speed);
m_modem->setModeParams(m_dstarEnabled, m_dmrEnabled, m_ysfEnabled, m_p25Enabled, m_nxdnEnabled, m_m17Enabled, m_pocsagEnabled, m_fmEnabled, m_ax25Enabled);
m_modem->setLevels(rxLevel, cwIdTXLevel, dstarTXLevel, dmrTXLevel, ysfTXLevel, p25TXLevel, nxdnTXLevel, m17TXLevel, pocsagTXLevel, fmTXLevel, ax25TXLevel);
m_modem->setRFParams(rxFrequency, rxOffset, txFrequency, txOffset, txDCOffset, rxDCOffset, rfLevel, pocsagFrequency);
m_modem->setDMRParams(colorCode);
m_modem->setYSFParams(lowDeviation, ysfTXHang);
m_modem->setP25Params(p25TXHang);
m_modem->setNXDNParams(nxdnTXHang);
m_modem->setM17Params(m17TXHang);
m_modem->setAX25Params(rxTwist, ax25TXDelay, ax25SlotTime, ax25PPersist);
if (m_fmEnabled) {
std::string callsign = m_conf.getFMCallsign();
unsigned int callsignSpeed = m_conf.getFMCallsignSpeed();
unsigned int callsignFrequency = m_conf.getFMCallsignFrequency();
unsigned int callsignTime = m_conf.getFMCallsignTime();
unsigned int callsignHoldoff = m_conf.getFMCallsignHoldoff();
float callsignHighLevel = m_conf.getFMCallsignHighLevel();
float callsignLowLevel = m_conf.getFMCallsignLowLevel();
bool callsignAtStart = m_conf.getFMCallsignAtStart();
bool callsignAtEnd = m_conf.getFMCallsignAtEnd();
bool callsignAtLatch = m_conf.getFMCallsignAtLatch();
std::string rfAck = m_conf.getFMRFAck();
std::string extAck = m_conf.getFMExtAck();
unsigned int ackSpeed = m_conf.getFMAckSpeed();
unsigned int ackFrequency = m_conf.getFMAckFrequency();
unsigned int ackMinTime = m_conf.getFMAckMinTime();
unsigned int ackDelay = m_conf.getFMAckDelay();
float ackLevel = m_conf.getFMAckLevel();
unsigned int timeout = m_conf.getFMTimeout();
float timeoutLevel = m_conf.getFMTimeoutLevel();
float ctcssFrequency = m_conf.getFMCTCSSFrequency();
unsigned int ctcssHighThreshold = m_conf.getFMCTCSSHighThreshold();
unsigned int ctcssLowThreshold = m_conf.getFMCTCSSLowThreshold();
float ctcssLevel = m_conf.getFMCTCSSLevel();
unsigned int kerchunkTime = m_conf.getFMKerchunkTime();
unsigned int hangTime = m_conf.getFMHangTime();
unsigned int accessMode = m_conf.getFMAccessMode();
bool cosInvert = m_conf.getFMCOSInvert();
unsigned int rfAudioBoost = m_conf.getFMRFAudioBoost();
float maxDevLevel = m_conf.getFMMaxDevLevel();
unsigned int extAudioBoost = m_conf.getFMExtAudioBoost();
std::string callsign = m_conf.getFMCallsign();
unsigned int callsignSpeed = m_conf.getFMCallsignSpeed();
unsigned int callsignFrequency = m_conf.getFMCallsignFrequency();
unsigned int callsignTime = m_conf.getFMCallsignTime();
unsigned int callsignHoldoff = m_conf.getFMCallsignHoldoff();
float callsignHighLevel = m_conf.getFMCallsignHighLevel();
float callsignLowLevel = m_conf.getFMCallsignLowLevel();
bool callsignAtStart = m_conf.getFMCallsignAtStart();
bool callsignAtEnd = m_conf.getFMCallsignAtEnd();
bool callsignAtLatch = m_conf.getFMCallsignAtLatch();
std::string rfAck = m_conf.getFMRFAck();
unsigned int ackSpeed = m_conf.getFMAckSpeed();
unsigned int ackFrequency = m_conf.getFMAckFrequency();
unsigned int ackMinTime = m_conf.getFMAckMinTime();
unsigned int ackDelay = m_conf.getFMAckDelay();
float ackLevel = m_conf.getFMAckLevel();
unsigned int timeout = m_conf.getFMTimeout();
float timeoutLevel = m_conf.getFMTimeoutLevel();
float ctcssFrequency = m_conf.getFMCTCSSFrequency();
unsigned int ctcssHighThreshold = m_conf.getFMCTCSSHighThreshold();
unsigned int ctcssLowThreshold = m_conf.getFMCTCSSLowThreshold();
float ctcssLevel = m_conf.getFMCTCSSLevel();
unsigned int kerchunkTime = m_conf.getFMKerchunkTime();
unsigned int hangTime = m_conf.getFMHangTime();
unsigned int accessMode = m_conf.getFMAccessMode();
bool cosInvert = m_conf.getFMCOSInvert();
bool noiseSquelch = m_conf.getFMNoiseSquelch();
unsigned int squelchHighThreshold = m_conf.getFMSquelchHighThreshold();
unsigned int squelchLowThreshold = m_conf.getFMSquelchLowThreshold();
unsigned int rfAudioBoost = m_conf.getFMRFAudioBoost();
float maxDevLevel = m_conf.getFMMaxDevLevel();
unsigned int modeHangTime = m_conf.getFMModeHang();
LogInfo("FM Parameters");
LogInfo(" Callsign: %s", callsign.c_str());
@ -1333,7 +1463,6 @@ bool CMMDVMHost::createModem()
LogInfo(" Callsign At End: %s", callsignAtEnd ? "yes" : "no");
LogInfo(" Callsign At Latch: %s", callsignAtLatch ? "yes" : "no");
LogInfo(" RF Ack: %s", rfAck.c_str());
// LogInfo(" Ext. Ack: %s", extAck.c_str());
LogInfo(" Ack Speed: %uWPM", ackSpeed);
LogInfo(" Ack Frequency: %uHz", ackFrequency);
LogInfo(" Ack Min Time: %us", ackMinTime);
@ -1349,13 +1478,30 @@ bool CMMDVMHost::createModem()
LogInfo(" Hang Time: %us", hangTime);
LogInfo(" Access Mode: %u", accessMode);
LogInfo(" COS Invert: %s", cosInvert ? "yes" : "no");
LogInfo(" Noise Squelch: %s", noiseSquelch ? "yes" : "no");
if (noiseSquelch) {
LogInfo(" Squelch High Threshold: %u", squelchHighThreshold);
LogInfo(" Squelch Low Threshold: %u", squelchLowThreshold);
}
LogInfo(" RF Audio Boost: x%u", rfAudioBoost);
LogInfo(" Max. Deviation Level: %.1f%%", maxDevLevel);
// LogInfo(" Ext. Audio Boost: x%u", extAudioBoost);
LogInfo(" Mode Hang: %us", modeHangTime);
m_modem->setFMCallsignParams(callsign, callsignSpeed, callsignFrequency, callsignTime, callsignHoldoff, callsignHighLevel, callsignLowLevel, callsignAtStart, callsignAtEnd, callsignAtLatch);
m_modem->setFMAckParams(rfAck, ackSpeed, ackFrequency, ackMinTime, ackDelay, ackLevel);
m_modem->setFMMiscParams(timeout, timeoutLevel, ctcssFrequency, ctcssHighThreshold, ctcssLowThreshold, ctcssLevel, kerchunkTime, hangTime, accessMode, cosInvert, rfAudioBoost, maxDevLevel);
m_modem->setFMMiscParams(timeout, timeoutLevel, ctcssFrequency, ctcssHighThreshold, ctcssLowThreshold, ctcssLevel, kerchunkTime, hangTime, accessMode, cosInvert, noiseSquelch, squelchHighThreshold, squelchLowThreshold, rfAudioBoost, maxDevLevel);
if (m_conf.getFMNetworkEnabled()) {
std::string extAck = m_conf.getFMExtAck();
unsigned int extAudioBoost = m_conf.getFMExtAudioBoost();
LogInfo(" Ext. Ack: %s", extAck.c_str());
LogInfo(" Ext. Audio Boost: x%u", extAudioBoost);
m_modem->setFMExtParams(extAck, extAudioBoost);
}
}
bool ret = m_modem->open();
@ -1599,6 +1745,62 @@ bool CMMDVMHost::createPOCSAGNetwork()
return true;
}
bool CMMDVMHost::createFMNetwork()
{
std::string gatewayAddress = m_conf.getFMGatewayAddress();
unsigned int gatewayPort = m_conf.getFMGatewayPort();
std::string localAddress = m_conf.getFMLocalAddress();
unsigned int localPort = m_conf.getFMLocalPort();
unsigned int sampleRate = m_conf.getFMSampleRate();
m_fmNetModeHang = m_conf.getFMNetworkModeHang();
bool debug = m_conf.getFMNetworkDebug();
LogInfo("FM Network Parameters");
LogInfo(" Gateway Address: %s", gatewayAddress.c_str());
LogInfo(" Gateway Port: %u", gatewayPort);
LogInfo(" Local Address: %s", localAddress.c_str());
LogInfo(" Local Port: %u", localPort);
LogInfo(" Sample Rate: %u", sampleRate);
LogInfo(" Mode Hang: %us", m_fmNetModeHang);
m_fmNetwork = new CFMNetwork(localAddress, localPort, gatewayAddress, gatewayPort, sampleRate, debug);
bool ret = m_fmNetwork->open();
if (!ret) {
delete m_fmNetwork;
m_fmNetwork = NULL;
return false;
}
m_fmNetwork->enable(true);
return true;
}
bool CMMDVMHost::createAX25Network()
{
std::string port = m_conf.getAX25NetworkPort();
unsigned int speed = m_conf.getAX25NetworkSpeed();
bool debug = m_conf.getAX25NetworkDebug();
LogInfo("AX.25 Network Parameters");
LogInfo(" Port: %s", port.c_str());
LogInfo(" Speed: %u", speed);
m_ax25Network = new CAX25Network(port, speed, debug);
bool ret = m_ax25Network->open();
if (!ret) {
delete m_ax25Network;
m_ax25Network = NULL;
return false;
}
m_ax25Network->enable(true);
return true;
}
void CMMDVMHost::readParams()
{
m_dstarEnabled = m_conf.getDStarEnabled();
@ -1609,6 +1811,7 @@ void CMMDVMHost::readParams()
m_m17Enabled = m_conf.getM17Enabled();
m_pocsagEnabled = m_conf.getPOCSAGEnabled();
m_fmEnabled = m_conf.getFMEnabled();
m_ax25Enabled = m_conf.getAX25Enabled();
m_duplex = m_conf.getDuplex();
m_callsign = m_conf.getCallsign();
m_id = m_conf.getId();
@ -1627,6 +1830,7 @@ void CMMDVMHost::readParams()
LogInfo(" M17: %s", m_m17Enabled ? "enabled" : "disabled");
LogInfo(" POCSAG: %s", m_pocsagEnabled ? "enabled" : "disabled");
LogInfo(" FM: %s", m_fmEnabled ? "enabled" : "disabled");
LogInfo(" AX.25: %s", m_ax25Enabled ? "enabled" : "disabled");
}
void CMMDVMHost::setMode(unsigned char mode)
@ -1650,6 +1854,10 @@ void CMMDVMHost::setMode(unsigned char mode)
m_m17Network->enable(false);
if (m_pocsagNetwork != NULL)
m_pocsagNetwork->enable(false);
if (m_fmNetwork != NULL)
m_fmNetwork->enable(false);
if (m_ax25Network != NULL)
m_ax25Network->enable(false);
if (m_dstar != NULL)
m_dstar->enable(true);
if (m_dmr != NULL)
@ -1664,6 +1872,10 @@ void CMMDVMHost::setMode(unsigned char mode)
m_m17->enable(false);
if (m_pocsag != NULL)
m_pocsag->enable(false);
if (m_fm != NULL)
m_fm->enable(false);
if (m_ax25 != NULL)
m_ax25->enable(false);
m_modem->setMode(MODE_DSTAR);
if (m_ump != NULL)
m_ump->setMode(MODE_DSTAR);
@ -1688,6 +1900,10 @@ void CMMDVMHost::setMode(unsigned char mode)
m_m17Network->enable(false);
if (m_pocsagNetwork != NULL)
m_pocsagNetwork->enable(false);
if (m_fmNetwork != NULL)
m_fmNetwork->enable(false);
if (m_ax25Network != NULL)
m_ax25Network->enable(false);
if (m_dstar != NULL)
m_dstar->enable(false);
if (m_dmr != NULL)
@ -1702,6 +1918,10 @@ void CMMDVMHost::setMode(unsigned char mode)
m_m17->enable(false);
if (m_pocsag != NULL)
m_pocsag->enable(false);
if (m_fm != NULL)
m_fm->enable(false);
if (m_ax25 != NULL)
m_ax25->enable(false);
m_modem->setMode(MODE_DMR);
if (m_ump != NULL)
m_ump->setMode(MODE_DMR);
@ -1730,6 +1950,10 @@ void CMMDVMHost::setMode(unsigned char mode)
m_m17Network->enable(false);
if (m_pocsagNetwork != NULL)
m_pocsagNetwork->enable(false);
if (m_fmNetwork != NULL)
m_fmNetwork->enable(false);
if (m_ax25Network != NULL)
m_ax25Network->enable(false);
if (m_dstar != NULL)
m_dstar->enable(false);
if (m_dmr != NULL)
@ -1744,6 +1968,10 @@ void CMMDVMHost::setMode(unsigned char mode)
m_m17->enable(false);
if (m_pocsag != NULL)
m_pocsag->enable(false);
if (m_fm != NULL)
m_fm->enable(false);
if (m_ax25 != NULL)
m_ax25->enable(false);
m_modem->setMode(MODE_YSF);
if (m_ump != NULL)
m_ump->setMode(MODE_YSF);
@ -1768,6 +1996,10 @@ void CMMDVMHost::setMode(unsigned char mode)
m_m17Network->enable(false);
if (m_pocsagNetwork != NULL)
m_pocsagNetwork->enable(false);
if (m_fmNetwork != NULL)
m_fmNetwork->enable(false);
if (m_ax25Network != NULL)
m_ax25Network->enable(false);
if (m_dstar != NULL)
m_dstar->enable(false);
if (m_dmr != NULL)
@ -1782,6 +2014,10 @@ void CMMDVMHost::setMode(unsigned char mode)
m_m17->enable(false);
if (m_pocsag != NULL)
m_pocsag->enable(false);
if (m_fm != NULL)
m_fm->enable(false);
if (m_ax25 != NULL)
m_ax25->enable(false);
m_modem->setMode(MODE_P25);
if (m_ump != NULL)
m_ump->setMode(MODE_P25);
@ -1806,6 +2042,10 @@ void CMMDVMHost::setMode(unsigned char mode)
m_m17Network->enable(false);
if (m_pocsagNetwork != NULL)
m_pocsagNetwork->enable(false);
if (m_fmNetwork != NULL)
m_fmNetwork->enable(false);
if (m_ax25Network != NULL)
m_ax25Network->enable(false);
if (m_dstar != NULL)
m_dstar->enable(false);
if (m_dmr != NULL)
@ -1820,6 +2060,10 @@ void CMMDVMHost::setMode(unsigned char mode)
m_m17->enable(false);
if (m_pocsag != NULL)
m_pocsag->enable(false);
if (m_fm != NULL)
m_fm->enable(false);
if (m_ax25 != NULL)
m_ax25->enable(false);
m_modem->setMode(MODE_NXDN);
if (m_ump != NULL)
m_ump->setMode(MODE_NXDN);
@ -1882,6 +2126,10 @@ void CMMDVMHost::setMode(unsigned char mode)
m_m17Network->enable(false);
if (m_pocsagNetwork != NULL)
m_pocsagNetwork->enable(true);
if (m_fmNetwork != NULL)
m_fmNetwork->enable(false);
if (m_ax25Network != NULL)
m_ax25Network->enable(false);
if (m_dstar != NULL)
m_dstar->enable(false);
if (m_dmr != NULL)
@ -1896,6 +2144,10 @@ void CMMDVMHost::setMode(unsigned char mode)
m_m17->enable(false);
if (m_pocsag != NULL)
m_pocsag->enable(true);
if (m_fm != NULL)
m_fm->enable(false);
if (m_ax25 != NULL)
m_ax25->enable(false);
m_modem->setMode(MODE_POCSAG);
if (m_ump != NULL)
m_ump->setMode(MODE_POCSAG);
@ -1920,6 +2172,10 @@ void CMMDVMHost::setMode(unsigned char mode)
m_m17Network->enable(false);
if (m_pocsagNetwork != NULL)
m_pocsagNetwork->enable(false);
if (m_fmNetwork != NULL)
m_fmNetwork->enable(true);
if (m_ax25Network != NULL)
m_ax25Network->enable(true);
if (m_dstar != NULL)
m_dstar->enable(false);
if (m_dmr != NULL)
@ -1934,15 +2190,20 @@ void CMMDVMHost::setMode(unsigned char mode)
m_m17->enable(false);
if (m_pocsag != NULL)
m_pocsag->enable(false);
if (m_fm != NULL)
m_fm->enable(true);
if (m_ax25 != NULL)
m_ax25->enable(true);
if (m_mode == MODE_DMR && m_duplex && m_modem->hasTX()) {
m_modem->writeDMRStart(false);
m_dmrTXTimer.stop();
}
m_modem->setMode(MODE_FM);
if (m_ump != NULL)
m_ump->setMode(MODE_FM);
m_display->setFM();
m_mode = MODE_FM;
m_modeTimer.stop();
m_modeTimer.start();
m_cwIdTimer.stop();
createLockFile("FM");
break;
@ -1962,6 +2223,10 @@ void CMMDVMHost::setMode(unsigned char mode)
m_m17Network->enable(false);
if (m_pocsagNetwork != NULL)
m_pocsagNetwork->enable(false);
if (m_fmNetwork != NULL)
m_fmNetwork->enable(false);
if (m_ax25Network != NULL)
m_ax25Network->enable(false);
if (m_dstar != NULL)
m_dstar->enable(false);
if (m_dmr != NULL)
@ -1976,6 +2241,10 @@ void CMMDVMHost::setMode(unsigned char mode)
m_m17->enable(false);
if (m_pocsag != NULL)
m_pocsag->enable(false);
if (m_fm != NULL)
m_fm->enable(false);
if (m_ax25 != NULL)
m_ax25->enable(false);
if (m_mode == MODE_DMR && m_duplex && m_modem->hasTX()) {
m_modem->writeDMRStart(false);
m_dmrTXTimer.stop();
@ -2006,6 +2275,10 @@ void CMMDVMHost::setMode(unsigned char mode)
m_m17Network->enable(false);
if (m_pocsagNetwork != NULL)
m_pocsagNetwork->enable(false);
if (m_fmNetwork != NULL)
m_fmNetwork->enable(false);
if (m_ax25Network != NULL)
m_ax25Network->enable(false);
if (m_dstar != NULL)
m_dstar->enable(false);
if (m_dmr != NULL)
@ -2020,6 +2293,10 @@ void CMMDVMHost::setMode(unsigned char mode)
m_m17->enable(false);
if (m_pocsag != NULL)
m_pocsag->enable(false);
if (m_fm != NULL)
m_fm->enable(false);
if (m_ax25 != NULL)
m_ax25->enable(false);
if (m_mode == MODE_DMR && m_duplex && m_modem->hasTX()) {
m_modem->writeDMRStart(false);
m_dmrTXTimer.stop();
@ -2048,6 +2325,10 @@ void CMMDVMHost::setMode(unsigned char mode)
m_m17Network->enable(true);
if (m_pocsagNetwork != NULL)
m_pocsagNetwork->enable(true);
if (m_fmNetwork != NULL)
m_fmNetwork->enable(true);
if (m_ax25Network != NULL)
m_ax25Network->enable(true);
if (m_dstar != NULL)
m_dstar->enable(true);
if (m_dmr != NULL)
@ -2062,6 +2343,10 @@ void CMMDVMHost::setMode(unsigned char mode)
m_m17->enable(true);
if (m_pocsag != NULL)
m_pocsag->enable(true);
if (m_fm != NULL)
m_fm->enable(true);
if (m_ax25 != NULL)
m_ax25->enable(true);
if (m_mode == MODE_DMR && m_duplex && m_modem->hasTX()) {
m_modem->writeDMRStart(false);
m_dmrTXTimer.stop();
@ -2144,38 +2429,38 @@ void CMMDVMHost::remoteControl()
processModeCommand(MODE_M17, m_m17RFModeHang);
break;
case RCD_MODE_FM:
if (m_fmEnabled != false)
if (m_fmEnabled)
processModeCommand(MODE_FM, 0);
break;
case RCD_ENABLE_DSTAR:
if (m_dstar != NULL && m_dstarEnabled==false)
if (m_dstar != NULL && !m_dstarEnabled)
processEnableCommand(m_dstarEnabled, true);
if (m_dstarNetwork != NULL)
m_dstarNetwork->enable(true);
if (m_dstarNetwork != NULL)
m_dstarNetwork->enable(true);
break;
case RCD_ENABLE_DMR:
if (m_dmr != NULL && m_dmrEnabled==false)
if (m_dmr != NULL && !m_dmrEnabled)
processEnableCommand(m_dmrEnabled, true);
if (m_dmrNetwork != NULL)
m_dmrNetwork->enable(true);
if (m_dmrNetwork != NULL)
m_dmrNetwork->enable(true);
break;
case RCD_ENABLE_YSF:
if (m_ysf != NULL && m_ysfEnabled==false)
if (m_ysf != NULL && !m_ysfEnabled)
processEnableCommand(m_ysfEnabled, true);
if (m_ysfNetwork != NULL)
m_ysfNetwork->enable(true);
if (m_ysfNetwork != NULL)
m_ysfNetwork->enable(true);
break;
case RCD_ENABLE_P25:
if (m_p25 != NULL && m_p25Enabled==false)
if (m_p25 != NULL && !m_p25Enabled)
processEnableCommand(m_p25Enabled, true);
if (m_p25Network != NULL)
m_p25Network->enable(true);
if (m_p25Network != NULL)
m_p25Network->enable(true);
break;
case RCD_ENABLE_NXDN:
if (m_nxdn != NULL && m_nxdnEnabled==false)
if (m_nxdn != NULL && !m_nxdnEnabled)
processEnableCommand(m_nxdnEnabled, true);
if (m_nxdnNetwork != NULL)
m_nxdnNetwork->enable(true);
if (m_nxdnNetwork != NULL)
m_nxdnNetwork->enable(true);
break;
case RCD_ENABLE_M17:
if (m_m17 != NULL && m_m17Enabled == false)
@ -2184,38 +2469,42 @@ void CMMDVMHost::remoteControl()
m_m17Network->enable(true);
break;
case RCD_ENABLE_FM:
if (m_fmEnabled==false)
if (!m_fmEnabled)
processEnableCommand(m_fmEnabled, true);
break;
case RCD_ENABLE_AX25:
if (!m_ax25Enabled)
processEnableCommand(m_ax25Enabled, true);
break;
case RCD_DISABLE_DSTAR:
if (m_dstar != NULL && m_dstarEnabled==true)
if (m_dstar != NULL && m_dstarEnabled)
processEnableCommand(m_dstarEnabled, false);
if (m_dstarNetwork != NULL)
m_dstarNetwork->enable(false);
if (m_dstarNetwork != NULL)
m_dstarNetwork->enable(false);
break;
case RCD_DISABLE_DMR:
if (m_dmr != NULL && m_dmrEnabled==true)
if (m_dmr != NULL && m_dmrEnabled)
processEnableCommand(m_dmrEnabled, false);
if (m_dmrNetwork != NULL)
m_dmrNetwork->enable(false);
if (m_dmrNetwork != NULL)
m_dmrNetwork->enable(false);
break;
case RCD_DISABLE_YSF:
if (m_ysf != NULL && m_ysfEnabled==true)
if (m_ysf != NULL && m_ysfEnabled)
processEnableCommand(m_ysfEnabled, false);
if (m_ysfNetwork != NULL)
m_ysfNetwork->enable(false);
if (m_ysfNetwork != NULL)
m_ysfNetwork->enable(false);
break;
case RCD_DISABLE_P25:
if (m_p25 != NULL && m_p25Enabled==true)
if (m_p25 != NULL && m_p25Enabled)
processEnableCommand(m_p25Enabled, false);
if (m_p25Network != NULL)
m_p25Network->enable(false);
if (m_p25Network != NULL)
m_p25Network->enable(false);
break;
case RCD_DISABLE_NXDN:
if (m_nxdn != NULL && m_nxdnEnabled==true)
if (m_nxdn != NULL && m_nxdnEnabled)
processEnableCommand(m_nxdnEnabled, false);
if (m_nxdnNetwork != NULL)
m_nxdnNetwork->enable(false);
if (m_nxdnNetwork != NULL)
m_nxdnNetwork->enable(false);
break;
case RCD_DISABLE_M17:
if (m_m17 != NULL && m_m17Enabled == true)
@ -2224,9 +2513,13 @@ void CMMDVMHost::remoteControl()
m_m17Network->enable(false);
break;
case RCD_DISABLE_FM:
if (m_fmEnabled == true)
if (m_fmEnabled)
processEnableCommand(m_fmEnabled, false);
break;
case RCD_DISABLE_AX25:
if (m_ax25Enabled == true)
processEnableCommand(m_ax25Enabled, false);
break;
case RCD_PAGE:
if (m_pocsag != NULL) {
unsigned int ric = m_remoteControl->getArgUInt(0U);
@ -2241,15 +2534,15 @@ void CMMDVMHost::remoteControl()
break;
case RCD_CW:
setMode(MODE_IDLE); // Force the modem to go idle so that we can send the CW text.
if (!m_modem->hasTX()){
if (!m_modem->hasTX()) {
std::string cwtext;
for (unsigned int i = 0U; i < m_remoteControl->getArgCount(); i++) {
if (i > 0U)
cwtext += " ";
cwtext += m_remoteControl->getArgString(i);
}
m_display->writeCW();
m_modem->sendCWId(cwtext);
for (unsigned int i = 0U; i < m_remoteControl->getArgCount(); i++) {
if (i > 0U)
cwtext += " ";
cwtext += m_remoteControl->getArgString(i);
}
m_display->writeCW();
m_modem->sendCWId(cwtext);
}
break;
default:
@ -2277,11 +2570,11 @@ void CMMDVMHost::processModeCommand(unsigned char mode, unsigned int timeout)
void CMMDVMHost::processEnableCommand(bool& mode, bool enabled)
{
LogDebug("Setting mode current=%s new=%s", mode ? "true" : "false", enabled ? "true" : "false");
LogDebug("Setting mode current=%s new=%s",mode ? "true" : "false",enabled ? "true" : "false");
mode = enabled;
m_modem->setModeParams(m_dstarEnabled, m_dmrEnabled, m_ysfEnabled, m_p25Enabled, m_nxdnEnabled, m_m17Enabled, m_pocsagEnabled, m_fmEnabled);
m_modem->setModeParams(m_dstarEnabled, m_dmrEnabled, m_ysfEnabled, m_p25Enabled, m_nxdnEnabled, m_m17Enabled, m_pocsagEnabled, m_fmEnabled, m_ax25Enabled);
if (!m_modem->writeConfig())
LogError("Cannot write Config to MMDVM");
}

View file

@ -23,8 +23,10 @@
#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"
@ -35,7 +37,9 @@
#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"
@ -55,7 +59,7 @@ public:
private:
CConf m_conf;
CModem* m_modem;
IModem* m_modem;
CDStarControl* m_dstar;
CDMRControl* m_dmr;
CYSFControl* m_ysf;
@ -63,6 +67,8 @@ private:
CNXDNControl* m_nxdn;
CM17Control* m_m17;
CPOCSAGControl* m_pocsag;
CFMControl* m_fm;
CAX25Control* m_ax25;
CDStarNetwork* m_dstarNetwork;
CDMRNetwork* m_dmrNetwork;
CYSFNetwork* m_ysfNetwork;
@ -70,6 +76,8 @@ private:
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;
@ -79,6 +87,7 @@ private:
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;
@ -86,6 +95,7 @@ private:
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;
@ -99,6 +109,7 @@ private:
bool m_m17Enabled;
bool m_pocsagEnabled;
bool m_fmEnabled;
bool m_ax25Enabled;
unsigned int m_cwIdTime;
CDMRLookup* m_dmrLookup;
CNXDNLookup* m_nxdnLookup;
@ -119,6 +130,8 @@ private:
bool createNXDNNetwork();
bool createM17Network();
bool createPOCSAGNetwork();
bool createFMNetwork();
bool createAX25Network();
void remoteControl();
void processModeCommand(unsigned char mode, unsigned int timeout);

View file

@ -153,6 +153,9 @@
</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" />
@ -181,11 +184,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="I2CController.h" />
<ClInclude Include="IIRDirectForm1Filter.h" />
<ClInclude Include="LCDproc.h" />
<ClInclude Include="Log.h" />
<ClInclude Include="M17Control.h" />
@ -228,6 +233,7 @@
<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" />
@ -236,6 +242,7 @@
<ClInclude Include="RSSIInterpolator.h" />
<ClInclude Include="NXDNSACCH.h" />
<ClInclude Include="SerialController.h" />
<ClInclude Include="SerialModem.h" />
<ClInclude Include="SerialPort.h" />
<ClInclude Include="StopWatch.h" />
<ClInclude Include="Sync.h" />
@ -258,6 +265,8 @@
</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" />
@ -284,10 +293,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="I2CController.cpp" />
<ClCompile Include="IIRDirectForm1Filter.cpp" />
<ClCompile Include="LCDproc.cpp" />
<ClCompile Include="Log.cpp" />
<ClCompile Include="M17Control.cpp" />
@ -326,12 +337,14 @@
<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="M17Utils.cpp" />
<ClCompile Include="StopWatch.cpp" />

View file

@ -272,9 +272,6 @@
<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>
@ -293,6 +290,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>
@ -320,6 +323,24 @@
<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>
</ItemGroup>
<ItemGroup>
<ClCompile Include="BPTC19696.cpp">
@ -556,9 +577,6 @@
<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>
@ -577,6 +595,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>
@ -601,5 +625,20 @@
<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>
</ItemGroup>
</Project>
</Project>

View file

@ -2,19 +2,20 @@
CC = cc
CXX = c++
CFLAGS = -g -O3 -Wall -std=c++0x -pthread -DHAVE_LOG_H
LIBS = -lpthread
LDFLAGS = -g
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
OBJECTS = \
AMBEFEC.o BCH.o BPTC19696.o CASTInfo.o Conf.o CRC.o Display.o DMRControl.o DMRCSBK.o DMRData.o DMRDataHeader.o DMREMB.o DMREmbeddedData.o DMRFullLC.o \
DMRLookup.o DMRLC.o DMRNetwork.o DMRShortLC.o DMRSlot.o DMRSlotType.o DMRAccessControl.o DMRTA.o DMRTrellis.o DStarControl.o DStarHeader.o \
DStarNetwork.o DStarSlowData.o Golay2087.o Golay24128.o Hamming.o I2CController.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 POCSAGControl.o POCSAGNetwork.o QR1676.o \
RemoteControl.o RS129.o RS241213.o RSSIInterpolator.o SerialController.o SerialPort.o StopWatch.o Sync.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
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 DMREMB.o \
DMREmbeddedData.o DMRFullLC.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 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
@ -27,10 +28,33 @@ RemoteCommand: Log.o RemoteCommand.o UDPSocket.o
%.o: %.cpp
$(CXX) $(CFLAGS) -c -o $@ $<
install:
.PHONY install:
install: all
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,18 +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
LIBS = -lwiringPi -lwiringPiDev -lpthread -lsamplerate -lutil
LDFLAGS = -g -L/usr/local/lib
OBJECTS = \
AMBEFEC.o BCH.o BPTC19696.o CASTInfo.o Conf.o CRC.o Display.o DMRControl.o DMRCSBK.o DMRData.o DMRDataHeader.o DMREMB.o DMREmbeddedData.o DMRFullLC.o \
DMRLookup.o DMRLC.o DMRNetwork.o DMRShortLC.o DMRSlot.o DMRSlotType.o DMRAccessControl.o DMRTA.o DMRTrellis.o DStarControl.o DStarHeader.o \
DStarNetwork.o DStarSlowData.o Golay2087.o Golay24128.o Hamming.o I2CController.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 POCSAGControl.o POCSAGNetwork.o QR1676.o \
RemoteControl.o RS129.o RS241213.o RSSIInterpolator.o SerialController.o SerialPort.o StopWatch.o Sync.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
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 DMREMB.o \
DMREmbeddedData.o DMRFullLC.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 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
@ -27,10 +28,33 @@ RemoteCommand: Log.o RemoteCommand.o UDPSocket.o
%.o: %.cpp
$(CXX) $(CFLAGS) -c -o $@ $<
install:
.PHONY install:
install: all
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,18 +4,19 @@
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
LIBS = -lwiringPi -lwiringPiDev -lpthread -lsamplerate -lutil
LDFLAGS = -g -L/usr/local/lib
OBJECTS = \
AMBEFEC.o BCH.o BPTC19696.o CASTInfo.o Conf.o CRC.o Display.o DMRControl.o DMRCSBK.o DMRData.o DMRDataHeader.o DMREMB.o DMREmbeddedData.o DMRFullLC.o \
DMRLookup.o DMRLC.o DMRNetwork.o DMRShortLC.o DMRSlot.o DMRSlotType.o DMRAccessControl.o 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 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 POCSAGControl.o \
POCSAGNetwork.o QR1676.o RemoteControl.o RS129.o RS241213.o RSSIInterpolator.o SerialController.o SerialPort.o StopWatch.o Sync.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
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 DMREMB.o \
DMREmbeddedData.o DMRFullLC.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 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 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,10 +29,33 @@ RemoteCommand: Log.o RemoteCommand.o UDPSocket.o
%.o: %.cpp
$(CXX) $(CFLAGS) -c -o $@ $<
install:
.PHONY install:
install: all
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,18 +3,19 @@
CC = cc
CXX = c++
CFLAGS = -g -O3 -Wall -std=c++0x -pthread -DHAVE_LOG_H -DHD44780 -I/usr/local/include
LIBS = -lwiringPi -lwiringPiDev -lpthread
LIBS = -lwiringPi -lwiringPiDev -lpthread -lsamplerate -lutil
LDFLAGS = -g -L/usr/local/lib
OBJECTS = \
AMBEFEC.o BCH.o BPTC19696.o CASTInfo.o Conf.o CRC.o Display.o DMRControl.o DMRCSBK.o DMRData.o DMRDataHeader.o DMREMB.o DMREmbeddedData.o DMRFullLC.o \
DMRLookup.o DMRLC.o DMRNetwork.o DMRShortLC.o DMRSlot.o DMRSlotType.o DMRAccessControl.o 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 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 POCSAGControl.o \
POCSAGNetwork.o QR1676.o RemoteControl.o RS129.o RS241213.o RSSIInterpolator.o SerialController.o SerialPort.o StopWatch.o Sync.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
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 DMREMB.o \
DMREmbeddedData.o DMRFullLC.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 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 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
@ -27,10 +28,33 @@ RemoteCommand: Log.o RemoteCommand.o UDPSocket.o
%.o: %.cpp
$(CXX) $(CFLAGS) -c -o $@ $<
install:
.PHONY install:
install: all
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
LIBS = -lArduiPi_OLED -lpthread -lsamplerate -lutil
# If you use NetBSD, add following CFLAGS
#CFLAGS += -L/usr/local/lib -Wl,-rpath=/usr/local/lib
@ -11,14 +11,15 @@ LIBS = -lArduiPi_OLED -lpthread
LDFLAGS = -g -L/usr/local/lib
OBJECTS = \
AMBEFEC.o BCH.o BPTC19696.o CASTInfo.o Conf.o CRC.o Display.o DMRControl.o DMRCSBK.o DMRData.o DMRDataHeader.o DMREMB.o DMREmbeddedData.o DMRFullLC.o \
DMRLookup.o DMRLC.o DMRNetwork.o DMRShortLC.o DMRSlot.o DMRSlotType.o DMRAccessControl.o 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 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 POCSAGControl.o \
POCSAGNetwork.o QR1676.o RemoteControl.o RS129.o RS241213.o RSSIInterpolator.o SerialController.o SerialPort.o StopWatch.o Sync.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
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 DMREMB.o \
DMREmbeddedData.o DMRFullLC.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 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
@ -31,10 +32,33 @@ RemoteCommand: Log.o RemoteCommand.o UDPSocket.o
%.o: %.cpp
$(CXX) $(CFLAGS) -c -o $@ $<
install:
.PHONY install:
install: all
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,18 +4,19 @@
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
LIBS = -lwiringPi -lwiringPiDev -lpthread -lsamplerate -lutil
LDFLAGS = -g -L/usr/local/lib
OBJECTS = \
AMBEFEC.o BCH.o BPTC19696.o CASTInfo.o Conf.o CRC.o Display.o DMRControl.o DMRCSBK.o DMRData.o DMRDataHeader.o DMREMB.o DMREmbeddedData.o DMRFullLC.o \
DMRLookup.o DMRLC.o DMRNetwork.o DMRShortLC.o DMRSlot.o DMRSlotType.o DMRAccessControl.o 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 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 POCSAGControl.o \
POCSAGNetwork.o QR1676.o RemoteControl.o RS129.o RS241213.o RSSIInterpolator.o SerialController.o SerialPort.o StopWatch.o Sync.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
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 DMREMB.o \
DMREmbeddedData.o DMRFullLC.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 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 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,10 +29,33 @@ RemoteCommand: Log.o RemoteCommand.o UDPSocket.o
%.o: %.cpp
$(CXX) $(CFLAGS) -c -o $@ $<
install:
.PHONY install:
install: all
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

2280
Modem.cpp

File diff suppressed because it is too large Load diff

270
Modem.h
View file

@ -19,228 +19,104 @@
#ifndef MODEM_H
#define MODEM_H
#include "SerialController.h"
#include "RingBuffer.h"
#include "Defines.h"
#include "Timer.h"
#include <string>
enum RESP_TYPE_MMDVM {
RTM_OK,
RTM_TIMEOUT,
RTM_ERROR
};
class CModem {
class IModem {
public:
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 ~IModem() = 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 m17Enabled, bool pocsagEnabled, bool fmEnabled);
virtual void setLevels(float rxLevel, float cwIdTXLevel, float dstarTXLevel, float dmrTXLevel, float ysfTXLevel, float p25TXLevel, float nxdnTXLevel, float m17TXLevel, 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 setM17Params(unsigned int txHang);
virtual void setTransparentDataParams(unsigned int sendFrameType);
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 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 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 bool open();
virtual bool open() = 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 readM17Data(unsigned char* data);
virtual unsigned int readTransparentData(unsigned char* data);
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 readTransparentData(unsigned char* data) = 0;
virtual unsigned int readSerial(unsigned char* data, unsigned int length);
virtual unsigned int readSerial(unsigned char* data, unsigned int length) = 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 hasM17Space() const;
virtual bool hasPOCSAGSpace() const;
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 bool hasTX() const;
virtual bool hasCD() const;
virtual bool hasTX() const = 0;
virtual bool hasCD() const = 0;
virtual bool hasLockout() const;
virtual bool hasError() const;
virtual bool hasLockout() const = 0;
virtual bool hasError() const = 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 writeM17Data(const unsigned char* data, unsigned int length);
virtual bool writePOCSAGData(const unsigned char* data, unsigned int length);
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 writeTransparentData(const unsigned char* data, unsigned int length);
virtual bool writeTransparentData(const unsigned char* data, unsigned int length) = 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 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 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 writeDMRStart(bool tx);
virtual bool writeDMRShortLC(const unsigned char* lc);
virtual bool writeDMRAbort(unsigned int slotNo);
virtual bool writeDMRStart(bool tx) = 0;
virtual bool writeDMRShortLC(const unsigned char* lc) = 0;
virtual bool writeDMRAbort(unsigned int slotNo) = 0;
virtual bool writeSerial(const unsigned char* data, unsigned int length);
virtual bool writeSerial(const unsigned char* data, unsigned int length) = 0;
virtual unsigned char getMode() const;
virtual bool setMode(unsigned char mode);
virtual unsigned char getMode() const = 0;
virtual bool setMode(unsigned char mode) = 0;
virtual bool sendCWId(const std::string& callsign);
virtual bool sendCWId(const std::string& callsign) = 0;
virtual HW_TYPE getHWType() const;
virtual HW_TYPE getHWType() const = 0;
virtual void clock(unsigned int ms);
virtual void clock(unsigned int ms) = 0;
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);
virtual void close() = 0;
private:
std::string m_port;
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_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;
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_rxM17Data;
CRingBuffer<unsigned char> m_txM17Data;
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_m17Space;
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 by Jonathan Naylor G4KLX
* Copyright (C) 2016,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
@ -21,22 +21,22 @@
#include <cstdio>
#include <cassert>
CModemSerialPort::CModemSerialPort(CModem* modem) :
IModemSerialPort::IModemSerialPort(IModem* modem) :
m_modem(modem)
{
assert(modem != NULL);
}
CModemSerialPort::~CModemSerialPort()
IModemSerialPort::~IModemSerialPort()
{
}
bool CModemSerialPort::open()
bool IModemSerialPort::open()
{
return true;
}
int CModemSerialPort::write(const unsigned char* data, unsigned int length)
int IModemSerialPort::write(const unsigned char* data, unsigned int length)
{
assert(data != NULL);
assert(length > 0U);
@ -46,7 +46,7 @@ int CModemSerialPort::write(const unsigned char* data, unsigned int length)
return ret ? int(length) : -1;
}
int CModemSerialPort::read(unsigned char* data, unsigned int length)
int IModemSerialPort::read(unsigned char* data, unsigned int length)
{
assert(data != NULL);
assert(length > 0U);
@ -54,6 +54,6 @@ int CModemSerialPort::read(unsigned char* data, unsigned int length)
return m_modem->readSerial(data, length);
}
void CModemSerialPort::close()
void IModemSerialPort::close()
{
}

View file

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

View file

@ -19,9 +19,7 @@
#include "NullModem.h"
#include "Log.h"
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)
CNullModem::CNullModem()
{
}
@ -29,7 +27,9 @@ CNullModem::~CNullModem()
{
}
bool CNullModem::open(){
bool CNullModem::open()
{
::LogMessage("Opening the MMDVM Null Modem");
return true;
}
}

View file

@ -24,82 +24,101 @@
#include <string>
class CNullModem : public CModem {
class CNullModem : public IModem {
public:
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);
CNullModem();
virtual ~CNullModem();
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 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){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 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 readTransparentData(unsigned char* data) { return 0U; };
virtual unsigned int readSerial(unsigned char* data, unsigned int length){return 0;};
virtual unsigned int readSerial(unsigned char* data, unsigned int length) { 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 hasPOCSAGSpace() const{return true;};
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 bool hasTX() const {return false;};
virtual bool hasCD() const {return false;};
virtual bool hasTX() const { return false; };
virtual bool hasCD() const { return false; };
virtual bool hasLockout() const {return false;};
virtual bool hasError() const {return false;};
virtual bool hasLockout() const { return false; };
virtual bool hasError() 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 writePOCSAGData(const unsigned char* data, unsigned int length){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 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 writeTransparentData(const unsigned char* data, unsigned int length){return true;};
virtual bool writeTransparentData(const unsigned char* data, unsigned int length) { 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, 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 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 writeDMRStart(bool tx){return true;};
virtual bool writeDMRShortLC(const unsigned char* lc){return true;};
virtual bool writeDMRAbort(unsigned int slotNo){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 writeSerial(const unsigned char* data, unsigned int length){return true;};
virtual bool writeSerial(const unsigned char* data, unsigned int length) { return true; };
virtual bool setMode(unsigned char mode){return true;};
virtual unsigned char getMode() const { return MODE_IDLE; };
virtual bool setMode(unsigned char mode) { return true; };
virtual bool sendCWId(const std::string& callsign){return true;};
virtual bool sendCWId(const std::string& callsign) { return true; };
virtual HW_TYPE getHWType() const {return m_hwType;};
virtual HW_TYPE getHWType() const { return HWT_MMDVM; };
virtual void clock(unsigned int ms){};
virtual void clock(unsigned int ms) {};
virtual void close(){};
virtual void close() {};
private:
HW_TYPE m_hwType;
};
#endif

86
PseudoTTYController.cpp Normal file
View file

@ -0,0 +1,86 @@
/*
* 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

43
PseudoTTYController.h Normal file
View file

@ -0,0 +1,43 @@
/*
* 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

@ -106,6 +106,8 @@ REMOTE_COMMAND CRemoteControl::getCommand()
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;
@ -121,6 +123,8 @@ REMOTE_COMMAND CRemoteControl::getCommand()
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;

View file

@ -42,6 +42,7 @@ enum REMOTE_COMMAND {
RCD_ENABLE_NXDN,
RCD_ENABLE_M17,
RCD_ENABLE_FM,
RCD_ENABLE_AX25,
RCD_DISABLE_DSTAR,
RCD_DISABLE_DMR,
RCD_DISABLE_YSF,
@ -49,6 +50,7 @@ enum REMOTE_COMMAND {
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 by Jonathan Naylor G4KLX
* 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
@ -23,12 +23,11 @@
#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>
@ -40,7 +39,7 @@
#if defined(_WIN32) || defined(_WIN64)
CSerialController::CSerialController(const std::string& device, SERIAL_SPEED speed, bool assertRTS) :
CSerialController::CSerialController(const std::string& device, unsigned int speed, bool assertRTS) :
m_device(device),
m_speed(speed),
m_assertRTS(assertRTS),
@ -49,6 +48,14 @@ 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()
{
}
@ -221,7 +228,7 @@ void CSerialController::close()
#else
CSerialController::CSerialController(const std::string& device, SERIAL_SPEED speed, bool assertRTS) :
CSerialController::CSerialController(const std::string& device, unsigned int speed, bool assertRTS) :
m_device(device),
m_speed(speed),
m_assertRTS(assertRTS),
@ -230,6 +237,14 @@ 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()
{
}
@ -248,97 +263,107 @@ bool CSerialController::open()
return false;
}
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;
}
if (::isatty(m_fd))
return setRaw();
return true;
}
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;
#else
termios.c_cc[VMIN] = 0;
termios.c_cc[VTIME] = 10;
#endif
switch (m_speed) {
case SERIAL_1200:
::cfsetospeed(&termios, B1200);
::cfsetispeed(&termios, B1200);
break;
case SERIAL_2400:
::cfsetospeed(&termios, B2400);
::cfsetispeed(&termios, B2400);
break;
case SERIAL_4800:
::cfsetospeed(&termios, B4800);
::cfsetispeed(&termios, B4800);
break;
case SERIAL_9600:
::cfsetospeed(&termios, B9600);
::cfsetispeed(&termios, B9600);
break;
case SERIAL_19200:
::cfsetospeed(&termios, B19200);
::cfsetispeed(&termios, B19200);
break;
case SERIAL_38400:
::cfsetospeed(&termios, B38400);
::cfsetispeed(&termios, B38400);
break;
case SERIAL_115200:
::cfsetospeed(&termios, B115200);
::cfsetispeed(&termios, B115200);
break;
case SERIAL_230400:
::cfsetospeed(&termios, B230400);
::cfsetispeed(&termios, B230400);
break;
default:
LogError("Unsupported serial port speed - %d", int(m_speed));
::close(m_fd);
return false;
}
if (::tcsetattr(m_fd, TCSANOW, &termios) < 0) {
LogError("Cannot set the attributes for %s", m_device.c_str());
::close(m_fd);
return false;
}
if (m_assertRTS) {
unsigned int y;
if (::ioctl(m_fd, TIOCMGET, &y) < 0) {
LogError("Cannot get the control attributes for %s", m_device.c_str());
::close(m_fd);
return false;
}
y |= TIOCM_RTS;
if (::ioctl(m_fd, TIOCMSET, &y) < 0) {
LogError("Cannot set the control attributes for %s", m_device.c_str());
::close(m_fd);
return false;
}
}
#if defined(__APPLE__)
setNonblock(false);
#endif
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);
#if defined(__APPLE__)
termios.c_cc[VMIN] = 1;
termios.c_cc[VTIME] = 1;
#else
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;
}
if (::tcsetattr(m_fd, TCSANOW, &termios) < 0) {
LogError("Cannot set the attributes for %s", m_device.c_str());
::close(m_fd);
return false;
}
if (m_assertRTS) {
unsigned int y;
if (::ioctl(m_fd, TIOCMGET, &y) < 0) {
LogError("Cannot get the control attributes for %s", m_device.c_str());
::close(m_fd);
return false;
}
y |= TIOCM_RTS;
if (::ioctl(m_fd, TIOCMSET, &y) < 0) {
LogError("Cannot set the control attributes for %s", m_device.c_str());
::close(m_fd);
return false;
}
}
#if defined(__APPLE__)
setNonblock(false);
#endif
return true;
}

View file

@ -1,5 +1,5 @@
/*
* Copyright (C) 2002-2004,2007-2009,2011-2013,2015-2017 by Jonathan Naylor G4KLX
* Copyright (C) 2002-2004,2007-2009,2011-2013,2015-2017,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
@ -28,21 +28,9 @@
#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, SERIAL_SPEED speed, bool assertRTS = false);
CSerialController(const std::string& device, unsigned int speed, bool assertRTS = false);
virtual ~CSerialController();
virtual bool open();
@ -58,8 +46,10 @@ public:
#endif
protected:
CSerialController(unsigned int speed, bool assertRTS = false);
std::string m_device;
SERIAL_SPEED m_speed;
unsigned int m_speed;
bool m_assertRTS;
#if defined(_WIN32) || defined(_WIN64)
HANDLE m_handle;
@ -71,6 +61,7 @@ protected:
int readNonblock(unsigned char* buffer, unsigned int length);
#else
bool canWrite();
bool setRaw();
#endif
};

2602
SerialModem.cpp Normal file

File diff suppressed because it is too large Load diff

283
SerialModem.h Normal file
View file

@ -0,0 +1,283 @@
/*
* 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 unsigned int readTransparentData(unsigned char* data);
virtual unsigned int readSerial(unsigned char* data, unsigned int length);
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 writeTransparentData(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 writeSerial(const 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_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_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 setConfig();
bool setFrequency();
bool setFMCallsignParams();
bool setFMAckParams();
bool setFMMiscParams();
bool setFMExtParams();
void printDebug();
RESP_TYPE_MMDVM getResponse();
};
#endif

43
Tools/DeEmphasis.py Normal file
View file

@ -0,0 +1,43 @@
#based on https://github.com/gnuradio/gnuradio/blob/master/gr-analog/python/analog/fm_emph.py
import math
import cmath
import numpy as np
import scipy.signal as signal
import pylab as pl
tau = 750e-6
fs = 8000
fh = 2700
# Digital corner frequency
w_c = 1.0 / tau
# Prewarped analog corner frequency
w_ca = 2.0 * fs * math.tan(w_c / (2.0 * fs))
# Resulting digital pole, zero, and gain term from the bilinear
# transformation of H(s) = w_ca / (s + w_ca) to
# H(z) = b0 (1 - z1 z^-1)/(1 - p1 z^-1)
k = -w_ca / (2.0 * fs)
z1 = -1.0
p1 = (1.0 + k) / (1.0 - k)
b0 = -k / (1.0 - k)
btaps = [ b0 * 1.0, b0 * -z1, 0 ]
ataps = [ 1.0, -p1, 0 ]
# Since H(s = 0) = 1.0, then H(z = 1) = 1.0 and has 0 dB gain at DC
taps = np.concatenate((btaps, ataps), axis=0)
print("Taps")
print(*taps, "", sep=",", end="\n")
f,h = signal.freqz(btaps,ataps, fs=fs)
pl.plot(f, 20*np.log10(np.abs(h)))
pl.xlabel('frequency/Hz')
pl.ylabel('gain/dB')
pl.ylim(top=0,bottom=-30)
pl.xlim(left=0, right=fh*2.5)
pl.show()

51
Tools/PreEmphasis.py Normal file
View file

@ -0,0 +1,51 @@
#based on https://github.com/gnuradio/gnuradio/blob/master/gr-analog/python/analog/fm_emph.py
import math
import cmath
import numpy as np
import scipy.signal as signal
import pylab as pl
tau = 750e-6
fs = 8000
fh = 2700
# Digital corner frequencies
w_cl = 1.0 / tau
w_ch = 2.0 * math.pi * fh
# Prewarped analog corner frequencies
w_cla = 2.0 * fs * math.tan(w_cl / (2.0 * fs))
w_cha = 2.0 * fs * math.tan(w_ch / (2.0 * fs))
# Resulting digital pole, zero, and gain term from the bilinear
# transformation of H(s) = (s + w_cla) / (s + w_cha) to
# H(z) = b0 (1 - z1 z^-1)/(1 - p1 z^-1)
kl = -w_cla / (2.0 * fs)
kh = -w_cha / (2.0 * fs)
z1 = (1.0 + kl) / (1.0 - kl)
p1 = (1.0 + kh) / (1.0 - kh)
b0 = (1.0 - kl) / (1.0 - kh)
# Since H(s = infinity) = 1.0, then H(z = -1) = 1.0 and
# this filter has 0 dB gain at fs/2.0.
# That isn't what users are going to expect, so adjust with a
# gain, g, so that H(z = 1) = 1.0 for 0 dB gain at DC.
w_0dB = 2.0 * math.pi * 0.0
g = abs(1.0 - p1 * cmath.rect(1.0, -w_0dB)) \
/ (b0 * abs(1.0 - z1 * cmath.rect(1.0, -w_0dB)))
btaps = [ g * b0 * 1.0, g * b0 * -z1, 0]
ataps = [ 1.0, -p1, 0]
taps = np.concatenate((btaps, ataps), axis=0)
print("Taps")
print(*taps, "", sep=",", end="\n")
f,h = signal.freqz(btaps,ataps, fs=fs)
pl.plot(f, 20*np.log10(np.abs(h)))
pl.xlabel('frequency/Hz')
pl.ylabel('gain/dB')
pl.ylim(top=30,bottom=0)
pl.xlim(left=0, right=fh*2.5)
pl.show()

View file

@ -1,5 +1,5 @@
/*
* Copyright (C) 2016 by Jonathan Naylor G4KLX
* Copyright (C) 2016,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
@ -41,7 +41,7 @@ const unsigned char UMP_STATUS = 0x50U;
const unsigned int BUFFER_LENGTH = 255U;
CUMP::CUMP(const std::string& port) :
m_serial(port, SERIAL_115200),
m_serial(port, 115200U),
m_open(false),
m_buffer(NULL),
m_length(0U),

View file

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

View file

@ -0,0 +1,12 @@
[Unit]
Description=MMDVMHost Radio Servce
After=syslog.target network.target
[Service]
Type=forking
ExecStart=/usr/local/sbin/mmdvmhost_service start
ExecStop=/usr/local/sbin/mmdvmhost_service stop
ExecReload=/usr/local/sbin/mmdvmhost_service restart
[Install]
WantedBy=multi-user.target

View file

@ -1,12 +1,12 @@
[Unit]
Description=MMDVMHost Radio Servce
Description=MMDVMHost Radio Service
After=syslog.target network.target
[Service]
User=mmdvm
Type=forking
ExecStart=/usr/local/sbin/mmdvmhost_service start
ExecStop=/usr/local/sbin/mmdvmhost_service stop
ExecReload=/usr/local/sbin/mmdvmhost_service restart
ExecStart=/usr/local/bin/MMDVMHost
Restart=on-abnormal
[Install]
WantedBy=multi-user.target