Simple System Fusion bent pipe.

This commit is contained in:
Jonathan Naylor 2016-02-16 07:27:13 +00:00
parent 04dddc68a1
commit 647c5d652b
9 changed files with 266 additions and 145 deletions

View file

@ -25,7 +25,7 @@
#include "DMRControl.h" #include "DMRControl.h"
#include "TFTSerial.h" #include "TFTSerial.h"
#include "NullDisplay.h" #include "NullDisplay.h"
#include "YSFEcho.h" #include "YSFControl.h"
#include <cstdio> #include <cstdio>
@ -166,9 +166,18 @@ int CMMDVMHost::run()
dmr = new CDMRControl(id, colorCode, timeout, m_modem, m_dmrNetwork, m_display, duplex); dmr = new CDMRControl(id, colorCode, timeout, m_modem, m_dmrNetwork, m_display, duplex);
} }
CYSFEcho* ysf = NULL; CYSFControl* ysf = NULL;
if (m_ysfEnabled) if (m_ysfEnabled) {
ysf = new CYSFEcho(2U, 10000U); std::string callsign = m_conf.getCallsign();
unsigned int timeout = m_conf.getTimeout();
bool duplex = m_conf.getDuplex();
LogInfo("System Fusion Parameters");
LogInfo(" Callsign: %s", callsign.c_str());
LogInfo(" Timeout: %us", timeout);
ysf = new CYSFControl(callsign, m_display, timeout, duplex);
}
m_modeTimer.setTimeout(m_conf.getModeHang()); m_modeTimer.setTimeout(m_conf.getModeHang());
@ -226,11 +235,11 @@ int CMMDVMHost::run()
len = m_modem->readYSFData(data); len = m_modem->readYSFData(data);
if (ysf != NULL && len > 0U) { if (ysf != NULL && len > 0U) {
if (m_mode == MODE_IDLE) { if (m_mode == MODE_IDLE) {
bool ret = ysf->writeData(data, len); bool ret = ysf->writeModem(data);
if (ret) if (ret)
setMode(MODE_YSF); setMode(MODE_YSF);
} else if (m_mode == MODE_YSF) { } else if (m_mode == MODE_YSF) {
ysf->writeData(data, len); ysf->writeModem(data);
m_modeTimer.start(); m_modeTimer.start();
} else { } else {
LogWarning("System Fusion modem data received when in mode %u", m_mode); LogWarning("System Fusion modem data received when in mode %u", m_mode);
@ -294,7 +303,7 @@ int CMMDVMHost::run()
if (ysf != NULL) { if (ysf != NULL) {
ret = m_modem->hasYSFSpace(); ret = m_modem->hasYSFSpace();
if (ret) { if (ret) {
len = ysf->readData(data); len = ysf->readModem(data);
if (len > 0U) { if (len > 0U) {
if (m_mode == MODE_IDLE) { if (m_mode == MODE_IDLE) {
setMode(MODE_YSF); setMode(MODE_YSF);

View file

@ -189,9 +189,9 @@
<ClInclude Include="UDPSocket.h" /> <ClInclude Include="UDPSocket.h" />
<ClInclude Include="Utils.h" /> <ClInclude Include="Utils.h" />
<ClInclude Include="Version.h" /> <ClInclude Include="Version.h" />
<ClInclude Include="YSFControl.h" />
<ClInclude Include="YSFConvolution.h" /> <ClInclude Include="YSFConvolution.h" />
<ClInclude Include="YSFDefines.h" /> <ClInclude Include="YSFDefines.h" />
<ClInclude Include="YSFEcho.h" />
<ClInclude Include="YSFFICH.h" /> <ClInclude Include="YSFFICH.h" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
@ -233,8 +233,8 @@
<ClCompile Include="Timer.cpp" /> <ClCompile Include="Timer.cpp" />
<ClCompile Include="UDPSocket.cpp" /> <ClCompile Include="UDPSocket.cpp" />
<ClCompile Include="Utils.cpp" /> <ClCompile Include="Utils.cpp" />
<ClCompile Include="YSFControl.cpp" />
<ClCompile Include="YSFConvolution.cpp" /> <ClCompile Include="YSFConvolution.cpp" />
<ClCompile Include="YSFEcho.cpp" />
<ClCompile Include="YSFFICH.cpp" /> <ClCompile Include="YSFFICH.cpp" />
</ItemGroup> </ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />

View file

@ -95,9 +95,6 @@
<ClInclude Include="YSFDefines.h"> <ClInclude Include="YSFDefines.h">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="YSFEcho.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Version.h"> <ClInclude Include="Version.h">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</ClInclude> </ClInclude>
@ -152,6 +149,9 @@
<ClInclude Include="DMRSlotType.h"> <ClInclude Include="DMRSlotType.h">
<Filter>Header Files</Filter> <Filter>Header Files</Filter>
</ClInclude> </ClInclude>
<ClInclude Include="YSFControl.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<ClCompile Include="BPTC19696.cpp"> <ClCompile Include="BPTC19696.cpp">
@ -223,9 +223,6 @@
<ClCompile Include="Utils.cpp"> <ClCompile Include="Utils.cpp">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="YSFEcho.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="AMBEFEC.cpp"> <ClCompile Include="AMBEFEC.cpp">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
@ -277,5 +274,8 @@
<ClCompile Include="DMRSlotType.cpp"> <ClCompile Include="DMRSlotType.cpp">
<Filter>Source Files</Filter> <Filter>Source Files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="YSFControl.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup> </ItemGroup>
</Project> </Project>

View file

@ -7,7 +7,7 @@ LDFLAGS = -g
OBJECTS = \ OBJECTS = \
AMBEFEC.o BPTC19696.o Conf.o CRC.o Display.o DMRControl.o DMRCSBK.o DMRData.o DMRDataHeader.o DMREMB.o DMREmbeddedLC.o DMRFullLC.o DMRIPSC.o DMRLC.o DMRShortLC.o \ AMBEFEC.o BPTC19696.o Conf.o CRC.o Display.o DMRControl.o DMRCSBK.o DMRData.o DMRDataHeader.o DMREMB.o DMREmbeddedLC.o DMRFullLC.o DMRIPSC.o DMRLC.o DMRShortLC.o \
DMRSlot.o DMRSlotType.o DStarControl.o DStarHeader.o DStarNetwork.o DStarSlowData.o Golay2087.o Golay24128.o Hamming.o Log.o MMDVMHost.o Modem.o NullDisplay.o \ DMRSlot.o DMRSlotType.o DStarControl.o DStarHeader.o DStarNetwork.o DStarSlowData.o Golay2087.o Golay24128.o Hamming.o Log.o MMDVMHost.o Modem.o NullDisplay.o \
QR1676.o RS129.o SerialController.o SHA256.o StopWatch.o Sync.o TFTSerial.o Timer.o UDPSocket.o Utils.o YSFConvolution.o YSFEcho.o YSFFICH.o QR1676.o RS129.o SerialController.o SHA256.o StopWatch.o Sync.o TFTSerial.o Timer.o UDPSocket.o Utils.o YSFControl.o YSFConvolution.o YSFFICH.o
all: MMDVMHost all: MMDVMHost

179
YSFControl.cpp Normal file
View file

@ -0,0 +1,179 @@
/*
* Copyright (C) 2015,2016 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
* the Free Software Foundation; version 2 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*/
#include "YSFControl.h"
#include "Utils.h"
#include "Sync.h"
#include "Log.h"
#include <cassert>
#include <ctime>
// #define DUMP_YSF
CYSFControl::CYSFControl(const std::string& callsign, IDisplay* display, unsigned int timeout, bool duplex) :
m_display(display),
m_duplex(duplex),
m_queue(1000U, "YSF Control"),
m_state(RS_LISTENING),
m_timeoutTimer(1000U, timeout),
m_frames(0U),
m_fp(NULL)
{
assert(display != NULL);
}
CYSFControl::~CYSFControl()
{
}
bool CYSFControl::writeModem(unsigned char *data)
{
unsigned char type = data[0U];
if (type == TAG_LOST && m_state == RS_RELAYING_RF_AUDIO) {
LogMessage("YSF, transmission lost, %.1f seconds", float(m_frames) / 10.0F);
writeEndOfTransmission();
return false;
}
if (type == TAG_LOST)
return false;
bool valid = (data[1U] & YSF_CKSUM_OK) == YSF_CKSUM_OK;
unsigned char fi = data[1U] & YSF_FI_MASK;
unsigned char dt = data[1U] & YSF_DT_MASK;
if (valid && m_state == RS_LISTENING) {
m_frames = 0U;
m_timeoutTimer.start();
m_state = RS_RELAYING_RF_AUDIO;
LogMessage("YSF, received RF header");
}
if (fi == YSF_DT_TERMINATOR_CHANNEL) {
if (m_state == RS_RELAYING_RF_AUDIO) {
CSync::addYSFSync(data + 2U);
m_frames++;
if (m_duplex) {
data[0U] = TAG_DATA;
data[1U] = 0x00U;
writeQueue(data);
}
LogMessage("YSF, received RF end of transmission, %.1f seconds", float(m_frames) / 10.0F);
writeEndOfTransmission();
}
return false;
} else {
CSync::addYSFSync(data + 2U);
m_frames++;
if (m_duplex) {
data[0U] = TAG_DATA;
data[1U] = 0x00U;
writeQueue(data);
}
}
return true;
}
unsigned int CYSFControl::readModem(unsigned char* data)
{
if (m_queue.isEmpty())
return 0U;
unsigned char len = 0U;
m_queue.getData(&len, 1U);
m_queue.getData(data, len);
return len;
}
void CYSFControl::writeEndOfTransmission()
{
m_state = RS_LISTENING;
m_timeoutTimer.stop();
m_display->clearFusion();
#if defined(DUMP_YSF)
closeFile();
#endif
}
void CYSFControl::clock(unsigned int ms)
{
m_timeoutTimer.clock(ms);
}
void CYSFControl::writeQueue(const unsigned char *data)
{
assert(data != NULL);
if (m_timeoutTimer.isRunning() && m_timeoutTimer.hasExpired())
return;
unsigned char len = YSF_FRAME_LENGTH_BYTES + 2U;
m_queue.addData(&len, 1U);
m_queue.addData(data, len);
}
bool CYSFControl::openFile()
{
if (m_fp != NULL)
return true;
time_t t;
::time(&t);
struct tm* tm = ::localtime(&t);
char name[100U];
::sprintf(name, "YSF_%04d%02d%02d_%02d%02d%02d.ambe", tm->tm_year + 1900, tm->tm_mon + 1, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec);
m_fp = ::fopen(name, "wb");
if (m_fp == NULL)
return false;
::fwrite("YSF", 1U, 3U, m_fp);
return true;
}
bool CYSFControl::writeFile(const unsigned char* data)
{
if (m_fp == NULL)
return false;
::fwrite(data, 1U, YSF_FRAME_LENGTH_BYTES, m_fp);
return true;
}
void CYSFControl::closeFile()
{
if (m_fp != NULL) {
::fclose(m_fp);
m_fp = NULL;
}
}

60
YSFControl.h Normal file
View file

@ -0,0 +1,60 @@
/*
* Copyright (C) 2015,2016 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
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#if !defined(YSFControl_H)
#define YSFControl_H
#include "YSFDefines.h"
#include "RingBuffer.h"
#include "Display.h"
#include "Defines.h"
#include "Timer.h"
#include "Modem.h"
#include <string>
class CYSFControl {
public:
CYSFControl(const std::string& callsign, IDisplay* display, unsigned int timeout, bool duplex);
~CYSFControl();
bool writeModem(unsigned char* data);
unsigned int readModem(unsigned char* data);
void clock(unsigned int ms);
private:
IDisplay* m_display;
bool m_duplex;
CRingBuffer<unsigned char> m_queue;
RPT_STATE m_state;
CTimer m_timeoutTimer;
unsigned int m_frames;
FILE* m_fp;
void writeQueue(const unsigned char* data);
void writeEndOfTransmission();
bool openFile();
bool writeFile(const unsigned char* data);
void closeFile();
};
#endif

View file

@ -1,5 +1,5 @@
/* /*
* Copyright (C) 2015 by Jonathan Naylor G4KLX * Copyright (C) 2015,2016 by Jonathan Naylor G4KLX
* *
* This program is free software; you can redistribute it and/or modify * 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 * it under the terms of the GNU General Public License as published by
@ -27,6 +27,7 @@ const unsigned int YSF_SYNC_LENGTH_BYTES = 5U;
const unsigned char YSF_FI_MASK = 0xC0U; const unsigned char YSF_FI_MASK = 0xC0U;
const unsigned char YSF_DT_MASK = 0x30U; const unsigned char YSF_DT_MASK = 0x30U;
const unsigned char YSF_DT_HEADER_CHANNEL = 0x00U;
const unsigned char YSF_DT_TERMINATOR_CHANNEL = 0x80U; const unsigned char YSF_DT_TERMINATOR_CHANNEL = 0x80U;
const unsigned char YSF_CKSUM_OK = 0x01U; const unsigned char YSF_CKSUM_OK = 0x01U;

View file

@ -1,85 +0,0 @@
/*
* Copyright (C) 2015 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
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "YSFEcho.h"
#include "YSFDefines.h"
CYSFEcho::CYSFEcho(unsigned int delay, unsigned int space) :
m_buffer(space, "YSF Echo"),
m_timer(1000U, delay)
{
}
CYSFEcho::~CYSFEcho()
{
}
unsigned int CYSFEcho::readData(unsigned char* data)
{
if (!hasData())
return 0U;
unsigned char len;
m_buffer.getData(&len, 1U);
m_buffer.getData(data, len);
// If the FICH is valid, regenerate the sync
if ((data[1U] & 0x01U) == 0x01U) {
data[2U] = YSF_SYNC_BYTES[0U];
data[3U] = YSF_SYNC_BYTES[1U];
data[4U] = YSF_SYNC_BYTES[2U];
data[5U] = YSF_SYNC_BYTES[3U];
data[6U] = YSF_SYNC_BYTES[4U];
}
if (!hasData())
m_timer.stop();
return len;
}
bool CYSFEcho::writeData(const unsigned char* data, unsigned int length)
{
bool ret = m_buffer.hasSpace(length + 1U);
if (!ret)
return false;
unsigned char len = length;
m_buffer.addData(&len, 1U);
m_buffer.addData(data, length);
m_timer.start();
return true;
}
bool CYSFEcho::hasData()
{
if (m_timer.isRunning() && m_timer.hasExpired())
return m_buffer.hasData();
else
return false;
}
void CYSFEcho::clock(unsigned int ms)
{
m_timer.clock(ms);
}

View file

@ -1,43 +0,0 @@
/*
* Copyright (C) 2015 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
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#if !defined(YSFECHO_H)
#define YSFECHO_H
#include "RingBuffer.h"
#include "Timer.h"
class CYSFEcho {
public:
CYSFEcho(unsigned int delay, unsigned int space);
~CYSFEcho();
unsigned int readData(unsigned char* data);
bool writeData(const unsigned char* data, unsigned int length);
bool hasData();
void clock(unsigned int ms);
private:
CRingBuffer<unsigned char> m_buffer;
CTimer m_timer;
};
#endif