Merge branch 'next' of github.com:softwareradiosystems/srsLTE into next

master
Pedro Alvarez 7 years ago
commit 06180a38ef

@ -84,6 +84,8 @@ int mbsfn_area_id = -1;
char *rf_args = ""; char *rf_args = "";
float rf_amp = 0.8, rf_gain = 70.0, rf_freq = 2400000000; float rf_amp = 0.8, rf_gain = 70.0, rf_freq = 2400000000;
float output_file_snr = +INFINITY;
bool null_file_sink=false; bool null_file_sink=false;
srslte_filesink_t fsink; srslte_filesink_t fsink;
srslte_ofdm_t ifft[SRSLTE_MAX_PORTS]; srslte_ofdm_t ifft[SRSLTE_MAX_PORTS];
@ -145,13 +147,14 @@ void usage(char *prog) {
printf("\t-w Number of codewords/layers (multiplex mode only)* [Default %d]\n", multiplex_nof_layers); printf("\t-w Number of codewords/layers (multiplex mode only)* [Default %d]\n", multiplex_nof_layers);
printf("\t-u listen TCP port for input data (-1 is random) [Default %d]\n", net_port); printf("\t-u listen TCP port for input data (-1 is random) [Default %d]\n", net_port);
printf("\t-v [set srslte_verbose to debug, default none]\n"); printf("\t-v [set srslte_verbose to debug, default none]\n");
printf("\t-s output file SNR [Default %f]\n", output_file_snr);
printf("\n"); printf("\n");
printf("\t*: See 3GPP 36.212 Table 5.3.3.1.5-4 for more information\n"); printf("\t*: See 3GPP 36.212 Table 5.3.3.1.5-4 for more information\n");
} }
void parse_args(int argc, char **argv) { void parse_args(int argc, char **argv) {
int opt; int opt;
while ((opt = getopt(argc, argv, "aglfmoncpvutxbwM")) != -1) { while ((opt = getopt(argc, argv, "aglfmoncpvutxbwMs")) != -1) {
switch (opt) { switch (opt) {
case 'a': case 'a':
@ -200,6 +203,9 @@ void parse_args(int argc, char **argv) {
case 'v': case 'v':
srslte_verbose++; srslte_verbose++;
break; break;
case 's':
output_file_snr = atof(argv[optind]);
break;
default: default:
usage(argv[0]); usage(argv[0]);
exit(-1); exit(-1);
@ -989,7 +995,14 @@ int main(int argc, char **argv) {
/* send to file or usrp */ /* send to file or usrp */
if (output_file_name) { if (output_file_name) {
if (!null_file_sink) { if (!null_file_sink) {
srslte_filesink_write_multi(&fsink, (void**) output_buffer, sf_n_samples, cell.nof_ports); /* Apply AWGN */
if (output_file_snr != +INFINITY) {
float var = powf(10.0f, -(output_file_snr + 3.0f) / 20.0f);
for (int k = 0; k < cell.nof_ports; k++) {
srslte_ch_awgn_c(output_buffer[k], output_buffer[k], var, sf_n_samples);
}
}
srslte_filesink_write_multi(&fsink, (void**) output_buffer, sf_n_samples, cell.nof_ports);
} }
usleep(1000); usleep(1000);
} else { } else {

@ -164,6 +164,7 @@ public:
} }
b->reset(); b->reset();
pool->deallocate(b); pool->deallocate(b);
b = NULL;
} }
private: private:
buffer_pool<byte_buffer_t> *pool; buffer_pool<byte_buffer_t> *pool;

@ -42,7 +42,10 @@ namespace srslte {
{ {
public: public:
void log(std::string *msg) { void log(std::string *msg) {
fprintf(stdout, "%s", msg->c_str()); if (msg) {
fprintf(stdout, "%s", msg->c_str());
delete msg;
}
} }
}; };

@ -492,6 +492,7 @@ typedef struct {
float estimator_fil_w; float estimator_fil_w;
bool rssi_sensor_enabled; bool rssi_sensor_enabled;
bool sic_pss_enabled; bool sic_pss_enabled;
float rx_gain_offset;
} phy_args_t; } phy_args_t;

@ -42,8 +42,8 @@
#include "srslte/config.h" #include "srslte/config.h"
#define SRSLTE_AGC_DEFAULT_TARGET 0.7 #define SRSLTE_AGC_DEFAULT_TARGET 0.3
#define SRSLTE_AGC_DEFAULT_BW (5e-1) #define SRSLTE_AGC_DEFAULT_BW 0.7
typedef enum SRSLTE_API { typedef enum SRSLTE_API {
SRSLTE_AGC_MODE_ENERGY = 0, SRSLTE_AGC_MODE_ENERGY = 0,

@ -120,6 +120,8 @@ SRSLTE_API void srslte_vec_abs_square_cf_simd(const cf_t *x, float *z, const int
/* Other Functions */ /* Other Functions */
SRSLTE_API void srslte_vec_lut_sss_simd(const short *x, const unsigned short *lut, short *y, const int len); SRSLTE_API void srslte_vec_lut_sss_simd(const short *x, const unsigned short *lut, short *y, const int len);
SRSLTE_API void srslte_vec_convert_if_simd(const int16_t *x, float *z, const float scale, const int len);
SRSLTE_API void srslte_vec_convert_fi_simd(const float *x, int16_t *z, const float scale, const int len); SRSLTE_API void srslte_vec_convert_fi_simd(const float *x, int16_t *z, const float scale, const int len);
SRSLTE_API void srslte_vec_cp_simd(const cf_t *src, cf_t *dst, int len); SRSLTE_API void srslte_vec_cp_simd(const cf_t *src, cf_t *dst, int len);

@ -71,6 +71,7 @@ class rlc_am
{ {
public: public:
rlc_am(); rlc_am();
~rlc_am();
void init(log *rlc_entity_log_, void init(log *rlc_entity_log_,
uint32_t lcid_, uint32_t lcid_,
srsue::pdcp_interface_rlc *pdcp_, srsue::pdcp_interface_rlc *pdcp_,

@ -50,6 +50,7 @@ class rlc_um
{ {
public: public:
rlc_um(); rlc_um();
~rlc_um();
void init(log *rlc_entity_log_, void init(log *rlc_entity_log_,
uint32_t lcid_, uint32_t lcid_,

@ -54,7 +54,7 @@ void logger_file::init(std::string file, int max_length_) {
pthread_mutex_init(&mutex, NULL); pthread_mutex_init(&mutex, NULL);
pthread_cond_init(&not_empty, NULL); pthread_cond_init(&not_empty, NULL);
pthread_cond_init(&not_full, NULL); pthread_cond_init(&not_full, NULL);
max_length = max_length_*1024; max_length = (int64_t)max_length_*1024;
name_idx = 0; name_idx = 0;
filename = file; filename = file;
logfile = fopen(filename.c_str(), "w"); logfile = fopen(filename.c_str(), "w");

@ -177,7 +177,7 @@ void srslte_agc_process(srslte_agc_t *q, cf_t *signal, uint32_t len) {
gg = expf(-0.5*q->bandwidth*logf(q->y_out/q->target)); gg = expf(-0.5*q->bandwidth*logf(q->y_out/q->target));
q->gain *= gg; q->gain *= gg;
} }
DEBUG("AGC gain: %.2f (%.2f) y_out=%.3f, y=%.3f target=%.1f gg=%.2f\n", gain_db, gain_uhd_db, q->y_out, y, q->target, gg); INFO("AGC gain: %.2f (%.2f) y_out=%.3f, y=%.3f target=%.1f gg=%.2f\n", gain_db, gain_uhd_db, q->y_out, y, q->target, gg);
} }
} }
} }

@ -291,7 +291,7 @@ static float estimate_noise_pilots(srslte_chest_dl_t *q, uint32_t port_id, srslt
norm /= norm3; norm /= norm3;
} }
} }
float power = norm*q->cell.nof_ports*srslte_vec_avg_power_cf(q->tmp_noise, nref); float power = norm*srslte_vec_avg_power_cf(q->tmp_noise, nref);
return power; return power;
} }
@ -543,7 +543,7 @@ void chest_interpolate_noise_est(srslte_chest_dl_t *q, cf_t *input, cf_t *ce, ui
/* Compute RSRP for the channel estimates in this port */ /* Compute RSRP for the channel estimates in this port */
uint32_t npilots = SRSLTE_REFSIGNAL_NUM_SF(q->cell.nof_prb, port_id); uint32_t npilots = SRSLTE_REFSIGNAL_NUM_SF(q->cell.nof_prb, port_id);
q->rsrp[rxant_id][port_id] = __real__ srslte_vec_dot_prod_conj_ccc(q->pilot_estimates, q->pilot_estimates, npilots) / npilots; q->rsrp[rxant_id][port_id] = srslte_vec_avg_power_cf(q->pilot_estimates, npilots);
q->rssi[rxant_id][port_id] = srslte_chest_dl_rssi(q, input, port_id); q->rssi[rxant_id][port_id] = srslte_chest_dl_rssi(q, input, port_id);
} }
@ -639,7 +639,10 @@ float srslte_chest_dl_get_noise_estimate(srslte_chest_dl_t *q) {
for (int i=0;i<q->last_nof_antennas;i++) { for (int i=0;i<q->last_nof_antennas;i++) {
n += srslte_vec_acc_ff(q->noise_estimate[i], q->cell.nof_ports)/q->cell.nof_ports; n += srslte_vec_acc_ff(q->noise_estimate[i], q->cell.nof_ports)/q->cell.nof_ports;
} }
return n/q->last_nof_antennas; if (q->last_nof_antennas) {
n /= q->last_nof_antennas;
}
return n;
} }
float srslte_chest_dl_get_snr(srslte_chest_dl_t *q) { float srslte_chest_dl_get_snr(srslte_chest_dl_t *q) {
@ -691,14 +694,25 @@ float srslte_chest_dl_get_rsrp_ant_port(srslte_chest_dl_t *q, uint32_t ant_idx,
} }
float srslte_chest_dl_get_rsrp_port(srslte_chest_dl_t *q, uint32_t port) { float srslte_chest_dl_get_rsrp_port(srslte_chest_dl_t *q, uint32_t port) {
float n = 0; float sum = 0.0f;
for (int i = 0; i < q->last_nof_antennas; i++) { for (int j = 0; j < q->cell.nof_ports; ++j) {
n += q->rsrp[i][port]; sum +=q->rsrp[port][j];
}
if (q->cell.nof_ports) {
sum /= q->cell.nof_ports;
} }
return n / q->last_nof_antennas;
return sum;
} }
float srslte_chest_dl_get_rsrp(srslte_chest_dl_t *q) { float srslte_chest_dl_get_rsrp(srslte_chest_dl_t *q) {
// Note: use only port 0 but average across antennas float max = -0.0f;
return srslte_chest_dl_get_rsrp_port(q, 0); for (int i = 0; i < q->last_nof_antennas; ++i) {
float v = srslte_chest_dl_get_rsrp_port(q, i);
if (v > max) {
max = v;
}
}
return max;
} }

@ -166,9 +166,15 @@ void free37_avx2_16bit(void *o) {
if (q->symbols_uc) { if (q->symbols_uc) {
free(q->symbols_uc); free(q->symbols_uc);
} }
if (q->symbols_us) {
free(q->symbols_us);
}
if (q->tmp) { if (q->tmp) {
free(q->tmp); free(q->tmp);
} }
if (q->tmp_s) {
free(q->tmp_s);
}
delete_viterbi37_avx2_16bit(q->ptr); delete_viterbi37_avx2_16bit(q->ptr);
} }

@ -57,132 +57,131 @@ float save_corr[4096];
uint32_t prach_Tcp[5] = {3168, 21024, 6240, 21024, 448}; uint32_t prach_Tcp[5] = {3168, 21024, 6240, 21024, 448};
// Table 5.7.1-1 T_seq for preamble formats // Table 5.7.1-1 T_seq for preamble formats
uint32_t prach_Tseq[5] = {24576, 24576, 2*24576, 2*24576, 4096}; uint32_t prach_Tseq[5] = {24576, 24576, 2 * 24576, 2 * 24576, 4096};
// Table 5.7.2-2 - N_cs values for unrestricted sets // Table 5.7.2-2 - N_cs values for unrestricted sets
uint32_t prach_Ncs_unrestricted[16] = {0,13,15,18,22,26,32,38,46,59,76,93,119,167,279,419}; uint32_t prach_Ncs_unrestricted[16] = {0, 13, 15, 18, 22, 26, 32, 38, 46, 59, 76, 93, 119, 167, 279, 419};
#define MAX_N_zc 839 #define MAX_N_zc 839
// Table 5.7.2-2 - N_cs values for restricted sets // Table 5.7.2-2 - N_cs values for restricted sets
uint32_t prach_Ncs_restricted[15] = {15,18,22,26,32,38,46,55,68,82,100,128,158,202,237}; uint32_t prach_Ncs_restricted[15] = {15, 18, 22, 26, 32, 38, 46, 55, 68, 82, 100, 128, 158, 202, 237};
// Table 5.7.2-3 - N_cs values for preamble format 4 // Table 5.7.2-3 - N_cs values for preamble format 4
uint32_t prach_Ncs_format4[7] = {2,4,6,8,10,12,15}; uint32_t prach_Ncs_format4[7] = {2, 4, 6, 8, 10, 12, 15};
// Table 5.7.2-4 - Root ZC sequence order // Table 5.7.2-4 - Root ZC sequence order
uint32_t prach_zc_roots[838] = { uint32_t prach_zc_roots[838] = {
129, 710, 140, 699, 120, 719, 210, 629, 168, 671, 84, 755, 129, 710, 140, 699, 120, 719, 210, 629, 168, 671, 84, 755,
105, 734, 93, 746, 70, 769, 60, 779, 2, 837, 1, 838, 105, 734, 93, 746, 70, 769, 60, 779, 2, 837, 1, 838,
56, 783, 112, 727, 148, 691, 80, 759, 42, 797, 40, 799, 56, 783, 112, 727, 148, 691, 80, 759, 42, 797, 40, 799,
35, 804, 73, 766, 146, 693, 31, 808, 28, 811, 30, 809, 35, 804, 73, 766, 146, 693, 31, 808, 28, 811, 30, 809,
27, 812, 29, 810, 24, 815, 48, 791, 68, 771, 74, 765, 27, 812, 29, 810, 24, 815, 48, 791, 68, 771, 74, 765,
178, 661, 136, 703, 86, 753, 78, 761, 43, 796, 39, 800, 178, 661, 136, 703, 86, 753, 78, 761, 43, 796, 39, 800,
20, 819, 21, 818, 95, 744, 202, 637, 190, 649, 181, 658, 20, 819, 21, 818, 95, 744, 202, 637, 190, 649, 181, 658,
137, 702, 125, 714, 151, 688, 217, 622, 128, 711, 142, 697, 137, 702, 125, 714, 151, 688, 217, 622, 128, 711, 142, 697,
122, 717, 203, 636, 118, 721, 110, 729, 89, 750, 103, 736, 122, 717, 203, 636, 118, 721, 110, 729, 89, 750, 103, 736,
61, 778, 55, 784, 15, 824, 14, 825, 12, 827, 23, 816, 61, 778, 55, 784, 15, 824, 14, 825, 12, 827, 23, 816,
34, 805, 37, 802, 46, 793, 207, 632, 179, 660, 145, 694, 34, 805, 37, 802, 46, 793, 207, 632, 179, 660, 145, 694,
130, 709, 223, 616, 228, 611, 227, 612, 132, 707, 133, 706, 130, 709, 223, 616, 228, 611, 227, 612, 132, 707, 133, 706,
143, 696, 135, 704, 161, 678, 201, 638, 173, 666, 106, 733, 143, 696, 135, 704, 161, 678, 201, 638, 173, 666, 106, 733,
83, 756, 91, 748, 66, 773, 53, 786, 10, 829, 9, 830, 83, 756, 91, 748, 66, 773, 53, 786, 10, 829, 9, 830,
7, 832, 8, 831, 16, 823, 47, 792, 64, 775, 57, 782, 7, 832, 8, 831, 16, 823, 47, 792, 64, 775, 57, 782,
104, 735, 101, 738, 108, 731, 208, 631, 184, 655, 197, 642, 104, 735, 101, 738, 108, 731, 208, 631, 184, 655, 197, 642,
191, 648, 121, 718, 141, 698, 149, 690, 216, 623, 218, 621, 191, 648, 121, 718, 141, 698, 149, 690, 216, 623, 218, 621,
152, 687, 144, 695, 134, 705, 138, 701, 199, 640, 162, 677, 152, 687, 144, 695, 134, 705, 138, 701, 199, 640, 162, 677,
176, 663, 119, 720, 158, 681, 164, 675, 174, 665, 171, 668, 176, 663, 119, 720, 158, 681, 164, 675, 174, 665, 171, 668,
170, 669, 87, 752, 169, 670, 88, 751, 107, 732, 81, 758, 170, 669, 87, 752, 169, 670, 88, 751, 107, 732, 81, 758,
82, 757, 100, 739, 98, 741, 71, 768, 59, 780, 65, 774, 82, 757, 100, 739, 98, 741, 71, 768, 59, 780, 65, 774,
50, 789, 49, 790, 26, 813, 17, 822, 13, 826, 6, 833, 50, 789, 49, 790, 26, 813, 17, 822, 13, 826, 6, 833,
5, 834, 33, 806, 51, 788, 75, 764, 99, 740, 96, 743, 5, 834, 33, 806, 51, 788, 75, 764, 99, 740, 96, 743,
97, 742, 166, 673, 172, 667, 175, 664, 187, 652, 163, 676, 97, 742, 166, 673, 172, 667, 175, 664, 187, 652, 163, 676,
185, 654, 200, 639, 114, 725, 189, 650, 115, 724, 194, 645, 185, 654, 200, 639, 114, 725, 189, 650, 115, 724, 194, 645,
195, 644, 192, 647, 182, 657, 157, 682, 156, 683, 211, 628, 195, 644, 192, 647, 182, 657, 157, 682, 156, 683, 211, 628,
154, 685, 123, 716, 139, 700, 212, 627, 153, 686, 213, 626, 154, 685, 123, 716, 139, 700, 212, 627, 153, 686, 213, 626,
215, 624, 150, 689, 225, 614, 224, 615, 221, 618, 220, 619, 215, 624, 150, 689, 225, 614, 224, 615, 221, 618, 220, 619,
127, 712, 147, 692, 124, 715, 193, 646, 205, 634, 206, 633, 127, 712, 147, 692, 124, 715, 193, 646, 205, 634, 206, 633,
116, 723, 160, 679, 186, 653, 167, 672, 79, 760, 85, 754, 116, 723, 160, 679, 186, 653, 167, 672, 79, 760, 85, 754,
77, 762, 92, 747, 58, 781, 62, 777, 69, 770, 54, 785, 77, 762, 92, 747, 58, 781, 62, 777, 69, 770, 54, 785,
36, 803, 32, 807, 25, 814, 18, 821, 11, 828, 4, 835, 36, 803, 32, 807, 25, 814, 18, 821, 11, 828, 4, 835,
3, 836, 19, 820, 22, 817, 41, 798, 38, 801, 44, 795, 3, 836, 19, 820, 22, 817, 41, 798, 38, 801, 44, 795,
52, 787, 45, 794, 63, 776, 67, 772, 72, 767, 76, 763, 52, 787, 45, 794, 63, 776, 67, 772, 72, 767, 76, 763,
94, 745, 102, 737, 90, 749, 109, 730, 165, 674, 111, 728, 94, 745, 102, 737, 90, 749, 109, 730, 165, 674, 111, 728,
209, 630, 204, 635, 117, 722, 188, 651, 159, 680, 198, 641, 209, 630, 204, 635, 117, 722, 188, 651, 159, 680, 198, 641,
113, 726, 183, 656, 180, 659, 177, 662, 196, 643, 155, 684, 113, 726, 183, 656, 180, 659, 177, 662, 196, 643, 155, 684,
214, 625, 126, 713, 131, 708, 219, 620, 222, 617, 226, 613, 214, 625, 126, 713, 131, 708, 219, 620, 222, 617, 226, 613,
230, 609, 232, 607, 262, 577, 252, 587, 418, 421, 416, 423, 230, 609, 232, 607, 262, 577, 252, 587, 418, 421, 416, 423,
413, 426, 411, 428, 376, 463, 395, 444, 283, 556, 285, 554, 413, 426, 411, 428, 376, 463, 395, 444, 283, 556, 285, 554,
379, 460, 390, 449, 363, 476, 384, 455, 388, 451, 386, 453, 379, 460, 390, 449, 363, 476, 384, 455, 388, 451, 386, 453,
361, 478, 387, 452, 360, 479, 310, 529, 354, 485, 328, 511, 361, 478, 387, 452, 360, 479, 310, 529, 354, 485, 328, 511,
315, 524, 337, 502, 349, 490, 335, 504, 324, 515, 323, 516, 315, 524, 337, 502, 349, 490, 335, 504, 324, 515, 323, 516,
320, 519, 334, 505, 359, 480, 295, 544, 385, 454, 292, 547, 320, 519, 334, 505, 359, 480, 295, 544, 385, 454, 292, 547,
291, 548, 381, 458, 399, 440, 380, 459, 397, 442, 369, 470, 291, 548, 381, 458, 399, 440, 380, 459, 397, 442, 369, 470,
377, 462, 410, 429, 407, 432, 281, 558, 414, 425, 247, 592, 377, 462, 410, 429, 407, 432, 281, 558, 414, 425, 247, 592,
277, 562, 271, 568, 272, 567, 264, 575, 259, 580, 237, 602, 277, 562, 271, 568, 272, 567, 264, 575, 259, 580, 237, 602,
239, 600, 244, 595, 243, 596, 275, 564, 278, 561, 250, 589, 239, 600, 244, 595, 243, 596, 275, 564, 278, 561, 250, 589,
246, 593, 417, 422, 248, 591, 394, 445, 393, 446, 370, 469, 246, 593, 417, 422, 248, 591, 394, 445, 393, 446, 370, 469,
365, 474, 300, 539, 299, 540, 364, 475, 362, 477, 298, 541, 365, 474, 300, 539, 299, 540, 364, 475, 362, 477, 298, 541,
312, 527, 313, 526, 314, 525, 353, 486, 352, 487, 343, 496, 312, 527, 313, 526, 314, 525, 353, 486, 352, 487, 343, 496,
327, 512, 350, 489, 326, 513, 319, 520, 332, 507, 333, 506, 327, 512, 350, 489, 326, 513, 319, 520, 332, 507, 333, 506,
348, 491, 347, 492, 322, 517, 330, 509, 338, 501, 341, 498, 348, 491, 347, 492, 322, 517, 330, 509, 338, 501, 341, 498,
340, 499, 342, 497, 301, 538, 366, 473, 401, 438, 371, 468, 340, 499, 342, 497, 301, 538, 366, 473, 401, 438, 371, 468,
408, 431, 375, 464, 249, 590, 269, 570, 238, 601, 234, 605, 408, 431, 375, 464, 249, 590, 269, 570, 238, 601, 234, 605,
257, 582, 273, 566, 255, 584, 254, 585, 245, 594, 251, 588, 257, 582, 273, 566, 255, 584, 254, 585, 245, 594, 251, 588,
412, 427, 372, 467, 282, 557, 403, 436, 396, 443, 392, 447, 412, 427, 372, 467, 282, 557, 403, 436, 396, 443, 392, 447,
391, 448, 382, 457, 389, 450, 294, 545, 297, 542, 311, 528, 391, 448, 382, 457, 389, 450, 294, 545, 297, 542, 311, 528,
344, 495, 345, 494, 318, 521, 331, 508, 325, 514, 321, 518, 344, 495, 345, 494, 318, 521, 331, 508, 325, 514, 321, 518,
346, 493, 339, 500, 351, 488, 306, 533, 289, 550, 400, 439, 346, 493, 339, 500, 351, 488, 306, 533, 289, 550, 400, 439,
378, 461, 374, 465, 415, 424, 270, 569, 241, 598, 231, 608, 378, 461, 374, 465, 415, 424, 270, 569, 241, 598, 231, 608,
260, 579, 268, 571, 276, 563, 409, 430, 398, 441, 290, 549, 260, 579, 268, 571, 276, 563, 409, 430, 398, 441, 290, 549,
304, 535, 308, 531, 358, 481, 316, 523, 293, 546, 288, 551, 304, 535, 308, 531, 358, 481, 316, 523, 293, 546, 288, 551,
284, 555, 368, 471, 253, 586, 256, 583, 263, 576, 242, 597, 284, 555, 368, 471, 253, 586, 256, 583, 263, 576, 242, 597,
274, 565, 402, 437, 383, 456, 357, 482, 329, 510, 317, 522, 274, 565, 402, 437, 383, 456, 357, 482, 329, 510, 317, 522,
307, 532, 286, 553, 287, 552, 266, 573, 261, 578, 236, 603, 307, 532, 286, 553, 287, 552, 266, 573, 261, 578, 236, 603,
303, 536, 356, 483, 355, 484, 405, 434, 404, 435, 406, 433, 303, 536, 356, 483, 355, 484, 405, 434, 404, 435, 406, 433,
235, 604, 267, 572, 302, 537, 309, 530, 265, 574, 233, 606, 235, 604, 267, 572, 302, 537, 309, 530, 265, 574, 233, 606,
367, 472, 296, 543, 336, 503, 305, 534, 373, 466, 280, 559, 367, 472, 296, 543, 336, 503, 305, 534, 373, 466, 280, 559,
279, 560, 419, 420, 240, 599, 258, 581, 229, 610}; 279, 560, 419, 420, 240, 599, 258, 581, 229, 610};
// Table 5.7.2-5 - Root ZC sequence order for preamble format 4 // Table 5.7.2-5 - Root ZC sequence order for preamble format 4
uint32_t prach_zc_roots_format4[138] = { uint32_t prach_zc_roots_format4[138] = {
1, 138, 2, 137, 3, 136, 4, 135, 5, 134, 6, 133, 1, 138, 2, 137, 3, 136, 4, 135, 5, 134, 6, 133,
7, 132, 8, 131, 9, 130, 10, 129, 11, 128, 12, 127, 7, 132, 8, 131, 9, 130, 10, 129, 11, 128, 12, 127,
13, 126, 14, 125, 15, 124, 16, 123, 17, 122, 18, 121, 13, 126, 14, 125, 15, 124, 16, 123, 17, 122, 18, 121,
19, 120, 20, 119, 21, 118, 22, 117, 23, 116, 24, 115, 19, 120, 20, 119, 21, 118, 22, 117, 23, 116, 24, 115,
25, 114, 26, 113, 27, 112, 28, 111, 29, 110, 30, 109, 25, 114, 26, 113, 27, 112, 28, 111, 29, 110, 30, 109,
31, 108, 32, 107, 33, 106, 34, 105, 35, 104, 36, 103, 31, 108, 32, 107, 33, 106, 34, 105, 35, 104, 36, 103,
37, 102, 38, 101, 39, 100, 40, 99, 41, 98, 42, 97, 37, 102, 38, 101, 39, 100, 40, 99, 41, 98, 42, 97,
43, 96, 44, 95, 45, 94, 46, 93, 47, 92, 48, 91, 43, 96, 44, 95, 45, 94, 46, 93, 47, 92, 48, 91,
49, 90, 50, 89, 51, 88, 52, 87, 53, 86, 54, 85, 49, 90, 50, 89, 51, 88, 52, 87, 53, 86, 54, 85,
55, 84, 56, 83, 57, 82, 58, 81, 59, 80, 60, 79, 55, 84, 56, 83, 57, 82, 58, 81, 59, 80, 60, 79,
61, 78, 62, 77, 63, 76, 64, 75, 65, 74, 66, 73, 61, 78, 62, 77, 63, 76, 64, 75, 65, 74, 66, 73,
67, 72, 68, 71, 69, 70}; 67, 72, 68, 71, 69, 70};
srslte_prach_sf_config_t prach_sf_config[16] = { srslte_prach_sf_config_t prach_sf_config[16] = {
{1, {1, 0, 0, 0, 0}}, {1, {1, 0, 0, 0, 0}},
{1, {4, 0, 0, 0, 0}}, {1, {4, 0, 0, 0, 0}},
{1, {7, 0, 0, 0, 0}}, {1, {7, 0, 0, 0, 0}},
{1, {1, 0, 0, 0, 0}}, {1, {1, 0, 0, 0, 0}},
{1, {4, 0, 0, 0, 0}}, {1, {4, 0, 0, 0, 0}},
{1, {7, 0, 0, 0, 0}}, {1, {7, 0, 0, 0, 0}},
{2, {1, 6, 0, 0, 0}}, {2, {1, 6, 0, 0, 0}},
{2, {2, 7, 0, 0, 0}}, {2, {2, 7, 0, 0, 0}},
{2, {3, 8, 0, 0, 0}}, {2, {3, 8, 0, 0, 0}},
{3, {1, 4, 7, 0, 0}}, {3, {1, 4, 7, 0, 0}},
{3, {2, 5, 8, 0, 0}}, {3, {2, 5, 8, 0, 0}},
{3, {3, 6, 9, 0, 0}}, {3, {3, 6, 9, 0, 0}},
{5, {0, 2, 4, 6, 8}}, {5, {0, 2, 4, 6, 8}},
{5, {1, 3, 5, 7, 9}}, {5, {1, 3, 5, 7, 9}},
{-1, {0, 0, 0, 0, 0}}, // this means all subframes {-1, {0, 0, 0, 0, 0}}, // this means all subframes
{1, {9, 0, 0, 0, 0}}}; {1, {9, 0, 0, 0, 0}}};
uint32_t srslte_prach_get_preamble_format(uint32_t config_idx) { uint32_t srslte_prach_get_preamble_format(uint32_t config_idx) {
return config_idx/16; return config_idx / 16;
} }
srslte_prach_sfn_t srslte_prach_get_sfn(uint32_t config_idx) { srslte_prach_sfn_t srslte_prach_get_sfn(uint32_t config_idx) {
if ((config_idx%16)<3 || (config_idx%16)==15) { if ((config_idx % 16) < 3 || (config_idx % 16) == 15) {
return SRSLTE_PRACH_SFN_EVEN; return SRSLTE_PRACH_SFN_EVEN;
} else { } else {
return SRSLTE_PRACH_SFN_ANY; return SRSLTE_PRACH_SFN_ANY;
@ -192,26 +191,23 @@ srslte_prach_sfn_t srslte_prach_get_sfn(uint32_t config_idx) {
/* Returns true if current_tti is a valid opportunity for PRACH transmission and the is an allowed subframe, /* Returns true if current_tti is a valid opportunity for PRACH transmission and the is an allowed subframe,
* or allowed_subframe == -1 * or allowed_subframe == -1
*/ */
bool srslte_prach_tti_opportunity(srslte_prach_t *p, uint32_t current_tti, int allowed_subframe) bool srslte_prach_tti_opportunity(srslte_prach_t *p, uint32_t current_tti, int allowed_subframe) {
{
uint32_t config_idx = p->config_idx; uint32_t config_idx = p->config_idx;
// Get SFN and sf_idx from the PRACH configuration index // Get SFN and sf_idx from the PRACH configuration index
srslte_prach_sfn_t prach_sfn = srslte_prach_get_sfn(config_idx); srslte_prach_sfn_t prach_sfn = srslte_prach_get_sfn(config_idx);
// This is the only option which provides always an opportunity for PRACH transmission. // This is the only option which provides always an opportunity for PRACH transmission.
if(config_idx == 14) { if (config_idx == 14) {
return true; return true;
} }
if ((prach_sfn == SRSLTE_PRACH_SFN_EVEN && ((current_tti/10)%2)==0) || if ((prach_sfn == SRSLTE_PRACH_SFN_EVEN && ((current_tti / 10) % 2) == 0) ||
prach_sfn == SRSLTE_PRACH_SFN_ANY) prach_sfn == SRSLTE_PRACH_SFN_ANY) {
{
srslte_prach_sf_config_t sf_config; srslte_prach_sf_config_t sf_config;
srslte_prach_sf_config(config_idx, &sf_config); srslte_prach_sf_config(config_idx, &sf_config);
for (int i=0;i<sf_config.nof_sf;i++) { for (int i = 0; i < sf_config.nof_sf; i++) {
if (((current_tti%10) == sf_config.sf[i] && allowed_subframe == -1) || if (((current_tti % 10) == sf_config.sf[i] && allowed_subframe == -1) ||
((current_tti%10) == sf_config.sf[i] && (current_tti%10) == allowed_subframe)) ((current_tti % 10) == sf_config.sf[i] && (current_tti % 10) == allowed_subframe)) {
{
return true; return true;
} }
} }
@ -219,23 +215,19 @@ bool srslte_prach_tti_opportunity(srslte_prach_t *p, uint32_t current_tti, int a
return false; return false;
} }
void srslte_prach_sf_config(uint32_t config_idx, srslte_prach_sf_config_t *sf_config) { void srslte_prach_sf_config(uint32_t config_idx, srslte_prach_sf_config_t *sf_config) {
memcpy(sf_config, &prach_sf_config[config_idx%16], sizeof(srslte_prach_sf_config_t)); memcpy(sf_config, &prach_sf_config[config_idx % 16], sizeof(srslte_prach_sf_config_t));
} }
// For debug use only // For debug use only
void print(void *d, uint32_t size, uint32_t len, char* file_str) void print(void *d, uint32_t size, uint32_t len, char *file_str) {
{
FILE *f; FILE *f;
f = fopen(file_str, "wb"); f = fopen(file_str, "wb");
fwrite(d , size, len, f); fwrite(d, size, len, f);
fclose(f); fclose(f);
} }
int srslte_prach_gen_seqs(srslte_prach_t *p) int srslte_prach_gen_seqs(srslte_prach_t *p) {
{
uint32_t u = 0; uint32_t u = 0;
uint32_t v = 1; uint32_t v = 1;
int v_max = 0; int v_max = 0;
@ -243,85 +235,91 @@ int srslte_prach_gen_seqs(srslte_prach_t *p)
uint32_t d_u = 0; uint32_t d_u = 0;
uint32_t d_start = 0; uint32_t d_start = 0;
uint32_t N_shift = 0; uint32_t N_shift = 0;
int N_neg_shift = 0; int N_neg_shift = 0;
uint32_t N_group = 0; uint32_t N_group = 0;
uint32_t C_v = 0; uint32_t C_v = 0;
cf_t root[839]; cf_t root[839];
// Generate our 64 preamble sequences // Generate our 64 preamble sequences
for(int i=0;i<N_SEQS;i++){ for (int i = 0; i < N_SEQS; i++) {
if(v > v_max){ if (v > v_max) {
// Get a new root sequence // Get a new root sequence
if(4 == p->f){ if (4 == p->f) {
u = prach_zc_roots_format4[(p->rsi + p->N_roots)%138]; u = prach_zc_roots_format4[(p->rsi + p->N_roots) % 138];
}else{ } else {
u = prach_zc_roots[(p->rsi + p->N_roots)%838]; u = prach_zc_roots[(p->rsi + p->N_roots) % 838];
} }
for(int j=0;j<p->N_zc;j++){ for (int j = 0; j < p->N_zc; j++) {
double phase = -M_PI*u*j*(j+1)/p->N_zc; double phase = -M_PI * u * j * (j + 1) / p->N_zc;
root[j] = cexp(phase*I); root[j] = cexp(phase * I);
} }
p->root_seqs_idx[p->N_roots++] = i; p->root_seqs_idx[p->N_roots++] = i;
// Determine v_max // Determine v_max
if(p->hs){ if (p->hs) {
// High-speed cell // High-speed cell
for(p_=1; p_<=p->N_zc; p_++){ for (p_ = 1; p_ <= p->N_zc; p_++) {
if(((p_*u) % p->N_zc) == 1) if (((p_ * u) % p->N_zc) == 1)
break; break;
} }
if(p_ < p->N_zc/2){ if (p_ < p->N_zc / 2) {
d_u = p_; d_u = p_;
}else{ } else {
d_u = p->N_zc - p_; d_u = p->N_zc - p_;
} }
if(d_u >= p->N_cs && d_u < p->N_zc/3){ if (d_u >= p->N_cs && d_u < p->N_zc / 3) {
N_shift = d_u/p->N_cs; N_shift = d_u / p->N_cs;
d_start = 2*d_u + N_shift*p->N_cs; d_start = 2 * d_u + N_shift * p->N_cs;
N_group = p->N_zc/d_start; N_group = p->N_zc / d_start;
N_neg_shift = (p->N_zc - 2*d_u - N_group*d_start)/p->N_cs; if (p->N_zc > 2 * d_u + N_group * d_start) {
if(N_neg_shift < 0) N_neg_shift = (p->N_zc - 2 * d_u - N_group * d_start) / p->N_cs;
N_neg_shift = 0; } else {
}else{ N_neg_shift = 0;
N_shift = (p->N_zc - 2*d_u)/p->N_cs; }
d_start = p->N_zc - 2*d_u + N_shift*p->N_cs; } else if (p->N_zc / 3 <= d_u && d_u <= (p->N_zc - p->N_cs) / 2) {
N_group = d_u/d_start; N_shift = (p->N_zc - 2 * d_u) / p->N_cs;
N_neg_shift = (d_u - N_group*d_start)/p->N_cs; d_start = p->N_zc - 2 * d_u + N_shift * p->N_cs;
if(N_neg_shift < 0) N_group = d_u / d_start;
N_neg_shift = 0; if (d_u > N_group * d_start) {
if(N_neg_shift > N_shift) N_neg_shift = (d_u - N_group * d_start) / p->N_cs;
N_neg_shift = N_shift; } else {
N_neg_shift = 0;
}
if (N_neg_shift > N_shift)
N_neg_shift = N_shift;
} else {
N_shift = 0;
} }
v_max = N_shift*N_group + N_neg_shift - 1; v_max = N_shift * N_group + N_neg_shift - 1;
if(v_max < 0){ if (v_max < 0) {
v_max = 0; v_max = 0;
} }
}else{ } else {
// Normal cell // Normal cell
if(0 == p->N_cs){ if (0 == p->N_cs) {
v_max = 0; v_max = 0;
}else{ } else {
v_max = (p->N_zc/p->N_cs)-1; v_max = (p->N_zc / p->N_cs) - 1;
} }
} }
v=0; v = 0;
} }
// Shift root and add to set // Shift root and add to set
if(p->hs){ if (p->hs) {
if(N_shift==0){ if (N_shift == 0) {
C_v = 0; C_v = 0;
}else{ } else {
C_v = d_start*floor(v/N_shift) + (v % N_shift)*p->N_cs; C_v = d_start * floor(v / N_shift) + (v % N_shift) * p->N_cs;
} }
}else{ } else {
C_v = v*p->N_cs; C_v = v * p->N_cs;
} }
for(int j=0;j<p->N_zc;j++){ for (int j = 0; j < p->N_zc; j++) {
p->seqs[i][j] = root[(j+C_v) % p->N_zc]; p->seqs[i][j] = root[(j + C_v) % p->N_zc];
} }
v++; v++;
@ -329,64 +327,61 @@ int srslte_prach_gen_seqs(srslte_prach_t *p)
return 0; return 0;
} }
int srslte_prach_init_cfg(srslte_prach_t *p, srslte_prach_cfg_t *cfg, uint32_t nof_prb) int srslte_prach_init_cfg(srslte_prach_t *p, srslte_prach_cfg_t *cfg, uint32_t nof_prb) {
{
if (srslte_prach_init(p, srslte_symbol_sz(nof_prb))) { if (srslte_prach_init(p, srslte_symbol_sz(nof_prb))) {
return -1; return -1;
} }
return srslte_prach_set_cell(p, return srslte_prach_set_cell(p,
srslte_symbol_sz(nof_prb), srslte_symbol_sz(nof_prb),
cfg->config_idx, cfg->config_idx,
cfg->root_seq_idx, cfg->root_seq_idx,
cfg->hs_flag, cfg->hs_flag,
cfg->zero_corr_zone); cfg->zero_corr_zone);
} }
int srslte_prach_init(srslte_prach_t *p, uint32_t max_N_ifft_ul) int srslte_prach_init(srslte_prach_t *p, uint32_t max_N_ifft_ul) {
{
int ret = SRSLTE_ERROR; int ret = SRSLTE_ERROR;
if(p != NULL && if (p != NULL &&
max_N_ifft_ul < 2049) max_N_ifft_ul < 2049) {
{
bzero(p, sizeof(srslte_prach_t)); bzero(p, sizeof(srslte_prach_t));
p->max_N_ifft_ul = max_N_ifft_ul; p->max_N_ifft_ul = max_N_ifft_ul;
// Set up containers // Set up containers
p->prach_bins = srslte_vec_malloc(sizeof(cf_t)*MAX_N_zc); p->prach_bins = srslte_vec_malloc(sizeof(cf_t) * MAX_N_zc);
p->corr_spec = srslte_vec_malloc(sizeof(cf_t)*MAX_N_zc); p->corr_spec = srslte_vec_malloc(sizeof(cf_t) * MAX_N_zc);
p->corr = srslte_vec_malloc(sizeof(float)*MAX_N_zc); p->corr = srslte_vec_malloc(sizeof(float) * MAX_N_zc);
// Set up ZC FFTS // Set up ZC FFTS
if(srslte_dft_plan(&p->zc_fft, MAX_N_zc, SRSLTE_DFT_FORWARD, SRSLTE_DFT_COMPLEX)){ if (srslte_dft_plan(&p->zc_fft, MAX_N_zc, SRSLTE_DFT_FORWARD, SRSLTE_DFT_COMPLEX)) {
return SRSLTE_ERROR; return SRSLTE_ERROR;
} }
srslte_dft_plan_set_mirror(&p->zc_fft, false); srslte_dft_plan_set_mirror(&p->zc_fft, false);
srslte_dft_plan_set_norm(&p->zc_fft, true); srslte_dft_plan_set_norm(&p->zc_fft, true);
if(srslte_dft_plan(&p->zc_ifft, MAX_N_zc, SRSLTE_DFT_BACKWARD, SRSLTE_DFT_COMPLEX)){ if (srslte_dft_plan(&p->zc_ifft, MAX_N_zc, SRSLTE_DFT_BACKWARD, SRSLTE_DFT_COMPLEX)) {
return SRSLTE_ERROR; return SRSLTE_ERROR;
} }
srslte_dft_plan_set_mirror(&p->zc_ifft, false); srslte_dft_plan_set_mirror(&p->zc_ifft, false);
srslte_dft_plan_set_norm(&p->zc_ifft, false); srslte_dft_plan_set_norm(&p->zc_ifft, false);
uint32_t fft_size_alloc = max_N_ifft_ul * DELTA_F/DELTA_F_RA; uint32_t fft_size_alloc = max_N_ifft_ul * DELTA_F / DELTA_F_RA;
p->ifft_in = (cf_t*)srslte_vec_malloc(fft_size_alloc*sizeof(cf_t)); p->ifft_in = (cf_t *) srslte_vec_malloc(fft_size_alloc * sizeof(cf_t));
p->ifft_out = (cf_t*)srslte_vec_malloc(fft_size_alloc*sizeof(cf_t)); p->ifft_out = (cf_t *) srslte_vec_malloc(fft_size_alloc * sizeof(cf_t));
if(srslte_dft_plan(&p->ifft, fft_size_alloc, SRSLTE_DFT_BACKWARD, SRSLTE_DFT_COMPLEX)) { if (srslte_dft_plan(&p->ifft, fft_size_alloc, SRSLTE_DFT_BACKWARD, SRSLTE_DFT_COMPLEX)) {
fprintf(stderr, "Error creating DFT plan\n"); fprintf(stderr, "Error creating DFT plan\n");
return -1; return -1;
} }
srslte_dft_plan_set_mirror(&p->ifft, true); srslte_dft_plan_set_mirror(&p->ifft, true);
srslte_dft_plan_set_norm(&p->ifft, true); srslte_dft_plan_set_norm(&p->ifft, true);
if(srslte_dft_plan(&p->fft, fft_size_alloc, SRSLTE_DFT_FORWARD, SRSLTE_DFT_COMPLEX)){ if (srslte_dft_plan(&p->fft, fft_size_alloc, SRSLTE_DFT_FORWARD, SRSLTE_DFT_COMPLEX)) {
fprintf(stderr, "Error creating DFT plan\n"); fprintf(stderr, "Error creating DFT plan\n");
return -1; return -1;
} }
p->signal_fft = srslte_vec_malloc(sizeof(cf_t)*fft_size_alloc); p->signal_fft = srslte_vec_malloc(sizeof(cf_t) * fft_size_alloc);
if (!p->signal_fft) { if (!p->signal_fft) {
fprintf(stderr, "Error allocating memory\n"); fprintf(stderr, "Error allocating memory\n");
return -1; return -1;
@ -403,20 +398,17 @@ int srslte_prach_init(srslte_prach_t *p, uint32_t max_N_ifft_ul)
return ret; return ret;
} }
int srslte_prach_set_cell(srslte_prach_t *p, int srslte_prach_set_cell(srslte_prach_t *p,
uint32_t N_ifft_ul, uint32_t N_ifft_ul,
uint32_t config_idx, uint32_t config_idx,
uint32_t root_seq_index, uint32_t root_seq_index,
bool high_speed_flag, bool high_speed_flag,
uint32_t zero_corr_zone_config) uint32_t zero_corr_zone_config) {
{
int ret = SRSLTE_ERROR; int ret = SRSLTE_ERROR;
if(p != NULL && if (p != NULL &&
N_ifft_ul < 2049 && N_ifft_ul < 2049 &&
config_idx < 64 && config_idx < 64 &&
root_seq_index < MAX_ROOTS) root_seq_index < MAX_ROOTS) {
{
if (N_ifft_ul > p->max_N_ifft_ul) { if (N_ifft_ul > p->max_N_ifft_ul) {
fprintf(stderr, "PRACH: Error in set_cell(): N_ifft_ul must be lower or equal max_N_ifft_ul in init()\n"); fprintf(stderr, "PRACH: Error in set_cell(): N_ifft_ul must be lower or equal max_N_ifft_ul in init()\n");
return -1; return -1;
@ -432,7 +424,7 @@ int srslte_prach_set_cell(srslte_prach_t *p,
// Determine N_zc and N_cs // Determine N_zc and N_cs
if(4 == preamble_format){ if (4 == preamble_format) {
if (p->zczc < 7) { if (p->zczc < 7) {
p->N_zc = 139; p->N_zc = 139;
p->N_cs = prach_Ncs_format4[p->zczc]; p->N_cs = prach_Ncs_format4[p->zczc];
@ -440,16 +432,16 @@ int srslte_prach_set_cell(srslte_prach_t *p,
fprintf(stderr, "Invalid zeroCorrelationZoneConfig=%d for format4\n", p->zczc); fprintf(stderr, "Invalid zeroCorrelationZoneConfig=%d for format4\n", p->zczc);
return SRSLTE_ERROR; return SRSLTE_ERROR;
} }
}else{ } else {
p->N_zc = MAX_N_zc; p->N_zc = MAX_N_zc;
if(p->hs){ if (p->hs) {
if (p->zczc < 15) { if (p->zczc < 15) {
p->N_cs = prach_Ncs_restricted[p->zczc]; p->N_cs = prach_Ncs_restricted[p->zczc];
} else { } else {
fprintf(stderr, "Invalid zeroCorrelationZoneConfig=%d for restricted set\n", p->zczc); fprintf(stderr, "Invalid zeroCorrelationZoneConfig=%d for restricted set\n", p->zczc);
return SRSLTE_ERROR; return SRSLTE_ERROR;
} }
}else{ } else {
if (p->zczc < 16) { if (p->zczc < 16) {
p->N_cs = prach_Ncs_unrestricted[p->zczc]; p->N_cs = prach_Ncs_unrestricted[p->zczc];
} else { } else {
@ -461,10 +453,10 @@ int srslte_prach_set_cell(srslte_prach_t *p,
// Set up ZC FFTS // Set up ZC FFTS
if (p->N_zc != MAX_N_zc) { if (p->N_zc != MAX_N_zc) {
if(srslte_dft_replan(&p->zc_fft, p->N_zc)){ if (srslte_dft_replan(&p->zc_fft, p->N_zc)) {
return SRSLTE_ERROR; return SRSLTE_ERROR;
} }
if(srslte_dft_replan(&p->zc_ifft, p->N_zc)){ if (srslte_dft_replan(&p->zc_ifft, p->N_zc)) {
return SRSLTE_ERROR; return SRSLTE_ERROR;
} }
} }
@ -474,16 +466,16 @@ int srslte_prach_set_cell(srslte_prach_t *p,
srslte_prach_gen_seqs(p); srslte_prach_gen_seqs(p);
// Generate sequence FFTs // Generate sequence FFTs
for(int i=0;i<N_SEQS;i++){ for (int i = 0; i < N_SEQS; i++) {
srslte_dft_run(&p->zc_fft, p->seqs[i], p->dft_seqs[i]); srslte_dft_run(&p->zc_fft, p->seqs[i], p->dft_seqs[i]);
} }
// Create our FFT objects and buffers // Create our FFT objects and buffers
p->N_ifft_ul = N_ifft_ul; p->N_ifft_ul = N_ifft_ul;
if(4 == preamble_format){ if (4 == preamble_format) {
p->N_ifft_prach = p->N_ifft_ul * DELTA_F/DELTA_F_RA_4; p->N_ifft_prach = p->N_ifft_ul * DELTA_F / DELTA_F_RA_4;
}else{ } else {
p->N_ifft_prach = p->N_ifft_ul * DELTA_F/DELTA_F_RA; p->N_ifft_prach = p->N_ifft_ul * DELTA_F / DELTA_F_RA;
} }
/* The deadzone specifies the number of samples at the end of the correlation window /* The deadzone specifies the number of samples at the end of the correlation window
@ -496,19 +488,19 @@ int srslte_prach_set_cell(srslte_prach_t *p,
p->deadzone = (uint32_t) ceil((float) samp_rate/((float) p->N_zc*subcarrier_spacing)); p->deadzone = (uint32_t) ceil((float) samp_rate/((float) p->N_zc*subcarrier_spacing));
}*/ }*/
if(srslte_dft_replan(&p->ifft, p->N_ifft_prach)) { if (srslte_dft_replan(&p->ifft, p->N_ifft_prach)) {
fprintf(stderr, "Error creating DFT plan\n"); fprintf(stderr, "Error creating DFT plan\n");
return -1; return -1;
} }
if(srslte_dft_replan(&p->fft, p->N_ifft_prach)){ if (srslte_dft_replan(&p->fft, p->N_ifft_prach)) {
fprintf(stderr, "Error creating DFT plan\n"); fprintf(stderr, "Error creating DFT plan\n");
return -1; return -1;
} }
p->N_seq = prach_Tseq[p->f]*p->N_ifft_ul/2048; p->N_seq = prach_Tseq[p->f] * p->N_ifft_ul / 2048;
p->N_cp = prach_Tcp[p->f]*p->N_ifft_ul/2048; p->N_cp = prach_Tcp[p->f] * p->N_ifft_ul / 2048;
p->T_seq = prach_Tseq[p->f]*SRSLTE_LTE_TS; p->T_seq = prach_Tseq[p->f] * SRSLTE_LTE_TS;
p->T_tot = (prach_Tseq[p->f]+prach_Tcp[p->f])*SRSLTE_LTE_TS; p->T_tot = (prach_Tseq[p->f] + prach_Tcp[p->f]) * SRSLTE_LTE_TS;
ret = SRSLTE_SUCCESS; ret = SRSLTE_SUCCESS;
} else { } else {
@ -519,20 +511,18 @@ int srslte_prach_set_cell(srslte_prach_t *p,
} }
int srslte_prach_gen(srslte_prach_t *p, int srslte_prach_gen(srslte_prach_t *p,
uint32_t seq_index, uint32_t seq_index,
uint32_t freq_offset, uint32_t freq_offset,
cf_t *signal) cf_t *signal) {
{
int ret = SRSLTE_ERROR; int ret = SRSLTE_ERROR;
if(p != NULL && if (p != NULL &&
seq_index < N_SEQS && seq_index < N_SEQS &&
signal != NULL) signal != NULL) {
{
// Calculate parameters // Calculate parameters
uint32_t N_rb_ul = srslte_nof_prb(p->N_ifft_ul); uint32_t N_rb_ul = srslte_nof_prb(p->N_ifft_ul);
uint32_t k_0 = freq_offset*N_RB_SC - N_rb_ul*N_RB_SC/2 + p->N_ifft_ul/2; uint32_t k_0 = freq_offset * N_RB_SC - N_rb_ul * N_RB_SC / 2 + p->N_ifft_ul / 2;
uint32_t K = DELTA_F/DELTA_F_RA; uint32_t K = DELTA_F / DELTA_F_RA;
uint32_t begin = PHI + (K*k_0) + (K/2); uint32_t begin = PHI + (K * k_0) + (K / 2);
if (6 + freq_offset > N_rb_ul) { if (6 + freq_offset > N_rb_ul) {
fprintf(stderr, "Error no space for PRACH: frequency offset=%d, N_rb_ul=%d\n", freq_offset, N_rb_ul); fprintf(stderr, "Error no space for PRACH: frequency offset=%d, N_rb_ul=%d\n", freq_offset, N_rb_ul);
@ -543,18 +533,18 @@ int srslte_prach_gen(srslte_prach_t *p,
p->N_zc, p->N_cp, p->N_seq, p->N_ifft_prach, begin); p->N_zc, p->N_cp, p->N_seq, p->N_ifft_prach, begin);
// Map dft-precoded sequence to ifft bins // Map dft-precoded sequence to ifft bins
memset(p->ifft_in, 0, begin*sizeof(cf_t)); memset(p->ifft_in, 0, begin * sizeof(cf_t));
memcpy(&p->ifft_in[begin], p->dft_seqs[seq_index], p->N_zc * sizeof(cf_t)); memcpy(&p->ifft_in[begin], p->dft_seqs[seq_index], p->N_zc * sizeof(cf_t));
memset(&p->ifft_in[begin+p->N_zc], 0, (p->N_ifft_prach - begin - p->N_zc) * sizeof(cf_t)); memset(&p->ifft_in[begin + p->N_zc], 0, (p->N_ifft_prach - begin - p->N_zc) * sizeof(cf_t));
srslte_dft_run(&p->ifft, p->ifft_in, p->ifft_out); srslte_dft_run(&p->ifft, p->ifft_in, p->ifft_out);
// Copy CP into buffer // Copy CP into buffer
memcpy(signal, &p->ifft_out[p->N_ifft_prach-p->N_cp], p->N_cp*sizeof(cf_t)); memcpy(signal, &p->ifft_out[p->N_ifft_prach - p->N_cp], p->N_cp * sizeof(cf_t));
// Copy preamble sequence into buffer // Copy preamble sequence into buffer
for(int i=0;i<p->N_seq;i++){ for (int i = 0; i < p->N_seq; i++) {
signal[p->N_cp+i] = p->ifft_out[i%p->N_ifft_prach]; signal[p->N_cp + i] = p->ifft_out[i % p->N_ifft_prach];
} }
ret = SRSLTE_SUCCESS; ret = SRSLTE_SUCCESS;
@ -572,8 +562,7 @@ int srslte_prach_detect(srslte_prach_t *p,
cf_t *signal, cf_t *signal,
uint32_t sig_len, uint32_t sig_len,
uint32_t *indices, uint32_t *indices,
uint32_t *n_indices) uint32_t *n_indices) {
{
return srslte_prach_detect_offset(p, freq_offset, signal, sig_len, indices, NULL, NULL, n_indices); return srslte_prach_detect_offset(p, freq_offset, signal, sig_len, indices, NULL, NULL, n_indices);
} }
@ -583,17 +572,15 @@ int srslte_prach_detect_offset(srslte_prach_t *p,
uint32_t sig_len, uint32_t sig_len,
uint32_t *indices, uint32_t *indices,
float *t_offsets, float *t_offsets,
float *peak_to_avg, float *peak_to_avg,
uint32_t *n_indices) uint32_t *n_indices) {
{
int ret = SRSLTE_ERROR; int ret = SRSLTE_ERROR;
if(p != NULL && if (p != NULL &&
signal != NULL && signal != NULL &&
sig_len > 0 && sig_len > 0 &&
indices != NULL) indices != NULL) {
{
if(sig_len < p->N_ifft_prach){ if (sig_len < p->N_ifft_prach) {
fprintf(stderr, "srslte_prach_detect: Signal length is %d and should be %d\n", sig_len, p->N_ifft_prach); fprintf(stderr, "srslte_prach_detect: Signal length is %d and should be %d\n", sig_len, p->N_ifft_prach);
return SRSLTE_ERROR_INVALID_INPUTS; return SRSLTE_ERROR_INVALID_INPUTS;
} }
@ -605,13 +592,13 @@ int srslte_prach_detect_offset(srslte_prach_t *p,
// Extract bins of interest // Extract bins of interest
uint32_t N_rb_ul = srslte_nof_prb(p->N_ifft_ul); uint32_t N_rb_ul = srslte_nof_prb(p->N_ifft_ul);
uint32_t k_0 = freq_offset*N_RB_SC - N_rb_ul*N_RB_SC/2 + p->N_ifft_ul/2; uint32_t k_0 = freq_offset * N_RB_SC - N_rb_ul * N_RB_SC / 2 + p->N_ifft_ul / 2;
uint32_t K = DELTA_F/DELTA_F_RA; uint32_t K = DELTA_F / DELTA_F_RA;
uint32_t begin = PHI + (K*k_0) + (K/2); uint32_t begin = PHI + (K * k_0) + (K / 2);
memcpy(p->prach_bins, &p->signal_fft[begin], p->N_zc*sizeof(cf_t)); memcpy(p->prach_bins, &p->signal_fft[begin], p->N_zc * sizeof(cf_t));
for(int i=0;i<p->N_roots;i++){ for (int i = 0; i < p->N_roots; i++) {
cf_t *root_spec = p->dft_seqs[p->root_seqs_idx[i]]; cf_t *root_spec = p->dft_seqs[p->root_seqs_idx[i]];
srslte_vec_prod_conj_ccc(p->prach_bins, root_spec, p->corr_spec, p->N_zc); srslte_vec_prod_conj_ccc(p->prach_bins, root_spec, p->corr_spec, p->N_zc);
@ -620,49 +607,48 @@ int srslte_prach_detect_offset(srslte_prach_t *p,
srslte_vec_abs_square_cf(p->corr_spec, p->corr, p->N_zc); srslte_vec_abs_square_cf(p->corr_spec, p->corr, p->N_zc);
float corr_ave = srslte_vec_acc_ff(p->corr, p->N_zc)/p->N_zc; float corr_ave = srslte_vec_acc_ff(p->corr, p->N_zc) / p->N_zc;
uint32_t winsize = 0; uint32_t winsize = 0;
if(p->N_cs != 0){ if (p->N_cs != 0) {
winsize = p->N_cs; winsize = p->N_cs;
}else{ } else {
winsize = p->N_zc; winsize = p->N_zc;
} }
uint32_t n_wins = p->N_zc/winsize; uint32_t n_wins = p->N_zc / winsize;
float max_peak = 0; float max_peak = 0;
for(int j=0;j<n_wins;j++) { for (int j = 0; j < n_wins; j++) {
uint32_t start = (p->N_zc-(j*p->N_cs))%p->N_zc; uint32_t start = (p->N_zc - (j * p->N_cs)) % p->N_zc;
uint32_t end = start+winsize; uint32_t end = start + winsize;
if (end>p->deadzone) { if (end > p->deadzone) {
end-=p->deadzone; end -= p->deadzone;
} }
start += p->deadzone; start += p->deadzone;
p->peak_values[j] = 0; p->peak_values[j] = 0;
for(int k=start;k<end;k++) { for (int k = start; k < end; k++) {
if(p->corr[k] > p->peak_values[j]) { if (p->corr[k] > p->peak_values[j]) {
p->peak_values[j] = p->corr[k]; p->peak_values[j] = p->corr[k];
p->peak_offsets[j] = k-start; p->peak_offsets[j] = k - start;
if (p->peak_values[j] > max_peak) { if (p->peak_values[j] > max_peak) {
max_peak = p->peak_values[j]; max_peak = p->peak_values[j];
} }
} }
} }
} }
if (max_peak > p->detect_factor*corr_ave) { if (max_peak > p->detect_factor * corr_ave) {
for (int j=0;j<n_wins;j++) { for (int j = 0; j < n_wins; j++) {
if(p->peak_values[j] > p->detect_factor*corr_ave) if (p->peak_values[j] > p->detect_factor * corr_ave) {
{
//printf("saving prach correlation\n"); //printf("saving prach correlation\n");
//memcpy(save_corr, p->corr, p->N_zc*sizeof(float)); //memcpy(save_corr, p->corr, p->N_zc*sizeof(float));
if (indices) { if (indices) {
indices[*n_indices] = (i*n_wins)+j; indices[*n_indices] = (i * n_wins) + j;
} }
if (peak_to_avg) { if (peak_to_avg) {
peak_to_avg[*n_indices] = p->peak_values[j]/corr_ave; peak_to_avg[*n_indices] = p->peak_values[j] / corr_ave;
} }
if (t_offsets) { if (t_offsets) {
t_offsets[*n_indices] = (float) p->peak_offsets[j]*p->T_seq/p->N_zc; t_offsets[*n_indices] = (float) p->peak_offsets[j] * p->T_seq / p->N_zc;
} }
(*n_indices)++; (*n_indices)++;
} }
@ -695,33 +681,29 @@ int srslte_prach_free(srslte_prach_t *p) {
return 0; return 0;
} }
int srslte_prach_print_seqs(srslte_prach_t *p) int srslte_prach_print_seqs(srslte_prach_t *p) {
{ for (int i = 0; i < N_SEQS; i++) {
for(int i=0; i<N_SEQS;i++)
{
FILE *f; FILE *f;
char str[32]; char str[32];
sprintf(str, "prach_seq_%d.bin", i); sprintf(str, "prach_seq_%d.bin", i);
f = fopen(str, "wb"); f = fopen(str, "wb");
fwrite(p->seqs[i] , sizeof(cf_t), p->N_zc, f); fwrite(p->seqs[i], sizeof(cf_t), p->N_zc, f);
fclose(f); fclose(f);
} }
for(int i=0; i<N_SEQS;i++) for (int i = 0; i < N_SEQS; i++) {
{
FILE *f; FILE *f;
char str[32]; char str[32];
sprintf(str, "prach_dft_seq_%d.bin", i); sprintf(str, "prach_dft_seq_%d.bin", i);
f = fopen(str, "wb"); f = fopen(str, "wb");
fwrite(p->dft_seqs[i] , sizeof(cf_t), p->N_zc, f); fwrite(p->dft_seqs[i], sizeof(cf_t), p->N_zc, f);
fclose(f); fclose(f);
} }
for(int i=0;i<p->N_roots;i++) for (int i = 0; i < p->N_roots; i++) {
{
FILE *f; FILE *f;
char str[32]; char str[32];
sprintf(str, "prach_root_seq_%d.bin", i); sprintf(str, "prach_root_seq_%d.bin", i);
f = fopen(str, "wb"); f = fopen(str, "wb");
fwrite(p->seqs[p->root_seqs_idx[i]] , sizeof(cf_t), p->N_zc, f); fwrite(p->seqs[p->root_seqs_idx[i]], sizeof(cf_t), p->N_zc, f);
fclose(f); fclose(f);
} }
return 0; return 0;

@ -186,9 +186,11 @@ int rf_cell_search(srslte_rf_t *rf, uint32_t nof_rx_antennas,
ret = srslte_ue_cellsearch_scan(&cs, found_cells, &max_peak_cell); ret = srslte_ue_cellsearch_scan(&cs, found_cells, &max_peak_cell);
} }
if (ret < 0) { if (ret < 0) {
srslte_rf_stop_rx_stream(rf);
fprintf(stderr, "Error searching cell\n"); fprintf(stderr, "Error searching cell\n");
return SRSLTE_ERROR; return SRSLTE_ERROR;
} else if (ret == 0) { } else if (ret == 0) {
srslte_rf_stop_rx_stream(rf);
fprintf(stderr, "Could not find any cell in this frequency\n"); fprintf(stderr, "Could not find any cell in this frequency\n");
return SRSLTE_SUCCESS; return SRSLTE_SUCCESS;
} }

@ -71,7 +71,7 @@ int srslte_sync_init_decim(srslte_sync_t *q, uint32_t frame_size, uint32_t max_o
q->N_id_1 = 1000; q->N_id_1 = 1000;
q->cfo_ema_alpha = CFO_EMA_ALPHA; q->cfo_ema_alpha = CFO_EMA_ALPHA;
q->sss_alg = SSS_PARTIAL_3; q->sss_alg = SSS_FULL;
q->detect_cp = true; q->detect_cp = true;
q->sss_en = true; q->sss_en = true;

@ -460,15 +460,15 @@ int srslte_ue_dl_cfg_grant(srslte_ue_dl_t *q, srslte_ra_dl_grant_t *grant, uint3
pmi = grant->pinfo - 1; pmi = grant->pinfo - 1;
} else { } else {
ERROR("Not Implemented (nof_tb=%d, pinfo=%d)", nof_tb, grant->pinfo); ERROR("Not Implemented (nof_tb=%d, pinfo=%d)", nof_tb, grant->pinfo);
return SRSLTE_ERROR; pmi = grant->pinfo % 4;
} }
} else { } else {
if (grant->pinfo < 2) { if (grant->pinfo == 2) {
pmi = grant->pinfo; ERROR("Not implemented codebook index (nof_tb=%d, pinfo=%d)", nof_tb, grant->pinfo);
} else { } else if (grant->pinfo > 2) {
ERROR("Not Implemented (nof_tb=%d, pinfo=%d)", nof_tb, grant->pinfo); ERROR("Reserved codebook index (nof_tb=%d, pinfo=%d)", nof_tb, grant->pinfo);
return SRSLTE_ERROR;
} }
pmi = grant->pinfo % 2;
} }
} }
if(SRSLTE_SF_MBSFN == grant->sf_type) { if(SRSLTE_SF_MBSFN == grant->sf_type) {

@ -144,18 +144,11 @@ void srslte_ue_sync_reset(srslte_ue_sync_t *q) {
int srslte_ue_sync_start_agc(srslte_ue_sync_t *q, double (set_gain_callback)(void*, double), float init_gain_value) { int srslte_ue_sync_start_agc(srslte_ue_sync_t *q, double (set_gain_callback)(void*, double), float init_gain_value) {
uint32_t nframes; int n = srslte_agc_init_uhd(&q->agc, SRSLTE_AGC_MODE_PEAK_AMPLITUDE, 0, set_gain_callback, q->stream);
if (q->nof_recv_sf == 1) {
nframes = 10;
} else {
nframes = 0;
}
int n = srslte_agc_init_uhd(&q->agc, SRSLTE_AGC_MODE_PEAK_AMPLITUDE, nframes, set_gain_callback, q->stream);
q->do_agc = n==0?true:false; q->do_agc = n==0?true:false;
if (q->do_agc) { if (q->do_agc) {
srslte_agc_set_gain(&q->agc, init_gain_value); srslte_agc_set_gain(&q->agc, init_gain_value);
srslte_agc_set_target(&q->agc, 0.3); srslte_ue_sync_set_agc_period(q, 4);
srslte_agc_set_bandwidth(&q->agc, 0.8);
} }
return n; return n;
} }
@ -329,7 +322,6 @@ int srslte_ue_sync_set_cell(srslte_ue_sync_t *q, srslte_cell_t cell)
memcpy(&q->cell, &cell, sizeof(srslte_cell_t)); memcpy(&q->cell, &cell, sizeof(srslte_cell_t));
q->fft_size = srslte_symbol_sz(q->cell.nof_prb); q->fft_size = srslte_symbol_sz(q->cell.nof_prb);
q->sf_len = SRSLTE_SF_LEN(q->fft_size); q->sf_len = SRSLTE_SF_LEN(q->fft_size);
q->agc_period = 0;
if (cell.id == 1000) { if (cell.id == 1000) {

@ -355,7 +355,7 @@ int srslte_ue_ul_pucch_encode(srslte_ue_ul_t *q, srslte_uci_data_t uci_data,
} }
if (q->normalize_en) { if (q->normalize_en) {
float norm_factor = (float) 0.8*q->cell.nof_prb/5; float norm_factor = (float) q->cell.nof_prb/15/10;
srslte_vec_sc_prod_cfc(output_signal, norm_factor, output_signal, SRSLTE_SF_LEN_PRB(q->cell.nof_prb)); srslte_vec_sc_prod_cfc(output_signal, norm_factor, output_signal, SRSLTE_SF_LEN_PRB(q->cell.nof_prb));
} }
ret = SRSLTE_SUCCESS; ret = SRSLTE_SUCCESS;

@ -54,6 +54,7 @@ int srslte_ringbuffer_write(srslte_ringbuffer_t *q, void *p, int nof_bytes)
int w_bytes = nof_bytes; int w_bytes = nof_bytes;
pthread_mutex_lock(&q->mutex); pthread_mutex_lock(&q->mutex);
if (!q->active) { if (!q->active) {
pthread_mutex_unlock(&q->mutex);
return 0; return 0;
} }
if (q->count + w_bytes > q->capacity) { if (q->count + w_bytes > q->capacity) {
@ -85,6 +86,7 @@ int srslte_ringbuffer_read(srslte_ringbuffer_t *q, void *p, int nof_bytes)
pthread_cond_wait(&q->cvar, &q->mutex); pthread_cond_wait(&q->cvar, &q->mutex);
} }
if (!q->active) { if (!q->active) {
pthread_mutex_unlock(&q->mutex);
return 0; return 0;
} }
if (nof_bytes + q->rpm > q->capacity) { if (nof_bytes + q->rpm > q->capacity) {

@ -452,6 +452,28 @@ TEST(srslte_vec_convert_fi,
free(z); free(z);
) )
TEST(srslte_vec_convert_if,
MALLOC(int16_t, x);
MALLOC(float, z);
float scale = 1000.0f;
float gold;
float k = 1.0f/scale;
for (int i = 0; i < block_size; i++) {
x[i] = (int16_t) RANDOM_S();
}
TEST_CALL(srslte_vec_convert_if(x, scale, z, block_size))
for (int i = 0; i < block_size; i++) {
gold = ((float)x[i]) * k;
mse += fabsf(gold - z[i]);
}
free(x);
free(z);
)
TEST(srslte_vec_prod_fff, TEST(srslte_vec_prod_fff,
MALLOC(float, x); MALLOC(float, x);
MALLOC(float, y); MALLOC(float, y);
@ -596,7 +618,7 @@ TEST(srslte_vec_div_ccc,
for (int i = 0; i < block_size; i++) { for (int i = 0; i < block_size; i++) {
gold = x[i] / y[i]; gold = x[i] / y[i];
mse += cabsf(gold - z[i]); mse += cabsf(gold - z[i]) / cabsf(gold);
} }
mse /= block_size; mse /= block_size;
@ -614,14 +636,14 @@ TEST(srslte_vec_div_cfc,
cf_t gold; cf_t gold;
for (int i = 0; i < block_size; i++) { for (int i = 0; i < block_size; i++) {
x[i] = RANDOM_CF(); x[i] = RANDOM_CF();
y[i] = RANDOM_F(); y[i] = RANDOM_F() + 0.0001f;
} }
TEST_CALL(srslte_vec_div_cfc(x, y, z, block_size)) TEST_CALL(srslte_vec_div_cfc(x, y, z, block_size))
for (int i = 0; i < block_size; i++) { for (int i = 0; i < block_size; i++) {
gold = x[i] / y[i]; gold = x[i] / y[i];
mse += cabsf(gold - z[i])/cabsf(gold); mse += cabsf(gold - z[i]) / cabsf(gold);
} }
mse /= block_size; mse /= block_size;
@ -638,15 +660,15 @@ TEST(srslte_vec_div_fff,
cf_t gold; cf_t gold;
for (int i = 0; i < block_size; i++) { for (int i = 0; i < block_size; i++) {
x[i] = RANDOM_F() + 0.0001; x[i] = RANDOM_F();
y[i] = RANDOM_F()+ 0.0001; y[i] = RANDOM_F() + 0.0001f;
} }
TEST_CALL(srslte_vec_div_fff(x, y, z, block_size)) TEST_CALL(srslte_vec_div_fff(x, y, z, block_size))
for (int i = 0; i < block_size; i++) { for (int i = 0; i < block_size; i++) {
gold = x[i] / y[i]; gold = x[i] / y[i];
mse += cabsf(gold - z[i]); mse += cabsf(gold - z[i]) / cabsf(gold);
} }
mse /= block_size; mse /= block_size;
@ -753,6 +775,9 @@ int main(int argc, char **argv) {
passed[func_count][size_count] = test_srslte_vec_convert_fi(func_names[func_count], &timmings[func_count][size_count], block_size); passed[func_count][size_count] = test_srslte_vec_convert_fi(func_names[func_count], &timmings[func_count][size_count], block_size);
func_count++; func_count++;
passed[func_count][size_count] = test_srslte_vec_convert_if(func_names[func_count], &timmings[func_count][size_count], block_size);
func_count++;
passed[func_count][size_count] = test_srslte_vec_prod_fff(func_names[func_count], &timmings[func_count][size_count], block_size); passed[func_count][size_count] = test_srslte_vec_prod_fff(func_names[func_count], &timmings[func_count][size_count], block_size);
func_count++; func_count++;

@ -93,10 +93,7 @@ void srslte_vec_sc_prod_ccc(const cf_t *x, const cf_t h, cf_t *z, const uint32_t
// Used in turbo decoder // Used in turbo decoder
void srslte_vec_convert_if(const int16_t *x, const float scale, float *z, const uint32_t len) { void srslte_vec_convert_if(const int16_t *x, const float scale, float *z, const uint32_t len) {
int i; srslte_vec_convert_if_simd(x, z, scale, len);
for (i=0;i<len;i++) {
z[i] = ((float) x[i])/scale;
}
} }
void srslte_vec_convert_fi(const float *x, const float scale, int16_t *z, const uint32_t len) { void srslte_vec_convert_fi(const float *x, const float scale, int16_t *z, const uint32_t len) {

@ -228,6 +228,36 @@ void srslte_vec_lut_sss_simd(const short *x, const unsigned short *lut, short *y
} }
} }
void srslte_vec_convert_if_simd(const int16_t *x, float *z, const float scale, const int len) {
int i = 0;
const float gain = 1.0f / scale;
#ifdef LV_HAVE_SSE
__m128 s = _mm_set1_ps(gain);
if (SRSLTE_IS_ALIGNED(z)) {
for (; i < len - 3; i += 4) {
__m64 *ptr = (__m64 *) &x[i];
__m128 fl = _mm_cvtpi16_ps(*ptr);
__m128 v = _mm_mul_ps(fl, s);
_mm_store_ps(&z[i], v);
}
} else {
for (; i < len - 3; i += 4) {
__m64 *ptr = (__m64 *) &x[i];
__m128 fl = _mm_cvtpi16_ps(*ptr);
__m128 v = _mm_mul_ps(fl, s);
_mm_storeu_ps(&z[i], v);
}
}
#endif /* LV_HAVE_SSE */
for (; i < len; i++) {
z[i] = ((float) x[i]) * gain;
}
}
void srslte_vec_convert_fi_simd(const float *x, int16_t *z, const float scale, const int len) { void srslte_vec_convert_fi_simd(const float *x, int16_t *z, const float scale, const int len) {
int i = 0; int i = 0;

@ -68,6 +68,12 @@ rlc_am::rlc_am() : tx_sdu_queue(16)
do_status = false; do_status = false;
} }
rlc_am::~rlc_am()
{
// reset RLC and dealloc SDUs
stop();
}
void rlc_am::init(srslte::log *log_, void rlc_am::init(srslte::log *log_,
uint32_t lcid_, uint32_t lcid_,
srsue::pdcp_interface_rlc *pdcp_, srsue::pdcp_interface_rlc *pdcp_,
@ -112,8 +118,10 @@ void rlc_am::reset()
pthread_mutex_lock(&mutex); pthread_mutex_lock(&mutex);
reordering_timeout.reset(); reordering_timeout.reset();
if(tx_sdu) if(tx_sdu) {
tx_sdu->reset(); pool->deallocate(tx_sdu);
tx_sdu = NULL;
}
if(rx_sdu) if(rx_sdu)
rx_sdu->reset(); rx_sdu->reset();
@ -587,7 +595,8 @@ int rlc_am::build_segment(uint8_t *payload, uint32_t nof_bytes, rlc_amd_retx_t r
rrc->get_rb_name(lcid).c_str(), nof_bytes, head_len); rrc->get_rb_name(lcid).c_str(), nof_bytes, head_len);
return 0; return 0;
} }
pdu_space = nof_bytes-head_len-2;
pdu_space = nof_bytes-head_len;
if(pdu_space < (retx.so_end-retx.so_start)) if(pdu_space < (retx.so_end-retx.so_start))
retx.so_end = retx.so_start+pdu_space; retx.so_end = retx.so_start+pdu_space;
@ -603,10 +612,13 @@ int rlc_am::build_segment(uint8_t *payload, uint32_t nof_bytes, rlc_amd_retx_t r
if(lower >= retx.so_end) if(lower >= retx.so_end)
break; break;
if(pdu_space <= 2)
break;
upper += old_header.li[i]; upper += old_header.li[i];
head_len = rlc_am_packed_length(&new_header); head_len = rlc_am_packed_length(&new_header);
pdu_space = nof_bytes-head_len-2; pdu_space = nof_bytes-head_len;
if(pdu_space < (retx.so_end-retx.so_start)) if(pdu_space < (retx.so_end-retx.so_start))
retx.so_end = retx.so_start+pdu_space; retx.so_end = retx.so_start+pdu_space;
@ -1085,11 +1097,11 @@ void rlc_am::handle_control_pdu(uint8_t *payload, uint32_t nof_bytes)
it = tx_window.find(i); it = tx_window.find(i);
if (it != tx_window.end()) { if (it != tx_window.end()) {
if(update_vt_a) { if(update_vt_a) {
tx_window.erase(it);
if(it->second.buf) { if(it->second.buf) {
pool->deallocate(it->second.buf); pool->deallocate(it->second.buf);
it->second.buf = 0; it->second.buf = 0;
} }
tx_window.erase(it);
vt_a = (vt_a + 1)%MOD; vt_a = (vt_a + 1)%MOD;
vt_ms = (vt_ms + 1)%MOD; vt_ms = (vt_ms + 1)%MOD;
} }
@ -1217,15 +1229,33 @@ void rlc_am::print_rx_segments()
bool rlc_am::add_segment_and_check(rlc_amd_rx_pdu_segments_t *pdu, rlc_amd_rx_pdu_t *segment) bool rlc_am::add_segment_and_check(rlc_amd_rx_pdu_segments_t *pdu, rlc_amd_rx_pdu_t *segment)
{ {
// Ordered insert // Check for first segment
std::list<rlc_amd_rx_pdu_t>::iterator tmpit; if(0 == segment->header.so) {
std::list<rlc_amd_rx_pdu_t>::iterator it = pdu->segments.begin(); std::list<rlc_amd_rx_pdu_t>::iterator it;
while(it != pdu->segments.end() && it->header.so < segment->header.so) for(it = pdu->segments.begin(); it != pdu->segments.end(); it++) {
it++; pool->deallocate(it->buf);
pdu->segments.insert(it, *segment); }
pdu->segments.clear();
pdu->segments.push_back(*segment);
return false;
}
// Check segment offset
uint32_t n = 0;
if(!pdu->segments.empty()) {
rlc_amd_rx_pdu_t &back = pdu->segments.back();
n = back.header.so + back.buf->N_bytes;
}
if(segment->header.so != n) {
pool->deallocate(segment->buf);
return false;
} else {
pdu->segments.push_back(*segment);
}
// Check for complete // Check for complete
uint32_t so = 0; uint32_t so = 0;
std::list<rlc_amd_rx_pdu_t>::iterator it, tmpit;
for(it = pdu->segments.begin(); it != pdu->segments.end(); it++) { for(it = pdu->segments.begin(); it != pdu->segments.end(); it++) {
if(so != it->header.so) if(so != it->header.so)
return false; return false;
@ -1287,6 +1317,7 @@ bool rlc_am::add_segment_and_check(rlc_amd_rx_pdu_segments_t *pdu, rlc_amd_rx_pd
} }
handle_data_pdu(full_pdu->msg, full_pdu->N_bytes, header); handle_data_pdu(full_pdu->msg, full_pdu->N_bytes, header);
pool->deallocate(full_pdu);
return true; return true;
} }

@ -59,6 +59,11 @@ rlc_um::rlc_um() : tx_sdu_queue(16)
pdu_lost = false; pdu_lost = false;
} }
rlc_um::~rlc_um()
{
stop();
}
void rlc_um::init(srslte::log *log_, void rlc_um::init(srslte::log *log_,
uint32_t lcid_, uint32_t lcid_,
srsue::pdcp_interface_rlc *pdcp_, srsue::pdcp_interface_rlc *pdcp_,
@ -114,12 +119,13 @@ void rlc_um::empty_queue() {
void rlc_um::stop() void rlc_um::stop()
{ {
reset(); reset();
mac_timers->timer_release_id(reordering_timer_id); if (mac_timers) {
mac_timers->timer_release_id(reordering_timer_id);
}
} }
void rlc_um::reset() void rlc_um::reset()
{ {
// Empty tx_sdu_queue before locking the mutex // Empty tx_sdu_queue before locking the mutex
empty_queue(); empty_queue();
@ -129,12 +135,17 @@ void rlc_um::reset()
vr_ux = 0; vr_ux = 0;
vr_uh = 0; vr_uh = 0;
pdu_lost = false; pdu_lost = false;
if(rx_sdu) if(rx_sdu) {
rx_sdu->reset(); rx_sdu->reset();
if(tx_sdu) }
if(tx_sdu) {
tx_sdu->reset(); tx_sdu->reset();
if(mac_timers) }
if(mac_timers) {
reordering_timer->stop(); reordering_timer->stop();
}
// Drop all messages in RX window // Drop all messages in RX window
std::map<uint32_t, rlc_umd_pdu_t>::iterator it; std::map<uint32_t, rlc_umd_pdu_t>::iterator it;

@ -47,6 +47,7 @@ public:
rlc2 = rlc2_; rlc2 = rlc2_;
fail_rate = fail_rate_; fail_rate = fail_rate_;
run_enable = true; run_enable = true;
running = false;
} }
void stop() void stop()
@ -81,9 +82,10 @@ private:
if(((float)rand()/RAND_MAX > fail_rate) && read>0) { if(((float)rand()/RAND_MAX > fail_rate) && read>0) {
rlc2->write_pdu(1, pdu->msg, opp_size); rlc2->write_pdu(1, pdu->msg, opp_size);
} }
usleep(1000); usleep(100);
} }
running = false; running = false;
byte_buffer_pool::get_instance()->deallocate(pdu);
} }
rlc_interface_mac *rlc1; rlc_interface_mac *rlc1;
@ -138,10 +140,12 @@ class rlc_am_tester
,public thread ,public thread
{ {
public: public:
rlc_am_tester(rlc_interface_pdcp *rlc_){ rlc_am_tester(rlc_interface_pdcp *rlc_, std::string name_=""){
rlc = rlc_; rlc = rlc_;
run_enable = true; run_enable = true;
running = false; running = false;
rx_pdus = 0;
name = name_;
} }
void stop() void stop()
@ -163,6 +167,7 @@ public:
{ {
assert(lcid == 1); assert(lcid == 1);
byte_buffer_pool::get_instance()->deallocate(sdu); byte_buffer_pool::get_instance()->deallocate(sdu);
std::cout << "rlc_am_tester " << name << " received " << rx_pdus++ << " PDUs" << std::endl;
} }
void write_pdu_bcch_bch(byte_buffer_t *sdu) {} void write_pdu_bcch_bch(byte_buffer_t *sdu) {}
void write_pdu_bcch_dlsch(byte_buffer_t *sdu) {} void write_pdu_bcch_dlsch(byte_buffer_t *sdu) {}
@ -186,13 +191,16 @@ private:
pdu->N_bytes = 1500; pdu->N_bytes = 1500;
pdu->msg[0] = sn++; pdu->msg[0] = sn++;
rlc->write_sdu(1, pdu); rlc->write_sdu(1, pdu);
usleep(1000); usleep(100);
} }
running = false; running = false;
} }
bool run_enable; bool run_enable;
bool running; bool running;
long rx_pdus;
std::string name;
rlc_interface_pdcp *rlc; rlc_interface_pdcp *rlc;
}; };
@ -211,13 +219,13 @@ void stress_test()
rlc rlc1; rlc rlc1;
rlc rlc2; rlc rlc2;
rlc_am_tester tester1(&rlc1); rlc_am_tester tester1(&rlc1, "tester1");
rlc_am_tester tester2(&rlc2); rlc_am_tester tester2(&rlc2, "tester2");
mac_dummy mac(&rlc1, &rlc2, fail_rate); mac_dummy mac(&rlc1, &rlc2, fail_rate);
ue_interface ue; ue_interface ue;
rlc1.init(&tester1, &tester1, &ue, &log1, &mac, 0); rlc1.init(&tester1, &tester1, &ue, &log1, &mac, 0);
rlc2.init(&tester1, &tester1, &ue, &log2, &mac, 0); rlc2.init(&tester2, &tester2, &ue, &log2, &mac, 0);
LIBLTE_RRC_RLC_CONFIG_STRUCT cnfg; LIBLTE_RRC_RLC_CONFIG_STRUCT cnfg;
cnfg.rlc_mode = LIBLTE_RRC_RLC_MODE_AM; cnfg.rlc_mode = LIBLTE_RRC_RLC_MODE_AM;
@ -234,7 +242,7 @@ void stress_test()
rlc2.add_bearer(1, cnfg_); rlc2.add_bearer(1, cnfg_);
tester1.start(7); tester1.start(7);
//tester2.start(7); tester2.start(7);
mac.start(); mac.start();
usleep(100e6); usleep(100e6);

@ -59,6 +59,14 @@ public:
n_sdus = 0; n_sdus = 0;
} }
~rlc_am_tester(){
for (uint32_t i = 0; i < 10; i++) {
if (sdus[i] != NULL) {
byte_buffer_pool::get_instance()->deallocate(sdus[i]);
}
}
}
// PDCP interface // PDCP interface
void write_pdu(uint32_t lcid, byte_buffer_t *sdu) void write_pdu(uint32_t lcid, byte_buffer_t *sdu)
{ {
@ -482,17 +490,17 @@ void resegment_test_1()
// Read the retx PDU from RLC1 and force resegmentation // Read the retx PDU from RLC1 and force resegmentation
byte_buffer_t retx1; byte_buffer_t retx1;
len = rlc1.read_pdu(retx1.msg, 11); // 4 byte header + 5 data len = rlc1.read_pdu(retx1.msg, 9); // 4 byte header + 5 data
retx1.N_bytes = len; retx1.N_bytes = len;
// Write the retx PDU to RLC2 // Write the retx PDU to RLC2
rlc2.write_pdu(retx1.msg, retx1.N_bytes); rlc2.write_pdu(retx1.msg, retx1.N_bytes);
assert(9 == rlc1.get_buffer_state()); // 4 byte header + 5 data assert(9 == rlc1.get_buffer_state());
// Read the remaining segment // Read the remaining segment
byte_buffer_t retx2; byte_buffer_t retx2;
len = rlc1.read_pdu(retx2.msg, 11); // 4 byte header + 5 data len = rlc1.read_pdu(retx2.msg, 9); // 4 byte header + 5 data
retx2.N_bytes = len; retx2.N_bytes = len;
// Write the retx PDU to RLC2 // Write the retx PDU to RLC2
@ -591,16 +599,16 @@ void resegment_test_2()
// Read the retx PDU from RLC1 and force resegmentation // Read the retx PDU from RLC1 and force resegmentation
byte_buffer_t retx1; byte_buffer_t retx1;
retx1.N_bytes = rlc1.read_pdu(retx1.msg, 18); // 6 byte header + 10 data retx1.N_bytes = rlc1.read_pdu(retx1.msg, 16); // 6 byte header + 10 data
// Write the retx PDU to RLC2 // Write the retx PDU to RLC2
rlc2.write_pdu(retx1.msg, retx1.N_bytes); rlc2.write_pdu(retx1.msg, retx1.N_bytes);
assert(16 == rlc1.get_buffer_state()); // 6 byte header + 10 data assert(16 == rlc1.get_buffer_state());
// Read the remaining segment // Read the remaining segment
byte_buffer_t retx2; byte_buffer_t retx2;
retx2.N_bytes = rlc1.read_pdu(retx2.msg, 18); // 6 byte header + 10 data retx2.N_bytes = rlc1.read_pdu(retx2.msg, 16); // 6 byte header + 10 data
// Write the retx PDU to RLC2 // Write the retx PDU to RLC2
rlc2.write_pdu(retx2.msg, retx2.N_bytes); rlc2.write_pdu(retx2.msg, retx2.N_bytes);
@ -696,14 +704,14 @@ void resegment_test_3()
// Read the retx PDU from RLC1 and force resegmentation // Read the retx PDU from RLC1 and force resegmentation
byte_buffer_t retx1; byte_buffer_t retx1;
retx1.N_bytes = rlc1.read_pdu(retx1.msg, 16); // 4 byte header + 10 data retx1.N_bytes = rlc1.read_pdu(retx1.msg, 14); // 4 byte header + 10 data
// Write the retx PDU to RLC2 // Write the retx PDU to RLC2
rlc2.write_pdu(retx1.msg, retx1.N_bytes); rlc2.write_pdu(retx1.msg, retx1.N_bytes);
// Read the remaining segment // Read the remaining segment
byte_buffer_t retx2; byte_buffer_t retx2;
retx2.N_bytes = rlc1.read_pdu(retx2.msg, 16); // 4 byte header + 10 data retx2.N_bytes = rlc1.read_pdu(retx2.msg, 14); // 4 byte header + 10 data
// Write the retx PDU to RLC2 // Write the retx PDU to RLC2
rlc2.write_pdu(retx2.msg, retx2.N_bytes); rlc2.write_pdu(retx2.msg, retx2.N_bytes);
@ -799,14 +807,14 @@ void resegment_test_4()
// Read the retx PDU from RLC1 and force resegmentation // Read the retx PDU from RLC1 and force resegmentation
byte_buffer_t retx1; byte_buffer_t retx1;
retx1.N_bytes = rlc1.read_pdu(retx1.msg, 23); // 6 byte header + 15 data retx1.N_bytes = rlc1.read_pdu(retx1.msg, 21); // 6 byte header + 15 data
// Write the retx PDU to RLC2 // Write the retx PDU to RLC2
rlc2.write_pdu(retx1.msg, retx1.N_bytes); rlc2.write_pdu(retx1.msg, retx1.N_bytes);
// Read the remaining segment // Read the remaining segment
byte_buffer_t retx2; byte_buffer_t retx2;
retx2.N_bytes = rlc1.read_pdu(retx2.msg, 23); // 6 byte header + 15 data retx2.N_bytes = rlc1.read_pdu(retx2.msg, 21); // 6 byte header + 15 data
// Write the retx PDU to RLC2 // Write the retx PDU to RLC2
rlc2.write_pdu(retx2.msg, retx2.N_bytes); rlc2.write_pdu(retx2.msg, retx2.N_bytes);
@ -902,14 +910,14 @@ void resegment_test_5()
// Read the retx PDU from RLC1 and force resegmentation // Read the retx PDU from RLC1 and force resegmentation
byte_buffer_t retx1; byte_buffer_t retx1;
retx1.N_bytes = rlc1.read_pdu(retx1.msg, 29); // 7 byte header + 20 data retx1.N_bytes = rlc1.read_pdu(retx1.msg, 27); // 7 byte header + 20 data
// Write the retx PDU to RLC2 // Write the retx PDU to RLC2
rlc2.write_pdu(retx1.msg, retx1.N_bytes); rlc2.write_pdu(retx1.msg, retx1.N_bytes);
// Read the remaining segment // Read the remaining segment
byte_buffer_t retx2; byte_buffer_t retx2;
retx2.N_bytes = rlc1.read_pdu(retx2.msg, 29); // 7 byte header + 20 data retx2.N_bytes = rlc1.read_pdu(retx2.msg, 27); // 7 byte header + 20 data
// Write the retx PDU to RLC2 // Write the retx PDU to RLC2
rlc2.write_pdu(retx2.msg, retx2.N_bytes); rlc2.write_pdu(retx2.msg, retx2.N_bytes);
@ -1023,11 +1031,11 @@ void resegment_test_6()
// Write the retx PDU to RLC2 // Write the retx PDU to RLC2
rlc2.write_pdu(retx1.msg, retx1.N_bytes); rlc2.write_pdu(retx1.msg, retx1.N_bytes);
assert(157 == rlc1.get_buffer_state()); assert(155 == rlc1.get_buffer_state());
// Read the remaining segment // Read the remaining segment
byte_buffer_t retx2; byte_buffer_t retx2;
len = rlc1.read_pdu(retx2.msg, 159); len = rlc1.read_pdu(retx2.msg, 157);
retx2.N_bytes = len; retx2.N_bytes = len;
// Write the retx PDU to RLC2 // Write the retx PDU to RLC2
@ -1048,24 +1056,91 @@ void resegment_test_6()
} }
} }
void reset_test()
{
srslte::log_filter log1("RLC_AM_1");
srslte::log_filter log2("RLC_AM_2");
log1.set_level(srslte::LOG_LEVEL_DEBUG);
log2.set_level(srslte::LOG_LEVEL_DEBUG);
log1.set_hex_limit(-1);
log2.set_hex_limit(-1);
rlc_am_tester tester;
mac_dummy_timers timers;
rlc_am rlc1;
int len;
log1.set_level(srslte::LOG_LEVEL_DEBUG);
rlc1.init(&log1, 1, &tester, &tester, &timers);
LIBLTE_RRC_RLC_CONFIG_STRUCT cnfg;
cnfg.rlc_mode = LIBLTE_RRC_RLC_MODE_AM;
cnfg.dl_am_rlc.t_reordering = LIBLTE_RRC_T_REORDERING_MS5;
cnfg.dl_am_rlc.t_status_prohibit = LIBLTE_RRC_T_STATUS_PROHIBIT_MS5;
cnfg.ul_am_rlc.max_retx_thresh = LIBLTE_RRC_MAX_RETX_THRESHOLD_T4;
cnfg.ul_am_rlc.poll_byte = LIBLTE_RRC_POLL_BYTE_KB25;
cnfg.ul_am_rlc.poll_pdu = LIBLTE_RRC_POLL_PDU_P4;
cnfg.ul_am_rlc.t_poll_retx = LIBLTE_RRC_T_POLL_RETRANSMIT_MS5;
rlc1.configure(&cnfg);
// Push 1 SDU of size 10 into RLC1
byte_buffer_t sdu_buf;
*sdu_buf.msg = 1; // Write the index into the buffer
sdu_buf.N_bytes = 100;
rlc1.write_sdu(&sdu_buf);
// read 1 PDU from RLC1 and force segmentation
byte_buffer_t pdu_bufs;
len = rlc1.read_pdu(pdu_bufs.msg, 4);
pdu_bufs.N_bytes = len;
// reset RLC1
rlc1.reset();
// read another PDU segment from RLC1
len = rlc1.read_pdu(pdu_bufs.msg, 4);
pdu_bufs.N_bytes = len;
// now empty RLC buffer
len = rlc1.read_pdu(pdu_bufs.msg, 100);
pdu_bufs.N_bytes = len;
assert(0 == rlc1.get_buffer_state());
}
int main(int argc, char **argv) { int main(int argc, char **argv) {
basic_test(); basic_test();
byte_buffer_pool::get_instance()->cleanup(); byte_buffer_pool::get_instance()->cleanup();
concat_test(); concat_test();
byte_buffer_pool::get_instance()->cleanup(); byte_buffer_pool::get_instance()->cleanup();
segment_test(); segment_test();
byte_buffer_pool::get_instance()->cleanup(); byte_buffer_pool::get_instance()->cleanup();
retx_test(); retx_test();
byte_buffer_pool::get_instance()->cleanup(); byte_buffer_pool::get_instance()->cleanup();
resegment_test_1(); resegment_test_1();
byte_buffer_pool::get_instance()->cleanup(); byte_buffer_pool::get_instance()->cleanup();
resegment_test_2(); resegment_test_2();
byte_buffer_pool::get_instance()->cleanup(); byte_buffer_pool::get_instance()->cleanup();
resegment_test_3(); resegment_test_3();
byte_buffer_pool::get_instance()->cleanup(); byte_buffer_pool::get_instance()->cleanup();
resegment_test_4(); resegment_test_4();
byte_buffer_pool::get_instance()->cleanup(); byte_buffer_pool::get_instance()->cleanup();
resegment_test_5(); resegment_test_5();
byte_buffer_pool::get_instance()->cleanup(); byte_buffer_pool::get_instance()->cleanup();
resegment_test_6(); resegment_test_6();
byte_buffer_pool::get_instance()->cleanup();
reset_test();
byte_buffer_pool::get_instance()->cleanup();
} }

@ -62,6 +62,14 @@ public:
n_sdus = 0; n_sdus = 0;
} }
~rlc_um_tester(){
for (uint32_t i = 0; i < NBUFS; i++) {
if (sdus[i] != NULL) {
byte_buffer_pool::get_instance()->deallocate(sdus[i]);
}
}
}
// PDCP interface // PDCP interface
void write_pdu(uint32_t lcid, byte_buffer_t *sdu) void write_pdu(uint32_t lcid, byte_buffer_t *sdu)
{ {

@ -1,3 +1,28 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2017 Software Radio Systems Limited
*
* \section LICENSE
*
* This file is part of srsLTE.
*
* srsUE 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.
*
* srsUE 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 <string.h> #include <string.h>

@ -1,3 +1,28 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2017 Software Radio Systems Limited
*
* \section LICENSE
*
* This file is part of srsLTE.
*
* srsUE 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.
*
* srsUE 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 <unistd.h> #include <unistd.h>

@ -1,3 +1,29 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2017 Software Radio Systems Limited
*
* \section LICENSE
*
* This file is part of srsLTE.
*
* srsUE 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.
*
* srsUE 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 <sys/types.h> #include <sys/types.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <fcntl.h> #include <fcntl.h>

@ -24,6 +24,7 @@
* *
*/ */
#include <iostream>
#include "mme/s1ap.h" #include "mme/s1ap.h"
#include "mme/s1ap_nas_transport.h" #include "mme/s1ap_nas_transport.h"
#include "srslte/common/security.h" #include "srslte/common/security.h"

@ -68,6 +68,9 @@ public:
void msg3_flush(); void msg3_flush();
bool msg3_is_transmitted(); bool msg3_is_transmitted();
void msg3_prepare();
bool msg3_is_pending();
void append_crnti_ce_next_tx(uint16_t crnti); void append_crnti_ce_next_tx(uint16_t crnti);
void set_priority(uint32_t lcid, uint32_t priority, int PBR_x_tti, uint32_t BSD); void set_priority(uint32_t lcid, uint32_t priority, int PBR_x_tti, uint32_t BSD);
@ -105,6 +108,7 @@ private:
/* PDU Buffer */ /* PDU Buffer */
srslte::sch_pdu pdu_msg; srslte::sch_pdu pdu_msg;
bool msg3_has_been_transmitted; bool msg3_has_been_transmitted;
bool msg3_pending;
}; };
} // namespace srsue } // namespace srsue

@ -237,8 +237,8 @@ private:
// New transmission // New transmission
reset(); reset();
// Uplink grant in a RAR // Uplink grant in a RAR and there is a PDU in the Msg3 buffer
if (grant->is_from_rar) { if (grant->is_from_rar && harq_entity->mux_unit->msg3_is_pending()) {
Debug("Getting Msg3 buffer payload, grant size=%d bytes\n", grant->n_bytes[0]); Debug("Getting Msg3 buffer payload, grant size=%d bytes\n", grant->n_bytes[0]);
pdu_ptr = harq_entity->mux_unit->msg3_get(payload_buffer, grant->n_bytes[0]); pdu_ptr = harq_entity->mux_unit->msg3_get(payload_buffer, grant->n_bytes[0]);
if (pdu_ptr) { if (pdu_ptr) {
@ -246,9 +246,13 @@ private:
} else { } else {
Warning("UL RAR grant available but no Msg3 on buffer\n"); Warning("UL RAR grant available but no Msg3 on buffer\n");
} }
printf("Transmitted Msg3\n");
// Normal UL grant // Normal UL grant
} else { } else {
if (grant->is_from_rar) {
grant->rnti = harq_entity->rntis->crnti;
}
// Request a MAC PDU from the Multiplexing & Assemble Unit // Request a MAC PDU from the Multiplexing & Assemble Unit
pdu_ptr = harq_entity->mux_unit->pdu_get(payload_buffer, grant->n_bytes[0], tti_tx, pid); pdu_ptr = harq_entity->mux_unit->pdu_get(payload_buffer, grant->n_bytes[0], tti_tx, pid);
if (pdu_ptr) { if (pdu_ptr) {
@ -268,7 +272,7 @@ private:
generate_retx(tti_tx, action); generate_retx(tti_tx, action);
} }
if (harq_entity->pcap && grant) { if (harq_entity->pcap && grant) {
if (grant->is_from_rar) { if (grant->is_from_rar && harq_entity->rntis->temp_rnti) {
grant->rnti = harq_entity->rntis->temp_rnti; grant->rnti = harq_entity->rntis->temp_rnti;
} }
harq_entity->pcap->write_ul_crnti(pdu_ptr, grant->n_bytes[0], grant->rnti, get_nof_retx(), tti_tx); harq_entity->pcap->write_ul_crnti(pdu_ptr, grant->n_bytes[0], grant->rnti, get_nof_retx(), tti_tx);

@ -87,6 +87,9 @@ public:
uint32_t last_ul_tti[2*HARQ_DELAY_MS]; uint32_t last_ul_tti[2*HARQ_DELAY_MS];
srslte_mod_t last_ul_mod[2*HARQ_DELAY_MS]; srslte_mod_t last_ul_mod[2*HARQ_DELAY_MS];
uint8_t last_ri;
uint8_t last_pmi;
phch_common(uint32_t max_mutex = 3); phch_common(uint32_t max_mutex = 3);
void init(phy_interface_rrc::phy_cfg_t *config, void init(phy_interface_rrc::phy_cfg_t *config,
phy_args_t *args, phy_args_t *args,

@ -125,6 +125,7 @@ private:
float get_last_gain(); float get_last_gain();
float get_last_cfo(); float get_last_cfo();
void set_N_id_2(int N_id_2); void set_N_id_2(int N_id_2);
void set_agc_enable(bool enable);
ret_code run(srslte_cell_t *cell); ret_code run(srslte_cell_t *cell);
private: private:
@ -308,10 +309,11 @@ private:
CELL_SELECT, CELL_SELECT,
CELL_RESELECT, CELL_RESELECT,
CELL_MEASURE, CELL_MEASURE,
CELL_CAMP CELL_CAMP,
IDLE_RX
} phy_state; } phy_state;
bool is_in_idle; bool is_in_idle, is_in_idle_rx;
// Sampling rate mode (find is 1.96 MHz, camp is the full cell BW) // Sampling rate mode (find is 1.96 MHz, camp is the full cell BW)
enum { enum {

@ -70,6 +70,9 @@ public:
void start_plot(); void start_plot();
float get_ref_cfo(); float get_ref_cfo();
float get_snr();
float get_rsrp();
float get_noise();
float get_cfo(); float get_cfo();
float get_ul_cfo(); float get_ul_cfo();

@ -53,7 +53,7 @@ public:
bool init(srslte::radio_multi *radio_handler, bool init(srslte::radio_multi *radio_handler,
mac_interface_phy *mac, mac_interface_phy *mac,
rrc_interface_phy *rrc, rrc_interface_phy *rrc,
std::vector<void*> log_vec, std::vector<srslte::log*> log_vec,
phy_args_t *args = NULL); phy_args_t *args = NULL);
void stop(); void stop();
@ -159,7 +159,7 @@ private:
const static int WORKERS_THREAD_PRIO = 0; const static int WORKERS_THREAD_PRIO = 0;
srslte::radio_multi *radio_handler; srslte::radio_multi *radio_handler;
std::vector<void*> log_vec; std::vector<srslte::log*> log_vec;
srslte::log *log_h; srslte::log *log_h;
srslte::log *log_phy_lib_h; srslte::log *log_phy_lib_h;
srsue::mac_interface_phy *mac; srsue::mac_interface_phy *mac;

@ -101,7 +101,7 @@ private:
srslte::logger *logger; srslte::logger *logger;
// rf_log is on ue_base // rf_log is on ue_base
std::vector<void*> phy_log; std::vector<srslte::log*> phy_log;
srslte::log_filter mac_log; srslte::log_filter mac_log;
srslte::log_filter rlc_log; srslte::log_filter rlc_log;
srslte::log_filter pdcp_log; srslte::log_filter pdcp_log;

@ -76,17 +76,22 @@ class cell_t
return false; return false;
} }
cell_t() { cell_t() {
this->has_valid_sib1 = false; srslte_cell_t tmp = {};
this->has_valid_sib2 = false; cell_t(tmp, 0, 0);
this->has_valid_sib3 = false;
} }
cell_t(srslte_cell_t phy_cell, uint32_t earfcn, float rsrp) { cell_t(srslte_cell_t phy_cell, uint32_t earfcn, float rsrp) {
this->has_valid_sib1 = false; this->has_valid_sib1 = false;
this->has_valid_sib2 = false; this->has_valid_sib2 = false;
this->has_valid_sib3 = false; this->has_valid_sib3 = false;
this->has_valid_sib13 = false;
this->phy_cell = phy_cell; this->phy_cell = phy_cell;
this->rsrp = rsrp; this->rsrp = rsrp;
this->earfcn = earfcn; this->earfcn = earfcn;
in_sync = true;
bzero(&sib1, sizeof(sib1));
bzero(&sib2, sizeof(sib2));
bzero(&sib3, sizeof(sib3));
bzero(&sib13, sizeof(sib13));
} }
uint32_t earfcn; uint32_t earfcn;
@ -114,6 +119,7 @@ class rrc
{ {
public: public:
rrc(); rrc();
~rrc();
void init(phy_interface_rrc *phy_, void init(phy_interface_rrc *phy_,
mac_interface_rrc *mac_, mac_interface_rrc *mac_,

@ -65,6 +65,7 @@ void mux::reset()
for (uint32_t i=0;i<lch.size();i++) { for (uint32_t i=0;i<lch.size();i++) {
lch[i].Bj = 0; lch[i].Bj = 0;
} }
msg3_pending = false;
pending_crnti_ce = 0; pending_crnti_ce = 0;
} }
@ -344,6 +345,7 @@ void mux::msg3_flush()
Debug("Msg3 buffer flushed\n"); Debug("Msg3 buffer flushed\n");
} }
msg3_has_been_transmitted = false; msg3_has_been_transmitted = false;
msg3_pending = false;
bzero(msg3_buff, sizeof(MSG3_BUFF_SZ)); bzero(msg3_buff, sizeof(MSG3_BUFF_SZ));
} }
@ -352,6 +354,14 @@ bool mux::msg3_is_transmitted()
return msg3_has_been_transmitted; return msg3_has_been_transmitted;
} }
void mux::msg3_prepare() {
msg3_pending = true;
}
bool mux::msg3_is_pending() {
return msg3_pending;
}
/* Returns a pointer to the Msg3 buffer */ /* Returns a pointer to the Msg3 buffer */
uint8_t* mux::msg3_get(uint8_t *payload, uint32_t pdu_sz) uint8_t* mux::msg3_get(uint8_t *payload, uint32_t pdu_sz)
{ {
@ -363,6 +373,7 @@ uint8_t* mux::msg3_get(uint8_t *payload, uint32_t pdu_sz)
} }
memcpy(payload, msg3_buff_start_pdu, sizeof(uint8_t)*pdu_sz); memcpy(payload, msg3_buff_start_pdu, sizeof(uint8_t)*pdu_sz);
msg3_has_been_transmitted = true; msg3_has_been_transmitted = true;
msg3_pending = false;
return payload; return payload;
} else { } else {
Error("Msg3 size (%d) is longer than internal msg3_buff size=%d, (see mux.h)\n", pdu_sz, MSG3_BUFF_SZ-32); Error("Msg3 size (%d) is longer than internal msg3_buff size=%d, (see mux.h)\n", pdu_sz, MSG3_BUFF_SZ-32);

@ -350,6 +350,7 @@ void ra_proc::tb_decoded_ok() {
state = COMPLETION; state = COMPLETION;
} else { } else {
// Preamble selected by UE MAC // Preamble selected by UE MAC
mux_unit->msg3_prepare();
rntis->temp_rnti = rar_pdu_msg.get()->get_temp_crnti(); rntis->temp_rnti = rar_pdu_msg.get()->get_temp_crnti();
phy_h->pdcch_dl_search(SRSLTE_RNTI_TEMP, rar_pdu_msg.get()->get_temp_crnti()); phy_h->pdcch_dl_search(SRSLTE_RNTI_TEMP, rar_pdu_msg.get()->get_temp_crnti());

@ -162,7 +162,11 @@ void parse_args(all_args_t *args, int argc, char *argv[]) {
bpo::value<bool>(&args->expert.phy.rssi_sensor_enabled)->default_value(true), bpo::value<bool>(&args->expert.phy.rssi_sensor_enabled)->default_value(true),
"Enable or disable RF frontend RSSI sensor. In some USRP devices can cause segmentation fault") "Enable or disable RF frontend RSSI sensor. In some USRP devices can cause segmentation fault")
("expert.prach_gain", ("expert.rx_gain_offset",
bpo::value<float>(&args->expert.phy.rx_gain_offset)->default_value(10),
"RX Gain offset to add to rx_gain to correct RSRP value")
("expert.prach_gain",
bpo::value<float>(&args->expert.phy.prach_gain)->default_value(-1.0), bpo::value<float>(&args->expert.phy.prach_gain)->default_value(-1.0),
"Disable PRACH power control") "Disable PRACH power control")

@ -48,6 +48,8 @@ phch_common::phch_common(uint32_t max_mutex_) : tx_mutex(max_mutex_)
max_mutex = max_mutex_; max_mutex = max_mutex_;
nof_mutex = 0; nof_mutex = 0;
rx_gain_offset = 0; rx_gain_offset = 0;
last_ri = 0;
last_pmi = 0;
bzero(&dl_metrics, sizeof(dl_metrics_t)); bzero(&dl_metrics, sizeof(dl_metrics_t));
dl_metrics_read = true; dl_metrics_read = true;
@ -62,9 +64,10 @@ phch_common::phch_common(uint32_t max_mutex_) : tx_mutex(max_mutex_)
bzero(zeros, 50000*sizeof(cf_t)); bzero(zeros, 50000*sizeof(cf_t));
// FIXME: This is an ugly fix to avoid the TX filters to empty // FIXME: This is an ugly fix to avoid the TX filters to empty
/*
for (int i=0;i<50000;i++) { for (int i=0;i<50000;i++) {
zeros[i] = 0.01*cexpf(((float) i/50000)*0.1*_Complex_I); zeros[i] = 0.01*cexpf(((float) i/50000)*0.1*_Complex_I);
} }*/
reset(); reset();

@ -174,16 +174,21 @@ bool phch_recv::wait_radio_reset() {
void phch_recv::set_agc_enable(bool enable) void phch_recv::set_agc_enable(bool enable)
{ {
do_agc = enable; do_agc = enable;
if (do_agc) {
if (running && radio_h) {
srslte_ue_sync_start_agc(&ue_sync, callback_set_rx_gain, radio_h->get_rx_gain());
search_p.set_agc_enable(true);
} else {
fprintf(stderr, "Error setting AGC: PHY not initiatec\n");
}
} else {
fprintf(stderr, "Error stopping AGC: not implemented\n");
}
} }
void phch_recv::set_time_adv_sec(float _time_adv_sec) void phch_recv::set_time_adv_sec(float time_adv_sec)
{ {
if (TX_MODE_CONTINUOUS && !radio_h->is_first_of_burst()) { this->time_adv_sec = time_adv_sec;
int nsamples = ceil(current_srate*_time_adv_sec);
next_offset = -nsamples;
} else {
time_adv_sec = _time_adv_sec;
}
} }
void phch_recv::set_ue_sync_opts(srslte_ue_sync_t *q, float cfo) void phch_recv::set_ue_sync_opts(srslte_ue_sync_t *q, float cfo)
@ -375,18 +380,30 @@ bool phch_recv::cell_handover(srslte_cell_t cell)
log_h->info("Cell HO: Waiting pending PHICH\n"); log_h->info("Cell HO: Waiting pending PHICH\n");
} }
bool ret; bool ret = false;
this->cell = cell; this->cell = cell;
Info("Cell HO: Stopping sync with current cell\n"); Info("Cell HO: Stopping sync with current cell\n");
worker_com->reset_ul(); worker_com->reset_ul();
stop_sync(); phy_state = IDLE_RX;
Info("Cell HO: Reconfiguring cell\n"); cnt = 0;
if (set_cell()) { while(!is_in_idle_rx && cnt<20) {
Info("Cell HO: Synchronizing with new cell\n"); usleep(1000);
resync_sfn(true, true); cnt++;
ret = true; }
if (is_in_idle_rx) {
Info("Cell HO: Reconfiguring cell\n");
if (set_cell()) {
//resync_sfn(true, true);
sfn_p.reset();
phy_state = CELL_RESELECT;
Info("Cell HO: Synchronizing with new cell\n");
ret = true;
} else {
log_h->error("Cell HO: Configuring cell PCI=%d\n", cell.id);
ret = false;
}
} else { } else {
log_h->error("Cell HO: Configuring cell PCI=%d\n", cell.id); log_h->error("Cell HO: Could not stop sync\n");
ret = false; ret = false;
} }
return ret; return ret;
@ -567,6 +584,7 @@ void phch_recv::run_thread()
uint32_t sf_idx = 0; uint32_t sf_idx = 0;
phy_state = IDLE; phy_state = IDLE;
is_in_idle = true; is_in_idle = true;
is_in_idle_rx = false;
while (running) while (running)
{ {
@ -575,6 +593,10 @@ void phch_recv::run_thread()
Debug("SYNC: state=%d\n", phy_state); Debug("SYNC: state=%d\n", phy_state);
} }
if (phy_state != IDLE_RX) {
is_in_idle_rx = false;
}
log_h->step(tti); log_h->step(tti);
log_phy_lib_h->step(tti); log_phy_lib_h->step(tti);
@ -665,10 +687,11 @@ void phch_recv::run_thread()
case 1: case 1:
if (last_worker) { if (last_worker) {
Debug("SF: cfo_tot=%7.1f Hz, ref=%f Hz, pss=%f Hz\n", Debug("SF: cfo_tot=%7.1f Hz, ref=%f Hz, pss=%f Hz, snr_sf=%.2f dB, rsrp=%.2f dB, noise=%.2f dB\n",
srslte_ue_sync_get_cfo(&ue_sync), srslte_ue_sync_get_cfo(&ue_sync),
15000*last_worker->get_ref_cfo(), 15000*last_worker->get_ref_cfo(),
15000*ue_sync.strack.cfo_pss_mean); 15000*ue_sync.strack.cfo_pss_mean,
last_worker->get_snr(), last_worker->get_rsrp(), last_worker->get_noise());
} }
last_worker = worker; last_worker = worker;
@ -739,6 +762,23 @@ void phch_recv::run_thread()
is_in_idle = true; is_in_idle = true;
usleep(1000); usleep(1000);
break; break;
case IDLE_RX:
if (!worker) {
worker = (phch_worker *) workers_pool->wait_worker(tti);
}
is_in_idle_rx = true;
if (worker) {
for (uint32_t i = 0; i < SRSLTE_MAX_PORTS; i++) {
buffer[i] = worker->get_buffer(i);
}
if (!radio_h->rx_now(buffer, SRSLTE_SF_LEN_PRB(cell.nof_prb), NULL)) {
Error("SYNC: Receiving from radio while in IDLE_RX\n");
}
} else {
// wait_worker() only returns NULL if it's being closed. Quit now to avoid unnecessary loops here
running = false;
}
break;
} }
// Increase TTI counter and trigger MAC clock (lower priority) // Increase TTI counter and trigger MAC clock (lower priority)
@ -832,6 +872,14 @@ float phch_recv::search::get_last_cfo()
return srslte_ue_sync_get_cfo(&ue_mib_sync.ue_sync); return srslte_ue_sync_get_cfo(&ue_mib_sync.ue_sync);
} }
void phch_recv::search::set_agc_enable(bool enable) {
if (enable) {
srslte_ue_sync_start_agc(&ue_mib_sync.ue_sync, callback_set_rx_gain, p->radio_h->get_rx_gain());
} else {
fprintf(stderr, "Error stop AGC not implemented\n");
}
}
phch_recv::search::ret_code phch_recv::search::run(srslte_cell_t *cell) phch_recv::search::ret_code phch_recv::search::run(srslte_cell_t *cell)
{ {
@ -891,11 +939,6 @@ phch_recv::search::ret_code phch_recv::search::run(srslte_cell_t *cell)
// Set options defined in expert section // Set options defined in expert section
p->set_ue_sync_opts(&ue_mib_sync.ue_sync, cfo); p->set_ue_sync_opts(&ue_mib_sync.ue_sync, cfo);
// Start AGC after initial cell search
if (p->do_agc) {
srslte_ue_sync_start_agc(&ue_mib_sync.ue_sync, callback_set_rx_gain, p->radio_h->get_rx_gain());
}
srslte_ue_sync_reset(&ue_mib_sync.ue_sync); srslte_ue_sync_reset(&ue_mib_sync.ue_sync);
/* Find and decode MIB */ /* Find and decode MIB */
@ -1011,7 +1054,6 @@ phch_recv::sfn_sync::ret_code phch_recv::sfn_sync::run_subframe(srslte_cell_t *c
Info("SYNC: DONE, TTI=%d, sfn_offset=%d\n", *tti_cnt, sfn_offset); Info("SYNC: DONE, TTI=%d, sfn_offset=%d\n", *tti_cnt, sfn_offset);
} }
srslte_ue_sync_set_agc_period(ue_sync, 20);
srslte_ue_sync_decode_sss_on_track(ue_sync, true); srslte_ue_sync_decode_sss_on_track(ue_sync, true);
reset(); reset();
return SFN_FOUND; return SFN_FOUND;
@ -1169,6 +1211,9 @@ phch_recv::measure::ret_code phch_recv::measure::run_multiple_subframes(cf_t *in
return ret; return ret;
} }
} }
if (ret != ERROR) {
return MEASURE_OK;
}
} else { } else {
Info("INTRA: not running because offset=%d, sf_len*max_sf=%d*%d\n", offset, sf_len, max_sf); Info("INTRA: not running because offset=%d, sf_len*max_sf=%d*%d\n", offset, sf_len, max_sf);
} }
@ -1216,9 +1261,6 @@ phch_recv::measure::ret_code phch_recv::measure::run_subframe(uint32_t sf_idx)
} }
mean_rsrp -= temporal_offset; mean_rsrp -= temporal_offset;
} }
}
if (cnt > 2) {
return MEASURE_OK; return MEASURE_OK;
} else { } else {
return IDLE; return IDLE;
@ -1264,13 +1306,11 @@ void phch_recv::scell_recv::init(srslte::log *log_h, bool sic_pss_enabled, uint3
srslte_sync_set_cfo_i_enable(&sync_find, false); srslte_sync_set_cfo_i_enable(&sync_find, false);
srslte_sync_set_cfo_pss_enable(&sync_find, true); srslte_sync_set_cfo_pss_enable(&sync_find, true);
srslte_sync_set_pss_filt_enable(&sync_find, true); srslte_sync_set_pss_filt_enable(&sync_find, true);
srslte_sync_set_sss_eq_enable(&sync_find, false); srslte_sync_set_sss_eq_enable(&sync_find, true);
sync_find.pss.chest_on_filter = true; sync_find.pss.chest_on_filter = true;
if (!sic_pss_enabled) { sync_find.sss_channel_equalize = true;
sync_find.sss_channel_equalize = false;
}
reset(); reset();
} }
@ -1311,13 +1351,12 @@ int phch_recv::scell_recv::find_cells(cf_t *input_buffer, float rx_gain_offset,
if (n_id_2 != (cell.id%3) || sic_pss_enabled) { if (n_id_2 != (cell.id%3) || sic_pss_enabled) {
srslte_sync_set_N_id_2(&sync_find, n_id_2); srslte_sync_set_N_id_2(&sync_find, n_id_2);
srslte_sync_find_ret_t sync_res, best_sync_res; srslte_sync_find_ret_t sync_res;
do { do {
srslte_sync_reset(&sync_find); srslte_sync_reset(&sync_find);
srslte_sync_cfo_reset(&sync_find); srslte_sync_cfo_reset(&sync_find);
best_sync_res = SRSLTE_SYNC_NOFOUND;
sync_res = SRSLTE_SYNC_NOFOUND; sync_res = SRSLTE_SYNC_NOFOUND;
cell_id = 0; cell_id = 0;
float max_peak = -1; float max_peak = -1;
@ -1330,14 +1369,13 @@ int phch_recv::scell_recv::find_cells(cf_t *input_buffer, float rx_gain_offset,
n_id_2, sf5_cnt, nof_sf/5, sync_res, srslte_sync_get_sf_idx(&sync_find), peak_idx, sync_find.peak_value); n_id_2, sf5_cnt, nof_sf/5, sync_res, srslte_sync_get_sf_idx(&sync_find), peak_idx, sync_find.peak_value);
if (sync_find.peak_value > max_peak && sync_res == SRSLTE_SYNC_FOUND) { if (sync_find.peak_value > max_peak && sync_res == SRSLTE_SYNC_FOUND) {
best_sync_res = sync_res;
max_sf5 = sf5_cnt; max_sf5 = sf5_cnt;
max_sf_idx = srslte_sync_get_sf_idx(&sync_find); max_sf_idx = srslte_sync_get_sf_idx(&sync_find);
cell_id = srslte_sync_get_cell_id(&sync_find); cell_id = srslte_sync_get_cell_id(&sync_find);
} }
} }
switch(best_sync_res) { switch(sync_res) {
case SRSLTE_SYNC_ERROR: case SRSLTE_SYNC_ERROR:
return SRSLTE_ERROR; return SRSLTE_ERROR;
fprintf(stderr, "Error finding correlation peak\n"); fprintf(stderr, "Error finding correlation peak\n");

@ -203,6 +203,22 @@ float phch_worker::get_ref_cfo()
return srslte_chest_dl_get_cfo(&ue_dl.chest); return srslte_chest_dl_get_cfo(&ue_dl.chest);
} }
float phch_worker::get_snr()
{
return 10*log10(srslte_chest_dl_get_snr(&ue_dl.chest));
}
float phch_worker::get_rsrp()
{
return 10*log10(srslte_chest_dl_get_rsrp(&ue_dl.chest));
}
float phch_worker::get_noise()
{
return 10*log10(srslte_chest_dl_get_noise_estimate(&ue_dl.chest));
}
float phch_worker::get_cfo() float phch_worker::get_cfo()
{ {
return cfo; return cfo;
@ -874,19 +890,20 @@ void phch_worker::set_uci_periodic_cqi()
int cqi_fixed = phy->args->cqi_fixed; int cqi_fixed = phy->args->cqi_fixed;
int cqi_max = phy->args->cqi_max; int cqi_max = phy->args->cqi_max;
uint8_t ri = (uint8_t) ue_dl.ri; float sinr = ue_dl.sinr[phy->last_ri & SRSLTE_MAX_LAYERS][phy->last_pmi % SRSLTE_MAX_CODEBOOKS];
uint8_t pmi = (uint8_t) ue_dl.pmi[ri];
float sinr = ue_dl.sinr[ri][pmi];
if (period_cqi.configured && rnti_is_set) { if (period_cqi.configured && rnti_is_set) {
if (period_cqi.ri_idx_present && srslte_ri_send(period_cqi.pmi_idx, period_cqi.ri_idx, TTI_TX(tti))) { if (period_cqi.ri_idx_present && srslte_ri_send(period_cqi.pmi_idx, period_cqi.ri_idx, TTI_TX(tti))) {
/* Compute RI, PMI and SINR */ /* Compute RI, PMI and SINR */
compute_ri(&ri, &pmi, &sinr); compute_ri(&phy->last_ri, &phy->last_pmi, &sinr);
uci_data.uci_ri = ri; uci_data.uci_ri = phy->last_ri;
uci_data.uci_ri_len = 1; uci_data.uci_ri_len = 1;
uci_data.ri_periodic_report = true; uci_data.ri_periodic_report = true;
Debug("PUCCH: Periodic ri=%d\n", ri); Debug("PUCCH: Periodic ri=%d, SINR=%.1f\n", phy->last_ri, sinr);
} else if (srslte_cqi_send(period_cqi.pmi_idx, TTI_TX(tti))) { } else if (srslte_cqi_send(period_cqi.pmi_idx, TTI_TX(tti))) {
compute_ri(NULL, NULL, NULL);
phy->last_pmi = (uint8_t) ue_dl.pmi[phy->last_ri % SRSLTE_MAX_LAYERS];
srslte_cqi_value_t cqi_report = {0}; srslte_cqi_value_t cqi_report = {0};
if (period_cqi.format_is_subband) { if (period_cqi.format_is_subband) {
// TODO: Implement subband periodic reports // TODO: Implement subband periodic reports
@ -907,8 +924,8 @@ void phch_worker::set_uci_periodic_cqi()
} }
if (phy->config->dedicated.antenna_info_explicit_value.tx_mode == LIBLTE_RRC_TRANSMISSION_MODE_4) { if (phy->config->dedicated.antenna_info_explicit_value.tx_mode == LIBLTE_RRC_TRANSMISSION_MODE_4) {
cqi_report.wideband.pmi_present = true; cqi_report.wideband.pmi_present = true;
cqi_report.wideband.pmi = pmi; cqi_report.wideband.pmi = phy->last_pmi;
cqi_report.wideband.rank_is_not_one = (ri != 0); cqi_report.wideband.rank_is_not_one = (phy->last_ri != 0);
} }
Debug("PUCCH: Periodic CQI=%d, SNR=%.1f dB\n", cqi_report.wideband.wideband_cqi, phy->avg_snr_db); Debug("PUCCH: Periodic CQI=%d, SNR=%.1f dB\n", cqi_report.wideband.wideband_cqi, phy->avg_snr_db);
} }
@ -920,13 +937,11 @@ void phch_worker::set_uci_periodic_cqi()
void phch_worker::set_uci_aperiodic_cqi() void phch_worker::set_uci_aperiodic_cqi()
{ {
uint8_t ri = (uint8_t) ue_dl.ri; float sinr_db = ue_dl.sinr[phy->last_ri % SRSLTE_MAX_LAYERS][phy->last_pmi%SRSLTE_MAX_CODEBOOKS];
uint8_t pmi = (uint8_t) ue_dl.pmi[ri];
float sinr_db = ue_dl.sinr[ri][pmi];
if (phy->config->dedicated.cqi_report_cnfg.report_mode_aperiodic_present) { if (phy->config->dedicated.cqi_report_cnfg.report_mode_aperiodic_present) {
/* Compute RI, PMI and SINR */ /* Compute RI, PMI and SINR */
compute_ri(&ri, &pmi, &sinr_db); compute_ri(&phy->last_ri, &phy->last_pmi, &sinr_db);
switch(phy->config->dedicated.cqi_report_cnfg.report_mode_aperiodic) { switch(phy->config->dedicated.cqi_report_cnfg.report_mode_aperiodic) {
case LIBLTE_RRC_CQI_REPORT_MODE_APERIODIC_RM30: case LIBLTE_RRC_CQI_REPORT_MODE_APERIODIC_RM30:
@ -961,7 +976,7 @@ void phch_worker::set_uci_aperiodic_cqi()
/* Set RI = 1 */ /* Set RI = 1 */
if (phy->config->dedicated.antenna_info_explicit_value.tx_mode == LIBLTE_RRC_TRANSMISSION_MODE_3 || if (phy->config->dedicated.antenna_info_explicit_value.tx_mode == LIBLTE_RRC_TRANSMISSION_MODE_3 ||
phy->config->dedicated.antenna_info_explicit_value.tx_mode == LIBLTE_RRC_TRANSMISSION_MODE_4) { phy->config->dedicated.antenna_info_explicit_value.tx_mode == LIBLTE_RRC_TRANSMISSION_MODE_4) {
uci_data.uci_ri = ri; uci_data.uci_ri = phy->last_ri;
uci_data.uci_ri_len = 1; uci_data.uci_ri_len = 1;
} else { } else {
uci_data.uci_ri_len = 0; uci_data.uci_ri_len = 0;
@ -991,13 +1006,13 @@ void phch_worker::set_uci_aperiodic_cqi()
cqi_report.subband_hl.wideband_cqi_cw0 = srslte_cqi_from_snr(sinr_db); cqi_report.subband_hl.wideband_cqi_cw0 = srslte_cqi_from_snr(sinr_db);
cqi_report.subband_hl.subband_diff_cqi_cw0 = 0; // Always report zero offset on all subbands cqi_report.subband_hl.subband_diff_cqi_cw0 = 0; // Always report zero offset on all subbands
if (ri > 0) { if (phy->last_ri > 0) {
cqi_report.subband_hl.rank_is_not_one = true; cqi_report.subband_hl.rank_is_not_one = true;
cqi_report.subband_hl.wideband_cqi_cw1 = srslte_cqi_from_snr(sinr_db); cqi_report.subband_hl.wideband_cqi_cw1 = srslte_cqi_from_snr(sinr_db);
cqi_report.subband_hl.subband_diff_cqi_cw1 = 0; // Always report zero offset on all subbands cqi_report.subband_hl.subband_diff_cqi_cw1 = 0; // Always report zero offset on all subbands
} }
cqi_report.subband_hl.pmi = pmi; cqi_report.subband_hl.pmi = phy->last_pmi;
cqi_report.subband_hl.pmi_present = true; cqi_report.subband_hl.pmi_present = true;
cqi_report.subband_hl.four_antenna_ports = (cell.nof_ports == 4); cqi_report.subband_hl.four_antenna_ports = (cell.nof_ports == 4);
@ -1011,7 +1026,7 @@ void phch_worker::set_uci_aperiodic_cqi()
} }
uci_data.uci_cqi_len = (uint32_t) cqi_len; uci_data.uci_cqi_len = (uint32_t) cqi_len;
uci_data.uci_ri_len = 1; uci_data.uci_ri_len = 1;
uci_data.uci_ri = ri; uci_data.uci_ri = phy->last_ri;
char cqi_str[SRSLTE_CQI_STR_MAX_CHAR] = {0}; char cqi_str[SRSLTE_CQI_STR_MAX_CHAR] = {0};
srslte_cqi_to_str(uci_data.uci_cqi, uci_data.uci_cqi_len, cqi_str, SRSLTE_CQI_STR_MAX_CHAR); srslte_cqi_to_str(uci_data.uci_cqi, uci_data.uci_cqi_len, cqi_str, SRSLTE_CQI_STR_MAX_CHAR);
@ -1019,11 +1034,11 @@ void phch_worker::set_uci_aperiodic_cqi()
if (cqi_report.subband_hl.rank_is_not_one) { if (cqi_report.subband_hl.rank_is_not_one) {
Info("PUSCH: Aperiodic RM31 ri~1, CQI=%02d/%02d, SINR=%2.1f/%2.1fdB, pmi=%d for %d subbands\n", Info("PUSCH: Aperiodic RM31 ri~1, CQI=%02d/%02d, SINR=%2.1f/%2.1fdB, pmi=%d for %d subbands\n",
cqi_report.subband_hl.wideband_cqi_cw0, cqi_report.subband_hl.wideband_cqi_cw1, cqi_report.subband_hl.wideband_cqi_cw0, cqi_report.subband_hl.wideband_cqi_cw1,
sinr_db, sinr_db, pmi, cqi_report.subband_hl.N); sinr_db, sinr_db, phy->last_pmi, cqi_report.subband_hl.N);
} else { } else {
Info("PUSCH: Aperiodic RM31 ri=1, CQI=%02d, SINR=%2.1f, pmi=%d for %d subbands\n", Info("PUSCH: Aperiodic RM31 ri=1, CQI=%02d, SINR=%2.1f, pmi=%d for %d subbands\n",
cqi_report.subband_hl.wideband_cqi_cw0, cqi_report.subband_hl.wideband_cqi_cw0,
sinr_db, pmi, cqi_report.subband_hl.N); sinr_db, phy->last_pmi, cqi_report.subband_hl.N);
} }
} }
break; break;
@ -1370,7 +1385,7 @@ void phch_worker::update_measurements()
phy->last_radio_rssi = phy->get_radio()->get_rssi(); phy->last_radio_rssi = phy->get_radio()->get_rssi();
phy->rx_gain_offset = phy->avg_rssi_dbm - phy->last_radio_rssi + 30; phy->rx_gain_offset = phy->avg_rssi_dbm - phy->last_radio_rssi + 30;
} else { } else {
phy->rx_gain_offset = phy->get_radio()->get_rx_gain(); phy->rx_gain_offset = phy->get_radio()->get_rx_gain() + phy->args->rx_gain_offset;
} }
} }
rssi_read_cnt++; rssi_read_cnt++;

@ -120,7 +120,7 @@ bool phy::check_args(phy_args_t *args)
} }
bool phy::init(srslte::radio_multi* radio_handler, mac_interface_phy *mac, rrc_interface_phy *rrc, bool phy::init(srslte::radio_multi* radio_handler, mac_interface_phy *mac, rrc_interface_phy *rrc,
std::vector<void*> log_vec, phy_args_t *phy_args) { std::vector<srslte::log*> log_vec, phy_args_t *phy_args) {
mlockall(MCL_CURRENT | MCL_FUTURE); mlockall(MCL_CURRENT | MCL_FUTURE);
@ -226,7 +226,7 @@ void phy::set_timeadv_rar(uint32_t ta_cmd) {
void phy::set_timeadv(uint32_t ta_cmd) { void phy::set_timeadv(uint32_t ta_cmd) {
uint32_t new_nta = srslte_N_ta_new(n_ta, ta_cmd); uint32_t new_nta = srslte_N_ta_new(n_ta, ta_cmd);
sf_recv.set_time_adv_sec(((float) (new_nta - n_ta))*SRSLTE_LTE_TS); //sf_recv.set_time_adv_sec(((float) new_nta)*SRSLTE_LTE_TS);
Info("PHY: Set TA: ta_cmd: %d, n_ta: %d, old_n_ta: %d, ta_usec: %.1f\n", ta_cmd, new_nta, n_ta, ((float) new_nta)*SRSLTE_LTE_TS*1e6); Info("PHY: Set TA: ta_cmd: %d, n_ta: %d, old_n_ta: %d, ta_usec: %.1f\n", ta_cmd, new_nta, n_ta, ((float) new_nta)*SRSLTE_LTE_TS*1e6);
n_ta = new_nta; n_ta = new_nta;
} }

@ -68,7 +68,7 @@ bool ue::init(all_args_t *args_)
char tmp[16]; char tmp[16];
sprintf(tmp, "PHY%d",i); sprintf(tmp, "PHY%d",i);
mylog->init(tmp, logger, true); mylog->init(tmp, logger, true);
phy_log.push_back((void*) mylog); phy_log.push_back(mylog);
} }
mac_log.init("MAC ", logger, true); mac_log.init("MAC ", logger, true);
@ -91,7 +91,7 @@ bool ue::init(all_args_t *args_)
char tmp[16]; char tmp[16];
sprintf(tmp, "PHY_LIB"); sprintf(tmp, "PHY_LIB");
lib_log->init(tmp, logger, true); lib_log->init(tmp, logger, true);
phy_log.push_back((void*) lib_log); phy_log.push_back(lib_log);
((srslte::log_filter*) phy_log[args->expert.phy.nof_phy_threads])->set_level(level(args->log.phy_lib_level)); ((srslte::log_filter*) phy_log[args->expert.phy.nof_phy_threads])->set_level(level(args->log.phy_lib_level));
@ -130,11 +130,7 @@ bool ue::init(all_args_t *args_)
// Init layers // Init layers
if (args->rf.rx_gain < 0) { // PHY inits in background, start before radio
phy.set_agc_enable(true);
}
// PHY initis in background, start before radio
args->expert.phy.nof_rx_ant = args->rf.nof_rx_ant; args->expert.phy.nof_rx_ant = args->rf.nof_rx_ant;
phy.init(&radio, &mac, &rrc, phy_log, &args->expert.phy); phy.init(&radio, &mac, &rrc, phy_log, &args->expert.phy);
@ -222,6 +218,11 @@ bool ue::init(all_args_t *args_)
phy.wait_initialize(); phy.wait_initialize();
phy.configure_ul_params(); phy.configure_ul_params();
// Enable AGC once PHY is initialized
if (args->rf.rx_gain < 0) {
phy.set_agc_enable(true);
}
printf("...\n"); printf("...\n");
nas.attach_request(); nas.attach_request();

@ -49,12 +49,20 @@ rrc::rrc()
:state(RRC_STATE_IDLE) :state(RRC_STATE_IDLE)
,drb_up(false) ,drb_up(false)
,sysinfo_index(0) ,sysinfo_index(0)
,serving_cell(NULL)
{ {
n310_cnt = 0; n310_cnt = 0;
n311_cnt = 0; n311_cnt = 0;
serving_cell = new cell_t(); serving_cell = new cell_t();
} }
rrc::~rrc()
{
if (serving_cell) {
delete(serving_cell);
}
}
static void liblte_rrc_handler(void *ctx, char *str) { static void liblte_rrc_handler(void *ctx, char *str) {
rrc *r = (rrc *) ctx; rrc *r = (rrc *) ctx;
r->liblte_rrc_log(str); r->liblte_rrc_log(str);
@ -333,11 +341,14 @@ void rrc::run_si_acquisition_procedure()
// Instruct MAC to look for SIB1 // Instruct MAC to look for SIB1
tti = mac->get_current_tti(); tti = mac->get_current_tti();
si_win_start = sib_start_tti(tti, 2, 0, 5); si_win_start = sib_start_tti(tti, 2, 0, 5);
if (tti > last_win_start + 10) { if (last_win_start == 0 ||
(srslte_tti_interval(last_win_start, tti) > 20 && srslte_tti_interval(last_win_start, tti) < 1000))
{
last_win_start = si_win_start; last_win_start = si_win_start;
mac->bcch_start_rx(si_win_start, 1); mac->bcch_start_rx(si_win_start, 1);
rrc_log->debug("Instructed MAC to search for SIB1, win_start=%d, win_len=%d\n", rrc_log->info("Instructed MAC to search for SIB1, win_start=%d, win_len=%d, interval=%d\n",
si_win_start, 1); si_win_start, 1, srslte_tti_interval(last_win_start, tti));
nof_sib1_trials++; nof_sib1_trials++;
if (nof_sib1_trials >= SIB1_SEARCH_TIMEOUT) { if (nof_sib1_trials >= SIB1_SEARCH_TIMEOUT) {
if (state == RRC_STATE_CELL_SELECTING) { if (state == RRC_STATE_CELL_SELECTING) {
@ -361,13 +372,15 @@ void rrc::run_si_acquisition_procedure()
tti = mac->get_current_tti(); tti = mac->get_current_tti();
period = liblte_rrc_si_periodicity_num[serving_cell->sib1.sched_info[sysinfo_index].si_periodicity]; period = liblte_rrc_si_periodicity_num[serving_cell->sib1.sched_info[sysinfo_index].si_periodicity];
si_win_start = sib_start_tti(tti, period, offset, sf); si_win_start = sib_start_tti(tti, period, offset, sf);
si_win_len = liblte_rrc_si_window_length_num[serving_cell->sib1.si_window_length];
if (tti > last_win_start + 10) { if (last_win_start == 0 ||
(srslte_tti_interval(last_win_start, tti) > period*10 && srslte_tti_interval(last_win_start, tti) < 1000))
{
last_win_start = si_win_start; last_win_start = si_win_start;
si_win_len = liblte_rrc_si_window_length_num[serving_cell->sib1.si_window_length];
mac->bcch_start_rx(si_win_start, si_win_len); mac->bcch_start_rx(si_win_start, si_win_len);
rrc_log->debug("Instructed MAC to search for system info, win_start=%d, win_len=%d\n", rrc_log->info("Instructed MAC to search for system info, win_start=%d, win_len=%d\n",
si_win_start, si_win_len); si_win_start, si_win_len);
} }
@ -1054,6 +1067,7 @@ bool rrc::ho_prepare() {
int target_cell_idx = find_neighbour_cell(serving_cell->earfcn, mob_reconf.mob_ctrl_info.target_pci); int target_cell_idx = find_neighbour_cell(serving_cell->earfcn, mob_reconf.mob_ctrl_info.target_pci);
if (target_cell_idx < 0) { if (target_cell_idx < 0) {
rrc_log->console("Received HO command to unknown PCI=%d\n", mob_reconf.mob_ctrl_info.target_pci);
rrc_log->error("Could not find target cell earfcn=%d, pci=%d\n", serving_cell->earfcn, mob_reconf.mob_ctrl_info.target_pci); rrc_log->error("Could not find target cell earfcn=%d, pci=%d\n", serving_cell->earfcn, mob_reconf.mob_ctrl_info.target_pci);
return false; return false;
} }
@ -1075,6 +1089,7 @@ bool rrc::ho_prepare() {
ho_src_rnti = uernti.crnti; ho_src_rnti = uernti.crnti;
// Reset/Reestablish stack // Reset/Reestablish stack
mac->bcch_stop_rx(); // FIXME: change function name
phy->meas_reset(); phy->meas_reset();
mac->wait_uplink(); mac->wait_uplink();
pdcp->reestablish(); pdcp->reestablish();
@ -1304,6 +1319,9 @@ void rrc::write_pdu_bcch_dlsch(byte_buffer_t *pdu) {
handle_sib13(); handle_sib13();
} }
} }
last_win_start = 0;
if(serving_cell->has_valid_sib2) { if(serving_cell->has_valid_sib2) {
sysinfo_index++; sysinfo_index++;
} }
@ -1762,9 +1780,9 @@ void rrc::apply_rr_config_common_dl(LIBLTE_RRC_RR_CONFIG_COMMON_STRUCT *config)
mac->get_config(&mac_cfg); mac->get_config(&mac_cfg);
if (config->rach_cnfg_present) { if (config->rach_cnfg_present) {
memcpy(&mac_cfg.rach, &config->rach_cnfg, sizeof(LIBLTE_RRC_RACH_CONFIG_COMMON_STRUCT)); memcpy(&mac_cfg.rach, &config->rach_cnfg, sizeof(LIBLTE_RRC_RACH_CONFIG_COMMON_STRUCT));
mac_cfg.ul_harq_params.max_harq_msg3_tx = config->rach_cnfg.max_harq_msg3_tx;
} }
mac_cfg.prach_config_index = config->prach_cnfg.root_sequence_index; mac_cfg.prach_config_index = config->prach_cnfg.root_sequence_index;
mac_cfg.ul_harq_params.max_harq_msg3_tx = config->rach_cnfg.max_harq_msg3_tx;
mac->set_config(&mac_cfg); mac->set_config(&mac_cfg);
@ -2530,6 +2548,8 @@ void rrc::rrc_meas::calculate_triggers(uint32_t tti)
} }
} }
for (std::map<uint32_t, meas_t>::iterator m = active.begin(); m != active.end(); ++m) { for (std::map<uint32_t, meas_t>::iterator m = active.begin(); m != active.end(); ++m) {
report_cfg_t *cfg = &reports_cfg[m->second.report_id]; report_cfg_t *cfg = &reports_cfg[m->second.report_id];
float hyst = 0.5*cfg->event.hysteresis; float hyst = 0.5*cfg->event.hysteresis;
@ -2554,45 +2574,53 @@ void rrc::rrc_meas::calculate_triggers(uint32_t tti)
enter_condition = Mp + hyst < range_to_value(cfg->trigger_quantity, cfg->event.event_a1.eutra.range); enter_condition = Mp + hyst < range_to_value(cfg->trigger_quantity, cfg->event.event_a1.eutra.range);
exit_condition = Mp - hyst > range_to_value(cfg->trigger_quantity, cfg->event.event_a1.eutra.range); exit_condition = Mp - hyst > range_to_value(cfg->trigger_quantity, cfg->event.event_a1.eutra.range);
} }
// check only if
gen_report |= process_event(&cfg->event, tti, enter_condition, exit_condition, gen_report |= process_event(&cfg->event, tti, enter_condition, exit_condition,
&m->second, &m->second.cell_values[serving_cell_idx]); &m->second, &pcell_measurement);
if (gen_report) {
log_h->info("Triggered by A1/A2 event\n");
}
// Rest are evaluated for every cell in frequency // Rest are evaluated for every cell in frequency
} else { } else {
meas_obj_t *obj = &objects[m->second.object_id]; meas_obj_t *obj = &objects[m->second.object_id];
for (std::map<uint32_t, meas_cell_t>::iterator cell = obj->cells.begin(); cell != obj->cells.end(); ++cell) { for (std::map<uint32_t, meas_cell_t>::iterator cell = obj->cells.begin(); cell != obj->cells.end(); ++cell) {
float Ofn = obj->q_offset; if (m->second.cell_values.count(cell->second.pci)) {
float Ocn = cell->second.q_offset; float Ofn = obj->q_offset;
float Mn = m->second.cell_values[cell->second.pci].ms[cfg->trigger_quantity]; float Ocn = cell->second.q_offset;
float Off=0, th=0, th1=0, th2=0; float Mn = m->second.cell_values[cell->second.pci].ms[cfg->trigger_quantity];
bool enter_condition = false; float Off=0, th=0, th1=0, th2=0;
bool exit_condition = false; bool enter_condition = false;
switch (event_id) { bool exit_condition = false;
case LIBLTE_RRC_EVENT_ID_EUTRA_A3: switch (event_id) {
Off = 0.5*cfg->event.event_a3.offset; case LIBLTE_RRC_EVENT_ID_EUTRA_A3:
enter_condition = Mn + Ofn + Ocn - hyst > Mp + Ofp + Ocp + Off; Off = 0.5*cfg->event.event_a3.offset;
exit_condition = Mn + Ofn + Ocn + hyst < Mp + Ofp + Ocp + Off; enter_condition = Mn + Ofn + Ocn - hyst > Mp + Ofp + Ocp + Off;
break; exit_condition = Mn + Ofn + Ocn + hyst < Mp + Ofp + Ocp + Off;
case LIBLTE_RRC_EVENT_ID_EUTRA_A4: break;
th = range_to_value(cfg->trigger_quantity, cfg->event.event_a4.eutra.range); case LIBLTE_RRC_EVENT_ID_EUTRA_A4:
enter_condition = Mn + Ofn + Ocn - hyst > th; th = range_to_value(cfg->trigger_quantity, cfg->event.event_a4.eutra.range);
exit_condition = Mn + Ofn + Ocn + hyst < th; enter_condition = Mn + Ofn + Ocn - hyst > th;
break; exit_condition = Mn + Ofn + Ocn + hyst < th;
case LIBLTE_RRC_EVENT_ID_EUTRA_A5: break;
th1 = range_to_value(cfg->trigger_quantity, cfg->event.event_a5.eutra1.range); case LIBLTE_RRC_EVENT_ID_EUTRA_A5:
th2 = range_to_value(cfg->trigger_quantity, cfg->event.event_a5.eutra2.range); th1 = range_to_value(cfg->trigger_quantity, cfg->event.event_a5.eutra1.range);
enter_condition = (Mp + hyst < th1) && (Mn + Ofn + Ocn - hyst > th2); th2 = range_to_value(cfg->trigger_quantity, cfg->event.event_a5.eutra2.range);
exit_condition = (Mp - hyst > th1) && (Mn + Ofn + Ocn + hyst < th2); enter_condition = (Mp + hyst < th1) && (Mn + Ofn + Ocn - hyst > th2);
break; exit_condition = (Mp - hyst > th1) && (Mn + Ofn + Ocn + hyst < th2);
default: break;
log_h->error("Error event %s not implemented\n", event_str); default:
log_h->error("Error event %s not implemented\n", event_str);
}
gen_report |= process_event(&cfg->event, tti, enter_condition, exit_condition,
&m->second, &m->second.cell_values[cell->second.pci]);
} }
gen_report |= process_event(&cfg->event, tti, enter_condition, exit_condition,
&m->second, &m->second.cell_values[cell->second.pci]);
} }
} }
} }
if (gen_report) { if (gen_report) {
log_h->info("Generate report MeasId=%d, from event\n", m->first);
generate_report(m->first); generate_report(m->first);
} }
} }
@ -2622,6 +2650,7 @@ void rrc::rrc_meas::ho_finish() {
bool rrc::rrc_meas::timer_expired(uint32_t timer_id) { bool rrc::rrc_meas::timer_expired(uint32_t timer_id) {
for (std::map<uint32_t, meas_t>::iterator iter = active.begin(); iter != active.end(); ++iter) { for (std::map<uint32_t, meas_t>::iterator iter = active.begin(); iter != active.end(); ++iter) {
if (iter->second.periodic_timer == timer_id) { if (iter->second.periodic_timer == timer_id) {
log_h->info("Generate report MeasId=%d, from timerId=%d\n", iter->first, timer_id);
generate_report(iter->first); generate_report(iter->first);
return true; return true;
} }
@ -2805,6 +2834,8 @@ void rrc::rrc_meas::parse_meas_config(LIBLTE_RRC_MEAS_CONFIG_STRUCT *cfg)
remove_meas_id(cfg->meas_id_to_remove_list[i]); remove_meas_id(cfg->meas_id_to_remove_list[i]);
} }
log_h->info("nof active measId=%d\n", active.size());
// Measurement identity addition/modification 5.5.2.3 // Measurement identity addition/modification 5.5.2.3
if (cfg->meas_id_to_add_mod_list_present) { if (cfg->meas_id_to_add_mod_list_present) {
for (uint32_t i=0;i<cfg->meas_id_to_add_mod_list.N_meas_id;i++) { for (uint32_t i=0;i<cfg->meas_id_to_add_mod_list.N_meas_id;i++) {
@ -2819,8 +2850,9 @@ void rrc::rrc_meas::parse_meas_config(LIBLTE_RRC_MEAS_CONFIG_STRUCT *cfg)
} }
active[measId->meas_id].object_id = measId->meas_obj_id; active[measId->meas_id].object_id = measId->meas_obj_id;
active[measId->meas_id].report_id = measId->rep_cnfg_id; active[measId->meas_id].report_id = measId->rep_cnfg_id;
log_h->info("MEAS: %s measId=%d, measObjectId=%d, reportConfigId=%d\n", log_h->info("MEAS: %s measId=%d, measObjectId=%d, reportConfigId=%d, nof_values=%d\n",
is_new?"Added":"Updated", measId->meas_id, measId->meas_obj_id, measId->rep_cnfg_id); is_new?"Added":"Updated", measId->meas_id, measId->meas_obj_id, measId->rep_cnfg_id,
active[measId->meas_id].cell_values.size());
} }
} }

@ -451,12 +451,12 @@ int main(int argc, char *argv[])
exit(1); exit(1);
} }
std::vector<void*> phy_log; std::vector<srslte::log*> phy_log;
srslte::log_filter *mylog = new srslte::log_filter("PHY"); srslte::log_filter *mylog = new srslte::log_filter("PHY");
char tmp[16]; char tmp[16];
sprintf(tmp, "PHY%d",0); sprintf(tmp, "PHY%d",0);
phy_log.push_back((void*) mylog); phy_log.push_back((srslte::log*) mylog);
switch (prog_args.verbose) { switch (prog_args.verbose) {
case 1: case 1:

@ -101,19 +101,11 @@ imei = 353490069873319
##################################################################### #####################################################################
# RRC configuration # RRC configuration
# #
# stimsi_attach: If enabled, always tries first an S-TMSI attach using the
# S-TMSI value stored in .stimsi file generated in previous run
# mmec_value: If defined (non-zero), overwrites the value stored in .stimsi file
# m_tmsi_value: If defined (non-zero), overwrites the value stored in .stimsi file
#
# ue_category: Sets UE category (range 1-5). Default: 4 # ue_category: Sets UE category (range 1-5). Default: 4
# feature_group: Hex value of the featureGroupIndicators field in the # feature_group: Hex value of the featureGroupIndicators field in the
# UECapabilityInformation message. Default 0xe6041c00 # UECapabilityInformation message. Default 0xe6041c00
##################################################################### #####################################################################
[rrc] [rrc]
#stmsi_attach = false
#mmec_value = 0
#mtmsi_value = 0
#ue_category = 4 #ue_category = 4
#feature_group = 0xe6041c00 #feature_group = 0xe6041c00

Loading…
Cancel
Save