dlsch_modulation_NB_IoT.c 6.93 KB
Newer Older
Matthieu Kanj's avatar
Matthieu Kanj committed
1 2 3 4 5 6 7 8 9 10 11 12 13
/***********************************************************************

**********************************************************************/
/*! \file PHY/LTE_TRANSPORT/dlsch_modulation_NB_IoT.c
* \brief Top-level routines for generating the NPDSCH physical channel for NB_IoT,
* \author M. KANJ
* \date 2017
* \version 0.0
* \company bcom
* \email: matthieu.kanj@b-com.com
* \note
* \warning
*/
14
#include <math.h>
15
//#include "PHY/defs.h"
16
//#include "PHY/defs_NB_IoT.h"
17
//#include "PHY/extern_NB_IoT.h"
18
#include "PHY/impl_defs_lte.h"
19 20 21
//#include "PHY/CODING/defs_nb_iot.h"
//#include "PHY/CODING/extern.h"
//#include "PHY/CODING/lte_interleaver_inline.h"
22
#include "PHY/LTE_TRANSPORT/defs_NB_IoT.h"
23
#include "PHY/LTE_TRANSPORT/proto_NB_IoT.h"
24 25
#include "PHY/impl_defs_lte_NB_IoT.h"
#include "PHY/impl_defs_top_NB_IoT.h"
26 27
//#include "defs.h"
//#include "UTIL/LOG/vcd_signal_dumper.h"
Matthieu Kanj's avatar
Matthieu Kanj committed
28

29
int allocate_REs_in_RB_NB_IoT(LTE_DL_FRAME_PARMS 	    *frame_parms,
30 31 32 33 34 35 36
                              int32_t 					**txdataF,
                              uint32_t 					*jj,
                              uint32_t 					symbol_offset,
                              uint8_t 					*x0,
                              uint8_t 					pilots,
                              int16_t 					amp,
						  	  unsigned short 			id_offset,
37
						  	  uint8_t                   pilot_shift,
38
                              uint32_t 					*re_allocated)  //  not used variable ??!!
Matthieu Kanj's avatar
Matthieu Kanj committed
39
{
40
  MIMO_mode_t 	mimo_mode = (frame_parms->mode1_flag==1)? SISO:ALAMOUTI;
41 42 43 44 45 46 47

  uint32_t  tti_offset,aa;
  uint8_t   re;
  int16_t   gain_lin_QPSK;
  uint8_t   first_re,last_re;
  int32_t   tmp_sample1,tmp_sample2;

48
  gain_lin_QPSK = (int16_t)((amp*ONE_OVER_SQRT2_Q15_NB_IoT)>>15);
49 50
  first_re      = 0;
  last_re       = 12;
Matthieu Kanj's avatar
Matthieu Kanj committed
51 52 53 54 55

  for (re=first_re; re<last_re; re++) {      		// re varies between 0 and 12 sub-carriers

    tti_offset = symbol_offset + re;				// symbol_offset = 512 * L ,  re_offset = 512 - 3*12  , re
	
56
	if (pilots != 1 || (re%6 != ((id_offset + 3*pilot_shift) % 6) ) )  			// if re is not a pilot
Matthieu Kanj's avatar
Matthieu Kanj committed
57
	{
58
													 
59
      if (mimo_mode == SISO) {  								//SISO mapping
Matthieu Kanj's avatar
Matthieu Kanj committed
60 61 62 63 64 65 66
			*re_allocated = *re_allocated + 1;						// variable incremented but never used
			
			for (aa=0; aa<frame_parms->nb_antennas_tx; aa++) {
					((int16_t*)&txdataF[aa][tti_offset])[0] += (x0[*jj]==1) ? (-gain_lin_QPSK) : gain_lin_QPSK; //I //b_i
			}
			*jj = *jj + 1;
			for (aa=0; aa<frame_parms->nb_antennas_tx; aa++) {
67
					((int16_t*)&txdataF[aa][tti_offset])[1] += (x0[*jj]==1) ? (-gain_lin_QPSK) : gain_lin_QPSK; //Q //b_{i+1}
Matthieu Kanj's avatar
Matthieu Kanj committed
68 69 70
			}
			*jj = *jj + 1;	
			
71
      } else if (mimo_mode == ALAMOUTI) {
Matthieu Kanj's avatar
Matthieu Kanj committed
72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87
	  
			*re_allocated = *re_allocated + 1;

			((int16_t*)&tmp_sample1)[0] = (x0[*jj]==1) ? (-gain_lin_QPSK) : gain_lin_QPSK;
			*jj=*jj+1;
			((int16_t*)&tmp_sample1)[1] = (x0[*jj]==1) ? (-gain_lin_QPSK) : gain_lin_QPSK;
			*jj=*jj+1;

			// second antenna position n -> -x1*

			((int16_t*)&tmp_sample2)[0] = (x0[*jj]==1) ? (gain_lin_QPSK) : -gain_lin_QPSK;
			*jj=*jj+1;
			((int16_t*)&tmp_sample2)[1] = (x0[*jj]==1) ? (-gain_lin_QPSK) : gain_lin_QPSK;
			*jj=*jj+1;

			// normalization for 2 tx antennas
88 89 90 91
			((int16_t*)&txdataF[0][tti_offset])[0] += (int16_t)((((int16_t*)&tmp_sample1)[0]*ONE_OVER_SQRT2_Q15_NB_IoT)>>15);
			((int16_t*)&txdataF[0][tti_offset])[1] += (int16_t)((((int16_t*)&tmp_sample1)[1]*ONE_OVER_SQRT2_Q15_NB_IoT)>>15);
			((int16_t*)&txdataF[1][tti_offset])[0] += (int16_t)((((int16_t*)&tmp_sample2)[0]*ONE_OVER_SQRT2_Q15_NB_IoT)>>15);
			((int16_t*)&txdataF[1][tti_offset])[1] += (int16_t)((((int16_t*)&tmp_sample2)[1]*ONE_OVER_SQRT2_Q15_NB_IoT)>>15);
Matthieu Kanj's avatar
Matthieu Kanj committed
92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117

			// fill in the rest of the ALAMOUTI precoding
			if ( pilots != 1 || (re+1)%3 != id_offset) {
				((int16_t *)&txdataF[0][tti_offset+1])[0] += -((int16_t *)&txdataF[1][tti_offset])[0]; //x1
				((int16_t *)&txdataF[0][tti_offset+1])[1] += ((int16_t *)&txdataF[1][tti_offset])[1];
				((int16_t *)&txdataF[1][tti_offset+1])[0] += ((int16_t *)&txdataF[0][tti_offset])[0];  //x0*
				((int16_t *)&txdataF[1][tti_offset+1])[1] += -((int16_t *)&txdataF[0][tti_offset])[1];
			} else {
				((int16_t *)&txdataF[0][tti_offset+2])[0] += -((int16_t *)&txdataF[1][tti_offset])[0]; //x1
				((int16_t *)&txdataF[0][tti_offset+2])[1] += ((int16_t *)&txdataF[1][tti_offset])[1];
				((int16_t *)&txdataF[1][tti_offset+2])[0] += ((int16_t *)&txdataF[0][tti_offset])[0];  //x0*
				((int16_t *)&txdataF[1][tti_offset+2])[1] += -((int16_t *)&txdataF[0][tti_offset])[1];
		
				re++;														// skip pilots
				*re_allocated = *re_allocated + 1;
			}
			re++;  															// adjacent carriers are taken care of by precoding
			*re_allocated = *re_allocated + 1;   							// incremented variable but never used
		}
    }
  }

  return(0);
}


118 119
int dlsch_modulation_NB_IoT(int32_t 				**txdataF,
							int16_t 				amp,
120
							LTE_DL_FRAME_PARMS 	    *frame_parms,
121
							uint8_t 				control_region_size,      // control region size for LTE , values between 0..3, (0 for stand-alone / 1, 2 or 3 for in-band)
Matthieu Kanj's avatar
Matthieu Kanj committed
122
							NB_IoT_eNB_NDLSCH_t     *dlsch0,
123 124 125
							int 					G,						  // number of bits per subframe
							unsigned 				npdsch_data_subframe,     // subframe index of the data table of npdsch channel (G*Nsf)  , values are between 0..Nsf  			
							unsigned short 			NB_IoT_RB_ID)
Matthieu Kanj's avatar
Matthieu Kanj committed
126 127 128
{
    //uint8_t harq_pid = dlsch0->current_harq_pid;
    //NB_IoT_DL_eNB_HARQ_t *dlsch0_harq = dlsch0->harq_processes[harq_pid];
129 130 131
    uint32_t 		jj = 0;
	uint32_t 		re_allocated,symbol_offset;
    uint16_t 		l;
132
    uint8_t 		id_offset,pilot_shift,pilots = 0; 
133 134 135 136 137
	unsigned short 	bandwidth_even_odd;
    unsigned short 	NB_IoT_start, RB_IoT_ID;

    re_allocated = 0;
	id_offset    = 0;
138
	pilot_shift  = 0;
Matthieu Kanj's avatar
Matthieu Kanj committed
139
	// testing if the total number of RBs is even or odd 
140 141
	bandwidth_even_odd  =  frame_parms->N_RB_DL % 2; 	 	// 0 even, 1 odd
	RB_IoT_ID 			=  NB_IoT_RB_ID;
Matthieu Kanj's avatar
Matthieu Kanj committed
142 143
	// step  5, 6, 7   									 	// modulation and mapping (slot 1, symbols 0..3)
	for (l=control_region_size; l<14; l++) { 								 	// loop on OFDM symbols	
144
		if((l>=4 && l<=7) || (l>=11 && l<=13))
Matthieu Kanj's avatar
Matthieu Kanj committed
145
		{
146
			pilots = 1;
147 148 149 150
			if(l==4 || l==6 || l==11 || l==13)
			{
				pilot_shift  = 1;
			}
Matthieu Kanj's avatar
Matthieu Kanj committed
151
		} else {
152
			pilots = 0;
Matthieu Kanj's avatar
Matthieu Kanj committed
153
		}
154
		id_offset = frame_parms->Nid_cell % 6;    			// Cell_ID_NB_IoT % 6
Matthieu Kanj's avatar
Matthieu Kanj committed
155 156
		if(RB_IoT_ID < (frame_parms->N_RB_DL/2))
		{
157
			NB_IoT_start = frame_parms->ofdm_symbol_size - 12*(frame_parms->N_RB_DL/2) - (bandwidth_even_odd*6) + 12*(RB_IoT_ID % (int)(ceil(frame_parms->N_RB_DL/(float)2)));
Matthieu Kanj's avatar
Matthieu Kanj committed
158
		} else {
159
			NB_IoT_start = 1 + (bandwidth_even_odd*6) + 12*(RB_IoT_ID % (int)(ceil(frame_parms->N_RB_DL/(float)2)));
Matthieu Kanj's avatar
Matthieu Kanj committed
160 161
		}
		symbol_offset = frame_parms->ofdm_symbol_size*l + NB_IoT_start;  						// symbol_offset = 512 * L + NB_IOT_RB start
162

Matthieu Kanj's avatar
Matthieu Kanj committed
163
		allocate_REs_in_RB_NB_IoT(frame_parms,
164 165 166
								  txdataF,
								  &jj,
								  symbol_offset,
Matthieu Kanj's avatar
Matthieu Kanj committed
167
								  &dlsch0->harq_process_sib1.s_e[G*npdsch_data_subframe],
168 169 170
								  pilots,
								  amp,
								  id_offset,
171
								  pilot_shift,
172
								  &re_allocated);
Matthieu Kanj's avatar
Matthieu Kanj committed
173 174 175 176 177
	}
	
 // VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_DLSCH_MODULATION, VCD_FUNCTION_OUT);
  return (re_allocated);
}