WIP not decoding the SACCH correctly.

This commit is contained in:
Jonathan Naylor 2018-01-23 20:06:14 +00:00
parent 88b12104d3
commit ee18aa602c
6 changed files with 182 additions and 48 deletions

View file

@ -30,14 +30,14 @@ const uint16_t BIT_MASK_TABLE2[] = { 0x8000U, 0x4000U, 0x2000U, 0x1000U, 0x0800U
#define READ_BIT2(p,i) (p[(i)>>4] & BIT_MASK_TABLE2[(i)&15]) #define READ_BIT2(p,i) (p[(i)>>4] & BIT_MASK_TABLE2[(i)&15])
bool CNXDNCRC::checkCRC6(const unsigned char* in, unsigned int offset, unsigned int length) bool CNXDNCRC::checkCRC6(const unsigned char* in, unsigned int length)
{ {
assert(in != NULL); assert(in != NULL);
uint8_t crc[1U]; uint8_t crc[1U];
crc[0U] = createCRC6(in, offset, length); crc[0U] = createCRC6(in, length);
unsigned int n = offset + length; unsigned int n = length;
for (unsigned int i = 0U; i < 6U; i++, n++) { for (unsigned int i = 0U; i < 6U; i++, n++) {
bool b1 = READ_BIT1(crc, i); bool b1 = READ_BIT1(crc, i);
bool b2 = READ_BIT1(in, n); bool b2 = READ_BIT1(in, n);
@ -48,28 +48,28 @@ bool CNXDNCRC::checkCRC6(const unsigned char* in, unsigned int offset, unsigned
return true; return true;
} }
void CNXDNCRC::encodeCRC6(unsigned char* in, unsigned int offset, unsigned int length) void CNXDNCRC::encodeCRC6(unsigned char* in, unsigned int length)
{ {
assert(in != NULL); assert(in != NULL);
uint8_t crc[1U]; uint8_t crc[1U];
crc[0U] = createCRC6(in, offset, length); crc[0U] = createCRC6(in, length);
unsigned int n = offset + length; unsigned int n = length;
for (unsigned int i = 0U; i < 6U; i++, n++) { for (unsigned int i = 0U; i < 6U; i++, n++) {
bool b = READ_BIT1(crc, i); bool b = READ_BIT1(crc, i);
WRITE_BIT1(in, n, b); WRITE_BIT1(in, n, b);
} }
} }
bool CNXDNCRC::checkCRC12(const unsigned char* in, unsigned int offset, unsigned int length) bool CNXDNCRC::checkCRC12(const unsigned char* in, unsigned int length)
{ {
assert(in != NULL); assert(in != NULL);
uint16_t crc[1U]; uint16_t crc[1U];
crc[0U] = createCRC12(in, offset, length); crc[0U] = createCRC12(in, length);
unsigned int n = offset + length; unsigned int n = length;
for (unsigned int i = 0U; i < 12U; i++, n++) { for (unsigned int i = 0U; i < 12U; i++, n++) {
bool b1 = READ_BIT2(crc, i); bool b1 = READ_BIT2(crc, i);
bool b2 = READ_BIT1(in, n); bool b2 = READ_BIT1(in, n);
@ -80,28 +80,28 @@ bool CNXDNCRC::checkCRC12(const unsigned char* in, unsigned int offset, unsigned
return true; return true;
} }
void CNXDNCRC::encodeCRC12(unsigned char* in, unsigned int offset, unsigned int length) void CNXDNCRC::encodeCRC12(unsigned char* in, unsigned int length)
{ {
assert(in != NULL); assert(in != NULL);
uint16_t crc[1U]; uint16_t crc[1U];
crc[0U] = createCRC12(in, offset, length); crc[0U] = createCRC12(in, length);
unsigned int n = offset + length; unsigned int n = length;
for (unsigned int i = 0U; i < 12U; i++, n++) { for (unsigned int i = 0U; i < 12U; i++, n++) {
bool b = READ_BIT2(crc, i); bool b = READ_BIT2(crc, i);
WRITE_BIT1(in, n, b); WRITE_BIT1(in, n, b);
} }
} }
bool CNXDNCRC::checkCRC15(const unsigned char* in, unsigned int offset, unsigned int length) bool CNXDNCRC::checkCRC15(const unsigned char* in, unsigned int length)
{ {
assert(in != NULL); assert(in != NULL);
uint16_t crc[1U]; uint16_t crc[1U];
crc[0U] = createCRC15(in, offset, length); crc[0U] = createCRC15(in, length);
unsigned int n = offset + length; unsigned int n = length;
for (unsigned int i = 0U; i < 15U; i++, n++) { for (unsigned int i = 0U; i < 15U; i++, n++) {
bool b1 = READ_BIT2(crc, i); bool b1 = READ_BIT2(crc, i);
bool b2 = READ_BIT1(in, n); bool b2 = READ_BIT1(in, n);
@ -112,38 +112,110 @@ bool CNXDNCRC::checkCRC15(const unsigned char* in, unsigned int offset, unsigned
return true; return true;
} }
void CNXDNCRC::encodeCRC15(unsigned char* in, unsigned int offset, unsigned int length) void CNXDNCRC::encodeCRC15(unsigned char* in, unsigned int length)
{ {
assert(in != NULL); assert(in != NULL);
uint16_t crc[1U]; uint16_t crc[1U];
crc[0U] = createCRC15(in, offset, length); crc[0U] = createCRC15(in, length);
unsigned int n = offset + length; unsigned int n = length;
for (unsigned int i = 0U; i < 15U; i++, n++) { for (unsigned int i = 0U; i < 15U; i++, n++) {
bool b = READ_BIT2(crc, i); bool b = READ_BIT2(crc, i);
WRITE_BIT1(in, n, b); WRITE_BIT1(in, n, b);
} }
} }
uint8_t CNXDNCRC::createCRC6(const unsigned char* in, unsigned int offset, unsigned int length) uint8_t CNXDNCRC::createCRC6(const unsigned char* in, unsigned int length)
{ {
uint8_t crc = 0x3FU; uint8_t crc = 0x3EU;
return crc; for (unsigned int i = 0U; i < length; i++) {
bool bit1 = READ_BIT1(in, i) != 0x00U;
bool bit2 = (crc & 0x20U) == 0x20U;
crc <<= 1;
if (bit1)
crc |= 0x01U;
if (bit2)
crc |= 0x27U;
crc &= 0x3FU;
}
for (unsigned int i = 0U; i < 6U; i++) {
bool bit = (crc & 0x20U) == 0x20U;
crc <<= 1;
if (bit)
crc ^= 0x27U;
}
return crc & 0x3FU;
} }
uint16_t CNXDNCRC::createCRC12(const unsigned char* in, unsigned int offset, unsigned int length) uint16_t CNXDNCRC::createCRC12(const unsigned char* in, unsigned int length)
{ {
uint16_t crc = 0x0FFFU; uint16_t crc = 0x0D9EU;
return crc; for (unsigned int i = 0U; i < length; i++) {
bool bit1 = READ_BIT1(in, i) != 0x00U;
bool bit2 = (crc & 0x0800U) == 0x0800U;
crc <<= 1;
if (bit1)
crc |= 0x0001U;
if (bit2)
crc ^= 0x080FU;
crc &= 0x0FFFU;
}
for (unsigned int i = 0U; i < 12U; i++) {
bool bit = (crc & 0x0800U) == 0x0800U;
crc <<= 1;
if (bit)
crc ^= 0x080FU;
}
return crc & 0x0FFFU;
} }
uint16_t CNXDNCRC::createCRC15(const unsigned char* in, unsigned int offset, unsigned int length) uint16_t CNXDNCRC::createCRC15(const unsigned char* in, unsigned int length)
{ {
uint16_t crc = 0x7FFFU; uint16_t crc = 0x02E4U;
return crc; for (unsigned int i = 0U; i < length; i++) {
bool bit1 = READ_BIT1(in, i) != 0x00U;
bool bit2 = (crc & 0x4000U) == 0x4000U;
crc <<= 1;
if (bit1)
crc |= 0x0001U;
if (bit2)
crc ^= 0x4CC5U;
crc &= 0x7FFFU;
}
for (unsigned int i = 0U; i < 15U; i++) {
bool bit = (crc & 0x4000U) == 0x4000U;
crc <<= 1;
if (bit)
crc ^= 0x4CC5U;
}
return crc & 0x7FFFU;
} }

View file

@ -24,19 +24,19 @@
class CNXDNCRC class CNXDNCRC
{ {
public: public:
static bool checkCRC6(const unsigned char* in, unsigned int offset, unsigned int length); static bool checkCRC6(const unsigned char* in, unsigned int length);
static void encodeCRC6(unsigned char* in, unsigned int offset, unsigned int length); static void encodeCRC6(unsigned char* in, unsigned int length);
static bool checkCRC12(const unsigned char* in, unsigned int offset, unsigned int length); static bool checkCRC12(const unsigned char* in, unsigned int length);
static void encodeCRC12(unsigned char* in, unsigned int offset, unsigned int length); static void encodeCRC12(unsigned char* in, unsigned int length);
static bool checkCRC15(const unsigned char* in, unsigned int offset, unsigned int length); static bool checkCRC15(const unsigned char* in, unsigned int length);
static void encodeCRC15(unsigned char* in, unsigned int offset, unsigned int length); static void encodeCRC15(unsigned char* in, unsigned int length);
private: private:
static uint8_t createCRC6(const unsigned char* in, unsigned int offser, unsigned int length); static uint8_t createCRC6(const unsigned char* in, unsigned int length);
static uint16_t createCRC12(const unsigned char* in, unsigned int offser, unsigned int length); static uint16_t createCRC12(const unsigned char* in, unsigned int length);
static uint16_t createCRC15(const unsigned char* in, unsigned int offser, unsigned int length); static uint16_t createCRC15(const unsigned char* in, unsigned int length);
}; };
#endif #endif

View file

@ -125,11 +125,11 @@ bool CNXDNControl::writeModem(unsigned char *data, unsigned int len)
m_rssiCount++; m_rssiCount++;
} }
CUtils::dump(2U, "NXDN, raw data", data + 2U, NXDN_FRAME_LENGTH_BYTES); // CUtils::dump(2U, "NXDN, raw data", data + 2U, NXDN_FRAME_LENGTH_BYTES);
scrambler(data + 2U); scrambler(data + 2U);
CUtils::dump(2U, "NXDN, after descrambling", data + 2U, NXDN_FRAME_LENGTH_BYTES); // CUtils::dump(2U, "NXDN, after descrambling", data + 2U, NXDN_FRAME_LENGTH_BYTES);
CNXDNLICH lich; CNXDNLICH lich;
bool valid = lich.decode(data + 2U); bool valid = lich.decode(data + 2U);

View file

@ -21,7 +21,7 @@
class CNXDNLICH { class CNXDNLICH {
public: public:
CNXDNLICH(const CNXDNLICH& fich); CNXDNLICH(const CNXDNLICH& lich);
CNXDNLICH(); CNXDNLICH();
~CNXDNLICH(); ~CNXDNLICH();
@ -39,7 +39,7 @@ public:
void setOption(unsigned char option); void setOption(unsigned char option);
void setDirection(unsigned char direction); void setDirection(unsigned char direction);
CNXDNLICH& operator=(const CNXDNLICH& fich); CNXDNLICH& operator=(const CNXDNLICH& lich);
private: private:
unsigned char m_lich; unsigned char m_lich;

View file

@ -35,13 +35,20 @@ const unsigned int INTERLEAVE_TABLE[] = {
4U, 9U, 14U, 19U, 24U, 29U, 34U, 39U, 44U, 49U, 54U, 59U 4U, 9U, 14U, 19U, 24U, 29U, 34U, 39U, 44U, 49U, 54U, 59U
}; };
const unsigned int PUNCTURE_LIST[] = { 5U, 11U, 17U, 23U, 29U, 35U, 41U, 47U, 53U, 59U }; const unsigned int PUNCTURE_LIST[] = { 5U, 11U, 17U, 23U, 29U, 35U, 41U, 47U, 53U, 59U, 65U, 71U };
const unsigned char BIT_MASK_TABLE[] = { 0x80U, 0x40U, 0x20U, 0x10U, 0x08U, 0x04U, 0x02U, 0x01U }; const unsigned char BIT_MASK_TABLE[] = { 0x80U, 0x40U, 0x20U, 0x10U, 0x08U, 0x04U, 0x02U, 0x01U };
#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 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]) #define READ_BIT1(p,i) (p[(i)>>3] & BIT_MASK_TABLE[(i)&7])
CNXDNSACCH::CNXDNSACCH(const CNXDNSACCH& sacch) :
m_data(NULL)
{
m_data = new unsigned char[5U];
::memcpy(m_data, sacch.m_data, 5U);
}
CNXDNSACCH::CNXDNSACCH() : CNXDNSACCH::CNXDNSACCH() :
m_data(NULL) m_data(NULL)
{ {
@ -57,15 +64,19 @@ bool CNXDNSACCH::decode(const unsigned char* data)
{ {
assert(data != NULL); assert(data != NULL);
CUtils::dump("NXDN, SACCH input", data, 12U);
unsigned char temp1[8U]; unsigned char temp1[8U];
for (unsigned int i = 0U; i < NXDN_SACCH_LENGTH_BITS; i++) { for (unsigned int i = 0U; i < NXDN_SACCH_LENGTH_BITS; i++) {
unsigned int n = INTERLEAVE_TABLE[i] + NXDN_LICH_LENGTH_BITS; unsigned int n = INTERLEAVE_TABLE[i] + NXDN_FSW_LENGTH_BITS + NXDN_LICH_LENGTH_BITS;
bool b = READ_BIT1(data, n); bool b = READ_BIT1(data, n);
WRITE_BIT1(temp1, i, b); WRITE_BIT1(temp1, i, b);
} }
unsigned char temp2[8U]; CUtils::dump("NXDN, SACCH de-interleaved", temp1, 8U);
unsigned char temp2[9U];
unsigned int n = 0U; unsigned int n = 0U;
unsigned int index = 0U; unsigned int index = 0U;
@ -81,6 +92,8 @@ bool CNXDNSACCH::decode(const unsigned char* data)
n++; n++;
} }
CUtils::dump("NXDN, SACCH de-punctured", temp2, 9U);
CNXDNConvolution conv; CNXDNConvolution conv;
conv.start(); conv.start();
@ -88,7 +101,9 @@ bool CNXDNSACCH::decode(const unsigned char* data)
for (unsigned int i = 0U; i < 36U; i++) { for (unsigned int i = 0U; i < 36U; i++) {
uint8_t s0 = READ_BIT1(temp2, n) ? 1U : 0U; uint8_t s0 = READ_BIT1(temp2, n) ? 1U : 0U;
n++; n++;
uint8_t s1 = READ_BIT1(temp2, n) ? 1U : 0U; uint8_t s1 = READ_BIT1(temp2, n) ? 1U : 0U;
n++;
conv.decode(s0, s1); conv.decode(s0, s1);
} }
@ -97,11 +112,47 @@ bool CNXDNSACCH::decode(const unsigned char* data)
CUtils::dump("NXDN, SACCH", m_data, 5U); CUtils::dump("NXDN, SACCH", m_data, 5U);
bool valid = CNXDNCRC::checkCRC6(m_data, 0U, 32U); return CNXDNCRC::checkCRC6(m_data, 26U);
// if (!valid) }
// return false;
return true; void CNXDNSACCH::encode(unsigned char* data) const
{
assert(data != NULL);
unsigned char temp1[5U];
::memset(temp1, 0x00U, 5U);
for (unsigned int i = 0U; i < 26U; i++) {
bool b = READ_BIT1(m_data, i);
WRITE_BIT1(temp1, i, b);
}
CNXDNCRC::encodeCRC6(temp1, 26U);
unsigned char temp2[9U];
CNXDNConvolution conv;
conv.encode(temp1, temp2, 36U);
unsigned char temp3[8U];
unsigned int n = 0U;
unsigned int index = 0U;
for (unsigned int i = 0U; i < 72U; i++) {
if (i != PUNCTURE_LIST[index]) {
bool b = READ_BIT1(temp2, i);
WRITE_BIT1(temp3, n, b);
n++;
} else {
index++;
}
}
for (unsigned int i = 0U; i < NXDN_SACCH_LENGTH_BITS; i++) {
unsigned int n = INTERLEAVE_TABLE[i] + NXDN_FSW_LENGTH_BITS + NXDN_LICH_LENGTH_BITS;
bool b = READ_BIT1(temp3, i);
WRITE_BIT1(data, n, b);
}
} }
unsigned char CNXDNSACCH::getRAN() const unsigned char CNXDNSACCH::getRAN() const
@ -139,3 +190,11 @@ void CNXDNSACCH::setData(const unsigned char* data)
::memcpy(m_data + 1U, data, 3U); ::memcpy(m_data + 1U, data, 3U);
} }
CNXDNSACCH& CNXDNSACCH::operator=(const CNXDNSACCH& sacch)
{
if (&sacch != this)
::memcpy(m_data, sacch.m_data, 5U);
return *this;
}

View file

@ -21,12 +21,13 @@
class CNXDNSACCH { class CNXDNSACCH {
public: public:
CNXDNSACCH(const CNXDNSACCH& sacch);
CNXDNSACCH(); CNXDNSACCH();
~CNXDNSACCH(); ~CNXDNSACCH();
bool decode(const unsigned char* data); bool decode(const unsigned char* data);
void encode(unsigned char* data); void encode(unsigned char* data) const;
unsigned char getRAN() const; unsigned char getRAN() const;
unsigned char getStructure() const; unsigned char getStructure() const;
@ -38,6 +39,8 @@ public:
void setData(const unsigned char* data); void setData(const unsigned char* data);
CNXDNSACCH& operator=(const CNXDNSACCH& fich);
private: private:
unsigned char* m_data; unsigned char* m_data;
}; };