Formatted the entire codebase and added a CI check for formatting

This commit is contained in:
AlexandreRouma
2021-12-19 22:11:44 +01:00
parent 8644957881
commit ea587db0cb
161 changed files with 3302 additions and 3393 deletions

View File

@ -1,11 +1,11 @@
#include <base40.h>
void decode_callsign_base40(uint64_t encoded, char *callsign) {
void decode_callsign_base40(uint64_t encoded, char* callsign) {
if (encoded >= 262144000000000) { // 40^9
*callsign = 0;
return;
}
char *p = callsign;
char* p = callsign;
for (; encoded > 0; p++) {
*p = " ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-/."[encoded % 40];
encoded /= 40;

View File

@ -6,67 +6,57 @@
#include <array>
#include <cstddef>
namespace mobilinkd
{
namespace mobilinkd {
template <uint16_t Poly = 0x5935, uint16_t Init = 0xFFFF>
struct CRC16
{
static constexpr uint16_t MASK = 0xFFFF;
static constexpr uint16_t LSB = 0x0001;
static constexpr uint16_t MSB = 0x8000;
template <uint16_t Poly = 0x5935, uint16_t Init = 0xFFFF>
struct CRC16 {
static constexpr uint16_t MASK = 0xFFFF;
static constexpr uint16_t LSB = 0x0001;
static constexpr uint16_t MSB = 0x8000;
uint16_t reg_ = Init;
uint16_t reg_ = Init;
void reset()
{
reg_ = Init;
void reset() {
reg_ = Init;
for (size_t i = 0; i != 16; ++i)
{
auto bit = reg_ & LSB;
if (bit) reg_ ^= Poly;
reg_ >>= 1;
if (bit) reg_ |= MSB;
for (size_t i = 0; i != 16; ++i) {
auto bit = reg_ & LSB;
if (bit) reg_ ^= Poly;
reg_ >>= 1;
if (bit) reg_ |= MSB;
}
reg_ &= MASK;
}
reg_ &= MASK;
}
void operator()(uint8_t byte)
{
reg_ = crc(byte, reg_);
}
uint16_t crc(uint8_t byte, uint16_t reg)
{
for (size_t i = 0; i != 8; ++i)
{
auto msb = reg & MSB;
reg = ((reg << 1) & MASK) | ((byte >> (7 - i)) & LSB);
if (msb) reg ^= Poly;
void operator()(uint8_t byte) {
reg_ = crc(byte, reg_);
}
return reg & MASK;
}
uint16_t get()
{
auto reg = reg_;
for (size_t i = 0; i != 16; ++i)
{
auto msb = reg & MSB;
reg = ((reg << 1) & MASK);
if (msb) reg ^= Poly;
uint16_t crc(uint8_t byte, uint16_t reg) {
for (size_t i = 0; i != 8; ++i) {
auto msb = reg & MSB;
reg = ((reg << 1) & MASK) | ((byte >> (7 - i)) & LSB);
if (msb) reg ^= Poly;
}
return reg & MASK;
}
return reg;
}
std::array<uint8_t, 2> get_bytes()
{
auto crc = get();
std::array<uint8_t, 2> result{uint8_t((crc >> 8) & 0xFF), uint8_t(crc & 0xFF)};
return result;
}
};
uint16_t get() {
auto reg = reg_;
for (size_t i = 0; i != 16; ++i) {
auto msb = reg & MSB;
reg = ((reg << 1) & MASK);
if (msb) reg ^= Poly;
}
return reg;
}
std::array<uint8_t, 2> get_bytes() {
auto crc = get();
std::array<uint8_t, 2> result{ uint8_t((crc >> 8) & 0xFF), uint8_t(crc & 0xFF) };
return result;
}
};
} // mobilinkd

View File

@ -10,224 +10,194 @@
namespace mobilinkd {
// Parts are adapted from:
// http://aqdi.com/articles/using-the-golay-error-detection-and-correction-code-3/
// Parts are adapted from:
// http://aqdi.com/articles/using-the-golay-error-detection-and-correction-code-3/
namespace Golay24
{
namespace Golay24 {
int popcount(uint32_t n) {
int count = 0;
for (int i = 0; i < 32; i++) {
count += ((n >> i) & 1);
int popcount(uint32_t n) {
int count = 0;
for (int i = 0; i < 32; i++) {
count += ((n >> i) & 1);
}
return count;
}
return count;
}
namespace detail
{
namespace detail {
// Need a constexpr sort.
// https://stackoverflow.com/a/40030044/854133
template<class T>
void swap(T& l, T& r)
{
T tmp = std::move(l);
l = std::move(r);
r = std::move(tmp);
}
// Need a constexpr sort.
// https://stackoverflow.com/a/40030044/854133
template <class T>
void swap(T& l, T& r) {
T tmp = std::move(l);
l = std::move(r);
r = std::move(tmp);
}
template <typename T, size_t N>
struct array
{
constexpr T& operator[](size_t i)
{
return arr[i];
}
template <typename T, size_t N>
struct array {
constexpr T& operator[](size_t i) {
return arr[i];
}
constexpr const T& operator[](size_t i) const
{
return arr[i];
}
constexpr const T& operator[](size_t i) const {
return arr[i];
}
constexpr const T* begin() const
{
return arr;
}
constexpr const T* end() const
{
return arr + N;
}
constexpr const T* begin() const {
return arr;
}
constexpr const T* end() const {
return arr + N;
}
T arr[N];
};
T arr[N];
};
template <typename T, size_t N>
void sort_impl(array<T, N> &array, size_t left, size_t right)
{
if (left < right)
{
size_t m = left;
template <typename T, size_t N>
void sort_impl(array<T, N>& array, size_t left, size_t right) {
if (left < right) {
size_t m = left;
for (size_t i = left + 1; i<right; i++)
if (array[i]<array[left])
swap(array[++m], array[i]);
for (size_t i = left + 1; i < right; i++)
if (array[i] < array[left])
swap(array[++m], array[i]);
swap(array[left], array[m]);
swap(array[left], array[m]);
sort_impl(array, left, m);
sort_impl(array, m + 1, right);
}
}
sort_impl(array, left, m);
sort_impl(array, m + 1, right);
}
}
template <typename T, size_t N>
array<T, N> sort(array<T, N> array)
{
auto sorted = array;
sort_impl(sorted, 0, N);
return sorted;
}
template <typename T, size_t N>
array<T, N> sort(array<T, N> array) {
auto sorted = array;
sort_impl(sorted, 0, N);
return sorted;
}
} // detail
} // detail
// static constexpr uint16_t POLY = 0xAE3;
constexpr uint16_t POLY = 0xC75;
// static constexpr uint16_t POLY = 0xAE3;
constexpr uint16_t POLY = 0xC75;
#pragma pack(push, 1)
struct SyndromeMapEntry
{
uint32_t a{0};
uint16_t b{0};
};
struct SyndromeMapEntry {
uint32_t a{ 0 };
uint16_t b{ 0 };
};
#pragma pack(pop)
/**
/**
* Calculate the syndrome of a [23,12] Golay codeword.
*
* @return the 11-bit syndrome of the codeword in bits [22:12].
*/
uint32_t syndrome(uint32_t codeword)
{
codeword &= 0xffffffl;
for (size_t i = 0; i != 12; ++i)
{
if (codeword & 1)
codeword ^= POLY;
codeword >>= 1;
}
return (codeword << 12);
}
bool parity(uint32_t codeword)
{
return popcount(codeword) & 1;
}
SyndromeMapEntry makeSyndromeMapEntry(uint64_t val)
{
return SyndromeMapEntry{uint32_t(val >> 16), uint16_t(val & 0xFFFF)};
}
uint64_t makeSME(uint64_t syndrome, uint32_t bits)
{
return (syndrome << 24) | (bits & 0xFFFFFF);
}
constexpr size_t LUT_SIZE = 2048;
std::array<SyndromeMapEntry, LUT_SIZE> make_lut()
{
constexpr size_t VECLEN=23;
detail::array<uint64_t, LUT_SIZE> result{};
size_t index = 0;
result[index++] = makeSME(syndrome(0), 0);
for (size_t i = 0; i != VECLEN; ++i)
{
auto v = (1 << i);
result[index++] = makeSME(syndrome(v), v);
}
for (size_t i = 0; i != VECLEN - 1; ++i)
{
for (size_t j = i + 1; j != VECLEN; ++j)
{
auto v = (1 << i) | (1 << j);
result[index++] = makeSME(syndrome(v), v);
uint32_t syndrome(uint32_t codeword) {
codeword &= 0xffffffl;
for (size_t i = 0; i != 12; ++i) {
if (codeword & 1)
codeword ^= POLY;
codeword >>= 1;
}
return (codeword << 12);
}
}
for (size_t i = 0; i != VECLEN - 2; ++i)
{
for (size_t j = i + 1; j != VECLEN - 1; ++j)
{
for (size_t k = j + 1; k != VECLEN; ++k)
{
auto v = (1 << i) | (1 << j) | (1 << k);
bool parity(uint32_t codeword) {
return popcount(codeword) & 1;
}
SyndromeMapEntry makeSyndromeMapEntry(uint64_t val) {
return SyndromeMapEntry{ uint32_t(val >> 16), uint16_t(val & 0xFFFF) };
}
uint64_t makeSME(uint64_t syndrome, uint32_t bits) {
return (syndrome << 24) | (bits & 0xFFFFFF);
}
constexpr size_t LUT_SIZE = 2048;
std::array<SyndromeMapEntry, LUT_SIZE> make_lut() {
constexpr size_t VECLEN = 23;
detail::array<uint64_t, LUT_SIZE> result{};
size_t index = 0;
result[index++] = makeSME(syndrome(0), 0);
for (size_t i = 0; i != VECLEN; ++i) {
auto v = (1 << i);
result[index++] = makeSME(syndrome(v), v);
}
for (size_t i = 0; i != VECLEN - 1; ++i) {
for (size_t j = i + 1; j != VECLEN; ++j) {
auto v = (1 << i) | (1 << j);
result[index++] = makeSME(syndrome(v), v);
}
}
for (size_t i = 0; i != VECLEN - 2; ++i) {
for (size_t j = i + 1; j != VECLEN - 1; ++j) {
for (size_t k = j + 1; k != VECLEN; ++k) {
auto v = (1 << i) | (1 << j) | (1 << k);
result[index++] = makeSME(syndrome(v), v);
}
}
}
result = detail::sort(result);
std::array<SyndromeMapEntry, LUT_SIZE> tmp;
for (size_t i = 0; i != LUT_SIZE; ++i) {
tmp[i] = makeSyndromeMapEntry(result[i]);
}
return tmp;
}
}
result = detail::sort(result);
inline auto LUT = make_lut();
std::array<SyndromeMapEntry, LUT_SIZE> tmp;
for (size_t i = 0; i != LUT_SIZE; ++i)
{
tmp[i] = makeSyndromeMapEntry(result[i]);
}
return tmp;
}
inline auto LUT = make_lut();
/**
/**
* Calculate [23,12] Golay codeword.
*
* @return checkbits(11)|data(12).
*/
uint32_t encode23(uint16_t data)
{
// data &= 0xfff;
uint32_t codeword = data;
for (size_t i = 0; i != 12; ++i)
{
if (codeword & 1)
codeword ^= POLY;
codeword >>= 1;
}
return codeword | (data << 11);
}
uint32_t encode23(uint16_t data) {
// data &= 0xfff;
uint32_t codeword = data;
for (size_t i = 0; i != 12; ++i) {
if (codeword & 1)
codeword ^= POLY;
codeword >>= 1;
}
return codeword | (data << 11);
}
uint32_t encode24(uint16_t data)
{
auto codeword = encode23(data);
return ((codeword << 1) | parity(codeword));
}
uint32_t encode24(uint16_t data) {
auto codeword = encode23(data);
return ((codeword << 1) | parity(codeword));
}
bool decode(uint32_t input, uint32_t& output)
{
auto syndrm = syndrome(input >> 1);
auto it = std::lower_bound(LUT.begin(), LUT.end(), syndrm,
[](const SyndromeMapEntry& sme, uint32_t val){
return (sme.a >> 8) < val;
});
bool decode(uint32_t input, uint32_t& output) {
auto syndrm = syndrome(input >> 1);
auto it = std::lower_bound(LUT.begin(), LUT.end(), syndrm,
[](const SyndromeMapEntry& sme, uint32_t val) {
return (sme.a >> 8) < val;
});
if ((it->a >> 8) == syndrm)
{
// Build the correction from the compressed entry.
auto correction = ((((it->a & 0xFF) << 16) | it->b) << 1);
// Apply the correction to the input.
output = input ^ correction;
// Only test parity for 3-bit errors.
return popcount(syndrm) < 3 || !parity(output);
}
if ((it->a >> 8) == syndrm) {
// Build the correction from the compressed entry.
auto correction = ((((it->a & 0xFF) << 16) | it->b) << 1);
// Apply the correction to the input.
output = input ^ correction;
// Only test parity for 3-bit errors.
return popcount(syndrm) < 3 || !parity(output);
}
return false;
}
return false;
}
} // Golay24
} // Golay24
} // mobilinkd

View File

@ -31,7 +31,7 @@ M17LSF M17DecodeLSF(uint8_t* _lsf) {
// Extract CRC
lsf.rawCRC = 0;
for (int i = 0; i < 16; i++) {
lsf.rawCRC |= (((uint16_t)_lsf[(i+48+48+16+112) / 8] >> (7 - (i%8))) & 1) << (15 - i);
lsf.rawCRC |= (((uint16_t)_lsf[(i + 48 + 48 + 16 + 112) / 8] >> (7 - (i % 8))) & 1) << (15 - i);
}
// Check CRC
@ -50,19 +50,19 @@ M17LSF M17DecodeLSF(uint8_t* _lsf) {
// Extract DST
lsf.rawDst = 0;
for (int i = 0; i < 48; i++) {
lsf.rawDst |= (((uint64_t)_lsf[i / 8] >> (7 - (i%8))) & 1) << (47 - i);
lsf.rawDst |= (((uint64_t)_lsf[i / 8] >> (7 - (i % 8))) & 1) << (47 - i);
}
// Extract SRC
lsf.rawSrc = 0;
for (int i = 0; i < 48; i++) {
lsf.rawSrc |= (((uint64_t)_lsf[(i+48) / 8] >> (7 - (i%8))) & 1) << (47 - i);
lsf.rawSrc |= (((uint64_t)_lsf[(i + 48) / 8] >> (7 - (i % 8))) & 1) << (47 - i);
}
// Extract TYPE
lsf.rawType = 0;
for (int i = 0; i < 16; i++) {
lsf.rawType |= (((uint16_t)_lsf[(i+48+48) / 8] >> (7 - (i%8))) & 1) << (15 - i);
lsf.rawType |= (((uint16_t)_lsf[(i + 48 + 48) / 8] >> (7 - (i % 8))) & 1) << (15 - i);
}
// Extract META

View File

@ -3,17 +3,17 @@
#include <stdint.h>
enum M17DataType {
M17_DATATYPE_UNKNOWN = 0b00,
M17_DATATYPE_DATA = 0b01,
M17_DATATYPE_VOICE = 0b10,
M17_DATATYPE_UNKNOWN = 0b00,
M17_DATATYPE_DATA = 0b01,
M17_DATATYPE_VOICE = 0b10,
M17_DATATYPE_DATA_VOICE = 0b11
};
enum M17EncryptionType {
M17_ENCRYPTION_NONE = 0b00,
M17_ENCRYPTION_AES = 0b01,
M17_ENCRYPTION_NONE = 0b00,
M17_ENCRYPTION_AES = 0b01,
M17_ENCRYPTION_SCRAMBLE = 0b10,
M17_ENCRYPTION_UNKNOWN = 0b11
M17_ENCRYPTION_UNKNOWN = 0b11
};
extern const char* M17DataTypesTxt[4];

View File

@ -7,50 +7,50 @@
#include <lsf_decode.h>
extern "C" {
#include <correct.h>
#include <correct.h>
}
#define M17_DEVIATION 2400.0f
#define M17_BAUDRATE 4800.0f
#define M17_RRC_ALPHA 0.5f
#define M17_4FSK_HIGH_CUT 0.5f
#define M17_DEVIATION 2400.0f
#define M17_BAUDRATE 4800.0f
#define M17_RRC_ALPHA 0.5f
#define M17_4FSK_HIGH_CUT 0.5f
#define M17_SYNC_SIZE 16
#define M17_LICH_SIZE 96
#define M17_PAYLOAD_SIZE 144
#define M17_ENCODED_PAYLOAD_SIZE 296
#define M17_LSF_SIZE 240
#define M17_ENCODED_LSF_SIZE 488
#define M17_RAW_FRAME_SIZE 384
#define M17_CUT_FRAME_SIZE 368
#define M17_SYNC_SIZE 16
#define M17_LICH_SIZE 96
#define M17_PAYLOAD_SIZE 144
#define M17_ENCODED_PAYLOAD_SIZE 296
#define M17_LSF_SIZE 240
#define M17_ENCODED_LSF_SIZE 488
#define M17_RAW_FRAME_SIZE 384
#define M17_CUT_FRAME_SIZE 368
const uint8_t M17_LSF_SYNC[16] = { 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1 };
const uint8_t M17_STF_SYNC[16] = { 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1 };
const uint8_t M17_PKF_SYNC[16] = { 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1 };
const uint8_t M17_LSF_SYNC[16] = { 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 1, 1, 1 };
const uint8_t M17_STF_SYNC[16] = { 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1 };
const uint8_t M17_PKF_SYNC[16] = { 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1 };
const uint8_t M17_SCRAMBLER[368] = { 1, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1,
1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0,
1, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1,
1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0,
1, 0, 1, 1, 1, 0, 1, 0, 0, 1, 0, 0, 1, 1, 1, 0,
1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0,
1, 1, 0, 1, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0,
1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1,
0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0,
0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 1,
1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1,
1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, 0,
0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1,
0, 0, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0,
0, 0, 0, 1, 0, 1, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0,
1, 1, 0, 0, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 0,
0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 1,
1, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0,
1, 1, 0, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 1,
1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1, 1,
0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0,
0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1,
0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1 };
const uint8_t M17_SCRAMBLER[368] = { 1, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1, 1, 0, 1, 0, 1,
1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0,
1, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1,
1, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0,
1, 0, 1, 1, 1, 0, 1, 0, 0, 1, 0, 0, 1, 1, 1, 0,
1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0,
1, 1, 0, 1, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0,
1, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1,
0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0,
0, 1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1, 1,
1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1,
1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, 0,
0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1,
0, 0, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0,
0, 0, 0, 1, 0, 1, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0,
1, 1, 0, 0, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 0,
0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 1,
1, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0,
1, 1, 0, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 1, 1,
1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1, 1,
0, 1, 0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0,
0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1,
0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1 };
const uint16_t M17_INTERLEAVER[368] = { 0, 137, 90, 227, 180, 317, 270, 39, 360, 129, 82, 219, 172, 309, 262, 31,
352, 121, 74, 211, 164, 301, 254, 23, 344, 113, 66, 203, 156, 293, 246, 15,
@ -83,7 +83,7 @@ const uint8_t M17_PUNCTURING_P1[61] = { 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1
const uint8_t M17_PUNCTURING_P2[12] = { 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0 };
static const correct_convolutional_polynomial_t correct_conv_m17_polynomial[] = {0b11001, 0b10111};
static const correct_convolutional_polynomial_t correct_conv_m17_polynomial[] = { 0b11001, 0b10111 };
namespace dsp {
class M17Slice4FSK : public generic_block<M17Slice4FSK> {
@ -116,8 +116,8 @@ namespace dsp {
float val;
for (int i = 0; i < count; i++) {
val = _in->readBuf[i];
out.writeBuf[i*2] = (val < 0.0f);
out.writeBuf[(i*2)+1] = (fabsf(val) > M17_4FSK_HIGH_CUT);
out.writeBuf[i * 2] = (val < 0.0f);
out.writeBuf[(i * 2) + 1] = (fabsf(val) > M17_4FSK_HIGH_CUT);
}
_in->flush();
@ -130,7 +130,6 @@ namespace dsp {
private:
stream<float>* _in;
};
class M17FrameDemux : public generic_block<M17FrameDemux> {
@ -176,7 +175,10 @@ namespace dsp {
for (int i = 0; i < count;) {
if (detect) {
if (outCount < M17_SYNC_SIZE) { outCount++; i++; }
if (outCount < M17_SYNC_SIZE) {
outCount++;
i++;
}
else {
int id = M17_INTERLEAVER[outCount - M17_SYNC_SIZE];
@ -192,21 +194,21 @@ namespace dsp {
else if (type == 2) {
packetOut.writeBuf[id - M17_LICH_SIZE] = (delay[i++] ^ M17_SCRAMBLER[outCount - M17_SYNC_SIZE]);
}
outCount++;
}
if (outCount >= M17_RAW_FRAME_SIZE) {
detect = false;
if (type == 0) {
if (!linkSetupOut.swap(M17_CUT_FRAME_SIZE)) { return -1; }
}
else if (type == 1) {
if (!lichOut.swap(M17_LICH_SIZE)) {return -1; }
if (!streamOut.swap(M17_CUT_FRAME_SIZE)) {return -1; }
if (!lichOut.swap(M17_LICH_SIZE)) { return -1; }
if (!streamOut.swap(M17_CUT_FRAME_SIZE)) { return -1; }
}
else if (type == 2) {
if (!lichOut.swap(M17_LICH_SIZE)) {return -1; }
if (!lichOut.swap(M17_LICH_SIZE)) { return -1; }
if (!packetOut.swap(M17_CUT_FRAME_SIZE)) { return -1; }
}
}
@ -242,7 +244,7 @@ namespace dsp {
i++;
}
memmove(delay, &delay[count], 16);
_in->flush();
@ -264,7 +266,6 @@ namespace dsp {
int type;
int outCount = 0;
};
class M17LSFDecoder : public generic_block<M17LSFDecoder> {
@ -283,7 +284,7 @@ namespace dsp {
_in = in;
_handler = handler;
_ctx = ctx;
conv = correct_convolutional_create(2, 5, correct_conv_m17_polynomial);
generic_block<M17LSFDecoder>::registerInput(_in);
@ -319,7 +320,7 @@ namespace dsp {
// Pack into bytes
memset(packed, 0, 61);
for (int i = 0; i < M17_ENCODED_LSF_SIZE; i++) {
packed[i/8] |= depunctured[i] << (7 - (i%8));
packed[i / 8] |= depunctured[i] << (7 - (i % 8));
}
// Run through convolutional decoder
@ -343,7 +344,6 @@ namespace dsp {
uint8_t lsf[30];
correct_convolutional* conv;
};
class M17PayloadFEC : public generic_block<M17PayloadFEC> {
@ -360,7 +360,7 @@ namespace dsp {
void init(stream<uint8_t>* in) {
_in = in;
conv = correct_convolutional_create(2, 5, correct_conv_m17_polynomial);
generic_block<M17PayloadFEC>::registerInput(_in);
@ -395,13 +395,13 @@ namespace dsp {
// Pack into bytes
memset(packed, 0, 37);
for (int i = 0; i < M17_ENCODED_PAYLOAD_SIZE; i++) {
if (!(i%8)) { packed[i/8] = 0; }
packed[i/8] |= depunctured[i] << (7 - (i%8));
if (!(i % 8)) { packed[i / 8] = 0; }
packed[i / 8] |= depunctured[i] << (7 - (i % 8));
}
// Run through convolutional decoder
correct_convolutional_decode(conv, packed, M17_ENCODED_PAYLOAD_SIZE, out.writeBuf);
_in->flush();
if (!out.swap(M17_PAYLOAD_SIZE / 8)) { return -1; }
@ -417,7 +417,6 @@ namespace dsp {
uint8_t packed[37];
correct_convolutional* conv;
};
class M17Codec2Decode : public generic_block<M17Codec2Decode> {
@ -464,7 +463,7 @@ namespace dsp {
// Decode both parts using codec
codec2_decode(codec, int16Audio, &_in->readBuf[2]);
codec2_decode(codec, &int16Audio[sampsPerC2Frame], &_in->readBuf[2+8]);
codec2_decode(codec, &int16Audio[sampsPerC2Frame], &_in->readBuf[2 + 8]);
// Convert to float
volk_16i_s32f_convert_32f(floatAudio, int16Audio, 32768.0f, sampsPerC2FrameDouble);
@ -489,7 +488,6 @@ namespace dsp {
CODEC2* codec;
int sampsPerC2Frame = 0;
int sampsPerC2FrameDouble = 0;
};
class M17LICHDecoder : public generic_block<M17LICHDecoder> {
@ -543,7 +541,7 @@ namespace dsp {
uint8_t temp;
for (int i = 0; i < 12; i++) {
id = (b * 12) + i;
chunk[id / 8] |= ((decodedBlock >> (23 - i)) & 1) << (7 - (id%8));
chunk[id / 8] |= ((decodedBlock >> (23 - i)) & 1) << (7 - (id % 8));
}
}
@ -555,7 +553,7 @@ namespace dsp {
if (partId == 0) {
newFrame = true;
lastId = 0;
memcpy(&lsf[partId*5], chunk, 5);
memcpy(&lsf[partId * 5], chunk, 5);
return count;
}
@ -568,7 +566,7 @@ namespace dsp {
// If we're recording and there's no discontinuity (see above), add the data to the full frame
if (newFrame) {
lastId = partId;
memcpy(&lsf[partId*5], chunk, 5);
memcpy(&lsf[partId * 5], chunk, 5);
// If the lsf is complete, send it out
if (partId == 5) {
@ -590,7 +588,6 @@ namespace dsp {
uint8_t lsf[240];
bool newFrame = false;
int lastId = 0;
};
class M17Decoder : public generic_hier_block<M17Decoder> {
@ -620,7 +617,7 @@ namespace dsp {
diagOut = &doubler.outB;
out = &decodeAudio.out;
generic_hier_block<M17Decoder>::registerBlock(&demod);
generic_hier_block<M17Decoder>::registerBlock(&fir);
generic_hier_block<M17Decoder>::registerBlock(&recov);
@ -661,7 +658,6 @@ namespace dsp {
NullSink<uint8_t> ns2;
float _sampleRate;
float _sampleRate;
};
}

View File

@ -21,9 +21,9 @@
#include <fstream>
#include <chrono>
#define CONCAT(a, b) ((std::string(a) + b).c_str())
#define CONCAT(a, b) ((std::string(a) + b).c_str())
SDRPP_MOD_INFO {
SDRPP_MOD_INFO{
/* Name: */ "m17_decoder",
/* Description: */ "M17 Digital Voice Decoder for SDR++",
/* Author: */ "Ryzerth",
@ -84,7 +84,7 @@ public:
sigpath::sinkManager.registerStream(name, &stream);
stream.start();
gui::menu.registerEntry(name, menuHandler, this, this);
}
@ -107,7 +107,7 @@ public:
void enable() {
double bw = gui::waterfall.getBandwidth();
vfo = sigpath::vfoManager.createVFO(name, ImGui::WaterfallVFO::REF_CENTER, std::clamp<double>(0, -bw/2.0, bw/2.0), 9600, INPUT_SAMPLE_RATE, 9600, 9600, true);
vfo = sigpath::vfoManager.createVFO(name, ImGui::WaterfallVFO::REF_CENTER, std::clamp<double>(0, -bw / 2.0, bw / 2.0), 9600, INPUT_SAMPLE_RATE, 9600, 9600, true);
vfo->setSnapInterval(250);
// Set Input of demod here
@ -152,7 +152,7 @@ private:
std::lock_guard lck(_this->lsfMtx);
auto now = std::chrono::high_resolution_clock::now();
if (std::chrono::duration_cast<std::chrono::milliseconds>(now-_this->lastUpdated).count() > 1000) {
if (std::chrono::duration_cast<std::chrono::milliseconds>(now - _this->lastUpdated).count() > 1000) {
_this->lsf.valid = false;
}
@ -251,7 +251,7 @@ private:
M17DecoderModule* _this = (M17DecoderModule*)ctx;
// TODO: If too slow, change all demods here and not when setting
_this->audioSampRate = sampleRate;
_this->resampWin.setCutoff(std::min<float>(sampleRate/2, 4000));
_this->resampWin.setCutoff(std::min<float>(sampleRate / 2, 4000));
_this->resamp.tempStop();
_this->resamp.setOutSampleRate(sampleRate);
_this->resampWin.setSampleRate(8000 * _this->resamp.getInterpolation());
@ -273,7 +273,7 @@ private:
VFOManager::VFO* vfo;
dsp::M17Decoder decoder;
dsp::Reshaper<float> reshape;
dsp::HandlerSink<float> diagHandler;