Merge pull request #33 from AndyTaylorTweet/master

This is all based on wok by @nostar and help from @g4klx;
This commit is contained in:
Andy CA6JAU 2020-06-13 15:46:15 -04:00 committed by GitHub
commit 9276cbcc71
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
21 changed files with 730 additions and 242 deletions

View File

@ -43,6 +43,17 @@ m_dstPort(0U),
m_localAddress(), m_localAddress(),
m_localPort(0U), m_localPort(0U),
m_fcsFile(), m_fcsFile(),
m_fichCallSign(2U),
m_fichCallMode(0U),
m_fichFrameTotal(7U),
m_fichMessageRoute(0U),
m_fichVOIP(0U),
m_fichDataType(2U),
m_fichSQLType(0U),
m_fichSQLCode(0U),
m_ysfDT1(),
m_ysfDT2(),
m_ysfRadioID("*****"),
m_daemon(false), m_daemon(false),
m_debug(false), m_debug(false),
m_dmrId(0U), m_dmrId(0U),
@ -107,6 +118,7 @@ bool CConf::read()
// Remove quotes from the value // Remove quotes from the value
size_t len = ::strlen(value); size_t len = ::strlen(value);
char *t;
if (len > 1U && *value == '"' && value[len - 1U] == '"') { if (len > 1U && *value == '"' && value[len - 1U] == '"') {
value[len - 1U] = '\0'; value[len - 1U] = '\0';
value++; value++;
@ -132,7 +144,32 @@ bool CConf::read()
m_daemon = ::atoi(value) == 1; m_daemon = ::atoi(value) == 1;
else if (::strcmp(key, "Debug") == 0) else if (::strcmp(key, "Debug") == 0)
m_debug = ::atoi(value) == 1; m_debug = ::atoi(value) == 1;
} else if (section == SECTION_DMR_NETWORK) { else if (::strcmp(key, "RadioID") == 0)
m_ysfRadioID = value;
else if (::strcmp(key, "FICHCallsign") == 0)
m_fichCallSign = ::atoi(value);
else if (::strcmp(key, "FICHCallMode") == 0)
m_fichCallMode = ::atoi(value);
else if (::strcmp(key, "FICHFrameTotal") == 0)
m_fichFrameTotal = ::atoi(value);
else if (::strcmp(key, "FICHMessageRoute") == 0)
m_fichMessageRoute = ::atoi(value);
else if (::strcmp(key, "FICHVOIP") == 0)
m_fichVOIP = ::atoi(value);
else if (::strcmp(key, "FICHDataType") == 0)
m_fichDataType = ::atoi(value);
else if (::strcmp(key, "FICHSQLType") == 0)
m_fichSQLType = ::atoi(value);
else if (::strcmp(key, "FICHSQLCode") == 0)
m_fichSQLCode = ::atoi(value);
else if (::strcmp(key, "DT1") == 0){
while ((t = strtok_r(value, ",", &value)) != NULL)
m_ysfDT1.push_back(::atoi(t));
} else if (::strcmp(key, "DT2") == 0){
while ((t = strtok_r(value, ",", &value)) != NULL)
m_ysfDT2.push_back(::atoi(t));
}
} else if (section == SECTION_DMR_NETWORK) {
if (::strcmp(key, "Id") == 0) if (::strcmp(key, "Id") == 0)
m_dmrId = (unsigned int)::atoi(value); m_dmrId = (unsigned int)::atoi(value);
else if (::strcmp(key, "RptAddress") == 0) else if (::strcmp(key, "RptAddress") == 0)
@ -213,6 +250,61 @@ bool CConf::getDebug() const
return m_debug; return m_debug;
} }
unsigned char CConf::getFICHCallSign() const
{
return m_fichCallSign;
}
unsigned char CConf::getFICHCallMode() const
{
return m_fichCallMode;
}
unsigned char CConf::getFICHFrameTotal() const
{
return m_fichFrameTotal;
}
unsigned char CConf::getFICHMessageRoute() const
{
return m_fichMessageRoute;
}
unsigned char CConf::getFICHVOIP() const
{
return m_fichVOIP;
}
unsigned char CConf::getFICHDataType() const
{
return m_fichDataType;
}
unsigned char CConf::getFICHSQLType() const
{
return m_fichSQLType;
}
unsigned char CConf::getFICHSQLCode() const
{
return m_fichSQLCode;
}
std::vector<unsigned char> CConf::getYsfDT1()
{
return m_ysfDT1;
}
std::vector<unsigned char> CConf::getYsfDT2()
{
return m_ysfDT2;
}
std::string CConf::getYsfRadioID()
{
return m_ysfRadioID;
}
unsigned int CConf::getDMRId() const unsigned int CConf::getDMRId() const
{ {
return m_dmrId; return m_dmrId;

View File

@ -38,6 +38,17 @@ public:
std::string getLocalAddress() const; std::string getLocalAddress() const;
unsigned int getLocalPort() const; unsigned int getLocalPort() const;
std::string getFCSFile() const; std::string getFCSFile() const;
unsigned char getFICHCallSign() const;
unsigned char getFICHCallMode() const;
unsigned char getFICHFrameTotal() const;
unsigned char getFICHMessageRoute() const;
unsigned char getFICHVOIP() const;
unsigned char getFICHDataType() const;
unsigned char getFICHSQLType() const;
unsigned char getFICHSQLCode() const;
std::vector<unsigned char> getYsfDT1();
std::vector<unsigned char> getYsfDT2();
std::string getYsfRadioID();
bool getDaemon() const; bool getDaemon() const;
bool getDebug() const; bool getDebug() const;
@ -70,6 +81,17 @@ private:
std::string m_localAddress; std::string m_localAddress;
unsigned int m_localPort; unsigned int m_localPort;
std::string m_fcsFile; std::string m_fcsFile;
unsigned char m_fichCallSign;
unsigned char m_fichCallMode;
unsigned char m_fichFrameTotal;
unsigned char m_fichMessageRoute;
unsigned char m_fichVOIP;
unsigned char m_fichDataType;
unsigned char m_fichSQLType;
unsigned char m_fichSQLCode;
std::vector<unsigned char> m_ysfDT1;
std::vector<unsigned char> m_ysfDT2;
std::string m_ysfRadioID;
bool m_daemon; bool m_daemon;
bool m_debug; bool m_debug;
@ -90,7 +112,6 @@ private:
unsigned int m_logFileLevel; unsigned int m_logFileLevel;
std::string m_logFilePath; std::string m_logFilePath;
std::string m_logFileRoot; std::string m_logFileRoot;
}; };
#endif #endif

View File

@ -33,9 +33,6 @@
const unsigned char dt1_temp[] = {0x31, 0x22, 0x62, 0x5F, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00}; const unsigned char dt1_temp[] = {0x31, 0x22, 0x62, 0x5F, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00};
const unsigned char dt2_temp[] = {0x00, 0x00, 0x00, 0x00, 0x6C, 0x20, 0x1C, 0x20, 0x03, 0x08}; const unsigned char dt2_temp[] = {0x00, 0x00, 0x00, 0x00, 0x6C, 0x20, 0x1C, 0x20, 0x03, 0x08};
// Added by AD8DP for FICH FT=6 transmissions
const uint8_t dt1[10] = {0x01, 0x22, 0x61, 0x5f, 0x2b, 0x03, 0x11, 0x00, 0x00, 0x00};
const unsigned char CONN_RESP[] = {0x5DU, 0x41U, 0x5FU, 0x26U}; const unsigned char CONN_RESP[] = {0x5DU, 0x41U, 0x5FU, 0x26U};
#define DMR_FRAME_PER 55U #define DMR_FRAME_PER 55U
@ -51,7 +48,6 @@ const char* HEADER1 = "This software is for use on amateur radio networks only,"
const char* HEADER2 = "it is to be used for educational purposes only. Its use on"; const char* HEADER2 = "it is to be used for educational purposes only. Its use on";
const char* HEADER3 = "commercial networks is strictly prohibited."; const char* HEADER3 = "commercial networks is strictly prohibited.";
const char* HEADER4 = "Copyright(C) 2018 by CA6JAU, G4KLX and others"; const char* HEADER4 = "Copyright(C) 2018 by CA6JAU, G4KLX and others";
const char ysf_radioid[] = {'H', '5', '0', '0', '0'};
#include <functional> #include <functional>
#include <algorithm> #include <algorithm>
@ -652,23 +648,24 @@ int CDMR2YSF::run()
// Set the FICH // Set the FICH
CYSFFICH fich; CYSFFICH fich;
fich.setFI(YSF_FI_HEADER); fich.setFI(YSF_FI_HEADER);
fich.setCS(2U); fich.setCS(m_conf.getFICHCallSign());
fich.setCM(1U); fich.setCM(m_conf.getFICHCallMode());
fich.setBN(0U); fich.setBN(0U);
fich.setBT(0U); fich.setBT(0U);
fich.setFN(0U); fich.setFN(0U);
fich.setFT(6U); fich.setFT(m_conf.getFICHFrameTotal());
fich.setDev(0U); fich.setDev(0U);
fich.setMR(0U); fich.setMR(m_conf.getFICHMessageRoute());
fich.setVoIP(false); fich.setVoIP(m_conf.getFICHVOIP());
fich.setDT(YSF_DT_VD_MODE2); fich.setDT(m_conf.getFICHDataType());
fich.setSQL(0U); fich.setSQL(m_conf.getFICHSQLType());
fich.setSQ(0U); fich.setSQ(m_conf.getFICHSQLCode());
fich.encode(m_ysfFrame + 35U); fich.encode(m_ysfFrame + 35U);
unsigned char csd1[20U], csd2[20U]; unsigned char csd1[20U], csd2[20U];
memset(csd1, '*', YSF_CALLSIGN_LENGTH/2); memset(csd1, '*', YSF_CALLSIGN_LENGTH);
memcpy(csd1 + YSF_CALLSIGN_LENGTH/2, ysf_radioid, YSF_CALLSIGN_LENGTH/2); memset(csd1, '*', YSF_CALLSIGN_LENGTH/2);
memcpy(csd1 + YSF_CALLSIGN_LENGTH/2, m_conf.getYsfRadioID().c_str(), YSF_CALLSIGN_LENGTH/2);
memcpy(csd1 + YSF_CALLSIGN_LENGTH, m_netSrc.c_str(), YSF_CALLSIGN_LENGTH); memcpy(csd1 + YSF_CALLSIGN_LENGTH, m_netSrc.c_str(), YSF_CALLSIGN_LENGTH);
memset(csd2, ' ', YSF_CALLSIGN_LENGTH + YSF_CALLSIGN_LENGTH); memset(csd2, ' ', YSF_CALLSIGN_LENGTH + YSF_CALLSIGN_LENGTH);
@ -676,7 +673,7 @@ int CDMR2YSF::run()
payload.writeHeader(m_ysfFrame + 35U, csd1, csd2); payload.writeHeader(m_ysfFrame + 35U, csd1, csd2);
m_ysfNetwork->write(m_ysfFrame); m_ysfNetwork->write(m_ysfFrame);
ysf_cnt++; ysf_cnt++;
ysfWatch.start(); ysfWatch.start();
} }
@ -693,23 +690,23 @@ int CDMR2YSF::run()
// Set the FICH // Set the FICH
CYSFFICH fich; CYSFFICH fich;
fich.setFI(YSF_FI_TERMINATOR); fich.setFI(YSF_FI_TERMINATOR);
fich.setCS(2U); fich.setCS(m_conf.getFICHCallSign());
fich.setCM(1U); fich.setCM(m_conf.getFICHCallMode());
fich.setBN(0U); fich.setBN(0U);
fich.setBT(0U); fich.setBT(0U);
fich.setFN(0U); fich.setFN(0U);
fich.setFT(6U); fich.setFT(m_conf.getFICHFrameTotal());
fich.setDev(0U); fich.setDev(0U);
fich.setMR(0U); fich.setMR(m_conf.getFICHMessageRoute());
fich.setVoIP(false); fich.setVoIP(m_conf.getFICHVOIP());
fich.setDT(YSF_DT_VD_MODE2); fich.setDT(m_conf.getFICHDataType());
fich.setSQL(0U); fich.setSQL(m_conf.getFICHSQLType());
fich.setSQ(0U); fich.setSQ(m_conf.getFICHSQLCode());
fich.encode(m_ysfFrame + 35U); fich.encode(m_ysfFrame + 35U);
unsigned char csd1[20U], csd2[20U]; unsigned char csd1[20U], csd2[20U];
memset(csd1, '*', YSF_CALLSIGN_LENGTH/2); memset(csd1, '*', YSF_CALLSIGN_LENGTH/2);
memcpy(csd1 + YSF_CALLSIGN_LENGTH/2, ysf_radioid, YSF_CALLSIGN_LENGTH/2); memcpy(csd1 + YSF_CALLSIGN_LENGTH/2, m_conf.getYsfRadioID().c_str(), YSF_CALLSIGN_LENGTH/2);
memcpy(csd1 + YSF_CALLSIGN_LENGTH, m_netSrc.c_str(), YSF_CALLSIGN_LENGTH); memcpy(csd1 + YSF_CALLSIGN_LENGTH, m_netSrc.c_str(), YSF_CALLSIGN_LENGTH);
memset(csd2, ' ', YSF_CALLSIGN_LENGTH + YSF_CALLSIGN_LENGTH); memset(csd2, ' ', YSF_CALLSIGN_LENGTH + YSF_CALLSIGN_LENGTH);
@ -724,7 +721,7 @@ int CDMR2YSF::run()
CYSFPayload ysfPayload; CYSFPayload ysfPayload;
unsigned char dch[10U]; unsigned char dch[10U];
unsigned int fn = (ysf_cnt - 1U) % 7U; unsigned int fn = (ysf_cnt - 1U) % (m_conf.getFICHFrameTotal() + 1);
::memcpy(m_ysfFrame + 0U, "YSFD", 4U); ::memcpy(m_ysfFrame + 0U, "YSFD", 4U);
::memcpy(m_ysfFrame + 4U, m_ysfNetwork->getCallsign().c_str(), YSF_CALLSIGN_LENGTH); ::memcpy(m_ysfFrame + 4U, m_ysfNetwork->getCallsign().c_str(), YSF_CALLSIGN_LENGTH);
@ -737,44 +734,52 @@ int CDMR2YSF::run()
switch (fn) { switch (fn) {
case 0: case 0:
memset(dch, '*', YSF_CALLSIGN_LENGTH/2); memset(dch, '*', YSF_CALLSIGN_LENGTH/2);
memcpy(dch + YSF_CALLSIGN_LENGTH/2, ysf_radioid, YSF_CALLSIGN_LENGTH/2); memcpy(dch + YSF_CALLSIGN_LENGTH/2, m_conf.getYsfRadioID().c_str(), YSF_CALLSIGN_LENGTH/2);
ysfPayload.writeVDMode2Data(m_ysfFrame + 35U, dch); ysfPayload.writeVDMode2Data(m_ysfFrame + 35U, dch);
break; break;
case 1: case 1:
ysfPayload.writeVDMode2Data(m_ysfFrame + 35U, (const unsigned char*)m_netSrc.c_str()); ysfPayload.writeVDMode2Data(m_ysfFrame + 35U, (unsigned char*)m_netSrc.c_str());
break; break;
case 2: case 2:
ysfPayload.writeVDMode2Data(m_ysfFrame + 35U, (const unsigned char*)m_netDst.c_str()); ysfPayload.writeVDMode2Data(m_ysfFrame + 35U, (unsigned char*)m_netDst.c_str());
break; break;
case 5: case 5:
memset(dch, ' ', YSF_CALLSIGN_LENGTH/2); memset(dch, ' ', YSF_CALLSIGN_LENGTH/2);
memcpy(dch + YSF_CALLSIGN_LENGTH/2, ysf_radioid, YSF_CALLSIGN_LENGTH/2); memcpy(dch + YSF_CALLSIGN_LENGTH/2, m_conf.getYsfRadioID().c_str(), YSF_CALLSIGN_LENGTH/2);
ysfPayload.writeVDMode2Data(m_ysfFrame + 35U, dch); // Rem3/4 ysfPayload.writeVDMode2Data(m_ysfFrame + 35U, dch); // Rem3/4
break;
case 6: {
unsigned char dt1[10U] = {0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U};
for (unsigned int i = 0U; i < m_conf.getYsfDT1().size() && i < 10U; i++)
dt1[i] = m_conf.getYsfDT1()[i];
ysfPayload.writeVDMode2Data(m_ysfFrame + 35U, dt1);
}
break; break;
case 6: case 7: {
ysfPayload.writeVDMode2Data(m_ysfFrame + 35U, dt1); unsigned char dt2[10U] = {0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U};
break; for (unsigned int i = 0U; i < m_conf.getYsfDT2().size() && i < 10U; i++)
case 7: dt2[i] = m_conf.getYsfDT2()[i];
ysfPayload.writeVDMode2Data(m_ysfFrame + 35U, dt2_temp); ysfPayload.writeVDMode2Data(m_ysfFrame + 35U, dt2);
}
break; break;
default: default:
ysfPayload.writeVDMode2Data(m_ysfFrame + 35U, (const unsigned char*)" "); ysfPayload.writeVDMode2Data(m_ysfFrame + 35U, (const unsigned char*)" ");
} }
// Set the FICH // Set the FICH
fich.setFI(YSF_FI_COMMUNICATIONS); fich.setFI(YSF_FI_COMMUNICATIONS);
fich.setCS(2U); fich.setCS(m_conf.getFICHCallSign());
fich.setCM(1U); fich.setCM(m_conf.getFICHCallMode());
fich.setBN(0U); fich.setBN(0U);
fich.setBT(0U); fich.setBT(0U);
fich.setFN(fn); fich.setFN(fn);
fich.setFT(6U); fich.setFT(m_conf.getFICHFrameTotal());
fich.setDev(0U); fich.setDev(0U);
fich.setMR(0U); fich.setMR(m_conf.getFICHMessageRoute());
fich.setVoIP(false); fich.setVoIP(m_conf.getFICHVOIP());
fich.setDT(YSF_DT_VD_MODE2); fich.setDT(m_conf.getFICHDataType());
fich.setSQL(0U); fich.setSQL(m_conf.getFICHSQLType());
fich.setSQ(0U); fich.setSQ(m_conf.getFICHSQLCode());
fich.encode(m_ysfFrame + 35U); fich.encode(m_ysfFrame + 35U);
// Net frame counter // Net frame counter
@ -782,7 +787,7 @@ int CDMR2YSF::run()
// Send data // Send data
m_ysfNetwork->write(m_ysfFrame); m_ysfNetwork->write(m_ysfFrame);
ysf_cnt++; ysf_cnt++;
ysfWatch.start(); ysfWatch.start();
} }
@ -901,7 +906,7 @@ unsigned int CDMR2YSF::findYSFID(std::string cs, bool showdst)
int mid1 = cs.find_last_of('-'); int mid1 = cs.find_last_of('-');
int mid2 = cs.find_last_of('/'); int mid2 = cs.find_last_of('/');
int last = cs.find_last_not_of(' '); int last = cs.find_last_not_of(' ');
if (mid1 == -1 && mid2 == -1 && first == -1 && last == -1) if (mid1 == -1 && mid2 == -1 && first == -1 && last == -1)
cstrim = "N0CALL"; cstrim = "N0CALL";
else if (mid1 == -1 && mid2 == -1) else if (mid1 == -1 && mid2 == -1)
@ -923,9 +928,9 @@ unsigned int CDMR2YSF::findYSFID(std::string cs, bool showdst)
if (id == 0) { if (id == 0) {
id = m_defsrcid; id = m_defsrcid;
if (showdst) if (showdst)
LogMessage("Not DMR ID found, using default ID: %u, DstID: %s%u", id, dmrpc ? "" : "TG ", m_dstid); LogMessage("DMR ID not found, using default ID: %u, DstID: %s%u", id, dmrpc ? "" : "TG ", m_dstid);
else else
LogMessage("Not DMR ID found, using default ID: %u", id); LogMessage("DMR ID not found, using default ID: %u", id);
} }
else { else {
if (showdst) if (showdst)
@ -943,10 +948,10 @@ std::string CDMR2YSF::getSrcYSF(const unsigned char* buffer)
::memcpy(temp, buffer + 14U, YSF_CALLSIGN_LENGTH); ::memcpy(temp, buffer + 14U, YSF_CALLSIGN_LENGTH);
temp[YSF_CALLSIGN_LENGTH] = 0U; temp[YSF_CALLSIGN_LENGTH] = 0U;
std::string trimmed = reinterpret_cast<char const*>(temp); std::string trimmed = reinterpret_cast<char const*>(temp);
trimmed.erase(std::find_if(trimmed.rbegin(), trimmed.rend(), std::not1(std::ptr_fun<int, int>(std::isspace))).base(), trimmed.end()); trimmed.erase(std::find_if(trimmed.rbegin(), trimmed.rend(), std::not1(std::ptr_fun<int, int>(std::isspace))).base(), trimmed.end());
return trimmed; return trimmed;
} }

View File

@ -5,6 +5,17 @@ GatewayPort=4200
LocalAddress=127.0.0.1 LocalAddress=127.0.0.1
LocalPort=3200 LocalPort=3200
FCSRooms=FCSRooms.txt FCSRooms=FCSRooms.txt
# RadioID=*****
# FICHCallsign=2
# FICHCallMode=0
# FICHFrameTotal=7
# FICHMessageRoute=0
# FICHVOIP=0
# FICHDataType=2
# FICHSQLType=0
# FICHSQLCode=0
DT1=49,34,98,95,41,0,0,0,0,0
DT2=0,0,0,0,108,32,28,32,3,8
Daemon=0 Daemon=0
Debug=0 Debug=0

View File

@ -20,6 +20,6 @@
#if !defined(VERSION_H) #if !defined(VERSION_H)
#define VERSION_H #define VERSION_H
const char* VERSION = "20200503"; const char* VERSION = "20200605";
#endif #endif

View File

@ -25,7 +25,7 @@
#include <cstdint> #include <cstdint>
const unsigned int INTERLEAVE_TABLE_9_20[] = { const unsigned int INTERLEAVE_TABLE_9_20[] = {
0U, 40U, 80U, 120U, 160U, 200U, 240U, 280U, 320U, 0U, 40U, 80U, 120U, 160U, 200U, 240U, 280U, 320U,
2U, 42U, 82U, 122U, 162U, 202U, 242U, 282U, 322U, 2U, 42U, 82U, 122U, 162U, 202U, 242U, 282U, 322U,
4U, 44U, 84U, 124U, 164U, 204U, 244U, 284U, 324U, 4U, 44U, 84U, 124U, 164U, 204U, 244U, 284U, 324U,
6U, 46U, 86U, 126U, 166U, 206U, 246U, 286U, 326U, 6U, 46U, 86U, 126U, 166U, 206U, 246U, 286U, 326U,
@ -609,7 +609,7 @@ std::string CYSFPayload::getDest()
std::string tmp; std::string tmp;
if (m_dest) if (m_dest)
tmp.assign((const char *)m_dest, YSF_CALLSIGN_LENGTH); tmp.assign((const char *)m_dest, 5);
else else
tmp = ""; tmp = "";

View File

@ -50,6 +50,17 @@ m_enableWiresX(false),
m_remoteGateway(false), m_remoteGateway(false),
m_hangTime(1000U), m_hangTime(1000U),
m_wiresXMakeUpper(true), m_wiresXMakeUpper(true),
m_fichCallSign(2U),
m_fichCallMode(0U),
m_fichFrameTotal(7U),
m_fichMessageRoute(0U),
m_fichVOIP(0U),
m_fichDataType(2U),
m_fichSQLType(0U),
m_fichSQLCode(0U),
m_ysfDT1(),
m_ysfDT2(),
m_ysfRadioID("*****"),
m_daemon(false), m_daemon(false),
m_rxFrequency(0U), m_rxFrequency(0U),
m_txFrequency(0U), m_txFrequency(0U),
@ -142,6 +153,7 @@ bool CConf::read()
// Remove quotes from the value // Remove quotes from the value
size_t len = ::strlen(value); size_t len = ::strlen(value);
char *t;
if (len > 1U && *value == '"' && value[len - 1U] == '"') { if (len > 1U && *value == '"' && value[len - 1U] == '"') {
value[len - 1U] = '\0'; value[len - 1U] = '\0';
value++; value++;
@ -176,6 +188,31 @@ bool CConf::read()
m_wiresXMakeUpper = ::atoi(value) == 1; m_wiresXMakeUpper = ::atoi(value) == 1;
else if (::strcmp(key, "Daemon") == 0) else if (::strcmp(key, "Daemon") == 0)
m_daemon = ::atoi(value) == 1; m_daemon = ::atoi(value) == 1;
else if (::strcmp(key, "RadioID") == 0)
m_ysfRadioID = value;
else if (::strcmp(key, "FICHCallsign") == 0)
m_fichCallSign = ::atoi(value);
else if (::strcmp(key, "FICHCallMode") == 0)
m_fichCallMode = ::atoi(value);
else if (::strcmp(key, "FICHFrameTotal") == 0)
m_fichFrameTotal = ::atoi(value);
else if (::strcmp(key, "FICHMessageRoute") == 0)
m_fichMessageRoute = ::atoi(value);
else if (::strcmp(key, "FICHVOIP") == 0)
m_fichVOIP = ::atoi(value);
else if (::strcmp(key, "FICHDataType") == 0)
m_fichDataType = ::atoi(value);
else if (::strcmp(key, "FICHSQLType") == 0)
m_fichSQLType = ::atoi(value);
else if (::strcmp(key, "FICHSQLCode") == 0)
m_fichSQLCode = ::atoi(value);
else if (::strcmp(key, "DT1") == 0){
while ((t = strtok_r(value, ",", &value)) != NULL)
m_ysfDT1.push_back(::atoi(t));
} else if (::strcmp(key, "DT2") == 0){
while ((t = strtok_r(value, ",", &value)) != NULL)
m_ysfDT2.push_back(::atoi(t));
}
} else if (section == SECTION_INFO) { } else if (section == SECTION_INFO) {
if (::strcmp(key, "TXFrequency") == 0) if (::strcmp(key, "TXFrequency") == 0)
m_txFrequency = (unsigned int)::atoi(value); m_txFrequency = (unsigned int)::atoi(value);
@ -334,6 +371,61 @@ bool CConf::getDaemon() const
return m_daemon; return m_daemon;
} }
unsigned char CConf::getFICHCallSign() const
{
return m_fichCallSign;
}
unsigned char CConf::getFICHCallMode() const
{
return m_fichCallMode;
}
unsigned char CConf::getFICHFrameTotal() const
{
return m_fichFrameTotal;
}
unsigned char CConf::getFICHMessageRoute() const
{
return m_fichMessageRoute;
}
unsigned char CConf::getFICHVOIP() const
{
return m_fichVOIP;
}
unsigned char CConf::getFICHDataType() const
{
return m_fichDataType;
}
unsigned char CConf::getFICHSQLType() const
{
return m_fichSQLType;
}
unsigned char CConf::getFICHSQLCode() const
{
return m_fichSQLCode;
}
std::vector<unsigned char> CConf::getYsfDT1()
{
return m_ysfDT1;
}
std::vector<unsigned char> CConf::getYsfDT2()
{
return m_ysfDT2;
}
std::string CConf::getYsfRadioID()
{
return m_ysfRadioID;
}
unsigned int CConf::getRxFrequency() const unsigned int CConf::getRxFrequency() const
{ {
return m_rxFrequency; return m_rxFrequency;

View File

@ -43,7 +43,21 @@ public:
bool getRemoteGateway() const; bool getRemoteGateway() const;
unsigned int getHangTime() const; unsigned int getHangTime() const;
bool getWiresXMakeUpper() const; bool getWiresXMakeUpper() const;
bool getDaemon() const; unsigned char getFICHCallSign() const;
unsigned char getFICHCallMode() const;
unsigned char getFICHFrameTotal() const;
unsigned char getFICHMessageRoute() const;
unsigned char getFICHVOIP() const;
unsigned char getFICHDataType() const;
unsigned char getFICHSQLType() const;
unsigned char getFICHSQLCode() const;
std::vector<unsigned char> getYsfDT1();
std::vector<unsigned char> getYsfDT2();
std::string getYsfRadioID();
unsigned char* getYsfDT1();
unsigned char* getYsfDT2();
char* getYsfRadioID();
bool getDaemon() const;
// The Info section // The Info section
unsigned int getRxFrequency() const; unsigned int getRxFrequency() const;
@ -109,6 +123,17 @@ private:
bool m_remoteGateway; bool m_remoteGateway;
unsigned int m_hangTime; unsigned int m_hangTime;
bool m_wiresXMakeUpper; bool m_wiresXMakeUpper;
unsigned char m_fichCallSign;
unsigned char m_fichCallMode;
unsigned char m_fichFrameTotal;
unsigned char m_fichMessageRoute;
unsigned char m_fichVOIP;
unsigned char m_fichDataType;
unsigned char m_fichSQLType;
unsigned char m_fichSQLCode;
std::vector<unsigned char> m_ysfDT1;
std::vector<unsigned char> m_ysfDT2;
std::string m_ysfRadioID;
bool m_daemon; bool m_daemon;
unsigned int m_rxFrequency; unsigned int m_rxFrequency;
@ -148,7 +173,7 @@ private:
unsigned int m_logFileLevel; unsigned int m_logFileLevel;
std::string m_logFilePath; std::string m_logFilePath;
std::string m_logFileRoot; std::string m_logFileRoot;
bool m_aprsEnabled; bool m_aprsEnabled;
std::string m_aprsServer; std::string m_aprsServer;
unsigned int m_aprsPort; unsigned int m_aprsPort;
@ -157,7 +182,6 @@ private:
std::string m_aprsAPIKey; std::string m_aprsAPIKey;
unsigned int m_aprsRefresh; unsigned int m_aprsRefresh;
std::string m_aprsDescription; std::string m_aprsDescription;
}; };
#endif #endif

View File

@ -20,6 +20,6 @@
#if !defined(VERSION_H) #if !defined(VERSION_H)
#define VERSION_H #define VERSION_H
const char* VERSION = "20200503"; const char* VERSION = "20200605";
#endif #endif

View File

@ -33,7 +33,6 @@
// DT1 and DT2, suggested by Manuel EA7EE // DT1 and DT2, suggested by Manuel EA7EE
const unsigned char dt1_temp[] = {0x31, 0x22, 0x62, 0x5F, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00}; const unsigned char dt1_temp[] = {0x31, 0x22, 0x62, 0x5F, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00};
const unsigned char dt2_temp[] = {0x00, 0x00, 0x00, 0x00, 0x6C, 0x20, 0x1C, 0x20, 0x03, 0x08}; const unsigned char dt2_temp[] = {0x00, 0x00, 0x00, 0x00, 0x6C, 0x20, 0x1C, 0x20, 0x03, 0x08};
const uint8_t dt1[10] = {0x01, 0x22, 0x61, 0x5f, 0x2b, 0x03, 0x11, 0x00, 0x00, 0x00};
#define DMR_FRAME_PER 55U #define DMR_FRAME_PER 55U
#define YSF_FRAME_PER 90U #define YSF_FRAME_PER 90U
@ -51,7 +50,6 @@ const char* HEADER1 = "This software is for use on amateur radio networks only,"
const char* HEADER2 = "it is to be used for educational purposes only. Its use on"; const char* HEADER2 = "it is to be used for educational purposes only. Its use on";
const char* HEADER3 = "commercial networks is strictly prohibited."; const char* HEADER3 = "commercial networks is strictly prohibited.";
const char* HEADER4 = "Copyright(C) 2018,2019 by CA6JAU, EA7EE, G4KLX and others"; const char* HEADER4 = "Copyright(C) 2018,2019 by CA6JAU, EA7EE, G4KLX and others";
const char ysf_radioid[] = {'H', '5', '0', '0', '0'};
#include <functional> #include <functional>
#include <algorithm> #include <algorithm>
@ -943,32 +941,23 @@ int CYSF2DMR::run()
// Set the FICH // Set the FICH
CYSFFICH fich; CYSFFICH fich;
fich.setFI(YSF_FI_HEADER); fich.setFI(YSF_FI_HEADER);
fich.setCS(2U); fich.setCS(m_conf.getFICHCallSign());
fich.setCM(1U); fich.setCM(m_conf.getFICHCallMode());
fich.setBN(0U); fich.setBN(0U);
fich.setBT(0U); fich.setBT(0U);
fich.setFN(0U); fich.setFN(0U);
fich.setFT(6U); fich.setFT(m_conf.getFICHFrameTotal());
fich.setDev(0U); fich.setDev(0U);
fich.setMR(0U); fich.setMR(m_conf.getFICHMessageRoute());
fich.setVoIP(false); fich.setVoIP(m_conf.getFICHVOIP());
fich.setDT(YSF_DT_VD_MODE2); fich.setDT(m_conf.getFICHDataType());
fich.setSQL(false); fich.setSQL(m_conf.getFICHSQLType());
fich.setSQ(0U); fich.setSQ(m_conf.getFICHSQLCode());
if (m_remoteGateway) {
fich.setVoIP(false);
fich.setMR(YSF_MR_DIRECT);
} else {
fich.setVoIP(true);
fich.setMR(YSF_MR_BUSY);
}
fich.encode(m_ysfFrame + 35U); fich.encode(m_ysfFrame + 35U);
unsigned char csd1[20U], csd2[20U]; unsigned char csd1[20U], csd2[20U];
memset(csd1, '*', YSF_CALLSIGN_LENGTH/2); memset(csd1, '*', YSF_CALLSIGN_LENGTH/2);
memcpy(csd1 + YSF_CALLSIGN_LENGTH/2, ysf_radioid, YSF_CALLSIGN_LENGTH/2); memcpy(csd1 + YSF_CALLSIGN_LENGTH/2, m_conf.getYsfRadioID().c_str(), YSF_CALLSIGN_LENGTH/2);
memcpy(csd1 + YSF_CALLSIGN_LENGTH, m_netSrc.c_str(), YSF_CALLSIGN_LENGTH); memcpy(csd1 + YSF_CALLSIGN_LENGTH, m_netSrc.c_str(), YSF_CALLSIGN_LENGTH);
memset(csd2, ' ', YSF_CALLSIGN_LENGTH + YSF_CALLSIGN_LENGTH); memset(csd2, ' ', YSF_CALLSIGN_LENGTH + YSF_CALLSIGN_LENGTH);
@ -976,7 +965,7 @@ int CYSF2DMR::run()
payload.writeHeader(m_ysfFrame + 35U, csd1, csd2); payload.writeHeader(m_ysfFrame + 35U, csd1, csd2);
m_ysfNetwork->write(m_ysfFrame); m_ysfNetwork->write(m_ysfFrame);
ysf_cnt++; ysf_cnt++;
ysfWatch.start(); ysfWatch.start();
} }
@ -992,32 +981,23 @@ int CYSF2DMR::run()
// Set the FICH // Set the FICH
CYSFFICH fich; CYSFFICH fich;
fich.setFI(YSF_FI_TERMINATOR); fich.setFI(YSF_FI_TERMINATOR);
fich.setCS(2U); fich.setCS(m_conf.getFICHCallSign());
fich.setCM(1U); fich.setCM(m_conf.getFICHCallMode());
fich.setBN(0U); fich.setBN(0U);
fich.setBT(0U); fich.setBT(0U);
fich.setFN(0U); fich.setFN(0U);
fich.setFT(6U); fich.setFT(m_conf.getFICHFrameTotal());
fich.setDev(0U); fich.setDev(0U);
fich.setMR(0U); fich.setMR(m_conf.getFICHMessageRoute());
fich.setVoIP(false); fich.setVoIP(m_conf.getFICHVOIP());
fich.setDT(YSF_DT_VD_MODE2); fich.setDT(m_conf.getFICHDataType());
fich.setSQL(false); fich.setSQL(m_conf.getFICHSQLType());
fich.setSQ(0U); fich.setSQ(m_conf.getFICHSQLCode());
if (m_remoteGateway) {
fich.setVoIP(false);
fich.setMR(YSF_MR_DIRECT);
} else {
fich.setVoIP(true);
fich.setMR(YSF_MR_BUSY);
}
fich.encode(m_ysfFrame + 35U); fich.encode(m_ysfFrame + 35U);
unsigned char csd1[20U], csd2[20U]; unsigned char csd1[20U], csd2[20U];
memset(csd1, '*', YSF_CALLSIGN_LENGTH/2); memset(csd1, '*', YSF_CALLSIGN_LENGTH/2);
memcpy(csd1 + YSF_CALLSIGN_LENGTH/2, ysf_radioid, YSF_CALLSIGN_LENGTH/2); memcpy(csd1 + YSF_CALLSIGN_LENGTH/2, m_conf.getYsfRadioID().c_str(), YSF_CALLSIGN_LENGTH/2);
memcpy(csd1 + YSF_CALLSIGN_LENGTH, m_netSrc.c_str(), YSF_CALLSIGN_LENGTH); memcpy(csd1 + YSF_CALLSIGN_LENGTH, m_netSrc.c_str(), YSF_CALLSIGN_LENGTH);
memset(csd2, ' ', YSF_CALLSIGN_LENGTH + YSF_CALLSIGN_LENGTH); memset(csd2, ' ', YSF_CALLSIGN_LENGTH + YSF_CALLSIGN_LENGTH);
@ -1031,7 +1011,7 @@ int CYSF2DMR::run()
CYSFPayload ysfPayload; CYSFPayload ysfPayload;
unsigned char dch[10U]; unsigned char dch[10U];
unsigned int fn = (ysf_cnt - 1U) % 7U; unsigned int fn = (ysf_cnt - 1U) % (m_conf.getFICHFrameTotal() + 1);
::memcpy(m_ysfFrame + 0U, "YSFD", 4U); ::memcpy(m_ysfFrame + 0U, "YSFD", 4U);
::memcpy(m_ysfFrame + 4U, m_ysfNetwork->getCallsign().c_str(), YSF_CALLSIGN_LENGTH); ::memcpy(m_ysfFrame + 4U, m_ysfNetwork->getCallsign().c_str(), YSF_CALLSIGN_LENGTH);
@ -1044,61 +1024,60 @@ int CYSF2DMR::run()
switch (fn) { switch (fn) {
case 0: case 0:
memset(dch, '*', YSF_CALLSIGN_LENGTH/2); memset(dch, '*', YSF_CALLSIGN_LENGTH/2);
memcpy(dch + YSF_CALLSIGN_LENGTH/2, ysf_radioid, YSF_CALLSIGN_LENGTH/2); memcpy(dch + YSF_CALLSIGN_LENGTH/2, m_conf.getYsfRadioID().c_str(), YSF_CALLSIGN_LENGTH/2);
ysfPayload.writeVDMode2Data(m_ysfFrame + 35U, dch); ysfPayload.writeVDMode2Data(m_ysfFrame + 35U, dch);
break; break;
case 1: case 1:
ysfPayload.writeVDMode2Data(m_ysfFrame + 35U, (const unsigned char*)m_netSrc.c_str()); ysfPayload.writeVDMode2Data(m_ysfFrame + 35U, (unsigned char*)m_netSrc.c_str());
break; break;
case 2: case 2:
ysfPayload.writeVDMode2Data(m_ysfFrame + 35U, (const unsigned char*)m_netDst.c_str()); ysfPayload.writeVDMode2Data(m_ysfFrame + 35U, (unsigned char*)m_netDst.c_str());
break; break;
case 5: case 5:
memset(dch, ' ', YSF_CALLSIGN_LENGTH/2); memset(dch, ' ', YSF_CALLSIGN_LENGTH/2);
memcpy(dch + YSF_CALLSIGN_LENGTH/2, ysf_radioid, YSF_CALLSIGN_LENGTH/2); memcpy(dch + YSF_CALLSIGN_LENGTH/2, m_conf.getYsfRadioID().c_str(), YSF_CALLSIGN_LENGTH/2);
ysfPayload.writeVDMode2Data(m_ysfFrame + 35U, dch); // Rem3/4 ysfPayload.writeVDMode2Data(m_ysfFrame + 35U, dch); // Rem3/4
break; break;
case 6: case 6: {
ysfPayload.writeVDMode2Data(m_ysfFrame + 35U, dt1); unsigned char dt1[10U] = {0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U};
for (unsigned int i = 0U; i < m_conf.getYsfDT1().size() && i < 10U; i++)
dt1[i] = m_conf.getYsfDT1()[i];
ysfPayload.writeVDMode2Data(m_ysfFrame + 35U, dt1);
}
break; break;
case 7: case 7: {
ysfPayload.writeVDMode2Data(m_ysfFrame + 35U, dt2_temp); unsigned char dt2[10U] = {0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U};
for (unsigned int i = 0U; i < m_conf.getYsfDT2().size() && i < 10U; i++)
dt2[i] = m_conf.getYsfDT2()[i];
ysfPayload.writeVDMode2Data(m_ysfFrame + 35U, dt2);
}
break; break;
default: default:
ysfPayload.writeVDMode2Data(m_ysfFrame + 35U, (const unsigned char*)" "); ysfPayload.writeVDMode2Data(m_ysfFrame + 35U, (const unsigned char*)" ");
} }
// Set the FICH // Set the FICH
fich.setFI(YSF_FI_COMMUNICATIONS); fich.setFI(YSF_FI_COMMUNICATIONS);
fich.setCS(2U); fich.setCS(m_conf.getFICHCallSign());
fich.setCM(1U); fich.setCM(m_conf.getFICHCallMode());
fich.setBN(0U); fich.setBN(0U);
fich.setBT(0U); fich.setBT(0U);
fich.setFN(fn); fich.setFN(fn);
fich.setFT(6U); fich.setFT(m_conf.getFICHFrameTotal());
fich.setDev(0U); fich.setDev(0U);
fich.setMR(0U); fich.setMR(m_conf.getFICHMessageRoute());
fich.setVoIP(false); fich.setVoIP(m_conf.getFICHVOIP());
fich.setDT(YSF_DT_VD_MODE2); fich.setDT(m_conf.getFICHDataType());
fich.setSQL(false); fich.setSQL(m_conf.getFICHSQLType());
fich.setSQ(0U); fich.setSQ(m_conf.getFICHSQLCode());
fich.encode(m_ysfFrame + 35U);
if (m_remoteGateway) {
fich.setVoIP(false);
fich.setMR(YSF_MR_DIRECT);
} else {
fich.setVoIP(true);
fich.setMR(YSF_MR_BUSY);
}
fich.encode(m_ysfFrame + 35U);
// Net frame counter // Net frame counter
m_ysfFrame[34U] = (ysf_cnt & 0x7FU) << 1; m_ysfFrame[34U] = (ysf_cnt & 0x7FU) << 1;
// Send data to MMDVMHost // Send data to MMDVMHost
m_ysfNetwork->write(m_ysfFrame); m_ysfNetwork->write(m_ysfFrame);
ysf_cnt++; ysf_cnt++;
ysfWatch.start(); ysfWatch.start();
} }

View File

@ -21,6 +21,18 @@ EnableWiresX=1
RemoteGateway=0 RemoteGateway=0
HangTime=1000 HangTime=1000
WiresXMakeUpper=1 WiresXMakeUpper=1
# RadioID=*****
# FICHCallsign=2
# FICHCallMode=0
# FICHBlockTotal=0
# FICHFrameTotal=7
# FICHMessageRoute=0
# FICHVOIP=0
# FICHDataType=2
# FICHSQLType=0
# FICHSQLCode=0
DT1=49,34,98,95,41,0,0,0,0,0
DT2=0,0,0,0,108,32,28,32,3,8
Daemon=0 Daemon=0
[DMR Network] [DMR Network]

View File

@ -47,6 +47,17 @@ m_localAddress(),
m_localPort(0U), m_localPort(0U),
m_enableWiresX(false), m_enableWiresX(false),
m_wiresXMakeUpper(true), m_wiresXMakeUpper(true),
m_fichCallSign(2U),
m_fichCallMode(0U),
m_fichFrameTotal(7U),
m_fichMessageRoute(0U),
m_fichVOIP(0U),
m_fichDataType(2U),
m_fichSQLType(0U),
m_fichSQLCode(0U),
m_ysfDT1(),
m_ysfDT2(),
m_ysfRadioID("*****"),
m_daemon(false), m_daemon(false),
m_rxFrequency(0U), m_rxFrequency(0U),
m_txFrequency(0U), m_txFrequency(0U),
@ -126,6 +137,7 @@ bool CConf::read()
// Remove quotes from the value // Remove quotes from the value
size_t len = ::strlen(value); size_t len = ::strlen(value);
char *t;
if (len > 1U && *value == '"' && value[len - 1U] == '"') { if (len > 1U && *value == '"' && value[len - 1U] == '"') {
value[len - 1U] = '\0'; value[len - 1U] = '\0';
value++; value++;
@ -167,6 +179,31 @@ bool CConf::read()
m_enableWiresX = ::atoi(value) == 1; m_enableWiresX = ::atoi(value) == 1;
else if (::strcmp(key, "WiresXMakeUpper") == 0) else if (::strcmp(key, "WiresXMakeUpper") == 0)
m_wiresXMakeUpper = ::atoi(value) == 1; m_wiresXMakeUpper = ::atoi(value) == 1;
else if (::strcmp(key, "RadioID") == 0)
m_ysfRadioID = value;
else if (::strcmp(key, "FICHCallsign") == 0)
m_fichCallSign = ::atoi(value);
else if (::strcmp(key, "FICHCallMode") == 0)
m_fichCallMode = ::atoi(value);
else if (::strcmp(key, "FICHFrameTotal") == 0)
m_fichFrameTotal = ::atoi(value);
else if (::strcmp(key, "FICHMessageRoute") == 0)
m_fichMessageRoute = ::atoi(value);
else if (::strcmp(key, "FICHVOIP") == 0)
m_fichVOIP = ::atoi(value);
else if (::strcmp(key, "FICHDataType") == 0)
m_fichDataType = ::atoi(value);
else if (::strcmp(key, "FICHSQLType") == 0)
m_fichSQLType = ::atoi(value);
else if (::strcmp(key, "FICHSQLCode") == 0)
m_fichSQLCode = ::atoi(value);
else if (::strcmp(key, "DT1") == 0){
while ((t = strtok_r(value, ",", &value)) != NULL)
m_ysfDT1.push_back(::atoi(t));
} else if (::strcmp(key, "DT2") == 0){
while ((t = strtok_r(value, ",", &value)) != NULL)
m_ysfDT2.push_back(::atoi(t));
}
else if (::strcmp(key, "Daemon") == 0) else if (::strcmp(key, "Daemon") == 0)
m_daemon = ::atoi(value) == 1; m_daemon = ::atoi(value) == 1;
} else if (section == SECTION_NXDN_NETWORK) { } else if (section == SECTION_NXDN_NETWORK) {
@ -293,6 +330,61 @@ bool CConf::getWiresXMakeUpper() const
return m_wiresXMakeUpper; return m_wiresXMakeUpper;
} }
unsigned char CConf::getFICHCallSign() const
{
return m_fichCallSign;
}
unsigned char CConf::getFICHCallMode() const
{
return m_fichCallMode;
}
unsigned char CConf::getFICHFrameTotal() const
{
return m_fichFrameTotal;
}
unsigned char CConf::getFICHMessageRoute() const
{
return m_fichMessageRoute;
}
unsigned char CConf::getFICHVOIP() const
{
return m_fichVOIP;
}
unsigned char CConf::getFICHDataType() const
{
return m_fichDataType;
}
unsigned char CConf::getFICHSQLType() const
{
return m_fichSQLType;
}
unsigned char CConf::getFICHSQLCode() const
{
return m_fichSQLCode;
}
std::vector<unsigned char> CConf::getYsfDT1()
{
return m_ysfDT1;
}
std::vector<unsigned char> CConf::getYsfDT2()
{
return m_ysfDT2;
}
std::string CConf::getYsfRadioID()
{
return m_ysfRadioID;
}
bool CConf::getDaemon() const bool CConf::getDaemon() const
{ {
return m_daemon; return m_daemon;

View File

@ -48,6 +48,17 @@ public:
unsigned int getLocalPort() const; unsigned int getLocalPort() const;
bool getEnableWiresX() const; bool getEnableWiresX() const;
bool getWiresXMakeUpper() const; bool getWiresXMakeUpper() const;
unsigned char getFICHCallSign() const;
unsigned char getFICHCallMode() const;
unsigned char getFICHFrameTotal() const;
unsigned char getFICHMessageRoute() const;
unsigned char getFICHVOIP() const;
unsigned char getFICHDataType() const;
unsigned char getFICHSQLType() const;
unsigned char getFICHSQLCode() const;
std::vector<unsigned char> getYsfDT1();
std::vector<unsigned char> getYsfDT2();
std::string getYsfRadioID();
bool getDaemon() const; bool getDaemon() const;
// The NXDN Network section // The NXDN Network section
@ -90,6 +101,17 @@ private:
unsigned int m_localPort; unsigned int m_localPort;
bool m_enableWiresX; bool m_enableWiresX;
bool m_wiresXMakeUpper; bool m_wiresXMakeUpper;
unsigned char m_fichCallSign;
unsigned char m_fichCallMode;
unsigned char m_fichFrameTotal;
unsigned char m_fichMessageRoute;
unsigned char m_fichVOIP;
unsigned char m_fichDataType;
unsigned char m_fichSQLType;
unsigned char m_fichSQLCode;
std::vector<unsigned char> m_ysfDT1;
std::vector<unsigned char> m_ysfDT2;
std::string m_ysfRadioID;
bool m_daemon; bool m_daemon;
unsigned int m_rxFrequency; unsigned int m_rxFrequency;

View File

@ -20,6 +20,6 @@
#if !defined(VERSION_H) #if !defined(VERSION_H)
#define VERSION_H #define VERSION_H
const char* VERSION = "20200503"; const char* VERSION = "20200605";
#endif #endif

View File

@ -33,7 +33,6 @@
// DT1 and DT2, suggested by Manuel EA7EE // DT1 and DT2, suggested by Manuel EA7EE
const unsigned char dt1_temp[] = {0x31, 0x22, 0x62, 0x5F, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00}; const unsigned char dt1_temp[] = {0x31, 0x22, 0x62, 0x5F, 0x29, 0x00, 0x00, 0x00, 0x00, 0x00};
const unsigned char dt2_temp[] = {0x00, 0x00, 0x00, 0x00, 0x6C, 0x20, 0x1C, 0x20, 0x03, 0x08}; const unsigned char dt2_temp[] = {0x00, 0x00, 0x00, 0x00, 0x6C, 0x20, 0x1C, 0x20, 0x03, 0x08};
const uint8_t dt1[10] = {0x01, 0x22, 0x61, 0x5f, 0x2b, 0x03, 0x11, 0x00, 0x00, 0x00};
#define NXDN_FRAME_PER 75U #define NXDN_FRAME_PER 75U
#define YSF_FRAME_PER 90U #define YSF_FRAME_PER 90U
@ -48,7 +47,6 @@ const char* HEADER1 = "This software is for use on amateur radio networks only,"
const char* HEADER2 = "it is to be used for educational purposes only. Its use on"; const char* HEADER2 = "it is to be used for educational purposes only. Its use on";
const char* HEADER3 = "commercial networks is strictly prohibited."; const char* HEADER3 = "commercial networks is strictly prohibited.";
const char* HEADER4 = "Copyright(C) 2018,2019 by CA6JAU, G4KLX and others"; const char* HEADER4 = "Copyright(C) 2018,2019 by CA6JAU, G4KLX and others";
const char ysf_radioid[] = {'H', '5', '0', '0', '0'};
#include <functional> #include <functional>
#include <algorithm> #include <algorithm>
@ -397,7 +395,7 @@ int CYSF2NXDN::run()
if (m_gps != NULL) if (m_gps != NULL)
m_gps->data(buffer + 14U, buffer + 35U, fi, dt, fn, ft); m_gps->data(buffer + 14U, buffer + 35U, fi, dt, fn, ft);
} }
if ((buffer[34U] & 0x01U) == 0x01U) { if ((buffer[34U] & 0x01U) == 0x01U) {
@ -519,7 +517,7 @@ int CYSF2NXDN::run()
// Send data to MMDVMHost // Send data to MMDVMHost
m_nxdnNetwork->write(m_nxdnFrame, false); m_nxdnNetwork->write(m_nxdnFrame, false);
nxdn_cnt++; nxdn_cnt++;
nxdnWatch.start(); nxdnWatch.start();
} }
@ -539,7 +537,7 @@ int CYSF2NXDN::run()
dstId = (m_nxdnFrame[10U] << 8) & 0xFF00U; dstId = (m_nxdnFrame[10U] << 8) & 0xFF00U;
dstId |= (m_nxdnFrame[11U] << 0) & 0x00FFU; dstId |= (m_nxdnFrame[11U] << 0) & 0x00FFU;
if (grp && m_dstid == dstId) { if (grp && m_dstid == dstId) {
if (m_nxdnFrame[5U] == 0x01) { if (m_nxdnFrame[5U] == 0x01) {
// DT1 & DT2 without GPS info // DT1 & DT2 without GPS info
@ -588,7 +586,7 @@ int CYSF2NXDN::run()
m_nxdnFrames++; m_nxdnFrames++;
} }
} }
if (ysfWatch.elapsed() > YSF_FRAME_PER) { if (ysfWatch.elapsed() > YSF_FRAME_PER) {
unsigned int ysfFrameType = m_conv.getYSF(m_ysfFrame + 35U); unsigned int ysfFrameType = m_conv.getYSF(m_ysfFrame + 35U);
@ -606,24 +604,23 @@ int CYSF2NXDN::run()
// Set the FICH // Set the FICH
CYSFFICH fich; CYSFFICH fich;
fich.setFI(YSF_FI_HEADER); fich.setFI(YSF_FI_HEADER);
fich.setCS(2U); fich.setCS(m_conf.getFICHCallSign());
fich.setCM(1U); fich.setCM(m_conf.getFICHCallMode());
fich.setBN(0U); fich.setBN(0U);
fich.setBT(0U); fich.setBT(0U);
fich.setFN(0U); fich.setFN(0U);
fich.setFT(6U); fich.setFT(m_conf.getFICHFrameTotal());
fich.setDev(0U); fich.setDev(0U);
fich.setMR(0U); fich.setMR(m_conf.getFICHMessageRoute());
fich.setVoIP(false); fich.setVoIP(m_conf.getFICHVOIP());
fich.setDT(YSF_DT_VD_MODE2); fich.setDT(m_conf.getFICHDataType());
fich.setSQL(0U); fich.setSQL(m_conf.getFICHSQLType());
fich.setSQ(0U); fich.setSQ(m_conf.getFICHSQLCode());
fich.encode(m_ysfFrame + 35U); fich.encode(m_ysfFrame + 35U);
unsigned char csd1[20U], csd2[20U]; unsigned char csd1[20U], csd2[20U];
memset(csd1, '*', YSF_CALLSIGN_LENGTH/2); memset(csd1, '*', YSF_CALLSIGN_LENGTH/2);
memcpy(csd1 + YSF_CALLSIGN_LENGTH/2, ysf_radioid, YSF_CALLSIGN_LENGTH/2); memcpy(csd1 + YSF_CALLSIGN_LENGTH/2, m_conf.getYsfRadioID().c_str(), YSF_CALLSIGN_LENGTH/2);
//memset(csd1, '*', YSF_CALLSIGN_LENGTH);
memcpy(csd1 + YSF_CALLSIGN_LENGTH, m_netSrc.c_str(), YSF_CALLSIGN_LENGTH); memcpy(csd1 + YSF_CALLSIGN_LENGTH, m_netSrc.c_str(), YSF_CALLSIGN_LENGTH);
memset(csd2, ' ', YSF_CALLSIGN_LENGTH + YSF_CALLSIGN_LENGTH); memset(csd2, ' ', YSF_CALLSIGN_LENGTH + YSF_CALLSIGN_LENGTH);
@ -646,27 +643,26 @@ int CYSF2NXDN::run()
// Set the FICH // Set the FICH
CYSFFICH fich; CYSFFICH fich;
fich.setFI(YSF_FI_TERMINATOR); fich.setFI(YSF_FI_HEADER);
fich.setCS(2U); fich.setCS(m_conf.getFICHCallSign());
fich.setCM(1U); fich.setCM(m_conf.getFICHCallMode());
fich.setBN(0U); fich.setBN(0U);
fich.setBT(0U); fich.setBT(0U);
fich.setFN(0U); fich.setFN(0U);
fich.setFT(6U); fich.setFT(m_conf.getFICHFrameTotal());
fich.setDev(0U); fich.setDev(0U);
fich.setMR(0U); fich.setMR(m_conf.getFICHMessageRoute());
fich.setVoIP(false); fich.setVoIP(m_conf.getFICHVOIP());
fich.setDT(YSF_DT_VD_MODE2); fich.setDT(m_conf.getFICHDataType());
fich.setSQL(0U); fich.setSQL(m_conf.getFICHSQLType());
fich.setSQ(0U); fich.setSQ(m_conf.getFICHSQLCode());
fich.encode(m_ysfFrame + 35U); fich.encode(m_ysfFrame + 35U);
unsigned char csd1[20U], csd2[20U]; unsigned char csd1[20U], csd2[20U];
memset(csd1, '*', YSF_CALLSIGN_LENGTH/2); memset(csd1, '*', YSF_CALLSIGN_LENGTH/2);
memcpy(csd1 + YSF_CALLSIGN_LENGTH/2, ysf_radioid, YSF_CALLSIGN_LENGTH/2); memcpy(csd1 + YSF_CALLSIGN_LENGTH/2, m_conf.getYsfRadioID().c_str(), YSF_CALLSIGN_LENGTH/2);
//memset(csd1, '*', YSF_CALLSIGN_LENGTH); memcpy(csd1 + YSF_CALLSIGN_LENGTH, m_netSrc.c_str(), YSF_CALLSIGN_LENGTH);
memcpy(csd1 + YSF_CALLSIGN_LENGTH, m_netSrc.c_str(), YSF_CALLSIGN_LENGTH); memset(csd2, ' ', YSF_CALLSIGN_LENGTH + YSF_CALLSIGN_LENGTH);
memset(csd2, ' ', YSF_CALLSIGN_LENGTH + YSF_CALLSIGN_LENGTH);
CYSFPayload payload; CYSFPayload payload;
payload.writeHeader(m_ysfFrame + 35U, csd1, csd2); payload.writeHeader(m_ysfFrame + 35U, csd1, csd2);
@ -691,45 +687,52 @@ int CYSF2NXDN::run()
switch (fn) { switch (fn) {
case 0: case 0:
memset(dch, '*', YSF_CALLSIGN_LENGTH/2); memset(dch, '*', YSF_CALLSIGN_LENGTH/2);
memcpy(dch + YSF_CALLSIGN_LENGTH/2, ysf_radioid, YSF_CALLSIGN_LENGTH/2); memcpy(dch + YSF_CALLSIGN_LENGTH/2, m_conf.getYsfRadioID().c_str(), YSF_CALLSIGN_LENGTH/2);
ysfPayload.writeVDMode2Data(m_ysfFrame + 35U, dch); ysfPayload.writeVDMode2Data(m_ysfFrame + 35U, dch);
//ysfPayload.writeVDMode2Data(m_ysfFrame + 35U, (const unsigned char*)"**********");
break; break;
case 1: case 1:
ysfPayload.writeVDMode2Data(m_ysfFrame + 35U, (const unsigned char*)m_netSrc.c_str()); ysfPayload.writeVDMode2Data(m_ysfFrame + 35U, (unsigned char*)m_netSrc.c_str());
break; break;
case 2: case 2:
ysfPayload.writeVDMode2Data(m_ysfFrame + 35U, (const unsigned char*)m_netDst.c_str()); ysfPayload.writeVDMode2Data(m_ysfFrame + 35U, (unsigned char*)m_netDst.c_str());
break; break;
case 5: case 5:
memset(dch, ' ', YSF_CALLSIGN_LENGTH/2); memset(dch, ' ', YSF_CALLSIGN_LENGTH/2);
memcpy(dch + YSF_CALLSIGN_LENGTH/2, ysf_radioid, YSF_CALLSIGN_LENGTH/2); memcpy(dch + YSF_CALLSIGN_LENGTH/2, m_conf.getYsfRadioID().c_str(), YSF_CALLSIGN_LENGTH/2);
ysfPayload.writeVDMode2Data(m_ysfFrame + 35U, dch); // Rem3/4 ysfPayload.writeVDMode2Data(m_ysfFrame + 35U, dch); // Rem3/4
break; break;
case 6: case 6: {
ysfPayload.writeVDMode2Data(m_ysfFrame + 35U, dt1); unsigned char dt1[10U] = {0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U};
for (unsigned int i = 0U; i < m_conf.getYsfDT1().size() && i < 10U; i++)
dt1[i] = m_conf.getYsfDT1()[i];
ysfPayload.writeVDMode2Data(m_ysfFrame + 35U, dt1);
}
break; break;
case 7: case 7: {
ysfPayload.writeVDMode2Data(m_ysfFrame + 35U, dt2_temp); unsigned char dt2[10U] = {0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U, 0U};
for (unsigned int i = 0U; i < m_conf.getYsfDT2().size() && i < 10U; i++)
dt2[i] = m_conf.getYsfDT2()[i];
ysfPayload.writeVDMode2Data(m_ysfFrame + 35U, dt2);
}
break; break;
default: default:
ysfPayload.writeVDMode2Data(m_ysfFrame + 35U, (const unsigned char*)" "); ysfPayload.writeVDMode2Data(m_ysfFrame + 35U, (const unsigned char*)" ");
} }
// Set the FICH // Set the FICH
fich.setFI(YSF_FI_COMMUNICATIONS); fich.setFI(YSF_FI_COMMUNICATIONS);
fich.setCS(2U); fich.setCS(m_conf.getFICHCallSign());
fich.setCM(1U); fich.setCM(m_conf.getFICHCallMode());
fich.setBN(0U); fich.setBN(0U);
fich.setBT(0U); fich.setBT(0U);
fich.setFN(fn); fich.setFN(fn);
fich.setFT(6U); fich.setFT(m_conf.getFICHFrameTotal());
fich.setDev(0U); fich.setDev(0U);
fich.setMR(0U); fich.setMR(m_conf.getFICHMessageRoute());
fich.setVoIP(false); fich.setVoIP(m_conf.getFICHVOIP());
fich.setDT(YSF_DT_VD_MODE2); fich.setDT(m_conf.getFICHDataType());
fich.setSQL(0U); fich.setSQL(m_conf.getFICHSQLType());
fich.setSQ(0U); fich.setSQ(m_conf.getFICHSQLCode());
fich.encode(m_ysfFrame + 35U); fich.encode(m_ysfFrame + 35U);
// Net frame counter // Net frame counter
@ -737,7 +740,7 @@ int CYSF2NXDN::run()
// Send data to MMDVMHost // Send data to MMDVMHost
m_ysfNetwork->write(m_ysfFrame); m_ysfNetwork->write(m_ysfFrame);
ysf_cnt++; ysf_cnt++;
ysfWatch.start(); ysfWatch.start();
} }
@ -766,17 +769,17 @@ int CYSF2NXDN::run()
m_ysfNetwork->close(); m_ysfNetwork->close();
m_nxdnNetwork->close(); m_nxdnNetwork->close();
if (m_APRS != NULL) { if (m_APRS != NULL) {
m_APRS->stop(); m_APRS->stop();
delete m_APRS; delete m_APRS;
} }
if (m_gps != NULL) { if (m_gps != NULL) {
m_gps->close(); m_gps->close();
delete m_gps; delete m_gps;
} }
delete m_nxdnNetwork; delete m_nxdnNetwork;
delete m_ysfNetwork; delete m_ysfNetwork;

View File

@ -16,6 +16,18 @@ LocalAddress=127.0.0.1
LocalPort=42014 LocalPort=42014
EnableWiresX=1 EnableWiresX=1
WiresXMakeUpper=1 WiresXMakeUpper=1
# RadioID=*****
# FICHCallsign=2
# FICHCallMode=0
# FICHBlockTotal=0
# FICHFrameTotal=7
# FICHMessageRoute=0
# FICHVOIP=0
# FICHDataType=2
# FICHSQLType=0
# FICHSQLCode=0
DT1=49,34,98,95,41,0,0,0,0,0
DT2=0,0,0,0,108,32,28,32,3,8
Daemon=0 Daemon=0
[NXDN Network] [NXDN Network]

View File

@ -46,6 +46,17 @@ m_localAddress(),
m_localPort(0U), m_localPort(0U),
m_enableWiresX(false), m_enableWiresX(false),
m_wiresXMakeUpper(true), m_wiresXMakeUpper(true),
m_fichCallSign(2U),
m_fichCallMode(0U),
m_fichFrameTotal(7U),
m_fichMessageRoute(0U),
m_fichVOIP(0U),
m_fichDataType(2U),
m_fichSQLType(0U),
m_fichSQLCode(0U),
m_ysfDT1(),
m_ysfDT2(),
m_ysfRadioID("*****"),
m_daemon(false), m_daemon(false),
m_networkDebug(false), m_networkDebug(false),
m_rxFrequency(0U), m_rxFrequency(0U),
@ -114,6 +125,7 @@ bool CConf::read()
// Remove quotes from the value // Remove quotes from the value
size_t len = ::strlen(value); size_t len = ::strlen(value);
char *t;
if (len > 1U && *value == '"' && value[len - 1U] == '"') { if (len > 1U && *value == '"' && value[len - 1U] == '"') {
value[len - 1U] = '\0'; value[len - 1U] = '\0';
value++; value++;
@ -149,6 +161,31 @@ bool CConf::read()
m_enableWiresX = ::atoi(value) == 1; m_enableWiresX = ::atoi(value) == 1;
else if (::strcmp(key, "WiresXMakeUpper") == 0) else if (::strcmp(key, "WiresXMakeUpper") == 0)
m_wiresXMakeUpper = ::atoi(value) == 1; m_wiresXMakeUpper = ::atoi(value) == 1;
else if (::strcmp(key, "RadioID") == 0)
m_ysfRadioID = value;
else if (::strcmp(key, "FICHCallsign") == 0)
m_fichCallSign = ::atoi(value);
else if (::strcmp(key, "FICHCallMode") == 0)
m_fichCallMode = ::atoi(value);
else if (::strcmp(key, "FICHFrameTotal") == 0)
m_fichFrameTotal = ::atoi(value);
else if (::strcmp(key, "FICHMessageRoute") == 0)
m_fichMessageRoute = ::atoi(value);
else if (::strcmp(key, "FICHVOIP") == 0)
m_fichVOIP = ::atoi(value);
else if (::strcmp(key, "FICHDataType") == 0)
m_fichDataType = ::atoi(value);
else if (::strcmp(key, "FICHSQLType") == 0)
m_fichSQLType = ::atoi(value);
else if (::strcmp(key, "FICHSQLCode") == 0)
m_fichSQLCode = ::atoi(value);
else if (::strcmp(key, "DT1") == 0){
while ((t = strtok_r(value, ",", &value)) != NULL)
m_ysfDT1.push_back(::atoi(t));
} else if (::strcmp(key, "DT2") == 0){
while ((t = strtok_r(value, ",", &value)) != NULL)
m_ysfDT2.push_back(::atoi(t));
}
else if (::strcmp(key, "Daemon") == 0) else if (::strcmp(key, "Daemon") == 0)
m_daemon = ::atoi(value) == 1; m_daemon = ::atoi(value) == 1;
else if (::strcmp(key, "Debug") == 0) else if (::strcmp(key, "Debug") == 0)
@ -247,6 +284,61 @@ bool CConf::getWiresXMakeUpper() const
return m_wiresXMakeUpper; return m_wiresXMakeUpper;
} }
unsigned char CConf::getFICHCallSign() const
{
return m_fichCallSign;
}
unsigned char CConf::getFICHCallMode() const
{
return m_fichCallMode;
}
unsigned char CConf::getFICHFrameTotal() const
{
return m_fichFrameTotal;
}
unsigned char CConf::getFICHMessageRoute() const
{
return m_fichMessageRoute;
}
unsigned char CConf::getFICHVOIP() const
{
return m_fichVOIP;
}
unsigned char CConf::getFICHDataType() const
{
return m_fichDataType;
}
unsigned char CConf::getFICHSQLType() const
{
return m_fichSQLType;
}
unsigned char CConf::getFICHSQLCode() const
{
return m_fichSQLCode;
}
std::vector<unsigned char> CConf::getYsfDT1()
{
return m_ysfDT1;
}
std::vector<unsigned char> CConf::getYsfDT2()
{
return m_ysfDT2;
}
std::string CConf::getYsfRadioID()
{
return m_ysfRadioID;
}
bool CConf::getDaemon() const bool CConf::getDaemon() const
{ {
return m_daemon; return m_daemon;

View File

@ -45,6 +45,17 @@ public:
unsigned int getLocalPort() const; unsigned int getLocalPort() const;
bool getEnableWiresX() const; bool getEnableWiresX() const;
bool getWiresXMakeUpper() const; bool getWiresXMakeUpper() const;
unsigned char getFICHCallSign() const;
unsigned char getFICHCallMode() const;
unsigned char getFICHFrameTotal() const;
unsigned char getFICHMessageRoute() const;
unsigned char getFICHVOIP() const;
unsigned char getFICHDataType() const;
unsigned char getFICHSQLType() const;
unsigned char getFICHSQLCode() const;
std::vector<unsigned char> getYsfDT1();
std::vector<unsigned char> getYsfDT2();
std::string getYsfRadioID();
bool getDaemon() const; bool getDaemon() const;
bool getNetworkDebug() const; bool getNetworkDebug() const;
@ -78,6 +89,17 @@ private:
unsigned int m_localPort; unsigned int m_localPort;
bool m_enableWiresX; bool m_enableWiresX;
bool m_wiresXMakeUpper; bool m_wiresXMakeUpper;
unsigned char m_fichCallSign;
unsigned char m_fichCallMode;
unsigned char m_fichFrameTotal;
unsigned char m_fichMessageRoute;
unsigned char m_fichVOIP;
unsigned char m_fichDataType;
unsigned char m_fichSQLType;
unsigned char m_fichSQLCode;
std::vector<unsigned char> m_ysfDT1;
std::vector<unsigned char> m_ysfDT2;
std::string m_ysfRadioID;
bool m_daemon; bool m_daemon;
bool m_networkDebug; bool m_networkDebug;

View File

@ -20,6 +20,6 @@
#if !defined(VERSION_H) #if !defined(VERSION_H)
#define VERSION_H #define VERSION_H
const char* VERSION = "20200503"; const char* VERSION = "20200605";
#endif #endif

View File

@ -92,8 +92,6 @@ const unsigned char REC73[] = {
const unsigned char REC80[] = { const unsigned char REC80[] = {
0x80U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U}; 0x80U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U};
const uint8_t dt1[10] = {0x01, 0x22, 0x61, 0x5f, 0x2b, 0x03, 0x11, 0x00, 0x00, 0x00};
#define P25_FRAME_PER 15U #define P25_FRAME_PER 15U
#define YSF_FRAME_PER 90U #define YSF_FRAME_PER 90U
@ -107,7 +105,6 @@ const char* HEADER1 = "This software is for use on amateur radio networks only,"
const char* HEADER2 = "it is to be used for educational purposes only. Its use on"; const char* HEADER2 = "it is to be used for educational purposes only. Its use on";
const char* HEADER3 = "commercial networks is strictly prohibited."; const char* HEADER3 = "commercial networks is strictly prohibited.";
const char* HEADER4 = "Copyright(C) 2018,2019 by CA6JAU, G4KLX and others"; const char* HEADER4 = "Copyright(C) 2018,2019 by CA6JAU, G4KLX and others";
const char ysf_radioid[] = {'H', '5', '0', '0', '0'};
#include <functional> #include <functional>
#include <algorithm> #include <algorithm>
@ -451,7 +448,7 @@ int CYSF2P25::run()
m_conv.putYSF(buffer + 35U); m_conv.putYSF(buffer + 35U);
m_ysfFrames++; m_ysfFrames++;
} }
} }
} }
} }
@ -623,23 +620,23 @@ int CYSF2P25::run()
// Set the FICH // Set the FICH
CYSFFICH fich; CYSFFICH fich;
fich.setFI(YSF_FI_HEADER); fich.setFI(YSF_FI_HEADER);
fich.setCS(2U); fich.setCS(m_conf.getFICHCallSign());
fich.setCM(1U); fich.setCM(m_conf.getFICHCallMode());
fich.setBN(0U); fich.setBN(0U);
fich.setBT(0U); fich.setBT(0U);
fich.setFN(0U); fich.setFN(0U);
fich.setFT(6U); fich.setFT(m_conf.getFICHFrameTotal());
fich.setDev(0U); fich.setDev(0U);
fich.setMR(0U); fich.setMR(m_conf.getFICHMessageRoute());
fich.setVoIP(false); fich.setVoIP(m_conf.getFICHVOIP());
fich.setDT(YSF_DT_VOICE_FR_MODE); fich.setDT(m_conf.getFICHDataType());
fich.setSQL(0U); fich.setSQL(m_conf.getFICHSQLType());
fich.setSQ(0U); fich.setSQ(m_conf.getFICHSQLCode());
fich.encode(m_ysfFrame + 35U); fich.encode(m_ysfFrame + 35U);
unsigned char csd1[20U], csd2[20U]; unsigned char csd1[20U], csd2[20U];
memset(csd1, '*', YSF_CALLSIGN_LENGTH/2); memset(csd1, '*', YSF_CALLSIGN_LENGTH/2);
memcpy(csd1 + YSF_CALLSIGN_LENGTH/2, ysf_radioid, YSF_CALLSIGN_LENGTH/2); memcpy(csd1 + YSF_CALLSIGN_LENGTH/2, m_conf.getYsfRadioID().c_str(), YSF_CALLSIGN_LENGTH/2);
memcpy(csd1 + YSF_CALLSIGN_LENGTH, m_netSrc.c_str(), YSF_CALLSIGN_LENGTH); memcpy(csd1 + YSF_CALLSIGN_LENGTH, m_netSrc.c_str(), YSF_CALLSIGN_LENGTH);
memset(csd2, ' ', YSF_CALLSIGN_LENGTH + YSF_CALLSIGN_LENGTH); memset(csd2, ' ', YSF_CALLSIGN_LENGTH + YSF_CALLSIGN_LENGTH);
@ -647,7 +644,7 @@ int CYSF2P25::run()
payload.writeHeader(m_ysfFrame + 35U, csd1, csd2); payload.writeHeader(m_ysfFrame + 35U, csd1, csd2);
m_ysfNetwork->write(m_ysfFrame); m_ysfNetwork->write(m_ysfFrame);
ysf_cnt++; ysf_cnt++;
ysfWatch.start(); ysfWatch.start();
} }
@ -663,23 +660,23 @@ int CYSF2P25::run()
// Set the FICH // Set the FICH
CYSFFICH fich; CYSFFICH fich;
fich.setFI(YSF_FI_TERMINATOR); fich.setFI(YSF_FI_TERMINATOR);
fich.setCS(2U); fich.setCS(m_conf.getFICHCallSign());
fich.setCM(1U); fich.setCM(m_conf.getFICHCallMode());
fich.setBN(0U); fich.setBN(0U);
fich.setBT(0U); fich.setBT(0U);
fich.setFN(0U); fich.setFN(0U);
fich.setFT(6U); fich.setFT(m_conf.getFICHFrameTotal());
fich.setDev(0U); fich.setDev(0U);
fich.setMR(0U); fich.setMR(m_conf.getFICHMessageRoute());
fich.setVoIP(false); fich.setVoIP(m_conf.getFICHVOIP());
fich.setDT(YSF_DT_VOICE_FR_MODE); fich.setDT(m_conf.getFICHDataType());
fich.setSQL(0U); fich.setSQL(m_conf.getFICHSQLType());
fich.setSQ(0U); fich.setSQ(m_conf.getFICHSQLCode());
fich.encode(m_ysfFrame + 35U); fich.encode(m_ysfFrame + 35U);
unsigned char csd1[20U], csd2[20U]; unsigned char csd1[20U], csd2[20U];
memset(csd1, '*', YSF_CALLSIGN_LENGTH/2); memset(csd1, '*', YSF_CALLSIGN_LENGTH/2);
memcpy(csd1 + YSF_CALLSIGN_LENGTH/2, ysf_radioid, YSF_CALLSIGN_LENGTH/2); memcpy(csd1 + YSF_CALLSIGN_LENGTH/2, m_conf.getYsfRadioID().c_str(), YSF_CALLSIGN_LENGTH/2);
memcpy(csd1 + YSF_CALLSIGN_LENGTH, m_netSrc.c_str(), YSF_CALLSIGN_LENGTH); memcpy(csd1 + YSF_CALLSIGN_LENGTH, m_netSrc.c_str(), YSF_CALLSIGN_LENGTH);
memset(csd2, ' ', YSF_CALLSIGN_LENGTH + YSF_CALLSIGN_LENGTH); memset(csd2, ' ', YSF_CALLSIGN_LENGTH + YSF_CALLSIGN_LENGTH);
@ -705,18 +702,18 @@ int CYSF2P25::run()
// Set the FICH // Set the FICH
fich.setFI(YSF_FI_COMMUNICATIONS); fich.setFI(YSF_FI_COMMUNICATIONS);
fich.setCS(2U); fich.setCS(m_conf.getFICHCallSign());
fich.setCM(1U); fich.setCM(m_conf.getFICHCallMode());
fich.setBN(0U); fich.setBN(0U);
fich.setBT(0U); fich.setBT(0U);
fich.setFN(fn); fich.setFN(fn);
fich.setFT(6U); fich.setFT(m_conf.getFICHFrameTotal());
fich.setDev(0U); fich.setDev(0U);
fich.setMR(0U); fich.setMR(m_conf.getFICHMessageRoute());
fich.setVoIP(false); fich.setVoIP(m_conf.getFICHVOIP());
fich.setDT(YSF_DT_VOICE_FR_MODE); fich.setDT(m_conf.getFICHDataType());
fich.setSQL(0U); fich.setSQL(m_conf.getFICHSQLType());
fich.setSQ(0U); fich.setSQ(m_conf.getFICHSQLCode());
fich.encode(m_ysfFrame + 35U); fich.encode(m_ysfFrame + 35U);
// Net frame counter // Net frame counter
@ -724,7 +721,7 @@ int CYSF2P25::run()
// Send data to MMDVMHost // Send data to MMDVMHost
m_ysfNetwork->write(m_ysfFrame); m_ysfNetwork->write(m_ysfFrame);
ysf_cnt++; ysf_cnt++;
ysfWatch.start(); ysfWatch.start();
} }
@ -749,7 +746,7 @@ int CYSF2P25::run()
m_ysfNetwork->close(); m_ysfNetwork->close();
m_p25Network->close(); m_p25Network->close();
delete m_p25Network; delete m_p25Network;
delete m_ysfNetwork; delete m_ysfNetwork;

View File

@ -13,6 +13,18 @@ LocalAddress=127.0.0.1
LocalPort=42015 LocalPort=42015
EnableWiresX=1 EnableWiresX=1
WiresXMakeUpper=1 WiresXMakeUpper=1
# RadioID=*****
# FICHCallsign=2
# FICHCallMode=0
# FICHBlockTotal=0
# FICHFrameTotal=7
# FICHMessageRoute=0
# FICHVOIP=0
# FICHDataType=2
# FICHSQLType=0
# FICHSQLCode=0
DT1=49,34,98,95,41,0,0,0,0,0
DT2=0,0,0,0,108,32,28,32,3,8
Daemon=0 Daemon=0
Debug=0 Debug=0