Parity errors in NIC are now ignored.

Clean up the code to make it easier to understand. Now the logic to error correct the NIC makes more sense.
This commit is contained in:
EdFuentetaja 2014-03-01 20:35:46 +08:00
parent 9b9cb78ddf
commit d7b36f32c0
7 changed files with 137 additions and 134 deletions

View File

@ -1,109 +0,0 @@
#include <itpp/itcomm.h>
#include "check_nid.h"
using namespace itpp;
// Ideas taken from http://op25.osmocom.org/trac/wiki.png/browser/op25/gr-op25/lib/decoder_ff_impl.cc
// See also p25_training_guide.pdf page 48.
// See also tia-102-baaa-a-project_25-fdma-common_air_interface.pdf page 40.
// BCH encoder/decoder implementation from IT++. GNU GPL 3 license.
itpp::BCH bch(63, 16, 11, "6 3 3 1 1 4 1 3 6 7 2 3 5 4 5 3", true);
/** Convenience class to calculate the parity of the DUID values. Keeps a table with the expected outcomes
* for fast lookup.
*/
class ParityTable
{
private:
unsigned char table[16];
unsigned char get_index(unsigned char x, unsigned char y)
{
return (x<<2) + y;
}
public:
ParityTable()
{
for (unsigned int i=0; i<sizeof(table); i++) {
table[i] = 0;
}
table[get_index(1,1)] = 1;
table[get_index(2,2)] = 1;
}
unsigned char get_value(unsigned char x, unsigned char y)
{
return table[get_index(x,y)];
}
} parity_table;
/** Checks a NID value, returns the fixed NAC, DUID and also an indication if it failed to decode the NID.
*
* \param bch_code Input. An array to the 63 bytes, each containing one bit of the NID.
* \param new_nac Output. An address where to store the calculated NAC value after error correction. Should
* be large enough to accommodate for an integer.
* \param new_duid Output. An address where to store the calculated DUID value after error correction. Should
* be able to accommodate 3 chars.
* \param parity Input. The parity value read.
* \return 0 if there were errors processing the NID.
*/
int check_NID(char* bch_code, int* new_nac, char* new_duid, unsigned char parity)
{
int result;
// Fill up with the input given
bvec input(63);
for(unsigned int i=0; i<63; i++) {
input[i] = bch_code[i];
}
// Decode it
bvec decoded = bch.decode(input);
// Check if the decoded output is zero
bool zero = true;
for (int i=0; i<decoded.length(); i++) {
if (decoded[i] != 0) {
zero = false;
break;
}
}
if (zero) {
// Decode failed
result = 0;
} else {
// Encode it again
bvec encoded = bch.encode(decoded);
// Take the fixed NAC from the encoded output. It's a 12 bit number starting from position 47.
// Just convert the output from a binary sequence to an integer.
int nac = 0;
for (int i=47; i<47+12; i++) {
nac <<= 1;
nac |= (int)encoded[i];
}
*new_nac = nac;
// Take the fixed DUID from the encoded output. 4 bit value starting at position 59.
unsigned char x = (((int)encoded[59])<<1) + ((int)encoded[60]);
unsigned char y = (((int)encoded[61])<<1) + ((int)encoded[62]);
new_duid[0] = x + '0';
new_duid[1] = y + '0';
new_duid[2] = 0;
// Check the parity
unsigned char expected_parity = parity_table.get_value(x,y);
// Returns false (0) if they don't match
result = (expected_parity == parity);
}
return result;
}

View File

@ -1,14 +0,0 @@
#ifndef __CHECK_NID_H__
#define __CHECK_NID_H__
#ifdef __cplusplus
extern "C" {
#endif
int check_NID(char* bch_code, int* new_nac, char* new_duid, unsigned char parity);
#ifdef __cplusplus
}
#endif
#endif // __CHECK_NID_H__

1
dsd.h
View File

@ -171,6 +171,7 @@ typedef struct
unsigned int debug_audio_errors;
unsigned int debug_header_errors;
unsigned int debug_header_critical_errors;
} dsd_state;

View File

@ -20,7 +20,7 @@
#define NULL 0
#endif
#include "check_nid.h"
#include "p25p1_check_nid.h"
void
printFrameInfo (dsd_opts * opts, dsd_state * state)
@ -246,9 +246,9 @@ processFrame (dsd_opts * opts, dsd_state * state)
}
else
{
// NAC, 12 bits
// Read the NAC, 12 bits
j = 0;
index_bch_code = 47;
index_bch_code = 0;
for (i = 0; i < 6; i++)
{
dibit = getDibit (opts, state);
@ -267,7 +267,7 @@ processFrame (dsd_opts * opts, dsd_state * state)
}
state->nac = strtol (nac, NULL, 2);
// DUID, 4 bits
// Read the DUID, 4 bits
for (i = 0; i < 2; i++)
{
dibit = getDibit (opts, state);
@ -279,8 +279,7 @@ processFrame (dsd_opts * opts, dsd_state * state)
index_bch_code++;
}
// Now processing NID
index_bch_code = 0;
// Read the BCH data for error correction of NAC and DUID
for (i = 0; i < 3; i++)
{
dibit = getDibit (opts, state);
@ -301,7 +300,7 @@ processFrame (dsd_opts * opts, dsd_state * state)
index_bch_code++;
}
// last bit is the parity bit
// Read the parity bit
dibit = getDibit (opts, state);
bch_code[index_bch_code] = 1 & (dibit >> 1); // bit 1
parity = (1 & dibit); // bit 0
@ -316,15 +315,17 @@ processFrame (dsd_opts * opts, dsd_state * state)
}
if (strcmp(new_duid, duid) != 0) {
// DUID fixed by error correction
//printf("Fixing DUID %s -> %s\n", duid, new_duid);
duid[0] = new_duid[0];
duid[1] = new_duid[1];
state->debug_header_errors++;
}
} else {
// Check of NID failed and unable to recover its value
//printf("NID error\n");
duid[0] = 'E';
duid[1] = 'E';
state->debug_header_errors += 10;
state->debug_header_critical_errors ++;
}
}
@ -505,7 +506,9 @@ processFrame (dsd_opts * opts, dsd_state * state)
openMbeOutFile (opts, state);
}
}
state->lastp25type = 0;
//state->lastp25type = 0;
// Guess that the state is LDU2
state->lastp25type = 2;
sprintf (state->fsubtype, "(LDU2) ");
state->numtdulc = 0;
processLDU2 (opts, state);
@ -524,7 +527,9 @@ processFrame (dsd_opts * opts, dsd_state * state)
openMbeOutFile (opts, state);
}
}
state->lastp25type = 0;
//state->lastp25type = 0;
// Guess that the state is LDU1
state->lastp25type = 1;
sprintf (state->fsubtype, "(LDU1) ");
state->numtdulc = 0;
processLDU1 (opts, state);
@ -536,7 +541,9 @@ processFrame (dsd_opts * opts, dsd_state * state)
printFrameInfo (opts, state);
printf (" (TSDU)\n");
}
state->lastp25type = 0;
//state->lastp25type = 0;
// Guess that the state is TSDU
state->lastp25type = 3;
sprintf (state->fsubtype, "(TSDU) ");
// Now processing NID

View File

@ -223,6 +223,7 @@ initState (dsd_state * state)
state->debug_audio_errors = 0;
state->debug_header_errors = 0;
state->debug_header_critical_errors = 0;
}
void
@ -325,6 +326,7 @@ cleanupAndExit (dsd_opts * opts, dsd_state * state)
printf("\n");
printf("Total audio errors: %i\n", state->debug_audio_errors);
printf("Total header errors: %i\n", state->debug_header_errors);
printf("Total irrecoverable header errors: %i\n", state->debug_header_critical_errors);
printf ("Exiting.\n");
exit (0);

92
p25p1_check_nid.cpp Normal file
View File

@ -0,0 +1,92 @@
#include <itpp/itcomm.h>
#include "p25p1_check_nid.h"
using namespace itpp;
// Ideas taken from http://op25.osmocom.org/trac/wiki.png/browser/op25/gr-op25/lib/decoder_ff_impl.cc
// See also p25_training_guide.pdf page 48.
// See also tia-102-baaa-a-project_25-fdma-common_air_interface.pdf page 40.
// BCH encoder/decoder implementation from IT++. GNU GPL 3 license.
itpp::BCH bch(63, 16, 11, "6 3 3 1 1 4 1 3 6 7 2 3 5 4 5 3", true);
/** Convenience class to calculate the parity of the DUID values. Keeps a table with the expected outcomes
* for fast lookup.
*/
class ParityTable
{
private:
unsigned char table[16];
unsigned char get_index(unsigned char x, unsigned char y)
{
return (x<<2) + y;
}
public:
ParityTable()
{
for (unsigned int i=0; i<sizeof(table); i++) {
table[i] = 0;
}
table[get_index(1,1)] = 1;
table[get_index(2,2)] = 1;
}
unsigned char get_value(unsigned char x, unsigned char y)
{
return table[get_index(x,y)];
}
} parity_table;
int check_NID(char* bch_code, int* new_nac, char* new_duid, unsigned char parity)
{
int result;
// Fill up with the given input
bvec input(63);
for(unsigned int i=0; i<63; i++) {
input[i] = bch_code[i];
}
// Decode it
bvec decoded, cw_isvalid;
bool ok = bch.decode(input, decoded, cw_isvalid);
if (!ok) {
// Decode failed
result = 0;
} else {
// Take the NAC from the decoded output. It's a 12 bit number starting from position 0.
// Just convert the output from a binary sequence to an integer.
int nac = 0;
for (int i=0; i<12; i++) {
nac <<= 1;
nac |= (int)decoded[i];
}
*new_nac = nac;
// Take the fixed DUID from the encoded output. 4 bit value starting at position 12.
unsigned char new_duid_0 = (((int)decoded[12])<<1) + ((int)decoded[13]);
unsigned char new_duid_1 = (((int)decoded[14])<<1) + ((int)decoded[15]);
new_duid[0] = new_duid_0 + '0';
new_duid[1] = new_duid_1 + '0';
new_duid[2] = 0; // Null terminate
// Check the parity
unsigned char expected_parity = parity_table.get_value(new_duid_0, new_duid_1);
if (expected_parity != parity) {
// Ignore, not sure what to do
//printf("Error in parity detected?");
}
result = 1;
}
return result;
}

24
p25p1_check_nid.h Normal file
View File

@ -0,0 +1,24 @@
#ifndef __CHECK_NID_H__
#define __CHECK_NID_H__
#ifdef __cplusplus
extern "C" {
#endif
/** Checks a NID value, returns the fixed NAC, DUID and also an indication if it failed to decode the NID.
*
* \param bch_code Input. An array to the 63 bytes, each containing one bit of the NID.
* \param new_nac Output. An address where to store the calculated NAC value after error correction. Should
* be large enough to accommodate for an integer.
* \param new_duid Output. An address where to store the calculated DUID value after error correction. Should
* be able to accommodate 3 chars.
* \param parity Input. The parity value read.
* \return 0 if there were errors processing the NID.
*/
int check_NID(char* bch_code, int* new_nac, char* new_duid, unsigned char parity);
#ifdef __cplusplus
}
#endif
#endif // __CHECK_NID_H__