M17: add Callsign class

Added class representing M17 callsign objects. Objects can be
constructed both from strings and base-40 encoded values and allow
conversion to any of the other representation. The class implements the
comparison operator to allow easy check for callsign match.
pull/335/merge
Ryan Turner 2025-10-19 15:44:17 -05:00 zatwierdzone przez Silvano Seva
rodzic 76ffe2d612
commit fdbe3f2583
6 zmienionych plików z 283 dodań i 0 usunięć

Wyświetl plik

@ -106,6 +106,7 @@ ObjCBinPackProtocolList: Auto
ObjCBlockIndentWidth: 4
ObjCSpaceAfterProperty: true
ObjCSpaceBeforeProtocolList: true
PackConstructorInitializers: NextLine
# Taken from git's rules
PenaltyBreakAssignment: 30

Wyświetl plik

@ -105,6 +105,7 @@ target_sources(app
openrtx/src/protocols/M17/M17DSP.cpp
openrtx/src/protocols/M17/M17Golay.cpp
openrtx/src/protocols/M17/M17Callsign.cpp
openrtx/src/protocols/M17/Callsign.cpp
openrtx/src/protocols/M17/M17Modulator.cpp
openrtx/src/protocols/M17/M17Demodulator.cpp
openrtx/src/protocols/M17/M17FrameEncoder.cpp

Wyświetl plik

@ -62,6 +62,7 @@ openrtx_src = ['openrtx/src/core/state.c',
'openrtx/src/protocols/M17/M17DSP.cpp',
'openrtx/src/protocols/M17/M17Golay.cpp',
'openrtx/src/protocols/M17/M17Callsign.cpp',
'openrtx/src/protocols/M17/Callsign.cpp',
'openrtx/src/protocols/M17/M17Modulator.cpp',
'openrtx/src/protocols/M17/M17Demodulator.cpp',
'openrtx/src/protocols/M17/M17FrameEncoder.cpp',

Wyświetl plik

@ -0,0 +1,125 @@
/***************************************************************************
* Copyright (C) 2025 by Federico Amedeo Izzo IU2NUO, *
* Niccolò Izzo IU2KIN *
* Frederik Saraci IU2NRO *
* Silvano Seva IU2KWO *
* *
* 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 3 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, see <http://www.gnu.org/licenses/> *
***************************************************************************/
#ifndef CALLSIGN_H
#define CALLSIGN_H
#ifndef __cplusplus
#error This header is C++ only!
#endif
#include <string>
#include "M17Datatypes.hpp"
namespace M17
{
/**
* Class representing an M17 callsign object.
*/
class Callsign
{
public:
/**
* Default constructor.
* By default, an uninitialized callsign is set to invalid.
*/
Callsign();
/**
* Construct a callsign object from an std::string
* The callsign can have up to 9 characters
*
* @param callsign: callsign string
*/
Callsign(const std::string callsign);
/**
* Construct a callsign object from a NULL-terminated string
* The callsign can have up to 9 characters
*
* @param callsign: callsign string
*/
Callsign(const char *callsign);
/**
* Construct a callsign object from a base-40 encoded callsign
*
* @param encodedCall: encoded callsign value
*/
Callsign(const call_t &encodedCall);
/**
* Test if callsign is empty.
* A callsign is considered empty when its first character is NULL.
*
* @return true if the callsign is empty
*/
inline bool isEmpty() const
{
return call[0] == '\0';
}
/**
* Test if callsign is a special one.
*
* @return true if the callsign is either ALL, INFO or ECHO
*/
bool isSpecial() const;
/**
* Type-conversion operator to retrieve the callsign in encoded format
*
* @return the base-40 encoded version of the callsign
*/
operator call_t() const;
/**
* Type-conversion operator to retrieve the callsign as a std::string
*
* @return a std::string containing the callsign
*/
operator std::string() const;
/**
* Type-conversion operator to retrieve the callsign as a NULL-terminated
* string
*
* @return the callsign as a NULL-terminated string
*/
operator const char *() const;
/**
* Comparison operator.
*
* @param other the incoming callsign to compare against
* @return true if callsigns are equivalent
*/
bool operator==(const Callsign &other) const;
private:
static constexpr size_t MAX_CALLSIGN_CHARS = 9;
static constexpr size_t MAX_CALLSIGN_LEN = MAX_CALLSIGN_CHARS + 1;
char call[MAX_CALLSIGN_LEN];
};
} // namespace M17
#endif // CALLSIGN_H

Wyświetl plik

@ -0,0 +1,153 @@
/***************************************************************************
* Copyright (C) 2025 by Federico Amedeo Izzo IU2NUO, *
* Niccolò Izzo IU2KIN *
* Frederik Saraci IU2NRO *
* Silvano Seva IU2KWO *
* *
* 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 3 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, see <http://www.gnu.org/licenses/> *
***************************************************************************/
#include <cstring>
#include "protocols/M17/Callsign.hpp"
using namespace M17;
static const char BROADCAST_CALL[] = "ALL";
static const char INVALID_CALL[] = "INVALID";
static const char charMap[] = " ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-/.";
Callsign::Callsign() : Callsign(INVALID_CALL)
{
}
Callsign::Callsign(const std::string callsign) : Callsign(callsign.c_str())
{
}
Callsign::Callsign(const char *callsign)
{
std::memset(call, 0, sizeof(call));
std::strncpy(call, callsign, MAX_CALLSIGN_CHARS);
}
Callsign::Callsign(const call_t &encodedCall)
{
bool isBroadcast = true;
bool isInvalid = true;
for (auto &elem : encodedCall) {
if (elem != 0xFF)
isBroadcast = false;
if (elem != 0x00)
isInvalid = false;
}
std::memset(call, 0, sizeof(call));
if (isBroadcast) {
std::strncpy(call, BROADCAST_CALL, sizeof(call));
return;
}
if (isInvalid) {
std::strncpy(call, INVALID_CALL, sizeof(call));
return;
}
// Convert to little endian format
uint64_t encoded = 0;
auto p = reinterpret_cast<uint8_t *>(&encoded);
std::copy(encodedCall.rbegin(), encodedCall.rend(), p);
size_t pos = 0;
while (encoded != 0 && pos < MAX_CALLSIGN_CHARS) {
call[pos++] = charMap[encoded % 40];
encoded /= 40;
}
}
bool Callsign::isSpecial() const
{
if ((std::strcmp(call, "INFO") == 0) || (std::strcmp(call, "ECHO") == 0)
|| (std::strcmp(call, "ALL") == 0))
return true;
return false;
}
Callsign::operator std::string() const
{
return std::string(call);
}
Callsign::operator const char *() const
{
return call;
}
Callsign::operator call_t() const
{
call_t encoded;
uint64_t tmp = 0;
if (strcmp(call, BROADCAST_CALL) == 0) {
encoded.fill(0xFF);
return encoded;
}
if (strcmp(call, INVALID_CALL) == 0) {
encoded.fill(0x00);
return encoded;
}
for (int i = strlen(call) - 1; i >= 0; i--) {
tmp *= 40;
if (call[i] >= 'A' && call[i] <= 'Z') {
tmp += (call[i] - 'A') + 1;
} else if (call[i] >= '0' && call[i] <= '9') {
tmp += (call[i] - '0') + 27;
} else if (call[i] == '-') {
tmp += 37;
} else if (call[i] == '/') {
tmp += 38;
} else if (call[i] == '.') {
tmp += 39;
}
}
// Return encoded callsign in big endian format
auto *ptr = reinterpret_cast<uint8_t *>(&tmp);
std::copy(ptr, ptr + 6, encoded.rbegin());
return encoded;
}
bool Callsign::operator==(const Callsign &other) const
{
// find slash and possibly truncate if slash is within first 3 chars
const char *truncatedLocal = call;
const char *truncatedIncoming = other.call;
const char *slash = std::strchr(call, '/');
if (slash && (slash - call) <= 2)
truncatedLocal = slash + 1;
slash = std::strchr(other.call, '/');
if (slash && (slash - other.call) <= 2)
truncatedIncoming = slash + 1;
return std::strcmp(truncatedLocal, truncatedIncoming) == 0;
}

Wyświetl plik

@ -69,9 +69,11 @@ openrtx/include/interfaces/radio.h
openrtx/include/peripherals/gps.h
openrtx/include/peripherals/rng.h
openrtx/include/peripherals/rtc.h
openrtx/include/protocols/M17/Callsign.hpp
openrtx/include/protocols/M17/M17FrameDecoder.hpp
openrtx/src/core/dsp.cpp
openrtx/src/core/memory_profiling.cpp
openrtx/src/protocols/M17/Callsign.cpp
openrtx/src/protocols/M17/M17FrameDecoder.cpp
platform/drivers/ADC/ADC0_GDx.h
platform/drivers/audio/MAX9814.h