Skip to content

Commit dc819b8

Browse files
committed
Decode and encode the System Fusion FICH.
1 parent 6792894 commit dc819b8

10 files changed

+219
-74
lines changed

CRC.cpp

-20
Original file line numberDiff line numberDiff line change
@@ -238,23 +238,3 @@ unsigned char CCRC::crc8(const unsigned char *in, unsigned int length)
238238

239239
return crc;
240240
}
241-
242-
bool CCRC::crcFICH(const unsigned char* fich)
243-
{
244-
assert(fich != NULL);
245-
246-
union {
247-
uint16_t crc16;
248-
uint8_t crc8[2U];
249-
};
250-
251-
crc16 = 0U;
252-
crc16 = (uint16_t(crc8[0U]) << 8) ^ CCITT16_TABLE2[crc8[1U] ^ fich[0U]];
253-
crc16 = (uint16_t(crc8[0U]) << 8) ^ CCITT16_TABLE2[crc8[1U] ^ fich[1U]];
254-
crc16 = (uint16_t(crc8[0U]) << 8) ^ CCITT16_TABLE2[crc8[1U] ^ fich[2U]];
255-
crc16 = (uint16_t(crc8[0U]) << 8) ^ CCITT16_TABLE2[crc8[1U] ^ fich[3U]];
256-
257-
crc16 = ~crc16;
258-
259-
return crc8[0U] == fich[5U] && crc8[1U] == fich[4U];
260-
}

CRC.h

-2
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,6 @@ class CCRC
3232
static bool checkCCITT162(const unsigned char* in, unsigned int length);
3333

3434
static unsigned char crc8(const unsigned char* in, unsigned int length);
35-
36-
static bool crcFICH(const unsigned char* fich);
3735
};
3836

3937
#endif

YSFControl.cpp

+26-1
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
*/
1313

1414
#include "YSFControl.h"
15+
#include "YSFFICH.h"
1516
#include "Utils.h"
1617
#include "Sync.h"
1718
#include "Log.h"
@@ -24,7 +25,6 @@
2425
/*
2526
* TODO:
2627
* AMBE FEC reconstruction.
27-
* FICH regeneration.
2828
* Callsign extraction + late entry.
2929
* Uplink and downlink callsign addition.
3030
*/
@@ -56,6 +56,10 @@ bool CYSFControl::writeModem(unsigned char *data)
5656

5757
if (type == TAG_LOST && m_state == RS_RELAYING_RF_AUDIO) {
5858
LogMessage("YSF, transmission lost, %.1f seconds", float(m_frames) / 10.0F);
59+
60+
if (m_parrot != NULL)
61+
m_parrot->end();
62+
5963
writeEndOfTransmission();
6064
return false;
6165
}
@@ -84,15 +88,24 @@ bool CYSFControl::writeModem(unsigned char *data)
8488
if (type == TAG_EOT) {
8589
CSync::addYSFSync(data + 2U);
8690

91+
CYSFFICH fich;
92+
fich.decode(data + 2U);
93+
8794
m_frames++;
8895

8996
if (m_duplex) {
97+
fich.setMR(YSF_MR_BUSY);
98+
fich.encode(data + 2U);
99+
90100
data[0U] = TAG_EOT;
91101
data[1U] = 0x00U;
92102
writeQueue(data);
93103
}
94104

95105
if (m_parrot != NULL) {
106+
fich.setMR(YSF_MR_NOT_BUSY);
107+
fich.encode(data + 2U);
108+
96109
data[0U] = TAG_EOT;
97110
data[1U] = 0x00U;
98111
writeParrot(data);
@@ -109,15 +122,24 @@ bool CYSFControl::writeModem(unsigned char *data)
109122
} else {
110123
CSync::addYSFSync(data + 2U);
111124

125+
CYSFFICH fich;
126+
fich.decode(data + 2U);
127+
112128
m_frames++;
113129

114130
if (m_duplex) {
131+
fich.setMR(YSF_MR_BUSY);
132+
fich.encode(data + 2U);
133+
115134
data[0U] = TAG_DATA;
116135
data[1U] = 0x00U;
117136
writeQueue(data);
118137
}
119138

120139
if (m_parrot != NULL) {
140+
fich.setMR(YSF_MR_NOT_BUSY);
141+
fich.encode(data + 2U);
142+
121143
data[0U] = TAG_DATA;
122144
data[1U] = 0x00U;
123145
writeParrot(data);
@@ -196,6 +218,9 @@ void CYSFControl::writeParrot(const unsigned char *data)
196218
return;
197219

198220
m_parrot->write(data);
221+
222+
if (data[0U] == TAG_EOT)
223+
m_parrot->end();
199224
}
200225

201226
bool CYSFControl::openFile()

YSFConvolution.cpp

+49-22
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,8 @@ const unsigned char BIT_MASK_TABLE[] = {0x80U, 0x40U, 0x20U, 0x10U, 0x08U, 0x04U
2929
#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])
3030
#define READ_BIT1(p,i) (p[(i)>>3] & BIT_MASK_TABLE[(i)&7])
3131

32-
const unsigned char BRANCH_TABLE1[] = {0U, 0U, 0U, 0U, 1U, 1U, 1U, 1U};
33-
const unsigned char BRANCH_TABLE2[] = {0U, 1U, 1U, 0U, 0U, 1U, 1U, 0U};
32+
const uint8_t BRANCH_TABLE1[] = {0U, 0U, 0U, 0U, 1U, 1U, 1U, 1U};
33+
const uint8_t BRANCH_TABLE2[] = {0U, 1U, 1U, 0U, 0U, 1U, 1U, 0U};
3434

3535
CYSFConvolution::CYSFConvolution() :
3636
m_metrics1(NULL),
@@ -40,9 +40,9 @@ m_newMetrics(NULL),
4040
m_decisions(NULL),
4141
m_dp(NULL)
4242
{
43-
m_metrics1 = new unsigned short[16U];
44-
m_metrics2 = new unsigned short[16U];
45-
m_decisions = new unsigned long long[100U];
43+
m_metrics1 = new uint16_t[16U];
44+
m_metrics2 = new uint16_t[16U];
45+
m_decisions = new uint64_t[100U];
4646
}
4747

4848
CYSFConvolution::~CYSFConvolution()
@@ -54,44 +54,44 @@ CYSFConvolution::~CYSFConvolution()
5454

5555
const unsigned int NUM_OF_STATES_D2 = 8U;
5656
const unsigned int NUM_OF_STATES = 16U;
57-
const unsigned int M = 3U;
57+
const uint32_t M = 3U;
5858
const unsigned int K = 5U;
5959

6060
void CYSFConvolution::start()
6161
{
62-
::memset(m_metrics1, 0x00U, NUM_OF_STATES * sizeof(unsigned short));
63-
::memset(m_metrics2, 0x00U, NUM_OF_STATES * sizeof(unsigned short));
62+
::memset(m_metrics1, 0x00U, NUM_OF_STATES * sizeof(uint16_t));
63+
::memset(m_metrics2, 0x00U, NUM_OF_STATES * sizeof(uint16_t));
6464

6565
m_oldMetrics = m_metrics1;
6666
m_newMetrics = m_metrics2;
6767
m_dp = m_decisions;
6868
}
6969

70-
void CYSFConvolution::decode(unsigned char s0, unsigned char s1)
70+
void CYSFConvolution::decode(uint8_t s0, uint8_t s1)
7171
{
7272
*m_dp = 0U;
7373

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

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

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

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

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

9292
++m_dp;
9393

94-
unsigned short* tmp = m_oldMetrics;
94+
uint16_t* tmp = m_oldMetrics;
9595
m_oldMetrics = m_newMetrics;
9696
m_newMetrics = tmp;
9797
}
@@ -100,16 +100,43 @@ void CYSFConvolution::chainback(unsigned char* out)
100100
{
101101
assert(out != NULL);
102102

103-
unsigned int state = 0U;
103+
uint32_t state = 0U;
104104

105-
unsigned char nbits = 96U;
105+
uint8_t nbits = 96U;
106106
while (nbits-- > 0) {
107107
--m_dp;
108108

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

113113
WRITE_BIT1(out, nbits, bit != 0U);
114114
}
115115
}
116+
117+
void CYSFConvolution::encode(const unsigned char* in, unsigned char* out, unsigned int nBits) const
118+
{
119+
assert(in != NULL);
120+
assert(out != NULL);
121+
assert(nBits > 0U);
122+
123+
uint8_t d1 = 0U, d2 = 0U, d3 = 0U, d4 = 0U;
124+
uint32_t k = 0U;
125+
for (unsigned int i = 0U; i < nBits; i++) {
126+
uint8_t d = READ_BIT1(in, i) ? 1U : 0U;
127+
128+
uint8_t g1 = (d + d3 + d4) & 1;
129+
uint8_t g2 = (d + d1 + d2 + d4) & 1;
130+
131+
d4 = d3;
132+
d3 = d2;
133+
d2 = d1;
134+
d1 = d;
135+
136+
WRITE_BIT1(out, k, g1 != 0U);
137+
k++;
138+
139+
WRITE_BIT1(out, k, g2 != 0U);
140+
k++;
141+
}
142+
}

YSFConvolution.h

+11-7
Original file line numberDiff line numberDiff line change
@@ -21,22 +21,26 @@
2121

2222
#include "YSFConvolution.h"
2323

24+
#include <cstdint>
25+
2426
class CYSFConvolution {
2527
public:
2628
CYSFConvolution();
2729
~CYSFConvolution();
2830

2931
void start();
30-
void decode(unsigned char s0, unsigned char s1);
32+
void decode(uint8_t s0, uint8_t s1);
3133
void chainback(unsigned char* out);
3234

35+
void encode(const unsigned char* in, unsigned char* out, unsigned int nBits) const;
36+
3337
private:
34-
unsigned short* m_metrics1;
35-
unsigned short* m_metrics2;
36-
unsigned short* m_oldMetrics;
37-
unsigned short* m_newMetrics;
38-
unsigned long long* m_decisions;
39-
unsigned long long* m_dp;
38+
uint16_t* m_metrics1;
39+
uint16_t* m_metrics2;
40+
uint16_t* m_oldMetrics;
41+
uint16_t* m_newMetrics;
42+
uint64_t* m_decisions;
43+
uint64_t* m_dp;
4044
};
4145

4246
#endif

YSFDefines.h

+6
Original file line numberDiff line numberDiff line change
@@ -32,4 +32,10 @@ const unsigned char YSF_DT_TERMINATOR_CHANNEL = 0x80U;
3232

3333
const unsigned char YSF_CKSUM_OK = 0x01U;
3434

35+
const unsigned char YSF_CM_GROUP = 0x00U;
36+
const unsigned char YSF_CM_INDIVIDUAL = 0x0CU;
37+
38+
const unsigned char YSF_MR_NOT_BUSY = 0x08U;
39+
const unsigned char YSF_MR_BUSY = 0x10U;
40+
3541
#endif

0 commit comments

Comments
 (0)