mirror of https://github.com/lwvmobile/dsd-fme.git
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:
parent
9b9cb78ddf
commit
d7b36f32c0
109
check_nid.cpp
109
check_nid.cpp
|
|
@ -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;
|
||||
}
|
||||
14
check_nid.h
14
check_nid.h
|
|
@ -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
1
dsd.h
|
|
@ -171,6 +171,7 @@ typedef struct
|
|||
|
||||
unsigned int debug_audio_errors;
|
||||
unsigned int debug_header_errors;
|
||||
unsigned int debug_header_critical_errors;
|
||||
|
||||
} dsd_state;
|
||||
|
||||
|
|
|
|||
29
dsd_frame.c
29
dsd_frame.c
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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__
|
||||
Loading…
Reference in New Issue