lte-ue.c 42.2 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
/*
 * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The OpenAirInterface Software Alliance licenses this file to You under
 * the OAI Public License, Version 1.0  (the "License"); you may not use this file
 * except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.openairinterface.org/?page_id=698
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *-------------------------------------------------------------------------------
 * For more information about the OpenAirInterface (OAI) Software Alliance:
 *      contact@openairinterface.org
 */
21 22 23 24 25 26 27 28 29 30 31

/*! \file lte-ue.c
 * \brief threads and support functions for real-time LTE UE target
 * \author R. Knopp, F. Kaltenberger, Navid Nikaein
 * \date 2015
 * \version 0.1
 * \company Eurecom
 * \email: knopp@eurecom.fr,florian.kaltenberger@eurecom.fr, navid.nikaein@eurecom.fr
 * \note
 * \warning
 */
32
#include "lte-softmodem.h"
33 34 35

#include "rt_wrapper.h"

36
#ifdef OPENAIR2
37 38
#include "LAYER2/MAC/defs.h"
#include "RRC/LITE/extern.h"
39
#endif
40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
#include "PHY_INTERFACE/extern.h"

#undef MALLOC //there are two conflicting definitions, so we better make sure we don't use it at all
//#undef FRAME_LENGTH_COMPLEX_SAMPLES //there are two conflicting definitions, so we better make sure we don't use it at all

#include "PHY/extern.h"
#include "SCHED/extern.h"
#include "LAYER2/MAC/extern.h"
#include "LAYER2/MAC/proto.h"

#include "UTIL/LOG/log_extern.h"
#include "UTIL/OTG/otg_tx.h"
#include "UTIL/OTG/otg_externs.h"
#include "UTIL/MATH/oml.h"
#include "UTIL/LOG/vcd_signal_dumper.h"
#include "UTIL/OPT/opt.h"

57 58
#include "T.h"

Bilel's avatar
Bilel committed
59 60
extern double cpuf;

61 62
#define FRAME_PERIOD    100000000ULL
#define DAQ_PERIOD      66667ULL
laurent's avatar
laurent committed
63
#define FIFO_PRIORITY   40
64 65

typedef enum {
laurent's avatar
laurent committed
66 67 68
    pss=0,
    pbch=1,
    si=2
69 70
} sync_mode_t;

71
void init_UE_threads(PHY_VARS_UE *UE);
72
void *UE_thread(void *arg);
knopp's avatar
knopp committed
73
void init_UE(int nb_inst);
74

75 76
int32_t **rxdata;
int32_t **txdata;
77 78

#define KHz (1000UL)
79
#define MHz (1000*KHz)
80 81

typedef struct eutra_band_s {
laurent's avatar
laurent committed
82 83 84 85 86 87
    int16_t band;
    uint32_t ul_min;
    uint32_t ul_max;
    uint32_t dl_min;
    uint32_t dl_max;
    lte_frame_type_t frame_type;
88 89 90
} eutra_band_t;

typedef struct band_info_s {
laurent's avatar
laurent committed
91 92
    int nbands;
    eutra_band_t band_info[100];
93 94 95 96
} band_info_t;

band_info_t bands_to_scan;

97
static const eutra_band_t eutra_bands[] = {
laurent's avatar
laurent committed
98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126
    { 1, 1920    * MHz, 1980    * MHz, 2110    * MHz, 2170    * MHz, FDD},
    { 2, 1850    * MHz, 1910    * MHz, 1930    * MHz, 1990    * MHz, FDD},
    { 3, 1710    * MHz, 1785    * MHz, 1805    * MHz, 1880    * MHz, FDD},
    { 4, 1710    * MHz, 1755    * MHz, 2110    * MHz, 2155    * MHz, FDD},
    { 5,  824    * MHz,  849    * MHz,  869    * MHz,  894    * MHz, FDD},
    { 6,  830    * MHz,  840    * MHz,  875    * MHz,  885    * MHz, FDD},
    { 7, 2500    * MHz, 2570    * MHz, 2620    * MHz, 2690    * MHz, FDD},
    { 8,  880    * MHz,  915    * MHz,  925    * MHz,  960    * MHz, FDD},
    { 9, 1749900 * KHz, 1784900 * KHz, 1844900 * KHz, 1879900 * KHz, FDD},
    {10, 1710    * MHz, 1770    * MHz, 2110    * MHz, 2170    * MHz, FDD},
    {11, 1427900 * KHz, 1452900 * KHz, 1475900 * KHz, 1500900 * KHz, FDD},
    {12,  698    * MHz,  716    * MHz,  728    * MHz,  746    * MHz, FDD},
    {13,  777    * MHz,  787    * MHz,  746    * MHz,  756    * MHz, FDD},
    {14,  788    * MHz,  798    * MHz,  758    * MHz,  768    * MHz, FDD},
    {17,  704    * MHz,  716    * MHz,  734    * MHz,  746    * MHz, FDD},
    {20,  832    * MHz,  862    * MHz,  791    * MHz,  821    * MHz, FDD},
    {22, 3510    * MHz, 3590    * MHz, 3410    * MHz, 3490    * MHz, FDD},
    {33, 1900    * MHz, 1920    * MHz, 1900    * MHz, 1920    * MHz, TDD},
    {34, 2010    * MHz, 2025    * MHz, 2010    * MHz, 2025    * MHz, TDD},
    {35, 1850    * MHz, 1910    * MHz, 1850    * MHz, 1910    * MHz, TDD},
    {36, 1930    * MHz, 1990    * MHz, 1930    * MHz, 1990    * MHz, TDD},
    {37, 1910    * MHz, 1930    * MHz, 1910    * MHz, 1930    * MHz, TDD},
    {38, 2570    * MHz, 2620    * MHz, 2570    * MHz, 2630    * MHz, TDD},
    {39, 1880    * MHz, 1920    * MHz, 1880    * MHz, 1920    * MHz, TDD},
    {40, 2300    * MHz, 2400    * MHz, 2300    * MHz, 2400    * MHz, TDD},
    {41, 2496    * MHz, 2690    * MHz, 2496    * MHz, 2690    * MHz, TDD},
    {42, 3400    * MHz, 3600    * MHz, 3400    * MHz, 3600    * MHz, TDD},
    {43, 3600    * MHz, 3800    * MHz, 3600    * MHz, 3800    * MHz, TDD},
    {44, 703    * MHz, 803    * MHz, 703    * MHz, 803    * MHz, TDD},
127 128
};

laurent's avatar
laurent committed
129
void init_thread(int sched_runtime, int sched_deadline, int sched_fifo, cpu_set_t *cpuset, char * name) {
130

laurent's avatar
laurent committed
131 132 133 134 135 136 137 138 139
#ifdef DEADLINE_SCHEDULER
    if (sched_runtime!=0) {
        struct sched_attr attr= {0};
        attr.size = sizeof(attr);
        attr.sched_policy = SCHED_DEADLINE;
        attr.sched_runtime  = sched_runtime;
        attr.sched_deadline = sched_deadline;
        attr.sched_period   = 0;
        AssertFatal(sched_setattr(0, &attr, 0) == 0,
140
                    "[SCHED] %s thread: sched_setattr failed %s \n", name, strerror(errno));
141 142
        LOG_I(HW,"[SCHED][eNB] %s deadline thread %lu started on CPU %d\n",
              name, (unsigned long)gettid(), sched_getcpu());
knopp's avatar
knopp committed
143
    }
144

laurent's avatar
laurent committed
145
#else
146
    if (CPU_COUNT(cpuset) > 0)
laurent's avatar
laurent committed
147 148 149 150 151
        AssertFatal( 0 == pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), cpuset), "");
    struct sched_param sp;
    sp.sched_priority = sched_fifo;
    AssertFatal(pthread_setschedparam(pthread_self(),SCHED_FIFO,&sp)==0,
                "Can't set thread priority, Are you root?\n");
152 153 154 155 156 157 158 159
    /* Check the actual affinity mask assigned to the thread */
    cpu_set_t *cset=CPU_ALLOC(CPU_SETSIZE);
    if (0 == pthread_getaffinity_np(pthread_self(), CPU_ALLOC_SIZE(CPU_SETSIZE), cset)) {
      char txt[512]={0};
      for (int j = 0; j < CPU_SETSIZE; j++)
        if (CPU_ISSET(j, cset))
	  sprintf(txt+strlen(txt), " %d ", j);
      printf("CPU Affinity of thread %s is %s\n", name, txt);
160
    }
161
    CPU_FREE(cset);
162 163
#endif

laurent's avatar
laurent committed
164 165 166 167 168 169 170 171 172 173 174
    // Lock memory from swapping. This is a process wide call (not constraint to this thread).
    mlockall(MCL_CURRENT | MCL_FUTURE);
    pthread_setname_np( pthread_self(), name );

    // LTS: this sync stuff should be wrong
    printf("waiting for sync (%s)\n",name);
    pthread_mutex_lock(&sync_mutex);
    printf("Locked sync_mutex, waiting (%s)\n",name);
    while (sync_var<0)
        pthread_cond_wait(&sync_cond, &sync_mutex);
    pthread_mutex_unlock(&sync_mutex);
175
    printf("started %s as PID: %ld\n",name, gettid());
laurent's avatar
laurent committed
176
}
177

178 179 180 181 182 183 184 185 186 187 188 189 190
void init_UE(int nb_inst)
{
  int inst;
  for (inst=0; inst < nb_inst; inst++) {
    //    UE->rfdevice.type      = NONE_DEV;
    PHY_VARS_UE *UE = PHY_vars_UE_g[inst][0];
    AssertFatal(0 == pthread_create(&UE->proc.pthread_ue,
                                    &UE->proc.attr_ue,
                                    UE_thread,
                                    (void*)UE), "");
  }

  printf("UE threads created by %ld\n", gettid());
191 192
#if 0
#if defined(ENABLE_USE_MME)
193 194 195 196
  extern volatile int start_UE;
  while (start_UE == 0) {
    sleep(1);
  }
197
#endif
198
#endif
199
}
knopp's avatar
knopp committed
200

201 202
/*!
 * \brief This is the UE synchronize thread.
203
 * It performs band scanning and synchonization.
204 205 206
 * \param arg is a pointer to a \ref PHY_VARS_UE structure.
 * \returns a pointer to an int. The storage is not on the heap and must not be freed.
 */
laurent's avatar
laurent committed
207 208 209 210 211 212 213 214 215
static void *UE_thread_synch(void *arg) {
    static int __thread UE_thread_synch_retval;
    int i, hw_slot_offset;
    PHY_VARS_UE *UE = (PHY_VARS_UE*) arg;
    int current_band = 0;
    int current_offset = 0;
    sync_mode_t sync_mode = pbch;
    int CC_id = UE->CC_id;
    int freq_offset=0;
216
    char threadname[128];
laurent's avatar
laurent committed
217 218 219

    cpu_set_t cpuset;
    CPU_ZERO(&cpuset);
220 221
    if ( threads.iq != -1 )
        CPU_SET(threads.iq, &cpuset);
laurent's avatar
laurent committed
222
    // this thread priority must be lower that the main acquisition thread
223 224
    sprintf(threadname, "sync UE %d\n", UE->Mod_id);
    init_thread(100000, 500000, FIFO_PRIORITY-1, &cpuset, threadname);
laurent's avatar
laurent committed
225

laurent's avatar
laurent committed
226
    UE->is_synchronized = 0;
227

laurent's avatar
laurent committed
228
    if (UE->UE_scan == 0) {
laurent's avatar
laurent committed
229 230 231 232
        int ind;
        for ( ind=0;
                ind < sizeof(eutra_bands) / sizeof(eutra_bands[0]);
                ind++) {
laurent's avatar
laurent committed
233
            current_band = eutra_bands[ind].band;
laurent's avatar
laurent committed
234 235
            LOG_D(PHY, "Scanning band %d, dl_min %"PRIu32", ul_min %"PRIu32"\n", current_band, eutra_bands[ind].dl_min,eutra_bands[ind].ul_min);
            if ( eutra_bands[ind].dl_min <= downlink_frequency[0][0] && eutra_bands[ind].dl_max >= downlink_frequency[0][0] ) {
laurent's avatar
laurent committed
236 237 238 239 240
                for (i=0; i<4; i++)
                    uplink_frequency_offset[CC_id][i] = eutra_bands[ind].ul_min - eutra_bands[ind].dl_min;
                break;
            }
        }
laurent's avatar
laurent committed
241
        AssertFatal( ind < sizeof(eutra_bands) / sizeof(eutra_bands[0]), "Can't find EUTRA band for frequency");
242

laurent's avatar
laurent committed
243 244 245
        LOG_I( PHY, "[SCHED][UE] Check absolute frequency DL %"PRIu32", UL %"PRIu32" (oai_exit %d, rx_num_channels %d)\n",
               downlink_frequency[0][0], downlink_frequency[0][0]+uplink_frequency_offset[0][0],
               oai_exit, openair0_cfg[0].rx_num_channels);
246

laurent's avatar
laurent committed
247 248
        for (i=0; i<openair0_cfg[UE->rf_map.card].rx_num_channels; i++) {
            openair0_cfg[UE->rf_map.card].rx_freq[UE->rf_map.chain+i] = downlink_frequency[CC_id][i];
laurent's avatar
laurent committed
249 250
            openair0_cfg[UE->rf_map.card].tx_freq[UE->rf_map.chain+i] =
                downlink_frequency[CC_id][i]+uplink_frequency_offset[CC_id][i];
laurent's avatar
laurent committed
251 252 253 254 255 256 257
            openair0_cfg[UE->rf_map.card].autocal[UE->rf_map.chain+i] = 1;
            if (uplink_frequency_offset[CC_id][i] != 0) //
                openair0_cfg[UE->rf_map.card].duplex_mode = duplex_mode_FDD;
            else //FDD
                openair0_cfg[UE->rf_map.card].duplex_mode = duplex_mode_TDD;
        }
        sync_mode = pbch;
258

laurent's avatar
laurent committed
259
    } else {
laurent's avatar
laurent committed
260 261 262
        current_band=0;
        for (i=0; i<openair0_cfg[UE->rf_map.card].rx_num_channels; i++) {
            downlink_frequency[UE->rf_map.card][UE->rf_map.chain+i] = bands_to_scan.band_info[CC_id].dl_min;
laurent's avatar
laurent committed
263 264
            uplink_frequency_offset[UE->rf_map.card][UE->rf_map.chain+i] =
                bands_to_scan.band_info[CC_id].ul_min-bands_to_scan.band_info[CC_id].dl_min;
laurent's avatar
laurent committed
265
            openair0_cfg[UE->rf_map.card].rx_freq[UE->rf_map.chain+i] = downlink_frequency[CC_id][i];
laurent's avatar
laurent committed
266 267
            openair0_cfg[UE->rf_map.card].tx_freq[UE->rf_map.chain+i] =
                downlink_frequency[CC_id][i]+uplink_frequency_offset[CC_id][i];
laurent's avatar
laurent committed
268 269
            openair0_cfg[UE->rf_map.card].rx_gain[UE->rf_map.chain+i] = UE->rx_total_gain_dB;
        }
270
    }
271

272
    //    AssertFatal(UE->rfdevice.trx_start_func(&UE->rfdevice) == 0, "Could not start the device\n");
273

laurent's avatar
laurent committed
274
    while (oai_exit==0) {
laurent's avatar
laurent committed
275 276
        AssertFatal ( 0== pthread_mutex_lock(&UE->proc.mutex_synch), "");
        while (UE->proc.instance_cnt_synch < 0)
laurent's avatar
laurent committed
277 278
            // the thread waits here most of the time
            pthread_cond_wait( &UE->proc.cond_synch, &UE->proc.mutex_synch );
laurent's avatar
laurent committed
279
        AssertFatal ( 0== pthread_mutex_unlock(&UE->proc.mutex_synch), "");
280

laurent's avatar
laurent committed
281 282 283 284 285
        switch (sync_mode) {
        case pss:
            LOG_I(PHY,"[SCHED][UE] Scanning band %d (%d), freq %u\n",bands_to_scan.band_info[current_band].band, current_band,bands_to_scan.band_info[current_band].dl_min+current_offset);
            lte_sync_timefreq(UE,current_band,bands_to_scan.band_info[current_band].dl_min+current_offset);
            current_offset += 20000000; // increase by 20 MHz
286

laurent's avatar
laurent committed
287 288 289 290
            if (current_offset > bands_to_scan.band_info[current_band].dl_max-bands_to_scan.band_info[current_band].dl_min) {
                current_band++;
                current_offset=0;
            }
291

laurent's avatar
laurent committed
292 293 294 295
            if (current_band==bands_to_scan.nbands) {
                current_band=0;
                oai_exit=1;
            }
296

laurent's avatar
laurent committed
297 298 299
            for (i=0; i<openair0_cfg[UE->rf_map.card].rx_num_channels; i++) {
                downlink_frequency[UE->rf_map.card][UE->rf_map.chain+i] = bands_to_scan.band_info[current_band].dl_min+current_offset;
                uplink_frequency_offset[UE->rf_map.card][UE->rf_map.chain+i] = bands_to_scan.band_info[current_band].ul_min-bands_to_scan.band_info[0].dl_min + current_offset;
300

laurent's avatar
laurent committed
301 302 303 304 305 306
                openair0_cfg[UE->rf_map.card].rx_freq[UE->rf_map.chain+i] = downlink_frequency[CC_id][i];
                openair0_cfg[UE->rf_map.card].tx_freq[UE->rf_map.chain+i] = downlink_frequency[CC_id][i]+uplink_frequency_offset[CC_id][i];
                openair0_cfg[UE->rf_map.card].rx_gain[UE->rf_map.chain+i] = UE->rx_total_gain_dB;
                if (UE->UE_scan_carrier) {
                    openair0_cfg[UE->rf_map.card].autocal[UE->rf_map.chain+i] = 1;
                }
307

laurent's avatar
laurent committed
308
            }
309

laurent's avatar
laurent committed
310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325
            break;

        case pbch:

            LOG_I(PHY,"[UE thread Synch] Running Initial Synch (mode %d)\n",UE->mode);
            if (initial_sync( UE, UE->mode ) == 0) {

                hw_slot_offset = (UE->rx_offset<<1) / UE->frame_parms.samples_per_tti;
                LOG_I( HW, "Got synch: hw_slot_offset %d, carrier off %d Hz, rxgain %d (DL %u, UL %u), UE_scan_carrier %d\n",
                       hw_slot_offset,
                       freq_offset,
                       UE->rx_total_gain_dB,
                       downlink_frequency[0][0]+freq_offset,
                       downlink_frequency[0][0]+uplink_frequency_offset[0][0]+freq_offset,
                       UE->UE_scan_carrier );

326

laurent's avatar
laurent committed
327 328 329
                    // rerun with new cell parameters and frequency-offset
                    for (i=0; i<openair0_cfg[UE->rf_map.card].rx_num_channels; i++) {
                        openair0_cfg[UE->rf_map.card].rx_gain[UE->rf_map.chain+i] = UE->rx_total_gain_dB;//-USRP_GAIN_OFFSET;
330
			if (UE->UE_scan_carrier == 1) {
laurent's avatar
laurent committed
331
                        if (freq_offset >= 0)
332
                            openair0_cfg[UE->rf_map.card].rx_freq[UE->rf_map.chain+i] += abs(UE->common_vars.freq_offset);
laurent's avatar
laurent committed
333
                        else
334
                            openair0_cfg[UE->rf_map.card].rx_freq[UE->rf_map.chain+i] -= abs(UE->common_vars.freq_offset);
laurent's avatar
laurent committed
335 336
                        openair0_cfg[UE->rf_map.card].tx_freq[UE->rf_map.chain+i] =
                            openair0_cfg[UE->rf_map.card].rx_freq[UE->rf_map.chain+i]+uplink_frequency_offset[CC_id][i];
laurent's avatar
laurent committed
337 338 339
                        downlink_frequency[CC_id][i] = openair0_cfg[CC_id].rx_freq[i];
                        freq_offset=0;
                    }
340
	  }
laurent's avatar
laurent committed
341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371

                    // reconfigure for potentially different bandwidth
                    switch(UE->frame_parms.N_RB_DL) {
                    case 6:
                        openair0_cfg[UE->rf_map.card].sample_rate =1.92e6;
                        openair0_cfg[UE->rf_map.card].rx_bw          =.96e6;
                        openair0_cfg[UE->rf_map.card].tx_bw          =.96e6;
                        //            openair0_cfg[0].rx_gain[0] -= 12;
                        break;
                    case 25:
                        openair0_cfg[UE->rf_map.card].sample_rate =7.68e6;
                        openair0_cfg[UE->rf_map.card].rx_bw          =2.5e6;
                        openair0_cfg[UE->rf_map.card].tx_bw          =2.5e6;
                        //            openair0_cfg[0].rx_gain[0] -= 6;
                        break;
                    case 50:
                        openair0_cfg[UE->rf_map.card].sample_rate =15.36e6;
                        openair0_cfg[UE->rf_map.card].rx_bw          =5.0e6;
                        openair0_cfg[UE->rf_map.card].tx_bw          =5.0e6;
                        //            openair0_cfg[0].rx_gain[0] -= 3;
                        break;
                    case 100:
                        openair0_cfg[UE->rf_map.card].sample_rate=30.72e6;
                        openair0_cfg[UE->rf_map.card].rx_bw=10.0e6;
                        openair0_cfg[UE->rf_map.card].tx_bw=10.0e6;
                        //            openair0_cfg[0].rx_gain[0] -= 0;
                        break;
                    }

                    UE->rfdevice.trx_set_freq_func(&UE->rfdevice,&openair0_cfg[0],0);
                    //UE->rfdevice.trx_set_gains_func(&openair0,&openair0_cfg[0]);
372
                    //UE->rfdevice.trx_stop_func(&UE->rfdevice);
laurent's avatar
laurent committed
373 374
                    sleep(1);
                    init_frame_parms(&UE->frame_parms,1);
375
                    /*if (UE->rfdevice.trx_start_func(&UE->rfdevice) != 0 ) {
laurent's avatar
laurent committed
376 377
                        LOG_E(HW,"Could not start the device\n");
                        oai_exit=1;
378
                    }*/
379 380 381 382

		if (UE->UE_scan_carrier == 1) {

		  UE->UE_scan_carrier = 0;
laurent's avatar
laurent committed
383
                } else {
laurent's avatar
laurent committed
384
                    AssertFatal ( 0== pthread_mutex_lock(&UE->proc.mutex_synch), "");
laurent's avatar
laurent committed
385
                    UE->is_synchronized = 1;
laurent's avatar
laurent committed
386
                    AssertFatal ( 0== pthread_mutex_unlock(&UE->proc.mutex_synch), "");
laurent's avatar
laurent committed
387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403

                    if( UE->mode == rx_dump_frame ) {
                        FILE *fd;
                        if ((UE->proc.proc_rxtx[0].frame_rx&1) == 0) {  // this guarantees SIB1 is present
                            if ((fd = fopen("rxsig_frame0.dat","w")) != NULL) {
                                fwrite((void*)&UE->common_vars.rxdata[0][0],
                                       sizeof(int32_t),
                                       10*UE->frame_parms.samples_per_tti,
                                       fd);
                                LOG_I(PHY,"Dummping Frame ... bye bye \n");
                                fclose(fd);
                                exit(0);
                            } else {
                                LOG_E(PHY,"Cannot open file for writing\n");
                                exit(0);
                            }
                        } else {
laurent's avatar
laurent committed
404
                            AssertFatal ( 0== pthread_mutex_lock(&UE->proc.mutex_synch), "");
laurent's avatar
laurent committed
405
                            UE->is_synchronized = 0;
laurent's avatar
laurent committed
406 407
                            AssertFatal ( 0== pthread_mutex_unlock(&UE->proc.mutex_synch), "");

laurent's avatar
laurent committed
408 409 410 411 412 413 414
                        }
                    }
                }
            } else {
                // initial sync failed
                // calculate new offset and try again
                if (UE->UE_scan_carrier == 1) {
laurent's avatar
laurent committed
415
                    if (freq_offset >= 0)
laurent's avatar
laurent committed
416
                        freq_offset += 100;
laurent's avatar
laurent committed
417
                    freq_offset *= -1;
laurent's avatar
laurent committed
418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444

                    if (abs(freq_offset) > 7500) {
                        LOG_I( PHY, "[initial_sync] No cell synchronization found, abandoning\n" );
                        FILE *fd;
                        if ((fd = fopen("rxsig_frame0.dat","w"))!=NULL) {
                            fwrite((void*)&UE->common_vars.rxdata[0][0],
                                   sizeof(int32_t),
                                   10*UE->frame_parms.samples_per_tti,
                                   fd);
                            LOG_I(PHY,"Dummping Frame ... bye bye \n");
                            fclose(fd);
                            exit(0);
                        }
                        mac_xface->macphy_exit("No cell synchronization found, abandoning");
                        return &UE_thread_synch_retval; // not reached
                    }
                }
                LOG_I( PHY, "[initial_sync] trying carrier off %d Hz, rxgain %d (DL %u, UL %u)\n",
                       freq_offset,
                       UE->rx_total_gain_dB,
                       downlink_frequency[0][0]+freq_offset,
                       downlink_frequency[0][0]+uplink_frequency_offset[0][0]+freq_offset );

                for (i=0; i<openair0_cfg[UE->rf_map.card].rx_num_channels; i++) {
                    openair0_cfg[UE->rf_map.card].rx_freq[UE->rf_map.chain+i] = downlink_frequency[CC_id][i]+freq_offset;
                    openair0_cfg[UE->rf_map.card].tx_freq[UE->rf_map.chain+i] = downlink_frequency[CC_id][i]+uplink_frequency_offset[CC_id][i]+freq_offset;
                    openair0_cfg[UE->rf_map.card].rx_gain[UE->rf_map.chain+i] = UE->rx_total_gain_dB;//-USRP_GAIN_OFFSET;
laurent's avatar
laurent committed
445
                    if (UE->UE_scan_carrier==1)
laurent's avatar
laurent committed
446 447 448 449 450 451 452 453 454
                        openair0_cfg[UE->rf_map.card].autocal[UE->rf_map.chain+i] = 1;
                }
                UE->rfdevice.trx_set_freq_func(&UE->rfdevice,&openair0_cfg[0],0);
            }// initial_sync=0
            break;
        case si:
        default:
            break;
        }
455

laurent's avatar
laurent committed
456
        AssertFatal ( 0== pthread_mutex_lock(&UE->proc.mutex_synch), "");
laurent's avatar
laurent committed
457 458
        // indicate readiness
        UE->proc.instance_cnt_synch--;
laurent's avatar
laurent committed
459
        AssertFatal ( 0== pthread_mutex_unlock(&UE->proc.mutex_synch), "");
460

laurent's avatar
laurent committed
461 462
        VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_UE_THREAD_SYNCH, 0 );
    }  // while !oai_exit
463

laurent's avatar
laurent committed
464
    return &UE_thread_synch_retval;
465 466
}

467

468 469 470 471 472 473 474
/* this structure is used to pass both UE phy vars and
 * proc to the function UE_thread_rxn_txnp4
 */
struct rx_tx_thread_data {
  PHY_VARS_UE    *UE;
  UE_rxtx_proc_t *proc;
};
475

476
/*!
477
 * \brief This is the UE thread for RX subframe n and TX subframe n+4.
478
 * This thread performs the phy_procedures_UE_RX() on every received slot.
laurent's avatar
laurent committed
479
 * then, if TX is enabled it performs TX for n+4.
480 481 482
 * \param arg is a pointer to a \ref PHY_VARS_UE structure.
 * \returns a pointer to an int. The storage is not on the heap and must not be freed.
 */
483

laurent's avatar
laurent committed
484 485
static void *UE_thread_rxn_txnp4(void *arg) {
    static __thread int UE_thread_rxtx_retval;
486 487 488
    struct rx_tx_thread_data *rtd = arg;
    UE_rxtx_proc_t *proc = rtd->proc;
    PHY_VARS_UE    *UE   = rtd->UE;
laurent's avatar
laurent committed
489 490
    int ret;

491
    proc->instance_cnt_rxtx=-1;
laurent's avatar
laurent committed
492 493
    proc->subframe_rx=proc->sub_frame_start;

494 495
    char threadname[256];
    sprintf(threadname,"UE_%d_proc_%d", UE->Mod_id, proc->sub_frame_start);
laurent's avatar
laurent committed
496 497
    cpu_set_t cpuset;
    CPU_ZERO(&cpuset);
498 499 500 501
    if ( (proc->sub_frame_start+1)%2 == 0 && threads.even != -1 )
        CPU_SET(threads.even, &cpuset);
    if ( (proc->sub_frame_start+1)%2 == 1 && threads.odd != -1 )
        CPU_SET(threads.odd, &cpuset);
laurent's avatar
laurent committed
502
    init_thread(900000,1000000 , FIFO_PRIORITY-1, &cpuset,
503
                threadname);
laurent's avatar
laurent committed
504 505

    while (!oai_exit) {
506 507 508 509 510 511 512 513 514 515 516 517
        if (pthread_mutex_lock(&proc->mutex_rxtx) != 0) {
          LOG_E( PHY, "[SCHED][UE] error locking mutex for UE RXTX\n" );
          exit_fun("nothing to add");
        }
        while (proc->instance_cnt_rxtx < 0) {
          // most of the time, the thread is waiting here
          pthread_cond_wait( &proc->cond_rxtx, &proc->mutex_rxtx );
        }
        if (pthread_mutex_unlock(&proc->mutex_rxtx) != 0) {
          LOG_E( PHY, "[SCHED][UE] error unlocking mutex for UE RXn_TXnp4\n" );
          exit_fun("nothing to add");
        }
laurent's avatar
laurent committed
518

519 520 521 522
        initRefTimes(t2);
        initRefTimes(t3);
        pickTime(current);
        updateTimes(proc->gotIQs, &t2, 10000, "Delay to wake up UE_Thread_Rx (case 2)");
laurent's avatar
laurent committed
523 524 525 526 527 528 529 530 531

        // Process Rx data for one sub-frame
        lte_subframe_t sf_type = subframe_select( &UE->frame_parms, proc->subframe_rx);
        if ((sf_type == SF_DL) ||
                (UE->frame_parms.frame_type == FDD) ||
                (sf_type == SF_S)) {

            if (UE->frame_parms.frame_type == TDD) {
                LOG_D(PHY, "%s,TDD%d,%s: calling UE_RX\n",
532
                      threadname,
laurent's avatar
laurent committed
533 534 535 536 537 538
                      UE->frame_parms.tdd_config,
                      (sf_type==SF_DL? "SF_DL" :
                       (sf_type==SF_UL? "SF_UL" :
                        (sf_type==SF_S ? "SF_S"  : "UNKNOWN_SF_TYPE"))));
            } else {
                LOG_D(PHY, "%s,%s,%s: calling UE_RX\n",
539
                      threadname,
laurent's avatar
laurent committed
540 541 542 543 544 545 546 547
                      (UE->frame_parms.frame_type==FDD? "FDD":
                       (UE->frame_parms.frame_type==TDD? "TDD":"UNKNOWN_DUPLEX_MODE")),
                      (sf_type==SF_DL? "SF_DL" :
                       (sf_type==SF_UL? "SF_UL" :
                        (sf_type==SF_S ? "SF_S"  : "UNKNOWN_SF_TYPE"))));
            }
            phy_procedures_UE_RX( UE, proc, 0, 0, UE->mode, no_relay, NULL );
        }
Bilel's avatar
Bilel committed
548 549 550

        start_meas(&UE->generic_stat);

laurent's avatar
laurent committed
551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579
        if (UE->mac_enabled==1) {

            ret = mac_xface->ue_scheduler(UE->Mod_id,
                                          proc->frame_rx,
                                          proc->subframe_rx,
                                          proc->frame_tx,
                                          proc->subframe_tx,
                                          subframe_select(&UE->frame_parms,proc->subframe_tx),
                                          0,
                                          0/*FIXME CC_id*/);
            if ( ret != CONNECTION_OK) {
                char *txt;
                switch (ret) {
                case CONNECTION_LOST:
                    txt="RRC Connection lost, returning to PRACH";
                    break;
                case PHY_RESYNCH:
                    txt="RRC Connection lost, trying to resynch";
                    break;
                case RESYNCH:
                    txt="return to PRACH and perform a contention-free access";
                    break;
                default:
                    txt="UNKNOWN RETURN CODE";
                };
                LOG_E( PHY, "[UE %"PRIu8"] Frame %"PRIu32", subframe %u %s\n",
                       UE->Mod_id, proc->frame_rx, proc->subframe_tx,txt );
            }
        }
Bilel's avatar
Bilel committed
580 581 582

        stop_meas(&UE->generic_stat);

laurent's avatar
laurent committed
583
        // Prepare the future Tx data
584

laurent's avatar
laurent committed
585 586 587 588
        if ((subframe_select( &UE->frame_parms, proc->subframe_tx) == SF_UL) ||
                (UE->frame_parms.frame_type == FDD) )
            if (UE->mode != loop_through_memory)
                phy_procedures_UE_TX(UE,proc,0,0,UE->mode,no_relay);
589 590


laurent's avatar
laurent committed
591 592 593 594
        if ((subframe_select( &UE->frame_parms, proc->subframe_tx) == SF_S) &&
                (UE->frame_parms.frame_type == TDD))
            if (UE->mode != loop_through_memory)
                phy_procedures_UE_S_TX(UE,0,0,no_relay);
595
        updateTimes(current, &t3, 10000, "Delay to process sub-frame (case 3)");
596

597 598 599 600 601 602 603 604 605
        if (pthread_mutex_lock(&proc->mutex_rxtx) != 0) {
          LOG_E( PHY, "[SCHED][UE] error locking mutex for UE RXTX\n" );
          exit_fun("noting to add");
        }
        proc->instance_cnt_rxtx--;
        if (pthread_mutex_unlock(&proc->mutex_rxtx) != 0) {
          LOG_E( PHY, "[SCHED][UE] error unlocking mutex for UE RXTX\n" );
          exit_fun("noting to add");
        }
606 607
    }

laurent's avatar
laurent committed
608
// thread finished
609
    free(arg);
laurent's avatar
laurent committed
610
    return &UE_thread_rxtx_retval;
611
}
612

613 614 615
/*!
 * \brief This is the main UE thread.
 * This thread controls the other three UE threads:
616 617
 * - UE_thread_rxn_txnp4 (even subframes)
 * - UE_thread_rxn_txnp4 (odd subframes)
618 619 620 621
 * - UE_thread_synch
 * \param arg unused
 * \returns a pointer to an int. The storage is not on the heap and must not be freed.
 */
622 623 624

void *UE_thread(void *arg) {

625
    PHY_VARS_UE *UE = (PHY_VARS_UE *) arg;
laurent's avatar
laurent committed
626 627 628 629 630 631
    //  int tx_enabled = 0;
    int dummy_rx[UE->frame_parms.nb_antennas_rx][UE->frame_parms.samples_per_tti] __attribute__((aligned(32)));
    openair0_timestamp timestamp,timestamp1;
    void* rxp[NB_ANTENNAS_RX], *txp[NB_ANTENNAS_TX];
    int start_rx_stream = 0;
    int i;
632
    char threadname[128];
633

laurent's avatar
laurent committed
634 635
    cpu_set_t cpuset;
    CPU_ZERO(&cpuset);
636 637
    if ( threads.iq != -1 )
        CPU_SET(threads.iq, &cpuset);
laurent's avatar
laurent committed
638
    init_thread(100000, 500000, FIFO_PRIORITY, &cpuset,
639 640 641
                "UHD Threads");
    if (oaisim_flag == 0)
        AssertFatal(0== openair0_device_load(&(UE->rfdevice), &openair0_cfg[0]), "");
642
    UE->rfdevice.host_type = BBU_HOST;
643 644
    sprintf(threadname, "Main UE %d", UE->Mod_id);
    pthread_setname_np(pthread_self(), threadname);
645
    init_UE_threads(UE);
646

647
#ifdef NAS_UE
laurent's avatar
laurent committed
648 649
    MessageDef *message_p;
    message_p = itti_alloc_new_message(TASK_NAS_UE, INITIALIZE_MESSAGE);
650
    itti_send_msg_to_task (TASK_NAS_UE, UE->Mod_id + NB_eNB_INST, message_p);
651
#endif
652

laurent's avatar
laurent committed
653
    int sub_frame=-1;
654
    //int cumulated_shift=0;
655
    AssertFatal(UE->rfdevice.trx_start_func(&UE->rfdevice) == 0, "Could not start the device\n");
laurent's avatar
laurent committed
656
    while (!oai_exit) {
laurent's avatar
laurent committed
657 658 659 660
        AssertFatal ( 0== pthread_mutex_lock(&UE->proc.mutex_synch), "");
        int instance_cnt_synch = UE->proc.instance_cnt_synch;
        int is_synchronized    = UE->is_synchronized;
        AssertFatal ( 0== pthread_mutex_unlock(&UE->proc.mutex_synch), "");
laurent's avatar
laurent committed
661

laurent's avatar
laurent committed
662
        if (is_synchronized == 0) {
laurent's avatar
laurent committed
663 664 665
            if (instance_cnt_synch < 0) {  // we can invoke the synch
                // grab 10 ms of signal and wakeup synch thread
                for (int i=0; i<UE->frame_parms.nb_antennas_rx; i++)
666
                    rxp[i] = (void*)&UE->common_vars.rxdata[i][0];
laurent's avatar
laurent committed
667 668 669 670 671 672 673 674

                if (UE->mode != loop_through_memory)
                    AssertFatal( UE->frame_parms.samples_per_tti*10 ==
                                 UE->rfdevice.trx_read_func(&UE->rfdevice,
                                                            &timestamp,
                                                            rxp,
                                                            UE->frame_parms.samples_per_tti*10,
                                                            UE->frame_parms.nb_antennas_rx), "");
laurent's avatar
laurent committed
675
		AssertFatal ( 0== pthread_mutex_lock(&UE->proc.mutex_synch), "");
laurent's avatar
laurent committed
676 677 678 679 680 681 682
                instance_cnt_synch = ++UE->proc.instance_cnt_synch;
                if (instance_cnt_synch == 0) {
                    AssertFatal( 0 == pthread_cond_signal(&UE->proc.cond_synch), "");
                } else {
                    LOG_E( PHY, "[SCHED][UE] UE sync thread busy!!\n" );
                    exit_fun("nothing to add");
                }
683
		AssertFatal ( 0== pthread_mutex_unlock(&UE->proc.mutex_synch), "");
laurent's avatar
laurent committed
684
            } else {
laurent's avatar
laurent committed
685 686 687 688
                // grab 10 ms of signal into dummy buffer
                if (UE->mode != loop_through_memory) {
                    for (int i=0; i<UE->frame_parms.nb_antennas_rx; i++)
                        rxp[i] = (void*)&dummy_rx[i][0];
laurent's avatar
laurent committed
689
                    for (int sf=0; sf<10; sf++)
laurent's avatar
laurent committed
690
                        //	    printf("Reading dummy sf %d\n",sf);
691
                          UE->rfdevice.trx_read_func(&UE->rfdevice,
laurent's avatar
laurent committed
692 693 694
                                              &timestamp,
                                              rxp,
                                              UE->frame_parms.samples_per_tti,
695
                                              UE->frame_parms.nb_antennas_rx);
laurent's avatar
laurent committed
696
                }
697
            }
698

laurent's avatar
laurent committed
699 700 701 702 703 704 705 706 707 708
        } // UE->is_synchronized==0
        else {
            if (start_rx_stream==0) {
                start_rx_stream=1;
                if (UE->mode != loop_through_memory) {
                    if (UE->no_timing_correction==0) {
                        LOG_I(PHY,"Resynchronizing RX by %d samples (mode = %d)\n",UE->rx_offset,UE->mode);
                        AssertFatal(UE->rx_offset ==
                                    UE->rfdevice.trx_read_func(&UE->rfdevice,
                                                               &timestamp,
709
                                                               (void**)UE->common_vars.rxdata,
laurent's avatar
laurent committed
710 711 712 713 714 715 716 717 718 719 720
                                                               UE->rx_offset,
                                                               UE->frame_parms.nb_antennas_rx),"");
                    }
                    UE->rx_offset=0;
                    UE->proc.proc_rxtx[0].frame_rx++;
                    UE->proc.proc_rxtx[1].frame_rx++;

                    // read in first symbol
                    AssertFatal (UE->frame_parms.ofdm_symbol_size+UE->frame_parms.nb_prefix_samples0 ==
                                 UE->rfdevice.trx_read_func(&UE->rfdevice,
                                                            &timestamp,
721 722
                                                            (void**)UE->common_vars.rxdata,
                                                            UE->frame_parms.ofdm_symbol_size+UE->frame_parms.nb_prefix_samples0,
laurent's avatar
laurent committed
723 724 725 726 727 728 729 730 731 732 733 734 735
                                                            UE->frame_parms.nb_antennas_rx),"");
                    slot_fep(UE,0, 0, 0, 0, 0);
                } //UE->mode != loop_through_memory
                else
                    rt_sleep_ns(1000*1000);

            } else {
                sub_frame++;
                sub_frame%=10;
                UE_rxtx_proc_t *proc = &UE->proc.proc_rxtx[sub_frame&1];

                if (UE->mode != loop_through_memory) {
                    for (i=0; i<UE->frame_parms.nb_antennas_rx; i++)
Thomas Laurent's avatar
Thomas Laurent committed
736
                        rxp[i] = (void*)&UE->common_vars.rxdata[i][UE->frame_parms.ofdm_symbol_size+
737 738
                                 UE->frame_parms.nb_prefix_samples0+
                                 sub_frame*UE->frame_parms.samples_per_tti];
laurent's avatar
laurent committed
739 740 741 742 743 744 745 746
                    for (i=0; i<UE->frame_parms.nb_antennas_tx; i++)
                        txp[i] = (void*)&UE->common_vars.txdata[i][((sub_frame+2)%10)*UE->frame_parms.samples_per_tti];

                    int readBlockSize, writeBlockSize;
                    if (sub_frame<9) {
                        readBlockSize=UE->frame_parms.samples_per_tti;
                        writeBlockSize=UE->frame_parms.samples_per_tti;
                    } else {
747 748 749
                        // set TO compensation to zero
                        UE->rx_offset_diff = 0;
                        // compute TO compensation that should be applied for this frame
laurent's avatar
laurent committed
750 751 752 753 754 755 756
                        if ( UE->rx_offset < 5*UE->frame_parms.samples_per_tti  &&
                                UE->rx_offset > 0 )
                            UE->rx_offset_diff = -1 ;
                        if ( UE->rx_offset > 5*UE->frame_parms.samples_per_tti &&
                                UE->rx_offset < 10*UE->frame_parms.samples_per_tti )
                            UE->rx_offset_diff = 1;

757
                        LOG_D(PHY,"AbsSubframe %d.%d SET rx_off_diff to %d rx_offset %d \n",proc->frame_rx,sub_frame,UE->rx_offset_diff,UE->rx_offset);
laurent's avatar
laurent committed
758 759 760 761 762 763
                        readBlockSize=UE->frame_parms.samples_per_tti -
                                      UE->frame_parms.ofdm_symbol_size -
                                      UE->frame_parms.nb_prefix_samples0 -
                                      UE->rx_offset_diff;
                        writeBlockSize=UE->frame_parms.samples_per_tti -
                                       UE->rx_offset_diff;
laurent's avatar
laurent committed
764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788
                    }

                    AssertFatal(readBlockSize ==
                                UE->rfdevice.trx_read_func(&UE->rfdevice,
                                                           &timestamp,
                                                           rxp,
                                                           readBlockSize,
                                                           UE->frame_parms.nb_antennas_rx),"");
                    AssertFatal( writeBlockSize ==
                                 UE->rfdevice.trx_write_func(&UE->rfdevice,
                                         timestamp+
                                         (2*UE->frame_parms.samples_per_tti) -
                                         UE->frame_parms.ofdm_symbol_size-UE->frame_parms.nb_prefix_samples0 -
                                         openair0_cfg[0].tx_sample_advance,
                                         txp,
                                         writeBlockSize,
                                         UE->frame_parms.nb_antennas_tx,
                                         1),"");
                    if( sub_frame==9) {
                        // read in first symbol of next frame and adjust for timing drift
                        int first_symbols=writeBlockSize-readBlockSize;
                        if ( first_symbols > 0 )
                            AssertFatal(first_symbols ==
                                        UE->rfdevice.trx_read_func(&UE->rfdevice,
                                                                   &timestamp1,
Thomas Laurent's avatar
Thomas Laurent committed
789
                                                                   (void**)UE->common_vars.rxdata,
laurent's avatar
laurent committed
790 791 792 793 794
                                                                   first_symbols,
                                                                   UE->frame_parms.nb_antennas_rx),"");
                        if ( first_symbols <0 )
                            LOG_E(PHY,"can't compensate: diff =%d\n", first_symbols);
                    }
795
                    pickTime(gotIQs);
laurent's avatar
laurent committed
796 797 798 799 800 801
                    // operate on thread sf mod 2
                    AssertFatal(pthread_mutex_lock(&proc->mutex_rxtx) ==0,"");
                    if(sub_frame == 0) {
                        UE->proc.proc_rxtx[0].frame_rx++;
                        UE->proc.proc_rxtx[1].frame_rx++;
                    }
802 803
                    UE->proc.proc_rxtx[0].gotIQs=readTime(gotIQs);
                    UE->proc.proc_rxtx[1].gotIQs=readTime(gotIQs);
laurent's avatar
laurent committed
804 805 806 807 808 809 810
                    proc->subframe_rx=sub_frame;
                    proc->subframe_tx=(sub_frame+4)%10;
                    proc->frame_tx = proc->frame_rx + (proc->subframe_rx>5?1:0);
                    proc->timestamp_tx = timestamp+
                                         (4*UE->frame_parms.samples_per_tti)-
                                         UE->frame_parms.ofdm_symbol_size-UE->frame_parms.nb_prefix_samples0;

811 812 813 814 815 816 817 818 819 820 821 822
                    proc->instance_cnt_rxtx++;
                    if (proc->instance_cnt_rxtx == 0) {
                      if (pthread_cond_signal(&proc->cond_rxtx) != 0) {
                        LOG_E( PHY, "[SCHED][UE %d] ERROR pthread_cond_signal for UE RX thread\n", UE->Mod_id);
                        exit_fun("nothing to add");
                      }
                    } else {
                      LOG_E( PHY, "[SCHED][UE %d] UE RX thread busy (IC %d)!!\n", UE->Mod_id, proc->instance_cnt_rxtx);
                      if (proc->instance_cnt_rxtx > 2)
                        exit_fun("instance_cnt_rxtx > 2");
                    }

laurent's avatar
laurent committed
823 824
                    AssertFatal (pthread_cond_signal(&proc->cond_rxtx) ==0 ,"");
                    AssertFatal(pthread_mutex_unlock(&proc->mutex_rxtx) ==0,"");
825 826 827 828
                    initRefTimes(t1);
                    initStaticTime(lastTime);
                    updateTimes(lastTime, &t1, 20000, "Delay between two IQ acquisitions (case 1)");
                    pickStaticTime(lastTime);
laurent's avatar
laurent committed
829 830 831 832 833 834 835 836 837 838

                } else {
                    printf("Processing subframe %d",proc->subframe_rx);
                    getchar();
                }
            } // start_rx_stream==1
        } // UE->is_synchronized==1

    } // while !oai_exit
    return NULL;
839 840
}

841 842 843
/*!
 * \brief Initialize the UE theads.
 * Creates the UE threads:
844 845
 * - UE_thread_rxtx0
 * - UE_thread_rxtx1
846 847 848
 * - UE_thread_synch
 * and the locking between them.
 */
849
void init_UE_threads(PHY_VARS_UE *UE) {
850
    struct rx_tx_thread_data *rtd;
851

laurent's avatar
laurent committed
852 853
    pthread_attr_init (&UE->proc.attr_ue);
    pthread_attr_setstacksize(&UE->proc.attr_ue,8192);//5*PTHREAD_STACK_MIN);
854

855 856
    pthread_mutex_init(&UE->proc.mutex_synch,NULL);
    pthread_cond_init(&UE->proc.cond_synch,NULL);
857

laurent's avatar
laurent committed
858 859 860
    // the threads are not yet active, therefore access is allowed without locking
    int nb_threads=2;
    for (int i=0; i<nb_threads; i++) {
861 862 863 864
        rtd = calloc(1, sizeof(struct rx_tx_thread_data));
        if (rtd == NULL) abort();
        rtd->UE = UE;
        rtd->proc = &UE->proc.proc_rxtx[i];
laurent's avatar
laurent committed
865 866 867 868
        pthread_mutex_init(&UE->proc.proc_rxtx[i].mutex_rxtx,NULL);
        pthread_cond_init(&UE->proc.proc_rxtx[i].cond_rxtx,NULL);
        UE->proc.proc_rxtx[i].sub_frame_start=i;
        UE->proc.proc_rxtx[i].sub_frame_step=nb_threads;
869
        pthread_create(&UE->proc.proc_rxtx[i].pthread_rxtx, NULL, UE_thread_rxn_txnp4, rtd);
870
    }
laurent's avatar
laurent committed
871
    pthread_create(&UE->proc.pthread_synch,NULL,UE_thread_synch,(void*)UE);
872

873 874 875
}


876
#ifdef OPENAIR2
laurent's avatar
laurent committed
877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900
void fill_ue_band_info(void) {

    UE_EUTRA_Capability_t *UE_EUTRA_Capability = UE_rrc_inst[0].UECap->UE_EUTRA_Capability;
    int i,j;

    bands_to_scan.nbands = UE_EUTRA_Capability->rf_Parameters.supportedBandListEUTRA.list.count;

    for (i=0; i<bands_to_scan.nbands; i++) {

        for (j=0; j<sizeof (eutra_bands) / sizeof (eutra_bands[0]); j++)
            if (eutra_bands[j].band == UE_EUTRA_Capability->rf_Parameters.supportedBandListEUTRA.list.array[i]->bandEUTRA) {
                memcpy(&bands_to_scan.band_info[i],
                       &eutra_bands[j],
                       sizeof(eutra_band_t));

                printf("Band %d (%lu) : DL %u..%u Hz, UL %u..%u Hz, Duplex %s \n",
                       bands_to_scan.band_info[i].band,
                       UE_EUTRA_Capability->rf_Parameters.supportedBandListEUTRA.list.array[i]->bandEUTRA,
                       bands_to_scan.band_info[i].dl_min,
                       bands_to_scan.band_info[i].dl_max,
                       bands_to_scan.band_info[i].ul_min,
                       bands_to_scan.band_info[i].ul_max,
                       (bands_to_scan.band_info[i].frame_type==FDD) ? "FDD" : "TDD");
                break;
901
            }
902 903
    }
}
904
#endif
905

laurent's avatar
laurent committed
906
int setup_ue_buffers(PHY_VARS_UE **phy_vars_ue, openair0_config_t *openair0_cfg) {
907

laurent's avatar
laurent committed
908 909 910
    int i, CC_id;
    LTE_DL_FRAME_PARMS *frame_parms;
    openair0_rf_map *rf_map;
911

laurent's avatar
laurent committed
912 913
    for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
        rf_map = &phy_vars_ue[CC_id]->rf_map;
914

laurent's avatar
laurent committed
915 916
        AssertFatal( phy_vars_ue[CC_id] !=0, "");
        frame_parms = &(phy_vars_ue[CC_id]->frame_parms);
917

laurent's avatar
laurent committed
918 919 920
        // replace RX signal buffers with mmaped HW versions
        rxdata = (int32_t**)malloc16( frame_parms->nb_antennas_rx*sizeof(int32_t*) );
        txdata = (int32_t**)malloc16( frame_parms->nb_antennas_tx*sizeof(int32_t*) );
921

laurent's avatar
laurent committed
922 923 924 925 926 927 928
        for (i=0; i<frame_parms->nb_antennas_rx; i++) {
            LOG_I(PHY, "Mapping UE CC_id %d, rx_ant %d, freq %u on card %d, chain %d\n",
                  CC_id, i, downlink_frequency[CC_id][i], rf_map->card, rf_map->chain+i );
            free( phy_vars_ue[CC_id]->common_vars.rxdata[i] );
            rxdata[i] = (int32_t*)malloc16_clear( 307200*sizeof(int32_t) );
            phy_vars_ue[CC_id]->common_vars.rxdata[i] = rxdata[i]; // what about the "-N_TA_offset" ? // N_TA offset for TDD
        }
929

laurent's avatar
laurent committed
930 931 932 933 934 935 936
        for (i=0; i<frame_parms->nb_antennas_tx; i++) {
            LOG_I(PHY, "Mapping UE CC_id %d, tx_ant %d, freq %u on card %d, chain %d\n",
                  CC_id, i, downlink_frequency[CC_id][i], rf_map->card, rf_map->chain+i );
            free( phy_vars_ue[CC_id]->common_vars.txdata[i] );
            txdata[i] = (int32_t*)malloc16_clear( 307200*sizeof(int32_t) );
            phy_vars_ue[CC_id]->common_vars.txdata[i] = txdata[i];
        }
937

laurent's avatar
laurent committed
938 939 940 941
        // rxdata[x] points now to the same memory region as phy_vars_ue[CC_id]->common_vars.rxdata[x]
        // txdata[x] points now to the same memory region as phy_vars_ue[CC_id]->common_vars.txdata[x]
        // be careful when releasing memory!
        // because no "release_ue_buffers"-function is available, at least rxdata and txdata memory will leak (only some bytes)
942
    }
laurent's avatar
laurent committed
943
    return 0;
944
}
945