Commit 0ce5fa6f authored by Florian Kaltenberger's avatar Florian Kaltenberger

removing unnecessary header files and autosave files

moving ldpc_encoder to PHY/CODING
input and output buffers to ldpc_decoding are now allocated outside ldpc_decoding
parent 86d01419
......@@ -1038,6 +1038,7 @@ set(PHY_SRC
${OPENAIR1_DIR}/PHY/CODING/3gpplte_sse.c
${OPENAIR1_DIR}/PHY/CODING/crc_byte.c
${OPENAIR1_DIR}/PHY/CODING/ldpc_decoder.c
${OPENAIR1_DIR}/PHY/CODING/ldpc_encoder.c
${OPENAIR1_DIR}/PHY/CODING/3gpplte_turbo_decoder_sse_8bit.c
${OPENAIR1_DIR}/PHY/CODING/3gpplte_turbo_decoder_sse_16bit.c
${OPENAIR1_DIR}/PHY/CODING/3gpplte_turbo_decoder_avx2_16bit.c
......
#include <stdlib.h>
#include <math.h>
#include <stdio.h>
#include <string.h>
short *ldpc_encoder_header(short *test_input,short block_length,double rate)
{
short *c; //padded codeword
short *channel_input; //output sequence
short *Gen_shift_values, *no_shift_values, *pointer_shift_values;
short BG,Zc,Kb,nrows,ncols,channel_temp;
int i1,i2,i3,i4,i5,t,temp,temp_prime;
int no_punctured_columns;
//Table of possible lifting sizes
short lift_size[51]={2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,20,22,24,26,28,30,32,36,40,44,48,52,56,60,64,72,80,88,96,104,112,120,128,144,160,176,192,208,224,240,256,288,320,352,384};
//determine number of bits in codeword
if (block_length>3840)
{
BG=1;
Kb = 22;
nrows=46; //parity check bits
ncols=22; //info bits
}
else if (block_length<=3840)
{
BG=2;
nrows=42; //parity check bits
ncols=10; // info bits
if (block_length>640)
Kb = 10;
else if (block_length>560)
Kb = 9;
else if (block_length>192)
Kb = 8;
else
Kb = 6;
}
//find minimum value in all sets of lifting size
for (i1=0; i1 < 51; i1++)
{
if (lift_size[i1] >= (double) block_length/Kb)
{
Zc = lift_size[i1];
//printf("%d\n",Zc);
break;
}
}
// load base graph of generator matrix
if (BG==1)
{
no_shift_values=(short*) no_shift_values_BG1;
pointer_shift_values=(short*) pointer_shift_values_BG1;
}
else if (BG==2)
{
no_shift_values=(short*) no_shift_values_BG2;
pointer_shift_values=(short*) pointer_shift_values_BG2;
}
Gen_shift_values=choose_generator_matrix(BG,Zc);
no_punctured_columns=(int)((nrows+Kb-2)*Zc-block_length/rate)/Zc;
//printf("%d\n",no_punctured_columns);
//padded input sequence
c=(short *)malloc(sizeof(short) * Kb * Zc);
channel_input = (short *)malloc( (Kb+nrows-no_punctured_columns) * Zc *sizeof(short));
memset(c,0,sizeof(short) * Kb * Zc);
memcpy(c,test_input,block_length * sizeof(short));
// parity check part
for (i2=0; i2 < Zc; i2++)
{
t=Kb*Zc+i2;
//rotate matrix here
for (i5=0; i5 < Kb; i5++)
{
temp = c[i5*Zc];
memmove(&c[i5*Zc], &c[i5*Zc+1], (Zc-1)*sizeof(short));
c[i5*Zc+Zc-1] = temp;
}
// calculate each row in base graph
for (i1=0; i1 < nrows-no_punctured_columns; i1++)
{
channel_temp=0;
for (i3=0; i3 < Kb; i3++)
{
temp_prime=i1 * ncols + i3;
for (i4=0; i4 < no_shift_values[temp_prime]; i4++)
{
channel_temp = channel_temp ^ c[ i3*Zc + Gen_shift_values[ pointer_shift_values[temp_prime]+i4 ] ];
}
}
channel_input[t+i1*Zc]=channel_temp;
}
}
// information part
memcpy(channel_input,c,Kb*Zc*sizeof(short));
return channel_input;
}
short *ldpc_encoder_header(short *test_input,short block_length,double rate)
{
short *c; //padded codeword
short *channel_input; //output sequence
short *Gen_shift_values, *no_shift_values, *pointer_shift_values;
short BG,Zc,Kb,nrows,ncols,channel_temp;
int i1,i2,i3,i4,i5,t,temp,temp_prime;
int no_punctured_columns;
//Table of possible lifting sizes
short lift_size[51]={2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,20,22,24,26,28,30,32,36,40,44,48,52,56,60,64,72,80,88,96,104,112,120,128,144,160,176,192,208,224,240,256,288,320,352,384};
//determine number of bits in codeword
if (block_length>3840)
{
BG=1;
Kb = 22;
nrows=46; //parity check bits
ncols=22; //info bits
}
else if (block_length<=3840)
{
BG=2;
nrows=42; //parity check bits
ncols=10; // info bits
if (block_length>640)
Kb = 10;
else if (block_length>560)
Kb = 9;
else if (block_length>192)
Kb = 8;
else
Kb = 6;
}
//find minimum value in all sets of lifting size
for (i1=0; i1 < 51; i1++)
{
if (lift_size[i1] >= (double) block_length/Kb)
{
Zc = lift_size[i1];
//printf("%d\n",Zc);
break;
}
}
// load base graph of generator matrix
if (BG==1)
{
no_shift_values=(short*) no_shift_values_BG1;
pointer_shift_values=(short*) pointer_shift_values_BG1;
}
else if (BG==2)
{
no_shift_values=(short*) no_shift_values_BG2;
pointer_shift_values=(short*) pointer_shift_values_BG2;
}
Gen_shift_values=choose_generator_matrix(BG,Zc);
no_punctured_columns=(int)((nrows+Kb-2)*Zc-block_length/rate)/Zc;
//printf("%d\n",no_punctured_columns);
//padded input sequence
c=(short *)malloc(sizeof(short) * Kb * Zc);
channel_input = (short *)malloc( (Kb+nrows-no_punctured_columns) * Zc *sizeof(short));
memset(c,0,sizeof(short) * Kb * Zc);
memcpy(c,test_input,block_length * sizeof(short));
// parity check part
for (i2=0; i2 < Zc; i2++)
{
t=Kb*Zc+i2;
//rotate matrix here
for (i5=0; i5 < Kb; i5++)
{
temp = c[i5*Zc];
memmove(&c[i5*Zc], &c[i5*Zc+1], (Zc-1)*sizeof(short));
c[i5*Zc+Zc-1] = temp;
}
// calculate each row in base graph
for (i1=0; i1 < nrows-no_punctured_columns; i1++)
{
channel_temp=0;
for (i3=0; i3 < Kb; i3++)
{
temp_prime=i1 * ncols + i3;
for (i4=0; i4 < no_shift_values[temp_prime]; i4++)
{
channel_temp = channel_temp ^ c[ i3*Zc + Gen_shift_values[ pointer_shift_values[temp_prime]+i4 ] ];
}
}
channel_input[t+i1*Zc]=channel_temp;
}
}
// information part
memcpy(channel_input,c,Kb*Zc*sizeof(short));
return channel_input;
}
short *ldpc_encoder_header(short *test_input,short block_length,double rate)
{
short *c; //padded codeword
short *channel_input; //output sequence
short *Gen_shift_values, *no_shift_values, *pointer_shift_values;
short BG,Zc,Kb,nrows,ncols,channel_temp;
int i1,i2,i3,i4,i5,t,temp,temp_prime;
int no_punctured_columns;
//Table of possible lifting sizes
short lift_size[51]={2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,20,22,24,26,28,30,32,36,40,44,48,52,56,60,64,72,80,88,96,104,112,120,128,144,160,176,192,208,224,240,256,288,320,352,384};
//determine number of bits in codeword
if (block_length>3840)
{
BG=1;
Kb = 22;
nrows=46; //parity check bits
ncols=22; //info bits
}
else if (block_length<=3840)
{
BG=2;
nrows=42; //parity check bits
ncols=10; // info bits
if (block_length>640)
Kb = 10;
else if (block_length>560)
Kb = 9;
else if (block_length>192)
Kb = 8;
else
Kb = 6;
}
//find minimum value in all sets of lifting size
for (i1=0; i1 < 51; i1++)
{
if (lift_size[i1] >= (double) block_length/Kb)
{
Zc = lift_size[i1];
printf("%d\n",Zc);
break;
}
}
// load base graph of generator matrix
if (BG==1)
{
no_shift_values=(short*) no_shift_values_BG1;
pointer_shift_values=(short*) pointer_shift_values_BG1;
}
else if (BG==2)
{
no_shift_values=(short*) no_shift_values_BG2;
pointer_shift_values=(short*) pointer_shift_values_BG2;
}
Gen_shift_values=choose_generator_matrix(BG,Zc);
no_punctured_columns=(int)((nrows+Kb-2)*Zc-block_length/rate)/Zc;
printf("%d\n",no_punctured_columns);
//padded input sequence
c=(short *)malloc(sizeof(short) * Kb * Zc);
channel_input = (short *)malloc( (Kb+nrows-no_punctured_columns) * Zc *sizeof(short));
memset(c,0,sizeof(short) * Kb * Zc);
memcpy(c,test_input,block_length * sizeof(short));
// parity check part
for (i2=0; i2 < Zc; i2++)
{
t=Kb*Zc+i2;
//rotate matrix here
for (i5=0; i5 < Kb; i5++)
{
temp = c[i5*Zc];
memmove(&c[i5*Zc], &c[i5*Zc+1], (Zc-1)*sizeof(short));
c[i5*Zc+Zc-1] = temp;
}
// calculate each row in base graph
for (i1=0; i1 < nrows-no_punctured_columns; i1++)
{
channel_temp=0;
for (i3=0; i3 < Kb; i3++)
{
temp_prime=i1 * ncols + i3;
for (i4=0; i4 < no_shift_values[temp_prime]; i4++)
{
channel_temp = channel_temp ^ c[ i3*Zc + Gen_shift_values[ pointer_shift_values[temp_prime]+i4 ] ];
}
}
channel_input[t+i1*Zc]=channel_temp;
}
}
// information part
memcpy(channel_input,c,Kb*Zc*sizeof(short));
return channel_input;
}
......@@ -26,10 +26,6 @@
#include "SIMULATION/TOOLS/defs.h"
#include "Gen_shift_value.h"
#include "choose_generator_matrix.h"
#include "ldpc_encoder_header.h"
// 4-bit quantizer
char quantize4bit(double D,double x)
{
......@@ -84,10 +80,10 @@ int test_ldpc(short No_iteration,
cpu_freq_GHz = get_cpu_freq_GHz();
//short test_input[block_length];
short *test_input;
char *test_input;
//short *c; //padded codeword
short *esimated_output;
short *channel_input;
char *channel_input;
double *channel_output;
double *modulated_input;
short *channel_output_fixed;
......@@ -104,13 +100,15 @@ int no_punctured_columns; //new
*errors=0;
*crc_misses=0;
// generate input block
test_input=(char*)malloc(sizeof(char) * block_length/8);
channel_input = (char*)malloc(sizeof(char) * 68*384/8);
while (trial++ < ntrials)
{
// generate input block
test_input=(short*)malloc(sizeof(short) * block_length);
for (i=0; i<block_length; i++)
for (i=0; i<block_length/8; i++)
{
test_input[i]=rand()%2;
test_input[i]=(char) rand();
//test_input[i]=i%2;
}
......@@ -150,12 +148,12 @@ int no_punctured_columns; //new
}
no_punctured_columns=(int)((nrows+Kb-2)*Zc-block_length/rate)/Zc;
//printf("%d\n",no_punctured_columns);
//printf("%d\n",no_punctured_columns);
*/
start_meas(&time);
//// encoder
channel_input=ldpc_encoder_header(test_input, block_length,rate);
ldpc_encoder(test_input, channel_input,block_length,rate);
stop_meas(&time);
print_meas_now(&time, "", stdout);
......@@ -193,6 +191,7 @@ int no_punctured_columns; //new
printf("\n");
exit(-1);
#endif
*/
/*
// decode the sequence
esimated_output=ldpc_decoder(channel_output_fixed, block_length, No_iteration, rate);
......
/*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The OpenAirInterface Software Alliance licenses this file to You under
* the OAI Public License, Version 1.0 (the "License"); you may not use this file
* except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.openairinterface.org/?page_id=698
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*-------------------------------------------------------------------------------
* For more information about the OpenAirInterface (OAI) Software Alliance:
* contact@openairinterface.org
*/
#include <stdlib.h>
#include <math.h>
#include <stdio.h>
#include <string.h>
#include "SIMULATION/TOOLS/defs.h"
#include "Gen_shift_value.h"
#include "choose_generator_matrix.h"
#include "ldpc_encoder_header.h"
// 4-bit quantizer
char quantize4bit(double D,double x)
{
double qxd;
qxd = floor(x/D);
// printf("x=%f,qxd=%f\n",x,qxd);
if (qxd <= -8)
qxd = -8;
else if (qxd > 7)
qxd = 7;
return((char)qxd);
}
char quantize(double D,double x,unsigned char B)
{
double qxd;
char maxlev;
qxd = floor(x/D);
// printf("x=%f,qxd=%f\n",x,qxd);
maxlev = 1<<(B-1);
if (qxd <= -maxlev)
qxd = -maxlev;
else if (qxd >= maxlev)
qxd = maxlev-1;
return((char)qxd);
}
#define MAX_BLOCK_LENGTH 8448
int test_ldpc(short No_iteration,
double rate,
double SNR,
unsigned char qbits,
short block_length,
unsigned int ntrials,
unsigned int *errors,
unsigned int *crc_misses)
{
//clock initiate
time_stats_t time;
opp_enabled=1;
cpu_freq_GHz = get_cpu_freq_GHz();
//short test_input[block_length];
short *test_input;
//short *c; //padded codeword
short *esimated_output;
short *channel_input;
double *channel_output;
double *modulated_input;
short *channel_output_fixed;
unsigned int i,trial=0;
/*
short *Gen_shift_values, *no_shift_values, *pointer_shift_values;
short BG,Zc,Kb,nrows,ncols,channel_temp;
int i1,i2,i3,i4,i5,i6,t,temp,temp_prime,k;
int no_punctured_columns; //new
//Table of possible lifting sizes
short lift_size[51]={2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,20,22,24,26,28,30,32,36,40,44,48,52,56,60,64,72,80,88,96,104,112,120,128,144,160,176,192,208,224,240,256,288,320,352,384};
*/
*errors=0;
*crc_misses=0;
while (trial++ < ntrials)
{
// generate input block
test_input=(short*)malloc(sizeof(short) * block_length);
for (i=0; i<block_length; i++)
{
test_input[i]=rand()%2;
//test_input[i]=i%2;
}
/*
//determine number of bits in codeword
if (block_length>3840)
{
BG=1;
Kb = 22;
nrows=46; //parity check bits
ncols=22; //info bits
}
else if (block_length<=3840)
{
BG=2;
nrows=42; //parity check bits
ncols=10; // info bits
if (block_length>640)
Kb = 10;
else if (block_length>560)
Kb = 9;
else if (block_length>192)
Kb = 8;
else
Kb = 6;
}
//find minimum value in all sets of lifting size
for (i1=0; i1 < 51; i1++)
{
if (lift_size[i1] >= (double) block_length/Kb)
{
Zc = lift_size[i1];
// printf("%d\n",Zc);
break;
}
}
no_punctured_columns=(int)((nrows+Kb-2)*Zc-block_length/rate)/Zc;
//printf("%d\n",no_punctured_columns);
*/
start_meas(&time);
//// encoder
channel_input=ldpc_encoder_header(test_input, block_length,rate);
stop_meas(&time);
print_meas_now(&time, "", stdout);
//for (i=0;i<10;i++)
//printf("channel_input[%d]=%d test_input[%d]=%d\n",i,channel_input[i],i,test_input[i]);
/*
//channel
modulated_input = (double *)malloc( (Kb+nrows) * Zc*sizeof(double));
channel_output = (double *)malloc( (Kb+nrows) * Zc*sizeof(double));
channel_output_fixed = (short *)malloc( (Kb+nrows) * Zc*sizeof(short));
memset(channel_output_fixed,0,(Kb+nrows) * Zc*sizeof(short));
for (i = 2*Zc; i < (Kb+nrows) * Zc; i++)
{
#ifdef DEBUG_CODER
if ((i&0xf)==0)
printf("\ne %d..%d: ",i,i+15);
#endif
if (channel_input[i]==0)
modulated_input[i]=1/sqrt(2); //QPSK
else
modulated_input[i]=-1/sqrt(2);
channel_output[i] = modulated_input[i] + gaussdouble(0.0,1.0) * 1/sqrt(2*SNR);
channel_output_fixed[i] = (short) ((channel_output[i]*128)<0?(channel_output[i]*128-0.5):(channel_output[i]*128+0.5)); //fixed point 9-7
}
//for (i=(Kb+nrows) * Zc-5;i<(Kb+nrows) * Zc;i++)
//{
// printf("channel_input[%d]=%d\n",i,channel_input[i]);
//printf("%lf %d\n",channel_output[i], channel_output_fixed[i]);
//printf("v[%d]=%lf\n",i,modulated_input[i]);}
#ifdef DEBUG_CODER
printf("\n");
exit(-1);
#endif
/*
// decode the sequence
esimated_output=ldpc_decoder(channel_output_fixed, block_length, No_iteration, rate);
//for (i=(Kb+nrows) * Zc-5;i<(Kb+nrows) * Zc;i++)
// printf("esimated_output[%d]=%d\n",i,esimated_output[i]);
//count errors
for (i=0;i<(Kb+nrows) * Zc;i++)
{
if (esimated_output[i] != channel_input[i])
{
*errors = (*errors) + 1;
break;
}
}
free(channel_input);
free(modulated_input);
free(channel_output);
free(channel_output_fixed);
*/
}
return *errors;
}
//#define NTRIALS 10000
#define NTRIALS 30
int main(int argc, char *argv[])
{
unsigned int errors,crc_misses;
short block_length=22*384;
short No_iteration=25;
double rate=0.667;
double SNR,SNR_lin;
unsigned char qbits;
int i=0;
randominit(0);
if (argc>1)
qbits = atoi(argv[1]);
else
qbits = 4;
unsigned int decoded_errors[100]; // initiate the size of matrix equivalent to size of SNR
for (SNR=-2.1; SNR<-2; SNR+=.1)
{
SNR_lin = pow(10,SNR/10);
decoded_errors[i]=test_ldpc(No_iteration,
rate,
SNR_lin, // noise standard deviation
qbits,
block_length, // block length bytes
NTRIALS,
&errors,
&crc_misses);
printf("SNR %f, BLER %f (%d/%d)\n",SNR,(float)decoded_errors[i]/(float)NTRIALS,decoded_errors[i],NTRIALS);
i=i+1;
}
return(0);
}
short sign(short x) {
return (x > 0) - (x < 0);
}
short *ldpc_decoder(short *msgChannel,short block_length,short No_iteration,double rate) {
// input
//short No_iteration;
//int *shift_value, *Col_position, *no_one_element, Z, BG,Kb;
//double rate;
//output
//char *output_estimate;
short *v_estimate; //estimated codeword
//variables
//int *shift_value, *Col_position, *no_one_element, Zc, BG,Kb;
int Zc, BG,Kb;
int nrows, ncols, nEdge_base_graph;
int irow, iShift, iZ,p1,p2,t1,temp_row,temp_col,iBit,iEdge;
int nEdge,nCheck,nBit;
int rows_total_La1=0,rows_total_La2=0,rows_total_La3=0,*no_rows_La1, *no_rows_La2, *no_rows_La3;
int i1, i2, i3, sum, sum1, sum2, no_punctured_columns, layer, iLayer, n=1, flag=0;
int *idxBit, idxCheck,*degBit, *degCheck,*degBit_base_graph, *pointerCheck, *pointerBit, *pointerCheck_temp, *pointerBit_temp;
int *idxEdge2Bit,*idxEdge2Check;
int *no_rows;
int rows_total;
short *msgBit2Check, *msgCheck2Bit, *msgBit; //variables for message passing algorithm
short mini;
short sgn;
int isEqual;
char syn; //syndrome
short lift_size[51]={2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,20,22,24,26,28,30,32,36,40,44,48,52,56,60,64,72,80,88,96,104,112,120,128,144,160,176,192,208,224,240,256,288,320,352,384};
short shift_value[197]={9,117,204,26,189,205,0,0,167,166,253,125,226,156,224,252,0,0,81,114,44,52,240,1,0,0,8,58,158,104,209,54,18,128,0,0,179,214,71,0,231,41,194,159,103,0,155,228,45,28,158,0,129,147,140,3,116,0,142,94,230,0,203,205,61,247,0,11,185,0,117,0,11,236,210,56,0,63,111,14,0,83,2,38,222,0,115,145,3,232,0,51,175,213,0,203,142,8,242,0,254,124,114,64,0,220,194,50,0,87,20,185,0,26,105,29,0,76,42,210,0,222,63,0,23,235,238,0,46,139,8,0,228,156,0,29,143,160,122,0,8,151,0,98,101,135,0,18,28,0,71,240,9,84,0,106,1,0,242,44,166,0,132,164,235,0,147,85,36,0,57,40,63,0,140,38,154,0,219,151,0,31,66,38,0,239,172,34,0,0,75,120,0,129,229,118,0};
short Col_position[197]={0,1,2,3,6,9,10,11,0,3,4,5,6,7,8,9,11,12,0,1,3,4,8,10,12,13,1,2,4,5,6,7,8,9,10,13,0,1,11,14,0,1,5,7,11,15,0,5,7,9,11,16,1,5,7,11,13,17,0,1,12,18,1,8,10,11,19,0,1,6,7,20,0,7,9,13,21,1,3,11,22,0,1,8,13,23,1,6,11,13,24,0,10,11,25,1,9,11,12,26,1,5,11,12,27,0,6,7,28,0,1,10,29,1,4,11,30,0,8,13,31,1,2,32,0,3,5,33,1,2,9,34,0,5,35,2,7,12,13,36,0,6,37,1,2,5,38,0,4,39,2,5,7,9,40,1,13,41,0,5,12,42,2,7,10,43,0,12,13,44,1,5,11,45,0,2,7,46,10,13,47,1,5,11,48,0,7,12,49,2,10,13,50,1,5,11,51};
short no_one_element[42]={8, 10, 8, 10, 4, 6, 6, 6, 4, 5, 5, 5, 4, 5, 5, 4, 5, 5, 4, 4, 4, 4, 3, 4, 4, 3, 5, 3, 4, 3, 5, 3, 4, 4, 4, 4, 4, 3, 4, 4, 4, 4};
if (block_length>3840)
{
BG=1;
Kb = 22;
nrows=46;
ncols=68;
}
else if (block_length<=3840)
{
BG=2;
nrows=42;
if (block_length>640)
{
Kb = 10;
ncols=52;
}
else if (block_length>560)
{
Kb = 9;
ncols=51;
}
else if (block_length>192)
{
Kb = 8;
ncols=50;
}
else
{
Kb = 6;
ncols=48;
}
}
//find minimum value in all sets of lifting size
for (i1=0; i1 < 51; i1++)
{
if (lift_size[i1] >= (double) block_length/Kb)
{
Zc = lift_size[i1];
// printf("%d",Zc);
break;
}
}
nEdge_base_graph=197;
nEdge=nEdge_base_graph*Zc;
nCheck=nrows*Zc;
nBit=ncols*Zc;
//initial positions of pointers to check nodes
//degrees of check nodes
pointerCheck = (int *)malloc(sizeof(int) * nCheck);
degCheck=(int *)malloc(sizeof(int) * nCheck);
for (i1=0,temp_row=0; i1 < nrows; i1++)
{
for (i2=0; i2 < Zc; i2++)
{
degCheck[i1*Zc+i2] = no_one_element[i1]; //degree equals number of 1 elements in a row
pointerCheck[i1*Zc+i2] = temp_row;
temp_row = temp_row + no_one_element[i1];
}
}
//initial positions of pointers to bit nodes
//degrees of bit nodes
pointerBit = (int *)malloc(sizeof(int) * nBit);
degBit=(int *)malloc(sizeof(int) * nBit);
degBit_base_graph=(int *)malloc(sizeof(int) * ncols);
memset(degBit_base_graph,0,sizeof(int) * ncols);
for (iBit=0; iBit < nEdge_base_graph; ++iBit)
{
++degBit_base_graph[Col_position[iBit]]; //number of 1 elements in a columns in base graph
}
for (i1=0,temp_col=0; i1 < ncols; i1++)
{
for (i2=0; i2 < Zc; i2++)
{
degBit[i1*Zc+i2] = degBit_base_graph[i1]; //degree equals number of 1 elements in a column
pointerBit[i1*Zc+i2] = temp_col;
temp_col = temp_col + degBit_base_graph[i1];
}
}
//indice and degrees of check nodes and bit nodes
//divide layer for message passing algorithm
idxBit=(int *)malloc(sizeof(int) * nEdge);
// idxCheck=mxMalloc(sizeof(int) * nEdge);
idxEdge2Bit=(int *)malloc(sizeof(int) * nEdge);
idxEdge2Check=(int *)malloc(sizeof(int) * nEdge);
pointerCheck_temp = (int *)malloc(sizeof(int) * nCheck);
memcpy(pointerCheck_temp,pointerCheck,sizeof(int) * nCheck);
pointerBit_temp = (int *)malloc(sizeof(int) * nBit);
memcpy(pointerBit_temp,pointerBit,sizeof(int) * nBit);
no_rows_La1=(int *)malloc(sizeof(int) * nBit);
no_rows_La2=(int *)malloc(sizeof(int) * nBit);
no_rows_La3=(int *)malloc(sizeof(int) * nBit);
for (irow=0,p1=0,t1=0,iEdge=0; irow < nrows; ++irow) //loop for rows in base graph
{
temp_row=irow*Zc;
sum=0;sum1=0;sum2=0;
for (iShift=0; iShift < no_one_element[irow]; ++iShift) //loop for 1 elements in one row of base graph
{
temp_col=Col_position[p1]*Zc;
if ( ((rate==0.2)&&(BG==2)&&(Kb==10)) || ((rate==0.33)&&(BG==1)&&(Kb==22)) ) //layer , no rate matching
{
layer=2;
if (Col_position[p1]==0||Col_position[p1]==1)
sum++;
}
else if ( ( (BG==1) && (rate>=0.33) && (rate<=0.89) )||( (BG==2) && (rate>=0.2) && (rate<=0.67) ) ) //layer, rate matching
{
layer=3;
no_punctured_columns=ceil(nBit/Zc-2-Kb/rate);
if (Col_position[p1]==0 || Col_position[p1]==1)
sum1++;
if ( (Col_position[p1] >= ncols-no_punctured_columns) && (Col_position[p1] < ncols) )
sum2++;
}
for (iZ=0,p2=0; iZ < Zc; iZ++) //loop for lift size
{
idxBit[t1] = (shift_value[p1]+p2)%Zc + temp_col; //column positions
p2++;
idxCheck = temp_row + iZ; // row positions
idxEdge2Check[ pointerCheck_temp[idxCheck] ] = iEdge; //label and store the edges connecting to check nodes
++pointerCheck_temp[idxCheck];
idxEdge2Bit[ pointerBit_temp[idxBit[t1]] ] = iEdge; //label and store the edges connecting to bit nodes
++pointerBit_temp[idxBit[t1]];
iEdge++;
t1++;
}
p1++;
}
if ( ((rate==0.2)&&(BG==2)&&(Kb==10)) || ((rate==0.33)&&(BG==1)&&(Kb==22)) )
{
if (sum==1||sum==0)
{
for (i1=0; i1 < Zc; i1++)
{
no_rows_La1[rows_total_La1]=irow*Zc + i1;
rows_total_La1++;
}
}
else
{
for (i1=0; i1 < Zc; i1++)
{
no_rows_La2[rows_total_La2]=irow*Zc + i1;
rows_total_La2++;
}
}
}
else if (( (BG==1) && (rate>=0.33) && (rate<=0.89) )||( (BG==2) && (rate>=0.2) && (rate<=0.67) ))
{
sum=sum1+sum2;
if (sum==1)
{
for (i1=0; i1 < Zc; i1++)
{
no_rows_La1[rows_total_La1]=irow*Zc + i1;
rows_total_La1++;
}
}
else if (sum==2)
{
if (sum1==1)
{
for (i1=0; i1 < Zc; i1++)
{
no_rows_La2[rows_total_La2]=irow*Zc + i1;
rows_total_La2++;
}
}
else if (sum1==2)
{
for (i1=0; i1 < Zc; i1++)
{
no_rows_La3[rows_total_La3]=irow*Zc + i1;
rows_total_La3++;
}
}
}
else if (sum==3)
{
for (i1=0; i1 < Zc; i1++)
{
no_rows_La2[rows_total_La2]=irow*Zc + i1;
rows_total_La2++;
}
}
else if (sum==0)
{
for (i1=0; i1 < Zc; i1++)
{
no_rows_La3[rows_total_La3]=irow*Zc + i1;
rows_total_La3++;
}
}
}
}
// allocate memory for message passing algorithm
msgBit2Check=(short *)malloc(sizeof(short) * nEdge);
msgCheck2Bit=(short *)malloc(sizeof(short) * nEdge);
msgBit=(short *)malloc(sizeof(short) * nBit);
memset(msgCheck2Bit,0,sizeof(short) * nEdge);
v_estimate=(short *)malloc(sizeof(short) * nBit);
// initial values of LLR of bit nodes
memcpy(msgBit,msgChannel,nBit*sizeof(short));
//message passing algorithm
while (n<=No_iteration)
{
for (iLayer=1;iLayer<=layer;iLayer++)
{
if (iLayer==1)
{
no_rows=no_rows_La1;
rows_total=rows_total_La1;
}
else if (iLayer==2)
{
no_rows=no_rows_La2;
rows_total=rows_total_La2;
}
else if (iLayer==3)
{
no_rows=no_rows_La3;
rows_total=rows_total_La3;
}
//message from bit nodes to check nodes
for(i1 = 0; i1 < rows_total; ++i1)
{
for(i2 = 0; i2 < degCheck[no_rows[i1]]; ++i2)
{
msgBit2Check[ idxEdge2Check[ pointerCheck[no_rows[i1]] + i2] ] = msgBit[ idxBit[ idxEdge2Check[ pointerCheck[no_rows[i1]] + i2] ] ]
-msgCheck2Bit[ idxEdge2Check[ pointerCheck[no_rows[i1]] + i2] ];
}
}
//message from check nodes to bit nodes
for(i1 = 0; i1 < rows_total; ++i1)
{
for(i2 = 0; i2 < degCheck[no_rows[i1]]; ++i2)
{
mini=32640;
sgn=1;
for(i3 = 0; i3 < degCheck[no_rows[i1]]; ++i3)
{
if (idxEdge2Check[ pointerCheck[no_rows[i1]] + i3] != idxEdge2Check[ pointerCheck[no_rows[i1]] + i2 ])
{
sgn *=sign(msgBit2Check[ idxEdge2Check[ pointerCheck[no_rows[i1]] + i3] ]);
if (abs(msgBit2Check[ idxEdge2Check[ pointerCheck[no_rows[i1]] + i3] ]) < mini)
mini=abs(msgBit2Check[ idxEdge2Check[ pointerCheck[no_rows[i1]] + i3] ]);
}
}
msgCheck2Bit[ idxEdge2Check[ pointerCheck[no_rows[i1]] + i2 ] ]=sgn * mini;
//atanh(1)=19.07, 19.07 is converted to fixed-point 9_7= 19.07*2^7=2441
if ( msgCheck2Bit[ idxEdge2Check[ pointerCheck[no_rows[i1]] + i2 ] ] > 2441)
msgCheck2Bit[ idxEdge2Check[ pointerCheck[no_rows[i1]] + i2 ] ] = 2441;
if (msgCheck2Bit[ idxEdge2Check[ pointerCheck[no_rows[i1]] + i2 ] ] < -2441)
msgCheck2Bit[ idxEdge2Check[ pointerCheck[no_rows[i1]] + i2 ] ] = -2441;
}
}
// LLR
for(iBit = 0; iBit < nBit; ++iBit)
{
msgBit[iBit]=msgChannel[iBit];
for(i1 = 0; i1 < degBit[iBit]; ++i1)
msgBit[iBit] += msgCheck2Bit[idxEdge2Bit[ pointerBit[iBit]+i1 ] ];
if (msgBit[iBit]>=0)
v_estimate[iBit]=0;
else
v_estimate[iBit]=1;
}
// // LLR
// for(iBit = 0; iBit < nBit; ++iBit)
// {
// msgBit[iBit]=msgChannel[iBit];
// for(i1 = 0; i1 < degBit[iBit]; ++i1)
// msgBit[iBit] += msgCheck2Bit[idxEdge2Bit[ pointerBit[iBit]+i1 ] ];
// }
//
// //estimate codeword
// v_estimate=mxMalloc(sizeof(char) * nBit);
// for(iBit = 0; iBit < nBit; ++iBit)
// {
// if (msgBit[iBit]>=0)
// v_estimate[iBit]=0;
// else
// v_estimate[iBit]=1;
// }
//check syndrome=0
for (i1=0,isEqual=1; i1 < nCheck; ++i1)
{
syn=0;
for(i2 = 0; i2 < degCheck[i1]; ++i2)
{
//sum of bits of estimated codeword in the positions where there are 1 elements in graph
syn += v_estimate[ idxBit[ idxEdge2Check[ pointerCheck[ i1 ] + i2 ] ] ];
}
syn=syn%2;
if (syn != 0)
{
isEqual=0;
break;
}
}
if (isEqual==1) //syndrome=0, break
{
flag=1;
break;
}
}
if (flag==1)
{
break;
}
n++;
}
printf("%d\n",layer);
return v_estimate;
}
......@@ -562,4 +562,6 @@ int16_t reverseBits(int32_t ,int32_t);
void phy_viterbi_dot11(int8_t *,uint8_t *,uint16_t);
short *ldpc_decoder(short *msgChannel,short block_length,short No_iteration,double rate);
short *ldpc_encoder(char *test_input,char* channel_input,short block_length,double rate);
#endif
#include <stdlib.h>
#include <math.h>
#include <stdio.h>
#include <string.h>
#include "Gen_shift_value.h"
short *choose_generator_matrix(short BG,short Zc)
{
short *Gen_shift_values;
......@@ -219,3 +225,113 @@ short *choose_generator_matrix(short BG,short Zc)
*/
return Gen_shift_values;
}
int ldpc_encoder(char *test_input,char* channel_input,short block_length,double rate)
{
char c[22*384]; //padded input, unpacked, max size
char d[68*384]; //coded output, unpacked, max size
short *Gen_shift_values, *no_shift_values, *pointer_shift_values;
short BG,Zc,Kb,nrows,ncols,channel_temp;
int i,i1,i2,i3,i4,i5,t,temp,temp_prime;
int no_punctured_columns,output_length;
//Table of possible lifting sizes
short lift_size[51]={2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,18,20,22,24,26,28,30,32,36,40,44,48,52,56,60,64,72,80,88,96,104,112,120,128,144,160,176,192,208,224,240,256,288,320,352,384};
//determine number of bits in codeword
if (block_length>3840)
{
BG=1;
Kb = 22;
nrows=46; //parity check bits
ncols=22; //info bits
}
else if (block_length<=3840)
{
BG=2;
nrows=42; //parity check bits
ncols=10; // info bits
if (block_length>640)
Kb = 10;
else if (block_length>560)
Kb = 9;
else if (block_length>192)
Kb = 8;
else
Kb = 6;
}
//find minimum value in all sets of lifting size
for (i1=0; i1 < 51; i1++)
{
if (lift_size[i1] >= (double) block_length/Kb)
{
Zc = lift_size[i1];
//printf("%d\n",Zc);
break;
}
}
// load base graph of generator matrix
if (BG==1)
{
no_shift_values=(short*) no_shift_values_BG1;
pointer_shift_values=(short*) pointer_shift_values_BG1;
}
else if (BG==2)
{
no_shift_values=(short*) no_shift_values_BG2;
pointer_shift_values=(short*) pointer_shift_values_BG2;
}
Gen_shift_values=choose_generator_matrix(BG,Zc);
no_punctured_columns=(int)((nrows+Kb-2)*Zc-block_length/rate)/Zc;
//printf("%d\n",no_punctured_columns);
output_length = (Kb+nrows-no_punctured_columns) * Zc;
// unpack input
for (i=0;i<block_length;i++)
c[i] = (test_input[i/8]>>(i%8))&1;
// parity check part
for (i2=0; i2 < Zc; i2++)
{
t=Kb*Zc+i2;
//rotate matrix here
for (i5=0; i5 < Kb; i5++)
{
temp = c[i5*Zc];
memmove(&c[i5*Zc], &c[i5*Zc+1], (Zc-1)*sizeof(short));
c[i5*Zc+Zc-1] = temp;
}
// calculate each row in base graph
for (i1=0; i1 < nrows-no_punctured_columns; i1++)
{
channel_temp=0;
for (i3=0; i3 < Kb; i3++)
{
temp_prime=i1 * ncols + i3;
for (i4=0; i4 < no_shift_values[temp_prime]; i4++)
{
channel_temp = channel_temp ^ c[ i3*Zc + Gen_shift_values[ pointer_shift_values[temp_prime]+i4 ] ];
}
}
d[t+i1*Zc]=channel_temp;
}
}
// information part
memcpy(d,c,Kb*Zc*sizeof(short));
//pack into output
memset(channel_input,0,output_length/8*sizeof(char));
for (i=0;i<output_length;i++)
channel_input[i/8] = channel_input[i/8] | (d[i] << (i%8));
return 0;
}
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment