kopia lustrzana https://github.com/mobilinkd/NucleoTNC
103 wiersze
2.5 KiB
C++
103 wiersze
2.5 KiB
C++
// Copyright 2020 Mobilinkd LLC.
|
|
|
|
#pragma once
|
|
|
|
#include <array>
|
|
#include <cstdint>
|
|
#include <string_view> // Don't have std::span in C++17.
|
|
#include <stdexcept>
|
|
|
|
namespace mobilinkd
|
|
{
|
|
|
|
struct LinkSetupFrame
|
|
{
|
|
using call_t = std::array<char,10>; // NUL-terminated C-string.
|
|
using encoded_call_t = std::array<uint8_t, 6>;
|
|
using frame_t = std::array<uint8_t, 30>;
|
|
using nonce_t = std::string_view; // std::span would be better here.
|
|
|
|
enum TxType { PACKET, STREAM };
|
|
enum DataType { DT_RESERVED, DATA, VOICE, MIXED };
|
|
enum EncType { NONE, AES, LFSR, ET_RESERVED };
|
|
|
|
call_t mycall_ = {0};
|
|
call_t tocall_ = {0};
|
|
TxType tx_type_ = TxType::STREAM;
|
|
DataType data_type_ = DataType::VOICE;
|
|
EncType encryption_type_ = EncType::NONE;
|
|
|
|
template <size_t N>
|
|
static encoded_call_t encode_callsign(std::array<char, N> callsign)
|
|
{
|
|
// Encode the characters to base-40 digits.
|
|
uint64_t encoded = 0;
|
|
|
|
std::reverse(callsign.begin(), callsign.end());
|
|
|
|
for (auto c : callsign)
|
|
{
|
|
if (c == 0) continue;
|
|
encoded *= 40;
|
|
if (c >= 'A' and c <= 'Z')
|
|
{
|
|
encoded += c - 'A' + 1;
|
|
}
|
|
else if (c >= '0' and c <= '9')
|
|
{
|
|
encoded += c - '0' + 27;
|
|
}
|
|
else if (c == '-')
|
|
{
|
|
encoded += 37;
|
|
}
|
|
else if (c == '/')
|
|
{
|
|
encoded += 38;
|
|
}
|
|
else if (c == '.')
|
|
{
|
|
encoded += 39;
|
|
}
|
|
}
|
|
const auto p = reinterpret_cast<uint8_t*>(&encoded);
|
|
|
|
encoded_call_t result;
|
|
std::copy(p, p + 6, result.rbegin());
|
|
|
|
return result;
|
|
}
|
|
|
|
static call_t decode_callsign(encoded_call_t callsign)
|
|
{
|
|
static const char callsign_map[] = "xABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-/.";
|
|
|
|
uint64_t encoded = 0; // This only works on little endian architectures.
|
|
auto p = reinterpret_cast<uint8_t*>(&encoded);
|
|
std::copy(callsign.rbegin(), callsign.rend(), p);
|
|
|
|
// decode each base-40 digit and map them to the appriate character.
|
|
call_t result;
|
|
result.fill(0);
|
|
size_t index = 0;
|
|
while (encoded)
|
|
{
|
|
result[index++] = callsign_map[encoded % 40];
|
|
encoded /= 40;
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
|
|
LinkSetupFrame()
|
|
{}
|
|
|
|
LinkSetupFrame& myCall(const char*)
|
|
{
|
|
return *this;
|
|
}
|
|
};
|
|
|
|
} // mobilinkd
|