Files
dsd-fme/src/bptc.c
2023-01-21 05:43:42 -05:00

583 lines
15 KiB
C

/*
============================================================================
Name : bptc.c
Author : MotoTRBO_Encrypted_DSD_Author
Version : 1.0
Date : 2017 - December - 11
Copyright : None
Description : BPTC library source
============================================================================
*/
/* Include ------------------------------------------------------------------*/
#include "dsd.h"
/* Define -------------------------------------------------------------------*/
/* Global variables ---------------------------------------------------------*/
const uint8_t BPTCInterleavingIndex[196] =
{
0, 181, 166, 151,
136, 121, 106, 91,
76, 61, 46, 31,
16, 1, 182, 167,
152, 137, 122, 107,
92, 77, 62, 47,
32, 17, 2, 183,
168, 153, 138, 123,
108, 93, 78, 63,
48, 33, 18, 3,
184, 169, 154, 139,
124, 109, 94, 79,
64, 49, 34, 19,
4, 185, 170, 155,
140, 125, 110, 95,
80, 65, 50, 35,
20, 5, 186, 171,
156, 141, 126, 111,
96, 81, 66, 51,
36, 21, 6, 187,
172, 157, 142, 127,
112, 97, 82, 67,
52, 37, 22, 7,
188, 173, 158, 143,
128, 113, 98, 83,
68, 53, 38, 23,
8, 189, 174, 159,
144, 129, 114, 99,
84, 69, 54, 39,
24, 9, 190, 175,
160, 145, 130, 115,
100, 85, 70, 55,
40, 25, 10, 191,
176, 161, 146, 131,
116, 101, 86, 71,
56, 41, 26, 11,
192, 177, 162, 147,
132, 117, 102, 87,
72, 57, 42, 27,
12, 193, 178, 163,
148, 133, 118, 103,
88, 73, 58, 43,
28, 13, 194, 179,
164, 149, 134, 119,
104, 89, 74, 59,
44, 29, 14, 195,
180, 165, 150, 135,
120, 105, 90, 75,
60, 45, 30, 15
};
const uint8_t BPTCDeInterleavingIndex[196] =
{
0, 13, 26, 39,
52, 65, 78, 91,
104, 117, 130, 143,
156, 169, 182, 195,
12, 25, 38, 51,
64, 77, 90, 103,
116, 129, 142, 155,
168, 181, 194, 11,
24, 37, 50, 63,
76, 89, 102, 115,
128, 141, 154, 167,
180, 193, 10, 23,
36, 49, 62, 75,
88, 101, 114, 127,
140, 153, 166, 179,
192, 9, 22, 35,
48, 61, 74, 87,
100, 113, 126, 139,
152, 165, 178, 191,
8, 21, 34, 47,
60, 73, 86, 99,
112, 125, 138, 151,
164, 177, 190, 7,
20, 33, 46, 59,
72, 85, 98, 111,
124, 137, 150, 163,
176, 189, 6, 19,
32, 45, 58, 71,
84, 97, 110, 123,
136, 149, 162, 175,
188, 5, 18, 31,
44, 57, 70, 83,
96, 109, 122, 135,
148, 161, 174, 187,
4, 17, 30, 43,
56, 69, 82, 95,
108, 121, 134, 147,
160, 173, 186, 3,
16, 29, 42, 55,
68, 81, 94, 107,
120, 133, 146, 159,
172, 185, 2, 15,
28, 41, 54, 67,
80, 93, 106, 119,
132, 145, 158, 171,
184, 1, 14, 27,
40, 53, 66, 79,
92, 105, 118, 131,
144, 157, 170, 183
};
const uint8_t DeInterleaveReverseChannelBptc[32] =
{
0, 17, 2, 19, 4, 21, 6, 23,
8, 25, 10, 27, 12, 29, 14, 31,
16, 1, 18, 3, 20, 5, 22, 7,
24, 9, 26, 11, 28, 13, 30, 15
};
const uint8_t DeInterleaveReverseChannelBptcPlacement[32] =
{
0, 16, 1, 17, 2, 18, 3, 19,
4, 20, 5, 21, 6, 22, 7, 23,
8, 24, 9, 25, 10, 26, 11, 27,
12, 28, 13, 29, 14, 30, 15, 31
};
/* Functions ----------------------------------------------------------------*/
/*
* @brief : This function deinterleave the DMR data by using BPTC (196,96)
*
* @param Input : Pointer of DMR input data interleaved (196 bytes)
*
* @param Output : Pointer where DMR deinterleaved data will be written (196 bytes)
*
* @return None
*/
void BPTCDeInterleaveDMRData(uint8_t * Input, uint8_t * Output)
{
uint32_t i, DeInterleaveIndex;
for(i = 0; i < 196; i++)
{
DeInterleaveIndex = BPTCDeInterleavingIndex[i];
Output[DeInterleaveIndex] = (Input[i] & 1);
}
} /* End BPTCDeInterleaveDMRData() */
/*
* @brief : This function extract the 96 bits of a deinteleaved 196 bits
* buffer using BPTC (196,96)
*
* @param InputDeInteleavedData : Pointer of DMR input data deinterleaved (196 bytes)
*
* @param DMRDataExtracted : Pointer where the DMR data will be written (96 bytes)
*
* @return The total number of irrecoverable Hamming check errors
*/
uint32_t BPTC_196x96_Extract_Data(uint8_t InputDeInteleavedData[196], uint8_t DMRDataExtracted[96], uint8_t R[3])
{
uint32_t i, j, k;
uint8_t DataMatrix[13][15];
uint8_t LineUncorrected[15];
uint8_t LineCorrected[11];
uint8_t ColumnUncorrected[13];
uint8_t ColumnCorrected[9];
uint32_t HammingIrrecoverableErrorNb = 0;
/* First step : Reconstitute the BPTC 15x11 matrix
* Note : Input data shall be deinterleaved */
k = 1; /* Discard R(3) bit - See DMR standard chapter B1.1 BPTC (196,96) */
for(i = 0; i < 13; i++)
{
for(j = 0; j < 15; j++)
{
/* Only the LSBit of the byte is stored */
DataMatrix[i][j] = (InputDeInteleavedData[k] & 1);
k++;
}
}
/* Set to 0 R(0) to R(2) - See DMR standard chapter B1.1 BPTC (196,96) */
// DataMatrix[0][0] = 0; /* R(2) */
// DataMatrix[0][1] = 0; /* R(1) */
// DataMatrix[0][2] = 0; /* R(0) */
/* Init the Hamming (15,11,3) library
* Not needed because it has already been done
* in the "InitAllFecFunction()" function */
//Hamming_15_11_init();
/* Init the Hamming (13,9,3) library
* Not needed because it has already been done
* in the "InitAllFecFunction()" function */
//Hamming_13_9_init();
/* Init the Hamming error counter */
HammingIrrecoverableErrorNb = 0;
/* Process the the Hamming (15,11,3) code
* check on each line (first time).
* Do not check the 4th last lines */
for(i = 0; i < 9; i++)
{
/* Get a full line */
for(j = 0; j < 15; j++)
{
LineUncorrected[j] = DataMatrix[i][j];
}
/* Apply Hamming (15,11,3) code correction */
if(Hamming_15_11_decode(LineUncorrected, LineCorrected, 1) == false)
{
HammingIrrecoverableErrorNb++;
}
/* Re-inject the line in the matrix (only the util data [11 bit],
* not the Hamming part [4 bit]) */
for(j = 0; j < 11; j++)
{
DataMatrix[i][j] = LineCorrected[j];
}
}
/* Process the the Hamming (15,11,3) code
* check on each column/row (first time) */
for(i = 0; i < 15; i++)
{
/* Get a full column */
for(j = 0; j < 13; j++)
{
ColumnUncorrected[j] = DataMatrix[j][i];
}
/* Apply Hamming (15,11,3) code correction */
if(Hamming_13_9_decode(ColumnUncorrected, ColumnCorrected, 1) == false)
{
HammingIrrecoverableErrorNb++;
}
/* Re-inject the column in the matrix (only the util data [11 bit],
* not the Hamming part [4 bit]) */
for(j = 0; j < 9; j++)
{
DataMatrix[j][i] = ColumnCorrected[j];
}
}
/* The first Hamming code check has maybe corrected bit
* witch can be use to correct other bit, so make the
* same operation twice */
/* Reset the number of irrecoverable errors */
HammingIrrecoverableErrorNb = 0;
/* Process the the Hamming (15,11,3) code
* check on each line (second time).
* Do not check the 4th last lines */
for(i = 0; i < 9; i++)
{
/* Get a full line */
for(j = 0; j < 15; j++)
{
LineUncorrected[j] = DataMatrix[i][j];
}
/* Apply Hamming (15,11,3) code correction */
if(Hamming_15_11_decode(LineUncorrected, LineCorrected, 1) == false)
{
/* Row/Line contains irrecoverable errors */
HammingIrrecoverableErrorNb++;
}
else
{
/* Row/Line contains correct data */
}
/* Re-inject the line in the matrix (only the util data [11 bit],
* not the Hamming part [4 bit]) */
for(j = 0; j < 11; j++)
{
DataMatrix[i][j] = LineCorrected[j];
}
}
/* Process the the Hamming (15,11,3) code
* check on each column/row (second time) */
for(i = 0; i < 15; i++)
{
/* Get a full column */
for(j = 0; j < 13; j++)
{
ColumnUncorrected[j] = DataMatrix[j][i];
}
/* Apply Hamming (15,11,3) code correction */
if(Hamming_13_9_decode(ColumnUncorrected, ColumnCorrected, 1) == false)
{
/* Row/Line contains irrecoverable errors */
HammingIrrecoverableErrorNb++;
}
else
{
/* Row/Line contains correct data */
}
/* Re-inject the column in the matrix (only the util data [11 bit],
* not the Hamming part [4 bit]) */
for(j = 0; j < 9; j++)
{
DataMatrix[j][i] = ColumnCorrected[j];
}
}
/* Extract the DMR data (96 bit) from the matrix */
/* First line : Do not take R(2), R(1) and R(0) */
k = 0;
for(i = 3; i < 11; i++)
{
DMRDataExtracted[k] = DataMatrix[0][i];
k++;
}
/* Next lines */
for(i = 1; i < 9; i++)
{
for(j = 0; j < 11; j++)
{
DMRDataExtracted[k] = DataMatrix[i][j];
k++;
}
}
/* R(0) to R(2) may be used to transport some
* Restricted Access System (RAS) information,
* So save these three bits after hamming correction
* See patent US 2013/0288643 A1 */
R[0] = DataMatrix[0][2]; /* Save R(0) */
R[1] = DataMatrix[0][1]; /* Save R(1) */
R[2] = DataMatrix[0][0]; /* Save R(2) */
/* Return the number of irrecoverable Hamming errors */
return HammingIrrecoverableErrorNb;
} /* End BPTC_196x96_Extract_Data() */
/*
* @brief : This function extract the 77 bits of a deinteleaved 128 bits
* buffer using BPTC (128,77).
*
* @note : See DMR standard ETSI TS 102 361-1 chapter B.2.1 for details
*
* @param InputDeInteleavedData : Pointer of DMR input data deinterleaved (128 bytes
act as a 16 x 8 byte data matrix)
*
* @param DMRDataExtracted : Pointer where the DMR data will be written (77 bytes)
* DMRDataExtracted[0..71] = Util data (hamming corrected)
* DMRDataExtracted[72..76] = 5 bit of CRC extracted (to be checked)
*
* @return 0 = All is OK
* Other = Error - Irrecoverable Hamming parity check error number
*/
uint32_t BPTC_128x77_Extract_Data(uint8_t InputDataMatrix[8][16], uint8_t DMRDataExtracted[77])
{
uint32_t i, j, k;
uint8_t DataMatrix[8][16];
uint8_t LineUncorrected[16];
uint8_t LineCorrected[11];
uint32_t HammingIrrecoverableErrorNb = 0;
uint32_t ParityCheckErrorNb = 0;
uint32_t NbOfOne;
/* First step : Reconstitute the BPTC 16x8 matrix */
for(i = 0; i < 8; i++)
{
for(j = 0; j < 16; j++)
{
/* Only the LSBit of the byte is stored */
DataMatrix[i][j] = (InputDataMatrix[i][j] & 1);
}
}
/* Init the Hamming (16,11,4) library
* Not needed because it has already been done
* in the "InitAllFecFunction()" function */
//Hamming_16_11_4_init();
/* Process the the Hamming (16,11,4) code
* check on each line.
* Do not check the last line (line nb 8) */
for(i = 0; i < 7; i++)
{
/* Get a full line */
for(j = 0; j < 16; j++)
{
LineUncorrected[j] = DataMatrix[i][j];
}
/* Apply Hamming (16,11,4) code correction */
if(Hamming_16_11_4_decode(LineUncorrected, LineCorrected, 1) == false)
{
HammingIrrecoverableErrorNb++;
}
/* Re-inject the line in the matrix (only the util data [11 bit],
* not the Hamming part [4 bit]) */
for(j = 0; j < 11; j++)
{
DataMatrix[i][j] = LineCorrected[j];
}
}
/* Extract the DMR data (77 bit) from the matrix */
k = 0;
/* 2 first lines */
for(i = 0; i < 2; i++)
{
for(j = 0; j < 11; j++)
{
DMRDataExtracted[k] = DataMatrix[i][j];
k++;
}
}
/* 5 Next lines */
for(i = 2; i < 7; i++)
{
for(j = 0; j < 10; j++)
{
DMRDataExtracted[k] = DataMatrix[i][j];
k++;
}
}
/* 5 bit of CRC */
for(i = 2; i < 7; i++)
{
DMRDataExtracted[k] = DataMatrix[i][10];
k++;
}
/* Verify the data integrity by checking
* all column parity bit */
ParityCheckErrorNb = 0;
for(i = 0; i < 16; i++)
{
NbOfOne = 0;
/* Get a full column */
for(j = 0; j < 7; j++)
{
NbOfOne += DataMatrix[j][i];
}
/* Check the parity bit (number of "1"
* must be even) */
if((NbOfOne % 2) != DataMatrix[7][i])
{
ParityCheckErrorNb++;
}
}
/* Return the number of irrecoverable Hamming errors +
* the number of parity check error */
return (HammingIrrecoverableErrorNb + ParityCheckErrorNb);
} /* End BPTC_128x77_Extract_Data() */
/*
* @brief : This function extract the 32 bits of a deinteleaved 32 bits
* buffer using Reverse Channel Single Burst BPTC.
*
* @note : See DMR standard ETSI TS 102 361-1 chapter B.2.2.2 for details
*
* @param InputInterleavedData : Pointer of DMR input data interleaved (32 bytes
act as a 16 x 2 bits data matrix)
*
* @param DMRDataExtracted : Pointer where the DMR data will be written (77 bytes)
* DMRDataExtracted[0..10] = Util data (Hamming corrected)
* DMRDataExtracted[11..15] = Hamming data
* DMRDataExtracted[16..31] = 16 bits of odd parity (to be checked)
*
* @param ParityCheckTypeOdd : 0 = Parity to check is even (used in Non-Reverse Channel Single Burst BPTC)
* 1 = Parity to check is odd (used in Reverse Channel Single Burst BPTC)
*
* @return 0 = All is OK
* Other = Error - Irrecoverable Hamming parity check error number
*/
uint32_t BPTC_16x2_Extract_Data(uint8_t InputInterleavedData[32], uint8_t DMRDataExtracted[32], uint32_t ParityCheckTypeOdd)
{
uint32_t i;
uint8_t DataMatrix[32];
uint8_t LineUncorrected[16];
uint8_t LineCorrected[11];
uint32_t HammingIrrecoverableErrorNb = 0;
uint32_t ParityCheckOddErrorNb = 0;
uint32_t ParityCheckEvenErrorNb = 0;
//TODO: make this so we can load either rc interleave, or single burst interleave
for(i = 0; i < 32; i++)
{
DataMatrix[DeInterleaveReverseChannelBptcPlacement[DeInterleaveReverseChannelBptc[i]]] = InputInterleavedData[i] & 1;
}
/* Copy the entire input buffer to the output buffer */
for(i = 0; i < 32; i++)
{
DMRDataExtracted[i] = DataMatrix[i] & 1;
}
/* Prepare the line to be corrected */
for(i = 0; i < 16; i++)
{
LineUncorrected[i] = DataMatrix[i] & 1;
}
/* Apply Hamming (16,11,4) code correction */
if(Hamming_16_11_4_decode(LineUncorrected, LineCorrected, 1) == false)
{
HammingIrrecoverableErrorNb++;
}
/* Copy the corrected content to the output buffer */
for(i = 0; i < 11; i++)
{
DMRDataExtracted[i] = LineCorrected[i] & 1;
}
/* Check Parity bits */
for(i = 0; i < 16; i++)
{
/* Odd parity ==> If data = 1 then parity = 0
* If data = 0 then parity = 1 */
if((DMRDataExtracted[i] & 1) == (DMRDataExtracted[i + 16] & 1)) ParityCheckOddErrorNb++;
if((DMRDataExtracted[i] & 1) != (DMRDataExtracted[i + 16] & 1)) ParityCheckEvenErrorNb++;
}
//fprintf(stderr, "Hamming ERR=%u ; Parity odd ERR=%u, Parity even ERR=%u, ", HammingIrrecoverableErrorNb, ParityCheckOddErrorNb, ParityCheckEvenErrorNb);
//fprintf(stderr, "Content =\n");
//for(i = 0; i < 32; i++)
//{
// fprintf(stderr, "%u", DMRDataExtracted[i] & 1);
// if((i == 15) || (i == 31)) fprintf(stderr, "\n");
// else fprintf(stderr, "-");
//}
/* Return the number of irrecoverable Hamming errors +
* the number of parity check error */
if(ParityCheckTypeOdd) return (HammingIrrecoverableErrorNb + ParityCheckOddErrorNb);
else return (HammingIrrecoverableErrorNb + ParityCheckEvenErrorNb);
} /* End BPTC_16x2_Extract_Data() */
/* End of file */