Restructure YSF again.

This commit is contained in:
Jonathan Naylor
2016-04-25 18:06:19 +01:00
parent 6f42e0dad3
commit 6700801653
4 changed files with 173 additions and 209 deletions

View File

@@ -32,6 +32,9 @@ m_state(RS_RF_LISTENING),
m_timeoutTimer(1000U, timeout), m_timeoutTimer(1000U, timeout),
m_interval(), m_interval(),
m_frames(0U), m_frames(0U),
m_errs(0U),
m_bits(0U),
m_headerSeen(false),
m_source(NULL), m_source(NULL),
m_dest(NULL), m_dest(NULL),
m_payload(), m_payload(),
@@ -61,7 +64,7 @@ bool CYSFControl::writeModem(unsigned char *data)
unsigned char type = data[0U]; unsigned char type = data[0U];
if (type == TAG_LOST && m_state == RS_RF_AUDIO) { if (type == TAG_LOST && m_state == RS_RF_AUDIO) {
LogMessage("YSF, transmission lost, %.1f seconds", float(m_frames) / 10.0F); LogMessage("YSF, transmission lost, %.1f seconds, BER: %.1f%%", float(m_frames) / 10.0F, float(m_errs * 100U) / float(m_bits));
if (m_parrot != NULL) if (m_parrot != NULL)
m_parrot->end(); m_parrot->end();
@@ -82,6 +85,9 @@ bool CYSFControl::writeModem(unsigned char *data)
return false; return false;
m_frames = 0U; m_frames = 0U;
m_errs = 0U;
m_bits = 1U;
m_headerSeen = false;
m_timeoutTimer.start(); m_timeoutTimer.start();
m_payload.reset(); m_payload.reset();
m_state = RS_RF_AUDIO; m_state = RS_RF_AUDIO;
@@ -93,6 +99,9 @@ bool CYSFControl::writeModem(unsigned char *data)
if (m_state != RS_RF_AUDIO) if (m_state != RS_RF_AUDIO)
return false; return false;
unsigned char orig[YSF_FRAME_LENGTH_BYTES];
::memcpy(orig, data + 2U, YSF_FRAME_LENGTH_BYTES);
unsigned char fi = fich.getFI(); unsigned char fi = fich.getFI();
if (valid && fi == YSF_FI_HEADER) { if (valid && fi == YSF_FI_HEADER) {
CSync::addYSFSync(data + 2U); CSync::addYSFSync(data + 2U);
@@ -102,15 +111,19 @@ bool CYSFControl::writeModem(unsigned char *data)
unsigned char dt = fich.getDT(); unsigned char dt = fich.getDT();
unsigned char cm = fich.getCM(); unsigned char cm = fich.getCM();
unsigned char orig[YSF_FRAME_LENGTH_BYTES];
::memcpy(orig, data + 2U, YSF_FRAME_LENGTH_BYTES);
fich.encode(data + 2U); fich.encode(data + 2U);
// valid = m_payload.processHeader(data + 2U);
unsigned int errs = calculateBER(orig, data + 2U); unsigned int errs = calculateBER(orig, data + 2U, YSF_SYNC_LENGTH_BYTES + YSF_FICH_LENGTH_BYTES);
LogDebug("YSF, FI=%u FN=%u FT=%u DT=%u BER=%.1f%%", fi, fn, ft, dt, float(errs) / 2.4F); LogDebug("YSF, FI=%u FN=%u FT=%u DT=%u BER=%.1f%%", fi, fn, ft, dt, float(errs) / 2.4F);
m_errs += errs;
m_bits += 240U;
m_frames++;
m_headerSeen = true;
// valid = m_payload.processHeaderData(data + 2U);
if (m_duplex) { if (m_duplex) {
fich.setMR(YSF_MR_BUSY); fich.setMR(YSF_MR_BUSY);
fich.encode(data + 2U); fich.encode(data + 2U);
@@ -158,17 +171,18 @@ bool CYSFControl::writeModem(unsigned char *data)
unsigned char ft = fich.getFT(); unsigned char ft = fich.getFT();
unsigned char dt = fich.getDT(); unsigned char dt = fich.getDT();
unsigned char orig[YSF_FRAME_LENGTH_BYTES];
::memcpy(orig, data + 2U, YSF_FRAME_LENGTH_BYTES);
fich.encode(data + 2U); fich.encode(data + 2U);
// m_payload.processTrailer(data + 2U);
unsigned int errs = calculateBER(orig, data + 2U); unsigned int errs = calculateBER(orig, data + 2U, YSF_SYNC_LENGTH_BYTES + YSF_FICH_LENGTH_BYTES);
LogDebug("YSF, FI=%u FN=%u FT=%u DT=%u BER=%.1f%%", fi, fn, ft, dt, float(errs) / 2.4F); LogDebug("YSF, FI=%u FN=%u FT=%u DT=%u BER=%.1f%%", fi, fn, ft, dt, float(errs) / 2.4F);
m_errs += errs;
m_bits += 240U;
m_frames++; m_frames++;
// m_payload.processHeaderData(data + 2U);
if (m_duplex) { if (m_duplex) {
fich.setMR(YSF_MR_BUSY); fich.setMR(YSF_MR_BUSY);
fich.encode(data + 2U); fich.encode(data + 2U);
@@ -191,7 +205,7 @@ bool CYSFControl::writeModem(unsigned char *data)
writeFile(data + 2U); writeFile(data + 2U);
#endif #endif
LogMessage("YSF, received RF end of transmission, %.1f seconds", float(m_frames) / 10.0F); LogMessage("YSF, received RF end of transmission, %.1f seconds, BER: %.1f%%", float(m_frames) / 10.0F, float(m_errs * 100U) / float(m_bits));
writeEndOfTransmission(); writeEndOfTransmission();
return false; return false;
@@ -203,15 +217,45 @@ bool CYSFControl::writeModem(unsigned char *data)
unsigned char ft = fich.getFT(); unsigned char ft = fich.getFT();
unsigned char dt = fich.getDT(); unsigned char dt = fich.getDT();
unsigned char orig[YSF_FRAME_LENGTH_BYTES];
::memcpy(orig, data + 2U, YSF_FRAME_LENGTH_BYTES);
fich.encode(data + 2U); fich.encode(data + 2U);
// m_payload.processData(data + 2U, fn, dt);
unsigned int errs = calculateBER(orig, data + 2U); unsigned int errs = calculateBER(orig, data + 2U, YSF_SYNC_LENGTH_BYTES + YSF_FICH_LENGTH_BYTES);
LogDebug("YSF, FI=%u FN=%u FT=%u DT=%u BER=%.1f%%", fi, fn, ft, dt, float(errs) / 2.4F); LogDebug("YSF, FI=%u FN=%u FT=%u DT=%u BER=%.1f%%", fi, fn, ft, dt, float(errs) / 2.4F);
m_errs += errs;
m_bits += 240U;
m_frames++;
switch (dt) {
case YSF_DT_VD_MODE1:
valid = m_payload.processVDMode1Data(data + 2U, fn);
m_errs += m_payload.processVDMode1Audio(data + 2U);
m_bits += 235U;
break;
case YSF_DT_VD_MODE2:
valid = m_payload.processVDMode2Data(data + 2U, fn);
m_errs += m_payload.processVDMode2Audio(data + 2U);
m_bits += 135U;
break;
case YSF_DT_DATA_FR_MODE:
valid = m_payload.processDataFRModeData(data + 2U, fn);
break;
default: // YSF_DT_VOICE_FR_MODE
if (!m_headerSeen) {
// The first packet after the header is odd, don't try and regenerate it
m_errs += m_payload.processVoiceFRModeAudio(data + 2U);
m_bits += 720U;
valid = false;
}
break;
}
m_headerSeen = false;
bool change = false; bool change = false;
if (m_dest == NULL) { if (m_dest == NULL) {
@@ -246,8 +290,6 @@ bool CYSFControl::writeModem(unsigned char *data)
} }
} }
m_frames++;
if (m_duplex) { if (m_duplex) {
fich.setMR(YSF_MR_BUSY); fich.setMR(YSF_MR_BUSY);
fich.encode(data + 2U); fich.encode(data + 2U);
@@ -272,7 +314,15 @@ bool CYSFControl::writeModem(unsigned char *data)
} else { } else {
CSync::addYSFSync(data + 2U); CSync::addYSFSync(data + 2U);
// Only calculate the BER on the sync word
unsigned int errs = calculateBER(orig, data + 2U, YSF_SYNC_LENGTH_BYTES);
LogDebug("YSF, invalid FICH, BER=%.1f%%", float(errs) / 0.4F);
m_errs += errs;
m_bits += 40U;
m_frames++; m_frames++;
m_headerSeen = false;
if (m_duplex) { if (m_duplex) {
data[0U] = TAG_DATA; data[0U] = TAG_DATA;
@@ -422,11 +472,11 @@ void CYSFControl::closeFile()
} }
} }
unsigned int CYSFControl::calculateBER(const unsigned char* orig, const unsigned char *curr) const unsigned int CYSFControl::calculateBER(const unsigned char* orig, const unsigned char *curr, unsigned int length) const
{ {
unsigned int errors = 0U; unsigned int errors = 0U;
for (unsigned int i = 0U; i < (YSF_SYNC_LENGTH_BYTES + YSF_FICH_LENGTH_BYTES); i++) { for (unsigned int i = 0U; i < length; i++) {
unsigned char v = orig[i] ^ curr[i]; unsigned char v = orig[i] ^ curr[i];
while (v != 0U) { while (v != 0U) {
v &= v - 1U; v &= v - 1U;

View File

@@ -50,6 +50,9 @@ private:
CTimer m_timeoutTimer; CTimer m_timeoutTimer;
CStopWatch m_interval; CStopWatch m_interval;
unsigned int m_frames; unsigned int m_frames;
unsigned int m_errs;
unsigned int m_bits;
bool m_headerSeen;
unsigned char* m_source; unsigned char* m_source;
unsigned char* m_dest; unsigned char* m_dest;
CYSFPayload m_payload; CYSFPayload m_payload;
@@ -65,7 +68,7 @@ private:
bool writeFile(const unsigned char* data); bool writeFile(const unsigned char* data);
void closeFile(); void closeFile();
unsigned int calculateBER(const unsigned char* orig, const unsigned char* curr) const; unsigned int calculateBER(const unsigned char* orig, const unsigned char* curr, unsigned int length) const;
}; };
#endif #endif

View File

@@ -98,31 +98,10 @@ CYSFPayload::~CYSFPayload()
delete[] m_dest; delete[] m_dest;
} }
void CYSFPayload::processData(unsigned char* bytes, unsigned char fn, unsigned char dt) bool CYSFPayload::processHeaderData(unsigned char* data)
{ {
assert(bytes != NULL); assert(data != NULL);
switch (dt) {
case YSF_DT_VD_MODE1:
processVDMode1(bytes + YSF_SYNC_LENGTH_BYTES + YSF_FICH_LENGTH_BYTES, fn);
break;
case YSF_DT_VD_MODE2:
processVDMode2(bytes + YSF_SYNC_LENGTH_BYTES + YSF_FICH_LENGTH_BYTES, fn);
break;
case YSF_DT_DATA_FR_MODE:
processDataFRMode(bytes + YSF_SYNC_LENGTH_BYTES + YSF_FICH_LENGTH_BYTES, fn);
break;
default: // YSF_DT_VOICE_FR_MODE
processVoiceFRMode(bytes + YSF_SYNC_LENGTH_BYTES + YSF_FICH_LENGTH_BYTES);
break;
}
}
bool CYSFPayload::processHeader(unsigned char* data)
{
data += YSF_SYNC_LENGTH_BYTES + YSF_FICH_LENGTH_BYTES; data += YSF_SYNC_LENGTH_BYTES + YSF_FICH_LENGTH_BYTES;
unsigned char dch[45U]; unsigned char dch[45U];
@@ -155,8 +134,8 @@ bool CYSFPayload::processHeader(unsigned char* data)
for (unsigned int i = 0U; i < 20U; i++) for (unsigned int i = 0U; i < 20U; i++)
output[i] ^= WHITENING_DATA[i]; output[i] ^= WHITENING_DATA[i];
CUtils::dump("Header, Source", output + 0U, 10U); CUtils::dump(1U, "Header, Source", output + 0U, 10U);
CUtils::dump("Header, Destination", output + 10U, 10U); CUtils::dump(1U, "Header, Destination", output + 10U, 10U);
if (m_source == NULL) { if (m_source == NULL) {
m_source = new unsigned char[10U]; m_source = new unsigned char[10U];
@@ -243,127 +222,30 @@ bool CYSFPayload::processHeader(unsigned char* data)
return valid; return valid;
} }
void CYSFPayload::processTrailer(unsigned char* data) unsigned int CYSFPayload::processVDMode1Audio(unsigned char* data)
{ {
assert(data != NULL);
data += YSF_SYNC_LENGTH_BYTES + YSF_FICH_LENGTH_BYTES; data += YSF_SYNC_LENGTH_BYTES + YSF_FICH_LENGTH_BYTES;
unsigned char dch[45U]; // Regenerate the AMBE FEC
unsigned int errors = 0U;
errors += m_fec.regenerateDMR(data + 9U);
errors += m_fec.regenerateDMR(data + 27U);
errors += m_fec.regenerateDMR(data + 45U);
errors += m_fec.regenerateDMR(data + 63U);
errors += m_fec.regenerateDMR(data + 81U);
unsigned char* p1 = data; LogDebug("YSF, V/D Mode 1, AMBE FEC %u/235 (%.1f%%)", errors, float(errors) / 2.35F);
unsigned char* p2 = dch;
for (unsigned int i = 0U; i < 5U; i++) {
::memcpy(p2, p1, 9U);
p1 += 18U; p2 += 9U;
}
CYSFConvolution conv; return errors;
conv.start();
for (unsigned int i = 0U; i < 180U; i++) {
unsigned int n = INTERLEAVE_TABLE_9_20[i];
uint8_t s0 = READ_BIT1(dch, n) ? 1U : 0U;
n++;
uint8_t s1 = READ_BIT1(dch, n) ? 1U : 0U;
conv.decode(s0, s1);
}
unsigned char output[23U];
conv.chainback(output, 180U);
bool valid = CCRC::checkCCITT162(output, 22U);
if (valid) {
for (unsigned int i = 0U; i < 20U; i++)
output[i] ^= WHITENING_DATA[i];
CUtils::dump("Trailer, Source", output + 0U, 10U);
CUtils::dump("Trailer, Destination", output + 10U, 10U);
for (unsigned int i = 0U; i < 20U; i++)
output[i] ^= WHITENING_DATA[i];
CCRC::addCCITT162(output, 22U);
output[22U] = 0x00U;
unsigned char convolved[45U];
conv.encode(output, convolved, 180U);
unsigned char bytes[45U];
unsigned int j = 0U;
for (unsigned int i = 0U; i < 180U; i++) {
unsigned int n = INTERLEAVE_TABLE_9_20[i];
bool s0 = READ_BIT1(convolved, j) != 0U;
j++;
bool s1 = READ_BIT1(convolved, j) != 0U;
j++;
WRITE_BIT1(bytes, n, s0);
n++;
WRITE_BIT1(bytes, n, s1);
}
p1 = data;
p2 = bytes;
for (unsigned int i = 0U; i < 5U; i++) {
::memcpy(p1, p2, 9U);
p1 += 18U; p2 += 9U;
}
}
::memset(output, ' ', 20U);
if (m_downlink != NULL)
::memcpy(output + 0U, m_downlink, 10U);
if (m_uplink != NULL)
::memcpy(output + 10U, m_uplink, 10U);
for (unsigned int i = 0U; i < 20U; i++)
output[i] ^= WHITENING_DATA[i];
CCRC::addCCITT162(output, 22U);
output[22U] = 0x00U;
unsigned char convolved[45U];
conv.encode(output, convolved, 180U);
unsigned char bytes[45U];
unsigned int j = 0U;
for (unsigned int i = 0U; i < 180U; i++) {
unsigned int n = INTERLEAVE_TABLE_9_20[i];
bool s0 = READ_BIT1(convolved, j) != 0U;
j++;
bool s1 = READ_BIT1(convolved, j) != 0U;
j++;
WRITE_BIT1(bytes, n, s0);
n++;
WRITE_BIT1(bytes, n, s1);
}
p1 = data + 9U;
p2 = bytes;
for (unsigned int i = 0U; i < 5U; i++) {
::memcpy(p1, p2, 9U);
p1 += 18U; p2 += 9U;
}
} }
void CYSFPayload::processVDMode1(unsigned char* data, unsigned char fn) bool CYSFPayload::processVDMode1Data(unsigned char* data, unsigned char fn)
{ {
// Regenerate the AMBE FEC assert(data != NULL);
// unsigned int errors = 0U;
// errors += m_fec.regenerateDMR(data + 9U);
// errors += m_fec.regenerateDMR(data + 27U);
// errors += m_fec.regenerateDMR(data + 45U);
// errors += m_fec.regenerateDMR(data + 63U);
// errors += m_fec.regenerateDMR(data + 81U);
// LogMessage("YSF, V/D Mode 1, AMBE FEC %u/235 (%.1f%%)", errors, float(errors) / 2.35F); data += YSF_SYNC_LENGTH_BYTES + YSF_FICH_LENGTH_BYTES;
unsigned char dch[45U]; unsigned char dch[45U];
@@ -397,8 +279,8 @@ void CYSFPayload::processVDMode1(unsigned char* data, unsigned char fn)
switch (fn) { switch (fn) {
case 0U: case 0U:
CUtils::dump("V/D Mode 1, Destination", output + 0U, 10U); CUtils::dump(1U, "V/D Mode 1, Destination", output + 0U, 10U);
CUtils::dump("V/D Mode 1, Source", output + 10U, 10U); CUtils::dump(1U, "V/D Mode 1, Source", output + 10U, 10U);
if (m_dest == NULL) { if (m_dest == NULL) {
m_dest = new unsigned char[10U]; m_dest = new unsigned char[10U];
@@ -464,10 +346,16 @@ void CYSFPayload::processVDMode1(unsigned char* data, unsigned char fn)
p1 += 18U; p2 += 9U; p1 += 18U; p2 += 9U;
} }
} }
return ret && (fn == 0U);
} }
void CYSFPayload::processVDMode2(unsigned char* data, unsigned char fn) unsigned int CYSFPayload::processVDMode2Audio(unsigned char* data)
{ {
assert(data != NULL);
data += YSF_SYNC_LENGTH_BYTES + YSF_FICH_LENGTH_BYTES;
unsigned int errors = 0U; unsigned int errors = 0U;
unsigned int offset = 40U; // DCH(0) unsigned int offset = 40U; // DCH(0)
@@ -476,9 +364,9 @@ void CYSFPayload::processVDMode2(unsigned char* data, unsigned char fn)
unsigned char vch[13U]; unsigned char vch[13U];
// Deinterleave // Deinterleave
for(unsigned int i = 0U; i < 104U; i++) { for (unsigned int i = 0U; i < 104U; i++) {
unsigned int n = INTERLEAVE_TABLE_26_4[i]; unsigned int n = INTERLEAVE_TABLE_26_4[i];
bool s = READ_BIT1(data, offset+n); bool s = READ_BIT1(data, offset + n);
WRITE_BIT1(vch, i, s); WRITE_BIT1(vch, i, s);
} }
@@ -486,43 +374,49 @@ void CYSFPayload::processVDMode2(unsigned char* data, unsigned char fn)
for (unsigned int i = 0U; i < 13U; i++) for (unsigned int i = 0U; i < 13U; i++)
vch[i] ^= WHITENING_DATA[i]; vch[i] ^= WHITENING_DATA[i];
// errors += READ_BIT1(vch, 103); // Padding bit must be zero but apparently it is not... // errors += READ_BIT1(vch, 103); // Padding bit must be zero but apparently it is not...
for(unsigned int i = 0U; i < 81U; i += 3) { for (unsigned int i = 0U; i < 81U; i += 3) {
uint8_t vote = bool(READ_BIT1(vch, i)) + bool(READ_BIT1(vch, i+1)) + bool(READ_BIT1(vch, i+2)); uint8_t vote = bool(READ_BIT1(vch, i)) + bool(READ_BIT1(vch, i + 1)) + bool(READ_BIT1(vch, i + 2));
if(vote == 1 || vote == 2) if (vote == 1 || vote == 2) {
{
bool decision = vote / 2; // exploit integer division: 1/2 == 0, 2/2 == 1. bool decision = vote / 2; // exploit integer division: 1/2 == 0, 2/2 == 1.
WRITE_BIT1(vch, i, decision); WRITE_BIT1(vch, i, decision);
WRITE_BIT1(vch, i+1, decision); WRITE_BIT1(vch, i + 1, decision);
WRITE_BIT1(vch, i+2, decision); WRITE_BIT1(vch, i + 2, decision);
errors++; errors++;
} }
} }
// Reconstruct only if we have bit errors. Technically we could even // Reconstruct only if we have bit errors. Technically we could even
// constrain it individually to the 5 VCH sections. // constrain it individually to the 5 VCH sections.
if(errors) if (errors > 0U) {
{
// Scramble // Scramble
for (unsigned int i = 0U; i < 13U; i++) for (unsigned int i = 0U; i < 13U; i++)
vch[i] ^= WHITENING_DATA[i]; vch[i] ^= WHITENING_DATA[i];
// Interleave // Interleave
for(unsigned int i = 0U; i < 104U; i++) { for (unsigned int i = 0U; i < 104U; i++) {
unsigned int n = INTERLEAVE_TABLE_26_4[i]; unsigned int n = INTERLEAVE_TABLE_26_4[i];
bool s = READ_BIT1(vch, i); bool s = READ_BIT1(vch, i);
WRITE_BIT1(data, offset+n, s); WRITE_BIT1(data, offset + n, s);
} }
} }
} }
LogDebug("YSF, V/D Mode 2, Repetition FEC %u/135 (%.1f%%)", errors, float(errors) / 1.35F);
// "errors" is the number of triplets that were recognized to be corrupted // "errors" is the number of triplets that were recognized to be corrupted
// and that were corrected. There are 27 of those per VCH and 5 VCH per CC, // and that were corrected. There are 27 of those per VCH and 5 VCH per CC,
// yielding a total of 27*5 = 135. I believe the expected value of this // yielding a total of 27*5 = 135. I believe the expected value of this
// error distribution to be Bin(1;3,BER)+Bin(2;3,BER) which entails 75% for // error distribution to be Bin(1;3,BER)+Bin(2;3,BER) which entails 75% for
// BER = 0.5. // BER = 0.5.
LogMessage("YSF, V/D Mode 2, Repetition FEC %u/135 (%.1f%%)", errors, float(errors) / 135.0F); return errors;
}
bool CYSFPayload::processVDMode2Data(unsigned char* data, unsigned char fn)
{
assert(data != NULL);
data += YSF_SYNC_LENGTH_BYTES + YSF_FICH_LENGTH_BYTES;
unsigned char dch[25U]; unsigned char dch[25U];
@@ -556,14 +450,14 @@ void CYSFPayload::processVDMode2(unsigned char* data, unsigned char fn)
switch (fn) { switch (fn) {
case 0U: case 0U:
CUtils::dump("V/D Mode 2, Destination", output, 10U); CUtils::dump(1U, "V/D Mode 2, Destination", output, 10U);
if (m_dest == NULL) { if (m_dest == NULL) {
m_dest = new unsigned char[10U]; m_dest = new unsigned char[10U];
::memcpy(m_dest, output, 10U); ::memcpy(m_dest, output, 10U);
} }
break; break;
case 1U: case 1U:
CUtils::dump("V/D Mode 2, Source", output, 10U); CUtils::dump(1U, "V/D Mode 2, Source", output, 10U);
if (m_source == NULL) { if (m_source == NULL) {
m_source = new unsigned char[10U]; m_source = new unsigned char[10U];
::memcpy(m_source, output, 10U); ::memcpy(m_source, output, 10U);
@@ -625,10 +519,16 @@ void CYSFPayload::processVDMode2(unsigned char* data, unsigned char fn)
p1 += 18U; p2 += 5U; p1 += 18U; p2 += 5U;
} }
} }
return ret && (fn == 0U || fn == 1U);
} }
void CYSFPayload::processDataFRMode(unsigned char* data, unsigned char fn) bool CYSFPayload::processDataFRModeData(unsigned char* data, unsigned char fn)
{ {
assert(data != NULL);
data += YSF_SYNC_LENGTH_BYTES + YSF_FICH_LENGTH_BYTES;
unsigned char dch[45U]; unsigned char dch[45U];
unsigned char* p1 = data; unsigned char* p1 = data;
@@ -654,15 +554,15 @@ void CYSFPayload::processDataFRMode(unsigned char* data, unsigned char fn)
unsigned char output[23U]; unsigned char output[23U];
conv.chainback(output, 180U); conv.chainback(output, 180U);
bool ret = CCRC::checkCCITT162(output, 22U); bool ret1 = CCRC::checkCCITT162(output, 22U);
if (ret) { if (ret1) {
for (unsigned int i = 0U; i < 20U; i++) for (unsigned int i = 0U; i < 20U; i++)
output[i] ^= WHITENING_DATA[i]; output[i] ^= WHITENING_DATA[i];
switch (fn) { switch (fn) {
case 0U: case 0U:
CUtils::dump("Data FR Mode, Destination", output + 0U, 10U); CUtils::dump(1U, "Data FR Mode, Destination", output + 0U, 10U);
CUtils::dump("Data FR Mode, Source", output + 10U, 10U); CUtils::dump(1U, "Data FR Mode, Source", output + 10U, 10U);
if (m_dest == NULL) { if (m_dest == NULL) {
m_dest = new unsigned char[10U]; m_dest = new unsigned char[10U];
@@ -735,7 +635,7 @@ void CYSFPayload::processDataFRMode(unsigned char* data, unsigned char fn)
conv.chainback(output, 180U); conv.chainback(output, 180U);
ret = CCRC::checkCCITT162(output, 22U); bool ret2 = CCRC::checkCCITT162(output, 22U);
if (fn == 0U) { if (fn == 0U) {
::memset(output, ' ', 20U); ::memset(output, ' ', 20U);
@@ -746,11 +646,11 @@ void CYSFPayload::processDataFRMode(unsigned char* data, unsigned char fn)
if (m_uplink != NULL) if (m_uplink != NULL)
::memcpy(output + 10U, m_uplink, 10U); ::memcpy(output + 10U, m_uplink, 10U);
ret = true; ret2 = true;
} }
// Data isn't corrupt so regenerate it // Data isn't corrupt so regenerate it
if (ret) { if (ret2) {
for (unsigned int i = 0U; i < 20U; i++) for (unsigned int i = 0U; i < 20U; i++)
output[i] ^= WHITENING_DATA[i]; output[i] ^= WHITENING_DATA[i];
@@ -784,19 +684,27 @@ void CYSFPayload::processDataFRMode(unsigned char* data, unsigned char fn)
p1 += 18U; p2 += 9U; p1 += 18U; p2 += 9U;
} }
} }
return ret1 && (fn == 0U);
} }
void CYSFPayload::processVoiceFRMode(unsigned char* data) unsigned int CYSFPayload::processVoiceFRModeAudio(unsigned char* data)
{ {
// Regenerate the AMBE FEC assert(data != NULL);
// unsigned int errors = 0U;
// errors += m_fec.regenerateYSF3(data + 0U);
// errors += m_fec.regenerateYSF3(data + 18U);
// errors += m_fec.regenerateYSF3(data + 36U);
// errors += m_fec.regenerateYSF3(data + 54U);
// errors += m_fec.regenerateYSF3(data + 72U);
// LogMessage("YSF, V Mode 3, AMBE FEC %u/720 (%.1f%%)", errors, float(errors) / 7.2F); data += YSF_SYNC_LENGTH_BYTES + YSF_FICH_LENGTH_BYTES;
// Regenerate the AMBE FEC
unsigned int errors = 0U;
errors += m_fec.regenerateYSF3(data + 0U);
errors += m_fec.regenerateYSF3(data + 18U);
errors += m_fec.regenerateYSF3(data + 36U);
errors += m_fec.regenerateYSF3(data + 54U);
errors += m_fec.regenerateYSF3(data + 72U);
LogDebug("YSF, V Mode 3, AMBE FEC %u/720 (%.1f%%)", errors, float(errors) / 7.2F);
return errors;
} }
void CYSFPayload::setUplink(const std::string& callsign) void CYSFPayload::setUplink(const std::string& callsign)

View File

@@ -28,9 +28,17 @@ public:
CYSFPayload(); CYSFPayload();
~CYSFPayload(); ~CYSFPayload();
bool processHeader(unsigned char* bytes); bool processHeaderData(unsigned char* bytes);
void processData(unsigned char* bytes, unsigned char fn, unsigned char dt);
void processTrailer(unsigned char* bytes); bool processVDMode1Data(unsigned char* bytes, unsigned char fn);
unsigned int processVDMode1Audio(unsigned char* bytes);
bool processVDMode2Data(unsigned char* bytes, unsigned char fn);
unsigned int processVDMode2Audio(unsigned char* bytes);
bool processDataFRModeData(unsigned char* bytes, unsigned char fn);
unsigned int processVoiceFRModeAudio(unsigned char* bytes);
unsigned char* getSource(); unsigned char* getSource();
unsigned char* getDest(); unsigned char* getDest();
@@ -46,11 +54,6 @@ private:
unsigned char* m_source; unsigned char* m_source;
unsigned char* m_dest; unsigned char* m_dest;
CAMBEFEC m_fec; CAMBEFEC m_fec;
void processVDMode1(unsigned char* bytes, unsigned char fn);
void processVDMode2(unsigned char* bytes, unsigned char fn);
void processDataFRMode(unsigned char* bytes, unsigned char fn);
void processVoiceFRMode(unsigned char* bytes);
}; };
#endif #endif