Commit 4deb7c54 authored by Matthieu Kanj's avatar Matthieu Kanj

add broadcast channel function for NB-IoT/Tail-biting convolutional...

add broadcast channel function for NB-IoT/Tail-biting convolutional coding/rate matching/gold sequence/pilots generation function
parent da4afbd4
/***********************************************************************
**********************************************************************/
/*! \file PHY/LTE_CODING/ccoding_byte_NB_IoT.c
* \Fucntions for CRC attachment and tail-biting convolutional coding for NPBCH channel, TS 36-212, V13.4.0 2017-02
* \author M. KANJ
* \date 2017
* \version 0.0
* \company bcom
* \email: matthieu.kanj@b-com.com
* \note
* \warning
*/
#include "defs.h"
#include "defs_NB_IoT.h"
unsigned char ccodelte_table_NB_IoT[128]; // for transmitter
//unsigned char ccodelte_table_rev[128]; // for receiver
/*************************************************************************
Encodes for an arbitrary convolutional code of rate 1/3
with a constraint length of 7 bits.
The inputs are bit packed in octets (from MSB to LSB).
An optional 8-bit CRC (3GPP) can be added.
Trellis tail-biting is included here
*************************************************************************/
void ccode_encode_NB_IoT (int32_t numbits,
uint8_t add_crc,
uint8_t *inPtr,
uint8_t *outPtr,
uint16_t rnti)
{
uint32_t state;
uint8_t c, out, first_bit;
int8_t shiftbit=0;
uint16_t c16;
uint16_t next_last_byte=0;
uint32_t crc=0;
/* The input bit is shifted in position 8 of the state.
Shiftbit will take values between 1 and 8 */
state = 0;
if (add_crc == 2) {
crc = crc16(inPtr,numbits); // crc is 2 bytes
// scramble with RNTI
crc ^= (((uint32_t)rnti)<<16); // XOR with crc
first_bit = 2;
c = (uint8_t)((crc>>16)&0xff);
} else {
next_last_byte = numbits>>3;
first_bit = (numbits-6)&7;
c = inPtr[next_last_byte-1];
}
// Perform Tail-biting
// get bits from last byte of input (or crc)
for (shiftbit = 0 ; shiftbit <(8-first_bit) ; shiftbit++) {
if ((c&(1<<(7-first_bit-shiftbit))) != 0)
state |= (1<<shiftbit);
}
state = state & 0x3f; // true initial state of Tail-biting CCode
state<<=1; // because of loop structure in CCode
while (numbits > 0) { // Tail-biting is applied to input bits , input 34 bits , output 102 bits
c = *inPtr++;
for (shiftbit = 7; (shiftbit>=0) && (numbits>0); shiftbit--,numbits--) {
state >>= 1;
if ((c&(1<<shiftbit)) != 0) {
state |= 64;
}
out = ccodelte_table_NB_IoT[state];
*outPtr++ = out & 1;
*outPtr++ = (out>>1)&1;
*outPtr++ = (out>>2)&1;
}
}
// now code 16-bit CRC for DCI // Tail-biting is applied to CRC bits , input 16 bits , output 48 bits
if (add_crc == 2) {
c16 = (uint16_t)(crc>>16);
for (shiftbit = 15; (shiftbit>=0); shiftbit--) {
state >>= 1;
if ((c16&(1<<shiftbit)) != 0) {
state |= 64;
}
out = ccodelte_table_NB_IoT[state];
*outPtr++ = out & 1;
*outPtr++ = (out>>1)&1;
*outPtr++ = (out>>2)&1;
}
}
}
/*************************************************************************
Functions to initialize the code tables
*************************************************************************/
/* Basic code table initialization for constraint length 7 */
/* Input in MSB, followed by state in 6 LSBs */
void ccodelte_init_NB_IoT(void)
{
unsigned int i, j, k, sum;
for (i = 0; i < 128; i++) {
ccodelte_table_NB_IoT[i] = 0;
/* Compute 3 output bits */
for (j = 0; j < 3; j++) {
sum = 0;
for (k = 0; k < 7; k++)
if ((i & glte[j]) & (1 << k))
sum++;
/* Write the sum modulo 2 in bit j */
ccodelte_table_NB_IoT[i] |= (sum & 1) << j;
}
}
}
/***********************************************************************
**********************************************************************/
/*! \file PHY/LTE_CODING/lte_rate_matching_NB_IoT.c
* \Procedures for rate matching/interleaving for NB-IoT (turbo-coded transport channels) (TX/RX), TS 36-212, V13.4.0 2017-02
* \author M. KANJ
* \date 2017
* \version 0.0
* \company bcom
* \email: matthieu.kanj@b-com.com
* \note
* \warning
*/
#ifdef MAIN
#include <stdio.h>
#include <stdlib.h>
#endif
#include "PHY/defs.h"
#include "assertions.h"
#include "PHY/defs_NB_IoT.h"
static uint32_t bitrev_cc[32] = {1,17,9,25,5,21,13,29,3,19,11,27,7,23,15,31,0,16,8,24,4,20,12,28,2,18,10,26,6,22,14,30};
uint32_t sub_block_interleaving_cc_NB_IoT(uint32_t D, uint8_t *d,uint8_t *w)
{
uint32_t RCC = (D>>5), ND, ND3; // D = 50 ,
uint32_t row,col,Kpi,index;
uint32_t index3,k;
if ((D&0x1f) > 0)
RCC++;
Kpi = (RCC<<5); // Kpi = 32
ND = Kpi - D;
ND3 = ND*3; // ND3 = ND*3 = 18 *3 = 54
k=0;
for (col=0; col<32; col++) {
index = bitrev_cc[col];
index3 = 3*index;
for (row=0; row<RCC; row++) {
w[k] = d[(int32_t)index3-(int32_t)ND3];
w[Kpi+k] = d[(int32_t)index3-(int32_t)ND3+1];
w[(Kpi<<1)+k] = d[(int32_t)index3-(int32_t)ND3+2];
index3+=66;
index+=32;
k++;
}
}
return(RCC);
}
uint32_t lte_rate_matching_cc_NB_IoT(uint32_t RCC, // RRC = 2
uint16_t E, // E = 1600
uint8_t *w, // length 192
uint8_t *e) // length 1600
{
uint32_t ind=0,k;
uint16_t Kw = 3*(RCC<<5); // 3*64 = 192
for (k=0; k<E; k++) {
while(w[ind] == LTE_NULL) {
ind++;
if (ind==Kw)
ind=0;
}
e[k] = w[ind];
ind++;
if (ind==Kw)
ind=0;
}
return(E);
}
/*******************************************************************************
*******************************************************************************/
/*! \file PHY/LTE_REFSIG/defs_NB_IoT.c
* \function called by lte_dl_cell_spec_NB_IoT.c , TS 36-211, V13.4.0 2017-02
* \author M. KANJ
* \date 2017
* \version 0.0
* \company bcom
* \email: matthieu.kanj@b-com.com
* \note
* \warning
*/
/* Definitions for NB_IoT Reference signals */
#ifndef __LTE_REFSIG_DEFS_NB_IOT__H__
#define __LTE_REFSIG_DEFS_NB_IOT__H__
#include "PHY/defs.h"
#include "PHY/defs_NB_IoT.h"
/** @ingroup _PHY_REF_SIG
* @{
*/
/*!\brief This function generates the LTE Gold sequence (36-211, Sec 7.2), specifically for DL reference signals.
@param frame_parms LTE DL Frame parameters
@param lte_gold_table pointer to table where sequences are stored
@param Nid_cell Cell Id for NB_IoT (to compute sequences for local and adjacent cells) */
void lte_gold_NB_IoT(LTE_DL_FRAME_PARMS *frame_parms,uint32_t lte_gold_table[20][2][14],uint16_t Nid_cell);
/*! \brief This function generates the Narrowband reference signal (NRS) sequence (36-211, Sec 6.10.1.1)
@param phy_vars_eNB Pointer to eNB variables
@param output Output vector for OFDM symbol (Frequency Domain)
@param amp Q15 amplitude
@param Ns Slot number (0..19)
@param l symbol (0,1) - Note 1 means 3!
@param p antenna index
@param RB_IoT_ID the ID of the RB dedicated for NB_IoT
*/
int lte_dl_cell_spec_NB_IoT(PHY_VARS_eNB *phy_vars_eNB,
int32_t *output,
short amp,
unsigned char Ns,
unsigned char l,
unsigned char p
unsigned short RB_IoT_ID);
#endif
/***********************************************************************
**********************************************************************/
/*! \file PHY/LTE_REFSIG/lte_dl_cell_spec_NB_IoT.c
* \function called by pilots_NB_IoT.c , TS 36-211, V13.4.0 2017-02
* \author M. KANJ
* \date 2017
* \version 0.0
* \company bcom
* \email: matthieu.kanj@b-com.com
* \note
* \warning
*/
#ifdef USER_MODE
#include <stdio.h>
#include <stdlib.h>
#endif
#include "defs.h"
#include "PHY/defs.h"
#include "defs_NB_IoT.h"
#include "PHY/defs_NB_IoT.h"
int lte_dl_cell_spec_NB_IoT(PHY_VARS_eNB *phy_vars_eNB,
int32_t *output,
short amp,
unsigned char Ns,
unsigned char l,
unsigned char p,
unsigned short RB_IoT_ID) // the ID of the RB dedicated for NB_IoT
{
unsigned char nu,mprime,mprime_dword,mprime_qpsk_symb,m;
unsigned short k,a;
unsigned short NB_IoT_start,bandwidth_even_odd;
int32_t qpsk[4];
a = (amp*ONE_OVER_SQRT2_Q15)>>15;
((short *)&qpsk[0])[0] = a;
((short *)&qpsk[0])[1] = a;
((short *)&qpsk[1])[0] = -a;
((short *)&qpsk[1])[1] = a;
((short *)&qpsk[2])[0] = a;
((short *)&qpsk[2])[1] = -a;
((short *)&qpsk[3])[0] = -a;
((short *)&qpsk[3])[1] = -a;
if ((p==0) && (l==0) )
nu = 0;
else if ((p==0) && (l>0))
nu = 3;
else if ((p==1) && (l==0))
nu = 3;
else if ((p==1) && (l>0))
nu = 0;
else {
printf("lte_dl_cell_spec: p %d, l %d -> ERROR\n",p,l);
return(-1);
}
// testing if the total number of RBs is even or odd
bandwidth_even_odd = frame_parms->N_RB_DL % 2; // 0 even, 1 odd
mprime = 0; // mprime = 0,1 for NB_IoT // for LTE , maximum number of resources blocks (110) - the total number of RB in the selected bandwidth (.... 15 , 25 , 50, 100)
k = (nu + phy_vars_eNB->lte_frame_parms.nushift)%6;
if(RB_IoT_ID < (phy_vars_eNB->lte_frame_parms.N_RB_DL/2))
{
NB_IoT_start = phy_vars_eNB->lte_frame_parms.ofdm_symbol_size - 12*(phy_vars_eNB->lte_frame_parms.N_RB_DL/2) - (bandwidth_even_odd*6) + 12*(RB_IoT_ID%(ceil(phy_vars_eNB->lte_frame_parms.N_RB_DL/(float)2)));
} else {
NB_IoT_start = (bandwidth_even_odd*6) + 12*(RB_IoT_ID%(ceil(phy_vars_eNB->lte_frame_parms.N_RB_DL/(float)2)));
}
k+=NB_IoT_start;
DevAssert( Ns < 20 );
DevAssert( l < 2 );
for (m=0; m<2; m++) {
output[k] = qpsk[(phy_vars_eNB->lte_gold_table_NB_IoT[Ns][l][0]) & 3];
k+=6;
}
return(0);
}
/***********************************************************************
**********************************************************************/
/*! \file PHY/LTE_REFSIG/lte_gold_NB_IoT.c
* \function called by lte_dl_cell_spec_NB_IoT.c , TS 36-211, V13.4.0 2017-02
* \author M. KANJ
* \date 2017
* \version 0.0
* \company bcom
* \email: matthieu.kanj@b-com.com
* \note
* \warning
*/
#include "defs.h"
#include "defs_NB_IoT.h"
void lte_gold_NB_IoT(LTE_DL_FRAME_PARMS *frame_parms,uint32_t lte_gold_table_NB_IoT[20][2][14],uint16_t Nid_cell) // Nid_cell = Nid_cell_NB_IoT
{
unsigned char ns,l,Ncp=1;
unsigned int n,x1,x2;
for (ns=0; ns<20; ns++) {
for (l=0; l<2; l++) {
x2 = Ncp +
(Nid_cell<<1) +
(((1+(Nid_cell<<1))*(1 + (l+5) + (7*(1+ns))))<<10); //cinit
x1 = 1+ (1<<31);
x2 = x2 ^ ((x2 ^ (x2>>1) ^ (x2>>2) ^ (x2>>3))<<31);
// skip first 50 double words (1600 bits)
for (n=1; n<50; n++) {
x1 = (x1>>1) ^ (x1>>4);
x1 = x1 ^ (x1<<31) ^ (x1<<28);
x2 = (x2>>1) ^ (x2>>2) ^ (x2>>3) ^ (x2>>4);
x2 = x2 ^ (x2<<31) ^ (x2<<30) ^ (x2<<29) ^ (x2<<28);
}
for (n=0; n<14; n++) {
x1 = (x1>>1) ^ (x1>>4);
x1 = x1 ^ (x1<<31) ^ (x1<<28);
x2 = (x2>>1) ^ (x2>>2) ^ (x2>>3) ^ (x2>>4);
x2 = x2 ^ (x2<<31) ^ (x2<<30) ^ (x2<<29) ^ (x2<<28);
lte_gold_table_NB_IoT[ns][l][n] = x1^x2;
}
}
}
}
// \brief gold sequenquence generator
//\param x1
//\param x2 this should be set to c_init if reset=1
//\param reset resets the generator
//\return 32 bits of the gold sequence
unsigned int lte_gold_generic_NB_IoT(unsigned int *x1, unsigned int *x2, unsigned char reset)
{
int n;
if (reset) {
*x1 = 1+ (1<<31);
*x2=*x2 ^ ((*x2 ^ (*x2>>1) ^ (*x2>>2) ^ (*x2>>3))<<31);
for (n=1; n<50; n++) {
*x1 = (*x1>>1) ^ (*x1>>4);
*x1 = *x1 ^ (*x1<<31) ^ (*x1<<28);
*x2 = (*x2>>1) ^ (*x2>>2) ^ (*x2>>3) ^ (*x2>>4);
*x2 = *x2 ^ (*x2<<31) ^ (*x2<<30) ^ (*x2<<29) ^ (*x2<<28);
}
}
*x1 = (*x1>>1) ^ (*x1>>4);
*x1 = *x1 ^ (*x1<<31) ^ (*x1<<28);
*x2 = (*x2>>1) ^ (*x2>>2) ^ (*x2>>3) ^ (*x2>>4);
*x2 = *x2 ^ (*x2<<31) ^ (*x2<<30) ^ (*x2<<29) ^ (*x2<<28);
return(*x1^*x2);
}
/***********************************************************************
**********************************************************************/
/*! \file PHY/LTE_TRANSPORT/npbch_NB_IoT.c
* \Fucntions for the generation of broadcast channel (NPBCH) for NB_IoT, TS 36-212, V13.4.0 2017-02
* \author M. KANJ
* \date 2017
* \version 0.0
* \company bcom
* \email: matthieu.kanj@b-com.com
* \note
* \warning
*/
#include "PHY/defs.h"
#include "PHY/CODING/extern.h"
#include "PHY/CODING/lte_interleaver_inline.h"
#include "defs.h"
#include "extern.h"
#include "PHY/extern.h"
#include "PHY/sse_intrin.h"
#ifdef PHY_ABSTRACTION
#include "SIMULATION/TOOLS/defs.h"
#endif
#ifdef OPENAIR2
#include "PHY_INTERFACE/defs.h"
#endif
#define NPBCH_A 34 // 34 for NB-IoT and 24 for LTE
int allocate_npbch_REs_in_RB(LTE_DL_FRAME_PARMS *frame_parms,
int32_t **txdataF,
uint32_t *jj,
uint32_t symbol_offset,
uint8_t *x0,
uint8_t pilots,
int16_t amp,
unsigned short id_offset,
uint32_t *re_allocated) // not used variable ??!!
{
MIMO_mode_t mimo_mode = (frame_parms->mode1_flag==1)?SISO:ALAMOUTI;
uint32_t tti_offset,aa;
uint8_t re, diff_re;
int16_t gain_lin_QPSK;
uint8_t first_re,last_re;
int32_t tmp_sample1,tmp_sample2;
gain_lin_QPSK = (int16_t)((amp*ONE_OVER_SQRT2_Q15)>>15);
first_re=0;
last_re=12;
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
if (pilots != 1 || re%3 != id_offset) // if re is not a pilot
{
// diff_re = re%3 - id_offset;
if (mimo_mode == SISO) { //SISO mapping
*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++) {
((int16_t*)&txdataF[aa][tti_offset])[1] += (x0[*jj]==1) ? (-gain_lin_QPSK) : gain_lin_QPSK; //Q //b_{i+1}
}
*jj = *jj + 1;
} else if (mimo_mode == ALAMOUTI) {
*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
((int16_t*)&txdataF[0][tti_offset])[0] += (int16_t)((((int16_t*)&tmp_sample1)[0]*ONE_OVER_SQRT2_Q15)>>15);
((int16_t*)&txdataF[0][tti_offset])[1] += (int16_t)((((int16_t*)&tmp_sample1)[1]*ONE_OVER_SQRT2_Q15)>>15);
((int16_t*)&txdataF[1][tti_offset])[0] += (int16_t)((((int16_t*)&tmp_sample2)[0]*ONE_OVER_SQRT2_Q15)>>15);
((int16_t*)&txdataF[1][tti_offset])[1] += (int16_t)((((int16_t*)&tmp_sample2)[1]*ONE_OVER_SQRT2_Q15)>>15);
// 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);
}
/**********************************************************
**********************************************************/
int generate_npbch(NB_IoT_eNB_NPBCH *eNB_npbch,
int32_t **txdataF,
int amp,
LTE_DL_FRAME_PARMS *frame_parms,
uint8_t *npbch_pdu,
uint8_t frame_mod64
unsigned short NB_IoT_RB_ID)
{
int i, l;
uint32_t npbch_D,npbch_E;
uint8_t npbch_a[5]; // 34/8 =4.25 => 4 bytes and 2 bits
uint8_t RCC;
unsigned short bandwidth_even_odd;
unsigned short NB_IoT_start, RB_IoT_ID;
uint32_t nsymb = 14;
uint32_t pilots;
uint32_t second_pilot = 4;
uint32_t jj=0;
uint32_t re_allocated=0;
uint32_t rb, symbol_offset;
uint16_t amask=0;
npbch_D = 16+NPBCH_A;
npbch_E = 1600;
if (frame_mod64==0) {
bzero(npbch_a,5); // initializing input data stream , filling with zeros
bzero(eNB_npbch->npbch_e,pbch_E); // filling with "0" the table pbch_e[1600]
memset(eNB_npbch->npbch_d,LTE_NULL,66); // filling with "2" the first 96 elements of table pbch_d[216]
for (i=0; i<5; i++) // set input bits stream
{
if (i !=4 )
{
npbch_a[5-i-1] = npbch_pdu[i]; // ????????/*****?? in LTE 24 bits with 3 bytes, but in NB_IoT 34 bits will require 4 bytes+2 bits !! to verify
} else {
npbch_a[5-i-1]= npbch_pdu[i] & 0x03;
}
}
if (frame_parms->mode1_flag == 1) // setting CRC mask depending on the number of used eNB antennas
amask = 0x0000;
else {
switch (frame_parms->nb_antennas_tx_eNB) { // *****???? better replacing nb_antennas_tx_eNB by nb_antennas_tx_eNB_NB_IoT
case 1:
amask = 0x0000;
break;
case 2:
amask = 0xffff;
break;
}
}
ccode_encode_NB_IoT(NPBCH_A,2,npbch_a,eNB_npbch->npbch_d+66,amask); // step 1 CRC Attachment
RCC = sub_block_interleaving_cc_NB_IoT(npbch_D,eNB_npbch->npbch_d+66,eNB_npbch->npbch_w); // step 2 Channel Coding
lte_rate_matching_cc_NB_IoT(RCC,npbch_E,eNB_npbch->npbch_w,eNB_npbch->npbch_e); // step 3 Rate Matching
npbch_scrambling(frame_parms, // step 4 Scrambling
eNB_npbch->npbch_e,
npbch_E);
}
// testing if the total number of RBs is even or odd
bandwidth_even_odd = frame_parms->N_RB_DL % 2; // 0 even, 1 odd
RB_IoT_ID = NB_IoT_RB_ID;
// step 5, 6, 7 // modulation and mapping (slot 1, symbols 0..3)
for (l=3; l<14; l++) { // loop on OFDM symbols
if((l>=4 && l<=8) || (l>=11 && l<=13))
{
pilots =1;
} else {
pilots=0;
}
id_offset = frame_parms->Nid_cell % 3; // Cell_ID_NB_IoT % 3
if(RB_IoT_ID < (frame_parms->N_RB_DL/2))
{
NB_IoT_start = frame_parms->ofdm_symbol_size - 12*(frame_parms->N_RB_DL/2) - (bandwidth_even_odd*6) + 12*(RB_IoT_ID%(ceil(frame_parms->N_RB_DL/(float)2)));
} else {
NB_IoT_start = (bandwidth_even_odd*6) + 12*(RB_IoT_ID%(ceil(frame_parms->N_RB_DL/(float)2)));
}
symbol_offset = frame_parms->ofdm_symbol_size*l + NB_IoT_start; // symbol_offset = 512 * L + NB_IOT_RB start
allocate_npbch_REs_in_RB(frame_parms,
txdataF,
&jj,
symbol_offset,
&eNB_npbch->npbch_e[(frame_mod64/8)*(npbch_E>>3)],
pilots,
amp,
id_offset,
&re_allocated);
}
return(0);
}
/**********************************************************
**********************************************************/
void npbch_scrambling(LTE_DL_FRAME_PARMS *frame_parms,
uint8_t *npbch_e,
uint32_t length) // 1600
{
int i;
uint8_t reset;
uint32_t x1, x2, s=0;
reset = 1;
x2 = frame_parms->Nid_cell;
for (i=0; i<length; i++) {
if ((i&0x1f)==0) {
s = lte_gold_generic_NB_IoT(&x1, &x2, reset);
reset = 0;
}
npbch_e[i] = (npbch_e[i]&1) ^ ((s>>(i&0x1f))&1);
}
}
/***********************************************************************
**********************************************************************/
/*! \file PHY/LTE_TRANSPORT/pilots_NB_IoT.c
* \Generation of Reference signal (RS) for NB-IoT, TS 36-211, V13.4.0 2017-02
* \author M. KANJ
* \date 2017
* \version 0.0
* \company bcom
* \email: matthieu.kanj@b-com.com
* \note
* \warning
*/
#include "PHY/defs.h"
void generate_pilots_NB_IoT(PHY_VARS_eNB *phy_vars_eNB,
int32_t **txdataF,
int16_t amp,
uint16_t Ntti, // Ntti = 10
unsigned short RB_IoT_ID, // RB reserved for NB-IoT
unsigned short With_NSSS;) // With_NSSS = 1; if the frame include a sub-Frame with NSSS signal
{
LTE_DL_FRAME_PARMS *frame_parms = &phy_vars_eNB->lte_frame_parms;
uint32_t tti,tti_offset,slot_offset,Nsymb,samples_per_symbol;
uint8_t first_pilot,second_pilot;
Nsymb = 14;
first_pilot = 5; // first pilot position
second_pilot = 6; // second pilot position
for (tti=0; tti<Ntti; tti++) { // loop on sub-frames
tti_offset = tti*frame_parms->ofdm_symbol_size*Nsymb; // begins with 0
samples_per_symbol = frame_parms->ofdm_symbol_size; // ex. 512
slot_offset = (tti*2)%20; // 0, 2, 4, ....... 18
if((slot_offset != 10) && ((With_NSSS*slot_offset) != 18)) { // condition to avoid NPSS and NSSS signals
//Generate Pilots for slot 0 and 1
//antenna 0 symbol 5 slot 0
lte_dl_cell_spec_NB_IoT(phy_vars_eNB,&txdataF[0][tti_offset + (first_pilot*samples_per_symbol)], // tti_offset 512 x 32 bits
amp,
RB_IoT_ID,
slot_offset,
0,
0);
//antenna 0 symbol 6 slot 0
lte_dl_cell_spec_NB_IoT(phy_vars_eNB,&txdataF[0][tti_offset + (second_pilot*samples_per_symbol)],
amp,
RB_IoT_ID,
slot_offset,
1,
0);
//antenna 0 symbol 5 slot 1
lte_dl_cell_spec_NB_IoT(phy_vars_eNB,&txdataF[0][tti_offset + (7*samples_per_symbol) + (first_pilot*samples_per_symbol)],
amp,
RB_IoT_ID,
1+slot_offset,
0,
0);
//antenna 0 symbol 6 slot 1
lte_dl_cell_spec_NB_IoT(phy_vars_eNB,&txdataF[0][tti_offset + (7*samples_per_symbol) + (second_pilot*samples_per_symbol)],
amp,
RB_IoT_ID,
1+slot_offset,
1,
0);
if (frame_parms->nb_antennas_tx > 1) { // Pilots generation with two antennas
// antenna 1 symbol 5 slot 0
lte_dl_cell_spec_NB_IoT(phy_vars_eNB,&txdataF[1][tti_offset + (first_pilot*samples_per_symbol)],
amp,
RB_IoT_ID,
slot_offset,
0,
1);
// antenna 1 symbol 6 slot 0
lte_dl_cell_spec_NB_IoT(phy_vars_eNB,&txdataF[1][tti_offset + (second_pilot*samples_per_symbol)],
amp,
RB_IoT_ID,
slot_offset,
1,
1);
//antenna 1 symbol 5 slot 1
lte_dl_cell_spec_NB_IoT(phy_vars_eNB,&txdataF[1][tti_offset + (7*samples_per_symbol) + (first_pilot*samples_per_symbol)],
amp,
RB_IoT_ID,
1+slot_offset,
0,
1);
// antenna 1 symbol 6 slot 1
lte_dl_cell_spec_NB_IoT(phy_vars_eNB,&txdataF[1][tti_offset + (7*samples_per_symbol) + (second_pilot*samples_per_symbol)],
amp,
RB_IoT_ID,
1+slot_offset,
1,
1);
}
}
}
}
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