mirror of https://github.com/PentHertz/srsLTE.git
Initial commit
This commit is contained in:
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
|
||||
}
|
||||
|
||||
#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
|
||||
|
||||
|
|
|
@ -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/)
|
||||
|
||||
add_subdirectory(phy)
|
||||
add_subdirectory(mac)
|
||||
#add_subdirectory(mac)
|
||||
|
||||
|
|
|
@ -44,57 +44,6 @@ namespace ue {
|
|||
mac_params() : params_db(NOF_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,16 +29,17 @@
|
|||
|
||||
|
||||
#include "srslte/srslte.h"
|
||||
#include "srsapps/common/phy_interface.h"
|
||||
#include "srsapps/common/log.h"
|
||||
#include "srsapps/common/tti_sync.h"
|
||||
#include "srsapps/ue/phy/dl_buffer.h"
|
||||
#include "srsapps/ue/phy/ul_buffer.h"
|
||||
#include "srsapps/ue/phy/phch_recv.h"
|
||||
#include "srsapps/ue/phy/prach.h"
|
||||
#include "srsapps/ue/phy/phy_params.h"
|
||||
#include "srsapps/ue/phy/sched_grant.h"
|
||||
#include "srsapps/common/queue.h"
|
||||
#include "srsapps/ue/phy/phch_worker.h"
|
||||
#include "srsapps/ue/phy/phch_common.h"
|
||||
#include "srsapps/radio/radio.h"
|
||||
#include "srsapps/common/task_dispatcher.h"
|
||||
#include "srsapps/common/trace.h"
|
||||
#include "srsapps/common/mac_interface.h"
|
||||
|
||||
#ifndef UEPHY_H
|
||||
#define UEPHY_H
|
||||
|
@ -46,135 +47,86 @@
|
|||
namespace srslte {
|
||||
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;
|
||||
|
||||
class phy
|
||||
class phy : public phy_interface, phy_interface_params
|
||||
{
|
||||
public:
|
||||
phy();
|
||||
void set();
|
||||
bool init(radio *radio_handler, tti_sync *ttisync, log *log_h);
|
||||
bool init_agc(radio *radio_handler, tti_sync *ttisync, log *log_h);
|
||||
bool init(radio *radio_handler, mac_interface_phy *mac, log *log_h);
|
||||
bool init_agc(radio *radio_handler, mac_interface_phy *mac, log *log_h);
|
||||
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 pregen_signals();
|
||||
|
||||
// Indicate the PHY to send PRACH as soon as possible
|
||||
bool init_prach();
|
||||
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);
|
||||
// Get status
|
||||
bool status_is_sync();
|
||||
|
||||
// Indicate the PHY to send SR as soon as possible or not
|
||||
void send_sr(bool enable);
|
||||
int sr_last_tx_tti();
|
||||
static uint32_t tti_to_SFN(uint32_t tti);
|
||||
static uint32_t tti_to_subf(uint32_t tti);
|
||||
|
||||
// Returns TTI when PRACH was transmitted. -1 if not yet transmitted
|
||||
int get_prach_transmitted_tti();
|
||||
void enable_pregen_signals(bool enable);
|
||||
|
||||
// Get handler to the radio
|
||||
radio* get_radio();
|
||||
void start_trace();
|
||||
void write_trace(std::string filename);
|
||||
|
||||
/********** MAC INTERFACE ********************/
|
||||
/* Instructs the PHY to configure using the parameters written with set_param() */
|
||||
void configure_prach_params();
|
||||
void configure_ul_params();
|
||||
|
||||
/* Functions to synchronize with a cell */
|
||||
void sync_start();
|
||||
void sync_stop();
|
||||
|
||||
/* Functions to initialize and transmit PRACH in the next opportunity */
|
||||
void prach_send(prach_cfg_t *cfg);
|
||||
|
||||
/* Indicates the transmission of a SR signal in the next opportunity */
|
||||
void sr_send();
|
||||
|
||||
// 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 rar_ul_grant(srslte_dci_rar_grant_t *rar, ul_sched_grant *grant);
|
||||
/* Sets RAR grant payload */
|
||||
void set_rar_grant(uint32_t tti, uint8_t grant_payload[SRSLTE_RAR_GRANT_LEN]);
|
||||
|
||||
// Get status
|
||||
bool status_is_idle();
|
||||
bool status_is_rxtx();
|
||||
/* Instruct the PHY to decode PDCCH with the CRC scrambled with given RNTI */
|
||||
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);
|
||||
|
||||
void set_param(phy_params::phy_param_t param, int64_t value);
|
||||
int64_t get_param(phy_params::phy_param_t param);
|
||||
/* Get/Set PHY parameters */
|
||||
void set_param(phy_param_t param, int64_t value);
|
||||
int64_t get_param(phy_param_t param);
|
||||
|
||||
void reset();
|
||||
|
||||
uint32_t get_current_tti();
|
||||
static uint32_t tti_to_SFN(uint32_t tti);
|
||||
static uint32_t tti_to_subf(uint32_t tti);
|
||||
|
||||
ul_buffer* get_ul_buffer(uint32_t tti);
|
||||
dl_buffer* get_dl_buffer(uint32_t tti);
|
||||
|
||||
void start_trace();
|
||||
void write_trace(std::string filename);
|
||||
|
||||
bool sr_is_ready_to_send(uint32_t tti);
|
||||
bool cqi_is_ready_to_send(uint32_t tti);
|
||||
|
||||
void main_radio_loop();
|
||||
|
||||
private:
|
||||
enum {
|
||||
IDLE, RXTX
|
||||
} phy_state;
|
||||
|
||||
static const int NOF_ULDL_QUEUES = 10;
|
||||
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;
|
||||
log *log_h;
|
||||
|
||||
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;
|
||||
thread_pool workers_pool;
|
||||
std::vector<phch_worker> workers;
|
||||
phch_common workers_common;
|
||||
phch_recv sf_recv;
|
||||
prach prach_buffer;
|
||||
|
||||
phy_params params_db;
|
||||
|
||||
pthread_t phy_thread;
|
||||
float time_adv_sec;
|
||||
/* Current time advance */
|
||||
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_end_time;
|
||||
|
|
|
@ -29,6 +29,7 @@
|
|||
|
||||
#include "srslte/srslte.h"
|
||||
#include "srsapps/common/params_db.h"
|
||||
#include "srsapps/common/phy_interface.h"
|
||||
|
||||
#ifndef PHYPARAMS_H
|
||||
#define PHYPARAMS_H
|
||||
|
@ -41,77 +42,10 @@ namespace ue {
|
|||
{
|
||||
public:
|
||||
|
||||
phy_params() : params_db(NOF_PARAMS) { }
|
||||
phy_params() : params_db(phy_interface_params::NOF_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 "srsapps/radio/radio.h"
|
||||
#include "srsapps/common/log.h"
|
||||
#include "srsapps/common/queue.h"
|
||||
#include "srsapps/common/phy_interface.h"
|
||||
#include "srsapps/ue/phy/phy_params.h"
|
||||
|
||||
#ifndef UEPRACH_H
|
||||
|
@ -46,14 +46,16 @@ namespace ue {
|
|||
initiated = false;
|
||||
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();
|
||||
bool prepare_to_send(uint32_t preamble_idx);
|
||||
bool prepare_to_send(uint32_t preamble_idx, int allowed_subframe);
|
||||
bool prepare_to_send(uint32_t preamble_idx, int allowed_subframe, int target_power_dbm);
|
||||
bool prepare_to_send(phy_interface::prach_cfg_t* cfg);
|
||||
bool prepare_to_send(uint32_t preamble_idx, int allowed_subframe = -1, float target_power_dbm = -1);
|
||||
bool is_ready_to_send(uint32_t current_tti);
|
||||
int get_transmitted_tti();
|
||||
bool send(srslte::radio* radio_handler, float cfo, srslte_timestamp_t rx_time);
|
||||
void get_rar_cfg(uint16_t* rar_rnti, uint32_t* tti_start, uint32_t* tti_end);
|
||||
|
||||
bool send(radio* radio_handler, float cfo, srslte_timestamp_t rx_time);
|
||||
|
||||
private:
|
||||
static const uint32_t tx_advance_sf = 1; // Number of subframes to advance transmission
|
||||
phy_params *params_db;
|
||||
|
@ -68,6 +70,8 @@ namespace ue {
|
|||
srslte_cell_t cell;
|
||||
cf_t *signal_buffer;
|
||||
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/log.h"
|
||||
#include "srsapps/ue/phy/phy.h"
|
||||
#include "srsapps/ue/phy/prach.h"
|
||||
#include "srsapps/ue/phy/ul_buffer.h"
|
||||
#include "srsapps/ue/phy/dl_buffer.h"
|
||||
#include "srsapps/ue/phy/phch_worker.h"
|
||||
|
||||
namespace srslte {
|
||||
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) {
|
||||
return init_(radio_handler_, ttisync_, log_h, false);
|
||||
bool phy::init(radio* radio_handler_, mac_interface_phy *mac, log *log_h) {
|
||||
return init_(radio_handler_, mac, log_h, false);
|
||||
}
|
||||
|
||||
bool phy::init_agc(srslte::radio* radio_handler_, srslte::ue::tti_sync* ttisync_, log *log_h) {
|
||||
return init_(radio_handler_, ttisync_, log_h, true);
|
||||
bool phy::init_agc(radio* radio_handler_, mac_interface_phy *mac, log *log_h) {
|
||||
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(¶ms_db, log_h);
|
||||
workers_common.init(¶ms_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()
|
||||
{
|
||||
tr_enabled = true;
|
||||
|
@ -73,227 +97,134 @@ void phy::write_trace(std::string filename)
|
|||
void phy::tr_log_start()
|
||||
{
|
||||
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()
|
||||
{
|
||||
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()
|
||||
{
|
||||
started = false;
|
||||
sf_recv.stop();
|
||||
sf_recv.wait_thread_finish();
|
||||
|
||||
pthread_join(phy_thread, NULL);
|
||||
|
||||
for (int i=0;i<NOF_ULDL_QUEUES;i++) {
|
||||
((ul_buffer*) ul_buffer_queue->get(i))->free_cell();
|
||||
((dl_buffer*) dl_buffer_queue->get(i))->free_cell();
|
||||
for (int i=0;i<NOF_WORKERS;i++) {
|
||||
((phch_worker) workers[i]).free_cell();
|
||||
workers[i].stop();
|
||||
workers[i].wait_thread_finish();
|
||||
}
|
||||
|
||||
delete ul_buffer_queue;
|
||||
delete dl_buffer_queue;
|
||||
|
||||
prach_buffer.free_cell();
|
||||
}
|
||||
|
||||
radio* phy::get_radio() {
|
||||
return radio_handler;
|
||||
}
|
||||
|
||||
void phy::set_timeadv_rar(uint32_t ta_cmd) {
|
||||
n_ta = srslte_N_ta_new_rar(ta_cmd);
|
||||
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);
|
||||
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, ((float) n_ta)*SRSLTE_LTE_TS*1e6);
|
||||
}
|
||||
|
||||
void phy::set_timeadv(uint32_t ta_cmd) {
|
||||
n_ta = srslte_N_ta_new(n_ta, ta_cmd);
|
||||
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);
|
||||
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, ((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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
// FIXME: Add PRACH power control
|
||||
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)
|
||||
void phy::configure_prach_params()
|
||||
{
|
||||
if (phy_state == RXTX) {
|
||||
return prach_buffer.prepare_to_send(preamble_idx, allowed_subframe, target_power_dbm);
|
||||
Info("Configuring PRACH parameters\n");
|
||||
if (prach_buffer.init_cell(cell)) {
|
||||
Error("Configuring PRACH parameters\n");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Instruct the PHY to send a SR as soon as possible */
|
||||
void phy::send_sr(bool enable)
|
||||
void phy::configure_ul_params()
|
||||
{
|
||||
sr_enabled = enable;
|
||||
if (!enable) {
|
||||
sr_tx_tti = 0;
|
||||
Info("Configuring UL parameters\n");
|
||||
for (int i=0;i<NOF_WORKERS;i++) {
|
||||
workers[i].set_ul_params();
|
||||
}
|
||||
}
|
||||
|
||||
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::pdcch_ul_search(srslte_rnti_type_t rnti_type, uint16_t rnti, int tti_start, int tti_end)
|
||||
{
|
||||
/*
|
||||
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)) {
|
||||
Warning("Sending PUCCH CQI\n");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
*/
|
||||
return false;
|
||||
workers_common.set_ul_rnti(rnti_type, rnti, tti_start, tti_end);
|
||||
}
|
||||
|
||||
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_dl_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_dl_rnti(rnti_type, rnti);
|
||||
}
|
||||
|
||||
// Do fast measurement on RSSI and/or PSS autocorrelation energy or PSR
|
||||
bool phy::measure()
|
||||
void phy::prach_send(phy_interface::prach_cfg_t* cfg)
|
||||
{
|
||||
if (phy_state == IDLE) {
|
||||
// capture and do measurement
|
||||
|
||||
if (prach_buffer.prepare_to_send(cfg)) {
|
||||
Error("Preparing PRACH to send\n");
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void phy::reset()
|
||||
{
|
||||
// TODO
|
||||
}
|
||||
|
||||
uint32_t phy::get_current_tti()
|
||||
{
|
||||
return sf_recv.get_current_tti();
|
||||
}
|
||||
|
||||
void phy::sr_send()
|
||||
{
|
||||
workers_common.sr_enabled = true;
|
||||
}
|
||||
|
||||
bool phy::status_is_sync()
|
||||
{
|
||||
return sf_recv.status_is_sync();
|
||||
}
|
||||
|
||||
void phy::sync_start()
|
||||
{
|
||||
sf_recv.sync_start();
|
||||
}
|
||||
|
||||
void phy::sync_stop()
|
||||
{
|
||||
sf_recv.sync_stop();
|
||||
}
|
||||
|
||||
void phy::set_rar_grant(uint32_t tti, uint8_t grant_payload[SRSLTE_RAR_GRANT_LEN])
|
||||
{
|
||||
workers_common.set_rar_grant(tti, grant_payload);
|
||||
}
|
||||
|
||||
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);
|
||||
for(uint32_t i=0;i<NOF_WORKERS;i++) {
|
||||
((phch_worker) workers[i]).set_crnti(rnti);
|
||||
}
|
||||
}
|
||||
|
||||
void phy::pregen_signals()
|
||||
void phy::enable_pregen_signals(bool enable)
|
||||
{
|
||||
for(uint32_t i=0;i<NOF_ULDL_QUEUES;i++) {
|
||||
((ul_buffer*) ul_buffer_queue->get(i))->pregen_signals();
|
||||
for(uint32_t i=0;i<NOF_WORKERS;i++) {
|
||||
((phch_worker) workers[i]).enable_pregen_signals(enable);
|
||||
}
|
||||
}
|
||||
|
||||
bool phy::start_rxtx()
|
||||
{
|
||||
if (phy_state == IDLE) {
|
||||
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()
|
||||
{
|
||||
if (phy_state == RXTX) {
|
||||
// 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()
|
||||
{
|
||||
return 10*log10(srslte_agc_get_gain(&ue_sync.agc));
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
@ -302,274 +233,12 @@ 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)
|
||||
{
|
||||
radio *radio_handler = (radio*) h;
|
||||
int n = radio_handler->rx_now(data, nsamples, rx_time);
|
||||
return n;
|
||||
}
|
||||
|
||||
double callback_set_rx_gain(void *h, double gain) {
|
||||
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, ¶ms_db, log_h, radio_handler);
|
||||
((dl_buffer*) dl_buffer_queue->get(i))->init_cell(cell, ¶ms_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, ¶ms_db, log_h);
|
||||
}
|
||||
|
||||
ul_buffer* phy::get_ul_buffer(uint32_t tti)
|
||||
{
|
||||
tti=tti%10240;
|
||||
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)
|
||||
{
|
||||
return (ul_buffer*) ul_buffer_queue->get(tti + ul_buffer::tx_advance_sf);
|
||||
}
|
||||
|
||||
dl_buffer* phy::get_dl_buffer(uint32_t tti)
|
||||
{
|
||||
tti=tti%10240;
|
||||
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]) {
|
||||
return decode_mib_N_id_2(-1, cell, payload);
|
||||
}
|
||||
|
||||
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])
|
||||
{
|
||||
srslte_ue_cellsearch_result_t found_cells[3];
|
||||
srslte_ue_cellsearch_t cs;
|
||||
|
||||
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);
|
||||
|
||||
|
||||
if (ret == 1) {
|
||||
srslte_pbch_mib_unpack(bch_payload, cell_ptr, NULL);
|
||||
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/ue/phy/prach.h"
|
||||
#include "srsapps/ue/phy/phy.h"
|
||||
#include "srsapps/ue/phy/phy_params.h"
|
||||
#include "srsapps/common/phy_interface.h"
|
||||
|
||||
namespace srslte {
|
||||
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_;
|
||||
params_db = params_db_;
|
||||
}
|
||||
|
||||
bool prach::init_cell(srslte_cell_t cell_)
|
||||
{
|
||||
cell = cell_;
|
||||
preamble_idx = -1;
|
||||
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)),
|
||||
params_db->get_param(phy_params::PRACH_ROOT_SEQ_IDX),
|
||||
params_db->get_param(phy_params::PRACH_HIGH_SPEED_FLAG)?true:false,
|
||||
params_db->get_param(phy_params::PRACH_ZC_CONFIG))) {
|
||||
srslte_prach_get_preamble_format(params_db->get_param(phy_interface_params::PRACH_CONFIG_INDEX)),
|
||||
params_db->get_param(phy_interface_params::PRACH_ROOT_SEQ_IDX),
|
||||
params_db->get_param(phy_interface_params::PRACH_HIGH_SPEED_FLAG)?true:false,
|
||||
params_db->get_param(phy_interface_params::PRACH_ZC_CONFIG))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
@ -75,7 +79,7 @@ bool prach::init_cell(srslte_cell_t cell_, phy_params *params_db_, log *log_h_)
|
|||
if(!buffer[i]) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
@ -86,13 +90,16 @@ bool prach::init_cell(srslte_cell_t cell_, phy_params *params_db_, log *log_h_)
|
|||
return initiated;
|
||||
}
|
||||
|
||||
bool prach::prepare_to_send(uint32_t preamble_idx_) {
|
||||
return prepare_to_send(preamble_idx_, -1, 0);
|
||||
bool prach::prepare_to_send(phy_interface::prach_cfg_t* cfg)
|
||||
{
|
||||
int allowed_sf = cfg->allowed_subframe_enabled?(int) cfg->allowed_subframe:-1;
|
||||
bool ret = prepare_to_send(cfg->preamble_idx, allowed_sf, cfg->target_power_dbm);
|
||||
if (ret) {
|
||||
memcpy(&prach_cfg, cfg, sizeof(phy_interface::prach_cfg_t));
|
||||
}
|
||||
bool prach::prepare_to_send(uint32_t preamble_idx_, int allowed_subframe_) {
|
||||
return prepare_to_send(preamble_idx_, allowed_subframe_, 0);
|
||||
}
|
||||
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) {
|
||||
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) {
|
||||
// consider the number of subframes the transmission must be anticipated
|
||||
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)) {
|
||||
Info("PRACH Buffer: Ready to send at tti: %d (now is %d)\n", current_tti, current_tti_);
|
||||
transmitted_tti = current_tti;
|
||||
|
@ -119,11 +126,16 @@ bool prach::is_ready_to_send(uint32_t current_tti_) {
|
|||
return false;
|
||||
}
|
||||
|
||||
int prach::get_transmitted_tti() {
|
||||
if (initiated) {
|
||||
return transmitted_tti;
|
||||
} else {
|
||||
return -1;
|
||||
void prach::get_rar_cfg(uint16_t *rar_rnti, uint32_t *tti_start, uint32_t *tti_end)
|
||||
{
|
||||
if (rar_rnti) {
|
||||
*rar_rnti = prach_cfg.rar_rnti;
|
||||
}
|
||||
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
|
||||
srslte_cfo_correct(&cfo_h, buffer[preamble_idx], signal_buffer, cfo /srslte_symbol_sz(cell.nof_prb));
|
||||
|
||||
// Compute peak
|
||||
float max = 0;
|
||||
float *t = (float*) signal_buffer;
|
||||
for (int i=0;i<2*len;i++) {
|
||||
if (fabsf(t[i]) > max) {
|
||||
max = fabsf(t[i]);
|
||||
}
|
||||
}
|
||||
// Normalize signal amplitude
|
||||
srslte_vec_norm_cfc(signal_buffer, 0.9, signal_buffer, len);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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)
|
||||
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)
|
||||
TARGET_LINK_LIBRARIES(ue_itf_test_prach srsapps_common srsapps_ue_phy srsapps_radio srslte srslte_uhd)
|
||||
# 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)
|
||||
ENDIF(UHD_FOUND)
|
||||
|
|
|
@ -30,18 +30,21 @@
|
|||
#include "srslte/utils/debug.h"
|
||||
#include "srsapps/ue/phy/phy.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"
|
||||
|
||||
|
||||
/**********************************************************************
|
||||
* Program arguments processing
|
||||
***********************************************************************/
|
||||
|
||||
typedef struct {
|
||||
float uhd_freq;
|
||||
float uhd_gain;
|
||||
}prog_args_t;
|
||||
|
||||
prog_args_t prog_args;
|
||||
|
||||
void args_default(prog_args_t *args) {
|
||||
args->uhd_freq = -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;
|
||||
prog_args_t prog_args;
|
||||
#ifdef kk
|
||||
|
||||
uint32_t total_pkts=0;
|
||||
uint32_t total_dci=0;
|
||||
|
@ -94,7 +121,6 @@ uint8_t payload[1024];
|
|||
|
||||
// This is the MAC implementation
|
||||
void run_tti(uint32_t tti) {
|
||||
srslte::ue::dl_sched_grant grant(SRSLTE_SIRNTI);
|
||||
INFO("MAC running tti: %d\n", tti);
|
||||
|
||||
// SIB1 is scheduled in subframe #5 of even frames
|
||||
|
@ -127,12 +153,14 @@ void run_tti(uint32_t tti) {
|
|||
total_pkts, gain);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
srslte::ue::phy phy;
|
||||
testmac mac;
|
||||
srslte_cell_t cell;
|
||||
uint8_t bch_payload[SRSLTE_BCH_PAYLOAD_LEN];
|
||||
srslte::ue::tti_sync_cv ttisync(10240);
|
||||
srslte::radio_uhd radio_uhd;
|
||||
srslte::log_stdout log("PHY");
|
||||
|
||||
|
@ -142,46 +170,28 @@ int main(int argc, char *argv[])
|
|||
if (prog_args.uhd_gain > 0) {
|
||||
radio_uhd.init();
|
||||
radio_uhd.set_rx_gain(prog_args.uhd_gain);
|
||||
phy.init(&radio_uhd, &ttisync, &log);
|
||||
phy.init(&radio_uhd, &mac, &log);
|
||||
} else {
|
||||
radio_uhd.init_agc();
|
||||
phy.init_agc(&radio_uhd, &ttisync, &log);
|
||||
phy.init_agc(&radio_uhd, &mac, &log);
|
||||
}
|
||||
|
||||
// Give it time to create thread
|
||||
sleep(1);
|
||||
|
||||
// Set default parameters
|
||||
phy.set_param(srslte::ue::phy_params::PRACH_CONFIG_INDEX, 0);
|
||||
phy.set_param(srslte::ue::phy_params::PRACH_ROOT_SEQ_IDX, 0);
|
||||
phy.set_param(srslte::ue::phy_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_CONFIG_INDEX, 0);
|
||||
phy.set_param(srslte::ue::phy_interface_params::PRACH_ROOT_SEQ_IDX, 0);
|
||||
phy.set_param(srslte::ue::phy_interface_params::PRACH_HIGH_SPEED_FLAG, 0);
|
||||
phy.set_param(srslte::ue::phy_interface_params::PRACH_ZC_CONFIG, 1);
|
||||
|
||||
// Set RX freq and gain
|
||||
phy.get_radio()->set_rx_freq(prog_args.uhd_freq);
|
||||
phy.get_radio()->set_rx_gain(prog_args.uhd_gain);
|
||||
radio_uhd.set_rx_freq(prog_args.uhd_freq);
|
||||
radio_uhd.set_rx_gain(prog_args.uhd_gain);
|
||||
|
||||
/* Instruct the PHY to decode BCH */
|
||||
if (!phy.decode_mib_best(&cell, bch_payload)) {
|
||||
exit(-1);
|
||||
}
|
||||
// Print MIB
|
||||
srslte_cell_fprint(stdout, &cell, phy.get_current_tti()/10);
|
||||
phy.sync_start();
|
||||
|
||||
// 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) {
|
||||
uint32_t tti = ttisync.wait();
|
||||
run_tti(tti);
|
||||
usleep(1000);
|
||||
}
|
||||
}
|
|
@ -576,8 +576,9 @@ int main(int argc, char **argv) {
|
|||
}
|
||||
|
||||
/* Configure pdsch_cfg parameters */
|
||||
srslte_ra_dl_dci_to_grant(&ra_dl, cell.nof_prb, true, &pdsch_cfg.grant);
|
||||
if (srslte_pdsch_cfg(&pdsch_cfg, cell, NULL, cfi, sf_idx, UE_CRNTI, 0)) {
|
||||
srslte_ra_dl_grant_t grant;
|
||||
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");
|
||||
exit(-1);
|
||||
}
|
||||
|
|
|
@ -385,12 +385,12 @@ cell.nof_ports = 1;
|
|||
|
||||
srslte_refsignal_dmrs_pusch_cfg_t dmrs_cfg;
|
||||
bzero(&dmrs_cfg, sizeof(srslte_refsignal_dmrs_pusch_cfg_t));
|
||||
dmrs_cfg.beta_pusch = 1.0;
|
||||
bool group_hopping_en = false;
|
||||
bool sequence_hopping_en = false;
|
||||
|
||||
dmrs_cfg.group_hopping_en = false;
|
||||
dmrs_cfg.sequence_hopping_en = false;
|
||||
dmrs_cfg.delta_ss = 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));
|
||||
if (!ul_signal) {
|
||||
|
@ -518,8 +518,7 @@ cell.nof_ports = 1;
|
|||
printf("Setting CFO: %f (%f)\n", cfo, cfo*15000);
|
||||
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, NULL, 0, 0, ul_sf_idx, 0, 0);
|
||||
srslte_ue_ul_cfg_grant(&ue_ul, &ra_grant, ul_sf_idx, 0, 0);
|
||||
|
||||
n = srslte_ue_ul_pusch_encode_rnti(&ue_ul, data, rar_msg.temp_c_rnti, ul_signal);
|
||||
if (n < 0) {
|
||||
|
|
|
@ -48,11 +48,11 @@
|
|||
typedef struct SRSLTE_API {
|
||||
uint32_t cyclic_shift;
|
||||
uint32_t delta_ss;
|
||||
float beta_pusch;
|
||||
bool group_hopping_en;
|
||||
bool sequence_hopping_en;
|
||||
}srslte_refsignal_dmrs_pusch_cfg_t;
|
||||
|
||||
typedef struct SRSLTE_API {
|
||||
float beta_srs;
|
||||
uint32_t subframe_config;
|
||||
uint32_t I_srs;
|
||||
uint32_t bw_cfg;
|
||||
|
@ -67,8 +67,6 @@ typedef struct SRSLTE_API {
|
|||
/** Uplink DeModulation Reference Signal (DMRS) */
|
||||
typedef struct SRSLTE_API {
|
||||
srslte_cell_t cell;
|
||||
bool group_hopping_en;
|
||||
bool sequence_hopping_en;
|
||||
srslte_refsignal_dmrs_pusch_cfg_t pusch_cfg;
|
||||
srslte_pucch_cfg_t pucch_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_refsignal_dmrs_pusch_cfg_t *pusch_cfg,
|
||||
srslte_pucch_cfg_t *pucch_cfg,
|
||||
srslte_refsignal_srs_cfg_t *srs_cfg,
|
||||
bool group_hopping_en,
|
||||
bool sequence_hopping_en);
|
||||
srslte_refsignal_srs_cfg_t *srs_cfg);
|
||||
|
||||
SRSLTE_API void srslte_refsignal_r_uv_arg_1prb(float *arg,
|
||||
uint32_t u);
|
||||
|
|
|
@ -139,6 +139,16 @@ typedef enum SRSLTE_API {
|
|||
|
||||
} 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 {
|
||||
uint32_t nof_prb;
|
||||
uint32_t nof_ports;
|
||||
|
|
|
@ -41,6 +41,10 @@
|
|||
#include "srslte/config.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
|
||||
CQI reports
|
||||
|
|
|
@ -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_cell_t cell,
|
||||
srslte_dci_msg_t *dci_msg,
|
||||
srslte_ra_dl_grant_t *grant,
|
||||
uint32_t cfi,
|
||||
uint32_t sf_idx,
|
||||
uint16_t rnti,
|
||||
|
|
|
@ -55,7 +55,6 @@ typedef enum SRSLTE_API {
|
|||
} srslte_pucch_format_t;
|
||||
|
||||
typedef struct SRSLTE_API {
|
||||
uint32_t n_cce;
|
||||
bool sps_enabled;
|
||||
uint32_t tpc_for_pucch;
|
||||
uint32_t N_pucch_1;
|
||||
|
@ -65,7 +64,6 @@ typedef struct SRSLTE_API {
|
|||
}srslte_pucch_sched_t;
|
||||
|
||||
typedef struct SRSLTE_API {
|
||||
float beta_pucch;
|
||||
uint32_t delta_pucch_shift;
|
||||
uint32_t n_rb_2;
|
||||
uint32_t N_cs;
|
||||
|
|
|
@ -60,7 +60,6 @@ typedef struct {
|
|||
SRSLTE_PUSCH_HOP_MODE_INTER_SF = 1,
|
||||
SRSLTE_PUSCH_HOP_MODE_INTRA_SF = 0
|
||||
} hop_mode;
|
||||
uint32_t current_tx_nb;
|
||||
uint32_t hopping_offset;
|
||||
uint32_t n_sb;
|
||||
} srslte_pusch_hopping_cfg_t;
|
||||
|
@ -105,12 +104,13 @@ SRSLTE_API void srslte_pusch_free(srslte_pusch_t *q);
|
|||
|
||||
SRSLTE_API int srslte_pusch_cfg(srslte_pusch_t *q,
|
||||
srslte_pusch_cfg_t *cfg,
|
||||
srslte_dci_msg_t *dci_msg,
|
||||
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 cyclic_shift_for_dmrs,
|
||||
uint32_t rvidx);
|
||||
uint32_t rv_idx,
|
||||
uint32_t current_tx_nb);
|
||||
|
||||
SRSLTE_API int srslte_pusch_set_rnti(srslte_pusch_t *q,
|
||||
uint16_t rnti);
|
||||
|
|
|
@ -40,11 +40,17 @@
|
|||
#include "srslte/fec/softbuffer.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 {
|
||||
srslte_cbsegm_t cb_segm;
|
||||
srslte_ra_ul_grant_t grant;
|
||||
srslte_ra_nbits_t nbits;
|
||||
uint32_t cyclic_shift_for_dmrs;
|
||||
srslte_uci_cfg_t uci_cfg;
|
||||
uint32_t rv;
|
||||
uint32_t sf_idx;
|
||||
uint32_t tti;
|
||||
|
|
|
@ -145,6 +145,7 @@ typedef struct SRSLTE_API {
|
|||
uint32_t M_sc_init;
|
||||
uint32_t Qm;
|
||||
srslte_ra_mcs_t mcs;
|
||||
uint32_t ncs_dmrs;
|
||||
} srslte_ra_ul_grant_t;
|
||||
|
||||
/** Unpacked DCI Format0 message */
|
||||
|
@ -172,12 +173,19 @@ typedef struct SRSLTE_API {
|
|||
|
||||
} 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
|
||||
**************************************************/
|
||||
|
||||
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,
|
||||
uint32_t nof_prb,
|
||||
|
|
|
@ -54,14 +54,11 @@ typedef struct SRSLTE_API {
|
|||
typedef struct SRSLTE_API {
|
||||
uint8_t *uci_cqi;
|
||||
uint32_t uci_cqi_len;
|
||||
uint32_t I_offset_cqi;
|
||||
uint8_t uci_ri; // Only 1-bit supported for RI
|
||||
uint32_t uci_ri_len;
|
||||
uint32_t I_offset_ri;
|
||||
uint8_t uci_ack; // 1st codeword bit for HARQ-ACK
|
||||
uint8_t uci_ack_2; // 2st codeword bit for HARQ-ACK
|
||||
uint32_t uci_ack_len;
|
||||
uint32_t I_offset_ack;
|
||||
bool scheduling_request;
|
||||
bool channel_selection;
|
||||
} srslte_uci_data_t;
|
||||
|
|
|
@ -98,15 +98,7 @@ SRSLTE_API int srslte_ue_dl_decode_fft_estimate(srslte_ue_dl_t *q,
|
|||
uint32_t *cfi);
|
||||
|
||||
SRSLTE_API 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);
|
||||
|
||||
SRSLTE_API int srslte_ue_dl_decode_rnti_rv_packet(srslte_ue_dl_t *q,
|
||||
srslte_dci_msg_t *dci_msg,
|
||||
uint8_t *data,
|
||||
srslte_ra_dl_grant_t *grant,
|
||||
uint32_t cfi,
|
||||
uint32_t sf_idx,
|
||||
uint16_t rnti,
|
||||
|
@ -124,6 +116,13 @@ SRSLTE_API int srslte_ue_dl_find_dl_dci(srslte_ue_dl_t *q,
|
|||
uint32_t sf_idx,
|
||||
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 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,
|
||||
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,
|
||||
float cfo);
|
||||
|
||||
|
|
|
@ -78,6 +78,9 @@ typedef struct SRSLTE_API {
|
|||
srslte_pucch_t pucch;
|
||||
|
||||
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 *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_refsignal_dmrs_pusch_cfg_t *dmrs_cfg,
|
||||
srslte_pucch_cfg_t *pucch_cfg,
|
||||
srslte_refsignal_srs_cfg_t *srs_cfg,
|
||||
srslte_pucch_cfg_t *pucch_cfg,
|
||||
srslte_pucch_sched_t *pucch_sched,
|
||||
bool group_hopping_en,
|
||||
bool sequence_hopping_en);
|
||||
srslte_uci_cfg_t *uci_cfg,
|
||||
srslte_pusch_hopping_cfg_t *hopping_cfg);
|
||||
|
||||
SRSLTE_API int srslte_ue_ul_cfg_grant(srslte_ue_ul_t *q,
|
||||
srslte_dci_msg_t *dci_msg,
|
||||
srslte_pusch_hopping_cfg_t *hopping_cfg,
|
||||
srslte_refsignal_srs_cfg_t *srs_cfg,
|
||||
srslte_ra_ul_grant_t *grant,
|
||||
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_uci_data_t uci_data,
|
||||
uint32_t pdcch_n_cce, /* Ncce of the last PDCCH message received */
|
||||
uint32_t tti,
|
||||
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_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_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,
|
||||
srslte_refsignal_dmrs_pusch_cfg_t *pusch_cfg,
|
||||
srslte_pucch_cfg_t *pucch_cfg,
|
||||
srslte_refsignal_srs_cfg_t *srs_cfg,
|
||||
bool group_hopping_en,
|
||||
bool sequence_hopping_en)
|
||||
srslte_refsignal_srs_cfg_t *srs_cfg)
|
||||
{
|
||||
q->group_hopping_en = group_hopping_en;
|
||||
q->sequence_hopping_en = sequence_hopping_en;
|
||||
if (pusch_cfg) {
|
||||
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) {
|
||||
// Get group hopping number u
|
||||
uint32_t f_gh=0;
|
||||
if (q->group_hopping_en) {
|
||||
if (q->pusch_cfg.group_hopping_en) {
|
||||
f_gh = q->f_gh[ns];
|
||||
}
|
||||
uint32_t u = (f_gh + (q->cell.id%30)+delta_ss)%30;
|
||||
|
||||
// Get sequence hopping number v
|
||||
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];
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
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;
|
||||
|
@ -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++) {
|
||||
// Get group hopping number u
|
||||
uint32_t f_gh=0;
|
||||
if (q->group_hopping_en) {
|
||||
if (q->pusch_cfg.group_hopping_en) {
|
||||
f_gh = q->f_gh[ns];
|
||||
}
|
||||
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) {
|
||||
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 {
|
||||
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
|
||||
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;
|
||||
|
|
|
@ -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));
|
||||
|
||||
|
||||
bool group_hopping_en = false;
|
||||
bool sequence_hopping_en = false;
|
||||
pusch_cfg.group_hopping_en = false;
|
||||
pusch_cfg.sequence_hopping_en = false;
|
||||
char *tmp = mexutils_get_char_struct(UECFG, "Hopping");
|
||||
if (tmp) {
|
||||
if (!strcmp(tmp, "Group")) {
|
||||
group_hopping_en = true;
|
||||
pusch_cfg.group_hopping_en = true;
|
||||
} else if (!strcmp(tmp, "Sequence")) {
|
||||
sequence_hopping_en = true;
|
||||
pusch_cfg.sequence_hopping_en = true;
|
||||
}
|
||||
mxFree(tmp);
|
||||
}
|
||||
|
@ -109,8 +109,6 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
|
|||
cyclic_shift_for_dmrs = 0;
|
||||
}
|
||||
|
||||
pusch_cfg.beta_pusch = 1.0;
|
||||
|
||||
if (srslte_refsignal_ul_init(&refs, cell)) {
|
||||
mexErrMsgTxt("Error initiating srslte_refsignal_ul\n");
|
||||
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));
|
||||
|
||||
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);
|
||||
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;
|
||||
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)) {
|
||||
mexErrMsgTxt("Field BWConfig not found in SRSCFG\n");
|
||||
return;
|
||||
|
@ -133,8 +133,10 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
|
|||
mexErrMsgTxt("Error initiating UL refsignal\n");
|
||||
return;
|
||||
}
|
||||
|
||||
srslte_refsignal_ul_set_cfg(&refsignal, NULL, NULL, &srs_cfg, 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(&refsignal, &pusch_cfg, NULL, &srs_cfg);
|
||||
|
||||
if (srslte_refsignal_srs_gen(&refsignal, sf_idx, r_srs)) {
|
||||
mexErrMsgTxt("Error generating SRS\n");
|
||||
|
|
|
@ -100,7 +100,7 @@ int main(int argc, char **argv) {
|
|||
for (int h=0;h<3;h++) {
|
||||
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++) {
|
||||
pusch_cfg.beta_pusch = 1.0;
|
||||
|
||||
uint32_t nof_prb = n;
|
||||
pusch_cfg.cyclic_shift = cshift;
|
||||
pusch_cfg.delta_ss = delta_ss;
|
||||
|
@ -118,7 +118,6 @@ int main(int argc, char **argv) {
|
|||
sequence_hopping_en = false;
|
||||
}
|
||||
|
||||
printf("Beta: %f, ",pusch_cfg.beta_pusch);
|
||||
printf("nof_prb: %d, ",nof_prb);
|
||||
printf("cyclic_shift: %d, ",pusch_cfg.cyclic_shift);
|
||||
printf("cyclic_shift_for_dmrs: %d, ", cshift_dmrs);
|
||||
|
@ -127,7 +126,9 @@ int main(int argc, char **argv) {
|
|||
struct timeval t[3];
|
||||
|
||||
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);
|
||||
gettimeofday(&t[2], NULL);
|
||||
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);
|
||||
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)) {
|
||||
fprintf(stderr, "Error: Creating DFT plan %d\n",i);
|
||||
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;
|
||||
|
|
|
@ -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);
|
||||
|
||||
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 */
|
||||
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.
|
||||
* 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 (srslte_dci_msg_to_dl_grant(dci_msg, rnti, cell.nof_prb, &dl_dci, &cfg->grant)) {
|
||||
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 (cfg && grant) {
|
||||
memcpy(&cfg->grant, grant, sizeof(srslte_ra_dl_grant_t));
|
||||
}
|
||||
if (srslte_cbsegm(&cfg->cb_segm, 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);
|
||||
cfg->sf_idx = sf_idx;
|
||||
cfg->rv = rvidx;
|
||||
|
||||
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 */
|
||||
bool srslte_pucch_cfg_isvalid(srslte_pucch_cfg_t *cfg, uint32_t nof_prb) {
|
||||
if (cfg->beta_pucch > 0 &&
|
||||
cfg->delta_pucch_shift > 0 && cfg->delta_pucch_shift < 4 &&
|
||||
if (cfg->delta_pucch_shift > 0 && cfg->delta_pucch_shift < 4 &&
|
||||
cfg->N_cs < 8 && (cfg->N_cs%cfg->delta_pucch_shift) == 0 &&
|
||||
cfg->n_rb_2 < nof_prb) {
|
||||
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) {
|
||||
cfg->beta_pucch = 1.0;
|
||||
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) {
|
||||
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++) {
|
||||
q->z[(ns%2)*N_sf*SRSLTE_PUCCH_N_SEQ+m*SRSLTE_PUCCH_N_SEQ+n] = q->pucch_cfg.beta_pucch
|
||||
*q->d[(ns%2)*N_sf+m]*cexpf(I*(q->tmp_arg[n]+alpha*n));
|
||||
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));
|
||||
}
|
||||
} 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);
|
||||
|
@ -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",
|
||||
__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++) {
|
||||
q->z[(ns%2)*N_sf_0*SRSLTE_PUCCH_N_SEQ+m*SRSLTE_PUCCH_N_SEQ+n] = q->pucch_cfg.beta_pucch
|
||||
*q->d[0]*cexpf(I*(w_n_oc[N_sf_widx][n_oc%3][m]+q->tmp_arg[n]+alpha*n+S_ns));
|
||||
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));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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->hop_mode == SRSLTE_PUSCH_HOP_MODE_INTER_SF) {
|
||||
return hopping->current_tx_nb%2;
|
||||
return current_tx_nb%2;
|
||||
} else {
|
||||
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 */
|
||||
void compute_freq_hopping(srslte_pusch_t *q, srslte_ra_ul_grant_t *grant,
|
||||
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++) {
|
||||
|
@ -98,7 +98,7 @@ void compute_freq_hopping(srslte_pusch_t *q, srslte_ra_ul_grant_t *grant,
|
|||
|
||||
if (grant->freq_hopping == 1) {
|
||||
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 {
|
||||
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_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",
|
||||
n_prb_tilde, n_vrb_tilde, n_rb_sb, hopping->n_sb);
|
||||
|
@ -305,27 +305,27 @@ void srslte_pusch_free(srslte_pusch_t *q) {
|
|||
/* 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
|
||||
*/
|
||||
int srslte_pusch_cfg(srslte_pusch_t *q, srslte_pusch_cfg_t *cfg, srslte_dci_msg_t *dci_msg,
|
||||
srslte_pusch_hopping_cfg_t *hopping_cfg, srslte_refsignal_srs_cfg_t *srs_cfg,
|
||||
uint32_t tti, uint32_t cyclic_shift_for_dmrs, uint32_t rvidx)
|
||||
int srslte_pusch_cfg(srslte_pusch_t *q,
|
||||
srslte_pusch_cfg_t *cfg,
|
||||
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) {
|
||||
srslte_ra_ul_dci_t ul_dci;
|
||||
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");
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
}
|
||||
if (q && cfg && grant) {
|
||||
memcpy(&cfg->grant, grant, sizeof(srslte_ra_ul_grant_t));
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
cfg->cyclic_shift_for_dmrs = cyclic_shift_for_dmrs;
|
||||
|
||||
/* Compute PUSCH frequency hopping */
|
||||
if (hopping_cfg) {
|
||||
compute_freq_hopping(q, &cfg->grant, hopping_cfg, tti%10);
|
||||
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->grant.n_prb_tilde[1] = cfg->grant.n_prb[1];
|
||||
|
@ -374,10 +374,16 @@ int srslte_pusch_cfg(srslte_pusch_t *q, srslte_pusch_cfg_t *cfg, srslte_dci_msg_
|
|||
|
||||
cfg->sf_idx = tti%10;
|
||||
cfg->tti = tti;
|
||||
cfg->rv = rvidx;
|
||||
cfg->rv = rv_idx;
|
||||
cfg->cp = q->cell.cp;
|
||||
|
||||
// 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
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
bzero(grant, sizeof(srslte_ra_ul_grant_t));
|
||||
|
||||
grant->ncs_dmrs = dci->n_dmrs;
|
||||
grant->L_prb = dci->type2_alloc.L_crb;
|
||||
uint32_t n_prb_1 = dci->type2_alloc.RB_start;
|
||||
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;
|
||||
}
|
||||
|
||||
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 */
|
||||
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
|
||||
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) {
|
||||
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);
|
||||
if (ret < 0) {
|
||||
|
@ -536,7 +536,7 @@ int srslte_ulsch_uci_encode(srslte_sch_t *q,
|
|||
if (uci_data.uci_cqi_len > 0) {
|
||||
ret = srslte_uci_encode_cqi_pusch(&q->uci_cqi, cfg,
|
||||
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);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
|
@ -562,9 +562,9 @@ int srslte_ulsch_uci_encode(srslte_sch_t *q,
|
|||
|
||||
// Encode (and interleave) ACK
|
||||
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) {
|
||||
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);
|
||||
if (ret < 0) {
|
||||
|
|
|
@ -137,17 +137,18 @@ int main(int argc, char **argv) {
|
|||
bzero(ce, sizeof(cf_t*)*SRSLTE_MAX_PORTS);
|
||||
bzero(slot_symbols, sizeof(cf_t*)*SRSLTE_MAX_PORTS);
|
||||
|
||||
pdsch_cfg.grant.mcs.tbs = tbs;
|
||||
pdsch_cfg.grant.mcs.mod = modulation;
|
||||
pdsch_cfg.grant.Qm = srslte_mod_bits_x_symbol(pdsch_cfg.grant.mcs.mod);
|
||||
pdsch_cfg.grant.nof_prb = cell.nof_prb; // Allocate all PRB
|
||||
for (i=0;i<pdsch_cfg.grant.nof_prb;i++) {
|
||||
pdsch_cfg.grant.prb_idx[0][i] = true;
|
||||
srslte_ra_dl_grant_t grant;
|
||||
grant.mcs.tbs = tbs;
|
||||
grant.mcs.mod = modulation;
|
||||
grant.Qm = srslte_mod_bits_x_symbol(grant.mcs.mod);
|
||||
grant.nof_prb = cell.nof_prb; // Allocate all PRB
|
||||
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 */
|
||||
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");
|
||||
exit(-1);
|
||||
}
|
||||
|
@ -193,9 +194,9 @@ int main(int argc, char **argv) {
|
|||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -223,11 +224,11 @@ int main(int argc, char **argv) {
|
|||
gettimeofday(&t[2], NULL);
|
||||
get_time_interval(t);
|
||||
if (r) {
|
||||
printf("Error decoding TBS: %d\n", pdsch_cfg.grant.mcs.tbs);
|
||||
printf("Error decoding TBS: %d\n", grant.mcs.tbs);
|
||||
ret = -1;
|
||||
goto quit;
|
||||
} 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;
|
||||
|
|
|
@ -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;
|
||||
|
||||
cfg.grant.mcs.tbs = mxGetScalar(TBS);
|
||||
if (cfg.grant.mcs.tbs == 0) {
|
||||
srslte_ra_dl_grant_t grant;
|
||||
grant.mcs.tbs = mxGetScalar(TBS);
|
||||
if (grant.mcs.tbs == 0) {
|
||||
mexErrMsgTxt("Error trblklen is zero\n");
|
||||
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");
|
||||
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");
|
||||
|
||||
if (!strcmp(mod_str, "QPSK")) {
|
||||
cfg.grant.mcs.mod = SRSLTE_MOD_QPSK;
|
||||
grant.mcs.mod = SRSLTE_MOD_QPSK;
|
||||
} 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")) {
|
||||
cfg.grant.mcs.mod = SRSLTE_MOD_64QAM;
|
||||
grant.mcs.mod = SRSLTE_MOD_64QAM;
|
||||
} else {
|
||||
mexErrMsgTxt("Unknown modulation\n");
|
||||
return;
|
||||
|
@ -149,23 +150,23 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
|
|||
}
|
||||
|
||||
// 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++) {
|
||||
cfg.grant.prb_idx[0][i] = false;
|
||||
for (int j=0;j<cfg.grant.nof_prb && !cfg.grant.prb_idx[0][i];j++) {
|
||||
grant.prb_idx[0][i] = false;
|
||||
for (int j=0;j<grant.nof_prb && !grant.prb_idx[0][i];j++) {
|
||||
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);
|
||||
|
||||
/* Configure rest of pdsch_cfg parameters */
|
||||
cfg.grant.Qm = srslte_mod_bits_x_symbol(cfg.grant.mcs.mod);
|
||||
if (srslte_pdsch_cfg(&cfg, cell, NULL, cfi, cfg.sf_idx, (uint16_t) (rnti32 & 0xffff), cfg.rv)) {
|
||||
grant.Qm = srslte_mod_bits_x_symbol(grant.mcs.mod);
|
||||
if (srslte_pdsch_cfg(&cfg, cell, &grant, cfi, cfg.sf_idx, (uint16_t) (rnti32 & 0xffff), cfg.rv)) {
|
||||
fprintf(stderr, "Error configuring PDSCH\n");
|
||||
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);
|
||||
}
|
||||
|
||||
uint8_t *data = malloc(sizeof(uint8_t) * cfg.grant.mcs.tbs);
|
||||
uint8_t *data = malloc(sizeof(uint8_t) * grant.mcs.tbs);
|
||||
if (!data) {
|
||||
return;
|
||||
}
|
||||
|
@ -218,7 +219,7 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
|
|||
plhs[0] = mxCreateLogicalScalar(r == 0);
|
||||
}
|
||||
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) {
|
||||
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;
|
||||
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)) {
|
||||
mexErrMsgTxt("Field DeltaShift not found in PUCCHCFG\n");
|
||||
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);
|
||||
|
||||
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)) {
|
||||
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++) {
|
||||
struct timeval t[3];
|
||||
|
||||
pucch_cfg.beta_pucch = 1.0;
|
||||
|
||||
pucch_cfg.delta_pucch_shift = d;
|
||||
bool group_hopping_en = false;
|
||||
pucch_cfg.N_cs = ncs;
|
||||
|
@ -140,7 +140,11 @@ int main(int argc, char **argv) {
|
|||
fprintf(stderr, "Error encoding PUCCH\n");
|
||||
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)) {
|
||||
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");
|
||||
return;
|
||||
}
|
||||
|
||||
srslte_ra_ul_grant_t grant;
|
||||
bzero(&grant, sizeof(srslte_ra_ul_grant_t));
|
||||
|
||||
char *mod_str = mexutils_get_char_struct(PUSCHCFG, "Modulation");
|
||||
if (!strcmp(mod_str, "QPSK")) {
|
||||
cfg.grant.mcs.mod = SRSLTE_MOD_QPSK;
|
||||
grant.mcs.mod = SRSLTE_MOD_QPSK;
|
||||
} 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")) {
|
||||
cfg.grant.mcs.mod = SRSLTE_MOD_64QAM;
|
||||
grant.mcs.mod = SRSLTE_MOD_64QAM;
|
||||
} else {
|
||||
mexErrMsgTxt("Unknown modulation\n");
|
||||
return;
|
||||
|
@ -113,33 +117,33 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
|
|||
if (N_srs == 1) {
|
||||
pusch.shortened = true;
|
||||
}
|
||||
cfg.grant.L_prb = mexutils_read_f(p, &prbset);
|
||||
cfg.grant.n_prb[0] = prbset[0];
|
||||
cfg.grant.n_prb[1] = prbset[0];
|
||||
cfg.grant.M_sc = cfg.grant.L_prb*SRSLTE_NRE;
|
||||
cfg.grant.M_sc_init = cfg.grant.M_sc; // FIXME: What should M_sc_init be?
|
||||
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)) {
|
||||
|
||||
grant.L_prb = mexutils_read_f(p, &prbset);
|
||||
grant.n_prb[0] = prbset[0];
|
||||
grant.n_prb[1] = prbset[0];
|
||||
free(prbset);
|
||||
|
||||
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");
|
||||
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;
|
||||
if (srslte_softbuffer_tx_init(&softbuffer, cell)) {
|
||||
mexErrMsgTxt("Error initiating soft buffer\n");
|
||||
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);
|
||||
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;
|
||||
if (mexutils_read_float_struct(PUSCHCFG, "BetaCQI", &beta)) {
|
||||
uci_data.I_offset_cqi = 7;
|
||||
cfg.uci_cfg.I_offset_cqi = 7;
|
||||
} 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)) {
|
||||
uci_data.I_offset_ri = 2;
|
||||
cfg.uci_cfg.I_offset_ri = 2;
|
||||
} 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)) {
|
||||
uci_data.I_offset_ack = 0;
|
||||
cfg.uci_cfg.I_offset_ack = 0;
|
||||
} 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);
|
||||
|
||||
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);
|
||||
if (r < 0) {
|
||||
mexErrMsgTxt("Error encoding PUSCH\n");
|
||||
|
|
|
@ -135,11 +135,15 @@ int main(int argc, char **argv) {
|
|||
srslte_dci_msg_t dci_msg;
|
||||
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;
|
||||
ul_hopping.n_sb = 1;
|
||||
ul_hopping.hopping_offset = 0;
|
||||
ul_hopping.hop_mode = SRSLTE_PUSCH_HOP_MODE_INTER_SF;
|
||||
ul_hopping.current_tx_nb = 0;
|
||||
|
||||
if (srslte_pusch_init(&pusch, cell)) {
|
||||
fprintf(stderr, "Error creating PDSCH object\n");
|
||||
|
@ -147,35 +151,38 @@ int main(int argc, char **argv) {
|
|||
}
|
||||
|
||||
/* 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");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
srslte_pusch_set_rnti(&pusch, 1234);
|
||||
|
||||
printf("Encoding rv_idx=%d\n",rv_idx);
|
||||
cfg.rv = 0;
|
||||
cfg.sf_idx = subframe;
|
||||
srslte_uci_data_t uci_data;
|
||||
bzero(&uci_data, sizeof(srslte_uci_data_t));
|
||||
uci_data.uci_cqi_len = 8;
|
||||
uci_data.uci_ri_len = 0;
|
||||
uci_data.uci_ack_len = 1;
|
||||
|
||||
uint8_t tmp[20];
|
||||
for (uint32_t i=0;i<20;i++) {
|
||||
tmp[i] = 1;
|
||||
}
|
||||
srslte_uci_data_t uci_data;
|
||||
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_ri_len = 0;
|
||||
uci_data.uci_ack_len = 1;
|
||||
|
||||
uci_data.uci_cqi = tmp;
|
||||
uci_data.uci_ri = 0;
|
||||
uci_data.uci_ack = 0;
|
||||
|
||||
|
||||
|
||||
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);
|
||||
if (!sf_symbols) {
|
||||
|
|
|
@ -99,19 +99,19 @@ void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
|
|||
|
||||
float beta;
|
||||
if (mexutils_read_float_struct(PUSCHCFG, "BetaCQI", &beta)) {
|
||||
uci_data.I_offset_cqi = 7;
|
||||
cfg.uci_cfg.I_offset_cqi = 7;
|
||||
} 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)) {
|
||||
uci_data.I_offset_ri = 2;
|
||||
cfg.uci_cfg.I_offset_ri = 2;
|
||||
} 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)) {
|
||||
uci_data.I_offset_ack = 0;
|
||||
cfg.uci_cfg.I_offset_ack = 0;
|
||||
} 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");
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
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++;
|
||||
|
||||
/* 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;
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
{
|
||||
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];
|
||||
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;
|
||||
|
||||
/* 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);
|
||||
formats = 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)
|
||||
{
|
||||
srslte_dci_msg_t dci_msg;
|
||||
srslte_ra_dl_dci_t dci_unpacked;
|
||||
srslte_ra_dl_grant_t grant;
|
||||
int ret = SRSLTE_ERROR;
|
||||
|
||||
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);
|
||||
|
||||
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) {
|
||||
|
|
|
@ -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));
|
||||
if (!q->input_buffer) {
|
||||
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)) {
|
||||
|
@ -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) {
|
||||
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*/
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -350,7 +351,7 @@ static int track_peak_no(srslte_ue_sync_t *q) {
|
|||
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,
|
||||
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 */
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -373,16 +374,24 @@ static int receive_samples(srslte_ue_sync_t *q) {
|
|||
bool first_track = true;
|
||||
|
||||
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;
|
||||
uint32_t track_idx;
|
||||
|
||||
if (q != NULL &&
|
||||
sf_symbols != NULL &&
|
||||
q->input_buffer != NULL)
|
||||
input_buffer != NULL)
|
||||
{
|
||||
|
||||
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) {
|
||||
fprintf(stderr, "Error reading input file\n");
|
||||
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) {
|
||||
srslte_filesource_seek(&q->file_source, 0);
|
||||
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) {
|
||||
fprintf(stderr, "Error reading input file\n");
|
||||
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);
|
||||
ret = 1;
|
||||
*sf_symbols = q->input_buffer;
|
||||
} else {
|
||||
if (receive_samples(q)) {
|
||||
if (receive_samples(q, input_buffer)) {
|
||||
fprintf(stderr, "Error receiving samples\n");
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
switch (q->state) {
|
||||
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) {
|
||||
fprintf(stderr, "Error finding correlation peak (%d)\n", ret);
|
||||
return SRSLTE_ERROR;
|
||||
}
|
||||
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) {
|
||||
ret = find_peak_ok(q);
|
||||
ret = find_peak_ok(q, input_buffer);
|
||||
}
|
||||
break;
|
||||
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->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
|
||||
|
@ -445,7 +453,7 @@ int srslte_ue_sync_get_buffer(srslte_ue_sync_t *q, cf_t **sf_symbols) {
|
|||
track_idx = 0;
|
||||
|
||||
/* 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,
|
||||
&track_idx);
|
||||
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 */
|
||||
if (!q->strack.correct_cfo && q->correct_cfo) {
|
||||
srslte_cfo_correct(&q->sfind.cfocorr,
|
||||
q->input_buffer,
|
||||
q->input_buffer,
|
||||
input_buffer,
|
||||
input_buffer,
|
||||
-srslte_sync_get_cfo(&q->strack) / q->fft_size);
|
||||
|
||||
}
|
||||
*sf_symbols = q->input_buffer;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -57,9 +57,9 @@ int srslte_ue_ul_init(srslte_ue_ul_t *q,
|
|||
goto clean_exit;
|
||||
}
|
||||
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)) {
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
void srslte_ue_ul_set_cfg(srslte_ue_ul_t *q,
|
||||
srslte_refsignal_dmrs_pusch_cfg_t *pusch_cfg,
|
||||
srslte_pucch_cfg_t *pucch_cfg,
|
||||
srslte_refsignal_dmrs_pusch_cfg_t *dmrs_cfg,
|
||||
srslte_refsignal_srs_cfg_t *srs_cfg,
|
||||
srslte_pucch_cfg_t *pucch_cfg,
|
||||
srslte_pucch_sched_t *pucch_sched,
|
||||
bool group_hopping_en,
|
||||
bool sequence_hopping_en)
|
||||
srslte_uci_cfg_t *uci_cfg,
|
||||
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_pucch_set_cfg(&q->pucch, pucch_cfg, group_hopping_en);
|
||||
srslte_refsignal_ul_set_cfg(&q->signals, dmrs_cfg, pucch_cfg, srs_cfg);
|
||||
if (pucch_cfg && dmrs_cfg) {
|
||||
srslte_pucch_set_cfg(&q->pucch, pucch_cfg, dmrs_cfg->group_hopping_en);
|
||||
}
|
||||
if (pucch_sched) {
|
||||
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,
|
||||
srslte_pusch_hopping_cfg_t *hopping_cfg,
|
||||
srslte_refsignal_srs_cfg_t *srs_cfg,
|
||||
uint32_t tti, uint32_t cyclic_shift_for_dmrs, uint32_t rvidx)
|
||||
int srslte_ue_ul_cfg_grant(srslte_ue_ul_t *q, srslte_ra_ul_grant_t *grant,
|
||||
uint32_t tti, uint32_t rvidx, uint32_t current_tx_nb)
|
||||
{
|
||||
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
|
||||
*/
|
||||
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,
|
||||
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) {
|
||||
n_pucch = q->pucch_sched.n_pucch_1[q->pucch_sched.tpc_for_pucch%4];
|
||||
} else {
|
||||
n_pucch = q->pucch_sched.n_cce + q->pucch_sched.N_pucch_1;
|
||||
n_pucch = pdcch_n_cce + q->pucch_sched.N_pucch_1;
|
||||
}
|
||||
} else {
|
||||
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,
|
||||
q->pusch_cfg.grant.L_prb,
|
||||
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->sf_symbols);
|
||||
} else {
|
||||
if (srslte_refsignal_dmrs_pusch_gen(&q->signals, q->pusch_cfg.grant.L_prb,
|
||||
q->pusch_cfg.sf_idx,
|
||||
q->pusch_cfg.cyclic_shift_for_dmrs,
|
||||
q->pusch_cfg.grant.ncs_dmrs,
|
||||
q->refsignal))
|
||||
{
|
||||
fprintf(stderr, "Error generating PUSCH DRMS signals\n");
|
||||
|
|
|
@ -28,6 +28,7 @@
|
|||
|
||||
#include <float.h>
|
||||
#include <complex.h>
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
|
@ -159,6 +160,22 @@ void srslte_vec_sc_prod_fff(float *x, float h, float *z, uint32_t len) {
|
|||
#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) {
|
||||
#ifndef HAVE_VOLK_MULT_FUNCTION
|
||||
int i;
|
||||
|
|
Loading…
Reference in New Issue