Skip to content
Snippets Groups Projects
Commit 5cf8d93a authored by Guy De Souza's avatar Guy De Souza
Browse files

NR Polar imports

parent 313cab3d
No related branches found
No related tags found
No related merge requests found
Showing
with 2104 additions and 0 deletions
#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 (&currentTime);
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(&currentTime));
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);
}
#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);
}
#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);
}
#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);
}
#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");
}
}
#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;
}
#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);
}
}
#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
#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;
}
}
}
}
#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);
}
#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;
}
}
#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);
}
#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);
}
#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 );
}
}
}
#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
#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);
}
#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++;
}
}
}
#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];
}
#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]);
}
}
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment