Added PUCCH to ue itf. Verified with amarisoft

master
ismagom 10 years ago
parent 7ad46244e8
commit f68f28637e

@ -388,7 +388,7 @@ int main(int argc, char **argv) {
dmrs_cfg.cyclic_shift = 0;
dmrs_cfg.cyclic_shift_for_dmrs = 0;
dmrs_cfg.en_dmrs_2 = false;
srslte_ue_ul_set_pusch_cfg(&ue_ul, &dmrs_cfg, &hop_cfg);
srslte_ue_ul_set_cfg(&ue_ul, &dmrs_cfg, &hop_cfg, NULL, NULL);
cf_t *ul_signal = srslte_vec_malloc(sizeof(cf_t) * SRSLTE_SF_LEN_PRB(cell.nof_prb));
if (!ul_signal) {

@ -105,9 +105,9 @@ SRSLTE_API void srslte_refsignal_dmrs_pusch_put(srslte_refsignal_ul_t *q,
SRSLTE_API int srslte_refsignal_dmrs_pucch_gen(srslte_refsignal_ul_t *q,
srslte_pucch_format_t format,
uint8_t pucch2_bits[2],
uint32_t n_pucch, // n_pucch_1 or n_pucch_2 depending on format
uint32_t sf_idx,
uint8_t pucch2_bits[2],
cf_t *r_pucch);
SRSLTE_API int srslte_refsignal_dmrs_pucch_put(srslte_refsignal_ul_t* q,

@ -54,6 +54,16 @@ typedef enum SRSLTE_API {
SRSLTE_PUCCH_FORMAT_2B,
} srslte_pucch_format_t;
typedef struct SRSLTE_API {
uint32_t n_cce;
bool sps_enabled;
uint32_t tpc_for_pucch;
uint32_t N_pucch_1;
uint32_t n_pucch_1[4]; // 4 n_pucch resources specified by RRC
uint32_t n_pucch_2;
uint32_t n_pucch_sr;
}srslte_pucch_sched_t;
typedef struct SRSLTE_API {
float beta_pucch;
uint32_t delta_pucch_shift;

@ -28,7 +28,7 @@
/******************************************************************************
* File: uci.h
*
* Description: Uplink control information.
* Description: Uplink control information. Only 1-bit ACK for UCI on PUSCCH is supported
*
* Reference: 3GPP TS 36.212 version 10.0.0 Release 10 Sec. 5.2.3, 5.2.4
*****************************************************************************/
@ -59,9 +59,12 @@ typedef struct SRSLTE_API {
uint8_t uci_ri; // Only 1-bit supported for RI
uint32_t uci_ri_len;
uint32_t I_offset_ri;
uint8_t uci_ack; // Only 1-bit supported for HARQ
uint8_t uci_ack; // 1st codeword bit for HARQ-ACK
uint8_t uci_ack_2; // 2st codeword bit for HARQ-ACK
uint32_t uci_ack_len;
uint32_t I_offset_ack;
bool scheduling_request;
bool channel_selection;
} srslte_uci_data_t;
SRSLTE_API int srslte_uci_cqi_init(srslte_uci_cqi_pusch_t *q);

@ -84,6 +84,7 @@ typedef struct SRSLTE_API {
uint64_t nof_detected;
uint16_t current_rnti;
uint32_t last_n_cce;
}srslte_ue_dl_t;
/* This function shall be called just after the initial synchronization */
@ -117,6 +118,8 @@ SRSLTE_API int srslte_ue_dl_find_dl_dci(srslte_ue_dl_t *q,
uint32_t sf_idx,
uint16_t rnti);
SRSLTE_API uint32_t srslte_ue_dl_get_ncce(srslte_ue_dl_t *q);
SRSLTE_API int srslte_ue_dl_decode(srslte_ue_dl_t * q,
cf_t *input,
uint8_t *data,

@ -66,6 +66,9 @@ typedef struct SRSLTE_API {
srslte_refsignal_ul_t dmrs;
srslte_harq_t harq_process[SRSLTE_UE_UL_NOF_HARQ_PROCESSES];
srslte_pusch_t pusch;
srslte_pucch_t pucch;
srslte_pucch_sched_t pucch_sched;
cf_t *refsignal;
cf_t *sf_symbols;
@ -88,9 +91,16 @@ SRSLTE_API void srslte_ue_ul_set_cfo_enable(srslte_ue_ul_t *q,
SRSLTE_API void srslte_ue_ul_set_normalization(srslte_ue_ul_t *q,
bool enabled);
SRSLTE_API void srslte_ue_ul_set_pusch_cfg(srslte_ue_ul_t *q,
srslte_refsignal_dmrs_pusch_cfg_t *dmrs_cfg,
srslte_pusch_hopping_cfg_t *pusch_hopping_cfg);
SRSLTE_API void srslte_ue_ul_set_cfg(srslte_ue_ul_t *q,
srslte_refsignal_dmrs_pusch_cfg_t *dmrs_cfg,
srslte_pusch_hopping_cfg_t *pusch_hopping_cfg,
srslte_pucch_cfg_t *pucch_cfg,
srslte_pucch_sched_t *pucch_sched);
SRSLTE_API int srslte_ue_ul_pucch_encode(srslte_ue_ul_t *q,
srslte_uci_data_t uci_data,
uint32_t sf_idx,
cf_t *output_signal);
SRSLTE_API int srslte_ue_ul_pusch_encode(srslte_ue_ul_t *q,
srslte_ra_pusch_t *ra_ul,

@ -66,8 +66,8 @@ namespace ue {
bool recv_ue_sync(srslte_ue_sync_t *ue_sync, srslte_timestamp_t *rx_time);
bool get_ul_grant(pdcch_ul_search_t mode, sched_grant *grant);
bool get_dl_grant(pdcch_dl_search_t mode, sched_grant *grant);
bool decode_phich(srslte::ue::sched_grant pusch_grant);
bool decode_pdsch(sched_grant pdsch_grant, uint8_t *payload); // returns true or false for CRC OK/KO
bool decode_ack(srslte::ue::sched_grant pusch_grant);
bool decode_data(sched_grant pdsch_grant, uint8_t *payload); // returns true or false for CRC OK/KO
private:
params *params_db;
srslte_cell_t cell;

@ -45,7 +45,6 @@ namespace ue {
CELLSEARCH_TIMEOUT_PSS_CORRELATION_THRESHOLD, // integer that will be divided by 10
PUSCH_BETA,
PUSCH_RS_GROUP_HOPPING_EN,
PUSCH_RS_SEQUENCE_HOPPING_EN,
PUSCH_RS_CYCLIC_SHIFT,
@ -55,6 +54,18 @@ namespace ue {
PUSCH_HOPPING_INTRA_SF,
PUSCH_HOPPING_OFFSET,
PUCCH_BETA,
PUCCH_DELTA_SHIFT,
PUCCH_CYCLIC_SHIFT,
PUCCH_N_RB_2,
PUCCH_N_PUCCH_1_0,
PUCCH_N_PUCCH_1_1,
PUCCH_N_PUCCH_1_2,
PUCCH_N_PUCCH_1_3,
PUCCH_N_PUCCH_1,
PUCCH_N_PUCCH_2,
PUCCH_N_PUCCH_SR,
UCI_I_OFFSET_ACK,
UCI_I_OFFSET_RI,
UCI_I_OFFSET_CQI,

@ -49,6 +49,8 @@ namespace ue {
bool is_uplink();
bool is_downlink();
void* get_grant_ptr();
void set_ncce(uint32_t ncce);
uint32_t get_ncce();
uint32_t get_tbs();
uint32_t get_current_tx_nb();
void set_current_tx_nb(uint32_t current_tx_nb);
@ -60,6 +62,7 @@ namespace ue {
uint32_t current_tx_nb;
direction_t dir;
uint16_t rnti;
uint32_t ncce;
};
}

@ -39,7 +39,7 @@ namespace srslte {
namespace ue {
/* Uplink scheduling assignment. The MAC instructs the PHY to prepare an UL packet (PUSCH or PUCCH)
* for transmission. The MAC must call generate_pusch() to set the packet ready for transmission
* for transmission. The MAC must call generate_data() to set the packet ready for transmission
*/
class SRSLTE_API ul_buffer : public queue::element {
@ -48,9 +48,13 @@ namespace ue {
void free_cell();
void set_tti(uint32_t tti);
void set_current_tx_nb(uint32_t current_tx_nb);
bool generate_pusch(sched_grant pusch_grant, uint8_t *payload);
bool generate_pusch(sched_grant pusch_grant, uint8_t *payload, srslte_uci_data_t uci_data);
bool generate_pucch(srslte_uci_data_t uci_data);
bool generate_ack(bool ack, sched_grant last_dl_grant);
bool generate_ack(bool ack[2]);
bool generate_sr();
bool generate_cqi_report();
bool uci_ready();
bool generate_data();
bool generate_data(sched_grant pusch_grant, uint8_t *payload);
bool send(radio* radio_handler, float time_adv_sec, float cfo, srslte_timestamp_t rx_time);
static const uint32_t tx_advance_sf = 1; // Number of subframes to advance transmission
@ -61,6 +65,9 @@ namespace ue {
bool cell_initiated;
cf_t* signal_buffer;
uint32_t current_tx_nb;
uint32_t last_n_cce;
srslte_uci_data_t uci_data;
bool uci_pending;
};
}

@ -172,7 +172,9 @@ void srslte_refsignal_ul_free(srslte_refsignal_ul_t * q) {
void srslte_refsignal_ul_set_pusch_cfg(srslte_refsignal_ul_t *q, srslte_refsignal_dmrs_pusch_cfg_t *cfg)
{
memcpy(&q->pusch_cfg, cfg, sizeof(srslte_refsignal_dmrs_pusch_cfg_t));
if (cfg) {
memcpy(&q->pusch_cfg, cfg, sizeof(srslte_refsignal_dmrs_pusch_cfg_t));
}
}
bool srslte_refsignal_ul_set_pucch_cfg(srslte_refsignal_ul_t *q, srslte_pucch_cfg_t *cfg)
@ -375,7 +377,8 @@ static uint32_t get_pucch_dmrs_symbol(uint32_t m, srslte_pucch_format_t format,
}
/* Generates DMRS for PUCCH according to 5.5.2.2 in 36.211 */
int srslte_refsignal_dmrs_pucch_gen(srslte_refsignal_ul_t *q, srslte_pucch_format_t format, uint8_t pucch_bits[2], uint32_t n_pucch, uint32_t sf_idx, cf_t *r_pucch)
int srslte_refsignal_dmrs_pucch_gen(srslte_refsignal_ul_t *q, srslte_pucch_format_t format, uint32_t n_pucch,
uint32_t sf_idx, uint8_t pucch_bits[2], cf_t *r_pucch)
{
int ret = SRSLTE_ERROR_INVALID_INPUTS;
if (q && r_pucch) {

@ -289,7 +289,6 @@ static int pucch_put(srslte_pucch_t *q, srslte_pucch_format_t format, uint32_t n
return SRSLTE_ERROR;
}
}
ret = SRSLTE_SUCCESS;
}
return ret;
@ -350,9 +349,13 @@ int srslte_pucch_set_crnti(srslte_pucch_t *q, uint16_t c_rnti) {
bool srslte_pucch_set_cfg(srslte_pucch_t *q, srslte_pucch_cfg_t *cfg)
{
if (srslte_pucch_cfg_isvalid(cfg, q->cell.nof_prb)) {
memcpy(&q->pucch_cfg, cfg, sizeof(srslte_pucch_cfg_t));
return true;
if (cfg) {
if (srslte_pucch_cfg_isvalid(cfg, q->cell.nof_prb)) {
memcpy(&q->pucch_cfg, cfg, sizeof(srslte_pucch_cfg_t));
return true;
} else {
return false;
}
} else {
return false;
}

@ -282,7 +282,9 @@ void srslte_pusch_free(srslte_pusch_t *q) {
void srslte_pusch_set_hopping_cfg(srslte_pusch_t *q, srslte_pusch_hopping_cfg_t *cfg)
{
memcpy(&q->hopping_cfg, cfg, sizeof(srslte_pusch_hopping_cfg_t));
if (cfg) {
memcpy(&q->hopping_cfg, cfg, sizeof(srslte_pusch_hopping_cfg_t));
}
}
/* Precalculate the PUSCH scramble sequences for a given RNTI. This function takes a while

@ -191,7 +191,7 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
return;
}
if (srslte_refsignal_dmrs_pucch_gen(&pucch_dmrs, format, pucch2_bits, n_pucch, sf_idx, dmrs_pucch)) {
if (srslte_refsignal_dmrs_pucch_gen(&pucch_dmrs, format, n_pucch, sf_idx, pucch2_bits, dmrs_pucch)) {
mexErrMsgTxt("Error generating PUCCH DMRS\n");
return;
}

@ -259,6 +259,10 @@ int srslte_ue_dl_find_ul_dci(srslte_ue_dl_t *q, srslte_dci_msg_t *dci_msg, uint3
return crc_rem == rnti;
}
uint32_t srslte_ue_dl_get_ncce(srslte_ue_dl_t *q) {
return q->last_n_cce;
}
int srslte_ue_dl_find_dl_dci(srslte_ue_dl_t *q, srslte_dci_msg_t *dci_msg, uint32_t cfi, uint32_t sf_idx, uint16_t rnti)
{
srslte_dci_location_t locations[MAX_CANDIDATES];
@ -281,6 +285,7 @@ int srslte_ue_dl_find_dl_dci(srslte_ue_dl_t *q, srslte_dci_msg_t *dci_msg, uint3
for (int f=0;f<nof_formats && crc_rem != rnti;f++) {
INFO("Trying format %s\n", srslte_dci_format_string(formats[f]));
for (int i=0;i<nof_locations && crc_rem != rnti;i++) {
q->last_n_cce = locations[i].ncce;
if (srslte_pdcch_decode_msg(&q->pdcch, dci_msg, &locations[i], formats[f], &crc_rem)) {
fprintf(stderr, "Error decoding DCI msg\n");
return SRSLTE_ERROR;

@ -70,6 +70,10 @@ int srslte_ue_ul_init(srslte_ue_ul_t *q,
fprintf(stderr, "Error creating PUSCH object\n");
goto clean_exit;
}
if (srslte_pucch_init(&q->pucch, q->cell)) {
fprintf(stderr, "Error creating PUSCH object\n");
goto clean_exit;
}
for (uint32_t i=0;i<SRSLTE_UE_UL_NOF_HARQ_PROCESSES; i++) {
if (srslte_harq_init(&q->harq_process[i], q->cell)) {
fprintf(stderr, "Error initiating HARQ process\n");
@ -108,6 +112,7 @@ void srslte_ue_ul_free(srslte_ue_ul_t *q) {
if (q) {
srslte_ofdm_rx_free(&q->fft);
srslte_pusch_free(&q->pusch);
srslte_pucch_free(&q->pucch);
for (uint32_t i=0;i<SRSLTE_UE_UL_NOF_HARQ_PROCESSES; i++) {
srslte_harq_free(&q->harq_process[i]);
}
@ -145,16 +150,142 @@ void srslte_ue_ul_set_normalization(srslte_ue_ul_t *q, bool enabled)
void srslte_ue_ul_set_rnti(srslte_ue_ul_t *q, uint16_t rnti) {
q->current_rnti = rnti;
srslte_pusch_set_rnti(&q->pusch, rnti);
srslte_pucch_set_crnti(&q->pucch, rnti);
}
void srslte_ue_ul_reset(srslte_ue_ul_t *q) {
srslte_harq_reset(&q->harq_process[0]);
}
void srslte_ue_ul_set_pusch_cfg(srslte_ue_ul_t *q, srslte_refsignal_dmrs_pusch_cfg_t *dmrs_cfg, srslte_pusch_hopping_cfg_t *pusch_hopping_cfg)
void srslte_ue_ul_set_cfg(srslte_ue_ul_t *q,
srslte_refsignal_dmrs_pusch_cfg_t *dmrs_cfg,
srslte_pusch_hopping_cfg_t *pusch_hopping_cfg,
srslte_pucch_cfg_t *pucch_cfg,
srslte_pucch_sched_t *pucch_sched)
{
srslte_refsignal_ul_set_pusch_cfg(&q->dmrs, dmrs_cfg);
srslte_pusch_set_hopping_cfg(&q->pusch, pusch_hopping_cfg);
srslte_pucch_set_cfg(&q->pucch, pucch_cfg);
if (pucch_sched) {
memcpy(&q->pucch_sched, pucch_sched, sizeof(srslte_pucch_sched_t));
}
}
/* Choose PUCCH format as in Sec 10.1 of 36.213 and generate PUCCH signal
*/
int srslte_ue_ul_pucch_encode(srslte_ue_ul_t *q, srslte_uci_data_t uci_data,
uint32_t sf_idx,
cf_t *output_signal)
{
int ret = SRSLTE_ERROR_INVALID_INPUTS;
if (q != NULL &&
output_signal != NULL)
{
ret = SRSLTE_ERROR;
bzero(q->sf_symbols, sizeof(cf_t)*SRSLTE_SF_LEN_RE(q->cell.nof_prb, q->cell.cp));
srslte_pucch_format_t format;
uint8_t pucch_bits[SRSLTE_PUCCH_MAX_BITS];
uint8_t pucch2_bits[2];
bzero(pucch_bits, SRSLTE_PUCCH_MAX_BITS*sizeof(uint8_t));
bzero(pucch2_bits, 2*sizeof(uint8_t));
// 1-bit ACK + SR
if (uci_data.uci_ack_len == 1) {
format = SRSLTE_PUCCH_FORMAT_1A;
pucch_bits[0] = uci_data.uci_ack;
}
// 2-bit ACK + SR
else if (uci_data.uci_ack_len == 2 && uci_data.scheduling_request) {
format = SRSLTE_PUCCH_FORMAT_1B;
pucch_bits[0] = uci_data.uci_ack;
pucch_bits[1] = uci_data.uci_ack_2;
}
// 2-bit ACK with channel selection
else if (uci_data.uci_ack_len == 2 && uci_data.channel_selection) {
format = SRSLTE_PUCCH_FORMAT_1B;
pucch_bits[0] = uci_data.uci_ack;
pucch_bits[1] = uci_data.uci_ack_2;
}
// scheduling_request
else if (uci_data.scheduling_request) {
format = SRSLTE_PUCCH_FORMAT_1;
}
// CQI and no ack
else if (uci_data.uci_cqi_len == SRSLTE_PUCCH_MAX_BITS && uci_data.uci_ack_len == 0) {
format = SRSLTE_PUCCH_FORMAT_2;
memcpy(pucch_bits, uci_data.uci_cqi, SRSLTE_PUCCH_MAX_BITS*sizeof(uint8_t));
}
// CQI + 1-bit ACK
else if (uci_data.uci_cqi_len == SRSLTE_PUCCH_MAX_BITS && uci_data.uci_ack_len == 1) {
format = SRSLTE_PUCCH_FORMAT_2A;
memcpy(pucch_bits, uci_data.uci_cqi, SRSLTE_PUCCH_MAX_BITS*sizeof(uint8_t));
pucch2_bits[0] = uci_data.uci_ack;
}
// CQI + 2-bit ACK
else if (uci_data.uci_cqi_len == 20 && uci_data.uci_ack_len == 2) {
format = SRSLTE_PUCCH_FORMAT_2B;
memcpy(pucch_bits, uci_data.uci_cqi, SRSLTE_PUCCH_MAX_BITS*sizeof(uint8_t));
pucch2_bits[0] = uci_data.uci_ack;
pucch2_bits[1] = uci_data.uci_ack_2;
}
// CQI + 2-bit ACK + cyclic prefix
else if (uci_data.uci_cqi_len == 20 && uci_data.uci_ack_len == 1 && SRSLTE_CP_ISEXT(q->cell.cp)) {
format = SRSLTE_PUCCH_FORMAT_2B;
memcpy(pucch_bits, uci_data.uci_cqi, SRSLTE_PUCCH_MAX_BITS*sizeof(uint8_t));
pucch2_bits[0] = uci_data.uci_ack;
pucch2_bits[1] = uci_data.uci_ack_2;
} else {
fprintf(stderr, "Unsupported combination of UCI parameters\n");
return SRSLTE_ERROR;
}
// Choose n_pucch
uint32_t n_pucch = 0;
if (format == SRSLTE_PUCCH_FORMAT_1) {
n_pucch = q->pucch_sched.n_pucch_sr;
} else if (format < SRSLTE_PUCCH_FORMAT_2) {
if (q->pucch_sched.sps_enabled) {
n_pucch = q->pucch_sched.n_pucch_1[q->pucch_sched.tpc_for_pucch%4];
} else {
n_pucch = q->pucch_sched.n_cce + q->pucch_sched.N_pucch_1;
}
} else {
n_pucch = q->pucch_sched.n_pucch_2;
}
if (srslte_pucch_encode(&q->pucch, format, n_pucch, sf_idx, pucch_bits, q->sf_symbols)) {
fprintf(stderr, "Error encoding TB\n");
return ret;
}
if (srslte_refsignal_dmrs_pucch_gen(&q->dmrs, format, n_pucch, sf_idx, pucch2_bits, q->refsignal))
{
fprintf(stderr, "Error generating PUSCH DRMS signals\n");
return ret;
}
srslte_refsignal_dmrs_pucch_put(&q->dmrs, format, n_pucch, q->refsignal, q->sf_symbols);
srslte_ofdm_tx_sf(&q->fft, q->sf_symbols, output_signal);
if (q->cfo_en) {
srslte_cfo_correct(&q->cfo, output_signal, output_signal, q->current_cfo / srslte_symbol_sz(q->cell.nof_prb));
}
if (q->normalize_en) {
uint32_t n_prb = 1;
if (q->harq_process[0].ul_alloc.L_prb > 0) {
n_prb = q->harq_process[0].ul_alloc.L_prb;
}
float norm_factor = (float) q->cell.nof_prb/10/sqrtf(n_prb);
srslte_vec_sc_prod_cfc(output_signal, norm_factor, output_signal, SRSLTE_SF_LEN_PRB(q->cell.nof_prb));
}
srslte_vec_save_file("pucch", output_signal, sizeof(cf_t)*SRSLTE_SF_LEN_PRB(q->cell.nof_prb));
ret = SRSLTE_SUCCESS;
}
return ret;
}
int srslte_ue_ul_pusch_encode(srslte_ue_ul_t *q, srslte_ra_pusch_t *ra_ul, uint8_t *data, uint32_t sf_idx, cf_t *output_signal)

@ -145,6 +145,8 @@ bool dl_buffer::get_dl_grant(pdcch_dl_search_t mode, sched_grant *grant)
return false;
}
grant->set_ncce(srslte_ue_dl_get_ncce(&ue_dl));
if (srslte_dci_msg_to_ra_dl(&dci_msg, grant->get_rnti(), cell, cfi,
(srslte_ra_pdsch_t*) grant->get_grant_ptr())) {
return false;
@ -154,7 +156,7 @@ bool dl_buffer::get_dl_grant(pdcch_dl_search_t mode, sched_grant *grant)
}
}
bool dl_buffer::decode_phich(sched_grant pusch_grant)
bool dl_buffer::decode_ack(sched_grant pusch_grant)
{
if (signal_buffer && is_ready()) {
if (!sf_symbols_and_ce_done) {
@ -170,7 +172,7 @@ bool dl_buffer::decode_phich(sched_grant pusch_grant)
}
}
bool dl_buffer::decode_pdsch(sched_grant pdsch_grant, uint8_t *payload)
bool dl_buffer::decode_data(sched_grant pdsch_grant, uint8_t *payload)
{
if (signal_buffer && is_ready()) {
INFO("DL Buffer TTI %d: Decoding PDSCH\n", tti);

@ -398,9 +398,13 @@ void phy::run_rx_tx_state()
prach_buffer.send(radio_handler, cfo, last_rx_time);
}
// send ul buffer if we have to
if (get_ul_buffer_adv(current_tti)->is_released()) {
if (get_ul_buffer_adv(current_tti)->is_released() || get_ul_buffer_adv(current_tti)->uci_ready()) {
// Generate PUCCH if no UL grant
if (!get_ul_buffer_adv(current_tti)->is_released()) {
get_ul_buffer_adv(current_tti)->generate_data();
}
get_ul_buffer_adv(current_tti)->send(radio_handler, time_adv_sec, cfo, last_rx_time);
}
}
// Receive alligned buffer for the current tti
get_dl_buffer(current_tti)->recv_ue_sync(&ue_sync, &last_rx_time);

@ -140,7 +140,7 @@ bool prach::send(radio *radio_handler, float cfo, srslte_timestamp_t rx_time)
srslte_timestamp_add(&tx_time, 0, 1e-3*tx_advance_sf);
// Correct CFO before transmission
srslte_cfo_correct(&cfo_h, buffer[preamble_idx], signal_buffer, 1.7*cfo / srslte_symbol_sz(cell.nof_prb));
srslte_cfo_correct(&cfo_h, buffer[preamble_idx], signal_buffer, 2*cfo / srslte_symbol_sz(cell.nof_prb));
// transmit
radio_handler->tx(signal_buffer, len, tx_time);

@ -62,6 +62,16 @@ namespace ue {
}
}
uint32_t sched_grant::get_ncce()
{
return ncce;
}
void sched_grant::set_ncce(uint32_t ncce_)
{
ncce = ncce_;
}
uint32_t sched_grant::get_current_tx_nb()
{
return current_tx_nb;

@ -46,6 +46,8 @@ bool ul_buffer::init_cell(srslte_cell_t cell_, params *params_db_) {
signal_buffer = (cf_t*) srslte_vec_malloc(sizeof(cf_t) * SRSLTE_SF_LEN_PRB(cell.nof_prb));
cell_initiated = signal_buffer?true:false;
srslte_ue_ul_set_cfo_enable(&ue_ul, false);
bzero(&uci_data, sizeof(srslte_uci_data_t));
uci_pending = false;
return cell_initiated;
} else {
return false;
@ -61,27 +63,45 @@ void ul_buffer::free_cell() {
}
}
bool ul_buffer::generate_pusch(sched_grant pusch_grant,
uint8_t *payload)
bool ul_buffer::generate_ack(bool ack, sched_grant last_dl_grant)
{
srslte_uci_data_t uci_data;
bzero(&uci_data, sizeof(srslte_uci_data_t));
return generate_pusch(pusch_grant, payload, uci_data);
uci_data.uci_ack_len = 1;
uci_data.uci_ack = ack?1:0;
uci_pending = true;
last_n_cce = last_dl_grant.get_ncce();
}
bool ul_buffer::generate_pusch(sched_grant pusch_grant,
uint8_t *payload,
srslte_uci_data_t uci_data)
bool ul_buffer::generate_ack(bool ack[2])
{
uci_data.uci_ack_len = 2;
uci_data.uci_ack = ack[0]?1:0;
uci_data.uci_ack_2 = ack[1]?1:0;
uci_pending = true;
}
bool ul_buffer::generate_sr() {
uci_data.scheduling_request = true;
uci_pending = true;
}
bool ul_buffer::uci_ready() {
return uci_pending;
}
bool ul_buffer::generate_data() {
sched_grant dummy(sched_grant::DOWNLINK, 0);
return generate_data(dummy, NULL);
}
bool ul_buffer::generate_data(sched_grant pusch_grant,
uint8_t *payload)
{
if (is_ready()) {
if (!pusch_grant.is_uplink()) {
fprintf(stderr, "Error in UL buffer: Invalid scheduling grant. Grant is for Downlink\n");
return false;
}
srslte_refsignal_dmrs_pusch_cfg_t dmrs_cfg;
bzero(&dmrs_cfg, sizeof(srslte_refsignal_dmrs_pusch_cfg_t));
bzero(signal_buffer, sizeof(cf_t)*SRSLTE_SF_LEN_PRB(cell.nof_prb));
srslte_refsignal_dmrs_pusch_cfg_t dmrs_cfg;
bzero(&dmrs_cfg, sizeof(srslte_refsignal_dmrs_pusch_cfg_t));
dmrs_cfg.beta_pusch = (float) params_db->get_param(params::PUSCH_BETA)/10;
dmrs_cfg.group_hopping_en = params_db->get_param(params::PUSCH_RS_GROUP_HOPPING_EN);
dmrs_cfg.sequence_hopping_en = params_db->get_param(params::PUSCH_RS_SEQUENCE_HOPPING_EN);
@ -89,6 +109,7 @@ bool ul_buffer::generate_pusch(sched_grant pusch_grant,
dmrs_cfg.delta_ss = params_db->get_param(params::PUSCH_RS_GROUP_ASSIGNMENT);
srslte_pusch_hopping_cfg_t pusch_hopping;
bzero(&pusch_hopping, sizeof(srslte_pusch_hopping_cfg_t));
pusch_hopping.n_sb = params_db->get_param(params::PUSCH_HOPPING_N_SB);
pusch_hopping.hop_mode = params_db->get_param(params::PUSCH_HOPPING_INTRA_SF) ?
pusch_hopping.SRSLTE_PUSCH_HOP_MODE_INTRA_SF :
@ -96,30 +117,57 @@ bool ul_buffer::generate_pusch(sched_grant pusch_grant,
pusch_hopping.hopping_offset = params_db->get_param(params::PUSCH_HOPPING_OFFSET);
pusch_hopping.current_tx_nb = pusch_grant.get_current_tx_nb();
srslte_ue_ul_set_pusch_cfg(&ue_ul, &dmrs_cfg, &pusch_hopping);
srslte_pucch_cfg_t pucch_cfg;
bzero(&pucch_cfg, sizeof(srslte_pucch_cfg_t));
pucch_cfg.beta_pucch = (float) params_db->get_param(params::PUCCH_BETA)/10;
pucch_cfg.delta_pucch_shift = params_db->get_param(params::PUCCH_DELTA_SHIFT);
pucch_cfg.group_hopping_en = dmrs_cfg.group_hopping_en;
pucch_cfg.N_cs = params_db->get_param(params::PUCCH_CYCLIC_SHIFT);
pucch_cfg.n_rb_2 = params_db->get_param(params::PUCCH_N_RB_2);
srslte_pucch_sched_t pucch_sched;
bzero(&pucch_sched, sizeof(srslte_pucch_sched_t));
pucch_sched.n_cce = last_n_cce;
pucch_sched.n_pucch_1[0] = params_db->get_param(params::PUCCH_N_PUCCH_1_0);
pucch_sched.n_pucch_1[1] = params_db->get_param(params::PUCCH_N_PUCCH_1_1);
pucch_sched.n_pucch_1[2] = params_db->get_param(params::PUCCH_N_PUCCH_1_2);
pucch_sched.n_pucch_1[3] = params_db->get_param(params::PUCCH_N_PUCCH_1_3);
pucch_sched.N_pucch_1 = params_db->get_param(params::PUCCH_N_PUCCH_1);
pucch_sched.n_pucch_2 = params_db->get_param(params::PUCCH_N_PUCCH_2);
pucch_sched.n_pucch_sr = params_db->get_param(params::PUCCH_N_PUCCH_SR);
srslte_ue_ul_set_cfg(&ue_ul, &dmrs_cfg, &pusch_hopping, &pucch_cfg, &pucch_sched);
int n = srslte_ue_ul_pusch_uci_encode_rnti(&ue_ul, (srslte_ra_pusch_t*) pusch_grant.get_grant_ptr(),
payload, uci_data,
tti%10, pusch_grant.get_rnti(),
signal_buffer);
uci_data.I_offset_ack = params_db->get_param(params::UCI_I_OFFSET_ACK);
uci_data.I_offset_cqi = params_db->get_param(params::UCI_I_OFFSET_CQI);
uci_data.I_offset_ri = params_db->get_param(params::UCI_I_OFFSET_RI);
int n = 0;
// Transmit on PUSCH if UL grant available, otherwise in PUCCH
if (payload) {
n = srslte_ue_ul_pusch_uci_encode_rnti(&ue_ul, (srslte_ra_pusch_t*) pusch_grant.get_grant_ptr(),
payload, uci_data,
tti%10, pusch_grant.get_rnti(),
signal_buffer);
} else {
n = srslte_ue_ul_pucch_encode(&ue_ul, uci_data, tti&10, signal_buffer);
}
// Reset UCI data
bzero(&uci_data, sizeof(srslte_uci_data_t));
uci_pending = false;
release();
if (n < 0) {
fprintf(stderr, "Error in UL buffer: Error encoding PUSCH\n");
fprintf(stderr, "Error in UL buffer: Error encoding %s\n", signal_buffer?"PUSCH":"PUCCH");
return false;
} else {
return true;
}
release();
return true;
} else {
fprintf(stderr, "Error in UL buffer: buffer not released\n");
return false;
}
}
bool ul_buffer::generate_pucch(srslte_uci_data_t uci_data)
{
fprintf(stderr, "Not implemented\n");
return false;
}
bool ul_buffer::send(srslte::radio* radio_handler, float time_adv_sec, float cfo, srslte_timestamp_t rx_time)
{
// send packet through usrp
@ -136,8 +184,6 @@ bool ul_buffer::send(srslte::radio* radio_handler, float time_adv_sec, float cfo
radio_handler->tx(signal_buffer, SRSLTE_SF_LEN_PRB(cell.nof_prb), tx_time);
//srslte_vec_save_file("pusch", signal_buffer, SRSLTE_SF_LEN_PRB(cell.nof_prb)*sizeof(cf_t));
ready();
}

@ -193,7 +193,7 @@ srslte::ue::phy phy;
uint8_t payload[102400];
const uint8_t conn_request_msg[] = {0x20, 0x06, 0x1F, 0x5C, 0x2C, 0x04, 0xB2, 0xAC, 0xF6, 0x00, 0x00, 0x00};
enum mac_state {RA, RAR, CONNSETUP} state = RA;
enum mac_state {RA, RAR, CONNREQUEST, CONNSETUP} state = RA;
uint32_t conreq_tti = 0;
uint32_t preamble_idx = 7;
@ -215,7 +215,13 @@ void config_phy() {
phy.set_param(srslte::ue::params::PUSCH_RS_SEQUENCE_HOPPING_EN, 0);
phy.set_param(srslte::ue::params::PUSCH_RS_CYCLIC_SHIFT, 0);
phy.set_param(srslte::ue::params::PUSCH_HOPPING_OFFSET, 0);
phy.set_param(srslte::ue::params::PUCCH_BETA, 10);
phy.set_param(srslte::ue::params::PUCCH_DELTA_SHIFT, 1);
phy.set_param(srslte::ue::params::PUCCH_CYCLIC_SHIFT, 0);
phy.set_param(srslte::ue::params::PUCCH_N_PUCCH_1, 0);
phy.set_param(srslte::ue::params::PUCCH_N_RB_2, 2);
}
uint32_t interval(uint32_t x1, uint32_t x2) {
@ -245,7 +251,8 @@ void run_tti(uint32_t tti) {
fprintf(stderr, "Error sending PRACH\n");
exit(-1);
}
} else if (state == RAR) {
}
if (state == RAR) {
srslte::ue::sched_grant rar_grant(srslte::ue::sched_grant::DOWNLINK, 2);
int ra_tti = phy.get_prach_transmitted_tti();
if (ra_tti > 0) {
@ -258,11 +265,11 @@ void run_tti(uint32_t tti) {
if (dl_buffer->get_dl_grant(srslte::ue::dl_buffer::PDCCH_DL_SEARCH_RARNTI, &rar_grant))
{
// Decode packet
if (dl_buffer->decode_pdsch(rar_grant, payload)) {
INFO("RAR received tti: %d\n", tti);
if (dl_buffer->decode_data(rar_grant, payload)) {
rar_unpack(payload, &rar_msg);
INFO("Received RAR for preamble %d\n", rar_msg.RAPID);
if (!prog_args.continous) {
printf("Received RAR for preamble %d\n", rar_msg.RAPID);
}
if (rar_msg.RAPID == preamble_idx) {
INFO("Received RAR at TTI: %d\n", tti);
@ -293,7 +300,7 @@ void run_tti(uint32_t tti) {
// Save transmission time
conreq_tti = ul_buffer->tti;
state = CONNSETUP;
state = CONNREQUEST;
} else {
fprintf(stderr, "Error getting UL buffer for TTI %d\n", tti);
state = RA;
@ -306,9 +313,8 @@ void run_tti(uint32_t tti) {
state = RA;
}
}
} else {
srslte::ue::sched_grant conn_setup_grant(srslte::ue::sched_grant::DOWNLINK, rar_msg.temp_c_rnti);
}
if (state == CONNREQUEST) {
uint32_t interval_conreq = interval(tti, conreq_tti);
if (interval_conreq == 4) {
@ -316,7 +322,7 @@ void run_tti(uint32_t tti) {
phy.rar_ul_grant(rar_msg.rba, rar_msg.mcs, rar_msg.hopping_flag, &connreq_grant);
// Decode PHICH from Connection Request
if (!dl_buffer->decode_phich(connreq_grant)) {
if (!dl_buffer->decode_ack(connreq_grant)) {
// Pack Msg3 bits
srslte_bit_pack_vector((uint8_t*) conn_request_msg, payload, connreq_grant.get_tbs());
@ -333,40 +339,55 @@ void run_tti(uint32_t tti) {
connreq_grant.set_current_tx_nb(nof_rtx_connsetup);
connreq_grant.set_rv(rv_value[nof_rtx_connsetup%4]);
INFO("Generating PUSCH for TTI: %d\n", ul_buffer->tti);
ul_buffer->generate_pusch(connreq_grant, payload);
ul_buffer->generate_data(connreq_grant, payload);
// Save transmission time
conreq_tti = ul_buffer->tti;
state = CONNSETUP;
}
} else {
fprintf(stderr, "Error getting UL buffer for TTI %d\n", tti);
state = RA;
}
} else {
// Get DL grant for tmp_rnti
if (dl_buffer->get_dl_grant(srslte::ue::dl_buffer::PDCCH_DL_SEARCH_TEMPORAL, &conn_setup_grant))
{
// Decode packet
if (dl_buffer->decode_pdsch(conn_setup_grant, payload)) {
nof_rx_connsetup++;
state = RA;
nof_rtx_connsetup=0;
if (!prog_args.continous) {
printf("Connection Setup received (%d/%d)\n", nof_rx_connsetup, nof_tx_ra);
}
} else {
INFO("Error decoding PDSCH for Connection Request at TTI=%d\n", tti);
state = RA;
}
} else {
INFO("DCI for Connection Request not found on PDCCH at TTI=%d\n", tti);
state = RA;
}
state = CONNSETUP;
}
}
}
if (state == CONNSETUP) {
srslte::ue::sched_grant conn_setup_grant(srslte::ue::sched_grant::DOWNLINK, rar_msg.temp_c_rnti);
bool connsetup_recv = false;
// Get DL grant for tmp_rnti
if (dl_buffer->get_dl_grant(srslte::ue::dl_buffer::PDCCH_DL_SEARCH_TEMPORAL, &conn_setup_grant))
{
// Decode packet
if (dl_buffer->decode_data(conn_setup_grant, payload)) {
nof_rx_connsetup++;
state = RA;
nof_rtx_connsetup=0;
if (!prog_args.continous) {
printf("Connection Setup received (%d/%d)\n", nof_rx_connsetup, nof_tx_ra);
}
connsetup_recv = true;
} else {
INFO("Error decoding PDSCH for Connection Request at TTI=%d\n", tti);
}
// send ACK
INFO("Sending ack %d on TTI: %d\n", connsetup_recv, tti+4);
srslte::ue::ul_buffer *ul_buffer = phy.get_ul_buffer(tti+4);
ul_buffer->generate_ack(connsetup_recv, conn_setup_grant);
if (!prog_args.continous) {
while(ul_buffer->uci_ready()) {
sleep(1);
}
}
state = RA;
} else {
INFO("DCI for Connection Request not found on PDCCH at TTI=%d\n", tti);
state = RA;
}
}
if (srslte_verbose == SRSLTE_VERBOSE_NONE && prog_args.continous) {
printf("RECV RAR %2.1f \%% RECV ConnSetup %2.1f \%% (%5u/%5u) \r",
(float) 100*nof_rx_rar/nof_tx_ra,
@ -421,6 +442,9 @@ int main(int argc, char *argv[])
printf("Could not start RX\n");
exit(-1);
}
for (int i=0;i<100;i++) {
ttisync.wait();
}
/* go to idle and process each tti */
while(1) {
uint32_t tti = ttisync.wait();

@ -108,7 +108,7 @@ void run_tti(uint32_t tti) {
grant.set_rv(((uint32_t) ceilf((float)3*((phy.tti_to_SFN(tti)/2)%4)/2))%4);
// Decode packet
if (!buffer->decode_pdsch(grant, payload)) {
if (!buffer->decode_data(grant, payload)) {
total_errors++;
}
}

Loading…
Cancel
Save