Initial commit

master
ismagom 10 years ago
parent e7fc0f839c
commit 805ccc2414

@ -1,72 +0,0 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2015 The srsLTE Developers. See the
* COPYRIGHT file at the top-level directory of this distribution.
*
* \section LICENSE
*
* This file is part of the srsLTE library.
*
* srsLTE 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.
*
* srsLTE 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 <pthread.h>
#ifndef BINSEM_H
#define BINSEM_H
/** Implementation of a binary semaphore using POSIX condition variable and mutex
*/
namespace srslte {
class binsem
{
public:
binsem() {
pthread_mutex_init(&mutex, NULL);
pthread_cond_init(&cv, NULL);
state = true;
}
~binsem() {
pthread_mutex_destroy(&mutex);
pthread_cond_destroy(&cv);
}
void take() {
pthread_mutex_lock(&mutex);
while(!state) {
pthread_cond_wait(&cv, &mutex);
}
state = false;
pthread_mutex_unlock(&mutex);
}
void give() {
pthread_mutex_lock(&mutex);
pthread_cond_signal(&cv);
state = true;
pthread_mutex_unlock(&mutex);
}
private:
pthread_cond_t cv;
pthread_mutex_t mutex;
bool state;
};
}
#endif

@ -1,96 +0,0 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2015 The srsLTE Developers. See the
* COPYRIGHT file at the top-level directory of this distribution.
*
* \section LICENSE
*
* This file is part of the srsLTE library.
*
* srsLTE 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.
*
* srsLTE 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 <stdint.h>
/******************************************************************************
* File: queue.h
*
* Description: Queue used at interface of PHY/MAC
*
* Reference:
*****************************************************************************/
#ifndef QUEUE_H
#define QUEUE_H
namespace srslte {
namespace ue {
class queue
{
public:
class element
{
public:
element() {
state = READY;
tti = 0;
}
~element();
void release()
{
state = RELEASED;
}
bool is_released()
{
return state == RELEASED;
}
void ready() {
state = READY;
}
bool is_ready() {
return state == READY;
}
uint32_t tti;
protected:
enum {
RELEASED, READY
} state;
};
queue(uint32_t nof_elements, uint32_t element_size);
~queue();
element* get(uint32_t tti);
private:
uint32_t nof_elements;
uint32_t element_size;
element* *buffer_of_elements;
};
}
}
#endif

@ -38,5 +38,31 @@
#ifdef __cplusplus #ifdef __cplusplus
} }
#ifndef THREADS_
#define THREADS_
class thread
{
public:
bool start(uint32_t prio = 0) {
return threads_new_rt_prio(&_thread, thread_function_entry, this, prio);
}
void print_priority() {
threads_print_self();
}
void wait_thread_finish() {
pthread_join(_thread, NULL);
}
protected:
virtual void run_thread() = 0;
private:
static void *thread_function_entry(void *_this) { ((thread*) _this)->run_thread();}
pthread_t _thread;
};
#endif
#endif #endif

@ -1,80 +0,0 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2015 The srsLTE Developers. See the
* COPYRIGHT file at the top-level directory of this distribution.
*
* \section LICENSE
*
* This file is part of the srsLTE library.
*
* srsLTE 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.
*
* srsLTE 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 <stdint.h>
#ifndef TTISYNC_H
#define TTISYNC_H
namespace srslte {
namespace ue {
/* Interface used for PHY-MAC synchronization (producer-consumer model).
* The consumer waits while its counter is lower than the producer counter.
* The PHY is the consumer. The MAC is the producer.
*/
class tti_sync
{
public:
tti_sync(uint32_t modulus_)
{
modulus = modulus_;
increment = 1;
init_counters(0);
}
virtual void increase() = 0;
virtual void resync() = 0;
virtual uint32_t wait() = 0;
virtual void set_producer_cntr(uint32_t) = 0;
uint32_t get_producer_cntr() { return producer_cntr; }
uint32_t get_consumer_cntr() { return consumer_cntr; }
void set_increment(uint32_t increment_) {
increment = increment_;
}
protected:
void increase_producer() { producer_cntr = (producer_cntr + increment)%modulus; }
void increase_consumer() { consumer_cntr = (consumer_cntr + increment)%modulus; }
bool wait_condition() { return producer_cntr == consumer_cntr; }
void init_counters(uint32_t val)
{
consumer_cntr = val;
producer_cntr = val;
}
uint32_t increment;
uint32_t modulus;
uint32_t producer_cntr;
uint32_t consumer_cntr;
};
}
}
#endif

@ -1,61 +0,0 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2015 The srsLTE Developers. See the
* COPYRIGHT file at the top-level directory of this distribution.
*
* \section LICENSE
*
* This file is part of the srsLTE library.
*
* srsLTE 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.
*
* srsLTE 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 <pthread.h>
#include "srsapps/common/tti_sync.h"
#ifndef TTISYNC_CV_H
#define TTISYNC_CV_H
namespace srslte {
namespace ue {
/* Implements tti_sync interface with condition variables.
*/
class tti_sync_cv : public tti_sync
{
public:
tti_sync_cv(uint32_t modulus = 10240);
~tti_sync_cv();
void increase();
uint32_t wait();
void resync();
void set_producer_cntr(uint32_t producer_cntr);
private:
pthread_cond_t cond;
pthread_mutex_t mutex;
};
}
}
#endif

@ -1,64 +0,0 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2015 The srsLTE Developers. See the
* COPYRIGHT file at the top-level directory of this distribution.
*
* \section LICENSE
*
* This file is part of the srsLTE library.
*
* srsLTE 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.
*
* srsLTE 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 <stdio.h>
#include <stdlib.h>
#include "srsapps/common/queue.h"
namespace srslte {
namespace ue {
queue::queue(uint32_t nof_elements_, uint32_t element_size)
{
nof_elements = nof_elements_;
buffer_of_elements = (queue::element**) malloc(sizeof(queue::element*) * nof_elements);
for (int i=0;i<nof_elements;i++) {
buffer_of_elements[i] = (queue::element*) malloc(element_size);
}
}
queue::~queue()
{
for (int i=0;i<nof_elements;i++) {
if (buffer_of_elements[i]) {
free(buffer_of_elements[i]);
}
}
if (buffer_of_elements) {
free(buffer_of_elements);
}
}
queue::element* queue::get(uint32_t tti)
{
queue::element* el = (queue::element*) buffer_of_elements[tti%nof_elements];
el->tti = tti;
return el;
}
} // namespace ue
} // namespace srslte

@ -1,80 +0,0 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2015 The srsLTE Developers. See the
* COPYRIGHT file at the top-level directory of this distribution.
*
* \section LICENSE
*
* This file is part of the srsLTE library.
*
* srsLTE 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.
*
* srsLTE 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 <pthread.h>
#include "srsapps/common/tti_sync_cv.h"
namespace srslte {
namespace ue {
tti_sync_cv::tti_sync_cv(uint32_t modulus): tti_sync(modulus)
{
pthread_mutex_init(&mutex, NULL);
pthread_cond_init(&cond, NULL);
}
tti_sync_cv::~tti_sync_cv()
{
pthread_cond_destroy(&cond);
pthread_mutex_destroy(&mutex);
}
uint32_t tti_sync_cv::wait()
{
pthread_mutex_lock(&mutex);
while(wait_condition()) {
pthread_cond_wait(&cond, &mutex);
}
uint32_t x = consumer_cntr;
increase_consumer();
pthread_mutex_unlock(&mutex);
return x;
}
void tti_sync_cv::resync()
{
consumer_cntr = producer_cntr;
}
void tti_sync_cv::set_producer_cntr(uint32_t producer_cntr)
{
pthread_mutex_lock(&mutex);
init_counters(producer_cntr);
pthread_cond_signal(&cond);
pthread_mutex_unlock(&mutex);
}
void tti_sync_cv::increase()
{
pthread_mutex_lock(&mutex);
increase_producer();
pthread_cond_signal(&cond);
pthread_mutex_unlock(&mutex);
}
}
}

@ -23,5 +23,5 @@ INCLUDE_DIRECTORIES(phy/include/)
INCLUDE_DIRECTORIES(mac/include/) INCLUDE_DIRECTORIES(mac/include/)
add_subdirectory(phy) add_subdirectory(phy)
add_subdirectory(mac) #add_subdirectory(mac)

@ -44,57 +44,6 @@ namespace ue {
mac_params() : params_db(NOF_PARAMS) {} mac_params() : params_db(NOF_PARAMS) {}
~mac_params() {} ~mac_params() {}
typedef enum {
// These 4 parameters must be together!!
RNTI_C = 0,
RNTI_SPS,
RNTI_TEMP,
RNTI_RA,
SPS_DL_SCHED_INTERVAL,
SPS_DL_NOF_PROC,
BCCH_SI_WINDOW_ST,
BCCH_SI_WINDOW_LEN,
PCCH_RECEIVE,
CONTENTION_ID, // Transmitted UE Contention ID
TIMER_TIMEALIGN,
// Random Access parameters. See 5.1.1
RA_CONFIGINDEX,
RA_PREAMBLEINDEX,
RA_MASKINDEX,
RA_NOFPREAMBLES,
RA_NOFGROUPAPREAMBLES,
RA_MESSAGEPOWEROFFSETB,
RA_MESSAGESIZEA,
RA_PCMAX,
RA_DELTAPREAMBLEMSG3,
RA_RESPONSEWINDOW,
RA_POWERRAMPINGSTEP,
RA_PREAMBLETRANSMAX,
RA_INITRECEIVEDPOWER,
RA_CONTENTIONTIMER,
SR_PUCCH_CONFIGURED,
SR_TRANS_MAX,
BSR_TIMER_PERIODIC,
BSR_TIMER_RETX,
HARQ_MAXTX,
HARQ_MAXMSG3TX,
PDSCH_RSPOWER,
PDSCH_PB,
NOF_PARAMS,
} mac_param_t;
}; };
} }

@ -1,80 +0,0 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2015 The srsLTE Developers. See the
* COPYRIGHT file at the top-level directory of this distribution.
*
* \section LICENSE
*
* This file is part of the srsLTE library.
*
* srsLTE 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.
*
* srsLTE 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 "srslte/srslte.h"
#include "srsapps/common/log.h"
#include "srsapps/common/queue.h"
#include "srsapps/ue/phy/ul_sched_grant.h"
#include "srsapps/ue/phy/dl_sched_grant.h"
#include "srsapps/ue/phy/phy_params.h"
#ifndef UEDLBUFFER_H
#define UEDLBUFFER_H
namespace srslte {
namespace ue {
/* Class for the processing of Downlink buffers. The MAC obtains a buffer for a given TTI and then
* gets ul/dl scheduling grants and/or processes phich/pdsch channels
*/
class dl_buffer : public queue::element {
public:
int buffer_id;
bool init_cell(srslte_cell_t cell, phy_params *params_db, log *log_h_);
void free_cell();
void set_crnti(uint16_t rnti);
bool recv_ue_sync(srslte_ue_sync_t *ue_sync, srslte_timestamp_t *rx_time);
bool get_ul_grant(ul_sched_grant *grant);
bool get_dl_grant(dl_sched_grant *grant);
void discard_pending_rar_grant();
void set_rar_grant(srslte_dci_rar_grant_t *rar_grant);
void set_rar_grant(uint8_t grant_payload[SRSLTE_RAR_GRANT_LEN]);
void reset_softbuffer();
bool decode_ack(ul_sched_grant *pusch_grant);
bool decode_data(dl_sched_grant *pdsch_grant, uint8_t *payload); // returns true or false for CRC OK/NOK
bool decode_data(dl_sched_grant *grant, srslte_softbuffer_rx_t *softbuffer, uint8_t *payload);
private:
phy_params *params_db;
log *log_h;
srslte_cell_t cell;
srslte_ue_dl_t ue_dl;
srslte_phich_t phich;
cf_t *signal_buffer;
uint32_t cfi;
bool sf_symbols_and_ce_done;
bool pdcch_llr_extracted;
bool pending_rar_grant;
srslte_dci_rar_grant_t rar_grant;
};
}
}
#endif

@ -1,114 +0,0 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2015 The srsLTE Developers. See the
* COPYRIGHT file at the top-level directory of this distribution.
*
* \section LICENSE
*
* This file is part of the srsLTE library.
*
* srsLTE 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.
*
* srsLTE 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 <string.h>
#include "srslte/srslte.h"
#include "srsapps/ue/phy/sched_grant.h"
#ifndef UEDLSCHEDGRANT_H
#define UEDLSCHEDGRANT_H
namespace srslte {
namespace ue {
/* Uplink/Downlink scheduling grant generated by a successfully decoded PDCCH */
class dl_sched_grant : public sched_grant {
public:
dl_sched_grant(rnti_type_t type, uint16_t rnti) : sched_grant(type, rnti) {}
dl_sched_grant(uint16_t rnti) : sched_grant(rnti) {}
uint32_t get_rv() {
return dl_dci.rv_idx;
}
void set_rv(uint32_t rv) {
dl_dci.rv_idx = rv;
}
bool get_ndi() {
return dl_dci.ndi;
}
void set_ndi(bool value) {
dl_dci.ndi = value;
}
uint32_t get_harq_process() {
return dl_dci.harq_process;
}
void get_dl_grant(srslte_ra_dl_grant_t *ul_grant) {
memcpy(ul_grant, &grant, sizeof(srslte_ra_dl_grant_t));
}
bool is_sps_release() {
return false;
}
uint32_t get_tbs() {
return grant.mcs.tbs;
}
uint32_t get_ncce() {
return ncce;
}
uint32_t get_mcs() {
return dl_dci.mcs_idx;
}
const char* get_dciformat_string() {
switch(dl_dci.dci_format) {
case srslte_ra_dl_dci_t::SRSLTE_RA_DCI_FORMAT1:
return "Format1";
case srslte_ra_dl_dci_t::SRSLTE_RA_DCI_FORMAT1A:
return "Format1A";
case srslte_ra_dl_dci_t::SRSLTE_RA_DCI_FORMAT1C:
return "Format1C";
}
}
bool create_from_dci(srslte_dci_msg_t *msg, uint32_t nof_prb, uint32_t ncce_) {
ncce = ncce_;
if (srslte_dci_msg_to_dl_grant(msg, rnti, nof_prb, &dl_dci, &grant)) {
return false;
} else {
return true;
}
}
bool get_pdsch_cfg(uint32_t sf_idx, uint32_t cfi, srslte_ue_dl_t *ue_dl) {
memcpy(&ue_dl->pdsch_cfg.grant, &grant, sizeof(srslte_ra_dl_grant_t));
/* Setup PDSCH configuration for this CFI, SFIDX and RVIDX */
if (srslte_ue_dl_cfg_grant(ue_dl, NULL, cfi, sf_idx, rnti, get_rv())) {
return false;
}
return true;
}
private:
srslte_ra_dl_grant_t grant;
srslte_ra_dl_dci_t dl_dci;
uint32_t ncce;
};
}
}
#endif

@ -29,153 +29,105 @@
#include "srslte/srslte.h" #include "srslte/srslte.h"
#include "srsapps/common/phy_interface.h"
#include "srsapps/common/log.h" #include "srsapps/common/log.h"
#include "srsapps/common/tti_sync.h" #include "srsapps/ue/phy/phch_recv.h"
#include "srsapps/ue/phy/dl_buffer.h"
#include "srsapps/ue/phy/ul_buffer.h"
#include "srsapps/ue/phy/prach.h" #include "srsapps/ue/phy/prach.h"
#include "srsapps/ue/phy/phy_params.h" #include "srsapps/ue/phy/phy_params.h"
#include "srsapps/ue/phy/sched_grant.h" #include "srsapps/ue/phy/phch_worker.h"
#include "srsapps/common/queue.h" #include "srsapps/ue/phy/phch_common.h"
#include "srsapps/radio/radio.h" #include "srsapps/radio/radio.h"
#include "srsapps/common/task_dispatcher.h"
#include "srsapps/common/trace.h" #include "srsapps/common/trace.h"
#include "srsapps/common/mac_interface.h"
#ifndef UEPHY_H #ifndef UEPHY_H
#define UEPHY_H #define UEPHY_H
namespace srslte { namespace srslte {
namespace ue { namespace ue {
/* The procedure for attaching to an eNodeB is the following:
*
* 1) Call init() to initialize the PHY (starts an internal thread)
* 2) Call set_rx_freq() and set_rx_gain() to set Downlink frequency and receiver gain
* 3) Call decode_mib() to receive and decode MIB from PBCH in the current frequency
* 4) Call set_cell() to set the current eNodeB
* 5) Call start_rxtx() to start continuous RX/TX stream
* 6) Call set_tx_freq()/set_tx_gain() to set Uplink frequency and transmitter gain
* 7) Call send_prach() to send the PRACH
*
*/
typedef _Complex float cf_t; typedef _Complex float cf_t;
class phy class phy : public phy_interface, phy_interface_params
{ {
public: public:
phy(); phy();
void set(); bool init(radio *radio_handler, mac_interface_phy *mac, log *log_h);
bool init(radio *radio_handler, tti_sync *ttisync, log *log_h); bool init_agc(radio *radio_handler, mac_interface_phy *mac, log *log_h);
bool init_agc(radio *radio_handler, tti_sync *ttisync, log *log_h);
void stop(); void stop();
// These functions can be called only if PHY is in IDLE (ie, not RX/TX)
bool measure(); // TBD
bool decode_mib(uint32_t N_id_2, srslte_cell_t *cell, uint8_t payload[SRSLTE_BCH_PAYLOAD_LEN]);
bool decode_mib_best(srslte_cell_t *cell, uint8_t payload[SRSLTE_BCH_PAYLOAD_LEN]);
bool set_cell(srslte_cell_t cell);
// Sets the PHY in continuous RX/TX mode
bool start_rxtx();
bool stop_rxtx();
float get_agc_gain();
void set_crnti(uint16_t rnti); void set_crnti(uint16_t rnti);
void pregen_signals();
// Indicate the PHY to send PRACH as soon as possible // Get status
bool init_prach(); bool status_is_sync();
bool send_prach(uint32_t preamble_idx);
bool send_prach(uint32_t preamble_idx, int allowed_subframe);
bool send_prach(uint32_t preamble_idx, int allowed_subframe, int target_power_dbm);
// Indicate the PHY to send SR as soon as possible or not
void send_sr(bool enable);
int sr_last_tx_tti();
// Returns TTI when PRACH was transmitted. -1 if not yet transmitted static uint32_t tti_to_SFN(uint32_t tti);
int get_prach_transmitted_tti(); static uint32_t tti_to_subf(uint32_t tti);
// Get handler to the radio void enable_pregen_signals(bool enable);
radio* get_radio();
// Time advance commands
void set_timeadv_rar(uint32_t ta_cmd);
void set_timeadv(uint32_t ta_cmd);
// Convert Msg3 UL grant to ul_sched_grant void start_trace();
void rar_ul_grant(srslte_dci_rar_grant_t *rar, ul_sched_grant *grant); void write_trace(std::string filename);
// Get status /********** MAC INTERFACE ********************/
bool status_is_idle(); /* Instructs the PHY to configure using the parameters written with set_param() */
bool status_is_rxtx(); void configure_prach_params();
void configure_ul_params();
/* Functions to synchronize with a cell */
void sync_start();
void sync_stop();
void set_param(phy_params::phy_param_t param, int64_t value); /* Functions to initialize and transmit PRACH in the next opportunity */
int64_t get_param(phy_params::phy_param_t param); void prach_send(prach_cfg_t *cfg);
uint32_t get_current_tti(); /* Indicates the transmission of a SR signal in the next opportunity */
static uint32_t tti_to_SFN(uint32_t tti); void sr_send();
static uint32_t tti_to_subf(uint32_t tti);
ul_buffer* get_ul_buffer(uint32_t tti); // Time advance commands
dl_buffer* get_dl_buffer(uint32_t tti); void set_timeadv_rar(uint32_t ta_cmd);
void set_timeadv(uint32_t ta_cmd);
/* Sets RAR grant payload */
void set_rar_grant(uint32_t tti, uint8_t grant_payload[SRSLTE_RAR_GRANT_LEN]);
void start_trace(); /* Instruct the PHY to decode PDCCH with the CRC scrambled with given RNTI */
void write_trace(std::string filename); void pdcch_ul_search(srslte_rnti_type_t rnti_type, uint16_t rnti, int tti_start = -1, int tti_end = -1);
void pdcch_dl_search(srslte_rnti_type_t rnti_type, uint16_t rnti, int tti_start = -1, int tti_end = -1);
bool sr_is_ready_to_send(uint32_t tti); /* Get/Set PHY parameters */
bool cqi_is_ready_to_send(uint32_t tti); void set_param(phy_param_t param, int64_t value);
int64_t get_param(phy_param_t param);
void main_radio_loop(); void reset();
private: uint32_t get_current_tti();
enum {
IDLE, RXTX
} phy_state;
static const int NOF_ULDL_QUEUES = 10; private:
const static int NOF_WORKERS = 1;
const static int SF_RECV_THREAD_PRIO = 1;
const static int WORKERS_THREAD_PRIO = 0;
tti_sync *ttisync;
radio *radio_handler; radio *radio_handler;
log *log_h; log *log_h;
thread_pool workers_pool;
std::vector<phch_worker> workers;
phch_common workers_common;
phch_recv sf_recv;
prach prach_buffer;
srslte_cell_t cell;
bool cell_is_set;
bool is_sfn_synched;
volatile bool started;
srslte_ue_sync_t ue_sync;
srslte_ue_mib_t ue_mib;
queue *ul_buffer_queue;
queue *dl_buffer_queue;
prach prach_buffer;
phy_params params_db; phy_params params_db;
pthread_t phy_thread; /* Current time advance */
float time_adv_sec;
uint32_t n_ta; uint32_t n_ta;
bool radio_is_streaming;
srslte_timestamp_t last_rx_time;
float cellsearch_cfo;
bool do_agc;
double last_gain;
bool sr_enabled; srslte_cell_t cell;
bool init_(radio *radio_handler, tti_sync *ttisync, log *log_h, bool do_agc);
static void *phy_thread_fnc(void *arg);
bool decode_mib_N_id_2(int force_N_id_2, srslte_cell_t *cell, uint8_t payload[SRSLTE_BCH_PAYLOAD_LEN]);
int sync_sfn();
void run_rx_tx_state();
ul_buffer* get_ul_buffer_adv(uint32_t tti);
float old_gain;
uint32_t sr_tx_tti;
bool is_first_of_burst;
bool init_(radio *radio_handler, mac_interface_phy *mac, log *log_h, bool do_agc);
trace<uint32_t> tr_start_time; trace<uint32_t> tr_start_time;
trace<uint32_t> tr_end_time; trace<uint32_t> tr_end_time;
bool tr_enabled; bool tr_enabled;

@ -29,6 +29,7 @@
#include "srslte/srslte.h" #include "srslte/srslte.h"
#include "srsapps/common/params_db.h" #include "srsapps/common/params_db.h"
#include "srsapps/common/phy_interface.h"
#ifndef PHYPARAMS_H #ifndef PHYPARAMS_H
#define PHYPARAMS_H #define PHYPARAMS_H
@ -41,77 +42,10 @@ namespace ue {
{ {
public: public:
phy_params() : params_db(NOF_PARAMS) { } phy_params() : params_db(phy_interface_params::NOF_PARAMS) { }
~phy_params() {} ~phy_params() {}
typedef enum {
DL_FREQ = 0,
UL_FREQ,
CELLSEARCH_TIMEOUT_PSS_NFRAMES,
CELLSEARCH_TIMEOUT_MIB_NFRAMES,
CELLSEARCH_TIMEOUT_PSS_CORRELATION_THRESHOLD, // integer that will be divided by 10
PUSCH_BETA,
PUSCH_EN_64QAM,
PUSCH_RS_CYCLIC_SHIFT,
PUSCH_RS_GROUP_ASSIGNMENT,
DMRS_GROUP_HOPPING_EN,
DMRS_SEQUENCE_HOPPING_EN,
PUSCH_HOPPING_N_SB,
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,
SR_CONFIG_INDEX,
SRS_BETA,
SRS_UE_TXCOMB,
SRS_UE_NRRC,
SRS_UE_DURATION,
SRS_UE_CONFIGINDEX,
SRS_UE_BW,
SRS_UE_HOP,
SRS_UE_CS,
SRS_UE_CYCLICSHIFT,
SRS_CS_BWCFG,
SRS_CS_SFCFG,
SRS_CS_ACKNACKSIMUL,
SRS_IS_CONFIGURED,
CQI_PERIODIC_PMI_IDX,
CQI_PERIODIC_SIMULT_ACK,
CQI_PERIODIC_FORMAT_SUBBAND,
CQI_PERIODIC_FORMAT_SUBBAND_K,
CQI_PERIODIC_CONFIGURED,
UCI_I_OFFSET_ACK,
UCI_I_OFFSET_RI,
UCI_I_OFFSET_CQI,
PRACH_CONFIG_INDEX,
PRACH_ROOT_SEQ_IDX,
PRACH_HIGH_SPEED_FLAG,
PRACH_ZC_CONFIG,
PRACH_FREQ_OFFSET,
NOF_PARAMS,
} phy_param_t;
}; };
} }
} }

@ -30,7 +30,7 @@
#include "srslte/srslte.h" #include "srslte/srslte.h"
#include "srsapps/radio/radio.h" #include "srsapps/radio/radio.h"
#include "srsapps/common/log.h" #include "srsapps/common/log.h"
#include "srsapps/common/queue.h" #include "srsapps/common/phy_interface.h"
#include "srsapps/ue/phy/phy_params.h" #include "srsapps/ue/phy/phy_params.h"
#ifndef UEPRACH_H #ifndef UEPRACH_H
@ -46,14 +46,16 @@ namespace ue {
initiated = false; initiated = false;
signal_buffer = NULL; signal_buffer = NULL;
} }
bool init_cell(srslte_cell_t cell, phy_params *params_db, log *log_h); void init(phy_params *params_db, log *log_h);
bool init_cell(srslte_cell_t cell);
void free_cell(); void free_cell();
bool prepare_to_send(uint32_t preamble_idx); bool prepare_to_send(phy_interface::prach_cfg_t* cfg);
bool prepare_to_send(uint32_t preamble_idx, int allowed_subframe); bool prepare_to_send(uint32_t preamble_idx, int allowed_subframe = -1, float target_power_dbm = -1);
bool prepare_to_send(uint32_t preamble_idx, int allowed_subframe, int target_power_dbm);
bool is_ready_to_send(uint32_t current_tti); bool is_ready_to_send(uint32_t current_tti);
int get_transmitted_tti(); void get_rar_cfg(uint16_t* rar_rnti, uint32_t* tti_start, uint32_t* tti_end);
bool send(srslte::radio* radio_handler, float cfo, srslte_timestamp_t rx_time);
bool send(radio* radio_handler, float cfo, srslte_timestamp_t rx_time);
private: private:
static const uint32_t tx_advance_sf = 1; // Number of subframes to advance transmission static const uint32_t tx_advance_sf = 1; // Number of subframes to advance transmission
phy_params *params_db; phy_params *params_db;
@ -68,6 +70,8 @@ namespace ue {
srslte_cell_t cell; srslte_cell_t cell;
cf_t *signal_buffer; cf_t *signal_buffer;
srslte_cfo_t cfo_h; srslte_cfo_t cfo_h;
phy_interface::prach_cfg_t prach_cfg;
}; };
} }

@ -1,104 +0,0 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2015 The srsLTE Developers. See the
* COPYRIGHT file at the top-level directory of this distribution.
*
* \section LICENSE
*
* This file is part of the srsLTE library.
*
* srsLTE 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.
*
* srsLTE 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 "srslte/srslte.h"
#include "srsapps/common/queue.h"
#ifndef UESCHEDGRANT_H
#define UESCHEDGRANT_H
namespace srslte {
namespace ue {
/* Uplink/Downlink scheduling grant generated by a successfully decoded PDCCH */
class sched_grant {
public:
typedef enum {
RNTI_TYPE_NOTDEFINED = 0,
RNTI_TYPE_CRNTI,
RNTI_TYPE_RA,
RNTI_TYPE_SPS,
RNTI_TYPE_TEMP,
RNTI_TYPE_SIRNTI,
RNTI_TYPE_PRNTI,
RNTI_TYPE_TPC_PUSCH,
RNTI_TYPE_TPC_PUCCH
} rnti_type_t;
sched_grant(uint16_t rnti_) {
rnti = rnti_;
rnti_type = RNTI_TYPE_NOTDEFINED;
}
sched_grant(rnti_type_t rnti_type_, uint16_t rnti_) {
rnti = rnti_;
rnti_type = rnti_type_;
}
uint16_t get_rnti() {
return rnti;
}
bool is_temp_rnti() {
return rnti_type == RNTI_TYPE_TEMP;
}
bool is_crnti() {
return rnti_type == RNTI_TYPE_CRNTI;
}
bool is_ra_rnti() {
return rnti_type == RNTI_TYPE_RA;
}
bool is_SPS_rnti() {
return rnti_type == RNTI_TYPE_SPS;
}
bool is_sys_rnti() {
return (rnti_type == RNTI_TYPE_SIRNTI || rnti_type == RNTI_TYPE_PRNTI);
}
bool is_tpc_rnti() {
return (rnti_type == RNTI_TYPE_TPC_PUSCH || rnti_type == RNTI_TYPE_TPC_PUCCH);
}
uint32_t get_tti() {
return tti;
}
void set_tti(uint32_t tti_) {
tti = tti_;
}
virtual uint32_t get_rv() = 0;
virtual void set_rv(uint32_t rv) = 0;
virtual bool get_ndi() = 0;
virtual void set_ndi(bool value) = 0;
virtual bool is_sps_release() = 0;
virtual uint32_t get_tbs() = 0;
protected:
uint16_t rnti;
rnti_type_t rnti_type;
uint32_t tti;
};
}
}
#endif

@ -1,89 +0,0 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2015 The srsLTE Developers. See the
* COPYRIGHT file at the top-level directory of this distribution.
*
* \section LICENSE
*
* This file is part of the srsLTE library.
*
* srsLTE 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.
*
* srsLTE 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 "srslte/srslte.h"
#include "srsapps/radio/radio.h"
#include "srsapps/common/log.h"
#include "srsapps/common/queue.h"
#include "srsapps/ue/phy/ul_sched_grant.h"
#include "srsapps/ue/phy/dl_sched_grant.h"
#include "srsapps/ue/phy/phy_params.h"
#include "srsapps/radio/radio.h"
#ifndef UEULBUFFER_H
#define UEULBUFFER_H
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_data() to set the packet ready for transmission
*/
class ul_buffer : public queue::element {
public:
bool init_cell(srslte_cell_t cell, phy_params *params_db, log *log_h, radio *radio_h);
void free_cell();
void set_crnti(uint16_t rnti);
void set_current_tx_nb(uint32_t current_tx_nb);
bool generate_ack(bool ack, dl_sched_grant *last_dl_grant);
bool generate_ack(bool ack[2]);
bool generate_sr();
bool generate_cqi_report();
bool uci_ready();
bool srs_is_ready_to_send();
bool generate_data();
bool generate_data(ul_sched_grant *pusch_grant, uint8_t *payload);
bool generate_data(ul_sched_grant *pusch_grant, srslte_softbuffer_tx_t *softbuffer, uint8_t *payload);
void set_tx_params(float cfo, float time_adv_sec, srslte_timestamp_t tx_time);
void send_end_of_burst();
void send();
void pregen_signals();
static const uint32_t tx_advance_sf = 1; // Number of subframes to advance transmission
static const bool normalize_amp = true;
private:
log *log_h;
phy_params *params_db;
radio *radio_h;
float cfo;
srslte_timestamp_t tx_time;
srslte_cell_t cell;
srslte_ue_ul_t ue_ul;
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;
};
}
}
#endif

@ -1,134 +0,0 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2015 The srsLTE Developers. See the
* COPYRIGHT file at the top-level directory of this distribution.
*
* \section LICENSE
*
* This file is part of the srsLTE library.
*
* srsLTE 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.
*
* srsLTE 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 <string.h>
#include "srslte/srslte.h"
#include "srsapps/ue/phy/sched_grant.h"
#ifndef UEULSCHEDGRANT_H
#define UEULSCHEDGRANT_H
namespace srslte {
namespace ue {
/* Uplink/Downlink scheduling grant generated by a successfully decoded PDCCH */
class ul_sched_grant : public sched_grant {
public:
ul_sched_grant(rnti_type_t type, uint16_t rnti) : sched_grant(type, rnti) {}
ul_sched_grant(uint16_t rnti) : sched_grant(rnti) {}
uint32_t get_rv() {
return ul_dci.rv_idx;
}
void set_rv(uint32_t rv) {
ul_dci.rv_idx = rv;
}
bool get_ndi() {
return ul_dci.ndi;
}
void set_ndi(bool value) {
ul_dci.ndi = value;
}
bool get_cqi_request() {
return ul_dci.cqi_request;
}
void get_ul_grant(srslte_ra_ul_grant_t *ul_grant) {
memcpy(ul_grant, &grant, sizeof(srslte_ra_ul_grant_t));
}
bool is_sps_release() {
return false;
}
uint32_t get_tbs() {
return grant.mcs.tbs;
}
uint32_t get_mcs() {
return ul_dci.mcs_idx;
}
uint32_t get_current_tx_nb() {
return current_tx_nb;
}
void set_current_tx_nb(uint32_t current_tx_nb) {
current_tx_nb = current_tx_nb;
}
uint32_t get_I_lowest() {
return grant.n_prb[0];
}
uint32_t get_n_dmrs() {
return ul_dci.n_dmrs;
}
bool is_from_rar() {
return grant_is_from_rar;
}
bool create_from_dci(srslte_dci_msg_t *msg, srslte_cell_t cell, uint32_t n_rb_ho) {
grant_is_from_rar = false;
if (srslte_dci_msg_to_ul_grant(msg, cell.nof_prb, n_rb_ho, &ul_dci, &grant)) {
return false;
} else {
if (SRSLTE_VERBOSE_ISINFO()) {
srslte_ra_pusch_fprint(stdout, &ul_dci, cell.nof_prb);
}
return true;
}
}
bool create_from_rar(srslte_dci_rar_grant_t *rar, srslte_cell_t cell, uint32_t n_rb_ho) {
grant_is_from_rar = true;
if (srslte_dci_rar_to_ul_grant(rar, cell.nof_prb, n_rb_ho, &ul_dci, &grant)) {
return false;
} else {
if (SRSLTE_VERBOSE_ISINFO()) {
srslte_ra_pusch_fprint(stdout, &ul_dci, cell.nof_prb);
}
return true;
}
}
bool to_pusch_cfg(srslte_pusch_hopping_cfg_t *hopping_cfg, srslte_refsignal_srs_cfg_t *srs_cfg, uint32_t tti, srslte_ue_ul_t *ue_ul) {
memcpy(&ue_ul->pusch_cfg.grant, &grant, sizeof(srslte_ra_ul_grant_t));
uint32_t cyclic_shift_for_dmrs = 0;
if (!is_from_rar()) {
cyclic_shift_for_dmrs = get_n_dmrs();
}
if (srslte_ue_ul_cfg_grant(ue_ul, NULL, hopping_cfg, srs_cfg, tti, cyclic_shift_for_dmrs, get_rv())) {
return false;
}
return true;
}
private:
srslte_ra_ul_grant_t grant;
srslte_ra_ul_dci_t ul_dci;
uint32_t current_tx_nb;
uint16_t rnti;
bool grant_is_from_rar;
};
}
}
#endif

@ -1,235 +0,0 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2014 The srsLTE Developers. See the
* COPYRIGHT file at the top-level directory of this distribution.
*
* \section LICENSE
*
* This file is part of the srsLTE library.
*
* srsLTE is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* srsLTE 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 Lesser General Public License for more details.
*
* A copy of the GNU Lesser 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 <string.h>
#include <strings.h>
#include <pthread.h>
#include "srslte/srslte.h"
#include "srsapps/common/log.h"
#include "srsapps/ue/phy/sched_grant.h"
#include "srsapps/ue/phy/dl_buffer.h"
#include "srsapps/ue/phy/phy.h"
#include "srsapps/ue/phy/phy_params.h"
namespace srslte {
namespace ue {
bool dl_buffer::init_cell(srslte_cell_t cell_, phy_params *params_db_, log *log_h_)
{
log_h = log_h_;
params_db = params_db_;
cell = cell_;
sf_symbols_and_ce_done = false;
pdcch_llr_extracted = false;
pending_rar_grant = false;
tti = 0;
if (!srslte_ue_dl_init(&ue_dl, cell)) {
signal_buffer = (cf_t*) srslte_vec_malloc(sizeof(cf_t) * SRSLTE_SF_LEN_PRB(cell.nof_prb));
return signal_buffer?true:false;
} else {
return false;
}
}
void dl_buffer::free_cell()
{
if (signal_buffer) {
free(signal_buffer);
}
srslte_ue_dl_free(&ue_dl);
}
void dl_buffer::set_crnti(uint16_t rnti)
{
srslte_ue_dl_set_rnti(&ue_dl, rnti);
}
// FIXME: Avoid this memcpy modifying ue_sync to directly write into provided pointer
bool dl_buffer::recv_ue_sync(srslte_ue_sync_t *ue_sync, srslte_timestamp_t *rx_time)
{
bool ret = false;
cf_t *sf_buffer = NULL;
sf_symbols_and_ce_done = false;
pdcch_llr_extracted = false;
if (signal_buffer) {
bzero(signal_buffer, sizeof(cf_t) * SRSLTE_SF_LEN_PRB(cell.nof_prb));
if (srslte_ue_sync_get_buffer(ue_sync, &sf_buffer) == 1) {
memcpy(signal_buffer, sf_buffer, sizeof(cf_t) * SRSLTE_SF_LEN_PRB(cell.nof_prb));
ready();
ret = true;
}
srslte_ue_sync_get_last_timestamp(ue_sync, rx_time);
}
return ret;
}
void dl_buffer::discard_pending_rar_grant() {
pending_rar_grant = false;
}
bool dl_buffer::get_ul_grant(ul_sched_grant *grant)
{
if (signal_buffer) {
if (pending_rar_grant && grant->is_temp_rnti()) {
return grant->create_from_rar(&rar_grant, cell, params_db->get_param(phy_params::PUSCH_HOPPING_OFFSET));
} else {
if (!sf_symbols_and_ce_done) {
if (srslte_ue_dl_decode_fft_estimate(&ue_dl, signal_buffer, tti%10, &cfi) < 0) {
return false;
}
sf_symbols_and_ce_done = true;
}
if (!pdcch_llr_extracted) {
if (srslte_pdcch_extract_llr(&ue_dl.pdcch, ue_dl.sf_symbols, ue_dl.ce, 0, tti%10, cfi)) {
return false;
}
pdcch_llr_extracted = true;
}
srslte_dci_msg_t dci_msg;
if (srslte_ue_dl_find_ul_dci(&ue_dl, &dci_msg, cfi, tti%10, grant->get_rnti()) != 1) {
return false;
}
grant->set_tti(tti);
Info("PDCCH: UL DCI Format0 cce_index=%d, n_data_bits=%d\n", ue_dl.last_n_cce, dci_msg.nof_bits);
return grant->create_from_dci(&dci_msg, cell, params_db->get_param(phy_params::PUSCH_HOPPING_OFFSET));
}
}
}
// Unpack RAR grant as defined in Section 6.2 of 36.213
void dl_buffer::set_rar_grant(uint8_t grant_payload[SRSLTE_RAR_GRANT_LEN])
{
pending_rar_grant = true;
srslte_dci_rar_grant_unpack(&rar_grant, grant_payload);
}
void dl_buffer::set_rar_grant(srslte_dci_rar_grant_t* rar_grant_)
{
pending_rar_grant = true;
memcpy(&rar_grant, rar_grant_, sizeof(srslte_dci_rar_grant_t));
}
bool dl_buffer::get_dl_grant(dl_sched_grant *grant)
{
if (signal_buffer && is_ready()) {
Debug("DL Buffer TTI %d: Getting DL grant\n", tti);
if (!sf_symbols_and_ce_done) {
Debug("DL Buffer TTI %d: Getting DL grant. Calling fft estimate\n", tti);
if (srslte_ue_dl_decode_fft_estimate(&ue_dl, signal_buffer, tti%10, &cfi) < 0) {
return false;
}
sf_symbols_and_ce_done = true;
}
if (!pdcch_llr_extracted) {
Debug("DL Buffer TTI %d: Getting DL grant. extracting LLR\n", tti);
if (srslte_pdcch_extract_llr(&ue_dl.pdcch, ue_dl.sf_symbols, ue_dl.ce, 0, tti%10, cfi)) {
return false;
}
pdcch_llr_extracted = true;
}
if (SRSLTE_VERBOSE_ISDEBUG()) {
srslte_vec_save_file((char*) "ce1", ue_dl.ce[0], SRSLTE_SF_LEN_RE(ue_dl.cell.nof_prb, ue_dl.cell.cp)*sizeof(cf_t));
srslte_vec_save_file((char*) "ce2", ue_dl.ce[1], SRSLTE_SF_LEN_RE(ue_dl.cell.nof_prb, ue_dl.cell.cp)*sizeof(cf_t));
srslte_vec_save_file((char*) "pdcch_d", ue_dl.pdcch.d, 36*ue_dl.pdcch.nof_cce*sizeof(cf_t));
srslte_vec_save_file((char*) "pdcch_llr", ue_dl.pdcch.llr, 72*ue_dl.pdcch.nof_cce*sizeof(cf_t));
}
srslte_dci_msg_t dci_msg;
if (srslte_ue_dl_find_dl_dci(&ue_dl, &dci_msg, cfi, tti%10, grant->get_rnti()) != 1) {
return false;
}
grant->set_tti(tti);
Info("PDCCH: DL DCI %s cce_index=%d, n_data_bits=%d\n", grant->get_dciformat_string(), ue_dl.last_n_cce, dci_msg.nof_bits);
return grant->create_from_dci(&dci_msg, cell.nof_prb, srslte_ue_dl_get_ncce(&ue_dl));
}
}
bool dl_buffer::decode_ack(ul_sched_grant *grant)
{
if (signal_buffer && is_ready()) {
if (!sf_symbols_and_ce_done) {
if (srslte_ue_dl_decode_fft_estimate(&ue_dl, signal_buffer, tti%10, &cfi) < 0) {
return false;
}
sf_symbols_and_ce_done = true;
}
return srslte_ue_dl_decode_phich(&ue_dl, tti%10, grant->get_I_lowest(), grant->get_n_dmrs());
}
}
void dl_buffer::reset_softbuffer()
{
srslte_softbuffer_rx_reset(&ue_dl.softbuffer);
}
bool dl_buffer::decode_data(dl_sched_grant *grant, uint8_t *payload)
{
return decode_data(grant, &ue_dl.softbuffer, payload);
}
bool dl_buffer::decode_data(dl_sched_grant *grant, srslte_softbuffer_rx_t *softbuffer, uint8_t *payload)
{
if (signal_buffer && is_ready()) {
Debug("DL Buffer TTI %d: Decoding PDSCH\n", tti);
if (!sf_symbols_and_ce_done) {
Debug("DL Buffer TTI %d: Decoding PDSCH. Calling fft estimate\n", tti);
if (srslte_ue_dl_decode_fft_estimate(&ue_dl, signal_buffer, tti%10, &cfi) < 0) {
return false;
}
sf_symbols_and_ce_done = true;
}
grant->get_pdsch_cfg(tti%10, cfi, &ue_dl);
if (ue_dl.pdsch_cfg.grant.mcs.mod > 0 && ue_dl.pdsch_cfg.grant.mcs.tbs >= 0) {
int ret = srslte_pdsch_decode_rnti(&ue_dl.pdsch, &ue_dl.pdsch_cfg, softbuffer, ue_dl.sf_symbols,
ue_dl.ce, 0, grant->get_rnti(), payload);
if (SRSLTE_VERBOSE_ISDEBUG()) {
srslte_vec_save_file((char*) "pdsch_d", ue_dl.pdsch.d, ue_dl.pdsch_cfg.nbits.nof_re*sizeof(cf_t));
}
if (ret == SRSLTE_SUCCESS) {
return true;
}
}
return false;
}
}
}
}

@ -36,29 +36,53 @@
#include "srsapps/common/threads.h" #include "srsapps/common/threads.h"
#include "srsapps/common/log.h" #include "srsapps/common/log.h"
#include "srsapps/ue/phy/phy.h" #include "srsapps/ue/phy/phy.h"
#include "srsapps/ue/phy/prach.h" #include "srsapps/ue/phy/phch_worker.h"
#include "srsapps/ue/phy/ul_buffer.h"
#include "srsapps/ue/phy/dl_buffer.h"
namespace srslte { namespace srslte {
namespace ue { namespace ue {
phy::phy() : tr_end_time(1024*10), tr_start_time(1024*10) phy::phy() : tr_end_time(1024*10), tr_start_time(1024*10), workers_pool(NOF_WORKERS), workers(NOF_WORKERS)
{ {
started = false;
is_sfn_synched = false;
cell_is_set = false;
phy_state = IDLE;
} }
bool phy::init(srslte::radio* radio_handler_, srslte::ue::tti_sync* ttisync_, log *log_h) { bool phy::init(radio* radio_handler_, mac_interface_phy *mac, log *log_h) {
return init_(radio_handler_, ttisync_, log_h, false); return init_(radio_handler_, mac, log_h, false);
} }
bool phy::init_agc(srslte::radio* radio_handler_, srslte::ue::tti_sync* ttisync_, log *log_h) { bool phy::init_agc(radio* radio_handler_, mac_interface_phy *mac, log *log_h) {
return init_(radio_handler_, ttisync_, log_h, true); return init_(radio_handler_, mac, log_h, true);
} }
bool phy::init_(radio* radio_handler_, mac_interface_phy *mac, log *log_h_, bool do_agc)
{
mlockall(MCL_CURRENT | MCL_FUTURE);
log_h = log_h_;
radio_handler = radio_handler_;
// Set default params
params_db.set_param(phy_interface_params::CELLSEARCH_TIMEOUT_PSS_NFRAMES, 100);
params_db.set_param(phy_interface_params::CELLSEARCH_TIMEOUT_PSS_CORRELATION_THRESHOLD, 160);
params_db.set_param(phy_interface_params::CELLSEARCH_TIMEOUT_MIB_NFRAMES, 100);
prach_buffer.init(&params_db, log_h);
workers_common.init(&params_db, log_h, radio_handler, mac);
sf_recv.init(radio_handler, mac, &prach_buffer, &workers_pool, &workers_common, log_h, do_agc);
// Add workers to workers pool and start threads
for (int i=0;i<NOF_WORKERS;i++) {
workers_pool.init_worker(i, &workers[i]);
workers[i].start(WORKERS_THREAD_PRIO);
workers[i].set_common(&workers_common);
}
// Start the Radio receiver thread
sf_recv.start(SF_RECV_THREAD_PRIO);
return true;
}
void phy::start_trace() void phy::start_trace()
{ {
tr_enabled = true; tr_enabled = true;
@ -73,502 +97,147 @@ void phy::write_trace(std::string filename)
void phy::tr_log_start() void phy::tr_log_start()
{ {
if (tr_enabled) { if (tr_enabled) {
tr_start_time.push_cur_time_us(get_current_tti()); tr_start_time.push_cur_time_us(sf_recv.get_current_tti());
} }
} }
void phy::tr_log_end() void phy::tr_log_end()
{ {
if (tr_enabled) { if (tr_enabled) {
tr_end_time.push_cur_time_us(get_current_tti()); tr_end_time.push_cur_time_us(sf_recv.get_current_tti());
} }
} }
bool phy::init_(srslte::radio* radio_handler_, srslte::ue::tti_sync* ttisync_, log *log_h_, bool do_agc_)
{
mlockall(MCL_CURRENT | MCL_FUTURE);
started = false;
radio_is_streaming = false;
ttisync = ttisync_;
log_h = log_h_;
radio_handler = radio_handler_;
ul_buffer_queue = new queue(NOF_ULDL_QUEUES, sizeof(ul_buffer));
dl_buffer_queue = new queue(NOF_ULDL_QUEUES, sizeof(dl_buffer));
do_agc = do_agc_;
last_gain = 1e4;
time_adv_sec = 0;
sr_tx_tti = 0;
// Set default params
params_db.set_param(phy_params::CELLSEARCH_TIMEOUT_PSS_NFRAMES, 100);
params_db.set_param(phy_params::CELLSEARCH_TIMEOUT_PSS_CORRELATION_THRESHOLD, 160);
params_db.set_param(phy_params::CELLSEARCH_TIMEOUT_MIB_NFRAMES, 100);
if (threads_new_rt_prio(&phy_thread, phy_thread_fnc, this, 2)) {
started = true;
}
return started;
}
void phy::stop() void phy::stop()
{ {
started = false; sf_recv.stop();
sf_recv.wait_thread_finish();
pthread_join(phy_thread, NULL); for (int i=0;i<NOF_WORKERS;i++) {
((phch_worker) workers[i]).free_cell();
for (int i=0;i<NOF_ULDL_QUEUES;i++) { workers[i].stop();
((ul_buffer*) ul_buffer_queue->get(i))->free_cell(); workers[i].wait_thread_finish();
((dl_buffer*) dl_buffer_queue->get(i))->free_cell();
} }
delete ul_buffer_queue;
delete dl_buffer_queue;
prach_buffer.free_cell(); prach_buffer.free_cell();
} }
radio* phy::get_radio() {
return radio_handler;
}
void phy::set_timeadv_rar(uint32_t ta_cmd) { void phy::set_timeadv_rar(uint32_t ta_cmd) {
n_ta = srslte_N_ta_new_rar(ta_cmd); n_ta = srslte_N_ta_new_rar(ta_cmd);
time_adv_sec = ((float) n_ta)*SRSLTE_LTE_TS; sf_recv.set_time_adv_sec(((float) n_ta)*SRSLTE_LTE_TS);
Info("Set TA RAR: ta_cmd: %d, n_ta: %d, ta_usec: %.1f\n", ta_cmd, n_ta, time_adv_sec*1e6); Info("Set TA RAR: ta_cmd: %d, n_ta: %d, ta_usec: %.1f\n", ta_cmd, n_ta, ((float) n_ta)*SRSLTE_LTE_TS*1e6);
} }
void phy::set_timeadv(uint32_t ta_cmd) { void phy::set_timeadv(uint32_t ta_cmd) {
n_ta = srslte_N_ta_new(n_ta, ta_cmd); n_ta = srslte_N_ta_new(n_ta, ta_cmd);
time_adv_sec = ((float) n_ta)*SRSLTE_LTE_TS; sf_recv.set_time_adv_sec(((float) n_ta)*SRSLTE_LTE_TS);
Info("Set TA: ta_cmd: %d, n_ta: %d, ta_usec: %.1f\n", ta_cmd, n_ta, time_adv_sec*1e6); Info("Set TA: ta_cmd: %d, n_ta: %d, ta_usec: %.1f\n", ta_cmd, n_ta, ((float) n_ta)*SRSLTE_LTE_TS*1e6);
}
void phy::rar_ul_grant(srslte_dci_rar_grant_t *rar, ul_sched_grant *grant)
{
uint32_t n_ho = params_db.get_param(phy_params::PUSCH_HOPPING_OFFSET);
grant->create_from_rar(rar, cell, params_db.get_param(phy_params::PUSCH_HOPPING_OFFSET));
} }
void phy::set_param(phy_params::phy_param_t param, int64_t value) { void phy::set_param(phy_interface_params::phy_param_t param, int64_t value) {
params_db.set_param((uint32_t) param, value); params_db.set_param((uint32_t) param, value);
} }
int64_t phy::get_param(phy_params::phy_param_t param) { int64_t phy::get_param(phy_interface_params::phy_param_t param) {
return params_db.get_param((uint32_t) param); return params_db.get_param((uint32_t) param);
} }
// FIXME: Add PRACH power control void phy::configure_prach_params()
bool phy::send_prach(uint32_t preamble_idx) {
return send_prach(preamble_idx, -1, 0);
}
bool phy::send_prach(uint32_t preamble_idx, int allowed_subframe) {
return send_prach(preamble_idx, allowed_subframe, 0);
}
bool phy::send_prach(uint32_t preamble_idx, int allowed_subframe, int target_power_dbm)
{
if (phy_state == RXTX) {
return prach_buffer.prepare_to_send(preamble_idx, allowed_subframe, target_power_dbm);
}
return false;
}
/* Instruct the PHY to send a SR as soon as possible */
void phy::send_sr(bool enable)
{ {
sr_enabled = enable; Info("Configuring PRACH parameters\n");
if (!enable) { if (prach_buffer.init_cell(cell)) {
sr_tx_tti = 0; Error("Configuring PRACH parameters\n");
}
}
int phy::sr_last_tx_tti() {
if (sr_enabled) {
return -1;
} else {
return (int) sr_tx_tti;
} }
} }
bool phy::cqi_is_ready_to_send(uint32_t tti) void phy::configure_ul_params()
{ {
/* Info("Configuring UL parameters\n");
if (params_db.get_param(phy_params::CQI_PERIODIC_CONFIGURED)) { for (int i=0;i<NOF_WORKERS;i++) {
if (srslte_cqi_send(params_db.get_param(phy_params::CQI_PERIODIC_PMI_IDX), tti)) { workers[i].set_ul_params();
Warning("Sending PUCCH CQI\n");
return true;
}
}
*/
return false;
}
bool phy::sr_is_ready_to_send(uint32_t tti_) {
if (sr_enabled) {
// Get I_sr parameter
uint32_t I_sr = params_db.get_param(phy_params::SR_CONFIG_INDEX);
if (srslte_ue_ul_sr_send_tti(I_sr, tti_)) {
sr_enabled = false;
sr_tx_tti = tti_;
Info("SR transmission at TTI=%d\n", tti_);
return true;
}
} }
return false;
} }
int phy::get_prach_transmitted_tti() void phy::pdcch_ul_search(srslte_rnti_type_t rnti_type, uint16_t rnti, int tti_start, int tti_end)
{ {
return prach_buffer.get_transmitted_tti(); workers_common.set_ul_rnti(rnti_type, rnti, tti_start, tti_end);
} }
// Do fast measurement on RSSI and/or PSS autocorrelation energy or PSR void phy::pdcch_dl_search(srslte_rnti_type_t rnti_type, uint16_t rnti, int tti_start, int tti_end)
bool phy::measure()
{ {
if (phy_state == IDLE) { workers_common.set_dl_rnti(rnti_type, rnti);
// capture and do measurement
}
return false;
}
void phy::set_crnti(uint16_t rnti) {
for(uint32_t i=0;i<NOF_ULDL_QUEUES;i++) {
((ul_buffer*) ul_buffer_queue->get(i))->set_crnti(rnti);
((dl_buffer*) dl_buffer_queue->get(i))->set_crnti(rnti);
}
} }
void phy::pregen_signals() void phy::prach_send(phy_interface::prach_cfg_t* cfg)
{ {
for(uint32_t i=0;i<NOF_ULDL_QUEUES;i++) {
((ul_buffer*) ul_buffer_queue->get(i))->pregen_signals(); if (prach_buffer.prepare_to_send(cfg)) {
Error("Preparing PRACH to send\n");
} }
} }
bool phy::start_rxtx() void phy::reset()
{ {
if (phy_state == IDLE) { // TODO
if (cell_is_set) {
// Set RX/TX sampling rate
radio_handler->set_rx_srate((float) srslte_sampling_freq_hz(cell.nof_prb));
radio_handler->set_tx_srate((float) srslte_sampling_freq_hz(cell.nof_prb));
phy_state = RXTX;
return true;
} else {
Error("Can not change state to RXTX: cell is not set\n");
}
} else {
Error("Can not change state to RXTX: invalid state %d\n", phy_state);
}
return false;
} }
bool phy::stop_rxtx() uint32_t phy::get_current_tti()
{ {
if (phy_state == RXTX) { return sf_recv.get_current_tti();
// Stop streaming
radio_handler->stop_rx();
phy_state = IDLE;
return true;
} else {
Error("Can not change state to RXTX: invalid state %d\n", phy_state);
}
return false;
} }
float phy::get_agc_gain() void phy::sr_send()
{ {
return 10*log10(srslte_agc_get_gain(&ue_sync.agc)); workers_common.sr_enabled = true;
}
bool phy::status_is_idle() {
return phy_state == IDLE;
}
bool phy::status_is_rxtx() {
return phy_state == RXTX;
}
uint32_t phy::get_current_tti() {
return ttisync->get_producer_cntr();
}
uint32_t phy::tti_to_SFN(uint32_t tti) {
return tti/10;
}
uint32_t phy::tti_to_subf(uint32_t tti) {
return tti%10;
}
void* phy::phy_thread_fnc(void *arg) {
phy* phy = static_cast<srslte::ue::phy*>(arg);
phy->main_radio_loop();
return NULL;
} }
int radio_recv_wrapper_cs(void *h,void *data, uint32_t nsamples, srslte_timestamp_t *rx_time) bool phy::status_is_sync()
{ {
radio *radio_handler = (radio*) h; return sf_recv.status_is_sync();
int n = radio_handler->rx_now(data, nsamples, rx_time);
return n;
} }
double callback_set_rx_gain(void *h, double gain) { void phy::sync_start()
radio *radio_handler = (radio*) h;
return radio_handler->set_rx_gain_th(gain);
}
bool phy::set_cell(srslte_cell_t cell_) {
if (phy_state == IDLE) {
cell_is_set = false;
cell = cell_;
if (!srslte_ue_mib_init(&ue_mib, cell))
{
if (!srslte_ue_sync_init(&ue_sync, cell, radio_recv_wrapper_cs, radio_handler))
{
if (do_agc) {
srslte_ue_sync_start_agc(&ue_sync, callback_set_rx_gain, last_gain);
}
srslte_ue_sync_set_cfo(&ue_sync, cellsearch_cfo);
for(uint32_t i=0;i<NOF_ULDL_QUEUES;i++) {
((ul_buffer*) ul_buffer_queue->get(i))->init_cell(cell, &params_db, log_h, radio_handler);
((dl_buffer*) dl_buffer_queue->get(i))->init_cell(cell, &params_db, log_h);
((dl_buffer*) dl_buffer_queue->get(i))->buffer_id = i;
((ul_buffer*) ul_buffer_queue->get(i))->ready();
((dl_buffer*) dl_buffer_queue->get(i))->release();
}
cell_is_set = true;
} else {
Error("Error setting cell: initiating ue_sync");
}
} else {
Error("Error setting cell: initiating ue_mib\n");
}
} else {
Error("Error setting cell: Invalid state %d\n", phy_state);
}
return cell_is_set;
}
bool phy::init_prach() {
return prach_buffer.init_cell(cell, &params_db, log_h);
}
ul_buffer* phy::get_ul_buffer(uint32_t tti)
{ {
tti=tti%10240; sf_recv.sync_start();
if (tti + 1 < get_current_tti() && tti > NOF_ULDL_QUEUES) {
Warning("Warning access to PHY UL buffer too late. Requested TTI=%d while PHY is in %d\n", tti, get_current_tti());
}
return (ul_buffer*) ul_buffer_queue->get(tti);
} }
ul_buffer* phy::get_ul_buffer_adv(uint32_t tti) void phy::sync_stop()
{ {
return (ul_buffer*) ul_buffer_queue->get(tti + ul_buffer::tx_advance_sf); sf_recv.sync_stop();
} }
dl_buffer* phy::get_dl_buffer(uint32_t tti) void phy::set_rar_grant(uint32_t tti, uint8_t grant_payload[SRSLTE_RAR_GRANT_LEN])
{ {
tti=tti%10240; workers_common.set_rar_grant(tti, grant_payload);
if (tti + 4 < get_current_tti()) {
Warning("Warning access to PHY DL buffer too late. Requested TTI=%d while PHY is in %d\n", tti, get_current_tti());
// return NULL;
}
return (dl_buffer*) dl_buffer_queue->get(tti);
}
bool phy::decode_mib(uint32_t N_id_2, srslte_cell_t *cell, uint8_t payload[SRSLTE_BCH_PAYLOAD_LEN]) {
return decode_mib_N_id_2((int) N_id_2, cell, payload);
} }
bool phy::decode_mib_best(srslte_cell_t *cell, uint8_t payload[SRSLTE_BCH_PAYLOAD_LEN]) { void phy::set_crnti(uint16_t rnti) {
return decode_mib_N_id_2(-1, cell, payload); for(uint32_t i=0;i<NOF_WORKERS;i++) {
((phch_worker) workers[i]).set_crnti(rnti);
}
} }
bool phy::decode_mib_N_id_2(int force_N_id_2, srslte_cell_t *cell_ptr, uint8_t bch_payload[SRSLTE_BCH_PAYLOAD_LEN]) void phy::enable_pregen_signals(bool enable)
{ {
srslte_ue_cellsearch_result_t found_cells[3]; for(uint32_t i=0;i<NOF_WORKERS;i++) {
srslte_ue_cellsearch_t cs; ((phch_worker) workers[i]).enable_pregen_signals(enable);
bzero(found_cells, 3*sizeof(srslte_ue_cellsearch_result_t));
if (srslte_ue_cellsearch_init(&cs, radio_recv_wrapper_cs, radio_handler)) {
return false;
}
if (do_agc) {
srslte_ue_sync_start_agc(&cs.ue_sync, callback_set_rx_gain, last_gain);
}
srslte_ue_cellsearch_set_nof_frames_to_scan(&cs, params_db.get_param(phy_params::CELLSEARCH_TIMEOUT_PSS_NFRAMES));
srslte_ue_cellsearch_set_threshold(&cs, (float)
params_db.get_param(phy_params::CELLSEARCH_TIMEOUT_PSS_CORRELATION_THRESHOLD)/10);
radio_handler->set_rx_srate(1920000.0);
radio_handler->start_rx();
/* Find a cell in the given N_id_2 or go through the 3 of them to find the strongest */
uint32_t max_peak_cell = 0;
int ret = SRSLTE_ERROR;
if (force_N_id_2 >= 0 && force_N_id_2 < 3) {
ret = srslte_ue_cellsearch_scan_N_id_2(&cs, force_N_id_2, &found_cells[force_N_id_2]);
max_peak_cell = force_N_id_2;
} else {
ret = srslte_ue_cellsearch_scan(&cs, found_cells, &max_peak_cell);
}
last_gain = srslte_agc_get_gain(&cs.ue_sync.agc);
radio_handler->stop_rx();
srslte_ue_cellsearch_free(&cs);
if (ret < 0) {
Error("Error decoding MIB: Error searching PSS\n");
return false;
} else if (ret == 0) {
Error("Error decoding MIB: Could not find any PSS in this frequency\n");
return false;
}
// Save result
cell_ptr->id = found_cells[max_peak_cell].cell_id;
cell_ptr->cp = found_cells[max_peak_cell].cp;
cellsearch_cfo = found_cells[max_peak_cell].cfo;
Info("\nFound CELL ID: %d CP: %s, CFO: %f\n", cell_ptr->id, srslte_cp_string(cell_ptr->cp), cellsearch_cfo);
srslte_ue_mib_sync_t ue_mib_sync;
if (srslte_ue_mib_sync_init(&ue_mib_sync, cell_ptr->id, cell_ptr->cp, radio_recv_wrapper_cs, radio_handler)) {
return false;
} }
}
if (do_agc) {
srslte_ue_sync_start_agc(&ue_mib_sync.ue_sync, callback_set_rx_gain, last_gain);
}
/* Find and decode MIB */
uint32_t sfn, sfn_offset;
radio_handler->start_rx();
ret = srslte_ue_mib_sync_decode(&ue_mib_sync, params_db.get_param(phy_params::CELLSEARCH_TIMEOUT_MIB_NFRAMES),
bch_payload, &cell_ptr->nof_ports, &sfn_offset);
radio_handler->stop_rx();
last_gain = srslte_agc_get_gain(&ue_mib_sync.ue_sync.agc);
srslte_ue_mib_sync_free(&ue_mib_sync);
uint32_t phy::tti_to_SFN(uint32_t tti) {
return tti/10;
}
if (ret == 1) { uint32_t phy::tti_to_subf(uint32_t tti) {
srslte_pbch_mib_unpack(bch_payload, cell_ptr, NULL); return tti%10;
return true;
} else {
Warning("Error decoding MIB: Error decoding PBCH\n");
return false;
}
} }
int phy::sync_sfn(void) {
cf_t *sf_buffer = NULL;
int ret = SRSLTE_ERROR;
uint8_t bch_payload[SRSLTE_BCH_PAYLOAD_LEN];
srslte_ue_sync_decode_sss_on_track(&ue_sync, true);
ret = srslte_ue_sync_get_buffer(&ue_sync, &sf_buffer);
if (ret < 0) {
Error("Error calling ue_sync_get_buffer");
return -1;
}
if (ret == 1) {
if (srslte_ue_sync_get_sfidx(&ue_sync) == 0) {
uint32_t sfn_offset=0;
srslte_pbch_decode_reset(&ue_mib.pbch);
int n = srslte_ue_mib_decode(&ue_mib, sf_buffer, bch_payload, NULL, &sfn_offset);
if (n < 0) {
Error("Error decoding MIB while synchronising SFN");
return -1;
} else if (n == SRSLTE_UE_MIB_FOUND) {
uint32_t sfn;
srslte_pbch_mib_unpack(bch_payload, &cell, &sfn);
sfn = (sfn + sfn_offset)%1024;
ttisync->set_producer_cntr(10*sfn+1);
srslte_ue_sync_decode_sss_on_track(&ue_sync, false);
return 1;
}
}
}
return 0;
}
void phy::run_rx_tx_state()
{
int ret;
if (!is_sfn_synched) {
if (!radio_is_streaming) {
// Start streaming
radio_handler->start_rx();
radio_is_streaming = true;
}
ret = sync_sfn();
switch(ret) {
default:
phy_state = IDLE;
break;
case 1:
is_sfn_synched = true;
is_first_of_burst = true;
break;
case 0:
break;
}
} else {
uint32_t current_tti = ttisync->get_producer_cntr();
log_h->step(current_tti);
float cfo = srslte_ue_sync_get_cfo(&ue_sync)/15000;
srslte_timestamp_add(&last_rx_time, 0, 1e-3);
/* Set CFO and next TX time for UL buffer for TTI+4 */
get_ul_buffer(current_tti+4)->set_tx_params(cfo, time_adv_sec, last_rx_time);
// Every subframe, TX a PRACH or a PUSCH/PUCCH
if (prach_buffer.is_ready_to_send(current_tti)) {
// send prach if we have to
prach_buffer.send(radio_handler, cfo, last_rx_time);
radio_handler->tx_end();
}
// Receive alligned buffer for the current tti
tr_log_end();
get_dl_buffer(current_tti)->recv_ue_sync(&ue_sync, &last_rx_time);
tr_log_start();
ttisync->increase();
}
}
void phy::main_radio_loop() {
while(started) {
switch(phy_state) {
case IDLE:
usleep(50000);
break;
case RXTX:
run_rx_tx_state();
break;
}
}
}
} }

@ -33,7 +33,7 @@
#include "srsapps/common/log.h" #include "srsapps/common/log.h"
#include "srsapps/ue/phy/prach.h" #include "srsapps/ue/phy/prach.h"
#include "srsapps/ue/phy/phy.h" #include "srsapps/ue/phy/phy.h"
#include "srsapps/ue/phy/phy_params.h" #include "srsapps/common/phy_interface.h"
namespace srslte { namespace srslte {
namespace ue { namespace ue {
@ -55,17 +55,21 @@ void prach::free_cell()
} }
} }
bool prach::init_cell(srslte_cell_t cell_, phy_params *params_db_, log *log_h_) void prach::init(phy_params* params_db_, log* log_h_)
{ {
cell = cell_;
log_h = log_h_; log_h = log_h_;
params_db = params_db_; params_db = params_db_;
}
bool prach::init_cell(srslte_cell_t cell_)
{
cell = cell_;
preamble_idx = -1; preamble_idx = -1;
if (srslte_prach_init(&prach_obj, srslte_symbol_sz(cell.nof_prb), if (srslte_prach_init(&prach_obj, srslte_symbol_sz(cell.nof_prb),
srslte_prach_get_preamble_format(params_db->get_param(phy_params::PRACH_CONFIG_INDEX)), srslte_prach_get_preamble_format(params_db->get_param(phy_interface_params::PRACH_CONFIG_INDEX)),
params_db->get_param(phy_params::PRACH_ROOT_SEQ_IDX), params_db->get_param(phy_interface_params::PRACH_ROOT_SEQ_IDX),
params_db->get_param(phy_params::PRACH_HIGH_SPEED_FLAG)?true:false, params_db->get_param(phy_interface_params::PRACH_HIGH_SPEED_FLAG)?true:false,
params_db->get_param(phy_params::PRACH_ZC_CONFIG))) { params_db->get_param(phy_interface_params::PRACH_ZC_CONFIG))) {
return false; return false;
} }
@ -75,7 +79,7 @@ bool prach::init_cell(srslte_cell_t cell_, phy_params *params_db_, log *log_h_)
if(!buffer[i]) { if(!buffer[i]) {
return false; return false;
} }
if(srslte_prach_gen(&prach_obj, i, params_db->get_param(phy_params::PRACH_FREQ_OFFSET), buffer[i])) { if(srslte_prach_gen(&prach_obj, i, params_db->get_param(phy_interface_params::PRACH_FREQ_OFFSET), buffer[i])) {
return false; return false;
} }
} }
@ -86,13 +90,16 @@ bool prach::init_cell(srslte_cell_t cell_, phy_params *params_db_, log *log_h_)
return initiated; return initiated;
} }
bool prach::prepare_to_send(uint32_t preamble_idx_) { bool prach::prepare_to_send(phy_interface::prach_cfg_t* cfg)
return prepare_to_send(preamble_idx_, -1, 0); {
} int allowed_sf = cfg->allowed_subframe_enabled?(int) cfg->allowed_subframe:-1;
bool prach::prepare_to_send(uint32_t preamble_idx_, int allowed_subframe_) { bool ret = prepare_to_send(cfg->preamble_idx, allowed_sf, cfg->target_power_dbm);
return prepare_to_send(preamble_idx_, allowed_subframe_, 0); if (ret) {
memcpy(&prach_cfg, cfg, sizeof(phy_interface::prach_cfg_t));
}
} }
bool prach::prepare_to_send(uint32_t preamble_idx_, int allowed_subframe_, int target_power_dbm)
bool prach::prepare_to_send(uint32_t preamble_idx_, int allowed_subframe_, float target_power_dbm)
{ {
if (initiated && preamble_idx_ < 64) { if (initiated && preamble_idx_ < 64) {
preamble_idx = preamble_idx_; preamble_idx = preamble_idx_;
@ -109,7 +116,7 @@ bool prach::is_ready_to_send(uint32_t current_tti_) {
if (initiated && preamble_idx >= 0 && preamble_idx < 64 && params_db != NULL) { if (initiated && preamble_idx >= 0 && preamble_idx < 64 && params_db != NULL) {
// consider the number of subframes the transmission must be anticipated // consider the number of subframes the transmission must be anticipated
uint32_t current_tti = (current_tti_ + tx_advance_sf)%10240; uint32_t current_tti = (current_tti_ + tx_advance_sf)%10240;
uint32_t config_idx = (uint32_t) params_db->get_param(phy_params::PRACH_CONFIG_INDEX); uint32_t config_idx = (uint32_t) params_db->get_param(phy_interface_params::PRACH_CONFIG_INDEX);
if (srslte_prach_send_tti(config_idx, current_tti, allowed_subframe)) { if (srslte_prach_send_tti(config_idx, current_tti, allowed_subframe)) {
Info("PRACH Buffer: Ready to send at tti: %d (now is %d)\n", current_tti, current_tti_); Info("PRACH Buffer: Ready to send at tti: %d (now is %d)\n", current_tti, current_tti_);
transmitted_tti = current_tti; transmitted_tti = current_tti;
@ -119,11 +126,16 @@ bool prach::is_ready_to_send(uint32_t current_tti_) {
return false; return false;
} }
int prach::get_transmitted_tti() { void prach::get_rar_cfg(uint16_t *rar_rnti, uint32_t *tti_start, uint32_t *tti_end)
if (initiated) { {
return transmitted_tti; if (rar_rnti) {
} else { *rar_rnti = prach_cfg.rar_rnti;
return -1; }
if (tti_start) {
*tti_start = transmitted_tti + prach_cfg.rar_start;
}
if (tti_end) {
*tti_end = transmitted_tti + prach_cfg.rar_start + prach_cfg.rar_window;
} }
} }
@ -137,18 +149,13 @@ bool prach::send(radio *radio_handler, float cfo, srslte_timestamp_t rx_time)
// Correct CFO before transmission // Correct CFO before transmission
srslte_cfo_correct(&cfo_h, buffer[preamble_idx], signal_buffer, cfo /srslte_symbol_sz(cell.nof_prb)); srslte_cfo_correct(&cfo_h, buffer[preamble_idx], signal_buffer, cfo /srslte_symbol_sz(cell.nof_prb));
// Compute peak // Normalize signal amplitude
float max = 0; srslte_vec_norm_cfc(signal_buffer, 0.9, signal_buffer, len);
float *t = (float*) signal_buffer;
for (int i=0;i<2*len;i++) {
if (fabsf(t[i]) > max) {
max = fabsf(t[i]);
}
}
radio_handler->tx(signal_buffer, len, tx_time); radio_handler->tx(signal_buffer, len, tx_time);
Debug("PRACH transmitted CFO: %f, preamble=%d, len=%d rx_time=%f, tx_time=%f, PeakAmplitude=%.2f\n",
cfo*15000, preamble_idx, len, rx_time.frac_secs, tx_time.frac_secs, max); Debug("PRACH transmitted CFO: %f, preamble=%d, len=%d rx_time=%f, tx_time=%f\n",
cfo*15000, preamble_idx, len, rx_time.frac_secs, tx_time.frac_secs);
preamble_idx = -1; preamble_idx = -1;
} }

@ -1,344 +0,0 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2014 The srsLTE Developers. See the
* COPYRIGHT file at the top-level directory of this distribution.
*
* \section LICENSE
*
* This file is part of the srsLTE library.
*
* srsLTE is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* srsLTE 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 Lesser General Public License for more details.
*
* A copy of the GNU Lesser 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 <string.h>
#include <strings.h>
#include <pthread.h>
#include <math.h>
#include "srslte/srslte.h"
#include "srsapps/common/log.h"
#include "srsapps/ue/phy/sched_grant.h"
#include "srsapps/ue/phy/ul_buffer.h"
#include "srsapps/ue/phy/phy.h"
#include "srsapps/ue/phy/phy_params.h"
namespace srslte {
namespace ue {
bool ul_buffer::init_cell(srslte_cell_t cell_, phy_params *params_db_, log *log_h_, radio *radio_h_) {
cell = cell_;
log_h = log_h_;
radio_h = radio_h_;
params_db = params_db_;
current_tx_nb = 0;
if (!srslte_ue_ul_init(&ue_ul, cell)) {
srslte_ue_ul_set_normalization(&ue_ul, false);
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, true);
bzero(&uci_data, sizeof(srslte_uci_data_t));
uci_pending = false;
return cell_initiated;
} else {
return false;
}
}
void ul_buffer::free_cell() {
if (cell_initiated) {
if (signal_buffer) {
free(signal_buffer);
}
srslte_ue_ul_free(&ue_ul);
}
}
void ul_buffer::set_crnti(uint16_t rnti)
{
srslte_ue_ul_set_rnti(&ue_ul, rnti);
}
void ul_buffer::pregen_signals()
{
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(phy_params::PUSCH_BETA)/10;
bool group_hopping_en = params_db->get_param(phy_params::DMRS_GROUP_HOPPING_EN);
bool sequence_hopping_en = params_db->get_param(phy_params::DMRS_SEQUENCE_HOPPING_EN);
dmrs_cfg.cyclic_shift = params_db->get_param(phy_params::PUSCH_RS_CYCLIC_SHIFT);
dmrs_cfg.delta_ss = params_db->get_param(phy_params::PUSCH_RS_GROUP_ASSIGNMENT);
srslte_refsignal_srs_cfg_t srs_cfg;
bzero(&srs_cfg, sizeof(srslte_refsignal_srs_cfg_t));
srs_cfg.configured = params_db->get_param(phy_params::SRS_IS_CONFIGURED)?true:false;
srs_cfg.subframe_config = (uint32_t) params_db->get_param(phy_params::SRS_CS_SFCFG);
srs_cfg.bw_cfg = (uint32_t) params_db->get_param(phy_params::SRS_CS_BWCFG);
srs_cfg.I_srs = (uint32_t) params_db->get_param(phy_params::SRS_UE_CONFIGINDEX);
srs_cfg.B = (uint32_t) params_db->get_param(phy_params::SRS_UE_BW);
srs_cfg.b_hop = (uint32_t) params_db->get_param(phy_params::SRS_UE_HOP);
srs_cfg.n_rrc = (uint32_t) params_db->get_param(phy_params::SRS_UE_NRRC);
srs_cfg.k_tc = (uint32_t) params_db->get_param(phy_params::SRS_UE_TXCOMB);
srs_cfg.n_srs = (uint32_t) params_db->get_param(phy_params::SRS_UE_CYCLICSHIFT);
srs_cfg.beta_srs = ((float) params_db->get_param(phy_params::SRS_BETA))/10;
srslte_ue_ul_set_cfg(&ue_ul, &dmrs_cfg, NULL, &srs_cfg, NULL, group_hopping_en, sequence_hopping_en);
srslte_ue_ul_pregen_signals(&ue_ul);
}
bool ul_buffer::generate_ack(bool ack, dl_sched_grant *last_dl_grant)
{
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_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;
}
void ul_buffer::set_current_tx_nb(uint32_t current_tx_nb_)
{
current_tx_nb = current_tx_nb_;
}
bool ul_buffer::generate_cqi_report()
{
uci_data.uci_cqi_len = 4;
uint8_t cqi[4] = {1, 1, 1, 1};
uci_data.uci_cqi = cqi;
return true;
}
bool ul_buffer::generate_sr() {
uci_data.scheduling_request = true;
uci_pending = true;
return true;
}
bool ul_buffer::uci_ready() {
return uci_pending;
}
bool ul_buffer::generate_data() {
return generate_data(NULL, NULL);
}
bool ul_buffer::generate_data(ul_sched_grant *grant,
uint8_t *payload)
{
return generate_data(grant, &ue_ul.softbuffer, payload);
}
//int nof_tx=0;
bool ul_buffer::srs_is_ready_to_send() {
if (params_db->get_param(phy_params::SRS_IS_CONFIGURED))
{
if (srslte_refsignal_srs_send_cs(params_db->get_param(phy_params::SRS_CS_SFCFG), tti%10) == 1 &&
srslte_refsignal_srs_send_ue(params_db->get_param(phy_params::SRS_UE_CONFIGINDEX), tti) == 1)
{
return true;
}
}
return false;
}
int srspkt = 0;
bool ul_buffer::generate_data(ul_sched_grant *grant, srslte_softbuffer_tx_t *softbuffer, uint8_t *payload)
{
if (is_ready()) {
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(phy_params::PUSCH_BETA)/10;
bool group_hopping_en = params_db->get_param(phy_params::DMRS_GROUP_HOPPING_EN);
bool sequence_hopping_en = params_db->get_param(phy_params::DMRS_SEQUENCE_HOPPING_EN);
dmrs_cfg.cyclic_shift = params_db->get_param(phy_params::PUSCH_RS_CYCLIC_SHIFT);
dmrs_cfg.delta_ss = params_db->get_param(phy_params::PUSCH_RS_GROUP_ASSIGNMENT);
srslte_pusch_hopping_cfg_t pusch_hopping;
if (grant) {
bzero(&pusch_hopping, sizeof(srslte_pusch_hopping_cfg_t));
pusch_hopping.n_sb = params_db->get_param(phy_params::PUSCH_HOPPING_N_SB);
pusch_hopping.hop_mode = params_db->get_param(phy_params::PUSCH_HOPPING_INTRA_SF) ?
pusch_hopping.SRSLTE_PUSCH_HOP_MODE_INTRA_SF :
pusch_hopping.SRSLTE_PUSCH_HOP_MODE_INTER_SF;
pusch_hopping.hopping_offset = params_db->get_param(phy_params::PUSCH_HOPPING_OFFSET);
pusch_hopping.current_tx_nb = grant->get_current_tx_nb();
}
srslte_pucch_cfg_t pucch_cfg;
bzero(&pucch_cfg, sizeof(srslte_pucch_cfg_t));
pucch_cfg.beta_pucch = (float) params_db->get_param(phy_params::PUCCH_BETA)/10;
pucch_cfg.delta_pucch_shift = params_db->get_param(phy_params::PUCCH_DELTA_SHIFT);
pucch_cfg.N_cs = params_db->get_param(phy_params::PUCCH_CYCLIC_SHIFT);
pucch_cfg.n_rb_2 = params_db->get_param(phy_params::PUCCH_N_RB_2);
pucch_cfg.srs_configured = params_db->get_param(phy_params::SRS_IS_CONFIGURED)?true:false;
pucch_cfg.srs_cs_subf_cfg = (uint32_t) params_db->get_param(phy_params::SRS_CS_SFCFG);
pucch_cfg.srs_simul_ack = params_db->get_param(phy_params::SRS_CS_ACKNACKSIMUL)?true:false;
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(phy_params::PUCCH_N_PUCCH_1_0);
pucch_sched.n_pucch_1[1] = params_db->get_param(phy_params::PUCCH_N_PUCCH_1_1);
pucch_sched.n_pucch_1[2] = params_db->get_param(phy_params::PUCCH_N_PUCCH_1_2);
pucch_sched.n_pucch_1[3] = params_db->get_param(phy_params::PUCCH_N_PUCCH_1_3);
pucch_sched.N_pucch_1 = params_db->get_param(phy_params::PUCCH_N_PUCCH_1);
pucch_sched.n_pucch_2 = params_db->get_param(phy_params::PUCCH_N_PUCCH_2);
pucch_sched.n_pucch_sr = params_db->get_param(phy_params::PUCCH_N_PUCCH_SR);
srslte_refsignal_srs_cfg_t srs_cfg;
bzero(&srs_cfg, sizeof(srslte_refsignal_srs_cfg_t));
srs_cfg.configured = params_db->get_param(phy_params::SRS_IS_CONFIGURED)?true:false;
srs_cfg.subframe_config = (uint32_t) params_db->get_param(phy_params::SRS_CS_SFCFG);
srs_cfg.bw_cfg = (uint32_t) params_db->get_param(phy_params::SRS_CS_BWCFG);
srs_cfg.I_srs = (uint32_t) params_db->get_param(phy_params::SRS_UE_CONFIGINDEX);
srs_cfg.B = (uint32_t) params_db->get_param(phy_params::SRS_UE_BW);
srs_cfg.b_hop = (uint32_t) params_db->get_param(phy_params::SRS_UE_HOP);
srs_cfg.n_rrc = (uint32_t) params_db->get_param(phy_params::SRS_UE_NRRC);
srs_cfg.k_tc = (uint32_t) params_db->get_param(phy_params::SRS_UE_TXCOMB);
srs_cfg.n_srs = (uint32_t) params_db->get_param(phy_params::SRS_UE_CYCLICSHIFT);
srs_cfg.beta_srs = ((float) params_db->get_param(phy_params::SRS_BETA))/10;
srslte_ue_ul_set_cfg(&ue_ul, &dmrs_cfg, &pucch_cfg, &srs_cfg, &pucch_sched,
group_hopping_en, sequence_hopping_en);
uci_data.I_offset_ack = params_db->get_param(phy_params::UCI_I_OFFSET_ACK);
uci_data.I_offset_cqi = params_db->get_param(phy_params::UCI_I_OFFSET_CQI);
uci_data.I_offset_ri = params_db->get_param(phy_params::UCI_I_OFFSET_RI);
srslte_ue_ul_set_cfo(&ue_ul, cfo);
int n = 0;
// Transmit on PUSCH if UL grant available, otherwise in PUCCH
if (grant) {
if (params_db->get_param(phy_params::CQI_PERIODIC_CONFIGURED)) {
if (srslte_cqi_send(params_db->get_param(phy_params::CQI_PERIODIC_PMI_IDX), tti)) {
generate_cqi_report();
}
}
srslte_pusch_hopping_cfg_t pusch_hopping_cfg;
bzero(&pusch_hopping_cfg, sizeof(srslte_pusch_hopping_cfg_t));
pusch_hopping_cfg.n_sb = params_db->get_param(phy_params::PUSCH_HOPPING_N_SB);
pusch_hopping_cfg.hop_mode = params_db->get_param(phy_params::PUSCH_HOPPING_INTRA_SF) ?
srslte_pusch_hopping_cfg_t::SRSLTE_PUSCH_HOP_MODE_INTRA_SF :
srslte_pusch_hopping_cfg_t::SRSLTE_PUSCH_HOP_MODE_INTER_SF;
pusch_hopping_cfg.hopping_offset = params_db->get_param(phy_params::PUSCH_HOPPING_OFFSET);
pusch_hopping_cfg.current_tx_nb = grant->get_current_tx_nb();
grant->to_pusch_cfg(&pusch_hopping_cfg, &srs_cfg, tti, &ue_ul);
n = srslte_ue_ul_pusch_encode_rnti_softbuffer(&ue_ul,
payload, uci_data,
softbuffer,
grant->get_rnti(),
signal_buffer);
if (ue_ul.pusch.shortened) {
Info("PUSCH shortened on tti=%d\n", tti);
}
Info("PUSCH: TTI=%d, CFO= %.1f KHz TBS=%d, mod=%s, rb_start=%d n_prb=%d, ack=%s, sr=%s, rnti=%d, shortened=%s\n",
tti, cfo*15e3, grant->get_tbs(), srslte_mod_string(ue_ul.pusch_cfg.grant.mcs.mod), ue_ul.pusch_cfg.grant.n_prb[0],
ue_ul.pusch_cfg.grant.L_prb,
uci_data.uci_ack_len>0?(uci_data.uci_ack?"1":"0"):"no",uci_data.scheduling_request?"yes":"no",
grant->get_rnti(), ue_ul.pusch.shortened?"yes":"no");
} else if (uci_data.scheduling_request || uci_data.uci_cqi_len > 0 || uci_data.uci_ack_len) {
n = srslte_ue_ul_pucch_encode(&ue_ul, uci_data, tti, signal_buffer);
Info("PUCCH: TTI=%d, CFO= %.1f KHz n_cce=%d, ack=%s, sr=%s, shortened=%s\n", tti, cfo*15e3, last_n_cce,
uci_data.uci_ack_len>0?(uci_data.uci_ack?"1":"0"):"no",uci_data.scheduling_request?"yes":"no",
ue_ul.pucch.shortened?"yes":"no");
} else {
n = srslte_ue_ul_srs_encode(&ue_ul, tti, signal_buffer);
Info("SRS: TTI=%d, CFO= %.1f KHz \n", tti, cfo*15e3);
}
// Reset UCI data
bzero(&uci_data, sizeof(srslte_uci_data_t));
uci_pending = false;
// Compute peak
float max = 0;
if (normalize_amp) {
float *t = (float*) signal_buffer;
for (int i=0;i<2*SRSLTE_SF_LEN_PRB(cell.nof_prb);i++) {
if (fabsf(t[i]) > max) {
max = fabsf(t[i]);
}
}
// Normalize before TX
srslte_vec_sc_prod_cfc(signal_buffer, 0.9/max, signal_buffer, SRSLTE_SF_LEN_PRB(cell.nof_prb));
}
release();
if (n < 0) {
fprintf(stderr, "Error in UL buffer: Error encoding %s\n", signal_buffer?"PUSCH":"PUCCH");
return false;
} else {
return true;
}
} else {
fprintf(stderr, "Error in UL buffer: buffer not released\n");
return false;
}
}
int nof_tx = 0;
void ul_buffer::set_tx_params(float cfo_, float time_adv_sec, srslte_timestamp_t tx_time_)
{
cfo = cfo_;
srslte_timestamp_copy(&tx_time, &tx_time_);
srslte_timestamp_add(&tx_time, 0, 4e-3 - time_adv_sec); // UL buffer is configured for tti+4
}
void ul_buffer::send() {
radio_h->tx(signal_buffer, SRSLTE_SF_LEN_PRB(cell.nof_prb), tx_time);
Info("TX TTI=%d\n", tti);
}
void ul_buffer::send_end_of_burst()
{
Info("TTI %d sending end of burst\n", tti);
radio_h->tx_end();
}
} // namespace ue
} // namespace srslte

@ -24,6 +24,6 @@ IF(UHD_FOUND)
ADD_EXECUTABLE(ue_itf_test_sib1 ue_itf_test_sib1.cc) ADD_EXECUTABLE(ue_itf_test_sib1 ue_itf_test_sib1.cc)
TARGET_LINK_LIBRARIES(ue_itf_test_sib1 srsapps_common srsapps_ue_phy srsapps_radio srslte srslte_uhd) TARGET_LINK_LIBRARIES(ue_itf_test_sib1 srsapps_common srsapps_ue_phy srsapps_radio srslte srslte_uhd)
ADD_EXECUTABLE(ue_itf_test_prach ue_itf_test_prach.cc) # ADD_EXECUTABLE(ue_itf_test_prach ue_itf_test_prach.cc)
TARGET_LINK_LIBRARIES(ue_itf_test_prach srsapps_common srsapps_ue_phy srsapps_radio srslte srslte_uhd) # TARGET_LINK_LIBRARIES(ue_itf_test_prach srsapps_common srsapps_ue_phy srsapps_radio srslte srslte_uhd)
ENDIF(UHD_FOUND) ENDIF(UHD_FOUND)

@ -30,18 +30,21 @@
#include "srslte/utils/debug.h" #include "srslte/utils/debug.h"
#include "srsapps/ue/phy/phy.h" #include "srsapps/ue/phy/phy.h"
#include "srsapps/common/log_stdout.h" #include "srsapps/common/log_stdout.h"
#include "srsapps/common/tti_sync_cv.h" #include "srsapps/common/mac_interface.h"
#include "srsapps/radio/radio_uhd.h" #include "srsapps/radio/radio_uhd.h"
/********************************************************************** /**********************************************************************
* Program arguments processing * Program arguments processing
***********************************************************************/ ***********************************************************************/
typedef struct { typedef struct {
float uhd_freq; float uhd_freq;
float uhd_gain; float uhd_gain;
}prog_args_t; }prog_args_t;
prog_args_t prog_args;
void args_default(prog_args_t *args) { void args_default(prog_args_t *args) {
args->uhd_freq = -1.0; args->uhd_freq = -1.0;
args->uhd_gain = -1.0; args->uhd_gain = -1.0;
@ -79,13 +82,37 @@ void parse_args(prog_args_t *args, int argc, char **argv) {
} }
/******** MAC Interface implementation */
class testmac : public srslte::ue::mac_interface_phy
{
public:
void new_grant_ul(mac_grant_t grant, uint8_t *payload_ptr, tb_action_ul_t *action) {
printf("New grant UL\n");
}
void new_grant_ul_ack(mac_grant_t grant, uint8_t *payload_ptr, bool ack, tb_action_ul_t *action) {
printf("New grant UL ACK\n");
}
void harq_recv(uint32_t tti, bool ack, tb_action_ul_t *action) {
printf("harq recv\n");
}
void new_grant_dl(mac_grant_t grant, tb_action_dl_t *action) {
printf("New grant DL\n");
}
void tb_decoded_ok(uint32_t harq_pid) {
printf("TB decoded OK\n");
}
void bch_decoded_ok(uint8_t *payload) {
printf("BCH decoded\n");
}
};
srslte::ue::phy phy; #ifdef kk
prog_args_t prog_args;
uint32_t total_pkts=0; uint32_t total_pkts=0;
uint32_t total_dci=0; uint32_t total_dci=0;
@ -94,7 +121,6 @@ uint8_t payload[1024];
// This is the MAC implementation // This is the MAC implementation
void run_tti(uint32_t tti) { void run_tti(uint32_t tti) {
srslte::ue::dl_sched_grant grant(SRSLTE_SIRNTI);
INFO("MAC running tti: %d\n", tti); INFO("MAC running tti: %d\n", tti);
// SIB1 is scheduled in subframe #5 of even frames // SIB1 is scheduled in subframe #5 of even frames
@ -127,12 +153,14 @@ void run_tti(uint32_t tti) {
total_pkts, gain); total_pkts, gain);
} }
} }
#endif
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
srslte::ue::phy phy;
testmac mac;
srslte_cell_t cell; srslte_cell_t cell;
uint8_t bch_payload[SRSLTE_BCH_PAYLOAD_LEN]; uint8_t bch_payload[SRSLTE_BCH_PAYLOAD_LEN];
srslte::ue::tti_sync_cv ttisync(10240);
srslte::radio_uhd radio_uhd; srslte::radio_uhd radio_uhd;
srslte::log_stdout log("PHY"); srslte::log_stdout log("PHY");
@ -142,46 +170,28 @@ int main(int argc, char *argv[])
if (prog_args.uhd_gain > 0) { if (prog_args.uhd_gain > 0) {
radio_uhd.init(); radio_uhd.init();
radio_uhd.set_rx_gain(prog_args.uhd_gain); radio_uhd.set_rx_gain(prog_args.uhd_gain);
phy.init(&radio_uhd, &ttisync, &log); phy.init(&radio_uhd, &mac, &log);
} else { } else {
radio_uhd.init_agc(); radio_uhd.init_agc();
phy.init_agc(&radio_uhd, &ttisync, &log); phy.init_agc(&radio_uhd, &mac, &log);
} }
// Give it time to create thread // Give it time to create thread
sleep(1); sleep(1);
// Set default parameters // Set default parameters
phy.set_param(srslte::ue::phy_params::PRACH_CONFIG_INDEX, 0); phy.set_param(srslte::ue::phy_interface_params::PRACH_CONFIG_INDEX, 0);
phy.set_param(srslte::ue::phy_params::PRACH_ROOT_SEQ_IDX, 0); phy.set_param(srslte::ue::phy_interface_params::PRACH_ROOT_SEQ_IDX, 0);
phy.set_param(srslte::ue::phy_params::PRACH_HIGH_SPEED_FLAG, 0); phy.set_param(srslte::ue::phy_interface_params::PRACH_HIGH_SPEED_FLAG, 0);
phy.set_param(srslte::ue::phy_params::PRACH_ZC_CONFIG, 1); phy.set_param(srslte::ue::phy_interface_params::PRACH_ZC_CONFIG, 1);
// Set RX freq and gain // Set RX freq and gain
phy.get_radio()->set_rx_freq(prog_args.uhd_freq); radio_uhd.set_rx_freq(prog_args.uhd_freq);
phy.get_radio()->set_rx_gain(prog_args.uhd_gain); radio_uhd.set_rx_gain(prog_args.uhd_gain);
/* Instruct the PHY to decode BCH */ phy.sync_start();
if (!phy.decode_mib_best(&cell, bch_payload)) {
exit(-1);
}
// Print MIB
srslte_cell_fprint(stdout, &cell, phy.get_current_tti()/10);
// Set the current PHY cell to the detected cell
if (!phy.set_cell(cell)) {
printf("Error setting cell\n");
exit(-1);
}
/* Instruct the PHY to start RX streaming and synchronize */
if (!phy.start_rxtx()) {
printf("Could not start RX\n");
exit(-1);
}
/* go to idle and process each tti */
while(1) { while(1) {
uint32_t tti = ttisync.wait(); usleep(1000);
run_tti(tti);
} }
} }

@ -576,8 +576,9 @@ int main(int argc, char **argv) {
} }
/* Configure pdsch_cfg parameters */ /* Configure pdsch_cfg parameters */
srslte_ra_dl_dci_to_grant(&ra_dl, cell.nof_prb, true, &pdsch_cfg.grant); srslte_ra_dl_grant_t grant;
if (srslte_pdsch_cfg(&pdsch_cfg, cell, NULL, cfi, sf_idx, UE_CRNTI, 0)) { srslte_ra_dl_dci_to_grant(&ra_dl, cell.nof_prb, true, &grant);
if (srslte_pdsch_cfg(&pdsch_cfg, cell, &grant, cfi, sf_idx, UE_CRNTI, 0)) {
fprintf(stderr, "Error configuring PDSCH\n"); fprintf(stderr, "Error configuring PDSCH\n");
exit(-1); exit(-1);
} }

@ -385,12 +385,12 @@ cell.nof_ports = 1;
srslte_refsignal_dmrs_pusch_cfg_t dmrs_cfg; srslte_refsignal_dmrs_pusch_cfg_t dmrs_cfg;
bzero(&dmrs_cfg, sizeof(srslte_refsignal_dmrs_pusch_cfg_t)); bzero(&dmrs_cfg, sizeof(srslte_refsignal_dmrs_pusch_cfg_t));
dmrs_cfg.beta_pusch = 1.0;
bool group_hopping_en = false; dmrs_cfg.group_hopping_en = false;
bool sequence_hopping_en = false; dmrs_cfg.sequence_hopping_en = false;
dmrs_cfg.delta_ss = 0; dmrs_cfg.delta_ss = 0;
dmrs_cfg.cyclic_shift = 0; dmrs_cfg.cyclic_shift = 0;
srslte_ue_ul_set_cfg(&ue_ul, &dmrs_cfg, NULL, NULL, NULL, group_hopping_en, sequence_hopping_en); srslte_ue_ul_set_cfg(&ue_ul, &dmrs_cfg, NULL, NULL, NULL, NULL, NULL);
cf_t *ul_signal = srslte_vec_malloc(sizeof(cf_t) * SRSLTE_SF_LEN_PRB(cell.nof_prb)); cf_t *ul_signal = srslte_vec_malloc(sizeof(cf_t) * SRSLTE_SF_LEN_PRB(cell.nof_prb));
if (!ul_signal) { if (!ul_signal) {
@ -518,8 +518,7 @@ cell.nof_ports = 1;
printf("Setting CFO: %f (%f)\n", cfo, cfo*15000); printf("Setting CFO: %f (%f)\n", cfo, cfo*15000);
srslte_ue_ul_set_cfo(&ue_ul, cfo); srslte_ue_ul_set_cfo(&ue_ul, cfo);
memcpy(&ue_ul.pusch_cfg.grant, &ra_grant, sizeof(srslte_ra_ul_grant_t)); srslte_ue_ul_cfg_grant(&ue_ul, &ra_grant, ul_sf_idx, 0, 0);
srslte_ue_ul_cfg_grant(&ue_ul, NULL, 0, 0, ul_sf_idx, 0, 0);
n = srslte_ue_ul_pusch_encode_rnti(&ue_ul, data, rar_msg.temp_c_rnti, ul_signal); n = srslte_ue_ul_pusch_encode_rnti(&ue_ul, data, rar_msg.temp_c_rnti, ul_signal);
if (n < 0) { if (n < 0) {

@ -48,11 +48,11 @@
typedef struct SRSLTE_API { typedef struct SRSLTE_API {
uint32_t cyclic_shift; uint32_t cyclic_shift;
uint32_t delta_ss; uint32_t delta_ss;
float beta_pusch; bool group_hopping_en;
bool sequence_hopping_en;
}srslte_refsignal_dmrs_pusch_cfg_t; }srslte_refsignal_dmrs_pusch_cfg_t;
typedef struct SRSLTE_API { typedef struct SRSLTE_API {
float beta_srs;
uint32_t subframe_config; uint32_t subframe_config;
uint32_t I_srs; uint32_t I_srs;
uint32_t bw_cfg; uint32_t bw_cfg;
@ -67,8 +67,6 @@ typedef struct SRSLTE_API {
/** Uplink DeModulation Reference Signal (DMRS) */ /** Uplink DeModulation Reference Signal (DMRS) */
typedef struct SRSLTE_API { typedef struct SRSLTE_API {
srslte_cell_t cell; srslte_cell_t cell;
bool group_hopping_en;
bool sequence_hopping_en;
srslte_refsignal_dmrs_pusch_cfg_t pusch_cfg; srslte_refsignal_dmrs_pusch_cfg_t pusch_cfg;
srslte_pucch_cfg_t pucch_cfg; srslte_pucch_cfg_t pucch_cfg;
srslte_refsignal_srs_cfg_t srs_cfg; srslte_refsignal_srs_cfg_t srs_cfg;
@ -97,9 +95,7 @@ SRSLTE_API void srslte_refsignal_ul_free(srslte_refsignal_ul_t *q);
SRSLTE_API void srslte_refsignal_ul_set_cfg(srslte_refsignal_ul_t *q, SRSLTE_API void srslte_refsignal_ul_set_cfg(srslte_refsignal_ul_t *q,
srslte_refsignal_dmrs_pusch_cfg_t *pusch_cfg, srslte_refsignal_dmrs_pusch_cfg_t *pusch_cfg,
srslte_pucch_cfg_t *pucch_cfg, srslte_pucch_cfg_t *pucch_cfg,
srslte_refsignal_srs_cfg_t *srs_cfg, srslte_refsignal_srs_cfg_t *srs_cfg);
bool group_hopping_en,
bool sequence_hopping_en);
SRSLTE_API void srslte_refsignal_r_uv_arg_1prb(float *arg, SRSLTE_API void srslte_refsignal_r_uv_arg_1prb(float *arg,
uint32_t u); uint32_t u);

@ -139,6 +139,16 @@ typedef enum SRSLTE_API {
} srslte_phich_resources_t; } srslte_phich_resources_t;
typedef enum {
SRSLTE_RNTI_USER = 0,
SRSLTE_RNTI_SI,
SRSLTE_RNTI_RAR,
SRSLTE_RNTI_TEMP,
SRSLTE_RNTI_SPS,
SRSLTE_RNTI_PCH,
SRSLTE_RNTI_NOF_TYPES
} srslte_rnti_type_t;
typedef struct SRSLTE_API { typedef struct SRSLTE_API {
uint32_t nof_prb; uint32_t nof_prb;
uint32_t nof_ports; uint32_t nof_ports;

@ -41,7 +41,11 @@
#include "srslte/config.h" #include "srslte/config.h"
#include "srslte/common/phy_common.h" #include "srslte/common/phy_common.h"
typedef struct {
bool configured;
uint32_t pmi_idx;
} srslte_cqi_cfg_t;
/* Table 5.2.2.6.2-1: Fields for channel quality information feedback for higher layer configured subband /* Table 5.2.2.6.2-1: Fields for channel quality information feedback for higher layer configured subband
CQI reports CQI reports
(transmission mode 1, transmission mode 2, transmission mode 3, transmission mode 7 and (transmission mode 1, transmission mode 2, transmission mode 3, transmission mode 7 and

@ -84,7 +84,7 @@ SRSLTE_API int srslte_pdsch_set_rnti(srslte_pdsch_t *q,
SRSLTE_API int srslte_pdsch_cfg(srslte_pdsch_cfg_t *cfg, SRSLTE_API int srslte_pdsch_cfg(srslte_pdsch_cfg_t *cfg,
srslte_cell_t cell, srslte_cell_t cell,
srslte_dci_msg_t *dci_msg, srslte_ra_dl_grant_t *grant,
uint32_t cfi, uint32_t cfi,
uint32_t sf_idx, uint32_t sf_idx,
uint16_t rnti, uint16_t rnti,

@ -55,7 +55,6 @@ typedef enum SRSLTE_API {
} srslte_pucch_format_t; } srslte_pucch_format_t;
typedef struct SRSLTE_API { typedef struct SRSLTE_API {
uint32_t n_cce;
bool sps_enabled; bool sps_enabled;
uint32_t tpc_for_pucch; uint32_t tpc_for_pucch;
uint32_t N_pucch_1; uint32_t N_pucch_1;
@ -65,7 +64,6 @@ typedef struct SRSLTE_API {
}srslte_pucch_sched_t; }srslte_pucch_sched_t;
typedef struct SRSLTE_API { typedef struct SRSLTE_API {
float beta_pucch;
uint32_t delta_pucch_shift; uint32_t delta_pucch_shift;
uint32_t n_rb_2; uint32_t n_rb_2;
uint32_t N_cs; uint32_t N_cs;

@ -60,7 +60,6 @@ typedef struct {
SRSLTE_PUSCH_HOP_MODE_INTER_SF = 1, SRSLTE_PUSCH_HOP_MODE_INTER_SF = 1,
SRSLTE_PUSCH_HOP_MODE_INTRA_SF = 0 SRSLTE_PUSCH_HOP_MODE_INTRA_SF = 0
} hop_mode; } hop_mode;
uint32_t current_tx_nb;
uint32_t hopping_offset; uint32_t hopping_offset;
uint32_t n_sb; uint32_t n_sb;
} srslte_pusch_hopping_cfg_t; } srslte_pusch_hopping_cfg_t;
@ -103,14 +102,15 @@ SRSLTE_API int srslte_pusch_init(srslte_pusch_t *q,
SRSLTE_API void srslte_pusch_free(srslte_pusch_t *q); SRSLTE_API void srslte_pusch_free(srslte_pusch_t *q);
SRSLTE_API int srslte_pusch_cfg(srslte_pusch_t *q, SRSLTE_API int srslte_pusch_cfg(srslte_pusch_t *q,
srslte_pusch_cfg_t *cfg, srslte_pusch_cfg_t *cfg,
srslte_dci_msg_t *dci_msg, srslte_ra_ul_grant_t *grant,
srslte_pusch_hopping_cfg_t *hopping_cfg, srslte_uci_cfg_t *uci_cfg,
srslte_refsignal_srs_cfg_t *srs_cfg, srslte_pusch_hopping_cfg_t *hopping_cfg,
srslte_refsignal_srs_cfg_t *srs_cfg,
uint32_t tti, uint32_t tti,
uint32_t cyclic_shift_for_dmrs, uint32_t rv_idx,
uint32_t rvidx); uint32_t current_tx_nb);
SRSLTE_API int srslte_pusch_set_rnti(srslte_pusch_t *q, SRSLTE_API int srslte_pusch_set_rnti(srslte_pusch_t *q,
uint16_t rnti); uint16_t rnti);

@ -40,11 +40,17 @@
#include "srslte/fec/softbuffer.h" #include "srslte/fec/softbuffer.h"
#include "srslte/fec/cbsegm.h" #include "srslte/fec/cbsegm.h"
typedef struct SRSLTE_API {
uint32_t I_offset_cqi;
uint32_t I_offset_ri;
uint32_t I_offset_ack;
} srslte_uci_cfg_t;
typedef struct SRSLTE_API { typedef struct SRSLTE_API {
srslte_cbsegm_t cb_segm; srslte_cbsegm_t cb_segm;
srslte_ra_ul_grant_t grant; srslte_ra_ul_grant_t grant;
srslte_ra_nbits_t nbits; srslte_ra_nbits_t nbits;
uint32_t cyclic_shift_for_dmrs; srslte_uci_cfg_t uci_cfg;
uint32_t rv; uint32_t rv;
uint32_t sf_idx; uint32_t sf_idx;
uint32_t tti; uint32_t tti;

@ -145,6 +145,7 @@ typedef struct SRSLTE_API {
uint32_t M_sc_init; uint32_t M_sc_init;
uint32_t Qm; uint32_t Qm;
srslte_ra_mcs_t mcs; srslte_ra_mcs_t mcs;
uint32_t ncs_dmrs;
} srslte_ra_ul_grant_t; } srslte_ra_ul_grant_t;
/** Unpacked DCI Format0 message */ /** Unpacked DCI Format0 message */
@ -172,12 +173,19 @@ typedef struct SRSLTE_API {
} srslte_ra_ul_dci_t; } srslte_ra_ul_dci_t;
typedef union {
srslte_ra_ul_grant_t ul;
srslte_ra_dl_grant_t dl;
} srslte_phy_grant_t;
#define SRSLTE_PHY_GRANT_LEN sizeof(srslte_phy_grant_t)
/************************************************** /**************************************************
* Functions * Functions
**************************************************/ **************************************************/
SRSLTE_API char* srslte_ra_dl_dci_string(srslte_ra_dl_dci_t *dci);
SRSLTE_API int srslte_ra_dl_dci_to_grant(srslte_ra_dl_dci_t *dci, SRSLTE_API int srslte_ra_dl_dci_to_grant(srslte_ra_dl_dci_t *dci,
uint32_t nof_prb, uint32_t nof_prb,

@ -54,14 +54,11 @@ typedef struct SRSLTE_API {
typedef struct SRSLTE_API { typedef struct SRSLTE_API {
uint8_t *uci_cqi; uint8_t *uci_cqi;
uint32_t uci_cqi_len; uint32_t uci_cqi_len;
uint32_t I_offset_cqi;
uint8_t uci_ri; // Only 1-bit supported for RI uint8_t uci_ri; // Only 1-bit supported for RI
uint32_t uci_ri_len; uint32_t uci_ri_len;
uint32_t I_offset_ri;
uint8_t uci_ack; // 1st codeword bit for HARQ-ACK uint8_t uci_ack; // 1st codeword bit for HARQ-ACK
uint8_t uci_ack_2; // 2st codeword bit for HARQ-ACK uint8_t uci_ack_2; // 2st codeword bit for HARQ-ACK
uint32_t uci_ack_len; uint32_t uci_ack_len;
uint32_t I_offset_ack;
bool scheduling_request; bool scheduling_request;
bool channel_selection; bool channel_selection;
} srslte_uci_data_t; } srslte_uci_data_t;

@ -98,20 +98,12 @@ SRSLTE_API int srslte_ue_dl_decode_fft_estimate(srslte_ue_dl_t *q,
uint32_t *cfi); uint32_t *cfi);
SRSLTE_API int srslte_ue_dl_cfg_grant(srslte_ue_dl_t *q, SRSLTE_API int srslte_ue_dl_cfg_grant(srslte_ue_dl_t *q,
srslte_dci_msg_t *dci_msg, srslte_ra_dl_grant_t *grant,
uint32_t cfi, uint32_t cfi,
uint32_t sf_idx, uint32_t sf_idx,
uint16_t rnti, uint16_t rnti,
uint32_t rvidx); uint32_t rvidx);
SRSLTE_API int srslte_ue_dl_decode_rnti_rv_packet(srslte_ue_dl_t *q,
srslte_dci_msg_t *dci_msg,
uint8_t *data,
uint32_t cfi,
uint32_t sf_idx,
uint16_t rnti,
uint32_t rvidx);
SRSLTE_API int srslte_ue_dl_find_ul_dci(srslte_ue_dl_t *q, SRSLTE_API int srslte_ue_dl_find_ul_dci(srslte_ue_dl_t *q,
srslte_dci_msg_t *dci_msg, srslte_dci_msg_t *dci_msg,
uint32_t cfi, uint32_t cfi,
@ -124,6 +116,13 @@ SRSLTE_API int srslte_ue_dl_find_dl_dci(srslte_ue_dl_t *q,
uint32_t sf_idx, uint32_t sf_idx,
uint16_t rnti); uint16_t rnti);
SRSLTE_API int srslte_ue_dl_find_dl_dci_type(srslte_ue_dl_t *q,
srslte_dci_msg_t *dci_msg,
uint32_t cfi,
uint32_t sf_idx,
uint16_t rnti,
srslte_rnti_type_t rnti_type);
SRSLTE_API uint32_t srslte_ue_dl_get_ncce(srslte_ue_dl_t *q); 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, SRSLTE_API int srslte_ue_dl_decode(srslte_ue_dl_t * q,

@ -136,6 +136,10 @@ SRSLTE_API uint32_t srslte_ue_sync_sf_len(srslte_ue_sync_t *q);
SRSLTE_API int srslte_ue_sync_get_buffer(srslte_ue_sync_t *q, SRSLTE_API int srslte_ue_sync_get_buffer(srslte_ue_sync_t *q,
cf_t **sf_symbols); cf_t **sf_symbols);
/* CAUTION: input_buffer MUST have space for 2 subframes */
SRSLTE_API int srslte_ue_sync_zerocopy(srslte_ue_sync_t *q,
cf_t *input_buffer);
SRSLTE_API void srslte_ue_sync_set_cfo(srslte_ue_sync_t *q, SRSLTE_API void srslte_ue_sync_set_cfo(srslte_ue_sync_t *q,
float cfo); float cfo);

@ -77,7 +77,10 @@ typedef struct SRSLTE_API {
srslte_pusch_t pusch; srslte_pusch_t pusch;
srslte_pucch_t pucch; srslte_pucch_t pucch;
srslte_pucch_sched_t pucch_sched; srslte_pucch_sched_t pucch_sched;
srslte_refsignal_srs_cfg_t srs_cfg;
srslte_uci_cfg_t uci_cfg;
srslte_pusch_hopping_cfg_t hopping_cfg;
cf_t *refsignal; cf_t *refsignal;
cf_t *srs_signal; cf_t *srs_signal;
@ -104,22 +107,21 @@ SRSLTE_API void srslte_ue_ul_set_normalization(srslte_ue_ul_t *q,
SRSLTE_API void srslte_ue_ul_set_cfg(srslte_ue_ul_t *q, SRSLTE_API void srslte_ue_ul_set_cfg(srslte_ue_ul_t *q,
srslte_refsignal_dmrs_pusch_cfg_t *dmrs_cfg, srslte_refsignal_dmrs_pusch_cfg_t *dmrs_cfg,
srslte_pucch_cfg_t *pucch_cfg, srslte_refsignal_srs_cfg_t *srs_cfg,
srslte_refsignal_srs_cfg_t *srs_cfg, srslte_pucch_cfg_t *pucch_cfg,
srslte_pucch_sched_t *pucch_sched, srslte_pucch_sched_t *pucch_sched,
bool group_hopping_en, srslte_uci_cfg_t *uci_cfg,
bool sequence_hopping_en); srslte_pusch_hopping_cfg_t *hopping_cfg);
SRSLTE_API int srslte_ue_ul_cfg_grant(srslte_ue_ul_t *q, SRSLTE_API int srslte_ue_ul_cfg_grant(srslte_ue_ul_t *q,
srslte_dci_msg_t *dci_msg, srslte_ra_ul_grant_t *grant,
srslte_pusch_hopping_cfg_t *hopping_cfg,
srslte_refsignal_srs_cfg_t *srs_cfg,
uint32_t tti, uint32_t tti,
uint32_t cyclic_shift_for_dmrs, uint32_t rvidx,
uint32_t rvidx); uint32_t current_tx_nb);
SRSLTE_API int srslte_ue_ul_pucch_encode(srslte_ue_ul_t *q, SRSLTE_API int srslte_ue_ul_pucch_encode(srslte_ue_ul_t *q,
srslte_uci_data_t uci_data, srslte_uci_data_t uci_data,
uint32_t pdcch_n_cce, /* Ncce of the last PDCCH message received */
uint32_t tti, uint32_t tti,
cf_t *output_signal); cf_t *output_signal);

@ -100,6 +100,9 @@ SRSLTE_API void srslte_vec_sc_prod_cfc(cf_t *x, float h, cf_t *z, uint32_t len);
SRSLTE_API void srslte_vec_sc_prod_ccc(cf_t *x, cf_t h, cf_t *z, uint32_t len); SRSLTE_API void srslte_vec_sc_prod_ccc(cf_t *x, cf_t h, cf_t *z, uint32_t len);
SRSLTE_API void srslte_vec_sc_prod_fff(float *x, float h, float *z, uint32_t len); SRSLTE_API void srslte_vec_sc_prod_fff(float *x, float h, float *z, uint32_t len);
/* Normalization */
SRSLTE_API void srslte_vec_norm_cfc(cf_t *x, float amplitude, cf_t *y, uint32_t len);
SRSLTE_API void srslte_vec_convert_fi(float *x, int16_t *z, float scale, uint32_t len); SRSLTE_API void srslte_vec_convert_fi(float *x, int16_t *z, float scale, uint32_t len);
SRSLTE_API void srslte_vec_deinterleave_cf(cf_t *x, float *real, float *imag, uint32_t len); SRSLTE_API void srslte_vec_deinterleave_cf(cf_t *x, float *real, float *imag, uint32_t len);

@ -228,12 +228,8 @@ void srslte_refsignal_ul_free(srslte_refsignal_ul_t * q) {
void srslte_refsignal_ul_set_cfg(srslte_refsignal_ul_t *q, void srslte_refsignal_ul_set_cfg(srslte_refsignal_ul_t *q,
srslte_refsignal_dmrs_pusch_cfg_t *pusch_cfg, srslte_refsignal_dmrs_pusch_cfg_t *pusch_cfg,
srslte_pucch_cfg_t *pucch_cfg, srslte_pucch_cfg_t *pucch_cfg,
srslte_refsignal_srs_cfg_t *srs_cfg, srslte_refsignal_srs_cfg_t *srs_cfg)
bool group_hopping_en,
bool sequence_hopping_en)
{ {
q->group_hopping_en = group_hopping_en;
q->sequence_hopping_en = sequence_hopping_en;
if (pusch_cfg) { if (pusch_cfg) {
memcpy(&q->pusch_cfg, pusch_cfg, sizeof(srslte_refsignal_dmrs_pusch_cfg_t)); memcpy(&q->pusch_cfg, pusch_cfg, sizeof(srslte_refsignal_dmrs_pusch_cfg_t));
} }
@ -335,14 +331,14 @@ void srslte_refsignal_dmrs_pusch_put(srslte_refsignal_ul_t *q, cf_t *r_pusch, ui
void compute_r(srslte_refsignal_ul_t *q, uint32_t nof_prb, uint32_t ns, uint32_t delta_ss) { void compute_r(srslte_refsignal_ul_t *q, uint32_t nof_prb, uint32_t ns, uint32_t delta_ss) {
// Get group hopping number u // Get group hopping number u
uint32_t f_gh=0; uint32_t f_gh=0;
if (q->group_hopping_en) { if (q->pusch_cfg.group_hopping_en) {
f_gh = q->f_gh[ns]; f_gh = q->f_gh[ns];
} }
uint32_t u = (f_gh + (q->cell.id%30)+delta_ss)%30; uint32_t u = (f_gh + (q->cell.id%30)+delta_ss)%30;
// Get sequence hopping number v // Get sequence hopping number v
uint32_t v = 0; uint32_t v = 0;
if (nof_prb >= 6 && q->sequence_hopping_en) { if (nof_prb >= 6 && q->pusch_cfg.sequence_hopping_en) {
v = q->v_pusch[ns][q->pusch_cfg.delta_ss]; v = q->v_pusch[ns][q->pusch_cfg.delta_ss];
} }
@ -433,7 +429,7 @@ int srslte_refsignal_dmrs_pusch_gen(srslte_refsignal_ul_t *q, uint32_t nof_prb,
// Do complex exponential and adjust amplitude // Do complex exponential and adjust amplitude
for (int i=0;i<SRSLTE_NRE*nof_prb;i++) { for (int i=0;i<SRSLTE_NRE*nof_prb;i++) {
r_pusch[(ns%2)*SRSLTE_NRE*nof_prb+i] = q->pusch_cfg.beta_pusch * cexpf(I*(q->tmp_arg[i] + alpha*i)); r_pusch[(ns%2)*SRSLTE_NRE*nof_prb+i] = cexpf(I*(q->tmp_arg[i] + alpha*i));
} }
} }
ret = 0; ret = 0;
@ -517,7 +513,7 @@ int srslte_refsignal_dmrs_pucch_gen(srslte_refsignal_ul_t *q, srslte_pucch_forma
for (uint32_t ns=2*sf_idx;ns<2*(sf_idx+1);ns++) { for (uint32_t ns=2*sf_idx;ns<2*(sf_idx+1);ns++) {
// Get group hopping number u // Get group hopping number u
uint32_t f_gh=0; uint32_t f_gh=0;
if (q->group_hopping_en) { if (q->pusch_cfg.group_hopping_en) {
f_gh = q->f_gh[ns]; f_gh = q->f_gh[ns];
} }
uint32_t u = (f_gh + (q->cell.id%30))%30; uint32_t u = (f_gh + (q->cell.id%30))%30;
@ -566,7 +562,7 @@ int srslte_refsignal_dmrs_pucch_gen(srslte_refsignal_ul_t *q, srslte_pucch_forma
} }
if (w) { if (w) {
for (uint32_t n=0;n<SRSLTE_NRE;n++) { for (uint32_t n=0;n<SRSLTE_NRE;n++) {
r_pucch[(ns%2)*SRSLTE_NRE*N_rs+m*SRSLTE_NRE+n] = q->pucch_cfg.beta_pucch*z_m*cexpf(I*(w[m]+q->tmp_arg[n]+alpha*n)); r_pucch[(ns%2)*SRSLTE_NRE*N_rs+m*SRSLTE_NRE+n] = z_m*cexpf(I*(w[m]+q->tmp_arg[n]+alpha*n));
} }
} else { } else {
return SRSLTE_ERROR; return SRSLTE_ERROR;
@ -846,7 +842,7 @@ int srslte_refsignal_srs_gen(srslte_refsignal_ul_t *q, uint32_t sf_idx, cf_t *r_
// Do complex exponential and adjust amplitude // Do complex exponential and adjust amplitude
for (int i=0;i<M_sc;i++) { for (int i=0;i<M_sc;i++) {
r_srs[(ns%2)*M_sc+i] = q->srs_cfg.beta_srs * cexpf(I*(q->tmp_arg[i] + alpha*i)); r_srs[(ns%2)*M_sc+i] = cexpf(I*(q->tmp_arg[i] + alpha*i));
} }
} }
ret = SRSLTE_SUCCESS; ret = SRSLTE_SUCCESS;

@ -76,14 +76,14 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
bzero(&pusch_cfg, sizeof(srslte_refsignal_dmrs_pusch_cfg_t)); bzero(&pusch_cfg, sizeof(srslte_refsignal_dmrs_pusch_cfg_t));
bool group_hopping_en = false; pusch_cfg.group_hopping_en = false;
bool sequence_hopping_en = false; pusch_cfg.sequence_hopping_en = false;
char *tmp = mexutils_get_char_struct(UECFG, "Hopping"); char *tmp = mexutils_get_char_struct(UECFG, "Hopping");
if (tmp) { if (tmp) {
if (!strcmp(tmp, "Group")) { if (!strcmp(tmp, "Group")) {
group_hopping_en = true; pusch_cfg.group_hopping_en = true;
} else if (!strcmp(tmp, "Sequence")) { } else if (!strcmp(tmp, "Sequence")) {
sequence_hopping_en = true; pusch_cfg.sequence_hopping_en = true;
} }
mxFree(tmp); mxFree(tmp);
} }
@ -109,8 +109,6 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
cyclic_shift_for_dmrs = 0; cyclic_shift_for_dmrs = 0;
} }
pusch_cfg.beta_pusch = 1.0;
if (srslte_refsignal_ul_init(&refs, cell)) { if (srslte_refsignal_ul_init(&refs, cell)) {
mexErrMsgTxt("Error initiating srslte_refsignal_ul\n"); mexErrMsgTxt("Error initiating srslte_refsignal_ul\n");
return; return;
@ -133,7 +131,7 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
} }
bzero(sf_symbols, SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp)*sizeof(cf_t)); bzero(sf_symbols, SRSLTE_SF_LEN_RE(cell.nof_prb, cell.cp)*sizeof(cf_t));
srslte_refsignal_ul_set_cfg(&refs, &pusch_cfg, NULL, NULL, group_hopping_en, sequence_hopping_en); srslte_refsignal_ul_set_cfg(&refs, &pusch_cfg, NULL, NULL);
//mexPrintf("Generating DRMS for ns=%d, nof_prb=%d\n", 2*sf_idx+i,pusch_cfg.nof_prb); //mexPrintf("Generating DRMS for ns=%d, nof_prb=%d\n", 2*sf_idx+i,pusch_cfg.nof_prb);
srslte_refsignal_dmrs_pusch_gen(&refs, nof_prb, sf_idx, cyclic_shift_for_dmrs, signal); srslte_refsignal_dmrs_pusch_gen(&refs, nof_prb, sf_idx, cyclic_shift_for_dmrs, signal);

@ -78,7 +78,7 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
srslte_refsignal_srs_cfg_t srs_cfg; srslte_refsignal_srs_cfg_t srs_cfg;
bzero(&srs_cfg, sizeof(srslte_refsignal_srs_cfg_t)); bzero(&srs_cfg, sizeof(srslte_refsignal_srs_cfg_t));
srs_cfg.beta_srs = 1.0;
if (mexutils_read_uint32_struct(SRSCFG, "BWConfig", &srs_cfg.bw_cfg)) { if (mexutils_read_uint32_struct(SRSCFG, "BWConfig", &srs_cfg.bw_cfg)) {
mexErrMsgTxt("Field BWConfig not found in SRSCFG\n"); mexErrMsgTxt("Field BWConfig not found in SRSCFG\n");
return; return;
@ -133,8 +133,10 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
mexErrMsgTxt("Error initiating UL refsignal\n"); mexErrMsgTxt("Error initiating UL refsignal\n");
return; return;
} }
srslte_refsignal_dmrs_pusch_cfg_t pusch_cfg;
srslte_refsignal_ul_set_cfg(&refsignal, NULL, NULL, &srs_cfg, group_hopping_en, false); pusch_cfg.group_hopping_en = group_hopping_en;
pusch_cfg.sequence_hopping_en = false;
srslte_refsignal_ul_set_cfg(&refsignal, &pusch_cfg, NULL, &srs_cfg);
if (srslte_refsignal_srs_gen(&refsignal, sf_idx, r_srs)) { if (srslte_refsignal_srs_gen(&refsignal, sf_idx, r_srs)) {
mexErrMsgTxt("Error generating SRS\n"); mexErrMsgTxt("Error generating SRS\n");

@ -100,7 +100,7 @@ int main(int argc, char **argv) {
for (int h=0;h<3;h++) { for (int h=0;h<3;h++) {
for (int sf_idx=0;sf_idx<SRSLTE_NSLOTS_X_FRAME;sf_idx++) { for (int sf_idx=0;sf_idx<SRSLTE_NSLOTS_X_FRAME;sf_idx++) {
for (int cshift_dmrs=0;cshift_dmrs<SRSLTE_NOF_CSHIFT;cshift_dmrs++) { for (int cshift_dmrs=0;cshift_dmrs<SRSLTE_NOF_CSHIFT;cshift_dmrs++) {
pusch_cfg.beta_pusch = 1.0;
uint32_t nof_prb = n; uint32_t nof_prb = n;
pusch_cfg.cyclic_shift = cshift; pusch_cfg.cyclic_shift = cshift;
pusch_cfg.delta_ss = delta_ss; pusch_cfg.delta_ss = delta_ss;
@ -118,7 +118,6 @@ int main(int argc, char **argv) {
sequence_hopping_en = false; sequence_hopping_en = false;
} }
printf("Beta: %f, ",pusch_cfg.beta_pusch);
printf("nof_prb: %d, ",nof_prb); printf("nof_prb: %d, ",nof_prb);
printf("cyclic_shift: %d, ",pusch_cfg.cyclic_shift); printf("cyclic_shift: %d, ",pusch_cfg.cyclic_shift);
printf("cyclic_shift_for_dmrs: %d, ", cshift_dmrs); printf("cyclic_shift_for_dmrs: %d, ", cshift_dmrs);
@ -127,7 +126,9 @@ int main(int argc, char **argv) {
struct timeval t[3]; struct timeval t[3];
gettimeofday(&t[1], NULL); gettimeofday(&t[1], NULL);
srslte_refsignal_ul_set_cfg(&refs, &pusch_cfg, NULL, NULL, group_hopping_en, sequence_hopping_en); pusch_cfg.group_hopping_en = group_hopping_en;
pusch_cfg.sequence_hopping_en = sequence_hopping_en;
srslte_refsignal_ul_set_cfg(&refs, &pusch_cfg, NULL, NULL);
srslte_refsignal_dmrs_pusch_gen(&refs, nof_prb, sf_idx, cshift_dmrs, signal); srslte_refsignal_dmrs_pusch_gen(&refs, nof_prb, sf_idx, cshift_dmrs, signal);
gettimeofday(&t[2], NULL); gettimeofday(&t[2], NULL);
get_time_interval(t); get_time_interval(t);

@ -55,12 +55,12 @@ int srslte_dft_precoding_init(srslte_dft_precoding_t *q, uint32_t max_prb)
fprintf(stderr, "Error: Creating DFT plan %d\n",i); fprintf(stderr, "Error: Creating DFT plan %d\n",i);
goto clean_exit; goto clean_exit;
} }
srslte_dft_plan_set_norm(&q->dft_plan[i], true); srslte_dft_plan_set_norm(&q->dft_plan[i], false);
if (srslte_dft_plan_c(&q->idft_plan[i], i*SRSLTE_NRE, SRSLTE_DFT_BACKWARD)) { if (srslte_dft_plan_c(&q->idft_plan[i], i*SRSLTE_NRE, SRSLTE_DFT_BACKWARD)) {
fprintf(stderr, "Error: Creating DFT plan %d\n",i); fprintf(stderr, "Error: Creating DFT plan %d\n",i);
goto clean_exit; goto clean_exit;
} }
srslte_dft_plan_set_norm(&q->idft_plan[i], true); srslte_dft_plan_set_norm(&q->idft_plan[i], false);
} }
} }
q->max_prb = max_prb; q->max_prb = max_prb;

@ -99,7 +99,7 @@ int srslte_ofdm_tx_init(srslte_ofdm_t *q, srslte_cp_t cp, uint32_t nof_prb) {
ret = srslte_ofdm_init_(q, cp, nof_prb, SRSLTE_DFT_BACKWARD); ret = srslte_ofdm_init_(q, cp, nof_prb, SRSLTE_DFT_BACKWARD);
if (ret == SRSLTE_SUCCESS) { if (ret == SRSLTE_SUCCESS) {
srslte_dft_plan_set_norm(&q->fft_plan, true); srslte_dft_plan_set_norm(&q->fft_plan, false);
/* set now zeros at CP */ /* set now zeros at CP */
for (i=0;i<q->nof_symbols;i++) { for (i=0;i<q->nof_symbols;i++) {

@ -305,21 +305,11 @@ void srslte_pdsch_free(srslte_pdsch_t *q) {
/* Configures the structure srslte_pdsch_cfg_t from the DL DCI allocation dci_msg. /* Configures the structure srslte_pdsch_cfg_t from the DL DCI allocation dci_msg.
* If dci_msg is NULL, the grant is assumed to be already stored in cfg->grant * If dci_msg is NULL, the grant is assumed to be already stored in cfg->grant
*/ */
int srslte_pdsch_cfg(srslte_pdsch_cfg_t *cfg, srslte_cell_t cell, srslte_dci_msg_t *dci_msg, uint32_t cfi, uint32_t sf_idx, uint16_t rnti, uint32_t rvidx) int srslte_pdsch_cfg(srslte_pdsch_cfg_t *cfg, srslte_cell_t cell, srslte_ra_dl_grant_t *grant, uint32_t cfi, uint32_t sf_idx, uint16_t rnti, uint32_t rvidx)
{ {
if (dci_msg) {
srslte_ra_dl_dci_t dl_dci; if (cfg && grant) {
if (srslte_dci_msg_to_dl_grant(dci_msg, rnti, cell.nof_prb, &dl_dci, &cfg->grant)) { memcpy(&cfg->grant, grant, sizeof(srslte_ra_dl_grant_t));
fprintf(stderr, "Error unpacking PDSCH scheduling DCI message\n");
return SRSLTE_ERROR;
}
if (rnti == SRSLTE_SIRNTI) {
cfg->rv = rvidx;
} else {
cfg->rv = dl_dci.rv_idx;
}
} else {
cfg->rv = rvidx;
} }
if (srslte_cbsegm(&cfg->cb_segm, cfg->grant.mcs.tbs)) { if (srslte_cbsegm(&cfg->cb_segm, cfg->grant.mcs.tbs)) {
fprintf(stderr, "Error computing Codeblock segmentation for TBS=%d\n", cfg->grant.mcs.tbs); fprintf(stderr, "Error computing Codeblock segmentation for TBS=%d\n", cfg->grant.mcs.tbs);
@ -327,6 +317,7 @@ int srslte_pdsch_cfg(srslte_pdsch_cfg_t *cfg, srslte_cell_t cell, srslte_dci_msg
} }
srslte_ra_dl_grant_to_nbits(&cfg->grant, cfi, cell, sf_idx, &cfg->nbits); srslte_ra_dl_grant_to_nbits(&cfg->grant, cfi, cell, sf_idx, &cfg->nbits);
cfg->sf_idx = sf_idx; cfg->sf_idx = sf_idx;
cfg->rv = rvidx;
return SRSLTE_SUCCESS; return SRSLTE_SUCCESS;
} }

@ -65,8 +65,7 @@ float w_n_oc[2][3][4] = {
/* Verify PUCCH configuration as given in Section 5.4 36.211 */ /* Verify PUCCH configuration as given in Section 5.4 36.211 */
bool srslte_pucch_cfg_isvalid(srslte_pucch_cfg_t *cfg, uint32_t nof_prb) { bool srslte_pucch_cfg_isvalid(srslte_pucch_cfg_t *cfg, uint32_t nof_prb) {
if (cfg->beta_pucch > 0 && if (cfg->delta_pucch_shift > 0 && cfg->delta_pucch_shift < 4 &&
cfg->delta_pucch_shift > 0 && cfg->delta_pucch_shift < 4 &&
cfg->N_cs < 8 && (cfg->N_cs%cfg->delta_pucch_shift) == 0 && cfg->N_cs < 8 && (cfg->N_cs%cfg->delta_pucch_shift) == 0 &&
cfg->n_rb_2 < nof_prb) { cfg->n_rb_2 < nof_prb) {
return true; return true;
@ -85,7 +84,6 @@ bool srslte_pucch_n2_isvalid(srslte_pucch_cfg_t *cfg, uint32_t n_pucch_2) {
} }
void srslte_pucch_cfg_default(srslte_pucch_cfg_t *cfg) { void srslte_pucch_cfg_default(srslte_pucch_cfg_t *cfg) {
cfg->beta_pucch = 1.0;
cfg->delta_pucch_shift = 1; cfg->delta_pucch_shift = 1;
} }
@ -522,8 +520,7 @@ int srslte_pucch_encode(srslte_pucch_t* q, srslte_pucch_format_t format,
if (format >= SRSLTE_PUCCH_FORMAT_2) { if (format >= SRSLTE_PUCCH_FORMAT_2) {
alpha = srslte_pucch_alpha_format2(q->n_cs_cell, &q->pucch_cfg, n_pucch, ns, l); alpha = srslte_pucch_alpha_format2(q->n_cs_cell, &q->pucch_cfg, n_pucch, ns, l);
for (uint32_t n=0;n<SRSLTE_PUCCH_N_SEQ;n++) { for (uint32_t n=0;n<SRSLTE_PUCCH_N_SEQ;n++) {
q->z[(ns%2)*N_sf*SRSLTE_PUCCH_N_SEQ+m*SRSLTE_PUCCH_N_SEQ+n] = q->pucch_cfg.beta_pucch q->z[(ns%2)*N_sf*SRSLTE_PUCCH_N_SEQ+m*SRSLTE_PUCCH_N_SEQ+n] = q->d[(ns%2)*N_sf+m]*cexpf(I*(q->tmp_arg[n]+alpha*n));
*q->d[(ns%2)*N_sf+m]*cexpf(I*(q->tmp_arg[n]+alpha*n));
} }
} else { } else {
alpha = srslte_pucch_alpha_format1(q->n_cs_cell, &q->pucch_cfg, n_pucch, q->cell.cp, true, ns, l, &n_oc, &n_prime_ns); alpha = srslte_pucch_alpha_format1(q->n_cs_cell, &q->pucch_cfg, n_pucch, q->cell.cp, true, ns, l, &n_oc, &n_prime_ns);
@ -534,8 +531,7 @@ int srslte_pucch_encode(srslte_pucch_t* q, srslte_pucch_format_t format,
DEBUG("PUCCH d_0: %.1f+%.1fi, alpha: %.1f, n_oc: %d, n_prime_ns: %d, n_rb_2=%d\n", DEBUG("PUCCH d_0: %.1f+%.1fi, alpha: %.1f, n_oc: %d, n_prime_ns: %d, n_rb_2=%d\n",
__real__ q->d[0], __imag__ q->d[0], alpha, n_oc, n_prime_ns, q->pucch_cfg.n_rb_2); __real__ q->d[0], __imag__ q->d[0], alpha, n_oc, n_prime_ns, q->pucch_cfg.n_rb_2);
for (uint32_t n=0;n<SRSLTE_PUCCH_N_SEQ;n++) { for (uint32_t n=0;n<SRSLTE_PUCCH_N_SEQ;n++) {
q->z[(ns%2)*N_sf_0*SRSLTE_PUCCH_N_SEQ+m*SRSLTE_PUCCH_N_SEQ+n] = q->pucch_cfg.beta_pucch q->z[(ns%2)*N_sf_0*SRSLTE_PUCCH_N_SEQ+m*SRSLTE_PUCCH_N_SEQ+n] = q->d[0]*cexpf(I*(w_n_oc[N_sf_widx][n_oc%3][m]+q->tmp_arg[n]+alpha*n+S_ns));
*q->d[0]*cexpf(I*(w_n_oc[N_sf_widx][n_oc%3][m]+q->tmp_arg[n]+alpha*n+S_ns));
} }
} }
} }

@ -73,10 +73,10 @@ static int f_hop(srslte_pusch_t *q, srslte_pusch_hopping_cfg_t *hopping, int i)
} }
} }
static int f_m(srslte_pusch_t *q, srslte_pusch_hopping_cfg_t *hopping, uint32_t i) { static int f_m(srslte_pusch_t *q, srslte_pusch_hopping_cfg_t *hopping, uint32_t i, uint32_t current_tx_nb) {
if (hopping->n_sb == 1) { if (hopping->n_sb == 1) {
if (hopping->hop_mode == SRSLTE_PUSCH_HOP_MODE_INTER_SF) { if (hopping->hop_mode == SRSLTE_PUSCH_HOP_MODE_INTER_SF) {
return hopping->current_tx_nb%2; return current_tx_nb%2;
} else { } else {
return i%2; return i%2;
} }
@ -88,7 +88,7 @@ static int f_m(srslte_pusch_t *q, srslte_pusch_hopping_cfg_t *hopping, uint32_t
/* Computes PUSCH frequency hopping as defined in Section 8.4 of 36.213 */ /* Computes PUSCH frequency hopping as defined in Section 8.4 of 36.213 */
void compute_freq_hopping(srslte_pusch_t *q, srslte_ra_ul_grant_t *grant, void compute_freq_hopping(srslte_pusch_t *q, srslte_ra_ul_grant_t *grant,
srslte_pusch_hopping_cfg_t *hopping, srslte_pusch_hopping_cfg_t *hopping,
uint32_t sf_idx) uint32_t sf_idx, uint32_t current_tx_nb)
{ {
for (uint32_t slot=0;slot<2;slot++) { for (uint32_t slot=0;slot<2;slot++) {
@ -98,7 +98,7 @@ void compute_freq_hopping(srslte_pusch_t *q, srslte_ra_ul_grant_t *grant,
if (grant->freq_hopping == 1) { if (grant->freq_hopping == 1) {
if (hopping->hop_mode == SRSLTE_PUSCH_HOP_MODE_INTER_SF) { if (hopping->hop_mode == SRSLTE_PUSCH_HOP_MODE_INTER_SF) {
n_prb_tilde = grant->n_prb[hopping->current_tx_nb%2]; n_prb_tilde = grant->n_prb[current_tx_nb%2];
} else { } else {
n_prb_tilde = grant->n_prb[slot]; n_prb_tilde = grant->n_prb[slot];
} }
@ -120,7 +120,7 @@ void compute_freq_hopping(srslte_pusch_t *q, srslte_ra_ul_grant_t *grant,
n_rb_sb = (n_rb_sb-hopping->hopping_offset-hopping->hopping_offset%2)/hopping->n_sb; n_rb_sb = (n_rb_sb-hopping->hopping_offset-hopping->hopping_offset%2)/hopping->n_sb;
} }
n_prb_tilde = (n_vrb_tilde+f_hop(q, hopping, i)*n_rb_sb+ n_prb_tilde = (n_vrb_tilde+f_hop(q, hopping, i)*n_rb_sb+
(n_rb_sb-1)-2*(n_vrb_tilde%n_rb_sb)*f_m(q, hopping, i))%(n_rb_sb*hopping->n_sb); (n_rb_sb-1)-2*(n_vrb_tilde%n_rb_sb)*f_m(q, hopping, i, current_tx_nb))%(n_rb_sb*hopping->n_sb);
INFO("n_prb_tilde: %d, n_vrb_tilde: %d, n_rb_sb: %d, n_sb: %d\n", INFO("n_prb_tilde: %d, n_vrb_tilde: %d, n_rb_sb: %d, n_sb: %d\n",
n_prb_tilde, n_vrb_tilde, n_rb_sb, hopping->n_sb); n_prb_tilde, n_vrb_tilde, n_rb_sb, hopping->n_sb);
@ -305,79 +305,85 @@ void srslte_pusch_free(srslte_pusch_t *q) {
/* Configures the structure srslte_pusch_cfg_t from the UL DCI allocation dci_msg. /* Configures the structure srslte_pusch_cfg_t from the UL DCI allocation dci_msg.
* If dci_msg is NULL, the grant is assumed to be already stored in cfg->grant * If dci_msg is NULL, the grant is assumed to be already stored in cfg->grant
*/ */
int srslte_pusch_cfg(srslte_pusch_t *q, srslte_pusch_cfg_t *cfg, srslte_dci_msg_t *dci_msg, int srslte_pusch_cfg(srslte_pusch_t *q,
srslte_pusch_hopping_cfg_t *hopping_cfg, srslte_refsignal_srs_cfg_t *srs_cfg, srslte_pusch_cfg_t *cfg,
uint32_t tti, uint32_t cyclic_shift_for_dmrs, uint32_t rvidx) srslte_ra_ul_grant_t *grant,
srslte_uci_cfg_t *uci_cfg,
srslte_pusch_hopping_cfg_t *hopping_cfg,
srslte_refsignal_srs_cfg_t *srs_cfg,
uint32_t tti,
uint32_t rv_idx,
uint32_t current_tx_nb)
{ {
if (dci_msg) { if (q && cfg && grant) {
srslte_ra_ul_dci_t ul_dci; memcpy(&cfg->grant, grant, sizeof(srslte_ra_ul_grant_t));
if (srslte_dci_msg_to_ul_grant(dci_msg, q->cell.nof_prb, hopping_cfg->hopping_offset, &ul_dci, &cfg->grant)) {
fprintf(stderr, "Error unpacking UL grant from DCI message\n"); if (srslte_cbsegm(&cfg->cb_segm, cfg->grant.mcs.tbs)) {
fprintf(stderr, "Error computing Codeblock segmentation for TBS=%d\n", cfg->grant.mcs.tbs);
return SRSLTE_ERROR; return SRSLTE_ERROR;
} }
}
if (srslte_cbsegm(&cfg->cb_segm, cfg->grant.mcs.tbs)) { /* Compute PUSCH frequency hopping */
fprintf(stderr, "Error computing Codeblock segmentation for TBS=%d\n", cfg->grant.mcs.tbs); if (hopping_cfg) {
return SRSLTE_ERROR; compute_freq_hopping(q, &cfg->grant, hopping_cfg, tti%10, current_tx_nb);
} } else {
cfg->grant.n_prb_tilde[0] = cfg->grant.n_prb[0];
cfg->cyclic_shift_for_dmrs = cyclic_shift_for_dmrs; cfg->grant.n_prb_tilde[1] = cfg->grant.n_prb[1];
}
/* Compute PUSCH frequency hopping */ if (srs_cfg) {
if (hopping_cfg) { q->shortened = false;
compute_freq_hopping(q, &cfg->grant, hopping_cfg, tti%10); if (srs_cfg->configured) {
} else { // If UE-specific SRS is configured, PUSCH is shortened every time UE transmits SRS even if overlaping in the same RB or not
cfg->grant.n_prb_tilde[0] = cfg->grant.n_prb[0]; if (srslte_refsignal_srs_send_cs(srs_cfg->subframe_config, tti%10) == 1 &&
cfg->grant.n_prb_tilde[1] = cfg->grant.n_prb[1]; srslte_refsignal_srs_send_ue(srs_cfg->I_srs, tti) == 1)
} {
if (srs_cfg) { q->shortened = true;
q->shortened = false; /* If RBs are contiguous, PUSCH is not shortened */
if (srs_cfg->configured) {
// If UE-specific SRS is configured, PUSCH is shortened every time UE transmits SRS even if overlaping in the same RB or not
if (srslte_refsignal_srs_send_cs(srs_cfg->subframe_config, tti%10) == 1 &&
srslte_refsignal_srs_send_ue(srs_cfg->I_srs, tti) == 1)
{
q->shortened = true;
/* If RBs are contiguous, PUSCH is not shortened */
uint32_t k0_srs = srslte_refsignal_srs_rb_start_cs(srs_cfg->bw_cfg, q->cell.nof_prb);
uint32_t nrb_srs = srslte_refsignal_srs_rb_L_cs(srs_cfg->bw_cfg, q->cell.nof_prb);
for (uint32_t ns=0;ns<2 && q->shortened;ns++) {
if (cfg->grant.n_prb_tilde[ns] != k0_srs + nrb_srs || // If grant allocation starts when SRS ends
cfg->grant.n_prb_tilde[ns] + cfg->grant.L_prb != k0_srs) // or SRS allocation starts when grant ends
{
q->shortened = false;
}
}
}
// If not coincides with UE transmission. PUSCH shall be shortened if cell-specific SRS transmission RB
//coincides with PUSCH allocated RB
if (!q->shortened) {
if (srslte_refsignal_srs_send_cs(srs_cfg->subframe_config, tti%10) == 1) {
uint32_t k0_srs = srslte_refsignal_srs_rb_start_cs(srs_cfg->bw_cfg, q->cell.nof_prb); uint32_t k0_srs = srslte_refsignal_srs_rb_start_cs(srs_cfg->bw_cfg, q->cell.nof_prb);
uint32_t nrb_srs = srslte_refsignal_srs_rb_L_cs(srs_cfg->bw_cfg, q->cell.nof_prb); uint32_t nrb_srs = srslte_refsignal_srs_rb_L_cs(srs_cfg->bw_cfg, q->cell.nof_prb);
for (uint32_t ns=0;ns<2 && !q->shortened;ns++) { for (uint32_t ns=0;ns<2 && q->shortened;ns++) {
if ((cfg->grant.n_prb_tilde[ns] >= k0_srs && cfg->grant.n_prb_tilde[ns] < k0_srs + nrb_srs) || if (cfg->grant.n_prb_tilde[ns] != k0_srs + nrb_srs || // If grant allocation starts when SRS ends
(cfg->grant.n_prb_tilde[ns] + cfg->grant.L_prb >= k0_srs && cfg->grant.n_prb_tilde[ns] + cfg->grant.L_prb != k0_srs) // or SRS allocation starts when grant ends
cfg->grant.n_prb_tilde[ns] + cfg->grant.L_prb < k0_srs + nrb_srs) || {
(cfg->grant.n_prb_tilde[ns] <= k0_srs && cfg->grant.n_prb_tilde[ns] + cfg->grant.L_prb >= k0_srs + nrb_srs)) q->shortened = false;
{
q->shortened = true;
} }
} }
} }
} // If not coincides with UE transmission. PUSCH shall be shortened if cell-specific SRS transmission RB
} //coincides with PUSCH allocated RB
} if (!q->shortened) {
if (srslte_refsignal_srs_send_cs(srs_cfg->subframe_config, tti%10) == 1) {
/* Compute final number of bits and RE */ uint32_t k0_srs = srslte_refsignal_srs_rb_start_cs(srs_cfg->bw_cfg, q->cell.nof_prb);
srslte_ra_ul_grant_to_nbits(&cfg->grant, q->cell.cp, q->shortened?1:0, &cfg->nbits); uint32_t nrb_srs = srslte_refsignal_srs_rb_L_cs(srs_cfg->bw_cfg, q->cell.nof_prb);
for (uint32_t ns=0;ns<2 && !q->shortened;ns++) {
if ((cfg->grant.n_prb_tilde[ns] >= k0_srs && cfg->grant.n_prb_tilde[ns] < k0_srs + nrb_srs) ||
(cfg->grant.n_prb_tilde[ns] + cfg->grant.L_prb >= k0_srs &&
cfg->grant.n_prb_tilde[ns] + cfg->grant.L_prb < k0_srs + nrb_srs) ||
(cfg->grant.n_prb_tilde[ns] <= k0_srs && cfg->grant.n_prb_tilde[ns] + cfg->grant.L_prb >= k0_srs + nrb_srs))
{
q->shortened = true;
}
}
}
}
}
}
/* Compute final number of bits and RE */
srslte_ra_ul_grant_to_nbits(&cfg->grant, q->cell.cp, q->shortened?1:0, &cfg->nbits);
cfg->sf_idx = tti%10; cfg->sf_idx = tti%10;
cfg->tti = tti; cfg->tti = tti;
cfg->rv = rvidx; cfg->rv = rv_idx;
cfg->cp = q->cell.cp; cfg->cp = q->cell.cp;
return SRSLTE_SUCCESS; // Save UCI configuration
memcpy(&cfg->uci_cfg, uci_cfg, sizeof(srslte_uci_cfg_t));
return SRSLTE_SUCCESS;
} else {
return SRSLTE_ERROR_INVALID_INPUTS;
}
} }
/* Precalculate the PUSCH scramble sequences for a given RNTI. This function takes a while /* Precalculate the PUSCH scramble sequences for a given RNTI. This function takes a while

@ -111,6 +111,8 @@ uint32_t ra_re_x_prb(uint32_t subframe, uint32_t slot, uint32_t prb_idx, uint32_
int srslte_ul_dci_to_grant_prb_allocation(srslte_ra_ul_dci_t *dci, srslte_ra_ul_grant_t *grant, uint32_t n_rb_ho, uint32_t nof_prb) int srslte_ul_dci_to_grant_prb_allocation(srslte_ra_ul_dci_t *dci, srslte_ra_ul_grant_t *grant, uint32_t n_rb_ho, uint32_t nof_prb)
{ {
bzero(grant, sizeof(srslte_ra_ul_grant_t)); bzero(grant, sizeof(srslte_ra_ul_grant_t));
grant->ncs_dmrs = dci->n_dmrs;
grant->L_prb = dci->type2_alloc.L_crb; grant->L_prb = dci->type2_alloc.L_crb;
uint32_t n_prb_1 = dci->type2_alloc.RB_start; uint32_t n_prb_1 = dci->type2_alloc.RB_start;
uint32_t n_rb_pusch = 0; uint32_t n_rb_pusch = 0;
@ -256,6 +258,18 @@ uint32_t srslte_ra_dl_grant_nof_re(srslte_ra_dl_grant_t *grant, srslte_cell_t ce
return nof_re; return nof_re;
} }
char* srslte_ra_dl_dci_string(srslte_ra_dl_dci_t *dci) {
switch(dci->dci_format) {
case SRSLTE_RA_DCI_FORMAT1:
return "1";
case SRSLTE_RA_DCI_FORMAT1A:
return "1A";
case SRSLTE_RA_DCI_FORMAT1C:
return "1C";
default:
return "";
}
}
/** Compute PRB allocation for Downlink as defined in 7.1.6 of 36.213 */ /** Compute PRB allocation for Downlink as defined in 7.1.6 of 36.213 */
static int dl_dci_to_grant_prb_allocation(srslte_ra_dl_dci_t *dci, srslte_ra_dl_grant_t *grant, uint32_t nof_prb) { static int dl_dci_to_grant_prb_allocation(srslte_ra_dl_dci_t *dci, srslte_ra_dl_grant_t *grant, uint32_t nof_prb) {

@ -521,9 +521,9 @@ int srslte_ulsch_uci_encode(srslte_sch_t *q,
// Encode RI // Encode RI
if (uci_data.uci_ri_len > 0) { if (uci_data.uci_ri_len > 0) {
float beta = beta_ri_offset[uci_data.I_offset_ri]; float beta = beta_ri_offset[cfg->uci_cfg.I_offset_ri];
if (cfg->cb_segm.tbs == 0) { if (cfg->cb_segm.tbs == 0) {
beta /= beta_cqi_offset[uci_data.I_offset_cqi]; beta /= beta_cqi_offset[cfg->uci_cfg.I_offset_cqi];
} }
ret = srslte_uci_encode_ri(cfg, uci_data.uci_ri, uci_data.uci_cqi_len, beta, nb_q/Qm, q_bits); ret = srslte_uci_encode_ri(cfg, uci_data.uci_ri, uci_data.uci_cqi_len, beta, nb_q/Qm, q_bits);
if (ret < 0) { if (ret < 0) {
@ -536,7 +536,7 @@ int srslte_ulsch_uci_encode(srslte_sch_t *q,
if (uci_data.uci_cqi_len > 0) { if (uci_data.uci_cqi_len > 0) {
ret = srslte_uci_encode_cqi_pusch(&q->uci_cqi, cfg, ret = srslte_uci_encode_cqi_pusch(&q->uci_cqi, cfg,
uci_data.uci_cqi, uci_data.uci_cqi_len, uci_data.uci_cqi, uci_data.uci_cqi_len,
beta_cqi_offset[uci_data.I_offset_cqi], beta_cqi_offset[cfg->uci_cfg.I_offset_cqi],
Q_prime_ri, g_bits); Q_prime_ri, g_bits);
if (ret < 0) { if (ret < 0) {
return ret; return ret;
@ -562,9 +562,9 @@ int srslte_ulsch_uci_encode(srslte_sch_t *q,
// Encode (and interleave) ACK // Encode (and interleave) ACK
if (uci_data.uci_ack_len > 0) { if (uci_data.uci_ack_len > 0) {
float beta = beta_harq_offset[uci_data.I_offset_ack]; float beta = beta_harq_offset[cfg->uci_cfg.I_offset_ack];
if (cfg->cb_segm.tbs == 0) { if (cfg->cb_segm.tbs == 0) {
beta /= beta_cqi_offset[uci_data.I_offset_cqi]; beta /= beta_cqi_offset[cfg->uci_cfg.I_offset_cqi];
} }
ret = srslte_uci_encode_ack(cfg, uci_data.uci_ack, uci_data.uci_cqi_len, beta, nb_q/Qm, q_bits); ret = srslte_uci_encode_ack(cfg, uci_data.uci_ack, uci_data.uci_cqi_len, beta, nb_q/Qm, q_bits);
if (ret < 0) { if (ret < 0) {

@ -137,17 +137,18 @@ int main(int argc, char **argv) {
bzero(ce, sizeof(cf_t*)*SRSLTE_MAX_PORTS); bzero(ce, sizeof(cf_t*)*SRSLTE_MAX_PORTS);
bzero(slot_symbols, sizeof(cf_t*)*SRSLTE_MAX_PORTS); bzero(slot_symbols, sizeof(cf_t*)*SRSLTE_MAX_PORTS);
pdsch_cfg.grant.mcs.tbs = tbs; srslte_ra_dl_grant_t grant;
pdsch_cfg.grant.mcs.mod = modulation; grant.mcs.tbs = tbs;
pdsch_cfg.grant.Qm = srslte_mod_bits_x_symbol(pdsch_cfg.grant.mcs.mod); grant.mcs.mod = modulation;
pdsch_cfg.grant.nof_prb = cell.nof_prb; // Allocate all PRB grant.Qm = srslte_mod_bits_x_symbol(grant.mcs.mod);
for (i=0;i<pdsch_cfg.grant.nof_prb;i++) { grant.nof_prb = cell.nof_prb; // Allocate all PRB
pdsch_cfg.grant.prb_idx[0][i] = true; for (i=0;i<grant.nof_prb;i++) {
grant.prb_idx[0][i] = true;
} }
memcpy(&pdsch_cfg.grant.prb_idx[1], &pdsch_cfg.grant.prb_idx[0], SRSLTE_MAX_PRB * sizeof(bool)); memcpy(&grant.prb_idx[1], &grant.prb_idx[0], SRSLTE_MAX_PRB * sizeof(bool));
/* Configure PDSCH */ /* Configure PDSCH */
if (srslte_pdsch_cfg(&pdsch_cfg, cell, NULL, cfi, subframe, 1234, 0)) { if (srslte_pdsch_cfg(&pdsch_cfg, cell, &grant, cfi, subframe, 1234, 0)) {
fprintf(stderr, "Error configuring PDSCH\n"); fprintf(stderr, "Error configuring PDSCH\n");
exit(-1); exit(-1);
} }
@ -193,9 +194,9 @@ int main(int argc, char **argv) {
} }
if (SRSLTE_VERBOSE_ISNONE()) { if (SRSLTE_VERBOSE_ISNONE()) {
printf("Decoding TBS: %d\r",pdsch_cfg.grant.mcs.tbs); printf("Decoding TBS: %d\r",grant.mcs.tbs);
} }
for (i=0;i<pdsch_cfg.grant.mcs.tbs;i++) { for (i=0;i<grant.mcs.tbs;i++) {
data[i] = rand()%2; data[i] = rand()%2;
} }
@ -223,11 +224,11 @@ int main(int argc, char **argv) {
gettimeofday(&t[2], NULL); gettimeofday(&t[2], NULL);
get_time_interval(t); get_time_interval(t);
if (r) { if (r) {
printf("Error decoding TBS: %d\n", pdsch_cfg.grant.mcs.tbs); printf("Error decoding TBS: %d\n", grant.mcs.tbs);
ret = -1; ret = -1;
goto quit; goto quit;
} else { } else {
printf("DECODED OK in %d:%d (%.2f Mbps)\n", (int) t[0].tv_sec, (int) t[0].tv_usec, (float) pdsch_cfg.grant.mcs.tbs/t[0].tv_usec); printf("DECODED OK in %d:%d (%.2f Mbps)\n", (int) t[0].tv_sec, (int) t[0].tv_usec, (float) grant.mcs.tbs/t[0].tv_usec);
} }
} }
ret = 0; ret = 0;

@ -110,12 +110,13 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
nof_re = 2 * SRSLTE_CP_NORM_NSYMB * cell.nof_prb * SRSLTE_NRE; nof_re = 2 * SRSLTE_CP_NORM_NSYMB * cell.nof_prb * SRSLTE_NRE;
cfg.grant.mcs.tbs = mxGetScalar(TBS); srslte_ra_dl_grant_t grant;
if (cfg.grant.mcs.tbs == 0) { grant.mcs.tbs = mxGetScalar(TBS);
if (grant.mcs.tbs == 0) {
mexErrMsgTxt("Error trblklen is zero\n"); mexErrMsgTxt("Error trblklen is zero\n");
return; return;
} }
if (srslte_cbsegm(&cfg.cb_segm, cfg.grant.mcs.tbs)) { if (srslte_cbsegm(&cfg.cb_segm, grant.mcs.tbs)) {
mexErrMsgTxt("Error computing CB segmentation\n"); mexErrMsgTxt("Error computing CB segmentation\n");
return; return;
} }
@ -128,11 +129,11 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
char *mod_str = mexutils_get_char_struct(PDSCHCFG, "Modulation"); char *mod_str = mexutils_get_char_struct(PDSCHCFG, "Modulation");
if (!strcmp(mod_str, "QPSK")) { if (!strcmp(mod_str, "QPSK")) {
cfg.grant.mcs.mod = SRSLTE_MOD_QPSK; grant.mcs.mod = SRSLTE_MOD_QPSK;
} else if (!strcmp(mod_str, "16QAM")) { } else if (!strcmp(mod_str, "16QAM")) {
cfg.grant.mcs.mod = SRSLTE_MOD_16QAM; grant.mcs.mod = SRSLTE_MOD_16QAM;
} else if (!strcmp(mod_str, "64QAM")) { } else if (!strcmp(mod_str, "64QAM")) {
cfg.grant.mcs.mod = SRSLTE_MOD_64QAM; grant.mcs.mod = SRSLTE_MOD_64QAM;
} else { } else {
mexErrMsgTxt("Unknown modulation\n"); mexErrMsgTxt("Unknown modulation\n");
return; return;
@ -149,23 +150,23 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
} }
// Only localized PRB supported // Only localized PRB supported
cfg.grant.nof_prb = mexutils_read_f(p, &prbset); grant.nof_prb = mexutils_read_f(p, &prbset);
for (i=0;i<cell.nof_prb;i++) { for (i=0;i<cell.nof_prb;i++) {
cfg.grant.prb_idx[0][i] = false; grant.prb_idx[0][i] = false;
for (int j=0;j<cfg.grant.nof_prb && !cfg.grant.prb_idx[0][i];j++) { for (int j=0;j<grant.nof_prb && !grant.prb_idx[0][i];j++) {
if ((int) prbset[j] == i) { if ((int) prbset[j] == i) {
cfg.grant.prb_idx[0][i] = true; grant.prb_idx[0][i] = true;
} }
} }
cfg.grant.prb_idx[1][i] = cfg.grant.prb_idx[0][i]; grant.prb_idx[1][i] = grant.prb_idx[0][i];
} }
free(prbset); free(prbset);
/* Configure rest of pdsch_cfg parameters */ /* Configure rest of pdsch_cfg parameters */
cfg.grant.Qm = srslte_mod_bits_x_symbol(cfg.grant.mcs.mod); grant.Qm = srslte_mod_bits_x_symbol(grant.mcs.mod);
if (srslte_pdsch_cfg(&cfg, cell, NULL, cfi, cfg.sf_idx, (uint16_t) (rnti32 & 0xffff), cfg.rv)) { if (srslte_pdsch_cfg(&cfg, cell, &grant, cfi, cfg.sf_idx, (uint16_t) (rnti32 & 0xffff), cfg.rv)) {
fprintf(stderr, "Error configuring PDSCH\n"); fprintf(stderr, "Error configuring PDSCH\n");
exit(-1); exit(-1);
} }
@ -206,7 +207,7 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
noise_power = srslte_chest_dl_get_noise_estimate(&chest); noise_power = srslte_chest_dl_get_noise_estimate(&chest);
} }
uint8_t *data = malloc(sizeof(uint8_t) * cfg.grant.mcs.tbs); uint8_t *data = malloc(sizeof(uint8_t) * grant.mcs.tbs);
if (!data) { if (!data) {
return; return;
} }
@ -218,7 +219,7 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
plhs[0] = mxCreateLogicalScalar(r == 0); plhs[0] = mxCreateLogicalScalar(r == 0);
} }
if (nlhs >= 2) { if (nlhs >= 2) {
mexutils_write_uint8(data, &plhs[1], cfg.grant.mcs.tbs, 1); mexutils_write_uint8(data, &plhs[1], grant.mcs.tbs, 1);
} }
if (nlhs >= 3) { if (nlhs >= 3) {
mexutils_write_cf(pdsch.symbols[0], &plhs[2], cfg.nbits.nof_re, 1); mexutils_write_cf(pdsch.symbols[0], &plhs[2], cfg.nbits.nof_re, 1);

@ -91,7 +91,7 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
} }
srslte_pucch_cfg_t pucch_cfg; srslte_pucch_cfg_t pucch_cfg;
bzero(&pucch_cfg, sizeof(srslte_pucch_cfg_t)); bzero(&pucch_cfg, sizeof(srslte_pucch_cfg_t));
pucch_cfg.beta_pucch = 1.0;
if (mexutils_read_uint32_struct(PUCCHCFG, "DeltaShift", &pucch_cfg.delta_pucch_shift)) { if (mexutils_read_uint32_struct(PUCCHCFG, "DeltaShift", &pucch_cfg.delta_pucch_shift)) {
mexErrMsgTxt("Field DeltaShift not found in PUCCHCFG\n"); mexErrMsgTxt("Field DeltaShift not found in PUCCHCFG\n");
return; return;
@ -190,7 +190,10 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
} }
bzero(dmrs_pucch, sizeof(cf_t)*SRSLTE_NRE*3*2); bzero(dmrs_pucch, sizeof(cf_t)*SRSLTE_NRE*3*2);
srslte_refsignal_ul_set_cfg(&pucch_dmrs, NULL, &pucch_cfg, NULL, group_hopping_en, false); srslte_refsignal_dmrs_pusch_cfg_t pusch_cfg;
pusch_cfg.group_hopping_en = group_hopping_en;
pusch_cfg.sequence_hopping_en = false;
srslte_refsignal_ul_set_cfg(&pucch_dmrs, &pusch_cfg, &pucch_cfg, NULL);
if (srslte_refsignal_dmrs_pucch_gen(&pucch_dmrs, format, n_pucch, sf_idx, pucch2_bits, 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"); mexErrMsgTxt("Error generating PUCCH DMRS\n");

@ -124,7 +124,7 @@ int main(int argc, char **argv) {
for (uint32_t n_pucch=1;n_pucch<130;n_pucch++) { for (uint32_t n_pucch=1;n_pucch<130;n_pucch++) {
struct timeval t[3]; struct timeval t[3];
pucch_cfg.beta_pucch = 1.0;
pucch_cfg.delta_pucch_shift = d; pucch_cfg.delta_pucch_shift = d;
bool group_hopping_en = false; bool group_hopping_en = false;
pucch_cfg.N_cs = ncs; pucch_cfg.N_cs = ncs;
@ -140,7 +140,11 @@ int main(int argc, char **argv) {
fprintf(stderr, "Error encoding PUCCH\n"); fprintf(stderr, "Error encoding PUCCH\n");
goto quit; goto quit;
} }
srslte_refsignal_ul_set_cfg(&dmrs, NULL, &pucch_cfg, NULL, group_hopping_en, false);
srslte_refsignal_dmrs_pusch_cfg_t pusch_cfg;
pusch_cfg.group_hopping_en = group_hopping_en;
pusch_cfg.sequence_hopping_en = false;
srslte_refsignal_ul_set_cfg(&dmrs, &pusch_cfg, &pucch_cfg, NULL);
if (srslte_refsignal_dmrs_pucch_gen(&dmrs, format, n_pucch, subframe, pucch2_bits, pucch_dmrs)) { if (srslte_refsignal_dmrs_pucch_gen(&dmrs, format, n_pucch, subframe, pucch2_bits, pucch_dmrs)) {
fprintf(stderr, "Error encoding PUCCH\n"); fprintf(stderr, "Error encoding PUCCH\n");

@ -86,13 +86,17 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
mexErrMsgTxt("Field NSubframe not found in UE config\n"); mexErrMsgTxt("Field NSubframe not found in UE config\n");
return; return;
} }
srslte_ra_ul_grant_t grant;
bzero(&grant, sizeof(srslte_ra_ul_grant_t));
char *mod_str = mexutils_get_char_struct(PUSCHCFG, "Modulation"); char *mod_str = mexutils_get_char_struct(PUSCHCFG, "Modulation");
if (!strcmp(mod_str, "QPSK")) { if (!strcmp(mod_str, "QPSK")) {
cfg.grant.mcs.mod = SRSLTE_MOD_QPSK; grant.mcs.mod = SRSLTE_MOD_QPSK;
} else if (!strcmp(mod_str, "16QAM")) { } else if (!strcmp(mod_str, "16QAM")) {
cfg.grant.mcs.mod = SRSLTE_MOD_16QAM; grant.mcs.mod = SRSLTE_MOD_16QAM;
} else if (!strcmp(mod_str, "64QAM")) { } else if (!strcmp(mod_str, "64QAM")) {
cfg.grant.mcs.mod = SRSLTE_MOD_64QAM; grant.mcs.mod = SRSLTE_MOD_64QAM;
} else { } else {
mexErrMsgTxt("Unknown modulation\n"); mexErrMsgTxt("Unknown modulation\n");
return; return;
@ -113,33 +117,33 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
if (N_srs == 1) { if (N_srs == 1) {
pusch.shortened = true; pusch.shortened = true;
} }
cfg.grant.L_prb = mexutils_read_f(p, &prbset);
cfg.grant.n_prb[0] = prbset[0]; grant.L_prb = mexutils_read_f(p, &prbset);
cfg.grant.n_prb[1] = prbset[0]; grant.n_prb[0] = prbset[0];
cfg.grant.M_sc = cfg.grant.L_prb*SRSLTE_NRE; grant.n_prb[1] = prbset[0];
cfg.grant.M_sc_init = cfg.grant.M_sc; // FIXME: What should M_sc_init be? free(prbset);
cfg.grant.Qm = srslte_mod_bits_x_symbol(cfg.grant.mcs.mod);
if (srslte_pusch_cfg(&pusch, &cfg, NULL, NULL, NULL, cfg.sf_idx, 0, cfg.rv)) { uint8_t *trblkin = NULL;
grant.mcs.tbs = mexutils_read_uint8(TRBLKIN, &trblkin);
grant.M_sc = grant.L_prb*SRSLTE_NRE;
grant.M_sc_init = grant.M_sc; // FIXME: What should M_sc_init be?
grant.Qm = srslte_mod_bits_x_symbol(grant.mcs.mod);
if (srslte_pusch_cfg(&pusch, &cfg, &grant, NULL, NULL, NULL, cfg.sf_idx, cfg.rv, 0)) {
fprintf(stderr, "Error configuring PDSCH\n"); fprintf(stderr, "Error configuring PDSCH\n");
exit(-1); exit(-1);
} }
free(prbset); mexPrintf("L_prb: %d, n_prb: %d\n", grant.L_prb, grant.n_prb[0]);
mexPrintf("L_prb: %d, n_prb: %d\n", cfg.grant.L_prb, cfg.grant.n_prb[0]);
uint8_t *trblkin = NULL;
cfg.grant.mcs.tbs = mexutils_read_uint8(TRBLKIN, &trblkin);
srslte_softbuffer_tx_t softbuffer; srslte_softbuffer_tx_t softbuffer;
if (srslte_softbuffer_tx_init(&softbuffer, cell)) { if (srslte_softbuffer_tx_init(&softbuffer, cell)) {
mexErrMsgTxt("Error initiating soft buffer\n"); mexErrMsgTxt("Error initiating soft buffer\n");
return; return;
} }
if (srslte_cbsegm(&cfg.cb_segm, cfg.grant.mcs.tbs)) {
mexErrMsgTxt("Error computing CB segmentation\n");
return;
}
uint32_t nof_re = SRSLTE_NRE*cell.nof_prb*2*SRSLTE_CP_NSYMB(cell.cp); uint32_t nof_re = SRSLTE_NRE*cell.nof_prb*2*SRSLTE_CP_NSYMB(cell.cp);
cf_t *sf_symbols = srslte_vec_malloc(sizeof(cf_t) * nof_re); cf_t *sf_symbols = srslte_vec_malloc(sizeof(cf_t) * nof_re);
@ -168,26 +172,26 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
float beta; float beta;
if (mexutils_read_float_struct(PUSCHCFG, "BetaCQI", &beta)) { if (mexutils_read_float_struct(PUSCHCFG, "BetaCQI", &beta)) {
uci_data.I_offset_cqi = 7; cfg.uci_cfg.I_offset_cqi = 7;
} else { } else {
uci_data.I_offset_cqi = srslte_sch_find_Ioffset_cqi(beta); cfg.uci_cfg.I_offset_cqi = srslte_sch_find_Ioffset_cqi(beta);
} }
if (mexutils_read_float_struct(PUSCHCFG, "BetaRI", &beta)) { if (mexutils_read_float_struct(PUSCHCFG, "BetaRI", &beta)) {
uci_data.I_offset_ri = 2; cfg.uci_cfg.I_offset_ri = 2;
} else { } else {
uci_data.I_offset_ri = srslte_sch_find_Ioffset_ri(beta); cfg.uci_cfg.I_offset_ri = srslte_sch_find_Ioffset_ri(beta);
} }
if (mexutils_read_float_struct(PUSCHCFG, "BetaACK", &beta)) { if (mexutils_read_float_struct(PUSCHCFG, "BetaACK", &beta)) {
uci_data.I_offset_ack = 0; cfg.uci_cfg.I_offset_ack = 0;
} else { } else {
uci_data.I_offset_ack = srslte_sch_find_Ioffset_ack(beta); cfg.uci_cfg.I_offset_ack = srslte_sch_find_Ioffset_ack(beta);
} }
mexPrintf("TRBL_len: %d, CQI_len: %d, ACK_len: %d (%d), RI_len: %d (%d)\n", cfg.grant.mcs.tbs, mexPrintf("TRBL_len: %d, CQI_len: %d, ACK_len: %d (%d), RI_len: %d (%d)\n", grant.mcs.tbs,
uci_data.uci_cqi_len, uci_data.uci_ack_len, uci_data.uci_ack, uci_data.uci_ri_len, uci_data.uci_ri); uci_data.uci_cqi_len, uci_data.uci_ack_len, uci_data.uci_ack, uci_data.uci_ri_len, uci_data.uci_ri);
mexPrintf("I_cqi: %d, I_ri: %d, I_ack=%d\n", uci_data.I_offset_cqi, uci_data.I_offset_ri, uci_data.I_offset_ack); mexPrintf("I_cqi: %d, I_ri: %d, I_ack=%d\n", cfg.uci_cfg.I_offset_cqi, cfg.uci_cfg.I_offset_ri, cfg.uci_cfg.I_offset_ack);
mexPrintf("NofRE: %d, NofBits: %d, TBS: %d, N_srs=%d\n", cfg.nbits.nof_re, cfg.nbits.nof_bits, cfg.grant.mcs.tbs, N_srs); mexPrintf("NofRE: %d, NofBits: %d, TBS: %d, N_srs=%d\n", cfg.nbits.nof_re, cfg.nbits.nof_bits, grant.mcs.tbs, N_srs);
int r = srslte_pusch_uci_encode(&pusch, &cfg, &softbuffer, trblkin, uci_data, sf_symbols); int r = srslte_pusch_uci_encode(&pusch, &cfg, &softbuffer, trblkin, uci_data, sf_symbols);
if (r < 0) { if (r < 0) {
mexErrMsgTxt("Error encoding PUSCH\n"); mexErrMsgTxt("Error encoding PUSCH\n");

@ -135,11 +135,15 @@ int main(int argc, char **argv) {
srslte_dci_msg_t dci_msg; srslte_dci_msg_t dci_msg;
srslte_dci_msg_pack_pusch(&dci, &dci_msg, cell.nof_prb); srslte_dci_msg_pack_pusch(&dci, &dci_msg, cell.nof_prb);
srslte_ra_ul_grant_t grant;
if (srslte_dci_msg_to_ul_grant(&dci_msg, cell.nof_prb, 0, NULL, &grant)) {
return false;
}
srslte_pusch_hopping_cfg_t ul_hopping; srslte_pusch_hopping_cfg_t ul_hopping;
ul_hopping.n_sb = 1; ul_hopping.n_sb = 1;
ul_hopping.hopping_offset = 0; ul_hopping.hopping_offset = 0;
ul_hopping.hop_mode = SRSLTE_PUSCH_HOP_MODE_INTER_SF; ul_hopping.hop_mode = SRSLTE_PUSCH_HOP_MODE_INTER_SF;
ul_hopping.current_tx_nb = 0;
if (srslte_pusch_init(&pusch, cell)) { if (srslte_pusch_init(&pusch, cell)) {
fprintf(stderr, "Error creating PDSCH object\n"); fprintf(stderr, "Error creating PDSCH object\n");
@ -147,35 +151,38 @@ int main(int argc, char **argv) {
} }
/* Configure PUSCH */ /* Configure PUSCH */
if (srslte_pusch_cfg(&pusch, &cfg, &dci_msg, &ul_hopping, NULL, subframe, 0, 0)) {
printf("Encoding rv_idx=%d\n",rv_idx);
srslte_uci_cfg_t uci_cfg;
uci_cfg.I_offset_cqi = 7;
uci_cfg.I_offset_ri = 2;
uci_cfg.I_offset_ack = 4;
if (srslte_pusch_cfg(&pusch, &cfg, &grant, &uci_cfg, &ul_hopping, NULL, subframe, 0, 0)) {
fprintf(stderr, "Error configuring PDSCH\n"); fprintf(stderr, "Error configuring PDSCH\n");
exit(-1); exit(-1);
} }
srslte_pusch_set_rnti(&pusch, 1234); srslte_pusch_set_rnti(&pusch, 1234);
printf("Encoding rv_idx=%d\n",rv_idx);
cfg.rv = 0;
cfg.sf_idx = subframe;
uint8_t tmp[20];
for (uint32_t i=0;i<20;i++) {
tmp[i] = 1;
}
srslte_uci_data_t uci_data; srslte_uci_data_t uci_data;
bzero(&uci_data, sizeof(srslte_uci_data_t)); bzero(&uci_data, sizeof(srslte_uci_data_t));
uci_data.I_offset_cqi = 7;
uci_data.I_offset_ri = 2;
uci_data.I_offset_ack = 4;
uci_data.uci_cqi_len = 8; uci_data.uci_cqi_len = 8;
uci_data.uci_ri_len = 0; uci_data.uci_ri_len = 0;
uci_data.uci_ack_len = 1; uci_data.uci_ack_len = 1;
uint8_t tmp[20];
for (uint32_t i=0;i<20;i++) {
tmp[i] = 1;
}
uci_data.uci_cqi = tmp; uci_data.uci_cqi = tmp;
uci_data.uci_ri = 0; uci_data.uci_ri = 0;
uci_data.uci_ack = 0; uci_data.uci_ack = 0;
uint32_t nof_re = SRSLTE_NRE*cell.nof_prb*2*SRSLTE_CP_NSYMB(cell.cp); uint32_t nof_re = SRSLTE_NRE*cell.nof_prb*2*SRSLTE_CP_NSYMB(cell.cp);
sf_symbols = srslte_vec_malloc(sizeof(cf_t) * nof_re); sf_symbols = srslte_vec_malloc(sizeof(cf_t) * nof_re);
if (!sf_symbols) { if (!sf_symbols) {

@ -99,19 +99,19 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
float beta; float beta;
if (mexutils_read_float_struct(PUSCHCFG, "BetaCQI", &beta)) { if (mexutils_read_float_struct(PUSCHCFG, "BetaCQI", &beta)) {
uci_data.I_offset_cqi = 7; cfg.uci_cfg.I_offset_cqi = 7;
} else { } else {
uci_data.I_offset_cqi = srslte_sch_find_Ioffset_cqi(beta); cfg.uci_cfg.I_offset_cqi = srslte_sch_find_Ioffset_cqi(beta);
} }
if (mexutils_read_float_struct(PUSCHCFG, "BetaRI", &beta)) { if (mexutils_read_float_struct(PUSCHCFG, "BetaRI", &beta)) {
uci_data.I_offset_ri = 2; cfg.uci_cfg.I_offset_ri = 2;
} else { } else {
uci_data.I_offset_ri = srslte_sch_find_Ioffset_ri(beta); cfg.uci_cfg.I_offset_ri = srslte_sch_find_Ioffset_ri(beta);
} }
if (mexutils_read_float_struct(PUSCHCFG, "BetaACK", &beta)) { if (mexutils_read_float_struct(PUSCHCFG, "BetaACK", &beta)) {
uci_data.I_offset_ack = 0; cfg.uci_cfg.I_offset_ack = 0;
} else { } else {
uci_data.I_offset_ack = srslte_sch_find_Ioffset_ack(beta); cfg.uci_cfg.I_offset_ack = srslte_sch_find_Ioffset_ack(beta);
} }
char *mod_str = mexutils_get_char_struct(PUSCHCFG, "Modulation"); char *mod_str = mexutils_get_char_struct(PUSCHCFG, "Modulation");

@ -203,12 +203,12 @@ int srslte_ue_dl_decode_fft_estimate(srslte_ue_dl_t *q, cf_t *input, uint32_t sf
} }
} }
int srslte_ue_dl_cfg_grant(srslte_ue_dl_t *q, srslte_dci_msg_t *dci_msg, uint32_t cfi, uint32_t sf_idx, uint16_t rnti, uint32_t rvidx) int srslte_ue_dl_cfg_grant(srslte_ue_dl_t *q, srslte_ra_dl_grant_t *grant, uint32_t cfi, uint32_t sf_idx, uint16_t rnti, uint32_t rvidx)
{ {
return srslte_pdsch_cfg(&q->pdsch_cfg, q->cell, dci_msg, cfi, sf_idx, rnti, rvidx); return srslte_pdsch_cfg(&q->pdsch_cfg, q->cell, grant, cfi, sf_idx, rnti, rvidx);
} }
int srslte_ue_dl_decode_rnti_rv_packet(srslte_ue_dl_t *q, srslte_dci_msg_t *dci_msg, uint8_t *data, int srslte_ue_dl_decode_rnti_rv_packet(srslte_ue_dl_t *q, srslte_ra_dl_grant_t *grant, uint8_t *data,
uint32_t cfi, uint32_t sf_idx, uint16_t rnti, uint32_t rvidx) uint32_t cfi, uint32_t sf_idx, uint16_t rnti, uint32_t rvidx)
{ {
int ret = SRSLTE_ERROR; int ret = SRSLTE_ERROR;
@ -216,7 +216,7 @@ int srslte_ue_dl_decode_rnti_rv_packet(srslte_ue_dl_t *q, srslte_dci_msg_t *dci_
q->nof_detected++; q->nof_detected++;
/* Setup PDSCH configuration for this CFI, SFIDX and RVIDX */ /* Setup PDSCH configuration for this CFI, SFIDX and RVIDX */
if (srslte_ue_dl_cfg_grant(q, dci_msg, cfi, sf_idx, rnti, rvidx)) { if (srslte_ue_dl_cfg_grant(q, grant, cfi, sf_idx, rnti, rvidx)) {
return SRSLTE_ERROR; return SRSLTE_ERROR;
} }
@ -278,6 +278,22 @@ uint32_t srslte_ue_dl_get_ncce(srslte_ue_dl_t *q) {
} }
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) 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_rnti_type_t rnti_type;
if (rnti == SRSLTE_SIRNTI) {
rnti_type = SRSLTE_RNTI_SI;
} else if (rnti == SRSLTE_PRNTI) {
rnti_type = SRSLTE_RNTI_PCH;
} else if (rnti <= SRSLTE_RARNTI_END) {
rnti_type = SRSLTE_RNTI_RAR;
} else {
rnti_type = SRSLTE_RNTI_USER;
}
return srslte_ue_dl_find_dl_dci_type(q, dci_msg, cfi, sf_idx, rnti, rnti_type);
}
int srslte_ue_dl_find_dl_dci_type(srslte_ue_dl_t *q, srslte_dci_msg_t *dci_msg, uint32_t cfi, uint32_t sf_idx,
uint16_t rnti, srslte_rnti_type_t rnti_type)
{ {
srslte_dci_location_t locations[MAX_CANDIDATES]; srslte_dci_location_t locations[MAX_CANDIDATES];
uint32_t nof_locations; uint32_t nof_locations;
@ -285,7 +301,7 @@ int srslte_ue_dl_find_dl_dci(srslte_ue_dl_t *q, srslte_dci_msg_t *dci_msg, uint3
srslte_dci_format_t *formats = NULL; srslte_dci_format_t *formats = NULL;
/* Generate PDCCH candidates */ /* Generate PDCCH candidates */
if (rnti == SRSLTE_SIRNTI) { if (rnti_type == SRSLTE_RNTI_SI || rnti_type == SRSLTE_RNTI_PCH || rnti_type == SRSLTE_RNTI_RAR) {
nof_locations = srslte_pdcch_common_locations(&q->pdcch, locations, MAX_CANDIDATES, q->cfi); nof_locations = srslte_pdcch_common_locations(&q->pdcch, locations, MAX_CANDIDATES, q->cfi);
formats = common_formats; formats = common_formats;
nof_formats = nof_common_formats; nof_formats = nof_common_formats;
@ -323,6 +339,8 @@ int srslte_ue_dl_find_dl_dci(srslte_ue_dl_t *q, srslte_dci_msg_t *dci_msg, uint3
int srslte_ue_dl_decode_rnti_rv(srslte_ue_dl_t *q, cf_t *input, uint8_t *data, uint32_t sf_idx, uint16_t rnti, uint32_t rvidx) int srslte_ue_dl_decode_rnti_rv(srslte_ue_dl_t *q, cf_t *input, uint8_t *data, uint32_t sf_idx, uint16_t rnti, uint32_t rvidx)
{ {
srslte_dci_msg_t dci_msg; srslte_dci_msg_t dci_msg;
srslte_ra_dl_dci_t dci_unpacked;
srslte_ra_dl_grant_t grant;
int ret = SRSLTE_ERROR; int ret = SRSLTE_ERROR;
if ((ret = srslte_ue_dl_decode_fft_estimate(q, input, sf_idx, &q->cfi)) < 0) { if ((ret = srslte_ue_dl_decode_fft_estimate(q, input, sf_idx, &q->cfi)) < 0) {
@ -337,7 +355,13 @@ int srslte_ue_dl_decode_rnti_rv(srslte_ue_dl_t *q, cf_t *input, uint8_t *data, u
int found_dci = srslte_ue_dl_find_dl_dci(q, &dci_msg, q->cfi, sf_idx, rnti); int found_dci = srslte_ue_dl_find_dl_dci(q, &dci_msg, q->cfi, sf_idx, rnti);
if (found_dci == 1) { if (found_dci == 1) {
ret = srslte_ue_dl_decode_rnti_rv_packet(q, &dci_msg, data, q->cfi, sf_idx, rnti, rvidx);
if (srslte_dci_msg_to_dl_grant(&dci_msg, rnti, q->cell.nof_prb, &dci_unpacked, &grant)) {
fprintf(stderr, "Error unpacking DCI\n");
return SRSLTE_ERROR;
}
ret = srslte_ue_dl_decode_rnti_rv_packet(q, &grant, data, q->cfi, sf_idx, rnti, rvidx);
} }
if (found_dci == 1 && ret == SRSLTE_SUCCESS) { if (found_dci == 1 && ret == SRSLTE_SUCCESS) {

@ -183,6 +183,7 @@ int srslte_ue_sync_init(srslte_ue_sync_t *q,
} }
/* FIXME: Go for zerocopy only and eliminate this allocation */
q->input_buffer = srslte_vec_malloc(2*q->frame_len * sizeof(cf_t)); q->input_buffer = srslte_vec_malloc(2*q->frame_len * sizeof(cf_t));
if (!q->input_buffer) { if (!q->input_buffer) {
perror("malloc"); perror("malloc");
@ -260,7 +261,7 @@ void srslte_ue_sync_set_N_id_2(srslte_ue_sync_t *q, uint32_t N_id_2) {
} }
} }
static int find_peak_ok(srslte_ue_sync_t *q) { static int find_peak_ok(srslte_ue_sync_t *q, cf_t *input_buffer) {
if (srslte_sync_sss_detected(&q->sfind)) { if (srslte_sync_sss_detected(&q->sfind)) {
@ -278,7 +279,7 @@ static int find_peak_ok(srslte_ue_sync_t *q) {
if (q->frame_find_cnt >= q->nof_avg_find_frames || q->peak_idx < 2*q->fft_size) { if (q->frame_find_cnt >= q->nof_avg_find_frames || q->peak_idx < 2*q->fft_size) {
DEBUG("Realigning frame, reading %d samples\n", q->peak_idx+q->sf_len/2); DEBUG("Realigning frame, reading %d samples\n", q->peak_idx+q->sf_len/2);
/* Receive the rest of the subframe so that we are subframe aligned*/ /* Receive the rest of the subframe so that we are subframe aligned*/
if (q->recv_callback(q->stream, q->input_buffer, q->peak_idx+q->sf_len/2, &q->last_timestamp) < 0) { if (q->recv_callback(q->stream, input_buffer, q->peak_idx+q->sf_len/2, &q->last_timestamp) < 0) {
return SRSLTE_ERROR; return SRSLTE_ERROR;
} }
@ -350,7 +351,7 @@ static int track_peak_no(srslte_ue_sync_t *q) {
return 1; return 1;
} }
static int receive_samples(srslte_ue_sync_t *q) { static int receive_samples(srslte_ue_sync_t *q, cf_t *input_buffer) {
/* A negative time offset means there are samples in our buffer for the next subframe, /* A negative time offset means there are samples in our buffer for the next subframe,
because we are sampling too fast. because we are sampling too fast.
@ -360,7 +361,7 @@ static int receive_samples(srslte_ue_sync_t *q) {
} }
/* Get N subframes from the USRP getting more samples and keeping the previous samples, if any */ /* Get N subframes from the USRP getting more samples and keeping the previous samples, if any */
if (q->recv_callback(q->stream, &q->input_buffer[q->time_offset], q->frame_len - q->time_offset, &q->last_timestamp) < 0) { if (q->recv_callback(q->stream, &input_buffer[q->time_offset], q->frame_len - q->time_offset, &q->last_timestamp) < 0) {
return SRSLTE_ERROR; return SRSLTE_ERROR;
} }
@ -373,16 +374,24 @@ static int receive_samples(srslte_ue_sync_t *q) {
bool first_track = true; bool first_track = true;
int srslte_ue_sync_get_buffer(srslte_ue_sync_t *q, cf_t **sf_symbols) { int srslte_ue_sync_get_buffer(srslte_ue_sync_t *q, cf_t **sf_symbols) {
int ret = srslte_ue_sync_zerocopy(q, q->input_buffer);
if (sf_symbols) {
*sf_symbols = q->input_buffer;
}
return ret;
}
int srslte_ue_sync_zerocopy(srslte_ue_sync_t *q, cf_t *input_buffer) {
int ret = SRSLTE_ERROR_INVALID_INPUTS; int ret = SRSLTE_ERROR_INVALID_INPUTS;
uint32_t track_idx; uint32_t track_idx;
if (q != NULL && if (q != NULL &&
sf_symbols != NULL && input_buffer != NULL)
q->input_buffer != NULL)
{ {
if (q->file_mode) { if (q->file_mode) {
int n = srslte_filesource_read(&q->file_source, q->input_buffer, q->sf_len); int n = srslte_filesource_read(&q->file_source, input_buffer, q->sf_len);
if (n < 0) { if (n < 0) {
fprintf(stderr, "Error reading input file\n"); fprintf(stderr, "Error reading input file\n");
return SRSLTE_ERROR; return SRSLTE_ERROR;
@ -390,7 +399,7 @@ int srslte_ue_sync_get_buffer(srslte_ue_sync_t *q, cf_t **sf_symbols) {
if (n == 0) { if (n == 0) {
srslte_filesource_seek(&q->file_source, 0); srslte_filesource_seek(&q->file_source, 0);
q->sf_idx = 9; q->sf_idx = 9;
int n = srslte_filesource_read(&q->file_source, q->input_buffer, q->sf_len); int n = srslte_filesource_read(&q->file_source, input_buffer, q->sf_len);
if (n < 0) { if (n < 0) {
fprintf(stderr, "Error reading input file\n"); fprintf(stderr, "Error reading input file\n");
return SRSLTE_ERROR; return SRSLTE_ERROR;
@ -402,25 +411,24 @@ int srslte_ue_sync_get_buffer(srslte_ue_sync_t *q, cf_t **sf_symbols) {
} }
DEBUG("Reading %d samples. sf_idx = %d\n", q->sf_len, q->sf_idx); DEBUG("Reading %d samples. sf_idx = %d\n", q->sf_len, q->sf_idx);
ret = 1; ret = 1;
*sf_symbols = q->input_buffer;
} else { } else {
if (receive_samples(q)) { if (receive_samples(q, input_buffer)) {
fprintf(stderr, "Error receiving samples\n"); fprintf(stderr, "Error receiving samples\n");
return SRSLTE_ERROR; return SRSLTE_ERROR;
} }
switch (q->state) { switch (q->state) {
case SF_FIND: case SF_FIND:
ret = srslte_sync_find(&q->sfind, q->input_buffer, 0, &q->peak_idx); ret = srslte_sync_find(&q->sfind, input_buffer, 0, &q->peak_idx);
if (ret < 0) { if (ret < 0) {
fprintf(stderr, "Error finding correlation peak (%d)\n", ret); fprintf(stderr, "Error finding correlation peak (%d)\n", ret);
return SRSLTE_ERROR; return SRSLTE_ERROR;
} }
if (q->do_agc) { if (q->do_agc) {
srslte_agc_process(&q->agc, q->input_buffer, q->sf_len); srslte_agc_process(&q->agc, input_buffer, q->sf_len);
} }
if (ret == 1) { if (ret == 1) {
ret = find_peak_ok(q); ret = find_peak_ok(q, input_buffer);
} }
break; break;
case SF_TRACK: case SF_TRACK:
@ -434,7 +442,7 @@ int srslte_ue_sync_get_buffer(srslte_ue_sync_t *q, cf_t **sf_symbols) {
if (q->sf_idx == 0 || q->sf_idx == 5) { if (q->sf_idx == 0 || q->sf_idx == 5) {
if (q->do_agc) { if (q->do_agc) {
srslte_agc_process(&q->agc, q->input_buffer, q->sf_len); srslte_agc_process(&q->agc, input_buffer, q->sf_len);
} }
#ifdef MEASURE_EXEC_TIME #ifdef MEASURE_EXEC_TIME
@ -445,7 +453,7 @@ int srslte_ue_sync_get_buffer(srslte_ue_sync_t *q, cf_t **sf_symbols) {
track_idx = 0; track_idx = 0;
/* track PSS/SSS around the expected PSS position */ /* track PSS/SSS around the expected PSS position */
ret = srslte_sync_find(&q->strack, q->input_buffer, ret = srslte_sync_find(&q->strack, input_buffer,
q->frame_len - q->sf_len/2 - q->fft_size - q->strack.frame_size/2, q->frame_len - q->sf_len/2 - q->fft_size - q->strack.frame_size/2,
&track_idx); &track_idx);
if (ret < 0) { if (ret < 0) {
@ -476,13 +484,11 @@ int srslte_ue_sync_get_buffer(srslte_ue_sync_t *q, cf_t **sf_symbols) {
/* Do CFO Correction if not done in track and deliver the frame */ /* Do CFO Correction if not done in track and deliver the frame */
if (!q->strack.correct_cfo && q->correct_cfo) { if (!q->strack.correct_cfo && q->correct_cfo) {
srslte_cfo_correct(&q->sfind.cfocorr, srslte_cfo_correct(&q->sfind.cfocorr,
q->input_buffer, input_buffer,
q->input_buffer, input_buffer,
-srslte_sync_get_cfo(&q->strack) / q->fft_size); -srslte_sync_get_cfo(&q->strack) / q->fft_size);
} }
*sf_symbols = q->input_buffer;
break; break;
} }

@ -57,9 +57,9 @@ int srslte_ue_ul_init(srslte_ue_ul_t *q,
goto clean_exit; goto clean_exit;
} }
srslte_ofdm_set_freq_shift(&q->fft, 0.5); srslte_ofdm_set_freq_shift(&q->fft, 0.5);
srslte_ofdm_set_normalize(&q->fft, true); srslte_ofdm_set_normalize(&q->fft, false);
q->normalize_en = true; q->normalize_en = false;
if (srslte_cfo_init(&q->cfo, CURRENT_SFLEN)) { if (srslte_cfo_init(&q->cfo, CURRENT_SFLEN)) {
fprintf(stderr, "Error creating CFO object\n"); fprintf(stderr, "Error creating CFO object\n");
@ -182,32 +182,43 @@ int srslte_ue_ul_pregen_signals(srslte_ue_ul_t *q) {
return SRSLTE_SUCCESS; return SRSLTE_SUCCESS;
} }
void srslte_ue_ul_set_cfg(srslte_ue_ul_t *q, void srslte_ue_ul_set_cfg(srslte_ue_ul_t *q,
srslte_refsignal_dmrs_pusch_cfg_t *pusch_cfg, srslte_refsignal_dmrs_pusch_cfg_t *dmrs_cfg,
srslte_pucch_cfg_t *pucch_cfg, srslte_refsignal_srs_cfg_t *srs_cfg,
srslte_refsignal_srs_cfg_t *srs_cfg, srslte_pucch_cfg_t *pucch_cfg,
srslte_pucch_sched_t *pucch_sched, srslte_pucch_sched_t *pucch_sched,
bool group_hopping_en, srslte_uci_cfg_t *uci_cfg,
bool sequence_hopping_en) srslte_pusch_hopping_cfg_t *hopping_cfg)
{ {
srslte_refsignal_ul_set_cfg(&q->signals, pusch_cfg, pucch_cfg, srs_cfg, group_hopping_en, sequence_hopping_en); srslte_refsignal_ul_set_cfg(&q->signals, dmrs_cfg, pucch_cfg, srs_cfg);
srslte_pucch_set_cfg(&q->pucch, pucch_cfg, group_hopping_en); if (pucch_cfg && dmrs_cfg) {
srslte_pucch_set_cfg(&q->pucch, pucch_cfg, dmrs_cfg->group_hopping_en);
}
if (pucch_sched) { if (pucch_sched) {
memcpy(&q->pucch_sched, pucch_sched, sizeof(srslte_pucch_sched_t)); memcpy(&q->pucch_sched, pucch_sched, sizeof(srslte_pucch_sched_t));
} }
if (srs_cfg) {
memcpy(&q->srs_cfg, srs_cfg, sizeof(srslte_refsignal_srs_cfg_t));
}
if (uci_cfg) {
memcpy(&q->uci_cfg, uci_cfg, sizeof(srslte_uci_cfg_t));
}
if (hopping_cfg) {
memcpy(&q->hopping_cfg, hopping_cfg, sizeof(srslte_pusch_hopping_cfg_t));
}
} }
int srslte_ue_ul_cfg_grant(srslte_ue_ul_t *q, srslte_dci_msg_t *dci_msg, int srslte_ue_ul_cfg_grant(srslte_ue_ul_t *q, srslte_ra_ul_grant_t *grant,
srslte_pusch_hopping_cfg_t *hopping_cfg, uint32_t tti, uint32_t rvidx, uint32_t current_tx_nb)
srslte_refsignal_srs_cfg_t *srs_cfg,
uint32_t tti, uint32_t cyclic_shift_for_dmrs, uint32_t rvidx)
{ {
return srslte_pusch_cfg(&q->pusch, &q->pusch_cfg, dci_msg, hopping_cfg, srs_cfg, tti, cyclic_shift_for_dmrs, rvidx); return srslte_pusch_cfg(&q->pusch, &q->pusch_cfg, grant, &q->uci_cfg, &q->hopping_cfg, &q->srs_cfg, tti, rvidx, current_tx_nb);
} }
/* Choose PUCCH format as in Sec 10.1 of 36.213 and generate PUCCH signal /* 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, int srslte_ue_ul_pucch_encode(srslte_ue_ul_t *q, srslte_uci_data_t uci_data,
uint32_t pdcch_n_cce,
uint32_t tti, uint32_t tti,
cf_t *output_signal) cf_t *output_signal)
{ {
@ -279,7 +290,7 @@ int srslte_ue_ul_pucch_encode(srslte_ue_ul_t *q, srslte_uci_data_t uci_data,
if (q->pucch_sched.sps_enabled) { if (q->pucch_sched.sps_enabled) {
n_pucch = q->pucch_sched.n_pucch_1[q->pucch_sched.tpc_for_pucch%4]; n_pucch = q->pucch_sched.n_pucch_1[q->pucch_sched.tpc_for_pucch%4];
} else { } else {
n_pucch = q->pucch_sched.n_cce + q->pucch_sched.N_pucch_1; n_pucch = pdcch_n_cce + q->pucch_sched.N_pucch_1;
} }
} else { } else {
n_pucch = q->pucch_sched.n_pucch_2; n_pucch = q->pucch_sched.n_pucch_2;
@ -410,13 +421,13 @@ int srslte_ue_ul_pusch_encode_rnti_softbuffer(srslte_ue_ul_t *q,
srslte_refsignal_dmrs_pusch_pregen_put(&q->signals, &q->pregen_drms, srslte_refsignal_dmrs_pusch_pregen_put(&q->signals, &q->pregen_drms,
q->pusch_cfg.grant.L_prb, q->pusch_cfg.grant.L_prb,
q->pusch_cfg.sf_idx, q->pusch_cfg.sf_idx,
q->pusch_cfg.cyclic_shift_for_dmrs, q->pusch_cfg.grant.ncs_dmrs,
q->pusch_cfg.grant.n_prb_tilde, q->pusch_cfg.grant.n_prb_tilde,
q->sf_symbols); q->sf_symbols);
} else { } else {
if (srslte_refsignal_dmrs_pusch_gen(&q->signals, q->pusch_cfg.grant.L_prb, if (srslte_refsignal_dmrs_pusch_gen(&q->signals, q->pusch_cfg.grant.L_prb,
q->pusch_cfg.sf_idx, q->pusch_cfg.sf_idx,
q->pusch_cfg.cyclic_shift_for_dmrs, q->pusch_cfg.grant.ncs_dmrs,
q->refsignal)) q->refsignal))
{ {
fprintf(stderr, "Error generating PUSCH DRMS signals\n"); fprintf(stderr, "Error generating PUSCH DRMS signals\n");

@ -28,6 +28,7 @@
#include <float.h> #include <float.h>
#include <complex.h> #include <complex.h>
#include <math.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
@ -159,6 +160,22 @@ void srslte_vec_sc_prod_fff(float *x, float h, float *z, uint32_t len) {
#endif #endif
} }
// TODO: Improve this implementation
void srslte_vec_norm_cfc(cf_t *x, float amplitude, cf_t *y, uint32_t len) {
// Compute peak
float max = 0;
float *t = (float*) x;
for (int i=0;i<2*len;i++) {
if (fabsf(t[i]) > max) {
max = fabsf(t[i]);
}
}
// Normalize before TX
srslte_vec_sc_prod_cfc(x, amplitude/max, y, len);
}
void srslte_vec_sc_prod_cfc(cf_t *x, float h, cf_t *z, uint32_t len) { void srslte_vec_sc_prod_cfc(cf_t *x, float h, cf_t *z, uint32_t len) {
#ifndef HAVE_VOLK_MULT_FUNCTION #ifndef HAVE_VOLK_MULT_FUNCTION
int i; int i;

Loading…
Cancel
Save