|
|
@ -40,6 +40,8 @@
|
|
|
|
namespace srslte {
|
|
|
|
namespace srslte {
|
|
|
|
namespace ue {
|
|
|
|
namespace ue {
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool mac::init(phy *phy_h_, tti_sync* ttisync_, log* log_h_)
|
|
|
|
bool mac::init(phy *phy_h_, tti_sync* ttisync_, log* log_h_)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
started = false;
|
|
|
|
started = false;
|
|
|
@ -59,6 +61,13 @@ bool mac::init(phy *phy_h_, tti_sync* ttisync_, log* log_h_)
|
|
|
|
is_first_of_burst = true;
|
|
|
|
is_first_of_burst = true;
|
|
|
|
reset();
|
|
|
|
reset();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
for (int i=0;i<NOF_TTI_THREADS;i++) {
|
|
|
|
|
|
|
|
tti_threads_sync[i].set_increment(NOF_TTI_THREADS);
|
|
|
|
|
|
|
|
if (!tti_threads[i].init(this, &tti_threads_sync[i])) {
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
if (threads_new_rt_prio(&mac_thread, mac_thread_fnc, this, 5)) {
|
|
|
|
if (threads_new_rt_prio(&mac_thread, mac_thread_fnc, this, 5)) {
|
|
|
|
started = true;
|
|
|
|
started = true;
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -70,6 +79,9 @@ void mac::stop()
|
|
|
|
{
|
|
|
|
{
|
|
|
|
started = false;
|
|
|
|
started = false;
|
|
|
|
pthread_join(mac_thread, NULL);
|
|
|
|
pthread_join(mac_thread, NULL);
|
|
|
|
|
|
|
|
for (int i=0;i<NOF_TTI_THREADS;i++) {
|
|
|
|
|
|
|
|
tti_threads[i].stop();
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int mac::get_tti()
|
|
|
|
int mac::get_tti()
|
|
|
@ -188,6 +200,10 @@ void mac::main_radio_loop() {
|
|
|
|
for (int i=0;i<1000;i++) {
|
|
|
|
for (int i=0;i<1000;i++) {
|
|
|
|
tti = ttisync->wait();
|
|
|
|
tti = ttisync->wait();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
for (int i=0;i<NOF_TTI_THREADS;i++) {
|
|
|
|
|
|
|
|
tti_threads_sync[i].set_producer_cntr(tti+i);
|
|
|
|
|
|
|
|
tti_threads_sync[i].resync();
|
|
|
|
|
|
|
|
}
|
|
|
|
is_synchronized = true;
|
|
|
|
is_synchronized = true;
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
Error("Starting PHY receiver\n");
|
|
|
|
Error("Starting PHY receiver\n");
|
|
|
@ -233,61 +249,11 @@ void mac::main_radio_loop() {
|
|
|
|
ra_procedure.step(tti);
|
|
|
|
ra_procedure.step(tti);
|
|
|
|
//phr_procedure.step(tti);
|
|
|
|
//phr_procedure.step(tti);
|
|
|
|
|
|
|
|
|
|
|
|
// Receive PCH, if requested
|
|
|
|
|
|
|
|
receive_pch(tti);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Process DL grants always
|
|
|
|
|
|
|
|
process_dl_grants(tti);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Send pending HARQ ACK, if any, and contention resolution is resolved
|
|
|
|
|
|
|
|
if (dl_harq.is_ack_pending_resolution()) {
|
|
|
|
|
|
|
|
ra_procedure.step(tti);
|
|
|
|
|
|
|
|
if (ra_procedure.is_successful() || ra_procedure.is_response_error()) {
|
|
|
|
|
|
|
|
Info("Sending pending ACK for contention resolution PHY TTI: %d\n", phy_h->get_current_tti());
|
|
|
|
|
|
|
|
dl_harq.send_pending_ack_contention_resolution();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Process UL grants if RA procedure is done and we have pending data or in contention resolution
|
|
|
|
|
|
|
|
if (ra_procedure.is_contention_resolution() || ra_procedure.is_successful()) {
|
|
|
|
|
|
|
|
process_ul_grants(tti);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
ul_buffer *ul_buffer = phy_h->get_ul_buffer(tti+4);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Generate scheduling request if we have to
|
|
|
|
|
|
|
|
if (phy_h->sr_is_ready_to_send(tti+4)) {
|
|
|
|
|
|
|
|
ul_buffer->generate_sr();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// The UL buffer is released when successfully transmitted.
|
|
|
|
|
|
|
|
if (ul_buffer->is_released()) {
|
|
|
|
|
|
|
|
ul_buffer->ready();
|
|
|
|
|
|
|
|
is_first_of_burst = false;
|
|
|
|
|
|
|
|
} else if (ul_buffer->uci_ready() || ul_buffer->srs_is_ready_to_send()) {
|
|
|
|
|
|
|
|
// If the packet was not generated by a call from MAC, means it's PUCCH or SRS. Generate now the signal
|
|
|
|
|
|
|
|
ul_buffer->generate_data();
|
|
|
|
|
|
|
|
ul_buffer->ready();
|
|
|
|
|
|
|
|
is_first_of_burst = false;
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
if (!is_first_of_burst) {
|
|
|
|
|
|
|
|
ul_buffer->set_end_of_burst();
|
|
|
|
|
|
|
|
is_first_of_burst = true;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
timers_db.step_all();
|
|
|
|
timers_db.step_all();
|
|
|
|
|
|
|
|
|
|
|
|
// Check if there is pending CCCH SDU in Multiplexing Unit
|
|
|
|
// Trigger execution of corresponding TTI processor thread
|
|
|
|
if (mux_unit.is_pending_ccch_sdu()) {
|
|
|
|
tti_threads_sync[tti%NOF_TTI_THREADS].increase();
|
|
|
|
// Start RA procedure
|
|
|
|
|
|
|
|
if (!ra_procedure.in_progress() && !ra_procedure.is_successful()) {
|
|
|
|
|
|
|
|
ra_procedure.start_rlc_order();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if (ra_procedure.is_successful() && phy_rnti != params_db.get_param(mac_params::RNTI_C) && params_db.get_param(mac_params::RNTI_C) > 0) {
|
|
|
|
|
|
|
|
phy_rnti = params_db.get_param(mac_params::RNTI_C);
|
|
|
|
|
|
|
|
set_phy_crnti(phy_rnti);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -620,5 +586,96 @@ void mac::setup_lcid(uint32_t lcid, uint32_t lcg, uint32_t priority, int PBR_x_t
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void* tti_thread_runner(void *arg) {
|
|
|
|
|
|
|
|
mac::tti_thread* x = (mac::tti_thread*) arg;
|
|
|
|
|
|
|
|
x->run();
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
bool mac::tti_thread::init(mac* parent_, tti_sync_cv *sync_)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
parent = parent_;
|
|
|
|
|
|
|
|
log_h = parent->log_h;
|
|
|
|
|
|
|
|
sync_ = sync;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
started = threads_new_rt(&thread, tti_thread_runner, this);
|
|
|
|
|
|
|
|
return started;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void mac::tti_thread::stop()
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
started = false;
|
|
|
|
|
|
|
|
pthread_join(thread, NULL);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
void mac::tti_thread::run()
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
while(started) {
|
|
|
|
|
|
|
|
uint32_t tti = sync->wait();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (parent->is_synchronized) {
|
|
|
|
|
|
|
|
// Receive PCH, if requested
|
|
|
|
|
|
|
|
parent->receive_pch(tti);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Process DL grants always
|
|
|
|
|
|
|
|
parent->process_dl_grants(tti);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Send pending HARQ ACK, if any, and contention resolution is resolved
|
|
|
|
|
|
|
|
if (parent->dl_harq.is_ack_pending_resolution()) {
|
|
|
|
|
|
|
|
parent->ra_procedure.step(tti);
|
|
|
|
|
|
|
|
if (parent->ra_procedure.is_successful() || parent->ra_procedure.is_response_error()) {
|
|
|
|
|
|
|
|
Info("Sending pending ACK for contention resolution PHY TTI: %d\n", parent->phy_h->get_current_tti());
|
|
|
|
|
|
|
|
parent->dl_harq.send_pending_ack_contention_resolution();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Process UL grants if RA procedure is done or in contention resolution
|
|
|
|
|
|
|
|
if (parent->ra_procedure.is_contention_resolution() || parent->ra_procedure.is_successful()) {
|
|
|
|
|
|
|
|
parent->process_ul_grants(tti);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// If ACK/SR was pending but there was no PUSCH transmission, transmit now through PUCCH
|
|
|
|
|
|
|
|
ul_buffer *ul_buffer = parent->phy_h->get_ul_buffer(tti+4);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Generate scheduling request if we have to
|
|
|
|
|
|
|
|
if (parent->phy_h->sr_is_ready_to_send(tti+4)) {
|
|
|
|
|
|
|
|
ul_buffer->generate_sr();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// The UL buffer is released when successfully transmitted.
|
|
|
|
|
|
|
|
if (ul_buffer->is_released()) {
|
|
|
|
|
|
|
|
ul_buffer->ready();
|
|
|
|
|
|
|
|
parent->is_first_of_burst = false;
|
|
|
|
|
|
|
|
} else if (ul_buffer->uci_ready() || ul_buffer->srs_is_ready_to_send()) {
|
|
|
|
|
|
|
|
// If the packet was not generated by a call from MAC, means it's PUCCH or SRS. Generate now the signal
|
|
|
|
|
|
|
|
ul_buffer->generate_data();
|
|
|
|
|
|
|
|
ul_buffer->ready();
|
|
|
|
|
|
|
|
parent->is_first_of_burst = false;
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
if (!parent->is_first_of_burst) {
|
|
|
|
|
|
|
|
ul_buffer->set_end_of_burst();
|
|
|
|
|
|
|
|
parent->is_first_of_burst = true;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Check if there is pending CCCH SDU in Multiplexing Unit
|
|
|
|
|
|
|
|
if (parent->mux_unit.is_pending_ccch_sdu()) {
|
|
|
|
|
|
|
|
// Start RA procedure
|
|
|
|
|
|
|
|
if (!parent->ra_procedure.in_progress() && !parent->ra_procedure.is_successful()) {
|
|
|
|
|
|
|
|
parent->ra_procedure.start_rlc_order();
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
if (parent->ra_procedure.is_successful() && parent->phy_rnti != parent->params_db.get_param(mac_params::RNTI_C) &&
|
|
|
|
|
|
|
|
parent->params_db.get_param(mac_params::RNTI_C) > 0)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
parent->phy_rnti = parent->params_db.get_param(mac_params::RNTI_C);
|
|
|
|
|
|
|
|
parent->set_phy_crnti(parent->phy_rnti);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|