Added multiple codeword architecture to MAC layer

master
Xavier Arteaga 7 years ago
parent 8c71c716c9
commit be0c6ebd20

@ -277,10 +277,10 @@ public:
uint32_t pid; uint32_t pid;
uint32_t tti; uint32_t tti;
uint32_t last_tti; uint32_t last_tti;
bool ndi; bool ndi[SRSLTE_MAX_CODEWORDS];
bool last_ndi; bool last_ndi[SRSLTE_MAX_CODEWORDS];
uint32_t n_bytes; uint32_t n_bytes[SRSLTE_MAX_CODEWORDS];
int rv; int rv[SRSLTE_MAX_CODEWORDS];
uint16_t rnti; uint16_t rnti;
bool is_from_rar; bool is_from_rar;
bool is_sps_release; bool is_sps_release;
@ -291,28 +291,28 @@ public:
typedef struct { typedef struct {
bool decode_enabled; bool decode_enabled;
int rv; int rv[SRSLTE_MAX_TB];
uint16_t rnti; uint16_t rnti;
bool generate_ack; bool generate_ack;
bool default_ack; bool default_ack;
// If non-null, called after tb_decoded_ok to determine if ack needs to be sent // If non-null, called after tb_decoded_ok to determine if ack needs to be sent
bool (*generate_ack_callback)(void*); bool (*generate_ack_callback)(void*);
void *generate_ack_callback_arg; void *generate_ack_callback_arg;
uint8_t *payload_ptr; uint8_t *payload_ptr[SRSLTE_MAX_TB];
srslte_softbuffer_rx_t *softbuffer; srslte_softbuffer_rx_t *softbuffers[SRSLTE_MAX_TB];
srslte_phy_grant_t phy_grant; srslte_phy_grant_t phy_grant;
} tb_action_dl_t; } tb_action_dl_t;
typedef struct { typedef struct {
bool tx_enabled; bool tx_enabled;
bool expect_ack; bool expect_ack;
uint32_t rv; uint32_t rv[SRSLTE_MAX_TB];
uint16_t rnti; uint16_t rnti;
uint32_t current_tx_nb; uint32_t current_tx_nb;
int32_t tti_offset; // relative offset between grant and UL tx/HARQ rx int32_t tti_offset; // relative offset between grant and UL tx/HARQ rx
srslte_softbuffer_tx_t *softbuffer; srslte_softbuffer_tx_t *softbuffers;
srslte_phy_grant_t phy_grant; srslte_phy_grant_t phy_grant;
uint8_t *payload_ptr; uint8_t *payload_ptr[SRSLTE_MAX_TB];
} tb_action_ul_t; } tb_action_ul_t;
/* Indicate reception of UL grant. /* Indicate reception of UL grant.
@ -329,7 +329,7 @@ public:
virtual void new_grant_dl(mac_grant_t grant, tb_action_dl_t *action) = 0; virtual void new_grant_dl(mac_grant_t grant, tb_action_dl_t *action) = 0;
/* Indicate successfull decoding of PDSCH TB. */ /* Indicate successfull decoding of PDSCH TB. */
virtual void tb_decoded(bool ack, srslte_rnti_type_t rnti_type, uint32_t harq_pid) = 0; virtual void tb_decoded(bool ack, uint32_t tb_idx, srslte_rnti_type_t rnti_type, uint32_t harq_pid) = 0;
/* Indicate successfull decoding of BCH TB through PBCH */ /* Indicate successfull decoding of BCH TB through PBCH */
virtual void bch_decoded_ok(uint8_t *payload, uint32_t len) = 0; virtual void bch_decoded_ok(uint8_t *payload, uint32_t len) = 0;

@ -84,20 +84,20 @@ public:
harq_pid = grant.pid%N; harq_pid = grant.pid%N;
} }
if (grant.rnti_type == SRSLTE_RNTI_TEMP && last_temporal_crnti != grant.rnti) { if (grant.rnti_type == SRSLTE_RNTI_TEMP && last_temporal_crnti != grant.rnti) {
grant.ndi = true; grant.ndi[0] = true;
Info("Set NDI=1 for Temp-RNTI DL grant\n"); Info("Set NDI=1 for Temp-RNTI DL grant\n");
last_temporal_crnti = grant.rnti; last_temporal_crnti = grant.rnti;
} }
if (grant.rnti_type == SRSLTE_RNTI_USER && proc[harq_pid].is_sps()) { if (grant.rnti_type == SRSLTE_RNTI_USER && proc[harq_pid].is_sps()) {
grant.ndi = true; grant.ndi[0] = true;
Info("Set NDI=1 for C-RNTI DL grant\n"); Info("Set NDI=1 for C-RNTI DL grant\n");
} }
proc[harq_pid].new_grant_dl(grant, action); proc[harq_pid].new_grant_dl(grant, action);
} else { } else {
/* This is for SPS scheduling */ /* This is for SPS scheduling */
uint32_t harq_pid = get_harq_sps_pid(grant.tti)%N; uint32_t harq_pid = get_harq_sps_pid(grant.tti)%N;
if (grant.ndi) { if (grant.ndi[0]) {
grant.ndi = false; grant.ndi[0] = false;
proc[harq_pid].new_grant_dl(grant, action); proc[harq_pid].new_grant_dl(grant, action);
} else { } else {
if (grant.is_sps_release) { if (grant.is_sps_release) {
@ -117,12 +117,12 @@ public:
} }
void tb_decoded(bool ack, srslte_rnti_type_t rnti_type, uint32_t harq_pid) void tb_decoded(bool ack, uint32_t tb_idx, srslte_rnti_type_t rnti_type, uint32_t harq_pid)
{ {
if (rnti_type == SRSLTE_RNTI_SI) { if (rnti_type == SRSLTE_RNTI_SI) {
proc[N].tb_decoded(ack); proc[N].tb_decoded(ack, 0);
} else { } else {
proc[harq_pid%N].tb_decoded(ack); proc[harq_pid%N].tb_decoded(ack, tb_idx);
} }
} }
@ -137,200 +137,239 @@ public:
void start_pcap(srslte::mac_pcap* pcap_) { pcap = pcap_; } void start_pcap(srslte::mac_pcap* pcap_) { pcap = pcap_; }
int get_current_tbs(uint32_t harq_pid) { return proc[harq_pid%N].get_current_tbs(); } int get_current_tbs(uint32_t harq_pid, uint32_t tb_idx) { return proc[harq_pid%N].get_current_tbs(tb_idx); }
void set_si_window_start(int si_window_start_) { si_window_start = si_window_start_; } void set_si_window_start(int si_window_start_) { si_window_start = si_window_start_; }
float get_average_retx() { return average_retx; } float get_average_retx() { return average_retx; }
private: private:
class dl_harq_process { class dl_harq_process {
public: public:
dl_harq_process() dl_harq_process() : subproc(SRSLTE_MAX_TB) {
{
is_initiated = false;
ack = false;
bzero(&cur_grant, sizeof(Tgrant));
} }
bool init(uint32_t pid_, dl_harq_entity *parent) bool init(uint32_t pid_, dl_harq_entity *parent) {
{ bool ret = true;
if (srslte_softbuffer_rx_init(&softbuffer, 110)) {
Error("Error initiating soft buffer\n"); for (uint32_t tb = 0; tb < SRSLTE_MAX_TB; tb++) {
return false; ret &= subproc[tb].init(pid_, parent, tb);
} else {
pid = pid_;
is_initiated = true;
harq_entity = parent;
log_h = harq_entity->log_h;
return true;
} }
return ret;
} }
void reset() void reset(void) {
{ for (uint32_t tb = 0; tb < SRSLTE_MAX_TB; tb++) {
ack = false; subproc[tb].reset();
payload_buffer_ptr = NULL;
bzero(&cur_grant, sizeof(Tgrant));
if (is_initiated) {
srslte_softbuffer_rx_reset(&softbuffer);
} }
} }
void new_grant_dl(Tgrant grant, Taction *action) void new_grant_dl(Tgrant grant, Taction *action) {
{ for (uint32_t tb = 0; tb < grant.phy_grant.dl.nof_tb; tb++) {
// Compute RV for BCCH when not specified in PDCCH format subproc[tb].new_grant_dl(grant, action);
if (pid == HARQ_BCCH_PID && grant.rv == -1) {
uint32_t k;
if ((grant.tti/10)%2 == 0 && grant.tti%10 == 5) { // This is SIB1, k is different
k = (grant.tti/20)%4;
grant.rv = ((uint32_t) ceilf((float)1.5*k))%4;
} else if (grant.rv == -1) {
k = (grant.tti-harq_entity->si_window_start)%4;
grant.rv = ((uint32_t) ceilf((float)1.5*k))%4;
}
}
calc_is_new_transmission(grant);
if (is_new_transmission) {
ack = false;
srslte_softbuffer_rx_reset_tbs(&softbuffer, cur_grant.n_bytes*8);
n_retx = 0;
} }
}
// Save grant
grant.last_ndi = cur_grant.ndi; int get_current_tbs(uint32_t tb_idx) { return subproc[tb_idx].get_current_tbs(); }
grant.last_tti = cur_grant.tti;
memcpy(&cur_grant, &grant, sizeof(Tgrant)); bool is_sps() { return false; }
// Fill action structure void tb_decoded(bool ack_, uint32_t tb_idx) {
bzero(action, sizeof(Taction)); subproc[tb_idx].tb_decoded(ack_);
action->default_ack = ack; }
action->generate_ack = true;
action->decode_enabled = false; private:
class dl_tb_process {
// If data has not yet been successfully decoded public:
if (ack == false) { dl_tb_process(void) {
is_initiated = false;
// Instruct the PHY To combine the received data and attempt to decode it ack = false;
payload_buffer_ptr = harq_entity->demux_unit->request_buffer(pid, cur_grant.n_bytes); bzero(&cur_grant, sizeof(Tgrant));
action->payload_ptr = payload_buffer_ptr;
if (!action->payload_ptr) {
action->decode_enabled = false;
Error("Can't get a buffer for TBS=%d\n", cur_grant.n_bytes);
return;
}
action->decode_enabled = true;
action->rv = cur_grant.rv;
action->rnti = cur_grant.rnti;
action->softbuffer = &softbuffer;
memcpy(&action->phy_grant, &cur_grant.phy_grant, sizeof(Tphygrant));
n_retx++;
} else {
Warning("DL PID %d: Received duplicate TB. Discarting and retransmitting ACK\n", pid);
} }
if (pid == HARQ_BCCH_PID || harq_entity->timers_db->get(TIME_ALIGNMENT)->is_expired()) { bool init(uint32_t pid_, dl_harq_entity *parent, uint32_t tb_idx) {
// Do not generate ACK tid = tb_idx;
Debug("Not generating ACK\n"); if (srslte_softbuffer_rx_init(&softbuffer, 110)) {
action->generate_ack = false; Error("Error initiating soft buffer\n");
} else { return false;
if (cur_grant.rnti_type == SRSLTE_RNTI_TEMP && ack == false) {
// Postpone ACK after contention resolution is resolved
action->generate_ack_callback = harq_entity->generate_ack_callback;
action->generate_ack_callback_arg = harq_entity->demux_unit;
Debug("ACK pending contention resolution\n");
} else { } else {
Debug("Generating ACK\n"); pid = pid_;
is_initiated = true;
harq_entity = parent;
log_h = harq_entity->log_h;
return true;
} }
} }
}
void reset(void) {
void tb_decoded(bool ack_) ack = false;
{ payload_buffer_ptr = NULL;
ack = ack_; bzero(&cur_grant, sizeof(Tgrant));
if (ack == true) { if (is_initiated) {
if (pid == HARQ_BCCH_PID) { srslte_softbuffer_rx_reset(&softbuffer);
if (harq_entity->pcap) { }
harq_entity->pcap->write_dl_sirnti(payload_buffer_ptr, cur_grant.n_bytes, ack, cur_grant.tti); }
void new_grant_dl(Tgrant grant, Taction *action) {
// Compute RV for BCCH when not specified in PDCCH format
if (pid == HARQ_BCCH_PID && grant.rv[tid] == -1) {
uint32_t k;
if ((grant.tti / 10) % 2 == 0 && grant.tti % 10 == 5) { // This is SIB1, k is different
k = (grant.tti / 20) % 4;
grant.rv[tid] = ((uint32_t) ceilf((float) 1.5 * k)) % 4;
} else if (grant.rv[tid] == -1) {
k = (grant.tti - harq_entity->si_window_start) % 4;
grant.rv[tid] = ((uint32_t) ceilf((float) 1.5 * k)) % 4;
} }
Debug("Delivering PDU=%d bytes to Dissassemble and Demux unit (BCCH)\n", cur_grant.n_bytes); }
harq_entity->demux_unit->push_pdu(pid, payload_buffer_ptr, cur_grant.n_bytes, cur_grant.tti); calc_is_new_transmission(grant);
} else { if (is_new_transmission) {
if (harq_entity->pcap) { ack = false;
harq_entity->pcap->write_dl_crnti(payload_buffer_ptr, cur_grant.n_bytes, cur_grant.rnti, ack, cur_grant.tti); srslte_softbuffer_rx_reset_tbs(&softbuffer, cur_grant.n_bytes[tid] * 8);
n_retx = 0;
}
// Save grant
grant.last_ndi[tid] = cur_grant.ndi[tid];
grant.last_tti = cur_grant.tti;
memcpy(&cur_grant, &grant, sizeof(Tgrant));
// Fill action structure
bzero(action, sizeof(Taction));
action->default_ack = ack;
action->generate_ack = true;
action->decode_enabled = false;
// If data has not yet been successfully decoded
if (!ack) {
// Instruct the PHY To combine the received data and attempt to decode it
payload_buffer_ptr = harq_entity->demux_unit->request_buffer(pid * SRSLTE_MAX_TB + tid,
cur_grant.n_bytes[tid]);
action->payload_ptr[tid] = payload_buffer_ptr;
if (!action->payload_ptr) {
action->decode_enabled = false;
Error("Can't get a buffer for TBS=%d\n", cur_grant.n_bytes[tid]);
return;
} }
if (ack) { action->decode_enabled = true;
if (cur_grant.rnti_type == SRSLTE_RNTI_TEMP) { action->rv[tid] = cur_grant.rv[tid];
Debug("Delivering PDU=%d bytes to Dissassemble and Demux unit (Temporal C-RNTI)\n", cur_grant.n_bytes); action->rnti = cur_grant.rnti;
harq_entity->demux_unit->push_pdu_temp_crnti(payload_buffer_ptr, cur_grant.n_bytes); action->softbuffers[tid] = &softbuffer;
} else { memcpy(&action->phy_grant, &cur_grant.phy_grant, sizeof(Tphygrant));
Debug("Delivering PDU=%d bytes to Dissassemble and Demux unit\n", cur_grant.n_bytes); n_retx++;
harq_entity->demux_unit->push_pdu(pid, payload_buffer_ptr, cur_grant.n_bytes, cur_grant.tti);
} else {
// Compute average number of retransmissions per packet Warning("DL PID %d: Received duplicate TB. Discarting and retransmitting ACK\n", pid);
harq_entity->average_retx = SRSLTE_VEC_CMA((float) n_retx, harq_entity->average_retx, harq_entity->nof_pkts++); }
}
if (pid == HARQ_BCCH_PID || harq_entity->timers_db->get(TIME_ALIGNMENT)->is_expired()) {
// Do not generate ACK
Debug("Not generating ACK\n");
action->generate_ack = false;
} else {
if (cur_grant.rnti_type == SRSLTE_RNTI_TEMP && !ack) {
// Postpone ACK after contention resolution is resolved
action->generate_ack_callback = harq_entity->generate_ack_callback;
action->generate_ack_callback_arg = harq_entity->demux_unit;
Debug("ACK pending contention resolution\n");
} else {
Debug("Generating ACK\n");
} }
} }
} else {
harq_entity->demux_unit->deallocate(payload_buffer_ptr);
}
Info("DL %d: %s tbs=%d, rv=%d, ack=%s, ndi=%d (%d), tti=%d (%d)\n",
pid, is_new_transmission?"newTX":"reTX ",
cur_grant.n_bytes, cur_grant.rv, ack?"OK":"KO",
cur_grant.ndi, cur_grant.last_ndi, cur_grant.tti, cur_grant.last_tti);
if (ack && pid == HARQ_BCCH_PID) {
reset();
} }
}
bool is_sps() { return false; }
int get_current_tbs() { return cur_grant.n_bytes*8; } void tb_decoded(bool ack_) {
ack = ack_;
private: if (ack) {
bool calc_is_new_transmission(Tgrant grant) if (pid == HARQ_BCCH_PID) {
{ if (harq_entity->pcap) {
bool is_new_tb = true; harq_entity->pcap->write_dl_sirnti(payload_buffer_ptr, cur_grant.n_bytes[tid], ack, cur_grant.tti);
if ((srslte_tti_interval(grant.tti, cur_grant.tti) <= 8 && (grant.n_bytes == cur_grant.n_bytes)) || }
pid == HARQ_BCCH_PID) Debug("Delivering PDU=%d bytes to Dissassemble and Demux unit (BCCH)\n", cur_grant.n_bytes[tid]);
{ harq_entity->demux_unit->push_pdu(pid * SRSLTE_MAX_TB + tid, payload_buffer_ptr, cur_grant.n_bytes[tid],
is_new_tb = false; cur_grant.tti);
} else {
if (harq_entity->pcap) {
harq_entity->pcap->write_dl_crnti(payload_buffer_ptr, cur_grant.n_bytes[tid], cur_grant.rnti, ack,
cur_grant.tti);
}
if (ack) {
if (cur_grant.rnti_type == SRSLTE_RNTI_TEMP) {
Debug("Delivering PDU=%d bytes to Dissassemble and Demux unit (Temporal C-RNTI)\n",
cur_grant.n_bytes[tid]);
harq_entity->demux_unit->push_pdu_temp_crnti(payload_buffer_ptr, cur_grant.n_bytes[tid]);
} else {
Debug("Delivering PDU=%d bytes to Dissassemble and Demux unit\n", cur_grant.n_bytes[tid]);
harq_entity->demux_unit->push_pdu(pid * SRSLTE_MAX_TB + tid, payload_buffer_ptr, cur_grant.n_bytes[tid],
cur_grant.tti);
// Compute average number of retransmissions per packet
harq_entity->average_retx = SRSLTE_VEC_CMA((float) n_retx, harq_entity->average_retx,
harq_entity->nof_pkts++);
}
}
}
} else {
harq_entity->demux_unit->deallocate(payload_buffer_ptr);
}
Info("DL %d (TB %d): %s tbs=%d, rv=%d, ack=%s, ndi=%d (%d), tti=%d (%d)\n",
pid, tid, is_new_transmission ? "newTX" : "reTX ",
cur_grant.n_bytes[tid], cur_grant.rv[tid], ack ? "OK" : "KO",
cur_grant.ndi[tid], cur_grant.last_ndi, cur_grant.tti, cur_grant.last_tti);
if (ack && pid == HARQ_BCCH_PID) {
reset();
}
} }
if ((grant.ndi != cur_grant.ndi && !is_new_tb) || // NDI toggled for same TB int get_current_tbs(void) { return cur_grant.n_bytes[tid] * 8; }
is_new_tb || // is new TB
(pid == HARQ_BCCH_PID && grant.rv == 0)) // Broadcast PID and 1st TX (RV=0) private:
{ bool calc_is_new_transmission(Tgrant grant) {
is_new_transmission = true; bool is_new_tb = true;
Debug("Set HARQ for new transmission\n"); if ((srslte_tti_interval(grant.tti, cur_grant.tti) <= 8 && (grant.n_bytes[tid] == cur_grant.n_bytes[tid])) ||
} else { pid == HARQ_BCCH_PID) {
is_new_transmission = false; is_new_tb = false;
Debug("Set HARQ for retransmission\n"); }
if ((grant.ndi[tid] != cur_grant.ndi[tid] && !is_new_tb) || // NDI toggled for same TB
is_new_tb || // is new TB
(pid == HARQ_BCCH_PID && grant.rv[tid] == 0)) // Broadcast PID and 1st TX (RV=0)
{
is_new_transmission = true;
Debug("Set HARQ for new transmission\n");
} else {
is_new_transmission = false;
Debug("Set HARQ for retransmission\n");
}
return is_new_transmission;
} }
return is_new_transmission; bool is_initiated;
} dl_harq_entity *harq_entity;
srslte::log *log_h;
bool is_initiated; bool is_new_transmission;
dl_harq_entity *harq_entity;
srslte::log *log_h; uint32_t pid; /* HARQ Proccess ID */
uint32_t tid; /* Transport block ID */
bool is_new_transmission; uint8_t *payload_buffer_ptr;
bool ack;
uint32_t pid;
uint8_t *payload_buffer_ptr; uint32_t n_retx;
bool ack;
Tgrant cur_grant;
uint32_t n_retx; srslte_softbuffer_rx_t softbuffer;
};
Tgrant cur_grant;
srslte_softbuffer_rx_t softbuffer; /* Transport blocks */
std::vector<dl_tb_process> subproc;
}; };
// Private members of dl_harq_entity // Private members of dl_harq_entity
static bool generate_ack_callback(void *arg) static bool generate_ack_callback(void *arg)

@ -65,7 +65,7 @@ public:
void new_grant_ul_ack(mac_grant_t grant, bool ack, tb_action_ul_t *action); void new_grant_ul_ack(mac_grant_t grant, bool ack, tb_action_ul_t *action);
void harq_recv(uint32_t tti, bool ack, tb_action_ul_t *action); void harq_recv(uint32_t tti, bool ack, tb_action_ul_t *action);
void new_grant_dl(mac_grant_t grant, tb_action_dl_t *action); void new_grant_dl(mac_grant_t grant, tb_action_dl_t *action);
void tb_decoded(bool ack, srslte_rnti_type_t rnti_type, uint32_t harq_pid); void tb_decoded(bool ack, uint32_t tb_idx, srslte_rnti_type_t rnti_type, uint32_t harq_pid);
void bch_decoded_ok(uint8_t *payload, uint32_t len); void bch_decoded_ok(uint8_t *payload, uint32_t len);
void pch_decoded_ok(uint32_t len); void pch_decoded_ok(uint32_t len);
void tti_clock(uint32_t tti); void tti_clock(uint32_t tti);

@ -113,12 +113,12 @@ public:
grant.rnti_type == SRSLTE_RNTI_RAR) grant.rnti_type == SRSLTE_RNTI_RAR)
{ {
if (grant.rnti_type == SRSLTE_RNTI_USER && proc[pidof(grant.tti)].is_sps()) { if (grant.rnti_type == SRSLTE_RNTI_USER && proc[pidof(grant.tti)].is_sps()) {
grant.ndi = true; grant.ndi[0] = true;
} }
run_tti(grant.tti, &grant, action); run_tti(grant.tti, &grant, action);
} else if (grant.rnti_type == SRSLTE_RNTI_SPS) { } else if (grant.rnti_type == SRSLTE_RNTI_SPS) {
if (grant.ndi) { if (grant.ndi[0]) {
grant.ndi = proc[pidof(grant.tti)].get_ndi(); grant.ndi[0] = proc[pidof(grant.tti)].get_ndi();
run_tti(grant.tti, &grant, action); run_tti(grant.tti, &grant, action);
} else { } else {
Info("Not implemented\n"); Info("Not implemented\n");
@ -208,7 +208,7 @@ private:
// Receive and route HARQ feedbacks // Receive and route HARQ feedbacks
if (grant) { if (grant) {
if ((!(grant->rnti_type == SRSLTE_RNTI_TEMP) && grant->ndi != get_ndi()) || if ((!(grant->rnti_type == SRSLTE_RNTI_TEMP) && grant->ndi[0] != get_ndi()) ||
(grant->rnti_type == SRSLTE_RNTI_USER && !has_grant()) || (grant->rnti_type == SRSLTE_RNTI_USER && !has_grant()) ||
grant->is_from_rar) grant->is_from_rar)
{ {
@ -216,8 +216,8 @@ private:
// Uplink grant in a RAR // Uplink grant in a RAR
if (grant->is_from_rar) { if (grant->is_from_rar) {
Debug("Getting Msg3 buffer payload, grant size=%d bytes\n", grant->n_bytes); Debug("Getting Msg3 buffer payload, grant size=%d bytes\n", grant->n_bytes[0]);
pdu_ptr = harq_entity->mux_unit->msg3_get(payload_buffer, grant->n_bytes); pdu_ptr = harq_entity->mux_unit->msg3_get(payload_buffer, grant->n_bytes[0]);
if (pdu_ptr) { if (pdu_ptr) {
generate_new_tx(tti_tx, true, grant, action); generate_new_tx(tti_tx, true, grant, action);
} else { } else {
@ -227,7 +227,7 @@ private:
// Normal UL grant // Normal UL grant
} else { } else {
// Request a MAC PDU from the Multiplexing & Assemble Unit // Request a MAC PDU from the Multiplexing & Assemble Unit
pdu_ptr = harq_entity->mux_unit->pdu_get(payload_buffer, grant->n_bytes, tti_tx, pid); pdu_ptr = harq_entity->mux_unit->pdu_get(payload_buffer, grant->n_bytes[0], tti_tx, pid);
if (pdu_ptr) { if (pdu_ptr) {
generate_new_tx(tti_tx, false, grant, action); generate_new_tx(tti_tx, false, grant, action);
} else { } else {
@ -258,7 +258,7 @@ private:
if (grant->is_from_rar) { if (grant->is_from_rar) {
grant->rnti = harq_entity->rntis->temp_rnti; grant->rnti = harq_entity->rntis->temp_rnti;
} }
harq_entity->pcap->write_ul_crnti(pdu_ptr, grant->n_bytes, grant->rnti, get_nof_retx(), tti_tx); harq_entity->pcap->write_ul_crnti(pdu_ptr, grant->n_bytes[0], grant->rnti, get_nof_retx(), tti_tx);
} }
} }
@ -285,7 +285,7 @@ private:
bool is_sps() { return false; } bool is_sps() { return false; }
uint32_t last_tx_tti() { return tti_last_tx; } uint32_t last_tx_tti() { return tti_last_tx; }
uint32_t get_nof_retx() { return current_tx_nb; } uint32_t get_nof_retx() { return current_tx_nb; }
int get_current_tbs() { return cur_grant.n_bytes*8; } int get_current_tbs() { return cur_grant.n_bytes[0]*8; }
private: private:
Tgrant cur_grant; Tgrant cur_grant;
@ -321,7 +321,7 @@ private:
if (grant) { if (grant) {
// HARQ entity requests an adaptive transmission // HARQ entity requests an adaptive transmission
if (grant->rv) { if (grant->rv) {
current_irv = irv_of_rv[grant->rv%4]; current_irv = irv_of_rv[grant->rv[0]%4];
} }
memcpy(&cur_grant, grant, sizeof(Tgrant)); memcpy(&cur_grant, grant, sizeof(Tgrant));
harq_feedback = false; harq_feedback = false;
@ -370,10 +370,10 @@ private:
current_tx_nb++; current_tx_nb++;
action->expect_ack = true; action->expect_ack = true;
action->rnti = is_msg3?harq_entity->rntis->temp_rnti:cur_grant.rnti; action->rnti = is_msg3?harq_entity->rntis->temp_rnti:cur_grant.rnti;
action->rv = cur_grant.rv>0?cur_grant.rv:get_rv(); action->rv[0] = cur_grant.rv[0]>0?cur_grant.rv[0]:get_rv();
action->softbuffer = &softbuffer; action->softbuffers = &softbuffer;
action->tx_enabled = true; action->tx_enabled = true;
action->payload_ptr = pdu_ptr; action->payload_ptr[0] = pdu_ptr;
memcpy(&action->phy_grant, &cur_grant.phy_grant, sizeof(Tphygrant)); memcpy(&action->phy_grant, &cur_grant.phy_grant, sizeof(Tphygrant));
current_irv = (current_irv+1)%4; current_irv = (current_irv+1)%4;

@ -78,18 +78,20 @@ private:
bool decode_pdcch_dl(mac_interface_phy::mac_grant_t *grant); bool decode_pdcch_dl(mac_interface_phy::mac_grant_t *grant);
bool decode_phich(bool *ack); bool decode_phich(bool *ack);
bool decode_pdsch(srslte_ra_dl_grant_t *grant, int decode_pdsch(srslte_ra_dl_grant_t *grant,
uint8_t *payload, srslte_softbuffer_rx_t *softbuffer, uint8_t *payload, srslte_softbuffer_rx_t *softbuffer,
int rv, int rv,
uint16_t rnti, uint16_t rnti,
uint32_t pid); uint32_t pid,
bool acks[SRSLTE_MAX_CODEWORDS]);
bool decode_pdsch_multi(srslte_ra_dl_grant_t *grant, int decode_pdsch_multi(srslte_ra_dl_grant_t *grant,
uint8_t *payload[SRSLTE_MAX_CODEWORDS], uint8_t *payload[SRSLTE_MAX_CODEWORDS],
srslte_softbuffer_rx_t softbuffers[SRSLTE_MAX_CODEWORDS], srslte_softbuffer_rx_t *softbuffers[SRSLTE_MAX_CODEWORDS],
int rv[SRSLTE_MAX_CODEWORDS], int rv[SRSLTE_MAX_CODEWORDS],
uint16_t rnti, uint16_t rnti,
uint32_t pid); uint32_t pid,
bool acks[SRSLTE_MAX_CODEWORDS]);
/* ... for UL */ /* ... for UL */
void encode_pusch(srslte_ra_ul_grant_t *grant, uint8_t *payload, uint32_t current_tx_nb, srslte_softbuffer_tx_t *softbuffer, void encode_pusch(srslte_ra_ul_grant_t *grant, uint8_t *payload, uint32_t current_tx_nb, srslte_softbuffer_tx_t *softbuffer,
@ -100,7 +102,7 @@ private:
void set_uci_sr(); void set_uci_sr();
void set_uci_periodic_cqi(); void set_uci_periodic_cqi();
void set_uci_aperiodic_cqi(); void set_uci_aperiodic_cqi();
void set_uci_ack(bool ack); void set_uci_ack(bool ack[SRSLTE_MAX_CODEWORDS], uint32_t nof_tb);
bool srs_is_ready_to_send(); bool srs_is_ready_to_send();
float set_power(float tx_power); float set_power(float tx_power);
void setup_tx_gain(); void setup_tx_gain();

@ -44,7 +44,7 @@ namespace srsue {
mac::mac() : ttisync(10240), mac::mac() : ttisync(10240),
timers_db((uint32_t) NOF_MAC_TIMERS), timers_db((uint32_t) NOF_MAC_TIMERS),
mux_unit(MAC_NOF_HARQ_PROC), mux_unit(MAC_NOF_HARQ_PROC),
demux_unit(MAC_NOF_HARQ_PROC), demux_unit(SRSLTE_MAX_TB*MAC_NOF_HARQ_PROC),
pdu_process_thread(&demux_unit) pdu_process_thread(&demux_unit)
{ {
started = false; started = false;
@ -255,17 +255,17 @@ void mac::pch_decoded_ok(uint32_t len)
} }
} }
void mac::tb_decoded(bool ack, srslte_rnti_type_t rnti_type, uint32_t harq_pid) void mac::tb_decoded(bool ack, uint32_t tb_idx, srslte_rnti_type_t rnti_type, uint32_t harq_pid)
{ {
if (rnti_type == SRSLTE_RNTI_RAR) { if (rnti_type == SRSLTE_RNTI_RAR) {
if (ack) { if (ack) {
ra_procedure.tb_decoded_ok(); ra_procedure.tb_decoded_ok();
} }
} else { } else {
dl_harq.tb_decoded(ack, rnti_type, harq_pid); dl_harq.tb_decoded(ack, tb_idx, rnti_type, harq_pid);
if (ack) { if (ack) {
pdu_process_thread.notify(); pdu_process_thread.notify();
metrics.rx_brate += dl_harq.get_current_tbs(harq_pid); metrics.rx_brate += dl_harq.get_current_tbs(harq_pid, tb_idx);
} else { } else {
metrics.rx_errors++; metrics.rx_errors++;
} }
@ -282,12 +282,9 @@ void mac::new_grant_dl(mac_interface_phy::mac_grant_t grant, mac_interface_phy::
memcpy(&action->phy_grant, &grant.phy_grant, sizeof(srslte_phy_grant_t)); memcpy(&action->phy_grant, &grant.phy_grant, sizeof(srslte_phy_grant_t));
action->generate_ack = false; action->generate_ack = false;
action->decode_enabled = true; action->decode_enabled = true;
srslte_softbuffer_rx_reset_cb(&pch_softbuffer, 1);
action->payload_ptr = pch_payload_buffer;
action->softbuffer = &pch_softbuffer;
action->rnti = grant.rnti; action->rnti = grant.rnti;
action->rv = grant.rv; action->rv[0] = grant.rv[0];
if (grant.n_bytes > pch_payload_buffer_sz) { if (grant.n_bytes[0] > pch_payload_buffer_sz) {
Error("Received grant for PCH (%d bytes) exceeds buffer (%d bytes)\n", grant.n_bytes, pch_payload_buffer_sz); Error("Received grant for PCH (%d bytes) exceeds buffer (%d bytes)\n", grant.n_bytes, pch_payload_buffer_sz);
action->decode_enabled = false; action->decode_enabled = false;
} }

@ -269,19 +269,19 @@ void ra_proc::step_pdcch_setup() {
void ra_proc::new_grant_dl(mac_interface_phy::mac_grant_t grant, mac_interface_phy::tb_action_dl_t* action) void ra_proc::new_grant_dl(mac_interface_phy::mac_grant_t grant, mac_interface_phy::tb_action_dl_t* action)
{ {
if (grant.n_bytes < MAX_RAR_PDU_LEN) { if (grant.n_bytes[0] < MAX_RAR_PDU_LEN) {
rDebug("DL grant found RA-RNTI=%d\n", ra_rnti); rDebug("DL grant found RA-RNTI=%d\n", ra_rnti);
action->decode_enabled = true; action->decode_enabled = true;
action->default_ack = false; action->default_ack = false;
action->generate_ack = false; action->generate_ack = false;
action->payload_ptr = rar_pdu_buffer; action->payload_ptr[0] = rar_pdu_buffer;
action->rnti = grant.rnti; action->rnti = grant.rnti;
memcpy(&action->phy_grant, &grant.phy_grant, sizeof(srslte_phy_grant_t)); memcpy(&action->phy_grant, &grant.phy_grant, sizeof(srslte_phy_grant_t));
action->rv = grant.rv; action->rv[0] = grant.rv[0];
action->softbuffer = &softbuffer_rar; action->softbuffers[0] = &softbuffer_rar;
rar_grant_nbytes = grant.n_bytes; rar_grant_nbytes = grant.n_bytes[0];
rar_grant_tti = grant.tti; rar_grant_tti = grant.tti;
if (action->rv == 0) { if (action->rv[0] == 0) {
srslte_softbuffer_rx_reset(&softbuffer_rar); srslte_softbuffer_rx_reset(&softbuffer_rar);
} }
} else { } else {

@ -178,8 +178,8 @@ void phch_worker::work_imp()
reset_uci(); reset_uci();
bool dl_grant_available = false; bool dl_grant_available = false;
bool ul_grant_available = false; bool ul_grant_available = false;
bool dl_ack = false; bool dl_ack[SRSLTE_MAX_CODEWORDS] = {false};
mac_interface_phy::mac_grant_t dl_mac_grant; mac_interface_phy::mac_grant_t dl_mac_grant;
mac_interface_phy::tb_action_dl_t dl_action; mac_interface_phy::tb_action_dl_t dl_action;
@ -200,22 +200,28 @@ void phch_worker::work_imp()
if(dl_grant_available) { if(dl_grant_available) {
/* Send grant to MAC and get action for this TB */ /* Send grant to MAC and get action for this TB */
phy->mac->new_grant_dl(dl_mac_grant, &dl_action); phy->mac->new_grant_dl(dl_mac_grant, &dl_action);
/* Set DL ACKs to default */
for (uint32_t tb = 0; tb < SRSLTE_MAX_CODEWORDS; tb++) {
dl_ack[tb] = dl_action.default_ack;
}
/* Decode PDSCH if instructed to do so */ /* Decode PDSCH if instructed to do so */
dl_ack = dl_action.default_ack;
if (dl_action.decode_enabled) { if (dl_action.decode_enabled) {
dl_ack = decode_pdsch(&dl_action.phy_grant.dl, dl_action.payload_ptr, decode_pdsch_multi(&dl_action.phy_grant.dl, dl_action.payload_ptr,
dl_action.softbuffer, dl_action.rv, dl_action.rnti, dl_action.softbuffers, dl_action.rv, dl_action.rnti,
dl_mac_grant.pid); dl_mac_grant.pid, dl_ack);
} }
if (dl_action.generate_ack_callback && dl_action.decode_enabled) { if (dl_action.generate_ack_callback && dl_action.decode_enabled) {
phy->mac->tb_decoded(dl_ack, dl_mac_grant.rnti_type, dl_mac_grant.pid); for (uint32_t tb = 0; tb < SRSLTE_MAX_CODEWORDS; tb++) {
dl_ack = dl_action.generate_ack_callback(dl_action.generate_ack_callback_arg); phy->mac->tb_decoded(dl_ack[tb], tb, dl_mac_grant.rnti_type, dl_mac_grant.pid);
Debug("Calling generate ACK callback returned=%d\n", dl_ack); dl_ack[tb] = dl_action.generate_ack_callback(dl_action.generate_ack_callback_arg);
Debug("Calling generate ACK callback for TB %d returned=%d\n", tb, dl_ack);
}
} }
Debug("dl_ack=%d, generate_ack=%d\n", dl_ack, dl_action.generate_ack); Debug("dl_ack={%d, %d}, generate_ack=%d\n", dl_ack[0], dl_ack[1], dl_action.generate_ack);
if (dl_action.generate_ack) { if (dl_action.generate_ack) {
set_uci_ack(dl_ack); set_uci_ack(dl_ack, dl_mac_grant.phy_grant.dl.nof_tb);
} }
} }
} }
@ -258,8 +264,8 @@ void phch_worker::work_imp()
/* Transmit PUSCH, PUCCH or SRS */ /* Transmit PUSCH, PUCCH or SRS */
bool signal_ready = false; bool signal_ready = false;
if (ul_action.tx_enabled) { if (ul_action.tx_enabled) {
encode_pusch(&ul_action.phy_grant.ul, ul_action.payload_ptr, ul_action.current_tx_nb, encode_pusch(&ul_action.phy_grant.ul, ul_action.payload_ptr[0], ul_action.current_tx_nb,
ul_action.softbuffer, ul_action.rv, ul_action.rnti, ul_mac_grant.is_from_rar); &ul_action.softbuffers[0], ul_action.rv[0], ul_action.rnti, ul_mac_grant.is_from_rar);
signal_ready = true; signal_ready = true;
if (ul_action.expect_ack) { if (ul_action.expect_ack) {
phy->set_pending_ack(tti + 8, ue_ul.pusch_cfg.grant.n_prb_tilde[0], ul_action.phy_grant.ul.ncs_dmrs); phy->set_pending_ack(tti + 8, ue_ul.pusch_cfg.grant.n_prb_tilde[0], ul_action.phy_grant.ul.ncs_dmrs);
@ -279,9 +285,11 @@ void phch_worker::work_imp()
if (dl_action.decode_enabled && !dl_action.generate_ack_callback) { if (dl_action.decode_enabled && !dl_action.generate_ack_callback) {
if (dl_mac_grant.rnti_type == SRSLTE_RNTI_PCH) { if (dl_mac_grant.rnti_type == SRSLTE_RNTI_PCH) {
phy->mac->pch_decoded_ok(dl_mac_grant.n_bytes); phy->mac->pch_decoded_ok(dl_mac_grant.n_bytes[0]);
} else { } else {
phy->mac->tb_decoded(dl_ack, dl_mac_grant.rnti_type, dl_mac_grant.pid); for (uint32_t tb = 0; tb < dl_mac_grant.phy_grant.dl.nof_tb; tb++) {
phy->mac->tb_decoded(dl_ack[tb], tb, dl_mac_grant.rnti_type, dl_mac_grant.pid);
}
} }
} }
@ -380,13 +388,16 @@ bool phch_worker::decode_pdcch_dl(srsue::mac_interface_phy::mac_grant_t* grant)
} }
/* Fill MAC grant structure */ /* Fill MAC grant structure */
grant->ndi = dci_unpacked.ndi; grant->ndi[0] = dci_unpacked.ndi;
grant->ndi[1] = dci_unpacked.ndi_1;
grant->pid = dci_unpacked.harq_process; grant->pid = dci_unpacked.harq_process;
grant->n_bytes = grant->phy_grant.dl.mcs[0].tbs/8; grant->n_bytes[0] = grant->phy_grant.dl.mcs[0].tbs / (uint32_t) 8;
grant->tti = tti; grant->n_bytes[1] = grant->phy_grant.dl.mcs[1].tbs / (uint32_t) 8;
grant->rv = dci_unpacked.rv_idx; grant->tti = tti;
grant->rnti = dl_rnti; grant->rv[0] = dci_unpacked.rv_idx;
grant->rnti_type = type; grant->rv[1] = dci_unpacked.rv_idx_1;
grant->rnti = dl_rnti;
grant->rnti_type = type;
grant->last_tti = 0; grant->last_tti = 0;
last_dl_pdcch_ncce = srslte_ue_dl_get_ncce(&ue_dl); last_dl_pdcch_ncce = srslte_ue_dl_get_ncce(&ue_dl);
@ -405,23 +416,27 @@ bool phch_worker::decode_pdcch_dl(srsue::mac_interface_phy::mac_grant_t* grant)
} }
} }
bool phch_worker::decode_pdsch(srslte_ra_dl_grant_t *grant, uint8_t *payload, int phch_worker::decode_pdsch(srslte_ra_dl_grant_t *grant, uint8_t *payload,
srslte_softbuffer_rx_t *softbuffer, int rv, srslte_softbuffer_rx_t *softbuffer, int rv,
uint16_t rnti, uint32_t harq_pid) { uint16_t rnti, uint32_t harq_pid, bool acks[SRSLTE_MAX_CODEWORDS]) {
int _rv [SRSLTE_MAX_CODEWORDS] = {1}; int _rv [SRSLTE_MAX_TB] = {1};
srslte_softbuffer_rx_t *softbuffers[SRSLTE_MAX_TB] = {NULL};
_rv[0] = rv; _rv[0] = rv;
softbuffers[0] = softbuffer;
return decode_pdsch_multi(grant, &payload, softbuffer, _rv, rnti, harq_pid); return decode_pdsch_multi(grant, &payload, softbuffers, _rv, rnti, harq_pid, acks);
} }
bool phch_worker::decode_pdsch_multi(srslte_ra_dl_grant_t *grant, uint8_t *payload[SRSLTE_MAX_CODEWORDS], int phch_worker::decode_pdsch_multi(srslte_ra_dl_grant_t *grant, uint8_t *payload[SRSLTE_MAX_CODEWORDS],
srslte_softbuffer_rx_t softbuffers[SRSLTE_MAX_CODEWORDS], srslte_softbuffer_rx_t *softbuffers[SRSLTE_MAX_CODEWORDS],
int rv[SRSLTE_MAX_CODEWORDS], int rv[SRSLTE_MAX_CODEWORDS],
uint16_t rnti, uint32_t harq_pid) { uint16_t rnti, uint32_t harq_pid, bool acks[SRSLTE_MAX_CODEWORDS]) {
char timestr[64]; char timestr[64];
bool valid_config = true; bool valid_config = true;
timestr[0]='\0'; timestr[0]='\0';
srslte_mimo_type_t mimo_type = SRSLTE_MIMO_TYPE_SINGLE_ANTENNA; srslte_mimo_type_t mimo_type = SRSLTE_MIMO_TYPE_SINGLE_ANTENNA;
int ret = SRSLTE_SUCCESS;
for (uint32_t tb = 0; tb < grant->nof_tb; tb++) { for (uint32_t tb = 0; tb < grant->nof_tb; tb++) {
if (rv[tb] < 0 || rv[tb] > 3) { if (rv[tb] < 0 || rv[tb] > 3) {
@ -497,38 +512,39 @@ bool phch_worker::decode_pdsch_multi(srslte_ra_dl_grant_t *grant, uint8_t *paylo
struct timeval t[3]; struct timeval t[3];
gettimeofday(&t[1], NULL); gettimeofday(&t[1], NULL);
#endif #endif
ret = srslte_pdsch_decode_multi(&ue_dl.pdsch, &ue_dl.pdsch_cfg, softbuffers, ue_dl.sf_symbols_m,
bool ack = srslte_pdsch_decode_multi(&ue_dl.pdsch, &ue_dl.pdsch_cfg, softbuffers, ue_dl.sf_symbols_m, ue_dl.ce_m, noise_estimate, rnti, payload, acks);
ue_dl.ce_m, noise_estimate, rnti, payload) == 0; if (ret) {
Error("Decoding PDSCH");
}
#ifdef LOG_EXECTIME #ifdef LOG_EXECTIME
gettimeofday(&t[2], NULL); gettimeofday(&t[2], NULL);
get_time_interval(t); get_time_interval(t);
snprintf(timestr, 64, ", dec_time=%4d us", (int) t[0].tv_usec); snprintf(timestr, 64, ", dec_time=%4d us", (int) t[0].tv_usec);
#endif #endif
Info("PDSCH: l_crb=%2d, harq=%d, tbs=%d, mcs=%d, rv=%d, crc=%s, snr=%.1f dB, n_iter=%d%s\n", Info("PDSCH: l_crb=%2d, harq=%d, nof_tb=%d, tbs={%d, %d}, mcs={%d, %d}, rv={%d, %d}, crc={%s, %s}, snr=%.1f dB, n_iter=%d%s\n",
grant->nof_prb, harq_pid, grant->nof_prb, harq_pid,
grant->mcs[0].tbs/8, grant->mcs[0].idx, rv, grant->nof_tb, grant->mcs[0].tbs / 8, grant->mcs[1].tbs / 8, grant->mcs[0].idx, grant->mcs[1].idx,
ack?"OK":"KO", rv[0], rv[1], acks[0] ? "OK" : "KO", acks[1] ? "OK" : "KO",
10*log10(srslte_chest_dl_get_snr(&ue_dl.chest)), 10 * log10(srslte_chest_dl_get_snr(&ue_dl.chest)),
srslte_pdsch_last_noi(&ue_dl.pdsch), srslte_pdsch_last_noi(&ue_dl.pdsch),
timestr); timestr);
//printf("tti=%d, cfo=%f\n", tti, cfo*15000); //printf("tti=%d, cfo=%f\n", tti, cfo*15000);
//srslte_vec_save_file("pdsch", signal_buffer, sizeof(cf_t)*SRSLTE_SF_LEN_PRB(cell.nof_prb)); //srslte_vec_save_file("pdsch", signal_buffer, sizeof(cf_t)*SRSLTE_SF_LEN_PRB(cell.nof_prb));
// Store metrics // Store metrics
dl_metrics.mcs = grant->mcs[0].idx; dl_metrics.mcs = grant->mcs[0].idx;
return ack;
} else { } else {
Warning("Received grant for TBS=0\n"); Warning("Received grant for TBS=0\n");
} }
} else { } else {
Error("Error configuring DL grant\n"); Error("Error configuring DL grant\n");
ret = SRSLTE_ERROR;
} }
} }
return true; return ret;
} }
bool phch_worker::decode_phich(bool *ack) bool phch_worker::decode_phich(bool *ack)
@ -625,12 +641,12 @@ bool phch_worker::decode_pdcch_ul(mac_interface_phy::mac_grant_t* grant)
} }
if (ret) { if (ret) {
grant->ndi = dci_unpacked.ndi; grant->ndi[0] = dci_unpacked.ndi;
grant->pid = 0; // This is computed by MAC from TTI grant->pid = 0; // This is computed by MAC from TTI
grant->n_bytes = grant->phy_grant.ul.mcs.tbs/8; grant->n_bytes[0] = grant->phy_grant.ul.mcs.tbs / (uint32_t) 8;
grant->tti = tti; grant->tti = tti;
grant->rnti = ul_rnti; grant->rnti = ul_rnti;
grant->rv = dci_unpacked.rv_idx; grant->rv[0] = dci_unpacked.rv_idx;
if (SRSLTE_VERBOSE_ISINFO()) { if (SRSLTE_VERBOSE_ISINFO()) {
srslte_ra_pusch_fprint(stdout, &dci_unpacked, cell.nof_prb); srslte_ra_pusch_fprint(stdout, &dci_unpacked, cell.nof_prb);
} }
@ -646,11 +662,22 @@ void phch_worker::reset_uci()
bzero(&uci_data, sizeof(srslte_uci_data_t)); bzero(&uci_data, sizeof(srslte_uci_data_t));
} }
void phch_worker::set_uci_ack(bool ack) void phch_worker::set_uci_ack(bool ack[SRSLTE_MAX_CODEWORDS], uint32_t nof_tb) {
{ if (nof_tb > 0) {
uci_data.uci_ack = ack?1:0; uci_data.uci_ack = (uint8_t) ((ack[0]) ? 1 : 0);
uci_data.uci_ack_len = 1; }
}
if (nof_tb > 1) {
uci_data.uci_ack_2 = (uint8_t) ((ack[1]) ? 1 : 0);
}
if (nof_tb > 2) {
Error("Number of transport blocks is not supported");
}
uci_data.uci_ack_len = nof_tb;
}
void phch_worker::set_uci_sr() void phch_worker::set_uci_sr()
{ {

@ -158,8 +158,8 @@ int rar_unpack(uint8_t *buffer, rar_msg_t *msg)
srsue::phy my_phy; srsue::phy my_phy;
bool bch_decoded = false; bool bch_decoded = false;
uint8_t payload[10240]; uint8_t payload[SRSLTE_MAX_TB][10240];
uint8_t payload_bits[10240]; uint8_t payload_bits[SRSLTE_MAX_TB][10240];
const uint8_t conn_request_msg[] = {0x20, 0x06, 0x1F, 0x5C, 0x2C, 0x04, 0xB2, 0xAC, 0xF6, 0x00, 0x00, 0x00}; const uint8_t conn_request_msg[] = {0x20, 0x06, 0x1F, 0x5C, 0x2C, 0x04, 0xB2, 0xAC, 0xF6, 0x00, 0x00, 0x00};
enum mac_state {RA, RAR, CONNREQUEST, CONNSETUP} state = RA; enum mac_state {RA, RAR, CONNREQUEST, CONNSETUP} state = RA;
@ -168,7 +168,7 @@ uint32_t preamble_idx = 0;
rar_msg_t rar_msg; rar_msg_t rar_msg;
uint32_t nof_rtx_connsetup = 0; uint32_t nof_rtx_connsetup = 0;
uint32_t rv_value[4] = {0, 2, 3, 1}; uint32_t rv_value[4] = {0, 2, 3, 1};
void config_phy() { void config_phy() {
srsue::phy_interface_rrc::phy_cfg_t config; srsue::phy_interface_rrc::phy_cfg_t config;
@ -194,8 +194,8 @@ void config_phy() {
my_phy.configure_prach_params(); my_phy.configure_prach_params();
} }
srslte_softbuffer_rx_t softbuffer_rx; srslte_softbuffer_rx_t softbuffers_rx[SRSLTE_MAX_TB];
srslte_softbuffer_tx_t softbuffer_tx; srslte_softbuffer_tx_t softbuffers_tx[SRSLTE_MAX_TB];
uint16_t temp_c_rnti; uint16_t temp_c_rnti;
@ -218,7 +218,7 @@ public:
bool rar_rnti_set; bool rar_rnti_set;
void pch_decoded_ok(uint32_t len) {} void pch_decoded_ok(uint32_t len) {}
void tti_clock(uint32_t tti) { void tti_clock(uint32_t tti) {
@ -233,19 +233,21 @@ public:
void new_grant_ul(mac_grant_t grant, tb_action_ul_t *action) { void new_grant_ul(mac_grant_t grant, tb_action_ul_t *action) {
printf("New grant UL\n"); printf("New grant UL\n");
memcpy(payload, conn_request_msg, grant.n_bytes*sizeof(uint8_t)); for (uint32_t tb = 0; tb < SRSLTE_MAX_TB; tb ++) {
memcpy(payload[tb], conn_request_msg, grant.n_bytes[tb]*sizeof(uint8_t));
action->rv[tb] = rv_value[nof_rtx_connsetup%4];
action->payload_ptr[tb] = payload[tb];
if (action->rv[tb] == 0) {
srslte_softbuffer_tx_reset(&softbuffers_tx[tb]);
}
}
action->current_tx_nb = nof_rtx_connsetup; action->current_tx_nb = nof_rtx_connsetup;
action->rv = rv_value[nof_rtx_connsetup%4]; action->softbuffers = softbuffers_tx;
action->softbuffer = &softbuffer_tx;
action->rnti = temp_c_rnti; action->rnti = temp_c_rnti;
action->expect_ack = (nof_rtx_connsetup < 5)?true:false; action->expect_ack = (nof_rtx_connsetup < 5)?true:false;
action->payload_ptr = payload;
memcpy(&action->phy_grant, &grant.phy_grant, sizeof(srslte_phy_grant_t)); memcpy(&action->phy_grant, &grant.phy_grant, sizeof(srslte_phy_grant_t));
memcpy(&last_grant, &grant, sizeof(mac_grant_t)); memcpy(&last_grant, &grant, sizeof(mac_grant_t));
action->tx_enabled = true; action->tx_enabled = true;
if (action->rv == 0) {
srslte_softbuffer_tx_reset(&softbuffer_tx);
}
my_phy.pdcch_dl_search(SRSLTE_RNTI_USER, temp_c_rnti); my_phy.pdcch_dl_search(SRSLTE_RNTI_USER, temp_c_rnti);
} }
@ -258,17 +260,20 @@ public:
if (!ack) { if (!ack) {
nof_rtx_connsetup++; nof_rtx_connsetup++;
action->current_tx_nb = nof_rtx_connsetup; action->current_tx_nb = nof_rtx_connsetup;
action->rv = rv_value[nof_rtx_connsetup%4]; action->softbuffers = softbuffers_tx;
action->softbuffer = &softbuffer_tx;
action->rnti = temp_c_rnti; action->rnti = temp_c_rnti;
action->expect_ack = true; action->expect_ack = true;
memcpy(&action->phy_grant, &last_grant.phy_grant, sizeof(srslte_phy_grant_t)); memcpy(&action->phy_grant, &last_grant.phy_grant, sizeof(srslte_phy_grant_t));
action->tx_enabled = true; action->tx_enabled = true;
if (action->rv == 0) { for (uint32_t tb = 0; tb < SRSLTE_MAX_TB; tb ++) {
srslte_softbuffer_tx_reset(&softbuffer_tx); action->rv[tb] = rv_value[nof_rtx_connsetup%4];
if (action->rv[tb] == 0) {
srslte_softbuffer_tx_reset(&softbuffers_tx[tb]);
}
printf("Retransmission %d (TB %d), rv=%d\n", nof_rtx_connsetup, tb, action->rv[tb]);
} }
printf("Retransmission %d, rv=%d\n", nof_rtx_connsetup, action->rv); }
}
} }
void new_grant_dl(mac_grant_t grant, tb_action_dl_t *action) { void new_grant_dl(mac_grant_t grant, tb_action_dl_t *action) {
@ -279,24 +284,25 @@ public:
} else { } else {
action->generate_ack = true; action->generate_ack = true;
} }
action->payload_ptr = payload; action->rnti = grant.rnti;
action->rnti = grant.rnti;
memcpy(&action->phy_grant, &grant.phy_grant, sizeof(srslte_phy_grant_t)); memcpy(&action->phy_grant, &grant.phy_grant, sizeof(srslte_phy_grant_t));
memcpy(&last_grant, &grant, sizeof(mac_grant_t)); memcpy(&last_grant, &grant, sizeof(mac_grant_t));
action->rv = grant.rv; for (uint32_t tb = 0; tb < SRSLTE_MAX_TB; tb ++) {
action->softbuffer = &softbuffer_rx; action->softbuffers[tb] = &softbuffers_rx[tb];
action->rv[tb] = grant.rv[tb];
if (action->rv == 0) { action->payload_ptr[tb] = payload[tb];
srslte_softbuffer_rx_reset(&softbuffer_rx); if (action->rv[tb] == 0) {
srslte_softbuffer_rx_reset(&softbuffers_rx[tb]);
}
} }
} }
void tb_decoded(bool ack, srslte_rnti_type_t rnti_type, uint32_t harq_pid) { void tb_decoded(bool ack, uint32_t tb_idx, srslte_rnti_type_t rnti_type, uint32_t harq_pid) {
if (ack) { if (ack) {
if (rnti_type == SRSLTE_RNTI_RAR) { if (rnti_type == SRSLTE_RNTI_RAR) {
my_phy.pdcch_dl_search_reset(); my_phy.pdcch_dl_search_reset();
srslte_bit_unpack_vector(payload, payload_bits, last_grant.n_bytes*8); srslte_bit_unpack_vector(payload[tb_idx], payload_bits[tb_idx], last_grant.n_bytes[tb_idx]*8);
rar_unpack(payload_bits, &rar_msg); rar_unpack(payload_bits[tb_idx], &rar_msg);
if (rar_msg.RAPID == preamble_idx) { if (rar_msg.RAPID == preamble_idx) {
printf("Received RAR at TTI: %d\n", last_grant.tti); printf("Received RAR at TTI: %d\n", last_grant.tti);
@ -304,7 +310,7 @@ public:
temp_c_rnti = rar_msg.temp_c_rnti; temp_c_rnti = rar_msg.temp_c_rnti;
if (last_grant.n_bytes*8 > 20 + SRSLTE_RAR_GRANT_LEN) { if (last_grant.n_bytes[0]*8 > 20 + SRSLTE_RAR_GRANT_LEN) {
uint8_t rar_grant[SRSLTE_RAR_GRANT_LEN]; uint8_t rar_grant[SRSLTE_RAR_GRANT_LEN];
memcpy(rar_grant, &payload_bits[20], sizeof(uint8_t)*SRSLTE_RAR_GRANT_LEN); memcpy(rar_grant, &payload_bits[20], sizeof(uint8_t)*SRSLTE_RAR_GRANT_LEN);
my_phy.set_rar_grant(last_grant.tti, rar_grant); my_phy.set_rar_grant(last_grant.tti, rar_grant);
@ -323,9 +329,11 @@ public:
printf("BCH decoded\n"); printf("BCH decoded\n");
bch_decoded = true; bch_decoded = true;
srslte_cell_t cell; srslte_cell_t cell;
my_phy.get_current_cell(&cell); my_phy.get_current_cell(&cell);
srslte_softbuffer_rx_init(&softbuffer_rx, cell.nof_prb); for (uint32_t tb = 0; tb < SRSLTE_MAX_TB; tb++) {
srslte_softbuffer_tx_init(&softbuffer_tx, cell.nof_prb); srslte_softbuffer_rx_init(&softbuffers_rx[tb], cell.nof_prb);
srslte_softbuffer_tx_init(&softbuffers_tx[tb], cell.nof_prb);
}
} }
private: private:

@ -87,8 +87,8 @@ bool bch_decoded = false;
uint32_t total_pkts=0; uint32_t total_pkts=0;
uint32_t total_dci=0; uint32_t total_dci=0;
uint32_t total_oks=0; uint32_t total_oks=0;
uint8_t payload[1024]; uint8_t payload[SRSLTE_MAX_TB][1024];
srslte_softbuffer_rx_t softbuffer; srslte_softbuffer_rx_t softbuffers[SRSLTE_MAX_TB];
class rrc_dummy : public srsue::rrc_interface_phy class rrc_dummy : public srsue::rrc_interface_phy
{ {
@ -118,20 +118,23 @@ public:
action->decode_enabled = true; action->decode_enabled = true;
action->default_ack = false; action->default_ack = false;
action->generate_ack = false; action->generate_ack = false;
action->payload_ptr = payload; for (uint32_t tb = 0; tb < SRSLTE_MAX_TB; tb++) {
memcpy(&action->phy_grant, &grant.phy_grant, sizeof(srslte_phy_grant_t)); action->payload_ptr[tb] = payload[tb];
action->rv = ((uint32_t) ceilf((float)3*((my_phy.tti_to_SFN(grant.tti)/2)%4)/2))%4; action->rv[tb] = ((uint32_t) ceilf((float) 3 * ((my_phy.tti_to_SFN(grant.tti) / 2) % 4) / 2)) % 4;
action->softbuffer = &softbuffer; if (action->rv == 0) {
action->rnti = grant.rnti; srslte_softbuffer_rx_reset(&softbuffers[tb]);
if (action->rv == 0) { }
srslte_softbuffer_rx_reset(&softbuffer); action->softbuffers[0] = &softbuffers[tb];
} }
memcpy(&action->phy_grant, &grant.phy_grant, sizeof(srslte_phy_grant_t));
action->rnti = grant.rnti;
} }
void tb_decoded(bool ack, srslte_rnti_type_t rnti, uint32_t harq_pid) { void tb_decoded(bool ack, uint32_t tb_idx, srslte_rnti_type_t rnti_type, uint32_t harq_pid) {
if (ack) { if (ack) {
total_oks++; total_oks++;
} }
@ -144,7 +147,9 @@ public:
bch_decoded = true; bch_decoded = true;
srslte_cell_t cell; srslte_cell_t cell;
my_phy.get_current_cell(&cell); my_phy.get_current_cell(&cell);
srslte_softbuffer_rx_init(&softbuffer, cell.nof_prb); for (uint32_t tb = 0; tb < SRSLTE_MAX_TB; tb++) {
srslte_softbuffer_rx_init(&softbuffers[tb], cell.nof_prb);
}
} }
void tti_clock(uint32_t tti) { void tti_clock(uint32_t tti) {

Loading…
Cancel
Save