Compare commits
2 commits
Author | SHA1 | Date | |
---|---|---|---|
|
d43a057f7a | ||
|
3c4f98a9a6 |
219 changed files with 27489 additions and 45246 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -17,4 +17,3 @@ RemoteCommand
|
|||
.vs
|
||||
*.ambe
|
||||
GitVersion.h
|
||||
.vscode
|
80
.vscode/settings.json
vendored
80
.vscode/settings.json
vendored
|
@ -1,80 +0,0 @@
|
|||
{
|
||||
"files.associations": {
|
||||
"fstream": "cpp",
|
||||
"cstring": "cpp",
|
||||
"string": "cpp",
|
||||
"cctype": "cpp",
|
||||
"clocale": "cpp",
|
||||
"cmath": "cpp",
|
||||
"cstdarg": "cpp",
|
||||
"cstddef": "cpp",
|
||||
"cstdio": "cpp",
|
||||
"cstdlib": "cpp",
|
||||
"ctime": "cpp",
|
||||
"cwchar": "cpp",
|
||||
"cwctype": "cpp",
|
||||
"any": "cpp",
|
||||
"array": "cpp",
|
||||
"atomic": "cpp",
|
||||
"hash_map": "cpp",
|
||||
"strstream": "cpp",
|
||||
"bit": "cpp",
|
||||
"*.tcc": "cpp",
|
||||
"bitset": "cpp",
|
||||
"cfenv": "cpp",
|
||||
"chrono": "cpp",
|
||||
"codecvt": "cpp",
|
||||
"compare": "cpp",
|
||||
"complex": "cpp",
|
||||
"concepts": "cpp",
|
||||
"condition_variable": "cpp",
|
||||
"cstdint": "cpp",
|
||||
"deque": "cpp",
|
||||
"forward_list": "cpp",
|
||||
"list": "cpp",
|
||||
"map": "cpp",
|
||||
"set": "cpp",
|
||||
"unordered_map": "cpp",
|
||||
"unordered_set": "cpp",
|
||||
"vector": "cpp",
|
||||
"exception": "cpp",
|
||||
"algorithm": "cpp",
|
||||
"functional": "cpp",
|
||||
"iterator": "cpp",
|
||||
"memory": "cpp",
|
||||
"memory_resource": "cpp",
|
||||
"numeric": "cpp",
|
||||
"optional": "cpp",
|
||||
"random": "cpp",
|
||||
"ratio": "cpp",
|
||||
"source_location": "cpp",
|
||||
"string_view": "cpp",
|
||||
"system_error": "cpp",
|
||||
"tuple": "cpp",
|
||||
"type_traits": "cpp",
|
||||
"utility": "cpp",
|
||||
"future": "cpp",
|
||||
"initializer_list": "cpp",
|
||||
"iomanip": "cpp",
|
||||
"iosfwd": "cpp",
|
||||
"iostream": "cpp",
|
||||
"istream": "cpp",
|
||||
"limits": "cpp",
|
||||
"mutex": "cpp",
|
||||
"new": "cpp",
|
||||
"numbers": "cpp",
|
||||
"ostream": "cpp",
|
||||
"semaphore": "cpp",
|
||||
"shared_mutex": "cpp",
|
||||
"sstream": "cpp",
|
||||
"stdexcept": "cpp",
|
||||
"stop_token": "cpp",
|
||||
"streambuf": "cpp",
|
||||
"thread": "cpp",
|
||||
"cinttypes": "cpp",
|
||||
"typeindex": "cpp",
|
||||
"typeinfo": "cpp",
|
||||
"valarray": "cpp",
|
||||
"variant": "cpp"
|
||||
}
|
||||
}
|
49
AMBEFEC.cpp
49
AMBEFEC.cpp
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2010,2014,2016,2018,2021 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2010,2014,2016,2018 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2016 Mathias Weyland, HB9FRV
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
|
@ -20,7 +20,6 @@
|
|||
#include "Golay24128.h"
|
||||
#include "Hamming.h"
|
||||
#include "AMBEFEC.h"
|
||||
#include "Utils.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <cassert>
|
||||
|
@ -796,31 +795,34 @@ unsigned int CAMBEFEC::regenerateDStar(unsigned int& a, unsigned int& b) const
|
|||
unsigned int orig_a = a;
|
||||
unsigned int orig_b = b;
|
||||
|
||||
unsigned int data;
|
||||
bool valid1 = CGolay24128::decode24128(a, data);
|
||||
if (!valid1)
|
||||
return 10U;
|
||||
unsigned int data = CGolay24128::decode24128(a);
|
||||
|
||||
a = CGolay24128::encode24128(data);
|
||||
|
||||
// The PRNG
|
||||
unsigned int p = PRNG_TABLE[data];
|
||||
|
||||
b ^= p;
|
||||
|
||||
unsigned int datb;
|
||||
bool valid2 = CGolay24128::decode24128(b, datb);
|
||||
if (!valid2)
|
||||
return 10U;
|
||||
unsigned int datb = CGolay24128::decode24128(b);
|
||||
|
||||
a = CGolay24128::encode24128(data);
|
||||
b = CGolay24128::encode24128(datb);
|
||||
|
||||
b ^= p;
|
||||
|
||||
unsigned int errsA = 0U, errsB = 0U;
|
||||
|
||||
unsigned int v = a ^ orig_a;
|
||||
unsigned int errsA = CUtils::countBits(v);
|
||||
while (v != 0U) {
|
||||
v &= v - 1U;
|
||||
errsA++;
|
||||
}
|
||||
|
||||
v = b ^ orig_b;
|
||||
unsigned int errsB = CUtils::countBits(v);
|
||||
while (v != 0U) {
|
||||
v &= v - 1U;
|
||||
errsB++;
|
||||
}
|
||||
|
||||
return errsA + errsB;
|
||||
}
|
||||
|
@ -830,14 +832,7 @@ unsigned int CAMBEFEC::regenerateDMR(unsigned int& a, unsigned int& b, unsigned
|
|||
unsigned int orig_a = a;
|
||||
unsigned int orig_b = b;
|
||||
|
||||
unsigned int data;
|
||||
bool valid = CGolay24128::decode24128(a, data);
|
||||
if (!valid) {
|
||||
a = 0xF00292U;
|
||||
b = 0x0E0B20U;
|
||||
c = 0x000000U;
|
||||
return 10U; // An invalid A block gives an error count of 10
|
||||
}
|
||||
unsigned int data = CGolay24128::decode24128(a);
|
||||
|
||||
a = CGolay24128::encode24128(data);
|
||||
|
||||
|
@ -852,11 +847,19 @@ unsigned int CAMBEFEC::regenerateDMR(unsigned int& a, unsigned int& b, unsigned
|
|||
|
||||
b ^= p;
|
||||
|
||||
unsigned int errsA = 0U, errsB = 0U;
|
||||
|
||||
unsigned int v = a ^ orig_a;
|
||||
unsigned int errsA = CUtils::countBits(v);
|
||||
while (v != 0U) {
|
||||
v &= v - 1U;
|
||||
errsA++;
|
||||
}
|
||||
|
||||
v = b ^ orig_b;
|
||||
unsigned int errsB = CUtils::countBits(v);
|
||||
while (v != 0U) {
|
||||
v &= v - 1U;
|
||||
errsB++;
|
||||
}
|
||||
|
||||
if (errsA >= 4U || ((errsA + errsB) >= 6U && errsA >= 2U)) {
|
||||
a = 0xF00292U;
|
||||
|
|
52
CASTInfo.cpp
52
CASTInfo.cpp
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2016,2018,2020,2021 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2016,2018 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
@ -76,6 +76,16 @@ void CCASTInfo::setQuitInt()
|
|||
{
|
||||
}
|
||||
|
||||
void CCASTInfo::writeDStarInt(const char* my1, const char* my2, const char* your, const char* type, const char* reflector)
|
||||
{
|
||||
if (m_modem != NULL)
|
||||
m_modem->writeDStarInfo(my1, my2, your, type, reflector);
|
||||
}
|
||||
|
||||
void CCASTInfo::clearDStarInt()
|
||||
{
|
||||
}
|
||||
|
||||
void CCASTInfo::writeDMRInt(unsigned int slotNo, const std::string& src, bool group, const std::string& dst, const char* type)
|
||||
{
|
||||
if (m_modem != NULL)
|
||||
|
@ -86,6 +96,46 @@ void CCASTInfo::clearDMRInt(unsigned int slotNo)
|
|||
{
|
||||
}
|
||||
|
||||
void CCASTInfo::writeFusionInt(const char* source, const char* dest, const char* type, const char* origin)
|
||||
{
|
||||
if (m_modem != NULL)
|
||||
m_modem->writeYSFInfo(source, dest, type, origin);
|
||||
}
|
||||
|
||||
void CCASTInfo::clearFusionInt()
|
||||
{
|
||||
}
|
||||
|
||||
void CCASTInfo::writeP25Int(const char* source, bool group, unsigned int dest, const char* type)
|
||||
{
|
||||
if (m_modem != NULL)
|
||||
m_modem->writeP25Info(source, group, dest, type);
|
||||
}
|
||||
|
||||
void CCASTInfo::clearP25Int()
|
||||
{
|
||||
}
|
||||
|
||||
void CCASTInfo::writeNXDNInt(const char* source, bool group, unsigned int dest, const char* type)
|
||||
{
|
||||
if (m_modem != NULL)
|
||||
m_modem->writeNXDNInfo(source, group, dest, type);
|
||||
}
|
||||
|
||||
void CCASTInfo::clearNXDNInt()
|
||||
{
|
||||
}
|
||||
|
||||
void CCASTInfo::writePOCSAGInt(uint32_t ric, const std::string& message)
|
||||
{
|
||||
if (m_modem != NULL)
|
||||
m_modem->writePOCSAGInfo(ric, message);
|
||||
}
|
||||
|
||||
void CCASTInfo::clearPOCSAGInt()
|
||||
{
|
||||
}
|
||||
|
||||
void CCASTInfo::writeCWInt()
|
||||
{
|
||||
}
|
||||
|
|
20
CASTInfo.h
20
CASTInfo.h
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2016,2018,2020,2021 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2016,2018 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
@ -25,7 +25,6 @@
|
|||
|
||||
#include "NetworkInfo.h"
|
||||
#include "Modem.h"
|
||||
|
||||
class CCASTInfo : public CDisplay
|
||||
{
|
||||
public:
|
||||
|
@ -42,14 +41,29 @@ protected:
|
|||
virtual void setLockoutInt();
|
||||
virtual void setQuitInt();
|
||||
|
||||
virtual void writeDStarInt(const char* my1, const char* my2, const char* your, const char* type, const char* reflector);
|
||||
virtual void clearDStarInt();
|
||||
|
||||
virtual void writeDMRInt(unsigned int slotNo, const std::string& src, bool group, const std::string& dst, const char* type);
|
||||
virtual void clearDMRInt(unsigned int slotNo);
|
||||
|
||||
virtual void writeFusionInt(const char* source, const char* dest, const char* type, const char* origin);
|
||||
virtual void clearFusionInt();
|
||||
|
||||
virtual void writeP25Int(const char* source, bool group, unsigned int dest, const char* type);
|
||||
virtual void clearP25Int();
|
||||
|
||||
virtual void writeNXDNInt(const char* source, bool group, unsigned int dest, const char* type);
|
||||
virtual void clearNXDNInt();
|
||||
|
||||
virtual void writePOCSAGInt(uint32_t ric, const std::string& message);
|
||||
virtual void clearPOCSAGInt();
|
||||
|
||||
virtual void writeCWInt();
|
||||
virtual void clearCWInt();
|
||||
|
||||
private:
|
||||
CModem* m_modem;
|
||||
CModem* m_modem;
|
||||
std::string m_ipaddress;
|
||||
};
|
||||
|
||||
|
|
270
Conf.h
270
Conf.h
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2015-2021 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2015-2019 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
@ -54,7 +54,6 @@ public:
|
|||
unsigned int getLogFileLevel() const;
|
||||
std::string getLogFilePath() const;
|
||||
std::string getLogFileRoot() const;
|
||||
bool getLogFileRotate() const;
|
||||
|
||||
// The CW ID section
|
||||
bool getCWIdEnabled() const;
|
||||
|
@ -65,16 +64,14 @@ public:
|
|||
std::string getDMRIdLookupFile() const;
|
||||
unsigned int getDMRIdLookupTime() const;
|
||||
|
||||
// The NXDN Id section
|
||||
std::string getNXDNIdLookupFile() const;
|
||||
unsigned int getNXDNIdLookupTime() const;
|
||||
|
||||
// The Modem section
|
||||
std::string getModemPort() const;
|
||||
std::string getModemProtocol() const;
|
||||
std::string getModemUARTPort() const;
|
||||
unsigned int getModemUARTSpeed() const;
|
||||
std::string getModemI2CPort() const;
|
||||
unsigned int getModemI2CAddress() const;
|
||||
std::string getModemModemAddress() const;
|
||||
unsigned short getModemModemPort() const;
|
||||
std::string getModemLocalAddress() const;
|
||||
unsigned short getModemLocalPort() const;
|
||||
unsigned int getModemAddress() const;
|
||||
bool getModemRXInvert() const;
|
||||
bool getModemTXInvert() const;
|
||||
bool getModemPTTInvert() const;
|
||||
|
@ -92,25 +89,37 @@ public:
|
|||
float getModemYSFTXLevel() const;
|
||||
float getModemP25TXLevel() const;
|
||||
float getModemNXDNTXLevel() const;
|
||||
float getModemM17TXLevel() const;
|
||||
float getModemPOCSAGTXLevel() const;
|
||||
float getModemFMTXLevel() const;
|
||||
float getModemAX25TXLevel() const;
|
||||
std::string getModemRSSIMappingFile() const;
|
||||
bool getModemUseCOSAsLockout() const;
|
||||
bool getModemTrace() const;
|
||||
bool getModemDebug() const;
|
||||
|
||||
// The Transparent Data section
|
||||
bool getTransparentEnabled() const;
|
||||
std::string getTransparentRemoteAddress() const;
|
||||
unsigned short getTransparentRemotePort() const;
|
||||
unsigned short getTransparentLocalPort() const;
|
||||
unsigned int getTransparentRemotePort() const;
|
||||
unsigned int getTransparentLocalPort() const;
|
||||
unsigned int getTransparentSendFrameType() const;
|
||||
|
||||
// The DMR section
|
||||
// The UMP section
|
||||
bool getUMPEnabled() const;
|
||||
std::string getUMPPort() const;
|
||||
|
||||
// The D-Star section
|
||||
bool getDStarEnabled() const;
|
||||
std::string getDStarModule() const;
|
||||
bool getDStarSelfOnly() const;
|
||||
std::vector<std::string> getDStarBlackList() const;
|
||||
bool getDStarAckReply() const;
|
||||
unsigned int getDStarAckTime() const;
|
||||
bool getDStarAckMessage() const;
|
||||
bool getDStarErrorReply() const;
|
||||
bool getDStarRemoteGateway() const;
|
||||
unsigned int getDStarModeHang() const;
|
||||
|
||||
// The DMR section
|
||||
bool getDMREnabled() const;
|
||||
DMR_BEACONS getDMRBeacons() const;
|
||||
bool getDMRBeacons() const;
|
||||
unsigned int getDMRBeaconInterval() const;
|
||||
unsigned int getDMRBeaconDuration() const;
|
||||
unsigned int getDMRId() const;
|
||||
|
@ -126,15 +135,51 @@ public:
|
|||
unsigned int getDMRCallHang() const;
|
||||
unsigned int getDMRTXHang() const;
|
||||
unsigned int getDMRModeHang() const;
|
||||
DMR_OVCM_TYPES getDMROVCM() const;
|
||||
|
||||
// The DMR Network section
|
||||
// The System Fusion section
|
||||
bool getFusionEnabled() const;
|
||||
bool getFusionLowDeviation() const;
|
||||
bool getFusionRemoteGateway() const;
|
||||
bool getFusionSelfOnly() const;
|
||||
unsigned int getFusionTXHang() const;
|
||||
bool getFusionDGIdEnabled() const;
|
||||
unsigned char getFusionDGId() const;
|
||||
unsigned int getFusionModeHang() const;
|
||||
|
||||
// The P25 section
|
||||
bool getP25Enabled() const;
|
||||
unsigned int getP25Id() const;
|
||||
unsigned int getP25NAC() const;
|
||||
bool getP25SelfOnly() const;
|
||||
bool getP25OverrideUID() const;
|
||||
bool getP25RemoteGateway() const;
|
||||
unsigned int getP25ModeHang() const;
|
||||
|
||||
// The NXDN section
|
||||
bool getNXDNEnabled() const;
|
||||
unsigned int getNXDNId() const;
|
||||
unsigned int getNXDNRAN() const;
|
||||
bool getNXDNSelfOnly() const;
|
||||
bool getNXDNRemoteGateway() const;
|
||||
unsigned int getNXDNModeHang() const;
|
||||
|
||||
// The POCSAG section
|
||||
bool getPOCSAGEnabled() const;
|
||||
unsigned int getPOCSAGFrequency() const;
|
||||
|
||||
// The D-Star Network section
|
||||
bool getDStarNetworkEnabled() const;
|
||||
std::string getDStarGatewayAddress() const;
|
||||
unsigned int getDStarGatewayPort() const;
|
||||
unsigned int getDStarLocalPort() const;
|
||||
unsigned int getDStarNetworkModeHang() const;
|
||||
bool getDStarNetworkDebug() const;
|
||||
|
||||
// The DMR Network section
|
||||
bool getDMRNetworkEnabled() const;
|
||||
std::string getDMRNetworkType() const;
|
||||
std::string getDMRNetworkRemoteAddress() const;
|
||||
unsigned short getDMRNetworkRemotePort() const;
|
||||
std::string getDMRNetworkLocalAddress() const;
|
||||
unsigned short getDMRNetworkLocalPort() const;
|
||||
std::string getDMRNetworkAddress() const;
|
||||
unsigned int getDMRNetworkPort() const;
|
||||
unsigned int getDMRNetworkLocal() const;
|
||||
std::string getDMRNetworkPassword() const;
|
||||
std::string getDMRNetworkOptions() const;
|
||||
bool getDMRNetworkDebug() const;
|
||||
|
@ -143,7 +188,42 @@ public:
|
|||
bool getDMRNetworkSlot2() const;
|
||||
unsigned int getDMRNetworkModeHang() const;
|
||||
|
||||
// The TFTSERIAL section
|
||||
// The System Fusion Network section
|
||||
bool getFusionNetworkEnabled() const;
|
||||
std::string getFusionNetworkMyAddress() const;
|
||||
unsigned int getFusionNetworkMyPort() const;
|
||||
std::string getFusionNetworkGatewayAddress() const;
|
||||
unsigned int getFusionNetworkGatewayPort() const;
|
||||
unsigned int getFusionNetworkModeHang() const;
|
||||
bool getFusionNetworkDebug() const;
|
||||
|
||||
// The P25 Network section
|
||||
bool getP25NetworkEnabled() const;
|
||||
std::string getP25GatewayAddress() const;
|
||||
unsigned int getP25GatewayPort() const;
|
||||
unsigned int getP25LocalPort() const;
|
||||
unsigned int getP25NetworkModeHang() const;
|
||||
bool getP25NetworkDebug() const;
|
||||
|
||||
// The NXDN Network section
|
||||
bool getNXDNNetworkEnabled() const;
|
||||
std::string getNXDNGatewayAddress() const;
|
||||
unsigned int getNXDNGatewayPort() const;
|
||||
std::string getNXDNLocalAddress() const;
|
||||
unsigned int getNXDNLocalPort() const;
|
||||
unsigned int getNXDNNetworkModeHang() const;
|
||||
bool getNXDNNetworkDebug() const;
|
||||
|
||||
// The POCSAG Network section
|
||||
bool getPOCSAGNetworkEnabled() const;
|
||||
std::string getPOCSAGGatewayAddress() const;
|
||||
unsigned int getPOCSAGGatewayPort() const;
|
||||
std::string getPOCSAGLocalAddress() const;
|
||||
unsigned int getPOCSAGLocalPort() const;
|
||||
unsigned int getPOCSAGNetworkModeHang() const;
|
||||
bool getPOCSAGNetworkDebug() const;
|
||||
|
||||
// The TFTSERIAL section
|
||||
std::string getTFTSerialPort() const;
|
||||
unsigned int getTFTSerialBrightness() const;
|
||||
|
||||
|
@ -174,12 +254,11 @@ public:
|
|||
bool getOLEDInvert() const;
|
||||
bool getOLEDScroll() const;
|
||||
bool getOLEDRotate() const;
|
||||
bool getOLEDLogoScreensaver() const;
|
||||
|
||||
// The LCDproc section
|
||||
std::string getLCDprocAddress() const;
|
||||
unsigned short getLCDprocPort() const;
|
||||
unsigned short getLCDprocLocalPort() const;
|
||||
unsigned int getLCDprocPort() const;
|
||||
unsigned int getLCDprocLocalPort() const;
|
||||
bool getLCDprocDisplayClock() const;
|
||||
bool getLCDprocUTC() const;
|
||||
bool getLCDprocDimOnIdle() const;
|
||||
|
@ -188,10 +267,14 @@ public:
|
|||
bool getLockFileEnabled() const;
|
||||
std::string getLockFileName() const;
|
||||
|
||||
// The Mobile GPS section
|
||||
bool getMobileGPSEnabled() const;
|
||||
std::string getMobileGPSAddress() const;
|
||||
unsigned int getMobileGPSPort() const;
|
||||
|
||||
// The Remote Control section
|
||||
bool getRemoteControlEnabled() const;
|
||||
std::string getRemoteControlAddress() const;
|
||||
unsigned short getRemoteControlPort() const;
|
||||
unsigned int getRemoteControlPort() const;
|
||||
|
||||
private:
|
||||
std::string m_file;
|
||||
|
@ -216,7 +299,6 @@ private:
|
|||
unsigned int m_logFileLevel;
|
||||
std::string m_logFilePath;
|
||||
std::string m_logFileRoot;
|
||||
bool m_logFileRotate;
|
||||
|
||||
bool m_cwIdEnabled;
|
||||
unsigned int m_cwIdTime;
|
||||
|
@ -228,15 +310,9 @@ private:
|
|||
std::string m_nxdnIdLookupFile;
|
||||
unsigned int m_nxdnIdLookupTime;
|
||||
|
||||
std::string m_modemPort;
|
||||
std::string m_modemProtocol;
|
||||
std::string m_modemUARTPort;
|
||||
unsigned int m_modemUARTSpeed;
|
||||
std::string m_modemI2CPort;
|
||||
unsigned int m_modemI2CAddress;
|
||||
std::string m_modemModemAddress;
|
||||
unsigned short m_modemModemPort;
|
||||
std::string m_modemLocalAddress;
|
||||
unsigned short m_modemLocalPort;
|
||||
unsigned int m_modemAddress;
|
||||
bool m_modemRXInvert;
|
||||
bool m_modemTXInvert;
|
||||
bool m_modemPTTInvert;
|
||||
|
@ -249,20 +325,38 @@ private:
|
|||
float m_modemRFLevel;
|
||||
float m_modemRXLevel;
|
||||
float m_modemCWIdTXLevel;
|
||||
float m_modemDStarTXLevel;
|
||||
float m_modemDMRTXLevel;
|
||||
float m_modemYSFTXLevel;
|
||||
float m_modemP25TXLevel;
|
||||
float m_modemNXDNTXLevel;
|
||||
float m_modemPOCSAGTXLevel;
|
||||
std::string m_modemRSSIMappingFile;
|
||||
bool m_modemUseCOSAsLockout;
|
||||
bool m_modemTrace;
|
||||
bool m_modemDebug;
|
||||
|
||||
bool m_transparentEnabled;
|
||||
std::string m_transparentRemoteAddress;
|
||||
unsigned short m_transparentRemotePort;
|
||||
unsigned short m_transparentLocalPort;
|
||||
unsigned int m_transparentRemotePort;
|
||||
unsigned int m_transparentLocalPort;
|
||||
unsigned int m_transparentSendFrameType;
|
||||
|
||||
bool m_umpEnabled;
|
||||
std::string m_umpPort;
|
||||
|
||||
bool m_dstarEnabled;
|
||||
std::string m_dstarModule;
|
||||
bool m_dstarSelfOnly;
|
||||
std::vector<std::string> m_dstarBlackList;
|
||||
bool m_dstarAckReply;
|
||||
unsigned int m_dstarAckTime;
|
||||
bool m_dstarAckMessage;
|
||||
bool m_dstarErrorReply;
|
||||
bool m_dstarRemoteGateway;
|
||||
unsigned int m_dstarModeHang;
|
||||
|
||||
bool m_dmrEnabled;
|
||||
DMR_BEACONS m_dmrBeacons;
|
||||
bool m_dmrBeacons;
|
||||
unsigned int m_dmrBeaconInterval;
|
||||
unsigned int m_dmrBeaconDuration;
|
||||
unsigned int m_dmrId;
|
||||
|
@ -278,14 +372,45 @@ private:
|
|||
unsigned int m_dmrCallHang;
|
||||
unsigned int m_dmrTXHang;
|
||||
unsigned int m_dmrModeHang;
|
||||
DMR_OVCM_TYPES m_dmrOVCM;
|
||||
|
||||
bool m_fusionEnabled;
|
||||
bool m_fusionLowDeviation;
|
||||
bool m_fusionRemoteGateway;
|
||||
bool m_fusionSelfOnly;
|
||||
unsigned int m_fusionTXHang;
|
||||
bool m_fusionDGIdEnabled;
|
||||
unsigned char m_fusionDGId;
|
||||
unsigned int m_fusionModeHang;
|
||||
|
||||
bool m_p25Enabled;
|
||||
unsigned int m_p25Id;
|
||||
unsigned int m_p25NAC;
|
||||
bool m_p25SelfOnly;
|
||||
bool m_p25OverrideUID;
|
||||
bool m_p25RemoteGateway;
|
||||
unsigned int m_p25ModeHang;
|
||||
|
||||
bool m_nxdnEnabled;
|
||||
unsigned int m_nxdnId;
|
||||
unsigned int m_nxdnRAN;
|
||||
bool m_nxdnSelfOnly;
|
||||
bool m_nxdnRemoteGateway;
|
||||
unsigned int m_nxdnModeHang;
|
||||
|
||||
bool m_pocsagEnabled;
|
||||
unsigned int m_pocsagFrequency;
|
||||
|
||||
bool m_dstarNetworkEnabled;
|
||||
std::string m_dstarGatewayAddress;
|
||||
unsigned int m_dstarGatewayPort;
|
||||
unsigned int m_dstarLocalPort;
|
||||
unsigned int m_dstarNetworkModeHang;
|
||||
bool m_dstarNetworkDebug;
|
||||
|
||||
bool m_dmrNetworkEnabled;
|
||||
std::string m_dmrNetworkType;
|
||||
std::string m_dmrNetworkRemoteAddress;
|
||||
unsigned short m_dmrNetworkRemotePort;
|
||||
std::string m_dmrNetworkLocalAddress;
|
||||
unsigned short m_dmrNetworkLocalPort;
|
||||
std::string m_dmrNetworkAddress;
|
||||
unsigned int m_dmrNetworkPort;
|
||||
unsigned int m_dmrNetworkLocal;
|
||||
std::string m_dmrNetworkPassword;
|
||||
std::string m_dmrNetworkOptions;
|
||||
bool m_dmrNetworkDebug;
|
||||
|
@ -294,7 +419,38 @@ private:
|
|||
bool m_dmrNetworkSlot2;
|
||||
unsigned int m_dmrNetworkModeHang;
|
||||
|
||||
std::string m_tftSerialPort;
|
||||
bool m_fusionNetworkEnabled;
|
||||
std::string m_fusionNetworkMyAddress;
|
||||
unsigned int m_fusionNetworkMyPort;
|
||||
std::string m_fusionNetworkGatewayAddress;
|
||||
unsigned int m_fusionNetworkGatewayPort;
|
||||
unsigned int m_fusionNetworkModeHang;
|
||||
bool m_fusionNetworkDebug;
|
||||
|
||||
bool m_p25NetworkEnabled;
|
||||
std::string m_p25GatewayAddress;
|
||||
unsigned int m_p25GatewayPort;
|
||||
unsigned int m_p25LocalPort;
|
||||
unsigned int m_p25NetworkModeHang;
|
||||
bool m_p25NetworkDebug;
|
||||
|
||||
bool m_nxdnNetworkEnabled;
|
||||
std::string m_nxdnGatewayAddress;
|
||||
unsigned int m_nxdnGatewayPort;
|
||||
std::string m_nxdnLocalAddress;
|
||||
unsigned int m_nxdnLocalPort;
|
||||
unsigned int m_nxdnNetworkModeHang;
|
||||
bool m_nxdnNetworkDebug;
|
||||
|
||||
bool m_pocsagNetworkEnabled;
|
||||
std::string m_pocsagGatewayAddress;
|
||||
unsigned int m_pocsagGatewayPort;
|
||||
std::string m_pocsagLocalAddress;
|
||||
unsigned int m_pocsagLocalPort;
|
||||
unsigned int m_pocsagNetworkModeHang;
|
||||
bool m_pocsagNetworkDebug;
|
||||
|
||||
std::string m_tftSerialPort;
|
||||
unsigned int m_tftSerialBrightness;
|
||||
|
||||
unsigned int m_hd44780Rows;
|
||||
|
@ -321,11 +477,10 @@ private:
|
|||
bool m_oledInvert;
|
||||
bool m_oledScroll;
|
||||
bool m_oledRotate;
|
||||
bool m_oledLogoScreensaver;
|
||||
|
||||
std::string m_lcdprocAddress;
|
||||
unsigned short m_lcdprocPort;
|
||||
unsigned short m_lcdprocLocalPort;
|
||||
unsigned int m_lcdprocPort;
|
||||
unsigned int m_lcdprocLocalPort;
|
||||
bool m_lcdprocDisplayClock;
|
||||
bool m_lcdprocUTC;
|
||||
bool m_lcdprocDimOnIdle;
|
||||
|
@ -333,9 +488,12 @@ private:
|
|||
bool m_lockFileEnabled;
|
||||
std::string m_lockFileName;
|
||||
|
||||
bool m_mobileGPSEnabled;
|
||||
std::string m_mobileGPSAddress;
|
||||
unsigned int m_mobileGPSPort;
|
||||
|
||||
bool m_remoteControlEnabled;
|
||||
std::string m_remoteControlAddress;
|
||||
unsigned short m_remoteControlPort;
|
||||
unsigned int m_remoteControlPort;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -61,7 +61,7 @@ bool CDMRAccessControl::validateSrcId(unsigned int id)
|
|||
return false;
|
||||
|
||||
unsigned int prefix = id / 10000U;
|
||||
if (prefix == 0U || prefix > 9999U)
|
||||
if (prefix == 0U || prefix > 999U)
|
||||
return false;
|
||||
|
||||
if (!m_prefixes.empty()) {
|
||||
|
|
58
DMRCSBK.cpp
58
DMRCSBK.cpp
|
@ -1,6 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2015,2016,2020,2021,2022 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2019 by Patrick Maier DK5MP
|
||||
* Copyright (C) 2015,2016 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
@ -34,8 +33,7 @@ m_bsId(0U),
|
|||
m_srcId(0U),
|
||||
m_dstId(0U),
|
||||
m_dataContent(false),
|
||||
m_CBF(0U),
|
||||
m_OVCM(false)
|
||||
m_CBF(0U)
|
||||
{
|
||||
m_data = new unsigned char[12U];
|
||||
}
|
||||
|
@ -82,7 +80,6 @@ bool CDMRCSBK::put(const unsigned char* bytes)
|
|||
m_srcId = m_data[7U] << 16 | m_data[8U] << 8 | m_data[9U];
|
||||
m_dataContent = false;
|
||||
m_CBF = 0U;
|
||||
m_OVCM = (m_data[2U] & 0x04U) == 0x04U;
|
||||
CUtils::dump(1U, "Unit to Unit Service Request CSBK", m_data, 12U);
|
||||
break;
|
||||
|
||||
|
@ -92,7 +89,6 @@ bool CDMRCSBK::put(const unsigned char* bytes)
|
|||
m_srcId = m_data[7U] << 16 | m_data[8U] << 8 | m_data[9U];
|
||||
m_dataContent = false;
|
||||
m_CBF = 0U;
|
||||
m_OVCM = (m_data[2U] & 0x04U) == 0x04U;
|
||||
CUtils::dump(1U, "Unit to Unit Service Answer Response CSBK", m_data, 12U);
|
||||
break;
|
||||
|
||||
|
@ -114,39 +110,6 @@ bool CDMRCSBK::put(const unsigned char* bytes)
|
|||
CUtils::dump(1U, "Negative Acknowledge Response CSBK", m_data, 12U);
|
||||
break;
|
||||
|
||||
case CSBKO_CALL_ALERT:
|
||||
m_GI = false;
|
||||
m_dstId = m_data[4U] << 16 | m_data[5U] << 8 | m_data[6U];
|
||||
m_srcId = m_data[7U] << 16 | m_data[8U] << 8 | m_data[9U];
|
||||
m_dataContent = false;
|
||||
m_CBF = 0U;
|
||||
CUtils::dump(1U, "Call Alert CSBK", m_data, 12U);
|
||||
break;
|
||||
|
||||
case CSBKO_CALL_ALERT_ACK:
|
||||
m_GI = false;
|
||||
m_dstId = m_data[4U] << 16 | m_data[5U] << 8 | m_data[6U];
|
||||
m_srcId = m_data[7U] << 16 | m_data[8U] << 8 | m_data[9U];
|
||||
m_dataContent = false;
|
||||
m_CBF = 0U;
|
||||
CUtils::dump(1U, "Call Alert Ack CSBK", m_data, 12U);
|
||||
break;
|
||||
|
||||
case CSBKO_RADIO_CHECK:
|
||||
m_GI = false;
|
||||
if (m_data[3U] == 0x80) {
|
||||
m_dstId = m_data[4U] << 16 | m_data[5U] << 8 | m_data[6U];
|
||||
m_srcId = m_data[7U] << 16 | m_data[8U] << 8 | m_data[9U];
|
||||
CUtils::dump(1U, "Radio Check Req CSBK", m_data, 12U);
|
||||
} else {
|
||||
m_srcId = m_data[4U] << 16 | m_data[5U] << 8 | m_data[6U];
|
||||
m_dstId = m_data[7U] << 16 | m_data[8U] << 8 | m_data[9U];
|
||||
CUtils::dump(1U, "Radio Check Ack CSBK", m_data, 12U);
|
||||
}
|
||||
m_dataContent = false;
|
||||
m_CBF = 0U;
|
||||
break;
|
||||
|
||||
default:
|
||||
m_GI = false;
|
||||
m_srcId = 0U;
|
||||
|
@ -186,23 +149,6 @@ unsigned char CDMRCSBK::getFID() const
|
|||
return m_FID;
|
||||
}
|
||||
|
||||
bool CDMRCSBK::getOVCM() const
|
||||
{
|
||||
return m_OVCM;
|
||||
}
|
||||
|
||||
void CDMRCSBK::setOVCM(bool ovcm)
|
||||
{
|
||||
if (m_CSBKO == CSBKO_UUVREQ || m_CSBKO == CSBKO_UUANSRSP) {
|
||||
m_OVCM = ovcm;
|
||||
|
||||
if (ovcm)
|
||||
m_data[2U] |= 0x04U;
|
||||
else
|
||||
m_data[2U] &= 0xFBU;
|
||||
}
|
||||
}
|
||||
|
||||
bool CDMRCSBK::getGI() const
|
||||
{
|
||||
return m_GI;
|
||||
|
|
24
DMRCSBK.h
24
DMRCSBK.h
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2015,2016,2020,2021,2022 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2015,2016 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
@ -22,16 +22,13 @@
|
|||
#include "DMRDefines.h"
|
||||
|
||||
enum CSBKO {
|
||||
CSBKO_NONE = 0x00,
|
||||
CSBKO_UUVREQ = 0x04,
|
||||
CSBKO_UUANSRSP = 0x05,
|
||||
CSBKO_CTCSBK = 0x07,
|
||||
CSBKO_CALL_ALERT = 0x1F,
|
||||
CSBKO_CALL_ALERT_ACK = 0x20,
|
||||
CSBKO_RADIO_CHECK = 0x24,
|
||||
CSBKO_NACKRSP = 0x26,
|
||||
CSBKO_BSDWNACT = 0x38,
|
||||
CSBKO_PRECCSBK = 0x3D
|
||||
CSBKO_NONE = 0x00,
|
||||
CSBKO_UUVREQ = 0x04,
|
||||
CSBKO_UUANSRSP = 0x05,
|
||||
CSBKO_CTCSBK = 0x07,
|
||||
CSBKO_NACKRSP = 0x26,
|
||||
CSBKO_BSDWNACT = 0x38,
|
||||
CSBKO_PRECCSBK = 0x3D
|
||||
};
|
||||
|
||||
class CDMRCSBK
|
||||
|
@ -48,10 +45,6 @@ public:
|
|||
CSBKO getCSBKO() const;
|
||||
unsigned char getFID() const;
|
||||
|
||||
// Set/Get the OVCM bit in the supported CSBKs
|
||||
bool getOVCM() const;
|
||||
void setOVCM(bool ovcm);
|
||||
|
||||
// For BS Dwn Act
|
||||
unsigned int getBSId() const;
|
||||
|
||||
|
@ -76,7 +69,6 @@ private:
|
|||
unsigned int m_dstId;
|
||||
bool m_dataContent;
|
||||
unsigned char m_CBF;
|
||||
bool m_OVCM;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2015-2021 Jonathan Naylor, G4KLX
|
||||
* Copyright (C) 2015-2019 Jonathan Naylor, G4KLX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
@ -21,7 +21,7 @@
|
|||
#include <cassert>
|
||||
#include <algorithm>
|
||||
|
||||
CDMRControl::CDMRControl(unsigned int id, unsigned int colorCode, unsigned int callHang, bool selfOnly, bool embeddedLCOnly, bool dumpTAData, const std::vector<unsigned int>& prefixes, const std::vector<unsigned int>& blacklist, const std::vector<unsigned int>& whitelist, const std::vector<unsigned int>& slot1TGWhitelist, const std::vector<unsigned int>& slot2TGWhitelist, unsigned int timeout, CModem* modem, IDMRNetwork* network, CDisplay* display, bool duplex, CDMRLookup* lookup, CRSSIInterpolator* rssi, unsigned int jitter, DMR_OVCM_TYPES ovcm) :
|
||||
CDMRControl::CDMRControl(unsigned int id, unsigned int colorCode, unsigned int callHang, bool selfOnly, bool embeddedLCOnly, bool dumpTAData, const std::vector<unsigned int>& prefixes, const std::vector<unsigned int>& blacklist, const std::vector<unsigned int>& whitelist, const std::vector<unsigned int>& slot1TGWhitelist, const std::vector<unsigned int>& slot2TGWhitelist, unsigned int timeout, CModem* modem, CDMRNetwork* network, CDisplay* display, bool duplex, CDMRLookup* lookup, CRSSIInterpolator* rssi, unsigned int jitter) :
|
||||
m_colorCode(colorCode),
|
||||
m_modem(modem),
|
||||
m_network(network),
|
||||
|
@ -38,14 +38,7 @@ m_lookup(lookup)
|
|||
// Load black and white lists to DMRAccessControl
|
||||
CDMRAccessControl::init(blacklist, whitelist, slot1TGWhitelist, slot2TGWhitelist, selfOnly, prefixes, id);
|
||||
|
||||
//Print whitelisted IDs
|
||||
LogMessage("Allowed radio ids: ");
|
||||
for (unsigned int i: whitelist) {
|
||||
std::string id_name = std::to_string(i);
|
||||
LogMessage(id_name.c_str());
|
||||
}
|
||||
|
||||
CDMRSlot::init(colorCode, embeddedLCOnly, dumpTAData, callHang, modem, network, display, duplex, m_lookup, rssi, jitter, ovcm);
|
||||
CDMRSlot::init(colorCode, embeddedLCOnly, dumpTAData, callHang, modem, network, display, duplex, m_lookup, rssi, jitter);
|
||||
}
|
||||
|
||||
CDMRControl::~CDMRControl()
|
||||
|
@ -70,17 +63,15 @@ bool CDMRControl::processWakeup(const unsigned char* data)
|
|||
return false;
|
||||
|
||||
unsigned int srcId = csbk.getSrcId();
|
||||
std::string srcId_name = std::to_string(srcId);
|
||||
LogMessage("Incoming uplink from radio id: %s", srcId_name.c_str());
|
||||
std::string src = m_lookup->find(srcId);
|
||||
|
||||
bool ret = CDMRAccessControl::validateSrcId(srcId);
|
||||
if (!ret) {
|
||||
LogMessage("Blocked downlink activation from %s (%s)", src.c_str(), srcId_name.c_str());
|
||||
LogMessage("Invalid Downlink Activate received from %s", src.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
LogMessage("Downlink request received from %s (%s)", src.c_str(), srcId_name.c_str());
|
||||
LogMessage("Downlink Activate received from %s", src.c_str());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2015-2021 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2015-2019 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
@ -31,7 +31,7 @@
|
|||
|
||||
class CDMRControl {
|
||||
public:
|
||||
CDMRControl(unsigned int id, unsigned int colorCode, unsigned int callHang, bool selfOnly, bool embeddedLCOnly, bool dumpTAData, const std::vector<unsigned int>& prefixes, const std::vector<unsigned int>& blacklist, const std::vector<unsigned int>& whitelist, const std::vector<unsigned int>& slot1TGWhitelist, const std::vector<unsigned int>& slot2TGWhitelist, unsigned int timeout, CModem* modem, IDMRNetwork* network, CDisplay* display, bool duplex, CDMRLookup* lookup, CRSSIInterpolator* rssi, unsigned int jitter, DMR_OVCM_TYPES ovcm);
|
||||
CDMRControl(unsigned int id, unsigned int colorCode, unsigned int callHang, bool selfOnly, bool embeddedLCOnly, bool dumpTAData, const std::vector<unsigned int>& prefixes, const std::vector<unsigned int>& blacklist, const std::vector<unsigned int>& whitelist, const std::vector<unsigned int>& slot1TGWhitelist, const std::vector<unsigned int>& slot2TGWhitelist, unsigned int timeout, CModem* modem, CDMRNetwork* network, CDisplay* display, bool duplex, CDMRLookup* lookup, CRSSIInterpolator* rssi, unsigned int jitter);
|
||||
~CDMRControl();
|
||||
|
||||
bool processWakeup(const unsigned char* data);
|
||||
|
@ -51,7 +51,7 @@ public:
|
|||
private:
|
||||
unsigned int m_colorCode;
|
||||
CModem* m_modem;
|
||||
IDMRNetwork* m_network;
|
||||
CDMRNetwork* m_network;
|
||||
CDMRSlot m_slot1;
|
||||
CDMRSlot m_slot2;
|
||||
CDMRLookup* m_lookup;
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2015,2016,2021 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2015,2016 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
|
|
@ -1,644 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2015,2016,2017,2018,2020,2021 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include "DMRDirectNetwork.h"
|
||||
|
||||
#include "SHA256.h"
|
||||
#include "Utils.h"
|
||||
#include "Log.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <cassert>
|
||||
|
||||
const unsigned int BUFFER_LENGTH = 500U;
|
||||
|
||||
const unsigned int HOMEBREW_DATA_PACKET_LENGTH = 55U;
|
||||
|
||||
|
||||
CDMRDirectNetwork::CDMRDirectNetwork(const std::string& address, unsigned short port, const std::string& localAddress, unsigned short localPort, unsigned int id, const std::string& password, bool duplex, const char* version, bool slot1, bool slot2, HW_TYPE hwType, bool debug) :
|
||||
m_address(address),
|
||||
m_port(port),
|
||||
m_addr(),
|
||||
m_addrLen(0U),
|
||||
m_id(NULL),
|
||||
m_password(password),
|
||||
m_duplex(duplex),
|
||||
m_version(version),
|
||||
m_debug(debug),
|
||||
m_socket(localAddress, localPort),
|
||||
m_enabled(false),
|
||||
m_slot1(slot1),
|
||||
m_slot2(slot2),
|
||||
m_hwType(hwType),
|
||||
m_status(WAITING_CONNECT),
|
||||
m_retryTimer(1000U, 10U),
|
||||
m_timeoutTimer(1000U, 60U),
|
||||
m_buffer(NULL),
|
||||
m_streamId(NULL),
|
||||
m_salt(NULL),
|
||||
m_rxData(1000U, "DMR Network"),
|
||||
m_options(),
|
||||
m_random(),
|
||||
m_callsign(),
|
||||
m_rxFrequency(0U),
|
||||
m_txFrequency(0U),
|
||||
m_power(0U),
|
||||
m_colorCode(0U),
|
||||
m_latitude(0.0F),
|
||||
m_longitude(0.0F),
|
||||
m_height(0),
|
||||
m_location(),
|
||||
m_description(),
|
||||
m_url(),
|
||||
m_beacon(false)
|
||||
{
|
||||
assert(!address.empty());
|
||||
assert(port > 0U);
|
||||
assert(id > 1000U);
|
||||
assert(!password.empty());
|
||||
|
||||
m_buffer = new unsigned char[BUFFER_LENGTH];
|
||||
m_salt = new unsigned char[sizeof(uint32_t)];
|
||||
m_id = new uint8_t[4U];
|
||||
m_streamId = new uint32_t[2U];
|
||||
|
||||
m_id[0U] = id >> 24;
|
||||
m_id[1U] = id >> 16;
|
||||
m_id[2U] = id >> 8;
|
||||
m_id[3U] = id >> 0;
|
||||
|
||||
std::random_device rd;
|
||||
std::mt19937 mt(rd());
|
||||
m_random = mt;
|
||||
|
||||
std::uniform_int_distribution<uint32_t> dist(0x00000001, 0xfffffffe);
|
||||
m_streamId[0U] = dist(m_random);
|
||||
m_streamId[1U] = dist(m_random);
|
||||
}
|
||||
|
||||
CDMRDirectNetwork::~CDMRDirectNetwork()
|
||||
{
|
||||
delete[] m_streamId;
|
||||
delete[] m_buffer;
|
||||
delete[] m_salt;
|
||||
delete[] m_id;
|
||||
}
|
||||
|
||||
void CDMRDirectNetwork::setOptions(const std::string& options)
|
||||
{
|
||||
m_options = options;
|
||||
}
|
||||
|
||||
void CDMRDirectNetwork::setConfig(const std::string& callsign, unsigned int rxFrequency, unsigned int txFrequency, unsigned int power, unsigned int colorCode, float latitude, float longitude, int height, const std::string& location, const std::string& description, const std::string& url)
|
||||
{
|
||||
m_callsign = callsign;
|
||||
m_rxFrequency = rxFrequency;
|
||||
m_txFrequency = txFrequency;
|
||||
m_power = power;
|
||||
m_colorCode = colorCode;
|
||||
m_latitude = latitude;
|
||||
m_longitude = longitude;
|
||||
m_height = height;
|
||||
m_location = location;
|
||||
m_description = description;
|
||||
m_url = url;
|
||||
}
|
||||
|
||||
bool CDMRDirectNetwork::open()
|
||||
{
|
||||
if (CUDPSocket::lookup(m_address, m_port, m_addr, m_addrLen) != 0) {
|
||||
LogError("DMR, Could not lookup the address of the DMR Network");
|
||||
return false;
|
||||
}
|
||||
|
||||
LogMessage("Opening DMR Network");
|
||||
|
||||
m_status = WAITING_CONNECT;
|
||||
m_timeoutTimer.stop();
|
||||
m_retryTimer.start();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CDMRDirectNetwork::enable(bool enabled)
|
||||
{
|
||||
if (!enabled && m_enabled)
|
||||
m_rxData.clear();
|
||||
|
||||
m_enabled = enabled;
|
||||
}
|
||||
|
||||
bool CDMRDirectNetwork::read(CDMRData& data)
|
||||
{
|
||||
if (m_status != RUNNING)
|
||||
return false;
|
||||
|
||||
if (m_rxData.isEmpty())
|
||||
return false;
|
||||
|
||||
unsigned char length = 0U;
|
||||
m_rxData.getData(&length, 1U);
|
||||
m_rxData.getData(m_buffer, length);
|
||||
|
||||
// Is this a data packet?
|
||||
if (::memcmp(m_buffer, "DMRD", 4U) != 0)
|
||||
return false;
|
||||
|
||||
unsigned char seqNo = m_buffer[4U];
|
||||
|
||||
unsigned int srcId = (m_buffer[5U] << 16) | (m_buffer[6U] << 8) | (m_buffer[7U] << 0);
|
||||
|
||||
unsigned int dstId = (m_buffer[8U] << 16) | (m_buffer[9U] << 8) | (m_buffer[10U] << 0);
|
||||
|
||||
unsigned int slotNo = (m_buffer[15U] & 0x80U) == 0x80U ? 2U : 1U;
|
||||
|
||||
// DMO mode slot disabling
|
||||
if (slotNo == 1U && !m_duplex)
|
||||
return false;
|
||||
|
||||
// Individual slot disabling
|
||||
if (slotNo == 1U && !m_slot1)
|
||||
return false;
|
||||
if (slotNo == 2U && !m_slot2)
|
||||
return false;
|
||||
|
||||
FLCO flco = (m_buffer[15U] & 0x40U) == 0x40U ? FLCO_USER_USER : FLCO_GROUP;
|
||||
|
||||
data.setSeqNo(seqNo);
|
||||
data.setSlotNo(slotNo);
|
||||
data.setSrcId(srcId);
|
||||
data.setDstId(dstId);
|
||||
data.setFLCO(flco);
|
||||
|
||||
bool dataSync = (m_buffer[15U] & 0x20U) == 0x20U;
|
||||
bool voiceSync = (m_buffer[15U] & 0x10U) == 0x10U;
|
||||
|
||||
if (dataSync) {
|
||||
unsigned char dataType = m_buffer[15U] & 0x0FU;
|
||||
data.setData(m_buffer + 20U);
|
||||
data.setDataType(dataType);
|
||||
data.setN(0U);
|
||||
} else if (voiceSync) {
|
||||
data.setData(m_buffer + 20U);
|
||||
data.setDataType(DT_VOICE_SYNC);
|
||||
data.setN(0U);
|
||||
} else {
|
||||
unsigned char n = m_buffer[15U] & 0x0FU;
|
||||
data.setData(m_buffer + 20U);
|
||||
data.setDataType(DT_VOICE);
|
||||
data.setN(n);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CDMRDirectNetwork::write(const CDMRData& data)
|
||||
{
|
||||
if (m_status != RUNNING)
|
||||
return false;
|
||||
|
||||
unsigned char buffer[HOMEBREW_DATA_PACKET_LENGTH];
|
||||
::memset(buffer, 0x00U, HOMEBREW_DATA_PACKET_LENGTH);
|
||||
|
||||
buffer[0U] = 'D';
|
||||
buffer[1U] = 'M';
|
||||
buffer[2U] = 'R';
|
||||
buffer[3U] = 'D';
|
||||
|
||||
unsigned int srcId = data.getSrcId();
|
||||
buffer[5U] = srcId >> 16;
|
||||
buffer[6U] = srcId >> 8;
|
||||
buffer[7U] = srcId >> 0;
|
||||
|
||||
unsigned int dstId = data.getDstId();
|
||||
buffer[8U] = dstId >> 16;
|
||||
buffer[9U] = dstId >> 8;
|
||||
buffer[10U] = dstId >> 0;
|
||||
|
||||
::memcpy(buffer + 11U, m_id, 4U);
|
||||
|
||||
unsigned int slotNo = data.getSlotNo();
|
||||
|
||||
// Individual slot disabling
|
||||
if (slotNo == 1U && !m_slot1)
|
||||
return false;
|
||||
if (slotNo == 2U && !m_slot2)
|
||||
return false;
|
||||
|
||||
buffer[15U] = slotNo == 1U ? 0x00U : 0x80U;
|
||||
|
||||
FLCO flco = data.getFLCO();
|
||||
buffer[15U] |= flco == FLCO_GROUP ? 0x00U : 0x40U;
|
||||
|
||||
unsigned int slotIndex = slotNo - 1U;
|
||||
|
||||
std::uniform_int_distribution<uint32_t> dist(0x00000001, 0xfffffffe);
|
||||
unsigned char dataType = data.getDataType();
|
||||
if (dataType == DT_VOICE_SYNC) {
|
||||
buffer[15U] |= 0x10U;
|
||||
} else if (dataType == DT_VOICE) {
|
||||
buffer[15U] |= data.getN();
|
||||
} else {
|
||||
if (dataType == DT_VOICE_LC_HEADER)
|
||||
m_streamId[slotIndex] = dist(m_random);
|
||||
|
||||
if (dataType == DT_CSBK || dataType == DT_DATA_HEADER)
|
||||
m_streamId[slotIndex] = dist(m_random);
|
||||
|
||||
buffer[15U] |= (0x20U | dataType);
|
||||
}
|
||||
|
||||
buffer[4U] = data.getSeqNo();
|
||||
|
||||
::memcpy(buffer + 16U, m_streamId + slotIndex, 4U);
|
||||
|
||||
data.getData(buffer + 20U);
|
||||
|
||||
buffer[53U] = data.getBER();
|
||||
|
||||
buffer[54U] = data.getRSSI();
|
||||
|
||||
write(buffer, HOMEBREW_DATA_PACKET_LENGTH);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CDMRDirectNetwork::writeRadioPosition(unsigned int id, const unsigned char* data)
|
||||
{
|
||||
if (m_status != RUNNING)
|
||||
return false;
|
||||
|
||||
unsigned char buffer[20U];
|
||||
|
||||
::memcpy(buffer + 0U, "DMRG", 4U);
|
||||
|
||||
buffer[4U] = id >> 16;
|
||||
buffer[5U] = id >> 8;
|
||||
buffer[6U] = id >> 0;
|
||||
|
||||
::memcpy(buffer + 7U, data + 2U, 7U);
|
||||
|
||||
return write(buffer, 14U);
|
||||
}
|
||||
|
||||
bool CDMRDirectNetwork::writeTalkerAlias(unsigned int id, unsigned char type, const unsigned char* data)
|
||||
{
|
||||
if (m_status != RUNNING)
|
||||
return false;
|
||||
|
||||
unsigned char buffer[20U];
|
||||
|
||||
::memcpy(buffer + 0U, "DMRA", 4U);
|
||||
|
||||
buffer[4U] = id >> 16;
|
||||
buffer[5U] = id >> 8;
|
||||
buffer[6U] = id >> 0;
|
||||
|
||||
buffer[7U] = type;
|
||||
|
||||
::memcpy(buffer + 8U, data + 2U, 7U);
|
||||
|
||||
return write(buffer, 15U);
|
||||
}
|
||||
|
||||
bool CDMRDirectNetwork::isConnected() const
|
||||
{
|
||||
return (m_status == RUNNING);
|
||||
}
|
||||
|
||||
void CDMRDirectNetwork::close(bool sayGoodbye)
|
||||
{
|
||||
LogMessage("Closing DMR Network");
|
||||
|
||||
if (sayGoodbye && (m_status == RUNNING)) {
|
||||
unsigned char buffer[9U];
|
||||
::memcpy(buffer + 0U, "RPTCL", 5U);
|
||||
::memcpy(buffer + 5U, m_id, 4U);
|
||||
write(buffer, 9U);
|
||||
}
|
||||
|
||||
m_socket.close();
|
||||
|
||||
m_retryTimer.stop();
|
||||
m_timeoutTimer.stop();
|
||||
}
|
||||
|
||||
void CDMRDirectNetwork::clock(unsigned int ms)
|
||||
{
|
||||
m_retryTimer.clock(ms);
|
||||
if (m_retryTimer.isRunning() && m_retryTimer.hasExpired()) {
|
||||
switch (m_status) {
|
||||
case WAITING_CONNECT:
|
||||
if (m_socket.open(m_addr.ss_family)) {
|
||||
if (writeLogin()) {
|
||||
m_status = WAITING_LOGIN;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case WAITING_LOGIN:
|
||||
writeLogin();
|
||||
break;
|
||||
case WAITING_AUTHORISATION:
|
||||
writeAuthorisation();
|
||||
break;
|
||||
case WAITING_OPTIONS:
|
||||
writeOptions();
|
||||
break;
|
||||
case WAITING_CONFIG:
|
||||
writeConfig();
|
||||
break;
|
||||
case RUNNING:
|
||||
writePing();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
m_retryTimer.start();
|
||||
}
|
||||
|
||||
sockaddr_storage address;
|
||||
unsigned int addrlen;
|
||||
int length = m_socket.read(m_buffer, BUFFER_LENGTH, address, addrlen);
|
||||
if (length < 0) {
|
||||
LogError("DMR, Socket has failed, retrying connection to the master");
|
||||
close(false);
|
||||
open();
|
||||
return;
|
||||
}
|
||||
|
||||
if (length > 0) {
|
||||
if (!CUDPSocket::match(m_addr, address)) {
|
||||
LogMessage("DMR, packet received from an invalid source");
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_debug)
|
||||
CUtils::dump(1U, "DMR, Network Received", m_buffer, length);
|
||||
|
||||
if (::memcmp(m_buffer, "DMRD", 4U) == 0) {
|
||||
if (m_enabled) {
|
||||
unsigned char len = length;
|
||||
m_rxData.addData(&len, 1U);
|
||||
m_rxData.addData(m_buffer, len);
|
||||
}
|
||||
} else if (::memcmp(m_buffer, "MSTNAK", 6U) == 0) {
|
||||
if (m_status == RUNNING) {
|
||||
LogWarning("DMR, Login to the master has failed, retrying login ...");
|
||||
m_status = WAITING_LOGIN;
|
||||
m_timeoutTimer.start();
|
||||
m_retryTimer.start();
|
||||
} else {
|
||||
/* Once the modem death spiral has been prevented in Modem.cpp
|
||||
the Network sometimes times out and reaches here.
|
||||
We want it to reconnect so... */
|
||||
LogError("DMR, Login to the master has failed, retrying network ...");
|
||||
close(false);
|
||||
open();
|
||||
return;
|
||||
}
|
||||
} else if (::memcmp(m_buffer, "RPTACK", 6U) == 0) {
|
||||
switch (m_status) {
|
||||
case WAITING_LOGIN:
|
||||
LogDebug("DMR, Sending authorisation");
|
||||
::memcpy(m_salt, m_buffer + 6U, sizeof(uint32_t));
|
||||
writeAuthorisation();
|
||||
m_status = WAITING_AUTHORISATION;
|
||||
m_timeoutTimer.start();
|
||||
m_retryTimer.start();
|
||||
break;
|
||||
case WAITING_AUTHORISATION:
|
||||
LogDebug("DMR, Sending configuration");
|
||||
writeConfig();
|
||||
m_status = WAITING_CONFIG;
|
||||
m_timeoutTimer.start();
|
||||
m_retryTimer.start();
|
||||
break;
|
||||
case WAITING_CONFIG:
|
||||
if (m_options.empty()) {
|
||||
LogMessage("DMR, Logged into the master successfully");
|
||||
m_status = RUNNING;
|
||||
} else {
|
||||
LogDebug("DMR, Sending options");
|
||||
writeOptions();
|
||||
m_status = WAITING_OPTIONS;
|
||||
}
|
||||
m_timeoutTimer.start();
|
||||
m_retryTimer.start();
|
||||
break;
|
||||
case WAITING_OPTIONS:
|
||||
LogMessage("DMR, Logged into the master successfully");
|
||||
m_status = RUNNING;
|
||||
m_timeoutTimer.start();
|
||||
m_retryTimer.start();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else if (::memcmp(m_buffer, "MSTCL", 5U) == 0) {
|
||||
LogError("DMR, Master is closing down");
|
||||
close(false);
|
||||
open();
|
||||
} else if (::memcmp(m_buffer, "MSTPONG", 7U) == 0) {
|
||||
m_timeoutTimer.start();
|
||||
} else if (::memcmp(m_buffer, "RPTSBKN", 7U) == 0) {
|
||||
m_beacon = true;
|
||||
} else {
|
||||
CUtils::dump("DMR, Unknown packet from the master", m_buffer, length);
|
||||
}
|
||||
}
|
||||
|
||||
m_timeoutTimer.clock(ms);
|
||||
if (m_timeoutTimer.isRunning() && m_timeoutTimer.hasExpired()) {
|
||||
LogError("DMR, Connection to the master has timed out, retrying connection");
|
||||
close(false);
|
||||
open();
|
||||
}
|
||||
}
|
||||
|
||||
bool CDMRDirectNetwork::writeLogin()
|
||||
{
|
||||
unsigned char buffer[8U];
|
||||
|
||||
::memcpy(buffer + 0U, "RPTL", 4U);
|
||||
::memcpy(buffer + 4U, m_id, 4U);
|
||||
|
||||
return write(buffer, 8U);
|
||||
}
|
||||
|
||||
bool CDMRDirectNetwork::writeAuthorisation()
|
||||
{
|
||||
size_t size = m_password.size();
|
||||
|
||||
unsigned char* in = new unsigned char[size + sizeof(uint32_t)];
|
||||
::memcpy(in, m_salt, sizeof(uint32_t));
|
||||
for (size_t i = 0U; i < size; i++)
|
||||
in[i + sizeof(uint32_t)] = m_password.at(i);
|
||||
|
||||
unsigned char out[40U];
|
||||
::memcpy(out + 0U, "RPTK", 4U);
|
||||
::memcpy(out + 4U, m_id, 4U);
|
||||
|
||||
CSHA256 sha256;
|
||||
sha256.buffer(in, (unsigned int)(size + sizeof(uint32_t)), out + 8U);
|
||||
|
||||
delete[] in;
|
||||
|
||||
return write(out, 40U);
|
||||
}
|
||||
|
||||
bool CDMRDirectNetwork::writeOptions()
|
||||
{
|
||||
char buffer[300U];
|
||||
|
||||
::memcpy(buffer + 0U, "RPTO", 4U);
|
||||
::memcpy(buffer + 4U, m_id, 4U);
|
||||
::strcpy(buffer + 8U, m_options.c_str());
|
||||
|
||||
return write((unsigned char*)buffer, (unsigned int)m_options.length() + 8U);
|
||||
}
|
||||
|
||||
bool CDMRDirectNetwork::writeConfig()
|
||||
{
|
||||
const char* software;
|
||||
char slots = '0';
|
||||
if (m_duplex) {
|
||||
if (m_slot1 && m_slot2)
|
||||
slots = '3';
|
||||
else if (m_slot1 && !m_slot2)
|
||||
slots = '1';
|
||||
else if (!m_slot1 && m_slot2)
|
||||
slots = '2';
|
||||
|
||||
switch (m_hwType) {
|
||||
case HWT_MMDVM:
|
||||
software = "MMDVM";
|
||||
break;
|
||||
case HWT_MMDVM_HS:
|
||||
software = "MMDVM_MMDVM_HS";
|
||||
break;
|
||||
case HWT_MMDVM_HS_DUAL_HAT:
|
||||
software = "MMDVM_MMDVM_HS_Dual_Hat";
|
||||
break;
|
||||
case HWT_NANO_HOTSPOT:
|
||||
software = "MMDVM_Nano_hotSPOT";
|
||||
break;
|
||||
default:
|
||||
software = "MMDVM_Unknown";
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
slots = '4';
|
||||
|
||||
switch (m_hwType) {
|
||||
case HWT_MMDVM:
|
||||
software = "MMDVM_DMO";
|
||||
break;
|
||||
case HWT_DVMEGA:
|
||||
software = "MMDVM_DVMega";
|
||||
break;
|
||||
case HWT_MMDVM_ZUMSPOT:
|
||||
software = "MMDVM_ZUMspot";
|
||||
break;
|
||||
case HWT_MMDVM_HS_HAT:
|
||||
software = "MMDVM_MMDVM_HS_Hat";
|
||||
break;
|
||||
case HWT_MMDVM_HS_DUAL_HAT:
|
||||
software = "MMDVM_MMDVM_HS_Dual_Hat";
|
||||
break;
|
||||
case HWT_NANO_HOTSPOT:
|
||||
software = "MMDVM_Nano_hotSPOT";
|
||||
break;
|
||||
case HWT_NANO_DV:
|
||||
software = "MMDVM_Nano_DV";
|
||||
break;
|
||||
case HWT_D2RG_MMDVM_HS:
|
||||
software = "MMDVM_D2RG_MMDVM_HS";
|
||||
break;
|
||||
case HWT_MMDVM_HS:
|
||||
software = "MMDVM_MMDVM_HS";
|
||||
break;
|
||||
default:
|
||||
software = "MMDVM_Unknown";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
char buffer[400U];
|
||||
|
||||
::memcpy(buffer + 0U, "RPTC", 4U);
|
||||
::memcpy(buffer + 4U, m_id, 4U);
|
||||
|
||||
char latitude[20U];
|
||||
::sprintf(latitude, "%08f", m_latitude);
|
||||
|
||||
char longitude[20U];
|
||||
::sprintf(longitude, "%09f", m_longitude);
|
||||
|
||||
unsigned int power = m_power;
|
||||
if (power > 99U)
|
||||
power = 99U;
|
||||
|
||||
int height = m_height;
|
||||
if (height > 999)
|
||||
height = 999;
|
||||
|
||||
::sprintf(buffer + 8U, "%-8.8s%09u%09u%02u%02u%8.8s%9.9s%03d%-20.20s%-19.19s%c%-124.124s%-40.40s%-40.40s", m_callsign.c_str(),
|
||||
m_rxFrequency, m_txFrequency, power, m_colorCode, latitude, longitude, height, m_location.c_str(),
|
||||
m_description.c_str(), slots, m_url.c_str(), m_version, software);
|
||||
|
||||
return write((unsigned char*)buffer, 302U);
|
||||
}
|
||||
|
||||
bool CDMRDirectNetwork::writePing()
|
||||
{
|
||||
unsigned char buffer[11U];
|
||||
|
||||
::memcpy(buffer + 0U, "RPTPING", 7U);
|
||||
::memcpy(buffer + 7U, m_id, 4U);
|
||||
|
||||
return write(buffer, 11U);
|
||||
}
|
||||
|
||||
bool CDMRDirectNetwork::wantsBeacon()
|
||||
{
|
||||
bool beacon = m_beacon;
|
||||
|
||||
m_beacon = false;
|
||||
|
||||
return beacon;
|
||||
}
|
||||
|
||||
bool CDMRDirectNetwork::write(const unsigned char* data, unsigned int length)
|
||||
{
|
||||
assert(data != NULL);
|
||||
assert(length > 0U);
|
||||
|
||||
if (m_debug)
|
||||
CUtils::dump(1U, "DMR Network Transmitted", data, length);
|
||||
|
||||
bool ret = m_socket.write(data, length, m_addr, m_addrLen);
|
||||
if (!ret) {
|
||||
LogError("DMR, Socket has failed when writing data to the master, retrying connection");
|
||||
close(false);
|
||||
open();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
|
@ -1,121 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2015,2016,2017,2018,2020,2021 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#if !defined(DMRDirectNetwork_H)
|
||||
#define DMRDirectNetwork_H
|
||||
|
||||
#include "DMRNetwork.h"
|
||||
#include "UDPSocket.h"
|
||||
#include "Timer.h"
|
||||
#include "RingBuffer.h"
|
||||
#include "DMRData.h"
|
||||
|
||||
#include <string>
|
||||
#include <cstdint>
|
||||
#include <random>
|
||||
|
||||
class CDMRDirectNetwork : public IDMRNetwork
|
||||
{
|
||||
public:
|
||||
CDMRDirectNetwork(const std::string& remoteAddress, unsigned short remotePort, const std::string& localAddress, unsigned short localPort, unsigned int id, const std::string& password, bool duplex, const char* version, bool slot1, bool slot2, HW_TYPE hwType, bool debug);
|
||||
virtual ~CDMRDirectNetwork();
|
||||
|
||||
virtual void setOptions(const std::string& options);
|
||||
|
||||
virtual void setConfig(const std::string& callsign, unsigned int rxFrequency, unsigned int txFrequency, unsigned int power, unsigned int colorCode, float latitude, float longitude, int height, const std::string& location, const std::string& description, const std::string& url);
|
||||
|
||||
virtual bool open();
|
||||
|
||||
virtual void enable(bool enabled);
|
||||
|
||||
virtual bool read(CDMRData& data);
|
||||
|
||||
virtual bool write(const CDMRData& data);
|
||||
|
||||
virtual bool writeRadioPosition(unsigned int id, const unsigned char* data);
|
||||
|
||||
virtual bool writeTalkerAlias(unsigned int id, unsigned char type, const unsigned char* data);
|
||||
|
||||
virtual bool wantsBeacon();
|
||||
|
||||
virtual void clock(unsigned int ms);
|
||||
|
||||
virtual bool isConnected() const;
|
||||
|
||||
virtual void close(bool sayGoodbye);
|
||||
|
||||
private:
|
||||
std::string m_address;
|
||||
unsigned short m_port;
|
||||
sockaddr_storage m_addr;
|
||||
unsigned int m_addrLen;
|
||||
uint8_t* m_id;
|
||||
std::string m_password;
|
||||
bool m_duplex;
|
||||
const char* m_version;
|
||||
bool m_debug;
|
||||
CUDPSocket m_socket;
|
||||
bool m_enabled;
|
||||
bool m_slot1;
|
||||
bool m_slot2;
|
||||
HW_TYPE m_hwType;
|
||||
|
||||
enum STATUS {
|
||||
WAITING_CONNECT,
|
||||
WAITING_LOGIN,
|
||||
WAITING_AUTHORISATION,
|
||||
WAITING_CONFIG,
|
||||
WAITING_OPTIONS,
|
||||
RUNNING
|
||||
};
|
||||
|
||||
STATUS m_status;
|
||||
CTimer m_retryTimer;
|
||||
CTimer m_timeoutTimer;
|
||||
unsigned char* m_buffer;
|
||||
uint32_t* m_streamId;
|
||||
unsigned char* m_salt;
|
||||
|
||||
CRingBuffer<unsigned char> m_rxData;
|
||||
|
||||
std::string m_options;
|
||||
|
||||
std::mt19937 m_random;
|
||||
std::string m_callsign;
|
||||
unsigned int m_rxFrequency;
|
||||
unsigned int m_txFrequency;
|
||||
unsigned int m_power;
|
||||
unsigned int m_colorCode;
|
||||
float m_latitude;
|
||||
float m_longitude;
|
||||
int m_height;
|
||||
std::string m_location;
|
||||
std::string m_description;
|
||||
std::string m_url;
|
||||
bool m_beacon;
|
||||
|
||||
bool writeLogin();
|
||||
bool writeAuthorisation();
|
||||
bool writeOptions();
|
||||
bool writeConfig();
|
||||
bool writePing();
|
||||
|
||||
bool write(const unsigned char* data, unsigned int length);
|
||||
};
|
||||
|
||||
#endif
|
|
@ -44,11 +44,11 @@ void CDMREMB::putData(const unsigned char* data)
|
|||
DMREMB[1U] = (data[18U] << 4) & 0xF0U;
|
||||
DMREMB[1U] |= (data[19U] >> 4) & 0x0FU;
|
||||
|
||||
unsigned char code = CQR1676::decode(DMREMB);
|
||||
CQR1676::decode(DMREMB);
|
||||
|
||||
m_colorCode = (code >> 4) & 0x0FU;
|
||||
m_PI = (code & 0x08U) == 0x08U;
|
||||
m_LCSS = (code >> 1) & 0x03U;
|
||||
m_colorCode = (DMREMB[0U] >> 4) & 0x0FU;
|
||||
m_PI = (DMREMB[0U] & 0x08U) == 0x08U;
|
||||
m_LCSS = (DMREMB[0U] >> 1) & 0x03U;
|
||||
}
|
||||
|
||||
void CDMREMB::getData(unsigned char* data) const
|
||||
|
|
|
@ -1,450 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2015-2021 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include "DMRGatewayNetwork.h"
|
||||
|
||||
#include "Utils.h"
|
||||
#include "Log.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
#include <cstdlib>
|
||||
|
||||
const unsigned int BUFFER_LENGTH = 500U;
|
||||
|
||||
const unsigned int HOMEBREW_DATA_PACKET_LENGTH = 55U;
|
||||
|
||||
|
||||
CDMRGatewayNetwork::CDMRGatewayNetwork(const std::string& address, unsigned short port, const std::string& localAddress, unsigned short localPort, unsigned int id, bool duplex, const char* version, bool slot1, bool slot2, HW_TYPE hwType, bool debug) :
|
||||
m_addressStr(address),
|
||||
m_addr(),
|
||||
m_addrLen(0U),
|
||||
m_port(port),
|
||||
m_id(NULL),
|
||||
m_duplex(duplex),
|
||||
m_version(version),
|
||||
m_debug(debug),
|
||||
m_socket(localAddress, localPort),
|
||||
m_enabled(false),
|
||||
m_slot1(slot1),
|
||||
m_slot2(slot2),
|
||||
m_hwType(hwType),
|
||||
m_buffer(NULL),
|
||||
m_streamId(NULL),
|
||||
m_rxData(1000U, "DMR Network"),
|
||||
m_beacon(false),
|
||||
m_random(),
|
||||
m_callsign(),
|
||||
m_rxFrequency(0U),
|
||||
m_txFrequency(0U),
|
||||
m_power(0U),
|
||||
m_colorCode(0U),
|
||||
m_pingTimer(1000U, 10U)
|
||||
{
|
||||
assert(!address.empty());
|
||||
assert(port > 0U);
|
||||
assert(id > 1000U);
|
||||
|
||||
if (CUDPSocket::lookup(m_addressStr, m_port, m_addr, m_addrLen) != 0)
|
||||
m_addrLen = 0U;
|
||||
|
||||
m_buffer = new unsigned char[BUFFER_LENGTH];
|
||||
m_id = new uint8_t[4U];
|
||||
m_streamId = new uint32_t[2U];
|
||||
|
||||
m_id[0U] = id >> 24;
|
||||
m_id[1U] = id >> 16;
|
||||
m_id[2U] = id >> 8;
|
||||
m_id[3U] = id >> 0;
|
||||
|
||||
std::random_device rd;
|
||||
std::mt19937 mt(rd());
|
||||
m_random = mt;
|
||||
|
||||
std::uniform_int_distribution<uint32_t> dist(0x00000001, 0xfffffffe);
|
||||
m_streamId[0U] = dist(m_random);
|
||||
m_streamId[1U] = dist(m_random);
|
||||
}
|
||||
|
||||
CDMRGatewayNetwork::~CDMRGatewayNetwork()
|
||||
{
|
||||
delete[] m_buffer;
|
||||
delete[] m_streamId;
|
||||
delete[] m_id;
|
||||
}
|
||||
|
||||
void CDMRGatewayNetwork::setConfig(const std::string & callsign, unsigned int rxFrequency, unsigned int txFrequency, unsigned int power, unsigned int colorCode, float latitude, float longitude, int height, const std::string& location, const std::string& description, const std::string& url)
|
||||
{
|
||||
m_callsign = callsign;
|
||||
m_rxFrequency = rxFrequency;
|
||||
m_txFrequency = txFrequency;
|
||||
m_power = power;
|
||||
m_colorCode = colorCode;
|
||||
}
|
||||
|
||||
void CDMRGatewayNetwork::setOptions(const std::string& options)
|
||||
{
|
||||
}
|
||||
|
||||
bool CDMRGatewayNetwork::open()
|
||||
{
|
||||
if (m_addrLen == 0U) {
|
||||
LogError("Unable to resolve the address of the DMR Network");
|
||||
return false;
|
||||
}
|
||||
|
||||
LogMessage("DMR, Opening DMR Network");
|
||||
|
||||
bool ret = m_socket.open(m_addr);
|
||||
if (ret)
|
||||
m_pingTimer.start();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void CDMRGatewayNetwork::enable(bool enabled)
|
||||
{
|
||||
if (!enabled && m_enabled)
|
||||
m_rxData.clear();
|
||||
|
||||
m_enabled = enabled;
|
||||
}
|
||||
|
||||
bool CDMRGatewayNetwork::read(CDMRData& data)
|
||||
{
|
||||
if (m_rxData.isEmpty())
|
||||
return false;
|
||||
|
||||
unsigned char length = 0U;
|
||||
m_rxData.getData(&length, 1U);
|
||||
m_rxData.getData(m_buffer, length);
|
||||
|
||||
// Is this a data packet?
|
||||
if (::memcmp(m_buffer, "DMRD", 4U) != 0)
|
||||
return false;
|
||||
|
||||
unsigned char seqNo = m_buffer[4U];
|
||||
|
||||
unsigned int srcId = (m_buffer[5U] << 16) | (m_buffer[6U] << 8) | (m_buffer[7U] << 0);
|
||||
|
||||
unsigned int dstId = (m_buffer[8U] << 16) | (m_buffer[9U] << 8) | (m_buffer[10U] << 0);
|
||||
|
||||
unsigned int slotNo = (m_buffer[15U] & 0x80U) == 0x80U ? 2U : 1U;
|
||||
|
||||
// DMO mode slot disabling
|
||||
if (slotNo == 1U && !m_duplex)
|
||||
return false;
|
||||
|
||||
// Individual slot disabling
|
||||
if (slotNo == 1U && !m_slot1)
|
||||
return false;
|
||||
if (slotNo == 2U && !m_slot2)
|
||||
return false;
|
||||
|
||||
FLCO flco = (m_buffer[15U] & 0x40U) == 0x40U ? FLCO_USER_USER : FLCO_GROUP;
|
||||
|
||||
data.setSeqNo(seqNo);
|
||||
data.setSlotNo(slotNo);
|
||||
data.setSrcId(srcId);
|
||||
data.setDstId(dstId);
|
||||
data.setFLCO(flco);
|
||||
|
||||
bool dataSync = (m_buffer[15U] & 0x20U) == 0x20U;
|
||||
bool voiceSync = (m_buffer[15U] & 0x10U) == 0x10U;
|
||||
|
||||
if (dataSync) {
|
||||
unsigned char dataType = m_buffer[15U] & 0x0FU;
|
||||
data.setData(m_buffer + 20U);
|
||||
data.setDataType(dataType);
|
||||
data.setN(0U);
|
||||
} else if (voiceSync) {
|
||||
data.setData(m_buffer + 20U);
|
||||
data.setDataType(DT_VOICE_SYNC);
|
||||
data.setN(0U);
|
||||
} else {
|
||||
unsigned char n = m_buffer[15U] & 0x0FU;
|
||||
data.setData(m_buffer + 20U);
|
||||
data.setDataType(DT_VOICE);
|
||||
data.setN(n);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CDMRGatewayNetwork::write(const CDMRData& data)
|
||||
{
|
||||
unsigned char buffer[HOMEBREW_DATA_PACKET_LENGTH];
|
||||
::memset(buffer, 0x00U, HOMEBREW_DATA_PACKET_LENGTH);
|
||||
|
||||
buffer[0U] = 'D';
|
||||
buffer[1U] = 'M';
|
||||
buffer[2U] = 'R';
|
||||
buffer[3U] = 'D';
|
||||
|
||||
unsigned int srcId = data.getSrcId();
|
||||
buffer[5U] = srcId >> 16;
|
||||
buffer[6U] = srcId >> 8;
|
||||
buffer[7U] = srcId >> 0;
|
||||
|
||||
unsigned int dstId = data.getDstId();
|
||||
buffer[8U] = dstId >> 16;
|
||||
buffer[9U] = dstId >> 8;
|
||||
buffer[10U] = dstId >> 0;
|
||||
|
||||
::memcpy(buffer + 11U, m_id, 4U);
|
||||
|
||||
unsigned int slotNo = data.getSlotNo();
|
||||
|
||||
// Individual slot disabling
|
||||
if (slotNo == 1U && !m_slot1)
|
||||
return false;
|
||||
if (slotNo == 2U && !m_slot2)
|
||||
return false;
|
||||
|
||||
buffer[15U] = slotNo == 1U ? 0x00U : 0x80U;
|
||||
|
||||
FLCO flco = data.getFLCO();
|
||||
buffer[15U] |= flco == FLCO_GROUP ? 0x00U : 0x40U;
|
||||
|
||||
unsigned int slotIndex = slotNo - 1U;
|
||||
|
||||
std::uniform_int_distribution<uint32_t> dist(0x00000001, 0xfffffffe);
|
||||
unsigned char dataType = data.getDataType();
|
||||
if (dataType == DT_VOICE_SYNC) {
|
||||
buffer[15U] |= 0x10U;
|
||||
} else if (dataType == DT_VOICE) {
|
||||
buffer[15U] |= data.getN();
|
||||
} else {
|
||||
if (dataType == DT_VOICE_LC_HEADER)
|
||||
m_streamId[slotIndex] = dist(m_random);
|
||||
|
||||
if (dataType == DT_CSBK || dataType == DT_DATA_HEADER)
|
||||
m_streamId[slotIndex] = dist(m_random);
|
||||
|
||||
buffer[15U] |= (0x20U | dataType);
|
||||
}
|
||||
|
||||
buffer[4U] = data.getSeqNo();
|
||||
|
||||
::memcpy(buffer + 16U, m_streamId + slotIndex, 4U);
|
||||
|
||||
data.getData(buffer + 20U);
|
||||
|
||||
buffer[53U] = data.getBER();
|
||||
|
||||
buffer[54U] = data.getRSSI();
|
||||
|
||||
write(buffer, HOMEBREW_DATA_PACKET_LENGTH);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CDMRGatewayNetwork::writeRadioPosition(unsigned int id, const unsigned char* data)
|
||||
{
|
||||
unsigned char buffer[20U];
|
||||
|
||||
::memcpy(buffer + 0U, "DMRG", 4U);
|
||||
|
||||
buffer[4U] = id >> 16;
|
||||
buffer[5U] = id >> 8;
|
||||
buffer[6U] = id >> 0;
|
||||
|
||||
::memcpy(buffer + 7U, data + 2U, 7U);
|
||||
|
||||
return write(buffer, 14U);
|
||||
}
|
||||
|
||||
bool CDMRGatewayNetwork::writeTalkerAlias(unsigned int id, unsigned char type, const unsigned char* data)
|
||||
{
|
||||
unsigned char buffer[20U];
|
||||
|
||||
::memcpy(buffer + 0U, "DMRA", 4U);
|
||||
|
||||
buffer[4U] = id >> 16;
|
||||
buffer[5U] = id >> 8;
|
||||
buffer[6U] = id >> 0;
|
||||
|
||||
buffer[7U] = type;
|
||||
|
||||
::memcpy(buffer + 8U, data + 2U, 7U);
|
||||
|
||||
return write(buffer, 15U);
|
||||
}
|
||||
|
||||
bool CDMRGatewayNetwork::isConnected() const
|
||||
{
|
||||
return (m_addrLen != 0);
|
||||
}
|
||||
|
||||
void CDMRGatewayNetwork::close(bool sayGoodbye)
|
||||
{
|
||||
LogMessage("DMR, Closing DMR Network");
|
||||
|
||||
m_socket.close();
|
||||
}
|
||||
|
||||
void CDMRGatewayNetwork::clock(unsigned int ms)
|
||||
{
|
||||
m_pingTimer.clock(ms);
|
||||
if (m_pingTimer.isRunning() && m_pingTimer.hasExpired()) {
|
||||
writeConfig();
|
||||
m_pingTimer.start();
|
||||
}
|
||||
|
||||
sockaddr_storage address;
|
||||
unsigned int addrLen;
|
||||
int length = m_socket.read(m_buffer, BUFFER_LENGTH, address, addrLen);
|
||||
if (length <= 0)
|
||||
return;
|
||||
|
||||
if (!CUDPSocket::match(m_addr, address)) {
|
||||
LogMessage("DMR, packet received from an invalid source");
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_debug)
|
||||
CUtils::dump(1U, "DMR Network Received", m_buffer, length);
|
||||
|
||||
if (::memcmp(m_buffer, "DMRD", 4U) == 0) {
|
||||
if (m_enabled) {
|
||||
unsigned char len = length;
|
||||
m_rxData.addData(&len, 1U);
|
||||
m_rxData.addData(m_buffer, len);
|
||||
}
|
||||
} else if (::memcmp(m_buffer, "DMRP", 4U) == 0) {
|
||||
;
|
||||
} else if (::memcmp(m_buffer, "DMRB", 4U) == 0) {
|
||||
m_beacon = true;
|
||||
} else {
|
||||
CUtils::dump("DMR, unknown packet from the DMR Network", m_buffer, length);
|
||||
}
|
||||
}
|
||||
|
||||
bool CDMRGatewayNetwork::writeConfig()
|
||||
{
|
||||
const char* software;
|
||||
char slots = '0';
|
||||
if (m_duplex) {
|
||||
if (m_slot1 && m_slot2)
|
||||
slots = '3';
|
||||
else if (m_slot1 && !m_slot2)
|
||||
slots = '1';
|
||||
else if (!m_slot1 && m_slot2)
|
||||
slots = '2';
|
||||
|
||||
switch (m_hwType) {
|
||||
case HWT_MMDVM:
|
||||
software = "MMDVM";
|
||||
break;
|
||||
case HWT_MMDVM_HS:
|
||||
software = "MMDVM_MMDVM_HS";
|
||||
break;
|
||||
case HWT_MMDVM_HS_DUAL_HAT:
|
||||
software = "MMDVM_MMDVM_HS_Dual_Hat";
|
||||
break;
|
||||
case HWT_NANO_HOTSPOT:
|
||||
software = "MMDVM_Nano_hotSPOT";
|
||||
break;
|
||||
default:
|
||||
software = "MMDVM_Unknown";
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
slots = '4';
|
||||
|
||||
switch (m_hwType) {
|
||||
case HWT_MMDVM:
|
||||
software = "MMDVM_DMO";
|
||||
break;
|
||||
case HWT_DVMEGA:
|
||||
software = "MMDVM_DVMega";
|
||||
break;
|
||||
case HWT_MMDVM_ZUMSPOT:
|
||||
software = "MMDVM_ZUMspot";
|
||||
break;
|
||||
case HWT_MMDVM_HS_HAT:
|
||||
software = "MMDVM_MMDVM_HS_Hat";
|
||||
break;
|
||||
case HWT_MMDVM_HS_DUAL_HAT:
|
||||
software = "MMDVM_MMDVM_HS_Dual_Hat";
|
||||
break;
|
||||
case HWT_NANO_HOTSPOT:
|
||||
software = "MMDVM_Nano_hotSPOT";
|
||||
break;
|
||||
case HWT_NANO_DV:
|
||||
software = "MMDVM_Nano_DV";
|
||||
break;
|
||||
case HWT_D2RG_MMDVM_HS:
|
||||
software = "MMDVM_D2RG_MMDVM_HS";
|
||||
break;
|
||||
case HWT_MMDVM_HS:
|
||||
software = "MMDVM_MMDVM_HS";
|
||||
break;
|
||||
case HWT_OPENGD77_HS:
|
||||
software = "MMDVM_OpenGD77_HS";
|
||||
break;
|
||||
case HWT_SKYBRIDGE:
|
||||
software = "MMDVM_SkyBridge";
|
||||
break;
|
||||
default:
|
||||
software = "MMDVM_Unknown";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int power = m_power;
|
||||
if (power > 99U)
|
||||
power = 99U;
|
||||
|
||||
char buffer[150U];
|
||||
|
||||
::memcpy(buffer + 0U, "DMRC", 4U);
|
||||
::memcpy(buffer + 4U, m_id, 4U);
|
||||
::sprintf(buffer + 8U, "%-8.8s%09u%09u%02u%02u%c%-40.40s%-40.40s",
|
||||
m_callsign.c_str(), m_rxFrequency, m_txFrequency, power, m_colorCode, slots, m_version,
|
||||
software);
|
||||
|
||||
return write((unsigned char*)buffer, 119U);
|
||||
}
|
||||
|
||||
bool CDMRGatewayNetwork::wantsBeacon()
|
||||
{
|
||||
bool beacon = m_beacon;
|
||||
|
||||
m_beacon = false;
|
||||
|
||||
return beacon;
|
||||
}
|
||||
|
||||
bool CDMRGatewayNetwork::write(const unsigned char* data, unsigned int length)
|
||||
{
|
||||
assert(data != NULL);
|
||||
assert(length > 0U);
|
||||
|
||||
if (m_debug)
|
||||
CUtils::dump(1U, "DMR Network Transmitted", data, length);
|
||||
|
||||
bool ret = m_socket.write(data, length, m_addr, m_addrLen);
|
||||
if (!ret) {
|
||||
LogError("DMR, socket error when writing to the DMR Network");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
|
@ -1,94 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2015,2016,2017,2018,2020,2021 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#if !defined(DMRGatewayNetwork_H)
|
||||
#define DMRGatewayNetwork_H
|
||||
|
||||
#include "DMRNetwork.h"
|
||||
#include "UDPSocket.h"
|
||||
#include "Timer.h"
|
||||
#include "RingBuffer.h"
|
||||
#include "DMRData.h"
|
||||
#include "Defines.h"
|
||||
|
||||
#include <string>
|
||||
#include <cstdint>
|
||||
#include <random>
|
||||
|
||||
class CDMRGatewayNetwork : public IDMRNetwork
|
||||
{
|
||||
public:
|
||||
CDMRGatewayNetwork(const std::string& remoteAddress, unsigned short remotePort, const std::string& localAddress, unsigned short localPort, unsigned int id, bool duplex, const char* version, bool slot1, bool slot2, HW_TYPE hwType, bool debug);
|
||||
virtual ~CDMRGatewayNetwork();
|
||||
|
||||
virtual void setOptions(const std::string& options);
|
||||
|
||||
virtual void setConfig(const std::string& callsign, unsigned int rxFrequency, unsigned int txFrequency, unsigned int power, unsigned int colorCode, float latitude, float longitude, int height, const std::string& location, const std::string& description, const std::string& url);
|
||||
|
||||
virtual bool open();
|
||||
|
||||
virtual void enable(bool enabled);
|
||||
|
||||
virtual bool read(CDMRData& data);
|
||||
|
||||
virtual bool write(const CDMRData& data);
|
||||
|
||||
virtual bool writeRadioPosition(unsigned int id, const unsigned char* data);
|
||||
|
||||
virtual bool writeTalkerAlias(unsigned int id, unsigned char type, const unsigned char* data);
|
||||
|
||||
virtual bool wantsBeacon();
|
||||
|
||||
virtual void clock(unsigned int ms);
|
||||
|
||||
virtual bool isConnected() const;
|
||||
|
||||
virtual void close(bool sayGoodbye);
|
||||
|
||||
private:
|
||||
std::string m_addressStr;
|
||||
sockaddr_storage m_addr;
|
||||
unsigned int m_addrLen;
|
||||
unsigned short m_port;
|
||||
uint8_t* m_id;
|
||||
bool m_duplex;
|
||||
const char* m_version;
|
||||
bool m_debug;
|
||||
CUDPSocket m_socket;
|
||||
bool m_enabled;
|
||||
bool m_slot1;
|
||||
bool m_slot2;
|
||||
HW_TYPE m_hwType;
|
||||
unsigned char* m_buffer;
|
||||
uint32_t* m_streamId;
|
||||
CRingBuffer<unsigned char> m_rxData;
|
||||
bool m_beacon;
|
||||
std::mt19937 m_random;
|
||||
std::string m_callsign;
|
||||
unsigned int m_rxFrequency;
|
||||
unsigned int m_txFrequency;
|
||||
unsigned int m_power;
|
||||
unsigned int m_colorCode;
|
||||
CTimer m_pingTimer;
|
||||
|
||||
bool writeConfig();
|
||||
|
||||
bool write(const unsigned char* data, unsigned int length);
|
||||
};
|
||||
|
||||
#endif
|
42048
DMRIds.dat
42048
DMRIds.dat
File diff suppressed because it is too large
Load diff
15
DMRLC.cpp
15
DMRLC.cpp
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2015,2016,2019,2021,2022 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2015,2016 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
@ -184,19 +184,6 @@ void CDMRLC::setFID(unsigned char fid)
|
|||
m_FID = fid;
|
||||
}
|
||||
|
||||
bool CDMRLC::getOVCM() const
|
||||
{
|
||||
return (m_options & 0x04U) == 0x04U;
|
||||
}
|
||||
|
||||
void CDMRLC::setOVCM(bool ovcm)
|
||||
{
|
||||
if (ovcm)
|
||||
m_options |= 0x04U;
|
||||
else
|
||||
m_options &= 0xFBU;
|
||||
}
|
||||
|
||||
unsigned int CDMRLC::getSrcId() const
|
||||
{
|
||||
return m_srcId;
|
||||
|
|
5
DMRLC.h
5
DMRLC.h
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2015,2016,2019,2021,2022 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2015,2016 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
@ -39,9 +39,6 @@ public:
|
|||
FLCO getFLCO() const;
|
||||
void setFLCO(FLCO flco);
|
||||
|
||||
bool getOVCM() const;
|
||||
void setOVCM(bool ovcm);
|
||||
|
||||
unsigned char getFID() const;
|
||||
void setFID(unsigned char fid);
|
||||
|
||||
|
|
148
DMRLookup.cpp
148
DMRLookup.cpp
|
@ -30,8 +30,8 @@ CThread(),
|
|||
m_filename(filename),
|
||||
m_reloadTime(reloadTime),
|
||||
m_table(),
|
||||
m_stop(false),
|
||||
m_reload(false)
|
||||
m_mutex(),
|
||||
m_stop(false)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -41,7 +41,7 @@ CDMRLookup::~CDMRLookup()
|
|||
|
||||
bool CDMRLookup::read()
|
||||
{
|
||||
bool ret = m_table.load(m_filename);
|
||||
bool ret = load();
|
||||
|
||||
if (m_reloadTime > 0U)
|
||||
run();
|
||||
|
@ -49,14 +49,6 @@ bool CDMRLookup::read()
|
|||
return ret;
|
||||
}
|
||||
|
||||
void CDMRLookup::reload()
|
||||
{
|
||||
if (m_reloadTime == 0U)
|
||||
m_table.load(m_filename);
|
||||
else
|
||||
m_reload = true;
|
||||
}
|
||||
|
||||
void CDMRLookup::entry()
|
||||
{
|
||||
LogInfo("Started the DMR Id lookup reload thread");
|
||||
|
@ -68,10 +60,9 @@ void CDMRLookup::entry()
|
|||
sleep(1000U);
|
||||
|
||||
timer.clock();
|
||||
if (timer.hasExpired() || m_reload) {
|
||||
m_table.load(m_filename);
|
||||
if (timer.hasExpired()) {
|
||||
load();
|
||||
timer.start();
|
||||
m_reload = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -90,47 +81,118 @@ void CDMRLookup::stop()
|
|||
wait();
|
||||
}
|
||||
|
||||
void CDMRLookup::findWithName(unsigned int id, class CUserDBentry *entry)
|
||||
{
|
||||
if (id == 0xFFFFFFFU) {
|
||||
entry->clear();
|
||||
entry->set(keyCALLSIGN, "ALL");
|
||||
return;
|
||||
}
|
||||
|
||||
if (m_table.lookup(id, entry)) {
|
||||
LogDebug("FindWithName =%s %s", entry->get(keyCALLSIGN).c_str(), entry->get(keyFIRST_NAME).c_str());
|
||||
} else {
|
||||
entry->clear();
|
||||
|
||||
char text[10U];
|
||||
::snprintf(text, sizeof(text), "%u", id);
|
||||
entry->set(keyCALLSIGN, text);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
std::string CDMRLookup::find(unsigned int id)
|
||||
std::string CDMRLookup::findWithName(unsigned int id)
|
||||
{
|
||||
std::string callsign;
|
||||
|
||||
if (id == 0xFFFFFFFU)
|
||||
if (id == 0xFFFFFFU)
|
||||
return std::string("ALL");
|
||||
|
||||
class CUserDBentry entry;
|
||||
if (m_table.lookup(id, &entry)) {
|
||||
callsign = entry.get(keyCALLSIGN);
|
||||
} else {
|
||||
m_mutex.lock();
|
||||
|
||||
try {
|
||||
callsign = m_table.at(id);
|
||||
LogDebug("FindWithName =%s",callsign.c_str());
|
||||
|
||||
} catch (...) {
|
||||
char text[10U];
|
||||
::snprintf(text, sizeof(text), "%u", id);
|
||||
::sprintf(text, "%u", id);
|
||||
callsign = std::string(text);
|
||||
}
|
||||
|
||||
m_mutex.unlock();
|
||||
|
||||
return callsign;
|
||||
}
|
||||
std::string CDMRLookup::find(unsigned int id)
|
||||
{
|
||||
std::string callsign;
|
||||
std::string b;
|
||||
|
||||
|
||||
if (id == 0xFFFFFFU)
|
||||
return std::string("ALL");
|
||||
|
||||
m_mutex.lock();
|
||||
|
||||
try {
|
||||
b = m_table.at(id);
|
||||
size_t n = b.find(" ");
|
||||
if (n > 0) {
|
||||
callsign = b.substr(0,n);
|
||||
|
||||
} else {
|
||||
LogDebug("b=%s",b.c_str());
|
||||
callsign = b;
|
||||
}
|
||||
|
||||
} catch (...) {
|
||||
char text[10U];
|
||||
::sprintf(text, "%u", id);
|
||||
callsign = std::string(text);
|
||||
}
|
||||
|
||||
m_mutex.unlock();
|
||||
|
||||
return callsign;
|
||||
}
|
||||
|
||||
bool CDMRLookup::exists(unsigned int id)
|
||||
{
|
||||
return m_table.lookup(id, NULL);
|
||||
m_mutex.lock();
|
||||
|
||||
bool found = m_table.count(id) == 1U;
|
||||
|
||||
m_mutex.unlock();
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
bool CDMRLookup::load()
|
||||
{
|
||||
FILE* fp = ::fopen(m_filename.c_str(), "rt");
|
||||
if (fp == NULL) {
|
||||
LogWarning("Cannot open the DMR Id lookup file - %s", m_filename.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
m_mutex.lock();
|
||||
|
||||
// Remove the old entries
|
||||
m_table.clear();
|
||||
|
||||
char buffer[100U];
|
||||
while (::fgets(buffer, 100U, fp) != NULL) {
|
||||
if (buffer[0U] == '#')
|
||||
continue;
|
||||
|
||||
char* p1 = ::strtok(buffer, " \t\r\n");
|
||||
char* p2 = ::strtok(NULL, " \r\n"); // tokenize to eol to capture name as well
|
||||
|
||||
if (p1 != NULL && p2 != NULL) {
|
||||
unsigned int id = (unsigned int)::atoi(p1);
|
||||
for (char* p = p2; *p != 0x00U; p++) {
|
||||
|
||||
if(*p == 0x09U)
|
||||
*p = 0x20U;
|
||||
|
||||
else
|
||||
*p = ::toupper(*p);
|
||||
|
||||
}
|
||||
m_table[id] = std::string(p2);
|
||||
}
|
||||
}
|
||||
|
||||
m_mutex.unlock();
|
||||
|
||||
::fclose(fp);
|
||||
|
||||
size_t size = m_table.size();
|
||||
if (size == 0U)
|
||||
return false;
|
||||
|
||||
LogInfo("Loaded %u Ids to the DMR callsign lookup table", size);
|
||||
|
||||
return true;
|
||||
}
|
21
DMRLookup.h
21
DMRLookup.h
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2016,2017,2021 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2016,2017 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
|
||||
|
@ -20,9 +20,10 @@
|
|||
#define DMRLookup_H
|
||||
|
||||
#include "Thread.h"
|
||||
#include "UserDB.h"
|
||||
#include "Mutex.h"
|
||||
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
|
||||
class CDMRLookup : public CThread {
|
||||
public:
|
||||
|
@ -31,23 +32,23 @@ public:
|
|||
|
||||
bool read();
|
||||
|
||||
void reload();
|
||||
|
||||
virtual void entry();
|
||||
|
||||
std::string find(unsigned int id);
|
||||
void findWithName(unsigned int id, class CUserDBentry *entry);
|
||||
std::string findWithName(unsigned int id);
|
||||
|
||||
bool exists(unsigned int id);
|
||||
|
||||
void stop();
|
||||
|
||||
private:
|
||||
std::string m_filename;
|
||||
unsigned int m_reloadTime;
|
||||
class CUserDB m_table;
|
||||
bool m_stop;
|
||||
bool m_reload;
|
||||
std::string m_filename;
|
||||
unsigned int m_reloadTime;
|
||||
std::unordered_map<unsigned int, std::string> m_table;
|
||||
CMutex m_mutex;
|
||||
bool m_stop;
|
||||
|
||||
bool load();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
660
DMRNetwork.cpp
660
DMRNetwork.cpp
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2015-2020 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2015-2019 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
@ -18,6 +18,662 @@
|
|||
|
||||
#include "DMRNetwork.h"
|
||||
|
||||
IDMRNetwork::~IDMRNetwork()
|
||||
#include "StopWatch.h"
|
||||
#include "SHA256.h"
|
||||
#include "Utils.h"
|
||||
#include "Log.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
#include <cstdlib>
|
||||
|
||||
const unsigned int BUFFER_LENGTH = 500U;
|
||||
|
||||
const unsigned int HOMEBREW_DATA_PACKET_LENGTH = 55U;
|
||||
|
||||
|
||||
CDMRNetwork::CDMRNetwork(const std::string& address, unsigned int port, unsigned int local, unsigned int id, const std::string& password, bool duplex, const char* version, bool debug, bool slot1, bool slot2, HW_TYPE hwType) :
|
||||
m_addressStr(address),
|
||||
m_address(),
|
||||
m_port(port),
|
||||
m_id(NULL),
|
||||
m_password(password),
|
||||
m_duplex(duplex),
|
||||
m_version(version),
|
||||
m_debug(debug),
|
||||
m_socket(local),
|
||||
m_enabled(false),
|
||||
m_slot1(slot1),
|
||||
m_slot2(slot2),
|
||||
m_hwType(hwType),
|
||||
m_status(WAITING_CONNECT),
|
||||
m_retryTimer(1000U, 10U),
|
||||
m_timeoutTimer(1000U, 60U),
|
||||
m_buffer(NULL),
|
||||
m_salt(NULL),
|
||||
m_streamId(NULL),
|
||||
m_rxData(1000U, "DMR Network"),
|
||||
m_options(),
|
||||
m_callsign(),
|
||||
m_rxFrequency(0U),
|
||||
m_txFrequency(0U),
|
||||
m_power(0U),
|
||||
m_colorCode(0U),
|
||||
m_latitude(0.0F),
|
||||
m_longitude(0.0F),
|
||||
m_height(0),
|
||||
m_location(),
|
||||
m_description(),
|
||||
m_url(),
|
||||
m_beacon(false)
|
||||
{
|
||||
assert(!address.empty());
|
||||
assert(port > 0U);
|
||||
assert(id > 1000U);
|
||||
assert(!password.empty());
|
||||
|
||||
m_address = CUDPSocket::lookup(address);
|
||||
|
||||
m_buffer = new unsigned char[BUFFER_LENGTH];
|
||||
m_salt = new unsigned char[sizeof(uint32_t)];
|
||||
m_id = new uint8_t[4U];
|
||||
m_streamId = new uint32_t[2U];
|
||||
|
||||
m_id[0U] = id >> 24;
|
||||
m_id[1U] = id >> 16;
|
||||
m_id[2U] = id >> 8;
|
||||
m_id[3U] = id >> 0;
|
||||
|
||||
CStopWatch stopWatch;
|
||||
::srand(stopWatch.start());
|
||||
|
||||
m_streamId[0U] = ::rand() + 1U;
|
||||
m_streamId[1U] = ::rand() + 1U;
|
||||
}
|
||||
|
||||
CDMRNetwork::~CDMRNetwork()
|
||||
{
|
||||
delete[] m_buffer;
|
||||
delete[] m_salt;
|
||||
delete[] m_streamId;
|
||||
delete[] m_id;
|
||||
}
|
||||
|
||||
void CDMRNetwork::setOptions(const std::string& options)
|
||||
{
|
||||
m_options = options;
|
||||
}
|
||||
|
||||
void CDMRNetwork::setConfig(const std::string& callsign, unsigned int rxFrequency, unsigned int txFrequency, unsigned int power, unsigned int colorCode, float latitude, float longitude, int height, const std::string& location, const std::string& description, const std::string& url)
|
||||
{
|
||||
m_callsign = callsign;
|
||||
m_rxFrequency = rxFrequency;
|
||||
m_txFrequency = txFrequency;
|
||||
m_power = power;
|
||||
m_colorCode = colorCode;
|
||||
m_latitude = latitude;
|
||||
m_longitude = longitude;
|
||||
m_height = height;
|
||||
m_location = location;
|
||||
m_description = description;
|
||||
m_url = url;
|
||||
}
|
||||
|
||||
bool CDMRNetwork::open()
|
||||
{
|
||||
LogMessage("DMR, Opening DMR Network");
|
||||
|
||||
if (m_address.s_addr == INADDR_NONE)
|
||||
m_address = CUDPSocket::lookup(m_addressStr);
|
||||
|
||||
m_status = WAITING_CONNECT;
|
||||
m_timeoutTimer.stop();
|
||||
m_retryTimer.start();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CDMRNetwork::enable(bool enabled)
|
||||
{
|
||||
if (!enabled && m_enabled)
|
||||
m_rxData.clear();
|
||||
|
||||
m_enabled = enabled;
|
||||
}
|
||||
|
||||
bool CDMRNetwork::read(CDMRData& data)
|
||||
{
|
||||
if (m_status != RUNNING)
|
||||
return false;
|
||||
|
||||
if (m_rxData.isEmpty())
|
||||
return false;
|
||||
|
||||
unsigned char length = 0U;
|
||||
m_rxData.getData(&length, 1U);
|
||||
m_rxData.getData(m_buffer, length);
|
||||
|
||||
// Is this a data packet?
|
||||
if (::memcmp(m_buffer, "DMRD", 4U) != 0)
|
||||
return false;
|
||||
|
||||
unsigned char seqNo = m_buffer[4U];
|
||||
|
||||
unsigned int srcId = (m_buffer[5U] << 16) | (m_buffer[6U] << 8) | (m_buffer[7U] << 0);
|
||||
|
||||
unsigned int dstId = (m_buffer[8U] << 16) | (m_buffer[9U] << 8) | (m_buffer[10U] << 0);
|
||||
|
||||
unsigned int slotNo = (m_buffer[15U] & 0x80U) == 0x80U ? 2U : 1U;
|
||||
|
||||
// DMO mode slot disabling
|
||||
if (slotNo == 1U && !m_duplex)
|
||||
return false;
|
||||
|
||||
// Individual slot disabling
|
||||
if (slotNo == 1U && !m_slot1)
|
||||
return false;
|
||||
if (slotNo == 2U && !m_slot2)
|
||||
return false;
|
||||
|
||||
FLCO flco = (m_buffer[15U] & 0x40U) == 0x40U ? FLCO_USER_USER : FLCO_GROUP;
|
||||
|
||||
data.setSeqNo(seqNo);
|
||||
data.setSlotNo(slotNo);
|
||||
data.setSrcId(srcId);
|
||||
data.setDstId(dstId);
|
||||
data.setFLCO(flco);
|
||||
|
||||
bool dataSync = (m_buffer[15U] & 0x20U) == 0x20U;
|
||||
bool voiceSync = (m_buffer[15U] & 0x10U) == 0x10U;
|
||||
|
||||
if (dataSync) {
|
||||
unsigned char dataType = m_buffer[15U] & 0x0FU;
|
||||
data.setData(m_buffer + 20U);
|
||||
data.setDataType(dataType);
|
||||
data.setN(0U);
|
||||
} else if (voiceSync) {
|
||||
data.setData(m_buffer + 20U);
|
||||
data.setDataType(DT_VOICE_SYNC);
|
||||
data.setN(0U);
|
||||
} else {
|
||||
unsigned char n = m_buffer[15U] & 0x0FU;
|
||||
data.setData(m_buffer + 20U);
|
||||
data.setDataType(DT_VOICE);
|
||||
data.setN(n);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CDMRNetwork::write(const CDMRData& data)
|
||||
{
|
||||
if (m_status != RUNNING)
|
||||
return false;
|
||||
|
||||
unsigned char buffer[HOMEBREW_DATA_PACKET_LENGTH];
|
||||
::memset(buffer, 0x00U, HOMEBREW_DATA_PACKET_LENGTH);
|
||||
|
||||
buffer[0U] = 'D';
|
||||
buffer[1U] = 'M';
|
||||
buffer[2U] = 'R';
|
||||
buffer[3U] = 'D';
|
||||
|
||||
unsigned int srcId = data.getSrcId();
|
||||
buffer[5U] = srcId >> 16;
|
||||
buffer[6U] = srcId >> 8;
|
||||
buffer[7U] = srcId >> 0;
|
||||
|
||||
unsigned int dstId = data.getDstId();
|
||||
buffer[8U] = dstId >> 16;
|
||||
buffer[9U] = dstId >> 8;
|
||||
buffer[10U] = dstId >> 0;
|
||||
|
||||
::memcpy(buffer + 11U, m_id, 4U);
|
||||
|
||||
unsigned int slotNo = data.getSlotNo();
|
||||
|
||||
// Individual slot disabling
|
||||
if (slotNo == 1U && !m_slot1)
|
||||
return false;
|
||||
if (slotNo == 2U && !m_slot2)
|
||||
return false;
|
||||
|
||||
buffer[15U] = slotNo == 1U ? 0x00U : 0x80U;
|
||||
|
||||
FLCO flco = data.getFLCO();
|
||||
buffer[15U] |= flco == FLCO_GROUP ? 0x00U : 0x40U;
|
||||
|
||||
unsigned int slotIndex = slotNo - 1U;
|
||||
|
||||
unsigned int count = 1U;
|
||||
|
||||
unsigned char dataType = data.getDataType();
|
||||
if (dataType == DT_VOICE_SYNC) {
|
||||
buffer[15U] |= 0x10U;
|
||||
} else if (dataType == DT_VOICE) {
|
||||
buffer[15U] |= data.getN();
|
||||
} else {
|
||||
if (dataType == DT_VOICE_LC_HEADER) {
|
||||
m_streamId[slotIndex] = ::rand() + 1U;
|
||||
count = 2U;
|
||||
}
|
||||
|
||||
if (dataType == DT_CSBK || dataType == DT_DATA_HEADER) {
|
||||
m_streamId[slotIndex] = ::rand() + 1U;
|
||||
count = 1U;
|
||||
}
|
||||
|
||||
buffer[15U] |= (0x20U | dataType);
|
||||
}
|
||||
|
||||
buffer[4U] = data.getSeqNo();
|
||||
|
||||
::memcpy(buffer + 16U, m_streamId + slotIndex, 4U);
|
||||
|
||||
data.getData(buffer + 20U);
|
||||
|
||||
buffer[53U] = data.getBER();
|
||||
|
||||
buffer[54U] = data.getRSSI();
|
||||
|
||||
if (m_debug)
|
||||
CUtils::dump(1U, "Network Transmitted", buffer, HOMEBREW_DATA_PACKET_LENGTH);
|
||||
|
||||
for (unsigned int i = 0U; i < count; i++)
|
||||
write(buffer, HOMEBREW_DATA_PACKET_LENGTH);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CDMRNetwork::writeRadioPosition(unsigned int id, const unsigned char* data)
|
||||
{
|
||||
if (m_status != RUNNING)
|
||||
return false;
|
||||
|
||||
unsigned char buffer[20U];
|
||||
|
||||
::memcpy(buffer + 0U, "DMRG", 4U);
|
||||
|
||||
::memcpy(buffer + 4U, m_id, 4U);
|
||||
|
||||
buffer[8U] = id >> 16;
|
||||
buffer[9U] = id >> 8;
|
||||
buffer[10U] = id >> 0;
|
||||
|
||||
::memcpy(buffer + 11U, data + 2U, 7U);
|
||||
|
||||
return write(buffer, 18U);
|
||||
}
|
||||
|
||||
bool CDMRNetwork::writeTalkerAlias(unsigned int id, unsigned char type, const unsigned char* data)
|
||||
{
|
||||
if (m_status != RUNNING)
|
||||
return false;
|
||||
|
||||
unsigned char buffer[20U];
|
||||
|
||||
::memcpy(buffer + 0U, "DMRA", 4U);
|
||||
|
||||
::memcpy(buffer + 4U, m_id, 4U);
|
||||
|
||||
buffer[8U] = id >> 16;
|
||||
buffer[9U] = id >> 8;
|
||||
buffer[10U] = id >> 0;
|
||||
|
||||
buffer[11U] = type;
|
||||
|
||||
::memcpy(buffer + 12U, data + 2U, 7U);
|
||||
|
||||
return write(buffer, 19U);
|
||||
}
|
||||
|
||||
bool CDMRNetwork::writeHomePosition(float latitude, float longitude)
|
||||
{
|
||||
m_latitude = latitude;
|
||||
m_longitude = longitude;
|
||||
|
||||
if (m_status != RUNNING)
|
||||
return false;
|
||||
|
||||
char buffer[50U];
|
||||
|
||||
::memcpy(buffer + 0U, "RPTG", 4U);
|
||||
::memcpy(buffer + 4U, m_id, 4U);
|
||||
|
||||
::sprintf(buffer + 8U, "%08f%09f", latitude, longitude);
|
||||
|
||||
return write((unsigned char*)buffer, 25U);
|
||||
}
|
||||
|
||||
void CDMRNetwork::close()
|
||||
{
|
||||
LogMessage("DMR, Closing DMR Network");
|
||||
|
||||
if (m_status == RUNNING) {
|
||||
unsigned char buffer[9U];
|
||||
::memcpy(buffer + 0U, "RPTCL", 5U);
|
||||
::memcpy(buffer + 5U, m_id, 4U);
|
||||
write(buffer, 9U);
|
||||
}
|
||||
|
||||
m_socket.close();
|
||||
|
||||
m_retryTimer.stop();
|
||||
m_timeoutTimer.stop();
|
||||
}
|
||||
|
||||
void CDMRNetwork::clock(unsigned int ms)
|
||||
{
|
||||
if (m_status == WAITING_CONNECT) {
|
||||
m_retryTimer.clock(ms);
|
||||
if (m_retryTimer.isRunning() && m_retryTimer.hasExpired()) {
|
||||
bool ret = m_socket.open();
|
||||
if (ret) {
|
||||
ret = writeLogin();
|
||||
if (!ret)
|
||||
return;
|
||||
|
||||
m_status = WAITING_LOGIN;
|
||||
m_timeoutTimer.start();
|
||||
}
|
||||
|
||||
m_retryTimer.start();
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
in_addr address;
|
||||
unsigned int port;
|
||||
int length = m_socket.read(m_buffer, BUFFER_LENGTH, address, port);
|
||||
if (length < 0) {
|
||||
LogError("DMR, Socket has failed, retrying connection to the master");
|
||||
close();
|
||||
open();
|
||||
return;
|
||||
}
|
||||
|
||||
// if (m_debug && length > 0)
|
||||
// CUtils::dump(1U, "Network Received", m_buffer, length);
|
||||
|
||||
if (length > 0 && m_address.s_addr == address.s_addr && m_port == port) {
|
||||
if (::memcmp(m_buffer, "DMRD", 4U) == 0) {
|
||||
if (m_enabled) {
|
||||
if (m_debug)
|
||||
CUtils::dump(1U, "Network Received", m_buffer, length);
|
||||
|
||||
unsigned char len = length;
|
||||
m_rxData.addData(&len, 1U);
|
||||
m_rxData.addData(m_buffer, len);
|
||||
}
|
||||
} else if (::memcmp(m_buffer, "MSTNAK", 6U) == 0) {
|
||||
if (m_status == RUNNING) {
|
||||
LogWarning("DMR, Login to the master has failed, retrying login ...");
|
||||
m_status = WAITING_LOGIN;
|
||||
m_timeoutTimer.start();
|
||||
m_retryTimer.start();
|
||||
} else {
|
||||
/* Once the modem death spiral has been prevented in Modem.cpp
|
||||
the Network sometimes times out and reaches here.
|
||||
We want it to reconnect so... */
|
||||
LogError("DMR, Login to the master has failed, retrying network ...");
|
||||
close();
|
||||
open();
|
||||
return;
|
||||
}
|
||||
} else if (::memcmp(m_buffer, "RPTACK", 6U) == 0) {
|
||||
switch (m_status) {
|
||||
case WAITING_LOGIN:
|
||||
LogDebug("DMR, Sending authorisation");
|
||||
::memcpy(m_salt, m_buffer + 6U, sizeof(uint32_t));
|
||||
writeAuthorisation();
|
||||
m_status = WAITING_AUTHORISATION;
|
||||
m_timeoutTimer.start();
|
||||
m_retryTimer.start();
|
||||
break;
|
||||
case WAITING_AUTHORISATION:
|
||||
LogDebug("DMR, Sending configuration");
|
||||
writeConfig();
|
||||
m_status = WAITING_CONFIG;
|
||||
m_timeoutTimer.start();
|
||||
m_retryTimer.start();
|
||||
break;
|
||||
case WAITING_CONFIG:
|
||||
if (m_options.empty()) {
|
||||
LogMessage("DMR, Logged into the master successfully");
|
||||
m_status = RUNNING;
|
||||
} else {
|
||||
LogDebug("DMR, Sending options");
|
||||
writeOptions();
|
||||
m_status = WAITING_OPTIONS;
|
||||
}
|
||||
m_timeoutTimer.start();
|
||||
m_retryTimer.start();
|
||||
break;
|
||||
case WAITING_OPTIONS:
|
||||
LogMessage("DMR, Logged into the master successfully");
|
||||
m_status = RUNNING;
|
||||
m_timeoutTimer.start();
|
||||
m_retryTimer.start();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
} else if (::memcmp(m_buffer, "MSTCL", 5U) == 0) {
|
||||
LogError("DMR, Master is closing down");
|
||||
close();
|
||||
open();
|
||||
} else if (::memcmp(m_buffer, "MSTPONG", 7U) == 0) {
|
||||
m_timeoutTimer.start();
|
||||
} else if (::memcmp(m_buffer, "RPTSBKN", 7U) == 0) {
|
||||
m_beacon = true;
|
||||
} else {
|
||||
CUtils::dump("Unknown packet from the master", m_buffer, length);
|
||||
}
|
||||
}
|
||||
|
||||
m_retryTimer.clock(ms);
|
||||
if (m_retryTimer.isRunning() && m_retryTimer.hasExpired()) {
|
||||
switch (m_status) {
|
||||
case WAITING_LOGIN:
|
||||
writeLogin();
|
||||
break;
|
||||
case WAITING_AUTHORISATION:
|
||||
writeAuthorisation();
|
||||
break;
|
||||
case WAITING_OPTIONS:
|
||||
writeOptions();
|
||||
break;
|
||||
case WAITING_CONFIG:
|
||||
writeConfig();
|
||||
break;
|
||||
case RUNNING:
|
||||
writePing();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
m_retryTimer.start();
|
||||
}
|
||||
|
||||
m_timeoutTimer.clock(ms);
|
||||
if (m_timeoutTimer.isRunning() && m_timeoutTimer.hasExpired()) {
|
||||
LogError("DMR, Connection to the master has timed out, retrying connection");
|
||||
close();
|
||||
open();
|
||||
}
|
||||
}
|
||||
|
||||
bool CDMRNetwork::writeLogin()
|
||||
{
|
||||
unsigned char buffer[8U];
|
||||
|
||||
::memcpy(buffer + 0U, "RPTL", 4U);
|
||||
::memcpy(buffer + 4U, m_id, 4U);
|
||||
|
||||
return write(buffer, 8U);
|
||||
}
|
||||
|
||||
bool CDMRNetwork::writeAuthorisation()
|
||||
{
|
||||
size_t size = m_password.size();
|
||||
|
||||
unsigned char* in = new unsigned char[size + sizeof(uint32_t)];
|
||||
::memcpy(in, m_salt, sizeof(uint32_t));
|
||||
for (size_t i = 0U; i < size; i++)
|
||||
in[i + sizeof(uint32_t)] = m_password.at(i);
|
||||
|
||||
unsigned char out[40U];
|
||||
::memcpy(out + 0U, "RPTK", 4U);
|
||||
::memcpy(out + 4U, m_id, 4U);
|
||||
|
||||
CSHA256 sha256;
|
||||
sha256.buffer(in, (unsigned int)(size + sizeof(uint32_t)), out + 8U);
|
||||
|
||||
delete[] in;
|
||||
|
||||
return write(out, 40U);
|
||||
}
|
||||
|
||||
bool CDMRNetwork::writeOptions()
|
||||
{
|
||||
char buffer[300U];
|
||||
|
||||
::memcpy(buffer + 0U, "RPTO", 4U);
|
||||
::memcpy(buffer + 4U, m_id, 4U);
|
||||
::strcpy(buffer + 8U, m_options.c_str());
|
||||
|
||||
return write((unsigned char*)buffer, (unsigned int)m_options.length() + 8U);
|
||||
}
|
||||
|
||||
bool CDMRNetwork::writeConfig()
|
||||
{
|
||||
const char* software;
|
||||
char slots = '0';
|
||||
if (m_duplex) {
|
||||
if (m_slot1 && m_slot2)
|
||||
slots = '3';
|
||||
else if (m_slot1 && !m_slot2)
|
||||
slots = '1';
|
||||
else if (!m_slot1 && m_slot2)
|
||||
slots = '2';
|
||||
|
||||
switch (m_hwType) {
|
||||
case HWT_MMDVM:
|
||||
software = "MMDVM";
|
||||
break;
|
||||
case HWT_MMDVM_HS:
|
||||
software = "MMDVM_MMDVM_HS";
|
||||
break;
|
||||
case HWT_MMDVM_HS_DUAL_HAT:
|
||||
software = "MMDVM_MMDVM_HS_Dual_Hat";
|
||||
break;
|
||||
case HWT_NANO_HOTSPOT:
|
||||
software = "MMDVM_Nano_hotSPOT";
|
||||
break;
|
||||
default:
|
||||
software = "MMDVM_Unknown";
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
slots = '4';
|
||||
|
||||
switch (m_hwType) {
|
||||
case HWT_MMDVM:
|
||||
software = "MMDVM_DMO";
|
||||
break;
|
||||
case HWT_DVMEGA:
|
||||
software = "MMDVM_DVMega";
|
||||
break;
|
||||
case HWT_MMDVM_ZUMSPOT:
|
||||
software = "MMDVM_ZUMspot";
|
||||
break;
|
||||
case HWT_MMDVM_HS_HAT:
|
||||
software = "MMDVM_MMDVM_HS_Hat";
|
||||
break;
|
||||
case HWT_MMDVM_HS_DUAL_HAT:
|
||||
software = "MMDVM_MMDVM_HS_Dual_Hat";
|
||||
break;
|
||||
case HWT_NANO_HOTSPOT:
|
||||
software = "MMDVM_Nano_hotSPOT";
|
||||
break;
|
||||
case HWT_NANO_DV:
|
||||
software = "MMDVM_Nano_DV";
|
||||
break;
|
||||
case HWT_D2RG_MMDVM_HS:
|
||||
software = "MMDVM_D2RG_MMDVM_HS";
|
||||
break;
|
||||
case HWT_MMDVM_HS:
|
||||
software = "MMDVM_MMDVM_HS";
|
||||
break;
|
||||
default:
|
||||
software = "MMDVM_Unknown";
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
char buffer[400U];
|
||||
|
||||
::memcpy(buffer + 0U, "RPTC", 4U);
|
||||
::memcpy(buffer + 4U, m_id, 4U);
|
||||
|
||||
char latitude[20U];
|
||||
::sprintf(latitude, "%08f", m_latitude);
|
||||
|
||||
char longitude[20U];
|
||||
::sprintf(longitude, "%09f", m_longitude);
|
||||
|
||||
unsigned int power = m_power;
|
||||
if (power > 99U)
|
||||
power = 99U;
|
||||
|
||||
int height = m_height;
|
||||
if (height > 999)
|
||||
height = 999;
|
||||
|
||||
::sprintf(buffer + 8U, "%-8.8s%09u%09u%02u%02u%8.8s%9.9s%03d%-20.20s%-19.19s%c%-124.124s%-40.40s%-40.40s", m_callsign.c_str(),
|
||||
m_rxFrequency, m_txFrequency, power, m_colorCode, latitude, longitude, height, m_location.c_str(),
|
||||
m_description.c_str(), slots, m_url.c_str(), m_version, software);
|
||||
|
||||
return write((unsigned char*)buffer, 302U);
|
||||
}
|
||||
|
||||
bool CDMRNetwork::writePing()
|
||||
{
|
||||
unsigned char buffer[11U];
|
||||
|
||||
::memcpy(buffer + 0U, "RPTPING", 7U);
|
||||
::memcpy(buffer + 7U, m_id, 4U);
|
||||
|
||||
return write(buffer, 11U);
|
||||
}
|
||||
|
||||
bool CDMRNetwork::wantsBeacon()
|
||||
{
|
||||
bool beacon = m_beacon;
|
||||
|
||||
m_beacon = false;
|
||||
|
||||
return beacon;
|
||||
}
|
||||
|
||||
bool CDMRNetwork::write(const unsigned char* data, unsigned int length)
|
||||
{
|
||||
assert(data != NULL);
|
||||
assert(length > 0U);
|
||||
|
||||
// if (m_debug)
|
||||
// CUtils::dump(1U, "Network Transmitted", data, length);
|
||||
|
||||
bool ret = m_socket.write(data, length, m_address, m_port);
|
||||
if (!ret) {
|
||||
LogError("DMR, Socket has failed when writing data to the master, retrying connection");
|
||||
m_socket.close();
|
||||
open();
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
91
DMRNetwork.h
91
DMRNetwork.h
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2015,2016,2017,2018,2020,2021 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2015,2016,2017,2018 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
@ -19,40 +19,101 @@
|
|||
#if !defined(DMRNetwork_H)
|
||||
#define DMRNetwork_H
|
||||
|
||||
#include "UDPSocket.h"
|
||||
#include "Timer.h"
|
||||
#include "RingBuffer.h"
|
||||
#include "DMRData.h"
|
||||
#include "Defines.h"
|
||||
|
||||
#include <string>
|
||||
#include <cstdint>
|
||||
|
||||
class IDMRNetwork
|
||||
class CDMRNetwork
|
||||
{
|
||||
public:
|
||||
virtual ~IDMRNetwork() = 0;
|
||||
CDMRNetwork(const std::string& address, unsigned int port, unsigned int local, unsigned int id, const std::string& password, bool duplex, const char* version, bool debug, bool slot1, bool slot2, HW_TYPE hwType);
|
||||
~CDMRNetwork();
|
||||
|
||||
virtual void setOptions(const std::string& options) = 0;
|
||||
void setOptions(const std::string& options);
|
||||
|
||||
virtual void setConfig(const std::string& callsign, unsigned int rxFrequency, unsigned int txFrequency, unsigned int power, unsigned int colorCode, float latitude, float longitude, int height, const std::string& location, const std::string& description, const std::string& url) = 0;
|
||||
void setConfig(const std::string& callsign, unsigned int rxFrequency, unsigned int txFrequency, unsigned int power, unsigned int colorCode, float latitude, float longitude, int height, const std::string& location, const std::string& description, const std::string& url);
|
||||
|
||||
virtual bool open() = 0;
|
||||
bool open();
|
||||
|
||||
virtual void enable(bool enabled) = 0;
|
||||
void enable(bool enabled);
|
||||
|
||||
virtual bool read(CDMRData& data) = 0;
|
||||
bool read(CDMRData& data);
|
||||
|
||||
virtual bool write(const CDMRData& data) = 0;
|
||||
bool write(const CDMRData& data);
|
||||
|
||||
virtual bool writeRadioPosition(unsigned int id, const unsigned char* data) = 0;
|
||||
bool writeRadioPosition(unsigned int id, const unsigned char* data);
|
||||
|
||||
virtual bool writeTalkerAlias(unsigned int id, unsigned char type, const unsigned char* data) = 0;
|
||||
bool writeTalkerAlias(unsigned int id, unsigned char type, const unsigned char* data);
|
||||
|
||||
virtual bool wantsBeacon() = 0;
|
||||
bool writeHomePosition(float latitude, float longitude);
|
||||
|
||||
virtual void clock(unsigned int ms) = 0;
|
||||
bool wantsBeacon();
|
||||
|
||||
virtual bool isConnected() const = 0;
|
||||
void clock(unsigned int ms);
|
||||
|
||||
virtual void close(bool sayGoodbye) = 0;
|
||||
void close();
|
||||
|
||||
private:
|
||||
std::string m_addressStr;
|
||||
in_addr m_address;
|
||||
unsigned int m_port;
|
||||
uint8_t* m_id;
|
||||
std::string m_password;
|
||||
bool m_duplex;
|
||||
const char* m_version;
|
||||
bool m_debug;
|
||||
CUDPSocket m_socket;
|
||||
bool m_enabled;
|
||||
bool m_slot1;
|
||||
bool m_slot2;
|
||||
HW_TYPE m_hwType;
|
||||
|
||||
enum STATUS {
|
||||
WAITING_CONNECT,
|
||||
WAITING_LOGIN,
|
||||
WAITING_AUTHORISATION,
|
||||
WAITING_CONFIG,
|
||||
WAITING_OPTIONS,
|
||||
RUNNING
|
||||
};
|
||||
|
||||
STATUS m_status;
|
||||
CTimer m_retryTimer;
|
||||
CTimer m_timeoutTimer;
|
||||
unsigned char* m_buffer;
|
||||
unsigned char* m_salt;
|
||||
uint32_t* m_streamId;
|
||||
|
||||
CRingBuffer<unsigned char> m_rxData;
|
||||
|
||||
std::string m_options;
|
||||
|
||||
std::string m_callsign;
|
||||
unsigned int m_rxFrequency;
|
||||
unsigned int m_txFrequency;
|
||||
unsigned int m_power;
|
||||
unsigned int m_colorCode;
|
||||
float m_latitude;
|
||||
float m_longitude;
|
||||
int m_height;
|
||||
std::string m_location;
|
||||
std::string m_description;
|
||||
std::string m_url;
|
||||
|
||||
bool m_beacon;
|
||||
|
||||
bool writeLogin();
|
||||
bool writeAuthorisation();
|
||||
bool writeOptions();
|
||||
bool writeConfig();
|
||||
bool writePing();
|
||||
|
||||
bool write(const unsigned char* data, unsigned int length);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
124
DMRSlot.cpp
124
DMRSlot.cpp
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2015-2021 Jonathan Naylor, G4KLX
|
||||
* Copyright (C) 2015-2019 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
|
||||
|
@ -38,12 +38,11 @@ bool CDMRSlot::m_embeddedLCOnly = false;
|
|||
bool CDMRSlot::m_dumpTAData = true;
|
||||
|
||||
CModem* CDMRSlot::m_modem = NULL;
|
||||
IDMRNetwork* CDMRSlot::m_network = NULL;
|
||||
CDMRNetwork* CDMRSlot::m_network = NULL;
|
||||
CDisplay* CDMRSlot::m_display = NULL;
|
||||
bool CDMRSlot::m_duplex = true;
|
||||
CDMRLookup* CDMRSlot::m_lookup = NULL;
|
||||
unsigned int CDMRSlot::m_hangCount = 3U * 17U;
|
||||
DMR_OVCM_TYPES CDMRSlot::m_ovcm = DMR_OVCM_OFF;
|
||||
|
||||
CRSSIInterpolator* CDMRSlot::m_rssiMapper = NULL;
|
||||
|
||||
|
@ -142,14 +141,10 @@ bool CDMRSlot::writeModem(unsigned char *data, unsigned int len)
|
|||
return false;
|
||||
|
||||
if (data[0U] == TAG_LOST && m_rfState == RS_RF_AUDIO) {
|
||||
std::string src = m_lookup->find(m_rfLC->getSrcId());
|
||||
std::string dst = m_lookup->find(m_rfLC->getDstId());
|
||||
FLCO flco = m_rfLC->getFLCO();
|
||||
|
||||
if (m_rssi != 0U)
|
||||
LogMessage("DMR Slot %u, RF voice transmission lost from %s to %s%s, %.1f seconds, BER: %.1f%%, RSSI: -%u/-%u/-%u dBm", m_slotNo, src.c_str(), flco == FLCO_GROUP ? "TG " : "", dst.c_str(), float(m_rfFrames) / 16.667F, float(m_rfErrs * 100U) / float(m_rfBits), m_minRSSI, m_maxRSSI, m_aveRSSI / m_rssiCount);
|
||||
LogMessage("DMR Slot %u, RF voice transmission lost, %.1f seconds, BER: %.1f%%, RSSI: -%u/-%u/-%u dBm", m_slotNo, float(m_rfFrames) / 16.667F, float(m_rfErrs * 100U) / float(m_rfBits), m_minRSSI, m_maxRSSI, m_aveRSSI / m_rssiCount);
|
||||
else
|
||||
LogMessage("DMR Slot %u, RF voice transmission lost from %s to %s%s, %.1f seconds, BER: %.1f%%", m_slotNo, src.c_str(), flco == FLCO_GROUP ? "TG " : "", dst.c_str(), float(m_rfFrames) / 16.667F, float(m_rfErrs * 100U) / float(m_rfBits));
|
||||
LogMessage("DMR Slot %u, RF voice transmission lost, %.1f seconds, BER: %.1f%%", m_slotNo, float(m_rfFrames) / 16.667F, float(m_rfErrs * 100U) / float(m_rfBits));
|
||||
if (m_rfTimeout) {
|
||||
writeEndRF();
|
||||
return false;
|
||||
|
@ -160,11 +155,7 @@ bool CDMRSlot::writeModem(unsigned char *data, unsigned int len)
|
|||
}
|
||||
|
||||
if (data[0U] == TAG_LOST && m_rfState == RS_RF_DATA) {
|
||||
std::string src = m_lookup->find(m_rfLC->getSrcId());
|
||||
std::string dst = m_lookup->find(m_rfLC->getDstId());
|
||||
FLCO flco = m_rfLC->getFLCO();
|
||||
|
||||
LogMessage("DMR Slot %u, RF data transmission lost from %s to %s%s", m_slotNo, src.c_str(), flco == FLCO_GROUP ? "TG " : "", dst.c_str());
|
||||
LogMessage("DMR Slot %u, RF data transmission lost", m_slotNo);
|
||||
writeEndRF();
|
||||
return false;
|
||||
}
|
||||
|
@ -224,22 +215,15 @@ bool CDMRSlot::writeModem(unsigned char *data, unsigned int len)
|
|||
if (!CDMRAccessControl::validateSrcId(srcId)) {
|
||||
LogMessage("DMR Slot %u, RF user %u rejected", m_slotNo, srcId);
|
||||
delete lc;
|
||||
m_rfState = RS_RF_LISTENING;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!CDMRAccessControl::validateTGId(m_slotNo, flco == FLCO_GROUP, dstId)) {
|
||||
LogMessage("DMR Slot %u, RF user %u rejected for using TG %u", m_slotNo, srcId, dstId);
|
||||
delete lc;
|
||||
m_rfState = RS_RF_LISTENING;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (m_ovcm == DMR_OVCM_TX_ON || m_ovcm == DMR_OVCM_ON)
|
||||
lc->setOVCM(true);
|
||||
else if (m_ovcm == DMR_OVCM_FORCE_OFF)
|
||||
lc->setOVCM(false);
|
||||
|
||||
m_rfLC = lc;
|
||||
|
||||
// The standby LC data
|
||||
|
@ -343,6 +327,7 @@ bool CDMRSlot::writeModem(unsigned char *data, unsigned int len)
|
|||
data[0U] = TAG_EOT;
|
||||
data[1U] = 0x00U;
|
||||
|
||||
writeNetworkRF(data, DT_TERMINATOR_WITH_LC);
|
||||
writeNetworkRF(data, DT_TERMINATOR_WITH_LC);
|
||||
|
||||
if (m_duplex) {
|
||||
|
@ -351,14 +336,10 @@ bool CDMRSlot::writeModem(unsigned char *data, unsigned int len)
|
|||
}
|
||||
}
|
||||
|
||||
std::string src = m_lookup->find(m_rfLC->getSrcId());
|
||||
std::string dst = m_lookup->find(m_rfLC->getDstId());
|
||||
FLCO flco = m_rfLC->getFLCO();
|
||||
|
||||
if (m_rssi != 0U)
|
||||
LogMessage("DMR Slot %u, received RF end of voice transmission from %s to %s%s, %.1f seconds, BER: %.1f%%, RSSI: -%u/-%u/-%u dBm", m_slotNo, src.c_str(), flco == FLCO_GROUP ? "TG " : "", dst.c_str(), float(m_rfFrames) / 16.667F, float(m_rfErrs * 100U) / float(m_rfBits), m_minRSSI, m_maxRSSI, m_aveRSSI / m_rssiCount);
|
||||
LogMessage("DMR Slot %u, received RF end of voice transmission, %.1f seconds, BER: %.1f%%, RSSI: -%u/-%u/-%u dBm", m_slotNo, float(m_rfFrames) / 16.667F, float(m_rfErrs * 100U) / float(m_rfBits), m_minRSSI, m_maxRSSI, m_aveRSSI / m_rssiCount);
|
||||
else
|
||||
LogMessage("DMR Slot %u, received RF end of voice transmission from %s to %s%s, %.1f seconds, BER: %.1f%%", m_slotNo, src.c_str(), flco == FLCO_GROUP ? "TG " : "", dst.c_str(), float(m_rfFrames) / 16.667F, float(m_rfErrs * 100U) / float(m_rfBits));
|
||||
LogMessage("DMR Slot %u, received RF end of voice transmission, %.1f seconds, BER: %.1f%%", m_slotNo, float(m_rfFrames) / 16.667F, float(m_rfErrs * 100U) / float(m_rfBits));
|
||||
|
||||
m_display->writeDMRTA(m_slotNo, NULL, " ");
|
||||
|
||||
|
@ -384,13 +365,11 @@ bool CDMRSlot::writeModem(unsigned char *data, unsigned int len)
|
|||
|
||||
if (!CDMRAccessControl::validateSrcId(srcId)) {
|
||||
LogMessage("DMR Slot %u, RF user %u rejected", m_slotNo, srcId);
|
||||
m_rfState = RS_RF_LISTENING;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!CDMRAccessControl::validateTGId(m_slotNo, gi, dstId)) {
|
||||
LogMessage("DMR Slot %u, RF user %u rejected for using TG %u", m_slotNo, srcId, dstId);
|
||||
m_rfState = RS_RF_LISTENING;
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -429,7 +408,7 @@ bool CDMRSlot::writeModem(unsigned char *data, unsigned int len)
|
|||
LogMessage("DMR Slot %u, received RF data header from %s to %s%s, %u blocks", m_slotNo, src.c_str(), gi ? "TG ": "", dst.c_str(), m_rfFrames);
|
||||
|
||||
if (m_rfFrames == 0U) {
|
||||
LogMessage("DMR Slot %u, ended RF data transmission from %s to %s%s", m_slotNo, src.c_str(), gi ? "TG " : "", dst.c_str());
|
||||
LogMessage("DMR Slot %u, ended RF data transmission", m_slotNo);
|
||||
writeEndRF();
|
||||
}
|
||||
|
||||
|
@ -444,12 +423,6 @@ bool CDMRSlot::writeModem(unsigned char *data, unsigned int len)
|
|||
if (csbko == CSBKO_BSDWNACT)
|
||||
return false;
|
||||
|
||||
// set the OVCM bit for the supported csbk
|
||||
if (m_ovcm == DMR_OVCM_TX_ON || m_ovcm == DMR_OVCM_ON)
|
||||
csbk.setOVCM(true);
|
||||
else if (m_ovcm == DMR_OVCM_FORCE_OFF)
|
||||
csbk.setOVCM(false);
|
||||
|
||||
bool gi = csbk.getGI();
|
||||
unsigned int srcId = csbk.getSrcId();
|
||||
unsigned int dstId = csbk.getDstId();
|
||||
|
@ -457,13 +430,11 @@ bool CDMRSlot::writeModem(unsigned char *data, unsigned int len)
|
|||
if (srcId != 0U || dstId != 0U) {
|
||||
if (!CDMRAccessControl::validateSrcId(srcId)) {
|
||||
LogMessage("DMR Slot %u, RF user %u rejected", m_slotNo, srcId);
|
||||
m_rfState = RS_RF_LISTENING;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!CDMRAccessControl::validateTGId(m_slotNo, gi, dstId)) {
|
||||
LogMessage("DMR Slot %u, RF user %u rejected for using TG %u", m_slotNo, srcId, dstId);
|
||||
m_rfState = RS_RF_LISTENING;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -501,15 +472,6 @@ bool CDMRSlot::writeModem(unsigned char *data, unsigned int len)
|
|||
case CSBKO_PRECCSBK:
|
||||
LogMessage("DMR Slot %u, received RF %s Preamble CSBK (%u to follow) from %s to %s%s", m_slotNo, csbk.getDataContent() ? "Data" : "CSBK", csbk.getCBF(), src.c_str(), gi ? "TG ": "", dst.c_str());
|
||||
break;
|
||||
case CSBKO_CALL_ALERT:
|
||||
LogMessage("DMR Slot %u, received RF Call Alert CSBK from %s to %s%s", m_slotNo, src.c_str(), gi ? "TG " : "", dst.c_str());
|
||||
break;
|
||||
case CSBKO_CALL_ALERT_ACK:
|
||||
LogMessage("DMR Slot %u, received RF Call Alert Ack CSBK from %s to %s%s", m_slotNo, src.c_str(), gi ? "TG " : "", dst.c_str());
|
||||
break;
|
||||
case CSBKO_RADIO_CHECK:
|
||||
LogMessage("DMR Slot %u, received RF Radio Check %s CSBK from %s to %s%s", m_slotNo, /* TBD */ 1 ? "Req" : "Ack", src.c_str(), gi ? "TG " : "", dst.c_str());
|
||||
break;
|
||||
default:
|
||||
LogWarning("DMR Slot %u, unhandled RF CSBK type - 0x%02X", m_slotNo, csbko);
|
||||
break;
|
||||
|
@ -672,7 +634,7 @@ bool CDMRSlot::writeModem(unsigned char *data, unsigned int len)
|
|||
if (!(m_rfTalkerId & TALKER_ID_HEADER)) {
|
||||
if (m_rfTalkerId == TALKER_ID_NONE)
|
||||
m_rfTalkerAlias.reset();
|
||||
m_rfTalkerAlias.add(0, data + 2U, 7U);
|
||||
m_rfTalkerAlias.add(0, data, 7U);
|
||||
m_display->writeDMRTA(m_slotNo, (unsigned char*)m_rfTalkerAlias.get(), "R");
|
||||
|
||||
if (m_dumpTAData) {
|
||||
|
@ -691,7 +653,7 @@ bool CDMRSlot::writeModem(unsigned char *data, unsigned int len)
|
|||
if (!(m_rfTalkerId & TALKER_ID_BLOCK1)) {
|
||||
if (m_rfTalkerId == TALKER_ID_NONE)
|
||||
m_rfTalkerAlias.reset();
|
||||
m_rfTalkerAlias.add(1, data + 2U, 7U);
|
||||
m_rfTalkerAlias.add(1, data, 7U);
|
||||
m_display->writeDMRTA(m_slotNo, (unsigned char*)m_rfTalkerAlias.get(), "R");
|
||||
|
||||
if (m_dumpTAData) {
|
||||
|
@ -710,7 +672,7 @@ bool CDMRSlot::writeModem(unsigned char *data, unsigned int len)
|
|||
if (!(m_rfTalkerId & TALKER_ID_BLOCK2)) {
|
||||
if (m_rfTalkerId == TALKER_ID_NONE)
|
||||
m_rfTalkerAlias.reset();
|
||||
m_rfTalkerAlias.add(2, data + 2U, 7U);
|
||||
m_rfTalkerAlias.add(2, data, 7U);
|
||||
m_display->writeDMRTA(m_slotNo, (unsigned char*)m_rfTalkerAlias.get(), "R");
|
||||
|
||||
if (m_dumpTAData) {
|
||||
|
@ -729,7 +691,7 @@ bool CDMRSlot::writeModem(unsigned char *data, unsigned int len)
|
|||
if (!(m_rfTalkerId & TALKER_ID_BLOCK3)) {
|
||||
if (m_rfTalkerId == TALKER_ID_NONE)
|
||||
m_rfTalkerAlias.reset();
|
||||
m_rfTalkerAlias.add(3, data + 2U, 7U);
|
||||
m_rfTalkerAlias.add(3, data, 7U);
|
||||
m_display->writeDMRTA(m_slotNo, (unsigned char*)m_rfTalkerAlias.get(), "R");
|
||||
|
||||
if (m_dumpTAData) {
|
||||
|
@ -801,22 +763,15 @@ bool CDMRSlot::writeModem(unsigned char *data, unsigned int len)
|
|||
if (!CDMRAccessControl::validateSrcId(srcId)) {
|
||||
LogMessage("DMR Slot %u, RF user %u rejected", m_slotNo, srcId);
|
||||
delete lc;
|
||||
m_rfState = RS_RF_LISTENING;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!CDMRAccessControl::validateTGId(m_slotNo, flco == FLCO_GROUP, dstId)) {
|
||||
LogMessage("DMR Slot %u, RF user %u rejected for using TG %u", m_slotNo, srcId, dstId);
|
||||
delete lc;
|
||||
m_rfState = RS_RF_LISTENING;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (m_ovcm == DMR_OVCM_TX_ON || m_ovcm == DMR_OVCM_ON)
|
||||
lc->setOVCM(true);
|
||||
else if (m_ovcm == DMR_OVCM_FORCE_OFF)
|
||||
lc->setOVCM(false);
|
||||
|
||||
m_rfLC = lc;
|
||||
|
||||
// The standby LC data
|
||||
|
@ -1072,11 +1027,6 @@ void CDMRSlot::writeNetwork(const CDMRData& dmrData)
|
|||
dmrData.getSrcId(), dmrData.getFLCO() == FLCO_GROUP ? "TG" : "", dmrData.getDstId(),
|
||||
srcId, flco == FLCO_GROUP ? "TG" : "", dstId);
|
||||
|
||||
if (m_ovcm == DMR_OVCM_RX_ON || m_ovcm == DMR_OVCM_ON)
|
||||
lc->setOVCM(true);
|
||||
else if (m_ovcm == DMR_OVCM_FORCE_OFF)
|
||||
lc->setOVCM(false);
|
||||
|
||||
m_netLC = lc;
|
||||
|
||||
// The standby LC data
|
||||
|
@ -1134,8 +1084,7 @@ void CDMRSlot::writeNetwork(const CDMRData& dmrData)
|
|||
setShortLC(m_slotNo, dstId, flco, ACTIVITY_VOICE);
|
||||
std::string src = m_lookup->find(srcId);
|
||||
std::string dst = m_lookup->find(dstId);
|
||||
class CUserDBentry cn;
|
||||
m_lookup->findWithName(srcId, &cn);
|
||||
std::string cn = m_lookup->findWithName(srcId);
|
||||
m_display->writeDMR(m_slotNo, cn, flco == FLCO_GROUP, dst, "N");
|
||||
|
||||
#if defined(DUMP_DMR)
|
||||
|
@ -1151,11 +1100,6 @@ void CDMRSlot::writeNetwork(const CDMRData& dmrData)
|
|||
unsigned int dstId = lc->getDstId();
|
||||
unsigned int srcId = lc->getSrcId();
|
||||
|
||||
if (m_ovcm == DMR_OVCM_RX_ON || m_ovcm == DMR_OVCM_ON)
|
||||
lc->setOVCM(true);
|
||||
else if (m_ovcm == DMR_OVCM_FORCE_OFF)
|
||||
lc->setOVCM(false);
|
||||
|
||||
m_netLC = lc;
|
||||
|
||||
m_lastFrameValid = false;
|
||||
|
@ -1206,12 +1150,11 @@ void CDMRSlot::writeNetwork(const CDMRData& dmrData)
|
|||
m_netState = RS_NET_AUDIO;
|
||||
|
||||
setShortLC(m_slotNo, dstId, m_netLC->getFLCO(), ACTIVITY_VOICE);
|
||||
|
||||
std::string src = m_lookup->find(srcId);
|
||||
std::string dst = m_lookup->find(dstId);
|
||||
class CUserDBentry cn;
|
||||
m_lookup->findWithName(srcId, &cn);
|
||||
|
||||
m_display->writeDMR(m_slotNo, cn, m_netLC->getFLCO() == FLCO_GROUP, dst, "N");
|
||||
m_display->writeDMR(m_slotNo, src, m_netLC->getFLCO() == FLCO_GROUP, dst, "N");
|
||||
|
||||
LogMessage("DMR Slot %u, received network late entry from %s to %s%s", m_slotNo, src.c_str(), m_netLC->getFLCO() == FLCO_GROUP ? "TG " : "", dst.c_str());
|
||||
}
|
||||
|
@ -1273,13 +1216,9 @@ void CDMRSlot::writeNetwork(const CDMRData& dmrData)
|
|||
writeFile(data);
|
||||
closeFile();
|
||||
#endif
|
||||
std::string src = m_lookup->find(m_netLC->getSrcId());
|
||||
std::string dst = m_lookup->find(m_netLC->getDstId());
|
||||
FLCO flco = m_netLC->getFLCO();
|
||||
|
||||
// We've received the voice header and terminator haven't we?
|
||||
m_netFrames += 2U;
|
||||
LogMessage("DMR Slot %u, received network end of voice transmission from %s to %s%s, %.1f seconds, %u%% packet loss, BER: %.1f%%", m_slotNo, src.c_str(), flco == FLCO_GROUP ? "TG " : "", dst.c_str(), float(m_netFrames) / 16.667F, (m_netLost * 100U) / m_netFrames, float(m_netErrs * 100U) / float(m_netBits));
|
||||
LogMessage("DMR Slot %u, received network end of voice transmission, %.1f seconds, %u%% packet loss, BER: %.1f%%", m_slotNo, float(m_netFrames) / 16.667F, (m_netLost * 100U) / m_netFrames, float(m_netErrs * 100U) / float(m_netBits));
|
||||
m_display->writeDMRTA(m_slotNo, NULL, " ");
|
||||
writeEndNet();
|
||||
} else if (dataType == DT_DATA_HEADER) {
|
||||
|
@ -1332,7 +1271,7 @@ void CDMRSlot::writeNetwork(const CDMRData& dmrData)
|
|||
LogMessage("DMR Slot %u, received network data header from %s to %s%s, %u blocks", m_slotNo, src.c_str(), gi ? "TG ": "", dst.c_str(), m_netFrames);
|
||||
|
||||
if (m_netFrames == 0U) {
|
||||
LogMessage("DMR Slot %u, ended network data transmission from %s to %s%s", m_slotNo, src.c_str(), gi ? "TG " : "", dst.c_str());
|
||||
LogMessage("DMR Slot %u, ended network data transmission", m_slotNo);
|
||||
writeEndNet();
|
||||
}
|
||||
} else if (dataType == DT_VOICE_SYNC) {
|
||||
|
@ -1342,11 +1281,6 @@ void CDMRSlot::writeNetwork(const CDMRData& dmrData)
|
|||
unsigned int dstId = lc->getDstId();
|
||||
unsigned int srcId = lc->getSrcId();
|
||||
|
||||
if (m_ovcm == DMR_OVCM_RX_ON || m_ovcm == DMR_OVCM_ON)
|
||||
lc->setOVCM(true);
|
||||
else if (m_ovcm == DMR_OVCM_FORCE_OFF)
|
||||
lc->setOVCM(false);
|
||||
|
||||
m_netLC = lc;
|
||||
|
||||
// The standby LC data
|
||||
|
@ -1409,10 +1343,8 @@ void CDMRSlot::writeNetwork(const CDMRData& dmrData)
|
|||
|
||||
std::string src = m_lookup->find(srcId);
|
||||
std::string dst = m_lookup->find(dstId);
|
||||
class CUserDBentry cn;
|
||||
m_lookup->findWithName(srcId, &cn);
|
||||
|
||||
m_display->writeDMR(m_slotNo, cn, m_netLC->getFLCO() == FLCO_GROUP, dst, "N");
|
||||
m_display->writeDMR(m_slotNo, src, m_netLC->getFLCO() == FLCO_GROUP, dst, "N");
|
||||
|
||||
LogMessage("DMR Slot %u, received network late entry from %s to %s%s", m_slotNo, src.c_str(), m_netLC->getFLCO() == FLCO_GROUP ? "TG " : "", dst.c_str());
|
||||
}
|
||||
|
@ -1617,12 +1549,6 @@ void CDMRSlot::writeNetwork(const CDMRData& dmrData)
|
|||
if (csbko == CSBKO_BSDWNACT)
|
||||
return;
|
||||
|
||||
// set the OVCM bit for the supported csbk
|
||||
if (m_ovcm == DMR_OVCM_RX_ON || m_ovcm == DMR_OVCM_ON)
|
||||
csbk.setOVCM(true);
|
||||
else if (m_ovcm == DMR_OVCM_FORCE_OFF)
|
||||
csbk.setOVCM(false);
|
||||
|
||||
bool gi = csbk.getGI();
|
||||
unsigned int srcId = csbk.getSrcId();
|
||||
unsigned int dstId = csbk.getDstId();
|
||||
|
@ -1687,15 +1613,6 @@ void CDMRSlot::writeNetwork(const CDMRData& dmrData)
|
|||
case CSBKO_PRECCSBK:
|
||||
LogMessage("DMR Slot %u, received network %s Preamble CSBK (%u to follow) from %s to %s%s", m_slotNo, csbk.getDataContent() ? "Data" : "CSBK", csbk.getCBF(), src.c_str(), gi ? "TG " : "", dst.c_str());
|
||||
break;
|
||||
case CSBKO_CALL_ALERT:
|
||||
LogMessage("DMR Slot %u, received network Call Alert CSBK from %s to %s%s", m_slotNo, src.c_str(), gi ? "TG " : "", dst.c_str());
|
||||
break;
|
||||
case CSBKO_CALL_ALERT_ACK:
|
||||
LogMessage("DMR Slot %u, received network Call Alert Ack CSBK from %s to %s%s", m_slotNo, src.c_str(), gi ? "TG " : "", dst.c_str());
|
||||
break;
|
||||
case CSBKO_RADIO_CHECK:
|
||||
LogMessage("DMR Slot %u, received network Radio Check %s CSBK from %s to %s%s", m_slotNo, /* TBD */ 1 ? "Req" : "Ack", src.c_str(), gi ? "TG " : "", dst.c_str());
|
||||
break;
|
||||
default:
|
||||
LogWarning("DMR Slot %u, unhandled network CSBK type - 0x%02X", m_slotNo, csbko);
|
||||
break;
|
||||
|
@ -1936,7 +1853,7 @@ void CDMRSlot::writeQueueNet(const unsigned char *data)
|
|||
m_queue.addData(data, len);
|
||||
}
|
||||
|
||||
void CDMRSlot::init(unsigned int colorCode, bool embeddedLCOnly, bool dumpTAData, unsigned int callHang, CModem* modem, IDMRNetwork* network, CDisplay* display, bool duplex, CDMRLookup* lookup, CRSSIInterpolator* rssiMapper, unsigned int jitter, DMR_OVCM_TYPES ovcm)
|
||||
void CDMRSlot::init(unsigned int colorCode, bool embeddedLCOnly, bool dumpTAData, unsigned int callHang, CModem* modem, CDMRNetwork* network, CDisplay* display, bool duplex, CDMRLookup* lookup, CRSSIInterpolator* rssiMapper, unsigned int jitter)
|
||||
{
|
||||
assert(modem != NULL);
|
||||
assert(display != NULL);
|
||||
|
@ -1952,7 +1869,6 @@ void CDMRSlot::init(unsigned int colorCode, bool embeddedLCOnly, bool dumpTAData
|
|||
m_duplex = duplex;
|
||||
m_lookup = lookup;
|
||||
m_hangCount = callHang * 17U;
|
||||
m_ovcm = ovcm;
|
||||
|
||||
m_rssiMapper = rssiMapper;
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2015-2021 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2015-2019 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
@ -62,7 +62,7 @@ public:
|
|||
|
||||
void enable(bool enabled);
|
||||
|
||||
static void init(unsigned int colorCode, bool embeddedLCOnly, bool dumpTAData, unsigned int callHang, CModem* modem, IDMRNetwork* network, CDisplay* display, bool duplex, CDMRLookup* lookup, CRSSIInterpolator* rssiMapper, unsigned int jitter, DMR_OVCM_TYPES ovcm);
|
||||
static void init(unsigned int colorCode, bool embeddedLCOnly, bool dumpTAData, unsigned int callHang, CModem* modem, CDMRNetwork* network, CDisplay* display, bool duplex, CDMRLookup* lookup, CRSSIInterpolator* rssiMapper, unsigned int jitter);
|
||||
|
||||
private:
|
||||
unsigned int m_slotNo;
|
||||
|
@ -118,12 +118,11 @@ private:
|
|||
static bool m_dumpTAData;
|
||||
|
||||
static CModem* m_modem;
|
||||
static IDMRNetwork* m_network;
|
||||
static CDMRNetwork* m_network;
|
||||
static CDisplay* m_display;
|
||||
static bool m_duplex;
|
||||
static CDMRLookup* m_lookup;
|
||||
static unsigned int m_hangCount;
|
||||
static DMR_OVCM_TYPES m_ovcm;
|
||||
|
||||
static CRSSIInterpolator* m_rssiMapper;
|
||||
|
||||
|
|
|
@ -72,7 +72,7 @@ bool CDMRTA::decodeTA()
|
|||
|
||||
unsigned int TAformat = (talkerAlias[0] >> 6U) & 0x03U;
|
||||
unsigned int TAsize = (talkerAlias[0] >> 1U) & 0x1FU;
|
||||
::strcpy(m_TA, "(could not decode)");
|
||||
::strncpy(m_TA, "(could not decode)", sizeof(m_TA));
|
||||
|
||||
switch (TAformat) {
|
||||
case 0U: // 7 bit
|
||||
|
@ -96,7 +96,7 @@ bool CDMRTA::decodeTA()
|
|||
|
||||
case 1U: // ISO 8 bit
|
||||
case 2U: // UTF8
|
||||
::memcpy(m_TA, talkerAlias + 1U, sizeof(m_TA));
|
||||
::strncpy(m_TA, (char*)talkerAlias + 1U, sizeof(m_TA));
|
||||
break;
|
||||
|
||||
case 3U: // UTF16 poor man's conversion
|
||||
|
@ -117,9 +117,9 @@ bool CDMRTA::decodeTA()
|
|||
|
||||
if (TAlen > TAsize) {
|
||||
if (TAlen < 29U)
|
||||
strcat(m_TA, " ?");
|
||||
strcat(m_TA," ?");
|
||||
else
|
||||
strcpy(m_TA + 28U, " ?");
|
||||
strcpy(m_TA + 28U," ?");
|
||||
}
|
||||
|
||||
return TAlen >= TAsize;
|
||||
|
|
32
DMRplus_startup_options.md
Normal file
32
DMRplus_startup_options.md
Normal file
|
@ -0,0 +1,32 @@
|
|||
# DMRplus - Startup Options
|
||||
|
||||
## Introduction
|
||||
This file is to give an overview over the Options-parameter in MMDVM.ini [DMR Network]-section.
|
||||
|
||||
## Example
|
||||
You can pull some conection-info at startup to the DMRplus-Network to define the behavior of TS1 and TS2 in DMR-mode.
|
||||
An example of such a line would be following:
|
||||
|
||||
Options=StartRef=4013;RelinkTime=15;UserLink=1;TS1_1=262;TS1_2=1;TS1_3=20;TS1_4=110;TS1_5=270;
|
||||
|
||||
If an option is set, it overwrites the setting preset at the master, if an option is empty, it unsets a predefined setting from
|
||||
the master. If an option is not set, the default from the master would be taken over.
|
||||
|
||||
## What the parameters are about?
|
||||
|
||||
Here is a quick explaination about the options to be set:
|
||||
|
||||
* StartRef: This is the default reflector in TS2, in example: Refl. 4013
|
||||
* RelinkTime: This is the time to fall back to the default-reflector if linked to another one and no local traffic is done,
|
||||
not yet implemented, would come next
|
||||
* UserLink: This defines, if users are allowed to link to another reflector (other than defined as startreflector)
|
||||
* 1 = allow
|
||||
* 0 = disallow
|
||||
* TS1_1: This is the first of 5 talkgroups that could be set static, in example: TG262
|
||||
* TS1_2: This is the second of 5 talkgroups that could be set static, in example: TG1
|
||||
* TS1_3: This is the third of 5 talkgroups that could be set static, in example: TG20
|
||||
* TS1_4: This is the fourth of 5 talkgroups that could be set static, in example: TG110
|
||||
* TS1_5: This is the fifth of 5 talkgroups that could be set static, in example: TG270
|
||||
|
||||
---
|
||||
Info created by DG9VH 2016-11-11
|
1245
DStarControl.cpp
Normal file
1245
DStarControl.cpp
Normal file
File diff suppressed because it is too large
Load diff
128
DStarControl.h
Normal file
128
DStarControl.h
Normal file
|
@ -0,0 +1,128 @@
|
|||
/*
|
||||
* Copyright (C) 2015-2019 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* 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(DStarControl_H)
|
||||
#define DStarControl_H
|
||||
|
||||
#include "RSSIInterpolator.h"
|
||||
#include "DStarNetwork.h"
|
||||
#include "DStarSlowData.h"
|
||||
#include "DStarDefines.h"
|
||||
#include "DStarHeader.h"
|
||||
#include "RingBuffer.h"
|
||||
#include "StopWatch.h"
|
||||
#include "AMBEFEC.h"
|
||||
#include "Display.h"
|
||||
#include "Defines.h"
|
||||
#include "Timer.h"
|
||||
#include "Modem.h"
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
class CDStarControl {
|
||||
public:
|
||||
CDStarControl(const std::string& callsign, const std::string& module, bool selfOnly, bool ackReply, unsigned int ackTime, bool ackMessage, bool errorReply, const std::vector<std::string>& blackList, CDStarNetwork* network, CDisplay* display, unsigned int timeout, bool duplex, bool remoteGateway, CRSSIInterpolator* rssiMapper);
|
||||
~CDStarControl();
|
||||
|
||||
bool writeModem(unsigned char* data, unsigned int len);
|
||||
|
||||
unsigned int readModem(unsigned char* data);
|
||||
|
||||
void clock();
|
||||
|
||||
bool isBusy() const;
|
||||
|
||||
void enable(bool enabled);
|
||||
|
||||
private:
|
||||
unsigned char* m_callsign;
|
||||
unsigned char* m_gateway;
|
||||
bool m_selfOnly;
|
||||
bool m_ackReply;
|
||||
bool m_ackMessage;
|
||||
bool m_errorReply;
|
||||
bool m_remoteGateway;
|
||||
std::vector<std::string> m_blackList;
|
||||
CDStarNetwork* m_network;
|
||||
CDisplay* m_display;
|
||||
bool m_duplex;
|
||||
CRingBuffer<unsigned char> m_queue;
|
||||
CDStarHeader m_rfHeader;
|
||||
CDStarHeader m_netHeader;
|
||||
RPT_RF_STATE m_rfState;
|
||||
RPT_NET_STATE m_netState;
|
||||
bool m_net;
|
||||
CDStarSlowData m_slowData;
|
||||
unsigned char m_rfN;
|
||||
unsigned char m_netN;
|
||||
CTimer m_networkWatchdog;
|
||||
CTimer m_rfTimeoutTimer;
|
||||
CTimer m_netTimeoutTimer;
|
||||
CTimer m_packetTimer;
|
||||
CTimer m_ackTimer;
|
||||
CTimer m_errTimer;
|
||||
CStopWatch m_interval;
|
||||
CStopWatch m_elapsed;
|
||||
unsigned int m_rfFrames;
|
||||
unsigned int m_netFrames;
|
||||
unsigned int m_netLost;
|
||||
CAMBEFEC m_fec;
|
||||
unsigned int m_rfBits;
|
||||
unsigned int m_netBits;
|
||||
unsigned int m_rfErrs;
|
||||
unsigned int m_netErrs;
|
||||
unsigned char* m_lastFrame;
|
||||
bool m_lastFrameValid;
|
||||
CRSSIInterpolator* m_rssiMapper;
|
||||
unsigned char m_rssi;
|
||||
unsigned char m_maxRSSI;
|
||||
unsigned char m_minRSSI;
|
||||
unsigned int m_aveRSSI;
|
||||
unsigned int m_rssiCount;
|
||||
bool m_enabled;
|
||||
FILE* m_fp;
|
||||
|
||||
void writeNetwork();
|
||||
|
||||
void writeQueueHeaderRF(const unsigned char* data);
|
||||
void writeQueueDataRF(const unsigned char* data);
|
||||
void writeQueueEOTRF();
|
||||
void writeQueueHeaderNet(const unsigned char* data);
|
||||
void writeQueueDataNet(const unsigned char* data);
|
||||
void writeQueueEOTNet();
|
||||
void writeNetworkHeaderRF(const unsigned char* data);
|
||||
void writeNetworkDataRF(const unsigned char* data, unsigned int errors, bool end);
|
||||
|
||||
void writeEndRF();
|
||||
void writeEndNet();
|
||||
|
||||
bool openFile();
|
||||
bool writeFile(const unsigned char* data, unsigned int length);
|
||||
void closeFile();
|
||||
|
||||
bool insertSilence(const unsigned char* data, unsigned char seqNo);
|
||||
void insertSilence(unsigned int count);
|
||||
|
||||
void blankDTMF(unsigned char* data) const;
|
||||
|
||||
void sendAck();
|
||||
void sendError();
|
||||
};
|
||||
|
||||
#endif
|
92
DStarDefines.h
Normal file
92
DStarDefines.h
Normal file
|
@ -0,0 +1,92 @@
|
|||
/*
|
||||
* Copyright (C) 2015,2016,2018,2019 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* 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(DStarDefines_H)
|
||||
#define DStarDefines_H
|
||||
|
||||
#include "Defines.h"
|
||||
|
||||
const unsigned int DSTAR_HEADER_LENGTH_BYTES = 41U;
|
||||
const unsigned int DSTAR_FRAME_LENGTH_BYTES = 12U;
|
||||
|
||||
const unsigned char DSTAR_END_PATTERN_BYTES[] = { TAG_EOT, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0xC8, 0x7A };
|
||||
const unsigned int DSTAR_END_PATTERN_LENGTH_BYTES = 6U;
|
||||
|
||||
const unsigned char DSTAR_NULL_AMBE_DATA_BYTES[] = { 0x9E, 0x8D, 0x32, 0x88, 0x26, 0x1A, 0x3F, 0x61, 0xE8 };
|
||||
|
||||
const unsigned char DSTAR_NULL_SLOW_SYNC_BYTES[] = { 0x55, 0x2D, 0x16 };
|
||||
// Note that these are already scrambled, 0x66 0x66 0x66 otherwise
|
||||
const unsigned char DSTAR_NULL_SLOW_DATA_BYTES[] = { 0x16, 0x29, 0xF5 };
|
||||
|
||||
const unsigned char DSTAR_NULL_FRAME_SYNC_BYTES[] = { TAG_DATA, 0x9E, 0x8D, 0x32, 0x88, 0x26, 0x1A, 0x3F, 0x61, 0xE8, 0x55, 0x2D, 0x16 };
|
||||
const unsigned char DSTAR_NULL_FRAME_DATA_BYTES[] = { TAG_DATA, 0x9E, 0x8D, 0x32, 0x88, 0x26, 0x1A, 0x3F, 0x61, 0xE8, 0x16, 0x29, 0xF5 };
|
||||
|
||||
const unsigned char DSTAR_NULL_FRAME_DATA_SRAMBLED_BYTES[] = { 0xEEU, 0xC2U, 0xA1U, 0xC8U, 0x42U, 0x6EU, 0x52U, 0x51U, 0xC3U };
|
||||
|
||||
const unsigned int DSTAR_VOICE_FRAME_LENGTH_BYTES = 9U;
|
||||
const unsigned int DSTAR_DATA_FRAME_LENGTH_BYTES = 3U;
|
||||
|
||||
const unsigned int DSTAR_LONG_CALLSIGN_LENGTH = 8U;
|
||||
const unsigned int DSTAR_SHORT_CALLSIGN_LENGTH = 4U;
|
||||
|
||||
const unsigned char DSTAR_SLOW_DATA_TYPE_MASK = 0xF0U;
|
||||
const unsigned char DSTAR_SLOW_DATA_TYPE_GPSDATA = 0x30U;
|
||||
const unsigned char DSTAR_SLOW_DATA_TYPE_TEXT = 0x40U;
|
||||
const unsigned char DSTAR_SLOW_DATA_TYPE_HEADER = 0x50U;
|
||||
const unsigned char DSTAR_SLOW_DATA_TYPE_FAST_DATA1 = 0x80U;
|
||||
const unsigned char DSTAR_SLOW_DATA_TYPE_FAST_DATA2 = 0x90U;
|
||||
const unsigned char DSTAR_SLOW_DATA_TYPE_SQUELCH = 0xC0U;
|
||||
const unsigned char DSTAR_SLOW_DATA_LENGTH_MASK = 0x0FU;
|
||||
|
||||
const unsigned char DSTAR_SCRAMBLER_BYTES[] = { 0x70U, 0x4FU, 0x93U, 0x40U, 0x64U, 0x74U, 0x6DU, 0x30U, 0x2BU };
|
||||
|
||||
const unsigned char DSTAR_DATA_MASK = 0x80U;
|
||||
const unsigned char DSTAR_REPEATER_MASK = 0x40U;
|
||||
const unsigned char DSTAR_INTERRUPTED_MASK = 0x20U;
|
||||
const unsigned char DSTAR_CONTROL_SIGNAL_MASK = 0x10U;
|
||||
const unsigned char DSTAR_URGENT_MASK = 0x08U;
|
||||
const unsigned char DSTAR_REPEATER_CONTROL = 0x07U;
|
||||
const unsigned char DSTAR_AUTO_REPLY = 0x06U;
|
||||
const unsigned char DSTAR_RESEND_REQUESTED = 0x04U;
|
||||
const unsigned char DSTAR_ACK_FLAG = 0x03U;
|
||||
const unsigned char DSTAR_NO_RESPONSE = 0x02U;
|
||||
const unsigned char DSTAR_RELAY_UNAVAILABLE = 0x01U;
|
||||
|
||||
const unsigned char DSTAR_SYNC_BYTES[] = {0x55U, 0x2DU, 0x16U};
|
||||
|
||||
const unsigned char DSTAR_DTMF_MASK[] = { 0x82U, 0x08U, 0x20U, 0x82U, 0x00U, 0x00U, 0x82U, 0x00U, 0x00U };
|
||||
const unsigned char DSTAR_DTMF_SIG[] = { 0x82U, 0x08U, 0x20U, 0x82U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U };
|
||||
|
||||
const unsigned int DSTAR_FRAME_TIME = 20U;
|
||||
|
||||
enum LINK_STATUS {
|
||||
LS_NONE,
|
||||
LS_PENDING_IRCDDB,
|
||||
LS_LINKING_LOOPBACK,
|
||||
LS_LINKING_DEXTRA,
|
||||
LS_LINKING_DPLUS,
|
||||
LS_LINKING_DCS,
|
||||
LS_LINKING_CCS,
|
||||
LS_LINKED_LOOPBACK,
|
||||
LS_LINKED_DEXTRA,
|
||||
LS_LINKED_DPLUS,
|
||||
LS_LINKED_DCS,
|
||||
LS_LINKED_CCS
|
||||
};
|
||||
|
||||
#endif
|
165
DStarHeader.cpp
Normal file
165
DStarHeader.cpp
Normal file
|
@ -0,0 +1,165 @@
|
|||
/*
|
||||
* Copyright (C) 2016 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* 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 "DStarDefines.h"
|
||||
#include "DStarHeader.h"
|
||||
#include "CRC.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
|
||||
CDStarHeader::CDStarHeader(const unsigned char* header) :
|
||||
m_header(NULL)
|
||||
{
|
||||
assert(header != NULL);
|
||||
|
||||
m_header = new unsigned char[DSTAR_HEADER_LENGTH_BYTES];
|
||||
|
||||
::memcpy(m_header, header, DSTAR_HEADER_LENGTH_BYTES);
|
||||
}
|
||||
|
||||
CDStarHeader::CDStarHeader() :
|
||||
m_header(NULL)
|
||||
{
|
||||
m_header = new unsigned char[DSTAR_HEADER_LENGTH_BYTES];
|
||||
|
||||
::memset(m_header, ' ', DSTAR_HEADER_LENGTH_BYTES);
|
||||
|
||||
m_header[0U] = 0x00U;
|
||||
m_header[1U] = 0x00U;
|
||||
m_header[2U] = 0x00U;
|
||||
}
|
||||
|
||||
CDStarHeader::~CDStarHeader()
|
||||
{
|
||||
delete[] m_header;
|
||||
}
|
||||
|
||||
CDStarHeader& CDStarHeader::operator=(const CDStarHeader& header)
|
||||
{
|
||||
if (&header != this)
|
||||
::memcpy(m_header, header.m_header, DSTAR_HEADER_LENGTH_BYTES);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool CDStarHeader::isRepeater() const
|
||||
{
|
||||
return (m_header[0U] & DSTAR_REPEATER_MASK) == DSTAR_REPEATER_MASK;
|
||||
}
|
||||
|
||||
void CDStarHeader::setRepeater(bool on)
|
||||
{
|
||||
if (on)
|
||||
m_header[0U] |= DSTAR_REPEATER_MASK;
|
||||
else
|
||||
m_header[0U] &= ~DSTAR_REPEATER_MASK;
|
||||
}
|
||||
|
||||
bool CDStarHeader::isDataPacket() const
|
||||
{
|
||||
return (m_header[0U] & DSTAR_DATA_MASK) == DSTAR_DATA_MASK;
|
||||
}
|
||||
|
||||
void CDStarHeader::setUnavailable(bool on)
|
||||
{
|
||||
if (on)
|
||||
m_header[0U] |= DSTAR_RELAY_UNAVAILABLE;
|
||||
else
|
||||
m_header[0U] &= ~DSTAR_RELAY_UNAVAILABLE;
|
||||
}
|
||||
|
||||
void CDStarHeader::getMyCall1(unsigned char* call1) const
|
||||
{
|
||||
assert(call1 != NULL);
|
||||
|
||||
::memcpy(call1, m_header + 27U, DSTAR_LONG_CALLSIGN_LENGTH);
|
||||
}
|
||||
|
||||
void CDStarHeader::getMyCall2(unsigned char* call2) const
|
||||
{
|
||||
assert(call2 != NULL);
|
||||
|
||||
::memcpy(call2, m_header + 35U, DSTAR_SHORT_CALLSIGN_LENGTH);
|
||||
}
|
||||
|
||||
void CDStarHeader::setMyCall1(const unsigned char* call1)
|
||||
{
|
||||
assert(call1 != NULL);
|
||||
|
||||
::memcpy(m_header + 27U, call1, DSTAR_LONG_CALLSIGN_LENGTH);
|
||||
}
|
||||
|
||||
void CDStarHeader::setMyCall2(const unsigned char* call2)
|
||||
{
|
||||
assert(call2 != NULL);
|
||||
|
||||
::memcpy(m_header + 35U, call2, DSTAR_SHORT_CALLSIGN_LENGTH);
|
||||
}
|
||||
|
||||
void CDStarHeader::getRPTCall1(unsigned char* call1) const
|
||||
{
|
||||
assert(call1 != NULL);
|
||||
|
||||
::memcpy(call1, m_header + 11U, DSTAR_LONG_CALLSIGN_LENGTH);
|
||||
}
|
||||
|
||||
void CDStarHeader::getRPTCall2(unsigned char* call2) const
|
||||
{
|
||||
assert(call2 != NULL);
|
||||
|
||||
::memcpy(call2, m_header + 3U, DSTAR_LONG_CALLSIGN_LENGTH);
|
||||
}
|
||||
|
||||
void CDStarHeader::setRPTCall1(const unsigned char* call1)
|
||||
{
|
||||
assert(call1 != NULL);
|
||||
|
||||
::memcpy(m_header + 11U, call1, DSTAR_LONG_CALLSIGN_LENGTH);
|
||||
}
|
||||
|
||||
void CDStarHeader::setRPTCall2(const unsigned char* call2)
|
||||
{
|
||||
assert(call2 != NULL);
|
||||
|
||||
::memcpy(m_header + 3U, call2, DSTAR_LONG_CALLSIGN_LENGTH);
|
||||
}
|
||||
|
||||
void CDStarHeader::getYourCall(unsigned char* call) const
|
||||
{
|
||||
assert(call != NULL);
|
||||
|
||||
::memcpy(call, m_header + 19U, DSTAR_LONG_CALLSIGN_LENGTH);
|
||||
}
|
||||
|
||||
void CDStarHeader::setYourCall(const unsigned char* call)
|
||||
{
|
||||
assert(call != NULL);
|
||||
|
||||
::memcpy(m_header + 19U, call, DSTAR_LONG_CALLSIGN_LENGTH);
|
||||
}
|
||||
|
||||
void CDStarHeader::get(unsigned char* header) const
|
||||
{
|
||||
assert(header != NULL);
|
||||
|
||||
::memcpy(header, m_header, DSTAR_HEADER_LENGTH_BYTES);
|
||||
|
||||
CCRC::addCCITT161(header, DSTAR_HEADER_LENGTH_BYTES);
|
||||
}
|
58
DStarHeader.h
Normal file
58
DStarHeader.h
Normal file
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
* Copyright (C) 2016 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* 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 DStarHeader_H
|
||||
#define DStarHeader_H
|
||||
|
||||
class CDStarHeader {
|
||||
public:
|
||||
CDStarHeader(const unsigned char* header);
|
||||
CDStarHeader();
|
||||
~CDStarHeader();
|
||||
|
||||
bool isRepeater() const;
|
||||
void setRepeater(bool on);
|
||||
|
||||
bool isDataPacket() const;
|
||||
|
||||
void setUnavailable(bool on);
|
||||
|
||||
void getMyCall1(unsigned char* call1) const;
|
||||
void getMyCall2(unsigned char* call2) const;
|
||||
|
||||
void setMyCall1(const unsigned char* call1);
|
||||
void setMyCall2(const unsigned char* call2);
|
||||
|
||||
void getRPTCall1(unsigned char* call1) const;
|
||||
void getRPTCall2(unsigned char* call2) const;
|
||||
|
||||
void setRPTCall1(const unsigned char* call1);
|
||||
void setRPTCall2(const unsigned char* call2);
|
||||
|
||||
void getYourCall(unsigned char* call) const;
|
||||
void setYourCall(const unsigned char* call);
|
||||
|
||||
void get(unsigned char* header) const;
|
||||
|
||||
CDStarHeader& operator=(const CDStarHeader& header);
|
||||
|
||||
private:
|
||||
unsigned char* m_header;
|
||||
};
|
||||
|
||||
#endif
|
336
DStarNetwork.cpp
Normal file
336
DStarNetwork.cpp
Normal file
|
@ -0,0 +1,336 @@
|
|||
/*
|
||||
* Copyright (C) 2009-2014,2016,2019 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* 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 "DStarDefines.h"
|
||||
#include "DStarNetwork.h"
|
||||
#include "StopWatch.h"
|
||||
#include "Defines.h"
|
||||
#include "Utils.h"
|
||||
#include "Log.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
#include <cstdlib>
|
||||
|
||||
const unsigned int BUFFER_LENGTH = 100U;
|
||||
|
||||
CDStarNetwork::CDStarNetwork(const std::string& gatewayAddress, unsigned int gatewayPort, unsigned int localPort, bool duplex, const char* version, bool debug) :
|
||||
m_socket(localPort),
|
||||
m_address(),
|
||||
m_port(gatewayPort),
|
||||
m_duplex(duplex),
|
||||
m_version(version),
|
||||
m_debug(debug),
|
||||
m_enabled(false),
|
||||
m_outId(0U),
|
||||
m_outSeq(0U),
|
||||
m_inId(0U),
|
||||
m_buffer(1000U, "D-Star Network"),
|
||||
m_pollTimer(1000U, 60U),
|
||||
m_linkStatus(LS_NONE),
|
||||
m_linkReflector(NULL)
|
||||
{
|
||||
m_address = CUDPSocket::lookup(gatewayAddress);
|
||||
|
||||
m_linkReflector = new unsigned char[DSTAR_LONG_CALLSIGN_LENGTH];
|
||||
|
||||
CStopWatch stopWatch;
|
||||
::srand(stopWatch.start());
|
||||
}
|
||||
|
||||
CDStarNetwork::~CDStarNetwork()
|
||||
{
|
||||
delete[] m_linkReflector;
|
||||
}
|
||||
|
||||
bool CDStarNetwork::open()
|
||||
{
|
||||
LogMessage("Opening D-Star network connection");
|
||||
|
||||
if (m_address.s_addr == INADDR_NONE)
|
||||
return false;
|
||||
|
||||
m_pollTimer.start();
|
||||
|
||||
return m_socket.open();
|
||||
}
|
||||
|
||||
bool CDStarNetwork::writeHeader(const unsigned char* header, unsigned int length, bool busy)
|
||||
{
|
||||
assert(header != NULL);
|
||||
|
||||
unsigned char buffer[50U];
|
||||
|
||||
buffer[0] = 'D';
|
||||
buffer[1] = 'S';
|
||||
buffer[2] = 'R';
|
||||
buffer[3] = 'P';
|
||||
|
||||
buffer[4] = busy ? 0x22U : 0x20U;
|
||||
|
||||
// Create a random id for this transmission
|
||||
m_outId = (::rand() % 65535U) + 1U;
|
||||
|
||||
buffer[5] = m_outId / 256U; // Unique session id
|
||||
buffer[6] = m_outId % 256U;
|
||||
|
||||
buffer[7] = 0U;
|
||||
|
||||
::memcpy(buffer + 8U, header, length);
|
||||
|
||||
m_outSeq = 0U;
|
||||
|
||||
if (m_debug)
|
||||
CUtils::dump(1U, "D-Star Network Header Sent", buffer, 49U);
|
||||
|
||||
for (unsigned int i = 0U; i < 2U; i++) {
|
||||
bool ret = m_socket.write(buffer, 49U, m_address, m_port);
|
||||
if (!ret)
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CDStarNetwork::writeData(const unsigned char* data, unsigned int length, unsigned int errors, bool end, bool busy)
|
||||
{
|
||||
assert(data != NULL);
|
||||
|
||||
unsigned char buffer[30U];
|
||||
|
||||
buffer[0] = 'D';
|
||||
buffer[1] = 'S';
|
||||
buffer[2] = 'R';
|
||||
buffer[3] = 'P';
|
||||
|
||||
buffer[4] = busy ? 0x23U : 0x21U;
|
||||
|
||||
buffer[5] = m_outId / 256U; // Unique session id
|
||||
buffer[6] = m_outId % 256U;
|
||||
|
||||
// If this is a data sync, reset the sequence to zero
|
||||
if (data[9] == 0x55 && data[10] == 0x2D && data[11] == 0x16)
|
||||
m_outSeq = 0U;
|
||||
|
||||
buffer[7] = m_outSeq;
|
||||
if (end)
|
||||
buffer[7] |= 0x40U; // End of data marker
|
||||
|
||||
buffer[8] = errors;
|
||||
|
||||
m_outSeq++;
|
||||
if (m_outSeq > 0x14U)
|
||||
m_outSeq = 0U;
|
||||
|
||||
::memcpy(buffer + 9U, data, length);
|
||||
|
||||
if (m_debug)
|
||||
CUtils::dump(1U, "D-Star Network Data Sent", buffer, length + 9U);
|
||||
|
||||
return m_socket.write(buffer, length + 9U, m_address, m_port);
|
||||
}
|
||||
|
||||
bool CDStarNetwork::writePoll(const char* text)
|
||||
{
|
||||
assert(text != NULL);
|
||||
|
||||
unsigned char buffer[40U];
|
||||
|
||||
buffer[0] = 'D';
|
||||
buffer[1] = 'S';
|
||||
buffer[2] = 'R';
|
||||
buffer[3] = 'P';
|
||||
|
||||
buffer[4] = 0x0A; // Poll with text
|
||||
|
||||
unsigned int length = ::strlen(text);
|
||||
|
||||
// Include the nul at the end also
|
||||
::memcpy(buffer + 5U, text, length + 1U);
|
||||
|
||||
// if (m_debug)
|
||||
// CUtils::dump(1U, "D-Star Network Poll Sent", buffer, 6U + length);
|
||||
|
||||
return m_socket.write(buffer, 6U + length, m_address, m_port);
|
||||
}
|
||||
|
||||
void CDStarNetwork::clock(unsigned int ms)
|
||||
{
|
||||
m_pollTimer.clock(ms);
|
||||
if (m_pollTimer.hasExpired()) {
|
||||
char text[60U];
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
if (m_duplex)
|
||||
::sprintf(text, "win_mmdvm-%s", m_version);
|
||||
else
|
||||
::sprintf(text, "win_mmdvm-dvmega-%s", m_version);
|
||||
#else
|
||||
if (m_duplex)
|
||||
::sprintf(text, "linux_mmdvm-%s", m_version);
|
||||
else
|
||||
::sprintf(text, "linux_mmdvm-dvmega-%s", m_version);
|
||||
#endif
|
||||
writePoll(text);
|
||||
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 || m_port != port) {
|
||||
LogMessage("D-Star packet received from an invalid source, %08X != %08X and/or %u != %u", m_address.s_addr, address.s_addr, m_port, port);
|
||||
return;
|
||||
}
|
||||
|
||||
// Invalid packet type?
|
||||
if (::memcmp(buffer, "DSRP", 4U) != 0)
|
||||
return;
|
||||
|
||||
switch (buffer[4]) {
|
||||
case 0x00U: // NETWORK_TEXT;
|
||||
if (m_debug)
|
||||
CUtils::dump(1U, "D-Star Network Status Received", buffer, length);
|
||||
|
||||
m_linkStatus = LINK_STATUS(buffer[25U]);
|
||||
::memcpy(m_linkReflector, buffer + 26U, DSTAR_LONG_CALLSIGN_LENGTH);
|
||||
LogMessage("D-Star link status set to \"%20.20s\"", buffer + 5U);
|
||||
return;
|
||||
|
||||
case 0x01U: // NETWORK_TEMPTEXT;
|
||||
case 0x04U: // NETWORK_STATUS1..5
|
||||
case 0x24U: // NETWORK_DD_DATA
|
||||
return;
|
||||
|
||||
case 0x20U: // NETWORK_HEADER
|
||||
if (m_inId == 0U && m_enabled) {
|
||||
if (m_debug)
|
||||
CUtils::dump(1U, "D-Star Network Header Received", buffer, length);
|
||||
|
||||
m_inId = buffer[5] * 256U + buffer[6];
|
||||
|
||||
unsigned char c = length - 7U;
|
||||
m_buffer.addData(&c, 1U);
|
||||
|
||||
c = TAG_HEADER;
|
||||
m_buffer.addData(&c, 1U);
|
||||
|
||||
m_buffer.addData(buffer + 8U, length - 8U);
|
||||
}
|
||||
break;
|
||||
|
||||
case 0x21U: // NETWORK_DATA
|
||||
if (m_enabled) {
|
||||
if (m_debug)
|
||||
CUtils::dump(1U, "D-Star Network Data Received", buffer, length);
|
||||
|
||||
uint16_t id = buffer[5] * 256U + buffer[6];
|
||||
|
||||
// Check that the stream id matches the valid header, reject otherwise
|
||||
if (id == m_inId && m_enabled) {
|
||||
unsigned char ctrl[3U];
|
||||
|
||||
ctrl[0U] = length - 7U;
|
||||
|
||||
// Is this the last packet in the stream?
|
||||
if ((buffer[7] & 0x40) == 0x40) {
|
||||
m_inId = 0U;
|
||||
ctrl[1U] = TAG_EOT;
|
||||
} else {
|
||||
ctrl[1U] = TAG_DATA;
|
||||
}
|
||||
|
||||
ctrl[2U] = buffer[7] & 0x3FU;
|
||||
|
||||
m_buffer.addData(ctrl, 3U);
|
||||
|
||||
m_buffer.addData(buffer + 9U, length - 9U);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
CUtils::dump("Unknown D-Star packet from the Gateway", buffer, length);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int CDStarNetwork::read(unsigned char* data, unsigned int length)
|
||||
{
|
||||
assert(data != NULL);
|
||||
|
||||
if (m_buffer.isEmpty())
|
||||
return 0U;
|
||||
|
||||
unsigned char c = 0U;
|
||||
m_buffer.getData(&c, 1U);
|
||||
|
||||
assert(c <= 100U);
|
||||
assert(c <= length);
|
||||
|
||||
unsigned char buffer[100U];
|
||||
m_buffer.getData(buffer, c);
|
||||
|
||||
switch (buffer[0U]) {
|
||||
case TAG_HEADER:
|
||||
case TAG_DATA:
|
||||
case TAG_EOT:
|
||||
::memcpy(data, buffer, c);
|
||||
return c;
|
||||
|
||||
default:
|
||||
return 0U;
|
||||
}
|
||||
}
|
||||
|
||||
void CDStarNetwork::reset()
|
||||
{
|
||||
m_inId = 0U;
|
||||
}
|
||||
|
||||
void CDStarNetwork::close()
|
||||
{
|
||||
m_socket.close();
|
||||
|
||||
LogMessage("Closing D-Star network connection");
|
||||
}
|
||||
|
||||
void CDStarNetwork::enable(bool enabled)
|
||||
{
|
||||
if (enabled && !m_enabled)
|
||||
reset();
|
||||
else if (!enabled && m_enabled)
|
||||
m_buffer.clear();
|
||||
|
||||
m_enabled = enabled;
|
||||
}
|
||||
|
||||
void CDStarNetwork::getStatus(LINK_STATUS& status, unsigned char* reflector)
|
||||
{
|
||||
assert(reflector != NULL);
|
||||
|
||||
status = m_linkStatus;
|
||||
|
||||
::memcpy(reflector, m_linkReflector, DSTAR_LONG_CALLSIGN_LENGTH);
|
||||
}
|
71
DStarNetwork.h
Normal file
71
DStarNetwork.h
Normal file
|
@ -0,0 +1,71 @@
|
|||
/*
|
||||
* Copyright (C) 2009-2014,2016 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* 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 DStarNetwork_H
|
||||
#define DStarNetwork_H
|
||||
|
||||
#include "DStarDefines.h"
|
||||
#include "RingBuffer.h"
|
||||
#include "UDPSocket.h"
|
||||
#include "Timer.h"
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
|
||||
class CDStarNetwork {
|
||||
public:
|
||||
CDStarNetwork(const std::string& gatewayAddress, unsigned int gatewayPort, unsigned int localPort, bool duplex, const char* version, bool debug);
|
||||
~CDStarNetwork();
|
||||
|
||||
bool open();
|
||||
|
||||
void enable(bool enabled);
|
||||
|
||||
bool writeHeader(const unsigned char* header, unsigned int length, bool busy);
|
||||
bool writeData(const unsigned char* data, unsigned int length, unsigned int errors, bool end, bool busy);
|
||||
|
||||
void getStatus(LINK_STATUS& status, unsigned char* reflector);
|
||||
|
||||
unsigned int read(unsigned char* data, unsigned int length);
|
||||
|
||||
void reset();
|
||||
|
||||
void close();
|
||||
|
||||
void clock(unsigned int ms);
|
||||
|
||||
private:
|
||||
CUDPSocket m_socket;
|
||||
in_addr m_address;
|
||||
unsigned int m_port;
|
||||
bool m_duplex;
|
||||
const char* m_version;
|
||||
bool m_debug;
|
||||
bool m_enabled;
|
||||
uint16_t m_outId;
|
||||
uint8_t m_outSeq;
|
||||
uint16_t m_inId;
|
||||
CRingBuffer<unsigned char> m_buffer;
|
||||
CTimer m_pollTimer;
|
||||
LINK_STATUS m_linkStatus;
|
||||
unsigned char* m_linkReflector;
|
||||
|
||||
bool writePoll(const char* text);
|
||||
};
|
||||
|
||||
#endif
|
158
DStarSlowData.cpp
Normal file
158
DStarSlowData.cpp
Normal file
|
@ -0,0 +1,158 @@
|
|||
/*
|
||||
* Copyright (C) 2016 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* 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 "DStarSlowData.h"
|
||||
#include "DStarDefines.h"
|
||||
#include "CRC.h"
|
||||
#include "Log.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
|
||||
CDStarSlowData::CDStarSlowData() :
|
||||
m_header(NULL),
|
||||
m_ptr(0U),
|
||||
m_buffer(NULL),
|
||||
m_text(NULL),
|
||||
m_textPtr(0U),
|
||||
m_state(SDD_FIRST)
|
||||
{
|
||||
m_header = new unsigned char[50U]; // DSTAR_HEADER_LENGTH_BYTES
|
||||
m_buffer = new unsigned char[DSTAR_DATA_FRAME_LENGTH_BYTES * 2U];
|
||||
m_text = new unsigned char[24U];
|
||||
}
|
||||
|
||||
CDStarSlowData::~CDStarSlowData()
|
||||
{
|
||||
delete[] m_header;
|
||||
delete[] m_buffer;
|
||||
delete[] m_text;
|
||||
}
|
||||
|
||||
CDStarHeader* CDStarSlowData::add(const unsigned char* data)
|
||||
{
|
||||
assert(data != NULL);
|
||||
|
||||
switch (m_state) {
|
||||
case SDD_FIRST:
|
||||
m_buffer[0U] = data[9U] ^ DSTAR_SCRAMBLER_BYTES[0U];
|
||||
m_buffer[1U] = data[10U] ^ DSTAR_SCRAMBLER_BYTES[1U];
|
||||
m_buffer[2U] = data[11U] ^ DSTAR_SCRAMBLER_BYTES[2U];
|
||||
m_state = SDD_SECOND;
|
||||
return NULL;
|
||||
|
||||
case SDD_SECOND:
|
||||
m_buffer[3U] = data[9U] ^ DSTAR_SCRAMBLER_BYTES[0U];
|
||||
m_buffer[4U] = data[10U] ^ DSTAR_SCRAMBLER_BYTES[1U];
|
||||
m_buffer[5U] = data[11U] ^ DSTAR_SCRAMBLER_BYTES[2U];
|
||||
m_state = SDD_FIRST;
|
||||
break;
|
||||
}
|
||||
|
||||
if ((m_buffer[0U] & DSTAR_SLOW_DATA_TYPE_MASK) != DSTAR_SLOW_DATA_TYPE_HEADER)
|
||||
return NULL;
|
||||
|
||||
if (m_ptr >= 45U)
|
||||
return NULL;
|
||||
|
||||
::memcpy(m_header + m_ptr, m_buffer + 1U, 5U);
|
||||
m_ptr += 5U;
|
||||
|
||||
// Clean up the data
|
||||
m_header[0U] &= (DSTAR_INTERRUPTED_MASK | DSTAR_URGENT_MASK | DSTAR_REPEATER_MASK);
|
||||
m_header[1U] = 0x00U;
|
||||
m_header[2U] = 0x00U;
|
||||
|
||||
for (unsigned int i = 3U; i < 39U; i++)
|
||||
m_header[i] &= 0x7FU;
|
||||
|
||||
// Check the CRC
|
||||
bool ret = CCRC::checkCCITT161(m_header, DSTAR_HEADER_LENGTH_BYTES);
|
||||
if (!ret) {
|
||||
if (m_ptr == 45U)
|
||||
LogMessage("D-Star, invalid slow data header");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return new CDStarHeader(m_header);
|
||||
}
|
||||
|
||||
void CDStarSlowData::start()
|
||||
{
|
||||
::memset(m_header, 0x00U, DSTAR_HEADER_LENGTH_BYTES);
|
||||
|
||||
m_ptr = 0U;
|
||||
m_state = SDD_FIRST;
|
||||
}
|
||||
|
||||
void CDStarSlowData::reset()
|
||||
{
|
||||
m_ptr = 0U;
|
||||
m_state = SDD_FIRST;
|
||||
}
|
||||
|
||||
void CDStarSlowData::setText(const char* text)
|
||||
{
|
||||
assert(text != NULL);
|
||||
|
||||
m_text[0U] = DSTAR_SLOW_DATA_TYPE_TEXT | 0U;
|
||||
m_text[1U] = text[0U];
|
||||
m_text[2U] = text[1U];
|
||||
m_text[3U] = text[2U];
|
||||
m_text[4U] = text[3U];
|
||||
m_text[5U] = text[4U];
|
||||
|
||||
m_text[6U] = DSTAR_SLOW_DATA_TYPE_TEXT | 1U;
|
||||
m_text[7U] = text[5U];
|
||||
m_text[8U] = text[6U];
|
||||
m_text[9U] = text[7U];
|
||||
m_text[10U] = text[8U];
|
||||
m_text[11U] = text[9U];
|
||||
|
||||
m_text[12U] = DSTAR_SLOW_DATA_TYPE_TEXT | 2U;
|
||||
m_text[13U] = text[10U];
|
||||
m_text[14U] = text[11U];
|
||||
m_text[15U] = text[12U];
|
||||
m_text[16U] = text[13U];
|
||||
m_text[17U] = text[14U];
|
||||
|
||||
m_text[18U] = DSTAR_SLOW_DATA_TYPE_TEXT | 3U;
|
||||
m_text[19U] = text[15U];
|
||||
m_text[20U] = text[16U];
|
||||
m_text[21U] = text[17U];
|
||||
m_text[22U] = text[18U];
|
||||
m_text[23U] = text[19U];
|
||||
|
||||
m_textPtr = 0U;
|
||||
}
|
||||
|
||||
void CDStarSlowData::get(unsigned char* data)
|
||||
{
|
||||
assert(data != NULL);
|
||||
|
||||
if (m_textPtr < 24U) {
|
||||
data[0U] = m_text[m_textPtr++] ^ DSTAR_SCRAMBLER_BYTES[0U];
|
||||
data[1U] = m_text[m_textPtr++] ^ DSTAR_SCRAMBLER_BYTES[1U];
|
||||
data[2U] = m_text[m_textPtr++] ^ DSTAR_SCRAMBLER_BYTES[2U];
|
||||
} else {
|
||||
data[0U] = 'f' ^ DSTAR_SCRAMBLER_BYTES[0U];
|
||||
data[1U] = 'f' ^ DSTAR_SCRAMBLER_BYTES[1U];
|
||||
data[2U] = 'f' ^ DSTAR_SCRAMBLER_BYTES[2U];
|
||||
}
|
||||
}
|
52
DStarSlowData.h
Normal file
52
DStarSlowData.h
Normal file
|
@ -0,0 +1,52 @@
|
|||
/*
|
||||
* Copyright (C) 2016 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* 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 DStarSlowData_H
|
||||
#define DStarSlowData_H
|
||||
|
||||
#include "DStarHeader.h"
|
||||
|
||||
class CDStarSlowData {
|
||||
public:
|
||||
CDStarSlowData();
|
||||
~CDStarSlowData();
|
||||
|
||||
CDStarHeader* add(const unsigned char* data);
|
||||
|
||||
void start();
|
||||
void reset();
|
||||
|
||||
void setText(const char* text);
|
||||
void get(unsigned char* data);
|
||||
|
||||
private:
|
||||
unsigned char* m_header;
|
||||
unsigned int m_ptr;
|
||||
unsigned char* m_buffer;
|
||||
unsigned char* m_text;
|
||||
unsigned int m_textPtr;
|
||||
|
||||
enum SDD_STATE {
|
||||
SDD_FIRST,
|
||||
SDD_SECOND
|
||||
};
|
||||
|
||||
SDD_STATE m_state;
|
||||
};
|
||||
|
||||
#endif
|
28
Defines.h
28
Defines.h
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2015,2016,2017,2018,2020,2021 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2015,2016,2017,2018 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
@ -20,8 +20,12 @@
|
|||
#define Defines_H
|
||||
|
||||
const unsigned char MODE_IDLE = 0U;
|
||||
const unsigned char MODE_DSTAR = 1U;
|
||||
const unsigned char MODE_DMR = 2U;
|
||||
|
||||
const unsigned char MODE_YSF = 3U;
|
||||
const unsigned char MODE_P25 = 4U;
|
||||
const unsigned char MODE_NXDN = 5U;
|
||||
const unsigned char MODE_POCSAG = 6U;
|
||||
const unsigned char MODE_CW = 98U;
|
||||
const unsigned char MODE_LOCKOUT = 99U;
|
||||
const unsigned char MODE_ERROR = 100U;
|
||||
|
@ -32,8 +36,6 @@ const unsigned char TAG_DATA = 0x01U;
|
|||
const unsigned char TAG_LOST = 0x02U;
|
||||
const unsigned char TAG_EOT = 0x03U;
|
||||
|
||||
const unsigned int DSTAR_MODEM_DATA_LEN = 220U;
|
||||
|
||||
enum HW_TYPE {
|
||||
HWT_MMDVM,
|
||||
HWT_DVMEGA,
|
||||
|
@ -44,8 +46,6 @@ enum HW_TYPE {
|
|||
HWT_NANO_DV,
|
||||
HWT_D2RG_MMDVM_HS,
|
||||
HWT_MMDVM_HS,
|
||||
HWT_OPENGD77_HS,
|
||||
HWT_SKYBRIDGE,
|
||||
HWT_UNKNOWN
|
||||
};
|
||||
|
||||
|
@ -53,7 +53,6 @@ enum RPT_RF_STATE {
|
|||
RS_RF_LISTENING,
|
||||
RS_RF_LATE_ENTRY,
|
||||
RS_RF_AUDIO,
|
||||
RS_RF_DATA_AUDIO,
|
||||
RS_RF_DATA,
|
||||
RS_RF_REJECTED,
|
||||
RS_RF_INVALID
|
||||
|
@ -62,22 +61,7 @@ enum RPT_RF_STATE {
|
|||
enum RPT_NET_STATE {
|
||||
RS_NET_IDLE,
|
||||
RS_NET_AUDIO,
|
||||
RS_NET_DATA_AUDIO,
|
||||
RS_NET_DATA
|
||||
};
|
||||
|
||||
enum DMR_BEACONS {
|
||||
DMR_BEACONS_OFF,
|
||||
DMR_BEACONS_NETWORK,
|
||||
DMR_BEACONS_TIMED
|
||||
};
|
||||
|
||||
enum DMR_OVCM_TYPES {
|
||||
DMR_OVCM_OFF,
|
||||
DMR_OVCM_RX_ON,
|
||||
DMR_OVCM_TX_ON,
|
||||
DMR_OVCM_ON,
|
||||
DMR_OVCM_FORCE_OFF
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
291
Display.cpp
291
Display.cpp
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2016,2017,2018,2020,2021 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2016,2017,2018 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
@ -18,15 +18,16 @@
|
|||
|
||||
#include "Display.h"
|
||||
#include "Defines.h"
|
||||
#include "UARTController.h"
|
||||
#include "SerialController.h"
|
||||
#include "ModemSerialPort.h"
|
||||
#include "NullDisplay.h"
|
||||
#include "TFTSurenoo.h"
|
||||
#include "TFTSerial.h"
|
||||
#include "LCDproc.h"
|
||||
#include "Nextion.h"
|
||||
#include "CASTInfo.h"
|
||||
#include "Conf.h"
|
||||
#include "Modem.h"
|
||||
#include "UMP.h"
|
||||
#include "Log.h"
|
||||
|
||||
#if defined(HD44780)
|
||||
|
@ -99,6 +100,42 @@ void CDisplay::setQuit()
|
|||
setQuitInt();
|
||||
}
|
||||
|
||||
void CDisplay::writeDStar(const char* my1, const char* my2, const char* your, const char* type, const char* reflector)
|
||||
{
|
||||
assert(my1 != NULL);
|
||||
assert(my2 != NULL);
|
||||
assert(your != NULL);
|
||||
assert(type != NULL);
|
||||
assert(reflector != NULL);
|
||||
|
||||
m_timer1.start();
|
||||
m_mode1 = MODE_IDLE;
|
||||
|
||||
writeDStarInt(my1, my2, your, type, reflector);
|
||||
}
|
||||
|
||||
void CDisplay::writeDStarRSSI(unsigned char rssi)
|
||||
{
|
||||
if (rssi != 0U)
|
||||
writeDStarRSSIInt(rssi);
|
||||
}
|
||||
|
||||
void CDisplay::writeDStarBER(float ber)
|
||||
{
|
||||
writeDStarBERInt(ber);
|
||||
}
|
||||
|
||||
void CDisplay::clearDStar()
|
||||
{
|
||||
if (m_timer1.hasExpired()) {
|
||||
clearDStarInt();
|
||||
m_timer1.stop();
|
||||
m_mode1 = MODE_IDLE;
|
||||
} else {
|
||||
m_mode1 = MODE_DSTAR;
|
||||
}
|
||||
}
|
||||
|
||||
void CDisplay::writeDMR(unsigned int slotNo, const std::string& src, bool group, const std::string& dst, const char* type)
|
||||
{
|
||||
assert(type != NULL);
|
||||
|
@ -113,29 +150,6 @@ void CDisplay::writeDMR(unsigned int slotNo, const std::string& src, bool group,
|
|||
writeDMRInt(slotNo, src, group, dst, type);
|
||||
}
|
||||
|
||||
void CDisplay::writeDMR(unsigned int slotNo, const class CUserDBentry& src, bool group, const std::string& dst, const char* type)
|
||||
{
|
||||
assert(type != NULL);
|
||||
|
||||
if (slotNo == 1U) {
|
||||
m_timer1.start();
|
||||
m_mode1 = MODE_IDLE;
|
||||
} else {
|
||||
m_timer2.start();
|
||||
m_mode2 = MODE_IDLE;
|
||||
}
|
||||
|
||||
if (int err = writeDMRIntEx(slotNo, src, group, dst, type)) {
|
||||
std::string src_str = src.get(keyCALLSIGN);
|
||||
if (err < 0 && !src.get(keyFIRST_NAME).empty()) {
|
||||
// emulate the result of old CDMRLookup::findWithName()
|
||||
// (it returned callsign and firstname)
|
||||
src_str += " " + src.get(keyFIRST_NAME);
|
||||
}
|
||||
writeDMRInt(slotNo, src_str, group, dst, type);
|
||||
}
|
||||
}
|
||||
|
||||
void CDisplay::writeDMRRSSI(unsigned int slotNo, unsigned char rssi)
|
||||
{
|
||||
if (rssi != 0U)
|
||||
|
@ -152,7 +166,6 @@ void CDisplay::writeDMRBER(unsigned int slotNo, float ber)
|
|||
{
|
||||
writeDMRBERInt(slotNo, ber);
|
||||
}
|
||||
|
||||
void CDisplay::clearDMR(unsigned int slotNo)
|
||||
{
|
||||
if (slotNo == 1U) {
|
||||
|
@ -174,6 +187,126 @@ void CDisplay::clearDMR(unsigned int slotNo)
|
|||
}
|
||||
}
|
||||
|
||||
void CDisplay::writeFusion(const char* source, const char* dest, const char* type, const char* origin)
|
||||
{
|
||||
assert(source != NULL);
|
||||
assert(dest != NULL);
|
||||
assert(type != NULL);
|
||||
assert(origin != NULL);
|
||||
|
||||
m_timer1.start();
|
||||
m_mode1 = MODE_IDLE;
|
||||
|
||||
writeFusionInt(source, dest, type, origin);
|
||||
}
|
||||
|
||||
void CDisplay::writeFusionRSSI(unsigned char rssi)
|
||||
{
|
||||
if (rssi != 0U)
|
||||
writeFusionRSSIInt(rssi);
|
||||
}
|
||||
|
||||
void CDisplay::writeFusionBER(float ber)
|
||||
{
|
||||
writeFusionBERInt(ber);
|
||||
}
|
||||
|
||||
void CDisplay::clearFusion()
|
||||
{
|
||||
if (m_timer1.hasExpired()) {
|
||||
clearFusionInt();
|
||||
m_timer1.stop();
|
||||
m_mode1 = MODE_IDLE;
|
||||
} else {
|
||||
m_mode1 = MODE_YSF;
|
||||
}
|
||||
}
|
||||
|
||||
void CDisplay::writeP25(const char* source, bool group, unsigned int dest, const char* type)
|
||||
{
|
||||
assert(source != NULL);
|
||||
assert(type != NULL);
|
||||
|
||||
m_timer1.start();
|
||||
m_mode1 = MODE_IDLE;
|
||||
|
||||
writeP25Int(source, group, dest, type);
|
||||
}
|
||||
|
||||
void CDisplay::writeP25RSSI(unsigned char rssi)
|
||||
{
|
||||
if (rssi != 0U)
|
||||
writeP25RSSIInt(rssi);
|
||||
}
|
||||
|
||||
void CDisplay::writeP25BER(float ber)
|
||||
{
|
||||
writeP25BERInt(ber);
|
||||
}
|
||||
|
||||
void CDisplay::clearP25()
|
||||
{
|
||||
if (m_timer1.hasExpired()) {
|
||||
clearP25Int();
|
||||
m_timer1.stop();
|
||||
m_mode1 = MODE_IDLE;
|
||||
} else {
|
||||
m_mode1 = MODE_P25;
|
||||
}
|
||||
}
|
||||
|
||||
void CDisplay::writeNXDN(const char* source, bool group, unsigned int dest, const char* type)
|
||||
{
|
||||
assert(source != NULL);
|
||||
assert(type != NULL);
|
||||
|
||||
m_timer1.start();
|
||||
m_mode1 = MODE_IDLE;
|
||||
|
||||
writeNXDNInt(source, group, dest, type);
|
||||
}
|
||||
|
||||
void CDisplay::writeNXDNRSSI(unsigned char rssi)
|
||||
{
|
||||
if (rssi != 0U)
|
||||
writeNXDNRSSIInt(rssi);
|
||||
}
|
||||
|
||||
void CDisplay::writeNXDNBER(float ber)
|
||||
{
|
||||
writeNXDNBERInt(ber);
|
||||
}
|
||||
|
||||
void CDisplay::clearNXDN()
|
||||
{
|
||||
if (m_timer1.hasExpired()) {
|
||||
clearNXDNInt();
|
||||
m_timer1.stop();
|
||||
m_mode1 = MODE_IDLE;
|
||||
} else {
|
||||
m_mode1 = MODE_NXDN;
|
||||
}
|
||||
}
|
||||
|
||||
void CDisplay::writePOCSAG(uint32_t ric, const std::string& message)
|
||||
{
|
||||
m_timer1.start();
|
||||
m_mode1 = MODE_POCSAG;
|
||||
|
||||
writePOCSAGInt(ric, message);
|
||||
}
|
||||
|
||||
void CDisplay::clearPOCSAG()
|
||||
{
|
||||
if (m_timer1.hasExpired()) {
|
||||
clearPOCSAGInt();
|
||||
m_timer1.stop();
|
||||
m_mode1 = MODE_IDLE;
|
||||
} else {
|
||||
m_mode1 = MODE_POCSAG;
|
||||
}
|
||||
}
|
||||
|
||||
void CDisplay::writeCW()
|
||||
{
|
||||
m_timer1.start();
|
||||
|
@ -187,11 +320,36 @@ void CDisplay::clock(unsigned int ms)
|
|||
m_timer1.clock(ms);
|
||||
if (m_timer1.isRunning() && m_timer1.hasExpired()) {
|
||||
switch (m_mode1) {
|
||||
case MODE_DSTAR:
|
||||
clearDStarInt();
|
||||
m_mode1 = MODE_IDLE;
|
||||
m_timer1.stop();
|
||||
break;
|
||||
case MODE_DMR:
|
||||
clearDMRInt(1U);
|
||||
m_mode1 = MODE_IDLE;
|
||||
m_timer1.stop();
|
||||
break;
|
||||
case MODE_YSF:
|
||||
clearFusionInt();
|
||||
m_mode1 = MODE_IDLE;
|
||||
m_timer1.stop();
|
||||
break;
|
||||
case MODE_P25:
|
||||
clearP25Int();
|
||||
m_mode1 = MODE_IDLE;
|
||||
m_timer1.stop();
|
||||
break;
|
||||
case MODE_NXDN:
|
||||
clearNXDNInt();
|
||||
m_mode1 = MODE_IDLE;
|
||||
m_timer1.stop();
|
||||
break;
|
||||
case MODE_POCSAG:
|
||||
clearPOCSAGInt();
|
||||
m_mode1 = MODE_IDLE;
|
||||
m_timer1.stop();
|
||||
break;
|
||||
case MODE_CW:
|
||||
clearCWInt();
|
||||
m_mode1 = MODE_IDLE;
|
||||
|
@ -219,18 +377,12 @@ void CDisplay::clockInt(unsigned int ms)
|
|||
{
|
||||
}
|
||||
|
||||
int CDisplay::writeDMRIntEx(unsigned int slotNo, const class CUserDBentry& src, bool group, const std::string& dst, const char* type)
|
||||
void CDisplay::writeDStarRSSIInt(unsigned char rssi)
|
||||
{
|
||||
}
|
||||
|
||||
void CDisplay::writeDStarBERInt(float ber)
|
||||
{
|
||||
/*
|
||||
* return value:
|
||||
* < 0 error condition (i.e. not supported)
|
||||
* -> call writeXXXXInt() to display
|
||||
* = 0 no error, writeXXXXIntEx() displayed whole status
|
||||
* = 1 no error, writeXXXXIntEx() displayed partial status
|
||||
* -> call writeXXXXInt() to display remain part
|
||||
* > 1 reserved for future use
|
||||
*/
|
||||
return -1; // not supported
|
||||
}
|
||||
|
||||
void CDisplay::writeDMRRSSIInt(unsigned int slotNo, unsigned char rssi)
|
||||
|
@ -245,19 +397,42 @@ void CDisplay::writeDMRBERInt(unsigned int slotNo, float ber)
|
|||
{
|
||||
}
|
||||
|
||||
void CDisplay::writeFusionRSSIInt(unsigned char rssi)
|
||||
{
|
||||
}
|
||||
|
||||
void CDisplay::writeFusionBERInt(float ber)
|
||||
{
|
||||
}
|
||||
|
||||
void CDisplay::writeP25RSSIInt(unsigned char rssi)
|
||||
{
|
||||
}
|
||||
|
||||
void CDisplay::writeP25BERInt(float ber)
|
||||
{
|
||||
}
|
||||
|
||||
void CDisplay::writeNXDNRSSIInt(unsigned char rssi)
|
||||
{
|
||||
}
|
||||
|
||||
void CDisplay::writeNXDNBERInt(float ber)
|
||||
{
|
||||
}
|
||||
|
||||
/* Factory method extracted from MMDVMHost.cpp - BG5HHP */
|
||||
CDisplay* CDisplay::createDisplay(const CConf& conf, CModem* modem)
|
||||
CDisplay* CDisplay::createDisplay(const CConf& conf, CUMP* ump, CModem* modem)
|
||||
{
|
||||
CDisplay *display = NULL;
|
||||
CDisplay *display = NULL;
|
||||
|
||||
std::string type = conf.getDisplay();
|
||||
std::string type = conf.getDisplay();
|
||||
unsigned int dmrid = conf.getDMRId();
|
||||
|
||||
LogInfo("Display Parameters");
|
||||
LogInfo(" Type: %s", type.c_str());
|
||||
|
||||
if (type == "TFT Surenoo") {
|
||||
if (type == "TFT Serial") {
|
||||
std::string port = conf.getTFTSerialPort();
|
||||
unsigned int brightness = conf.getTFTSerialBrightness();
|
||||
|
||||
|
@ -266,11 +441,11 @@ CDisplay* CDisplay::createDisplay(const CConf& conf, CModem* modem)
|
|||
|
||||
ISerialPort* serial = NULL;
|
||||
if (port == "modem")
|
||||
serial = new IModemSerialPort(modem);
|
||||
serial = new CModemSerialPort(modem);
|
||||
else
|
||||
serial = new CUARTController(port, 115200U);
|
||||
serial = new CSerialController(port, SERIAL_9600);
|
||||
|
||||
display = new CTFTSurenoo(conf.getCallsign(), dmrid, serial, brightness, conf.getDuplex());
|
||||
display = new CTFTSerial(conf.getCallsign(), dmrid, serial, brightness);
|
||||
} else if (type == "Nextion") {
|
||||
std::string port = conf.getNextionPort();
|
||||
unsigned int brightness = conf.getNextionBrightness();
|
||||
|
@ -309,16 +484,23 @@ CDisplay* CDisplay::createDisplay(const CConf& conf, CModem* modem)
|
|||
}
|
||||
|
||||
if (port == "modem") {
|
||||
ISerialPort* serial = new IModemSerialPort(modem);
|
||||
display = new CNextion(conf.getCallsign(), dmrid, serial, brightness, displayClock, utc, idleBrightness, screenLayout, txFrequency, rxFrequency, displayTempInF);
|
||||
ISerialPort* serial = new CModemSerialPort(modem);
|
||||
display = new CNextion(conf.getCallsign(), dmrid, serial, brightness, displayClock, utc, idleBrightness, screenLayout, txFrequency, rxFrequency, displayTempInF, conf.getLocation());
|
||||
} else if (port == "ump") {
|
||||
if (ump != NULL) {
|
||||
display = new CNextion(conf.getCallsign(), dmrid, ump, brightness, displayClock, utc, idleBrightness, screenLayout, txFrequency, rxFrequency, displayTempInF, conf.getLocation());
|
||||
} else {
|
||||
LogInfo(" NullDisplay loaded");
|
||||
display = new CNullDisplay;
|
||||
}
|
||||
} else {
|
||||
unsigned int baudrate = 9600U;
|
||||
if (screenLayout == 4U)
|
||||
baudrate = 115200U;
|
||||
SERIAL_SPEED baudrate = SERIAL_9600;
|
||||
if (screenLayout==4U)
|
||||
baudrate = SERIAL_115200;
|
||||
|
||||
LogInfo(" Display baudrate: %u ", baudrate);
|
||||
ISerialPort* serial = new CUARTController(port, baudrate);
|
||||
display = new CNextion(conf.getCallsign(), dmrid, serial, brightness, displayClock, utc, idleBrightness, screenLayout, txFrequency, rxFrequency, displayTempInF);
|
||||
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());
|
||||
}
|
||||
} else if (type == "LCDproc") {
|
||||
std::string address = conf.getLCDprocAddress();
|
||||
|
@ -387,9 +569,8 @@ CDisplay* CDisplay::createDisplay(const CConf& conf, CModem* modem)
|
|||
bool invert = conf.getOLEDInvert();
|
||||
bool scroll = conf.getOLEDScroll();
|
||||
bool rotate = conf.getOLEDRotate();
|
||||
bool logosaver = conf.getOLEDLogoScreensaver();
|
||||
|
||||
display = new COLED(type, brightness, invert, scroll, rotate, logosaver, conf.getDuplex());
|
||||
display = new COLED(type, brightness, invert, scroll, rotate, conf.getDMRNetworkSlot1(), conf.getDMRNetworkSlot2());
|
||||
#endif
|
||||
} else if (type == "CAST") {
|
||||
display = new CCASTInfo(modem);
|
||||
|
|
56
Display.h
56
Display.h
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2016,2017,2018,2020,2021 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2016,2017,2018 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
@ -20,8 +20,6 @@
|
|||
#define DISPLAY_H
|
||||
|
||||
#include "Timer.h"
|
||||
#include "UserDBentry.h"
|
||||
#include "Modem.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
|
@ -29,6 +27,7 @@
|
|||
|
||||
class CConf;
|
||||
class CModem;
|
||||
class CUMP;
|
||||
|
||||
class CDisplay
|
||||
{
|
||||
|
@ -42,22 +41,43 @@ public:
|
|||
void setLockout();
|
||||
void setError(const char* text);
|
||||
void setQuit();
|
||||
void setFM();
|
||||
|
||||
void writeDStar(const char* my1, const char* my2, const char* your, const char* type, const char* reflector);
|
||||
void writeDStarRSSI(unsigned char rssi);
|
||||
void writeDStarBER(float ber);
|
||||
void clearDStar();
|
||||
|
||||
void writeDMR(unsigned int slotNo, const std::string& src, bool group, const std::string& dst, const char* type);
|
||||
void writeDMR(unsigned int slotNo, const class CUserDBentry& src, bool group, const std::string& dst, const char* type);
|
||||
void writeDMRRSSI(unsigned int slotNo, unsigned char rssi);
|
||||
void writeDMRBER(unsigned int slotNo, float ber);
|
||||
void writeDMRTA(unsigned int slotNo, unsigned char* talkerAlias, const char* type);
|
||||
void clearDMR(unsigned int slotNo);
|
||||
|
||||
void writeFusion(const char* source, const char* dest, const char* type, const char* origin);
|
||||
void writeFusionRSSI(unsigned char rssi);
|
||||
void writeFusionBER(float ber);
|
||||
void clearFusion();
|
||||
|
||||
void writeP25(const char* source, bool group, unsigned int dest, const char* type);
|
||||
void writeP25RSSI(unsigned char rssi);
|
||||
void writeP25BER(float ber);
|
||||
void clearP25();
|
||||
|
||||
void writeNXDN(const char* source, bool group, unsigned int dest, const char* type);
|
||||
void writeNXDNRSSI(unsigned char rssi);
|
||||
void writeNXDNBER(float ber);
|
||||
void clearNXDN();
|
||||
|
||||
void writePOCSAG(uint32_t ric, const std::string& message);
|
||||
void clearPOCSAG();
|
||||
|
||||
void writeCW();
|
||||
|
||||
virtual void close() = 0;
|
||||
|
||||
void clock(unsigned int ms);
|
||||
|
||||
static CDisplay* createDisplay(const CConf& conf, CModem* modem);
|
||||
static CDisplay* createDisplay(const CConf& conf, CUMP* ump, CModem* modem);
|
||||
|
||||
protected:
|
||||
virtual void setIdleInt() = 0;
|
||||
|
@ -65,13 +85,35 @@ protected:
|
|||
virtual void setErrorInt(const char* text) = 0;
|
||||
virtual void setQuitInt() = 0;
|
||||
|
||||
virtual void writeDStarInt(const char* my1, const char* my2, const char* your, const char* type, const char* reflector) = 0;
|
||||
virtual void writeDStarRSSIInt(unsigned char rssi);
|
||||
virtual void writeDStarBERInt(float ber);
|
||||
virtual void clearDStarInt() = 0;
|
||||
|
||||
virtual void writeDMRInt(unsigned int slotNo, const std::string& src, bool group, const std::string& dst, const char* type) = 0;
|
||||
virtual int writeDMRIntEx(unsigned int slotNo, const class CUserDBentry& src, bool group, const std::string& dst, const char* type);
|
||||
virtual void writeDMRRSSIInt(unsigned int slotNo, unsigned char rssi);
|
||||
virtual void writeDMRTAInt(unsigned int slotNo, unsigned char* talkerAlias, const char* type);
|
||||
virtual void writeDMRBERInt(unsigned int slotNo, float ber);
|
||||
virtual void clearDMRInt(unsigned int slotNo) = 0;
|
||||
|
||||
virtual void writeFusionInt(const char* source, const char* dest, const char* type, const char* origin) = 0;
|
||||
virtual void writeFusionRSSIInt(unsigned char rssi);
|
||||
virtual void writeFusionBERInt(float ber);
|
||||
virtual void clearFusionInt() = 0;
|
||||
|
||||
virtual void writeP25Int(const char* source, bool group, unsigned int dest, const char* type) = 0;
|
||||
virtual void writeP25RSSIInt(unsigned char rssi);
|
||||
virtual void writeP25BERInt(float ber);
|
||||
virtual void clearP25Int() = 0;
|
||||
|
||||
virtual void writeNXDNInt(const char* source, bool group, unsigned int dest, const char* type) = 0;
|
||||
virtual void writeNXDNRSSIInt(unsigned char rssi);
|
||||
virtual void writeNXDNBERInt(float ber);
|
||||
virtual void clearNXDNInt() = 0;
|
||||
|
||||
virtual void writePOCSAGInt(uint32_t ric, const std::string& message) = 0;
|
||||
virtual void clearPOCSAGInt() = 0;
|
||||
|
||||
virtual void writeCWInt() = 0;
|
||||
virtual void clearCWInt() = 0;
|
||||
|
||||
|
|
19
Dockerfile
Normal file
19
Dockerfile
Normal file
|
@ -0,0 +1,19 @@
|
|||
FROM alpine
|
||||
|
||||
RUN apk add --update --no-cache \
|
||||
cmake \
|
||||
make \
|
||||
g++ \
|
||||
git \
|
||||
&& rm -rf /var/cache/apk/*
|
||||
|
||||
ADD ./ /MMDVMHost
|
||||
WORKDIR /MMDVMHost
|
||||
RUN make \
|
||||
&& cp MMDVMHost /usr/local/bin
|
||||
|
||||
VOLUME /MMDVMHost
|
||||
WORKDIR /MMDVMHost
|
||||
|
||||
CMD ["MMDVMHost", "/MMDVMHost/MMDVM.ini"]
|
||||
|
|
@ -1,10 +1,9 @@
|
|||
/*
|
||||
* Copyright (C) 2010,2016,2021 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2010,2016 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2002 by Robert H. Morelos-Zaragoza. All rights reserved.
|
||||
*/
|
||||
|
||||
#include "Golay24128.h"
|
||||
#include "Utils.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <cassert>
|
||||
|
@ -1090,25 +1089,20 @@ unsigned int CGolay24128::decode23127(unsigned int code)
|
|||
return code >> 11;
|
||||
}
|
||||
|
||||
bool CGolay24128::decode24128(unsigned int in, unsigned int& out)
|
||||
unsigned int CGolay24128::decode24128(unsigned int code)
|
||||
{
|
||||
unsigned int syndrome = ::get_syndrome_23127(in >> 1);
|
||||
unsigned int error_pattern = DECODING_TABLE_23127[syndrome] << 1;
|
||||
|
||||
out = in ^ error_pattern;
|
||||
|
||||
bool valid = (CUtils::countBits(syndrome) < 3U) || !(CUtils::countBits(out) & 1);
|
||||
|
||||
out >>= 12;
|
||||
|
||||
return valid;
|
||||
return decode23127(code >> 1);
|
||||
}
|
||||
|
||||
bool CGolay24128::decode24128(unsigned char* in, unsigned int& out)
|
||||
unsigned int CGolay24128::decode24128(unsigned char* bytes)
|
||||
{
|
||||
assert(in != NULL);
|
||||
assert(bytes != NULL);
|
||||
|
||||
unsigned int code = (in[0U] << 16) | (in[1U] << 8) | (in[2U] << 0);
|
||||
unsigned int code = bytes[0U];
|
||||
code <<= 8;
|
||||
code |= bytes[1U];
|
||||
code <<= 8;
|
||||
code |= bytes[2U];
|
||||
|
||||
return decode24128(code, out);
|
||||
return decode23127(code >> 1);
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2010,2016,2021 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2010,2016 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
@ -25,9 +25,8 @@ public:
|
|||
static unsigned int encode24128(unsigned int data);
|
||||
|
||||
static unsigned int decode23127(unsigned int code);
|
||||
|
||||
static bool decode24128(unsigned int in, unsigned int& out);
|
||||
static bool decode24128(unsigned char* in, unsigned int& out);
|
||||
static unsigned int decode24128(unsigned int code);
|
||||
static unsigned int decode24128(unsigned char* bytes);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
374
HD44780.cpp
374
HD44780.cpp
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2016,2017,2018,2020,2021 by Jonathan Naylor G4KLX & Tony Corbett G0WFV
|
||||
* Copyright (C) 2016,2017,2018 by Jonathan Naylor G4KLX & Tony Corbett G0WFV
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
@ -41,7 +41,6 @@ const unsigned int DMR_RSSI_COUNT = 4U; // 4 * 360ms = 1440ms
|
|||
const unsigned int YSF_RSSI_COUNT = 13U; // 13 * 100ms = 1300ms
|
||||
const unsigned int P25_RSSI_COUNT = 7U; // 7 * 180ms = 1260ms
|
||||
const unsigned int NXDN_RSSI_COUNT = 28U; // 28 * 40ms = 1120ms
|
||||
const unsigned int M17_RSSI_COUNT = 28U; // 28 * 40ms = 1120ms
|
||||
|
||||
CHD44780::CHD44780(unsigned int rows, unsigned int cols, const std::string& callsign, unsigned int dmrid, const std::vector<unsigned int>& pins, unsigned int i2cAddress, bool pwm, unsigned int pwmPin, unsigned int pwmBright, unsigned int pwmDim, bool displayClock, bool utc, bool duplex) :
|
||||
CDisplay(),
|
||||
|
@ -212,12 +211,12 @@ void CHD44780::adafruitLCDSetup()
|
|||
::pinMode(AF_RW, OUTPUT);
|
||||
::digitalWrite(AF_RW, LOW);
|
||||
|
||||
m_rb = AF_RS;
|
||||
m_strb = AF_E;
|
||||
m_d0 = AF_D0;
|
||||
m_d1 = AF_D1;
|
||||
m_d2 = AF_D2;
|
||||
m_d3 = AF_D3;
|
||||
m_rb = AF_RS;
|
||||
m_strb = AF_E;
|
||||
m_d0 = AF_D0;
|
||||
m_d1 = AF_D1;
|
||||
m_d2 = AF_D2;
|
||||
m_d3 = AF_D3;
|
||||
}
|
||||
|
||||
void CHD44780::adafruitLCDColour(ADAFRUIT_COLOUR colour)
|
||||
|
@ -276,12 +275,12 @@ void CHD44780::pcf8574LCDSetup()
|
|||
::pcf8574Setup(AF_BASE, m_i2cAddress);
|
||||
|
||||
// Turn on backlight
|
||||
::pinMode(AF_BL, OUTPUT);
|
||||
::digitalWrite(AF_BL, 1);
|
||||
::pinMode (AF_BL, OUTPUT);
|
||||
::digitalWrite (AF_BL, 1);
|
||||
|
||||
// Set LCD to write mode.
|
||||
::pinMode(AF_RW, OUTPUT);
|
||||
::digitalWrite(AF_RW, 0);
|
||||
::pinMode (AF_RW, OUTPUT);
|
||||
::digitalWrite (AF_RW, 0);
|
||||
|
||||
m_rb = AF_RS;
|
||||
m_strb = AF_E;
|
||||
|
@ -298,7 +297,7 @@ void CHD44780::setIdleInt()
|
|||
::lcdClear(m_fd);
|
||||
|
||||
#ifdef ADAFRUIT_DISPLAY
|
||||
adafruitLCDColour(AC_WHITE);
|
||||
adafruitLCDColour(AC_WHITE);
|
||||
#endif
|
||||
|
||||
if (m_pwm) {
|
||||
|
@ -328,7 +327,7 @@ void CHD44780::setErrorInt(const char* text)
|
|||
assert(text != NULL);
|
||||
|
||||
#ifdef ADAFRUIT_DISPLAY
|
||||
adafruitLCDColour(AC_RED);
|
||||
adafruitLCDColour(AC_RED);
|
||||
#endif
|
||||
|
||||
m_clockDisplayTimer.stop(); // Stop the clock display
|
||||
|
@ -400,37 +399,6 @@ void CHD44780::setQuitInt()
|
|||
m_dmr = false;
|
||||
}
|
||||
|
||||
void CHD44780::setFMInt()
|
||||
{
|
||||
m_clockDisplayTimer.stop();
|
||||
::lcdClear(m_fd);
|
||||
|
||||
#ifdef ADAFRUIT_DISPLAY
|
||||
adafruitLCDColour(AC_WHITE);
|
||||
#endif
|
||||
|
||||
if (m_pwm) {
|
||||
if (m_pwmPin != 1U)
|
||||
::softPwmWrite(m_pwmPin, m_pwmDim);
|
||||
else
|
||||
::pwmWrite(m_pwmPin, (m_pwmDim / 100) * 1024);
|
||||
}
|
||||
|
||||
// Print callsign and ID at on top row for all screen sizes
|
||||
::lcdPosition(m_fd, 0, 0);
|
||||
::lcdPrintf(m_fd, "%-6s", m_callsign.c_str());
|
||||
::lcdPosition(m_fd, m_cols - 7, 0);
|
||||
::lcdPrintf(m_fd, "%7u", m_dmrid);
|
||||
|
||||
// Print MMDVM and Idle on bottom row for all screen sizes
|
||||
::lcdPosition(m_fd, 0, m_rows - 1);
|
||||
::lcdPuts(m_fd, "MMDVM");
|
||||
::lcdPosition(m_fd, m_cols - 4, m_rows - 1);
|
||||
::lcdPuts(m_fd, "FM"); // Gets overwritten by clock on 2 line screen
|
||||
|
||||
m_dmr = false;
|
||||
}
|
||||
|
||||
void CHD44780::writeDStarInt(const char* my1, const char* my2, const char* your, const char* type, const char* reflector)
|
||||
{
|
||||
assert(my1 != NULL);
|
||||
|
@ -440,7 +408,7 @@ void CHD44780::writeDStarInt(const char* my1, const char* my2, const char* your,
|
|||
assert(reflector != NULL);
|
||||
|
||||
#ifdef ADAFRUIT_DISPLAY
|
||||
adafruitLCDColour(AC_RED);
|
||||
adafruitLCDColour(AC_RED);
|
||||
#endif
|
||||
|
||||
m_clockDisplayTimer.stop(); // Stop the clock display
|
||||
|
@ -464,10 +432,11 @@ void CHD44780::writeDStarInt(const char* my1, const char* my2, const char* your,
|
|||
::lcdPrintf(m_fd, " %.8s/%.4s", my1, my2);
|
||||
::lcdPosition(m_fd, m_cols - 1, (m_rows / 2) - 1);
|
||||
|
||||
if (strcmp(type, "R") == 0)
|
||||
if (strcmp(type, "R") == 0) {
|
||||
::lcdPutchar(m_fd, 2);
|
||||
else
|
||||
} else {
|
||||
::lcdPutchar(m_fd, 3);
|
||||
}
|
||||
|
||||
::sprintf(m_buffer1, "%.8s", your);
|
||||
|
||||
|
@ -493,19 +462,19 @@ void CHD44780::writeDStarInt(const char* my1, const char* my2, const char* your,
|
|||
::lcdPrintf(m_fd, " %.*s", m_cols, m_buffer1);
|
||||
|
||||
m_dmr = false;
|
||||
m_rssiCount1 = 0U;
|
||||
m_rssiCount1 = 0U;
|
||||
}
|
||||
|
||||
void CHD44780::writeDStarRSSIInt(unsigned char rssi)
|
||||
{
|
||||
if (m_rssiCount1 == 0U && m_rows > 2) {
|
||||
void CHD44780::writeDStarRSSIInt(unsigned char rssi)
|
||||
{
|
||||
if (m_rssiCount1 == 0U && m_rows > 2) {
|
||||
::lcdPosition(m_fd, 0, 3);
|
||||
::lcdPrintf(m_fd, "-%3udBm", rssi);
|
||||
}
|
||||
|
||||
m_rssiCount1++;
|
||||
if (m_rssiCount1 >= DSTAR_RSSI_COUNT)
|
||||
m_rssiCount1 = 0U;
|
||||
}
|
||||
|
||||
m_rssiCount1++;
|
||||
if (m_rssiCount1 >= DSTAR_RSSI_COUNT)
|
||||
m_rssiCount1 = 0U;
|
||||
}
|
||||
|
||||
void CHD44780::clearDStarInt()
|
||||
|
@ -599,20 +568,21 @@ void CHD44780::writeDMRInt(unsigned int slotNo, const std::string& src, bool gro
|
|||
::lcdPosition(m_fd, m_cols - 3U, (m_rows / 2) - 1);
|
||||
::lcdPuts(m_fd, " ");
|
||||
|
||||
if (group)
|
||||
if (group) {
|
||||
::lcdPutchar(m_fd, 5);
|
||||
else
|
||||
} else {
|
||||
::lcdPutchar(m_fd, 4);
|
||||
}
|
||||
|
||||
if (strcmp(type, "R") == 0)
|
||||
if (strcmp(type, "R") == 0) {
|
||||
::lcdPutchar(m_fd, 2);
|
||||
else
|
||||
} else {
|
||||
::lcdPutchar(m_fd, 3);
|
||||
}
|
||||
} else {
|
||||
::lcdPosition(m_fd, 0, (m_rows / 2));
|
||||
::lcdPuts(m_fd, "2 ");
|
||||
|
||||
if (m_cols > 16)
|
||||
if (m_cols > 16 )
|
||||
::sprintf(m_buffer2, "%s > %s%s%s", src.c_str(), group ? "TG" : "", dst.c_str(), DEADSPACE);
|
||||
else
|
||||
::sprintf(m_buffer2, "%s>%s%s", src.c_str(), dst.c_str(), DEADSPACE);
|
||||
|
@ -621,15 +591,17 @@ void CHD44780::writeDMRInt(unsigned int slotNo, const std::string& src, bool gro
|
|||
::lcdPosition(m_fd, m_cols - 3U, (m_rows / 2));
|
||||
::lcdPuts(m_fd, " ");
|
||||
|
||||
if (group)
|
||||
if (group) {
|
||||
::lcdPutchar(m_fd, 5);
|
||||
else
|
||||
} else {
|
||||
::lcdPutchar(m_fd, 4);
|
||||
}
|
||||
|
||||
if (strcmp(type, "R") == 0)
|
||||
if (strcmp(type, "R") == 0) {
|
||||
::lcdPutchar(m_fd, 2);
|
||||
else
|
||||
} else {
|
||||
::lcdPutchar(m_fd, 3);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (m_rows > 2U) {
|
||||
|
@ -644,10 +616,11 @@ void CHD44780::writeDMRInt(unsigned int slotNo, const std::string& src, bool gro
|
|||
::lcdPrintf(m_fd, "%.*s", m_cols - 4U, m_buffer2);
|
||||
::lcdPosition(m_fd, m_cols - 1U, (m_rows / 2) - 1);
|
||||
|
||||
if (strcmp(type, "R") == 0)
|
||||
if (strcmp(type, "R") == 0) {
|
||||
::lcdPutchar(m_fd, 2);
|
||||
else
|
||||
} else {
|
||||
::lcdPutchar(m_fd, 3);
|
||||
}
|
||||
|
||||
::lcdPosition(m_fd, 0, (m_rows / 2));
|
||||
::lcdPutchar(m_fd, 1);
|
||||
|
@ -655,38 +628,38 @@ void CHD44780::writeDMRInt(unsigned int slotNo, const std::string& src, bool gro
|
|||
::lcdPrintf(m_fd, "%.*s", m_cols - 4U, m_buffer2);
|
||||
::lcdPosition(m_fd, m_cols - 1U, (m_rows / 2));
|
||||
|
||||
if (group)
|
||||
if (group) {
|
||||
::lcdPutchar(m_fd, 5);
|
||||
else
|
||||
} else {
|
||||
::lcdPutchar(m_fd, 4);
|
||||
}
|
||||
}
|
||||
|
||||
m_dmr = true;
|
||||
m_rssiCount1 = 0U;
|
||||
m_rssiCount2 = 0U;
|
||||
m_rssiCount2 = 0U;
|
||||
}
|
||||
|
||||
void CHD44780::writeDMRRSSIInt(unsigned int slotNo, unsigned char rssi)
|
||||
{
|
||||
void CHD44780::writeDMRRSSIInt(unsigned int slotNo, unsigned char rssi)
|
||||
{
|
||||
if (m_rows > 2) {
|
||||
if (slotNo == 1U) {
|
||||
if (m_rssiCount1 == 0U) {
|
||||
if (slotNo == 1U) {
|
||||
if (m_rssiCount1 == 0U) {
|
||||
::lcdPosition(m_fd, 0, 3);
|
||||
::lcdPrintf(m_fd, "-%3udBm", rssi);
|
||||
}
|
||||
}
|
||||
|
||||
m_rssiCount1++;
|
||||
if (m_rssiCount1 >= DMR_RSSI_COUNT)
|
||||
m_rssiCount1 = 0U;
|
||||
} else {
|
||||
if (m_rssiCount2 == 0U) {
|
||||
m_rssiCount1++;
|
||||
if (m_rssiCount1 >= DMR_RSSI_COUNT)
|
||||
m_rssiCount1 = 0U;
|
||||
} else {
|
||||
if (m_rssiCount2 == 0U) {
|
||||
::lcdPosition(m_fd, (m_cols / 2), 3);
|
||||
::lcdPrintf(m_fd, "-%3udBm", rssi);
|
||||
}
|
||||
}
|
||||
|
||||
m_rssiCount2++;
|
||||
if (m_rssiCount2 >= DMR_RSSI_COUNT)
|
||||
m_rssiCount2 = 0U;
|
||||
m_rssiCount2++;
|
||||
if (m_rssiCount2 >= DMR_RSSI_COUNT)
|
||||
m_rssiCount2 = 0U;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -718,6 +691,7 @@ void CHD44780::clearDMRInt(unsigned int slotNo)
|
|||
}
|
||||
}
|
||||
} else {
|
||||
|
||||
if (m_rows > 2U) {
|
||||
::lcdPosition(m_fd, 0, (m_rows / 2) - 2);
|
||||
::sprintf(m_buffer1, "%s", DEADSPACE);
|
||||
|
@ -732,7 +706,7 @@ void CHD44780::clearDMRInt(unsigned int slotNo)
|
|||
}
|
||||
}
|
||||
|
||||
void CHD44780::writeFusionInt(const char* source, const char* dest, unsigned char dgid, const char* type, const char* origin)
|
||||
void CHD44780::writeFusionInt(const char* source, const char* dest, const char* type, const char* origin)
|
||||
{
|
||||
assert(source != NULL);
|
||||
assert(dest != NULL);
|
||||
|
@ -740,7 +714,7 @@ void CHD44780::writeFusionInt(const char* source, const char* dest, unsigned cha
|
|||
assert(origin != NULL);
|
||||
|
||||
#ifdef ADAFRUIT_DISPLAY
|
||||
adafruitLCDColour(AC_RED);
|
||||
adafruitLCDColour(AC_RED);
|
||||
#endif
|
||||
|
||||
m_clockDisplayTimer.stop(); // Stop the clock display
|
||||
|
@ -757,46 +731,50 @@ void CHD44780::writeFusionInt(const char* source, const char* dest, unsigned cha
|
|||
::lcdPuts(m_fd, "System Fusion");
|
||||
|
||||
if (m_rows == 2U && m_cols == 16U) {
|
||||
char m_buffer1[16U];
|
||||
::sprintf(m_buffer1, "%.10s >", source);
|
||||
::lcdPosition(m_fd, 0, 1);
|
||||
::lcdPrintf(m_fd, "%.*s", m_cols, m_buffer1);
|
||||
} else if (m_rows == 4U && m_cols == 16U) {
|
||||
char m_buffer1[16U];
|
||||
::sprintf(m_buffer1, "%.10s >", source);
|
||||
::lcdPosition(m_fd, 0, 1);
|
||||
::lcdPrintf(m_fd, "%.*s", m_cols, m_buffer1);
|
||||
|
||||
::sprintf(m_buffer1, "DG-ID %u", dgid);
|
||||
::sprintf(m_buffer1, "%.10s", dest);
|
||||
::lcdPosition(m_fd, 0, 2);
|
||||
::lcdPrintf(m_fd, "%.*s", m_cols, m_buffer1);
|
||||
} else if (m_rows == 4U && m_cols == 20U) {
|
||||
char m_buffer1[20U];
|
||||
::sprintf(m_buffer1, "%.10s >", source);
|
||||
::lcdPosition(m_fd, 0, 1);
|
||||
::lcdPrintf(m_fd, "%.*s", m_cols, m_buffer1);
|
||||
|
||||
::sprintf(m_buffer1, "DG-ID %u", dgid);
|
||||
::sprintf(m_buffer1, "%.10s", dest);
|
||||
::lcdPosition(m_fd, 0, 2);
|
||||
::lcdPrintf(m_fd, "%.*s", m_cols, m_buffer1);
|
||||
} else if (m_rows == 2 && m_cols == 40U) {
|
||||
::sprintf(m_buffer1, "%.10s > DG-ID %u", source, dgid);
|
||||
char m_buffer1[40U];
|
||||
::sprintf(m_buffer1, "%.10s > %.10s", source, dest);
|
||||
|
||||
::lcdPosition(m_fd, 0, 1);
|
||||
::lcdPrintf(m_fd, "%.*s", m_cols, m_buffer1);
|
||||
}
|
||||
|
||||
m_dmr = false;
|
||||
m_rssiCount1 = 0U;
|
||||
m_rssiCount1 = 0U;
|
||||
}
|
||||
|
||||
void CHD44780::writeFusionRSSIInt(unsigned char rssi)
|
||||
{
|
||||
if (m_rssiCount1 == 0U && m_rows > 2) {
|
||||
void CHD44780::writeFusionRSSIInt(unsigned char rssi)
|
||||
{
|
||||
if (m_rssiCount1 == 0U && m_rows > 2) {
|
||||
::lcdPosition(m_fd, 0, 3);
|
||||
::lcdPrintf(m_fd, "-%3udBm", rssi);
|
||||
}
|
||||
|
||||
m_rssiCount1++;
|
||||
if (m_rssiCount1 >= YSF_RSSI_COUNT)
|
||||
m_rssiCount1 = 0U;
|
||||
}
|
||||
|
||||
m_rssiCount1++;
|
||||
if (m_rssiCount1 >= YSF_RSSI_COUNT)
|
||||
m_rssiCount1 = 0U;
|
||||
}
|
||||
|
||||
void CHD44780::clearFusionInt()
|
||||
|
@ -804,6 +782,7 @@ void CHD44780::clearFusionInt()
|
|||
#ifdef ADAFRUIT_DISPLAY
|
||||
adafruitLCDColour(AC_PURPLE);
|
||||
#endif
|
||||
|
||||
m_clockDisplayTimer.stop(); // Stop the clock display
|
||||
|
||||
if (m_rows == 2U && m_cols == 16U) {
|
||||
|
@ -839,7 +818,7 @@ void CHD44780::writeP25Int(const char* source, bool group, unsigned int dest, co
|
|||
assert(type != NULL);
|
||||
|
||||
#ifdef ADAFRUIT_DISPLAY
|
||||
adafruitLCDColour(AC_RED);
|
||||
adafruitLCDColour(AC_RED);
|
||||
#endif
|
||||
|
||||
m_clockDisplayTimer.stop(); // Stop the clock display
|
||||
|
@ -856,10 +835,12 @@ void CHD44780::writeP25Int(const char* source, bool group, unsigned int dest, co
|
|||
::lcdPuts(m_fd, "P25");
|
||||
|
||||
if (m_rows == 2U && m_cols == 16U) {
|
||||
char m_buffer1[16U];
|
||||
::sprintf(m_buffer1, "%.10s >", source);
|
||||
::lcdPosition(m_fd, 0, 1);
|
||||
::lcdPrintf(m_fd, "%.*s", m_cols, m_buffer1);
|
||||
} else if (m_rows == 4U && m_cols == 16U) {
|
||||
char m_buffer1[16U];
|
||||
::sprintf(m_buffer1, "%.10s >", source);
|
||||
::lcdPosition(m_fd, 0, 1);
|
||||
::lcdPrintf(m_fd, "%.*s", m_cols, m_buffer1);
|
||||
|
@ -868,6 +849,7 @@ void CHD44780::writeP25Int(const char* source, bool group, unsigned int dest, co
|
|||
::lcdPosition(m_fd, 0, 2);
|
||||
::lcdPrintf(m_fd, "%.*s", m_cols, m_buffer1);
|
||||
} else if (m_rows == 4U && m_cols == 20U) {
|
||||
char m_buffer1[20U];
|
||||
::sprintf(m_buffer1, "%.10s >", source);
|
||||
::lcdPosition(m_fd, 0, 1);
|
||||
::lcdPrintf(m_fd, "%.*s", m_cols, m_buffer1);
|
||||
|
@ -876,6 +858,7 @@ void CHD44780::writeP25Int(const char* source, bool group, unsigned int dest, co
|
|||
::lcdPosition(m_fd, 0, 2);
|
||||
::lcdPrintf(m_fd, "%.*s", m_cols, m_buffer1);
|
||||
} else if (m_rows == 2 && m_cols == 40U) {
|
||||
char m_buffer1[40U];
|
||||
::sprintf(m_buffer1, "%.10s > %s%u", source, group ? "TG" : "", dest);
|
||||
|
||||
::lcdPosition(m_fd, 0, 1);
|
||||
|
@ -883,19 +866,19 @@ void CHD44780::writeP25Int(const char* source, bool group, unsigned int dest, co
|
|||
}
|
||||
|
||||
m_dmr = false;
|
||||
m_rssiCount1 = 0U;
|
||||
m_rssiCount1 = 0U;
|
||||
}
|
||||
|
||||
void CHD44780::writeP25RSSIInt(unsigned char rssi)
|
||||
{
|
||||
if (m_rssiCount1 == 0U && m_rows > 2) {
|
||||
void CHD44780::writeP25RSSIInt(unsigned char rssi)
|
||||
{
|
||||
if (m_rssiCount1 == 0U && m_rows > 2) {
|
||||
::lcdPosition(m_fd, 0, 3);
|
||||
::lcdPrintf(m_fd, "-%3udBm", rssi);
|
||||
}
|
||||
|
||||
m_rssiCount1++;
|
||||
if (m_rssiCount1 >= P25_RSSI_COUNT)
|
||||
m_rssiCount1 = 0U;
|
||||
}
|
||||
|
||||
m_rssiCount1++;
|
||||
if (m_rssiCount1 >= P25_RSSI_COUNT)
|
||||
m_rssiCount1 = 0U;
|
||||
}
|
||||
|
||||
void CHD44780::clearP25Int()
|
||||
|
@ -939,7 +922,7 @@ void CHD44780::writeNXDNInt(const char* source, bool group, unsigned int dest, c
|
|||
assert(type != NULL);
|
||||
|
||||
#ifdef ADAFRUIT_DISPLAY
|
||||
adafruitLCDColour(AC_RED);
|
||||
adafruitLCDColour(AC_RED);
|
||||
#endif
|
||||
|
||||
m_clockDisplayTimer.stop(); // Stop the clock display
|
||||
|
@ -956,10 +939,12 @@ void CHD44780::writeNXDNInt(const char* source, bool group, unsigned int dest, c
|
|||
::lcdPuts(m_fd, "NXDN");
|
||||
|
||||
if (m_rows == 2U && m_cols == 16U) {
|
||||
char m_buffer1[16U];
|
||||
::sprintf(m_buffer1, "%.10s >", source);
|
||||
::lcdPosition(m_fd, 0, 1);
|
||||
::lcdPrintf(m_fd, "%.*s", m_cols, m_buffer1);
|
||||
} else if (m_rows == 4U && m_cols == 16U) {
|
||||
char m_buffer1[16U];
|
||||
::sprintf(m_buffer1, "%.10s >", source);
|
||||
::lcdPosition(m_fd, 0, 1);
|
||||
::lcdPrintf(m_fd, "%.*s", m_cols, m_buffer1);
|
||||
|
@ -968,6 +953,7 @@ void CHD44780::writeNXDNInt(const char* source, bool group, unsigned int dest, c
|
|||
::lcdPosition(m_fd, 0, 2);
|
||||
::lcdPrintf(m_fd, "%.*s", m_cols, m_buffer1);
|
||||
} else if (m_rows == 4U && m_cols == 20U) {
|
||||
char m_buffer1[20U];
|
||||
::sprintf(m_buffer1, "%.10s >", source);
|
||||
::lcdPosition(m_fd, 0, 1);
|
||||
::lcdPrintf(m_fd, "%.*s", m_cols, m_buffer1);
|
||||
|
@ -976,25 +962,27 @@ void CHD44780::writeNXDNInt(const char* source, bool group, unsigned int dest, c
|
|||
::lcdPosition(m_fd, 0, 2);
|
||||
::lcdPrintf(m_fd, "%.*s", m_cols, m_buffer1);
|
||||
} else if (m_rows == 2 && m_cols == 40U) {
|
||||
char m_buffer1[40U];
|
||||
::sprintf(m_buffer1, "%.10s > %s%u", source, group ? "TG" : "", dest);
|
||||
|
||||
::lcdPosition(m_fd, 0, 1);
|
||||
::lcdPrintf(m_fd, "%.*s", m_cols, m_buffer1);
|
||||
}
|
||||
|
||||
m_dmr = false;
|
||||
m_rssiCount1 = 0U;
|
||||
m_rssiCount1 = 0U;
|
||||
}
|
||||
|
||||
void CHD44780::writeNXDNRSSIInt(unsigned char rssi)
|
||||
{
|
||||
if (m_rssiCount1 == 0U && m_rows > 2) {
|
||||
void CHD44780::writeNXDNRSSIInt(unsigned char rssi)
|
||||
{
|
||||
if (m_rssiCount1 == 0U && m_rows > 2) {
|
||||
::lcdPosition(m_fd, 0, 3);
|
||||
::lcdPrintf(m_fd, "-%3udBm", rssi);
|
||||
}
|
||||
|
||||
m_rssiCount1++;
|
||||
if (m_rssiCount1 >= NXDN_RSSI_COUNT)
|
||||
m_rssiCount1 = 0U;
|
||||
}
|
||||
|
||||
m_rssiCount1++;
|
||||
if (m_rssiCount1 >= NXDN_RSSI_COUNT)
|
||||
m_rssiCount1 = 0U;
|
||||
}
|
||||
|
||||
void CHD44780::clearNXDNInt()
|
||||
|
@ -1032,115 +1020,16 @@ void CHD44780::clearNXDNInt()
|
|||
}
|
||||
}
|
||||
|
||||
void CHD44780::writeM17Int(const char* source, const char* dest, const char* type)
|
||||
{
|
||||
assert(source != NULL);
|
||||
assert(dest != NULL);
|
||||
assert(type != NULL);
|
||||
|
||||
#ifdef ADAFRUIT_DISPLAY
|
||||
adafruitLCDColour(AC_RED);
|
||||
#endif
|
||||
|
||||
m_clockDisplayTimer.stop(); // Stop the clock display
|
||||
::lcdClear(m_fd);
|
||||
|
||||
if (m_pwm) {
|
||||
if (m_pwmPin != 1U)
|
||||
::softPwmWrite(m_pwmPin, m_pwmBright);
|
||||
else
|
||||
::pwmWrite(m_pwmPin, (m_pwmBright / 100) * 1024);
|
||||
}
|
||||
|
||||
::lcdPosition(m_fd, 0, 0);
|
||||
::lcdPuts(m_fd, "M17");
|
||||
|
||||
::sprintf(m_buffer1, "%.9s", source);
|
||||
::sprintf(m_buffer2, "%.9s", dest);
|
||||
|
||||
if (m_rows == 2U && m_cols == 16U) {
|
||||
::lcdPosition(m_fd, 5, 0);
|
||||
::lcdPrintf(m_fd, "%.*s", m_cols - 5, m_buffer1);
|
||||
::lcdPosition(m_fd, 5, 1);
|
||||
::lcdPrintf(m_fd, "%.*s", m_cols - 5, m_buffer2);
|
||||
} else if (m_rows == 4U && m_cols == 16U) {
|
||||
::lcdPosition(m_fd, 0, 1);
|
||||
::lcdPrintf(m_fd, "%.*s", m_cols, m_buffer1);
|
||||
::lcdPosition(m_fd, 0, 2);
|
||||
::lcdPrintf(m_fd, "%.*s", m_cols, m_buffer2);
|
||||
} else if (m_rows == 4U && m_cols == 20U) {
|
||||
::lcdPosition(m_fd, 0, 1);
|
||||
::lcdPrintf(m_fd, "%.*s", m_cols, m_buffer1);
|
||||
::lcdPosition(m_fd, 0, 2);
|
||||
::lcdPrintf(m_fd, "%.*s", m_cols, m_buffer1);
|
||||
} else if (m_rows == 2 && m_cols == 40U) {
|
||||
::sprintf(m_buffer1, "%.9s > %.9s", source, dest);
|
||||
::lcdPosition(m_fd, 0, 1);
|
||||
::lcdPrintf(m_fd, "%.*s", m_cols, m_buffer1);
|
||||
}
|
||||
|
||||
m_dmr = false;
|
||||
m_rssiCount1 = 0U;
|
||||
}
|
||||
|
||||
void CHD44780::writeM17RSSIInt(unsigned char rssi)
|
||||
{
|
||||
if (m_rssiCount1 == 0U && m_rows > 2) {
|
||||
::lcdPosition(m_fd, 0, 3);
|
||||
::lcdPrintf(m_fd, "-%3udBm", rssi);
|
||||
}
|
||||
|
||||
m_rssiCount1++;
|
||||
if (m_rssiCount1 >= M17_RSSI_COUNT)
|
||||
m_rssiCount1 = 0U;
|
||||
}
|
||||
|
||||
void CHD44780::clearM17Int()
|
||||
{
|
||||
#ifdef ADAFRUIT_DISPLAY
|
||||
adafruitLCDColour(AC_PURPLE);
|
||||
#endif
|
||||
m_clockDisplayTimer.stop(); // Stop the clock display
|
||||
|
||||
if (m_rows == 2U && m_cols == 16U) {
|
||||
::lcdPosition(m_fd, 5, 0);
|
||||
::lcdPrintf(m_fd, "%.*s", m_cols - 5, LISTENING);
|
||||
::lcdPosition(m_fd, 5, 1);
|
||||
::lcdPrintf(m_fd, "%.*s", m_cols - 5, " ");
|
||||
} else if (m_rows == 4U && m_cols == 16U) {
|
||||
::lcdPosition(m_fd, 0, 1);
|
||||
::lcdPrintf(m_fd, "%.*s", m_cols, LISTENING);
|
||||
|
||||
::lcdPosition(m_fd, 0, 2);
|
||||
::lcdPrintf(m_fd, "%.*s", m_cols, " ");
|
||||
|
||||
::lcdPosition(m_fd, 0, 3);
|
||||
::lcdPrintf(m_fd, "%.*s", m_cols, " ");
|
||||
} else if (m_rows == 4U && m_cols == 20U) {
|
||||
::lcdPosition(m_fd, 0, 1);
|
||||
::lcdPrintf(m_fd, "%.*s", m_cols, LISTENING);
|
||||
|
||||
::lcdPosition(m_fd, 0, 2);
|
||||
::lcdPrintf(m_fd, "%.*s", m_cols, " ");
|
||||
|
||||
::lcdPosition(m_fd, 0, 3);
|
||||
::lcdPrintf(m_fd, "%.*s", m_cols, " ");
|
||||
} else if (m_rows == 2 && m_cols == 40U) {
|
||||
::lcdPosition(m_fd, 0, 1);
|
||||
::lcdPrintf(m_fd, "%.*s", m_cols, LISTENING);
|
||||
}
|
||||
}
|
||||
|
||||
void CHD44780::writePOCSAGInt(uint32_t ric, const std::string& message)
|
||||
{
|
||||
::lcdPosition(m_fd, m_cols - 5, m_rows - 1);
|
||||
::lcdPuts(m_fd, "POCSG"); // Shortened "POCSAG TX" to 5 characters because it wraps around onto the next line (or on 16x2 displays the 1st line).
|
||||
::lcdPuts(m_fd, "POCSAG TX");
|
||||
}
|
||||
|
||||
void CHD44780::clearPOCSAGInt()
|
||||
{
|
||||
::lcdPosition(m_fd, m_cols - 5, m_rows - 1);
|
||||
::lcdPuts(m_fd, " Idle"); // Reverted back to 5 character implementation.
|
||||
::lcdPuts(m_fd, " Idle");
|
||||
}
|
||||
|
||||
void CHD44780::writeCWInt()
|
||||
|
@ -1161,30 +1050,31 @@ void CHD44780::clockInt(unsigned int ms)
|
|||
|
||||
// Idle clock display
|
||||
if (m_displayClock && m_clockDisplayTimer.isRunning() && m_clockDisplayTimer.hasExpired()) {
|
||||
time_t currentTime;
|
||||
struct tm *Time;
|
||||
::time(¤tTime);
|
||||
time_t currentTime;
|
||||
struct tm *Time;
|
||||
time(¤tTime);
|
||||
|
||||
if (m_utc)
|
||||
Time = ::gmtime(¤tTime);
|
||||
else
|
||||
Time = ::localtime(¤tTime);
|
||||
if (m_utc) {
|
||||
Time = gmtime(¤tTime);
|
||||
} else {
|
||||
Time = localtime(¤tTime);
|
||||
}
|
||||
|
||||
setlocale(LC_TIME,"");
|
||||
::strftime(m_buffer1, 128, "%X", Time); // Time
|
||||
::strftime(m_buffer2, 128, "%x", Time); // Date
|
||||
setlocale(LC_TIME,"");
|
||||
strftime(m_buffer1, 128, "%X", Time); // Time
|
||||
strftime(m_buffer2, 128, "%x", Time); // Date
|
||||
|
||||
if (m_cols == 16U && m_rows == 2U) {
|
||||
::lcdPosition(m_fd, m_cols - 10, 1);
|
||||
::lcdPrintf(m_fd, "%s%.*s", strlen(m_buffer1) > 8 ? "" : " ", 10, m_buffer1);
|
||||
} else {
|
||||
::lcdPosition(m_fd, (m_cols - (strlen(m_buffer1) == 8 ? 8 : 10)) / 2, m_rows == 2 ? 1 : 2);
|
||||
::lcdPrintf(m_fd, "%.*s", strlen(m_buffer1) == 8 ? 8 : 10, m_buffer1);
|
||||
::lcdPosition(m_fd, (m_cols - strlen(m_buffer2)) / 2, m_rows == 2 ? 0 : 1);
|
||||
::lcdPrintf(m_fd, "%s", m_buffer2);
|
||||
}
|
||||
if (m_cols == 16U && m_rows == 2U) {
|
||||
::lcdPosition(m_fd, m_cols - 10, 1);
|
||||
::lcdPrintf(m_fd, "%s%.*s", strlen(m_buffer1) > 8 ? "" : " ", 10, m_buffer1);
|
||||
} else {
|
||||
::lcdPosition(m_fd, (m_cols - (strlen(m_buffer1) == 8 ? 8 : 10)) / 2, m_rows == 2 ? 1 : 2);
|
||||
::lcdPrintf(m_fd, "%.*s", strlen(m_buffer1) == 8 ? 8 : 10, m_buffer1);
|
||||
::lcdPosition(m_fd, (m_cols - strlen(m_buffer2)) / 2, m_rows == 2 ? 0 : 1);
|
||||
::lcdPrintf(m_fd, "%s", m_buffer2);
|
||||
}
|
||||
|
||||
m_clockDisplayTimer.start();
|
||||
m_clockDisplayTimer.start();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
69
HD44780.h
69
HD44780.h
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2016,2017,2018,2020,2021 by Jonathan Naylor G4KLX & Tony Corbett G0WFV
|
||||
* Copyright (C) 2016,2017,2018 by Jonathan Naylor G4KLX & Tony Corbett G0WFV
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
@ -89,51 +89,46 @@ enum ADAFRUIT_COLOUR {
|
|||
class CHD44780 : public CDisplay
|
||||
{
|
||||
public:
|
||||
CHD44780(unsigned int rows, unsigned int cols, const std::string& callsign, unsigned int dmrid, const std::vector<unsigned int>& pins, unsigned int i2cAddress, bool pwm, unsigned int pwmPin, unsigned int pwmBright, unsigned int pwmDim, bool displayClock, bool utc, bool duplex);
|
||||
virtual ~CHD44780();
|
||||
CHD44780(unsigned int rows, unsigned int cols, const std::string& callsign, unsigned int dmrid, const std::vector<unsigned int>& pins, unsigned int i2cAddress, bool pwm, unsigned int pwmPin, unsigned int pwmBright, unsigned int pwmDim, bool displayClock, bool utc, bool duplex);
|
||||
virtual ~CHD44780();
|
||||
|
||||
virtual bool open();
|
||||
virtual bool open();
|
||||
|
||||
virtual void close();
|
||||
virtual void close();
|
||||
|
||||
protected:
|
||||
virtual void setIdleInt();
|
||||
virtual void setErrorInt(const char* text);
|
||||
virtual void setLockoutInt();
|
||||
virtual void setQuitInt();
|
||||
virtual void setFMInt();
|
||||
virtual void setIdleInt();
|
||||
virtual void setErrorInt(const char* text);
|
||||
virtual void setLockoutInt();
|
||||
virtual void setQuitInt();
|
||||
|
||||
virtual void writeDStarInt(const char* my1, const char* my2, const char* your, const char* type, const char* reflector);
|
||||
virtual void writeDStarRSSIInt(unsigned char rssi);
|
||||
virtual void clearDStarInt();
|
||||
virtual void writeDStarInt(const char* my1, const char* my2, const char* your, const char* type, const char* reflector);
|
||||
virtual void writeDStarRSSIInt(unsigned char rssi);
|
||||
virtual void clearDStarInt();
|
||||
|
||||
virtual void writeDMRInt(unsigned int slotNo, const std::string& src, bool group, const std::string& dst, const char* type);
|
||||
virtual void writeDMRRSSIInt(unsigned int slotNo, unsigned char rssi);
|
||||
virtual void clearDMRInt(unsigned int slotNo);
|
||||
virtual void writeDMRInt(unsigned int slotNo, const std::string& src, bool group, const std::string& dst, const char* type);
|
||||
virtual void writeDMRRSSIInt(unsigned int slotNo, unsigned char rssi);
|
||||
virtual void clearDMRInt(unsigned int slotNo);
|
||||
|
||||
virtual void writeFusionInt(const char* source, const char* dest, unsigned char dgid, const char* type, const char* origin);
|
||||
virtual void writeFusionRSSIInt(unsigned char rssi);
|
||||
virtual void clearFusionInt();
|
||||
virtual void writeFusionInt(const char* source, const char* dest, const char* type, const char* origin);
|
||||
virtual void writeFusionRSSIInt(unsigned char rssi);
|
||||
virtual void clearFusionInt();
|
||||
|
||||
virtual void writeP25Int(const char* source, bool group, unsigned int dest, const char* type);
|
||||
virtual void writeP25RSSIInt(unsigned char rssi);
|
||||
virtual void clearP25Int();
|
||||
virtual void writeP25Int(const char* source, bool group, unsigned int dest, const char* type);
|
||||
virtual void writeP25RSSIInt(unsigned char rssi);
|
||||
virtual void clearP25Int();
|
||||
|
||||
virtual void writeNXDNInt(const char* source, bool group, unsigned int dest, const char* type);
|
||||
virtual void writeNXDNRSSIInt(unsigned char rssi);
|
||||
virtual void clearNXDNInt();
|
||||
virtual void writeNXDNInt(const char* source, bool group, unsigned int dest, const char* type);
|
||||
virtual void writeNXDNRSSIInt(unsigned char rssi);
|
||||
virtual void clearNXDNInt();
|
||||
|
||||
virtual void writeM17Int(const char* source, const char* dest, const char* type);
|
||||
virtual void writeM17RSSIInt(unsigned char rssi);
|
||||
virtual void clearM17Int();
|
||||
virtual void writePOCSAGInt(uint32_t ric, const std::string& message);
|
||||
virtual void clearPOCSAGInt();
|
||||
|
||||
virtual void writePOCSAGInt(uint32_t ric, const std::string& message);
|
||||
virtual void clearPOCSAGInt();
|
||||
virtual void writeCWInt();
|
||||
virtual void clearCWInt();
|
||||
|
||||
virtual void writeCWInt();
|
||||
virtual void clearCWInt();
|
||||
|
||||
virtual void clockInt(unsigned int ms);
|
||||
virtual void clockInt(unsigned int ms);
|
||||
|
||||
private:
|
||||
unsigned int m_rows;
|
||||
|
@ -166,12 +161,12 @@ private:
|
|||
*/
|
||||
|
||||
#ifdef ADAFRUIT_DISPLAY
|
||||
void adafruitLCDSetup();
|
||||
void adafruitLCDColour(ADAFRUIT_COLOUR colour);
|
||||
void adafruitLCDSetup();
|
||||
void adafruitLCDColour(ADAFRUIT_COLOUR colour);
|
||||
#endif
|
||||
|
||||
#ifdef PCF8574_DISPLAY
|
||||
void pcf8574LCDSetup();
|
||||
void pcf8574LCDSetup();
|
||||
#endif
|
||||
};
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2002-2004,2007-2011,2013,2014-2017,2020 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2002-2004,2007-2011,2013,2014-2017 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 1999-2001 by Thomas Sailor HB9JNX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
|
@ -17,8 +17,6 @@
|
|||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#if defined(__linux__)
|
||||
|
||||
#include "I2CController.h"
|
||||
#include "Log.h"
|
||||
|
||||
|
@ -26,18 +24,52 @@
|
|||
#include <cassert>
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
|
||||
#include <setupapi.h>
|
||||
#include <winioctl.h>
|
||||
|
||||
CI2CController::CI2CController(const std::string& device, SERIAL_SPEED speed, unsigned int address, bool assertRTS) :
|
||||
CSerialController(device, speed, assertRTS),
|
||||
m_address(address)
|
||||
{
|
||||
}
|
||||
|
||||
CI2CController::~CI2CController()
|
||||
{
|
||||
}
|
||||
|
||||
bool CI2CController::open()
|
||||
{
|
||||
return CSerialController::open();
|
||||
}
|
||||
|
||||
int CI2CController::read(unsigned char* buffer, unsigned int length)
|
||||
{
|
||||
return CSerialController::read(buffer, length);
|
||||
}
|
||||
|
||||
int CI2CController::write(const unsigned char* buffer, unsigned int length)
|
||||
{
|
||||
return CSerialController::write(buffer, length);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/stat.h>
|
||||
#include <cerrno>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <termios.h>
|
||||
#if defined(__linux__)
|
||||
#include <linux/i2c-dev.h>
|
||||
#endif
|
||||
|
||||
CI2CController::CI2CController(const std::string& device, unsigned int address) :
|
||||
m_device(device),
|
||||
m_address(address),
|
||||
m_fd(-1)
|
||||
CI2CController::CI2CController(const std::string& device, SERIAL_SPEED speed, unsigned int address, bool assertRTS) :
|
||||
CSerialController(device, speed, assertRTS),
|
||||
m_address(address)
|
||||
{
|
||||
}
|
||||
|
||||
|
@ -49,6 +81,7 @@ bool CI2CController::open()
|
|||
{
|
||||
assert(m_fd == -1);
|
||||
|
||||
#if defined(__linux__)
|
||||
m_fd = ::open(m_device.c_str(), O_RDWR);
|
||||
if (m_fd < 0) {
|
||||
LogError("Cannot open device - %s", m_device.c_str());
|
||||
|
@ -56,16 +89,19 @@ bool CI2CController::open()
|
|||
}
|
||||
|
||||
if (::ioctl(m_fd, I2C_TENBIT, 0) < 0) {
|
||||
LogError("I2C: failed to set 7bitaddress");
|
||||
LogError("CI2C: failed to set 7bitaddress");
|
||||
::close(m_fd);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (::ioctl(m_fd, I2C_SLAVE, m_address) < 0) {
|
||||
LogError("I2C: Failed to acquire bus access/talk to slave 0x%02X", m_address);
|
||||
LogError("CI2C: Failed to acquire bus access/talk to slave 0x%02X", m_address);
|
||||
::close(m_fd);
|
||||
return false;
|
||||
}
|
||||
#else
|
||||
#warning "I2C controller supports Linux only"
|
||||
#endif
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -81,6 +117,7 @@ int CI2CController::read(unsigned char* buffer, unsigned int length)
|
|||
unsigned int offset = 0U;
|
||||
|
||||
while (offset < length) {
|
||||
#if defined(__linux__)
|
||||
ssize_t n = ::read(m_fd, buffer + offset, 1U);
|
||||
if (n < 0) {
|
||||
if (errno != EAGAIN) {
|
||||
|
@ -91,6 +128,7 @@ int CI2CController::read(unsigned char* buffer, unsigned int length)
|
|||
|
||||
if (n > 0)
|
||||
offset += n;
|
||||
#endif
|
||||
}
|
||||
|
||||
return length;
|
||||
|
@ -106,7 +144,10 @@ int CI2CController::write(const unsigned char* buffer, unsigned int length)
|
|||
|
||||
unsigned int ptr = 0U;
|
||||
while (ptr < length) {
|
||||
ssize_t n = ::write(m_fd, buffer + ptr, 1U);
|
||||
ssize_t n = 0U;
|
||||
#if defined(__linux__)
|
||||
n = ::write(m_fd, buffer + ptr, 1U);
|
||||
#endif
|
||||
if (n < 0) {
|
||||
if (errno != EAGAIN) {
|
||||
LogError("Error returned from write(), errno=%d", errno);
|
||||
|
@ -121,12 +162,4 @@ int CI2CController::write(const unsigned char* buffer, unsigned int length)
|
|||
return length;
|
||||
}
|
||||
|
||||
void CI2CController::close()
|
||||
{
|
||||
assert(m_fd != -1);
|
||||
|
||||
::close(m_fd);
|
||||
m_fd = -1;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2002-2004,2007-2009,2011-2013,2015-2017,2020,2021 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2002-2004,2007-2009,2011-2013,2015-2017 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 1999-2001 by Thomas Sailor HB9JNX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
|
@ -20,16 +20,11 @@
|
|||
#ifndef I2CController_H
|
||||
#define I2CController_H
|
||||
|
||||
#if defined(__linux__)
|
||||
#include "SerialController.h"
|
||||
|
||||
#include "ModemPort.h"
|
||||
#include "SerialPort.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
class CI2CController : public ISerialPort, public IModemPort {
|
||||
class CI2CController : public CSerialController {
|
||||
public:
|
||||
CI2CController(const std::string& device, unsigned int address = 0x22U);
|
||||
CI2CController(const std::string& device, SERIAL_SPEED speed, unsigned int address = 0x22U, bool assertRTS = false);
|
||||
virtual ~CI2CController();
|
||||
|
||||
virtual bool open();
|
||||
|
@ -38,14 +33,8 @@ public:
|
|||
|
||||
virtual int write(const unsigned char* buffer, unsigned int length);
|
||||
|
||||
virtual void close();
|
||||
|
||||
private:
|
||||
std::string m_device;
|
||||
unsigned int m_address;
|
||||
int m_fd;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
|
@ -1,60 +0,0 @@
|
|||
/*
|
||||
* Copyright (C) 2015-2020 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2020 by Geoffrey Merck - F4FXL KC3FRA
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include "IIRDirectForm1Filter.h"
|
||||
#include "math.h"
|
||||
|
||||
CIIRDirectForm1Filter::CIIRDirectForm1Filter(float b0, float b1, float b2, float , float a1, float a2, float addtionalGaindB) :
|
||||
m_x2(0.0F),
|
||||
m_y2(0.0F),
|
||||
m_x1(0.0F),
|
||||
m_y1(0.0F),
|
||||
m_b0(b0),
|
||||
m_b1(b1),
|
||||
m_b2(b2),
|
||||
m_a1(a1),
|
||||
m_a2(a2),
|
||||
m_additionalGainLin(0.0F)
|
||||
{
|
||||
m_additionalGainLin = ::powf(10.0F, addtionalGaindB / 20.0F);
|
||||
}
|
||||
|
||||
float CIIRDirectForm1Filter::filter(float sample)
|
||||
{
|
||||
float output = m_b0 * sample
|
||||
+ m_b1 * m_x1
|
||||
+ m_b2 * m_x2
|
||||
- m_a1 * m_y1
|
||||
- m_a2 * m_y2;
|
||||
|
||||
m_x2 = m_x1;
|
||||
m_y2 = m_y1;
|
||||
m_x1 = sample;
|
||||
m_y1 = output;
|
||||
|
||||
return output * m_additionalGainLin;
|
||||
}
|
||||
|
||||
void CIIRDirectForm1Filter::reset()
|
||||
{
|
||||
m_x1 = 0.0f;
|
||||
m_x2 = 0.0f;
|
||||
m_y1 = 0.0f;
|
||||
m_y2 = 0.0f;
|
||||
}
|
9
ISSUES.txt
Normal file
9
ISSUES.txt
Normal file
|
@ -0,0 +1,9 @@
|
|||
D-Star: On some radios, the header is not decoded correctly. It looks like frequency drift at the beginning of the transmission.
|
||||
|
||||
DMR: DMO mode doesn't wake up older radios like other radios do.
|
||||
|
||||
YSF: No known issues.
|
||||
|
||||
P25: Upgrade the filters, processing power in the Due permiting.
|
||||
|
||||
NXDN: No known issues.
|
BIN
Images/M17.bmp
BIN
Images/M17.bmp
Binary file not shown.
Before Width: | Height: | Size: 57 KiB |
182
LCDproc.cpp
182
LCDproc.cpp
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* Copyright (C) 2016,2017,2018 by Tony Corbett G0WFV
|
||||
* Copyright (C) 2018,2020 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2018 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
@ -72,7 +72,7 @@
|
|||
#include <unistd.h>
|
||||
#include <stdarg.h>
|
||||
#else
|
||||
#include <ws2tcpip.h>
|
||||
#include <winsock.h>
|
||||
#endif
|
||||
|
||||
#define BUFFER_MAX_LEN 128
|
||||
|
@ -95,9 +95,8 @@ const unsigned int DMR_RSSI_COUNT = 4U; // 4 * 360ms = 1440ms
|
|||
const unsigned int YSF_RSSI_COUNT = 13U; // 13 * 100ms = 1300ms
|
||||
const unsigned int P25_RSSI_COUNT = 7U; // 7 * 180ms = 1260ms
|
||||
const unsigned int NXDN_RSSI_COUNT = 28U; // 28 * 40ms = 1120ms
|
||||
const unsigned int M17_RSSI_COUNT = 28U; // 28 * 40ms = 1120ms
|
||||
|
||||
CLCDproc::CLCDproc(std::string address, unsigned int port, unsigned short localPort, const std::string& callsign, unsigned int dmrid, bool displayClock, bool utc, bool duplex, bool dimOnIdle) :
|
||||
CLCDproc::CLCDproc(std::string address, unsigned int port, unsigned int localPort, const std::string& callsign, unsigned int dmrid, bool displayClock, bool utc, bool duplex, bool dimOnIdle) :
|
||||
CDisplay(),
|
||||
m_address(address),
|
||||
m_port(port),
|
||||
|
@ -122,53 +121,44 @@ CLCDproc::~CLCDproc()
|
|||
|
||||
bool CLCDproc::open()
|
||||
{
|
||||
int err;
|
||||
unsigned int addrlen;
|
||||
std::string port, localPort;
|
||||
struct sockaddr_storage serverAddress, clientAddress;
|
||||
struct addrinfo hints, *res;
|
||||
const char *server;
|
||||
unsigned int port, localPort;
|
||||
struct sockaddr_in serverAddress, clientAddress;
|
||||
struct hostent *h;
|
||||
|
||||
port = std::to_string(m_port);
|
||||
localPort = std::to_string(m_localPort);
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
server = m_address.c_str();
|
||||
port = m_port;
|
||||
localPort = m_localPort;
|
||||
|
||||
/* Lookup the hostname address */
|
||||
hints.ai_flags = AI_NUMERICSERV;
|
||||
hints.ai_socktype = SOCK_STREAM;
|
||||
err = getaddrinfo(m_address.c_str(), port.c_str(), &hints, &res);
|
||||
if (err) {
|
||||
LogError("LCDproc, cannot lookup server");
|
||||
return false;
|
||||
}
|
||||
memcpy(&serverAddress, res->ai_addr, addrlen = res->ai_addrlen);
|
||||
freeaddrinfo(res);
|
||||
|
||||
/* Lookup the client address (random port - need to specify manual port from ini file) */
|
||||
hints.ai_flags = AI_NUMERICSERV | AI_PASSIVE;
|
||||
hints.ai_family = serverAddress.ss_family;
|
||||
err = getaddrinfo(NULL, localPort.c_str(), &hints, &res);
|
||||
if (err) {
|
||||
LogError("LCDproc, cannot lookup client");
|
||||
return false;
|
||||
}
|
||||
memcpy(&clientAddress, res->ai_addr, res->ai_addrlen);
|
||||
freeaddrinfo(res);
|
||||
|
||||
/* Create TCP socket */
|
||||
m_socketfd = socket(clientAddress.ss_family, SOCK_STREAM, 0);
|
||||
m_socketfd = socket(AF_INET, SOCK_STREAM, 0);
|
||||
if (m_socketfd == -1) {
|
||||
LogError("LCDproc, failed to create socket");
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Sets client address (random port - need to specify manual port from ini file?) */
|
||||
clientAddress.sin_family = AF_INET;
|
||||
clientAddress.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||
//clientAddress.sin_port = htons(0);
|
||||
clientAddress.sin_port = htons(localPort);
|
||||
|
||||
/* Bind the address to the socket */
|
||||
if (bind(m_socketfd, (struct sockaddr *)&clientAddress, addrlen) == -1) {
|
||||
if (bind(m_socketfd, (struct sockaddr *)&clientAddress, sizeof(clientAddress)) == -1) {
|
||||
LogError("LCDproc, error whilst binding address");
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Connect to server */
|
||||
if (connect(m_socketfd, (struct sockaddr *)&serverAddress, addrlen) == -1) {
|
||||
/* Lookup the hostname address */
|
||||
h = gethostbyname(server);
|
||||
|
||||
/* Sets server address */
|
||||
serverAddress.sin_family = h->h_addrtype;
|
||||
memcpy((char*)&serverAddress.sin_addr.s_addr, h->h_addr_list[0], h->h_length);
|
||||
serverAddress.sin_port = htons(port);
|
||||
|
||||
if (connect(m_socketfd, (struct sockaddr * )&serverAddress, sizeof(serverAddress))==-1) {
|
||||
LogError("LCDproc, cannot connect to server");
|
||||
return false;
|
||||
}
|
||||
|
@ -189,7 +179,6 @@ void CLCDproc::setIdleInt()
|
|||
socketPrintf(m_socketfd, "screen_set YSF -priority hidden");
|
||||
socketPrintf(m_socketfd, "screen_set P25 -priority hidden");
|
||||
socketPrintf(m_socketfd, "screen_set NXDN -priority hidden");
|
||||
socketPrintf(m_socketfd, "screen_set M17 -priority hidden");
|
||||
socketPrintf(m_socketfd, "widget_set Status Status %u %u Idle", m_cols - 3, m_rows);
|
||||
socketPrintf(m_socketfd, "output 0"); // Clear all LEDs
|
||||
}
|
||||
|
@ -209,7 +198,6 @@ void CLCDproc::setErrorInt(const char* text)
|
|||
socketPrintf(m_socketfd, "screen_set YSF -priority hidden");
|
||||
socketPrintf(m_socketfd, "screen_set P25 -priority hidden");
|
||||
socketPrintf(m_socketfd, "screen_set NXDN -priority hidden");
|
||||
socketPrintf(m_socketfd, "screen_set M17 -priority hidden");
|
||||
socketPrintf(m_socketfd, "widget_set Status Status %u %u Error", m_cols - 4, m_rows);
|
||||
socketPrintf(m_socketfd, "output 0"); // Clear all LEDs
|
||||
}
|
||||
|
@ -227,7 +215,6 @@ void CLCDproc::setLockoutInt()
|
|||
socketPrintf(m_socketfd, "screen_set YSF -priority hidden");
|
||||
socketPrintf(m_socketfd, "screen_set P25 -priority hidden");
|
||||
socketPrintf(m_socketfd, "screen_set NXDN -priority hidden");
|
||||
socketPrintf(m_socketfd, "screen_set M17 -priority hidden");
|
||||
socketPrintf(m_socketfd, "widget_set Status Status %u %u Lockout", m_cols - 6, m_rows);
|
||||
socketPrintf(m_socketfd, "output 0"); // Clear all LEDs
|
||||
}
|
||||
|
@ -247,7 +234,6 @@ void CLCDproc::setQuitInt()
|
|||
socketPrintf(m_socketfd, "screen_set YSF -priority hidden");
|
||||
socketPrintf(m_socketfd, "screen_set P25 -priority hidden");
|
||||
socketPrintf(m_socketfd, "screen_set NXDN -priority hidden");
|
||||
socketPrintf(m_socketfd, "screen_set M17 -priority hidden");
|
||||
socketPrintf(m_socketfd, "widget_set Status Status %u %u Stopped", m_cols - 6, m_rows);
|
||||
socketPrintf(m_socketfd, "output 0"); // Clear all LEDs
|
||||
}
|
||||
|
@ -255,24 +241,6 @@ void CLCDproc::setQuitInt()
|
|||
m_dmr = false;
|
||||
}
|
||||
|
||||
void CLCDproc::setFMInt()
|
||||
{
|
||||
m_clockDisplayTimer.stop(); // Stop the clock display
|
||||
|
||||
if (m_screensDefined) {
|
||||
socketPrintf(m_socketfd, "screen_set DStar -priority hidden");
|
||||
socketPrintf(m_socketfd, "screen_set DMR -priority hidden");
|
||||
socketPrintf(m_socketfd, "screen_set YSF -priority hidden");
|
||||
socketPrintf(m_socketfd, "screen_set P25 -priority hidden");
|
||||
socketPrintf(m_socketfd, "screen_set NXDN -priority hidden");
|
||||
socketPrintf(m_socketfd, "screen_set M17 -priority hidden");
|
||||
socketPrintf(m_socketfd, "widget_set Status Status %u %u FM", m_cols - 6, m_rows);
|
||||
socketPrintf(m_socketfd, "output 0"); // Clear all LEDs
|
||||
}
|
||||
|
||||
m_dmr = false;
|
||||
}
|
||||
|
||||
void CLCDproc::writeDStarInt(const char* my1, const char* my2, const char* your, const char* type, const char* reflector)
|
||||
{
|
||||
assert(my1 != NULL);
|
||||
|
@ -326,7 +294,7 @@ void CLCDproc::clearDStarInt()
|
|||
{
|
||||
m_clockDisplayTimer.stop(); // Stop the clock display
|
||||
|
||||
socketPrintf(m_socketfd, "widget_set DStar Line2 1 2 15 2 h 3 \"Listening\"");
|
||||
socketPrintf(m_socketfd, "widget_set DStar Line2 1 2 15 2 h 3 Listening");
|
||||
socketPrintf(m_socketfd, "widget_set DStar Line3 1 3 15 3 h 3 \"\"");
|
||||
socketPrintf(m_socketfd, "widget_set DStar Line4 1 4 15 4 h 3 \"\"");
|
||||
socketPrintf(m_socketfd, "output 8"); // Set LED4 color green
|
||||
|
@ -419,7 +387,7 @@ void CLCDproc::clearDMRInt(unsigned int slotNo)
|
|||
socketPrintf(m_socketfd, "widget_set DMR Slot2RSSI %u %u %*.s", (m_cols / 2) + 1, 4, m_cols / 2, " ");
|
||||
}
|
||||
} else {
|
||||
socketPrintf(m_socketfd, "widget_set DMR Slot1 1 2 15 2 h 3 \"Listening\"");
|
||||
socketPrintf(m_socketfd, "widget_set DMR Slot1 1 2 15 2 h 3 Listening");
|
||||
socketPrintf(m_socketfd, "widget_set DMR Slot2 1 3 15 3 h 3 \"\"");
|
||||
socketPrintf(m_socketfd, "widget_set DMR Slot2RSSI %u %u %*.s", (m_cols / 2) + 1, 4, m_cols / 2, " ");
|
||||
}
|
||||
|
@ -428,7 +396,7 @@ void CLCDproc::clearDMRInt(unsigned int slotNo)
|
|||
|
||||
// LED 3 Green 4 Red 64 Yellow 68
|
||||
|
||||
void CLCDproc::writeFusionInt(const char* source, const char* dest, unsigned char dgid, const char* type, const char* origin)
|
||||
void CLCDproc::writeFusionInt(const char* source, const char* dest, const char* type, const char* origin)
|
||||
{
|
||||
assert(source != NULL);
|
||||
assert(dest != NULL);
|
||||
|
@ -441,10 +409,10 @@ void CLCDproc::writeFusionInt(const char* source, const char* dest, unsigned cha
|
|||
socketPrintf(m_socketfd, "widget_set YSF Mode 1 1 \"System Fusion\"");
|
||||
|
||||
if (m_rows == 2U) {
|
||||
socketPrintf(m_socketfd, "widget_set YSF Line2 1 2 15 2 h 3 \"%.10s > DG-ID %u\"", source, dgid);
|
||||
socketPrintf(m_socketfd, "widget_set YSF Line2 1 2 15 2 h 3 \"%.10s > %s%u\"", source, dest);
|
||||
} else {
|
||||
socketPrintf(m_socketfd, "widget_set YSF Line2 1 2 15 2 h 3 \"%.10s >\"", source);
|
||||
socketPrintf(m_socketfd, "widget_set YSF Line3 1 3 15 3 h 3 \"DG-ID %u\"", dgid);
|
||||
socketPrintf(m_socketfd, "widget_set YSF Line3 1 3 15 3 h 3 \"%s%u\"", dest);
|
||||
socketPrintf(m_socketfd, "output 64"); // Set LED3 color red
|
||||
}
|
||||
|
||||
|
@ -454,19 +422,20 @@ void CLCDproc::writeFusionInt(const char* source, const char* dest, unsigned cha
|
|||
|
||||
void CLCDproc::writeFusionRSSIInt(unsigned char rssi)
|
||||
{
|
||||
if (m_rssiCount1 == 0U)
|
||||
if (m_rssiCount1 == 0U) {
|
||||
socketPrintf(m_socketfd, "widget_set YSF Line4 1 4 %u 4 h 3 \"-%3udBm\"", m_cols - 1, rssi);
|
||||
}
|
||||
|
||||
m_rssiCount1++;
|
||||
if (m_rssiCount1 >= YSF_RSSI_COUNT)
|
||||
m_rssiCount1 = 0U;
|
||||
if (m_rssiCount1 >= YSF_RSSI_COUNT)
|
||||
m_rssiCount1 = 0U;
|
||||
}
|
||||
|
||||
void CLCDproc::clearFusionInt()
|
||||
{
|
||||
m_clockDisplayTimer.stop(); // Stop the clock display
|
||||
|
||||
socketPrintf(m_socketfd, "widget_set YSF Line2 1 2 15 2 h 3 \"Listening\"");
|
||||
socketPrintf(m_socketfd, "widget_set YSF Line2 1 2 15 2 h 3 Listening");
|
||||
socketPrintf(m_socketfd, "widget_set YSF Line3 1 3 15 3 h 3 \"\"");
|
||||
socketPrintf(m_socketfd, "widget_set YSF Line4 1 4 15 4 h 3 \"\"");
|
||||
socketPrintf(m_socketfd, "output 4"); // Set LED3 color green
|
||||
|
@ -511,7 +480,7 @@ void CLCDproc::clearP25Int()
|
|||
{
|
||||
m_clockDisplayTimer.stop(); // Stop the clock display
|
||||
|
||||
socketPrintf(m_socketfd, "widget_set P25 Line2 1 2 15 2 h 3 \"Listening\"");
|
||||
socketPrintf(m_socketfd, "widget_set P25 Line2 1 2 15 2 h 3 Listening");
|
||||
socketPrintf(m_socketfd, "widget_set P25 Line3 1 3 15 3 h 3 \"\"");
|
||||
socketPrintf(m_socketfd, "widget_set P25 Line4 1 4 15 4 h 3 \"\"");
|
||||
socketPrintf(m_socketfd, "output 2"); // Set LED2 color green
|
||||
|
@ -556,57 +525,12 @@ void CLCDproc::clearNXDNInt()
|
|||
{
|
||||
m_clockDisplayTimer.stop(); // Stop the clock display
|
||||
|
||||
socketPrintf(m_socketfd, "widget_set NXDN Line2 1 2 15 2 h 3 \"Listening\"");
|
||||
socketPrintf(m_socketfd, "widget_set NXDN Line2 1 2 15 2 h 3 Listening");
|
||||
socketPrintf(m_socketfd, "widget_set NXDN Line3 1 3 15 3 h 3 \"\"");
|
||||
socketPrintf(m_socketfd, "widget_set NXDN Line4 1 4 15 4 h 3 \"\"");
|
||||
socketPrintf(m_socketfd, "output 16"); // Set LED5 color green
|
||||
}
|
||||
|
||||
void CLCDproc::writeM17Int(const char* source, const char* dest, const char* type)
|
||||
{
|
||||
assert(source != NULL);
|
||||
assert(dest != NULL);
|
||||
assert(type != NULL);
|
||||
|
||||
m_clockDisplayTimer.stop(); // Stop the clock display
|
||||
|
||||
socketPrintf(m_socketfd, "screen_set M17 -priority foreground");
|
||||
socketPrintf(m_socketfd, "widget_set M17 Mode 1 1 M17");
|
||||
|
||||
if (m_rows == 2U) {
|
||||
socketPrintf(m_socketfd, "widget_set M17 Line2 1 2 15 2 h 3 \"%.9s > %.9s\"", source, dest);
|
||||
}
|
||||
else {
|
||||
socketPrintf(m_socketfd, "widget_set M17 Line2 1 2 15 2 h 3 \"%.9s >\"", source);
|
||||
socketPrintf(m_socketfd, "widget_set M17 Line3 1 3 15 3 h 3 \"%.9ss\"", dest);
|
||||
socketPrintf(m_socketfd, "output 255"); // Set LED5 color red
|
||||
}
|
||||
|
||||
m_dmr = false;
|
||||
m_rssiCount1 = 0U;
|
||||
}
|
||||
|
||||
void CLCDproc::writeM17RSSIInt(unsigned char rssi)
|
||||
{
|
||||
if (m_rssiCount1 == 0U) {
|
||||
socketPrintf(m_socketfd, "widget_set M17 Line4 1 4 %u 4 h 3 \"-%3udBm\"", m_cols - 1, rssi);
|
||||
}
|
||||
|
||||
m_rssiCount1++;
|
||||
if (m_rssiCount1 >= M17_RSSI_COUNT)
|
||||
m_rssiCount1 = 0U;
|
||||
}
|
||||
|
||||
void CLCDproc::clearM17Int()
|
||||
{
|
||||
m_clockDisplayTimer.stop(); // Stop the clock display
|
||||
|
||||
socketPrintf(m_socketfd, "widget_set M17 Line2 1 2 15 2 h 3 \"Listening\"");
|
||||
socketPrintf(m_socketfd, "widget_set M17 Line3 1 3 15 3 h 3 \"\"");
|
||||
socketPrintf(m_socketfd, "widget_set M17 Line4 1 4 15 4 h 3 \"\"");
|
||||
socketPrintf(m_socketfd, "output 16"); // Set LED5 color green
|
||||
}
|
||||
|
||||
void CLCDproc::writePOCSAGInt(uint32_t ric, const std::string& message)
|
||||
{
|
||||
}
|
||||
|
@ -828,7 +752,7 @@ void CLCDproc::defineScreens()
|
|||
socketPrintf(m_socketfd, "widget_add DStar Line4 scroller");
|
||||
|
||||
/* Do we need to pre-populate the values??
|
||||
socketPrintf(m_socketfd, "widget_set DStar Line2 1 2 15 2 h 3 \"Listening\"");
|
||||
socketPrintf(m_socketfd, "widget_set DStar Line2 1 2 15 2 h 3 Listening");
|
||||
socketPrintf(m_socketfd, "widget_set DStar Line3 1 3 15 3 h 3 \"\"");
|
||||
socketPrintf(m_socketfd, "widget_set DStar Line4 1 4 15 4 h 3 \"\"");
|
||||
*/
|
||||
|
@ -849,8 +773,8 @@ void CLCDproc::defineScreens()
|
|||
/* Do we need to pre-populate the values??
|
||||
socketPrintf(m_socketfd, "widget_set DMR Slot1_ 1 %u 1", m_rows / 2);
|
||||
socketPrintf(m_socketfd, "widget_set DMR Slot2_ 1 %u 2", m_rows / 2 + 1);
|
||||
socketPrintf(m_socketfd, "widget_set DMR Slot1 3 1 15 1 h 3 \"Listening\"");
|
||||
socketPrintf(m_socketfd, "widget_set DMR Slot2 3 2 15 2 h 3 \"Listening\"");
|
||||
socketPrintf(m_socketfd, "widget_set DMR Slot1 3 1 15 1 h 3 Listening");
|
||||
socketPrintf(m_socketfd, "widget_set DMR Slot2 3 2 15 2 h 3 Listening");
|
||||
*/
|
||||
|
||||
// The YSF Screen
|
||||
|
@ -864,7 +788,7 @@ void CLCDproc::defineScreens()
|
|||
socketPrintf(m_socketfd, "widget_add YSF Line4 scroller");
|
||||
|
||||
/* Do we need to pre-populate the values??
|
||||
socketPrintf(m_socketfd, "widget_set YSF Line2 2 1 15 1 h 3 \"Listening\"");
|
||||
socketPrintf(m_socketfd, "widget_set YSF Line2 2 1 15 1 h 3 Listening");
|
||||
socketPrintf(m_socketfd, "widget_set YSF Line3 3 1 15 1 h 3 \" \"");
|
||||
socketPrintf(m_socketfd, "widget_set YSF Line4 4 2 15 2 h 3 \" \"");
|
||||
*/
|
||||
|
@ -880,7 +804,7 @@ void CLCDproc::defineScreens()
|
|||
socketPrintf(m_socketfd, "widget_add P25 Line4 scroller");
|
||||
|
||||
/* Do we need to pre-populate the values??
|
||||
socketPrintf(m_socketfd, "widget_set P25 Line3 2 1 15 1 h 3 \"Listening\"");
|
||||
socketPrintf(m_socketfd, "widget_set P25 Line3 2 1 15 1 h 3 Listening");
|
||||
socketPrintf(m_socketfd, "widget_set P25 Line3 3 1 15 1 h 3 \" \"");
|
||||
socketPrintf(m_socketfd, "widget_set P25 Line4 4 2 15 2 h 3 \" \"");
|
||||
*/
|
||||
|
@ -896,26 +820,10 @@ void CLCDproc::defineScreens()
|
|||
socketPrintf(m_socketfd, "widget_add NXDN Line4 scroller");
|
||||
|
||||
/* Do we need to pre-populate the values??
|
||||
socketPrintf(m_socketfd, "widget_set NXDN Line3 2 1 15 1 h 3 \"Listening\"");
|
||||
socketPrintf(m_socketfd, "widget_set NXDN Line3 2 1 15 1 h 3 Listening");
|
||||
socketPrintf(m_socketfd, "widget_set NXDN Line3 3 1 15 1 h 3 \" \"");
|
||||
socketPrintf(m_socketfd, "widget_set NXDN Line4 4 2 15 2 h 3 \" \"");
|
||||
*/
|
||||
|
||||
// The M17 Screen
|
||||
|
||||
socketPrintf(m_socketfd, "screen_add M17");
|
||||
socketPrintf(m_socketfd, "screen_set M17 -name M17 -heartbeat on -priority hidden -backlight on");
|
||||
|
||||
socketPrintf(m_socketfd, "widget_add M17 Mode string");
|
||||
socketPrintf(m_socketfd, "widget_add M17 Line2 scroller");
|
||||
socketPrintf(m_socketfd, "widget_add M17 Line3 scroller");
|
||||
socketPrintf(m_socketfd, "widget_add M17 Line4 scroller");
|
||||
|
||||
/* Do we need to pre-populate the values??
|
||||
socketPrintf(m_socketfd, "widget_set M17 Line3 2 1 15 1 h 3 \"Listening\"");
|
||||
socketPrintf(m_socketfd, "widget_set M17 Line3 3 1 15 1 h 3 \" \"");
|
||||
socketPrintf(m_socketfd, "widget_set M17 Line4 4 2 15 2 h 3 \" \"");
|
||||
*/
|
||||
|
||||
m_screensDefined = true;
|
||||
}
|
||||
|
|
14
LCDproc.h
14
LCDproc.h
|
@ -1,6 +1,6 @@
|
|||
/*
|
||||
* Copyright (C) 2016,2017 by Tony Corbett G0WFV
|
||||
* Copyright (C) 2018,2020 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2018 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
@ -28,7 +28,7 @@
|
|||
class CLCDproc : public CDisplay
|
||||
{
|
||||
public:
|
||||
CLCDproc(std::string address, unsigned int port, unsigned short localPort, const std::string& callsign, unsigned int dmrid, bool displayClock, bool utc, bool duplex, bool dimOnIdle);
|
||||
CLCDproc(std::string address, unsigned int port, unsigned int localPort, const std::string& callsign, unsigned int dmrid, bool displayClock, bool utc, bool duplex, bool dimOnIdle);
|
||||
virtual ~CLCDproc();
|
||||
|
||||
virtual bool open();
|
||||
|
@ -40,8 +40,8 @@ protected:
|
|||
virtual void setErrorInt(const char* text);
|
||||
virtual void setLockoutInt();
|
||||
virtual void setQuitInt();
|
||||
virtual void setFMInt();
|
||||
|
||||
|
||||
virtual void writeDStarInt(const char* my1, const char* my2, const char* your, const char* type, const char* reflector);
|
||||
virtual void writeDStarRSSIInt(unsigned char rssi);
|
||||
virtual void clearDStarInt();
|
||||
|
@ -50,7 +50,7 @@ protected:
|
|||
virtual void writeDMRRSSIInt(unsigned int slotNo, unsigned char rssi);
|
||||
virtual void clearDMRInt(unsigned int slotNo);
|
||||
|
||||
virtual void writeFusionInt(const char* source, const char* dest, unsigned char dgid, const char* type, const char* origin);
|
||||
virtual void writeFusionInt(const char* source, const char* dest, const char* type, const char* origin);
|
||||
virtual void writeFusionRSSIInt(unsigned char rssi);
|
||||
virtual void clearFusionInt();
|
||||
|
||||
|
@ -62,10 +62,6 @@ protected:
|
|||
virtual void writeNXDNRSSIInt(unsigned char rssi);
|
||||
virtual void clearNXDNInt();
|
||||
|
||||
virtual void writeM17Int(const char* source, const char* dest, const char* type);
|
||||
virtual void writeM17RSSIInt(unsigned char rssi);
|
||||
virtual void clearM17Int();
|
||||
|
||||
virtual void writePOCSAGInt(uint32_t ric, const std::string& message);
|
||||
virtual void clearPOCSAGInt();
|
||||
|
||||
|
@ -77,7 +73,7 @@ protected:
|
|||
private:
|
||||
std::string m_address;
|
||||
unsigned int m_port;
|
||||
unsigned short m_localPort;
|
||||
unsigned int m_localPort;
|
||||
std::string m_callsign;
|
||||
unsigned int m_dmrid;
|
||||
bool m_displayClock;
|
||||
|
|
88
Log.cpp
88
Log.cpp
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2015,2016,2020 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2015,2016 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
@ -22,7 +22,6 @@
|
|||
#include <Windows.h>
|
||||
#else
|
||||
#include <sys/time.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include <cstdio>
|
||||
|
@ -35,10 +34,8 @@
|
|||
static unsigned int m_fileLevel = 2U;
|
||||
static std::string m_filePath;
|
||||
static std::string m_fileRoot;
|
||||
static bool m_fileRotate = true;
|
||||
|
||||
static FILE* m_fpLog = NULL;
|
||||
static bool m_daemon = false;
|
||||
|
||||
static unsigned int m_displayLevel = 2U;
|
||||
|
||||
|
@ -46,10 +43,8 @@ static struct tm m_tm;
|
|||
|
||||
static char LEVELS[] = " DMIWEF";
|
||||
|
||||
static bool logOpenRotate()
|
||||
static bool LogOpen()
|
||||
{
|
||||
bool status = false;
|
||||
|
||||
if (m_fileLevel == 0U)
|
||||
return true;
|
||||
|
||||
|
@ -66,90 +61,39 @@ static bool logOpenRotate()
|
|||
::fclose(m_fpLog);
|
||||
}
|
||||
|
||||
char filename[200U];
|
||||
char filename[100U];
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
::sprintf(filename, "%s\\%s-%04d-%02d-%02d.log", m_filePath.c_str(), m_fileRoot.c_str(), tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday);
|
||||
#else
|
||||
::sprintf(filename, "%s/%s-%04d-%02d-%02d.log", m_filePath.c_str(), m_fileRoot.c_str(), tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday);
|
||||
#endif
|
||||
|
||||
if ((m_fpLog = ::fopen(filename, "a+t")) != NULL) {
|
||||
status = true;
|
||||
|
||||
#if !defined(_WIN32) && !defined(_WIN64)
|
||||
if (m_daemon)
|
||||
dup2(fileno(m_fpLog), fileno(stderr));
|
||||
#endif
|
||||
}
|
||||
|
||||
m_fpLog = ::fopen(filename, "a+t");
|
||||
m_tm = *tm;
|
||||
|
||||
return status;
|
||||
return m_fpLog != NULL;
|
||||
}
|
||||
|
||||
static bool logOpenNoRotate()
|
||||
{
|
||||
bool status = false;
|
||||
|
||||
if (m_fileLevel == 0U)
|
||||
return true;
|
||||
|
||||
if (m_fpLog != NULL)
|
||||
return true;
|
||||
|
||||
char filename[200U];
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
::sprintf(filename, "%s\\%s.log", m_filePath.c_str(), m_fileRoot.c_str());
|
||||
#else
|
||||
::sprintf(filename, "%s/%s.log", m_filePath.c_str(), m_fileRoot.c_str());
|
||||
#endif
|
||||
|
||||
if ((m_fpLog = ::fopen(filename, "a+t")) != NULL) {
|
||||
status = true;
|
||||
|
||||
#if !defined(_WIN32) && !defined(_WIN64)
|
||||
if (m_daemon)
|
||||
dup2(fileno(m_fpLog), fileno(stderr));
|
||||
#endif
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
bool LogOpen()
|
||||
{
|
||||
if (m_fileRotate)
|
||||
return logOpenRotate();
|
||||
else
|
||||
return logOpenNoRotate();
|
||||
}
|
||||
|
||||
bool LogInitialise(bool daemon, const std::string& filePath, const std::string& fileRoot, unsigned int fileLevel, unsigned int displayLevel, bool rotate)
|
||||
bool LogInitialise(const std::string& filePath, const std::string& fileRoot, unsigned int fileLevel, unsigned int displayLevel)
|
||||
{
|
||||
m_filePath = filePath;
|
||||
m_fileRoot = fileRoot;
|
||||
m_fileLevel = fileLevel;
|
||||
m_displayLevel = displayLevel;
|
||||
m_daemon = daemon;
|
||||
m_fileRotate = rotate;
|
||||
|
||||
if (m_daemon)
|
||||
m_displayLevel = 0U;
|
||||
|
||||
return ::LogOpen();
|
||||
return ::LogOpen();
|
||||
}
|
||||
|
||||
void LogFinalise()
|
||||
{
|
||||
if (m_fpLog != NULL)
|
||||
::fclose(m_fpLog);
|
||||
if (m_fpLog != NULL)
|
||||
::fclose(m_fpLog);
|
||||
}
|
||||
|
||||
void Log(unsigned int level, const char* fmt, ...)
|
||||
{
|
||||
assert(fmt != NULL);
|
||||
assert(fmt != NULL);
|
||||
|
||||
char buffer[501U];
|
||||
char buffer[300U];
|
||||
#if defined(_WIN32) || defined(_WIN64)
|
||||
SYSTEMTIME st;
|
||||
::GetSystemTime(&st);
|
||||
|
@ -161,13 +105,13 @@ void Log(unsigned int level, const char* fmt, ...)
|
|||
|
||||
struct tm* tm = ::gmtime(&now.tv_sec);
|
||||
|
||||
::sprintf(buffer, "%c: %04d-%02d-%02d %02d:%02d:%02d.%03lld ", LEVELS[level], tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec, now.tv_usec / 1000LL);
|
||||
::sprintf(buffer, "%c: %04d-%02d-%02d %02d:%02d:%02d.%03lu ", LEVELS[level], tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec, now.tv_usec / 1000U);
|
||||
#endif
|
||||
|
||||
va_list vl;
|
||||
va_start(vl, fmt);
|
||||
|
||||
::vsnprintf(buffer + ::strlen(buffer), 500, fmt, vl);
|
||||
::vsprintf(buffer + ::strlen(buffer), fmt, vl);
|
||||
|
||||
va_end(vl);
|
||||
|
||||
|
@ -186,7 +130,7 @@ void Log(unsigned int level, const char* fmt, ...)
|
|||
}
|
||||
|
||||
if (level == 6U) { // Fatal
|
||||
::fclose(m_fpLog);
|
||||
exit(1);
|
||||
}
|
||||
::fclose(m_fpLog);
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
|
4
Log.h
4
Log.h
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2015,2016,2020 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2015,2016 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
@ -30,7 +30,7 @@
|
|||
|
||||
extern void Log(unsigned int level, const char* fmt, ...);
|
||||
|
||||
extern bool LogInitialise(bool daemon, const std::string& filePath, const std::string& fileRoot, unsigned int fileLevel, unsigned int displayLevel, bool rotate);
|
||||
extern bool LogInitialise(const std::string& filePath, const std::string& fileRoot, unsigned int fileLevel, unsigned int displayLevel);
|
||||
extern void LogFinalise();
|
||||
|
||||
#endif
|
||||
|
|
157
MMDVM.ini
157
MMDVM.ini
|
@ -1,6 +1,6 @@
|
|||
[General]
|
||||
Callsign=MUTRPT
|
||||
Id=1337
|
||||
Callsign=G9BF
|
||||
Id=123456
|
||||
Timeout=180
|
||||
Duplex=1
|
||||
# ModeHang=10
|
||||
|
@ -13,6 +13,12 @@ Daemon=0
|
|||
RXFrequency=435000000
|
||||
TXFrequency=435000000
|
||||
Power=1
|
||||
Latitude=0.0
|
||||
Longitude=0.0
|
||||
Height=0
|
||||
Location=Nowhere
|
||||
Description=Multi-Mode Repeater
|
||||
URL=www.google.co.uk
|
||||
|
||||
[Log]
|
||||
# Logging levels, 0=No logging
|
||||
|
@ -20,7 +26,6 @@ DisplayLevel=1
|
|||
FileLevel=1
|
||||
FilePath=.
|
||||
FileRoot=MMDVM
|
||||
FileRotate=1
|
||||
|
||||
[CW Id]
|
||||
Enable=1
|
||||
|
@ -31,23 +36,16 @@ Time=10
|
|||
File=DMRIds.dat
|
||||
Time=24
|
||||
|
||||
[Modem]
|
||||
# Valid values are "null", "uart", "udp", and (on Linux) "i2c"
|
||||
Protocol=uart
|
||||
# The port and speed used for a UART connection
|
||||
# UARTPort=\\.\COM4
|
||||
# UARTPort=/dev/ttyACM0
|
||||
UARTPort=/dev/ttyAMA0
|
||||
UARTSpeed=460800
|
||||
# The port and address for an I2C connection
|
||||
I2CPort=/dev/i2c
|
||||
I2CAddress=0x22
|
||||
# IP parameters for UDP connection
|
||||
ModemAddress=192.168.2.100
|
||||
ModemPort=3334
|
||||
LocalAddress=192.168.2.1
|
||||
LocalPort=3335
|
||||
[NXDN Id Lookup]
|
||||
File=NXDN.csv
|
||||
Time=24
|
||||
|
||||
[Modem]
|
||||
# Port=/dev/ttyACM0
|
||||
# Port=/dev/ttyAMA0
|
||||
Port=\\.\COM3
|
||||
Protocol=uart
|
||||
# Address=0x22
|
||||
TXInvert=1
|
||||
RXInvert=0
|
||||
PTTInvert=0
|
||||
|
@ -60,9 +58,14 @@ TXLevel=50
|
|||
RXDCOffset=0
|
||||
TXDCOffset=0
|
||||
RFLevel=100
|
||||
DMRTXLevel=50
|
||||
# CWIdTXLevel=50
|
||||
# D-StarTXLevel=50
|
||||
# DMRTXLevel=50
|
||||
# YSFTXLevel=50
|
||||
# P25TXLevel=50
|
||||
# NXDNTXLevel=50
|
||||
# POCSAGTXLevel=50
|
||||
RSSIMappingFile=RSSI.dat
|
||||
UseCOSAsLockout=0
|
||||
Trace=0
|
||||
Debug=0
|
||||
|
||||
|
@ -73,12 +76,28 @@ RemotePort=40094
|
|||
LocalPort=40095
|
||||
# SendFrameType=0
|
||||
|
||||
[UMP]
|
||||
Enable=0
|
||||
# Port=\\.\COM4
|
||||
Port=/dev/ttyACM1
|
||||
|
||||
[D-Star]
|
||||
Enable=1
|
||||
Module=C
|
||||
SelfOnly=0
|
||||
AckReply=1
|
||||
AckTime=750
|
||||
AckMessage=0
|
||||
ErrorReply=1
|
||||
RemoteGateway=0
|
||||
# ModeHang=10
|
||||
|
||||
[DMR]
|
||||
Enable=1
|
||||
Beacons=0
|
||||
BeaconInterval=60
|
||||
BeaconDuration=3
|
||||
ColorCode=7
|
||||
ColorCode=1
|
||||
SelfOnly=0
|
||||
EmbeddedLCOnly=0
|
||||
DumpTAData=1
|
||||
|
@ -88,23 +107,88 @@ DumpTAData=1
|
|||
CallHang=3
|
||||
TXHang=4
|
||||
# ModeHang=10
|
||||
# OVCM Values, 0=off, 1=rx_on, 2=tx_on, 3=both_on, 4=force off
|
||||
# OVCM=0
|
||||
|
||||
[System Fusion]
|
||||
Enable=1
|
||||
LowDeviation=0
|
||||
SelfOnly=0
|
||||
TXHang=4
|
||||
#DGID=1
|
||||
RemoteGateway=0
|
||||
# ModeHang=10
|
||||
|
||||
[P25]
|
||||
Enable=1
|
||||
NAC=293
|
||||
SelfOnly=0
|
||||
OverrideUIDCheck=0
|
||||
RemoteGateway=0
|
||||
# ModeHang=10
|
||||
|
||||
[NXDN]
|
||||
Enable=1
|
||||
RAN=1
|
||||
SelfOnly=0
|
||||
RemoteGateway=0
|
||||
# ModeHang=10
|
||||
|
||||
[POCSAG]
|
||||
Enable=1
|
||||
Frequency=439987500
|
||||
|
||||
[D-Star Network]
|
||||
Enable=1
|
||||
GatewayAddress=127.0.0.1
|
||||
GatewayPort=20010
|
||||
LocalPort=20011
|
||||
# ModeHang=3
|
||||
Debug=0
|
||||
|
||||
[DMR Network]
|
||||
Enable=1
|
||||
# Type may be either 'Direct' or 'Gateway'. When Direct you must provide the Master's
|
||||
# address as well as the Password, and for DMR+, Options also.
|
||||
Type=Direct
|
||||
LocalAddress=127.0.0.1
|
||||
LocalPort=62032
|
||||
RemoteAddress=127.0.0.1
|
||||
RemotePort=62031
|
||||
# Password=P@ssw0rd1234
|
||||
Address=44.131.4.1
|
||||
Port=62031
|
||||
Jitter=360
|
||||
# Local=62032
|
||||
Password=PASSWORD
|
||||
# Options=
|
||||
Slot1=1
|
||||
Slot2=1
|
||||
# Options=
|
||||
# ModeHang=3
|
||||
Debug=0
|
||||
|
||||
[System Fusion Network]
|
||||
Enable=1
|
||||
LocalAddress=127.0.0.1
|
||||
LocalPort=3200
|
||||
GatewayAddress=127.0.0.1
|
||||
GatewayPort=4200
|
||||
# ModeHang=3
|
||||
Debug=0
|
||||
|
||||
[P25 Network]
|
||||
Enable=1
|
||||
GatewayAddress=127.0.0.1
|
||||
GatewayPort=42020
|
||||
LocalPort=32010
|
||||
# ModeHang=3
|
||||
Debug=0
|
||||
|
||||
[NXDN Network]
|
||||
Enable=1
|
||||
LocalAddress=127.0.0.1
|
||||
LocalPort=14021
|
||||
GatewayAddress=127.0.0.1
|
||||
GatewayPort=14020
|
||||
# ModeHang=3
|
||||
Debug=0
|
||||
|
||||
[POCSAG Network]
|
||||
Enable=1
|
||||
LocalAddress=127.0.0.1
|
||||
LocalPort=3800
|
||||
GatewayAddress=127.0.0.1
|
||||
GatewayPort=4800
|
||||
# ModeHang=3
|
||||
Debug=0
|
||||
|
||||
|
@ -150,7 +234,6 @@ Invert=0
|
|||
Scroll=1
|
||||
Rotate=0
|
||||
Cast=0
|
||||
LogoScreensaver=1
|
||||
|
||||
[LCDproc]
|
||||
Address=localhost
|
||||
|
@ -164,7 +247,11 @@ UTC=0
|
|||
Enable=0
|
||||
File=/tmp/MMDVM_Active.lck
|
||||
|
||||
[Remote Control]
|
||||
[Mobile GPS]
|
||||
Enable=0
|
||||
Address=127.0.0.1
|
||||
Port=7834
|
||||
|
||||
[Remote Control]
|
||||
Enable=0
|
||||
Port=7642
|
||||
|
|
1261
MMDVMHost.cpp
1261
MMDVMHost.cpp
File diff suppressed because it is too large
Load diff
66
MMDVMHost.h
66
MMDVMHost.h
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2015-2021 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2015-2019 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
@ -20,34 +20,31 @@
|
|||
#define MMDVMHOST_H
|
||||
|
||||
#include "RemoteControl.h"
|
||||
//#include "POCSAGNetwork.h"
|
||||
//#include "POCSAGControl.h"
|
||||
//#include "DStarNetwork.h"
|
||||
//#include "AX25Network.h"
|
||||
//#include "NXDNNetwork.h"
|
||||
//#include "DStarControl.h"
|
||||
//#include "AX25Control.h"
|
||||
#include "POCSAGNetwork.h"
|
||||
#include "POCSAGControl.h"
|
||||
#include "DStarNetwork.h"
|
||||
#include "NXDNNetwork.h"
|
||||
#include "DStarControl.h"
|
||||
#include "DMRControl.h"
|
||||
//#include "YSFControl.h"
|
||||
//#include "P25Control.h"
|
||||
//#include "NXDNControl.h"
|
||||
//#include "M17Control.h"
|
||||
//#include "NXDNLookup.h"
|
||||
//#include "YSFNetwork.h"
|
||||
//#include "P25Network.h"
|
||||
#include "YSFControl.h"
|
||||
#include "P25Control.h"
|
||||
#include "NXDNControl.h"
|
||||
#include "NXDNLookup.h"
|
||||
#include "YSFNetwork.h"
|
||||
#include "P25Network.h"
|
||||
#include "DMRNetwork.h"
|
||||
//#include "M17Network.h"
|
||||
//#include "FMNetwork.h"
|
||||
#include "DMRLookup.h"
|
||||
//#include "FMControl.h"
|
||||
//#include "Display.h"
|
||||
#include "MobileGPS.h"
|
||||
#include "Display.h"
|
||||
#include "Timer.h"
|
||||
#include "Modem.h"
|
||||
#include "Conf.h"
|
||||
#include "UMP.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
|
||||
|
||||
class CMMDVMHost
|
||||
{
|
||||
public:
|
||||
|
@ -56,33 +53,35 @@ public:
|
|||
|
||||
int run();
|
||||
|
||||
void buildNetworkStatusString(std::string &str);
|
||||
void buildNetworkHostsString(std::string &str);
|
||||
|
||||
private:
|
||||
CConf m_conf;
|
||||
CModem* m_modem;
|
||||
CDStarControl* m_dstar;
|
||||
CDMRControl* m_dmr;
|
||||
|
||||
IDMRNetwork* m_dmrNetwork;
|
||||
|
||||
CYSFControl* m_ysf;
|
||||
CP25Control* m_p25;
|
||||
CNXDNControl* m_nxdn;
|
||||
CPOCSAGControl* m_pocsag;
|
||||
CDStarNetwork* m_dstarNetwork;
|
||||
CDMRNetwork* m_dmrNetwork;
|
||||
CYSFNetwork* m_ysfNetwork;
|
||||
CP25Network* m_p25Network;
|
||||
CNXDNNetwork* m_nxdnNetwork;
|
||||
CPOCSAGNetwork* m_pocsagNetwork;
|
||||
CDisplay* m_display;
|
||||
CUMP* m_ump;
|
||||
unsigned char m_mode;
|
||||
unsigned int m_dstarRFModeHang;
|
||||
unsigned int m_dmrRFModeHang;
|
||||
unsigned int m_ysfRFModeHang;
|
||||
unsigned int m_p25RFModeHang;
|
||||
unsigned int m_nxdnRFModeHang;
|
||||
unsigned int m_m17RFModeHang;
|
||||
unsigned int m_fmRFModeHang;
|
||||
unsigned int m_dstarNetModeHang;
|
||||
unsigned int m_dmrNetModeHang;
|
||||
unsigned int m_ysfNetModeHang;
|
||||
unsigned int m_p25NetModeHang;
|
||||
unsigned int m_nxdnNetModeHang;
|
||||
unsigned int m_m17NetModeHang;
|
||||
unsigned int m_pocsagNetModeHang;
|
||||
unsigned int m_fmNetModeHang;
|
||||
CTimer m_modeTimer;
|
||||
CTimer m_dmrTXTimer;
|
||||
CTimer m_cwIdTimer;
|
||||
|
@ -93,17 +92,16 @@ private:
|
|||
bool m_ysfEnabled;
|
||||
bool m_p25Enabled;
|
||||
bool m_nxdnEnabled;
|
||||
bool m_m17Enabled;
|
||||
bool m_pocsagEnabled;
|
||||
bool m_fmEnabled;
|
||||
bool m_ax25Enabled;
|
||||
unsigned int m_cwIdTime;
|
||||
CDMRLookup* m_dmrLookup;
|
||||
CNXDNLookup* m_nxdnLookup;
|
||||
std::string m_callsign;
|
||||
unsigned int m_id;
|
||||
std::string m_cwCallsign;
|
||||
bool m_lockFileEnabled;
|
||||
std::string m_lockFileName;
|
||||
CMobileGPS* m_mobileGPS;
|
||||
CRemoteControl* m_remoteControl;
|
||||
bool m_fixedMode;
|
||||
|
||||
|
@ -114,14 +112,10 @@ private:
|
|||
bool createYSFNetwork();
|
||||
bool createP25Network();
|
||||
bool createNXDNNetwork();
|
||||
bool createM17Network();
|
||||
bool createPOCSAGNetwork();
|
||||
bool createFMNetwork();
|
||||
bool createAX25Network();
|
||||
|
||||
void remoteControl();
|
||||
void processModeCommand(unsigned char mode, unsigned int timeout);
|
||||
void processEnableCommand(bool& mode, bool enabled);
|
||||
|
||||
void setMode(unsigned char mode);
|
||||
|
||||
|
|
41
MMDVMHost.sln
Normal file
41
MMDVMHost.sln
Normal file
|
@ -0,0 +1,41 @@
|
|||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio 15
|
||||
VisualStudioVersion = 15.0.28307.271
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MMDVMHost", "MMDVMHost.vcxproj", "{1D34E8C1-CFA5-4D60-B509-9DB58DC4AE92}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "RemoteCommand", "RemoteCommand.vcxproj", "{5A61AB93-58BB-413A-BBD9-A26284CB37AE}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|x64 = Debug|x64
|
||||
Debug|x86 = Debug|x86
|
||||
Release|x64 = Release|x64
|
||||
Release|x86 = Release|x86
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{1D34E8C1-CFA5-4D60-B509-9DB58DC4AE92}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{1D34E8C1-CFA5-4D60-B509-9DB58DC4AE92}.Debug|x64.Build.0 = Debug|x64
|
||||
{1D34E8C1-CFA5-4D60-B509-9DB58DC4AE92}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{1D34E8C1-CFA5-4D60-B509-9DB58DC4AE92}.Debug|x86.Build.0 = Debug|Win32
|
||||
{1D34E8C1-CFA5-4D60-B509-9DB58DC4AE92}.Release|x64.ActiveCfg = Release|x64
|
||||
{1D34E8C1-CFA5-4D60-B509-9DB58DC4AE92}.Release|x64.Build.0 = Release|x64
|
||||
{1D34E8C1-CFA5-4D60-B509-9DB58DC4AE92}.Release|x86.ActiveCfg = Release|Win32
|
||||
{1D34E8C1-CFA5-4D60-B509-9DB58DC4AE92}.Release|x86.Build.0 = Release|Win32
|
||||
{5A61AB93-58BB-413A-BBD9-A26284CB37AE}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{5A61AB93-58BB-413A-BBD9-A26284CB37AE}.Debug|x64.Build.0 = Debug|x64
|
||||
{5A61AB93-58BB-413A-BBD9-A26284CB37AE}.Debug|x86.ActiveCfg = Debug|Win32
|
||||
{5A61AB93-58BB-413A-BBD9-A26284CB37AE}.Debug|x86.Build.0 = Debug|Win32
|
||||
{5A61AB93-58BB-413A-BBD9-A26284CB37AE}.Release|x64.ActiveCfg = Release|x64
|
||||
{5A61AB93-58BB-413A-BBD9-A26284CB37AE}.Release|x64.Build.0 = Release|x64
|
||||
{5A61AB93-58BB-413A-BBD9-A26284CB37AE}.Release|x86.ActiveCfg = Release|Win32
|
||||
{5A61AB93-58BB-413A-BBD9-A26284CB37AE}.Release|x86.Build.0 = Release|Win32
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {4FE84D69-7345-440E-8E0A-0CC1C84477F8}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
338
MMDVMHost.vcxproj
Normal file
338
MMDVMHost.vcxproj
Normal file
|
@ -0,0 +1,338 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{1D34E8C1-CFA5-4D60-B509-9DB58DC4AE92}</ProjectGuid>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<RootNamespace>MMDVMHost</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>10.0.15063.0</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<PlatformToolset>v141</PlatformToolset>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="Shared">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<LinkIncremental>true</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<LinkIncremental>false</LinkIncremental>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PreprocessorDefinitions>_DEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
<PreBuildEvent>
|
||||
<Command>"$(ProjectDir)prebuild.cmd" $(ProjectDir)</Command>
|
||||
</PreBuildEvent>
|
||||
<PreBuildEvent>
|
||||
<Message>prebuild.cmd generates GitVersion.h from git refs heads master</Message>
|
||||
</PreBuildEvent>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<PrecompiledHeader>
|
||||
</PrecompiledHeader>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
<PreprocessorDefinitions>NDEBUG;_CONSOLE;_CRT_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="AMBEFEC.h" />
|
||||
<ClInclude Include="BCH.h" />
|
||||
<ClInclude Include="BPTC19696.h" />
|
||||
<ClInclude Include="CASTInfo.h" />
|
||||
<ClInclude Include="Conf.h" />
|
||||
<ClInclude Include="CRC.h" />
|
||||
<ClInclude Include="Defines.h" />
|
||||
<ClInclude Include="Display.h" />
|
||||
<ClInclude Include="DMRAccessControl.h" />
|
||||
<ClInclude Include="DMRControl.h" />
|
||||
<ClInclude Include="DMRCSBK.h" />
|
||||
<ClInclude Include="DMRData.h" />
|
||||
<ClInclude Include="DMRDataHeader.h" />
|
||||
<ClInclude Include="DMRDefines.h" />
|
||||
<ClInclude Include="DMREMB.h" />
|
||||
<ClInclude Include="DMREmbeddedData.h" />
|
||||
<ClInclude Include="DMRFullLC.h" />
|
||||
<ClInclude Include="DMRLC.h" />
|
||||
<ClInclude Include="DMRNetwork.h" />
|
||||
<ClInclude Include="DMRShortLC.h" />
|
||||
<ClInclude Include="DMRSlot.h" />
|
||||
<ClInclude Include="DMRSlotType.h" />
|
||||
<ClInclude Include="DMRTA.h" />
|
||||
<ClInclude Include="DMRTrellis.h" />
|
||||
<ClInclude Include="DStarControl.h" />
|
||||
<ClInclude Include="DStarDefines.h" />
|
||||
<ClInclude Include="DStarHeader.h" />
|
||||
<ClInclude Include="DStarNetwork.h" />
|
||||
<ClInclude Include="DStarSlowData.h" />
|
||||
<ClInclude Include="Golay2087.h" />
|
||||
<ClInclude Include="Golay24128.h" />
|
||||
<ClInclude Include="Hamming.h" />
|
||||
<ClInclude Include="DMRLookup.h" />
|
||||
<ClInclude Include="I2CController.h" />
|
||||
<ClInclude Include="LCDproc.h" />
|
||||
<ClInclude Include="Log.h" />
|
||||
<ClInclude Include="MMDVMHost.h" />
|
||||
<ClInclude Include="MobileGPS.h" />
|
||||
<ClInclude Include="Modem.h" />
|
||||
<ClInclude Include="ModemSerialPort.h" />
|
||||
<ClInclude Include="Mutex.h" />
|
||||
<ClInclude Include="NetworkInfo.h" />
|
||||
<ClInclude Include="Nextion.h" />
|
||||
<ClInclude Include="NullDisplay.h" />
|
||||
<ClInclude Include="NullModem.h" />
|
||||
<ClInclude Include="NXDNAudio.h" />
|
||||
<ClInclude Include="NXDNControl.h" />
|
||||
<ClInclude Include="NXDNConvolution.h" />
|
||||
<ClInclude Include="NXDNCRC.h" />
|
||||
<ClInclude Include="NXDNDefines.h" />
|
||||
<ClInclude Include="NXDNFACCH1.h" />
|
||||
<ClInclude Include="NXDNLayer3.h" />
|
||||
<ClInclude Include="NXDNLICH.h" />
|
||||
<ClInclude Include="NXDNLookup.h" />
|
||||
<ClInclude Include="NXDNNetwork.h" />
|
||||
<ClInclude Include="NXDNUDCH.h" />
|
||||
<ClInclude Include="P25Audio.h" />
|
||||
<ClInclude Include="P25Control.h" />
|
||||
<ClInclude Include="P25Defines.h" />
|
||||
<ClInclude Include="P25Data.h" />
|
||||
<ClInclude Include="P25LowSpeedData.h" />
|
||||
<ClInclude Include="P25Network.h" />
|
||||
<ClInclude Include="P25NID.h" />
|
||||
<ClInclude Include="P25Trellis.h" />
|
||||
<ClInclude Include="P25Utils.h" />
|
||||
<ClInclude Include="POCSAGControl.h" />
|
||||
<ClInclude Include="POCSAGDefines.h" />
|
||||
<ClInclude Include="POCSAGNetwork.h" />
|
||||
<ClInclude Include="QR1676.h" />
|
||||
<ClInclude Include="RemoteControl.h" />
|
||||
<ClInclude Include="RingBuffer.h" />
|
||||
<ClInclude Include="RS129.h" />
|
||||
<ClInclude Include="RS241213.h" />
|
||||
<ClInclude Include="RSSIInterpolator.h" />
|
||||
<ClInclude Include="NXDNSACCH.h" />
|
||||
<ClInclude Include="SerialController.h" />
|
||||
<ClInclude Include="SerialPort.h" />
|
||||
<ClInclude Include="SHA256.h" />
|
||||
<ClInclude Include="StopWatch.h" />
|
||||
<ClInclude Include="Sync.h" />
|
||||
<ClInclude Include="TFTSerial.h" />
|
||||
<ClInclude Include="Thread.h" />
|
||||
<ClInclude Include="Timer.h" />
|
||||
<ClInclude Include="UDPSocket.h" />
|
||||
<ClInclude Include="UMP.h" />
|
||||
<ClInclude Include="Utils.h" />
|
||||
<ClInclude Include="Version.h" />
|
||||
<ClInclude Include="YSFControl.h" />
|
||||
<ClInclude Include="YSFConvolution.h" />
|
||||
<ClInclude Include="YSFDefines.h" />
|
||||
<ClInclude Include="YSFFICH.h" />
|
||||
<ClInclude Include="YSFNetwork.h" />
|
||||
<ClInclude Include="YSFPayload.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="AMBEFEC.cpp" />
|
||||
<ClCompile Include="BCH.cpp" />
|
||||
<ClCompile Include="BPTC19696.cpp" />
|
||||
<ClCompile Include="CASTInfo.cpp" />
|
||||
<ClCompile Include="Conf.cpp" />
|
||||
<ClCompile Include="CRC.cpp" />
|
||||
<ClCompile Include="Display.cpp" />
|
||||
<ClCompile Include="DMRAccessControl.cpp" />
|
||||
<ClCompile Include="DMRControl.cpp" />
|
||||
<ClCompile Include="DMRCSBK.cpp" />
|
||||
<ClCompile Include="DMRData.cpp" />
|
||||
<ClCompile Include="DMRDataHeader.cpp" />
|
||||
<ClCompile Include="DMREMB.cpp" />
|
||||
<ClCompile Include="DMREmbeddedData.cpp" />
|
||||
<ClCompile Include="DMRFullLC.cpp" />
|
||||
<ClCompile Include="DMRLC.cpp" />
|
||||
<ClCompile Include="DMRLookup.cpp" />
|
||||
<ClCompile Include="DMRNetwork.cpp" />
|
||||
<ClCompile Include="DMRShortLC.cpp" />
|
||||
<ClCompile Include="DMRSlot.cpp" />
|
||||
<ClCompile Include="DMRSlotType.cpp" />
|
||||
<ClCompile Include="DMRTA.cpp" />
|
||||
<ClCompile Include="DMRTrellis.cpp" />
|
||||
<ClCompile Include="DStarControl.cpp" />
|
||||
<ClCompile Include="DStarHeader.cpp" />
|
||||
<ClCompile Include="DStarNetwork.cpp" />
|
||||
<ClCompile Include="DStarSlowData.cpp" />
|
||||
<ClCompile Include="Golay2087.cpp" />
|
||||
<ClCompile Include="Golay24128.cpp" />
|
||||
<ClCompile Include="Hamming.cpp" />
|
||||
<ClCompile Include="I2CController.cpp" />
|
||||
<ClCompile Include="LCDproc.cpp" />
|
||||
<ClCompile Include="Log.cpp" />
|
||||
<ClCompile Include="MMDVMHost.cpp" />
|
||||
<ClCompile Include="MobileGPS.cpp" />
|
||||
<ClCompile Include="Modem.cpp" />
|
||||
<ClCompile Include="ModemSerialPort.cpp" />
|
||||
<ClCompile Include="Mutex.cpp" />
|
||||
<ClCompile Include="NetworkInfo.cpp" />
|
||||
<ClCompile Include="Nextion.cpp" />
|
||||
<ClCompile Include="NullDisplay.cpp" />
|
||||
<ClCompile Include="NullModem.cpp" />
|
||||
<ClCompile Include="NXDNAudio.cpp" />
|
||||
<ClCompile Include="NXDNControl.cpp" />
|
||||
<ClCompile Include="NXDNConvolution.cpp" />
|
||||
<ClCompile Include="NXDNCRC.cpp" />
|
||||
<ClCompile Include="NXDNFACCH1.cpp" />
|
||||
<ClCompile Include="NXDNLayer3.cpp" />
|
||||
<ClCompile Include="NXDNLICH.cpp" />
|
||||
<ClCompile Include="NXDNLookup.cpp" />
|
||||
<ClCompile Include="NXDNNetwork.cpp" />
|
||||
<ClCompile Include="NXDNSACCH.cpp" />
|
||||
<ClCompile Include="NXDNUDCH.cpp" />
|
||||
<ClCompile Include="P25Audio.cpp" />
|
||||
<ClCompile Include="P25Control.cpp" />
|
||||
<ClCompile Include="P25Data.cpp" />
|
||||
<ClCompile Include="P25LowSpeedData.cpp" />
|
||||
<ClCompile Include="P25Network.cpp" />
|
||||
<ClCompile Include="P25NID.cpp" />
|
||||
<ClCompile Include="P25Trellis.cpp" />
|
||||
<ClCompile Include="P25Utils.cpp" />
|
||||
<ClCompile Include="POCSAGControl.cpp" />
|
||||
<ClCompile Include="POCSAGNetwork.cpp" />
|
||||
<ClCompile Include="QR1676.cpp" />
|
||||
<ClCompile Include="RemoteControl.cpp" />
|
||||
<ClCompile Include="RS129.cpp" />
|
||||
<ClCompile Include="RS241213.cpp" />
|
||||
<ClCompile Include="RSSIInterpolator.cpp" />
|
||||
<ClCompile Include="SerialController.cpp" />
|
||||
<ClCompile Include="SerialPort.cpp" />
|
||||
<ClCompile Include="SHA256.cpp" />
|
||||
<ClCompile Include="StopWatch.cpp" />
|
||||
<ClCompile Include="Sync.cpp" />
|
||||
<ClCompile Include="TFTSerial.cpp" />
|
||||
<ClCompile Include="Thread.cpp" />
|
||||
<ClCompile Include="Timer.cpp" />
|
||||
<ClCompile Include="UDPSocket.cpp" />
|
||||
<ClCompile Include="UMP.cpp" />
|
||||
<ClCompile Include="Utils.cpp" />
|
||||
<ClCompile Include="YSFNetwork.cpp" />
|
||||
<ClCompile Include="YSFPayload.cpp" />
|
||||
<ClCompile Include="YSFControl.cpp" />
|
||||
<ClCompile Include="YSFConvolution.cpp" />
|
||||
<ClCompile Include="YSFFICH.cpp" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
548
MMDVMHost.vcxproj.filters
Normal file
548
MMDVMHost.vcxproj.filters
Normal file
|
@ -0,0 +1,548 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="Source Files">
|
||||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Header Files">
|
||||
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||
<Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="BPTC19696.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Conf.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="CRC.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Defines.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Display.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="DMRControl.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="DMRData.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="DMRDefines.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="DMRSlot.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="DStarDefines.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Golay2087.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Golay24128.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Hamming.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Log.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="MMDVMHost.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Modem.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="NullDisplay.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="QR1676.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="RemoteControl.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="RingBuffer.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="RS129.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="SerialController.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="SHA256.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="StopWatch.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="TFTSerial.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Timer.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="UDPSocket.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Utils.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="YSFDefines.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Version.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="AMBEFEC.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="DStarNetwork.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="DMRDataHeader.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="DStarHeader.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="DStarSlowData.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="DStarControl.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="YSFConvolution.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="YSFFICH.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="DMRCSBK.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Sync.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="DMREMB.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="DMREmbeddedData.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="DMRFullLC.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="DMRLC.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="DMRShortLC.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="DMRSlotType.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="YSFControl.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="YSFPayload.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Nextion.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="DMRLookup.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="YSFNetwork.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Thread.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="DMRTrellis.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="DMRAccessControl.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="P25Defines.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="P25Control.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="P25NID.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="P25Audio.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="P25Data.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="P25Utils.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="P25LowSpeedData.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="P25Network.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="DMRNetwork.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="BCH.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="RS241213.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="SerialPort.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="ModemSerialPort.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Mutex.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="LCDproc.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="UMP.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="RSSIInterpolator.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="NetworkInfo.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="P25Trellis.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="NXDNDefines.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="NXDNControl.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="NXDNNetwork.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="NXDNLICH.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="NXDNConvolution.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="NXDNCRC.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="NXDNLookup.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="NXDNSACCH.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="NXDNFACCH1.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="NXDNUDCH.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="NXDNLayer3.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="NXDNAudio.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="POCSAGNetwork.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="POCSAGControl.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<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>
|
||||
<ClInclude Include="NullModem.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="DMRTA.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="CASTInfo.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="BPTC19696.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Conf.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="CRC.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Display.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="DMRControl.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="DMRData.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="DMRSlot.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Golay2087.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Golay24128.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Hamming.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Log.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="MMDVMHost.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Modem.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="NullDisplay.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="QR1676.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="RemoteControl.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="RS129.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="SerialController.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="SHA256.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="StopWatch.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="TFTSerial.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Timer.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="UDPSocket.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Utils.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="AMBEFEC.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="DStarNetwork.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="DMRDataHeader.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="DStarHeader.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="DStarSlowData.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="DStarControl.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="YSFConvolution.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="YSFFICH.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="DMRCSBK.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Sync.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="DMREMB.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="DMREmbeddedData.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="DMRFullLC.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="DMRLC.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="DMRShortLC.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="DMRSlotType.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="YSFControl.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="YSFPayload.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Nextion.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="DMRLookup.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="YSFNetwork.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Thread.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="DMRTrellis.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="DMRAccessControl.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="P25Control.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="P25NID.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="P25Audio.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="P25Data.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="P25Utils.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="P25LowSpeedData.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="P25Network.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="DMRNetwork.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="BCH.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="RS241213.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="SerialPort.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="ModemSerialPort.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Mutex.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="LCDproc.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="UMP.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="RSSIInterpolator.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="NetworkInfo.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="P25Trellis.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="NXDNControl.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="NXDNNetwork.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="NXDNLICH.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="NXDNConvolution.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="NXDNCRC.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="NXDNLookup.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="NXDNSACCH.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="NXDNFACCH1.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="NXDNUDCH.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="NXDNLayer3.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="NXDNAudio.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="POCSAGNetwork.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<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>
|
||||
<ClCompile Include="NullModem.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="DMRTA.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="CASTInfo.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
</Project>
|
47
Makefile
47
Makefile
|
@ -2,18 +2,18 @@
|
|||
|
||||
CC = cc
|
||||
CXX = c++
|
||||
CFLAGS = -g -O3 -Wall -std=c++0x -pthread -DHAVE_LOG_H -I/usr/local/include
|
||||
LIBS = -lpthread -lutil
|
||||
LDFLAGS = -g -L/usr/local/lib
|
||||
CFLAGS = -g -O3 -Wall -std=c++0x -pthread
|
||||
LIBS = -lpthread
|
||||
LDFLAGS = -g
|
||||
|
||||
OBJECTS = \
|
||||
AMBEFEC.o BCH.o BPTC19696.o CASTInfo.o Conf.o CRC.o Display.o DMRControl.o DMRCSBK.o DMRData.o DMRDataHeader.o \
|
||||
DMRDirectNetwork.o DMREMB.o DMREmbeddedData.o DMRFullLC.o DMRGatewayNetwork.o DMRLookup.o DMRLC.o DMRNetwork.o DMRShortLC.o DMRSlot.o DMRSlotType.o \
|
||||
DMRAccessControl.o DMRTA.o DMRTrellis.o Golay2087.o Golay24128.o\
|
||||
Hamming.o I2CController.o IIRDirectForm1Filter.o LCDproc.o Log.o MMDVMHost.o \
|
||||
Modem.o ModemPort.o ModemSerialPort.o Mutex.o NetworkInfo.o Nextion.o NullController.o NullDisplay.o \
|
||||
RemoteControl.o QR1676.o RS129.o RS241213.o RSSIInterpolator.o SerialPort.o SMeter.o StopWatch.o Sync.o SHA256.o TFTSurenoo.o Thread.o \
|
||||
Timer.o UARTController.o UDPController.o UDPSocket.o UserDB.o UserDBentry.o Utils.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 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 \
|
||||
Thread.o Timer.o UDPSocket.o UMP.o Utils.o YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o
|
||||
|
||||
all: MMDVMHost RemoteCommand
|
||||
|
||||
|
@ -26,33 +26,6 @@ RemoteCommand: Log.o RemoteCommand.o UDPSocket.o
|
|||
%.o: %.cpp
|
||||
$(CXX) $(CFLAGS) -c -o $@ $<
|
||||
|
||||
.PHONY install:
|
||||
install: all
|
||||
install -m 755 MMDVMHost /usr/local/bin/
|
||||
install -m 755 RemoteCommand /usr/local/bin/
|
||||
|
||||
.PHONY install-service:
|
||||
install-service: install /etc/MMDVM.ini
|
||||
@useradd --user-group -M --system mmdvm --shell /bin/false || true
|
||||
@usermod --groups dialout --append mmdvm || true
|
||||
@mkdir /var/log/mmdvm || true
|
||||
@chown mmdvm:mmdvm /var/log/mmdvm
|
||||
@cp ./linux/systemd/mmdvmhost.service /lib/systemd/system/
|
||||
@systemctl enable mmdvmhost.service
|
||||
|
||||
/etc/MMDVM.ini:
|
||||
@cp -n MMDVM.ini /etc/MMDVM.ini
|
||||
@sed -i 's/FilePath=./FilePath=\/var\/log\/mmdvm\//' /etc/MMDVM.ini
|
||||
@sed -i 's/Daemon=0/Daemon=1/' /etc/MMDVM.ini
|
||||
@chown mmdvm:mmdvm /etc/MMDVM.ini
|
||||
|
||||
.PHONY uninstall-service:
|
||||
uninstall-service:
|
||||
@systemctl stop mmdvmhost.service || true
|
||||
@systemctl disable mmdvmhost.service || true
|
||||
@rm -f /usr/local/bin/MMDVMHost || true
|
||||
@rm -f /lib/systemd/system/mmdvmhost.service || true
|
||||
|
||||
clean:
|
||||
$(RM) MMDVMHost RemoteCommand *.o *.d *.bak *~ GitVersion.h
|
||||
|
||||
|
|
49
Makefile.Pi
49
Makefile.Pi
|
@ -1,19 +1,19 @@
|
|||
# This makefile is for use with the Raspberry Pi. The wiringpi library is needed.
|
||||
|
||||
CC = cc
|
||||
CXX = c++
|
||||
CFLAGS = -g -O3 -Wall -std=c++0x -pthread -DHAVE_LOG_H -DRASPBERRY_PI -I/usr/local/include
|
||||
LIBS = -lwiringPi -lwiringPiDev -lpthread -lutil
|
||||
CC = gcc
|
||||
CXX = g++
|
||||
CFLAGS = -g -O3 -Wall -std=c++0x -pthread -DRASPBERRY_PI -I/usr/local/include
|
||||
LIBS = -lwiringPi -lwiringPiDev -lpthread
|
||||
LDFLAGS = -g -L/usr/local/lib
|
||||
|
||||
OBJECTS = \
|
||||
AMBEFEC.o BCH.o BPTC19696.o CASTInfo.o Conf.o CRC.o Display.o DMRControl.o DMRCSBK.o DMRData.o DMRDataHeader.o \
|
||||
DMRDirectNetwork.o DMREMB.o DMREmbeddedData.o DMRFullLC.o DMRGatewayNetwork.o DMRLookup.o DMRLC.o DMRNetwork.o DMRShortLC.o DMRSlot.o DMRSlotType.o \
|
||||
DMRAccessControl.o DMRTA.o DMRTrellis.o Golay2087.o Golay24128.o\
|
||||
Hamming.o I2CController.o IIRDirectForm1Filter.o LCDproc.o Log.o MMDVMHost.o \
|
||||
Modem.o ModemPort.o ModemSerialPort.o Mutex.o NetworkInfo.o Nextion.o NullController.o NullDisplay.o \
|
||||
RemoteControl.o QR1676.o RS129.o RS241213.o RSSIInterpolator.o SerialPort.o SMeter.o StopWatch.o Sync.o SHA256.o TFTSurenoo.o Thread.o \
|
||||
Timer.o UARTController.o UDPController.o UDPSocket.o UserDB.o UserDBentry.o Utils.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 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 Thread.o Timer.o \
|
||||
UDPSocket.o UMP.o Utils.o YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o
|
||||
|
||||
all: MMDVMHost RemoteCommand
|
||||
|
||||
|
@ -26,33 +26,6 @@ RemoteCommand: Log.o RemoteCommand.o UDPSocket.o
|
|||
%.o: %.cpp
|
||||
$(CXX) $(CFLAGS) -c -o $@ $<
|
||||
|
||||
.PHONY install:
|
||||
install: all
|
||||
install -m 755 MMDVMHost /usr/local/bin/
|
||||
install -m 755 RemoteCommand /usr/local/bin/
|
||||
|
||||
.PHONY install-service:
|
||||
install-service: install /etc/MMDVM.ini
|
||||
@useradd --user-group -M --system mmdvm --shell /bin/false || true
|
||||
@usermod --groups dialout --append mmdvm || true
|
||||
@mkdir /var/log/mmdvm || true
|
||||
@chown mmdvm:mmdvm /var/log/mmdvm
|
||||
@cp ./linux/systemd/mmdvmhost.service /lib/systemd/system/
|
||||
@systemctl enable mmdvmhost.service
|
||||
|
||||
/etc/MMDVM.ini:
|
||||
@cp -n MMDVM.ini /etc/MMDVM.ini
|
||||
@sed -i 's/FilePath=./FilePath=\/var\/log\/mmdvm\//' /etc/MMDVM.ini
|
||||
@sed -i 's/Daemon=0/Daemon=1/' /etc/MMDVM.ini
|
||||
@chown mmdvm:mmdvm /etc/MMDVM.ini
|
||||
|
||||
.PHONY uninstall-service:
|
||||
uninstall-service:
|
||||
@systemctl stop mmdvmhost.service || true
|
||||
@systemctl disable mmdvmhost.service || true
|
||||
@rm -f /usr/local/bin/MMDVMHost || true
|
||||
@rm -f /lib/systemd/system/mmdvmhost.service || true
|
||||
|
||||
clean:
|
||||
$(RM) MMDVMHost RemoteCommand *.o *.d *.bak *~ GitVersion.h
|
||||
|
||||
|
|
39
Makefile.Pi.Adafruit
Normal file
39
Makefile.Pi.Adafruit
Normal file
|
@ -0,0 +1,39 @@
|
|||
# This makefile is for use with the Raspberry Pi when using an HD44780 compatible display. The wiringpi library is needed.
|
||||
# Support for the Adafruit i2c 16 x 2 RGB LCD Pi Plate
|
||||
|
||||
CC = gcc
|
||||
CXX = g++
|
||||
CFLAGS = -g -O3 -Wall -std=c++0x -pthread -DHD44780 -DADAFRUIT_DISPLAY -I/usr/local/include
|
||||
LIBS = -lwiringPi -lwiringPiDev -lpthread
|
||||
LDFLAGS = -g -L/usr/local/lib
|
||||
|
||||
OBJECTS = \
|
||||
AMBEFEC.o BCH.o BPTC19696.o CASTInfo.o Conf.o CRC.o Display.o DMRControl.o DMRCSBK.o DMRData.o DMRDataHeader.o DMREMB.o DMREmbeddedData.o DMRFullLC.o \
|
||||
DMRLookup.o DMRLC.o DMRNetwork.o DMRShortLC.o DMRSlot.o DMRSlotType.o DMRAccessControl.o DMRTA.o DMRTrellis.o DStarControl.o DStarHeader.o DStarNetwork.o \
|
||||
DStarSlowData.o Golay2087.o Golay24128.o Hamming.o 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 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 Thread.o \
|
||||
Timer.o UDPSocket.o UMP.o Utils.o YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o
|
||||
|
||||
all: MMDVMHost RemoteCommand
|
||||
|
||||
MMDVMHost: GitVersion.h $(OBJECTS)
|
||||
$(CXX) $(OBJECTS) $(CFLAGS) $(LIBS) -o MMDVMHost
|
||||
|
||||
RemoteCommand: Log.o RemoteCommand.o UDPSocket.o
|
||||
$(CXX) Log.o RemoteCommand.o UDPSocket.o $(CFLAGS) $(LIBS) -o RemoteCommand
|
||||
|
||||
%.o: %.cpp
|
||||
$(CXX) $(CFLAGS) -c -o $@ $<
|
||||
|
||||
clean:
|
||||
$(RM) MMDVMHost RemoteCommand *.o *.d *.bak *~ GitVersion.h
|
||||
|
||||
# Export the current git version if the index file exists, else 000...
|
||||
GitVersion.h:
|
||||
ifneq ("$(wildcard .git/index)","")
|
||||
echo "const char *gitversion = \"$(shell git rev-parse HEAD)\";" > $@
|
||||
else
|
||||
echo "const char *gitversion = \"0000000000000000000000000000000000000000\";" > $@
|
||||
endif
|
38
Makefile.Pi.HD44780
Normal file
38
Makefile.Pi.HD44780
Normal file
|
@ -0,0 +1,38 @@
|
|||
# This makefile is for use with the Raspberry Pi when using an HD44780 compatible display. The wiringpi library is needed.
|
||||
|
||||
CC = gcc
|
||||
CXX = g++
|
||||
CFLAGS = -g -O3 -Wall -std=c++0x -pthread -DHD44780 -I/usr/local/include
|
||||
LIBS = -lwiringPi -lwiringPiDev -lpthread
|
||||
LDFLAGS = -g -L/usr/local/lib
|
||||
|
||||
OBJECTS = \
|
||||
AMBEFEC.o BCH.o BPTC19696.o CASTInfo.o Conf.o CRC.o Display.o DMRControl.o DMRCSBK.o DMRData.o DMRDataHeader.o DMREMB.o DMREmbeddedData.o DMRFullLC.o \
|
||||
DMRLookup.o DMRLC.o DMRNetwork.o DMRShortLC.o DMRSlot.o DMRSlotType.o DMRAccessControl.o DMRTA.o DMRTrellis.o DStarControl.o DStarHeader.o DStarNetwork.o \
|
||||
DStarSlowData.o Golay2087.o Golay24128.o Hamming.o 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 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 Thread.o \
|
||||
Timer.o UDPSocket.o UMP.o Utils.o YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o
|
||||
|
||||
all: MMDVMHost RemoteCommand
|
||||
|
||||
MMDVMHost: GitVersion.h $(OBJECTS)
|
||||
$(CXX) $(OBJECTS) $(CFLAGS) $(LIBS) -o MMDVMHost
|
||||
|
||||
RemoteCommand: Log.o RemoteCommand.o UDPSocket.o
|
||||
$(CXX) Log.o RemoteCommand.o UDPSocket.o $(CFLAGS) $(LIBS) -o RemoteCommand
|
||||
|
||||
%.o: %.cpp
|
||||
$(CXX) $(CFLAGS) -c -o $@ $<
|
||||
|
||||
clean:
|
||||
$(RM) MMDVMHost RemoteCommand *.o *.d *.bak *~ GitVersion.h
|
||||
|
||||
# Export the current git version if the index file exists, else 000...
|
||||
GitVersion.h:
|
||||
ifneq ("$(wildcard .git/index)","")
|
||||
echo "const char *gitversion = \"$(shell git rev-parse HEAD)\";" > $@
|
||||
else
|
||||
echo "const char *gitversion = \"0000000000000000000000000000000000000000\";" > $@
|
||||
endif
|
38
Makefile.Pi.OLED
Normal file
38
Makefile.Pi.OLED
Normal file
|
@ -0,0 +1,38 @@
|
|||
# This makefile is for use with the Raspberry Pi when using an OLED display. The wiringpi library is needed.
|
||||
|
||||
CC = gcc
|
||||
CXX = g++
|
||||
CFLAGS = -g -O3 -Wall -std=c++0x -pthread -DOLED -I/usr/local/include
|
||||
LIBS = -lArduiPi_OLED -lwiringPi -lpthread
|
||||
LDFLAGS = -g -L/usr/local/lib
|
||||
|
||||
OBJECTS = \
|
||||
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 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 Thread.o \
|
||||
Timer.o UDPSocket.o UMP.o Utils.o YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o
|
||||
|
||||
all: MMDVMHost RemoteCommand
|
||||
|
||||
MMDVMHost: GitVersion.h $(OBJECTS)
|
||||
$(CXX) $(OBJECTS) $(CFLAGS) $(LIBS) -o MMDVMHost
|
||||
|
||||
RemoteCommand: Log.o RemoteCommand.o UDPSocket.o
|
||||
$(CXX) Log.o RemoteCommand.o UDPSocket.o $(CFLAGS) $(LIBS) -o RemoteCommand
|
||||
|
||||
%.o: %.cpp
|
||||
$(CXX) $(CFLAGS) -c -o $@ $<
|
||||
|
||||
clean:
|
||||
$(RM) MMDVMHost RemoteCommand *.o *.d *.bak *~ GitVersion.h
|
||||
|
||||
# Export the current git version if the index file exists, else 000...
|
||||
GitVersion.h:
|
||||
ifneq ("$(wildcard .git/index)","")
|
||||
echo "const char *gitversion = \"$(shell git rev-parse HEAD)\";" > $@
|
||||
else
|
||||
echo "const char *gitversion = \"0000000000000000000000000000000000000000\";" > $@
|
||||
endif
|
39
Makefile.Pi.PCF8574
Normal file
39
Makefile.Pi.PCF8574
Normal file
|
@ -0,0 +1,39 @@
|
|||
# This makefile is for use with the Raspberry Pi when using an HD44780 compatible display. The wiringpi library is needed.
|
||||
# Support for the HD44780 connected via a PCF8574 8-bit GPIO expander IC
|
||||
|
||||
CC = gcc
|
||||
CXX = g++
|
||||
CFLAGS = -g -O3 -Wall -std=c++0x -pthread -DHD44780 -DPCF8574_DISPLAY -I/usr/local/include
|
||||
LIBS = -lwiringPi -lwiringPiDev -lpthread
|
||||
LDFLAGS = -g -L/usr/local/lib
|
||||
|
||||
OBJECTS = \
|
||||
AMBEFEC.o BCH.o BPTC19696.o CASTInfo.o Conf.o CRC.o Display.o DMRControl.o DMRCSBK.o DMRData.o DMRDataHeader.o DMREMB.o DMREmbeddedData.o DMRFullLC.o \
|
||||
DMRLookup.o DMRLC.o DMRNetwork.o DMRShortLC.o DMRSlot.o DMRSlotType.o DMRAccessControl.o DMRTA.o DMRTrellis.o DStarControl.o DStarHeader.o DStarNetwork.o \
|
||||
DStarSlowData.o Golay2087.o Golay24128.o Hamming.o 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 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 Thread.o \
|
||||
Timer.o UDPSocket.o UMP.o Utils.o YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o
|
||||
|
||||
all: MMDVMHost RemoteCommand
|
||||
|
||||
MMDVMHost: GitVersion.h $(OBJECTS)
|
||||
$(CXX) $(OBJECTS) $(CFLAGS) $(LIBS) -o MMDVMHost
|
||||
|
||||
RemoteCommand: Log.o RemoteCommand.o UDPSocket.o
|
||||
$(CXX) Log.o RemoteCommand.o UDPSocket.o $(CFLAGS) $(LIBS) -o RemoteCommand
|
||||
|
||||
%.o: %.cpp
|
||||
$(CXX) $(CFLAGS) -c -o $@ $<
|
||||
|
||||
clean:
|
||||
$(RM) MMDVMHost RemoteCommand *.o *.d *.bak *~ GitVersion.h
|
||||
|
||||
# Export the current git version if the index file exists, else 000...
|
||||
GitVersion.h:
|
||||
ifneq ("$(wildcard .git/index)","")
|
||||
echo "const char *gitversion = \"$(shell git rev-parse HEAD)\";" > $@
|
||||
else
|
||||
echo "const char *gitversion = \"0000000000000000000000000000000000000000\";" > $@
|
||||
endif
|
38
Makefile.Solaris
Normal file
38
Makefile.Solaris
Normal file
|
@ -0,0 +1,38 @@
|
|||
# This makefile is for Solaris using gcc
|
||||
|
||||
CC = gcc
|
||||
CXX = g++
|
||||
CFLAGS = -g -O3 -Wall -std=c++0x -pthread
|
||||
LIBS = -lpthread -lsocket
|
||||
LDFLAGS = -g
|
||||
|
||||
OBJECTS = \
|
||||
AMBEFEC.o BCH.o BPTC19696.o CASTInfo.o Conf.o CRC.o Display.o DMRControl.o DMRCSBK.o DMRData.o DMRDataHeader.o DMREMB.o DMREmbeddedData.o DMRFullLC.o \
|
||||
DMRLookup.o DMRLC.o DMRNetwork.o DMRShortLC.o DMRSlot.o DMRSlotType.o DMRAccessControl.o DMRTA.o DMRTrellis.o DStarControl.o DStarHeader.o DStarNetwork.o \
|
||||
DStarSlowData.o Golay2087.o Golay24128.o Hamming.o 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 Thread.o Timer.o UDPSocket.o \
|
||||
UMP.o Utils.o YSFControl.o YSFConvolution.o YSFFICH.o YSFNetwork.o YSFPayload.o
|
||||
|
||||
all: MMDVMHost RemoteCommand
|
||||
|
||||
MMDVMHost: GitVersion.h $(OBJECTS)
|
||||
$(CXX) $(OBJECTS) $(CFLAGS) $(LIBS) -o MMDVMHost
|
||||
|
||||
RemoteCommand: Log.o RemoteCommand.o UDPSocket.o
|
||||
$(CXX) Log.o RemoteCommand.o UDPSocket.o $(CFLAGS) $(LIBS) -o RemoteCommand
|
||||
|
||||
%.o: %.cpp
|
||||
$(CXX) $(CFLAGS) -c -o $@ $<
|
||||
|
||||
clean:
|
||||
$(RM) MMDVMHost RemoteCommand *.o *.d *.bak *~ GitVersion.h
|
||||
|
||||
# Export the current git version if the index file exists, else 000...
|
||||
GitVersion.h:
|
||||
ifneq ("$(wildcard .git/index)","")
|
||||
echo "const char *gitversion = \"$(shell git rev-parse HEAD)\";" > $@
|
||||
else
|
||||
echo "const char *gitversion = \"0000000000000000000000000000000000000000\";" > $@
|
||||
endif
|
101
MobileGPS.cpp
Normal file
101
MobileGPS.cpp
Normal file
|
@ -0,0 +1,101 @@
|
|||
/*
|
||||
* Copyright (C) 2018 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* 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 "MobileGPS.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
#include <cmath>
|
||||
|
||||
CMobileGPS::CMobileGPS(const std::string& address, unsigned int port, CDMRNetwork* network) :
|
||||
m_idTimer(1000U, 60U),
|
||||
m_address(),
|
||||
m_port(port),
|
||||
m_socket(),
|
||||
m_network(network)
|
||||
{
|
||||
assert(!address.empty());
|
||||
assert(port > 0U);
|
||||
assert(network != NULL);
|
||||
|
||||
m_address = CUDPSocket::lookup(address);
|
||||
}
|
||||
|
||||
CMobileGPS::~CMobileGPS()
|
||||
{
|
||||
}
|
||||
|
||||
bool CMobileGPS::open()
|
||||
{
|
||||
bool ret = m_socket.open();
|
||||
if (!ret)
|
||||
return false;
|
||||
|
||||
m_idTimer.start();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CMobileGPS::clock(unsigned int ms)
|
||||
{
|
||||
m_idTimer.clock(ms);
|
||||
|
||||
if (m_idTimer.hasExpired()) {
|
||||
pollGPS();
|
||||
m_idTimer.start();
|
||||
}
|
||||
|
||||
sendReport();
|
||||
}
|
||||
|
||||
void CMobileGPS::close()
|
||||
{
|
||||
m_socket.close();
|
||||
}
|
||||
|
||||
bool CMobileGPS::pollGPS()
|
||||
{
|
||||
return m_socket.write((unsigned char*)"MMDVMHost", 9U, m_address, m_port);
|
||||
}
|
||||
|
||||
void CMobileGPS::sendReport()
|
||||
{
|
||||
// Grab GPS data if it's available
|
||||
unsigned char buffer[200U];
|
||||
in_addr address;
|
||||
unsigned int port;
|
||||
int ret = m_socket.read(buffer, 200U, address, port);
|
||||
if (ret <= 0)
|
||||
return;
|
||||
|
||||
buffer[ret] = '\0';
|
||||
|
||||
// Parse the GPS data
|
||||
char* pLatitude = ::strtok((char*)buffer, ",\n"); // Latitude
|
||||
char* pLongitude = ::strtok(NULL, ",\n"); // Longitude
|
||||
|
||||
if (pLatitude == NULL || pLongitude == NULL)
|
||||
return;
|
||||
|
||||
float latitude = float(::atof(pLatitude));
|
||||
float longitude = float(::atof(pLongitude));
|
||||
|
||||
m_network->writeHomePosition(latitude, longitude);
|
||||
}
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2020 by SASANO Takayoshi JG1UAA
|
||||
* Copyright (C) 2018 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
@ -16,35 +16,48 @@
|
|||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#if !defined(USERDBENTRY_H)
|
||||
#define USERDBENTRY_H
|
||||
#ifndef MobileGPS_H
|
||||
#define MobileGPS_H
|
||||
|
||||
#include "DMRNetwork.h"
|
||||
#include "UDPSocket.h"
|
||||
#include "Timer.h"
|
||||
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
#define keyRADIO_ID "RADIO_ID"
|
||||
#define keyCALLSIGN "CALLSIGN"
|
||||
#define keyFIRST_NAME "FIRST_NAME"
|
||||
#define keyLAST_NAME "LAST_NAME"
|
||||
#define keyCITY "CITY"
|
||||
#define keySTATE "STATE"
|
||||
#define keyCOUNTRY "COUNTRY"
|
||||
#if !defined(_WIN32) && !defined(_WIN64)
|
||||
#include <netdb.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <unistd.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <errno.h>
|
||||
#else
|
||||
#include <winsock.h>
|
||||
#endif
|
||||
|
||||
class CUserDBentry {
|
||||
class CMobileGPS {
|
||||
public:
|
||||
CUserDBentry();
|
||||
~CUserDBentry();
|
||||
CMobileGPS(const std::string& address, unsigned int port, CDMRNetwork* network);
|
||||
~CMobileGPS();
|
||||
|
||||
static const std::vector<std::string> keyList;
|
||||
static bool isValidKey(const std::string key);
|
||||
bool open();
|
||||
|
||||
void set(const std::string key, const std::string value);
|
||||
const std::string get(const std::string key) const;
|
||||
void clear(void);
|
||||
void clock(unsigned int ms);
|
||||
|
||||
void close();
|
||||
|
||||
private:
|
||||
std::unordered_map<std::string, std::string> m_db;
|
||||
CTimer m_idTimer;
|
||||
in_addr m_address;
|
||||
unsigned int m_port;
|
||||
CUDPSocket m_socket;
|
||||
CDMRNetwork* m_network;
|
||||
|
||||
bool pollGPS();
|
||||
void sendReport();
|
||||
};
|
||||
|
||||
#endif
|
184
Modem.h
184
Modem.h
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2011-2018,2020,2021 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2011-2018 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
@ -16,10 +16,10 @@
|
|||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#ifndef Modem_H
|
||||
#define Modem_H
|
||||
#ifndef MODEM_H
|
||||
#define MODEM_H
|
||||
|
||||
#include "ModemPort.h"
|
||||
#include "SerialController.h"
|
||||
#include "RingBuffer.h"
|
||||
#include "Defines.h"
|
||||
#include "Timer.h"
|
||||
|
@ -32,107 +32,86 @@ enum RESP_TYPE_MMDVM {
|
|||
RTM_ERROR
|
||||
};
|
||||
|
||||
enum SERIAL_STATE {
|
||||
SS_START,
|
||||
SS_LENGTH1,
|
||||
SS_LENGTH2,
|
||||
SS_TYPE,
|
||||
SS_DATA
|
||||
};
|
||||
|
||||
class CModem {
|
||||
public:
|
||||
CModem(bool duplex, bool rxInvert, bool txInvert, bool pttInvert, unsigned int txDelay, unsigned int dmrDelay, bool useCOSAsLockout, bool trace, bool debug);
|
||||
~CModem();
|
||||
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();
|
||||
|
||||
void setPort(IModemPort* port);
|
||||
void setRFParams(unsigned int rxFrequency, int rxOffset, unsigned int txFrequency, int txOffset, int txDCOffset, int rxDCOffset, float rfLevel);
|
||||
void setModeParams(bool dstarEnabled, bool dmrEnabled, bool ysfEnabled, bool p25Enabled, bool nxdnEnabled, bool m17Enabled, bool pocsagEnabled, bool fmEnabled, bool ax25Enabled);
|
||||
void setLevels(float rxLevel, float cwIdTXLevel, float dmrTXLevel);
|
||||
void setDMRParams(unsigned int colorCode);
|
||||
void setYSFParams(bool loDev, unsigned int txHang);
|
||||
void setP25Params(unsigned int txHang);
|
||||
void setNXDNParams(unsigned int txHang);
|
||||
void setM17Params(unsigned int txHang);
|
||||
void setAX25Params(int rxTwist, unsigned int txDelay, unsigned int slotTime, unsigned int pPersist);
|
||||
void setTransparentDataParams(unsigned int sendFrameType);
|
||||
virtual void setSerialParams(const std::string& protocol, unsigned int address);
|
||||
virtual void setRFParams(unsigned int rxFrequency, int rxOffset, unsigned int txFrequency, int txOffset, int txDCOffset, int rxDCOffset, float rfLevel, unsigned int pocsagFrequency);
|
||||
virtual void setModeParams(bool dstarEnabled, bool dmrEnabled, bool ysfEnabled, bool p25Enabled, bool nxdnEnabled, bool pocsagEnabled);
|
||||
virtual void setLevels(float rxLevel, float cwIdTXLevel, float dstarTXLevel, float dmrTXLevel, float ysfTXLevel, float p25TXLevel, float nxdnTXLevel, float pocsagLevel);
|
||||
virtual void setDMRParams(unsigned int colorCode);
|
||||
virtual void setYSFParams(bool loDev, unsigned int txHang);
|
||||
virtual void setTransparentDataParams(unsigned int sendFrameType);
|
||||
|
||||
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);
|
||||
void setFMAckParams(const std::string& rfAck, unsigned int ackSpeed, unsigned int ackFrequency, unsigned int ackMinTime, unsigned int ackDelay, float ackLevel);
|
||||
void setFMMiscParams(unsigned int timeout, float timeoutLevel, float ctcssFrequency, unsigned int ctcssHighThreshold, unsigned int ctcssLowThreshold, float ctcssLevel, unsigned int kerchunkTime, unsigned int hangTime, unsigned int accessMode, bool linkMode, bool cosInvert, bool noiseSquelch, unsigned int squelchHighThreshold, unsigned int squelchLowThreshold, unsigned int rfAudioBoost, float maxDevLevel);
|
||||
void setFMExtParams(const std::string& ack, unsigned int audioBoost);
|
||||
virtual bool open();
|
||||
|
||||
bool open();
|
||||
virtual unsigned int readDStarData(unsigned char* data);
|
||||
virtual unsigned int readDMRData1(unsigned char* data);
|
||||
virtual unsigned int readDMRData2(unsigned char* data);
|
||||
virtual unsigned int readYSFData(unsigned char* data);
|
||||
virtual unsigned int readP25Data(unsigned char* data);
|
||||
virtual unsigned int readNXDNData(unsigned char* data);
|
||||
virtual unsigned int readTransparentData(unsigned char* data);
|
||||
|
||||
bool hasDStar() const;
|
||||
bool hasDMR() const;
|
||||
bool hasYSF() const;
|
||||
bool hasP25() const;
|
||||
bool hasNXDN() const;
|
||||
bool hasM17() const;
|
||||
bool hasPOCSAG() const;
|
||||
bool hasFM() const;
|
||||
bool hasAX25() const;
|
||||
virtual unsigned int readSerial(unsigned char* data, unsigned int length);
|
||||
|
||||
unsigned int getVersion() const;
|
||||
virtual bool hasDStarSpace() const;
|
||||
virtual bool hasDMRSpace1() const;
|
||||
virtual bool hasDMRSpace2() const;
|
||||
virtual bool hasYSFSpace() const;
|
||||
virtual bool hasP25Space() const;
|
||||
virtual bool hasNXDNSpace() const;
|
||||
virtual bool hasPOCSAGSpace() const;
|
||||
|
||||
unsigned int readDStarData(unsigned char* data);
|
||||
unsigned int readDMRData1(unsigned char* data);
|
||||
unsigned int readDMRData2(unsigned char* data);
|
||||
unsigned int readYSFData(unsigned char* data);
|
||||
unsigned int readP25Data(unsigned char* data);
|
||||
unsigned int readNXDNData(unsigned char* data);
|
||||
unsigned int readM17Data(unsigned char* data);
|
||||
unsigned int readFMData(unsigned char* data);
|
||||
unsigned int readAX25Data(unsigned char* data);
|
||||
virtual bool hasTX() const;
|
||||
virtual bool hasCD() const;
|
||||
|
||||
bool hasDStarSpace() const;
|
||||
bool hasDMRSpace1() const;
|
||||
bool hasDMRSpace2() const;
|
||||
bool hasYSFSpace() const;
|
||||
bool hasP25Space() const;
|
||||
bool hasNXDNSpace() const;
|
||||
bool hasM17Space() const;
|
||||
bool hasPOCSAGSpace() const;
|
||||
unsigned int getFMSpace() const;
|
||||
bool hasAX25Space() const;
|
||||
virtual bool hasLockout() const;
|
||||
virtual bool hasError() const;
|
||||
|
||||
bool hasTX() const;
|
||||
bool hasCD() const;
|
||||
virtual bool writeDStarData(const unsigned char* data, unsigned int length);
|
||||
virtual bool writeDMRData1(const unsigned char* data, unsigned int length);
|
||||
virtual bool writeDMRData2(const unsigned char* data, unsigned int length);
|
||||
virtual bool writeYSFData(const unsigned char* data, unsigned int length);
|
||||
virtual bool writeP25Data(const unsigned char* data, unsigned int length);
|
||||
virtual bool writeNXDNData(const unsigned char* data, unsigned int length);
|
||||
virtual bool writePOCSAGData(const unsigned char* data, unsigned int length);
|
||||
|
||||
bool hasLockout() const;
|
||||
bool hasError() const;
|
||||
virtual bool writeTransparentData(const unsigned char* data, unsigned int length);
|
||||
|
||||
bool writeConfig();
|
||||
bool writeDMRData1(const unsigned char* data, unsigned int length);
|
||||
bool writeDMRData2(const unsigned char* data, unsigned int length);
|
||||
bool writeDMRInfo(unsigned int slotNo, const std::string& src, bool group, const std::string& dst, const char* type);
|
||||
bool writeIPInfo(const std::string& address);
|
||||
virtual bool writeDStarInfo(const char* my1, const char* my2, const char* your, const char* type, const char* reflector);
|
||||
virtual bool writeDMRInfo(unsigned int slotNo, const std::string& src, bool group, const std::string& dst, const char* type);
|
||||
virtual bool writeYSFInfo(const char* source, const char* dest, const char* type, const char* origin);
|
||||
virtual bool writeP25Info(const char* source, bool group, unsigned int dest, const char* type);
|
||||
virtual bool writeNXDNInfo(const char* source, bool group, unsigned int dest, const char* type);
|
||||
virtual bool writePOCSAGInfo(unsigned int ric, const std::string& message);
|
||||
virtual bool writeIPInfo(const std::string& address);
|
||||
|
||||
bool writeDMRStart(bool tx);
|
||||
bool writeDMRShortLC(const unsigned char* lc);
|
||||
bool writeDMRAbort(unsigned int slotNo);
|
||||
virtual bool writeDMRStart(bool tx);
|
||||
virtual bool writeDMRShortLC(const unsigned char* lc);
|
||||
virtual bool writeDMRAbort(unsigned int slotNo);
|
||||
|
||||
bool writeTransparentData(const unsigned char* data, unsigned int length);
|
||||
unsigned int readTransparentData(unsigned char* data);
|
||||
virtual bool writeSerial(const unsigned char* data, unsigned int length);
|
||||
|
||||
bool writeSerial(const unsigned char* data, unsigned int length);
|
||||
unsigned int readSerial(unsigned char* data, unsigned int length);
|
||||
virtual bool setMode(unsigned char mode);
|
||||
|
||||
unsigned char getMode() const;
|
||||
bool setMode(unsigned char mode);
|
||||
virtual bool sendCWId(const std::string& callsign);
|
||||
|
||||
bool sendCWId(const std::string& callsign);
|
||||
virtual HW_TYPE getHWType() const;
|
||||
|
||||
HW_TYPE getHWType() const;
|
||||
virtual void clock(unsigned int ms);
|
||||
|
||||
void clock(unsigned int ms);
|
||||
virtual void close();
|
||||
|
||||
void close();
|
||||
static CModem* createModem(const std::string& port, bool duplex, bool rxInvert, bool txInvert, bool pttInvert, unsigned int txDelay, unsigned int dmrDelay, bool trace, bool debug);
|
||||
|
||||
private:
|
||||
unsigned int m_protocolVersion;
|
||||
std::string m_port;
|
||||
unsigned int m_dmrColorCode;
|
||||
bool m_ysfLoDev;
|
||||
unsigned int m_ysfTXHang;
|
||||
bool m_duplex;
|
||||
bool m_rxInvert;
|
||||
bool m_txInvert;
|
||||
|
@ -141,55 +120,66 @@ private:
|
|||
unsigned int m_dmrDelay;
|
||||
float m_rxLevel;
|
||||
float m_cwIdTXLevel;
|
||||
float m_dstarTXLevel;
|
||||
float m_dmrTXLevel;
|
||||
float m_ysfTXLevel;
|
||||
float m_p25TXLevel;
|
||||
float m_nxdnTXLevel;
|
||||
float m_pocsagTXLevel;
|
||||
float m_rfLevel;
|
||||
bool m_useCOSAsLockout;
|
||||
bool m_trace;
|
||||
bool m_debug;
|
||||
unsigned int m_rxFrequency;
|
||||
unsigned int m_txFrequency;
|
||||
unsigned int m_pocsagFrequency;
|
||||
bool m_dstarEnabled;
|
||||
bool m_dmrEnabled;
|
||||
bool m_ysfEnabled;
|
||||
bool m_p25Enabled;
|
||||
bool m_nxdnEnabled;
|
||||
bool m_pocsagEnabled;
|
||||
int m_rxDCOffset;
|
||||
int m_txDCOffset;
|
||||
IModemPort* m_port;
|
||||
CSerialController* m_serial;
|
||||
unsigned char* m_buffer;
|
||||
unsigned int m_length;
|
||||
unsigned int m_offset;
|
||||
SERIAL_STATE m_state;
|
||||
unsigned char m_type;
|
||||
CRingBuffer<unsigned char> m_rxDStarData;
|
||||
CRingBuffer<unsigned char> m_txDStarData;
|
||||
CRingBuffer<unsigned char> m_rxDMRData1;
|
||||
CRingBuffer<unsigned char> m_rxDMRData2;
|
||||
CRingBuffer<unsigned char> m_txDMRData1;
|
||||
CRingBuffer<unsigned char> m_txDMRData2;
|
||||
CRingBuffer<unsigned char> m_rxSerialData;
|
||||
CRingBuffer<unsigned char> m_txSerialData;
|
||||
CRingBuffer<unsigned char> m_rxYSFData;
|
||||
CRingBuffer<unsigned char> m_txYSFData;
|
||||
CRingBuffer<unsigned char> m_rxP25Data;
|
||||
CRingBuffer<unsigned char> m_txP25Data;
|
||||
CRingBuffer<unsigned char> m_rxNXDNData;
|
||||
CRingBuffer<unsigned char> m_txNXDNData;
|
||||
CRingBuffer<unsigned char> m_txPOCSAGData;
|
||||
CRingBuffer<unsigned char> m_rxTransparentData;
|
||||
CRingBuffer<unsigned char> m_txTransparentData;
|
||||
unsigned int m_sendTransparentDataFrameType;
|
||||
CTimer m_statusTimer;
|
||||
CTimer m_inactivityTimer;
|
||||
CTimer m_playoutTimer;
|
||||
unsigned int m_dstarSpace;
|
||||
unsigned int m_dmrSpace1;
|
||||
unsigned int m_dmrSpace2;
|
||||
unsigned int m_ysfSpace;
|
||||
unsigned int m_p25Space;
|
||||
unsigned int m_nxdnSpace;
|
||||
unsigned int m_pocsagSpace;
|
||||
bool m_tx;
|
||||
bool m_cd;
|
||||
bool m_lockout;
|
||||
bool m_error;
|
||||
unsigned char m_mode;
|
||||
HW_TYPE m_hwType;
|
||||
unsigned char m_capabilities1;
|
||||
unsigned char m_capabilities2;
|
||||
|
||||
bool readVersion();
|
||||
bool readStatus();
|
||||
bool setConfig1();
|
||||
bool setConfig2();
|
||||
bool setConfig();
|
||||
bool setFrequency();
|
||||
bool setFMCallsignParams();
|
||||
bool setFMAckParams();
|
||||
bool setFMMiscParams();
|
||||
bool setFMExtParams();
|
||||
|
||||
void printDebug();
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2016,2020,2021 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2016 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
@ -21,22 +21,22 @@
|
|||
#include <cstdio>
|
||||
#include <cassert>
|
||||
|
||||
IModemSerialPort::IModemSerialPort(CModem* modem) :
|
||||
CModemSerialPort::CModemSerialPort(CModem* modem) :
|
||||
m_modem(modem)
|
||||
{
|
||||
assert(modem != NULL);
|
||||
}
|
||||
|
||||
IModemSerialPort::~IModemSerialPort()
|
||||
CModemSerialPort::~CModemSerialPort()
|
||||
{
|
||||
}
|
||||
|
||||
bool IModemSerialPort::open()
|
||||
bool CModemSerialPort::open()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
int IModemSerialPort::write(const unsigned char* data, unsigned int length)
|
||||
int CModemSerialPort::write(const unsigned char* data, unsigned int length)
|
||||
{
|
||||
assert(data != NULL);
|
||||
assert(length > 0U);
|
||||
|
@ -46,7 +46,7 @@ int IModemSerialPort::write(const unsigned char* data, unsigned int length)
|
|||
return ret ? int(length) : -1;
|
||||
}
|
||||
|
||||
int IModemSerialPort::read(unsigned char* data, unsigned int length)
|
||||
int CModemSerialPort::read(unsigned char* data, unsigned int length)
|
||||
{
|
||||
assert(data != NULL);
|
||||
assert(length > 0U);
|
||||
|
@ -54,6 +54,6 @@ int IModemSerialPort::read(unsigned char* data, unsigned int length)
|
|||
return m_modem->readSerial(data, length);
|
||||
}
|
||||
|
||||
void IModemSerialPort::close()
|
||||
void CModemSerialPort::close()
|
||||
{
|
||||
}
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2016,2020,2021 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2016 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
@ -22,10 +22,10 @@
|
|||
#include "SerialPort.h"
|
||||
#include "Modem.h"
|
||||
|
||||
class IModemSerialPort : public ISerialPort {
|
||||
class CModemSerialPort : public ISerialPort {
|
||||
public:
|
||||
IModemSerialPort(CModem* modem);
|
||||
virtual ~IModemSerialPort();
|
||||
CModemSerialPort(CModem* modem);
|
||||
virtual ~CModemSerialPort();
|
||||
|
||||
virtual bool open();
|
||||
|
||||
|
|
577
NXDNAudio.cpp
Normal file
577
NXDNAudio.cpp
Normal file
|
@ -0,0 +1,577 @@
|
|||
/*
|
||||
* Copyright (C) 2018 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* 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 "NXDNAudio.h"
|
||||
#include "Golay24128.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
|
||||
const unsigned char BIT_MASK_TABLE[] = { 0x80U, 0x40U, 0x20U, 0x10U, 0x08U, 0x04U, 0x02U, 0x01U };
|
||||
|
||||
#define WRITE_BIT(p,i,b) p[(i)>>3] = (b) ? (p[(i)>>3] | BIT_MASK_TABLE[(i)&7]) : (p[(i)>>3] & ~BIT_MASK_TABLE[(i)&7])
|
||||
#define READ_BIT(p,i) (p[(i)>>3] & BIT_MASK_TABLE[(i)&7])
|
||||
|
||||
const unsigned int PRNG_TABLE[] = {
|
||||
0x42CC47U, 0x19D6FEU, 0x304729U, 0x6B2CD0U, 0x60BF47U, 0x39650EU, 0x7354F1U, 0xEACF60U, 0x819C9FU, 0xDE25CEU,
|
||||
0xD7B745U, 0x8CC8B8U, 0x8D592BU, 0xF71257U, 0xBCA084U, 0xA5B329U, 0xEE6AFAU, 0xF7D9A7U, 0xBCC21CU, 0x4712D9U,
|
||||
0x4F2922U, 0x14FA37U, 0x5D43ECU, 0x564115U, 0x299A92U, 0x20A9EBU, 0x7B707DU, 0x3BE3A4U, 0x20D95BU, 0x6B085AU,
|
||||
0x5233A5U, 0x99A474U, 0xC0EDCBU, 0xCB5F12U, 0x918455U, 0xF897ECU, 0xE32E3BU, 0xAA7CC2U, 0xB1E7C9U, 0xFC561DU,
|
||||
0xA70DE6U, 0x8DBE73U, 0xD4F608U, 0x57658DU, 0x0E5E56U, 0x458DABU, 0x7E15B8U, 0x376645U, 0x2DFD86U, 0x64EC3BU,
|
||||
0x3F1F60U, 0x3481B4U, 0x4DA00FU, 0x067BCEU, 0x1B68B1U, 0xD19328U, 0xCA03FFU, 0xA31856U, 0xF8EB81U, 0xF9F2F8U,
|
||||
0xA26067U, 0xA91BB6U, 0xF19A59U, 0x9A6148U, 0x8372B6U, 0xC8E86FU, 0x9399DCU, 0x1A0291U, 0x619142U, 0x6DE9FFU,
|
||||
0x367A2CU, 0x7D2511U, 0x6484DAU, 0x2F1F0FU, 0x1E6DB4U, 0x55F6E1U, 0x0EA70AU, 0x061C96U, 0xDD0E45U, 0xB4D738U,
|
||||
0xAF64ABU, 0xE47F42U, 0xFDBE9DU, 0xB684ACU, 0xFE5773U, 0xC1E4A2U, 0x8AFD0DU, 0x932ED4U, 0xD814E3U, 0x81853AU,
|
||||
0x225EECU, 0x7A6945U, 0x31A112U, 0x2AB2EBU, 0x630974U, 0x785AB5U, 0x11E3CEU, 0x4A715BU, 0x402AA0U, 0x199B7DU,
|
||||
0x16C05EU, 0x6F5283U, 0xA4FB10U, 0xBFA8ECU, 0xF633B7U, 0xEC4012U, 0xADD8C9U, 0xD6EB1CU, 0xDD3027U, 0x84A1FAU,
|
||||
0xCF9E19U, 0xD64C80U, 0xBC4557U, 0xA7B62EU, 0x6E2DA1U, 0x311F50U, 0x38C68EU, 0x63D5BFU, 0x486E60U, 0x10BFE1U,
|
||||
0x5BAD1EU, 0x4A4647U, 0x0157F0U, 0x7ACC29U, 0x73BEEAU, 0x2825D7U, 0xA0940CU, 0xFBCFF9U, 0xB05C62U, 0x892426U,
|
||||
0xC6B3DDU, 0xDF3840U, 0x9449B3U, 0xCED3BEU, 0xE7804DU, 0xBC3B90U, 0xF5AA0BU, 0xE6D17EU, 0x2D43B5U, 0x345A04U,
|
||||
0x5EA9DBU, 0x07A202U, 0x0C7134U, 0x45C9FDU, 0x5EDA0AU, 0x310193U, 0x6830C4U, 0x62AA3DU, 0x3B59B2U, 0xB04043U,
|
||||
0xEB975CU, 0x82BCADU, 0x912E62U, 0xD8F7FBU, 0x82C489U, 0x895F54U, 0xF00FE7U, 0xFBBC2AU, 0xA2E771U, 0xE956C4U,
|
||||
0xF6CD1FU, 0x3F8FEAU, 0x0534E1U, 0x4C653CU, 0x17FE8FU, 0x1C4C52U, 0x4515A1U, 0x2E86A9U, 0x3FBD56U, 0x756C87U,
|
||||
0x6ED218U, 0x279179U, 0x7C0AA6U, 0xD53B17U, 0x8EE0C8U, 0x85F291U, 0xD94B36U, 0x9298EFU, 0xAB8318U, 0xE07301U,
|
||||
0xBB68DFU, 0xB2CB7CU, 0xE910A5U, 0xE101D2U, 0x92BB4BU, 0x59E8B4U, 0x407175U, 0x0B026AU, 0x12989BU, 0x792944U,
|
||||
0x2376EDU, 0x2EF5BAU, 0x758663U, 0x7C1ED5U, 0x078D0CU, 0x4EF6ABU, 0x5567F2U, 0x9F7C29U, 0xC68E9CU, 0xC51747U,
|
||||
0xBC6422U, 0xB7EFB9U, 0xECFD44U, 0xA50497U, 0xAF178AU, 0xD68C69U, 0xD97DB5U, 0x82670EU, 0xCBB45BU, 0x508D90U,
|
||||
0x190A25U, 0x63F0FEU, 0x68E3C7U, 0x317A10U, 0x3A09D9U, 0x6B926EU, 0x004237U, 0x1B79C8U, 0x53EA59U, 0x48B3B7U,
|
||||
0x811166U, 0xDE4A79U, 0xF5F988U, 0xAC6057U, 0xE733FEU, 0xFF89ADU, 0xB49830U, 0x8F4BC3U, 0xC6F00EU, 0x9DA135U,
|
||||
0x942FE0U, 0xC71C3BU, 0x4DC78FU, 0x3476C4U, 0x7F6C39U, 0x66BFAAU, 0x298657U, 0x725504U, 0x5B4E89U, 0x01FE72U,
|
||||
0x0835A3U, 0x53269CU, 0x189D4DU, 0x01CDC2U, 0xEA763BU, 0xF3A56DU, 0xB0BCD4U, 0xE80F13U, 0xE355CAU, 0x98C47DU,
|
||||
0x91AB24U, 0xCE38DBU, 0x87A35AU, 0x9CD3A5U, 0xD648F4U, 0xAF7B6FU, 0x24A292U, 0x7D3011U, 0x764B6DU, 0x2DDABEU,
|
||||
0x44D123U, 0x5E22D8U, 0x1FB09DU, 0x04A926U, 0x4F5AF3U, 0x064128U, 0x3DB105U, 0x70AAD6U, 0xAA392FU, 0xA1C4B8U,
|
||||
0xF8C7C0U, 0xD35D0FU, 0x8A2E9EU, 0xC1B761U, 0xDA44F0U, 0x925E8FU, 0x89CF4EU, 0xE8B4D1U, 0xB32728U, 0xB8FE7FU,
|
||||
0x61DCC6U, 0x2A4701U, 0x1614D8U, 0x5DADE2U, 0x46BE37U, 0x0F44DCU, 0x54D549U, 0x5D8E32U, 0x263DAFU, 0x2C237CU,
|
||||
0x75E291U, 0xBE5982U, 0xA74A7FU, 0xC493A4U, 0xDFA131U, 0x967A5AU, 0xCCCB8EU, 0xC1D835U, 0x9A02ECU, 0xF331BBU,
|
||||
0xE8B812U, 0xA3EBC5U, 0xBA507CU, 0x7080ABU, 0x099BC2U, 0x02285DU, 0x59718CU, 0x50C273U, 0x0B1862U, 0x4A1F8CU,
|
||||
0x70A655U, 0x3BF5C2U, 0x666FBBU, 0x6DDE68U, 0x3485C5U, 0x9F161EU, 0xC46F4BU, 0x8CFDF0U, 0x97C625U, 0xDE058EU,
|
||||
0xC59CD3U, 0xAEAE20U, 0xF775BCU, 0xFC647FU, 0xBD9F02U, 0xE70C91U, 0xCC1468U, 0x11E7B7U, 0x1AFC36U, 0x435B49U,
|
||||
0x080398U, 0x139027U, 0x7B63FEU, 0x607AF9U, 0x29E900U, 0x7293D6U, 0x79026FU, 0x00D930U, 0x0BEAF1U, 0xD3614EU,
|
||||
0x90119FU, 0x8B8AE4U, 0xC61969U, 0xBD609AU, 0xB4F247U, 0xEFA954U, 0xE518A9U, 0xBC0362U, 0xD7D0D6U, 0xCE7E8DU,
|
||||
0x856F18U, 0x1C94E3U, 0x578726U, 0x0D5F1DU, 0x24ECC0U, 0x7FF713U, 0x3E26AAU, 0x251D6DU, 0x6A8F14U, 0x53648BU,
|
||||
0x19757AU, 0x40AEB4U, 0xCB9CA5U, 0x90055AU, 0x9956C3U, 0xE2ED34U, 0xAB3C7DU, 0xB126EAU, 0xFA9513U, 0xA3D2C8U,
|
||||
0x886BFDU, 0xD9F836U, 0xD2A2E3U, 0x8D1359U, 0x454804U, 0x5EDBF7U, 0x37637AU, 0x2C3089U, 0x67ABD4U, 0x3E8847U,
|
||||
0x3551BAU, 0x4D6331U, 0x46B8C4U, 0x1D299FU, 0x54120EU, 0x5FC0E1U, 0x86D93BU, 0xE56A0EU, 0xFBB1D5U, 0xB2B600U,
|
||||
0xA94EABU, 0xE05DF6U, 0x9BE605U, 0x90B798U, 0xC92C6BU, 0xC3DE66U, 0x9AC7BDU, 0xD15448U, 0x6A3FD3U, 0x23ADA3U,
|
||||
0x78346CU, 0x7147F5U, 0x2BDC02U, 0x0EAD5BU, 0x553FFCU, 0x1EA425U, 0x07D5F2U, 0x4C4ECBU, 0x554C14U, 0x3EB3F5U,
|
||||
0xE4A26AU, 0xED799BU, 0xB6CA85U, 0xFFD25CU, 0xC421BFU, 0x8F3A22U, 0x96AB51U, 0xDC518CU, 0x895217U, 0x8289F2U,
|
||||
0xF9B8A9U, 0xF0231CU, 0x2BF1C7U, 0x62C80AU, 0x781B39U, 0x1320E5U, 0x4AB156U, 0x41EB8FU, 0x1848E0U, 0x13D771U,
|
||||
0x4886AEU, 0x203C5FU, 0x3B6F40U, 0x76F6A1U, 0xE5457EU, 0xAE1EE7U, 0xD7AC10U, 0xDCB549U, 0x8476EFU, 0x8FC536U,
|
||||
0xD49DE9U, 0x9D0ED8U, 0xA63513U, 0xEFE4A6U, 0xB4DF7DU, 0x3E0D00U, 0x779693U, 0x4CA75EU, 0x0568ADU, 0x527BB0U,
|
||||
0x59C34BU, 0x00109FU, 0x0A0B14U, 0x73FA61U, 0x38E0BAU, 0x23530FU, 0x6A88D4U, 0xB199DDU, 0x98322AU, 0xC260F3U,
|
||||
0xCBF944U, 0x908A0DU, 0xDB11F2U, 0xC28163U, 0xADFABDU, 0xBC694CU, 0xF65243U, 0xAD83BAU, 0xA40D6DU, 0x5F7EF4U,
|
||||
0x16E787U, 0x0DF44AU, 0x460EF1U, 0x5E1F24U, 0x15CC3FU, 0x6C77CAU, 0x676401U, 0x3C9CBDU, 0x359FEEU, 0x6A0413U,
|
||||
0x02F590U, 0x91EE4DU, 0xDA3C3EU, 0xC305A3U, 0x889658U, 0xF14D99U, 0xFA7F86U, 0xA1E677U, 0xE981E8U, 0xF21A10U,
|
||||
0xBB4BD7U, 0x80F1CEU, 0xCB6239U, 0x123BE0U, 0x1D885FU, 0x45921EU, 0x6641E1U, 0x3DE870U, 0x74BBAFU, 0x6F00C6U,
|
||||
0x261055U, 0x7DCBA8U, 0x57787AU, 0x0E2167U, 0x05B28CU, 0xCC8819U, 0x975BE2U, 0xBC52B7U, 0xE5E52CU, 0xEB37C9U,
|
||||
0xB20E12U, 0xF9DD2FU, 0xE8C6FCU, 0x837701U, 0xD8AD82U, 0xD1BE5AU, 0x0B0525U, 0x0244B4U, 0x79FE5BU, 0x322DCAU,
|
||||
0x2B3495U, 0x60876CU, 0x79DCFBU, 0x334C12U, 0x4C7745U, 0x45A4DCU, 0x1E3F23U, 0x175FF2U, 0xC4C0D8U, 0xAFF30DU,
|
||||
0xB72AF6U, 0xFCB96BU, 0xA5C338U, 0xAE5295U, 0xF54946U, 0xDCBABBU, 0x87A1A8U, 0xCF2165U, 0xD4DA9EU, 0x9FC90BU,
|
||||
0x223070U, 0x6922A4U, 0x30B92FU, 0x3348D6U, 0x695B01U, 0x20C038U, 0x1BB2EFU, 0x523B06U, 0x49EC99U, 0x02D7C8U,
|
||||
0x5B4777U, 0x713CA6U, 0xA8AF49U, 0xA3B650U, 0xF84586U, 0xB5DF7FU, 0xAE8CF8U, 0xC72581U, 0x9D3652U, 0x9EEDCFU,
|
||||
0xC75D34U, 0xCC0671U, 0xB5B5CAU, 0xFEAC1FU, 0x677EA4U, 0x2DC5F9U, 0x26D63AU, 0x7F1F86U, 0x142855U, 0x0DF2A8U,
|
||||
0x42E3B3U, 0x195872U, 0x108B8DU, 0x6AB31CU, 0x632063U, 0x307BAAU, 0xFBC83DU, 0xE201C4U, 0xA91393U, 0x90A82AU,
|
||||
0xDAF9E4U, 0x816A55U, 0x88D00AU, 0xD383DBU, 0xFA3A64U, 0xA569A5U, 0xEEE2DEU, 0x76D243U, 0x3D0D90U, 0x649E6DU,
|
||||
0x47E76EU, 0x1C7491U, 0x156E49U, 0x4E9DDEU, 0x0604B7U, 0x3D3720U, 0x76FDD9U, 0x6FEC06U, 0x2417B7U, 0xFD04F8U,
|
||||
0xF29D29U, 0x886F92U, 0xC1744FU, 0xDAC73CU, 0x939EB1U, 0x880C63U, 0xEBE79EU, 0xB2F285U, 0xB86970U, 0xE11ABBU,
|
||||
0xEA822EU, 0x311155U, 0x586AC0U, 0x43F92BU, 0x0A81F6U, 0x5412C5U, 0x5D111CU, 0x26E8CBU, 0x2D7B63U, 0x74213CU,
|
||||
0x3F90CDU, 0x2E8B52U, 0x645883U, 0xDFE36CU, 0x96F375U, 0xDD0882U, 0xC40B1BU, 0x8FD6CCU, 0xB464A5U, 0xFC7F3EU,
|
||||
0xA7AECBU, 0xAA9511U, 0xF10634U, 0xBA5CEFU, 0x83ED32U, 0x483681U, 0x5015DCU, 0x138D3FU, 0x48DEA2U, 0x616571U,
|
||||
0x3AF40CU, 0x33AF97U, 0x681D72U, 0x2246E9U, 0x3BD7B9U, 0x506C46U, 0x0D2FDFU, 0x869338U, 0xDDC061U, 0xD45BD6U,
|
||||
0xAF6A0FU, 0xE7B8C0U, 0xFC2371U, 0xBF102EU, 0xA6C9DFU, 0xEDDA40U, 0x943089U, 0x9FA1BFU, 0x459A66U, 0x0C4995U,
|
||||
0x175108U, 0x7AE243U, 0x6139B6U, 0x2A2A2DU, 0x73D3D8U, 0x79C183U, 0x204A26U, 0x0B3FFDU, 0x5AA420U, 0x111613U,
|
||||
0x8A4FDFU, 0xC3DC2CU, 0xF9A7B5U, 0xB034EAU, 0xEBAC5BU, 0xE0CF94U, 0xBD5465U, 0xF605FAU, 0xCFBEA3U, 0x85AC54U,
|
||||
0x9E55DDU, 0xD7C62AU, 0x0CDD73U, 0x252FCDU, 0x76361CU, 0x7DF5D3U, 0x3546E2U, 0x6E5B39U, 0x67A98CU, 0x1CB247U,
|
||||
0x57231AU, 0x4AD8A9U, 0x01CA74U, 0x191187U, 0xF2208AU, 0xA9AB50U, 0xA0F8A5U, 0xFB403EU, 0xF2D34BU, 0xA9A880U,
|
||||
0xCB393DU, 0xD262EEU, 0x99D0B7U, 0xC04B00U, 0xCB1AC9U, 0xB0B176U, 0x39E3A7U, 0x677EF8U, 0x2ECD58U, 0x359687U,
|
||||
0x7E277EU, 0x473D69U, 0x0CEEB0U, 0x55D557U, 0x5F04CEU, 0x0C8EBDU, 0x25BD60U, 0x7E64DBU, 0xB7771EU, 0xACCC05U,
|
||||
0xE51CF0U, 0xBF2F2AU, 0x90F497U, 0xC9E7D4U, 0xC25F09U, 0x9B9CBAU, 0xD08767U, 0xEB320CU, 0xA36999U, 0x38FB42U,
|
||||
0x7180B3U, 0x22112CU, 0x29AA45U, 0x50F9D2U, 0x1B610AU, 0x0202FDU, 0x4899E4U, 0x57080BU, 0x3E72DAU, 0x65E165U,
|
||||
0x6CFA34U, 0xB70BEBU, 0xBC104AU, 0xE4E295U, 0x8F7BECU, 0x96787FU, 0xD583B2U, 0x9E9740U, 0x870C5DU, 0xECFFA6U,
|
||||
0xF4E433U, 0xBF35F8U, 0xE00F8DU, 0x699C16U, 0x3265EBU, 0x1B6638U, 0x40F515U, 0x0A8DC6U, 0x131E1BU, 0x5845A0U,
|
||||
0x21F670U, 0x2A6E1FU, 0x791D8EU, 0x708651U, 0x2AD7E8U, 0xE37CAFU, 0xD8EE56U, 0x97B3C1U, 0x8E0018U, 0xC51B6FU,
|
||||
0x9CC9E6U, 0xB67019U, 0xEF23C8U, 0xE498F2U, 0xBF9927U, 0xF643ECU, 0xCD7051U, 0x04E902U, 0x563AFFU, 0x5D006CU,
|
||||
0x04D3A1U, 0x0FCA9AU, 0x72794FU, 0x39A2B4U, 0x228231U, 0x6A19EAU, 0x714E96U, 0x18F705U, 0x4324FCU, 0xC83E3BU,
|
||||
0x918D02U, 0xDADCD5U, 0xC2470CU, 0xA135B3U, 0xBABCF2U, 0xF30F4DU, 0xA8549EU, 0xA1C543U, 0xDEFF78U, 0xD42CBCU,
|
||||
0x0DB747U, 0x46C6D2U, 0x5F5C89U, 0x144F60U, 0x6FA6F7U, 0x66350EU, 0x2C0A59U, 0x35DAE0U, 0x7EC12FU, 0x0D32FEU,
|
||||
0x0429C1U, 0x5FB911U, 0xD642AEU, 0x895167U, 0xC3D8B0U, 0xFAAB89U, 0xB1315AU, 0xA8C0A7U, 0xE3DB24U, 0xB84879U,
|
||||
0x913382U, 0xCBA317U, 0x82F8FCU, 0x994BA9U, 0x50C213U, 0x4390CEU, 0x282F5DU, 0x713E30U, 0x7FCDE3U, 0x26565EU,
|
||||
0x2D0485U, 0x56BDD4U, 0x1FAE7BU, 0x0475AAU, 0x4DD555U, 0x17CE4CU, 0x9C1D9BU, 0xE52473U, 0xEEF7E4U, 0xB7CD1DU,
|
||||
0xF45E42U, 0xEF87E3U, 0x87B43CU, 0x986FADU, 0xD16FD2U, 0x8AD403U, 0x8103A8U, 0xD83A75U, 0x33A826U, 0x2BF39BU,
|
||||
0x604049U, 0x7B99A4U, 0x328ABFU, 0x49306AU, 0x407191U, 0x1BEA04U, 0x19D96FU, 0x4001F2U, 0x0FB201U, 0x36E9DCU,
|
||||
0xFD7ADFU, 0xE64326U, 0xAF91F9U, 0xF51249U, 0xDC2B16U, 0x87F8D7U, 0xCCE668U, 0xC517B1U, 0x9E8C46U, 0x97BF5FU,
|
||||
0xED6498U, 0xA67461U, 0x378FF6U, 0x788C8FU, 0x611514U, 0x0AE6F1U, 0x53FC2BU, 0x596F3EU, 0x0216C5U, 0x4B8508U,
|
||||
0x507FBBU, 0x396EE6U, 0x22F535U, 0xE99688U, 0xB10F43U, 0xBA1D36U, 0xC3E2ADU, 0xC07178U, 0x9B28C3U, 0xD69A8BU,
|
||||
0xCD817CU, 0x8570E5U, 0xFEEB12U, 0xF5E8CBU, 0xAC10C4U, 0x270335U, 0x7ED8EAU, 0x156B5BU, 0x0E7A14U, 0x46A0C5U,
|
||||
0x5D937AU, 0x144AA3U, 0x4F79D5U, 0x6CF35CU, 0x31228FU, 0x7A1932U, 0x628E69U, 0xA9D59CU, 0x926517U, 0xDBBEE2U,
|
||||
0x80ADB9U, 0x891424U, 0xD246D7U, 0xD8ED1AU, 0xA17C28U, 0xEA27F5U, 0xF3942EU, 0xB8CE8FU, 0xAB5FD0U, 0x466461U,
|
||||
0x1CB7BEU, 0x152F6FU, 0x4E1CC0U, 0x05D799U, 0x1CE66EU, 0x773DF7U, 0x7EAB00U, 0x249048U, 0x6D41D7U, 0x765A26U,
|
||||
0x1DA9F9U, 0x8431C8U, 0xCF0203U, 0x96C1DEU, 0x90D86DU, 0xCB6A30U, 0xA23193U, 0xB9A24EU, 0xF05B95U, 0xEB48A0U,
|
||||
0xA0D27AU, 0xD8A39FU, 0xD33804U, 0x0A9B79U, 0x01C3AAU, 0x5A5437U, 0x132FD4U, 0x28BC0DU, 0x60253AU, 0x3F57E3U,
|
||||
0x3CCC7CU, 0x65DD9DU, 0x4E26C2U, 0x172572U, 0xDCDDADU, 0xC64E64U, 0x8F5553U, 0x94A68AU, 0xFDBE7DU, 0xA66DE4U,
|
||||
0xADD68BU, 0xF4C75AU, 0xFE0CC1U, 0x873E34U, 0xC8A72FU, 0xDBD0C2U, 0x124B10U, 0x49998DU, 0x40A8FEU, 0x3A3323U,
|
||||
0x316088U, 0x68D95DU, 0x235B06U, 0x3A00B3U, 0x51B178U, 0x4AEA89U, 0x025816U, 0x59C36FU, 0xD092B8U, 0x8B2930U,
|
||||
0xE43AC7U, 0xF5E2DEU, 0xBEC121U, 0xA71AF0U, 0xED8B7FU, 0x94B40EU, 0x9F66D1U, 0xD45D68U, 0xCD8CBFU, 0x8617F6U,
|
||||
0x5F2545U, 0x75FC98U, 0x2EFF62U, 0x674467U, 0x7C959CU, 0x318F09U, 0x0A7CD2U, 0x4967AFU, 0x11D62CU, 0x1A8CD1U,
|
||||
0x431F02U, 0x48A69DU, 0xB3E5ECU, 0xFA7623U, 0xE10E9AU, 0xA99948U, 0xB20215U, 0xD971A6U, 0x80E86BU, 0x8BDA90U,
|
||||
0xD60185U, 0x9D907EU, 0x8FFBFBU, 0xE66920U, 0x7D705DU, 0x3483CEU, 0x6F9833U, 0x646BF1U, 0x1DF3E8U, 0x17E017U,
|
||||
0x4E1BC6U, 0x050A79U, 0x1E8038U, 0x5773E7U, 0x2C685EU, 0xA1BD89U, 0xFB86B0U, 0xF01477U, 0xA16D8EU, 0xCAFE19U,
|
||||
0xD365C1U, 0x9815AEU, 0x839E3FU, 0xCBCDC4U, 0x907611U, 0xB9E70AU, 0xE2BDE7U, 0x2B0E34U, 0x301789U, 0x7BE4DAU,
|
||||
0x477707U, 0x0C2FACU, 0x558C79U, 0x5E9743U, 0x0D4496U, 0x04786DU, 0x7FABE0U, 0x3730B3U, 0x3C014AU, 0xE7DADDU,
|
||||
0xEEE834U, 0x956163U, 0xDCB2FAU, 0xC78905U, 0x8D5BD4U, 0xD0427BU, 0xDBF12BU, 0xA22AB4U, 0xA93B4DU, 0xFA819AU,
|
||||
0xB3D2B3U, 0x287B64U, 0x40289DU, 0x5BB206U, 0x100153U, 0x495CB8U, 0x42CF2DU, 0x3BF4D6U, 0x70248BU, 0x6ABF19U,
|
||||
0x23CCF4U, 0x3C4527U, 0x75761AU, 0x8EACC1U, 0x853F44U, 0xD44EBFU, 0xDED5EEU, 0x87C751U, 0xEC3E80U, 0xF72D6FU,
|
||||
0xBEB676U, 0xE557A1U, 0xEC4D59U, 0xB6BECEU, 0x9DA527U, 0x443078U, 0x0BCAE9U, 0x12D916U, 0x594087U, 0x6033E8U,
|
||||
0x22A831U, 0x7948A2U, 0x70535FU, 0x2BC01CU, 0x62BBA1U, 0x592A7BU, 0x92308EU, 0x8AC395U, 0xC15A50U, 0x9809ABU,
|
||||
0xB3B336U, 0xECB245U, 0xE54998U, 0xBEDA1BU, 0xF681E6U, 0xED35F5U, 0x8E2E0CU, 0x87FDD3U, 0x5CC453U, 0x1556ACU,
|
||||
0x0E85FDU, 0x64AC42U, 0x3D7F8BU, 0x36447CU, 0x6FD665U, 0x640FB2U, 0x3B3C4BU, 0x52A7C4U, 0x48F7B5U, 0x014C2EU,
|
||||
0x9A9FFBU, 0xD19601U, 0xA0250CU, 0xAB7FFFU, 0xF2C822U, 0xB8D1B1U, 0xA302CCU, 0xEAB907U, 0xD1E9B2U, 0x987269U,
|
||||
0xC3411CU, 0xCC8897U, 0x141A42U, 0x3F61B8U, 0x66F2A1U, 0x2DCB56U, 0x3618DFU, 0x778208U, 0x2CB3F1U, 0x0468EEU,
|
||||
0x5F7B1FU, 0x5693D0U, 0x0D8041U, 0x461B3EU, 0xFFECE7U, 0xB4FD50U, 0xA94798U, 0xE314CFU, 0xB88D76U, 0xB17EADU,
|
||||
0xCA7508U, 0xC3E553U, 0x989EA6U, 0xDB0D3DU, 0xC396E8U, 0xA8E683U, 0x717D1EU, 0x7A0EEDU, 0x219730U, 0x288422U,
|
||||
0x736ECFU, 0x1BFF14U, 0x04A4A1U, 0x4F177AU, 0x56092BU, 0x1DD884U, 0x64635DU, 0xEF70EAU, 0xA589B3U, 0xF49B54U,
|
||||
0xFF50CDU, 0xA66312U, 0x8DFA62U, 0xD628FDU, 0x9F131CU, 0x8582C3U, 0xCCF9DAU, 0xF36A29U, 0xB8B2F4U, 0x618157U,
|
||||
0x6A020AU, 0x335999U, 0x79E864U, 0x4272BFU, 0x03259AU, 0x189C40U, 0x51CFB5U, 0x0A752EU, 0x216463U, 0x79BF90U,
|
||||
0x721C0DU, 0xAB47FEU, 0xE4D727U, 0xFDEC28U, 0x963FD9U, 0x8DA646U, 0xC594B7U, 0x9E4FE8U, 0x977E60U, 0xECA597U,
|
||||
0xAF264EU, 0xB61C79U, 0xFDCDA0U, 0x65D64FU, 0x2E61DCU, 0x553881U, 0x5CAA72U, 0x0351FBU, 0x0A400CU, 0x51FB55U,
|
||||
0x3BB9CAU, 0x22223AU, 0x6993B5U, 0x30C8C4U, 0x3B5B1BU, 0xE02B82U, 0xC1B075U, 0x9B23BCU, 0xD25A8BU, 0xC9C852U,
|
||||
0x82A3A9U, 0xBB303CU, 0xF42977U, 0xADDA82U, 0xA64418U, 0xFC55E5U, 0xB5AEE6U, 0x0EBD3BU, 0x4765C8U, 0x4CD655U,
|
||||
0x17DD2EU, 0x562EEBU, 0x6C3770U, 0x25A585U, 0x3E5EDEU, 0x754F6FU, 0x2C94A1U, 0x23A758U, 0x5A3F4FU, 0xD07C96U,
|
||||
0x8BC761U, 0xC254E8U, 0xD92C97U, 0xB0BF06U, 0xEBE0D9U, 0xE25138U, 0xB8CAA7U, 0xBB98DEU, 0xE22109U, 0x896291U,
|
||||
0x10F172U, 0x5BCB2FU, 0x401A94U, 0x0CA141U, 0x77B2BAU, 0x7E6BBFU, 0x255964U, 0x6E82D9U, 0x77130AU, 0x3C3877U,
|
||||
0x04EAF4U, 0x4FD129U, 0x9C40DBU, 0x959BC6U, 0xCEAC2DU, 0xE774FCU, 0xBC6763U, 0xF6DC12U, 0xEB8DCDU, 0xA00664U,
|
||||
0xF9F4B3U, 0xD2EF4AU, 0x895E5DU, 0x800584U, 0x5A972BU, 0x132EFBU, 0x287D84U, 0x63E615U, 0x7297CEU, 0x391D23U,
|
||||
0x608E30U, 0x6AF5CDU, 0x11641EU, 0x5C5E93U, 0x4789E0U, 0x0E903DU, 0x956386U, 0xFEF053U, 0xB6E879U, 0xAD0BACU,
|
||||
0xE41077U, 0xFF83CAU, 0xB47A99U, 0xCD6870U, 0xCE93E7U, 0x96823EU, 0x9D1941U, 0xC4EBD0U, 0x2BF23FU, 0x3031EEU,
|
||||
0x790A71U, 0x229909U, 0x2AC1CEU, 0x717677U, 0x5AEDA0U, 0x039C99U, 0x480646U, 0x515587U, 0x1AEC3CU, 0x296F69U,
|
||||
0xE13492U, 0xBA8607U, 0xB39FCCU, 0xEC4CB1U, 0xA77723U, 0x9EA7DEU, 0xD51C0DU, 0xCD0F00U, 0x86D4FBU, 0xDDF56EU,
|
||||
0xF46F95U, 0x2FBCD4U, 0x268D6BU, 0x7D52B2U, 0x374165U, 0x26F9DCU, 0x4D2A9BU, 0x141163U, 0x1FD2FCU, 0x40CA2DU,
|
||||
0x497952U, 0x3322D3U, 0x7AB32CU, 0xE108F5U, 0xAA5AE2U, 0xB3E31BU, 0xF8B098U, 0x812B65U, 0x8B8936U, 0xD0D08AU,
|
||||
0xD94341U, 0x8A7894U, 0xE3A9AFU, 0xF8377AU, 0xB74481U, 0x6FDD0CU, 0x64EE5FU, 0x3D35A2U, 0x163731U, 0x5F8ECCU,
|
||||
0x045DC7U, 0x0F4616U, 0x57B6E8U, 0x7CAD79U, 0x253E86U, 0x6EC7CFU, 0x7DD478U, 0xB426A1U, 0xCF2D76U, 0xC3BC5FU,
|
||||
0x984780U, 0x935571U, 0xCACCEEU, 0x81BBBFU, 0xB82054U, 0xF371C0U, 0xE9CB3BU, 0xA05826U, 0xFB33F5U, 0x52A218U,
|
||||
0x09B88BU, 0x424BF6U, 0x53D22DU, 0x198198U, 0x043A53U, 0x6F2A06U, 0x34F1BDU, 0x3DC260U, 0x664982U, 0x6FB81BU,
|
||||
0x15A24CU, 0xDE71F5U, 0xC7482AU, 0x8CDFCBU, 0x9505D4U, 0xDE3405U, 0xA5EFFAU, 0xA4FC63U, 0xFE5704U, 0xB387DDU,
|
||||
0xA8BC6AU, 0xC32FB2U, 0x5A7EE5U, 0x11C44CU, 0x489797U, 0x420E62U, 0x19BD79U, 0x30E6BCU, 0x6B6407U, 0x225DDAU,
|
||||
0x398EA9U, 0x703534U, 0x0A64F7U, 0x09FA0AU, 0xD4C910U, 0xDF10E5U, 0x86833EU, 0xCDB99BU, 0xE67A40U, 0xBE631BU,
|
||||
0xB590AEU, 0xEC8B75U, 0xA73BD0U, 0x9CE08BU, 0xD5F35EU, 0x8E0AE5U, 0x061828U, 0x5D835AU, 0x5660C7U, 0x277914U,
|
||||
0x68CAE9U, 0x7190E2U, 0x3A0113U, 0x20FECCU, 0x49ED7DU, 0x127522U, 0x1B06ABU, 0x40855CU, 0x8B9E85U, 0x926FB2U,
|
||||
0xF8F56AU, 0xE186A5U, 0xAA1F14U, 0xF10CCBU, 0xF0F7BAU, 0x8F6735U, 0x867CECU, 0xDC9F1FU, 0x978402U, 0x8E54F1U,
|
||||
0x45EF3CU, 0x7CFC8FU, 0x3705D2U, 0x6C1248U, 0x64C8BDU, 0x3FF976U, 0x566243U, 0x4DA198U, 0x069B45U, 0x1F0AF6U,
|
||||
0x5851BBU, 0x00E248U, 0xAB3BD1U, 0xF2090EU, 0xF9926FU, 0xA2C3F1U, 0xEB7800U, 0xD07B9FU, 0x98A1E6U, 0xC31021U,
|
||||
0xC84BB8U, 0x91D84FU, 0x9AEC96U, 0x6337A9U, 0x288468U, 0x369FB3U, 0x774E06U, 0x6C645DU, 0x05B7A9U, 0x4E2E22U,
|
||||
0x551DFFU, 0x1CC78CU, 0x47D611U, 0x4F2DF2U, 0x343E6FU, 0xBF8514U, 0xE655C1U, 0xAD5E5AU, 0xB4EDBFU, 0xDFB4E4U,
|
||||
0xC1265DU, 0x80DD8BU, 0xDBC852U, 0xD25375U, 0x8920ACU, 0xA2BA53U, 0xFB0BC2U, 0x31401DU, 0x28D33CU, 0x63AAE3U,
|
||||
0x18381AU, 0x11238DU, 0x4AD2E4U, 0x434933U, 0x195BABU, 0x56A058U, 0x6FB105U, 0x2C5AAEU, 0x35C97BU, 0xFED9A0U,
|
||||
0xA52295U, 0x8D314EU, 0xD6ECA3U, 0x9F5E30U, 0x84456DU, 0xCFB6DEU, 0xD6AF03U, 0xBD2CE9U, 0xE556FCU, 0xEEC707U,
|
||||
0xB71CD6U, 0x382F59U, 0x43B720U, 0x02E4F7U, 0x195F4EU, 0x51CC99U, 0x0AA550U, 0x013767U, 0x786CBEU, 0x73DD01U,
|
||||
0x2AC6D1U, 0x61159EU, 0x7BA92FU, 0x92BAF4U, 0x896109U, 0xC0521AU, 0x9F9AF7U, 0x942924U, 0xC532B9U, 0xEFE3C2U,
|
||||
0xA6D807U, 0xFD0ABCU, 0xF69369U, 0xAFA033U, 0x44738EU, 0x5D694DU, 0x17C8F0U, 0x0C93A3U, 0x45207AU, 0x1EF9C5U,
|
||||
0x37EB04U, 0x6850FBU, 0x6305EAU, 0x3B9E15U, 0x782DC4U, 0x41774BU, 0x8AF633U, 0xD18DE4U, 0xD81E5DU, 0x83A69AU,
|
||||
0x8AF583U, 0xF06E7CU, 0xBB5FADU, 0xA28416U, 0xE99653U, 0xF06D88U, 0x9FEC35U, 0xC4F7E6U, 0x4C059AU, 0x1F1C19U,
|
||||
0x56EFC4U, 0x4D743FU, 0x24612AU, 0x3F9BD1U, 0x748814U, 0x2C13AFU, 0x27F276U, 0x5EE861U, 0x553B88U, 0x0E0A5FU,
|
||||
0xC791E6U, 0xD8E2B0U, 0x907A69U, 0xABE9C6U, 0xE09217U, 0xB10168U, 0xBA48F9U, 0xE3FA26U, 0x8861CFU, 0x9230D8U,
|
||||
0xDB8B21U, 0xC099B2U, 0x09644FU, 0x52F704U, 0x79AC90U, 0x201F6BU, 0x2E17BEU, 0x77C495U, 0x3CFF48U, 0x172E9BU,
|
||||
0x4E9426U, 0x0D8775U, 0x145E98U, 0x5E6D03U, 0xC5F6D6U, 0xAC242DU, 0xF70D3CU, 0xFEDED2U, 0xA5C543U, 0xAE74BCU,
|
||||
0xD62EE5U, 0x9D9D72U, 0x80029BU, 0xCB534CU, 0x90E175U, 0x19BAAAU, 0x6A3B6BU, 0x6280D4U, 0x39D385U, 0x724B7AU,
|
||||
0x6B78E2U, 0x00A321U, 0x19101CU, 0x5248CFU, 0x0ADB30U, 0x01F0A9U, 0x5A21CEU, 0xB73A17U, 0xACC880U, 0xE55179U,
|
||||
0xFE42A6U, 0xB4B987U, 0xC5AF58U, 0xCE1688U, 0x97C533U, 0x9CCE76U, 0xC73F8DU, 0x8E2510U, 0xB4B6C3U, 0x7D4FFEU,
|
||||
0x665C3DU, 0x2DC7C0U, 0x70B55BU, 0x5B2C2EU, 0x025FF5U, 0x49D470U, 0x53448AU, 0x1A3FD7U, 0x09AC64U, 0x60BDBDU,
|
||||
0x3B467AU, 0xB0D043U, 0xE98B9CU, 0xE33A2DU, 0x9A21E2U, 0xD1C3B3U, 0xCA5A0CU, 0x8709DDU, 0xDCB222U, 0xF5A3AAU,
|
||||
0xBF79DDU, 0xA44A04U, 0xEDD193U, 0x3E006AU, 0x373B21U, 0x4CF994U, 0x47C04FU, 0x1F53DAU, 0x5488A1U, 0x4DB86CU,
|
||||
0x2623DFU, 0x7D7402U, 0x70CF50U, 0x2B9EFDU, 0x232426U, 0xF8A7D3U, 0x91FEC8U, 0x8A4D39U, 0xC117F6U, 0xD0866FU,
|
||||
0x9B3D18U, 0xE36EC1U, 0xE8F576U, 0xB3C5BFU, 0xBA1629U, 0xE1BD50U, 0xA8EC8FU, 0x17763EU, 0x5D45F1U, 0x049CA0U,
|
||||
0x0F8F1FU, 0x5630C6U, 0x7DE225U, 0x26FB38U, 0x6F08CBU, 0x7D0316U, 0x34B28DU, 0x2F68E9U, 0xC47B72U, 0x9DC287U,
|
||||
0x96915CU, 0xCF0B41U, 0x85F8A2U, 0xBAE17FU, 0xF372CCU, 0xE81991U, 0xA1894AU, 0xFAF2EBU, 0xF16134U, 0x89F845U,
|
||||
0x0A8ADBU, 0x53153AU, 0x1806E5U, 0x03FF7CU, 0x6A7C0BU, 0x312692U, 0x399775U, 0x628CACU, 0x6D7FB3U, 0x34EE42U,
|
||||
0x5FF49DU, 0x56073CU, 0x8D1C67U, 0x87CDBBU, 0xDEE708U, 0xB574D5U, 0xA4ADB6U, 0xEF9E2BU, 0xF605D0U, 0xBD7545U,
|
||||
0xE6EE0EU, 0xCE39FBU, 0x950260U, 0xD8929DU, 0x43D9CEU, 0x086A47U, 0x31B3B1U, 0x7AA068U, 0x221ADFU, 0x294B86U,
|
||||
0x72F049U, 0x73E3F8U, 0x083927U, 0x418856U, 0x5AC3C9U, 0x105020U, 0xC969B7U, 0xE2BBEEU, 0xBF2019U, 0xB41181U,
|
||||
0xEFCA6AU, 0xA6FD3FU, 0xBC27A4U, 0xD53651U, 0xCE9D9AU, 0x854EA7U, 0xDC5E74U, 0xDFE5A9U, 0x26B61AU, 0x6C0D57U,
|
||||
0x77DCECU, 0x3EC639U, 0x2575C3U, 0x682CD6U, 0x13AF1DU, 0x1855ECU, 0x404473U, 0x4BDF8AU, 0x12ACDDU, 0xF93754U,
|
||||
0xE207A3U, 0xABD87AU, 0xF04B45U, 0xF03284U, 0xABB05BU, 0x80ABEBU, 0xD95AB4U, 0x92C10DU, 0x8FD2CEU, 0xC42833U,
|
||||
0xEC3920U, 0x37C2FDU, 0x7C5106U, 0x654883U, 0x2EAAF8U, 0x37B12DU, 0x5C20B6U, 0x065B42U, 0x07C909U, 0x5C12B4U,
|
||||
0x152367U, 0x2EB4FAU, 0x65CF19U, 0xFC5F40U, 0xB294FFU, 0xEBA72EU, 0xE03ED1U, 0x9B6CD0U, 0x92D70FU, 0xC944F6U,
|
||||
0x801D60U, 0x9AAE19U, 0xF1F4DEU, 0xA85547U, 0xAB4EB8U, 0x729DE9U, 0x792456U, 0x223697U, 0x4BED0CU, 0x55DE71U,
|
||||
0x1C03A2U, 0x07910FU, 0x4CAADCU, 0x356BA0U, 0x3E5033U, 0x67C3EEU, 0x2D9B05U, 0xB62810U, 0xFFF3EBU, 0xC4E03EU,
|
||||
0x8558A5U, 0xDE0B48U, 0xD5905BU, 0x8D71A2U, 0xA26A75U, 0xFBD8ECU, 0xB08982U, 0xAB1253U, 0xE2A1ECU, 0x79FB3FU,
|
||||
0x116E52U, 0x4A15C9U, 0x43861CU, 0x188FE7U, 0x537DF2U, 0x62E619U, 0x29D7C0U, 0x310C57U, 0x7A1F2EU, 0x25E5B8U,
|
||||
0xAC7451U, 0xC76F86U, 0xDE9C9FU, 0x959460U, 0xCF27B1U, 0xC6FC1EU, 0xBDEDCFU, 0xF416B0U, 0xEF0429U, 0xA49FEEU,
|
||||
0xBDEA17U, 0xFF7104U, 0x06A3F8U, 0x0D8A63U, 0x5219A6U, 0x5B62DDU, 0x00F348U, 0x6969B3U, 0x731A6EU, 0x38816DU,
|
||||
0x61D090U, 0x6A6343U, 0x33F9FEU, 0x18B8A5U, 0xC30340U, 0x8B10DAU, 0x98E80BU, 0xD1FB74U, 0xEA20F5U, 0xA5930AU,
|
||||
0xFC8E93U, 0xF75CC4U, 0xAF673DU, 0xA4E6BAU, 0xDF3D43U, 0x960F9CU, 0x0DD68DU, 0x44E572U, 0x1F7EB2U, 0x35AD09U,
|
||||
0x6C9554U, 0x6746A7U, 0x365D3AU, 0x7DFCF9U, 0x64A6C4U, 0x0B351FU, 0x118CEAU, 0x58DF61U, 0x836434U, 0x8A36CFU,
|
||||
0xF1AB5BU, 0xBA18A0U, 0xA343EDU, 0xE8C27EU, 0xF0F887U, 0xBB2B50U, 0xC03A69U, 0xC9C1A6U, 0x9A5317U, 0x9368C8U,
|
||||
0x5CB919U, 0x26A226U, 0x2F01EFU, 0x74D919U, 0x3DCA80U, 0x2631D7U, 0x6D223EU, 0x54BAA1U, 0x1E4950U, 0x47520BU,
|
||||
0x4CA79EU, 0x97BC75U, 0xBE3EA8U, 0xED479BU, 0xA4D446U, 0xBA4FF5U, 0xF13C39U, 0xE8A46AU, 0x83D7D7U, 0xDA4C0CU,
|
||||
0xD1DDF9U, 0x8AA7F2U, 0xC22427U, 0x793DDCU, 0x30CE45U, 0x2B5522U, 0x6007FBU, 0x39BE6CU, 0x32AD95U, 0x42560BU,
|
||||
0x4D426AU, 0x16D1B5U, 0x5F3A04U, 0x442BDBU, 0x2DF082U, 0xF6C225U, 0xFE59FCU, 0xA5880FU, 0xAEB312U, 0xF761C9U,
|
||||
0x9C582CU, 0x85CBB7U, 0xCE00C3U, 0xD43118U, 0x9DAB9DU, 0xEAF866U, 0xE3437BU, 0x381288U, 0x738955U, 0x6A3BF6U,
|
||||
0x2066ABU, 0x19D570U, 0x52DEC1U, 0x090E1EU, 0x00B5FFU, 0x5BE6E1U, 0x727D38U, 0x284CCFU, 0x639656U, 0xFA8531U,
|
||||
0xBD3CA8U, 0xD4EF77U, 0xCFC586U, 0x841489U, 0x9C0F78U, 0xD7BCA7U, 0x8E671EU, 0xA5774DU, 0xFE8481U, 0xF79F32U,
|
||||
0xAC0AEFU, 0x65F09CU, 0x5FF301U, 0x144ACAU, 0x0D193FU, 0x468224U, 0x13F0D1U, 0x18694AU, 0x63FA87U, 0x2B81F4U,
|
||||
0x30106DU, 0x790A9BU, 0xE2E952U, 0x8970CDU, 0xD003BCU, 0xDB9963U, 0x838AD2U, 0x88731DU, 0xD1E064U, 0xBAFFF3U,
|
||||
0xA10F2AU, 0xEC049DU, 0xBFD7D4U, 0xB7EE2BU, 0x4C7CBBU, 0x478760U, 0x1E9415U, 0x554D9EU, 0x4C7E6BU, 0x07E4B0U,
|
||||
0x3D35ADU, 0x741E4EU, 0x2F8D93U, 0x26FC20U, 0x7D667DU, 0x16B586U, 0x8B8E02U, 0xC91FD9U, 0xD0456CU, 0x9BF237U,
|
||||
0xC0EBCEU, 0xE92849U, 0xB29390U, 0xBBC3E7U, 0xE1787EU, 0xAA6B81U, 0x93B040U, 0xD8005FU, 0x411BAEU, 0x0AC870U,
|
||||
0x51F1D1U, 0x5D328EU, 0x362837U, 0x6799E0U, 0x6C4239U, 0x37711AU, 0x3EABC7U, 0x45BA3CU, 0x0D01A9U, 0x16D6F2U,
|
||||
0xDDCF17U, 0xC46D8CU, 0x8F3670U, 0xF6A723U, 0xFD5CBCU, 0xA74F5DU, 0xEAF582U, 0xF1A43BU, 0x903768U, 0x8B0CC5U,
|
||||
0xC0DC16U, 0x9957CBU, 0x1324F0U, 0x4ABD25U, 0x61AECEU, 0x38545AU, 0x73C701U, 0x68FEF4U, 0x212D6FU, 0x5B3382U,
|
||||
0x52C2D1U, 0x09494CU, 0x065ABFU, 0xDFA126U, 0x9CB149U, 0xA56A98U, 0xEE5927U, 0xF4C0F6U, 0xBD33B8U, 0xE62901U,
|
||||
0xCFB8D6U, 0x94D32FU, 0x9F40B8U, 0xC69AF1U, 0x8CAB0EU, 0x15309FU, 0x7E6360U, 0x21DA31U, 0x2848BAU, 0x733747U,
|
||||
0x72A6D4U, 0x08EDA8U, 0x435F7BU, 0x5A4CD6U, 0x119505U, 0x082658U, 0x433DE3U, 0xB8ED26U, 0xB0D6DDU, 0xEB05C8U,
|
||||
0xA2BC13U, 0xA9BEEAU, 0xD6656DU, 0xDF5614U, 0x848F82U, 0xC41C5BU, 0xDF26A4U, 0x94F7A5U, 0xADCC5AU, 0x665B8BU,
|
||||
0x3F1234U, 0x34A0EDU, 0x6E7BAAU, 0x076813U, 0x1CD1C4U, 0x55833DU, 0x4E1836U, 0x03A9E2U, 0x58F219U, 0x72418CU,
|
||||
0x2B09F7U, 0xA89A72U, 0xF1A1A9U, 0xBA7254U, 0x81EA47U, 0xC899BAU, 0xD20279U, 0x9B13C4U, 0xC0E09FU, 0xCB7E4BU,
|
||||
0xB25FF0U, 0xF98431U, 0xE4974EU, 0x2E6CD7U, 0x35FC00U, 0x5CE7A9U, 0x07147EU, 0x060D07U, 0x5D9F98U, 0x56E449U,
|
||||
0x0E65A6U, 0x659EB7U, 0x7C8D49U, 0x371790U, 0x6C6623U, 0xE5FD6EU, 0x9E6EBDU, 0x921600U, 0xC985D3U, 0x82DAEEU,
|
||||
0x9B7B25U, 0xD0E0F0U, 0xE1924BU, 0xAA091EU, 0xF158F5U, 0xF9E369U, 0x22F1BAU, 0x4B28C7U, 0x509B54U, 0x1B80BDU,
|
||||
0x024162U, 0x497B53U, 0x01A88CU, 0x3E1B5DU, 0x7502F2U, 0x6CD12BU, 0x27EB1CU, 0x7E7AC5U, 0xDDA113U, 0x8596BAU,
|
||||
0xCE5EEDU, 0xD54D14U, 0x9CF68BU, 0x87A54AU, 0xEE1C31U, 0xB58EA4U, 0xBFD55FU, 0xE66482U, 0xE93FA1U, 0x90AD7CU,
|
||||
0x5B04EFU, 0x405713U, 0x09CC48U, 0x13BFEDU, 0x522736U, 0x2914E3U, 0x22CFD8U, 0x7B5E05U, 0x3061E6U, 0x29B37FU,
|
||||
0x43BAA8U, 0x5849D1U, 0x91D25EU, 0xCEE0AFU, 0xC73971U, 0x9C2A40U, 0xB7919FU, 0xEF401EU, 0xA452E1U, 0xB5B9B8U,
|
||||
0xFEA80FU, 0x8533D6U, 0x8C4115U, 0xD7DA28U, 0x5F6BF3U, 0x043006U, 0x4FA39DU, 0x76DBD9U, 0x394C22U, 0x20C7BFU,
|
||||
0x6BB64CU, 0x312C41U, 0x187FB2U, 0x43C46FU, 0x0A55F4U, 0x192E81U, 0xD2BC4AU, 0xCBA5FBU, 0xA15624U, 0xF85DFDU,
|
||||
0xF38ECBU, 0xBA3602U, 0xA125F5U, 0xCEFE6CU, 0x97CF3BU, 0x9D55C2U, 0xC4A64DU, 0x4FBFBCU, 0x1468A3U, 0x7D4352U,
|
||||
0x6ED19DU, 0x270804U, 0x7D3B76U, 0x76A0ABU, 0x0FF018U, 0x0443D5U, 0x5D188EU, 0x16A93BU, 0x0932E0U, 0xC07015U,
|
||||
0xFACB1EU, 0xB39AC3U, 0xE80170U, 0xE3B3ADU, 0xBAEA5EU, 0xD17956U, 0xC042A9U, 0x8A9378U, 0x912DE7U, 0xD86E86U,
|
||||
0x83F559U, 0x2AC4E8U, 0x711F37U, 0x7A0D6EU, 0x26B4C9U, 0x6D6710U, 0x547CE7U, 0x1F8CFEU, 0x449720U, 0x4D3483U,
|
||||
0x16EF5AU, 0x1EFE2DU, 0x6D44B4U, 0xA6174BU, 0xBF8E8AU, 0xF4FD95U, 0xED6764U, 0x86D6BBU, 0xDC8912U, 0xD10A45U,
|
||||
0x8A799CU, 0x83E12AU, 0xF872F3U, 0xB10954U, 0xAA980DU, 0x6083D6U, 0x397163U, 0x3AE8B8U, 0x439BDDU, 0x481046U,
|
||||
0x1302BBU, 0x5AFB68U, 0x50E875U, 0x297396U, 0x26824AU, 0x7D98F1U, 0x344BA4U, 0xAF726FU, 0xE6F5DAU, 0x9C0F01U,
|
||||
0x971C38U, 0xCE85EFU, 0xC5F626U, 0x946D91U, 0xFFBDC8U, 0xE48637U, 0xAC15A6U, 0xB74C48U, 0x7EEE99U, 0x21B586U,
|
||||
0x0A0677U, 0x539FA8U, 0x18CC01U, 0x007652U, 0x4B67CFU, 0x70B43CU, 0x390FF1U, 0x625ECAU, 0x6BD01FU, 0x38E3C4U,
|
||||
0xB23870U, 0xCB893BU, 0x8093C6U, 0x994055U, 0xD679A8U, 0x8DAAFBU, 0xA4B176U, 0xFE018DU, 0xF7CA5CU, 0xACD963U,
|
||||
0xE762B2U, 0xFE323DU, 0x1589C4U, 0x0C5A92U, 0x4F432BU, 0x17F0ECU, 0x1CAA35U, 0x673B82U, 0x6E54DBU, 0x31C724U,
|
||||
0x785CA5U, 0x632C5AU, 0x29B70BU, 0x508490U, 0xDB5D6DU, 0x82CFEEU, 0x89B492U, 0xD22541U, 0xBB2EDCU, 0xA1DD27U,
|
||||
0xE04F62U, 0xFB56D9U, 0xB0A50CU, 0xF9BED7U, 0xC24EFAU, 0x8F5529U, 0x55C6D0U, 0x5E3B47U, 0x07383FU, 0x2CA2F0U,
|
||||
0x75D161U, 0x3E489EU, 0x25BB0FU, 0x6DA170U, 0x7630B1U, 0x174B2EU, 0x4CD8D7U, 0x470180U, 0x9E2339U, 0xD5B8FEU,
|
||||
0xE9EB27U, 0xA2521DU, 0xB941C8U, 0xF0BB23U, 0xAB2AB6U, 0xA271CDU, 0xD9C250U, 0xD3DC83U, 0x8A1D6EU, 0x41A67DU,
|
||||
0x58B580U, 0x3B6C5BU, 0x205ECEU, 0x6985A5U, 0x333471U, 0x3E27CAU, 0x65FD13U, 0x0CCE44U, 0x1747EDU, 0x5C143AU,
|
||||
0x45AF83U, 0x8F7F54U, 0xF6643DU, 0xFDD7A2U, 0xA68E73U, 0xAF3D8CU, 0xF4E79DU, 0xB5E073U, 0x8F59AAU, 0xC40A3DU,
|
||||
0x999044U, 0x922197U, 0xCB7A3AU, 0x60E9E1U, 0x3B90B4U, 0x73020FU, 0x6839DAU, 0x21FA71U, 0x3A632CU, 0x5151DFU,
|
||||
0x088A43U, 0x039B80U, 0x4260FDU, 0x18F36EU, 0x33EB97U, 0xEE1848U, 0xE503C9U, 0xBCA4B6U, 0xF7FC67U, 0xEC6FD8U,
|
||||
0x849C01U, 0x9F8506U, 0xD616FFU, 0x8D6C29U, 0x86FD90U, 0xFF26CFU, 0xF4150EU, 0x2C9EB1U, 0x6FEE60U, 0x74751BU,
|
||||
0x39E696U, 0x429F65U, 0x4B0DB8U, 0x1056ABU, 0x1AE756U, 0x43FC9DU, 0x282F29U, 0x318172U, 0x7A90E7U, 0xE36B1CU,
|
||||
0xA878D9U, 0xF2A0E2U, 0xDB133FU, 0x8008ECU, 0xC1D955U, 0xDAE292U, 0x9570EBU, 0xAC9B74U, 0xE68A85U, 0xBF514BU,
|
||||
0x34635AU, 0x6FFAA5U, 0x66A93CU, 0x1D12CBU, 0x54C382U, 0x4ED915U, 0x056AECU, 0x5C2D37U, 0x779402U, 0x2607C9U,
|
||||
0x2D5D1CU, 0x72ECA6U, 0xBAB7FBU, 0xA12408U, 0xC89C85U, 0xD3CF76U, 0x98542BU, 0xC177B8U, 0xCAAE45U, 0xB29CCEU,
|
||||
0xB9473BU, 0xE2D660U, 0xABEDF1U, 0xA03F1EU, 0x7926C4U, 0x1A95F1U, 0x044E2AU, 0x4D49FFU, 0x56B154U, 0x1FA209U,
|
||||
0x6419FAU, 0x6F4867U, 0x36D394U, 0x3C2199U, 0x653842U, 0x2EABB7U, 0x95C02CU, 0xDC525CU, 0x87CB93U, 0x8EB80AU,
|
||||
0xD423FDU, 0xF152A4U, 0xAAC003U, 0xE15BDAU, 0xF82A0DU, 0xB3B134U, 0xAAB3EBU, 0xC14C0AU, 0x1B5D95U, 0x128664U,
|
||||
0x49357AU, 0x002DA3U, 0x3BDE40U, 0x70C5DDU, 0x6954AEU, 0x23AE73U, 0x76ADE8U, 0x7D760DU, 0x064756U, 0x0FDCE3U,
|
||||
0xD40E38U, 0x9D37F5U, 0x87E4C6U, 0xECDF1AU, 0xB54EA9U, 0xBE1470U, 0xE7B71FU, 0xEC288EU, 0xB77951U, 0xDFC3A0U,
|
||||
0xC490BFU, 0x89095EU, 0x1ABA81U, 0x51E118U, 0x2853EFU, 0x234AB6U, 0x7B8910U, 0x703AC9U, 0x2B6216U, 0x62F127U,
|
||||
0x59CAECU, 0x101B59U, 0x4B2082U, 0xC1F2FFU, 0x88696CU, 0xB358A1U, 0xFA9752U, 0xAD844FU, 0xA63CB4U, 0xFFEF60U,
|
||||
0xF5F4EBU, 0x8C059EU, 0xC71F45U, 0xDCACF0U, 0x95772BU, 0x4E6622U, 0x67CDD5U, 0x3D9F0CU, 0x3406BBU, 0x6F75F2U,
|
||||
0x24EE0DU, 0x3D7E9CU, 0x520542U, 0x4396B3U, 0x09ADBCU, 0x527C45U, 0x5BF292U, 0xA0810BU, 0xE91878U, 0xF20BB5U,
|
||||
0xB9F10EU, 0xA1E0DBU, 0xEA33C0U, 0x938835U, 0x989BFEU, 0xC36342U, 0xCA6011U, 0x95FBECU, 0xFD0A6FU, 0x6E11B2U,
|
||||
0x25C3C1U, 0x3CFA5CU, 0x7769A7U, 0x0EB266U, 0x058079U, 0x5E1988U, 0x167E17U, 0x0DE5EFU, 0x44B428U, 0x7F0E31U,
|
||||
0x349DC6U, 0xEDC41FU, 0xE277A0U, 0xBA6DE1U, 0x99BE1EU, 0xC2178FU, 0x8B4450U, 0x90FF39U, 0xD9EFAAU, 0x823457U,
|
||||
0xA88785U, 0xF1DE98U, 0xFA4D73U, 0x3377E6U, 0x68A41DU, 0x43AD48U, 0x1A1AD3U, 0x14C836U, 0x4DF1EDU, 0x0622D0U,
|
||||
0x173903U, 0x7C88FEU, 0x27527DU, 0x2E41A5U, 0xF4FADAU, 0xFDBB4BU, 0x8601A4U, 0xCDD235U, 0xD4CB6AU, 0x9F7893U,
|
||||
0x862304U, 0xCCB3EDU, 0xB388BAU, 0xBA5B23U, 0xE1C0DCU, 0xE8A00DU, 0x3B3F27U, 0x500CF2U, 0x48D509U, 0x034694U,
|
||||
0x5A3CC7U, 0x51AD6AU, 0x0AB6B9U, 0x234544U, 0x785E57U, 0x30DE9AU, 0x2B2561U, 0x6036F4U, 0xDDCF8FU, 0x96DD5BU,
|
||||
0xCF46D0U, 0xCCB729U, 0x96A4FEU, 0xDF3FC7U, 0xE44D10U, 0xADC4F9U, 0xB61366U, 0xFD2837U, 0xA4B888U, 0x8EC359U,
|
||||
0x5750B6U, 0x5C49AFU, 0x07BA79U, 0x4A2080U, 0x517307U, 0x38DA7EU, 0x62C9ADU, 0x611230U, 0x38A2CBU, 0x33F98EU,
|
||||
0x4A4A35U, 0x0153E0U, 0x98815BU, 0xD23A06U, 0xD929C5U, 0x80E079U, 0xEBD7AAU, 0xF20D57U, 0xBD1C4CU, 0xE6A78DU,
|
||||
0xEF7472U, 0x954CE3U, 0x9CDF9CU, 0xCF8455U, 0x0437C2U, 0x1DFE3BU, 0x56EC6CU, 0x6F57D5U, 0x25061BU, 0x7E95AAU,
|
||||
0x772FF5U, 0x2C7C24U, 0x05C59BU, 0x5A965AU, 0x111D21U, 0x892DBCU, 0xC2F26FU, 0x9B6192U, 0xB81891U, 0xE38B6EU,
|
||||
0xEA91B6U, 0xB16221U, 0xF9FB48U, 0xC2C8DFU, 0x890226U, 0x9013F9U, 0xDBE848U, 0x02FB07U, 0x0D62D6U, 0x77906DU,
|
||||
0x3E8BB0U, 0x2538C3U, 0x6C614EU, 0x77F39CU, 0x141861U, 0x4D0D7AU, 0x47968FU, 0x1EE544U, 0x157DD1U, 0xCEEEAAU,
|
||||
0xA7953FU, 0xBC06D4U, 0xF57E09U, 0xABED3AU, 0xA2EEE3U, 0xD91734U, 0xD2849CU, 0x8BDEC3U, 0xC06F32U, 0xD174ADU,
|
||||
0x9BA77CU, 0x201C93U, 0x690C8AU, 0x22F77DU, 0x3BF4E4U, 0x702933U, 0x4B9B5AU, 0x0380C1U, 0x585134U, 0x556AEEU,
|
||||
0x0EF9CBU, 0x45A310U, 0x7C12CDU, 0xB7C97EU, 0xAFEA23U, 0xEC72C0U, 0xB7215DU, 0x9E9A8EU, 0xC50BF3U, 0xCC5068U,
|
||||
0x97E28DU, 0xDDB916U, 0xC42846U, 0xAF93B9U, 0xF2D020U, 0x796CC7U, 0x223F9EU, 0x2BA429U, 0x5095F0U, 0x18473FU,
|
||||
0x03DC8EU, 0x40EFD1U, 0x593620U, 0x1225BFU, 0x6BCF76U, 0x605E40U, 0xBA6599U, 0xF3B66AU, 0xE8AEF7U, 0x851DBCU,
|
||||
0x9EC649U, 0xD5D5D2U, 0x8C2C27U, 0x863E7CU, 0xDFB5D9U, 0xF4C002U, 0xA55BDFU, 0xEEE9ECU, 0x75B020U, 0x3C23D3U,
|
||||
0x06584AU, 0x4FCB15U, 0x1453A4U, 0x1F306BU, 0x42AB9AU, 0x09FA05U, 0x30415CU, 0x7A53ABU, 0x61AA22U, 0x2839D5U,
|
||||
0xF3228CU, 0xDAD032U, 0x89C9E3U, 0x820A2CU, 0xCAB91DU, 0x91A4C6U, 0x985673U, 0xE34DB8U, 0xA8DCE5U, 0xB52756U,
|
||||
0xFE358BU, 0xE6EE78U, 0x0DDF75U, 0x5654AFU, 0x5F075AU, 0x04BFC1U, 0x0D2CB4U, 0x56577FU, 0x34C6C2U, 0x2D9D11U,
|
||||
0x662F48U, 0x3FB4FFU, 0x34E536U, 0x4F4E89U, 0xC61C58U, 0x988107U, 0xD132A7U, 0xCA6978U, 0x81D881U, 0xB8C296U,
|
||||
0xF3114FU, 0xAA2AA8U, 0xA0FB31U, 0xF37142U, 0xDA429FU, 0x819B24U, 0x4888E1U, 0x5333FAU, 0x1AE30FU, 0x40D0D5U,
|
||||
0x6F0B68U, 0x36182BU, 0x3DA0F6U, 0x646345U, 0x2F7898U, 0x14CDF3U, 0x5C9666U, 0xC704BDU, 0x8E7F4CU, 0xDDEED3U,
|
||||
0xD655BAU, 0xAF062DU, 0xE49EF5U, 0xFDFD02U, 0xB7661BU, 0xA8F7F4U, 0xC18D25U, 0x9A1E9AU, 0x9305CBU, 0x48F414U,
|
||||
0x43EFB5U, 0x1B1D6AU, 0x708413U, 0x698780U, 0x2A7C4DU, 0x6168BFU, 0x78F3A2U, 0x130059U, 0x0B1BCCU, 0x40CA07U,
|
||||
0x1FF072U, 0x9663E9U, 0xCD9A14U, 0xE499C7U, 0xBF0AEAU, 0xF57239U, 0xECE1E4U, 0xA7BA5FU, 0xDE098FU, 0xD591E0U,
|
||||
0x86E271U, 0x8F79AEU, 0xD52817U, 0x1C8350U, 0x2711A9U, 0x684C3EU, 0x71FFE7U, 0x3AE490U, 0x633619U, 0x498FE6U,
|
||||
0x10DC37U, 0x1B670DU, 0x4066D8U, 0x09BC13U, 0x328FAEU, 0xFB16FDU, 0xA9C500U, 0xA2FF93U, 0xFB2C5EU, 0xF03565U,
|
||||
0x8D86B0U, 0xC65D4BU, 0xDD7DCEU, 0x95E615U, 0x8EB169U, 0xE708FAU, 0xBCDB03U, 0x37C1C4U, 0x6E72FDU, 0x25232AU,
|
||||
0x3DB8F3U, 0x5ECA4CU, 0x45430DU, 0x0CF0B2U, 0x57AB61U, 0x5E3ABCU, 0x210087U, 0x2BD343U, 0xF248B8U, 0xB9392DU,
|
||||
0xA0A376U, 0xEBB09FU, 0x905908U, 0x99CAF1U, 0xD3F5A6U, 0xCA251FU, 0x813ED0U, 0xF2CD01U, 0xFBD63EU, 0xA046EEU,
|
||||
0x29BD51U, 0x76AE98U, 0x3C274FU, 0x055476U, 0x4ECEA5U, 0x573F58U, 0x1C24DBU, 0x47B786U, 0x6ECC7DU, 0x345CE8U,
|
||||
0x7D0703U, 0x66B456U, 0xAF3DECU, 0xBC6F31U, 0xD7D0A2U, 0x8EC1CFU, 0x80321CU, 0xD9A9A1U, 0xD2FB7AU, 0xA9422BU,
|
||||
0xE05184U, 0xFB8A55U, 0xB22AAAU, 0xE831B3U, 0x63E264U, 0x1ADB8CU, 0x11081BU, 0x4832E2U, 0x0BA1BDU, 0x10781CU,
|
||||
0x784BC3U, 0x679052U, 0x2E902DU, 0x752BFCU, 0x7EFC57U, 0x27C58AU, 0xCC57D9U, 0xD40C64U, 0x9FBFB6U, 0x84665BU,
|
||||
0xCD7540U, 0xB6CF95U, 0xBF8E6EU, 0xE415FBU, 0xE62690U, 0xBFFE0DU, 0xF04DFEU, 0xC91623U, 0x028520U, 0x19BCD9U,
|
||||
0x506E06U, 0x0AEDB6U, 0x23D4E9U, 0x780728U, 0x331997U, 0x3AE84EU, 0x6173B9U, 0x6840A0U, 0x129B67U, 0x598B9EU,
|
||||
0xC87009U, 0x877370U, 0x9EEAEBU, 0xF5190EU, 0xAC03D4U, 0xA690C1U, 0xFDE93AU, 0xB47AF7U, 0xAF8044U, 0xC69119U,
|
||||
0xDD0ACAU, 0x166977U, 0x4EF0BCU, 0x45E2C9U, 0x3C1D52U, 0x3F8E87U, 0x64D73CU, 0x296574U, 0x327E83U, 0x7A8F1AU,
|
||||
0x0114EDU, 0x0A1734U, 0x53EF3BU, 0xD8FCCAU, 0x812715U, 0xEA94A4U, 0xF185EBU, 0xB95F3AU, 0xA26C85U, 0xEBB55CU,
|
||||
0xB0862AU, 0x930CA3U, 0xCEDD70U, 0x85E6CDU, 0x9D7196U, 0x562A63U, 0x6D9AE8U, 0x24411DU, 0x7F5246U, 0x76EBDBU,
|
||||
0x2DB928U, 0x2712E5U, 0x5E83D7U, 0x15D80AU, 0x0C6BD1U, 0x473170U, 0x54A02FU, 0xB99B9EU, 0xE34841U, 0xEAD090U,
|
||||
0xB1E33FU, 0xFA2866U, 0xE31991U, 0x88C208U, 0x8154FFU, 0xDB6FB7U, 0x92BE28U, 0x89A5D9U, 0xE25606U, 0x7BCE37U,
|
||||
0x30FDFCU, 0x693E21U, 0x6F2792U, 0x3495CFU, 0x5DCE6CU, 0x465DB1U, 0x0FA46AU, 0x14B75FU, 0x5F2D85U, 0x275C60U,
|
||||
0x2CC7FBU, 0xF56486U, 0xFE3C55U, 0xA5ABC8U, 0xECD02BU, 0xD743F2U, 0x9FDAC5U, 0xC0A81CU, 0xC33383U, 0x9A2262U,
|
||||
0xB1D93DU, 0xE8DA8DU, 0x232252U, 0x39B19BU, 0x70AAACU, 0x6B5975U, 0x024182U, 0x59921BU, 0x522974U, 0x0B38A5U,
|
||||
0x01F33EU, 0x78C1CBU, 0x3758D0U, 0x242F3DU, 0xEDB4EFU, 0xB66672U, 0xBF5701U, 0xC5CCDCU, 0xCE9F77U, 0x9726A2U,
|
||||
0xDCA4F9U, 0xC5FF4CU, 0xAE4E87U, 0xB51576U, 0xFDA7E9U, 0xA63C90U, 0x2F6D47U, 0x74D6CFU, 0x1BC538U, 0x0A1D21U,
|
||||
0x413EDEU, 0x58E50FU, 0x127480U, 0x6B4BF1U, 0x60992EU, 0x2BA297U, 0x327340U, 0x79E809U, 0xA0DABAU, 0x8A0367U,
|
||||
0xD1009DU, 0x98BB98U, 0x836A63U, 0xCE70F6U, 0xF5832DU, 0xB69850U, 0xEE29D3U, 0xE5732EU, 0xBCE0FDU, 0xB75962U,
|
||||
0x4C1A13U, 0x0589DCU, 0x1EF165U, 0x5666B7U, 0x4DFDEAU, 0x268E59U, 0x7F1794U, 0x74256FU, 0x29FE7AU, 0x626F81U,
|
||||
0x700404U, 0x1996DFU, 0x828FA2U, 0xCB7C31U, 0x9067CCU, 0x9B940EU, 0xE20C17U, 0xE81FE8U, 0xB1E439U, 0xFAF586U,
|
||||
0xE17FC7U, 0xA88C18U, 0xD397A1U, 0x5E4276U, 0x04794FU, 0x0FEB88U, 0x5E9271U, 0x3501E6U, 0x2C9A3EU, 0x67EA51U,
|
||||
0x7C61C0U, 0x34323BU, 0x6F89EEU, 0x4618F5U, 0x1D4218U, 0xD4F1CBU, 0xCFE876U, 0x841B25U, 0xB888F8U, 0xF3D053U,
|
||||
0xAA7386U, 0xA168BCU, 0xF2BB69U, 0xFB8792U, 0x80541FU, 0xC8CF4CU, 0xC3FEB5U, 0x182522U, 0x1117CBU, 0x6A9E9CU,
|
||||
0x234D05U, 0x3876FAU, 0x72A42BU, 0x2FBD84U, 0x240ED4U, 0x5DD54BU, 0x56C4B2U, 0x057E65U, 0x4C2D4CU, 0xD7849BU,
|
||||
0xBFD762U, 0xA44DF9U, 0xEFFEACU, 0xB6A347U, 0xBD30D2U, 0xC40B29U, 0x8FDB74U, 0x9540E6U, 0xDC330BU, 0xC3BAD8U,
|
||||
0x8A89E5U, 0x71533EU, 0x7AC0BBU, 0x2BB140U, 0x212A11U, 0x7838AEU, 0x13C17FU, 0x08D290U, 0x414989U, 0x1AA85EU,
|
||||
0x13B2A6U, 0x494131U, 0x625AD8U, 0xBBCF87U, 0xF43516U, 0xED26E9U, 0xA6BF78U, 0x9FCC17U, 0xDD57CEU, 0x86B75DU,
|
||||
0x8FACA0U, 0xD43FE3U, 0x9D445EU, 0xA6D584U, 0x6DCF71U, 0x753C6AU, 0x3EA5AFU, 0x67F654U, 0x4C4CC9U, 0x134DBAU,
|
||||
0x1AB667U, 0x4125E4U, 0x097E19U, 0x12CA0AU, 0x71D1F3U, 0x78022CU, 0xA33BACU, 0xEAA953U, 0xF17A02U, 0x9B53BDU,
|
||||
0xC28074U, 0xC9BB83U, 0x90299AU, 0x9BF04DU, 0xC4C3B4U, 0xAD583BU, 0xB7084AU, 0xFEB3D1U, 0x656004U, 0x2E69FEU,
|
||||
0x5FDAF3U, 0x548000U, 0x0D37DDU, 0x472E4EU, 0x5CFD33U, 0x1546F8U, 0x2E164DU, 0x678D96U, 0x3CBEE3U, 0x337768U,
|
||||
0xEBE5BDU, 0xC09E47U, 0x990D5EU, 0xD234A9U, 0xC9E720U, 0x887DF7U, 0xD34C0EU, 0xFB9711U, 0xA084E0U, 0xA96C2FU,
|
||||
0xF27FBEU, 0xB9E4C1U, 0x001318U, 0x4B02AFU, 0x56B867U, 0x1CEB30U, 0x477289U, 0x4E8152U, 0x358AF7U, 0x3C1AACU,
|
||||
0x676159U, 0x24F2C2U, 0x3C6917U, 0x57197CU, 0x8E82E1U, 0x85F112U, 0xDE68CFU, 0xD77BDDU, 0x8C9130U, 0xE400EBU,
|
||||
0xFB5B5EU, 0xB0E885U, 0xA9F6D4U, 0xE2277BU, 0x9B9CA2U, 0x108F15U, 0x5A764CU, 0x0B64ABU, 0x00AF32U, 0x599CEDU,
|
||||
0x72059DU, 0x29D702U, 0x60ECE3U, 0x7A7D3CU, 0x330625U, 0x0C95D6U, 0x474D0BU, 0x9E7EA8U, 0x95FDF5U, 0xCCA666U,
|
||||
0x86179BU, 0xBD8D40U, 0xFCDA65U, 0xE763BFU, 0xAE304AU, 0xF58AD1U, 0xDE9B9CU, 0x86406FU, 0x8DE3F2U, 0x54B801U,
|
||||
0x1B28D8U, 0x0213D7U, 0x69C026U, 0x7259B9U, 0x3A6B48U, 0x61B017U, 0x68819FU, 0x135A68U, 0x50D9B1U, 0x49E386U,
|
||||
0x02325FU, 0x9A29B0U, 0xD19E23U, 0xAAC77EU, 0xA3558DU, 0xFCAE04U, 0xF5BFF3U, 0xAE04AAU, 0xC44635U, 0xDDDDC5U,
|
||||
0x966C4AU, 0xCF373BU, 0xC4A4E4U, 0x1FD47DU, 0x3E4F8AU, 0x64DC43U, 0x2DA574U, 0x3637ADU, 0x7D5C56U, 0x44CFC3U,
|
||||
0x0BD688U, 0x52257DU, 0x59BBE7U, 0x03AA1AU, 0x4A5119U, 0xF142C4U, 0xB89A37U, 0xB329AAU, 0xE822D1U, 0xA9D114U,
|
||||
0x93C88FU, 0xDA5A7AU, 0xC1A121U, 0x8AB090U, 0xD36B5EU, 0xDC58A7U, 0xA5C0B0U, 0x2F8369U, 0x74389EU, 0x3DAB17U,
|
||||
0x26D368U, 0x4F40F9U, 0x141F26U, 0x1DAEC7U, 0x473558U, 0x446721U, 0x1DDEF6U, 0x769D6EU, 0xEF0E8DU, 0xA434D0U,
|
||||
0xBFE56BU, 0xF35EBEU, 0x884D45U, 0x819440U, 0xDAA69BU, 0x917D26U, 0x88ECF5U, 0xC3C788U, 0xFB150BU, 0xB02ED6U,
|
||||
0x63BF24U, 0x6A6439U, 0x3153D2U, 0x188B03U, 0x43989CU, 0x0923EDU, 0x147232U, 0x5FF99BU, 0x060B4CU, 0x2D10B5U,
|
||||
0x76A1A2U, 0x7FFA7BU, 0xA568D4U, 0xECD104U, 0xD7827BU, 0x9C19EAU, 0x8D6831U, 0xC6E2DCU, 0x9F71CFU, 0x950A32U,
|
||||
0xEE9BE1U, 0xA3A16CU, 0xB8761FU, 0xF16FC2U, 0x6A9C79U, 0x010FACU, 0x491786U, 0x52F453U, 0x1BEF88U, 0x007C35U,
|
||||
0x4B8566U, 0x32978FU, 0x316C18U, 0x697DC1U, 0x62E6BEU, 0x3B142FU, 0xD40DC0U, 0xCFCE11U, 0x86F58EU, 0xDD66F6U,
|
||||
0xD53E31U, 0x8E8988U, 0xA5125FU, 0xFC6366U, 0xB7F9B9U, 0xAEAA78U, 0xE513C3U, 0xD69096U, 0x1ECB6DU, 0x4579F8U,
|
||||
0x4C6033U, 0x13B34EU, 0x5888DCU, 0x615821U, 0x2AE3F2U, 0x32F0FFU, 0x792B04U, 0x220A91U, 0x0B906AU, 0xD0432BU,
|
||||
0xD97294U, 0x82AD4DU, 0xC8BE9AU, 0xD90623U, 0xB2D564U, 0xEBEE9CU, 0xE02D03U, 0xBF35D2U, 0xB686ADU, 0xCCDD2CU,
|
||||
0x854CD3U, 0x1EF70AU, 0x55A51DU, 0x4C1CE4U, 0x074F67U, 0x7ED49AU, 0x7476C9U, 0x2F2F75U, 0x26BCBEU, 0x75876BU,
|
||||
0x1C5650U, 0x07C885U, 0x48BB7EU, 0x9022F3U, 0x9B11A0U, 0xC2CA5DU, 0xE9C8CEU, 0xA07133U, 0xFBA238U, 0xF0B9E9U,
|
||||
0xA84917U, 0x835286U, 0xDAC179U, 0x913830U, 0x822B87U, 0x4BD95EU, 0x30D289U, 0x3C43A0U, 0x67B87FU, 0x6CAA8EU,
|
||||
0x353311U, 0x7E4440U, 0x47DFABU, 0x0C8E3FU, 0x1634C4U, 0x5FA7D9U, 0x04CC0AU, 0xAD5DE7U, 0xF64774U, 0xBDB409U,
|
||||
0xAC2DD2U, 0xE67E67U, 0xFBC5ACU, 0x90D5F9U, 0xCB0E42U, 0xC23D9FU, 0x99B67DU, 0x9047E4U, 0xEA5DB3U, 0x218E0AU,
|
||||
0x38B7D5U, 0x732034U, 0x6AFA2BU, 0x21CBFAU, 0x5A1005U, 0x5B039CU, 0x01A8FBU, 0x4C7822U, 0x574395U, 0x3CD04DU,
|
||||
0xA5811AU, 0xEE3BB3U, 0xB76868U, 0xBDF19DU, 0xE64286U, 0xCF1943U, 0x949BF8U, 0xDDA225U, 0xC67156U, 0x8FCACBU,
|
||||
0xF59B08U, 0xF605F5U, 0x2B36EFU, 0x20EF1AU, 0x797CC1U, 0x324664U, 0x1985BFU, 0x419CE4U, 0x4A6F51U, 0x13748AU,
|
||||
0x58C42FU, 0x631F74U, 0x2A0CA1U, 0x71F51AU, 0xF9E7D7U, 0xA27CA5U, 0xA99F38U, 0xD886EBU, 0x973516U, 0x8E6F1DU,
|
||||
0xC5FEECU, 0xDF0133U, 0xB61282U, 0xED8ADDU, 0xE4F954U, 0xBF7AA3U, 0x74617AU, 0x6D904DU, 0x070A95U, 0x1E795AU,
|
||||
0x55E0EBU, 0x0EF334U, 0x0F0845U, 0x7098CAU, 0x798313U, 0x2360E0U, 0x687BFDU, 0x71AB0EU, 0xBA10C3U, 0x830370U,
|
||||
0xC8FA2DU, 0x93EDB7U, 0x9B3742U, 0xC00689U, 0xA99DBCU, 0xB25E67U, 0xF964BAU, 0xE0F509U, 0xA7AE44U, 0xFF1DB7U,
|
||||
0x54C42EU, 0x0DF6F1U, 0x066D90U, 0x5D3C0EU, 0x1487FFU, 0x2F8460U, 0x675E19U, 0x3CEFDEU, 0x37B447U, 0x6E27B0U,
|
||||
0x651369U, 0x9CC856U, 0xD77B97U, 0xC9604CU, 0x88B1F9U, 0x939BA2U, 0xFA4856U, 0xB1D1DDU, 0xAAE200U, 0xE33873U,
|
||||
0xB829EEU, 0xB0D20DU, 0xCBC190U, 0x407AEBU, 0x19AA3EU, 0x52A1A5U, 0x4B1240U, 0x204B1BU, 0x3ED9A2U, 0x7F2274U,
|
||||
0x2437ADU, 0x2DAC8AU, 0x76DF53U, 0x5D45ACU, 0x04F43DU, 0xCEBFE2U, 0xD72CC3U, 0x9C551CU, 0xE7C7E5U, 0xEEDC72U,
|
||||
0xB52D1BU, 0xBCB6CCU, 0xE6A454U, 0xA95FA7U, 0x904EFAU, 0xD3A551U, 0xCA3684U, 0x01265FU, 0x5ADD6AU, 0x72CEB1U,
|
||||
0x29135CU, 0x60A1CFU, 0x7BBA92U, 0x304921U, 0x2950FCU, 0x42D316U, 0x1AA903U, 0x1138F8U, 0x48E329U, 0xC7D0A6U,
|
||||
0xBC48DFU, 0xFD1B08U, 0xE6A0B1U, 0xAE3366U, 0xF55AAFU, 0xFEC898U, 0x879341U, 0x8C22FEU, 0xD5392EU, 0x9EEA61U,
|
||||
0x8456D0U, 0x6D450BU, 0x769EF6U, 0x3FADE5U, 0x606508U, 0x6BD6DBU, 0x3ACD46U, 0x101C3DU, 0x5927F8U, 0x02F543U,
|
||||
0x096C96U, 0x505FCCU, 0xBB8C71U, 0xA296B2U, 0xE8370FU, 0xF36C5CU, 0xBADF85U, 0xE1063AU, 0xC814FBU, 0x97AF04U,
|
||||
0x9CFA15U, 0xC461EAU, 0x87D23BU, 0xBE88B4U, 0x7509CCU, 0x2E721BU, 0x27E1A2U, 0x7C5965U, 0x750A7CU, 0x0F9183U,
|
||||
0x44A052U, 0x5D7BE9U, 0x1669ACU, 0x0F9277U, 0x6013CAU, 0x3B0819U, 0xB3FA65U, 0xE0E3E6U, 0xA9103BU, 0xB28BC0U,
|
||||
0xDB9ED5U, 0xC0642EU, 0x8B77EBU, 0xD3EC50U, 0xD80D89U, 0xA1179EU, 0xAAC477U, 0xF1F5A0U, 0x386E19U, 0x271D4FU,
|
||||
0x6F8596U, 0x541639U, 0x1F6DE8U, 0x4EFE97U, 0x45B706U, 0x1C05D9U, 0x779E30U, 0x6DCF27U, 0x2474DEU, 0x3F664DU,
|
||||
0xF69BB0U, 0xAD08FBU, 0x86536FU, 0xDFE094U, 0xD1E841U, 0x883B6AU, 0xC300B7U, 0xE8D164U, 0xB16BD9U, 0xF2788AU,
|
||||
0xEBA167U, 0xA192FCU, 0x3A0929U, 0x53DBD2U, 0x08F2C3U, 0x01212DU, 0x5A3ABCU, 0x518B43U, 0x29D11AU, 0x62628DU,
|
||||
0x7FFD64U, 0x34ACB3U, 0x6F1E8AU, 0xE64555U, 0x95C494U, 0x9D7F2BU, 0xC62C7AU, 0x8DB485U, 0x94871DU, 0xFF5CDEU,
|
||||
0xE6EFE3U, 0xADB730U, 0xF524CFU, 0xFE0F56U, 0xA5DE31U, 0x48C5E8U, 0x53377FU, 0x1AAE86U, 0x01BD59U, 0x4B4678U,
|
||||
0x3A50A7U, 0x31E977U, 0x683ACCU, 0x633189U, 0x38C072U, 0x71DAEFU, 0x4B493CU, 0x82B001U, 0x99A3C2U, 0xD2383FU,
|
||||
0x8F4AA4U, 0xA4D3D1U, 0xFDA00AU, 0xB62B8FU, 0xACBB75U, 0xE5C028U, 0xF6539BU, 0x9F4242U, 0xC4B985U, 0x4F2FBCU,
|
||||
0x167463U, 0x1CC5D2U, 0x65DE1DU, 0x2E3C4CU, 0x35A5F3U, 0x78F622U, 0x234DDDU, 0x0A5C55U, 0x408622U, 0x5BB5FBU,
|
||||
0x122E6CU, 0xC1FF95U, 0xC8C4DEU, 0xB3066BU, 0xB83FB0U, 0xE0AC25U, 0xAB775EU, 0xB24793U, 0xD9DC20U, 0x828BFDU,
|
||||
0x8F30AFU, 0xD46102U, 0xDCDBD9U, 0x07582CU, 0x6E0137U, 0x75B2C6U, 0x3EE809U, 0x2F7990U, 0x64C2E7U, 0x1C913EU,
|
||||
0x170A89U, 0x4C3A40U, 0x45E9D6U, 0x1E42AFU, 0x571370U, 0xE889C1U, 0xA2BA0EU, 0xFB635FU, 0xF070E0U, 0xA9CF39U,
|
||||
0x821DDAU, 0xD904C7U, 0x90F734U, 0x82FCE9U, 0xCB4D72U, 0xD09716U, 0x3B848DU, 0x623D78U, 0x696EA3U, 0x30F4BEU,
|
||||
0x7A075DU, 0x451E80U, 0x0C8D33U, 0x17E66EU, 0x5E76B5U, 0x050D14U, 0x0E9ECBU, 0x7607BAU, 0xF57524U, 0xACEAC5U,
|
||||
0xE7F91AU, 0xFC0083U, 0x9583F4U, 0xCED96DU, 0xC6688AU, 0x9D7353U, 0x92804CU, 0xCB11BDU, 0xA00B62U, 0xA9F8C3U,
|
||||
0x72E398U, 0x783244U, 0x2118F7U, 0x4A8B2AU, 0x5B5249U, 0x1061D4U, 0x09FA2FU, 0x428ABAU, 0x1911F1U, 0x31C604U,
|
||||
0x6AFD9FU, 0x276D62U, 0xBC2631U, 0xF795B8U, 0xCE4C4EU, 0x855F97U, 0xDDE520U, 0xD6B479U, 0x8D0FB6U, 0x8C1C07U,
|
||||
0xF7C6D8U, 0xBE77A9U, 0xA53C36U, 0xEFAFDFU, 0x369648U, 0x1D4411U, 0x40DFE6U, 0x4BEE7EU, 0x103595U, 0x5902C0U,
|
||||
0x43D85BU, 0x2AC9AEU, 0x316265U, 0x7AB158U, 0x23A18BU, 0x201A56U, 0xD949E5U, 0x93F2A8U, 0x882313U, 0xC139C6U,
|
||||
0xDA8A3CU, 0x97D329U, 0xEC50E2U, 0xE7AA13U, 0xBFBB8CU, 0xB42075U, 0xED5322U, 0x06C8ABU, 0x1DF85CU, 0x542785U,
|
||||
0x0FB4BAU, 0x0FCD7BU, 0x544FA4U, 0x7F5414U, 0x26A54BU, 0x6D3EF2U, 0x702D31U, 0x3BD7CCU, 0x13C6DFU, 0xC83D02U,
|
||||
0x83AEF9U, 0x9AB77CU, 0xD15507U, 0xC84ED2U, 0xA3DF49U, 0xF9A4BDU, 0xF836F6U, 0xA3ED4BU, 0xEADC98U, 0xD14B05U,
|
||||
0x9A30E6U, 0x03A0BFU, 0x4D6B00U, 0x1458D1U, 0x1FC12EU, 0x64932FU, 0x6D28F0U, 0x36BB09U, 0x7FE29FU, 0x6551E6U,
|
||||
0x0E0B21U, 0x57AAB8U, 0x54B147U, 0x8D6216U, 0x86DBA9U, 0xDDC968U, 0xB412F3U, 0xAA218EU, 0xE3FC5DU, 0xF86EF0U,
|
||||
0xB35523U, 0xCA945FU, 0xC1AFCCU, 0x983C11U, 0xD264FAU, 0x49D7EFU, 0x000C14U, 0x3B1FC1U, 0x7AA75AU, 0x21F4B7U,
|
||||
0x2A6FA4U, 0x728E5DU, 0x5D958AU, 0x042713U, 0x4F767DU, 0x54EDACU, 0x1D5E13U, 0x8604C0U, 0xEE91ADU, 0xB5EA36U,
|
||||
0xBC79E3U, 0xE77018U, 0xAC820DU, 0x9D19E6U, 0xD6283FU, 0xCEF3A8U, 0x85E0D1U, 0xDA1A47U, 0x538BAEU, 0x389079U,
|
||||
0x216360U, 0x6A6B9FU, 0x30D84EU, 0x3903E1U, 0x421230U, 0x0BE94FU, 0x10FBD6U, 0x5B6011U, 0x4215E8U, 0x008EFBU,
|
||||
0xF95C07U, 0xF2759CU, 0xADE659U, 0xA49D22U, 0xFF0CB7U, 0x96964CU, 0x8CE591U, 0xC77E92U, 0x9E2F6FU, 0x959CBCU,
|
||||
0xCC0601U, 0xE7475AU, 0x3CFCBFU, 0x74EF25U, 0x6717F4U, 0x2E048BU, 0x15DF0AU, 0x5A6CF5U, 0x03716CU, 0x08A33BU,
|
||||
0x5098C2U, 0x5B1945U, 0x20C2BCU, 0x69F063U, 0xF22972U, 0xBB1A8DU, 0xE0814DU, 0xCA52F6U, 0x936AABU, 0x98B958U,
|
||||
0xC9A2C5U, 0x820306U, 0x9B593BU, 0xF4CAE0U, 0xEE7315U, 0xA7209EU, 0x7C9BCBU, 0x75C930U, 0x0E54A4U, 0x45E75FU,
|
||||
0x5CBC12U, 0x173D81U, 0x0F0778U, 0x44D4AFU, 0x3FC596U, 0x363E59U, 0x65ACE8U, 0x6C9737U, 0xA346E6U, 0xD95DD9U,
|
||||
0xD0FE10U, 0x8B26E6U, 0xC2357FU, 0xD9CE28U, 0x92DDC1U, 0xAB455EU, 0xE1B6AFU, 0xB8ADF4U, 0xB35861U, 0x68438AU,
|
||||
0x41C157U, 0x12B864U, 0x5B2BB9U, 0x45B00AU, 0x0EC3C6U, 0x175B95U, 0x7C2828U, 0x25B3F3U, 0x2E2206U, 0x75580DU,
|
||||
0x3DDBD8U, 0x86C223U, 0xCF31BAU, 0xD4AADDU, 0x9FF804U, 0xC64193U, 0xCD526AU, 0xBDA9F4U, 0xB2BD95U, 0xE92E4AU,
|
||||
0xA0C5FBU, 0xBBD424U, 0xD20F7DU, 0x093DDAU, 0x01A603U, 0x5A77F0U, 0x514CEDU, 0x089E36U, 0x63A7D3U, 0x7A3448U,
|
||||
0x31FF3CU, 0x2BCEE7U, 0x625462U, 0x150799U, 0x1CBC84U, 0xC7ED77U, 0x8C76AAU, 0x95C409U, 0xDF9954U, 0xE62A8FU,
|
||||
0xAD213EU, 0xF6F1E1U, 0xFF4A00U, 0xA4191EU, 0x8D82C7U, 0xD7B330U, 0x9C69A9U, 0x057ACEU, 0x42C357U, 0x2B1088U,
|
||||
0x303A79U, 0x7BEB76U, 0x63F087U, 0x284358U, 0x7198E1U, 0x5A88B2U, 0x017B7EU, 0x0860CDU, 0x53F510U, 0x9A0F63U,
|
||||
0xA00CFEU, 0xEBB535U, 0xF2E6C0U, 0xB97DDBU, 0xEC0F2EU, 0xE796B5U, 0x9C0578U, 0xD47E0BU, 0xCFEF92U, 0x86F564U,
|
||||
0x1D16ADU, 0x768F32U, 0x2FFC43U, 0x24669CU, 0x7C752DU, 0x778CE2U, 0x2E1F9BU, 0x45000CU, 0x5EF0D5U, 0x13FB62U,
|
||||
0x40282BU, 0x4811D4U, 0xB38344U, 0xB8789FU, 0xE16BEAU, 0xAAB261U, 0xB38194U, 0xF81B4FU, 0xC2CA52U, 0x8BE1B1U,
|
||||
0xD0726CU, 0xD903DFU, 0x829982U, 0xE94A79U, 0x7471FDU, 0x36E026U, 0x2FBA93U, 0x640DC8U, 0x3F1431U, 0x16D7B6U,
|
||||
0x4D6C6FU, 0x443C18U, 0x1E8781U, 0x55947EU, 0x6C4FBFU, 0x27FFA0U, 0xBEE451U, 0xF5378FU, 0xAE0E2EU, 0xA2CD71U,
|
||||
0xC9D7C8U, 0x98661FU, 0x93BDC6U, 0xC88EE5U, 0xC15438U, 0xBA45C3U, 0xF2FE56U, 0xE9290DU, 0x2230E8U, 0x3B9273U,
|
||||
0x70C98FU, 0x0958DCU, 0x02A343U, 0x58B0A2U, 0x150A7DU, 0x0E5BC4U, 0x6FC897U, 0x74F33AU, 0x3F23E9U, 0x66A834U,
|
||||
0xECDB0FU, 0xB542DAU, 0x9E5131U, 0xC7ABA5U, 0x8C38FEU, 0x97010BU, 0xDED290U, 0xA4CC7DU, 0xAD3D2EU, 0xF6B6B3U,
|
||||
0xF9A540U, 0x205ED9U, 0x634EB6U, 0x5A9567U, 0x11A6D8U, 0x0B3F09U };
|
||||
|
||||
const unsigned int A_TABLE[] = { 0U, 4U, 8U, 12U, 16U, 20U, 24U, 28U, 32U, 36U, 40U, 44U,
|
||||
48U, 52U, 56U, 60U, 64U, 68U, 1U, 5U, 9U, 13U, 17U, 21U };
|
||||
const unsigned int B_TABLE[] = { 25U, 29U, 33U, 37U, 41U, 45U, 49U, 53U, 57U, 61U, 65U, 69U,
|
||||
2U, 6U, 10U, 14U, 18U, 22U, 26U, 30U, 34U, 38U, 42U };
|
||||
const unsigned int C_TABLE[] = { 46U, 50U, 54U, 58U, 62U, 66U, 70U, 3U, 7U, 11U, 15U, 19U,
|
||||
23U, 27U, 31U, 35U, 39U, 43U, 47U, 51U, 55U, 59U, 63U, 67U, 71U };
|
||||
|
||||
CNXDNAudio::CNXDNAudio()
|
||||
{
|
||||
}
|
||||
|
||||
CNXDNAudio::~CNXDNAudio()
|
||||
{
|
||||
}
|
||||
|
||||
void CNXDNAudio::decode(const unsigned char* in, unsigned char* out) const
|
||||
{
|
||||
assert(in != NULL);
|
||||
assert(out != NULL);
|
||||
|
||||
decode(in + 0U, out, 0U);
|
||||
decode(in + 9U, out, 49U);
|
||||
}
|
||||
|
||||
void CNXDNAudio::encode(const unsigned char* in, unsigned char* out) const
|
||||
{
|
||||
assert(in != NULL);
|
||||
assert(out != NULL);
|
||||
|
||||
encode(in, out + 0U, 0U);
|
||||
encode(in, out + 9U, 49U);
|
||||
}
|
||||
|
||||
void CNXDNAudio::decode(const unsigned char* in, unsigned char* out, unsigned int offset) const
|
||||
{
|
||||
assert(in != NULL);
|
||||
assert(out != NULL);
|
||||
|
||||
unsigned int a = 0U;
|
||||
unsigned int MASK = 0x800000U;
|
||||
for (unsigned int i = 0U; i < 24U; i++, MASK >>= 1) {
|
||||
unsigned int aPos = A_TABLE[i];
|
||||
if (READ_BIT(in, aPos))
|
||||
a |= MASK;
|
||||
}
|
||||
|
||||
unsigned int b = 0U;
|
||||
MASK = 0x400000U;
|
||||
for (unsigned int i = 0U; i < 23U; i++, MASK >>= 1) {
|
||||
unsigned int bPos = B_TABLE[i];
|
||||
if (READ_BIT(in, bPos))
|
||||
b |= MASK;
|
||||
}
|
||||
|
||||
unsigned int c = 0U;
|
||||
MASK = 0x1000000U;
|
||||
for (unsigned int i = 0U; i < 25U; i++, MASK >>= 1) {
|
||||
unsigned int cPos = C_TABLE[i];
|
||||
if (READ_BIT(in, cPos))
|
||||
c |= MASK;
|
||||
}
|
||||
|
||||
a >>= 12;
|
||||
|
||||
// The PRNG
|
||||
b ^= (PRNG_TABLE[a] >> 1);
|
||||
b >>= 11;
|
||||
|
||||
MASK = 0x000800U;
|
||||
for (unsigned int i = 0U; i < 12U; i++, MASK >>= 1) {
|
||||
unsigned int aPos = i + offset + 0U;
|
||||
unsigned int bPos = i + offset + 12U;
|
||||
WRITE_BIT(out, aPos, a & MASK);
|
||||
WRITE_BIT(out, bPos, b & MASK);
|
||||
}
|
||||
|
||||
MASK = 0x1000000U;
|
||||
for (unsigned int i = 0U; i < 25U; i++, MASK >>= 1) {
|
||||
unsigned int cPos = i + offset + 24U;
|
||||
WRITE_BIT(out, cPos, c & MASK);
|
||||
}
|
||||
}
|
||||
|
||||
void CNXDNAudio::encode(const unsigned char* in, unsigned char* out, unsigned int offset) const
|
||||
{
|
||||
assert(in != NULL);
|
||||
assert(out != NULL);
|
||||
|
||||
unsigned int aOrig = 0U;
|
||||
unsigned int bOrig = 0U;
|
||||
unsigned int cOrig = 0U;
|
||||
|
||||
unsigned int MASK = 0x000800U;
|
||||
for (unsigned int i = 0U; i < 12U; i++, MASK >>= 1) {
|
||||
unsigned int n1 = i + offset + 0U;
|
||||
unsigned int n2 = i + offset + 12U;
|
||||
if (READ_BIT(in, n1))
|
||||
aOrig |= MASK;
|
||||
if (READ_BIT(in, n2))
|
||||
bOrig |= MASK;
|
||||
}
|
||||
|
||||
MASK = 0x1000000U;
|
||||
for (unsigned int i = 0U; i < 25U; i++, MASK >>= 1) {
|
||||
unsigned int n = i + offset + 24U;
|
||||
if (READ_BIT(in, n))
|
||||
cOrig |= MASK;
|
||||
}
|
||||
|
||||
unsigned int a = CGolay24128::encode24128(aOrig);
|
||||
|
||||
// The PRNG
|
||||
unsigned int p = PRNG_TABLE[aOrig] >> 1;
|
||||
|
||||
unsigned int b = CGolay24128::encode23127(bOrig) >> 1;
|
||||
b ^= p;
|
||||
|
||||
MASK = 0x800000U;
|
||||
for (unsigned int i = 0U; i < 24U; i++, MASK >>= 1) {
|
||||
unsigned int aPos = A_TABLE[i];
|
||||
WRITE_BIT(out, aPos, a & MASK);
|
||||
}
|
||||
|
||||
MASK = 0x400000U;
|
||||
for (unsigned int i = 0U; i < 23U; i++, MASK >>= 1) {
|
||||
unsigned int bPos = B_TABLE[i];
|
||||
WRITE_BIT(out, bPos, b & MASK);
|
||||
}
|
||||
|
||||
MASK = 0x1000000U;
|
||||
for (unsigned int i = 0U; i < 25U; i++, MASK >>= 1) {
|
||||
unsigned int cPos = C_TABLE[i];
|
||||
WRITE_BIT(out, cPos, cOrig & MASK);
|
||||
}
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2016,2021 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2018 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
@ -16,8 +16,22 @@
|
|||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include "ModemPort.h"
|
||||
#if !defined(NXDNAudio_H)
|
||||
#define NXDNAudio_H
|
||||
|
||||
IModemPort::~IModemPort()
|
||||
{
|
||||
}
|
||||
class CNXDNAudio {
|
||||
public:
|
||||
CNXDNAudio();
|
||||
~CNXDNAudio();
|
||||
|
||||
void encode(const unsigned char* in, unsigned char* out) const;
|
||||
|
||||
void decode(const unsigned char* in, unsigned char* out) const;
|
||||
|
||||
private:
|
||||
void encode(const unsigned char* in, unsigned char* out, unsigned int offset) const;
|
||||
|
||||
void decode(const unsigned char* in, unsigned char* out, unsigned int offset) const;
|
||||
};
|
||||
|
||||
#endif
|
185
NXDNCRC.cpp
Normal file
185
NXDNCRC.cpp
Normal file
|
@ -0,0 +1,185 @@
|
|||
/*
|
||||
* Copyright (C) 2018 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* 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 "NXDNCRC.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <cassert>
|
||||
|
||||
const uint8_t BIT_MASK_TABLE1[] = { 0x80U, 0x40U, 0x20U, 0x10U, 0x08U, 0x04U, 0x02U, 0x01U };
|
||||
|
||||
#define WRITE_BIT1(p,i,b) p[(i)>>3] = (b) ? (p[(i)>>3] | BIT_MASK_TABLE1[(i)&7]) : (p[(i)>>3] & ~BIT_MASK_TABLE1[(i)&7])
|
||||
#define READ_BIT1(p,i) (p[(i)>>3] & BIT_MASK_TABLE1[(i)&7])
|
||||
|
||||
bool CNXDNCRC::checkCRC6(const unsigned char* in, unsigned int length)
|
||||
{
|
||||
assert(in != NULL);
|
||||
|
||||
uint8_t crc = createCRC6(in, length);
|
||||
|
||||
uint8_t temp[1U];
|
||||
temp[0U] = 0x00U;
|
||||
unsigned int j = length;
|
||||
for (unsigned int i = 2U; i < 8U; i++, j++) {
|
||||
bool b = READ_BIT1(in, j);
|
||||
WRITE_BIT1(temp, i, b);
|
||||
}
|
||||
|
||||
return crc == temp[0U];
|
||||
}
|
||||
|
||||
void CNXDNCRC::encodeCRC6(unsigned char* in, unsigned int length)
|
||||
{
|
||||
assert(in != NULL);
|
||||
|
||||
uint8_t crc[1U];
|
||||
crc[0U] = createCRC6(in, length);
|
||||
|
||||
unsigned int n = length;
|
||||
for (unsigned int i = 2U; i < 8U; i++, n++) {
|
||||
bool b = READ_BIT1(crc, i);
|
||||
WRITE_BIT1(in, n, b);
|
||||
}
|
||||
}
|
||||
|
||||
bool CNXDNCRC::checkCRC12(const unsigned char* in, unsigned int length)
|
||||
{
|
||||
assert(in != NULL);
|
||||
|
||||
uint16_t crc = createCRC12(in, length);
|
||||
uint8_t temp1[2U];
|
||||
temp1[0U] = (crc >> 8) & 0xFFU;
|
||||
temp1[1U] = (crc >> 0) & 0xFFU;
|
||||
|
||||
uint8_t temp2[2U];
|
||||
temp2[0U] = 0x00U;
|
||||
temp2[1U] = 0x00U;
|
||||
unsigned int j = length;
|
||||
for (unsigned int i = 4U; i < 16U; i++, j++) {
|
||||
bool b = READ_BIT1(in, j);
|
||||
WRITE_BIT1(temp2, i, b);
|
||||
}
|
||||
|
||||
return temp1[0U] == temp2[0U] && temp1[1U] == temp2[1U];
|
||||
}
|
||||
|
||||
void CNXDNCRC::encodeCRC12(unsigned char* in, unsigned int length)
|
||||
{
|
||||
assert(in != NULL);
|
||||
|
||||
uint16_t crc = createCRC12(in, length);
|
||||
|
||||
uint8_t temp[2U];
|
||||
temp[0U] = (crc >> 8) & 0xFFU;
|
||||
temp[1U] = (crc >> 0) & 0xFFU;
|
||||
|
||||
unsigned int n = length;
|
||||
for (unsigned int i = 4U; i < 16U; i++, n++) {
|
||||
bool b = READ_BIT1(temp, i);
|
||||
WRITE_BIT1(in, n, b);
|
||||
}
|
||||
}
|
||||
|
||||
bool CNXDNCRC::checkCRC15(const unsigned char* in, unsigned int length)
|
||||
{
|
||||
assert(in != NULL);
|
||||
|
||||
uint16_t crc = createCRC15(in, length);
|
||||
uint8_t temp1[2U];
|
||||
temp1[0U] = (crc >> 8) & 0xFFU;
|
||||
temp1[1U] = (crc >> 0) & 0xFFU;
|
||||
|
||||
uint8_t temp2[2U];
|
||||
temp2[0U] = 0x00U;
|
||||
temp2[1U] = 0x00U;
|
||||
unsigned int j = length;
|
||||
for (unsigned int i = 1U; i < 16U; i++, j++) {
|
||||
bool b = READ_BIT1(in, j);
|
||||
WRITE_BIT1(temp2, i, b);
|
||||
}
|
||||
|
||||
return temp1[0U] == temp2[0U] && temp1[1U] == temp2[1U];
|
||||
}
|
||||
|
||||
void CNXDNCRC::encodeCRC15(unsigned char* in, unsigned int length)
|
||||
{
|
||||
assert(in != NULL);
|
||||
|
||||
uint16_t crc = createCRC15(in, length);
|
||||
|
||||
uint8_t temp[2U];
|
||||
temp[0U] = (crc >> 8) & 0xFFU;
|
||||
temp[1U] = (crc >> 0) & 0xFFU;
|
||||
|
||||
unsigned int n = length;
|
||||
for (unsigned int i = 1U; i < 16U; i++, n++) {
|
||||
bool b = READ_BIT1(temp, i);
|
||||
WRITE_BIT1(in, n, b);
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t CNXDNCRC::createCRC6(const unsigned char* in, unsigned int length)
|
||||
{
|
||||
uint8_t crc = 0x3FU;
|
||||
|
||||
for (unsigned int i = 0U; i < length; i++) {
|
||||
bool bit1 = READ_BIT1(in, i) != 0x00U;
|
||||
bool bit2 = (crc & 0x20U) == 0x20U;
|
||||
|
||||
crc <<= 1;
|
||||
|
||||
if (bit1 ^ bit2)
|
||||
crc ^= 0x27U;
|
||||
}
|
||||
|
||||
return crc & 0x3FU;
|
||||
}
|
||||
|
||||
uint16_t CNXDNCRC::createCRC12(const unsigned char* in, unsigned int length)
|
||||
{
|
||||
uint16_t crc = 0x0FFFU;
|
||||
|
||||
for (unsigned int i = 0U; i < length; i++) {
|
||||
bool bit1 = READ_BIT1(in, i) != 0x00U;
|
||||
bool bit2 = (crc & 0x0800U) == 0x0800U;
|
||||
|
||||
crc <<= 1;
|
||||
|
||||
if (bit1 ^ bit2)
|
||||
crc ^= 0x080FU;
|
||||
}
|
||||
|
||||
return crc & 0x0FFFU;
|
||||
}
|
||||
|
||||
uint16_t CNXDNCRC::createCRC15(const unsigned char* in, unsigned int length)
|
||||
{
|
||||
uint16_t crc = 0x7FFFU;
|
||||
|
||||
for (unsigned int i = 0U; i < length; i++) {
|
||||
bool bit1 = READ_BIT1(in, i) != 0x00U;
|
||||
bool bit2 = (crc & 0x4000U) == 0x4000U;
|
||||
|
||||
crc <<= 1;
|
||||
|
||||
if (bit1 ^ bit2)
|
||||
crc ^= 0x4CC5U;
|
||||
}
|
||||
|
||||
return crc & 0x7FFFU;
|
||||
}
|
42
NXDNCRC.h
Normal file
42
NXDNCRC.h
Normal file
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* Copyright (C) 2018 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* 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(NXDNCRC_H)
|
||||
#define NXDNCRC_H
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
class CNXDNCRC
|
||||
{
|
||||
public:
|
||||
static bool checkCRC6(const unsigned char* in, unsigned int length);
|
||||
static void encodeCRC6(unsigned char* in, unsigned int length);
|
||||
|
||||
static bool checkCRC12(const unsigned char* in, unsigned int length);
|
||||
static void encodeCRC12(unsigned char* in, unsigned int length);
|
||||
|
||||
static bool checkCRC15(const unsigned char* in, unsigned int length);
|
||||
static void encodeCRC15(unsigned char* in, unsigned int length);
|
||||
|
||||
private:
|
||||
static uint8_t createCRC6(const unsigned char* in, unsigned int length);
|
||||
static uint16_t createCRC12(const unsigned char* in, unsigned int length);
|
||||
static uint16_t createCRC15(const unsigned char* in, unsigned int length);
|
||||
};
|
||||
|
||||
#endif
|
1122
NXDNControl.cpp
Normal file
1122
NXDNControl.cpp
Normal file
File diff suppressed because it is too large
Load diff
105
NXDNControl.h
Normal file
105
NXDNControl.h
Normal file
|
@ -0,0 +1,105 @@
|
|||
/*
|
||||
* Copyright (C) 2015-2019 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* 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(NXDNControl_H)
|
||||
#define NXDNControl_H
|
||||
|
||||
#include "RSSIInterpolator.h"
|
||||
#include "NXDNNetwork.h"
|
||||
#include "NXDNDefines.h"
|
||||
#include "NXDNLayer3.h"
|
||||
#include "NXDNLookup.h"
|
||||
#include "RingBuffer.h"
|
||||
#include "StopWatch.h"
|
||||
#include "NXDNLICH.h"
|
||||
#include "Display.h"
|
||||
#include "Defines.h"
|
||||
#include "Timer.h"
|
||||
#include "Modem.h"
|
||||
|
||||
#include <string>
|
||||
|
||||
class CNXDNControl {
|
||||
public:
|
||||
CNXDNControl(unsigned int ran, unsigned int id, bool selfOnly, CNXDNNetwork* network, CDisplay* display, unsigned int timeout, bool duplex, bool remoteGateway, CNXDNLookup* lookup, CRSSIInterpolator* rssiMapper);
|
||||
~CNXDNControl();
|
||||
|
||||
bool writeModem(unsigned char* data, unsigned int len);
|
||||
|
||||
unsigned int readModem(unsigned char* data);
|
||||
|
||||
void clock(unsigned int ms);
|
||||
|
||||
bool isBusy() const;
|
||||
|
||||
void enable(bool enabled);
|
||||
|
||||
private:
|
||||
unsigned int m_ran;
|
||||
unsigned int m_id;
|
||||
bool m_selfOnly;
|
||||
CNXDNNetwork* m_network;
|
||||
CDisplay* m_display;
|
||||
bool m_duplex;
|
||||
bool m_remoteGateway;
|
||||
CNXDNLookup* m_lookup;
|
||||
CRingBuffer<unsigned char> m_queue;
|
||||
RPT_RF_STATE m_rfState;
|
||||
RPT_NET_STATE m_netState;
|
||||
CTimer m_rfTimeoutTimer;
|
||||
CTimer m_netTimeoutTimer;
|
||||
CTimer m_packetTimer;
|
||||
CTimer m_networkWatchdog;
|
||||
CStopWatch m_elapsed;
|
||||
unsigned int m_rfFrames;
|
||||
unsigned int m_netFrames;
|
||||
unsigned int m_rfErrs;
|
||||
unsigned int m_rfBits;
|
||||
CNXDNLICH m_rfLastLICH;
|
||||
CNXDNLayer3 m_rfLayer3;
|
||||
CNXDNLayer3 m_netLayer3;
|
||||
unsigned char m_rfMask;
|
||||
unsigned char m_netMask;
|
||||
CRSSIInterpolator* m_rssiMapper;
|
||||
unsigned char m_rssi;
|
||||
unsigned char m_maxRSSI;
|
||||
unsigned char m_minRSSI;
|
||||
unsigned int m_aveRSSI;
|
||||
unsigned int m_rssiCount;
|
||||
bool m_enabled;
|
||||
FILE* m_fp;
|
||||
|
||||
bool processVoice(unsigned char usc, unsigned char option, unsigned char *data);
|
||||
bool processData(unsigned char option, unsigned char *data);
|
||||
|
||||
void writeQueueRF(const unsigned char* data);
|
||||
void writeQueueNet(const unsigned char* data);
|
||||
void writeNetwork(const unsigned char* data, NXDN_NETWORK_MESSAGE_TYPE type);
|
||||
void writeNetwork();
|
||||
|
||||
void scrambler(unsigned char* data) const;
|
||||
|
||||
void writeEndRF();
|
||||
void writeEndNet();
|
||||
|
||||
bool openFile();
|
||||
bool writeFile(const unsigned char* data);
|
||||
void closeFile();
|
||||
};
|
||||
|
||||
#endif
|
142
NXDNConvolution.cpp
Normal file
142
NXDNConvolution.cpp
Normal file
|
@ -0,0 +1,142 @@
|
|||
/*
|
||||
* Copyright (C) 2009-2016,2018 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* 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 "NXDNConvolution.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
#include <cstdlib>
|
||||
|
||||
const unsigned char BIT_MASK_TABLE[] = {0x80U, 0x40U, 0x20U, 0x10U, 0x08U, 0x04U, 0x02U, 0x01U};
|
||||
|
||||
#define WRITE_BIT1(p,i,b) p[(i)>>3] = (b) ? (p[(i)>>3] | BIT_MASK_TABLE[(i)&7]) : (p[(i)>>3] & ~BIT_MASK_TABLE[(i)&7])
|
||||
#define READ_BIT1(p,i) (p[(i)>>3] & BIT_MASK_TABLE[(i)&7])
|
||||
|
||||
const uint8_t BRANCH_TABLE1[] = {0U, 0U, 0U, 0U, 2U, 2U, 2U, 2U};
|
||||
const uint8_t BRANCH_TABLE2[] = {0U, 2U, 2U, 0U, 0U, 2U, 2U, 0U};
|
||||
|
||||
const unsigned int NUM_OF_STATES_D2 = 8U;
|
||||
const unsigned int NUM_OF_STATES = 16U;
|
||||
const uint32_t M = 4U;
|
||||
const unsigned int K = 5U;
|
||||
|
||||
CNXDNConvolution::CNXDNConvolution() :
|
||||
m_metrics1(NULL),
|
||||
m_metrics2(NULL),
|
||||
m_oldMetrics(NULL),
|
||||
m_newMetrics(NULL),
|
||||
m_decisions(NULL),
|
||||
m_dp(NULL)
|
||||
{
|
||||
m_metrics1 = new uint16_t[16U];
|
||||
m_metrics2 = new uint16_t[16U];
|
||||
m_decisions = new uint64_t[300U];
|
||||
}
|
||||
|
||||
CNXDNConvolution::~CNXDNConvolution()
|
||||
{
|
||||
delete[] m_metrics1;
|
||||
delete[] m_metrics2;
|
||||
delete[] m_decisions;
|
||||
}
|
||||
|
||||
void CNXDNConvolution::start()
|
||||
{
|
||||
::memset(m_metrics1, 0x00U, NUM_OF_STATES * sizeof(uint16_t));
|
||||
::memset(m_metrics2, 0x00U, NUM_OF_STATES * sizeof(uint16_t));
|
||||
|
||||
m_oldMetrics = m_metrics1;
|
||||
m_newMetrics = m_metrics2;
|
||||
m_dp = m_decisions;
|
||||
}
|
||||
|
||||
void CNXDNConvolution::decode(uint8_t s0, uint8_t s1)
|
||||
{
|
||||
*m_dp = 0U;
|
||||
|
||||
for (uint8_t i = 0U; i < NUM_OF_STATES_D2; i++) {
|
||||
uint8_t j = i * 2U;
|
||||
|
||||
uint16_t metric = std::abs(BRANCH_TABLE1[i] - s0) + std::abs(BRANCH_TABLE2[i] - s1);
|
||||
|
||||
uint16_t m0 = m_oldMetrics[i] + metric;
|
||||
uint16_t m1 = m_oldMetrics[i + NUM_OF_STATES_D2] + (M - metric);
|
||||
uint8_t decision0 = (m0 >= m1) ? 1U : 0U;
|
||||
m_newMetrics[j + 0U] = decision0 != 0U ? m1 : m0;
|
||||
|
||||
m0 = m_oldMetrics[i] + (M - metric);
|
||||
m1 = m_oldMetrics[i + NUM_OF_STATES_D2] + metric;
|
||||
uint8_t decision1 = (m0 >= m1) ? 1U : 0U;
|
||||
m_newMetrics[j + 1U] = decision1 != 0U ? m1 : m0;
|
||||
|
||||
*m_dp |= (uint64_t(decision1) << (j + 1U)) | (uint64_t(decision0) << (j + 0U));
|
||||
}
|
||||
|
||||
++m_dp;
|
||||
|
||||
assert((m_dp - m_decisions) <= 300);
|
||||
|
||||
uint16_t* tmp = m_oldMetrics;
|
||||
m_oldMetrics = m_newMetrics;
|
||||
m_newMetrics = tmp;
|
||||
}
|
||||
|
||||
void CNXDNConvolution::chainback(unsigned char* out, unsigned int nBits)
|
||||
{
|
||||
assert(out != NULL);
|
||||
|
||||
uint32_t state = 0U;
|
||||
|
||||
while (nBits-- > 0) {
|
||||
--m_dp;
|
||||
|
||||
uint32_t i = state >> (9 - K);
|
||||
uint8_t bit = uint8_t(*m_dp >> i) & 1;
|
||||
state = (bit << 7) | (state >> 1);
|
||||
|
||||
WRITE_BIT1(out, nBits, bit != 0U);
|
||||
}
|
||||
}
|
||||
|
||||
void CNXDNConvolution::encode(const unsigned char* in, unsigned char* out, unsigned int nBits) const
|
||||
{
|
||||
assert(in != NULL);
|
||||
assert(out != NULL);
|
||||
assert(nBits > 0U);
|
||||
|
||||
uint8_t d1 = 0U, d2 = 0U, d3 = 0U, d4 = 0U;
|
||||
uint32_t k = 0U;
|
||||
for (unsigned int i = 0U; i < nBits; i++) {
|
||||
uint8_t d = READ_BIT1(in, i) ? 1U : 0U;
|
||||
|
||||
uint8_t g1 = (d + d3 + d4) & 1;
|
||||
uint8_t g2 = (d + d1 + d2 + d4) & 1;
|
||||
|
||||
d4 = d3;
|
||||
d3 = d2;
|
||||
d2 = d1;
|
||||
d1 = d;
|
||||
|
||||
WRITE_BIT1(out, k, g1 != 0U);
|
||||
k++;
|
||||
|
||||
WRITE_BIT1(out, k, g2 != 0U);
|
||||
k++;
|
||||
}
|
||||
}
|
|
@ -1,6 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2015-2021 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2021 by Geoffrey Merck F4FXL / KC3FRA
|
||||
* Copyright (C) 2015,2016,2018 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
@ -17,21 +16,30 @@
|
|||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#include "SMeter.h"
|
||||
#if !defined(NXDNConvolution_H)
|
||||
#define NXDNConvolution_H
|
||||
|
||||
const unsigned int RSSI_S1 = 141U;
|
||||
const unsigned int RSSI_S9 = 93U;
|
||||
#include <cstdint>
|
||||
|
||||
class CNXDNConvolution {
|
||||
public:
|
||||
CNXDNConvolution();
|
||||
~CNXDNConvolution();
|
||||
|
||||
void start();
|
||||
void decode(uint8_t s0, uint8_t s1);
|
||||
void chainback(unsigned char* out, unsigned int nBits);
|
||||
|
||||
void encode(const unsigned char* in, unsigned char* out, unsigned int nBits) const;
|
||||
|
||||
private:
|
||||
uint16_t* m_metrics1;
|
||||
uint16_t* m_metrics2;
|
||||
uint16_t* m_oldMetrics;
|
||||
uint16_t* m_newMetrics;
|
||||
uint64_t* m_decisions;
|
||||
uint64_t* m_dp;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
void CSMeter::getSignal(unsigned int rssi, unsigned int& signal, unsigned int& plus)
|
||||
{
|
||||
if (rssi > RSSI_S1) {
|
||||
signal = 0U;
|
||||
plus = rssi - RSSI_S1;
|
||||
} else if (rssi > RSSI_S9 && rssi <= RSSI_S1) {
|
||||
signal = ((RSSI_S1 - rssi) / 6U) + 1U;
|
||||
plus = (RSSI_S1 - rssi) % 6U;
|
||||
} else {
|
||||
signal = 9U;
|
||||
plus = RSSI_S9 - rssi;
|
||||
}
|
||||
}
|
102
NXDNDefines.h
Normal file
102
NXDNDefines.h
Normal file
|
@ -0,0 +1,102 @@
|
|||
/*
|
||||
* Copyright (C) 2016,2017,2018 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* 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(NXDNDEFINES_H)
|
||||
#define NXDNDEFINES_H
|
||||
|
||||
const unsigned int NXDN_RADIO_SYMBOL_LENGTH = 5U; // At 24 kHz sample rate
|
||||
|
||||
const unsigned int NXDN_FRAME_LENGTH_BITS = 384U;
|
||||
const unsigned int NXDN_FRAME_LENGTH_BYTES = NXDN_FRAME_LENGTH_BITS / 8U;
|
||||
const unsigned int NXDN_FRAME_LENGTH_SYMBOLS = NXDN_FRAME_LENGTH_BITS / 2U;
|
||||
|
||||
const unsigned int NXDN_FSW_LENGTH_BITS = 20U;
|
||||
const unsigned int NXDN_FSW_LENGTH_SYMBOLS = NXDN_FSW_LENGTH_BITS / 2U;
|
||||
const unsigned int NXDN_FSW_LENGTH_SAMPLES = NXDN_FSW_LENGTH_SYMBOLS * NXDN_RADIO_SYMBOL_LENGTH;
|
||||
|
||||
const unsigned char NXDN_FSW_BYTES[] = {0xCDU, 0xF5U, 0x90U};
|
||||
const unsigned char NXDN_FSW_BYTES_MASK[] = {0xFFU, 0xFFU, 0xF0U};
|
||||
const unsigned int NXDN_FSW_BYTES_LENGTH = 3U;
|
||||
|
||||
const unsigned int NXDN_LICH_LENGTH_BITS = 16U;
|
||||
|
||||
const unsigned int NXDN_SACCH_LENGTH_BITS = 60U;
|
||||
const unsigned int NXDN_FACCH1_LENGTH_BITS = 144U;
|
||||
const unsigned int NXDN_FACCH2_LENGTH_BITS = 348U;
|
||||
|
||||
const unsigned int NXDN_FSW_LICH_SACCH_LENGTH_BITS = NXDN_FSW_LENGTH_BITS + NXDN_LICH_LENGTH_BITS + NXDN_SACCH_LENGTH_BITS;
|
||||
const unsigned int NXDN_FSW_LICH_SACCH_LENGTH_BYTES = NXDN_FSW_LICH_SACCH_LENGTH_BITS / 8U;
|
||||
|
||||
const unsigned char NXDN_LICH_RFCT_RCCH = 0U;
|
||||
const unsigned char NXDN_LICH_RFCT_RTCH = 1U;
|
||||
const unsigned char NXDN_LICH_RFCT_RDCH = 2U;
|
||||
const unsigned char NXDN_LICH_RFCT_RTCH_C = 3U;
|
||||
|
||||
const unsigned char NXDN_LICH_USC_SACCH_NS = 0U;
|
||||
const unsigned char NXDN_LICH_USC_UDCH = 1U;
|
||||
const unsigned char NXDN_LICH_USC_SACCH_SS = 2U;
|
||||
const unsigned char NXDN_LICH_USC_SACCH_SS_IDLE = 3U;
|
||||
|
||||
const unsigned char NXDN_LICH_STEAL_NONE = 3U;
|
||||
const unsigned char NXDN_LICH_STEAL_FACCH1_2 = 2U;
|
||||
const unsigned char NXDN_LICH_STEAL_FACCH1_1 = 1U;
|
||||
const unsigned char NXDN_LICH_STEAL_FACCH = 0U;
|
||||
|
||||
const unsigned char NXDN_LICH_DIRECTION_INBOUND = 0U;
|
||||
const unsigned char NXDN_LICH_DIRECTION_OUTBOUND = 1U;
|
||||
|
||||
const unsigned char NXDN_SR_SINGLE = 0U;
|
||||
const unsigned char NXDN_SR_4_4 = 0U;
|
||||
const unsigned char NXDN_SR_3_4 = 1U;
|
||||
const unsigned char NXDN_SR_2_4 = 2U;
|
||||
const unsigned char NXDN_SR_1_4 = 3U;
|
||||
|
||||
const unsigned char NXDN_MESSAGE_TYPE_VCALL = 0x01U;
|
||||
const unsigned char NXDN_MESSAGE_TYPE_VCALL_IV = 0x03U;
|
||||
const unsigned char NXDN_MESSAGE_TYPE_DCALL_HDR = 0x09U;
|
||||
const unsigned char NXDN_MESSAGE_TYPE_DCALL_DATA = 0x0BU;
|
||||
const unsigned char NXDN_MESSAGE_TYPE_DCALL_ACK = 0x0CU;
|
||||
const unsigned char NXDN_MESSAGE_TYPE_TX_REL = 0x08U;
|
||||
const unsigned char NXDN_MESSAGE_TYPE_HEAD_DLY = 0x0FU;
|
||||
const unsigned char NXDN_MESSAGE_TYPE_SDCALL_REQ_HDR = 0x38U;
|
||||
const unsigned char NXDN_MESSAGE_TYPE_SDCALL_REQ_DATA = 0x39U;
|
||||
const unsigned char NXDN_MESSAGE_TYPE_SDCALL_RESP = 0x3BU;
|
||||
const unsigned char NXDN_MESSAGE_TYPE_SDCALL_IV = 0x3AU;
|
||||
const unsigned char NXDN_MESSAGE_TYPE_STAT_INQ_REQ = 0x30U;
|
||||
const unsigned char NXDN_MESSAGE_TYPE_STAT_INQ_RESP = 0x31U;
|
||||
const unsigned char NXDN_MESSAGE_TYPE_STAT_REQ = 0x32U;
|
||||
const unsigned char NXDN_MESSAGE_TYPE_STAT_RESP = 0x33U;
|
||||
const unsigned char NXDN_MESSAGE_TYPE_REM_CON_REQ = 0x34U;
|
||||
const unsigned char NXDN_MESSAGE_TYPE_REM_CON_RESP = 0x35U;
|
||||
const unsigned char NXDN_MESSAGE_TYPE_IDLE = 0x10U;
|
||||
const unsigned char NXDN_MESSAGE_TYPE_AUTH_INQ_REQ = 0x28U;
|
||||
const unsigned char NXDN_MESSAGE_TYPE_AUTH_INQ_RESP = 0x29U;
|
||||
const unsigned char NXDN_MESSAGE_TYPE_PROP_FORM = 0x3FU;
|
||||
|
||||
const unsigned char NXDN_VOICE_CALL_OPTION_HALF_DUPLEX = 0x00U;
|
||||
const unsigned char NXDN_VOICE_CALL_OPTION_DUPLEX = 0x10U;
|
||||
|
||||
const unsigned char NXDN_DATA_CALL_OPTION_HALF_DUPLEX = 0x00U;
|
||||
const unsigned char NXDN_DATA_CALL_OPTION_DUPLEX = 0x10U;
|
||||
|
||||
const unsigned char NXDN_DATA_CALL_OPTION_4800 = 0x00U;
|
||||
const unsigned char NXDN_DATA_CALL_OPTION_9600 = 0x02U;
|
||||
|
||||
const unsigned char SACCH_IDLE[] = { NXDN_MESSAGE_TYPE_IDLE, 0x00U, 0x00U };
|
||||
|
||||
#endif
|
188
NXDNFACCH1.cpp
Normal file
188
NXDNFACCH1.cpp
Normal file
|
@ -0,0 +1,188 @@
|
|||
/*
|
||||
* Copyright (C) 2018 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* 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 "NXDNFACCH1.h"
|
||||
|
||||
#include "NXDNConvolution.h"
|
||||
#include "NXDNDefines.h"
|
||||
#include "NXDNCRC.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
|
||||
const unsigned int INTERLEAVE_TABLE[] = {
|
||||
0U, 9U, 18U, 27U, 36U, 45U, 54U, 63U, 72U, 81U, 90U, 99U, 108U, 117U, 126U, 135U,
|
||||
1U, 10U, 19U, 28U, 37U, 46U, 55U, 64U, 73U, 82U, 91U, 100U, 109U, 118U, 127U, 136U,
|
||||
2U, 11U, 20U, 29U, 38U, 47U, 56U, 65U, 74U, 83U, 92U, 101U, 110U, 119U, 128U, 137U,
|
||||
3U, 12U, 21U, 30U, 39U, 48U, 57U, 66U, 75U, 84U, 93U, 102U, 111U, 120U, 129U, 138U,
|
||||
4U, 13U, 22U, 31U, 40U, 49U, 58U, 67U, 76U, 85U, 94U, 103U, 112U, 121U, 130U, 139U,
|
||||
5U, 14U, 23U, 32U, 41U, 50U, 59U, 68U, 77U, 86U, 95U, 104U, 113U, 122U, 131U, 140U,
|
||||
6U, 15U, 24U, 33U, 42U, 51U, 60U, 69U, 78U, 87U, 96U, 105U, 114U, 123U, 132U, 141U,
|
||||
7U, 16U, 25U, 34U, 43U, 52U, 61U, 70U, 79U, 88U, 97U, 106U, 115U, 124U, 133U, 142U,
|
||||
8U, 17U, 26U, 35U, 44U, 53U, 62U, 71U, 80U, 89U, 98U, 107U, 116U, 125U, 134U, 143U };
|
||||
|
||||
const unsigned int PUNCTURE_LIST[] = { 1U, 5U, 9U, 13U, 17U, 21U, 25U, 29U, 33U, 37U,
|
||||
41U, 45U, 49U, 53U, 57U, 61U, 65U, 69U, 73U, 77U,
|
||||
81U, 85U, 89U, 93U, 97U, 101U, 105U, 109U, 113U, 117U,
|
||||
121U, 125U, 129U, 133U, 137U, 141U, 145U, 149U, 153U, 157U,
|
||||
161U, 165U, 169U, 173U, 177U, 181U, 185U, 189U };
|
||||
|
||||
const unsigned char BIT_MASK_TABLE[] = { 0x80U, 0x40U, 0x20U, 0x10U, 0x08U, 0x04U, 0x02U, 0x01U };
|
||||
|
||||
#define WRITE_BIT1(p,i,b) p[(i)>>3] = (b) ? (p[(i)>>3] | BIT_MASK_TABLE[(i)&7]) : (p[(i)>>3] & ~BIT_MASK_TABLE[(i)&7])
|
||||
#define READ_BIT1(p,i) (p[(i)>>3] & BIT_MASK_TABLE[(i)&7])
|
||||
|
||||
CNXDNFACCH1::CNXDNFACCH1(const CNXDNFACCH1& facch1) :
|
||||
m_data(NULL)
|
||||
{
|
||||
m_data = new unsigned char[10U + 2U];
|
||||
::memcpy(m_data, facch1.m_data, 10U + 2U);
|
||||
}
|
||||
|
||||
CNXDNFACCH1::CNXDNFACCH1() :
|
||||
m_data(NULL)
|
||||
{
|
||||
m_data = new unsigned char[10U + 2U];
|
||||
}
|
||||
|
||||
CNXDNFACCH1::~CNXDNFACCH1()
|
||||
{
|
||||
delete[] m_data;
|
||||
}
|
||||
|
||||
bool CNXDNFACCH1::decode(const unsigned char* data, unsigned int offset)
|
||||
{
|
||||
assert(data != NULL);
|
||||
|
||||
unsigned char temp1[18U];
|
||||
|
||||
for (unsigned int i = 0U; i < NXDN_FACCH1_LENGTH_BITS; i++) {
|
||||
unsigned int n = INTERLEAVE_TABLE[i] + offset;
|
||||
bool b = READ_BIT1(data, n);
|
||||
WRITE_BIT1(temp1, i, b);
|
||||
}
|
||||
|
||||
uint8_t temp2[210U];
|
||||
|
||||
unsigned int n = 0U;
|
||||
unsigned int index = 0U;
|
||||
for (unsigned int i = 0U; i < NXDN_FACCH1_LENGTH_BITS; i++) {
|
||||
if (n == PUNCTURE_LIST[index]) {
|
||||
temp2[n++] = 1U;
|
||||
index++;
|
||||
}
|
||||
|
||||
bool b = READ_BIT1(temp1, i);
|
||||
temp2[n++] = b ? 2U : 0U;
|
||||
}
|
||||
|
||||
for (unsigned int i = 0U; i < 8U; i++) {
|
||||
temp2[n++] = 0U;
|
||||
}
|
||||
|
||||
CNXDNConvolution conv;
|
||||
conv.start();
|
||||
|
||||
n = 0U;
|
||||
for (unsigned int i = 0U; i < 100U; i++) {
|
||||
uint8_t s0 = temp2[n++];
|
||||
uint8_t s1 = temp2[n++];
|
||||
|
||||
conv.decode(s0, s1);
|
||||
}
|
||||
|
||||
conv.chainback(m_data, 96U);
|
||||
|
||||
return CNXDNCRC::checkCRC12(m_data, 80U);
|
||||
}
|
||||
|
||||
void CNXDNFACCH1::encode(unsigned char* data, unsigned int offset) const
|
||||
{
|
||||
assert(data != NULL);
|
||||
|
||||
unsigned char temp1[12U];
|
||||
::memset(temp1, 0x00U, 12U);
|
||||
::memcpy(temp1, m_data, 10U);
|
||||
|
||||
CNXDNCRC::encodeCRC12(temp1, 80U);
|
||||
|
||||
unsigned char temp2[24U];
|
||||
|
||||
CNXDNConvolution conv;
|
||||
conv.encode(temp1, temp2, 96U);
|
||||
|
||||
unsigned char temp3[18U];
|
||||
|
||||
unsigned int n = 0U;
|
||||
unsigned int index = 0U;
|
||||
for (unsigned int i = 0U; i < 192U; i++) {
|
||||
if (i != PUNCTURE_LIST[index]) {
|
||||
bool b = READ_BIT1(temp2, i);
|
||||
WRITE_BIT1(temp3, n, b);
|
||||
n++;
|
||||
} else {
|
||||
index++;
|
||||
}
|
||||
}
|
||||
|
||||
for (unsigned int i = 0U; i < NXDN_FACCH1_LENGTH_BITS; i++) {
|
||||
unsigned int n = INTERLEAVE_TABLE[i] + offset;
|
||||
bool b = READ_BIT1(temp3, i);
|
||||
WRITE_BIT1(data, n, b);
|
||||
}
|
||||
}
|
||||
|
||||
void CNXDNFACCH1::getData(unsigned char* data) const
|
||||
{
|
||||
assert(data != NULL);
|
||||
|
||||
::memcpy(data, m_data, 10U);
|
||||
}
|
||||
|
||||
void CNXDNFACCH1::getRaw(unsigned char* data) const
|
||||
{
|
||||
assert(data != NULL);
|
||||
|
||||
::memset(data, 0x00U, 12U);
|
||||
::memcpy(data, m_data, 10U);
|
||||
|
||||
CNXDNCRC::encodeCRC12(data, 80U);
|
||||
}
|
||||
|
||||
void CNXDNFACCH1::setData(const unsigned char* data)
|
||||
{
|
||||
assert(data != NULL);
|
||||
|
||||
::memcpy(m_data, data, 10U);
|
||||
}
|
||||
|
||||
void CNXDNFACCH1::setRaw(const unsigned char* data)
|
||||
{
|
||||
assert(data != NULL);
|
||||
|
||||
::memcpy(m_data, data, 12U);
|
||||
}
|
||||
|
||||
CNXDNFACCH1& CNXDNFACCH1::operator=(const CNXDNFACCH1& facch1)
|
||||
{
|
||||
if (&facch1 != this)
|
||||
::memcpy(m_data, facch1.m_data, 10U + 2U);
|
||||
|
||||
return *this;
|
||||
}
|
44
NXDNFACCH1.h
Normal file
44
NXDNFACCH1.h
Normal file
|
@ -0,0 +1,44 @@
|
|||
/*
|
||||
* Copyright (C) 2018 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* 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(NXDNFACCH1_H)
|
||||
#define NXDNFACCH1_H
|
||||
|
||||
class CNXDNFACCH1 {
|
||||
public:
|
||||
CNXDNFACCH1(const CNXDNFACCH1& facch);
|
||||
CNXDNFACCH1();
|
||||
~CNXDNFACCH1();
|
||||
|
||||
bool decode(const unsigned char* data, unsigned int offset);
|
||||
|
||||
void encode(unsigned char* data, unsigned int offset) const;
|
||||
|
||||
void getData(unsigned char* data) const;
|
||||
void getRaw(unsigned char* data) const;
|
||||
|
||||
void setData(const unsigned char* data);
|
||||
void setRaw(const unsigned char* data);
|
||||
|
||||
CNXDNFACCH1& operator=(const CNXDNFACCH1& facch);
|
||||
|
||||
private:
|
||||
unsigned char* m_data;
|
||||
};
|
||||
|
||||
#endif
|
162
NXDNLICH.cpp
Normal file
162
NXDNLICH.cpp
Normal file
|
@ -0,0 +1,162 @@
|
|||
/*
|
||||
* Copyright (C) 2018 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* 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 "NXDNDefines.h"
|
||||
#include "NXDNLICH.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
|
||||
const unsigned char BIT_MASK_TABLE[] = {0x80U, 0x40U, 0x20U, 0x10U, 0x08U, 0x04U, 0x02U, 0x01U};
|
||||
|
||||
#define WRITE_BIT1(p,i,b) p[(i)>>3] = (b) ? (p[(i)>>3] | BIT_MASK_TABLE[(i)&7]) : (p[(i)>>3] & ~BIT_MASK_TABLE[(i)&7])
|
||||
#define READ_BIT1(p,i) (p[(i)>>3] & BIT_MASK_TABLE[(i)&7])
|
||||
|
||||
CNXDNLICH::CNXDNLICH(const CNXDNLICH& lich) :
|
||||
m_lich(NULL)
|
||||
{
|
||||
m_lich = new unsigned char[1U];
|
||||
m_lich[0U] = lich.m_lich[0U];
|
||||
}
|
||||
|
||||
CNXDNLICH::CNXDNLICH() :
|
||||
m_lich(NULL)
|
||||
{
|
||||
m_lich = new unsigned char[1U];
|
||||
}
|
||||
|
||||
CNXDNLICH::~CNXDNLICH()
|
||||
{
|
||||
delete[] m_lich;
|
||||
}
|
||||
|
||||
bool CNXDNLICH::decode(const unsigned char* bytes)
|
||||
{
|
||||
assert(bytes != NULL);
|
||||
|
||||
unsigned int offset = NXDN_FSW_LENGTH_BITS;
|
||||
for (unsigned int i = 0U; i < (NXDN_LICH_LENGTH_BITS / 2U); i++, offset += 2U) {
|
||||
bool b = READ_BIT1(bytes, offset);
|
||||
WRITE_BIT1(m_lich, i, b);
|
||||
}
|
||||
|
||||
bool newParity = getParity();
|
||||
bool origParity = (m_lich[0U] & 0x01U) == 0x01U;
|
||||
|
||||
return origParity == newParity;
|
||||
}
|
||||
|
||||
void CNXDNLICH::encode(unsigned char* bytes)
|
||||
{
|
||||
assert(bytes != NULL);
|
||||
|
||||
bool parity = getParity();
|
||||
if (parity)
|
||||
m_lich[0U] |= 0x01U;
|
||||
else
|
||||
m_lich[0U] &= 0xFEU;
|
||||
|
||||
unsigned int offset = NXDN_FSW_LENGTH_BITS;
|
||||
for (unsigned int i = 0U; i < (NXDN_LICH_LENGTH_BITS / 2U); i++) {
|
||||
bool b = READ_BIT1(m_lich, i);
|
||||
WRITE_BIT1(bytes, offset, b);
|
||||
offset++;
|
||||
WRITE_BIT1(bytes, offset, true);
|
||||
offset++;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned char CNXDNLICH::getRFCT() const
|
||||
{
|
||||
return (m_lich[0U] >> 6) & 0x03U;
|
||||
}
|
||||
|
||||
unsigned char CNXDNLICH::getFCT() const
|
||||
{
|
||||
return (m_lich[0U] >> 4) & 0x03U;
|
||||
}
|
||||
|
||||
unsigned char CNXDNLICH::getOption() const
|
||||
{
|
||||
return (m_lich[0U] >> 2) & 0x03U;
|
||||
}
|
||||
|
||||
unsigned char CNXDNLICH::getDirection() const
|
||||
{
|
||||
return (m_lich[0U] >> 1) & 0x01U;
|
||||
}
|
||||
|
||||
unsigned char CNXDNLICH::getRaw() const
|
||||
{
|
||||
bool parity = getParity();
|
||||
if (parity)
|
||||
m_lich[0U] |= 0x01U;
|
||||
else
|
||||
m_lich[0U] &= 0xFEU;
|
||||
|
||||
return m_lich[0U];
|
||||
}
|
||||
|
||||
void CNXDNLICH::setRFCT(unsigned char rfct)
|
||||
{
|
||||
m_lich[0U] &= 0x3FU;
|
||||
m_lich[0U] |= (rfct << 6) & 0xC0U;
|
||||
}
|
||||
|
||||
void CNXDNLICH::setFCT(unsigned char usc)
|
||||
{
|
||||
m_lich[0U] &= 0xCFU;
|
||||
m_lich[0U] |= (usc << 4) & 0x30U;
|
||||
}
|
||||
|
||||
void CNXDNLICH::setOption(unsigned char option)
|
||||
{
|
||||
m_lich[0U] &= 0xF3U;
|
||||
m_lich[0U] |= (option << 2) & 0x0CU;
|
||||
}
|
||||
|
||||
void CNXDNLICH::setDirection(unsigned char direction)
|
||||
{
|
||||
m_lich[0U] &= 0xFDU;
|
||||
m_lich[0U] |= (direction << 1) & 0x02U;
|
||||
}
|
||||
|
||||
void CNXDNLICH::setRaw(unsigned char lich)
|
||||
{
|
||||
m_lich[0U] = lich;
|
||||
}
|
||||
|
||||
CNXDNLICH& CNXDNLICH::operator=(const CNXDNLICH& lich)
|
||||
{
|
||||
if (&lich != this)
|
||||
m_lich[0U] = lich.m_lich[0U];
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool CNXDNLICH::getParity() const
|
||||
{
|
||||
switch (m_lich[0U] & 0xF0U) {
|
||||
case 0x80U:
|
||||
case 0xB0U:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2020 by SASANO Takayoshi JG1UAA
|
||||
* Copyright (C) 2018 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
@ -16,28 +16,37 @@
|
|||
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
*/
|
||||
|
||||
#if !defined(USERDB_H)
|
||||
#define USERDB_H
|
||||
#if !defined(NXDNLICH_H)
|
||||
#define NXDNLICH_H
|
||||
|
||||
#include "UserDBentry.h"
|
||||
#include "Mutex.h"
|
||||
|
||||
class CUserDB {
|
||||
class CNXDNLICH {
|
||||
public:
|
||||
CUserDB();
|
||||
~CUserDB();
|
||||
CNXDNLICH(const CNXDNLICH& lich);
|
||||
CNXDNLICH();
|
||||
~CNXDNLICH();
|
||||
|
||||
bool lookup(unsigned int id, class CUserDBentry *entry);
|
||||
bool load(std::string const& filename);
|
||||
bool decode(const unsigned char* bytes);
|
||||
|
||||
void encode(unsigned char* bytes);
|
||||
|
||||
unsigned char getRFCT() const;
|
||||
unsigned char getFCT() const;
|
||||
unsigned char getOption() const;
|
||||
unsigned char getDirection() const;
|
||||
unsigned char getRaw() const;
|
||||
|
||||
void setRFCT(unsigned char rfct);
|
||||
void setFCT(unsigned char usc);
|
||||
void setOption(unsigned char option);
|
||||
void setDirection(unsigned char direction);
|
||||
void setRaw(unsigned char lich);
|
||||
|
||||
CNXDNLICH& operator=(const CNXDNLICH& lich);
|
||||
|
||||
private:
|
||||
bool makeindex(char* buf, std::unordered_map<std::string, int>& index);
|
||||
void parse(char* buf, std::unordered_map<std::string, int>& index);
|
||||
void toupper_string(char* str);
|
||||
char* tokenize(char* str, char** next);
|
||||
unsigned char* m_lich;
|
||||
|
||||
std::unordered_map<unsigned int, class CUserDBentry> m_table;
|
||||
CMutex m_mutex;
|
||||
bool getParity() const;
|
||||
};
|
||||
|
||||
|
||||
#endif
|
117
NXDNLayer3.cpp
Normal file
117
NXDNLayer3.cpp
Normal file
|
@ -0,0 +1,117 @@
|
|||
/*
|
||||
* Copyright (C) 2018 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* 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 "NXDNDefines.h"
|
||||
#include "NXDNLayer3.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
|
||||
const unsigned char BIT_MASK_TABLE[] = { 0x80U, 0x40U, 0x20U, 0x10U, 0x08U, 0x04U, 0x02U, 0x01U };
|
||||
|
||||
#define WRITE_BIT1(p,i,b) p[(i)>>3] = (b) ? (p[(i)>>3] | BIT_MASK_TABLE[(i)&7]) : (p[(i)>>3] & ~BIT_MASK_TABLE[(i)&7])
|
||||
#define READ_BIT1(p,i) (p[(i)>>3] & BIT_MASK_TABLE[(i)&7])
|
||||
|
||||
CNXDNLayer3::CNXDNLayer3(const CNXDNLayer3& layer3) :
|
||||
m_data(NULL)
|
||||
{
|
||||
m_data = new unsigned char[22U];
|
||||
::memcpy(m_data, layer3.m_data, 22U);
|
||||
}
|
||||
|
||||
CNXDNLayer3::CNXDNLayer3() :
|
||||
m_data(NULL)
|
||||
{
|
||||
m_data = new unsigned char[22U];
|
||||
::memset(m_data, 0x00U, 22U);
|
||||
}
|
||||
|
||||
CNXDNLayer3::~CNXDNLayer3()
|
||||
{
|
||||
delete[] m_data;
|
||||
}
|
||||
|
||||
void CNXDNLayer3::decode(const unsigned char* bytes, unsigned int length, unsigned int offset)
|
||||
{
|
||||
assert(bytes != NULL);
|
||||
|
||||
for (unsigned int i = 0U; i < length; i++, offset++) {
|
||||
bool b = READ_BIT1(bytes, i);
|
||||
WRITE_BIT1(m_data, offset, b);
|
||||
}
|
||||
}
|
||||
|
||||
void CNXDNLayer3::encode(unsigned char* bytes, unsigned int length, unsigned int offset)
|
||||
{
|
||||
assert(bytes != NULL);
|
||||
|
||||
for (unsigned int i = 0U; i < length; i++, offset++) {
|
||||
bool b = READ_BIT1(m_data, offset);
|
||||
WRITE_BIT1(bytes, i, b);
|
||||
}
|
||||
}
|
||||
|
||||
unsigned char CNXDNLayer3::getMessageType() const
|
||||
{
|
||||
return m_data[0U] & 0x3FU;
|
||||
}
|
||||
|
||||
unsigned short CNXDNLayer3::getSourceUnitId() const
|
||||
{
|
||||
return (m_data[3U] << 8) | m_data[4U];
|
||||
}
|
||||
|
||||
unsigned short CNXDNLayer3::getDestinationGroupId() const
|
||||
{
|
||||
return (m_data[5U] << 8) | m_data[6U];
|
||||
}
|
||||
|
||||
bool CNXDNLayer3::getIsGroup() const
|
||||
{
|
||||
return (m_data[2U] & 0x80U) != 0x80U;
|
||||
}
|
||||
|
||||
unsigned char CNXDNLayer3::getDataBlocks() const
|
||||
{
|
||||
return (m_data[8U] & 0x0FU) + 1U;
|
||||
}
|
||||
|
||||
void CNXDNLayer3::getData(unsigned char* data) const
|
||||
{
|
||||
::memcpy(data, m_data, 22U);
|
||||
}
|
||||
|
||||
void CNXDNLayer3::setData(const unsigned char* data, unsigned int length)
|
||||
{
|
||||
::memset(m_data, 0x00U, 22U);
|
||||
::memcpy(m_data, data, length);
|
||||
}
|
||||
|
||||
void CNXDNLayer3::reset()
|
||||
{
|
||||
::memset(m_data, 0x00U, 22U);
|
||||
}
|
||||
|
||||
CNXDNLayer3& CNXDNLayer3::operator=(const CNXDNLayer3& layer3)
|
||||
{
|
||||
if (&layer3 != this)
|
||||
::memcpy(m_data, layer3.m_data, 22U);
|
||||
|
||||
return *this;
|
||||
}
|
49
NXDNLayer3.h
Normal file
49
NXDNLayer3.h
Normal file
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
* Copyright (C) 2018 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* 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(NXDNLayer3_H)
|
||||
#define NXDNLayer3_H
|
||||
|
||||
class CNXDNLayer3 {
|
||||
public:
|
||||
CNXDNLayer3(const CNXDNLayer3& layer3);
|
||||
CNXDNLayer3();
|
||||
~CNXDNLayer3();
|
||||
|
||||
void decode(const unsigned char* bytes, unsigned int length, unsigned int offset = 0U);
|
||||
|
||||
void encode(unsigned char* bytes, unsigned int length, unsigned int offset = 0U);
|
||||
|
||||
unsigned char getMessageType() const;
|
||||
unsigned short getSourceUnitId() const;
|
||||
unsigned short getDestinationGroupId() const;
|
||||
bool getIsGroup() const;
|
||||
unsigned char getDataBlocks() const;
|
||||
|
||||
void setData(const unsigned char* data, unsigned int length);
|
||||
void getData(unsigned char* data) const;
|
||||
|
||||
void reset();
|
||||
|
||||
CNXDNLayer3& operator=(const CNXDNLayer3& layer3);
|
||||
|
||||
private:
|
||||
unsigned char* m_data;
|
||||
};
|
||||
|
||||
#endif
|
160
NXDNLookup.cpp
Normal file
160
NXDNLookup.cpp
Normal file
|
@ -0,0 +1,160 @@
|
|||
/*
|
||||
* Copyright (C) 2016,2017,2018 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* 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 "NXDNLookup.h"
|
||||
#include "Timer.h"
|
||||
#include "Log.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <cstdlib>
|
||||
#include <cstring>
|
||||
#include <cctype>
|
||||
|
||||
CNXDNLookup::CNXDNLookup(const std::string& filename, unsigned int reloadTime) :
|
||||
CThread(),
|
||||
m_filename(filename),
|
||||
m_reloadTime(reloadTime),
|
||||
m_table(),
|
||||
m_mutex(),
|
||||
m_stop(false)
|
||||
{
|
||||
}
|
||||
|
||||
CNXDNLookup::~CNXDNLookup()
|
||||
{
|
||||
}
|
||||
|
||||
bool CNXDNLookup::read()
|
||||
{
|
||||
bool ret = load();
|
||||
|
||||
if (m_reloadTime > 0U)
|
||||
run();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void CNXDNLookup::entry()
|
||||
{
|
||||
LogInfo("Started the NXDN Id lookup reload thread");
|
||||
|
||||
CTimer timer(1U, 3600U * m_reloadTime);
|
||||
timer.start();
|
||||
|
||||
while (!m_stop) {
|
||||
sleep(1000U);
|
||||
|
||||
timer.clock();
|
||||
if (timer.hasExpired()) {
|
||||
load();
|
||||
timer.start();
|
||||
}
|
||||
}
|
||||
|
||||
LogInfo("Stopped the NXDN Id lookup reload thread");
|
||||
}
|
||||
|
||||
void CNXDNLookup::stop()
|
||||
{
|
||||
if (m_reloadTime == 0U) {
|
||||
delete this;
|
||||
return;
|
||||
}
|
||||
|
||||
m_stop = true;
|
||||
|
||||
wait();
|
||||
}
|
||||
|
||||
std::string CNXDNLookup::find(unsigned int id)
|
||||
{
|
||||
std::string callsign;
|
||||
|
||||
if (id == 0xFFFFU)
|
||||
return std::string("ALL");
|
||||
|
||||
m_mutex.lock();
|
||||
|
||||
try {
|
||||
callsign = m_table.at(id);
|
||||
} catch (...) {
|
||||
char text[10U];
|
||||
::sprintf(text, "%u", id);
|
||||
callsign = std::string(text);
|
||||
}
|
||||
|
||||
m_mutex.unlock();
|
||||
|
||||
return callsign;
|
||||
}
|
||||
|
||||
bool CNXDNLookup::exists(unsigned int id)
|
||||
{
|
||||
m_mutex.lock();
|
||||
|
||||
bool found = m_table.count(id) == 1U;
|
||||
|
||||
m_mutex.unlock();
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
bool CNXDNLookup::load()
|
||||
{
|
||||
FILE* fp = ::fopen(m_filename.c_str(), "rt");
|
||||
if (fp == NULL) {
|
||||
LogWarning("Cannot open the NXDN Id lookup file - %s", m_filename.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
m_mutex.lock();
|
||||
|
||||
// Remove the old entries
|
||||
m_table.clear();
|
||||
|
||||
char buffer[100U];
|
||||
while (::fgets(buffer, 100U, fp) != NULL) {
|
||||
if (buffer[0U] == '#')
|
||||
continue;
|
||||
|
||||
char* p1 = ::strtok(buffer, ",\t\r\n");
|
||||
char* p2 = ::strtok(NULL, ",\t\r\n");
|
||||
|
||||
if (p1 != NULL && p2 != NULL) {
|
||||
unsigned int id = (unsigned int)::atoi(p1);
|
||||
if (id > 0U) {
|
||||
for (char* p = p2; *p != 0x00U; p++)
|
||||
*p = ::toupper(*p);
|
||||
|
||||
m_table[id] = std::string(p2);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_mutex.unlock();
|
||||
|
||||
::fclose(fp);
|
||||
|
||||
size_t size = m_table.size();
|
||||
if (size == 0U)
|
||||
return false;
|
||||
|
||||
LogInfo("Loaded %u Ids to the NXDN callsign lookup table", size);
|
||||
|
||||
return true;
|
||||
}
|
53
NXDNLookup.h
Normal file
53
NXDNLookup.h
Normal file
|
@ -0,0 +1,53 @@
|
|||
/*
|
||||
* Copyright (C) 2016,2017,2018 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* 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 NXDNLookup_H
|
||||
#define NXDNLookup_H
|
||||
|
||||
#include "Thread.h"
|
||||
#include "Mutex.h"
|
||||
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
|
||||
class CNXDNLookup : public CThread {
|
||||
public:
|
||||
CNXDNLookup(const std::string& filename, unsigned int reloadTime);
|
||||
virtual ~CNXDNLookup();
|
||||
|
||||
bool read();
|
||||
|
||||
virtual void entry();
|
||||
|
||||
std::string find(unsigned int id);
|
||||
|
||||
bool exists(unsigned int id);
|
||||
|
||||
void stop();
|
||||
|
||||
private:
|
||||
std::string m_filename;
|
||||
unsigned int m_reloadTime;
|
||||
std::unordered_map<unsigned int, std::string> m_table;
|
||||
CMutex m_mutex;
|
||||
bool m_stop;
|
||||
|
||||
bool load();
|
||||
};
|
||||
|
||||
#endif
|
169
NXDNNetwork.cpp
Normal file
169
NXDNNetwork.cpp
Normal file
|
@ -0,0 +1,169 @@
|
|||
/*
|
||||
* Copyright (C) 2009-2014,2016,2018,2019 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* 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 "NXDNDefines.h"
|
||||
#include "NXDNNetwork.h"
|
||||
#include "Defines.h"
|
||||
#include "Utils.h"
|
||||
#include "Log.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
|
||||
const unsigned int BUFFER_LENGTH = 200U;
|
||||
|
||||
CNXDNNetwork::CNXDNNetwork(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(1000U, "NXDN Network")
|
||||
{
|
||||
assert(gatewayPort > 0U);
|
||||
assert(!gatewayAddress.empty());
|
||||
|
||||
m_address = CUDPSocket::lookup(gatewayAddress);
|
||||
}
|
||||
|
||||
CNXDNNetwork::~CNXDNNetwork()
|
||||
{
|
||||
}
|
||||
|
||||
bool CNXDNNetwork::open()
|
||||
{
|
||||
LogMessage("Opening NXDN network connection");
|
||||
|
||||
if (m_address.s_addr == INADDR_NONE)
|
||||
return false;
|
||||
|
||||
return m_socket.open();
|
||||
}
|
||||
|
||||
bool CNXDNNetwork::write(const unsigned char* data, NXDN_NETWORK_MESSAGE_TYPE type)
|
||||
{
|
||||
assert(data != NULL);
|
||||
|
||||
unsigned char buffer[110U];
|
||||
::memset(buffer, 0x00U, 110U);
|
||||
|
||||
buffer[0U] = 'I';
|
||||
buffer[1U] = 'C';
|
||||
buffer[2U] = 'O';
|
||||
buffer[3U] = 'M';
|
||||
buffer[4U] = 0x01U;
|
||||
buffer[5U] = 0x01U;
|
||||
buffer[6U] = 0x08U;
|
||||
buffer[7U] = 0xE0U;
|
||||
|
||||
switch (type) {
|
||||
case NNMT_VOICE_HEADER:
|
||||
case NNMT_VOICE_TRAILER:
|
||||
buffer[37U] = 0x23U;
|
||||
buffer[38U] = 0x1CU;
|
||||
buffer[39U] = 0x21U;
|
||||
break;
|
||||
case NNMT_VOICE_BODY:
|
||||
buffer[37U] = 0x23U;
|
||||
buffer[38U] = 0x10U;
|
||||
buffer[39U] = 0x21U;
|
||||
break;
|
||||
case NNMT_DATA_HEADER:
|
||||
case NNMT_DATA_BODY:
|
||||
case NNMT_DATA_TRAILER:
|
||||
buffer[37U] = 0x23U;
|
||||
buffer[38U] = 0x02U;
|
||||
buffer[39U] = 0x18U;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
::memcpy(buffer + 40U, data, 33U);
|
||||
|
||||
if (m_debug)
|
||||
CUtils::dump(1U, "NXDN Network Data Sent", buffer, 102U);
|
||||
|
||||
return m_socket.write(buffer, 102U, m_address, m_port);
|
||||
}
|
||||
|
||||
void CNXDNNetwork::clock(unsigned int ms)
|
||||
{
|
||||
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("NXDN packet received from an invalid source, %08X != %08X and/or %u != %u", m_address.s_addr, address.s_addr, m_port, port);
|
||||
return;
|
||||
}
|
||||
|
||||
// Invalid packet type?
|
||||
if (::memcmp(buffer, "ICOM", 4U) != 0)
|
||||
return;
|
||||
|
||||
if (length != 102)
|
||||
return;
|
||||
|
||||
if (!m_enabled)
|
||||
return;
|
||||
|
||||
if (m_debug)
|
||||
CUtils::dump(1U, "NXDN Network Data Received", buffer, length);
|
||||
|
||||
m_buffer.addData(buffer + 40U, 33U);
|
||||
}
|
||||
|
||||
bool CNXDNNetwork::read(unsigned char* data)
|
||||
{
|
||||
assert(data != NULL);
|
||||
|
||||
if (m_buffer.isEmpty())
|
||||
return false;
|
||||
|
||||
m_buffer.getData(data, 33U);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void CNXDNNetwork::reset()
|
||||
{
|
||||
}
|
||||
|
||||
void CNXDNNetwork::close()
|
||||
{
|
||||
m_socket.close();
|
||||
|
||||
LogMessage("Closing NXDN network connection");
|
||||
}
|
||||
|
||||
void CNXDNNetwork::enable(bool enabled)
|
||||
{
|
||||
if (enabled && !m_enabled)
|
||||
reset();
|
||||
else if (!enabled && m_enabled)
|
||||
m_buffer.clear();
|
||||
|
||||
m_enabled = enabled;
|
||||
}
|
67
NXDNNetwork.h
Normal file
67
NXDNNetwork.h
Normal file
|
@ -0,0 +1,67 @@
|
|||
/*
|
||||
* Copyright (C) 2009-2014,2016,2018 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* 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 NXDNNetwork_H
|
||||
#define NXDNNetwork_H
|
||||
|
||||
#include "NXDNDefines.h"
|
||||
#include "RingBuffer.h"
|
||||
#include "UDPSocket.h"
|
||||
#include "Timer.h"
|
||||
|
||||
#include <cstdint>
|
||||
#include <string>
|
||||
|
||||
enum NXDN_NETWORK_MESSAGE_TYPE {
|
||||
NNMT_VOICE_HEADER,
|
||||
NNMT_VOICE_BODY,
|
||||
NNMT_VOICE_TRAILER,
|
||||
NNMT_DATA_HEADER,
|
||||
NNMT_DATA_BODY,
|
||||
NNMT_DATA_TRAILER
|
||||
};
|
||||
|
||||
class CNXDNNetwork {
|
||||
public:
|
||||
CNXDNNetwork(const std::string& localAddress, unsigned int localPort, const std::string& gatewayAddress, unsigned int gatewayPort, bool debug);
|
||||
~CNXDNNetwork();
|
||||
|
||||
bool open();
|
||||
|
||||
void enable(bool enabled);
|
||||
|
||||
bool write(const unsigned char* data, NXDN_NETWORK_MESSAGE_TYPE type);
|
||||
|
||||
bool read(unsigned char* data);
|
||||
|
||||
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;
|
||||
};
|
||||
|
||||
#endif
|
214
NXDNSACCH.cpp
Normal file
214
NXDNSACCH.cpp
Normal file
|
@ -0,0 +1,214 @@
|
|||
/*
|
||||
* Copyright (C) 2018 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* 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 "NXDNSACCH.h"
|
||||
|
||||
#include "NXDNConvolution.h"
|
||||
#include "NXDNDefines.h"
|
||||
#include "NXDNCRC.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
|
||||
const unsigned int INTERLEAVE_TABLE[] = {
|
||||
0U, 5U, 10U, 15U, 20U, 25U, 30U, 35U, 40U, 45U, 50U, 55U,
|
||||
1U, 6U, 11U, 16U, 21U, 26U, 31U, 36U, 41U, 46U, 51U, 56U,
|
||||
2U, 7U, 12U, 17U, 22U, 27U, 32U, 37U, 42U, 47U, 52U, 57U,
|
||||
3U, 8U, 13U, 18U, 23U, 28U, 33U, 38U, 43U, 48U, 53U, 58U,
|
||||
4U, 9U, 14U, 19U, 24U, 29U, 34U, 39U, 44U, 49U, 54U, 59U
|
||||
};
|
||||
|
||||
const unsigned int PUNCTURE_LIST[] = { 5U, 11U, 17U, 23U, 29U, 35U, 41U, 47U, 53U, 59U, 65U, 71U };
|
||||
|
||||
const unsigned char BIT_MASK_TABLE[] = { 0x80U, 0x40U, 0x20U, 0x10U, 0x08U, 0x04U, 0x02U, 0x01U };
|
||||
|
||||
#define WRITE_BIT1(p,i,b) p[(i)>>3] = (b) ? (p[(i)>>3] | BIT_MASK_TABLE[(i)&7]) : (p[(i)>>3] & ~BIT_MASK_TABLE[(i)&7])
|
||||
#define READ_BIT1(p,i) (p[(i)>>3] & BIT_MASK_TABLE[(i)&7])
|
||||
|
||||
CNXDNSACCH::CNXDNSACCH(const CNXDNSACCH& sacch) :
|
||||
m_data(NULL)
|
||||
{
|
||||
m_data = new unsigned char[5U];
|
||||
::memcpy(m_data, sacch.m_data, 5U);
|
||||
}
|
||||
|
||||
CNXDNSACCH::CNXDNSACCH() :
|
||||
m_data(NULL)
|
||||
{
|
||||
m_data = new unsigned char[5U];
|
||||
}
|
||||
|
||||
CNXDNSACCH::~CNXDNSACCH()
|
||||
{
|
||||
delete[] m_data;
|
||||
}
|
||||
|
||||
bool CNXDNSACCH::decode(const unsigned char* data)
|
||||
{
|
||||
assert(data != NULL);
|
||||
|
||||
unsigned char temp1[8U];
|
||||
|
||||
for (unsigned int i = 0U; i < NXDN_SACCH_LENGTH_BITS; i++) {
|
||||
unsigned int n = INTERLEAVE_TABLE[i] + NXDN_FSW_LENGTH_BITS + NXDN_LICH_LENGTH_BITS;
|
||||
bool b = READ_BIT1(data, n);
|
||||
WRITE_BIT1(temp1, i, b);
|
||||
}
|
||||
|
||||
uint8_t temp2[90U];
|
||||
|
||||
unsigned int n = 0U;
|
||||
unsigned int index = 0U;
|
||||
for (unsigned int i = 0U; i < NXDN_SACCH_LENGTH_BITS; i++) {
|
||||
if (n == PUNCTURE_LIST[index]) {
|
||||
temp2[n++] = 1U;
|
||||
index++;
|
||||
}
|
||||
|
||||
bool b = READ_BIT1(temp1, i);
|
||||
temp2[n++] = b ? 2U : 0U;
|
||||
}
|
||||
|
||||
for (unsigned int i = 0U; i < 8U; i++) {
|
||||
temp2[n++] = 0U;
|
||||
}
|
||||
|
||||
CNXDNConvolution conv;
|
||||
conv.start();
|
||||
|
||||
n = 0U;
|
||||
for (unsigned int i = 0U; i < 40U; i++) {
|
||||
uint8_t s0 = temp2[n++];
|
||||
uint8_t s1 = temp2[n++];
|
||||
|
||||
conv.decode(s0, s1);
|
||||
}
|
||||
|
||||
conv.chainback(m_data, 36U);
|
||||
|
||||
return CNXDNCRC::checkCRC6(m_data, 26U);
|
||||
}
|
||||
|
||||
void CNXDNSACCH::encode(unsigned char* data) const
|
||||
{
|
||||
assert(data != NULL);
|
||||
|
||||
unsigned char temp1[5U];
|
||||
::memset(temp1, 0x00U, 5U);
|
||||
|
||||
for (unsigned int i = 0U; i < 26U; i++) {
|
||||
bool b = READ_BIT1(m_data, i);
|
||||
WRITE_BIT1(temp1, i, b);
|
||||
}
|
||||
|
||||
CNXDNCRC::encodeCRC6(temp1, 26U);
|
||||
|
||||
unsigned char temp2[9U];
|
||||
|
||||
CNXDNConvolution conv;
|
||||
conv.encode(temp1, temp2, 36U);
|
||||
|
||||
unsigned char temp3[8U];
|
||||
|
||||
unsigned int n = 0U;
|
||||
unsigned int index = 0U;
|
||||
for (unsigned int i = 0U; i < 72U; i++) {
|
||||
if (i != PUNCTURE_LIST[index]) {
|
||||
bool b = READ_BIT1(temp2, i);
|
||||
WRITE_BIT1(temp3, n, b);
|
||||
n++;
|
||||
} else {
|
||||
index++;
|
||||
}
|
||||
}
|
||||
|
||||
for (unsigned int i = 0U; i < NXDN_SACCH_LENGTH_BITS; i++) {
|
||||
unsigned int n = INTERLEAVE_TABLE[i] + NXDN_FSW_LENGTH_BITS + NXDN_LICH_LENGTH_BITS;
|
||||
bool b = READ_BIT1(temp3, i);
|
||||
WRITE_BIT1(data, n, b);
|
||||
}
|
||||
}
|
||||
|
||||
unsigned char CNXDNSACCH::getRAN() const
|
||||
{
|
||||
return m_data[0U] & 0x3FU;
|
||||
}
|
||||
|
||||
unsigned char CNXDNSACCH::getStructure() const
|
||||
{
|
||||
return (m_data[0U] >> 6) & 0x03U;
|
||||
}
|
||||
|
||||
void CNXDNSACCH::getData(unsigned char* data) const
|
||||
{
|
||||
assert(data != NULL);
|
||||
|
||||
unsigned int offset = 8U;
|
||||
for (unsigned int i = 0U; i < 18U; i++, offset++) {
|
||||
bool b = READ_BIT1(m_data, offset);
|
||||
WRITE_BIT1(data, i, b);
|
||||
}
|
||||
}
|
||||
|
||||
void CNXDNSACCH::getRaw(unsigned char* data) const
|
||||
{
|
||||
assert(data != NULL);
|
||||
|
||||
::memcpy(data, m_data, 4U);
|
||||
|
||||
CNXDNCRC::encodeCRC6(data, 26U);
|
||||
}
|
||||
|
||||
void CNXDNSACCH::setRAN(unsigned char ran)
|
||||
{
|
||||
m_data[0U] &= 0xC0U;
|
||||
m_data[0U] |= ran;
|
||||
}
|
||||
|
||||
void CNXDNSACCH::setStructure(unsigned char structure)
|
||||
{
|
||||
m_data[0U] &= 0x3FU;
|
||||
m_data[0U] |= (structure << 6) & 0xC0U;
|
||||
}
|
||||
|
||||
void CNXDNSACCH::setData(const unsigned char* data)
|
||||
{
|
||||
assert(data != NULL);
|
||||
|
||||
unsigned int offset = 8U;
|
||||
for (unsigned int i = 0U; i < 18U; i++, offset++) {
|
||||
bool b = READ_BIT1(data, i);
|
||||
WRITE_BIT1(m_data, offset, b);
|
||||
}
|
||||
}
|
||||
|
||||
void CNXDNSACCH::setRaw(const unsigned char* data)
|
||||
{
|
||||
assert(data != NULL);
|
||||
|
||||
::memcpy(m_data, data, 4U);
|
||||
}
|
||||
|
||||
CNXDNSACCH& CNXDNSACCH::operator=(const CNXDNSACCH& sacch)
|
||||
{
|
||||
if (&sacch != this)
|
||||
::memcpy(m_data, sacch.m_data, 5U);
|
||||
|
||||
return *this;
|
||||
}
|
50
NXDNSACCH.h
Normal file
50
NXDNSACCH.h
Normal file
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
* Copyright (C) 2018 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* 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(NXDNSACCH_H)
|
||||
#define NXDNSACCH_H
|
||||
|
||||
class CNXDNSACCH {
|
||||
public:
|
||||
CNXDNSACCH(const CNXDNSACCH& sacch);
|
||||
CNXDNSACCH();
|
||||
~CNXDNSACCH();
|
||||
|
||||
bool decode(const unsigned char* data);
|
||||
|
||||
void encode(unsigned char* data) const;
|
||||
|
||||
unsigned char getRAN() const;
|
||||
unsigned char getStructure() const;
|
||||
|
||||
void getData(unsigned char* data) const;
|
||||
void getRaw(unsigned char* data) const;
|
||||
|
||||
void setRAN(unsigned char ran);
|
||||
void setStructure(unsigned char structure);
|
||||
|
||||
void setData(const unsigned char* data);
|
||||
void setRaw(const unsigned char* data);
|
||||
|
||||
CNXDNSACCH& operator=(const CNXDNSACCH& sacch);
|
||||
|
||||
private:
|
||||
unsigned char* m_data;
|
||||
};
|
||||
|
||||
#endif
|
217
NXDNUDCH.cpp
Normal file
217
NXDNUDCH.cpp
Normal file
|
@ -0,0 +1,217 @@
|
|||
/*
|
||||
* Copyright (C) 2018 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* 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 "NXDNUDCH.h"
|
||||
|
||||
#include "NXDNConvolution.h"
|
||||
#include "NXDNDefines.h"
|
||||
#include "NXDNCRC.h"
|
||||
|
||||
#include <cstdio>
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
|
||||
const unsigned int INTERLEAVE_TABLE[] = {
|
||||
0U, 29U, 58U, 87U, 116U, 145U, 174U, 203U, 232U, 261U, 290U, 319U,
|
||||
1U, 30U, 59U, 88U, 117U, 146U, 175U, 204U, 233U, 262U, 291U, 320U,
|
||||
2U, 31U, 60U, 89U, 118U, 147U, 176U, 205U, 234U, 263U, 292U, 321U,
|
||||
3U, 32U, 61U, 90U, 119U, 148U, 177U, 206U, 235U, 264U, 293U, 322U,
|
||||
4U, 33U, 62U, 91U, 120U, 149U, 178U, 207U, 236U, 265U, 294U, 323U,
|
||||
5U, 34U, 63U, 92U, 121U, 150U, 179U, 208U, 237U, 266U, 295U, 324U,
|
||||
6U, 35U, 64U, 93U, 122U, 151U, 180U, 209U, 238U, 267U, 296U, 325U,
|
||||
7U, 36U, 65U, 94U, 123U, 152U, 181U, 210U, 239U, 268U, 297U, 326U,
|
||||
8U, 37U, 66U, 95U, 124U, 153U, 182U, 211U, 240U, 269U, 298U, 327U,
|
||||
9U, 38U, 67U, 96U, 125U, 154U, 183U, 212U, 241U, 270U, 299U, 328U,
|
||||
10U, 39U, 68U, 97U, 126U, 155U, 184U, 213U, 242U, 271U, 300U, 329U,
|
||||
11U, 40U, 69U, 98U, 127U, 156U, 185U, 214U, 243U, 272U, 301U, 330U,
|
||||
12U, 41U, 70U, 99U, 128U, 157U, 186U, 215U, 244U, 273U, 302U, 331U,
|
||||
13U, 42U, 71U, 100U, 129U, 158U, 187U, 216U, 245U, 274U, 303U, 332U,
|
||||
14U, 43U, 72U, 101U, 130U, 159U, 188U, 217U, 246U, 275U, 304U, 333U,
|
||||
15U, 44U, 73U, 102U, 131U, 160U, 189U, 218U, 247U, 276U, 305U, 334U,
|
||||
16U, 45U, 74U, 103U, 132U, 161U, 190U, 219U, 248U, 277U, 306U, 335U,
|
||||
17U, 46U, 75U, 104U, 133U, 162U, 191U, 220U, 249U, 278U, 307U, 336U,
|
||||
18U, 47U, 76U, 105U, 134U, 163U, 192U, 221U, 250U, 279U, 308U, 337U,
|
||||
19U, 48U, 77U, 106U, 135U, 164U, 193U, 222U, 251U, 280U, 309U, 338U,
|
||||
20U, 49U, 78U, 107U, 136U, 165U, 194U, 223U, 252U, 281U, 310U, 339U,
|
||||
21U, 50U, 79U, 108U, 137U, 166U, 195U, 224U, 253U, 282U, 311U, 340U,
|
||||
22U, 51U, 80U, 109U, 138U, 167U, 196U, 225U, 254U, 283U, 312U, 341U,
|
||||
23U, 52U, 81U, 110U, 139U, 168U, 197U, 226U, 255U, 284U, 313U, 342U,
|
||||
24U, 53U, 82U, 111U, 140U, 169U, 198U, 227U, 256U, 285U, 314U, 343U,
|
||||
25U, 54U, 83U, 112U, 141U, 170U, 199U, 228U, 257U, 286U, 315U, 344U,
|
||||
26U, 55U, 84U, 113U, 142U, 171U, 200U, 229U, 258U, 287U, 316U, 345U,
|
||||
27U, 56U, 85U, 114U, 143U, 172U, 201U, 230U, 259U, 288U, 317U, 346U,
|
||||
28U, 57U, 86U, 115U, 144U, 173U, 202U, 231U, 260U, 289U, 318U, 347U };
|
||||
|
||||
const unsigned int PUNCTURE_LIST[] = { 3U, 11U, 17U, 25U, 31U, 39U, 45U, 53U, 59U, 67U,
|
||||
73U, 81U, 87U, 95U, 101U, 109U, 115U, 123U, 129U, 137U,
|
||||
143U, 151U, 157U, 165U, 171U, 179U, 185U, 193U, 199U, 207U,
|
||||
213U, 221U, 227U, 235U, 241U, 249U, 255U, 263U, 269U, 277U,
|
||||
283U, 291U, 297U, 305U, 311U, 319U, 325U, 333U, 339U, 347U,
|
||||
353U, 361U, 367U, 375U, 381U, 389U, 395U, 403U };
|
||||
|
||||
const unsigned char BIT_MASK_TABLE[] = { 0x80U, 0x40U, 0x20U, 0x10U, 0x08U, 0x04U, 0x02U, 0x01U };
|
||||
|
||||
#define WRITE_BIT1(p,i,b) p[(i)>>3] = (b) ? (p[(i)>>3] | BIT_MASK_TABLE[(i)&7]) : (p[(i)>>3] & ~BIT_MASK_TABLE[(i)&7])
|
||||
#define READ_BIT1(p,i) (p[(i)>>3] & BIT_MASK_TABLE[(i)&7])
|
||||
|
||||
CNXDNUDCH::CNXDNUDCH(const CNXDNUDCH& udch) :
|
||||
m_data(NULL)
|
||||
{
|
||||
m_data = new unsigned char[23U + 3U];
|
||||
::memcpy(m_data, udch.m_data, 23U + 3U);
|
||||
}
|
||||
|
||||
CNXDNUDCH::CNXDNUDCH() :
|
||||
m_data(NULL)
|
||||
{
|
||||
m_data = new unsigned char[23U + 3U];
|
||||
}
|
||||
|
||||
CNXDNUDCH::~CNXDNUDCH()
|
||||
{
|
||||
delete[] m_data;
|
||||
}
|
||||
|
||||
bool CNXDNUDCH::decode(const unsigned char* data)
|
||||
{
|
||||
assert(data != NULL);
|
||||
|
||||
unsigned char temp1[44U];
|
||||
|
||||
for (unsigned int i = 0U; i < NXDN_FACCH2_LENGTH_BITS; i++) {
|
||||
unsigned int n = INTERLEAVE_TABLE[i] + NXDN_FSW_LENGTH_BITS + NXDN_LICH_LENGTH_BITS;
|
||||
bool b = READ_BIT1(data, n);
|
||||
WRITE_BIT1(temp1, i, b);
|
||||
}
|
||||
|
||||
uint8_t temp2[420U];
|
||||
|
||||
unsigned int n = 0U;
|
||||
unsigned int index = 0U;
|
||||
for (unsigned int i = 0U; i < NXDN_FACCH2_LENGTH_BITS; i++) {
|
||||
if (n == PUNCTURE_LIST[index]) {
|
||||
temp2[n++] = 1U;
|
||||
index++;
|
||||
}
|
||||
|
||||
bool b = READ_BIT1(temp1, i);
|
||||
temp2[n++] = b ? 2U : 0U;
|
||||
}
|
||||
|
||||
for (unsigned int i = 0U; i < 8U; i++) {
|
||||
temp2[n++] = 0U;
|
||||
}
|
||||
|
||||
CNXDNConvolution conv;
|
||||
conv.start();
|
||||
|
||||
n = 0U;
|
||||
for (unsigned int i = 0U; i < 207U; i++) {
|
||||
uint8_t s0 = temp2[n++];
|
||||
uint8_t s1 = temp2[n++];
|
||||
|
||||
conv.decode(s0, s1);
|
||||
}
|
||||
|
||||
conv.chainback(m_data, 203U);
|
||||
|
||||
return CNXDNCRC::checkCRC15(m_data, 184U);
|
||||
}
|
||||
|
||||
void CNXDNUDCH::encode(unsigned char* data) const
|
||||
{
|
||||
assert(data != NULL);
|
||||
|
||||
unsigned char temp1[25U];
|
||||
::memset(temp1, 0x00U, 25U);
|
||||
::memcpy(temp1, m_data, 23U);
|
||||
|
||||
CNXDNCRC::encodeCRC15(temp1, 184U);
|
||||
|
||||
unsigned char temp2[51U];
|
||||
|
||||
CNXDNConvolution conv;
|
||||
conv.encode(temp1, temp2, 203U);
|
||||
|
||||
unsigned char temp3[44U];
|
||||
|
||||
unsigned int n = 0U;
|
||||
unsigned int index = 0U;
|
||||
for (unsigned int i = 0U; i < 406U; i++) {
|
||||
if (i != PUNCTURE_LIST[index]) {
|
||||
bool b = READ_BIT1(temp2, i);
|
||||
WRITE_BIT1(temp3, n, b);
|
||||
n++;
|
||||
} else {
|
||||
index++;
|
||||
}
|
||||
}
|
||||
|
||||
for (unsigned int i = 0U; i < NXDN_FACCH2_LENGTH_BITS; i++) {
|
||||
unsigned int n = INTERLEAVE_TABLE[i] + NXDN_FSW_LENGTH_BITS + NXDN_LICH_LENGTH_BITS;
|
||||
bool b = READ_BIT1(temp3, i);
|
||||
WRITE_BIT1(data, n, b);
|
||||
}
|
||||
}
|
||||
|
||||
unsigned char CNXDNUDCH::getRAN() const
|
||||
{
|
||||
return m_data[0U] & 0x3FU;
|
||||
}
|
||||
|
||||
void CNXDNUDCH::getData(unsigned char* data) const
|
||||
{
|
||||
assert(data != NULL);
|
||||
|
||||
::memcpy(data, m_data + 1U, 22U);
|
||||
}
|
||||
|
||||
void CNXDNUDCH::getRaw(unsigned char* data) const
|
||||
{
|
||||
assert(data != NULL);
|
||||
|
||||
::memset(data, 0x00U, 25U);
|
||||
::memcpy(data, m_data, 23U);
|
||||
}
|
||||
|
||||
void CNXDNUDCH::setRAN(unsigned char ran)
|
||||
{
|
||||
m_data[0U] = ran;
|
||||
}
|
||||
|
||||
void CNXDNUDCH::setData(const unsigned char* data)
|
||||
{
|
||||
assert(data != NULL);
|
||||
|
||||
::memcpy(m_data + 1U, data, 22U);
|
||||
}
|
||||
|
||||
void CNXDNUDCH::setRaw(const unsigned char* data)
|
||||
{
|
||||
assert(data != NULL);
|
||||
|
||||
::memcpy(m_data, data, 25U);
|
||||
}
|
||||
|
||||
CNXDNUDCH& CNXDNUDCH::operator=(const CNXDNUDCH& udch)
|
||||
{
|
||||
if (&udch != this)
|
||||
::memcpy(m_data, udch.m_data, 23U + 2U);
|
||||
|
||||
return *this;
|
||||
}
|
48
NXDNUDCH.h
Normal file
48
NXDNUDCH.h
Normal file
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
* Copyright (C) 2018 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* 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(NXDNUDCH_H)
|
||||
#define NXDNUDCH_H
|
||||
|
||||
class CNXDNUDCH {
|
||||
public:
|
||||
CNXDNUDCH(const CNXDNUDCH& udch);
|
||||
CNXDNUDCH();
|
||||
~CNXDNUDCH();
|
||||
|
||||
bool decode(const unsigned char* data);
|
||||
|
||||
void encode(unsigned char* data) const;
|
||||
|
||||
unsigned char getRAN() const;
|
||||
|
||||
void getData(unsigned char* data) const;
|
||||
void getRaw(unsigned char* data) const;
|
||||
|
||||
void setRAN(unsigned char ran);
|
||||
|
||||
void setData(const unsigned char* data);
|
||||
void setRaw(const unsigned char* data);
|
||||
|
||||
CNXDNUDCH& operator=(const CNXDNUDCH& udch);
|
||||
|
||||
private:
|
||||
unsigned char* m_data;
|
||||
};
|
||||
|
||||
#endif
|
|
@ -26,18 +26,13 @@
|
|||
#include <clocale>
|
||||
|
||||
#include <sys/types.h>
|
||||
#if defined(__linux__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__FreeBSD__) || defined(__APPLE__)
|
||||
#if !defined(_WIN32) && !defined(_WIN64)
|
||||
#include <ifaddrs.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netdb.h>
|
||||
#if defined(__OpenBSD__) || defined(__NetBSD__) || defined(__FreeBSD__) || defined(__APPLE__)
|
||||
#include <sys/sysctl.h>
|
||||
#include <net/if.h>
|
||||
#include <net/route.h>
|
||||
#endif
|
||||
#elif defined(_WIN32) || defined(_WIN64)
|
||||
#else
|
||||
#include <ws2tcpip.h>
|
||||
#include <iphlpapi.h>
|
||||
#pragma comment(lib, "iphlpapi.lib")
|
||||
|
@ -66,16 +61,17 @@ void CNetworkInfo::getNetworkInterface(unsigned char* info)
|
|||
|
||||
::strcpy((char*)info, "(address unknown)");
|
||||
|
||||
#if defined(__linux__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__FreeBSD__) || defined(__APPLE__)
|
||||
char* dflt = NULL;
|
||||
#if !defined(_WIN32) && !defined(_WIN64)
|
||||
const unsigned int IFLISTSIZ = 25U;
|
||||
|
||||
#if defined(__linux__)
|
||||
FILE* fp = ::fopen("/proc/net/route" , "r"); // IPv4 routing
|
||||
FILE* fp = ::fopen("/proc/net/route" , "r");
|
||||
if (fp == NULL) {
|
||||
LogError("Unabled to open /proc/route");
|
||||
return;
|
||||
}
|
||||
|
||||
char* dflt = NULL;
|
||||
|
||||
char line[100U];
|
||||
while (::fgets(line, 100U, fp)) {
|
||||
char* p1 = strtok(line , " \t");
|
||||
|
@ -91,60 +87,11 @@ void CNetworkInfo::getNetworkInterface(unsigned char* info)
|
|||
|
||||
::fclose(fp);
|
||||
|
||||
#elif defined(__OpenBSD__) || defined(__NetBSD__) || defined(__FreeBSD__) || defined(__APPLE__)
|
||||
int mib[] = {
|
||||
CTL_NET,
|
||||
PF_ROUTE,
|
||||
0, // protocol
|
||||
AF_INET, // IPv4 routing
|
||||
NET_RT_DUMP,
|
||||
0, // show all routes
|
||||
#if defined(__OpenBSD__) || defined(__FreeBSD__)
|
||||
0, // table id
|
||||
#endif
|
||||
};
|
||||
const int cnt = sizeof(mib) / sizeof(int);
|
||||
size_t size;
|
||||
char ifname[IF_NAMESIZE] = {};
|
||||
|
||||
if (::sysctl(mib, cnt, NULL, &size, NULL, 0) == -1 || size <= 0) {
|
||||
LogError("Unable to estimate routing table size");
|
||||
return;
|
||||
}
|
||||
|
||||
char *buf = new char[size];
|
||||
if (::sysctl(mib, cnt, buf, &size, NULL, 0) == -1) {
|
||||
LogError("Unable to get routing table");
|
||||
delete[] buf;
|
||||
return;
|
||||
}
|
||||
|
||||
struct rt_msghdr *rtm;
|
||||
for (char *p = buf; p < buf + size; p += rtm->rtm_msglen) {
|
||||
rtm = (struct rt_msghdr *)p;
|
||||
if (rtm->rtm_version != RTM_VERSION)
|
||||
continue;
|
||||
#if defined(__OpenBSD__)
|
||||
struct sockaddr_in *sa = (struct sockaddr_in *)(p + rtm->rtm_hdrlen);
|
||||
#elif defined(__NetBSD__) || defined(__FreeBSD__) || defined(__APPLE__)
|
||||
struct sockaddr_in *sa = (struct sockaddr_in *)(rtm + 1);
|
||||
#endif
|
||||
if (sa->sin_addr.s_addr == INADDR_ANY) {
|
||||
::if_indextoname(rtm->rtm_index, ifname);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
delete[] buf;
|
||||
if (::strlen(ifname))
|
||||
dflt = ifname;
|
||||
#endif
|
||||
if (dflt == NULL) {
|
||||
LogError("Unable to find the default route");
|
||||
return;
|
||||
}
|
||||
|
||||
const unsigned int IFLISTSIZ = 25U;
|
||||
char interfacelist[IFLISTSIZ][50+INET6_ADDRSTRLEN];
|
||||
for (unsigned int n = 0U; n < IFLISTSIZ; n++)
|
||||
interfacelist[n][0] = 0;
|
||||
|
@ -172,13 +119,12 @@ void CNetworkInfo::getNetworkInterface(unsigned char* info)
|
|||
if (family == AF_INET) {
|
||||
::sprintf(interfacelist[ifnr], "%s:%s", ifa->ifa_name, host);
|
||||
LogInfo(" IPv4: %s", interfacelist[ifnr]);
|
||||
ifnr++;
|
||||
} else {
|
||||
::sprintf(interfacelist[ifnr], "%s:%s", ifa->ifa_name, host);
|
||||
LogInfo(" IPv6: %s", interfacelist[ifnr]);
|
||||
// due to default routing is for IPv4, other
|
||||
// protocols are not candidate to display.
|
||||
}
|
||||
|
||||
ifnr++;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -198,7 +144,7 @@ void CNetworkInfo::getNetworkInterface(unsigned char* info)
|
|||
}
|
||||
|
||||
LogInfo(" IP to show: %s", info);
|
||||
#elif defined(_WIN32) || defined(_WIN64)
|
||||
#else
|
||||
PMIB_IPFORWARDTABLE pIpForwardTable = (MIB_IPFORWARDTABLE *)::malloc(sizeof(MIB_IPFORWARDTABLE));
|
||||
if (pIpForwardTable == NULL) {
|
||||
LogError("Error allocating memory");
|
||||
|
|
471
Nextion.cpp
471
Nextion.cpp
|
@ -1,5 +1,5 @@
|
|||
/*
|
||||
* Copyright (C) 2016,2017,2018,2020 by Jonathan Naylor G4KLX
|
||||
* Copyright (C) 2016,2017,2018 by Jonathan Naylor G4KLX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
|
@ -25,21 +25,20 @@
|
|||
#include <cstring>
|
||||
#include <ctime>
|
||||
#include <clocale>
|
||||
//#include <unistd.h>
|
||||
|
||||
const unsigned int DSTAR_RSSI_COUNT = 3U; // 3 * 420ms = 1260ms
|
||||
const unsigned int DSTAR_BER_COUNT = 63U; // 63 * 20ms = 1260ms
|
||||
const unsigned int DMR_RSSI_COUNT = 4U; // 4 * 360ms = 1440ms
|
||||
const unsigned int DMR_BER_COUNT = 24U; // 24 * 60ms = 1440ms
|
||||
const unsigned int YSF_RSSI_COUNT = 13U; // 13 * 100ms = 1300ms
|
||||
const unsigned int YSF_BER_COUNT = 13U; // 13 * 100ms = 1300ms
|
||||
const unsigned int P25_RSSI_COUNT = 7U; // 7 * 180ms = 1260ms
|
||||
const unsigned int P25_BER_COUNT = 7U; // 7 * 180ms = 1260ms
|
||||
const unsigned int NXDN_RSSI_COUNT = 28U; // 28 * 40ms = 1120ms
|
||||
const unsigned int NXDN_BER_COUNT = 28U; // 28 * 40ms = 1120ms
|
||||
|
||||
#define LAYOUT_COMPAT_MASK (7 << 0) // compatibility for old setting
|
||||
#define LAYOUT_TA_ENABLE (1 << 4) // enable Talker Alias (TA) display
|
||||
#define LAYOUT_TA_COLOUR (1 << 5) // TA display with font colour change
|
||||
#define LAYOUT_TA_FONTSIZE (1 << 6) // TA display with font size change
|
||||
#define LAYOUT_DIY (1 << 7) // use ON7LDS-DIY layout
|
||||
|
||||
// bit[3:2] is used in Display.cpp to set connection speed for LCD panel.
|
||||
// 00:low, others:high-speed. bit[2] is overlapped with LAYOUT_COMPAT_MASK.
|
||||
#define LAYOUT_HIGHSPEED (3 << 2)
|
||||
|
||||
CNextion::CNextion(const std::string& callsign, unsigned int dmrid, ISerialPort* serial, unsigned int brightness, bool displayClock, bool utc, unsigned int idleBrightness, unsigned int screenLayout, unsigned int txFrequency, unsigned int rxFrequency, bool displayTempInF) :
|
||||
CNextion::CNextion(const std::string& callsign, unsigned int dmrid, ISerialPort* serial, unsigned int brightness, bool displayClock, bool utc, unsigned int idleBrightness, unsigned int screenLayout, unsigned int txFrequency, unsigned int rxFrequency, bool displayTempInF, const std::string& location) :
|
||||
CDisplay(),
|
||||
m_callsign(callsign),
|
||||
m_ipaddress("(ip unknown)"),
|
||||
|
@ -50,7 +49,7 @@ m_mode(MODE_IDLE),
|
|||
m_displayClock(displayClock),
|
||||
m_utc(utc),
|
||||
m_idleBrightness(idleBrightness),
|
||||
m_screenLayout(0),
|
||||
m_screenLayout(screenLayout),
|
||||
m_clockDisplayTimer(1000U, 0U, 400U),
|
||||
m_rssiAccum1(0U),
|
||||
m_rssiAccum2(0U),
|
||||
|
@ -64,27 +63,11 @@ m_txFrequency(txFrequency),
|
|||
m_rxFrequency(rxFrequency),
|
||||
m_fl_txFrequency(0.0F),
|
||||
m_fl_rxFrequency(0.0F),
|
||||
m_displayTempInF(displayTempInF)
|
||||
m_displayTempInF(displayTempInF),
|
||||
m_location(location)
|
||||
{
|
||||
assert(serial != NULL);
|
||||
assert(brightness >= 0U && brightness <= 100U);
|
||||
|
||||
static const unsigned int feature_set[] = {
|
||||
0, // 0: G4KLX
|
||||
0, // 1: (reserved, low speed)
|
||||
// 2: ON7LDS
|
||||
LAYOUT_TA_ENABLE | LAYOUT_TA_COLOUR | LAYOUT_TA_FONTSIZE,
|
||||
LAYOUT_TA_ENABLE | LAYOUT_DIY, // 3: ON7LDS-DIY
|
||||
LAYOUT_TA_ENABLE | LAYOUT_DIY, // 4: ON7LDS-DIY (high speed)
|
||||
0, // 5: (reserved, high speed)
|
||||
0, // 6: (reserved, high speed)
|
||||
0, // 7: (reserved, high speed)
|
||||
};
|
||||
|
||||
if (screenLayout & ~LAYOUT_COMPAT_MASK)
|
||||
m_screenLayout = screenLayout & ~LAYOUT_COMPAT_MASK;
|
||||
else
|
||||
m_screenLayout = feature_set[screenLayout];
|
||||
}
|
||||
|
||||
CNextion::~CNextion()
|
||||
|
@ -111,14 +94,15 @@ bool CNextion::open()
|
|||
sendCommand("bkcmd=0");
|
||||
sendCommandAction(0U);
|
||||
|
||||
m_fl_txFrequency = double(m_txFrequency) / 1000000.0F;
|
||||
m_fl_rxFrequency = double(m_rxFrequency) / 1000000.0F;
|
||||
m_fl_txFrequency = float(m_txFrequency) / 1000000.0F;
|
||||
m_fl_rxFrequency = float(m_rxFrequency) / 1000000.0F;
|
||||
|
||||
setIdle();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
void CNextion::setIdleInt()
|
||||
{
|
||||
// a few bits borrowed from Lieven De Samblanx ON7LDS, NextionDriver
|
||||
|
@ -135,18 +119,18 @@ void CNextion::setIdleInt()
|
|||
::sprintf(command, "t0.txt=\"%s/%u\"", m_callsign.c_str(), m_dmrid);
|
||||
sendCommand(command);
|
||||
|
||||
if (m_screenLayout & LAYOUT_DIY) {
|
||||
if (m_screenLayout > 2U) {
|
||||
::sprintf(command, "t4.txt=\"%s\"", m_callsign.c_str());
|
||||
sendCommand(command);
|
||||
::sprintf(command, "t5.txt=\"%u\"", m_dmrid);
|
||||
sendCommand(command);
|
||||
sendCommandAction(17U);
|
||||
|
||||
::sprintf(command, "t30.txt=\"%3.6f\"",m_fl_rxFrequency); // RX freq
|
||||
::sprintf(command, "t30.txt=\"%3.4f\"",m_fl_rxFrequency); // RX freq
|
||||
sendCommand(command);
|
||||
sendCommandAction(20U);
|
||||
|
||||
::sprintf(command, "t32.txt=\"%3.6f\"",m_fl_txFrequency); // TX freq
|
||||
::sprintf(command, "t32.txt=\"%3.4f\"",m_fl_txFrequency); // TX freq
|
||||
sendCommand(command);
|
||||
sendCommandAction(21U);
|
||||
|
||||
|
@ -169,6 +153,10 @@ void CNextion::setIdleInt()
|
|||
sendCommandAction(22U);
|
||||
}
|
||||
}
|
||||
|
||||
::sprintf(command, "t31.txt=\"%s\"", m_location.c_str()); // location
|
||||
sendCommand(command);
|
||||
sendCommandAction(23U);
|
||||
} else {
|
||||
sendCommandAction(17U);
|
||||
}
|
||||
|
@ -252,6 +240,88 @@ void CNextion::setQuitInt()
|
|||
m_mode = MODE_QUIT;
|
||||
}
|
||||
|
||||
void CNextion::writeDStarInt(const char* my1, const char* my2, const char* your, const char* type, const char* reflector)
|
||||
{
|
||||
assert(my1 != NULL);
|
||||
assert(my2 != NULL);
|
||||
assert(your != NULL);
|
||||
assert(type != NULL);
|
||||
assert(reflector != NULL);
|
||||
|
||||
if (m_mode != MODE_DSTAR) {
|
||||
sendCommand("page DStar");
|
||||
sendCommandAction(2U);
|
||||
}
|
||||
|
||||
char text[50U];
|
||||
if (m_brightness>0) {
|
||||
::sprintf(text, "dim=%u", m_brightness);
|
||||
sendCommand(text);
|
||||
}
|
||||
|
||||
::sprintf(text, "t0.txt=\"%s %.8s/%4.4s\"", type, my1, my2);
|
||||
sendCommand(text);
|
||||
sendCommandAction(42U);
|
||||
|
||||
::sprintf(text, "t1.txt=\"%.8s\"", your);
|
||||
sendCommand(text);
|
||||
sendCommandAction(45U);
|
||||
|
||||
if (::strcmp(reflector, " ") != 0) {
|
||||
::sprintf(text, "t2.txt=\"via %.8s\"", reflector);
|
||||
sendCommand(text);
|
||||
sendCommandAction(46U);
|
||||
}
|
||||
|
||||
m_clockDisplayTimer.stop();
|
||||
|
||||
m_mode = MODE_DSTAR;
|
||||
m_rssiAccum1 = 0U;
|
||||
m_berAccum1 = 0.0F;
|
||||
m_rssiCount1 = 0U;
|
||||
m_berCount1 = 0U;
|
||||
}
|
||||
|
||||
void CNextion::writeDStarRSSIInt(unsigned char rssi)
|
||||
{
|
||||
m_rssiAccum1 += rssi;
|
||||
m_rssiCount1++;
|
||||
|
||||
if (m_rssiCount1 == DSTAR_RSSI_COUNT) {
|
||||
char text[25U];
|
||||
::sprintf(text, "t3.txt=\"-%udBm\"", m_rssiAccum1 / DSTAR_RSSI_COUNT);
|
||||
sendCommand(text);
|
||||
sendCommandAction(47U);
|
||||
m_rssiAccum1 = 0U;
|
||||
m_rssiCount1 = 0U;
|
||||
}
|
||||
}
|
||||
|
||||
void CNextion::writeDStarBERInt(float ber)
|
||||
{
|
||||
m_berAccum1 += ber;
|
||||
m_berCount1++;
|
||||
|
||||
if (m_berCount1 == DSTAR_BER_COUNT) {
|
||||
char text[25U];
|
||||
::sprintf(text, "t4.txt=\"%.1f%%\"", m_berAccum1 / float(DSTAR_BER_COUNT));
|
||||
sendCommand(text);
|
||||
sendCommandAction(48U);
|
||||
m_berAccum1 = 0.0F;
|
||||
m_berCount1 = 0U;
|
||||
}
|
||||
}
|
||||
|
||||
void CNextion::clearDStarInt()
|
||||
{
|
||||
sendCommand("t0.txt=\"Listening\"");
|
||||
sendCommandAction(41U);
|
||||
sendCommand("t1.txt=\"\"");
|
||||
sendCommand("t2.txt=\"\"");
|
||||
sendCommand("t3.txt=\"\"");
|
||||
sendCommand("t4.txt=\"\"");
|
||||
}
|
||||
|
||||
void CNextion::writeDMRInt(unsigned int slotNo, const std::string& src, bool group, const std::string& dst, const char* type)
|
||||
{
|
||||
assert(type != NULL);
|
||||
|
@ -262,21 +332,17 @@ void CNextion::writeDMRInt(unsigned int slotNo, const std::string& src, bool gro
|
|||
|
||||
|
||||
if (slotNo == 1U) {
|
||||
if (m_screenLayout & LAYOUT_TA_ENABLE) {
|
||||
if (m_screenLayout & LAYOUT_TA_COLOUR)
|
||||
sendCommand("t2.pco=0");
|
||||
if (m_screenLayout & LAYOUT_TA_FONTSIZE)
|
||||
sendCommand("t2.font=4");
|
||||
if (m_screenLayout == 2U) {
|
||||
sendCommand("t2.pco=0");
|
||||
sendCommand("t2.font=4");
|
||||
}
|
||||
|
||||
sendCommand("t2.txt=\"2 Listening\"");
|
||||
sendCommandAction(69U);
|
||||
} else {
|
||||
if (m_screenLayout & LAYOUT_TA_ENABLE) {
|
||||
if (m_screenLayout & LAYOUT_TA_COLOUR)
|
||||
sendCommand("t0.pco=0");
|
||||
if (m_screenLayout & LAYOUT_TA_FONTSIZE)
|
||||
sendCommand("t0.font=4");
|
||||
if (m_screenLayout == 2U) {
|
||||
sendCommand("t0.pco=0");
|
||||
sendCommand("t0.font=4");
|
||||
}
|
||||
|
||||
sendCommand("t0.txt=\"1 Listening\"");
|
||||
|
@ -293,11 +359,9 @@ void CNextion::writeDMRInt(unsigned int slotNo, const std::string& src, bool gro
|
|||
if (slotNo == 1U) {
|
||||
::sprintf(text, "t0.txt=\"1 %s %s\"", type, src.c_str());
|
||||
|
||||
if (m_screenLayout & LAYOUT_TA_ENABLE) {
|
||||
if (m_screenLayout & LAYOUT_TA_COLOUR)
|
||||
sendCommand("t0.pco=0");
|
||||
if (m_screenLayout & LAYOUT_TA_FONTSIZE)
|
||||
sendCommand("t0.font=4");
|
||||
if (m_screenLayout == 2U) {
|
||||
sendCommand("t0.pco=0");
|
||||
sendCommand("t0.font=4");
|
||||
}
|
||||
|
||||
sendCommand(text);
|
||||
|
@ -309,11 +373,9 @@ void CNextion::writeDMRInt(unsigned int slotNo, const std::string& src, bool gro
|
|||
} else {
|
||||
::sprintf(text, "t2.txt=\"2 %s %s\"", type, src.c_str());
|
||||
|
||||
if (m_screenLayout & LAYOUT_TA_ENABLE) {
|
||||
if (m_screenLayout & LAYOUT_TA_COLOUR)
|
||||
sendCommand("t2.pco=0");
|
||||
if (m_screenLayout & LAYOUT_TA_FONTSIZE)
|
||||
sendCommand("t2.font=4");
|
||||
if (m_screenLayout == 2U) {
|
||||
sendCommand("t2.pco=0");
|
||||
sendCommand("t2.font=4");
|
||||
}
|
||||
|
||||
sendCommand(text);
|
||||
|
@ -368,17 +430,15 @@ void CNextion::writeDMRRSSIInt(unsigned int slotNo, unsigned char rssi)
|
|||
|
||||
void CNextion::writeDMRTAInt(unsigned int slotNo, unsigned char* talkerAlias, const char* type)
|
||||
{
|
||||
if (!(m_screenLayout & LAYOUT_TA_ENABLE))
|
||||
if (m_screenLayout < 2U)
|
||||
return;
|
||||
|
||||
if (type[0] == ' ') {
|
||||
if (slotNo == 1U) {
|
||||
if (m_screenLayout & LAYOUT_TA_COLOUR)
|
||||
sendCommand("t0.pco=33808");
|
||||
if (m_screenLayout == 2U) sendCommand("t0.pco=33808");
|
||||
sendCommandAction(64U);
|
||||
} else {
|
||||
if (m_screenLayout & LAYOUT_TA_COLOUR)
|
||||
sendCommand("t2.pco=33808");
|
||||
if (m_screenLayout == 2U) sendCommand("t2.pco=33808");
|
||||
sendCommandAction(72U);
|
||||
}
|
||||
|
||||
|
@ -389,17 +449,16 @@ void CNextion::writeDMRTAInt(unsigned int slotNo, unsigned char* talkerAlias, co
|
|||
char text[50U];
|
||||
::sprintf(text, "t0.txt=\"1 %s %s\"", type, talkerAlias);
|
||||
|
||||
if (m_screenLayout & LAYOUT_TA_FONTSIZE) {
|
||||
if (m_screenLayout == 2U) {
|
||||
if (::strlen((char*)talkerAlias) > (16U-4U))
|
||||
sendCommand("t0.font=3");
|
||||
if (::strlen((char*)talkerAlias) > (20U-4U))
|
||||
sendCommand("t0.font=2");
|
||||
if (::strlen((char*)talkerAlias) > (24U-4U))
|
||||
sendCommand("t0.font=1");
|
||||
}
|
||||
|
||||
if (m_screenLayout & LAYOUT_TA_COLOUR)
|
||||
sendCommand("t0.pco=1024");
|
||||
}
|
||||
|
||||
sendCommand(text);
|
||||
sendCommandAction(63U);
|
||||
|
@ -407,18 +466,16 @@ void CNextion::writeDMRTAInt(unsigned int slotNo, unsigned char* talkerAlias, co
|
|||
char text[50U];
|
||||
::sprintf(text, "t2.txt=\"2 %s %s\"", type, talkerAlias);
|
||||
|
||||
if (m_screenLayout & LAYOUT_TA_FONTSIZE) {
|
||||
if (m_screenLayout == 2U) {
|
||||
if (::strlen((char*)talkerAlias) > (16U-4U))
|
||||
sendCommand("t2.font=3");
|
||||
if (::strlen((char*)talkerAlias) > (20U-4U))
|
||||
sendCommand("t2.font=2");
|
||||
if (::strlen((char*)talkerAlias) > (24U-4U))
|
||||
sendCommand("t2.font=1");
|
||||
}
|
||||
|
||||
if (m_screenLayout & LAYOUT_TA_COLOUR)
|
||||
sendCommand("t2.pco=1024");
|
||||
|
||||
}
|
||||
sendCommand(text);
|
||||
sendCommandAction(71U);
|
||||
}
|
||||
|
@ -460,11 +517,9 @@ void CNextion::clearDMRInt(unsigned int slotNo)
|
|||
sendCommand("t0.txt=\"1 Listening\"");
|
||||
sendCommandAction(61U);
|
||||
|
||||
if (m_screenLayout & LAYOUT_TA_ENABLE) {
|
||||
if (m_screenLayout & LAYOUT_TA_COLOUR)
|
||||
sendCommand("t0.pco=0");
|
||||
if (m_screenLayout & LAYOUT_TA_FONTSIZE)
|
||||
sendCommand("t0.font=4");
|
||||
if (m_screenLayout == 2U) {
|
||||
sendCommand("t0.pco=0");
|
||||
sendCommand("t0.font=4");
|
||||
}
|
||||
|
||||
sendCommand("t1.txt=\"\"");
|
||||
|
@ -474,11 +529,9 @@ void CNextion::clearDMRInt(unsigned int slotNo)
|
|||
sendCommand("t2.txt=\"2 Listening\"");
|
||||
sendCommandAction(69U);
|
||||
|
||||
if (m_screenLayout & LAYOUT_TA_ENABLE) {
|
||||
if (m_screenLayout & LAYOUT_TA_COLOUR)
|
||||
sendCommand("t2.pco=0");
|
||||
if (m_screenLayout & LAYOUT_TA_FONTSIZE)
|
||||
sendCommand("t2.font=4");
|
||||
if (m_screenLayout == 2U) {
|
||||
sendCommand("t2.pco=0");
|
||||
sendCommand("t2.font=4");
|
||||
}
|
||||
|
||||
sendCommand("t3.txt=\"\"");
|
||||
|
@ -487,6 +540,264 @@ void CNextion::clearDMRInt(unsigned int slotNo)
|
|||
}
|
||||
}
|
||||
|
||||
void CNextion::writeFusionInt(const char* source, const char* dest, const char* type, const char* origin)
|
||||
{
|
||||
assert(source != NULL);
|
||||
assert(dest != NULL);
|
||||
assert(type != NULL);
|
||||
assert(origin != NULL);
|
||||
|
||||
if (m_mode != MODE_YSF) {
|
||||
sendCommand("page YSF");
|
||||
sendCommandAction(4U);
|
||||
}
|
||||
|
||||
|
||||
char text[30U];
|
||||
if (m_brightness>0) {
|
||||
::sprintf(text, "dim=%u", m_brightness);
|
||||
sendCommand(text);
|
||||
}
|
||||
|
||||
::sprintf(text, "t0.txt=\"%s %.10s\"", type, source);
|
||||
sendCommand(text);
|
||||
sendCommandAction(82U);
|
||||
|
||||
::sprintf(text, "t1.txt=\"%.10s\"", dest);
|
||||
sendCommand(text);
|
||||
sendCommandAction(83U);
|
||||
if (::strcmp(origin, " ") != 0) {
|
||||
::sprintf(text, "t2.txt=\"at %.10s\"", origin);
|
||||
sendCommand(text);
|
||||
sendCommandAction(84U);
|
||||
}
|
||||
|
||||
m_clockDisplayTimer.stop();
|
||||
|
||||
m_mode = MODE_YSF;
|
||||
m_rssiAccum1 = 0U;
|
||||
m_berAccum1 = 0.0F;
|
||||
m_rssiCount1 = 0U;
|
||||
m_berCount1 = 0U;
|
||||
}
|
||||
|
||||
void CNextion::writeFusionRSSIInt(unsigned char rssi)
|
||||
{
|
||||
m_rssiAccum1 += rssi;
|
||||
m_rssiCount1++;
|
||||
|
||||
if (m_rssiCount1 == YSF_RSSI_COUNT) {
|
||||
char text[25U];
|
||||
::sprintf(text, "t3.txt=\"-%udBm\"", m_rssiAccum1 / YSF_RSSI_COUNT);
|
||||
sendCommand(text);
|
||||
sendCommandAction(85U);
|
||||
m_rssiAccum1 = 0U;
|
||||
m_rssiCount1 = 0U;
|
||||
}
|
||||
}
|
||||
|
||||
void CNextion::writeFusionBERInt(float ber)
|
||||
{
|
||||
m_berAccum1 += ber;
|
||||
m_berCount1++;
|
||||
|
||||
if (m_berCount1 == YSF_BER_COUNT) {
|
||||
char text[25U];
|
||||
::sprintf(text, "t4.txt=\"%.1f%%\"", m_berAccum1 / float(YSF_BER_COUNT));
|
||||
sendCommand(text);
|
||||
sendCommandAction(86U);
|
||||
m_berAccum1 = 0.0F;
|
||||
m_berCount1 = 0U;
|
||||
}
|
||||
}
|
||||
|
||||
void CNextion::clearFusionInt()
|
||||
{
|
||||
sendCommand("t0.txt=\"Listening\"");
|
||||
sendCommandAction(81U);
|
||||
sendCommand("t1.txt=\"\"");
|
||||
sendCommand("t2.txt=\"\"");
|
||||
sendCommand("t3.txt=\"\"");
|
||||
sendCommand("t4.txt=\"\"");
|
||||
}
|
||||
|
||||
void CNextion::writeP25Int(const char* source, bool group, unsigned int dest, const char* type)
|
||||
{
|
||||
assert(source != NULL);
|
||||
assert(type != NULL);
|
||||
|
||||
if (m_mode != MODE_P25) {
|
||||
sendCommand("page P25");
|
||||
sendCommandAction(5U);
|
||||
}
|
||||
|
||||
char text[30U];
|
||||
if (m_brightness>0) {
|
||||
::sprintf(text, "dim=%u", m_brightness);
|
||||
sendCommand(text);
|
||||
}
|
||||
|
||||
::sprintf(text, "t0.txt=\"%s %.10s\"", type, source);
|
||||
sendCommand(text);
|
||||
sendCommandAction(102U);
|
||||
|
||||
::sprintf(text, "t1.txt=\"%s%u\"", group ? "TG" : "", dest);
|
||||
sendCommand(text);
|
||||
sendCommandAction(103U);
|
||||
|
||||
m_clockDisplayTimer.stop();
|
||||
|
||||
m_mode = MODE_P25;
|
||||
m_rssiAccum1 = 0U;
|
||||
m_berAccum1 = 0.0F;
|
||||
m_rssiCount1 = 0U;
|
||||
m_berCount1 = 0U;
|
||||
}
|
||||
|
||||
void CNextion::writeP25RSSIInt(unsigned char rssi)
|
||||
{
|
||||
m_rssiAccum1 += rssi;
|
||||
m_rssiCount1++;
|
||||
|
||||
if (m_rssiCount1 == P25_RSSI_COUNT) {
|
||||
char text[25U];
|
||||
::sprintf(text, "t2.txt=\"-%udBm\"", m_rssiAccum1 / P25_RSSI_COUNT);
|
||||
sendCommand(text);
|
||||
sendCommandAction(104U);
|
||||
m_rssiAccum1 = 0U;
|
||||
m_rssiCount1 = 0U;
|
||||
}
|
||||
}
|
||||
|
||||
void CNextion::writeP25BERInt(float ber)
|
||||
{
|
||||
m_berAccum1 += ber;
|
||||
m_berCount1++;
|
||||
|
||||
if (m_berCount1 == P25_BER_COUNT) {
|
||||
char text[25U];
|
||||
::sprintf(text, "t3.txt=\"%.1f%%\"", m_berAccum1 / float(P25_BER_COUNT));
|
||||
sendCommand(text);
|
||||
sendCommandAction(105U);
|
||||
m_berAccum1 = 0.0F;
|
||||
m_berCount1 = 0U;
|
||||
}
|
||||
}
|
||||
|
||||
void CNextion::clearP25Int()
|
||||
{
|
||||
sendCommand("t0.txt=\"Listening\"");
|
||||
sendCommandAction(101U);
|
||||
sendCommand("t1.txt=\"\"");
|
||||
sendCommand("t2.txt=\"\"");
|
||||
sendCommand("t3.txt=\"\"");
|
||||
}
|
||||
|
||||
void CNextion::writeNXDNInt(const char* source, bool group, unsigned int dest, const char* type)
|
||||
{
|
||||
assert(source != NULL);
|
||||
assert(type != NULL);
|
||||
|
||||
if (m_mode != MODE_NXDN) {
|
||||
sendCommand("page NXDN");
|
||||
sendCommandAction(6U);
|
||||
}
|
||||
|
||||
char text[30U];
|
||||
if (m_brightness>0) {
|
||||
::sprintf(text, "dim=%u", m_brightness);
|
||||
sendCommand(text);
|
||||
}
|
||||
|
||||
::sprintf(text, "t0.txt=\"%s %.10s\"", type, source);
|
||||
sendCommand(text);
|
||||
sendCommandAction(122U);
|
||||
|
||||
::sprintf(text, "t1.txt=\"%s%u\"", group ? "TG" : "", dest);
|
||||
sendCommand(text);
|
||||
sendCommandAction(123U);
|
||||
|
||||
m_clockDisplayTimer.stop();
|
||||
|
||||
m_mode = MODE_NXDN;
|
||||
m_rssiAccum1 = 0U;
|
||||
m_berAccum1 = 0.0F;
|
||||
m_rssiCount1 = 0U;
|
||||
m_berCount1 = 0U;
|
||||
}
|
||||
|
||||
void CNextion::writeNXDNRSSIInt(unsigned char rssi)
|
||||
{
|
||||
m_rssiAccum1 += rssi;
|
||||
m_rssiCount1++;
|
||||
|
||||
if (m_rssiCount1 == NXDN_RSSI_COUNT) {
|
||||
char text[25U];
|
||||
::sprintf(text, "t2.txt=\"-%udBm\"", m_rssiAccum1 / NXDN_RSSI_COUNT);
|
||||
sendCommand(text);
|
||||
sendCommandAction(124U);
|
||||
m_rssiAccum1 = 0U;
|
||||
m_rssiCount1 = 0U;
|
||||
}
|
||||
}
|
||||
|
||||
void CNextion::writeNXDNBERInt(float ber)
|
||||
{
|
||||
m_berAccum1 += ber;
|
||||
m_berCount1++;
|
||||
|
||||
if (m_berCount1 == NXDN_BER_COUNT) {
|
||||
char text[25U];
|
||||
::sprintf(text, "t3.txt=\"%.1f%%\"", m_berAccum1 / float(NXDN_BER_COUNT));
|
||||
sendCommand(text);
|
||||
sendCommandAction(125U);
|
||||
m_berAccum1 = 0.0F;
|
||||
m_berCount1 = 0U;
|
||||
}
|
||||
}
|
||||
|
||||
void CNextion::clearNXDNInt()
|
||||
{
|
||||
sendCommand("t0.txt=\"Listening\"");
|
||||
sendCommandAction(121U);
|
||||
sendCommand("t1.txt=\"\"");
|
||||
sendCommand("t2.txt=\"\"");
|
||||
sendCommand("t3.txt=\"\"");
|
||||
}
|
||||
|
||||
void CNextion::writePOCSAGInt(uint32_t ric, const std::string& message)
|
||||
{
|
||||
if (m_mode != MODE_POCSAG) {
|
||||
sendCommand("page POCSAG");
|
||||
sendCommandAction(7U);
|
||||
}
|
||||
|
||||
char text[200U];
|
||||
if (m_brightness>0) {
|
||||
::sprintf(text, "dim=%u", m_brightness);
|
||||
sendCommand(text);
|
||||
}
|
||||
|
||||
::sprintf(text, "t0.txt=\"RIC: %u\"", ric);
|
||||
sendCommand(text);
|
||||
sendCommandAction(132U);
|
||||
|
||||
::sprintf(text, "t1.txt=\"%s\"", message.c_str());
|
||||
sendCommand(text);
|
||||
sendCommandAction(133U);
|
||||
|
||||
m_clockDisplayTimer.stop();
|
||||
|
||||
m_mode = MODE_POCSAG;
|
||||
}
|
||||
|
||||
void CNextion::clearPOCSAGInt()
|
||||
{
|
||||
sendCommand("t0.txt=\"Waiting\"");
|
||||
sendCommandAction(134U);
|
||||
sendCommand("t1.txt=\"\"");
|
||||
}
|
||||
|
||||
void CNextion::writeCWInt()
|
||||
{
|
||||
sendCommand("t1.txt=\"Sending CW Ident\"");
|
||||
|
@ -533,7 +844,7 @@ void CNextion::close()
|
|||
|
||||
void CNextion::sendCommandAction(unsigned int status)
|
||||
{
|
||||
if (!(m_screenLayout & LAYOUT_DIY))
|
||||
if (m_screenLayout<3U)
|
||||
return;
|
||||
|
||||
char text[30U];
|
||||
|
@ -552,4 +863,4 @@ void CNextion::sendCommand(const char* command)
|
|||
// we must add a bit of a delay to allow the display to process the commands, else some are getting mangled.
|
||||
// 10 ms is just a guess, but seems to be sufficient.
|
||||
CThread::sleep(10U);
|
||||
}
|
||||
}
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue