From e2c7a28fb98b9d12a19e80ae89d9f4d179004952 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Mon, 22 Feb 2016 21:13:48 +0000 Subject: [PATCH] Add the optional System Fusion Parrot. --- Conf.cpp | 8 ++++ Conf.h | 2 + MMDVM.ini | 1 + MMDVMHost.cpp | 4 +- MMDVMHost.vcxproj | 2 + MMDVMHost.vcxproj.filters | 6 +++ Makefile | 2 +- YSFControl.cpp | 43 +++++++++++++++++- YSFControl.h | 5 ++- YSFParrot.cpp | 92 +++++++++++++++++++++++++++++++++++++++ YSFParrot.h | 46 ++++++++++++++++++++ 11 files changed, 206 insertions(+), 5 deletions(-) create mode 100644 YSFParrot.cpp create mode 100644 YSFParrot.h diff --git a/Conf.cpp b/Conf.cpp index 74ac69d00..ab61be2d1 100644 --- a/Conf.cpp +++ b/Conf.cpp @@ -75,6 +75,7 @@ m_dmrBeacons(false), m_dmrId(0U), m_dmrColorCode(2U), m_fusionEnabled(true), +m_fusionParrotEnabled(false), m_dstarNetworkEnabled(true), m_dstarGatewayAddress(), m_dstarGatewayPort(0U), @@ -222,6 +223,8 @@ bool CConf::read() } else if (section == SECTION_FUSION) { if (::strcmp(key, "Enable") == 0) m_fusionEnabled = ::atoi(value) == 1; + else if (::strcmp(key, "Parrot") == 0) + m_fusionParrotEnabled = ::atoi(value) == 1; } else if (section == SECTION_DSTAR_NETWORK) { if (::strcmp(key, "Enable") == 0) m_dstarNetworkEnabled = ::atoi(value) == 1; @@ -435,6 +438,11 @@ bool CConf::getFusionEnabled() const return m_fusionEnabled; } +bool CConf::getFusionParrotEnabled() const +{ + return m_fusionParrotEnabled; +} + bool CConf::getDStarNetworkEnabled() const { return m_dstarNetworkEnabled; diff --git a/Conf.h b/Conf.h index bddf0b294..39c7684da 100644 --- a/Conf.h +++ b/Conf.h @@ -75,6 +75,7 @@ class CConf // The System Fusion section bool getFusionEnabled() const; + bool getFusionParrotEnabled() const; // The D-Star Network section bool getDStarNetworkEnabled() const; @@ -143,6 +144,7 @@ class CConf unsigned int m_dmrColorCode; bool m_fusionEnabled; + bool m_fusionParrotEnabled; bool m_dstarNetworkEnabled; std::string m_dstarGatewayAddress; diff --git a/MMDVM.ini b/MMDVM.ini index 8748b28a3..4d100f4d2 100644 --- a/MMDVM.ini +++ b/MMDVM.ini @@ -46,6 +46,7 @@ ColorCode=1 [System Fusion] Enable=1 +Parrot=1 [D-Star Network] Enable=1 diff --git a/MMDVMHost.cpp b/MMDVMHost.cpp index acd1cd92e..c477c5ba6 100644 --- a/MMDVMHost.cpp +++ b/MMDVMHost.cpp @@ -171,12 +171,14 @@ int CMMDVMHost::run() std::string callsign = m_conf.getCallsign(); unsigned int timeout = m_conf.getTimeout(); bool duplex = m_conf.getDuplex(); + bool parrot = m_conf.getFusionParrotEnabled(); LogInfo("System Fusion Parameters"); LogInfo(" Callsign: %s", callsign.c_str()); LogInfo(" Timeout: %us", timeout); + LogInfo(" Parrot: %s", parrot ? "enabled" : "disabled"); - ysf = new CYSFControl(callsign, m_display, timeout, duplex); + ysf = new CYSFControl(callsign, m_display, timeout, duplex, parrot); } m_modeTimer.setTimeout(m_conf.getModeHang()); diff --git a/MMDVMHost.vcxproj b/MMDVMHost.vcxproj index e2960068e..87f753fcf 100644 --- a/MMDVMHost.vcxproj +++ b/MMDVMHost.vcxproj @@ -193,6 +193,7 @@ + @@ -236,6 +237,7 @@ + diff --git a/MMDVMHost.vcxproj.filters b/MMDVMHost.vcxproj.filters index 14741f953..fdd11f709 100644 --- a/MMDVMHost.vcxproj.filters +++ b/MMDVMHost.vcxproj.filters @@ -152,6 +152,9 @@ Header Files + + Header Files + @@ -277,5 +280,8 @@ Source Files + + Source Files + \ No newline at end of file diff --git a/Makefile b/Makefile index 38be0abe5..8596e72d0 100644 --- a/Makefile +++ b/Makefile @@ -7,7 +7,7 @@ LDFLAGS = -g 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 \ 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 YSFControl.o YSFConvolution.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 YSFParrot.o all: MMDVMHost diff --git a/YSFControl.cpp b/YSFControl.cpp index 32ea5087e..d2ab7dc43 100644 --- a/YSFControl.cpp +++ b/YSFControl.cpp @@ -29,20 +29,25 @@ * Uplink and downlink callsign addition. */ -CYSFControl::CYSFControl(const std::string& callsign, IDisplay* display, unsigned int timeout, bool duplex) : +CYSFControl::CYSFControl(const std::string& callsign, IDisplay* display, unsigned int timeout, bool duplex, bool parrot) : m_display(display), m_duplex(duplex), m_queue(1000U, "YSF Control"), m_state(RS_LISTENING), m_timeoutTimer(1000U, timeout), m_frames(0U), +m_parrot(NULL), m_fp(NULL) { assert(display != NULL); + + if (parrot) + m_parrot = new CYSFParrot(timeout); } CYSFControl::~CYSFControl() { + delete m_parrot; } bool CYSFControl::writeModem(unsigned char *data) @@ -87,12 +92,17 @@ bool CYSFControl::writeModem(unsigned char *data) writeQueue(data); } + if (m_parrot != NULL) { + data[0U] = TAG_EOT; + data[1U] = 0x00U; + writeParrot(data); + } + #if defined(DUMP_YSF) writeFile(data + 2U); #endif LogMessage("YSF, received RF end of transmission, %.1f seconds", float(m_frames) / 10.0F); - writeEndOfTransmission(); return false; @@ -107,6 +117,12 @@ bool CYSFControl::writeModem(unsigned char *data) writeQueue(data); } + if (m_parrot != NULL) { + data[0U] = TAG_DATA; + data[1U] = 0x00U; + writeParrot(data); + } + #if defined(DUMP_YSF) writeFile(data + 2U); #endif @@ -144,6 +160,19 @@ void CYSFControl::writeEndOfTransmission() void CYSFControl::clock(unsigned int ms) { m_timeoutTimer.clock(ms); + + if (m_parrot != NULL) { + m_parrot->clock(ms); + + unsigned int space = m_queue.freeSpace(); + bool hasData = m_parrot->hasData(); + + if (space > (YSF_FRAME_LENGTH_BYTES + 2U) && hasData) { + unsigned char data[YSF_FRAME_LENGTH_BYTES + 2U]; + m_parrot->read(data); + writeQueue(data); + } + } } void CYSFControl::writeQueue(const unsigned char *data) @@ -159,6 +188,16 @@ void CYSFControl::writeQueue(const unsigned char *data) m_queue.addData(data, len); } +void CYSFControl::writeParrot(const unsigned char *data) +{ + assert(data != NULL); + + if (m_timeoutTimer.isRunning() && m_timeoutTimer.hasExpired()) + return; + + m_parrot->write(data); +} + bool CYSFControl::openFile() { if (m_fp != NULL) diff --git a/YSFControl.h b/YSFControl.h index 2f838d77d..5fabdc174 100644 --- a/YSFControl.h +++ b/YSFControl.h @@ -21,6 +21,7 @@ #include "YSFDefines.h" #include "RingBuffer.h" +#include "YSFParrot.h" #include "Display.h" #include "Defines.h" #include "Timer.h" @@ -30,7 +31,7 @@ class CYSFControl { public: - CYSFControl(const std::string& callsign, IDisplay* display, unsigned int timeout, bool duplex); + CYSFControl(const std::string& callsign, IDisplay* display, unsigned int timeout, bool duplex, bool parrot); ~CYSFControl(); bool writeModem(unsigned char* data); @@ -46,9 +47,11 @@ class CYSFControl { RPT_STATE m_state; CTimer m_timeoutTimer; unsigned int m_frames; + CYSFParrot* m_parrot; FILE* m_fp; void writeQueue(const unsigned char* data); + void writeParrot(const unsigned char* data); void writeEndOfTransmission(); diff --git a/YSFParrot.cpp b/YSFParrot.cpp new file mode 100644 index 000000000..582d66a53 --- /dev/null +++ b/YSFParrot.cpp @@ -0,0 +1,92 @@ +/* +* Copyright (C) 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. +*/ + +#include "YSFParrot.h" +#include "YSFDefines.h" +#include "Defines.h" + +#include +#include +#include + +CYSFParrot::CYSFParrot(unsigned int timeout) : +m_data(NULL), +m_length(timeout * 1220U + 1000U), +m_used(0U), +m_ptr(0U), +m_timer(1000U, 2U) +{ + assert(timeout > 0U); + + m_data = new unsigned char[m_length]; +} + +CYSFParrot::~CYSFParrot() +{ + delete[] m_data; +} + +bool CYSFParrot::write(const unsigned char* data) +{ + assert(data != NULL); + + if ((m_length - m_used) < 1000U) + return false; + + ::memcpy(m_data + m_used, data, YSF_FRAME_LENGTH_BYTES + 2U); + m_used += YSF_FRAME_LENGTH_BYTES + 2U; + + if (data[0U] == TAG_EOT) { + m_timer.start(); + m_ptr = 0U; + } + + return true; +} + +void CYSFParrot::read(unsigned char* data) +{ + assert(data != NULL); + + if (m_used == 0U) + return; + + ::memcpy(data, m_data + m_ptr, YSF_FRAME_LENGTH_BYTES + 2U); + m_ptr += YSF_FRAME_LENGTH_BYTES + 2U; + + if (m_ptr >= m_used) { + m_timer.stop(); + m_used = 0U; + } +} + +bool CYSFParrot::hasData() +{ + if (m_timer.isRunning() && m_timer.hasExpired()) + return true; + + if (m_used == 0U) + return false; + + return false; +} + +void CYSFParrot::clock(unsigned int ms) +{ + m_timer.clock(ms); +} diff --git a/YSFParrot.h b/YSFParrot.h new file mode 100644 index 000000000..fd794608d --- /dev/null +++ b/YSFParrot.h @@ -0,0 +1,46 @@ +/* +* Copyright (C) 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(YAFParrot_H) +#define YSFParrot_H + +#include "Timer.h" + +class CYSFParrot +{ +public: + CYSFParrot(unsigned int timeout); + ~CYSFParrot(); + + bool write(const unsigned char* data); + + void read(unsigned char* data); + + bool hasData(); + + void clock(unsigned int ms); + +private: + unsigned char* m_data; + unsigned int m_length; + unsigned int m_used; + unsigned int m_ptr; + CTimer m_timer; +}; + +#endif