nr_dlsch.c 12.3 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
/*
 * 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
 */

22 23 24 25
/*! \file PHY/NR_TRANSPORT/dlsch_decoding.c
* \brief Top-level routines for transmission of the PDSCH 38211 v 15.2.0
* \author Guy De Souza
* \date 2018
26 27
* \version 0.1
* \company Eurecom
28
* \email: desouza@eurecom.fr
29 30 31
* \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
//#define DEBUG_DLSCH_MAPPING
Guy De Souza's avatar
Guy De Souza committed
39

40 41 42
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
43
void nr_pdsch_codeword_scrambling(uint8_t *in,
Guy De Souza's avatar
Guy De Souza committed
44
                         uint16_t size,
45 46 47 48 49
                         uint8_t q,
                         uint32_t Nid,
                         uint32_t n_RNTI,
                         uint32_t* out) {

50
  uint8_t reset, b_idx;
51 52 53 54 55 56
  uint32_t x1, x2, s=0;

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

  for (int i=0; i<size; i++) {
57 58
    b_idx = i&0x1f;
    if (b_idx==0) {
59 60
      s = lte_gold_generic(&x1, &x2, reset);
      reset = 0;
61 62
      if (i)
        out++;
63
    }
64
    *out ^= (((in[i])&1) ^ ((s>>b_idx)&1))<<b_idx;
Guy De Souza's avatar
Guy De Souza committed
65
    //printf("i %d b_idx %d in %d s 0x%08x out 0x%08x\n", i, b_idx, in[i], s, *out);
66 67 68 69
  }

}

Guy De Souza's avatar
Guy De Souza committed
70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94
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];
  }
}

95 96 97
void nr_pdsch_codeword_modulation(uint32_t *in,
                         uint8_t  Qm,
                         uint32_t length,
Guy De Souza's avatar
Guy De Souza committed
98
                         int16_t *out) {
99 100 101 102 103 104 105 106 107 108 109 110

  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
111
      idx ^= (((*in)>>b_idx)&1)<<(Qm-j-1);
112 113 114 115 116 117 118
    }

    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
119
void nr_pdsch_layer_mapping(int16_t **mod_symbs,
120
                         uint8_t n_layers,
Guy De Souza's avatar
Guy De Souza committed
121
                         uint16_t n_symbs,
Guy De Souza's avatar
Guy De Souza committed
122
                         int16_t **tx_layers) {
123 124 125 126

  switch (n_layers) {

    case 1:
Guy De Souza's avatar
Guy De Souza committed
127
      memcpy((void*)tx_layers[0], (void*)mod_symbs[0], (n_symbs<<1)*sizeof(int16_t));
128 129 130 131 132
    break;

    case 2:
    case 3:
    case 4:
Guy De Souza's avatar
Guy De Souza committed
133
      for (int i=0; i<n_symbs/n_layers; i++)
134 135 136 137 138 139 140
        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
141
      for (int i=0; i<n_symbs>>1; i++)
142 143 144 145
        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
146
      for (int i=0; i<n_symbs/3; i++)
147 148 149 150 151 152 153 154
        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
155
        for (int i=0; i<n_symbs/3; i++)
156 157 158 159 160 161 162
          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
163
      for (int i=0; i<n_symbs/3; i++)
164 165 166 167
        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
168
      for (int i=0; i<n_symbs/4; i++)
169 170 171 172 173 174 175 176
        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
177
        for (int i=0; i<n_symbs>>2; i++)
178 179 180 181 182 183 184
          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
185
  AssertFatal(0, "Invalid number of layers %d\n", n_layers);
186 187 188
  }
}

Guy De Souza's avatar
Guy De Souza committed
189 190 191 192 193
static inline uint16_t get_pdsch_dmrs_idx(uint8_t n, uint8_t k_prime, uint8_t delta, uint8_t dmrs_type) {
  uint16_t dmrs_idx = (dmrs_type)? (6*n+k_prime+delta):((n<<2)+(k_prime<<1)+delta);
  return dmrs_idx;
}

194 195
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
196
                          uint32_t ***pdsch_dmrs,
197 198
                          int32_t** txdataF,
                          int16_t amp,
199
                          uint8_t slot,
200 201 202
                          NR_DL_FRAME_PARMS frame_parms,
                          nfapi_nr_config_request_t config) {

Guy De Souza's avatar
Guy De Souza committed
203 204 205
  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
206
  uint32_t scrambled_output[NR_MAX_NB_CODEWORDS][NR_MAX_PDSCH_ENCODED_LENGTH>>5];
207 208
  int16_t **mod_symbs = (int16_t**)dlsch.mod_symbs;
  int16_t **tx_layers = (int16_t**)dlsch.txdataF;
209 210
  int8_t Wf[2], Wt[2], l0, l_prime[2], delta;
  uint16_t nb_symbols = rel15->nb_mod_symbols;
Guy De Souza's avatar
Guy De Souza committed
211
  uint8_t Qm = rel15->modulation_order;
212
  uint16_t encoded_length = nb_symbols*Qm;
Guy De Souza's avatar
Guy De Souza committed
213 214

  /// CRC, coding, interleaving and rate matching
215
  nr_dlsch_encoding(harq->pdu, slot, &dlsch, &frame_parms);
Guy De Souza's avatar
Guy De Souza committed
216 217
#ifdef DEBUG_DLSCH
printf("PDSCH encoding:\nPayload:\n");
218
for (int i=0; i<harq->B>>7; i++) {
Guy De Souza's avatar
Guy De Souza committed
219 220 221 222 223
  for (int j=0; j<16; j++)
    printf("0x%02x\t", harq->pdu[(i<<4)+j]);
  printf("\n");
}
printf("\nEncoded payload:\n");
Guy De Souza's avatar
Guy De Souza committed
224 225 226 227
for (int i=0; i<encoded_length>>3; i++) {
  for (int j=0; j<8; j++)
    printf("%d", harq->f[(i<<3)+j]);
  printf("\t");
Guy De Souza's avatar
Guy De Souza committed
228
}
Guy De Souza's avatar
Guy De Souza committed
229
printf("\n");
Guy De Souza's avatar
Guy De Souza committed
230
#endif
Guy De Souza's avatar
Guy De Souza committed
231 232

  /// scrambling
Guy De Souza's avatar
Guy De Souza committed
233 234
  for (int q=0; q<rel15->nb_codewords; q++)
    memset((void*)scrambled_output[q], 0, (encoded_length>>5)*sizeof(uint32_t));
Guy De Souza's avatar
Guy De Souza committed
235 236 237 238 239
  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
240
    nr_pdsch_codeword_scrambling(harq->f,
241
                         encoded_length,
Guy De Souza's avatar
Guy De Souza committed
242 243 244 245
                         q,
                         Nid,
                         n_RNTI,
                         scrambled_output[q]);
Guy De Souza's avatar
Guy De Souza committed
246
#ifdef DEBUG_DLSCH
Guy De Souza's avatar
Guy De Souza committed
247
printf("PDSCH scrambling:\n");
Guy De Souza's avatar
Guy De Souza committed
248
for (int i=0; i<encoded_length>>8; i++) {
Guy De Souza's avatar
Guy De Souza committed
249 250 251 252
  for (int j=0; j<8; j++)
    printf("0x%08x\t", scrambled_output[0][(i<<3)+j]);
  printf("\n");
}
Guy De Souza's avatar
Guy De Souza committed
253
#endif
Guy De Souza's avatar
Guy De Souza committed
254 255
 
  /// Modulation
Guy De Souza's avatar
Guy De Souza committed
256
  for (int q=0; q<rel15->nb_codewords; q++)
Guy De Souza's avatar
Guy De Souza committed
257
    nr_pdsch_codeword_modulation(scrambled_output[q],
Guy De Souza's avatar
Guy De Souza committed
258
                         Qm,
259
                         encoded_length,
Guy De Souza's avatar
Guy De Souza committed
260
                         mod_symbs[q]);
Guy De Souza's avatar
Guy De Souza committed
261
#ifdef DEBUG_DLSCH
Guy De Souza's avatar
Guy De Souza committed
262
printf("PDSCH Modulation: Qm %d(%d)\n", Qm, nb_symbols);
263
for (int i=0; i<nb_symbols>>3; i++) {
Guy De Souza's avatar
Guy De Souza committed
264 265
  for (int j=0; j<8; j++) {
    printf("%d %d\t", mod_symbs[0][((i<<3)+j)<<1], mod_symbs[0][(((i<<3)+j)<<1)+1]);
Guy De Souza's avatar
Guy De Souza committed
266
  }
Guy De Souza's avatar
Guy De Souza committed
267 268
  printf("\n");
}
Guy De Souza's avatar
Guy De Souza committed
269 270
#endif

Guy De Souza's avatar
Guy De Souza committed
271 272

  /// Layer mapping
273
  nr_pdsch_layer_mapping(mod_symbs,
Guy De Souza's avatar
Guy De Souza committed
274
                         rel15->nb_layers,
275
                         nb_symbols,
276
                         tx_layers);
Guy De Souza's avatar
Guy De Souza committed
277 278 279
#ifdef DEBUG_DLSCH
printf("Layer mapping (%d layers):\n", rel15->nb_layers);
for (int l=0; l<rel15->nb_layers; l++)
Guy De Souza's avatar
Guy De Souza committed
280
  for (int i=0; i<(nb_symbols/rel15->nb_layers)>>3; i++) {
Guy De Souza's avatar
Guy De Souza committed
281 282 283 284 285 286
    for (int j=0; j<8; j++) {
      printf("%d %d\t", tx_layers[l][((i<<3)+j)<<1], tx_layers[l][(((i<<3)+j)<<1)+1]);
    }
    printf("\n");
  }
#endif
Guy De Souza's avatar
Guy De Souza committed
287

Guy De Souza's avatar
Guy De Souza committed
288 289 290 291
  /// 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
292
  uint16_t n_dmrs = (rel15->n_prb*rel15->nb_re_dmrs)<<1;
293
  int16_t mod_dmrs[n_dmrs<<1];
Guy De Souza's avatar
Guy De Souza committed
294
  uint8_t dmrs_type = config.pdsch_config.dmrs_type.value;
Guy De Souza's avatar
Guy De Souza committed
295
  l0 = get_l0(dmrs_type, 2);//config.pdsch_config.dmrs_typeA_position.value);
Guy De Souza's avatar
Guy De Souza committed
296
  nr_modulation(pdsch_dmrs[l0][0], n_dmrs, MOD_QPSK, mod_dmrs); // currently only codeword 0 is modulated
297
#ifdef DEBUG_DLSCH
298 299
printf("DMRS modulation (single symbol %d, %d symbols, type %d):\n", l0, n_dmrs>>1, dmrs_type);
for (int i=0; i<n_dmrs>>4; i++) {
Guy De Souza's avatar
Guy De Souza committed
300 301 302 303 304
  for (int j=0; j<8; j++) {
    printf("%d %d\t", mod_dmrs[((i<<3)+j)<<1], mod_dmrs[(((i<<3)+j)<<1)+1]);
  }
  printf("\n");
}
305
#endif
Guy De Souza's avatar
Guy De Souza committed
306 307

  /// Resource mapping
308

Guy De Souza's avatar
Guy De Souza committed
309 310

    // Non interleaved VRB to PRB mapping
311 312 313
 uint16_t start_sc = frame_parms.first_carrier_offset + rel15->start_prb*NR_NB_SC_PER_RB;
 if (start_sc >= frame_parms.ofdm_symbol_size)
   start_sc -= frame_parms.ofdm_symbol_size;
Guy De Souza's avatar
Guy De Souza committed
314

Guy De Souza's avatar
Guy De Souza committed
315
#ifdef DEBUG_DLSCH_MAPPING
316 317
 printf("PDSCH resource mapping started (start SC %d\tstart symbol %d\tN_PRB %d\tnb_symbols %d)\n",
	start_sc, rel15->start_symbol, rel15->n_prb, rel15->nb_symbols);
Guy De Souza's avatar
Guy De Souza committed
318 319
#endif

Guy De Souza's avatar
Guy De Souza committed
320 321 322
  for (int ap=0; ap<rel15->nb_layers; ap++) {

    // DMRS params for this ap
323 324
    get_Wt(Wt, ap, dmrs_type);
    get_Wf(Wf, ap, dmrs_type);
Guy De Souza's avatar
Guy De Souza committed
325
    delta = get_delta(ap, dmrs_type);
326
    l_prime[0] = 0; // single symbol ap 0
Guy De Souza's avatar
Guy De Souza committed
327
    uint8_t dmrs_symbol = l0+l_prime[0];
Guy De Souza's avatar
Guy De Souza committed
328
#ifdef DEBUG_DLSCH_MAPPING
329 330
printf("DMRS params for ap %d: Wt %d %d \t Wf %d %d \t delta %d \t l_prime %d \t l0 %d\tDMRS symbol %d\n",
ap, Wt[0], Wt[1], Wf[0], Wf[1], delta, l_prime[0], l0, dmrs_symbol);
Guy De Souza's avatar
Guy De Souza committed
331
#endif
Guy De Souza's avatar
Guy De Souza committed
332
    uint8_t k_prime=0;
333 334 335 336 337
    uint16_t m=0, n=0, dmrs_idx=0, k=0;

    for (int l=rel15->start_symbol; l<rel15->start_symbol+rel15->nb_symbols; l++) {
      k = start_sc;
      for (int i=0; i<rel15->n_prb*NR_NB_SC_PER_RB; i++) {
Guy De Souza's avatar
Guy De Souza committed
338 339 340
        if ((l == dmrs_symbol) && (k == ((start_sc+get_pdsch_dmrs_idx(n, k_prime, delta, dmrs_type))%(frame_parms.ofdm_symbol_size)))) {
          ((int16_t*)txdataF[ap])[(l*frame_parms.ofdm_symbol_size + k)<<1] = (Wt[l_prime[0]]*Wf[k_prime]*amp*mod_dmrs[dmrs_idx<<1]) >> 15;
          ((int16_t*)txdataF[ap])[((l*frame_parms.ofdm_symbol_size + k)<<1) + 1] = (Wt[l_prime[0]]*Wf[k_prime]*amp*mod_dmrs[(dmrs_idx<<1) + 1]) >> 15;
Guy De Souza's avatar
Guy De Souza committed
341
#ifdef DEBUG_DLSCH_MAPPING
Guy De Souza's avatar
Guy De Souza committed
342
printf("dmrs_idx %d\t l %d \t k %d \t k_prime %d \t n %d \t txdataF: %d %d\n",
343 344
dmrs_idx, l, k, k_prime, n, ((int16_t*)txdataF[ap])[(l*frame_parms.ofdm_symbol_size + k)<<1],
((int16_t*)txdataF[ap])[((l*frame_parms.ofdm_symbol_size + k)<<1) + 1]);
Guy De Souza's avatar
Guy De Souza committed
345
#endif
346 347 348
          dmrs_idx++;
          k_prime++;
          k_prime&=1;
Guy De Souza's avatar
Guy De Souza committed
349
          n+=(k_prime)?0:1;
Guy De Souza's avatar
Guy De Souza committed
350 351
        }

Guy De Souza's avatar
Guy De Souza committed
352 353
        else {

Guy De Souza's avatar
Guy De Souza committed
354 355
          ((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;
Guy De Souza's avatar
Guy De Souza committed
356
#ifdef DEBUG_DLSCH_MAPPING
Guy De Souza's avatar
Guy De Souza committed
357
printf("m %d\t l %d \t k %d \t txdataF: %d %d\n",
358 359
m, l, k, ((int16_t*)txdataF[ap])[(l*frame_parms.ofdm_symbol_size + k)<<1],
((int16_t*)txdataF[ap])[((l*frame_parms.ofdm_symbol_size + k)<<1) + 1]);
Guy De Souza's avatar
Guy De Souza committed
360
#endif
Guy De Souza's avatar
Guy De Souza committed
361 362
          m++;
        }
363 364
        if (++k >= frame_parms.ofdm_symbol_size)
          k -= frame_parms.ofdm_symbol_size;
Guy De Souza's avatar
Guy De Souza committed
365
      }
366
    }
Guy De Souza's avatar
Guy De Souza committed
367
  }
368 369
  return 0;
}