Commit 7bec8575 authored by Matthieu Kanj's avatar Matthieu Kanj

Merge branch 'develop-nb-iot-mac' of...

Merge branch 'develop-nb-iot-mac' of https://gitlab.eurecom.fr/oai/openairinterface5g into develop-nb-iot-mac
parents ec2b045d 8cd9b164
...@@ -2120,6 +2120,8 @@ uint8_t generate_dci_top(uint8_t num_ue_spec_dci, ...@@ -2120,6 +2120,8 @@ uint8_t generate_dci_top(uint8_t num_ue_spec_dci,
// generate DCIs in order of decreasing aggregation level, then common/ue spec // generate DCIs in order of decreasing aggregation level, then common/ue spec
// MAC is assumed to have ordered the UE spec DCI according to the RNTI-based randomization // MAC is assumed to have ordered the UE spec DCI according to the RNTI-based randomization
for (L=3; L>=0; L--) { for (L=3; L>=0; L--) {
//first common DCI
for (i=0; i<num_common_dci; i++) { for (i=0; i<num_common_dci; i++) {
if (dci_alloc[i].L == (uint8_t)L) { if (dci_alloc[i].L == (uint8_t)L) {
...@@ -2140,6 +2142,7 @@ uint8_t generate_dci_top(uint8_t num_ue_spec_dci, ...@@ -2140,6 +2142,7 @@ uint8_t generate_dci_top(uint8_t num_ue_spec_dci,
} }
} }
//start the second loop from the end of the previous one for ue specific DCI
for (; i<num_ue_spec_dci + num_common_dci; i++) { for (; i<num_ue_spec_dci + num_common_dci; i++) {
if (dci_alloc[i].L == (uint8_t)L) { if (dci_alloc[i].L == (uint8_t)L) {
......
/******************************************************************************* /*
* Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
*******************************************************************************/ * contributor license agreements. See the NOTICE file distributed with
/*! \file PHY/LTE_TRANSPORT/dci_NB_IoT.c * this work for additional information regarding copyright ownership.
* \brief Top-level routines for implementing Tail-biting convolutional coding for transport channels (NPDCCH) for NB_IoT, TS 36-212, V13.4.0 2017-02 * The OpenAirInterface Software Alliance licenses this file to You under
* \author M. KANJ * the OAI Public License, Version 1.0 (the "License"); you may not use this file
* \date 2017 * except in compliance with the License.
* \version 0.0 * You may obtain a copy of the License at
* \company bcom *
* \email: matthieu.kanj@b-com.com * 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 PHY/LTE_TRANSPORT/dci.c
* \brief Implements PDCCH physical channel TX/RX procedures (36.211) and DCI encoding/decoding (36.212/36.213). Current LTE compliance V8.6 2009-03.
* \author R. Knopp
* \date 2011
* \version 0.1
* \company Eurecom
* \email: knopp@eurecom.fr
* \note * \note
* \warning * \warning
*/ */
#ifdef USER_MODE #ifdef USER_MODE
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
...@@ -20,23 +37,29 @@ ...@@ -20,23 +37,29 @@
#include "PHY/defs.h" #include "PHY/defs.h"
#include "PHY/extern.h" #include "PHY/extern.h"
#include "SCHED/defs.h" #include "SCHED/defs.h"
#include "SIMULATION/TOOLS/defs.h" #include "SIMULATION/TOOLS/defs.h" // for taus
#include "PHY/sse_intrin.h" #include "PHY/sse_intrin.h"
#include "assertions.h" #include "assertions.h"
#include "T.h" #include "T.h"
//------------------------------------------------
// BCOM code functions npdcch start
// (TODO solve some error in compilation)
//------------------------------------------------
static uint8_t d[2][3*(MAX_DCI_SIZE_BITS_NB_IOT + 16) + 96]; static uint8_t d[2][3*(MAX_DCI_SIZE_BITS_NB_IOT + 16) + 96];
static uint8_t w[2][3*3*(MAX_DCI_SIZE_BITS_NB_IOT+16)]; static uint8_t w[2][3*3*(MAX_DCI_SIZE_BITS_NB_IOT+16)];
void dci_encoding_NB_IoT(uint8_t *a[2], // Table of two DCI, even if one DCI is to transmit , the number of DCI is indicated in dci_number /*
uint8_t A, // Length of table a void dci_encoding_NB_IoT(uint8_t *a[2], // Array of two DCI pdus, even if one DCI is to transmit , the number of DCI is indicated in dci_number
uint8_t A, // Length of array a (in number of bytes)(es 4 bytes = 32 bits) is a parameter fixed
uint16_t E, // E should equals to G (number of available bits in one RB) uint16_t E, // E should equals to G (number of available bits in one RB)
uint8_t *e[2], // *e should be e[2][G] uint8_t *e[2], // *e should be e[2][G]
uint16_t rnti[2], // RNTI for UE specific or common search space uint16_t rnti[2], // RNTI for UE specific or common search space
uint8_t dci_number, // This variable should takes the 1 or 2 (1 for in case of one DCI, 2 in case of two DCI) uint8_t dci_number, // This variable should takes the 1 or 2 (1 for in case of one DCI, 2 in case of two DCI)
uint8_t agr_level) // Aggregation level uint8_t agr_level) // Aggregation level
{ {
uint8_t D = (A + 16); uint8_t D = (A + 16);
uint32_t RCC; uint32_t RCC;
...@@ -51,13 +74,13 @@ void dci_encoding_NB_IoT(uint8_t *a[2], // Table of two DCI, even if one DCI ...@@ -51,13 +74,13 @@ void dci_encoding_NB_IoT(uint8_t *a[2], // Table of two DCI, even if one DCI
occupation_size=2; occupation_size=2;
} }
memset((void *)d[0],LTE_NULL,96); memset((void *)d[0],LTE_NULL,96);
ccode_encode_NB_IoT(A,2,a[0],d[0]+96,rnti[0]); // CRC attachement & Tail-biting convolutional coding ccode_encode_NB_IoT(A,2,a[0],d[0]+96,rnti[0]); // CRC attachement & Tail-biting convolutional coding
RCC = sub_block_interleaving_cc_NB_IoT(D,d[0]+96,w[0]); // Interleaving RCC = sub_block_interleaving_cc_NB_IoT(D,d[0]+96,w[0]); // Interleaving
lte_rate_matching_cc_NB_IoT(RCC,(E/occupation_size),w[0],e[0]); // Rate Matching lte_rate_matching_cc_NB_IoT(RCC,(E/occupation_size),w[0],e[0]); // Rate Matching
}else if (dci_number == 2) { }else if (dci_number == 2) {
memset((void *)d[0],LTE_NULL,96); memset((void *)d[0],LTE_NULL,96);
memset((void *)d[1],LTE_NULL,96); memset((void *)d[1],LTE_NULL,96);
// first DCI encoding // first DCI encoding
...@@ -68,26 +91,26 @@ void dci_encoding_NB_IoT(uint8_t *a[2], // Table of two DCI, even if one DCI ...@@ -68,26 +91,26 @@ void dci_encoding_NB_IoT(uint8_t *a[2], // Table of two DCI, even if one DCI
ccode_encode_NB_IoT(A,2,a[1],d[1]+96,rnti[1]); // CRC attachement & Tail-biting convolutional coding ccode_encode_NB_IoT(A,2,a[1],d[1]+96,rnti[1]); // CRC attachement & Tail-biting convolutional coding
RCC = sub_block_interleaving_cc_NB_IoT(D,d[1]+96,w[1]); // Interleaving RCC = sub_block_interleaving_cc_NB_IoT(D,d[1]+96,w[1]); // Interleaving
lte_rate_matching_cc_NB_IoT(RCC,E/2,w[1],e[1]); // Rate Matching, E/2 , NCCE1 lte_rate_matching_cc_NB_IoT(RCC,E/2,w[1],e[1]); // Rate Matching, E/2 , NCCE1
} }
} }
///The scrambling sequence shall be initialised at the start of the search space and after every 4th NPDCCH subframes. ///The scrambling sequence shall be initialised at the start of the search space and after every 4th NPDCCH subframes.
/// ///
/// ///
void npdcch_scrambling_NB_IoT(NB_IOT_DL_FRAME_PARMS *frame_parms, void npdcch_scrambling_NB_IoT(NB_DL_FRAME_PARMS *frame_parms,
uint8_t *e[2], // Input data uint8_t *e[2], // Input data
int length, // Total number of bits to transmit in one subframe(case of DCI = G) int length, // Total number of bits to transmit in one subframe(case of DCI = G)
uint8_t Ns, // Slot number (0..19) uint8_t Ns,//XXX we pass the subframe // Slot number (0..19)
uint8_t dci_number, // This variable should takes the 1 or 2 (1 for in case of one DCI, 2 in case of two DCI) uint8_t dci_number, // This variable should takes the 1 or 2 (1 for in case of one DCI, 2 in case of two DCI)
uint8_t agr_level) // Aggregation level uint8_t agr_level) // Aggregation level
{ {
int i,j,k=0; int i,j,k=0;
uint32_t x1, x2, s=0; uint32_t x1, x2, s=0;
uint8_t reset; uint8_t reset;
reset = 1; reset = 1;
uint8_t occupation_size=1; uint8_t occupation_size=1;
if(agr_level == 2) if(agr_level == 2)
{ {
occupation_size=1; occupation_size=1;
...@@ -98,7 +121,7 @@ void npdcch_scrambling_NB_IoT(NB_IOT_DL_FRAME_PARMS *frame_parms, ...@@ -98,7 +121,7 @@ void npdcch_scrambling_NB_IoT(NB_IOT_DL_FRAME_PARMS *frame_parms,
if(dci_number == 1) // Case of one DCI if(dci_number == 1) // Case of one DCI
{ {
x2 = ((Ns>>1)<<9) + frame_parms->Nid_cell; // This is c_init in 36.211 Sec 10.2.3.1 x2 = ((Ns>>1)<<9) + frame_parms->Nid_cell; // This is c_init in 36.211 Sec 10.2.3.1
for (i=0; i<length/occupation_size; i++) { for (i=0; i<length/occupation_size; i++) {
if ((i&0x1f)==0) { if ((i&0x1f)==0) {
s = lte_gold_generic_NB_IoT(&x1, &x2, reset); s = lte_gold_generic_NB_IoT(&x1, &x2, reset);
...@@ -106,13 +129,13 @@ void npdcch_scrambling_NB_IoT(NB_IOT_DL_FRAME_PARMS *frame_parms, ...@@ -106,13 +129,13 @@ void npdcch_scrambling_NB_IoT(NB_IOT_DL_FRAME_PARMS *frame_parms,
} }
e[0][k] = (e[0][k]&1) ^ ((s>>(i&0x1f))&1); e[0][k] = (e[0][k]&1) ^ ((s>>(i&0x1f))&1);
} }
}else if(dci_number == 2 && occupation_size == 2) { // Case of two DCI }else if(dci_number == 2 && occupation_size == 2) { // Case of two DCI
// Scrambling the first DCI // Scrambling the first DCI
// //
x2 = ((Ns>>1)<<9) + frame_parms->Nid_cell; // This is c_init in 36.211 Sec 10.2.3.1 x2 = ((Ns>>1)<<9) + frame_parms->Nid_cell; // This is c_init in 36.211 Sec 10.2.3.1
for (i=0; i<length/occupation_size; i++) { for (i=0; i<length/occupation_size; i++) {
if ((i&0x1f)==0) { if ((i&0x1f)==0) {
s = lte_gold_generic_NB_IoT(&x1, &x2, reset); s = lte_gold_generic_NB_IoT(&x1, &x2, reset);
...@@ -125,7 +148,7 @@ void npdcch_scrambling_NB_IoT(NB_IOT_DL_FRAME_PARMS *frame_parms, ...@@ -125,7 +148,7 @@ void npdcch_scrambling_NB_IoT(NB_IOT_DL_FRAME_PARMS *frame_parms,
// Scrambling the second DCI // Scrambling the second DCI
// //
x2 = ((Ns>>1)<<9) + frame_parms->Nid_cell; //this is c_init in 36.211 Sec 10.2.3.1 x2 = ((Ns>>1)<<9) + frame_parms->Nid_cell; //this is c_init in 36.211 Sec 10.2.3.1
for (i=0; i<length/occupation_size; i++) { for (i=0; i<length/occupation_size; i++) {
if ((i&0x1f)==0) { if ((i&0x1f)==0) {
s = lte_gold_generic_NB_IoT(&x1, &x2, reset); s = lte_gold_generic_NB_IoT(&x1, &x2, reset);
...@@ -137,7 +160,7 @@ void npdcch_scrambling_NB_IoT(NB_IOT_DL_FRAME_PARMS *frame_parms, ...@@ -137,7 +160,7 @@ void npdcch_scrambling_NB_IoT(NB_IOT_DL_FRAME_PARMS *frame_parms,
} }
int dci_allocate_REs_in_RB_NB_IoT(NB_IOT_DL_FRAME_PARMS *frame_parms, int dci_allocate_REs_in_RB_NB_IoT(NB_DL_FRAME_PARMS *frame_parms,
int32_t **txdataF, int32_t **txdataF,
uint32_t *jj, uint32_t *jj,
uint32_t symbol_offset, uint32_t symbol_offset,
...@@ -147,7 +170,7 @@ int dci_allocate_REs_in_RB_NB_IoT(NB_IOT_DL_FRAME_PARMS *frame_parms, ...@@ -147,7 +170,7 @@ int dci_allocate_REs_in_RB_NB_IoT(NB_IOT_DL_FRAME_PARMS *frame_parms,
unsigned short id_offset, unsigned short id_offset,
uint32_t *re_allocated, // not used variable ??!! uint32_t *re_allocated, // not used variable ??!!
uint8_t dci_number, // This variable should takes the 1 or 2 (1 for in case of one DCI, 2 in case of two DCI) uint8_t dci_number, // This variable should takes the 1 or 2 (1 for in case of one DCI, 2 in case of two DCI)
uint8_t agr_level) uint8_t agr_level)
{ {
MIMO_mode_t mimo_mode = (frame_parms->mode1_flag==1)?SISO:ALAMOUTI; MIMO_mode_t mimo_mode = (frame_parms->mode1_flag==1)?SISO:ALAMOUTI;
uint32_t tti_offset,aa; uint32_t tti_offset,aa;
...@@ -158,19 +181,19 @@ int dci_allocate_REs_in_RB_NB_IoT(NB_IOT_DL_FRAME_PARMS *frame_parms, ...@@ -158,19 +181,19 @@ int dci_allocate_REs_in_RB_NB_IoT(NB_IOT_DL_FRAME_PARMS *frame_parms,
gain_lin_QPSK = (int16_t)((amp*ONE_OVER_SQRT2_Q15)>>15); gain_lin_QPSK = (int16_t)((amp*ONE_OVER_SQRT2_Q15)>>15);
first_re=0; first_re=0;
last_re=12; last_re=12;
if(agr_level == 2 && dci_number == 1) if(agr_level == 2 && dci_number == 1)
{ {
for (re=first_re; re<last_re; re++) { // re varies between 0 and 12 sub-carriers 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 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 if (pilots != 1 || re%3 != id_offset) // if re is not a pilot
{ {
// diff_re = re%3 - id_offset; // diff_re = re%3 - id_offset;
if (mimo_mode == SISO) { //SISO mapping if (mimo_mode == SISO) { //SISO mapping
*re_allocated = *re_allocated + 1; // variable incremented but never used *re_allocated = *re_allocated + 1; // variable incremented but never used
for (aa=0; aa<frame_parms->nb_antennas_tx; aa++) { for (aa=0; aa<frame_parms->nb_antennas_tx; aa++) {
((int16_t*)&txdataF[aa][tti_offset])[0] += (x0[0][*jj]==1) ? (-gain_lin_QPSK) : gain_lin_QPSK; //I //b_i ((int16_t*)&txdataF[aa][tti_offset])[0] += (x0[0][*jj]==1) ? (-gain_lin_QPSK) : gain_lin_QPSK; //I //b_i
} }
...@@ -178,10 +201,10 @@ int dci_allocate_REs_in_RB_NB_IoT(NB_IOT_DL_FRAME_PARMS *frame_parms, ...@@ -178,10 +201,10 @@ int dci_allocate_REs_in_RB_NB_IoT(NB_IOT_DL_FRAME_PARMS *frame_parms,
for (aa=0; aa<frame_parms->nb_antennas_tx; aa++) { for (aa=0; aa<frame_parms->nb_antennas_tx; aa++) {
((int16_t*)&txdataF[aa][tti_offset])[1] += (x0[0][*jj]==1) ? (-gain_lin_QPSK) : gain_lin_QPSK; //Q //b_{i+1} ((int16_t*)&txdataF[aa][tti_offset])[1] += (x0[0][*jj]==1) ? (-gain_lin_QPSK) : gain_lin_QPSK; //Q //b_{i+1}
} }
*jj = *jj + 1; *jj = *jj + 1;
} else if (mimo_mode == ALAMOUTI) { } else if (mimo_mode == ALAMOUTI) {
*re_allocated = *re_allocated + 1; *re_allocated = *re_allocated + 1;
((int16_t*)&tmp_sample1)[0] = (x0[0][*jj]==1) ? (-gain_lin_QPSK) : gain_lin_QPSK; ((int16_t*)&tmp_sample1)[0] = (x0[0][*jj]==1) ? (-gain_lin_QPSK) : gain_lin_QPSK;
...@@ -201,7 +224,7 @@ int dci_allocate_REs_in_RB_NB_IoT(NB_IOT_DL_FRAME_PARMS *frame_parms, ...@@ -201,7 +224,7 @@ int dci_allocate_REs_in_RB_NB_IoT(NB_IOT_DL_FRAME_PARMS *frame_parms,
((int16_t*)&txdataF[0][tti_offset])[1] += (int16_t)((((int16_t*)&tmp_sample1)[1]*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])[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); ((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 // fill in the rest of the ALAMOUTI precoding
if ( pilots != 1 || (re+1)%3 != id_offset) { 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])[0] += -((int16_t *)&txdataF[1][tti_offset])[0]; //x1
...@@ -213,26 +236,26 @@ int dci_allocate_REs_in_RB_NB_IoT(NB_IOT_DL_FRAME_PARMS *frame_parms, ...@@ -213,26 +236,26 @@ int dci_allocate_REs_in_RB_NB_IoT(NB_IOT_DL_FRAME_PARMS *frame_parms,
((int16_t *)&txdataF[0][tti_offset+2])[1] += ((int16_t *)&txdataF[1][tti_offset])[1]; ((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])[0] += ((int16_t *)&txdataF[0][tti_offset])[0]; //x0*
((int16_t *)&txdataF[1][tti_offset+2])[1] += -((int16_t *)&txdataF[0][tti_offset])[1]; ((int16_t *)&txdataF[1][tti_offset+2])[1] += -((int16_t *)&txdataF[0][tti_offset])[1];
re++; // skip pilots re++; // skip pilots
*re_allocated = *re_allocated + 1; *re_allocated = *re_allocated + 1;
} }
re++; // adjacent carriers are taken care of by precoding re++; // adjacent carriers are taken care of by precoding
*re_allocated = *re_allocated + 1; // incremented variable but never used *re_allocated = *re_allocated + 1; // incremented variable but never used
} }
} }
} }
}else if(agr_level == 1 && dci_number == 1){ }else if(agr_level == 1 && dci_number == 1){
for (re=first_re; re<6; re++) { // re varies between 0 and 6 sub-carriers for (re=first_re; re<6; re++) { // re varies between 0 and 6 sub-carriers
tti_offset = symbol_offset + re; // symbol_offset = 512 * L , re_offset = 512 - 3*12 , re 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 if (pilots != 1 || re%3 != id_offset) // if re is not a pilot
{ {
// diff_re = re%3 - id_offset; // diff_re = re%3 - id_offset;
if (mimo_mode == SISO) { //SISO mapping if (mimo_mode == SISO) { //SISO mapping
*re_allocated = *re_allocated + 1; // variable incremented but never used *re_allocated = *re_allocated + 1; // variable incremented but never used
for (aa=0; aa<frame_parms->nb_antennas_tx; aa++) { for (aa=0; aa<frame_parms->nb_antennas_tx; aa++) {
((int16_t*)&txdataF[aa][tti_offset])[0] += (x0[0][*jj]==1) ? (-gain_lin_QPSK) : gain_lin_QPSK; //I //b_i ((int16_t*)&txdataF[aa][tti_offset])[0] += (x0[0][*jj]==1) ? (-gain_lin_QPSK) : gain_lin_QPSK; //I //b_i
} }
...@@ -240,10 +263,10 @@ int dci_allocate_REs_in_RB_NB_IoT(NB_IOT_DL_FRAME_PARMS *frame_parms, ...@@ -240,10 +263,10 @@ int dci_allocate_REs_in_RB_NB_IoT(NB_IOT_DL_FRAME_PARMS *frame_parms,
for (aa=0; aa<frame_parms->nb_antennas_tx; aa++) { for (aa=0; aa<frame_parms->nb_antennas_tx; aa++) {
((int16_t*)&txdataF[aa][tti_offset])[1] += (x0[0][*jj]==1) ? (-gain_lin_QPSK) : gain_lin_QPSK; //Q //b_{i+1} ((int16_t*)&txdataF[aa][tti_offset])[1] += (x0[0][*jj]==1) ? (-gain_lin_QPSK) : gain_lin_QPSK; //Q //b_{i+1}
} }
*jj = *jj + 1; *jj = *jj + 1;
} else if (mimo_mode == ALAMOUTI) { } else if (mimo_mode == ALAMOUTI) {
*re_allocated = *re_allocated + 1; *re_allocated = *re_allocated + 1;
((int16_t*)&tmp_sample1)[0] = (x0[0][*jj]==1) ? (-gain_lin_QPSK) : gain_lin_QPSK; ((int16_t*)&tmp_sample1)[0] = (x0[0][*jj]==1) ? (-gain_lin_QPSK) : gain_lin_QPSK;
...@@ -275,7 +298,7 @@ int dci_allocate_REs_in_RB_NB_IoT(NB_IOT_DL_FRAME_PARMS *frame_parms, ...@@ -275,7 +298,7 @@ int dci_allocate_REs_in_RB_NB_IoT(NB_IOT_DL_FRAME_PARMS *frame_parms,
((int16_t *)&txdataF[0][tti_offset+2])[1] += ((int16_t *)&txdataF[1][tti_offset])[1]; ((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])[0] += ((int16_t *)&txdataF[0][tti_offset])[0]; //x0*
((int16_t *)&txdataF[1][tti_offset+2])[1] += -((int16_t *)&txdataF[0][tti_offset])[1]; ((int16_t *)&txdataF[1][tti_offset+2])[1] += -((int16_t *)&txdataF[0][tti_offset])[1];
re++; // skip pilots re++; // skip pilots
*re_allocated = *re_allocated + 1; *re_allocated = *re_allocated + 1;
} }
...@@ -285,18 +308,18 @@ int dci_allocate_REs_in_RB_NB_IoT(NB_IOT_DL_FRAME_PARMS *frame_parms, ...@@ -285,18 +308,18 @@ int dci_allocate_REs_in_RB_NB_IoT(NB_IOT_DL_FRAME_PARMS *frame_parms,
} }
} }
} else { } else {
// allocate first DCI // allocate first DCI
for (re=first_re; re<6; re++) { // re varies between 0 and 12 sub-carriers for (re=first_re; re<6; re++) { // re varies between 0 and 12 sub-carriers
tti_offset = symbol_offset + re; // symbol_offset = 512 * L , re_offset = 512 - 3*12 , re 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 if (pilots != 1 || re%3 != id_offset) // if re is not a pilot
{ {
// diff_re = re%3 - id_offset; // diff_re = re%3 - id_offset;
if (mimo_mode == SISO) { //SISO mapping if (mimo_mode == SISO) { //SISO mapping
*re_allocated = *re_allocated + 1; // variable incremented but never used *re_allocated = *re_allocated + 1; // variable incremented but never used
for (aa=0; aa<frame_parms->nb_antennas_tx; aa++) { for (aa=0; aa<frame_parms->nb_antennas_tx; aa++) {
((int16_t*)&txdataF[aa][tti_offset])[0] += (x0[0][*jj]==1) ? (-gain_lin_QPSK) : gain_lin_QPSK; //I //b_i ((int16_t*)&txdataF[aa][tti_offset])[0] += (x0[0][*jj]==1) ? (-gain_lin_QPSK) : gain_lin_QPSK; //I //b_i
((int16_t*)&txdataF[aa][tti_offset+6])[0] += (x0[1][*jj]==1) ? (-gain_lin_QPSK) : gain_lin_QPSK; //I //b_i ((int16_t*)&txdataF[aa][tti_offset+6])[0] += (x0[1][*jj]==1) ? (-gain_lin_QPSK) : gain_lin_QPSK; //I //b_i
...@@ -306,10 +329,10 @@ int dci_allocate_REs_in_RB_NB_IoT(NB_IOT_DL_FRAME_PARMS *frame_parms, ...@@ -306,10 +329,10 @@ int dci_allocate_REs_in_RB_NB_IoT(NB_IOT_DL_FRAME_PARMS *frame_parms,
((int16_t*)&txdataF[aa][tti_offset])[1] += (x0[0][*jj]==1) ? (-gain_lin_QPSK) : gain_lin_QPSK; //Q //b_{i+1} ((int16_t*)&txdataF[aa][tti_offset])[1] += (x0[0][*jj]==1) ? (-gain_lin_QPSK) : gain_lin_QPSK; //Q //b_{i+1}
((int16_t*)&txdataF[aa][tti_offset+6])[1] += (x0[1][*jj]==1) ? (-gain_lin_QPSK) : gain_lin_QPSK; //Q //b_{i+1} ((int16_t*)&txdataF[aa][tti_offset+6])[1] += (x0[1][*jj]==1) ? (-gain_lin_QPSK) : gain_lin_QPSK; //Q //b_{i+1}
} }
*jj = *jj + 1; *jj = *jj + 1;
} else if (mimo_mode == ALAMOUTI) { } else if (mimo_mode == ALAMOUTI) {
*re_allocated = *re_allocated + 1; *re_allocated = *re_allocated + 1;
((int16_t*)&tmp_sample1)[0] = (x0[0][*jj]==1) ? (-gain_lin_QPSK) : gain_lin_QPSK; ((int16_t*)&tmp_sample1)[0] = (x0[0][*jj]==1) ? (-gain_lin_QPSK) : gain_lin_QPSK;
...@@ -333,7 +356,7 @@ int dci_allocate_REs_in_RB_NB_IoT(NB_IOT_DL_FRAME_PARMS *frame_parms, ...@@ -333,7 +356,7 @@ int dci_allocate_REs_in_RB_NB_IoT(NB_IOT_DL_FRAME_PARMS *frame_parms,
((int16_t*)&txdataF[0][tti_offset])[1] += (int16_t)((((int16_t*)&tmp_sample1)[1]*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])[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); ((int16_t*)&txdataF[1][tti_offset])[1] += (int16_t)((((int16_t*)&tmp_sample2)[1]*ONE_OVER_SQRT2_Q15)>>15);
((int16_t*)&txdataF[0][tti_offset+6])[0] += (int16_t)((((int16_t*)&tmp_sample3)[0]*ONE_OVER_SQRT2_Q15)>>15); ((int16_t*)&txdataF[0][tti_offset+6])[0] += (int16_t)((((int16_t*)&tmp_sample3)[0]*ONE_OVER_SQRT2_Q15)>>15);
((int16_t*)&txdataF[0][tti_offset+6])[1] += (int16_t)((((int16_t*)&tmp_sample3)[1]*ONE_OVER_SQRT2_Q15)>>15); ((int16_t*)&txdataF[0][tti_offset+6])[1] += (int16_t)((((int16_t*)&tmp_sample3)[1]*ONE_OVER_SQRT2_Q15)>>15);
((int16_t*)&txdataF[1][tti_offset+6])[0] += (int16_t)((((int16_t*)&tmp_sample4)[0]*ONE_OVER_SQRT2_Q15)>>15); ((int16_t*)&txdataF[1][tti_offset+6])[0] += (int16_t)((((int16_t*)&tmp_sample4)[0]*ONE_OVER_SQRT2_Q15)>>15);
...@@ -345,7 +368,7 @@ int dci_allocate_REs_in_RB_NB_IoT(NB_IOT_DL_FRAME_PARMS *frame_parms, ...@@ -345,7 +368,7 @@ int dci_allocate_REs_in_RB_NB_IoT(NB_IOT_DL_FRAME_PARMS *frame_parms,
((int16_t *)&txdataF[0][tti_offset+1])[1] += ((int16_t *)&txdataF[1][tti_offset])[1]; ((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])[0] += ((int16_t *)&txdataF[0][tti_offset])[0]; //x0*
((int16_t *)&txdataF[1][tti_offset+1])[1] += -((int16_t *)&txdataF[0][tti_offset])[1]; ((int16_t *)&txdataF[1][tti_offset+1])[1] += -((int16_t *)&txdataF[0][tti_offset])[1];
((int16_t *)&txdataF[0][tti_offset+6+1])[0] += -((int16_t *)&txdataF[1][tti_offset+6])[0]; //x1 ((int16_t *)&txdataF[0][tti_offset+6+1])[0] += -((int16_t *)&txdataF[1][tti_offset+6])[0]; //x1
((int16_t *)&txdataF[0][tti_offset+6+1])[1] += ((int16_t *)&txdataF[1][tti_offset+6])[1]; ((int16_t *)&txdataF[0][tti_offset+6+1])[1] += ((int16_t *)&txdataF[1][tti_offset+6])[1];
((int16_t *)&txdataF[1][tti_offset+6+1])[0] += ((int16_t *)&txdataF[0][tti_offset+6])[0]; //x0* ((int16_t *)&txdataF[1][tti_offset+6+1])[0] += ((int16_t *)&txdataF[0][tti_offset+6])[0]; //x0*
...@@ -355,12 +378,12 @@ int dci_allocate_REs_in_RB_NB_IoT(NB_IOT_DL_FRAME_PARMS *frame_parms, ...@@ -355,12 +378,12 @@ int dci_allocate_REs_in_RB_NB_IoT(NB_IOT_DL_FRAME_PARMS *frame_parms,
((int16_t *)&txdataF[0][tti_offset+2])[1] += ((int16_t *)&txdataF[1][tti_offset])[1]; ((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])[0] += ((int16_t *)&txdataF[0][tti_offset])[0]; //x0*
((int16_t *)&txdataF[1][tti_offset+2])[1] += -((int16_t *)&txdataF[0][tti_offset])[1]; ((int16_t *)&txdataF[1][tti_offset+2])[1] += -((int16_t *)&txdataF[0][tti_offset])[1];
((int16_t *)&txdataF[0][tti_offset+6+2])[0] += -((int16_t *)&txdataF[1][tti_offset+6])[0]; //x1 ((int16_t *)&txdataF[0][tti_offset+6+2])[0] += -((int16_t *)&txdataF[1][tti_offset+6])[0]; //x1
((int16_t *)&txdataF[0][tti_offset+6+2])[1] += ((int16_t *)&txdataF[1][tti_offset+6])[1]; ((int16_t *)&txdataF[0][tti_offset+6+2])[1] += ((int16_t *)&txdataF[1][tti_offset+6])[1];
((int16_t *)&txdataF[1][tti_offset+6+2])[0] += ((int16_t *)&txdataF[0][tti_offset+6])[0]; //x0* ((int16_t *)&txdataF[1][tti_offset+6+2])[0] += ((int16_t *)&txdataF[0][tti_offset+6])[0]; //x0*
((int16_t *)&txdataF[1][tti_offset+6+2])[1] += -((int16_t *)&txdataF[0][tti_offset+6])[1]; ((int16_t *)&txdataF[1][tti_offset+6+2])[1] += -((int16_t *)&txdataF[0][tti_offset+6])[1];
re++; // skip pilots re++; // skip pilots
*re_allocated = *re_allocated + 1; *re_allocated = *re_allocated + 1;
} }
...@@ -376,27 +399,26 @@ int dci_allocate_REs_in_RB_NB_IoT(NB_IOT_DL_FRAME_PARMS *frame_parms, ...@@ -376,27 +399,26 @@ int dci_allocate_REs_in_RB_NB_IoT(NB_IOT_DL_FRAME_PARMS *frame_parms,
int dci_modulation_NB_IoT(int32_t **txdataF, int dci_modulation_NB_IoT(int32_t **txdataF,
int16_t amp, int16_t amp,
NB_IOT_DL_FRAME_PARMS *frame_parms, NB_DL_FRAME_PARMS *frame_parms,
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) uint8_t control_region_size,//XXX we pass the npdcch_start_symbol // control region size for LTE , values between 0..3, (0 for stand-alone / 1, 2 or 3 for in-band)
uint8_t *e[2], // Input data uint8_t *e[2], // Input data
int G, // number of bits per subframe int G, // number of bits per subframe
unsigned short NB_IoT_RB_ID
uint8_t dci_number, // This variable should takes the 1 or 2 (1 for in case of one DCI, 2 in case of two DCI) uint8_t dci_number, // This variable should takes the 1 or 2 (1 for in case of one DCI, 2 in case of two DCI)
uint8_t agr_level) // Aggregation level uint8_t agr_level) // Aggregation level
{ {
uint32_t jj=0; uint32_t jj=0;
uint32_t re_allocated,symbol_offset; uint32_t re_allocated,symbol_offset;
uint16_t l; uint16_t l;
uint8_t id_offset,pilots=0; uint8_t id_offset,pilots=0;
unsigned short bandwidth_even_odd; unsigned short bandwidth_even_odd;
unsigned short NB_IoT_start, RB_IoT_ID; unsigned short NB_IoT_start, RB_IoT_ID;
re_allocated=0; re_allocated=0;
id_offset=0; id_offset=0;
// testing if the total number of RBs is even or odd // testing if the total number of RBs is even or odd
bandwidth_even_odd = frame_parms->N_RB_DL % 2; // 0 even, 1 odd bandwidth_even_odd = frame_parms->N_RB_DL % 2; // 0 even, 1 odd
RB_IoT_ID = NB_IoT_RB_ID; RB_IoT_ID = frame_parms->NB_IoT_RB_ID;
// step 5, 6, 7 // modulation and mapping (slot 1, symbols 0..3) // step 5, 6, 7 // modulation and mapping (slot 1, symbols 0..3)
for (l=control_region_size; l<14; l++) { // loop on OFDM symbols for (l=control_region_size; l<14; l++) { // loop on OFDM symbols
if((l>=4 && l<=8) || (l>=11 && l<=13)) if((l>=4 && l<=8) || (l>=11 && l<=13))
{ {
pilots =1; pilots =1;
...@@ -423,33 +445,35 @@ int dci_modulation_NB_IoT(int32_t **txdataF, ...@@ -423,33 +445,35 @@ int dci_modulation_NB_IoT(int32_t **txdataF,
dci_number, dci_number,
agr_level); agr_level);
} }
// VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_DLSCH_MODULATION, VCD_FUNCTION_OUT); // VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_DLSCH_MODULATION, VCD_FUNCTION_OUT);
return (re_allocated); return (re_allocated);
} }
*/
//------------------------------------------------
// BCOM code functions npdcch end
//------------------------------------------------
uint8_t generate_dci_top_NB(
//******************************************************************************************************* NB_IoT_eNB_NPDCCH_t* npdcch,
//******************************************************************************************************* uint8_t Num_dci,
//********************************** Michele code *******************************************************
//*******************************************************************************************************
//*******************************************************************************************************
//*******************************************************************************************************
uint8_t generate_dci_top_NB(uint8_t Num_dci,
DCI_ALLOC_NB_t *dci_alloc, DCI_ALLOC_NB_t *dci_alloc,
int16_t amp, int16_t amp,
NB_DL_FRAME_PARMS *fp, NB_DL_FRAME_PARMS *fp,
//NB_IoT_eNB_NPDCCH_t npdcch,
int32_t **txdataF, int32_t **txdataF,
uint32_t subframe) uint32_t subframe,
uint8_t npdcch_start_symbol)
{ {
int i,L, G; int i, G;
int npdcch_start_index; //temporary variable
uint16_t rnti[2];
uint8_t L = 0;
/* PARAMETERS may not needed /* PARAMETERS may not needed
**e_ptr : store the encoding result, and as a input to modulation **e_ptr : store the encoding result, and as a input to modulation
...@@ -462,124 +486,104 @@ uint8_t generate_dci_top_NB(uint8_t Num_dci, ...@@ -462,124 +486,104 @@ uint8_t generate_dci_top_NB(uint8_t Num_dci,
*wbar used in the interleaving and also REG allocation *wbar used in the interleaving and also REG allocation
*/ */
//num_pdcch_symbols = get_num_pdcch_symbols(num_ue_spec_dci+num_common_dci,dci_alloc,frame_parms,subframe);
// generate DCIs in order of decreasing aggregation level, then common/ue spec
// MAC is assumed to have ordered the UE spec DCI according to the RNTI-based randomization??? // MAC is assumed to have ordered the UE spec DCI according to the RNTI-based randomization???
// Value of aggregation level (FAPI/NFAPI specs v.9.0 pag 221 value 1,2) // Value of aggregation level (FAPI/NFAPI specs v.9.0 pag 221 value 1,2)
for (L=2; L>=1; L--) { /*
for (i=0; i<Num_dci; i++) { * in NB-IoT we can have at most 2 aggregation level since we have only 2 NCCE (Narrowband control channel element)
* if only 1 DCI transmitted:
//XXX should be checked how the scheduler store the aggregation level for NB-IoT (value 1-2 or 0-1) * - Aggregation level could be 1 or 2
if (dci_alloc[i].L == (uint8_t)L) { * if 2 DCI transmitted:
* - Aggregation level should be 1
if (dci_alloc[i].firstCCE>=0) { *
*/
//First take all the DCI pdu and their corrispondent rnti
for(i = 0; i<Num_dci;i++)
{
npdcch->a[i]=dci_alloc[i].dci_pdu;
rnti[i]=dci_alloc[i].rnti;
L = dci_alloc[i].L;
//NB-IoT encoding }
/*npdcch_encoding_NB_IoT(dci_alloc[i].dci_pdu,
frame_parms,
npdcch, //see when function dci_top is called
//no frame
subframe
//rm_stats, te_stats, i_stats
);*/
} if(Num_dci == 2 && L == 1)
} LOG_E(PHY,"generate_dci_top_NB: Aggregation level not compatible with Num_dci\n" );
}
}
//Second, evaluate the G variable based of the npdcch_start_sysmbol
//NB-IoT scrambling
/* /*
*
* TS 36.213 ch 16.6.1 * TS 36.213 ch 16.6.1
* npdcch_start_index indicate the starting OFDM symbol for NPDCCH in the first slot of a subframe k ad is determined as follow: * npdcch_start_symbol indicate the starting OFDM symbol for NPDCCH in the first slot of a subframe k ad is determined as follow:
* - if eutracontrolregionsize is present (defined for in-band operating mode (mode 0,1 for FAPI specs)) * - if eutracontrolregionsize is present (defined for in-band operating mode (mode 0,1 for FAPI specs))
* npdcch_start_index = eutracontrolregionsize (value 1,2,3) [units in number of OFDM symbol] * npdcch_start_symbol = eutracontrolregionsize (value 1,2,3) [units in number of OFDM symbol]
* -otherwise * -otherwise
* npdcch_start_index = 0 * npdcch_start_symbol = 0
*
*XXX npdcch_start symbol should be the same for every DCI once is decided since depends on the parameters
*(the setting of this npdcch_start_symbol parameter should be done in the MAC)
*Depending on npdcch_start_symbol then we define different values for G
* *
*Depending on npddch_start_index then we define different values for G
*/ */
//XXX the setting of this npdcch_start_index parameter should be done in the MAC
// if(fp->operating_mode == 0 || fp->operating_mode == 1) //in-band operating mode
// {
// npdcch_start_index = fp->control_region_size;
// }
// else
// {
// npdcch_start_index = 0;
// }
for(int i = 0; i <Num_dci; i++)
{
switch(dci_alloc[i].npdcch_start_symbol) //mail Bcom matthieu
{
case 0:
G = 304;
break;
case 1:
G = 240;
break;
case 2:
G = 224;
break;
case 3:
G =200;
break;
default:
LOG_E (PHY,"npdcch_start_index has unwanted value\n");
break;
}
// // NB-IoT scrambling
// npdcch_scrambling_NB_IoT(
// frame_parms,
// npdcch,
// //G,
// //q = nf mod 2 (TS 36.211 ch 10.2.3.1) with nf = number of frame
// //slot_id
// );
switch(npdcch_start_symbol) //mail Bcom matthieu
{
case 0:
G = 304;
break;
case 1:
G = 240;
break;
case 2:
G = 224;
break;
case 3:
G =200;
break;
default:
LOG_E (PHY,"npdcch_start_symbol has unwanted value\n");
break;
} }
//NB-IoT encoding
// dci_encoding_NB_IoT(
// a,
// 4, // total length (in byte) of a [assume max 2 pdus of ??]
// G,
// npdcch->e,
// rnti,
// Num_dci,
// L
// );
// //NB-IoT modulation
// npdcch_modulation_NB_IoT(
// txdataF,
// AMP,
// frame_parms,
// //no symbol
// //npdcch0???
// //RB_ID --> statically get from the higher layer (may included in the dl_frame params)
// );
//NB-IoT scrambling
// npdcch_scrambling_NB_IoT(
// fp,
// npdcch->e,
// G,
// subframe,
// Num_dci,
// L
// );
//NB-IoT Modulation
// dci_modulation_NB_IoT(
// txdataF,
// amp,
// fp,
// npdcch_start_symbol,
// npdcch->e,
// G,
// Num_dci,
// L
// );
//in NB-IoT the interleaving is done directly with the encoding procedure
//there is no interleaving because we don't apply turbo coding
// This is the REG allocation algorithm from 36-211
//already done in the modulation in our NB-IoT implementaiton??
//*******************************************************************************************************
//*******************************************************************************************************
//*******************************************************************************************************
//*******************************************************************************************************
//*******************************************************************************************************
return 0; return 0;
} }
...@@ -42,7 +42,7 @@ typedef enum ...@@ -42,7 +42,7 @@ typedef enum
{ {
DCIFormatN0 = 0, DCIFormatN0 = 0,
DCIFormatN1, DCIFormatN1,
DCIFormatN1_RA, DCIFormatN1_RA,//is for initial RA procedure (semi-static information) so maybe is not needed
DCIFormatN1_RAR, DCIFormatN1_RAR,
DCIFormatN2, DCIFormatN2,
DCIFormatN2_Ind, DCIFormatN2_Ind,
...@@ -288,4 +288,4 @@ typedef struct DCIN2_Pag DCIN2_Pag_t; ...@@ -288,4 +288,4 @@ typedef struct DCIN2_Pag DCIN2_Pag_t;
#define MAX_DCI_SIZE_BITS_NB_IOT 23 #define MAX_DCI_SIZE_BITS_NB_IOT 23
#endif #endif
\ No newline at end of file
...@@ -56,7 +56,7 @@ void NB_add_dci(DCI_PDU_NB *DCI_pdu,void *pdu,rnti_t rnti,unsigned char dci_size ...@@ -56,7 +56,7 @@ void NB_add_dci(DCI_PDU_NB *DCI_pdu,void *pdu,rnti_t rnti,unsigned char dci_size
DCI_pdu->dci_alloc[DCI_pdu->Num_dci].L = aggregation; DCI_pdu->dci_alloc[DCI_pdu->Num_dci].L = aggregation;
DCI_pdu->dci_alloc[DCI_pdu->Num_dci].rnti = rnti; DCI_pdu->dci_alloc[DCI_pdu->Num_dci].rnti = rnti;
DCI_pdu->dci_alloc[DCI_pdu->Num_dci].format = dci_fmt; DCI_pdu->dci_alloc[DCI_pdu->Num_dci].format = dci_fmt;
DCI_pdu->dci_alloc[DCI_pdu->Num_dci].npdcch_start_symbol = npdcch_start_symbol; DCI_pdu->npdcch_start_symbol = npdcch_start_symbol;
DCI_pdu->Num_dci++; DCI_pdu->Num_dci++;
...@@ -122,7 +122,6 @@ int NB_generate_eNB_ulsch_params_from_dci(PHY_VARS_eNB *eNB, ...@@ -122,7 +122,6 @@ int NB_generate_eNB_ulsch_params_from_dci(PHY_VARS_eNB *eNB,
((DCIN0_t *)ULSCH_DCI_NB)->ndi =ndi; ((DCIN0_t *)ULSCH_DCI_NB)->ndi =ndi;
((DCIN0_t *)ULSCH_DCI_NB)->DCIRep =DCIRep; ((DCIN0_t *)ULSCH_DCI_NB)->DCIRep =DCIRep;
eNB->DCI_pdu->Num_dci++;
NB_add_dci(eNB->DCI_pdu,ULSCH_DCI_NB,rnti,sizeof(DCIN0_t),aggregation,sizeof_DCIN0_t,DCIFormatN0, npdcch_start_symbol); NB_add_dci(eNB->DCI_pdu,ULSCH_DCI_NB,rnti,sizeof(DCIN0_t),aggregation,sizeof_DCIN0_t,DCIFormatN0, npdcch_start_symbol);
...@@ -160,6 +159,7 @@ int NB_generate_eNB_dlsch_params_from_dci(PHY_VARS_eNB *eNB, ...@@ -160,6 +159,7 @@ int NB_generate_eNB_dlsch_params_from_dci(PHY_VARS_eNB *eNB,
eNB->DCI_pdu = (DCI_PDU_NB*) malloc(sizeof(DCI_PDU_NB)); eNB->DCI_pdu = (DCI_PDU_NB*) malloc(sizeof(DCI_PDU_NB));
//N1 parameters //N1 parameters
/// type = 0 => DCI Format N0, type = 1 => DCI Format N1, 1 bits /// type = 0 => DCI Format N0, type = 1 => DCI Format N1, 1 bits
...@@ -229,8 +229,8 @@ int NB_generate_eNB_dlsch_params_from_dci(PHY_VARS_eNB *eNB, ...@@ -229,8 +229,8 @@ int NB_generate_eNB_dlsch_params_from_dci(PHY_VARS_eNB *eNB,
/*Now configure the ndlsch structure*/ /*Now configure the ndlsch structure*/
ndlsch->subframe_tx[subframe] = 1; // check if it's OK ndlsch->subframe_tx[subframe] = 1; // check if it's OK
ndlsch->rnti = rnti; ndlsch->rnti = rnti; //we store the RNTI (e.g. for RNTI will be used later)
ndlsch->active = 1; ndlsch->active = 0; //will be activated by the corresponding NDSLCH pdu
// use this value to configure PHY both harq_processes and resource mapping. // use this value to configure PHY both harq_processes and resource mapping.
ndlsch_harq->scheduling_delay = Sched_delay; ndlsch_harq->scheduling_delay = Sched_delay;
...@@ -248,8 +248,7 @@ int NB_generate_eNB_dlsch_params_from_dci(PHY_VARS_eNB *eNB, ...@@ -248,8 +248,7 @@ int NB_generate_eNB_dlsch_params_from_dci(PHY_VARS_eNB *eNB,
* ISF = ResAssign * ISF = ResAssign
*/ */
ndlsch_harq->TBS = TBStable_NB_IoT[mcs][ResAssign]; // this table should be rewritten for nb-iot ndlsch_harq->TBS = TBStable_NB_IoT[mcs][ResAssign];
ndlsch_harq->frame = frame;
ndlsch_harq->subframe = subframe; ndlsch_harq->subframe = subframe;
//ndlsch_harq->B; we don-t have now my is given when we receive the dlsch data //ndlsch_harq->B; we don-t have now my is given when we receive the dlsch data
...@@ -299,6 +298,8 @@ int NB_generate_eNB_dlsch_params_from_dci(PHY_VARS_eNB *eNB, ...@@ -299,6 +298,8 @@ int NB_generate_eNB_dlsch_params_from_dci(PHY_VARS_eNB *eNB,
/*Now configure the ndlsch structure*/ /*Now configure the ndlsch structure*/
ndlsch->subframe_tx[subframe] = 1; // check if it's OK ndlsch->subframe_tx[subframe] = 1; // check if it's OK
ndlsch->rnti = rnti; //we store the RNTI (e.g. for RNTI will be used later)
ndlsch->active = 0;//will be activated by the corresponding NDSLCH pdu
// use this value to configure PHY both harq_processes and resource mapping. // use this value to configure PHY both harq_processes and resource mapping.
ndlsch_harq->scheduling_delay = Sched_delay; ndlsch_harq->scheduling_delay = Sched_delay;
......
...@@ -818,14 +818,24 @@ typedef enum ...@@ -818,14 +818,24 @@ typedef enum
}ndlsch_flag_t; }ndlsch_flag_t;
typedef struct {
//array containing the pdus of DCI
uint8_t *a[2];
//Array containing encoded DCI data
uint8_t *e[2];
}NB_IoT_eNB_NPDCCH_t;
typedef struct { typedef struct {
///indicates the starting OFDM symbol in the first slot of a subframe k for the NPDCCH transmission
/// see FAPI/NFAPI specs Table 4-121
uint8_t npdcch_start_symbol;
/// Length of DCI in bits /// Length of DCI in bits
uint8_t dci_length; uint8_t dci_length;
/// Aggregation level only 0,1 in NB-IoT /// Aggregation level only 1,2 in NB-IoT
uint8_t L; uint8_t L;
/// Position of first CCE of the dci /// Position of first CCE of the dci
int firstCCE; int firstCCE;
...@@ -842,6 +852,9 @@ typedef struct { ...@@ -842,6 +852,9 @@ typedef struct {
typedef struct { typedef struct {
//delete the count for the DCI numbers,NUM_DCI_MAX should set to 2 //delete the count for the DCI numbers,NUM_DCI_MAX should set to 2
uint32_t num_npdcch_symbols; uint32_t num_npdcch_symbols;
///indicates the starting OFDM symbol in the first slot of a subframe k for the NPDCCH transmission
/// see FAPI/NFAPI specs Table 4-45
uint8_t npdcch_start_symbol;
uint8_t Num_dci; uint8_t Num_dci;
DCI_ALLOC_NB_t dci_alloc[2] ; DCI_ALLOC_NB_t dci_alloc[2] ;
} DCI_PDU_NB; } DCI_PDU_NB;
...@@ -882,6 +895,8 @@ typedef struct { ...@@ -882,6 +895,8 @@ typedef struct {
uint8_t mcs; uint8_t mcs;
// we don't have code block segmentation / crc attachment / concatenation in NB-IoT R13 36.212 6.4.2 // we don't have code block segmentation / crc attachment / concatenation in NB-IoT R13 36.212 6.4.2
// we don't have beamforming in NB-IoT // we don't have beamforming in NB-IoT
//this index will be used mainly for SI message buffer
uint8_t pdu_buffer_index;
} NB_IoT_DL_eNB_HARQ_t; } NB_IoT_DL_eNB_HARQ_t;
...@@ -933,10 +948,11 @@ typedef struct { ...@@ -933,10 +948,11 @@ typedef struct {
uint8_t relative_sib1_frame; uint8_t relative_sib1_frame;
//Flag used to discern among different NDLSCH structures (SIB1,SI,RA,UE-spec) //Flag used to discern among different NDLSCH structures (SIB1,SI,RA,UE-spec)
//(in this case is used because we may have that more that one calls of npdch_procedure is needed for transmitting a data (NB-IoT implement repetitions) //(used inside the ndlsch procedure for distinguish the different type of data to manage also in term of repetitions and transmission over more subframes
ndlsch_flag_t ndlsch_type; ndlsch_flag_t ndlsch_type;
} NB_IoT_eNB_NDLSCH_t; } NB_IoT_eNB_NDLSCH_t;
typedef struct { typedef struct {
......
...@@ -11,171 +11,171 @@ ...@@ -11,171 +11,171 @@
* \note * \note
* \warning * \warning
*/ */
#ifndef __LTE_TRANSPORT_DEFS_NB_IOT__H__ //#ifndef __LTE_TRANSPORT_DEFS_NB_IOT__H__
#define __LTE_TRANSPORT_DEFS_NB_IOT__H__ //#define __LTE_TRANSPORT_DEFS_NB_IOT__H__
#include "PHY/defs.h" //#include "PHY/defs.h"
#include "dci_nb_iot.h" //#include "dci_nb_iot.h"
#include "dci.h" //#include "dci.h"
#include "uci.h" //#include "uci.h"
#ifndef STANDALONE_COMPILE //#ifndef STANDALONE_COMPILE
#include "UTIL/LISTS/list.h" //#include "UTIL/LISTS/list.h"
#endif //#endif
//
#define MOD_TABLE_QPSK_OFFSET 1 //#define MOD_TABLE_QPSK_OFFSET 1
#define MOD_TABLE_16QAM_OFFSET 5 //#define MOD_TABLE_16QAM_OFFSET 5
#define MOD_TABLE_64QAM_OFFSET 21 //#define MOD_TABLE_64QAM_OFFSET 21
#define MOD_TABLE_PSS_OFFSET 85 //#define MOD_TABLE_PSS_OFFSET 85
//
// structures below implement 36-211 and 36-212 //// structures below implement 36-211 and 36-212
//
#define NSOFT 1827072 //#define NSOFT 1827072
#define LTE_NULL 2 //#define LTE_NULL 2
//
// maximum of 3 segments before each coding block if data length exceeds 6144 bits. //// maximum of 3 segments before each coding block if data length exceeds 6144 bits.
//
#define MAX_NUM_DLSCH_SEGMENTS 16 //#define MAX_NUM_DLSCH_SEGMENTS 16
#define MAX_NUM_ULSCH_SEGMENTS MAX_NUM_DLSCH_SEGMENTS //#define MAX_NUM_ULSCH_SEGMENTS MAX_NUM_DLSCH_SEGMENTS
#define MAX_DLSCH_PAYLOAD_BYTES (MAX_NUM_DLSCH_SEGMENTS*768) //#define MAX_DLSCH_PAYLOAD_BYTES (MAX_NUM_DLSCH_SEGMENTS*768)
#define MAX_ULSCH_PAYLOAD_BYTES (MAX_NUM_ULSCH_SEGMENTS*768) //#define MAX_ULSCH_PAYLOAD_BYTES (MAX_NUM_ULSCH_SEGMENTS*768)
//
#define MAX_NUM_CHANNEL_BITS (14*1200*6) // 14 symbols, 1200 REs, 12 bits/RE //#define MAX_NUM_CHANNEL_BITS (14*1200*6) // 14 symbols, 1200 REs, 12 bits/RE
#define MAX_NUM_RE (14*1200) //#define MAX_NUM_RE (14*1200)
//
#if !defined(SI_RNTI) //#if !defined(SI_RNTI)
#define SI_RNTI (rnti_t)0xffff //#define SI_RNTI (rnti_t)0xffff
#endif //#endif
#if !defined(M_RNTI) //#if !defined(M_RNTI)
#define M_RNTI (rnti_t)0xfffd //#define M_RNTI (rnti_t)0xfffd
#endif //#endif
#if !defined(P_RNTI) //#if !defined(P_RNTI)
#define P_RNTI (rnti_t)0xfffe //#define P_RNTI (rnti_t)0xfffe
#endif //#endif
#if !defined(CBA_RNTI) //#if !defined(CBA_RNTI)
#define CBA_RNTI (rnti_t)0xfff4 //#define CBA_RNTI (rnti_t)0xfff4
#endif //#endif
#if !defined(C_RNTI) //#if !defined(C_RNTI)
#define C_RNTI (rnti_t)0x1234 //#define C_RNTI (rnti_t)0x1234
#endif //#endif
//
#define PMI_2A_11 0 //#define PMI_2A_11 0
#define PMI_2A_1m1 1 //#define PMI_2A_1m1 1
#define PMI_2A_1j 2 //#define PMI_2A_1j 2
#define PMI_2A_1mj 3 //#define PMI_2A_1mj 3
//
// for NB-IoT //// for NB-IoT
#define MAX_NUM_CHANNEL_BITS_NB_IOT 3360 //14 symbols * 12 sub-carriers * 10 SF * 2bits/RE // to check during real tests //#define MAX_NUM_CHANNEL_BITS_NB_IOT 3360 //14 symbols * 12 sub-carriers * 10 SF * 2bits/RE // to check during real tests
#define MAX_DL_SIZE_BITS_NB_IOT 680 // in release 13 // in release 14 = 2048 // ??? **** not sure //#define MAX_DL_SIZE_BITS_NB_IOT 680 // in release 13 // in release 14 = 2048 // ??? **** not sure
//#define MAX_NUM_CHANNEL_BITS_NB_IOT 3*680 /// ??? ****not sure ////#define MAX_NUM_CHANNEL_BITS_NB_IOT 3*680 /// ??? ****not sure
//
// to be created LTE_eNB_DLSCH_t --> is duplicated for each number of UE and then indexed in the table //// to be created LTE_eNB_DLSCH_t --> is duplicated for each number of UE and then indexed in the table
//
typedef struct { // LTE_eNB_DLSCH_t //typedef struct { // LTE_eNB_DLSCH_t
/// TX buffers for UE-spec transmission (antenna ports 5 or 7..14, prior to precoding) // /// TX buffers for UE-spec transmission (antenna ports 5 or 7..14, prior to precoding)
uint32_t *txdataF[8]; // uint32_t *txdataF[8];
/// Allocated RNTI (0 means DLSCH_t is not currently used) // /// Allocated RNTI (0 means DLSCH_t is not currently used)
uint16_t rnti; // uint16_t rnti;
/// Active flag for baseband transmitter processing // /// Active flag for baseband transmitter processing
uint8_t active; // uint8_t active;
/// Indicator of TX activation per subframe. Used during PUCCH detection for ACK/NAK. // /// Indicator of TX activation per subframe. Used during PUCCH detection for ACK/NAK.
uint8_t subframe_tx[10]; // uint8_t subframe_tx[10];
/// First CCE of last PDSCH scheduling per subframe. Again used during PUCCH detection for ACK/NAK. // /// First CCE of last PDSCH scheduling per subframe. Again used during PUCCH detection for ACK/NAK.
uint8_t nCCE[10]; // uint8_t nCCE[10];
/// Current HARQ process id // /// Current HARQ process id
uint8_t current_harq_pid; // uint8_t current_harq_pid;
/// Process ID's per subframe. Used to associate received ACKs on PUSCH/PUCCH to DLSCH harq process ids // /// Process ID's per subframe. Used to associate received ACKs on PUSCH/PUCCH to DLSCH harq process ids
uint8_t harq_ids[10]; // uint8_t harq_ids[10];
/// Window size (in outgoing transport blocks) for fine-grain rate adaptation // /// Window size (in outgoing transport blocks) for fine-grain rate adaptation
uint8_t ra_window_size; // uint8_t ra_window_size;
/// First-round error threshold for fine-grain rate adaptation // /// First-round error threshold for fine-grain rate adaptation
uint8_t error_threshold; // uint8_t error_threshold;
/// Pointers to 8 HARQ processes for the DLSCH // /// Pointers to 8 HARQ processes for the DLSCH
NB_IoT_DL_eNB_HARQ_t harq_processe; // NB_IoT_DL_eNB_HARQ_t harq_processe;
/// circular list of free harq PIDs (the oldest come first) // /// circular list of free harq PIDs (the oldest come first)
/// (10 is arbitrary value, must be > to max number of DL HARQ processes in LTE) // /// (10 is arbitrary value, must be > to max number of DL HARQ processes in LTE)
int harq_pid_freelist[10]; // int harq_pid_freelist[10];
/// the head position of the free list (if list is free then head=tail) // /// the head position of the free list (if list is free then head=tail)
int head_freelist; // int head_freelist;
/// the tail position of the free list // /// the tail position of the free list
int tail_freelist; // int tail_freelist;
/// Number of soft channel bits // /// Number of soft channel bits
uint32_t G; // uint32_t G;
/// Codebook index for this dlsch (0,1,2,3) // /// Codebook index for this dlsch (0,1,2,3)
uint8_t codebook_index; // uint8_t codebook_index;
/// Maximum number of HARQ processes (for definition see 36-212 V8.6 2009-03, p.17) // /// Maximum number of HARQ processes (for definition see 36-212 V8.6 2009-03, p.17)
uint8_t Mdlharq; // uint8_t Mdlharq;
/// Maximum number of HARQ rounds // /// Maximum number of HARQ rounds
uint8_t Mlimit; // uint8_t Mlimit;
/// MIMO transmission mode indicator for this sub-frame (for definition see 36-212 V8.6 2009-03, p.17) // /// MIMO transmission mode indicator for this sub-frame (for definition see 36-212 V8.6 2009-03, p.17)
uint8_t Kmimo; // uint8_t Kmimo;
/// Nsoft parameter related to UE Category // /// Nsoft parameter related to UE Category
uint32_t Nsoft; // uint32_t Nsoft;
/// amplitude of PDSCH (compared to RS) in symbols without pilots // /// amplitude of PDSCH (compared to RS) in symbols without pilots
int16_t sqrt_rho_a; // int16_t sqrt_rho_a;
/// amplitude of PDSCH (compared to RS) in symbols containing pilots // /// amplitude of PDSCH (compared to RS) in symbols containing pilots
int16_t sqrt_rho_b; // int16_t sqrt_rho_b;
//
} NB_IoT_eNB_DLSCH_t; //} NB_IoT_eNB_DLSCH_t;
//
//
//
typedef struct { // LTE_DL_eNB_HARQ_t //typedef struct { // LTE_DL_eNB_HARQ_t
/// Status Flag indicating for this DLSCH (idle,active,disabled) // /// Status Flag indicating for this DLSCH (idle,active,disabled)
SCH_status_t status; // SCH_status_t status;
/// Transport block size // /// Transport block size
uint32_t TBS; // uint32_t TBS;
/// The payload + CRC size in bits, "B" from 36-212 // /// The payload + CRC size in bits, "B" from 36-212
uint32_t B; // keep this parameter // uint32_t B; // keep this parameter
/// Pointer to the payload // /// Pointer to the payload
uint8_t *b; // keep this parameter // uint8_t *b; // keep this parameter
/// Pointers to transport block segments // /// Pointers to transport block segments
//uint8_t *c[MAX_NUM_DLSCH_SEGMENTS]; // //uint8_t *c[MAX_NUM_DLSCH_SEGMENTS];
/// RTC values for each segment (for definition see 36-212 V8.6 2009-03, p.15) // /// RTC values for each segment (for definition see 36-212 V8.6 2009-03, p.15)
// uint32_t RTC[MAX_NUM_DLSCH_SEGMENTS]; // // uint32_t RTC[MAX_NUM_DLSCH_SEGMENTS];
/// Frame where current HARQ round was sent // /// Frame where current HARQ round was sent
uint32_t frame; // uint32_t frame;
/// Subframe where current HARQ round was sent // /// Subframe where current HARQ round was sent
uint32_t subframe; // uint32_t subframe;
/// Index of current HARQ round for this DLSCH // /// Index of current HARQ round for this DLSCH
uint8_t round; // uint8_t round;
/// MCS format for this DLSCH // /// MCS format for this DLSCH
uint8_t mcs; // uint8_t mcs;
/// Redundancy-version of the current sub-frame // /// Redundancy-version of the current sub-frame
uint8_t rvidx; // uint8_t rvidx;
/// MIMO mode for this DLSCH // /// MIMO mode for this DLSCH
MIMO_mode_t mimo_mode; // MIMO_mode_t mimo_mode;
/// Current RB allocation // /// Current RB allocation
uint32_t rb_alloc[4]; // uint32_t rb_alloc[4];
/// distributed/localized flag // /// distributed/localized flag
vrb_t vrb_type; // vrb_t vrb_type;
/// Current subband PMI allocation // /// Current subband PMI allocation
uint16_t pmi_alloc; // uint16_t pmi_alloc;
/// Current subband RI allocation // /// Current subband RI allocation
uint32_t ri_alloc; // uint32_t ri_alloc;
/// Current subband CQI1 allocation // /// Current subband CQI1 allocation
uint32_t cqi_alloc1; // uint32_t cqi_alloc1;
/// Current subband CQI2 allocation // /// Current subband CQI2 allocation
uint32_t cqi_alloc2; // uint32_t cqi_alloc2;
/// Current Number of RBs // /// Current Number of RBs
uint16_t nb_rb; // uint16_t nb_rb;
/// downlink power offset field // /// downlink power offset field
uint8_t dl_power_off; // uint8_t dl_power_off;
/// Concatenated "e"-sequences (for definition see 36-212 V8.6 2009-03, p.17-18) // /// Concatenated "e"-sequences (for definition see 36-212 V8.6 2009-03, p.17-18)
uint8_t e[MAX_NUM_CHANNEL_BITS_NB_IOT]; // uint8_t e[MAX_NUM_CHANNEL_BITS_NB_IOT];
/// data after scrambling // /// data after scrambling
uint8_t s_e[MAX_NUM_CHANNEL_BITS_NB_IOT]; // uint8_t s_e[MAX_NUM_CHANNEL_BITS_NB_IOT];
/// length of the table e // /// length of the table e
uint16_t length_e // new parameter // uint16_t length_e // new parameter
/// Tail-biting convolutional coding outputs // /// Tail-biting convolutional coding outputs
uint8_t d[96+(3*(24+MAX_DL_SIZE_BITS_NB_IOT))]; // new parameter // uint8_t d[96+(3*(24+MAX_DL_SIZE_BITS_NB_IOT))]; // new parameter
/// Sub-block interleaver outputs // /// Sub-block interleaver outputs
uint8_t w[3*3*(MAX_DL_SIZE_BITS_NB_IOT+24)]; // new parameter // uint8_t w[3*3*(MAX_DL_SIZE_BITS_NB_IOT+24)]; // new parameter
/// Number of MIMO layers (streams) (for definition see 36-212 V8.6 2009-03, p.17, TM3-4) // /// Number of MIMO layers (streams) (for definition see 36-212 V8.6 2009-03, p.17, TM3-4)
uint8_t Nl; // uint8_t Nl;
/// Number of layers for this PDSCH transmission (TM8-10) // /// Number of layers for this PDSCH transmission (TM8-10)
uint8_t Nlayers; // uint8_t Nlayers;
/// First layer for this PSCH transmission // /// First layer for this PSCH transmission
uint8_t first_layer; // uint8_t first_layer;
} NB_IoT_DL_eNB_HARQ_t; //} NB_IoT_DL_eNB_HARQ_t;
#endif //#endif
...@@ -92,7 +92,7 @@ void npbch_scrambling(LTE_DL_FRAME_PARMS *frame_parms, ...@@ -92,7 +92,7 @@ void npbch_scrambling(LTE_DL_FRAME_PARMS *frame_parms,
/*Function to pack the DCI*/ /*Function to pack the DCI*/
void NB_add_dci(DCI_PDU_NB *DCI_pdu,void *pdu,rnti_t rnti,unsigned char dci_size_bytes,unsigned char aggregation,unsigned char dci_size_bits,unsigned char dci_fmt, uint8_t npdcch_start_symbol); void NB_add_dci(DCI_PDU_NB *DCI_pdu,void *pdu,rnti_t rnti,unsigned char dci_size_bytes,unsigned char aggregation,unsigned char dci_size_bits,unsigned char dci_fmt, uint8_t npdcch_start_symbol);
/*Use the UL DCI Information to configure PHY and also Packed*/ /*Use the UL DCI Information to configure PHY and also Pack the DCI*/
int NB_generate_eNB_ulsch_params_from_dci(PHY_VARS_eNB *eNB, int NB_generate_eNB_ulsch_params_from_dci(PHY_VARS_eNB *eNB,
eNB_rxtx_proc_t *proc, eNB_rxtx_proc_t *proc,
DCI_CONTENT *DCI_Content, DCI_CONTENT *DCI_Content,
...@@ -102,7 +102,7 @@ int NB_generate_eNB_ulsch_params_from_dci(PHY_VARS_eNB *eNB, ...@@ -102,7 +102,7 @@ int NB_generate_eNB_ulsch_params_from_dci(PHY_VARS_eNB *eNB,
uint8_t aggregation, uint8_t aggregation,
uint8_t npdcch_start_symbol uint8_t npdcch_start_symbol
); );
/*Use the DL DCI Information to configure PHY and also Packed*/ /*Use the DL DCI Information to configure PHY and also Pack the DCI*/
int NB_generate_eNB_dlsch_params_from_dci(PHY_VARS_eNB *eNB, int NB_generate_eNB_dlsch_params_from_dci(PHY_VARS_eNB *eNB,
int frame, int frame,
uint8_t subframe, uint8_t subframe,
...@@ -115,5 +115,17 @@ int NB_generate_eNB_dlsch_params_from_dci(PHY_VARS_eNB *eNB, ...@@ -115,5 +115,17 @@ int NB_generate_eNB_dlsch_params_from_dci(PHY_VARS_eNB *eNB,
uint8_t npdcch_start_symbol uint8_t npdcch_start_symbol
); );
/*Function for DCI encoding, scrambling, modulation*/
uint8_t generate_dci_top_NB(
NB_IoT_eNB_NPDCCH_t* npdcch,
uint8_t Num_dci,
DCI_ALLOC_NB_t *dci_alloc,
int16_t amp,
NB_DL_FRAME_PARMS *fp,
int32_t **txdataF,
uint32_t subframe,
uint8_t npdcch_start_symbol);
#endif #endif
...@@ -703,7 +703,7 @@ typedef struct PHY_VARS_eNB_s { ...@@ -703,7 +703,7 @@ typedef struct PHY_VARS_eNB_s {
*/ */
NB_IoT_eNB_NPBCH *npbch; NB_IoT_eNB_NPBCH *npbch;
//NB_IoT_eNB_NPDCCH_t *npdcch[NUMBER_OF_UE_MAX_NB_IoT]; //check the max size of this array NB_IoT_eNB_NPDCCH_t *npdcch; //check if should be an array and the max size of this array
NB_IoT_eNB_NDLSCH_t *ndlsch[NUMBER_OF_UE_MAX_NB_IoT]; NB_IoT_eNB_NDLSCH_t *ndlsch[NUMBER_OF_UE_MAX_NB_IoT];
NB_IoT_eNB_NULSCH_t *nulsch[NUMBER_OF_UE_MAX_NB_IoT+1]; //nulsch[0] contains the RAR NB_IoT_eNB_NULSCH_t *nulsch[NUMBER_OF_UE_MAX_NB_IoT+1]; //nulsch[0] contains the RAR
NB_IoT_eNB_NDLSCH_t *ndlsch_SI,*ndlsch_ra, *ndlsch_SIB1; NB_IoT_eNB_NDLSCH_t *ndlsch_SI,*ndlsch_ra, *ndlsch_SIB1;
......
...@@ -152,6 +152,13 @@ typedef struct { ...@@ -152,6 +152,13 @@ typedef struct {
} DL_GapConfig_NB; } DL_GapConfig_NB;
typedef struct { typedef struct {
/// Number of resource blocks (RB) in DL of the LTE (for knowing the bandwidth)
uint8_t N_RB_DL;
/// Number of resource blocks (RB) in UL of the LTE ((for knowing the bandwidth)
uint8_t N_RB_UL;
/// Cell ID /// Cell ID
uint16_t Nid_cell; uint16_t Nid_cell;
/// Cyclic Prefix for DL (0=Normal CP, 1=Extended CP) /// Cyclic Prefix for DL (0=Normal CP, 1=Extended CP)
...@@ -226,8 +233,6 @@ typedef struct { ...@@ -226,8 +233,6 @@ typedef struct {
// CE level to determine the NPRACH Configuration (one CE for each NPRACH config.) // CE level to determine the NPRACH Configuration (one CE for each NPRACH config.)
uint8_t CE; uint8_t CE;
/* /*
* index of the PRB assigned to NB-IoT carrier in in-band/guard-band operating mode * index of the PRB assigned to NB-IoT carrier in in-band/guard-band operating mode
*/ */
......
...@@ -75,23 +75,25 @@ void handle_nfapi_dlsch_pdu_NB(PHY_VARS_eNB *eNB, ...@@ -75,23 +75,25 @@ void handle_nfapi_dlsch_pdu_NB(PHY_VARS_eNB *eNB,
* *
* From spec. TS 36.321 v14.2.o pag 31 --> there is an HARQ process for all the broadcast * From spec. TS 36.321 v14.2.o pag 31 --> there is an HARQ process for all the broadcast
* *
* XXX for the moment we are not able to prevent the problem of Error: first transmission but sdu = NULL.
* anyway, the PHY layer if have finished the transmission it will not transmit anything and will generate the error
*
*/ */
ndlsch= eNB->ndlsch_SI; ndlsch= eNB->ndlsch_SI;
ndlsch->ndlsch_type = SI_Message; ndlsch_harq = ndlsch->harq_process;
ndlsch->npdsch_start_symbol = rel13->start_symbol; //start OFDM symbol for the ndlsch transmission
ndlsch_harq = ndlsch->harq_process;
//new SI starting transmission //new SI starting transmission (should enter here only the first time for a new transmission)
if(sdu != NULL) if(sdu != NULL)
{ {
ndlsch->ndlsch_type = SI_Message;
ndlsch->npdsch_start_symbol = rel13->start_symbol; //start OFDM symbol for the ndlsch transmission
ndlsch_harq->pdu = sdu; ndlsch_harq->pdu = sdu;
ndlsch_harq->resource_assignment = rel13->number_of_subframes_for_resource_assignment;//value 2 or 8 ndlsch_harq->resource_assignment = rel13->number_of_subframes_for_resource_assignment;//value 2 or 8
ndlsch_harq->repetition_number = rel13->repetition_number;//should be always fix to 0 to be mapped in 1 ndlsch_harq->repetition_number = rel13->repetition_number;//should be always fix to 0 to be mapped in 1
ndlsch_harq->modulation = rel13->modulation; ndlsch_harq->modulation = rel13->modulation;
ndlsch_harq->status = ACTIVE;
//SI information in reality have no feedback (so there is no retransmission from the HARQ view point since no sck and nack) //SI information in reality have no feedback (so there is no retransmission from the HARQ view point since no sck and nack)
// ndlsch_harq->frame = frame; // ndlsch_harq->frame = frame;
...@@ -100,14 +102,17 @@ void handle_nfapi_dlsch_pdu_NB(PHY_VARS_eNB *eNB, ...@@ -100,14 +102,17 @@ void handle_nfapi_dlsch_pdu_NB(PHY_VARS_eNB *eNB,
ndlsch->nrs_antenna_ports = rel13->nrs_antenna_ports_assumed_by_the_ue; ndlsch->nrs_antenna_ports = rel13->nrs_antenna_ports_assumed_by_the_ue;
ndlsch->scrambling_sequence_intialization = rel13->scrambling_sequence_initialization_cinit; ndlsch->scrambling_sequence_intialization = rel13->scrambling_sequence_initialization_cinit;
} }
//continue the remaining transmission of the previous SI at PHY if any (otherwise nothing)
else else
{ {
ndlsch_harq->pdu = NULL; //continue the remaining transmission of the previous SI at PHY if any (otherwise nothing)
//there is no need of repeating the configuration on the ndlsch //there is no need of repeating the configuration on the ndlsch
ndlsch_harq->pdu = NULL;
} }
//Independently if we have the PDU or not (first transmission or repetition) the process is activated for triggering the ndlsch_procedure
ndlsch_harq->status = ACTIVE;
} }
//ue specific data or RAR (we already have received the DCI for this) //ue specific data or RAR (we already have received the DCI for this)
else if(rel13->rnti != 65535 && rel13->rnti_type == 1) else if(rel13->rnti != 65535 && rel13->rnti_type == 1)
...@@ -118,6 +123,7 @@ void handle_nfapi_dlsch_pdu_NB(PHY_VARS_eNB *eNB, ...@@ -118,6 +123,7 @@ void handle_nfapi_dlsch_pdu_NB(PHY_VARS_eNB *eNB,
{ {
eNB->ndlsch_ra->harq_process->pdu = sdu; eNB->ndlsch_ra->harq_process->pdu = sdu;
eNB->ndlsch_ra->npdsch_start_symbol = rel13->start_symbol; eNB->ndlsch_ra->npdsch_start_symbol = rel13->start_symbol;
eNB->ndlsch_ra->active = 1;
} }
else else
{ //this for ue data { //this for ue data
...@@ -132,8 +138,11 @@ void handle_nfapi_dlsch_pdu_NB(PHY_VARS_eNB *eNB, ...@@ -132,8 +138,11 @@ void handle_nfapi_dlsch_pdu_NB(PHY_VARS_eNB *eNB,
ndlsch = eNB->ndlsch[(uint8_t)UE_id]; ndlsch = eNB->ndlsch[(uint8_t)UE_id];
ndlsch_harq = eNB->ndlsch[(uint8_t)UE_id]->harq_process; ndlsch_harq = eNB->ndlsch[(uint8_t)UE_id]->harq_process;
AssertFatal(ndlsch_harq!=NULL,"dlsch_harq for ue specific is null\n"); AssertFatal(ndlsch_harq!=NULL,"dlsch_harq for ue specific is null\n");
ndlsch->npdsch_start_symbol = rel13->start_symbol; ndlsch->npdsch_start_symbol = rel13->start_symbol;
ndlsch_harq->pdu = sdu; ndlsch_harq->pdu = sdu;
ndlsch->active = 1;
} }
} }
...@@ -147,6 +156,11 @@ void handle_nfapi_dlsch_pdu_NB(PHY_VARS_eNB *eNB, ...@@ -147,6 +156,11 @@ void handle_nfapi_dlsch_pdu_NB(PHY_VARS_eNB *eNB,
/////////////////////////////////////////////////////////////////////////////////////////////////
//Memo for initialization TODO: target/SIMU/USER/init_lte.c/init_lte_eNB --> new_eNB_dlsch(..) //
//this is where the allocation of PHy_vars_eNB and all the ndlsch structures happen //
/////////////////////////////////////////////////////////////////////////////////////////////////
// do the schedule response and trigger the TX // do the schedule response and trigger the TX
void schedule_response(Sched_Rsp_t *Sched_INFO) void schedule_response(Sched_Rsp_t *Sched_INFO)
...@@ -206,7 +220,7 @@ void schedule_response(Sched_Rsp_t *Sched_INFO) ...@@ -206,7 +220,7 @@ void schedule_response(Sched_Rsp_t *Sched_INFO)
for (i=0;i<number_dl_pdu;i++) //in principle this should be always = 1 for (i=0;i<number_dl_pdu;i++) //in principle this should be at most 2 (in case of DCI)
{ {
dl_config_pdu = &DL_req->dl_config_pdu_list[i]; dl_config_pdu = &DL_req->dl_config_pdu_list[i];
switch (dl_config_pdu->pdu_type) switch (dl_config_pdu->pdu_type)
...@@ -229,8 +243,17 @@ void schedule_response(Sched_Rsp_t *Sched_INFO) ...@@ -229,8 +243,17 @@ void schedule_response(Sched_Rsp_t *Sched_INFO)
break; break;
case NFAPI_DL_CONFIG_NDLSCH_PDU_TYPE: case NFAPI_DL_CONFIG_NDLSCH_PDU_TYPE:
//we can have three types of NDLSCH based on our assumptions: SIB1, SI, Data //we can have three types of NDLSCH based on our assumptions: SIB1, SI, Data, RAR
//remember that SI messages have no DCI in NB-IoT therefore this is the only way to configure the ndlsch_SI structure //remember that SI messages have no DCI in NB-IoT therefore this is the only way to configure the ndlsch_SI/ndlsch_SIB1 structures ndlsch->active = 1;
/*
* OBSERVATION:
* Although 2 DCI may be received over a schedule_response the transmission of the NDLSCH data foresees only 1 NDLSCH PDU at time.
* Therefore is the MAC scheduler that knowing the different timing delay will send the corresponding schedule_response containing the NDLSCH PDU and the MAC PDU
* at the proper DL subframe
* -for this reason the activation of the ndslch structure is done only when we receive the NDLSCH pdu (here) such the in the TX procedure only 1 ue-specific pdu
* result active from the loop before calling the ndlsch_procedure
*/
handle_nfapi_dlsch_pdu_NB(eNB, proc,dl_config_pdu,Sched_INFO->sdu[i]); handle_nfapi_dlsch_pdu_NB(eNB, proc,dl_config_pdu,Sched_INFO->sdu[i]);
...@@ -282,6 +305,8 @@ void schedule_response(Sched_Rsp_t *Sched_INFO) ...@@ -282,6 +305,8 @@ void schedule_response(Sched_Rsp_t *Sched_INFO)
} }
//XXX problem: although we may have nothing to transmit this function should be always triggered in order to allow the PHY layer to complete the repetitions
//of previous Transport Blocks
NB_phy_procedures_eNB_TX(eNB,proc,NULL); NB_phy_procedures_eNB_TX(eNB,proc,NULL);
} }
......
...@@ -376,6 +376,7 @@ uint16_t get_Np(uint8_t N_RB_DL,uint8_t nCCE,uint8_t plus1); ...@@ -376,6 +376,7 @@ uint16_t get_Np(uint8_t N_RB_DL,uint8_t nCCE,uint8_t plus1);
int8_t find_ue(uint16_t rnti, PHY_VARS_eNB *phy_vars_eNB); int8_t find_ue(uint16_t rnti, PHY_VARS_eNB *phy_vars_eNB);
//NB-IoT //NB-IoT
int8_t find_ue_NB(uint16_t rnti, PHY_VARS_eNB *eNB); int8_t find_ue_NB(uint16_t rnti, PHY_VARS_eNB *eNB);
int32_t add_ue(int16_t rnti, PHY_VARS_eNB *phy_vars_eNB); int32_t add_ue(int16_t rnti, PHY_VARS_eNB *phy_vars_eNB);
int mac_phy_remove_ue(module_id_t Mod_idP,rnti_t rnti); int mac_phy_remove_ue(module_id_t Mod_idP,rnti_t rnti);
......
...@@ -487,24 +487,19 @@ void NB_generate_eNB_dlsch_params(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t * proc,nfapi ...@@ -487,24 +487,19 @@ void NB_generate_eNB_dlsch_params(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t * proc,nfapi
DCI_format_NB_t DCI_format; DCI_format_NB_t DCI_format;
NB_IoT_eNB_NDLSCH_t *ndlsch; NB_IoT_eNB_NDLSCH_t *ndlsch;
DCI_Content = (DCI_CONTENT*) malloc(sizeof(DCI_CONTENT)); DCI_Content = (DCI_CONTENT*) malloc(sizeof(DCI_CONTENT));
// In NB-IoT, there is no DCI for SI, we might use the scheduling infomation from SIB1-NB to get the phyical layer configuration.
//mapping the fapi parameters to the oai parameters
// check DCI format is N1 (format 0) or N2 (format 1) // check DCI format is N1 (format 0)
if(dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.dci_format == 0) if(dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.dci_format == 0)
{ {
//check DCI format N1 is for RAR rnti_type in FAPI specs table 4-45 //check DCI format N1 is for RAR rnti_type in FAPI specs table 4-45
if(dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.rnti_type == 1) if(dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.rnti_type == 1)
{ {
DCI_format = DCIFormatN1_RAR;
ndlsch= eNB->ndlsch_ra;//we store the RNTI for the RAR //mapping the fapi parameters to the oai parameters
ndlsch->ndlsch_type = RAR;
DCI_format = DCIFormatN1_RAR;
//DCI format N1 to RAR //DCI format N1 to RAR
DCI_Content->DCIN1_RAR.type = 1; DCI_Content->DCIN1_RAR.type = 1;
...@@ -519,7 +514,11 @@ void NB_generate_eNB_dlsch_params(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t * proc,nfapi ...@@ -519,7 +514,11 @@ void NB_generate_eNB_dlsch_params(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t * proc,nfapi
// fill the dlsch_ra_NB sructure for RAR, and packed the DCI PDU // fill the dlsch_ra_NB sructure for RAR, and packed the DCI PDU
LOG_D(PHY,"Generating dlsch params for RA_RNTI\n");
ndlsch= eNB->ndlsch_ra;
ndlsch->ndlsch_type = RAR;
LOG_D(PHY,"Generating dlsch params for RA_RNTI and packing DCI\n");
NB_generate_eNB_dlsch_params_from_dci(eNB, NB_generate_eNB_dlsch_params_from_dci(eNB,
frame, frame,
subframe, subframe,
...@@ -539,10 +538,12 @@ void NB_generate_eNB_dlsch_params(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t * proc,nfapi ...@@ -539,10 +538,12 @@ void NB_generate_eNB_dlsch_params(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t * proc,nfapi
//TODO target/SIMU/USER?init_lte/init_lte_eNB we should allocate the ndlsch structures //TODO target/SIMU/USER?init_lte/init_lte_eNB we should allocate the ndlsch structures
UE_id = find_ue_NB(dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.rnti, eNB); UE_id = find_ue_NB(dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.rnti, eNB);
AssertFatal(UE_id == -1, "no ndlsch context available or no ndlsch context corresponding to that rnti\n"); AssertFatal(UE_id != -1, "no ndlsch context available or no ndlsch context corresponding to that rnti\n");
ndlsch = eNB->ndlsch[(uint8_t)UE_id]; //in the old implementation they also consider UE_id = 1; //mapping the fapi parameters to the oai parameters
ndlsch->ndlsch_type = UE_Data;
DCI_format = DCIFormatN1;
//DCI format N1 to DLSCH //DCI format N1 to DLSCH
DCI_Content->DCIN1.type = 1; DCI_Content->DCIN1.type = 1;
...@@ -555,8 +556,14 @@ void NB_generate_eNB_dlsch_params(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t * proc,nfapi ...@@ -555,8 +556,14 @@ void NB_generate_eNB_dlsch_params(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t * proc,nfapi
DCI_Content->DCIN1.HARQackRes = dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.harq_ack_resource; DCI_Content->DCIN1.HARQackRes = dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.harq_ack_resource;
DCI_Content->DCIN1.DCIRep = dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.dci_subframe_repetition_number; DCI_Content->DCIN1.DCIRep = dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.dci_subframe_repetition_number;
//fill the ndlsch structure for UE //fill the ndlsch structure for UE and packed the DCI PD
ndlsch = eNB->ndlsch[(uint8_t)UE_id]; //in the old implementation they also consider UE_id = 1;
ndlsch->ndlsch_type = UE_Data;
//parameters we don't consider pdsch config dedicated since not calling the phy config dedicated step2 //parameters we don't consider pdsch config dedicated since not calling the phy config dedicated step2
LOG_D(PHY,"Generating dlsch params for DCIN1 data and packing DCI\n");
NB_generate_eNB_dlsch_params_from_dci(eNB, NB_generate_eNB_dlsch_params_from_dci(eNB,
frame, frame,
subframe, subframe,
...@@ -870,6 +877,9 @@ extern int oai_exit; ...@@ -870,6 +877,9 @@ extern int oai_exit;
/* /*
* ASSUMPTION * ASSUMPTION
*
* The MAC schedule the schedule_response in a SUBFRAME BASE (at least because otherwise we have problem with our assumptions on SI transmission)
*
*Since in FAPI specs seems to not manage the information for the sceduling of system information: *Since in FAPI specs seems to not manage the information for the sceduling of system information:
* Assume that the MAC layer manage the scheduling for the System information (SI messages) transmission while MIB and SIB1 are done directly at PHY layer * Assume that the MAC layer manage the scheduling for the System information (SI messages) transmission while MIB and SIB1 are done directly at PHY layer
* This means that the MAC scheduler will send to the PHY the NDLSCH PDU and MIB PDU (DL_CONFIG.request)each time they should be transmitted. In particular: * This means that the MAC scheduler will send to the PHY the NDLSCH PDU and MIB PDU (DL_CONFIG.request)each time they should be transmitted. In particular:
...@@ -882,20 +892,20 @@ extern int oai_exit; ...@@ -882,20 +892,20 @@ extern int oai_exit;
*if no new NDLSCH pdu (configured for SIB1-NB) at SFN mod 256 = 0 is transmitted. stop SIB1-NB transmission *if no new NDLSCH pdu (configured for SIB1-NB) at SFN mod 256 = 0 is transmitted. stop SIB1-NB transmission
****SI Messages ****SI Messages
* -schedule_response is transmitted by the MAC in every subframe needed for the SI transmission (NDLSCH should have a proper configuration) * -schedule_response is transmitted by the MAC in every subframe needed for the SI transmission (NDLSCH should have a proper configuration)
* -if the schedule_response carry any SDU (SDU!= NULL)--> put the SDU in the PHY buffer to be encoded ecc... and start the transmission * -if the schedule_response carry any SDU for SI-Message (SDU!= NULL)--> put the SDU in the PHY buffer to be encoded ecc... and start the transmission
* -if the schedule_response not carry any SDU (SDU == NULL) but NDLSCH is properly set for SI, then PHY continue transmit the remaining part of the previous SDU * -if the schedule_response not carry any SDU (SDU == NULL) but NDLSCH is properly set for SI, then PHY continue transmit the remaining part of the previous SDU
* (this because the PHY layer have no logic of repetition_pattern, si_window ecc.. so should be continuously instructed the PHY when to transmit. * (this because the PHY layer have no logic of repetition_pattern, si_window ecc.. so should be continuously instructed the PHY when to transmit.
*
* Furthermore, SI messages are transmitted in more that 1 subframe (2 or 8) and therefore MAC layer need to count how many subframes are available in the current frame for transmit it * Furthermore, SI messages are transmitted in more that 1 subframe (2 or 8) and therefore MAC layer need to count how many subframes are available in the current frame for transmit it
* and take in consideration that other frames are needed before starting the transmission of a new one) * and take in consideration that other frames are needed before starting the transmission of a new one)
* *
* *
* FAPI distingsh the BCCH info in the NDLSCH may for some reasons: *We assume that whenever the NDLSCH pdu is a BCCH type, we consider as if it's a SIB1 while in other case can be data or SI-message depending on the RNTI
* -scrambling is different
* *
* **relevant aspects for the System information Transmission (Table 4-47 NDLSCH FAPi specs) * **relevant aspects for the System information Transmission (Table 4-47 NDLSCH FAPi specs)
* 1)RNTI type = 0 (contains a BCCH) * 1)RNTI type = 0 (contains a BCCH)
* 2)Repetition number == scheduling info SIB1 * 2)Repetition number == scheduling info SIB1 mapped into 4-8-16
* 3)RNTI * 3)RNTI (0xFFFF = SI-RNTI)
* (see schedule_response implementation) * (see schedule_response implementation)
* *
*/ */
...@@ -919,6 +929,9 @@ void NB_phy_procedures_eNB_TX(PHY_VARS_eNB *eNB, ...@@ -919,6 +929,9 @@ void NB_phy_procedures_eNB_TX(PHY_VARS_eNB *eNB,
uint8_t ul_subframe; uint8_t ul_subframe;
uint32_t ul_frame; uint32_t ul_frame;
int **txdataF = eNB->common_vars.txdataF[0]; int **txdataF = eNB->common_vars.txdataF[0];
uint32_t sib1_startFrame = -1;
if(do_meas == 1) if(do_meas == 1)
...@@ -966,7 +979,9 @@ void NB_phy_procedures_eNB_TX(PHY_VARS_eNB *eNB, ...@@ -966,7 +979,9 @@ void NB_phy_procedures_eNB_TX(PHY_VARS_eNB *eNB,
//In the last frame in which the MIB-NB should be transmitted after we point to NULL since maybe we stop MIB trasnmission //In the last frame in which the MIB-NB should be transmitted after we point to NULL since maybe we stop MIB trasnmission
//this should be in line with FAPI specs pag 94 (BCH procedure in Downlink 3.2.4.2 for NB-IoT) //this should be in line with FAPI specs pag 94 (BCH procedure in Downlink 3.2.4.2 for NB-IoT)
if(frame%64 == 63) if(frame%64 == 63)
{
eNB->npbch->pdu = NULL; eNB->npbch->pdu = NULL;
}
} }
...@@ -984,14 +999,14 @@ void NB_phy_procedures_eNB_TX(PHY_VARS_eNB *eNB, ...@@ -984,14 +999,14 @@ void NB_phy_procedures_eNB_TX(PHY_VARS_eNB *eNB,
* consider that if at the start of the new SIB1-NB period the MAC will not send an NPDSCH for the SIB1-NB transmission then SIB1-NB will be not transmitted (pdu = NULL) * consider that if at the start of the new SIB1-NB period the MAC will not send an NPDSCH for the SIB1-NB transmission then SIB1-NB will be not transmitted (pdu = NULL)
* *
*/ */
if(subframe == 4 && eNB->ndlsch_SIB1 != NULL) if(subframe == 4 && eNB->ndlsch_SIB1 != NULL && eNB->ndlsch_SIB1->harq_process->status == ACTIVE)
{ {
//check if current frame is for SIB1-NB transmission (if yes get the starting frame of SIB1-NB) and set the flag for the encoding //check if current frame is for SIB1-NB transmission (if yes get the starting frame of SIB1-NB) and set the flag for the encoding
uint32_t sib1_startFrame = is_SIB1_NB(frame, sib1_startFrame = is_SIB1_NB(frame,
eNB->ndlsch_SIB1->harq_process->repetition_number, eNB->ndlsch_SIB1->harq_process->repetition_number,
fp->Nid_cell, fp->Nid_cell,
eNB->ndlsch_SIB1 // we need it to set the flag eNB->ndlsch_SIB1 //set the flags
); );
if(sib1_startFrame != -1 && eNB->ndlsch_SIB1->harq_process->pdu != NULL) if(sib1_startFrame != -1 && eNB->ndlsch_SIB1->harq_process->pdu != NULL)
{ {
...@@ -1003,7 +1018,11 @@ void NB_phy_procedures_eNB_TX(PHY_VARS_eNB *eNB, ...@@ -1003,7 +1018,11 @@ void NB_phy_procedures_eNB_TX(PHY_VARS_eNB *eNB,
//at the end of the period we put the PDU to NULL since we have to wait for the new one from the MAC for starting the next SIB1-NB transmission //at the end of the period we put the PDU to NULL since we have to wait for the new one from the MAC for starting the next SIB1-NB transmission
if((frame-sib1_startFrame)%256 == 255) if((frame-sib1_startFrame)%256 == 255)
{
//whenever we will not receive a new sdu from MAC at the start of the next SIB1-NB period we prevent future SIB1-NB transmission (may just only of the two condition is necessary)
eNB->ndlsch_SIB1->harq_process->status = DISABLED;
eNB->ndlsch_SIB1->harq_process->pdu = NULL; eNB->ndlsch_SIB1->harq_process->pdu = NULL;
}
} }
...@@ -1022,48 +1041,124 @@ void NB_phy_procedures_eNB_TX(PHY_VARS_eNB *eNB, ...@@ -1022,48 +1041,124 @@ void NB_phy_procedures_eNB_TX(PHY_VARS_eNB *eNB,
* subframe = 5 (NPSS) * subframe = 5 (NPSS)
* subframe = 9 (NSSS) but depends on the frame (if is even) * subframe = 9 (NSSS) but depends on the frame (if is even)
* *
* [This condition should be known by the MAC layer so it should trigger an DLSCH pdu only at proper instants]
*
* XXX Important: in the case the SI-window finish the PHY layer should have also being able to conclude all the SI transmission in time * XXX Important: in the case the SI-window finish the PHY layer should have also being able to conclude all the SI transmission in time
* (because this is managed by the MAC layer that stops transmitting the SDU to PHY in advance because is counting the remaining subframe for the transmission) * (because this is managed by the MAC layer that stops transmitting the SDU to PHY in advance because is counting the remaining subframe for the transmission)
* *
* *
*XXX important: set the flag HARQ process->status to DISABLE when PHY finished the SI-transmission over the 2 or 8 subframes
*XXX important: whenever we enter for some error in the ndlsch_procedure with a pdu that is NULL but all the data of the SI have been transmitted (pdu_buffer_index = 0)
*XXX --> generate error
*XXX: the npdlsch_procedure in this case should be only called when is triggered by the MAC schedule_response (use the status flag set by the schedule_response)
*
*/ */
if(eNB->ndlsch_SI != NULL)
{
//check if the PDU != NULL will be done inside just for understanding if a new SI message need to be transmitted or not
npdsch_procedures(eNB,
proc,
eNB->ndlsch_SI, //since we have no DCI for system information, this is filled directly when we receive the DL_CONFIG.request message
eNB->ndlsch_SI->harq_process->pdu);
}
if(eNB->ndlsch_SI->harq_process->status == ACTIVE && (eNB->ndlsch_SIB1->harq_process->status != ACTIVE || subframe != 4)) //condition on SIB1-NB
{
if(frame%2 == 0)//condition on NSSS (subframe 9 not available)
{
if(eNB->ndlsch_SI != NULL && subframe!= 0 && subframe != 5 && subframe != 9)
{
//check if the PDU != NULL will be done inside just for understanding if a new SI message need to be transmitted or not
npdsch_procedures(eNB,
proc,
eNB->ndlsch_SI, //since we have no DCI for system information, this is filled directly when we receive the DL_CONFIG.request message
eNB->ndlsch_SI->harq_process->pdu);
///check for RAR transmission eNB->ndlsch_SI->harq_process->status = DISABLED;
if(eNB->ndlsch_ra != NULL && eNB->ndlsch_ra->active == 1) }
{ }
else //this frame not foresee the transmission of NSSS (subframe 9 is available)
{
if(eNB->ndlsch_SI != NULL && subframe!= 0 && subframe != 5)
{
npdsch_procedures(eNB,
proc,
eNB->ndlsch_SI, //since we have no DCI for system information, this is filled directly when we receive the DL_CONFIG.request message
eNB->ndlsch_SI->harq_process->pdu);
npdsch_procedures(eNB, eNB->ndlsch_SI->harq_process->status = DISABLED;
proc,
eNB->ndlsch_ra, //should be filled ?? (in the old implementation was filled when from DCI we generate_dlsch_params
eNB->ndlsch_ra->harq_process->pdu);
eNB->ndlsch_ra->active= 0; }
}
} }
///check for RAR transmission
if(eNB->ndlsch_ra != NULL && eNB->ndlsch_ra->active == 1 && (eNB->ndlsch_SIB1->harq_process->status != ACTIVE || subframe != 4)) //condition on SIB1-NB
{
if(frame%2 == 0)//condition on NSSS (subframe 9 not available)
{
if(eNB->ndlsch_SI != NULL && subframe!= 0 && subframe != 5 && subframe != 9)
{
npdsch_procedures(eNB,
proc,
eNB->ndlsch_ra, //should be filled ?? (in the old implementation was filled when from DCI we generate_dlsch_params
eNB->ndlsch_ra->harq_process->pdu);
//it should be activated only when we receive the proper DCIN1_RAR
eNB->ndlsch_ra->active= 0;
}
}
else //this frame not foresee the transmission of NSSS (subframe 9 is available)
{
if(eNB->ndlsch_SI != NULL && subframe!= 0 && subframe != 5)
{
npdsch_procedures(eNB,
proc,
eNB->ndlsch_ra, //should be filled ?? (in the old implementation was filled when from DCI we generate_dlsch_params
eNB->ndlsch_ra->harq_process->pdu);
//it should be activated only when we receive the proper DCIN1_RAR
eNB->ndlsch_ra->active= 0; // maybe this is already done inside the ndlsch_procedure
}
}
}
/*
* Delays between DCI transmission and NDLSCH transmission are taken in consideration by the MAC scheduler by sending in the proper subframe the scheduler_response
* Transmission over more subframe and Repetitions are managed directly by the PHY layer
* We should have only 1 ue-specific ndlsch structure active at each time (active flag is set = 1 only at the corresponding NDLSCH pdu reception and not at the DCI time
* (NDLSCH transmission should be compliant with the FAPI procedure Figure 3-49)
*
* XXX how are managed the transmission and repetitions???
*
*/
//transmission of UE specific ndlsch data //this should give only 1 result (since only 1 ndlsch procedure is activated at once) so we brak after the transmission
for (int UE_id = 0; i < NUMBER_OF_UE_MAX_NB_IoT; UE_id++) for (int UE_id = 0; i < NUMBER_OF_UE_MAX_NB_IoT; UE_id++)
{ {
if(eNB->ndlsch[(uint8_t)UE_id] != NULL && eNB->ndlsch[(uint8_t)UE_id]->active == 1) if(eNB->ndlsch[(uint8_t)UE_id] != NULL && eNB->ndlsch[(uint8_t)UE_id]->active == 1 && (eNB->ndlsch_SIB1->harq_process->status != ACTIVE || subframe != 4)) //condition on sib1-NB
{ {
npdsch_procedures(eNB, if(frame%2 == 0)//condition on NSSS (subframe 9 not available)
proc, {
eNB->ndlsch[(uint8_t)UE_id], if(eNB->ndlsch_SI != NULL && subframe!= 0 && subframe != 5 && subframe != 9)
eNB->ndlsch[(uint8_t)UE_id]->harq_process->pdu); {
npdsch_procedures(eNB,
proc,
eNB->ndlsch[(uint8_t)UE_id],
eNB->ndlsch[(uint8_t)UE_id]->harq_process->pdu);
break;
}
}
else //this frame not foresee the transmission of NSSS (subframe 9 is available)
{
if(eNB->ndlsch_SI != NULL && subframe!= 0 && subframe != 5)
{
npdsch_procedures(eNB,
proc,
eNB->ndlsch[(uint8_t)UE_id],
eNB->ndlsch[(uint8_t)UE_id]->harq_process->pdu);
break;
}
}
} }
//we don't care about subframe TX for the PUCCH since not defined by NB-IoT //we don't care about subframe TX for the PUCCH since not defined by NB-IoT
...@@ -1075,11 +1170,13 @@ void NB_phy_procedures_eNB_TX(PHY_VARS_eNB *eNB, ...@@ -1075,11 +1170,13 @@ void NB_phy_procedures_eNB_TX(PHY_VARS_eNB *eNB,
/*If we have DCI to generate do it now*/ /*If we have DCI to generate do it now*/
generate_dci_top_NB( generate_dci_top_NB(
eNB->npdcch,
dci_pdu->Num_dci, dci_pdu->Num_dci,
dci_pdu->dci_alloc, dci_pdu->dci_alloc,
AMP, AMP,
fp, fp,
eNB->common_vars.txdataF[0], eNB->common_vars.txdataF[0],
subframe); subframe,
dci_pdu->npdcch_start_symbol); //this parameter depends by eutraControlRegionSize (see TS36.213 16.6.1)
} }
...@@ -768,6 +768,9 @@ const Enb_properties_array_t *enb_config_init(char* lib_config_file_name_pP) ...@@ -768,6 +768,9 @@ const Enb_properties_array_t *enb_config_init(char* lib_config_file_name_pP)
enb_properties_index = 0; enb_properties_index = 0;
num_enbs = config_setting_length(setting); num_enbs = config_setting_length(setting);
//Start the loop for parsing all the element over the .config file
for (i = 0; i < num_enbs; i++) { for (i = 0; i < num_enbs; i++) {
setting_enb = config_setting_get_elem(setting, i); setting_enb = config_setting_get_elem(setting, i);
...@@ -783,6 +786,8 @@ const Enb_properties_array_t *enb_config_init(char* lib_config_file_name_pP) ...@@ -783,6 +786,8 @@ const Enb_properties_array_t *enb_config_init(char* lib_config_file_name_pP)
# endif # endif
} }
//Identification Parameters
if ( !( config_setting_lookup_string(setting_enb, ENB_CONFIG_STRING_CELL_TYPE, &cell_type) if ( !( config_setting_lookup_string(setting_enb, ENB_CONFIG_STRING_CELL_TYPE, &cell_type)
&& config_setting_lookup_string(setting_enb, ENB_CONFIG_STRING_ENB_NAME, &enb_name) && config_setting_lookup_string(setting_enb, ENB_CONFIG_STRING_ENB_NAME, &enb_name)
&& config_setting_lookup_string(setting_enb, ENB_CONFIG_STRING_TRACKING_AREA_CODE, &tac) && config_setting_lookup_string(setting_enb, ENB_CONFIG_STRING_TRACKING_AREA_CODE, &tac)
...@@ -2519,7 +2524,7 @@ const Enb_properties_array_t *enb_config_init(char* lib_config_file_name_pP) ...@@ -2519,7 +2524,7 @@ const Enb_properties_array_t *enb_config_init(char* lib_config_file_name_pP)
} }
// OTG _CONFIG // OTG _CONFIG //MP: refers to USB On the GO Features ?? (use USB devices as a fleshdrives)
setting_otg = config_setting_get_member (setting_enb, ENB_CONF_STRING_OTG_CONFIG); setting_otg = config_setting_get_member (setting_enb, ENB_CONF_STRING_OTG_CONFIG);
if (setting_otg != NULL) { if (setting_otg != NULL) {
......
...@@ -12,6 +12,7 @@ ...@@ -12,6 +12,7 @@
#include "openair1/PHY/LTE_TRANSPORT/defs_nb_iot.h" #include "openair1/PHY/LTE_TRANSPORT/defs_nb_iot.h"
#include "PhysicalConfigDedicated-NB-r13.h" #include "PhysicalConfigDedicated-NB-r13.h"
#include "openair2/PHY_INTERFACE/IF_Module_nb_iot.h" #include "openair2/PHY_INTERFACE/IF_Module_nb_iot.h"
#include "openair2/COMMON/platform_types.h"
#define SCH_PAYLOAD_SIZE_MAX 4096 #define SCH_PAYLOAD_SIZE_MAX 4096
#define BCCH_PAYLOAD_SIZE_MAX 128 #define BCCH_PAYLOAD_SIZE_MAX 128
......
...@@ -141,7 +141,8 @@ int NB_rrc_mac_config_req_eNB( ...@@ -141,7 +141,8 @@ int NB_rrc_mac_config_req_eNB(
int p_rx_eNB,// number of eNB Rx antenna ports (1 or 2 for NB-IoT) int p_rx_eNB,// number of eNB Rx antenna ports (1 or 2 for NB-IoT)
int Ncp, int Ncp,
int Ncp_UL, int Ncp_UL,
long eutra_band,//FIXME: frequencyBandIndicator in sib1 (is a long not an int!!) //FIXME: frequencyBandIndicator (eutra_band) in sib1 (as Rymond Implementation) (is a long not an int!!)//XXX this param is set in the do_sib1_nb and is directly taken from the .config file
long eutra_band,
struct NS_PmaxList_NB_r13 *frequencyBandInfo, //optional SIB1 struct NS_PmaxList_NB_r13 *frequencyBandInfo, //optional SIB1
struct MultiBandInfoList_NB_r13 *multiBandInfoList, //optional SIB1 struct MultiBandInfoList_NB_r13 *multiBandInfoList, //optional SIB1
struct DL_Bitmap_NB_r13 *dl_bitmap, //optional SIB1 struct DL_Bitmap_NB_r13 *dl_bitmap, //optional SIB1
......
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