Removed old soft demodulation algorithm. Removed hl/ll examples. Removed prach_ue example.

This commit is contained in:
ismagom 2015-10-05 09:58:44 +02:00
parent cc1623f1cd
commit 5e3f577e97
28 changed files with 72 additions and 2022 deletions

View File

@ -23,16 +23,6 @@ IF(UHD_FOUND)
LINK_DIRECTORIES(${UHD_LIBRARY_DIRS})
ENDIF(UHD_FOUND)
#################################################################
# EXAMPLES
#################################################################
add_executable(hl_example hl_example.c)
target_link_libraries(hl_example srslte)
add_executable(ll_example ll_example.c)
target_link_libraries(ll_example srslte)
#################################################################
# Applications
@ -41,7 +31,6 @@ target_link_libraries(ll_example srslte)
add_executable(synch_file synch_file.c)
target_link_libraries(synch_file srslte)
#################################################################
# These can be compiled without UHD or graphics support
#################################################################
@ -78,9 +67,6 @@ IF(UHD_FOUND)
add_executable(cell_search cell_search.c)
target_link_libraries(cell_search srslte srslte_uhd)
add_executable(prach_ue prach_ue.c)
target_link_libraries(prach_ue srslte srslte_uhd)
add_executable(cell_measurement cell_measurement.c)
target_link_libraries(cell_measurement srslte srslte_uhd)

View File

@ -1,123 +0,0 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2015 The srsLTE Developers. See the
* COPYRIGHT file at the top-level directory of this distribution.
*
* \section LICENSE
*
* This file is part of the srsLTE library.
*
* srsLTE is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* srsLTE 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 Affero General Public License for more details.
*
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <strings.h>
#include <math.h>
#include "srslte/srslte.h"
void usage(char *arg) {
printf("Usage: %s nbits snr_db\n",arg);
}
int main(int argc, char **argv) {
srslte_binsource_hl bs;
srslte_mod_hl mod;
srslte_ch_awgn_hl ch;
srslte_demod_soft_hl demod_s;
srslte_demod_hard_hl demod_h;
bzero(&bs,sizeof(bs));
bzero(&mod,sizeof(mod));
bzero(&ch,sizeof(ch));
bzero(&demod_s,sizeof(demod_s));
bzero(&demod_h,sizeof(demod_h));
if (argc<3) {
usage(argv[0]);
exit(-1);
}
int nbits = atoi(argv[1]);
float snr_db = atof(argv[2]);
float var = sqrt(pow(10,-snr_db/10));
bs.init.seed = 0;
bs.init.cache_seq_nbits = 0;
bs.ctrl_in.nbits = nbits;
bs.output = malloc(nbits);
mod.in_len = nbits;
mod.init.std = SRSLTE_MOD_BPSK;
mod.input = bs.output;
mod.output = malloc(nbits*sizeof(_Complex float));
ch.in_len = nbits;
ch.input = mod.output;
ch.ctrl_in.variance = var;
ch.output = malloc(nbits*sizeof(_Complex float));
demod_h.in_len = nbits;
demod_h.init.std = SRSLTE_MOD_BPSK;
demod_h.input = ch.output;
demod_h.output = malloc(nbits);
demod_s.in_len = nbits;
demod_s.init.std = SRSLTE_MOD_BPSK;
demod_s.input = ch.output;
demod_s.output = malloc(sizeof(float)*nbits);
demod_s.ctrl_in.alg_type = SRSLTE_DEMOD_SOFT_ALG_APPROX;
demod_s.ctrl_in.sigma = var;
if ( srslte_binsource_initialize(&bs) ||
mod_initialize(&mod) ||
srslte_ch_awgn_initialize(&ch) ||
srslte_demod_hard_initialize(&demod_h) ||
srslte_demod_soft_initialize(&demod_s)
) {
printf("Error initializing modules\n");
exit(-1);
}
srslte_binsource_work(&bs);
mod_work(&mod);
srslte_ch_awgn_work(&ch);
srslte_demod_hard_work(&demod_h);
srslte_demod_soft_work(&demod_s);
/* hard decision for soft demodulation */
uint8_t* tmp = malloc(nbits);
for (int i=0;i<nbits;i++) {
tmp[i] = demod_s.output[i]>0?1:0;
}
printf("Hard errors: %u/%d\n",srslte_bit_diff(bs.output,demod_h.output,nbits),nbits);
printf("Soft errors: %u/%d\n",srslte_bit_diff(bs.output,tmp,nbits),nbits);
free(bs.output);
free(mod.output);
free(ch.output);
free(demod_h.output);
free(demod_s.output);
free(tmp);
printf("Exit\n");
exit(0);
}

View File

@ -1,51 +0,0 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2015 The srsLTE Developers. See the
* COPYRIGHT file at the top-level directory of this distribution.
*
* \section LICENSE
*
* This file is part of the srsLTE library.
*
* srsLTE is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* srsLTE 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 Affero General Public License for more details.
*
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
#include <stdio.h>
#include <stdlib.h>
#include "srslte/srslte.h"
int main(int argc, char **argv) {
srslte_binsource_t bs;
uint8_t* output;
srslte_binsource_init(&bs);
srslte_binsource_seed_time(&bs);
output = malloc(100);
if (srslte_binsource_generate(&bs,output,100)) {
printf("Error generating bits\n");
exit(-1);
}
printf("output: ");
srslte_bit_fprint(stdout,output,100);
printf("Done\n");
exit(0);
}

View File

@ -1,634 +0,0 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2015 The srsLTE Developers. See the
* COPYRIGHT file at the top-level directory of this distribution.
*
* \section LICENSE
*
* This file is part of the srsLTE library.
*
* srsLTE is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* srsLTE 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 Affero General Public License for more details.
*
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
#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 <assert.h>
#include <signal.h>
#include <pthread.h>
#include <semaphore.h>
#include "srslte/srslte.h"
#include "srslte/cuhd/cuhd.h"
#include "srslte/cuhd/cuhd_utils.h"
cell_search_cfg_t cell_detect_config = {
5000,
200, // nof_frames_total
10.0 // threshold
};
#define B210_DEFAULT_GAIN 40.0
#define B210_DEFAULT_GAIN_CORREC 110.0 // Gain of the Rx chain when the gain is set to 40
float gain_offset = B210_DEFAULT_GAIN_CORREC;
/**********************************************************************
* Program arguments processing
***********************************************************************/
typedef struct {
int nof_subframes;
int force_N_id_2;
uint32_t file_nof_prb;
uint32_t preamble_idx;
float beta_prach;
float ta_usec;
float beta_pusch;
char *uhd_args;
float uhd_rx_freq;
float uhd_tx_freq;
float uhd_tx_freq_offset;
float uhd_tx_gain;
float uhd_rx_gain;
}prog_args_t;
void args_default(prog_args_t *args) {
args->nof_subframes = -1;
args->force_N_id_2 = -1; // Pick the best
args->file_nof_prb = 6;
args->beta_prach = 0.005;
args->beta_pusch = 2.0;
args->ta_usec = -1.0;
args->preamble_idx = 7;
args->uhd_args = "";
args->uhd_rx_freq = 2112500000.0;
args->uhd_tx_freq = 1922500000.0;
args->uhd_tx_freq_offset = 8000000.0;
args->uhd_tx_gain = 60.0;
args->uhd_rx_gain = 60.0;
}
void usage(prog_args_t *args, char *prog) {
printf("Usage: %s [agfFbrlpnv]\n", prog);
printf("\t-a UHD args [Default %s]\n", args->uhd_args);
printf("\t-g UHD TX/RX gain [Default %.2f dB]\n", args->uhd_rx_gain);
printf("\t-G UHD TX/RX gain [Default %.2f dB]\n", args->uhd_tx_gain);
printf("\t-f UHD RX freq [Default %.1f MHz]\n", args->uhd_rx_freq/1000000);
printf("\t-F UHD TX freq [Default %.1f MHz]\n", args->uhd_tx_freq/1000000);
printf("\t-b beta PRACH (transmission amplitude) [Default %f]\n",args->beta_prach);
printf("\t-B beta PUSCH (transmission amplitude) [Default %f]\n",args->beta_pusch);
printf("\t-t TA usec (time advance, -1 from RAR) [Default %f]\n",args->ta_usec);
printf("\t-p PRACH preamble idx [Default %d]\n",args->preamble_idx);
printf("\t-l Force N_id_2 [Default best]\n");
printf("\t-n nof_subframes [Default %d]\n", args->nof_subframes);
printf("\t-v [set srslte_verbose to debug, default none]\n");
}
void parse_args(prog_args_t *args, int argc, char **argv) {
int opt;
args_default(args);
while ((opt = getopt(argc, argv, "agGfFplnvbBt")) != -1) {
switch (opt) {
case 'a':
args->uhd_args = argv[optind];
break;
case 'b':
args->beta_prach = atof(argv[optind]);
break;
case 'B':
args->beta_pusch = atof(argv[optind]);
break;
case 't':
args->ta_usec = atof(argv[optind]);
break;
case 'g':
args->uhd_rx_gain = atof(argv[optind]);
break;
case 'G':
args->uhd_tx_gain = atof(argv[optind]);
break;
case 'f':
args->uhd_rx_freq = atof(argv[optind]);
break;
case 'F':
args->uhd_tx_freq = atof(argv[optind]);
break;
case 'n':
args->nof_subframes = atoi(argv[optind]);
break;
case 'p':
args->preamble_idx = atoi(argv[optind]);
break;
case 'l':
args->force_N_id_2 = atoi(argv[optind]);
break;
case 'v':
srslte_verbose++;
break;
default:
usage(args, argv[0]);
exit(-1);
}
}
if (args->uhd_tx_freq < 0 && args->uhd_rx_freq < 0) {
usage(args, argv[0]);
exit(-1);
}
}
/**********************************************************************/
/* TODO: Do something with the output data */
uint8_t data_rx[20000];
int cuhd_recv_wrapper_timed(void *h, void *data, uint32_t nsamples, srslte_timestamp_t *uhd_time) {
DEBUG(" ---- Receive %d samples ---- \n", nsamples);
return cuhd_recv_with_time(h, data, nsamples, true, &uhd_time->full_secs, &uhd_time->frac_secs);
}
extern float mean_exec_time;
enum receiver_state { DECODE_MIB, SEND_PRACH, RECV_RAR, RECV_CONNSETUP} state;
#define NOF_PRACH_SEQUENCES 52
srslte_ue_dl_t ue_dl;
srslte_ue_ul_t ue_ul;
srslte_ue_sync_t ue_sync;
srslte_prach_t prach;
int prach_buffer_len;
prog_args_t prog_args;
uint32_t sfn = 0; // system frame number
cf_t *sf_buffer = NULL;
typedef enum{
rar_tpc_n6dB = 0,
rar_tpc_n4dB,
rar_tpc_n2dB,
rar_tpc_0dB,
rar_tpc_2dB,
rar_tpc_4dB,
rar_tpc_6dB,
rar_tpc_8dB,
rar_tpc_n_items,
}rar_tpc_command_t;
static const char tpc_command_text[rar_tpc_n_items][8] = {"-6dB", "-4dB", "-2dB", "0dB", "2dB", "4dB", "6dB", "8dB"};
typedef enum{
rar_header_type_bi = 0,
rar_header_type_rapid,
rar_header_type_n_items,
}rar_header_t;
static const char rar_header_text[rar_header_type_n_items][8] = {"BI", "RAPID"};
typedef struct {
rar_header_t hdr_type;
bool hopping_flag;
rar_tpc_command_t tpc_command;
bool ul_delay;
bool csi_req;
uint16_t rba;
uint16_t timing_adv_cmd;
uint16_t temp_c_rnti;
uint8_t mcs;
uint8_t RAPID;
uint8_t BI;
}rar_msg_t;
char *bool_to_string(bool x) {
if (x) {
return "Enabled";
} else {
return "Disabled";
}
}
void rar_msg_fprint(FILE *stream, rar_msg_t *msg)
{
fprintf(stream, "Header type: %s\n", rar_header_text[msg->hdr_type]);
fprintf(stream, "Hopping flag: %s\n", bool_to_string(msg->hopping_flag));
fprintf(stream, "TPC command: %s\n", tpc_command_text[msg->tpc_command]);
fprintf(stream, "UL delay: %s\n", bool_to_string(msg->ul_delay));
fprintf(stream, "CSI required: %s\n", bool_to_string(msg->csi_req));
fprintf(stream, "RBA: %d\n", msg->rba);
fprintf(stream, "TA: %d\n", msg->timing_adv_cmd);
fprintf(stream, "T-CRNTI: %d\n", msg->temp_c_rnti);
fprintf(stream, "MCS: %d\n", msg->mcs);
fprintf(stream, "RAPID: %d\n", msg->RAPID);
fprintf(stream, "BI: %d\n", msg->BI);
}
bool go_exit = false;
void sig_int_handler(int signo)
{
printf("SIGINT received. Exiting...\n");
if (signo == SIGINT) {
go_exit = true;
}
}
int rar_unpack(uint8_t *buffer, rar_msg_t *msg)
{
int ret = SRSLTE_ERROR;
uint8_t *ptr = buffer;
if(buffer != NULL &&
msg != NULL)
{
ptr++;
msg->hdr_type = *ptr++;
if(msg->hdr_type == rar_header_type_bi) {
ptr += 2;
msg->BI = srslte_bit_pack(&ptr, 4);
ret = SRSLTE_SUCCESS;
} else if (msg->hdr_type == rar_header_type_rapid) {
msg->RAPID = srslte_bit_pack(&ptr, 6);
ptr++;
msg->timing_adv_cmd = srslte_bit_pack(&ptr, 11);
msg->hopping_flag = *ptr++;
msg->rba = srslte_bit_pack(&ptr, 10);
msg->mcs = srslte_bit_pack(&ptr, 4);
msg->tpc_command = (rar_tpc_command_t) srslte_bit_pack(&ptr, 3);
msg->ul_delay = *ptr++;
msg->csi_req = *ptr++;
msg->temp_c_rnti = srslte_bit_pack(&ptr, 16);
ret = SRSLTE_SUCCESS;
}
}
return(ret);
}
int main(int argc, char **argv) {
int ret;
srslte_cell_t cell;
int64_t sf_cnt;
srslte_ue_mib_t ue_mib;
void *uhd;
int n;
uint8_t bch_payload[SRSLTE_BCH_PAYLOAD_LEN];
uint32_t sfn_offset;
rar_msg_t rar_msg;
srslte_ra_ul_dci_t ra_pusch;
srslte_ra_ul_grant_t ra_grant;
uint32_t rar_window_start = 0, rar_trials = 0, rar_window_stop = 0;
srslte_timestamp_t uhd_time;
srslte_timestamp_t next_tx_time;
const uint8_t conn_request_msg[] = {0x20, 0x06, 0x1F, 0x5C, 0x2C, 0x04, 0xB2, 0xAC, 0xF6, 0x00, 0x00, 0x00};
uint8_t data[1000];
cf_t *prach_buffer;
parse_args(&prog_args, argc, argv);
printf("Opening UHD device...\n");
if (cuhd_open(prog_args.uhd_args, &uhd)) {
fprintf(stderr, "Error opening uhd\n");
exit(-1);
}
sigset_t sigset;
sigemptyset(&sigset);
sigaddset(&sigset, SIGINT);
sigprocmask(SIG_UNBLOCK, &sigset, NULL);
signal(SIGINT, sig_int_handler);
cuhd_set_master_clock_rate(uhd, 30.72e6);
/* Set receiver gain */
float x = cuhd_set_rx_gain(uhd, prog_args.uhd_rx_gain);
printf("Set RX gain to %.1f dB\n", x);
x = cuhd_set_tx_gain(uhd, prog_args.uhd_tx_gain);
printf("Set TX gain to %.1f dB\n", x);
/* set receiver frequency */
cuhd_set_rx_freq(uhd, (double) prog_args.uhd_rx_freq);
cuhd_rx_wait_lo_locked(uhd);
printf("Tunning RX receiver to %.3f MHz\n", (double ) prog_args.uhd_rx_freq/1000000);
cuhd_set_tx_freq_offset(uhd, prog_args.uhd_tx_freq, prog_args.uhd_tx_freq_offset);
printf("Tunning TX receiver to %.3f MHz\n", (double ) prog_args.uhd_tx_freq/1000000);
uint32_t ntrial=0;
do {
ret = cuhd_search_and_decode_mib(uhd, &cell_detect_config, prog_args.force_N_id_2, &cell);
if (ret < 0) {
fprintf(stderr, "Error searching for cell\n");
exit(-1);
} else if (ret == 0 && !go_exit) {
printf("Cell not found after %d trials. Trying again (Press Ctrl+C to exit)\n", ntrial++);
}
} while (ret == 0 && !go_exit);
if (go_exit) {
exit(0);
}
/* set sampling frequency */
int srate = srslte_sampling_freq_hz(cell.nof_prb);
if (srate != -1) {
if (srate < 10e6) {
cuhd_set_master_clock_rate(uhd, 4*srate);
} else {
cuhd_set_master_clock_rate(uhd, srate);
}
printf("Setting sampling rate %.2f MHz\n", (float) srate/1000000);
float srate_uhd = cuhd_set_rx_srate(uhd, (double) srate);
if (srate_uhd != srate) {
fprintf(stderr, "Could not set sampling rate\n");
exit(-1);
}
} else {
fprintf(stderr, "Invalid number of PRB %d\n", cell.nof_prb);
exit(-1);
}
INFO("Stopping UHD and flushing buffer...\r",0);
cuhd_stop_rx_stream(uhd);
cuhd_flush_buffer(uhd);
if (srslte_ue_mib_init(&ue_mib, cell)) {
fprintf(stderr, "Error initaiting UE MIB decoder\n");
exit(-1);
}
if (srslte_prach_init(&prach, srslte_symbol_sz(cell.nof_prb), 0, 0, false, 1)) {
fprintf(stderr, "Error initializing PRACH\n");
exit(-1);
}
prach_buffer_len = prach.N_seq + prach.N_cp;
prach_buffer = srslte_vec_malloc(prach_buffer_len*sizeof(cf_t));
if(!prach_buffer) {
perror("maloc");
exit(-1);
}
if(srslte_prach_gen(&prach, prog_args.preamble_idx, 0, prach_buffer)){
fprintf(stderr, "Error generating prach sequence\n");
return -1;
}
if (srslte_ue_ul_init(&ue_ul, cell)) {
fprintf(stderr, "Error initiating UE UL\n");
exit(-1);
}
srslte_ue_ul_set_cfo_enable(&ue_ul, true);
srslte_refsignal_dmrs_pusch_cfg_t dmrs_cfg;
bzero(&dmrs_cfg, sizeof(srslte_refsignal_dmrs_pusch_cfg_t));
dmrs_cfg.group_hopping_en = false;
dmrs_cfg.sequence_hopping_en = false;
dmrs_cfg.delta_ss = 0;
dmrs_cfg.cyclic_shift = 0;
srslte_ue_ul_set_cfg(&ue_ul, &dmrs_cfg, NULL, NULL, NULL, NULL, NULL, NULL);
cf_t *ul_signal = srslte_vec_malloc(sizeof(cf_t) * SRSLTE_SF_LEN_PRB(cell.nof_prb));
if (!ul_signal) {
perror("malloc");
exit(-1);
}
bzero(ul_signal, sizeof(cf_t) * SRSLTE_SF_LEN_PRB(cell.nof_prb));
if (srslte_ue_dl_init(&ue_dl, cell)) {
fprintf(stderr, "Error initiating UE downlink processing module\n");
exit(-1);
}
/* Initialize subframe counter */
sf_cnt = 0;
if (srslte_ue_sync_init(&ue_sync, cell, cuhd_recv_wrapper_timed, uhd)) {
fprintf(stderr, "Error initiating ue_sync\n");
exit(-1);
}
cuhd_start_rx_stream(uhd);
uint16_t ra_rnti;
uint32_t conn_setup_trial = 0;
uint32_t ul_sf_idx = 0;
state = DECODE_MIB;
/* Main loop */
while (!go_exit && (sf_cnt < prog_args.nof_subframes || prog_args.nof_subframes == -1)) {
ret = srslte_ue_sync_get_buffer(&ue_sync, &sf_buffer);
if (ret < 0) {
fprintf(stderr, "Error calling srslte_ue_sync_work()\n");
}
/* srslte_ue_sync_get_buffer returns 1 if successfully read 1 aligned subframe */
if (ret == 1) {
if (state != RECV_RAR) {
/* Run FFT for all subframe data */
srslte_ofdm_rx_sf(&ue_dl.fft, sf_buffer, ue_dl.sf_symbols);
/* Get channel estimates for each port */
srslte_chest_dl_estimate(&ue_dl.chest, ue_dl.sf_symbols, ue_dl.ce, srslte_ue_sync_get_sfidx(&ue_sync));
}
if (sf_cnt > 1000) {
switch (state) {
case DECODE_MIB:
if (srslte_ue_sync_get_sfidx(&ue_sync) == 0) {
srslte_pbch_decode_reset(&ue_mib.pbch);
n = srslte_ue_mib_decode(&ue_mib, sf_buffer, bch_payload, NULL, &sfn_offset);
if (n < 0) {
fprintf(stderr, "Error decoding UE MIB\n");
exit(-1);
} else if (n == SRSLTE_UE_MIB_FOUND) {
srslte_pbch_mib_unpack(bch_payload, &cell, &sfn);
srslte_cell_fprint(stdout, &cell, sfn);
printf("Decoded MIB. SFN: %d, offset: %d\n", sfn, sfn_offset);
sfn = (sfn + sfn_offset)%1024;
state = SEND_PRACH;
}
}
break;
case SEND_PRACH:
if (((sfn%2) == 1) && (srslte_ue_sync_get_sfidx(&ue_sync) == 1)) {
srslte_ue_sync_get_last_timestamp(&ue_sync, &uhd_time);
srslte_timestamp_copy(&next_tx_time, &uhd_time);
srslte_timestamp_add(&next_tx_time, 0, 0.01); // send next frame (10 ms)
printf("Send prach sfn: %d. Last frame time = %.6f, send prach time = %.6f\n",
sfn, srslte_timestamp_real(&uhd_time), srslte_timestamp_real(&next_tx_time));
cuhd_send_timed(uhd, prach_buffer, prach_buffer_len,
next_tx_time.full_secs, next_tx_time.frac_secs);
srslte_vec_save_file("prach_ue.dat", prach_buffer, prach_buffer_len*sizeof(cf_t));
ra_rnti = 2;
rar_window_start = sfn+1;
rar_window_stop = sfn+3;
state = RECV_RAR;
}
break;
case RECV_RAR:
if ((sfn == rar_window_start && srslte_ue_sync_get_sfidx(&ue_sync) > 3) || sfn > rar_window_start) {
printf("Looking for RAR in sfn: %d sf_idx: %d\n", sfn, srslte_ue_sync_get_sfidx(&ue_sync));
n = srslte_ue_dl_decode_rnti(&ue_dl, sf_buffer, data_rx, srslte_ue_sync_get_sfidx(&ue_sync), ra_rnti);
if (n < 0) {
fprintf(stderr, "Error decoding UE DL\n");fflush(stdout);
} else if (n > 0) {
rar_unpack(data_rx, &rar_msg);
rar_msg_fprint(stdout, &rar_msg);
srslte_dci_rar_grant_t rar_grant;
rar_grant.hopping_flag = rar_msg.hopping_flag;
rar_grant.rba = rar_msg.rba;
rar_grant.trunc_mcs = rar_msg.mcs;
srslte_dci_rar_to_ul_grant(&rar_grant, cell.nof_prb, 0, &ra_pusch, &ra_grant);
srslte_ra_pusch_fprint(stdout, &ra_pusch, cell.nof_prb);
srslte_ue_sync_get_last_timestamp(&ue_sync, &uhd_time);
srslte_bit_unpack_vector((uint8_t*) conn_request_msg, data, ra_grant.mcs.tbs);
uint32_t n_ta = srslte_N_ta_new_rar(rar_msg.timing_adv_cmd);
printf("ta: %d, n_ta: %d\n", rar_msg.timing_adv_cmd, n_ta);
float time_adv_sec = SRSLTE_TA_OFFSET+((float) n_ta)*SRSLTE_LTE_TS;
if (prog_args.ta_usec >= 0) {
time_adv_sec = prog_args.ta_usec*1e-6;
}
#define N_TX 1
const uint32_t rv[N_TX]={0};
for (int i=0; i<N_TX;i++) {
ra_pusch.rv_idx = rv[i];
ul_sf_idx = (srslte_ue_sync_get_sfidx(&ue_sync)+6+i*8)%10;
float cfo = srslte_ue_sync_get_cfo(&ue_sync)/15000;
printf("Setting CFO: %f (%f)\n", cfo, cfo*15000);
srslte_ue_ul_set_cfo(&ue_ul, cfo);
srslte_ue_ul_cfg_grant(&ue_ul, &ra_grant, ul_sf_idx, 0, 0);
n = srslte_ue_ul_pusch_encode_rnti(&ue_ul, data, rar_msg.temp_c_rnti, ul_signal);
if (n < 0) {
fprintf(stderr, "Error encoding PUSCH\n");
exit(-1);
}
srslte_vec_sc_prod_cfc(ul_signal, prog_args.beta_pusch, ul_signal, SRSLTE_SF_LEN_PRB(cell.nof_prb));
srslte_timestamp_copy(&next_tx_time, &uhd_time);
srslte_timestamp_add(&next_tx_time, 0, 0.006 + i*0.008 - time_adv_sec); // send after 6 sub-frames (6 ms)
printf("Send %d samples PUSCH sfn: %d. RV_idx=%d, Last frame time = %.6f "
"send PUSCH time = %.6f TA: %.1f us\n",
SRSLTE_SF_LEN_PRB(cell.nof_prb), sfn, ra_pusch.rv_idx,
srslte_timestamp_real(&uhd_time),
srslte_timestamp_real(&next_tx_time), time_adv_sec*1000000);
cuhd_send_timed(uhd, ul_signal, SRSLTE_SF_LEN_PRB(cell.nof_prb),
next_tx_time.full_secs, next_tx_time.frac_secs);
srslte_vec_save_file("prach_ue_connreq.dat", ul_signal, sizeof(cf_t)*SRSLTE_SF_LEN_PRB(cell.nof_prb));
//cuhd_start_rx_stream(uhd);
state = RECV_CONNSETUP;
conn_setup_trial = 0;
}
}
if (sfn >= rar_window_stop) {
state = SEND_PRACH;
rar_trials++;
if (rar_trials >= 1) {
go_exit = 1;
}
}
}
break;
case RECV_CONNSETUP:
if (srslte_ue_sync_get_sfidx(&ue_sync) == (ul_sf_idx+4)%10) {
//srslte_verbose=SRSLTE_VERBOSE_DEBUG;
srslte_vec_save_file("connsetup",sf_buffer,SRSLTE_SF_LEN_PRB(cell.nof_prb)*sizeof(cf_t));
} else {
//srslte_verbose=SRSLTE_VERBOSE_NONE;
}
printf("Looking for ConnectionSetup in sfn: %d sf_idx: %d, RNTI: %d\n", sfn, srslte_ue_sync_get_sfidx(&ue_sync),rar_msg.temp_c_rnti);
n = srslte_ue_dl_decode_rnti(&ue_dl, sf_buffer, data_rx, srslte_ue_sync_get_sfidx(&ue_sync), rar_msg.temp_c_rnti);
if (n < 0) {
fprintf(stderr, "Error decoding UE DL\n");fflush(stdout);
} else if (n > 0) {
printf("Received ConnectionSetup len: %d.\n", n);
srslte_vec_fprint_hex(stdout, data_rx, n);
exit(0);
} else {
conn_setup_trial++;
if (conn_setup_trial == 20) {
go_exit = 1;
}
}
break;
}
if (srslte_ue_sync_get_sfidx(&ue_sync) == 9) {
sfn++;
if (sfn == 1024) {
sfn = 0;
}
}
}
} else if (ret == 0) {
printf("Finding PSS... Peak: %8.1f, FrameCnt: %d, State: %d\r",
srslte_sync_get_peak_value(&ue_sync.sfind),
ue_sync.frame_total_cnt, ue_sync.state);
}
sf_cnt++;
} // Main loop
srslte_ue_dl_free(&ue_dl);
srslte_ue_sync_free(&ue_sync);
srslte_ue_mib_free(&ue_mib);
cuhd_close(uhd);
printf("\nBye\n");
exit(0);
}

View File

@ -206,7 +206,7 @@ int main(int argc, char **argv) {
srslte_modem_table_t modulator;
srslte_modem_table_init(&modulator);
srslte_modem_table_lte(&modulator, modulation, false);
srslte_modem_table_lte(&modulator, modulation);
srslte_tcod_t turbocoder;
srslte_tcod_init(&turbocoder, SRSLTE_TCOD_MAX_LEN_CB);

View File

@ -43,47 +43,14 @@
#include "srslte/config.h"
#include "modem_table.h"
typedef enum SRSLTE_API {
SRSLTE_DEMOD_SOFT_ALG_EXACT,
SRSLTE_DEMOD_SOFT_ALG_APPROX
} srslte_demod_soft_alg_t;
typedef struct SRSLTE_API {
float sigma; // noise power
srslte_demod_soft_alg_t alg_type; // soft demapping algorithm (SRSLTE_DEMOD_SOFT_ALG_EXACT or SRSLTE_DEMOD_SOFT_ALG_APPROX)
srslte_modem_table_t *table; // symbol mapping table (see modem_table.h)
uint32_t *zones;
float *dd;
uint32_t max_symbols;
} srslte_demod_soft_t;
SRSLTE_API int srslte_demod_soft_init(srslte_demod_soft_t *q,
uint32_t max_symbols);
SRSLTE_API void srslte_demod_soft_free(srslte_demod_soft_t *q);
SRSLTE_API void srslte_demod_soft_table_set(srslte_demod_soft_t *q,
srslte_modem_table_t *table);
SRSLTE_API void srslte_demod_soft_alg_set(srslte_demod_soft_t *q,
srslte_demod_soft_alg_t alg_type);
SRSLTE_API void srslte_demod_soft_sigma_set(srslte_demod_soft_t *q,
float sigma);
SRSLTE_API int srslte_demod_soft_demodulate(srslte_demod_soft_t *q,
SRSLTE_API int srslte_demod_soft_demodulate(srslte_mod_t modulation,
const cf_t* symbols,
float* llr,
int nsymbols);
SRSLTE_API int srslte_demod_soft_demodulate_lte(srslte_mod_t modulation,
const cf_t* symbols,
float* llr,
int nsymbols);
int nsymbols);
/* High-level API */
typedef struct SRSLTE_API {
srslte_demod_soft_t obj;
srslte_modem_table_t table;
struct srslte_demod_soft_init{
@ -95,7 +62,6 @@ typedef struct SRSLTE_API {
struct srslte_demod_soft_ctrl_in {
float sigma; // Estimated noise variance
srslte_demod_soft_alg_t alg_type; // soft demapping algorithm (SRSLTE_DEMOD_SOFT_ALG_EXACT or SRSLTE_DEMOD_SOFT_ALG_APPROX)
}ctrl_in;
float* output;

View File

@ -44,14 +44,6 @@
#include "srslte/common/phy_common.h"
#include "srslte/config.h"
typedef struct SRSLTE_API {
uint32_t idx[2][6][32];
uint32_t min_idx[2][64][6]; /* NEW: for each constellation point zone (2, 4, 16, 64 for BPSK, QPSK, 16QAM, 64QAM) the 2x(1, 2, 4, and 6 closest constellation points) for each bit, respectively. */
uint32_t d_idx[64][7]; /* NEW: for each constellation point zone (2, 4, 16, 64 for BPSK, QPSK, 16QAM, 64QAM) the 2, 3, 5 and 7 indices to constellation points that need to be computed for any recevied symbol modulated as BPSK, QPSK, 16QAM, and 64QAM, respectively. */
}srslte_soft_table_t;
typedef struct {
cf_t symbol[8];
} bpsk_packed_t;
@ -66,7 +58,6 @@ typedef struct {
typedef struct SRSLTE_API {
cf_t* symbol_table; // bit-to-symbol mapping
srslte_soft_table_t soft_table; // symbol-to-bit mapping (used in soft demodulating)
uint32_t nsymbols; // number of modulation symbols
uint32_t nbits_x_symbol; // number of bits per symbol
@ -85,13 +76,11 @@ SRSLTE_API void srslte_modem_table_reset(srslte_modem_table_t* q);
SRSLTE_API int srslte_modem_table_set(srslte_modem_table_t* q,
cf_t* table,
srslte_soft_table_t *soft_table,
uint32_t nsymbols,
uint32_t nbits_x_symbol);
SRSLTE_API int srslte_modem_table_lte(srslte_modem_table_t* q,
srslte_mod_t modulation,
bool compute_soft_demod);
srslte_mod_t modulation);
SRSLTE_API void srslte_modem_table_bytes(srslte_modem_table_t* q);

View File

@ -50,6 +50,7 @@
typedef struct SRSLTE_API {
srslte_mod_t mod;
int tbs;
uint32_t idx;
} srslte_ra_mcs_t;

View File

@ -46,7 +46,7 @@
#include "srslte/phch/pusch_cfg.h"
#include "srslte/phch/uci.h"
#define SRSLTE_PDSCH_MAX_TDEC_ITERS 6
#define SRSLTE_PDSCH_MAX_TDEC_ITERS 3
#ifndef SRSLTE_RX_NULL

View File

@ -27,10 +27,7 @@
#include <string.h>
#include "srslte/srslte.h"
#ifdef UNDEF_BOOL
#undef bool
#endif
#include "mex.h"
#include "srslte/mex/mexutils.h"
/** MEX function to be called from MATLAB to test the channel estimator

View File

@ -32,57 +32,9 @@
#include "srslte/utils/vector.h"
#include "srslte/utils/bit.h"
#include "srslte/modem/demod_soft.h"
#include "soft_algs.h"
//#define SCALE_DEMOD16QAM
#define SCALE_DEMOD16QAM
int srslte_demod_soft_init(srslte_demod_soft_t *q, uint32_t max_symbols) {
int ret = SRSLTE_ERROR;
bzero((void*)q,sizeof(srslte_demod_soft_t));
q->sigma = 1.0;
q->zones = srslte_vec_malloc(sizeof(uint32_t) * max_symbols);
if (!q->zones) {
perror("malloc");
goto clean_exit;
}
q->dd = srslte_vec_malloc(sizeof(float*) * max_symbols * 7);
if (!q->dd) {
perror("malloc");
goto clean_exit;
}
q->max_symbols = max_symbols;
ret = SRSLTE_SUCCESS;
clean_exit:
if (ret != SRSLTE_SUCCESS) {
srslte_demod_soft_free(q);
}
return ret;
}
void srslte_demod_soft_free(srslte_demod_soft_t *q) {
if (q->zones) {
free(q->zones);
}
if (q->dd) {
free(q->dd);
}
bzero((void*)q,sizeof(srslte_demod_soft_t));
}
void srslte_demod_soft_table_set(srslte_demod_soft_t *q, srslte_modem_table_t *table) {
q->table = table;
}
void srslte_demod_soft_alg_set(srslte_demod_soft_t *q, srslte_demod_soft_alg_t alg_type) {
q->alg_type = alg_type;
}
void srslte_demod_soft_sigma_set(srslte_demod_soft_t *q, float sigma) {
q->sigma = 2*sigma;
}
void demod_bpsk_lte(const cf_t *symbols, float *llr, int nsymbols) {
for (int i=0;i<nsymbols;i++) {
@ -143,7 +95,7 @@ void demod_64qam_lte(const cf_t *symbols, float *llr, int nsymbols)
}
int srslte_demod_soft_demodulate_lte(srslte_mod_t modulation, const cf_t* symbols, float* llr, int nsymbols) {
int srslte_demod_soft_demodulate(srslte_mod_t modulation, const cf_t* symbols, float* llr, int nsymbols) {
switch(modulation) {
case SRSLTE_MOD_BPSK:
demod_bpsk_lte(symbols, llr, nsymbols);
@ -164,53 +116,18 @@ int srslte_demod_soft_demodulate_lte(srslte_mod_t modulation, const cf_t* symbol
return 0;
}
int srslte_demod_soft_demodulate(srslte_demod_soft_t *q, const cf_t* symbols, float* llr, int nsymbols) {
switch(q->alg_type) {
case SRSLTE_DEMOD_SOFT_ALG_EXACT:
llr_exact(symbols, llr, nsymbols, q->table->nsymbols, q->table->nbits_x_symbol,
q->table->symbol_table, q->table->soft_table.idx, q->sigma);
break;
case SRSLTE_DEMOD_SOFT_ALG_APPROX:
if (nsymbols <= q->max_symbols) {
llr_approx(symbols, llr, nsymbols, q->table->nsymbols,
q->table->nbits_x_symbol,
q->table->symbol_table, q->table->soft_table.idx,
q->table->soft_table.d_idx, q->table->soft_table.min_idx, q->sigma,
q->zones, q->dd);
} else {
fprintf(stderr, "Too many symbols (%d>%d)\n", nsymbols, q->max_symbols);
return -1;
}
break;
}
return nsymbols*q->table->nbits_x_symbol;
}
/* High-Level API */
int srslte_demod_soft_initialize(srslte_demod_soft_hl* hl) {
srslte_modem_table_init(&hl->table);
if (srslte_modem_table_lte(&hl->table,hl->init.std,true)) {
return -1;
}
srslte_demod_soft_init(&hl->obj, 10000);
hl->obj.table = &hl->table;
return 0;
}
int srslte_demod_soft_work(srslte_demod_soft_hl* hl) {
hl->obj.sigma = hl->ctrl_in.sigma;
hl->obj.alg_type = hl->ctrl_in.alg_type;
int ret = srslte_demod_soft_demodulate(&hl->obj,hl->input,hl->output,hl->in_len);
int ret = srslte_demod_soft_demodulate(hl->init.std,hl->input,hl->output,hl->in_len);
hl->out_len = ret;
return 0;
}
int srslte_demod_soft_stop(srslte_demod_soft_hl* hl) {
srslte_modem_table_free(&hl->table);
return 0;
}

View File

@ -34,11 +34,9 @@
#include "srslte/modem/modem_table.h"
#include "lte_tables.h"
void LLR_approx_params(const cf_t* table, srslte_soft_table_t *soft_table, int B);
/**
* Set the BPSK modulation table */
void set_BPSKtable(cf_t* table, srslte_soft_table_t *soft_table, bool compute_soft_demod)
void set_BPSKtable(cf_t* table)
{
// LTE-BPSK constellation:
// Q
@ -48,32 +46,12 @@ void set_BPSKtable(cf_t* table, srslte_soft_table_t *soft_table, bool compute_so
table[0] = BPSK_LEVEL + BPSK_LEVEL*_Complex_I;
table[1] = -BPSK_LEVEL -BPSK_LEVEL*_Complex_I;
if (!compute_soft_demod) {
return;
}
/* BSPK symbols containing a '0' and a '1' (only two symbols, 1 bit) */
soft_table->idx[0][0][0] = 0;
soft_table->idx[1][0][0] = 1;
/* set two matrices for LLR approx. calculation */
soft_table->min_idx[0][0][0] = 0;
soft_table->min_idx[0][1][0] = 0;
soft_table->min_idx[1][0][0] = 1;
soft_table->min_idx[1][1][0] = 1;
soft_table->d_idx[0][0] = 0;
soft_table->d_idx[0][1] = 1;
soft_table->d_idx[1][0] = 0;
soft_table->d_idx[1][1] = 1;
}
/**
* Set the QPSK modulation table */
void set_QPSKtable(cf_t* table, srslte_soft_table_t *soft_table, bool compute_soft_demod)
void set_QPSKtable(cf_t* table)
{
uint32_t i,j;
// LTE-QPSK constellation:
// Q
@ -84,36 +62,12 @@ void set_QPSKtable(cf_t* table, srslte_soft_table_t *soft_table, bool compute_so
table[1] = QPSK_LEVEL - QPSK_LEVEL*_Complex_I;
table[2] = -QPSK_LEVEL + QPSK_LEVEL*_Complex_I;
table[3] = -QPSK_LEVEL - QPSK_LEVEL*_Complex_I;
for (i=0;i<6;i++) {
for (j=0;j<32;j++) {
soft_table->idx[0][i][j] = 0;
soft_table->idx[1][i][j] = 0;
}
}
if (!compute_soft_demod) {
return;
}
/* QSPK symbols containing a '0' at the different bit positions */
soft_table->idx[0][0][0] = 0;
soft_table->idx[0][0][1] = 1;
soft_table->idx[0][1][0] = 0;
soft_table->idx[0][1][1] = 2;
/* QSPK symbols containing a '1' at the different bit positions */
soft_table->idx[1][0][0] = 2;
soft_table->idx[1][0][1] = 3;
soft_table->idx[1][1][0] = 1;
soft_table->idx[1][1][1] = 3;
LLR_approx_params(table, soft_table, 2); /* last param indicating B (bits per symbol) */
}
/**
* Set the 16QAM modulation table */
void set_16QAMtable(cf_t* table, srslte_soft_table_t *soft_table, bool compute_soft_demod)
void set_16QAMtable(cf_t* table)
{
uint32_t i,j;
// LTE-16QAM constellation:
// Q
// 1011 1001 | 0001 0011
@ -137,50 +91,12 @@ void set_16QAMtable(cf_t* table, srslte_soft_table_t *soft_table, bool compute_s
table[13] = -QAM16_LEVEL_1 - QAM16_LEVEL_2*_Complex_I;
table[14] = -QAM16_LEVEL_2 - QAM16_LEVEL_1*_Complex_I;
table[15] = -QAM16_LEVEL_2 - QAM16_LEVEL_2*_Complex_I;
for (i=0;i<6;i++) {
for (j=0;j<32;j++) {
soft_table->idx[0][i][j] = 0;
soft_table->idx[1][i][j] = 0;
}
}
if (!compute_soft_demod) {
return;
}
/* Matrices identifying the zeros and ones of LTE-16QAM constellation */
for (i=0;i<8;i++) {
soft_table->idx[0][0][i] = i; /* symbols with a '0' at the bit0 (leftmost)*/
soft_table->idx[1][0][i] = i+8; /* symbols with a '1' at the bit0 (leftmost)*/
}
/* symbols with a '0' ans '1' at the bit position 1: */
for (i=0;i<4;i++) {
soft_table->idx[0][1][i] = i;
soft_table->idx[0][1][i+4] = i+8;
soft_table->idx[1][1][i] = i+4;
soft_table->idx[1][1][i+4] = i+12;
}
/* symbols with a '0' ans '1' at the bit position 2: */
for (j=0;j<4;j++) {
for (i=0;i<2;i++) {
soft_table->idx[0][2][i+2*j] = i + 4*j;
soft_table->idx[1][2][i+2*j] = i+2 + 4*j;
}
}
/* symbols with a '0' ans '1' at the bit position 3: */
for (i=0;i<8;i++) {
soft_table->idx[0][3][i] = 2*i;
soft_table->idx[1][3][i] = 2*i+1;
}
LLR_approx_params(table, soft_table, 4); /* last param indication B (bits per symbol) */
}
/**
* Set the 64QAM modulation table */
void set_64QAMtable(cf_t* table, srslte_soft_table_t *soft_table, bool compute_soft_demod)
void set_64QAMtable(cf_t* table)
{
uint32_t i,j;
// LTE-64QAM constellation:
// see [3GPP TS 36.211 version 10.5.0 Release 10, Section 7.1.4]
table[0] = QAM64_LEVEL_2 + QAM64_LEVEL_2*_Complex_I;
@ -247,144 +163,5 @@ void set_64QAMtable(cf_t* table, srslte_soft_table_t *soft_table, bool compute_s
table[61] = -QAM64_LEVEL_3 - QAM64_LEVEL_4*_Complex_I;
table[62] = -QAM64_LEVEL_4 - QAM64_LEVEL_3*_Complex_I;
table[63] = -QAM64_LEVEL_4 - QAM64_LEVEL_4*_Complex_I;
if (!compute_soft_demod) {
return;
}
/* Matrices identifying the zeros and ones of LTE-64QAM constellation */
for (i=0;i<32;i++) {
soft_table->idx[0][0][i] = i; /* symbols with a '0' at the bit0 (leftmost)*/
soft_table->idx[1][0][i] = i+32; /* symbols with a '1' at the bit0 (leftmost)*/
}
/* symbols with a '0' ans '1' at the bit position 1: */
for (i=0;i<16;i++) {
soft_table->idx[0][1][i] = i;
soft_table->idx[0][1][i+16] = i+32;
soft_table->idx[1][1][i] = i+16;
soft_table->idx[1][1][i+16] = i+48;
}
/* symbols with a '0' ans '1' at the bit position 2: */
for (i=0;i<8;i++) {
soft_table->idx[0][2][i] = i;
soft_table->idx[0][2][i+8] = i+16;
soft_table->idx[0][2][i+16] = i+32;
soft_table->idx[0][2][i+24] = i+48;
soft_table->idx[1][2][i] = i+8;
soft_table->idx[1][2][i+8] = i+24;
soft_table->idx[1][2][i+16] = i+40;
soft_table->idx[1][2][i+24] = i+56;
}
/* symbols with a '0' ans '1' at the bit position 3: */
for (j=0;j<8;j++) {
for (i=0;i<4;i++) {
soft_table->idx[0][3][i+4*j] = i + 8*j;
soft_table->idx[1][3][i+4*j] = i+4 + 8*j;
}
}
/* symbols with a '0' ans '1' at the bit position 4: */
for (j=0;j<16;j++) {
for (i=0;i<2;i++) {
soft_table->idx[0][4][i+2*j] = i + 4*j;
soft_table->idx[1][4][i+2*j] = i+2 + 4*j;
}
}
/* symbols with a '0' ans '1' at the bit position 5: */
for (i=0;i<32;i++) {
soft_table->idx[0][5][i] = 2*i;
soft_table->idx[1][5][i] = 2*i+1;
}
LLR_approx_params(table, soft_table, 6); /* last param indication modulation */
}
/* Precompute two tables for calculating the distances based on the received symbol location relative to the constellation points */
void LLR_approx_params(const cf_t* table, srslte_soft_table_t *soft_table, int B) {
int i, j, b, k;
float x, y, d0, d1, min_d0, min_d1;
int M, D;
uint32_t min_idx0[64][6], min_idx1[64][6];
uint32_t count;
int flag;
D = B+1; /* number of different distances to be computed */
//M = pow(2,B); /* number of constellation points */
switch (B) {
case 1: {M = 2; break;} /* BPSK */
case 2: {M = 4; break;} /* QPSK */
case 4: {M = 16; break;} /* 16QAM */
case 6: {M = 64; break;} /* 64QAM */
default: {M = 4; break;} /* QPSK */
}
for (i=0;i<M;i++) { /* constellation points */
for (b=0;b<B;b++) { /* bits per symbol */
min_d0 = 100;
min_d1 = 100;
for (j=0;j<M/2;j++) { /* half the symbols have a '0', the other half a '1' at any bit position of modulation symbol */
x = __real__ table[i] - __real__ table[soft_table->idx[0][b][j]];
y = __imag__ table[i] - __imag__ table[soft_table->idx[0][b][j]];
d0 = x*x + y*y;
if (d0 < min_d0) {
min_d0 = d0;
min_idx0[i][b] = soft_table->idx[0][b][j];
}
x = __real__ table[i] - __real__ table[soft_table->idx[1][b][j]];
y = __imag__ table[i] - __imag__ table[soft_table->idx[1][b][j]];
d1 = x*x + y*y;
if (d1 < min_d1) {
min_d1 = d1;
min_idx1[i][b] = soft_table->idx[1][b][j];
}
}
}
}
for (i=0;i<M;i++) {
for (j=0;j<D;j++) {
soft_table->d_idx[i][j] = -1; /* intialization */
}
}
for (i=0;i<M;i++) {
count = 0;
for (b=0;b<B;b++) { /* bit(b) = 0 */
flag = 0;
for (k=0;k<count;k++) {
if (min_idx0[i][b] == soft_table->d_idx[i][k]) {
soft_table->min_idx[0][i][b] = k;
flag = 1; /* no new entry to idxdx */
break;
}
}
if (flag == 0) { /* new entry to min and d_idx */
soft_table->d_idx[i][count] = min_idx0[i][b];
soft_table->min_idx[0][i][b] = count;
count++;
}
}
for (b=0;b<B;b++) { /* bit(b) = 1 */
flag = 0;
for (k=0;k<count;k++) {
if (min_idx1[i][b] == soft_table->d_idx[i][k]) {
soft_table->min_idx[1][i][b] = k;
flag = 1; /* no new entry to d_idx */
break;
}
}
if (flag == 0) { /* new entry to min and d_idx */
soft_table->d_idx[i][count] = min_idx1[i][b];
soft_table->min_idx[1][i][b] = count;
count++;
}
}
}
}

View File

@ -38,12 +38,11 @@
#define QAM64_LEVEL_3 5/sqrt(42)
#define QAM64_LEVEL_4 7/sqrt(42)
//////////////// NUEVO //////////////////////
/* HARD DEMODULATION Thresholds, necessary for obtaining the zone of received symbol for optimized LLR approx implementation */
#define QAM16_THRESHOLD 2/sqrt(10)
#define QAM64_THRESHOLD_1 2/sqrt(42)
#define QAM64_THRESHOLD_2 4/sqrt(42)
#define QAM64_THRESHOLD_3 6/sqrt(42)
#define QAM16_THRESHOLD 2/sqrt(10)
#define QAM64_THRESHOLD_1 2/sqrt(42)
#define QAM64_THRESHOLD_2 4/sqrt(42)
#define QAM64_THRESHOLD_3 6/sqrt(42)
//=========================================//
#define QAM64_LEVEL_x 2/sqrt(42)
@ -53,18 +52,10 @@
void set_BPSKtable(cf_t* table,
srslte_soft_table_t *soft_table,
bool compute_soft_demod);
void set_BPSKtable(cf_t* table);
void set_QPSKtable(cf_t* table,
srslte_soft_table_t *soft_table,
bool compute_soft_demod);
void set_QPSKtable(cf_t* table);
void set_16QAMtable(cf_t* table,
srslte_soft_table_t *soft_table,
bool compute_soft_demod);
void set_16QAMtable(cf_t* table);
void set_64QAMtable(cf_t* table,
srslte_soft_table_t *soft_table,
bool compute_soft_demod);
void set_64QAMtable(cf_t* table);

View File

@ -157,7 +157,7 @@ int srslte_mod_modulate_bytes(srslte_modem_table_t* q, uint8_t *bits, cf_t* symb
/* High-Level API */
int mod_initialize(srslte_mod_hl* hl) {
srslte_modem_table_init(&hl->obj);
if (srslte_modem_table_lte(&hl->obj,hl->init.std,false)) {
if (srslte_modem_table_lte(&hl->obj,hl->init.std)) {
return -1;
}

View File

@ -67,7 +67,7 @@ void srslte_modem_table_reset(srslte_modem_table_t* q) {
srslte_modem_table_init(q);
}
int srslte_modem_table_set(srslte_modem_table_t* q, cf_t* table, srslte_soft_table_t *soft_table, uint32_t nsymbols, uint32_t nbits_x_symbol) {
int srslte_modem_table_set(srslte_modem_table_t* q, cf_t* table, uint32_t nsymbols, uint32_t nbits_x_symbol) {
if (q->nsymbols) {
return SRSLTE_ERROR;
}
@ -76,12 +76,11 @@ int srslte_modem_table_set(srslte_modem_table_t* q, cf_t* table, srslte_soft_tab
return SRSLTE_ERROR;
}
memcpy(q->symbol_table,table,q->nsymbols*sizeof(cf_t));
memcpy(&q->soft_table,soft_table,sizeof(srslte_soft_table_t));
q->nbits_x_symbol = nbits_x_symbol;
return SRSLTE_SUCCESS;
}
int srslte_modem_table_lte(srslte_modem_table_t* q, srslte_mod_t modulation, bool compute_soft_demod) {
int srslte_modem_table_lte(srslte_modem_table_t* q, srslte_mod_t modulation) {
srslte_modem_table_init(q);
switch(modulation) {
case SRSLTE_MOD_BPSK:
@ -90,7 +89,7 @@ int srslte_modem_table_lte(srslte_modem_table_t* q, srslte_mod_t modulation, boo
if (table_create(q)) {
return SRSLTE_ERROR;
}
set_BPSKtable(q->symbol_table, &q->soft_table, compute_soft_demod);
set_BPSKtable(q->symbol_table);
break;
case SRSLTE_MOD_QPSK:
q->nbits_x_symbol = 2;
@ -98,7 +97,7 @@ int srslte_modem_table_lte(srslte_modem_table_t* q, srslte_mod_t modulation, boo
if (table_create(q)) {
return SRSLTE_ERROR;
}
set_QPSKtable(q->symbol_table, &q->soft_table, compute_soft_demod);
set_QPSKtable(q->symbol_table);
break;
case SRSLTE_MOD_16QAM:
q->nbits_x_symbol = 4;
@ -106,7 +105,7 @@ int srslte_modem_table_lte(srslte_modem_table_t* q, srslte_mod_t modulation, boo
if (table_create(q)) {
return SRSLTE_ERROR;
}
set_16QAMtable(q->symbol_table, &q->soft_table, compute_soft_demod);
set_16QAMtable(q->symbol_table);
break;
case SRSLTE_MOD_64QAM:
q->nbits_x_symbol = 6;
@ -114,7 +113,7 @@ int srslte_modem_table_lte(srslte_modem_table_t* q, srslte_mod_t modulation, boo
if (table_create(q)) {
return SRSLTE_ERROR;
}
set_64QAMtable(q->symbol_table, &q->soft_table, compute_soft_demod);
set_64QAMtable(q->symbol_table);
break;
}
return SRSLTE_SUCCESS;

View File

@ -1,696 +0,0 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2015 The srsLTE Developers. See the
* COPYRIGHT file at the top-level directory of this distribution.
*
* \section LICENSE
*
* This file is part of the srsLTE library.
*
* srsLTE is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* srsLTE 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 Affero General Public License for more details.
*
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
#include <stdio.h>
#include <math.h>
#include <complex.h>
#include <stdint.h>
#include <string.h>
#include "soft_algs.h"
#include "srslte/utils/vector.h"
#define QAM16_THRESHOLD 2/sqrt(10)
#define QAM64_THRESHOLD_1 2/sqrt(42)
#define QAM64_THRESHOLD_2 4/sqrt(42)
#define QAM64_THRESHOLD_3 6/sqrt(42)
// There are 3 implemenations: 1 - based on zones; 2 - using volk, 3 - straightforward C
#define LLR_SRSLTE_DEMOD_SOFT_ALG_APPROX_IMPLEMENTATION 1
#if LLR_SRSLTE_DEMOD_SOFT_ALG_APPROX_IMPLEMENTATION == 1
/**
* @ingroup Received modulation symbol zone
* Determine location of received modulation symbol
*
* \param in input symbol (_Complex float)
* \param z associated zone in constellation diagram (int)
* \param N number of symbols
*/
static void zone_QPSK(const cf_t * in, uint32_t * z, int N)
{
int s;
float re, im;
for (s = 0; s < N; s++) {
re = __real__ in[s];
im = __imag__ in[s];
if (re > 0) {
if (im > 0) { /* 1st Quadrand (upper-right) */
z[s] = 0;
} else { /* 4th Quadrand (lower-right) */
z[s] = 1;
}
} else {
if (im > 0) { /* 2nd Quadrand (upper-left) */
z[s] = 2;
} else { /* 3rd Quadrand (lower-left) */
z[s] = 3;
}
}
}
}
/**
* @ingroup Received modulation symbol zone
* Determine location of received modulation symbol
*
* \param in input symbol (_Complex float)
* \param z associated zone in constellation diagram (int)
* \param N number of symbols
*/
static void zone_QAM16(const cf_t * in, uint32_t * z, int N)
{
int s;
float re, im;
for (s = 0; s < N; s++) {
re = __real__ in[s];
im = __imag__ in[s];
if (re > 0) {
if (im > 0) { /* 1st Quadrand (upper-right) */
if (re > QAM16_THRESHOLD) {
if (im > QAM16_THRESHOLD) {
z[s] = 3;
} else {
z[s] = 2;
}
} else {
if (im > QAM16_THRESHOLD) {
z[s] = 1;
} else {
z[s] = 0;
}
}
} else { /* 4th Quadrand (lower-right) */
if (re > QAM16_THRESHOLD) {
if (im < -QAM16_THRESHOLD) {
z[s] = 7;
} else {
z[s] = 6;
}
} else {
if (im < -QAM16_THRESHOLD) {
z[s] = 5;
} else {
z[s] = 4;
}
}
}
} else {
if (im > 0) { /* 2nd Quadrand (upper-left) */
if (re < -QAM16_THRESHOLD) {
if (im > QAM16_THRESHOLD) {
z[s] = 11;
} else {
z[s] = 10;
}
} else {
if (im > QAM16_THRESHOLD) {
z[s] = 9;
} else {
z[s] = 8;
}
}
} else { /* 3rd Quadrand (lower-left) */
if (re < -QAM16_THRESHOLD) {
if (im < -QAM16_THRESHOLD) {
z[s] = 15;
} else {
z[s] = 14;
}
} else {
if (im < -QAM16_THRESHOLD) {
z[s] = 13;
} else {
z[s] = 12;
}
}
}
}
}
}
/**
* @ingroup Received modulation symbol zone
* Determine location of received modulation symbol
*
* \param in input symbol (_Complex float)
* \param z associated zone in constellation diagram (int)
* \param N number of symbols
*/
static void zone_QAM64(const cf_t * in, uint32_t * z, int N)
{
int s;
float re, im;
for (s = 0; s < N; s++) {
re = __real__ in[s];
im = __imag__ in[s];
if (re > 0) {
if (im > 0) {
if (re > QAM64_THRESHOLD_2) {
if (re > QAM64_THRESHOLD_3) {
if (im > QAM64_THRESHOLD_2) {
if (im > QAM64_THRESHOLD_3) {
z[s] = 15;
} else {
z[s] = 14;
}
} else if (im > QAM64_THRESHOLD_1) {
z[s] = 10;
} else {
z[s] = 11;
}
} else {
if (im > QAM64_THRESHOLD_2) {
if (im > QAM64_THRESHOLD_3) {
z[s] = 13;
} else {
z[s] = 12;
}
} else if (im > QAM64_THRESHOLD_1) {
z[s] = 8;
} else {
z[s] = 9;
}
}
} else if (re > QAM64_THRESHOLD_1) {
if (im > QAM64_THRESHOLD_2) {
if (im > QAM64_THRESHOLD_3) {
z[s] = 5;
} else {
z[s] = 4;
}
} else if (im > QAM64_THRESHOLD_1) {
z[s] = 0;
} else {
z[s] = 1;
}
} else {
if (im > QAM64_THRESHOLD_2) {
if (im > QAM64_THRESHOLD_3) {
z[s] = 7;
} else {
z[s] = 6;
}
} else if (im > QAM64_THRESHOLD_1) {
z[s] = 2;
} else {
z[s] = 3;
}
}
} else { /* forth quadrant (lower-right) */
if (re > QAM64_THRESHOLD_2) {
if (re > QAM64_THRESHOLD_3) {
if (im < -QAM64_THRESHOLD_2) {
if (im < -QAM64_THRESHOLD_3) {
z[s] = 31;
} else {
z[s] = 30;
}
} else if (im < -QAM64_THRESHOLD_1) {
z[s] = 26;
} else {
z[s] = 27;
}
} else {
if (im < -QAM64_THRESHOLD_2) {
if (im < -QAM64_THRESHOLD_3) {
z[s] = 29;
} else {
z[s] = 28;
}
} else if (im < -QAM64_THRESHOLD_1) {
z[s] = 24;
} else {
z[s] = 25;
}
}
} else if (re > QAM64_THRESHOLD_1) {
if (im < -QAM64_THRESHOLD_2) {
if (im < -QAM64_THRESHOLD_3) {
z[s] = 21;
} else {
z[s] = 20;
}
} else if (im < -QAM64_THRESHOLD_1) {
z[s] = 16;
} else {
z[s] = 17;
}
} else {
if (im < -QAM64_THRESHOLD_2) {
if (im < -QAM64_THRESHOLD_3) {
z[s] = 23;
} else {
z[s] = 22;
}
} else if (im < -QAM64_THRESHOLD_1) {
z[s] = 18;
} else {
z[s] = 19;
}
}
}
} else { /* re < 0 */
if (im > 0) { /* second quadrant (upper-left) */
if (re < -QAM64_THRESHOLD_2) {
if (re < -QAM64_THRESHOLD_3) {
if (im > QAM64_THRESHOLD_2) {
if (im > QAM64_THRESHOLD_3) {
z[s] = 47;
} else {
z[s] = 46;
}
} else if (im > QAM64_THRESHOLD_1) {
z[s] = 42;
} else {
z[s] = 43;
}
} else {
if (im > QAM64_THRESHOLD_2) {
if (im > QAM64_THRESHOLD_3) {
z[s] = 45;
} else {
z[s] = 44;
}
} else if (im > QAM64_THRESHOLD_1) {
z[s] = 40;
} else {
z[s] = 41;
}
}
} else if (re < -QAM64_THRESHOLD_1) {
if (im > QAM64_THRESHOLD_2) {
if (im > QAM64_THRESHOLD_3) {
z[s] = 37;
} else {
z[s] = 36;
}
} else if (im > QAM64_THRESHOLD_1) {
z[s] = 32;
} else {
z[s] = 33;
}
} else {
if (im > QAM64_THRESHOLD_2) {
if (im > QAM64_THRESHOLD_3) {
z[s] = 39;
} else {
z[s] = 38;
}
} else if (im > QAM64_THRESHOLD_1) {
z[s] = 34;
} else {
z[s] = 35;
}
}
} else { /* third quadrant (lower-left) */
if (re < -QAM64_THRESHOLD_2) {
if (re < -QAM64_THRESHOLD_3) {
if (im < -QAM64_THRESHOLD_2) {
if (im < -QAM64_THRESHOLD_3) {
z[s] = 63;
} else {
z[s] = 62;
}
} else if (im < -QAM64_THRESHOLD_1) {
z[s] = 58;
} else {
z[s] = 59;
}
} else {
if (im < -QAM64_THRESHOLD_2) {
if (im < -QAM64_THRESHOLD_3) {
z[s] = 61;
} else {
z[s] = 60;
}
} else if (im < -QAM64_THRESHOLD_1) {
z[s] = 56;
} else {
z[s] = 57;
}
}
} else if (re < -QAM64_THRESHOLD_1) {
if (im < -QAM64_THRESHOLD_2) {
if (im < -QAM64_THRESHOLD_3) {
z[s] = 53;
} else {
z[s] = 52;
}
} else if (im < -QAM64_THRESHOLD_1) {
z[s] = 48;
} else {
z[s] = 49;
}
} else {
if (im < -QAM64_THRESHOLD_2) {
if (im < -QAM64_THRESHOLD_3) {
z[s] = 55;
} else {
z[s] = 54;
}
} else if (im < -QAM64_THRESHOLD_1) {
z[s] = 50;
} else {
z[s] = 51;
}
}
}
}
}
}
static void compute_zone(const cf_t * in, uint32_t * z, int N, int B)
{
switch (B) {
case 1:{
memset(z, 0, N * sizeof(uint32_t));
break;
} /* BPSK */
case 2:{
zone_QPSK(in, z, N);
break;
} /* QPSK */
case 4:{
zone_QAM16(in, z, N);
break;
} /* 16QAM */
case 6:{
zone_QAM64(in, z, N);
break;
} /* 64QAM */
}
}
static void compute_square_dist(uint32_t *zone, float *dd, const cf_t * in, cf_t * symbols,
uint32_t(*idx)[7], int N, int B)
{
int s, b;
float *d_ptr;
cf_t symbols_extract[7];
for (s = 0; s < N; s++) { /* N: number of received symbols */
d_ptr = &dd[7*s];
for (b = 0; b < B + 1; b++) {
symbols_extract[b] = symbols[idx[zone[s]][b]];
/* only subset of distances to constellation points needed for LLR approx */
}
srslte_vec_square_dist(in[s], symbols_extract, d_ptr, B + 1); /* B+1 distances to be computed */
}
}
static void compute_llr(uint32_t *zone, float *dd, int N, int B, uint32_t(*min)[64][6], float sigma2,
float *out)
{
int s, b;
for (s = 0; s < N; s++) {
for (b = 0; b < B; b++) { /* bits per symbol */
out[s * B + b] =
(dd[7*s+min[0][zone[s]][b]] - dd[7*s+min[1][zone[s]][b]]) / sigma2;
}
}
}
void llr_approx(const _Complex float *in, float *out, int N, int M, int B,
_Complex float *symbols, uint32_t(*S)[6][32], uint32_t(*idx)[7],
uint32_t(*min)[64][6], float sigma2, uint32_t *zone, float *dd)
{
if ((M == 1) || (M == 2) || (M == 4) || (M == 16) || (M == 64)) {
compute_zone(in, zone, N, B);
compute_square_dist(zone, dd, in, symbols, idx, N, B);
compute_llr(zone, dd, N, B, min, sigma2, out);
}
}
#elif LLR_SRSLTE_DEMOD_SOFT_ALG_APPROX_IMPLEMENTATION == 2
float d[10000][64];
float num[10000], den[10000];
static void compute_square_dist(const cf_t * in, cf_t * symbols, int N, int M)
{
int s;
float *d_ptr;
for (s = 0; s < N; s++) {
d_ptr = d[s];
srslte_vec_square_dist(in[s], symbols, d_ptr, M);
}
}
static void compute_min_dist(uint32_t(*S)[6][32], int N, int B, int M)
{
int s, b, i;
for (s = 0; s < N; s++) {
for (b = 0; b < B; b++) { /* bits per symbol */
/* initiate num[b] and den[b] */
num[s * B + b] = 1e10;
den[s * B + b] = 1e10;
for (i = 0; i < M / 2; i++) {
if (d[s][S[0][b][i]] < num[s * B + b]) {
num[s * B + b] = d[s][S[0][b][i]];
}
if (d[s][S[1][b][i]] < den[s * B + b]) {
den[s * B + b] = d[s][S[1][b][i]];
}
}
}
}
}
static void compute_llr(int N, int B, float sigma2, float *out)
{
int s, b;
for (s = 0; s < N; s++) {
for (b = 0; b < B; b++) { /* bits per symbol */
out[s * B + b] = (num[s * B + b] - den[s * B + b]) / sigma2;
}
}
}
void llr_approx(const _Complex float *in, float *out, int N, int M, int B,
_Complex float *symbols, uint32_t(*S)[6][32], float sigma2)
{
if (M <= 64) {
compute_square_dist(in, symbols, N, M);
compute_min_dist(S, N, B, M);
compute_llr(N, B, sigma2, out);
}
for (b = 0; b < B; b++) { /* bits per symbol */
out[s * B + b] = (num[s * B + b] - den[s * B + b]) / sigma2;
}
}
void llr_approx(const _Complex float *in, float *out, int N, int M, int B,
_Complex float *symbols, uint32_t(*S)[6][32], uint32_t(*idx)[7],
uint32_t(*min)[64][6], float sigma2)
{
if (M <= 64) {
compute_square_dist(in, symbols, N, M);
compute_min_dist(S, N, B, M);
compute_llr(N, B, sigma2, out);
}
}
#else
/**
* @ingroup Soft Modulation Demapping based on the approximate
* log-likelihood algorithm
* Common algorithm that approximates the log-likelihood ratio. It takes
* only the two closest constellation symbols into account, one with a '0'
* and the other with a '1' at the given bit position.
*
* \param in input symbols (_Complex float)
* \param out output symbols (float)
* \param N Number of input symbols
* \param M Number of constellation points
* \param B Number of bits per symbol
* \param symbols constellation symbols
* \param S Soft demapping auxiliary matrix
* \param sigma2 Noise vatiance
*/
void llr_approx(const _Complex float *in, float *out, int N, int M, int B,
_Complex float *symbols, uint32_t(*S)[6][32], uint32_t(*idx)[7],
uint32_t(*min)[64][6], float sigma2)
{
int i, s, b;
float num, den;
int change_sign = -1;
float x, y, d[64];
for (s = 0; s < N; s++) { /* recevied symbols */
/* Compute the distances squared d[i] between the received symbol and all constellation points */
for (i = 0; i < M; i++) {
x = __real__ in[s] - __real__ symbols[i];
y = __imag__ in[s] - __imag__ symbols[i];
d[i] = x * x + y * y;
}
for (b = 0; b < B; b++) { /* bits per symbol */
/* initiate num[b] and den[b] */
num = d[S[0][b][0]];
den = d[S[1][b][0]];
/* Minimum distance squared search between recevied symbol and a constellation point with a
'1' and a '0' for each bit position */
for (i = 1; i < M / 2; i++) { /* half the constellation points have '1'|'0' at any given bit position */
if (d[S[0][b][i]] < num) {
num = d[S[0][b][i]];
}
if (d[S[1][b][i]] < den) {
den = d[S[1][b][i]];
}
}
/* Theoretical LLR and approximate LLR values are positive if
* symbol(s) with '0' is/are closer and negative if symbol(s)
* with '1' are closer.
* Change sign if mapping negative to '0' and positive to '1' */
out[s * B + b] = change_sign * (den - num) / sigma2;
if (s < 10)
printf("out[%d]=%f=%f/%f\n", s * B + b, out[s * B + b], num, den);
}
/* if (s<10)
printf("out[%d]=%f=%f/%f\n",s*B+b,out[s*B+b], num,den);
*/ }
}
#endif
/**
* @ingroup Soft Modulation Demapping based on the approximate
* log-likelihood ratio algorithm
* Common algorithm that approximates the log-likelihood ratio. It takes
* only the two closest constellation symbols into account, one with a '0'
* and the other with a '1' at the given bit position.
*
* \param in input symbols (_Complex float)
* \param out output symbols (float)
* \param N Number of input symbols
* \param M Number of constellation points
* \param B Number of bits per symbol
* \param symbols constellation symbols
* \param S Soft demapping auxiliary matrix
* \param sigma2 Noise vatiance
*/
void llr_exact(const _Complex float *in, float *out, int N, int M, int B,
_Complex float *symbols, uint32_t(*S)[6][32], float sigma2)
{
int i, s, b;
float num, den;
int change_sign = -1;
float x, y, d[64];
for (s = 0; s < N; s++) { /* recevied symbols */
/* Compute exp{·} of the distances squared d[i] between the received symbol and all constellation points */
for (i = 0; i < M; i++) {
x = __real__ in[s] - __real__ symbols[i];
y = __imag__ in[s] - __imag__ symbols[i];
d[i] = exp(-1 * (x * x + y * y) / sigma2);
}
/* Sum up the corresponding d[i]'s for each bit position */
for (b = 0; b < B; b++) { /* bits per symbol */
/* initiate num[b] and den[b] */
num = 0;
den = 0;
for (i = 0; i < M / 2; i++) { /* half the constellation points have '1'|'0' at any given bit position */
num += d[S[0][b][i]];
den += d[S[1][b][i]];
}
/* Theoretical LLR and approximate LLR values are positive if
* symbol(s) with '0' is/are closer and negative if symbol(s)
* with '1' are closer.
* Change sign if mapping negative to '0' and positive to '1' */
out[s * B + b] = change_sign * log(num / den);
}
}
}

View File

@ -1,59 +0,0 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2015 The srsLTE Developers. See the
* COPYRIGHT file at the top-level directory of this distribution.
*
* \section LICENSE
*
* This file is part of the srsLTE library.
*
* srsLTE is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* srsLTE 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 Affero General Public License for more details.
*
* A copy of the GNU Affero General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
/*void llr_approx(const _Complex float *in,
float *out,
int N,
int M,
int B,
_Complex float *symbols,
uint32_t (*S)[6][32],
float sigma2);
*/
void llr_approx(const _Complex float *in,
float *out,
int N,
int M,
int B,
_Complex float *symbols,
uint32_t (*S)[6][32],
uint32_t (*idx)[7], /*64x7 table of integers [0..63], indices to 7 distances to be computed */
uint32_t (*min)[64][6], /*2x64x6 table of integers [0..6], indices to 2x6 nearest symbols */
float sigma2,
uint32_t *zone,
float *dd);
void llr_exact(const _Complex float *in,
float *out,
int N,
int M,
int B,
_Complex float *symbols,
uint32_t (*S)[6][32],
float sigma2);

View File

@ -31,18 +31,14 @@ ADD_TEST(modem_qpsk modem_test -n 1024 -m 2)
ADD_TEST(modem_qam16 modem_test -n 1024 -m 4)
ADD_TEST(modem_qam64 modem_test -n 1008 -m 6)
ADD_TEST(modem_bpsk_soft modem_test -n 1024 -m 1 -s)
ADD_TEST(modem_qpsk_soft modem_test -n 1024 -m 2 -s)
ADD_TEST(modem_qam16_soft modem_test -n 1024 -m 4 -s)
ADD_TEST(modem_qam64_soft modem_test -n 1008 -m 6 -s)
ADD_TEST(modem_bpsk_soft modem_test -n 1024 -m 1)
ADD_TEST(modem_qpsk_soft modem_test -n 1024 -m 2)
ADD_TEST(modem_qam16_soft modem_test -n 1024 -m 4)
ADD_TEST(modem_qam64_soft modem_test -n 1008 -m 6)
ADD_EXECUTABLE(soft_demod_test soft_demod_test.c)
TARGET_LINK_LIBRARIES(soft_demod_test srslte)
ADD_TEST(modem_bpsk_soft_approx soft_demod_test -n 1024 -m 1)
ADD_TEST(modem_qpsk_soft_approx soft_demod_test -n 1024 -m 2)
ADD_TEST(modem_qam16_soft_approx soft_demod_test -n 1024 -m 4)
ADD_TEST(modem_qam64_soft_approx soft_demod_test -n 1008 -m 6)

View File

@ -41,29 +41,20 @@ struct timeval x, y;
int num_bits = 1000;
srslte_mod_t modulation = SRSLTE_MOD_BPSK;
bool soft_output = true, soft_exact = false;
void usage(char *prog) {
printf("Usage: %s [nmse]\n", prog);
printf("\t-n num_bits [Default %d]\n", num_bits);
printf("\t-m modulation (1: BPSK, 2: QPSK, 3: QAM16, 4: QAM64) [Default BPSK]\n");
printf("\t-s soft outputs [Default %s]\n", soft_output?"soft":"hard");
printf("\t-e soft outputs exact algorithm [Default approx]\n");
printf("\t-m modulation (1: BPSK, 2: QPSK, 3: QAM16, 4: QAM64) [Default BPSK]\n");
}
void parse_args(int argc, char **argv) {
int opt;
while ((opt = getopt(argc, argv, "nmse")) != -1) {
while ((opt = getopt(argc, argv, "nm")) != -1) {
switch (opt) {
case 'n':
num_bits = atoi(argv[optind]);
break;
case 's':
soft_output = true;
break;
case 'e':
soft_exact = true;
break;
case 'm':
switch(atoi(argv[optind])) {
case 1:
@ -95,7 +86,6 @@ void parse_args(int argc, char **argv) {
int main(int argc, char **argv) {
int i;
srslte_modem_table_t mod;
srslte_demod_hard_t demod_hard;
uint8_t *input, *input_bytes, *output;
cf_t *symbols, *symbols_bytes;
float *llr, *llr2;
@ -103,7 +93,7 @@ int main(int argc, char **argv) {
parse_args(argc, argv);
/* initialize objects */
if (srslte_modem_table_lte(&mod, modulation, soft_output)) {
if (srslte_modem_table_lte(&mod, modulation)) {
fprintf(stderr, "Error initializing modem table\n");
exit(-1);
}
@ -116,11 +106,6 @@ int main(int argc, char **argv) {
exit(-1);
}
if (!soft_output) {
srslte_demod_hard_init(&demod_hard);
srslte_demod_hard_table_set(&demod_hard, modulation);
}
/* allocate buffers */
input = srslte_vec_malloc(sizeof(uint8_t) * num_bits);
if (!input) {
@ -196,18 +181,13 @@ int main(int argc, char **argv) {
}
printf("Symbols OK\n");
/* demodulate */
if (soft_output) {
gettimeofday(&x, NULL);
srslte_demod_soft_demodulate_lte(modulation, symbols, llr, num_bits / mod.nbits_x_symbol);
gettimeofday(&y, NULL);
printf("\nElapsed time [ns]: %d\n", (int) y.tv_usec - (int) x.tv_usec);
for (i=0;i<num_bits;i++) {
output[i] = llr[i]>=0 ? 1 : 0;
}
} else {
srslte_demod_hard_demodulate(&demod_hard, symbols, output, num_bits / mod.nbits_x_symbol);
gettimeofday(&x, NULL);
srslte_demod_soft_demodulate(modulation, symbols, llr, num_bits / mod.nbits_x_symbol);
gettimeofday(&y, NULL);
printf("\nElapsed time [ns]: %d\n", (int) y.tv_usec - (int) x.tv_usec);
for (i=0;i<num_bits;i++) {
output[i] = llr[i]>=0 ? 1 : 0;
}
/* check errors */

View File

@ -116,7 +116,7 @@ int main(int argc, char **argv) {
parse_args(argc, argv);
/* initialize objects */
if (srslte_modem_table_lte(&mod, modulation, true)) {
if (srslte_modem_table_lte(&mod, modulation)) {
fprintf(stderr, "Error initializing modem table\n");
exit(-1);
}
@ -162,7 +162,7 @@ int main(int argc, char **argv) {
srslte_mod_modulate(&mod, input, symbols, num_bits);
gettimeofday(&t[1], NULL);
srslte_demod_soft_demodulate_lte(modulation, symbols, llr, num_bits / mod.nbits_x_symbol);
srslte_demod_soft_demodulate(modulation, symbols, llr, num_bits / mod.nbits_x_symbol);
gettimeofday(&t[2], NULL);
get_time_interval(t);

View File

@ -156,7 +156,7 @@ int srslte_pbch_init(srslte_pbch_t *q, srslte_cell_t cell) {
fprintf(stderr, "Error initializing precoding\n");
}
if (srslte_modem_table_lte(&q->mod, SRSLTE_MOD_QPSK, true)) {
if (srslte_modem_table_lte(&q->mod, SRSLTE_MOD_QPSK)) {
goto clean;
}
if (srslte_sequence_pbch(&q->seq, q->cell.cp, q->cell.id)) {
@ -479,7 +479,7 @@ int srslte_pbch_decode(srslte_pbch_t *q, cf_t *slot1_symbols, cf_t *ce_slot1[SRS
}
/* demodulate symbols */
srslte_demod_soft_demodulate_lte(SRSLTE_MOD_QPSK, q->d, &q->llr[nof_bits * (q->frame_idx - 1)], q->nof_symbols);
srslte_demod_soft_demodulate(SRSLTE_MOD_QPSK, q->d, &q->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
* 4 frames, try 1,2,3,4 individually, 12, 23, 34 in pairs, 123, 234 and finally 1234.

View File

@ -79,7 +79,7 @@ int srslte_pcfich_init(srslte_pcfich_t *q, srslte_regs_t *regs, srslte_cell_t ce
fprintf(stderr, "Error initializing precoding\n");
}
if (srslte_modem_table_lte(&q->mod, SRSLTE_MOD_QPSK, true)) {
if (srslte_modem_table_lte(&q->mod, SRSLTE_MOD_QPSK)) {
goto clean;
}
@ -203,7 +203,7 @@ int srslte_pcfich_decode(srslte_pcfich_t *q, cf_t *slot_symbols, cf_t *ce[SRSLTE
}
/* demodulate symbols */
srslte_demod_soft_demodulate_lte(SRSLTE_MOD_QPSK, q->d, q->data_f, q->nof_symbols);
srslte_demod_soft_demodulate(SRSLTE_MOD_QPSK, q->d, q->data_f, q->nof_symbols);
/* Scramble with the sequence for slot nslot */
srslte_scrambling_f(&q->seq[nsubframe], q->data_f);

View File

@ -78,7 +78,7 @@ int srslte_pdcch_init(srslte_pdcch_t *q, srslte_regs_t *regs, srslte_cell_t cell
INFO("Init PDCCH: Max bits: %d, %d ports.\n",
q->max_bits, q->cell.nof_ports);
if (srslte_modem_table_lte(&q->mod, SRSLTE_MOD_QPSK, true)) {
if (srslte_modem_table_lte(&q->mod, SRSLTE_MOD_QPSK)) {
goto clean;
}
if (srslte_crc_init(&q->crc, SRSLTE_LTE_CRC16, 16)) {
@ -420,7 +420,7 @@ int srslte_pdcch_extract_llr(srslte_pdcch_t *q, cf_t *sf_symbols, cf_t *ce[SRSLT
}
/* demodulate symbols */
srslte_demod_soft_demodulate_lte(SRSLTE_MOD_QPSK, q->d, q->llr, nof_symbols);
srslte_demod_soft_demodulate(SRSLTE_MOD_QPSK, q->d, q->llr, nof_symbols);
/* descramble */
srslte_scrambling_f_offset(&q->seq[nsubframe], q->llr, 0, e_bits);

View File

@ -219,7 +219,7 @@ int srslte_pdsch_init(srslte_pdsch_t *q, srslte_cell_t cell) {
}
for (i = 0; i < 4; i++) {
if (srslte_modem_table_lte(&q->mod[i], modulations[i], true)) {
if (srslte_modem_table_lte(&q->mod[i], modulations[i])) {
goto clean;
}
srslte_modem_table_bytes(&q->mod[i]);
@ -417,7 +417,7 @@ int srslte_pdsch_decode_rnti(srslte_pdsch_t *q,
* The MAX-log-MAP algorithm used in turbo decoding is unsensitive to SNR estimation,
* thus we don't need tot set it in the LLRs normalization
*/
srslte_demod_soft_demodulate_lte(cfg->grant.mcs.mod, q->d, q->e, cfg->nbits.nof_re);
srslte_demod_soft_demodulate(cfg->grant.mcs.mod, q->d, q->e, cfg->nbits.nof_re);
/* descramble */
if (rnti != q->rnti) {
@ -535,4 +535,16 @@ int srslte_pdsch_encode_rnti(srslte_pdsch_t *q,
}
return ret;
}
float srslte_pdsch_average_noi(srslte_pdsch_t *q)
{
return q->dl_sch.average_nof_iterations;
}
uint32_t srslte_pdsch_last_noi(srslte_pdsch_t *q) {
return q->dl_sch.nof_iterations;
}

View File

@ -87,7 +87,7 @@ int srslte_phich_init(srslte_phich_t *q, srslte_regs_t *regs, srslte_cell_t cell
fprintf(stderr, "Error initializing precoding\n");
}
if (srslte_modem_table_lte(&q->mod, SRSLTE_MOD_BPSK, true)) {
if (srslte_modem_table_lte(&q->mod, SRSLTE_MOD_BPSK)) {
goto clean;
}
@ -274,7 +274,7 @@ int srslte_phich_decode(srslte_phich_t *q, cf_t *slot_symbols, cf_t *ce[SRSLTE_M
if (SRSLTE_VERBOSE_ISDEBUG())
srslte_vec_fprint_c(stdout, q->z, SRSLTE_PHICH_NBITS);
srslte_demod_soft_demodulate_lte(SRSLTE_MOD_BPSK, q->z, q->data_rx, SRSLTE_PHICH_NBITS);
srslte_demod_soft_demodulate(SRSLTE_MOD_BPSK, q->z, q->data_rx, SRSLTE_PHICH_NBITS);
if (ack) {
*ack = srslte_phich_ack_decode(q->data_rx, distance);

View File

@ -329,7 +329,7 @@ int srslte_pucch_init(srslte_pucch_t *q, srslte_cell_t cell) {
srslte_pucch_cfg_default(&q->pucch_cfg);
if (srslte_modem_table_lte(&q->mod, SRSLTE_MOD_QPSK, false)) {
if (srslte_modem_table_lte(&q->mod, SRSLTE_MOD_QPSK)) {
return SRSLTE_ERROR;
}

View File

@ -200,7 +200,7 @@ int srslte_pusch_init(srslte_pusch_t *q, srslte_cell_t cell) {
q->cell.nof_prb, q->max_re);
for (i = 0; i < 4; i++) {
if (srslte_modem_table_lte(&q->mod[i], modulations[i], true)) {
if (srslte_modem_table_lte(&q->mod[i], modulations[i])) {
goto clean;
}
srslte_modem_table_bytes(&q->mod[i]);
@ -447,7 +447,7 @@ int srslte_pusch_decode(srslte_pusch_t *q,
* The MAX-log-MAP algorithm used in turbo decoding is unsensitive to SNR estimation,
* thus we don't need tot set it in the LLRs normalization
*/
srslte_demod_soft_demodulate_lte(cfg->grant.mcs.mod, q->d, q->q, cfg->nbits.nof_re);
srslte_demod_soft_demodulate(cfg->grant.mcs.mod, q->d, q->q, cfg->nbits.nof_re);
/* descramble */
srslte_scrambling_f_offset(&q->seq[cfg->sf_idx], q->q, 0, cfg->nbits.nof_bits);

View File

@ -228,6 +228,7 @@ int srslte_ra_ul_dci_to_grant(srslte_ra_ul_dci_t *dci, uint32_t nof_prb, uint32_
if (!ul_dci_to_grant_mcs(dci, grant)) {
// Fill rest of grant structure
grant->mcs.idx = dci->mcs_idx;
grant->M_sc = grant->L_prb*SRSLTE_NRE;
grant->M_sc_init = grant->M_sc; // FIXME: What should M_sc_init be?
grant->Qm = srslte_mod_bits_x_symbol(grant->mcs.mod);
@ -455,6 +456,7 @@ int srslte_ra_dl_dci_to_grant(srslte_ra_dl_dci_t *dci, uint32_t nof_prb, bool cr
// Compute MCS
if (!dl_dci_to_grant_mcs(dci, grant, crc_is_crnti)) {
// Fill rest of grant structure
grant->mcs.idx = dci->mcs_idx;
grant->Qm = srslte_mod_bits_x_symbol(grant->mcs.mod);
} else {
return SRSLTE_ERROR;