int test_dci_payload_size() { int i, j; int x[5]; const srslte_dci_format_t formats[] = { SRSLTE_DCI_FORMAT0, SRSLTE_DCI_FORMAT1, SRSLTE_DCI_FORMAT1A, SRSLTE_DCI_FORMAT1C, SRSLTE_DCI_FORMAT2A }; const int prb[6] = { 6, 15, 25, 50, 75, 100 }; const int dci_sz[6][5] = { { 21, 19, 21, 8, 28 }, { 22, 23, 22, 10 , 31}, { 25, 27, 25, 12 , 36}, { 27, 31, 27, 13 , 41}, { 27, 33, 27, 14 , 42}, { 28, 39, 28, 15, 48 }}; srslte_dl_sf_cfg_t dl_sf; ZERO_OBJECT(dl_sf); srslte_cell_t cell_test; ZERO_OBJECT(cell_test); cell_test.nof_ports = 1; ZERO_OBJECT(dci_cfg); printf("Testing DCI payload sizes...\n"); printf(" PRB\t0\t1\t1A\t1C\t2A\n"); for (i = 0; i < 6; i++) { int n = prb[i]; cell_test.nof_prb = n; for (j = 0; j < 5; j++) { x[j] = srslte_dci_format_sizeof(&cell_test, &dl_sf, &dci_cfg, formats[j]); if (x[j] != dci_sz[i][j]) { ERROR("Invalid DCI payload size for %s and %d PRB. Is %d and should be %d\n", srslte_dci_format_string(formats[j]), n, x[j], dci_sz[i][j]); return -1; } } printf(" %2d:\t%2d\t%2d\t%2d\t%2d\t%2d\n", n, x[0], x[1], x[2], x[3], x[4]); } printf("Ok\n"); if (print_dci_table) { printf("dci_sz_table[101][4] = {\n"); for (i=0;i<=100;i++) { printf(" {"); for (j = 0; j < 4; j++) { cell_test.nof_prb = i; printf("%d", srslte_dci_format_sizeof(&cell, &dl_sf, &dci_cfg, formats[j])); if (j<3) { printf(", "); } } if (i<100) { printf("},\n"); } else { printf("}\n"); } } printf("};\n"); } return 0; }
int main(int argc, char** argv) { parse_args(argc, argv); srslte_prach_t prach; bool high_speed_flag = false; cf_t preamble[MAX_LEN]; memset(preamble, 0, sizeof(cf_t)*MAX_LEN); srslte_prach_cfg_t prach_cfg; ZERO_OBJECT(prach_cfg); prach_cfg.config_idx = config_idx; prach_cfg.hs_flag = high_speed_flag; prach_cfg.freq_offset = 0; prach_cfg.root_seq_idx = root_seq_idx; prach_cfg.zero_corr_zone = zero_corr_zone; if (srslte_prach_init(&prach, srslte_symbol_sz(nof_prb))) { return -1; } if (srslte_prach_set_cfg(&prach, &prach_cfg, nof_prb)) { ERROR("Error initiating PRACH object\n"); return -1; } uint32_t seq_index = 0; uint32_t indices[64]; uint32_t n_indices = 0; for(int i=0;i<64;i++) indices[i] = 0; for(seq_index=0;seq_index<64;seq_index++) { srslte_prach_gen(&prach, seq_index, 0, preamble); uint32_t prach_len = prach.N_seq; struct timeval t[3]; gettimeofday(&t[1], NULL); srslte_prach_detect(&prach, 0, &preamble[prach.N_cp], prach_len, indices, &n_indices); gettimeofday(&t[2], NULL); get_time_interval(t); printf("texec=%ld us\n", t[0].tv_usec); if(n_indices != 1 || indices[0] != seq_index) return -1; } srslte_prach_free(&prach); srslte_dft_exit(); printf("Done\n"); exit(0); }
int srslte_enb_dl_put_pdcch_ul(srslte_enb_dl_t* q, srslte_dci_cfg_t* dci_cfg, srslte_dci_ul_t* dci_ul) { srslte_dci_msg_t dci_msg; ZERO_OBJECT(dci_msg); if (srslte_dci_msg_pack_pusch(&q->cell, &q->dl_sf, dci_cfg, dci_ul, &dci_msg)) { ERROR("Error packing UL DCI\n"); } if (srslte_pdcch_encode(&q->pdcch, &q->dl_sf, &dci_msg, q->sf_symbols)) { ERROR("Error encoding UL DCI message\n"); return SRSLTE_ERROR; } return SRSLTE_SUCCESS; }
void CleanupSPIHW(SDHCD_HW_DEVICE *pHWDevice) { pHWDevice->ShutDown = TRUE; if (pHWDevice->InitStateMask & SDHC_COMMON_INIT) { /* deinit common layer */ HcdDeinitialize(pHWDevice->pDevice); } if (pHWDevice->InitStateMask & SDHC_REGISTERED) { SDIO_UnregisterHostController(&pHWDevice->pDevice->Hcd); } if (pHWDevice->pWorker != NULL) { SDLIB_FlushWorkTask(pHWDevice->pWorker,&pHWDevice->IOCompleteWorkTask); SDLIB_DestroyWorker(pHWDevice->pWorker); } if (pHWDevice->hIstEventSPIGpioIRQ != NULL) { /* make sure interrupt asssociated with the event is disabled */ if (pHWDevice->SysIntrSPIGpioIRQ != 0) { InterruptDisable(pHWDevice->SysIntrSPIGpioIRQ); } if (pHWDevice->hIstSPIGpioIRQ != NULL) { /* wake IST */ SetEvent(pHWDevice->hIstEventSPIGpioIRQ); /* wait for IST to exit */ WaitForSingleObject(pHWDevice->hIstSPIGpioIRQ, INFINITE); CloseHandle(pHWDevice->hIstSPIGpioIRQ); pHWDevice->hIstSPIGpioIRQ = NULL; } CloseHandle(pHWDevice->hIstEventSPIGpioIRQ); pHWDevice->hIstEventSPIGpioIRQ = NULL; } /* TODO : free hardware resources */ /*********************************/ ZERO_OBJECT(g_HWDevice); DBG_PRINT(SDDBG_TRACE, ("SPI HCD: CleanupDevice\n")); }
/* Precalculate the PDSCH scramble sequences for a given RNTI. This function takes a while * to execute, so shall be called once the final C-RNTI has been allocated for the session. * For the connection procedure, use srslte_pusch_encode_rnti() or srslte_pusch_decode_rnti() functions */ void srslte_ue_dl_set_rnti(srslte_ue_dl_t* q, uint16_t rnti) { srslte_pdsch_set_rnti(&q->pdsch, rnti); srslte_dl_sf_cfg_t sf_cfg; ZERO_OBJECT(sf_cfg); // Compute UE-specific and Common search space for this RNTI for (int i = 0; i < MI_NOF_REGS; i++) { srslte_pdcch_set_regs(&q->pdcch, &q->regs[i]); for (int cfi = 0; cfi < 3; cfi++) { sf_cfg.cfi = cfi + 1; for (int sf_idx = 0; sf_idx < 10; sf_idx++) { sf_cfg.tti = sf_idx; q->current_ss_ue[i][cfi][sf_idx].nof_locations = srslte_pdcch_ue_locations( &q->pdcch, &sf_cfg, q->current_ss_ue[i][cfi][sf_idx].loc, MAX_CANDIDATES_UE, rnti); } q->current_ss_common[i][cfi].nof_locations = srslte_pdcch_common_locations(&q->pdcch, q->current_ss_common[i][cfi].loc, MAX_CANDIDATES_COM, cfi + 1); } } q->pregen_rnti = rnti; }
int main(int argc, char** argv) { parse_args(argc, argv); srslte_prach_t prach; bool high_speed_flag = false; cf_t preamble[MAX_LEN]; memset(preamble, 0, sizeof(cf_t)*MAX_LEN); cf_t preamble_sum[MAX_LEN]; memset(preamble_sum, 0, sizeof(cf_t)*MAX_LEN); srslte_prach_cfg_t prach_cfg; ZERO_OBJECT(prach_cfg); prach_cfg.config_idx = preamble_format; prach_cfg.hs_flag = high_speed_flag; prach_cfg.freq_offset = 0; prach_cfg.root_seq_idx = root_seq_idx; prach_cfg.zero_corr_zone = zero_corr_zone; if (srslte_prach_init(&prach, srslte_symbol_sz(nof_prb))) { return -1; } if (srslte_prach_set_cfg(&prach, &prach_cfg, nof_prb)) { ERROR("Error initiating PRACH object\n"); return -1; } uint32_t seq_index = 0; uint32_t frequency_offset = 0; uint32_t indices[64]; uint32_t n_indices = 0; for(int i=0;i<64;i++) indices[i] = 0; srslte_prach_set_detect_factor(&prach, 10); for(seq_index=0;seq_index<n_seqs;seq_index++) { srslte_prach_gen(&prach, seq_index, frequency_offset, preamble); for (int i = 0; i < prach.N_cp + prach.N_seq; i++) { preamble_sum[i] += preamble[i]; } } uint32_t prach_len = prach.N_seq; if (preamble_format == 2 || preamble_format == 3) { prach_len /= 2; } srslte_prach_detect(&prach, 0, &preamble_sum[prach.N_cp], prach_len, indices, &n_indices); if (n_indices != n_seqs) { return -1; } for (int i = 0; i < n_seqs; i++) { if (indices[i] != i) { return -1; } } srslte_prach_free(&prach); srslte_dft_exit(); printf("Done\n"); exit(0); }
int exec(const char* logfilename, const char* cmdline) { #ifdef _WIN32 STARTUPINFO si; PROCESS_INFORMATION pi; //HandleCloser hEvent; SECURITY_ATTRIBUTES sa; sa.lpSecurityDescriptor = NULL; sa.nLength = sizeof(sa); sa.bInheritHandle = true; W32TEST(CreatePipe(hReadPipe.p(), hWritePipe.p(), &sa, 0)); W32TEST(CreatePipe(hStdinPipeRead.p(), hStdinPipeWrite.p(), &sa, 0)); hLogfile = CreateFile(logfilename, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); W32TEST(hLogfile != INVALID_HANDLE_VALUE); //todo: create console ZERO_OBJECT(si); si.cb = sizeof(si); si.dwFlags = STARTF_USESTDHANDLES; si.hStdOutput = hWritePipe; si.hStdError = hWritePipe; si.hStdInput = hStdinPipeRead; std::string commandLine = cmdline; //will modify string. is ok since commandLine is a copy. W32TEST(CreateProcess(NULL, (char*)commandLine.c_str(), NULL, NULL, true, CREATE_NO_WINDOW, NULL, NULL, &si, &pi)); HandleCloser hcProcess = pi.hProcess; HandleCloser hcThread = pi.hThread; DWORD exitCode; hWritePipe.close(); hStdinPipeRead.close(); HandleCloser hOutThread = CreateThread(NULL, 0, OutThreadFunc, NULL, 0, NULL); HandleCloser hInThread = CreateThread(NULL, 0, InThreadFunc, NULL, 0, NULL); if(WaitForSingleObject(pi.hProcess, INFINITE) == WAIT_FAILED) { DO_GLE; } W32TEST(GetExitCodeProcess(pi.hProcess, &exitCode)); return exitCode; #else #define FAIL_ERRNO LOG("Errno %i @ %s:%i\n", errno, __FILE__, __LINE__); return -2 #define ERRNO(a) if((a) < 0) { FAIL_ERRNO; } LOG("execDoublePipe(%s, %i)\n", cmdline, in.size()); int pin[2], pout[2]; ERRNO(pipe(pin)); ERRNO(pipe(pout)); pid_t pid = fork(); if(pid == 0) { //child if(dup2(pin[0], STDIN_FILENO) < 0) _exit(errno); close(pin[1]); if(dup2(pout[1], STDOUT_FILENO) < 0) _exit(errno); close(pout[0]); execvp(cmdline, NULL); //if this function returns, it has failed. _exit(errno); } else { //parent if(pid < 0) { //fork failed FAIL_ERRNO; } } ERRNO(close(pin[0])); FILE* fout = fdopen(pin[1], "w"); if(!fout) { FAIL_ERRNO; } ERRNO(close(pout[1])); fprintf(fout, "%s", in.c_str()); ERRNO(fclose(fout)); out.clear(); while(1) { char buffer[BUFSIZE]; ssize_t res; ERRNO(res = read(pout[0], buffer, BUFSIZE)); if(res == 0) //EOF break; out.append(buffer, res); } ERRNO(close(pout[0])); int status; ERRNO(waitpid(pid, &status, 0)); errno = status; ERRNO(errno); return status; #endif }
int main(int argc, char** argv) { srslte_chest_dl_res_t chest_dl_res; srslte_pdcch_t pdcch_tx, pdcch_rx; testcase_dci_t testcases[10]; srslte_regs_t regs; int i; int nof_re; cf_t *slot_symbols[SRSLTE_MAX_PORTS]; int nof_dcis; bzero(&testcases, sizeof(testcase_dci_t)*10); int ret = -1; parse_args(argc, argv); nof_re = SRSLTE_CP_NORM_NSYMB * cell.nof_prb * SRSLTE_NRE; if (test_dci_payload_size()) { exit(-1); } /* init memory */ srslte_chest_dl_res_init(&chest_dl_res, cell.nof_prb); srslte_chest_dl_res_set_identity(&chest_dl_res); for (i = 0; i < SRSLTE_MAX_PORTS; i++) { slot_symbols[i] = malloc(sizeof(cf_t) * nof_re); if (!slot_symbols[i]) { perror("malloc"); exit(-1); } bzero(slot_symbols[i], sizeof(cf_t) * nof_re); } if (srslte_regs_init(®s, cell)) { ERROR("Error initiating regs\n"); exit(-1); } if (srslte_pdcch_init_enb(&pdcch_tx, cell.nof_prb)) { ERROR("Error creating PDCCH object\n"); exit(-1); } if (srslte_pdcch_set_cell(&pdcch_tx, ®s, cell)) { ERROR("Error setting cell in PDCCH object\n"); exit(-1); } if (srslte_pdcch_init_ue(&pdcch_rx, cell.nof_prb, nof_rx_ant)) { ERROR("Error creating PDCCH object\n"); exit(-1); } if (srslte_pdcch_set_cell(&pdcch_rx, ®s, cell)) { ERROR("Error setting cell in PDCCH object\n"); exit(-1); } /* Resource allocate init */ nof_dcis = 0; srslte_dci_dl_t dci; ZERO_OBJECT(dci); dci.pid = 5; dci.tb[0].mcs_idx = 5; dci.tb[0].ndi = 0; dci.tb[0].rv = 1; dci.alloc_type = SRSLTE_RA_ALLOC_TYPE0; dci.type0_alloc.rbg_bitmask = 0x5; dci.cif_present = dci_cfg.cif_enabled; if (dci_cfg.cif_enabled) { dci.cif = (uint32_t)(random() & 0x7); } /* Format 1 Test case */ if (cell.nof_ports == 1) { testcases[nof_dcis].dci_format = SRSLTE_DCI_FORMAT1; if (dci_cfg.cif_enabled) { dci.cif = (uint32_t)(random() & 0x7); } testcases[nof_dcis].ra_dl_tx = dci; nof_dcis++; /* Format 1 Test case */ dci.tb[0].mcs_idx = 15; testcases[nof_dcis].dci_format = SRSLTE_DCI_FORMAT1; if (dci_cfg.cif_enabled) { dci.cif = (uint32_t)(random() & 0x7); } testcases[nof_dcis].ra_dl_tx = dci; nof_dcis++; } /* Tx Diversity Test case */ if (cell.nof_ports > 1) { dci.tb[1].mcs_idx = 13; dci.tb[1].rv = 3; dci.tb[1].ndi = true; testcases[nof_dcis].dci_format = SRSLTE_DCI_FORMAT2A; if (dci_cfg.cif_enabled) { dci.cif = (uint32_t)(random() & 0x7); } testcases[nof_dcis].ra_dl_tx = dci; nof_dcis++; } /* CDD Spatial Multiplexing Test case */ if (cell.nof_ports > 1) { dci.tb[1].mcs_idx = 28; dci.tb[1].rv = 1; dci.tb[1].ndi = false; testcases[nof_dcis].dci_format = SRSLTE_DCI_FORMAT2; if (dci_cfg.cif_enabled) { dci.cif = (uint32_t)(random() & 0x7); } testcases[nof_dcis].ra_dl_tx = dci; nof_dcis++; } srslte_dci_cfg_t dci_cfg; ZERO_OBJECT(dci_cfg); srslte_dl_sf_cfg_t dl_sf; ZERO_OBJECT(dl_sf); dl_sf.cfi = cfi; for (int s=0;s<10;s++) { dl_sf.tti = s; printf("Encoding %d DCIs for sf_idx=%d\n", nof_dcis, s); /* Execute Rx */ for (i=0;i<nof_dcis;i++) { testcases[i].ra_dl_tx.rnti = (uint16_t) (1234 + i); testcases[i].ra_dl_tx.format = testcases[i].dci_format; srslte_dci_msg_pack_pdsch(&cell, &dl_sf, &dci_cfg, &testcases[i].ra_dl_tx, &testcases[i].dci_tx); srslte_dci_location_set(&testcases[i].dci_location, 0, (uint32_t) i); testcases[i].dci_tx.format = testcases[i].dci_format; testcases[i].dci_tx.location = testcases[i].dci_location; // Enable just 1 TB per default if (testcases[i].dci_format < SRSLTE_DCI_FORMAT2) { for (int j=1;j<SRSLTE_MAX_CODEWORDS;j++) { SRSLTE_DCI_TB_DISABLE(testcases[i].ra_dl_tx.tb[j]); } } if (srslte_pdcch_encode(&pdcch_tx, &dl_sf, &testcases[i].dci_tx, slot_symbols)) { ERROR("Error encoding DCI message\n"); goto quit; } } /* Execute 'Rx' */ if (srslte_pdcch_extract_llr(&pdcch_rx, &dl_sf, &chest_dl_res, slot_symbols)) { ERROR("Error extracting LLRs\n"); goto quit; } /* Decode DCIs */ for (i=0;i<nof_dcis;i++) { testcases[i].dci_rx.format = testcases[i].dci_format; testcases[i].dci_rx.location = testcases[i].dci_location; if (srslte_pdcch_decode_msg(&pdcch_rx, &dl_sf, &dci_cfg, &testcases[i].dci_rx)) { ERROR("Error decoding DCI message\n"); goto quit; } if (srslte_dci_msg_unpack_pdsch(&cell, &dl_sf, &dci_cfg, &testcases[i].dci_rx, &testcases[i].ra_dl_rx)) { ERROR("Error unpacking DCI message\n"); goto quit; } if (testcases[i].dci_rx.rnti >= 1234 && testcases[i].dci_rx.rnti < 1234 + nof_dcis) { testcases[i].dci_rx.rnti -= 1234; } else { printf("Received invalid DCI CRC %d\n", testcases[i].dci_rx.rnti); goto quit; } } /* Compare Tx and Rx */ for (i = 0; i < nof_dcis; i++) { if (memcmp(testcases[i].dci_tx.payload, testcases[i].dci_rx.payload, testcases[i].dci_tx.nof_bits)) { printf("Error in DCI %d: Received data does not match\n", i); goto quit; } #if SRSLTE_DCI_HEXDEBUG // Ignore Hex str bzero(testcases[i].ra_dl_rx.hex_str, sizeof(testcases[i].ra_dl_rx.hex_str)); testcases[i].ra_dl_rx.nof_bits = 0; #endif // Ignore DCI location testcases[i].ra_dl_rx.location = testcases[i].ra_dl_tx.location; // Ignore cw_idx for (int j=0;j<SRSLTE_MAX_CODEWORDS;j++) { testcases[i].ra_dl_rx.tb[j].cw_idx = testcases[i].ra_dl_tx.tb[j].cw_idx; } if (memcmp(&testcases[i].ra_dl_tx, &testcases[i].ra_dl_rx, sizeof(srslte_dci_dl_t))) { uint8_t *x=(uint8_t*) &testcases[i].ra_dl_rx; uint8_t *y=(uint8_t*) &testcases[i].ra_dl_tx; for (int j=0;j<sizeof(srslte_dci_dl_t);j++) { if (x[j] != y[j]) { printf("error in byte %d, rx=%d, tx=%d\n", j, x[j], y[j]); } } printf("tx: "); srslte_vec_fprint_byte(stdout, (uint8_t*) &testcases[i].ra_dl_tx, sizeof(srslte_dci_dl_t)); printf("rx: "); srslte_vec_fprint_byte(stdout, (uint8_t*) &testcases[i].ra_dl_rx, sizeof(srslte_dci_dl_t)); printf("Error in RA %d: Received data does not match\n", i); printf(" Field | Tx | Rx \n"); printf("--------------+----------+----------\n"); if (testcases[i].ra_dl_tx.cif) { printf(" cif | %8d | %8d\n", testcases[i].ra_dl_tx.cif, testcases[i].ra_dl_rx.cif); } printf(" harq_process | %8d | %8d\n", testcases[i].ra_dl_tx.pid, testcases[i].ra_dl_rx.pid); printf(" mcs_idx | %8d | %8d\n", testcases[i].ra_dl_tx.tb[0].mcs_idx, testcases[i].ra_dl_rx.tb[0].mcs_idx); printf(" rv_idx | %8d | %8d\n", testcases[i].ra_dl_tx.tb[0].rv, testcases[i].ra_dl_rx.tb[0].rv); printf(" ndi | %8d | %8d\n", testcases[i].ra_dl_tx.tb[0].ndi, testcases[i].ra_dl_rx.tb[0].ndi); printf(" mcs_idx_1 | %8d | %8d\n", testcases[i].ra_dl_tx.tb[1].mcs_idx, testcases[i].ra_dl_rx.tb[1].mcs_idx); printf(" rv_idx_1 | %8d | %8d\n", testcases[i].ra_dl_tx.tb[1].rv, testcases[i].ra_dl_rx.tb[1].rv); printf(" ndi_1 | %8d | %8d\n", testcases[i].ra_dl_tx.tb[1].ndi, testcases[i].ra_dl_rx.tb[1].ndi); printf(" tb_cw_swap | %8d | %8d\n", testcases[i].ra_dl_tx.tb_cw_swap, testcases[i].ra_dl_rx.tb_cw_swap); printf(" sram_id | %8d | %8d\n", testcases[i].ra_dl_tx.sram_id, testcases[i].ra_dl_rx.sram_id); printf(" pinfo | %8d | %8d\n", testcases[i].ra_dl_tx.pinfo, testcases[i].ra_dl_rx.pinfo); printf(" pconf | %8d | %8d\n", testcases[i].ra_dl_tx.pconf, testcases[i].ra_dl_rx.pconf); printf(" power_offset | %8d | %8d\n", testcases[i].ra_dl_tx.power_offset, testcases[i].ra_dl_rx.power_offset); printf(" tpc_pucch | %8d | %8d\n", testcases[i].ra_dl_tx.tpc_pucch, testcases[i].ra_dl_rx.tpc_pucch); goto quit; } } } ret = 0; quit: srslte_pdcch_free(&pdcch_tx); srslte_pdcch_free(&pdcch_rx); srslte_chest_dl_res_free(&chest_dl_res); srslte_regs_free(®s); for (i = 0; i < SRSLTE_MAX_PORTS; i++) { free(slot_symbols[i]); } if (ret) { printf("Error\n"); } else { printf("Ok\n"); } srslte_dft_exit(); exit(ret); }
int srslte_ue_dl_find_and_decode(srslte_ue_dl_t* q, srslte_dl_sf_cfg_t* sf, srslte_ue_dl_cfg_t* cfg, srslte_pdsch_cfg_t* pdsch_cfg, uint8_t* data[SRSLTE_MAX_CODEWORDS], bool acks[SRSLTE_MAX_CODEWORDS]) { int ret = SRSLTE_ERROR; srslte_dci_dl_t dci_dl; srslte_pmch_cfg_t pmch_cfg; srslte_pdsch_res_t pdsch_res[SRSLTE_MAX_CODEWORDS]; // Use default values for PDSCH decoder ZERO_OBJECT(pmch_cfg); uint32_t mi_set_len; if (q->cell.frame_type == SRSLTE_TDD && !sf->tdd_config.configured) { mi_set_len = 3; } else { mi_set_len = 1; } // Blind search PHICH mi value ZERO_OBJECT(dci_dl); ret = 0; for (uint32_t i = 0; i < mi_set_len && !ret; i++) { if (mi_set_len == 1) { srslte_ue_dl_set_mi_auto(q); } else { srslte_ue_dl_set_mi_manual(q, i); } if ((ret = srslte_ue_dl_decode_fft_estimate(q, sf, cfg)) < 0) { return ret; } ret = srslte_ue_dl_find_dl_dci(q, sf, cfg, pdsch_cfg->rnti, &dci_dl); } if (ret == 1) { // Logging char str[512]; srslte_dci_dl_info(&dci_dl, str, 512); INFO("PDCCH: %s, snr=%.1f dB\n", str, q->chest_res.snr_db); // Force known MBSFN grant if (sf->sf_type == SRSLTE_SF_MBSFN) { dci_dl.rnti = SRSLTE_MRNTI; dci_dl.alloc_type = SRSLTE_RA_ALLOC_TYPE0; dci_dl.type0_alloc.rbg_bitmask = 0xffffffff; dci_dl.tb[0].rv = 0; dci_dl.tb[0].mcs_idx = 2; dci_dl.format = SRSLTE_DCI_FORMAT1; } // Convert DCI message to DL grant if (srslte_ue_dl_dci_to_pdsch_grant(q, sf, cfg, &dci_dl, &pdsch_cfg->grant)) { ERROR("Error unpacking DCI\n"); return SRSLTE_ERROR; } // Calculate RV if not provided in the grant and reset softbuffer for (int i = 0; i < SRSLTE_MAX_CODEWORDS; i++) { if (pdsch_cfg->grant.tb[i].enabled) { if (pdsch_cfg->grant.tb[i].rv < 0) { uint32_t sfn = sf->tti / 10; uint32_t k = (sfn / 2) % 4; pdsch_cfg->grant.tb[i].rv = ((uint32_t)ceilf((float)1.5 * k)) % 4; } srslte_softbuffer_rx_reset_tbs(pdsch_cfg->softbuffers.rx[i], (uint32_t)pdsch_cfg->grant.tb[i].tbs); } } bool decode_enable = false; for (uint32_t tb = 0; tb < SRSLTE_MAX_CODEWORDS; tb++) { if (pdsch_cfg->grant.tb[tb].enabled) { decode_enable = true; pdsch_res[tb].payload = data[tb]; pdsch_res[tb].crc = false; } } if (decode_enable) { if (sf->sf_type == SRSLTE_SF_NORM) { if (srslte_ue_dl_decode_pdsch(q, sf, pdsch_cfg, pdsch_res)) { ERROR("ERROR: Decoding PDSCH\n"); ret = -1; } } else { pmch_cfg.pdsch_cfg = *pdsch_cfg; if (srslte_ue_dl_decode_pmch(q, sf, &pmch_cfg, pdsch_res)) { ERROR("Decoding PMCH\n"); ret = -1; } } } for (uint32_t tb = 0; tb < SRSLTE_MAX_CODEWORDS; tb++) { if (pdsch_cfg->grant.tb[tb].enabled) { acks[tb] = pdsch_res[tb].crc; } } } return ret; }