Skip to content

Commit

Permalink
Decode and encode the System Fusion FICH.
Browse files Browse the repository at this point in the history
  • Loading branch information
g4klx committed Feb 23, 2016
1 parent 6792894 commit dc819b8
Show file tree
Hide file tree
Showing 10 changed files with 219 additions and 74 deletions.
20 changes: 0 additions & 20 deletions CRC.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -238,23 +238,3 @@ unsigned char CCRC::crc8(const unsigned char *in, unsigned int length)

return crc;
}

bool CCRC::crcFICH(const unsigned char* fich)
{
assert(fich != NULL);

union {
uint16_t crc16;
uint8_t crc8[2U];
};

crc16 = 0U;
crc16 = (uint16_t(crc8[0U]) << 8) ^ CCITT16_TABLE2[crc8[1U] ^ fich[0U]];
crc16 = (uint16_t(crc8[0U]) << 8) ^ CCITT16_TABLE2[crc8[1U] ^ fich[1U]];
crc16 = (uint16_t(crc8[0U]) << 8) ^ CCITT16_TABLE2[crc8[1U] ^ fich[2U]];
crc16 = (uint16_t(crc8[0U]) << 8) ^ CCITT16_TABLE2[crc8[1U] ^ fich[3U]];

crc16 = ~crc16;

return crc8[0U] == fich[5U] && crc8[1U] == fich[4U];
}
2 changes: 0 additions & 2 deletions CRC.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,8 +32,6 @@ class CCRC
static bool checkCCITT162(const unsigned char* in, unsigned int length);

static unsigned char crc8(const unsigned char* in, unsigned int length);

static bool crcFICH(const unsigned char* fich);
};

#endif
27 changes: 26 additions & 1 deletion YSFControl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
*/

#include "YSFControl.h"
#include "YSFFICH.h"
#include "Utils.h"
#include "Sync.h"
#include "Log.h"
Expand All @@ -24,7 +25,6 @@
/*
* TODO:
* AMBE FEC reconstruction.
* FICH regeneration.
* Callsign extraction + late entry.
* Uplink and downlink callsign addition.
*/
Expand Down Expand Up @@ -56,6 +56,10 @@ bool CYSFControl::writeModem(unsigned char *data)

if (type == TAG_LOST && m_state == RS_RELAYING_RF_AUDIO) {
LogMessage("YSF, transmission lost, %.1f seconds", float(m_frames) / 10.0F);

if (m_parrot != NULL)
m_parrot->end();

writeEndOfTransmission();
return false;
}
Expand Down Expand Up @@ -84,15 +88,24 @@ bool CYSFControl::writeModem(unsigned char *data)
if (type == TAG_EOT) {
CSync::addYSFSync(data + 2U);

CYSFFICH fich;
fich.decode(data + 2U);

m_frames++;

if (m_duplex) {
fich.setMR(YSF_MR_BUSY);
fich.encode(data + 2U);

data[0U] = TAG_EOT;
data[1U] = 0x00U;
writeQueue(data);
}

if (m_parrot != NULL) {
fich.setMR(YSF_MR_NOT_BUSY);
fich.encode(data + 2U);

data[0U] = TAG_EOT;
data[1U] = 0x00U;
writeParrot(data);
Expand All @@ -109,15 +122,24 @@ bool CYSFControl::writeModem(unsigned char *data)
} else {
CSync::addYSFSync(data + 2U);

CYSFFICH fich;
fich.decode(data + 2U);

m_frames++;

if (m_duplex) {
fich.setMR(YSF_MR_BUSY);
fich.encode(data + 2U);

data[0U] = TAG_DATA;
data[1U] = 0x00U;
writeQueue(data);
}

if (m_parrot != NULL) {
fich.setMR(YSF_MR_NOT_BUSY);
fich.encode(data + 2U);

data[0U] = TAG_DATA;
data[1U] = 0x00U;
writeParrot(data);
Expand Down Expand Up @@ -196,6 +218,9 @@ void CYSFControl::writeParrot(const unsigned char *data)
return;

m_parrot->write(data);

if (data[0U] == TAG_EOT)
m_parrot->end();
}

bool CYSFControl::openFile()
Expand Down
71 changes: 49 additions & 22 deletions YSFConvolution.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ const unsigned char BIT_MASK_TABLE[] = {0x80U, 0x40U, 0x20U, 0x10U, 0x08U, 0x04U
#define WRITE_BIT1(p,i,b) p[(i)>>3] = (b) ? (p[(i)>>3] | BIT_MASK_TABLE[(i)&7]) : (p[(i)>>3] & ~BIT_MASK_TABLE[(i)&7])
#define READ_BIT1(p,i) (p[(i)>>3] & BIT_MASK_TABLE[(i)&7])

const unsigned char BRANCH_TABLE1[] = {0U, 0U, 0U, 0U, 1U, 1U, 1U, 1U};
const unsigned char BRANCH_TABLE2[] = {0U, 1U, 1U, 0U, 0U, 1U, 1U, 0U};
const uint8_t BRANCH_TABLE1[] = {0U, 0U, 0U, 0U, 1U, 1U, 1U, 1U};
const uint8_t BRANCH_TABLE2[] = {0U, 1U, 1U, 0U, 0U, 1U, 1U, 0U};

CYSFConvolution::CYSFConvolution() :
m_metrics1(NULL),
Expand All @@ -40,9 +40,9 @@ m_newMetrics(NULL),
m_decisions(NULL),
m_dp(NULL)
{
m_metrics1 = new unsigned short[16U];
m_metrics2 = new unsigned short[16U];
m_decisions = new unsigned long long[100U];
m_metrics1 = new uint16_t[16U];
m_metrics2 = new uint16_t[16U];
m_decisions = new uint64_t[100U];
}

CYSFConvolution::~CYSFConvolution()
Expand All @@ -54,44 +54,44 @@ CYSFConvolution::~CYSFConvolution()

const unsigned int NUM_OF_STATES_D2 = 8U;
const unsigned int NUM_OF_STATES = 16U;
const unsigned int M = 3U;
const uint32_t M = 3U;
const unsigned int K = 5U;

void CYSFConvolution::start()
{
::memset(m_metrics1, 0x00U, NUM_OF_STATES * sizeof(unsigned short));
::memset(m_metrics2, 0x00U, NUM_OF_STATES * sizeof(unsigned short));
::memset(m_metrics1, 0x00U, NUM_OF_STATES * sizeof(uint16_t));
::memset(m_metrics2, 0x00U, NUM_OF_STATES * sizeof(uint16_t));

m_oldMetrics = m_metrics1;
m_newMetrics = m_metrics2;
m_dp = m_decisions;
}

void CYSFConvolution::decode(unsigned char s0, unsigned char s1)
void CYSFConvolution::decode(uint8_t s0, uint8_t s1)
{
*m_dp = 0U;

for (unsigned int i = 0U; i < NUM_OF_STATES_D2; i++) {
unsigned int j = i * 2U;
for (uint8_t i = 0U; i < NUM_OF_STATES_D2; i++) {
uint8_t j = i * 2U;

unsigned short metric = (BRANCH_TABLE1[i] ^ s0) + (BRANCH_TABLE2[i] ^ s1);
uint16_t metric = (BRANCH_TABLE1[i] ^ s0) + (BRANCH_TABLE2[i] ^ s1);

unsigned short m0 = m_oldMetrics[i] + metric;
unsigned short m1 = m_oldMetrics[i + NUM_OF_STATES_D2] + (M - metric);
unsigned char decision0 = (m0 >= m1) ? 1U : 0U;
uint16_t m0 = m_oldMetrics[i] + metric;
uint16_t m1 = m_oldMetrics[i + NUM_OF_STATES_D2] + (M - metric);
uint8_t decision0 = (m0 >= m1) ? 1U : 0U;
m_newMetrics[j + 0U] = decision0 != 0U ? m1 : m0;

m0 = m_oldMetrics[i] + (M - metric);
m1 = m_oldMetrics[i + NUM_OF_STATES_D2] + metric;
unsigned char decision1 = (m0 >= m1) ? 1U : 0U;
uint8_t decision1 = (m0 >= m1) ? 1U : 0U;
m_newMetrics[j + 1U] = decision1 != 0U ? m1 : m0;

*m_dp |= ((unsigned long long)(decision1) << (j + 1U)) | ((unsigned long long)(decision0) << (j + 0U));
*m_dp |= (uint64_t(decision1) << (j + 1U)) | (uint64_t(decision0) << (j + 0U));
}

++m_dp;

unsigned short* tmp = m_oldMetrics;
uint16_t* tmp = m_oldMetrics;
m_oldMetrics = m_newMetrics;
m_newMetrics = tmp;
}
Expand All @@ -100,16 +100,43 @@ void CYSFConvolution::chainback(unsigned char* out)
{
assert(out != NULL);

unsigned int state = 0U;
uint32_t state = 0U;

unsigned char nbits = 96U;
uint8_t nbits = 96U;
while (nbits-- > 0) {
--m_dp;

unsigned int i = state >> (9 - K);
unsigned char bit = (unsigned char)(*m_dp >> i) & 1;
uint32_t i = state >> (9 - K);
uint8_t bit = uint8_t(*m_dp >> i) & 1;
state = (bit << 7) | (state >> 1);

WRITE_BIT1(out, nbits, bit != 0U);
}
}

void CYSFConvolution::encode(const unsigned char* in, unsigned char* out, unsigned int nBits) const
{
assert(in != NULL);
assert(out != NULL);
assert(nBits > 0U);

uint8_t d1 = 0U, d2 = 0U, d3 = 0U, d4 = 0U;
uint32_t k = 0U;
for (unsigned int i = 0U; i < nBits; i++) {
uint8_t d = READ_BIT1(in, i) ? 1U : 0U;

uint8_t g1 = (d + d3 + d4) & 1;
uint8_t g2 = (d + d1 + d2 + d4) & 1;

d4 = d3;
d3 = d2;
d2 = d1;
d1 = d;

WRITE_BIT1(out, k, g1 != 0U);
k++;

WRITE_BIT1(out, k, g2 != 0U);
k++;
}
}
18 changes: 11 additions & 7 deletions YSFConvolution.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,22 +21,26 @@

#include "YSFConvolution.h"

#include <cstdint>

class CYSFConvolution {
public:
CYSFConvolution();
~CYSFConvolution();

void start();
void decode(unsigned char s0, unsigned char s1);
void decode(uint8_t s0, uint8_t s1);
void chainback(unsigned char* out);

void encode(const unsigned char* in, unsigned char* out, unsigned int nBits) const;

private:
unsigned short* m_metrics1;
unsigned short* m_metrics2;
unsigned short* m_oldMetrics;
unsigned short* m_newMetrics;
unsigned long long* m_decisions;
unsigned long long* m_dp;
uint16_t* m_metrics1;
uint16_t* m_metrics2;
uint16_t* m_oldMetrics;
uint16_t* m_newMetrics;
uint64_t* m_decisions;
uint64_t* m_dp;
};

#endif
Expand Down
6 changes: 6 additions & 0 deletions YSFDefines.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,4 +32,10 @@ const unsigned char YSF_DT_TERMINATOR_CHANNEL = 0x80U;

const unsigned char YSF_CKSUM_OK = 0x01U;

const unsigned char YSF_CM_GROUP = 0x00U;
const unsigned char YSF_CM_INDIVIDUAL = 0x0CU;

const unsigned char YSF_MR_NOT_BUSY = 0x08U;
const unsigned char YSF_MR_BUSY = 0x10U;

#endif
Loading

0 comments on commit dc819b8

Please sign in to comment.