vp-digi/Src/fx25.c

151 wiersze
3.1 KiB
C

#ifdef ENABLE_FX25
#include "fx25.h"
#include <stddef.h>
#include "rs.h"
#define FX25_RS_FCR 1
#define FX25_PREGENERATE_POLYS
#define FX25_MAX_DISTANCE 10 //maximum Hamming distance when comparing tags
const struct Fx25Mode Fx25ModeList[11] =
{
{.tag = 0xB74DB7DF8A532F3E, .K = 239, .T = 16},
{.tag = 0x26FF60A600CC8FDE, .K = 128, .T = 16},
{.tag = 0xC7DC0508F3D9B09E, .K = 64, .T = 16},
{.tag = 0x8F056EB4369660EE, .K = 32, .T = 16},
{.tag = 0x6E260B1AC5835FAE, .K = 223, .T = 32},
{.tag = 0xFF94DC634F1CFF4E, .K = 128, .T = 32},
{.tag = 0x1EB7B9CDBC09C00E, .K = 64, .T = 32},
{.tag = 0xDBF869BD2DBB1776, .K = 32, .T = 32},
{.tag = 0x3ADB0C13DEAE2836, .K = 191, .T = 64},
{.tag = 0xAB69DB6A543188D6, .K = 128, .T = 64},
{.tag = 0x4A4ABEC4A724B796, .K = 64, .T = 64}
};
static inline uint8_t hammingDistance(uint64_t x, uint64_t y)
{
uint8_t distance = 0;
for(uint8_t i = 0; i < 64; i++)
{
distance += (x ^ y) & 1;
x >>= 1;
y >>= 1;
}
return distance;
}
const struct Fx25Mode* Fx25GetModeForTag(uint64_t tag)
{
struct Fx25Mode *closest = NULL;
uint8_t closestDistance = 255;
for(uint8_t i = 0; i < sizeof(Fx25ModeList) / sizeof(*Fx25ModeList); i++)
{
uint8_t distance = hammingDistance(tag, Fx25ModeList[i].tag);
if(distance == 0)
return &Fx25ModeList[i];
else if(distance < closestDistance)
{
closest = (struct Fx25Mode*)&Fx25ModeList[i];
closestDistance = distance;
}
}
if(closestDistance <= FX25_MAX_DISTANCE)
return closest;
else
return NULL;
}
const struct Fx25Mode* Fx25GetModeForSize(uint16_t size)
{
//use "UZ7HO Soundmodem standard" for choosing FX.25 mode
if(size <= 32)
return &Fx25ModeList[3];
else if(size <= 64)
return &Fx25ModeList[2];
else if(size <= 128)
return &Fx25ModeList[5];
else if(size <= 191)
return &Fx25ModeList[8];
else if(size <= 223)
return &Fx25ModeList[4];
else if(size <= 239)
return &Fx25ModeList[0];
else
return NULL; //frame too big, do not use FX.25
}
#ifdef FX25_PREGENERATE_POLYS
static struct LwFecRS rs16, rs32, rs64;
#else
static struct LwFecRS rs;
#endif
void Fx25Encode(uint8_t *buffer, const struct Fx25Mode *mode)
{
#ifdef FX25_PREGENERATE_POLYS
struct LwFecRS *rs = NULL;
switch(mode->T)
{
case 16:
rs = &rs16;
break;
case 32:
rs = &rs32;
break;
case 64:
rs = &rs64;
break;
default:
rs = &rs16;
break;
}
RsEncode(rs, buffer, mode->K);
#else
RsInit(&rs, mode->T, FX25_RS_FCR);
RsEncode(&rs, buffer, mode->K);
#endif
}
bool Fx25Decode(uint8_t *buffer, const struct Fx25Mode *mode, uint8_t *fixed)
{
#ifdef FX25_PREGENERATE_POLYS
struct LwFecRS *rs = NULL;
switch(mode->T)
{
case 16:
rs = &rs16;
break;
case 32:
rs = &rs32;
break;
case 64:
rs = &rs64;
break;
default:
rs = &rs16;
break;
}
return RsDecode(rs, buffer, mode->K, fixed);
#else
RsInit(&rs, mode->T, FX25_RS_FCR);
return RsDecode(&rs, buffer, mode->K, fixed);
#endif
}
void Fx25Init(void)
{
#ifdef FX25_PREGENERATE_POLYS
RsInit(&rs16, 16, FX25_RS_FCR);
RsInit(&rs32, 32, FX25_RS_FCR);
RsInit(&rs64, 64, FX25_RS_FCR);
#else
#endif
}
#endif