Merge branch 'FM_Ext' into AX25_FM
This commit is contained in:
commit
2953ce85a0
|
@ -30,7 +30,7 @@ const unsigned int BUFFER_LENGTH = 500U;
|
|||
|
||||
|
||||
CAX25Network::CAX25Network(const std::string& port, unsigned int speed, bool debug) :
|
||||
m_serial(port, SERIAL_SPEED(speed), false), // XXX
|
||||
m_serial(port, speed, false),
|
||||
m_txData(NULL),
|
||||
m_rxData(NULL),
|
||||
m_rxLength(0U),
|
||||
|
|
23
Conf.h
23
Conf.h
|
@ -71,6 +71,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;
|
||||
|
@ -204,12 +205,14 @@ public:
|
|||
unsigned int getFMCTCSSLowThreshold() const;
|
||||
float getFMCTCSSLevel() const;
|
||||
unsigned int getFMKerchunkTime() const;
|
||||
bool getFMKerchunkTX() const;
|
||||
unsigned int getFMHangTime() const;
|
||||
bool getFMUseCOS() const;
|
||||
bool getFMCOSInvert() const;
|
||||
unsigned int getFMRFAudioBoost() const;
|
||||
float getFMMaxDevLevel() const;
|
||||
unsigned int getFMExtAudioBoost() const;
|
||||
unsigned int getFMModeHang() const;
|
||||
|
||||
// The D-Star Network section
|
||||
bool getDStarNetworkEnabled() const;
|
||||
|
@ -268,6 +271,15 @@ 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 getFMNetworkModeHang() const;
|
||||
bool getFMNetworkDebug() const;
|
||||
|
||||
// The AX.25 Network section
|
||||
bool getAX25NetworkEnabled() const;
|
||||
std::string getAX25NetworkPort() const;
|
||||
|
@ -364,6 +376,7 @@ private:
|
|||
|
||||
std::string m_modemPort;
|
||||
std::string m_modemProtocol;
|
||||
unsigned int m_modemSpeed;
|
||||
unsigned int m_modemAddress;
|
||||
bool m_modemRXInvert;
|
||||
bool m_modemTXInvert;
|
||||
|
@ -487,12 +500,14 @@ private:
|
|||
unsigned int m_fmCTCSSLowThreshold;
|
||||
float m_fmCTCSSLevel;
|
||||
unsigned int m_fmKerchunkTime;
|
||||
bool m_fmKerchunkTX;
|
||||
unsigned int m_fmHangTime;
|
||||
bool m_fmUseCOS;
|
||||
bool m_fmCOSInvert;
|
||||
unsigned int m_fmRFAudioBoost;
|
||||
float m_fmMaxDevLevel;
|
||||
unsigned int m_fmExtAudioBoost;
|
||||
unsigned int m_fmModeHang;
|
||||
|
||||
bool m_dstarNetworkEnabled;
|
||||
std::string m_dstarGatewayAddress;
|
||||
|
@ -545,6 +560,14 @@ 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_fmNetworkModeHang;
|
||||
bool m_fmNetworkDebug;
|
||||
|
||||
bool m_ax25NetworkEnabled;
|
||||
std::string m_ax25NetworkPort;
|
||||
unsigned int m_ax25NetworkSpeed;
|
||||
|
|
10
Display.cpp
10
Display.cpp
|
@ -511,7 +511,7 @@ CDisplay* CDisplay::createDisplay(const CConf& conf, CUMP* ump, CModem* modem)
|
|||
if (port == "modem")
|
||||
serial = new CModemSerialPort(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());
|
||||
|
@ -565,11 +565,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, conf.getLocation());
|
||||
}
|
||||
|
|
189
FMControl.cpp
Normal file
189
FMControl.cpp
Normal file
|
@ -0,0 +1,189 @@
|
|||
/*
|
||||
* 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;
|
||||
unsigned short 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);
|
||||
sampleFloat = m_filterStage3->filter(m_filterStage2->filter(m_filterStage1->filter(sampleFloat)));
|
||||
|
||||
// Repack the float data to 16 bit unsigned
|
||||
unsigned short sampleUShort = (unsigned short)((sampleFloat + 1.0F) * 32767.0F + 0.5F);
|
||||
out[nOut++] = SWAP_BYTES_16(sampleUShort);
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(DUMP_RF_AUDIO)
|
||||
FILE * audiofile = fopen("./audiodump.bin", "ab");
|
||||
if(audiofile != NULL) {
|
||||
fwrite(out, sizeof(unsigned short), nOut, audiofile);
|
||||
fclose(audiofile);
|
||||
}
|
||||
#endif
|
||||
return m_network->writeData((unsigned char*)out, nOut * sizeof(unsigned short));
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
unsigned short netData[168U];//modem can handle up to 168 samples at a time
|
||||
unsigned int length = m_network->read((unsigned char*)netData, 168U * sizeof(unsigned short));
|
||||
length /= sizeof(unsigned short);
|
||||
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++) {
|
||||
unsigned short netSample = SWAP_BYTES_16(netData[i]);
|
||||
|
||||
// Convert the unsigned 16-bit data (+65535 - 0) to float (+1.0 - -1.0)
|
||||
float sampleFloat = (float(netSample) / 32768.0F) - 1.0F;
|
||||
|
||||
//preemphasis
|
||||
sampleFloat = m_preemphasis->filter(sampleFloat);
|
||||
|
||||
// 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
55
FMControl.h
Normal 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
|
188
FMNetwork.cpp
Normal file
188
FMNetwork.cpp
Normal file
|
@ -0,0 +1,188 @@
|
|||
/*
|
||||
* 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, bool debug) :
|
||||
m_socket(localAddress, localPort),
|
||||
m_address(),
|
||||
m_port(gatewayPort),
|
||||
m_debug(debug),
|
||||
m_enabled(false),
|
||||
m_buffer(2000U, "FM Network"),
|
||||
m_pollTimer(1000U, 5U)
|
||||
{
|
||||
assert(gatewayPort > 0U);
|
||||
assert(!gatewayAddress.empty());
|
||||
|
||||
m_address = CUDPSocket::lookup(gatewayAddress);
|
||||
}
|
||||
|
||||
CFMNetwork::~CFMNetwork()
|
||||
{
|
||||
}
|
||||
|
||||
bool CFMNetwork::open()
|
||||
{
|
||||
LogMessage("Opening FM network connection");
|
||||
|
||||
if (m_address.s_addr == INADDR_NONE)
|
||||
return false;
|
||||
|
||||
m_pollTimer.start();
|
||||
|
||||
return m_socket.open();
|
||||
}
|
||||
|
||||
bool CFMNetwork::writeData(const unsigned char* data, unsigned int length)
|
||||
{
|
||||
assert(data != NULL);
|
||||
|
||||
unsigned char buffer[500U];
|
||||
::memset(buffer, 0x00U, 500U);
|
||||
|
||||
buffer[0U] = 'F';
|
||||
buffer[1U] = 'M';
|
||||
buffer[2U] = 'D';
|
||||
|
||||
::memcpy(buffer + 3U, data, length);
|
||||
|
||||
if (m_debug)
|
||||
CUtils::dump(1U, "FM Network Data Sent", buffer, length + 3U);
|
||||
|
||||
return m_socket.write(buffer, length + 3U, m_address, m_port);
|
||||
}
|
||||
|
||||
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_address, m_port);
|
||||
}
|
||||
|
||||
void CFMNetwork::clock(unsigned int ms)
|
||||
{
|
||||
m_pollTimer.clock(ms);
|
||||
if (m_pollTimer.hasExpired()) {
|
||||
writePoll();
|
||||
m_pollTimer.start();
|
||||
}
|
||||
|
||||
unsigned char buffer[BUFFER_LENGTH];
|
||||
|
||||
in_addr address;
|
||||
unsigned int port;
|
||||
int length = m_socket.read(buffer, BUFFER_LENGTH, address, port);
|
||||
if (length <= 0)
|
||||
return;
|
||||
|
||||
// Check if the data is for us
|
||||
if (m_address.s_addr != address.s_addr || port != m_port) {
|
||||
LogMessage("FM packet received from an invalid source, %08X != %08X and/or %u != %u", m_address.s_addr, address.s_addr, m_port, port);
|
||||
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(unsigned char* data, unsigned int space)
|
||||
{
|
||||
assert(data != NULL);
|
||||
|
||||
|
||||
unsigned int bytes = m_buffer.dataSize();
|
||||
if (bytes == 0U)
|
||||
return 0U;
|
||||
|
||||
if (bytes < space)
|
||||
space = bytes;
|
||||
|
||||
//we store usignedshorts, therefore ensure we always return and even number of data
|
||||
if(space > 0 && space % 2 != 0)
|
||||
space--;//round down to multiple of 2
|
||||
|
||||
m_buffer.getData(data, space);
|
||||
|
||||
return space;
|
||||
}
|
||||
|
||||
void CFMNetwork::reset()
|
||||
{
|
||||
}
|
||||
|
||||
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)
|
||||
m_buffer.clear();
|
||||
|
||||
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_address, m_port);
|
||||
}
|
62
FMNetwork.h
Normal file
62
FMNetwork.h
Normal 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 FMNetwork_H
|
||||
#define FMNetwork_H
|
||||
|
||||
#include "RingBuffer.h"
|
||||
#include "UDPSocket.h"
|
||||
#include "Timer.h"
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
|
||||
class CFMNetwork {
|
||||
public:
|
||||
CFMNetwork(const std::string& myAddress, unsigned int myPort, const std::string& gatewayAddress, unsigned int gatewayPort, bool debug);
|
||||
~CFMNetwork();
|
||||
|
||||
bool open();
|
||||
|
||||
void enable(bool enabled);
|
||||
|
||||
bool writeData(const unsigned char* data, unsigned int length);
|
||||
|
||||
bool writeEOT();
|
||||
|
||||
unsigned int read(unsigned char* data, unsigned int space);
|
||||
|
||||
void reset();
|
||||
|
||||
void close();
|
||||
|
||||
void clock(unsigned int ms);
|
||||
|
||||
private:
|
||||
CUDPSocket m_socket;
|
||||
in_addr m_address;
|
||||
unsigned int m_port;
|
||||
bool m_debug;
|
||||
bool m_enabled;
|
||||
CRingBuffer<unsigned char> m_buffer;
|
||||
CTimer m_pollTimer;
|
||||
|
||||
bool writePoll();
|
||||
};
|
||||
|
||||
#endif
|
|
@ -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
|
||||
|
|
|
@ -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
60
IIRDirectForm1Filter.cpp
Normal 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
50
IIRDirectForm1Filter.h
Normal 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
|
12
MMDVM.ini
12
MMDVM.ini
|
@ -45,6 +45,7 @@ Time=24
|
|||
# Port=/dev/ttyAMA0
|
||||
Port=\\.\COM4
|
||||
Protocol=uart
|
||||
Speed=115200
|
||||
# Address=0x22
|
||||
TXInvert=1
|
||||
RXInvert=0
|
||||
|
@ -169,12 +170,14 @@ CTCSSThreshold=30
|
|||
# CTCSSLowThreshold=20
|
||||
CTCSSLevel=20
|
||||
KerchunkTime=0
|
||||
KerchunkTX=1
|
||||
HangTime=7
|
||||
UseCOS=1
|
||||
COSInvert=0
|
||||
RFAudioBoost=1
|
||||
MaxDevLevel=90
|
||||
ExtAudioBoost=1
|
||||
# ModeHang=10
|
||||
|
||||
[AX.25]
|
||||
Enable=1
|
||||
|
@ -239,6 +242,15 @@ GatewayPort=4800
|
|||
# ModeHang=3
|
||||
Debug=0
|
||||
|
||||
[FM Network]
|
||||
Enable=1
|
||||
LocalAddress=127.0.0.1
|
||||
LocalPort=3810
|
||||
GatewayAddress=127.0.0.1
|
||||
GatewayPort=4810
|
||||
# ModeHang=3
|
||||
Debug=0
|
||||
|
||||
[AX.25 Network]
|
||||
Enable=1
|
||||
Port=/dev/ttyp7
|
||||
|
|
243
MMDVMHost.cpp
243
MMDVMHost.cpp
|
@ -121,6 +121,7 @@ m_ysf(NULL),
|
|||
m_p25(NULL),
|
||||
m_nxdn(NULL),
|
||||
m_pocsag(NULL),
|
||||
m_fm(NULL),
|
||||
m_ax25(NULL),
|
||||
m_dstarNetwork(NULL),
|
||||
m_dmrNetwork(NULL),
|
||||
|
@ -128,6 +129,7 @@ m_ysfNetwork(NULL),
|
|||
m_p25Network(NULL),
|
||||
m_nxdnNetwork(NULL),
|
||||
m_pocsagNetwork(NULL),
|
||||
m_fmNetwork(NULL),
|
||||
m_ax25Network(NULL),
|
||||
m_display(NULL),
|
||||
m_ump(NULL),
|
||||
|
@ -137,12 +139,14 @@ m_dmrRFModeHang(10U),
|
|||
m_ysfRFModeHang(10U),
|
||||
m_p25RFModeHang(10U),
|
||||
m_nxdnRFModeHang(10U),
|
||||
m_fmRFModeHang(10U),
|
||||
m_dstarNetModeHang(3U),
|
||||
m_dmrNetModeHang(3U),
|
||||
m_ysfNetModeHang(3U),
|
||||
m_p25NetModeHang(3U),
|
||||
m_nxdnNetModeHang(3U),
|
||||
m_pocsagNetModeHang(3U),
|
||||
m_fmNetModeHang(3U),
|
||||
m_modeTimer(1000U),
|
||||
m_dmrTXTimer(1000U),
|
||||
m_cwIdTimer(1000U),
|
||||
|
@ -325,6 +329,12 @@ 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)
|
||||
|
@ -638,6 +648,12 @@ int CMMDVMHost::run()
|
|||
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) {
|
||||
unsigned int port = m_conf.getRemoteControlPort();
|
||||
|
@ -675,12 +691,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);
|
||||
|
@ -830,11 +840,28 @@ 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) {
|
||||
}
|
||||
else if (m_mode != MODE_LOCKOUT) {
|
||||
LogWarning("NXDN modem data received when in mode %u", m_mode);
|
||||
}
|
||||
}
|
||||
|
@ -989,6 +1016,25 @@ 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) {
|
||||
|
@ -996,7 +1042,8 @@ int CMMDVMHost::run()
|
|||
if (len > 0U) {
|
||||
if (m_mode == MODE_IDLE || m_mode == MODE_FM) {
|
||||
m_modem->writeAX25Data(data, len);
|
||||
} else if (m_mode != MODE_LOCKOUT) {
|
||||
}
|
||||
else if (m_mode != MODE_LOCKOUT) {
|
||||
LogWarning("AX.25 data received when in mode %u", m_mode);
|
||||
}
|
||||
}
|
||||
|
@ -1035,6 +1082,8 @@ int CMMDVMHost::run()
|
|||
m_nxdn->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);
|
||||
|
@ -1048,6 +1097,8 @@ int CMMDVMHost::run()
|
|||
m_nxdnNetwork->clock(ms);
|
||||
if (m_pocsagNetwork != NULL)
|
||||
m_pocsagNetwork->clock(ms);
|
||||
if (m_fmNetwork != NULL)
|
||||
m_fmNetwork->clock(ms);
|
||||
|
||||
if (m_mobileGPS != NULL)
|
||||
m_mobileGPS->clock(ms);
|
||||
|
@ -1173,6 +1224,11 @@ 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;
|
||||
|
@ -1194,6 +1250,7 @@ int CMMDVMHost::run()
|
|||
delete m_p25;
|
||||
delete m_nxdn;
|
||||
delete m_pocsag;
|
||||
delete m_fm;
|
||||
delete m_ax25;
|
||||
|
||||
return 0;
|
||||
|
@ -1203,6 +1260,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();
|
||||
|
@ -1239,9 +1297,13 @@ bool CMMDVMHost::createModem()
|
|||
|
||||
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");
|
||||
|
@ -1265,7 +1327,7 @@ bool CMMDVMHost::createModem()
|
|||
LogInfo(" TX Frequency: %uHz (%uHz)", txFrequency, txFrequency + txOffset);
|
||||
|
||||
m_modem = CModem::createModem(port, m_duplex, rxInvert, txInvert, pttInvert, txDelay, dmrDelay, trace, debug);
|
||||
m_modem->setSerialParams(protocol,address);
|
||||
m_modem->setSerialParams(protocol, address, speed);
|
||||
m_modem->setModeParams(m_dstarEnabled, m_dmrEnabled, m_ysfEnabled, m_p25Enabled, m_nxdnEnabled, m_pocsagEnabled, m_fmEnabled, m_ax25Enabled);
|
||||
m_modem->setLevels(rxLevel, cwIdTXLevel, dstarTXLevel, dmrTXLevel, ysfTXLevel, p25TXLevel, nxdnTXLevel, pocsagTXLevel, fmTXLevel, ax25TXLevel);
|
||||
m_modem->setRFParams(rxFrequency, rxOffset, txFrequency, txOffset, txDCOffset, rxDCOffset, rfLevel, pocsagFrequency);
|
||||
|
@ -1287,7 +1349,6 @@ bool CMMDVMHost::createModem()
|
|||
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();
|
||||
|
@ -1300,12 +1361,13 @@ bool CMMDVMHost::createModem()
|
|||
unsigned int ctcssLowThreshold = m_conf.getFMCTCSSLowThreshold();
|
||||
float ctcssLevel = m_conf.getFMCTCSSLevel();
|
||||
unsigned int kerchunkTime = m_conf.getFMKerchunkTime();
|
||||
bool kerchunkTX = m_conf.getFMKerchunkTX();
|
||||
unsigned int hangTime = m_conf.getFMHangTime();
|
||||
bool useCOS = m_conf.getFMUseCOS();
|
||||
bool cosInvert = m_conf.getFMCOSInvert();
|
||||
unsigned int rfAudioBoost = m_conf.getFMRFAudioBoost();
|
||||
float maxDevLevel = m_conf.getFMMaxDevLevel();
|
||||
unsigned int extAudioBoost = m_conf.getFMExtAudioBoost();
|
||||
unsigned int modeHangTime = m_conf.getFMModeHang();
|
||||
|
||||
LogInfo("FM Parameters");
|
||||
LogInfo(" Callsign: %s", callsign.c_str());
|
||||
|
@ -1319,7 +1381,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);
|
||||
|
@ -1332,16 +1393,27 @@ bool CMMDVMHost::createModem()
|
|||
LogInfo(" CTCSS Low Threshold: %u", ctcssLowThreshold);
|
||||
LogInfo(" CTCSS Level: %.1f%%", ctcssLevel);
|
||||
LogInfo(" Kerchunk Time: %us", kerchunkTime);
|
||||
LogInfo(" Kerchunk TX: %s", kerchunkTX ? "yes" : "no");
|
||||
LogInfo(" Hang Time: %us", hangTime);
|
||||
LogInfo(" Use COS: %s", useCOS ? "yes" : "no");
|
||||
LogInfo(" COS Invert: %s", cosInvert ? "yes" : "no");
|
||||
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, useCOS, cosInvert, rfAudioBoost, maxDevLevel);
|
||||
m_modem->setFMMiscParams(timeout, timeoutLevel, ctcssFrequency, ctcssHighThreshold, ctcssLowThreshold, ctcssLevel, kerchunkTime, kerchunkTX, hangTime, useCOS, cosInvert, 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();
|
||||
|
@ -1594,11 +1666,41 @@ 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();
|
||||
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(" Mode Hang: %us", m_fmNetModeHang);
|
||||
|
||||
m_fmNetwork = new CFMNetwork(localAddress, localPort, gatewayAddress, gatewayPort, 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();
|
||||
std::string port = m_conf.getAX25NetworkPort();
|
||||
unsigned int speed = m_conf.getAX25NetworkSpeed();
|
||||
bool debug = m_conf.getAX25NetworkDebug();
|
||||
bool debug = m_conf.getAX25NetworkDebug();
|
||||
|
||||
LogInfo("AX.25 Network Parameters");
|
||||
LogInfo(" Port: %s", port.c_str());
|
||||
|
@ -1667,6 +1769,8 @@ void CMMDVMHost::setMode(unsigned char mode)
|
|||
m_nxdnNetwork->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)
|
||||
|
@ -1681,6 +1785,8 @@ void CMMDVMHost::setMode(unsigned char mode)
|
|||
m_nxdn->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);
|
||||
|
@ -1705,6 +1811,8 @@ void CMMDVMHost::setMode(unsigned char mode)
|
|||
m_nxdnNetwork->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)
|
||||
|
@ -1719,6 +1827,8 @@ void CMMDVMHost::setMode(unsigned char mode)
|
|||
m_nxdn->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);
|
||||
|
@ -1747,6 +1857,8 @@ void CMMDVMHost::setMode(unsigned char mode)
|
|||
m_nxdnNetwork->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)
|
||||
|
@ -1761,6 +1873,8 @@ void CMMDVMHost::setMode(unsigned char mode)
|
|||
m_nxdn->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);
|
||||
|
@ -1785,6 +1899,8 @@ void CMMDVMHost::setMode(unsigned char mode)
|
|||
m_nxdnNetwork->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)
|
||||
|
@ -1799,6 +1915,8 @@ void CMMDVMHost::setMode(unsigned char mode)
|
|||
m_nxdn->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);
|
||||
|
@ -1823,6 +1941,8 @@ void CMMDVMHost::setMode(unsigned char mode)
|
|||
m_nxdnNetwork->enable(true);
|
||||
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)
|
||||
|
@ -1837,6 +1957,8 @@ void CMMDVMHost::setMode(unsigned char mode)
|
|||
m_nxdn->enable(true);
|
||||
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);
|
||||
|
@ -1861,6 +1983,8 @@ void CMMDVMHost::setMode(unsigned char mode)
|
|||
m_nxdnNetwork->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)
|
||||
|
@ -1875,6 +1999,8 @@ void CMMDVMHost::setMode(unsigned char mode)
|
|||
m_nxdn->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);
|
||||
|
@ -1899,6 +2025,8 @@ void CMMDVMHost::setMode(unsigned char mode)
|
|||
m_nxdnNetwork->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)
|
||||
|
@ -1913,17 +2041,20 @@ void CMMDVMHost::setMode(unsigned char mode)
|
|||
m_nxdn->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;
|
||||
|
@ -1941,6 +2072,8 @@ void CMMDVMHost::setMode(unsigned char mode)
|
|||
m_nxdnNetwork->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)
|
||||
|
@ -1955,6 +2088,8 @@ void CMMDVMHost::setMode(unsigned char mode)
|
|||
m_nxdn->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()) {
|
||||
|
@ -1985,6 +2120,8 @@ void CMMDVMHost::setMode(unsigned char mode)
|
|||
m_nxdnNetwork->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)
|
||||
|
@ -1999,6 +2136,8 @@ void CMMDVMHost::setMode(unsigned char mode)
|
|||
m_nxdn->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()) {
|
||||
|
@ -2027,6 +2166,8 @@ void CMMDVMHost::setMode(unsigned char mode)
|
|||
m_nxdnNetwork->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)
|
||||
|
@ -2041,6 +2182,8 @@ void CMMDVMHost::setMode(unsigned char mode)
|
|||
m_nxdn->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()) {
|
||||
|
@ -2121,38 +2264,38 @@ void CMMDVMHost::remoteControl()
|
|||
processModeCommand(MODE_NXDN, m_nxdnRFModeHang);
|
||||
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_FM:
|
||||
if (!m_fmEnabled)
|
||||
|
@ -2163,37 +2306,37 @@ void CMMDVMHost::remoteControl()
|
|||
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_FM:
|
||||
if (m_fmEnabled == true)
|
||||
if (m_fmEnabled)
|
||||
processEnableCommand(m_fmEnabled, false);
|
||||
break;
|
||||
case RCD_DISABLE_AX25:
|
||||
|
|
|
@ -35,8 +35,10 @@
|
|||
#include "YSFNetwork.h"
|
||||
#include "P25Network.h"
|
||||
#include "DMRNetwork.h"
|
||||
#include "FMNetwork.h"
|
||||
#include "DMRLookup.h"
|
||||
#include "MobileGPS.h"
|
||||
#include "FMControl.h"
|
||||
#include "Display.h"
|
||||
#include "Timer.h"
|
||||
#include "Modem.h"
|
||||
|
@ -64,6 +66,7 @@ private:
|
|||
CP25Control* m_p25;
|
||||
CNXDNControl* m_nxdn;
|
||||
CPOCSAGControl* m_pocsag;
|
||||
CFMControl* m_fm;
|
||||
CAX25Control* m_ax25;
|
||||
CDStarNetwork* m_dstarNetwork;
|
||||
CDMRNetwork* m_dmrNetwork;
|
||||
|
@ -71,6 +74,7 @@ private:
|
|||
CP25Network* m_p25Network;
|
||||
INXDNNetwork* m_nxdnNetwork;
|
||||
CPOCSAGNetwork* m_pocsagNetwork;
|
||||
CFMNetwork* m_fmNetwork;
|
||||
CAX25Network* m_ax25Network;
|
||||
CDisplay* m_display;
|
||||
CUMP* m_ump;
|
||||
|
@ -80,12 +84,14 @@ private:
|
|||
unsigned int m_ysfRFModeHang;
|
||||
unsigned int m_p25RFModeHang;
|
||||
unsigned int m_nxdnRFModeHang;
|
||||
unsigned int m_fmRFModeHang;
|
||||
unsigned int m_dstarNetModeHang;
|
||||
unsigned int m_dmrNetModeHang;
|
||||
unsigned int m_ysfNetModeHang;
|
||||
unsigned int m_p25NetModeHang;
|
||||
unsigned int m_nxdnNetModeHang;
|
||||
unsigned int m_pocsagNetModeHang;
|
||||
unsigned int m_fmNetModeHang;
|
||||
CTimer m_modeTimer;
|
||||
CTimer m_dmrTXTimer;
|
||||
CTimer m_cwIdTimer;
|
||||
|
@ -119,6 +125,7 @@ private:
|
|||
bool createP25Network();
|
||||
bool createNXDNNetwork();
|
||||
bool createPOCSAGNetwork();
|
||||
bool createFMNetwork();
|
||||
bool createAX25Network();
|
||||
|
||||
void remoteControl();
|
||||
|
|
|
@ -184,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="MMDVMHost.h" />
|
||||
|
@ -284,10 +286,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="MMDVMHost.cpp" />
|
||||
|
|
|
@ -275,9 +275,6 @@
|
|||
<ClInclude Include="POCSAGDefines.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="I2CController.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="MobileGPS.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
|
@ -314,6 +311,15 @@
|
|||
<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>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="BPTC19696.cpp">
|
||||
|
@ -553,9 +559,6 @@
|
|||
<ClCompile Include="POCSAGControl.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="I2CController.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="MobileGPS.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
|
@ -589,5 +592,14 @@
|
|||
<ClCompile Include="NXDNKenwoodNetwork.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>
|
||||
</ItemGroup>
|
||||
</Project>
|
12
Makefile
12
Makefile
|
@ -9,12 +9,12 @@ LDFLAGS = -g
|
|||
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 \
|
||||
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 SHA256.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
|
||||
DStarSlowData.o FMControl.o FMNetwork.o Golay2087.o Golay24128.o Hamming.o I2CController.o IIRDirectForm1Filter.o LCDproc.o Log.o MMDVMHost.o MobileGPS.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 \
|
||||
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 \
|
||||
SHA256.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
|
||||
|
||||
|
|
|
@ -9,8 +9,8 @@ LDFLAGS = -g -L/usr/local/lib
|
|||
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 \
|
||||
NetworkInfo.o Nextion.o NullDisplay.o NullModem.o NXDNAudio.o NXDNControl.o NXDNConvolution.o NXDNCRC.o NXDNFACCH1.o NXDNIcomNetwork.o NXDNKenwoodNetwork.o \
|
||||
DStarSlowData.o FMControl.o FMNetwork.o Golay2087.o Golay24128.o Hamming.o I2CController.o IIRDirectForm1Filter.o LCDproc.o Log.o MMDVMHost.o MobileGPS.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 \
|
||||
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 \
|
||||
SHA256.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 \
|
||||
|
|
|
@ -10,8 +10,8 @@ LDFLAGS = -g -L/usr/local/lib
|
|||
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 \
|
||||
NetworkInfo.o Nextion.o NullDisplay.o NullModem.o NXDNAudio.o NXDNControl.o NXDNConvolution.o NXDNCRC.o NXDNFACCH1.o NXDNIcomNetwork.o NXDNKenwoodNetwork.o \
|
||||
DStarSlowData.o FMControl.o FMNetwork.o Golay2087.o Golay24128.o Hamming.o HD44780.o I2CController.o IIRDirectForm1Filter.o LCDproc.o Log.o MMDVMHost.o MobileGPS.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 \
|
||||
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 \
|
||||
SHA256.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 \
|
||||
|
|
|
@ -9,8 +9,8 @@ LDFLAGS = -g -L/usr/local/lib
|
|||
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 \
|
||||
NetworkInfo.o Nextion.o NullDisplay.o NullModem.o NXDNAudio.o NXDNControl.o NXDNConvolution.o NXDNCRC.o NXDNFACCH1.o NXDNIcomNetwork.o NXDNKenwoodNetwork.o \
|
||||
DStarSlowData.o FMControl.o FMNetwork.o Golay2087.o Golay24128.o Hamming.o HD44780.o I2CController.o IIDirectForm1Filter.o LCDproc.o Log.o MMDVMHost.o MobileGPS.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 \
|
||||
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 \
|
||||
SHA256.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 \
|
||||
|
|
|
@ -9,8 +9,8 @@ LDFLAGS = -g -L/usr/local/lib
|
|||
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 \
|
||||
NetworkInfo.o Nextion.o NullDisplay.o NullModem.o NXDNAudio.o NXDNControl.o NXDNConvolution.o NXDNCRC.o NXDNFACCH1.o NXDNIcomNetwork.o NXDNKenwoodNetwork.o \
|
||||
DStarSlowData.o FMControl.o FMNetwork.o Golay2087.o Golay24128.o Hamming.o I2CController.o IIRDirectForm1Filter.o OLED.o LCDproc.o Log.o MMDVMHost.o MobileGPS.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 \
|
||||
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 \
|
||||
SHA256.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 \
|
||||
|
|
|
@ -10,8 +10,8 @@ LDFLAGS = -g -L/usr/local/lib
|
|||
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 \
|
||||
NetworkInfo.o Nextion.o NullDisplay.o NullModem.o NXDNAudio.o NXDNControl.o NXDNConvolution.o NXDNCRC.o NXDNFACCH1.o NXDNIcomNetwork.o NXDNKenwoodNetwork.o \
|
||||
DStarSlowData.o FMControl.o FMNetwork.o Golay2087.o Golay24128.o Hamming.o HD44780.o I2CController.o IIRDirectForm1Filter.o LCDproc.o Log.o MMDVMHost.o MobileGPS.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 \
|
||||
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 \
|
||||
SHA256.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 \
|
||||
|
|
236
Modem.cpp
236
Modem.cpp
|
@ -16,7 +16,10 @@
|
|||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include "SerialController.h"
|
||||
#if defined(__linux__)
|
||||
#include "I2CController.h"
|
||||
#endif
|
||||
#include "DStarDefines.h"
|
||||
#include "DMRDefines.h"
|
||||
#include "YSFDefines.h"
|
||||
|
@ -82,6 +85,10 @@ 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;
|
||||
const unsigned char MMDVM_FM_PARAMS4 = 0x63U;
|
||||
const unsigned char MMDVM_FM_DATA = 0x65U;
|
||||
const unsigned char MMDVM_FM_CONTROL = 0x66U;
|
||||
const unsigned char MMDVM_FM_EOT = 0x67U;
|
||||
|
||||
const unsigned char MMDVM_ACK = 0x70U;
|
||||
const unsigned char MMDVM_NAK = 0x7FU;
|
||||
|
@ -160,6 +167,8 @@ 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_rxFMData(5000U, "Modem RX FM"),
|
||||
m_txFMData(5000U, "Modem TX FM"),
|
||||
m_rxAX25Data(1000U, "Modem RX AX.25"),
|
||||
m_txAX25Data(1000U, "Modem TX AX.25"),
|
||||
m_rxTransparentData(1000U, "Modem RX Transparent"),
|
||||
|
@ -175,6 +184,7 @@ m_ysfSpace(0U),
|
|||
m_p25Space(0U),
|
||||
m_nxdnSpace(0U),
|
||||
m_pocsagSpace(0U),
|
||||
m_fmSpace(0U),
|
||||
m_ax25Space(0U),
|
||||
m_tx(false),
|
||||
m_cd(false),
|
||||
|
@ -195,6 +205,7 @@ m_fmCallsignAtStart(true),
|
|||
m_fmCallsignAtEnd(true),
|
||||
m_fmCallsignAtLatch(true),
|
||||
m_fmRfAck("K"),
|
||||
m_fmExtAck("N"),
|
||||
m_fmAckSpeed(20U),
|
||||
m_fmAckFrequency(1750U),
|
||||
m_fmAckMinTime(4U),
|
||||
|
@ -207,11 +218,14 @@ m_fmCtcssHighThreshold(30U),
|
|||
m_fmCtcssLowThreshold(20U),
|
||||
m_fmCtcssLevel(10.0F),
|
||||
m_fmKerchunkTime(0U),
|
||||
m_fmKerchunkTX(true),
|
||||
m_fmHangTime(5U),
|
||||
m_fmUseCOS(true),
|
||||
m_fmCOSInvert(false),
|
||||
m_fmRFAudioBoost(1U),
|
||||
m_fmMaxDevLevel(90.0F)
|
||||
m_fmExtAudioBoost(1U),
|
||||
m_fmMaxDevLevel(90.0F),
|
||||
m_fmExtEnable(false)
|
||||
{
|
||||
m_buffer = new unsigned char[BUFFER_LENGTH];
|
||||
|
||||
|
@ -224,13 +238,15 @@ CModem::~CModem()
|
|||
delete[] m_buffer;
|
||||
}
|
||||
|
||||
void CModem::setSerialParams(const std::string& protocol, unsigned int address)
|
||||
void CModem::setSerialParams(const std::string& protocol, unsigned int address, unsigned int speed)
|
||||
{
|
||||
// Create the serial controller instance according the protocol specified in conf.
|
||||
#if defined(__linux__)
|
||||
if (protocol == "i2c")
|
||||
m_serial = new CI2CController(m_port, SERIAL_115200, address, true);
|
||||
m_serial = new CI2CController(m_port, address);
|
||||
else
|
||||
m_serial = new CSerialController(m_port, SERIAL_115200, true);
|
||||
#endif
|
||||
m_serial = new CSerialController(m_port, speed, true);
|
||||
}
|
||||
|
||||
void CModem::setRFParams(unsigned int rxFrequency, int rxOffset, unsigned int txFrequency, int txOffset, int txDCOffset, int rxDCOffset, float rfLevel, unsigned int pocsagFrequency)
|
||||
|
@ -363,6 +379,16 @@ bool CModem::open()
|
|||
m_serial = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (m_fmExtEnable) {
|
||||
ret = setFMExtParams();
|
||||
if (!ret) {
|
||||
m_serial->close();
|
||||
delete m_serial;
|
||||
m_serial = NULL;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_statusTimer.start();
|
||||
|
@ -408,7 +434,7 @@ void CModem::clock(unsigned int ms)
|
|||
if (m_trace)
|
||||
CUtils::dump(1U, "RX D-Star Header", m_buffer, m_length);
|
||||
|
||||
unsigned char data = m_length - 2U;
|
||||
unsigned char data = m_length - m_offset + 1U;
|
||||
m_rxDStarData.addData(&data, 1U);
|
||||
|
||||
data = TAG_HEADER;
|
||||
|
@ -422,7 +448,7 @@ void CModem::clock(unsigned int ms)
|
|||
if (m_trace)
|
||||
CUtils::dump(1U, "RX D-Star Data", m_buffer, m_length);
|
||||
|
||||
unsigned char data = m_length - 2U;
|
||||
unsigned char data = m_length - m_offset + 1U;
|
||||
m_rxDStarData.addData(&data, 1U);
|
||||
|
||||
data = TAG_DATA;
|
||||
|
@ -460,7 +486,7 @@ void CModem::clock(unsigned int ms)
|
|||
if (m_trace)
|
||||
CUtils::dump(1U, "RX DMR Data 1", m_buffer, m_length);
|
||||
|
||||
unsigned char data = m_length - 2U;
|
||||
unsigned char data = m_length - m_offset + 1U;
|
||||
m_rxDMRData1.addData(&data, 1U);
|
||||
|
||||
if (m_buffer[3U] == (DMR_SYNC_DATA | DT_TERMINATOR_WITH_LC))
|
||||
|
@ -477,7 +503,7 @@ void CModem::clock(unsigned int ms)
|
|||
if (m_trace)
|
||||
CUtils::dump(1U, "RX DMR Data 2", m_buffer, m_length);
|
||||
|
||||
unsigned char data = m_length - 2U;
|
||||
unsigned char data = m_length - m_offset + 1U;
|
||||
m_rxDMRData2.addData(&data, 1U);
|
||||
|
||||
if (m_buffer[3U] == (DMR_SYNC_DATA | DT_TERMINATOR_WITH_LC))
|
||||
|
@ -518,7 +544,7 @@ void CModem::clock(unsigned int ms)
|
|||
if (m_trace)
|
||||
CUtils::dump(1U, "RX YSF Data", m_buffer, m_length);
|
||||
|
||||
unsigned char data = m_length - 2U;
|
||||
unsigned char data = m_length - m_offset + 1U;
|
||||
m_rxYSFData.addData(&data, 1U);
|
||||
|
||||
data = TAG_DATA;
|
||||
|
@ -544,7 +570,7 @@ void CModem::clock(unsigned int ms)
|
|||
if (m_trace)
|
||||
CUtils::dump(1U, "RX P25 Header", m_buffer, m_length);
|
||||
|
||||
unsigned char data = m_length - 2U;
|
||||
unsigned char data = m_length - m_offset + 1U;
|
||||
m_rxP25Data.addData(&data, 1U);
|
||||
|
||||
data = TAG_HEADER;
|
||||
|
@ -558,7 +584,7 @@ void CModem::clock(unsigned int ms)
|
|||
if (m_trace)
|
||||
CUtils::dump(1U, "RX P25 LDU", m_buffer, m_length);
|
||||
|
||||
unsigned char data = m_length - 2U;
|
||||
unsigned char data = m_length - m_offset + 1U;
|
||||
m_rxP25Data.addData(&data, 1U);
|
||||
|
||||
data = TAG_DATA;
|
||||
|
@ -584,7 +610,7 @@ void CModem::clock(unsigned int ms)
|
|||
if (m_trace)
|
||||
CUtils::dump(1U, "RX NXDN Data", m_buffer, m_length);
|
||||
|
||||
unsigned char data = m_length - 2U;
|
||||
unsigned char data = m_length - m_offset + 1U;
|
||||
m_rxNXDNData.addData(&data, 1U);
|
||||
|
||||
data = TAG_DATA;
|
||||
|
@ -606,12 +632,54 @@ void CModem::clock(unsigned int ms)
|
|||
}
|
||||
break;
|
||||
|
||||
case MMDVM_FM_DATA: {
|
||||
if (m_trace)
|
||||
CUtils::dump(1U, "RX FM Data", m_buffer, m_length);
|
||||
|
||||
unsigned int data1 = m_length - m_offset + 1U;
|
||||
m_rxFMData.addData((unsigned char*)&data1, sizeof(unsigned int));
|
||||
|
||||
unsigned char data2 = TAG_DATA;
|
||||
m_rxFMData.addData(&data2, 1U);
|
||||
|
||||
m_rxFMData.addData(m_buffer + m_offset, m_length - m_offset);
|
||||
}
|
||||
break;
|
||||
|
||||
case MMDVM_FM_CONTROL: {
|
||||
if (m_trace)
|
||||
CUtils::dump(1U, "RX FM Control", m_buffer, m_length);
|
||||
|
||||
unsigned char data = m_length - m_offset + 1U;
|
||||
m_rxFMData.addData(&data, 1U);
|
||||
|
||||
data = TAG_HEADER;
|
||||
m_rxFMData.addData(&data, 1U);
|
||||
|
||||
m_rxFMData.addData(m_buffer + m_offset, m_length - m_offset);
|
||||
}
|
||||
break;
|
||||
|
||||
case MMDVM_FM_EOT: {
|
||||
if(m_trace)
|
||||
CUtils::dump(1U, "RX FM End of transmission", m_buffer, m_length);
|
||||
|
||||
unsigned char data = m_length - m_offset + 1U;
|
||||
m_rxFMData.addData(&data, 1U);
|
||||
|
||||
data = TAG_EOT;
|
||||
m_rxFMData.addData(&data, 1U);
|
||||
|
||||
m_rxFMData.addData(m_buffer + m_offset, m_length - m_offset);
|
||||
}
|
||||
break;
|
||||
|
||||
case MMDVM_AX25_DATA: {
|
||||
if (m_trace)
|
||||
CUtils::dump(1U, "RX AX.25 Data", m_buffer, m_length);
|
||||
|
||||
unsigned char data = m_length - 3U;
|
||||
m_rxAX25Data.addData(&data, 1U);
|
||||
unsigned int data = m_length - m_offset;
|
||||
m_rxAX25Data.addData((unsigned char*)&data, sizeof(unsigned int));
|
||||
|
||||
m_rxAX25Data.addData(m_buffer + m_offset, m_length - m_offset);
|
||||
}
|
||||
|
@ -624,6 +692,7 @@ void CModem::clock(unsigned int ms)
|
|||
m_p25Space = 0U;
|
||||
m_nxdnSpace = 0U;
|
||||
m_pocsagSpace = 0U;
|
||||
m_fmSpace = 0U;
|
||||
m_ax25Space = 0U;
|
||||
|
||||
m_mode = m_buffer[m_offset + 1U];
|
||||
|
@ -662,10 +731,12 @@ void CModem::clock(unsigned int ms)
|
|||
if (m_length > (m_offset + 9U))
|
||||
m_pocsagSpace = m_buffer[m_offset + 9U];
|
||||
if (m_length > (m_offset + 10U))
|
||||
m_ax25Space = m_buffer[m_offset + 10U] * 8U;
|
||||
m_fmSpace = m_buffer[m_offset + 10U];
|
||||
if (m_length > (m_offset + 11U))
|
||||
m_ax25Space = m_buffer[m_offset + 11U];
|
||||
|
||||
m_inactivityTimer.start();
|
||||
// LogMessage("status=%02X, tx=%d, space=%u,%u,%u,%u,%u,%u,%u,%u lockout=%d, cd=%d", m_buffer[m_offset + 2U], int(m_tx), m_dstarSpace, m_dmrSpace1, m_dmrSpace2, m_ysfSpace, m_p25Space, m_nxdnSpace, m_pocsagSpace, m_ax25Space, int(m_lockout), int(m_cd));
|
||||
// LogMessage("status=%02X, tx=%d, space=%u,%u,%u,%u,%u,%u,%u,%u,%u lockout=%d, cd=%d", m_buffer[m_offset + 2U], int(m_tx), m_dstarSpace, m_dmrSpace1, m_dmrSpace2, m_ysfSpace, m_p25Space, m_nxdnSpace, m_pocsagSpace, m_fmSpace, m_ax25Space, int(m_lockout), int(m_cd));
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -869,6 +940,23 @@ void CModem::clock(unsigned int ms)
|
|||
m_pocsagSpace--;
|
||||
}
|
||||
|
||||
if (m_fmSpace > 1U && !m_txFMData.isEmpty()) {
|
||||
unsigned char len = 0U;
|
||||
m_txFMData.getData(&len, 1U);
|
||||
m_txFMData.getData(m_buffer, len);
|
||||
|
||||
if (m_trace)
|
||||
CUtils::dump(1U, "TX FM Data", m_buffer, len);
|
||||
|
||||
int ret = m_serial->write(m_buffer, len);
|
||||
if (ret != int(len))
|
||||
LogWarning("Error when writing FM data to the MMDVM");
|
||||
|
||||
m_playoutTimer.start();
|
||||
|
||||
m_fmSpace--;
|
||||
}
|
||||
|
||||
if (m_ax25Space > 0U && !m_txAX25Data.isEmpty()) {
|
||||
unsigned char len = 0U;
|
||||
m_txAX25Data.getData((unsigned char*)&len, sizeof(unsigned int));
|
||||
|
@ -993,6 +1081,20 @@ unsigned int CModem::readNXDNData(unsigned char* data)
|
|||
return len;
|
||||
}
|
||||
|
||||
unsigned int CModem::readFMData(unsigned char* data)
|
||||
{
|
||||
assert(data != NULL);
|
||||
|
||||
if (m_rxFMData.isEmpty())
|
||||
return 0U;
|
||||
|
||||
unsigned int len = 0U;
|
||||
m_rxFMData.getData((unsigned char*)&len, sizeof(unsigned int));
|
||||
m_rxFMData.getData(data, len);
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
unsigned int CModem::readAX25Data(unsigned char* data)
|
||||
{
|
||||
assert(data != NULL);
|
||||
|
@ -1000,8 +1102,8 @@ unsigned int CModem::readAX25Data(unsigned char* data)
|
|||
if (m_rxAX25Data.isEmpty())
|
||||
return 0U;
|
||||
|
||||
unsigned char len = 0U;
|
||||
m_rxAX25Data.getData(&len, 1U);
|
||||
unsigned int len = 0U;
|
||||
m_rxAX25Data.getData((unsigned char*)&len, sizeof(unsigned int));
|
||||
m_rxAX25Data.getData(data, len);
|
||||
|
||||
return len;
|
||||
|
@ -1248,6 +1350,40 @@ bool CModem::writePOCSAGData(const unsigned char* data, unsigned int length)
|
|||
return true;
|
||||
}
|
||||
|
||||
unsigned int CModem::getFMSpace() const
|
||||
{
|
||||
return m_txFMData.freeSpace();
|
||||
}
|
||||
|
||||
bool CModem::writeFMData(const unsigned char* data, unsigned int length)
|
||||
{
|
||||
assert(data != NULL);
|
||||
assert(length > 0U);
|
||||
|
||||
unsigned char buffer[500U];
|
||||
|
||||
unsigned int len;
|
||||
if (length > 252U) {
|
||||
buffer[0U] = MMDVM_FRAME_START;
|
||||
buffer[1U] = 0U;
|
||||
buffer[2U] = (length + 4U) - 255U;
|
||||
buffer[3U] = MMDVM_FM_DATA;
|
||||
::memcpy(buffer + 4U, data, length);
|
||||
len = length + 4U;
|
||||
} else {
|
||||
buffer[0U] = MMDVM_FRAME_START;
|
||||
buffer[1U] = length + 3U;
|
||||
buffer[2U] = MMDVM_FM_DATA;
|
||||
::memcpy(buffer + 3U, data, length);
|
||||
len = length + 3U;
|
||||
}
|
||||
|
||||
m_txFMData.addData((unsigned char*)&len, sizeof(unsigned int));
|
||||
m_txFMData.addData(buffer, len);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CModem::hasAX25Space() const
|
||||
{
|
||||
unsigned int space = m_txAX25Data.freeSpace() / (AX25_MAX_FRAME_LENGTH_BYTES + 5U);
|
||||
|
@ -2044,7 +2180,7 @@ void CModem::setFMAckParams(const std::string& rfAck, unsigned int ackSpeed, uns
|
|||
m_fmAckLevel = ackLevel;
|
||||
}
|
||||
|
||||
void CModem::setFMMiscParams(unsigned int timeout, float timeoutLevel, float ctcssFrequency, unsigned int ctcssHighThreshold, unsigned int ctcssLowThreshold, float ctcssLevel, unsigned int kerchunkTime, unsigned int hangTime, bool useCOS, bool cosInvert, unsigned int rfAudioBoost, float maxDevLevel)
|
||||
void CModem::setFMMiscParams(unsigned int timeout, float timeoutLevel, float ctcssFrequency, unsigned int ctcssHighThreshold, unsigned int ctcssLowThreshold, float ctcssLevel, unsigned int kerchunkTime, bool kerchunkTX, unsigned int hangTime, bool useCOS, bool cosInvert, unsigned int rfAudioBoost, float maxDevLevel)
|
||||
{
|
||||
m_fmTimeout = timeout;
|
||||
m_fmTimeoutLevel = timeoutLevel;
|
||||
|
@ -2055,6 +2191,8 @@ void CModem::setFMMiscParams(unsigned int timeout, float timeoutLevel, float ctc
|
|||
m_fmCtcssLevel = ctcssLevel;
|
||||
|
||||
m_fmKerchunkTime = kerchunkTime;
|
||||
m_fmKerchunkTX = kerchunkTX;
|
||||
|
||||
m_fmHangTime = hangTime;
|
||||
|
||||
m_fmUseCOS = useCOS;
|
||||
|
@ -2064,6 +2202,13 @@ void CModem::setFMMiscParams(unsigned int timeout, float timeoutLevel, float ctc
|
|||
m_fmMaxDevLevel = maxDevLevel;
|
||||
}
|
||||
|
||||
void CModem::setFMExtParams(const std::string& ack, unsigned int audioBoost)
|
||||
{
|
||||
m_fmExtAck = ack;
|
||||
m_fmExtAudioBoost = audioBoost;
|
||||
m_fmExtEnable = true;
|
||||
}
|
||||
|
||||
bool CModem::setFMCallsignParams()
|
||||
{
|
||||
assert(m_serial != NULL);
|
||||
|
@ -2203,6 +2348,8 @@ bool CModem::setFMMiscParams()
|
|||
buffer[11U] |= 0x01U;
|
||||
if (m_fmCOSInvert)
|
||||
buffer[11U] |= 0x02U;
|
||||
if (m_fmKerchunkTX)
|
||||
buffer[11U] |= 0x04U;
|
||||
|
||||
buffer[12U] = m_fmRFAudioBoost;
|
||||
|
||||
|
@ -2241,6 +2388,57 @@ bool CModem::setFMMiscParams()
|
|||
return true;
|
||||
}
|
||||
|
||||
bool CModem::setFMExtParams()
|
||||
{
|
||||
assert(m_serial != NULL);
|
||||
|
||||
unsigned char buffer[80U];
|
||||
unsigned char len = 7U + m_fmExtAck.size();
|
||||
|
||||
buffer[0U] = MMDVM_FRAME_START;
|
||||
buffer[1U] = len;
|
||||
buffer[2U] = MMDVM_FM_PARAMS4;
|
||||
|
||||
buffer[3U] = m_fmExtAudioBoost;
|
||||
buffer[4U] = m_fmAckSpeed;
|
||||
buffer[5U] = m_fmAckFrequency / 10U;
|
||||
|
||||
buffer[6U] = (unsigned char)(m_fmAckLevel * 2.55F + 0.5F);
|
||||
|
||||
for (unsigned int i = 0U; i < m_fmExtAck.size(); i++)
|
||||
buffer[7U + i] = m_fmExtAck.at(i);
|
||||
|
||||
// CUtils::dump(1U, "Written", buffer, len);
|
||||
|
||||
int ret = m_serial->write(buffer, len);
|
||||
if (ret != len)
|
||||
return false;
|
||||
|
||||
unsigned int count = 0U;
|
||||
RESP_TYPE_MMDVM resp;
|
||||
do {
|
||||
CThread::sleep(10U);
|
||||
|
||||
resp = getResponse();
|
||||
if (resp == RTM_OK && m_buffer[2U] != MMDVM_ACK && m_buffer[2U] != MMDVM_NAK) {
|
||||
count++;
|
||||
if (count >= MAX_RESPONSES) {
|
||||
LogError("The MMDVM is not responding to the SET_FM_PARAMS4 command");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} while (resp == RTM_OK && m_buffer[2U] != MMDVM_ACK && m_buffer[2U] != MMDVM_NAK);
|
||||
|
||||
// CUtils::dump(1U, "Response", m_buffer, m_length);
|
||||
|
||||
if (resp == RTM_OK && m_buffer[2U] == MMDVM_NAK) {
|
||||
LogError("Received a NAK to the SET_FM_PARAMS4 command from the modem");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CModem::printDebug()
|
||||
{
|
||||
if (m_buffer[2U] == MMDVM_DEBUG1) {
|
||||
|
|
20
Modem.h
20
Modem.h
|
@ -19,7 +19,7 @@
|
|||
#ifndef MODEM_H
|
||||
#define MODEM_H
|
||||
|
||||
#include "SerialController.h"
|
||||
#include "SerialPort.h"
|
||||
#include "RingBuffer.h"
|
||||
#include "Defines.h"
|
||||
#include "Timer.h"
|
||||
|
@ -45,7 +45,7 @@ public:
|
|||
CModem(const std::string& port, bool duplex, bool rxInvert, bool txInvert, bool pttInvert, unsigned int txDelay, unsigned int dmrDelay, bool trace, bool debug);
|
||||
virtual ~CModem();
|
||||
|
||||
virtual void setSerialParams(const std::string& protocol, unsigned int address);
|
||||
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 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, float ax25TXLevel);
|
||||
|
@ -58,7 +58,8 @@ public:
|
|||
|
||||
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, bool useCOS, bool cosInvert, unsigned int rfAudioBoost, float maxDevLevel);
|
||||
virtual void setFMMiscParams(unsigned int timeout, float timeoutLevel, float ctcssFrequency, unsigned int ctcssHighThreshold, unsigned int ctcssLowThreshold, float ctcssLevel, unsigned int kerchunkTime, bool kerchunkTX, unsigned int hangTime, bool useCOS, bool cosInvert, unsigned int rfAudioBoost, float maxDevLevel);
|
||||
virtual void setFMExtParams(const std::string& ack, unsigned int audioBoost);
|
||||
|
||||
virtual bool open();
|
||||
|
||||
|
@ -68,6 +69,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 readFMData(unsigned char* data);
|
||||
virtual unsigned int readAX25Data(unsigned char* data);
|
||||
virtual unsigned int readTransparentData(unsigned char* data);
|
||||
|
||||
|
@ -80,6 +82,7 @@ public:
|
|||
virtual bool hasP25Space() const;
|
||||
virtual bool hasNXDNSpace() const;
|
||||
virtual bool hasPOCSAGSpace() const;
|
||||
virtual unsigned int getFMSpace() const;
|
||||
virtual bool hasAX25Space() const;
|
||||
|
||||
virtual bool hasTX() const;
|
||||
|
@ -96,6 +99,7 @@ public:
|
|||
virtual bool writeP25Data(const unsigned char* data, unsigned int length);
|
||||
virtual bool writeNXDNData(const unsigned char* data, unsigned int length);
|
||||
virtual bool writePOCSAGData(const unsigned char* data, unsigned int length);
|
||||
virtual bool 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);
|
||||
|
@ -166,7 +170,7 @@ private:
|
|||
bool m_ax25Enabled;
|
||||
int m_rxDCOffset;
|
||||
int m_txDCOffset;
|
||||
CSerialController* m_serial;
|
||||
ISerialPort* m_serial;
|
||||
unsigned char* m_buffer;
|
||||
unsigned int m_length;
|
||||
unsigned int m_offset;
|
||||
|
@ -185,6 +189,8 @@ private:
|
|||
CRingBuffer<unsigned char> m_rxNXDNData;
|
||||
CRingBuffer<unsigned char> m_txNXDNData;
|
||||
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;
|
||||
|
@ -200,6 +206,7 @@ private:
|
|||
unsigned int m_p25Space;
|
||||
unsigned int m_nxdnSpace;
|
||||
unsigned int m_pocsagSpace;
|
||||
unsigned int m_fmSpace;
|
||||
unsigned int m_ax25Space;
|
||||
bool m_tx;
|
||||
bool m_cd;
|
||||
|
@ -221,6 +228,7 @@ private:
|
|||
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;
|
||||
|
@ -233,11 +241,14 @@ private:
|
|||
unsigned int m_fmCtcssLowThreshold;
|
||||
float m_fmCtcssLevel;
|
||||
unsigned int m_fmKerchunkTime;
|
||||
bool m_fmKerchunkTX;
|
||||
unsigned int m_fmHangTime;
|
||||
bool m_fmUseCOS;
|
||||
bool m_fmCOSInvert;
|
||||
unsigned int m_fmRFAudioBoost;
|
||||
unsigned int m_fmExtAudioBoost;
|
||||
float m_fmMaxDevLevel;
|
||||
bool m_fmExtEnable;
|
||||
|
||||
bool readVersion();
|
||||
bool readStatus();
|
||||
|
@ -246,6 +257,7 @@ private:
|
|||
bool setFMCallsignParams();
|
||||
bool setFMAckParams();
|
||||
bool setFMMiscParams();
|
||||
bool setFMExtParams();
|
||||
|
||||
void printDebug();
|
||||
|
||||
|
|
|
@ -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),
|
||||
|
@ -221,7 +220,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),
|
||||
|
@ -273,40 +272,44 @@ bool CSerialController::open()
|
|||
#endif
|
||||
|
||||
switch (m_speed) {
|
||||
case SERIAL_1200:
|
||||
case 1200U:
|
||||
::cfsetospeed(&termios, B1200);
|
||||
::cfsetispeed(&termios, B1200);
|
||||
break;
|
||||
case SERIAL_2400:
|
||||
case 2400U:
|
||||
::cfsetospeed(&termios, B2400);
|
||||
::cfsetispeed(&termios, B2400);
|
||||
break;
|
||||
case SERIAL_4800:
|
||||
case 4800U:
|
||||
::cfsetospeed(&termios, B4800);
|
||||
::cfsetispeed(&termios, B4800);
|
||||
break;
|
||||
case SERIAL_9600:
|
||||
case 9600U:
|
||||
::cfsetospeed(&termios, B9600);
|
||||
::cfsetispeed(&termios, B9600);
|
||||
break;
|
||||
case SERIAL_19200:
|
||||
case 19200U:
|
||||
::cfsetospeed(&termios, B19200);
|
||||
::cfsetispeed(&termios, B19200);
|
||||
break;
|
||||
case SERIAL_38400:
|
||||
case 38400U:
|
||||
::cfsetospeed(&termios, B38400);
|
||||
::cfsetispeed(&termios, B38400);
|
||||
break;
|
||||
case SERIAL_115200:
|
||||
case 115200U:
|
||||
::cfsetospeed(&termios, B115200);
|
||||
::cfsetispeed(&termios, B115200);
|
||||
break;
|
||||
case SERIAL_230400:
|
||||
case 230400U:
|
||||
::cfsetospeed(&termios, B230400);
|
||||
::cfsetispeed(&termios, B230400);
|
||||
break;
|
||||
case 460800U:
|
||||
::cfsetospeed(&termios, B460800);
|
||||
::cfsetispeed(&termios, B460800);
|
||||
break;
|
||||
default:
|
||||
LogError("Unsupported serial port speed - %d", int(m_speed));
|
||||
LogError("Unsupported serial port speed - %u", m_speed);
|
||||
::close(m_fd);
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
|
@ -59,7 +47,7 @@ public:
|
|||
|
||||
protected:
|
||||
std::string m_device;
|
||||
SERIAL_SPEED m_speed;
|
||||
unsigned int m_speed;
|
||||
bool m_assertRTS;
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
HANDLE m_handle;
|
||||
|
|
43
Tools/DeEmphasis.py
Normal file
43
Tools/DeEmphasis.py
Normal 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
51
Tools/PreEmphasis.py
Normal 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()
|
4
UMP.cpp
4
UMP.cpp
|
@ -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),
|
||||
|
|
Loading…
Reference in a new issue