mirror of https://github.com/PentHertz/srsLTE.git
Fixed naming convention in vec module. Separated viterbit and convolutional coder.
This commit is contained in:
parent
a07f3966a3
commit
f356937046
|
@ -42,5 +42,9 @@ add_executable(pss_scan_usrp pss_scan_usrp.c ../uhd/uhd_imp.cpp ../uhd/uhd_utils
|
|||
target_link_libraries(pss_scan_usrp ${LIBRARIES} ${UHD_LIBRARIES})
|
||||
|
||||
|
||||
include_directories(${UHD_INCLUDE_DIRS} ${CMAKE_CURRENT_SOURCE_DIR}/../uhd)
|
||||
add_executable(mib_scan_usrp mib_scan_usrp.c ../uhd/uhd_imp.cpp ../uhd/uhd_utils.c)
|
||||
target_link_libraries(mib_scan_usrp ${LIBRARIES} ${UHD_LIBRARIES})
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -8,7 +8,7 @@
|
|||
|
||||
char *input_file_name = NULL;
|
||||
int nof_slots=100;
|
||||
float corr_peak_threshold=15;
|
||||
float corr_peak_threshold=30;
|
||||
int file_binary = 0;
|
||||
int force_N_id_2=-1;
|
||||
int nof_ports = 1;
|
||||
|
@ -94,7 +94,7 @@ int base_init() {
|
|||
}
|
||||
}
|
||||
|
||||
if (chest_init(&chest, CPNORM, 6, 1)) {
|
||||
if (chest_init(&chest, LINEAR, CPNORM, 6, 1)) {
|
||||
fprintf(stderr, "Error initializing equalizer\n");
|
||||
return -1;
|
||||
}
|
||||
|
|
|
@ -124,7 +124,7 @@ int main(int argc, char **argv) {
|
|||
fprintf(stderr, "Error: initializing FFT\n");
|
||||
goto do_exit;
|
||||
}
|
||||
if (chest_init(&eq, cp, nof_prb, 1)) {
|
||||
if (chest_init(&eq, LINEAR, cp, nof_prb, 1)) {
|
||||
fprintf(stderr, "Error initializing equalizer\n");
|
||||
goto do_exit;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,592 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <strings.h>
|
||||
#include <unistd.h>
|
||||
#include <math.h>
|
||||
#include <sys/time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "lte.h"
|
||||
|
||||
#define DISABLE_UHD
|
||||
|
||||
#ifndef DISABLE_UHD
|
||||
#include "uhd.h"
|
||||
#include "uhd_utils.h"
|
||||
#endif
|
||||
|
||||
#define MHZ 1000000
|
||||
#define SAMP_FREQ 1920000
|
||||
#define RSSI_FS 1000000
|
||||
#define FLEN 9600
|
||||
#define FLEN_PERIOD 0.005
|
||||
|
||||
#define RSSI_DECIM 20
|
||||
|
||||
#define IS_SIGNAL(i) (10*log10f(rssi[i]) + 30 > rssi_threshold)
|
||||
|
||||
|
||||
int band, earfcn=-1;
|
||||
float find_threshold = 40.0, track_threshold = 8.0;
|
||||
int earfcn_start=-1, earfcn_end = -1;
|
||||
float rssi_threshold = -30.0;
|
||||
int max_track_lost=9;
|
||||
int nof_frames_find=8, nof_frames_track=100, nof_samples_rssi=50000;
|
||||
int track_len=500;
|
||||
int nof_ports;
|
||||
|
||||
cf_t *input_buffer, *fft_buffer, *ce[MAX_PORTS];
|
||||
pbch_t pbch;
|
||||
lte_fft_t fft;
|
||||
chest_t chest;
|
||||
sync_t sfind, strack;
|
||||
|
||||
float *cfo_v;
|
||||
int *idx_v, *idx_valid, *t;
|
||||
float *p2a_v;
|
||||
void *uhd;
|
||||
int nof_bands;
|
||||
float gain = 20.0;
|
||||
|
||||
#define MAX_EARFCN 1000
|
||||
lte_earfcn_t channels[MAX_EARFCN];
|
||||
float rssi[MAX_EARFCN];
|
||||
float rssi_d[MAX_EARFCN/RSSI_DECIM];
|
||||
float freqs[MAX_EARFCN];
|
||||
float cfo[MAX_EARFCN];
|
||||
float p2a[MAX_EARFCN];
|
||||
|
||||
enum sync_state {INIT, FIND, TRACK, MIB, DONE};
|
||||
|
||||
void print_to_matlab();
|
||||
|
||||
void usage(char *prog) {
|
||||
printf("Usage: %s [seRrFfTtgv] -b band\n", prog);
|
||||
printf("\t-s earfcn_start [Default All]\n");
|
||||
printf("\t-e earfcn_end [Default All]\n");
|
||||
printf("\t-R rssi_nof_samples [Default %d]\n", nof_samples_rssi);
|
||||
printf("\t-r rssi_threshold [Default %.2f dBm]\n", rssi_threshold);
|
||||
printf("\t-F pss_find_nof_frames [Default %d]\n", nof_frames_find);
|
||||
printf("\t-f pss_find_threshold [Default %.2f]\n", find_threshold);
|
||||
printf("\t-T pss_track_nof_frames [Default %d]\n", nof_frames_track);
|
||||
printf("\t-t pss_track_threshold [Default %.2f]\n", track_threshold);
|
||||
printf("\t-l pss_track_len [Default %d]\n", track_len);
|
||||
printf("\t-g gain [Default %.2f dB]\n", gain);
|
||||
printf("\t-v [set verbose to debug, default none]\n");
|
||||
}
|
||||
|
||||
void parse_args(int argc, char **argv) {
|
||||
int opt;
|
||||
while ((opt = getopt(argc, argv, "bseRrFfTtgv")) != -1) {
|
||||
switch(opt) {
|
||||
case 'b':
|
||||
band = atoi(argv[optind]);
|
||||
break;
|
||||
case 's':
|
||||
earfcn_start = atoi(argv[optind]);
|
||||
break;
|
||||
case 'e':
|
||||
earfcn_end = atoi(argv[optind]);
|
||||
break;
|
||||
case 'R':
|
||||
nof_samples_rssi = atoi(argv[optind]);
|
||||
break;
|
||||
case 'r':
|
||||
rssi_threshold = -atof(argv[optind]);
|
||||
break;
|
||||
case 'F':
|
||||
nof_frames_find = atoi(argv[optind]);
|
||||
break;
|
||||
case 'f':
|
||||
find_threshold = atof(argv[optind]);
|
||||
break;
|
||||
case 'T':
|
||||
nof_frames_track = atoi(argv[optind]);
|
||||
break;
|
||||
case 't':
|
||||
track_threshold = atof(argv[optind]);
|
||||
break;
|
||||
case 'g':
|
||||
gain = atof(argv[optind]);
|
||||
break;
|
||||
case 'v':
|
||||
verbose++;
|
||||
break;
|
||||
default:
|
||||
usage(argv[0]);
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int base_init(int frame_length) {
|
||||
int i;
|
||||
|
||||
input_buffer = malloc(2 * frame_length * sizeof(cf_t));
|
||||
if (!input_buffer) {
|
||||
perror("malloc");
|
||||
return -1;
|
||||
}
|
||||
|
||||
fft_buffer = malloc(CPNORM_NSYMB * 72 * sizeof(cf_t));
|
||||
if (!fft_buffer) {
|
||||
perror("malloc");
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (i=0;i<nof_ports;i++) {
|
||||
ce[i] = malloc(CPNORM_NSYMB * 72 * sizeof(cf_t));
|
||||
if (!ce[i]) {
|
||||
perror("malloc");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
if (sync_init(&sfind, FLEN)) {
|
||||
fprintf(stderr, "Error initiating PSS/SSS\n");
|
||||
return -1;
|
||||
}
|
||||
if (sync_init(&strack, track_len)) {
|
||||
fprintf(stderr, "Error initiating PSS/SSS\n");
|
||||
return -1;
|
||||
}
|
||||
if (chest_init(&chest, LINEAR, CPNORM, 6, 1)) {
|
||||
fprintf(stderr, "Error initializing equalizer\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (lte_fft_init(&fft, CPNORM, 6)) {
|
||||
fprintf(stderr, "Error initializing FFT\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
idx_v = malloc(nof_frames_track * sizeof(int));
|
||||
if (!idx_v) {
|
||||
perror("malloc");
|
||||
return -1;
|
||||
}
|
||||
idx_valid = malloc(nof_frames_track * sizeof(int));
|
||||
if (!idx_valid) {
|
||||
perror("malloc");
|
||||
return -1;
|
||||
}
|
||||
t = malloc(nof_frames_track * sizeof(int));
|
||||
if (!t) {
|
||||
perror("malloc");
|
||||
return -1;
|
||||
}
|
||||
cfo_v = malloc(nof_frames_track * sizeof(float));
|
||||
if (!cfo_v) {
|
||||
perror("malloc");
|
||||
return -1;
|
||||
}
|
||||
p2a_v = malloc(nof_frames_track * sizeof(float));
|
||||
if (!p2a_v) {
|
||||
perror("malloc");
|
||||
return -1;
|
||||
}
|
||||
|
||||
bzero(cfo, sizeof(float) * MAX_EARFCN);
|
||||
bzero(p2a, sizeof(float) * MAX_EARFCN);
|
||||
|
||||
/* open UHD device */
|
||||
#ifndef DISABLE_UHD
|
||||
printf("Opening UHD device...\n");
|
||||
if (uhd_open("",&uhd)) {
|
||||
fprintf(stderr, "Error opening uhd\n");
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
void base_free() {
|
||||
int i;
|
||||
|
||||
#ifndef DISABLE_UHD
|
||||
uhd_close(&uhd);
|
||||
#endif
|
||||
sync_free(&sfind);
|
||||
sync_free(&strack);
|
||||
lte_fft_free(&fft);
|
||||
chest_free(&chest);
|
||||
|
||||
free(input_buffer);
|
||||
free(fft_buffer);
|
||||
for (i=0;i<nof_ports;i++) {
|
||||
free(ce[i]);
|
||||
}
|
||||
free(idx_v);
|
||||
free(idx_valid);
|
||||
free(t);
|
||||
free(cfo_v);
|
||||
free(p2a_v);
|
||||
}
|
||||
|
||||
float mean_valid(int *idx_v, float *x, int nof_frames) {
|
||||
int i;
|
||||
float mean = 0;
|
||||
int n = 0;
|
||||
for (i=0;i<nof_frames;i++) {
|
||||
if (idx_v[i] != -1) {
|
||||
mean += x[i];
|
||||
n++;
|
||||
}
|
||||
}
|
||||
if (n > 0) {
|
||||
return mean/n;
|
||||
} else {
|
||||
return 0.0;
|
||||
}
|
||||
}
|
||||
|
||||
int preprocess_idx(int *in, int *out, int *period, int len) {
|
||||
int i, n;
|
||||
n=0;
|
||||
for (i=0;i<len;i++) {
|
||||
if (in[i] != -1) {
|
||||
out[n] = in[i];
|
||||
period[n] = i;
|
||||
n++;
|
||||
}
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
int rssi_scan() {
|
||||
int n=0;
|
||||
int i;
|
||||
|
||||
if (nof_bands > 100) {
|
||||
/* scan every Mhz, that is 10 freqs */
|
||||
for (i=0;i<nof_bands;i+=RSSI_DECIM) {
|
||||
freqs[n] = channels[i].fd * MHZ;
|
||||
n++;
|
||||
}
|
||||
#ifndef DISABLE_UHD
|
||||
if (uhd_rssi_scan(uhd, freqs, rssi_d, n, (double) RSSI_FS, nof_samples_rssi)) {
|
||||
fprintf(stderr, "Error while doing RSSI scan\n");
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
/* linearly interpolate the rssi vector */
|
||||
interp_linear_f(rssi_d, rssi, RSSI_DECIM, n);
|
||||
} else {
|
||||
for (i=0;i<nof_bands;i++) {
|
||||
freqs[i] = channels[i].fd * MHZ;
|
||||
}
|
||||
#ifndef DISABLE_UHD
|
||||
if (uhd_rssi_scan(uhd, freqs, rssi, nof_bands, (double) RSSI_FS, nof_samples_rssi)) {
|
||||
fprintf(stderr, "Error while doing RSSI scan\n");
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
n = nof_bands;
|
||||
}
|
||||
|
||||
return n;
|
||||
}
|
||||
|
||||
|
||||
int mib_decoder_init(int cell_id) {
|
||||
|
||||
if (chest_ref_LTEDL(&chest, cell_id)) {
|
||||
fprintf(stderr, "Error initializing reference signal\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (pbch_init(&pbch, cell_id, CPNORM)) {
|
||||
fprintf(stderr, "Error initiating PBCH\n");
|
||||
return -1;
|
||||
}
|
||||
DEBUG("PBCH initiated cell_id=%d\n", cell_id);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int mib_decoder_run(cf_t *input, pbch_mib_t *mib) {
|
||||
int i;
|
||||
lte_fft_run(&fft, input, fft_buffer);
|
||||
|
||||
/* Get channel estimates for each port */
|
||||
for (i=0;i<nof_ports;i++) {
|
||||
chest_ce_slot_port(&chest, fft_buffer, ce[i], 1, 0);
|
||||
}
|
||||
|
||||
DEBUG("Decoding PBCH\n", 0);
|
||||
return pbch_decode(&pbch, fft_buffer, ce, nof_ports, 6, 1, mib);
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
int frame_cnt, valid_frames;
|
||||
int freq;
|
||||
int cell_id;
|
||||
float max_peak_to_avg;
|
||||
float sfo;
|
||||
int find_idx, track_idx, last_found;
|
||||
enum sync_state state;
|
||||
int n;
|
||||
int mib_attempts;
|
||||
int nslot;
|
||||
pbch_mib_t mib;
|
||||
|
||||
if (argc < 3) {
|
||||
usage(argv[0]);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
parse_args(argc,argv);
|
||||
|
||||
if (base_init(FLEN)) {
|
||||
fprintf(stderr, "Error initializing memory\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
sync_pss_det_peakmean(&sfind);
|
||||
sync_pss_det_peakmean(&strack);
|
||||
|
||||
nof_bands = lte_band_get_fd_band(band, channels, earfcn_start, earfcn_end, MAX_EARFCN);
|
||||
printf("RSSI scan: %d freqs in band %d, RSSI threshold %.2f dBm\n", nof_bands, band, rssi_threshold);
|
||||
|
||||
n = rssi_scan();
|
||||
if (n == -1) {
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
printf("\nDone. Starting PSS search on %d channels\n", n);
|
||||
usleep(500000);
|
||||
INFO("Setting sampling frequency %.2f MHz\n", (float) SAMP_FREQ/MHZ);
|
||||
#ifndef DISABLE_UHD
|
||||
uhd_set_rx_srate(uhd, SAMP_FREQ);
|
||||
|
||||
uhd_set_rx_gain(uhd, gain);
|
||||
#endif
|
||||
|
||||
print_to_matlab();
|
||||
|
||||
freq=0;
|
||||
state = INIT;
|
||||
nslot = 0;
|
||||
sfo = 0;
|
||||
find_idx = 0;
|
||||
frame_cnt = 0;
|
||||
while(freq<nof_bands) {
|
||||
/* scan only bands above rssi_threshold */
|
||||
if (!IS_SIGNAL(freq)) {
|
||||
INFO("[%3d/%d]: Skipping EARFCN %d %.2f MHz RSSI %.2f dB\n", freq, nof_bands,
|
||||
channels[freq].id, channels[freq].fd,10*log10f(rssi[freq]) + 30);
|
||||
freq++;
|
||||
} else {
|
||||
if (state != INIT && state != DONE) {
|
||||
#ifndef DISABLE_UHD
|
||||
uhd_recv(uhd, &input_buffer[FLEN], FLEN, 1);
|
||||
#endif
|
||||
}
|
||||
switch(state) {
|
||||
case INIT:
|
||||
DEBUG("Stopping receiver...\n",0);
|
||||
#ifndef DISABLE_UHD
|
||||
uhd_stop_rx_stream(uhd);
|
||||
|
||||
/* set freq */
|
||||
uhd_set_rx_freq(uhd, (double) channels[freq].fd * MHZ);
|
||||
uhd_rx_wait_lo_locked(uhd);
|
||||
DEBUG("Set freq to %.3f MHz\n", (double) channels[freq].fd);
|
||||
|
||||
DEBUG("Starting receiver...\n",0);
|
||||
uhd_start_rx_stream(uhd);
|
||||
#endif
|
||||
/* init variables */
|
||||
frame_cnt = 0;
|
||||
max_peak_to_avg = -99;
|
||||
cell_id = -1;
|
||||
|
||||
/* receive first frame */
|
||||
#ifndef DISABLE_UHD
|
||||
uhd_recv(uhd, input_buffer, FLEN, 1);
|
||||
#endif
|
||||
/* set find_threshold and go to FIND state */
|
||||
sync_set_threshold(&sfind, find_threshold);
|
||||
sync_force_N_id_2(&sfind, -1);
|
||||
state = FIND;
|
||||
break;
|
||||
case FIND:
|
||||
/* find peak in all frame */
|
||||
find_idx = sync_run(&sfind, input_buffer, FLEN);
|
||||
DEBUG("[%3d/%d]: PAR=%.2f\n", freq, nof_bands, sync_get_peak_to_avg(&sfind));
|
||||
if (find_idx != -1) {
|
||||
/* if found peak, go to track and set lower threshold */
|
||||
frame_cnt = -1;
|
||||
last_found = 0;
|
||||
max_peak_to_avg = -1;
|
||||
sync_set_threshold(&strack, track_threshold);
|
||||
sync_force_N_id_2(&strack, sync_get_N_id_2(&sfind));
|
||||
cell_id = sync_get_cell_id(&strack);
|
||||
mib_decoder_init(cell_id);
|
||||
|
||||
state = TRACK;
|
||||
INFO("[%3d/%d]: EARFCN %d Freq. %.2f MHz PSS found PAR %.2f dB\n", freq, nof_bands,
|
||||
channels[freq].id, channels[freq].fd,
|
||||
10*log10f(sync_get_peak_to_avg(&sfind)));
|
||||
} else {
|
||||
if (frame_cnt >= nof_frames_find) {
|
||||
state = INIT;
|
||||
freq++;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case TRACK:
|
||||
INFO("Tracking PSS find_idx %d offset %d\n", find_idx, find_idx + track_len);
|
||||
|
||||
track_idx = sync_run(&strack, input_buffer, FLEN + find_idx - track_len);
|
||||
p2a_v[frame_cnt] = sync_get_peak_to_avg(&strack);
|
||||
|
||||
/* save cell id for the best peak-to-avg */
|
||||
if (p2a_v[frame_cnt] > max_peak_to_avg) {
|
||||
max_peak_to_avg = p2a_v[frame_cnt];
|
||||
cell_id = sync_get_cell_id(&strack);
|
||||
}
|
||||
if (track_idx != -1) {
|
||||
cfo_v[frame_cnt] = sync_get_cfo(&strack);
|
||||
last_found = frame_cnt;
|
||||
find_idx += track_idx - track_len;
|
||||
idx_v[frame_cnt] = find_idx;
|
||||
nslot = sync_get_slot_id(&strack);
|
||||
} else {
|
||||
idx_v[frame_cnt] = -1;
|
||||
cfo_v[frame_cnt] = 0.0;
|
||||
}
|
||||
/* if we missed to many PSS it is not a cell, next freq */
|
||||
if (frame_cnt - last_found > max_track_lost) {
|
||||
INFO("\n[%3d/%d]: EARFCN %d Freq. %.2f MHz %d frames lost\n", freq, nof_bands,
|
||||
channels[freq].id, channels[freq].fd, frame_cnt - last_found);
|
||||
|
||||
state = INIT;
|
||||
freq++;
|
||||
} else if (frame_cnt >= nof_frames_track) {
|
||||
state = MIB;
|
||||
nslot=(nslot+10)%20;
|
||||
}
|
||||
break;
|
||||
case MIB:
|
||||
INFO("Finding MIB at freq %.2f Mhz\n", channels[freq].fd);
|
||||
cfo[freq] = mean_valid(idx_v, cfo_v, frame_cnt);
|
||||
p2a[freq] = mean_valid(idx_v, p2a_v, frame_cnt);
|
||||
valid_frames = preprocess_idx(idx_v, idx_valid, t, frame_cnt);
|
||||
sfo = sfo_estimate_period(idx_valid, t, valid_frames, FLEN_PERIOD);
|
||||
|
||||
// TODO: Correct SFO
|
||||
|
||||
// Correct CFO
|
||||
INFO("Correcting CFO=%.4f\n", cfo[freq]);
|
||||
nco_cexp_f_direct(&input_buffer[FLEN], -cfo[freq]/128, FLEN);
|
||||
|
||||
if (nslot == 10) {
|
||||
if (mib_decoder_run(&input_buffer[FLEN+find_idx+FLEN/10], &mib)) {
|
||||
INFO("MIB detected attempt=%d\n", mib_attempts);
|
||||
state = DONE;
|
||||
} else {
|
||||
INFO("MIB not detected attempt=%d\n", mib_attempts);
|
||||
if (mib_attempts >= 20) {
|
||||
freq++;
|
||||
state = INIT;
|
||||
}
|
||||
}
|
||||
mib_attempts++;
|
||||
} else {
|
||||
nslot = (nslot+10)%20;
|
||||
}
|
||||
|
||||
break;
|
||||
case DONE:
|
||||
printf("\n[%3d/%d]: FOUND EARFCN %d Freq. %.2f MHz. "
|
||||
"PAR %2.2f dB, CFO=%+.2f KHz, SFO=%+2.3f KHz, CELL_ID=%3d\n", freq, nof_bands,
|
||||
channels[freq].id, channels[freq].fd,
|
||||
10*log10f(p2a[freq]), cfo[freq] * 15, sfo / 1000, cell_id);
|
||||
pbch_mib_fprint(stdout, &mib);
|
||||
state = INIT;
|
||||
freq++;
|
||||
break;
|
||||
}
|
||||
|
||||
/** FIXME: This is not necessary at all */
|
||||
if (state == TRACK || (state == FIND && frame_cnt)) {
|
||||
memcpy(input_buffer, &input_buffer[FLEN], FLEN * sizeof(cf_t));
|
||||
}
|
||||
frame_cnt++;
|
||||
}
|
||||
}
|
||||
|
||||
print_to_matlab();
|
||||
|
||||
base_free();
|
||||
|
||||
printf("\n\nDone\n");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
void print_to_matlab() {
|
||||
int i;
|
||||
|
||||
FILE *f = fopen("output.m", "w");
|
||||
if (!f) {
|
||||
perror("fopen");
|
||||
exit(-1);
|
||||
}
|
||||
fprintf(f, "fd=[");
|
||||
for (i=0;i<nof_bands;i++) {
|
||||
fprintf(f, "%g, ", channels[i].fd);
|
||||
}
|
||||
fprintf(f, "];\n");
|
||||
|
||||
fprintf(f, "rssi=[");
|
||||
for (i=0;i<nof_bands;i++) {
|
||||
fprintf(f, "%g, ", rssi[i]);
|
||||
}
|
||||
fprintf(f, "];\n");
|
||||
|
||||
|
||||
fprintf(f, "rssi_d=[");
|
||||
for (i=0;i<nof_bands/RSSI_DECIM;i++) {
|
||||
fprintf(f, "%g, ", rssi_d[i]);
|
||||
}
|
||||
fprintf(f, "];\n");
|
||||
|
||||
/*
|
||||
fprintf(f, "cfo=[");
|
||||
for (i=0;i<nof_bands;i++) {
|
||||
if (IS_SIGNAL(i)) {
|
||||
fprintf(f, "%g, ", cfo[i]);
|
||||
} else {
|
||||
fprintf(f, "NaN, ");
|
||||
}
|
||||
}
|
||||
fprintf(f, "];\n");
|
||||
*/
|
||||
fprintf(f, "p2a=[");
|
||||
for (i=0;i<nof_bands;i++) {
|
||||
if (IS_SIGNAL(i)) {
|
||||
fprintf(f, "%g, ", p2a[i]);
|
||||
} else {
|
||||
fprintf(f, "0, ");
|
||||
}
|
||||
}
|
||||
fprintf(f, "];\n");
|
||||
fprintf(f, "clf;\n\n");
|
||||
fprintf(f, "subplot(1,2,1)\n");
|
||||
fprintf(f, "plot(fd, 10*log10(rssi)+30)\n");
|
||||
fprintf(f, "grid on; xlabel('f [Mhz]'); ylabel('RSSI [dBm]');\n");
|
||||
fprintf(f, "title('RSSI Estimation')\n");
|
||||
|
||||
fprintf(f, "subplot(1,2,2)\n");
|
||||
fprintf(f, "plot(fd, p2a)\n");
|
||||
fprintf(f, "grid on; xlabel('f [Mhz]'); ylabel('Peak-to-Avg [dB]');\n");
|
||||
fprintf(f, "title('PSS Correlation')\n");
|
||||
/*
|
||||
fprintf(f, "subplot(1,3,3)\n");
|
||||
fprintf(f, "plot(fd, cfo)\n");
|
||||
fprintf(f, "grid on; xlabel('f [Mhz]'); ylabel(''); axis([min(fd) max(fd) -0.5 0.5]);\n");
|
||||
fprintf(f, "title('CFO Estimation')\n");
|
||||
*/
|
||||
fprintf(f, "drawnow;\n");
|
||||
fclose(f);
|
||||
}
|
|
@ -286,6 +286,10 @@ int main(int argc, char **argv) {
|
|||
|
||||
freq=0;
|
||||
state = INIT;
|
||||
find_idx = 0;
|
||||
max_peak_to_avg = 0;
|
||||
last_found = 0;
|
||||
frame_cnt = 0;
|
||||
while(freq<nof_bands) {
|
||||
/* scan only bands above rssi_threshold */
|
||||
if (!IS_SIGNAL(freq)) {
|
||||
|
|
|
@ -107,7 +107,7 @@ int main(int argc, char **argv) {
|
|||
rssi[i]=0;
|
||||
while(frame_cnt < nof_slots) {
|
||||
nsamples += uhd_recv(uhd, input_buffer, 1920, 1);
|
||||
rssi[i] += vec_power(input_buffer, 1920);
|
||||
rssi[i] += vec_avg_power_cf(input_buffer, 1920);
|
||||
frame_cnt++;
|
||||
}
|
||||
printf("[%3d/%d]: Scanning earfcn %d freq %.2f MHz RSSI %.2f dBm\n", i, nof_bands,
|
||||
|
|
|
@ -123,7 +123,7 @@ int main(int argc, char **argv) {
|
|||
demod_soft_alg_set(&demod, APPROX);
|
||||
demod_soft_sigma_set(&demod, var);
|
||||
|
||||
viterbi_init(&dec, CONVCODER_37, cod.poly, frame_length, tail_biting);
|
||||
viterbi_init(&dec, viterbi_37, cod.poly, frame_length, tail_biting);
|
||||
|
||||
/* read all file or nof_frames */
|
||||
frame_cnt = 0;
|
||||
|
@ -135,7 +135,7 @@ int main(int argc, char **argv) {
|
|||
data_tx[i] = message[i];
|
||||
}
|
||||
|
||||
conv_encode(&cod, data_tx, symbols);
|
||||
convcoder_encode(&cod, data_tx, symbols);
|
||||
|
||||
bit_fprint(stdout, symbols, 120);
|
||||
|
||||
|
|
|
@ -27,6 +27,9 @@
|
|||
|
||||
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);
|
||||
|
||||
/** This is an OFDM channel estimator.
|
||||
* It works with any reference signal pattern, provided by the object
|
||||
* refsignal_t
|
||||
|
@ -41,9 +44,10 @@ typedef struct {
|
|||
int nof_prb;
|
||||
lte_cp_t cp;
|
||||
refsignal_t refsignal[MAX_PORTS][NSLOTS_X_FRAME];
|
||||
interpolate_fnc_t interp;
|
||||
}chest_t;
|
||||
|
||||
int chest_init(chest_t *q, lte_cp_t cp, int nof_prb, int nof_ports);
|
||||
int chest_init(chest_t *q, chest_interp_t interp, lte_cp_t cp, int nof_prb, int nof_ports);
|
||||
void chest_free(chest_t *q);
|
||||
|
||||
int chest_ref_LTEDL_slot_port(chest_t *q, int port, int nslot, int cell_id);
|
||||
|
@ -68,20 +72,18 @@ typedef struct {
|
|||
chest_t obj;
|
||||
struct chest_init {
|
||||
int nof_symbols; // 7 for normal cp, 6 for extended
|
||||
int port_id;
|
||||
int nof_ports;
|
||||
int cell_id;
|
||||
int nof_prb;
|
||||
int ntime;
|
||||
int nfreq;
|
||||
int cell_id; // set to -1 to init at runtime
|
||||
} init;
|
||||
cf_t *input;
|
||||
int in_len;
|
||||
struct chest_ctrl_in {
|
||||
int slot_id; // slot id in the 10ms frame
|
||||
int cell_id;
|
||||
} ctrl_in;
|
||||
cf_t *output;
|
||||
int *out_len;
|
||||
cf_t *output[MAX_PORTS];
|
||||
int out_len[MAX_PORTS];
|
||||
}chest_hl;
|
||||
|
||||
#define DEFAULT_FRAME_SIZE 2048
|
||||
|
|
|
@ -34,10 +34,11 @@ typedef struct {
|
|||
} ctrl_in;
|
||||
|
||||
cf* output;
|
||||
int* out_len;
|
||||
int out_len;
|
||||
}ch_awgn_hl;
|
||||
|
||||
int ch_awgn_initialize(ch_awgn_hl* hl);
|
||||
int ch_awgn_work(ch_awgn_hl* hl);
|
||||
int ch_awgn_stop(ch_awgn_hl* hl);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -19,27 +19,9 @@
|
|||
#ifndef CONVCODER_
|
||||
#define CONVCODER_
|
||||
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
typedef enum {
|
||||
CONVCODER_27, CONVCODER_29, CONVCODER_37, CONVCODER_39
|
||||
}viterbi_type_t;
|
||||
|
||||
typedef struct {
|
||||
void *ptr;
|
||||
int R;
|
||||
int K;
|
||||
unsigned int framebits;
|
||||
bool tail_biting;
|
||||
int poly[3];
|
||||
int (*decode) (void*, float*, char*);
|
||||
void (*free) (void*);
|
||||
}viterbi_t;
|
||||
|
||||
int viterbi_init(viterbi_t *q, viterbi_type_t type, int poly[3], int framebits, bool tail_bitting);
|
||||
void viterbi_free(viterbi_t *q);
|
||||
int viterbi_decode(viterbi_t *q, float *symbols, char *data);
|
||||
|
||||
typedef struct {
|
||||
int R;
|
||||
|
@ -49,6 +31,29 @@ typedef struct {
|
|||
bool tail_biting;
|
||||
}convcoder_t;
|
||||
|
||||
int conv_encode(convcoder_t *q, char *input, char *output);
|
||||
int convcoder_encode(convcoder_t *q, char *input, char *output);
|
||||
|
||||
|
||||
/* High-level API */
|
||||
typedef struct {
|
||||
convcoder_t obj;
|
||||
struct convcoder_ctrl_in {
|
||||
int rate;
|
||||
int constraint_length;
|
||||
int tail_bitting;
|
||||
int generator_0;
|
||||
int generator_1;
|
||||
int generator_2;
|
||||
int frame_length;
|
||||
} ctrl_in;
|
||||
char *input;
|
||||
int in_len;
|
||||
char *output;
|
||||
int out_len;
|
||||
}convcoder_hl;
|
||||
|
||||
int convcoder_initialize(convcoder_hl* h);
|
||||
int convcoder_work(convcoder_hl* hl);
|
||||
int convcoder_stop(convcoder_hl* h);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -0,0 +1,66 @@
|
|||
/*
|
||||
* Copyright (c) 2013, Ismael Gomez-Miguelez <gomezi@tcd.ie>.
|
||||
* This file is part of OSLD-lib (http://https://github.com/ismagom/osld-lib)
|
||||
*
|
||||
* OSLD-lib is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* OSLD-lib is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with OSLD-lib. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef VITERBI_
|
||||
#define VITERBI_
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
typedef enum {
|
||||
viterbi_27, viterbi_29, viterbi_37, viterbi_39
|
||||
}viterbi_type_t;
|
||||
|
||||
typedef struct {
|
||||
void *ptr;
|
||||
int R;
|
||||
int K;
|
||||
unsigned int framebits;
|
||||
bool tail_biting;
|
||||
int poly[3];
|
||||
int (*decode) (void*, float*, char*);
|
||||
void (*free) (void*);
|
||||
}viterbi_t;
|
||||
|
||||
int viterbi_init(viterbi_t *q, viterbi_type_t type, int poly[3], int framebits, bool tail_bitting);
|
||||
void viterbi_free(viterbi_t *q);
|
||||
int viterbi_decode(viterbi_t *q, float *symbols, char *data);
|
||||
|
||||
|
||||
/* High-level API */
|
||||
typedef struct {
|
||||
viterbi_t obj;
|
||||
struct viterbi_init {
|
||||
int rate;
|
||||
int constraint_length;
|
||||
int tail_bitting;
|
||||
int generator_0;
|
||||
int generator_1;
|
||||
int generator_2;
|
||||
int frame_length;
|
||||
} init;
|
||||
float *input;
|
||||
int in_len;
|
||||
char *output;
|
||||
int out_len;
|
||||
}viterbi_hl;
|
||||
|
||||
int viterbi_initialize(viterbi_hl* h);
|
||||
int viterbi_work(viterbi_hl* hl);
|
||||
int viterbi_stop(viterbi_hl* h);
|
||||
|
||||
#endif
|
|
@ -50,7 +50,7 @@ typedef struct {
|
|||
int nbits; // Number of bits to generate
|
||||
} ctrl_in;
|
||||
char* output;
|
||||
int* out_len;
|
||||
int out_len;
|
||||
}binsource_hl;
|
||||
|
||||
int binsource_initialize(binsource_hl* h);
|
||||
|
|
|
@ -48,7 +48,7 @@ typedef struct {
|
|||
int nsamples; // Number of samples to read
|
||||
} ctrl_in;
|
||||
void* output;
|
||||
int* out_len;
|
||||
int out_len;
|
||||
}filesource_hl;
|
||||
|
||||
int filesource_initialize(filesource_hl* h);
|
||||
|
|
|
@ -41,6 +41,7 @@
|
|||
|
||||
#include "channel/ch_awgn.h"
|
||||
|
||||
#include "fec/viterbi.h"
|
||||
#include "fec/convcoder.h"
|
||||
#include "fec/crc.h"
|
||||
|
||||
|
|
|
@ -48,11 +48,12 @@ typedef struct {
|
|||
int in_len;
|
||||
|
||||
char* output;
|
||||
int *out_len;
|
||||
int out_len;
|
||||
}demod_hard_hl;
|
||||
|
||||
int demod_hard_initialize(demod_hard_hl* hl);
|
||||
int demod_hard_work(demod_hard_hl* hl);
|
||||
int demod_hard_stop(demod_hard_hl* hl);
|
||||
|
||||
|
||||
#endif
|
||||
|
|
|
@ -57,7 +57,7 @@ typedef struct {
|
|||
}ctrl_in;
|
||||
|
||||
float* output;
|
||||
int *out_len;
|
||||
int out_len;
|
||||
|
||||
}demod_soft_hl;
|
||||
|
||||
|
|
|
@ -39,7 +39,7 @@ typedef struct {
|
|||
int in_len;
|
||||
|
||||
cf* output;
|
||||
int *out_len;
|
||||
int out_len;
|
||||
}mod_hl;
|
||||
|
||||
int mod_initialize(mod_hl* hl);
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
#include "scrambling/scrambling.h"
|
||||
#include "ratematching/rm_conv.h"
|
||||
#include "fec/convcoder.h"
|
||||
#include "fec/viterbi.h"
|
||||
#include "fec/crc.h"
|
||||
|
||||
#define PBCH_RE_CPNORM 240
|
||||
|
|
|
@ -36,7 +36,7 @@ typedef struct {
|
|||
int S;
|
||||
} ctrl_in;
|
||||
void *output;
|
||||
int *out_len;
|
||||
int out_len;
|
||||
}rm_conv_hl;
|
||||
|
||||
int rm_conv_initialize(rm_conv_hl* h);
|
||||
|
|
|
@ -59,7 +59,7 @@ typedef struct {
|
|||
int subframe;
|
||||
} ctrl_in;
|
||||
void *output;
|
||||
int *out_len;
|
||||
int out_len;
|
||||
}scrambling_hl;
|
||||
|
||||
#endif
|
||||
|
|
|
@ -114,7 +114,7 @@ typedef struct {
|
|||
float manual_cfo;
|
||||
} ctrl_in;
|
||||
cf_t *output;
|
||||
int *out_len;
|
||||
int out_len;
|
||||
}pss_synch_hl;
|
||||
|
||||
#define DEFAULT_FRAME_SIZE 2048
|
||||
|
|
|
@ -21,24 +21,42 @@
|
|||
|
||||
#include <stdio.h>
|
||||
|
||||
int sum_i(int *x, int len);
|
||||
float sum_r(float *x, int len);
|
||||
_Complex float sum_c(_Complex float *x, int len);
|
||||
typedef _Complex float cf_t;
|
||||
|
||||
/** Return the sum of all the elements */
|
||||
int vec_acc_ii(int *x, int len);
|
||||
float vec_acc_ff(float *x, int len);
|
||||
cf_t vec_acc_cc(cf_t *x, int len);
|
||||
|
||||
void *vec_malloc(int size);
|
||||
void vec_fprint_c(FILE *stream, _Complex float *x, int len);
|
||||
|
||||
/* print vectors */
|
||||
void vec_fprint_c(FILE *stream, cf_t *x, int len);
|
||||
void vec_fprint_f(FILE *stream, float *x, int len);
|
||||
void vec_fprint_i(FILE *stream, int *x, int len);
|
||||
|
||||
/* sum two vectors */
|
||||
void vec_sum_ch(char *z, char *x, char *y, int len);
|
||||
void vec_sum_c(_Complex float *z, _Complex float *x, _Complex float *y, int len);
|
||||
void vec_mult_c_r(_Complex float *x,_Complex float *y, float h, int len);
|
||||
void vec_mult_c(_Complex float *x,_Complex float *y, _Complex float h, int len);
|
||||
void vec_conj(_Complex float *x, _Complex float *y, int len);
|
||||
float vec_power(_Complex float *x, int len);
|
||||
void vec_dot_prod(_Complex float *x,_Complex float *y, _Complex float *z, int len);
|
||||
void vec_dot_prod_u(_Complex float *x,_Complex float *y, _Complex float *z, int len);
|
||||
void vec_max(float *x, float *max, int *pos, int len);
|
||||
void vec_abs(_Complex float *x, float *abs, int len);
|
||||
void vec_sum_ccc(cf_t *z, cf_t *x, cf_t *y, int len);
|
||||
|
||||
/* scalar product */
|
||||
void vec_sc_prod_cfc(cf_t *x, float h, cf_t *z, int len);
|
||||
void vec_sc_prod_ccc(cf_t *x, cf_t h, cf_t *z, int len);
|
||||
|
||||
/* dot product */
|
||||
void vec_dot_prod_ccc(cf_t *x, cf_t *y, cf_t *z, int len);
|
||||
void vec_dot_prod_ccc_unalign(cf_t *x, cf_t *y, cf_t *z, int len);
|
||||
|
||||
/* conjugate */
|
||||
void vec_conj_cc(cf_t *x, cf_t *y, int len);
|
||||
|
||||
/* average vector power */
|
||||
float vec_avg_power_cf(cf_t *x, int len);
|
||||
|
||||
/* return the index of the maximum value in the vector */
|
||||
int vec_max_fi(float *x, int len);
|
||||
|
||||
/* magnitude of each vector element */
|
||||
void vec_abs_cf(cf_t *x, float *abs, int len);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -80,8 +80,8 @@ void chest_ce_ref(chest_t *q, cf_t *input, int nslot, int port_id, int nref) {
|
|||
channel_ref = input[SAMPLE_IDX(q->nof_prb, tidx, fidx)];
|
||||
q->refsignal[port_id][nslot].refs[nref].recv_simbol = channel_ref;
|
||||
|
||||
DEBUG("Reference %d pos (%d,%d)=%d %.2f/%.2f=%.2f %.2f/%.2f=%.2f\n", nref, tidx, fidx, SAMPLE_IDX(q->nof_prb, tidx, fidx),
|
||||
cabsf(channel_ref),cabsf(known_ref),cabsf(channel_ref/known_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 treshold */
|
||||
if (channel_ref != 0) {
|
||||
|
@ -141,7 +141,7 @@ void chest_ce_slot(chest_t *q, cf_t *input, cf_t **ce, int nslot) {
|
|||
}
|
||||
}
|
||||
|
||||
int chest_init(chest_t *q, lte_cp_t cp, int nof_prb, int nof_ports) {
|
||||
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);
|
||||
|
@ -154,6 +154,11 @@ int chest_init(chest_t *q, lte_cp_t cp, int nof_prb, int nof_ports) {
|
|||
q->cp = cp;
|
||||
q->nof_prb = nof_prb;
|
||||
|
||||
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);
|
||||
|
||||
|
@ -222,50 +227,45 @@ int chest_ref_symbols(chest_t *q, int port_id, int nslot, int l[2]) {
|
|||
*/
|
||||
int chest_initialize(chest_hl* h) {
|
||||
|
||||
if (!h->init.ntime) {
|
||||
h->init.ntime = 7;
|
||||
}
|
||||
if (!h->init.nfreq) {
|
||||
h->init.nfreq = 10;
|
||||
}
|
||||
if (!h->init.nof_symbols) {
|
||||
h->init.nof_symbols = CPNORM_NSYMB; // Normal CP
|
||||
}
|
||||
if (!h->init.port_id) {
|
||||
h->init.port_id = 0;
|
||||
}
|
||||
if (!h->init.cell_id) {
|
||||
h->init.cell_id = 0;
|
||||
}
|
||||
if (!h->init.nof_prb) {
|
||||
h->init.nof_prb = 6;
|
||||
}
|
||||
|
||||
/* if (chest_LTEDL_init(&h->obj, h->init.ntime, h->init.nfreq,
|
||||
h->init.nof_symbols==CPNORM_NSYMB, h->init.cell_id, h->init.nof_prb)) {
|
||||
if (chest_init(&h->obj, LINEAR, (h->init.nof_symbols==CPNORM_NSYMB)?CPNORM:CPEXT,
|
||||
h->init.nof_prb, h->init.nof_ports)) {
|
||||
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 can be called in a subframe (1ms) or slot basis (0.5ms) for LTE */
|
||||
/** This function must be called in an slot basis (0.5ms) for LTE */
|
||||
int chest_work(chest_hl* hl) {
|
||||
int i;
|
||||
chest_t *q = &hl->obj;
|
||||
/*
|
||||
if (hl->in_len == SF_SZ(q)) {
|
||||
*hl->out_len = chest_LTEDL_run_sf(q, hl->input, hl->output, hl->ctrl_in.slot_id/2);
|
||||
} else if (hl->in_len == SLOT_SZ(q)) {
|
||||
*hl->out_len = chest_LTEDL_run_slot(q, hl->input, hl->output, hl->ctrl_in.slot_id);
|
||||
}
|
||||
*/
|
||||
|
||||
if (*hl->out_len < 0) {
|
||||
return -1;
|
||||
} else {
|
||||
return 0;
|
||||
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;i<hl->init.nof_ports;i++) {
|
||||
chest_ce_slot_port(q, hl->input, hl->output[i], 1, 0);
|
||||
hl->out_len[i] = hl->in_len;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int chest_stop(chest_hl* hl) {
|
||||
|
|
|
@ -43,8 +43,10 @@ int ch_awgn_initialize(ch_awgn_hl* hl) {
|
|||
|
||||
int ch_awgn_work(ch_awgn_hl* hl) {
|
||||
ch_awgn(hl->input,hl->output,hl->ctrl_in.variance,hl->in_len);
|
||||
if (hl->out_len) {
|
||||
*hl->out_len = hl->in_len;
|
||||
}
|
||||
hl->out_len = hl->in_len;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ch_awgn_stop(ch_awgn_hl* hl) {
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -16,85 +16,14 @@
|
|||
* along with OSLD-lib. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/**@TODO frontend to FEC library if installed
|
||||
*/
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "fec/convcoder.h"
|
||||
#include "parity.h"
|
||||
#include "viterbi37.h"
|
||||
|
||||
#define DEB 0
|
||||
|
||||
int decode37(void *o, float *symbols, char *data) {
|
||||
viterbi_t *q = o;
|
||||
int i;
|
||||
int len = q->tail_biting ? q->framebits : (q->framebits + q->K - 1);
|
||||
float amp = 0;
|
||||
|
||||
for (i=0;i<3*len;i++) {
|
||||
if (fabsf(symbols[i] > amp)) {
|
||||
amp = symbols[i];
|
||||
}
|
||||
}
|
||||
|
||||
/* Decode it and make sure we get the right answer */
|
||||
/* Initialize Viterbi decoder */
|
||||
init_viterbi37_port(q->ptr, q->tail_biting?-1:0);
|
||||
|
||||
/* Decode block */
|
||||
update_viterbi37_blk_port(q->ptr, symbols,q->framebits + q->K - 1, amp, len);
|
||||
|
||||
/* Do Viterbi chainback */
|
||||
chainback_viterbi37_port(q->ptr, data, q->framebits, 0);
|
||||
|
||||
return q->framebits;
|
||||
}
|
||||
|
||||
void free37(void *o) {
|
||||
viterbi_t *q = o;
|
||||
delete_viterbi37_port(q->ptr);
|
||||
}
|
||||
|
||||
int init37(viterbi_t *q, int poly[3], int framebits, bool tail_biting) {
|
||||
q->K = 7;
|
||||
q->R = 3;
|
||||
q->framebits = framebits;
|
||||
q->tail_biting = tail_biting;
|
||||
q->decode = decode37;
|
||||
q->free = free37;
|
||||
|
||||
if ((q->ptr = create_viterbi37_port(poly, framebits, tail_biting)) == NULL) {
|
||||
fprintf(stderr, "create_viterbi37 failed\n");
|
||||
return -1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int viterbi_init(viterbi_t *q, viterbi_type_t type, int poly[3], int framebits, bool tail_bitting) {
|
||||
switch(type) {
|
||||
case CONVCODER_37:
|
||||
return init37(q, poly, framebits, tail_bitting);
|
||||
default:
|
||||
fprintf(stderr, "Decoder not implemented\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
void viterbi_free(viterbi_t *q) {
|
||||
q->free(q);
|
||||
}
|
||||
|
||||
/* symbols are real-valued */
|
||||
int viterbi_decode(viterbi_t *q, float *symbols, char *data) {
|
||||
return q->decode(q, symbols, data);
|
||||
}
|
||||
|
||||
|
||||
int conv_encode(convcoder_t *q, char *input, char *output) {
|
||||
int convcoder_encode(convcoder_t *q, char *input, char *output) {
|
||||
unsigned int sr;
|
||||
int i,j;
|
||||
int len = q->tail_biting ? q->framelength : (q->framelength + q->K - 1);
|
||||
|
@ -102,24 +31,42 @@ int conv_encode(convcoder_t *q, char *input, char *output) {
|
|||
if (q->tail_biting) {
|
||||
sr = 0;
|
||||
for (i=q->framelength - q->K + 1; i<q->framelength; i++) {
|
||||
if (DEB) printf("%3d: sr=%3d, bit=%d\n",i,sr&7,input[i]);
|
||||
sr = (sr << 1) | (input[i] & 1);
|
||||
}
|
||||
} else {
|
||||
sr = 0;
|
||||
}
|
||||
|
||||
if (DEB) printf("state st=%d\n",sr&7);
|
||||
for (i = 0; i < len; i++) {
|
||||
int bit = (i < q->framelength) ? (input[i] & 1) : 0;
|
||||
sr = (sr << 1) | bit;
|
||||
if (DEB) printf("%d, ",input[i]);
|
||||
for (j=0;j<q->R;j++) {
|
||||
output[q->R * i + j] = parity(sr & q->poly[j]);
|
||||
}
|
||||
}
|
||||
if (DEB) printf("\n");
|
||||
if (DEB) printf("state fin=%u\n",sr&7);
|
||||
|
||||
return q->R*len;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int convcoder_initialize(convcoder_hl* h) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int convcoder_work(convcoder_hl* hl) {
|
||||
|
||||
hl->obj.K = hl->ctrl_in.constraint_length;
|
||||
hl->obj.R = hl->ctrl_in.rate;
|
||||
hl->obj.framelength = hl->in_len;
|
||||
hl->obj.poly[0] = hl->ctrl_in.generator_0;
|
||||
hl->obj.poly[1] = hl->ctrl_in.generator_1;
|
||||
hl->obj.poly[2] = hl->ctrl_in.generator_2;
|
||||
hl->obj.tail_biting = hl->ctrl_in.tail_bitting?true:false;
|
||||
hl->out_len = convcoder_encode(&hl->obj, hl->input, hl->output);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int convcoder_stop(convcoder_hl* h) {
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,144 @@
|
|||
/*
|
||||
* Copyright (c) 2013, Ismael Gomez-Miguelez <gomezi@tcd.ie>.
|
||||
* This file is part of OSLD-lib (http://https://github.com/ismagom/osld-lib)
|
||||
*
|
||||
* OSLD-lib is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* OSLD-lib is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with OSLD-lib. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/**@TODO frontend to FEC library if installed
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "fec/viterbi.h"
|
||||
#include "parity.h"
|
||||
#include "viterbi37.h"
|
||||
|
||||
#define DEB 0
|
||||
|
||||
int decode37(void *o, float *symbols, char *data) {
|
||||
viterbi_t *q = o;
|
||||
int i;
|
||||
int len = q->tail_biting ? q->framebits : (q->framebits + q->K - 1);
|
||||
float amp = 0;
|
||||
|
||||
for (i=0;i<3*len;i++) {
|
||||
if (fabsf(symbols[i] > amp)) {
|
||||
amp = symbols[i];
|
||||
}
|
||||
}
|
||||
|
||||
/* Decode it and make sure we get the right answer */
|
||||
/* Initialize Viterbi decoder */
|
||||
init_viterbi37_port(q->ptr, q->tail_biting?-1:0);
|
||||
|
||||
/* Decode block */
|
||||
update_viterbi37_blk_port(q->ptr, symbols,q->framebits + q->K - 1, amp, len);
|
||||
|
||||
/* Do Viterbi chainback */
|
||||
chainback_viterbi37_port(q->ptr, data, q->framebits, 0);
|
||||
|
||||
return q->framebits;
|
||||
}
|
||||
|
||||
void free37(void *o) {
|
||||
viterbi_t *q = o;
|
||||
delete_viterbi37_port(q->ptr);
|
||||
}
|
||||
|
||||
int init37(viterbi_t *q, int poly[3], int framebits, bool tail_biting) {
|
||||
q->K = 7;
|
||||
q->R = 3;
|
||||
q->framebits = framebits;
|
||||
q->tail_biting = tail_biting;
|
||||
q->decode = decode37;
|
||||
q->free = free37;
|
||||
|
||||
if ((q->ptr = create_viterbi37_port(poly, framebits, tail_biting)) == NULL) {
|
||||
fprintf(stderr, "create_viterbi37 failed\n");
|
||||
return -1;
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int viterbi_init(viterbi_t *q, viterbi_type_t type, int poly[3], int framebits, bool tail_bitting) {
|
||||
switch(type) {
|
||||
case viterbi_37:
|
||||
return init37(q, poly, framebits, tail_bitting);
|
||||
default:
|
||||
fprintf(stderr, "Decoder not implemented\n");
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
void viterbi_free(viterbi_t *q) {
|
||||
q->free(q);
|
||||
}
|
||||
|
||||
/* symbols are real-valued */
|
||||
int viterbi_decode(viterbi_t *q, float *symbols, char *data) {
|
||||
return q->decode(q, symbols, data);
|
||||
}
|
||||
|
||||
|
||||
int viterbi_initialize(viterbi_hl* h) {
|
||||
int poly[3];
|
||||
viterbi_type_t type;
|
||||
if (h->init.rate == 2) {
|
||||
if (h->init.constraint_length == 7) {
|
||||
type = viterbi_27;
|
||||
} else if (h->init.constraint_length == 9) {
|
||||
type = viterbi_29;
|
||||
} else {
|
||||
fprintf(stderr, "Unsupported decoder %d/%d\n", h->init.rate,
|
||||
h->init.constraint_length);
|
||||
return -1;
|
||||
}
|
||||
} else if (h->init.rate == 3) {
|
||||
if (h->init.constraint_length == 7) {
|
||||
type = viterbi_37;
|
||||
} else if (h->init.constraint_length == 9) {
|
||||
type = viterbi_39;
|
||||
} else {
|
||||
fprintf(stderr, "Unsupported decoder %d/%d\n", h->init.rate,
|
||||
h->init.constraint_length);
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
fprintf(stderr, "Unsupported decoder %d/%d\n", h->init.rate,
|
||||
h->init.constraint_length);
|
||||
return -1;
|
||||
}
|
||||
poly[0] = h->init.generator_0;
|
||||
poly[1] = h->init.generator_1;
|
||||
poly[2] = h->init.generator_2;
|
||||
return viterbi_init(&h->obj, type, poly, h->init.frame_length,
|
||||
h->init.tail_bitting?true:false);
|
||||
}
|
||||
|
||||
int viterbi_work(viterbi_hl* hl) {
|
||||
if (hl->in_len != hl->init.frame_length) {
|
||||
fprintf(stderr, "Expected input length %d but got %d\n", hl->init.frame_length, hl->in_len);
|
||||
return -1;
|
||||
}
|
||||
return viterbi_decode(&hl->obj, hl->input, hl->output);
|
||||
}
|
||||
|
||||
int viterbi_stop(viterbi_hl* h) {
|
||||
viterbi_free(&h->obj);
|
||||
return 0;
|
||||
}
|
|
@ -155,12 +155,10 @@ int binsource_work(binsource_hl* hl) {
|
|||
} else {
|
||||
ret = binsource_generate(&hl->obj,hl->output,hl->ctrl_in.nbits);
|
||||
}
|
||||
if (hl->out_len) {
|
||||
if (!ret) {
|
||||
*hl->out_len = hl->ctrl_in.nbits;
|
||||
} else {
|
||||
*hl->out_len = 0;
|
||||
}
|
||||
if (!ret) {
|
||||
hl->out_len = hl->ctrl_in.nbits;
|
||||
} else {
|
||||
hl->out_len = 0;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -92,8 +92,8 @@ int filesource_initialize(filesource_hl* h) {
|
|||
}
|
||||
|
||||
int filesource_work(filesource_hl* h) {
|
||||
*h->out_len = filesource_read(&h->obj, h->output, h->ctrl_in.nsamples);
|
||||
if (*h->out_len < 0) {
|
||||
h->out_len = filesource_read(&h->obj, h->output, h->ctrl_in.nsamples);
|
||||
if (h->out_len < 0) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
|
|
|
@ -65,11 +65,12 @@ int demod_hard_initialize(demod_hard_hl* hl) {
|
|||
|
||||
int demod_hard_work(demod_hard_hl* hl) {
|
||||
int ret = demod_hard_demodulate(&hl->obj,hl->input,hl->output,hl->in_len);
|
||||
if (hl->out_len) {
|
||||
*hl->out_len = ret;
|
||||
}
|
||||
hl->out_len = ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int demod_hard_stop(demod_hard_hl* hl) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -72,9 +72,7 @@ int demod_soft_work(demod_soft_hl* hl) {
|
|||
hl->obj.sigma = hl->ctrl_in.sigma;
|
||||
hl->obj.alg_type = hl->ctrl_in.alg_type;
|
||||
int ret = demod_soft_demodulate(&hl->obj,hl->input,hl->output,hl->in_len);
|
||||
if (hl->out_len) {
|
||||
*hl->out_len = ret;
|
||||
}
|
||||
hl->out_len = ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -49,9 +49,7 @@ int mod_initialize(mod_hl* hl) {
|
|||
|
||||
int mod_work(mod_hl* hl) {
|
||||
int ret = mod_modulate(&hl->obj,hl->input,hl->output,hl->in_len);
|
||||
if (hl->out_len) {
|
||||
*hl->out_len = ret;
|
||||
}
|
||||
hl->out_len = ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -137,7 +137,7 @@ int pbch_init(pbch_t *q, int cell_id, lte_cp_t cp) {
|
|||
}
|
||||
|
||||
int poly[3] = {0x6D, 0x4F, 0x57};
|
||||
if (viterbi_init(&q->decoder, CONVCODER_37, poly, 40, true)) {
|
||||
if (viterbi_init(&q->decoder, viterbi_37, poly, 40, true)) {
|
||||
goto clean;
|
||||
}
|
||||
int nof_symbols = (CP_ISNORM(q->cp)) ? PBCH_RE_CPNORM: PBCH_RE_CPEXT;
|
||||
|
@ -275,7 +275,7 @@ int pbch_decode_frame(pbch_t *q, pbch_mib_t *mib, int src, int dst, int n, int n
|
|||
}
|
||||
|
||||
/* unrate matching */
|
||||
rm_conv_rx(q->temp, q->pbch_rm, 4*nof_bits, 120);
|
||||
rm_conv_rx(q->temp, q->pbch_rm, 4 * nof_bits, 120);
|
||||
|
||||
/* decode */
|
||||
viterbi_decode(&q->decoder, q->pbch_rm, q->data);
|
||||
|
@ -324,15 +324,13 @@ int pbch_decode(pbch_t *q, cf_t *slot1_symbols, cf_t **ce, int nof_ports,
|
|||
/* Try decoding for 1 to nof_ports antennas */
|
||||
for (nant=0;nant<nof_ports;nant++) {
|
||||
|
||||
/* pre-decoder & matched filter */
|
||||
/*@TODO: pre-decoder & matched filter */
|
||||
int i;
|
||||
for (i=0;i<nof_symbols;i++) {
|
||||
q->pbch_symbols[i] /= ce[0][i];
|
||||
}
|
||||
|
||||
/* layer demapper */
|
||||
//x = lte_pre_decoder_and_matched_filter(y_est, ce(1:n,:), "tx_diversity");
|
||||
//d = lte_layer_demapper(x, 1, "tx_diversity");
|
||||
/*@TODO: layer demapping */
|
||||
|
||||
/* demodulate symbols */
|
||||
demod_soft_sigma_set(&q->demod, ebno);
|
||||
|
|
|
@ -102,10 +102,10 @@ int rm_conv_initialize(rm_conv_hl* h) {
|
|||
int rm_conv_work(rm_conv_hl* hl) {
|
||||
if (hl->init.direction) {
|
||||
//rm_conv_tx(hl->input, hl->output, hl->in_len, hl->ctrl_in.S);
|
||||
*(hl->out_len) = hl->ctrl_in.S;
|
||||
hl->out_len = hl->ctrl_in.S;
|
||||
} else {
|
||||
rm_conv_rx(hl->input, hl->output, hl->in_len, hl->ctrl_in.E);
|
||||
*(hl->out_len) = hl->ctrl_in.E;
|
||||
hl->out_len = hl->ctrl_in.E;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -41,15 +41,14 @@ void interp_linear_offset(cf_t *input, cf_t *output, int M, int len, int off_st,
|
|||
mag = mag0 + j*(mag1-mag0)/M;
|
||||
arg = arg0 + j*(arg1-arg0)/M;
|
||||
output[i*M+j+off_st] = mag * cexpf(I * arg);
|
||||
// DEBUG("output[%d] = input[%d]+%d*(input[%d]-input[%d])/%d = %.3f+%.3f = %.3f delta=%.3f\n",
|
||||
// i*M+j, i, j, i+1, i, M, cabsf(input[i]), cabsf(j*(input[i+1] - input[i])/M),
|
||||
// cabsf(output[i*M+j]));
|
||||
}
|
||||
}
|
||||
for (j=0;j<off_end;j++) {
|
||||
mag = mag1 + j*(mag1-mag0)/M;
|
||||
arg = arg1 + j*(arg1-arg0)/M;
|
||||
output[i*M+j+off_st] = mag * cexpf(I * arg);
|
||||
if (len > 1) {
|
||||
for (j=0;j<off_end;j++) {
|
||||
mag = mag1 + j*(mag1-mag0)/M;
|
||||
arg = arg1 + j*(arg1-arg0)/M;
|
||||
output[i*M+j+off_st] = mag * cexpf(I * arg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -100,7 +100,7 @@ int scrambling_work(scrambling_hl* hl) {
|
|||
memcpy(hl->output, hl->input, sizeof(float) * hl->in_len);
|
||||
scrambling_float(seq, hl->output);
|
||||
}
|
||||
*(hl->out_len) = hl->in_len;
|
||||
hl->out_len = hl->in_len;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -24,8 +24,8 @@
|
|||
cf_t corr_sz(cf_t *z, cf_t *s) {
|
||||
cf_t sum;
|
||||
cf_t zsprod[32];
|
||||
vec_dot_prod(z, s, zsprod, N_SSS - 1);
|
||||
sum = sum_c(zsprod, N_SSS - 1);
|
||||
vec_dot_prod_ccc(z, s, zsprod, N_SSS - 1);
|
||||
sum = vec_acc_cc(zsprod, N_SSS - 1);
|
||||
|
||||
return sum;
|
||||
}
|
||||
|
@ -66,24 +66,30 @@ void sss_synch_m0m1(sss_synch_t *q, cf_t *input, int *m0, float *m0_value,
|
|||
y[1][i] = input_fft[SSS_POS_SYMBOL + 2 * i + 1];
|
||||
}
|
||||
|
||||
vec_dot_prod(y[0], q->fc_tables.c[0], z, N_SSS);
|
||||
vec_dot_prod_ccc(y[0], q->fc_tables.c[0], z, N_SSS);
|
||||
memcpy(zdelay, &z[1], (N_SSS - 1) * sizeof(cf_t));
|
||||
vec_conj(z, zconj, N_SSS - 1);
|
||||
vec_dot_prod(zdelay, zconj, zprod, N_SSS - 1);
|
||||
vec_conj_cc(z, zconj, N_SSS - 1);
|
||||
vec_dot_prod_ccc(zdelay, zconj, zprod, N_SSS - 1);
|
||||
|
||||
corr_all_zs(zprod, q->fc_tables.s, tmp);
|
||||
vec_abs(tmp, tmp_real, N_SSS);
|
||||
vec_max(tmp_real, m0_value, m0, N_SSS);
|
||||
vec_abs_cf(tmp, tmp_real, N_SSS);
|
||||
*m0 = vec_max_fi(tmp_real, N_SSS);
|
||||
if (m0_value) {
|
||||
*m0_value = tmp_real[*m0];
|
||||
}
|
||||
|
||||
vec_dot_prod(y[1], q->fc_tables.c[1], tmp, N_SSS);
|
||||
vec_dot_prod(tmp, q->fc_tables.z1[*m0], z, N_SSS);
|
||||
vec_dot_prod_ccc(y[1], q->fc_tables.c[1], tmp, N_SSS);
|
||||
vec_dot_prod_ccc(tmp, q->fc_tables.z1[*m0], z, N_SSS);
|
||||
memcpy(zdelay, &z[1], (N_SSS - 1) * sizeof(cf_t));
|
||||
vec_conj(z, zconj, N_SSS - 1);
|
||||
vec_dot_prod(zdelay, zconj, zprod, N_SSS - 1);
|
||||
vec_conj_cc(z, zconj, N_SSS - 1);
|
||||
vec_dot_prod_ccc(zdelay, zconj, zprod, N_SSS - 1);
|
||||
|
||||
corr_all_zs(zprod, q->fc_tables.s, tmp);
|
||||
vec_abs(tmp, tmp_real, N_SSS);
|
||||
vec_max(tmp_real, m1_value, m1, N_SSS);
|
||||
vec_abs_cf(tmp, tmp_real, N_SSS);
|
||||
*m1 = vec_max_fi(tmp_real, N_SSS);
|
||||
if (m1_value) {
|
||||
*m1_value = tmp_real[*m1];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -174,10 +174,10 @@ int pss_synch_set_N_id_2(pss_synch_t *q, int N_id_2) {
|
|||
|
||||
dft_run_c2c(&plan, pss_signal_pad, q->pss_signal_freq);
|
||||
|
||||
vec_mult_c_r(q->pss_signal_freq, pss_signal_pad,
|
||||
(float) 1 / (PSS_LEN_FREQ - 1), PSS_LEN_FREQ);
|
||||
vec_sc_prod_cfc(q->pss_signal_freq, (float) 1 / (PSS_LEN_FREQ - 1),
|
||||
pss_signal_pad, PSS_LEN_FREQ);
|
||||
|
||||
vec_conj(pss_signal_pad, q->pss_signal_freq, PSS_LEN_FREQ);
|
||||
vec_conj_cc(pss_signal_pad, q->pss_signal_freq, PSS_LEN_FREQ);
|
||||
|
||||
q->N_id_2 = N_id_2;
|
||||
|
||||
|
@ -206,13 +206,16 @@ int pss_synch_find_pss(pss_synch_t *q, cf_t *input, float *corr_peak_value, floa
|
|||
conv_output_len = conv_cc(input, q->pss_signal_freq, q->conv_output, q->frame_size, PSS_LEN_FREQ);
|
||||
#endif
|
||||
|
||||
vec_abs(q->conv_output, q->conv_abs, conv_output_len);
|
||||
vec_max(q->conv_abs, corr_peak_value, &corr_peak_pos, conv_output_len);
|
||||
vec_abs_cf(q->conv_output, q->conv_abs, conv_output_len);
|
||||
corr_peak_pos = vec_max_fi(q->conv_abs, conv_output_len);
|
||||
if (corr_peak_value) {
|
||||
*corr_peak_value = q->conv_abs[corr_peak_pos];
|
||||
}
|
||||
if (corr_mean_value) {
|
||||
*corr_mean_value = sum_r(q->conv_abs, conv_output_len) / conv_output_len;
|
||||
*corr_mean_value = vec_acc_ff(q->conv_abs, conv_output_len) / conv_output_len;
|
||||
}
|
||||
|
||||
return corr_peak_pos;
|
||||
return (int) corr_peak_pos;
|
||||
}
|
||||
|
||||
/* Returns the CFO estimation given a PSS received sequence
|
||||
|
@ -224,10 +227,10 @@ float pss_synch_cfo_compute(pss_synch_t* q, cf_t *pss_recv) {
|
|||
cf_t y0, y1, yr;
|
||||
cf_t y[PSS_LEN_FREQ-1];
|
||||
|
||||
vec_dot_prod_u(q->pss_signal_freq, pss_recv, y, PSS_LEN_FREQ - 1);
|
||||
vec_dot_prod_ccc_unalign(q->pss_signal_freq, pss_recv, y, PSS_LEN_FREQ - 1);
|
||||
|
||||
y0 = sum_c(y, (PSS_LEN_FREQ - 1)/2);
|
||||
y1 = sum_c(&y[(PSS_LEN_FREQ - 1)/2], (PSS_LEN_FREQ - 1)/2);
|
||||
y0 = vec_acc_cc(y, (PSS_LEN_FREQ - 1)/2);
|
||||
y1 = vec_acc_cc(&y[(PSS_LEN_FREQ - 1)/2], (PSS_LEN_FREQ - 1)/2);
|
||||
yr = conjf(y0) * y1;
|
||||
|
||||
return atan2f(__imag__ yr, __real__ yr) / M_PI;
|
||||
|
@ -380,10 +383,7 @@ int pss_synch_work(pss_synch_hl* hl) {
|
|||
pss_synch_set_threshold(&hl->obj, hl->ctrl_in.correlation_threshold);
|
||||
}
|
||||
|
||||
*hl->out_len = pss_synch_frame(&hl->obj, hl->input, hl->output, hl->in_len);
|
||||
if (*hl->out_len < 0) {
|
||||
return -1;
|
||||
}
|
||||
hl->out_len = pss_synch_frame(&hl->obj, hl->input, hl->output, hl->in_len);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -66,7 +66,7 @@ int conv_fft_cc_run(conv_fft_cc_t *state, _Complex float *input, _Complex float
|
|||
dft_run_c2c(&state->input_plan, input, state->input_fft);
|
||||
dft_run_c2c(&state->filter_plan, filter, state->filter_fft);
|
||||
|
||||
vec_dot_prod(state->input_fft,state->filter_fft,state->output_fft,state->output_len);
|
||||
vec_dot_prod_ccc(state->input_fft,state->filter_fft,state->output_fft,state->output_len);
|
||||
|
||||
dft_run_c2c(&state->output_plan, state->output_fft, output);
|
||||
|
||||
|
|
|
@ -27,23 +27,23 @@
|
|||
#include "volk/volk.h"
|
||||
#endif
|
||||
|
||||
int sum_i(int *x, int len) {
|
||||
int vec_acc_ii(int *x, int len) {
|
||||
int i;
|
||||
int y=0;
|
||||
int z=0;
|
||||
for (i=0;i<len;i++) {
|
||||
y+=x[i];
|
||||
z+=x[i];
|
||||
}
|
||||
return y;
|
||||
return z;
|
||||
}
|
||||
|
||||
float sum_r(float *x, int len) {
|
||||
float vec_acc_ff(float *x, int len) {
|
||||
#ifndef HAVE_VOLK
|
||||
int i;
|
||||
float y=0;
|
||||
float z=0;
|
||||
for (i=0;i<len;i++) {
|
||||
y+=x[i];
|
||||
z+=x[i];
|
||||
}
|
||||
return y;
|
||||
return z;
|
||||
#else
|
||||
float result;
|
||||
volk_32f_accumulator_s32f_a(&result,x,(unsigned int) len);
|
||||
|
@ -51,50 +51,55 @@ float sum_r(float *x, int len) {
|
|||
#endif
|
||||
}
|
||||
|
||||
_Complex float sum_c(_Complex float *x, int len) {
|
||||
cf_t vec_acc_cc(cf_t *x, int len) {
|
||||
int i;
|
||||
_Complex float y=0;
|
||||
cf_t z=0;
|
||||
for (i=0;i<len;i++) {
|
||||
y+=x[i];
|
||||
z+=x[i];
|
||||
}
|
||||
return y;
|
||||
return z;
|
||||
}
|
||||
|
||||
void vec_sum_c(_Complex float *z, _Complex float *x, _Complex float *y, int len) {
|
||||
void vec_sum_ccc(cf_t *z, cf_t *x, cf_t *y, int len) {
|
||||
int i;
|
||||
for (i=0;i<len;i++) {
|
||||
z[i] = x[i]+y[i];
|
||||
}
|
||||
}
|
||||
|
||||
void vec_sum_char(char *z, char *x, char *y, int len) {
|
||||
void vec_sum_bbb(char *z, char *x, char *y, int len) {
|
||||
int i;
|
||||
for (i=0;i<len;i++) {
|
||||
z[i] = x[i]+y[i];
|
||||
}
|
||||
}
|
||||
|
||||
void vec_mult_c_r(_Complex float *x,_Complex float *y, float h, int len) {
|
||||
void vec_sc_prod_cfc(cf_t *x, float h, cf_t *z, int len) {
|
||||
#ifndef HAVE_VOLK
|
||||
int i;
|
||||
for (i=0;i<len;i++) {
|
||||
y[i] = x[i]*h;
|
||||
z[i] = x[i]*h;
|
||||
}
|
||||
#else
|
||||
_Complex float hh;
|
||||
cf_t hh;
|
||||
__real__ hh = h;
|
||||
__imag__ hh = 0;
|
||||
volk_32fc_s32fc_multiply_32fc_a(y,x,hh,(unsigned int) len);
|
||||
volk_32fc_s32fc_multiply_32fc_a(z,x,hh,(unsigned int) len);
|
||||
#endif
|
||||
}
|
||||
|
||||
void vec_sc_prod_ccc(cf_t *x, cf_t h, cf_t *z, int len) {
|
||||
#ifndef HAVE_VOLK
|
||||
int i;
|
||||
for (i=0;i<len;i++) {
|
||||
z[i] = x[i]*h;
|
||||
}
|
||||
#else
|
||||
volk_32fc_s32fc_multiply_32fc_a(z,x,h,(unsigned int) len);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void vec_mult_c(_Complex float *x,_Complex float *y, _Complex float h, int len) {
|
||||
int i;
|
||||
for (i=0;i<len;i++) {
|
||||
y[i] = x[i]*h;
|
||||
}
|
||||
}
|
||||
|
||||
void *vec_malloc(int size) {
|
||||
#ifndef HAVE_VOLK
|
||||
|
@ -109,7 +114,7 @@ void *vec_malloc(int size) {
|
|||
#endif
|
||||
}
|
||||
|
||||
void vec_fprint_c(FILE *stream, _Complex float *x, int len) {
|
||||
void vec_fprint_c(FILE *stream, cf_t *x, int len) {
|
||||
int i;
|
||||
fprintf(stream, "[");
|
||||
for (i=0;i<len;i++) {
|
||||
|
@ -141,7 +146,7 @@ void vec_fprint_i(FILE *stream, int *x, int len) {
|
|||
fprintf(stream, "];\n");
|
||||
}
|
||||
|
||||
void vec_conj(_Complex float *x, _Complex float *y, int len) {
|
||||
void vec_conj_cc(cf_t *x, cf_t *y, int len) {
|
||||
#ifndef HAVE_VOLK
|
||||
int i;
|
||||
for (i=0;i<len;i++) {
|
||||
|
@ -152,7 +157,7 @@ void vec_conj(_Complex float *x, _Complex float *y, int len) {
|
|||
#endif
|
||||
}
|
||||
|
||||
void vec_dot_prod(_Complex float *x,_Complex float *y, _Complex float *z, int len) {
|
||||
void vec_dot_prod_ccc(cf_t *x,cf_t *y, cf_t *z, int len) {
|
||||
#ifndef HAVE_VOLK
|
||||
int i;
|
||||
for (i=0;i<len;i++) {
|
||||
|
@ -164,7 +169,7 @@ void vec_dot_prod(_Complex float *x,_Complex float *y, _Complex float *z, int le
|
|||
}
|
||||
|
||||
|
||||
float vec_power(_Complex float *x, int len) {
|
||||
float vec_avg_power_cf(cf_t *x, int len) {
|
||||
int j;
|
||||
float power = 0;
|
||||
for (j=0;j<len;j++) {
|
||||
|
@ -174,7 +179,7 @@ float vec_power(_Complex float *x, int len) {
|
|||
return power / len;
|
||||
}
|
||||
|
||||
void vec_dot_prod_u(_Complex float *x,_Complex float *y, _Complex float *z, int len) {
|
||||
void vec_dot_prod_ccc_unalign(cf_t *x,cf_t *y, cf_t *z, int len) {
|
||||
#ifndef HAVE_VOLK
|
||||
int i;
|
||||
for (i=0;i<len;i++) {
|
||||
|
@ -185,7 +190,7 @@ void vec_dot_prod_u(_Complex float *x,_Complex float *y, _Complex float *z, int
|
|||
#endif
|
||||
}
|
||||
|
||||
void vec_abs(_Complex float *x, float *abs, int len) {
|
||||
void vec_abs_cf(cf_t *x, float *abs, int len) {
|
||||
#ifndef HAVE_VOLK
|
||||
int i;
|
||||
for (i=0;i<len;i++) {
|
||||
|
@ -198,24 +203,22 @@ void vec_abs(_Complex float *x, float *abs, int len) {
|
|||
|
||||
}
|
||||
|
||||
void vec_max(float *x, float *max, int *pos, int len) {
|
||||
int vec_max_fi(float *x, int len) {
|
||||
#ifndef HAVE_VOLK
|
||||
int i;
|
||||
float m=-FLT_MAX;
|
||||
int p=-1;
|
||||
int p=0;
|
||||
for (i=0;i<len;i++) {
|
||||
if (x[i]>m) {
|
||||
m=x[i];
|
||||
p=i;
|
||||
}
|
||||
}
|
||||
if (pos) *pos=p;
|
||||
if (max) *max=m;
|
||||
return p;
|
||||
#else
|
||||
unsigned int target=0;
|
||||
volk_32f_index_max_16u_a(&target,x,(unsigned int) len);
|
||||
if (pos) *pos=(int) target;
|
||||
if (max) *max=x[target];
|
||||
return (int) target;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
function [ out ] = read_real( filename, count )
|
||||
%READ_COMPLEX Summary of this function goes here
|
||||
% Detailed explanation goes here
|
||||
|
||||
[tidin msg]=fopen(filename,'r');
|
||||
if (tidin==-1)
|
||||
fprintf('error opening %s: %s\n',filename, msg);
|
||||
out=[];
|
||||
return
|
||||
end
|
||||
|
||||
if (nargin==1)
|
||||
count=inf;
|
||||
end
|
||||
|
||||
out=fread(tidin,count,'single');
|
||||
end
|
||||
|
|
@ -28,7 +28,7 @@ function [ fs eps p_m w2] = find_pss( x, N_id_2, doplot, threshold)
|
|||
end
|
||||
|
||||
% Estimate PSS-aided CFO
|
||||
if (i > 200 && i<length(x)&& p_m > threshold)
|
||||
if (i > 128 && i<length(x)&& p_m > threshold)
|
||||
y=ccf.*x(i-128:i-1);
|
||||
|
||||
y0=y(1:64);
|
||||
|
|
|
@ -15,8 +15,6 @@ typedef _Complex float complex_t;
|
|||
|
||||
#define SAMPLE_SZ sizeof(complex_t)
|
||||
|
||||
void uhd_rx_stream(void *h);
|
||||
|
||||
bool isLocked(void *h)
|
||||
{
|
||||
uhd_handler* handler = static_cast<uhd_handler*>(h);
|
||||
|
|
|
@ -36,7 +36,7 @@ int uhd_rssi_scan(void *uhd, float *freqs, float *rssi, int nof_bands, double fs
|
|||
goto free_and_exit;
|
||||
}
|
||||
}
|
||||
rssi[i] = vec_power(buffer, nsamp);
|
||||
rssi[i] = vec_avg_power_cf(buffer, nsamp);
|
||||
printf("[%3d]: Freq %4.1f Mhz - RSSI: %3.2f dBm\r", i, f/1000000, 10*log10f(rssi[i]) + 30); fflush(stdout);
|
||||
if (VERBOSE_ISINFO()) {
|
||||
printf("\n");
|
||||
|
|
Loading…
Reference in New Issue