nr_dlsch.c 10.1 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31
/*
 * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The OpenAirInterface Software Alliance licenses this file to You under
 * the OAI Public License, Version 1.1  (the "License"); you may not use this file
 * except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.openairinterface.org/?page_id=698
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *-------------------------------------------------------------------------------
 * For more information about the OpenAirInterface (OAI) Software Alliance:
 *      contact@openairinterface.org
 */

/*! \file PHY/LTE_TRANSPORT/dlsch_decoding.c
* \brief Top-level routines for decoding  Turbo-coded (DLSCH) transport channels from 36-212, V8.6 2009-03
* \author R. Knopp
* \date 2011
* \version 0.1
* \company Eurecom
* \email: knopp@eurecom.fr
* \note
* \warning
*/
Guy De Souza's avatar
Guy De Souza committed
32

33 34
#include "nr_dlsch.h"
#include "nr_dci.h"
Guy De Souza's avatar
Guy De Souza committed
35
#include "nr_sch_dmrs.h"
Guy De Souza's avatar
Guy De Souza committed
36

Guy De Souza's avatar
Guy De Souza committed
37
#define DEBUG_DLSCH
Guy De Souza's avatar
Guy De Souza committed
38

39 40 41
uint8_t mod_order[5] = {1, 2, 4, 6, 8};
uint16_t mod_offset[5] = {1,3,7,23,87};

Guy De Souza's avatar
Guy De Souza committed
42
void nr_pdsch_codeword_scrambling(uint8_t *in,
43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59
                         uint8_t size,
                         uint8_t q,
                         uint32_t Nid,
                         uint32_t n_RNTI,
                         uint32_t* out) {

  uint8_t reset;
  uint32_t x1, x2, s=0;

  reset = 1;
  x2 = (n_RNTI<<15) + (q<<14) + Nid;

  for (int i=0; i<size; i++) {
    if ((i&0x1f)==0) {
      s = lte_gold_generic(&x1, &x2, reset);
      reset = 0;
    }
Guy De Souza's avatar
Guy De Souza committed
60
    *out ^= ((in[i])&1) ^ ((s>>i)&1);
61 62 63 64
  }

}

Guy De Souza's avatar
Guy De Souza committed
65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89
void nr_modulation(uint32_t *in,
                   uint16_t length,
                   nr_mod_t modulation_type,
                   int16_t *out) {

  uint16_t offset;
	uint16_t order;
	order = mod_order[modulation_type];
	offset = mod_offset[modulation_type];
   
  for (int i=0; i<length/order; i++) {
    uint8_t idx = 0, b_idx;

    for (int j=0; j<order; j++) {
      b_idx = (i*order+j)&0x1f;
      if (i && (!b_idx))
        in++;
      idx ^= (((*in)>>b_idx)&1)<<(order-j-1);
    }

    out[i<<1] = nr_mod_table[(offset+idx)<<1];
    out[(i<<1)+1] = nr_mod_table[((offset+idx)<<1)+1];
  }
}

90 91 92
void nr_pdsch_codeword_modulation(uint32_t *in,
                         uint8_t  Qm,
                         uint32_t length,
Guy De Souza's avatar
Guy De Souza committed
93
                         int16_t *out) {
94 95 96 97 98 99 100 101 102 103 104 105

  uint16_t offset = (Qm==2)? NR_MOD_TABLE_QPSK_OFFSET : (Qm==4)? NR_MOD_TABLE_QAM16_OFFSET : \
                    (Qm==6)? NR_MOD_TABLE_QAM64_OFFSET: (Qm==8)? NR_MOD_TABLE_QAM256_OFFSET : 0;
  AssertFatal(offset, "Invalid modulation order %d\n", Qm);

  for (int i=0; i<length/Qm; i++) {
    uint8_t idx = 0, b_idx;

    for (int j=0; j<Qm; j++) {
      b_idx = (i*Qm+j)&0x1f;
      if (i && (!b_idx))
        in++;
Guy De Souza's avatar
Guy De Souza committed
106
      idx ^= (((*in)>>b_idx)&1)<<(Qm-j-1);
107 108 109 110 111 112 113
    }

    out[i<<1] = nr_mod_table[(offset+idx)<<1];
    out[(i<<1)+1] = nr_mod_table[((offset+idx)<<1)+1];
  }
}

Guy De Souza's avatar
Guy De Souza committed
114
void nr_pdsch_layer_mapping(int16_t **mod_symbs,
115
                         uint8_t n_layers,
Guy De Souza's avatar
Guy De Souza committed
116
                         uint16_t n_symbs,
Guy De Souza's avatar
Guy De Souza committed
117
                         int16_t **tx_layers) {
118 119 120 121

  switch (n_layers) {

    case 1:
Guy De Souza's avatar
Guy De Souza committed
122
      memcpy((void*)tx_layers[0], (void*)mod_symbs[0], (n_symbs<<1)*sizeof(int16_t));
123 124 125 126 127
    break;

    case 2:
    case 3:
    case 4:
Guy De Souza's avatar
Guy De Souza committed
128
      for (int i=0; i<n_symbs/n_layers; i++)
129 130 131 132 133 134 135
        for (int l=0; l<n_layers; l++) {
          tx_layers[l][i<<1] = mod_symbs[0][(n_layers*i+l)<<1];
          tx_layers[l][(i<<1)+1] = mod_symbs[0][((n_layers*i+l)<<1)+1];
        }
    break;

    case 5:
Guy De Souza's avatar
Guy De Souza committed
136
      for (int i=0; i<n_symbs>>1; i++)
137 138 139 140
        for (int l=0; l<2; l++) {
          tx_layers[l][i<<1] = mod_symbs[0][((i<<1)+l)<<1];
          tx_layers[l][(i<<1)+1] = mod_symbs[0][(((i<<1)+l)<<1)+1];
        }
Guy De Souza's avatar
Guy De Souza committed
141
      for (int i=0; i<n_symbs/3; i++)
142 143 144 145 146 147 148 149
        for (int l=2; l<5; l++) {
          tx_layers[l][i<<1] = mod_symbs[1][(3*i+l)<<1];
          tx_layers[l][(i<<1)+1] = mod_symbs[1][((3*i+l)<<1)+1];
      }
    break;

    case 6:
      for (int q=0; q<2; q++)
Guy De Souza's avatar
Guy De Souza committed
150
        for (int i=0; i<n_symbs/3; i++)
151 152 153 154 155 156 157
          for (int l=0; l<3; l++) {
            tx_layers[l][i<<1] = mod_symbs[q][(3*i+l)<<1];
            tx_layers[l][(i<<1)+1] = mod_symbs[q][((3*i+l)<<1)+1];
          }
    break;

    case 7:
Guy De Souza's avatar
Guy De Souza committed
158
      for (int i=0; i<n_symbs/3; i++)
159 160 161 162
        for (int l=0; l<3; l++) {
          tx_layers[l][i<<1] = mod_symbs[1][(3*i+l)<<1];
          tx_layers[l][(i<<1)+1] = mod_symbs[1][((3*i+l)<<1)+1];
        }
Guy De Souza's avatar
Guy De Souza committed
163
      for (int i=0; i<n_symbs/4; i++)
164 165 166 167 168 169 170 171
        for (int l=3; l<7; l++) {
          tx_layers[l][i<<1] = mod_symbs[0][((i<<2)+l)<<1];
          tx_layers[l][(i<<1)+1] = mod_symbs[0][(((i<<2)+l)<<1)+1];
        }
    break;

    case 8:
      for (int q=0; q<2; q++)
Guy De Souza's avatar
Guy De Souza committed
172
        for (int i=0; i<n_symbs>>2; i++)
173 174 175 176 177 178 179
          for (int l=0; l<3; l++) {
            tx_layers[l][i<<1] = mod_symbs[q][((i<<2)+l)<<1];
            tx_layers[l][(i<<1)+1] = mod_symbs[q][(((i<<2)+l)<<1)+1];
          }
    break;

  default:
Guy De Souza's avatar
Guy De Souza committed
180
  AssertFatal(0, "Invalid number of layers %d\n", n_layers);
181 182 183 184 185
  }
}

uint8_t nr_generate_pdsch(NR_gNB_DLSCH_t dlsch,
                          NR_gNB_DCI_ALLOC_t dci_alloc,
Guy De Souza's avatar
Guy De Souza committed
186
                          uint32_t **pdsch_dmrs,
187 188
                          int32_t** txdataF,
                          int16_t amp,
Guy De Souza's avatar
Guy De Souza committed
189
                          uint8_t subframe,
190 191 192
                          NR_DL_FRAME_PARMS frame_parms,
                          nfapi_nr_config_request_t config) {

Guy De Souza's avatar
Guy De Souza committed
193 194 195
  NR_DL_gNB_HARQ_t *harq = dlsch.harq_processes[dci_alloc.harq_pid];
  nfapi_nr_dl_config_dlsch_pdu_rel15_t *rel15 = &harq->dlsch_pdu.dlsch_pdu_rel15;
  nfapi_nr_dl_config_pdcch_parameters_rel15_t pdcch_params = dci_alloc.pdcch_params;
Guy De Souza's avatar
Guy De Souza committed
196
  uint32_t scrambled_output[NR_MAX_NB_CODEWORDS][NR_MAX_PDSCH_ENCODED_LENGTH>>5];
197 198
  int16_t **mod_symbs = (int16_t**)dlsch.mod_symbs;
  int16_t **tx_layers = (int16_t**)dlsch.txdataF;
Guy De Souza's avatar
Guy De Souza committed
199
  uint16_t n_symbs;
200
  int8_t Wf[2], Wt[2], l0, delta;
Guy De Souza's avatar
Guy De Souza committed
201 202
  uint16_t TBS = rel15->transport_block_size;
  uint8_t Qm = rel15->modulation_order;
Guy De Souza's avatar
Guy De Souza committed
203 204

  /// CRC, coding, interleaving and rate matching
Guy De Souza's avatar
Guy De Souza committed
205
  nr_dlsch_encoding(harq->pdu, subframe, &dlsch, &frame_parms);
Guy De Souza's avatar
Guy De Souza committed
206 207

  /// scrambling
Guy De Souza's avatar
Guy De Souza committed
208 209 210 211 212
  uint16_t n_RNTI = (pdcch_params.search_space_type == NFAPI_NR_SEARCH_SPACE_TYPE_UE_SPECIFIC)? \
  ((pdcch_params.scrambling_id)?pdcch_params.rnti:0) : 0;
  uint16_t Nid = (pdcch_params.search_space_type == NFAPI_NR_SEARCH_SPACE_TYPE_UE_SPECIFIC)? \
  pdcch_params.scrambling_id : config.sch_config.physical_cell_id.value;
  for (int q=0; q<rel15->nb_codewords; q++)
Guy De Souza's avatar
Guy De Souza committed
213
    nr_pdsch_codeword_scrambling(harq->f,
Guy De Souza's avatar
Guy De Souza committed
214
                         TBS,
Guy De Souza's avatar
Guy De Souza committed
215 216 217 218
                         q,
                         Nid,
                         n_RNTI,
                         scrambled_output[q]);
Guy De Souza's avatar
Guy De Souza committed
219
#ifdef DEBUG_DLSCH
Guy De Souza's avatar
Guy De Souza committed
220 221 222 223
//printf("PDSCH Scrambling(TBS %d): before  \t after \n", TBS);
//for (int i=0; i<TBS; i++) {
  //printf("%d\t%d\n", harq->f[i], scrambled_output[0][i]);
//}
Guy De Souza's avatar
Guy De Souza committed
224 225
#endif

Guy De Souza's avatar
Guy De Souza committed
226 227
 
  /// Modulation
Guy De Souza's avatar
Guy De Souza committed
228
  n_symbs = TBS/Qm;
Guy De Souza's avatar
Guy De Souza committed
229
  for (int q=0; q<rel15->nb_codewords; q++)
Guy De Souza's avatar
Guy De Souza committed
230
    nr_pdsch_codeword_modulation(scrambled_output[q],
Guy De Souza's avatar
Guy De Souza committed
231 232
                         Qm,
                         TBS,
Guy De Souza's avatar
Guy De Souza committed
233
                         mod_symbs[q]);
Guy De Souza's avatar
Guy De Souza committed
234
#ifdef DEBUG_DLSCH
Guy De Souza's avatar
Guy De Souza committed
235
printf("PDSCH Modulation: Qm %d(%d)\n", Qm, n_symbs);
Guy De Souza's avatar
Guy De Souza committed
236
for (int i=0; i<n_symbs; i++) {
Guy De Souza's avatar
Guy De Souza committed
237
  for (int j=0; j<Qm; j++) {
Guy De Souza's avatar
Guy De Souza committed
238
    printf("%d %d\t", mod_symbs[0][(i*Qm+j)<<1], mod_symbs[0][((i*Qm+j)<<1)+1]);
Guy De Souza's avatar
Guy De Souza committed
239
  }
Guy De Souza's avatar
Guy De Souza committed
240 241
  printf("\n");
}
Guy De Souza's avatar
Guy De Souza committed
242 243
#endif

Guy De Souza's avatar
Guy De Souza committed
244 245

  /// Layer mapping
246
  nr_pdsch_layer_mapping(mod_symbs,
Guy De Souza's avatar
Guy De Souza committed
247
                         rel15->nb_layers,
Guy De Souza's avatar
Guy De Souza committed
248
                         n_symbs,
249
                         tx_layers);
Guy De Souza's avatar
Guy De Souza committed
250

Guy De Souza's avatar
Guy De Souza committed
251 252 253 254
  /// Antenna port mapping
    //to be moved to init phase potentially, for now tx_layers 1-8 are mapped on antenna ports 1000-1007

  /// DMRS QPSK modulation
Guy De Souza's avatar
Guy De Souza committed
255
  uint16_t n_dmrs = rel15->n_prb*rel15->nb_re_dmrs;
256
  int16_t mod_dmrs[n_dmrs<<1];
Guy De Souza's avatar
Guy De Souza committed
257
  uint8_t dmrs_type = config.pdsch_config.dmrs_type.value;
Guy De Souza's avatar
Guy De Souza committed
258
  l0 = get_l0(dmrs_type, 2);//config.pdsch_config.dmrs_typeA_position.value);
Guy De Souza's avatar
Guy De Souza committed
259
  nr_modulation(pdsch_dmrs[l0], n_dmrs, MOD_QPSK, mod_dmrs);
Guy De Souza's avatar
Guy De Souza committed
260 261

  /// Resource mapping
Guy De Souza's avatar
Guy De Souza committed
262 263
  AssertFatal(rel15->nb_layers<=config.rf_config.tx_antenna_ports.value, "Not enough Tx antennas (%d) for %d layers\n",\
   config.rf_config.tx_antenna_ports.value, rel15->nb_layers);
Guy De Souza's avatar
Guy De Souza committed
264 265 266 267 268 269 270 271 272

    // Non interleaved VRB to PRB mapping
  uint8_t start_sc = frame_parms.first_carrier_offset + rel15->start_prb*NR_NB_SC_PER_RB +\
  ((pdcch_params.search_space_type == NFAPI_NR_SEARCH_SPACE_TYPE_COMMON) && (pdcch_params.dci_format == NFAPI_NR_DL_DCI_FORMAT_1_0))?\
       (((int)floor(frame_parms.ssb_start_subcarrier/NR_NB_SC_PER_RB) + pdcch_params.rb_offset)*NR_NB_SC_PER_RB) : 0;

  for (int ap=0; ap<rel15->nb_layers; ap++) {

    // DMRS params for this ap
273 274
    get_Wt(Wt, ap, dmrs_type);
    get_Wf(Wf, ap, dmrs_type);
Guy De Souza's avatar
Guy De Souza committed
275 276 277 278
    delta = get_delta(ap, dmrs_type);
    uint8_t k_prime=0, n=0, dmrs_idx=0;
    uint16_t m = 0;

Guy De Souza's avatar
Guy De Souza committed
279
    for (int l=rel15->start_symbol; l<rel15->nb_symbols; l++)
Guy De Souza's avatar
Guy De Souza committed
280 281 282 283 284
      for (int k=start_sc; k<rel15->n_prb*NR_NB_SC_PER_RB; k++) {
        if (k >= frame_parms.ofdm_symbol_size)
          k -= frame_parms.ofdm_symbol_size;

        if ((l==l0) && (k == ((dmrs_type)? (6*n+k_prime+delta):((n<<2)+(k_prime<<1)+delta)))) {
Guy De Souza's avatar
Guy De Souza committed
285 286
          ((int16_t*)txdataF[ap])[(l*frame_parms.ofdm_symbol_size + k)<<1] = (Wt[k_prime]*Wf[k_prime]*amp/2*mod_dmrs[dmrs_idx<<1]) >> 15;
          ((int16_t*)txdataF[ap])[((l*frame_parms.ofdm_symbol_size + k)<<1) + 1] = (Wt[k_prime]*Wf[k_prime]*amp/2*mod_dmrs[(dmrs_idx<<1) + 1]) >> 15;
287
          dmrs_idx++;
Guy De Souza's avatar
Guy De Souza committed
288
          n++;
289 290
          k_prime++;
          k_prime&=1;
Guy De Souza's avatar
Guy De Souza committed
291 292 293 294 295 296 297 298 299
        }

        ((int16_t*)txdataF[ap])[(l*frame_parms.ofdm_symbol_size + k)<<1] = (amp * tx_layers[ap][m<<1]) >> 15;
        ((int16_t*)txdataF[ap])[((l*frame_parms.ofdm_symbol_size + k)<<1) + 1] = (amp * tx_layers[ap][(m<<1) + 1]) >> 15;
        m++;
      }
  }

#ifdef DEBUG_DLSCH
Guy De Souza's avatar
Guy De Souza committed
300
  write_output("txdataF_dlsch.m", "txdataF_dlsch", txdataF[0], frame_parms.samples_per_subframe_wCP>>1, 1, 1);
Guy De Souza's avatar
Guy De Souza committed
301 302
#endif

303 304
  return 0;
}