Add the USDP metadata header to the FM network output.

This commit is contained in:
Jonathan Naylor
2021-04-24 08:43:48 +01:00
parent 82b5b010eb
commit 609f1e356a
5 changed files with 136 additions and 16 deletions

View File

@@ -79,7 +79,7 @@ bool CFMControl::writeModem(const unsigned char* data, unsigned int length)
return true; return true;
if (data[0U] == TAG_EOT) if (data[0U] == TAG_EOT)
return m_network->writeEOT(); return m_network->writeEnd();
if (data[0U] != TAG_DATA1) if (data[0U] != TAG_DATA1)
return false; return false;

View File

@@ -27,7 +27,8 @@
const unsigned int BUFFER_LENGTH = 1500U; const unsigned int BUFFER_LENGTH = 1500U;
CFMNetwork::CFMNetwork(const std::string& protocol, const std::string& localAddress, unsigned int localPort, const std::string& gatewayAddress, unsigned int gatewayPort, bool debug) : CFMNetwork::CFMNetwork(const std::string& callsign, const std::string& protocol, const std::string& localAddress, unsigned int localPort, const std::string& gatewayAddress, unsigned int gatewayPort, bool debug) :
m_callsign(callsign),
m_protocol(FMNP_USRP), m_protocol(FMNP_USRP),
m_socket(localAddress, localPort), m_socket(localAddress, localPort),
m_addr(), m_addr(),
@@ -37,12 +38,18 @@ m_enabled(false),
m_buffer(2000U, "FM Network"), m_buffer(2000U, "FM Network"),
m_seqNo(0U) m_seqNo(0U)
{ {
assert(!callsign.empty());
assert(gatewayPort > 0U); assert(gatewayPort > 0U);
assert(!gatewayAddress.empty()); assert(!gatewayAddress.empty());
if (CUDPSocket::lookup(gatewayAddress, gatewayPort, m_addr, m_addrLen) != 0) if (CUDPSocket::lookup(gatewayAddress, gatewayPort, m_addr, m_addrLen) != 0)
m_addrLen = 0U; m_addrLen = 0U;
// Remove any trailing letters in the callsign
size_t pos = callsign.find_first_of(' ');
if (pos != std::string::npos)
m_callsign = callsign.substr(0U, pos);
// if (protocol == "USRP") // if (protocol == "USRP")
// m_protocol = FMNP_USRP; // m_protocol = FMNP_USRP;
} }
@@ -68,8 +75,14 @@ bool CFMNetwork::writeData(float* data, unsigned int nSamples)
assert(data != NULL); assert(data != NULL);
assert(nSamples > 0U); assert(nSamples > 0U);
unsigned char buffer[1500U]; if (m_seqNo == 0U) {
::memset(buffer, 0x00U, 1500U); bool ret = writeStart();
if (!ret)
return false;
}
unsigned char buffer[500U];
::memset(buffer, 0x00U, 500U);
unsigned int length = 0U; unsigned int length = 0U;
@@ -133,10 +146,10 @@ bool CFMNetwork::writeData(float* data, unsigned int nSamples)
return m_socket.write(buffer, length, m_addr, m_addrLen); return m_socket.write(buffer, length, m_addr, m_addrLen);
} }
bool CFMNetwork::writeEOT() bool CFMNetwork::writeEnd()
{ {
unsigned char buffer[1500U]; unsigned char buffer[500U];
::memset(buffer, 0x00U, 1500U); ::memset(buffer, 0x00U, 500U);
unsigned int length = 0U; unsigned int length = 0U;
@@ -184,15 +197,19 @@ bool CFMNetwork::writeEOT()
buffer[length++] = 0x00U; buffer[length++] = 0x00U;
buffer[length++] = 0x00U; buffer[length++] = 0x00U;
length += 160U * sizeof(int16_t); length += 320U;
} }
if (m_debug) m_seqNo = 0U;
CUtils::dump(1U, "FM Network Data Sent", buffer, length);
m_seqNo++; if (length > 0U) {
if (m_debug)
CUtils::dump(1U, "FM Network Data Sent", buffer, length);
return m_socket.write(buffer, length, m_addr, m_addrLen); return m_socket.write(buffer, length, m_addr, m_addrLen);
} else {
return true;
}
} }
void CFMNetwork::clock(unsigned int ms) void CFMNetwork::clock(unsigned int ms)
@@ -280,3 +297,102 @@ void CFMNetwork::enable(bool enabled)
m_enabled = enabled; m_enabled = enabled;
} }
bool CFMNetwork::writeStart()
{
unsigned char buffer[500U];
::memset(buffer, 0x00U, 500U);
unsigned int length = 0U;
if (m_protocol == FMNP_USRP) {
buffer[length++] = 'U';
buffer[length++] = 'S';
buffer[length++] = 'R';
buffer[length++] = 'P';
// Sequence number
buffer[length++] = (m_seqNo >> 24) & 0xFFU;
buffer[length++] = (m_seqNo >> 16) & 0xFFU;
buffer[length++] = (m_seqNo >> 8) & 0xFFU;
buffer[length++] = (m_seqNo >> 0) & 0xFFU;
buffer[length++] = 0x00U;
buffer[length++] = 0x00U;
buffer[length++] = 0x00U;
buffer[length++] = 0x00U;
// PTT off
buffer[length++] = 0x00U;
buffer[length++] = 0x00U;
buffer[length++] = 0x00U;
buffer[length++] = 0x00U;
buffer[length++] = 0x00U;
buffer[length++] = 0x00U;
buffer[length++] = 0x00U;
buffer[length++] = 0x00U;
// Type, 2 for metadata
buffer[length++] = 0x00U;
buffer[length++] = 0x00U;
buffer[length++] = 0x00U;
buffer[length++] = 0x02U;
buffer[length++] = 0x00U;
buffer[length++] = 0x00U;
buffer[length++] = 0x00U;
buffer[length++] = 0x00U;
buffer[length++] = 0x00U;
buffer[length++] = 0x00U;
buffer[length++] = 0x00U;
buffer[length++] = 0x00U;
// TLV TAG for Metadata
buffer[length++] = 0x08U;
// TLV Length
buffer[length++] = 3U + 4U + 3U + 1U + 1U + m_callsign.size() + 1U;
// DMR Id
buffer[length++] = 0x00U;
buffer[length++] = 0x00U;
buffer[length++] = 0x00U;
// Rpt Id
buffer[length++] = 0x00U;
buffer[length++] = 0x00U;
buffer[length++] = 0x00U;
buffer[length++] = 0x00U;
// Talk Group
buffer[length++] = 0x00U;
buffer[length++] = 0x00U;
buffer[length++] = 0x00U;
// Time Slot
buffer[length++] = 0x00U;
// Color Code
buffer[length++] = 0x00U;
// Callsign
for (std::string::const_iterator it = m_callsign.cbegin(); it != m_callsign.cend(); ++it)
buffer[length++] = *it;
// End of Metadata
buffer[length++] = 0x00U;
length = 70U;
}
if (length > 0U) {
if (m_debug)
CUtils::dump(1U, "FM Network Data Sent", buffer, length);
return m_socket.write(buffer, length, m_addr, m_addrLen);
} else {
return true;
}
}

View File

@@ -31,7 +31,7 @@ enum FM_NETWORK_PROTOCOL {
class CFMNetwork { class CFMNetwork {
public: public:
CFMNetwork(const std::string& protocol, const std::string& myAddress, unsigned int myPort, const std::string& gatewayAddress, unsigned int gatewayPort, bool debug); CFMNetwork(const std::string& callsign, const std::string& protocol, const std::string& myAddress, unsigned int myPort, const std::string& gatewayAddress, unsigned int gatewayPort, bool debug);
~CFMNetwork(); ~CFMNetwork();
bool open(); bool open();
@@ -40,7 +40,7 @@ public:
bool writeData(float* data, unsigned int nSamples); bool writeData(float* data, unsigned int nSamples);
bool writeEOT(); bool writeEnd();
unsigned int read(float* data, unsigned int nSamples); unsigned int read(float* data, unsigned int nSamples);
@@ -51,6 +51,7 @@ public:
void clock(unsigned int ms); void clock(unsigned int ms);
private: private:
std::string m_callsign;
FM_NETWORK_PROTOCOL m_protocol; FM_NETWORK_PROTOCOL m_protocol;
CUDPSocket m_socket; CUDPSocket m_socket;
sockaddr_storage m_addr; sockaddr_storage m_addr;
@@ -59,6 +60,8 @@ private:
bool m_enabled; bool m_enabled;
CRingBuffer<unsigned char> m_buffer; CRingBuffer<unsigned char> m_buffer;
unsigned int m_seqNo; unsigned int m_seqNo;
bool writeStart();
}; };
#endif #endif

View File

@@ -1800,6 +1800,7 @@ bool CMMDVMHost::createPOCSAGNetwork()
bool CMMDVMHost::createFMNetwork() bool CMMDVMHost::createFMNetwork()
{ {
std::string callsign = m_conf.getFMCallsign();
std::string protocol = m_conf.getFMNetworkProtocol(); std::string protocol = m_conf.getFMNetworkProtocol();
std::string gatewayAddress = m_conf.getFMGatewayAddress(); std::string gatewayAddress = m_conf.getFMGatewayAddress();
unsigned int gatewayPort = m_conf.getFMGatewayPort(); unsigned int gatewayPort = m_conf.getFMGatewayPort();
@@ -1824,7 +1825,7 @@ bool CMMDVMHost::createFMNetwork()
LogInfo(" RX Audio Gain: %.2f", rxAudioGain); LogInfo(" RX Audio Gain: %.2f", rxAudioGain);
LogInfo(" Mode Hang: %us", m_fmNetModeHang); LogInfo(" Mode Hang: %us", m_fmNetModeHang);
m_fmNetwork = new CFMNetwork(protocol, localAddress, localPort, gatewayAddress, gatewayPort, debug); m_fmNetwork = new CFMNetwork(callsign, protocol, localAddress, localPort, gatewayAddress, gatewayPort, debug);
bool ret = m_fmNetwork->open(); bool ret = m_fmNetwork->open();
if (!ret) { if (!ret) {

View File

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