Merge branch 'develop' into feature/NewVoices

develop
Geoffrey Merck 1 month ago
commit ebde23ce89

@ -80,7 +80,7 @@ bool CAPRSGPSDIdFrameProvider::buildAPRSFramesInt(const CAPRSEntry * entry, std:
#elif GPSD_API_MAJOR_VERSION == 11
if(m_gpsdData.fix.status == STATUS_NO_FIX)
return false;
#elif GPSD_API_MAJOR_VERSION <= 14
#elif GPSD_API_MAJOR_VERSION <= 16
if(m_gpsdData.fix.status == STATUS_UNK)
return false;
#else

@ -23,27 +23,6 @@
#include "DTMF.h"
#include "Log.h"
const unsigned char DTMF_MASK[] = {0x82U, 0x08U, 0x20U, 0x82U, 0x00U, 0x00U, 0x82U, 0x00U, 0x00U};
const unsigned char DTMF_SIG[] = {0x82U, 0x08U, 0x20U, 0x82U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U};
const unsigned char DTMF_SYM_MASK[] = {0x10U, 0x40U, 0x08U, 0x20U};
const unsigned char DTMF_SYM0[] = {0x00U, 0x40U, 0x08U, 0x20U};
const unsigned char DTMF_SYM1[] = {0x00U, 0x00U, 0x00U, 0x00U};
const unsigned char DTMF_SYM2[] = {0x00U, 0x40U, 0x00U, 0x00U};
const unsigned char DTMF_SYM3[] = {0x10U, 0x00U, 0x00U, 0x00U};
const unsigned char DTMF_SYM4[] = {0x00U, 0x00U, 0x00U, 0x20U};
const unsigned char DTMF_SYM5[] = {0x00U, 0x40U, 0x00U, 0x20U};
const unsigned char DTMF_SYM6[] = {0x10U, 0x00U, 0x00U, 0x20U};
const unsigned char DTMF_SYM7[] = {0x00U, 0x00U, 0x08U, 0x00U};
const unsigned char DTMF_SYM8[] = {0x00U, 0x40U, 0x08U, 0x00U};
const unsigned char DTMF_SYM9[] = {0x10U, 0x00U, 0x08U, 0x00U};
const unsigned char DTMF_SYMA[] = {0x10U, 0x40U, 0x00U, 0x00U};
const unsigned char DTMF_SYMB[] = {0x10U, 0x40U, 0x00U, 0x20U};
const unsigned char DTMF_SYMC[] = {0x10U, 0x40U, 0x08U, 0x00U};
const unsigned char DTMF_SYMD[] = {0x10U, 0x40U, 0x08U, 0x20U};
const unsigned char DTMF_SYMS[] = {0x00U, 0x00U, 0x08U, 0x20U};
const unsigned char DTMF_SYMH[] = {0x10U, 0x00U, 0x08U, 0x20U};
CDTMF::CDTMF() :
m_data(),
m_command(),
@ -125,6 +104,7 @@ bool CDTMF::decode(const unsigned char* ambe, bool end)
// If it is not a DTMF Code
if ((end || m_releaseCount >= 100U) && m_data.length() > 0U) {
m_command = m_data;
CLog::logDebug("Received DTMF Command %s", m_command.c_str());
m_data.clear();
m_releaseCount = 0U;
}
@ -192,6 +172,9 @@ std::string CDTMF::processReflector(const std::string& prefix, const std::string
{
unsigned int len = command.size();
if(len == 0U)
return std::string("");
char c = command.at(len - 1U);
if (c == 'A' || c == 'B' || c == 'C' || c == 'D') {
if (len < 2U || len > 4U)
@ -213,14 +196,14 @@ std::string CDTMF::processReflector(const std::string& prefix, const std::string
if (n1 == 0UL)
return std::string("");
unsigned long n2 = std::stoul(command.substr(2));
unsigned long n2 = std::stoul(command.substr(len-2U));
if (n2 == 0UL || n2 > 26UL)
return std::string("");
c = 'A' + n2 - 1UL;
char ostr[32];
snprintf(ostr, 32, "%s%03lu%cL", prefix.c_str(), n1, c);
std::snprintf(ostr, 32, "%s%03lu%cL", prefix.c_str(), n1, c);
return std::string(ostr);
}

@ -45,3 +45,24 @@ private:
std::string processReflector(const std::string& prefix, const std::string& command) const;
std::string processCCS(const std::string& command) const;
};
const unsigned char DTMF_MASK[] = {0x82U, 0x08U, 0x20U, 0x82U, 0x00U, 0x00U, 0x82U, 0x00U, 0x00U};
const unsigned char DTMF_SIG[] = {0x82U, 0x08U, 0x20U, 0x82U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U};
const unsigned char DTMF_SYM_MASK[] = {0x10U, 0x40U, 0x08U, 0x20U};
const unsigned char DTMF_SYM0[] = {0x00U, 0x40U, 0x08U, 0x20U};
const unsigned char DTMF_SYM1[] = {0x00U, 0x00U, 0x00U, 0x00U};
const unsigned char DTMF_SYM2[] = {0x00U, 0x40U, 0x00U, 0x00U};
const unsigned char DTMF_SYM3[] = {0x10U, 0x00U, 0x00U, 0x00U};
const unsigned char DTMF_SYM4[] = {0x00U, 0x00U, 0x00U, 0x20U};
const unsigned char DTMF_SYM5[] = {0x00U, 0x40U, 0x00U, 0x20U};
const unsigned char DTMF_SYM6[] = {0x10U, 0x00U, 0x00U, 0x20U};
const unsigned char DTMF_SYM7[] = {0x00U, 0x00U, 0x08U, 0x00U};
const unsigned char DTMF_SYM8[] = {0x00U, 0x40U, 0x08U, 0x00U};
const unsigned char DTMF_SYM9[] = {0x10U, 0x00U, 0x08U, 0x00U};
const unsigned char DTMF_SYMA[] = {0x10U, 0x40U, 0x00U, 0x00U};
const unsigned char DTMF_SYMB[] = {0x10U, 0x40U, 0x00U, 0x20U};
const unsigned char DTMF_SYMC[] = {0x10U, 0x40U, 0x08U, 0x00U};
const unsigned char DTMF_SYMD[] = {0x10U, 0x40U, 0x08U, 0x20U};
const unsigned char DTMF_SYMS[] = {0x00U, 0x00U, 0x08U, 0x20U};
const unsigned char DTMF_SYMH[] = {0x10U, 0x00U, 0x08U, 0x20U};

@ -158,6 +158,7 @@ The testing framwework used is Google Test.
# 6. Version History
## 6.1. Version 1.0
- [**Bugfix**] Fix decoding of DTMF commands with leading 0 ([#61](https://github.com/F4FXL/DStarGateway/issues/61))
- [**Improvement**] Add second French voice ([#60](https://github.com/F4FXL/DStarGateway/issues/60))
- [**Improvement**] Clarify French "Linking to" announcement ([#60](https://github.com/F4FXL/DStarGateway/issues/60))
- [**Improvement**] Improve threading handling ([#58](https://github.com/F4FXL/DStarGateway/issues/58))

@ -1,5 +1,5 @@
/*
* Copyright (C) 2021-2024 by Geoffrey Merck F4FXL / KC3FRA
* Copyright (C) 2021-2026 by Geoffrey Merck F4FXL / KC3FRA
*
* 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
@ -16,56 +16,125 @@
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include <array>
#include <gtest/gtest.h>
#include "DTMF.h"
const unsigned char DTMF_MASK[] = {0x82U, 0x08U, 0x20U, 0x82U, 0x00U, 0x00U, 0x82U, 0x00U, 0x00U};
const unsigned char DTMF_SIG[] = {0x82U, 0x08U, 0x20U, 0x82U, 0x00U, 0x00U, 0x00U, 0x00U, 0x00U};
const unsigned char DTMF_SYM_MASK[] = {0x10U, 0x40U, 0x08U, 0x20U};
const unsigned char DTMF_SYM0[] = {0x00U, 0x40U, 0x08U, 0x20U};
const unsigned char DTMF_SYM1[] = {0x00U, 0x00U, 0x00U, 0x00U};
const unsigned char DTMF_SYM2[] = {0x00U, 0x40U, 0x00U, 0x00U};
const unsigned char DTMF_SYM3[] = {0x10U, 0x00U, 0x00U, 0x00U};
const unsigned char DTMF_SYM4[] = {0x00U, 0x00U, 0x00U, 0x20U};
const unsigned char DTMF_SYM5[] = {0x00U, 0x40U, 0x00U, 0x20U};
const unsigned char DTMF_SYM6[] = {0x10U, 0x00U, 0x00U, 0x20U};
const unsigned char DTMF_SYM7[] = {0x00U, 0x00U, 0x08U, 0x00U};
const unsigned char DTMF_SYM8[] = {0x00U, 0x40U, 0x08U, 0x00U};
const unsigned char DTMF_SYM9[] = {0x10U, 0x00U, 0x08U, 0x00U};
const unsigned char DTMF_SYMA[] = {0x10U, 0x40U, 0x00U, 0x00U};
const unsigned char DTMF_SYMB[] = {0x10U, 0x40U, 0x00U, 0x20U};
const unsigned char DTMF_SYMC[] = {0x10U, 0x40U, 0x08U, 0x00U};
const unsigned char DTMF_SYMD[] = {0x10U, 0x40U, 0x08U, 0x20U};
const unsigned char DTMF_SYMS[] = {0x00U, 0x00U, 0x08U, 0x20U};
const unsigned char DTMF_SYMH[] = {0x10U, 0x00U, 0x08U, 0x20U};
#include "DStarDefines.h"
namespace DTMFTests
{
class DTMF_decode : public ::testing::Test {
};
using Frame = std::array<unsigned char, 9>;
TEST_F(DTMF_decode, decode_valid_dtmf)
static Frame makeFrame(const unsigned char sym[4])
{
unsigned char ambe[] = {DTMF_SIG[0],
return Frame{
DTMF_SIG[0],
DTMF_SIG[1],
DTMF_SIG[2],
DTMF_SIG[3],
(unsigned char)(DTMF_SIG[4] | DTMF_SYM1[0]),
(unsigned char)(DTMF_SIG[5] | DTMF_SYM1[1]),
static_cast<unsigned char>(DTMF_SIG[4] | sym[0]),
static_cast<unsigned char>(DTMF_SIG[5] | sym[1]),
DTMF_SIG[6],
(unsigned char)(DTMF_SIG[7] | DTMF_SYM1[2]),
(unsigned char)(DTMF_SIG[8] | DTMF_SYM1[3])};
static_cast<unsigned char>(DTMF_SIG[7] | sym[2]),
static_cast<unsigned char>(DTMF_SIG[8] | sym[3]),
};
}
static void decode4(CDTMF& dtmf, const Frame& f, bool last = false)
{
dtmf.decode(f.data(), false);
dtmf.decode(f.data(), false);
dtmf.decode(f.data(), false);
dtmf.decode(f.data(), last);
}
static void gap(CDTMF& dtmf, unsigned n = 10, bool end = false)
{
for (unsigned i = 0; i < n; ++i)
dtmf.decode(NULL_AMBE_DATA_BYTES, end);
}
class DTMF_decode : public ::testing::Test {};
TEST_F(DTMF_decode, decode_reflector_module_as_number)
{
const auto D = makeFrame(DTMF_SYMD);
const auto Zero = makeFrame(DTMF_SYM0);
const auto One = makeFrame(DTMF_SYM1);
const auto Eight= makeFrame(DTMF_SYM8);
const auto Four = makeFrame(DTMF_SYM4);
CDTMF dtmf;
dtmf.decode(ambe, false);
dtmf.decode(ambe, false);
dtmf.decode(ambe, false);
dtmf.decode(ambe, false);
dtmf.decode(ambe, false);
dtmf.decode(ambe, false);
dtmf.decode(ambe, true);
decode4(dtmf, D); gap(dtmf);
decode4(dtmf, Zero); gap(dtmf);
decode4(dtmf, One); gap(dtmf);
decode4(dtmf, Eight); gap(dtmf);
decode4(dtmf, Zero); gap(dtmf);
decode4(dtmf, Four);
gap(dtmf, 10, true);
EXPECT_TRUE(dtmf.hasCommand());
EXPECT_STREQ(dtmf.translate().c_str(), "DCS018DL");
}
TEST_F(DTMF_decode, decode_reflector_module_as_letter)
{
const auto D = makeFrame(DTMF_SYMD);
const auto Zero = makeFrame(DTMF_SYM0);
const auto One = makeFrame(DTMF_SYM1);
const auto Eight= makeFrame(DTMF_SYM8);
CDTMF dtmf;
decode4(dtmf, D); gap(dtmf);
decode4(dtmf, Zero); gap(dtmf);
decode4(dtmf, One); gap(dtmf);
decode4(dtmf, Eight); gap(dtmf);
decode4(dtmf, D);
gap(dtmf, 10, true);
EXPECT_TRUE(dtmf.hasCommand());
EXPECT_STREQ(dtmf.translate().c_str(), "DCS018DL");
}
TEST_F(DTMF_decode, decode_reflector_short_module_as_letter)
{
const auto D = makeFrame(DTMF_SYMD);
const auto One = makeFrame(DTMF_SYM1);
const auto Eight = makeFrame(DTMF_SYM8);
CDTMF dtmf;
decode4(dtmf, D); gap(dtmf);
decode4(dtmf, One); gap(dtmf);
decode4(dtmf, Eight); gap(dtmf);
decode4(dtmf, D);
gap(dtmf, 10, true);
EXPECT_TRUE(dtmf.hasCommand());
EXPECT_STREQ(dtmf.translate().c_str(), "DCS018DL");
}
TEST_F(DTMF_decode, decode_reflector_short_module_as_number)
{
const auto D = makeFrame(DTMF_SYMD);
const auto Zero = makeFrame(DTMF_SYM0);
const auto One = makeFrame(DTMF_SYM1);
const auto Eight = makeFrame(DTMF_SYM8);
const auto Four = makeFrame(DTMF_SYM4);
CDTMF dtmf;
decode4(dtmf, D); gap(dtmf);
decode4(dtmf, One); gap(dtmf);
decode4(dtmf, Eight); gap(dtmf);
decode4(dtmf, Zero); gap(dtmf);
decode4(dtmf, Four);
gap(dtmf, 10, true);
EXPECT_TRUE(dtmf.hasCommand());
EXPECT_STREQ(dtmf.translate().c_str(), "DCS018DL");
}
}
Loading…
Cancel
Save

Powered by TurnKey Linux.