/* * 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.1 (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 */ /* file: 3gpplte_turbo_decoder.c purpose: Fixed-point routines for implementing max-logmap decoding of Turbo-coded (DLSCH) transport channels from 36-212, V8.6 2009-03 Modified from TI C6x reference design. currently maintained in openairinterface.org by R. Knopp (knopp@eurecom.fr) Note: This is a reference design for the sse version (3gpplte_turbo_decoder_sse.c) */ #include "PHY/defs_common.h" #include "PHY/CODING/coding_defs.h" #include "PHY/CODING/lte_interleaver_inline.h" #include "PHY/sse_intrin.h" /* // 3gpp2 polynomials #define M0T -m11 #define M0B m11 #define M1T m11 #define M1B -m11 #define M2T -m10 #define M2B m10 #define M3T m10 #define M3B -m10 #define M4T m10 #define M4B -m10 #define M5T -m10 #define M5B m10 #define M6T m11 #define M6B -m11 #define M7T -m11 #define M7B m11 */ // 3gpplte polynomials #define m00 (-m11) #define m01 (-m10) #define M0T m00 #define M0B m11 #define M1T m11 #define M1B m00 #define M2T m10 #define M2B m01 #define M3T m01 #define M3B m10 #define M4T m01 #define M4B m10 #define M5T m10 #define M5B m01 #define M6T m11 #define M6B m00 #define M7T m00 #define M7B m11 #define M0T_TERM m00 #define M1T_TERM m11 #define M2T_TERM m10 #define M3T_TERM m01 #define M4T_TERM m01 #define M5T_TERM m10 #define M6T_TERM m11 #define M7T_TERM m00 /* // 3GPP2 AlphaBeta #define ALPHA_BETA_1m00 alpha[(k-1)*STATES+0] + beta[k*STATES+0] #define ALPHA_BETA_1m11 alpha[(k-1)*STATES+0] + beta[k*STATES+4] #define ALPHA_BETA_2m11 alpha[(k-1)*STATES+1] + beta[k*STATES+0] #define ALPHA_BETA_2m00 alpha[(k-1)*STATES+1] + beta[k*STATES+4] #define ALPHA_BETA_1m01 alpha[(k-1)*STATES+2] + beta[k*STATES+1] #define ALPHA_BETA_1m10 alpha[(k-1)*STATES+2] + beta[k*STATES+5] #define ALPHA_BETA_2m10 alpha[(k-1)*STATES+3] + beta[k*STATES+1] #define ALPHA_BETA_2m01 alpha[(k-1)*STATES+3] + beta[k*STATES+5] #define ALPHA_BETA_3m10 alpha[(k-1)*STATES+4] + beta[k*STATES+2] #define ALPHA_BETA_3m01 alpha[(k-1)*STATES+4] + beta[k*STATES+6] #define ALPHA_BETA_4m01 alpha[(k-1)*STATES+5] + beta[k*STATES+2] #define ALPHA_BETA_4m10 alpha[(k-1)*STATES+5] + beta[k*STATES+6] #define ALPHA_BETA_3m11 alpha[(k-1)*STATES+6] + beta[k*STATES+3] #define ALPHA_BETA_3m00 alpha[(k-1)*STATES+6] + beta[k*STATES+7] #define ALPHA_BETA_4m00 alpha[(k-1)*STATES+7] + beta[k*STATES+3] #define ALPHA_BETA_4m11 alpha[(k-1)*STATES+7] + beta[k*STATES+7] */ #define ALPHA_BETA_1m00 alpha[(k-1)*STATES+0] + beta[k*STATES+0] #define ALPHA_BETA_1m11 alpha[(k-1)*STATES+0] + beta[k*STATES+4] #define ALPHA_BETA_2m11 alpha[(k-1)*STATES+1] + beta[k*STATES+0] #define ALPHA_BETA_2m00 alpha[(k-1)*STATES+1] + beta[k*STATES+4] #define ALPHA_BETA_1m10 alpha[(k-1)*STATES+2] + beta[k*STATES+1] #define ALPHA_BETA_1m01 alpha[(k-1)*STATES+2] + beta[k*STATES+5] #define ALPHA_BETA_2m10 alpha[(k-1)*STATES+3] + beta[k*STATES+5] #define ALPHA_BETA_2m01 alpha[(k-1)*STATES+3] + beta[k*STATES+1] #define ALPHA_BETA_3m10 alpha[(k-1)*STATES+4] + beta[k*STATES+6] #define ALPHA_BETA_3m01 alpha[(k-1)*STATES+4] + beta[k*STATES+2] #define ALPHA_BETA_4m01 alpha[(k-1)*STATES+5] + beta[k*STATES+6] #define ALPHA_BETA_4m10 alpha[(k-1)*STATES+5] + beta[k*STATES+2] #define ALPHA_BETA_3m11 alpha[(k-1)*STATES+6] + beta[k*STATES+3] #define ALPHA_BETA_3m00 alpha[(k-1)*STATES+6] + beta[k*STATES+7] #define ALPHA_BETA_4m00 alpha[(k-1)*STATES+7] + beta[k*STATES+3] #define ALPHA_BETA_4m11 alpha[(k-1)*STATES+7] + beta[k*STATES+7] typedef char Binary; typedef short llr_t; // internal decoder data is 16-bit fixed typedef short channel_t; #define LLR_MAX 32767 #define LLR_MIN -32768 #define LLRTOT 16 #define MAX 32767//16383 #define FRAME_LENGTH_MAX 6144 #define STATES 8 void log_map_s (llr_t* systematic,channel_t* y_parity, llr_t* ext,unsigned short frame_length,unsigned char term_flag,unsigned char F); void compute_gamma_s(llr_t* m11,llr_t* m10,llr_t* systematic, channel_t* y_parity, unsigned short frame_length,unsigned char term_flag); void compute_alpha_s(llr_t*alpha,llr_t* m11,llr_t* m10, unsigned short frame_length,unsigned char F); void compute_beta_s(llr_t* beta,llr_t* m11,llr_t* m10,llr_t* alpha, unsigned short frame_length,unsigned char F); void compute_ext_s(llr_t* alpha,llr_t* beta,llr_t* m11,llr_t* m10,llr_t* extrinsic, llr_t* ap, unsigned short frame_length); // global variables // llr_t alpha[(FRAME_LENGTH_MAX+3+1)*8]; llr_t beta[(FRAME_LENGTH_MAX+3+1)*8]; llr_t m11[(FRAME_LENGTH_MAX+3)]; llr_t m10[(FRAME_LENGTH_MAX+3)]; void log_map_s(llr_t* systematic,channel_t* y_parity, llr_t* ext,unsigned short frame_length,unsigned char term_flag,unsigned char F) { #ifdef DEBUG_LOGMAP unsigned short i; unsigned short argmax; llr_t max; printf("Gamma ...\n"); #endif //DEBUG_LOGMAP compute_gamma_s(m11,m10,systematic,y_parity,frame_length,term_flag); #ifdef DEBUG_LOGMAP for (i=0; i<frame_length+3; i++) printf("Position %d : (%d,%d,%d,%d)\n",i,m11[i],m10[i],-m11[i],-m10[i]); printf("\n"); printf("Alpha ...\n"); #endif //DEBUG_LOGMAP compute_alpha_s(alpha,m11,m10,frame_length,F); #ifdef DEBUG_LOGMAP for (i=0; i<frame_length+4; i++) { printf("Position %d : (%d,%d,%d,%d) (%d,%d,%d,%d,%d,%d,%d,%d) -> ",i, -m11[i],m10[i],m11[i],-m10[i],alpha[(i<<3) + 0], alpha[(i<<3) + 1], alpha[(i<<3) + 2], alpha[(i<<3) + 3], alpha[(i<<3) + 4], alpha[(i<<3) + 5], alpha[(i<<3) + 6], alpha[(i<<3) + 7]); argmax = 0; max = alpha[(i<<3)]; if (max<alpha[(i<<3) + 1]) { argmax=1; max = alpha[(i<<3) + 1]; } if (max<alpha[(i<<3) + 2]) { argmax=2; max = alpha[(i<<3) + 2]; } if (max<alpha[(i<<3) + 3]) { argmax=3; max = alpha[(i<<3) + 3]; } if (max<alpha[(i<<3) + 4]) { argmax=4; max = alpha[(i<<3) + 4]; } if (max<alpha[(i<<3) + 5]) { argmax=5; max = alpha[(i<<3) + 5]; } if (max<alpha[(i<<3) + 6]) { argmax=6; max = alpha[(i<<3) + 6]; } if (max<alpha[(i<<3) + 7]) { argmax=7; max = alpha[(i<<3) + 7]; } printf("argmax = %d\n",argmax); } printf("Beta ...\n"); #endif //DEBUG_LOGMAP compute_beta_s(beta,m11,m10,alpha,frame_length,F); #ifdef DEBUG_LOGMAP for (i=0; i<=frame_length+3; i++) { printf("Position %d : (%d,%d,%d,%d,%d,%d,%d,%d)->",i, beta[(i<<3) + 0], beta[(i<<3) + 1], beta[(i<<3) + 2], beta[(i<<3) + 3], beta[(i<<3) + 4], beta[(i<<3) + 5], beta[(i<<3) + 6], beta[(i<<3) + 7]); argmax = 0; max = beta[(i<<3)]; if (max<beta[(i<<3) + 1]) { argmax=1; max = beta[(i<<3) + 1]; } if (max<beta[(i<<3) + 2]) { argmax=2; max = beta[(i<<3) + 2]; } if (max<beta[(i<<3) + 3]) { argmax=3; max = beta[(i<<3) + 3]; } if (max<beta[(i<<3) + 4]) { argmax=4; max = beta[(i<<3) + 4]; } if (max<beta[(i<<3) + 5]) { argmax=5; max = beta[(i<<3) + 5]; } if (max<beta[(i<<3) + 6]) { argmax=6; max = beta[(i<<3) + 6]; } if (max<beta[(i<<3) + 7]) { argmax=7; max = beta[(i<<3) + 7]; } printf("argmax = %d\n",argmax); } printf("Extrinsic ...\n"); #endif //DEBUG_LOGMAP compute_ext_s(alpha,beta,m11,m10,ext,systematic,frame_length); #ifdef DEBUG_LOGMAP for (i=0; i<frame_length+3; i++) printf("Position %d : ext %d, ext+sys %d\n",i, ext[i],ext[i]+systematic[i]); printf("\n"); #endif //DEBUG_LOGMAP } inline int SAT_ADD(int a,int b,int m) { if (a+b > m) { #ifdef DEBUG_LOGMAP printf("***\n"); #endif return(m); } if (a+b < -m) { #ifdef DEBUG_LOGMAP printf("***\n"); #endif return(-m); } return(a+b); } void compute_gamma_s(llr_t* m11,llr_t* m10,llr_t* systematic,channel_t* y_parity, unsigned short frame_length,unsigned char term_flag) { int k; for (k=0; k<frame_length; k++) { m11[k] = (systematic[k]+y_parity[k])/2; m10[k] = (systematic[k]-y_parity[k])/2; // printf("gamma %d : (%d,%d) -> (%d,%d)\n",k,systematic[k],y_parity[k],m11[k],m10[k]); } // Compute metrics for trellis termination if (term_flag == 0) { // This is for the termination of the first code for (k=frame_length; k<frame_length+3; k++) { m11[k] = (systematic[k]+y_parity[k])/2; m10[k] = (systematic[k]-y_parity[k])/2; // printf("gamma %d : (%d,%d) -> (%d,%d)\n",k,systematic[k],y_parity[k],m11[k],m10[k]); } } else { for (k=frame_length; k<frame_length+3; k++) { m11[k] = (systematic[k+3]+y_parity[k])/2; m10[k] = (systematic[k+3]-y_parity[k])/2; // printf("gamma %d : (%d,%d) -> (%d,%d)\n",k,systematic[k],y_parity[k],m11[k],m10[k]); } } } short systematic0[6144],systematic1[6144],systematic2[6144],yparity1[6144],yparity2[6144]; void compute_alpha_s(llr_t* alpha,llr_t* m_11,llr_t* m_10,unsigned short frame_length,unsigned char F) { int k,i; llr_t m11,m10; llr_t old0,old1,old2, old3, old4, old5, old6, old7; llr_t new0,new1,new2, new3, new4, new5, new6, new7; llr_t m_b0,m_b1,m_b2, m_b3, m_b4, m_b5, m_b6, m_b7; // initialize log_alpha[0][m] llr_t alpha_max; old0 = 0; old1 = -MAX/2; old2 = -MAX/2; old3 = -MAX/2; old4 = -MAX/2; old5 = -MAX/2; old6 = -MAX/2; old7 = -MAX/2; alpha[0*(frame_length)+0] = old0; alpha[0*(frame_length)+1] = old1; alpha[0*(frame_length)+2] = old2; alpha[0*(frame_length)+3] = old3; alpha[0*(frame_length)+4] = old4; alpha[0*(frame_length)+5] = old5; alpha[0*(frame_length)+6] = old6; alpha[0*(frame_length)+7] = old7; // // compute log_alpha[k][m] // Steady-state portion for (k=1; k<=F; k++) for (i=0; i<8; i++) alpha[i+(k*8)] = alpha[i]; for (k=1; k<=frame_length; k++) { m11=m_11[k-1]; m10=m_10[k-1]; m_b0 = SAT_ADD(old1,M1T,MAX); m_b4 = SAT_ADD(old1,M1B,MAX); m_b1 = SAT_ADD(old3,M3T,MAX); m_b5 = SAT_ADD(old3,M3B,MAX); m_b2 = SAT_ADD(old5,M5T,MAX); m_b6 = SAT_ADD(old5,M5B,MAX); m_b3 = SAT_ADD(old7,M7T,MAX); m_b7 = SAT_ADD(old7,M7B,MAX); new0 = SAT_ADD(old0,M0T,MAX); new4 = SAT_ADD(old0,M0B,MAX); new1 = SAT_ADD(old2,M2T,MAX); new5 = SAT_ADD(old2,M2B,MAX); new2 = SAT_ADD(old4,M4T,MAX); new6 = SAT_ADD(old4,M4B,MAX); new3 = SAT_ADD(old6,M6T,MAX); new7 = SAT_ADD(old6,M6B,MAX); // printf("Output %d (%d,%d)\n",k-1,systematic0[k-1],yparity1[k-1]); // printf("(m_b0 %d,new0 %d),(m_b1 %d,new1 %d),(m_b2 %d,new2 %d),(m_b3 %d,new3 %d),(m_b4 %d,new4 %d),(m_b5 %d,new5 %d),(m_b6 %d,new6 %d),(m_b7 %d,new7 %d)\n",m_b0,new0,m_b1,new1,m_b2,new2,m_b3,new3,m_b4,new4,m_b5,new5,m_b6,new6,m_b7,new7); if (m_b0 > new0) new0=m_b0; alpha[k*STATES + 0] = new0; old0=new0; if (m_b4 > new4) new4=m_b4; alpha[k*STATES + 4] = new4; old4=new4; if (m_b1 > new1) new1=m_b1; alpha[k*STATES + 1] = new1; old1=new1; if (m_b5 > new5) new5=m_b5; alpha[k*STATES + 5] = new5; old5=new5; if (m_b2 > new2) new2=m_b2; alpha[k*STATES + 2] = new2; old2=new2; if (m_b6 > new6) new6=m_b6; alpha[k*STATES + 6] = new6; old6=new6; if (m_b3 > new3) new3=m_b3; alpha[k*STATES + 3] = new3; old3=new3; if (m_b7 > new7) new7=m_b7; alpha[k*STATES + 7] = new7; old7=new7; alpha_max = alpha[(STATES*k) + 0]; if(alpha[(STATES*k) + 1]>alpha_max) alpha_max = alpha[(STATES*k) + 1]; if(alpha[(STATES*k) + 2]>alpha_max) alpha_max = alpha[(STATES*k) + 2]; if(alpha[(STATES*k) + 3]>alpha_max) alpha_max = alpha[(STATES*k) + 3]; if(alpha[(STATES*k) + 4]>alpha_max) alpha_max = alpha[(STATES*k) + 4]; if(alpha[(STATES*k) + 5]>alpha_max) alpha_max = alpha[(STATES*k) + 5]; if(alpha[(STATES*k) + 6]>alpha_max) alpha_max = alpha[(STATES*k) + 6]; if(alpha[(STATES*k) + 7]>alpha_max) alpha_max = alpha[(STATES*k) + 7]; alpha[(STATES*k)+0]-=alpha_max; alpha[(STATES*k)+1]-=alpha_max; alpha[(STATES*k)+2]-=alpha_max; alpha[(STATES*k)+3]-=alpha_max; alpha[(STATES*k)+4]-=alpha_max; alpha[(STATES*k)+5]-=alpha_max; alpha[(STATES*k)+6]-=alpha_max; alpha[(STATES*k)+7]-=alpha_max; new0=alpha[(STATES*k)+0]; new1=alpha[(STATES*k)+1]; new2=alpha[(STATES*k)+2]; new3=alpha[(STATES*k)+3]; new4=alpha[(STATES*k)+4]; new5=alpha[(STATES*k)+5]; new6=alpha[(STATES*k)+6]; new7=alpha[(STATES*k)+7]; } for (k=frame_length+1; k<=frame_length+3; k++) { m11=m_11[k-1]; m10=m_10[k-1]; m_b0 = SAT_ADD(old1,M1T_TERM,MAX); m_b1 = SAT_ADD(old3,M3T_TERM,MAX); m_b2 = SAT_ADD(old5,M5T_TERM,MAX); m_b3 = SAT_ADD(old7,M7T_TERM,MAX); new0 = SAT_ADD(old0,M0T_TERM,MAX); new1 = SAT_ADD(old2,M2T_TERM,MAX); new2 = SAT_ADD(old4,M4T_TERM,MAX); new3 = SAT_ADD(old6,M6T_TERM,MAX); #ifdef DEBUG_LOGMAP printf("alpha term: m00 %d, m10 %d : (%d,%d,%d,%d) (%d,%d,%d,%d) (%d,%d,%d,%d) (%d,%d,%d,%d)\n", m00,m10,old0,old1,m_b0,new0,old2,old3,m_b1,new1,old3,old4,m_b2,new2,old6,old7,m_b3,new3); #endif //DEBUG_LOGMAP if (m_b0 > new0) new0=m_b0; alpha[k*STATES + 0] = new0; old0=new0; if (m_b2 > new2) new2=m_b2; alpha[k*STATES + 2] = new2; old2=new2; if (m_b1 > new1) new1=m_b1; alpha[k*STATES + 1] = new1; old1=new1; if (m_b3 > new3) new3=m_b3; alpha[k*STATES + 3] = new3; old3=new3; alpha_max = alpha[(STATES*k) + 0]; if(alpha[(STATES*k) + 1]>alpha_max) alpha_max = alpha[(STATES*k) + 1]; if(alpha[(STATES*k) + 2]>alpha_max) alpha_max = alpha[(STATES*k) + 2]; if(alpha[(STATES*k) + 3]>alpha_max) alpha_max = alpha[(STATES*k) + 3]; alpha[(STATES*k)+0]-=alpha_max; alpha[(STATES*k)+1]-=alpha_max; alpha[(STATES*k)+2]-=alpha_max; alpha[(STATES*k)+3]-=alpha_max; new0=alpha[(STATES*k)+0]; new1=alpha[(STATES*k)+1]; new2=alpha[(STATES*k)+2]; new3=alpha[(STATES*k)+3]; } } void compute_beta_s(llr_t* beta,llr_t *m_11,llr_t* m_10,llr_t* alpha,unsigned short frame_length,unsigned char F) { int k; llr_t old0, old1, old2, old3, old4, old5, old6, old7; llr_t new0, new1, new2, new3, new4, new5, new6, new7; llr_t m_b0, m_b1, m_b2, m_b3, m_b4,m_b5, m_b6, m_b7; llr_t m11,m10; llr_t beta_max; // int m_max; // llr_t max1, temp1, max2, temp2; // int m_max1, m_max2; // // initialize the first stage; // for state for which alpha iz maximum, set log_beta to 0, // set the other ones to MAX. /* m_max1 = 0; max1 = alpha[((frame_length+3)*STATES)+0]; temp1 = alpha[((frame_length+3)*STATES)+1]; if (temp1 > max1) { m_max1 = 1; max1 = temp1;}; temp1 = alpha[((frame_length+3)*STATES)+2]; if (temp1 > max1) { m_max1 = 2; max1 = temp1;}; temp1 = alpha[((frame_length+3)*STATES)+3]; if (temp1 > max1) { m_max1 = 3; max1 = temp1;}; m_max2 = 7; max2 = alpha[((frame_length+3)*STATES)+7]; temp2 = alpha[((frame_length+3)*STATES)+6]; if (temp2 > max2) { m_max2 = 6; max2 = temp2;}; temp2 = alpha[((frame_length+3)*STATES)+5]; if (temp2 > max2) { m_max2 = 5; max2 = temp2;}; temp2 = alpha[((frame_length+3)*STATES)+4]; if (temp2 > max2) { m_max2 = 4; max2 = temp2;}; if (max2 > max1) m_max1 = m_max2; if (m_max1==0) old0=0; else old0 = -MAX/2; if (m_max1==1) old1=0; else old1 = -MAX/2; if (m_max1==2) old2=0; else old2 = -MAX/2; if (m_max1==3) old3=0; else old3 = -MAX/2; if (m_max1==4) old4=0; else old4 = -MAX/2; if (m_max1==5) old5=0; else old5 = -MAX/2; if (m_max1==6) old6=0; else old6 = -MAX/2; if (m_max1==7) old7=0; else old7 = -MAX/2; */ /* // Initialise zero state because of termination beta[(STATES*(frame_length+3)) + 0] = 0; beta[(STATES*(frame_length+3)) + 1] = -MAX/2; beta[(STATES*(frame_length+3)) + 2] = -MAX/2; beta[(STATES*(frame_length+3)) + 3] = -MAX/2; beta[(STATES*(frame_length+3)) + 4] = -MAX/2; beta[(STATES*(frame_length+3)) + 5] = -MAX/2; beta[(STATES*(frame_length+3)) + 6] = -MAX/2; beta[(STATES*(frame_length+3)) + 7] = -MAX/2; for (k=0;k<F;k++) for (i=0;i<8;i++) beta[i+(k*8)] = beta[i]; old0 = 0; old1 = -MAX/2; old2 = -MAX/2; old3 = -MAX/2; old4 = -MAX/2; old5 = -MAX/2; old6 = -MAX/2; old7 = -MAX/2; // // compute beta[k][m] // for (k=(frame_length+2);k>=frame_length;k--) { m11=m_11[k]; m10=m_10[k]; new0 = SAT_ADD(old0,M0T_TERM,MAX); new1 = SAT_ADD(old0,M1T_TERM,MAX); new2 = SAT_ADD(old1,M2T_TERM,MAX); new3 = SAT_ADD(old1,M3T_TERM,MAX); new4 = SAT_ADD(old2,M4T_TERM,MAX); new5 = SAT_ADD(old2,M5T_TERM,MAX); new6 = SAT_ADD(old3,M6T_TERM,MAX); new7 = SAT_ADD(old3,M7T_TERM,MAX); beta[k*STATES + 0] = new0; old0=new0; beta[k*STATES + 1] = new1; old1=new1; beta[k*STATES + 2] = new2; old2=new2; beta[k*STATES + 3] = new3; old3=new3; beta[k*STATES + 4] = new4; old4=new4; beta[k*STATES + 5] = new5; old5=new5; beta[k*STATES + 6] = new6; old6=new6; beta[k*STATES + 7] = new7; old7=new7; } */ beta[(STATES*(frame_length)) + 0] = alpha[(STATES*frame_length) + 0]; beta[(STATES*(frame_length)) + 1] = alpha[(STATES*frame_length) + 1]; beta[(STATES*(frame_length)) + 2] = alpha[(STATES*frame_length) + 2]; beta[(STATES*(frame_length)) + 3] = alpha[(STATES*frame_length) + 3]; beta[(STATES*(frame_length)) + 4] = alpha[(STATES*frame_length) + 4]; beta[(STATES*(frame_length)) + 5] = alpha[(STATES*frame_length) + 5]; beta[(STATES*(frame_length)) + 6] = alpha[(STATES*frame_length) + 6]; beta[(STATES*(frame_length)) + 7] = alpha[(STATES*frame_length) + 7]; old0 = beta[(STATES*frame_length)+0]; old1 = beta[(STATES*frame_length)+1]; old2 = beta[(STATES*frame_length)+2]; old3 = beta[(STATES*frame_length)+3]; old4 = beta[(STATES*frame_length)+4]; old5 = beta[(STATES*frame_length)+5]; old6 = beta[(STATES*frame_length)+6]; old7 = beta[(STATES*frame_length)+7]; for (k=(frame_length-1); k>=0; k--) { m11=m_11[k]; m10=m_10[k]; m_b0 = SAT_ADD(old4,M0B,MAX); m_b1 = SAT_ADD(old4,M1B,MAX); m_b2 = SAT_ADD(old5,M2B,MAX); m_b3 = SAT_ADD(old5,M3B,MAX); m_b4 = SAT_ADD(old6,M4B,MAX); m_b5 = SAT_ADD(old6,M5B,MAX); m_b6 = SAT_ADD(old7,M6B,MAX); m_b7 = SAT_ADD(old7,M7B,MAX); new0 = SAT_ADD(old0,M0T,MAX); new1 = SAT_ADD(old0,M1T,MAX); new2 = SAT_ADD(old1,M2T,MAX); new3 = SAT_ADD(old1,M3T,MAX); new4 = SAT_ADD(old2,M4T,MAX); new5 = SAT_ADD(old2,M5T,MAX); new6 = SAT_ADD(old3,M6T,MAX); new7 = SAT_ADD(old3,M7T,MAX); if (m_b0 > new0) new0=m_b0; beta[k*STATES + 0] = new0; old0=new0; if (m_b1 > new1) new1=m_b1; beta[k*STATES + 1] = new1; old1=new1; if (m_b2 > new2) new2=m_b2; beta[k*STATES + 2] = new2; old2=new2; if (m_b3 > new3) new3=m_b3; beta[k*STATES + 3] = new3; old3=new3; if (m_b4 > new4) new4=m_b4; beta[k*STATES + 4] = new4; old4=new4; if (m_b5 > new5) new5=m_b5; beta[k*STATES + 5] = new5; old5=new5; if (m_b6 > new6) new6=m_b6; beta[k*STATES + 6] = new6; old6=new6; if (m_b7 > new7) new7=m_b7; beta[k*STATES + 7] = new7; old7=new7; beta_max = beta[(STATES*k) + 0]; if(beta[(STATES*k) + 1]>beta_max) beta_max = beta[(STATES*k) + 1]; if(beta[(STATES*k) + 2]>beta_max) beta_max = beta[(STATES*k) + 2]; if(beta[(STATES*k) + 3]>beta_max) beta_max = beta[(STATES*k) + 3]; if(beta[(STATES*k) + 4]>beta_max) beta_max = beta[(STATES*k) + 4]; if(beta[(STATES*k) + 5]>beta_max) beta_max = beta[(STATES*k) + 5]; if(beta[(STATES*k) + 6]>beta_max) beta_max = beta[(STATES*k) + 6]; if(beta[(STATES*k) + 7]>beta_max) beta_max = beta[(STATES*k) + 7]; beta[(STATES*k)+0]-=beta_max; beta[(STATES*k)+1]-=beta_max; beta[(STATES*k)+2]-=beta_max; beta[(STATES*k)+3]-=beta_max; beta[(STATES*k)+4]-=beta_max; beta[(STATES*k)+5]-=beta_max; beta[(STATES*k)+6]-=beta_max; beta[(STATES*k)+7]-=beta_max; new0=beta[(STATES*k)+0]; new1=beta[(STATES*k)+1]; new2=beta[(STATES*k)+2]; new3=beta[(STATES*k)+3]; new4=beta[(STATES*k)+4]; new5=beta[(STATES*k)+5]; new6=beta[(STATES*k)+6]; new7=beta[(STATES*k)+7]; /* if (((k%(frame_length>>3))==0)&&(k>0)) { alpha[((k)*STATES)+0]=beta[((k)*STATES)+0] alpha[((k)*STATES)+1]=beta[((k)*STATES)+1]; alpha[((k)*STATES)+2]=beta[((k)*STATES)+2]; alpha[((k)*STATES)+3]=beta[((k)*STATES)+3]; alpha[((k)*STATES)+4]=beta[((k)*STATES)+4]; alpha[((k)*STATES)+5]=beta[((k)*STATES)+5]; alpha[((k)*STATES)+6]=beta[((k)*STATES)+6]; alpha[((k)*STATES)+7]=beta[((k)*STATES)+7]; } */ } } void compute_ext_s(llr_t* alpha,llr_t* beta,llr_t* m_11,llr_t* m_10,llr_t* ext, llr_t* systematic,unsigned short frame_length) { int k; llr_t m11,m10; llr_t m00_1,m11_1,m00_2,m11_2,m00_3,m11_3,m00_4,m11_4; llr_t m01_1,m10_1,m01_2,m10_2,m01_3,m10_3,m01_4,m10_4; // // LLR computation // for (k=1; k<=(frame_length+3); k++) { m00_4 = ALPHA_BETA_4m00; m11_4 = ALPHA_BETA_4m11; m00_3 = ALPHA_BETA_3m00; m11_3 = ALPHA_BETA_3m11; m00_2 = ALPHA_BETA_2m00; m11_2 = ALPHA_BETA_2m11; m11_1 = ALPHA_BETA_1m11; m00_1 = ALPHA_BETA_1m00; m01_4 = ALPHA_BETA_4m01; m10_4 = ALPHA_BETA_4m10; m01_3 = ALPHA_BETA_3m01; m10_3 = ALPHA_BETA_3m10; m01_2 = ALPHA_BETA_2m01; m10_2 = ALPHA_BETA_2m10; m10_1 = ALPHA_BETA_1m10; m01_1 = ALPHA_BETA_1m01; if (m01_2 > m01_1) m01_1 = m01_2; if (m01_3 > m01_1) m01_1 = m01_3; if (m01_4 > m01_1) m01_1 = m01_4; if (m00_2 > m00_1) m00_1 = m00_2; if (m00_3 > m00_1) m00_1 = m00_3; if (m00_4 > m00_1) m00_1 = m00_4; if (m10_2 > m10_1) m10_1 = m10_2; if (m10_3 > m10_1) m10_1 = m10_3; if (m10_4 > m10_1) m10_1 = m10_4; if (m11_2 > m11_1) m11_1 = m11_2; if (m11_3 > m11_1) m11_1 = m11_3; if (m11_4 > m11_1) m11_1 = m11_4; m11=m_11[k-1]; m10=m_10[k-1]; m01_1 = SAT_ADD(m01_1,m01,MAX); m00_1 = SAT_ADD(m00_1,m00,MAX); m10_1 = SAT_ADD(m10_1,m10,MAX); m11_1 = SAT_ADD(m11_1,m11,MAX); if (m00_1 > m01_1) m01_1 = m00_1; if (m11_1 > m10_1) m10_1 = m11_1; ext[k-1] = SAT_ADD(m10_1,-SAT_ADD(m01_1,systematic[k-1],MAX),MAX); #ifdef DEBUG_LOGMAP printf("Ext %d: m0 %d, m1 %d, syst %d ext %d\n",k-1,m01_1,m10_1,systematic[k-1],ext[k-1]); #endif //DEBUG_LOGMAP }; } unsigned char phy_threegpplte_turbo_decoder_scalar(llr_t *y, llr_t *y2, unsigned char *decoded_bytes, unsigned char *decoded_bytes2, unsigned short n, unsigned short f1, unsigned short f2, unsigned char max_iterations, unsigned char crc_type, unsigned char F, time_stats_t *init_stats, time_stats_t *alpha_stats, time_stats_t *beta_stats, time_stats_t *gamma_stats, time_stats_t *ext_stats, time_stats_t *intl1_stats, time_stats_t *intl2_stats) { /* y is a pointer to the input decoded_bytes is a pointer to the decoded output n is the size in bits of the coded block, with the tail */ short ext[n],ext2[n]; // short systematic0[n],systematic1[n],systematic2[n],yparity1[n],yparity2[n]; llr_t *yp = y; unsigned short i,pi; unsigned char iteration_cnt=0; unsigned int crc,oldcrc; unsigned char crc_len,temp; if (crc_type > 3) { fprintf(stderr,"Illegal crc length!\n"); return 255; } switch (crc_type) { case CRC24_A: case CRC24_B: crc_len=3; break; case CRC16: crc_len=2; break; case CRC8: crc_len=1; break; default: crc_len=3; } for (i=0; i<n; i++) { systematic0[i] = *yp; yp++; yparity1[i] = *yp; yp++; yparity2[i] = *yp; yp++; #ifdef DEBUG_LOGMAP printf("Position %d: (%d,%d,%d)\n",i,systematic0[i],yparity1[i],yparity2[i]); #endif //DEBUG_LOGMAP } for (i=n; i<n+3; i++) { systematic0[i]= *yp ; yp++; yparity1[i] = *yp; yp++; #ifdef DEBUG_LOGMAP printf("Term 1 (%d): %d %d\n",i,systematic0[i],yparity1[i]); #endif //DEBUG_LOGMAP } for (i=n+3; i<n+6; i++) { systematic0[i]= *yp ; yp++; yparity2[i-3] = *yp; yp++; #ifdef DEBUG_LOGMAP printf("Term 2 (%d): %d %d\n",i-3,systematic0[i],yparity2[i-3]); #endif //DEBUG_LOGMAP } #ifdef DEBUG_LOGMAP printf("\n"); #endif //DEBUG_LOGMAP // do log_map from first parity bit log_map_s(systematic0,yparity1,ext,n,0,F); while (iteration_cnt++ < max_iterations) { #ifdef DEBUG_LOGMAP printf("\n*******************ITERATION %d\n\n",iteration_cnt); #endif //DEBUG_LOGMAP threegpplte_interleaver_reset(); pi=0; // compute input to second encoder by interleaving extrinsic info for (i=0; i<n; i++) { // steady-state portion systematic2[i] = (ext[pi] + systematic0[pi]); pi = threegpplte_interleaver(f1,f2,n); } for (i=n; i<n+3; i++) { // termination systematic2[i] = (systematic0[i+8]); } // do log_map from second parity bit log_map_s(systematic2,yparity2,ext2,n,1,0); threegpplte_interleaver_reset(); pi=0; for (i=0; i<n>>3; i++) decoded_bytes[i]=0; // compute input to first encoder and output for (i=0; i<n; i++) { systematic1[pi] = (ext2[i] + systematic0[pi]); #ifdef DEBUG_LOGMAP printf("Second half %d: ext2[i] %d, systematic0[i] %d (e+s %d)\n",i,ext2[i],systematic0[pi], ext2[i]+systematic2[i]); #endif //DEBUG_LOGMAP if ((systematic2[i] + ext2[i]) > 0) decoded_bytes[pi>>3] += (1 << (7-(pi&7))); pi = threegpplte_interleaver(f1,f2,n); } for (i=n; i<n+3; i++) { systematic1[i] = (systematic0[i]); #ifdef DEBUG_LOGMAP printf("Second half %d: ext2[i] %d, systematic0[i] %d (e+s %d)\n",i,ext2[i],systematic0[i], ext2[i]+systematic2[i]); #endif //DEBUG_LOGMAP } // check status on output oldcrc= *((unsigned int *)(&decoded_bytes[(n>>3)-crc_len])); switch (crc_type) { case CRC24_A: oldcrc&=0x00ffffff; crc = crc24a(&decoded_bytes[F>>3], n-24-F)>>8; temp=((uint8_t *)&crc)[2]; ((uint8_t *)&crc)[2] = ((uint8_t *)&crc)[0]; ((uint8_t *)&crc)[0] = temp; // msg("CRC24_A = %x, oldcrc = %x (F %d)\n",crc,oldcrc,F); break; case CRC24_B: oldcrc&=0x00ffffff; crc = crc24b(decoded_bytes, n-24)>>8; temp=((uint8_t *)&crc)[2]; ((uint8_t *)&crc)[2] = ((uint8_t *)&crc)[0]; ((uint8_t *)&crc)[0] = temp; // msg("CRC24_B = %x, oldcrc = %x\n",crc,oldcrc); break; case CRC16: oldcrc&=0x0000ffff; crc = crc16(decoded_bytes, n-16)>>16; break; case CRC8: oldcrc&=0x000000ff; crc = crc8(decoded_bytes, n-8)>>24; break; } if (crc == oldcrc) { return(iteration_cnt); } // do log_map from first parity bit if (iteration_cnt < max_iterations) log_map_s(systematic1,yparity1,ext,n,0,F); } return(iteration_cnt); } #ifdef TEST_DEBUG int test_logmap8() { unsigned char test[8]; //_declspec(align(16)) char channel_output[512]; //_declspec(align(16)) unsigned char output[512],decoded_output[16], *inPtr, *outPtr; short channel_output[512]; unsigned char output[512],decoded_output[16]; unsigned int i; test[0] = 7; test[1] = 0xa5; test[2] = 0; test[3] = 0xfe; test[4] = 0x1a; test[5] = 0x0; // test[5] = 0x33; // test[6] = 0x99; // test[7] = 0; threegpplte_turbo_encoder(test, 5, output, 3, 10); for (i = 0; i < 132; i++) { channel_output[i] = 15*(2*output[i] - 1); // printf("Position %d : %d\n",i,channel_output[i]); } memset(decoded_output,0,16); phy_threegpplte_turbo_decoder(channel_output,decoded_output,40,3,10,6,3); } void main() { test_logmap8(); } #endif // TEST_DEBUG