mirror of
https://github.com/lwvmobile/dsd-fme.git
synced 2026-11-12 16:57:23 -05:00
583 lines
15 KiB
C
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 */
|