Initial code for AX.25 support.

This commit is contained in:
Jonathan Naylor 2020-06-08 16:33:20 +01:00
parent 933b9ef014
commit dbe04c3c2f
22 changed files with 549 additions and 17 deletions

97
AX25Control.cpp Normal file
View file

@ -0,0 +1,97 @@
/*
* 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 "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) :
m_network(network),
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;
unsigned char type = data[0U];
return true;
}
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;
}

45
AX25Control.h Normal file
View file

@ -0,0 +1,45 @@
/*
* 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);
~CAX25Control();
bool writeModem(unsigned char* data, unsigned int len);
void enable(bool enabled);
private:
CAX25Network* m_network;
bool m_enabled;
FILE* m_fp;
bool openFile();
bool writeFile(const unsigned char* data, unsigned int length);
void closeFile();
};
#endif

111
AX25Network.cpp Normal file
View file

@ -0,0 +1,111 @@
/*
* 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 "Defines.h"
#include "Utils.h"
#include "Log.h"
#include <cstdio>
#include <cassert>
#include <cstring>
const unsigned int BUFFER_LENGTH = 200U;
CAX25Network::CAX25Network(const std::string& localAddress, unsigned int localPort, const std::string& gatewayAddress, unsigned int gatewayPort, bool debug) :
m_socket(localAddress, localPort),
m_address(),
m_port(gatewayPort),
m_debug(debug),
m_enabled(false)
{
assert(gatewayPort > 0U);
assert(!gatewayAddress.empty());
m_address = CUDPSocket::lookup(gatewayAddress);
}
CAX25Network::~CAX25Network()
{
}
bool CAX25Network::open()
{
LogMessage("Opening AX25 network connection");
if (m_address.s_addr == INADDR_NONE)
return false;
return m_socket.open();
}
bool CAX25Network::writeAX25(const unsigned char* data, unsigned int length)
{
assert(data != NULL);
unsigned char buffer[110U];
::memset(buffer, 0x00U, 110U);
buffer[0U] = 'A';
buffer[1U] = 'X';
buffer[2U] = '2';
buffer[3U] = '5';
::memcpy(buffer + 4U, data, length);
if (m_debug)
CUtils::dump(1U, "AX25 Network Data Sent", buffer, length + 4U);
return m_socket.write(buffer, length + 4U, m_address, m_port);
}
bool CAX25Network::writeMICE(const unsigned char* data, unsigned int length)
{
assert(data != NULL);
unsigned char buffer[110U];
::memset(buffer, 0x00U, 110U);
buffer[0U] = 'M';
buffer[1U] = 'I';
buffer[2U] = 'C';
buffer[3U] = 'E';
::memcpy(buffer + 4U, data, length);
if (m_debug)
CUtils::dump(1U, "AX25 Network Data Sent", buffer, length + 4U);
return m_socket.write(buffer, length + 4U, m_address, m_port);
}
void CAX25Network::reset()
{
}
void CAX25Network::close()
{
m_socket.close();
LogMessage("Closing AX25 network connection");
}
void CAX25Network::enable(bool enabled)
{
m_enabled = enabled;
}

51
AX25Network.h Normal file
View file

@ -0,0 +1,51 @@
/*
* 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
#include "UDPSocket.h"
#include <cstdint>
#include <string>
class CAX25Network {
public:
CAX25Network(const std::string& localAddress, unsigned int localPort, const std::string& gatewayAddress, unsigned int gatewayPort, bool debug);
~CAX25Network();
bool open();
void enable(bool enabled);
bool writeAX25(const unsigned char* data, unsigned int length);
bool writeMICE(const unsigned char* data, unsigned int length);
void reset();
void close();
private:
CUDPSocket m_socket;
in_addr m_address;
unsigned int m_port;
bool m_debug;
bool m_enabled;
};
#endif

View file

@ -45,12 +45,14 @@ enum SECTION {
SECTION_NXDN,
SECTION_POCSAG,
SECTION_FM,
SECTION_AX25,
SECTION_DSTAR_NETWORK,
SECTION_DMR_NETWORK,
SECTION_FUSION_NETWORK,
SECTION_P25_NETWORK,
SECTION_NXDN_NETWORK,
SECTION_POCSAG_NETWORK,
SECTION_AX25_NETWORK,
SECTION_TFTSERIAL,
SECTION_HD44780,
SECTION_NEXTION,
@ -205,6 +207,7 @@ m_fmCOSInvert(false),
m_fmRFAudioBoost(1U),
m_fmMaxDevLevel(90.0F),
m_fmExtAudioBoost(1U),
m_ax25Enabled(false),
m_dstarNetworkEnabled(false),
m_dstarGatewayAddress(),
m_dstarGatewayPort(0U),
@ -249,6 +252,12 @@ m_pocsagLocalAddress(),
m_pocsagLocalPort(0U),
m_pocsagNetworkModeHang(3U),
m_pocsagNetworkDebug(false),
m_ax25NetworkEnabled(false),
m_ax25GatewayAddress(),
m_ax25GatewayPort(0U),
m_ax25LocalAddress(),
m_ax25LocalPort(0U),
m_ax25NetworkDebug(false),
m_tftSerialPort("/dev/ttyAMA0"),
m_tftSerialBrightness(50U),
m_hd44780Rows(2U),
@ -342,6 +351,8 @@ bool CConf::read()
section = SECTION_POCSAG;
else if (::strncmp(buffer, "[FM]", 4U) == 0)
section = SECTION_FM;
else if (::strncmp(buffer, "[AX.25]", 7U) == 0)
section = SECTION_AX25;
else if (::strncmp(buffer, "[D-Star Network]", 16U) == 0)
section = SECTION_DSTAR_NETWORK;
else if (::strncmp(buffer, "[DMR Network]", 13U) == 0)
@ -354,6 +365,8 @@ bool CConf::read()
section = SECTION_NXDN_NETWORK;
else if (::strncmp(buffer, "[POCSAG Network]", 16U) == 0)
section = SECTION_POCSAG_NETWORK;
else if (::strncmp(buffer, "[AX.25 Network]", 15U) == 0)
section = SECTION_AX25_NETWORK;
else if (::strncmp(buffer, "[TFT Serial]", 12U) == 0)
section = SECTION_TFTSERIAL;
else if (::strncmp(buffer, "[HD44780]", 9U) == 0)
@ -700,8 +713,7 @@ bool CConf::read()
m_pocsagEnabled = ::atoi(value) == 1;
else if (::strcmp(key, "Frequency") == 0)
m_pocsagFrequency = (unsigned int)::atoi(value);
}
else if (section == SECTION_FM) {
} else if (section == SECTION_FM) {
if (::strcmp(key, "Enable") == 0)
m_fmEnabled = ::atoi(value) == 1;
else if (::strcmp(key, "Callsign") == 0) {
@ -775,6 +787,9 @@ bool CConf::read()
m_fmMaxDevLevel = float(::atof(value));
else if (::strcmp(key, "ExtAudioBoost") == 0)
m_fmExtAudioBoost = (unsigned int)::atoi(value);
} else if (section == SECTION_AX25) {
if (::strcmp(key, "Enable") == 0)
m_ax25Enabled = ::atoi(value) == 1;
} else if (section == SECTION_DSTAR_NETWORK) {
if (::strcmp(key, "Enable") == 0)
m_dstarNetworkEnabled = ::atoi(value) == 1;
@ -869,6 +884,19 @@ bool CConf::read()
m_pocsagNetworkModeHang = (unsigned int)::atoi(value);
else if (::strcmp(key, "Debug") == 0)
m_pocsagNetworkDebug = ::atoi(value) == 1;
} else if (section == SECTION_AX25_NETWORK) {
if (::strcmp(key, "Enable") == 0)
m_ax25NetworkEnabled = ::atoi(value) == 1;
else if (::strcmp(key, "LocalAddress") == 0)
m_ax25LocalAddress = value;
else if (::strcmp(key, "LocalPort") == 0)
m_ax25LocalPort = (unsigned int)::atoi(value);
else if (::strcmp(key, "GatewayAddress") == 0)
m_ax25GatewayAddress = value;
else if (::strcmp(key, "GatewayPort") == 0)
m_ax25GatewayPort = (unsigned int)::atoi(value);
else if (::strcmp(key, "Debug") == 0)
m_ax25NetworkDebug = ::atoi(value) == 1;
} else if (section == SECTION_TFTSERIAL) {
if (::strcmp(key, "Port") == 0)
m_tftSerialPort = value;
@ -1677,6 +1705,11 @@ unsigned int CConf::getFMExtAudioBoost() const
return m_fmExtAudioBoost;
}
bool CConf::getAX25Enabled() const
{
return m_ax25Enabled;
}
bool CConf::getDStarNetworkEnabled() const
{
return m_dstarNetworkEnabled;
@ -1897,6 +1930,36 @@ bool CConf::getPOCSAGNetworkDebug() const
return m_pocsagNetworkDebug;
}
bool CConf::getAX25NetworkEnabled() const
{
return m_ax25NetworkEnabled;
}
std::string CConf::getAX25GatewayAddress() const
{
return m_ax25GatewayAddress;
}
unsigned int CConf::getAX25GatewayPort() const
{
return m_ax25GatewayPort;
}
std::string CConf::getAX25LocalAddress() const
{
return m_ax25LocalAddress;
}
unsigned int CConf::getAX25LocalPort() const
{
return m_ax25LocalPort;
}
bool CConf::getAX25NetworkDebug() const
{
return m_ax25NetworkDebug;
}
std::string CConf::getTFTSerialPort() const
{
return m_tftSerialPort;

20
Conf.h
View file

@ -171,6 +171,9 @@ public:
bool getPOCSAGEnabled() const;
unsigned int getPOCSAGFrequency() const;
// The AX.25 section
bool getAX25Enabled() const;
// The FM Section
bool getFMEnabled() const;
std::string getFMCallsign() const;
@ -260,6 +263,14 @@ public:
unsigned int getPOCSAGNetworkModeHang() const;
bool getPOCSAGNetworkDebug() const;
// The AX.25 Network section
bool getAX25NetworkEnabled() const;
std::string getAX25GatewayAddress() const;
unsigned int getAX25GatewayPort() const;
std::string getAX25LocalAddress() const;
unsigned int getAX25LocalPort() const;
bool getAX25NetworkDebug() const;
// The TFTSERIAL section
std::string getTFTSerialPort() const;
unsigned int getTFTSerialBrightness() const;
@ -442,6 +453,8 @@ private:
bool m_pocsagEnabled;
unsigned int m_pocsagFrequency;
bool m_ax25Enabled;
bool m_fmEnabled;
std::string m_fmCallsign;
unsigned int m_fmCallsignSpeed;
@ -524,6 +537,13 @@ private:
unsigned int m_pocsagNetworkModeHang;
bool m_pocsagNetworkDebug;
bool m_ax25NetworkEnabled;
std::string m_ax25GatewayAddress;
unsigned int m_ax25GatewayPort;
std::string m_ax25LocalAddress;
unsigned int m_ax25LocalPort;
bool m_ax25NetworkDebug;
std::string m_tftSerialPort;
unsigned int m_tftSerialBrightness;

View file

@ -175,6 +175,9 @@ RFAudioBoost=1
MaxDevLevel=90
ExtAudioBoost=1
[AX.25]
Enable=1
[D-Star Network]
Enable=1
GatewayAddress=127.0.0.1
@ -231,6 +234,14 @@ GatewayPort=4800
# ModeHang=3
Debug=0
[AX.25 Network]
Enable=1
LocalAddress=127.0.0.1
LocalPort=47325
GatewayAddress=127.0.0.1
GatewayPort=47326
Debug=0
[TFT Serial]
# Port=modem
Port=/dev/ttyAMA0

View file

@ -119,12 +119,14 @@ m_ysf(NULL),
m_p25(NULL),
m_nxdn(NULL),
m_pocsag(NULL),
m_ax25(NULL),
m_dstarNetwork(NULL),
m_dmrNetwork(NULL),
m_ysfNetwork(NULL),
m_p25Network(NULL),
m_nxdnNetwork(NULL),
m_pocsagNetwork(NULL),
m_ax25Network(NULL),
m_display(NULL),
m_ump(NULL),
m_mode(MODE_IDLE),
@ -151,6 +153,7 @@ m_p25Enabled(false),
m_nxdnEnabled(false),
m_pocsagEnabled(false),
m_fmEnabled(false),
m_ax25Enabled(false),
m_cwIdTime(0U),
m_dmrLookup(NULL),
m_nxdnLookup(NULL),
@ -320,6 +323,12 @@ int CMMDVMHost::run()
return 1;
}
if (m_ax25Enabled && m_conf.getAX25NetworkEnabled()) {
ret = createAX25Network();
if (!ret)
return 1;
}
in_addr transparentAddress;
unsigned int transparentPort = 0U;
CUDPSocket* transparentSocket = NULL;
@ -614,6 +623,9 @@ int CMMDVMHost::run()
pocsagTimer.start();
}
if (m_ax25Enabled)
m_ax25 = new CAX25Control(m_ax25Network);
bool remoteControlEnabled = m_conf.getRemoteControlEnabled();
if (remoteControlEnabled) {
unsigned int port = m_conf.getRemoteControlPort();
@ -806,6 +818,15 @@ int CMMDVMHost::run()
}
}
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, transparentPort);
@ -1126,6 +1147,11 @@ int CMMDVMHost::run()
delete m_pocsagNetwork;
}
if (m_ax25Network != NULL) {
m_ax25Network->close();
delete m_ax25Network;
}
if (transparentSocket != NULL) {
transparentSocket->close();
delete transparentSocket;
@ -1142,6 +1168,7 @@ int CMMDVMHost::run()
delete m_p25;
delete m_nxdn;
delete m_pocsag;
delete m_ax25;
return 0;
}
@ -1209,7 +1236,7 @@ bool CMMDVMHost::createModem()
m_modem = CModem::createModem(port, m_duplex, rxInvert, txInvert, pttInvert, txDelay, dmrDelay, trace, debug);
m_modem->setSerialParams(protocol,address);
m_modem->setModeParams(m_dstarEnabled, m_dmrEnabled, m_ysfEnabled, m_p25Enabled, m_nxdnEnabled, m_pocsagEnabled, m_fmEnabled);
m_modem->setModeParams(m_dstarEnabled, m_dmrEnabled, m_ysfEnabled, m_p25Enabled, m_nxdnEnabled, m_pocsagEnabled, m_fmEnabled, m_ax25Enabled);
m_modem->setLevels(rxLevel, cwIdTXLevel, dstarTXLevel, dmrTXLevel, ysfTXLevel, p25TXLevel, nxdnTXLevel, pocsagTXLevel, fmTXLevel);
m_modem->setRFParams(rxFrequency, rxOffset, txFrequency, txOffset, txDCOffset, rxDCOffset, rfLevel, pocsagFrequency);
m_modem->setDMRParams(colorCode);
@ -1531,6 +1558,34 @@ bool CMMDVMHost::createPOCSAGNetwork()
return true;
}
bool CMMDVMHost::createAX25Network()
{
std::string gatewayAddress = m_conf.getAX25GatewayAddress();
unsigned int gatewayPort = m_conf.getAX25GatewayPort();
std::string localAddress = m_conf.getAX25LocalAddress();
unsigned int localPort = m_conf.getAX25LocalPort();
bool debug = m_conf.getAX25NetworkDebug();
LogInfo("AX.25 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);
m_ax25Network = new CAX25Network(localAddress, localPort, gatewayAddress, gatewayPort, 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();
@ -1540,6 +1595,7 @@ void CMMDVMHost::readParams()
m_nxdnEnabled = m_conf.getNXDNEnabled();
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();
@ -1557,8 +1613,10 @@ void CMMDVMHost::readParams()
LogInfo(" NXDN: %s", m_nxdnEnabled ? "enabled" : "disabled");
LogInfo(" POCSAG: %s", m_pocsagEnabled ? "enabled" : "disabled");
LogInfo(" FM: %s", m_fmEnabled ? "enabled" : "disabled");
LogInfo(" AX.25: %s", m_ax25Enabled ? "enabled" : "disabled");
}
// XXX AX.25 enabled/disabled
void CMMDVMHost::setMode(unsigned char mode)
{
assert(m_modem != NULL);
@ -2016,9 +2074,13 @@ void CMMDVMHost::remoteControl()
processEnableCommand(m_nxdnEnabled, 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)
processEnableCommand(m_dstarEnabled, false);
@ -2043,6 +2105,10 @@ void CMMDVMHost::remoteControl()
if (m_fmEnabled == true)
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);
@ -2092,8 +2158,10 @@ 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");
mode=enabled;
m_modem->setModeParams(m_dstarEnabled, m_dmrEnabled, m_ysfEnabled, m_p25Enabled, m_nxdnEnabled, m_pocsagEnabled, m_fmEnabled);
mode = enabled;
m_modem->setModeParams(m_dstarEnabled, m_dmrEnabled, m_ysfEnabled, m_p25Enabled, m_nxdnEnabled, m_pocsagEnabled, m_fmEnabled, m_ax25Enabled);
if (!m_modem->writeConfig())
LogError("Cannot write Config to MMDVM");
}

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"
@ -62,12 +64,14 @@ private:
CP25Control* m_p25;
CNXDNControl* m_nxdn;
CPOCSAGControl* m_pocsag;
CAX25Control* m_ax25;
CDStarNetwork* m_dstarNetwork;
CDMRNetwork* m_dmrNetwork;
CYSFNetwork* m_ysfNetwork;
CP25Network* m_p25Network;
CNXDNNetwork* m_nxdnNetwork;
CPOCSAGNetwork* m_pocsagNetwork;
CAX25Network* m_ax25Network;
CDisplay* m_display;
CUMP* m_ump;
unsigned char m_mode;
@ -94,6 +98,7 @@ private:
bool m_nxdnEnabled;
bool m_pocsagEnabled;
bool m_fmEnabled;
bool m_ax25Enabled;
unsigned int m_cwIdTime;
CDMRLookup* m_dmrLookup;
CNXDNLookup* m_nxdnLookup;
@ -114,6 +119,7 @@ private:
bool createP25Network();
bool createNXDNNetwork();
bool createPOCSAGNetwork();
bool createAX25Network();
void remoteControl();
void processModeCommand(unsigned char mode, unsigned int timeout);

View file

@ -153,6 +153,8 @@
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="AMBEFEC.h" />
<ClInclude Include="AX25Control.h" />
<ClInclude Include="AX25Network.h" />
<ClInclude Include="BCH.h" />
<ClInclude Include="BPTC19696.h" />
<ClInclude Include="CASTInfo.h" />
@ -251,6 +253,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" />

View file

@ -299,6 +299,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>
</ItemGroup>
<ItemGroup>
<ClCompile Include="BPTC19696.cpp">
@ -562,5 +568,11 @@
<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>
</ItemGroup>
</Project>

View file

@ -6,7 +6,7 @@ CFLAGS = -g -O3 -Wall -std=c++0x -pthread
LIBS = -lpthread
LDFLAGS = -g
OBJECTS = \
OBJECTS = AX25Control.o AX25Network.o \
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 MMDVMHost.o MobileGPS.o Modem.o ModemSerialPort.o Mutex.o \

View file

@ -6,7 +6,7 @@ CFLAGS = -g -O3 -Wall -std=c++0x -pthread -DRASPBERRY_PI -I/usr/local/include
LIBS = -lwiringPi -lwiringPiDev -lpthread
LDFLAGS = -g -L/usr/local/lib
OBJECTS = \
OBJECTS = AX25Control.o AX25Network.o \
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 MMDVMHost.o MobileGPS.o Modem.o ModemSerialPort.o Mutex.o \

View file

@ -7,7 +7,7 @@ CFLAGS = -g -O3 -Wall -std=c++0x -pthread -DHD44780 -DADAFRUIT_DISPLAY -I/usr/l
LIBS = -lwiringPi -lwiringPiDev -lpthread
LDFLAGS = -g -L/usr/local/lib
OBJECTS = \
OBJECTS = AX25Control.o AX25Network.o \
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 MMDVMHost.o MobileGPS.o Modem.o ModemSerialPort.o Mutex.o \

View file

@ -6,7 +6,7 @@ CFLAGS = -g -O3 -Wall -std=c++0x -pthread -DHD44780 -I/usr/local/include
LIBS = -lwiringPi -lwiringPiDev -lpthread
LDFLAGS = -g -L/usr/local/lib
OBJECTS = \
OBJECTS = AX25Control.o AX25Network.o \
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 MMDVMHost.o MobileGPS.o Modem.o ModemSerialPort.o Mutex.o \

View file

@ -6,7 +6,7 @@ CFLAGS = -g -O3 -Wall -std=c++0x -pthread -DOLED -I/usr/local/include
LIBS = -lArduiPi_OLED -lwiringPi -lpthread
LDFLAGS = -g -L/usr/local/lib
OBJECTS = \
OBJECTS = AX25Control.o AX25Network.o \
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 MMDVMHost.o MobileGPS.o Modem.o ModemSerialPort.o Mutex.o \

View file

@ -7,7 +7,7 @@ CFLAGS = -g -O3 -Wall -std=c++0x -pthread -DHD44780 -DPCF8574_DISPLAY -I/usr/lo
LIBS = -lwiringPi -lwiringPiDev -lpthread
LDFLAGS = -g -L/usr/local/lib
OBJECTS = \
OBJECTS = AX25Control.o AX25Network.o \
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 MMDVMHost.o MobileGPS.o Modem.o ModemSerialPort.o Mutex.o \

View file

@ -6,7 +6,7 @@ CFLAGS = -g -O3 -Wall -std=c++0x -pthread
LIBS = -lpthread -lsocket
LDFLAGS = -g
OBJECTS = \
OBJECTS = AX25Control.o AX25Network.o \
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 LCDproc.o Log.o MMDVMHost.o MobileGPS.o Modem.o ModemSerialPort.o Mutex.o NetworkInfo.o Nextion.o \

View file

@ -76,6 +76,8 @@ const unsigned char MMDVM_NXDN_LOST = 0x41U;
const unsigned char MMDVM_POCSAG_DATA = 0x50U;
const unsigned char MMDVM_AX25_DATA = 0x55U;
const unsigned char MMDVM_FM_PARAMS1 = 0x60U;
const unsigned char MMDVM_FM_PARAMS2 = 0x61U;
const unsigned char MMDVM_FM_PARAMS3 = 0x62U;
@ -133,6 +135,7 @@ m_p25Enabled(false),
m_nxdnEnabled(false),
m_pocsagEnabled(false),
m_fmEnabled(false),
m_ax25Enabled(false),
m_rxDCOffset(0),
m_txDCOffset(0),
m_serial(NULL),
@ -152,6 +155,7 @@ m_txP25Data(1000U, "Modem TX P25"),
m_rxNXDNData(1000U, "Modem RX NXDN"),
m_txNXDNData(1000U, "Modem TX NXDN"),
m_txPOCSAGData(1000U, "Modem TX POCSAG"),
m_rxAX25Data(1000U, "Modem RX AX.25"),
m_rxTransparentData(1000U, "Modem RX Transparent"),
m_txTransparentData(1000U, "Modem TX Transparent"),
m_sendTransparentDataFrameType(0U),
@ -230,7 +234,7 @@ void CModem::setRFParams(unsigned int rxFrequency, int rxOffset, unsigned int tx
m_pocsagFrequency = pocsagFrequency + txOffset;
}
void CModem::setModeParams(bool dstarEnabled, bool dmrEnabled, bool ysfEnabled, bool p25Enabled, bool nxdnEnabled, bool pocsagEnabled, bool fmEnabled)
void CModem::setModeParams(bool dstarEnabled, bool dmrEnabled, bool ysfEnabled, bool p25Enabled, bool nxdnEnabled, bool pocsagEnabled, bool fmEnabled, bool ax25Enabled)
{
m_dstarEnabled = dstarEnabled;
m_dmrEnabled = dmrEnabled;
@ -239,6 +243,7 @@ void CModem::setModeParams(bool dstarEnabled, bool dmrEnabled, bool ysfEnabled,
m_nxdnEnabled = nxdnEnabled;
m_pocsagEnabled = pocsagEnabled;
m_fmEnabled = fmEnabled;
m_ax25Enabled = ax25Enabled;
}
void CModem::setLevels(float rxLevel, float cwIdTXLevel, float dstarTXLevel, float dmrTXLevel, float ysfTXLevel, float p25TXLevel, float nxdnTXLevel, float pocsagTXLevel, float fmTXLevel)
@ -585,6 +590,20 @@ void CModem::clock(unsigned int ms)
}
break;
case MMDVM_AX25_DATA: {
if (m_trace)
CUtils::dump(1U, "RX AX.25 Data", m_buffer, m_length);
unsigned char data = m_length - 2U;
m_rxAX25Data.addData(&data, 1U);
data = TAG_DATA;
m_rxAX25Data.addData(&data, 1U);
m_rxAX25Data.addData(m_buffer + 3U, m_length - 3U);
}
break;
case MMDVM_GET_STATUS: {
// if (m_trace)
// CUtils::dump(1U, "GET_STATUS", m_buffer, m_length);
@ -941,6 +960,20 @@ unsigned int CModem::readNXDNData(unsigned char* data)
return len;
}
unsigned int CModem::readAX25Data(unsigned char* data)
{
assert(data != NULL);
if (m_rxAX25Data.isEmpty())
return 0U;
unsigned char len = 0U;
m_rxAX25Data.getData(&len, 1U);
m_rxAX25Data.getData(data, len);
return len;
}
unsigned int CModem::readTransparentData(unsigned char* data)
{
assert(data != NULL);
@ -1552,6 +1585,8 @@ bool CModem::setConfig()
buffer[4U] |= 0x20U;
if (m_fmEnabled && m_duplex)
buffer[4U] |= 0x40U;
if (m_ax25Enabled)
buffer[4U] |= 0x80U;
buffer[5U] = m_txDelay / 10U; // In 10ms units

View file

@ -39,7 +39,7 @@ public:
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 setModeParams(bool dstarEnabled, bool dmrEnabled, bool ysfEnabled, bool p25Enabled, bool nxdnEnabled, bool pocsagEnabled, bool fmEnabled, bool ax25Enabled);
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);
@ -59,6 +59,7 @@ public:
virtual unsigned int readYSFData(unsigned char* data);
virtual unsigned int readP25Data(unsigned char* data);
virtual unsigned int readNXDNData(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);
@ -150,6 +151,7 @@ private:
bool m_nxdnEnabled;
bool m_pocsagEnabled;
bool m_fmEnabled;
bool m_ax25Enabled;
int m_rxDCOffset;
int m_txDCOffset;
CSerialController* m_serial;
@ -169,6 +171,7 @@ private:
CRingBuffer<unsigned char> m_rxNXDNData;
CRingBuffer<unsigned char> m_txNXDNData;
CRingBuffer<unsigned char> m_txPOCSAGData;
CRingBuffer<unsigned char> m_rxAX25Data;
CRingBuffer<unsigned char> m_rxTransparentData;
CRingBuffer<unsigned char> m_txTransparentData;
unsigned int m_sendTransparentDataFrameType;

View file

@ -1,5 +1,5 @@
/*
* Copyright (C) 2019 by Jonathan Naylor G4KLX
* Copyright (C) 2019,2020 by Jonathan Naylor G4KLX
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -102,6 +102,8 @@ REMOTE_COMMAND CRemoteControl::getCommand()
m_command = RCD_ENABLE_NXDN;
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;
@ -115,6 +117,8 @@ REMOTE_COMMAND CRemoteControl::getCommand()
m_command = RCD_DISABLE_NXDN;
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

@ -1,5 +1,5 @@
/*
* Copyright (C) 2019 by Jonathan Naylor G4KLX
* Copyright (C) 2019,2020 by Jonathan Naylor G4KLX
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -40,12 +40,14 @@ enum REMOTE_COMMAND {
RCD_ENABLE_P25,
RCD_ENABLE_NXDN,
RCD_ENABLE_FM,
RCD_ENABLE_AX25,
RCD_DISABLE_DSTAR,
RCD_DISABLE_DMR,
RCD_DISABLE_YSF,
RCD_DISABLE_P25,
RCD_DISABLE_NXDN,
RCD_DISABLE_FM,
RCD_DISABLE_AX25,
RCD_PAGE,
RCD_CW
};