Skip to content

Commit

Permalink
Allow the USRP audio format to be used natively by the FM networking.
Browse files Browse the repository at this point in the history
  • Loading branch information
g4klx committed Mar 14, 2021
1 parent 7c14a6e commit fb0d1ef
Show file tree
Hide file tree
Showing 7 changed files with 141 additions and 47 deletions.
10 changes: 9 additions & 1 deletion Conf.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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(),
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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;
Expand Down
2 changes: 2 additions & 0 deletions Conf.h
Original file line number Diff line number Diff line change
Expand Up @@ -296,6 +296,7 @@ class CConf

// The FM Network section
bool getFMNetworkEnabled() const;
std::string getFMNetworkFormat() const;
std::string getFMGatewayAddress() const;
unsigned int getFMGatewayPort() const;
std::string getFMLocalAddress() const;
Expand Down Expand Up @@ -603,6 +604,7 @@ class CConf
bool m_pocsagNetworkDebug;

bool m_fmNetworkEnabled;
std::string m_fmNetworkFormat;
std::string m_fmGatewayAddress;
unsigned int m_fmGatewayPort;
std::string m_fmLocalAddress;
Expand Down
155 changes: 114 additions & 41 deletions FMNetwork.cpp
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -27,15 +27,17 @@

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),
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());
Expand All @@ -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);
Expand Down Expand Up @@ -106,46 +111,97 @@ bool CFMNetwork::writeData(float* data, unsigned int nSamples)
}
#endif

unsigned int length = 3U;

unsigned char buffer[1500U];
::memset(buffer, 0x00U, 1500U);

buffer[0U] = 'F';
buffer[1U] = 'M';
buffer[2U] = 'D';
unsigned char buffer[2000U];
::memset(buffer, 0x00U, 2000U);

unsigned int length = 0U;

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)
Expand All @@ -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)
Expand Down Expand Up @@ -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);
}
}
13 changes: 10 additions & 3 deletions FMNetwork.h
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -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();
Expand All @@ -52,6 +57,7 @@ class CFMNetwork {
void clock(unsigned int ms);

private:
FM_FORMAT m_format;
CUDPSocket m_socket;
sockaddr_storage m_addr;
unsigned int m_addrLen;
Expand All @@ -60,12 +66,13 @@ class CFMNetwork {
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
2 changes: 2 additions & 0 deletions MMDVM.ini
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 3 additions & 1 deletion MMDVMHost.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand All @@ -1805,14 +1806,15 @@ 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());
LogInfo(" Local Port: %u", localPort);
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) {
Expand Down
2 changes: 1 addition & 1 deletion Version.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,6 @@
#if !defined(VERSION_H)
#define VERSION_H

const char* VERSION = "20210312";
const char* VERSION = "20210314";

#endif

0 comments on commit fb0d1ef

Please sign in to comment.