Mostly complete processing of RF frames.

This commit is contained in:
Jonathan Naylor 2020-10-17 21:59:27 +01:00
parent 9a72e95ec0
commit 48f95be982
8 changed files with 118 additions and 35 deletions

View file

@ -72,7 +72,7 @@ m_networkWatchdog(1000U, 0U, 1500U),
m_elapsed(),
m_rfFrames(0U),
m_netFrames(0U),
m_rfLastFN(0U),
m_rfFN(0U),
m_rfErrs(0U),
m_rfBits(1U),
m_rfLICH(),
@ -179,7 +179,7 @@ bool CM17Control::writeModem(unsigned char* data, unsigned int len)
m_maxRSSI = m_rssi;
m_aveRSSI = m_rssi;
m_rssiCount = 1U;
m_rfLastFN = 0U;
m_rfFN = 0U;
#if defined(DUMP_M17)
openFile();
@ -259,7 +259,7 @@ bool CM17Control::writeModem(unsigned char* data, unsigned int len)
bool valid = CM17CRC::checkCRC(frame, M17_FN_LENGTH_BITS + M17_PAYLOAD_LENGTH_BITS + M17_CRC_LENGTH_BITS);
if (valid) {
m_rfLastFN = (frame[0U] << 8) + (frame[1U] << 0);
m_rfFN = (frame[0U] << 8) + (frame[1U] << 0);
unsigned int frag1, frag2, frag3, frag4;
@ -270,7 +270,7 @@ bool CM17Control::writeModem(unsigned char* data, unsigned int len)
unsigned int lich3 = CGolay24128::decode24128(frag3);
unsigned int lich4 = CGolay24128::decode24128(frag4);
m_rfLICH.setFragment(data + 2U + M17_SYNC_LENGTH_BYTES, m_rfLastFN & 0x7FFFU);
m_rfLICH.setFragment(data + 2U + M17_SYNC_LENGTH_BYTES, m_rfFN & 0x7FFFU);
valid = m_rfLICH.isValid();
if (valid) {
@ -343,12 +343,11 @@ bool CM17Control::writeModem(unsigned char* data, unsigned int len)
#if defined(DUMP_M17)
writeFile(data + 2U);
#endif
CM17Convolution conv;
conv.start();
unsigned int n = 2U + M17_SYNC_LENGTH_BYTES + M17_LICH_FRAGMENT_LENGTH_BYTES;
for (unsigned int i = 0U; i < (M17_LICH_LENGTH_BYTES / 2U); i++) {
for (unsigned int i = 0U; i < ((M17_FN_LENGTH_BYTES + M17_PAYLOAD_LENGTH_BYTES + M17_CRC_LENGTH_BYTES) / 2U); i++) {
uint8_t s0 = data[n++];
uint8_t s1 = data[n++];
@ -360,19 +359,77 @@ bool CM17Control::writeModem(unsigned char* data, unsigned int len)
bool valid = CM17CRC::checkCRC(frame, M17_FN_LENGTH_BITS + M17_PAYLOAD_LENGTH_BITS + M17_CRC_LENGTH_BITS);
if (valid) {
m_rfLastFN = (frame[0U] << 8) + (frame[1U] << 0);
m_rfFN = (frame[0U] << 8) + (frame[1U] << 0);
} else {
m_rfLastFN++;
// Create a silence frame
m_rfFN++;
// The new FN
frame[0U] = m_rfFN >> 8;
frame[1U] = m_rfFN >> 0;
// Add silent audio
unsigned char dataType = m_rfLICH.getDataType();
switch (dataType) {
case 2U:
::memcpy(frame + M17_FN_LENGTH_BYTES + 0U, M17_3200_SILENCE, 8U);
::memcpy(frame + M17_FN_LENGTH_BYTES + 8U, M17_3200_SILENCE, 8U);
break;
case 3U:
::memcpy(frame + M17_FN_LENGTH_BYTES + 0U, M17_1600_SILENCE, 8U);
break;
default:
break;
}
// Add the CRC
CM17CRC::encodeCRC(frame, M17_FN_LENGTH_BITS + M17_PAYLOAD_LENGTH_BITS + M17_CRC_LENGTH_BITS);
}
unsigned char rfData[2U + M17_FRAME_LENGTH_BYTES];
rfData[0U] = TAG_DATA;
rfData[1U] = 0x00U;
CSync::addM17Sync(rfData + 2U);
// Re-encode the LICH fragment
m_rfLICH.getFragment(rfData + 2U + M17_SYNC_LENGTH_BYTES, m_rfFN & 0x7FFFU);
// XXX TODO Golay on LICH fragment
// Re-encode the payload
conv.encode(frame, rfData + 2U + M17_SYNC_LENGTH_BYTES + M17_LICH_FRAGMENT_LENGTH_BYTES, M17_FN_LENGTH_BITS + M17_PAYLOAD_LENGTH_BITS + M17_CRC_LENGTH_BITS);
// Calculate the BER
if (valid) {
for (unsigned int i = 2U; i < 50U; i++)
m_rfErrs += countBits(rfData[i] ^ data[i]);
m_rfBits += 272U;
float ber = float(m_rfErrs) / float(m_rfBits);
m_display->writeM17BER(ber);
}
if (m_duplex)
writeQueueRF(data);
writeQueueRF(rfData);
unsigned char netData[M17_LICH_LENGTH_BYTES + M17_FN_LENGTH_BYTES + M17_PAYLOAD_LENGTH_BYTES + M17_CRC_LENGTH_BYTES];
m_rfLICH.getNetworkData(netData + 0U);
// Copy the FN and payload from the frame
::memcpy(netData + M17_LICH_LENGTH_BYTES, frame, M17_FN_LENGTH_BYTES + M17_PAYLOAD_LENGTH_BYTES);
CM17CRC::encodeCRC(netData, M17_LICH_LENGTH_BITS + M17_FN_LENGTH_BITS + M17_PAYLOAD_LENGTH_BITS + M17_CRC_LENGTH_BITS);
writeNetwork(netData);
m_rfFrames++;
// EOT?
if ((m_rfLastFN & 0x8000U) == 0x8000U) {
if ((m_rfFN & 0x8000U) == 0x8000U) {
std::string source = m_rfLICH.getSource();
std::string dest = m_rfLICH.getDest();
@ -737,3 +794,17 @@ void CM17Control::enable(bool enabled)
m_enabled = enabled;
}
unsigned int CM17Control::countBits(unsigned char byte)
{
unsigned int count = 0U;
const unsigned char* p = &byte;
for (unsigned int i = 0U; i < 8U; i++) {
if (READ_BIT(p, i) != 0U)
count++;
}
return count;
}

View file

@ -63,7 +63,7 @@ private:
CStopWatch m_elapsed;
unsigned int m_rfFrames;
unsigned int m_netFrames;
unsigned int m_rfLastFN;
unsigned int m_rfFN;
unsigned int m_rfErrs;
unsigned int m_rfBits;
CM17LICH m_rfLICH;
@ -85,6 +85,8 @@ private:
void interleaver(const unsigned char* in, unsigned char* out) const;
void decorrelator(const unsigned char* in, unsigned char* out) const;
unsigned int countBits(unsigned char byte);
void writeEndRF();
void writeEndNet();

View file

@ -28,8 +28,8 @@ const unsigned char M17_SYNC_BYTES[] = {0x32U, 0x43U};
const unsigned int M17_SYNC_LENGTH_BITS = 16U;
const unsigned int M17_SYNC_LENGTH_BYTES = M17_SYNC_LENGTH_BITS / 8U;
const unsigned int M17_LICH_LENGTH_BITS = 244U;
const unsigned int M17_LICH_LENGTH_BYTES = 31U;
const unsigned int M17_LICH_LENGTH_BITS = 224U;
const unsigned int M17_LICH_LENGTH_BYTES = M17_LICH_LENGTH_BITS / 8U;
const unsigned int M17_LICH_FRAGMENT_LENGTH_BITS = 96U;
const unsigned int M17_LICH_FRAGMENT_LENGTH_BYTES = M17_LICH_FRAGMENT_LENGTH_BITS / 8U;
@ -43,4 +43,7 @@ const unsigned int M17_FN_LENGTH_BYTES = M17_FN_LENGTH_BITS / 8U;
const unsigned int M17_CRC_LENGTH_BITS = 16U;
const unsigned int M17_CRC_LENGTH_BYTES = M17_CRC_LENGTH_BITS / 8U;
const unsigned char M17_3200_SILENCE[] = {0x01U, 0x00U, 0x09U, 0x43U, 0x9CU, 0xE4U, 0x21U, 0x08U};
const unsigned char M17_1600_SILENCE[] = {0x01U, 0x00U, 0x04U, 0x00U, 0x25U, 0x75U, 0xDDU, 0xF2U};
#endif

View file

@ -31,8 +31,13 @@ public:
void setNetworkData(const unsigned char* data);
std::string getSource() const;
void setSource(const std::string& callsign);
std::string getDest() const;
void setDest(const std::string& callsign);
unsigned char getDataType() const;
void setDataType(unsigned char type);
void reset();
bool isValid() const;

View file

@ -29,7 +29,8 @@
const unsigned int BUFFER_LENGTH = 200U;
CM17Network::CM17Network(unsigned int port, bool debug) :
CM17Network::CM17Network(const std::string& callsign, unsigned int port, bool debug) :
m_callsign(callsign),
m_socket(port),
m_addr(),
m_addrLen(0U),
@ -40,7 +41,7 @@ m_inId(0U),
m_buffer(1000U, "M17 Network"),
m_random(),
m_state(M17N_NOTLINKED),
m_reflector(NULL),
m_encoded(NULL),
m_module(' '),
m_timer(1000U, 5U)
{
@ -49,6 +50,8 @@ m_timer(1000U, 5U)
m_random = mt;
m_encoded = new unsigned char[6U];
CM17Utils::encodeCallsign(m_callsign, m_encoded);
}
CM17Network::~CM17Network()
@ -63,17 +66,14 @@ bool CM17Network::open()
return m_socket.open(m_addr);
}
bool CM17Network::link(const std::string& address, unsigned int port, const std::string& reflector, char module)
bool CM17Network::link(const std::string& address, unsigned int port, char module)
{
if (CUDPSocket::lookup(address, port, m_addr, m_addrLen) != 0) {
m_state = M17N_NOTLINKED;
return false;
}
m_reflector = reflector;
m_module = module;
CM17Utils::encodeCallsign(m_reflector, m_encoded);
m_module = module;
m_state = M17N_LINKING;
@ -119,10 +119,12 @@ bool CM17Network::write(const unsigned char* data)
buffer[4U] = m_outId / 256U; // Unique session id
buffer[5U] = m_outId % 256U;
if (m_debug)
CUtils::dump(1U, "M17 data transmitted", buffer, 36U);
::memcpy(buffer + 6U, data, 48U);
return m_socket.write(buffer, 36U, m_addr, m_addrLen);
if (m_debug)
CUtils::dump(1U, "M17 data transmitted", buffer, 54U);
return m_socket.write(buffer, 54U, m_addr, m_addrLen);
}
void CM17Network::clock(unsigned int ms)
@ -163,21 +165,21 @@ void CM17Network::clock(unsigned int ms)
if (::memcmp(buffer + 0U, "ACKN", 4U) == 0) {
m_timer.stop();
m_state = M17N_LINKED;
LogMessage("M17, linked to %s", m_reflector.c_str());
LogMessage("M17, linked to reflector");
return;
}
if (::memcmp(buffer + 0U, "NACK", 4U) == 0) {
m_timer.stop();
m_state = M17N_NOTLINKED;
LogMessage("M17, link refused by %s", m_reflector.c_str());
LogMessage("M17, link refused by reflector");
return;
}
if (::memcmp(buffer + 0U, "DISC", 4U) == 0) {
m_timer.stop();
m_state = M17N_NOTLINKED;
LogMessage("M17, unlinked from %s", m_reflector.c_str());
LogMessage("M17, unlinked from reflector");
return;
}
@ -208,10 +210,10 @@ void CM17Network::clock(unsigned int ms)
if ((fn & 0x8000U) == 0x8000U)
m_inId = 0U;
unsigned char c = length;
unsigned char c = length - 6U;
m_buffer.addData(&c, 1U);
m_buffer.addData(buffer, length);
m_buffer.addData(buffer + 6U, length - 6U);
}
bool CM17Network::read(unsigned char* data)

View file

@ -36,12 +36,12 @@ enum M17NET_STATUS {
class CM17Network {
public:
CM17Network(unsigned int port, bool debug);
CM17Network(const std::string& callsign, unsigned int port, bool debug);
~CM17Network();
bool open();
bool link(const std::string& address, unsigned int port, const std::string& reflector, char module);
bool link(const std::string& address, unsigned int port, char module);
void unlink();
@ -58,6 +58,7 @@ public:
void clock(unsigned int ms);
private:
std::string m_callsign;
CUDPSocket m_socket;
sockaddr_storage m_addr;
unsigned int m_addrLen;
@ -68,7 +69,6 @@ private:
CRingBuffer<unsigned char> m_buffer;
std::mt19937 m_random;
M17NET_STATUS m_state;
std::string m_reflector;
unsigned char* m_encoded;
char m_module;
CTimer m_timer;

View file

@ -224,7 +224,7 @@ Debug=0
[M17 Network]
Enable=1
GatewayAddress=127.0.0.1
GatewayAddress=3.138.122.152
GatewayPort=17000
LocalPort=17000
# ModeHang=3

View file

@ -1551,7 +1551,7 @@ bool CMMDVMHost::createM17Network()
LogInfo(" Local Port: %u", localPort);
LogInfo(" Mode Hang: %us", m_m17NetModeHang);
m_m17Network = new CM17Network(localPort, debug);
m_m17Network = new CM17Network(m_callsign, localPort, debug);
bool ret = m_m17Network->open();
if (!ret) {
delete m_m17Network;
@ -1559,7 +1559,7 @@ bool CMMDVMHost::createM17Network()
return false;
}
m_m17Network->link(gatewayAddress, gatewayPort, "M17-USA", 'A');
m_m17Network->link(gatewayAddress, gatewayPort, 'A');
m_m17Network->enable(true);