NR Polar imports
This commit is contained in:
@@ -0,0 +1,194 @@
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
#include <time.h>
|
||||
|
||||
#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; i<nrPolar_params.payloadBits; i++) aPrioriArray[i] = NAN;
|
||||
|
||||
for (SNR = SNRstart; SNR <= SNRstop; SNR += SNRinc) {
|
||||
SNR_lin = pow(10, SNR/10);
|
||||
for (itr = 1; itr <= iterations; itr++) {
|
||||
|
||||
for(int i=0; i<testLength; i++) testInput[i]=(uint8_t) (rand() % 2);
|
||||
|
||||
start_meas(&timeEncoder);
|
||||
polar_encoder(testInput, encoderOutput, &nrPolar_params);
|
||||
stop_meas(&timeEncoder);
|
||||
|
||||
//BPSK modulation
|
||||
for(int i=0; i<coderLength; i++) {
|
||||
if (encoderOutput[i] == 0)
|
||||
modulatedInput[i]=1/sqrt(2);
|
||||
else
|
||||
modulatedInput[i]=(-1)/sqrt(2);
|
||||
|
||||
channelOutput[i] = modulatedInput[i] + (gaussdouble(0.0,1.0) * (1/sqrt(2*SNR_lin)));
|
||||
}
|
||||
|
||||
|
||||
start_meas(&timeDecoder);
|
||||
decoderState = polar_decoder(channelOutput, estimatedOutput, &nrPolar_params, decoderListSize, aPrioriArray, pathMetricAppr);
|
||||
stop_meas(&timeDecoder);
|
||||
|
||||
//calculate errors
|
||||
if (decoderState==-1) {
|
||||
blockErrorState=-1;
|
||||
nBitError=-1;
|
||||
} else {
|
||||
for(int i=0; i<testLength; i++){
|
||||
if (estimatedOutput[i]!=testInput[i]) nBitError++;
|
||||
}
|
||||
if (nBitError>0) 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);
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -0,0 +1,200 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <stdint.h>
|
||||
|
||||
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<Q_N_length; j++)
|
||||
{
|
||||
i=floor(32*(double)j/Q_N_length);
|
||||
J[j] = P[i]*(Q_N_length/32)+(j%(Q_N_length/32));
|
||||
}
|
||||
|
||||
//Q_Ftmp_N = [];
|
||||
int Q_Ftmp_N_length= Q_N_length-E_r;
|
||||
if (E_r < Q_N_length)
|
||||
{
|
||||
if ((double)(I)/E_r <= (double)7/16) // puncturing
|
||||
{
|
||||
//Q_Ftmp_N_length = Q_Ftmp_N_length + N-E;
|
||||
if (E_r >= (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<Q_N_length-E_r; j++)
|
||||
{
|
||||
Q_Ftmp_N[j] = J[j];
|
||||
}
|
||||
|
||||
if (E_r >= 3*Q_N_length/4)
|
||||
{
|
||||
for (j=0; j<ceil(3*Q_N_length/4-(double)E_r/2); j++)
|
||||
{
|
||||
Q_Ftmp_N[Q_N_length-E_r+1+j] = j;
|
||||
}
|
||||
} else
|
||||
{
|
||||
for (j=0; j<ceil(9*Q_N_length/16-(double)E_r/4); j++)
|
||||
{
|
||||
Q_Ftmp_N[Q_N_length-E_r+1+j] = j;
|
||||
}
|
||||
}
|
||||
} else // shortening
|
||||
{
|
||||
for (j=E_r; j<Q_N_length; j++)
|
||||
{
|
||||
Q_Ftmp_N[j-E_r] = J[j];
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
//Q_Itmp_N = setdiff(Q_N-1,Q_Ftmp_N,'stable'); // -1 because TS 38.212 assumes that indices start at 0, not 1 like in Matlab
|
||||
int Q_Itmp_N_length = Q_N_length;
|
||||
int Q_Itmp_N_common[Q_N_length];
|
||||
|
||||
for(i=0; i<Q_N_length; i++)
|
||||
{
|
||||
Q_Itmp_N_common[i]=0; //1 if in common, otherwise 0
|
||||
|
||||
for (j=0; j<Q_Ftmp_N_length; j++)
|
||||
{
|
||||
if((int)Q_N[i]==Q_Ftmp_N[j])
|
||||
{
|
||||
Q_Itmp_N_common[i]=1;
|
||||
Q_Itmp_N_length--;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
free(Q_Ftmp_N);
|
||||
|
||||
if (Q_Itmp_N_length < I)
|
||||
{
|
||||
fprintf(stderr, "Too many pre-frozen bits.");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
int* Q_Itmp_N = (int *)malloc(sizeof(int)*Q_Itmp_N_length);
|
||||
if (Q_Itmp_N == NULL)
|
||||
{
|
||||
fprintf(stderr, "malloc failed\n");
|
||||
exit(-1);
|
||||
}
|
||||
j=0;
|
||||
for(i=0; i<Q_N_length; i++)
|
||||
{
|
||||
if(!Q_Itmp_N_common[i]) //if not commonc
|
||||
{
|
||||
Q_Itmp_N[j]=(int)Q_N[i];
|
||||
j++;
|
||||
}
|
||||
}
|
||||
|
||||
int* Q_I_N = (int *)malloc(sizeof(int)*(I));
|
||||
if (Q_I_N == NULL)
|
||||
{
|
||||
fprintf(stderr, "malloc failed\n");
|
||||
exit(-1);
|
||||
}
|
||||
//Q_I_N=Q_Itmp_N(end-I+1:end);
|
||||
for (j=Q_Itmp_N_length-(I); j<Q_Itmp_N_length; j++)
|
||||
{
|
||||
Q_I_N[j-(Q_Itmp_N_length-(I))]=Q_Itmp_N[j];
|
||||
}
|
||||
|
||||
free(Q_Itmp_N);
|
||||
|
||||
//info_bit_pattern(Q_I_N+1) = true;
|
||||
*info_bit_pattern = (uint8_t *)malloc(sizeof(uint8_t)*Q_N_length);
|
||||
if (*info_bit_pattern == NULL)
|
||||
{
|
||||
fprintf(stderr, "malloc failed\n");
|
||||
exit(-1);
|
||||
}
|
||||
for(j=0; j<Q_N_length; j++)
|
||||
{
|
||||
(*info_bit_pattern)[j]=0;
|
||||
for(i=0; i<I; i++)
|
||||
{
|
||||
if(Q_I_N[i]==j)
|
||||
{
|
||||
(*info_bit_pattern)[j]=1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
free(Q_I_N);
|
||||
}
|
||||
@@ -0,0 +1,259 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <stdint.h>
|
||||
|
||||
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<Q_N_length; j++)
|
||||
{
|
||||
if(info_bit_pattern[j])
|
||||
totInfoBit++;
|
||||
}
|
||||
|
||||
if (n_PC > 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<Q_N_length; j++)
|
||||
{
|
||||
Q_I[j]=j+1;
|
||||
}
|
||||
|
||||
//Q_N_I = intersect(Q_N, Q_I(info_bit_pattern), 'stable');
|
||||
int Q_N_I_length=0;
|
||||
int* Q_N_common = (int*) malloc(sizeof(int)*Q_N_length);
|
||||
if (Q_N_common == NULL)
|
||||
{
|
||||
fprintf(stderr, "malloc failed\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
for (j=0; j<Q_N_length; j++) //init
|
||||
{
|
||||
Q_N_common[j]=0;
|
||||
}
|
||||
|
||||
for (j=0; j<Q_N_length; j++) //look in Q_I
|
||||
{
|
||||
if(info_bit_pattern[j])
|
||||
{
|
||||
//Q_I(info_bit_pattern)
|
||||
for (i=0; i<Q_N_length; i++) //look in Q_N
|
||||
{
|
||||
if(Q_N[i]+1==Q_I[j])
|
||||
{
|
||||
Q_N_common[i]=1;
|
||||
Q_N_I_length++;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
free(Q_I);
|
||||
|
||||
int* Q_N_I = (int*) malloc(sizeof(int)*Q_N_I_length);
|
||||
if (Q_N_I == NULL)
|
||||
{
|
||||
fprintf(stderr, "malloc failed\n");
|
||||
exit(-1);
|
||||
}
|
||||
i=0;
|
||||
for(j=0; j<Q_N_length; j++)
|
||||
{
|
||||
if(Q_N_common[j])
|
||||
{
|
||||
Q_N_I[i]=Q_N[j]+1;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
|
||||
free(Q_N_common);
|
||||
|
||||
//int G_N = get_G_N(N);
|
||||
//int w_g = sum(G_N,2);
|
||||
//useless, I do this
|
||||
int* w_g = (int*) malloc(sizeof(int)*Q_N_length);
|
||||
if (w_g == NULL)
|
||||
{
|
||||
fprintf(stderr, "malloc failed\n");
|
||||
exit(-1);
|
||||
}
|
||||
w_g[0]=1;
|
||||
w_g[1]=2;
|
||||
int counter=2;
|
||||
int n = log2(Q_N_length);
|
||||
|
||||
for(i=0; i<n-1; i++) //n=log2(N)
|
||||
{
|
||||
for(j=0; j<counter; j++)
|
||||
{
|
||||
w_g[counter+j]=w_g[j]*2;
|
||||
}
|
||||
counter = counter*2;
|
||||
}
|
||||
|
||||
//Q_tilde_N_I = Q_N_I(n_PC+1:end); % This is what it says in TS 38.212
|
||||
int* Q_tilde_N_I = (int*) malloc(sizeof(int)*(Q_N_I_length-n_PC));
|
||||
if (Q_tilde_N_I == NULL)
|
||||
{
|
||||
fprintf(stderr, "malloc failed\n");
|
||||
exit(-1);
|
||||
}
|
||||
int* Q_tilde_N_I_flip = (int*) malloc(sizeof(int)*(Q_N_I_length-n_PC));
|
||||
if (Q_tilde_N_I_flip == NULL)
|
||||
{
|
||||
fprintf(stderr, "malloc failed\n");
|
||||
exit(-1);
|
||||
}
|
||||
for (i=0; i<Q_N_I_length-n_PC; i++)
|
||||
{
|
||||
Q_tilde_N_I[i]=Q_N_I[n_PC+i];
|
||||
//Q_tilde_N_I_flip = fliplr(Q_tilde_N_I);
|
||||
Q_tilde_N_I_flip[Q_N_I_length-n_PC-i-1] = Q_tilde_N_I[i];
|
||||
}
|
||||
//%Q_tilde_N_I = Q_N_I(n_PC-n_PC_wm+1:end); % I think that this would be slightly more elegant
|
||||
|
||||
//[w_g_sorted, indices] = sort(w_g(Q_tilde_N_I_flip));
|
||||
int* w_g_sorted = (int*) malloc(sizeof(int)*(Q_N_I_length-n_PC));
|
||||
if (w_g_sorted == NULL)
|
||||
{
|
||||
fprintf(stderr, "malloc failed\n");
|
||||
exit(-1);
|
||||
}
|
||||
int* indices = (int*) malloc(sizeof(int)*(Q_N_I_length-n_PC));
|
||||
if (indices == NULL)
|
||||
{
|
||||
fprintf(stderr, "malloc failed\n");
|
||||
exit(-1);
|
||||
}
|
||||
for (i=0; i<Q_N_I_length-n_PC; i++)
|
||||
{
|
||||
w_g_sorted[i]=w_g[Q_tilde_N_I_flip[i]-1]; // w_g(Q_tilde_N_I_flip), yet to sort
|
||||
indices[i] = i;
|
||||
}
|
||||
free(Q_tilde_N_I);
|
||||
free(w_g);
|
||||
|
||||
//bubble sort
|
||||
int tempToSwap=0;
|
||||
for (i = 0; i < (Q_N_I_length-n_PC)-1; i++)
|
||||
{
|
||||
for (j = 0; j < (Q_N_I_length-n_PC)-i-1; j++)
|
||||
{
|
||||
if (w_g_sorted[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<n_PC-n_PC_wm; i++)
|
||||
{
|
||||
Q_N_PC[i]=Q_N_I[i]; //Q_N_PC = [Q_N_I(1:n_PC-n_PC_wm), ...
|
||||
}
|
||||
free(Q_N_I);
|
||||
|
||||
for (i=0; i<n_PC_wm; i++)
|
||||
{
|
||||
Q_N_PC[n_PC-n_PC_wm+i] = Q_tilde_N_I_flip[indices[i]];//... Q_tilde_N_I_flip(indices(1:n_PC_wm))];
|
||||
}
|
||||
free(Q_tilde_N_I_flip);
|
||||
free(indices);
|
||||
|
||||
//PC_bit_pattern = false(1,N);
|
||||
//PC_bit_pattern(Q_N_PC) = true;
|
||||
*PC_bit_pattern = (uint8_t*) malloc(sizeof(uint8_t)*(Q_N_length));
|
||||
if (*PC_bit_pattern == NULL)
|
||||
{
|
||||
fprintf(stderr, "malloc failed\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
for (i=0; i<Q_N_length; i++)
|
||||
{
|
||||
(*PC_bit_pattern)[i]=0;
|
||||
for (j=0; j<n_PC; j++)
|
||||
{
|
||||
if (Q_N_PC[j]-1==i)
|
||||
{
|
||||
(*PC_bit_pattern)[i]=1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//free(Q_I);
|
||||
//free(Q_N_common);
|
||||
//free(Q_N_I);
|
||||
//free(w_g);
|
||||
//free(Q_tilde_N_I);
|
||||
//free(Q_tilde_N_I_flip);
|
||||
//free(w_g_sorted);
|
||||
//free(indices);
|
||||
free(Q_N_PC);
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <stdint.h>
|
||||
|
||||
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; i<A; i++)
|
||||
{
|
||||
(*G_P)[i] = (uint8_t *)malloc(P * sizeof(uint8_t));
|
||||
if ((*G_P)[i] == NULL)
|
||||
{
|
||||
fprintf(stderr, "malloc failed\n");
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
|
||||
if(A>0)
|
||||
{
|
||||
//G_P(end,:) = crc_polynomial_pattern(2:end);
|
||||
for(i=0; i<P; i++)
|
||||
{
|
||||
(*G_P)[A-1][i] = crc_polynomial_pattern[i+1];
|
||||
}
|
||||
|
||||
//for k = A-1:-1:1
|
||||
// G_P(k,:) = xor([G_P(k+1,2:end),0],G_P(k+1,1)*crc_polynomial_pattern(2:end));
|
||||
//end
|
||||
for(j=A-2; j>-1; j--)
|
||||
{
|
||||
for(i=0; i<P; i++)
|
||||
{
|
||||
(*G_P)[j][i]=0; //init with zeros
|
||||
}
|
||||
|
||||
for(i=1; i<P; i++)
|
||||
{
|
||||
if( (*G_P)[j+1][i] != ( (*G_P)[j+1][0])*crc_polynomial_pattern[i]) //xor
|
||||
(*G_P)[j][i-1]=1;
|
||||
}
|
||||
|
||||
if(0 != ( (*G_P)[j+1][0])*crc_polynomial_pattern[P]) //xor
|
||||
(*G_P)[j][P-1]=1;
|
||||
}
|
||||
}
|
||||
printf("G_P=\n");
|
||||
for(i=0; i<A; i++)
|
||||
{
|
||||
for(j=0; j<P; j++)
|
||||
{
|
||||
printf("%i ", (int)(*G_P)[i][j]);
|
||||
}
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
|
||||
#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<A; j++) //create the message to encode
|
||||
{
|
||||
//a[j]=rand()%2;
|
||||
a[j]=1; // ONLY ONES FOR TEST, otherwise random
|
||||
printf("%i", a[j]);
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
PUCCH_encoder(a, A, G, &E_r, &f);
|
||||
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
#include "PHY/CODING/nrPolar_tools/nr_polar_defs.h"
|
||||
|
||||
void nr_byte2bit(uint8_t *array, uint8_t arraySize, uint8_t *bitArray){//First 2 parameters are in bytes.
|
||||
|
||||
for (int i=0; i<arraySize; i++){
|
||||
bitArray[(7+(i*8))] = ( array[i]>>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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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 <stdio.h>
|
||||
|
||||
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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <stdint.h>
|
||||
|
||||
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<PC_circular_buffer_length; i++)
|
||||
{
|
||||
y[i]=0;
|
||||
}
|
||||
|
||||
int tempToShift;
|
||||
//for n=0:N-1
|
||||
printf("u = ");
|
||||
for(i=0; i<N; i++)
|
||||
{
|
||||
//y = [y(2:end),y(1)];
|
||||
tempToShift=y[0];
|
||||
for (j=0; j<PC_circular_buffer_length-1; j++)
|
||||
{
|
||||
y[j]=y[j+1];
|
||||
}
|
||||
y[PC_circular_buffer_length-1]=tempToShift;
|
||||
|
||||
//if info_bit_pattern(n+1)
|
||||
// if PC_bit_pattern(n+1)
|
||||
// u(n+1) = y(1);
|
||||
// else
|
||||
// u(n+1) = b(k+1);
|
||||
// k=k+1;
|
||||
// y(1) = xor(y(1),u(n+1));
|
||||
if (info_bit_pattern[i])
|
||||
{
|
||||
if (PC_bit_pattern[i])
|
||||
{
|
||||
u[i] = y[1];
|
||||
} else
|
||||
{
|
||||
u[i] = b[k];
|
||||
k++;
|
||||
y[1] = ( y[1]!=u[i]);
|
||||
}
|
||||
} else
|
||||
{
|
||||
u[i]=0;
|
||||
}
|
||||
printf("%i ", u[i]);
|
||||
}
|
||||
|
||||
free(y);
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
#include "PHY/CODING/nrPolar_tools/nr_polar_defs.h"
|
||||
|
||||
void nr_polar_channel_interleaver_pattern(uint16_t *cip, uint8_t I_BIL, uint16_t E){
|
||||
|
||||
if (I_BIL == 1) {
|
||||
uint16_t T=0, k;
|
||||
while( ((T/2)*(T+1)) < E ) T++;
|
||||
|
||||
|
||||
int16_t **v = malloc(T * sizeof(*v));
|
||||
for (int i = 0; i <= T-1; i++) v[i] = malloc((T-i) * sizeof(*(v[i])));
|
||||
|
||||
k=0;
|
||||
for (int i = 0; i <= T-1; i++) {
|
||||
for (int j = 0; j <= (T-1)-i; j++) {
|
||||
if (k<E) {
|
||||
v[i][j] = k;
|
||||
} else {
|
||||
v[i][j] = (-1);
|
||||
}
|
||||
k++;
|
||||
}
|
||||
}
|
||||
|
||||
k=0;
|
||||
for (int j = 0; j <= T-1; j++) {
|
||||
for (int i = 0; i <= (T-1)-j; i++) {
|
||||
if ( v[i][j] != (-1) ) {
|
||||
cip[k]=v[i][j];
|
||||
k++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i <= T-1; i++) free(v[i]);
|
||||
free(v);
|
||||
|
||||
} else {
|
||||
for (int i=0; i<=E-1; i++) cip[i]=i;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <stdint.h>
|
||||
|
||||
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<P; i++)
|
||||
{
|
||||
temp_b[i]=0;
|
||||
for(j=0; j<A; j++)
|
||||
{
|
||||
temp_b[i]=temp_b[i] + a[j]*G_P[j][i];
|
||||
}
|
||||
temp_b[i]=temp_b[i]%2;
|
||||
printf("%i ", temp_b[i]);
|
||||
}
|
||||
|
||||
*b = (uint8_t*) malloc(sizeof(uint8_t)*(A+P));
|
||||
if (*b == NULL)
|
||||
{
|
||||
fprintf(stderr, "malloc failed\n");
|
||||
exit(-1);
|
||||
}
|
||||
printf("\nb = ");
|
||||
for(i=0; i<A; i++)
|
||||
{
|
||||
(*b)[i]=a[i];
|
||||
printf("%i", (*b)[i]);
|
||||
}
|
||||
for(i=A; i<A+P; i++)
|
||||
{
|
||||
(*b)[i]=temp_b[i-A];
|
||||
printf("%i", (*b)[i]);
|
||||
}
|
||||
|
||||
free(temp_b);
|
||||
}
|
||||
@@ -0,0 +1,254 @@
|
||||
#include "PHY/CODING/nrPolar_tools/nr_polar_defs.h"
|
||||
#include "PHY/CODING/nrPolar_tools/nr_polar_pbch_defs.h"
|
||||
|
||||
/*
|
||||
* Return values:
|
||||
* 0 --> 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; i<polarParams->N; 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; i<polarParams->payloadBits; i++) {
|
||||
for (int j=0; j<polarParams->crcParityBits; j++) {
|
||||
tempECGM[i][j]=crc_generator_matrix[i][j];
|
||||
}
|
||||
}
|
||||
for (int i=polarParams->payloadBits; i<polarParams->K; i++) {
|
||||
for (int j=0; j<polarParams->crcParityBits; j++) {
|
||||
if( (i-polarParams->payloadBits) == j ){
|
||||
tempECGM[i][j]=1;
|
||||
} else {
|
||||
tempECGM[i][j]=0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int i=0; i<polarParams->K; i++) {
|
||||
for (int j=0; j<polarParams->crcParityBits; 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; j<polarParams->crcParityBits; j++) {
|
||||
for (int i=0; i<polarParams->K; 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; currentBit<polarParams->N; 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; i<currentListSize; i++) bit[currentBit][0][i]=1;
|
||||
bitUpdated[currentBit][0]=1;
|
||||
updateCrcChecksum(crcChecksum, extended_crc_generator_matrix, currentListSize, nonFrozenBit, polarParams->crcParityBits);
|
||||
} 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; i<polarParams->N; 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; i<polarParams->crcParityBits; 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);
|
||||
}
|
||||
@@ -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<listSize; i++) {
|
||||
if (( (row) % (2*offset) ) >= 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<listSize; i++) {
|
||||
if (( (row) % (2*offset) ) >= 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<listSize; i++) {
|
||||
if ((2*bitValue) != ( 1 - copysign(1.0,llr[row][0][i]) )) pathMetric[i] += fabs(llr[row][0][i]);
|
||||
}
|
||||
} else { //eq. (11b)
|
||||
int8_t multiplier = (2*bitValue) - 1;
|
||||
for (uint8_t i=0; i<listSize; i++) pathMetric[i] += log ( 1 + exp(multiplier*llr[row][0][i]) ) ;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void updatePathMetric2(double *pathMetric, double ***llr, uint8_t listSize, uint16_t row, uint8_t appr) {
|
||||
|
||||
double *tempPM = malloc(sizeof(double) * listSize);
|
||||
for (int i=0; i < listSize; i++) tempPM[i]=pathMetric[i];
|
||||
|
||||
uint8_t bitValue = 0;
|
||||
if (appr) { //eq. (12)
|
||||
for (uint8_t i = 0; i < listSize; i++) {
|
||||
if ((2 * bitValue) != (1 - copysign(1.0, llr[row][0][i]))) pathMetric[i] += fabs(llr[row][0][i]);
|
||||
}
|
||||
} else { //eq. (11b)
|
||||
int8_t multiplier = (2 * bitValue) - 1;
|
||||
for (uint8_t i = 0; i < listSize; i++) pathMetric[i] += log(1 + exp(multiplier * llr[row][0][i]));
|
||||
}
|
||||
|
||||
bitValue = 1;
|
||||
if (appr) { //eq. (12)
|
||||
for (uint8_t i = listSize; i < 2*listSize; i++) {
|
||||
if ((2 * bitValue) != (1 - copysign(1.0, llr[row][0][(i-listSize)]))) pathMetric[i] = tempPM[(i-listSize)] + fabs(llr[row][0][(i-listSize)]);
|
||||
}
|
||||
} else { //eq. (11b)
|
||||
int8_t multiplier = (2 * bitValue) - 1;
|
||||
for (uint8_t i = listSize; i < 2*listSize; i++) pathMetric[i] = tempPM[(i-listSize)] + log(1 + exp(multiplier * llr[row][0][(i-listSize)]));
|
||||
}
|
||||
|
||||
free(tempPM);
|
||||
|
||||
}
|
||||
|
||||
void computeLLR(double ***llr, uint16_t row, uint16_t col, uint8_t i,
|
||||
uint16_t offset, uint8_t approximation) {
|
||||
|
||||
double a = llr[row][col + 1][i];
|
||||
double absA = fabs(a);
|
||||
double b = llr[row + offset][col + 1][i];
|
||||
double absB = fabs(b);
|
||||
|
||||
if (approximation || isinf(absA) || isinf(absB)) { //eq. (9)
|
||||
llr[row][col][i] = copysign(1.0, a) * copysign(1.0, b) * fmin(absA, absB);
|
||||
} else { //eq. (8a)
|
||||
llr[row][col][i] = log((exp(a + b) + 1) / (exp(a) + exp(b)));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void updateCrcChecksum(uint8_t **crcChecksum, uint8_t **crcGen,
|
||||
uint8_t listSize, uint32_t i2, uint8_t len) {
|
||||
for (uint8_t i = 0; i < listSize; i++) {
|
||||
for (uint8_t j = 0; j < len; j++) {
|
||||
crcChecksum[j][i] = ( (crcChecksum[j][i] + crcGen[i2][j]) % 2 );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void updateCrcChecksum2(uint8_t **crcChecksum, uint8_t **crcGen,
|
||||
uint8_t listSize, uint32_t i2, uint8_t len) {
|
||||
for (uint8_t i = 0; i < listSize; i++) {
|
||||
for (uint8_t j = 0; j < len; j++) {
|
||||
crcChecksum[j][i+listSize] = ( (crcChecksum[j][i] + crcGen[i2][j]) % 2 );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
#ifndef __NR_POLAR_DEFS__H__
|
||||
#define __NR_POLAR_DEFS__H__
|
||||
|
||||
#include <math.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
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
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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++;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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<size; i++) output[i]=input[pattern[i]];
|
||||
}
|
||||
|
||||
void nr_polar_deinterleaver(uint8_t *input, uint8_t *output, uint16_t *pattern, uint16_t size) {
|
||||
for (int i=0; i<size; i++) output[pattern[i]]=input[i];
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
#include <stdint.h>
|
||||
|
||||
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<N; i++)
|
||||
{
|
||||
d[i]=0;
|
||||
for(j=0; j<N; j++)
|
||||
{
|
||||
d[i]=d[i]+(( (j-i)& i )==0)*u[j];
|
||||
}
|
||||
d[i]=d[i]%2;
|
||||
|
||||
printf("%i", d[i]);
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,160 @@
|
||||
#include "PHY/CODING/nrPolar_tools/nr_polar_defs.h"
|
||||
|
||||
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) {
|
||||
|
||||
for (uint16_t i = 0; i < col; i++) {
|
||||
output[i] = 0;
|
||||
for (uint16_t j = 0; j < row; j++) {
|
||||
output[i] += matrix1[j] * matrix2[j][i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t ***nr_alloc_uint8_t_3D_array(uint16_t xlen, uint16_t ylen, uint16_t zlen) {
|
||||
uint8_t ***output;
|
||||
int i, j;
|
||||
|
||||
if ((output = malloc(xlen * sizeof(*output))) == NULL) {
|
||||
perror("[nr_alloc_uint8_t_3D_array] Problem at 1D allocation");
|
||||
return NULL;
|
||||
}
|
||||
for (i = 0; i < xlen; i++)
|
||||
output[i] = NULL;
|
||||
|
||||
|
||||
for (i = 0; i < xlen; i++)
|
||||
if ((output[i] = malloc(ylen * sizeof *output[i])) == NULL) {
|
||||
perror("[nr_alloc_uint8_t_3D_array] Problem at 2D allocation");
|
||||
nr_free_uint8_t_3D_array(output, xlen, ylen);
|
||||
return NULL;
|
||||
}
|
||||
for (i = 0; i < xlen; i++)
|
||||
for (j = 0; j < ylen; j++)
|
||||
output[i][j] = NULL;
|
||||
|
||||
|
||||
for (i = 0; i < xlen; i++)
|
||||
for (j = 0; j < ylen; j++)
|
||||
if ((output[i][j] = malloc(zlen * sizeof *output[i][j])) == NULL) {
|
||||
perror("[nr_alloc_uint8_t_3D_array] Problem at 3D allocation");
|
||||
nr_free_uint8_t_3D_array(output, xlen, ylen);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
double ***nr_alloc_double_3D_array(uint16_t xlen, uint16_t ylen, uint16_t zlen) {
|
||||
double ***output;
|
||||
int i, j;
|
||||
|
||||
if ((output = malloc(xlen * sizeof(*output))) == NULL) {
|
||||
perror("[nr_alloc_double_3D_array] Problem at 1D allocation");
|
||||
return NULL;
|
||||
}
|
||||
for (i = 0; i < xlen; i++)
|
||||
output[i] = NULL;
|
||||
|
||||
|
||||
for (i = 0; i < xlen; i++)
|
||||
if ((output[i] = malloc(ylen * sizeof *output[i])) == NULL) {
|
||||
perror("[nr_alloc_double_3D_array] Problem at 2D allocation");
|
||||
nr_free_double_3D_array(output, xlen, ylen);
|
||||
return NULL;
|
||||
}
|
||||
for (i = 0; i < xlen; i++)
|
||||
for (j = 0; j < ylen; j++)
|
||||
output[i][j] = NULL;
|
||||
|
||||
|
||||
for (i = 0; i < xlen; i++)
|
||||
for (j = 0; j < ylen; j++)
|
||||
if ((output[i][j] = malloc(zlen * sizeof *output[i][j])) == NULL) {
|
||||
perror("[nr_alloc_double_3D_array] Problem at 3D allocation");
|
||||
nr_free_double_3D_array(output, xlen, ylen);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
uint8_t **nr_alloc_uint8_t_2D_array(uint16_t xlen, uint16_t ylen) {
|
||||
uint8_t **output;
|
||||
int i, j;
|
||||
|
||||
if ((output = malloc(xlen * sizeof(*output))) == NULL) {
|
||||
perror("[nr_alloc_uint8_t_2D_array] Problem at 1D allocation");
|
||||
return NULL;
|
||||
}
|
||||
for (i = 0; i < xlen; i++)
|
||||
output[i] = NULL;
|
||||
|
||||
|
||||
for (i = 0; i < xlen; i++)
|
||||
if ((output[i] = malloc(ylen * sizeof *output[i])) == NULL) {
|
||||
perror("[nr_alloc_uint8_t_2D_array] Problem at 2D allocation");
|
||||
nr_free_uint8_t_2D_array(output, xlen);
|
||||
return NULL;
|
||||
}
|
||||
for (i = 0; i < xlen; i++)
|
||||
for (j = 0; j < ylen; j++)
|
||||
output[i][j] = 0;
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
void nr_free_uint8_t_3D_array(uint8_t ***input, uint16_t xlen, uint16_t ylen) {
|
||||
int i, j;
|
||||
|
||||
for (i = 0; i < xlen; i++) {
|
||||
for (j = 0; j < ylen; j++) {
|
||||
free(input[i][j]);
|
||||
}
|
||||
free(input[i]);
|
||||
}
|
||||
free(input);
|
||||
}
|
||||
|
||||
void nr_free_uint8_t_2D_array(uint8_t **input, uint16_t xlen) {
|
||||
for (int i = 0; i < xlen; i++) free(input[i]);
|
||||
free(input);
|
||||
}
|
||||
|
||||
void nr_free_double_3D_array(double ***input, uint16_t xlen, uint16_t ylen) {
|
||||
int i, j;
|
||||
|
||||
for (i = 0; i < xlen; i++) {
|
||||
for (j = 0; j < ylen; j++) {
|
||||
free(input[i][j]);
|
||||
}
|
||||
free(input[i]);
|
||||
}
|
||||
free(input);
|
||||
}
|
||||
|
||||
// Modified Bubble Sort.
|
||||
void nr_sort_asc_double_1D_array_ind(double *matrix, uint8_t *ind, uint8_t len) {
|
||||
uint8_t swaps;
|
||||
double temp;
|
||||
uint8_t tempInd;
|
||||
|
||||
for (uint8_t i = 0; i < len; i++) {
|
||||
swaps = 0;
|
||||
for (uint8_t j = 0; j < (len - i) - 1; j++) {
|
||||
if (matrix[j] > 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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
#include <math.h>
|
||||
#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 (n<n_min) n=n_min;
|
||||
|
||||
polar_code_output_length = (uint32_t) pow(2.0,n);
|
||||
|
||||
return polar_code_output_length;
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Defines the constant variables for polar coding of the PBCH.
|
||||
*/
|
||||
|
||||
#ifndef __NR_POLAR_PBCH_DEFS__H__
|
||||
#define __NR_POLAR_PBCH_DEFS__H__
|
||||
|
||||
|
||||
#define NR_POLAR_PBCH_PAYLOAD_BITS 32 //uint16_t
|
||||
#define NR_POLAR_PBCH_CRC_PARITY_BITS 24
|
||||
#define NR_POLAR_PBCH_CRC_ERROR_CORRECTION_BITS 3
|
||||
//Assumed 3 by 3GPP when NR_POLAR_PBCH_L>8 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
|
||||
@@ -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
|
||||
@@ -0,0 +1,64 @@
|
||||
#include <math.h>
|
||||
#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<size; i++) output[i]=input[pattern[i]];
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,310 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <math.h>
|
||||
|
||||
#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<N; i++) {
|
||||
printf("%i ", Q_0_Nminus1[i]);
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
// Get the channel interleaving pattern
|
||||
uint16_t *channel_interleaver_pattern = malloc(sizeof(uint16_t) * *E_r);
|
||||
nr_polar_coding_channel_interleaver_pattern(channel_interleaver_pattern, 1, *E_r);
|
||||
printf("DEBUG: The channel interleaver pattern is " );
|
||||
for (i=0; i<*E_r; i++) {
|
||||
printf("%i ", (int)channel_interleaver_pattern[i]);
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
uint16_t n_PC; //PC bits
|
||||
uint8_t* info_bit_pattern;
|
||||
uint8_t** G_P;
|
||||
uint8_t* b;
|
||||
uint8_t* u;
|
||||
uint8_t* d;
|
||||
uint8_t* e;
|
||||
|
||||
if (A <= 19) // Use PCCA-polar
|
||||
{
|
||||
n_PC = 3; // 3 PC bits
|
||||
|
||||
// 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<N; i++) {
|
||||
printf("%i", (int)info_bit_pattern[i] );
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
//Get a PC bit pattern.
|
||||
uint8_t* PC_bit_pattern;
|
||||
if (G-K+3 > 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<N; i++) {
|
||||
printf("%i", PC_bit_pattern[i] );
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
/// ------------------
|
||||
|
||||
//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);
|
||||
}
|
||||
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<N; i++) {
|
||||
printf("%i", (int)info_bit_pattern[i] );
|
||||
}
|
||||
printf("\n");
|
||||
|
||||
if (C == 2)
|
||||
{
|
||||
//info_bit_pattern2 = info_bit_pattern;
|
||||
uint8_t* info_bit_pattern2;
|
||||
if(A%2) // Prepend a zero to the first segment during encoding (Treat the first information bit as a frozen bit)
|
||||
{
|
||||
info_bit_pattern2 = (uint8_t*)malloc(sizeof(uint8_t)*(1+N));
|
||||
info_bit_pattern2[0] =0;
|
||||
|
||||
for (i=0; i<1+N; i++)
|
||||
{
|
||||
info_bit_pattern2[i+1] = info_bit_pattern[i];
|
||||
}
|
||||
} else
|
||||
{
|
||||
info_bit_pattern2 = (uint8_t*)malloc(sizeof(uint8_t)*N);
|
||||
|
||||
for (i=0; i<N; i++)
|
||||
{
|
||||
info_bit_pattern2[i] = info_bit_pattern[i];
|
||||
}
|
||||
}
|
||||
|
||||
//Attach CRC to the Transport Block. (a to b)
|
||||
get_crc_generator_matrix(A/C, crc_polynomial_pattern_length-1, crc_polynomial_pattern, &G_P); // -> 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<N; i++)
|
||||
{
|
||||
if(info_bit_pattern[i])
|
||||
{
|
||||
u[i]=b[j];
|
||||
j++;
|
||||
}
|
||||
else
|
||||
u[i]=0;
|
||||
|
||||
printf("%i ", u[i]);
|
||||
}
|
||||
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 ");
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
//
|
||||
// free(crc_polynomial_pattern);
|
||||
// //free others...
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user