mirror of https://github.com/PentHertz/srsLTE.git
Removed old soft demodulation algorithm. Removed hl/ll examples. Removed prach_ue example.
This commit is contained in:
parent
cc1623f1cd
commit
5e3f577e97
|
@ -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)
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -50,6 +50,7 @@
|
|||
typedef struct SRSLTE_API {
|
||||
srslte_mod_t mod;
|
||||
int tbs;
|
||||
uint32_t idx;
|
||||
} srslte_ra_mcs_t;
|
||||
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
|
|
@ -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)
|
||||
|
||||
|
||||
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in New Issue