|
|
@ -498,114 +498,90 @@ int srslte_dlsch_encode(srslte_sch_t *q, srslte_pdsch_cfg_t *cfg, srslte_softbuf
|
|
|
|
data, e_bits);
|
|
|
|
data, e_bits);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/* UL-SCH channel interleaver according to 5.2.2.8 of 36.212 */
|
|
|
|
/* Compute the interleaving function on-the-fly, because it depends on number of RI bits
|
|
|
|
void ulsch_interleave(uint8_t *g_bits, uint32_t Qm, uint32_t H_prime_total,
|
|
|
|
* Profiling show that the computation of this matrix is neglegible.
|
|
|
|
uint32_t N_pusch_symbs, uint8_t *q_bits, srslte_uci_bit_t *ri_bits, uint32_t nof_ri_bits,
|
|
|
|
*/
|
|
|
|
uint16_t *interleaver_buffer, uint8_t *temp_buffer, uint32_t buffer_sz)
|
|
|
|
static void ulsch_interleave_gen(uint32_t H_prime_total, uint32_t N_pusch_symbs, uint32_t Qm,
|
|
|
|
|
|
|
|
uint8_t *ri_present, uint16_t *interleaver_lut)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
|
|
uint32_t rows = H_prime_total/N_pusch_symbs;
|
|
|
|
uint32_t rows = H_prime_total/N_pusch_symbs;
|
|
|
|
uint32_t cols = N_pusch_symbs;
|
|
|
|
uint32_t cols = N_pusch_symbs;
|
|
|
|
|
|
|
|
|
|
|
|
// Prepare ri_bits for fast search using temp_buffer
|
|
|
|
|
|
|
|
if (nof_ri_bits > 0) {
|
|
|
|
|
|
|
|
for (uint32_t i=0;i<nof_ri_bits;i++) {
|
|
|
|
|
|
|
|
if (ri_bits[i].position < buffer_sz) {
|
|
|
|
|
|
|
|
temp_buffer[ri_bits[i].position] = 1;
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
fprintf(stderr, "Error computing ULSCH interleaver RI bits. Position %d exceeds buffer size %d\n", ri_bits[i].position, buffer_sz);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* Compute the interleaving function on-the-fly, because it depends on number of RI bits
|
|
|
|
|
|
|
|
* Profiling show that the computation of this matrix is neglegible.
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
uint32_t idx = 0;
|
|
|
|
uint32_t idx = 0;
|
|
|
|
for(uint32_t j=0; j<rows; j++) {
|
|
|
|
for(uint32_t j=0; j<rows; j++) {
|
|
|
|
for(uint32_t i=0; i<cols; i++) {
|
|
|
|
for(uint32_t i=0; i<cols; i++) {
|
|
|
|
for(uint32_t k=0; k<Qm; k++) {
|
|
|
|
for(uint32_t k=0; k<Qm; k++) {
|
|
|
|
if (temp_buffer[j*Qm + i*rows*Qm + k]) {
|
|
|
|
if (ri_present[j*Qm + i*rows*Qm + k]) {
|
|
|
|
interleaver_buffer[j*Qm + i*rows*Qm + k] = 0;
|
|
|
|
interleaver_lut[j*Qm + i*rows*Qm + k] = 0;
|
|
|
|
} else {
|
|
|
|
} else {
|
|
|
|
if (j*Qm + i*rows*Qm + k < buffer_sz) {
|
|
|
|
interleaver_lut[j*Qm + i*rows*Qm + k] = idx;
|
|
|
|
interleaver_buffer[j*Qm + i*rows*Qm + k] = idx;
|
|
|
|
idx++;
|
|
|
|
idx++;
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
fprintf(stderr, "Error computing ULSCH interleaver. Position %d exceeds buffer size %d\n", j*Qm + i*rows*Qm + k, buffer_sz);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
srslte_bit_interleave(g_bits, q_bits, interleaver_buffer, H_prime_total*Qm);
|
|
|
|
|
|
|
|
|
|
|
|
printf("rows=%d, cols=%d, Qm=%d, total=%d, symb=%d\n", rows, cols, Qm, H_prime_total, N_pusch_symbs);
|
|
|
|
|
|
|
|
|
|
|
|
// Reset temp_buffer because will be reused next time
|
|
|
|
|
|
|
|
if (nof_ri_bits > 0) {
|
|
|
|
|
|
|
|
for (uint32_t i=0;i<nof_ri_bits;i++) {
|
|
|
|
|
|
|
|
if (ri_bits[i].position < buffer_sz) {
|
|
|
|
|
|
|
|
temp_buffer[ri_bits[i].position] = 0;
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
fprintf(stderr, "Error computing ULSCH interleaver RI bits. Position %d exceeds buffer size %d\n", ri_bits[i].position, buffer_sz);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
uint16_t deinterleaver_buffer[100000];
|
|
|
|
/* UL-SCH channel interleaver according to 5.2.2.8 of 36.212 */
|
|
|
|
|
|
|
|
void ulsch_interleave(uint8_t *g_bits, uint32_t Qm, uint32_t H_prime_total,
|
|
|
|
/* UL-SCH channel deinterleaver according to 5.2.2.8 of 36.212 */
|
|
|
|
uint32_t N_pusch_symbs, uint8_t *q_bits, srslte_uci_bit_t *ri_bits, uint32_t nof_ri_bits,
|
|
|
|
void ulsch_deinterleave(uint8_t *q_bits, uint32_t Qm, uint32_t H_prime_total,
|
|
|
|
uint8_t *ri_present, uint16_t *inteleaver_lut)
|
|
|
|
uint32_t N_pusch_symbs, uint8_t *g_bits, srslte_uci_bit_t *ri_bits, uint32_t nof_ri_bits,
|
|
|
|
|
|
|
|
uint16_t *interleaver_buffer, uint8_t *temp_buffer, uint32_t buffer_sz)
|
|
|
|
|
|
|
|
{
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
|
|
uint32_t rows = H_prime_total/N_pusch_symbs;
|
|
|
|
// Prepare ri_bits for fast search using temp_buffer
|
|
|
|
uint32_t cols = N_pusch_symbs;
|
|
|
|
if (nof_ri_bits > 0) {
|
|
|
|
|
|
|
|
for (uint32_t i=0;i<nof_ri_bits;i++) {
|
|
|
|
/* Compute the interleaving function on-the-fly, because it depends on number of RI bits
|
|
|
|
ri_present[ri_bits[i].position] = 1;
|
|
|
|
* Profiling show that the computation of this matrix is neglegible.
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
uint32_t idx = 0;
|
|
|
|
|
|
|
|
for(uint32_t j=0; j<rows; j++) {
|
|
|
|
|
|
|
|
for(uint32_t i=0; i<cols; i++) {
|
|
|
|
|
|
|
|
for(uint32_t k=0; k<Qm; k++) {
|
|
|
|
|
|
|
|
if (temp_buffer[j*Qm + i*rows*Qm + k]) {
|
|
|
|
|
|
|
|
interleaver_buffer[j*Qm + i*rows*Qm + k] = 0;
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
if (j*Qm + i*rows*Qm + k < buffer_sz) {
|
|
|
|
|
|
|
|
interleaver_buffer[j*Qm + i*rows*Qm + k] = idx;
|
|
|
|
|
|
|
|
deinterleaver_buffer[idx] = j*Qm + i*rows*Qm + k;
|
|
|
|
|
|
|
|
idx++;
|
|
|
|
|
|
|
|
} else {
|
|
|
|
|
|
|
|
fprintf(stderr, "Error computing ULSCH interleaver. Position %d exceeds buffer size %d\n", j*Qm + i*rows*Qm + k, buffer_sz);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
srslte_vec_fprint_s(stdout, interleaver_buffer, H_prime_total*Qm);
|
|
|
|
// Genearate interleaver table and interleave bits
|
|
|
|
srslte_vec_fprint_s(stdout, deinterleaver_buffer, H_prime_total*Qm);
|
|
|
|
ulsch_interleave_gen(H_prime_total, N_pusch_symbs, Qm, ri_present, inteleaver_lut);
|
|
|
|
|
|
|
|
srslte_bit_interleave(g_bits, q_bits, inteleaver_lut, H_prime_total*Qm);
|
|
|
|
|
|
|
|
|
|
|
|
srslte_bit_interleave(q_bits, g_bits, deinterleaver_buffer, H_prime_total*Qm);
|
|
|
|
// Reset temp_buffer because will be reused next time
|
|
|
|
|
|
|
|
if (nof_ri_bits > 0) {
|
|
|
|
|
|
|
|
for (uint32_t i=0;i<nof_ri_bits;i++) {
|
|
|
|
|
|
|
|
ri_present[ri_bits[i].position] = 0;
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/* UL-SCH channel deinterleaver according to 5.2.2.8 of 36.212 */
|
|
|
|
|
|
|
|
void ulsch_deinterleave(int16_t *q_bits, uint32_t Qm, uint32_t H_prime_total,
|
|
|
|
|
|
|
|
uint32_t N_pusch_symbs, int16_t *g_bits, srslte_uci_bit_t *ri_bits, uint32_t nof_ri_bits,
|
|
|
|
|
|
|
|
uint8_t *ri_present, uint16_t *inteleaver_lut)
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
// Generate interleaver table and interleave samples
|
|
|
|
|
|
|
|
ulsch_interleave_gen(H_prime_total, N_pusch_symbs, Qm, ri_present, inteleaver_lut);
|
|
|
|
|
|
|
|
srslte_vec_lut_sss(q_bits, inteleaver_lut, g_bits, H_prime_total*Qm);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
int srslte_ulsch_decode(srslte_sch_t *q, srslte_pusch_cfg_t *cfg, srslte_softbuffer_rx_t *softbuffer,
|
|
|
|
int srslte_ulsch_decode(srslte_sch_t *q, srslte_pusch_cfg_t *cfg, srslte_softbuffer_rx_t *softbuffer,
|
|
|
|
int16_t *e_bits, uint8_t *data)
|
|
|
|
int16_t *q_bits, int16_t *g_bits, uint8_t *data)
|
|
|
|
{
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
|
|
// Interleave UL-SCH (and RI and CQI)
|
|
|
|
uint32_t Q_prime_ri = 0;
|
|
|
|
ulsch_deinterleave(e_bits, Qm, nb_q/Qm, cfg->nbits.nof_symb, q_bits, q->ack_ri_bits, Q_prime_ri*Qm,
|
|
|
|
|
|
|
|
q->ul_interleaver, q->temp_g_bits, SRSLTE_MAX_PRB*12*12*12);
|
|
|
|
uint32_t nb_q = cfg->nbits.nof_bits;
|
|
|
|
|
|
|
|
uint32_t Qm = cfg->grant.Qm;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// Interleave UL-SCH (and RI and CQI)
|
|
|
|
|
|
|
|
ulsch_deinterleave(q_bits, Qm, nb_q/Qm, cfg->nbits.nof_symb, g_bits, q->ack_ri_bits, Q_prime_ri*Qm,
|
|
|
|
|
|
|
|
q->temp_g_bits, q->ul_interleaver);
|
|
|
|
|
|
|
|
|
|
|
|
srslte_vec_fprint_f(stdout, q->temp_g_bits, nb_q);
|
|
|
|
printf("g_bits=[");
|
|
|
|
|
|
|
|
for (int i=0;i<nb_q;i++) {
|
|
|
|
|
|
|
|
printf("%d, ", g_bits[i]>0);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
printf("];\n");
|
|
|
|
|
|
|
|
|
|
|
|
decode_tb(q, softbuffer, &cfg->cb_segm,
|
|
|
|
return decode_tb(q, softbuffer, &cfg->cb_segm,
|
|
|
|
cfg->grant.Qm, cfg->rv, cfg->nbits.nof_bits,
|
|
|
|
cfg->grant.Qm, cfg->rv, cfg->nbits.nof_bits,
|
|
|
|
e_bits, data);
|
|
|
|
g_bits, data);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int srslte_ulsch_encode(srslte_sch_t *q, srslte_pusch_cfg_t *cfg, srslte_softbuffer_tx_t *softbuffer,
|
|
|
|
int srslte_ulsch_encode(srslte_sch_t *q, srslte_pusch_cfg_t *cfg, srslte_softbuffer_tx_t *softbuffer,
|
|
|
@ -675,11 +651,12 @@ int srslte_ulsch_uci_encode(srslte_sch_t *q,
|
|
|
|
uint8_t kk[10000];
|
|
|
|
uint8_t kk[10000];
|
|
|
|
srslte_bit_unpack_vector(g_bits, kk, nb_q);
|
|
|
|
srslte_bit_unpack_vector(g_bits, kk, nb_q);
|
|
|
|
srslte_vec_save_file("g_bits_tx", kk, nb_q);
|
|
|
|
srslte_vec_save_file("g_bits_tx", kk, nb_q);
|
|
|
|
|
|
|
|
printf("g_bits_tx=");
|
|
|
|
srslte_vec_fprint_b(stdout, kk, nb_q);
|
|
|
|
srslte_vec_fprint_b(stdout, kk, nb_q);
|
|
|
|
|
|
|
|
|
|
|
|
// Interleave UL-SCH (and RI and CQI)
|
|
|
|
// Interleave UL-SCH (and RI and CQI)
|
|
|
|
ulsch_interleave(g_bits, Qm, nb_q/Qm, cfg->nbits.nof_symb, q_bits, q->ack_ri_bits, Q_prime_ri*Qm,
|
|
|
|
ulsch_interleave(g_bits, Qm, nb_q/Qm, cfg->nbits.nof_symb, q_bits, q->ack_ri_bits, Q_prime_ri*Qm,
|
|
|
|
q->ul_interleaver, q->temp_g_bits, SRSLTE_MAX_PRB*12*12*12);
|
|
|
|
q->temp_g_bits, q->ul_interleaver);
|
|
|
|
|
|
|
|
|
|
|
|
// Encode (and interleave) ACK
|
|
|
|
// Encode (and interleave) ACK
|
|
|
|
if (uci_data.uci_ack_len > 0) {
|
|
|
|
if (uci_data.uci_ack_len > 0) {
|
|
|
|