diff --git a/openair1/PHY/CODING/TESTBENCH/polartest.c b/openair1/PHY/CODING/TESTBENCH/polartest.c new file mode 100644 index 0000000000..cdf99a06eb --- /dev/null +++ b/openair1/PHY/CODING/TESTBENCH/polartest.c @@ -0,0 +1,194 @@ +#include +#include +#include +#include +#include +#include +#include + +#include "PHY/CODING/nrPolar_tools/nr_polar_defs.h" +#include "PHY/CODING/nrPolar_tools/nr_polar_pbch_defs.h" +#include "SIMULATION/TOOLS/defs.h" + +int main(int argc, char *argv[]) { + + //Initiate timing. (Results depend on CPU Frequency. Therefore, might change due to performance variances during simulation.) + time_stats_t timeEncoder,timeDecoder; + opp_enabled=1; + cpu_freq_GHz = get_cpu_freq_GHz(); + reset_meas(&timeEncoder); + reset_meas(&timeDecoder); + + randominit(0); + //Default simulation values (Aim for iterations = 1000000.) + int itr, iterations = 1000, arguments, polarMessageType = 1; //0=DCI, 1=PBCH, 2=UCI + double SNRstart = -20.0, SNRstop = 20.0, SNRinc= 0.5; //dB + + double SNR, SNR_lin; + int16_t nBitError = 0; // -1 = Decoding failed (All list entries have failed the CRC checks). + int8_t decoderState=0, blockErrorState=0; //0 = Success, -1 = Decoding failed, 1 = Block Error. + uint16_t testLength, coderLength, blockErrorCumulative=0, bitErrorCumulative=0; + double timeEncoderCumulative = 0, timeDecoderCumulative = 0; + + uint8_t decoderListSize = 8, pathMetricAppr = 0; //0 --> eq. (8a) and (11b), 1 --> eq. (9) and (12) + + while ((arguments = getopt (argc, argv, "s:d:f:m:i:l:a:")) != -1) + switch (arguments) + { + case 's': + SNRstart = atof(optarg); + printf("SNRstart = %f\n", SNRstart); + break; + + case 'd': + SNRinc = atof(optarg); + break; + + case 'f': + SNRstop = atof(optarg); + break; + + case 'm': + polarMessageType = atoi(optarg); + break; + + case 'i': + iterations = atoi(optarg); + break; + + case 'l': + decoderListSize = (uint8_t) atoi(optarg); + break; + + case 'a': + pathMetricAppr = (uint8_t) atoi(optarg); + break; + + default: + perror("[polartest.c] Problem at argument parsing with getopt"); + abort (); + } + + if (polarMessageType == 0) { //DCI + //testLength = ; + //coderLength = ; + } else if (polarMessageType == 1) { //PBCH + testLength = NR_POLAR_PBCH_PAYLOAD_BITS; + coderLength = NR_POLAR_PBCH_E; + } else if (polarMessageType == 2) { //UCI + //testLength = ; + //coderLength = ; + } + + //Logging + time_t currentTime; + time (¤tTime); + char fileName[512], currentTimeInfo[25]; + + sprintf(fileName,"./polartestResults/_ListSize_%d_pmAppr_%d_Payload_%d_Itr_%d",decoderListSize,pathMetricAppr,testLength,iterations); + strftime(currentTimeInfo, 25, "_%Y-%m-%d-%H-%M-%S.csv", localtime(¤tTime)); + strcat(fileName,currentTimeInfo); + + //Create "./polartestResults" folder if it doesn't already exist. + struct stat folder = {0}; + if (stat("./polartestResults", &folder) == -1) mkdir("./polartestResults", S_IRWXU | S_IRWXO); + + FILE* logFile; + logFile = fopen(fileName, "w"); + if (logFile==NULL) { + fprintf(stderr,"[polartest.c] Problem creating file %s with fopen\n",fileName); + exit(-1); + } + fprintf(logFile,",SNR,nBitError,blockErrorState,t_encoder[us],t_decoder[us]\n"); + + uint8_t *testInput = malloc(sizeof(uint8_t) * testLength); //generate randomly + uint8_t *encoderOutput = malloc(sizeof(uint8_t) * coderLength); + double *modulatedInput = malloc (sizeof(double) * coderLength); //channel input + + double *channelOutput = malloc (sizeof(double) * coderLength); //add noise + uint8_t *estimatedOutput = malloc(sizeof(uint8_t) * testLength); //decoder output + + t_nrPolar_params nrPolar_params; + nr_polar_init(&nrPolar_params, polarMessageType); + + // We assume no a priori knowledge available about the payload. + double aPrioriArray[nrPolar_params.payloadBits]; + for (int i=0; i0) blockErrorState=1; + } + + //Iteration times are in microseconds. + timeEncoderCumulative+=(timeEncoder.diff_now/(cpu_freq_GHz*1000.0)); + timeDecoderCumulative+=(timeDecoder.diff_now/(cpu_freq_GHz*1000.0)); + fprintf(logFile,",%f,%d,%d,%f,%f\n", SNR, nBitError, blockErrorState, + (timeEncoder.diff_now/(cpu_freq_GHz*1000.0)), (timeDecoder.diff_now/(cpu_freq_GHz*1000.0))); + + if (nBitError<0) { + blockErrorCumulative++; + bitErrorCumulative+=testLength; + } else { + blockErrorCumulative+=blockErrorState; + bitErrorCumulative+=nBitError; + } + + decoderState=0; + nBitError=0; + blockErrorState=0; + + } + //Calculate error statistics for the SNR. + printf("[ListSize=%d, Appr=%d] SNR=%+8.3f, BLER=%9.6f, BER=%12.9f, t_Encoder=%9.3fus, t_Decoder=%9.3fus\n", + decoderListSize, pathMetricAppr, SNR, ((double)blockErrorCumulative/iterations), + ((double)bitErrorCumulative / (iterations*testLength)), + (timeEncoderCumulative/iterations),timeDecoderCumulative/iterations); + + blockErrorCumulative = 0; bitErrorCumulative = 0; + timeEncoderCumulative = 0; timeDecoderCumulative = 0; + } + + print_meas(&timeEncoder,"polar_encoder",NULL,NULL); + print_meas(&timeDecoder,"polar_decoder",NULL,NULL); + + fclose(logFile); + free(testInput); + free(encoderOutput); + free(modulatedInput); + free(channelOutput); + free(estimatedOutput); + + return (0); +} diff --git a/openair1/PHY/CODING/nrPolar_init.c b/openair1/PHY/CODING/nrPolar_init.c new file mode 100644 index 0000000000..cf788bae22 --- /dev/null +++ b/openair1/PHY/CODING/nrPolar_init.c @@ -0,0 +1,54 @@ +#include "nrPolar_tools/nr_polar_defs.h" +#include "nrPolar_tools/nr_polar_pbch_defs.h" + +void nr_polar_init(t_nrPolar_params* polarParams, int messageType) { + + if (messageType == 0) { //DCI + + } else if (messageType == 1) { //PBCH + polarParams->n_max = NR_POLAR_PBCH_N_MAX; + polarParams->i_il = NR_POLAR_PBCH_I_IL; + polarParams->n_pc = NR_POLAR_PBCH_N_PC; + polarParams->n_pc_wm = NR_POLAR_PBCH_N_PC_WM; + polarParams->i_bil = NR_POLAR_PBCH_I_BIL; + polarParams->payloadBits = NR_POLAR_PBCH_PAYLOAD_BITS; + polarParams->encoderLength = NR_POLAR_PBCH_E; + polarParams->crcParityBits = NR_POLAR_PBCH_CRC_PARITY_BITS; + polarParams->crcCorrectionBits = NR_POLAR_PBCH_CRC_ERROR_CORRECTION_BITS; + + polarParams->K = polarParams->payloadBits + polarParams->crcParityBits; // Number of bits to encode. + polarParams->N = nr_polar_output_length(polarParams->K, polarParams->encoderLength, polarParams->n_max); + polarParams->n = log2(polarParams->N); + + polarParams->crc_generator_matrix=crc24c_generator_matrix(polarParams->payloadBits); + polarParams->G_N = nr_polar_kronecker_power_matrices(polarParams->n); + } else if (messageType == 2) { //UCI + + } + + polarParams->Q_0_Nminus1 = nr_polar_sequence_pattern(polarParams->n); + + polarParams->interleaving_pattern = (uint16_t *)malloc(sizeof(uint16_t) * polarParams->K); + nr_polar_interleaving_pattern(polarParams->K, polarParams->i_il, polarParams->interleaving_pattern); + + polarParams->rate_matching_pattern = (uint16_t *)malloc(sizeof(uint16_t) * polarParams->encoderLength); + uint16_t *J = malloc(sizeof(uint16_t) * polarParams->N); + nr_polar_rate_matching_pattern(polarParams->rate_matching_pattern, J, nr_polar_subblock_interleaver_pattern, + polarParams->K, polarParams->N, polarParams->encoderLength); + + + polarParams->information_bit_pattern = malloc(sizeof(uint8_t) * polarParams->N); + polarParams->Q_I_N = malloc(sizeof(int16_t) * (polarParams->K + polarParams->n_pc)); + polarParams->Q_F_N = malloc(sizeof(int16_t) * (polarParams->N+1)); // Last element shows the final array index assigned a value. + polarParams->Q_PC_N = malloc(sizeof(int16_t) * (polarParams->n_pc)); + for (int i=0; i<=polarParams->N; i++) polarParams->Q_F_N[i] = -1; // Empty array. + nr_polar_info_bit_pattern(polarParams->information_bit_pattern, + polarParams->Q_I_N, polarParams->Q_F_N, J, polarParams->Q_0_Nminus1, + polarParams->K, polarParams->N, polarParams->encoderLength, polarParams->n_pc); + + polarParams->channel_interleaver_pattern = malloc(sizeof(uint16_t) * polarParams->encoderLength); + nr_polar_channel_interleaver_pattern(polarParams->channel_interleaver_pattern, + polarParams->i_bil, polarParams->encoderLength); + + free(J); +} diff --git a/openair1/PHY/CODING/nrPolar_tools/.gitkeep b/openair1/PHY/CODING/nrPolar_tools/.gitkeep new file mode 100644 index 0000000000..e69de29bb2 diff --git a/openair1/PHY/CODING/nrPolar_tools/get_3GPP_info_bit_pattern.c b/openair1/PHY/CODING/nrPolar_tools/get_3GPP_info_bit_pattern.c new file mode 100644 index 0000000000..0e20b2c8f9 --- /dev/null +++ b/openair1/PHY/CODING/nrPolar_tools/get_3GPP_info_bit_pattern.c @@ -0,0 +1,200 @@ +#include +#include +#include +#include + +void get_3GPP_info_bit_pattern(uint16_t K, uint16_t n_PC, uint16_t Q_N_length, uint8_t E_r, uint8_t* P, uint16_t* Q_N, uint8_t** info_bit_pattern) +{ +// GET_3GPP_INFO_BIT_PATTERN Obtain the 3GPP information bit pattern, +// according to Section 5.4.1.1 of 3GPP TS 38.212 +// +// I should be an integer scalar. It specifies the number of bits in the +// information, CRC and PC bit sequence. It should be no greater than N or E. +// +// Q_N should be a row vector comprising N number of unique integers in the +// range 1 to N. Each successive element of Q_N provides the index of the +// next most reliable input to the polar encoder kernal, where the first +// element of Q_N gives the index of the least reliable bit and the last +// element gives the index of the most reliable bit. +// +// rate_matching_pattern should be a vector comprising E_r number of +// integers, each having a value in the range 1 to N. Each integer +// identifies which one of the N outputs from the polar encoder kernal +// provides the corresponding bit in the encoded bit sequence e. +// +// mode should have the value 'repetition', 'puncturing' or 'shortening'. +// This specifies how the rate matching has been achieved. 'repetition' +// indicates that some outputs of the polar encoder kernal are repeated in +// the encoded bit sequence two or more times. 'puncturing' and +// 'shortening' indicate that some outputs of the polar encoder kernal +// have been excluded from the encoded bit sequence. In the case of +// 'puncturing' these excluded bits could have values of 0 or 1. In the +// case of 'shortening' these excluded bits are guaranteed to have values +// of 0. +// +// info_bit_pattern will be a vector comprising N number of logical +// elements, each having the value true or false. The number of elements +// in info_bit_pattern having the value true will be I. These elements +// having the value true identify the positions of the information and +// CRC bits within the input to the polar encoder kernal. The +// information bit arrangement can be achieved according to +// u(info_bit_pattern) = a. + +int I=K+n_PC; + + if (I > Q_N_length) //I=K+n_PC + { + fprintf(stderr, "I=K+n_PC should be no greater than N."); + exit(-1); + } + if (I > E_r) + { + fprintf(stderr, "I=K+n_PC should be no greater than E."); + exit(-1); + } + + //This is how the rate matching is described in TS 38.212 + int J[Q_N_length]; + int i,j; + for (j=0; j= (double)3*Q_N_length/4) + { + //Q_Ftmp_N = [Q_Ftmp_N,0:ceil(3*N/4-E/2)-1]; + Q_Ftmp_N_length = Q_Ftmp_N_length + ceil(3*Q_N_length/4-(double)E_r/2); + } else + { + //Q_Ftmp_N = [Q_Ftmp_N,0:ceil(9*N/16-E/4)-1]; + Q_Ftmp_N_length = Q_Ftmp_N_length + ceil(9*Q_N_length/16-(double)E_r/4); + } + } + } + + int* Q_Ftmp_N = (int *)malloc(sizeof(int)*Q_Ftmp_N_length); + if (Q_Ftmp_N == NULL) + { + fprintf(stderr, "malloc failed\n"); + exit(-1); + } + if (E_r < Q_N_length) + { + if ((double)I/E_r <= 7/16) // puncturing + { + for (j=0; j= 3*Q_N_length/4) + { + for (j=0; j +#include +#include +#include + +void get_PC_bit_pattern(uint16_t Q_N_length, uint16_t n_PC, uint8_t n_PC_wm, uint16_t* Q_N, uint8_t* info_bit_pattern, uint8_t** PC_bit_pattern) +{ +// GET_PC_BIT_PATTERN Obtain the Parity Check (PC) bit pattern, +// according to Section 5.3.1.2 of 3GPP TS 38.212 +// +// info_bit_pattern should be a vector comprising N number of logical +// elements, each having the value true or false. The number of elements +// in info_bit_pattern having the value true should be I, where +// I = A+P+n_PC. These elements having the value true identify the +// positions of the information, CRC and PC bits within the input to the +// polar encoder kernal. +// +// Q_N should be a row vector comprising N number of unique integers in the +// range 1 to N. Each successive element of Q_N provides the index of the +// next most reliable input to the polar encoder kernal, where the first +// element of Q_N gives the index of the least reliable bit and the last +// element gives the index of the most reliable bit. +// +// n_PC should be an integer scalar. It specifies the number of PC bits to +// use, where n_PC should be no greater than I. +// +// n_PC_wm should be an integer scalar. It specifies the number of PC bits +// that occupy some of the most reliable positions at the input to the +// polar encoder kernal. The remaining n_PC-n_PC_wm PC bits occupy some of +// the least reliable positions at the input to the polar encoder kernal. +// n_PC_wm should be no greater than n_PC. +// +// PC_bit_pattern will be a vector comprising N number of logical +// elements, each having the value true or false. The number of elements +// in PC_bit_pattern having the value true will be n_PC. +// These elements having the value true identify the positions of the +// PC bits within the input to the polar encoder kernal. + + //N = length(info_bit_pattern); -> Q_N_length + //I = sum(info_bit_pattern); + int totInfoBit =0; + int j,i; + for (j=0; j totInfoBit) + { + fprintf(stderr, "n_PC should be no greater than totInfoBit."); + exit(-1); + } + + if (n_PC_wm > n_PC) + { + fprintf(stderr, "n_PC_wm should be no greater than n_PC."); + exit(-1); + } + //Q_I = 1:N; + int* Q_I = (int*) malloc(sizeof(int)*Q_N_length); + if (Q_I == NULL) + { + fprintf(stderr, "malloc failed\n"); + exit(-1); + } + for (j=0; j w_g_sorted[j+1]) //then swap + { + tempToSwap = w_g_sorted[j]; + w_g_sorted[j] = w_g_sorted[j+1]; + w_g_sorted[j+1] = tempToSwap; + + tempToSwap = indices[j]; + indices[j] = indices[j+1]; + indices[j+1] = tempToSwap; + } + } + } + free(w_g_sorted); + + //Q_N_PC = [Q_N_I(1:n_PC-n_PC_wm), Q_tilde_N_I_flip(indices(1:n_PC_wm))]; + int* Q_N_PC = (int*) malloc(sizeof(int)*(n_PC)); + if (Q_N_PC == NULL) + { + fprintf(stderr, "malloc failed\n"); + exit(-1); + } + + for (i=0; i +#include +#include +#include + +void get_crc_generator_matrix(uint8_t A, uint8_t P, uint8_t* crc_polynomial_pattern, uint8_t*** G_P) +{ +// GET_CRC_GENERATOR_MATRIX Obtain a Cyclic Redudancy Check (CRC) generator +// matrix. +// +// A should be an integer scalar. It specifies the number of bits in the +// information bit sequence. +// +// crc_polynomial_pattern should be a binary row vector comprising P+1 +// number of bits, each having the value 0 or 1. These bits parameterise a +// Cyclic Redundancy Check (CRC) comprising P bits. Each bit provides the +// coefficient of the corresponding element in the CRC generator +// polynomial. From left to right, the bits provide the coefficients for +// the elements D^P, D^P-1, D^P-2, ..., D^2, D, 1. +// +// G_P will be a K by P binary matrix. The CRC bits can be generated +// according to mod(a*G_P,2). + + *G_P = (uint8_t **)malloc(A * sizeof(uint8_t *)); + if (*G_P == NULL) + { + fprintf(stderr, "malloc failed\n"); + exit(-1); + } + int i,j; + for (i=0; i0) + { + //G_P(end,:) = crc_polynomial_pattern(2:end); + for(i=0; i-1; j--) + { + for(i=0; i +#include +#include + +#include "nr_polar_defs.h" +#include "nr_polar_pucch_defs.h" + +void PUCCH_encoder(uint8_t a[], uint8_t A, uint8_t G, uint16_t* E_r, uint8_t** f); + +int main() +{ + uint16_t E_r; + uint8_t* f; + uint8_t A=32; //16, 32, 64, 128, 256, 512, 1024 Payload length + uint8_t G = 54; //, 108, 216, 432, 864, 1728, 3456, 6912, 13824}; encoded block length + + uint8_t j; + + uint8_t* a = (uint8_t *)malloc(sizeof(uint8_t)*A); + if (a == NULL) + { + fprintf(stderr, "malloc failed\n"); + exit(-1); + } + + printf("DEBUG: Send "); + for (j=0; j>0 & 0x01); + bitArray[(6+(i*8))] = ( array[i]>>1 & 0x01); + bitArray[(5+(i*8))] = ( array[i]>>2 & 0x01); + bitArray[(4+(i*8))] = ( array[i]>>3 & 0x01); + bitArray[(3+(i*8))] = ( array[i]>>4 & 0x01); + bitArray[(2+(i*8))] = ( array[i]>>5 & 0x01); + bitArray[(1+(i*8))] = ( array[i]>>6 & 0x01); + bitArray[ (i*8) ] = ( array[i]>>7 & 0x01); + } + +} diff --git a/openair1/PHY/CODING/nrPolar_tools/nr_crc_byte.c b/openair1/PHY/CODING/nrPolar_tools/nr_crc_byte.c new file mode 100644 index 0000000000..abe918bc3f --- /dev/null +++ b/openair1/PHY/CODING/nrPolar_tools/nr_crc_byte.c @@ -0,0 +1,374 @@ +#include "PHY/CODING/nrPolar_tools/nr_polar_defs.h" + +/*ref 38-212 v15.0.0, pp 8-9 */ +/* the highest degree is set by default */ +unsigned int poly24a = 0x864cfb00; // 1000 0110 0100 1100 1111 1011 D^24 + D^23 + D^18 + D^17 + D^14 + D^11 + D^10 + D^7 + D^6 + D^5 + D^4 + D^3 + D + 1 +unsigned int poly24b = 0x80006300; // 1000 0000 0000 0000 0110 0011 D^24 + D^23 + D^6 + D^5 + D + 1 +unsigned int poly24c = 0xb2b11700; // 1011 0010 1011 0001 0001 0111 D^24 + D^23 + D^21 + D^20 + D^17 + D^15 + D^13 + D^12 + D^8 + D^4 + D^2 + D + 1 +unsigned int poly16 = 0x10210000; // 0001 0000 0010 0001 D^16 + D^12 + D^5 + 1 +unsigned int poly11 = 0xe2100000; // 1110 0010 0001 D^11 + D^10 + D^9 + D^5 + 1 +unsigned int poly6 = 0x61000000; // 0110 0001 D^6 + D^5 + 1 +/********************************************************* + +For initialization && verification purposes, + bit by bit implementation with any polynomial + +The first bit is in the MSB of each byte + +*********************************************************/ +unsigned int crcbit (unsigned char * inputptr, int octetlen, unsigned int poly) +{ + unsigned int i, crc = 0, c; + + while (octetlen-- > 0) { + c = (*inputptr++) << 24; + + for (i = 8; i != 0; i--) { + if ((1 << 31) & (c ^ crc)) + crc = (crc << 1) ^ poly; + else + crc <<= 1; + + c <<= 1; + } + } + + return crc; +} + +/********************************************************* + +crc table initialization + +*********************************************************/ +static unsigned int crc24aTable[256]; +static unsigned int crc24bTable[256]; +static unsigned int crc24cTable[256]; +static unsigned short crc16Table[256]; +static unsigned short crc11Table[256]; +static unsigned char crc6Table[256]; + +void crcTableInit (void) +{ + unsigned char c = 0; + + do { + crc24aTable[c] = crcbit (&c, 1, poly24a); + crc24bTable[c] = crcbit (&c, 1, poly24b); + crc24cTable[c] = crcbit (&c, 1, poly24c); + crc16Table[c] = (unsigned short) (crcbit (&c, 1, poly16) >> 16); + crc11Table[c] = (unsigned short) (crcbit (&c, 1, poly11) >> 16); + crc6Table[c] = (unsigned char) (crcbit (&c, 1, poly6) >> 24); + } while (++c); +} +/********************************************************* + +Byte by byte implementations, +assuming initial byte is 0 padded (in MSB) if necessary + +*********************************************************/ +unsigned int crc24a (unsigned char * inptr, int bitlen) +{ + + int octetlen, resbit; + unsigned int crc = 0; + octetlen = bitlen / 8; /* Change in octets */ + resbit = (bitlen % 8); + + while (octetlen-- > 0) { + // printf("in %x => crc %x\n",crc,*inptr); + crc = (crc << 8) ^ crc24aTable[(*inptr++) ^ (crc >> 24)]; + } + + if (resbit > 0) + crc = (crc << resbit) ^ crc24aTable[((*inptr) >> (8 - resbit)) ^ (crc >> (32 - resbit))]; + + return crc; +} + +unsigned int crc24b (unsigned char * inptr, int bitlen) +{ + + int octetlen, resbit; + unsigned int crc = 0; + octetlen = bitlen / 8; + resbit = (bitlen % 8); + + while (octetlen-- > 0) { + crc = (crc << 8) ^ crc24bTable[(*inptr++) ^ (crc >> 24)]; + } + + if (resbit > 0) + crc = (crc << resbit) ^ crc24bTable[((*inptr) >> (8 - resbit)) ^ (crc >> (32 - resbit))]; + + return crc; +} + +unsigned int crc24c (unsigned char * inptr, int bitlen) +{ + + int octetlen, resbit; + unsigned int crc = 0; + octetlen = bitlen / 8; + resbit = (bitlen % 8); + + while (octetlen-- > 0) { + crc = (crc << 8) ^ crc24cTable[(*inptr++) ^ (crc >> 24)]; + } + + if (resbit > 0) + crc = (crc << resbit) ^ crc24cTable[((*inptr) >> (8 - resbit)) ^ (crc >> (32 - resbit))]; + + return crc; +} + +unsigned int crc16 (unsigned char * inptr, int bitlen) +{ + int octetlen, resbit; + unsigned int crc = 0; + octetlen = bitlen / 8; /* Change in octets */ + resbit = (bitlen % 8); + + while (octetlen-- > 0) { + + crc = (crc << 8) ^ (crc16Table[(*inptr++) ^ (crc >> 24)] << 16); + } + + if (resbit > 0) + crc = (crc << resbit) ^ (crc16Table[((*inptr) >> (8 - resbit)) ^ (crc >> (32 - resbit))] << 16); + + return crc; +} + +unsigned int crc11 (unsigned char * inptr, int bitlen) +{ + int octetlen, resbit; + unsigned int crc = 0; + octetlen = bitlen / 8; /* Change in octets */ + resbit = (bitlen % 8); + + while (octetlen-- > 0) { + crc = (crc << 8) ^ (crc11Table[(*inptr++) ^ (crc >> 24)] << 16); + } + + if (resbit > 0) + crc = (crc << resbit) ^ (crc11Table[((*inptr) >> (8 - resbit)) ^ (crc >> (32 - resbit))] << 16); + + return crc; +} + +unsigned int crc6 (unsigned char * inptr, int bitlen) +{ + int octetlen, resbit; + unsigned int crc = 0; + octetlen = bitlen / 8; /* Change in octets */ + resbit = (bitlen % 8); + + while (octetlen-- > 0) { + crc = crc6Table[(*inptr++) ^ (crc >> 24)] << 24; + } + + if (resbit > 0) + crc = (crc << resbit) ^ (crc6Table[((*inptr) >> (8 - resbit)) ^ (crc >> (32 - resbit))] << 24); + + return crc; +} + +uint8_t check_crc(uint8_t *decoded_bytes, uint16_t len, uint8_t crc_type) +{ + uint8_t crc_len,temp; + uint16_t oldcrc,crc; + + switch (crc_type) { + + case 0: //CRC24_A: + case 1: //CRC24_B: + crc_len=3; + break; + + case 2: //CRC16: + crc_len=2; + break; + + case 3: //CRC8: + crc_len=1; + break; + + default: + crc_len=3; + } + + // check the CRC + oldcrc= *((unsigned int *)(&decoded_bytes[(len>>3)-crc_len])); + + switch (crc_type) { + + case 0: //CRC24_A: + oldcrc&=0x00ffffff; + crc = crc24a(decoded_bytes,len-24)>>8; + temp=((uint8_t *)&crc)[2]; + ((uint8_t *)&crc)[2] = ((uint8_t *)&crc)[0]; + ((uint8_t *)&crc)[0] = temp; + break; + + case 1: //CRC24_B: + oldcrc&=0x00ffffff; + crc = crc24b(decoded_bytes,len-24)>>8; + temp=((uint8_t *)&crc)[2]; + ((uint8_t *)&crc)[2] = ((uint8_t *)&crc)[0]; + ((uint8_t *)&crc)[0] = temp; + break; + + case 2: //CRC16: + oldcrc&=0x0000ffff; + crc = crc16(decoded_bytes,len-16)>>16; + break; + + case 3: //CRC8: + oldcrc&=0x000000ff; + crc = crc6(decoded_bytes,len-8)>>24; + break; + + default: + printf("FATAL: Unknown CRC\n"); + return(255); + break; + } + + printf("old CRC %x, CRC %x \n",oldcrc,crc); + return (crc == oldcrc); +} + +uint8_t **crc24c_generator_matrix(uint16_t payloadSizeBits){ + + uint8_t crcPolynomialPattern[25] = {1,1,0,1,1,0,0,1,0,1,0,1,1,0,0,0,1,0,0,0,1,0,1,1,1}; + // 1011 0010 1011 0001 0001 0111 D^24 + D^23 + D^21 + D^20 + D^17 + D^15 + D^13 + D^12 + D^8 + D^4 + D^2 + D + 1 + uint8_t crcPolynomialSize = 24;// 24 because crc24c + uint8_t temp1[crcPolynomialSize], temp2[crcPolynomialSize]; + + uint8_t **crc_generator_matrix = malloc(payloadSizeBits * sizeof(uint8_t *)); + if (crc_generator_matrix) + { + for (int i = 0; i < payloadSizeBits; i++) + { + crc_generator_matrix[i] = malloc(crcPolynomialSize * sizeof(uint8_t)); + } + } + + for (int i = 0; i < crcPolynomialSize; i++) crc_generator_matrix[payloadSizeBits-1][i]=crcPolynomialPattern[i+1]; + + for (int i = payloadSizeBits-2; i >= 0; i--){ + + for (int j = 0; j < crcPolynomialSize-1; j++) temp1[j]=crc_generator_matrix[i+1][j+1]; + temp1[crcPolynomialSize-1]=0; + + for (int j = 0; j < crcPolynomialSize; j++) temp2[j]=crc_generator_matrix[i+1][0]*crcPolynomialPattern[j+1]; + + for (int j = 0; j < crcPolynomialSize; j++){ + if(temp1[j]+temp2[j] == 1){ + crc_generator_matrix[i][j]=1; + } else { + crc_generator_matrix[i][j]=0; + } + } + + } + + return crc_generator_matrix; +} + +uint8_t **crc11_generator_matrix(uint16_t payloadSizeBits){ + + uint8_t crcPolynomialPattern[12] = {1,1,1,0,0,0,1,0,0,0,0,1}; + // 1110 0010 0001 D^11 + D^10 + D^9 + D^5 + 1 + uint8_t crcPolynomialSize = 11; + uint8_t temp1[crcPolynomialSize], temp2[crcPolynomialSize]; + + uint8_t **crc_generator_matrix = malloc(payloadSizeBits * sizeof(uint8_t *)); + if (crc_generator_matrix) + { + for (int i = 0; i < payloadSizeBits; i++) + { + crc_generator_matrix[i] = malloc(crcPolynomialSize * sizeof(uint8_t)); + } + } + + for (int i = 0; i < crcPolynomialSize; i++) crc_generator_matrix[payloadSizeBits-1][i]=crcPolynomialPattern[i+1]; + + for (int i = payloadSizeBits-2; i >= 0; i--){ + + for (int j = 0; j < crcPolynomialSize-1; j++) temp1[j]=crc_generator_matrix[i+1][j+1]; + temp1[crcPolynomialSize-1]=0; + + for (int j = 0; j < crcPolynomialSize; j++) temp2[j]=crc_generator_matrix[i+1][0]*crcPolynomialPattern[j+1]; + + for (int j = 0; j < crcPolynomialSize; j++){ + if(temp1[j]+temp2[j] == 1){ + crc_generator_matrix[i][j]=1; + } else { + crc_generator_matrix[i][j]=0; + } + } + + } + + return crc_generator_matrix; +} + +uint8_t **crc6_generator_matrix(uint16_t payloadSizeBits){ + + uint8_t crcPolynomialPattern[7] = {1,1,0,0,0,0,1}; + // 0110 0001 D^6 + D^5 + 1 + uint8_t crcPolynomialSize = 6; + uint8_t temp1[crcPolynomialSize], temp2[crcPolynomialSize]; + + uint8_t **crc_generator_matrix = malloc(payloadSizeBits * sizeof(uint8_t *)); + if (crc_generator_matrix) + { + for (int i = 0; i < payloadSizeBits; i++) + { + crc_generator_matrix[i] = malloc(crcPolynomialSize * sizeof(uint8_t)); + } + } + + for (int i = 0; i < crcPolynomialSize; i++) crc_generator_matrix[payloadSizeBits-1][i]=crcPolynomialPattern[i+1]; + + for (int i = payloadSizeBits-2; i >= 0; i--){ + + for (int j = 0; j < crcPolynomialSize-1; j++) temp1[j]=crc_generator_matrix[i+1][j+1]; + temp1[crcPolynomialSize-1]=0; + + for (int j = 0; j < crcPolynomialSize; j++) temp2[j]=crc_generator_matrix[i+1][0]*crcPolynomialPattern[j+1]; + + for (int j = 0; j < crcPolynomialSize; j++){ + if(temp1[j]+temp2[j] == 1){ + crc_generator_matrix[i][j]=1; + } else { + crc_generator_matrix[i][j]=0; + } + } + + } + + return crc_generator_matrix; +} + + +#ifdef DEBUG_CRC +/*******************************************************************/ +/** Test code +/*******************************************************************/ + +#include + +main() +{ + unsigned char test[] = "Thebigredfox"; + crcTableInit(); + printf("%x\n", crcbit(test, sizeof(test) - 1, poly24a)); + printf("%x\n", crc24a(test, (sizeof(test) - 1)*8)); + printf("%x\n", crcbit(test, sizeof(test) - 1, poly6)); + printf("%x\n", crc6(test, (sizeof(test) - 1)*8)); +} +#endif + diff --git a/openair1/PHY/CODING/nrPolar_tools/nr_polar_bit_insertion.c b/openair1/PHY/CODING/nrPolar_tools/nr_polar_bit_insertion.c new file mode 100644 index 0000000000..52fdf6ca46 --- /dev/null +++ b/openair1/PHY/CODING/nrPolar_tools/nr_polar_bit_insertion.c @@ -0,0 +1,31 @@ +#include "PHY/CODING/nrPolar_tools/nr_polar_defs.h" + +void nr_polar_bit_insertion(uint8_t *input, uint8_t *output, uint16_t N, uint16_t K, + uint16_t *Q_I_N, uint16_t *Q_PC_N, uint8_t n_PC){ + + uint16_t k=0; + uint8_t flag; + + if (n_PC>0) { + /* + * + */ + } else { + for (int n=0; n<=N-1; n++) { + flag=0; + for (int m=0; m<=(K+n_PC)-1; m++) { + if ( n == Q_I_N[m]) { + flag=1; + break; + } + } + if (flag) { // n ϵ Q_I_N + output[n]=input[k]; + k++; + } else { + output[n] = 0; + } + } + } + +} diff --git a/openair1/PHY/CODING/nrPolar_tools/nr_polar_bit_insertion_2.c b/openair1/PHY/CODING/nrPolar_tools/nr_polar_bit_insertion_2.c new file mode 100644 index 0000000000..1a7c1264b5 --- /dev/null +++ b/openair1/PHY/CODING/nrPolar_tools/nr_polar_bit_insertion_2.c @@ -0,0 +1,63 @@ +#include +#include +#include +#include + +void nr_polar_bit_insertion_2(uint8_t* u, uint8_t* b, uint8_t* info_bit_pattern, uint8_t* PC_bit_pattern, uint16_t N) +{ + int PC_circular_buffer_length=5; + + int i, j; + int k=0; + + int* y = (int*) malloc(sizeof(int)*PC_circular_buffer_length); + if (y == NULL) + { + fprintf(stderr, "malloc failed\n"); + exit(-1); + } + for(i=0; i +#include +#include +#include + +void nr_polar_crc(uint8_t* a, uint8_t A, uint8_t P, uint8_t** G_P, uint8_t** b) +{ + int i, j; + int* temp_b = (int*) malloc(sizeof(int)*P); + if (temp_b == NULL) + { + fprintf(stderr, "malloc failed\n"); + exit(-1); + } + printf("temp = "); + for(i=0; i Success + * -1 --> All list entries have failed the CRC checks + */ + +int8_t polar_decoder(double *input, uint8_t *output, t_nrPolar_params *polarParams, uint8_t listSize, + double *aPrioriPayload, uint8_t pathMetricAppr){ + + uint8_t ***bit = nr_alloc_uint8_t_3D_array(polarParams->N, (polarParams->n+1), 2*listSize); + uint8_t **bitUpdated = nr_alloc_uint8_t_2D_array(polarParams->N, (polarParams->n+1)); //0=False, 1=True + uint8_t **llrUpdated = nr_alloc_uint8_t_2D_array(polarParams->N, (polarParams->n+1)); //0=False, 1=True + double ***llr = nr_alloc_double_3D_array(polarParams->N, (polarParams->n+1), 2*listSize); + uint8_t **crcChecksum = nr_alloc_uint8_t_2D_array(polarParams->crcParityBits, 2*listSize); + double *pathMetric = malloc(sizeof(double)*(2*listSize)); + uint8_t *crcState = malloc(sizeof(uint8_t)*(2*listSize)); //0=False, 1=True + + for (int i=0; i<(2*listSize); i++) { + pathMetric[i] = 0; + crcState[i]=1; + } + for (int i=0; iN; i++) { + llrUpdated[i][polarParams->n]=1; + bitUpdated[i][0]=((polarParams->information_bit_pattern[i]+1) % 2); + } + + uint8_t **crc_generator_matrix=crc24c_generator_matrix(polarParams->payloadBits); //G_P + + uint8_t **extended_crc_generator_matrix = malloc(polarParams->K * sizeof(uint8_t *)); //G_P3 + uint8_t **tempECGM = malloc(polarParams->K * sizeof(uint8_t *)); //G_P2 + for (int i = 0; i < polarParams->K; i++){ + extended_crc_generator_matrix[i] = malloc(polarParams->crcParityBits * sizeof(uint8_t)); + tempECGM[i] = malloc(polarParams->crcParityBits * sizeof(uint8_t)); + } + + for (int i=0; ipayloadBits; i++) { + for (int j=0; jcrcParityBits; j++) { + tempECGM[i][j]=crc_generator_matrix[i][j]; + } + } + for (int i=polarParams->payloadBits; iK; i++) { + for (int j=0; jcrcParityBits; j++) { + if( (i-polarParams->payloadBits) == j ){ + tempECGM[i][j]=1; + } else { + tempECGM[i][j]=0; + } + } + } + + for (int i=0; iK; i++) { + for (int j=0; jcrcParityBits; j++) { + extended_crc_generator_matrix[i][j]=tempECGM[polarParams->interleaving_pattern[i]][j]; + } + } + + //The index of the last 1-valued bit that appears in each column. + uint16_t last1ind[polarParams->crcParityBits]; + for (int j=0; jcrcParityBits; j++) { + for (int i=0; iK; i++) { + if (extended_crc_generator_matrix[i][j]==1) last1ind[j]=i; + } + } + + double *d_tilde = malloc(sizeof(double) * polarParams->N); + nr_polar_rate_matching(input, d_tilde, polarParams->rate_matching_pattern, polarParams->K, polarParams->N, polarParams->encoderLength); + for (int j = 0; j < polarParams->N; j++) llr[j][polarParams->n][0]=d_tilde[j]; + + + /* + * SCL polar decoder. + */ + + uint32_t nonFrozenBit=0; + uint8_t currentListSize=1; + uint8_t decoderIterationCheck=0; + int16_t checkCrcBits=-1; + uint8_t listIndex[2*listSize], copyIndex; + + for (uint16_t currentBit=0; currentBitN; currentBit++){ + updateLLR(llr, llrUpdated, bit, bitUpdated, currentListSize, currentBit, 0, polarParams->N, (polarParams->n+1), pathMetricAppr); + if (polarParams->information_bit_pattern[currentBit]==0) { //Frozen bit. + updatePathMetric(pathMetric, llr, currentListSize, 0, currentBit, pathMetricAppr); //approximation=0 --> 11b, approximation=1 --> 12 + } else { //Information or CRC bit. + if ( (polarParams->interleaving_pattern[nonFrozenBit] <= polarParams->payloadBits) && (aPrioriPayload[polarParams->interleaving_pattern[nonFrozenBit]] == 0) ) { + //Information bit with known value of "0". + updatePathMetric(pathMetric, llr, currentListSize, 0, currentBit, pathMetricAppr); + bitUpdated[currentBit][0]=1; //0=False, 1=True + } else if ( (polarParams->interleaving_pattern[nonFrozenBit] <= polarParams->payloadBits) && (aPrioriPayload[polarParams->interleaving_pattern[nonFrozenBit]] == 1) ) { + //Information bit with known value of "1". + updatePathMetric(pathMetric, llr, currentListSize, 1, currentBit, pathMetricAppr); + for (uint8_t i=0; icrcParityBits); + } else { + updatePathMetric2(pathMetric, llr, currentListSize, currentBit, pathMetricAppr); + + for (int i = 0; i < currentListSize; i++) { + for (int j = 0; j < polarParams->N; j++) { + for (int k = 0; k < (polarParams->n+1); k++) { + bit[j][k][i+currentListSize]=bit[j][k][i]; + llr[j][k][i+currentListSize]=llr[j][k][i];}}} + for (int i = 0; i < currentListSize; i++) { + bit[currentBit][0][i]=0; + crcState[i+currentListSize]=crcState[i]; + } + for (int i = currentListSize; i < 2*currentListSize; i++) bit[currentBit][0][i]=1; + bitUpdated[currentBit][0]=1; + updateCrcChecksum2(crcChecksum, extended_crc_generator_matrix, currentListSize, nonFrozenBit, polarParams->crcParityBits); + currentListSize*=2; + + //Keep only the best "listSize" number of entries. + if (currentListSize > listSize) { + for (uint8_t i = 0; i < 2*listSize; i++) listIndex[i]=i; + nr_sort_asc_double_1D_array_ind(pathMetric, listIndex, currentListSize); + + //sort listIndex[listSize, ..., 2*listSize-1] in descending order. + uint8_t swaps, tempInd; + for (uint8_t i = 0; i < listSize; i++) { + swaps = 0; + for (uint8_t j = listSize; j < (2*listSize - i) - 1; j++) { + if (listIndex[j+1] > listIndex[j]) { + tempInd = listIndex[j]; + listIndex[j] = listIndex[j + 1]; + listIndex[j + 1] = tempInd; + swaps++; + } + } + if (swaps == 0) + break; + } + + //First, backup the best "listSize" number of entries. + for (int k=(listSize-1); k>0; k--) { + for (int i=0; iN; i++) { + for (int j=0; j<(polarParams->n+1); j++) { + bit[i][j][listIndex[(2*listSize-1)-k]]=bit[i][j][listIndex[k]]; + llr[i][j][listIndex[(2*listSize-1)-k]]=llr[i][j][listIndex[k]]; + } + } + } + for (int k=(listSize-1); k>0; k--) { + for (int i = 0; i < polarParams->crcParityBits; i++) { + crcChecksum[i][listIndex[(2*listSize-1)-k]] = crcChecksum[i][listIndex[k]]; + } + } + for (int k=(listSize-1); k>0; k--) crcState[listIndex[(2*listSize-1)-k]]=crcState[listIndex[k]]; + + //Copy the best "listSize" number of entries to the first indices. + for (int k = 0; k < listSize; k++) { + if (k > listIndex[k]) { + copyIndex = listIndex[(2*listSize-1)-k]; + } else { //Use the backup. + copyIndex = listIndex[k]; + } + for (int i = 0; i < polarParams->N; i++) { + for (int j = 0; j < (polarParams->n + 1); j++) { + bit[i][j][k] = bit[i][j][copyIndex]; + llr[i][j][k] = llr[i][j][copyIndex]; + } + } + } + for (int k = 0; k < listSize; k++) { + if (k > listIndex[k]) { + copyIndex = listIndex[(2*listSize-1)-k]; + } else { //Use the backup. + copyIndex = listIndex[k]; + } + for (int i = 0; i < polarParams->crcParityBits; i++) { + crcChecksum[i][k]=crcChecksum[i][copyIndex]; + } + } + for (int k = 0; k < listSize; k++) { + if (k > listIndex[k]) { + copyIndex = listIndex[(2*listSize-1)-k]; + } else { //Use the backup. + copyIndex = listIndex[k]; + } + crcState[k]=crcState[copyIndex]; + } + currentListSize = listSize; + } + } + + for (int i=0; icrcParityBits; i++) { + if (last1ind[i]==nonFrozenBit) { + checkCrcBits=i; + break; + } + } + + if ( checkCrcBits > (-1) ) { + for (uint8_t i = 0; i < currentListSize; i++) { + if (crcChecksum[checkCrcBits][i]==1) { + crcState[i]=0; //0=False, 1=True + } + } + } + + for (uint8_t i = 0; i < currentListSize; i++) decoderIterationCheck+=crcState[i]; + if (decoderIterationCheck==0) { + //perror("[SCL polar decoder] All list entries have failed the CRC checks."); + free(crc_generator_matrix); + free(d_tilde); + free(pathMetric); + nr_free_uint8_t_3D_array(bit, polarParams->N, (polarParams->n+1)); + nr_free_double_3D_array(llr, polarParams->N, (polarParams->n+1)); + nr_free_uint8_t_2D_array(crcChecksum, polarParams->crcParityBits); + return(-1); + } + + nonFrozenBit++; + decoderIterationCheck=0; + checkCrcBits=-1; + } + } + + for (uint8_t i = 0; i < 2*listSize; i++) listIndex[i]=i; + nr_sort_asc_double_1D_array_ind(pathMetric, listIndex, currentListSize); + + uint8_t *nr_polar_uHat = malloc(sizeof(uint8_t) * polarParams->N); + uint8_t *nr_polar_cHat = malloc(sizeof(uint8_t) * polarParams->K); + uint8_t *nr_polar_bHat = malloc(sizeof(uint8_t) * polarParams->K); + for (uint8_t i = 0; i < fmin(listSize, (pow(2,polarParams->crcCorrectionBits)) ); i++) { + if ( crcState[listIndex[i]] == 1 ) { + for (int j = 0; j < polarParams->N; j++) nr_polar_uHat[j]=bit[j][0][listIndex[i]]; + + //Extract the information bits (û to ĉ) + nr_polar_info_bit_extraction(nr_polar_uHat, nr_polar_cHat, polarParams->information_bit_pattern, polarParams->N); + + //Deinterleaving (ĉ to b) + nr_polar_deinterleaver(nr_polar_cHat, nr_polar_bHat, polarParams->interleaving_pattern, polarParams->K); + + //Remove the CRC (â) + for (int j = 0; j < polarParams->payloadBits; j++) output[j]=nr_polar_bHat[j]; + + break; + } + } + + free(crc_generator_matrix); + free(d_tilde); + free(pathMetric); + free(nr_polar_uHat); + free(nr_polar_cHat); + free(nr_polar_bHat); + nr_free_uint8_t_3D_array(bit, polarParams->N, (polarParams->n+1)); + nr_free_double_3D_array(llr, polarParams->N, (polarParams->n+1)); + nr_free_uint8_t_2D_array(crcChecksum, polarParams->crcParityBits); + return(0); +} diff --git a/openair1/PHY/CODING/nrPolar_tools/nr_polar_decoding_tools.c b/openair1/PHY/CODING/nrPolar_tools/nr_polar_decoding_tools.c new file mode 100644 index 0000000000..4555f8c3ba --- /dev/null +++ b/openair1/PHY/CODING/nrPolar_tools/nr_polar_decoding_tools.c @@ -0,0 +1,115 @@ +#include "PHY/CODING/nrPolar_tools/nr_polar_defs.h" + +void updateLLR(double ***llr, uint8_t **llrU, uint8_t ***bit, uint8_t **bitU, + uint8_t listSize, uint16_t row, uint16_t col, uint16_t xlen, uint8_t ylen, uint8_t approximation) { + uint16_t offset = (xlen/(pow(2,(ylen-col-1)))); + for (uint8_t i=0; i= offset ) { + if(bitU[row-offset][col]==0) updateBit(bit, bitU, listSize, (row-offset), col, xlen, ylen); + if(llrU[row-offset][col+1]==0) updateLLR(llr, llrU, bit, bitU, listSize, (row-offset), (col+1), xlen, ylen, approximation); + if(llrU[row][col+1]==0) updateLLR(llr, llrU, bit, bitU, listSize, row, (col+1), xlen, ylen, approximation); + llr[row][col][i] = (pow((-1),bit[row-offset][col][i])*llr[row-offset][col+1][i]) + llr[row][col+1][i]; + } else { + if(llrU[row][col+1]==0) updateLLR(llr, llrU, bit, bitU, listSize, row, (col+1), xlen, ylen, approximation); + if(llrU[row+offset][col+1]==0) updateLLR(llr, llrU, bit, bitU, listSize, (row+offset), (col+1), xlen, ylen, approximation); + computeLLR(llr, row, col, i, offset, approximation); + } + } + + llrU[row][col]=1; +} + +void updateBit(uint8_t ***bit, uint8_t **bitU, uint8_t listSize, uint16_t row, + uint16_t col, uint16_t xlen, uint8_t ylen) { + uint16_t offset = ( xlen/(pow(2,(ylen-col))) ); + + for (uint8_t i=0; i= offset ) { + if (bitU[row][col-1]==0) updateBit(bit, bitU, listSize, row, (col-1), xlen, ylen); + bit[row][col][i] = bit[row][col-1][i]; + } else { + if (bitU[row][col-1]==0) updateBit(bit, bitU, listSize, row, (col-1), xlen, ylen); + if (bitU[row+offset][col-1]==0) updateBit(bit, bitU, listSize, (row+offset), (col-1), xlen, ylen); + bit[row][col][i] = ( (bit[row][col-1][i]+bit[row+offset][col-1][i]) % 2); + } + } + + bitU[row][col]=1; +} + +void updatePathMetric(double *pathMetric, double ***llr, uint8_t listSize, uint8_t bitValue, + uint16_t row, uint8_t approximation) { + + if (approximation) { //eq. (12) + for (uint8_t i=0; i +#include +#include +#include +#include + +static const uint8_t nr_polar_subblock_interleaver_pattern[32] = { 0, 1, 2, 4, 3, 5, 6, 7, 8, 16, 9, 17, 10, 18, 11, 19, 12, 20, 13, 21, 14, 22, 15, 23, 24, 25, 26, 28, 27, 29, 30, 31 }; + +typedef struct nrPolar_params { + uint8_t n_max; + uint8_t i_il; + uint8_t n_pc; + uint8_t n_pc_wm; + uint8_t i_bil; + uint16_t payloadBits; + uint16_t encoderLength; + uint8_t crcParityBits; + uint8_t crcCorrectionBits; + uint16_t K; + uint16_t N; + uint8_t n; + + uint16_t *interleaving_pattern; + uint16_t *rate_matching_pattern; + uint16_t *Q_0_Nminus1; + int16_t *Q_I_N; + int16_t *Q_F_N; + int16_t *Q_PC_N; + uint8_t *information_bit_pattern; + uint16_t *channel_interleaver_pattern; + + uint8_t **crc_generator_matrix; //G_P + uint8_t **G_N; +} t_nrPolar_params; + +void polar_encoder(uint8_t *input, uint8_t *channel_input, t_nrPolar_params* polarParams); + +int8_t polar_decoder(double *input, uint8_t *output, t_nrPolar_params *polarParams, + uint8_t listSize, double *aPrioriPayload, uint8_t pathMetricAppr); + +void nr_polar_init(t_nrPolar_params* polarParams, int messageType); + +uint8_t** nr_polar_kronecker_power_matrices(uint8_t n); + +uint16_t* nr_polar_sequence_pattern(uint8_t n); + +uint32_t nr_polar_output_length(uint16_t K, uint16_t E, uint8_t n_max); + +void nr_polar_channel_interleaver_pattern(uint16_t *cip, uint8_t I_BIL, + uint16_t E); + +void nr_polar_rate_matching_pattern(uint16_t *rmp, uint16_t *J, uint8_t *P_i_, + uint16_t K, uint16_t N, uint16_t E); + +void nr_polar_rate_matching(double *input, double *output, uint16_t *rmp, + uint16_t K, uint16_t N, uint16_t E); + +void nr_polar_rate_matcher(uint8_t *input, unsigned char *output, uint16_t *pattern, uint16_t size); + +void nr_polar_interleaving_pattern(uint16_t K, uint8_t I_IL, uint16_t *PI_k_); + +void nr_polar_interleaver(uint8_t *input, uint8_t *output, uint16_t *pattern, + uint16_t size); + +void nr_polar_deinterleaver(uint8_t *input, uint8_t *output, uint16_t *pattern, + uint16_t size); + +void nr_polar_info_bit_pattern(uint8_t *ibp, uint16_t *Q_I_N, int16_t *Q_F_N, + uint16_t *J, uint16_t *Q_0_Nminus1, uint16_t K, uint16_t N, uint16_t E, + uint8_t n_PC); + +void nr_polar_info_bit_extraction(uint8_t *input, uint8_t *output, + uint8_t *pattern, uint16_t size); + +void nr_byte2bit(uint8_t *array, uint8_t arraySize, uint8_t *bitArray); + +void nr_polar_bit_insertion(uint8_t *input, uint8_t *output, uint16_t N, + uint16_t K, uint16_t *Q_I_N, uint16_t *Q_PC_N, uint8_t n_PC); + +void nr_matrix_multiplication_uint8_t_1D_uint8_t_2D(uint8_t *matrix1, uint8_t **matrix2, + uint8_t *output, uint16_t row, uint16_t col); + +uint8_t ***nr_alloc_uint8_t_3D_array(uint16_t xlen, uint16_t ylen, + uint16_t zlen); +uint8_t **nr_alloc_uint8_t_2D_array(uint16_t xlen, uint16_t ylen); +double ***nr_alloc_double_3D_array(uint16_t xlen, uint16_t ylen, uint16_t zlen); + +void nr_free_uint8_t_3D_array(uint8_t ***input, uint16_t xlen, uint16_t ylen); +void nr_free_uint8_t_2D_array(uint8_t **input, uint16_t xlen); +void nr_free_double_3D_array(double ***input, uint16_t xlen, uint16_t ylen); + +void updateLLR(double ***llr, uint8_t **llrU, uint8_t ***bit, uint8_t **bitU, + uint8_t listSize, uint16_t row, uint16_t col, uint16_t xlen, + uint8_t ylen, uint8_t approximation); +void updateBit(uint8_t ***bit, uint8_t **bitU, uint8_t listSize, uint16_t row, + uint16_t col, uint16_t xlen, uint8_t ylen); +void updatePathMetric(double *pathMetric, double ***llr, uint8_t listSize, + uint8_t bitValue, uint16_t row, uint8_t approximation); +void updatePathMetric2(double *pathMetric, double ***llr, uint8_t listSize, + uint16_t row, uint8_t approximation); +void computeLLR(double ***llr, uint16_t row, uint16_t col, uint8_t i, + uint16_t offset, uint8_t approximation); +void updateCrcChecksum(uint8_t **crcChecksum, uint8_t **crcGen, + uint8_t listSize, uint32_t i2, uint8_t len); +void updateCrcChecksum2(uint8_t **crcChecksum, uint8_t **crcGen, + uint8_t listSize, uint32_t i2, uint8_t len); +void nr_sort_asc_double_1D_array_ind(double *matrix, uint8_t *ind, uint8_t len); + +#endif diff --git a/openair1/PHY/CODING/nrPolar_tools/nr_polar_encoder.c b/openair1/PHY/CODING/nrPolar_tools/nr_polar_encoder.c new file mode 100644 index 0000000000..680d0d718a --- /dev/null +++ b/openair1/PHY/CODING/nrPolar_tools/nr_polar_encoder.c @@ -0,0 +1,56 @@ +#include "PHY/CODING/nrPolar_tools/nr_polar_defs.h" +#include "PHY/CODING/nrPolar_tools/nr_polar_pbch_defs.h" + +void polar_encoder(uint8_t *input, uint8_t *channel_input, t_nrPolar_params *polarParams){ + /*//Create the Transport Block. + unsigned int payload=0xb3f02c82; + uint8_t pbchTransportBlockSize = ( polarParams->K / (8*sizeof(uint8_t)) ); + uint8_t *pbchTransportBlock = malloc(pbchTransportBlockSize); + memcpy(pbchTransportBlock,&payload,sizeof(payload)); + + //Attach CRC to the Transport Block. (a to b) + uint32_t crc = crc24c(&payload, NR_POLAR_PBCH_PAYLOAD_BITS)>>8; + pbchTransportBlock[NR_POLAR_PBCH_PAYLOAD_BITS>>3] = ((uint8_t*)&crc)[2]; + pbchTransportBlock[1+(NR_POLAR_PBCH_PAYLOAD_BITS>>3)] = ((uint8_t*)&crc)[1]; + pbchTransportBlock[2+(NR_POLAR_PBCH_PAYLOAD_BITS>>3)] = ((uint8_t*)&crc)[0];*/ + + /* + * Bytewise operations + */ + + //Calculate CRC. + uint8_t *nr_polar_crc = malloc(sizeof(uint8_t) * polarParams->crcParityBits); + nr_matrix_multiplication_uint8_t_1D_uint8_t_2D(input, polarParams->crc_generator_matrix, + nr_polar_crc, polarParams->payloadBits, polarParams->crcParityBits); + for (uint8_t i = 0; i < polarParams->crcParityBits; i++) nr_polar_crc[i] = (nr_polar_crc[i] % 2); + + //Attach CRC to the Transport Block. (a to b) + uint8_t *nr_polar_b = malloc(sizeof(uint8_t) * polarParams->K); + for (uint16_t i = 0; i < polarParams->payloadBits; i++) nr_polar_b[i] = input[i]; + for (uint16_t i = polarParams->payloadBits; i < polarParams->K; i++) nr_polar_b[i]= nr_polar_crc[i-(polarParams->payloadBits)]; + + //Interleaving (c to c') + uint8_t *nr_polar_cPrime = malloc(sizeof(uint8_t) * polarParams->K); + nr_polar_interleaver(nr_polar_b, nr_polar_cPrime, polarParams->interleaving_pattern, polarParams->K); + + //Bit insertion (c' to u) + uint8_t *nr_polar_u = malloc(sizeof(uint8_t) * polarParams->N); + nr_polar_bit_insertion(nr_polar_cPrime, nr_polar_u, polarParams->N, polarParams->K, + polarParams->Q_I_N, polarParams->Q_PC_N, polarParams->n_pc); + + //Encoding (u to d) + uint8_t *pbch_polar_encoder_output = malloc(sizeof(uint8_t) * polarParams->N); + nr_matrix_multiplication_uint8_t_1D_uint8_t_2D(nr_polar_u, polarParams->G_N, pbch_polar_encoder_output, polarParams->N, polarParams->N); + for (uint16_t i = 0; i < polarParams->N; i++) pbch_polar_encoder_output[i] = (pbch_polar_encoder_output[i] % 2); + + //Rate matching + //Sub-block interleaving (d to y) and Bit selection (y to e) + nr_polar_rate_matcher(pbch_polar_encoder_output, channel_input, polarParams->rate_matching_pattern, polarParams->encoderLength); + + //free(pbchTransportBlock); + free(nr_polar_crc); + free(nr_polar_b); + free(nr_polar_cPrime); + free(nr_polar_u); + free(pbch_polar_encoder_output); +} diff --git a/openair1/PHY/CODING/nrPolar_tools/nr_polar_info_bit_pattern.c b/openair1/PHY/CODING/nrPolar_tools/nr_polar_info_bit_pattern.c new file mode 100644 index 0000000000..f311571c99 --- /dev/null +++ b/openair1/PHY/CODING/nrPolar_tools/nr_polar_info_bit_pattern.c @@ -0,0 +1,110 @@ +#include "PHY/CODING/nrPolar_tools/nr_polar_defs.h" + +void nr_polar_info_bit_pattern(uint8_t *ibp, uint16_t *Q_I_N, int16_t *Q_F_N, + uint16_t *J, uint16_t *Q_0_Nminus1, uint16_t K, uint16_t N, uint16_t E, + uint8_t n_PC) { + + int16_t *Q_Ftmp_N = malloc(sizeof(int16_t) * (N + 1)); // Last element shows the final + int16_t *Q_Itmp_N = malloc(sizeof(int16_t) * (N + 1)); // array index assigned a value. + + for (int i = 0; i <= N; i++) { + Q_Ftmp_N[i] = -1; // Empty array. + Q_Itmp_N[i] = -1; + } + + uint8_t flag; + uint16_t limit, ind; + + if (E < N) { + if ((K / (double) E) <= (7.0 / 16)) { //puncturing + for (int n = 0; n <= N - E - 1; n++) { + ind = Q_Ftmp_N[N] + 1; + Q_Ftmp_N[ind] = J[n]; + Q_Ftmp_N[N] = Q_Ftmp_N[N] + 1; + } + + if ((E / (double) N) >= (3.0 / 4)) { + limit = ceil((double) (3 * N - 2 * E) / 4); + for (int n = 0; n <= limit - 1; n++) { + ind = Q_Ftmp_N[N] + 1; + Q_Ftmp_N[ind] = n; + Q_Ftmp_N[N] = Q_Ftmp_N[N] + 1; + } + } else { + limit = ceil((double) (9 * N - 4 * E) / 16); + for (int n = 0; n <= limit - 1; n++) { + ind = Q_Ftmp_N[N] + 1; + Q_Ftmp_N[ind] = n; + Q_Ftmp_N[N] = Q_Ftmp_N[N] + 1; + } + } + } else { //shortening + for (int n = E; n <= N - 1; n++) { + ind = Q_Ftmp_N[N] + 1; + Q_Ftmp_N[ind] = J[n]; + Q_Ftmp_N[N] = Q_Ftmp_N[N] + 1; + } + } + } + + //Q_I,tmp_N = Q_0_N-1 \ Q_F,tmp_N + for (int n = 0; n <= N - 1; n++) { + flag = 1; + for (int m = 0; m <= Q_Ftmp_N[N]; m++) { + if (Q_0_Nminus1[n] == Q_Ftmp_N[m]) { + flag = 0; + break; + } + } + if (flag) { + Q_Itmp_N[Q_Itmp_N[N] + 1] = Q_0_Nminus1[n]; + Q_Itmp_N[N]++; + } + } + + //Q_I_N comprises (K+n_PC) most reliable bit indices in Q_I,tmp_N + for (int n = 0; n <= (K + n_PC) - 1; n++) { + ind = Q_Itmp_N[N] + n - ((K + n_PC) - 1); + Q_I_N[n] = Q_Itmp_N[ind]; + } + + //Q_F_N = Q_0_N-1 \ Q_I_N + for (int n = 0; n <= N - 1; n++) { + flag = 1; + for (int m = 0; m <= (K + n_PC) - 1; m++) { + if (Q_0_Nminus1[n] == Q_I_N[m]) { + flag = 0; + break; + } + } + if (flag) { + Q_F_N[Q_F_N[N] + 1] = Q_0_Nminus1[n]; + Q_F_N[N]++; + } + } + + //Information Bit Pattern + for (int n = 0; n <= N - 1; n++) { + ibp[n] = 0; + + for (int m = 0; m <= (K + n_PC) - 1; m++) { + if (n == Q_I_N[m]) { + ibp[n] = 1; + break; + } + } + } + + free(Q_Ftmp_N); + free(Q_Itmp_N); +} + +void nr_polar_info_bit_extraction(uint8_t *input, uint8_t *output, uint8_t *pattern, uint16_t size) { + uint16_t j = 0; + for (int i = 0; i < size; i++) { + if (pattern[i] > 0) { + output[j] = input[i]; + j++; + } + } +} diff --git a/openair1/PHY/CODING/nrPolar_tools/nr_polar_interleave.c b/openair1/PHY/CODING/nrPolar_tools/nr_polar_interleave.c new file mode 100644 index 0000000000..643b5fd034 --- /dev/null +++ b/openair1/PHY/CODING/nrPolar_tools/nr_polar_interleave.c @@ -0,0 +1,37 @@ +#include "PHY/CODING/nrPolar_tools/nr_polar_defs.h" + +void nr_polar_interleaving_pattern(uint16_t K, uint8_t I_IL, uint16_t *PI_k_){ + uint8_t K_IL_max=164, k=0; + uint8_t interleaving_pattern_table[164] = {0, 2, 4, 7, 9, 14, 19, 20, 24, 25, 26, 28, 31, 34, + 42, 45, 49, 50, 51, 53, 54, 56, 58, 59, 61, 62, 65, 66, + 67, 69, 70, 71, 72, 76, 77, 81, 82, 83, 87, 88, 89, 91, + 93, 95, 98, 101, 104, 106, 108, 110, 111, 113, 115, 118, 119, 120, + 122, 123, 126, 127, 129, 132, 134, 138, 139, 140, 1, 3, 5, 8, + 10, 15, 21, 27, 29, 32, 35, 43, 46, 52, 55, 57, 60, 63, + 68, 73, 78, 84, 90, 92, 94, 96, 99, 102, 105, 107, 109, 112, + 114, 116, 121, 124, 128, 130, 133, 135, 141, 6, 11, 16, 22, 30, + 33, 36, 44, 47, 64, 74, 79, 85, 97, 100, 103, 117, 125, 131, + 136, 142, 12, 17, 23, 37, 48, 75, 80, 86, 137, 143, 13, 18, + 38, 144, 39, 145, 40, 146, 41, 147, 148, 149, 150, 151, 152, 153, + 154, 155, 156, 157, 158, 159, 160, 161, 162, 163}; + + if (I_IL == 0){ + for (; k<= K-1; k++) + PI_k_[k] = k; + } else { + for (int m=0; m<= (K_IL_max-1); m++){ + if (interleaving_pattern_table[m] >= (K_IL_max-K)) { + PI_k_[k] = interleaving_pattern_table[m]-(K_IL_max-K); + k++; + } + } + } +} + +void nr_polar_interleaver(uint8_t *input, uint8_t *output, uint16_t *pattern, uint16_t size) { + for (int i=0; i +#include +#include +#include + +void nr_polar_kernel_operation(uint8_t *u, uint8_t *d, uint16_t N) +{ + // Martino's algorithm to avoid multiplication for the generating matrix + + int i,j; + printf("\nd = "); + for(i=0; i matrix[j + 1]) { + temp = matrix[j]; + matrix[j] = matrix[j + 1]; + matrix[j + 1] = temp; + + tempInd = ind[j]; + ind[j] = ind[j + 1]; + ind[j + 1] = tempInd; + + swaps++; + } + } + if (swaps == 0) + break; + } +} diff --git a/openair1/PHY/CODING/nrPolar_tools/nr_polar_output_length.c b/openair1/PHY/CODING/nrPolar_tools/nr_polar_output_length.c new file mode 100644 index 0000000000..bbb6c8b3b8 --- /dev/null +++ b/openair1/PHY/CODING/nrPolar_tools/nr_polar_output_length.c @@ -0,0 +1,25 @@ +#include +#include "PHY/CODING/nrPolar_tools/nr_polar_defs.h" + +uint32_t nr_polar_output_length(uint16_t K, uint16_t E, uint8_t n_max){ + uint8_t n_1, n_2, n_min=5, n; + uint32_t polar_code_output_length; + double R_min=1.0/8; + + if ( (E <= (9.0/8)*pow(2,ceil(log2(E))-1)) && (K/E < 9.0/16) ) { + n_1 = ceil(log2(E))-1; + } else { + n_1 = ceil(log2(E)); + } + + n_2 = ceil(log2(K/R_min)); + + n=n_max; + if (n>n_1) n=n_1; + if (n>n_2) n=n_2; + if (n8 to meet false alarm rate requirements. + +//Ref. 38-212 v15.0.1, Section 7.1.4: Channel Coding +#define NR_POLAR_PBCH_N_MAX 9 //uint8_t +#define NR_POLAR_PBCH_I_IL 1 //uint8_t +#define NR_POLAR_PBCH_N_PC 0 //uint8_t +#define NR_POLAR_PBCH_N_PC_WM 0 //uint8_t +//#define NR_POLAR_PBCH_N 512 //uint16_t + +//Ref. 38-212 v15.0.1, Section 7.1.5: Rate Matching +#define NR_POLAR_PBCH_I_BIL 0 //uint8_t +#define NR_POLAR_PBCH_E 864 //uint16_t + +//#define NR_POLAR_PBCH_L 5 //uint8_t +#define NR_POLAR_PBCH_PATH_METRIC_APPROXIMATION 0 //uint8_t; 0 --> eq. (8a) and (11b), 1 --> eq. (9) and (12) + +/* + * TEST CODE + */ +//#define DEBUG_POLAR +// Usage in code: +//#ifdef DEBUG_POLAR +//... +//#endif + +//unsigned int testPayload0=0x00000000, testPayload1=0xffffffff; //payload1=~payload0; +//unsigned int testPayload2=0xa5a5a5a5; //testPayload3=0xb3f02c82; + +//double testReceivedPayload3[NR_POLAR_PBCH_E] = {-1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, -1, -1, -1, 1, 1, 1, 1, -1, -1, -1, 1, -1, 1, -1, 1, -1, 1, 1, -1, 1, 1, 1, -1, -1, -1, 1, 1, 1, -1, 1, 1, -1, 1, 1, -1, 1, -1, -1, 1, 1, -1, 1, 1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, -1, -1, 1, -1, 1, -1, -1, 1, 1, -1, -1, -1, -1, 1, 1, 1, -1, 1, -1, 1, 1, 1, -1, 1, -1, -1, 1, -1, -1, 1, 1, -1, -1, 1, 1, 1, -1, -1, 1, 1, -1, -1, -1, -1, 1, -1, -1, -1, 1, -1, -1, 1, 1, 1, 1, -1, -1, -1, -1, 1, -1, -1, 1, -1, 1, 1, 1, 1, -1, 1, -1, -1, 1, -1, 1, -1, -1, -1, -1, 1, 1, 1, -1, -1, -1, 1, 1, 1, 1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, -1, -1, 1, 1, -1, -1, 1, 1, 1, -1, -1, -1, -1, 1, 1, -1, 1, -1, 1, -1, 1, -1, 1, 1, -1, -1, -1, 1, -1, 1, 1, -1, -1, 1, -1, -1, -1, -1, 1, -1, 1, -1, -1, -1, 1, 1, 1, 1, 1, 1, -1, 1, 1, -1, 1, 1, 1, -1, -1, 1, 1, 1, 1, -1, 1, 1, -1, 1, -1, 1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, -1, 1, -1, -1, 1, 1, -1, 1, -1, -1, 1, -1, 1, -1, 1, -1, -1, -1, -1, 1, 1, -1, -1, -1, 1, -1, 1, 1, -1, -1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 1, -1, 1, 1, 1, -1, 1, -1, 1, 1, 1, -1, -1, -1, 1, 1, 1, -1, -1, -1, 1, -1, -1, 1, 1, 1, -1, 1, -1, -1, 1, -1, 1, -1, 1, -1, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, -1, -1, 1, 1, -1, 1, 1, -1, -1, 1, 1, -1, -1, -1, -1, -1, 1, -1, -1, -1, 1, 1, -1, 1, 1, -1, 1, -1, -1, 1, 1, -1, 1, 1, 1, -1, 1, -1, 1, 1, 1, 1, -1, -1, -1, 1, -1, 1, 1, -1, 1, -1, -1, 1, 1, -1, 1, -1, -1, 1, -1, 1, 1, 1, 1, -1, -1, -1, -1, 1, -1, -1, 1, 1, -1, -1, 1, -1, 1, 1, 1, -1, 1, -1, -1, -1, -1, 1, -1, -1, -1, -1, 1, -1, 1, 1, -1, 1, -1, 1, -1, -1, -1, -1, -1, 1, 1, -1, -1, -1, -1, 1, 1, -1, -1, -1, -1, -1, 1, 1, -1, 1, -1, 1, -1, 1, 1, -1, 1, -1, -1, -1, 1, 1, -1, 1, 1, 1, -1, -1, -1, -1, 1, -1, 1, -1, 1, -1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, -1, 1, 1, 1, -1, 1, -1, 1, 1, -1, 1, -1, -1, -1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, -1, -1, -1, 1, 1, 1, 1, -1, -1, -1, 1, -1, 1, -1, 1, -1, 1, 1, -1, 1, 1, 1, -1, -1, -1, 1, 1, 1, -1, 1, 1, -1, 1, 1, -1, 1, -1, -1, 1, 1, -1, 1, 1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, -1, -1, 1, -1, 1, -1, -1, 1, 1, -1, -1, -1, -1, 1, 1, 1, -1, 1, -1, 1, 1, 1, -1, 1, -1, -1, 1, -1, -1, 1, 1, -1, -1, 1, 1, 1, -1, -1, 1, 1, -1, -1, -1, -1, 1, -1, -1, -1, 1, -1, -1, 1, 1, 1, 1, -1, -1, -1, -1, 1, -1, -1, 1, -1, 1, 1, 1, 1, -1, 1, -1, -1, 1, -1, 1, -1, -1, -1, -1, 1, 1, 1, -1, -1, -1, 1, 1, 1, 1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, -1, -1, 1, 1, -1, -1, 1, 1, 1, -1, -1, -1, -1, 1, 1, -1, 1, -1, 1, -1, 1, -1, 1, 1, -1, -1, -1, 1, -1, 1, 1, -1, -1, 1, -1, -1, -1, -1, 1, -1, 1, -1, -1, -1, 1, 1, 1, 1, 1, 1, -1, 1, 1, -1, 1, 1, 1, -1, -1, 1, 1, 1, 1, -1, 1, 1, -1, 1, -1, 1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, -1, 1, -1, -1, 1, 1, -1, 1, -1, -1, 1, -1, 1, -1, 1, -1, -1, -1, -1, 1, 1, -1, -1, -1, 1, -1, 1, 1, -1, -1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, -1, 1, -1, 1, 1, 1, -1, 1, -1, 1, 1, 1, -1, -1, -1, 1, 1, 1, -1, -1, -1, 1, -1, -1, 1, 1, 1, -1, 1, -1, -1, 1, -1, 1, -1, 1, -1, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 1, 1, -1, -1, 1, 1, -1, 1, 1, -1, -1, 1, 1, -1, -1}; + +#endif diff --git a/openair1/PHY/CODING/nrPolar_tools/nr_polar_plot.m b/openair1/PHY/CODING/nrPolar_tools/nr_polar_plot.m new file mode 100644 index 0000000000..e69de29bb2 diff --git a/openair1/PHY/CODING/nrPolar_tools/nr_polar_pucch_defs.h b/openair1/PHY/CODING/nrPolar_tools/nr_polar_pucch_defs.h new file mode 100644 index 0000000000..cf23982752 --- /dev/null +++ b/openair1/PHY/CODING/nrPolar_tools/nr_polar_pucch_defs.h @@ -0,0 +1,28 @@ +/* + * Defines the constant variables for polar coding of the PUCCH. + */ + +#ifndef __NR_POLAR_PUCCH_DEFS__H__ +#define __NR_POLAR_PUCCH_DEFS__H__ + +#define NR_POLAR_PUCCH_PAYLOAD_BITS 16 + +//Ref. 38-212 v15.0.1 +#define NR_POLAR_PUCCH_N_MAX 10 //uint8_t <------ +#define NR_POLAR_PUCCH_I_IL 1 //uint8_t <--- interleaving: if 0 no interleaving +#define NR_POLAR_PUCCH_N_PC 3 //uint8_t <-- or zero ?? +#define NR_POLAR_PUCCH_N_PC_WM 0 //uint8_t +//#define NR_POLAR_PUCCH_N 512 //uint16_t + +//Ref. 38-212 v15.0.1, Section 7.1.5: Rate Matching +#define NR_POLAR_PUCCH_I_BIL 0 //uint8_t +#define NR_POLAR_PUCCH_E 864 //uint16_t + + +/* + * TEST CODE + */ +//unsigned int testPayload0=0x00000000, testPayload1=0xffffffff; //payload1=~payload0; +//unsigned int testPayload2=0xa5a5a5a5, testPayload3=0xb3f02c82; + +#endif diff --git a/openair1/PHY/CODING/nrPolar_tools/nr_polar_rate_match.c b/openair1/PHY/CODING/nrPolar_tools/nr_polar_rate_match.c new file mode 100644 index 0000000000..13e0e1a6d4 --- /dev/null +++ b/openair1/PHY/CODING/nrPolar_tools/nr_polar_rate_match.c @@ -0,0 +1,64 @@ +#include +#include "PHY/CODING/nrPolar_tools/nr_polar_defs.h" + +void nr_polar_rate_matching_pattern(uint16_t *rmp, uint16_t *J, uint8_t *P_i_, uint16_t K, uint16_t N, uint16_t E){ + + uint8_t i; + uint16_t *d, *y, ind; + d = (uint16_t *)malloc(sizeof(uint16_t) * N); + y = (uint16_t *)malloc(sizeof(uint16_t) * N); + + for (int m=0; m<=N-1; m++) d[m]=m; + + for (int m=0; m<=N-1; m++){ + i=floor((32*m)/N); + J[m] = (P_i_[i]*(N/32)) + (m%(N/32)); + y[m] = d[J[m]]; + } + + if (E>=N) { //repetition + for (int k=0; k<=E-1; k++) { + ind = (k%N); + rmp[k]=y[ind]; + } + } else { + if ( (K/(double)E) <= (7.0/16) ) { //puncturing + for (int k=0; k<=E-1; k++) { + rmp[k]=y[k+N-E]; + } + } else { //shortening + for (int k=0; k<=E-1; k++) { + rmp[k]=y[k]; + } + } + } + + free(d); + free(y); +} + + +void nr_polar_rate_matching(double *input, double *output, uint16_t *rmp, uint16_t K, uint16_t N, uint16_t E){ + + if (E>=N) { //repetition + for (int i=0; i<=N-1; i++) output[i]=0; + for (int i=0; i<=E-1; i++){ + output[rmp[i]]+=input[i]; + } + } else { + if ( (K/(double)E) <= (7.0/16) ) { //puncturing + for (int i=0; i<=N-1; i++) output[i]=0; + } else { //shortening + for (int i=0; i<=N-1; i++) output[i]=INFINITY; + } + + for (int i=0; i<=E-1; i++){ + output[rmp[i]]=input[i]; + } + } + +} + +void nr_polar_rate_matcher(uint8_t *input, unsigned char *output, uint16_t *pattern, uint16_t size) { + for (int i=0; i +#include +#include + +#include "nr_polar_defs.h" +#include "nr_polar_pucch_defs.h" + +void PUCCH_encoder(uint8_t a[], uint8_t A, uint8_t G, uint16_t* E_r, uint8_t** f) +{ +// PUCCH_ENCODER Polar encoder for the Physical Uplink Control Channel (PUCCH) and the +// Physical Uplink Shared Channel (PUSCH) of 3GPP New Radio, as defined in +// Section 6.3 of TS38.212. Implements the code block segmentation and +// Cyclic Redudancy Check (CRC) attachment of Sections 6.3.1.2.1 and 6.3.2.2.1, +// the channel coding of Sections 6.3.1.3.1 and 6.3.2.3.2, the rate matching of +// Sections 6.3.1.4.1 and 6.3.2.4.1, as well as the code block concatenation of +// Sections 6.3.1.5.1 and 6.3.2.5.1. Note that this code does not implement the +// UCI bit sequence generation of Sections 6.3.1.1 and 6.3.2.1, the +// determination of the encoded block length E_UCI of Sections 6.3.1.4.1 and +// 6.3.2.4.1, or the multiplexing of Sections 6.3.1.6 and 6.3.2.6. Also, this +// code does not implement the small block lengths, which are detailed in +// Sections 6.3.1.2.2, 6.3.1.3.2, 6.3.1.4.2, 6.3.2.2.2, 6.3.2.3.2 and 6.3.2.4.2. + + uint8_t C=0; + uint8_t i; + uint8_t crc_polynomial_pattern_length; + uint8_t P[32] = {0, 1, 2, 4, 3, 5, 6, 7, 8, 16, 9, 17, 10, 18, 11, 19, 12, 20, 13, 21, 14, 22, 15, 23, 24, 25, 26, 28, 27, 29, 30, 31}; + uint8_t* crc_polynomial_pattern; + + if (A < 12) { + fprintf(stderr, "A should be no less than 12."); + exit(-1); + } else if (A > 1706) { + fprintf(stderr, "A should be no greater than 1706."); + exit(-1); + } + else if (A <= 19) //Use PCCA-polar + { + // The CRC polynomial used with PCCA-polar in 3GPP PUCCH channel is D^6 + D^5 + 1 + crc_polynomial_pattern_length = 7; + crc_polynomial_pattern = (uint8_t *)malloc(sizeof(uint8_t)*crc_polynomial_pattern_length); + crc_polynomial_pattern[0] = 1; + crc_polynomial_pattern[1] = 1; + crc_polynomial_pattern[2] = 0; + crc_polynomial_pattern[3] = 0; + crc_polynomial_pattern[4] = 0; + crc_polynomial_pattern[5] = 0; + crc_polynomial_pattern[6] = 1; + + C = 1; // Use one segment + } + else // Use CA-polar + { + crc_polynomial_pattern_length = 12; + crc_polynomial_pattern = (uint8_t *)malloc(sizeof(uint8_t)*crc_polynomial_pattern_length); + crc_polynomial_pattern[0] = 1; + crc_polynomial_pattern[1] = 1; + crc_polynomial_pattern[2] = 1; + crc_polynomial_pattern[3] = 0; + crc_polynomial_pattern[4] = 0; + crc_polynomial_pattern[5] = 0; + crc_polynomial_pattern[6] = 1; + crc_polynomial_pattern[7] = 0; + crc_polynomial_pattern[8] = 0; + crc_polynomial_pattern[9] = 0; + crc_polynomial_pattern[10] = 0; + crc_polynomial_pattern[11] = 1; + + if (A >= 360 && G >= 1088 ) + C = 2; // Use two segments + else + C = 1; // Use one segment + } + + // Determine the number of information and CRC bits. + uint16_t K = ceil(A/C)+crc_polynomial_pattern_length-1; + + *E_r = floor((double)G/C); + + if(*E_r > 8192) { + fprintf(stderr, "G is too long."); + exit(-1); + } + + //Determine the number of bits used at the input and output of the polar encoder kernal. + uint16_t N = nr_polar_coding_output_length(K, *E_r, NR_POLAR_PUCCH_N_MAX); + uint8_t n = log2(N); + + //int N = get_3GPP_N(K,*E_r,10); //n_max = 10 is used in PUCCH channels + printf("DEBUG: The number of bits used at I/O of encoder kernal is %i\n", (int)N); + + // Get a rate matching pattern + uint16_t* rate_matching_pattern = (uint16_t*)malloc(sizeof(uint16_t) * (*E_r)); + uint16_t *J = malloc(sizeof(uint16_t) * N); + nr_polar_coding_rate_matching_pattern(rate_matching_pattern, J, P, K, N, *E_r); + + printf("DEBUG: The rate matching pattern is "); + for (i=0; i<*E_r; i++) { + printf("%i ", (int)rate_matching_pattern[i]); + } + printf("\n"); + + // Get a sequence pattern + uint16_t *Q_0_Nminus1 = nr_polar_coding_sequence_pattern(n); + printf("DEBUG: The sequence pattern is "); + for (i=0; i info_bit_pattern + printf("DEBUG: The information bit pattern is " ); + for (i=0; i 192) + get_PC_bit_pattern(N, n_PC, 1, Q_0_Nminus1, info_bit_pattern, &PC_bit_pattern); // -> PC_bit_pattern + else + get_PC_bit_pattern(N, n_PC, 0, Q_0_Nminus1, info_bit_pattern, &PC_bit_pattern); // -> PC_bit_pattern + + printf("DEBUG: The PC bit pattern is " ); + for (i=0; i G_P + nr_polar_crc(a, A, crc_polynomial_pattern_length-1, G_P, &b); //-> b + + //Bit insertion + u = (uint8_t*) malloc(sizeof(uint8_t)*N); + if (u == NULL) { + fprintf(stderr, "malloc failed\n"); + exit(-1); + } + nr_polar_bit_insertion_2(u, b, info_bit_pattern, PC_bit_pattern, N); // -> u + free(b); + + //encoding + d = malloc(sizeof(uint8_t) * N); + if (d == NULL) { + fprintf(stderr, "malloc failed\n"); + exit(-1); + } + nr_polar_kernel_operation(u, d, N); // -> d + free(u); + + //rate matching + e = malloc(sizeof(uint8_t) * N); + if (e == NULL) { + fprintf(stderr, "malloc failed\n"); + exit(-1); + } + nr_polar_coding_rate_matcher(d, e, rate_matching_pattern, (*E_r)); + free(d); + printf("\ne = "); + for(i=0;i<(*E_r);i++) + { + printf("%i ", e[i]); + } + + // Perform channel interleaving. + *f = (uint8_t*) malloc(sizeof(uint8_t)*(*E_r)); + nr_polar_coding_interleaver(e, *f, channel_interleaver_pattern, (uint16_t)(*E_r)); + free(e); + printf("\nf = "); + for(i=0;i<(*E_r);i++) + { + printf("%i ", (*f)[i]); + } + printf("\n\n\n "); + } else //Use CA-polar + { + n_PC = 0; + + // Get an information bit pattern. + get_3GPP_info_bit_pattern(K, n_PC, N, *E_r, P, Q_0_Nminus1, &info_bit_pattern); // -> info_bit_pattern + printf("DEBUG: The information bit pattern is " ); + for (i=0; i G_P + nr_polar_crc(a, A/C, crc_polynomial_pattern_length-1, G_P, &b); //-> b + + } else + { + //Attach CRC to the Transport Block. (a to b) + get_crc_generator_matrix(A, crc_polynomial_pattern_length-1, crc_polynomial_pattern, &G_P); // -> G_P + nr_polar_crc(a, A, crc_polynomial_pattern_length-1, G_P, &b); //-> b + } + + //Bit insertion + u = (uint8_t*) malloc(sizeof(uint8_t)*N); + if (u == NULL) { + fprintf(stderr, "malloc failed\n"); + exit(-1); + } + int j=0; + printf("\nu = "); + for(i=0; i d + free(u); + + //rate matching + e = malloc(sizeof(uint8_t) * N); + if (e == NULL) { + fprintf(stderr, "malloc failed\n"); + exit(-1); + } + nr_polar_coding_rate_matcher(d, e, rate_matching_pattern, (*E_r)); + free(d); + printf("\ne = "); + for(i=0;i<(*E_r);i++) + { + printf("%i ", e[i]); + } + + // Perform channel interleaving. + *f = (uint8_t*) malloc(sizeof(uint8_t)*(*E_r)); + nr_polar_coding_interleaver(e, *f, channel_interleaver_pattern, (uint16_t)(*E_r)); + free(e); + printf("\nf = "); + for(i=0;i<(*E_r);i++) + { + printf("%i ", (*f)[i]); + } + printf("\n\n\n "); + + + + + } +// +// free(crc_polynomial_pattern); +// //free others... + +}