Commit 0799a07f authored by Ben Wojtowicz's avatar Ben Wojtowicz

Version 0.19.3: Added support for PUCCH decode in liblte, added support for...

Version 0.19.3: Added support for PUCCH decode in liblte, added support for H-ARQ and PUCCH in LTE_fdd_enodeb, and fixed a bug related to improper cleanup of the inactivity timer in LTE_fdd_enodeb.
parent d232409f
......@@ -23,7 +23,7 @@
########################################################################
cmake_minimum_required(VERSION 2.6)
project(openLTE CXX C)
set(openLTE_version 0.19.1)
set(openLTE_version 0.19.3)
enable_testing()
#select the release build type by default to get optimization flags
......
......@@ -222,3 +222,6 @@ v00.19.02 Pulled in unit tests for the turbo decoder from Ziming He, optimiz
EPS bearer context (thanks to Pedro Batista), moved the message queue
empty error to a warning, and properly updating the user list iterator
after erasing a user (thanks to Damian Jarek).
v00.19.03 Added support for PUCCH decode in liblte, added support for H-ARQ and
PUCCH in LTE_fdd_enodeb, and fixed a bug related to improper cleanup
of the inactivity timer in LTE_fdd_enodeb
/*******************************************************************************
Copyright 2015 Ben Wojtowicz
Copyright 2015-2016 Ben Wojtowicz
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
......@@ -24,6 +24,7 @@
Revision History
---------- ------------- --------------------------------------------
02/15/2015 Ben Wojtowicz Created file
03/12/2016 Ben Wojtowicz Added error for H-ARQ info not found.
*******************************************************************************/
......@@ -73,6 +74,7 @@ typedef enum{
LTE_FDD_ENB_ERROR_CANT_REASSEMBLE_SDU,
LTE_FDD_ENB_ERROR_DUPLICATE_ENTRY,
LTE_FDD_ENB_ERROR_READ_ONLY,
LTE_FDD_ENB_ERROR_HARQ_INFO_NOT_FOUND,
LTE_FDD_ENB_ERROR_N_ITEMS,
}LTE_FDD_ENB_ERROR_ENUM;
static const char LTE_fdd_enb_error_text[LTE_FDD_ENB_ERROR_N_ITEMS][100] = {"none",
......@@ -97,7 +99,8 @@ static const char LTE_fdd_enb_error_text[LTE_FDD_ENB_ERROR_N_ITEMS][100] = {"non
"timer not found",
"cant reassemble SDU",
"duplicate entry",
"read only"};
"read only",
"HARQ info not found"};
/*******************************************************************************
CLASS DECLARATIONS
......
/*******************************************************************************
Copyright 2013-2015 Ben Wojtowicz
Copyright 2013-2016 Ben Wojtowicz
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
......@@ -43,6 +43,7 @@
12/06/2015 Ben Wojtowicz Changed boost::mutex and
boost::interprocess::interprocess_semaphore
to sem_t.
03/12/2016 Ben Wojtowicz Added PUCCH support.
*******************************************************************************/
......@@ -177,11 +178,16 @@ typedef struct{
uint32 current_tti;
}LTE_FDD_ENB_DL_SCHEDULE_MSG_STRUCT;
typedef struct{
LIBLTE_PHY_PDCCH_STRUCT decodes;
uint32 N_avail_prbs;
uint32 N_sched_prbs;
uint32 current_tti;
uint8 next_prb;
uint16 rnti;
bool decode;
}LTE_FDD_ENB_PUCCH_STRUCT;
typedef struct{
LIBLTE_PHY_PDCCH_STRUCT decodes;
LTE_FDD_ENB_PUCCH_STRUCT pucch;
uint32 N_avail_prbs;
uint32 N_sched_prbs;
uint32 current_tti;
uint8 next_prb;
}LTE_FDD_ENB_UL_SCHEDULE_MSG_STRUCT;
typedef struct{
LTE_FDD_ENB_DL_SCHEDULE_MSG_STRUCT dl_sched;
......@@ -202,6 +208,8 @@ typedef struct{
}LTE_FDD_ENB_PRACH_DECODE_MSG_STRUCT;
typedef struct{
uint32 current_tti;
uint16 rnti;
bool ack;
}LTE_FDD_ENB_PUCCH_DECODE_MSG_STRUCT;
typedef struct{
LIBLTE_BIT_MSG_STRUCT msg;
......
......@@ -41,6 +41,7 @@
12/06/2015 Ben Wojtowicz Changed the deletion and C-RNTI release
procedures.
02/13/2016 Ben Wojtowicz Added an inactivity timer.
03/12/2016 Ben Wojtowicz Added H-ARQ support.
*******************************************************************************/
......@@ -52,6 +53,7 @@
*******************************************************************************/
#include "LTE_fdd_enb_rb.h"
#include "liblte_phy.h"
#include "liblte_mac.h"
#include "liblte_mme.h"
#include "typedefs.h"
......@@ -109,6 +111,11 @@ typedef struct{
uint32 dl_bytes_per_subfn;
}LTE_FDD_ENB_QOS_STRUCT;
typedef struct{
LIBLTE_MAC_PDU_STRUCT mac_pdu;
LIBLTE_PHY_ALLOCATION_STRUCT alloc;
}LTE_FDD_ENB_HARQ_INFO_STRUCT;
/*******************************************************************************
CLASS DECLARATIONS
*******************************************************************************/
......@@ -203,6 +210,9 @@ public:
void flip_ul_ndi(void);
void start_ul_sched_timer(uint32 m_seconds);
void stop_ul_sched_timer(void);
void store_harq_info(uint32 pucch_tti, LIBLTE_MAC_PDU_STRUCT *mac_pdu, LIBLTE_PHY_ALLOCATION_STRUCT *alloc);
void clear_harq_info(uint32 pucch_tti);
LTE_FDD_ENB_ERROR_ENUM get_harq_info(uint32 pucch_tti, LIBLTE_MAC_PDU_STRUCT *mac_pdu, LIBLTE_PHY_ALLOCATION_STRUCT *alloc);
// Generic
void set_N_del_ticks(uint32 N_ticks);
......@@ -259,10 +269,12 @@ private:
bool eit_flag;
// MAC
uint32 ul_sched_timer_m_seconds;
uint32 ul_sched_timer_id;
bool dl_ndi;
bool ul_ndi;
sem_t harq_buffer_sem;
std::map<uint32, LTE_FDD_ENB_HARQ_INFO_STRUCT*> harq_buffer;
uint32 ul_sched_timer_m_seconds;
uint32 ul_sched_timer_id;
bool dl_ndi;
bool ul_ndi;
// Generic
void handle_timer_expiry(uint32 timer_id);
......
......@@ -59,6 +59,7 @@
structure (thanks to Markus Grab for finding
this).
02/13/2016 Ben Wojtowicz Added a user inactivity timer.
03/12/2016 Ben Wojtowicz Added PUCCH and H-ARQ support.
*******************************************************************************/
......@@ -184,6 +185,8 @@ void LTE_fdd_enb_mac::start(LTE_fdd_enb_msgq *from_phy,
sched_ul_subfr[i].N_sched_prbs = 0;
sched_ul_subfr[i].current_tti = i;
sched_ul_subfr[i].next_prb = 0;
sched_ul_subfr[i].pucch.decode = false;
sched_ul_subfr[i].pucch.rnti = LIBLTE_MAC_INVALID_RNTI;
}
sched_dl_subfr[0].current_tti = 10;
sched_dl_subfr[1].current_tti = 11;
......@@ -363,6 +366,8 @@ void LTE_fdd_enb_mac::handle_ready_to_send(LTE_FDD_ENB_READY_TO_SEND_MSG_STRUCT
sched_ul_subfr[sched_cur_ul_subfn].decodes.N_alloc = 0;
sched_ul_subfr[sched_cur_ul_subfn].N_sched_prbs = 0;
sched_ul_subfr[sched_cur_ul_subfn].next_prb = 0;
sched_ul_subfr[sched_cur_ul_subfn].pucch.decode = false;
sched_ul_subfr[sched_cur_ul_subfn].pucch.rnti = LIBLTE_MAC_INVALID_RNTI;
sem_post(&sys_info_sem);
// Advance the subframe numbers
......@@ -388,6 +393,8 @@ void LTE_fdd_enb_mac::handle_ready_to_send(LTE_FDD_ENB_READY_TO_SEND_MSG_STRUCT
sched_ul_subfr[sched_cur_ul_subfn].decodes.N_alloc = 0;
sched_ul_subfr[sched_cur_ul_subfn].N_sched_prbs = 0;
sched_ul_subfr[sched_cur_ul_subfn].next_prb = 0;
sched_ul_subfr[sched_cur_ul_subfn].pucch.decode = false;
sched_ul_subfr[sched_cur_ul_subfn].pucch.rnti = LIBLTE_MAC_INVALID_RNTI;
sem_post(&sys_info_sem);
// Advance the subframe numbers
......@@ -411,11 +418,77 @@ void LTE_fdd_enb_mac::handle_prach_decode(LTE_FDD_ENB_PRACH_DECODE_MSG_STRUCT *p
}
void LTE_fdd_enb_mac::handle_pucch_decode(LTE_FDD_ENB_PUCCH_DECODE_MSG_STRUCT *pucch_decode)
{
interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_ERROR,
LTE_fdd_enb_user_mgr *user_mgr = LTE_fdd_enb_user_mgr::get_instance();
LTE_fdd_enb_user *user;
LIBLTE_MAC_PDU_STRUCT mac_pdu;
LIBLTE_PHY_ALLOCATION_STRUCT alloc;
interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_INFO,
LTE_FDD_ENB_DEBUG_LEVEL_MAC,
__FILE__,
__LINE__,
"Not handling PUCCH_DECODE");
"PUCCH decode received %u for %u",
pucch_decode->ack,
pucch_decode->current_tti);
if(LTE_FDD_ENB_ERROR_NONE == user_mgr->find_user(pucch_decode->rnti, &user))
{
if(pucch_decode->ack)
{
user->clear_harq_info(pucch_decode->current_tti);
interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_INFO,
LTE_FDD_ENB_DEBUG_LEVEL_MAC,
__FILE__,
__LINE__,
"Clearing HARQ info RNTI=%u TTI=%u",
pucch_decode->rnti,
pucch_decode->current_tti);
}else{
if(LTE_FDD_ENB_ERROR_NONE == user->get_harq_info(pucch_decode->current_tti,
&mac_pdu,
&alloc))
{
alloc.ndi = user->get_dl_ndi();
if(LTE_FDD_ENB_ERROR_NONE == add_to_dl_sched_queue(add_to_tti(sched_dl_subfr[sched_cur_dl_subfn].current_tti,
4),
&mac_pdu,
&alloc))
{
interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_INFO,
LTE_FDD_ENB_DEBUG_LEVEL_MAC,
__FILE__,
__LINE__,
"Resending HARQ info RNTI=%u TTI=%u",
pucch_decode->rnti,
pucch_decode->current_tti);
}else{
interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_ERROR,
LTE_FDD_ENB_DEBUG_LEVEL_MAC,
__FILE__,
__LINE__,
"Failed to resend HARQ info RNTI=%u TTI=%u",
pucch_decode->rnti,
pucch_decode->current_tti);
}
}else{
interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_ERROR,
LTE_FDD_ENB_DEBUG_LEVEL_MAC,
__FILE__,
__LINE__,
"Failed to find HARQ info RNTI=%u TTI=%u",
pucch_decode->rnti,
pucch_decode->current_tti);
}
}
}else{
interface->send_debug_msg(LTE_FDD_ENB_DEBUG_TYPE_ERROR,
LTE_FDD_ENB_DEBUG_LEVEL_MAC,
__FILE__,
__LINE__,
"Failed to find PUCCH user RNTI=%u TTI=%u",
pucch_decode->rnti,
pucch_decode->current_tti);
}
}
void LTE_fdd_enb_mac::handle_pusch_decode(LTE_FDD_ENB_PUSCH_DECODE_MSG_STRUCT *pusch_decode)
{
......@@ -881,7 +954,9 @@ void LTE_fdd_enb_mac::construct_random_access_response(uint8 preamble,
void LTE_fdd_enb_mac::scheduler(void)
{
libtools_scoped_lock lock(sys_info_sem);
LTE_fdd_enb_phy *phy = LTE_fdd_enb_phy::get_instance();
LTE_fdd_enb_phy *phy = LTE_fdd_enb_phy::get_instance();
LTE_fdd_enb_user_mgr *user_mgr = LTE_fdd_enb_user_mgr::get_instance();
LTE_fdd_enb_user *user;
LTE_FDD_ENB_RAR_SCHED_QUEUE_STRUCT *rar_sched;
LTE_FDD_ENB_DL_SCHED_QUEUE_STRUCT *dl_sched;
LTE_FDD_ENB_UL_SCHED_QUEUE_STRUCT *ul_sched;
......@@ -1123,6 +1198,14 @@ void LTE_fdd_enb_mac::scheduler(void)
sizeof(LIBLTE_PHY_ALLOCATION_STRUCT));
sched_dl_subfr[sched_cur_dl_subfn].dl_allocations.N_alloc++;
// Schedule PUCCH 4 subframes from now and store the DL allocation for potential H-ARQ retransmission
sched_ul_subfr[(sched_cur_dl_subfn+4)%10].pucch.decode = true;
sched_ul_subfr[(sched_cur_dl_subfn+4)%10].pucch.rnti = dl_sched->alloc.rnti;
if(LTE_FDD_ENB_ERROR_NONE == user_mgr->find_user(dl_sched->alloc.rnti, &user))
{
user->store_harq_info(sched_ul_subfr[(sched_cur_dl_subfn+4)%10].current_tti, &dl_sched->mac_pdu, &dl_sched->alloc);
}
// Remove DL schedule from queue
dl_sched_queue.pop_front();
delete dl_sched;
......
#line 2 "LTE_fdd_enb_phy.cc" // Make __FILE__ omit the path
/*******************************************************************************
Copyright 2013-2015 Ben Wojtowicz
Copyright 2013-2016 Ben Wojtowicz
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
......@@ -47,6 +47,7 @@
new radio interface.
12/06/2015 Ben Wojtowicz Changed boost::mutex to pthread_mutex_t and
sem_t.
03/12/2016 Ben Wojtowicz Added PUCCH support.
*******************************************************************************/
......@@ -182,7 +183,9 @@ void LTE_fdd_enb_phy::start(LTE_fdd_enb_msgq *from_mac,
sys_info.sib2.rr_config_common_sib.pusch_cnfg.ul_rs.group_hopping_enabled,
sys_info.sib2.rr_config_common_sib.pusch_cnfg.ul_rs.sequence_hopping_enabled,
sys_info.sib2.rr_config_common_sib.pusch_cnfg.ul_rs.cyclic_shift,
0);
0,
sys_info.sib2.rr_config_common_sib.pucch_cnfg.n_cs_an,
sys_info.sib2.rr_config_common_sib.pucch_cnfg.delta_pucch_shift);
// Downlink
for(i=0; i<10; i++)
......@@ -736,12 +739,13 @@ void LTE_fdd_enb_phy::process_dl(LTE_FDD_ENB_RADIO_TX_BUF_STRUCT *tx_buf)
/****************/
void LTE_fdd_enb_phy::process_ul(LTE_FDD_ENB_RADIO_RX_BUF_STRUCT *rx_buf)
{
uint32 N_skipped_subfrs = 0;
uint32 sfn;
uint32 i;
uint32 I_prb_ra;
uint32 n_group_phich;
uint32 n_seq_phich;
LIBLTE_ERROR_ENUM subfr_err;
uint32 N_skipped_subfrs = 0;
uint32 sfn;
uint32 i;
uint32 I_prb_ra;
uint32 n_group_phich;
uint32 n_seq_phich;
// Check the received current_tti
if(rx_buf->current_tti != ul_current_tti)
......@@ -785,50 +789,75 @@ void LTE_fdd_enb_phy::process_ul(LTE_FDD_ENB_RADIO_RX_BUF_STRUCT *rx_buf)
}
}
sem_wait(&ul_sched_sem);
if(ul_schedule[ul_subframe.num].pucch.decode ||
0 != ul_schedule[ul_subframe.num].decodes.N_alloc)
{
subfr_err = liblte_phy_get_ul_subframe(phy_struct,
rx_buf->i_buf,
rx_buf->q_buf,
&ul_subframe);
}
// Handle PUCCH
// FIXME
if(LIBLTE_SUCCESS == subfr_err &&
ul_schedule[ul_subframe.num].pucch.decode)
{
pucch_decode.current_tti = ul_current_tti;
pucch_decode.rnti = ul_schedule[ul_subframe.num].pucch.rnti;
if(LIBLTE_SUCCESS == liblte_phy_pucch_channel_decode(phy_struct,
&ul_subframe,
sys_info.N_id_cell,
sys_info.N_ant,
0)) // FIXME: N_1_p_pucch
{
pucch_decode.ack = true;
}else{
pucch_decode.ack = false;
}
msgq_to_mac->send(LTE_FDD_ENB_MESSAGE_TYPE_PUCCH_DECODE,
LTE_FDD_ENB_DEST_LAYER_MAC,
(LTE_FDD_ENB_MESSAGE_UNION *)&pucch_decode,
sizeof(LTE_FDD_ENB_PUCCH_DECODE_MSG_STRUCT));
}
ul_schedule[ul_subframe.num].pucch.decode = false;
ul_schedule[ul_subframe.num].pucch.rnti = LIBLTE_MAC_INVALID_RNTI;
// Handle PUSCH
sem_wait(&ul_sched_sem);
if(0 != ul_schedule[ul_subframe.num].decodes.N_alloc)
if(LIBLTE_SUCCESS == subfr_err &&
0 != ul_schedule[ul_subframe.num].decodes.N_alloc)
{
if(LIBLTE_SUCCESS == liblte_phy_get_ul_subframe(phy_struct,
rx_buf->i_buf,
rx_buf->q_buf,
&ul_subframe))
for(i=0; i<ul_schedule[ul_subframe.num].decodes.N_alloc; i++)
{
for(i=0; i<ul_schedule[ul_subframe.num].decodes.N_alloc; i++)
// Determine PHICH indecies
I_prb_ra = ul_schedule[ul_subframe.num].decodes.alloc[i].prb[0][0];
n_group_phich = I_prb_ra % phy_struct->N_group_phich;
n_seq_phich = (I_prb_ra/phy_struct->N_group_phich) % (2*phy_struct->N_sf_phich);
// Attempt decode
if(LIBLTE_SUCCESS == liblte_phy_pusch_channel_decode(phy_struct,
&ul_subframe,
&ul_schedule[ul_subframe.num].decodes.alloc[i],
sys_info.N_id_cell,
1,
pusch_decode.msg.msg,
&pusch_decode.msg.N_bits))
{
// Determine PHICH indecies
I_prb_ra = ul_schedule[ul_subframe.num].decodes.alloc[i].prb[0][0];
n_group_phich = I_prb_ra % phy_struct->N_group_phich;
n_seq_phich = (I_prb_ra/phy_struct->N_group_phich) % (2*phy_struct->N_sf_phich);
// Attempt decode
if(LIBLTE_SUCCESS == liblte_phy_pusch_channel_decode(phy_struct,
&ul_subframe,
&ul_schedule[ul_subframe.num].decodes.alloc[i],
sys_info.N_id_cell,
1,
pusch_decode.msg.msg,
&pusch_decode.msg.N_bits))
{
pusch_decode.current_tti = ul_current_tti;
pusch_decode.rnti = ul_schedule[ul_subframe.num].decodes.alloc[i].rnti;
msgq_to_mac->send(LTE_FDD_ENB_MESSAGE_TYPE_PUSCH_DECODE,
LTE_FDD_ENB_DEST_LAYER_MAC,
(LTE_FDD_ENB_MESSAGE_UNION *)&pusch_decode,
sizeof(LTE_FDD_ENB_PUSCH_DECODE_MSG_STRUCT));
// Add ACK to PHICH
phich[(ul_subframe.num + 4) % 10].present[n_group_phich][n_seq_phich] = true;
phich[(ul_subframe.num + 4) % 10].b[n_group_phich][n_seq_phich] = 1;
}else{
// Add NACK to PHICH
phich[(ul_subframe.num + 4) % 10].present[n_group_phich][n_seq_phich] = true;
phich[(ul_subframe.num + 4) % 10].b[n_group_phich][n_seq_phich] = 0;
}
pusch_decode.current_tti = ul_current_tti;
pusch_decode.rnti = ul_schedule[ul_subframe.num].decodes.alloc[i].rnti;
msgq_to_mac->send(LTE_FDD_ENB_MESSAGE_TYPE_PUSCH_DECODE,
LTE_FDD_ENB_DEST_LAYER_MAC,
(LTE_FDD_ENB_MESSAGE_UNION *)&pusch_decode,
sizeof(LTE_FDD_ENB_PUSCH_DECODE_MSG_STRUCT));
// Add ACK to PHICH
phich[(ul_subframe.num + 4) % 10].present[n_group_phich][n_seq_phich] = true;
phich[(ul_subframe.num + 4) % 10].b[n_group_phich][n_seq_phich] = 1;
}else{
// Add NACK to PHICH
phich[(ul_subframe.num + 4) % 10].present[n_group_phich][n_seq_phich] = true;
phich[(ul_subframe.num + 4) % 10].b[n_group_phich][n_seq_phich] = 0;
}
}
}
......
......@@ -42,6 +42,8 @@
procedures and changed the QoS parameters
for default data.
02/13/2016 Ben Wojtowicz Added an inactivity timer.
03/12/2016 Ben Wojtowicz Added H-ARQ support and properly cleaning
up inactivity timer.
*******************************************************************************/
......@@ -55,6 +57,7 @@
#include "LTE_fdd_enb_mac.h"
#include "LTE_fdd_enb_rrc.h"
#include "liblte_mme.h"
#include "libtools_scoped_lock.h"
#include <boost/lexical_cast.hpp>
/*******************************************************************************
......@@ -125,6 +128,8 @@ LTE_fdd_enb_user::LTE_fdd_enb_user()
protocol_cnfg_opts.N_opts = 0;
// MAC
sem_init(&harq_buffer_sem, 0, 1);
harq_buffer.clear();
ul_sched_timer_id = LTE_FDD_ENB_INVALID_TIMER_ID;
dl_ndi = false;
ul_ndi = false;
......@@ -139,8 +144,17 @@ LTE_fdd_enb_user::LTE_fdd_enb_user()
}
LTE_fdd_enb_user::~LTE_fdd_enb_user()
{
LTE_fdd_enb_timer_mgr *timer_mgr = LTE_fdd_enb_timer_mgr::get_instance();
uint32 i;
LTE_fdd_enb_timer_mgr *timer_mgr = LTE_fdd_enb_timer_mgr::get_instance();
std::map<uint32, LTE_FDD_ENB_HARQ_INFO_STRUCT*>::iterator iter;
uint32 i;
// MAC
sem_wait(&harq_buffer_sem);
for(iter=harq_buffer.begin(); iter!=harq_buffer.end(); iter++)
{
delete (*iter).second;
}
sem_destroy(&harq_buffer_sem);
// Radio Bearers
for(i=0; i<8; i++)
......@@ -155,6 +169,10 @@ LTE_fdd_enb_user::~LTE_fdd_enb_user()
{
timer_mgr->stop_timer(ul_sched_timer_id);
}
if(LTE_FDD_ENB_INVALID_TIMER_ID != inactivity_timer_id)
{
timer_mgr->stop_timer(inactivity_timer_id);
}
}
/********************/
......@@ -644,6 +662,55 @@ void LTE_fdd_enb_user::stop_ul_sched_timer(void)
timer_mgr->stop_timer(ul_sched_timer_id);
ul_sched_timer_id = LTE_FDD_ENB_INVALID_TIMER_ID;
}
void LTE_fdd_enb_user::store_harq_info(uint32 pucch_tti,
LIBLTE_MAC_PDU_STRUCT *mac_pdu,
LIBLTE_PHY_ALLOCATION_STRUCT *alloc)
{
LTE_FDD_ENB_HARQ_INFO_STRUCT *harq_info = NULL;
harq_info = new LTE_FDD_ENB_HARQ_INFO_STRUCT;
if(NULL != harq_info)
{
memcpy(&harq_info->mac_pdu, mac_pdu, sizeof(LIBLTE_MAC_PDU_STRUCT));
memcpy(&harq_info->alloc, alloc, sizeof(LIBLTE_PHY_ALLOCATION_STRUCT));
sem_wait(&harq_buffer_sem);
harq_buffer[pucch_tti] = harq_info;
sem_post(&harq_buffer_sem);
}
}
void LTE_fdd_enb_user::clear_harq_info(uint32 pucch_tti)
{
libtools_scoped_lock lock(harq_buffer_sem);
std::map<uint32, LTE_FDD_ENB_HARQ_INFO_STRUCT*>::iterator iter;
iter = harq_buffer.find(pucch_tti);
if(harq_buffer.end() != iter)
{
delete (*iter).second;
harq_buffer.erase(iter);
}
}
LTE_FDD_ENB_ERROR_ENUM LTE_fdd_enb_user::get_harq_info(uint32 pucch_tti,
LIBLTE_MAC_PDU_STRUCT *mac_pdu,
LIBLTE_PHY_ALLOCATION_STRUCT *alloc)
{
libtools_scoped_lock lock(harq_buffer_sem);
std::map<uint32, LTE_FDD_ENB_HARQ_INFO_STRUCT*>::iterator iter;
LTE_FDD_ENB_ERROR_ENUM err = LTE_FDD_ENB_ERROR_HARQ_INFO_NOT_FOUND;
iter = harq_buffer.find(pucch_tti);
if(harq_buffer.end() != iter)
{
memcpy(mac_pdu, &(*iter).second->mac_pdu, sizeof(LIBLTE_MAC_PDU_STRUCT));
memcpy(alloc, &(*iter).second->alloc, sizeof(LIBLTE_PHY_ALLOCATION_STRUCT));
delete (*iter).second;
harq_buffer.erase(iter);
err = LTE_FDD_ENB_ERROR_NONE;
}
return(err);
}
/*****************/
/* Generic */
......
......@@ -71,6 +71,7 @@
code block segmentation/desegmentation to
globally available routines to support unit
tests.
03/12/2016 Ben Wojtowicz Added PUCCH channel decode support.
*******************************************************************************/
......@@ -119,6 +120,10 @@
#define LIBLTE_PHY_N_SC_RB_DL_NORMAL_CP 12
// FIXME: Add Extended CP
// M_pucch_rs
#define LIBLTE_PHY_M_PUCCH_RS 3
// FIXME: Add Extended CP
// N_ant
#define LIBLTE_PHY_N_ANT_MAX 4
......@@ -202,6 +207,7 @@ typedef enum{
LIBLTE_PHY_CHAN_TYPE_DLSCH = 0,
LIBLTE_PHY_CHAN_TYPE_PCH,
LIBLTE_PHY_CHAN_TYPE_ULSCH,
LIBLTE_PHY_CHAN_TYPE_ULCCH,
}LIBLTE_PHY_CHAN_TYPE_ENUM;
typedef struct{
......@@ -262,6 +268,18 @@ typedef struct{
uint8 pusch_scramb_bits[28800];
int8 pusch_soft_bits[28800];
// PUCCH
float pucch_z_est_re[LIBLTE_PHY_N_SC_RB_UL*14];
float pucch_z_est_im[LIBLTE_PHY_N_SC_RB_UL*14];
float pucch_c_est_0_re[LIBLTE_PHY_M_PUCCH_RS*LIBLTE_PHY_N_SC_RB_UL];
float pucch_c_est_0_im[LIBLTE_PHY_M_PUCCH_RS*LIBLTE_PHY_N_SC_RB_UL];
float pucch_c_est_1_re[LIBLTE_PHY_M_PUCCH_RS*LIBLTE_PHY_N_SC_RB_UL];
float pucch_c_est_1_im[LIBLTE_PHY_M_PUCCH_RS*LIBLTE_PHY_N_SC_RB_UL];
float pucch_c_est_re[LIBLTE_PHY_N_SC_RB_UL*14];
float pucch_c_est_im[LIBLTE_PHY_N_SC_RB_UL*14];
float pucch_z_re[LIBLTE_PHY_N_ANT_MAX][LIBLTE_PHY_N_SC_RB_UL*14];
float pucch_z_im[LIBLTE_PHY_N_ANT_MAX][LIBLTE_PHY_N_SC_RB_UL*14];
// UL Reference Signals
float ulrs_x_q_re[2048];
float ulrs_x_q_im[2048];
......@@ -270,11 +288,20 @@ typedef struct{
uint32 ulrs_c[160];
// DMRS
float dmrs_0_re[LIBLTE_PHY_N_SUBFR_PER_FRAME][LIBLTE_PHY_N_RB_UL_MAX][LIBLTE_PHY_N_RB_UL_MAX*LIBLTE_PHY_N_SC_RB_UL];
float dmrs_0_im[LIBLTE_PHY_N_SUBFR_PER_FRAME][LIBLTE_PHY_N_RB_UL_MAX][LIBLTE_PHY_N_RB_UL_MAX*LIBLTE_PHY_N_SC_RB_UL];
float dmrs_1_re[LIBLTE_PHY_N_SUBFR_PER_FRAME][LIBLTE_PHY_N_RB_UL_MAX][LIBLTE_PHY_N_RB_UL_MAX*LIBLTE_PHY_N_SC_RB_UL];
float dmrs_1_im[LIBLTE_PHY_N_SUBFR_PER_FRAME][LIBLTE_PHY_N_RB_UL_MAX][LIBLTE_PHY_N_RB_UL_MAX*LIBLTE_PHY_N_SC_RB_UL];
uint32 dmrs_c[1120];
float pusch_dmrs_0_re[LIBLTE_PHY_N_SUBFR_PER_FRAME][LIBLTE_PHY_N_RB_UL_MAX][LIBLTE_PHY_N_RB_UL_MAX*LIBLTE_PHY_N_SC_RB_UL];
float pusch_dmrs_0_im[LIBLTE_PHY_N_SUBFR_PER_FRAME][LIBLTE_PHY_N_RB_UL_MAX][LIBLTE_PHY_N_RB_UL_MAX*LIBLTE_PHY_N_SC_RB_UL];
float pusch_dmrs_1_re[LIBLTE_PHY_N_SUBFR_PER_FRAME][LIBLTE_PHY_N_RB_UL_MAX][LIBLTE_PHY_N_RB_UL_MAX*LIBLTE_PHY_N_SC_RB_UL];
float pusch_dmrs_1_im[LIBLTE_PHY_N_SUBFR_PER_FRAME][LIBLTE_PHY_N_RB_UL_MAX][LIBLTE_PHY_N_RB_UL_MAX*LIBLTE_PHY_N_SC_RB_UL];
float pucch_dmrs_0_re[LIBLTE_PHY_N_SUBFR_PER_FRAME][LIBLTE_PHY_N_RB_UL_MAX/2][LIBLTE_PHY_M_PUCCH_RS*LIBLTE_PHY_N_SC_RB_UL];
float pucch_dmrs_0_im[LIBLTE_PHY_N_SUBFR_PER_FRAME][LIBLTE_PHY_N_RB_UL_MAX/2][LIBLTE_PHY_M_PUCCH_RS*LIBLTE_PHY_N_SC_RB_UL];
float pucch_dmrs_1_re[LIBLTE_PHY_N_SUBFR_PER_FRAME][LIBLTE_PHY_N_RB_UL_MAX/2][LIBLTE_PHY_M_PUCCH_RS*LIBLTE_PHY_N_SC_RB_UL];
float pucch_dmrs_1_im[LIBLTE_PHY_N_SUBFR_PER_FRAME][LIBLTE_PHY_N_RB_UL_MAX/2][LIBLTE_PHY_M_PUCCH_RS*LIBLTE_PHY_N_SC_RB_UL];
float pucch_r_u_v_alpha_p_re[LIBLTE_PHY_N_SUBFR_PER_FRAME][LIBLTE_PHY_N_RB_UL_MAX/2][2][7][LIBLTE_PHY_N_SC_RB_UL];
float pucch_r_u_v_alpha_p_im[LIBLTE_PHY_N_SUBFR_PER_FRAME][LIBLTE_PHY_N_RB_UL_MAX/2][2][7][LIBLTE_PHY_N_SC_RB_UL];
uint32 pusch_dmrs_c[1120];
uint32 pucch_dmrs_c[1120];
uint32 pucch_n_prime_p[LIBLTE_PHY_N_SUBFR_PER_FRAME][LIBLTE_PHY_N_RB_UL_MAX/2][2];
uint32 pucch_n_oc_p[LIBLTE_PHY_N_SUBFR_PER_FRAME][LIBLTE_PHY_N_RB_UL_MAX/2][2];
// PRACH
fftwf_complex *prach_dft_in;
......@@ -560,6 +587,7 @@ typedef struct{
uint32 N_sc_rb_ul;
uint32 FFT_pad_size;
uint32 FFT_size;
uint8 N_ant;
bool ul_init;
}LIBLTE_PHY_STRUCT;
// Functions
......@@ -580,7 +608,9 @@ LIBLTE_ERROR_ENUM liblte_phy_ul_init(LIBLTE_PHY_STRUCT *phy_struct,
bool group_hopping_enabled,
bool sequence_hopping_enabled,
uint8 cyclic_shift,
uint8 cyclic_shift_dci);
uint8 cyclic_shift_dci,
uint8 N_cs_an,
uint8 delta_pucch_shift);
/*********************************************************************
Name: liblte_phy_cleanup
......@@ -683,6 +713,42 @@ LIBLTE_ERROR_ENUM liblte_phy_pusch_channel_decode(LIBLTE_PHY_STRUCT *
uint8 *out_bits,
uint32 *N_out_bits);
/*********************************************************************
Name: liblte_phy_pucch_channel_encode
Description: Encodes and modulates the Physical Uplink Control
Channel
Document Reference: 3GPP TS 36.211 v10.1.0 section 5.4
Notes: Only handling normal CP, N_ant=1, and Format 1, 1a, 1b
*********************************************************************/
// Defines
// Enums
// Structs
// Functions
// FIXME
/*********************************************************************
Name: liblte_phy_pucch_channel_decode
Description: Demodulates and decodes the Physical Uplink Control
Channel
Document Reference: 3GPP TS 36.211 v10.1.0 section 5.4
Notes: Only handling normal CP, N_ant=1, and Format 1, 1a, 1b
*********************************************************************/
// Defines
// Enums
// Structs
// Functions
LIBLTE_ERROR_ENUM liblte_phy_pucch_channel_decode(LIBLTE_PHY_STRUCT *phy_struct,
LIBLTE_PHY_SUBFRAME_STRUCT *subframe,
uint32 N_id_cell,
uint8 N_ant,
uint32 N_1_p_pucch);
/*********************************************************************
Name: liblte_phy_generate_prach
......
This diff is collapsed.
%
% Copyright 2016 Ben Wojtowicz
%
% This program 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.
%
% This program 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.
%
% You should have received a copy of the GNU Affero General Public License
% along with this program. If not, see <http://www.gnu.org/licenses/>.
%
% Function: lte_generate_dmrs_pucch_format1_1a_1b
% Description: Generates LTE demodulation reference signal for PUCCH formats 1, 1A, and 1B
% Inputs: N_subfr - Subframe number within a radio frame
% N_id_cell - Physical layer cell identity
% delta_ss - Configurable portion of the sequence-shift pattern for PUSCH (sib2 groupAssignmentPUSCH)
% group_hopping_enabled - Boolean value determining if group hopping is enabled (sib2 groupHoppingEnabled)
% sequence_hopping_enabled - Boolean value determining if sequence hopping is enabled (sib2 sequenceHoppingEnabled)
% N_cs_1 - Number of cyclic shifts used (sib2 nCS-AN)
% N_1_p_pucch - Resource index
% delta_pucch_shift - Controls the amount of multiplexing on PUCCH (sib2 deltaPUCCH-Shift)
% N_ant - Number of antennas
% Outputs: r - Demodulation reference signal for PUCCH format 1, 1A, and 1B
% Spec: 3GPP TS 36.211 section 5.5.2.2 v10.1.0
% Notes: Currently only handles normal CP and 1 antenna
% Rev History: Ben Wojtowicz 03/12/2016 Created
%
function [r] = lte_generate_dmrs_pucch_format1_1a_1b(N_subfr, N_id_cell, delta_ss, group_hopping_enabled, sequence_hopping_enabled, N_cs_1, N_1_p_pucch, delta_pucch_shift, N_ant)