From 5eab57670b95cc4cedd9ad54de5a6c03211e3f2e Mon Sep 17 00:00:00 2001 From: ismagom Date: Sun, 29 Jun 2014 19:51:25 +0200 Subject: [PATCH] Changed nof_prb, nof_ports, cell_id, etc. by lte_cell_t structure. Fixed PBCH/PDSCH resource mapping with odd number PRB. PDSCH examles not working with more than 6 PRB due to downsampling problem. --- CMakeLists.txt | 2 +- lte/phy/examples/pbch_enodeb.c | 8 +- lte/phy/examples/pbch_ue.c | 9 +- lte/phy/examples/pdsch_enodeb.c | 35 +- lte/phy/examples/pdsch_ue.c | 102 ++- lte/phy/examples/scan_mib.c | 8 +- .../include/liblte/phy/ch_estimation/chest.h | 122 ++- .../liblte/phy/ch_estimation/refsignal.h | 24 +- lte/phy/include/liblte/phy/channel/ch_awgn.h | 12 +- lte/phy/include/liblte/phy/common/fft.h | 30 +- .../include/liblte/phy/common/phy_common.h | 52 +- lte/phy/include/liblte/phy/common/sequence.h | 38 +- lte/phy/include/liblte/phy/phch/dci.h | 61 +- lte/phy/include/liblte/phy/phch/pbch.h | 21 +- lte/phy/include/liblte/phy/phch/pcfich.h | 29 +- lte/phy/include/liblte/phy/phch/pdcch.h | 77 +- lte/phy/include/liblte/phy/phch/pdsch.h | 44 +- lte/phy/include/liblte/phy/phch/phich.h | 41 +- lte/phy/include/liblte/phy/phch/prach.h | 2 +- lte/phy/include/liblte/phy/phch/regs.h | 82 +- lte/phy/include/liblte/phy/phy.h | 1 - lte/phy/include/liblte/phy/sync/sync_frame.h | 1 + lte/phy/lib/ch_estimation/src/chest.c | 305 +++---- lte/phy/lib/ch_estimation/src/refsignal.c | 159 ++-- lte/phy/lib/ch_estimation/test/chest_test.c | 58 +- lte/phy/lib/common/src/phy_common.c | 15 + lte/phy/lib/common/src/sequence.c | 21 +- lte/phy/lib/phch/src/dci.c | 132 +-- lte/phy/lib/phch/src/pcfich.c | 242 +++--- lte/phy/lib/phch/src/pdcch.c | 646 ++++++++------- lte/phy/lib/phch/src/pdsch.c | 753 +++++++++--------- lte/phy/lib/phch/src/phich.c | 150 ++-- lte/phy/lib/phch/src/regs.c | 301 +++---- lte/phy/lib/phch/src/sequences.c | 14 +- lte/phy/lib/phch/test/pbch_file_test.c | 47 +- lte/phy/lib/phch/test/pcfich_file_test.c | 64 +- lte/phy/lib/phch/test/pcfich_test.c | 39 +- lte/phy/lib/phch/test/pdcch_file_test.c | 74 +- lte/phy/lib/phch/test/pdcch_test.c | 51 +- lte/phy/lib/phch/test/pdsch_file_test.c | 90 +-- lte/phy/lib/phch/test/pdsch_re_test.c | 12 +- lte/phy/lib/phch/test/pdsch_test.c | 46 +- lte/phy/lib/phch/test/phich_file_test.c | 55 +- lte/phy/lib/phch/test/phich_test.c | 49 +- lte/phy/lib/sync/src/sync_frame.c | 5 + 45 files changed, 2327 insertions(+), 1802 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index c8f92b065..73195b1d5 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -77,7 +77,7 @@ IF(CMAKE_COMPILER_IS_GNUCXX) ENDIF(CMAKE_COMPILER_IS_GNUCXX) IF(CMAKE_COMPILER_IS_GNUCC) - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Wall -Wno-format-extra-args -Winline -Wno-unused-result -Wno-format -std=c99 -D_GNU_SOURCE") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -Werror -Wall -Wno-format-extra-args -Winline -Wno-unused-result -Wno-format -std=c99 -D_GNU_SOURCE") IF(NOT WIN32) ADD_CXX_COMPILER_FLAG_IF_AVAILABLE(-fvisibility=hidden HAVE_VISIBILITY_HIDDEN) ENDIF(NOT WIN32) diff --git a/lte/phy/examples/pbch_enodeb.c b/lte/phy/examples/pbch_enodeb.c index 1d7a62801..7be23a2b7 100644 --- a/lte/phy/examples/pbch_enodeb.c +++ b/lte/phy/examples/pbch_enodeb.c @@ -211,8 +211,14 @@ int main(int argc, char **argv) { sss_generate(sss_signal0, sss_signal5, cell_id); /* Generate CRS signals */ + lte_cell_t cell; + cell.id = cell_id; + cell.nof_prb = 6; + cell.cp = CPNORM; + cell.nof_ports = 1; + for (i=0;i sampling_nof_prb) { + if (!lte_cell_isvalid(&cell)) { + fprintf(stderr, "Invalid cell properties: Id=%d, Ports=%d, PRBs=%d\n", + cell.id, cell.nof_ports, cell.nof_prb); + return -1; + } + if (cell.nof_prb > sampling_nof_prb) { fprintf(stderr, "Error sampling frequency is %.2f Mhz but captured signal has %d PRB\n", - (float) lte_sampling_freq_hz(sampling_nof_prb)/MHZ, mib.nof_prb); + (float) lte_sampling_freq_hz(sampling_nof_prb)/MHZ, cell.nof_prb); return -1; } - if (regs_init(®s, cell_id, mib.nof_prb, mib.nof_ports, - mib.phich_resources, mib.phich_length, CPNORM)) { - fprintf(stderr, "Error initiating regs\n"); + if (regs_init(®s, phich_resources, phich_length, cell)) { + fprintf(stderr, "Error initiating REGs\n"); return -1; } - if (pcfich_init(&pcfich, ®s, cell_id, mib.nof_prb, mib.nof_ports, CPNORM)) { + if (pcfich_init(&pcfich, ®s, cell)) { fprintf(stderr, "Error creating PCFICH object\n"); return -1; } - if (pdcch_init(&pdcch, ®s, mib.nof_prb, mib.nof_ports, cell_id, CPNORM)) { + if (pdcch_init(&pdcch, ®s, cell)) { fprintf(stderr, "Error creating PDCCH object\n"); return -1; } - if (pdsch_init(&pdsch, 1234, mib.nof_prb, mib.nof_ports, cell_id, CPNORM)) { + if (pdsch_init(&pdsch, 1234, cell)) { fprintf(stderr, "Error creating PDSCH object\n"); return -1; } - chest_set_nof_ports(&chest, mib.nof_ports); + chest_set_nof_ports(&chest, cell.nof_ports); mib_initiated = 1; - DEBUG("Receiver initiated cell_id=%d nof_prb=%d\n", cell_id, mib.nof_prb); + DEBUG("Receiver initiated cell.id=%d nof_prb=%d\n", cell.id, cell.nof_prb); return 0; } int cell_id_init(int nof_prb, int cell_id) { - if (chest_ref_LTEDL(&chest, cell_id)) { + lte_cell_t cell; + + cell.id = cell_id; + cell.nof_prb = 6; + cell.nof_ports = MAX_PORTS; + cell.cp = CPNORM; + + if (chest_ref_LTEDL(&chest, cell)) { fprintf(stderr, "Error initializing reference signal\n"); return -1; } @@ -373,14 +384,15 @@ int cell_id_init(int nof_prb, int cell_id) { char data[10000]; int rx_run(cf_t *input, int sf_idx) { - int cfi, i, cfi_distance, nof_dcis; + uint8_t cfi, cfi_distance; + int i, nof_dcis; cf_t *input_decim; ra_pdsch_t ra_dl; ra_prb_t prb_alloc; /* Downsample if the signal bandwith is shorter */ - if (sampling_nof_prb > mib.nof_prb) { - decim_c(input, input_decim_buffer, sf_n_samples, DOWNSAMPLE_FACTOR(sampling_nof_prb, mib.nof_prb)); + if (sampling_nof_prb > cell.nof_prb) { + decim_c(input, input_decim_buffer, sf_n_samples, DOWNSAMPLE_FACTOR(sampling_nof_prb, cell.nof_prb)); input_decim = input_decim_buffer; } else { input_decim = input; @@ -402,18 +414,15 @@ int rx_run(cf_t *input, int sf_idx) { fprintf(stderr, "Error setting CFI\n"); return -1; } - if (pdcch_set_cfi(&pdcch, cfi)) { - fprintf(stderr, "Error setting CFI\n"); - return -1; - } - pdcch_init_search_ue(&pdcch, 1234); + + pdcch_init_search_ue(&pdcch, 1234, cfi); dci_set.nof_dcis = 0; - nof_dcis = pdcch_decode(&pdcch, fft_buffer, ce, &dci_set, sf_idx); + nof_dcis = pdcch_decode(&pdcch, fft_buffer, ce, &dci_set, sf_idx, cfi); INFO("Received %d DCIs\n", nof_dcis); for (i=0;i 0) { - int n_re = 2 * RE_X_RB * CPNORM_NSYMB * mib.nof_prb; + int n_re = 2 * RE_X_RB * CPNORM_NSYMB * cell.nof_prb; for (i = 0; i < n_re; i++) { tmp_plot[i] = 10 * log10f(cabsf(fft_buffer[i])); if (isinf(tmp_plot[i])) { @@ -472,7 +481,7 @@ int rx_run(cf_t *input, int sf_idx) { return 0; } -int mib_decoder_run(cf_t *input) { +int mib_decoder_run(cf_t *input, pbch_mib_t *mib) { int i, n; lte_fft_run_slot(&fft, input, fft_buffer); @@ -483,23 +492,30 @@ int mib_decoder_run(cf_t *input) { } DEBUG("Decoding PBCH\n", 0); - n = pbch_decode(&pbch, fft_buffer, ce, &mib); + n = pbch_decode(&pbch, fft_buffer, ce, mib); return n; } int run_receiver(cf_t *input, int cell_id, int sf_idx) { - + pbch_mib_t mib; + if (!cell_id_initated) { cell_id_init(sampling_nof_prb, cell_id); } - if (!mib.nof_prb) { + if (!cell.nof_prb) { if (!sf_idx) { - if (mib_decoder_run(&input[sf_n_samples/2])) { + if (mib_decoder_run(&input[sf_n_samples/2], &mib)) { INFO("MIB decoded!\n", 0); + cell.id = cell_id; + cell.cp = CPNORM; + cell.nof_ports = mib.nof_ports; + cell.nof_prb = mib.nof_prb; + subframe_number = mib.sfn; + if (!mib_initiated) { - if (mib_init(cell_id)) { + if (mib_init(mib.phich_resources, mib.phich_length)) { return -1; } } @@ -511,7 +527,7 @@ int run_receiver(cf_t *input, int cell_id, int sf_idx) { } } } - if (mib.nof_prb) { + if (cell.nof_prb) { if (rx_run(input, sf_idx)) { return -1; } @@ -566,7 +582,7 @@ void read_io(cf_t *buffer, int nsamples) { } int main(int argc, char **argv) { - + #ifdef DISABLE_UHD if (argc < 3) { usage(argv[0]); @@ -590,8 +606,8 @@ int main(int argc, char **argv) { signal(SIGINT, sigintHandler); /* Initialize variables */ - mib.sfn = -1; frame_cnt = 0; + subframe_number = -1; /* The number of samples read from the USRP or file corresponds to 1 ms (subframe) */ sf_n_samples = 1920 * lte_symbol_sz(sampling_nof_prb)/128; @@ -608,7 +624,7 @@ int main(int argc, char **argv) { break; case 1: if (!(frame_cnt%10)) { - mib.sfn++; + subframe_number++; } /* synch'd and tracking */ if (run_receiver(sf_buffer, sync_frame_cell_id(&sframe), sync_frame_sfidx(&sframe))) { @@ -617,7 +633,7 @@ int main(int argc, char **argv) { if (!(frame_cnt % 10)) { printf( "SFN: %4d, CFO: %+.4f KHz, SFO: %+.4f Khz, TimeOffset: %4d, Errors: %4d/%4d, BLER: %.1e\r", - mib.sfn, sframe.cur_cfo * 15, sframe.timeoffset / 5, sframe.peak_idx, + subframe_number, sframe.cur_cfo * 15, sframe.timeoffset / 5, sframe.peak_idx, pdsch_errors, pdsch_total, (float) pdsch_errors / pdsch_total); fflush(stdout); diff --git a/lte/phy/examples/scan_mib.c b/lte/phy/examples/scan_mib.c index 600a635f7..b22dcde49 100644 --- a/lte/phy/examples/scan_mib.c +++ b/lte/phy/examples/scan_mib.c @@ -311,7 +311,13 @@ int rssi_scan() { int mib_decoder_init(int cell_id) { - if (chest_ref_LTEDL(&chest, cell_id)) { + lte_cell_t cell; + cell.id = cell_id; + cell.nof_prb = 6; + cell.nof_ports = MAX_PORTS; + cell.cp = CPNORM; + + if (chest_ref_LTEDL(&chest, cell)) { fprintf(stderr, "Error initializing reference signal\n"); return -1; } diff --git a/lte/phy/include/liblte/phy/ch_estimation/chest.h b/lte/phy/include/liblte/phy/ch_estimation/chest.h index db99dacbf..2d4707870 100644 --- a/lte/phy/include/liblte/phy/ch_estimation/chest.h +++ b/lte/phy/include/liblte/phy/ch_estimation/chest.h @@ -40,7 +40,12 @@ typedef _Complex float cf_t; /* this is only a shortcut */ typedef enum {LINEAR} chest_interp_t; -typedef void (*interpolate_fnc_t) (cf_t *input, cf_t *output, int M, int len, int off_st, int off_end); +typedef void (*interpolate_fnc_t) (cf_t *input, + cf_t *output, + int M, + int len, + int off_st, + int off_end); /** This is an OFDM channel estimator. * It works with any reference signal pattern, provided by the object @@ -50,34 +55,94 @@ typedef void (*interpolate_fnc_t) (cf_t *input, cf_t *output, int M, int len, in */ /* Low-level API */ -typedef struct LIBLTE_API{ - int nof_ports; - int nof_symbols; - int nof_prb; - lte_cp_t cp; +typedef struct LIBLTE_API { + uint8_t nof_ports; + uint16_t nof_re; + uint8_t nof_symbols; + refsignal_t refsignal[MAX_PORTS][NSLOTS_X_FRAME]; interpolate_fnc_t interp; }chest_t; -LIBLTE_API int chest_init(chest_t *q, chest_interp_t interp, lte_cp_t cp, int nof_prb, int nof_ports); -LIBLTE_API void chest_free(chest_t *q); -LIBLTE_API void chest_set_nof_ports(chest_t *q, int nof_ports); - -LIBLTE_API int chest_ref_LTEDL_slot_port(chest_t *q, int port, int nslot, int cell_id); -LIBLTE_API int chest_ref_LTEDL_slot(chest_t *q, int nslot, int cell_id); -LIBLTE_API int chest_ref_LTEDL(chest_t *q, int cell_id); +LIBLTE_API int chest_init(chest_t *q, + chest_interp_t interp, + uint16_t nof_re, + uint8_t nof_symbols, + uint8_t nof_ports); -LIBLTE_API void chest_ce_ref(chest_t *q, cf_t *input, int nslot, int port_id, int nref); -LIBLTE_API void chest_ce_slot_port(chest_t *q, cf_t *input, cf_t *ce, int nslot, int port_id); -LIBLTE_API void chest_ce_sf_port(chest_t *q, cf_t *input, cf_t *ce, int sf_idx, int port_id); -LIBLTE_API void chest_ce_slot(chest_t *q, cf_t *input, cf_t *ce[MAX_PORTS], int nslot); -LIBLTE_API void chest_ce_sf(chest_t *q, cf_t *input, cf_t *ce[MAX_PORTS], int sf_idx); +LIBLTE_API void chest_free(chest_t *q); -LIBLTE_API void chest_fprint(chest_t *q, FILE *stream, int nslot, int port_id); -LIBLTE_API void chest_ref_fprint(chest_t *q, FILE *stream, int nslot, int port_id); -LIBLTE_API void chest_recvsig_fprint(chest_t *q, FILE *stream, int nslot, int port_id); -LIBLTE_API void chest_ce_fprint(chest_t *q, FILE *stream, int nslot, int port_id); -LIBLTE_API int chest_ref_symbols(chest_t *q, int port_id, int nslot, int l[2]); +LIBLTE_API int chest_set_nof_ports(chest_t *q, + uint8_t nof_ports); + +LIBLTE_API int chest_init_LTEDL(chest_t *q, + chest_interp_t interp, + lte_cell_t cell); + +LIBLTE_API int chest_ref_LTEDL_slot_port(chest_t *q, + uint8_t nslot, + uint8_t port_id, + lte_cell_t cell); + +LIBLTE_API int chest_ref_LTEDL_slot(chest_t *q, + uint8_t nslot, + lte_cell_t cell); + +LIBLTE_API int chest_ref_LTEDL(chest_t *q, + lte_cell_t cell); + +LIBLTE_API int chest_ce_ref(chest_t *q, + cf_t *input, + uint8_t nslot, + uint8_t port_id, + uint16_t nref); + +LIBLTE_API int chest_ce_slot_port(chest_t *q, + cf_t *input, + cf_t *ce, + uint8_t nslot, + uint8_t port_id); + +LIBLTE_API int chest_ce_sf_port(chest_t *q, + cf_t *input, + cf_t *ce, + uint8_t sf_idx, + uint8_t port_id); + +LIBLTE_API int chest_ce_slot(chest_t *q, + cf_t *input, + cf_t *ce[MAX_PORTS], + uint8_t nslot); + +LIBLTE_API int chest_ce_sf(chest_t *q, + cf_t *input, + cf_t *ce[MAX_PORTS], + uint8_t sf_idx); + +LIBLTE_API void chest_fprint(chest_t *q, + FILE *stream, + uint8_t nslot, + uint8_t port_id); + +LIBLTE_API void chest_ref_fprint(chest_t *q, + FILE *stream, + uint8_t nslot, + uint8_t port_id); + +LIBLTE_API void chest_recvsig_fprint(chest_t *q, + FILE *stream, + uint8_t nslot, + uint8_t port_id); + +LIBLTE_API void chest_ce_fprint(chest_t *q, + FILE *stream, + uint8_t nslot, + uint8_t port_id); + +LIBLTE_API int chest_ref_symbols(chest_t *q, + uint8_t port_id, + uint8_t nslot, + uint8_t l[2]); /* High-level API */ @@ -94,8 +159,7 @@ typedef struct LIBLTE_API{ cf_t *input; int in_len; struct chest_ctrl_in { - int slot_id; // slot id in the 10ms frame - int cell_id; + int sf_idx; // subframe id in the 10ms frame } ctrl_in; cf_t *output[MAX_PORTS]; int out_len[MAX_PORTS]; @@ -108,3 +172,11 @@ LIBLTE_API int chest_work(chest_hl* hl); LIBLTE_API int chest_stop(chest_hl* hl); #endif + + + + + + + + diff --git a/lte/phy/include/liblte/phy/ch_estimation/refsignal.h b/lte/phy/include/liblte/phy/ch_estimation/refsignal.h index 7b1f6518a..c6ef8d859 100644 --- a/lte/phy/include/liblte/phy/ch_estimation/refsignal.h +++ b/lte/phy/include/liblte/phy/ch_estimation/refsignal.h @@ -43,26 +43,30 @@ typedef _Complex float cf_t; typedef struct LIBLTE_API{ - int time_idx; - int freq_idx; + uint8_t time_idx; + uint16_t freq_idx; cf_t simbol; cf_t recv_simbol; }ref_t; typedef struct LIBLTE_API{ - int nof_refs; // number of reference signals - int *symbols_ref; // symbols with at least one reference - int nsymbols; // number of symbols with at least one reference - int voffset; // offset of the first reference in the freq domain - int nof_prb; + uint16_t nof_refs; // number of reference signals + uint8_t *symbols_ref; // symbols with at least one reference + uint8_t nsymbols; // number of symbols with at least one reference + uint8_t voffset; // offset of the first reference in the freq domain + uint16_t nof_prb; ref_t *refs; cf_t *ch_est; } refsignal_t; -LIBLTE_API int refsignal_init_LTEDL(refsignal_t *q, int port_id, int nslot, - int cell_id, lte_cp_t cp, int nof_prb); +LIBLTE_API int refsignal_init_LTEDL(refsignal_t *q, + uint8_t port_id, + uint8_t nslot, + lte_cell_t cell); + LIBLTE_API void refsignal_free(refsignal_t *q); -LIBLTE_API void refsignal_put(refsignal_t *q, cf_t *slot_symbols); +LIBLTE_API int refsignal_put(refsignal_t *q, + cf_t *slot_symbols); #endif diff --git a/lte/phy/include/liblte/phy/channel/ch_awgn.h b/lte/phy/include/liblte/phy/channel/ch_awgn.h index 19a452cb1..fa209dfe3 100644 --- a/lte/phy/include/liblte/phy/channel/ch_awgn.h +++ b/lte/phy/include/liblte/phy/channel/ch_awgn.h @@ -34,8 +34,16 @@ typedef _Complex float cf_t; -LIBLTE_API void ch_awgn_c(const cf_t* input, cf_t* output, float variance, int buff_sz); -LIBLTE_API void ch_awgn_f(const float* x, float* y, float variance, int buff_sz); +LIBLTE_API void ch_awgn_c(const cf_t* input, + cf_t* output, + float variance, + int buff_sz); + +LIBLTE_API void ch_awgn_f(const float* x, + float* y, + float variance, + int buff_sz); + /* High-level API */ diff --git a/lte/phy/include/liblte/phy/common/fft.h b/lte/phy/include/liblte/phy/common/fft.h index 1c89ae09b..048bd37dc 100644 --- a/lte/phy/include/liblte/phy/common/fft.h +++ b/lte/phy/include/liblte/phy/common/fft.h @@ -51,14 +51,32 @@ typedef struct LIBLTE_API{ cf_t *tmp; // for removing zero padding }lte_fft_t; -LIBLTE_API int lte_fft_init(lte_fft_t *q, lte_cp_t cp_type, int nof_prb); +LIBLTE_API int lte_fft_init(lte_fft_t *q, + lte_cp_t cp_type, + int nof_prb); + LIBLTE_API void lte_fft_free(lte_fft_t *q); -LIBLTE_API void lte_fft_run_slot(lte_fft_t *q, cf_t *input, cf_t *output); -LIBLTE_API void lte_fft_run_sf(lte_fft_t *q, cf_t *input, cf_t *output); -LIBLTE_API int lte_ifft_init(lte_fft_t *q, lte_cp_t cp_type, int nof_prb); +LIBLTE_API void lte_fft_run_slot(lte_fft_t *q, + cf_t *input, + cf_t *output); + +LIBLTE_API void lte_fft_run_sf(lte_fft_t *q, + cf_t *input, + cf_t *output); + +LIBLTE_API int lte_ifft_init(lte_fft_t *q, + lte_cp_t cp_type, + int nof_prb); + LIBLTE_API void lte_ifft_free(lte_fft_t *q); -LIBLTE_API void lte_ifft_run_slot(lte_fft_t *q, cf_t *input, cf_t *output); -LIBLTE_API void lte_ifft_run_sf(lte_fft_t *q, cf_t *input, cf_t *output); + +LIBLTE_API void lte_ifft_run_slot(lte_fft_t *q, + cf_t *input, + cf_t *output); + +LIBLTE_API void lte_ifft_run_sf(lte_fft_t *q, + cf_t *input, + cf_t *output); #endif diff --git a/lte/phy/include/liblte/phy/common/phy_common.h b/lte/phy/include/liblte/phy/common/phy_common.h index c553a7c51..5fcdbb176 100644 --- a/lte/phy/include/liblte/phy/common/phy_common.h +++ b/lte/phy/include/liblte/phy/common/phy_common.h @@ -29,6 +29,8 @@ #ifndef _LTEBASE_ #define _LTEBASE_ +#include +#include #include "liblte/config.h" #define NSUBFRAMES_X_FRAME 10 @@ -100,23 +102,17 @@ typedef enum {CPNORM, CPEXT} lte_cp_t; || l == CP_NSYMB(cp) - 3) -LIBLTE_API const int lte_symbol_sz(int nof_prb); -LIBLTE_API const int lte_sampling_freq_hz(int nof_prb); -LIBLTE_API int lte_re_x_prb(int ns, int symbol, int nof_ports, int nof_symbols); -LIBLTE_API int lte_voffset(int symbol_id, int cell_id, int nof_ports); - #define NOF_LTE_BANDS 29 #define NOF_TC_CB_SIZES 188 typedef struct LIBLTE_API { - int nof_prb; - int nof_ports; - int cell_id; + uint8_t nof_prb; + uint8_t nof_ports; + uint16_t id; lte_cp_t cp; }lte_cell_t; - typedef enum LIBLTE_API { SINGLE_ANTENNA,TX_DIVERSITY, SPATIAL_MULTIPLEX } lte_mimo_type_t; @@ -134,16 +130,46 @@ LIBLTE_API enum band_geographical_area { ALL, NAR, APAC, EMEA, JAPAN, CALA, NA }; +LIBLTE_API bool lte_cell_isvalid(lte_cell_t *cell); + +LIBLTE_API const int lte_symbol_sz(int nof_prb); + +LIBLTE_API const int lte_sampling_freq_hz(int nof_prb); + +LIBLTE_API int lte_re_x_prb(int ns, + int symbol, + int nof_ports, + int nof_symbols); + +LIBLTE_API int lte_voffset(int symbol_id, + int cell_id, + int nof_ports); + LIBLTE_API int lte_cb_size(int index); + LIBLTE_API int lte_find_cb_index(int long_cb); LIBLTE_API float lte_band_fd(int earfcn); -LIBLTE_API int lte_band_get_fd_band(int band, lte_earfcn_t *earfcn, int earfcn_start, int earfcn_end, int max_elems); -LIBLTE_API int lte_band_get_fd_band_all(int band, lte_earfcn_t *earfcn, int max_nelems); -LIBLTE_API int lte_band_get_fd_region(enum band_geographical_area region, lte_earfcn_t *earfcn, int max_elems); -LIBLTE_API int lte_str2mimotype(char *mimo_type_str, lte_mimo_type_t *type); +LIBLTE_API int lte_band_get_fd_band(int band, + lte_earfcn_t *earfcn, + int earfcn_start, + int earfcn_end, + int max_elems); + +LIBLTE_API int lte_band_get_fd_band_all(int band, + lte_earfcn_t *earfcn, + int max_nelems); + +LIBLTE_API int lte_band_get_fd_region(enum band_geographical_area region, + lte_earfcn_t *earfcn, + int max_elems); + +LIBLTE_API int lte_str2mimotype(char *mimo_type_str, + lte_mimo_type_t *type); + LIBLTE_API char *lte_mimotype2str(lte_mimo_type_t type); + #endif diff --git a/lte/phy/include/liblte/phy/common/sequence.h b/lte/phy/include/liblte/phy/common/sequence.h index 0fb52df2f..f237ac20c 100644 --- a/lte/phy/include/liblte/phy/common/sequence.h +++ b/lte/phy/include/liblte/phy/common/sequence.h @@ -33,19 +33,39 @@ typedef struct LIBLTE_API { char *c; - int len; + uint32_t len; } sequence_t; -LIBLTE_API int sequence_init(sequence_t *q, int len); +LIBLTE_API int sequence_init(sequence_t *q, uint32_t len); + LIBLTE_API void sequence_free(sequence_t *q); -LIBLTE_API int sequence_LTEPRS(sequence_t *q, int len, int seed); +LIBLTE_API int sequence_LTEPRS(sequence_t *q, + uint32_t len, + uint32_t seed); + +LIBLTE_API int sequence_pbch(sequence_t *seq, + lte_cp_t cp, + uint16_t cell_id); + +LIBLTE_API int sequence_pcfich(sequence_t *seq, + uint8_t nslot, + uint16_t cell_id); + +LIBLTE_API int sequence_phich(sequence_t *seq, + uint8_t nslot, + uint16_t cell_id); + +LIBLTE_API int sequence_pdcch(sequence_t *seq, + uint8_t nslot, + uint16_t cell_id, + uint32_t len); -LIBLTE_API int sequence_pbch(sequence_t *seq, lte_cp_t cp, int cell_id); -LIBLTE_API int sequence_pcfich(sequence_t *seq, int nslot, int cell_id); -LIBLTE_API int sequence_phich(sequence_t *seq, int nslot, int cell_id); -LIBLTE_API int sequence_pdcch(sequence_t *seq, int nslot, int cell_id, int len); -LIBLTE_API int sequence_pdsch(sequence_t *seq, unsigned short rnti, int q, - int nslot, int cell_id, int len); +LIBLTE_API int sequence_pdsch(sequence_t *seq, + unsigned short rnti, + int q, + uint8_t nslot, + uint16_t cell_id, + uint32_t len); #endif diff --git a/lte/phy/include/liblte/phy/phch/dci.h b/lte/phy/include/liblte/phy/phch/dci.h index eb6b8afd3..23137e214 100644 --- a/lte/phy/include/liblte/phy/phch/dci.h +++ b/lte/phy/include/liblte/phy/phch/dci.h @@ -62,10 +62,10 @@ typedef enum { } dci_spec_t; typedef struct LIBLTE_API { - unsigned char nof_bits; - unsigned char L; // Aggregation level - unsigned char ncce; // Position of first CCE of the dci - unsigned short rnti; + uint8_t nof_bits; + uint8_t L; // Aggregation level + uint8_t ncce; // Position of first CCE of the dci + uint16_t rnti; } dci_candidate_t; typedef struct LIBLTE_API { @@ -75,28 +75,55 @@ typedef struct LIBLTE_API { typedef struct LIBLTE_API { dci_msg_t *msg; - int nof_dcis; - int max_dcis; + uint8_t nof_dcis; + uint8_t max_dcis; } dci_t; -LIBLTE_API int dci_init(dci_t *q, int max_dci); +LIBLTE_API int dci_init(dci_t *q, + uint8_t max_dci); + LIBLTE_API void dci_free(dci_t *q); + LIBLTE_API char* dci_format_string(dci_format_t format); -LIBLTE_API int dci_msg_candidate_set(dci_msg_t *msg, int L, int nCCE, unsigned short rnti); -LIBLTE_API void dci_candidate_fprint(FILE *f, dci_candidate_t *q); +LIBLTE_API int dci_msg_candidate_set(dci_msg_t *msg, + uint8_t L, + uint8_t nCCE, + uint16_t rnti); + +LIBLTE_API void dci_candidate_fprint(FILE *f, + dci_candidate_t *q); -LIBLTE_API int dci_msg_get_type(dci_msg_t *msg, dci_msg_type_t *type, int nof_prb, unsigned short crnti); -LIBLTE_API void dci_msg_type_fprint(FILE *f, dci_msg_type_t type); +LIBLTE_API int dci_msg_get_type(dci_msg_t *msg, + dci_msg_type_t *type, + uint8_t nof_prb, + uint16_t crnti); + +LIBLTE_API void dci_msg_type_fprint(FILE *f, + dci_msg_type_t type); // For dci_msg_type_t = PUSCH_SCHED -LIBLTE_API int dci_msg_pack_pusch(ra_pusch_t *data, dci_msg_t *msg, int nof_prb); -LIBLTE_API int dci_msg_unpack_pusch(dci_msg_t *msg, ra_pusch_t *data, int nof_prb); +LIBLTE_API int dci_msg_pack_pusch(ra_pusch_t *data, + dci_msg_t *msg, + uint8_t nof_prb); -// For dci_msg_type_t = PDSCH_SCHED -LIBLTE_API int dci_msg_pack_pdsch(ra_pdsch_t *data, dci_msg_t *msg, dci_format_t format, int nof_prb, bool crc_is_crnti); -LIBLTE_API int dci_msg_unpack_pdsch(dci_msg_t *msg, ra_pdsch_t *data, int nof_prb, bool crc_is_crnti); +LIBLTE_API int dci_msg_unpack_pusch(dci_msg_t *msg, + ra_pusch_t *data, + uint8_t nof_prb); -LIBLTE_API int dci_format_sizeof(dci_format_t format, int nof_prb); +// For dci_msg_type_t = PDSCH_SCHED +LIBLTE_API int dci_msg_pack_pdsch(ra_pdsch_t *data, + dci_msg_t *msg, + dci_format_t format, + uint8_t nof_prb, + bool crc_is_crnti); + +LIBLTE_API int dci_msg_unpack_pdsch(dci_msg_t *msg, + ra_pdsch_t *data, + uint8_t nof_prb, + bool crc_is_crnti); + +LIBLTE_API uint8_t dci_format_sizeof(dci_format_t format, + uint8_t nof_prb); #endif // DCI_ diff --git a/lte/phy/include/liblte/phy/phch/pbch.h b/lte/phy/include/liblte/phy/phch/pbch.h index b3b146d4c..ac96c2174 100644 --- a/lte/phy/include/liblte/phy/phch/pbch.h +++ b/lte/phy/include/liblte/phy/phch/pbch.h @@ -85,12 +85,25 @@ typedef struct LIBLTE_API { }pbch_t; -LIBLTE_API int pbch_init(pbch_t *q, int nof_prb, int cell_id, lte_cp_t cp); +LIBLTE_API int pbch_init(pbch_t *q, + int nof_prb, + int cell_id, + lte_cp_t cp); + LIBLTE_API void pbch_free(pbch_t *q); -LIBLTE_API int pbch_decode(pbch_t *q, cf_t *slot1_symbols, cf_t *ce[MAX_PORTS], pbch_mib_t *mib); -LIBLTE_API void pbch_encode(pbch_t *q, pbch_mib_t *mib, cf_t *slot1_symbols[MAX_PORTS], int nof_ports); +LIBLTE_API int pbch_decode(pbch_t *q, + cf_t *slot1_symbols, + cf_t *ce[MAX_PORTS], + pbch_mib_t *mib); + +LIBLTE_API void pbch_encode(pbch_t *q, + pbch_mib_t *mib, + cf_t *slot1_symbols[MAX_PORTS], + int nof_ports); + LIBLTE_API void pbch_decode_reset(pbch_t *q); -LIBLTE_API void pbch_mib_fprint(FILE *stream, pbch_mib_t *mib); +LIBLTE_API void pbch_mib_fprint(FILE *stream, + pbch_mib_t *mib); #endif // PBCH_ diff --git a/lte/phy/include/liblte/phy/phch/pcfich.h b/lte/phy/include/liblte/phy/phch/pcfich.h index 68b487719..7e04267a0 100644 --- a/lte/phy/include/liblte/phy/phch/pcfich.h +++ b/lte/phy/include/liblte/phy/phch/pcfich.h @@ -45,11 +45,8 @@ typedef _Complex float cf_t; /* PCFICH object */ typedef struct LIBLTE_API { - int cell_id; - lte_cp_t cp; + lte_cell_t cell; int nof_symbols; - int nof_prb; - int nof_ports; /* handler to REGs resource mapper */ regs_t *regs; @@ -70,16 +67,22 @@ typedef struct LIBLTE_API { } pcfich_t; -LIBLTE_API int pcfich_init(pcfich_t *q, regs_t *regs, int cell_id, int nof_prb, - int nof_tx_ports, lte_cp_t cp); +LIBLTE_API int pcfich_init(pcfich_t *q, + regs_t *regs, + lte_cell_t cell); + LIBLTE_API void pcfich_free(pcfich_t *q); -LIBLTE_API int pcfich_decode(pcfich_t *q, cf_t *slot_symbols, cf_t *ce[MAX_PORTS], - int nsubframe, int *cfi, int *distance); -LIBLTE_API int pcfich_encode(pcfich_t *q, int cfi, cf_t *slot_symbols[MAX_PORTS], - int nsubframe); -LIBLTE_API bool pcfich_exists(int nframe, int nslot); -LIBLTE_API int pcfich_put(regs_t *h, cf_t *pcfich, cf_t *slot_data); -LIBLTE_API int pcfich_get(regs_t *h, cf_t *pcfich, cf_t *slot_data); +LIBLTE_API int pcfich_decode(pcfich_t *q, + cf_t *sf_symbols, + cf_t *ce[MAX_PORTS], + uint8_t subframe, + uint8_t *cfi, + uint8_t *distance); + +LIBLTE_API int pcfich_encode(pcfich_t *q, + uint8_t cfi, + cf_t *sf_symbols[MAX_PORTS], + uint8_t subframe); #endif diff --git a/lte/phy/include/liblte/phy/phch/pdcch.h b/lte/phy/include/liblte/phy/phch/pdcch.h index b44a00a56..cbcf7824c 100644 --- a/lte/phy/include/liblte/phy/phch/pdcch.h +++ b/lte/phy/include/liblte/phy/phch/pdcch.h @@ -56,20 +56,18 @@ typedef enum LIBLTE_API { * DCI messages as defined in Section 7.1 of 36.213 */ typedef struct LIBLTE_API { - int nof_candidates; + uint8_t nof_candidates; dci_candidate_t candidates[NSUBFRAMES_X_FRAME][MAX_CANDIDATES]; } pdcch_search_t; /* PDCCH object */ typedef struct LIBLTE_API { - int cell_id; - lte_cp_t cp; - int nof_prb; - int nof_bits; - int nof_symbols; - int nof_ports; - int nof_regs; - int nof_cce; + lte_cell_t cell; + uint16_t nof_bits; + uint16_t nof_symbols; + uint16_t nof_regs; + uint16_t nof_cce; + uint16_t max_bits; pdcch_search_t search_mode[PDCCH_NOF_SEARCH_MODES]; pdcch_search_mode_t current_search_mode; @@ -92,15 +90,19 @@ typedef struct LIBLTE_API { crc_t crc; } pdcch_t; -LIBLTE_API int pdcch_init(pdcch_t *q, regs_t *regs, int nof_prb, int nof_ports, - int cell_id, lte_cp_t cp); +LIBLTE_API int pdcch_init(pdcch_t *q, + regs_t *regs, + lte_cell_t cell); + LIBLTE_API void pdcch_free(pdcch_t *q); -LIBLTE_API int pdcch_set_cfi(pdcch_t *q, int cfi); /* Encoding functions */ -LIBLTE_API int pdcch_encode(pdcch_t *q, dci_t *dci, cf_t *slot_symbols[MAX_PORTS], - int nsubframe); +LIBLTE_API int pdcch_encode(pdcch_t *q, + dci_t *dci, + cf_t *slot_symbols[MAX_PORTS], + uint8_t nsubframe, + uint8_t cfi); /* Decoding functions */ @@ -109,21 +111,48 @@ LIBLTE_API int pdcch_encode(pdcch_t *q, dci_t *dci, cf_t *slot_symbols[MAX_PORTS * b) call pdcch_extract_llr() and then call pdcch_decode_si/ue/ra */ -LIBLTE_API int pdcch_decode(pdcch_t *q, cf_t *slot_symbols, cf_t *ce[MAX_PORTS], - dci_t *dci, int nsubframe); -LIBLTE_API int pdcch_extract_llr(pdcch_t *q, cf_t *slot_symbols, cf_t *ce[MAX_PORTS], - float *llr, int nsubframe); +LIBLTE_API int pdcch_decode(pdcch_t *q, + cf_t *slot_symbols, + cf_t *ce[MAX_PORTS], + dci_t *dci, + uint8_t nsubframe, + uint8_t cfi); + +LIBLTE_API int pdcch_extract_llr(pdcch_t *q, + cf_t *slot_symbols, + cf_t *ce[MAX_PORTS], + float *llr, + uint8_t nsubframe, + uint8_t cfi); + +LIBLTE_API int pdcch_init_search_si(pdcch_t *q, + uint8_t cfi); -LIBLTE_API void pdcch_init_search_si(pdcch_t *q); LIBLTE_API void pdcch_set_search_si(pdcch_t *q); -LIBLTE_API int pdcch_decode_si(pdcch_t *q, float *llr, dci_t *dci); -LIBLTE_API void pdcch_init_search_ue(pdcch_t *q, unsigned short c_rnti); +LIBLTE_API int pdcch_decode_si(pdcch_t *q, + float *llr, + dci_t *dci); + +LIBLTE_API int pdcch_init_search_ue(pdcch_t *q, + uint16_t c_rnti, + uint8_t cfi); + LIBLTE_API void pdcch_set_search_ue(pdcch_t *q); -LIBLTE_API int pdcch_decode_ue(pdcch_t *q, float *llr, dci_t *dci, int nsubframe); -LIBLTE_API void pdcch_init_search_ra(pdcch_t *q, unsigned short ra_rnti); +LIBLTE_API int pdcch_decode_ue(pdcch_t *q, + float *llr, + dci_t *dci, + uint8_t nsubframe); + +LIBLTE_API int pdcch_init_search_ra(pdcch_t *q, + uint16_t ra_rnti, + uint8_t cfi); + LIBLTE_API void pdcch_set_search_ra(pdcch_t *q); -LIBLTE_API int pdcch_decode_ra(pdcch_t *q, float *llr, dci_t *dci); + +LIBLTE_API int pdcch_decode_ra(pdcch_t *q, + float *llr, + dci_t *dci); #endif diff --git a/lte/phy/include/liblte/phy/phch/pdsch.h b/lte/phy/include/liblte/phy/phch/pdsch.h index 8f2ce7504..9f7ac40cc 100644 --- a/lte/phy/include/liblte/phy/phch/pdsch.h +++ b/lte/phy/include/liblte/phy/phch/pdsch.h @@ -49,12 +49,10 @@ typedef _Complex float cf_t; /* PDSCH object */ typedef struct LIBLTE_API { - int cell_id; - lte_cp_t cp; - int nof_prb; - int nof_ports; - int max_symbols; - unsigned short rnti; + lte_cell_t cell; + + uint16_t max_symbols; + uint16_t rnti; /* buffers */ cf_t *ce[MAX_PORTS]; @@ -78,17 +76,31 @@ typedef struct LIBLTE_API { crc_t crc_cb; }pdsch_t; -LIBLTE_API int pdsch_init(pdsch_t *q, unsigned short user_rnti, int nof_prb, - int nof_ports, int cell_id, lte_cp_t cp); +LIBLTE_API int pdsch_init(pdsch_t *q, + uint16_t user_rnti, + lte_cell_t cell); + LIBLTE_API void pdsch_free(pdsch_t *q); -LIBLTE_API int pdsch_encode(pdsch_t *q, char *data, cf_t *sf_symbols[MAX_PORTS], - int nsubframe, ra_mcs_t mcs, ra_prb_t *prb_alloc); -LIBLTE_API int pdsch_decode(pdsch_t *q, cf_t *sf_symbols, cf_t *ce[MAX_PORTS], - char *data, int nsubframe, ra_mcs_t mcs, ra_prb_t *prb_alloc); -LIBLTE_API int pdsch_get(pdsch_t *q, cf_t *sf_symbols, cf_t *pdsch_symbols, - ra_prb_t *prb_alloc, int nsubframe); -LIBLTE_API int pdsch_put(pdsch_t *q, cf_t *pdsch_symbols, cf_t *sf_symbols, - ra_prb_t *prb_alloc, int nsubframe); +LIBLTE_API int pdsch_encode(pdsch_t *q, + char *data, + cf_t *sf_symbols[MAX_PORTS], + uint8_t nsubframe, + ra_mcs_t mcs, + ra_prb_t *prb_alloc); + +LIBLTE_API int pdsch_decode(pdsch_t *q, + cf_t *sf_symbols, + cf_t *ce[MAX_PORTS], + char *data, + uint8_t nsubframe, + ra_mcs_t mcs, + ra_prb_t *prb_alloc); + +LIBLTE_API int pdsch_get(pdsch_t *q, + cf_t *sf_symbols, + cf_t *pdsch_symbols, + ra_prb_t *prb_alloc, + uint8_t subframe); #endif diff --git a/lte/phy/include/liblte/phy/phch/phich.h b/lte/phy/include/liblte/phy/phch/phich.h index 63b7a1b57..fad03467a 100644 --- a/lte/phy/include/liblte/phy/phch/phich.h +++ b/lte/phy/include/liblte/phy/phch/phich.h @@ -55,10 +55,8 @@ typedef _Complex float cf_t; /* phich object */ typedef struct LIBLTE_API { - lte_cp_t cp; - int nof_prb; - int nof_tx_ports; - + lte_cell_t cell; + /* handler to REGs resource mapper */ regs_t *regs; @@ -80,18 +78,31 @@ typedef struct LIBLTE_API { }phich_t; -LIBLTE_API int phich_init(phich_t *q, regs_t *regs, int cell_id, int nof_prb, int nof_tx_ports, lte_cp_t cp); -LIBLTE_API void phich_free(phich_t *q); -LIBLTE_API int phich_decode(phich_t *q, cf_t *slot_symbols, cf_t *ce[MAX_PORTS], - int ngroup, int nseq, int nsubframe, char *ack, int *distance); -LIBLTE_API int phich_encode(phich_t *q, char ack, int ngroup, int nseq, int nsubframe, - cf_t *slot_symbols[MAX_PORTS]); +LIBLTE_API int phich_init(phich_t *q, + regs_t *regs, + lte_cell_t cell); +LIBLTE_API void phich_free(phich_t *q); -LIBLTE_API void phich_reset(phich_t *q, cf_t *slot_symbols[MAX_PORTS]); -LIBLTE_API int phich_ngroups(phich_t *q); -LIBLTE_API bool phich_exists(int nframe, int nslot); -LIBLTE_API int phich_put(regs_t *h, cf_t *phich, cf_t *slot_data); -LIBLTE_API int phich_get(regs_t *h, cf_t *phich, cf_t *slot_data); +LIBLTE_API int phich_decode(phich_t *q, + cf_t *slot_symbols, + cf_t *ce[MAX_PORTS], + uint8_t ngroup, + uint8_t nseq, + uint8_t nsubframe, + char *ack, + uint8_t *distance); + +LIBLTE_API int phich_encode(phich_t *q, + char ack, + uint8_t ngroup, + uint8_t nseq, + uint8_t nsubframe, + cf_t *slot_symbols[MAX_PORTS]); + +LIBLTE_API void phich_reset(phich_t *q, + cf_t *slot_symbols[MAX_PORTS]); + +LIBLTE_API uint8_t phich_ngroups(phich_t *q); #endif // PHICH_ diff --git a/lte/phy/include/liblte/phy/phch/prach.h b/lte/phy/include/liblte/phy/phch/prach.h index b50e78b0d..4bdd08778 100644 --- a/lte/phy/include/liblte/phy/phch/prach.h +++ b/lte/phy/include/liblte/phy/phch/prach.h @@ -46,7 +46,7 @@ typedef _Complex float cf_t; * Based on 3GPP TS 36.211 version 10.7.0 Release 10. */ -typedef struct LIBLTE_API{ +typedef struct LIBLTE_API { // Parameters from higher layers (extracted from SIB2) uint32_t f; // preamble format uint32_t rsi; // rootSequenceIndex diff --git a/lte/phy/include/liblte/phy/phch/regs.h b/lte/phy/include/liblte/phy/phch/regs.h index 9a23474bc..61d289513 100644 --- a/lte/phy/include/liblte/phy/phch/regs.h +++ b/lte/phy/include/liblte/phy/phch/regs.h @@ -45,57 +45,79 @@ typedef _Complex float cf_t; typedef struct LIBLTE_API { - int k[4]; - int k0; - int l; + uint16_t k[4]; + uint16_t k0; + uint8_t l; bool assigned; }regs_reg_t; typedef struct LIBLTE_API { - int nof_regs; + uint16_t nof_regs; regs_reg_t **regs; }regs_ch_t; typedef struct LIBLTE_API { - int cell_id; - int nof_prb; - int max_ctrl_symbols; - int cfi; - int ngroups_phich; - int nof_ports; - lte_cp_t cp; + lte_cell_t cell; + uint8_t max_ctrl_symbols; + uint8_t cfi; + bool cfi_initiated; + uint8_t ngroups_phich; + phich_resources_t phich_res; phich_length_t phich_len; + regs_ch_t pcfich; regs_ch_t *phich; // there are several phich regs_ch_t pdcch[3]; /* PDCCH indexing, permutation and interleaving is computed for the three possible CFI value */ - int nof_regs; + + uint16_t nof_regs; regs_reg_t *regs; }regs_t; -LIBLTE_API int regs_init(regs_t *h, int cell_id, int nof_prb, int nof_ports, - phich_resources_t phich_res, phich_length_t phich_len, lte_cp_t cp); +LIBLTE_API int regs_init(regs_t *h, + phich_resources_t phich_res, + phich_length_t phich_len, + lte_cell_t cell); + LIBLTE_API void regs_free(regs_t *h); -LIBLTE_API int regs_set_cfi(regs_t *h, int nof_ctrl_symbols); +LIBLTE_API int regs_set_cfi(regs_t *h, + uint8_t nof_ctrl_symbols); + + +LIBLTE_API uint16_t regs_pcfich_nregs(regs_t *h); +LIBLTE_API int regs_pcfich_put(regs_t *h, + cf_t pcfich_symbols[REGS_PCFICH_NSYM], + cf_t *slot_symbols); + +LIBLTE_API int regs_pcfich_get(regs_t *h, + cf_t *slot_symbols, + cf_t pcfich_symbols[REGS_PCFICH_NSYM]); -LIBLTE_API int regs_put_reg(regs_reg_t *reg, cf_t *reg_data, cf_t *slot_symbols, int nof_prb); -LIBLTE_API int regs_add_reg(regs_reg_t *reg, cf_t *reg_data, cf_t *slot_symbols, int nof_prb); -LIBLTE_API int regs_get_reg(regs_reg_t *reg, cf_t *slot_symbols, cf_t *reg_data, int nof_prb); -LIBLTE_API int regs_reset_reg(regs_reg_t *reg, cf_t *slot_symbols, int nof_prb); +LIBLTE_API uint16_t regs_phich_nregs(regs_t *h); +LIBLTE_API int regs_phich_add(regs_t *h, + cf_t phich_symbols[REGS_PHICH_NSYM], + uint8_t ngroup, + cf_t *slot_symbols); -LIBLTE_API int regs_pcfich_nregs(regs_t *h); -LIBLTE_API int regs_pcfich_put(regs_t *h, cf_t pcfich_symbols[REGS_PCFICH_NSYM], cf_t *slot_symbols); -LIBLTE_API int regs_pcfich_get(regs_t *h, cf_t *slot_symbols, cf_t pcfich_symbols[REGS_PCFICH_NSYM]); +LIBLTE_API int regs_phich_get(regs_t *h, + cf_t *slot_symbols, + cf_t phich_symbols[REGS_PHICH_NSYM], + uint8_t ngroup); -LIBLTE_API int regs_phich_nregs(regs_t *h); -LIBLTE_API int regs_phich_add(regs_t *h, cf_t phich_symbols[REGS_PHICH_NSYM], int ngroup, cf_t *slot_symbols); -LIBLTE_API int regs_phich_get(regs_t *h, cf_t *slot_symbols, cf_t phich_symbols[REGS_PHICH_NSYM], int ngroup); -LIBLTE_API int regs_phich_ngroups(regs_t *h); -LIBLTE_API int regs_phich_reset(regs_t *h, cf_t *slot_symbols); +LIBLTE_API uint8_t regs_phich_ngroups(regs_t *h); +LIBLTE_API int regs_phich_reset(regs_t *h, + cf_t *slot_symbols); -LIBLTE_API int regs_pdcch_nregs(regs_t *h, int cfi); -LIBLTE_API int regs_pdcch_put(regs_t *h, cf_t *pdcch_symbols, cf_t *slot_symbols); -LIBLTE_API int regs_pdcch_get(regs_t *h, cf_t *slot_symbols, cf_t *pdcch_symbols); +LIBLTE_API int regs_pdcch_nregs(regs_t *h, uint8_t cfi); +LIBLTE_API int regs_pdcch_put(regs_t *h, + cf_t *pdcch_symbols, + cf_t *slot_symbols); + +LIBLTE_API int regs_pdcch_get(regs_t *h, + cf_t *slot_symbols, + cf_t *pdcch_symbols); #endif // REGS_H_ + + diff --git a/lte/phy/include/liblte/phy/phy.h b/lte/phy/include/liblte/phy/phy.h index 4839572e6..0b5ba19d2 100644 --- a/lte/phy/include/liblte/phy/phy.h +++ b/lte/phy/include/liblte/phy/phy.h @@ -50,7 +50,6 @@ #include "liblte/phy/common/phy_common.h" #include "liblte/phy/common/fft.h" -#include "liblte/phy/common/sequence.h" #include "liblte/phy/ch_estimation/chest.h" #include "liblte/phy/ch_estimation/refsignal.h" diff --git a/lte/phy/include/liblte/phy/sync/sync_frame.h b/lte/phy/include/liblte/phy/sync/sync_frame.h index 9ed2335f0..c4758a5db 100644 --- a/lte/phy/include/liblte/phy/sync/sync_frame.h +++ b/lte/phy/include/liblte/phy/sync/sync_frame.h @@ -56,6 +56,7 @@ typedef struct LIBLTE_API { sync_t s; enum sync_frame_state state; int downsampling; + resample_arb_t resample; unsigned long frame_cnt; bool fb_wp; int frame_size; diff --git a/lte/phy/lib/ch_estimation/src/chest.c b/lte/phy/lib/ch_estimation/src/chest.c index ae855cfdc..73d72906b 100644 --- a/lte/phy/lib/ch_estimation/src/chest.c +++ b/lte/phy/lib/ch_estimation/src/chest.c @@ -29,7 +29,6 @@ #include #include #include -#include #include #include "liblte/phy/ch_estimation/chest.h" @@ -40,7 +39,7 @@ #define SLOT_SZ(q) (q->nof_symbols * q->symbol_sz) #define SF_SZ(q) (2 * SLOT_SZ(q)) -void chest_fprint(chest_t *q, FILE *stream, int nslot, int port_id) { +void chest_fprint(chest_t *q, FILE *stream, uint8_t nslot, uint8_t port_id) { chest_ref_fprint(q, stream, nslot, port_id); chest_recvsig_fprint(q, stream, nslot, port_id); chest_ce_fprint(q, stream, nslot, port_id); @@ -49,13 +48,16 @@ void chest_fprint(chest_t *q, FILE *stream, int nslot, int port_id) { /* Sets the number of ports to estimate. nof_ports must be smaler than nof_ports * used during the call to chest_init(). */ -void chest_set_nof_ports(chest_t *q, int nof_ports) { - if (nof_ports < q->nof_ports && nof_ports > 0) { +int chest_set_nof_ports(chest_t *q, uint8_t nof_ports) { + if (nof_ports < q->nof_ports) { q->nof_ports = nof_ports; + return LIBLTE_SUCCESS; + } else { + return LIBLTE_ERROR_INVALID_INPUTS; } } -void chest_ref_fprint(chest_t *q, FILE *stream, int nslot, int port_id) { +void chest_ref_fprint(chest_t *q, FILE *stream, uint8_t nslot, uint8_t port_id) { int i; fprintf(stream, "refs%d=[",port_id); for (i=0;irefsignal[port_id][nslot].nof_refs;i++) { @@ -65,7 +67,7 @@ void chest_ref_fprint(chest_t *q, FILE *stream, int nslot, int port_id) { fprintf(stream, "];\n"); } -void chest_recvsig_fprint(chest_t *q, FILE *stream, int nslot, int port_id) { +void chest_recvsig_fprint(chest_t *q, FILE *stream, uint8_t nslot, uint8_t port_id) { int i; fprintf(stream, "recvsig%d=[",port_id); for (i=0;irefsignal[port_id][nslot].nof_refs;i++) { @@ -75,7 +77,7 @@ void chest_recvsig_fprint(chest_t *q, FILE *stream, int nslot, int port_id) { fprintf(stream, "];\n"); } -void chest_ce_fprint(chest_t *q, FILE *stream, int nslot, int port_id) { +void chest_ce_fprint(chest_t *q, FILE *stream, uint8_t nslot, uint8_t port_id) { int i; fprintf(stream, "mag%d=[",port_id); for (i=0;irefsignal[port_id][nslot].nof_refs;i++) { @@ -89,164 +91,206 @@ void chest_ce_fprint(chest_t *q, FILE *stream, int nslot, int port_id) { fprintf(stream, "];\n"); } -void chest_ce_ref(chest_t *q, cf_t *input, int nslot, int port_id, int nref) { +int chest_ce_ref(chest_t *q, cf_t *input, uint8_t nslot, uint8_t port_id, uint16_t nref) { int fidx, tidx; cf_t known_ref, channel_ref; - - fidx = q->refsignal[port_id][nslot].refs[nref].freq_idx; // reference frequency index - tidx = q->refsignal[port_id][nslot].refs[nref].time_idx; // reference time index - known_ref = q->refsignal[port_id][nslot].refs[nref].simbol; - channel_ref = input[SAMPLE_IDX(q->nof_prb, tidx, fidx)]; - q->refsignal[port_id][nslot].refs[nref].recv_simbol = channel_ref; - - DEBUG("Reference %2d pos (%2d,%2d)=%3d %.2f dB %.2f/%.2f=%.2f\n", nref, tidx, fidx, SAMPLE_IDX(q->nof_prb, tidx, fidx), - 10*log10f(cabsf(channel_ref/known_ref)), - cargf(channel_ref)/M_PI,cargf(known_ref)/M_PI,cargf(channel_ref/known_ref)/M_PI); - - /* FIXME: compare with threshold */ - if (channel_ref != 0) { - q->refsignal[port_id][nslot].ch_est[nref] = channel_ref/known_ref; - } else { - q->refsignal[port_id][nslot].ch_est[nref] = 0; + int ret = LIBLTE_ERROR_INVALID_INPUTS; + + if (q != NULL && + input != NULL && + nslot < NSLOTS_X_FRAME && + port_id < q->nof_ports) + { + if (nref < q->refsignal[port_id][nslot].nof_refs) { + fidx = q->refsignal[port_id][nslot].refs[nref].freq_idx; // reference frequency index + tidx = q->refsignal[port_id][nslot].refs[nref].time_idx; // reference time index + known_ref = q->refsignal[port_id][nslot].refs[nref].simbol; + channel_ref = input[tidx * q->nof_re + fidx]; + q->refsignal[port_id][nslot].refs[nref].recv_simbol = channel_ref; + + DEBUG("Reference %2d pos (%2d,%2d)=%3d %.2f dB %.2f/%.2f=%.2f\n", nref, tidx, fidx, tidx * q->nof_re + fidx, + 10*log10f(cabsf(channel_ref/known_ref)), + cargf(channel_ref)/M_PI,cargf(known_ref)/M_PI, + cargf(channel_ref/known_ref)/M_PI); + + /* FIXME: compare with threshold */ + if (channel_ref != 0) { + q->refsignal[port_id][nslot].ch_est[nref] = channel_ref/known_ref; + } else { + q->refsignal[port_id][nslot].ch_est[nref] = 0; + } + ret = LIBLTE_SUCCESS; + } } + return ret; } /* Computes channel estimates for each reference in a slot and port. * Saves the nof_prb * 12 * nof_symbols channel estimates in the array ce */ -void chest_ce_slot_port(chest_t *q, cf_t *input, cf_t *ce, int nslot, int port_id) { +int chest_ce_slot_port(chest_t *q, cf_t *input, cf_t *ce, uint8_t nslot, uint8_t port_id) { int i, j; cf_t x[2], y[MAX_NSYMB]; - assert(nslot >= 0 && nslot < NSLOTS_X_FRAME); - assert(port_id >= 0 && port_id < q->nof_ports); - assert(q->refsignal[port_id][nslot].nsymbols <= 2); - - refsignal_t *r = &q->refsignal[port_id][nslot]; - - INFO("Estimating channel slot=%d port=%d using %d reference signals\n", - nslot, port_id, r->nof_refs); - - for (i=0;inof_refs;i++) { - chest_ce_ref(q, input, nslot, port_id, i); - } + int ret = LIBLTE_ERROR_INVALID_INPUTS; + + if (q != NULL && + input != NULL && + nslot < NSLOTS_X_FRAME && + port_id < q->nof_ports) + { + if (q->refsignal[port_id][nslot].nsymbols <= 2) { + refsignal_t *r = &q->refsignal[port_id][nslot]; + + INFO("Estimating channel slot=%d port=%d using %d reference signals\n", + nslot, port_id, r->nof_refs); + + for (i=0;inof_refs;i++) { + chest_ce_ref(q, input, nslot, port_id, i); + } - /* interpolate the symbols with references - * in the freq domain */ - for (i=0;insymbols;i++) { - interp_linear_offset(&r->ch_est[i * r->nof_refs/2], - &ce[r->symbols_ref[i] * q->nof_prb * RE_X_RB], RE_X_RB/2, - r->nof_refs/2, r->voffset, RE_X_RB/2-r->voffset); + /* interpolate the symbols with references + * in the freq domain */ + for (i=0;insymbols;i++) { + interp_linear_offset(&r->ch_est[i * r->nof_refs/2], + &ce[r->symbols_ref[i] * q->nof_re], RE_X_RB/2, + r->nof_refs/2, r->voffset, RE_X_RB/2-r->voffset); - } - /* now interpolate in the time domain */ - for (i=0;inof_prb * RE_X_RB; i++) { - if (r->nsymbols > 1) { - for (j=0;jnsymbols;j++) { - x[j] = ce[r->symbols_ref[j] * q->nof_prb * RE_X_RB + i]; } - interp_linear_offset(x, y, r->symbols_ref[1]-r->symbols_ref[0], - 2, r->symbols_ref[0], 3); - } else { - for (j=0;jsymbols_ref[0] * q->nof_prb * RE_X_RB + i]; + /* now interpolate in the time domain */ + for (i=0;inof_re; i++) { + if (r->nsymbols > 1) { + for (j=0;jnsymbols;j++) { + x[j] = ce[r->symbols_ref[j] * q->nof_re + i]; + } + interp_linear_offset(x, y, r->symbols_ref[1]-r->symbols_ref[0], + 2, r->symbols_ref[0], 3); + } else { + for (j=0;jsymbols_ref[0] * q->nof_re + i]; + } + } + for (j=0;jnof_symbols;j++) { + ce[j * q->nof_re + i] = y[j]; + } } - } - for (j=0;jnof_symbols;j++) { - ce[j * q->nof_prb * RE_X_RB + i] = y[j]; + ret = LIBLTE_SUCCESS; } } + return ret; } /* Computes channel estimates for each reference in a subframe and port id. */ -void chest_ce_sf_port(chest_t *q, cf_t *input, cf_t *ce, int sf_idx, int port_id) { - int n, slotsz; - slotsz = CP_NSYMB(q->cp)*q->nof_prb*RE_X_RB; +int chest_ce_sf_port(chest_t *q, cf_t *input, cf_t *ce, uint8_t sf_idx, uint8_t port_id) { + int n, slotsz, ret; + slotsz = q->nof_symbols*q->nof_re; for (n=0;n<2;n++) { - chest_ce_slot_port(q, &input[n*slotsz], &ce[n*slotsz], 2*sf_idx+n, port_id); + ret = chest_ce_slot_port(q, &input[n*slotsz], &ce[n*slotsz], 2*sf_idx+n, port_id); + if (ret != LIBLTE_SUCCESS) { + return ret; + } } + return LIBLTE_SUCCESS; } /* Computes channel estimates for each reference in a slot for all ports. */ -void chest_ce_slot(chest_t *q, cf_t *input, cf_t **ce, int nslot) { - int p; +int chest_ce_slot(chest_t *q, cf_t *input, cf_t **ce, uint8_t nslot) { + int p, ret; for (p=0;pnof_ports;p++) { - chest_ce_slot_port(q, input, ce[p], nslot, p); + ret = chest_ce_slot_port(q, input, ce[p], nslot, p); + if (ret != LIBLTE_SUCCESS) { + return ret; + } } + return LIBLTE_SUCCESS; } /* Computes channel estimates for each reference in a subframe for all ports. */ -void chest_ce_sf(chest_t *q, cf_t *input, cf_t *ce[MAX_PORTS], int sf_idx) { - int p, n, slotsz; - slotsz = CP_NSYMB(q->cp)*q->nof_prb*RE_X_RB; +int chest_ce_sf(chest_t *q, cf_t *input, cf_t *ce[MAX_PORTS], uint8_t sf_idx) { + int p, n, slotsz, ret; + slotsz = q->nof_symbols*q->nof_re; for (p=0;pnof_ports;p++) { for (n=0;n<2;n++) { - chest_ce_slot_port(q, &input[n*slotsz], &ce[p][n*slotsz], 2*sf_idx+n, p); + ret = chest_ce_slot_port(q, &input[n*slotsz], &ce[p][n*slotsz], 2*sf_idx+n, p); + if (ret != LIBLTE_SUCCESS) { + return ret; + } } } + return LIBLTE_SUCCESS; } -int chest_init(chest_t *q, chest_interp_t interp, lte_cp_t cp, int nof_prb, int nof_ports) { - - if (nof_ports > MAX_PORTS) { - fprintf(stderr, "Error: Maximum ports %d\n", MAX_PORTS); - return -1; - } - bzero(q, sizeof(chest_t)); - q->nof_ports = nof_ports; - q->nof_symbols = CP_NSYMB(cp); - q->cp = cp; - q->nof_prb = nof_prb; +int chest_init(chest_t *q, chest_interp_t interp, uint16_t nof_re, uint8_t nof_symbols, uint8_t nof_ports) { + int ret = LIBLTE_ERROR_INVALID_INPUTS; + + if (q != NULL && + nof_ports < MAX_PORTS) + { + bzero(q, sizeof(chest_t)); - switch(interp) { - case LINEAR: - q->interp = interp_linear_offset; - } + q->nof_ports = nof_ports; + q->nof_symbols = nof_symbols; + q->nof_re = nof_re; + + switch(interp) { + case LINEAR: + q->interp = interp_linear_offset; + } - INFO("Initializing channel estimator size %dx%d, nof_ports=%d\n", - q->nof_symbols, nof_prb, nof_ports); + INFO("Initializing channel estimator size %dx%d, nof_ports=%d\n", + q->nof_symbols, q->nof_re, nof_ports); - return 0; + ret = LIBLTE_SUCCESS; + } + return ret; } -int chest_ref_LTEDL_slot_port(chest_t *q, int port, int nslot, int cell_id) { - if (port < 0 || port > q->nof_ports) { - return -1; - } - if (nslot < 0 || nslot > NSLOTS_X_FRAME) { - return -1; +int chest_init_LTEDL(chest_t *q, chest_interp_t interp, lte_cell_t cell) { + int ret; + ret = chest_init(q, interp, cell.nof_prb * RE_X_RB, CP_NSYMB(cell.cp), cell.nof_ports); + if (ret != LIBLTE_SUCCESS) { + return ret; + } else { + return chest_ref_LTEDL(q, cell); } +} - if (refsignal_init_LTEDL(&q->refsignal[port][nslot], port, nslot, cell_id, q->cp, q->nof_prb)) { - fprintf(stderr, "Error initiating CRS port=%d, slot=%d\n", port, nslot); - return -1; +int chest_ref_LTEDL_slot_port(chest_t *q, uint8_t nslot, uint8_t port_id, lte_cell_t cell) { + int ret = LIBLTE_ERROR_INVALID_INPUTS; + + if (q != NULL && + port_id < MAX_PORTS && + nslot < NSLOTS_X_FRAME) + { + ret = refsignal_init_LTEDL(&q->refsignal[port_id][nslot], port_id, nslot, cell); } - - return 0; + return ret; } -int chest_ref_LTEDL_slot(chest_t *q, int nslot, int cell_id) { - int p; +int chest_ref_LTEDL_slot(chest_t *q, uint8_t nslot, lte_cell_t cell) { + int p, ret; for (p=0;pnof_ports;p++) { - if (chest_ref_LTEDL_slot_port(q, p, nslot, cell_id)) { - return -1; + ret = chest_ref_LTEDL_slot_port(q, nslot, p, cell); + if (ret != LIBLTE_SUCCESS) { + return ret; } } - return 0; + return LIBLTE_SUCCESS; } -int chest_ref_LTEDL(chest_t *q, int cell_id) { - int n; +int chest_ref_LTEDL(chest_t *q, lte_cell_t cell) { + int n, ret; for (n=0;n NSLOTS_X_FRAME) { - return -1; +int chest_ref_symbols(chest_t *q, uint8_t port_id, uint8_t nslot, uint8_t l[2]) { + + if (q != NULL && + port_id < MAX_PORTS && + nslot < NSLOTS_X_FRAME) + { + memcpy(l, q->refsignal[port_id][nslot].symbols_ref, sizeof(uint8_t) * q->refsignal[port_id][nslot].nsymbols); + return q->refsignal[port_id][nslot].nsymbols; + } else { + return LIBLTE_ERROR_INVALID_INPUTS; } - memcpy(l, q->refsignal[port_id][nslot].symbols_ref, sizeof(int) * q->refsignal[port_id][nslot].nsymbols); - return q->refsignal[port_id][nslot].nsymbols; } @@ -275,6 +324,8 @@ int chest_ref_symbols(chest_t *q, int port_id, int nslot, int l[2]) { */ int chest_initialize(chest_hl* h) { + lte_cell_t cell; + if (!h->init.nof_symbols) { h->init.nof_symbols = CPNORM_NSYMB; // Normal CP } @@ -282,37 +333,23 @@ int chest_initialize(chest_hl* h) { h->init.nof_prb = 6; } - if (chest_init(&h->obj, LINEAR, (h->init.nof_symbols==CPNORM_NSYMB)?CPNORM:CPEXT, - h->init.nof_prb, h->init.nof_ports)) { + cell.id = h->init.cell_id; + cell.nof_ports = h->init.nof_ports; + cell.nof_prb = h->init.nof_prb; + cell.cp = h->init.nof_symbols == CPNORM_NSYMB ? CPNORM : CPEXT; + + if (chest_init_LTEDL(&h->obj, LINEAR, cell)) { fprintf(stderr, "Error initializing equalizer\n"); return -1; } - if (h->init.cell_id != -1) { - if (chest_ref_LTEDL(&h->obj, h->init.cell_id)) { - fprintf(stderr, "Error initializing reference signal\n"); - return -1; - } - } return 0; } -/** This function must be called in an slot basis (0.5ms) for LTE */ +/** This function must be called in an subframe basis (1ms) for LTE */ int chest_work(chest_hl* hl) { - int i; chest_t *q = &hl->obj; - - if (hl->init.cell_id != hl->ctrl_in.cell_id) { - if (chest_ref_LTEDL(q, hl->init.cell_id)) { - fprintf(stderr, "Error initializing reference signal\n"); - return -1; - } - } - - for (i=0;iinit.nof_ports;i++) { - chest_ce_slot_port(q, hl->input, hl->output[i], 1, 0); - hl->out_len[i] = hl->in_len; - } + chest_ce_sf(q, hl->input, hl->output, hl->ctrl_in.sf_idx); return 0; } diff --git a/lte/phy/lib/ch_estimation/src/refsignal.c b/lte/phy/lib/ch_estimation/src/refsignal.c index 3303899a9..f4eb0dfd8 100644 --- a/lte/phy/lib/ch_estimation/src/refsignal.c +++ b/lte/phy/lib/ch_estimation/src/refsignal.c @@ -40,7 +40,7 @@ #define idx(x, y) (l*nof_refs_x_symbol+i) -int refsignal_v(int port_id, int ns, int symbol_id) { +int refsignal_v(uint8_t port_id, uint8_t ns, uint8_t symbol_id) { int v=-1; switch(port_id) { case 0: @@ -67,108 +67,121 @@ int refsignal_v(int port_id, int ns, int symbol_id) { return v; } -int refsignal_k(int m, int v, int cell_id) { +int refsignal_k(int m, int v, uint16_t cell_id) { return 6*m+((v+(cell_id%6))%6); } -void refsignal_put(refsignal_t *q, cf_t *slot_symbols) { +int refsignal_put(refsignal_t *q, cf_t *slot_symbols) { int i; - int fidx, tidx; - for (i=0;inof_refs;i++) { - fidx = q->refs[i].freq_idx; // reference frequency index - tidx = q->refs[i].time_idx; // reference time index - slot_symbols[SAMPLE_IDX(q->nof_prb, tidx, fidx)] = q->refs[i].simbol; + uint16_t fidx, tidx; + if (q != NULL && + slot_symbols != NULL) + { + for (i=0;inof_refs;i++) { + fidx = q->refs[i].freq_idx; // reference frequency index + tidx = q->refs[i].time_idx; // reference time index + slot_symbols[SAMPLE_IDX(q->nof_prb, tidx, fidx)] = q->refs[i].simbol; + } + return LIBLTE_SUCCESS; + } else { + return LIBLTE_ERROR_INVALID_INPUTS; } } /** Initializes refsignal_t object according to 3GPP 36.211 6.10.1 * */ -int refsignal_init_LTEDL(refsignal_t *q, int port_id, int nslot, - int cell_id, lte_cp_t cp, int nof_prb) { +int refsignal_init_LTEDL(refsignal_t *q, uint8_t port_id, uint8_t nslot, + lte_cell_t cell) { - unsigned int c_init; - int ns, l, lp[2]; + uint32_t c_init; + uint8_t ns, l, lp[2]; int N_cp; int i; - int ret = -1; + int ret = LIBLTE_ERROR_INVALID_INPUTS; sequence_t seq; int v; int mp; - int nof_refs_x_symbol, nof_ref_symbols; - - bzero(q, sizeof(refsignal_t)); - bzero(&seq, sizeof(sequence_t)); - - if (CP_ISNORM(cp)) { - N_cp = 1; - } else { - N_cp = 0; - } - - if (port_id < 0 || port_id > (MAX_PORTS - 1)) { - fprintf(stderr, "Invalid port id %d\n", port_id); - return -1; - } + uint8_t nof_refs_x_symbol, nof_ref_symbols; + + if (q != NULL && + port_id < MAX_PORTS && + nslot < NSLOTS_X_FRAME && + lte_cell_isvalid(&cell)) + { + + bzero(q, sizeof(refsignal_t)); + bzero(&seq, sizeof(sequence_t)); + + if (CP_ISNORM(cell.cp)) { + N_cp = 1; + } else { + N_cp = 0; + } - if (port_id < 2) { - nof_ref_symbols = 2; - lp[0] = 0; - lp[1] = CP_NSYMB(cp) - 3; - } else { - nof_ref_symbols = 1; - lp[0] = 1; - } - nof_refs_x_symbol = 2 * nof_prb; - - q->nof_refs = nof_refs_x_symbol * nof_ref_symbols; - q->nsymbols = nof_ref_symbols; - q->symbols_ref = malloc(sizeof(int) * nof_ref_symbols); - q->voffset = cell_id%6; - q->nof_prb = nof_prb; - if (!q->symbols_ref) { - return -1; - } + if (port_id < 2) { + nof_ref_symbols = 2; + lp[0] = 0; + lp[1] = CP_NSYMB(cell.cp) - 3; + } else { + nof_ref_symbols = 1; + lp[0] = 1; + } + nof_refs_x_symbol = 2 * cell.nof_prb; - memcpy(q->symbols_ref, lp, sizeof(int) * nof_ref_symbols); + q->nof_refs = nof_refs_x_symbol * nof_ref_symbols; + q->nsymbols = nof_ref_symbols; + q->voffset = cell.id%6; + q->nof_prb = cell.nof_prb; - q->refs = vec_malloc(q->nof_refs * sizeof(ref_t)); - if (!q->refs) { - goto free_and_exit; - } - q->ch_est = vec_malloc(q->nof_refs * sizeof(cf_t)); - if (!q->ch_est) { - goto free_and_exit; - } + q->symbols_ref = malloc(sizeof(uint8_t) * nof_ref_symbols); + if (!q->symbols_ref) { + perror("malloc"); + goto free_and_exit; + } - ns = nslot; - for (l = 0; l < nof_ref_symbols; l++) { + memcpy(q->symbols_ref, lp, sizeof(uint8_t) * nof_ref_symbols); - c_init = 1024 * (7 * (ns + 1) + lp[l] + 1) * (2 * cell_id + 1) - + 2 * cell_id + N_cp; - if (sequence_LTEPRS(&seq, 2 * 2 * MAX_PRB, c_init)) { + q->refs = vec_malloc(q->nof_refs * sizeof(ref_t)); + if (!q->refs) { goto free_and_exit; } + q->ch_est = vec_malloc(q->nof_refs * sizeof(cf_t)); + if (!q->ch_est) { + goto free_and_exit; + } + + ns = nslot; + for (l = 0; l < nof_ref_symbols; l++) { - v = refsignal_v(port_id, ns, lp[l]); + c_init = 1024 * (7 * (ns + 1) + lp[l] + 1) * (2 * cell.id + 1) + + 2 * cell.id + N_cp; + ret = sequence_LTEPRS(&seq, 2 * 2 * MAX_PRB, c_init); + if (ret != LIBLTE_SUCCESS) { + goto free_and_exit; + } - for (i = 0; i < nof_refs_x_symbol; i++) { - mp = i + MAX_PRB - nof_prb; + v = refsignal_v(port_id, ns, lp[l]); - /* generate signal */ - __real__ q->refs[idx(l,i)].simbol = (1 - 2 * (float) seq.c[2 * mp]) / sqrt(2); - __imag__ q->refs[idx(l,i)].simbol = (1 - 2 * (float) seq.c[2 * mp + 1]) / sqrt(2); + for (i = 0; i < nof_refs_x_symbol; i++) { + mp = i + MAX_PRB - cell.nof_prb; - /* mapping to resource elements */ - q->refs[idx(l,i)].freq_idx = refsignal_k(i, v, cell_id); - q->refs[idx(l,i)].time_idx = lp[l]; + /* generate signal */ + __real__ q->refs[idx(l,i)].simbol = (1 - 2 * (float) seq.c[2 * mp]) / sqrt(2); + __imag__ q->refs[idx(l,i)].simbol = (1 - 2 * (float) seq.c[2 * mp + 1]) / sqrt(2); + + /* mapping to resource elements */ + q->refs[idx(l,i)].freq_idx = refsignal_k(i, v, cell.id); + q->refs[idx(l,i)].time_idx = lp[l]; + } } + ret = LIBLTE_SUCCESS; } - - ret = 0; free_and_exit: - sequence_free(&seq); - if (ret == -1) { + if (ret != LIBLTE_ERROR_INVALID_INPUTS) { + sequence_free(&seq); + } + if (ret == LIBLTE_ERROR) { refsignal_free(q); } return ret; diff --git a/lte/phy/lib/ch_estimation/test/chest_test.c b/lte/phy/lib/ch_estimation/test/chest_test.c index 5f5d6647e..3408ce553 100644 --- a/lte/phy/lib/ch_estimation/test/chest_test.c +++ b/lte/phy/lib/ch_estimation/test/chest_test.c @@ -33,19 +33,22 @@ #include "liblte/phy/phy.h" -int cell_id = -1; -int nof_prb = 6; -lte_cp_t cp = CPNORM; +lte_cell_t cell = { + 6, // nof_prb + MAX_PORTS, // nof_ports + 1000, // cell_id + CPNORM // cyclic prefix +}; char *output_matlab = NULL; void usage(char *prog) { printf("Usage: %s [recov]\n", prog); - printf("\t-r nof_prb [Default %d]\n", nof_prb); + printf("\t-r nof_prb [Default %d]\n", cell.nof_prb); printf("\t-e extended cyclic prefix [Default normal]\n"); - printf("\t-c cell_id (-1 tests all). [Default %d]\n", cell_id); + printf("\t-c cell_id (1000 tests all). [Default %d]\n", cell.id); printf("\t-o output matlab file [Default %s]\n",output_matlab?output_matlab:"None"); printf("\t-v increase verbosity\n"); @@ -56,13 +59,13 @@ void parse_args(int argc, char **argv) { while ((opt = getopt(argc, argv, "recov")) != -1) { switch(opt) { case 'r': - nof_prb = atoi(argv[optind]); + cell.nof_prb = atoi(argv[optind]); break; case 'e': - cp = CPEXT; + cell.cp = CPEXT; break; case 'c': - cell_id = atoi(argv[optind]); + cell.id = atoi(argv[optind]); break; case 'o': output_matlab = argv[optind]; @@ -120,7 +123,8 @@ int main(int argc, char **argv) { int max_cid; FILE *fmatlab = NULL; float mse_mag, mse_phase; - + lte_cell_t cell; + parse_args(argc,argv); if (output_matlab) { @@ -131,7 +135,7 @@ int main(int argc, char **argv) { } } - num_re = nof_prb * RE_X_RB * CP_NSYMB(cp); + num_re = cell.nof_prb * RE_X_RB * CP_NSYMB(cell.cp); input = malloc(num_re * sizeof(cf_t)); if (!input) { @@ -149,31 +153,23 @@ int main(int argc, char **argv) { goto do_exit; } - if (cell_id == -1) { + if (cell.id == 1000) { cid = 0; max_cid = 504; } else { - cid = cell_id; - max_cid = cell_id; + cid = cell.id; + max_cid = cell.id; } + while(cid <= max_cid) { - if (chest_init(&eq, LINEAR, cp, nof_prb, MAX_PORTS)) { + cell.id = cid; + if (chest_init_LTEDL(&eq, LINEAR, cell)) { fprintf(stderr, "Error initializing equalizer\n"); goto do_exit; } - if (chest_ref_LTEDL(&eq, cid)) { - fprintf(stderr, "Error initializing reference signal\n"); - goto do_exit; - } - for (n_slot=0;n_slotid < 504 && + cell->nof_ports > 0 && + cell->nof_ports < 5 && + cell->nof_prb > 5 && + cell->nof_prb < 111 + ) { + return true; + } else { + return false; + } +} + /* * Returns Turbo coder interleaver size for Table 5.1.3-3 (36.212) index */ diff --git a/lte/phy/lib/common/src/sequence.c b/lte/phy/lib/common/src/sequence.c index a659b0562..f4325ccd7 100644 --- a/lte/phy/lib/common/src/sequence.c +++ b/lte/phy/lib/common/src/sequence.c @@ -41,17 +41,16 @@ * It follows the 3GPP Release 8 (LTE) 36.211 * Section 7.2 */ -void generate_prs_c(sequence_t *q, unsigned int seed) { +void generate_prs_c(sequence_t *q, uint32_t seed) { int n; - unsigned int *x1; - unsigned int *x2; + uint32_t *x1, *x2; - x1 = calloc(Nc + q->len + 31, sizeof(unsigned int)); + x1 = calloc(Nc + q->len + 31, sizeof(uint32_t)); if (!x1) { perror("calloc"); return; } - x2 = calloc(Nc + q->len + 31, sizeof(unsigned int)); + x2 = calloc(Nc + q->len + 31, sizeof(uint32_t)); if (!x2) { free(x1); perror("calloc"); @@ -76,26 +75,26 @@ void generate_prs_c(sequence_t *q, unsigned int seed) { free(x2); } -int sequence_LTEPRS(sequence_t *q, int len, int seed) { +int sequence_LTEPRS(sequence_t *q, uint32_t len, uint32_t seed) { if (sequence_init(q, len)) { - return -1; + return LIBLTE_ERROR; } q->len = len; generate_prs_c(q, seed); - return 0; + return LIBLTE_SUCCESS; } -int sequence_init(sequence_t *q, int len) { +int sequence_init(sequence_t *q, uint32_t len) { if (q->c && (q->len != len)) { free(q->c); } if (!q->c) { q->c = malloc(len * sizeof(char)); if (!q->c) { - return -1; + return LIBLTE_ERROR; } } - return 0; + return LIBLTE_SUCCESS; } void sequence_free(sequence_t *q) { diff --git a/lte/phy/lib/phch/src/dci.c b/lte/phy/lib/phch/src/dci.c index 0b81a7076..d98426c64 100644 --- a/lte/phy/lib/phch/src/dci.c +++ b/lte/phy/lib/phch/src/dci.c @@ -40,15 +40,15 @@ #include "liblte/phy/utils/vector.h" #include "liblte/phy/utils/debug.h" -int dci_init(dci_t *q, int max_dcis) { +int dci_init(dci_t *q, uint8_t max_dcis) { q->msg = calloc(sizeof(dci_msg_t), max_dcis); if (!q->msg) { perror("malloc"); - return -1; + return LIBLTE_ERROR; } q->nof_dcis = 0; q->max_dcis = max_dcis; - return 0; + return LIBLTE_SUCCESS; } void dci_free(dci_t *q) { @@ -62,30 +62,30 @@ void dci_candidate_fprint(FILE *f, dci_candidate_t *q) { q->nof_bits); } -int dci_msg_candidate_set(dci_msg_t *msg, int L, int nCCE, unsigned short rnti) { +int dci_msg_candidate_set(dci_msg_t *msg, uint8_t L, uint8_t nCCE, uint16_t rnti) { if (L >= 0 && L <= 3) { - msg->location.L = (unsigned char) L; + msg->location.L = L; } else { fprintf(stderr, "Invalid L %d\n", L); - return -1; + return LIBLTE_ERROR; } if (nCCE >= 0 && nCCE <= 87) { - msg->location.ncce = (unsigned char) nCCE; + msg->location.ncce = nCCE; } else { fprintf(stderr, "Invalid nCCE %d\n", nCCE); - return -1; + return LIBLTE_ERROR; } msg->location.rnti = rnti; - return 0; + return LIBLTE_SUCCESS; } -int riv_nbits(int nof_prb) { - return (int) ceilf(log2f((float) nof_prb * ((float) nof_prb + 1) / 2)); +uint8_t riv_nbits(uint8_t nof_prb) { + return (uint8_t) ceilf(log2f((float) nof_prb * ((float) nof_prb + 1) / 2)); } const int ambiguous_sizes[10] = { 12, 14, 16, 20, 24, 26, 32, 40, 44, 56 }; -bool is_ambiguous_size(int size) { +bool is_ambiguous_size(uint8_t size) { int i; for (i = 0; i < 10; i++) { if (size == ambiguous_sizes[i]) { @@ -98,12 +98,12 @@ bool is_ambiguous_size(int size) { /********************************** * PAYLOAD sizeof functions * ********************************/ -int dci_format0_sizeof_(int nof_prb) { +uint8_t dci_format0_sizeof_(uint8_t nof_prb) { return 1 + 1 + riv_nbits(nof_prb) + 5 + 1 + 2 + 3 + 1; } -int dci_format1A_sizeof(int nof_prb) { - int n; +uint8_t dci_format1A_sizeof(uint8_t nof_prb) { + uint8_t n; n = 1 + 1 + riv_nbits(nof_prb) + 5 + 3 + 1 + 2 + 2; while (n < dci_format0_sizeof_(nof_prb)) { n++; @@ -114,7 +114,7 @@ int dci_format1A_sizeof(int nof_prb) { return n; } -int dci_format0_sizeof(int nof_prb) { +uint8_t dci_format0_sizeof(uint8_t nof_prb) { int n = dci_format0_sizeof_(nof_prb); while (n < dci_format1A_sizeof(nof_prb)) { n++; @@ -122,9 +122,9 @@ int dci_format0_sizeof(int nof_prb) { return n; } -int dci_format1_sizeof(int nof_prb) { +uint8_t dci_format1_sizeof(uint8_t nof_prb) { - int n = (int) ceilf((float) nof_prb / ra_type0_P(nof_prb)) + 5 + 3 + 1 + 2 + uint8_t n = (uint8_t) ceilf((float) nof_prb / ra_type0_P(nof_prb)) + 5 + 3 + 1 + 2 + 2; if (nof_prb > 10) { n++; @@ -136,17 +136,17 @@ int dci_format1_sizeof(int nof_prb) { return n; } -int dci_format1C_sizeof(int nof_prb) { +uint8_t dci_format1C_sizeof(uint8_t nof_prb) { int n_vrb_dl_gap1 = ra_type2_n_vrb_dl(nof_prb, true); int n_step = ra_type2_n_rb_step(nof_prb); - int n = +riv_nbits((int) n_vrb_dl_gap1 / n_step) + 5; + uint8_t n = +riv_nbits((uint8_t) n_vrb_dl_gap1 / n_step) + 5; if (nof_prb >= 50) { n++; } return n; } -int dci_format_sizeof(dci_format_t format, int nof_prb) { +uint8_t dci_format_sizeof(dci_format_t format, uint8_t nof_prb) { switch (format) { case Format0: return dci_format0_sizeof(nof_prb); @@ -157,7 +157,7 @@ int dci_format_sizeof(dci_format_t format, int nof_prb) { case Format1C: return dci_format1C_sizeof(nof_prb); default: - return -1; + return LIBLTE_ERROR; } } @@ -170,7 +170,7 @@ int dci_format_sizeof(dci_format_t format, int nof_prb) { * * TODO: TPC and cyclic shift for DM RS not implemented */ -int dci_format0_pack(ra_pusch_t *data, dci_msg_t *msg, int nof_prb) { +int dci_format0_pack(ra_pusch_t *data, dci_msg_t *msg, uint8_t nof_prb) { /* pack bits */ char *y = msg->data; @@ -246,14 +246,14 @@ int dci_format0_pack(ra_pusch_t *data, dci_msg_t *msg, int nof_prb) { *y++ = 0; } msg->location.nof_bits = (y - msg->data); - return 0; + return LIBLTE_SUCCESS; } /* Unpacks DCI format 0 data and store result in msg according * to 36.212 5.3.3.1.1 * * TODO: TPC and cyclic shift for DM RS not implemented */ -int dci_format0_unpack(dci_msg_t *msg, ra_pusch_t *data, int nof_prb) { +int dci_format0_unpack(dci_msg_t *msg, ra_pusch_t *data, uint8_t nof_prb) { /* pack bits */ char *y = msg->data; @@ -262,12 +262,12 @@ int dci_format0_unpack(dci_msg_t *msg, ra_pusch_t *data, int nof_prb) { /* Make sure it's a Format0 message */ if (msg->location.nof_bits != dci_format_sizeof(Format0, nof_prb)) { fprintf(stderr, "Invalid message length for format 0\n"); - return -1; + return LIBLTE_ERROR; } if (*y++ != 0) { fprintf(stderr, "Invalid format differentiation field value. This is Format1A\n"); - return -1; + return LIBLTE_ERROR; } if (*y++ == 0) { data->freq_hop_fl = hop_disabled; @@ -317,7 +317,7 @@ int dci_format0_unpack(dci_msg_t *msg, ra_pusch_t *data, int nof_prb) { data->rv_idx = mcs - 28; } - return 0; + return LIBLTE_SUCCESS; } /* Packs DCI format 1 data to a sequence of bits and store them in msg according @@ -326,7 +326,7 @@ int dci_format0_unpack(dci_msg_t *msg, ra_pusch_t *data, int nof_prb) { * TODO: TPC commands */ -int dci_format1_pack(ra_pdsch_t *data, dci_msg_t *msg, int nof_prb) { +int dci_format1_pack(ra_pdsch_t *data, dci_msg_t *msg, uint8_t nof_prb) { /* pack bits */ char *y = msg->data; @@ -351,7 +351,7 @@ int dci_format1_pack(ra_pdsch_t *data, dci_msg_t *msg, int nof_prb) { default: fprintf(stderr, "Format 1 accepts type0 or type1 resource allocation only\n"); - return -1; + return LIBLTE_ERROR; } /* pack MCS according to 7.1.7 of 36.213 */ @@ -387,10 +387,10 @@ int dci_format1_pack(ra_pdsch_t *data, dci_msg_t *msg, int nof_prb) { } msg->location.nof_bits = (y - msg->data); - return 0; + return LIBLTE_SUCCESS; } -int dci_format1_unpack(dci_msg_t *msg, ra_pdsch_t *data, int nof_prb) { +int dci_format1_unpack(dci_msg_t *msg, ra_pdsch_t *data, uint8_t nof_prb) { /* pack bits */ char *y = msg->data; @@ -398,7 +398,7 @@ int dci_format1_unpack(dci_msg_t *msg, ra_pdsch_t *data, int nof_prb) { /* Make sure it's a Format1 message */ if (msg->location.nof_bits != dci_format_sizeof(Format1, nof_prb)) { fprintf(stderr, "Invalid message length for format 1\n"); - return -1; + return LIBLTE_ERROR; } if (nof_prb > 10) { @@ -408,7 +408,7 @@ int dci_format1_unpack(dci_msg_t *msg, ra_pdsch_t *data, int nof_prb) { } /* Resource allocation: type0 or type 1 */ - int P = ra_type0_P(nof_prb); + uint8_t P = ra_type0_P(nof_prb); int alloc_size = (int) ceilf((float) nof_prb / P); switch (data->alloc_type) { case alloc_type0: @@ -423,7 +423,7 @@ int dci_format1_unpack(dci_msg_t *msg, ra_pdsch_t *data, int nof_prb) { default: fprintf(stderr, "Format 1 accepts type0 or type1 resource allocation only\n"); - return -1; + return LIBLTE_ERROR; } /* unpack MCS according to 7.1.7 of 36.213 */ @@ -442,14 +442,14 @@ int dci_format1_unpack(dci_msg_t *msg, ra_pdsch_t *data, int nof_prb) { // TPC not implemented - return 0; + return LIBLTE_SUCCESS; } /* Packs DCI format 1A for compact scheduling of PDSCH words according to 36.212 5.3.3.1.3 * * TODO: RA procedure initiated by PDCCH, TPC commands */ -int dci_format1As_pack(ra_pdsch_t *data, dci_msg_t *msg, int nof_prb, +int dci_format1As_pack(ra_pdsch_t *data, dci_msg_t *msg, uint8_t nof_prb, bool crc_is_crnti) { /* pack bits */ @@ -459,7 +459,7 @@ int dci_format1As_pack(ra_pdsch_t *data, dci_msg_t *msg, int nof_prb, if (data->alloc_type != alloc_type2) { fprintf(stderr, "Format 1A accepts type2 resource allocation only\n"); - return -1; + return LIBLTE_ERROR; } *y++ = data->type2_alloc.mode; // localized or distributed VRB assignment @@ -468,7 +468,7 @@ int dci_format1As_pack(ra_pdsch_t *data, dci_msg_t *msg, int nof_prb, if (data->type2_alloc.L_crb > nof_prb) { fprintf(stderr, "L_CRB=%d can not exceed system BW for localized type2\n", data->type2_alloc.L_crb); - return -1; + return LIBLTE_ERROR; } } else { int n_vrb_dl; @@ -481,7 +481,7 @@ int dci_format1As_pack(ra_pdsch_t *data, dci_msg_t *msg, int nof_prb, fprintf(stderr, "L_CRB=%d can not exceed N_vrb_dl=%d for distributed type2\n", data->type2_alloc.L_crb, n_vrb_dl); - return -1; + return LIBLTE_ERROR; } } /* pack RIV according to 7.1.6.3 of 36.213 */ @@ -545,13 +545,13 @@ int dci_format1As_pack(ra_pdsch_t *data, dci_msg_t *msg, int nof_prb, } msg->location.nof_bits = (y - msg->data); - return 0; + return LIBLTE_SUCCESS; } /* Unpacks DCI format 1A for compact scheduling of PDSCH words according to 36.212 5.3.3.1.3 * */ -int dci_format1As_unpack(dci_msg_t *msg, ra_pdsch_t *data, int nof_prb, +int dci_format1As_unpack(dci_msg_t *msg, ra_pdsch_t *data, uint8_t nof_prb, bool crc_is_crnti) { /* pack bits */ @@ -560,13 +560,13 @@ int dci_format1As_unpack(dci_msg_t *msg, ra_pdsch_t *data, int nof_prb, /* Make sure it's a Format0 message */ if (msg->location.nof_bits != dci_format_sizeof(Format1A, nof_prb)) { fprintf(stderr, "Invalid message length for format 1A\n"); - return -1; + return LIBLTE_ERROR; } if (*y++ != 1) { fprintf(stderr, "Invalid format differentiation field value. This is Format0\n"); - return -1; + return LIBLTE_ERROR; } data->alloc_type = alloc_type2; @@ -624,13 +624,13 @@ int dci_format1As_unpack(dci_msg_t *msg, ra_pdsch_t *data, int nof_prb, data->mcs.tbs = ra_tbs_from_idx(data->mcs.tbs_idx, n_prb); data->mcs.mod = QPSK; - return 0; + return LIBLTE_SUCCESS; } /* Format 1C for compact scheduling of PDSCH words * */ -int dci_format1Cs_pack(ra_pdsch_t *data, dci_msg_t *msg, int nof_prb) { +int dci_format1Cs_pack(ra_pdsch_t *data, dci_msg_t *msg, uint8_t nof_prb) { /* pack bits */ char *y = msg->data; @@ -638,7 +638,7 @@ int dci_format1Cs_pack(ra_pdsch_t *data, dci_msg_t *msg, int nof_prb) { if (data->alloc_type != alloc_type2 || data->type2_alloc.mode != t2_dist) { fprintf(stderr, "Format 1C accepts distributed type2 resource allocation only\n"); - return -1; + return LIBLTE_ERROR; } if (nof_prb >= 50) { @@ -651,15 +651,15 @@ int dci_format1Cs_pack(ra_pdsch_t *data, dci_msg_t *msg, int nof_prb) { fprintf(stderr, "L_CRB=%d can not exceed N_vrb_dl=%d for distributed type2\n", data->type2_alloc.L_crb, ((int) n_vrb_dl / n_step) * n_step); - return -1; + return LIBLTE_ERROR; } if (data->type2_alloc.L_crb % n_step) { fprintf(stderr, "L_crb must be multiple of n_step\n"); - return -1; + return LIBLTE_ERROR; } if (data->type2_alloc.RB_start % n_step) { fprintf(stderr, "RB_start must be multiple of n_step\n"); - return -1; + return LIBLTE_ERROR; } int L_p = data->type2_alloc.L_crb / n_step; int RB_p = data->type2_alloc.RB_start / n_step; @@ -687,10 +687,10 @@ int dci_format1Cs_pack(ra_pdsch_t *data, dci_msg_t *msg, int nof_prb) { msg->location.nof_bits = (y - msg->data); - return 0; + return LIBLTE_SUCCESS; } -int dci_format1Cs_unpack(dci_msg_t *msg, ra_pdsch_t *data, int nof_prb) { +int dci_format1Cs_unpack(dci_msg_t *msg, ra_pdsch_t *data, uint8_t nof_prb) { uint16_t L_p, RB_p; /* pack bits */ @@ -698,7 +698,7 @@ int dci_format1Cs_unpack(dci_msg_t *msg, ra_pdsch_t *data, int nof_prb) { if (msg->location.nof_bits != dci_format_sizeof(Format1C, nof_prb)) { fprintf(stderr, "Invalid message length for format 1C\n"); - return -1; + return LIBLTE_ERROR; } data->alloc_type = alloc_type2; data->type2_alloc.mode = t2_dist; @@ -723,11 +723,11 @@ int dci_format1Cs_unpack(dci_msg_t *msg, ra_pdsch_t *data, int nof_prb) { msg->location.nof_bits = (y - msg->data); - return 0; + return LIBLTE_SUCCESS; } int dci_msg_pack_pdsch(ra_pdsch_t *data, dci_msg_t *msg, dci_format_t format, - int nof_prb, bool crc_is_crnti) { + uint8_t nof_prb, bool crc_is_crnti) { switch (format) { case Format1: return dci_format1_pack(data, msg, nof_prb); @@ -738,11 +738,11 @@ int dci_msg_pack_pdsch(ra_pdsch_t *data, dci_msg_t *msg, dci_format_t format, default: fprintf(stderr, "Invalid DCI format %s for PDSCH resource allocation\n", dci_format_string(format)); - return -1; + return LIBLTE_ERROR; } } -int dci_msg_unpack_pdsch(dci_msg_t *msg, ra_pdsch_t *data, int nof_prb, +int dci_msg_unpack_pdsch(dci_msg_t *msg, ra_pdsch_t *data, uint8_t nof_prb, bool crc_is_crnti) { if (msg->location.nof_bits == dci_format_sizeof(Format1, nof_prb)) { return dci_format1_unpack(msg, data, nof_prb); @@ -751,15 +751,15 @@ int dci_msg_unpack_pdsch(dci_msg_t *msg, ra_pdsch_t *data, int nof_prb, } else if (msg->location.nof_bits == dci_format_sizeof(Format1C, nof_prb)) { return dci_format1Cs_unpack(msg, data, nof_prb); } else { - return -1; + return LIBLTE_ERROR; } } -int dci_msg_pack_pusch(ra_pusch_t *data, dci_msg_t *msg, int nof_prb) { +int dci_msg_pack_pusch(ra_pusch_t *data, dci_msg_t *msg, uint8_t nof_prb) { return dci_format0_pack(data, msg, nof_prb); } -int dci_msg_unpack_pusch(dci_msg_t *msg, ra_pusch_t *data, int nof_prb) { +int dci_msg_unpack_pusch(dci_msg_t *msg, ra_pusch_t *data, uint8_t nof_prb) { return dci_format0_unpack(msg, data, nof_prb); } @@ -799,17 +799,17 @@ void dci_msg_type_fprint(FILE *f, dci_msg_type_t type) { } } -int dci_msg_get_type(dci_msg_t *msg, dci_msg_type_t *type, int nof_prb, +int dci_msg_get_type(dci_msg_t *msg, dci_msg_type_t *type, uint8_t nof_prb, unsigned short crnti) { if (msg->location.nof_bits == dci_format_sizeof(Format0, nof_prb) && !msg->data[0]) { type->type = PUSCH_SCHED; type->format = Format0; - return 0; + return LIBLTE_SUCCESS; } else if (msg->location.nof_bits == dci_format_sizeof(Format1, nof_prb)) { type->type = PDSCH_SCHED; // only these 2 types supported type->format = Format1; - return 0; + return LIBLTE_SUCCESS; } else if (msg->location.nof_bits == dci_format_sizeof(Format1A, nof_prb)) { if (msg->location.rnti == crnti) { type->type = RA_PROC_PDCCH; @@ -818,7 +818,7 @@ int dci_msg_get_type(dci_msg_t *msg, dci_msg_type_t *type, int nof_prb, type->type = PDSCH_SCHED; // only these 2 types supported type->format = Format1A; } - return 0; + return LIBLTE_SUCCESS; } else if (msg->location.nof_bits == dci_format_sizeof(Format1C, nof_prb)) { if (msg->location.rnti == MRNTI) { type->type = MCCH_CHANGE; @@ -827,8 +827,8 @@ int dci_msg_get_type(dci_msg_t *msg, dci_msg_type_t *type, int nof_prb, type->type = PDSCH_SCHED; // only these 2 types supported type->format = Format1C; } - return 0; + return LIBLTE_SUCCESS; } - return -1; + return LIBLTE_ERROR; } diff --git a/lte/phy/lib/phch/src/pcfich.c b/lte/phy/lib/phch/src/pcfich.c index af7da9feb..f342d6406 100644 --- a/lte/phy/lib/phch/src/pcfich.c +++ b/lte/phy/lib/phch/src/pcfich.c @@ -54,37 +54,42 @@ bool pcfich_exists(int nframe, int nslot) { return true; } -/** Initializes the pcfich channel receiver */ -int pcfich_init(pcfich_t *q, regs_t *regs, int cell_id, int nof_prb, - int nof_ports, lte_cp_t cp) { - int ret = -1; - if (cell_id < 0) { - return -1; - } - bzero(q, sizeof(pcfich_t)); - q->cell_id = cell_id; - q->cp = cp; - q->regs = regs; - q->nof_prb = nof_prb; - q->nof_ports = nof_ports; - - if (modem_table_std(&q->mod, LTE_QPSK, false)) { - goto clean; - } +/** Initializes the pcfich channel receiver. + * On error, returns -1 and frees the structrure + */ +int pcfich_init(pcfich_t *q, regs_t *regs, lte_cell_t cell) { + int ret = LIBLTE_ERROR_INVALID_INPUTS; + + if (q != NULL && + regs != NULL && + lte_cell_isvalid(&cell)) + { + ret = LIBLTE_ERROR; + + bzero(q, sizeof(pcfich_t)); + q->cell = cell; + q->regs = regs; + + if (modem_table_std(&q->mod, LTE_QPSK, false)) { + goto clean; + } - demod_hard_init(&q->demod); - demod_hard_table_set(&q->demod, LTE_QPSK); + demod_hard_init(&q->demod); + demod_hard_table_set(&q->demod, LTE_QPSK); - for (int nsf = 0; nsf < NSUBFRAMES_X_FRAME; nsf++) { - if (sequence_pcfich(&q->seq_pcfich[nsf], 2 * nsf, q->cell_id)) { - goto clean; + for (int nsf = 0; nsf < NSUBFRAMES_X_FRAME; nsf++) { + if (sequence_pcfich(&q->seq_pcfich[nsf], 2 * nsf, q->cell.id)) { + goto clean; + } } - } - q->nof_symbols = PCFICH_RE; + q->nof_symbols = PCFICH_RE; - ret = 0; - clean: if (ret == -1) { + ret = LIBLTE_SUCCESS; + } + + clean: + if (ret == LIBLTE_ERROR) { pcfich_free(q); } return ret; @@ -100,7 +105,7 @@ void pcfich_free(pcfich_t *q) { /** Finds the CFI with minimum distance with the vector of received 32 bits. * Saves the CFI value in the cfi pointer and returns the distance. */ -int pcfich_cfi_decode(char bits[PCFICH_CFI_LEN], int *cfi) { +int pcfich_cfi_decode(char bits[PCFICH_CFI_LEN], uint8_t *cfi) { int i, j; int distance, index = -1; int min = 32; @@ -120,7 +125,6 @@ int pcfich_cfi_decode(char bits[PCFICH_CFI_LEN], int *cfi) { *cfi = index + 1; } return min; - } /** Encodes the CFI producing a vector of 32 bits. @@ -128,11 +132,11 @@ int pcfich_cfi_decode(char bits[PCFICH_CFI_LEN], int *cfi) { */ int pcfich_cfi_encode(int cfi, char bits[PCFICH_CFI_LEN]) { if (cfi < 1 || cfi > 3) { - fprintf(stderr, "Invalid CFI %d\n", cfi); - return -1; + return LIBLTE_ERROR_INVALID_INPUTS; + } else{ + memcpy(bits, cfi_table[cfi - 1], PCFICH_CFI_LEN * sizeof(char)); + return LIBLTE_SUCCESS; } - memcpy(bits, cfi_table[cfi - 1], PCFICH_CFI_LEN * sizeof(char)); - return 0; } /* Decodes the PCFICH channel and saves the CFI in the cfi pointer. @@ -140,7 +144,7 @@ int pcfich_cfi_encode(int cfi, char bits[PCFICH_CFI_LEN]) { * Returns 1 if successfully decoded the CFI, 0 if not and -1 on error */ int pcfich_decode(pcfich_t *q, cf_t *slot_symbols, cf_t *ce[MAX_PORTS], - int nsubframe, int *cfi, int *distance) { + uint8_t nsubframe, uint8_t *cfi, uint8_t *distance) { int dist; /* Set pointers for layermapping & precoding */ @@ -148,112 +152,120 @@ int pcfich_decode(pcfich_t *q, cf_t *slot_symbols, cf_t *ce[MAX_PORTS], cf_t *x[MAX_LAYERS]; cf_t *ce_precoding[MAX_PORTS]; - if (nsubframe < 0 || nsubframe > NSUBFRAMES_X_FRAME) { - fprintf(stderr, "Invalid nslot %d\n", nsubframe); - return -1; - } + if (q != NULL && + slot_symbols != NULL && + nsubframe < NSUBFRAMES_X_FRAME) + { - /* number of layers equals number of ports */ - for (i = 0; i < MAX_PORTS; i++) { - x[i] = q->pcfich_x[i]; - } - for (i = 0; i < MAX_PORTS; i++) { - ce_precoding[i] = q->ce[i]; - } - - /* extract symbols */ - if (q->nof_symbols - != regs_pcfich_get(q->regs, slot_symbols, q->pcfich_symbols[0])) { - fprintf(stderr, "There was an error getting the PCFICH symbols\n"); - return -1; - } + /* number of layers equals number of ports */ + for (i = 0; i < MAX_PORTS; i++) { + x[i] = q->pcfich_x[i]; + } + for (i = 0; i < MAX_PORTS; i++) { + ce_precoding[i] = q->ce[i]; + } - /* extract channel estimates */ - for (i = 0; i < q->nof_ports; i++) { - if (q->nof_symbols != regs_pcfich_get(q->regs, ce[i], q->ce[i])) { + /* extract symbols */ + if (q->nof_symbols + != regs_pcfich_get(q->regs, slot_symbols, q->pcfich_symbols[0])) { fprintf(stderr, "There was an error getting the PCFICH symbols\n"); - return -1; + return LIBLTE_ERROR; } - } - /* in control channels, only diversity is supported */ - if (q->nof_ports == 1) { - /* no need for layer demapping */ - predecoding_single_zf(q->pcfich_symbols[0], q->ce[0], q->pcfich_d, - q->nof_symbols); - } else { - predecoding_diversity_zf(q->pcfich_symbols[0], ce_precoding, x, - q->nof_ports, q->nof_symbols); - layerdemap_diversity(x, q->pcfich_d, q->nof_ports, - q->nof_symbols / q->nof_ports); - } + /* extract channel estimates */ + for (i = 0; i < q->cell.nof_ports; i++) { + if (q->nof_symbols != regs_pcfich_get(q->regs, ce[i], q->ce[i])) { + fprintf(stderr, "There was an error getting the PCFICH symbols\n"); + return LIBLTE_ERROR; + } + } - /* demodulate symbols */ - demod_hard_demodulate(&q->demod, q->pcfich_d, q->data, q->nof_symbols); + /* in control channels, only diversity is supported */ + if (q->cell.nof_ports == 1) { + /* no need for layer demapping */ + predecoding_single_zf(q->pcfich_symbols[0], q->ce[0], q->pcfich_d, + q->nof_symbols); + } else { + predecoding_diversity_zf(q->pcfich_symbols[0], ce_precoding, x, + q->cell.nof_ports, q->nof_symbols); + layerdemap_diversity(x, q->pcfich_d, q->cell.nof_ports, + q->nof_symbols / q->cell.nof_ports); + } - /* Scramble with the sequence for slot nslot */ - scrambling_b(&q->seq_pcfich[nsubframe], q->data); + /* demodulate symbols */ + demod_hard_demodulate(&q->demod, q->pcfich_d, q->data, q->nof_symbols); - /* decode CFI */ - dist = pcfich_cfi_decode(q->data, cfi); - if (distance) { - *distance = dist; - } - if (dist < PCFICH_MAX_DISTANCE) { - return 1; + /* Scramble with the sequence for slot nslot */ + scrambling_b(&q->seq_pcfich[nsubframe], q->data); + + /* decode CFI */ + dist = pcfich_cfi_decode(q->data, cfi); + if (distance) { + *distance = dist; + } + if (dist < PCFICH_MAX_DISTANCE) { + return 1; + } else { + return 0; + } } else { - return 0; + return LIBLTE_ERROR_INVALID_INPUTS; } + } /** Encodes CFI and maps symbols to the slot */ -int pcfich_encode(pcfich_t *q, int cfi, cf_t *slot_symbols[MAX_PORTS], - int nsubframe) { +int pcfich_encode(pcfich_t *q, uint8_t cfi, cf_t *slot_symbols[MAX_PORTS], + uint8_t subframe) { int i; - if (nsubframe < 0 || nsubframe > NSUBFRAMES_X_FRAME) { - fprintf(stderr, "Invalid nslot %d\n", nsubframe); - return -1; - } + if (q != NULL && + cfi < 3 && + slot_symbols != NULL && + subframe < NSUBFRAMES_X_FRAME) + { - /* Set pointers for layermapping & precoding */ - cf_t *x[MAX_LAYERS]; - cf_t *symbols_precoding[MAX_PORTS]; + /* Set pointers for layermapping & precoding */ + cf_t *x[MAX_LAYERS]; + cf_t *symbols_precoding[MAX_PORTS]; - /* number of layers equals number of ports */ - for (i = 0; i < q->nof_ports; i++) { - x[i] = q->pcfich_x[i]; - } - for (i = 0; i < MAX_PORTS; i++) { - symbols_precoding[i] = q->pcfich_symbols[i]; - } + /* number of layers equals number of ports */ + for (i = 0; i < q->cell.nof_ports; i++) { + x[i] = q->pcfich_x[i]; + } + for (i = 0; i < MAX_PORTS; i++) { + symbols_precoding[i] = q->pcfich_symbols[i]; + } - /* pack CFI */ - pcfich_cfi_encode(cfi, q->data); + /* pack CFI */ + pcfich_cfi_encode(cfi, q->data); - /* scramble for slot sequence nslot */ - scrambling_b(&q->seq_pcfich[nsubframe], q->data); + /* scramble for slot sequence nslot */ + scrambling_b(&q->seq_pcfich[subframe], q->data); - mod_modulate(&q->mod, q->data, q->pcfich_d, PCFICH_CFI_LEN); + mod_modulate(&q->mod, q->data, q->pcfich_d, PCFICH_CFI_LEN); - /* layer mapping & precoding */ - if (q->nof_ports > 1) { - layermap_diversity(q->pcfich_d, x, q->nof_ports, q->nof_symbols); - precoding_diversity(x, symbols_precoding, q->nof_ports, - q->nof_symbols / q->nof_ports); - } else { - memcpy(q->pcfich_symbols[0], q->pcfich_d, q->nof_symbols * sizeof(cf_t)); - } + /* layer mapping & precoding */ + if (q->cell.nof_ports > 1) { + layermap_diversity(q->pcfich_d, x, q->cell.nof_ports, q->nof_symbols); + precoding_diversity(x, symbols_precoding, q->cell.nof_ports, + q->nof_symbols / q->cell.nof_ports); + } else { + memcpy(q->pcfich_symbols[0], q->pcfich_d, q->nof_symbols * sizeof(cf_t)); + } - /* mapping to resource elements */ - for (i = 0; i < q->nof_ports; i++) { - if (regs_pcfich_put(q->regs, q->pcfich_symbols[i], slot_symbols[i]) < 0) { - fprintf(stderr, "Error putting PCHICH resource elements\n"); - return -1; + /* mapping to resource elements */ + for (i = 0; i < q->cell.nof_ports; i++) { + if (regs_pcfich_put(q->regs, q->pcfich_symbols[i], slot_symbols[i]) < 0) { + fprintf(stderr, "Error putting PCHICH resource elements\n"); + return LIBLTE_ERROR; + } } + return LIBLTE_SUCCESS; + } else { + return LIBLTE_ERROR_INVALID_INPUTS; } - - return 0; } + diff --git a/lte/phy/lib/phch/src/pdcch.c b/lte/phy/lib/phch/src/pdcch.c index 512badb96..a239d9507 100644 --- a/lte/phy/lib/phch/src/pdcch.c +++ b/lte/phy/lib/phch/src/pdcch.c @@ -31,7 +31,6 @@ #include #include #include -#include #include #include "liblte/phy/phch/dci.h" @@ -42,24 +41,26 @@ #include "liblte/phy/utils/vector.h" #include "liblte/phy/utils/debug.h" -#define PDCCH_NOF_FORMATS 4 -#define PDCCH_FORMAT_NOF_CCE(i) (1<b)?b:a) +void set_cfi(pdcch_t *q, uint8_t cfi); + /** * 36.213 9.1 */ -int gen_common_search(dci_candidate_t *c, int nof_cce, int nof_bits, - unsigned short rnti) { +int gen_common_search(dci_candidate_t *c, uint16_t nof_cce, uint16_t nof_bits, + uint16_t rnti) { int i, l, L, k; k = 0; for (l = 3; l > 1; l--) { @@ -80,15 +81,15 @@ int gen_common_search(dci_candidate_t *c, int nof_cce, int nof_bits, /** * 36.213 9.1 */ -int gen_ue_search(dci_candidate_t *c, int nof_cce, int nof_bits, - unsigned short rnti, int subframe) { +int gen_ue_search(dci_candidate_t *c, uint16_t nof_cce, uint8_t nof_bits, + uint16_t rnti, uint8_t subframe) { int i, l, L, k, m; unsigned int Yk; const int S[4] = { 6, 12, 8, 16 }; k = 0; - if (!subframe) { - INFO("UE-specific candidates for RNTI: 0x%x, NofBits: %d, NofCCE: %d\n", - rnti, nof_bits, nof_cce); + + if (VERBOSE_ISDEBUG()) { + printf("NofBits=%d, RNTI: 0x%x, SF=%d (n, L): ", nof_bits, rnti, subframe); } for (l = 3; l >= 0; l--) { L = (1 << l); @@ -102,7 +103,12 @@ int gen_ue_search(dci_candidate_t *c, int nof_cce, int nof_bits, } c[k].ncce = L * ((Yk + i) % (nof_cce / L)); if (VERBOSE_ISDEBUG()) { - printf("sf %d - (%d, %d), ", subframe, c[k].ncce, c[k].L); + printf("(%d, %d), ", c[k].ncce, c[k].L); + } + if (c[k].ncce + PDCCH_FORMAT_NOF_CCE(c[k].L) > nof_cce || + nof_bits > DCI_MAX_BITS) { + fprintf(stderr, "Illegal DCI message\n"); + return LIBLTE_ERROR; } k++; } @@ -113,35 +119,17 @@ int gen_ue_search(dci_candidate_t *c, int nof_cce, int nof_bits, return k; } -void pdcch_init_common(pdcch_t *q, pdcch_search_t *s, unsigned short rnti) { - int k, i; - dci_candidate_t *c = s->candidates[0]; - s->nof_candidates = 0; - // Format 1A and 1C L=4 and L=8, 4 and 2 candidates, only if nof_cce > 16 - k = 0; - for (i = 0; i < NOF_COMMON_FORMATS && k < MAX_CANDIDATES; i++) { - k += gen_common_search(&c[k], q->nof_cce, - dci_format_sizeof(common_formats[i], q->nof_prb), SIRNTI); - } - s->nof_candidates=k; - INFO("Initiated %d candidate(s) in the Common search space for RNTI: 0x%x\n", - s->nof_candidates, rnti); -} - -/** 36.213 v9.3 Table 7.1-1: System Information DCI messages - * Expect DCI formats 1C and 1A in the common search space - */ -void pdcch_init_search_si(pdcch_t *q) { - pdcch_init_common(q, &q->search_mode[SEARCH_SI], SIRNTI); - q->current_search_mode = SEARCH_SI; -} /** 36.213 v9.3 Table 7.1-5 * user-specific search space. Currently supported transmission Mode 1: * DCI Format 1A and 1 + PUSCH scheduling format 0 */ -void pdcch_init_search_ue(pdcch_t *q, unsigned short c_rnti) { - int n, k, i; +int pdcch_init_search_ue(pdcch_t *q, uint16_t c_rnti, uint8_t cfi) { + int k, i, r; + uint8_t n; + + set_cfi(q, cfi); + pdcch_search_t *s = &q->search_mode[SEARCH_UE]; for (n = 0; n < NSUBFRAMES_X_FRAME; n++) { dci_candidate_t *c = s->candidates[n]; @@ -151,22 +139,67 @@ void pdcch_init_search_ue(pdcch_t *q, unsigned short c_rnti) { // Expect Formats 1, 1A, 0 k = 0; for (i = 0; i < NOF_UE_FORMATS && k < MAX_CANDIDATES; i++) { - k += gen_ue_search(&c[k], q->nof_cce, - dci_format_sizeof(ue_formats[i], q->nof_prb), c_rnti, n); + r = gen_ue_search(&c[k], q->nof_cce, + dci_format_sizeof(ue_formats[i], q->cell.nof_prb), c_rnti, n); + if (r < 0) { + fprintf(stderr, "Error generating UE-specific search space\n"); + return r; + } + k += r; } s->nof_candidates = k; } INFO("Initiated %d candidate(s) in the UE-specific search space for C-RNTI: 0x%x\n", s->nof_candidates, c_rnti); q->current_search_mode = SEARCH_UE; + + return LIBLTE_SUCCESS; +} + + +int pdcch_init_common(pdcch_t *q, pdcch_search_t *s, uint16_t rnti) { + int k, r, i; + dci_candidate_t *c = s->candidates[0]; + s->nof_candidates = 0; + // Format 1A and 1C L=4 and L=8, 4 and 2 candidates, only if nof_cce > 16 + k = 0; + for (i = 0; i < NOF_COMMON_FORMATS && k < MAX_CANDIDATES; i++) { + r = gen_common_search(&c[k], q->nof_cce, + dci_format_sizeof(common_formats[i], q->cell.nof_prb), SIRNTI); + if (r < 0) { + return r; + } + k += r; + } + s->nof_candidates=k; + INFO("Initiated %d candidate(s) in the Common search space for RNTI: 0x%x\n", + s->nof_candidates, rnti); + + return LIBLTE_SUCCESS; +} + +/** 36.213 v9.3 Table 7.1-1: System Information DCI messages + * Expect DCI formats 1C and 1A in the common search space + */ +int pdcch_init_search_si(pdcch_t *q, uint8_t cfi) { + set_cfi(q, cfi); + int r = pdcch_init_common(q, &q->search_mode[SEARCH_SI], SIRNTI); + if (r >= 0) { + q->current_search_mode = SEARCH_SI; + } + return r; } /** 36.213 v9.3 Table 7.1-3 * Expect DCI formats 1C and 1A in the common search space */ -void pdcch_init_search_ra(pdcch_t *q, unsigned short ra_rnti) { - pdcch_init_common(q, &q->search_mode[SEARCH_RA], ra_rnti); - q->current_search_mode = SEARCH_RA; +int pdcch_init_search_ra(pdcch_t *q, uint16_t ra_rnti, uint8_t cfi) { + set_cfi(q, cfi); + int r = pdcch_init_common(q, &q->search_mode[SEARCH_RA], ra_rnti); + if (r >= 0) { + q->current_search_mode = SEARCH_RA; + } + return r; } void pdcch_set_search_si(pdcch_t *q) { @@ -179,110 +212,94 @@ void pdcch_set_search_ra(pdcch_t *q) { q->current_search_mode = SEARCH_RA; } -int pdcch_set_cfi(pdcch_t *q, int cfi) { - if (cfi == -1) { - q->nof_bits = -1; - q->nof_symbols = -1; - q->nof_cce = -1; - q->nof_regs = -1; - return 0; - } else if (cfi < 4 && cfi > 0) { +void set_cfi(pdcch_t *q, uint8_t cfi) { + if (cfi > 0 && cfi < 4) { q->nof_regs = (regs_pdcch_nregs(q->regs, cfi) / 9) * 9; q->nof_cce = q->nof_regs / 9; q->nof_symbols = 4 * q->nof_regs; q->nof_bits = 2 * q->nof_symbols; - return 0; - } else { - return -1; - } + } } /** Initializes the PDCCH transmitter and receiver */ -int pdcch_init(pdcch_t *q, regs_t *regs, int nof_prb, int nof_ports, - int cell_id, lte_cp_t cp) { - int ret = -1; +int pdcch_init(pdcch_t *q, regs_t *regs, lte_cell_t cell) { + int ret = LIBLTE_ERROR_INVALID_INPUTS; int i; - if (cell_id < 0) { - return -1; - } - if (nof_ports > MAX_PORTS) { - fprintf(stderr, "Invalid number of ports %d\n", nof_ports); - return -1; - } - bzero(q, sizeof(pdcch_t)); - q->cell_id = cell_id; - q->cp = cp; - q->regs = regs; - q->nof_ports = nof_ports; - q->nof_prb = nof_prb; - q->current_search_mode = SEARCH_NONE; - - /* Now allocate memory for the maximum number of REGs (CFI=2), then can - * be changed at runtime - */ - pdcch_set_cfi(q, 3); - - INFO("Init PDCCH: %d CCEs (%d REGs), %d bits, %d symbols, %d ports\n", - q->nof_cce, q->nof_regs, q->nof_bits, q->nof_symbols, q->nof_ports); - - if (modem_table_std(&q->mod, LTE_QPSK, true)) { - goto clean; - } - if (crc_init(&q->crc, LTE_CRC16, 16)) { - goto clean; - } - - demod_soft_init(&q->demod); - demod_soft_table_set(&q->demod, &q->mod); - demod_soft_alg_set(&q->demod, APPROX); - - for (i = 0; i < NSUBFRAMES_X_FRAME; i++) { - if (sequence_pdcch(&q->seq_pdcch[i], 2 * i, q->cell_id, q->nof_bits)) { + if (q != NULL && + regs != NULL && + lte_cell_isvalid(&cell)) + { + ret = LIBLTE_ERROR; + bzero(q, sizeof(pdcch_t)); + q->cell = cell; + q->regs = regs; + q->current_search_mode = SEARCH_NONE; + + /* Now allocate memory for the maximum number of REGs (CFI=3) + */ + set_cfi(q, 3); + q->max_bits = q->nof_bits; + + INFO("Init PDCCH: %d CCEs (%d REGs), %d bits, %d symbols, %d ports\n", + q->nof_cce, q->nof_regs, q->nof_bits, q->nof_symbols, q->cell.nof_ports); + + if (modem_table_std(&q->mod, LTE_QPSK, true)) { + goto clean; + } + if (crc_init(&q->crc, LTE_CRC16, 16)) { goto clean; } - } - - int poly[3] = { 0x6D, 0x4F, 0x57 }; - if (viterbi_init(&q->decoder, viterbi_37, poly, DCI_MAX_BITS + 16, true)) { - goto clean; - } - q->pdcch_e = malloc(sizeof(char) * q->nof_bits); - if (!q->pdcch_e) { - goto clean; - } + demod_soft_init(&q->demod); + demod_soft_table_set(&q->demod, &q->mod); + demod_soft_alg_set(&q->demod, APPROX); - q->pdcch_llr = malloc(sizeof(float) * q->nof_bits); - if (!q->pdcch_llr) { - goto clean; - } + for (i = 0; i < NSUBFRAMES_X_FRAME; i++) { + if (sequence_pdcch(&q->seq_pdcch[i], 2 * i, q->cell.id, q->nof_bits)) { + goto clean; + } + } - q->pdcch_d = malloc(sizeof(cf_t) * q->nof_symbols); - if (!q->pdcch_d) { - goto clean; - } + int poly[3] = { 0x6D, 0x4F, 0x57 }; + if (viterbi_init(&q->decoder, viterbi_37, poly, DCI_MAX_BITS + 16, true)) { + goto clean; + } - for (i = 0; i < MAX_PORTS; i++) { - q->ce[i] = malloc(sizeof(cf_t) * q->nof_symbols); - if (!q->ce[i]) { + q->pdcch_e = malloc(sizeof(char) * q->nof_bits); + if (!q->pdcch_e) { goto clean; } - q->pdcch_x[i] = malloc(sizeof(cf_t) * q->nof_symbols); - if (!q->pdcch_x[i]) { + + q->pdcch_llr = malloc(sizeof(float) * q->nof_bits); + if (!q->pdcch_llr) { goto clean; } - q->pdcch_symbols[i] = malloc(sizeof(cf_t) * q->nof_symbols); - if (!q->pdcch_symbols[i]) { + + q->pdcch_d = malloc(sizeof(cf_t) * q->nof_symbols); + if (!q->pdcch_d) { goto clean; } - } - /* Reset CFI to make sure we return error if new CFI is not set */ - pdcch_set_cfi(q, -1); + for (i = 0; i < MAX_PORTS; i++) { + q->ce[i] = malloc(sizeof(cf_t) * q->nof_symbols); + if (!q->ce[i]) { + goto clean; + } + q->pdcch_x[i] = malloc(sizeof(cf_t) * q->nof_symbols); + if (!q->pdcch_x[i]) { + goto clean; + } + q->pdcch_symbols[i] = malloc(sizeof(cf_t) * q->nof_symbols); + if (!q->pdcch_symbols[i]) { + goto clean; + } + } - ret = 0; - clean: if (ret == -1) { + ret = LIBLTE_SUCCESS; + } + clean: + if (ret == LIBLTE_ERROR) { pdcch_free(q); } return ret; @@ -326,44 +343,58 @@ void pdcch_free(pdcch_t *q) { * * TODO: UE transmit antenna selection CRC mask */ -unsigned short dci_decode(pdcch_t *q, float *e, char *data, int E, int nof_bits) { +int dci_decode(pdcch_t *q, float *e, char *data, uint16_t E, uint16_t nof_bits, uint16_t *crc) { float tmp[3 * (DCI_MAX_BITS + 16)]; - unsigned short p_bits, crc_res; + uint16_t p_bits, crc_res; char *x; - assert(nof_bits < DCI_MAX_BITS); + if (q != NULL && + data != NULL && + E < q->max_bits && + nof_bits < DCI_MAX_BITS) + { - /* unrate matching */ - rm_conv_rx(e, E, tmp, 3 * (nof_bits + 16)); + /* unrate matching */ + rm_conv_rx(e, E, tmp, 3 * (nof_bits + 16)); - DEBUG("Viterbi input: ", 0); - if (VERBOSE_ISDEBUG()) { - vec_fprint_f(stdout, tmp, 3 * (nof_bits + 16)); - } + DEBUG("Viterbi input: ", 0); + if (VERBOSE_ISDEBUG()) { + vec_fprint_f(stdout, tmp, 3 * (nof_bits + 16)); + } - /* viterbi decoder */ - viterbi_decode_f(&q->decoder, tmp, data, nof_bits + 16); + /* viterbi decoder */ + viterbi_decode_f(&q->decoder, tmp, data, nof_bits + 16); - if (VERBOSE_ISDEBUG()) { - bit_fprint(stdout, data, nof_bits + 16); - } + if (VERBOSE_ISDEBUG()) { + bit_fprint(stdout, data, nof_bits + 16); + } - x = &data[nof_bits]; - p_bits = (unsigned short) bit_unpack(&x, 16); - crc_res = ((unsigned short) crc_checksum(&q->crc, data, nof_bits) & 0xffff); - DEBUG("p_bits: 0x%x, crc_res: 0x%x, tot: 0x%x\n", p_bits, crc_res, - p_bits ^ crc_res); - return (p_bits ^ crc_res); + x = &data[nof_bits]; + p_bits = (uint16_t) bit_unpack(&x, 16); + crc_res = ((uint16_t) crc_checksum(&q->crc, data, nof_bits) & 0xffff); + DEBUG("p_bits: 0x%x, crc_res: 0x%x, tot: 0x%x\n", p_bits, crc_res, + p_bits ^ crc_res); + + if (crc) { + *crc = p_bits ^ crc_res; + } + return LIBLTE_SUCCESS; + } else { + return LIBLTE_ERROR_INVALID_INPUTS; + } } int pdcch_decode_candidate(pdcch_t *q, float *llr, dci_candidate_t *c, dci_msg_t *msg) { - unsigned short crc_res; + uint16_t crc_res; INFO("Trying Candidate: Nbits: %d, E: %3d, nCCE: %d, L: %d, RNTI: 0x%x\n", c->nof_bits, PDCCH_FORMAT_NOF_BITS(c->L), c->ncce, c->L, c->rnti); - crc_res = dci_decode(q, &llr[72 * c->ncce], msg->data, - PDCCH_FORMAT_NOF_BITS(c->L), c->nof_bits); + + if (dci_decode(q, &llr[72 * c->ncce], msg->data, + PDCCH_FORMAT_NOF_BITS(c->L), c->nof_bits, &crc_res)) { + return LIBLTE_ERROR; + } if (c->rnti == crc_res) { memcpy(&msg->location, c, sizeof(dci_candidate_t)); @@ -371,85 +402,88 @@ int pdcch_decode_candidate(pdcch_t *q, float *llr, dci_candidate_t *c, c->nof_bits, PDCCH_FORMAT_NOF_BITS(c->L), c->ncce, c->L, c->rnti); return 1; } - return 0; + return LIBLTE_SUCCESS; } int pdcch_extract_llr(pdcch_t *q, cf_t *slot_symbols, cf_t *ce[MAX_PORTS], - float *llr, int nsubframe) { + float *llr, uint8_t nsubframe, uint8_t cfi) { /* Set pointers for layermapping & precoding */ int i; cf_t *x[MAX_LAYERS]; - if (q->nof_bits == -1 || q->nof_cce == -1 || q->nof_regs == -1) { - fprintf(stderr, "Must call pdcch_set_cfi() first to set the CFI\n"); - return -1; - } - - if (nsubframe < 0 || nsubframe > NSUBFRAMES_X_FRAME) { - fprintf(stderr, "Invalid subframe %d\n", nsubframe); - return -1; - } - - /* number of layers equals number of ports */ - for (i = 0; i < q->nof_ports; i++) { - x[i] = q->pdcch_x[i]; - } - memset(&x[q->nof_ports], 0, sizeof(cf_t*) * (MAX_LAYERS - q->nof_ports)); - - /* extract symbols */ - int n = regs_pdcch_get(q->regs, slot_symbols, q->pdcch_symbols[0]); - if (q->nof_symbols != n) { - fprintf(stderr, "Expected %d PDCCH symbols but got %d symbols\n", - q->nof_symbols, n); - return -1; - } + if (q != NULL && + llr != NULL && + slot_symbols != NULL && + nsubframe < 10 && + cfi > 0 && + cfi < 4) + { + set_cfi(q, cfi); + + /* number of layers equals number of ports */ + for (i = 0; i < q->cell.nof_ports; i++) { + x[i] = q->pdcch_x[i]; + } + memset(&x[q->cell.nof_ports], 0, sizeof(cf_t*) * (MAX_LAYERS - q->cell.nof_ports)); - /* extract channel estimates */ - for (i = 0; i < q->nof_ports; i++) { - n = regs_pdcch_get(q->regs, ce[i], q->ce[i]); + /* extract symbols */ + int n = regs_pdcch_get(q->regs, slot_symbols, q->pdcch_symbols[0]); if (q->nof_symbols != n) { fprintf(stderr, "Expected %d PDCCH symbols but got %d symbols\n", q->nof_symbols, n); - return -1; + return LIBLTE_ERROR; } - } - /* in control channels, only diversity is supported */ - if (q->nof_ports == 1) { - /* no need for layer demapping */ - predecoding_single_zf(q->pdcch_symbols[0], q->ce[0], q->pdcch_d, - q->nof_symbols); - } else { - predecoding_diversity_zf(q->pdcch_symbols[0], q->ce, x, q->nof_ports, - q->nof_symbols); - layerdemap_diversity(x, q->pdcch_d, q->nof_ports, - q->nof_symbols / q->nof_ports); - } + /* extract channel estimates */ + for (i = 0; i < q->cell.nof_ports; i++) { + n = regs_pdcch_get(q->regs, ce[i], q->ce[i]); + if (q->nof_symbols != n) { + fprintf(stderr, "Expected %d PDCCH symbols but got %d symbols\n", + q->nof_symbols, n); + return LIBLTE_ERROR; + } + } - DEBUG("pdcch d symbols: ", 0); - if (VERBOSE_ISDEBUG()) { - vec_fprint_c(stdout, q->pdcch_d, q->nof_symbols); - } + /* in control channels, only diversity is supported */ + if (q->cell.nof_ports == 1) { + /* no need for layer demapping */ + predecoding_single_zf(q->pdcch_symbols[0], q->ce[0], q->pdcch_d, + q->nof_symbols); + } else { + predecoding_diversity_zf(q->pdcch_symbols[0], q->ce, x, q->cell.nof_ports, + q->nof_symbols); + layerdemap_diversity(x, q->pdcch_d, q->cell.nof_ports, + q->nof_symbols / q->cell.nof_ports); + } - /* demodulate symbols */ - demod_soft_sigma_set(&q->demod, 1.0); - demod_soft_demodulate(&q->demod, q->pdcch_d, q->pdcch_llr, q->nof_symbols); + DEBUG("pdcch d symbols: ", 0); + if (VERBOSE_ISDEBUG()) { + vec_fprint_c(stdout, q->pdcch_d, q->nof_symbols); + } - DEBUG("llr: ", 0); - if (VERBOSE_ISDEBUG()) { - vec_fprint_f(stdout, q->pdcch_llr, q->nof_bits); - } + /* demodulate symbols */ + demod_soft_sigma_set(&q->demod, 1.0); + demod_soft_demodulate(&q->demod, q->pdcch_d, q->pdcch_llr, q->nof_symbols); + + DEBUG("llr: ", 0); + if (VERBOSE_ISDEBUG()) { + vec_fprint_f(stdout, q->pdcch_llr, q->nof_bits); + } - /* descramble */ - scrambling_f_offset(&q->seq_pdcch[nsubframe], llr, 0, q->nof_bits); + /* descramble */ + scrambling_f_offset(&q->seq_pdcch[nsubframe], llr, 0, q->nof_bits); - return 0; + return LIBLTE_SUCCESS; + } else { + return LIBLTE_ERROR_INVALID_INPUTS; + } } -int pdcch_decode_current_mode(pdcch_t *q, float *llr, dci_t *dci, int subframe) { +int pdcch_decode_current_mode(pdcch_t *q, float *llr, dci_t *dci, uint8_t subframe) { int k, i; - + int ret; + if (q->current_search_mode == SEARCH_UE) { k = subframe; } else { @@ -459,10 +493,13 @@ int pdcch_decode_current_mode(pdcch_t *q, float *llr, dci_t *dci, int subframe) for (i = 0; i < q->search_mode[q->current_search_mode].nof_candidates && dci->nof_dcis < dci->max_dcis; i++) { - if (pdcch_decode_candidate(q, q->pdcch_llr, + ret = pdcch_decode_candidate(q, q->pdcch_llr, &q->search_mode[q->current_search_mode].candidates[k][i], - &dci->msg[dci->nof_dcis])) { + &dci->msg[dci->nof_dcis]); + if (ret == 1) { dci->nof_dcis++; + } else if (ret == -1) { + return LIBLTE_ERROR; } } return dci->nof_dcis; @@ -476,7 +513,7 @@ int pdcch_decode_ra(pdcch_t *q, float *llr, dci_t *dci) { pdcch_set_search_ra(q); return pdcch_decode_current_mode(q, llr, dci, 0); } -int pdcch_decode_ue(pdcch_t *q, float *llr, dci_t *dci, int nsubframe) { +int pdcch_decode_ue(pdcch_t *q, float *llr, dci_t *dci, uint8_t nsubframe) { pdcch_set_search_ue(q); return pdcch_decode_current_mode(q, llr, dci, nsubframe); } @@ -488,25 +525,30 @@ int pdcch_decode_ue(pdcch_t *q, float *llr, dci_t *dci, int nsubframe) { * Returns number of messages stored in dci */ int pdcch_decode(pdcch_t *q, cf_t *slot_symbols, cf_t *ce[MAX_PORTS], - dci_t *dci, int nsubframe) { - - if (q->nof_bits == -1 || q->nof_cce == -1 || q->nof_regs == -1) { - fprintf(stderr, "Must call pdcch_set_cfi() first to set the CFI\n"); - return -1; - } + dci_t *dci, uint8_t subframe, uint8_t cfi) { + + if (q != NULL && + dci != NULL && + slot_symbols != NULL && + subframe < 10 && + cfi > 0 && + cfi < 4) + { + if (pdcch_extract_llr(q, slot_symbols, ce, q->pdcch_llr, subframe, cfi)) { + return LIBLTE_ERROR; + } - if (pdcch_extract_llr(q, slot_symbols, ce, q->pdcch_llr, nsubframe)) { - return -1; - } + if (q->current_search_mode != SEARCH_NONE) { + return pdcch_decode_current_mode(q, q->pdcch_llr, dci, subframe); + } - if (q->current_search_mode != SEARCH_NONE) { - return pdcch_decode_current_mode(q, q->pdcch_llr, dci, nsubframe); + return LIBLTE_SUCCESS; + } else { + return LIBLTE_ERROR_INVALID_INPUTS; } - - return 0; } -void crc_set_mask_rnti(char *crc, unsigned short rnti) { +void crc_set_mask_rnti(char *crc, uint16_t rnti) { int i; char mask[16]; char *r = mask; @@ -522,96 +564,110 @@ void crc_set_mask_rnti(char *crc, unsigned short rnti) { /** 36.212 5.3.3.2 to 5.3.3.4 * TODO: UE transmit antenna selection CRC mask */ -void dci_encode(pdcch_t *q, char *data, char *e, int nof_bits, int E, - unsigned short rnti) { +int dci_encode(pdcch_t *q, char *data, char *e, uint16_t nof_bits, uint16_t E, + uint16_t rnti) { convcoder_t encoder; char tmp[3 * (DCI_MAX_BITS + 16)]; + + if (q != NULL && + data != NULL && + e != NULL && + nof_bits < DCI_MAX_BITS && + E < q->max_bits) + { + + int poly[3] = { 0x6D, 0x4F, 0x57 }; + encoder.K = 7; + encoder.R = 3; + encoder.tail_biting = true; + memcpy(encoder.poly, poly, 3 * sizeof(int)); + + crc_attach(&q->crc, data, nof_bits); + crc_set_mask_rnti(&data[nof_bits], rnti); + + convcoder_encode(&encoder, data, tmp, nof_bits + 16); + + DEBUG("CConv output: ", 0); + if (VERBOSE_ISDEBUG()) { + vec_fprint_b(stdout, tmp, 3 * (nof_bits + 16)); + } - assert(nof_bits < DCI_MAX_BITS); - - int poly[3] = { 0x6D, 0x4F, 0x57 }; - encoder.K = 7; - encoder.R = 3; - encoder.tail_biting = true; - memcpy(encoder.poly, poly, 3 * sizeof(int)); - - crc_attach(&q->crc, data, nof_bits); - crc_set_mask_rnti(&data[nof_bits], rnti); - - convcoder_encode(&encoder, data, tmp, nof_bits + 16); - - DEBUG("CConv output: ", 0); - if (VERBOSE_ISDEBUG()) { - vec_fprint_b(stdout, tmp, 3 * (nof_bits + 16)); + rm_conv_tx(tmp, 3 * (nof_bits + 16), e, E); + + return LIBLTE_SUCCESS; + } else { + return LIBLTE_ERROR_INVALID_INPUTS; } - - rm_conv_tx(tmp, 3 * (nof_bits + 16), e, E); } /** Converts the set of DCI messages to symbols mapped to the slot ready for transmission */ int pdcch_encode(pdcch_t *q, dci_t *dci, cf_t *slot_symbols[MAX_PORTS], - int nsubframe) { + uint8_t nsubframe, uint8_t cfi) { int i; /* Set pointers for layermapping & precoding */ cf_t *x[MAX_LAYERS]; + + if (q != NULL && + dci != NULL && + slot_symbols != NULL && + nsubframe < 10 && + cfi > 0 && + cfi < 4) + { + set_cfi(q, cfi); + + /* number of layers equals number of ports */ + for (i = 0; i < q->cell.nof_ports; i++) { + x[i] = q->pdcch_x[i]; + } + memset(&x[q->cell.nof_ports], 0, sizeof(cf_t*) * (MAX_LAYERS - q->cell.nof_ports)); + + /* should add elements? Or maybe random bits to facilitate power estimation */ + bzero(q->pdcch_e, q->nof_bits); + + /* Encode DCIs */ + for (i = 0; i < dci->nof_dcis; i++) { + /* do some checks */ + if (dci->msg[i].location.ncce + PDCCH_FORMAT_NOF_CCE(dci->msg[i].location.L) + > q->nof_cce || dci->msg[i].location.L > 3 + || dci->msg[i].location.nof_bits > DCI_MAX_BITS) { + fprintf(stderr, "Illegal DCI message nCCE: %d, L: %d, nof_cce: %d\n", + dci->msg[i].location.ncce, dci->msg[i].location.L, q->nof_cce); + return LIBLTE_ERROR; + } + INFO("Encoding DCI %d: Nbits: %d, E: %d, nCCE: %d, L: %d, RNTI: 0x%x\n", i, + dci->msg[i].location.nof_bits, + PDCCH_FORMAT_NOF_BITS(dci->msg[i].location.L), + dci->msg[i].location.ncce, dci->msg[i].location.L, + dci->msg[i].location.rnti); + + dci_encode(q, dci->msg[i].data, &q->pdcch_e[72 * dci->msg[i].location.ncce], + dci->msg[i].location.nof_bits, + PDCCH_FORMAT_NOF_BITS(dci->msg[i].location.L), + dci->msg[i].location.rnti); + } - if (q->nof_bits == -1 || q->nof_cce == -1 || q->nof_regs == -1) { - fprintf(stderr, "Must call pdcch_set_cfi() first to set the CFI\n"); - return -1; - } - if (nsubframe < 0 || nsubframe > NSUBFRAMES_X_FRAME) { - fprintf(stderr, "Invalid subframe %d\n", nsubframe); - return -1; - } - - /* number of layers equals number of ports */ - for (i = 0; i < q->nof_ports; i++) { - x[i] = q->pdcch_x[i]; - } - memset(&x[q->nof_ports], 0, sizeof(cf_t*) * (MAX_LAYERS - q->nof_ports)); - - /* should add elements? Or maybe random bits to facilitate power estimation */ - bzero(q->pdcch_e, q->nof_bits); - - /* Encode DCIs */ - for (i = 0; i < dci->nof_dcis; i++) { - /* do some sanity checks */ - if (dci->msg[i].location.ncce + PDCCH_FORMAT_NOF_CCE(dci->msg[i].location.L) - > q->nof_cce || dci->msg[i].location.L > 3 - || dci->msg[i].location.nof_bits > DCI_MAX_BITS) { - fprintf(stderr, "Illegal DCI message %d\n", i); - return -1; - } - INFO("Encoding DCI %d: Nbits: %d, E: %d, nCCE: %d, L: %d, RNTI: 0x%x\n", i, - dci->msg[i].location.nof_bits, - PDCCH_FORMAT_NOF_BITS(dci->msg[i].location.L), - dci->msg[i].location.ncce, dci->msg[i].location.L, - dci->msg[i].location.rnti); - - dci_encode(q, dci->msg[i].data, &q->pdcch_e[72 * dci->msg[i].location.ncce], - dci->msg[i].location.nof_bits, - PDCCH_FORMAT_NOF_BITS(dci->msg[i].location.L), - dci->msg[i].location.rnti); - } + scrambling_b_offset(&q->seq_pdcch[nsubframe], q->pdcch_e, 0, q->nof_bits); - scrambling_b_offset(&q->seq_pdcch[nsubframe], q->pdcch_e, 0, q->nof_bits); + mod_modulate(&q->mod, q->pdcch_e, q->pdcch_d, q->nof_bits); - mod_modulate(&q->mod, q->pdcch_e, q->pdcch_d, q->nof_bits); + /* layer mapping & precoding */ + if (q->cell.nof_ports > 1) { + layermap_diversity(q->pdcch_d, x, q->cell.nof_ports, q->nof_symbols); + precoding_diversity(x, q->pdcch_symbols, q->cell.nof_ports, + q->nof_symbols / q->cell.nof_ports); + } else { + memcpy(q->pdcch_symbols[0], q->pdcch_d, q->nof_symbols * sizeof(cf_t)); + } - /* layer mapping & precoding */ - if (q->nof_ports > 1) { - layermap_diversity(q->pdcch_d, x, q->nof_ports, q->nof_symbols); - precoding_diversity(x, q->pdcch_symbols, q->nof_ports, - q->nof_symbols / q->nof_ports); + /* mapping to resource elements */ + for (i = 0; i < q->cell.nof_ports; i++) { + regs_pdcch_put(q->regs, q->pdcch_symbols[i], slot_symbols[i]); + } + return LIBLTE_SUCCESS; } else { - memcpy(q->pdcch_symbols[0], q->pdcch_d, q->nof_symbols * sizeof(cf_t)); - } - - /* mapping to resource elements */ - for (i = 0; i < q->nof_ports; i++) { - regs_pdcch_put(q->regs, q->pdcch_symbols[i], slot_symbols[i]); + return LIBLTE_ERROR_INVALID_INPUTS; } - return 0; } diff --git a/lte/phy/lib/phch/src/pdsch.c b/lte/phy/lib/phch/src/pdsch.c index c3de1494b..a5459a480 100644 --- a/lte/phy/lib/phch/src/pdsch.c +++ b/lte/phy/lib/phch/src/pdsch.c @@ -41,24 +41,35 @@ #include "liblte/phy/utils/debug.h" #include "liblte/phy/utils/vector.h" -const enum modem_std modulations[4] = - { LTE_BPSK, LTE_QPSK, LTE_QAM16, LTE_QAM64 }; #define MAX_PDSCH_RE(cp) (2 * CP_NSYMB(cp) * 12) + + +const enum modem_std modulations[4] = + { LTE_BPSK, LTE_QPSK, LTE_QAM16, LTE_QAM64 }; + + +struct cb_segm { + int F; + int C; + int K1; + int K2; + int C1; + int C2; +}; + int pdsch_cp(pdsch_t *q, cf_t *input, cf_t *output, ra_prb_t *prb_alloc, - int nsubframe, bool put) { + uint8_t nsubframe, bool put) { int s, n, l, lp, lstart, lend, nof_refs; bool is_pbch, is_sss; cf_t *in_ptr = input, *out_ptr = output; int offset; - assert(q->cell_id >= 0); - INFO("%s %d RE from %d PRB\n", put ? "Putting" : "Getting", prb_alloc->re_sf[nsubframe], prb_alloc->slot[0].nof_prb); - if (q->nof_ports == 1) { + if (q->cell.nof_ports == 1) { nof_refs = 2; } else { nof_refs = 4; @@ -66,66 +77,66 @@ int pdsch_cp(pdsch_t *q, cf_t *input, cf_t *output, ra_prb_t *prb_alloc, for (s = 0; s < 2; s++) { - for (l = 0; l < CP_NSYMB(q->cp); l++) { + for (l = 0; l < CP_NSYMB(q->cell.cp); l++) { for (n = 0; n < prb_alloc->slot[s].nof_prb; n++) { if (s == 0) { lstart = prb_alloc->lstart; } else { lstart = 0; } - lend = CP_NSYMB(q->cp); + lend = CP_NSYMB(q->cell.cp); is_pbch = is_sss = false; // Skip PSS/SSS signals if (s == 0 && (nsubframe == 0 || nsubframe == 5)) { - if (prb_alloc->slot[s].prb_idx[n] >= q->nof_prb / 2 - 3 - && prb_alloc->slot[s].prb_idx[n] <= q->nof_prb / 2 + 3) { - lend = CP_NSYMB(q->cp) - 2; + if (prb_alloc->slot[s].prb_idx[n] >= q->cell.nof_prb / 2 - 3 + && prb_alloc->slot[s].prb_idx[n] <= q->cell.nof_prb / 2 + 3) { + lend = CP_NSYMB(q->cell.cp) - 2; is_sss = true; } } // Skip PBCH if (s == 1 && nsubframe == 0) { - if (prb_alloc->slot[s].prb_idx[n] >= q->nof_prb / 2 - 3 - && prb_alloc->slot[s].prb_idx[n] <= q->nof_prb / 2 + 3) { + if (prb_alloc->slot[s].prb_idx[n] >= q->cell.nof_prb / 2 - 3 + && prb_alloc->slot[s].prb_idx[n] <= q->cell.nof_prb / 2 + 3) { lstart = 4; is_pbch = true; } } - lp = l + s * CP_NSYMB(q->cp); + lp = l + s * CP_NSYMB(q->cell.cp); if (put) { - out_ptr = &output[(lp * q->nof_prb + prb_alloc->slot[s].prb_idx[n]) + out_ptr = &output[(lp * q->cell.nof_prb + prb_alloc->slot[s].prb_idx[n]) * RE_X_RB]; } else { - in_ptr = &input[(lp * q->nof_prb + prb_alloc->slot[s].prb_idx[n]) + in_ptr = &input[(lp * q->cell.nof_prb + prb_alloc->slot[s].prb_idx[n]) * RE_X_RB]; } if (l >= lstart && l < lend) { - if (SYMBOL_HAS_REF(l, q->cp, q->nof_ports)) { + if (SYMBOL_HAS_REF(l, q->cell.cp, q->cell.nof_ports)) { if (nof_refs == 2 && l != 0) { - offset = q->cell_id % 3 + 3; + offset = q->cell.id % 3 + 3; } else { - offset = q->cell_id % 3; + offset = q->cell.id % 3; } prb_cp_ref(&in_ptr, &out_ptr, offset, nof_refs, nof_refs, put); } else { prb_cp(&in_ptr, &out_ptr, 1); } } - if ((q->nof_prb % 2) && ((is_pbch && l < lstart) || (is_sss && l >= lend))) { - if (prb_alloc->slot[s].prb_idx[n] == q->nof_prb / 2 - 3) { - if (SYMBOL_HAS_REF(l, q->cp, q->nof_ports)) { + if ((q->cell.nof_prb % 2) && ((is_pbch && l < lstart) || (is_sss && l >= lend))) { + if (prb_alloc->slot[s].prb_idx[n] == q->cell.nof_prb / 2 - 3) { + if (SYMBOL_HAS_REF(l, q->cell.cp, q->cell.nof_ports)) { prb_cp_ref(&in_ptr, &out_ptr, offset, nof_refs, nof_refs/2, put); } else { prb_cp_half(&in_ptr, &out_ptr, 1); } - } else if (prb_alloc->slot[s].prb_idx[n] == q->nof_prb / 2 + 3) { + } else if (prb_alloc->slot[s].prb_idx[n] == q->cell.nof_prb / 2 + 3) { if (put) { out_ptr += 6; } else { in_ptr += 6; } - if (SYMBOL_HAS_REF(l, q->cp, q->nof_ports)) { + if (SYMBOL_HAS_REF(l, q->cell.cp, q->cell.nof_ports)) { prb_cp_ref(&in_ptr, &out_ptr, offset, nof_refs, nof_refs/2, put); } else { prb_cp_half(&in_ptr, &out_ptr, 1); @@ -151,8 +162,8 @@ int pdsch_cp(pdsch_t *q, cf_t *input, cf_t *output, ra_prb_t *prb_alloc, * 36.211 10.3 section 6.3.5 */ int pdsch_put(pdsch_t *q, cf_t *pdsch_symbols, cf_t *sf_symbols, - ra_prb_t *prb_alloc, int nsubframe) { - return pdsch_cp(q, pdsch_symbols, sf_symbols, prb_alloc, nsubframe, true); + ra_prb_t *prb_alloc, uint8_t subframe) { + return pdsch_cp(q, pdsch_symbols, sf_symbols, prb_alloc, subframe, true); } /** @@ -163,117 +174,112 @@ int pdsch_put(pdsch_t *q, cf_t *pdsch_symbols, cf_t *sf_symbols, * 36.211 10.3 section 6.3.5 */ int pdsch_get(pdsch_t *q, cf_t *sf_symbols, cf_t *pdsch_symbols, - ra_prb_t *prb_alloc, int nsubframe) { - return pdsch_cp(q, sf_symbols, pdsch_symbols, prb_alloc, nsubframe, false); + ra_prb_t *prb_alloc, uint8_t subframe) { + return pdsch_cp(q, sf_symbols, pdsch_symbols, prb_alloc, subframe, false); } /** Initializes the PDCCH transmitter and receiver */ -int pdsch_init(pdsch_t *q, unsigned short user_rnti, int nof_prb, int nof_ports, - int cell_id, lte_cp_t cp) { - int ret = -1; +int pdsch_init(pdsch_t *q, uint16_t user_rnti, lte_cell_t cell) { + int ret = LIBLTE_ERROR_INVALID_INPUTS; int i; - if (cell_id < 0) { - return -1; - } - - if (nof_ports > MAX_PORTS) { - fprintf(stderr, "Invalid number of ports %d\n", nof_ports); - return -1; - } - - bzero(q, sizeof(pdsch_t)); - q->cell_id = cell_id; - q->cp = cp; - q->nof_ports = nof_ports; - q->nof_prb = nof_prb; - q->rnti = user_rnti; + if (q != NULL && + lte_cell_isvalid(&cell)) + { + + bzero(q, sizeof(pdsch_t)); + ret = LIBLTE_ERROR; + + q->cell = cell; + q->rnti = user_rnti; - q->max_symbols = nof_prb * MAX_PDSCH_RE(cp); + q->max_symbols = q->cell.nof_prb * MAX_PDSCH_RE(q->cell.cp); - INFO("Init PDSCH: %d ports %d PRBs, max_symbols: %d\n", q->nof_ports, - q->nof_prb, q->max_symbols); + INFO("Init PDSCH: %d ports %d PRBs, max_symbols: %d\n", q->cell.nof_ports, + q->cell.nof_prb, q->max_symbols); - for (i = 0; i < 4; i++) { - if (modem_table_std(&q->mod[i], modulations[i], true)) { + for (i = 0; i < 4; i++) { + if (modem_table_std(&q->mod[i], modulations[i], true)) { + goto clean; + } + } + if (crc_init(&q->crc_tb, LTE_CRC24A, 24)) { goto clean; } - } - if (crc_init(&q->crc_tb, LTE_CRC24A, 24)) { - goto clean; - } - if (crc_init(&q->crc_cb, LTE_CRC24B, 24)) { - goto clean; - } - - demod_soft_init(&q->demod); - demod_soft_alg_set(&q->demod, APPROX); - - for (i = 0; i < NSUBFRAMES_X_FRAME; i++) { - if (sequence_pdsch(&q->seq_pdsch[i], q->rnti, 0, 2 * i, q->cell_id, - q->max_symbols * q->mod[3].nbits_x_symbol)) { + if (crc_init(&q->crc_cb, LTE_CRC24B, 24)) { goto clean; } - } - if (tcod_init(&q->encoder, MAX_LONG_CB)) { - goto clean; - } - if (tdec_init(&q->decoder, MAX_LONG_CB)) { - goto clean; - } - if (rm_turbo_init(&q->rm_turbo, 3 * MAX_LONG_CB)) { - goto clean; - } + demod_soft_init(&q->demod); + demod_soft_alg_set(&q->demod, APPROX); - q->cb_in_b = malloc(sizeof(char) * MAX_LONG_CB); - if (!q->cb_in_b) { - goto clean; - } - q->cb_out_b = malloc(sizeof(char) * (3 * MAX_LONG_CB + 12)); - if (!q->cb_out_b) { - goto clean; - } - - q->pdsch_rm_f = malloc(sizeof(float) * (3 * MAX_LONG_CB + 12)); - if (!q->pdsch_rm_f) { - goto clean; - } + for (i = 0; i < NSUBFRAMES_X_FRAME; i++) { + if (sequence_pdsch(&q->seq_pdsch[i], q->rnti, 0, 2 * i, q->cell.id, + q->max_symbols * q->mod[3].nbits_x_symbol)) { + goto clean; + } + } - q->pdsch_e_bits = malloc( - sizeof(char) * q->max_symbols * q->mod[3].nbits_x_symbol); - if (!q->pdsch_e_bits) { - goto clean; - } + if (tcod_init(&q->encoder, MAX_LONG_CB)) { + goto clean; + } + if (tdec_init(&q->decoder, MAX_LONG_CB)) { + goto clean; + } + if (rm_turbo_init(&q->rm_turbo, 3 * MAX_LONG_CB)) { + goto clean; + } - q->pdsch_llr = malloc( - sizeof(float) * q->max_symbols * q->mod[3].nbits_x_symbol); - if (!q->pdsch_llr) { - goto clean; - } + q->cb_in_b = malloc(sizeof(char) * MAX_LONG_CB); + if (!q->cb_in_b) { + goto clean; + } + q->cb_out_b = malloc(sizeof(char) * (3 * MAX_LONG_CB + 12)); + if (!q->cb_out_b) { + goto clean; + } - q->pdsch_d = malloc(sizeof(cf_t) * q->max_symbols); - if (!q->pdsch_d) { - goto clean; - } + q->pdsch_rm_f = malloc(sizeof(float) * (3 * MAX_LONG_CB + 12)); + if (!q->pdsch_rm_f) { + goto clean; + } - for (i = 0; i < nof_ports; i++) { - q->ce[i] = malloc(sizeof(cf_t) * q->max_symbols); - if (!q->ce[i]) { + q->pdsch_e_bits = malloc( + sizeof(char) * q->max_symbols * q->mod[3].nbits_x_symbol); + if (!q->pdsch_e_bits) { goto clean; } - q->pdsch_x[i] = malloc(sizeof(cf_t) * q->max_symbols); - if (!q->pdsch_x[i]) { + + q->pdsch_llr = malloc( + sizeof(float) * q->max_symbols * q->mod[3].nbits_x_symbol); + if (!q->pdsch_llr) { goto clean; } - q->pdsch_symbols[i] = malloc(sizeof(cf_t) * q->max_symbols); - if (!q->pdsch_symbols[i]) { + + q->pdsch_d = malloc(sizeof(cf_t) * q->max_symbols); + if (!q->pdsch_d) { goto clean; } - } - ret = 0; - clean: if (ret == -1) { + for (i = 0; i < q->cell.nof_ports; i++) { + q->ce[i] = malloc(sizeof(cf_t) * q->max_symbols); + if (!q->ce[i]) { + goto clean; + } + q->pdsch_x[i] = malloc(sizeof(cf_t) * q->max_symbols); + if (!q->pdsch_x[i]) { + goto clean; + } + q->pdsch_symbols[i] = malloc(sizeof(cf_t) * q->max_symbols); + if (!q->pdsch_symbols[i]) { + goto clean; + } + } + + ret = LIBLTE_SUCCESS; + } + clean: + if (ret == LIBLTE_ERROR) { pdsch_free(q); } return ret; @@ -300,7 +306,7 @@ void pdsch_free(pdsch_t *q) { if (q->pdsch_d) { free(q->pdsch_d); } - for (i = 0; i < q->nof_ports; i++) { + for (i = 0; i < q->cell.nof_ports; i++) { if (q->ce[i]) { free(q->ce[i]); } @@ -325,15 +331,6 @@ void pdsch_free(pdsch_t *q) { } -struct cb_segm { - int F; - int C; - int K1; - int K2; - int C1; - int C2; -}; - /* Calculate Codeblock Segmentation as in Section 5.1.2 of 36.212 */ void codeblock_segmentation(struct cb_segm *s, int tbs) { int Bp, B, idx1; @@ -368,175 +365,191 @@ void codeblock_segmentation(struct cb_segm *s, int tbs) { /* Decode a transport block according to 36.212 5.3.2 * */ -int pdsch_decode_tb(pdsch_t *q, char *data, int tbs, int nb_e, int rv_idx) { +int pdsch_decode_tb(pdsch_t *q, char *data, uint16_t tbs, uint16_t nb_e, uint8_t rv_idx) { char parity[24]; char *p_parity = parity; - unsigned int par_rx, par_tx; + uint32_t par_rx, par_tx; int i; int cb_len, rp, wp, rlen, F, n_e; struct cb_segm cbs; + + if (q != NULL && + data != NULL && + nb_e < q->max_symbols * q->mod[3].nbits_x_symbol) + { + /* Compute CB segmentation for this TBS */ + codeblock_segmentation(&cbs, tbs); + + rp = 0; + rp = 0; + wp = 0; + for (i = 0; i < cbs.C; i++) { + + /* Get read/write lengths */ + if (i < cbs.C - cbs.C2) { + cb_len = cbs.K1; + } else { + cb_len = cbs.K2; + } + if (cbs.C == 1) { + rlen = cb_len; + } else { + rlen = cb_len - 24; + } + if (i == 0) { + F = cbs.F; + } else { + F = 0; + } - /* Compute CB segmentation for this TBS */ - codeblock_segmentation(&cbs, tbs); - - rp = 0; - rp = 0; - wp = 0; - for (i = 0; i < cbs.C; i++) { - - /* Get read/write lengths */ - if (i < cbs.C - cbs.C2) { - cb_len = cbs.K1; - } else { - cb_len = cbs.K2; - } - if (cbs.C == 1) { - rlen = cb_len; - } else { - rlen = cb_len - 24; - } - if (i == 0) { - F = cbs.F; - } else { - F = 0; - } + if (i < cbs.C - 1) { + n_e = nb_e / cbs.C; + } else { + n_e = nb_e - rp; + } - if (i < cbs.C - 1) { - n_e = nb_e / cbs.C; - } else { - n_e = nb_e - rp; - } + INFO("CB#%d: cb_len: %d, rlen: %d, wp: %d, rp: %d, F: %d, E: %d\n", i, + cb_len, rlen - F, wp, rp, F, n_e); - INFO("CB#%d: cb_len: %d, rlen: %d, wp: %d, rp: %d, F: %d, E: %d\n", i, - cb_len, rlen - F, wp, rp, F, n_e); + /* Rate Unmatching */ + rm_turbo_rx(&q->rm_turbo, &q->pdsch_llr[rp], n_e, q->pdsch_rm_f, + 3 * cb_len + 12, rv_idx); - /* Rate Unmatching */ - rm_turbo_rx(&q->rm_turbo, &q->pdsch_llr[rp], n_e, q->pdsch_rm_f, - 3 * cb_len + 12, rv_idx); + /* Turbo Decoding */ + tdec_run_all(&q->decoder, q->pdsch_rm_f, q->cb_in_b, TDEC_ITERATIONS, + cb_len); - /* Turbo Decoding */ - tdec_run_all(&q->decoder, q->pdsch_rm_f, q->cb_in_b, TDEC_ITERATIONS, - cb_len); + if (cbs.C > 1) { + /* Check Codeblock CRC */ + //crc_attach(&q->crc_cb, q->pdsch_b[wp], cb_len); + } - if (cbs.C > 1) { - /* Check Codeblock CRC */ - //crc_attach(&q->crc_cb, q->pdsch_b[wp], cb_len); - } + /* Copy data to another buffer, removing the Codeblock CRC */ + if (i < cbs.C - 1) { + memcpy(&data[wp], &q->cb_in_b[F], (rlen - F) * sizeof(char)); + } else { + INFO("Last CB, appending parity: %d to %d from %d and 24 from %d\n", + rlen - F - 24, wp, F, rlen - 24); + /* Append Transport Block parity bits to the last CB */ + memcpy(&data[wp], &q->cb_in_b[F], (rlen - F - 24) * sizeof(char)); + memcpy(parity, &q->cb_in_b[rlen - 24], 24 * sizeof(char)); + } - /* Copy data to another buffer, removing the Codeblock CRC */ - if (i < cbs.C - 1) { - memcpy(&data[wp], &q->cb_in_b[F], (rlen - F) * sizeof(char)); - } else { - INFO("Last CB, appending parity: %d to %d from %d and 24 from %d\n", - rlen - F - 24, wp, F, rlen - 24); - /* Append Transport Block parity bits to the last CB */ - memcpy(&data[wp], &q->cb_in_b[F], (rlen - F - 24) * sizeof(char)); - memcpy(parity, &q->cb_in_b[rlen - 24], 24 * sizeof(char)); + /* Set read/write pointers */ + wp += (rlen - F); + rp += n_e; } - /* Set read/write pointers */ - wp += (rlen - F); - rp += n_e; - } + INFO("END CB#%d: wp: %d, rp: %d\n", i, wp, rp); - INFO("END CB#%d: wp: %d, rp: %d\n", i, wp, rp); + // Compute transport block CRC + par_rx = crc_checksum(&q->crc_tb, data, tbs); - // Compute transport block CRC - par_rx = crc_checksum(&q->crc_tb, data, tbs); + // check parity bits + par_tx = bit_unpack(&p_parity, 24); - // check parity bits - par_tx = bit_unpack(&p_parity, 24); + if (!par_rx) { + printf("\n\tCAUTION!! Received all-zero transport block\n\n"); + } - if (!par_rx) { - printf("\n\tCAUTION!! Received all-zero transport block\n\n"); + if (par_rx == par_tx) { + return LIBLTE_SUCCESS; + } else { + return LIBLTE_ERROR; + } + } else { + return LIBLTE_ERROR_INVALID_INPUTS; } - - return (par_rx != par_tx); } /** Decodes the PDSCH from the received symbols */ int pdsch_decode(pdsch_t *q, cf_t *sf_symbols, cf_t *ce[MAX_PORTS], char *data, - int nsubframe, ra_mcs_t mcs, ra_prb_t *prb_alloc) { + uint8_t subframe, ra_mcs_t mcs, ra_prb_t *prb_alloc) { /* Set pointers for layermapping & precoding */ int i, n; cf_t *x[MAX_LAYERS]; int nof_symbols, nof_bits, nof_bits_e; + + if (q != NULL && + sf_symbols != NULL && + data != NULL && + subframe < 10 && + prb_alloc != NULL) + { + + nof_bits = mcs.tbs; + nof_symbols = prb_alloc->re_sf[subframe]; + nof_bits_e = nof_symbols * q->mod[mcs.mod - 1].nbits_x_symbol; - nof_bits = mcs.tbs; - nof_symbols = prb_alloc->re_sf[nsubframe]; - nof_bits_e = nof_symbols * q->mod[mcs.mod - 1].nbits_x_symbol; - - if (nof_bits > nof_bits_e) { - fprintf(stderr, "Invalid code rate %.2f\n", (float) nof_bits / nof_bits_e); - return -1; - } - - if (nof_symbols > q->max_symbols) { - fprintf(stderr, - "Error too many RE per subframe (%d). PDSCH configured for %d RE (%d PRB)\n", - nof_symbols, q->max_symbols, q->nof_prb); - return -1; - } - - INFO("Decoding PDSCH SF: %d, Mod %d, NofBits: %d, NofSymbols: %d, NofBitsE: %d\n", - nsubframe, mcs.mod, nof_bits, nof_symbols, nof_bits_e); + if (nof_bits > nof_bits_e) { + fprintf(stderr, "Invalid code rate %.2f\n", (float) nof_bits / nof_bits_e); + return LIBLTE_ERROR_INVALID_INPUTS; + } - if (nsubframe < 0 || nsubframe > NSUBFRAMES_X_FRAME) { - fprintf(stderr, "Invalid subframe %d\n", nsubframe); - return -1; - } + if (nof_symbols > q->max_symbols) { + fprintf(stderr, + "Error too many RE per subframe (%d). PDSCH configured for %d RE (%d PRB)\n", + nof_symbols, q->max_symbols, q->cell.nof_prb); + return LIBLTE_ERROR_INVALID_INPUTS; + } - /* number of layers equals number of ports */ - for (i = 0; i < q->nof_ports; i++) { - x[i] = q->pdsch_x[i]; - } - memset(&x[q->nof_ports], 0, sizeof(cf_t*) * (MAX_LAYERS - q->nof_ports)); - - /* extract symbols */ - n = pdsch_get(q, sf_symbols, q->pdsch_symbols[0], prb_alloc, nsubframe); - if (n != nof_symbols) { - fprintf(stderr, "Error expecting %d symbols but got %d\n", nof_symbols, n); - return -1; - } + INFO("Decoding PDSCH SF: %d, Mod %d, NofBits: %d, NofSymbols: %d, NofBitsE: %d\n", + subframe, mcs.mod, nof_bits, nof_symbols, nof_bits_e); - /* extract channel estimates */ - for (i = 0; i < q->nof_ports; i++) { - n = pdsch_get(q, ce[i], q->ce[i], prb_alloc, nsubframe); + /* number of layers equals number of ports */ + for (i = 0; i < q->cell.nof_ports; i++) { + x[i] = q->pdsch_x[i]; + } + memset(&x[q->cell.nof_ports], 0, sizeof(cf_t*) * (MAX_LAYERS - q->cell.nof_ports)); + + /* extract symbols */ + n = pdsch_get(q, sf_symbols, q->pdsch_symbols[0], prb_alloc, subframe); if (n != nof_symbols) { fprintf(stderr, "Error expecting %d symbols but got %d\n", nof_symbols, n); - return -1; + return LIBLTE_ERROR; + } + + /* extract channel estimates */ + for (i = 0; i < q->cell.nof_ports; i++) { + n = pdsch_get(q, ce[i], q->ce[i], prb_alloc, subframe); + if (n != nof_symbols) { + fprintf(stderr, "Error expecting %d symbols but got %d\n", nof_symbols, n); + return LIBLTE_ERROR; + } + } + + /* TODO: only diversity is supported */ + if (q->cell.nof_ports == 1) { + /* no need for layer demapping */ + predecoding_single_zf(q->pdsch_symbols[0], q->ce[0], q->pdsch_d, + nof_symbols); + } else { + predecoding_diversity_zf(q->pdsch_symbols[0], q->ce, x, q->cell.nof_ports, + nof_symbols); + layerdemap_diversity(x, q->pdsch_d, q->cell.nof_ports, + nof_symbols / q->cell.nof_ports); } - } - /* TODO: only diversity is supported */ - if (q->nof_ports == 1) { - /* no need for layer demapping */ - predecoding_single_zf(q->pdsch_symbols[0], q->ce[0], q->pdsch_d, - nof_symbols); - } else { - predecoding_diversity_zf(q->pdsch_symbols[0], q->ce, x, q->nof_ports, - nof_symbols); - layerdemap_diversity(x, q->pdsch_d, q->nof_ports, - nof_symbols / q->nof_ports); - } - - /* demodulate symbols */ - demod_soft_sigma_set(&q->demod, 2.0 / q->mod[mcs.mod - 1].nbits_x_symbol); - demod_soft_table_set(&q->demod, &q->mod[mcs.mod - 1]); - demod_soft_demodulate(&q->demod, q->pdsch_d, q->pdsch_llr, nof_symbols); + /* demodulate symbols */ + demod_soft_sigma_set(&q->demod, 2.0 / q->mod[mcs.mod - 1].nbits_x_symbol); + demod_soft_table_set(&q->demod, &q->mod[mcs.mod - 1]); + demod_soft_demodulate(&q->demod, q->pdsch_d, q->pdsch_llr, nof_symbols); - /* descramble */ - scrambling_f_offset(&q->seq_pdsch[nsubframe], q->pdsch_llr, 0, nof_bits_e); + /* descramble */ + scrambling_f_offset(&q->seq_pdsch[subframe], q->pdsch_llr, 0, nof_bits_e); - return pdsch_decode_tb(q, data, nof_bits, nof_bits_e, 0); + return pdsch_decode_tb(q, data, nof_bits, nof_bits_e, 0); + } else { + return LIBLTE_ERROR_INVALID_INPUTS; + } } /* Encode a transport block according to 36.212 5.3.2 * */ -void pdsch_encode_tb(pdsch_t *q, char *data, int tbs, int nb_e, int rv_idx) { +int pdsch_encode_tb(pdsch_t *q, char *data, uint16_t tbs, uint16_t nb_e, uint8_t rv_idx) { char parity[24]; char *p_parity = parity; unsigned int par; @@ -544,152 +557,174 @@ void pdsch_encode_tb(pdsch_t *q, char *data, int tbs, int nb_e, int rv_idx) { int cb_len, rp, wp, rlen, F, n_e; struct cb_segm cbs; - /* Compute CB segmentation */ - codeblock_segmentation(&cbs, tbs); + if (q != NULL && + data != NULL && + nb_e < q->max_symbols * q->mod[3].nbits_x_symbol) + { + + /* Compute CB segmentation */ + codeblock_segmentation(&cbs, tbs); - /* Compute transport block CRC */ - par = crc_checksum(&q->crc_tb, data, tbs); + /* Compute transport block CRC */ + par = crc_checksum(&q->crc_tb, data, tbs); - /* parity bits will be appended later */ - bit_pack(par, &p_parity, 24); + /* parity bits will be appended later */ + bit_pack(par, &p_parity, 24); - if (VERBOSE_ISDEBUG()) { - DEBUG("DATA: ", 0); - vec_fprint_b(stdout, data, tbs); - DEBUG("PARITY: ", 0); - vec_fprint_b(stdout, parity, 24); - } + if (VERBOSE_ISDEBUG()) { + DEBUG("DATA: ", 0); + vec_fprint_b(stdout, data, tbs); + DEBUG("PARITY: ", 0); + vec_fprint_b(stdout, parity, 24); + } - /* Add filler bits to the new data buffer */ - for (i = 0; i < cbs.F; i++) { - q->cb_in_b[i] = LTE_NULL_BIT; - } + /* Add filler bits to the new data buffer */ + for (i = 0; i < cbs.F; i++) { + q->cb_in_b[i] = LTE_NULL_BIT; + } - wp = 0; - rp = 0; - for (i = 0; i < cbs.C; i++) { + wp = 0; + rp = 0; + for (i = 0; i < cbs.C; i++) { - /* Get read lengths */ - if (i < cbs.C - cbs.C2) { - cb_len = cbs.K1; - } else { - cb_len = cbs.K2; - } - if (cbs.C > 1) { - rlen = cb_len - 24; - } else { - rlen = cb_len; - } - if (i == 0) { - F = cbs.F; - } else { - F = 0; - } + /* Get read lengths */ + if (i < cbs.C - cbs.C2) { + cb_len = cbs.K1; + } else { + cb_len = cbs.K2; + } + if (cbs.C > 1) { + rlen = cb_len - 24; + } else { + rlen = cb_len; + } + if (i == 0) { + F = cbs.F; + } else { + F = 0; + } - if (i < cbs.C - 1) { - n_e = nb_e / cbs.C; - } else { - n_e = nb_e - wp; - } + if (i < cbs.C - 1) { + n_e = nb_e / cbs.C; + } else { + n_e = nb_e - wp; + } - INFO("CB#%d: cb_len: %d, rlen: %d, wp: %d, rp: %d, F: %d, E: %d\n", i, - cb_len, rlen - F, wp, rp, F, n_e); + INFO("CB#%d: cb_len: %d, rlen: %d, wp: %d, rp: %d, F: %d, E: %d\n", i, + cb_len, rlen - F, wp, rp, F, n_e); + + /* Copy data to another buffer, making space for the Codeblock CRC */ + if (i < cbs.C - 1) { + memcpy(&q->cb_in_b[F], &data[rp], (rlen - F) * sizeof(char)); + } else { + INFO("Last CB, appending parity: %d from %d and 24 to %d\n", + rlen - F - 24, rp, rlen - 24); + /* Append Transport Block parity bits to the last CB */ + memcpy(&q->cb_in_b[F], &data[rp], (rlen - F - 24) * sizeof(char)); + memcpy(&q->cb_in_b[rlen - 24], parity, 24 * sizeof(char)); + } - /* Copy data to another buffer, making space for the Codeblock CRC */ - if (i < cbs.C - 1) { - memcpy(&q->cb_in_b[F], &data[rp], (rlen - F) * sizeof(char)); - } else { - INFO("Last CB, appending parity: %d from %d and 24 to %d\n", - rlen - F - 24, rp, rlen - 24); - /* Append Transport Block parity bits to the last CB */ - memcpy(&q->cb_in_b[F], &data[rp], (rlen - F - 24) * sizeof(char)); - memcpy(&q->cb_in_b[rlen - 24], parity, 24 * sizeof(char)); - } + if (cbs.C > 1) { + /* Attach Codeblock CRC */ + crc_attach(&q->crc_cb, q->cb_in_b, rlen); + } - if (cbs.C > 1) { - /* Attach Codeblock CRC */ - crc_attach(&q->crc_cb, q->cb_in_b, rlen); - } + if (VERBOSE_ISDEBUG()) { + DEBUG("CB#%d Len=%d: ", i, cb_len); + vec_fprint_b(stdout, q->cb_in_b, cb_len); + } - if (VERBOSE_ISDEBUG()) { - DEBUG("CB#%d Len=%d: ", i, cb_len); - vec_fprint_b(stdout, q->cb_in_b, cb_len); - } + /* Turbo Encoding */ + tcod_encode(&q->encoder, q->cb_in_b, q->cb_out_b, cb_len); - /* Turbo Encoding */ - tcod_encode(&q->encoder, q->cb_in_b, q->cb_out_b, cb_len); + /* Rate matching */ + rm_turbo_tx(&q->rm_turbo, q->cb_out_b, 3 * cb_len + 12, + &q->pdsch_e_bits[wp], n_e, rv_idx); - /* Rate matching */ - rm_turbo_tx(&q->rm_turbo, q->cb_out_b, 3 * cb_len + 12, - &q->pdsch_e_bits[wp], n_e, rv_idx); + /* Set read/write pointers */ + rp += (rlen - F); + wp += n_e; + } - /* Set read/write pointers */ - rp += (rlen - F); - wp += n_e; + INFO("END CB#%d: wp: %d, rp: %d\n", i, wp, rp); + + return LIBLTE_SUCCESS; + } else { + return LIBLTE_ERROR_INVALID_INPUTS; } - - INFO("END CB#%d: wp: %d, rp: %d\n", i, wp, rp); } /** Converts the PDSCH data bits to symbols mapped to the slot ready for transmission */ int pdsch_encode(pdsch_t *q, char *data, cf_t *sf_symbols[MAX_PORTS], - int nsubframe, ra_mcs_t mcs, ra_prb_t *prb_alloc) { + uint8_t subframe, ra_mcs_t mcs, ra_prb_t *prb_alloc) { int i; - int nof_symbols, nof_bits, nof_bits_e; + uint16_t nof_symbols, nof_bits, nof_bits_e; /* Set pointers for layermapping & precoding */ cf_t *x[MAX_LAYERS]; - if (nsubframe < 0 || nsubframe > NSUBFRAMES_X_FRAME) { - fprintf(stderr, "Invalid subframe %d\n", nsubframe); - return -1; - } + if (q != NULL && + data != NULL && + subframe < 10 && + prb_alloc != NULL) + { - nof_bits = mcs.tbs; - nof_symbols = prb_alloc->re_sf[nsubframe]; - nof_bits_e = nof_symbols * q->mod[mcs.mod - 1].nbits_x_symbol; + for (i=0;icell.nof_ports;i++) { + if (sf_symbols[i] == NULL) { + return LIBLTE_ERROR_INVALID_INPUTS; + } + } + + nof_bits = mcs.tbs; + nof_symbols = prb_alloc->re_sf[subframe]; + nof_bits_e = nof_symbols * q->mod[mcs.mod - 1].nbits_x_symbol; - if (nof_bits > nof_bits_e) { - fprintf(stderr, "Invalid code rate %.2f\n", (float) nof_bits / nof_bits_e); - return -1; - } + if (nof_bits > nof_bits_e) { + fprintf(stderr, "Invalid code rate %.2f\n", (float) nof_bits / nof_bits_e); + return LIBLTE_ERROR_INVALID_INPUTS; + } - if (nof_symbols > q->max_symbols) { - fprintf(stderr, - "Error too many RE per subframe (%d). PDSCH configured for %d RE (%d PRB)\n", - nof_symbols, q->max_symbols, q->nof_prb); - return -1; - } + if (nof_symbols > q->max_symbols) { + fprintf(stderr, + "Error too many RE per subframe (%d). PDSCH configured for %d RE (%d PRB)\n", + nof_symbols, q->max_symbols, q->cell.nof_prb); + return LIBLTE_ERROR_INVALID_INPUTS; + } - INFO( - "Encoding PDSCH SF: %d, Mod %d, NofBits: %d, NofSymbols: %d, NofBitsE: %d\n", - nsubframe, mcs.mod, nof_bits, nof_symbols, nof_bits_e); + INFO("Encoding PDSCH SF: %d, Mod %d, NofBits: %d, NofSymbols: %d, NofBitsE: %d\n", + subframe, mcs.mod, nof_bits, nof_symbols, nof_bits_e); - /* number of layers equals number of ports */ - for (i = 0; i < q->nof_ports; i++) { - x[i] = q->pdsch_x[i]; - } - memset(&x[q->nof_ports], 0, sizeof(cf_t*) * (MAX_LAYERS - q->nof_ports)); + /* number of layers equals number of ports */ + for (i = 0; i < q->cell.nof_ports; i++) { + x[i] = q->pdsch_x[i]; + } + memset(&x[q->cell.nof_ports], 0, sizeof(cf_t*) * (MAX_LAYERS - q->cell.nof_ports)); - pdsch_encode_tb(q, data, nof_bits, nof_bits_e, 0); + if (pdsch_encode_tb(q, data, nof_bits, nof_bits_e, 0)) { + fprintf(stderr, "Error encoding TB\n"); + return LIBLTE_ERROR; + } - scrambling_b_offset(&q->seq_pdsch[nsubframe], q->pdsch_e_bits, 0, nof_bits_e); + scrambling_b_offset(&q->seq_pdsch[subframe], q->pdsch_e_bits, 0, nof_bits_e); - mod_modulate(&q->mod[mcs.mod - 1], q->pdsch_e_bits, q->pdsch_d, nof_bits_e); + mod_modulate(&q->mod[mcs.mod - 1], q->pdsch_e_bits, q->pdsch_d, nof_bits_e); - /* TODO: only diversity supported */ - if (q->nof_ports > 1) { - layermap_diversity(q->pdsch_d, x, q->nof_ports, nof_symbols); - precoding_diversity(x, q->pdsch_symbols, q->nof_ports, - nof_symbols / q->nof_ports); - } else { - memcpy(q->pdsch_symbols[0], q->pdsch_d, nof_symbols * sizeof(cf_t)); - } + /* TODO: only diversity supported */ + if (q->cell.nof_ports > 1) { + layermap_diversity(q->pdsch_d, x, q->cell.nof_ports, nof_symbols); + precoding_diversity(x, q->pdsch_symbols, q->cell.nof_ports, + nof_symbols / q->cell.nof_ports); + } else { + memcpy(q->pdsch_symbols[0], q->pdsch_d, nof_symbols * sizeof(cf_t)); + } - /* mapping to resource elements */ - for (i = 0; i < q->nof_ports; i++) { - pdsch_put(q, q->pdsch_symbols[i], sf_symbols[i], prb_alloc, nsubframe); + /* mapping to resource elements */ + for (i = 0; i < q->cell.nof_ports; i++) { + pdsch_put(q, q->pdsch_symbols[i], sf_symbols[i], prb_alloc, subframe); + } + return LIBLTE_SUCCESS; + } else { + return LIBLTE_ERROR_INVALID_INPUTS; } - return 0; } diff --git a/lte/phy/lib/phch/src/phich.c b/lte/phy/lib/phch/src/phich.c index 0165e59eb..a38c97bf7 100644 --- a/lte/phy/lib/phch/src/phich.c +++ b/lte/phy/lib/phch/src/phich.c @@ -49,11 +49,8 @@ const cf_t w_normal[PHICH_NORM_NSEQUENCES][4] = { { 1, 1, 1, 1 }, const cf_t w_ext[PHICH_EXT_NSEQUENCES][2] = { { 1, 1 }, { 1, -1 }, { I, I }, { I, -I } }; -bool phich_exists(int nframe, int nslot) { - return true; -} -int phich_ngroups(phich_t *q) { +uint8_t phich_ngroups(phich_t *q) { return regs_phich_ngroups(q->regs); } @@ -65,30 +62,36 @@ void phich_reset(phich_t *q, cf_t *slot_symbols[MAX_PORTS]) { } /** Initializes the phich channel receiver */ -int phich_init(phich_t *q, regs_t *regs, int cell_id, int nof_prb, - int nof_tx_ports, lte_cp_t cp) { - int ret = -1; - bzero(q, sizeof(phich_t)); - q->cp = cp; - q->regs = regs; - q->nof_prb = nof_prb; - q->nof_tx_ports = nof_tx_ports; - - if (modem_table_std(&q->mod, LTE_BPSK, false)) { - goto clean; - } +int phich_init(phich_t *q, regs_t *regs, lte_cell_t cell) { + int ret = LIBLTE_ERROR_INVALID_INPUTS; + + if (q != NULL && + regs != NULL && + lte_cell_isvalid(&cell)) + { + + bzero(q, sizeof(phich_t)); + ret = LIBLTE_ERROR; + + q->cell = cell; + q->regs = regs; + + if (modem_table_std(&q->mod, LTE_BPSK, false)) { + goto clean; + } - demod_hard_init(&q->demod); - demod_hard_table_set(&q->demod, LTE_BPSK); + demod_hard_init(&q->demod); + demod_hard_table_set(&q->demod, LTE_BPSK); - for (int nsf = 0; nsf < NSUBFRAMES_X_FRAME; nsf++) { - if (sequence_phich(&q->seq_phich[nsf], 2 * nsf, cell_id)) { - goto clean; + for (int nsf = 0; nsf < NSUBFRAMES_X_FRAME; nsf++) { + if (sequence_phich(&q->seq_phich[nsf], 2 * nsf, q->cell.id)) { + goto clean; + } } + ret = LIBLTE_SUCCESS; } - - ret = 0; - clean: if (ret == -1) { + clean: + if (ret == LIBLTE_ERROR) { phich_free(q); } return ret; @@ -104,7 +107,7 @@ void phich_free(phich_t *q) { /* Decodes ACK * */ -char phich_ack_decode(char bits[PHICH_NBITS], int *distance) { +char phich_ack_decode(char bits[PHICH_NBITS], uint8_t *distance) { int i, n; n = 0; @@ -137,36 +140,40 @@ void phich_ack_encode(char ack, char bits[PHICH_NBITS]) { * Returns 1 if successfully decoded the CFI, 0 if not and -1 on error */ int phich_decode(phich_t *q, cf_t *slot_symbols, cf_t *ce[MAX_PORTS], - int ngroup, int nseq, int nsubframe, char *ack, int *distance) { + uint8_t ngroup, uint8_t nseq, uint8_t subframe, char *ack, uint8_t *distance) { /* Set pointers for layermapping & precoding */ int i, j; cf_t *x[MAX_LAYERS]; cf_t *ce_precoding[MAX_PORTS]; + + if (q == NULL || slot_symbols == NULL) { + return LIBLTE_ERROR_INVALID_INPUTS; + } - DEBUG("Decoding PHICH Ngroup: %d, Nseq: %d\n", ngroup, nseq); - - if (nsubframe < 0 || nsubframe > NSUBFRAMES_X_FRAME) { - fprintf(stderr, "Invalid nslot %d\n", nsubframe); - return -1; + if (subframe >= NSUBFRAMES_X_FRAME) { + fprintf(stderr, "Invalid nslot %d\n", subframe); + return LIBLTE_ERROR_INVALID_INPUTS; } - if (CP_ISEXT(q->cp)) { - if (nseq < 0 || nseq > PHICH_EXT_NSEQUENCES) { + if (CP_ISEXT(q->cell.cp)) { + if (nseq >= PHICH_EXT_NSEQUENCES) { fprintf(stderr, "Invalid nseq %d\n", nseq); - return -1; + return LIBLTE_ERROR_INVALID_INPUTS; } } else { - if (nseq < 0 || nseq > PHICH_NORM_NSEQUENCES) { + if (nseq >= PHICH_NORM_NSEQUENCES) { fprintf(stderr, "Invalid nseq %d\n", nseq); - return -1; + return LIBLTE_ERROR_INVALID_INPUTS; } } if (ngroup >= regs_phich_ngroups(q->regs)) { fprintf(stderr, "Invalid ngroup %d\n", ngroup); - return -1; + return LIBLTE_ERROR_INVALID_INPUTS; } + DEBUG("Decoding PHICH Ngroup: %d, Nseq: %d\n", ngroup, nseq); + /* number of layers equals number of ports */ for (i = 0; i < MAX_PORTS; i++) { x[i] = q->phich_x[i]; @@ -179,34 +186,34 @@ int phich_decode(phich_t *q, cf_t *slot_symbols, cf_t *ce[MAX_PORTS], if (PHICH_MAX_NSYMB != regs_phich_get(q->regs, slot_symbols, q->phich_symbols[0], ngroup)) { fprintf(stderr, "There was an error getting the phich symbols\n"); - return -1; + return LIBLTE_ERROR; } /* extract channel estimates */ - for (i = 0; i < q->nof_tx_ports; i++) { + for (i = 0; i < q->cell.nof_ports; i++) { if (PHICH_MAX_NSYMB != regs_phich_get(q->regs, ce[i], q->ce[i], ngroup)) { fprintf(stderr, "There was an error getting the phich symbols\n"); - return -1; + return LIBLTE_ERROR; } } /* in control channels, only diversity is supported */ - if (q->nof_tx_ports == 1) { + if (q->cell.nof_ports == 1) { /* no need for layer demapping */ predecoding_single_zf(q->phich_symbols[0], q->ce[0], q->phich_d0, PHICH_MAX_NSYMB); } else { predecoding_diversity_zf(q->phich_symbols[0], ce_precoding, x, - q->nof_tx_ports, PHICH_MAX_NSYMB); - layerdemap_diversity(x, q->phich_d0, q->nof_tx_ports, - PHICH_MAX_NSYMB / q->nof_tx_ports); + q->cell.nof_ports, PHICH_MAX_NSYMB); + layerdemap_diversity(x, q->phich_d0, q->cell.nof_ports, + PHICH_MAX_NSYMB / q->cell.nof_ports); } DEBUG("Recv!!: \n", 0); DEBUG("d0: ", 0); if (VERBOSE_ISDEBUG()) vec_fprint_c(stdout, q->phich_d0, PHICH_MAX_NSYMB); - if (CP_ISEXT(q->cp)) { + if (CP_ISEXT(q->cell.cp)) { if (ngroup % 2) { for (i = 0; i < PHICH_EXT_MSYMB / 2; i++) { q->phich_d[2 * i + 0] = q->phich_d0[4 * i + 2]; @@ -226,10 +233,10 @@ int phich_decode(phich_t *q, cf_t *slot_symbols, cf_t *ce[MAX_PORTS], if (VERBOSE_ISDEBUG()) vec_fprint_c(stdout, q->phich_d, PHICH_EXT_MSYMB); - scrambling_c(&q->seq_phich[nsubframe], q->phich_d); + scrambling_c(&q->seq_phich[subframe], q->phich_d); /* De-spreading */ - if (CP_ISEXT(q->cp)) { + if (CP_ISEXT(q->cell.cp)) { for (i = 0; i < PHICH_NBITS; i++) { q->phich_z[i] = 0; for (j = 0; j < PHICH_EXT_NSF; j++) { @@ -257,43 +264,48 @@ int phich_decode(phich_t *q, cf_t *slot_symbols, cf_t *ce[MAX_PORTS], *ack = phich_ack_decode(q->data, distance); } - return 0; + return LIBLTE_SUCCESS; } /** Encodes ACK/NACK bits, modulates and inserts into resource. * The parameter ack is an array of phich_ngroups() pointers to buffers of nof_sequences chars */ -int phich_encode(phich_t *q, char ack, int ngroup, int nseq, int nsubframe, +int phich_encode(phich_t *q, char ack, uint8_t ngroup, uint8_t nseq, uint8_t subframe, cf_t *slot_symbols[MAX_PORTS]) { int i; - if (nsubframe < 0 || nsubframe > NSUBFRAMES_X_FRAME) { - fprintf(stderr, "Invalid nslot %d\n", nsubframe); - return -1; + if (q == NULL || slot_symbols == NULL) { + return LIBLTE_ERROR_INVALID_INPUTS; } - if (CP_ISEXT(q->cp)) { - if (nseq < 0 || nseq > PHICH_EXT_NSEQUENCES) { + if (subframe >= NSUBFRAMES_X_FRAME) { + fprintf(stderr, "Invalid nslot %d\n", subframe); + return LIBLTE_ERROR_INVALID_INPUTS; + } + + if (CP_ISEXT(q->cell.cp)) { + if (nseq >= PHICH_EXT_NSEQUENCES) { fprintf(stderr, "Invalid nseq %d\n", nseq); - return -1; + return LIBLTE_ERROR_INVALID_INPUTS; } } else { - if (nseq < 0 || nseq > PHICH_NORM_NSEQUENCES) { + if (nseq >= PHICH_NORM_NSEQUENCES) { fprintf(stderr, "Invalid nseq %d\n", nseq); - return -1; + return LIBLTE_ERROR_INVALID_INPUTS; } } if (ngroup >= regs_phich_ngroups(q->regs)) { fprintf(stderr, "Invalid ngroup %d\n", ngroup); - return -1; + return LIBLTE_ERROR_INVALID_INPUTS; } + /* Set pointers for layermapping & precoding */ cf_t *x[MAX_LAYERS]; cf_t *symbols_precoding[MAX_PORTS]; /* number of layers equals number of ports */ - for (i = 0; i < q->nof_tx_ports; i++) { + for (i = 0; i < q->cell.nof_ports; i++) { x[i] = q->phich_x[i]; } for (i = 0; i < MAX_PORTS; i++) { @@ -310,7 +322,7 @@ int phich_encode(phich_t *q, char ack, int ngroup, int nseq, int nsubframe, vec_fprint_c(stdout, q->phich_z, PHICH_NBITS); /* Spread with w */ - if (CP_ISEXT(q->cp)) { + if (CP_ISEXT(q->cell.cp)) { for (i = 0; i < PHICH_EXT_MSYMB; i++) { q->phich_d[i] = w_ext[nseq][i % PHICH_EXT_NSF] * q->phich_z[i / PHICH_EXT_NSF]; @@ -326,10 +338,10 @@ int phich_encode(phich_t *q, char ack, int ngroup, int nseq, int nsubframe, if (VERBOSE_ISDEBUG()) vec_fprint_c(stdout, q->phich_d, PHICH_EXT_MSYMB); - scrambling_c(&q->seq_phich[nsubframe], q->phich_d); + scrambling_c(&q->seq_phich[subframe], q->phich_d); /* align to REG */ - if (CP_ISEXT(q->cp)) { + if (CP_ISEXT(q->cell.cp)) { if (ngroup % 2) { for (i = 0; i < PHICH_EXT_MSYMB / 2; i++) { q->phich_d0[4 * i + 0] = 0; @@ -354,24 +366,24 @@ int phich_encode(phich_t *q, char ack, int ngroup, int nseq, int nsubframe, vec_fprint_c(stdout, q->phich_d0, PHICH_MAX_NSYMB); /* layer mapping & precoding */ - if (q->nof_tx_ports > 1) { - layermap_diversity(q->phich_d0, x, q->nof_tx_ports, PHICH_MAX_NSYMB); - precoding_diversity(x, symbols_precoding, q->nof_tx_ports, - PHICH_MAX_NSYMB / q->nof_tx_ports); + if (q->cell.nof_ports > 1) { + layermap_diversity(q->phich_d0, x, q->cell.nof_ports, PHICH_MAX_NSYMB); + precoding_diversity(x, symbols_precoding, q->cell.nof_ports, + PHICH_MAX_NSYMB / q->cell.nof_ports); /**FIXME: According to 6.9.2, Precoding for 4 tx ports is different! */ } else { memcpy(q->phich_symbols[0], q->phich_d0, PHICH_MAX_NSYMB * sizeof(cf_t)); } /* mapping to resource elements */ - for (i = 0; i < q->nof_tx_ports; i++) { + for (i = 0; i < q->cell.nof_ports; i++) { if (regs_phich_add(q->regs, q->phich_symbols[i], ngroup, slot_symbols[i]) < 0) { fprintf(stderr, "Error putting PCHICH resource elements\n"); - return -1; + return LIBLTE_ERROR; } } - return 0; + return LIBLTE_SUCCESS; } diff --git a/lte/phy/lib/phch/src/regs.c b/lte/phy/lib/phch/src/regs.c index ade13eaa5..50fe5e42a 100644 --- a/lte/phy/lib/phch/src/regs.c +++ b/lte/phy/lib/phch/src/regs.c @@ -34,7 +34,23 @@ #include "liblte/phy/phch/regs.h" #include "liblte/phy/utils/debug.h" -regs_reg_t *regs_find_reg(regs_t *h, int k, int l); +regs_reg_t *regs_find_reg(regs_t *h, uint16_t k, uint8_t l); +int regs_put_reg(regs_reg_t *reg, + cf_t *reg_data, + cf_t *slot_symbols, + uint8_t nof_prb); + +int regs_add_reg(regs_reg_t *reg, + cf_t *reg_data, + cf_t *slot_symbols, + uint8_t nof_prb); + +int regs_get_reg(regs_reg_t *reg, + cf_t *slot_symbols, + cf_t *reg_data, + uint8_t nof_prb); + +int regs_reset_reg(regs_reg_t *reg, cf_t *slot_symbols, uint8_t nof_prb); /*************************************************************** @@ -62,14 +78,14 @@ const unsigned char PDCCH_PERM[PDCCH_NCOLS] = */ int regs_pdcch_init(regs_t *h) { int i, m, cfi, nof_ctrl_symbols; - int ret = -1; + int ret = LIBLTE_ERROR; int nrows, ndummy, j, k, kp; regs_reg_t **tmp = NULL; bzero(&h->pdcch, sizeof(regs_ch_t)); for (cfi=0;cfi<3;cfi++) { - if (h->nof_prb < 10) { + if (h->cell.nof_prb < 10) { nof_ctrl_symbols = cfi+2; } else { nof_ctrl_symbols = cfi+1; @@ -110,7 +126,7 @@ int regs_pdcch_init(regs_t *h) { for (i = 0; i < nrows; i++) { if (i*PDCCH_NCOLS + PDCCH_PERM[j] >= ndummy) { m = i*PDCCH_NCOLS + PDCCH_PERM[j]-ndummy; - kp = (k-h->cell_id)%h->pdcch[cfi].nof_regs; + kp = (k-h->cell.id)%h->pdcch[cfi].nof_regs; if (kp < 0) { kp += h->pdcch[cfi].nof_regs; } @@ -124,23 +140,23 @@ int regs_pdcch_init(regs_t *h) { tmp = NULL; } - ret = 0; + ret = LIBLTE_SUCCESS; clean_and_exit: if (tmp) { free(tmp); } - if (ret == -1) { + if (ret == LIBLTE_ERROR) { regs_pdcch_free(h); } return ret; } -int regs_pdcch_nregs(regs_t *h, int cfi) { +int regs_pdcch_nregs(regs_t *h, uint8_t cfi) { if (cfi < 1 || cfi > 3) { fprintf(stderr, "Invalid CFI=%d\n", cfi); - return -1; + return LIBLTE_ERROR; } else { - return h->pdcch[cfi-1].nof_regs; + return (int) h->pdcch[cfi-1].nof_regs; } } @@ -148,25 +164,25 @@ int regs_pdcch_nregs(regs_t *h, int cfi) { * second part of 6.8.5 in 36.211 */ int regs_pdcch_put(regs_t *h, cf_t *pdcch_symbols, cf_t *slot_symbols) { - if (h->cfi == -1) { + if (!h->cfi_initiated) { fprintf(stderr, "Must call regs_set_cfi() first\n"); - return -1; + return LIBLTE_ERROR; } int i; for (i=0;ipdcch[h->cfi].nof_regs;i++) { - regs_put_reg(h->pdcch[h->cfi].regs[i], &pdcch_symbols[i*4], slot_symbols, h->nof_prb); + regs_put_reg(h->pdcch[h->cfi].regs[i], &pdcch_symbols[i*4], slot_symbols, h->cell.nof_prb); } return h->pdcch[h->cfi].nof_regs*4; } int regs_pdcch_get(regs_t *h, cf_t *slot_symbols, cf_t *pdcch_symbols) { - if (h->cfi == -1) { + if (!h->cfi_initiated) { fprintf(stderr, "Must call regs_set_cfi() first\n"); - return -1; + return LIBLTE_ERROR; } int i; for (i=0;ipdcch[h->cfi].nof_regs;i++) { - regs_get_reg(h->pdcch[h->cfi].regs[i], slot_symbols, &pdcch_symbols[i*4], h->nof_prb); + regs_get_reg(h->pdcch[h->cfi].regs[i], slot_symbols, &pdcch_symbols[i*4], h->cell.nof_prb); } return h->pdcch[h->cfi].nof_regs*4; } @@ -187,7 +203,7 @@ int regs_phich_init(regs_t *h) { float ng; int i,ni,li,n[3],nreg,mi; regs_reg_t **regs_phich[3]; - int ret = -1; + int ret = LIBLTE_ERROR; switch(h->phich_res) { case R_1_6: @@ -206,7 +222,7 @@ int regs_phich_init(regs_t *h) { ng = 0; break; } - h->ngroups_phich = (int) ceilf(ng * ((float) h->nof_prb/8)); + h->ngroups_phich = (int) ceilf(ng * ((float) h->cell.nof_prb/8)); h->phich = malloc(sizeof(regs_ch_t) * h->ngroups_phich); if (!h->phich) { perror("malloc"); @@ -255,7 +271,7 @@ int regs_phich_init(regs_t *h) { for (mi=0;mingroups_phich;mi++) { // here ngroups is the number of mapping units for (i=0;i<3;i++) { li=h->phich_len==PHICH_EXT?i:0; // Step 7 - ni=((h->cell_id*n[li]/n[0])+mi+i*n[li]/3) % n[li]; // Step 8 + ni=((h->cell.id*n[li]/n[0])+mi+i*n[li]/3) % n[li]; // Step 8 h->phich[mi].regs[i] = regs_phich[li][ni]; h->phich[mi].regs[i]->assigned = true; INFO("Assigned PHICH REG#%d (%d,%d)\n",nreg,h->phich[mi].regs[i]->k0,li); @@ -265,13 +281,13 @@ int regs_phich_init(regs_t *h) { // now the number of mapping units = number of groups for normal cp. For extended cp // ngroups = 2 * number mapping units - if (CP_ISEXT(h->cp)) { + if (CP_ISEXT(h->cell.cp)) { h->ngroups_phich *= 2; } - ret = 0; + ret = LIBLTE_SUCCESS; clean_and_exit: - if (ret == -1) { + if (ret == LIBLTE_ERROR) { if (h->phich) { for (i=0;ingroups_phich;i++) { if (h->phich[i].regs) { @@ -292,7 +308,7 @@ clean_and_exit: void regs_phich_free(regs_t *h) { int i; if (h->phich) { - if (CP_ISEXT(h->cp)) { + if (CP_ISEXT(h->cell.cp)) { h->ngroups_phich /= 2; } for (i=0;ingroups_phich;i++) { @@ -304,8 +320,9 @@ void regs_phich_free(regs_t *h) { } } -int regs_phich_nregs(regs_t *h) { - int i, n; +u_int16_t regs_phich_nregs(regs_t *h) { + int i; + u_int16_t n; n=0; for (i=0;ingroups_phich;i++) { n += h->phich[i].nof_regs; @@ -314,7 +331,7 @@ int regs_phich_nregs(regs_t *h) { } -int regs_phich_ngroups(regs_t *h) { +u_int8_t regs_phich_ngroups(regs_t *h) { return h->ngroups_phich; } @@ -325,18 +342,18 @@ int regs_phich_ngroups(regs_t *h) { * * Returns the number of written symbols, or -1 on error */ -int regs_phich_add(regs_t *h, cf_t phich_symbols[REGS_PHICH_NSYM], int ngroup, cf_t *slot_symbols) { +int regs_phich_add(regs_t *h, cf_t phich_symbols[REGS_PHICH_NSYM], u_int8_t ngroup, cf_t *slot_symbols) { int i; - if (ngroup < 0 || ngroup > h->ngroups_phich) { + if (ngroup >= h->ngroups_phich) { fprintf(stderr, "Error invalid ngroup %d\n", ngroup); - return -1; + return LIBLTE_ERROR_INVALID_INPUTS; } - if (CP_ISEXT(h->cp)) { + if (CP_ISEXT(h->cell.cp)) { ngroup /= 2; } regs_ch_t *rch = &h->phich[ngroup]; for (i = 0; i < rch->nof_regs && i*REGS_RE_X_REG < REGS_PHICH_NSYM; i++) { - regs_add_reg(rch->regs[i], &phich_symbols[i*REGS_RE_X_REG], slot_symbols, h->nof_prb); + regs_add_reg(rch->regs[i], &phich_symbols[i*REGS_RE_X_REG], slot_symbols, h->cell.nof_prb); } return i*REGS_RE_X_REG; } @@ -348,19 +365,19 @@ int regs_phich_add(regs_t *h, cf_t phich_symbols[REGS_PHICH_NSYM], int ngroup, c */ int regs_phich_reset(regs_t *h, cf_t *slot_symbols) { int i; - int ngroup, ng; - for (ngroup = 0;ngroup < h->ngroups_phich;CP_ISEXT(h->cp)?ngroup+=2:ngroup++) { - if (CP_ISEXT(h->cp)) { + u_int8_t ngroup, ng; + for (ngroup = 0;ngroup < h->ngroups_phich;CP_ISEXT(h->cell.cp)?ngroup+=2:ngroup++) { + if (CP_ISEXT(h->cell.cp)) { ng = ngroup/2; } else { ng = ngroup; } regs_ch_t *rch = &h->phich[ng]; for (i = 0; i < rch->nof_regs && i*REGS_RE_X_REG < REGS_PHICH_NSYM; i++) { - regs_reset_reg(rch->regs[i], slot_symbols, h->nof_prb); + regs_reset_reg(rch->regs[i], slot_symbols, h->cell.nof_prb); } } - return 0; + return LIBLTE_SUCCESS; } /** @@ -368,18 +385,18 @@ int regs_phich_reset(regs_t *h, cf_t *slot_symbols) { * * Returns the number of written symbols, or -1 on error */ -int regs_phich_get(regs_t *h, cf_t *slot_symbols, cf_t phich_symbols[REGS_PHICH_NSYM], int ngroup) { +int regs_phich_get(regs_t *h, cf_t *slot_symbols, cf_t phich_symbols[REGS_PHICH_NSYM], u_int8_t ngroup) { int i; - if (ngroup < 0 || ngroup > h->ngroups_phich) { + if (ngroup >= h->ngroups_phich) { fprintf(stderr, "Error invalid ngroup %d\n", ngroup); - return -1; + return LIBLTE_ERROR_INVALID_INPUTS; } - if (CP_ISEXT(h->cp)) { + if (CP_ISEXT(h->cell.cp)) { ngroup /= 2; } regs_ch_t *rch = &h->phich[ngroup]; for (i = 0; i < rch->nof_regs && i*REGS_RE_X_REG < REGS_PHICH_NSYM; i++) { - regs_get_reg(rch->regs[i], slot_symbols, &phich_symbols[i*REGS_RE_X_REG], h->nof_prb); + regs_get_reg(rch->regs[i], slot_symbols, &phich_symbols[i*REGS_RE_X_REG], h->cell.nof_prb); } return i*REGS_RE_X_REG; } @@ -404,39 +421,40 @@ int regs_phich_get(regs_t *h, cf_t *slot_symbols, cf_t phich_symbols[REGS_PHICH_ * 36.211 10.3 section 6.7.4 */ int regs_pcfich_init(regs_t *h) { - int i, k_hat, k; + int i; + uint16_t k_hat, k; regs_ch_t *ch = &h->pcfich; ch->regs = malloc(sizeof(regs_reg_t*) * REGS_PCFICH_NREGS); if (!ch->regs) { perror("malloc"); - return -1; + return LIBLTE_ERROR; } ch->nof_regs = REGS_PCFICH_NREGS; - INFO("PCFICH allocating %d regs. CellID: %d, PRB: %d\n", ch->nof_regs, h->cell_id, h->nof_prb); + INFO("PCFICH allocating %d regs. CellID: %d, PRB: %d\n", ch->nof_regs, h->cell.id, h->cell.nof_prb); - k_hat = (RE_X_RB / 2) * (h->cell_id % (2 * h->nof_prb)); + k_hat = (RE_X_RB / 2) * (h->cell.id % (2 * h->cell.nof_prb)); for (i = 0; i < REGS_PCFICH_NREGS; i++) { - k = (k_hat + (i * h->nof_prb / 2) * (RE_X_RB / 2)) - % (h->nof_prb * RE_X_RB); + k = (k_hat + (i * h->cell.nof_prb / 2) * (RE_X_RB / 2)) + % (h->cell.nof_prb * RE_X_RB); ch->regs[i] = regs_find_reg(h, k, 0); if (!ch->regs[i]) { fprintf(stderr, "Error allocating PCFICH: REG (%d,0) not found\n", k); - return -1; + return LIBLTE_ERROR; } else if (ch->regs[i]->assigned) { fprintf(stderr, "Error allocating PCFICH: REG (%d,0) already allocated\n", k); - return -1; + return LIBLTE_ERROR; } else { ch->regs[i]->assigned = true; INFO("Assigned PCFICH REG#%d (%d,0)\n", i, k); } } - return 0; + return LIBLTE_SUCCESS; } void regs_pcfich_free(regs_t *h) { @@ -445,7 +463,7 @@ void regs_pcfich_free(regs_t *h) { } } -int regs_pcfich_nregs(regs_t *h) { +uint16_t regs_pcfich_nregs(regs_t *h) { return h->pcfich.nof_regs; } @@ -459,7 +477,7 @@ int regs_pcfich_put(regs_t *h, cf_t pcfich_symbols[REGS_PCFICH_NSYM], cf_t *slot int i; for (i = 0; i < rch->nof_regs && i*REGS_RE_X_REG < REGS_PCFICH_NSYM; i++) { - regs_put_reg(rch->regs[i], &pcfich_symbols[i*REGS_RE_X_REG], slot_symbols, h->nof_prb); + regs_put_reg(rch->regs[i], &pcfich_symbols[i*REGS_RE_X_REG], slot_symbols, h->cell.nof_prb); } return i*REGS_RE_X_REG; } @@ -473,7 +491,7 @@ int regs_pcfich_get(regs_t *h, cf_t *slot_symbols, cf_t ch_data[REGS_PCFICH_NSYM regs_ch_t *rch = &h->pcfich; int i; for (i = 0; i < rch->nof_regs && i*REGS_RE_X_REG < REGS_PCFICH_NSYM; i++) { - regs_get_reg(rch->regs[i], slot_symbols, &ch_data[i*REGS_RE_X_REG], h->nof_prb); + regs_get_reg(rch->regs[i], slot_symbols, &ch_data[i*REGS_RE_X_REG], h->cell.nof_prb); } return i*REGS_RE_X_REG; } @@ -497,7 +515,7 @@ int regs_pcfich_get(regs_t *h, cf_t *slot_symbols, cf_t ch_data[REGS_PCFICH_NSYM * ***************************************************************/ -regs_reg_t *regs_find_reg(regs_t *h, int k, int l) { +regs_reg_t *regs_find_reg(regs_t *h, uint16_t k, uint8_t l) { int i; for (i=0;inof_regs;i++) { if (h->regs[i].l == l && h->regs[i].k0 == k) { @@ -511,7 +529,7 @@ regs_reg_t *regs_find_reg(regs_t *h, int k, int l) { * Returns the number of REGs in a PRB * 36.211 Section 6.2.4 */ -int regs_num_x_symbol(int symbol, int nof_port, lte_cp_t cp) { +int regs_num_x_symbol(uint8_t symbol, uint8_t nof_port, lte_cp_t cp) { switch (symbol) { case 0: @@ -524,7 +542,7 @@ int regs_num_x_symbol(int symbol, int nof_port, lte_cp_t cp) { case 4: return 2; default: - return -1; + return LIBLTE_ERROR; } break; case 2: @@ -536,7 +554,7 @@ int regs_num_x_symbol(int symbol, int nof_port, lte_cp_t cp) { return 2; } default: - return -1; + return LIBLTE_ERROR; } } @@ -544,7 +562,7 @@ int regs_num_x_symbol(int symbol, int nof_port, lte_cp_t cp) { * Initializes the indices of a REG * 36.211 Section 6.2.4 */ -int regs_reg_init(regs_reg_t *reg, int symbol, int nreg, int k0, int maxreg, int vo) { +int regs_reg_init(regs_reg_t *reg, uint8_t symbol, uint16_t nreg, uint16_t k0, uint8_t maxreg, uint8_t vo) { int i, j, z; reg->l = symbol; @@ -570,7 +588,7 @@ int regs_reg_init(regs_reg_t *reg, int symbol, int nreg, int k0, int maxreg, int } if (j != 4) { fprintf(stderr, "Something went wrong: expected 2 references\n"); - return -1; + return LIBLTE_ERROR; } break; @@ -583,9 +601,9 @@ int regs_reg_init(regs_reg_t *reg, int symbol, int nreg, int k0, int maxreg, int break; default: fprintf(stderr, "Invalid number of REGs per PRB: %d\n", maxreg); - return -1; + return LIBLTE_ERROR; } - return 0; + return LIBLTE_SUCCESS; } void regs_free(regs_t *h) { @@ -601,19 +619,20 @@ void regs_free(regs_t *h) { /** Sets the CFI value for this subframe (CFI must be in the range 1..3). */ -int regs_set_cfi(regs_t *h, int cfi) { +int regs_set_cfi(regs_t *h, uint8_t cfi) { if (cfi > 0 && cfi <= 3) { if (h->phich_len == PHICH_EXT && - ((h->nof_prb < 10 && cfi < 2) || (h->nof_prb >= 10 && cfi < 3))) { + ((h->cell.nof_prb < 10 && cfi < 2) || (h->cell.nof_prb >= 10 && cfi < 3))) { fprintf(stderr, "PHICH length is extended. The number of control symbols should be at least 3.\n"); - return -1; + return LIBLTE_ERROR_INVALID_INPUTS; } else { + h->cfi_initiated = true; h->cfi = cfi - 1; - return 0; + return LIBLTE_SUCCESS; } } else { fprintf(stderr, "Invalid CFI %d\n", cfi); - return -1; + return LIBLTE_ERROR_INVALID_INPUTS; } } @@ -622,84 +641,87 @@ int regs_set_cfi(regs_t *h, int cfi) { * Sets all REG indices and initializes PCFICH, PHICH and PDCCH REGs * Returns 0 if OK, -1 on error */ -int regs_init(regs_t *h, int cell_id, int nof_prb, int nof_ports, - phich_resources_t phich_res, phich_length_t phich_len, lte_cp_t cp) { - int ret = -1; - int i, j[4], jmax, n[4], prb, k; - int vo = cell_id % 3; - int max_ctrl_symbols = nof_prb<10?4:3; - - bzero(h, sizeof(regs_t)); - - h->cell_id = cell_id; - h->nof_prb = nof_prb; - h->max_ctrl_symbols = max_ctrl_symbols; - h->cfi = -1; // not yet initialized - h->phich_res = phich_res; - h->phich_len = phich_len; - h->cp = cp; - h->nof_ports = nof_ports; - - h->nof_regs = 0; - for (i = 0; i < max_ctrl_symbols; i++) { - n[i] = regs_num_x_symbol(i, nof_ports, cp); - if (n[i] == -1) { - return -1; - } - h->nof_regs += nof_prb * n[i]; - } - INFO("Indexing %d REGs. CellId: %d, %d PRB, CP: %s\n", h->nof_regs, h->cell_id, h->nof_prb, - CP_ISNORM(cp)?"Normal":"Extended"); - h->regs = malloc(sizeof(regs_reg_t) * h->nof_regs); - if (!h->regs) { - perror("malloc"); - goto clean_and_exit; - } +int regs_init(regs_t *h, phich_resources_t phich_res, phich_length_t phich_len, lte_cell_t cell) { + int ret = LIBLTE_ERROR_INVALID_INPUTS; + int i, k; + uint16_t j[4], jmax, prb; + uint8_t n[4], vo; + int max_ctrl_symbols; + + if (h != NULL && + lte_cell_isvalid(&cell)) + { + bzero(h, sizeof(regs_t)); + ret = LIBLTE_ERROR; + + max_ctrl_symbols = cell.nof_prb<10?4:3; + vo = cell.id % 3; + h->cell = cell; + h->max_ctrl_symbols = max_ctrl_symbols; + h->cfi_initiated = false; + h->phich_res = phich_res; + h->phich_len = phich_len; + + h->nof_regs = 0; + for (i = 0; i < max_ctrl_symbols; i++) { + n[i] = regs_num_x_symbol(i, h->cell.nof_ports, h->cell.cp); + if (n[i] == -1) { + return -1; + } + h->nof_regs += h->cell.nof_prb * n[i]; + } + INFO("Indexing %d REGs. CellId: %d, %d PRB, CP: %s\n", h->nof_regs, h->cell.id, h->cell.nof_prb, + CP_ISNORM(h->cell.cp)?"Normal":"Extended"); + h->regs = malloc(sizeof(regs_reg_t) * h->nof_regs); + if (!h->regs) { + perror("malloc"); + goto clean_and_exit; + } - /* Sort REGs according to PDCCH mapping, beggining from the lowest l index then k */ - bzero(j, sizeof(int) * 4); - k = i = prb = jmax = 0; - while (k < h->nof_regs) { - if (n[i] == 3 || (n[i] == 2 && jmax != 1)) { - if (regs_reg_init(&h->regs[k], i, j[i], prb * RE_X_RB, n[i], vo)) { - fprintf(stderr, "Error initializing REGs\n"); - goto clean_and_exit; + /* Sort REGs according to PDCCH mapping, beggining from the lowest l index then k */ + bzero(j, sizeof(int) * 4); + k = i = prb = jmax = 0; + while (k < h->nof_regs) { + if (n[i] == 3 || (n[i] == 2 && jmax != 1)) { + if (regs_reg_init(&h->regs[k], i, j[i], prb * RE_X_RB, n[i], vo)) { + fprintf(stderr, "Error initializing REGs\n"); + goto clean_and_exit; + } + /*DEBUG("Available REG #%3d: l=%d, prb=%d, nreg=%d (k0=%d)\n", k, i, prb, j[i], + h->regs[k].k0); + */ + j[i]++; + k++; } - /*DEBUG("Available REG #%3d: l=%d, prb=%d, nreg=%d (k0=%d)\n", k, i, prb, j[i], - h->regs[k].k0); - */ - j[i]++; - k++; + i++; + if (i == max_ctrl_symbols) { + i = 0; + jmax++; + } + if (jmax == 3) { + prb++; + bzero(j, sizeof(int) * 4); + jmax = 0; + } + } + if (regs_pcfich_init(h)) { + fprintf(stderr, "Error initializing PCFICH REGs\n"); + goto clean_and_exit; } - i++; - if (i == max_ctrl_symbols) { - i = 0; - jmax++; + + if (regs_phich_init(h)) { + fprintf(stderr, "Error initializing PHICH REGs\n"); + goto clean_and_exit; } - if (jmax == 3) { - prb++; - bzero(j, sizeof(int) * 4); - jmax = 0; + if (regs_pdcch_init(h)) { + fprintf(stderr, "Error initializing PDCCH REGs\n"); + goto clean_and_exit; } - } - if (regs_pcfich_init(h)) { - fprintf(stderr, "Error initializing PCFICH REGs\n"); - goto clean_and_exit; - } - if (regs_phich_init(h)) { - fprintf(stderr, "Error initializing PHICH REGs\n"); - goto clean_and_exit; + ret = LIBLTE_SUCCESS; } - if (regs_pdcch_init(h)) { - fprintf(stderr, "Error initializing PDCCH REGs\n"); - goto clean_and_exit; - } - - ret = 0; - clean_and_exit: - if (ret == -1) { + if (ret == LIBLTE_ERROR) { regs_free(h); } return ret; @@ -710,7 +732,7 @@ clean_and_exit: /** * Puts one REG data (4 symbols) in the slot symbols array */ -int regs_put_reg(regs_reg_t *reg, cf_t *reg_data, cf_t *slot_symbols, int nof_prb) { +int regs_put_reg(regs_reg_t *reg, cf_t *reg_data, cf_t *slot_symbols, uint8_t nof_prb) { int i; for (i = 0; i < REGS_RE_X_REG; i++) { slot_symbols[REG_IDX(reg, i, nof_prb)] = reg_data[i]; @@ -722,7 +744,7 @@ int regs_put_reg(regs_reg_t *reg, cf_t *reg_data, cf_t *slot_symbols, int nof_pr * Adds one REG data (4 symbols) in the slot symbols array * Used by PHICH */ -int regs_add_reg(regs_reg_t *reg, cf_t *reg_data, cf_t *slot_symbols, int nof_prb) { +int regs_add_reg(regs_reg_t *reg, cf_t *reg_data, cf_t *slot_symbols, uint8_t nof_prb) { int i; for (i = 0; i < REGS_RE_X_REG; i++) { slot_symbols[REG_IDX(reg, i, nof_prb)] += reg_data[i]; @@ -734,7 +756,7 @@ int regs_add_reg(regs_reg_t *reg, cf_t *reg_data, cf_t *slot_symbols, int nof_pr /** * Reset REG data (4 symbols) in the slot symbols array */ -int regs_reset_reg(regs_reg_t *reg, cf_t *slot_symbols, int nof_prb) { +int regs_reset_reg(regs_reg_t *reg, cf_t *slot_symbols, uint8_t nof_prb) { int i; for (i = 0; i < REGS_RE_X_REG; i++) { slot_symbols[REG_IDX(reg, i, nof_prb)] = 0; @@ -745,7 +767,7 @@ int regs_reset_reg(regs_reg_t *reg, cf_t *slot_symbols, int nof_prb) { /** * Gets one REG data (4 symbols) from the slot symbols array */ -int regs_get_reg(regs_reg_t *reg, cf_t *slot_symbols, cf_t *reg_data, int nof_prb) { +int regs_get_reg(regs_reg_t *reg, cf_t *slot_symbols, cf_t *reg_data, uint8_t nof_prb) { int i; for (i = 0; i < REGS_RE_X_REG; i++) { reg_data[i] = slot_symbols[REG_IDX(reg, i, nof_prb)]; @@ -753,3 +775,4 @@ int regs_get_reg(regs_reg_t *reg, cf_t *slot_symbols, cf_t *reg_data, int nof_pr return REGS_RE_X_REG; } + diff --git a/lte/phy/lib/phch/src/sequences.c b/lte/phy/lib/phch/src/sequences.c index 372179926..6a530dc5a 100644 --- a/lte/phy/lib/phch/src/sequences.c +++ b/lte/phy/lib/phch/src/sequences.c @@ -33,7 +33,7 @@ /** * 36.211 6.6.1 */ -int sequence_pbch(sequence_t *seq, lte_cp_t cp, int cell_id) { +int sequence_pbch(sequence_t *seq, lte_cp_t cp, uint16_t cell_id) { bzero(seq, sizeof(sequence_t)); return sequence_LTEPRS(seq, CP_ISNORM(cp)?1920:1728, cell_id); } @@ -41,7 +41,7 @@ int sequence_pbch(sequence_t *seq, lte_cp_t cp, int cell_id) { /** * 36.211 6.7.1 */ -int sequence_pcfich(sequence_t *seq, int nslot, int cell_id) { +int sequence_pcfich(sequence_t *seq, uint8_t nslot, uint16_t cell_id) { bzero(seq, sizeof(sequence_t)); return sequence_LTEPRS(seq, 32, (nslot/2+1) * (2*cell_id + 1) * 512 + cell_id); } @@ -50,7 +50,7 @@ int sequence_pcfich(sequence_t *seq, int nslot, int cell_id) { /** * 36.211 6.9.1 */ -int sequence_phich(sequence_t *seq, int nslot, int cell_id) { +int sequence_phich(sequence_t *seq, uint8_t nslot, uint16_t cell_id) { bzero(seq, sizeof(sequence_t)); return sequence_LTEPRS(seq, 12, (nslot/2+1) * (2*cell_id + 1) * 512 + cell_id); } @@ -58,7 +58,7 @@ int sequence_phich(sequence_t *seq, int nslot, int cell_id) { /** * 36.211 6.8.2 */ -int sequence_pdcch(sequence_t *seq, int nslot, int cell_id, int len) { +int sequence_pdcch(sequence_t *seq, uint8_t nslot, uint16_t cell_id, uint32_t len) { bzero(seq, sizeof(sequence_t)); return sequence_LTEPRS(seq, len, (nslot/2) * 512 + cell_id); } @@ -66,7 +66,7 @@ int sequence_pdcch(sequence_t *seq, int nslot, int cell_id, int len) { /** * 36.211 6.3.1 */ -int sequence_pdsch(sequence_t *seq, unsigned short rnti, int q, int nslot, int cell_id, int len) { - bzero(seq, sizeof(sequence_t)); - return sequence_LTEPRS(seq, len, (rnti<<14) + (q<<13) + ((nslot/2)<<9) + cell_id); +int sequence_pdsch(sequence_t *seq, unsigned short rnti, int q, uint8_t nslot, uint16_t cell_id, uint32_t len) { + bzero(seq, sizeof(sequence_t)); + return sequence_LTEPRS(seq, len, (rnti<<14) + (q<<13) + ((nslot/2)<<9) + cell_id); } diff --git a/lte/phy/lib/phch/test/pbch_file_test.c b/lte/phy/lib/phch/test/pbch_file_test.c index a3fab332e..908af0ed7 100644 --- a/lte/phy/lib/phch/test/pbch_file_test.c +++ b/lte/phy/lib/phch/test/pbch_file_test.c @@ -35,13 +35,16 @@ char *input_file_name = NULL; char *matlab_file_name = NULL; -int cell_id = 150; -lte_cp_t cp = CPNORM; -int nof_prb = 6; FILE *fmatlab = NULL; -#define NOF_PORTS 2 +lte_cell_t cell = { + 6, // nof_prb + 2, // nof_ports + 150, // cell_id + CPNORM // cyclic prefix +}; + #define FLEN 9600 filesource_t fsrc; @@ -53,20 +56,22 @@ chest_t chest; void usage(char *prog) { printf("Usage: %s [vcoe] -i input_file\n", prog); printf("\t-o output matlab file name [Default Disabled]\n"); - printf("\t-c cell_id [Default %d]\n", cell_id); + printf("\t-c cell_id [Default %d]\n", cell.id); + printf("\t-n nof_prb [Default %d]\n", cell.nof_prb); printf("\t-e Set extended prefix [Default Normal]\n"); printf("\t-v [set verbose to debug, default none]\n"); } void parse_args(int argc, char **argv) { int opt; + while ((opt = getopt(argc, argv, "iovce")) != -1) { switch(opt) { case 'i': input_file_name = argv[optind]; break; case 'c': - cell_id = atoi(argv[optind]); + cell.id = atoi(argv[optind]); break; case 'o': matlab_file_name = argv[optind]; @@ -75,7 +80,7 @@ void parse_args(int argc, char **argv) { verbose++; break; case 'e': - cp = CPEXT; + cell.cp = CPEXT; break; default: usage(argv[0]); @@ -112,36 +117,36 @@ int base_init() { exit(-1); } - fft_buffer = malloc(CP_NSYMB(cp) * nof_prb * RE_X_RB * sizeof(cf_t)); + fft_buffer = malloc(CP_NSYMB(cell.cp) * cell.nof_prb * RE_X_RB * sizeof(cf_t)); if (!fft_buffer) { perror("malloc"); return -1; } for (i=0;i 0) { slot_symbols[0][j] += slot_symbols[i][j]; @@ -190,7 +194,7 @@ int main(int argc, char **argv) { quit: pdsch_free(&pdsch); - for (i=0;i #include "liblte/phy/resampling/decim.h" +#include "liblte/phy/resampling/resample_arb.h" #include "liblte/phy/utils/debug.h" #include "liblte/phy/sync/sync_frame.h" @@ -59,6 +60,8 @@ int sync_frame_init(sync_frame_t *q, int downsampling) { perror("malloc"); goto clean_exit; } + + resample_arb_init(&q->resample, (float) 1/downsampling); q->downsampling = downsampling; sync_frame_reset(q); @@ -78,6 +81,7 @@ void sync_frame_free(sync_frame_t *q) { if (q->input_downsampled) { free(q->input_downsampled); } + cfo_free(&q->cfocorr); sync_free(&q->s); } @@ -183,6 +187,7 @@ int sync_frame_push(sync_frame_t *q, cf_t *input, cf_t *output) { if (q->downsampling == 1) { input_ds = input; } else { + //resample_arb_compute(&q->resample, input, q->input_downsampled, SYNC_SF_LEN * q->downsampling); decim_c(input, q->input_downsampled, q->downsampling, SYNC_SF_LEN * q->downsampling); input_ds = q->input_downsampled; }