srsLTE/lib/src/phy/phch/regs.c

832 lines
22 KiB
C

/**
* Copyright 2013-2022 Software Radio Systems Limited
*
* This file is part of srsRAN.
*
* srsRAN is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* srsRAN is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "srsran/phy/common/phy_common.h"
#include "srsran/phy/phch/regs.h"
#include "srsran/phy/utils/debug.h"
#define REG_IDX(r, i, n) r->k[i] + r->l* n* SRSRAN_NRE
srsran_regs_reg_t* regs_find_reg(srsran_regs_t* h, uint32_t k, uint32_t l);
int regs_put_reg(srsran_regs_reg_t* reg, cf_t* reg_data, cf_t* slot_symbols, uint32_t nof_prb);
int regs_add_reg(srsran_regs_reg_t* reg, cf_t* reg_data, cf_t* slot_symbols, uint32_t nof_prb);
int regs_get_reg(srsran_regs_reg_t* reg, cf_t* slot_symbols, cf_t* reg_data, uint32_t nof_prb);
int regs_reset_reg(srsran_regs_reg_t* reg, cf_t* slot_symbols, uint32_t nof_prb);
/***************************************************************
*
* PDCCH REG ALLOCATION
*
***************************************************************/
void regs_pdcch_free(srsran_regs_t* h)
{
int i;
for (i = 0; i < 3; i++) {
if (h->pdcch[i].regs) {
free(h->pdcch[i].regs);
h->pdcch[i].regs = NULL;
}
}
}
#define PDCCH_NCOLS 32
const uint8_t PDCCH_PERM[PDCCH_NCOLS] = {1, 17, 9, 25, 5, 21, 13, 29, 3, 19, 11, 27, 7, 23, 15, 31,
0, 16, 8, 24, 4, 20, 12, 28, 2, 18, 10, 26, 6, 22, 14, 30};
/** Initialize REGs for PDCCH
* 36.211 10.3 section 6.8.5
*/
int regs_pdcch_init(srsran_regs_t* h)
{
int i, m, cfi, nof_ctrl_symbols;
int ret = SRSRAN_ERROR;
int nrows, ndummy, j;
uint32_t k, kp;
srsran_regs_reg_t** tmp = NULL;
bzero(&h->pdcch, sizeof(srsran_regs_ch_t));
for (cfi = 0; cfi < 3; cfi++) {
if (h->cell.nof_prb <= 10) {
nof_ctrl_symbols = cfi + 2;
} else {
nof_ctrl_symbols = cfi + 1;
}
tmp = malloc(sizeof(srsran_regs_reg_t*) * h->nof_regs);
if (!tmp) {
perror("malloc");
goto clean_and_exit;
}
/* Number and count REGs for this CFI */
m = 0;
for (i = 0; i < h->nof_regs; i++) {
if (h->regs[i].l < nof_ctrl_symbols && !h->regs[i].assigned) {
tmp[m] = &h->regs[i];
m++;
}
}
h->pdcch[cfi].nof_regs = m;
h->pdcch[cfi].regs = malloc(sizeof(srsran_regs_reg_t*) * h->pdcch[cfi].nof_regs);
if (!h->pdcch[cfi].regs) {
perror("malloc");
goto clean_and_exit;
}
/* Interleave REGs */
nrows = (h->pdcch[cfi].nof_regs - 1) / PDCCH_NCOLS + 1;
ndummy = PDCCH_NCOLS * nrows - h->pdcch[cfi].nof_regs;
if (ndummy < 0) {
ndummy = 0;
}
k = 0;
for (j = 0; j < PDCCH_NCOLS; j++) {
for (i = 0; i < nrows; i++) {
if (i * PDCCH_NCOLS + PDCCH_PERM[j] >= ndummy) {
m = i * PDCCH_NCOLS + PDCCH_PERM[j] - ndummy;
if (k < h->cell.id) {
kp = (h->pdcch[cfi].nof_regs + k - (h->cell.id % h->pdcch[cfi].nof_regs)) % h->pdcch[cfi].nof_regs;
} else {
kp = (k - h->cell.id) % h->pdcch[cfi].nof_regs;
}
h->pdcch[cfi].regs[m] = tmp[kp];
k++;
}
}
}
h->pdcch[cfi].nof_regs = (h->pdcch[cfi].nof_regs / 9) * 9;
INFO("Init PDCCH REG space CFI %d. %d useful REGs (%d CCEs)",
cfi + 1,
h->pdcch[cfi].nof_regs,
h->pdcch[cfi].nof_regs / 9);
free(tmp);
tmp = NULL;
}
ret = SRSRAN_SUCCESS;
clean_and_exit:
if (tmp) {
free(tmp);
}
if (ret == SRSRAN_ERROR) {
regs_pdcch_free(h);
}
return ret;
}
int srsran_regs_pdcch_nregs(srsran_regs_t* h, uint32_t cfi)
{
if (cfi < 1 || cfi > 3) {
ERROR("Invalid CFI=%d", cfi);
return SRSRAN_ERROR;
} else {
return (int)h->pdcch[cfi - 1].nof_regs;
}
}
int srsran_regs_pdcch_ncce(srsran_regs_t* h, uint32_t cfi)
{
int nregs = srsran_regs_pdcch_nregs(h, cfi);
if (nregs > 0) {
return (uint32_t)(nregs / 9);
} else {
return SRSRAN_ERROR;
}
}
/** Copy quadruplets to REGs and cyclic shift them, according to the
* second part of 6.8.5 in 36.211
*/
int srsran_regs_pdcch_put_offset(srsran_regs_t* h,
uint32_t cfi,
cf_t* d,
cf_t* slot_symbols,
uint32_t start_reg,
uint32_t nof_regs)
{
if (cfi < 1 || cfi > 3) {
ERROR("Invalid CFI=%d", cfi);
return SRSRAN_ERROR;
}
if (start_reg + nof_regs <= h->pdcch[cfi - 1].nof_regs) {
uint32_t i, k;
k = 0;
for (i = start_reg; i < start_reg + nof_regs; i++) {
regs_put_reg(h->pdcch[cfi - 1].regs[i], &d[k], slot_symbols, h->cell.nof_prb);
k += 4;
}
return k;
} else {
ERROR("Out of range: start_reg + nof_reg must be lower than %d", h->pdcch[cfi - 1].nof_regs);
return SRSRAN_ERROR;
}
}
int srsran_regs_pdcch_put(srsran_regs_t* h, uint32_t cfi, cf_t* d, cf_t* slot_symbols)
{
if (cfi < 1 || cfi > 3) {
ERROR("Invalid CFI=%d", cfi);
return SRSRAN_ERROR;
}
return srsran_regs_pdcch_put_offset(h, cfi, d, slot_symbols, 0, h->pdcch[cfi - 1].nof_regs);
}
int srsran_regs_pdcch_get_offset(srsran_regs_t* h,
uint32_t cfi,
cf_t* slot_symbols,
cf_t* d,
uint32_t start_reg,
uint32_t nof_regs)
{
if (cfi < 1 || cfi > 3) {
ERROR("Invalid CFI=%d", cfi);
return SRSRAN_ERROR;
}
if (start_reg + nof_regs <= h->pdcch[cfi - 1].nof_regs) {
uint32_t i, k;
k = 0;
for (i = start_reg; i < start_reg + nof_regs; i++) {
regs_get_reg(h->pdcch[cfi - 1].regs[i], slot_symbols, &d[k], h->cell.nof_prb);
k += 4;
}
return k;
} else {
ERROR("Out of range: start_reg + nof_reg must be lower than %d", h->pdcch[cfi - 1].nof_regs);
return SRSRAN_ERROR;
}
}
int srsran_regs_pdcch_get(srsran_regs_t* h, uint32_t cfi, cf_t* slot_symbols, cf_t* d)
{
if (cfi < 1 || cfi > 3) {
ERROR("Invalid CFI=%d", cfi);
return SRSRAN_ERROR;
}
return srsran_regs_pdcch_get_offset(h, cfi, slot_symbols, d, 0, h->pdcch[cfi - 1].nof_regs);
}
/***************************************************************
*
* PHICH REG ALLOCATION
*
***************************************************************/
/** Initialize REGs for PHICH
* 36.211 10.3 section 6.9.3
*/
int regs_phich_init(srsran_regs_t* h, uint32_t phich_mi, bool mbsfn_or_sf1_6_tdd)
{
float ng;
uint32_t i, ni, li, n[3], nreg, mi;
srsran_regs_reg_t** regs_phich[3];
int ret = SRSRAN_ERROR;
for (int i = 0; i < 3; i++) {
regs_phich[i] = NULL;
}
switch (h->phich_res) {
case SRSRAN_PHICH_R_1_6:
ng = (float)1 / 6;
break;
case SRSRAN_PHICH_R_1_2:
ng = (float)1 / 2;
break;
case SRSRAN_PHICH_R_1:
ng = 1;
break;
case SRSRAN_PHICH_R_2:
ng = 2;
break;
default:
ng = 0;
break;
}
h->ngroups_phich_m1 = (int)ceilf(ng * ((float)h->cell.nof_prb / 8));
h->ngroups_phich = (int)phich_mi * h->ngroups_phich_m1;
h->phich = malloc(sizeof(srsran_regs_ch_t) * h->ngroups_phich);
if (!h->phich) {
perror("malloc");
return -1;
}
INFO("Creating %d PHICH mapping units. %s length, Ng=%.2f",
h->ngroups_phich,
h->phich_len == SRSRAN_PHICH_EXT ? "Extended" : "Normal",
ng);
for (i = 0; i < h->ngroups_phich; i++) {
h->phich[i].nof_regs = REGS_PHICH_REGS_X_GROUP;
h->phich[i].regs = malloc(sizeof(srsran_regs_reg_t*) * REGS_PHICH_REGS_X_GROUP);
if (!h->phich[i].regs) {
perror("malloc");
goto clean_and_exit;
}
}
/** Here begins the mapping algorithm */
/* Step 2. Count REGs not assigned to PCFICH */
bzero(n, 3 * sizeof(int));
for (i = 0; i < h->nof_regs; i++) {
if (h->regs[i].l < 3 && !h->regs[i].assigned) {
n[h->regs[i].l]++;
}
}
bzero(regs_phich, sizeof(srsran_regs_reg_t*) * 3);
for (i = 0; i < 3; i++) {
regs_phich[i] = malloc(n[i] * sizeof(srsran_regs_reg_t*));
if (!regs_phich[i]) {
perror("malloc");
goto clean_and_exit;
}
}
bzero(n, 3 * sizeof(int));
/* Step 3. Number REGs not assigned to PCFICH */
for (i = 0; i < h->nof_regs; i++) {
// they are already sorted starting from the REG with the lowest frequency-domain index
if (h->regs[i].l < 3 && !h->regs[i].assigned) {
regs_phich[h->regs[i].l][n[h->regs[i].l]++] = &h->regs[i];
}
}
nreg = 0;
for (mi = 0; mi < h->ngroups_phich; mi++) { // here ngroups is the number of mapping units
for (i = 0; i < 3; i++) {
// Step 7
if (h->phich_len == SRSRAN_PHICH_NORM) {
li = 0;
} else if (h->phich_len == SRSRAN_PHICH_EXT && mbsfn_or_sf1_6_tdd) {
li = (mi / 2 + i + 1) % 2;
} else {
li = i;
}
// Step 8
if (h->phich_len == SRSRAN_PHICH_EXT && mbsfn_or_sf1_6_tdd) {
ni = ((h->cell.id * n[li] / n[1]) + mi + i * n[li] / 3) % n[li];
} else {
ni = ((h->cell.id * n[li] / n[0]) + mi + i * n[li] / 3) % n[li];
}
h->phich[mi].regs[i] = regs_phich[li][ni];
h->phich[mi].regs[i]->assigned = true;
DEBUG("Assigned PHICH REG#%d (%d,%d)", nreg, h->phich[mi].regs[i]->k0, li);
nreg++;
}
}
// now the number of mapping units = number of groups for normal cp. For extended cp
// ngroups = 2 * number mapping units
if (SRSRAN_CP_ISEXT(h->cell.cp)) {
h->ngroups_phich *= 2;
}
ret = SRSRAN_SUCCESS;
clean_and_exit:
if (ret == SRSRAN_ERROR) {
if (h->phich) {
for (i = 0; i < h->ngroups_phich; i++) {
if (h->phich[i].regs) {
free(h->phich[i].regs);
}
}
free(h->phich);
}
}
for (i = 0; i < 3; i++) {
if (regs_phich[i]) {
free(regs_phich[i]);
}
}
return ret;
}
void regs_phich_free(srsran_regs_t* h)
{
uint32_t i;
if (h->phich) {
if (SRSRAN_CP_ISEXT(h->cell.cp)) {
h->ngroups_phich /= 2;
}
for (i = 0; i < h->ngroups_phich; i++) {
if (h->phich[i].regs) {
free(h->phich[i].regs);
h->phich[i].regs = NULL;
}
}
free(h->phich);
h->phich = NULL;
}
}
uint32_t srsran_regs_phich_nregs(srsran_regs_t* h)
{
uint32_t i;
uint32_t n;
n = 0;
for (i = 0; i < h->ngroups_phich; i++) {
n += h->phich[i].nof_regs;
}
return n;
}
uint32_t srsran_regs_phich_ngroups(srsran_regs_t* h)
{
return h->ngroups_phich;
}
uint32_t srsran_regs_phich_ngroups_m1(srsran_regs_t* h)
{
return h->ngroups_phich_m1;
}
/**
* Adds the PHICH symbols to the resource grid pointed by slot_symbols.
*
* Each subframe, the user shall call the srsran_v function before adding PHICH symbols.
*
* Returns the number of written symbols, or -1 on error
*/
int srsran_regs_phich_add(srsran_regs_t* h, cf_t symbols[REGS_PHICH_NSYM], uint32_t ngroup, cf_t* slot_symbols)
{
uint32_t i;
if (ngroup >= h->ngroups_phich) {
ERROR("Error invalid ngroup %d", ngroup);
return SRSRAN_ERROR_INVALID_INPUTS;
}
if (SRSRAN_CP_ISEXT(h->cell.cp)) {
ngroup /= 2;
}
srsran_regs_ch_t* rch = &h->phich[ngroup];
for (i = 0; i < rch->nof_regs && i * REGS_RE_X_REG < REGS_PHICH_NSYM; i++) {
regs_add_reg(rch->regs[i], &symbols[i * REGS_RE_X_REG], slot_symbols, h->cell.nof_prb);
}
return i * REGS_RE_X_REG;
}
/**
* Resets the PHICH symbols
*
* Returns the number of written symbols, or -1 on error
*/
int srsran_regs_phich_reset(srsran_regs_t* h, cf_t* slot_symbols)
{
uint32_t i;
uint32_t ngroup, ng;
for (ngroup = 0; ngroup < h->ngroups_phich; SRSRAN_CP_ISEXT(h->cell.cp) ? ngroup += 2 : ngroup++) {
if (SRSRAN_CP_ISEXT(h->cell.cp)) {
ng = ngroup / 2;
} else {
ng = ngroup;
}
srsran_regs_ch_t* rch = &h->phich[ng];
for (i = 0; i < rch->nof_regs && i * REGS_RE_X_REG < REGS_PHICH_NSYM; i++) {
regs_reset_reg(rch->regs[i], slot_symbols, h->cell.nof_prb);
}
}
return SRSRAN_SUCCESS;
}
/**
* Gets the PHICH symbols from the resource grid pointed by slot_symbols
*
* Returns the number of written symbols, or -1 on error
*/
int srsran_regs_phich_get(srsran_regs_t* h, cf_t* slot_symbols, cf_t symbols[REGS_PHICH_NSYM], uint32_t ngroup)
{
uint32_t i;
if (ngroup >= h->ngroups_phich) {
ERROR("Error invalid ngroup %d", ngroup);
return SRSRAN_ERROR_INVALID_INPUTS;
}
if (SRSRAN_CP_ISEXT(h->cell.cp)) {
ngroup /= 2;
}
srsran_regs_ch_t* rch = &h->phich[ngroup];
for (i = 0; i < rch->nof_regs && i * REGS_RE_X_REG < REGS_PHICH_NSYM; i++) {
regs_get_reg(rch->regs[i], slot_symbols, &symbols[i * REGS_RE_X_REG], h->cell.nof_prb);
}
return i * REGS_RE_X_REG;
}
/***************************************************************
*
* PCFICH REG ALLOCATION
*
***************************************************************/
/** Initialize REGs for PCFICH
* 36.211 10.3 section 6.7.4
*/
int regs_pcfich_init(srsran_regs_t* h)
{
uint32_t i;
uint32_t k_hat, k;
srsran_regs_ch_t* ch = &h->pcfich;
ch->regs = malloc(sizeof(srsran_regs_reg_t*) * REGS_PCFICH_NREGS);
if (!ch->regs) {
perror("malloc");
return SRSRAN_ERROR;
}
ch->nof_regs = REGS_PCFICH_NREGS;
INFO("PCFICH allocating %d regs. CellID: %d, PRB: %d", ch->nof_regs, h->cell.id, h->cell.nof_prb);
k_hat = (SRSRAN_NRE / 2) * (h->cell.id % (2 * h->cell.nof_prb));
for (i = 0; i < REGS_PCFICH_NREGS; i++) {
k = (k_hat + (i * h->cell.nof_prb / 2) * (SRSRAN_NRE / 2)) % (h->cell.nof_prb * SRSRAN_NRE);
ch->regs[i] = regs_find_reg(h, k, 0);
if (!ch->regs[i]) {
ERROR("Error allocating PCFICH: REG (%d,0) not found", k);
return SRSRAN_ERROR;
} else if (ch->regs[i]->assigned) {
ERROR("Error allocating PCFICH: REG (%d,0) already allocated", k);
return SRSRAN_ERROR;
} else {
ch->regs[i]->assigned = true;
DEBUG("Assigned PCFICH REG#%d (%d,0)", i, k);
}
}
return SRSRAN_SUCCESS;
}
void regs_pcfich_free(srsran_regs_t* h)
{
if (h->pcfich.regs) {
free(h->pcfich.regs);
h->pcfich.regs = NULL;
}
}
uint32_t srsran_regs_pcfich_nregs(srsran_regs_t* h)
{
return h->pcfich.nof_regs;
}
/**
* Maps the PCFICH symbols to the resource grid pointed by slot_symbols
*
* Returns the number of written symbols, or -1 on error
*/
int srsran_regs_pcfich_put(srsran_regs_t* h, cf_t symbols[REGS_PCFICH_NSYM], cf_t* slot_symbols)
{
srsran_regs_ch_t* rch = &h->pcfich;
uint32_t i;
for (i = 0; i < rch->nof_regs && i * REGS_RE_X_REG < REGS_PCFICH_NSYM; i++) {
regs_put_reg(rch->regs[i], &symbols[i * REGS_RE_X_REG], slot_symbols, h->cell.nof_prb);
}
return i * REGS_RE_X_REG;
}
/**
* Gets the PCFICH symbols from the resource grid pointed by slot_symbols
*
* Returns the number of written symbols, or -1 on error
*/
int srsran_regs_pcfich_get(srsran_regs_t* h, cf_t* slot_symbols, cf_t ch_data[REGS_PCFICH_NSYM])
{
srsran_regs_ch_t* rch = &h->pcfich;
uint32_t i;
for (i = 0; i < rch->nof_regs && i * REGS_RE_X_REG < REGS_PCFICH_NSYM; i++) {
regs_get_reg(rch->regs[i], slot_symbols, &ch_data[i * REGS_RE_X_REG], h->cell.nof_prb);
}
return i * REGS_RE_X_REG;
}
/***************************************************************
*
* COMMON FUNCTIONS
*
***************************************************************/
srsran_regs_reg_t* regs_find_reg(srsran_regs_t* h, uint32_t k, uint32_t l)
{
uint32_t i;
for (i = 0; i < h->nof_regs; i++) {
if (h->regs[i].l == l && h->regs[i].k0 == k) {
return &h->regs[i];
}
}
return NULL;
}
/**
* Returns the number of REGs in a PRB
* 36.211 Section 6.2.4
*/
int regs_num_x_symbol(uint32_t symbol, uint32_t nof_port, srsran_cp_t cp)
{
switch (symbol) {
case 0:
return 2;
case 1:
switch (nof_port) {
case 1:
case 2:
return 3;
case 4:
return 2;
default:
ERROR("Invalid number of ports %d", nof_port);
return SRSRAN_ERROR;
}
break;
case 2:
return 3;
case 3:
if (SRSRAN_CP_ISNORM(cp)) {
return 3;
} else {
return 2;
}
default:
ERROR("Invalid symbol %d", symbol);
return SRSRAN_ERROR;
}
return SRSRAN_ERROR;
}
/**
* Initializes the indices of a REG
* 36.211 Section 6.2.4
*/
int regs_reg_init(srsran_regs_reg_t* reg, uint32_t symbol, uint32_t nreg, uint32_t k0, uint32_t maxreg, uint32_t vo)
{
uint32_t i, j, z;
reg->l = symbol;
reg->assigned = false;
switch (maxreg) {
case 2:
reg->k0 = k0 + nreg * 6;
/* there are two references in the middle */
j = z = 0;
for (i = 0; i < vo; i++) {
reg->k[j] = k0 + nreg * 6 + i;
j++;
}
for (i = 0; i < 2; i++) {
reg->k[j] = k0 + nreg * 6 + i + vo + 1;
j++;
}
z = j;
for (i = 0; i < 4 - z; i++) {
reg->k[j] = k0 + nreg * 6 + vo + 3 + i + 1;
j++;
}
if (j != 4) {
ERROR("Something went wrong: expected 2 references");
return SRSRAN_ERROR;
}
break;
case 3:
reg->k0 = k0 + nreg * 4;
/* there is no reference */
for (i = 0; i < 4; i++) {
reg->k[i] = k0 + nreg * 4 + i;
}
break;
default:
ERROR("Invalid number of REGs per PRB: %d", maxreg);
return SRSRAN_ERROR;
}
return SRSRAN_SUCCESS;
}
void srsran_regs_free(srsran_regs_t* h)
{
if (h->regs) {
free(h->regs);
}
regs_pcfich_free(h);
regs_phich_free(h);
regs_pdcch_free(h);
bzero(h, sizeof(srsran_regs_t));
}
int srsran_regs_init(srsran_regs_t* h, srsran_cell_t cell)
{
return srsran_regs_init_opts(h, cell, 1, false);
}
/**
* Initializes REGs structure.
* Sets all REG indices and initializes PCFICH, PHICH and PDCCH REGs
* Returns 0 if OK, -1 on error
*/
int srsran_regs_init_opts(srsran_regs_t* h, srsran_cell_t cell, uint32_t phich_mi, bool mbsfn_or_sf1_6_tdd)
{
int ret = SRSRAN_ERROR_INVALID_INPUTS;
uint32_t i, k;
uint32_t j[4], jmax, prb;
uint32_t n[4], vo;
uint32_t max_ctrl_symbols;
if (h != NULL && srsran_cell_isvalid(&cell)) {
bzero(h, sizeof(srsran_regs_t));
ret = SRSRAN_ERROR;
max_ctrl_symbols = cell.nof_prb <= 10 ? 4 : 3;
vo = cell.id % 3;
h->cell = cell;
h->max_ctrl_symbols = max_ctrl_symbols;
h->phich_res = cell.phich_resources;
h->phich_len = cell.phich_length;
h->nof_regs = 0;
for (i = 0; i < max_ctrl_symbols; i++) {
n[i] = regs_num_x_symbol(i, h->cell.nof_ports, h->cell.cp);
if (n[i] == -1) {
goto clean_and_exit;
}
h->nof_regs += h->cell.nof_prb * n[i];
}
INFO("Indexing %d REGs. CellId: %d, %d PRB, CP: %s",
h->nof_regs,
h->cell.id,
h->cell.nof_prb,
SRSRAN_CP_ISNORM(h->cell.cp) ? "Normal" : "Extended");
h->regs = malloc(sizeof(srsran_regs_reg_t) * h->nof_regs);
if (!h->regs) {
perror("malloc");
goto clean_and_exit;
}
/* Sort REGs according to PDCCH mapping, beggining from the lowest l index then k */
bzero(j, sizeof(int) * 4);
k = i = prb = jmax = 0;
while (k < h->nof_regs) {
if (n[i] == 3 || (n[i] == 2 && jmax != 1)) {
if (regs_reg_init(&h->regs[k], i, j[i], prb * SRSRAN_NRE, n[i], vo)) {
ERROR("Error initializing REGs");
goto clean_and_exit;
}
/*DEBUG("Available REG #%3d: l=%d, prb=%d, nreg=%d (k0=%d)", k, i, prb, j[i],
h->regs[k].k0);
*/
j[i]++;
k++;
}
i++;
if (i == max_ctrl_symbols) {
i = 0;
jmax++;
}
if (jmax == 3) {
prb++;
bzero(j, sizeof(int) * 4);
jmax = 0;
}
}
if (regs_pcfich_init(h)) {
ERROR("Error initializing PCFICH REGs");
goto clean_and_exit;
}
h->phich_mi = phich_mi;
if (phich_mi > 0) {
if (regs_phich_init(h, phich_mi, mbsfn_or_sf1_6_tdd)) {
ERROR("Error initializing PHICH REGs");
goto clean_and_exit;
}
}
if (regs_pdcch_init(h)) {
ERROR("Error initializing PDCCH REGs");
goto clean_and_exit;
}
ret = SRSRAN_SUCCESS;
}
clean_and_exit:
if (h) {
if (ret != SRSRAN_SUCCESS) {
srsran_regs_free(h);
}
}
return ret;
}
/**
* Puts one REG data (4 symbols) in the slot symbols array
*/
int regs_put_reg(srsran_regs_reg_t* reg, cf_t* reg_data, cf_t* slot_symbols, uint32_t nof_prb)
{
uint32_t i;
for (i = 0; i < REGS_RE_X_REG; i++) {
slot_symbols[REG_IDX(reg, i, nof_prb)] = reg_data[i];
}
return REGS_RE_X_REG;
}
/**
* Adds one REG data (4 symbols) in the slot symbols array
* Used by PHICH
*/
int regs_add_reg(srsran_regs_reg_t* reg, cf_t* reg_data, cf_t* slot_symbols, uint32_t nof_prb)
{
uint32_t i;
for (i = 0; i < REGS_RE_X_REG; i++) {
slot_symbols[REG_IDX(reg, i, nof_prb)] += reg_data[i];
}
return REGS_RE_X_REG;
}
/**
* Reset REG data (4 symbols) in the slot symbols array
*/
int regs_reset_reg(srsran_regs_reg_t* reg, cf_t* slot_symbols, uint32_t nof_prb)
{
uint32_t i;
for (i = 0; i < REGS_RE_X_REG; i++) {
slot_symbols[REG_IDX(reg, i, nof_prb)] = 0;
}
return REGS_RE_X_REG;
}
/**
* Gets one REG data (4 symbols) from the slot symbols array
*/
int regs_get_reg(srsran_regs_reg_t* reg, cf_t* slot_symbols, cf_t* reg_data, uint32_t nof_prb)
{
uint32_t i;
for (i = 0; i < REGS_RE_X_REG; i++) {
reg_data[i] = slot_symbols[REG_IDX(reg, i, nof_prb)];
}
return REGS_RE_X_REG;
}