Allow the USRP audio format to be used natively by the FM networking.

This commit is contained in:
Jonathan Naylor 2021-03-14 12:16:39 +00:00
parent 7c14a6ec40
commit fb0d1ef5e2
7 changed files with 139 additions and 45 deletions

View file

@ -283,6 +283,7 @@ m_pocsagLocalPort(0U),
m_pocsagNetworkModeHang(3U),
m_pocsagNetworkDebug(false),
m_fmNetworkEnabled(false),
m_fmNetworkFormat("MMDVM"),
m_fmGatewayAddress(),
m_fmGatewayPort(0U),
m_fmLocalAddress(),
@ -440,7 +441,7 @@ bool CConf::read()
value++;
} else {
// if value is not quoted, remove after # (to make comment)
::strtok(value, "#");
(void)::strtok(value, "#");
}
if (section == SECTION_GENERAL) {
@ -998,6 +999,8 @@ bool CConf::read()
} else if (section == SECTION_FM_NETWORK) {
if (::strcmp(key, "Enable") == 0)
m_fmNetworkEnabled = ::atoi(value) == 1;
else if (::strcmp(key, "Format") == 0)
m_fmNetworkFormat = value;
else if (::strcmp(key, "LocalAddress") == 0)
m_fmLocalAddress = value;
else if (::strcmp(key, "LocalPort") == 0)
@ -2197,6 +2200,11 @@ bool CConf::getFMNetworkEnabled() const
return m_fmNetworkEnabled;
}
std::string CConf::getFMNetworkFormat() const
{
return m_fmNetworkFormat;
}
std::string CConf::getFMGatewayAddress() const
{
return m_fmGatewayAddress;

2
Conf.h
View file

@ -296,6 +296,7 @@ public:
// The FM Network section
bool getFMNetworkEnabled() const;
std::string getFMNetworkFormat() const;
std::string getFMGatewayAddress() const;
unsigned int getFMGatewayPort() const;
std::string getFMLocalAddress() const;
@ -603,6 +604,7 @@ private:
bool m_pocsagNetworkDebug;
bool m_fmNetworkEnabled;
std::string m_fmNetworkFormat;
std::string m_fmGatewayAddress;
unsigned int m_fmGatewayPort;
std::string m_fmLocalAddress;

View file

@ -1,5 +1,5 @@
/*
* Copyright (C) 2020 by Jonathan Naylor G4KLX
* Copyright (C) 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
@ -27,7 +27,8 @@
const unsigned int BUFFER_LENGTH = 500U;
CFMNetwork::CFMNetwork(const std::string& localAddress, unsigned int localPort, const std::string& gatewayAddress, unsigned int gatewayPort, unsigned int sampleRate, bool debug) :
CFMNetwork::CFMNetwork(const std::string& format, const std::string& localAddress, unsigned int localPort, const std::string& gatewayAddress, unsigned int gatewayPort, unsigned int sampleRate, bool debug) :
m_format(FMF_MMDVM),
m_socket(localAddress, localPort),
m_addr(),
m_addrLen(0U),
@ -35,7 +36,8 @@ m_sampleRate(sampleRate),
m_debug(debug),
m_enabled(false),
m_buffer(2000U, "FM Network"),
m_pollTimer(1000U, 5U)
m_pollTimer(1000U, 5U),
m_seqNo(0U)
{
assert(gatewayPort > 0U);
assert(!gatewayAddress.empty());
@ -44,6 +46,9 @@ m_pollTimer(1000U, 5U)
if (CUDPSocket::lookup(gatewayAddress, gatewayPort, m_addr, m_addrLen) != 0)
m_addrLen = 0U;
if (format == "USRP")
m_format = FMF_USRP;
#if !defined(_WIN32) && !defined(_WIN64)
int error;
m_incoming = ::src_new(SRC_SINC_FASTEST, 1, &error);
@ -106,46 +111,97 @@ bool CFMNetwork::writeData(float* data, unsigned int nSamples)
}
#endif
unsigned int length = 3U;
unsigned char buffer[2000U];
::memset(buffer, 0x00U, 2000U);
unsigned char buffer[1500U];
::memset(buffer, 0x00U, 1500U);
unsigned int length = 0U;
buffer[0U] = 'F';
buffer[1U] = 'M';
buffer[2U] = 'D';
if (m_format == FMF_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, this may be wrong
buffer[length++] = 0x00U;
buffer[length++] = 0x00U;
buffer[length++] = 0x00U;
buffer[length++] = 0x01U;
buffer[length++] = 0x00U;
buffer[length++] = 0x00U;
buffer[length++] = 0x00U;
buffer[length++] = 0x00U;
// Type, 0 for audio
buffer[length++] = 0x00U;
buffer[length++] = 0x00U;
buffer[length++] = 0x00U;
buffer[length++] = 0x00U;
buffer[length++] = 0x00U;
buffer[length++] = 0x00U;
buffer[length++] = 0x00U;
buffer[length++] = 0x00U;
buffer[length++] = 0x00U;
buffer[length++] = 0x00U;
buffer[length++] = 0x00U;
buffer[length++] = 0x00U;
} else {
buffer[length++] = 'F';
buffer[length++] = 'M';
buffer[length++] = 'D';
}
#if defined(_WIN32) || defined(_WIN64)
for (long i = 0L; i < nSamples; i++) {
short val = ( short)((data[i] ) * 32767.0F); // Changing audio format from U16BE to S16LE
for (unsigned int i = 0U; i < nSamples; i++) {
short val = short(data[i] * 32767.0F + 0.5F); // Changing audio format from float to S16LE
#else
for (long i = 0L; i < src.output_frames_gen; i++) {
short val = ( short)((src.data_out[i] ) * 32767.0F ); // Changing audio format from U16BE to S16LE
short val = short(src.data_out[i] * 32767.0F + 0.5F); // Changing audio format from float to S16LE
#endif
buffer[length++] = (val >> 0) & 0xFFU; // changing from BE to LE
buffer[length++] = (val >> 8) & 0xFFU; // changing from BE to LE
buffer[length++] = (val >> 0) & 0xFFU;
buffer[length++] = (val >> 8) & 0xFFU;
}
if (m_debug)
CUtils::dump(1U, "FM Network Data Sent", buffer, length);
m_seqNo++;
return m_socket.write(buffer, length, m_addr, m_addrLen);
}
bool CFMNetwork::writeEOT()
{
unsigned char buffer[10U];
::memset(buffer, 0x00U, 10U);
if (m_format == FMF_MMDVM) {
unsigned char buffer[10U];
::memset(buffer, 0x00U, 10U);
buffer[0U] = 'F';
buffer[1U] = 'M';
buffer[2U] = 'E';
buffer[0U] = 'F';
buffer[1U] = 'M';
buffer[2U] = 'E';
if (m_debug)
CUtils::dump(1U, "FM Network End of Transmission Sent", buffer, 3U);
if (m_debug)
CUtils::dump(1U, "FM Network End of Transmission Sent", buffer, 3U);
return m_socket.write(buffer, 3U, m_addr, m_addrLen);
return m_socket.write(buffer, 3U, m_addr, m_addrLen);
}
return true;
}
void CFMNetwork::clock(unsigned int ms)
@ -170,21 +226,36 @@ void CFMNetwork::clock(unsigned int ms)
// return;
//}
// Ignore incoming polls
if (::memcmp(buffer, "FMP", 3U) == 0)
return;
// Invalid packet type?
if (::memcmp(buffer, "FMD", 3U) != 0)
return;
if (!m_enabled)
return;
if (m_debug)
CUtils::dump(1U, "FM Network Data Received", buffer, length);
m_buffer.addData(buffer + 3U, length - 3U);
if (m_format == FMF_USRP) {
// Invalid packet type?
if (::memcmp(buffer, "USRP", 4U) != 0)
return;
// The type is a big-endian 4-byte integer
unsigned int type = (buffer[20U] << 24) +
(buffer[21U] << 16) +
(buffer[22U] << 8) +
(buffer[23U] << 0);
if (type == 0U)
m_buffer.addData(buffer + 32U, length - 32U);
} else {
// Ignore incoming polls
if (::memcmp(buffer, "FMP", 3U) == 0)
return;
// Invalid packet type?
if (::memcmp(buffer, "FMD", 3U) != 0)
return;
m_buffer.addData(buffer + 3U, length - 3U);
}
}
unsigned int CFMNetwork::read(float* data, unsigned int nSamples)
@ -274,16 +345,18 @@ void CFMNetwork::enable(bool enabled)
m_enabled = enabled;
}
bool CFMNetwork::writePoll()
void CFMNetwork::writePoll()
{
unsigned char buffer[3U];
if (m_format == FMF_MMDVM) {
unsigned char buffer[3U];
buffer[0U] = 'F';
buffer[1U] = 'M';
buffer[2U] = 'P';
buffer[0U] = 'F';
buffer[1U] = 'M';
buffer[2U] = 'P';
if (m_debug)
CUtils::dump(1U, "FM Network Poll Sent", buffer, 3U);
if (m_debug)
CUtils::dump(1U, "FM Network Poll Sent", buffer, 3U);
return m_socket.write(buffer, 3U, m_addr, m_addrLen);
m_socket.write(buffer, 3U, m_addr, m_addrLen);
}
}

View file

@ -1,5 +1,5 @@
/*
* Copyright (C) 2020 by Jonathan Naylor G4KLX
* Copyright (C) 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
@ -30,9 +30,14 @@
#include <cstdint>
#include <string>
enum FM_FORMAT {
FMF_MMDVM,
FMF_USRP
};
class CFMNetwork {
public:
CFMNetwork(const std::string& myAddress, unsigned int myPort, const std::string& gatewayAddress, unsigned int gatewayPort, unsigned int sampleRate, bool debug);
CFMNetwork(const std::string& format, const std::string& myAddress, unsigned int myPort, const std::string& gatewayAddress, unsigned int gatewayPort, unsigned int sampleRate, bool debug);
~CFMNetwork();
bool open();
@ -52,6 +57,7 @@ public:
void clock(unsigned int ms);
private:
FM_FORMAT m_format;
CUDPSocket m_socket;
sockaddr_storage m_addr;
unsigned int m_addrLen;
@ -60,12 +66,13 @@ private:
bool m_enabled;
CRingBuffer<unsigned char> m_buffer;
CTimer m_pollTimer;
unsigned int m_seqNo;
#if !defined(_WIN32) && !defined(_WIN64)
SRC_STATE* m_incoming;
SRC_STATE* m_outgoing;
#endif
bool writePoll();
void writePoll();
};
#endif

View file

@ -275,6 +275,8 @@ Debug=0
[FM Network]
Enable=1
# Values are MMDVM and USRP
Format=USRP
LocalAddress=127.0.0.1
LocalPort=3810
GatewayAddress=127.0.0.1

View file

@ -1796,6 +1796,7 @@ bool CMMDVMHost::createPOCSAGNetwork()
bool CMMDVMHost::createFMNetwork()
{
std::string format = m_conf.getFMNetworkFormat();
std::string gatewayAddress = m_conf.getFMGatewayAddress();
unsigned int gatewayPort = m_conf.getFMGatewayPort();
std::string localAddress = m_conf.getFMLocalAddress();
@ -1805,6 +1806,7 @@ bool CMMDVMHost::createFMNetwork()
bool debug = m_conf.getFMNetworkDebug();
LogInfo("FM Network Parameters");
LogInfo(" Format: %s", format.c_str());
LogInfo(" Gateway Address: %s", gatewayAddress.c_str());
LogInfo(" Gateway Port: %u", gatewayPort);
LogInfo(" Local Address: %s", localAddress.c_str());
@ -1812,7 +1814,7 @@ bool CMMDVMHost::createFMNetwork()
LogInfo(" Sample Rate: %u", sampleRate);
LogInfo(" Mode Hang: %us", m_fmNetModeHang);
m_fmNetwork = new CFMNetwork(localAddress, localPort, gatewayAddress, gatewayPort, sampleRate, debug);
m_fmNetwork = new CFMNetwork(format, localAddress, localPort, gatewayAddress, gatewayPort, sampleRate, debug);
bool ret = m_fmNetwork->open();
if (!ret) {

View file

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