Fixed issues with cell_measurement

master
ismagom 10 years ago
parent b2c009e1fa
commit 17dd292089

@ -113,6 +113,9 @@ int cuhd_recv_wrapper(void *h, void *data, uint32_t nsamples) {
return cuhd_recv(h, data, nsamples, 1); return cuhd_recv(h, data, nsamples, 1);
} }
extern float mean_exec_time;
enum receiver_state { DECODE_MIB, DECODE_SIB, MEASURE} state;
int main(int argc, char **argv) { int main(int argc, char **argv) {
int ret; int ret;
@ -121,8 +124,18 @@ int main(int argc, char **argv) {
lte_cell_t cell; lte_cell_t cell;
int64_t sf_cnt; int64_t sf_cnt;
ue_sync_t ue_sync; ue_sync_t ue_sync;
ue_mib_t ue_mib;
void *uhd; void *uhd;
ue_dl_t ue_dl; ue_dl_t ue_dl;
lte_fft_t fft;
chest_t chest;
uint32_t nframes=0;
uint32_t nof_trials = 0;
uint32_t sfn = 0; // system frame number
int n;
uint8_t bch_payload[BCH_PAYLOAD_LEN], bch_payload_unpacked[BCH_PAYLOAD_LEN];
uint32_t sfn_offset;
float rssi=0, rsrp=0, rsrq=0;
parse_args(&prog_args, argc, argv); parse_args(&prog_args, argc, argv);
@ -154,14 +167,15 @@ int main(int argc, char **argv) {
fprintf(stderr, "Error initiating UE downlink processing module\n"); fprintf(stderr, "Error initiating UE downlink processing module\n");
exit(-1); exit(-1);
} }
if (ue_mib_init_known_cell(&ue_mib, cell, false)) {
fprintf(stderr, "Error initaiting UE MIB decoder\n");
exit(-1);
}
pdsch_set_rnti(&ue_dl.pdsch, SIRNTI); pdsch_set_rnti(&ue_dl.pdsch, SIRNTI);
/* Initialize subframe counter */ /* Initialize subframe counter */
sf_cnt = 0; sf_cnt = 0;
lte_fft_t fft;
chest_t chest;
if (lte_fft_init(&fft, cell.cp, cell.nof_prb)) { if (lte_fft_init(&fft, cell.cp, cell.nof_prb)) {
fprintf(stderr, "Error initiating FFT\n"); fprintf(stderr, "Error initiating FFT\n");
return -1; return -1;
@ -172,11 +186,8 @@ int main(int argc, char **argv) {
} }
int sf_re = SF_LEN_RE(cell.nof_prb, cell.cp); int sf_re = SF_LEN_RE(cell.nof_prb, cell.cp);
printf("%d RE allocated\n", sf_re);
cf_t *sf_symbols = vec_malloc(sf_re * sizeof(cf_t)); cf_t *sf_symbols = vec_malloc(sf_re * sizeof(cf_t));
uint32_t nframes=0;
bool sib1_decoded = false;
int n;
/* Main loop */ /* Main loop */
while (sf_cnt < prog_args.nof_subframes || prog_args.nof_subframes == -1) { while (sf_cnt < prog_args.nof_subframes || prog_args.nof_subframes == -1) {
@ -186,30 +197,58 @@ int main(int argc, char **argv) {
fprintf(stderr, "Error calling ue_sync_work()\n"); fprintf(stderr, "Error calling ue_sync_work()\n");
} }
float rssi=0, rsrp=0, rsrq=0;
/* iodev_receive returns 1 if successfully read 1 aligned subframe */ /* iodev_receive returns 1 if successfully read 1 aligned subframe */
if (ret == 1) { if (ret == 1) {
switch (state) {
if (!sib1_decoded) { case DECODE_MIB:
n = ue_dl_decode(&ue_dl, sf_buffer, data, ue_sync_get_sfidx(&ue_sync), SIRNTI); if (ue_sync_get_sfidx(&ue_sync) == 0) {
if (n < 0) { pbch_decode_reset(&ue_mib.pbch);
fprintf(stderr, "\nError running receiver\n");fflush(stdout); n = ue_mib_decode_aligned_frame(&ue_mib, &sf_buffer[ue_sync_sf_len(&ue_sync)/2], bch_payload_unpacked, NULL, &sfn_offset);
exit(-1); if (n < 0) {
} else if (n > 0) { fprintf(stderr, "Error decoding UE MIB\n");
printf("\n\nDecoded SIB1 Message Len %d: ",n); exit(-1);
bit_unpack_vector(data, data_unpacked, n); } else if (n == MIB_FOUND) {
void *dlsch_msg = bcch_dlsch_unpack(data_unpacked, n); bit_unpack_vector(bch_payload_unpacked, bch_payload, BCH_PAYLOAD_LEN);
if (dlsch_msg) { bcch_bch_unpack(bch_payload, BCH_PAYLOAD_LEN, &cell, &sfn);
printf("\n");fflush(stdout); printf("MIB found SFN: %d, offset: %d\n", sfn, sfn_offset);
sib1_decoded = true; sfn = (sfn<<2) + sfn_offset;
cell_access_info_t cell_info; state = DECODE_SIB;
bcch_dlsch_sib1_get_cell_access_info(dlsch_msg, &cell_info); }
printf("Cell ID: 0x%x\n", cell_info.cell_id);
} }
} break;
} else { case DECODE_SIB:
/* Run FFT for all subframe data */ sfn=0;
/* If we are looking for SI Blocks, search only in appropiate places */
if ((sfn % 2) == 0 && (ue_sync_get_sfidx(&ue_sync) == 5)) {
n = ue_dl_decode(&ue_dl, sf_buffer, data, ue_sync_get_sfidx(&ue_sync), sfn, SIRNTI);
if (n < 0) {
fprintf(stderr, "Error decoding UE DL\n");fflush(stdout);
exit(-1);
} else if (n == 0) {
// Printf
// if (!(sf_cnt%20)) {
printf("CFO: %+6.4f KHz, SFO: %+6.4f Khz, ExecTime: %5.1f us, NOI: %.2f, Nof Trials: %4d, Nof Error: %4d\r",
ue_sync_get_cfo(&ue_sync)/1000, ue_sync_get_sfo(&ue_sync)/1000,
mean_exec_time, pdsch_average_noi(&ue_dl.pdsch),
(int) nof_trials, (int) ue_dl.pkt_errors);
// }
nof_trials++;
} else {
printf("\n\nDecoded SIB1 Message Len %d: ",n);
bit_unpack_vector(data, data_unpacked, n);
void *dlsch_msg = bcch_dlsch_unpack(data_unpacked, n);
if (dlsch_msg) {
printf("\n");fflush(stdout);
cell_access_info_t cell_info;
bcch_dlsch_sib1_get_cell_access_info(dlsch_msg, &cell_info);
printf("Cell ID: 0x%x\n", cell_info.cell_id);
}
state = MEASURE;
}
}
break;
case MEASURE:
/* Run FFT for all subframe data */
lte_fft_run_sf(&fft, sf_buffer, sf_symbols); lte_fft_run_sf(&fft, sf_buffer, sf_symbols);
chest_measure_sf(&chest, sf_symbols, ue_sync_get_sfidx(&ue_sync)); chest_measure_sf(&chest, sf_symbols, ue_sync_get_sfidx(&ue_sync));
@ -226,12 +265,21 @@ int main(int argc, char **argv) {
10*log10(rsrp*1000)-prog_args.uhd_gain, 10*log10(rsrp*1000)-prog_args.uhd_gain,
10*log10(rsrq)); 10*log10(rsrq));
} }
break;
}
if (ue_sync_get_sfidx(&ue_sync) == 0) {
sfn++;
if (sfn == 1024) {
sfn = 0;
}
} }
} else if (ret == 0) { } else if (ret == 0) {
printf("Finding PSS... Peak: %8.1f, FrameCnt: %d, State: %d\r", printf("Finding PSS... Peak: %8.1f, FrameCnt: %d, State: %d\r",
sync_get_peak_value(&ue_sync.sfind), sync_get_peak_value(&ue_sync.sfind),
ue_sync.frame_total_cnt, ue_sync.state); ue_sync.frame_total_cnt, ue_sync.state);
} }
sf_cnt++; sf_cnt++;
} // Main loop } // Main loop

@ -49,7 +49,7 @@ int decode_pbch(void *uhd, ue_celldetect_result_t *found_cell, uint32_t nof_fram
int ret = LIBLTE_ERROR; int ret = LIBLTE_ERROR;
uint32_t nof_frames = 0; uint32_t nof_frames = 0;
uint32_t flen = MIB_FRAME_SIZE; uint32_t flen = MIB_FRAME_SIZE_SEARCH;
cf_t *buffer = vec_malloc(sizeof(cf_t) * flen); cf_t *buffer = vec_malloc(sizeof(cf_t) * flen);
if (!buffer) { if (!buffer) {
@ -75,7 +75,7 @@ int decode_pbch(void *uhd, ue_celldetect_result_t *found_cell, uint32_t nof_fram
DEBUG("Calling ue_mib_decode() %d/%d\n", nof_frames, nof_frames_total); DEBUG("Calling ue_mib_decode() %d/%d\n", nof_frames, nof_frames_total);
n = ue_mib_decode(&uemib, buffer, flen); n = ue_mib_sync_and_decode(&uemib, buffer, flen);
if (n == LIBLTE_ERROR || n == LIBLTE_ERROR_INVALID_INPUTS) { if (n == LIBLTE_ERROR || n == LIBLTE_ERROR_INVALID_INPUTS) {
fprintf(stderr, "Error calling ue_mib_decode()\n"); fprintf(stderr, "Error calling ue_mib_decode()\n");
goto free_and_exit; goto free_and_exit;

@ -204,9 +204,12 @@ int main(int argc, char **argv) {
break; break;
} }
fprintf(stderr, "Change in ue_dl API\n");
exit(-1);
/* iodev_receive returns 1 if successfully read 1 aligned subframe */ /* iodev_receive returns 1 if successfully read 1 aligned subframe */
if (ret == 1) { if (ret == 1) {
rlen = ue_dl_decode(&ue_dl, sf_buffer, data, iodev_get_sfidx(&iodev), prog_args.rnti); rlen = ue_dl_decode(&ue_dl, sf_buffer, data, iodev_get_sfidx(&iodev), 0, prog_args.rnti);
if (rlen < 0) { if (rlen < 0) {
fprintf(stderr, "\nError running receiver\n");fflush(stdout); fprintf(stderr, "\nError running receiver\n");fflush(stdout);
exit(-1); exit(-1);
@ -220,11 +223,10 @@ int main(int argc, char **argv) {
// Plot and Printf // Plot and Printf
if (!(sf_cnt % 10)) { if (!(sf_cnt % 10)) {
printf("CFO: %+.4f KHz, SFO: %+.4f Khz, NOI: %.2f Errors: %4d/%4d/%4d, BLER: %.1e, Texec: %.2f\r", printf("CFO: %+.4f KHz, SFO: %+.4f Khz, NOI: %.2f Errors: %4d/%4d, BLER: %.1e, Texec: %.2f\r",
ue_sync_get_cfo(&iodev.sframe)/1000, ue_sync_get_sfo(&iodev.sframe)/1000, ue_sync_get_cfo(&iodev.sframe)/1000, ue_sync_get_sfo(&iodev.sframe)/1000,
pdsch_average_noi(&ue_dl.pdsch), pdsch_average_noi(&ue_dl.pdsch),
(int) ue_dl.pkt_errors, (int) ue_dl.pkts_total, (int) ue_dl.nof_trials, (int) ue_dl.pkt_errors, (int) ue_dl.pkts_total, (float) ue_dl.pkt_errors / ue_dl.pkts_total,
(float) ue_dl.pkt_errors / ue_dl.pkts_total,
mean_exec_time); mean_exec_time);
} }

@ -29,6 +29,7 @@
#ifndef _LTEBASE_ #ifndef _LTEBASE_
#define _LTEBASE_ #define _LTEBASE_
#include <stdio.h>
#include <stdint.h> #include <stdint.h>
#include <stdbool.h> #include <stdbool.h>
#include "liblte/config.h" #include "liblte/config.h"
@ -86,6 +87,9 @@ typedef enum {CPNORM, CPEXT} lte_cp_t;
#define SF_LEN(symbol_sz) (2*SLOT_LEN(symbol_sz)) #define SF_LEN(symbol_sz) (2*SLOT_LEN(symbol_sz))
#define SF_LEN_MAX (SF_LEN(SYMBOL_SZ_MAX)) #define SF_LEN_MAX (SF_LEN(SYMBOL_SZ_MAX))
#define SLOT_LEN_PRB(nof_prb) (SLOT_LEN(lte_symbol_sz(nof_prb)))
#define SF_LEN_PRB(nof_prb) (SF_LEN(lte_symbol_sz(nof_prb)))
#define SLOT_LEN_RE(nof_prb, cp) (nof_prb*RE_X_RB*CP_NSYMB(cp)) #define SLOT_LEN_RE(nof_prb, cp) (nof_prb*RE_X_RB*CP_NSYMB(cp))
#define SF_LEN_RE(nof_prb, cp) (2*SLOT_LEN_RE(nof_prb, cp)) #define SF_LEN_RE(nof_prb, cp) (2*SLOT_LEN_RE(nof_prb, cp))
@ -139,6 +143,9 @@ LIBLTE_API enum band_geographical_area {
LIBLTE_API bool lte_cell_isvalid(lte_cell_t *cell); LIBLTE_API bool lte_cell_isvalid(lte_cell_t *cell);
LIBLTE_API void lte_cell_fprint(FILE *stream,
lte_cell_t *cell);
LIBLTE_API bool lte_N_id_2_isvalid(uint32_t N_id_2); LIBLTE_API bool lte_N_id_2_isvalid(uint32_t N_id_2);
LIBLTE_API bool lte_N_id_1_isvalid(uint32_t N_id_1); LIBLTE_API bool lte_N_id_1_isvalid(uint32_t N_id_1);

@ -73,10 +73,6 @@ typedef struct LIBLTE_API {
uint64_t pkt_errors; uint64_t pkt_errors;
uint64_t pkts_total; uint64_t pkts_total;
uint64_t nof_trials;
uint32_t sfn;
bool pbch_decoded;
uint16_t user_rnti; uint16_t user_rnti;
}ue_dl_t; }ue_dl_t;
@ -92,6 +88,7 @@ LIBLTE_API int ue_dl_decode(ue_dl_t *q,
cf_t *sf_buffer, cf_t *sf_buffer,
uint8_t *data, uint8_t *data,
uint32_t sf_idx, uint32_t sf_idx,
uint32_t sfn,
uint16_t rnti); uint16_t rnti);
#endif #endif

@ -56,8 +56,8 @@
#include "liblte/phy/common/fft.h" #include "liblte/phy/common/fft.h"
#define MIB_NOF_PORTS 2 #define MIB_MAX_PORTS 4
#define MIB_FRAME_SIZE 9600 #define MIB_FRAME_SIZE_SEARCH 9600
#define MIB_FRAME_UNALIGNED -3 #define MIB_FRAME_UNALIGNED -3
#define MIB_FOUND 1 #define MIB_FOUND 1
@ -66,10 +66,8 @@
typedef struct LIBLTE_API { typedef struct LIBLTE_API {
sync_t sfind; sync_t sfind;
uint32_t cell_id;
cf_t *slot1_symbols; cf_t *slot1_symbols;
cf_t *ce[MIB_NOF_PORTS]; cf_t *ce[MIB_MAX_PORTS];
lte_fft_t fft; lte_fft_t fft;
chest_t chest; chest_t chest;
@ -88,13 +86,23 @@ LIBLTE_API int ue_mib_init(ue_mib_t *q,
uint32_t cell_id, uint32_t cell_id,
lte_cp_t cp); lte_cp_t cp);
LIBLTE_API int ue_mib_init_known_cell(ue_mib_t *q,
lte_cell_t cell,
bool do_sync);
LIBLTE_API void ue_mib_free(ue_mib_t *q); LIBLTE_API void ue_mib_free(ue_mib_t *q);
LIBLTE_API void ue_mib_reset(ue_mib_t *q); LIBLTE_API void ue_mib_reset(ue_mib_t *q);
LIBLTE_API int ue_mib_decode(ue_mib_t *q, LIBLTE_API int ue_mib_sync_and_decode(ue_mib_t *q,
cf_t *signal, cf_t *signal,
uint32_t nsamples); uint32_t nsamples);
LIBLTE_API int ue_mib_decode_aligned_frame(ue_mib_t * q,
cf_t *input,
uint8_t bch_payload[BCH_PAYLOAD_LEN],
uint32_t *nof_tx_ports,
uint32_t *sfn_offset);
LIBLTE_API void ue_mib_get_payload(ue_mib_t *q, LIBLTE_API void ue_mib_get_payload(ue_mib_t *q,
uint8_t bch_payload[BCH_PAYLOAD_LEN], uint8_t bch_payload[BCH_PAYLOAD_LEN],

@ -99,6 +99,8 @@ LIBLTE_API int ue_sync_init(ue_sync_t *q,
LIBLTE_API void ue_sync_free(ue_sync_t *q); LIBLTE_API void ue_sync_free(ue_sync_t *q);
LIBLTE_API uint32_t ue_sync_sf_len(ue_sync_t *q);
LIBLTE_API int ue_sync_get_buffer(ue_sync_t *q, LIBLTE_API int ue_sync_get_buffer(ue_sync_t *q,
cf_t **sf_symbols); cf_t **sf_symbols);

@ -38,7 +38,7 @@
#define SLOT_SZ(q) (q->nof_symbols * q->symbol_sz) #define SLOT_SZ(q) (q->nof_symbols * q->symbol_sz)
#define SF_SZ(q) (2 * SLOT_SZ(q)) #define SF_SZ(q) (2 * SLOT_SZ(q))
#define VOLK_INTERP //#define VOLK_INTERP
void chest_fprint(chest_t *q, FILE *stream, uint32_t nslot, uint32_t port_id) { void chest_fprint(chest_t *q, FILE *stream, uint32_t nslot, uint32_t port_id) {
chest_ref_fprint(q, stream, nslot, port_id); chest_ref_fprint(q, stream, nslot, port_id);

@ -65,6 +65,10 @@ bool lte_cell_isvalid(lte_cell_t *cell) {
} }
} }
void lte_cell_fprint(FILE *stream, lte_cell_t *cell) {
fprintf(stream, "PCI: %d, CP: %s, PRB: %d, Ports: %d\n", cell->id, lte_cp_string(cell->cp), cell->nof_prb, cell->nof_ports);
}
bool lte_N_id_2_isvalid(uint32_t N_id_2) { bool lte_N_id_2_isvalid(uint32_t N_id_2) {
if (N_id_2 < 3) { if (N_id_2 < 3) {
return true; return true;

@ -77,7 +77,7 @@ int precoding_diversity(cf_t *x[MAX_LAYERS], cf_t *y[MAX_PORTS], int nof_ports,
} }
return 4 * i; return 4 * i;
} else { } else {
fprintf(stderr, "Number of ports must be 2 or 4 for transmit diversity\n"); fprintf(stderr, "Number of ports must be 2 or 4 for transmit diversity (nof_ports=%d)\n", nof_ports);
return -1; return -1;
} }
} }
@ -180,7 +180,7 @@ int predecoding_diversity_zf(cf_t *y, cf_t *ce[MAX_PORTS], cf_t *x[MAX_LAYERS],
} }
return i; return i;
} else { } else {
fprintf(stderr, "Number of ports must be 2 or 4 for transmit diversity\n"); fprintf(stderr, "Number of ports must be 2 or 4 for transmit diversity (nof_ports=%d)\n", nof_ports);
return -1; return -1;
} }
} }

@ -270,6 +270,8 @@ int pbch_decode_frame(pbch_t *q, uint32_t src, uint32_t dst, uint32_t n,
uint32_t nof_bits, uint32_t nof_ports) { uint32_t nof_bits, uint32_t nof_ports) {
int j; int j;
INFO("Trying to decode PBCH %d bits, %d ports, src: %d, dst: %d, n=%d\n", nof_bits, nof_ports, src, dst, n);
memcpy(&q->temp[dst * nof_bits], &q->pbch_llr[src * nof_bits], memcpy(&q->temp[dst * nof_bits], &q->pbch_llr[src * nof_bits],
n * nof_bits * sizeof(float)); n * nof_bits * sizeof(float));
@ -290,6 +292,7 @@ int pbch_decode_frame(pbch_t *q, uint32_t src, uint32_t dst, uint32_t n,
/* FIXME: If channel estimates are zero, received LLR are NaN. Check and return error */ /* FIXME: If channel estimates are zero, received LLR are NaN. Check and return error */
for (j = 0; j < BCH_ENCODED_LEN; j++) { for (j = 0; j < BCH_ENCODED_LEN; j++) {
if (isnan(q->pbch_rm_f[j]) || isinf(q->pbch_rm_f[j])) { if (isnan(q->pbch_rm_f[j]) || isinf(q->pbch_rm_f[j])) {
printf("Some CE are NaN or Inf!\n");
return LIBLTE_ERROR; return LIBLTE_ERROR;
} }
} }
@ -316,8 +319,7 @@ int pbch_decode(pbch_t *q, cf_t *slot1_symbols, cf_t *ce_slot1[MAX_PORTS],
uint8_t bch_payload[BCH_PAYLOAD_LEN], uint32_t *nof_tx_ports, uint32_t *sfn_offset) uint8_t bch_payload[BCH_PAYLOAD_LEN], uint32_t *nof_tx_ports, uint32_t *sfn_offset)
{ {
uint32_t src, dst, nb; uint32_t src, dst, nb;
uint32_t nant_[3] = { 1, 2, 4 }; uint32_t nant;
uint32_t na, nant;
int i; int i;
int nof_bits; int nof_bits;
cf_t *x[MAX_LAYERS]; cf_t *x[MAX_LAYERS];
@ -360,38 +362,50 @@ int pbch_decode(pbch_t *q, cf_t *slot1_symbols, cf_t *ce_slot1[MAX_PORTS],
ret = 0; ret = 0;
/* Try decoding for 1 to cell.nof_ports antennas */ /* Try decoding for 1 to cell.nof_ports antennas */
for (na = 0; na < q->cell.nof_ports && !ret; na++) { for (nant = 1; nant <= q->cell.nof_ports && !ret; nant++) {
nant = nant_[na]; if (nant != 3) {
DEBUG("Trying %d TX antennas with %d frames\n", nant, q->frame_idx);
DEBUG("Trying %d TX antennas with %d frames\n", nant, q->frame_idx);
/* in conctrol channels, only diversity is supported */
/* in conctrol channels, only diversity is supported */ if (nant == 1) {
if (nant == 1) { /* no need for layer demapping */
/* no need for layer demapping */ predecoding_single_zf(q->pbch_symbols[0], q->ce[0], q->pbch_d,
predecoding_single_zf(q->pbch_symbols[0], q->ce[0], q->pbch_d, q->nof_symbols);
q->nof_symbols); } else {
} else { predecoding_diversity_zf(q->pbch_symbols[0], q->ce, x, nant,
predecoding_diversity_zf(q->pbch_symbols[0], q->ce, x, nant, q->nof_symbols);
q->nof_symbols); layerdemap_diversity(x, q->pbch_d, nant, q->nof_symbols / nant);
layerdemap_diversity(x, q->pbch_d, nant, q->nof_symbols / nant); }
}
/* demodulate symbols */ /* demodulate symbols */
demod_soft_sigma_set(&q->demod, 1.0); demod_soft_sigma_set(&q->demod, 1.0);
demod_soft_demodulate(&q->demod, q->pbch_d, demod_soft_demodulate(&q->demod, q->pbch_d,
&q->pbch_llr[nof_bits * (q->frame_idx - 1)], q->nof_symbols); &q->pbch_llr[nof_bits * (q->frame_idx - 1)], q->nof_symbols);
/* We don't know where the 40 ms begin, so we try all combinations. E.g. if we received /* We don't know where the 40 ms begin, so we try all combinations. E.g. if we received
* 4 frames, try 1,2,3,4 individually, 12, 23, 34 in pairs, 123, 234 and finally 1234. * 4 frames, try 1,2,3,4 individually, 12, 23, 34 in pairs, 123, 234 and finally 1234.
* We know they are ordered. * We know they are ordered.
* *
* FIXME: There are unnecessary checks because 2,3,4 have already been processed in the previous * FIXME: There are unnecessary checks because 2,3,4 have already been processed in the previous
* calls. * calls.
*/ */
for (nb = 0; nb < q->frame_idx && !ret; nb++) { for (nb = 0; nb < q->frame_idx && !ret; nb++) {
for (dst = 0; (dst < 4 - nb) && !ret; dst++) { for (dst = 0; (dst < 4 - nb) && !ret; dst++) {
for (src = 0; src < q->frame_idx - nb && !ret; src++) { for (src = 0; src < q->frame_idx - nb && !ret; src++) {
ret = pbch_decode_frame(q, src, dst, nb + 1, nof_bits, nant); ret = pbch_decode_frame(q, src, dst, nb + 1, nof_bits, nant);
if (ret == 1) {
if (sfn_offset) {
*sfn_offset = dst - src;
}
if (nof_tx_ports) {
*nof_tx_ports = nant;
}
if (bch_payload) {
memcpy(bch_payload, q->data, sizeof(uint8_t) * BCH_PAYLOAD_LEN);
vec_fprint_hex(stdout, bch_payload, BCH_PAYLOAD_LEN);
}
}
}
} }
} }
} }
@ -403,18 +417,6 @@ int pbch_decode(pbch_t *q, cf_t *slot1_symbols, cf_t *ce_slot1[MAX_PORTS],
q->frame_idx = 3; q->frame_idx = 3;
} }
} }
if (ret == 1) {
if (sfn_offset) {
*sfn_offset = dst - src;
}
if (nof_tx_ports) {
*nof_tx_ports = nant;
}
if (bch_payload) {
memcpy(bch_payload, q->data, sizeof(uint8_t) * BCH_PAYLOAD_LEN);
vec_fprint_hex(stdout, bch_payload, BCH_PAYLOAD_LEN);
}
}
return ret; return ret;
} }

@ -573,6 +573,7 @@ int regs_num_x_symbol(uint32_t symbol, uint32_t nof_port, lte_cp_t cp) {
case 4: case 4:
return 2; return 2;
default: default:
fprintf(stderr, "Invalid number of ports %d\n", nof_port);
return LIBLTE_ERROR; return LIBLTE_ERROR;
} }
break; break;
@ -585,6 +586,7 @@ int regs_num_x_symbol(uint32_t symbol, uint32_t nof_port, lte_cp_t cp) {
return 2; return 2;
} }
default: default:
fprintf(stderr, "Invalid symbol %d\n", symbol);
return LIBLTE_ERROR; return LIBLTE_ERROR;
} }
} }
@ -697,7 +699,7 @@ int regs_init(regs_t *h, lte_cell_t cell) {
for (i = 0; i < max_ctrl_symbols; i++) { for (i = 0; i < max_ctrl_symbols; i++) {
n[i] = regs_num_x_symbol(i, h->cell.nof_ports, h->cell.cp); n[i] = regs_num_x_symbol(i, h->cell.nof_ports, h->cell.cp);
if (n[i] == -1) { if (n[i] == -1) {
return -1; goto clean_and_exit;
} }
h->nof_regs += h->cell.nof_prb * n[i]; h->nof_regs += h->cell.nof_prb * n[i];
} }
@ -752,7 +754,7 @@ int regs_init(regs_t *h, lte_cell_t cell) {
ret = LIBLTE_SUCCESS; ret = LIBLTE_SUCCESS;
} }
clean_and_exit: clean_and_exit:
if (ret == LIBLTE_ERROR) { if (ret != LIBLTE_SUCCESS) {
regs_free(h); regs_free(h);
} }
return ret; return ret;

@ -232,6 +232,8 @@ int sync_find(sync_t *q, cf_t *input, uint32_t find_offset, uint32_t *peak_posit
{ {
int peak_pos; int peak_pos;
ret = LIBLTE_ERROR;
if (peak_position) { if (peak_position) {
*peak_position = 0; *peak_position = 0;
} }

@ -48,13 +48,12 @@ int ue_dl_init(ue_dl_t *q,
{ {
ret = LIBLTE_ERROR; ret = LIBLTE_ERROR;
bzero(q, sizeof(ue_dl_t));
q->cell = cell; q->cell = cell;
q->user_rnti = user_rnti; q->user_rnti = user_rnti;
q->pkt_errors = 0; q->pkt_errors = 0;
q->pkts_total = 0; q->pkts_total = 0;
q->nof_trials = 0;
q->sfn = 0;
q->pbch_decoded = false;
if (lte_fft_init(&q->fft, q->cell.cp, q->cell.nof_prb)) { if (lte_fft_init(&q->fft, q->cell.cp, q->cell.nof_prb)) {
fprintf(stderr, "Error initiating FFT\n"); fprintf(stderr, "Error initiating FFT\n");
@ -144,7 +143,7 @@ void ue_dl_free(ue_dl_t *q) {
LIBLTE_API float mean_exec_time=0; LIBLTE_API float mean_exec_time=0;
int frame_cnt=0; int frame_cnt=0;
int ue_dl_decode(ue_dl_t *q, cf_t *input, uint8_t *data, uint32_t sf_idx, uint16_t rnti) int ue_dl_decode(ue_dl_t *q, cf_t *input, uint8_t *data, uint32_t sf_idx, uint32_t sfn, uint16_t rnti)
{ {
uint32_t cfi, cfi_distance, i; uint32_t cfi, cfi_distance, i;
ra_pdsch_t ra_dl; ra_pdsch_t ra_dl;
@ -154,7 +153,6 @@ int ue_dl_decode(ue_dl_t *q, cf_t *input, uint8_t *data, uint32_t sf_idx, uint16
uint16_t crc_rem; uint16_t crc_rem;
dci_format_t format; dci_format_t format;
int ret = LIBLTE_ERROR; int ret = LIBLTE_ERROR;
cf_t *ce_slot1[MAX_PORTS];
struct timeval t[3]; struct timeval t[3];
/* Run FFT for all subframe data */ /* Run FFT for all subframe data */
@ -168,127 +166,101 @@ int ue_dl_decode(ue_dl_t *q, cf_t *input, uint8_t *data, uint32_t sf_idx, uint16
gettimeofday(&t[2], NULL); gettimeofday(&t[2], NULL);
get_time_interval(t); get_time_interval(t);
mean_exec_time = (float) VEC_CMA((float) t[0].tv_usec, mean_exec_time, frame_cnt); mean_exec_time = (float) VEC_CMA((float) t[0].tv_usec, mean_exec_time, frame_cnt);
frame_cnt++; frame_cnt++;
for (int i=0;i<MAX_PORTS;i++) {
ce_slot1[i] = &q->ce[i][SLOT_LEN_RE(q->cell.nof_prb, q->cell.cp)]; /* First decode PCFICH and obtain CFI */
if (pcfich_decode(&q->pcfich, q->sf_symbols, q->ce, sf_idx, &cfi, &cfi_distance)<0) {
fprintf(stderr, "Error decoding PCFICH\n");
return LIBLTE_ERROR;
} }
/* Decode PBCH if not yet decoded to obtain the System Frame Number (SFN) */ INFO("Decoded CFI=%d with distance %d\n", cfi, cfi_distance);
if (sf_idx == 0) {
// FIXME: There is no need to do this every frame! if (regs_set_cfi(&q->regs, cfi)) {
pbch_decode_reset(&q->pbch); fprintf(stderr, "Error setting CFI\n");
if (pbch_decode(&q->pbch, &q->sf_symbols[SLOT_LEN_RE(q->cell.nof_prb, q->cell.cp)], ce_slot1, NULL, NULL, &q->sfn) == 1) { return LIBLTE_ERROR;
q->pbch_decoded = true;
INFO("Decoded SFN: %d\n", q->sfn);
} else {
INFO("Not decoded MIB (SFN: %d)\n", q->sfn);
q->sfn++;
if (q->sfn == 4) {
q->sfn = 0;
}
}
} }
/* If we are looking for SI Blocks, search only in appropiate places */
if (((rnti == SIRNTI && (q->sfn % 2) == 0 && sf_idx == 5) ||
rnti != SIRNTI))
{
/* First decode PCFICH and obtain CFI */ /* Generate PDCCH candidates */
if (pcfich_decode(&q->pcfich, q->sf_symbols, q->ce, sf_idx, &cfi, &cfi_distance)<0) { if (rnti == SIRNTI) {
fprintf(stderr, "Error decoding PCFICH\n"); nof_locations = pdcch_common_locations(&q->pdcch, locations, 10, cfi);
format = Format1A;
} else {
nof_locations = pdcch_ue_locations(&q->pdcch, locations, 10, sf_idx, cfi, q->user_rnti);
format = Format1;
}
crc_rem = 0;
for (i=0;i<nof_locations && crc_rem != rnti;i++) {
if (pdcch_extract_llr(&q->pdcch, q->sf_symbols, q->ce, locations[i], sf_idx, cfi)) {
fprintf(stderr, "Error extracting LLRs\n");
return LIBLTE_ERROR; return LIBLTE_ERROR;
} }
if (pdcch_decode_msg(&q->pdcch, &dci_msg, format, &crc_rem)) {
fprintf(stderr, "Error decoding DCI msg\n");
return LIBLTE_ERROR;
}
INFO("Decoded DCI message RNTI: 0x%x\n", crc_rem);
}
INFO("Decoded CFI=%d with distance %d\n", cfi, cfi_distance); if (crc_rem == rnti) {
printf("Hem trobat\n");
if (regs_set_cfi(&q->regs, cfi)) { if (dci_msg_to_ra_dl(&dci_msg, rnti, q->user_rnti, q->cell, cfi, &ra_dl)) {
fprintf(stderr, "Error setting CFI\n"); fprintf(stderr, "Error unpacking PDSCH scheduling DCI message\n");
return LIBLTE_ERROR; return LIBLTE_ERROR;
} }
/* Generate PDCCH candidates */ uint32_t rvidx;
if (rnti == SIRNTI) { if (rnti == SIRNTI) {
nof_locations = pdcch_common_locations(&q->pdcch, locations, 10, cfi); switch((sfn%8)/2) {
format = Format1A; case 0:
rvidx = 0;
break;
case 1:
rvidx = 2;
break;
case 2:
rvidx = 3;
break;
case 3:
rvidx = 1;
break;
}
} else { } else {
nof_locations = pdcch_ue_locations(&q->pdcch, locations, 10, sf_idx, cfi, q->user_rnti); rvidx = ra_dl.rv_idx;
format = Format1;
} }
if (rvidx == 0) {
crc_rem = 0; if (pdsch_harq_setup(&q->harq_process[0], ra_dl.mcs, &ra_dl.prb_alloc)) {
for (i=0;i<nof_locations && crc_rem != rnti;i++) { fprintf(stderr, "Error configuring HARQ process\n");
if (pdcch_extract_llr(&q->pdcch, q->sf_symbols, q->ce, locations[i], sf_idx, cfi)) {
fprintf(stderr, "Error extracting LLRs\n");
return LIBLTE_ERROR; return LIBLTE_ERROR;
} }
if (pdcch_decode_msg(&q->pdcch, &dci_msg, format, &crc_rem)) {
fprintf(stderr, "Error decoding DCI msg\n");
return LIBLTE_ERROR;
}
INFO("Decoded DCI message RNTI: 0x%x\n", crc_rem);
} }
if (q->harq_process[0].mcs.mod > 0) {
if (crc_rem == rnti) { ret = pdsch_decode(&q->pdsch, q->sf_symbols, q->ce, data, sf_idx,
if (dci_msg_to_ra_dl(&dci_msg, rnti, q->user_rnti, q->cell, cfi, &ra_dl)) { &q->harq_process[0], rvidx);
fprintf(stderr, "Error unpacking PDSCH scheduling DCI message\n"); if (ret == LIBLTE_ERROR) {
return LIBLTE_ERROR;
}
uint32_t rvidx;
if (rnti == SIRNTI) {
switch((q->sfn%8)/2) {
case 0:
rvidx = 0;
break;
case 1:
rvidx = 2;
break;
case 2:
rvidx = 3;
break;
case 3:
rvidx = 1;
break;
}
} else {
rvidx = ra_dl.rv_idx;
}
if (rvidx == 0) {
if (pdsch_harq_setup(&q->harq_process[0], ra_dl.mcs, &ra_dl.prb_alloc)) {
fprintf(stderr, "Error configuring HARQ process\n");
return LIBLTE_ERROR;
}
}
if (q->harq_process[0].mcs.mod > 0) {
ret = pdsch_decode(&q->pdsch, q->sf_symbols, q->ce, data, sf_idx,
&q->harq_process[0], rvidx);
if (ret == LIBLTE_ERROR) {
if (rnti == SIRNTI && rvidx == 1) {
q->pkt_errors++;
} else if (rnti != SIRNTI) {
q->pkt_errors++;
}
} else if (ret == LIBLTE_ERROR_INVALID_INPUTS) {
fprintf(stderr, "Error calling pdsch_decode()\n");
return LIBLTE_ERROR;
} else if (ret == LIBLTE_SUCCESS) {
if (VERBOSE_ISINFO()) {
INFO("Decoded Message: ", 0);
vec_fprint_hex(stdout, data, ra_dl.mcs.tbs);
}
}
if (rnti == SIRNTI && rvidx == 1) { if (rnti == SIRNTI && rvidx == 1) {
q->pkts_total++; q->pkt_errors++;
} else if (rnti != SIRNTI) { } else if (rnti != SIRNTI) {
q->pkts_total++; q->pkt_errors++;
}
} else if (ret == LIBLTE_ERROR_INVALID_INPUTS) {
fprintf(stderr, "Error calling pdsch_decode()\n");
return LIBLTE_ERROR;
} else if (ret == LIBLTE_SUCCESS) {
if (VERBOSE_ISINFO()) {
INFO("Decoded Message: ", 0);
vec_fprint_hex(stdout, data, ra_dl.mcs.tbs);
} }
} }
} if (rnti == SIRNTI && rvidx == 1) {
if (rnti == SIRNTI && (q->sfn%8) == 0) { q->pkts_total++;
q->nof_trials++; } else if (rnti != SIRNTI) {
q->pkts_total++;
}
} }
} }

@ -36,56 +36,61 @@
#include "liblte/phy/utils/debug.h" #include "liblte/phy/utils/debug.h"
#include "liblte/phy/utils/vector.h" #include "liblte/phy/utils/vector.h"
#define FIND_FFTSIZE 128
#define FIND_SFLEN 5*SF_LEN(FIND_FFTSIZE)
#define MIB_FIND_THRESHOLD 0.0 #define MIB_FIND_THRESHOLD 0.0
int ue_mib_init(ue_mib_t * q, int ue_mib_init(ue_mib_t * q,
uint32_t cell_id, uint32_t cell_id,
lte_cp_t cp) lte_cp_t cp)
{
lte_cell_t cell;
cell.nof_ports = MIB_MAX_PORTS;
cell.nof_prb = 6;
cell.id = cell_id;
cell.cp = cp;
return ue_mib_init_known_cell(q, cell, true);
}
int ue_mib_init_known_cell(ue_mib_t * q,
lte_cell_t cell,
bool do_sync)
{ {
int ret = LIBLTE_ERROR_INVALID_INPUTS; int ret = LIBLTE_ERROR_INVALID_INPUTS;
if (q != NULL) { if (q != NULL &&
cell.nof_ports <= MIB_MAX_PORTS)
{
ret = LIBLTE_ERROR; ret = LIBLTE_ERROR;
lte_cell_t cell;
cell.nof_ports = MIB_NOF_PORTS;
cell.nof_prb = 6;
cell.id = cell_id;
cell.cp = cp;
q->cell_id = cell_id;
bzero(q, sizeof(ue_mib_t)); bzero(q, sizeof(ue_mib_t));
q->slot1_symbols = malloc(SLOT_LEN_RE(6, cp) * sizeof(cf_t)); q->slot1_symbols = vec_malloc(SLOT_LEN_RE(cell.nof_prb, cell.cp) * sizeof(cf_t));
if (!q->slot1_symbols) { if (!q->slot1_symbols) {
perror("malloc"); perror("malloc");
goto clean_exit; goto clean_exit;
} }
for (int i=0;i<MIB_NOF_PORTS;i++) { for (int i=0;i<cell.nof_ports;i++) {
q->ce[i] = malloc(SLOT_LEN_RE(6, cp) * sizeof(cf_t)); q->ce[i] = vec_malloc(SLOT_LEN_RE(cell.nof_prb, cell.cp) * sizeof(cf_t));
if (!q->ce[i]) { if (!q->ce[i]) {
perror("malloc"); perror("malloc");
goto clean_exit; goto clean_exit;
} }
} }
if (sync_init(&q->sfind, FIND_SFLEN, FIND_FFTSIZE)) { if (do_sync) {
goto clean_exit; if (sync_init(&q->sfind, 5*SF_LEN_PRB(cell.nof_prb), lte_symbol_sz(cell.nof_prb))) {
} goto clean_exit;
}
sync_set_threshold(&q->sfind, MIB_FIND_THRESHOLD); sync_set_threshold(&q->sfind, MIB_FIND_THRESHOLD);
sync_sss_en(&q->sfind, true); sync_sss_en(&q->sfind, true);
sync_set_N_id_2(&q->sfind, cell_id % 3); sync_set_N_id_2(&q->sfind, cell.id % 3);
sync_cp_en(&q->sfind, false); sync_cp_en(&q->sfind, false);
sync_set_cp(&q->sfind, cp); sync_set_cp(&q->sfind, cell.cp);
}
if (lte_fft_init(&q->fft, cp, cell.nof_prb)) { if (lte_fft_init(&q->fft, cell.cp, cell.nof_prb)) {
fprintf(stderr, "Error initializing FFT\n"); fprintf(stderr, "Error initializing FFT\n");
goto clean_exit; goto clean_exit;
} }
@ -114,7 +119,7 @@ void ue_mib_free(ue_mib_t * q)
if (q->slot1_symbols) { if (q->slot1_symbols) {
free(q->slot1_symbols); free(q->slot1_symbols);
} }
for (int i=0;i<MIB_NOF_PORTS;i++) { for (int i=0;i<MIB_MAX_PORTS;i++) {
if (q->ce[i]) { if (q->ce[i]) {
free(q->ce[i]); free(q->ce[i]);
} }
@ -139,7 +144,8 @@ void ue_mib_set_threshold(ue_mib_t * q, float threshold)
sync_set_threshold(&q->sfind, threshold); sync_set_threshold(&q->sfind, threshold);
} }
static int mib_decoder_run(ue_mib_t * q, cf_t *input) int ue_mib_decode_aligned_frame(ue_mib_t * q, cf_t *input,
uint8_t bch_payload[BCH_PAYLOAD_LEN], uint32_t *nof_tx_ports, uint32_t *sfn_offset)
{ {
int ret = LIBLTE_SUCCESS; int ret = LIBLTE_SUCCESS;
@ -162,9 +168,9 @@ static int mib_decoder_run(ue_mib_t * q, cf_t *input)
} }
/* Decode PBCH */ /* Decode PBCH */
ret = pbch_decode(&q->pbch, q->slot1_symbols, q->ce, q->bch_payload, &q->nof_tx_ports, &q->sfn_offset); ret = pbch_decode(&q->pbch, q->slot1_symbols, q->ce, bch_payload, nof_tx_ports, sfn_offset);
if (ret < 0) { if (ret < 0) {
fprintf(stderr, "Error decoding PBCH\n"); fprintf(stderr, "Error decoding PBCH (%d)\n", ret);
} else if (ret == 1) { } else if (ret == 1) {
INFO("MIB decoded: %u\n", q->frame_cnt/2); INFO("MIB decoded: %u\n", q->frame_cnt/2);
ue_mib_reset(q); ue_mib_reset(q);
@ -176,6 +182,7 @@ static int mib_decoder_run(ue_mib_t * q, cf_t *input)
} }
return ret; return ret;
} }
int counter1=0,counter2=0,counter3=0,counter4=0; int counter1=0,counter2=0,counter3=0,counter4=0;
void ue_mib_get_payload(ue_mib_t *q, void ue_mib_get_payload(ue_mib_t *q,
@ -192,9 +199,9 @@ void ue_mib_get_payload(ue_mib_t *q,
} }
} }
int ue_mib_decode(ue_mib_t * q, int ue_mib_sync_and_decode(ue_mib_t * q,
cf_t *signal, cf_t *signal,
uint32_t nsamples) uint32_t nsamples)
{ {
int ret = LIBLTE_ERROR_INVALID_INPUTS; int ret = LIBLTE_ERROR_INVALID_INPUTS;
uint32_t peak_idx=0; uint32_t peak_idx=0;
@ -204,23 +211,23 @@ int ue_mib_decode(ue_mib_t * q,
if (q != NULL && if (q != NULL &&
signal != NULL) signal != NULL)
{ {
if (nsamples < MIB_FRAME_SIZE) { if (nsamples < MIB_FRAME_SIZE_SEARCH) {
fprintf(stderr, "Error: nsamples must be greater than %d\n", MIB_FRAME_SIZE); fprintf(stderr, "Error: nsamples must be greater than %d\n", MIB_FRAME_SIZE_SEARCH);
return LIBLTE_ERROR; return LIBLTE_ERROR;
} }
ret = LIBLTE_SUCCESS; ret = LIBLTE_SUCCESS;
if (nsamples % MIB_FRAME_SIZE) { if (nsamples % MIB_FRAME_SIZE_SEARCH) {
printf("Warning: nsamples must be a multiple of %d. Some samples will be ignored\n", MIB_FRAME_SIZE); printf("Warning: nsamples must be a multiple of %d. Some samples will be ignored\n", MIB_FRAME_SIZE_SEARCH);
nsamples = (nsamples/MIB_FRAME_SIZE) * MIB_FRAME_SIZE; nsamples = (nsamples/MIB_FRAME_SIZE_SEARCH) * MIB_FRAME_SIZE_SEARCH;
} }
nof_input_frames = nsamples/MIB_FRAME_SIZE; nof_input_frames = nsamples/MIB_FRAME_SIZE_SEARCH;
for (uint32_t nf=0;nf<nof_input_frames;nf++) { for (uint32_t nf=0;nf<nof_input_frames;nf++) {
/* Find peak and cell id */ /* Find peak and cell id */
ret = sync_find(&q->sfind, signal, nf*MIB_FRAME_SIZE, &peak_idx); ret = sync_find(&q->sfind, signal, nf*MIB_FRAME_SIZE_SEARCH, &peak_idx);
if (ret < 0) { if (ret < 0) {
fprintf(stderr, "Error finding correlation peak (%d)\n", ret); fprintf(stderr, "Error finding correlation peak (%d)\n", ret);
return -1; return -1;
@ -234,15 +241,15 @@ int ue_mib_decode(ue_mib_t * q,
/* Check if we have space for reading the MIB and we are in Subframe #0 */ /* Check if we have space for reading the MIB and we are in Subframe #0 */
if (ret == 1 && if (ret == 1 &&
nf*MIB_FRAME_SIZE + peak_idx + 960 <= nsamples && nf*MIB_FRAME_SIZE_SEARCH + peak_idx + MIB_FRAME_SIZE_SEARCH/10 <= nsamples &&
sync_sss_detected(&q->sfind) && sync_sss_detected(&q->sfind) &&
sync_get_sf_idx(&q->sfind) == 0) sync_get_sf_idx(&q->sfind) == 0)
{ {
INFO("Trying to decode MIB\n",0); INFO("Trying to decode MIB\n",0);
ret = mib_decoder_run(q, &signal[nf*MIB_FRAME_SIZE+peak_idx]); ret = ue_mib_decode_aligned_frame(q, &signal[nf*MIB_FRAME_SIZE_SEARCH+peak_idx], q->bch_payload, &q->nof_tx_ports, &q->sfn_offset);
counter3++; counter3++;
} else if ((ret == LIBLTE_SUCCESS && peak_idx != 0) || } else if ((ret == LIBLTE_SUCCESS && peak_idx != 0) ||
(ret == 1 && nf*MIB_FRAME_SIZE + peak_idx + 960 > nsamples)) (ret == 1 && nf*MIB_FRAME_SIZE_SEARCH + peak_idx + MIB_FRAME_SIZE_SEARCH/10 > nsamples))
{ {
printf("Not enough space for PBCH\n",0); printf("Not enough space for PBCH\n",0);
ret = MIB_FRAME_UNALIGNED; ret = MIB_FRAME_UNALIGNED;

@ -68,7 +68,7 @@ int ue_sync_init(ue_sync_t *q,
ue_sync_reset(q); ue_sync_reset(q);
q->decode_sss_on_track = false; q->decode_sss_on_track = true;
q->stream = stream_handler; q->stream = stream_handler;
q->recv_callback = recv_callback; q->recv_callback = recv_callback;
q->cell = cell; q->cell = cell;
@ -113,6 +113,10 @@ clean_exit:
return ret; return ret;
} }
uint32_t ue_sync_sf_len(ue_sync_t *q) {
return CURRENT_SFLEN;
}
void ue_sync_free(ue_sync_t *q) { void ue_sync_free(ue_sync_t *q) {
if (q->input_buffer) { if (q->input_buffer) {
free(q->input_buffer); free(q->input_buffer);

Loading…
Cancel
Save