From b9ebdee601e73485e87ce7585012e2c7c06d86a2 Mon Sep 17 00:00:00 2001 From: Jonathan Naylor Date: Mon, 1 May 2017 14:46:43 +0100 Subject: [PATCH] Start the voice transmission module. --- Conf.cpp | 46 ++++++++++++++++++------- Conf.h | 7 ++++ DMRGateway.cpp | 50 ++++++++++++++++++++++++++- DMRGateway.ini | 4 +++ DMRGateway.vcxproj | 2 ++ DMRGateway.vcxproj.filters | 6 ++++ Makefile | 2 +- Voice.cpp | 69 ++++++++++++++++++++++++++++++++++++++ Voice.h | 57 +++++++++++++++++++++++++++++++ 9 files changed, 228 insertions(+), 15 deletions(-) create mode 100644 Voice.cpp create mode 100644 Voice.h diff --git a/Conf.cpp b/Conf.cpp index 6393851..7a1846b 100644 --- a/Conf.cpp +++ b/Conf.cpp @@ -30,6 +30,7 @@ enum SECTION { SECTION_NONE, SECTION_GENERAL, SECTION_LOG, + SECTION_VOICE, SECTION_DMR_NETWORK, SECTION_XLX_NETWORK }; @@ -49,6 +50,8 @@ m_logDisplayLevel(0U), m_logFileLevel(0U), m_logFilePath(), m_logFileRoot(), +m_voiceEnabled(true), +m_voiceLanguage("en_GB"), m_dmrNetworkAddress(), m_dmrNetworkPort(0U), m_dmrNetworkLocal(0U), @@ -82,20 +85,22 @@ bool CConf::read() if (buffer[0U] == '#') continue; - if (buffer[0U] == '[') { - if (::strncmp(buffer, "[General]", 9U) == 0) - section = SECTION_GENERAL; - else if (::strncmp(buffer, "[Log]", 5U) == 0) - section = SECTION_LOG; - else if (::strncmp(buffer, "[XLX Network]", 13U) == 0) - section = SECTION_XLX_NETWORK; - else if (::strncmp(buffer, "[DMR Network]", 13U) == 0) - section = SECTION_DMR_NETWORK; - else - section = SECTION_NONE; + if (buffer[0U] == '[') { + if (::strncmp(buffer, "[General]", 9U) == 0) + section = SECTION_GENERAL; + else if (::strncmp(buffer, "[Log]", 5U) == 0) + section = SECTION_LOG; + else if (::strncmp(buffer, "[Voice]", 7U) == 0) + section = SECTION_VOICE; + else if (::strncmp(buffer, "[XLX Network]", 13U) == 0) + section = SECTION_XLX_NETWORK; + else if (::strncmp(buffer, "[DMR Network]", 13U) == 0) + section = SECTION_DMR_NETWORK; + else + section = SECTION_NONE; - continue; - } + continue; + } char* key = ::strtok(buffer, " \t=\r\n"); if (key == NULL) @@ -133,6 +138,11 @@ bool CConf::read() m_logFileLevel = (unsigned int)::atoi(value); else if (::strcmp(key, "DisplayLevel") == 0) m_logDisplayLevel = (unsigned int)::atoi(value); + } else if (section == SECTION_VOICE) { + if (::strcmp(key, "Enabled") == 0) + m_voiceEnabled = ::atoi(value) == 1; + else if (::strcmp(key, "Language") == 0) + m_voiceLanguage = value; } else if (section == SECTION_XLX_NETWORK) { if (::strcmp(key, "Address") == 0) m_xlxNetworkAddress = value; @@ -230,6 +240,16 @@ std::string CConf::getLogFileRoot() const return m_logFileRoot; } +bool CConf::getVoiceEnabled() const +{ + return m_voiceEnabled; +} + +std::string CConf::getVoiceLanguage() const +{ + return m_voiceLanguage; +} + std::string CConf::getXLXNetworkAddress() const { return m_xlxNetworkAddress; diff --git a/Conf.h b/Conf.h index c8ebdcb..2a66c41 100644 --- a/Conf.h +++ b/Conf.h @@ -47,6 +47,10 @@ public: std::string getLogFilePath() const; std::string getLogFileRoot() const; + // The Voice section + bool getVoiceEnabled() const; + std::string getVoiceLanguage() const; + // The DMR Network section std::string getDMRNetworkAddress() const; unsigned int getDMRNetworkPort() const; @@ -74,6 +78,9 @@ private: unsigned int m_timeout; bool m_debug; + bool m_voiceEnabled; + std::string m_voiceLanguage; + unsigned int m_logDisplayLevel; unsigned int m_logFileLevel; std::string m_logFilePath; diff --git a/DMRGateway.cpp b/DMRGateway.cpp index db752f3..359dfde 100644 --- a/DMRGateway.cpp +++ b/DMRGateway.cpp @@ -21,6 +21,7 @@ #include "StopWatch.h" #include "Rewrite.h" #include "Thread.h" +#include "Voice.h" #include "Log.h" #include @@ -63,7 +64,7 @@ enum DMRGW_STATUS { const char* HEADER1 = "This software is for use on amateur radio networks only,"; const char* HEADER2 = "it is to be used for educational purposes only. Its use on"; const char* HEADER3 = "commercial networks is strictly prohibited."; -const char* HEADER4 = "Copyright(C) 2015-2017 by Jonathan Naylor, G4KLX and others"; +const char* HEADER4 = "Copyright(C) 2017 by Jonathan Naylor, G4KLX and others"; int main(int argc, char** argv) { @@ -247,6 +248,23 @@ int CDMRGateway::run() if (!ret) return 1; + CVoice* voice = NULL; + if (m_conf.getVoiceEnabled()) { + std::string language = m_conf.getVoiceLanguage(); + + LogInfo("Voice Parameters"); + LogInfo(" Enabled: yes"); + LogInfo(" Language: %s", language.c_str()); + + voice = new CVoice(language, xlxSlot, xlxTG); + + bool ret = voice->open(); + if (!ret) { + delete voice; + voice = NULL; + } + } + DMRGW_STATUS status = DMRGWS_NONE; CTimer timer(1000U, timeout); @@ -256,6 +274,8 @@ int CDMRGateway::run() LogMessage("DMRGateway-%s is running", VERSION); + bool changed = false; + while (!m_killed) { CDMRData data; @@ -281,12 +301,26 @@ int CDMRGateway::run() LogMessage("Unlinking"); m_reflector = id; + changed = true; } xlxRewrite.process(data); m_xlxNetwork->write(data); status = DMRGWS_REFLECTOR; timer.start(); + + if (voice != NULL) { + unsigned char type = data.getDataType(); + if (type == DT_TERMINATOR_WITH_LC) { + if (changed) { + if (m_reflector == 4000U) + voice->unlinked(); + else + voice->linkedTo(m_reflector); + changed = false; + } + } + } } else { m_dmrNetwork->write(data); status = DMRGWS_NETWORK; @@ -334,6 +368,15 @@ int CDMRGateway::run() } } + if (voice != NULL) { + ret = voice->read(data); + if (ret) { + m_repeater->write(data); + status = DMRGWS_REFLECTOR; + timer.start(); + } + } + unsigned int ms = stopWatch.elapsed(); stopWatch.start(); @@ -341,6 +384,9 @@ int CDMRGateway::run() m_dmrNetwork->clock(ms); m_xlxNetwork->clock(ms); + if (voice != NULL) + voice->clock(ms); + timer.clock(ms); if (timer.isRunning() && timer.hasExpired()) { status = DMRGWS_NONE; @@ -353,6 +399,8 @@ int CDMRGateway::run() LogMessage("DMRGateway-%s is exiting on receipt of SIGHUP1", VERSION); + delete voice; + m_repeater->close(); delete m_repeater; diff --git a/DMRGateway.ini b/DMRGateway.ini index 3feff11..ddf5bb3 100644 --- a/DMRGateway.ini +++ b/DMRGateway.ini @@ -16,6 +16,10 @@ FileLevel=1 FilePath=. FileRoot=DMRGateway +[Voice] +Enabled=1 +Language=en_GB + [XLX Network] Address=xlx950.epf.lu Port=55555 diff --git a/DMRGateway.vcxproj b/DMRGateway.vcxproj index ba24855..7eb59db 100644 --- a/DMRGateway.vcxproj +++ b/DMRGateway.vcxproj @@ -175,6 +175,7 @@ + @@ -203,6 +204,7 @@ + diff --git a/DMRGateway.vcxproj.filters b/DMRGateway.vcxproj.filters index ae1276c..1bd54a4 100644 --- a/DMRGateway.vcxproj.filters +++ b/DMRGateway.vcxproj.filters @@ -98,6 +98,9 @@ Header Files + + Header Files + @@ -178,5 +181,8 @@ Source Files + + Source Files + \ No newline at end of file diff --git a/Makefile b/Makefile index dc60f42..8a1cf89 100644 --- a/Makefile +++ b/Makefile @@ -5,7 +5,7 @@ LIBS = -lpthread LDFLAGS = -g OBJECTS = BPTC19696.o Conf.o CRC.o DMRData.o DMREmbeddedData.o DMREMB.o DMRFullLC.o DMRGateway.o DMRLC.o DMRNetwork.o DMRSlotType.o Golay2087.o Hamming.o Log.o \ - MMDVMNetwork.o QR1676.o RepeaterProtocol.o Rewrite.o RS129.o SHA256.o StopWatch.o Sync.o Thread.o Timer.o UDPSocket.o Utils.o + MMDVMNetwork.o QR1676.o RepeaterProtocol.o Rewrite.o RS129.o SHA256.o StopWatch.o Sync.o Thread.o Timer.o UDPSocket.o Utils.o Voice.o all: DMRGateway diff --git a/Voice.cpp b/Voice.cpp new file mode 100644 index 0000000..35bf22a --- /dev/null +++ b/Voice.cpp @@ -0,0 +1,69 @@ +/* +* Copyright (C) 2017 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 "Voice.h" + +CVoice::CVoice(const std::string& language, unsigned int slot, unsigned int tg) : +m_language(language), +m_slot(slot), +m_tg(tg), +m_status(VS_NONE), +m_timer(1000U, 1U), +m_stopWatch() +{ +} + +CVoice::~CVoice() +{ +} + +bool CVoice::open() +{ + return true; +} + +void CVoice::linkedTo(unsigned int id) +{ + m_status = VS_WAITING; + m_timer.start(); +} + +void CVoice::unlinked() +{ + m_status = VS_WAITING; + m_timer.start(); +} + +bool CVoice::read(CDMRData& data) +{ + if (m_status != VS_SENDING) + return false; + + return false; +} + +void CVoice::clock(unsigned int ms) +{ + m_timer.clock(ms); + if (m_timer.isRunning() && m_timer.hasExpired()) { + if (m_status == VS_WAITING) { + m_stopWatch.start(); + m_status = VS_SENDING; + } + } +} diff --git a/Voice.h b/Voice.h new file mode 100644 index 0000000..cd63657 --- /dev/null +++ b/Voice.h @@ -0,0 +1,57 @@ +/* +* Copyright (C) 2017 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(Voice_H) +#define Voice_H + +#include "StopWatch.h" +#include "DMRData.h" +#include "Timer.h" + +#include + +enum VOICE_STATUS { + VS_NONE, + VS_WAITING, + VS_SENDING +}; + +class CVoice { +public: + CVoice(const std::string& language, unsigned int slot, unsigned int tg); + ~CVoice(); + + bool open(); + + void linkedTo(unsigned int id); + void unlinked(); + + bool read(CDMRData& data); + + void clock(unsigned int ms); + +private: + std::string m_language; + unsigned int m_slot; + unsigned int m_tg; + VOICE_STATUS m_status; + CTimer m_timer; + CStopWatch m_stopWatch; +}; + +#endif