From c383e50bd6074834f9933b2457ff7ead0b8b849a Mon Sep 17 00:00:00 2001 From: Cedric Roux Date: Fri, 9 Oct 2015 17:15:11 +0200 Subject: [PATCH 001/263] This commit rejects an UE that connects by sending RRCConnectionRequest with S-TMSI. The observed behavior (samsung phone, lte dongle, sequans box) is that the UE keeps connecting over and over again. --- openair2/RRC/LITE/MESSAGES/asn1_msg.c | 61 +++++++++++++++++++++++++++ openair2/RRC/LITE/MESSAGES/asn1_msg.h | 10 +++++ openair2/RRC/LITE/rrc_eNB.c | 54 +++++++++++++++++++++++- 3 files changed, 123 insertions(+), 2 deletions(-) diff --git a/openair2/RRC/LITE/MESSAGES/asn1_msg.c b/openair2/RRC/LITE/MESSAGES/asn1_msg.c index 110dc6442d..ff0adf713b 100644 --- a/openair2/RRC/LITE/MESSAGES/asn1_msg.c +++ b/openair2/RRC/LITE/MESSAGES/asn1_msg.c @@ -2110,6 +2110,67 @@ do_RRCConnectionReestablishmentReject( return((enc_rval.encoded+7)/8); } +//------------------------------------------------------------------------------ +uint8_t +do_RRCConnectionReject( + uint8_t Mod_id, + uint8_t* const buffer) +//------------------------------------------------------------------------------ +{ + + asn_enc_rval_t enc_rval; + + DL_CCCH_Message_t dl_ccch_msg; + RRCConnectionReject_t *rrcConnectionReject; + + memset((void *)&dl_ccch_msg,0,sizeof(DL_CCCH_Message_t)); + dl_ccch_msg.message.present = DL_CCCH_MessageType_PR_c1; + dl_ccch_msg.message.choice.c1.present = DL_CCCH_MessageType__c1_PR_rrcConnectionReject; + rrcConnectionReject = &dl_ccch_msg.message.choice.c1.choice.rrcConnectionReject; + + // RRCConnectionReject + rrcConnectionReject->criticalExtensions.present = RRCConnectionReject__criticalExtensions_PR_c1; + rrcConnectionReject->criticalExtensions.choice.c1.present = RRCConnectionReject__criticalExtensions__c1_PR_rrcConnectionReject_r8; + /* let's put a wait time of 1s for the moment */ + rrcConnectionReject->criticalExtensions.choice.c1.choice.rrcConnectionReject_r8.waitTime = 1; + +#ifdef XER_PRINT + xer_fprint(stdout, &asn_DEF_DL_CCCH_Message, (void*)&dl_ccch_msg); +#endif + enc_rval = uper_encode_to_buffer(&asn_DEF_DL_CCCH_Message, + (void*)&dl_ccch_msg, + buffer, + 100); + AssertFatal (enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %ld)!\n", + enc_rval.failed_type->name, enc_rval.encoded); + +#if defined(ENABLE_ITTI) +# if !defined(DISABLE_XER_SPRINT) + { + char message_string[20000]; + size_t message_string_size; + + if ((message_string_size = xer_sprint(message_string, sizeof(message_string), &asn_DEF_DL_CCCH_Message, (void *) &dl_ccch_msg)) > 0) { + MessageDef *msg_p; + + msg_p = itti_alloc_new_message_sized (TASK_RRC_ENB, RRC_DL_CCCH, message_string_size + sizeof (IttiMsgText)); + msg_p->ittiMsg.rrc_dl_ccch.size = message_string_size; + memcpy(&msg_p->ittiMsg.rrc_dl_ccch.text, message_string, message_string_size); + + itti_send_msg_to_task(TASK_UNKNOWN, Mod_id, msg_p); + } + } +# endif +#endif + +#ifdef USER_MODE + LOG_D(RRC,"RRCConnectionReject Encoded %d bits (%d bytes)\n", + enc_rval.encoded,(enc_rval.encoded+7)/8); +#endif + + return((enc_rval.encoded+7)/8); +} + uint8_t do_RRCConnectionRelease( uint8_t Mod_id, uint8_t *buffer, diff --git a/openair2/RRC/LITE/MESSAGES/asn1_msg.h b/openair2/RRC/LITE/MESSAGES/asn1_msg.h index b5747cb94b..9c5e72293a 100644 --- a/openair2/RRC/LITE/MESSAGES/asn1_msg.h +++ b/openair2/RRC/LITE/MESSAGES/asn1_msg.h @@ -218,6 +218,16 @@ do_RRCConnectionReestablishmentReject( uint8_t Mod_id, uint8_t* const buffer); +/** +\brief Generate an RRCConnectionReject DL-CCCH-Message (eNB). +@param Mod_id Module ID of eNB +@param buffer Pointer to PER-encoded ASN.1 description of DL-CCCH-Message PDU +@returns Size of encoded bit stream in bytes*/ +uint8_t +do_RRCConnectionReject( + uint8_t Mod_id, + uint8_t* const buffer); + /** \brief Generate an RRCConnectionRequest UL-CCCH-Message (UE) based on random string or S-TMSI. This routine only generates an mo-data establishment cause. diff --git a/openair2/RRC/LITE/rrc_eNB.c b/openair2/RRC/LITE/rrc_eNB.c index f19c3bced4..0148626e5f 100644 --- a/openair2/RRC/LITE/rrc_eNB.c +++ b/openair2/RRC/LITE/rrc_eNB.c @@ -963,6 +963,49 @@ rrc_eNB_generate_UECapabilityEnquiry( } +//----------------------------------------------------------------------------- +void +rrc_eNB_generate_RRCConnectionReject( + const protocol_ctxt_t* const ctxt_pP, + rrc_eNB_ue_context_t* const ue_context_pP, + const int CC_id +) +//----------------------------------------------------------------------------- +{ +#ifdef RRC_MSG_PRINT + int cnt; +#endif + + eNB_rrc_inst[ctxt_pP->module_id].carrier[CC_id].Srb0.Tx_buffer.payload_size = + do_RRCConnectionReject(ctxt_pP->module_id, + (uint8_t*) eNB_rrc_inst[ctxt_pP->module_id].carrier[CC_id].Srb0.Tx_buffer.Payload); + +#ifdef RRC_MSG_PRINT + LOG_F(RRC,"[MSG] RRCConnectionReject\n"); + + for (cnt = 0; cnt < eNB_rrc_inst[ctxt_pP->module_id].carrier[CC_id].Srb0.Tx_buffer.payload_size; cnt++) { + LOG_F(RRC,"%02x ", ((uint8_t*)eNB_rrc_inst[ctxt_pP->module_id].Srb0.Tx_buffer.Payload)[cnt]); + } + + LOG_F(RRC,"\n"); +#endif + + MSC_LOG_TX_MESSAGE( + MSC_RRC_ENB, + MSC_RRC_UE, + eNB_rrc_inst[ctxt_pP->module_id].carrier[CC_id].Srb0.Tx_buffer.Header, + eNB_rrc_inst[ctxt_pP->module_id].carrier[CC_id].Srb0.Tx_buffer.payload_size, + MSC_AS_TIME_FMT" RRCConnectionReject UE %x size %u", + MSC_AS_TIME_ARGS(ctxt_pP), + ue_context_pP == NULL ? -1 : ue_context_pP->ue_context.rnti, + eNB_rrc_inst[ctxt_pP->module_id].carrier[CC_id].Srb0.Tx_buffer.payload_size); + + LOG_I(RRC, + PROTOCOL_RRC_CTXT_UE_FMT" [RAPROC] Logical Channel DL-CCCH, Generating RRCConnectionReject (bytes %d)\n", + PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP), + eNB_rrc_inst[ctxt_pP->module_id].carrier[CC_id].Srb0.Tx_buffer.payload_size); +} + //----------------------------------------------------------------------------- void rrc_eNB_generate_RRCConnectionReestablishmentReject( @@ -3627,8 +3670,15 @@ rrc_eNB_decode_ccch( } else { rrcConnectionRequest = &ul_ccch_msg->message.choice.c1.choice.rrcConnectionRequest.criticalExtensions.choice.rrcConnectionRequest_r8; { - AssertFatal(rrcConnectionRequest->ue_Identity.present == InitialUE_Identity_PR_randomValue, - "unsupported InitialUE-Identity in RRCConnectionRequest"); + if (rrcConnectionRequest->ue_Identity.present != InitialUE_Identity_PR_randomValue) { + LOG_E(RRC, + PROTOCOL_RRC_CTXT_UE_FMT" RRCConnectionRequest with S-TMSI not supported yet, let's reject the UE\n", + PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP)); + rrc_eNB_generate_RRCConnectionReject(ctxt_pP, + rrc_eNB_get_ue_context(&eNB_rrc_inst[ctxt_pP->module_id], ctxt_pP->rnti), + CC_id); + break; + } AssertFatal(rrcConnectionRequest->ue_Identity.choice.randomValue.size == 5, "wrong InitialUE-Identity randomValue size, expected 5, provided %d", rrcConnectionRequest->ue_Identity.choice.randomValue.size); From 9dd1341db4ab53ff18d53d9f74c387757400f0ff Mon Sep 17 00:00:00 2001 From: Navid Nikaein Date: Mon, 12 Oct 2015 18:42:11 +0200 Subject: [PATCH 002/263] update bladerf RX and TX API --- .../ARCH/BLADERF/USERSPACE/LIB/bladerf_lib.c | 178 +++++++++++------- 1 file changed, 108 insertions(+), 70 deletions(-) diff --git a/targets/ARCH/BLADERF/USERSPACE/LIB/bladerf_lib.c b/targets/ARCH/BLADERF/USERSPACE/LIB/bladerf_lib.c index d515a206ae..ce2e998fbf 100644 --- a/targets/ARCH/BLADERF/USERSPACE/LIB/bladerf_lib.c +++ b/targets/ARCH/BLADERF/USERSPACE/LIB/bladerf_lib.c @@ -38,6 +38,14 @@ #include #include "bladerf_lib.h" +#ifdef __SSE4_1__ +# include +#endif + +#ifdef __AVX2__ +# include +#endif + int num_devices=0; /*These items configure the underlying asynch stream used by the the sync interface. */ @@ -47,16 +55,17 @@ int trx_brf_init(openair0_device *openair0) { } -openair0_timestamp trx_get_timestamp(openair0_device *device) { +openair0_timestamp trx_get_timestamp(openair0_device *device, bladerf_module module) { int status; struct bladerf_metadata meta; brf_state_t *brf = (brf_state_t*)device->priv; + memset(&meta, 0, sizeof(meta)); - if ((status=bladerf_get_timestamp(brf->dev, BLADERF_MODULE_TX, &meta.timestamp)) != 0) { - fprintf(stderr,"Failed to get current RX timestamp: %s\n",bladerf_strerror(status)); - } else { - printf("Current TX timestampe 0x%016"PRIx64"\n", meta.timestamp); - } + if ((status=bladerf_get_timestamp(brf->dev, module, &meta.timestamp)) != 0) { + fprintf(stderr,"Failed to get current %s timestamp: %s\n",(module == BLADERF_MODULE_RX ) ? "RX" : "TX", bladerf_strerror(status)); + return -1; + } // else {printf("Current RX timestampe 0x%016"PRIx64"\n", meta.timestamp); } + return meta.timestamp; } @@ -73,22 +82,26 @@ static void trx_brf_stats(openair0_device *device){ static int trx_brf_write(openair0_device *device,openair0_timestamp ptimestamp, void **buff, int nsamps, int cc) { - int status, i; + int status; brf_state_t *brf = (brf_state_t*)device->priv; /* BRF has only 1 rx/tx chaine : is it correct? */ - void *samples = (void*)buff[0]; + int16_t *samples = (int16_t*)buff[0]; - //brf->meta_tx.flags &= ~BLADERF_META_FLAG_TX_NOW; - brf->meta_tx.flags = BLADERF_META_FLAG_TX_BURST_START | - BLADERF_META_FLAG_TX_NOW | - BLADERF_META_FLAG_TX_BURST_END; - - brf->meta_tx.timestamp= (uint64_t) ptimestamp; - + //memset(&brf->meta_tx, 0, sizeof(brf->meta_tx)); + // When BLADERF_META_FLAG_TX_NOW is used the timestamp is not used, so one can't schedule a tx + if (brf->meta_tx.flags == 0 ) + brf->meta_tx.flags = (BLADERF_META_FLAG_TX_BURST_START);// | BLADERF_META_FLAG_TX_BURST_END);// | BLADERF_META_FLAG_TX_NOW); + + + brf->meta_tx.timestamp= (uint64_t) (ptimestamp); status = bladerf_sync_tx(brf->dev, samples, (unsigned int) nsamps, &brf->meta_tx, 2*brf->tx_timeout_ms); + + if (brf->meta_tx.flags == BLADERF_META_FLAG_TX_BURST_START) + brf->meta_tx.flags = BLADERF_META_FLAG_TX_UPDATE_TIMESTAMP; + if (status != 0) { - fprintf(stderr,"Failed to TX sample: %s\n", bladerf_strerror(status)); + //fprintf(stderr,"Failed to TX sample: %s\n", bladerf_strerror(status)); brf->num_tx_errors++; brf_error(status); } else if (brf->meta_tx.status & BLADERF_META_STATUS_UNDERRUN){ @@ -96,6 +109,8 @@ static int trx_brf_write(openair0_device *device,openair0_timestamp ptimestamp, fprintf(stderr, "TX Underrun detected. %u valid samples were read.\n", brf->meta_tx.actual_count); brf->num_underflows++; } + //printf("Provided TX timestampe %u, meta timestame %u\n", ptimestamp,brf->meta_tx.timestamp); + // printf("tx status %d \n",brf->meta_tx.status); brf->tx_current_ts=brf->meta_tx.timestamp; brf->tx_actual_nsamps+=brf->meta_tx.actual_count; @@ -107,26 +122,27 @@ static int trx_brf_write(openair0_device *device,openair0_timestamp ptimestamp, } static int trx_brf_read(openair0_device *device, openair0_timestamp *ptimestamp, void **buff, int nsamps, int cc) { - int status, ret; - - unsigned int i; + + int status=0; brf_state_t *brf = (brf_state_t*)device->priv; // BRF has only one rx/tx chain - void *samples = (void*)buff[0]; - - brf->meta_rx.flags |= BLADERF_META_FLAG_RX_NOW; + int16_t *samples = (int16_t*)buff[0]; + + brf->meta_rx.flags = BLADERF_META_FLAG_RX_NOW; status = bladerf_sync_rx(brf->dev, samples, (unsigned int) nsamps, &brf->meta_rx, 2*brf->rx_timeout_ms); + //printf("Current RX timestampe %u, nsamps %u, actual %u, cc %d\n", brf->meta_rx.timestamp, nsamps, brf->meta_rx.actual_count, cc); + if (status != 0) { fprintf(stderr, "RX failed: %s\n", bladerf_strerror(status)); brf->num_rx_errors++; } else if ( brf->meta_rx.status & BLADERF_META_STATUS_OVERRUN) { brf->num_overflows++; - fprintf(stderr, "RX overrun (%d) is detected. t=0x%"PRIu64". Got %u samples. nsymps %d\n", + fprintf(stderr, "RX overrun (%d) is detected. t=%u. Got %u samples. nsymps %d\n", brf->num_overflows,brf->meta_rx.timestamp, brf->meta_rx.actual_count, nsamps); - //brf->meta_rx.timestamp=(unsigned int)(nsamps-brf->meta_rx.actual_count); - } + } + //printf("Current RX timestampe %u\n", brf->meta_rx.timestamp); //printf("[BRF] (buff %p) ts=0x%"PRIu64" %s\n",samples, brf->meta_rx.timestamp,bladerf_strerror(status)); brf->rx_current_ts=brf->meta_rx.timestamp; brf->rx_actual_nsamps+=brf->meta_rx.actual_count; @@ -135,7 +151,7 @@ static int trx_brf_read(openair0_device *device, openair0_timestamp *ptimestamp, *ptimestamp = brf->meta_rx.timestamp; - + return brf->meta_rx.actual_count; } @@ -193,17 +209,21 @@ int openair0_dev_init_bladerf(openair0_device *device, openair0_config_t *openai brf_state_t *brf = (brf_state_t*)malloc(sizeof(brf_state_t)); memset(brf, 0, sizeof(brf_state_t)); // init required params for BRF - brf->num_buffers = 128; - brf->buffer_size = (unsigned int) openair0_cfg[card].samples_per_packet*sizeof(int32_t); // buffer size = 4096 for sample_len of 1024 - brf->num_transfers = 16; - brf->rx_timeout_ms = 0; - brf->tx_timeout_ms = 0; - brf->sample_rate=(unsigned int)openair0_cfg[card].sample_rate; + // The number of buffers to use in the underlying data stream + brf->num_buffers = 128; + // the size of the underlying stream buffers, in samples + brf->buffer_size = (unsigned int) openair0_cfg[card].samples_per_packet;//*sizeof(int32_t); // buffer size = 4096 for sample_len of 1024 + brf->num_transfers = 16; + brf->rx_timeout_ms = 0; + brf->tx_timeout_ms = 0; + brf->sample_rate=(unsigned int)openair0_cfg[card].sample_rate; - - printf("\n[BRF] sampling_rate %d, num_buffers %d, buffer_size %d, num transfer %d, timeout_ms (rx %d, tx %d)\n", - brf->sample_rate, brf->num_buffers, brf->buffer_size,brf->num_transfers, brf->rx_timeout_ms, brf->tx_timeout_ms); + memset(&brf->meta_rx, 0, sizeof(brf->meta_rx)); + memset(&brf->meta_tx, 0, sizeof(brf->meta_tx)); + printf("\n[BRF] sampling_rate %d, num_buffers %d, buffer_size %d, num transfer %d, timeout_ms (rx %d, tx %d)\n", + brf->sample_rate, brf->num_buffers, brf->buffer_size,brf->num_transfers, brf->rx_timeout_ms, brf->tx_timeout_ms); + if ((status=bladerf_open(&brf->dev, "")) != 0 ) { fprintf(stderr,"Failed to open brf device: %s\n",bladerf_strerror(status)); brf_error(status); @@ -217,83 +237,78 @@ int openair0_dev_init_bladerf(openair0_device *device, openair0_config_t *openai printf("[BRF] Device does not operates at max speed, change the USB port\n"); brf_error(BLADERF_ERR_UNSUPPORTED); } - // RX + // RX // Example of CLI output: RX Frequency: 2539999999Hz if ((status=bladerf_set_frequency(brf->dev, BLADERF_MODULE_RX, (unsigned int) openair0_cfg[card].rx_freq[0])) != 0){ fprintf(stderr,"Failed to set RX frequency: %s\n",bladerf_strerror(status)); brf_error(status); } else - printf("[BRF] set RX frequency to %f\n",openair0_cfg[card].rx_freq[0]); + printf("[BRF] set RX frequency to %u\n",(unsigned int)openair0_cfg[card].rx_freq[0]); - - if ((status=bladerf_set_sample_rate(brf->dev, BLADERF_MODULE_RX, (unsigned int)openair0_cfg[card].sample_rate, NULL)) != 0){ + unsigned int actual_value=0; + if ((status=bladerf_set_sample_rate(brf->dev, BLADERF_MODULE_RX, (unsigned int) openair0_cfg[card].sample_rate, &actual_value)) != 0){ fprintf(stderr,"Failed to set RX sample rate: %s\n", bladerf_strerror(status)); brf_error(status); - }else - printf("[BRF] set RX sample rate to %f\n",openair0_cfg[card].sample_rate); + }else + printf("[BRF] set RX sample rate to %u, %u\n", (unsigned int) openair0_cfg[card].sample_rate, actual_value); - if ((status=bladerf_set_bandwidth(brf->dev, BLADERF_MODULE_RX, (unsigned int) openair0_cfg[card].rx_bw, NULL)) != 0){ + + if ((status=bladerf_set_bandwidth(brf->dev, BLADERF_MODULE_RX, (unsigned int) openair0_cfg[card].rx_bw, &actual_value)) != 0){ fprintf(stderr,"Failed to set RX bandwidth: %s\n", bladerf_strerror(status)); brf_error(status); }else - printf("[BRF] set RX bandwidth to %f\n",openair0_cfg[card].rx_bw); + printf("[BRF] set RX bandwidth to %u, %u\n",(unsigned int)openair0_cfg[card].rx_bw, actual_value); if ((status=bladerf_set_gain(brf->dev, BLADERF_MODULE_RX, (int) openair0_cfg[card].rx_gain[0])) != 0) { fprintf(stderr,"Failed to set RX gain: %s\n",bladerf_strerror(status)); brf_error(status); } else - printf("[BRF] set RX gain to %f\n",openair0_cfg[card].rx_gain[0]); + printf("[BRF] set RX gain to %d\n",(int)openair0_cfg[card].rx_gain[0]); - /* Configure the device's RX module for use with the sync interface. - * SC16 Q11 samples *with* metadata are used. */ - if ((status=bladerf_sync_config(brf->dev, BLADERF_MODULE_RX, BLADERF_FORMAT_SC16_Q11_META,brf->num_buffers,brf->buffer_size,brf->num_transfers,brf->rx_timeout_ms)) != 0 ) { - fprintf(stderr,"Failed to configure RX sync interface: %s\n", bladerf_strerror(status)); - brf_error(status); - }else - printf("[BRF] configured Rx for sync interface \n"); - - /* We must always enable the RX module after calling bladerf_sync_config(), and - * before attempting to RX samples via bladerf_sync_rx(). */ - if ((status=bladerf_enable_module(brf->dev, BLADERF_MODULE_RX, true)) != 0) { - fprintf(stderr,"Failed to enable RX module: %s\n", bladerf_strerror(status)); - brf_error(status); - }else - printf("[BRF] RX module enabled \n"); - // TX + if ((status=bladerf_set_frequency(brf->dev, BLADERF_MODULE_TX, (unsigned int) openair0_cfg[card].tx_freq[0])) != 0){ fprintf(stderr,"Failed to set TX frequency: %s\n",bladerf_strerror(status)); brf_error(status); }else - printf("[BRF] set Tx Frequenct to %f \n", openair0_cfg[card].tx_freq[0]); + printf("[BRF] set TX Frequenct to %u\n", (unsigned int) openair0_cfg[card].tx_freq[0]); if ((status=bladerf_set_sample_rate(brf->dev, BLADERF_MODULE_TX, (unsigned int) openair0_cfg[card].sample_rate, NULL)) != 0){ fprintf(stderr,"Failed to set TX sample rate: %s\n", bladerf_strerror(status)); brf_error(status); }else - printf("[BRF] set Tx sampling rate to %f \n", openair0_cfg[card].sample_rate); + printf("[BRF] set TX sampling rate to %u \n", (unsigned int) openair0_cfg[card].sample_rate); if ((status=bladerf_set_bandwidth(brf->dev, BLADERF_MODULE_TX,(unsigned int)openair0_cfg[card].tx_bw, NULL)) != 0){ - fprintf(stderr, "Failed to set RX bandwidth: %s\n", bladerf_strerror(status)); + fprintf(stderr, "Failed to set TX bandwidth: %s\n", bladerf_strerror(status)); brf_error(status); }else - printf("[BRF] set Tx sampling ratebandwidth to %f \n", openair0_cfg[card].tx_bw); + printf("[BRF] set TX bandwidth to %u \n", (unsigned int) openair0_cfg[card].tx_bw); - if ((status=bladerf_set_gain(brf->dev, BLADERF_MODULE_TX, (int)openair0_cfg[card].tx_gain[0])) != 0) { + if ((status=bladerf_set_gain(brf->dev, BLADERF_MODULE_TX, (int) openair0_cfg[card].tx_gain[0])) != 0) { fprintf(stderr,"Failed to set TX gain: %s\n",bladerf_strerror(status)); brf_error(status); }else - printf("[BRF] set the Tx gain to %f \n", openair0_cfg[card].tx_gain[0]); + printf("[BRF] set the TX gain to %d\n", (int)openair0_cfg[card].tx_gain[0]); + - - /* Configure the device's TX module for use with the sync interface. + /* Configure the device's TX module for use with the sync interface. * SC16 Q11 samples *with* metadata are used. */ if ((status=bladerf_sync_config(brf->dev, BLADERF_MODULE_TX,BLADERF_FORMAT_SC16_Q11_META,brf->num_buffers,brf->buffer_size,brf->num_transfers,brf->tx_timeout_ms)) != 0 ) { fprintf(stderr,"Failed to configure TX sync interface: %s\n", bladerf_strerror(status)); brf_error(status); }else - printf("[BRF] configured tx for sync interface \n"); + printf("[BRF] configured TX sync interface \n"); + +/* Configure the device's RX module for use with the sync interface. + * SC16 Q11 samples *with* metadata are used. */ + if ((status=bladerf_sync_config(brf->dev, BLADERF_MODULE_RX, BLADERF_FORMAT_SC16_Q11_META,brf->num_buffers,brf->buffer_size,brf->num_transfers,brf->rx_timeout_ms)) != 0 ) { + fprintf(stderr,"Failed to configure RX sync interface: %s\n", bladerf_strerror(status)); + brf_error(status); + }else + printf("[BRF] configured Rx sync interface \n"); + /* We must always enable the TX module after calling bladerf_sync_config(), and * before attempting to TX samples via bladerf_sync_tx(). */ @@ -303,6 +318,29 @@ int openair0_dev_init_bladerf(openair0_device *device, openair0_config_t *openai } else printf("[BRF] TX module enabled \n"); + /* We must always enable the RX module after calling bladerf_sync_config(), and + * before attempting to RX samples via bladerf_sync_rx(). */ + if ((status=bladerf_enable_module(brf->dev, BLADERF_MODULE_RX, true)) != 0) { + fprintf(stderr,"Failed to enable RX module: %s\n", bladerf_strerror(status)); + brf_error(status); + }else + printf("[BRF] RX module enabled \n"); + + // calibrate + /* + if ((status=bladerf_calibrate_dc(brf->dev, BLADERF_MODULE_TX)) != 0) { + fprintf(stderr,"Failed to calibrate TX DC: %s\n", bladerf_strerror(status)); + brf_error(status); + } else + printf("[BRF] TX module calibrated DC \n"); + + if ((status=bladerf_calibrate_dc(brf->dev, BLADERF_MODULE_RX)) != 0) { + fprintf(stderr,"Failed to calibrate RX DC: %s\n", bladerf_strerror(status)); + brf_error(status); + }else + printf("[BRF] RX module calibrated DC \n"); + */ + bladerf_log_set_verbosity(get_brf_log_level(openair0_cfg[card].log_level)); printf("BLADERF: Initializing openair0_device\n"); @@ -359,7 +397,7 @@ struct bladerf * open_bladerf_from_serial(const char *serial) { int get_brf_log_level(int log_level){ int level=BLADERF_LOG_LEVEL_INFO; - //return BLADERF_LOG_LEVEL_DEBUG; + return BLADERF_LOG_LEVEL_DEBUG; // BLADERF_LOG_LEVEL_VERBOSE;// BLADERF_LOG_LEVEL_DEBUG; // switch(log_level) { case LOG_DEBUG: level=BLADERF_LOG_LEVEL_DEBUG; From 7ca47603097e3cf40d6b813a965e89f251ce1697 Mon Sep 17 00:00:00 2001 From: Navid Nikaein Date: Mon, 12 Oct 2015 18:46:03 +0200 Subject: [PATCH 003/263] update bladerf timing --- targets/RT/USER/lte-softmodem.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/targets/RT/USER/lte-softmodem.c b/targets/RT/USER/lte-softmodem.c index b96a7ae529..8e08cfc04c 100644 --- a/targets/RT/USER/lte-softmodem.c +++ b/targets/RT/USER/lte-softmodem.c @@ -2885,7 +2885,7 @@ int main( int argc, char **argv ) openair0_cfg[card].tx_delay = 5; #elif OAI_BLADERF openair0_cfg[card].tx_forward_nsamps = 0; - openair0_cfg[card].tx_delay = 8; + openair0_cfg[card].tx_delay = 4; #endif #endif } else if (frame_parms[0]->N_RB_DL == 6) { From 33860c1604cef2ea63093667b5cd8dcacc70d559 Mon Sep 17 00:00:00 2001 From: ABEILLE Date: Mon, 19 Oct 2015 19:29:04 +0200 Subject: [PATCH 004/263] merged in changes from abeille (modifications on final svn version) --- openair1/PHY/LTE_ESTIMATION/defs.h | 7 +- .../PHY/LTE_ESTIMATION/lte_eNB_measurements.c | 102 +++++--------- openair1/PHY/LTE_TRANSPORT/defs.h | 6 +- openair1/PHY/LTE_TRANSPORT/print_stats.c | 18 +-- openair1/PHY/LTE_TRANSPORT/proto.h | 28 ++-- openair1/PHY/LTE_TRANSPORT/pucch.c | 133 ++++++++++-------- .../PHY/LTE_TRANSPORT/ulsch_demodulation.c | 7 + openair1/PHY/TOOLS/lte_phy_scope.c | 13 +- openair1/PHY/defs.h | 3 + openair1/PHY/impl_defs_top.h | 2 +- openair1/SCHED/phy_procedures_lte_eNb.c | 61 ++++++-- openair1/SIMULATION/LTE_PHY/pucchsim.c | 26 ++-- openair2/LAYER2/MAC/eNB_scheduler_dlsch.c | 11 +- openair2/LAYER2/MAC/eNB_scheduler_ulsch.c | 1 + targets/ARCH/COMMON/common_lib.c | 11 +- .../CONF/enb.band7.tm1.usrpb210.conf | 6 +- targets/RT/USER/lte-softmodem.c | 35 +++-- 17 files changed, 274 insertions(+), 196 deletions(-) diff --git a/openair1/PHY/LTE_ESTIMATION/defs.h b/openair1/PHY/LTE_ESTIMATION/defs.h index 10dc558c9b..903793c2b5 100644 --- a/openair1/PHY/LTE_ESTIMATION/defs.h +++ b/openair1/PHY/LTE_ESTIMATION/defs.h @@ -243,15 +243,16 @@ int lte_est_timing_advance(LTE_DL_FRAME_PARMS *frame_parms, int lte_est_timing_advance_pusch(PHY_VARS_eNB* phy_vars_eNB,module_id_t UE_id,uint8_t subframe); -void lte_eNB_I0_measurements(PHY_VARS_eNB *phy_vars_eNb, +void lte_eNB_I0_measurements(PHY_VARS_eNB *phy_vars_eNB, + int subframe, module_id_t eNB_id, unsigned char clear); -void lte_eNB_I0_measurements_emul(PHY_VARS_eNB *phy_vars_eNb, +void lte_eNB_I0_measurements_emul(PHY_VARS_eNB *phy_vars_eNB, uint8_t sect_id); -void lte_eNB_srs_measurements(PHY_VARS_eNB *phy_vars_eNb, +void lte_eNB_srs_measurements(PHY_VARS_eNB *phy_vars_eNBy, module_id_t eNB_id, module_id_t UE_id, unsigned char init_averaging); diff --git a/openair1/PHY/LTE_ESTIMATION/lte_eNB_measurements.c b/openair1/PHY/LTE_ESTIMATION/lte_eNB_measurements.c index 9564b7842c..7c0c45b05c 100644 --- a/openair1/PHY/LTE_ESTIMATION/lte_eNB_measurements.c +++ b/openair1/PHY/LTE_ESTIMATION/lte_eNB_measurements.c @@ -39,57 +39,36 @@ int32_t rx_power_avg_eNB[3][3]; -void lte_eNB_I0_measurements(PHY_VARS_eNB *phy_vars_eNb, +void lte_eNB_I0_measurements(PHY_VARS_eNB *phy_vars_eNB, + int subframe, unsigned char eNB_id, unsigned char clear) { - LTE_eNB_COMMON *eNB_common_vars = &phy_vars_eNb->lte_eNB_common_vars; - LTE_DL_FRAME_PARMS *frame_parms = &phy_vars_eNb->lte_frame_parms; - PHY_MEASUREMENTS_eNB *phy_measurements = &phy_vars_eNb->PHY_measurements_eNB[eNB_id]; - + LTE_eNB_COMMON *eNB_common_vars = &phy_vars_eNB->lte_eNB_common_vars; + LTE_DL_FRAME_PARMS *frame_parms = &phy_vars_eNB->lte_frame_parms; + PHY_MEASUREMENTS_eNB *phy_measurements = &phy_vars_eNB->PHY_measurements_eNB[eNB_id]; + int32_t *rb_mask = phy_vars_eNB->rb_mask_ul; uint32_t aarx,rx_power_correction; uint32_t rb; int32_t *ul_ch; int32_t n0_power_tot; - + int len; + int offset; + int Nsymb = (frame_parms->Ncp==NORMAL)?14:12; // noise measurements // for the moment we measure the noise on the 7th OFDM symbol (in S subframe) phy_measurements->n0_power_tot = 0; - /* printf("rxdataF0 %p, rxdataF1 %p\n", - (&eNB_common_vars->rxdataF[0][0][(frame_parms->ofdm_symbol_size + frame_parms->first_carrier_offset)<<1 ]), - (&eNB_common_vars->rxdataF[0][1][(frame_parms->ofdm_symbol_size + frame_parms->first_carrier_offset)<<1 ])); - */ - /* - for (i=0;i<512;i++) - printf("sector 0 antenna 0 : %d,%d\n",((short *)&eNB_common_vars->rxdataF[0][0][(19*frame_parms->ofdm_symbol_size)<<1])[i<<1], - ((short *)&eNB_common_vars->rxdataF[0][0][(19*frame_parms->ofdm_symbol_size)<<1])[1+(i<<1)]); - - for (i=0;i<12;i++) - // printf("sector 0 antenna 1 : %d,%d\n",((short *)&eNB_common_vars->rxdataF[0][1][(19*frame_parms->ofdm_symbol_size)<<1])[i<<1], - ((short *)&eNB_common_vars->rxdataF[0][1][(19*frame_parms->ofdm_symbol_size)<<1])[1+(i<<1)]); - */ - - if ( (frame_parms->ofdm_symbol_size == 128) || - (frame_parms->ofdm_symbol_size == 512) ) - rx_power_correction = 2; - else - rx_power_correction = 1; - for (aarx=0; aarxnb_antennas_rx; aarx++) { if (clear == 1) phy_measurements->n0_power[aarx]=0; -#ifdef USER_MODE + phy_measurements->n0_power[aarx] = ((k1*signal_energy(&eNB_common_vars->rxdata[eNB_id][aarx][(frame_parms->samples_per_tti<<1) -frame_parms->ofdm_symbol_size], frame_parms->ofdm_symbol_size)) + k2*phy_measurements->n0_power[aarx])>>10; -#else - phy_measurements->n0_power[aarx] = ((k1*signal_energy(&eNB_common_vars->rxdata[eNB_id][aarx][(frame_parms->samples_per_tti<<1) -frame_parms->ofdm_symbol_size], - frame_parms->ofdm_symbol_size))+k2*phy_measurements->n0_power[aarx])>>10; -#endif phy_measurements->n0_power[aarx] = (phy_measurements->n0_power[aarx] * 12*frame_parms->N_RB_DL)/(frame_parms->ofdm_symbol_size); phy_measurements->n0_power_dB[aarx] = (unsigned short) dB_fixed(phy_measurements->n0_power[aarx]); phy_measurements->n0_power_tot += phy_measurements->n0_power[aarx]; @@ -97,52 +76,49 @@ void lte_eNB_I0_measurements(PHY_VARS_eNB *phy_vars_eNb, phy_measurements->n0_power_tot_dB = (unsigned short) dB_fixed(phy_measurements->n0_power_tot); - phy_measurements->n0_power_tot_dBm = phy_measurements->n0_power_tot_dB - phy_vars_eNb->rx_total_gain_eNB_dB; + phy_measurements->n0_power_tot_dBm = phy_measurements->n0_power_tot_dB - phy_vars_eNB->rx_total_gain_eNB_dB; // printf("n0_power %d\n",phy_measurements->n0_power_tot_dB); for (rb=0; rbN_RB_UL; rb++) { n0_power_tot=0; + if ((rb_mask[rb>>5]&(1<<(rb&31))) == 0) { // check that rb was not used in this subframe + for (aarx=0; aarxnb_antennas_rx; aarx++) { - for (aarx=0; aarxnb_antennas_rx; aarx++) { + // select the 7th symbol in an uplink subframe + offset = (frame_parms->first_carrier_offset + (rb*12))%frame_parms->ofdm_symbol_size; + offset += (7*frame_parms->ofdm_symbol_size);//(((Nsymb*subframe)+7)*frame_parms->ofdm_symbol_size); + ul_ch = &eNB_common_vars->rxdataF[eNB_id][aarx][offset]; + len = 12; + // just do first half of middle PRB for odd number of PRBs + if (((frame_parms->N_RB_UL&1) == 1) && + (rb==(frame_parms->N_RB_UL>>1))) { + len=6; + } + if (clear == 1) + phy_measurements->n0_subband_power[aarx][rb]=0; + + AssertFatal(ul_ch, "RX signal buffer (freq) problem"); - if (rb < 12) - // ul_ch = &eNB_common_vars->rxdataF[eNB_id][aarx][((19*(frame_parms->ofdm_symbol_size)) + frame_parms->first_carrier_offset + (rb*12))<<1]; - ul_ch = &eNB_common_vars->rxdataF[eNB_id][aarx][((7*frame_parms->ofdm_symbol_size) + frame_parms->first_carrier_offset + (rb*12))<<1]; - else if (rb>12) - ul_ch = &eNB_common_vars->rxdataF[eNB_id][aarx][((7*frame_parms->ofdm_symbol_size) + 6 + (rb-13)*12)<<1]; - else { - ul_ch = NULL; - } - - if (clear == 1) - phy_measurements->n0_subband_power[aarx][rb]=0; - - if (ul_ch) { - // for (i=0;i<24;i+=2) - // printf("re %d => %d\n",i/2,ul_ch[i]); - phy_measurements->n0_subband_power[aarx][rb] = ((k1*(signal_energy_nodc(ul_ch, - 24))*rx_power_correction) + (k2*phy_measurements->n0_subband_power[aarx][rb]))>>11; // 11 and 24 to compensate for repeated signal format - - phy_measurements->n0_subband_power_dB[aarx][rb] = dB_fixed(phy_measurements->n0_subband_power[aarx][rb]); - // printf("eNb %d, aarx %d, rb %d : energy %d (%d dB)\n",eNB_id,aarx,rb,signal_energy_nodc(ul_ch,24), phy_measurements->n0_subband_power_dB[aarx][rb]); - n0_power_tot += phy_measurements->n0_subband_power[aarx][rb]; - } else { - phy_measurements->n0_subband_power[aarx][rb] = 1; - phy_measurements->n0_subband_power_dB[aarx][rb] = -99; - n0_power_tot = 1; + phy_measurements->n0_subband_power[aarx][rb] = signal_energy_nodc(ul_ch,len); + //((k1*(signal_energy_nodc(ul_ch,len))) + // + (k2*phy_measurements->n0_subband_power[aarx][rb])); + + phy_measurements->n0_subband_power_dB[aarx][rb] = dB_fixed(phy_measurements->n0_subband_power[aarx][rb]); + // printf("subframe %d (%d): eNb %d, aarx %d, rb %d len %d: energy %d (%d dB)\n",subframe,offset,eNB_id,aarx,rb,len,signal_energy_nodc(ul_ch,len), + // phy_measurements->n0_subband_power_dB[aarx][rb]); + n0_power_tot += phy_measurements->n0_subband_power[aarx][rb]; } + + phy_measurements->n0_subband_power_tot_dB[rb] = dB_fixed(n0_power_tot); + phy_measurements->n0_subband_power_tot_dBm[rb] = phy_measurements->n0_subband_power_tot_dB[rb] - phy_vars_eNB->rx_total_gain_eNB_dB - dB_fixed(frame_parms->N_RB_UL); + } - - phy_measurements->n0_subband_power_tot_dB[rb] = dB_fixed(n0_power_tot); - phy_measurements->n0_subband_power_tot_dBm[rb] = phy_measurements->n0_subband_power_tot_dB[rb] - phy_vars_eNb->rx_total_gain_eNB_dB - 14; - } } - void lte_eNB_srs_measurements(PHY_VARS_eNB *phy_vars_eNb, unsigned char eNB_id, unsigned char UE_id, diff --git a/openair1/PHY/LTE_TRANSPORT/defs.h b/openair1/PHY/LTE_TRANSPORT/defs.h index a21693fea0..8b23c51079 100644 --- a/openair1/PHY/LTE_TRANSPORT/defs.h +++ b/openair1/PHY/LTE_TRANSPORT/defs.h @@ -576,13 +576,13 @@ typedef struct { /// UL RSSI per receive antenna int32_t UL_rssi[NB_ANTENNAS_RX]; /// PUCCH1a/b power (digital linear) - int32_t Po_PUCCH; + uint32_t Po_PUCCH; /// PUCCH1a/b power (dBm) int32_t Po_PUCCH_dBm; /// PUCCH1 power (digital linear), conditioned on below threshold - int32_t Po_PUCCH1_below; + uint32_t Po_PUCCH1_below; /// PUCCH1 power (digital linear), conditioned on above threshold - int32_t Po_PUCCH1_above; + uint32_t Po_PUCCH1_above; /// Indicator that Po_PUCCH has been updated by PHY int32_t Po_PUCCH_update; /// DL Wideband CQI index (2 TBs) diff --git a/openair1/PHY/LTE_TRANSPORT/print_stats.c b/openair1/PHY/LTE_TRANSPORT/print_stats.c index 53ca875953..ab946fc3da 100644 --- a/openair1/PHY/LTE_TRANSPORT/print_stats.c +++ b/openair1/PHY/LTE_TRANSPORT/print_stats.c @@ -573,11 +573,13 @@ int dump_eNB_stats(PHY_VARS_eNB *phy_vars_eNB, char* buffer, int length) phy_vars_eNB->PHY_measurements_eNB[eNB].n0_power_dB[0], phy_vars_eNB->PHY_measurements_eNB[eNB].n0_power_dB[1]); - len += sprintf(&buffer[len],"[eNB PROC] Subband I0: "); + len += sprintf(&buffer[len],"[eNB PROC] PRB I0 (%X.%X.%X.%X): ", + phy_vars_eNB->rb_mask_ul[0], + phy_vars_eNB->rb_mask_ul[1],phy_vars_eNB->rb_mask_ul[2],phy_vars_eNB->rb_mask_ul[3]); - for (i=0; i<25; i++) - len += sprintf(&buffer[len],"%2d ", - phy_vars_eNB->PHY_measurements_eNB[eNB].n0_subband_power_tot_dB[i]); + for (i=0; ilte_frame_parms.N_RB_UL; i++) + len += sprintf(&buffer[len],"%4d ", + phy_vars_eNB->PHY_measurements_eNB[eNB].n0_subband_power_tot_dBm[i]); len += sprintf(&buffer[len],"\n"); len += sprintf(&buffer[len],"\n[eNB PROC] PERFORMANCE PARAMETERS\n"); @@ -634,11 +636,11 @@ int dump_eNB_stats(PHY_VARS_eNB *phy_vars_eNB, char* buffer, int length) dB_fixed(phy_vars_eNB->lte_eNB_pusch_vars[UE_id]->ulsch_power[1]), phy_vars_eNB->eNB_UE_stats[UE_id].UL_rssi[0], phy_vars_eNB->eNB_UE_stats[UE_id].UL_rssi[1], - dB_fixed(phy_vars_eNB->eNB_UE_stats[UE_id].Po_PUCCH)-phy_vars_eNB->rx_total_gain_eNB_dB, + dB_fixed(phy_vars_eNB->eNB_UE_stats[UE_id].Po_PUCCH/phy_vars_eNB->lte_frame_parms.N_RB_UL)-phy_vars_eNB->rx_total_gain_eNB_dB, phy_vars_eNB->lte_frame_parms.ul_power_control_config_common.p0_NominalPUCCH, - dB_fixed(phy_vars_eNB->eNB_UE_stats[UE_id].Po_PUCCH1_below)-phy_vars_eNB->rx_total_gain_eNB_dB, - dB_fixed(phy_vars_eNB->eNB_UE_stats[UE_id].Po_PUCCH1_above)-phy_vars_eNB->rx_total_gain_eNB_dB, - PUCCH1_THRES+phy_vars_eNB->PHY_measurements_eNB[0].n0_power_tot_dBm, //-dB_fixed(phy_vars_eNB->lte_frame_parms.N_RB_UL), + dB_fixed(phy_vars_eNB->eNB_UE_stats[UE_id].Po_PUCCH1_below/phy_vars_eNB->lte_frame_parms.N_RB_UL)-phy_vars_eNB->rx_total_gain_eNB_dB, + dB_fixed(phy_vars_eNB->eNB_UE_stats[UE_id].Po_PUCCH1_above/phy_vars_eNB->lte_frame_parms.N_RB_UL)-phy_vars_eNB->rx_total_gain_eNB_dB, + PUCCH1_THRES+phy_vars_eNB->PHY_measurements_eNB[0].n0_power_tot_dBm-dB_fixed(phy_vars_eNB->lte_frame_parms.N_RB_UL), phy_vars_eNB->eNB_UE_stats[UE_id].sector); for(i=0; i<8; i++) diff --git a/openair1/PHY/LTE_TRANSPORT/proto.h b/openair1/PHY/LTE_TRANSPORT/proto.h index eb32aab24e..e472e30676 100644 --- a/openair1/PHY/LTE_TRANSPORT/proto.h +++ b/openair1/PHY/LTE_TRANSPORT/proto.h @@ -1634,22 +1634,22 @@ void generate_pucch_emul(PHY_VARS_UE *phy_vars_ue, uint8_t subframe); -int32_t rx_pucch(PHY_VARS_eNB *phy_vars_eNB, - PUCCH_FMT_t fmt, - uint8_t UE_id, - uint16_t n1_pucch, - uint16_t n2_pucch, - uint8_t shortened_format, - uint8_t *payload, - uint8_t subframe, - uint8_t pucch1_thres); +uint32_t rx_pucch(PHY_VARS_eNB *phy_vars_eNB, + PUCCH_FMT_t fmt, + uint8_t UE_id, + uint16_t n1_pucch, + uint16_t n2_pucch, + uint8_t shortened_format, + uint8_t *payload, + uint8_t subframe, + uint8_t pucch1_thres); int32_t rx_pucch_emul(PHY_VARS_eNB *phy_vars_eNB, - uint8_t UE_index, - PUCCH_FMT_t fmt, - uint8_t n1_pucch_sel, - uint8_t *payload, - uint8_t subframe); + uint8_t UE_index, + PUCCH_FMT_t fmt, + uint8_t n1_pucch_sel, + uint8_t *payload, + uint8_t subframe); /*! diff --git a/openair1/PHY/LTE_TRANSPORT/pucch.c b/openair1/PHY/LTE_TRANSPORT/pucch.c index 2ed5694dd1..58d08ac205 100644 --- a/openair1/PHY/LTE_TRANSPORT/pucch.c +++ b/openair1/PHY/LTE_TRANSPORT/pucch.c @@ -430,15 +430,15 @@ void generate_pucch_emul(PHY_VARS_UE *phy_vars_ue, } -int32_t rx_pucch(PHY_VARS_eNB *phy_vars_eNB, - PUCCH_FMT_t fmt, - uint8_t UE_id, - uint16_t n1_pucch, - uint16_t n2_pucch, - uint8_t shortened_format, - uint8_t *payload, - uint8_t subframe, - uint8_t pucch1_thres) +uint32_t rx_pucch(PHY_VARS_eNB *phy_vars_eNB, + PUCCH_FMT_t fmt, + uint8_t UE_id, + uint16_t n1_pucch, + uint16_t n2_pucch, + uint8_t shortened_format, + uint8_t *payload, + uint8_t subframe, + uint8_t pucch1_thres) { @@ -446,11 +446,11 @@ int32_t rx_pucch(PHY_VARS_eNB *phy_vars_eNB, LTE_eNB_COMMON *eNB_common_vars = &phy_vars_eNB->lte_eNB_common_vars; LTE_DL_FRAME_PARMS *frame_parms = &phy_vars_eNB->lte_frame_parms; // PUCCH_CONFIG_DEDICATED *pucch_config_dedicated = &phy_vars_eNB->pucch_config_dedicated[UE_id]; - int8_t sigma2_dB = phy_vars_eNB->PHY_measurements_eNB[0].n0_power_dB[0]; - int32_t *Po_PUCCH = &(phy_vars_eNB->eNB_UE_stats[UE_id].Po_PUCCH); + int8_t sigma2_dB = phy_vars_eNB->PHY_measurements_eNB[0].n0_subband_power_tot_dB[6]; + uint32_t *Po_PUCCH = &(phy_vars_eNB->eNB_UE_stats[UE_id].Po_PUCCH); int32_t *Po_PUCCH_dBm = &(phy_vars_eNB->eNB_UE_stats[UE_id].Po_PUCCH_dBm); - int32_t *Po_PUCCH1_below = &(phy_vars_eNB->eNB_UE_stats[UE_id].Po_PUCCH1_below); - int32_t *Po_PUCCH1_above = &(phy_vars_eNB->eNB_UE_stats[UE_id].Po_PUCCH1_above); + uint32_t *Po_PUCCH1_below = &(phy_vars_eNB->eNB_UE_stats[UE_id].Po_PUCCH1_below); + uint32_t *Po_PUCCH1_above = &(phy_vars_eNB->eNB_UE_stats[UE_id].Po_PUCCH1_above); int32_t *Po_PUCCH_update = &(phy_vars_eNB->eNB_UE_stats[UE_id].Po_PUCCH_update); uint32_t u,v,n,aa; uint32_t z[12*14]; @@ -468,7 +468,7 @@ int32_t rx_pucch(PHY_VARS_eNB *phy_vars_eNB, uint32_t symbol_offset; int16_t stat_ref_re,stat_ref_im,*cfo,chest_re,chest_im; int32_t stat_re=0,stat_im=0; - int32_t stat,stat_max=0; + uint32_t stat,stat_max=0; uint8_t deltaPUCCH_Shift = frame_parms->pucch_config_common.deltaPUCCH_Shift; uint8_t NRB2 = frame_parms->pucch_config_common.nRB_CQI; @@ -478,6 +478,7 @@ int32_t rx_pucch(PHY_VARS_eNB *phy_vars_eNB, uint32_t u1 = (frame_parms->Nid_cell + frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.grouphop[1+(subframe<<1)]) % 30; uint32_t v0=frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.seqhop[subframe<<1]; uint32_t v1=frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.seqhop[1+(subframe<<1)]; + int chL; if (first_call == 1) { for (i=0;i<10;i++) { @@ -508,6 +509,7 @@ int32_t rx_pucch(PHY_VARS_eNB *phy_vars_eNB, } */ + if ((deltaPUCCH_Shift==0) || (deltaPUCCH_Shift>3)) { LOG_E(PHY,"[eNB] rx_pucch: Illegal deltaPUCCH_shift %d (should be 1,2,3)\n",deltaPUCCH_Shift); return(-1); @@ -737,30 +739,35 @@ int32_t rx_pucch(PHY_VARS_eNB *phy_vars_eNB, cfo = (frame_parms->Ncp==0) ? &cfo_pucch_np[14*phase] : &cfo_pucch_ep[12*phase]; for (l=0; l<(nsymb>>1); l++) { - stat_re += ((rxcomp[aa][off]*(int32_t)cfo[l<<1])>>15) - ((rxcomp[aa][1+off]*(int32_t)cfo[1+(l<<1)])>>15); - stat_im += ((rxcomp[aa][off]*(int32_t)cfo[1+(l<<1)])>>15) + ((rxcomp[aa][1+off]*(int32_t)cfo[(l<<1)])>>15); + stat_re += (((rxcomp[aa][off]*(int32_t)cfo[l<<1])>>15) - ((rxcomp[aa][1+off]*(int32_t)cfo[1+(l<<1)])>>15))/nsymb; + stat_im += (((rxcomp[aa][off]*(int32_t)cfo[1+(l<<1)])>>15) + ((rxcomp[aa][1+off]*(int32_t)cfo[(l<<1)])>>15))/nsymb; off+=2; + + #ifdef DEBUG_PUCCH_RX - LOG_D(PHY,"[eNB] PUCCH subframe %d (%d,%d) => (%d,%d) x (%d,%d) : (%d,%d)\n",subframe,l,re, + LOG_D(PHY,"[eNB] PUCCH subframe %d (%d,%d,%d) => (%d,%d) x (%d,%d) : (%d,%d) , stat %d\n",subframe,phase,l,re, rxcomp[aa][off],rxcomp[aa][1+off], cfo[l<<1],cfo[1+(l<<1)], - stat_re,stat_im); + stat_re,stat_im,stat); #endif } for (l2=0,l=(nsymb>>1); l<(nsymb-1); l++,l2++) { - stat_re += ((rxcomp[aa][off]*(int32_t)cfo[l2<<1])>>15) - ((rxcomp[aa][1+off]*(int32_t)cfo[1+(l2<<1)])>>15); - stat_im += ((rxcomp[aa][off]*(int32_t)cfo[1+(l2<<1)])>>15) + ((rxcomp[aa][1+off]*(int32_t)cfo[(l2<<1)])>>15); + stat_re += (((rxcomp[aa][off]*(int32_t)cfo[l2<<1])>>15) - ((rxcomp[aa][1+off]*(int32_t)cfo[1+(l2<<1)])>>15))/nsymb; + stat_im += (((rxcomp[aa][off]*(int32_t)cfo[1+(l2<<1)])>>15) + ((rxcomp[aa][1+off]*(int32_t)cfo[(l2<<1)])>>15))/nsymb; off+=2; + #ifdef DEBUG_PUCCH_RX - LOG_D(PHY,"[eNB] PUCCH subframe %d (%d,%d) => (%d,%d) x (%d,%d) : (%d,%d)\n",subframe,l2,re, + LOG_D(PHY,"[eNB] PUCCH subframe %d (%d,%d,%d) => (%d,%d) x (%d,%d) : (%d,%d), stat %d\n",subframe,phase,l2,re, rxcomp[aa][off],rxcomp[aa][1+off], cfo[l2<<1],cfo[1+(l2<<1)], - stat_re,stat_im); + stat_re,stat_im,stat); #endif + } - stat += (stat_re*stat_re) + (stat_im*stat_im); + stat += ((stat_re*stat_re) + (stat_im*stat_im)); + } //re } // aa @@ -772,16 +779,18 @@ int32_t rx_pucch(PHY_VARS_eNB *phy_vars_eNB, } //phase - stat_max /= (nsymb*12); // normalize to energy per symbol and RE + stat_max *= nsymb; // normalize to energy per symbol + stat_max /= (frame_parms->N_RB_UL*12); // #ifdef DEBUG_PUCCH_RX LOG_D(PHY,"[eNB] PUCCH: stat %d, stat_max %d, phase_max %d\n", stat,stat_max,phase_max); #endif #ifdef DEBUG_PUCCH_RX - LOG_D(PHY,"[eNB] PUCCH fmt0: stat_max : %d, sigma2_dB %d (%d, %d), phase_max : %d\n",dB_fixed(stat_max),sigma2_dB,phy_vars_eNB->PHY_measurements_eNB[0].n0_power_tot_dBm,pucch1_thres,phase_max); + LOG_D(PHY,"[eNB] PUCCH fmt1: stat_max : %d, sigma2_dB %d (%d, %d), phase_max : %d\n",dB_fixed(stat_max),sigma2_dB,phy_vars_eNB->PHY_measurements_eNB[0].n0_subband_power_tot_dBm[6],pucch1_thres,phase_max); #endif phy_vars_eNB->pucch1_stats[UE_id][(subframe<<10)+phy_vars_eNB->pucch1_stats_cnt[UE_id][subframe]] = stat_max; + phy_vars_eNB->pucch1_stats_thres[UE_id][(subframe<<10)+phy_vars_eNB->pucch1_stats_cnt[UE_id][subframe]] = sigma2_dB+pucch1_thres; phy_vars_eNB->pucch1_stats_cnt[UE_id][subframe] = (phy_vars_eNB->pucch1_stats_cnt[UE_id][subframe]+1)&1023; /* @@ -798,13 +807,13 @@ int32_t rx_pucch(PHY_VARS_eNB *phy_vars_eNB, if (sigma2_dB<(dB_fixed(stat_max)-pucch1_thres)) { *payload = 1; *Po_PUCCH1_above = ((*Po_PUCCH1_above<<9) + (stat_max<<9)+1024)>>10; - + // LOG_I(PHY,"[eNB] PUCCH fmt1: stat_max : %d, sigma2_dB %d (%d, %d), phase_max : %d\n",dB_fixed(stat_max),sigma2_dB,phy_vars_eNB->PHY_measurements_eNB[0].n0_power_tot_dBm,pucch1_thres,phase_max); } else { *payload = 0; *Po_PUCCH1_below = ((*Po_PUCCH1_below<<9) + (stat_max<<9)+1024)>>10; } - LOG_D(PHY,"[eNB] PUCCH fmt0: stat_max : %d, sigma2_dB %d (I0 %d dBm, thres %d), Po_PUCCH1_below/above : %d / %d\n",dB_fixed(stat_max),sigma2_dB,phy_vars_eNB->PHY_measurements_eNB[0].n0_power_tot_dBm,pucch1_thres,dB_fixed(*Po_PUCCH1_below),dB_fixed(*Po_PUCCH1_above)); + LOG_D(PHY,"[eNB] PUCCH fmt1: stat_max : %d, sigma2_dB %d (I0 %d dBm, thres %d), Po_PUCCH1_below/above : %d / %d\n",dB_fixed(stat_max),sigma2_dB,phy_vars_eNB->PHY_measurements_eNB[0].n0_subband_power_tot_dBm[6],pucch1_thres,dB_fixed(*Po_PUCCH1_below),dB_fixed(*Po_PUCCH1_above)); *Po_PUCCH_update = 1; } else if ((fmt == pucch_format1a)||(fmt == pucch_format1b)) { @@ -813,7 +822,7 @@ int32_t rx_pucch(PHY_VARS_eNB *phy_vars_eNB, LOG_I(PHY,"Doing PUCCH detection for format 1a/1b\n"); #endif - for (phase=0; phase<7; phase++) { + for (phase=3;phase<4;phase++){ //phase=0; phase<7; phase++) { stat=0; for (aa=0; aanb_antennas_rx; aa++) { @@ -844,6 +853,9 @@ int32_t rx_pucch(PHY_VARS_eNB *phy_vars_eNB, #endif } + + + for (l2=0,l=(nsymb>>1); l<(nsymb-1); l++,l2++) { if ((l2<2) || ((l2>(nsymb>>1) - 3)) ) { // data symbols stat_re += ((rxcomp[aa][off]*(int32_t)cfo[l2<<1])>>15) - ((rxcomp[aa][1+off]*(int32_t)cfo[1+(l2<<1)])>>15); @@ -863,34 +875,36 @@ int32_t rx_pucch(PHY_VARS_eNB *phy_vars_eNB, } - stat += (((stat_re*stat_re)) + ((stat_im*stat_im)) + - ((stat_ref_re*stat_ref_re)) + ((stat_ref_im*stat_ref_im))); #ifdef DEBUG_PUCCH_RX LOG_D(PHY,"aa%d re %d : phase %d : stat %d\n",aa,re,phase,stat); #endif + + stat += ((((stat_re*stat_re)) + ((stat_im*stat_im)) + + ((stat_ref_re*stat_ref_re)) + ((stat_ref_im*stat_ref_im)))/nsymb); + + } //re } // aa #ifdef DEBUG_PUCCH_RX - LOG_I(PHY,"phase %d : stat %d\n",phase,stat); + LOG_I(PHY,"Format 1A: phase %d : stat %d\n",phase,stat); #endif - if (stat>stat_max) { stat_max = stat; phase_max = phase; } } //phase - stat_max/=(nsymb*12); //normalize to energy per symbol and RE -#ifdef DEBUG_PUCCH_RX - LOG_I(PHY,"[eNB] PUCCH fmt1: stat_max : %d, phase_max : %d\n",stat_max,phase_max); -#endif + stat_max/=(12); //normalize to energy per symbol and RE + //#ifdef DEBUG_PUCCH_RX + LOG_D(PHY,"[eNB] PUCCH fmt1a/b: stat_max : %d, phase_max : %d\n",stat_max,phase_max); + //#endif stat_re=0; stat_im=0; LOG_D(PHY,"PUCCH1A : Po_PUCCH before %d dB (%d)\n",dB_fixed(*Po_PUCCH),*Po_PUCCH); - *Po_PUCCH = ((*Po_PUCCH<<9) + (stat_max<<9)+1024)>>10; - *Po_PUCCH_dBm = dB_fixed(*Po_PUCCH) - phy_vars_eNB->rx_total_gain_eNB_dB; + *Po_PUCCH = ((*Po_PUCCH>>1) + ((stat_max)>>1)); + *Po_PUCCH_dBm = dB_fixed(*Po_PUCCH/frame_parms->N_RB_UL) - phy_vars_eNB->rx_total_gain_eNB_dB; *Po_PUCCH_update = 1; LOG_D(PHY,"PUCCH1A : stat_max %d (%d,%d,%d) => Po_PUCCH %d\n", @@ -906,6 +920,8 @@ int32_t rx_pucch(PHY_VARS_eNB *phy_vars_eNB, *Po_PUCCH = ((*Po_PUCCH*1023) + stat_max)>>10; + chL = (nsymb>>1)-4; + for (aa=0; aanb_antennas_rx; aa++) { for (re=0; re<12; re++) { chest_re=0; @@ -915,8 +931,8 @@ int32_t rx_pucch(PHY_VARS_eNB *phy_vars_eNB, // channel estimate for first slot for (l=2; l<(nsymb>>1)-2; l++) { off=(re<<1) + (24*l); - chest_re += ((rxcomp[aa][off]*(int32_t)cfo[l<<1])>>15) - ((rxcomp[aa][1+off]*(int32_t)cfo[1+(l<<1)])>>15); - chest_im += ((rxcomp[aa][off]*(int32_t)cfo[1+(l<<1)])>>15) + ((rxcomp[aa][1+off]*(int32_t)cfo[(l<<1)])>>15); + chest_re += (((rxcomp[aa][off]*(int32_t)cfo[l<<1])>>15) - ((rxcomp[aa][1+off]*(int32_t)cfo[1+(l<<1)])>>15))/chL; + chest_im += (((rxcomp[aa][off]*(int32_t)cfo[1+(l<<1)])>>15) + ((rxcomp[aa][1+off]*(int32_t)cfo[(l<<1)])>>15))/chL; } #ifdef DEBUG_PUCCH_RX @@ -928,8 +944,8 @@ int32_t rx_pucch(PHY_VARS_eNB *phy_vars_eNB, off=(re<<1) + (24*l); tmp_re = ((rxcomp[aa][off]*(int32_t)cfo[l<<1])>>15) - ((rxcomp[aa][1+off]*(int32_t)cfo[1+(l<<1)])>>15); tmp_im = ((rxcomp[aa][off]*(int32_t)cfo[1+(l<<1)])>>15) + ((rxcomp[aa][1+off]*(int32_t)cfo[(l<<1)])>>15); - stat_re += ((tmp_re*chest_re)>>15) + ((tmp_im*chest_im)>>15); - stat_im += ((tmp_re*chest_im)>>15) - ((tmp_im*chest_re)>>15); + stat_re += (((tmp_re*chest_re)>>15) + ((tmp_im*chest_im)>>15))/4; + stat_im += (((tmp_re*chest_im)>>15) - ((tmp_im*chest_re)>>15))/4; off+=2; #ifdef DEBUG_PUCCH_RX LOG_D(PHY,"[eNB] PUCCH subframe %d (%d,%d) => (%d,%d) x (%d,%d) : (%d,%d)\n",subframe,l,re, @@ -943,8 +959,8 @@ int32_t rx_pucch(PHY_VARS_eNB *phy_vars_eNB, off=(re<<1) + (24*l); tmp_re = ((rxcomp[aa][off]*(int32_t)cfo[l<<1])>>15) - ((rxcomp[aa][1+off]*(int32_t)cfo[1+(l<<1)])>>15); tmp_im = ((rxcomp[aa][off]*(int32_t)cfo[1+(l<<1)])>>15) + ((rxcomp[aa][1+off]*(int32_t)cfo[(l<<1)])>>15); - stat_re += ((tmp_re*chest_re)>>15) + ((tmp_im*chest_im)>>15); - stat_im += ((tmp_re*chest_im)>>15) - ((tmp_im*chest_re)>>15); + stat_re += (((tmp_re*chest_re)>>15) + ((tmp_im*chest_im)>>15)/4); + stat_im += (((tmp_re*chest_im)>>15) - ((tmp_im*chest_re)>>15)/4); off+=2; #ifdef DEBUG_PUCCH_RX LOG_D(PHY,"[eNB] PUCCH subframe %d (%d,%d) => (%d,%d) x (%d,%d) : (%d,%d)\n",subframe,l,re, @@ -960,8 +976,8 @@ int32_t rx_pucch(PHY_VARS_eNB *phy_vars_eNB, // channel estimate for second slot for (l=2; l<(nsymb>>1)-2; l++) { off=(re<<1) + (24*l) + (nsymb>>1)*24; - chest_re += ((rxcomp[aa][off]*(int32_t)cfo[l<<1])>>15) - ((rxcomp[aa][1+off]*(int32_t)cfo[1+(l<<1)])>>15); - chest_im += ((rxcomp[aa][off]*(int32_t)cfo[1+(l<<1)])>>15) + ((rxcomp[aa][1+off]*(int32_t)cfo[(l<<1)])>>15); + chest_re += (((rxcomp[aa][off]*(int32_t)cfo[l<<1])>>15) - ((rxcomp[aa][1+off]*(int32_t)cfo[1+(l<<1)])>>15))/chL; + chest_im += (((rxcomp[aa][off]*(int32_t)cfo[1+(l<<1)])>>15) + ((rxcomp[aa][1+off]*(int32_t)cfo[(l<<1)])>>15))/chL; } #ifdef DEBUG_PUCCH_RX @@ -973,8 +989,8 @@ int32_t rx_pucch(PHY_VARS_eNB *phy_vars_eNB, off=(re<<1) + (24*l) + (nsymb>>1)*24; tmp_re = ((rxcomp[aa][off]*(int32_t)cfo[l<<1])>>15) - ((rxcomp[aa][1+off]*(int32_t)cfo[1+(l<<1)])>>15); tmp_im = ((rxcomp[aa][off]*(int32_t)cfo[1+(l<<1)])>>15) + ((rxcomp[aa][1+off]*(int32_t)cfo[(l<<1)])>>15); - stat_re += ((tmp_re*chest_re)>>15) + ((tmp_im*chest_im)>>15); - stat_im += ((tmp_re*chest_im)>>15) - ((tmp_im*chest_re)>>15); + stat_re += (((tmp_re*chest_re)>>15) + ((tmp_im*chest_im)>>15))/4; + stat_im += (((tmp_re*chest_im)>>15) - ((tmp_im*chest_re)>>15))/4; off+=2; #ifdef DEBUG_PUCCH_RX LOG_D(PHY,"[PHY][eNB] PUCCH subframe %d (%d,%d) => (%d,%d) x (%d,%d) : (%d,%d)\n",subframe,l,re, @@ -988,8 +1004,8 @@ int32_t rx_pucch(PHY_VARS_eNB *phy_vars_eNB, off=(re<<1) + (24*l) + (nsymb>>1)*24; tmp_re = ((rxcomp[aa][off]*(int32_t)cfo[l<<1])>>15) - ((rxcomp[aa][1+off]*(int32_t)cfo[1+(l<<1)])>>15); tmp_im = ((rxcomp[aa][off]*(int32_t)cfo[1+(l<<1)])>>15) + ((rxcomp[aa][1+off]*(int32_t)cfo[(l<<1)])>>15); - stat_re += ((tmp_re*chest_re)>>9) + ((tmp_im*chest_im)>>9); - stat_im += ((tmp_re*chest_im)>>9) - ((tmp_im*chest_re)>>9); + stat_re += (((tmp_re*chest_re)>>15) + ((tmp_im*chest_im)>>15))/4; + stat_im += (((tmp_re*chest_im)>>15) - ((tmp_im*chest_re)>>15))/4; off+=2; #ifdef DEBUG_PUCCH_RX LOG_D(PHY,"[PHY][eNB] PUCCH subframe %d (%d,%d) => (%d,%d) x (%d,%d) : (%d,%d)\n",subframe,l,re, @@ -1007,20 +1023,27 @@ int32_t rx_pucch(PHY_VARS_eNB *phy_vars_eNB, } // aa #ifdef DEBUG_PUCCH_RX - LOG_D(PHY,"PUCCH 1a/b: subframe %d : stat %d,%d (pos %d)\n",subframe,stat_re,stat_im, + LOG_I(PHY,"PUCCH 1a/b: subframe %d : stat %d,%d (pos %d)\n",subframe,stat_re,stat_im, (subframe<<10) + (phy_vars_eNB->pucch1ab_stats_cnt[UE_id][subframe])); #endif - - ((int16_t*)&phy_vars_eNB->pucch1ab_stats[UE_id][(subframe<<10) + (phy_vars_eNB->pucch1_stats_cnt[UE_id][subframe])])[0] = stat_re; - ((int16_t*)&phy_vars_eNB->pucch1ab_stats[UE_id][(subframe<<10) + (phy_vars_eNB->pucch1_stats_cnt[UE_id][subframe])])[1] = stat_im; - phy_vars_eNB->pucch1ab_stats_cnt[UE_id][subframe] = (phy_vars_eNB->pucch1ab_stats_cnt[UE_id][subframe]+1)&1023; + ((int16_t*)&phy_vars_eNB->pucch1ab_stats[UE_id][(subframe<<10) + (phy_vars_eNB->pucch1_stats_cnt[UE_id][subframe])])[0] = (int16_t)(stat_re); + ((int16_t*)&phy_vars_eNB->pucch1ab_stats[UE_id][(subframe<<10) + (phy_vars_eNB->pucch1_stats_cnt[UE_id][subframe])])[1] = (int16_t)(stat_im); + phy_vars_eNB->pucch1ab_stats_cnt[UE_id][subframe] = (phy_vars_eNB->pucch1ab_stats_cnt[UE_id][subframe]+1)&1023; + + + *payload = (stat_re<0) ? 1 : 0; if (fmt==pucch_format1b) *(1+payload) = (stat_im<0) ? 1 : 0; } else { // insufficient energy on PUCCH so NAK *payload = 0; + ((int16_t*)&phy_vars_eNB->pucch1ab_stats[UE_id][(subframe<<10) + (phy_vars_eNB->pucch1_stats_cnt[UE_id][subframe])])[0] = (int16_t)(stat_re); + ((int16_t*)&phy_vars_eNB->pucch1ab_stats[UE_id][(subframe<<10) + (phy_vars_eNB->pucch1_stats_cnt[UE_id][subframe])])[1] = (int16_t)(stat_im); + phy_vars_eNB->pucch1ab_stats_cnt[UE_id][subframe] = (phy_vars_eNB->pucch1ab_stats_cnt[UE_id][subframe]+1)&1023; + + *payload = (stat_re<0) ? 1 : 0; if (fmt==pucch_format1b) *(1+payload) = 0; diff --git a/openair1/PHY/LTE_TRANSPORT/ulsch_demodulation.c b/openair1/PHY/LTE_TRANSPORT/ulsch_demodulation.c index 606b2692d5..f2e4dea58a 100644 --- a/openair1/PHY/LTE_TRANSPORT/ulsch_demodulation.c +++ b/openair1/PHY/LTE_TRANSPORT/ulsch_demodulation.c @@ -1657,8 +1657,15 @@ void rx_ulsch(PHY_VARS_eNB *phy_vars_eNB, } } else { for (i=0; inb_antennas_rx; i++) { + /* eNB_pusch_vars->ulsch_power[i] = signal_energy_nodc(eNB_pusch_vars->drs_ch_estimates[eNB_id][i], ulsch[UE_id]->harq_processes[harq_pid]->nb_rb*12)*rx_power_correction; + + */ + + eNB_pusch_vars->ulsch_power[i] = signal_energy_nodc(eNB_pusch_vars->drs_ch_estimates[eNB_id][i], + ulsch[UE_id]->harq_processes[harq_pid]->nb_rb*12); + #ifdef LOCALIZATION eNB_pusch_vars->subcarrier_power = (int32_t *)malloc(ulsch[UE_id]->harq_processes[harq_pid]->nb_rb*12*sizeof(int32_t)); eNB_pusch_vars->active_subcarrier = subcarrier_energy(eNB_pusch_vars->drs_ch_estimates[eNB_id][i], diff --git a/openair1/PHY/TOOLS/lte_phy_scope.c b/openair1/PHY/TOOLS/lte_phy_scope.c index 49cafa19b5..e9820d0604 100644 --- a/openair1/PHY/TOOLS/lte_phy_scope.c +++ b/openair1/PHY/TOOLS/lte_phy_scope.c @@ -119,7 +119,7 @@ FD_lte_phy_scope_enb *create_lte_phy_scope_enb( void ) fl_set_xyplot_xgrid( fdui->pusch_llr,FL_GRID_MAJOR); // I/Q PUCCH comp (format 1) - fdui->pucch_comp1 = fl_add_xyplot( FL_POINTS_XYPLOT, 540, 480, 240, 100, "PUCCH I/Q of MF Output" ); + fdui->pucch_comp1 = fl_add_xyplot( FL_POINTS_XYPLOT, 540, 480, 240, 100, "PUCCH1 Energy (SR)" ); fl_set_object_boxtype( fdui->pucch_comp1, FL_EMBOSSED_BOX ); fl_set_object_color( fdui->pucch_comp1, FL_BLACK, FL_YELLOW ); fl_set_object_lcolor( fdui->pucch_comp1, FL_WHITE ); // Label color @@ -171,11 +171,12 @@ void phy_scope_eNB(FD_lte_phy_scope_enb *form, int16_t *pusch_llr; int16_t *pusch_comp; int32_t *pucch1_comp; + int32_t *pucch1_thres; int16_t *pucch1ab_comp; float Re,Im,ymax; float *llr, *bit; float I[nsymb_ce*2], Q[nsymb_ce*2]; - float I_pucch[10240],Q_pucch[10240],A_pucch[10240],B_pucch[10240]; + float I_pucch[10240],Q_pucch[10240],A_pucch[10240],B_pucch[10240],C_pucch[10240]; float rxsig_t_dB[nb_antennas_rx][FRAME_LENGTH_COMPLEX_SAMPLES]; float chest_t_abs[nb_antennas_rx][frame_parms->ofdm_symbol_size]; float *chest_f_abs; @@ -206,6 +207,7 @@ void phy_scope_eNB(FD_lte_phy_scope_enb *form, pusch_llr = (int16_t*) phy_vars_enb->lte_eNB_pusch_vars[UE_id]->llr; pusch_comp = (int16_t*) phy_vars_enb->lte_eNB_pusch_vars[UE_id]->rxdataF_comp[eNB_id][0]; pucch1_comp = (int32_t*) phy_vars_enb->pucch1_stats[UE_id]; + pucch1_thres = (int32_t*) phy_vars_enb->pucch1_stats_thres[UE_id]; pucch1ab_comp = (int16_t*) phy_vars_enb->pucch1ab_stats[UE_id]; // Received signal in time domain of receive antenna 0 @@ -341,12 +343,13 @@ void phy_scope_eNB(FD_lte_phy_scope_enb *form, Q_pucch[ind] = pucch1ab_comp[2*ind+1]; A_pucch[ind] = 10*log10(pucch1_comp[ind]); B_pucch[ind] = ind; + C_pucch[ind] = (float)pucch1_thres[ind]; } fl_set_xyplot_data(form->pucch_comp,I_pucch,Q_pucch,10240,"","",""); fl_set_xyplot_data(form->pucch_comp1,B_pucch,A_pucch,1024,"","",""); - fl_set_xyplot_xbounds(form->pucch_comp,-200,200); - fl_set_xyplot_ybounds(form->pucch_comp,-100,100); - fl_set_xyplot_ybounds(form->pucch_comp1,10,40); + fl_add_xyplot_overlay(form->pucch_comp1,1,B_pucch,C_pucch,1024,FL_RED); + // fl_set_xyplot_ybounds(form->pucch_comp,-100,100); + fl_set_xyplot_ybounds(form->pucch_comp1,20,80); } diff --git a/openair1/PHY/defs.h b/openair1/PHY/defs.h index 398861cabf..c0b61806a6 100755 --- a/openair1/PHY/defs.h +++ b/openair1/PHY/defs.h @@ -313,6 +313,8 @@ typedef struct PHY_VARS_eNB_s { struct PhysicalConfigDedicated *physicalConfigDedicated[NUMBER_OF_UE_MAX]; + uint32_t rb_mask_ul[4]; + /// Information regarding TM5 MU_MIMO_mode mu_mimo_mode[NUMBER_OF_UE_MAX]; @@ -378,6 +380,7 @@ typedef struct PHY_VARS_eNB_s { int32_t pucch1_stats_cnt[NUMBER_OF_UE_MAX][10]; int32_t pucch1_stats[NUMBER_OF_UE_MAX][10*1024]; + int32_t pucch1_stats_thres[NUMBER_OF_UE_MAX][10*1024]; int32_t pucch1ab_stats_cnt[NUMBER_OF_UE_MAX][10]; int32_t pucch1ab_stats[NUMBER_OF_UE_MAX][10*1024]; diff --git a/openair1/PHY/impl_defs_top.h b/openair1/PHY/impl_defs_top.h index c84b7d3ece..80530c932f 100755 --- a/openair1/PHY/impl_defs_top.h +++ b/openair1/PHY/impl_defs_top.h @@ -257,7 +257,7 @@ #define AMP_OVER_2 (AMP>>1) /// Threshold for PUCCH Format 1 detection -#define PUCCH1_THRES 10 +#define PUCCH1_THRES 4 /// Threshold for PUCCH Format 1a/1b detection #define PUCCH1a_THRES 4 diff --git a/openair1/SCHED/phy_procedures_lte_eNb.c b/openair1/SCHED/phy_procedures_lte_eNb.c index 165f2fbac6..b9cb618ea0 100755 --- a/openair1/SCHED/phy_procedures_lte_eNb.c +++ b/openair1/SCHED/phy_procedures_lte_eNb.c @@ -104,7 +104,6 @@ extern uint8_t smbv_frame_cnt; #ifdef DIAG_PHY extern int rx_sig_fifo; #endif -static unsigned char I0_clear = 1; uint8_t is_SR_subframe(PHY_VARS_eNB *phy_vars_eNB,uint8_t UE_id,uint8_t sched_subframe) { @@ -476,6 +475,7 @@ void phy_procedures_eNB_S_RX(unsigned char sched_subframe,PHY_VARS_eNB *phy_vars if (abstraction_flag == 0) { lte_eNB_I0_measurements(phy_vars_eNB, + subframe, 0, phy_vars_eNB->first_run_I0_measurements); } @@ -489,8 +489,6 @@ void phy_procedures_eNB_S_RX(unsigned char sched_subframe,PHY_VARS_eNB *phy_vars #endif - if (I0_clear == 1) - I0_clear = 0; } @@ -3247,6 +3245,11 @@ void phy_procedures_eNB_RX(const unsigned char sched_subframe,PHY_VARS_eNB *phy_ phy_vars_eNB->lte_frame_parms.samples_per_tti); #endif */ + phy_vars_eNB->rb_mask_ul[0]=0; + phy_vars_eNB->rb_mask_ul[1]=0; + phy_vars_eNB->rb_mask_ul[2]=0; + phy_vars_eNB->rb_mask_ul[3]=0; + if (abstraction_flag == 0) { remove_7_5_kHz(phy_vars_eNB,subframe<<1); remove_7_5_kHz(phy_vars_eNB,(subframe<<1)+1); @@ -3395,6 +3398,12 @@ void phy_procedures_eNB_RX(const unsigned char sched_subframe,PHY_VARS_eNB *phy_ pusch_active = 1; round = phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->round; + for (int rb=0; + rb<=phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->nb_rb; + rb++) { + int rb2 = rb+phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->first_rb; + phy_vars_eNB->rb_mask_ul[rb2>>5] |= (1<<(rb2&31)); + } #ifdef DEBUG_PHY_PROC LOG_D(PHY,"[eNB %d][PUSCH %d] frame %d subframe %d Scheduling PUSCH/ULSCH Reception for rnti %x (UE_id %d)\n", phy_vars_eNB->Mod_id,harq_pid, @@ -3715,13 +3724,19 @@ void phy_procedures_eNB_RX(const unsigned char sched_subframe,PHY_VARS_eNB *phy_ for (j=0; jlte_frame_parms.nb_antennas_rx; j++) //this is the RSSI per RB phy_vars_eNB->eNB_UE_stats[i].UL_rssi[j] = + dB_fixed(phy_vars_eNB->lte_eNB_pusch_vars[i]->ulsch_power[j]* (phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->nb_rb*12)/ phy_vars_eNB->lte_frame_parms.ofdm_symbol_size) - phy_vars_eNB->rx_total_gain_eNB_dB - hundred_times_log10_NPRB[phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->nb_rb-1]/100 - get_hundred_times_delta_IF_eNB(phy_vars_eNB,i,harq_pid, 0)/100; - + + /* + dB_fixed(phy_vars_eNB->lte_eNB_pusch_vars[i]->ulsch_power[j]*phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->nb_rb) - + phy_vars_eNB->rx_total_gain_eNB_dB - + hundred_times_log10_NPRB[phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->nb_rb-1]/100 - + get_hundred_times_delta_IF_eNB(phy_vars_eNB,i,harq_pid, 0)/100;*/ phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->phich_active = 1; phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->phich_ACK = 1; phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->round = 0; @@ -3915,6 +3930,34 @@ void phy_procedures_eNB_RX(const unsigned char sched_subframe,PHY_VARS_eNB *phy_ } else { // otherwise we have some PUCCH detection to do + // Null out PUCCH PRBs for noise measurement + switch(phy_vars_eNB->lte_frame_parms.N_RB_UL) { + case 6: + phy_vars_eNB->rb_mask_ul[0] |= (0x1 | (1<<5)); //position 5 + break; + case 15: + phy_vars_eNB->rb_mask_ul[0] |= (0x1 | (1<<14)); // position 14 + break; + case 25: + phy_vars_eNB->rb_mask_ul[0] |= (0x1 | (1<<24)); // position 24 + break; + case 50: + phy_vars_eNB->rb_mask_ul[0] |= 0x1; + phy_vars_eNB->rb_mask_ul[1] |= (1<<17); // position 49 (49-32) + break; + case 75: + phy_vars_eNB->rb_mask_ul[0] |= 0x1; + phy_vars_eNB->rb_mask_ul[2] |= (1<<10); // position 74 (74-64) + break; + case 100: + phy_vars_eNB->rb_mask_ul[0] |= 0x1; + phy_vars_eNB->rb_mask_ul[3] |= (1<<3); // position 99 (99-96) + break; + default: + LOG_E(PHY,"Unknown number for N_RB_UL %d\n",phy_vars_eNB->lte_frame_parms.N_RB_UL); + break; + } + if (do_SR == 1) { phy_vars_eNB->eNB_UE_stats[i].sr_total++; @@ -3924,7 +3967,7 @@ void phy_procedures_eNB_RX(const unsigned char sched_subframe,PHY_VARS_eNB *phy_ i, phy_vars_eNB->scheduling_request_config[i].sr_PUCCH_ResourceIndex, 0, // n2_pucch - 1, // shortened format + 0, // shortened format, should be use_srs flag, later &SR_payload, subframe, PUCCH1_THRES); @@ -4336,13 +4379,15 @@ void phy_procedures_eNB_RX(const unsigned char sched_subframe,PHY_VARS_eNB *phy_ } // loop i=0 ... NUMBER_OF_UE_MAX-1 - if (pusch_active == 0) { + // if (pusch_active == 0) { if (abstraction_flag == 0) { // LOG_D(PHY,"[eNB] Frame %d, subframe %d Doing I0_measurements\n", // (((subframe)==9)?-1:0) + phy_vars_eNB->proc[sched_subframe].frame_tx,subframe); lte_eNB_I0_measurements(phy_vars_eNB, + subframe, 0, phy_vars_eNB->first_run_I0_measurements); + phy_vars_eNB->first_run_I0_measurements = 0; } #ifdef PHY_ABSTRACTION @@ -4354,9 +4399,7 @@ void phy_procedures_eNB_RX(const unsigned char sched_subframe,PHY_VARS_eNB *phy_ #endif - if (I0_clear == 1) - I0_clear = 0; - } + //} #ifdef EMOS phy_procedures_emos_eNB_RX(subframe,phy_vars_eNB); diff --git a/openair1/SIMULATION/LTE_PHY/pucchsim.c b/openair1/SIMULATION/LTE_PHY/pucchsim.c index 919bec144d..cd29554b90 100644 --- a/openair1/SIMULATION/LTE_PHY/pucchsim.c +++ b/openair1/SIMULATION/LTE_PHY/pucchsim.c @@ -248,7 +248,7 @@ int main(int argc, char **argv) break; default: - msg("Unsupported channel model!\n"); + printf("Unsupported channel model!\n"); exit(-1); } @@ -260,13 +260,13 @@ int main(int argc, char **argv) case 's': snr0 = atof(optarg); - msg("Setting SNR0 to %f\n",snr0); + printf("Setting SNR0 to %f\n",snr0); break; case 'S': snr1 = atof(optarg); snr1set=1; - msg("Setting SNR1 to %f\n",snr1); + printf("Setting SNR1 to %f\n",snr1); break; case 'p': @@ -289,7 +289,7 @@ int main(int argc, char **argv) if ((transmission_mode!=1) && (transmission_mode!=2) && (transmission_mode!=6)) { - msg("Unsupported transmission mode %d\n",transmission_mode); + printf("Unsupported transmission mode %d\n",transmission_mode); exit(-1); } @@ -299,7 +299,7 @@ int main(int argc, char **argv) n_tx=atoi(optarg); if ((n_tx==0) || (n_tx>2)) { - msg("Unsupported number of tx antennas %d\n",n_tx); + printf("Unsupported number of tx antennas %d\n",n_tx); exit(-1); } @@ -309,7 +309,7 @@ int main(int argc, char **argv) n_rx=atoi(optarg); if ((n_rx==0) || (n_rx>2)) { - msg("Unsupported number of rx antennas %d\n",n_rx); + printf("Unsupported number of rx antennas %d\n",n_rx); exit(-1); } @@ -414,7 +414,7 @@ int main(int argc, char **argv) - msg("[SIM] Using SCM/101\n"); + printf("[SIM] Using SCM/101\n"); UE2eNB = new_channel_desc_scm(PHY_vars_eNB->lte_frame_parms.nb_antennas_tx, PHY_vars_UE->lte_frame_parms.nb_antennas_rx, channel_model, @@ -425,7 +425,7 @@ int main(int argc, char **argv) if (UE2eNB==NULL) { - msg("Problem generating channel model. Exiting.\n"); + printf("Problem generating channel model. Exiting.\n"); exit(-1); } @@ -453,7 +453,7 @@ int main(int argc, char **argv) PHY_vars_UE->lte_frame_parms.pucch_config_common.nRB_CQI = 0; PHY_vars_UE->lte_frame_parms.pucch_config_common.nCS_AN = 0; - pucch_payload = 1; + pucch_payload = 0; generate_pucch(PHY_vars_UE->lte_ue_common_vars.txdataF, frame_parms, @@ -596,9 +596,7 @@ int main(int argc, char **argv) } } - lte_eNB_I0_measurements(PHY_vars_eNB, - 0, - 1); + for (i=0; i<2*nsymb*OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES; i++) { for (aa=0; aalte_frame_parms.nb_antennas_rx; aa++) { @@ -646,6 +644,10 @@ int main(int argc, char **argv) // if (sig == 1) // printf("*"); + lte_eNB_I0_measurements(PHY_vars_eNB, + subframe, + 0, + 1); PHY_vars_eNB->PHY_measurements_eNB[0].n0_power_tot_dB = N0;//(int8_t)(sigma2_dB-10*log10(PHY_vars_eNB->lte_frame_parms.ofdm_symbol_size/(12*NB_RB))); stat = rx_pucch(PHY_vars_eNB, pucch_format, diff --git a/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c b/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c index 52e0f60d65..3dea35f053 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c @@ -1166,7 +1166,7 @@ schedule_ue_spec( // this is the normalized RX power eNB_UE_stats = mac_xface->get_eNB_UE_stats(module_idP,CC_id,rnti); normalized_rx_power = eNB_UE_stats->Po_PUCCH_dBm; - target_rx_power = mac_xface->get_target_pucch_rx_power(module_idP,CC_id) + 10; + target_rx_power = mac_xface->get_target_pucch_rx_power(module_idP,CC_id) + 20; // this assumes accumulated tpc // make sure that we are only sending a tpc update once a frame, otherwise the control loop will freak out @@ -1178,6 +1178,7 @@ schedule_ue_spec( UE_list->UE_template[CC_id][UE_id].pucch_tpc_tx_frame=frameP; UE_list->UE_template[CC_id][UE_id].pucch_tpc_tx_subframe=subframeP; + if (normalized_rx_power>(target_rx_power+1)) { tpc = 0; //-1 tpc_accumulated--; @@ -1187,9 +1188,11 @@ schedule_ue_spec( } else { tpc = 1; //0 } - LOG_D(MAC,"[eNB %d] DLSCH scheduler: frame %d, subframe %d, harq_pid %d, tpc %d, accumulated %d, normalized/target rx power %d/%d\n", + /* + LOG_I(MAC,"[eNB %d] DLSCH scheduler: frame %d, subframe %d, harq_pid %d, tpc %d, accumulated %d, normalized/target rx power %d/%d\n", module_idP,frameP, subframeP,harq_pid,tpc, - tpc_accumulated,normalized_rx_power,target_rx_power); + tpc_accumulated,normalized_rx_power,target_rx_power);*/ + } // Po_PUCCH has been updated else { tpc = 1; //0 @@ -1561,7 +1564,7 @@ fill_DLSCH_dci( eNB->common_channels[CC_id].bcch_active = 0; LOG_D(MAC,"[eNB %d] CC_id %d Frame %d subframeP %d: BCCH active\n", module_idP, CC_id, frameP, subframeP); // randomize frequency allocation for SI - first_rb = 10;//(unsigned char)(taus()%(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL-4)); + first_rb = 0;//10;//(unsigned char)(taus()%(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL-4)); /* Where is this from, should be removed!!!! diff --git a/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c b/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c index 1018c6e7d8..10c728f2a7 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c @@ -750,6 +750,7 @@ void schedule_ulsch_rnti(module_id_t module_idP, LOG_T(MAC,"[eNB %d] Frame %d, subframeP %d, UE %d CC %d : got harq pid %d round %d (nCCE %d, rnti %x,mode %s)\n", module_idP,frameP,subframeP,UE_id,CC_id, harq_pid, round,nCCE[CC_id],rnti,mode_string[eNB_UE_stats->mode]); +#undef EXMIMO_IOT #ifndef EXMIMO_IOT if (((UE_is_to_be_scheduled(module_idP,CC_id,UE_id)>0)) || (round>0) || ((frameP%10)==0)) diff --git a/targets/ARCH/COMMON/common_lib.c b/targets/ARCH/COMMON/common_lib.c index 8b91a74b49..f0bf1f6847 100644 --- a/targets/ARCH/COMMON/common_lib.c +++ b/targets/ARCH/COMMON/common_lib.c @@ -45,20 +45,23 @@ int openair0_device_init(openair0_device *device, openair0_config_t *openair0_cf #ifdef ETHERNET device->type=ETH_IF; device->func_type = BBU_FUNC; - openair0_dev_init_eth(device, openair0_cfg); printf(" openair0_dev_init_eth ...\n"); + return(openair0_dev_init_eth(device, openair0_cfg)); + #elif EXMIMO device->type=EXMIMO_IF; - openair0_dev_init_exmimo(device, openair0_cfg); printf("openair0_dev_init_exmimo...\n"); + return(openair0_dev_init_exmimo(device, openair0_cfg)); #elif OAI_USRP device->type=USRP_IF; - openair0_dev_init_usrp(device, openair0_cfg); printf("openair0_dev_init_usrp ...\n"); + return(openair0_dev_init_usrp(device, openair0_cfg)); + #elif OAI_BLADERF device->type=BLADERF_IF; - openair0_dev_init_bladerf(device, openair0_cfg); printf(" openair0_dev_init_bladerf ...\n"); + return(openair0_dev_init_bladerf(device, openair0_cfg)); + #endif } diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf index 2f11e42ba9..2974ce8551 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf @@ -28,7 +28,7 @@ eNBs = tdd_config_s = 0; prefix_type = "NORMAL"; eutra_band = 7; - downlink_frequency = 2680000000L; + downlink_frequency = 2660000000L; uplink_frequency_offset = -120000000; Nid_cell = 0; N_RB_DL = 25; @@ -143,10 +143,10 @@ eNBs = NETWORK_INTERFACES : { ENB_INTERFACE_NAME_FOR_S1_MME = "eth0"; - ENB_IPV4_ADDRESS_FOR_S1_MME = "192.168.12.216/24"; + ENB_IPV4_ADDRESS_FOR_S1_MME = "192.168.12.213/24"; ENB_INTERFACE_NAME_FOR_S1U = "eth0"; - ENB_IPV4_ADDRESS_FOR_S1U = "192.168.12.216/24"; + ENB_IPV4_ADDRESS_FOR_S1U = "192.168.12.213/24"; ENB_PORT_FOR_S1U = 2152; # Spec 2152 }; diff --git a/targets/RT/USER/lte-softmodem.c b/targets/RT/USER/lte-softmodem.c index b96a7ae529..623a83da2a 100644 --- a/targets/RT/USER/lte-softmodem.c +++ b/targets/RT/USER/lte-softmodem.c @@ -1631,6 +1631,8 @@ static void* eNB_thread( void* arg ) pthread_mutex_unlock(&sync_mutex); + printf( "got sync (eNB_thread)\n" ); + int frame = 0; #ifndef EXMIMO @@ -2893,12 +2895,12 @@ int main( int argc, char **argv ) bw = 0.96e6; #ifndef EXMIMO openair0_cfg[card].sample_rate=1.92e6; - openair0_cfg[card].samples_per_packet = 256; + openair0_cfg[card].samples_per_packet = 640; openair0_cfg[card].samples_per_frame = 19200; openair0_cfg[card].tx_bw = 1.5e6; openair0_cfg[card].rx_bw = 1.5e6; openair0_cfg[card].tx_forward_nsamps = 40; - openair0_cfg[card].tx_delay = 8; + openair0_cfg[card].tx_delay = 6; #endif } @@ -2992,10 +2994,14 @@ openair0_cfg[card].num_rb_dl=frame_parms[0]->N_RB_DL; openair0.func_type = BBU_FUNC; openair0_cfg[0].log_level = glog_level; - if ((mode!=loop_through_memory) && - (openair0_device_init(&openair0, &openair0_cfg[0]) <0)) { - printf("Exiting, cannot initialize device\n"); - exit(-1); + if (mode!=loop_through_memory){ + int ret; + ret= openair0_device_init(&openair0, &openair0_cfg[0]); + printf("openair0_device_init returns %d\n",ret); + if (ret<0) { + printf("Exiting, cannot initialize device\n"); + exit(-1); + } } else if (mode==loop_through_memory) { } @@ -3279,6 +3285,16 @@ openair0_cfg[card].num_rb_dl=frame_parms[0]->N_RB_DL; #endif printf("UE threads created\n"); +#ifdef USE_MME + + while (start_UE == 0) { + sleep(1); + } + +#endif + + + } else { if (multi_thread>0) { init_eNB_proc(); @@ -3306,13 +3322,7 @@ openair0_cfg[card].num_rb_dl=frame_parms[0]->N_RB_DL; // Sleep to allow all threads to setup sleep(1); -#ifdef USE_MME - while (start_UE == 0) { - sleep(1); - } - -#endif #ifndef EXMIMO @@ -3325,6 +3335,7 @@ openair0_cfg[card].num_rb_dl=frame_parms[0]->N_RB_DL; #endif + printf("Sending sync to all threads\n"); pthread_mutex_lock(&sync_mutex); sync_var=0; From 2120582005d28eefbb0aad198a770649b3c869a3 Mon Sep 17 00:00:00 2001 From: Navid Nikaein Date: Wed, 21 Oct 2015 15:35:18 +0200 Subject: [PATCH 005/263] fix the flag for the usrp device write operation (trx_write) --- targets/RT/USER/eNB_transport_IQ.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/targets/RT/USER/eNB_transport_IQ.c b/targets/RT/USER/eNB_transport_IQ.c index 07533ff59c..fffe93ab5f 100644 --- a/targets/RT/USER/eNB_transport_IQ.c +++ b/targets/RT/USER/eNB_transport_IQ.c @@ -724,7 +724,7 @@ void *rrh_eNB_tx_thread(void *arg) { tx_eNB, spp_rf, dev->devs->openair0_cfg.tx_num_channels, - 0)<0){ + 1)<0){ perror("RRH eNB : USRP write"); } VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE_RF, 0 ); From 6957f9e5ee91787000c0345215c09a827b7b2e12 Mon Sep 17 00:00:00 2001 From: Raymond Knopp Date: Thu, 22 Oct 2015 02:45:28 -0700 Subject: [PATCH 006/263] corrected HARQ ACK/NAK handling for TDD, in openair1/SCHED/phy_procedures_lte_common.c. --- openair1/SCHED/phy_procedures_lte_common.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openair1/SCHED/phy_procedures_lte_common.c b/openair1/SCHED/phy_procedures_lte_common.c index ce659a60f8..c51bd82d8a 100755 --- a/openair1/SCHED/phy_procedures_lte_common.c +++ b/openair1/SCHED/phy_procedures_lte_common.c @@ -405,8 +405,8 @@ uint8_t get_ack(LTE_DL_FRAME_PARMS *frame_parms, if (harq_ack[0].send_harq_status == 1) o_ACK[1] = harq_ack[0].ack; - } else if (harq_ack[8].send_harq_status == 1) - o_ACK[0] = harq_ack[8].ack; + } else if (harq_ack[0].send_harq_status == 1) + o_ACK[0] = harq_ack[0].ack; status = harq_ack[9].send_harq_status + (harq_ack[0].send_harq_status<<1); //printf("Subframe 4, TDD config 3: harq_ack[9] = %d,harq_ack[0] = %d\n",harq_ack[9].ack,harq_ack[0].ack); From 2fe218e91a59d154343a3c07634a460a92ebce1b Mon Sep 17 00:00:00 2001 From: Raymond Knopp Date: Wed, 18 Nov 2015 14:18:58 -0800 Subject: [PATCH 007/263] Moved CCE allocations from PHY to MAC and updated MAC interfaces for BCCH/RA/UE-SPEC scheduling. --- openair1/PHY/CODING/lte_rate_matching.c | 9 +- openair1/PHY/LTE_TRANSPORT/dci.c | 18 +- openair1/PHY/LTE_TRANSPORT/defs.h | 6 +- openair1/PHY/LTE_TRANSPORT/dlsch_coding.c | 5 +- openair1/PHY/LTE_TRANSPORT/dlsch_decoding.c | 5 +- openair1/PHY/LTE_TRANSPORT/proto.h | 19 +- openair1/SCHED/defs.h | 1 - openair1/SCHED/phy_procedures_lte_eNb.c | 225 ++----- openair1/SIMULATION/LTE_PHY/dlsim.c | 32 +- openair2/LAYER2/MAC/defs.h | 13 +- openair2/LAYER2/MAC/eNB_scheduler.c | 188 +++--- openair2/LAYER2/MAC/eNB_scheduler_RA.c | 560 +++++++++++---- openair2/LAYER2/MAC/eNB_scheduler_bch.c | 150 ++++- openair2/LAYER2/MAC/eNB_scheduler_dlsch.c | 635 +----------------- .../LAYER2/MAC/eNB_scheduler_primitives.c | 205 ++++++ openair2/LAYER2/MAC/eNB_scheduler_ulsch.c | 55 +- openair2/LAYER2/MAC/main.c | 2 +- openair2/LAYER2/MAC/pre_processor.c | 13 +- openair2/LAYER2/MAC/proto.h | 48 +- openair2/PHY_INTERFACE/defs.h | 3 +- targets/SIMU/USER/init_lte.c | 20 +- 21 files changed, 1083 insertions(+), 1129 deletions(-) diff --git a/openair1/PHY/CODING/lte_rate_matching.c b/openair1/PHY/CODING/lte_rate_matching.c index 69697fc2e0..96663bd8a6 100644 --- a/openair1/PHY/CODING/lte_rate_matching.c +++ b/openair1/PHY/CODING/lte_rate_matching.c @@ -36,6 +36,7 @@ #include #endif #include "PHY/defs.h" +#include "assertions.h" //#define cmin(a,b) ((a)<(b) ? (a) : (b)) @@ -515,16 +516,14 @@ uint32_t lte_rate_matching_turbo(uint32_t RTC, // if (rvidx==3) // for (cnt=0;cnt=(3*RTC<<5),"Exiting, RM condition (Ncb %d, Nir/C %d, Nsoft %d, Kw %d\n",Ncb,Nir/C,Nsoft,3*(RTC<<5)); + Gp = G/Nl/Qm; GpmodC = Gp%C; #ifdef RM_DEBUG - printf("lte_rate_matching_turbo: Kw %d, rvidx %d, G %d, Qm %d, Nl%d, r %d\n",3*(RTC<<5),rvidx, G, Qm,Nl,r); + printf("lte_rate_matching_turbo: Ncb %d, Kw %d, Nir/C %d, rvidx %d, G %d, Qm %d, Nl%d, r %d\n",Ncb,3*(RTC<<5),Nir/C,rvidx, G, Qm,Nl,r); #endif if (r < (C-(GpmodC))) diff --git a/openair1/PHY/LTE_TRANSPORT/dci.c b/openair1/PHY/LTE_TRANSPORT/dci.c index 2fd89c8f64..f126d0e2ea 100644 --- a/openair1/PHY/LTE_TRANSPORT/dci.c +++ b/openair1/PHY/LTE_TRANSPORT/dci.c @@ -2108,14 +2108,14 @@ uint8_t generate_dci_top(uint8_t num_ue_spec_dci, if (dci_alloc[i].L == (uint8_t)L) { #ifdef DEBUG_DCI_ENCODING - LOG_I(PHY,"Generating common DCI %d/%d (nCCE %d) of length %d, aggregation %d (%x)\n",i,num_common_dci,dci_alloc[i].nCCE,dci_alloc[i].dci_length,1<=0) { + if (dci_alloc[i].firstCCE>=0) { e_ptr = generate_dci0(dci_alloc[i].dci_pdu, - e+(72*dci_alloc[i].nCCE), + e+(72*dci_alloc[i].firstCCE), dci_alloc[i].dci_length, dci_alloc[i].L, dci_alloc[i].rnti); @@ -2133,9 +2133,9 @@ uint8_t generate_dci_top(uint8_t num_ue_spec_dci, dump_dci(frame_parms,&dci_alloc[i]); #endif - if (dci_alloc[i].nCCE >= 0) { + if (dci_alloc[i].firstCCE >= 0) { e_ptr = generate_dci0(dci_alloc[i].dci_pdu, - e+(72*dci_alloc[i].nCCE), + e+(72*dci_alloc[i].firstCCE), dci_alloc[i].dci_length, dci_alloc[i].L, dci_alloc[i].rnti); @@ -2537,11 +2537,13 @@ uint16_t get_nquad(uint8_t num_pdcch_symbols,LTE_DL_FRAME_PARMS *frame_parms,uin return(Nreg - 4 - (3*Ngroup_PHICH)); } -uint16_t get_nCCE_max(uint8_t Mod_id,uint8_t CC_id) +uint16_t get_nCCE_mac(uint8_t Mod_id,uint8_t CC_id,int num_pdcch_symbols,int subframe) { // check for eNB only ! - return(get_nCCE(3,&PHY_vars_eNB_g[Mod_id][CC_id]->lte_frame_parms,1)); // 5, 15,21 + return(get_nCCE(num_pdcch_symbols, + &PHY_vars_eNB_g[Mod_id][CC_id]->lte_frame_parms, + get_mi(&PHY_vars_eNB_g[Mod_id][CC_id]->lte_frame_parms,subframe))); } void dci_decoding_procedure0(LTE_UE_PDCCH **lte_ue_pdcch_vars, @@ -2691,7 +2693,7 @@ void dci_decoding_procedure0(LTE_UE_PDCCH **lte_ue_pdcch_vars, dci_alloc[*dci_cnt].dci_length = sizeof_bits; dci_alloc[*dci_cnt].rnti = crc; dci_alloc[*dci_cnt].L = L; - dci_alloc[*dci_cnt].nCCE = CCEind; + dci_alloc[*dci_cnt].firstCCE = CCEind; if (sizeof_bytes<=4) { dci_alloc[*dci_cnt].dci_pdu[3] = dci_decoded_output[0]; diff --git a/openair1/PHY/LTE_TRANSPORT/defs.h b/openair1/PHY/LTE_TRANSPORT/defs.h index 8b23c51079..f25e199e9d 100644 --- a/openair1/PHY/LTE_TRANSPORT/defs.h +++ b/openair1/PHY/LTE_TRANSPORT/defs.h @@ -266,6 +266,8 @@ typedef struct { uint8_t Mdlharq; /// MIMO transmission mode indicator for this sub-frame (for definition see 36-212 V8.6 2009-03, p.17) uint8_t Kmimo; + /// Nsoft parameter related to UE Category + uint32_t Nsoft; /// amplitude of PDSCH (compared to RS) in symbols without pilots int16_t sqrt_rho_a; /// amplitude of PDSCH (compared to RS) in symbols containing pilots @@ -693,6 +695,8 @@ typedef struct { uint8_t Mdlharq; /// MIMO transmission mode indicator for this sub-frame (for definition see 36-212 V8.6 2009-03, p.17) uint8_t Kmimo; + /// Nsoft parameter related to UE Category + uint32_t Nsoft; /// Maximum number of Turbo iterations uint8_t max_turbo_iterations; /// accumulated tx power adjustment for PUCCH @@ -737,7 +741,7 @@ typedef struct { /// Aggregation level uint8_t L; /// Position of first CCE of the dci - int nCCE; + int firstCCE; /// flag to indicate that this is a RA response boolean_t ra_flag; /// rnti diff --git a/openair1/PHY/LTE_TRANSPORT/dlsch_coding.c b/openair1/PHY/LTE_TRANSPORT/dlsch_coding.c index 83066480b4..a2f33f0fb2 100644 --- a/openair1/PHY/LTE_TRANSPORT/dlsch_coding.c +++ b/openair1/PHY/LTE_TRANSPORT/dlsch_coding.c @@ -117,7 +117,7 @@ void free_eNB_dlsch(LTE_eNB_DLSCH_t *dlsch) } -LTE_eNB_DLSCH_t *new_eNB_dlsch(unsigned char Kmimo,unsigned char Mdlharq,unsigned char N_RB_DL, uint8_t abstraction_flag) +LTE_eNB_DLSCH_t *new_eNB_dlsch(unsigned char Kmimo,unsigned char Mdlharq,uint32_t Nsoft,unsigned char N_RB_DL, uint8_t abstraction_flag) { LTE_eNB_DLSCH_t *dlsch; @@ -148,6 +148,7 @@ LTE_eNB_DLSCH_t *new_eNB_dlsch(unsigned char Kmimo,unsigned char Mdlharq,unsigne bzero(dlsch,sizeof(LTE_eNB_DLSCH_t)); dlsch->Kmimo = Kmimo; dlsch->Mdlharq = Mdlharq; + dlsch->Nsoft = Nsoft; for (i=0; i<10; i++) dlsch->harq_ids[i] = Mdlharq; @@ -395,7 +396,7 @@ int dlsch_encoding(unsigned char *a, dlsch->harq_processes[harq_pid]->w[r], dlsch->harq_processes[harq_pid]->e+r_offset, dlsch->harq_processes[harq_pid]->C, // C - NSOFT, // Nsoft, + dlsch->Nsoft, // Nsoft, dlsch->Mdlharq, dlsch->Kmimo, dlsch->harq_processes[harq_pid]->rvidx, diff --git a/openair1/PHY/LTE_TRANSPORT/dlsch_decoding.c b/openair1/PHY/LTE_TRANSPORT/dlsch_decoding.c index 6ab784aa18..efcd868338 100644 --- a/openair1/PHY/LTE_TRANSPORT/dlsch_decoding.c +++ b/openair1/PHY/LTE_TRANSPORT/dlsch_decoding.c @@ -81,7 +81,7 @@ void free_ue_dlsch(LTE_UE_DLSCH_t *dlsch) } } -LTE_UE_DLSCH_t *new_ue_dlsch(uint8_t Kmimo,uint8_t Mdlharq,uint8_t max_turbo_iterations,uint8_t N_RB_DL, uint8_t abstraction_flag) +LTE_UE_DLSCH_t *new_ue_dlsch(uint8_t Kmimo,uint8_t Mdlharq,uint32_t Nsoft,uint8_t max_turbo_iterations,uint8_t N_RB_DL, uint8_t abstraction_flag) { LTE_UE_DLSCH_t *dlsch; @@ -113,6 +113,7 @@ LTE_UE_DLSCH_t *new_ue_dlsch(uint8_t Kmimo,uint8_t Mdlharq,uint8_t max_turbo_ite memset(dlsch,0,sizeof(LTE_UE_DLSCH_t)); dlsch->Kmimo = Kmimo; dlsch->Mdlharq = Mdlharq; + dlsch->Nsoft = Nsoft; dlsch->max_turbo_iterations = max_turbo_iterations; for (i=0; iC, - NSOFT, + dlsch->Nsoft, dlsch->Mdlharq, dlsch->Kmimo, harq_process->rvidx, diff --git a/openair1/PHY/LTE_TRANSPORT/proto.h b/openair1/PHY/LTE_TRANSPORT/proto.h index e472e30676..8506891e6d 100644 --- a/openair1/PHY/LTE_TRANSPORT/proto.h +++ b/openair1/PHY/LTE_TRANSPORT/proto.h @@ -56,15 +56,16 @@ void free_eNB_dlsch(LTE_eNB_DLSCH_t *dlsch); void clean_eNb_dlsch(LTE_eNB_DLSCH_t *dlsch, uint8_t abstraction_flag); -/** \fn new_eNB_dlsch(uint8_t Kmimo,uint8_t Mdlharq,uint8_t abstraction_flag) +/** \fn new_eNB_dlsch(uint8_t Kmimo,uint8_t Mdlharq,uint32_t Nsoft,uint8_t abstraction_flag) \brief This function allocates structures for a particular DLSCH at eNB @returns Pointer to DLSCH to be removed @param Kmimo Kmimo factor from 36-212/36-213 @param Mdlharq Maximum number of HARQ rounds (36-212/36-213) + @param Nsoft Soft-LLR buffer size from UE-Category @params N_RB_DL total number of resource blocks (determine the operating BW) @param abstraction_flag Flag to indicate abstracted interface */ -LTE_eNB_DLSCH_t *new_eNB_dlsch(uint8_t Kmimo,uint8_t Mdlharq,uint8_t N_RB_DL, uint8_t abstraction_flag); +LTE_eNB_DLSCH_t *new_eNB_dlsch(uint8_t Kmimo,uint8_t Mdlharq,uint32_t Nsoft,uint8_t N_RB_DL, uint8_t abstraction_flag); /** \fn free_ue_dlsch(LTE_UE_DLSCH_t *dlsch) \brief This function frees memory allocated for a particular DLSCH at UE @@ -72,8 +73,16 @@ LTE_eNB_DLSCH_t *new_eNB_dlsch(uint8_t Kmimo,uint8_t Mdlharq,uint8_t N_RB_DL, ui */ void free_ue_dlsch(LTE_UE_DLSCH_t *dlsch); -LTE_UE_DLSCH_t *new_ue_dlsch(uint8_t Kmimo,uint8_t Mdlharq,uint8_t max_turbo_iterations,uint8_t N_RB_DL, uint8_t abstraction_flag); - +/** \fn new_ue_dlsch(uint8_t Kmimo,uint8_t Mdlharq,uint32_t Nsoft,uint8_t abstraction_flag) + \brief This function allocates structures for a particular DLSCH at eNB + @returns Pointer to DLSCH to be removed + @param Kmimo Kmimo factor from 36-212/36-213 + @param Mdlharq Maximum number of HARQ rounds (36-212/36-213) + @param Nsoft Soft-LLR buffer size from UE-Category + @params N_RB_DL total number of resource blocks (determine the operating BW) + @param abstraction_flag Flag to indicate abstracted interface +*/ +LTE_UE_DLSCH_t *new_ue_dlsch(uint8_t Kmimo,uint8_t Mdlharq,uint32_t Nsoft,uint8_t max_turbo_iterations,uint8_t N_RB_DL, uint8_t abstraction_flag); void clean_eNb_ulsch(LTE_eNB_ULSCH_t *ulsch, uint8_t abstraction_flag); @@ -1581,7 +1590,7 @@ uint16_t get_nquad(uint8_t num_pdcch_symbols,LTE_DL_FRAME_PARMS *frame_parms,uin uint8_t get_mi(LTE_DL_FRAME_PARMS *frame,uint8_t subframe); -uint16_t get_nCCE_max(uint8_t Mod_id,uint8_t CC_id); +uint16_t get_nCCE_mac(uint8_t Mod_id,uint8_t CC_id,int num_pdcch_symbols,int subframe); uint8_t get_num_pdcch_symbols(uint8_t num_dci,DCI_ALLOC_t *dci_alloc,LTE_DL_FRAME_PARMS *frame_parms,uint8_t subframe); diff --git a/openair1/SCHED/defs.h b/openair1/SCHED/defs.h index bebe476dcd..bcf2c213c2 100644 --- a/openair1/SCHED/defs.h +++ b/openair1/SCHED/defs.h @@ -399,7 +399,6 @@ uint32_t pdcch_alloc2ul_frame(LTE_DL_FRAME_PARMS *frame_parms,uint32_t frame, ui uint16_t get_Np(uint8_t N_RB_DL,uint8_t nCCE,uint8_t plus1); -int get_nCCE_offset(unsigned char L, int nCCE, int common_dci, unsigned short rnti, unsigned char subframe); int8_t find_ue(uint16_t rnti, PHY_VARS_eNB *phy_vars_eNB); diff --git a/openair1/SCHED/phy_procedures_lte_eNb.c b/openair1/SCHED/phy_procedures_lte_eNb.c index b9cb618ea0..cb78f429b5 100755 --- a/openair1/SCHED/phy_procedures_lte_eNb.c +++ b/openair1/SCHED/phy_procedures_lte_eNb.c @@ -296,100 +296,6 @@ int get_ue_active_harq_pid(const uint8_t Mod_id,const uint8_t CC_id,const uint16 } -int CCE_table[800]; - -void init_nCCE_table(void) -{ - memset(CCE_table,0,800*sizeof(int)); -} - - -int get_nCCE_offset(const unsigned char L, const int nCCE, const int common_dci, const unsigned short rnti, const unsigned char subframe) -{ - - int search_space_free,m,nb_candidates = 0,l,i; - unsigned int Yk; - - /* - printf("CCE Allocation: "); - for (i=0;i=0 ; m--) { - search_space_free = 1; - for (l=0; lPHY_measurements_eNB[0].n0_power_tot_dBm; @@ -1811,15 +1717,18 @@ void phy_procedures_eNB_TX(unsigned char sched_subframe,PHY_VARS_eNB *phy_vars_e phy_vars_eNB->dlsch_eNB[i][0]->subframe_tx[subframe] = 0; } - init_nCCE_table(); + // init_nCCE_table(); - num_pdcch_symbols = get_num_pdcch_symbols(DCI_pdu->Num_common_dci + DCI_pdu->Num_ue_spec_dci, - DCI_pdu->dci_alloc, - &phy_vars_eNB->lte_frame_parms, - subframe); + num_pdcch_symbols = DCI_pdu->num_pdcch_symbols; + /*get_num_pdcch_symbols(DCI_pdu->Num_common_dci + DCI_pdu->Num_ue_spec_dci, + DCI_pdu->dci_alloc, + &phy_vars_eNB->lte_frame_parms, + subframe);*/ + /* DCI_pdu->nCCE = get_nCCE(num_pdcch_symbols, &phy_vars_eNB->lte_frame_parms, - get_mi(&phy_vars_eNB->lte_frame_parms,subframe)); + get_mi(&phy_vars_eNB->lte_frame_parms,subframe));*/ + LOG_D(PHY,"num_pdcch_symbols %"PRIu8", nCCE %u (dci commond %"PRIu8", dci uespec %"PRIu8"\n",num_pdcch_symbols,DCI_pdu->nCCE, DCI_pdu->Num_common_dci,DCI_pdu->Num_ue_spec_dci); @@ -1835,6 +1744,7 @@ void phy_procedures_eNB_TX(unsigned char sched_subframe,PHY_VARS_eNB *phy_vars_e #endif for (i=0; iNum_common_dci + DCI_pdu->Num_ue_spec_dci ; i++) { + LOG_D(PHY,"[eNB] Subframe %d: DCI %d/%d : rnti %x, CCEind %d\n",subframe,i,DCI_pdu->Num_common_dci+DCI_pdu->Num_ue_spec_dci,DCI_pdu->dci_alloc[i].rnti,DCI_pdu->dci_alloc[i].firstCCE); #ifdef DEBUG_PHY_PROC if (DCI_pdu->dci_alloc[i].rnti != SI_RNTI) { @@ -1862,28 +1772,21 @@ void phy_procedures_eNB_TX(unsigned char sched_subframe,PHY_VARS_eNB *phy_vars_e phy_vars_eNB->eNB_UE_stats[0].DL_pmi_single); - int result = get_nCCE_offset(1<dci_alloc[i].L, DCI_pdu->nCCE, 1, SI_RNTI, subframe); - phy_vars_eNB->dlsch_eNB_SI->nCCE[subframe] = result; - - if (result == -1) { - // FIXME what happens to phy_vars_eNB->dlsch_eNB_SI->nCCE[subframe]? - LOG_E(PHY,"[eNB %"PRIu8"] Frame %d subframe %d : No available CCE resources for common DCI (SI)!!!\n",phy_vars_eNB->Mod_id,phy_vars_eNB->proc[sched_subframe].frame_tx,subframe); - } else { - LOG_T(PHY,"[eNB %"PRIu8"] Frame %d subframe %d : CCE resource for common DCI (SI) => %"PRIu8"/%u\n",phy_vars_eNB->Mod_id,phy_vars_eNB->proc[sched_subframe].frame_tx,subframe, - phy_vars_eNB->dlsch_eNB_SI->nCCE[subframe],DCI_pdu->nCCE); + phy_vars_eNB->dlsch_eNB_SI->nCCE[subframe] = DCI_pdu->dci_alloc[i].firstCCE; + LOG_T(PHY,"[eNB %"PRIu8"] Frame %d subframe %d : CCE resource for common DCI (SI) => %"PRIu8"/%u\n",phy_vars_eNB->Mod_id,phy_vars_eNB->proc[sched_subframe].frame_tx,subframe, + phy_vars_eNB->dlsch_eNB_SI->nCCE[subframe],DCI_pdu->nCCE); + #if defined(SMBV) && !defined(EXMIMO) - // configure SI DCI - if (smbv_is_config_frame(phy_vars_eNB->proc[sched_subframe].frame_tx) && (smbv_frame_cnt < 4)) { - msg("[SMBV] Frame %3d, SI in SF %d DCI %"PRIu32"\n",phy_vars_eNB->proc[sched_subframe].frame_tx,subframe,i); - smbv_configure_common_dci(smbv_fname,(smbv_frame_cnt*10) + (subframe), "SI", &DCI_pdu->dci_alloc[i], i); - } - -#endif + // configure SI DCI + if (smbv_is_config_frame(phy_vars_eNB->proc[sched_subframe].frame_tx) && (smbv_frame_cnt < 4)) { + msg("[SMBV] Frame %3d, SI in SF %d DCI %"PRIu32"\n",phy_vars_eNB->proc[sched_subframe].frame_tx,subframe,i); + smbv_configure_common_dci(smbv_fname,(smbv_frame_cnt*10) + (subframe), "SI", &DCI_pdu->dci_alloc[i], i); } - - DCI_pdu->dci_alloc[i].nCCE = phy_vars_eNB->dlsch_eNB_SI->nCCE[subframe]; + +#endif + } else if (DCI_pdu->dci_alloc[i].ra_flag == 1) { #ifdef DEBUG_PHY_PROC @@ -1904,28 +1807,20 @@ void phy_procedures_eNB_TX(unsigned char sched_subframe,PHY_VARS_eNB *phy_vars_e // mac_xface->macphy_exit("Transmitted RAR, exiting\n"); - int result = get_nCCE_offset(1<dci_alloc[i].L, DCI_pdu->nCCE, 1, DCI_pdu->dci_alloc[i].rnti, subframe); - phy_vars_eNB->dlsch_eNB_ra->nCCE[subframe] = result; - if (result == -1) { - // FIXME what happens to phy_vars_eNB->dlsch_eNB_ra->nCCE[subframe]? - LOG_E(PHY,"[eNB %"PRIu8"] Frame %d subframe %d : No available CCE resources for common DCI (RA) !!!\n",phy_vars_eNB->Mod_id,phy_vars_eNB->proc[sched_subframe].frame_tx,subframe); - } else { - LOG_D(PHY,"[eNB %"PRIu8"] Frame %d subframe %d : CCE resource for common DCI (RA) => %"PRIu8"/%u\n",phy_vars_eNB->Mod_id,phy_vars_eNB->proc[sched_subframe].frame_tx,subframe, - phy_vars_eNB->dlsch_eNB_ra->nCCE[subframe],DCI_pdu->nCCE); + phy_vars_eNB->dlsch_eNB_ra->nCCE[subframe] = DCI_pdu->dci_alloc[i].firstCCE; + + LOG_D(PHY,"[eNB %"PRIu8"] Frame %d subframe %d : CCE resource for common DCI (RA) => %"PRIu8"/%u\n",phy_vars_eNB->Mod_id,phy_vars_eNB->proc[sched_subframe].frame_tx,subframe, + phy_vars_eNB->dlsch_eNB_ra->nCCE[subframe],DCI_pdu->nCCE); #if defined(SMBV) && !defined(EXMIMO) - // configure RA DCI - if (smbv_is_config_frame(phy_vars_eNB->proc[sched_subframe].frame_tx) && (smbv_frame_cnt < 4)) { - msg("[SMBV] Frame %3d, RA in SF %d DCI %"PRIu32"\n",phy_vars_eNB->proc[sched_subframe].frame_tx,subframe,i); - smbv_configure_common_dci(smbv_fname,(smbv_frame_cnt*10) + (subframe), "RA", &DCI_pdu->dci_alloc[i], i); - } - -#endif - + // configure RA DCI + if (smbv_is_config_frame(phy_vars_eNB->proc[sched_subframe].frame_tx) && (smbv_frame_cnt < 4)) { + msg("[SMBV] Frame %3d, RA in SF %d DCI %"PRIu32"\n",phy_vars_eNB->proc[sched_subframe].frame_tx,subframe,i); + smbv_configure_common_dci(smbv_fname,(smbv_frame_cnt*10) + (subframe), "RA", &DCI_pdu->dci_alloc[i], i); } - DCI_pdu->dci_alloc[i].nCCE = phy_vars_eNB->dlsch_eNB_ra->nCCE[subframe]; +#endif } @@ -1966,30 +1861,22 @@ void phy_procedures_eNB_TX(unsigned char sched_subframe,PHY_VARS_eNB *phy_vars_e LOG_D(PHY,"[eNB %"PRIu8"][PDSCH %"PRIx16"/%"PRIu8"] Frame %d subframe %d: Generated dlsch params\n", phy_vars_eNB->Mod_id,DCI_pdu->dci_alloc[i].rnti,phy_vars_eNB->dlsch_eNB[(uint8_t)UE_id][0]->current_harq_pid,phy_vars_eNB->proc[sched_subframe].frame_tx,subframe); - int result = get_nCCE_offset(1<dci_alloc[i].L, DCI_pdu->nCCE, 0, DCI_pdu->dci_alloc[i].rnti, subframe); - phy_vars_eNB->dlsch_eNB[(uint8_t)UE_id][0]->nCCE[subframe] = result; - if (result == -1) { - // FIXME what happens to phy_vars_eNB->dlsch_eNB[(uint8_t)UE_id][0]->nCCE[subframe]? - LOG_E(PHY,"[eNB %"PRIu8"] Frame %d subframe %d : No available CCE resources for UE spec DCI (PDSCH %"PRIx16") !!!\n", - phy_vars_eNB->Mod_id,phy_vars_eNB->proc[sched_subframe].frame_tx,subframe,DCI_pdu->dci_alloc[i].rnti); - } else { - LOG_D(PHY,"[eNB %"PRIu8"] Frame %d subframe %d : CCE resource for ue DCI (PDSCH %"PRIx16") => %"PRIu8"/%u\n",phy_vars_eNB->Mod_id,phy_vars_eNB->proc[sched_subframe].frame_tx,subframe, - DCI_pdu->dci_alloc[i].rnti,phy_vars_eNB->dlsch_eNB[(uint8_t)UE_id][0]->nCCE[subframe],DCI_pdu->nCCE); + phy_vars_eNB->dlsch_eNB[(uint8_t)UE_id][0]->nCCE[subframe] = DCI_pdu->dci_alloc[i].firstCCE; + + LOG_D(PHY,"[eNB %"PRIu8"] Frame %d subframe %d : CCE resource for ue DCI (PDSCH %"PRIx16") => %"PRIu8"/%u\n",phy_vars_eNB->Mod_id,phy_vars_eNB->proc[sched_subframe].frame_tx,subframe, + DCI_pdu->dci_alloc[i].rnti,phy_vars_eNB->dlsch_eNB[(uint8_t)UE_id][0]->nCCE[subframe],DCI_pdu->nCCE); #if defined(SMBV) && !defined(EXMIMO) - DCI_pdu->dci_alloc[i].nCCE = phy_vars_eNB->dlsch_eNB[(uint8_t)UE_id][0]->nCCE[subframe]; - - // configure UE-spec DCI - if (smbv_is_config_frame(phy_vars_eNB->proc[sched_subframe].frame_tx) && (smbv_frame_cnt < 4)) { - msg("[SMBV] Frame %3d, PDSCH in SF %d DCI %"PRIu32"\n",phy_vars_eNB->proc[sched_subframe].frame_tx,subframe,i); - smbv_configure_ue_spec_dci(smbv_fname,(smbv_frame_cnt*10) + (subframe), UE_id+1, &DCI_pdu->dci_alloc[i], i); - } + + // configure UE-spec DCI + if (smbv_is_config_frame(phy_vars_eNB->proc[sched_subframe].frame_tx) && (smbv_frame_cnt < 4)) { + msg("[SMBV] Frame %3d, PDSCH in SF %d DCI %"PRIu32"\n",phy_vars_eNB->proc[sched_subframe].frame_tx,subframe,i); + smbv_configure_ue_spec_dci(smbv_fname,(smbv_frame_cnt*10) + (subframe), UE_id+1, &DCI_pdu->dci_alloc[i], i); + } #endif - } - DCI_pdu->dci_alloc[i].nCCE = phy_vars_eNB->dlsch_eNB[(uint8_t)UE_id][0]->nCCE[subframe]; #ifdef DEBUG_PHY_PROC //if (phy_vars_eNB->proc[sched_subframe].frame_tx%100 == 0) LOG_D(PHY,"[eNB %"PRIu8"][DCI][PDSCH %"PRIx16"] Frame %d subframe %d UE_id %"PRId8" Generated DCI format %d, aggregation %d\n", @@ -2067,29 +1954,21 @@ void phy_procedures_eNB_TX(unsigned char sched_subframe,PHY_VARS_eNB *phy_vars_e CBA_RNTI, 0); // do_srs - if ((DCI_pdu->dci_alloc[i].nCCE=get_nCCE_offset(1<dci_alloc[i].L, - DCI_pdu->nCCE, - 0, - DCI_pdu->dci_alloc[i].rnti, - subframe)) == -1) { - LOG_E(PHY,"[eNB %"PRIu8"] Frame %d subframe %d : No available CCE resources (%u) for UE spec DCI (PUSCH %"PRIx16") !!!\n", - phy_vars_eNB->Mod_id,phy_vars_eNB->proc[sched_subframe].frame_tx,subframe,DCI_pdu->nCCE,DCI_pdu->dci_alloc[i].rnti); - } else { - LOG_T(PHY,"[eNB %"PRIu8"] Frame %d subframe %d : CCE resources for UE spec DCI (PUSCH %"PRIx16") => %d/%u\n", - phy_vars_eNB->Mod_id,phy_vars_eNB->proc[sched_subframe].frame_tx,subframe,DCI_pdu->dci_alloc[i].rnti, - DCI_pdu->dci_alloc[i].nCCE,DCI_pdu->nCCE); - + LOG_T(PHY,"[eNB %"PRIu8"] Frame %d subframe %d : CCE resources for UE spec DCI (PUSCH %"PRIx16") => %d/%u\n", + phy_vars_eNB->Mod_id,phy_vars_eNB->proc[sched_subframe].frame_tx,subframe,DCI_pdu->dci_alloc[i].rnti, + DCI_pdu->dci_alloc[i].firstCCE,DCI_pdu->nCCE); + #if defined(SMBV) && !defined(EXMIMO) // configure UE-spec DCI for UL Grant - if (smbv_is_config_frame(phy_vars_eNB->proc[sched_subframe].frame_tx) && (smbv_frame_cnt < 4)) { - msg("[SMBV] Frame %3d, SF %d UL DCI %"PRIu32"\n",phy_vars_eNB->proc[sched_subframe].frame_tx,subframe,i); - smbv_configure_ue_spec_dci(smbv_fname,(smbv_frame_cnt*10) + (subframe), UE_id+1, &DCI_pdu->dci_alloc[i], i); - } - + if (smbv_is_config_frame(phy_vars_eNB->proc[sched_subframe].frame_tx) && (smbv_frame_cnt < 4)) { + msg("[SMBV] Frame %3d, SF %d UL DCI %"PRIu32"\n",phy_vars_eNB->proc[sched_subframe].frame_tx,subframe,i); + smbv_configure_ue_spec_dci(smbv_fname,(smbv_frame_cnt*10) + (subframe), UE_id+1, &DCI_pdu->dci_alloc[i], i); + } + #endif - } + #ifdef DEBUG_PHY_PROC LOG_D(PHY,"[eNB %"PRIu8"][PUSCH %"PRIu8"] frame %d subframe %d Setting subframe_scheduling_flag for UE %"PRIu32" harq_pid %"PRIu8" (ul subframe %"PRIu8")\n", @@ -2120,13 +1999,13 @@ void phy_procedures_eNB_TX(unsigned char sched_subframe,PHY_VARS_eNB *phy_vars_e } if (abstraction_flag == 0) { -#ifdef DEBUG_PHY_PROC + //#ifdef DEBUG_PHY_PROC if (DCI_pdu->Num_ue_spec_dci+DCI_pdu->Num_common_dci > 0) LOG_D(PHY,"[eNB %"PRIu8"] Frame %d, subframe %d: Calling generate_dci_top (pdcch) (common %"PRIu8",ue_spec %"PRIu8")\n",phy_vars_eNB->Mod_id,phy_vars_eNB->proc[sched_subframe].frame_tx, subframe, DCI_pdu->Num_common_dci,DCI_pdu->Num_ue_spec_dci); -#endif + //#endif // for (sect_id=0;sect_idNum_ue_spec_dci, diff --git a/openair1/SIMULATION/LTE_PHY/dlsim.c b/openair1/SIMULATION/LTE_PHY/dlsim.c index 28e7bc8216..8f5c3aeb31 100644 --- a/openair1/SIMULATION/LTE_PHY/dlsim.c +++ b/openair1/SIMULATION/LTE_PHY/dlsim.c @@ -347,6 +347,8 @@ int main(int argc, char **argv) LTE_DL_UE_HARQ_t *dlsch0_ue_harq; LTE_DL_eNB_HARQ_t *dlsch0_eNB_harq; uint8_t Kmimo; + uint8_t ue_category=4; + uint32_t Nsoft; FILE *proc_fd = NULL; char buf[64]; @@ -378,7 +380,7 @@ int main(int argc, char **argv) num_layers = 1; perfect_ce = 0; - while ((c = getopt (argc, argv, "ahdpZDe:m:n:o:s:f:t:c:g:r:F:x:y:z:AM:N:I:i:O:R:S:C:T:b:u:v:w:B:PLl:Y")) != -1) { + while ((c = getopt (argc, argv, "ahdpZDe:m:n:o:s:f:t:c:g:r:F:x:y:z:AM:N:I:i:O:R:S:C:T:b:u:U:v:w:B:PLl:Y")) != -1) { switch (c) { case 'a': awgn_flag = 1; @@ -522,7 +524,6 @@ int main(int argc, char **argv) case 'N': channel_model=AWGN; break; - default: msg("Unsupported channel model!\n"); exit(-1); @@ -530,6 +531,10 @@ int main(int argc, char **argv) break; + case 'U': + ue_category = atoi(optarg); + break; + case 'x': transmission_mode=atoi(optarg); @@ -981,10 +986,27 @@ int main(int argc, char **argv) else Kmimo=1; + switch (ue_category) { + case 1: + Nsoft = 250368; + break; + case 2: + case 3: + Nsoft = 1237248; + break; + case 4: + Nsoft = 1827072; + break; + default: + printf("Unsupported UE category %d\n",ue_category); + exit(-1); + break; + } + for (k=0; kdlsch_eNB[k][i] = new_eNB_dlsch(Kmimo,8,N_RB_DL,0); + PHY_vars_eNB->dlsch_eNB[k][i] = new_eNB_dlsch(Kmimo,8,Nsoft,N_RB_DL,0); if (!PHY_vars_eNB->dlsch_eNB[k][i]) { printf("Can't get eNB dlsch structures\n"); @@ -996,7 +1018,7 @@ int main(int argc, char **argv) } for (i=0; i<2; i++) { - PHY_vars_UE->dlsch_ue[0][i] = new_ue_dlsch(Kmimo,8,MAX_TURBO_ITERATIONS,N_RB_DL,0); + PHY_vars_UE->dlsch_ue[0][i] = new_ue_dlsch(Kmimo,8,Nsoft,MAX_TURBO_ITERATIONS,N_RB_DL,0); if (!PHY_vars_UE->dlsch_ue[0][i]) { printf("Can't get ue dlsch structures\n"); @@ -1007,7 +1029,7 @@ int main(int argc, char **argv) } // structure for SIC at UE - PHY_vars_UE->dlsch_eNB[0] = new_eNB_dlsch(Kmimo,8,N_RB_DL,0); + PHY_vars_UE->dlsch_eNB[0] = new_eNB_dlsch(Kmimo,8,Nsoft,N_RB_DL,0); if (DLSCH_alloc_pdu2_1E[0].tpmi == 5) { diff --git a/openair2/LAYER2/MAC/defs.h b/openair2/LAYER2/MAC/defs.h index a0a43b6d79..d92a143348 100644 --- a/openair2/LAYER2/MAC/defs.h +++ b/openair2/LAYER2/MAC/defs.h @@ -251,7 +251,8 @@ typedef struct { typedef struct { uint8_t Num_ue_spec_dci ; uint8_t Num_common_dci ; - unsigned int nCCE; + uint32_t nCCE; + uint32_t num_pdcch_symbols; DCI_ALLOC_t dci_alloc[NUM_DCI_MAX] ; } DCI_PDU; /*! \brief CCCH payload */ @@ -765,8 +766,6 @@ typedef struct { uint8_t Msg3_subframe; /// Flag to indicate the eNB should generate Msg4 upon reception of SDU from RRC. This is triggered by first ULSCH reception at eNB for new user. uint8_t generate_Msg4; - /// Flag to indicate the eNB should generate the DCI for Msg4, after getting the SDU from RRC. - uint8_t generate_Msg4_dci; /// Flag to indicate that eNB is waiting for ACK that UE has received Msg3. uint8_t wait_ack_Msg4; /// UE RNTI allocated during RAR @@ -835,8 +834,8 @@ typedef struct { /// Outgoing CCCH pdu for PHY CCCH_PDU CCCH_pdu; RA_TEMPLATE RA_template[NB_RA_PROC_MAX]; - /// BCCH active flag - uint8_t bcch_active; + /// VRB map for common channels + uint8_t vrb_map[100]; /// MBSFN SubframeConfig struct MBSFN_SubframeConfig *mbsfn_SubframeConfig[8]; /// number of subframe allocation pattern available for MBSFN sync area @@ -883,9 +882,11 @@ typedef struct { /// Common cell resources COMMON_channels_t common_channels[MAX_NUM_CCs]; UE_list_t UE_list; + ///subband bitmap configuration SBMAP_CONF sbmap_conf; - + /// CCE table used to build DCI scheduling information + int CCE_table[MAX_NUM_CCs][800]; /// active flag for Other lcid // uint8_t lcid_active[NB_RB_MAX]; /// eNB stats diff --git a/openair2/LAYER2/MAC/eNB_scheduler.c b/openair2/LAYER2/MAC/eNB_scheduler.c index 329c40be05..01e32ec307 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler.c +++ b/openair2/LAYER2/MAC/eNB_scheduler.c @@ -77,11 +77,13 @@ + + + void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag, frame_t frameP, sub_frame_t subframeP) //, int calibration_flag) { { unsigned int nprb[MAX_NUM_CCs]; - unsigned int nCCE[MAX_NUM_CCs]; int mbsfn_status[MAX_NUM_CCs]; uint32_t RBalloc[MAX_NUM_CCs]; protocol_ctxt_t ctxt; @@ -106,10 +108,13 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag, for (CC_id=0; CC_idnCCE=0; + DCI_pdu[CC_id]->num_pdcch_symbols=1; nprb[CC_id]=0; RBalloc[CC_id]=0; mbsfn_status[CC_id]=0; + // clear vrb_map + memset(eNB_mac_inst[module_idP].common_channels[CC_id].vrb_map,0,100); } // refresh UE list based on UEs dropped by PHY in previous subframe @@ -186,7 +191,7 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag, for (CC_id=0; CC_idNum_common_dci = 0; DCI_pdu[CC_id]->Num_ue_spec_dci = 0; - eNB_mac_inst[module_idP].common_channels[CC_id].bcch_active = 0; + #ifdef Rel10 eNB_mac_inst[module_idP].common_channels[CC_id].mcch_active =0; @@ -194,6 +199,8 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag, eNB_mac_inst[module_idP].frame = frameP; eNB_mac_inst[module_idP].subframe = subframeP; + + } //if (subframeP%5 == 0) @@ -238,19 +245,19 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag, // Schedule ULSCH for FDD or subframeP 4 (TDD config 0,3,6) // Schedule Normal DLSCH - schedule_RA(module_idP,frameP,subframeP,2,nprb,nCCE); + schedule_RA(module_idP,frameP,subframeP,2,nprb); if (mac_xface->lte_frame_parms->frame_type == FDD) { //FDD - schedule_ulsch(module_idP,frameP,cooperation_flag,0,4,nCCE);//,calibration_flag); + schedule_ulsch(module_idP,frameP,cooperation_flag,0,4);//,calibration_flag); } else if ((mac_xface->lte_frame_parms->tdd_config == TDD) || //TDD (mac_xface->lte_frame_parms->tdd_config == 3) || (mac_xface->lte_frame_parms->tdd_config == 6)) { - //schedule_ulsch(module_idP,frameP,cooperation_flag,subframeP,4,nCCE);//,calibration_flag); + //schedule_ulsch(module_idP,frameP,cooperation_flag,subframeP,4);//,calibration_flag); } - // schedule_ue_spec(module_idP,frameP,subframeP,nprb,nCCE,mbsfn_status); + // schedule_ue_spec(module_idP,frameP,subframeP,nprb,mbsfn_status); - fill_DLSCH_dci(module_idP,frameP,subframeP,RBalloc,1,mbsfn_status); + fill_DLSCH_dci(module_idP,frameP,subframeP,RBalloc,mbsfn_status); break; @@ -262,22 +269,22 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag, switch (mac_xface->lte_frame_parms->tdd_config) { case 0: case 1: - schedule_ulsch(module_idP,frameP,cooperation_flag,subframeP,7,nCCE); - fill_DLSCH_dci(module_idP,frameP,subframeP,RBalloc,0,mbsfn_status); + schedule_ulsch(module_idP,frameP,cooperation_flag,subframeP,7); + fill_DLSCH_dci(module_idP,frameP,subframeP,RBalloc,mbsfn_status); break; case 6: - schedule_ulsch(module_idP,frameP,cooperation_flag,subframeP,8,nCCE); - fill_DLSCH_dci(module_idP,frameP,subframeP,RBalloc,0,mbsfn_status); + schedule_ulsch(module_idP,frameP,cooperation_flag,subframeP,8); + fill_DLSCH_dci(module_idP,frameP,subframeP,RBalloc,mbsfn_status); break; default: break; } } else { //FDD - schedule_ue_spec(module_idP,frameP,subframeP,nprb,nCCE,mbsfn_status); - fill_DLSCH_dci(module_idP,frameP,subframeP,RBalloc,0,mbsfn_status); - schedule_ulsch(module_idP,frameP,cooperation_flag,1,5,nCCE); + schedule_ue_spec(module_idP,frameP,subframeP,nprb,mbsfn_status); + fill_DLSCH_dci(module_idP,frameP,subframeP,RBalloc,mbsfn_status); + schedule_ulsch(module_idP,frameP,cooperation_flag,1,5); } break; @@ -287,9 +294,9 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag, // TDD, nothing // FDD, normal UL/DLSCH if (mac_xface->lte_frame_parms->frame_type == FDD) { //FDD - schedule_ue_spec(module_idP,frameP,subframeP,nprb,nCCE,mbsfn_status); - fill_DLSCH_dci(module_idP,frameP,subframeP,RBalloc,0,mbsfn_status); - schedule_ulsch(module_idP,frameP,cooperation_flag,2,6,nCCE); + schedule_ue_spec(module_idP,frameP,subframeP,nprb,mbsfn_status); + fill_DLSCH_dci(module_idP,frameP,subframeP,RBalloc,mbsfn_status); + schedule_ulsch(module_idP,frameP,cooperation_flag,2,6); } break; @@ -302,21 +309,21 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag, if (mac_xface->lte_frame_parms->frame_type == TDD) { switch (mac_xface->lte_frame_parms->tdd_config) { case 2: - schedule_ulsch(module_idP,frameP,cooperation_flag,subframeP,7,nCCE); + schedule_ulsch(module_idP,frameP,cooperation_flag,subframeP,7); // no break here! case 5: - schedule_ue_spec(module_idP,frameP,subframeP,nprb,nCCE,mbsfn_status); - fill_DLSCH_dci(module_idP,frameP,subframeP,RBalloc,0,mbsfn_status); + schedule_ue_spec(module_idP,frameP,subframeP,nprb,mbsfn_status); + fill_DLSCH_dci(module_idP,frameP,subframeP,RBalloc,mbsfn_status); break; default: break; } } else { //FDD - schedule_ue_spec(module_idP,frameP,subframeP,nprb,nCCE,mbsfn_status); - fill_DLSCH_dci(module_idP,frameP,subframeP,RBalloc,0,mbsfn_status); - schedule_ulsch(module_idP,frameP,cooperation_flag,3,7,nCCE); + schedule_ue_spec(module_idP,frameP,subframeP,nprb,mbsfn_status); + fill_DLSCH_dci(module_idP,frameP,subframeP,RBalloc,mbsfn_status); + schedule_ulsch(module_idP,frameP,cooperation_flag,3,7); } @@ -330,8 +337,8 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag, if (mac_xface->lte_frame_parms->frame_type == 1) { // TDD switch (mac_xface->lte_frame_parms->tdd_config) { case 1: - // schedule_RA(module_idP,frameP,subframeP,nprb,nCCE); - schedule_ulsch(module_idP,frameP,cooperation_flag,subframeP,8,nCCE); + // schedule_RA(module_idP,frameP,subframeP,nprb); + schedule_ulsch(module_idP,frameP,cooperation_flag,subframeP,8); // no break here! case 2: @@ -341,8 +348,8 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag, // no break here! case 5: - schedule_ue_spec(module_idP,frameP,subframeP,nprb,nCCE,mbsfn_status); - fill_DLSCH_dci(module_idP,frameP,subframeP,RBalloc,1,mbsfn_status); + schedule_ue_spec(module_idP,frameP,subframeP,nprb,mbsfn_status); + fill_DLSCH_dci(module_idP,frameP,subframeP,RBalloc,mbsfn_status); break; default: @@ -350,10 +357,10 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag, } } else { if (mac_xface->lte_frame_parms->frame_type == FDD) { //FDD - // schedule_RA(module_idP,frameP, subframeP, 0, nprb, nCCE); - // schedule_ulsch(module_idP, frameP, cooperation_flag, 4, 8, nCCE); - schedule_ue_spec(module_idP, frameP, subframeP, nprb, nCCE, mbsfn_status); - fill_DLSCH_dci(module_idP, frameP, subframeP, RBalloc, 1, mbsfn_status); + // schedule_RA(module_idP,frameP, subframeP, 0, nprb); + // schedule_ulsch(module_idP, frameP, cooperation_flag, 4, 8); + schedule_ue_spec(module_idP, frameP, subframeP, nprb, mbsfn_status); + fill_DLSCH_dci(module_idP, frameP, subframeP, RBalloc, mbsfn_status); } } @@ -365,21 +372,21 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag, // TDD Config 0,6 ULSCH for subframes 9,3 resp. // TDD normal DLSCH // FDD normal UL/DLSCH - schedule_SI(module_idP,frameP,nprb,nCCE); + schedule_SI(module_idP,frameP,subframeP,nprb); - //schedule_RA(module_idP,frameP,subframeP,5,nprb,nCCE); + //schedule_RA(module_idP,frameP,subframeP,5,nprb); if (mac_xface->lte_frame_parms->frame_type == FDD) { - schedule_RA(module_idP,frameP,subframeP,1,nprb,nCCE); - // schedule_ulsch(module_idP,frameP,cooperation_flag,5,9,nCCE); - fill_DLSCH_dci(module_idP,frameP,subframeP,RBalloc,1,mbsfn_status); + schedule_RA(module_idP,frameP,subframeP,1,nprb); + // schedule_ulsch(module_idP,frameP,cooperation_flag,5,9); + fill_DLSCH_dci(module_idP,frameP,subframeP,RBalloc,mbsfn_status); } else if ((mac_xface->lte_frame_parms->tdd_config == 0) || // TDD Config 0 (mac_xface->lte_frame_parms->tdd_config == 6)) { // TDD Config 6 - //schedule_ulsch(module_idP,cooperation_flag,subframeP,nCCE); - fill_DLSCH_dci(module_idP,frameP,subframeP,RBalloc,0,mbsfn_status); + //schedule_ulsch(module_idP,cooperation_flag,subframeP); + fill_DLSCH_dci(module_idP,frameP,subframeP,RBalloc,mbsfn_status); } else { - //schedule_ue_spec(module_idP,frameP,subframeP,nprb,nCCE,mbsfn_status); - fill_DLSCH_dci(module_idP,frameP,subframeP,RBalloc,0,mbsfn_status); + //schedule_ue_spec(module_idP,frameP,subframeP,nprb,mbsfn_status); + fill_DLSCH_dci(module_idP,frameP,subframeP,RBalloc,mbsfn_status); } break; @@ -395,36 +402,36 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag, break; case 1: - schedule_ulsch(module_idP,frameP,cooperation_flag,subframeP,2,nCCE); - // schedule_ue_spec(module_idP,frameP,subframeP,nprb,nCCE,mbsfn_status); - fill_DLSCH_dci(module_idP,frameP,subframeP,RBalloc,0,mbsfn_status); + schedule_ulsch(module_idP,frameP,cooperation_flag,subframeP,2); + // schedule_ue_spec(module_idP,frameP,subframeP,nprb,mbsfn_status); + fill_DLSCH_dci(module_idP,frameP,subframeP,RBalloc,mbsfn_status); break; case 6: - schedule_ulsch(module_idP,frameP,cooperation_flag,subframeP,3,nCCE); - // schedule_ue_spec(module_idP,frameP,subframeP,nprb,nCCE,mbsfn_status); - fill_DLSCH_dci(module_idP,frameP,subframeP,RBalloc,0,mbsfn_status); + schedule_ulsch(module_idP,frameP,cooperation_flag,subframeP,3); + // schedule_ue_spec(module_idP,frameP,subframeP,nprb,mbsfn_status); + fill_DLSCH_dci(module_idP,frameP,subframeP,RBalloc,mbsfn_status); break; case 5: - schedule_RA(module_idP,frameP,subframeP,2,nprb,nCCE); - schedule_ue_spec(module_idP,frameP,subframeP,nprb,nCCE,mbsfn_status); - fill_DLSCH_dci(module_idP,frameP,subframeP,RBalloc,1,mbsfn_status); + schedule_RA(module_idP,frameP,subframeP,2,nprb); + schedule_ue_spec(module_idP,frameP,subframeP,nprb,mbsfn_status); + fill_DLSCH_dci(module_idP,frameP,subframeP,RBalloc,mbsfn_status); break; case 3: case 4: - schedule_ue_spec(module_idP,frameP,subframeP,nprb,nCCE,mbsfn_status); - fill_DLSCH_dci(module_idP,frameP,subframeP,RBalloc,0,mbsfn_status); + schedule_ue_spec(module_idP,frameP,subframeP,nprb,mbsfn_status); + fill_DLSCH_dci(module_idP,frameP,subframeP,RBalloc,mbsfn_status); break; default: break; } } else { //FDD - // schedule_ulsch(module_idP,frameP,cooperation_flag,6,0,nCCE); - schedule_ue_spec(module_idP,frameP,subframeP,nprb,nCCE,mbsfn_status); - fill_DLSCH_dci(module_idP,frameP,subframeP,RBalloc,0,mbsfn_status); + // schedule_ulsch(module_idP,frameP,cooperation_flag,6,0); + schedule_ue_spec(module_idP,frameP,subframeP,nprb,mbsfn_status); + fill_DLSCH_dci(module_idP,frameP,subframeP,RBalloc,mbsfn_status); } break; @@ -437,23 +444,23 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag, switch (mac_xface->lte_frame_parms->tdd_config) { case 3: case 4: - schedule_RA(module_idP,frameP,subframeP,3,nprb,nCCE); // 3 = Msg3 subframeP, not - schedule_ue_spec(module_idP,frameP,subframeP,nprb,nCCE,mbsfn_status); - fill_DLSCH_dci(module_idP,frameP,subframeP,RBalloc,1,mbsfn_status); + schedule_RA(module_idP,frameP,subframeP,3,nprb); // 3 = Msg3 subframeP, not + schedule_ue_spec(module_idP,frameP,subframeP,nprb,mbsfn_status); + fill_DLSCH_dci(module_idP,frameP,subframeP,RBalloc,mbsfn_status); break; case 5: - schedule_ue_spec(module_idP,frameP,subframeP,nprb,nCCE,mbsfn_status); - fill_DLSCH_dci(module_idP,frameP,subframeP,RBalloc,0,mbsfn_status); + schedule_ue_spec(module_idP,frameP,subframeP,nprb,mbsfn_status); + fill_DLSCH_dci(module_idP,frameP,subframeP,RBalloc,mbsfn_status); break; default: break; } } else { //FDD - //schedule_ulsch(module_idP,frameP,cooperation_flag,7,1,nCCE); - schedule_ue_spec(module_idP,frameP,subframeP,nprb,nCCE,mbsfn_status); - fill_DLSCH_dci(module_idP,frameP,subframeP,RBalloc,0,mbsfn_status); + //schedule_ulsch(module_idP,frameP,cooperation_flag,7,1); + schedule_ue_spec(module_idP,frameP,subframeP,nprb,mbsfn_status); + fill_DLSCH_dci(module_idP,frameP,subframeP,RBalloc,mbsfn_status); } break; @@ -470,19 +477,19 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag, case 4: case 5: - // schedule_RA(module_idP,subframeP,nprb,nCCE); - schedule_ulsch(module_idP,frameP,cooperation_flag,subframeP,2,nCCE); - schedule_ue_spec(module_idP,frameP,subframeP,nprb,nCCE,mbsfn_status); - fill_DLSCH_dci(module_idP,frameP,subframeP,RBalloc,0,mbsfn_status); + // schedule_RA(module_idP,subframeP,nprb); + schedule_ulsch(module_idP,frameP,cooperation_flag,subframeP,2); + schedule_ue_spec(module_idP,frameP,subframeP,nprb,mbsfn_status); + fill_DLSCH_dci(module_idP,frameP,subframeP,RBalloc,mbsfn_status); break; default: break; } } else { //FDD - //schedule_ulsch(module_idP,frameP,cooperation_flag,8,2,nCCE); - schedule_ue_spec(module_idP,frameP,subframeP,nprb,nCCE,mbsfn_status); - fill_DLSCH_dci(module_idP,frameP,subframeP,RBalloc,0,mbsfn_status); + //schedule_ulsch(module_idP,frameP,cooperation_flag,8,2); + schedule_ue_spec(module_idP,frameP,subframeP,nprb,mbsfn_status); + fill_DLSCH_dci(module_idP,frameP,subframeP,RBalloc,mbsfn_status); } break; @@ -493,51 +500,50 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag, if (mac_xface->lte_frame_parms->frame_type == TDD) { switch (mac_xface->lte_frame_parms->tdd_config) { case 1: - schedule_ulsch(module_idP,frameP,cooperation_flag,subframeP,3,nCCE); - schedule_RA(module_idP,frameP,subframeP,7,nprb,nCCE); // 7 = Msg3 subframeP, not - schedule_ue_spec(module_idP,frameP,subframeP,nprb,nCCE,mbsfn_status); - fill_DLSCH_dci(module_idP,frameP,subframeP,RBalloc,1,mbsfn_status); + schedule_ulsch(module_idP,frameP,cooperation_flag,subframeP,3); + schedule_RA(module_idP,frameP,subframeP,7,nprb); // 7 = Msg3 subframeP, not + schedule_ue_spec(module_idP,frameP,subframeP,nprb,mbsfn_status); + fill_DLSCH_dci(module_idP,frameP,subframeP,RBalloc,mbsfn_status); break; case 3: case 4: - schedule_ulsch(module_idP,frameP,cooperation_flag,subframeP,3,nCCE); - schedule_ue_spec(module_idP,frameP,subframeP,nprb,nCCE,mbsfn_status); - fill_DLSCH_dci(module_idP,frameP,subframeP,RBalloc,0,mbsfn_status); + schedule_ulsch(module_idP,frameP,cooperation_flag,subframeP,3); + schedule_ue_spec(module_idP,frameP,subframeP,nprb,mbsfn_status); + fill_DLSCH_dci(module_idP,frameP,subframeP,RBalloc,mbsfn_status); break; case 6: - schedule_ulsch(module_idP,frameP,cooperation_flag,subframeP,4,nCCE); - //schedule_RA(module_idP,frameP,subframeP,nprb,nCCE); - schedule_ue_spec(module_idP,frameP,subframeP,nprb,nCCE,mbsfn_status); - fill_DLSCH_dci(module_idP,frameP,subframeP,RBalloc,0,mbsfn_status); + schedule_ulsch(module_idP,frameP,cooperation_flag,subframeP,4); + //schedule_RA(module_idP,frameP,subframeP,nprb); + schedule_ue_spec(module_idP,frameP,subframeP,nprb,mbsfn_status); + fill_DLSCH_dci(module_idP,frameP,subframeP,RBalloc,mbsfn_status); break; case 2: case 5: - //schedule_RA(module_idP,frameP,subframeP,nprb,nCCE); - schedule_ue_spec(module_idP,frameP,subframeP,nprb,nCCE,mbsfn_status); - fill_DLSCH_dci(module_idP,frameP,subframeP,RBalloc,0,mbsfn_status); + //schedule_RA(module_idP,frameP,subframeP,nprb); + schedule_ue_spec(module_idP,frameP,subframeP,nprb,mbsfn_status); + fill_DLSCH_dci(module_idP,frameP,subframeP,RBalloc,mbsfn_status); break; default: break; } } else { //FDD - // schedule_ulsch(module_idP,frameP,cooperation_flag,9,3,nCCE); - schedule_ue_spec(module_idP,frameP,subframeP,nprb,nCCE,mbsfn_status); - fill_DLSCH_dci(module_idP,frameP,subframeP,RBalloc,0,mbsfn_status); + // schedule_ulsch(module_idP,frameP,cooperation_flag,9,3); + schedule_ue_spec(module_idP,frameP,subframeP,nprb,mbsfn_status); + fill_DLSCH_dci(module_idP,frameP,subframeP,RBalloc,mbsfn_status); } break; } - for (CC_id=0; CC_idnCCE = nCCE[CC_id]; - } + for (CC_id=0;CC_idschedule_ra); for (CC_id=0; CC_idcommon_channels[CC_id].RA_template[0]; + + vrb_map = eNB->common_channels[CC_id].vrb_map; + DCI_pdu = &eNB->common_channels[CC_id].DCI_pdu; for (i=0; icommon_channels[CC_id].RA_template[i]; + + if (RA_template->RA_active == TRUE) { LOG_D(MAC,"[eNB %d][RAPROC] CC_id %d RA %d is active (generate RAR %d, generate_Msg4 %d, wait_ack_Msg4 %d, rnti %x)\n", - module_idP,CC_id,i,RA_template[i].generate_rar,RA_template[i].generate_Msg4,RA_template[i].wait_ack_Msg4, RA_template[i].rnti); + module_idP,CC_id,i,RA_template->generate_rar,RA_template->generate_Msg4,RA_template->wait_ack_Msg4, RA_template->rnti); - if (RA_template[i].generate_rar == 1) { - nprb[CC_id]= nprb[CC_id] + 3; - nCCE[CC_id] = nCCE[CC_id] + 4; - RA_template[i].Msg3_subframe=Msg3_subframe; - } else if (RA_template[i].generate_Msg4 == 1) { + if (RA_template->generate_rar == 1) { + + LOG_D(MAC,"[eNB %d] CC_id %d Frame %d, subframeP %d: Generating RAR DCI (proc %d), RA_active %d format 1A (%d,%d))\n", + module_idP, CC_id, frameP, subframeP,i, + RA_template->RA_active, + RA_template->RA_dci_fmt1, + RA_template->RA_dci_size_bits1); + + + + if (PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.frame_type == TDD) { + switch(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL) { + case 6: + ((DCI1A_1_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->type=1; + ((DCI1A_1_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->vrb_type=0; + ((DCI1A_1_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->ndi=1; + ((DCI1A_1_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->rv=0; + ((DCI1A_1_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->mcs=0; + ((DCI1A_1_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->harq_pid=0; + ((DCI1A_1_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->TPC=1; + ((DCI1A_1_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->padding=0; + ((DCI1A_1_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->rballoc = mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL,first_rb,4); + rballoc[CC_id] |= mac_xface->get_rballoc(((DCI1A_1_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->vrb_type, + ((DCI1A_1_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->rballoc); + break; + + case 25: + ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->type=1; + ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->vrb_type=0; + ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->ndi=1; + ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->rv=0; + ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->mcs=0; + ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->harq_pid=0; + ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->TPC=1; + ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->padding=0; + ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->rballoc = mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL,first_rb,4); + rballoc[CC_id] |= mac_xface->get_rballoc(((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->vrb_type, + ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->rballoc); + break; + + case 50: + ((DCI1A_10MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->type=1; + ((DCI1A_10MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->vrb_type=0; + ((DCI1A_10MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->ndi=1; + ((DCI1A_10MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->rv=0; + ((DCI1A_10MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->mcs=0; + ((DCI1A_10MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->harq_pid=0; + ((DCI1A_10MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->TPC=1; + ((DCI1A_10MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->padding=0; + ((DCI1A_10MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->rballoc = mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL,first_rb,4); + rballoc[CC_id] |= mac_xface->get_rballoc(((DCI1A_10MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->vrb_type, + ((DCI1A_10MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->rballoc); + break; + + case 100: + ((DCI1A_20MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->type=1; + ((DCI1A_20MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->vrb_type=0; + ((DCI1A_20MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->ndi=1; + ((DCI1A_20MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->rv=0; + ((DCI1A_20MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->mcs=0; + ((DCI1A_20MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->harq_pid=0; + ((DCI1A_20MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->TPC=1; + ((DCI1A_20MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->padding=0; + ((DCI1A_20MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->rballoc = mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL,first_rb,4); + rballoc[CC_id] |= mac_xface->get_rballoc(((DCI1A_20MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->vrb_type, + ((DCI1A_20MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->rballoc); + break; + + default: + ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->type=1; + ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->vrb_type=0; + ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->ndi=1; + ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->rv=0; + ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->mcs=0; + ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->harq_pid=0; + ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->TPC=1; + ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->padding=0; + ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->rballoc = mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL,first_rb,4); + rballoc[CC_id] |= mac_xface->get_rballoc(((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->vrb_type, + ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->rballoc); + break; + } + } else { + switch(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL) { + case 6: + ((DCI1A_1_5MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->type=1; + ((DCI1A_1_5MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->vrb_type=0; + ((DCI1A_1_5MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->ndi=1; + ((DCI1A_1_5MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->rv=0; + ((DCI1A_1_5MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->mcs=0; + ((DCI1A_1_5MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->harq_pid=0; + ((DCI1A_1_5MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->TPC=1; + ((DCI1A_1_5MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->padding=0; + ((DCI1A_1_5MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->rballoc = mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL,first_rb,4); + rballoc[CC_id] |= mac_xface->get_rballoc(((DCI1A_1_5MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->vrb_type, + ((DCI1A_1_5MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->rballoc); + break; + + case 25: + ((DCI1A_5MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->type=1; + ((DCI1A_5MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->vrb_type=0; + ((DCI1A_5MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->ndi=1; + ((DCI1A_5MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->rv=0; + ((DCI1A_5MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->mcs=0; + ((DCI1A_5MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->harq_pid=0; + ((DCI1A_5MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->TPC=1; + ((DCI1A_5MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->padding=0; + ((DCI1A_5MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->rballoc = mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_UL,first_rb,4); + rballoc[CC_id] |= mac_xface->get_rballoc(((DCI1A_5MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->vrb_type, + ((DCI1A_5MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->rballoc); + break; + + case 50: + ((DCI1A_10MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->type=1; + ((DCI1A_10MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->vrb_type=0; + ((DCI1A_10MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->ndi=1; + ((DCI1A_10MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->rv=0; + ((DCI1A_10MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->mcs=0; + ((DCI1A_10MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->harq_pid=0; + ((DCI1A_10MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->TPC=1; + ((DCI1A_10MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->padding=0; + ((DCI1A_10MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->rballoc = mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL,first_rb,4); + rballoc[CC_id] |= mac_xface->get_rballoc(((DCI1A_10MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->vrb_type, + ((DCI1A_10MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->rballoc); + break; + + case 100: + ((DCI1A_20MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->type=1; + ((DCI1A_20MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->vrb_type=0; + ((DCI1A_20MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->ndi=1; + ((DCI1A_20MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->rv=0; + ((DCI1A_20MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->mcs=0; + ((DCI1A_20MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->harq_pid=0; + ((DCI1A_20MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->TPC=1; + ((DCI1A_20MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->padding=0; + ((DCI1A_20MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->rballoc = mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL,first_rb,4); + rballoc[CC_id] |= mac_xface->get_rballoc(((DCI1A_20MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->vrb_type, + ((DCI1A_20MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->rballoc); + break; + + default: + break; + } + } + + if (!CCE_allocation_infeasible(module_idP,CC_id,1,subframeP,2,RA_template->RA_rnti)) { + add_common_dci(DCI_pdu, + (void*)&RA_template->RA_alloc_pdu1[0], + RA_template->RA_rnti, + RA_template->RA_dci_size_bytes1, + 2, + RA_template->RA_dci_size_bits1, + RA_template->RA_dci_fmt1, + 1); + + nprb[CC_id]= nprb[CC_id] + 3; + RA_template->Msg3_subframe=Msg3_subframe; + } + } else if (RA_template->generate_Msg4 == 1) { // check for Msg4 Message - UE_id = find_UE_id(module_idP,RA_template[i].rnti); + UE_id = find_UE_id(module_idP,RA_template->rnti); if (Is_rrc_registered == 1) { @@ -131,7 +293,7 @@ void schedule_RA(module_id_t module_idP,frame_t frameP, sub_frame_t subframeP,un if (rrc_sdu_length>0) { LOG_I(MAC,"[eNB %d][RAPROC] CC_id %d Frame %d, subframeP %d: Generating Msg4 with RRC Piggyback (RA proc %d, RNTI %x)\n", - module_idP, CC_id, frameP, subframeP,i,RA_template[i].rnti); + module_idP, CC_id, frameP, subframeP,i,RA_template->rnti); //msg("[MAC][eNB %d][RAPROC] Frame %d, subframeP %d: Received %d bytes for Msg4: \n",module_idP,frameP,subframeP,rrc_sdu_length); // for (j=0;jlte_frame_parms.N_RB_DL-4)); + + if ((vrb_map[first_rb] != 1) && (vrb_map[first_rb+3] != 1)) + break; + } + + vrb_map[first_rb] = 1; + vrb_map[first_rb+1] = 1; + vrb_map[first_rb+2] = 1; + vrb_map[first_rb+3] = 1; // Compute MCS for 3 PRB @@ -149,273 +323,405 @@ void schedule_RA(module_id_t module_idP,frame_t frameP, sub_frame_t subframeP,un switch (mac_xface->lte_frame_parms->N_RB_DL) { case 6: - ((DCI1A_1_5MHz_TDD_1_6_t*)&RA_template[i].RA_alloc_pdu2[0])->ndi=1; + ((DCI1A_1_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->ndi=1; if ((rrc_sdu_length+msg4_header) <= 22) { - ((DCI1A_1_5MHz_TDD_1_6_t*)&RA_template[i].RA_alloc_pdu2[0])->mcs=4; + ((DCI1A_1_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->mcs=4; TBsize = 22; } else if ((rrc_sdu_length+msg4_header) <= 28) { - ((DCI1A_1_5MHz_TDD_1_6_t*)&RA_template[i].RA_alloc_pdu2[0])->mcs=5; + ((DCI1A_1_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->mcs=5; TBsize = 28; } else if ((rrc_sdu_length+msg4_header) <= 32) { - ((DCI1A_1_5MHz_TDD_1_6_t*)&RA_template[i].RA_alloc_pdu2[0])->mcs=6; + ((DCI1A_1_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->mcs=6; TBsize = 32; } else if ((rrc_sdu_length+msg4_header) <= 41) { - ((DCI1A_1_5MHz_TDD_1_6_t*)&RA_template[i].RA_alloc_pdu2[0])->mcs=7; + ((DCI1A_1_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->mcs=7; TBsize = 41; } else if ((rrc_sdu_length+msg4_header) <= 49) { - ((DCI1A_1_5MHz_TDD_1_6_t*)&RA_template[i].RA_alloc_pdu2[0])->mcs=8; + ((DCI1A_1_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->mcs=8; TBsize = 49; } else if ((rrc_sdu_length+msg4_header) <= 57) { - ((DCI1A_1_5MHz_TDD_1_6_t*)&RA_template[i].RA_alloc_pdu2[0])->mcs=9; + ((DCI1A_1_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->mcs=9; TBsize = 57; } - + ((DCI1A_1_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->type=1; + ((DCI1A_1_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->vrb_type=0; + ((DCI1A_1_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->rv=0; + ((DCI1A_1_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->harq_pid=0; + ((DCI1A_1_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->TPC=1; + ((DCI1A_1_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->padding=0; + ((DCI1A_1_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->rballoc= mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL,first_rb,4); + rballoc[CC_id] |= mac_xface->get_rballoc(((DCI1A_1_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->vrb_type, + ((DCI1A_1_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->rballoc); + break; case 25: - ((DCI1A_5MHz_TDD_1_6_t*)&RA_template[i].RA_alloc_pdu2[0])->ndi=1; + ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->ndi=1; if ((rrc_sdu_length+msg4_header) <= 22) { - ((DCI1A_5MHz_TDD_1_6_t*)&RA_template[i].RA_alloc_pdu2[0])->mcs=4; + ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->mcs=4; TBsize = 22; } else if ((rrc_sdu_length+msg4_header) <= 28) { - ((DCI1A_5MHz_TDD_1_6_t*)&RA_template[i].RA_alloc_pdu2[0])->mcs=5; + ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->mcs=5; TBsize = 28; } else if ((rrc_sdu_length+msg4_header) <= 32) { - ((DCI1A_5MHz_TDD_1_6_t*)&RA_template[i].RA_alloc_pdu2[0])->mcs=6; + ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->mcs=6; TBsize = 32; } else if ((rrc_sdu_length+msg4_header) <= 41) { - ((DCI1A_5MHz_TDD_1_6_t*)&RA_template[i].RA_alloc_pdu2[0])->mcs=7; + ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->mcs=7; TBsize = 41; } else if ((rrc_sdu_length+msg4_header) <= 49) { - ((DCI1A_5MHz_TDD_1_6_t*)&RA_template[i].RA_alloc_pdu2[0])->mcs=8; + ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->mcs=8; TBsize = 49; } else if ((rrc_sdu_length+msg4_header) <= 57) { - ((DCI1A_5MHz_TDD_1_6_t*)&RA_template[i].RA_alloc_pdu2[0])->mcs=9; + ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->mcs=9; TBsize = 57; } - + + ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->type=1; + ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->vrb_type=0; + ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->rv=0; + ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->harq_pid=0; + ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->TPC=1; + ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->padding=0; + ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->rballoc= mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL,first_rb,4); + rballoc[CC_id] |= mac_xface->get_rballoc(((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->vrb_type, + ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->rballoc); break; case 50: - ((DCI1A_10MHz_TDD_1_6_t*)&RA_template[i].RA_alloc_pdu2[0])->ndi=1; + ((DCI1A_10MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->ndi=1; if ((rrc_sdu_length+msg4_header) <= 22) { - ((DCI1A_10MHz_TDD_1_6_t*)&RA_template[i].RA_alloc_pdu2[0])->mcs=4; + ((DCI1A_10MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->mcs=4; TBsize = 22; } else if ((rrc_sdu_length+msg4_header) <= 28) { - ((DCI1A_10MHz_TDD_1_6_t*)&RA_template[i].RA_alloc_pdu2[0])->mcs=5; + ((DCI1A_10MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->mcs=5; TBsize = 28; } else if ((rrc_sdu_length+msg4_header) <= 32) { - ((DCI1A_10MHz_TDD_1_6_t*)&RA_template[i].RA_alloc_pdu2[0])->mcs=6; + ((DCI1A_10MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->mcs=6; TBsize = 32; } else if ((rrc_sdu_length+msg4_header) <= 41) { - ((DCI1A_10MHz_TDD_1_6_t*)&RA_template[i].RA_alloc_pdu2[0])->mcs=7; + ((DCI1A_10MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->mcs=7; TBsize = 41; } else if ((rrc_sdu_length+msg4_header) <= 49) { - ((DCI1A_10MHz_TDD_1_6_t*)&RA_template[i].RA_alloc_pdu2[0])->mcs=8; + ((DCI1A_10MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->mcs=8; TBsize = 49; } else if ((rrc_sdu_length+msg4_header) <= 57) { - ((DCI1A_10MHz_TDD_1_6_t*)&RA_template[i].RA_alloc_pdu2[0])->mcs=9; + ((DCI1A_10MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->mcs=9; TBsize = 57; } + ((DCI1A_10MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->type=1; + ((DCI1A_10MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->vrb_type=0; + ((DCI1A_10MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->rv=0; + ((DCI1A_10MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->harq_pid=0; + ((DCI1A_10MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->TPC=1; + ((DCI1A_10MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->padding=0; + ((DCI1A_10MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->rballoc= mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL,first_rb,4); + rballoc[CC_id] |= mac_xface->get_rballoc(((DCI1A_10MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->vrb_type, + ((DCI1A_10MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->rballoc); break; case 100: - ((DCI1A_20MHz_TDD_1_6_t*)&RA_template[i].RA_alloc_pdu2[0])->ndi=1; + ((DCI1A_20MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->ndi=1; if ((rrc_sdu_length+msg4_header) <= 22) { - ((DCI1A_20MHz_TDD_1_6_t*)&RA_template[i].RA_alloc_pdu2[0])->mcs=4; + ((DCI1A_20MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->mcs=4; TBsize = 22; } else if ((rrc_sdu_length+msg4_header) <= 28) { - ((DCI1A_20MHz_TDD_1_6_t*)&RA_template[i].RA_alloc_pdu2[0])->mcs=5; + ((DCI1A_20MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->mcs=5; TBsize = 28; } else if ((rrc_sdu_length+msg4_header) <= 32) { - ((DCI1A_20MHz_TDD_1_6_t*)&RA_template[i].RA_alloc_pdu2[0])->mcs=6; + ((DCI1A_20MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->mcs=6; TBsize = 32; } else if ((rrc_sdu_length+msg4_header) <= 41) { - ((DCI1A_20MHz_TDD_1_6_t*)&RA_template[i].RA_alloc_pdu2[0])->mcs=7; + ((DCI1A_20MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->mcs=7; TBsize = 41; } else if ((rrc_sdu_length+msg4_header) <= 49) { - ((DCI1A_20MHz_TDD_1_6_t*)&RA_template[i].RA_alloc_pdu2[0])->mcs=8; + ((DCI1A_20MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->mcs=8; TBsize = 49; } else if ((rrc_sdu_length+msg4_header) <= 57) { - ((DCI1A_20MHz_TDD_1_6_t*)&RA_template[i].RA_alloc_pdu2[0])->mcs=9; + ((DCI1A_20MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->mcs=9; TBsize = 57; } + ((DCI1A_20MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->type=1; + ((DCI1A_20MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->vrb_type=0; + ((DCI1A_20MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->rv=0; + ((DCI1A_20MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->harq_pid=0; + ((DCI1A_20MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->TPC=1; + ((DCI1A_20MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->rballoc= mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL,first_rb,4); + rballoc[CC_id] |= mac_xface->get_rballoc(((DCI1A_20MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->vrb_type, + ((DCI1A_20MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->rballoc); break; } } else { // FDD DCI switch (mac_xface->lte_frame_parms->N_RB_DL) { case 6: - ((DCI1A_1_5MHz_FDD_t*)&RA_template[i].RA_alloc_pdu2[0])->ndi=1; + ((DCI1A_1_5MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->ndi=1; if ((rrc_sdu_length+msg4_header) <= 22) { - ((DCI1A_1_5MHz_FDD_t*)&RA_template[i].RA_alloc_pdu2[0])->mcs=4; + ((DCI1A_1_5MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->mcs=4; TBsize = 22; } else if ((rrc_sdu_length+msg4_header) <= 28) { - ((DCI1A_1_5MHz_FDD_t*)&RA_template[i].RA_alloc_pdu2[0])->mcs=5; + ((DCI1A_1_5MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->mcs=5; TBsize = 28; } else if ((rrc_sdu_length+msg4_header) <= 32) { - ((DCI1A_1_5MHz_FDD_t*)&RA_template[i].RA_alloc_pdu2[0])->mcs=6; + ((DCI1A_1_5MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->mcs=6; TBsize = 32; } else if ((rrc_sdu_length+msg4_header) <= 41) { - ((DCI1A_1_5MHz_FDD_t*)&RA_template[i].RA_alloc_pdu2[0])->mcs=7; + ((DCI1A_1_5MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->mcs=7; TBsize = 41; } else if ((rrc_sdu_length+msg4_header) <= 49) { - ((DCI1A_1_5MHz_FDD_t*)&RA_template[i].RA_alloc_pdu2[0])->mcs=8; + ((DCI1A_1_5MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->mcs=8; TBsize = 49; } else if ((rrc_sdu_length+msg4_header) <= 57) { - ((DCI1A_1_5MHz_FDD_t*)&RA_template[i].RA_alloc_pdu2[0])->mcs=9; + ((DCI1A_1_5MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->mcs=9; TBsize = 57; } + ((DCI1A_1_5MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->type=1; + ((DCI1A_1_5MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->vrb_type=0; + ((DCI1A_1_5MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->rv=0; + ((DCI1A_1_5MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->harq_pid=0; + ((DCI1A_1_5MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->TPC=1; + ((DCI1A_1_5MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->padding=0; + ((DCI1A_1_5MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->rballoc= mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL,first_rb,4); + rballoc[CC_id] |= mac_xface->get_rballoc(((DCI1A_1_5MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->vrb_type, + ((DCI1A_1_5MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->rballoc); break; case 25: - ((DCI1A_5MHz_FDD_t*)&RA_template[i].RA_alloc_pdu2[0])->ndi=1; + ((DCI1A_5MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->ndi=1; if ((rrc_sdu_length+msg4_header) <= 22) { - ((DCI1A_5MHz_FDD_t*)&RA_template[i].RA_alloc_pdu2[0])->mcs=4; + ((DCI1A_5MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->mcs=4; TBsize = 22; } else if ((rrc_sdu_length+msg4_header) <= 28) { - ((DCI1A_5MHz_FDD_t*)&RA_template[i].RA_alloc_pdu2[0])->mcs=5; + ((DCI1A_5MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->mcs=5; TBsize = 28; } else if ((rrc_sdu_length+msg4_header) <= 32) { - ((DCI1A_5MHz_FDD_t*)&RA_template[i].RA_alloc_pdu2[0])->mcs=6; + ((DCI1A_5MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->mcs=6; TBsize = 32; } else if ((rrc_sdu_length+msg4_header) <= 41) { - ((DCI1A_5MHz_FDD_t*)&RA_template[i].RA_alloc_pdu2[0])->mcs=7; + ((DCI1A_5MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->mcs=7; TBsize = 41; } else if ((rrc_sdu_length+msg4_header) <= 49) { - ((DCI1A_5MHz_FDD_t*)&RA_template[i].RA_alloc_pdu2[0])->mcs=8; + ((DCI1A_5MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->mcs=8; TBsize = 49; } else if ((rrc_sdu_length+msg4_header) <= 57) { - ((DCI1A_5MHz_FDD_t*)&RA_template[i].RA_alloc_pdu2[0])->mcs=9; + ((DCI1A_5MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->mcs=9; TBsize = 57; } + ((DCI1A_5MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->type=1; + ((DCI1A_5MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->vrb_type=0; + ((DCI1A_5MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->rv=0; + ((DCI1A_5MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->harq_pid=0; + ((DCI1A_5MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->TPC=1; + ((DCI1A_5MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->padding=0; + ((DCI1A_5MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->rballoc= mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL,first_rb,4); + rballoc[CC_id] |= mac_xface->get_rballoc(((DCI1A_5MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->vrb_type, + ((DCI1A_5MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->rballoc); break; case 50: - ((DCI1A_10MHz_FDD_t*)&RA_template[i].RA_alloc_pdu2[0])->ndi=1; + ((DCI1A_10MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->ndi=1; if ((rrc_sdu_length+msg4_header) <= 22) { - ((DCI1A_10MHz_FDD_t*)&RA_template[i].RA_alloc_pdu2[0])->mcs=4; + ((DCI1A_10MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->mcs=4; TBsize = 22; } else if ((rrc_sdu_length+msg4_header) <= 28) { - ((DCI1A_10MHz_FDD_t*)&RA_template[i].RA_alloc_pdu2[0])->mcs=5; + ((DCI1A_10MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->mcs=5; TBsize = 28; } else if ((rrc_sdu_length+msg4_header) <= 32) { - ((DCI1A_10MHz_FDD_t*)&RA_template[i].RA_alloc_pdu2[0])->mcs=6; + ((DCI1A_10MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->mcs=6; TBsize = 32; } else if ((rrc_sdu_length+msg4_header) <= 41) { - ((DCI1A_10MHz_FDD_t*)&RA_template[i].RA_alloc_pdu2[0])->mcs=7; + ((DCI1A_10MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->mcs=7; TBsize = 41; } else if ((rrc_sdu_length+msg4_header) <= 49) { - ((DCI1A_10MHz_FDD_t*)&RA_template[i].RA_alloc_pdu2[0])->mcs=8; + ((DCI1A_10MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->mcs=8; TBsize = 49; } else if ((rrc_sdu_length+msg4_header) <= 57) { - ((DCI1A_10MHz_FDD_t*)&RA_template[i].RA_alloc_pdu2[0])->mcs=9; + ((DCI1A_10MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->mcs=9; TBsize = 57; } + ((DCI1A_10MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->type=1; + ((DCI1A_10MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->vrb_type=0; + ((DCI1A_10MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->rv=0; + ((DCI1A_10MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->harq_pid=0; + ((DCI1A_10MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->TPC=1; + ((DCI1A_10MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->padding=0; + ((DCI1A_10MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->rballoc= mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL,first_rb,4); + rballoc[CC_id] |= mac_xface->get_rballoc(((DCI1A_10MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->vrb_type, + ((DCI1A_10MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->rballoc); break; case 100: - ((DCI1A_20MHz_FDD_t*)&RA_template[i].RA_alloc_pdu2[0])->ndi=1; + ((DCI1A_20MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->ndi=1; if ((rrc_sdu_length+msg4_header) <= 22) { - ((DCI1A_20MHz_FDD_t*)&RA_template[i].RA_alloc_pdu2[0])->mcs=4; + ((DCI1A_20MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->mcs=4; TBsize = 22; } else if ((rrc_sdu_length+msg4_header) <= 28) { - ((DCI1A_20MHz_FDD_t*)&RA_template[i].RA_alloc_pdu2[0])->mcs=5; + ((DCI1A_20MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->mcs=5; TBsize = 28; } else if ((rrc_sdu_length+msg4_header) <= 32) { - ((DCI1A_20MHz_FDD_t*)&RA_template[i].RA_alloc_pdu2[0])->mcs=6; + ((DCI1A_20MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->mcs=6; TBsize = 32; } else if ((rrc_sdu_length+msg4_header) <= 41) { - ((DCI1A_20MHz_FDD_t*)&RA_template[i].RA_alloc_pdu2[0])->mcs=7; + ((DCI1A_20MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->mcs=7; TBsize = 41; } else if ((rrc_sdu_length+msg4_header) <= 49) { - ((DCI1A_20MHz_FDD_t*)&RA_template[i].RA_alloc_pdu2[0])->mcs=8; + ((DCI1A_20MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->mcs=8; TBsize = 49; } else if ((rrc_sdu_length+msg4_header) <= 57) { - ((DCI1A_20MHz_FDD_t*)&RA_template[i].RA_alloc_pdu2[0])->mcs=9; + ((DCI1A_20MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->mcs=9; TBsize = 57; } - + ((DCI1A_20MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->type=1; + ((DCI1A_20MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->vrb_type=0; + ((DCI1A_20MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->rv=0; + ((DCI1A_20MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->harq_pid=0; + ((DCI1A_20MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->TPC=1; + ((DCI1A_20MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->padding=0; + ((DCI1A_20MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->rballoc= mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL,first_rb,4); + rballoc[CC_id] |= mac_xface->get_rballoc(((DCI1A_20MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->vrb_type, + ((DCI1A_20MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->rballoc); break; } } - RA_template[i].generate_Msg4=0; - RA_template[i].generate_Msg4_dci=1; - RA_template[i].wait_ack_Msg4=1; - RA_template[i].RA_active = FALSE; - lcid=0; - - if ((TBsize - rrc_sdu_length - msg4_header) <= 2) { - msg4_padding = TBsize - rrc_sdu_length - msg4_header; - msg4_post_padding = 0; - } else { - msg4_padding = 0; - msg4_post_padding = TBsize - rrc_sdu_length - msg4_header -1; - } - - LOG_I(MAC,"[eNB %d][RAPROC] CC_id %d Frame %d subframeP %d Msg4 : TBS %d, sdu_len %d, msg4_header %d, msg4_padding %d, msg4_post_padding %d\n", - module_idP,CC_id,frameP,subframeP,TBsize,rrc_sdu_length,msg4_header,msg4_padding,msg4_post_padding); - DevAssert( UE_id != UE_INDEX_INVALID ); // FIXME not sure how to gracefully return - offset = generate_dlsch_header((unsigned char*)eNB->UE_list.DLSCH_pdu[CC_id][0][(unsigned char)UE_id].payload[0], - 1, //num_sdus - (unsigned short*)&rrc_sdu_length, // - &lcid, // sdu_lcid - 255, // no drx - 0, // no timing advance - RA_template[i].cont_res_id, // contention res id - msg4_padding, // no padding - msg4_post_padding); - - memcpy((void*)&eNB->UE_list.DLSCH_pdu[CC_id][0][(unsigned char)UE_id].payload[0][(unsigned char)offset], - &eNB->common_channels[CC_id].CCCH_pdu.payload[0], - rrc_sdu_length); - - if (opt_enabled==1) { - trace_pdu(1, (uint8_t *)eNB->UE_list.DLSCH_pdu[CC_id][0][(unsigned char)UE_id].payload[0], - rrc_sdu_length, UE_id, 3, UE_RNTI(module_idP, UE_id), - eNB->subframe,0,0); - LOG_D(OPT,"[eNB %d][DLSCH] CC_id %d Frame %d trace pdu for rnti %x with size %d\n", - module_idP, CC_id, frameP, UE_RNTI(module_idP,UE_id), rrc_sdu_length); - } - - nprb[CC_id]= nprb[CC_id] + 3; - nCCE[CC_id] = nCCE[CC_id] + 4; - } + if (!CCE_allocation_infeasible(module_idP,CC_id,0,subframeP,2,RA_template->rnti)) { + add_ue_spec_dci(DCI_pdu, + (void*)&RA_template->RA_alloc_pdu2[0], + RA_template->rnti, + RA_template->RA_dci_size_bytes2, + 1, + RA_template->RA_dci_size_bits2, + RA_template->RA_dci_fmt2, + 0); + + RA_template->generate_Msg4=0; + RA_template->wait_ack_Msg4=1; + RA_template->RA_active = FALSE; + lcid=0; + + if ((TBsize - rrc_sdu_length - msg4_header) <= 2) { + msg4_padding = TBsize - rrc_sdu_length - msg4_header; + msg4_post_padding = 0; + } else { + msg4_padding = 0; + msg4_post_padding = TBsize - rrc_sdu_length - msg4_header -1; + } + + LOG_I(MAC,"[eNB %d][RAPROC] CC_id %d Frame %d subframeP %d Msg4 : TBS %d, sdu_len %d, msg4_header %d, msg4_padding %d, msg4_post_padding %d\n", + module_idP,CC_id,frameP,subframeP,TBsize,rrc_sdu_length,msg4_header,msg4_padding,msg4_post_padding); + DevAssert( UE_id != UE_INDEX_INVALID ); // FIXME not sure how to gracefully return + offset = generate_dlsch_header((unsigned char*)eNB->UE_list.DLSCH_pdu[CC_id][0][(unsigned char)UE_id].payload[0], + 1, //num_sdus + (unsigned short*)&rrc_sdu_length, // + &lcid, // sdu_lcid + 255, // no drx + 0, // no timing advance + RA_template->cont_res_id, // contention res id + msg4_padding, // no padding + msg4_post_padding); + + memcpy((void*)&eNB->UE_list.DLSCH_pdu[CC_id][0][(unsigned char)UE_id].payload[0][(unsigned char)offset], + &eNB->common_channels[CC_id].CCCH_pdu.payload[0], + rrc_sdu_length); + + if (opt_enabled==1) { + trace_pdu(1, (uint8_t *)eNB->UE_list.DLSCH_pdu[CC_id][0][(unsigned char)UE_id].payload[0], + rrc_sdu_length, UE_id, 3, UE_RNTI(module_idP, UE_id), + eNB->subframe,0,0); + LOG_D(OPT,"[eNB %d][DLSCH] CC_id %d Frame %d trace pdu for rnti %x with size %d\n", + module_idP, CC_id, frameP, UE_RNTI(module_idP,UE_id), rrc_sdu_length); + } + + nprb[CC_id]= nprb[CC_id] + 3; + } + } //try here } - /* - else if (eNB_mac_inst[module_idP][CC_id].RA_template[i].wait_ack_Msg4==1) { - // check HARQ status and retransmit if necessary - LOG_I(MAC,"[eNB %d][RAPROC] Frame %d, subframeP %d: Checking if Msg4 was acknowledged :\n",module_idP,frameP,subframeP); - // Get candidate harq_pid from PHY - mac_xface->get_ue_active_harq_pid(module_idP,eNB_mac_inst[module_idP][CC_id].RA_template[i].rnti,subframeP,&harq_pid,&round,0); - if (round>0) { - *nprb= (*nprb) + 3; - *nCCE = (*nCCE) + 4; - } - } - */ + } else if (RA_template->wait_ack_Msg4==1) { + // check HARQ status and retransmit if necessary + LOG_I(MAC,"[eNB %d][RAPROC] CC_id %d Frame %d, subframeP %d: Checking if Msg4 was acknowledged: \n", + module_idP,CC_id,frameP,subframeP); + // Get candidate harq_pid from PHY + mac_xface->get_ue_active_harq_pid(module_idP,CC_id,RA_template->rnti,frameP,subframeP,&harq_pid,&round,0); + + if (round>0) { + //RA_template->wait_ack_Msg4++; + // we have to schedule a retransmission + if (PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.frame_type == TDD) { + ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->ndi=1; + } else { + ((DCI1A_5MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->ndi=1; + } + + // randomize frequency allocation for RA + while (1) { + first_rb = (unsigned char)(taus()%(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL-4)); + + if ((vrb_map[first_rb] != 1) && (vrb_map[first_rb+3] != 1)) + break; + } + + vrb_map[first_rb] = 1; + vrb_map[first_rb+1] = 1; + vrb_map[first_rb+2] = 1; + vrb_map[first_rb+3] = 1; + + if (PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.frame_type == TDD) { + ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->rballoc = mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_UL,first_rb,4); + rballoc[CC_id] |= mac_xface->get_rballoc(((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->vrb_type, + ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->rballoc); + } else { + ((DCI1A_5MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->rballoc = mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_UL,first_rb,4); + rballoc[CC_id] |= mac_xface->get_rballoc(((DCI1A_5MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->vrb_type, + ((DCI1A_5MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->rballoc); + } + + if (!CCE_allocation_infeasible(module_idP,CC_id,0,subframeP,2,RA_template->rnti)) { + add_ue_spec_dci(DCI_pdu, + (void*)&RA_template->RA_alloc_pdu2[0], + RA_template->rnti, + RA_template->RA_dci_size_bytes2, + 2, + RA_template->RA_dci_size_bits2, + RA_template->RA_dci_fmt2, + 0); + } + LOG_W(MAC,"[eNB %d][RAPROC] CC_id %d Frame %d, subframeP %d: Msg4 not acknowledged, adding ue specific dci (rnti %x) for RA (Msg4 Retransmission)\n", + module_idP,CC_id,frameP,subframeP,RA_template->rnti); + } else { + /* msg4 not received + if ((round == 0) && (RA_template->wait_ack_Msg4>1){ + remove UE instance across all the layers: mac_xface->cancel_RA(); + } + */ + LOG_I(MAC,"[eNB %d][RAPROC] CC_id %d Frame %d, subframeP %d : Msg4 acknowledged\n",module_idP,CC_id,frameP,subframeP); + RA_template->wait_ack_Msg4=0; + RA_template->RA_active=FALSE; + UE_id = find_UE_id(module_idP,RA_template->rnti); + DevAssert( UE_id != -1 ); + eNB_mac_inst[module_idP].UE_list.UE_template[UE_PCCID(module_idP,UE_id)][UE_id].configured=TRUE; + + } } - } - } + } // for i=0 .. N_RA_PROC-1 + } // CC_id stop_meas(&eNB->schedule_ra); } diff --git a/openair2/LAYER2/MAC/eNB_scheduler_bch.c b/openair2/LAYER2/MAC/eNB_scheduler_bch.c index dd0890783e..a109e6fb5f 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_bch.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_bch.c @@ -72,9 +72,9 @@ void schedule_SI( module_id_t module_idP, frame_t frameP, - unsigned int* nprbP, - unsigned int* nCCEP -) + sub_frame_t subframeP, + unsigned int* nprbP) + //------------------------------------------------------------------------------ { @@ -85,12 +85,19 @@ schedule_SI( void *BCCH_alloc_pdu; int CC_id; eNB_MAC_INST *eNB = &eNB_mac_inst[module_idP]; + uint8_t *vrb_map; + int first_rb; + int rballoc[MAX_NUM_CCs]; + int sizeof1A_bytes,sizeof1A_bits; + DCI_PDU *DCI_pdu; start_meas(&eNB->schedule_si); for (CC_id=0; CC_idcommon_channels[CC_id].BCCH_alloc_pdu; + + BCCH_alloc_pdu = (void*)&eNB->common_channels[CC_id].BCCH_alloc_pdu; + DCI_pdu = (void*)&eNB->common_channels[CC_id].DCI_pdu; + vrb_map = (void*)&eNB->common_channels[CC_id].vrb_map; bcch_sdu_length = mac_rrc_data_req(module_idP, CC_id, @@ -104,7 +111,21 @@ schedule_SI( if (bcch_sdu_length > 0) { LOG_D(MAC,"[eNB %d] Frame %d : BCCH->DLSCH CC_id %d, Received %d bytes \n",module_idP,frameP,CC_id,bcch_sdu_length); + // Allocate 4 PRBs in a random location + while (1) { + first_rb = (unsigned char)(taus()%(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL-4)); + if ((vrb_map[first_rb] != 1) && + (vrb_map[first_rb+1] != 1) && + (vrb_map[first_rb+2] != 1) && + (vrb_map[first_rb+3] != 1)) + break; + } + vrb_map[first_rb] = 1; + vrb_map[first_rb+1] = 1; + vrb_map[first_rb+2] = 1; + vrb_map[first_rb+3] = 1; + // Get MCS for length of SI if (bcch_sdu_length <= (mac_xface->get_TBS_DL(0,3))) { mcs=0; } else if (bcch_sdu_length <= (mac_xface->get_TBS_DL(1,3))) { @@ -125,46 +146,153 @@ schedule_SI( mcs=8; } + + if (PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.frame_type == TDD) { switch (PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL) { case 6: ((DCI1A_1_5MHz_TDD_1_6_t*)BCCH_alloc_pdu)->mcs = mcs; + ((DCI1A_1_5MHz_TDD_1_6_t*)BCCH_alloc_pdu)->rballoc = mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL,first_rb,4); + ((DCI1A_1_5MHz_TDD_1_6_t*)BCCH_alloc_pdu)->type = 1; + ((DCI1A_1_5MHz_TDD_1_6_t*)BCCH_alloc_pdu)->vrb_type = 0; + ((DCI1A_1_5MHz_TDD_1_6_t*)BCCH_alloc_pdu)->ndi = 1; + ((DCI1A_1_5MHz_TDD_1_6_t*)BCCH_alloc_pdu)->rv = 1; + ((DCI1A_1_5MHz_TDD_1_6_t*)BCCH_alloc_pdu)->harq_pid = 0; + ((DCI1A_1_5MHz_TDD_1_6_t*)BCCH_alloc_pdu)->TPC = 1; + ((DCI1A_1_5MHz_TDD_1_6_t*)BCCH_alloc_pdu)->padding = 0; + rballoc[CC_id] |= mac_xface->get_rballoc(0,((DCI1A_1_5MHz_TDD_1_6_t*)BCCH_alloc_pdu)->rballoc); + sizeof1A_bytes = sizeof(DCI1A_1_5MHz_TDD_1_6_t); + sizeof1A_bits = sizeof_DCI1A_1_5MHz_TDD_1_6_t; break; case 25: ((DCI1A_5MHz_TDD_1_6_t*)BCCH_alloc_pdu)->mcs = mcs; - break; + ((DCI1A_5MHz_TDD_1_6_t*)BCCH_alloc_pdu)->rballoc = mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL,first_rb,4); + ((DCI1A_5MHz_TDD_1_6_t*)BCCH_alloc_pdu)->type = 1; + ((DCI1A_5MHz_TDD_1_6_t*)BCCH_alloc_pdu)->vrb_type = 0; + ((DCI1A_5MHz_TDD_1_6_t*)BCCH_alloc_pdu)->ndi = 1; + ((DCI1A_5MHz_TDD_1_6_t*)BCCH_alloc_pdu)->rv = 1; + ((DCI1A_5MHz_TDD_1_6_t*)BCCH_alloc_pdu)->harq_pid = 0; + ((DCI1A_5MHz_TDD_1_6_t*)BCCH_alloc_pdu)->TPC = 1; + ((DCI1A_5MHz_TDD_1_6_t*)BCCH_alloc_pdu)->padding = 0; + rballoc[CC_id] |= mac_xface->get_rballoc(0,((DCI1A_5MHz_TDD_1_6_t*)BCCH_alloc_pdu)->rballoc); + sizeof1A_bytes = sizeof(DCI1A_5MHz_TDD_1_6_t); + sizeof1A_bits = sizeof_DCI1A_5MHz_TDD_1_6_t; + break; case 50: ((DCI1A_10MHz_TDD_1_6_t*)BCCH_alloc_pdu)->mcs = mcs; + ((DCI1A_10MHz_TDD_1_6_t*)BCCH_alloc_pdu)->rballoc = mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL,first_rb,4); + ((DCI1A_10MHz_TDD_1_6_t*)BCCH_alloc_pdu)->type = 1; + ((DCI1A_10MHz_TDD_1_6_t*)BCCH_alloc_pdu)->vrb_type = 0; + ((DCI1A_10MHz_TDD_1_6_t*)BCCH_alloc_pdu)->ndi = 1; + ((DCI1A_10MHz_TDD_1_6_t*)BCCH_alloc_pdu)->rv = 1; + ((DCI1A_10MHz_TDD_1_6_t*)BCCH_alloc_pdu)->harq_pid = 0; + ((DCI1A_10MHz_TDD_1_6_t*)BCCH_alloc_pdu)->TPC = 1; + ((DCI1A_10MHz_TDD_1_6_t*)BCCH_alloc_pdu)->padding = 0; + rballoc[CC_id] |= mac_xface->get_rballoc(0,((DCI1A_10MHz_TDD_1_6_t*)BCCH_alloc_pdu)->rballoc); + sizeof1A_bytes = sizeof(DCI1A_10MHz_TDD_1_6_t); + sizeof1A_bits = sizeof_DCI1A_10MHz_TDD_1_6_t; break; case 100: ((DCI1A_20MHz_TDD_1_6_t*)BCCH_alloc_pdu)->mcs = mcs; - break; + ((DCI1A_20MHz_TDD_1_6_t*)BCCH_alloc_pdu)->rballoc = mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL,first_rb,4); + ((DCI1A_20MHz_TDD_1_6_t*)BCCH_alloc_pdu)->type = 1; + ((DCI1A_20MHz_TDD_1_6_t*)BCCH_alloc_pdu)->vrb_type = 0; + ((DCI1A_20MHz_TDD_1_6_t*)BCCH_alloc_pdu)->ndi = 1; + ((DCI1A_20MHz_TDD_1_6_t*)BCCH_alloc_pdu)->rv = 1; + ((DCI1A_20MHz_TDD_1_6_t*)BCCH_alloc_pdu)->harq_pid = 0; + ((DCI1A_20MHz_TDD_1_6_t*)BCCH_alloc_pdu)->TPC = 1; + ((DCI1A_20MHz_TDD_1_6_t*)BCCH_alloc_pdu)->padding = 0; + rballoc[CC_id] |= mac_xface->get_rballoc(0,((DCI1A_20MHz_TDD_1_6_t*)BCCH_alloc_pdu)->rballoc); + sizeof1A_bytes = sizeof(DCI1A_20MHz_TDD_1_6_t); + sizeof1A_bits = sizeof_DCI1A_20MHz_TDD_1_6_t; + break; } } else { switch (PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL) { case 6: ((DCI1A_1_5MHz_FDD_t*)BCCH_alloc_pdu)->mcs = mcs; + ((DCI1A_1_5MHz_FDD_t*)BCCH_alloc_pdu)->rballoc = mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL,first_rb,4); + ((DCI1A_1_5MHz_FDD_t*)BCCH_alloc_pdu)->type = 1; + ((DCI1A_1_5MHz_FDD_t*)BCCH_alloc_pdu)->vrb_type = 0; + ((DCI1A_1_5MHz_FDD_t*)BCCH_alloc_pdu)->ndi = 1; + ((DCI1A_1_5MHz_FDD_t*)BCCH_alloc_pdu)->rv = 1; + ((DCI1A_1_5MHz_FDD_t*)BCCH_alloc_pdu)->harq_pid = 0; + ((DCI1A_1_5MHz_FDD_t*)BCCH_alloc_pdu)->TPC = 1; + ((DCI1A_1_5MHz_FDD_t*)BCCH_alloc_pdu)->padding = 0; + + rballoc[CC_id] |= mac_xface->get_rballoc(0,((DCI1A_1_5MHz_FDD_t*)BCCH_alloc_pdu)->rballoc); + sizeof1A_bytes = sizeof(DCI1A_1_5MHz_FDD_t); + sizeof1A_bits = sizeof_DCI1A_1_5MHz_FDD_t; break; case 25: ((DCI1A_5MHz_FDD_t*)BCCH_alloc_pdu)->mcs = mcs; + ((DCI1A_5MHz_FDD_t*)BCCH_alloc_pdu)->rballoc = mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL,first_rb,4); + ((DCI1A_5MHz_FDD_t*)BCCH_alloc_pdu)->type = 1; + ((DCI1A_5MHz_FDD_t*)BCCH_alloc_pdu)->vrb_type = 0; + ((DCI1A_5MHz_FDD_t*)BCCH_alloc_pdu)->ndi = 1; + ((DCI1A_5MHz_FDD_t*)BCCH_alloc_pdu)->rv = 1; + ((DCI1A_5MHz_FDD_t*)BCCH_alloc_pdu)->harq_pid = 0; + ((DCI1A_5MHz_FDD_t*)BCCH_alloc_pdu)->TPC = 1; + ((DCI1A_5MHz_FDD_t*)BCCH_alloc_pdu)->padding = 0; + + rballoc[CC_id] |= mac_xface->get_rballoc(0,((DCI1A_5MHz_FDD_t*)BCCH_alloc_pdu)->rballoc); + sizeof1A_bytes = sizeof(DCI1A_5MHz_FDD_t); + sizeof1A_bits = sizeof_DCI1A_5MHz_FDD_t; break; case 50: ((DCI1A_10MHz_FDD_t*)BCCH_alloc_pdu)->mcs = mcs; + ((DCI1A_10MHz_FDD_t*)BCCH_alloc_pdu)->rballoc = mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL,first_rb,4); + ((DCI1A_10MHz_FDD_t*)BCCH_alloc_pdu)->type = 1; + ((DCI1A_10MHz_FDD_t*)BCCH_alloc_pdu)->vrb_type = 0; + ((DCI1A_10MHz_FDD_t*)BCCH_alloc_pdu)->ndi = 1; + ((DCI1A_10MHz_FDD_t*)BCCH_alloc_pdu)->rv = 1; + ((DCI1A_10MHz_FDD_t*)BCCH_alloc_pdu)->harq_pid = 0; + ((DCI1A_10MHz_FDD_t*)BCCH_alloc_pdu)->TPC = 1; + ((DCI1A_10MHz_FDD_t*)BCCH_alloc_pdu)->padding = 0; + + rballoc[CC_id] |= mac_xface->get_rballoc(0,((DCI1A_10MHz_FDD_t*)BCCH_alloc_pdu)->rballoc); + sizeof1A_bytes = sizeof(DCI1A_10MHz_FDD_t); + sizeof1A_bits = sizeof_DCI1A_10MHz_FDD_t; break; case 100: ((DCI1A_20MHz_FDD_t*)BCCH_alloc_pdu)->mcs = mcs; - break; + ((DCI1A_20MHz_FDD_t*)BCCH_alloc_pdu)->rballoc = mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL,first_rb,4); + ((DCI1A_20MHz_FDD_t*)BCCH_alloc_pdu)->type = 1; + ((DCI1A_20MHz_FDD_t*)BCCH_alloc_pdu)->vrb_type = 0; + ((DCI1A_20MHz_FDD_t*)BCCH_alloc_pdu)->ndi = 1; + ((DCI1A_20MHz_FDD_t*)BCCH_alloc_pdu)->rv = 1; + ((DCI1A_20MHz_FDD_t*)BCCH_alloc_pdu)->harq_pid = 0; + ((DCI1A_20MHz_FDD_t*)BCCH_alloc_pdu)->TPC = 1; + ((DCI1A_20MHz_FDD_t*)BCCH_alloc_pdu)->padding = 0; + + rballoc[CC_id] |= mac_xface->get_rballoc(0,((DCI1A_20MHz_FDD_t*)BCCH_alloc_pdu)->rballoc); + sizeof1A_bytes = sizeof(DCI1A_20MHz_FDD_t); + sizeof1A_bits = sizeof_DCI1A_20MHz_FDD_t; + break; } } + if (!CCE_allocation_infeasible(module_idP,CC_id,1,subframeP,2,SI_RNTI)) { + add_common_dci(DCI_pdu, + BCCH_alloc_pdu, + SI_RNTI, + sizeof1A_bytes, + 2, + sizeof1A_bits, + format1A,0); + } + else { + LOG_E(MAC,"[eNB %d] CCid %d Frame %d, subframe %d : Cannot add DCI 1A for SI\n",module_idP, CC_id,frameP,subframeP); + } + if (opt_enabled == 1) { trace_pdu(1, &eNB->common_channels[CC_id].BCCH_pdu.payload[0], @@ -194,17 +322,15 @@ schedule_SI( mac_xface->get_TBS_DL(mcs,3)); } - eNB->common_channels[CC_id].bcch_active=1; + nprbP[CC_id]=3; - nCCEP[CC_id]=4; eNB->eNB_stats[CC_id].total_num_bcch_pdu+=1; eNB->eNB_stats[CC_id].bcch_buffer=bcch_sdu_length; eNB->eNB_stats[CC_id].total_bcch_buffer+=bcch_sdu_length; eNB->eNB_stats[CC_id].bcch_mcs=mcs; } else { - eNB->common_channels[CC_id].bcch_active=0; + nprbP[CC_id]=0; - nCCEP[CC_id]=0; //LOG_D(MAC,"[eNB %d] Frame %d : BCCH not active \n",Mod_id,frame); } } diff --git a/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c b/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c index 3dea35f053..e3b1a96a55 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c @@ -423,7 +423,6 @@ schedule_ue_spec( frame_t frameP, sub_frame_t subframeP, unsigned int *nb_rb_used0, - unsigned int *nCCE_used, int* mbsfn_flag ) //------------------------------------------------------------------------------ @@ -431,7 +430,6 @@ schedule_ue_spec( uint8_t CC_id; int UE_id; - uint16_t nCCE[MAX_NUM_CCs]; int N_RBG[MAX_NUM_CCs]; unsigned char aggregation; mac_rlc_status_resp_t rlc_status; @@ -474,14 +472,12 @@ schedule_ue_spec( min_rb_unit[CC_id]=get_min_rb_unit(module_idP,CC_id); frame_parms[CC_id] = mac_xface->get_lte_frame_parms(module_idP,CC_id); total_nb_available_rb[CC_id] = frame_parms[CC_id]->N_RB_DL - nb_rb_used0[CC_id]; - nCCE[CC_id] = mac_xface->get_nCCE_max(module_idP,CC_id) - nCCE_used[CC_id]; N_RBG[CC_id] = frame_parms[CC_id]->N_RBG; // store the global enb stats: eNB->eNB_stats[CC_id].num_dlactive_UEs = UE_list->num_UEs; eNB->eNB_stats[CC_id].available_prbs = total_nb_available_rb[CC_id]; eNB->eNB_stats[CC_id].total_available_prbs += total_nb_available_rb[CC_id]; - eNB->eNB_stats[CC_id].available_ncces = nCCE[CC_id]; eNB->eNB_stats[CC_id].dlsch_bytes_tx=0; eNB->eNB_stats[CC_id].dlsch_pdus_tx=0; } @@ -523,9 +519,11 @@ schedule_ue_spec( continue_flag=1; } - if ((ue_sched_ctl->pre_nb_available_rbs[CC_id] == 0) || (nCCE[CC_id] < (1<pre_nb_available_rbs[CC_id] == 0) || // no RBs allocated + CCE_allocation_infeasible(module_idP,CC_id,0,subframeP,aggregation,rnti) + ) { LOG_D(MAC,"[eNB %d] Frame %d : no RB allocated for UE %d on CC_id %d: continue \n", - module_idP, frameP, UE_id, CC_id, nb_rb_used0[CC_id], ue_sched_ctl->pre_nb_available_rbs[CC_id], nCCE[CC_id], aggregation); + module_idP, frameP, UE_id, CC_id); //if(mac_xface->get_transmission_mode(module_idP,rnti)==5) continue_flag=1; //to next user (there might be rbs availiable for other UEs in TM5 // else @@ -587,11 +585,10 @@ schedule_ue_spec( UE_list->UE_template[CC_id][UE_id].rballoc_subband[harq_pid][j] = 0; } - LOG_D(MAC,"[eNB %d] Frame %d: Scheduling UE %d on CC_id %d (rnti %x, harq_pid %d, round %d, rb %d, cqi %d, mcs %d, ncc %d, rrc %d)\n", + LOG_D(MAC,"[eNB %d] Frame %d: Scheduling UE %d on CC_id %d (rnti %x, harq_pid %d, round %d, rb %d, cqi %d, mcs %d, rrc %d)\n", module_idP, frameP, UE_id,CC_id,rnti,harq_pid, round,nb_available_rb, eNB_UE_stats->DL_cqi[0], eNB_UE_stats->dlsch_mcs1, - nCCE[CC_id], - UE_list->eNB_UE_stats[CC_id][UE_id].rrc_status); + UE_list->eNB_UE_stats[CC_id][UE_id].rrc_status); // Note this code is for a specific DCI format @@ -641,8 +638,6 @@ schedule_ue_spec( nb_available_rb -= nb_rb; aggregation = process_ue_cqi(module_idP,UE_id); - nCCE[CC_id]-=(1<mu_mimo_mode[UE_id].pre_nb_available_rbs = nb_rb; @@ -789,7 +784,6 @@ schedule_ue_spec( UE_list->eNB_UE_stats[CC_id][UE_id].num_retransmission+=1; UE_list->eNB_UE_stats[CC_id][UE_id].rbs_used_retx=nb_rb; UE_list->eNB_UE_stats[CC_id][UE_id].total_rbs_used_retx+=nb_rb; - UE_list->eNB_UE_stats[CC_id][UE_id].ncce_used_retx=nCCE[CC_id]; UE_list->eNB_UE_stats[CC_id][UE_id].dlsch_mcs1=eNB_UE_stats->dlsch_mcs1; UE_list->eNB_UE_stats[CC_id][UE_id].dlsch_mcs2=eNB_UE_stats->dlsch_mcs1; } else { @@ -1130,8 +1124,6 @@ schedule_ue_spec( } aggregation = process_ue_cqi(module_idP,UE_id); - nCCE[CC_id]-=(1<UE_template[CC_id][UE_id].nb_rb[harq_pid] = nb_rb; add_ue_dlsch_info(module_idP, @@ -1145,7 +1137,6 @@ schedule_ue_spec( UE_list->eNB_UE_stats[CC_id][UE_id].rbs_used = nb_rb; UE_list->eNB_UE_stats[CC_id][UE_id].total_rbs_used += nb_rb; - UE_list->eNB_UE_stats[CC_id][UE_id].ncce_used = nCCE[CC_id]; UE_list->eNB_UE_stats[CC_id][UE_id].dlsch_mcs1=eNB_UE_stats->dlsch_mcs1; UE_list->eNB_UE_stats[CC_id][UE_id].dlsch_mcs2=mcs; UE_list->eNB_UE_stats[CC_id][UE_id].TBS = TBS; @@ -1498,10 +1489,9 @@ schedule_ue_spec( if (frame_parms[CC_id]->frame_type == TDD) { set_ul_DAI(module_idP,UE_id,CC_id,frameP,subframeP,frame_parms); } - } - } - //printf("MAC nCCE : %d\n",*nCCE_used); + } // UE_id loop + } // CC_id loop stop_meas(&eNB->schedule_dlsch); @@ -1512,13 +1502,12 @@ schedule_ue_spec( //------------------------------------------------------------------------------ void fill_DLSCH_dci( - module_id_t module_idP, - frame_t frameP, - sub_frame_t subframeP, - uint32_t* RBallocP, - uint8_t RA_scheduledP, - int* mbsfn_flagP -) + module_id_t module_idP, + frame_t frameP, + sub_frame_t subframeP, + uint32_t* RBallocP, + int* mbsfn_flagP + ) //------------------------------------------------------------------------------ { @@ -1526,7 +1515,7 @@ fill_DLSCH_dci( int UE_id = -1; uint8_t first_rb,nb_rb=3; rnti_t rnti; - unsigned char vrb_map[100]; + unsigned char *vrb_map; uint8_t rballoc_sub[25]; //uint8_t number_of_subbands=13; uint32_t *rballoc=RBallocP; @@ -1552,598 +1541,8 @@ fill_DLSCH_dci( if (mbsfn_flagP[CC_id]>0) continue; - DCI_pdu = &eNB->common_channels[CC_id].DCI_pdu; - BCCH_alloc_pdu=(void*)&eNB->common_channels[CC_id].BCCH_alloc_pdu; - // clear vrb_map - memset(vrb_map,0,100); - - - // SI DLSCH - // printf("BCCH check\n"); - if (eNB->common_channels[CC_id].bcch_active == 1) { - eNB->common_channels[CC_id].bcch_active = 0; - LOG_D(MAC,"[eNB %d] CC_id %d Frame %d subframeP %d: BCCH active\n", module_idP, CC_id, frameP, subframeP); - // randomize frequency allocation for SI - first_rb = 0;//10;//(unsigned char)(taus()%(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL-4)); - - /* Where is this from, should be removed!!!! - - if (PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.frame_type == TDD) { - - } - else { - BCCH_alloc_pdu_fdd.rballoc = mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL,first_rb,4); - rballoc[CC_id] |= mac_xface->get_rballoc(BCCH_alloc_pdu_fdd.vrb_type,BCCH_alloc_pdu_fdd.rballoc); - } - */ - - - vrb_map[first_rb] = 1; - vrb_map[first_rb+1] = 1; - vrb_map[first_rb+2] = 1; - vrb_map[first_rb+3] = 1; - - if (PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.frame_type == TDD) { - switch (PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL) { - case 6: - ((DCI1A_1_5MHz_TDD_1_6_t*)BCCH_alloc_pdu)->rballoc = mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL,first_rb,4); - ((DCI1A_1_5MHz_TDD_1_6_t*)BCCH_alloc_pdu)->type = 1; - ((DCI1A_1_5MHz_TDD_1_6_t*)BCCH_alloc_pdu)->vrb_type = 0; - ((DCI1A_1_5MHz_TDD_1_6_t*)BCCH_alloc_pdu)->ndi = 1; - ((DCI1A_1_5MHz_TDD_1_6_t*)BCCH_alloc_pdu)->rv = 1; - ((DCI1A_1_5MHz_TDD_1_6_t*)BCCH_alloc_pdu)->harq_pid = 0; - ((DCI1A_1_5MHz_TDD_1_6_t*)BCCH_alloc_pdu)->TPC = 1; - ((DCI1A_1_5MHz_TDD_1_6_t*)BCCH_alloc_pdu)->padding = 0; - rballoc[CC_id] |= mac_xface->get_rballoc(0,((DCI1A_1_5MHz_TDD_1_6_t*)BCCH_alloc_pdu)->rballoc); - add_common_dci(DCI_pdu, - BCCH_alloc_pdu, - SI_RNTI, - sizeof(DCI1A_1_5MHz_TDD_1_6_t), - 2, - sizeof_DCI1A_1_5MHz_TDD_1_6_t, - format1A,0); - break; - - case 25: - ((DCI1A_5MHz_TDD_1_6_t*)BCCH_alloc_pdu)->rballoc = mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL,first_rb,4); - ((DCI1A_5MHz_TDD_1_6_t*)BCCH_alloc_pdu)->type = 1; - ((DCI1A_5MHz_TDD_1_6_t*)BCCH_alloc_pdu)->vrb_type = 0; - ((DCI1A_5MHz_TDD_1_6_t*)BCCH_alloc_pdu)->ndi = 1; - ((DCI1A_5MHz_TDD_1_6_t*)BCCH_alloc_pdu)->rv = 1; - ((DCI1A_5MHz_TDD_1_6_t*)BCCH_alloc_pdu)->harq_pid = 0; - ((DCI1A_5MHz_TDD_1_6_t*)BCCH_alloc_pdu)->TPC = 1; - ((DCI1A_5MHz_TDD_1_6_t*)BCCH_alloc_pdu)->padding = 0; - rballoc[CC_id] |= mac_xface->get_rballoc(0,((DCI1A_5MHz_TDD_1_6_t*)BCCH_alloc_pdu)->rballoc); - add_common_dci(DCI_pdu, - BCCH_alloc_pdu, - SI_RNTI, - sizeof(DCI1A_5MHz_TDD_1_6_t), - 2, - sizeof_DCI1A_5MHz_TDD_1_6_t, - format1A,0); - break; - - case 50: - ((DCI1A_10MHz_TDD_1_6_t*)BCCH_alloc_pdu)->rballoc = mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL,first_rb,4); - ((DCI1A_10MHz_TDD_1_6_t*)BCCH_alloc_pdu)->type = 1; - ((DCI1A_10MHz_TDD_1_6_t*)BCCH_alloc_pdu)->vrb_type = 0; - ((DCI1A_10MHz_TDD_1_6_t*)BCCH_alloc_pdu)->ndi = 1; - ((DCI1A_10MHz_TDD_1_6_t*)BCCH_alloc_pdu)->rv = 1; - ((DCI1A_10MHz_TDD_1_6_t*)BCCH_alloc_pdu)->harq_pid = 0; - ((DCI1A_10MHz_TDD_1_6_t*)BCCH_alloc_pdu)->TPC = 1; - ((DCI1A_10MHz_TDD_1_6_t*)BCCH_alloc_pdu)->padding = 0; - rballoc[CC_id] |= mac_xface->get_rballoc(0,((DCI1A_10MHz_TDD_1_6_t*)BCCH_alloc_pdu)->rballoc); - add_common_dci(DCI_pdu, - BCCH_alloc_pdu, - SI_RNTI, - sizeof(DCI1A_10MHz_TDD_1_6_t), - 2, - sizeof_DCI1A_10MHz_TDD_1_6_t, - format1A,0); - break; - - case 100: - ((DCI1A_20MHz_TDD_1_6_t*)BCCH_alloc_pdu)->rballoc = mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL,first_rb,4); - ((DCI1A_20MHz_TDD_1_6_t*)BCCH_alloc_pdu)->type = 1; - ((DCI1A_20MHz_TDD_1_6_t*)BCCH_alloc_pdu)->vrb_type = 0; - ((DCI1A_20MHz_TDD_1_6_t*)BCCH_alloc_pdu)->ndi = 1; - ((DCI1A_20MHz_TDD_1_6_t*)BCCH_alloc_pdu)->rv = 1; - ((DCI1A_20MHz_TDD_1_6_t*)BCCH_alloc_pdu)->harq_pid = 0; - ((DCI1A_20MHz_TDD_1_6_t*)BCCH_alloc_pdu)->TPC = 1; - ((DCI1A_20MHz_TDD_1_6_t*)BCCH_alloc_pdu)->padding = 0; - rballoc[CC_id] |= mac_xface->get_rballoc(0,((DCI1A_20MHz_TDD_1_6_t*)BCCH_alloc_pdu)->rballoc); - add_common_dci(DCI_pdu, - BCCH_alloc_pdu, - SI_RNTI, - sizeof(DCI1A_20MHz_TDD_1_6_t), - 2, - sizeof_DCI1A_20MHz_TDD_1_6_t, - format1A,0); - break; - } - } else { - switch (PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL) { - case 6: - ((DCI1A_1_5MHz_FDD_t*)BCCH_alloc_pdu)->rballoc = mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL,first_rb,4); - ((DCI1A_1_5MHz_FDD_t*)BCCH_alloc_pdu)->type = 1; - ((DCI1A_1_5MHz_FDD_t*)BCCH_alloc_pdu)->vrb_type = 0; - ((DCI1A_1_5MHz_FDD_t*)BCCH_alloc_pdu)->ndi = 1; - ((DCI1A_1_5MHz_FDD_t*)BCCH_alloc_pdu)->rv = 1; - ((DCI1A_1_5MHz_FDD_t*)BCCH_alloc_pdu)->harq_pid = 0; - ((DCI1A_1_5MHz_FDD_t*)BCCH_alloc_pdu)->TPC = 1; - ((DCI1A_1_5MHz_FDD_t*)BCCH_alloc_pdu)->padding = 0; - - rballoc[CC_id] |= mac_xface->get_rballoc(0,((DCI1A_1_5MHz_FDD_t*)BCCH_alloc_pdu)->rballoc); - add_common_dci(DCI_pdu, - BCCH_alloc_pdu, - SI_RNTI, - sizeof(DCI1A_1_5MHz_FDD_t), - 2, - sizeof_DCI1A_1_5MHz_FDD_t, - format1A,0); - break; - - case 25: - ((DCI1A_5MHz_FDD_t*)BCCH_alloc_pdu)->rballoc = mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL,first_rb,4); - ((DCI1A_5MHz_FDD_t*)BCCH_alloc_pdu)->type = 1; - ((DCI1A_5MHz_FDD_t*)BCCH_alloc_pdu)->vrb_type = 0; - ((DCI1A_5MHz_FDD_t*)BCCH_alloc_pdu)->ndi = 1; - ((DCI1A_5MHz_FDD_t*)BCCH_alloc_pdu)->rv = 1; - ((DCI1A_5MHz_FDD_t*)BCCH_alloc_pdu)->harq_pid = 0; - ((DCI1A_5MHz_FDD_t*)BCCH_alloc_pdu)->TPC = 1; - ((DCI1A_5MHz_FDD_t*)BCCH_alloc_pdu)->padding = 0; - - rballoc[CC_id] |= mac_xface->get_rballoc(0,((DCI1A_5MHz_FDD_t*)BCCH_alloc_pdu)->rballoc); - add_common_dci(DCI_pdu, - BCCH_alloc_pdu, - SI_RNTI, - sizeof(DCI1A_5MHz_FDD_t), - 2, - sizeof_DCI1A_5MHz_FDD_t, - format1A,0); - break; - - case 50: - ((DCI1A_10MHz_FDD_t*)BCCH_alloc_pdu)->rballoc = mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL,first_rb,4); - ((DCI1A_10MHz_FDD_t*)BCCH_alloc_pdu)->type = 1; - ((DCI1A_10MHz_FDD_t*)BCCH_alloc_pdu)->vrb_type = 0; - ((DCI1A_10MHz_FDD_t*)BCCH_alloc_pdu)->ndi = 1; - ((DCI1A_10MHz_FDD_t*)BCCH_alloc_pdu)->rv = 1; - ((DCI1A_10MHz_FDD_t*)BCCH_alloc_pdu)->harq_pid = 0; - ((DCI1A_10MHz_FDD_t*)BCCH_alloc_pdu)->TPC = 1; - ((DCI1A_10MHz_FDD_t*)BCCH_alloc_pdu)->padding = 0; - - rballoc[CC_id] |= mac_xface->get_rballoc(0,((DCI1A_10MHz_FDD_t*)BCCH_alloc_pdu)->rballoc); - add_common_dci(DCI_pdu, - BCCH_alloc_pdu, - SI_RNTI, - sizeof(DCI1A_10MHz_FDD_t), - 2, - sizeof_DCI1A_10MHz_FDD_t, - format1A,0); - break; - - case 100: - ((DCI1A_20MHz_FDD_t*)BCCH_alloc_pdu)->rballoc = mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL,first_rb,4); - ((DCI1A_20MHz_FDD_t*)BCCH_alloc_pdu)->type = 1; - ((DCI1A_20MHz_FDD_t*)BCCH_alloc_pdu)->vrb_type = 0; - ((DCI1A_20MHz_FDD_t*)BCCH_alloc_pdu)->ndi = 1; - ((DCI1A_20MHz_FDD_t*)BCCH_alloc_pdu)->rv = 1; - ((DCI1A_20MHz_FDD_t*)BCCH_alloc_pdu)->harq_pid = 0; - ((DCI1A_20MHz_FDD_t*)BCCH_alloc_pdu)->TPC = 1; - ((DCI1A_20MHz_FDD_t*)BCCH_alloc_pdu)->padding = 0; - - rballoc[CC_id] |= mac_xface->get_rballoc(0,((DCI1A_20MHz_FDD_t*)BCCH_alloc_pdu)->rballoc); - add_common_dci(DCI_pdu, - BCCH_alloc_pdu, - SI_RNTI, - sizeof(DCI1A_20MHz_FDD_t), - 2, - sizeof_DCI1A_20MHz_FDD_t, - format1A,0); - break; - } - } - } - - if (RA_scheduledP == 1) { - for (i=0; icommon_channels[CC_id].RA_template[i]; - - if (RA_template->generate_rar == 1) { - - //FK: postponed to fill_rar - //RA_template->generate_rar = 0; - - LOG_D(MAC,"[eNB %d] CC_id %d Frame %d, subframeP %d: Generating RAR DCI (proc %d), RA_active %d format 1A (%d,%d))\n", - module_idP, CC_id, frameP, subframeP,i, - RA_template->RA_active, - RA_template->RA_dci_fmt1, - RA_template->RA_dci_size_bits1); - - // randomize frequency allocation for RA - while (1) { - first_rb = (unsigned char)(taus()%(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL-4)); - - if ((vrb_map[first_rb] != 1) && (vrb_map[first_rb+3] != 1)) - break; - } - - vrb_map[first_rb] = 1; - vrb_map[first_rb+1] = 1; - vrb_map[first_rb+2] = 1; - vrb_map[first_rb+3] = 1; - - if (PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.frame_type == TDD) { - switch(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL) { - case 6: - ((DCI1A_1_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->type=1; - ((DCI1A_1_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->vrb_type=0; - ((DCI1A_1_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->ndi=1; - ((DCI1A_1_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->rv=0; - ((DCI1A_1_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->mcs=0; - ((DCI1A_1_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->harq_pid=0; - ((DCI1A_1_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->TPC=1; - ((DCI1A_1_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->padding=0; - ((DCI1A_1_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->rballoc = mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL,first_rb,4); - rballoc[CC_id] |= mac_xface->get_rballoc(((DCI1A_1_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->vrb_type, - ((DCI1A_1_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->rballoc); - break; - - case 25: - ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->type=1; - ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->vrb_type=0; - ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->ndi=1; - ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->rv=0; - ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->mcs=0; - ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->harq_pid=0; - ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->TPC=1; - ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->padding=0; - ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->rballoc = mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL,first_rb,4); - rballoc[CC_id] |= mac_xface->get_rballoc(((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->vrb_type, - ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->rballoc); - break; - - case 50: - ((DCI1A_10MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->type=1; - ((DCI1A_10MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->vrb_type=0; - ((DCI1A_10MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->ndi=1; - ((DCI1A_10MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->rv=0; - ((DCI1A_10MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->mcs=0; - ((DCI1A_10MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->harq_pid=0; - ((DCI1A_10MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->TPC=1; - ((DCI1A_10MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->padding=0; - ((DCI1A_10MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->rballoc = mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL,first_rb,4); - rballoc[CC_id] |= mac_xface->get_rballoc(((DCI1A_10MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->vrb_type, - ((DCI1A_10MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->rballoc); - break; - - case 100: - ((DCI1A_20MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->type=1; - ((DCI1A_20MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->vrb_type=0; - ((DCI1A_20MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->ndi=1; - ((DCI1A_20MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->rv=0; - ((DCI1A_20MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->mcs=0; - ((DCI1A_20MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->harq_pid=0; - ((DCI1A_20MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->TPC=1; - ((DCI1A_20MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->padding=0; - ((DCI1A_20MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->rballoc = mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL,first_rb,4); - rballoc[CC_id] |= mac_xface->get_rballoc(((DCI1A_20MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->vrb_type, - ((DCI1A_20MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->rballoc); - break; - - default: - ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->type=1; - ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->vrb_type=0; - ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->ndi=1; - ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->rv=0; - ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->mcs=0; - ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->harq_pid=0; - ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->TPC=1; - ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->padding=0; - ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->rballoc = mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL,first_rb,4); - rballoc[CC_id] |= mac_xface->get_rballoc(((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->vrb_type, - ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->rballoc); - break; - } - } else { - switch(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL) { - case 6: - ((DCI1A_1_5MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->type=1; - ((DCI1A_1_5MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->vrb_type=0; - ((DCI1A_1_5MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->ndi=1; - ((DCI1A_1_5MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->rv=0; - ((DCI1A_1_5MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->mcs=0; - ((DCI1A_1_5MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->harq_pid=0; - ((DCI1A_1_5MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->TPC=1; - ((DCI1A_1_5MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->padding=0; - ((DCI1A_1_5MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->rballoc = mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL,first_rb,4); - rballoc[CC_id] |= mac_xface->get_rballoc(((DCI1A_1_5MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->vrb_type, - ((DCI1A_1_5MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->rballoc); - break; - - case 25: - ((DCI1A_5MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->type=1; - ((DCI1A_5MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->vrb_type=0; - ((DCI1A_5MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->ndi=1; - ((DCI1A_5MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->rv=0; - ((DCI1A_5MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->mcs=0; - ((DCI1A_5MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->harq_pid=0; - ((DCI1A_5MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->TPC=1; - ((DCI1A_5MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->padding=0; - ((DCI1A_5MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->rballoc = mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_UL,first_rb,4); - rballoc[CC_id] |= mac_xface->get_rballoc(((DCI1A_5MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->vrb_type, - ((DCI1A_5MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->rballoc); - break; - - case 50: - ((DCI1A_10MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->type=1; - ((DCI1A_10MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->vrb_type=0; - ((DCI1A_10MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->ndi=1; - ((DCI1A_10MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->rv=0; - ((DCI1A_10MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->mcs=0; - ((DCI1A_10MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->harq_pid=0; - ((DCI1A_10MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->TPC=1; - ((DCI1A_10MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->padding=0; - ((DCI1A_10MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->rballoc = mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL,first_rb,4); - rballoc[CC_id] |= mac_xface->get_rballoc(((DCI1A_10MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->vrb_type, - ((DCI1A_10MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->rballoc); - break; - - case 100: - ((DCI1A_20MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->type=1; - ((DCI1A_20MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->vrb_type=0; - ((DCI1A_20MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->ndi=1; - ((DCI1A_20MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->rv=0; - ((DCI1A_20MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->mcs=0; - ((DCI1A_20MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->harq_pid=0; - ((DCI1A_20MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->TPC=1; - ((DCI1A_20MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->padding=0; - ((DCI1A_20MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->rballoc = mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL,first_rb,4); - rballoc[CC_id] |= mac_xface->get_rballoc(((DCI1A_20MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->vrb_type, - ((DCI1A_20MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->rballoc); - break; - - default: - break; - } - } - - add_common_dci(DCI_pdu, - (void*)&RA_template->RA_alloc_pdu1[0], - RA_template->RA_rnti, - RA_template->RA_dci_size_bytes1, - 2, - RA_template->RA_dci_size_bits1, - RA_template->RA_dci_fmt1, - 1); - - - - LOG_D(MAC,"[eNB %d] CC_id %d Frame %d: Adding common dci for RA%d (RAR) RA_active %d\n", - module_idP,CC_id,frameP,i, RA_template->RA_active); - } - - if (RA_template->generate_Msg4_dci == 1) { - - // randomize frequency allocation for RA - while (1) { - first_rb = (unsigned char)(taus()%(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL-4)); - - if ((vrb_map[first_rb] != 1) && (vrb_map[first_rb+3] != 1)) - break; - } - - vrb_map[first_rb] = 1; - vrb_map[first_rb+1] = 1; - vrb_map[first_rb+2] = 1; - vrb_map[first_rb+3] = 1; - - if (PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.frame_type == TDD) { - switch (PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL) { - case 6: - ((DCI1A_1_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->type=1; - ((DCI1A_1_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->vrb_type=0; - ((DCI1A_1_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->rv=0; - ((DCI1A_1_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->harq_pid=0; - ((DCI1A_1_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->TPC=1; - ((DCI1A_1_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->padding=0; - ((DCI1A_1_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->rballoc= mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL,first_rb,4); - rballoc[CC_id] |= mac_xface->get_rballoc(((DCI1A_1_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->vrb_type, - ((DCI1A_1_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->rballoc); - break; - - case 25: - ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->type=1; - ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->vrb_type=0; - ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->rv=0; - ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->harq_pid=0; - ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->TPC=1; - ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->padding=0; - ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->rballoc= mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL,first_rb,4); - rballoc[CC_id] |= mac_xface->get_rballoc(((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->vrb_type, - ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->rballoc); - break; - - case 50: - ((DCI1A_10MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->type=1; - ((DCI1A_10MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->vrb_type=0; - ((DCI1A_10MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->rv=0; - ((DCI1A_10MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->harq_pid=0; - ((DCI1A_10MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->TPC=1; - ((DCI1A_10MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->padding=0; - ((DCI1A_10MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->rballoc= mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL,first_rb,4); - rballoc[CC_id] |= mac_xface->get_rballoc(((DCI1A_10MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->vrb_type, - ((DCI1A_10MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->rballoc); - break; - - case 100: - ((DCI1A_20MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->type=1; - ((DCI1A_20MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->vrb_type=0; - ((DCI1A_20MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->rv=0; - ((DCI1A_20MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->harq_pid=0; - ((DCI1A_20MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->TPC=1; - ((DCI1A_20MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->rballoc= mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL,first_rb,4); - rballoc[CC_id] |= mac_xface->get_rballoc(((DCI1A_20MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->vrb_type, - ((DCI1A_20MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->rballoc); - break; - - default: - ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->type=1; - ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->vrb_type=0; - ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->rv=0; - ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->harq_pid=0; - ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->TPC=1; - ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->padding=0; - ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->rballoc= mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL,first_rb,4); - rballoc[CC_id] |= mac_xface->get_rballoc(((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->vrb_type, - ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->rballoc); - break; - } - } else { - switch (PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL) { - - case 6: - ((DCI1A_1_5MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->type=1; - ((DCI1A_1_5MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->vrb_type=0; - ((DCI1A_1_5MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->rv=0; - ((DCI1A_1_5MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->harq_pid=0; - ((DCI1A_1_5MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->TPC=1; - ((DCI1A_1_5MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->padding=0; - ((DCI1A_1_5MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->rballoc= mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL,first_rb,4); - rballoc[CC_id] |= mac_xface->get_rballoc(((DCI1A_1_5MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->vrb_type, - ((DCI1A_1_5MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->rballoc); - break; - - case 25: - ((DCI1A_5MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->type=1; - ((DCI1A_5MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->vrb_type=0; - ((DCI1A_5MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->rv=0; - ((DCI1A_5MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->harq_pid=0; - ((DCI1A_5MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->TPC=1; - ((DCI1A_5MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->padding=0; - ((DCI1A_5MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->rballoc= mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL,first_rb,4); - rballoc[CC_id] |= mac_xface->get_rballoc(((DCI1A_5MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->vrb_type, - ((DCI1A_5MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->rballoc); - break; - - case 50: - ((DCI1A_10MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->type=1; - ((DCI1A_10MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->vrb_type=0; - ((DCI1A_10MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->rv=0; - ((DCI1A_10MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->harq_pid=0; - ((DCI1A_10MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->TPC=1; - ((DCI1A_10MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->padding=0; - ((DCI1A_10MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->rballoc= mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL,first_rb,4); - rballoc[CC_id] |= mac_xface->get_rballoc(((DCI1A_10MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->vrb_type, - ((DCI1A_10MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->rballoc); - break; - - case 100: - ((DCI1A_20MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->type=1; - ((DCI1A_20MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->vrb_type=0; - ((DCI1A_20MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->rv=0; - ((DCI1A_20MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->harq_pid=0; - ((DCI1A_20MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->TPC=1; - ((DCI1A_20MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->padding=0; - ((DCI1A_20MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->rballoc= mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL,first_rb,4); - rballoc[CC_id] |= mac_xface->get_rballoc(((DCI1A_20MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->vrb_type, - ((DCI1A_20MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->rballoc); - break; - - default: - ((DCI1A_5MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->type=1; - ((DCI1A_5MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->vrb_type=0; - ((DCI1A_5MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->rv=0; - ((DCI1A_5MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->harq_pid=0; - ((DCI1A_5MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->TPC=1; - ((DCI1A_5MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->rballoc= mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL,first_rb,4); - rballoc[CC_id] |= mac_xface->get_rballoc(((DCI1A_5MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->vrb_type, - ((DCI1A_5MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->rballoc); - break; - } - } - - add_ue_spec_dci(DCI_pdu, - (void*)&RA_template->RA_alloc_pdu2[0], - RA_template->rnti, - RA_template->RA_dci_size_bytes2, - 1, - RA_template->RA_dci_size_bits2, - RA_template->RA_dci_fmt2, - 0); - LOG_D(MAC,"[eNB %d][RAPROC] CC_id %d Frame %d, subframeP %d: Adding ue specific dci (rnti %x) for Msg4\n", - module_idP,CC_id,frameP,subframeP,RA_template->rnti); - RA_template->generate_Msg4_dci=0; - - } else if (RA_template->wait_ack_Msg4==1) { - // check HARQ status and retransmit if necessary - LOG_I(MAC,"[eNB %d][RAPROC] CC_id %d Frame %d, subframeP %d: Checking if Msg4 was acknowledged: \n", - module_idP,CC_id,frameP,subframeP); - // Get candidate harq_pid from PHY - mac_xface->get_ue_active_harq_pid(module_idP,CC_id,RA_template->rnti,frameP,subframeP,&harq_pid,&round,0); - - if (round>0) { - //RA_template->wait_ack_Msg4++; - // we have to schedule a retransmission - if (PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.frame_type == TDD) { - ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->ndi=1; - } else { - ((DCI1A_5MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->ndi=1; - } - - // randomize frequency allocation for RA - while (1) { - first_rb = (unsigned char)(taus()%(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL-4)); - - if ((vrb_map[first_rb] != 1) && (vrb_map[first_rb+3] != 1)) - break; - } - - vrb_map[first_rb] = 1; - vrb_map[first_rb+1] = 1; - vrb_map[first_rb+2] = 1; - vrb_map[first_rb+3] = 1; - - if (PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.frame_type == TDD) { - ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->rballoc = mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_UL,first_rb,4); - rballoc[CC_id] |= mac_xface->get_rballoc(((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->vrb_type, - ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->rballoc); - } else { - ((DCI1A_5MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->rballoc = mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_UL,first_rb,4); - rballoc[CC_id] |= mac_xface->get_rballoc(((DCI1A_5MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->vrb_type, - ((DCI1A_5MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->rballoc); - } - - add_ue_spec_dci(DCI_pdu, - (void*)&RA_template->RA_alloc_pdu2[0], - RA_template->rnti, - RA_template->RA_dci_size_bytes2, - 2, - RA_template->RA_dci_size_bits2, - RA_template->RA_dci_fmt2, - 0); - LOG_W(MAC,"[eNB %d][RAPROC] CC_id %d Frame %d, subframeP %d: Msg4 not acknowledged, adding ue specific dci (rnti %x) for RA (Msg4 Retransmission)\n", - module_idP,CC_id,frameP,subframeP,RA_template->rnti); - } else { - /* msg4 not received - if ((round == 0) && (RA_template->wait_ack_Msg4>1){ - remove UE instance across all the layers: mac_xface->cancel_RA(); - } - */ - LOG_I(MAC,"[eNB %d][RAPROC] CC_id %d Frame %d, subframeP %d : Msg4 acknowledged\n",module_idP,CC_id,frameP,subframeP); - RA_template->wait_ack_Msg4=0; - RA_template->RA_active=FALSE; - UE_id = find_UE_id(module_idP,RA_template->rnti); - DevAssert( UE_id != -1 ); - eNB_mac_inst[module_idP].UE_list.UE_template[UE_PCCID(module_idP,UE_id)][UE_id].configured=TRUE; - - } - } - } - } // RA is scheduled in this subframeP - + DCI_pdu = &eNB->common_channels[CC_id].DCI_pdu; + // UE specific DCIs for (UE_id=UE_list->head; UE_id>=0; UE_id=UE_list->next[UE_id]) { diff --git a/openair2/LAYER2/MAC/eNB_scheduler_primitives.c b/openair2/LAYER2/MAC/eNB_scheduler_primitives.c index 34169d902e..da2e5f311e 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_primitives.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_primitives.c @@ -879,3 +879,208 @@ int get_nb_subband(void) return nb_sb; } + +void init_CCE_table(int module_idP,int CC_idP) +{ + memset(eNB_mac_inst[module_idP].CCE_table[CC_idP],0,800*sizeof(int)); +} + + +int get_nCCE_offset(int *CCE_table, + const unsigned char L, + const int nCCE, + const int common_dci, + const unsigned short rnti, + const unsigned char subframe) +{ + + int search_space_free,m,nb_candidates = 0,l,i; + unsigned int Yk; + /* + printf("CCE Allocation: "); + for (i=0;i=0 ; m--) { + + search_space_free = 1; + for (l=0; lget_nCCE_max(module_idP,CC_idP,DCI_pdu->num_pdcch_symbols,subframeP); + int fCCE; + int i; + int allocation_is_feasible = 1; + DCI_ALLOC_t *dci_alloc; + + LOG_I(MAC,"Allocate CCEs subframe %d, test %d\n",subframeP,test_onlyP); + init_CCE_table(module_idP,CC_idP); + DCI_pdu->nCCE=0; + + while (allocation_is_feasible == 1) { + + for (i=0;iNum_common_dci + DCI_pdu->Num_ue_spec_dci;i++) { + dci_alloc = &DCI_pdu->dci_alloc[i]; + LOG_I(MAC,"Trying to allocate DCI %d/%d (%d,%d) : rnti %x, aggreg %d nCCE %d / %d (num_pdcch_symbols %d)\n", + i,DCI_pdu->Num_common_dci+DCI_pdu->Num_ue_spec_dci, + DCI_pdu->Num_common_dci,DCI_pdu->Num_ue_spec_dci, + dci_alloc->rnti,1<L, + DCI_pdu->nCCE,nCCE_max,DCI_pdu->num_pdcch_symbols); + + if (DCI_pdu->nCCE + (1<L) > nCCE_max) { + if (DCI_pdu->num_pdcch_symbols == 3) + allocation_is_feasible = 0; + else { + DCI_pdu->num_pdcch_symbols++; + nCCE_max = mac_xface->get_nCCE_max(module_idP,CC_idP,DCI_pdu->num_pdcch_symbols,subframeP); + } + break; + } + else { // number of CCEs left can potentially hold this allocation + if ((fCCE = get_nCCE_offset(CCE_table, + 1<<(dci_alloc->L), + nCCE_max, + (iNum_common_dci) ? 1 : 0, + dci_alloc->rnti, + subframeP))>=0) {// the allocation is feasible, rnti rule passes + LOG_I(MAC,"Allocating at nCCE %d\n",fCCE); + if (test_onlyP == 0) { + DCI_pdu->nCCE += (1<L); + dci_alloc->firstCCE=fCCE; + LOG_I(MAC,"Allocate CCEs subframe %d, test %d\n",subframeP,test_onlyP); + } + } // fCCE>=0 + else { + if (DCI_pdu->num_pdcch_symbols == 3) + allocation_is_feasible = 0; + else { + DCI_pdu->num_pdcch_symbols++; + nCCE_max = mac_xface->get_nCCE_max(module_idP,CC_idP,DCI_pdu->num_pdcch_symbols,subframeP); + } + break; + } // fCCE==-1 + } // nCCE <= nCCE_max + } // for i = 0 ... num_dcis + if (allocation_is_feasible==1) + return (0); + } // allocation_is_feasible == 1 + + return(-1); + + +} + +boolean_t CCE_allocation_infeasible(int module_idP, + int CC_idP, + int common_flag, + int subframe, + int aggregation, + int rnti) { + + + DCI_PDU *DCI_pdu = &eNB_mac_inst[module_idP].common_channels[CC_idP].DCI_pdu; + DCI_ALLOC_t *dci_alloc; + int ret; + boolean_t res=FALSE; + + if (common_flag==1) { + DCI_pdu->dci_alloc[DCI_pdu->Num_common_dci + DCI_pdu->Num_ue_spec_dci].rnti = rnti; + DCI_pdu->dci_alloc[DCI_pdu->Num_common_dci + DCI_pdu->Num_ue_spec_dci].L = aggregation; + DCI_pdu->Num_common_dci++; + ret = allocate_CCEs(module_idP,CC_idP,subframe,1); + if (ret==-1) + res = TRUE; + DCI_pdu->Num_common_dci--; + } + else { + DCI_pdu->dci_alloc[DCI_pdu->Num_common_dci + DCI_pdu->Num_ue_spec_dci].rnti = rnti; + DCI_pdu->dci_alloc[DCI_pdu->Num_common_dci + DCI_pdu->Num_ue_spec_dci].L = aggregation; + DCI_pdu->Num_ue_spec_dci++; + ret = allocate_CCEs(module_idP,CC_idP,subframe,1); + if (ret==-1) + res = FALSE; + DCI_pdu->Num_ue_spec_dci--; + } +} + diff --git a/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c b/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c index 10c728f2a7..82aca12b34 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c @@ -596,12 +596,14 @@ unsigned char *parse_ulsch_header(unsigned char *mac_header, } -void schedule_ulsch(module_id_t module_idP, frame_t frameP,unsigned char cooperation_flag,sub_frame_t subframeP, unsigned char sched_subframe, - unsigned int *nCCE) //,int calibration_flag) { -{ +void schedule_ulsch(module_id_t module_idP, + frame_t frameP, + unsigned char cooperation_flag, + sub_frame_t subframeP, + unsigned char sched_subframe) { + - unsigned int nCCE_available[MAX_NUM_CCs]; uint16_t first_rb[MAX_NUM_CCs],i; int CC_id; eNB_MAC_INST *eNB=&eNB_mac_inst[module_idP]; @@ -612,7 +614,6 @@ void schedule_ulsch(module_id_t module_idP, frame_t frameP,unsigned char coopera for (CC_id=0; CC_idget_nCCE_max(module_idP,CC_id) - nCCE[CC_id]; // UE data info; // check which UE has data to transmit @@ -644,10 +645,10 @@ void schedule_ulsch(module_id_t module_idP, frame_t frameP,unsigned char coopera } - schedule_ulsch_rnti(module_idP, cooperation_flag, frameP, subframeP, sched_subframe, nCCE, nCCE_available, first_rb); + schedule_ulsch_rnti(module_idP, cooperation_flag, frameP, subframeP, sched_subframe,first_rb); #ifdef CBA - schedule_ulsch_cba_rnti(module_idP, cooperation_flag, frameP, subframeP, sched_subframe, nCCE, nCCE_available, first_rb); + schedule_ulsch_cba_rnti(module_idP, cooperation_flag, frameP, subframeP, sched_subframe, first_rb); #endif @@ -662,8 +663,6 @@ void schedule_ulsch_rnti(module_id_t module_idP, frame_t frameP, sub_frame_t subframeP, unsigned char sched_subframe, - unsigned int *nCCE, - unsigned int *nCCE_available, uint16_t *first_rb) { @@ -697,8 +696,7 @@ void schedule_ulsch_rnti(module_id_t module_idP, frameP, subframeP, first_rb, - aggregation, - nCCE); + aggregation); // LOG_I(MAC,"exiting ulsch preprocesor\n"); @@ -729,8 +727,8 @@ void schedule_ulsch_rnti(module_id_t module_idP, continue; // mac_xface->macphy_exit("[MAC][eNB] Cannot find eNB_UE_stats\n"); } - if (nCCE_available[CC_id] < (1<mode]); + LOG_T(MAC,"[eNB %d] Frame %d, subframeP %d, UE %d CC %d : got harq pid %d round %d (rnti %x,mode %s)\n", + module_idP,frameP,subframeP,UE_id,CC_id, harq_pid, round,rnti,mode_string[eNB_UE_stats->mode]); #undef EXMIMO_IOT #ifndef EXMIMO_IOT @@ -1089,9 +1087,6 @@ void schedule_ulsch_rnti(module_id_t module_idP, subframeP, S_UL_SCHEDULED); - nCCE[CC_id] = nCCE[CC_id] + (1<get_nCCE_max(module_idP,CC_id) - nCCE[CC_id]; - LOG_D(MAC,"[eNB %d] CC_id %d Frame %d, subframeP %d: Generated ULSCH DCI for next UE_id %d, format 0\n", module_idP,CC_id,frameP,subframeP,UE_id); #ifdef DEBUG dump_dci(frame_parms, &DCI_pdu->dci_alloc[DCI_pdu->Num_common_dci+DCI_pdu->Num_ue_spec_dci-1]); @@ -1104,8 +1099,7 @@ void schedule_ulsch_rnti(module_id_t module_idP, } #ifdef CBA -void schedule_ulsch_cba_rnti(module_id_t module_idP, unsigned char cooperation_flag, frame_t frameP, sub_frame_t subframeP, unsigned char sched_subframe, unsigned int *nCCE, - unsigned int *nCCE_available, uint16_t *first_rb) +void schedule_ulsch_cba_rnti(module_id_t module_idP, unsigned char cooperation_flag, frame_t frameP, sub_frame_t subframeP, unsigned char sched_subframe, uint16_t *first_rb) { eNB_MAC_INST *eNB = &eNB_mac_inst[module_idP]; @@ -1164,11 +1158,11 @@ void schedule_ulsch_cba_rnti(module_id_t module_idP, unsigned char cooperation_f // cba group template uses the exisitng UE template, and thus if a UE // is scheduled, the correspodning group can't be used for CBA // this can be fixed later - if ((total_groups > 0) && (nCCE[CC_id] == 0)) { + if (total_groups > 0) { DCI_pdu = &eNB_mac_inst[module_idP].common_channels[CC_id].DCI_pdu; for (cba_group=0; - (cba_group (1< (1<= nCCE_available[CC_id]) { - num_cba_resources[cba_group%total_groups]--; - total_cba_resources--; - // LOG_N(MAC,"reducing num cba resources to %d for group %d \n", num_cba_resources[cba_group%total_groups], cba_group%total_groups ); - cba_group++; - } - if (total_cba_resources <= 0) { return; } @@ -1280,11 +1267,11 @@ void schedule_ulsch_cba_rnti(module_id_t module_idP, unsigned char cooperation_f for (cba_group=0; cba_groupN_RB_UL) { case 6: @@ -1426,8 +1413,6 @@ void schedule_ulsch_cba_rnti(module_id_t module_idP, unsigned char cooperation_f break; } - nCCE[CC_id] = nCCE[CC_id] + (1<get_nCCE_max(module_idP,CC_id) - nCCE[CC_id]; // break;// for the moment only schedule one } } diff --git a/openair2/LAYER2/MAC/main.c b/openair2/LAYER2/MAC/main.c index 5db78a30c2..a55301d80d 100644 --- a/openair2/LAYER2/MAC/main.c +++ b/openair2/LAYER2/MAC/main.c @@ -507,7 +507,7 @@ int l2_init(LTE_DL_FRAME_PARMS *frame_parms,int eMBMS_active, char *uecap_xer,ui mac_xface->computeRIV = computeRIV; mac_xface->get_TBS_DL = get_TBS_DL; mac_xface->get_TBS_UL = get_TBS_UL; - mac_xface->get_nCCE_max = get_nCCE_max; + mac_xface->get_nCCE_max = get_nCCE_mac; mac_xface->get_nCCE_offset = get_nCCE_offset; mac_xface->get_ue_mode = get_ue_mode; mac_xface->phy_config_sib1_eNB = phy_config_sib1_eNB; diff --git a/openair2/LAYER2/MAC/pre_processor.c b/openair2/LAYER2/MAC/pre_processor.c index 5a4caf82c4..316c79c524 100644 --- a/openair2/LAYER2/MAC/pre_processor.c +++ b/openair2/LAYER2/MAC/pre_processor.c @@ -828,8 +828,7 @@ void ulsch_scheduler_pre_processor(module_id_t module_idP, int frameP, sub_frame_t subframeP, uint16_t *first_rb, - uint8_t aggregation, - uint32_t *nCCE) + uint8_t aggregation) { int16_t i; @@ -839,7 +838,6 @@ void ulsch_scheduler_pre_processor(module_id_t module_idP, int16_t total_remaining_rbs[MAX_NUM_CCs]; uint16_t max_num_ue_to_be_scheduled=0,total_ue_count=0; rnti_t rnti= -1; - uint32_t nCCE_to_be_used[MAX_NUM_CCs]; UE_list_t *UE_list = &eNB_mac_inst[module_idP].UE_list; UE_TEMPLATE *UE_template = 0; LTE_DL_FRAME_PARMS *frame_parms = 0; @@ -860,7 +858,6 @@ void ulsch_scheduler_pre_processor(module_id_t module_idP, // we need to distribute RBs among UEs // step1: reset the vars for (CC_id=0; CC_idpre_allocated_nb_rb_ul > 0) { total_ue_count+=1; } - - if((mac_xface->get_nCCE_max(module_idP,CC_id) - nCCE_to_be_used[CC_id]) > (1<get_nCCE_max(module_idP,CC_id,3,subframeP) - nCCE_to_be_used[CC_id]) > (1<dlsch_eNB[i][j] = new_eNB_dlsch(1,NUMBER_OF_HARQ_PID_MAX,frame_parms->N_RB_DL,abstraction_flag); + PHY_vars_eNB->dlsch_eNB[i][j] = new_eNB_dlsch(1,NUMBER_OF_HARQ_PID_MAX,NSOFT,frame_parms->N_RB_DL,abstraction_flag); if (!PHY_vars_eNB->dlsch_eNB[i][j]) { LOG_E(PHY,"Can't get eNB dlsch structures for UE %d \n", i); @@ -128,11 +128,11 @@ PHY_VARS_eNB* init_lte_eNB(LTE_DL_FRAME_PARMS *frame_parms, exit(-1); } - PHY_vars_eNB->dlsch_eNB_SI = new_eNB_dlsch(1,1,frame_parms->N_RB_DL, abstraction_flag); + PHY_vars_eNB->dlsch_eNB_SI = new_eNB_dlsch(1,1,NSOFT,frame_parms->N_RB_DL, abstraction_flag); LOG_D(PHY,"eNB %d : SI %p\n",eNB_id,PHY_vars_eNB->dlsch_eNB_SI); - PHY_vars_eNB->dlsch_eNB_ra = new_eNB_dlsch(1,1,frame_parms->N_RB_DL, abstraction_flag); + PHY_vars_eNB->dlsch_eNB_ra = new_eNB_dlsch(1,1,NSOFT,frame_parms->N_RB_DL, abstraction_flag); LOG_D(PHY,"eNB %d : RA %p\n",eNB_id,PHY_vars_eNB->dlsch_eNB_ra); - PHY_vars_eNB->dlsch_eNB_MCH = new_eNB_dlsch(1,NUMBER_OF_HARQ_PID_MAX,frame_parms->N_RB_DL, 0); + PHY_vars_eNB->dlsch_eNB_MCH = new_eNB_dlsch(1,NUMBER_OF_HARQ_PID_MAX,NSOFT,frame_parms->N_RB_DL, 0); LOG_D(PHY,"eNB %d : MCH %p\n",eNB_id,PHY_vars_eNB->dlsch_eNB_MCH); @@ -169,7 +169,7 @@ PHY_VARS_UE* init_lte_UE(LTE_DL_FRAME_PARMS *frame_parms, for (i=0; idlsch_ue[i][j] = new_ue_dlsch(1,NUMBER_OF_HARQ_PID_MAX,MAX_TURBO_ITERATIONS,frame_parms->N_RB_DL, abstraction_flag); + PHY_vars_UE->dlsch_ue[i][j] = new_ue_dlsch(1,NUMBER_OF_HARQ_PID_MAX,NSOFT,MAX_TURBO_ITERATIONS,frame_parms->N_RB_DL, abstraction_flag); if (!PHY_vars_UE->dlsch_ue[i][j]) { LOG_E(PHY,"Can't get ue dlsch structures\n"); @@ -187,15 +187,15 @@ PHY_VARS_UE* init_lte_UE(LTE_DL_FRAME_PARMS *frame_parms, exit(-1); } - PHY_vars_UE->dlsch_ue_SI[i] = new_ue_dlsch(1,1,MAX_TURBO_ITERATIONS,frame_parms->N_RB_DL, abstraction_flag); - PHY_vars_UE->dlsch_ue_ra[i] = new_ue_dlsch(1,1,MAX_TURBO_ITERATIONS,frame_parms->N_RB_DL, abstraction_flag); + PHY_vars_UE->dlsch_ue_SI[i] = new_ue_dlsch(1,1,NSOFT,MAX_TURBO_ITERATIONS,frame_parms->N_RB_DL, abstraction_flag); + PHY_vars_UE->dlsch_ue_ra[i] = new_ue_dlsch(1,1,NSOFT,MAX_TURBO_ITERATIONS,frame_parms->N_RB_DL, abstraction_flag); PHY_vars_UE->transmission_mode[i] = transmission_mode; } PHY_vars_UE->lte_frame_parms.pucch_config_common.deltaPUCCH_Shift = 1; - PHY_vars_UE->dlsch_ue_MCH[0] = new_ue_dlsch(1,NUMBER_OF_HARQ_PID_MAX,MAX_TURBO_ITERATIONS_MBSFN,frame_parms->N_RB_DL,0); + PHY_vars_UE->dlsch_ue_MCH[0] = new_ue_dlsch(1,NUMBER_OF_HARQ_PID_MAX,NSOFT,MAX_TURBO_ITERATIONS_MBSFN,frame_parms->N_RB_DL,0); return (PHY_vars_UE); } @@ -211,11 +211,11 @@ PHY_VARS_RN* init_lte_RN(LTE_DL_FRAME_PARMS *frame_parms, if (eMBMS_active_state == multicast_relay) { for (i=0; i < 10 ; i++) { // num SF in a frame - PHY_vars_RN->dlsch_rn_MCH[i] = new_ue_dlsch(1,1,MAX_TURBO_ITERATIONS_MBSFN,frame_parms->N_RB_DL, 0); + PHY_vars_RN->dlsch_rn_MCH[i] = new_ue_dlsch(1,1,MAX_TURBO_ITERATIONS_MBSFN,NSOFT,frame_parms->N_RB_DL, 0); LOG_D(PHY,"eNB %d : MCH[%d] %p\n",RN_id,i,PHY_vars_RN->dlsch_rn_MCH[i]); } } else { - PHY_vars_RN->dlsch_rn_MCH[0] = new_ue_dlsch(1,1,MAX_TURBO_ITERATIONS,frame_parms->N_RB_DL, 0); + PHY_vars_RN->dlsch_rn_MCH[0] = new_ue_dlsch(1,1,MAX_TURBO_ITERATIONS,NSOFT,frame_parms->N_RB_DL, 0); LOG_D(PHY,"eNB %d : MCH[0] %p\n",RN_id,PHY_vars_RN->dlsch_rn_MCH[0]); } From f0e8581fe328091ed7026d246af0fa8999e478af Mon Sep 17 00:00:00 2001 From: "aikaterini.trilyraki" Date: Thu, 19 Nov 2015 16:49:58 +0100 Subject: [PATCH 008/263] 1. update ethernet library-raw/udp modes supported 2. rrh_gw UE/eNB_trasport files updated accordingly --- targets/ARCH/ETHERNET/USERSPACE/LIB/eth_raw.c | 317 ++++++++++ targets/ARCH/ETHERNET/USERSPACE/LIB/eth_udp.c | 379 +++++++++++ .../ETHERNET/USERSPACE/LIB/ethernet_lib.c | 597 ++++++++---------- .../ETHERNET/USERSPACE/LIB/ethernet_lib.h | 183 ++++-- targets/RT/USER/UE_transport_IQ.c | 2 +- targets/RT/USER/eNB_transport_IQ.c | 145 ++--- targets/RT/USER/rrh_gw.c | 132 ++-- 7 files changed, 1218 insertions(+), 537 deletions(-) create mode 100644 targets/ARCH/ETHERNET/USERSPACE/LIB/eth_raw.c create mode 100644 targets/ARCH/ETHERNET/USERSPACE/LIB/eth_udp.c diff --git a/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_raw.c b/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_raw.c new file mode 100644 index 0000000000..f8d1a31462 --- /dev/null +++ b/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_raw.c @@ -0,0 +1,317 @@ +/******************************************************************************* + OpenAirInterface + Copyright(c) 1999 - 2014 Eurecom + + OpenAirInterface is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + + OpenAirInterface 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with OpenAirInterface.The full GNU General Public License is + included in this distribution in the file called "COPYING". If not, + see . + + Contact Information + OpenAirInterface Admin: openair_admin@eurecom.fr + OpenAirInterface Tech : openair_tech@eurecom.fr + OpenAirInterface Dev : openair4g-devel@lists.eurecom.fr + + Address : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE + + *******************************************************************************/ +/*! \file ethernet_lib.c + * \brief API to stream I/Q samples over standard ethernet + * \author add alcatel Katerina Trilyraki, Navid Nikaein, Pedro Dinis, Lucio Ferreira, Raymond Knopp + * \date 2015 + * \version 0.2 + * \company Eurecom + * \maintainer: navid.nikaein@eurecom.fr + * \note + * \warning + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "common_lib.h" +#include "ethernet_lib.h" + +#define DEBUG 1 + +struct sockaddr_ll dest_addr[MAX_INST]; +struct sockaddr_ll local_addr[MAX_INST]; +int addr_len[MAX_INST]; +struct ifreq if_index[MAX_INST]; +struct ether_header eh; + +int eth_socket_init_raw(openair0_device *device) { + + int i = 0; + eth_state_t *eth = (eth_state_t*)device->priv; + int Mod_id = device->Mod_id; + const char *local_mac, *remote_mac; + int local_port=0, remote_port=0; + int sock_dom=0; + int sock_type=0; + int sock_proto=0; + + if (device->host_type == RRH_HOST ) { + local_mac = device->openair0_cfg.my_addr; + local_port = device->openair0_cfg.my_port; + remote_mac = "0:0:0:0:0:0"; + remote_port = device->openair0_cfg.my_port; + printf("[%s] local MAC addr %s remote MAC addr %s\n","RRH", local_mac,remote_mac); + } else { + local_mac = device->openair0_cfg.my_addr; + local_port = device->openair0_cfg.my_port; + remote_mac = device->openair0_cfg.remote_addr; + remote_port = device->openair0_cfg.remote_port; + printf("[%s] local MAC addr %s remote MAC addr %s\n","BBU", local_mac,remote_mac); + } + + + /* Open a RAW socket to send on */ + sock_dom=AF_PACKET; + sock_type=SOCK_RAW; + sock_proto=IPPROTO_RAW; + if ((eth->sockfd[Mod_id] = socket(sock_dom, sock_type, sock_proto)) == -1) { + perror("ETHERNET: Error opening RAW socket"); + exit(0); + } + + /* initialize destination address */ + for (i=0; i< MAX_INST; i++) { + bzero((void *)&(local_addr[i]), sizeof(struct sockaddr_ll)); + bzero((void *)&(if_index[i]), sizeof(struct ifreq)); + } + /* Get the index of the interface to send on */ + strcpy(if_index[Mod_id].ifr_name,eth->if_name[Mod_id]); + if (ioctl(eth->sockfd[Mod_id], SIOCGIFINDEX, &(if_index[Mod_id])) < 0) + perror("SIOCGIFINDEX"); + + local_addr[Mod_id].sll_family = AF_PACKET; + local_addr[Mod_id].sll_ifindex = if_index[Mod_id].ifr_ifindex; + /* hear traffic from specific protocol*/ + local_addr[Mod_id].sll_protocol = htons((short)device->openair0_cfg.my_port); + local_addr[Mod_id].sll_halen = ETH_ALEN; + local_addr[Mod_id].sll_pkttype = PACKET_OTHERHOST; + addr_len[Mod_id] = sizeof(struct sockaddr_ll); + + if (bind(eth->sockfd[Mod_id],(struct sockaddr *)&local_addr[Mod_id],addr_len[Mod_id])<0) { + perror("ETHERNET: Cannot bind to socket"); + exit(0); + } + + /* Construct the Ethernet header */ + ether_aton_r(device->openair0_cfg.my_addr, (struct ether_addr *)(&(eh.ether_shost))); + ether_aton_r(device->openair0_cfg.remote_addr, (struct ether_addr *)(&(eh.ether_dhost))); + eh.ether_type = htons((short)device->openair0_cfg.my_port); + + printf("[%s] binding mod_%d to hardware address %x:%x:%x:%x:%x:%x\n",((device->host_type == BBU_HOST) ? "BBU": "RRH"),Mod_id,eh.ether_shost[0],eh.ether_shost[1],eh.ether_shost[2],eh.ether_shost[3],eh.ether_shost[4],eh.ether_shost[5]); + + return 0; +} + + +int trx_eth_write_raw(openair0_device *device, openair0_timestamp timestamp, void **buff, int nsamps,int cc, int flags) { + + int bytes_sent=0; + eth_state_t *eth = (eth_state_t*)device->priv; + int Mod_id = device->Mod_id; + int sendto_flag =0; + int i=0; + //sendto_flag|=flags; + + eth->tx_nsamps=nsamps; + + for (i=0;isockfd[Mod_id],RAW_PACKET_SIZE_BYTES(nsamps), buff2);*/ + + while(bytes_sent < RAW_PACKET_SIZE_BYTES(nsamps)) { +#if DEBUG + printf("------- TX ------: buff2 current position=%d remaining_bytes=%d bytes_sent=%d \n", + (void *)(buff2+bytes_sent), + RAW_PACKET_SIZE_BYTES(nsamps) - bytes_sent, + bytes_sent); +#endif + /* Send packet */ + bytes_sent += send(eth->sockfd[Mod_id], + buff2, + RAW_PACKET_SIZE_BYTES(nsamps), + sendto_flag); + if ( bytes_sent == -1) { + eth->num_tx_errors++; + perror("ETHERNET WRITE: "); + exit(-1); + } else { +#if DEBUG + printf("------- TX ------: nu=%x an_id=%d ts%d bytes_sent=%d\n", + *(uint8_t *)(buff2+ETH_ALEN), + *(int16_t *)(buff2 + MAC_HEADER_SIZE_BYTES + sizeof(int16_t)), + *(openair0_timestamp *)(buff2 + MAC_HEADER_SIZE_BYTES + sizeof(int32_t)), + bytes_sent); + dump_packet((device->host_type == BBU_HOST)? "BBU":"RRH", buff2, RAW_PACKET_SIZE_BYTES(nsamps), TX_FLAG); +#endif + eth->tx_actual_nsamps=bytes_sent>>2; + eth->tx_count++; + } + } + + /* tx buffer values restored */ + *(struct ether_header *)buff2 = temp; + *(int32_t *)(buff2 + MAC_HEADER_SIZE_BYTES) = temp0; + *(openair0_timestamp *)(buff2 + MAC_HEADER_SIZE_BYTES + sizeof(int32_t)) = temp1; + } + return (bytes_sent-APP_HEADER_SIZE_BYTES-MAC_HEADER_SIZE_BYTES)>>2; +} + + +int trx_eth_read_raw(openair0_device *device, openair0_timestamp *timestamp, void **buff, int nsamps, int cc) { + + int bytes_received=0; + int i=0; + eth_state_t *eth = (eth_state_t*)device->priv; + int Mod_id = device->Mod_id; + int rcvfrom_flag =0; + + eth->rx_nsamps=nsamps; + + for (i=0;isockfd[Mod_id], + buff2, + RAW_PACKET_SIZE_BYTES(nsamps), + rcvfrom_flag); + + if (bytes_received ==-1) { + eth->num_rx_errors++; + perror("ETHERNET READ: "); + exit(-1); + } else { + /* store the timestamp value from packet's header */ + *timestamp = *(openair0_timestamp *)(buff2 + MAC_HEADER_SIZE_BYTES + sizeof(int32_t)); + eth->rx_actual_nsamps=bytes_received>>2; + eth->rx_count++; + } + } + +#if DEBUG + printf("------- RX------: nu=%x an_id=%d ts%d bytes_recv=%d \n", + *(uint8_t *)(buff2+ETH_ALEN), + *(int16_t *)(buff2 + MAC_HEADER_SIZE_BYTES + sizeof(int16_t)), + *(openair0_timestamp *)(buff2 + MAC_HEADER_SIZE_BYTES + sizeof(int32_t)), + bytes_received); + dump_packet((device->host_type == BBU_HOST)? "BBU":"RRH", buff2, RAW_PACKET_SIZE_BYTES(nsamps),RX_FLAG); + +#endif + + /* tx buffer values restored */ + *(struct ether_header *)buff2 = temp; + *(int32_t *)(buff2 + MAC_HEADER_SIZE_BYTES) = temp0; + *(openair0_timestamp *)(buff2 + MAC_HEADER_SIZE_BYTES + sizeof(int32_t)) = temp1; + } + return (bytes_received-APP_HEADER_SIZE_BYTES-MAC_HEADER_SIZE_BYTES)>>2; +} + + + + +int eth_set_dev_conf_raw(openair0_device *device) { + + int Mod_id = device->Mod_id; + eth_state_t *eth = (eth_state_t*)device->priv; + void *msg; + ssize_t msg_len; + + /* a BBU client sends to RRH a set of configuration parameters (openair0_config_t) + so that RF front end is configured appropriately and + frame/packet size etc. can be set */ + + msg = malloc(MAC_HEADER_SIZE_BYTES + sizeof(openair0_config_t)); + msg_len = MAC_HEADER_SIZE_BYTES + sizeof(openair0_config_t); + + + memcpy(msg,(void*)&eh,MAC_HEADER_SIZE_BYTES); + memcpy((msg+MAC_HEADER_SIZE_BYTES),(void*)&device->openair0_cfg,sizeof(openair0_config_t)); + + if (send(eth->sockfd[Mod_id], + msg, + msg_len, + 0)==-1) { + perror("ETHERNET: "); + exit(0); + } + + return 0; +} + + +int eth_get_dev_conf_raw(openair0_device *device) { + + eth_state_t *eth = (eth_state_t*)device->priv; + int Mod_id = device->Mod_id; + char str[INET_ADDRSTRLEN]; + void *msg; + ssize_t msg_len; + + msg = malloc(MAC_HEADER_SIZE_BYTES + sizeof(openair0_config_t)); + msg_len = MAC_HEADER_SIZE_BYTES + sizeof(openair0_config_t); + + /* RRH receives from BBU openair0_config_t */ + if (recv(eth->sockfd[Mod_id], + msg, + msg_len, + 0)==-1) { + perror("ETHERNET: "); + exit(0); + } + + /* RRH stores the remote MAC address */ + memcpy(eh.ether_dhost,(msg+ETH_ALEN),ETH_ALEN); + memcpy((void*)&device->openair0_cfg,(msg + MAC_HEADER_SIZE_BYTES), sizeof(openair0_config_t)); + printf("[%s] binding mod_%d to hardware address %x:%x:%x:%x:%x:%x hardware address %x:%x:%x:%x:%x:%x\n",((device->host_type == BBU_HOST) ? "BBU": "RRH"),Mod_id,eh.ether_shost[0],eh.ether_shost[1],eh.ether_shost[2],eh.ether_shost[3],eh.ether_shost[4],eh.ether_shost[5],eh.ether_dhost[0],eh.ether_dhost[1],eh.ether_dhost[2],eh.ether_dhost[3],eh.ether_dhost[4],eh.ether_dhost[5]); + + return 0; +} diff --git a/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_udp.c b/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_udp.c new file mode 100644 index 0000000000..fe4d4db0db --- /dev/null +++ b/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_udp.c @@ -0,0 +1,379 @@ +/******************************************************************************* + OpenAirInterface + Copyright(c) 1999 - 2014 Eurecom + + OpenAirInterface is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + + OpenAirInterface 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with OpenAirInterface.The full GNU General Public License is + included in this distribution in the file called "COPYING". If not, + see . + + Contact Information + OpenAirInterface Admin: openair_admin@eurecom.fr + OpenAirInterface Tech : openair_tech@eurecom.fr + OpenAirInterface Dev : openair4g-devel@lists.eurecom.fr + + Address : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE + + *******************************************************************************/ +/*! \file ethernet_lib.c + * \brief API to stream I/Q samples over standard ethernet + * \author add alcatel Katerina Trilyraki, Navid Nikaein, Pedro Dinis, Lucio Ferreira, Raymond Knopp + * \date 2015 + * \version 0.2 + * \company Eurecom + * \maintainer: navid.nikaein@eurecom.fr + * \note + * \warning + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "common_lib.h" +#include "ethernet_lib.h" + +#define DEBUG 0 +struct sockaddr_in dest_addr[MAX_INST]; +struct sockaddr_in local_addr[MAX_INST]; +int addr_len[MAX_INST]; + + + int eth_socket_init_udp(openair0_device *device) { + + int i = 0; + eth_state_t *eth = (eth_state_t*)device->priv; + int Mod_id = device->Mod_id; + char str_local[INET_ADDRSTRLEN]; + char str_remote[INET_ADDRSTRLEN]; + const char *local_ip, *remote_ip; + int local_port=0, remote_port=0; + int sock_dom=0; + int sock_type=0; + int sock_proto=0; + int enable=1; + + if (device->host_type == RRH_HOST ) { + local_ip = device->openair0_cfg.my_addr; + local_port = device->openair0_cfg.my_port; + remote_ip = "0.0.0.0"; + remote_port = 0; + printf("[%s] local ip addr %s port %d\n", "RRH", local_ip, local_port); + } else { + local_ip = device->openair0_cfg.my_addr; + local_port = device->openair0_cfg.my_port; + remote_ip = device->openair0_cfg.remote_addr; + remote_port = device->openair0_cfg.remote_port; + printf("[%s] local ip addr %s port %d\n","BBU", local_ip, local_port); + } + + /* Open socket to send on */ + sock_dom=AF_INET; + sock_type=SOCK_DGRAM; + sock_proto=IPPROTO_UDP; + + if ((eth->sockfd[Mod_id] = socket(sock_dom, sock_type, sock_proto)) == -1) { + perror("ETHERNET: Error opening socket"); + exit(0); + } + + /* initialize addresses */ + for (i=0; i< MAX_INST; i++) { + bzero((void *)&(dest_addr[i]), sizeof(dest_addr[i])); + bzero((void *)&(local_addr[i]), sizeof(local_addr[i])); + } + + addr_len[Mod_id] = sizeof(struct sockaddr_in); + + dest_addr[Mod_id].sin_family = AF_INET; + inet_pton(AF_INET,remote_ip,&(dest_addr[Mod_id].sin_addr.s_addr)); + dest_addr[Mod_id].sin_port=htons(remote_port); + inet_ntop(AF_INET, &(dest_addr[Mod_id].sin_addr), str_remote, INET_ADDRSTRLEN); + + + local_addr[Mod_id].sin_family = AF_INET; + inet_pton(AF_INET,local_ip,&(local_addr[Mod_id].sin_addr.s_addr)); + local_addr[Mod_id].sin_port=htons(local_port); + inet_ntop(AF_INET, &(local_addr[Mod_id].sin_addr), str_local, INET_ADDRSTRLEN); + + + /* set reuse address flag */ + if (setsockopt(eth->sockfd[Mod_id], SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(int))) { + perror("ETHERNET: Cannot set SO_REUSEADDR option on socket"); + exit(0); + } + + /* apply additional configuration */ + //ethernet_tune (device,MTU_SIZE,UDP_PACKET_SIZE_BYTES(device->openair0_cfg.samples_per_packet)); + + /* if RRH, then I am the server, so bind */ + if (device->host_type == RRH_HOST) { + if (bind(eth->sockfd[Mod_id],(struct sockaddr *)&local_addr[Mod_id],addr_len[Mod_id])<0) { + perror("ETHERNET: Cannot bind to socket"); + exit(0); + } else { + printf("[%s] binding mod_%d to %s:%d\n","RRH",Mod_id,str_local,ntohs(local_addr[Mod_id].sin_port)); + } + /* if BBU, then I am a client, so connect */ + } else { + printf("[%s] Connecting to %s:%d\n","BBU",str_remote,ntohs(dest_addr[Mod_id].sin_port)); + } + + + + return 0; +} + +int trx_eth_write_udp(openair0_device *device, openair0_timestamp timestamp, void **buff, int nsamps,int cc, int flags) { + + int bytes_sent=0; + eth_state_t *eth = (eth_state_t*)device->priv; + int Mod_id = device->Mod_id; + int sendto_flag =0; + int i=0; + //sendto_flag|=flags; + eth->tx_nsamps=nsamps; + + for (i=0;isockfd[Mod_id], + buff2, + UDP_PACKET_SIZE_BYTES(nsamps), + sendto_flag, + (struct sockaddr*)&dest_addr[Mod_id], + addr_len[Mod_id]); + + if ( bytes_sent == -1) { + eth->num_tx_errors++; + perror("ETHERNET WRITE: "); + exit(-1); + } else { +#if DEBUG + printf("------- TX ------: nu=%d an_id=%d ts%d bytes_send=%d\n", + *(int16_t *)buff2, + *(int16_t *)(buff2 + sizeof(int16_t)), + *(openair0_timestamp *)(buff2 + sizeof(int32_t)), + bytes_sent); + dump_packet((device->host_type == BBU_HOST)? "BBU":"RRH", buff2, UDP_PACKET_SIZE_BYTES(nsamps), TX_FLAG); +#endif + eth->tx_actual_nsamps=bytes_sent>>2; + eth->tx_count++; + } + } + /* tx buffer values restored */ + *(int32_t *)buff2 = temp0; + *(openair0_timestamp *)(buff2 + sizeof(int32_t)) = temp1; + } + + return (bytes_sent-APP_HEADER_SIZE_BYTES)>>2; +} + + + +int trx_eth_read_udp(openair0_device *device, openair0_timestamp *timestamp, void **buff, int nsamps, int cc) { + + int bytes_received=0; + eth_state_t *eth = (eth_state_t*)device->priv; + openair0_timestamp prev_timestamp = -1; + int Mod_id = device->Mod_id; + int rcvfrom_flag =0; + int block_cnt=0; + int again_cnt=0; + int i=0; + + eth->rx_nsamps=nsamps; + + for (i=0;isockfd[Mod_id], + buff2, + UDP_PACKET_SIZE_BYTES(nsamps), + rcvfrom_flag, + (struct sockaddr *)&dest_addr[Mod_id], + (socklen_t *)&addr_len[Mod_id]); + + if (bytes_received ==-1) { + eth->num_rx_errors++; + if (errno == EAGAIN) { + again_cnt++; + usleep(10); + if (again_cnt == 1000) { + perror("ETHERNET READ: "); + exit(-1); + } else { + printf("AGAIN AGAIN AGAIN AGAIN AGAIN AGAIN AGAIN AGAIN AGAIN AGAIN AGAIN AGAIN \n"); + goto again; + } + } else if (errno == EWOULDBLOCK) { + block_cnt++; + usleep(10); + if (block_cnt == 1000) { + perror("ETHERNET READ: "); + exit(-1); + } else { + printf("BLOCK BLOCK BLOCK BLOCK BLOCK BLOCK BLOCK BLOCK BLOCK BLOCK BLOCK BLOCK \n"); + goto again; + } + } + } else { +#if DEBUG + printf("------- RX------: nu=%d an_id=%d ts%d bytes_recv=%d\n", + *(int16_t *)buff2, + *(int16_t *)(buff2 + sizeof(int16_t)), + *(openair0_timestamp *)(buff2 + sizeof(int32_t)), + bytes_received); + dump_packet((device->host_type == BBU_HOST)? "BBU":"RRH", buff2, UDP_PACKET_SIZE_BYTES(nsamps),RX_FLAG); +#endif + /* store the timestamp value from packet's header */ + if (prev_timestamp == -1) { + prev_timestamp = *(openair0_timestamp *)(buff2 + sizeof(int32_t)); + } else { + prev_timestamp =timestamp; + } + /* store the timestamp value from packet's header */ + *timestamp = *(openair0_timestamp *)(buff2 + sizeof(int32_t)); + eth->rx_actual_nsamps=bytes_received>>2; + eth->rx_count++; + } + + } + /* tx buffer values restored */ + *(int32_t *)buff2 = temp0; + *(openair0_timestamp *)(buff2 + sizeof(int32_t)) = temp1; + + } + return (bytes_received-APP_HEADER_SIZE_BYTES)>>2; +} + + + + +int eth_set_dev_conf_udp(openair0_device *device) { + + int Mod_id = device->Mod_id; + eth_state_t *eth = (eth_state_t*)device->priv; + void *msg; + ssize_t msg_len; + + + /* a BBU client sents to RRH a set of configuration parameters (openair0_config_t) + so that RF front end is configured appropriately and + frame/packet size etc. can be set */ + + msg=malloc(sizeof(openair0_config_t)); + msg_len=sizeof(openair0_config_t); + memcpy(msg,(void*)&device->openair0_cfg,msg_len); + + if (sendto(eth->sockfd[Mod_id],msg,msg_len,0,(struct sockaddr *)&dest_addr[Mod_id],addr_len[Mod_id])==-1) { + perror("ETHERNET: "); + exit(0); + } + + /* printf("[RRHbbb] mod_%d socket %d connected to BBU %s:%d\n", Mod_id, eth->sockfd[Mod_id], inet_ntoa(dest_addr[Mod_id].sin_addr), */ + /* ntohs(dest_addr[Mod_id].sin_port)); */ + return 0; +} + +int eth_get_dev_conf_udp(openair0_device *device) { + + eth_state_t *eth = (eth_state_t*)device->priv; + int Mod_id = device->Mod_id; + char str1[INET_ADDRSTRLEN],str[INET_ADDRSTRLEN]; + void *msg; + ssize_t msg_len; + + msg=malloc(sizeof(openair0_config_t)); + msg_len=sizeof(openair0_config_t); + + inet_ntop(AF_INET, &(local_addr[Mod_id].sin_addr), str, INET_ADDRSTRLEN); + inet_ntop(AF_INET, &(dest_addr[Mod_id].sin_addr), str1, INET_ADDRSTRLEN); + + /* printf("[RRH] mod_%d socket %d connected to BBU %s:%d %s:%d\n", Mod_id, eth->sockfd[Mod_id], str1, */ + /* ntohs(dest_addr[Mod_id].sin_port),str, */ + /* ntohs(local_addr[Mod_id].sin_port)); */ + + /* RRH receives from BBU openair0_config_t */ + if (recvfrom(eth->sockfd[Mod_id], + msg, + msg_len, + 0, + (struct sockaddr *)&dest_addr[Mod_id], + (socklen_t *)&addr_len[Mod_id])==-1) { + perror("ETHERNET: "); + exit(0); + } + + memcpy((void*)&device->openair0_cfg,msg,msg_len); + + /* get remote ip address and port */ + inet_ntop(AF_INET, &(dest_addr[Mod_id].sin_addr), str1, INET_ADDRSTRLEN); + device->openair0_cfg.remote_port =ntohs(dest_addr[Mod_id].sin_port); + device->openair0_cfg.remote_addr =str1; + + /* restore local ip address and port */ + inet_ntop(AF_INET, &(local_addr[Mod_id].sin_addr), str, INET_ADDRSTRLEN); + device->openair0_cfg.my_port =ntohs(local_addr[Mod_id].sin_port); + device->openair0_cfg.my_addr =str; + + /* printf("[RRH2] mod_%d socket %d connected to BBU %s:%d %s:%d\n", Mod_id, eth->sockfd[Mod_id],str1, device->openair0_cfg.remote_port, str, device->openair0_cfg.my_port); */ + return 0; +} diff --git a/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c b/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c index ce90d2cff9..995ced1f0d 100644 --- a/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c +++ b/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c @@ -28,7 +28,7 @@ *******************************************************************************/ /*! \file ethernet_lib.c * \brief API to stream I/Q samples over standard ethernet - * \author Katerina Trilyraki, Navid Nikaein, Pedro Dinis, Lucio Ferreira, Raymond Knopp + * \author add alcatel Katerina Trilyraki, Navid Nikaein, Pedro Dinis, Lucio Ferreira, Raymond Knopp * \date 2015 * \version 0.2 * \company Eurecom @@ -52,186 +52,43 @@ #include "common_lib.h" #include "ethernet_lib.h" -//#define DEBUG 1 int num_devices_eth = 0; +struct sockaddr_in dest_addr[MAX_INST]; int dest_addr_len[MAX_INST]; -char sendbuf[MAX_INST][BUF_SIZ]; /*TODO*/ - - -/*! \fn static int eth_socket_init(openair0_device *device) -* \brief initialization of UDP Socket to communicate with one destination -* \param[in] *device openair device for which the socket will be created -* \param[out] -* \return 0 on success, otherwise -1 -* \note -* @ingroup _oai -*/ -static int eth_socket_init(openair0_device *device); - -/*! \fn static int eth_set_dev_conf(openair0_device *device) -* \brief -* \param[in] *device openair device -* \param[out] -* \return 0 on success, otherwise -1 -* \note -* @ingroup _oai -*/ -static int eth_set_dev_conf(openair0_device *device); - -/*! \fn static int eth_get_dev_conf(openair0_device *device) -* \brief -* \param[in] *device openair device -* \param[out] -* \return 0 on success, otherwise -1 -* \note -* @ingroup _oai -*/ -static int eth_get_dev_conf(openair0_device *device); - int trx_eth_start(openair0_device *device) { + + eth_state_t *eth = (eth_state_t*)device->priv; /* initialize socket */ - if (eth_socket_init(device)!=0) { - return -1; - } - - /* RRH gets openair0 device configuration BBU sets openair0 device configuration*/ - if (device->func_type == BBU_FUNC) { - return eth_set_dev_conf(device); + if ((eth->flags & ETH_RAW_MODE) != 0 ) { + if (eth_socket_init_raw(device)!=0) return -1; + /* RRH gets openair0 device configuration - BBU sets openair0 device configuration*/ + if (device->host_type == BBU_HOST) { + if(eth_set_dev_conf_raw(device)!=0) return -1; + } else { + if(eth_get_dev_conf_raw(device)!=0) return -1; + } + /* adjust MTU wrt number of samples per packet */ + if(ethernet_tune (device,MTU_SIZE,RAW_PACKET_SIZE_BYTES(device->openair0_cfg.samples_per_packet))!=0) return -1; } else { - return eth_get_dev_conf(device); + if (eth_socket_init_udp(device)!=0) return -1; + /* RRH gets openair0 device configuration - BBU sets openair0 device configuration*/ + if (device->host_type == BBU_HOST) { + if(eth_set_dev_conf_udp(device)!=0) return -1; + } else { + if(eth_get_dev_conf_udp(device)!=0) return -1; + } + /* adjust MTU wrt number of samples per packet */ + if(ethernet_tune (device,MTU_SIZE,UDP_PACKET_SIZE_BYTES(device->openair0_cfg.samples_per_packet))!=0) return -1; } - + return 0; } -int trx_eth_write(openair0_device *device, openair0_timestamp timestamp, void **buff, int nsamps,int cc, int flags) { - - int n_written=0,i; - uint16_t header_size=sizeof(int32_t) + sizeof(openair0_timestamp); - eth_state_t *eth = (eth_state_t*)device->priv; - int Mod_id = device->Mod_id; - int sendto_flag =0; - sendto_flag|=MSG_DONTWAIT; - - for (i=0;isockfd[Mod_id],(nsamps<<2)+header_size, buff2, antenna_id);*/ - - while(n_written < nsamps) { - /* Send packet */ - if ((n_written += sendto(eth->sockfd[Mod_id], - buff2, - (nsamps<<2)+header_size, - 0, - (struct sockaddr*)ð->dest_addr[Mod_id], - dest_addr_len[Mod_id])) < 0) { - perror("ETHERNET WRITE"); - exit(-1); - } - } - -#if DEBUG - printf("Buffer head TX: nu=%d an_id=%d ts%d samples_send=%d i=%d data=%x\n", - *(int16_t *)buff2, - *(int16_t *)(buff2 + sizeof(int16_t)), - *(openair0_timestamp *)(buff2 + sizeof(int32_t)), - n_written>>2,i,*(int32_t *)(buff2 + 20*sizeof(int32_t))); -#endif - - /* tx buffer values restored */ - *(int32_t *)buff2 = temp0; - *(openair0_timestamp *)(buff2 + sizeof(int32_t)) = temp1; - } - return n_written; - -} - -int trx_eth_read(openair0_device *device, openair0_timestamp *timestamp, void **buff, int nsamps, int cc) { - - int bytes_received=0; - int block_cnt=0; - int ret=0,i; - uint16_t header_size=sizeof(int32_t) + sizeof(openair0_timestamp); - - eth_state_t *eth = (eth_state_t*)device->priv; - int Mod_id = device->Mod_id; - - for (i=0;isockfd[Mod_id],(nsamps<<2)+header_size, buff2, antenna_id);*/ - - while(bytes_received < (int)((nsamps<<2))) { - ret=recvfrom(eth->sockfd[Mod_id], - buff2+bytes_received, - (nsamps<<2)+header_size-bytes_received, - 0,//MSG_DONTWAIT, - (struct sockaddr *)ð->dest_addr[Mod_id], - (socklen_t *)&dest_addr_len[Mod_id]); - - if (ret==-1) { - if (errno == EAGAIN) { - perror("ETHERNET READ: "); - return((nsamps<<2) + header_size); - } else if (errno == EWOULDBLOCK) { - block_cnt++; - usleep(10); - - if (block_cnt == 100) return(-1); - } - } else { - bytes_received+=ret; - } - } - -#if DEBUG - printf("Buffer head RX: nu=%d an_id=%d ts%d samples_recv=%d i=%d data=%x\n", - *(int16_t *)buff2, - *(int16_t *)(buff2 + sizeof(int16_t)), - *(openair0_timestamp *)(buff2 + sizeof(int32_t)), - ret>>2,i,*(int32_t *)(buff2 + 20*sizeof(int32_t))); -#endif - - /* store the timestamp value from packet's header */ - *timestamp = *(openair0_timestamp *)(buff2 + sizeof(int32_t)); - - /* tx buffer values restored */ - *(int32_t *)buff2 = temp0; - *(openair0_timestamp *)(buff2 + sizeof(int32_t)) = temp1; - } - return nsamps; - -} - void trx_eth_end(openair0_device *device) { eth_state_t *eth = (eth_state_t*)device->priv; @@ -241,7 +98,7 @@ void trx_eth_end(openair0_device *device) { perror("ETHERNET: Failed to close socket"); exit(0); } else { - printf("[RRH] socket for mod_id %d has been successfully closed.\n",Mod_id); + printf("[%s] socket for mod_id %d has been successfully closed.\n",(device->host_type == BBU_HOST)? "BBU":"RRH",Mod_id); } } @@ -253,7 +110,7 @@ int trx_eth_request(openair0_device *device, void *msg, ssize_t msg_len) { eth_state_t *eth = (eth_state_t*)device->priv; /* BBU sends a message to RRH */ - if (sendto(eth->sockfd[Mod_id],msg,msg_len,0,(struct sockaddr *)ð->dest_addr[Mod_id],dest_addr_len[Mod_id])==-1) { + if (sendto(eth->sockfd[Mod_id],msg,msg_len,0,(struct sockaddr *)&dest_addr[Mod_id],dest_addr_len[Mod_id])==-1) { perror("ETHERNET: "); exit(0); } @@ -262,7 +119,6 @@ int trx_eth_request(openair0_device *device, void *msg, ssize_t msg_len) { } - int trx_eth_reply(openair0_device *device, void *msg, ssize_t msg_len) { eth_state_t *eth = (eth_state_t*)device->priv; @@ -273,7 +129,7 @@ int trx_eth_reply(openair0_device *device, void *msg, ssize_t msg_len) { msg, msg_len, 0, - (struct sockaddr *)ð->dest_addr[Mod_id], + (struct sockaddr *)&dest_addr[Mod_id], (socklen_t *)&dest_addr_len[Mod_id])==-1) { perror("ETHERNET: "); exit(0); @@ -283,65 +139,6 @@ int trx_eth_reply(openair0_device *device, void *msg, ssize_t msg_len) { } -static int eth_set_dev_conf(openair0_device *device) { - - int Mod_id = device->Mod_id; - eth_state_t *eth = (eth_state_t*)device->priv; - void *msg; - ssize_t msg_len; - - - /* a BBU client sents to RRH a set of configuration parameters (openair0_config_t) - so that RF front end is configured appropriately and - frame/packet size etc. can be set */ - - msg=malloc(sizeof(openair0_config_t)); - msg_len=sizeof(openair0_config_t); - memcpy(msg,(void*)&device->openair0_cfg,msg_len); - - if (sendto(eth->sockfd[Mod_id],msg,msg_len,0,(struct sockaddr *)ð->dest_addr[Mod_id],dest_addr_len[Mod_id])==-1) { - perror("ETHERNET: "); - exit(0); - } - - return 0; -} - - -static int eth_get_dev_conf(openair0_device *device) { - - eth_state_t *eth = (eth_state_t*)device->priv; - int Mod_id = device->Mod_id; - char str[INET_ADDRSTRLEN]; - void *msg; - ssize_t msg_len; - - msg=malloc(sizeof(openair0_config_t)); - msg_len=sizeof(openair0_config_t); - - /* RRH receives from BBU openair0_config_t */ - if (recvfrom(eth->sockfd[Mod_id], - msg, - msg_len, - 0, - (struct sockaddr *)ð->dest_addr[Mod_id], - (socklen_t *)&dest_addr_len[Mod_id])==-1) { - perror("ETHERNET: "); - exit(0); - } - - memcpy((void*)&device->openair0_cfg,msg,msg_len); - inet_ntop(AF_INET, &(eth->dest_addr[Mod_id].sin_addr), str, INET_ADDRSTRLEN); - device->openair0_cfg.remote_port =ntohs(eth->dest_addr[Mod_id].sin_port); - device->openair0_cfg.remote_ip=str; - /*apply additional configuration*/ - //ethernet_tune (device, RING_PAR); - // printf("[RRH] write mod_%d %d to %s:%d\n",Mod_id,eth->sockfd[Mod_id],str,ntohs(eth->dest_addr[Mod_id].sin_port)); - - return 0; -} - - int trx_eth_stop(int card) { return(0); @@ -364,186 +161,310 @@ int trx_eth_reset_stats(openair0_device* device) { } -static int eth_socket_init(openair0_device *device) { - - int i = 0; - eth_state_t *eth = (eth_state_t*)device->priv; - int Mod_id = device->Mod_id; - char str[INET_ADDRSTRLEN]; - const char *dest_ip; - int dest_port=0; - - if (device->func_type == RRH_FUNC ) { - dest_ip = device->openair0_cfg.my_ip; - dest_port = device->openair0_cfg.my_port; - printf("[RRH] ip addr %s port %d\n",dest_ip, dest_port); - } else { - dest_ip = device->openair0_cfg.remote_ip; - dest_port = device->openair0_cfg.remote_port; - printf("[BBU] ip addr %s port %d\n",dest_ip, dest_port); - } - - /* Open RAW socket to send on */ - if ((eth->sockfd[Mod_id] = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) { - perror("ETHERNET: Error opening socket"); - exit(0); - } - - /* initialize destination address */ - for (i=0; i< MAX_INST; i++) { - bzero((void *)&(eth->dest_addr[i]), sizeof(eth->dest_addr[i])); - } - - // bzero((void *)dest,sizeof(struct sockaddr_in)); - eth->dest_addr[Mod_id].sin_family = AF_INET; - inet_pton(AF_INET,dest_ip,&(eth->dest_addr[Mod_id].sin_addr.s_addr)); - eth->dest_addr[Mod_id].sin_port=htons(dest_port); - dest_addr_len[Mod_id] = sizeof(struct sockaddr_in); - inet_ntop(AF_INET, &(eth->dest_addr[Mod_id].sin_addr), str, INET_ADDRSTRLEN); - - /* if RRH, then I am the server, so bind */ - if (device->func_type == RRH_FUNC ) { - if (bind(eth->sockfd[Mod_id],(struct sockaddr *)ð->dest_addr[Mod_id], dest_addr_len[Mod_id])<0) { - perror("ETHERNET: Cannot bind to socket"); - exit(0); - } else { - printf("[RRH] binding mod_%d to %s:%d\n",Mod_id,str,ntohs(eth->dest_addr[Mod_id].sin_port)); - } - - } else { - printf("[BBU] Connecting to %s:%d\n",str,ntohs(eth->dest_addr[Mod_id].sin_port)); - } - - return 0; -} - - -int ethernet_tune(openair0_device *device , eth_opt_t option) { +int ethernet_tune(openair0_device *device, unsigned int option, int value) { eth_state_t *eth = (eth_state_t*)device->priv; int Mod_id=device->Mod_id; - - unsigned int sndbuf_size=0, rcvbuf_size=0; - struct timeval snd_timeout, rcv_timeout; + struct timeval timeout; struct ifreq ifr; char system_cmd[256]; char* if_name=DEFAULT_IF; + struct in_addr ia; + struct if_nameindex *ids; + int ret=0; + int i=0; + + + /***************** get working interface name ***************************/ + /* /\* convert ascii ip address from config file to network binary format *\/ */ + /* inet_aton(device->openair0_cfg.my_addr, &ia); */ + /* /\* look for the interface used, we have its ip address *\/ */ + /* /\* get info on all our network interfaces *\/ */ + /* ids = if_nameindex(); */ + /* /\* loop on these network interfaces *\/ */ + /* for (i=0; ids[i].if_index != 0 ; i++) { */ + /* /\* skip unamed interfaces *\/ */ + /* if (ids[i].if_name == NULL) */ + /* continue; */ + /* /\* get ip address of current network interface *\/ */ + /* strcpy(ifr.ifr_name,ids[i].if_name); */ + /* if (-1 == ioctl(eth->sockfd[Mod_id], SIOCGIFADDR, &ifr)) { */ + /* printf( " Interface %i: %s isn't configured (no ip addr), skipped\n",ids[i].if_index, ifr.ifr_name) ; */ + /* continue; */ + /* } */ + /* /\* test if this is the interface to be used *\/ */ + /* if ( ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr.s_addr != ia.s_addr) */ + /* continue; */ + /* /\* store interface name *\/ */ + /* if_name = ids[i].if_name; */ + /* break; */ + + /* } */ + /* if_freenameindex(ids); */ + /* if( if_name == NULL) { */ + /* printf("Unable to find interface name for %s\n",device->openair0_cfg.my_addr); */ + /* return -1; */ + /* } */ + /* eth->if_name[Mod_id]=if_name; */ - /****************** socket level options ************************/ - if (option== SND_BUF_SIZE) { /* transmit socket buffer size */ + /****************** socket level options ************************/ + switch(option) { + case SND_BUF_SIZE: /* transmit socket buffer size */ if (setsockopt(eth->sockfd[Mod_id], SOL_SOCKET, SO_SNDBUF, - &sndbuf_size,sizeof(sndbuf_size))) { + &value,sizeof(value))) { perror("[ETHERNET] setsockopt()"); } else { - printf( "sndbuf_size= %d bytes\n", sndbuf_size); - } - } else if (option== RCV_BUF_SIZE) { /* receive socket buffer size */ + printf("send buffer size= %d bytes\n",value); + } + break; + + case RCV_BUF_SIZE: /* receive socket buffer size */ if (setsockopt(eth->sockfd[Mod_id], SOL_SOCKET, SO_RCVBUF, - &rcvbuf_size,sizeof(rcvbuf_size))) { + &value,sizeof(value))) { perror("[ETHERNET] setsockopt()"); } else { - printf( "rcvbuf_size= %d bytes\n", rcvbuf_size); + printf("receive bufffer size= %d bytes\n",value); } - } else if (option==RCV_TIMEOUT) { - rcv_timeout.tv_sec = 0; - rcv_timeout.tv_usec = 180;//less than rt_period + break; + + case RCV_TIMEOUT: + timeout.tv_sec = value/1000000000; + timeout.tv_usec = value%1000000000;//less than rt_period? if (setsockopt(eth->sockfd[Mod_id], SOL_SOCKET, SO_RCVTIMEO, - (char *)&rcv_timeout,sizeof(rcv_timeout))) { + (char *)&timeout,sizeof(timeout))) { perror("[ETHERNET] setsockopt()"); } else { - printf( "rcv_timeout= %d usecs\n", rcv_timeout.tv_usec); + printf( "receive timeout= %d,%d sec\n",timeout.tv_sec,timeout.tv_usec); } - } else if (option==SND_TIMEOUT) { - snd_timeout.tv_sec = 0; - snd_timeout.tv_usec = 180;//less than rt_period + break; + + case SND_TIMEOUT: + timeout.tv_sec = value/1000000000; + timeout.tv_usec = value%1000000000;//less than rt_period? if (setsockopt(eth->sockfd[Mod_id], SOL_SOCKET, SO_SNDTIMEO, - (char *)&snd_timeout,sizeof(snd_timeout))) { + (char *)&timeout,sizeof(timeout))) { perror("[ETHERNET] setsockopt()"); } else { - printf( "snd_timeout= %d usecs\n", snd_timeout.tv_usec); + printf( "send timeout= %d,%d sec\n",timeout.tv_sec,timeout.tv_usec); } - } - - /******************* interface level options *************************/ - else if (option==MTU_SIZE) { /* change MTU of the eth interface */ + break; + + + /******************* interface level options *************************/ + case MTU_SIZE: /* change MTU of the eth interface */ ifr.ifr_addr.sa_family = AF_INET; - strncpy(ifr.ifr_name,if_name, sizeof(ifr.ifr_name)); - ifr.ifr_mtu =8960; + strncpy(ifr.ifr_name,eth->if_name[Mod_id], sizeof(ifr.ifr_name)); + ifr.ifr_mtu =value; if (ioctl(eth->sockfd[Mod_id],SIOCSIFMTU,(caddr_t)&ifr) < 0 ) perror ("[ETHERNET] Can't set the MTU"); else - printf("[ETHERNET] %s MTU size has changed to %d\n",DEFAULT_IF,ifr.ifr_mtu); - } else if (option==TX_Q_LEN) { /* change TX queue length of eth interface */ + printf("[ETHERNET] %s MTU size has changed to %d\n",eth->if_name[Mod_id],ifr.ifr_mtu); + break; + + case TX_Q_LEN: /* change TX queue length of eth interface */ ifr.ifr_addr.sa_family = AF_INET; - strncpy(ifr.ifr_name,if_name, sizeof(ifr.ifr_name)); - ifr.ifr_qlen =3000 ; + strncpy(ifr.ifr_name,eth->if_name[Mod_id], sizeof(ifr.ifr_name)); + ifr.ifr_qlen =value; if (ioctl(eth->sockfd[Mod_id],SIOCSIFTXQLEN,(caddr_t)&ifr) < 0 ) perror ("[ETHERNET] Can't set the txqueuelen"); else - printf("[ETHERNET] %s txqueuelen size has changed to %d\n",DEFAULT_IF,ifr.ifr_qlen); - - + printf("[ETHERNET] %s txqueuelen size has changed to %d\n",eth->if_name[Mod_id],ifr.ifr_qlen); + break; + /******************* device level options *************************/ - } else if (option==COALESCE_PAR) { - if (snprintf(system_cmd,sizeof(system_cmd),"ethtool -C %s rx-usecs 3",DEFAULT_IF) > 0) { - system(system_cmd); + case COALESCE_PAR: + ret=snprintf(system_cmd,sizeof(system_cmd),"ethtool -C %s rx-usecs %d",eth->if_name[Mod_id],value); + if (ret > 0) { + ret=system(system_cmd); + if (ret == -1) { + fprintf (stderr,"[ETHERNET] Can't start shell to execute %s %s",system_cmd, strerror(errno)); + } else { + printf ("[ETHERNET] status of %s is %i\n",WEXITSTATUS(ret)); + } printf("[ETHERNET] Coalesce parameters %s\n",system_cmd); } else { perror("[ETHERNET] Can't set coalesce parameters\n"); } + break; - } else if (option==PAUSE_PAR ) { - if (snprintf(system_cmd,sizeof(system_cmd),"ethtool -A %s autoneg off rx off tx off",DEFAULT_IF) > 0) { - system(system_cmd); + case PAUSE_PAR: + if (value==1) ret=snprintf(system_cmd,sizeof(system_cmd),"ethtool -A %s autoneg off rx off tx off",eth->if_name[Mod_id]); + else if (value==0) ret=snprintf(system_cmd,sizeof(system_cmd),"ethtool -A %s autoneg on rx on tx on",eth->if_name[Mod_id]); + else break; + if (ret > 0) { + ret=system(system_cmd); + if (ret == -1) { + fprintf (stderr,"[ETHERNET] Can't start shell to execute %s %s",system_cmd, strerror(errno)); + } else { + printf ("[ETHERNET] status of %s is %i\n",WEXITSTATUS(ret)); + } printf("[ETHERNET] Pause parameters %s\n",system_cmd); } else { perror("[ETHERNET] Can't set pause parameters\n"); } - } else if (option==RING_PAR ) { - if (snprintf(system_cmd,sizeof(system_cmd),"ethtool -G %s rx 4096 tx 4096",DEFAULT_IF) > 0) { - system(system_cmd); + break; + + case RING_PAR: + ret=snprintf(system_cmd,sizeof(system_cmd),"ethtool -G %s rx %d tx %d",eth->if_name[Mod_id],value); + if (ret > 0) { + ret=system(system_cmd); + if (ret == -1) { + fprintf (stderr,"[ETHERNET] Can't start shell to execute %s %s",system_cmd, strerror(errno)); + } else { + printf ("[ETHERNET] status of %s is %i\n",WEXITSTATUS(ret)); + } printf("[ETHERNET] Ring parameters %s\n",system_cmd); } else { perror("[ETHERNET] Can't set ring parameters\n"); } + break; + default: + break; } + return 0; } -int openair0_dev_init_eth(openair0_device *device, openair0_config_t *openair0_cfg) { +int transport_init(openair0_device *device, openair0_config_t *openair0_cfg, char *cfgfile) { eth_state_t *eth = (eth_state_t*)malloc(sizeof(eth_state_t)); - int card = 0; memset(eth, 0, sizeof(eth_state_t)); - eth->buffer_size = (unsigned int)openair0_cfg[card].samples_per_packet*sizeof(int32_t); // buffer size = 4096 for sample_len of 1024 - eth->sample_rate = (unsigned int)openair0_cfg[card].sample_rate; - device->priv = eth; + int card = 0; - printf("ETHERNET: Initializing openair0_device for %s ...\n", ((device->func_type == BBU_FUNC) ? "BBU": "RRH")); + /*hoedcoded!!!!*/ + eth->flags = ETH_UDP_MODE; + eth->buffer_size = (unsigned int)openair0_cfg[card].samples_per_packet*sizeof(int32_t); // buffer size = 4096 for sample_len of 1024 + + printf("[ETHERNET]: Initializing openair0_device for %s ...\n", ((device->host_type == BBU_HOST) ? "BBU": "RRH")); device->Mod_id = num_devices_eth++; + device->transp_type = ETHERNET_TP; device->trx_start_func = trx_eth_start; device->trx_request_func = trx_eth_request; device->trx_reply_func = trx_eth_reply; - device->trx_write_func = trx_eth_write; - device->trx_read_func = trx_eth_read; device->trx_get_stats_func = trx_eth_get_stats; device->trx_reset_stats_func = trx_eth_reset_stats; - device->trx_end_func = trx_eth_end; - device->trx_stop_func = trx_eth_stop; + device->trx_end_func = trx_eth_end; + device->trx_stop_func = trx_eth_stop; device->trx_set_freq_func = trx_eth_set_freq; device->trx_set_gains_func = trx_eth_set_gains; + + if ((eth->flags & ETH_RAW_MODE) != 0 ) { + device->trx_write_func = trx_eth_write_raw; + device->trx_read_func = trx_eth_read_raw; + } else { + device->trx_write_func = trx_eth_write_udp; + device->trx_read_func = trx_eth_read_udp; + } + /*hoedcoded!!!!*/ + eth->if_name[device->Mod_id] = "eth0"; + device->priv = eth; memcpy((void*)&device->openair0_cfg,(void*)openair0_cfg,sizeof(openair0_config_t)); + + /*iqoffset*/ + /*keep conf*/ + /*usrsignal */ return 0; } + + +/************************************************************************************************************************** + * DEBUGING-RELATED FUNCTIONS * + **************************************************************************************************************************/ +void dump_packet(char *title, unsigned char* pkt, int bytes, unsigned int tx_rx_flag) { + + static int numSend = 1; + static int numRecv = 1; + int num, k; + char tmp[48]; + unsigned short int cksum; + + num = (tx_rx_flag)? numSend++:numRecv++; + for (k = 0; k < 24; k++) sprintf(tmp+k, "%02X", pkt[k]); + cksum = calc_csum((unsigned short *)pkt, bytes>>2); + printf("%s-%s (%06d): %s 0x%04X\n", title,(tx_rx_flag)? "TX":"RX", num, tmp, cksum); +} + +unsigned short calc_csum (unsigned short *buf, int nwords) { + + unsigned long sum; + for (sum = 0; nwords > 0; nwords--) + sum += *buf++; + sum = (sum >> 16) + (sum & 0xffff); + sum += (sum >> 16); + return ~sum; +} + +void dump_dev(openair0_device *device) { + + eth_state_t *eth = (eth_state_t*)device->priv; + + printf("Ethernet device interface %i configuration:\n" ,device->openair0_cfg.Mod_id); + printf(" Log level is %i :\n" ,device->openair0_cfg.log_level); + printf(" RB number: %i, sample rate: %lf \n" , + device->openair0_cfg.num_rb_dl, device->openair0_cfg.sample_rate); + printf(" Delay: %i, Forward samples: %u \n" , + device->openair0_cfg.tx_delay, device->openair0_cfg.tx_forward_nsamps); + printf(" BBU configured for %i tx/%i rx channels)\n", + device->openair0_cfg.tx_num_channels,device->openair0_cfg.rx_num_channels); + printf(" Running flags: %s %s %s\n", + ((eth->flags & ETH_RAW_MODE) ? "RAW socket mode - ":""), + ((eth->flags & ETH_UDP_MODE) ? "UDP socket mode - ":""), + ((eth->flags & ETH_LOOP_MODE) ? "loopback mode - ":"")); + printf(" Number of iqs dumped when displaying packets: %i\n\n",eth->iqdumpcnt); + +} + +void inline dump_txcounters(openair0_device *device) { + eth_state_t *eth = (eth_state_t*)device->priv; + printf(" Ethernet device interface %i, tx counters:\n" ,device->openair0_cfg.Mod_id); + printf(" Sent packets: %llu send errors: %i\n", eth->tx_count, eth->num_tx_errors); +} + +void inline dump_rxcounters(openair0_device *device) { + + eth_state_t *eth = (eth_state_t*)device->priv; + printf(" Ethernet device interface %i rx counters:\n" ,device->openair0_cfg.Mod_id); + printf(" Received packets: %llu missed packets errors: %i\n", eth->rx_count, eth->num_underflows); +} + +void inline dump_buff(openair0_device *device, char *buff,unsigned int tx_rx_flag, int nsamps) { + + char *strptr; + eth_state_t *eth = (eth_state_t*)device->priv; + /*need to add ts number of iqs in printf need to fix dump iqs call */ + strptr = (( tx_rx_flag == TX_FLAG) ? "TX" : "RX"); + printf("\n %s, nsamps=%i \n" ,strptr,nsamps); + + if (tx_rx_flag == 1) { + dump_txcounters(device); + printf(" First %i iqs of TX buffer\n",eth->iqdumpcnt); + dump_iqs(buff,eth->iqdumpcnt); + } else { + dump_rxcounters(device); + printf(" First %i iqs of RX buffer\n",eth->iqdumpcnt); + dump_iqs(buff,eth->iqdumpcnt); + } + +} + +void dump_iqs(char * buff, int iq_cnt) { + int i; + for (i=0;i #include @@ -47,61 +49,95 @@ #include #include -#define MAX_INST 4 -#define DEFAULT_IF "lo" -#define BUF_SIZ 8960 /*Jumbo frame size*/ +#define MAX_INST 4 +#define DEFAULT_IF "lo" +#define ETH_RAW_MODE 1 +#define ETH_UDP_MODE (1<<1) +#define ETH_LOOP_MODE (1<<2) + +#define TX_FLAG 1 +#define RX_FLAG 0 + + +#define MAC_HEADER_SIZE_BYTES (sizeof(struct ether_header)) +#define APP_HEADER_SIZE_BYTES (sizeof(int32_t) + sizeof(openair0_timestamp)) +#define PAYLOAD_SIZE_BYTES(nsamps) (nsamps<<2) +#define UDP_PACKET_SIZE_BYTES(nsamps) (APP_HEADER_SIZE_BYTES + PAYLOAD_SIZE_BYTES(nsamps)) +#define RAW_PACKET_SIZE_BYTES(nsamps) (APP_HEADER_SIZE_BYTES + MAC_HEADER_SIZE_BYTES + PAYLOAD_SIZE_BYTES(nsamps)) +/* +#define RRH_DEST_MAC0 0x74 +#define RRH_DEST_MAC1 0xd4 +#define RRH_DEST_MAC2 0x35 +#define RRH_DEST_MAC3 0xcc +#define RRH_DEST_MAC4 0x88 +#define RRH_DEST_MAC5 0x45 + +#define BBU_DEST_MAC0 0xd4 +#define BBU_DEST_MAC1 0xbe +#define BBU_DEST_MAC2 0xd9 +#define BBU_DEST_MAC3 0x22 +#define BBU_DEST_MAC4 0x0a +#define BBU_DEST_MAC5 0xac +*/ + +/*!\brief opaque ethernet data structure */ typedef struct { - - // opaque eth data struct - //struct eth_if *dev; - // An empty ("") or NULL device identifier will result in the first encountered device being opened (using the first discovered backend) - + + /*!\brief socket file desc */ int sockfd[MAX_INST]; - struct sockaddr_in dest_addr[MAX_INST]; - + /*!\brief interface name */ + char *if_name[MAX_INST]; + /*!\brief buffer size */ unsigned int buffer_size; - unsigned int timeout_ns; - - //struct eth_metadata meta_rx; - //struct eth_metadata meta_tx; - - unsigned int sample_rate; - // time offset between transmiter timestamp and receiver timestamp; + /*!\brief timeout ms */ + unsigned int rx_timeout_ms; + /*!\brief timeout ms */ + unsigned int tx_timeout_ms; + /*!\brief runtime flags */ + uint32_t flags; + /*!\ time offset between transmiter timestamp and receiver timestamp */ double tdiff; - // use brf_time_offset to get this value - int tx_forward_nsamps; //166 for 20Mhz - - + /*!\ calibration */ + int tx_forward_nsamps; + // -------------------------------- // Debug and output control // -------------------------------- - int num_underflows; - int num_overflows; - int num_seq_errors; - int num_rx_errors; - int num_tx_errors; + + /*!\brief number of I/Q samples to be printed */ + int iqdumpcnt; - uint64_t tx_actual_nsamps; // actual number of samples transmitted + /*!\brief number of underflows in interface */ + int num_underflows; + /*!\brief number of overflows in interface */ + int num_overflows; + /*!\brief number of concesutive errors in interface */ + int num_seq_errors; + /*!\brief number of errors in interface's receiver */ + int num_rx_errors; + /*!\brief umber of errors in interface's transmitter */ + int num_tx_errors; + + /*!\brief current TX timestamp */ + openair0_timestamp tx_current_ts; + /*!\brief socket file desc */ + openair0_timestamp rx_current_ts; + /*!\brief actual number of samples transmitted */ + uint64_t tx_actual_nsamps; + /*!\brief actual number of samples received */ uint64_t rx_actual_nsamps; - uint64_t tx_nsamps; // number of planned samples + /*!\brief number of samples to be transmitted */ + uint64_t tx_nsamps; + /*!\brief number of samples to be received */ uint64_t rx_nsamps; - uint64_t tx_count; // number pf packets + /*!\brief number of packets transmitted */ + uint64_t tx_count; + /*!\brief number of packets received */ uint64_t rx_count; - //openair0_timestamp rx_timestamp; } eth_state_t; -#define ETH_META_STATUS_OVERRUN (1 << 0) -#define ETH_META_STATUS_UNDERRUN (1 << 1) - -struct eth_meta_data{ - uint64_t timestamp; - uint32_t flags; - uint32_t status; - unsigned int actual_count; -}; - /*!\brief packet header */ @@ -138,9 +174,37 @@ typedef enum { MAX_OPT } eth_opt_t; +/* +#define SND_BUF_SIZE 1 +#define RCV_BUF_SIZE 1<<1 +#define SND_TIMEOUT 1<<2 +#define RCV_TIMEOUT 1<<3 +#define MTU_SIZE 1<<4 +#define TX_Q_LEN 1<<5 +#define RING_PAR 1<<5 +#define COALESCE_PAR 1<<6 +#define PAUSE_PAR 1<<7 +*/ + +/*!\brief I/Q samples */ +typedef struct { + /*!\brief phase */ + short i; + /*!\brief quadrature */ + short q; +} iqoai_t ; + +void dump_packet(char *title, unsigned char* pkt, int bytes, unsigned int tx_rx_flag); +unsigned short calc_csum (unsigned short *buf, int nwords); +void dump_dev(openair0_device *device); +void inline dump_buff(openair0_device *device, char *buff,unsigned int tx_rx_flag,int nsamps); +void inline dump_rxcounters(openair0_device *device); +void inline dump_txcounters(openair0_device *device); +void dump_iqs(char * buff, int iq_cnt); -/*! \fn int ethernet_tune (openair0_device *device, eth_opt_t option) + +/*! \fn int ethernet_tune (openair0_device *device, unsigned int option, int value); * \brief this function allows you to configure certain ethernet parameters in socket or device level * \param[in] openair0 device which bears the socket * \param[in] name of parameter to configure @@ -148,6 +212,37 @@ typedef enum { * \note * @ingroup _oai */ -int ethernet_tune (openair0_device *device, eth_opt_t option); -int ethernet_write_data(openair0_device *device, openair0_timestamp timestamp, void **buff, int nsamps,int cc) ; -int ethernet_read_data(openair0_device *device,openair0_timestamp *timestamp,void **buff, int nsamps,int cc); +int ethernet_tune(openair0_device *device, unsigned int option, int value); + + + +/*! \fn int eth_socket_init_udp(openair0_device *device) +* \brief initialization of UDP Socket to communicate with one destination +* \param[in] *device openair device for which the socket will be created +* \param[out] +* \return 0 on success, otherwise -1 +* \note +* @ingroup _oai +*/ +int eth_socket_init_udp(openair0_device *device); +int trx_eth_write_udp(openair0_device *device, openair0_timestamp timestamp, void **buff, int nsamps,int cc, int flags); +int trx_eth_read_udp(openair0_device *device, openair0_timestamp *timestamp, void **buff, int nsamps, int cc); +int eth_get_dev_conf_udp(openair0_device *device); + +/*! \fn static int eth_set_dev_conf_udp(openair0_device *device) +* \brief +* \param[in] *device openair device +* \param[out] +* \return 0 on success, otherwise -1 +* \note +* @ingroup _oai +*/ +int eth_set_dev_conf_udp(openair0_device *device); +int eth_socket_init_raw(openair0_device *device); +int trx_eth_write_raw(openair0_device *device, openair0_timestamp timestamp, void **buff, int nsamps,int cc, int flags); +int trx_eth_read_raw(openair0_device *device, openair0_timestamp *timestamp, void **buff, int nsamps, int cc); +int eth_get_dev_conf_raw(openair0_device *device); +int eth_set_dev_conf_raw(openair0_device *device); + + +#endif diff --git a/targets/RT/USER/UE_transport_IQ.c b/targets/RT/USER/UE_transport_IQ.c index a52e3654ae..055b45ba72 100644 --- a/targets/RT/USER/UE_transport_IQ.c +++ b/targets/RT/USER/UE_transport_IQ.c @@ -284,7 +284,7 @@ void *rrh_UE_thread(void *arg) { tx_buffer_UE[i]=(tmp+4*sizeof(int32_t)); } - printf("Client %s:%d is connected (DL_RB=%d) rt=%d|%d. \n" , dev->eth_dev.openair0_cfg.remote_ip, + printf("Client %s:%d is connected (DL_RB=%d) rt=%d|%d. \n" , dev->eth_dev.openair0_cfg.remote_addr, dev->eth_dev.openair0_cfg.remote_port, dev->eth_dev.openair0_cfg.num_rb_dl, dev->eth_dev.openair0_cfg.rx_num_channels, diff --git a/targets/RT/USER/eNB_transport_IQ.c b/targets/RT/USER/eNB_transport_IQ.c index fffe93ab5f..0b4b6c5fc6 100644 --- a/targets/RT/USER/eNB_transport_IQ.c +++ b/targets/RT/USER/eNB_transport_IQ.c @@ -140,17 +140,17 @@ void config_BBU_mod( rrh_module_t *mod_enb, uint8_t RT_flag, uint8_t NRT_flag) { RT_flag_eNB=RT_flag; NRT_flag_eNB=NRT_flag; - - /* handshake with client to exchange parameters */ + + /* init socket and have handshake-like msg with client to exchange parameters */ mod_enb->eth_dev.trx_start_func(&mod_enb->eth_dev);//change port make it plus_id - + if (1==0) { /* if a RF iterface is added to RRH module get the configuration parameters sent from eNB */ - if (mod_enb->devs->type != NONE_IF ) { +if (mod_enb->devs->type != NONE_DEV ) { memcpy((void*)&mod_enb->devs->openair0_cfg,(void *)&mod_enb->eth_dev.openair0_cfg,sizeof(openair0_config_t)); /* certain parameters have to be updated (calibration related)*/ - if ( mod_enb->devs->type == EXMIMO_IF ) { + if ( mod_enb->devs->type == EXMIMO_DEV ) { if ( mod_enb->devs->openair0_cfg.num_rb_dl == 100 ) { mod_enb->devs->openair0_cfg.samples_per_packet = 2048; mod_enb->devs->openair0_cfg.tx_forward_nsamps = 175; @@ -172,7 +172,7 @@ void config_BBU_mod( rrh_module_t *mod_enb, uint8_t RT_flag, uint8_t NRT_flag) { mod_enb->devs->openair0_cfg.tx_delay = 8; } } - else if (mod_enb->devs->type == USRP_IF) { + else if (mod_enb->devs->type == USRP_DEV) { if ( mod_enb->devs->openair0_cfg.num_rb_dl == 100 ) { mod_enb->devs->openair0_cfg.samples_per_packet = 2048; mod_enb->devs->openair0_cfg.tx_forward_nsamps = 175; @@ -194,7 +194,7 @@ void config_BBU_mod( rrh_module_t *mod_enb, uint8_t RT_flag, uint8_t NRT_flag) { mod_enb->devs->openair0_cfg.tx_delay = 8; } } - else if(mod_enb->devs->type == BLADERF_IF) { + else if(mod_enb->devs->type == BLADERF_DEV) { if ( mod_enb->devs->openair0_cfg.num_rb_dl == 100 ) { mod_enb->devs->openair0_cfg.samples_per_packet = 2048; mod_enb->devs->openair0_cfg.tx_forward_nsamps = 175; @@ -221,24 +221,42 @@ void config_BBU_mod( rrh_module_t *mod_enb, uint8_t RT_flag, uint8_t NRT_flag) { check_dev_config(mod_enb); /* initialize and configure the RF device */ - if (openair0_device_init(mod_enb->devs, &mod_enb->devs->openair0_cfg)<0){ + if (openair0_device_load(mod_enb->devs, &mod_enb->devs->openair0_cfg)<0){ LOG_E(RRH,"Exiting, cannot initialize RF device.\n"); exit(-1); - } - else { - LOG_I(RRH,"RF device has been successfully initialized.\n"); - } - - /* start RF device */ - if (mod_enb->devs->type == EXMIMO_IF ) { - } else { - if (mod_enb->devs->trx_start_func(mod_enb->devs)!=0) - LOG_E(RRH,"Unable to initiate RF device.\n"); - } - LOG_I(RRH,"RF device has been initiated.\n"); + LOG_I(RRH,"RF device has been successfully initialized.\n"); + } + } - + + } else { + + memcpy((void*)&mod_enb->devs->openair0_cfg,(void *)&mod_enb->eth_dev.openair0_cfg,sizeof(openair0_config_t)); + + /* check sanity of configuration parameters and print */ + check_dev_config(mod_enb); + + /* initialize and configure the RF device */ + if (openair0_device_load(mod_enb->devs, &mod_enb->devs->openair0_cfg)<0){ + LOG_E(RRH,"Exiting, cannot initialize RF device.\n"); + exit(-1); + } else { + if (mod_enb->devs->type != NONE_DEV) { + /* start RF device */ + if (mod_enb->devs->type == EXMIMO_DEV) { + //call start function for exmino + } else { + if (mod_enb->devs->trx_start_func(mod_enb->devs)!=0) + LOG_E(RRH,"Unable to initiate RF device.\n"); + else + LOG_I(RRH,"RF device has been initiated.\n"); + } + + } + } + } + /* create main eNB module thread main_rrh_eNB_thread allocates memory for TX/RX buffers and creates TX/RX @@ -287,14 +305,14 @@ void *rrh_eNB_thread(void *arg) { tmp=(void *)malloc16(sizeof(int32_t)*(samples_per_frame + 32)); memset(tmp,0,sizeof(int32_t)*(samples_per_frame + 32)); rx_buffer_eNB[i]=( tmp + (32*sizeof(int32_t)) ); - LOG_D(RRH,"i=%d rx_buffer_eNB[i]=%p tmp= %p\n",i,rx_buffer_eNB[i],tmp); + LOG_D(RRH,"i=%d rx_buffer_eNB[i]=%p tmp= %p samples_per_frame=%d\n",i,rx_buffer_eNB[i],tmp, samples_per_frame); } /* tx_buffer_eNB points to the beginning of data */ for (i=0; ieth_dev.openair0_cfg.tx_num_channels; i++) { tmp=(void *)malloc16(sizeof(int32_t)*(samples_per_frame + 32)); memset(tmp,0,sizeof(int32_t)*(samples_per_frame + 32)); tx_buffer_eNB[i]=( tmp + (32*sizeof(int32_t)) ); - LOG_D(RRH,"i= %d tx_buffer_eNB[i]=%p tmp= %p \n",i,tx_buffer_eNB[i],tmp); + LOG_D(RRH,"i= %d tx_buffer_eNB[i]=%p tmp= %p samples_per_frame=%d\n",i,tx_buffer_eNB[i],tmp, samples_per_frame); } /* dummy initialization for TX/RX buffers */ for (i=0; ieth_dev.openair0_cfg.rx_num_channels; i++) { @@ -353,7 +371,7 @@ void *rrh_eNB_thread(void *arg) { } /* create timer thread; when no RF device is present a software clock is generated */ - if (dev->devs->type == NONE_IF) { + if (dev->devs->type == NONE_DEV) { int error_code_timer; pthread_t main_timer_proc_thread; @@ -405,10 +423,11 @@ void *rrh_eNB_thread(void *arg) { return(0); } +/* Receive from RF and transmit to RRH */ void *rrh_eNB_rx_thread(void *arg) { - /* measuremnt related vars */ + /* measurement related vars */ struct timespec time0,time1,time2; unsigned long long max_rx_time=0, min_rx_time=rt_period, total_rx_time=0, average_rx_time=rt_period, s_period=0, trial=0; int trace_cnt=0; @@ -463,7 +482,7 @@ void *rrh_eNB_rx_thread(void *arg) { VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_RX_PCK, pck_rx ); LOG_D(RRH,"pack=%d rx_pos=%d subframe=%d frame=%d\n ",pck_rx, rx_pos, subframe,frame); - if (dev->devs->type == NONE_IF) { + if (dev->devs->type == NONE_DEV) { VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_RX_HWCNT, hw_counter ); VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_RX_LHWCNT, last_hw_counter ); VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_CNT, s_cnt ); @@ -506,7 +525,7 @@ void *rrh_eNB_rx_thread(void *arg) { LOG_D(RRH," rx_eNB[i]=%p rx_buffer_eNB[i][rx_pos]=%p ,rx_pos=%d, i=%d ts=%d\n",rx_eNB[i],&rx_buffer_eNB[i][rx_pos],rx_pos,i,timestamp_rx); } VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_RXCNT, rx_pos ); - if (dev->devs->type != NONE_IF) { + if (dev->devs->type != NONE_DEV) { VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ_RF, 1 ); /* Read operation to RF device (RX)*/ if ( dev->devs->trx_read_func (dev->devs, @@ -533,7 +552,7 @@ void *rrh_eNB_rx_thread(void *arg) { VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE, 0 ); /* when there is no RF timestamp is updated by number of samples */ - if (dev->devs->type == NONE_IF) { + if (dev->devs->type == NONE_DEV) { timestamp_rx+=spp_eth; last_hw_counter=hw_counter; } @@ -559,7 +578,7 @@ void *rrh_eNB_rx_thread(void *arg) { } if (s_period++ == PRINTF_PERIOD) { s_period=0; - LOG_I(RRH,"Average eNB RX time : %lu\tMax RX time : %lu\tMin RX time : %lu\n",average_rx_time,max_rx_time,min_rx_time); + LOG_I(RRH,"Average eNB RX time : %lu ns\tMax RX time : %lu ns\tMin RXX time : %lu ns\n",average_rx_time,max_rx_time,min_rx_time); } } @@ -577,17 +596,7 @@ void *rrh_eNB_rx_thread(void *arg) { next_rx_pos=(rx_pos+spp_eth); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_RX, 0 ); - /**/ - if (frame>50) { - pthread_mutex_lock(&sync_trx_mutex); - while (sync_trx) { - pthread_cond_wait(&sync_trx_cond,&sync_trx_mutex); - } - sync_trx=1; - LOG_D(RRH,"out of while send:%d %d\n",sync_trx,frame); - pthread_cond_signal(&sync_trx_cond); - pthread_mutex_unlock(&sync_trx_mutex); - } + } // while subframe++; @@ -609,6 +618,7 @@ void *rrh_eNB_rx_thread(void *arg) { return 0; } +/* Receive from eNB and transmit to RF */ void *rrh_eNB_tx_thread(void *arg) { @@ -660,45 +670,13 @@ void *rrh_eNB_tx_thread(void *arg) { while (rrh_exit == 0) { while (tx_pos < (1 + subframe)*samples_per_subframe) { - LOG_D(RRH,"bef lock read:%d %d\n",sync_trx,frame); - pthread_mutex_lock(&sync_trx_mutex); - - while (!sync_trx) { - LOG_D(RRH,"in sync read:%d %d\n",sync_trx,frame); - pthread_cond_wait(&sync_trx_cond,&sync_trx_mutex); - } - LOG_D(RRH,"out of while read:%d %d\n",sync_trx,frame); + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_TX, 1 ); VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_HW_FRAME, frame); VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_HW_SUBFRAME, subframe ); VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TX_PCK, pck_tx ); - - /* - if (dev->devs->type == NONE_IF) { - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TX_HWCNT, hw_counter ); - VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TX_LHWCNT, last_hw_counter ); - - if (!eNB_tx_started) { - eNB_tx_started=1; // set this flag to 1 to indicate that eNB started - if (RT_flag_eNB==1) { - last_hw_counter=hw_counter; - } - } else { - if (RT_flag_eNB==1) { - if (hw_counter > last_hw_counter+1) { - printf("LT"); - } else { - while ((hw_counter < last_hw_counter+1)) { - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_TX_SLEEP, 1 ); - nanosleep(&time_req_1us,&time_rem_1us); - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_TX_SLEEP, 0 ); - } - } - } - } - } */ - + if (measurements == 1 ) clock_gettime(CLOCK_MONOTONIC,&time1); for (i=0; ieth_dev.openair0_cfg.tx_num_channels; i++) tx_eNB[i] = (void*)&tx_buffer_eNB[i][tx_pos]; //RF!!!!! @@ -715,7 +693,7 @@ void *rrh_eNB_tx_thread(void *arg) { } VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ, 0 ); - if (dev->devs->type != NONE_IF) { + if (dev->devs->type != NONE_DEV) { LOG_D(RRH," tx_buffer_eNB[i][tx_pos]=%x t_buffer_eNB[i][tx_pos+1]=%x t_buffer_eNB[i][tx_pos+2]=%x \n",tx_buffer_eNB[0][tx_pos],tx_buffer_eNB[0][tx_pos+1],tx_buffer_eNB[0][tx_pos+2]); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE_RF, 1 ); /* Write operation to RF device (TX)*/ @@ -733,7 +711,7 @@ void *rrh_eNB_tx_thread(void *arg) { VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TX_TS, timestamp_tx&0xffffffff ); - if (dev->devs->type == NONE_IF) last_hw_counter=hw_counter; + if (dev->devs->type == NONE_DEV) last_hw_counter=hw_counter; if (loopback ==1 ) { @@ -755,9 +733,7 @@ void *rrh_eNB_tx_thread(void *arg) { pck_tx++; VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_TX, 0 ); - sync_trx=0; - pthread_cond_signal(&sync_trx_cond); - pthread_mutex_unlock(&sync_trx_mutex); + } /* wrap around tx buffer index */ @@ -784,8 +760,7 @@ static void calc_rt_period_ns( openair0_config_t openair0_cfg) { static void check_dev_config( rrh_module_t *mod_enb) { - - + AssertFatal( (mod_enb->devs->openair0_cfg.num_rb_dl==100 || mod_enb->devs->openair0_cfg.num_rb_dl==50 || mod_enb->devs->openair0_cfg.num_rb_dl==25 || mod_enb->devs->openair0_cfg.num_rb_dl==6) , "Invalid number of resource blocks! %d\n", mod_enb->devs->openair0_cfg.num_rb_dl); AssertFatal( mod_enb->devs->openair0_cfg.samples_per_frame > 0 , "Invalid number of samples per frame! %d\n",mod_enb->devs->openair0_cfg.samples_per_frame); AssertFatal( mod_enb->devs->openair0_cfg.sample_rate > 0.0, "Invalid sample rate! %f\n", mod_enb->devs->openair0_cfg.sample_rate); @@ -802,7 +777,7 @@ static void check_dev_config( rrh_module_t *mod_enb) { printf("\n---------------------RF device configuration parameters---------------------\n"); - printf("\tMod_id=%d\n \tlog level=%d\n \tDL_RB=%d\n \tsamples_per_frame=%d\n \tsample_rate=%f\n \tsamples_per_packet=%d\n \ttx_delay=%d\n \ttx_forward_nsamps=%d\n \trx_num_channels=%d\n \ttx_num_channels=%d\n \trx_freq_0=%f\n \ttx_freq_0=%f\n \trx_freq_1=%f\n \ttx_freq_1=%f\n \trx_freq_2=%f\n \ttx_freq_2=%f\n \trx_freq_3=%f\n \ttx_freq_3=%f\n \trxg_mode=%d\n \trx_gain_0=%f\n \ttx_gain_0=%f\n \trx_gain_1=%f\n \ttx_gain_1=%f\n \trx_gain_2=%f\n \ttx_gain_2=%f\n \trx_gain_3=%f\n \ttx_gain_3=%f\n \trx_gain_offset_2=%f\n \ttx_gain_offset_3=%f\n \trx_bw=%f\n \ttx_bw=%f\n \tautocal=%d\n \trem_addr %s:%d\n \tmy_addr %s:%d\n", + printf("\tMod_id=%d\n \tlog level=%d\n \tDL_RB=%d\n \tsamples_per_frame=%d\n \tsample_rate=%f\n \tsamples_per_packet=%d\n \ttx_delay=%d\n \ttx_forward_nsamps=%d\n \trx_num_channels=%d\n \ttx_num_channels=%d\n \trx_freq_0=%f\n \ttx_freq_0=%f\n \trx_freq_1=%f\n \ttx_freq_1=%f\n \trx_freq_2=%f\n \ttx_freq_2=%f\n \trx_freq_3=%f\n \ttx_freq_3=%f\n \trxg_mode=%d\n \trx_gain_0=%f\n \ttx_gain_0=%f\n \trx_gain_1=%f\n \ttx_gain_1=%f\n \trx_gain_2=%f\n \ttx_gain_2=%f\n \trx_gain_3=%f\n \ttx_gain_3=%f\n \trx_gain_offset_2=%f\n \ttx_gain_offset_3=%f\n \trx_bw=%f\n \ttx_bw=%f\n \tautocal=%d\n", mod_enb->devs->openair0_cfg.Mod_id, mod_enb->devs->openair0_cfg.log_level, mod_enb->devs->openair0_cfg.num_rb_dl, @@ -836,11 +811,7 @@ static void check_dev_config( rrh_module_t *mod_enb) { mod_enb->devs->openair0_cfg.rx_gain_offset[3], mod_enb->devs->openair0_cfg.rx_bw, mod_enb->devs->openair0_cfg.tx_bw, - mod_enb->devs->openair0_cfg.autocal[0], - mod_enb->devs->openair0_cfg.remote_ip, - mod_enb->devs->openair0_cfg.remote_port, - mod_enb->devs->openair0_cfg.my_ip, - mod_enb->devs->openair0_cfg.my_port + mod_enb->devs->openair0_cfg.autocal[0] ); printf("----------------------------------------------------------------------------\n"); diff --git a/targets/RT/USER/rrh_gw.c b/targets/RT/USER/rrh_gw.c index 39b726ae07..c479c2a211 100644 --- a/targets/RT/USER/rrh_gw.c +++ b/targets/RT/USER/rrh_gw.c @@ -51,9 +51,9 @@ #include #include "common_lib.h" -#include "rrh_gw.h" // change to rrh_new.h, put externs in rrh_extern.h +#include "rrh_gw.h" #include "rt_wrapper.h" -#include "rrh_gw_externs.h" // change to rrh_new.h, put externs in rrh_extern.h +#include "rrh_gw_externs.h" #include "log_if.h" @@ -72,7 +72,8 @@ -char rrh_ip[20] = "192.168.12.242"; // there is code to detect the my ip address +char rrh_ip[20] = "0.0.0.0"; // there is code to detect my ip address +unsigned char rrh_mac[6] = "0:0:0:0:0:0"; int rrh_port = 50000; // has to be an option /* log */ @@ -86,7 +87,7 @@ int16_t ue_log_level = LOG_INFO; int16_t ue_log_verbosity = LOG_MED; -/* flags definitions */ +/* flag definitions */ uint8_t eNB_flag=0; uint8_t UE_flag=0; uint8_t EXMIMO_flag=0; @@ -102,10 +103,8 @@ uint8_t measurements_flag=0; - default ethernet interface is local */ uint8_t num_eNB_mod=0; uint8_t num_UE_mod=0; -uint8_t num_EXMIMO_mod=0; -uint8_t num_USRP_mod=0; -uint8_t hardware_target=NONE_IF; char* if_name="lo"; +uint8_t eth_mode=ETH_UDP_MODE; rrh_module_t *enb_array; rrh_module_t *ue_array; @@ -128,14 +127,14 @@ static void print_help(void); */ static rrh_module_t new_module(unsigned int id); -/*!\fn static int get_ip_address(char* if_name) +/*!\fn static int get_address(char* if_name, uint8_t flag); * \brief retrieves IP address from the specified network interface * \param[in] name of network interface * \return 0 * \note * @ingroup _oai */ -static int get_ip_address(char* if_name); +static int get_address(char* if_name, uint8_t flag); @@ -192,48 +191,45 @@ static rrh_module_t new_module (unsigned int id) { rrh_mod.measurements=measurements_flag; /* each module is associated with an ethernet device */ - rrh_mod.eth_dev.type=ETH_IF; + rrh_mod.eth_dev.type=NONE_DEV; + rrh_mod.eth_dev.transp_type=NONE_TP; /* ethernet device is functioning within RRH */ - rrh_mod.eth_dev.func_type=RRH_FUNC; - /* specify IP address */ - get_ip_address(if_name); - openair0_cfg.my_ip=&rrh_ip[0]; - openair0_cfg.my_port=rrh_port; + rrh_mod.eth_dev.host_type=RRH_HOST; + /* get IP and MAC address */ + get_address(if_name,eth_mode); + + if(eth_mode==ETH_UDP_MODE) { + openair0_cfg.my_addr = &rrh_ip[0]; + openair0_cfg.my_port = rrh_port; + LOG_I(RRH,"UDP mode selected for ethernet.\n"); + } else if (eth_mode==ETH_RAW_MODE) { + openair0_cfg.my_addr = &rrh_mac[0]; + openair0_cfg.my_port = rrh_port; + LOG_I(RRH,"RAW mode selected for ethernet.\n"); + } + + /* if use setrunnig parameters we should keep in device->priv keep if_name and raw/udp flag*/ /* ethernet device initialization */ - if (openair0_dev_init_eth(&rrh_mod.eth_dev, &openair0_cfg)<0){ + if (openair0_transport_load(&rrh_mod.eth_dev, &openair0_cfg)<0,NULL) { LOG_E(RRH,"Exiting, cannot initialize ethernet interface.\n"); exit(-1); } /* allocate space and specify associated RF device */ openair0_device *oai_dv = (openair0_device *)malloc(sizeof(openair0_device)); - memset(oai_dv,0, sizeof(openair0_device)); - -#ifdef EXMIMO + memset(oai_dv,0,sizeof(openair0_device)); rrh_mod.devs=oai_dv; - rrh_mod.devs->type=EXMIMO_IF; - LOG_I(RRH,"Setting RF device to EXMIMO\n"); -#elif OAI_USRP - rrh_mod.devs=oai_dv; - rrh_mod.devs->type=USRP_IF; - LOG_I(RRH,"Setting RF device to USRP\n"); -#elif OAI_BLADERF - rrh_mod.devs=oai_dv; - rrh_mod.devs->type=BLADERF_IF; - LOG_I(RRH,"Setting RF device to BLADERF\n"); -#else - rrh_mod.devs=oai_dv; - rrh_mod.devs->type=NONE_IF; - LOG_I(RRH,"Setting RF interface to NONE_IF... \n"); -#endif - + rrh_mod.devs->type=NONE_DEV; + rrh_mod.devs->transp_type=NONE_TP; + rrh_mod.devs->host_type=RRH_HOST; + return rrh_mod; } static void debug_init(void) { - // log initialization + /* log initialization */ logInit(); set_glog(glog_level, glog_verbosity); @@ -241,7 +237,7 @@ static void debug_init(void) { //set_comp_log(ENB_LOG, enb_log_level, enb_log_verbosity, 1); //set_comp_log(UE_LOG, ue_log_level, ue_log_verbosity, 1); - // vcd initialization + /* vcd initialization */ if (ouput_vcd) { vcd_signal_dumper_init("/tmp/openair_dump_rrh.vcd"); @@ -253,7 +249,7 @@ static void get_options(int argc, char *argv[]) { int opt; - while ((opt = getopt(argc, argv, "xvhlte:n:u:g:r:w:i:")) != -1) { + while ((opt = getopt(argc, argv, "xvhlte:n:u:g:r:m:i:")) != -1) { switch (opt) { case 'n': @@ -273,6 +269,9 @@ static void get_options(int argc, char *argv[]) { printf("RRH interface name is set to %s\n", if_name); } break; + case 'm': + eth_mode=atoi(optarg); + break; case 'r': //rrh_log_level=atoi(optarg); break; @@ -293,49 +292,48 @@ static void get_options(int argc, char *argv[]) { loopback_flag=1; break; case 't': - /*When measurements are enabled statistics related to TX/RX time are printed*/ + /* When measurements are enabled statistics related to TX/RX time are printed */ measurements_flag=1; - break; - case 'w': - /* force to use this target*/ - hardware_target=1; - break; - case 'h': - print_help(); - exit(-1); + break; + case 'h': + print_help(); + exit(-1); default: /* '?' */ //fprintf(stderr, "Usage: \n", argv[0]); exit(-1); - } + } } } -static int get_ip_address(char* if_name) { +static int get_address(char* if_name, uint8_t flag) { int fd; struct ifreq ifr; - - - fd = socket(AF_INET, SOCK_DGRAM, 0); - + + fd = socket(AF_INET, SOCK_DGRAM, 0); /* I want to get an IPv4 IP address */ - ifr.ifr_addr.sa_family = AF_INET; - + ifr.ifr_addr.sa_family = AF_INET; /* I want IP address attached to "if_name" */ strncpy(ifr.ifr_name, if_name, IFNAMSIZ-1); - - if ( ioctl(fd, SIOCGIFADDR, &ifr)<0 ) { - perror("IOCTL:"); - exit(-1); - } + + if (flag==ETH_UDP_MODE) { + if ( ioctl(fd, SIOCGIFADDR, &ifr)<0 ) { + perror("IOCTL:"); + exit(-1); + } + snprintf(&rrh_ip[0],20,"%s", inet_ntoa(((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr)); + LOG_I(RRH,"%s: IP address: %s\n",if_name,rrh_ip); + } else if (flag==ETH_RAW_MODE) { + if ( ioctl(fd, SIOCGIFHWADDR, &ifr)<0 ) { + perror("IOCTL:"); + exit(-1); + } + ether_ntoa_r ((unsigned char *)ifr.ifr_hwaddr.sa_data, rrh_mac); + LOG_I(RRH,"%s: MAC address: %s\n",if_name,rrh_mac); + } close(fd); - - /* display result */ - snprintf(&rrh_ip[0],20,"%s", inet_ntoa(((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr)); - LOG_I(RRH,"Got IP address %s from interface %s\n", rrh_ip,if_name); - return 0; } @@ -343,19 +341,19 @@ static int get_ip_address(char* if_name) { static void print_help(void) { puts("Usage: \n"); - puts(" sudo -E chrt 99 ./rrh -n1 -g6 -v -t"); + puts(" sudo -E chrt 99 ./rrh -n1 -g6 -v -t -i lo -m1"); puts("Options:\n"); puts("\t -n create eNB module\n"); puts("\t -u create UE module\n"); puts("\t -g define global log level\n"); puts("\t -i set the RRH interface (default lo)\n"); + puts("\t -m set ethernet mode to be used by RRH, valid options: (1:raw, 2:udp) \n"); puts("\t -r define rrh log level\n"); puts("\t -e define eNB log level\n"); puts("\t -x enable real time bahaviour\n"); puts("\t -v enable vcd dump\n"); puts("\t -l enable loopback mode\n"); puts("\t -t enable measurements\n"); - puts("\t -w force to use specified HW\n"); puts("\t -h display info\n"); } From 40d6386969666c524661f17775467d4d14ee2ac5 Mon Sep 17 00:00:00 2001 From: "aikaterini.trilyraki" Date: Thu, 19 Nov 2015 17:00:19 +0100 Subject: [PATCH 009/263] lte-softmodem updated to reflect the fact that ethernet is not considered a device anymore- '-M' option changed used to be RRH IP address now it's flag for local/remote RF --- targets/RT/USER/lte-softmodem.c | 107 ++++++++++++++++++++------------ 1 file changed, 68 insertions(+), 39 deletions(-) diff --git a/targets/RT/USER/lte-softmodem.c b/targets/RT/USER/lte-softmodem.c index b96a7ae529..f16f0b9eb8 100644 --- a/targets/RT/USER/lte-softmodem.c +++ b/targets/RT/USER/lte-softmodem.c @@ -361,12 +361,14 @@ int16_t osa_log_verbosity = LOG_MED; #ifdef ETHERNET -char rrh_eNB_ip[20] = "127.0.0.1"; -int rrh_eNB_port = 50000; -char *rrh_UE_ip = "127.0.0.1"; -int rrh_UE_port = 51000; +//char rrh_eNB_ip[20] = "127.0.0.1"; +//int rrh_eNB_port = 50000; +//char *rrh_UE_ip = "127.0.0.1"; +//int rrh_UE_port = 51000; #endif - +/* flag given in runtime to specify if the RF head is local or remote*/ +uint8_t local_remote_RF; + char uecap_xer[1024],uecap_xer_in=0; extern void *UE_thread(void *arg); extern void init_UE_threads(void); @@ -430,7 +432,7 @@ void help (void) { printf(" -h provides this help message!\n"); printf(" -K Generate ITTI analyzser logs (similar to wireshark logs but with more details)\n"); printf(" -m Set the maximum downlink MCS\n"); - printf(" -M IP address of RRH\n"); + printf(" -M Specify whether RF head is local or remote,valid options: (1: local , 2:remote) \n"); printf(" -O eNB configuration file (located in targets/PROJECTS/GENERIC-LTE-EPC/CONF\n"); printf(" -q Enable processing timing measurement of lte softmodem on per subframe basis \n"); printf(" -r Set the PRB, valid values: 6, 25, 50, 100 \n"); @@ -1818,9 +1820,11 @@ static void* eNB_thread( void* arg ) // USRP_DEBUG is active rt_sleep_ns(1000000); #endif - +/* FT configurable tx lauch delay (in slots )*/ if ((tx_launched == 0) && - (rx_pos >= (((2*hw_subframe)+1)*PHY_vars_eNB_g[0][0]->lte_frame_parms.samples_per_tti>>1))) { + ((openair0_cfg[card].txlaunch_wait == 0) || + ((openair0_cfg[card].txlaunch_wait == 1) && + (rx_pos >= (((2*hw_subframe)+openair0_cfg[card].txlaunch_wait_slotcount)*PHY_vars_eNB_g[0][0]->lte_frame_parms.samples_per_tti>>1))))) { tx_launched = 1; for (CC_id=0; CC_idN_RB_DL == 50) { sample_rate = 15.36e6; @@ -2868,8 +2870,8 @@ int main( int argc, char **argv ) openair0_cfg[card].samples_per_frame = 153600; openair0_cfg[card].tx_bw = 5e6; openair0_cfg[card].rx_bw = 5e6; - openair0_cfg[card].tx_forward_nsamps = 95; - openair0_cfg[card].tx_delay = 5; + //openair0_cfg[card].tx_forward_nsamps = 95; + //openair0_cfg[card].tx_delay = 5; #endif } else if (frame_parms[0]->N_RB_DL == 25) { sample_rate = 7.68e6; @@ -2881,12 +2883,14 @@ int main( int argc, char **argv ) openair0_cfg[card].rx_bw = 2.5e6; openair0_cfg[card].samples_per_packet = 1024; #ifdef OAI_USRP - openair0_cfg[card].tx_forward_nsamps = 70; - openair0_cfg[card].tx_delay = 5; -#elif OAI_BLADERF - openair0_cfg[card].tx_forward_nsamps = 0; - openair0_cfg[card].tx_delay = 8; -#endif + + openair0_cfg[card].tx_forward_nsamps = 70; + openair0_cfg[card].tx_delay = 5; +#endif + //#elif OAI_BLADERF + //openair0_cfg[card].tx_forward_nsamps = 0; + //openair0_cfg[card].tx_delay = 8; + //#endif #endif } else if (frame_parms[0]->N_RB_DL == 6) { sample_rate = 1.92e6; @@ -2897,16 +2901,25 @@ int main( int argc, char **argv ) openair0_cfg[card].samples_per_frame = 19200; openair0_cfg[card].tx_bw = 1.5e6; openair0_cfg[card].rx_bw = 1.5e6; - openair0_cfg[card].tx_forward_nsamps = 40; - openair0_cfg[card].tx_delay = 8; + //openair0_cfg[card].tx_forward_nsamps = 40; + //openair0_cfg[card].tx_delay = 8; #endif } #ifdef ETHERNET - //calib needed - openair0_cfg[card].tx_delay = 0; + openair0_cfg[card].remote_addr = "192.168.12.242"; + //openair0_cfg[card].remote_addr = "127.0.0.1"; +// openair0_cfg[card].remote_addr = "74:d4:35:cc:88:45"; + openair0_cfg[card].remote_port = 50000; + openair0_cfg[card].my_addr = "192.168.12.31"; + //openair0_cfg[card].my_addr = "127.0.0.1"; + //openair0_cfg[card].my_addr = "d4:be:d9:22:0a:ac"; + openair0_cfg[card].my_port = 50001; + openair0_cfg[card].tx_delay = 5; openair0_cfg[card].tx_forward_nsamps = 0; + openair0_cfg[card].txlaunch_wait = 0; + openair0_cfg[card].txlaunch_wait_slotcount = 0; if (frame_parms[0]->N_RB_DL == 6) openair0_cfg[card].samples_per_packet = 256; @@ -2924,17 +2937,18 @@ int main( int argc, char **argv ) ((UE_flag==0) ? PHY_vars_eNB_g[0][0]->lte_frame_parms.nb_antennas_tx : PHY_vars_UE_g[0][0]->lte_frame_parms.nb_antennas_tx), ((UE_flag==0) ? PHY_vars_eNB_g[0][0]->lte_frame_parms.nb_antennas_rx : PHY_vars_UE_g[0][0]->lte_frame_parms.nb_antennas_rx)); openair0_cfg[card].Mod_id = 0; -#ifdef ETHERNET - +#ifdef ETHERNET/*do we need to separate ue and enb????*/ + /* if (UE_flag) { printf("ETHERNET: Configuring UE ETH for %s:%d\n",rrh_UE_ip,rrh_UE_port); - openair0_cfg[card].remote_ip = &rrh_UE_ip[0]; + openair0_cfg[card].remote_addr = &rrh_UE_ip[0]; openair0_cfg[card].remote_port = rrh_UE_port; } else { printf("ETHERNET: Configuring eNB ETH for %s:%d\n",rrh_eNB_ip,rrh_eNB_port); - openair0_cfg[card].remote_ip = &rrh_eNB_ip[0]; - openair0_cfg[card].remote_port = rrh_eNB_port; + openair0_cfg[card].remote_addr =&rrh_eNB_ip[0]; + openair0_cfg[card].remote_port =rrh_eNB_port; } + */ openair0_cfg[card].num_rb_dl=frame_parms[0]->N_RB_DL; #endif openair0_cfg[card].sample_rate = sample_rate; @@ -2988,18 +3002,33 @@ openair0_cfg[card].num_rb_dl=frame_parms[0]->N_RB_DL; #endif } - - openair0.func_type = BBU_FUNC; + /* device host type is set*/ + openair0.host_type = BBU_HOST; + /* device type is initialized NONE_DEV (no RF device) when the RF device will be initiated device type will be set */ + openair0.type = NONE_DEV; + openair0.transp_type = NONE_TP; openair0_cfg[0].log_level = glog_level; - if ((mode!=loop_through_memory) && - (openair0_device_init(&openair0, &openair0_cfg[0]) <0)) { - printf("Exiting, cannot initialize device\n"); - exit(-1); + /* BBU can either have local or remote radio heads */ + if (local_remote_RF == BBU_LOCAL_RF_ENABLED) { /* radio heads are local so the corresponding device is initiated */ + + if ((mode!=loop_through_memory) && + (openair0_device_load(&openair0, &openair0_cfg[0]) <0)) { + printf("Exiting, cannot initialize device\n"); + exit(-1); + } + else if (mode==loop_through_memory) { + } + } else if (local_remote_RF == BBU_REMOTE_RF_ENABLED) {/* radio heads are remote so the trasnsport protocol is initiated */ + if ((mode!=loop_through_memory) && + (openair0_transport_load(&openair0, &openair0_cfg[0]) <0)) { + printf("Exiting, cannot initialize transport protocol\n"); + exit(-1); + } + else if (mode==loop_through_memory) { + } } - else if (mode==loop_through_memory) { - } - + printf("Done\n"); mac_xface = malloc(sizeof(MAC_xface)); From a85c64c3cf387e858e6b881c0e3352db161c0393 Mon Sep 17 00:00:00 2001 From: "aikaterini.trilyraki" Date: Thu, 19 Nov 2015 17:28:52 +0100 Subject: [PATCH 010/263] build_oai script and cmake updated - rf device and transport protocol libraries are dynamically linked Note: EXMIMO not supported yet (even though compilation is successful) --- cmake_targets/CMakeLists.txt | 113 +++++++++++++++++------ cmake_targets/build_oai | 169 +++++++++++++++++++++++++++-------- 2 files changed, 217 insertions(+), 65 deletions(-) diff --git a/cmake_targets/CMakeLists.txt b/cmake_targets/CMakeLists.txt index 17d921d4d9..1600d13b5b 100644 --- a/cmake_targets/CMakeLists.txt +++ b/cmake_targets/CMakeLists.txt @@ -36,7 +36,7 @@ set (OPENAIR1_DIR ${OPENAIR_DIR}/openair1) set (OPENAIR2_DIR ${OPENAIR_DIR}/openair2) set (OPENAIR3_DIR ${OPENAIR_DIR}/openair3) set (OPENAIR_TARGETS ${OPENAIR_DIR}/targets) -set (OPENAIR3_DIR ${OPENAIR_DIR}/openair3) +set (OPENAIR3_DIR ${OPENAIR_DIR}/openair3) set (OPENAIR_CMAKE ${OPENAIR_DIR}/cmake_targets) set (OPENAIR_BIN_DIR ${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}) @@ -407,8 +407,47 @@ add_list1_option(NB_ANTENNAS_RX "2" "Number of antennas in reception" "1" "2" "4 add_list1_option(NB_ANTENNAS_TX "2" "Number of antennas in transmission" "1" "2" "4") add_list1_option(NB_ANTENNAS_TXRX "2" "Number of antennas in ????" "1" "2" "4") -add_list2_option(RF_BOARD "EXMIMO" "RF head type" "False" "EXMIMO" "OAI_USRP" "ETHERNET" "OAI_BLADERF" "CPRIGW") +add_list2_option(RF_BOARD "NO_VALUE" "RF head type" "False" "EXMIMO" "OAI_USRP" "OAI_BLADERF" "CPRIGW" "NO_VALUE")# make cleanup false rf_head_type cprigw??? +add_list2_option(TRANSP_PRO "NO_VALUE" "ETHERNET" "NO_VALUE") + + +# include RF devices / transport protocols library modules +###################################################################### + +include_directories("${OPENAIR_TARGETS}/ARCH/EXMIMO/USERSPACE/LIB/") +include_directories ("${OPENAIR_TARGETS}/ARCH/EXMIMO/DEFS/") +#set (option_HWEXMIMOLIB_lib "-l ") +set(HWLIB_EXMIMO_SOURCE + ${OPENAIR_TARGETS}/ARCH/EXMIMO/USERSPACE/LIB/openair0_lib.c + ${OPENAIR_TARGETS}/ARCH/EXMIMO/USERSPACE/LIB/gain_control.c + ) +add_library(oai_exmimodevif MODULE ${HWLIB_EXMIMO_SOURCE} ) + +include_directories("${OPENAIR_TARGETS}/ARCH/USRP/USERSPACE/LIB/") +set (option_HWUSRPLIB_lib "-l uhd") +set(HWLIB_USRP_SOURCE + ${OPENAIR_TARGETS}/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp + ) +add_library(oai_usrpdevif MODULE ${HWLIB_USRP_SOURCE} ) + +include_directories("${OPENAIR_TARGETS}/ARCH/BLADERF/USERSPACE/LIB/") +set (option_HWBLADERFLIB_lib "-l bladerf") +set(HWLIB_BLADERF_SOURCE + ${OPENAIR_TARGETS}/ARCH/BLADERF/USERSPACE/LIB/bladerf_lib.c + ) +add_library(oai_bladerfdevif MODULE ${HWLIB_BLADERF_SOURCE} ) + +include_directories("${OPENAIR_TARGETS}/ARCH/ETHERNET/USERSPACE/LIB/") +set(TPLIB_ETHERNET_SOURCE + ${OPENAIR_TARGETS}/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c + ${OPENAIR_TARGETS}/ARCH/ETHERNET/USERSPACE/LIB/eth_udp.c + ${OPENAIR_TARGETS}/ARCH/ETHERNET/USERSPACE/LIB/eth_raw.c + ) +add_library(oai_eth_transpro MODULE ${TPLIB_ETHERNET_SOURCE} ) + +# RF devices / transport protocols settings +###################################################################### if (${RF_BOARD} STREQUAL "EXMIMO") set(DRIVER2013) include_directories ("${OPENAIR_TARGETS}/ARCH/EXMIMO/USERSPACE/LIB/") @@ -416,6 +455,7 @@ if (${RF_BOARD} STREQUAL "EXMIMO") set(HW_SOURCE ${HW_SOURCE} ${OPENAIR_TARGETS}/ARCH/EXMIMO/USERSPACE/LIB/openair0_lib.c ${OPENAIR_TARGETS}/ARCH/EXMIMO/USERSPACE/LIB/gain_control.c) + set(option_HW_lib "-rdynamic -ldl") elseif (${RF_BOARD} STREQUAL "OAI_USRP") include_directories("${OPENAIR_TARGETS}/ARCH/USRP/USERSPACE/LIB/") @@ -423,7 +463,7 @@ elseif (${RF_BOARD} STREQUAL "OAI_USRP") set(HW_SOURCE ${HW_SOURCE} ${OPENAIR_TARGETS}/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp) LINK_DIRECTORIES("/opt/lib") - set(option_HW_lib "uhd") + set(option_HW_lib "-luhd -rdynamic -ldl") set(LOWLATENCY False) elseif (${RF_BOARD} STREQUAL "OAI_BLADERF") @@ -434,27 +474,34 @@ elseif (${RF_BOARD} STREQUAL "OAI_BLADERF") ${OPENAIR_TARGETS}/ARCH/BLADERF/USERSPACE/LIB/bladerf_lib.c ) LINK_DIRECTORIES("/usr/lib/x86_64-linux-gnu") - set(option_HW_lib "bladeRF") -#set(LOWLATENCY False) - -elseif (${RF_BOARD} STREQUAL "ETHERNET") - include_directories ("${OPENAIR_TARGETS}/ARCH/ETHERNET/USERSPACE/LIB") - set(HW_SOURCE ${HW_SOURCE} - ${OPENAIR_TARGETS}/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c - ) - set(LOWLATENCY True) - -elseif (${RF_BOARD} STREQUAL "CPRIGW") + set(option_HW_lib "bladeRF -rdynamic -ldl") + #set(LOWLATENCY False) + +elseif (${RF_BOARD} STREQUAL "CPRIGW") #to ask set(HW_SOURCE ${HW_SOURCE} ${OPENAIR_TARGETS}/ARCH/CPRIGW/USERSPACE/LIB/cprigw_lib.c ) include_directories("${OPENAIR_TARGETS}/ARCH/CPRIGW/USERSPACE/LIB/") - set(option_HW_lib "-rdynamic dl") + set(option_HW_lib "-rdynamic dl") + endif (${RF_BOARD} STREQUAL "EXMIMO") +if (${TRANSP_PRO} STREQUAL "ETHERNET") + + include_directories ("${OPENAIR_TARGETS}/ARCH/ETHERNET/USERSPACE/LIB") + set(TRANSPORT_SOURCE ${TRANSPORT_SOURCE} + ${OPENAIR_TARGETS}/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c + ${OPENAIR_TARGETS}/ARCH/ETHERNET/USERSPACE/LIB/eth_udp.c + ${OPENAIR_TARGETS}/ARCH/ETHERNET/USERSPACE/LIB/eth_raw.c + ) + set(option_TP_lib "-rdynamic -ldl") + set(LOWLATENCY True) + +endif (${TRANSP_PRO} STREQUAL "ETHERNET") +########################################################## + include_directories ("${OPENAIR_TARGETS}/ARCH/COMMON") - - + ############################################################## # ???!!! TO BE DOCUMENTED OPTIONS !!!??? ############################################################## @@ -1407,6 +1454,7 @@ add_definitions(-DASN1_MINIMUM_VERSION=924) # lte-softmodem is both eNB and UE implementation ################################################### +set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-rpath -Wl,${OPENAIR_CMAKE}/lte_build_oai/build/") add_executable(lte-softmodem ${rrc_h} ${s1ap_h} @@ -1424,6 +1472,7 @@ add_executable(lte-softmodem ${OPENAIR3_DIR}/NAS/UE/nas_ue_task.c ${GTPU_need_ITTI} ${HW_SOURCE} + ${TRANSPORT_SOURCE} ${RTAI_SOURCE} ${XFORMS_SOURCE} ${XFORMS_SOURCE_SOFTMODEM} @@ -1436,11 +1485,12 @@ target_link_libraries (lte-softmodem target_link_libraries (lte-softmodem ${LIBXML2_LIBRARIES}) -target_link_libraries (lte-softmodem pthread m ${CONFIG_LIBRARIES} rt crypt ${CRYPTO_LIBRARIES} ${OPENSSL_LIBRARIES} ${NETTLE_LIBRARIES} sctp ${option_HW_lib} ${XFORMS_LIBRARIES} ) +target_link_libraries (lte-softmodem pthread m ${CONFIG_LIBRARIES} rt crypt ${CRYPTO_LIBRARIES} ${OPENSSL_LIBRARIES} ${NETTLE_LIBRARIES} sctp ${option_HW_lib} ${option_TP_lib} ${XFORMS_LIBRARIES} ) target_link_libraries (lte-softmodem ${LIBBOOST_LIBRARIES}) # lte-softmodem-nos1 is both eNB and UE implementation ################################################### +set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-rpath -Wl,${OPENAIR_CMAKE}/lte_noS1_build_oai/build/") add_executable(lte-softmodem-nos1 ${rrc_h} ${s1ap_h} @@ -1458,6 +1508,7 @@ add_executable(lte-softmodem-nos1 #${OPENAIR2_DIR}/RRC/NAS/rb_config.c ${OPENAIR1_DIR}/SIMULATION/ETH_TRANSPORT/netlink_init.c ${HW_SOURCE} + ${TRANSPORT_SOURCE} ${RTAI_SOURCE} ${XFORMS_SOURCE} ${XFORMS_SOURCE_SOFTMODEM} @@ -1468,38 +1519,40 @@ target_link_libraries (lte-softmodem-nos1 -Wl,--end-group ) target_link_libraries (lte-softmodem-nos1 ${LIBXML2_LIBRARIES}) -target_link_libraries (lte-softmodem-nos1 pthread m ${CONFIG_LIBRARIES} rt crypt ${CRYPTO_LIBRARIES} ${OPENSSL_LIBRARIES} ${NETTLE_LIBRARIES} ${option_HW_lib} ${XFORMS_LIBRARIES} ) +target_link_libraries (lte-softmodem-nos1 pthread m ${CONFIG_LIBRARIES} rt crypt ${CRYPTO_LIBRARIES} ${OPENSSL_LIBRARIES} ${NETTLE_LIBRARIES} ${option_HW_lib} ${option_TP_lib} ${XFORMS_LIBRARIES} ) target_link_libraries (lte-softmodem-nos1 ${LIBBOOST_LIBRARIES}) # rrh ################################ -set(DRIVER2013) - -#Note: only on RF type is currently supported for RRH +set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-rpath -Wl,${OPENAIR_CMAKE}/rrh_gw/build/") +#Note: only one RF type (USRP) is currently supported for RRH add_executable(rrh_gw ${OPENAIR_TARGETS}/RT/USER/rrh_gw.c ${OPENAIR_TARGETS}/RT/USER/eNB_transport_IQ.c ${OPENAIR_TARGETS}/RT/USER/UE_transport_IQ.c ${OPENAIR_TARGETS}/RT/USER/rt_wrapper.c ${OPENAIR_TARGETS}/ARCH/COMMON/common_lib.c - ${OPENAIR_TARGETS}/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c + ${OPENAIR_TARGETS}/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c + ${OPENAIR_TARGETS}/ARCH/ETHERNET/USERSPACE/LIB/eth_udp.c + ${OPENAIR_TARGETS}/ARCH/ETHERNET/USERSPACE/LIB/eth_raw.c ${HW_SOURCE} + ${TRANSPORT_SOURCE} ) # assert and common_lib.h -target_include_directories(rrh_gw PRIVATE ${OPENAIR_DIR}/common/utils/itti ${OPENAIR_TARGETS}/ARCH/COMMON ${OPENAIR_TARGETS}/ARCH/ETHERNET/USERSPACE/LIB/ ) - +target_include_directories(rrh_gw PRIVATE ${OPENAIR_DIR}/common/utils/itti ${OPENAIR_TARGETS}/ARCH/COMMON ) target_link_libraries(rrh_gw -Wl,--start-group UTIL LFDS -Wl,--end-group ) target_link_libraries (rrh_gw rt pthread m ) -target_link_libraries (rrh_gw ${option_HW_lib} ${LIBBOOST_LIBRARIES} ) +target_link_libraries (rrh_gw ${option_HW_lib} ${option_TP_lib} ${LIBBOOST_LIBRARIES} ) -#Message("-- default_HW_lib=ETHERNET") # only in case of RRH Message("-- option_HW_lib=${option_HW_lib}") Message("-- HW_SOURCE=${HW_SOURCE}") +Message("-- option_TP_lib=${option_TP_lib}") +Message("-- TRANSPORT_SOURCE=${TRANSPORT_SOURCE}") # USIM process ################# @@ -1550,6 +1603,7 @@ add_executable(oaisim ${GTPU_need_ITTI} ${OPENAIR_TARGETS}/COMMON/create_tasks.c ${HW_SOURCE} + ${TRANSPORT_SOURCE} ${XFORMS_SOURCE} ) @@ -1561,7 +1615,7 @@ target_link_libraries (oaisim -Wl,--end-group ) target_link_libraries (oaisim ${LIBXML2_LIBRARIES} ${LAPACK_LIBRARIES}) -target_link_libraries (oaisim pthread m ${CONFIG_LIBRARIES} rt crypt ${CRYPTO_LIBRARIES} ${OPENSSL_LIBRARIES} ${NETTLE_LIBRARIES} sctp ${option_HW_lib} +target_link_libraries (oaisim pthread m ${CONFIG_LIBRARIES} rt crypt ${CRYPTO_LIBRARIES} ${OPENSSL_LIBRARIES} ${NETTLE_LIBRARIES} sctp ${option_HW_lib} ${option_TP_lib} ${ATLAS_LIBRARIES} ${XFORMS_LIBRARIES} ${OPENPGM_LIBRARIES}) #Force link with forms, regardless XFORMS option target_link_libraries (oaisim forms) @@ -1588,6 +1642,7 @@ add_executable(oaisim_nos1 ${OPENAIR2_DIR}/UTIL/OMG/sumo.c ${OPENAIR_TARGETS}/COMMON/create_tasks.c ${HW_SOURCE} + ${TRANSPORT_SOURCE} ${XFORMS_SOURCE} ) target_include_directories(oaisim_nos1 PUBLIC ${OPENAIR_TARGETS}/SIMU/USER) @@ -1597,7 +1652,7 @@ target_link_libraries (oaisim_nos1 -Wl,--end-group ) target_link_libraries (oaisim_nos1 ${LIBXML2_LIBRARIES} ${LAPACK_LIBRARIES}) -target_link_libraries (oaisim_nos1 pthread m ${CONFIG_LIBRARIES} rt crypt ${CRYPTO_LIBRARIES} ${OPENSSL_LIBRARIES} ${NETTLE_LIBRARIES} ${option_HW_lib} +target_link_libraries (oaisim_nos1 pthread m ${CONFIG_LIBRARIES} rt crypt ${CRYPTO_LIBRARIES} ${OPENSSL_LIBRARIES} ${NETTLE_LIBRARIES} ${option_HW_lib} ${option_TP_lib} ${ATLAS_LIBRARIES} ${XFORMS_LIBRARIES} ${OPENPGM_LIBRARIES}) #Force link with forms, regardless XFORMS option target_link_libraries (oaisim_nos1 forms) diff --git a/cmake_targets/build_oai b/cmake_targets/build_oai index af147d682a..6347b97542 100755 --- a/cmake_targets/build_oai +++ b/cmake_targets/build_oai @@ -46,7 +46,8 @@ XFORMS="False" PRINT_STATS="False" VCD_TIMING="False" REL="Rel10" -HW="EXMIMO" +HW="NO_VALUE" +TP="NO_VALUE" NOS1=0 EPC=0 VERBOSE_COMPILE=0 @@ -88,10 +89,13 @@ Options default is Rel10, Rel8 limits the implementation to 3GPP Release 8 version -w | --hardware - EXMIMO (Default), USRP, BLADERF, ETHERNET, None + EXMIMO, USRP, BLADERF Adds this RF board support (in external packages installation and in compilation) +-t | --transport protocol + ETHERNET , None + Adds this trasport protocol support in compilation --oaisim - Makes the oaisim simulator. Hardware will be defaulted to "NONE". + Makes the oaisim simulator. Hardware will be defaulted to "NO_VALUE". --phy_simulators Makes the unitary tests Layer 1 simulators --core_simulators @@ -169,7 +173,7 @@ function main() { shift;; -r | --3gpp-release) REL=$2 - echo_info "setting release to: $REL" + echo_info "Setting release to: $REL" shift 2;; -w | --hardware) HW="$2" #"${i#*=}" @@ -180,7 +184,11 @@ function main() { if [ "$HW" == "BLADERF" ] ; then HW="OAI_BLADERF" fi - echo_info "setting hardware to: $HW" + echo_info "Setting hardware to: $HW" + shift 2;; + -t | --transport_protocol) + TP="$2" #"${i#*=}" + echo_info "Setting transport protocol to: $TP" shift 2;; --oaisim) oaisim=1 @@ -204,7 +212,7 @@ function main() { echo_info "executing test cases only in group: $TEST_CASE_GROUP" shift 2;; -V | --vcd) - echo_info "setting gtk-wave output" + echo_info "Setting gtk-wave output" VCD_TIMING=1 EXE_ARGUMENTS="$EXE_ARGUMENTS -V" shift;; @@ -227,7 +235,7 @@ function main() { shift;; --cflags_processor) CFLAGS_PROCESSOR_USER=$2 - echo_info "setting CPU FLAGS from USER to: $CFLAGS_PROCESSOR_USER" + echo_info "Setting CPU FLAGS from USER to: $CFLAGS_PROCESSOR_USER" shift 2;; -h | --help) print_help @@ -238,6 +246,35 @@ function main() { break;; esac done + + ############################################ + # check validity of HW and TP parameters for RRH and eNB + ############################################# + + if [ "$eNB" = "1" ] ; then + if [ "$HW" = "NO_VALUE" -a "$TP" = "NO_VALUE" ] ; then + echo_fatal "A hardware target or a transport protocol must be defined!!" + fi + if [ "$HW" != "NO_VALUE" -a "$TP" != "NO_VALUE" ] ; then + echo_fatal "Currentlt lte-softmodem can not support simultaniously local and remote RF heads!!" + fi + if [ "$HW" = "NO_VALUE" ] ; then + echo_info "No RF device has been selected: (HW=$HW)" + fi + if [ "$TP" = "NO_VALUE" ] ; then + echo_info "No transport protocol has been selected: (TP=$TP)" + fi + fi + + if [ "$RRH" = "1" ] ; then + if [ "$TP" = "NO_VALUE" ] ; then + echo_fatal "A transport protocol must be defined!!" + fi + if [ "$HW" = "NO_VALUE" ] ; then + echo_info "No RF device has been selected: (HW=$HW)" + fi + fi + ############################################ # setting and printing OAI envs, we should check here @@ -277,7 +314,7 @@ function main() { check_install_usrp_uhd_driver fi if [ "$HW" == "OAI_BLADERF" ] ; then - echo_info "installing packages for BALDERF support" + echo_info "installing packages for BLADERF support" check_install_bladerf_driver fi fi @@ -288,16 +325,18 @@ function main() { fi if [ "$oaisim" = "1" ] ; then - if [ "$HW" != "ETHERNET" ] ; then - HW="NONE" - fi + # if [ "$HW" == "ETHERNET" ] ; then # to ask + # HW="NONE" + #fi + if [ $HW != "EXMIMO" -a $HW != "OAI_USRP" -a $HW != "OAI_BLADERF" ] ; then + HW="NO_VALUE" + fi if [ "$XFORMS" == "True" ] ; then PRINT_STATS="True" fi fi - - echo_info "3. building the compilation directives ..." + echo_info "3. building the compilation directives ..." DIR=$OPENAIR_DIR/cmake_targets if [ "$NOS1" = "1" ] ; then @@ -324,7 +363,9 @@ function main() { echo "set ( RRC_ASN1_VERSION \"${REL}\")" >> $cmake_file echo "set ( ENABLE_VCD_FIFO $VCD_TIMING )" >> $cmake_file echo "set ( RF_BOARD \"${HW}\")" >> $cmake_file - echo "set(PACKAGE_NAME \"${lte_exec}\")" >> $cmake_file + echo "set ( TRANSP_PRO \"${TP}\")" >> $cmake_file + echo "set ( SHRLIBDEV ${SHRLIBDEV})" >> $cmake_file + echo "set(PACKAGE_NAME \"${lte_exec}\")" >> $cmake_file echo 'include(${CMAKE_CURRENT_SOURCE_DIR}/../CMakeLists.txt)' >> $cmake_file cd $DIR/$lte_build_dir/build cmake .. @@ -529,30 +570,86 @@ function main() { fi # RRH compilation - ################## + ##################### if [ "$RRH" = "1" ] ; then - echo_info "Compiling RRH" - if [ $HW == "ETHERNET" ] ; then - echo_info "RF frontend for RRH is not defined. This mode is used for testing (loopback)." - elif [ $HW != "EXMIMO" -a $HW != "OAI_USRP" -a $HW != "OAI_BLADERF" ] ; then - echo_fatal "Hardware not defined ($HW)" - fi - cmake_file=$DIR/rrh_gw/CMakeLists.txt - echo "cmake_minimum_required(VERSION 2.8)" > $cmake_file - echo "set(ENABLE_VCD_FIFO $VCD_TIMING )" >> $cmake_file - echo "set(ENABLE_ITTI False )" >> $cmake_file - echo "set(RF_BOARD \"${HW}\")" >> $cmake_file - echo 'set(PACKAGE_NAME "\"rrh_gw\"")' >> $cmake_file - echo 'include(${CMAKE_CURRENT_SOURCE_DIR}/../CMakeLists.txt)' >> $cmake_file - - [ "$CLEAN" = "1" ] && rm -rf $DIR/rrh_gw/build - mkdir -p $DIR/rrh_gw/build - cd $DIR/rrh_gw/build - cmake .. - compilations \ - rrh_gw rrh_gw \ - rrh_gw $dbin/rrh_gw + rrh_exec=rrh_gw + rrh_build_dir=rrh_gw + + echo_info "Compiling $rrh_exec ..." + + cmake_file=$DIR/$rrh_build_dir/CMakeLists.txt + echo "cmake_minimum_required(VERSION 2.8)" > $cmake_file + echo "set(ENABLE_VCD_FIFO $VCD_TIMING )" >> $cmake_file + echo "set(ENABLE_ITTI False )" >> $cmake_file + echo "set(RF_BOARD \"${HW}\")" >> $cmake_file + echo "set(TRANSP_PRO \"${TP}\")" >> $cmake_file + echo "set(SHRLIBDEV ${SHRLIBDEV})" >> $cmake_file + echo 'set(PACKAGE_NAME "\"rrh_gw\"")' >> $cmake_file + echo 'include(${CMAKE_CURRENT_SOURCE_DIR}/../CMakeLists.txt)' >> $cmake_file + [ "$CLEAN" = "1" ] && rm -rf $DIR/rrh_gw/build + mkdir -p $DIR/$rrh_build_dir/build + cd $DIR/$rrh_build_dir/build + cmake .. + compilations \ + rrh_gw rrh_gw \ + rrh_gw $dbin/rrh_gw fi + + # build RF device and transport protocol libraries + ##################################### + if [ "$eNB" = "1" -o "$RRH" = "1" ] ; then + + if [ "$eNB" = "1" ] ; then + build_dir=$lte_build_dir + else + build_dir=$rrh_build_dir + fi + + # build RF device libraries (currently EXMIMO is not complied with the rest of HW targets) + if [ "$HW" != "NO_VALUE" ] ; then + rm -f liboai_device.so + if [ -d "/usr/include/uhd" ] ; then + compilations \ + $build_dir oai_usrpdevif \ + liboai_usrpdevif.so $dbin/liboai_usrpdevif.so.$REL + fi + if [ -f "/usr/include/libbladeRF.h" ] ; then + compilations \ + $build_dir oai_bladerfdevif \ + liboai_bladerfdevif.so $dbin/liboai_bladerfdevif.so.$REL + fi + + #add exmimo compilation + + + + if [ "$HW" == "EXMIMO" ] ; then + ln -s liboai_exmimodevif.so liboai_device.so + echo_info "liboai_device.so is linked to EXMIMO device library" + elif [ "$HW" == "OAI_USRP" ] ; then + ln -s liboai_usrpdevif.so liboai_device.so + echo_info "liboai_device.so is linked to USRP device library" + elif [ "$HW" == "OAI_BLADERF" ] ; then + ln -s liboai_bladerfdevif.so liboai_device.so + echo_info "liboai_device.so is linked to BLADERF device library" + else + echo_info "liboai_device.so is not linked to any device library" + fi + fi + + # build trasport protocol libraries (currently only ETHERNET is available) + if [ "$TP" != "NO_VALUE" ] ; then + rm -f liboai_transpro.so + compilations \ + $build_dir oai_eth_transpro \ + liboai_eth_transpro.so $dbin/liboai_eth_transpro.so.$REL + if [ "$TP" == "ETHERNET" ] ; then + ln -s liboai_eth_transpro.so liboai_transpro.so + echo_info "liboai_transpro.so is linked with ETHERNET library" + fi + fi +fi + # EPC compilation ################## From d8b69ffb5c537afe63bc06677e47d3cd984e33fc Mon Sep 17 00:00:00 2001 From: "aikaterini.trilyraki" Date: Thu, 19 Nov 2015 17:59:36 +0100 Subject: [PATCH 011/263] update common_lib 1. ethernet is no longer considered a device 2. libraries are loaded dynamically --- .../ARCH/BLADERF/USERSPACE/LIB/bladerf_lib.c | 28 ++- targets/ARCH/COMMON/common_lib.c | 162 +++++++++++++++--- targets/ARCH/COMMON/common_lib.h | 120 ++++++++----- .../ARCH/EXMIMO/USERSPACE/LIB/openair0_lib.c | 4 +- targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp | 38 +++- 5 files changed, 279 insertions(+), 73 deletions(-) diff --git a/targets/ARCH/BLADERF/USERSPACE/LIB/bladerf_lib.c b/targets/ARCH/BLADERF/USERSPACE/LIB/bladerf_lib.c index d515a206ae..c9ca8fedc6 100644 --- a/targets/ARCH/BLADERF/USERSPACE/LIB/bladerf_lib.c +++ b/targets/ARCH/BLADERF/USERSPACE/LIB/bladerf_lib.c @@ -185,7 +185,7 @@ int trx_brf_set_gains(openair0_device* device) { } -int openair0_dev_init_bladerf(openair0_device *device, openair0_config_t *openair0_cfg) { +int device_init(openair0_device *device, openair0_config_t *openair0_cfg, char *cfgfile) { int status; int card=0; @@ -308,6 +308,7 @@ int openair0_dev_init_bladerf(openair0_device *device, openair0_config_t *openai printf("BLADERF: Initializing openair0_device\n"); device->priv = brf; device->Mod_id = num_devices++; + device->type = BLADERF_DEV; device->trx_start_func = trx_brf_start; device->trx_end_func = trx_brf_end; device->trx_read_func = trx_brf_read; @@ -317,6 +318,31 @@ int openair0_dev_init_bladerf(openair0_device *device, openair0_config_t *openai device->trx_stop_func = trx_brf_stop; device->trx_set_freq_func = trx_brf_set_freq; device->trx_set_gains_func = trx_brf_set_gains; + + if(brf->sample_rate==30.72e6) { + openair0_cfg->tx_delay = 8; + openair0_cfg->tx_forward_nsamps = 175; + brf->tx_forward_nsamps = 175; + } + if(brf->sample_rate==15.36e6) { + openair0_cfg->tx_delay = 5; + openair0_cfg->tx_forward_nsamps = 95; + brf->tx_forward_nsamps = 95; + } + if(brf->sample_rate==7.68e6) { + openair0_cfg->tx_delay = 8; + openair0_cfg->tx_forward_nsamps = 0; + brf->tx_forward_nsamps = 0; + } + if(brf->sample_rate==1.92e6) { + openair0_cfg->tx_delay = 8; + openair0_cfg->tx_forward_nsamps = 40; + brf->tx_forward_nsamps = 40; + } + + openair0_cfg->iq_txshift= 0; + openair0_cfg->iq_rxrescale = 15; + memcpy((void*)&device->openair0_cfg,(void*)openair0_cfg,sizeof(openair0_config_t)); return 0; diff --git a/targets/ARCH/COMMON/common_lib.c b/targets/ARCH/COMMON/common_lib.c index 8b91a74b49..8fb07d7eb5 100644 --- a/targets/ARCH/COMMON/common_lib.c +++ b/targets/ARCH/COMMON/common_lib.c @@ -37,28 +37,150 @@ * \warning */ #include +#include +#include +#include +#include + #include "common_lib.h" +/* + FT: The device interface is implemented in a shared library, the softmodem knows which kind + of harware is used by parsing the device name returned when calling the trx_getinfo_func function + provided by this shared library +*/ +int set_device(openair0_device *device) { -int openair0_device_init(openair0_device *device, openair0_config_t *openair0_cfg) { + switch (device->type) { + + case EXMIMO_DEV: + printf("[%s] has loaded EXPRESS MIMO device.\n",((device->host_type == BBU_HOST) ? "BBU": "RRH")); + return 0; + break; + case USRP_DEV: + printf("[%s] has loaded USRP device.\n",((device->host_type == BBU_HOST) ? "BBU": "RRH")); + return 0; + break; + case BLADERF_DEV: + printf("[%s] has loaded BLADERF device.\n",((device->host_type == BBU_HOST) ? "BBU": "RRH")); + return 0; + break; + case NONE_DEV: + printf("[%s] has not loaded a HW device.\n",((device->host_type == BBU_HOST) ? "BBU": "RRH")); + return 0; + break; + default: + printf("[%s] invalid HW device.\n",((device->host_type == BBU_HOST) ? "BBU": "RRH")); + return -1; + break; + } -#ifdef ETHERNET - device->type=ETH_IF; - device->func_type = BBU_FUNC; - openair0_dev_init_eth(device, openair0_cfg); - printf(" openair0_dev_init_eth ...\n"); -#elif EXMIMO - device->type=EXMIMO_IF; - openair0_dev_init_exmimo(device, openair0_cfg); - printf("openair0_dev_init_exmimo...\n"); -#elif OAI_USRP - device->type=USRP_IF; - openair0_dev_init_usrp(device, openair0_cfg); - printf("openair0_dev_init_usrp ...\n"); -#elif OAI_BLADERF - device->type=BLADERF_IF; - openair0_dev_init_bladerf(device, openair0_cfg); - printf(" openair0_dev_init_bladerf ...\n"); -#endif - +} + +int set_transport(openair0_device *device) { + + switch (device->transp_type) { + + case ETHERNET_TP: + printf("[%s] has loaded ETHERNET trasport protocol.\n",((device->host_type == BBU_HOST) ? "BBU": "RRH")); + return 0; + break; + case NONE_TP: + printf("[%s] has not loaded a transport protocol.\n",((device->host_type == BBU_HOST) ? "BBU": "RRH")); + return 0; + break; + default: + printf("[%s] invalid transport protocol.\n",((device->host_type == BBU_HOST) ? "BBU": "RRH")); + return -1; + break; + } + +} + +/* FT: looking for the rh interface library and load it */ +int load_lib(openair0_device *device, openair0_config_t *openair0_cfg, char *cfgfile, uint8_t flag) { + + void *lib_handle; + char *OAI_RF_LIBNAME; + char *OAI_TP_LIBNAME; + oai_device_initfunc_t fp ; + + if (device->host_type==BBU_HOST) { + OAI_RF_LIBNAME= "/home/guepe/openairinterface5g/cmake_targets/lte_noS1_build_oai/build/liboai_device.so"; + OAI_TP_LIBNAME= "/home/guepe/openairinterface5g/cmake_targets/lte_noS1_build_oai/build/liboai_transpro.so"; + } else { + OAI_RF_LIBNAME= "liboai_device.so"; + OAI_TP_LIBNAME= "liboai_transpro.so"; + } + + if (flag == RF_DEVICE) { + lib_handle = dlopen(OAI_RF_LIBNAME, RTLD_LAZY); + if (!lib_handle) { + printf( "Unable to locate %s: HW device set to NONE_DEV.\n", OAI_RF_LIBNAME); + return 0; + } + + fp = dlsym(lib_handle,"device_init"); + + if (fp != NULL ) { + fp(device,openair0_cfg,cfgfile); + } else { + fprintf(stderr, "%s %d:oai device intializing function not found %s\n", __FILE__, __LINE__, dlerror()); + return -1; + } + } else { + lib_handle = dlopen(OAI_TP_LIBNAME, RTLD_LAZY); + if (!lib_handle) { + printf( "Unable to locate %s: transport protocol set to NONE_TP.\n", OAI_TP_LIBNAME); + return 0; + } + + fp = dlsym(lib_handle,"transport_init"); + + if (fp != NULL ) { + fp(device,openair0_cfg,cfgfile); + } else { + fprintf(stderr, "%s %d:oai device intializing function not found %s\n", __FILE__, __LINE__, dlerror()); + return -1; + } + } + + return 0; +} + + + +int openair0_device_load(openair0_device *device, openair0_config_t *openair0_cfg) { + + int rc; + static char *cfgfile; + uint8_t flag=RF_DEVICE; + /* FT: rewritten for shared library, common, radio head interface implementation */ + rc=load_lib(device, openair0_cfg, NULL,flag); + if ( rc >= 0) { + if ( set_device(device) < 0) { + fprintf(stderr, "%s %d:Unsupported radio head\n",__FILE__, __LINE__); + return -1; + } + } + + return 0; +} + +int openair0_transport_load(openair0_device *device, openair0_config_t *openair0_cfg) { + + int rc; + static char *cfgfile; + uint8_t flag=TRANSPORT_PROTOCOL; + + /* FT: rewritten for shared library, common, radio head interface implementation */ + rc=load_lib(device, openair0_cfg, NULL,flag); + if ( rc >= 0) { + if ( set_transport(device) < 0) { + fprintf(stderr, "%s %d:Unsupported radio head\n",__FILE__, __LINE__); + return -1; + } + } + + return 0; } diff --git a/targets/ARCH/COMMON/common_lib.h b/targets/ARCH/COMMON/common_lib.h index 8cc7926d45..0b4825714b 100644 --- a/targets/ARCH/COMMON/common_lib.h +++ b/targets/ARCH/COMMON/common_lib.h @@ -42,6 +42,22 @@ #include #include +/* name of shared library implementing the radio front end */ +#define OAI_RF_LIBNAME "liboai_device.so" +/* name of shared library implementing the transport */ +#define OAI_TP_LIBNAME "liboai_transpro.so" + +/* flags for BBU to determine whether RF front end is local or remote +Note: currently lte-softmodem supports either a local RF device or a remote. */ +#define BBU_LOCAL_RF_ENABLED 1 +#define BBU_REMOTE_RF_ENABLED 2 +#define BBU_LOCAL_REMOTE_RF_ENABLED 3 +/*flags for load_lib() used to specify whether a RF device or a transport protocol library is loaded */ +#define TRANSPORT_PROTOCOL 1 +#define RF_DEVICE 2 + + + typedef int64_t openair0_timestamp; typedef volatile int64_t openair0_vtimestamp; @@ -75,7 +91,7 @@ typedef struct { //! Module ID for this configuration int Mod_id; // device log level - int log_level; + unsigned int log_level; //! number of downlink resource blocks int num_rb_dl; //! number of samples per frame @@ -83,12 +99,15 @@ typedef struct { //! the sample rate for both transmit and receive. double sample_rate; //! number of samples per RX/TX packet (USRP + Ethernet) - int samples_per_packet; + unsigned int samples_per_packet; // delay in sending samples (write) due to hardware access, softmodem processing and fronthaul delay if exist int tx_delay; //! adjust the position of the samples after delay when sending unsigned int tx_forward_nsamps; - //! number of RX channels (=RX antennas) + //! configurable tx thread lauch delay + int txlaunch_wait; /* 1 or 0 */ + int txlaunch_wait_slotcount; + //! number of RX channels (=RX antennas) int rx_num_channels; //! number of TX channels (=TX antennas) int tx_num_channels; @@ -114,14 +133,18 @@ typedef struct { double tx_bw; //! Auto calibration flag int autocal[4]; - //! RRH IP addr for Ethernet interface - char *remote_ip; - //! RRH port number for Ethernet interface - int remote_port; - //! my IP addr for Ethernet interface (eNB/BBU, UE) - char *my_ip; - //! my port number for Ethernet interface (eNB/BBU, UE) - int my_port; + //! rf devices work with x bits iqs when oai have its own iq format + //! the two following parameters are used to convert iqs + int iq_txshift; + int iq_rxrescale; + //! remote IP/MAC addr for Ethernet interface + char *remote_addr; + //! remote port number for Ethernet interface + unsigned int remote_port; + //! local IP/MAC addr for Ethernet interface (eNB/BBU, UE) + char *my_addr; + //! local port number for Ethernet interface (eNB/BBU, UE) + unsigned int my_port; } openair0_config_t; @@ -134,55 +157,63 @@ typedef struct { -/*!\brief interface types that apply to modules (RRH_BBU/RRH_UE) created in RRH (rrh_gw.c) - and are defined with respect to the RF device that is present in RRH - -RRH_BBU modules have two devices, one is by default ETHERNET (will have ETH_IF) and the other one is a - RF device (EXMIMO,USRP,BLADERF) or no device (NONE_IF). - -RRH_UE modules have two devices one is by default ETHERNET (will have ETH_IF) - and the other one by default not present so it will have NONE_IF +/*!\brief RF device types */ typedef enum { - MIN_DEV_TYPE = 0, - /*!\brief device is ETH */ - ETH_IF, + MIN_RF_DEV_TYPE = 0, /*!\brief device is ExpressMIMO */ - EXMIMO_IF, + EXMIMO_DEV, /*!\brief device is USRP*/ - USRP_IF, + USRP_DEV, /*!\brief device is BLADE RF*/ - BLADERF_IF, + BLADERF_DEV, /*!\brief device is NONE*/ - NONE_IF, - MAX_DEV_TYPE + NONE_DEV, + MAX_RF_DEV_TYPE } dev_type_t; +/*!\brief transport protocol types + */ +typedef enum { + MIN_TRANSP_TYPE = 0, + /*!\brief transport protocol ETHERNET */ + ETHERNET_TP, + /*!\brief no transport protocol*/ + NONE_TP, + MAX_TRANSP_TYPE + +} transport_type_t; + /*!\brief openair0 device host type */ typedef enum { - MIN_FUNC_TYPE = 0, + MIN_HOST_TYPE = 0, /*!\brief device functions within a BBU */ - BBU_FUNC, + BBU_HOST, /*!\brief device functions within a RRH */ - RRH_FUNC, - MAX_FUNC_TYPE + RRH_HOST, + MAX_HOST_TYPE -}func_type_t; +}host_type_t; struct openair0_device_t { - /* Module ID of this device */ + /*!brief Module ID of this device */ int Mod_id; - /* Type of this device */ + /*!brief Type of this device */ dev_type_t type; - /* Type of the device's host (BBU/RRH) */ - func_type_t func_type; + /*!brief Transport protocol type that the device suppports (in case I/Q samples need to be transported) */ + transport_type_t transp_type; - /* RF frontend parameters set by application */ + /*!brief Type of the device's host (BBU/RRH) */ + host_type_t host_type; + + /*!brief RF frontend parameters set by application */ openair0_config_t openair0_cfg; - /* Can be used by driver to hold internal structure*/ + /*!brief Can be used by driver to hold internal structure*/ void *priv; /* Functions API, which are called by the application*/ @@ -263,28 +294,25 @@ struct openair0_device_t { }; +/* type of device init function, implemented in shared lib */ +typedef int(*oai_device_initfunc_t)(openair0_device *device, openair0_config_t *openair0_cfg, char *cfgfile); #ifdef __cplusplus extern "C" { #endif -/*! \brief Initialize Openair RF target. It returns 0 if OK */ - int openair0_device_init(openair0_device* device, openair0_config_t *openair0_cfg); + /*! \brief Initialize openair RF target. It returns 0 if OK */ + int openair0_device_load(openair0_device *device, openair0_config_t *openair0_cfg); + /*! \brief Initialize transport protocol . It returns 0 if OK */ + int openair0_transport_load(openair0_device *device, openair0_config_t *openair0_cfg); //USRP /*! \brief Get the current timestamp of USRP */ openair0_timestamp get_usrp_time(openair0_device *device); /*! \brief Set the RX frequency of USRP RF TARGET */ int openair0_set_rx_frequencies(openair0_device* device, openair0_config_t *openair0_cfg); - -//extern -/*! \brief Initialize Openair ETHERNET target. It returns 0 if OK */ - int openair0_dev_init_eth(openair0_device *device, openair0_config_t *openair0_cfg); - int openair0_dev_init_bladerf(openair0_device *device, openair0_config_t *openair0_cfg); - int openair0_dev_init_usrp(openair0_device* device, openair0_config_t *openair0_cfg); - int openair0_dev_init_exmimo(openair0_device *device, openair0_config_t *openair0_cfg); -/*@}*/ + #ifdef __cplusplus } diff --git a/targets/ARCH/EXMIMO/USERSPACE/LIB/openair0_lib.c b/targets/ARCH/EXMIMO/USERSPACE/LIB/openair0_lib.c index df9900d3bc..05105d60df 100644 --- a/targets/ARCH/EXMIMO/USERSPACE/LIB/openair0_lib.c +++ b/targets/ARCH/EXMIMO/USERSPACE/LIB/openair0_lib.c @@ -247,7 +247,7 @@ int openair0_stop_without_reset(int card) #define MY_RF_MODE (RXEN + TXEN + TXLPFNORM + TXLPFEN + TXLPF25 + RXLPFNORM + RXLPFEN + RXLPF25 + LNA1ON +LNAMax + RFBBNORM + DMAMODE_RX + DMAMODE_TX) #define RF_MODE_BASE (LNA1ON + RFBBNORM) -int openair0_dev_init_exmimo(openair0_device *device, openair0_config_t *openair0_cfg) { +int device_init(openair0_device *device, openair0_config_t *openair0_cfg, char *cfgfile) { // Initialize card // exmimo_config_t *p_exmimo_config; @@ -287,6 +287,8 @@ int openair0_dev_init_exmimo(openair0_device *device, openair0_config_t *openair return(-1); } + device->type = EXMIMO_DEV; + return(0); } diff --git a/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp b/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp index e57f55720b..00a0a93116 100644 --- a/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp +++ b/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp @@ -329,8 +329,9 @@ int trx_usrp_reset_stats(openair0_device* device) { } -int openair0_dev_init_usrp(openair0_device* device, openair0_config_t *openair0_cfg) -{ +extern "C" { + int device_init(openair0_device* device, openair0_config_t *openair0_cfg, char *cfgfile) { + uhd::set_thread_priority_safe(1.0); usrp_state_t *s = (usrp_state_t*)malloc(sizeof(usrp_state_t)); memset(s, 0, sizeof(usrp_state_t)); @@ -364,7 +365,7 @@ int openair0_dev_init_usrp(openair0_device* device, openair0_config_t *openair0_ } - printf("Found USRP X300\n"); + printf("Found USRP X300\n"); s->usrp = uhd::usrp::multi_usrp::make(args); // s->usrp->set_rx_subdev_spec(rx_subdev); // s->usrp->set_tx_subdev_spec(tx_subdev); @@ -475,6 +476,7 @@ int openair0_dev_init_usrp(openair0_device* device, openair0_config_t *openair0_ std::cout << boost::format("Device timestamp: %f...") % (s->usrp->get_time_now().get_real_secs()) << std::endl; device->priv = s; + device->type = USRP_DEV; device->trx_start_func = trx_usrp_start; device->trx_write_func = trx_usrp_write; device->trx_read_func = trx_usrp_read; @@ -488,11 +490,37 @@ int openair0_dev_init_usrp(openair0_device* device, openair0_config_t *openair0_ s->sample_rate = openair0_cfg[0].sample_rate; // TODO: // init tx_forward_nsamps based usrp_time_offset ex - if(is_equal(s->sample_rate, (double)30.72e6)) + /*if(is_equal(s->sample_rate, (double)30.72e6)) s->tx_forward_nsamps = 176; if(is_equal(s->sample_rate, (double)15.36e6)) s->tx_forward_nsamps = 90; if(is_equal(s->sample_rate, (double)7.68e6)) - s->tx_forward_nsamps = 50; + s->tx_forward_nsamps = 50;*/ +/* move device specific parameters from lte-softmodem.c here */ + if(is_equal(s->sample_rate, (double)30.72e6)) { + openair0_cfg->tx_delay = 8; + s->tx_forward_nsamps = 175; + openair0_cfg->tx_forward_nsamps = 175; + } + if(is_equal(s->sample_rate, (double)15.36e6)) { + openair0_cfg->tx_delay = 5; + s->tx_forward_nsamps = 95; + openair0_cfg->tx_forward_nsamps = 95; + } + if(is_equal(s->sample_rate, (double)7.68e6)) { + openair0_cfg->tx_delay = 5; + s->tx_forward_nsamps = 70; + openair0_cfg->tx_forward_nsamps = 70; + } + if(is_equal(s->sample_rate, (double)1.92e6)) { + openair0_cfg->tx_delay = 8; + s->tx_forward_nsamps = 40; + openair0_cfg->tx_forward_nsamps = 40; + } + openair0_cfg->iq_txshift= 5; + openair0_cfg->iq_rxrescale = 15; + printf("check params %d:%d",openair0_cfg->tx_forward_nsamps, openair0_cfg->tx_delay); + return 0; } +} \ No newline at end of file From 18e1fdbe5d696e4b5aa2bfba6fd40be6eb0fa07e Mon Sep 17 00:00:00 2001 From: "aikaterini.trilyraki" Date: Thu, 19 Nov 2015 18:05:54 +0100 Subject: [PATCH 012/263] minor update in library name --- targets/ARCH/COMMON/common_lib.c | 12 +- targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp | 134 +++++++++---------- 2 files changed, 65 insertions(+), 81 deletions(-) diff --git a/targets/ARCH/COMMON/common_lib.c b/targets/ARCH/COMMON/common_lib.c index 8fb07d7eb5..a9d6daa954 100644 --- a/targets/ARCH/COMMON/common_lib.c +++ b/targets/ARCH/COMMON/common_lib.c @@ -101,19 +101,9 @@ int set_transport(openair0_device *device) { int load_lib(openair0_device *device, openair0_config_t *openair0_cfg, char *cfgfile, uint8_t flag) { void *lib_handle; - char *OAI_RF_LIBNAME; - char *OAI_TP_LIBNAME; oai_device_initfunc_t fp ; - if (device->host_type==BBU_HOST) { - OAI_RF_LIBNAME= "/home/guepe/openairinterface5g/cmake_targets/lte_noS1_build_oai/build/liboai_device.so"; - OAI_TP_LIBNAME= "/home/guepe/openairinterface5g/cmake_targets/lte_noS1_build_oai/build/liboai_transpro.so"; - } else { - OAI_RF_LIBNAME= "liboai_device.so"; - OAI_TP_LIBNAME= "liboai_transpro.so"; - } - - if (flag == RF_DEVICE) { + if (flag == RF_DEVICE) { lib_handle = dlopen(OAI_RF_LIBNAME, RTLD_LAZY); if (!lib_handle) { printf( "Unable to locate %s: HW device set to NONE_DEV.\n", OAI_RF_LIBNAME); diff --git a/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp b/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp index 00a0a93116..2dea91dc84 100644 --- a/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp +++ b/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp @@ -332,44 +332,44 @@ int trx_usrp_reset_stats(openair0_device* device) { extern "C" { int device_init(openair0_device* device, openair0_config_t *openair0_cfg, char *cfgfile) { - uhd::set_thread_priority_safe(1.0); - usrp_state_t *s = (usrp_state_t*)malloc(sizeof(usrp_state_t)); - memset(s, 0, sizeof(usrp_state_t)); + uhd::set_thread_priority_safe(1.0); + usrp_state_t *s = (usrp_state_t*)malloc(sizeof(usrp_state_t)); + memset(s, 0, sizeof(usrp_state_t)); + + // Initialize USRP device - // Initialize USRP device - - std::string args = "type=b200"; - - - uhd::device_addrs_t device_adds = uhd::device::find(args); - size_t i; + std::string args = "type=b200"; + + uhd::device_addrs_t device_adds = uhd::device::find(args); + size_t i; + printf("Checking for USRPs\n"); if(device_adds.size() == 0) { double usrp_master_clock = 184.32e6; - + std::string args = "type=x300"; // workaround for an api problem, master clock has to be set with the constructor not via set_master_clock_rate args += boost::str(boost::format(",master_clock_rate=%f") % usrp_master_clock); uhd::device_addrs_t device_adds = uhd::device::find(args); - + if(device_adds.size() == 0) - { - std::cerr<<"No USRP Device Found. " << std::endl; - free(s); - return -1; - - } - - printf("Found USRP X300\n"); + { + std::cerr<<"No USRP Device Found. " << std::endl; + free(s); + return -1; + + } + + printf("Found USRP X300\n"); s->usrp = uhd::usrp::multi_usrp::make(args); // s->usrp->set_rx_subdev_spec(rx_subdev); // s->usrp->set_tx_subdev_spec(tx_subdev); - + // lock mboard clocks s->usrp->set_clock_source("internal"); @@ -382,16 +382,15 @@ extern "C" { // s->usrp->set_rx_subdev_spec(rx_subdev); // s->usrp->set_tx_subdev_spec(tx_subdev); - -// do not explicitly set the clock to "internal", because this will disable the gpsdo -// // lock mboard clocks -// s->usrp->set_clock_source("internal"); + + // do not explicitly set the clock to "internal", because this will disable the gpsdo + // // lock mboard clocks + // s->usrp->set_clock_source("internal"); // set master clock rate and sample rate for tx & rx for streaming s->usrp->set_master_clock_rate(30.72e6); } - - + for(i=0;iusrp->get_rx_num_channels();i++) { if (iusrp->set_rx_rate(openair0_cfg[0].sample_rate,i); @@ -399,7 +398,7 @@ extern "C" { printf("Setting rx freq/gain on channel %lu/%lu\n",i,s->usrp->get_rx_num_channels()); s->usrp->set_rx_freq(openair0_cfg[0].rx_freq[i],i); set_rx_gain_offset(&openair0_cfg[0],i); - + ::uhd::gain_range_t gain_range = s->usrp->get_rx_gain_range(i); // limit to maximum gain if (openair0_cfg[0].rx_gain[i]-openair0_cfg[0].rx_gain_offset[i] > gain_range.stop()) { @@ -422,11 +421,11 @@ extern "C" { s->usrp->set_tx_gain(openair0_cfg[0].tx_gain[i],i); } } - - + + // display USRP settings std::cout << boost::format("Actual master clock: %fMHz...") % (s->usrp->get_master_clock_rate()/1e6) << std::endl; - + // create tx & rx streamer uhd::stream_args_t stream_args_rx("sc16", "sc16"); //stream_args_rx.args["spp"] = str(boost::format("%d") % 2048);//(openair0_cfg[0].rx_num_channels*openair0_cfg[0].samples_per_packet)); @@ -435,21 +434,17 @@ extern "C" { s->rx_stream = s->usrp->get_rx_stream(stream_args_rx); std::cout << boost::format("rx_max_num_samps %u") % (s->rx_stream->get_max_num_samps()) << std::endl; //openair0_cfg[0].samples_per_packet = s->rx_stream->get_max_num_samps(); - + uhd::stream_args_t stream_args_tx("sc16", "sc16"); //stream_args_tx.args["spp"] = str(boost::format("%d") % 2048);//(openair0_cfg[0].tx_num_channels*openair0_cfg[0].samples_per_packet)); for (i = 0; itx_stream = s->usrp->get_tx_stream(stream_args_tx); std::cout << boost::format("tx_max_num_samps %u") % (s->tx_stream->get_max_num_samps()) << std::endl; - - - s->usrp->set_time_now(uhd::time_spec_t(0.0)); - - - + s->usrp->set_time_now(uhd::time_spec_t(0.0)); + for (i=0;iusrp->get_rx_antenna(i)) << std::endl; } } - + for (i=0;iusrp->get_tx_rate(i)/1e6) << std::endl; @@ -472,7 +466,7 @@ extern "C" { std::cout << boost::format("Actual TX antenna: %s...") % (s->usrp->get_tx_antenna(i)) << std::endl; } } - + std::cout << boost::format("Device timestamp: %f...") % (s->usrp->get_time_now().get_real_secs()) << std::endl; device->priv = s; @@ -492,35 +486,35 @@ extern "C" { // init tx_forward_nsamps based usrp_time_offset ex /*if(is_equal(s->sample_rate, (double)30.72e6)) s->tx_forward_nsamps = 176; - if(is_equal(s->sample_rate, (double)15.36e6)) + if(is_equal(s->sample_rate, (double)15.36e6)) s->tx_forward_nsamps = 90; if(is_equal(s->sample_rate, (double)7.68e6)) - s->tx_forward_nsamps = 50;*/ -/* move device specific parameters from lte-softmodem.c here */ - if(is_equal(s->sample_rate, (double)30.72e6)) { - openair0_cfg->tx_delay = 8; - s->tx_forward_nsamps = 175; - openair0_cfg->tx_forward_nsamps = 175; - } - if(is_equal(s->sample_rate, (double)15.36e6)) { - openair0_cfg->tx_delay = 5; - s->tx_forward_nsamps = 95; - openair0_cfg->tx_forward_nsamps = 95; - } - if(is_equal(s->sample_rate, (double)7.68e6)) { - openair0_cfg->tx_delay = 5; - s->tx_forward_nsamps = 70; - openair0_cfg->tx_forward_nsamps = 70; - } - if(is_equal(s->sample_rate, (double)1.92e6)) { - openair0_cfg->tx_delay = 8; - s->tx_forward_nsamps = 40; - openair0_cfg->tx_forward_nsamps = 40; - } - openair0_cfg->iq_txshift= 5; - openair0_cfg->iq_rxrescale = 15; - printf("check params %d:%d",openair0_cfg->tx_forward_nsamps, openair0_cfg->tx_delay); - + s->tx_forward_nsamps = 50;*/ + /* move device specific parameters from lte-softmodem.c here */ + if(is_equal(s->sample_rate, (double)30.72e6)) { + openair0_cfg->tx_delay = 8; + s->tx_forward_nsamps = 175; + openair0_cfg->tx_forward_nsamps = 175; + } + if(is_equal(s->sample_rate, (double)15.36e6)) { + openair0_cfg->tx_delay = 5; + s->tx_forward_nsamps = 95; + openair0_cfg->tx_forward_nsamps = 95; + } + if(is_equal(s->sample_rate, (double)7.68e6)) { + openair0_cfg->tx_delay = 5; + s->tx_forward_nsamps = 70; + openair0_cfg->tx_forward_nsamps = 70; + } + if(is_equal(s->sample_rate, (double)1.92e6)) { + openair0_cfg->tx_delay = 8; + s->tx_forward_nsamps = 40; + openair0_cfg->tx_forward_nsamps = 40; + } + openair0_cfg->iq_txshift= 5; + openair0_cfg->iq_rxrescale = 15; + printf("check params %d:%d",openair0_cfg->tx_forward_nsamps, openair0_cfg->tx_delay); + return 0; + } } -} \ No newline at end of file From 3858c92056dd26068f4ac2fda5863703fe4266ac Mon Sep 17 00:00:00 2001 From: "aikaterini.trilyraki" Date: Thu, 19 Nov 2015 20:04:28 +0100 Subject: [PATCH 013/263] minor addition related to shift and rescale --- targets/ARCH/BLADERF/USERSPACE/LIB/bladerf_lib.c | 2 +- targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/targets/ARCH/BLADERF/USERSPACE/LIB/bladerf_lib.c b/targets/ARCH/BLADERF/USERSPACE/LIB/bladerf_lib.c index c9ca8fedc6..d92317f20b 100644 --- a/targets/ARCH/BLADERF/USERSPACE/LIB/bladerf_lib.c +++ b/targets/ARCH/BLADERF/USERSPACE/LIB/bladerf_lib.c @@ -341,7 +341,7 @@ int device_init(openair0_device *device, openair0_config_t *openair0_cfg, char * } openair0_cfg->iq_txshift= 0; - openair0_cfg->iq_rxrescale = 15; + openair0_cfg->iq_rxrescale = 15; /*not sure*/ memcpy((void*)&device->openair0_cfg,(void*)openair0_cfg,sizeof(openair0_config_t)); diff --git a/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c b/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c index 995ced1f0d..6d3bfc8205 100644 --- a/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c +++ b/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c @@ -369,7 +369,8 @@ int transport_init(openair0_device *device, openair0_config_t *openair0_cfg, cha /*hoedcoded!!!!*/ eth->if_name[device->Mod_id] = "eth0"; device->priv = eth; - + openair0_cfg->iq_txshift = 5; + openair0_cfg->iq_rxrescale = 15; memcpy((void*)&device->openair0_cfg,(void*)openair0_cfg,sizeof(openair0_config_t)); /*iqoffset*/ From 9db853f1b1e35784832f58298d39871448ad8a8f Mon Sep 17 00:00:00 2001 From: "aikaterini.trilyraki" Date: Thu, 19 Nov 2015 20:15:40 +0100 Subject: [PATCH 014/263] changes to lte-softmodem proposed by alcatel- minor change to defs.h --- openair1/PHY/defs.h | 7 +++ targets/RT/USER/lte-softmodem.c | 103 ++++++++++++++++++++++++++------ 2 files changed, 92 insertions(+), 18 deletions(-) diff --git a/openair1/PHY/defs.h b/openair1/PHY/defs.h index 398861cabf..2fef7e347d 100755 --- a/openair1/PHY/defs.h +++ b/openair1/PHY/defs.h @@ -76,6 +76,13 @@ #define openair_free(y,x) free((y)) #define PAGE_SIZE 4096 +//#ifdef SHRLIBDEV +//extern int rxrescale; +//#define RX_IQRESCALELEN rxrescale +//#else +//#define RX_IQRESCALELEN 15 +//#endif + //! \brief Allocate \c size bytes of memory on the heap with alignment 16 and zero it afterwards. //! If no more memory is available, this function will terminate the program with an assertion error. static inline void* malloc16_clear( size_t size ) diff --git a/targets/RT/USER/lte-softmodem.c b/targets/RT/USER/lte-softmodem.c index f16f0b9eb8..ebd9e85a32 100644 --- a/targets/RT/USER/lte-softmodem.c +++ b/targets/RT/USER/lte-softmodem.c @@ -329,7 +329,15 @@ time_stats_t softmodem_stats_rx_sf[10]; // total rx time void reset_opp_meas(void); void print_opp_meas(void); int transmission_mode=1; - +/* + FT: not a very clean way of managing the rescale of iqs in rx path, but this is done in + openair1/PHY/MODULATION/ul_7_5_kHz.c which doesn't have access to config parameters + to re-worked later..... + RX_IQRESCALELEN is setup in device libraries for all non expressmimo targets and acessed as an + external variable in ul_7_5_kHz.c. For expressmimo it is a macro (openair1/PHY/defs.h) + Regarding the value of this variable or macro: 18 is for 15 bits iqs, 15 is used for USRP, EXMIMO +*/ +//int rxrescale; int16_t glog_level = LOG_INFO; int16_t glog_verbosity = LOG_MED; @@ -361,8 +369,6 @@ int16_t osa_log_verbosity = LOG_MED; #ifdef ETHERNET -//char rrh_eNB_ip[20] = "127.0.0.1"; -//int rrh_eNB_port = 50000; //char *rrh_UE_ip = "127.0.0.1"; //int rrh_UE_port = 51000; #endif @@ -373,6 +379,47 @@ char uecap_xer[1024],uecap_xer_in=0; extern void *UE_thread(void *arg); extern void init_UE_threads(void); +/*---------------------BMC: timespec helpers -----------------------------*/ + +struct timespec min_diff_time = { .tv_sec = 0, .tv_nsec = 0 }; +struct timespec max_diff_time = { .tv_sec = 0, .tv_nsec = 0 }; + +struct timespec clock_difftime(struct timespec start, struct timespec end) +{ + struct timespec temp; + if ((end.tv_nsec-start.tv_nsec)<0) { + temp.tv_sec = end.tv_sec-start.tv_sec-1; + temp.tv_nsec = 1000000000+end.tv_nsec-start.tv_nsec; + } else { + temp.tv_sec = end.tv_sec-start.tv_sec; + temp.tv_nsec = end.tv_nsec-start.tv_nsec; + } + return temp; +} + +void print_difftimes() +{ +#ifdef DEBUG + printf("difftimes min = %lu ns ; max = %lu ns\n", min_diff_time.tv_nsec, max_diff_time.tv_nsec); +#else + LOG_D(HW,"difftimes min = %lu ns ; max = %lu ns\n", min_diff_time.tv_nsec, max_diff_time.tv_nsec); +#endif +} + +void update_difftimes(struct timespec start, struct timespec end) +{ + struct timespec diff_time = { .tv_sec = 0, .tv_nsec = 0 }; + int changed = 0; + diff_time = clock_difftime(start, end); + if ((min_diff_time.tv_nsec == 0) || (diff_time.tv_nsec < min_diff_time.tv_nsec)) { min_diff_time.tv_nsec = diff_time.tv_nsec; changed = 1; } + if ((max_diff_time.tv_nsec == 0) || (diff_time.tv_nsec > max_diff_time.tv_nsec)) { max_diff_time.tv_nsec = diff_time.tv_nsec; changed = 1; } +#if 1 + if (changed) print_difftimes(); +#endif +} + +/*------------------------------------------------------------------------*/ + unsigned int build_rflocal(int txi, int txq, int rxi, int rxq) { return (txi + (txq<<6) + (rxi<<12) + (rxq<<18)); @@ -949,6 +996,12 @@ void do_OFDM_mod_rt(int subframe,PHY_VARS_eNB *phy_vars_eNB) if (tx_offset>=(LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*phy_vars_eNB->lte_frame_parms.samples_per_tti)) tx_offset -= LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*phy_vars_eNB->lte_frame_parms.samples_per_tti; + ((short*)&phy_vars_eNB->lte_eNB_common_vars.txdata[0][aa][tx_offset])[0] = ((short*)dummy_tx_b)[2*i]<lte_eNB_common_vars.txdata[0][aa][tx_offset])[1] = ((short*)dummy_tx_b)[2*i+1]<lte_eNB_common_vars.txdata[0][aa][tx_offset])[0]= #ifdef EXMIMO ((short*)dummy_tx_b)[2*i]<<4; @@ -965,6 +1018,7 @@ void do_OFDM_mod_rt(int subframe,PHY_VARS_eNB *phy_vars_eNB) #else ((short*)dummy_tx_b)[2*i+1]<<4; #endif +*/ } // if S-subframe switch to RX in second subframe if (subframe_select(&phy_vars_eNB->lte_frame_parms,subframe) == SF_S) { @@ -1782,7 +1836,9 @@ static void* eNB_thread( void* arg ) PHY_vars_eNB_g[0][0]->lte_frame_parms.nb_antennas_rx); stop_meas( &softmodem_stats_hw ); - clock_gettime( CLOCK_MONOTONIC, &trx_time1 ); + if (frame > 50) { + clock_gettime( CLOCK_MONOTONIC, &trx_time1 ); + } if (frame > 20){ if (rxs != spp) @@ -1791,8 +1847,6 @@ static void* eNB_thread( void* arg ) VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ, 0 ); // Transmit TX buffer based on timestamp from RX - - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE, 1 ); // prepare tx buffer pointers @@ -1813,7 +1867,12 @@ static void* eNB_thread( void* arg ) VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TST, (timestamp+(openair0_cfg[card].tx_delay*spp)-openair0_cfg[card].tx_forward_nsamps)&0xffffffff ); stop_meas( &softmodem_stats_mt ); - clock_gettime( CLOCK_MONOTONIC, &trx_time2 ); + if (frame > 50) { + clock_gettime( CLOCK_MONOTONIC, &trx_time2 ); + // BMC: compute time between rx and tx + update_difftimes(trx_time1, trx_time2); + } + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE,0); #else @@ -1985,6 +2044,9 @@ eNB_thread_cleanup: #endif eNB_thread_status = 0; + + print_difftimes(); + return &eNB_thread_status; } @@ -1997,7 +2059,7 @@ static void get_options (int argc, char **argv) // char line[1000]; // int l; int k,i;//,j,k; -#if defined(OAI_USRP) || defined(CPRIGW) +#if defined(OAI_USRP) || defined(CPRIGW) //#ifndef EXMIMO? int clock_src; #endif int CC_id; @@ -2245,7 +2307,7 @@ static void get_options (int argc, char **argv) break; case 's': -#if defined(OAI_USRP) || defined(CPRIGW) +#if defined(OAI_USRP) || defined(CPRIGW) //#ifndef EXMIMO clock_src = atoi(optarg); @@ -2848,6 +2910,11 @@ int main( int argc, char **argv ) for (card=0; cardN_RB_DL == 100) { sample_rate = 30.72e6; bw = 10.0e6; @@ -2932,24 +2999,20 @@ int main( int argc, char **argv ) #ifndef EXMIMO openair0_cfg[card].samples_per_packet = openair0_cfg[0].samples_per_packet; + openair0_cfg[card].num_rb_dl=frame_parms[0]->N_RB_DL; #endif printf("HW: Configuring card %d, nb_antennas_tx/rx %d/%d\n",card, ((UE_flag==0) ? PHY_vars_eNB_g[0][0]->lte_frame_parms.nb_antennas_tx : PHY_vars_UE_g[0][0]->lte_frame_parms.nb_antennas_tx), ((UE_flag==0) ? PHY_vars_eNB_g[0][0]->lte_frame_parms.nb_antennas_rx : PHY_vars_UE_g[0][0]->lte_frame_parms.nb_antennas_rx)); openair0_cfg[card].Mod_id = 0; #ifdef ETHERNET/*do we need to separate ue and enb????*/ - /* + if (UE_flag) { printf("ETHERNET: Configuring UE ETH for %s:%d\n",rrh_UE_ip,rrh_UE_port); openair0_cfg[card].remote_addr = &rrh_UE_ip[0]; openair0_cfg[card].remote_port = rrh_UE_port; - } else { - printf("ETHERNET: Configuring eNB ETH for %s:%d\n",rrh_eNB_ip,rrh_eNB_port); - openair0_cfg[card].remote_addr =&rrh_eNB_ip[0]; - openair0_cfg[card].remote_port =rrh_eNB_port; - } - */ -openair0_cfg[card].num_rb_dl=frame_parms[0]->N_RB_DL; + } + #endif openair0_cfg[card].sample_rate = sample_rate; openair0_cfg[card].tx_bw = bw; @@ -3028,6 +3091,11 @@ openair0_cfg[card].num_rb_dl=frame_parms[0]->N_RB_DL; else if (mode==loop_through_memory) { } } +//for EXMIMO +//openair0_cfg[0].iq_rxrescale=15; /* default value if build with EXMIMO */ +//rxrescale=openair0_cfg[0].iq_rxrescale; /* see comments near RX_IQRESCALELEN definition */ + + printf("Done\n"); @@ -3446,7 +3514,6 @@ openair0_cfg[card].num_rb_dl=frame_parms[0]->N_RB_DL; if (multi_thread>0) { printf("Killing eNB processing threads\n"); kill_eNB_proc(); - } } From 4f14199e645ce71771e8268e9412aec9cc98c4e6 Mon Sep 17 00:00:00 2001 From: "aikaterini.trilyraki" Date: Fri, 20 Nov 2015 16:09:08 +0100 Subject: [PATCH 015/263] minor change to eth_raw.c --- targets/ARCH/ETHERNET/USERSPACE/LIB/eth_raw.c | 4 ++-- targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c | 2 +- targets/RT/USER/lte-softmodem.c | 12 ++++++------ 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_raw.c b/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_raw.c index f8d1a31462..91b2b7f03e 100644 --- a/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_raw.c +++ b/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_raw.c @@ -119,8 +119,8 @@ int eth_socket_init_raw(openair0_device *device) { } /* Construct the Ethernet header */ - ether_aton_r(device->openair0_cfg.my_addr, (struct ether_addr *)(&(eh.ether_shost))); - ether_aton_r(device->openair0_cfg.remote_addr, (struct ether_addr *)(&(eh.ether_dhost))); + ether_aton_r(local_mac, (struct ether_addr *)(&(eh.ether_shost))); + ether_aton_r(remote_mac, (struct ether_addr *)(&(eh.ether_dhost))); eh.ether_type = htons((short)device->openair0_cfg.my_port); printf("[%s] binding mod_%d to hardware address %x:%x:%x:%x:%x:%x\n",((device->host_type == BBU_HOST) ? "BBU": "RRH"),Mod_id,eh.ether_shost[0],eh.ether_shost[1],eh.ether_shost[2],eh.ether_shost[3],eh.ether_shost[4],eh.ether_shost[5]); diff --git a/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c b/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c index 6d3bfc8205..634018f6e1 100644 --- a/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c +++ b/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c @@ -343,7 +343,7 @@ int transport_init(openair0_device *device, openair0_config_t *openair0_cfg, cha int card = 0; /*hoedcoded!!!!*/ - eth->flags = ETH_UDP_MODE; + eth->flags = ETH_RAW_MODE; eth->buffer_size = (unsigned int)openair0_cfg[card].samples_per_packet*sizeof(int32_t); // buffer size = 4096 for sample_len of 1024 printf("[ETHERNET]: Initializing openair0_device for %s ...\n", ((device->host_type == BBU_HOST) ? "BBU": "RRH")); diff --git a/targets/RT/USER/lte-softmodem.c b/targets/RT/USER/lte-softmodem.c index ebd9e85a32..e915925fe8 100644 --- a/targets/RT/USER/lte-softmodem.c +++ b/targets/RT/USER/lte-softmodem.c @@ -369,8 +369,8 @@ int16_t osa_log_verbosity = LOG_MED; #ifdef ETHERNET -//char *rrh_UE_ip = "127.0.0.1"; -//int rrh_UE_port = 51000; +char *rrh_UE_ip = "127.0.0.1"; +int rrh_UE_port = 51000; #endif /* flag given in runtime to specify if the RF head is local or remote*/ uint8_t local_remote_RF; @@ -2977,13 +2977,13 @@ int main( int argc, char **argv ) openair0_cfg[card].remote_addr = "192.168.12.242"; //openair0_cfg[card].remote_addr = "127.0.0.1"; -// openair0_cfg[card].remote_addr = "74:d4:35:cc:88:45"; + openair0_cfg[card].remote_addr = "74:d4:35:cc:88:45"; openair0_cfg[card].remote_port = 50000; openair0_cfg[card].my_addr = "192.168.12.31"; //openair0_cfg[card].my_addr = "127.0.0.1"; - //openair0_cfg[card].my_addr = "d4:be:d9:22:0a:ac"; - openair0_cfg[card].my_port = 50001; - openair0_cfg[card].tx_delay = 5; + openair0_cfg[card].my_addr = "d4:be:d9:22:0a:ac"; + openair0_cfg[card].my_port = 50000; + openair0_cfg[card].tx_delay = 10; openair0_cfg[card].tx_forward_nsamps = 0; openair0_cfg[card].txlaunch_wait = 0; openair0_cfg[card].txlaunch_wait_slotcount = 0; From 8bbff142ab49bddb40f4c414e3d0f52cc482e97b Mon Sep 17 00:00:00 2001 From: "aikaterini.trilyraki" Date: Fri, 20 Nov 2015 17:27:41 +0100 Subject: [PATCH 016/263] initialization for remote/local_mac --- targets/ARCH/ETHERNET/USERSPACE/LIB/eth_raw.c | 8 +- .../ETHERNET/USERSPACE/LIB/ethernet_lib.c | 76 +++++++++---------- 2 files changed, 40 insertions(+), 44 deletions(-) diff --git a/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_raw.c b/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_raw.c index 91b2b7f03e..64085c051b 100644 --- a/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_raw.c +++ b/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_raw.c @@ -70,12 +70,12 @@ int eth_socket_init_raw(openair0_device *device) { int sock_dom=0; int sock_type=0; int sock_proto=0; - - if (device->host_type == RRH_HOST ) { + + if (device->host_type == RRH_HOST ) { /* RRH doesn't know remote MAC(will be retrieved from first packet send from BBU) and remote port(don't care) */ local_mac = device->openair0_cfg.my_addr; local_port = device->openair0_cfg.my_port; - remote_mac = "0:0:0:0:0:0"; - remote_port = device->openair0_cfg.my_port; + remote_mac = malloc(ETH_ALEN); + remote_port = 0; printf("[%s] local MAC addr %s remote MAC addr %s\n","RRH", local_mac,remote_mac); } else { local_mac = device->openair0_cfg.my_addr; diff --git a/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c b/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c index 634018f6e1..9a87858e34 100644 --- a/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c +++ b/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c @@ -174,39 +174,38 @@ int ethernet_tune(openair0_device *device, unsigned int option, int value) { int ret=0; int i=0; - - /***************** get working interface name ***************************/ - /* /\* convert ascii ip address from config file to network binary format *\/ */ - /* inet_aton(device->openair0_cfg.my_addr, &ia); */ - /* /\* look for the interface used, we have its ip address *\/ */ - /* /\* get info on all our network interfaces *\/ */ - /* ids = if_nameindex(); */ - /* /\* loop on these network interfaces *\/ */ - /* for (i=0; ids[i].if_index != 0 ; i++) { */ - /* /\* skip unamed interfaces *\/ */ - /* if (ids[i].if_name == NULL) */ - /* continue; */ - /* /\* get ip address of current network interface *\/ */ - /* strcpy(ifr.ifr_name,ids[i].if_name); */ - /* if (-1 == ioctl(eth->sockfd[Mod_id], SIOCGIFADDR, &ifr)) { */ - /* printf( " Interface %i: %s isn't configured (no ip addr), skipped\n",ids[i].if_index, ifr.ifr_name) ; */ - /* continue; */ - /* } */ - /* /\* test if this is the interface to be used *\/ */ - /* if ( ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr.s_addr != ia.s_addr) */ - /* continue; */ - /* /\* store interface name *\/ */ - /* if_name = ids[i].if_name; */ - /* break; */ - - /* } */ - /* if_freenameindex(ids); */ - /* if( if_name == NULL) { */ - /* printf("Unable to find interface name for %s\n",device->openair0_cfg.my_addr); */ - /* return -1; */ - /* } */ - /* eth->if_name[Mod_id]=if_name; */ - + if (1==0) { + /***************** get working interface name ***************************/ + /* convert ascii ip address from config file to network binary format */ + inet_aton(device->openair0_cfg.my_addr, &ia); */ + /* look for the interface used, we have its ip address get info on all our network interfaces*/ + ids = if_nameindex(); + /* loop on these network interfaces */ + for (i=0; ids[i].if_index != 0 ; i++) { + /* skip unamed interfaces */ + if (ids[i].if_name == NULL) + continue; + /* get ip address of current network interface */ + strcpy(ifr.ifr_name,ids[i].if_name); + if (-1 == ioctl(eth->sockfd[Mod_id], SIOCGIFADDR, &ifr)) { + printf( " Interface %i: %s isn't configured (no ip addr), skipped\n",ids[i].if_index, ifr.ifr_name); + continue; + } + /* test if this is the interface to be used */ + if ( ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr.s_addr != ia.s_addr) + continue; + /* store interface name */ + if_name = ids[i].if_name; + break; + + } + if_freenameindex(ids); + if( if_name == NULL) { + printf("Unable to find interface name for %s\n",device->openair0_cfg.my_addr); + return -1; + } + eth->if_name[Mod_id]=if_name; + } /****************** socket level options ************************/ switch(option) { case SND_BUF_SIZE: /* transmit socket buffer size */ @@ -342,9 +341,9 @@ int transport_init(openair0_device *device, openair0_config_t *openair0_cfg, cha memset(eth, 0, sizeof(eth_state_t)); int card = 0; - /*hoedcoded!!!!*/ + /*hardcoded!!!!*/ eth->flags = ETH_RAW_MODE; - eth->buffer_size = (unsigned int)openair0_cfg[card].samples_per_packet*sizeof(int32_t); // buffer size = 4096 for sample_len of 1024 + eth->buffer_size = (unsigned int)openair0_cfg[card].samples_per_packet*sizeof(int32_t); printf("[ETHERNET]: Initializing openair0_device for %s ...\n", ((device->host_type == BBU_HOST) ? "BBU": "RRH")); device->Mod_id = num_devices_eth++; @@ -366,16 +365,13 @@ int transport_init(openair0_device *device, openair0_config_t *openair0_cfg, cha device->trx_write_func = trx_eth_write_udp; device->trx_read_func = trx_eth_read_udp; } - /*hoedcoded!!!!*/ + /*hardcoded!!!!*/ eth->if_name[device->Mod_id] = "eth0"; device->priv = eth; openair0_cfg->iq_txshift = 5; openair0_cfg->iq_rxrescale = 15; memcpy((void*)&device->openair0_cfg,(void*)openair0_cfg,sizeof(openair0_config_t)); - - /*iqoffset*/ - /*keep conf*/ - /*usrsignal */ + return 0; } From ccef9862fa48555c103309e69093ad1c0c2141e0 Mon Sep 17 00:00:00 2001 From: Raymond Knopp Date: Tue, 24 Nov 2015 14:34:32 -0800 Subject: [PATCH 017/263] nCCE changes prior to rebase --- openair1/PHY/LTE_TRANSPORT/dci_tools.c | 48 +++++++++---------- .../PHY/LTE_TRANSPORT/dlsch_llr_computation.c | 8 ++-- openair1/PHY/TOOLS/lte_dfts.c | 2 +- openair1/PHY/impl_defs_top.h | 3 +- openair1/SCHED/phy_procedures_lte_eNb.c | 30 ++++++------ openair1/SCHED/phy_procedures_lte_ue.c | 29 +++++------ openair2/LAYER2/MAC/eNB_scheduler.c | 2 + openair2/LAYER2/MAC/eNB_scheduler_RA.c | 2 +- .../LAYER2/MAC/eNB_scheduler_primitives.c | 4 +- openair2/LAYER2/MAC/eNB_scheduler_ulsch.c | 31 ++++++------ 10 files changed, 81 insertions(+), 78 deletions(-) diff --git a/openair1/PHY/LTE_TRANSPORT/dci_tools.c b/openair1/PHY/LTE_TRANSPORT/dci_tools.c index a77501e14c..3456c74ee2 100644 --- a/openair1/PHY/LTE_TRANSPORT/dci_tools.c +++ b/openair1/PHY/LTE_TRANSPORT/dci_tools.c @@ -2641,23 +2641,23 @@ int generate_eNB_dlsch_params_from_dci(int frame, dlsch1_harq->subframe = subframe; } -#ifdef DEBUG_DCI + //#ifdef DEBUG_DCI if (dlsch0) { - msg("dlsch0 eNB: dlsch0 %p\n",dlsch0); - msg("dlsch0 eNB: rnti %x\n",dlsch0->rnti); - msg("dlsch0 eNB: NBRB %d\n",dlsch0_harq->nb_rb); - msg("dlsch0 eNB: rballoc %x\n",dlsch0_harq->rb_alloc[0]); - msg("dlsch0 eNB: harq_pid %d\n",harq_pid); - msg("dlsch0 eNB: round %d\n",dlsch0_harq->round); - msg("dlsch0 eNB: rvidx %d\n",dlsch0_harq->rvidx); - msg("dlsch0 eNB: TBS %d (NPRB %d)\n",dlsch0_harq->TBS,NPRB); - msg("dlsch0 eNB: mcs %d\n",dlsch0_harq->mcs); - msg("dlsch0 eNB: tpmi %d\n",tpmi); - msg("dlsch0 eNB: mimo_mode %d\n",dlsch0_harq->mimo_mode); + printf("dlsch0 eNB: dlsch0 %p\n",dlsch0); + printf("dlsch0 eNB: rnti %x\n",dlsch0->rnti); + printf("dlsch0 eNB: NBRB %d\n",dlsch0_harq->nb_rb); + printf("dlsch0 eNB: rballoc %x\n",dlsch0_harq->rb_alloc[0]); + printf("dlsch0 eNB: harq_pid %d\n",harq_pid); + printf("dlsch0 eNB: round %d\n",dlsch0_harq->round); + printf("dlsch0 eNB: rvidx %d\n",dlsch0_harq->rvidx); + printf("dlsch0 eNB: TBS %d (NPRB %d)\n",dlsch0_harq->TBS,NPRB); + printf("dlsch0 eNB: mcs %d\n",dlsch0_harq->mcs); + printf("dlsch0 eNB: tpmi %d\n",tpmi); + printf("dlsch0 eNB: mimo_mode %d\n",dlsch0_harq->mimo_mode); } -#endif + //#endif // compute DL power control parameters computeRhoA_eNB(pdsch_config_dedicated, dlsch[0],dlsch0_harq->dl_power_off); @@ -5508,21 +5508,21 @@ int generate_ue_dlsch_params_from_dci(int frame, } -#ifdef DEBUG_DCI + //#ifdef DEBUG_DCI if (dlsch[0]) { - msg("PDSCH dlsch0 UE: rnti %x\n",dlsch[0]->rnti); - msg("PDSCH dlsch0 UE: NBRB %d\n",dlsch0_harq->nb_rb); - msg("PDSCH dlsch0 UE: rballoc %x\n",dlsch0_harq->rb_alloc[0]); - msg("PDSCH dlsch0 UE: harq_pid %d\n",harq_pid); - msg("PDSCH dlsch0 UE: DCINdi %d\n",dlsch0_harq->DCINdi); - msg("PDSCH dlsch0 UE: rvidx %d\n",dlsch0_harq->rvidx); - msg("PDSCH dlsch0 UE: TBS %d\n",dlsch0_harq->TBS); - msg("PDSCH dlsch0 UE: mcs %d\n",dlsch0_harq->mcs); - msg("PDSCH dlsch0 UE: pwr_off %d\n",dlsch0_harq->dl_power_off); + printf("PDSCH dlsch0 UE: rnti %x\n",dlsch[0]->rnti); + printf("PDSCH dlsch0 UE: NBRB %d\n",dlsch0_harq->nb_rb); + printf("PDSCH dlsch0 UE: rballoc %x\n",dlsch0_harq->rb_alloc_even[0]); + printf("PDSCH dlsch0 UE: harq_pid %d\n",harq_pid); + printf("PDSCH dlsch0 UE: DCINdi %d\n",dlsch0_harq->DCINdi); + printf("PDSCH dlsch0 UE: rvidx %d\n",dlsch0_harq->rvidx); + printf("PDSCH dlsch0 UE: TBS %d\n",dlsch0_harq->TBS); + printf("PDSCH dlsch0 UE: mcs %d\n",dlsch0_harq->mcs); + printf("PDSCH dlsch0 UE: pwr_off %d\n",dlsch0_harq->dl_power_off); } -#endif + //#endif dlsch[0]->active=1; // compute DL power control parameters diff --git a/openair1/PHY/LTE_TRANSPORT/dlsch_llr_computation.c b/openair1/PHY/LTE_TRANSPORT/dlsch_llr_computation.c index 7425a4ed65..89f290e305 100644 --- a/openair1/PHY/LTE_TRANSPORT/dlsch_llr_computation.c +++ b/openair1/PHY/LTE_TRANSPORT/dlsch_llr_computation.c @@ -662,14 +662,14 @@ int dlsch_qpsk_llr(LTE_DL_FRAME_PARMS *frame_parms, if ((symbol_mod==0) || (symbol_mod==(4-frame_parms->Ncp))) { if (frame_parms->mode1_flag==0) - len = (nb_rb*8);// - (2*pbch_pss_sss_adjust/3); + len = (nb_rb*8) - (2*pbch_pss_sss_adjust/3); else - len = (nb_rb*10);// - (5*pbch_pss_sss_adjust/6); + len = (nb_rb*10) - (5*pbch_pss_sss_adjust/6); } else { - len = (nb_rb*12);// - pbch_pss_sss_adjust; + len = (nb_rb*12) - pbch_pss_sss_adjust; } -// printf("dlsch_qpsk_llr: symbol %d,nb_rb %d, len %d,pbch_pss_sss_adjust %d\n",symbol,nb_rb,len,pbch_pss_sss_adjust); + printf("dlsch_qpsk_llr: symbol %d,nb_rb %d, len %d,pbch_pss_sss_adjust %d\n",symbol,nb_rb,len,pbch_pss_sss_adjust); for (i=0; idlsch_eNB[(uint8_t)UE_id][0]->harq_processes[harq_pid]->TBS/8; -#ifdef DEBUG_PHY_PROC + //#ifdef DEBUG_PHY_PROC LOG_D(PHY, "[eNB %"PRIu8"][PDSCH %"PRIx16"/%"PRIu8"] Frame %d, subframe %d: Generating PDSCH/DLSCH with input size = %"PRIu16", G %d, nb_rb %"PRIu16", mcs %"PRIu8", pmi_alloc %"PRIx16", rv %"PRIu8" (round %"PRIu8")\n", phy_vars_eNB->Mod_id, phy_vars_eNB->dlsch_eNB[(uint8_t)UE_id][0]->rnti,harq_pid, @@ -2304,7 +2304,7 @@ void phy_procedures_eNB_TX(unsigned char sched_subframe,PHY_VARS_eNB *phy_vars_e pmi2hex_2Ar1(phy_vars_eNB->dlsch_eNB[(uint8_t)UE_id][0]->harq_processes[harq_pid]->pmi_alloc), phy_vars_eNB->dlsch_eNB[(uint8_t)UE_id][0]->harq_processes[harq_pid]->rvidx, phy_vars_eNB->dlsch_eNB[(uint8_t)UE_id][0]->harq_processes[harq_pid]->round); -#endif + //#endif #if defined(MESSAGE_CHART_GENERATOR_PHY) MSC_LOG_TX_MESSAGE( MSC_PHY_ENB,MSC_PHY_UE, @@ -3324,7 +3324,7 @@ void phy_procedures_eNB_RX(const unsigned char sched_subframe,PHY_VARS_eNB *phy_ } } -#ifdef DEBUG_PHY_PROC + //#ifdef DEBUG_PHY_PROC LOG_D(PHY, "[eNB %d][PUSCH %d] Frame %d Subframe %d Demodulating PUSCH: dci_alloc %d, rar_alloc %d, round %d, first_rb %d, nb_rb %d, mcs %d, TBS %d, rv %d, cyclic_shift %d (n_DMRS2 %d, cyclicShift_common %d, nprs %d), O_ACK %d \n", phy_vars_eNB->Mod_id,harq_pid,frame,subframe, @@ -3341,7 +3341,7 @@ void phy_procedures_eNB_RX(const unsigned char sched_subframe,PHY_VARS_eNB *phy_ phy_vars_eNB->lte_frame_parms.pusch_config_common.ul_ReferenceSignalsPUSCH.cyclicShift, nPRS, phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->O_ACK); -#endif + //#endif start_meas(&phy_vars_eNB->ulsch_demodulation_stats); if (abstraction_flag==0) { @@ -3387,7 +3387,7 @@ void phy_procedures_eNB_RX(const unsigned char sched_subframe,PHY_VARS_eNB *phy_ #endif stop_meas(&phy_vars_eNB->ulsch_decoding_stats); -#ifdef DEBUG_PHY_PROC + //#ifdef DEBUG_PHY_PROC LOG_D(PHY,"[eNB %d][PUSCH %d] frame %d subframe %d RNTI %x RX power (%d,%d) RSSI (%d,%d) N0 (%d,%d) dB ACK (%d,%d), decoding iter %d\n", phy_vars_eNB->Mod_id,harq_pid, frame,subframe, @@ -3401,7 +3401,7 @@ void phy_procedures_eNB_RX(const unsigned char sched_subframe,PHY_VARS_eNB *phy_ phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->o_ACK[0], phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->o_ACK[1], ret); -#endif //DEBUG_PHY_PROC + //#endif //DEBUG_PHY_PROC /* if ((two_ues_connected==1) && (phy_vars_eNB->cooperation_flag==2)) { for (j=0;jlte_frame_parms.nb_antennas_rx;j++) { @@ -3623,11 +3623,11 @@ void phy_procedures_eNB_RX(const unsigned char sched_subframe,PHY_VARS_eNB *phy_ if (phy_vars_eNB->ulsch_eNB[i]->Msg3_flag == 1) { #ifdef OPENAIR2 -#ifdef DEBUG_PHY_PROC + //#ifdef DEBUG_PHY_PROC LOG_I(PHY,"[eNB %d][RAPROC] Frame %d Terminating ra_proc for harq %d, UE %d\n", phy_vars_eNB->Mod_id, frame,harq_pid,i); -#endif + //#endif mac_xface->rx_sdu(phy_vars_eNB->Mod_id, phy_vars_eNB->CC_id, frame,subframe, @@ -3660,9 +3660,9 @@ void phy_procedures_eNB_RX(const unsigned char sched_subframe,PHY_VARS_eNB *phy_ phy_vars_eNB->eNB_UE_stats[i].mode = PUSCH; phy_vars_eNB->ulsch_eNB[i]->Msg3_flag = 0; -#ifdef DEBUG_PHY_PROC - LOG_D(PHY,"[eNB %d][RAPROC] Frame %d : RX Subframe %d Setting UE %d mode to PUSCH\n",phy_vars_eNB->Mod_id,frame,subframe,i); -#endif //DEBUG_PHY_PROC + //#ifdef DEBUG_PHY_PROC + LOG_D(PHY,"[eNB %d][RAPROC] Frame %d : RX Subframe %d Setting UE %d mode to PUSCH\n",phy_vars_eNB->Mod_id,frame,subframe,i); + //#endif //DEBUG_PHY_PROC for (k=0; k<8; k++) { //harq_processes for (j=0; jdlsch_eNB[i][0]->Mdlharq; j++) { @@ -4517,11 +4517,11 @@ void phy_procedures_eNB_lte(unsigned char subframe,PHY_VARS_eNB **phy_vars_eNB,u phy_vars_eNB[CC_id]->proc[subframe].frame_tx++; phy_vars_eNB[CC_id]->proc[subframe].frame_rx++; - if (phy_vars_eNB[CC_id]->proc[subframe].frame_tx==MAX_FRAME_NUMBER) // defined in impl_defs_top.h - phy_vars_eNB[CC_id]->proc[subframe].frame_tx=0; + if (phy_vars_eNB[CC_id]->proc[subframe].frame_tx>=MAX_FRAME_NUMBER) // defined in impl_defs_top.h + phy_vars_eNB[CC_id]->proc[subframe].frame_tx-=MAX_FRAME_NUMBER; - if (phy_vars_eNB[CC_id]->proc[subframe].frame_rx==MAX_FRAME_NUMBER) - phy_vars_eNB[CC_id]->proc[subframe].frame_rx=0; + if (phy_vars_eNB[CC_id]->proc[subframe].frame_rx>=MAX_FRAME_NUMBER) + phy_vars_eNB[CC_id]->proc[subframe].frame_rx-=MAX_FRAME_NUMBER; } VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_LTE,0); diff --git a/openair1/SCHED/phy_procedures_lte_ue.c b/openair1/SCHED/phy_procedures_lte_ue.c index 7dcd71ce47..2abccfd900 100755 --- a/openair1/SCHED/phy_procedures_lte_ue.c +++ b/openair1/SCHED/phy_procedures_lte_ue.c @@ -2061,9 +2061,9 @@ int lte_ue_pdcch_procedures(uint8_t eNB_id,PHY_VARS_UE *phy_vars_ue,uint8_t abst #endif -#ifdef DEBUG_PHY_PROC - LOG_D(PHY,"[UE %d] Frame %d, slot %d, Mode %s: DCI found %i\n",phy_vars_ue->Mod_id,frame_rx,slot_rx,mode_string[phy_vars_ue->UE_mode[eNB_id]],dci_cnt); -#endif + //#ifdef DEBUG_PHY_PROC + LOG_I(PHY,"[UE %d] Frame %d, slot %d, Mode %s: DCI found %i\n",phy_vars_ue->Mod_id,frame_rx,slot_rx,mode_string[phy_vars_ue->UE_mode[eNB_id]],dci_cnt); + //#endif phy_vars_ue->lte_ue_pdcch_vars[eNB_id]->dci_received += dci_cnt; /* @@ -2101,10 +2101,10 @@ int lte_ue_pdcch_procedures(uint8_t eNB_id,PHY_VARS_UE *phy_vars_ue,uint8_t abst #ifdef DEBUG_PHY_PROC - if (subframe_rx == 9) { //( frame_rx % 100 == 0) { - LOG_D(PHY,"frame %d, subframe %d, rnti %x: dci %d/%d\n",frame_rx,subframe_rx,phy_vars_ue->lte_ue_pdcch_vars[eNB_id]->crnti,i,dci_cnt); + // if (subframe_rx == 9) { //( frame_rx % 100 == 0) { + LOG_I(PHY,"frame %d, subframe %d, rnti %x: dci %d/%d\n",frame_rx,subframe_rx,phy_vars_ue->lte_ue_pdcch_vars[eNB_id]->crnti,i,dci_cnt); //dump_dci(&phy_vars_ue->lte_frame_parms, &dci_alloc_rx[i]); - } + // } #endif @@ -2622,13 +2622,13 @@ int phy_procedures_UE_RX(PHY_VARS_UE *phy_vars_ue,uint8_t eNB_id,uint8_t abstrac phy_vars_ue->dlsch_ue[eNB_id][0]->active = 0; -#ifdef DEBUG_PHY_PROC + //#ifdef DEBUG_PHY_PROC LOG_D(PHY,"[UE %d][PDSCH %x/%d] Frame %d subframe %d Scheduling DLSCH decoding\n", phy_vars_ue->Mod_id, phy_vars_ue->dlsch_ue[eNB_id][0]->rnti, harq_pid, (subframe_prev == 9) ? (frame_rx-1) : frame_rx,subframe_prev); -#endif + //#endif if (phy_vars_ue->dlsch_ue[eNB_id][0]) { if (abstraction_flag == 0) { @@ -2674,17 +2674,18 @@ int phy_procedures_UE_RX(PHY_VARS_UE *phy_vars_ue,uint8_t eNB_id,uint8_t abstrac if (ret == (1+phy_vars_ue->dlsch_ue[eNB_id][0]->max_turbo_iterations)) { phy_vars_ue->dlsch_errors[eNB_id]++; -#ifdef DEBUG_PHY_PROC - LOG_D(PHY,"[UE %d][PDSCH %x/%d] Frame %d subframe %d DLSCH in error (rv %d,mcs %d)\n", + //#ifdef DEBUG_PHY_PROC + LOG_D(PHY,"[UE %d][PDSCH %x/%d] Frame %d subframe %d DLSCH in error (rv %d,mcs %d,TBS %d)\n", phy_vars_ue->Mod_id,phy_vars_ue->dlsch_ue[eNB_id][0]->rnti, harq_pid,frame_rx,subframe_prev, phy_vars_ue->dlsch_ue[eNB_id][0]->harq_processes[harq_pid]->rvidx, - phy_vars_ue->dlsch_ue[eNB_id][0]->harq_processes[harq_pid]->mcs); + phy_vars_ue->dlsch_ue[eNB_id][0]->harq_processes[harq_pid]->mcs, + phy_vars_ue->dlsch_ue[eNB_id][0]->harq_processes[harq_pid]->TBS); // if (abstraction_flag ==0 ) - //dump_dlsch(phy_vars_ue,eNB_id,subframe_prev,harq_pid); - //mac_xface->macphy_exit(""); -#endif + dump_dlsch(phy_vars_ue,eNB_id,subframe_prev,harq_pid); + mac_xface->macphy_exit(""); + //#endif } else { LOG_D(PHY,"[UE %d][PDSCH %x/%d] Frame %d subframe %d (slot_rx %d): Received DLSCH (rv %d,mcs %d,TBS %d)\n", phy_vars_ue->Mod_id,phy_vars_ue->dlsch_ue[eNB_id][0]->rnti, diff --git a/openair2/LAYER2/MAC/eNB_scheduler.c b/openair2/LAYER2/MAC/eNB_scheduler.c index 01e32ec307..01593aea2a 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler.c +++ b/openair2/LAYER2/MAC/eNB_scheduler.c @@ -540,6 +540,8 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag, } + LOG_I(MAC,"FrameP %d, subframeP %d : Scheduling CCEs\n",frameP,subframeP); + for (CC_id=0;CC_idRA_alloc_pdu2[0], RA_template->rnti, RA_template->RA_dci_size_bytes2, - 1, + 2, RA_template->RA_dci_size_bits2, RA_template->RA_dci_fmt2, 0); diff --git a/openair2/LAYER2/MAC/eNB_scheduler_primitives.c b/openair2/LAYER2/MAC/eNB_scheduler_primitives.c index da2e5f311e..bbb22f8bde 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_primitives.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_primitives.c @@ -955,7 +955,7 @@ int get_nCCE_offset(int *CCE_table, break; } - // LOG_I(PHY,"rnti %x, Yk = %d, nCCE %d (nCCE/L %d),nb_cand %d\n",rnti,Yk,nCCE,nCCE/L,nb_candidates); + LOG_I(MAC,"rnti %x, Yk = %d, nCCE %d (nCCE/L %d),nb_cand %d\n",rnti,Yk,nCCE,nCCE/L,nb_candidates); for (m = 0 ; m < nb_candidates ; m++) { search_space_free = 1; @@ -994,7 +994,7 @@ int allocate_CCEs(int module_idP, int allocation_is_feasible = 1; DCI_ALLOC_t *dci_alloc; - LOG_I(MAC,"Allocate CCEs subframe %d, test %d\n",subframeP,test_onlyP); + LOG_I(MAC,"Allocate CCEs subframe %d, test %d : (common %d,uspec %d)\n",subframeP,test_onlyP,DCI_pdu->Num_common_dci,DCI_pdu->Num_ue_spec_dci); init_CCE_table(module_idP,CC_idP); DCI_pdu->nCCE=0; diff --git a/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c b/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c index 82aca12b34..30cc27fbfd 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c @@ -223,7 +223,7 @@ void rx_sdu( payload_ptr[0],payload_ptr[1],payload_ptr[2],payload_ptr[3],payload_ptr[4], payload_ptr[5], rntiP); for (ii=0; iicommon_channels[CC_idP].RA_template[ii].rnti, rntiP, eNB->common_channels[CC_idP].RA_template[ii].RA_active); @@ -236,7 +236,7 @@ void rx_sdu( if (UE_id < 0) { memcpy(&eNB->common_channels[CC_idP].RA_template[ii].cont_res_id[0],payload_ptr,6); LOG_I(MAC,"[eNB %d][RAPROC] CC_id %d Frame %d CCCH: Received Msg3: length %d, offset %d\n", - enb_mod_idP,CC_idP,frameP,rx_lengths[ii],payload_ptr-sduP); + enb_mod_idP,CC_idP,frameP,rx_lengths[i],payload_ptr-sduP); if ((UE_id=add_new_ue(enb_mod_idP,CC_idP,eNB->common_channels[CC_idP].RA_template[ii].rnti,harq_pidP)) == -1 ) { mac_xface->macphy_exit("[MAC][eNB] Max user count reached\n"); @@ -246,7 +246,7 @@ void rx_sdu( enb_mod_idP,CC_idP,frameP,eNB->common_channels[CC_idP].RA_template[ii].rnti,UE_id); } else { LOG_I(MAC,"[eNB %d][RAPROC] CC_id %d Frame %d CCCH: Received Msg3 from already registered UE %d: length %d, offset %d\n", - enb_mod_idP,CC_idP,frameP,UE_id,rx_lengths[ii],payload_ptr-sduP); + enb_mod_idP,CC_idP,frameP,UE_id,rx_lengths[i],payload_ptr-sduP); // kill RA procedure } @@ -258,7 +258,7 @@ void rx_sdu( rntiP, CCCH, (uint8_t*)payload_ptr, - rx_lengths[ii], + rx_lengths[i], ENB_FLAG_YES, enb_mod_idP, 0); @@ -297,17 +297,17 @@ void rx_sdu( enb_mod_idP,CC_idP,frameP, rx_lengths[i], UE_id, rx_lcids[i]); mac_rlc_data_ind( - enb_mod_idP, - rntiP, - enb_mod_idP, - frameP, - ENB_FLAG_YES, - MBMS_FLAG_NO, - rx_lcids[i], - (char *)payload_ptr, - rx_lengths[i], - 1, - NULL);//(unsigned int*)crc_status); + enb_mod_idP, + rntiP, + enb_mod_idP, + frameP, + ENB_FLAG_YES, + MBMS_FLAG_NO, + rx_lcids[i], + (char *)payload_ptr, + rx_lengths[i], + 1, + NULL);//(unsigned int*)crc_status); UE_list->eNB_UE_stats[CC_idP][UE_id].num_pdu_rx[rx_lcids[i]]+=1; UE_list->eNB_UE_stats[CC_idP][UE_id].num_bytes_rx[rx_lcids[i]]+=rx_lengths[i]; } @@ -732,6 +732,7 @@ void schedule_ulsch_rnti(module_id_t module_idP, continue; // break; } + printf("UE %d/%x is feasible, mode %s\n",UE_id,rnti,mode_string[eNB_UE_stats->mode]); if (eNB_UE_stats->mode == PUSCH) { // ue has a ulsch channel From 4f35207900c9db12f663848d150f34125835e613 Mon Sep 17 00:00:00 2001 From: ABEILLE Date: Mon, 19 Oct 2015 19:29:04 +0200 Subject: [PATCH 018/263] merged in changes from abeille (modifications on final svn version) --- openair1/PHY/LTE_ESTIMATION/defs.h | 7 +- .../PHY/LTE_ESTIMATION/lte_eNB_measurements.c | 102 +++++--------- openair1/PHY/LTE_TRANSPORT/defs.h | 6 +- openair1/PHY/LTE_TRANSPORT/print_stats.c | 18 +-- openair1/PHY/LTE_TRANSPORT/proto.h | 28 ++-- openair1/PHY/LTE_TRANSPORT/pucch.c | 133 ++++++++++-------- .../PHY/LTE_TRANSPORT/ulsch_demodulation.c | 7 + openair1/PHY/TOOLS/lte_phy_scope.c | 13 +- openair1/PHY/defs.h | 3 + openair1/PHY/impl_defs_top.h | 2 +- openair1/SCHED/phy_procedures_lte_eNb.c | 61 ++++++-- openair1/SIMULATION/LTE_PHY/pucchsim.c | 26 ++-- openair2/LAYER2/MAC/eNB_scheduler_dlsch.c | 11 +- openair2/LAYER2/MAC/eNB_scheduler_ulsch.c | 1 + targets/ARCH/COMMON/common_lib.c | 11 +- .../CONF/enb.band7.tm1.usrpb210.conf | 6 +- targets/RT/USER/lte-softmodem.c | 35 +++-- 17 files changed, 274 insertions(+), 196 deletions(-) diff --git a/openair1/PHY/LTE_ESTIMATION/defs.h b/openair1/PHY/LTE_ESTIMATION/defs.h index 10dc558c9b..903793c2b5 100644 --- a/openair1/PHY/LTE_ESTIMATION/defs.h +++ b/openair1/PHY/LTE_ESTIMATION/defs.h @@ -243,15 +243,16 @@ int lte_est_timing_advance(LTE_DL_FRAME_PARMS *frame_parms, int lte_est_timing_advance_pusch(PHY_VARS_eNB* phy_vars_eNB,module_id_t UE_id,uint8_t subframe); -void lte_eNB_I0_measurements(PHY_VARS_eNB *phy_vars_eNb, +void lte_eNB_I0_measurements(PHY_VARS_eNB *phy_vars_eNB, + int subframe, module_id_t eNB_id, unsigned char clear); -void lte_eNB_I0_measurements_emul(PHY_VARS_eNB *phy_vars_eNb, +void lte_eNB_I0_measurements_emul(PHY_VARS_eNB *phy_vars_eNB, uint8_t sect_id); -void lte_eNB_srs_measurements(PHY_VARS_eNB *phy_vars_eNb, +void lte_eNB_srs_measurements(PHY_VARS_eNB *phy_vars_eNBy, module_id_t eNB_id, module_id_t UE_id, unsigned char init_averaging); diff --git a/openair1/PHY/LTE_ESTIMATION/lte_eNB_measurements.c b/openair1/PHY/LTE_ESTIMATION/lte_eNB_measurements.c index 9564b7842c..7c0c45b05c 100644 --- a/openair1/PHY/LTE_ESTIMATION/lte_eNB_measurements.c +++ b/openair1/PHY/LTE_ESTIMATION/lte_eNB_measurements.c @@ -39,57 +39,36 @@ int32_t rx_power_avg_eNB[3][3]; -void lte_eNB_I0_measurements(PHY_VARS_eNB *phy_vars_eNb, +void lte_eNB_I0_measurements(PHY_VARS_eNB *phy_vars_eNB, + int subframe, unsigned char eNB_id, unsigned char clear) { - LTE_eNB_COMMON *eNB_common_vars = &phy_vars_eNb->lte_eNB_common_vars; - LTE_DL_FRAME_PARMS *frame_parms = &phy_vars_eNb->lte_frame_parms; - PHY_MEASUREMENTS_eNB *phy_measurements = &phy_vars_eNb->PHY_measurements_eNB[eNB_id]; - + LTE_eNB_COMMON *eNB_common_vars = &phy_vars_eNB->lte_eNB_common_vars; + LTE_DL_FRAME_PARMS *frame_parms = &phy_vars_eNB->lte_frame_parms; + PHY_MEASUREMENTS_eNB *phy_measurements = &phy_vars_eNB->PHY_measurements_eNB[eNB_id]; + int32_t *rb_mask = phy_vars_eNB->rb_mask_ul; uint32_t aarx,rx_power_correction; uint32_t rb; int32_t *ul_ch; int32_t n0_power_tot; - + int len; + int offset; + int Nsymb = (frame_parms->Ncp==NORMAL)?14:12; // noise measurements // for the moment we measure the noise on the 7th OFDM symbol (in S subframe) phy_measurements->n0_power_tot = 0; - /* printf("rxdataF0 %p, rxdataF1 %p\n", - (&eNB_common_vars->rxdataF[0][0][(frame_parms->ofdm_symbol_size + frame_parms->first_carrier_offset)<<1 ]), - (&eNB_common_vars->rxdataF[0][1][(frame_parms->ofdm_symbol_size + frame_parms->first_carrier_offset)<<1 ])); - */ - /* - for (i=0;i<512;i++) - printf("sector 0 antenna 0 : %d,%d\n",((short *)&eNB_common_vars->rxdataF[0][0][(19*frame_parms->ofdm_symbol_size)<<1])[i<<1], - ((short *)&eNB_common_vars->rxdataF[0][0][(19*frame_parms->ofdm_symbol_size)<<1])[1+(i<<1)]); - - for (i=0;i<12;i++) - // printf("sector 0 antenna 1 : %d,%d\n",((short *)&eNB_common_vars->rxdataF[0][1][(19*frame_parms->ofdm_symbol_size)<<1])[i<<1], - ((short *)&eNB_common_vars->rxdataF[0][1][(19*frame_parms->ofdm_symbol_size)<<1])[1+(i<<1)]); - */ - - if ( (frame_parms->ofdm_symbol_size == 128) || - (frame_parms->ofdm_symbol_size == 512) ) - rx_power_correction = 2; - else - rx_power_correction = 1; - for (aarx=0; aarxnb_antennas_rx; aarx++) { if (clear == 1) phy_measurements->n0_power[aarx]=0; -#ifdef USER_MODE + phy_measurements->n0_power[aarx] = ((k1*signal_energy(&eNB_common_vars->rxdata[eNB_id][aarx][(frame_parms->samples_per_tti<<1) -frame_parms->ofdm_symbol_size], frame_parms->ofdm_symbol_size)) + k2*phy_measurements->n0_power[aarx])>>10; -#else - phy_measurements->n0_power[aarx] = ((k1*signal_energy(&eNB_common_vars->rxdata[eNB_id][aarx][(frame_parms->samples_per_tti<<1) -frame_parms->ofdm_symbol_size], - frame_parms->ofdm_symbol_size))+k2*phy_measurements->n0_power[aarx])>>10; -#endif phy_measurements->n0_power[aarx] = (phy_measurements->n0_power[aarx] * 12*frame_parms->N_RB_DL)/(frame_parms->ofdm_symbol_size); phy_measurements->n0_power_dB[aarx] = (unsigned short) dB_fixed(phy_measurements->n0_power[aarx]); phy_measurements->n0_power_tot += phy_measurements->n0_power[aarx]; @@ -97,52 +76,49 @@ void lte_eNB_I0_measurements(PHY_VARS_eNB *phy_vars_eNb, phy_measurements->n0_power_tot_dB = (unsigned short) dB_fixed(phy_measurements->n0_power_tot); - phy_measurements->n0_power_tot_dBm = phy_measurements->n0_power_tot_dB - phy_vars_eNb->rx_total_gain_eNB_dB; + phy_measurements->n0_power_tot_dBm = phy_measurements->n0_power_tot_dB - phy_vars_eNB->rx_total_gain_eNB_dB; // printf("n0_power %d\n",phy_measurements->n0_power_tot_dB); for (rb=0; rbN_RB_UL; rb++) { n0_power_tot=0; + if ((rb_mask[rb>>5]&(1<<(rb&31))) == 0) { // check that rb was not used in this subframe + for (aarx=0; aarxnb_antennas_rx; aarx++) { - for (aarx=0; aarxnb_antennas_rx; aarx++) { + // select the 7th symbol in an uplink subframe + offset = (frame_parms->first_carrier_offset + (rb*12))%frame_parms->ofdm_symbol_size; + offset += (7*frame_parms->ofdm_symbol_size);//(((Nsymb*subframe)+7)*frame_parms->ofdm_symbol_size); + ul_ch = &eNB_common_vars->rxdataF[eNB_id][aarx][offset]; + len = 12; + // just do first half of middle PRB for odd number of PRBs + if (((frame_parms->N_RB_UL&1) == 1) && + (rb==(frame_parms->N_RB_UL>>1))) { + len=6; + } + if (clear == 1) + phy_measurements->n0_subband_power[aarx][rb]=0; + + AssertFatal(ul_ch, "RX signal buffer (freq) problem"); - if (rb < 12) - // ul_ch = &eNB_common_vars->rxdataF[eNB_id][aarx][((19*(frame_parms->ofdm_symbol_size)) + frame_parms->first_carrier_offset + (rb*12))<<1]; - ul_ch = &eNB_common_vars->rxdataF[eNB_id][aarx][((7*frame_parms->ofdm_symbol_size) + frame_parms->first_carrier_offset + (rb*12))<<1]; - else if (rb>12) - ul_ch = &eNB_common_vars->rxdataF[eNB_id][aarx][((7*frame_parms->ofdm_symbol_size) + 6 + (rb-13)*12)<<1]; - else { - ul_ch = NULL; - } - - if (clear == 1) - phy_measurements->n0_subband_power[aarx][rb]=0; - - if (ul_ch) { - // for (i=0;i<24;i+=2) - // printf("re %d => %d\n",i/2,ul_ch[i]); - phy_measurements->n0_subband_power[aarx][rb] = ((k1*(signal_energy_nodc(ul_ch, - 24))*rx_power_correction) + (k2*phy_measurements->n0_subband_power[aarx][rb]))>>11; // 11 and 24 to compensate for repeated signal format - - phy_measurements->n0_subband_power_dB[aarx][rb] = dB_fixed(phy_measurements->n0_subband_power[aarx][rb]); - // printf("eNb %d, aarx %d, rb %d : energy %d (%d dB)\n",eNB_id,aarx,rb,signal_energy_nodc(ul_ch,24), phy_measurements->n0_subband_power_dB[aarx][rb]); - n0_power_tot += phy_measurements->n0_subband_power[aarx][rb]; - } else { - phy_measurements->n0_subband_power[aarx][rb] = 1; - phy_measurements->n0_subband_power_dB[aarx][rb] = -99; - n0_power_tot = 1; + phy_measurements->n0_subband_power[aarx][rb] = signal_energy_nodc(ul_ch,len); + //((k1*(signal_energy_nodc(ul_ch,len))) + // + (k2*phy_measurements->n0_subband_power[aarx][rb])); + + phy_measurements->n0_subband_power_dB[aarx][rb] = dB_fixed(phy_measurements->n0_subband_power[aarx][rb]); + // printf("subframe %d (%d): eNb %d, aarx %d, rb %d len %d: energy %d (%d dB)\n",subframe,offset,eNB_id,aarx,rb,len,signal_energy_nodc(ul_ch,len), + // phy_measurements->n0_subband_power_dB[aarx][rb]); + n0_power_tot += phy_measurements->n0_subband_power[aarx][rb]; } + + phy_measurements->n0_subband_power_tot_dB[rb] = dB_fixed(n0_power_tot); + phy_measurements->n0_subband_power_tot_dBm[rb] = phy_measurements->n0_subband_power_tot_dB[rb] - phy_vars_eNB->rx_total_gain_eNB_dB - dB_fixed(frame_parms->N_RB_UL); + } - - phy_measurements->n0_subband_power_tot_dB[rb] = dB_fixed(n0_power_tot); - phy_measurements->n0_subband_power_tot_dBm[rb] = phy_measurements->n0_subband_power_tot_dB[rb] - phy_vars_eNb->rx_total_gain_eNB_dB - 14; - } } - void lte_eNB_srs_measurements(PHY_VARS_eNB *phy_vars_eNb, unsigned char eNB_id, unsigned char UE_id, diff --git a/openair1/PHY/LTE_TRANSPORT/defs.h b/openair1/PHY/LTE_TRANSPORT/defs.h index a21693fea0..8b23c51079 100644 --- a/openair1/PHY/LTE_TRANSPORT/defs.h +++ b/openair1/PHY/LTE_TRANSPORT/defs.h @@ -576,13 +576,13 @@ typedef struct { /// UL RSSI per receive antenna int32_t UL_rssi[NB_ANTENNAS_RX]; /// PUCCH1a/b power (digital linear) - int32_t Po_PUCCH; + uint32_t Po_PUCCH; /// PUCCH1a/b power (dBm) int32_t Po_PUCCH_dBm; /// PUCCH1 power (digital linear), conditioned on below threshold - int32_t Po_PUCCH1_below; + uint32_t Po_PUCCH1_below; /// PUCCH1 power (digital linear), conditioned on above threshold - int32_t Po_PUCCH1_above; + uint32_t Po_PUCCH1_above; /// Indicator that Po_PUCCH has been updated by PHY int32_t Po_PUCCH_update; /// DL Wideband CQI index (2 TBs) diff --git a/openair1/PHY/LTE_TRANSPORT/print_stats.c b/openair1/PHY/LTE_TRANSPORT/print_stats.c index 53ca875953..ab946fc3da 100644 --- a/openair1/PHY/LTE_TRANSPORT/print_stats.c +++ b/openair1/PHY/LTE_TRANSPORT/print_stats.c @@ -573,11 +573,13 @@ int dump_eNB_stats(PHY_VARS_eNB *phy_vars_eNB, char* buffer, int length) phy_vars_eNB->PHY_measurements_eNB[eNB].n0_power_dB[0], phy_vars_eNB->PHY_measurements_eNB[eNB].n0_power_dB[1]); - len += sprintf(&buffer[len],"[eNB PROC] Subband I0: "); + len += sprintf(&buffer[len],"[eNB PROC] PRB I0 (%X.%X.%X.%X): ", + phy_vars_eNB->rb_mask_ul[0], + phy_vars_eNB->rb_mask_ul[1],phy_vars_eNB->rb_mask_ul[2],phy_vars_eNB->rb_mask_ul[3]); - for (i=0; i<25; i++) - len += sprintf(&buffer[len],"%2d ", - phy_vars_eNB->PHY_measurements_eNB[eNB].n0_subband_power_tot_dB[i]); + for (i=0; ilte_frame_parms.N_RB_UL; i++) + len += sprintf(&buffer[len],"%4d ", + phy_vars_eNB->PHY_measurements_eNB[eNB].n0_subband_power_tot_dBm[i]); len += sprintf(&buffer[len],"\n"); len += sprintf(&buffer[len],"\n[eNB PROC] PERFORMANCE PARAMETERS\n"); @@ -634,11 +636,11 @@ int dump_eNB_stats(PHY_VARS_eNB *phy_vars_eNB, char* buffer, int length) dB_fixed(phy_vars_eNB->lte_eNB_pusch_vars[UE_id]->ulsch_power[1]), phy_vars_eNB->eNB_UE_stats[UE_id].UL_rssi[0], phy_vars_eNB->eNB_UE_stats[UE_id].UL_rssi[1], - dB_fixed(phy_vars_eNB->eNB_UE_stats[UE_id].Po_PUCCH)-phy_vars_eNB->rx_total_gain_eNB_dB, + dB_fixed(phy_vars_eNB->eNB_UE_stats[UE_id].Po_PUCCH/phy_vars_eNB->lte_frame_parms.N_RB_UL)-phy_vars_eNB->rx_total_gain_eNB_dB, phy_vars_eNB->lte_frame_parms.ul_power_control_config_common.p0_NominalPUCCH, - dB_fixed(phy_vars_eNB->eNB_UE_stats[UE_id].Po_PUCCH1_below)-phy_vars_eNB->rx_total_gain_eNB_dB, - dB_fixed(phy_vars_eNB->eNB_UE_stats[UE_id].Po_PUCCH1_above)-phy_vars_eNB->rx_total_gain_eNB_dB, - PUCCH1_THRES+phy_vars_eNB->PHY_measurements_eNB[0].n0_power_tot_dBm, //-dB_fixed(phy_vars_eNB->lte_frame_parms.N_RB_UL), + dB_fixed(phy_vars_eNB->eNB_UE_stats[UE_id].Po_PUCCH1_below/phy_vars_eNB->lte_frame_parms.N_RB_UL)-phy_vars_eNB->rx_total_gain_eNB_dB, + dB_fixed(phy_vars_eNB->eNB_UE_stats[UE_id].Po_PUCCH1_above/phy_vars_eNB->lte_frame_parms.N_RB_UL)-phy_vars_eNB->rx_total_gain_eNB_dB, + PUCCH1_THRES+phy_vars_eNB->PHY_measurements_eNB[0].n0_power_tot_dBm-dB_fixed(phy_vars_eNB->lte_frame_parms.N_RB_UL), phy_vars_eNB->eNB_UE_stats[UE_id].sector); for(i=0; i<8; i++) diff --git a/openair1/PHY/LTE_TRANSPORT/proto.h b/openair1/PHY/LTE_TRANSPORT/proto.h index e6aa7ef919..5142f9443a 100644 --- a/openair1/PHY/LTE_TRANSPORT/proto.h +++ b/openair1/PHY/LTE_TRANSPORT/proto.h @@ -1637,22 +1637,22 @@ void generate_pucch_emul(PHY_VARS_UE *phy_vars_ue, uint8_t subframe); -int32_t rx_pucch(PHY_VARS_eNB *phy_vars_eNB, - PUCCH_FMT_t fmt, - uint8_t UE_id, - uint16_t n1_pucch, - uint16_t n2_pucch, - uint8_t shortened_format, - uint8_t *payload, - uint8_t subframe, - uint8_t pucch1_thres); +uint32_t rx_pucch(PHY_VARS_eNB *phy_vars_eNB, + PUCCH_FMT_t fmt, + uint8_t UE_id, + uint16_t n1_pucch, + uint16_t n2_pucch, + uint8_t shortened_format, + uint8_t *payload, + uint8_t subframe, + uint8_t pucch1_thres); int32_t rx_pucch_emul(PHY_VARS_eNB *phy_vars_eNB, - uint8_t UE_index, - PUCCH_FMT_t fmt, - uint8_t n1_pucch_sel, - uint8_t *payload, - uint8_t subframe); + uint8_t UE_index, + PUCCH_FMT_t fmt, + uint8_t n1_pucch_sel, + uint8_t *payload, + uint8_t subframe); /*! diff --git a/openair1/PHY/LTE_TRANSPORT/pucch.c b/openair1/PHY/LTE_TRANSPORT/pucch.c index 2ed5694dd1..58d08ac205 100644 --- a/openair1/PHY/LTE_TRANSPORT/pucch.c +++ b/openair1/PHY/LTE_TRANSPORT/pucch.c @@ -430,15 +430,15 @@ void generate_pucch_emul(PHY_VARS_UE *phy_vars_ue, } -int32_t rx_pucch(PHY_VARS_eNB *phy_vars_eNB, - PUCCH_FMT_t fmt, - uint8_t UE_id, - uint16_t n1_pucch, - uint16_t n2_pucch, - uint8_t shortened_format, - uint8_t *payload, - uint8_t subframe, - uint8_t pucch1_thres) +uint32_t rx_pucch(PHY_VARS_eNB *phy_vars_eNB, + PUCCH_FMT_t fmt, + uint8_t UE_id, + uint16_t n1_pucch, + uint16_t n2_pucch, + uint8_t shortened_format, + uint8_t *payload, + uint8_t subframe, + uint8_t pucch1_thres) { @@ -446,11 +446,11 @@ int32_t rx_pucch(PHY_VARS_eNB *phy_vars_eNB, LTE_eNB_COMMON *eNB_common_vars = &phy_vars_eNB->lte_eNB_common_vars; LTE_DL_FRAME_PARMS *frame_parms = &phy_vars_eNB->lte_frame_parms; // PUCCH_CONFIG_DEDICATED *pucch_config_dedicated = &phy_vars_eNB->pucch_config_dedicated[UE_id]; - int8_t sigma2_dB = phy_vars_eNB->PHY_measurements_eNB[0].n0_power_dB[0]; - int32_t *Po_PUCCH = &(phy_vars_eNB->eNB_UE_stats[UE_id].Po_PUCCH); + int8_t sigma2_dB = phy_vars_eNB->PHY_measurements_eNB[0].n0_subband_power_tot_dB[6]; + uint32_t *Po_PUCCH = &(phy_vars_eNB->eNB_UE_stats[UE_id].Po_PUCCH); int32_t *Po_PUCCH_dBm = &(phy_vars_eNB->eNB_UE_stats[UE_id].Po_PUCCH_dBm); - int32_t *Po_PUCCH1_below = &(phy_vars_eNB->eNB_UE_stats[UE_id].Po_PUCCH1_below); - int32_t *Po_PUCCH1_above = &(phy_vars_eNB->eNB_UE_stats[UE_id].Po_PUCCH1_above); + uint32_t *Po_PUCCH1_below = &(phy_vars_eNB->eNB_UE_stats[UE_id].Po_PUCCH1_below); + uint32_t *Po_PUCCH1_above = &(phy_vars_eNB->eNB_UE_stats[UE_id].Po_PUCCH1_above); int32_t *Po_PUCCH_update = &(phy_vars_eNB->eNB_UE_stats[UE_id].Po_PUCCH_update); uint32_t u,v,n,aa; uint32_t z[12*14]; @@ -468,7 +468,7 @@ int32_t rx_pucch(PHY_VARS_eNB *phy_vars_eNB, uint32_t symbol_offset; int16_t stat_ref_re,stat_ref_im,*cfo,chest_re,chest_im; int32_t stat_re=0,stat_im=0; - int32_t stat,stat_max=0; + uint32_t stat,stat_max=0; uint8_t deltaPUCCH_Shift = frame_parms->pucch_config_common.deltaPUCCH_Shift; uint8_t NRB2 = frame_parms->pucch_config_common.nRB_CQI; @@ -478,6 +478,7 @@ int32_t rx_pucch(PHY_VARS_eNB *phy_vars_eNB, uint32_t u1 = (frame_parms->Nid_cell + frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.grouphop[1+(subframe<<1)]) % 30; uint32_t v0=frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.seqhop[subframe<<1]; uint32_t v1=frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.seqhop[1+(subframe<<1)]; + int chL; if (first_call == 1) { for (i=0;i<10;i++) { @@ -508,6 +509,7 @@ int32_t rx_pucch(PHY_VARS_eNB *phy_vars_eNB, } */ + if ((deltaPUCCH_Shift==0) || (deltaPUCCH_Shift>3)) { LOG_E(PHY,"[eNB] rx_pucch: Illegal deltaPUCCH_shift %d (should be 1,2,3)\n",deltaPUCCH_Shift); return(-1); @@ -737,30 +739,35 @@ int32_t rx_pucch(PHY_VARS_eNB *phy_vars_eNB, cfo = (frame_parms->Ncp==0) ? &cfo_pucch_np[14*phase] : &cfo_pucch_ep[12*phase]; for (l=0; l<(nsymb>>1); l++) { - stat_re += ((rxcomp[aa][off]*(int32_t)cfo[l<<1])>>15) - ((rxcomp[aa][1+off]*(int32_t)cfo[1+(l<<1)])>>15); - stat_im += ((rxcomp[aa][off]*(int32_t)cfo[1+(l<<1)])>>15) + ((rxcomp[aa][1+off]*(int32_t)cfo[(l<<1)])>>15); + stat_re += (((rxcomp[aa][off]*(int32_t)cfo[l<<1])>>15) - ((rxcomp[aa][1+off]*(int32_t)cfo[1+(l<<1)])>>15))/nsymb; + stat_im += (((rxcomp[aa][off]*(int32_t)cfo[1+(l<<1)])>>15) + ((rxcomp[aa][1+off]*(int32_t)cfo[(l<<1)])>>15))/nsymb; off+=2; + + #ifdef DEBUG_PUCCH_RX - LOG_D(PHY,"[eNB] PUCCH subframe %d (%d,%d) => (%d,%d) x (%d,%d) : (%d,%d)\n",subframe,l,re, + LOG_D(PHY,"[eNB] PUCCH subframe %d (%d,%d,%d) => (%d,%d) x (%d,%d) : (%d,%d) , stat %d\n",subframe,phase,l,re, rxcomp[aa][off],rxcomp[aa][1+off], cfo[l<<1],cfo[1+(l<<1)], - stat_re,stat_im); + stat_re,stat_im,stat); #endif } for (l2=0,l=(nsymb>>1); l<(nsymb-1); l++,l2++) { - stat_re += ((rxcomp[aa][off]*(int32_t)cfo[l2<<1])>>15) - ((rxcomp[aa][1+off]*(int32_t)cfo[1+(l2<<1)])>>15); - stat_im += ((rxcomp[aa][off]*(int32_t)cfo[1+(l2<<1)])>>15) + ((rxcomp[aa][1+off]*(int32_t)cfo[(l2<<1)])>>15); + stat_re += (((rxcomp[aa][off]*(int32_t)cfo[l2<<1])>>15) - ((rxcomp[aa][1+off]*(int32_t)cfo[1+(l2<<1)])>>15))/nsymb; + stat_im += (((rxcomp[aa][off]*(int32_t)cfo[1+(l2<<1)])>>15) + ((rxcomp[aa][1+off]*(int32_t)cfo[(l2<<1)])>>15))/nsymb; off+=2; + #ifdef DEBUG_PUCCH_RX - LOG_D(PHY,"[eNB] PUCCH subframe %d (%d,%d) => (%d,%d) x (%d,%d) : (%d,%d)\n",subframe,l2,re, + LOG_D(PHY,"[eNB] PUCCH subframe %d (%d,%d,%d) => (%d,%d) x (%d,%d) : (%d,%d), stat %d\n",subframe,phase,l2,re, rxcomp[aa][off],rxcomp[aa][1+off], cfo[l2<<1],cfo[1+(l2<<1)], - stat_re,stat_im); + stat_re,stat_im,stat); #endif + } - stat += (stat_re*stat_re) + (stat_im*stat_im); + stat += ((stat_re*stat_re) + (stat_im*stat_im)); + } //re } // aa @@ -772,16 +779,18 @@ int32_t rx_pucch(PHY_VARS_eNB *phy_vars_eNB, } //phase - stat_max /= (nsymb*12); // normalize to energy per symbol and RE + stat_max *= nsymb; // normalize to energy per symbol + stat_max /= (frame_parms->N_RB_UL*12); // #ifdef DEBUG_PUCCH_RX LOG_D(PHY,"[eNB] PUCCH: stat %d, stat_max %d, phase_max %d\n", stat,stat_max,phase_max); #endif #ifdef DEBUG_PUCCH_RX - LOG_D(PHY,"[eNB] PUCCH fmt0: stat_max : %d, sigma2_dB %d (%d, %d), phase_max : %d\n",dB_fixed(stat_max),sigma2_dB,phy_vars_eNB->PHY_measurements_eNB[0].n0_power_tot_dBm,pucch1_thres,phase_max); + LOG_D(PHY,"[eNB] PUCCH fmt1: stat_max : %d, sigma2_dB %d (%d, %d), phase_max : %d\n",dB_fixed(stat_max),sigma2_dB,phy_vars_eNB->PHY_measurements_eNB[0].n0_subband_power_tot_dBm[6],pucch1_thres,phase_max); #endif phy_vars_eNB->pucch1_stats[UE_id][(subframe<<10)+phy_vars_eNB->pucch1_stats_cnt[UE_id][subframe]] = stat_max; + phy_vars_eNB->pucch1_stats_thres[UE_id][(subframe<<10)+phy_vars_eNB->pucch1_stats_cnt[UE_id][subframe]] = sigma2_dB+pucch1_thres; phy_vars_eNB->pucch1_stats_cnt[UE_id][subframe] = (phy_vars_eNB->pucch1_stats_cnt[UE_id][subframe]+1)&1023; /* @@ -798,13 +807,13 @@ int32_t rx_pucch(PHY_VARS_eNB *phy_vars_eNB, if (sigma2_dB<(dB_fixed(stat_max)-pucch1_thres)) { *payload = 1; *Po_PUCCH1_above = ((*Po_PUCCH1_above<<9) + (stat_max<<9)+1024)>>10; - + // LOG_I(PHY,"[eNB] PUCCH fmt1: stat_max : %d, sigma2_dB %d (%d, %d), phase_max : %d\n",dB_fixed(stat_max),sigma2_dB,phy_vars_eNB->PHY_measurements_eNB[0].n0_power_tot_dBm,pucch1_thres,phase_max); } else { *payload = 0; *Po_PUCCH1_below = ((*Po_PUCCH1_below<<9) + (stat_max<<9)+1024)>>10; } - LOG_D(PHY,"[eNB] PUCCH fmt0: stat_max : %d, sigma2_dB %d (I0 %d dBm, thres %d), Po_PUCCH1_below/above : %d / %d\n",dB_fixed(stat_max),sigma2_dB,phy_vars_eNB->PHY_measurements_eNB[0].n0_power_tot_dBm,pucch1_thres,dB_fixed(*Po_PUCCH1_below),dB_fixed(*Po_PUCCH1_above)); + LOG_D(PHY,"[eNB] PUCCH fmt1: stat_max : %d, sigma2_dB %d (I0 %d dBm, thres %d), Po_PUCCH1_below/above : %d / %d\n",dB_fixed(stat_max),sigma2_dB,phy_vars_eNB->PHY_measurements_eNB[0].n0_subband_power_tot_dBm[6],pucch1_thres,dB_fixed(*Po_PUCCH1_below),dB_fixed(*Po_PUCCH1_above)); *Po_PUCCH_update = 1; } else if ((fmt == pucch_format1a)||(fmt == pucch_format1b)) { @@ -813,7 +822,7 @@ int32_t rx_pucch(PHY_VARS_eNB *phy_vars_eNB, LOG_I(PHY,"Doing PUCCH detection for format 1a/1b\n"); #endif - for (phase=0; phase<7; phase++) { + for (phase=3;phase<4;phase++){ //phase=0; phase<7; phase++) { stat=0; for (aa=0; aanb_antennas_rx; aa++) { @@ -844,6 +853,9 @@ int32_t rx_pucch(PHY_VARS_eNB *phy_vars_eNB, #endif } + + + for (l2=0,l=(nsymb>>1); l<(nsymb-1); l++,l2++) { if ((l2<2) || ((l2>(nsymb>>1) - 3)) ) { // data symbols stat_re += ((rxcomp[aa][off]*(int32_t)cfo[l2<<1])>>15) - ((rxcomp[aa][1+off]*(int32_t)cfo[1+(l2<<1)])>>15); @@ -863,34 +875,36 @@ int32_t rx_pucch(PHY_VARS_eNB *phy_vars_eNB, } - stat += (((stat_re*stat_re)) + ((stat_im*stat_im)) + - ((stat_ref_re*stat_ref_re)) + ((stat_ref_im*stat_ref_im))); #ifdef DEBUG_PUCCH_RX LOG_D(PHY,"aa%d re %d : phase %d : stat %d\n",aa,re,phase,stat); #endif + + stat += ((((stat_re*stat_re)) + ((stat_im*stat_im)) + + ((stat_ref_re*stat_ref_re)) + ((stat_ref_im*stat_ref_im)))/nsymb); + + } //re } // aa #ifdef DEBUG_PUCCH_RX - LOG_I(PHY,"phase %d : stat %d\n",phase,stat); + LOG_I(PHY,"Format 1A: phase %d : stat %d\n",phase,stat); #endif - if (stat>stat_max) { stat_max = stat; phase_max = phase; } } //phase - stat_max/=(nsymb*12); //normalize to energy per symbol and RE -#ifdef DEBUG_PUCCH_RX - LOG_I(PHY,"[eNB] PUCCH fmt1: stat_max : %d, phase_max : %d\n",stat_max,phase_max); -#endif + stat_max/=(12); //normalize to energy per symbol and RE + //#ifdef DEBUG_PUCCH_RX + LOG_D(PHY,"[eNB] PUCCH fmt1a/b: stat_max : %d, phase_max : %d\n",stat_max,phase_max); + //#endif stat_re=0; stat_im=0; LOG_D(PHY,"PUCCH1A : Po_PUCCH before %d dB (%d)\n",dB_fixed(*Po_PUCCH),*Po_PUCCH); - *Po_PUCCH = ((*Po_PUCCH<<9) + (stat_max<<9)+1024)>>10; - *Po_PUCCH_dBm = dB_fixed(*Po_PUCCH) - phy_vars_eNB->rx_total_gain_eNB_dB; + *Po_PUCCH = ((*Po_PUCCH>>1) + ((stat_max)>>1)); + *Po_PUCCH_dBm = dB_fixed(*Po_PUCCH/frame_parms->N_RB_UL) - phy_vars_eNB->rx_total_gain_eNB_dB; *Po_PUCCH_update = 1; LOG_D(PHY,"PUCCH1A : stat_max %d (%d,%d,%d) => Po_PUCCH %d\n", @@ -906,6 +920,8 @@ int32_t rx_pucch(PHY_VARS_eNB *phy_vars_eNB, *Po_PUCCH = ((*Po_PUCCH*1023) + stat_max)>>10; + chL = (nsymb>>1)-4; + for (aa=0; aanb_antennas_rx; aa++) { for (re=0; re<12; re++) { chest_re=0; @@ -915,8 +931,8 @@ int32_t rx_pucch(PHY_VARS_eNB *phy_vars_eNB, // channel estimate for first slot for (l=2; l<(nsymb>>1)-2; l++) { off=(re<<1) + (24*l); - chest_re += ((rxcomp[aa][off]*(int32_t)cfo[l<<1])>>15) - ((rxcomp[aa][1+off]*(int32_t)cfo[1+(l<<1)])>>15); - chest_im += ((rxcomp[aa][off]*(int32_t)cfo[1+(l<<1)])>>15) + ((rxcomp[aa][1+off]*(int32_t)cfo[(l<<1)])>>15); + chest_re += (((rxcomp[aa][off]*(int32_t)cfo[l<<1])>>15) - ((rxcomp[aa][1+off]*(int32_t)cfo[1+(l<<1)])>>15))/chL; + chest_im += (((rxcomp[aa][off]*(int32_t)cfo[1+(l<<1)])>>15) + ((rxcomp[aa][1+off]*(int32_t)cfo[(l<<1)])>>15))/chL; } #ifdef DEBUG_PUCCH_RX @@ -928,8 +944,8 @@ int32_t rx_pucch(PHY_VARS_eNB *phy_vars_eNB, off=(re<<1) + (24*l); tmp_re = ((rxcomp[aa][off]*(int32_t)cfo[l<<1])>>15) - ((rxcomp[aa][1+off]*(int32_t)cfo[1+(l<<1)])>>15); tmp_im = ((rxcomp[aa][off]*(int32_t)cfo[1+(l<<1)])>>15) + ((rxcomp[aa][1+off]*(int32_t)cfo[(l<<1)])>>15); - stat_re += ((tmp_re*chest_re)>>15) + ((tmp_im*chest_im)>>15); - stat_im += ((tmp_re*chest_im)>>15) - ((tmp_im*chest_re)>>15); + stat_re += (((tmp_re*chest_re)>>15) + ((tmp_im*chest_im)>>15))/4; + stat_im += (((tmp_re*chest_im)>>15) - ((tmp_im*chest_re)>>15))/4; off+=2; #ifdef DEBUG_PUCCH_RX LOG_D(PHY,"[eNB] PUCCH subframe %d (%d,%d) => (%d,%d) x (%d,%d) : (%d,%d)\n",subframe,l,re, @@ -943,8 +959,8 @@ int32_t rx_pucch(PHY_VARS_eNB *phy_vars_eNB, off=(re<<1) + (24*l); tmp_re = ((rxcomp[aa][off]*(int32_t)cfo[l<<1])>>15) - ((rxcomp[aa][1+off]*(int32_t)cfo[1+(l<<1)])>>15); tmp_im = ((rxcomp[aa][off]*(int32_t)cfo[1+(l<<1)])>>15) + ((rxcomp[aa][1+off]*(int32_t)cfo[(l<<1)])>>15); - stat_re += ((tmp_re*chest_re)>>15) + ((tmp_im*chest_im)>>15); - stat_im += ((tmp_re*chest_im)>>15) - ((tmp_im*chest_re)>>15); + stat_re += (((tmp_re*chest_re)>>15) + ((tmp_im*chest_im)>>15)/4); + stat_im += (((tmp_re*chest_im)>>15) - ((tmp_im*chest_re)>>15)/4); off+=2; #ifdef DEBUG_PUCCH_RX LOG_D(PHY,"[eNB] PUCCH subframe %d (%d,%d) => (%d,%d) x (%d,%d) : (%d,%d)\n",subframe,l,re, @@ -960,8 +976,8 @@ int32_t rx_pucch(PHY_VARS_eNB *phy_vars_eNB, // channel estimate for second slot for (l=2; l<(nsymb>>1)-2; l++) { off=(re<<1) + (24*l) + (nsymb>>1)*24; - chest_re += ((rxcomp[aa][off]*(int32_t)cfo[l<<1])>>15) - ((rxcomp[aa][1+off]*(int32_t)cfo[1+(l<<1)])>>15); - chest_im += ((rxcomp[aa][off]*(int32_t)cfo[1+(l<<1)])>>15) + ((rxcomp[aa][1+off]*(int32_t)cfo[(l<<1)])>>15); + chest_re += (((rxcomp[aa][off]*(int32_t)cfo[l<<1])>>15) - ((rxcomp[aa][1+off]*(int32_t)cfo[1+(l<<1)])>>15))/chL; + chest_im += (((rxcomp[aa][off]*(int32_t)cfo[1+(l<<1)])>>15) + ((rxcomp[aa][1+off]*(int32_t)cfo[(l<<1)])>>15))/chL; } #ifdef DEBUG_PUCCH_RX @@ -973,8 +989,8 @@ int32_t rx_pucch(PHY_VARS_eNB *phy_vars_eNB, off=(re<<1) + (24*l) + (nsymb>>1)*24; tmp_re = ((rxcomp[aa][off]*(int32_t)cfo[l<<1])>>15) - ((rxcomp[aa][1+off]*(int32_t)cfo[1+(l<<1)])>>15); tmp_im = ((rxcomp[aa][off]*(int32_t)cfo[1+(l<<1)])>>15) + ((rxcomp[aa][1+off]*(int32_t)cfo[(l<<1)])>>15); - stat_re += ((tmp_re*chest_re)>>15) + ((tmp_im*chest_im)>>15); - stat_im += ((tmp_re*chest_im)>>15) - ((tmp_im*chest_re)>>15); + stat_re += (((tmp_re*chest_re)>>15) + ((tmp_im*chest_im)>>15))/4; + stat_im += (((tmp_re*chest_im)>>15) - ((tmp_im*chest_re)>>15))/4; off+=2; #ifdef DEBUG_PUCCH_RX LOG_D(PHY,"[PHY][eNB] PUCCH subframe %d (%d,%d) => (%d,%d) x (%d,%d) : (%d,%d)\n",subframe,l,re, @@ -988,8 +1004,8 @@ int32_t rx_pucch(PHY_VARS_eNB *phy_vars_eNB, off=(re<<1) + (24*l) + (nsymb>>1)*24; tmp_re = ((rxcomp[aa][off]*(int32_t)cfo[l<<1])>>15) - ((rxcomp[aa][1+off]*(int32_t)cfo[1+(l<<1)])>>15); tmp_im = ((rxcomp[aa][off]*(int32_t)cfo[1+(l<<1)])>>15) + ((rxcomp[aa][1+off]*(int32_t)cfo[(l<<1)])>>15); - stat_re += ((tmp_re*chest_re)>>9) + ((tmp_im*chest_im)>>9); - stat_im += ((tmp_re*chest_im)>>9) - ((tmp_im*chest_re)>>9); + stat_re += (((tmp_re*chest_re)>>15) + ((tmp_im*chest_im)>>15))/4; + stat_im += (((tmp_re*chest_im)>>15) - ((tmp_im*chest_re)>>15))/4; off+=2; #ifdef DEBUG_PUCCH_RX LOG_D(PHY,"[PHY][eNB] PUCCH subframe %d (%d,%d) => (%d,%d) x (%d,%d) : (%d,%d)\n",subframe,l,re, @@ -1007,20 +1023,27 @@ int32_t rx_pucch(PHY_VARS_eNB *phy_vars_eNB, } // aa #ifdef DEBUG_PUCCH_RX - LOG_D(PHY,"PUCCH 1a/b: subframe %d : stat %d,%d (pos %d)\n",subframe,stat_re,stat_im, + LOG_I(PHY,"PUCCH 1a/b: subframe %d : stat %d,%d (pos %d)\n",subframe,stat_re,stat_im, (subframe<<10) + (phy_vars_eNB->pucch1ab_stats_cnt[UE_id][subframe])); #endif - - ((int16_t*)&phy_vars_eNB->pucch1ab_stats[UE_id][(subframe<<10) + (phy_vars_eNB->pucch1_stats_cnt[UE_id][subframe])])[0] = stat_re; - ((int16_t*)&phy_vars_eNB->pucch1ab_stats[UE_id][(subframe<<10) + (phy_vars_eNB->pucch1_stats_cnt[UE_id][subframe])])[1] = stat_im; - phy_vars_eNB->pucch1ab_stats_cnt[UE_id][subframe] = (phy_vars_eNB->pucch1ab_stats_cnt[UE_id][subframe]+1)&1023; + ((int16_t*)&phy_vars_eNB->pucch1ab_stats[UE_id][(subframe<<10) + (phy_vars_eNB->pucch1_stats_cnt[UE_id][subframe])])[0] = (int16_t)(stat_re); + ((int16_t*)&phy_vars_eNB->pucch1ab_stats[UE_id][(subframe<<10) + (phy_vars_eNB->pucch1_stats_cnt[UE_id][subframe])])[1] = (int16_t)(stat_im); + phy_vars_eNB->pucch1ab_stats_cnt[UE_id][subframe] = (phy_vars_eNB->pucch1ab_stats_cnt[UE_id][subframe]+1)&1023; + + + *payload = (stat_re<0) ? 1 : 0; if (fmt==pucch_format1b) *(1+payload) = (stat_im<0) ? 1 : 0; } else { // insufficient energy on PUCCH so NAK *payload = 0; + ((int16_t*)&phy_vars_eNB->pucch1ab_stats[UE_id][(subframe<<10) + (phy_vars_eNB->pucch1_stats_cnt[UE_id][subframe])])[0] = (int16_t)(stat_re); + ((int16_t*)&phy_vars_eNB->pucch1ab_stats[UE_id][(subframe<<10) + (phy_vars_eNB->pucch1_stats_cnt[UE_id][subframe])])[1] = (int16_t)(stat_im); + phy_vars_eNB->pucch1ab_stats_cnt[UE_id][subframe] = (phy_vars_eNB->pucch1ab_stats_cnt[UE_id][subframe]+1)&1023; + + *payload = (stat_re<0) ? 1 : 0; if (fmt==pucch_format1b) *(1+payload) = 0; diff --git a/openair1/PHY/LTE_TRANSPORT/ulsch_demodulation.c b/openair1/PHY/LTE_TRANSPORT/ulsch_demodulation.c index 606b2692d5..f2e4dea58a 100644 --- a/openair1/PHY/LTE_TRANSPORT/ulsch_demodulation.c +++ b/openair1/PHY/LTE_TRANSPORT/ulsch_demodulation.c @@ -1657,8 +1657,15 @@ void rx_ulsch(PHY_VARS_eNB *phy_vars_eNB, } } else { for (i=0; inb_antennas_rx; i++) { + /* eNB_pusch_vars->ulsch_power[i] = signal_energy_nodc(eNB_pusch_vars->drs_ch_estimates[eNB_id][i], ulsch[UE_id]->harq_processes[harq_pid]->nb_rb*12)*rx_power_correction; + + */ + + eNB_pusch_vars->ulsch_power[i] = signal_energy_nodc(eNB_pusch_vars->drs_ch_estimates[eNB_id][i], + ulsch[UE_id]->harq_processes[harq_pid]->nb_rb*12); + #ifdef LOCALIZATION eNB_pusch_vars->subcarrier_power = (int32_t *)malloc(ulsch[UE_id]->harq_processes[harq_pid]->nb_rb*12*sizeof(int32_t)); eNB_pusch_vars->active_subcarrier = subcarrier_energy(eNB_pusch_vars->drs_ch_estimates[eNB_id][i], diff --git a/openair1/PHY/TOOLS/lte_phy_scope.c b/openair1/PHY/TOOLS/lte_phy_scope.c index 49cafa19b5..e9820d0604 100644 --- a/openair1/PHY/TOOLS/lte_phy_scope.c +++ b/openair1/PHY/TOOLS/lte_phy_scope.c @@ -119,7 +119,7 @@ FD_lte_phy_scope_enb *create_lte_phy_scope_enb( void ) fl_set_xyplot_xgrid( fdui->pusch_llr,FL_GRID_MAJOR); // I/Q PUCCH comp (format 1) - fdui->pucch_comp1 = fl_add_xyplot( FL_POINTS_XYPLOT, 540, 480, 240, 100, "PUCCH I/Q of MF Output" ); + fdui->pucch_comp1 = fl_add_xyplot( FL_POINTS_XYPLOT, 540, 480, 240, 100, "PUCCH1 Energy (SR)" ); fl_set_object_boxtype( fdui->pucch_comp1, FL_EMBOSSED_BOX ); fl_set_object_color( fdui->pucch_comp1, FL_BLACK, FL_YELLOW ); fl_set_object_lcolor( fdui->pucch_comp1, FL_WHITE ); // Label color @@ -171,11 +171,12 @@ void phy_scope_eNB(FD_lte_phy_scope_enb *form, int16_t *pusch_llr; int16_t *pusch_comp; int32_t *pucch1_comp; + int32_t *pucch1_thres; int16_t *pucch1ab_comp; float Re,Im,ymax; float *llr, *bit; float I[nsymb_ce*2], Q[nsymb_ce*2]; - float I_pucch[10240],Q_pucch[10240],A_pucch[10240],B_pucch[10240]; + float I_pucch[10240],Q_pucch[10240],A_pucch[10240],B_pucch[10240],C_pucch[10240]; float rxsig_t_dB[nb_antennas_rx][FRAME_LENGTH_COMPLEX_SAMPLES]; float chest_t_abs[nb_antennas_rx][frame_parms->ofdm_symbol_size]; float *chest_f_abs; @@ -206,6 +207,7 @@ void phy_scope_eNB(FD_lte_phy_scope_enb *form, pusch_llr = (int16_t*) phy_vars_enb->lte_eNB_pusch_vars[UE_id]->llr; pusch_comp = (int16_t*) phy_vars_enb->lte_eNB_pusch_vars[UE_id]->rxdataF_comp[eNB_id][0]; pucch1_comp = (int32_t*) phy_vars_enb->pucch1_stats[UE_id]; + pucch1_thres = (int32_t*) phy_vars_enb->pucch1_stats_thres[UE_id]; pucch1ab_comp = (int16_t*) phy_vars_enb->pucch1ab_stats[UE_id]; // Received signal in time domain of receive antenna 0 @@ -341,12 +343,13 @@ void phy_scope_eNB(FD_lte_phy_scope_enb *form, Q_pucch[ind] = pucch1ab_comp[2*ind+1]; A_pucch[ind] = 10*log10(pucch1_comp[ind]); B_pucch[ind] = ind; + C_pucch[ind] = (float)pucch1_thres[ind]; } fl_set_xyplot_data(form->pucch_comp,I_pucch,Q_pucch,10240,"","",""); fl_set_xyplot_data(form->pucch_comp1,B_pucch,A_pucch,1024,"","",""); - fl_set_xyplot_xbounds(form->pucch_comp,-200,200); - fl_set_xyplot_ybounds(form->pucch_comp,-100,100); - fl_set_xyplot_ybounds(form->pucch_comp1,10,40); + fl_add_xyplot_overlay(form->pucch_comp1,1,B_pucch,C_pucch,1024,FL_RED); + // fl_set_xyplot_ybounds(form->pucch_comp,-100,100); + fl_set_xyplot_ybounds(form->pucch_comp1,20,80); } diff --git a/openair1/PHY/defs.h b/openair1/PHY/defs.h index 398861cabf..c0b61806a6 100755 --- a/openair1/PHY/defs.h +++ b/openair1/PHY/defs.h @@ -313,6 +313,8 @@ typedef struct PHY_VARS_eNB_s { struct PhysicalConfigDedicated *physicalConfigDedicated[NUMBER_OF_UE_MAX]; + uint32_t rb_mask_ul[4]; + /// Information regarding TM5 MU_MIMO_mode mu_mimo_mode[NUMBER_OF_UE_MAX]; @@ -378,6 +380,7 @@ typedef struct PHY_VARS_eNB_s { int32_t pucch1_stats_cnt[NUMBER_OF_UE_MAX][10]; int32_t pucch1_stats[NUMBER_OF_UE_MAX][10*1024]; + int32_t pucch1_stats_thres[NUMBER_OF_UE_MAX][10*1024]; int32_t pucch1ab_stats_cnt[NUMBER_OF_UE_MAX][10]; int32_t pucch1ab_stats[NUMBER_OF_UE_MAX][10*1024]; diff --git a/openair1/PHY/impl_defs_top.h b/openair1/PHY/impl_defs_top.h index c84b7d3ece..80530c932f 100755 --- a/openair1/PHY/impl_defs_top.h +++ b/openair1/PHY/impl_defs_top.h @@ -257,7 +257,7 @@ #define AMP_OVER_2 (AMP>>1) /// Threshold for PUCCH Format 1 detection -#define PUCCH1_THRES 10 +#define PUCCH1_THRES 4 /// Threshold for PUCCH Format 1a/1b detection #define PUCCH1a_THRES 4 diff --git a/openair1/SCHED/phy_procedures_lte_eNb.c b/openair1/SCHED/phy_procedures_lte_eNb.c index 165f2fbac6..b9cb618ea0 100755 --- a/openair1/SCHED/phy_procedures_lte_eNb.c +++ b/openair1/SCHED/phy_procedures_lte_eNb.c @@ -104,7 +104,6 @@ extern uint8_t smbv_frame_cnt; #ifdef DIAG_PHY extern int rx_sig_fifo; #endif -static unsigned char I0_clear = 1; uint8_t is_SR_subframe(PHY_VARS_eNB *phy_vars_eNB,uint8_t UE_id,uint8_t sched_subframe) { @@ -476,6 +475,7 @@ void phy_procedures_eNB_S_RX(unsigned char sched_subframe,PHY_VARS_eNB *phy_vars if (abstraction_flag == 0) { lte_eNB_I0_measurements(phy_vars_eNB, + subframe, 0, phy_vars_eNB->first_run_I0_measurements); } @@ -489,8 +489,6 @@ void phy_procedures_eNB_S_RX(unsigned char sched_subframe,PHY_VARS_eNB *phy_vars #endif - if (I0_clear == 1) - I0_clear = 0; } @@ -3247,6 +3245,11 @@ void phy_procedures_eNB_RX(const unsigned char sched_subframe,PHY_VARS_eNB *phy_ phy_vars_eNB->lte_frame_parms.samples_per_tti); #endif */ + phy_vars_eNB->rb_mask_ul[0]=0; + phy_vars_eNB->rb_mask_ul[1]=0; + phy_vars_eNB->rb_mask_ul[2]=0; + phy_vars_eNB->rb_mask_ul[3]=0; + if (abstraction_flag == 0) { remove_7_5_kHz(phy_vars_eNB,subframe<<1); remove_7_5_kHz(phy_vars_eNB,(subframe<<1)+1); @@ -3395,6 +3398,12 @@ void phy_procedures_eNB_RX(const unsigned char sched_subframe,PHY_VARS_eNB *phy_ pusch_active = 1; round = phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->round; + for (int rb=0; + rb<=phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->nb_rb; + rb++) { + int rb2 = rb+phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->first_rb; + phy_vars_eNB->rb_mask_ul[rb2>>5] |= (1<<(rb2&31)); + } #ifdef DEBUG_PHY_PROC LOG_D(PHY,"[eNB %d][PUSCH %d] frame %d subframe %d Scheduling PUSCH/ULSCH Reception for rnti %x (UE_id %d)\n", phy_vars_eNB->Mod_id,harq_pid, @@ -3715,13 +3724,19 @@ void phy_procedures_eNB_RX(const unsigned char sched_subframe,PHY_VARS_eNB *phy_ for (j=0; jlte_frame_parms.nb_antennas_rx; j++) //this is the RSSI per RB phy_vars_eNB->eNB_UE_stats[i].UL_rssi[j] = + dB_fixed(phy_vars_eNB->lte_eNB_pusch_vars[i]->ulsch_power[j]* (phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->nb_rb*12)/ phy_vars_eNB->lte_frame_parms.ofdm_symbol_size) - phy_vars_eNB->rx_total_gain_eNB_dB - hundred_times_log10_NPRB[phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->nb_rb-1]/100 - get_hundred_times_delta_IF_eNB(phy_vars_eNB,i,harq_pid, 0)/100; - + + /* + dB_fixed(phy_vars_eNB->lte_eNB_pusch_vars[i]->ulsch_power[j]*phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->nb_rb) - + phy_vars_eNB->rx_total_gain_eNB_dB - + hundred_times_log10_NPRB[phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->nb_rb-1]/100 - + get_hundred_times_delta_IF_eNB(phy_vars_eNB,i,harq_pid, 0)/100;*/ phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->phich_active = 1; phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->phich_ACK = 1; phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->round = 0; @@ -3915,6 +3930,34 @@ void phy_procedures_eNB_RX(const unsigned char sched_subframe,PHY_VARS_eNB *phy_ } else { // otherwise we have some PUCCH detection to do + // Null out PUCCH PRBs for noise measurement + switch(phy_vars_eNB->lte_frame_parms.N_RB_UL) { + case 6: + phy_vars_eNB->rb_mask_ul[0] |= (0x1 | (1<<5)); //position 5 + break; + case 15: + phy_vars_eNB->rb_mask_ul[0] |= (0x1 | (1<<14)); // position 14 + break; + case 25: + phy_vars_eNB->rb_mask_ul[0] |= (0x1 | (1<<24)); // position 24 + break; + case 50: + phy_vars_eNB->rb_mask_ul[0] |= 0x1; + phy_vars_eNB->rb_mask_ul[1] |= (1<<17); // position 49 (49-32) + break; + case 75: + phy_vars_eNB->rb_mask_ul[0] |= 0x1; + phy_vars_eNB->rb_mask_ul[2] |= (1<<10); // position 74 (74-64) + break; + case 100: + phy_vars_eNB->rb_mask_ul[0] |= 0x1; + phy_vars_eNB->rb_mask_ul[3] |= (1<<3); // position 99 (99-96) + break; + default: + LOG_E(PHY,"Unknown number for N_RB_UL %d\n",phy_vars_eNB->lte_frame_parms.N_RB_UL); + break; + } + if (do_SR == 1) { phy_vars_eNB->eNB_UE_stats[i].sr_total++; @@ -3924,7 +3967,7 @@ void phy_procedures_eNB_RX(const unsigned char sched_subframe,PHY_VARS_eNB *phy_ i, phy_vars_eNB->scheduling_request_config[i].sr_PUCCH_ResourceIndex, 0, // n2_pucch - 1, // shortened format + 0, // shortened format, should be use_srs flag, later &SR_payload, subframe, PUCCH1_THRES); @@ -4336,13 +4379,15 @@ void phy_procedures_eNB_RX(const unsigned char sched_subframe,PHY_VARS_eNB *phy_ } // loop i=0 ... NUMBER_OF_UE_MAX-1 - if (pusch_active == 0) { + // if (pusch_active == 0) { if (abstraction_flag == 0) { // LOG_D(PHY,"[eNB] Frame %d, subframe %d Doing I0_measurements\n", // (((subframe)==9)?-1:0) + phy_vars_eNB->proc[sched_subframe].frame_tx,subframe); lte_eNB_I0_measurements(phy_vars_eNB, + subframe, 0, phy_vars_eNB->first_run_I0_measurements); + phy_vars_eNB->first_run_I0_measurements = 0; } #ifdef PHY_ABSTRACTION @@ -4354,9 +4399,7 @@ void phy_procedures_eNB_RX(const unsigned char sched_subframe,PHY_VARS_eNB *phy_ #endif - if (I0_clear == 1) - I0_clear = 0; - } + //} #ifdef EMOS phy_procedures_emos_eNB_RX(subframe,phy_vars_eNB); diff --git a/openair1/SIMULATION/LTE_PHY/pucchsim.c b/openair1/SIMULATION/LTE_PHY/pucchsim.c index 919bec144d..cd29554b90 100644 --- a/openair1/SIMULATION/LTE_PHY/pucchsim.c +++ b/openair1/SIMULATION/LTE_PHY/pucchsim.c @@ -248,7 +248,7 @@ int main(int argc, char **argv) break; default: - msg("Unsupported channel model!\n"); + printf("Unsupported channel model!\n"); exit(-1); } @@ -260,13 +260,13 @@ int main(int argc, char **argv) case 's': snr0 = atof(optarg); - msg("Setting SNR0 to %f\n",snr0); + printf("Setting SNR0 to %f\n",snr0); break; case 'S': snr1 = atof(optarg); snr1set=1; - msg("Setting SNR1 to %f\n",snr1); + printf("Setting SNR1 to %f\n",snr1); break; case 'p': @@ -289,7 +289,7 @@ int main(int argc, char **argv) if ((transmission_mode!=1) && (transmission_mode!=2) && (transmission_mode!=6)) { - msg("Unsupported transmission mode %d\n",transmission_mode); + printf("Unsupported transmission mode %d\n",transmission_mode); exit(-1); } @@ -299,7 +299,7 @@ int main(int argc, char **argv) n_tx=atoi(optarg); if ((n_tx==0) || (n_tx>2)) { - msg("Unsupported number of tx antennas %d\n",n_tx); + printf("Unsupported number of tx antennas %d\n",n_tx); exit(-1); } @@ -309,7 +309,7 @@ int main(int argc, char **argv) n_rx=atoi(optarg); if ((n_rx==0) || (n_rx>2)) { - msg("Unsupported number of rx antennas %d\n",n_rx); + printf("Unsupported number of rx antennas %d\n",n_rx); exit(-1); } @@ -414,7 +414,7 @@ int main(int argc, char **argv) - msg("[SIM] Using SCM/101\n"); + printf("[SIM] Using SCM/101\n"); UE2eNB = new_channel_desc_scm(PHY_vars_eNB->lte_frame_parms.nb_antennas_tx, PHY_vars_UE->lte_frame_parms.nb_antennas_rx, channel_model, @@ -425,7 +425,7 @@ int main(int argc, char **argv) if (UE2eNB==NULL) { - msg("Problem generating channel model. Exiting.\n"); + printf("Problem generating channel model. Exiting.\n"); exit(-1); } @@ -453,7 +453,7 @@ int main(int argc, char **argv) PHY_vars_UE->lte_frame_parms.pucch_config_common.nRB_CQI = 0; PHY_vars_UE->lte_frame_parms.pucch_config_common.nCS_AN = 0; - pucch_payload = 1; + pucch_payload = 0; generate_pucch(PHY_vars_UE->lte_ue_common_vars.txdataF, frame_parms, @@ -596,9 +596,7 @@ int main(int argc, char **argv) } } - lte_eNB_I0_measurements(PHY_vars_eNB, - 0, - 1); + for (i=0; i<2*nsymb*OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES; i++) { for (aa=0; aalte_frame_parms.nb_antennas_rx; aa++) { @@ -646,6 +644,10 @@ int main(int argc, char **argv) // if (sig == 1) // printf("*"); + lte_eNB_I0_measurements(PHY_vars_eNB, + subframe, + 0, + 1); PHY_vars_eNB->PHY_measurements_eNB[0].n0_power_tot_dB = N0;//(int8_t)(sigma2_dB-10*log10(PHY_vars_eNB->lte_frame_parms.ofdm_symbol_size/(12*NB_RB))); stat = rx_pucch(PHY_vars_eNB, pucch_format, diff --git a/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c b/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c index 52e0f60d65..3dea35f053 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c @@ -1166,7 +1166,7 @@ schedule_ue_spec( // this is the normalized RX power eNB_UE_stats = mac_xface->get_eNB_UE_stats(module_idP,CC_id,rnti); normalized_rx_power = eNB_UE_stats->Po_PUCCH_dBm; - target_rx_power = mac_xface->get_target_pucch_rx_power(module_idP,CC_id) + 10; + target_rx_power = mac_xface->get_target_pucch_rx_power(module_idP,CC_id) + 20; // this assumes accumulated tpc // make sure that we are only sending a tpc update once a frame, otherwise the control loop will freak out @@ -1178,6 +1178,7 @@ schedule_ue_spec( UE_list->UE_template[CC_id][UE_id].pucch_tpc_tx_frame=frameP; UE_list->UE_template[CC_id][UE_id].pucch_tpc_tx_subframe=subframeP; + if (normalized_rx_power>(target_rx_power+1)) { tpc = 0; //-1 tpc_accumulated--; @@ -1187,9 +1188,11 @@ schedule_ue_spec( } else { tpc = 1; //0 } - LOG_D(MAC,"[eNB %d] DLSCH scheduler: frame %d, subframe %d, harq_pid %d, tpc %d, accumulated %d, normalized/target rx power %d/%d\n", + /* + LOG_I(MAC,"[eNB %d] DLSCH scheduler: frame %d, subframe %d, harq_pid %d, tpc %d, accumulated %d, normalized/target rx power %d/%d\n", module_idP,frameP, subframeP,harq_pid,tpc, - tpc_accumulated,normalized_rx_power,target_rx_power); + tpc_accumulated,normalized_rx_power,target_rx_power);*/ + } // Po_PUCCH has been updated else { tpc = 1; //0 @@ -1561,7 +1564,7 @@ fill_DLSCH_dci( eNB->common_channels[CC_id].bcch_active = 0; LOG_D(MAC,"[eNB %d] CC_id %d Frame %d subframeP %d: BCCH active\n", module_idP, CC_id, frameP, subframeP); // randomize frequency allocation for SI - first_rb = 10;//(unsigned char)(taus()%(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL-4)); + first_rb = 0;//10;//(unsigned char)(taus()%(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL-4)); /* Where is this from, should be removed!!!! diff --git a/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c b/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c index 1018c6e7d8..10c728f2a7 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c @@ -750,6 +750,7 @@ void schedule_ulsch_rnti(module_id_t module_idP, LOG_T(MAC,"[eNB %d] Frame %d, subframeP %d, UE %d CC %d : got harq pid %d round %d (nCCE %d, rnti %x,mode %s)\n", module_idP,frameP,subframeP,UE_id,CC_id, harq_pid, round,nCCE[CC_id],rnti,mode_string[eNB_UE_stats->mode]); +#undef EXMIMO_IOT #ifndef EXMIMO_IOT if (((UE_is_to_be_scheduled(module_idP,CC_id,UE_id)>0)) || (round>0) || ((frameP%10)==0)) diff --git a/targets/ARCH/COMMON/common_lib.c b/targets/ARCH/COMMON/common_lib.c index 8b91a74b49..f0bf1f6847 100644 --- a/targets/ARCH/COMMON/common_lib.c +++ b/targets/ARCH/COMMON/common_lib.c @@ -45,20 +45,23 @@ int openair0_device_init(openair0_device *device, openair0_config_t *openair0_cf #ifdef ETHERNET device->type=ETH_IF; device->func_type = BBU_FUNC; - openair0_dev_init_eth(device, openair0_cfg); printf(" openair0_dev_init_eth ...\n"); + return(openair0_dev_init_eth(device, openair0_cfg)); + #elif EXMIMO device->type=EXMIMO_IF; - openair0_dev_init_exmimo(device, openair0_cfg); printf("openair0_dev_init_exmimo...\n"); + return(openair0_dev_init_exmimo(device, openair0_cfg)); #elif OAI_USRP device->type=USRP_IF; - openair0_dev_init_usrp(device, openair0_cfg); printf("openair0_dev_init_usrp ...\n"); + return(openair0_dev_init_usrp(device, openair0_cfg)); + #elif OAI_BLADERF device->type=BLADERF_IF; - openair0_dev_init_bladerf(device, openair0_cfg); printf(" openair0_dev_init_bladerf ...\n"); + return(openair0_dev_init_bladerf(device, openair0_cfg)); + #endif } diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf index 2f11e42ba9..2974ce8551 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf @@ -28,7 +28,7 @@ eNBs = tdd_config_s = 0; prefix_type = "NORMAL"; eutra_band = 7; - downlink_frequency = 2680000000L; + downlink_frequency = 2660000000L; uplink_frequency_offset = -120000000; Nid_cell = 0; N_RB_DL = 25; @@ -143,10 +143,10 @@ eNBs = NETWORK_INTERFACES : { ENB_INTERFACE_NAME_FOR_S1_MME = "eth0"; - ENB_IPV4_ADDRESS_FOR_S1_MME = "192.168.12.216/24"; + ENB_IPV4_ADDRESS_FOR_S1_MME = "192.168.12.213/24"; ENB_INTERFACE_NAME_FOR_S1U = "eth0"; - ENB_IPV4_ADDRESS_FOR_S1U = "192.168.12.216/24"; + ENB_IPV4_ADDRESS_FOR_S1U = "192.168.12.213/24"; ENB_PORT_FOR_S1U = 2152; # Spec 2152 }; diff --git a/targets/RT/USER/lte-softmodem.c b/targets/RT/USER/lte-softmodem.c index b96a7ae529..623a83da2a 100644 --- a/targets/RT/USER/lte-softmodem.c +++ b/targets/RT/USER/lte-softmodem.c @@ -1631,6 +1631,8 @@ static void* eNB_thread( void* arg ) pthread_mutex_unlock(&sync_mutex); + printf( "got sync (eNB_thread)\n" ); + int frame = 0; #ifndef EXMIMO @@ -2893,12 +2895,12 @@ int main( int argc, char **argv ) bw = 0.96e6; #ifndef EXMIMO openair0_cfg[card].sample_rate=1.92e6; - openair0_cfg[card].samples_per_packet = 256; + openair0_cfg[card].samples_per_packet = 640; openair0_cfg[card].samples_per_frame = 19200; openair0_cfg[card].tx_bw = 1.5e6; openair0_cfg[card].rx_bw = 1.5e6; openair0_cfg[card].tx_forward_nsamps = 40; - openair0_cfg[card].tx_delay = 8; + openair0_cfg[card].tx_delay = 6; #endif } @@ -2992,10 +2994,14 @@ openair0_cfg[card].num_rb_dl=frame_parms[0]->N_RB_DL; openair0.func_type = BBU_FUNC; openair0_cfg[0].log_level = glog_level; - if ((mode!=loop_through_memory) && - (openair0_device_init(&openair0, &openair0_cfg[0]) <0)) { - printf("Exiting, cannot initialize device\n"); - exit(-1); + if (mode!=loop_through_memory){ + int ret; + ret= openair0_device_init(&openair0, &openair0_cfg[0]); + printf("openair0_device_init returns %d\n",ret); + if (ret<0) { + printf("Exiting, cannot initialize device\n"); + exit(-1); + } } else if (mode==loop_through_memory) { } @@ -3279,6 +3285,16 @@ openair0_cfg[card].num_rb_dl=frame_parms[0]->N_RB_DL; #endif printf("UE threads created\n"); +#ifdef USE_MME + + while (start_UE == 0) { + sleep(1); + } + +#endif + + + } else { if (multi_thread>0) { init_eNB_proc(); @@ -3306,13 +3322,7 @@ openair0_cfg[card].num_rb_dl=frame_parms[0]->N_RB_DL; // Sleep to allow all threads to setup sleep(1); -#ifdef USE_MME - while (start_UE == 0) { - sleep(1); - } - -#endif #ifndef EXMIMO @@ -3325,6 +3335,7 @@ openair0_cfg[card].num_rb_dl=frame_parms[0]->N_RB_DL; #endif + printf("Sending sync to all threads\n"); pthread_mutex_lock(&sync_mutex); sync_var=0; From e3030b0f9fa90bf7374fb96463590891b4b8923a Mon Sep 17 00:00:00 2001 From: Raymond Knopp Date: Thu, 22 Oct 2015 02:45:28 -0700 Subject: [PATCH 019/263] corrected HARQ ACK/NAK handling for TDD, in openair1/SCHED/phy_procedures_lte_common.c. --- openair1/SCHED/phy_procedures_lte_common.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openair1/SCHED/phy_procedures_lte_common.c b/openair1/SCHED/phy_procedures_lte_common.c index ce659a60f8..c51bd82d8a 100755 --- a/openair1/SCHED/phy_procedures_lte_common.c +++ b/openair1/SCHED/phy_procedures_lte_common.c @@ -405,8 +405,8 @@ uint8_t get_ack(LTE_DL_FRAME_PARMS *frame_parms, if (harq_ack[0].send_harq_status == 1) o_ACK[1] = harq_ack[0].ack; - } else if (harq_ack[8].send_harq_status == 1) - o_ACK[0] = harq_ack[8].ack; + } else if (harq_ack[0].send_harq_status == 1) + o_ACK[0] = harq_ack[0].ack; status = harq_ack[9].send_harq_status + (harq_ack[0].send_harq_status<<1); //printf("Subframe 4, TDD config 3: harq_ack[9] = %d,harq_ack[0] = %d\n",harq_ack[9].ack,harq_ack[0].ack); From b10937db8260db1e0e06e761545fd520a05db3a3 Mon Sep 17 00:00:00 2001 From: Raymond Knopp Date: Wed, 18 Nov 2015 14:18:58 -0800 Subject: [PATCH 020/263] Moved CCE allocations from PHY to MAC and updated MAC interfaces for BCCH/RA/UE-SPEC scheduling. --- openair1/PHY/CODING/lte_rate_matching.c | 9 +- openair1/PHY/LTE_TRANSPORT/dci.c | 18 +- openair1/PHY/LTE_TRANSPORT/defs.h | 6 +- openair1/PHY/LTE_TRANSPORT/dlsch_coding.c | 5 +- openair1/PHY/LTE_TRANSPORT/dlsch_decoding.c | 5 +- openair1/PHY/LTE_TRANSPORT/proto.h | 19 +- openair1/SCHED/defs.h | 1 - openair1/SCHED/phy_procedures_lte_eNb.c | 225 ++----- openair1/SIMULATION/LTE_PHY/dlsim.c | 32 +- openair2/LAYER2/MAC/defs.h | 13 +- openair2/LAYER2/MAC/eNB_scheduler.c | 188 +++--- openair2/LAYER2/MAC/eNB_scheduler_RA.c | 560 +++++++++++---- openair2/LAYER2/MAC/eNB_scheduler_bch.c | 150 ++++- openair2/LAYER2/MAC/eNB_scheduler_dlsch.c | 635 +----------------- .../LAYER2/MAC/eNB_scheduler_primitives.c | 205 ++++++ openair2/LAYER2/MAC/eNB_scheduler_ulsch.c | 55 +- openair2/LAYER2/MAC/main.c | 2 +- openair2/LAYER2/MAC/pre_processor.c | 13 +- openair2/LAYER2/MAC/proto.h | 48 +- openair2/PHY_INTERFACE/defs.h | 3 +- targets/SIMU/USER/init_lte.c | 20 +- 21 files changed, 1083 insertions(+), 1129 deletions(-) diff --git a/openair1/PHY/CODING/lte_rate_matching.c b/openair1/PHY/CODING/lte_rate_matching.c index 69697fc2e0..96663bd8a6 100644 --- a/openair1/PHY/CODING/lte_rate_matching.c +++ b/openair1/PHY/CODING/lte_rate_matching.c @@ -36,6 +36,7 @@ #include #endif #include "PHY/defs.h" +#include "assertions.h" //#define cmin(a,b) ((a)<(b) ? (a) : (b)) @@ -515,16 +516,14 @@ uint32_t lte_rate_matching_turbo(uint32_t RTC, // if (rvidx==3) // for (cnt=0;cnt=(3*RTC<<5),"Exiting, RM condition (Ncb %d, Nir/C %d, Nsoft %d, Kw %d\n",Ncb,Nir/C,Nsoft,3*(RTC<<5)); + Gp = G/Nl/Qm; GpmodC = Gp%C; #ifdef RM_DEBUG - printf("lte_rate_matching_turbo: Kw %d, rvidx %d, G %d, Qm %d, Nl%d, r %d\n",3*(RTC<<5),rvidx, G, Qm,Nl,r); + printf("lte_rate_matching_turbo: Ncb %d, Kw %d, Nir/C %d, rvidx %d, G %d, Qm %d, Nl%d, r %d\n",Ncb,3*(RTC<<5),Nir/C,rvidx, G, Qm,Nl,r); #endif if (r < (C-(GpmodC))) diff --git a/openair1/PHY/LTE_TRANSPORT/dci.c b/openair1/PHY/LTE_TRANSPORT/dci.c index 2fd89c8f64..f126d0e2ea 100644 --- a/openair1/PHY/LTE_TRANSPORT/dci.c +++ b/openair1/PHY/LTE_TRANSPORT/dci.c @@ -2108,14 +2108,14 @@ uint8_t generate_dci_top(uint8_t num_ue_spec_dci, if (dci_alloc[i].L == (uint8_t)L) { #ifdef DEBUG_DCI_ENCODING - LOG_I(PHY,"Generating common DCI %d/%d (nCCE %d) of length %d, aggregation %d (%x)\n",i,num_common_dci,dci_alloc[i].nCCE,dci_alloc[i].dci_length,1<=0) { + if (dci_alloc[i].firstCCE>=0) { e_ptr = generate_dci0(dci_alloc[i].dci_pdu, - e+(72*dci_alloc[i].nCCE), + e+(72*dci_alloc[i].firstCCE), dci_alloc[i].dci_length, dci_alloc[i].L, dci_alloc[i].rnti); @@ -2133,9 +2133,9 @@ uint8_t generate_dci_top(uint8_t num_ue_spec_dci, dump_dci(frame_parms,&dci_alloc[i]); #endif - if (dci_alloc[i].nCCE >= 0) { + if (dci_alloc[i].firstCCE >= 0) { e_ptr = generate_dci0(dci_alloc[i].dci_pdu, - e+(72*dci_alloc[i].nCCE), + e+(72*dci_alloc[i].firstCCE), dci_alloc[i].dci_length, dci_alloc[i].L, dci_alloc[i].rnti); @@ -2537,11 +2537,13 @@ uint16_t get_nquad(uint8_t num_pdcch_symbols,LTE_DL_FRAME_PARMS *frame_parms,uin return(Nreg - 4 - (3*Ngroup_PHICH)); } -uint16_t get_nCCE_max(uint8_t Mod_id,uint8_t CC_id) +uint16_t get_nCCE_mac(uint8_t Mod_id,uint8_t CC_id,int num_pdcch_symbols,int subframe) { // check for eNB only ! - return(get_nCCE(3,&PHY_vars_eNB_g[Mod_id][CC_id]->lte_frame_parms,1)); // 5, 15,21 + return(get_nCCE(num_pdcch_symbols, + &PHY_vars_eNB_g[Mod_id][CC_id]->lte_frame_parms, + get_mi(&PHY_vars_eNB_g[Mod_id][CC_id]->lte_frame_parms,subframe))); } void dci_decoding_procedure0(LTE_UE_PDCCH **lte_ue_pdcch_vars, @@ -2691,7 +2693,7 @@ void dci_decoding_procedure0(LTE_UE_PDCCH **lte_ue_pdcch_vars, dci_alloc[*dci_cnt].dci_length = sizeof_bits; dci_alloc[*dci_cnt].rnti = crc; dci_alloc[*dci_cnt].L = L; - dci_alloc[*dci_cnt].nCCE = CCEind; + dci_alloc[*dci_cnt].firstCCE = CCEind; if (sizeof_bytes<=4) { dci_alloc[*dci_cnt].dci_pdu[3] = dci_decoded_output[0]; diff --git a/openair1/PHY/LTE_TRANSPORT/defs.h b/openair1/PHY/LTE_TRANSPORT/defs.h index 8b23c51079..f25e199e9d 100644 --- a/openair1/PHY/LTE_TRANSPORT/defs.h +++ b/openair1/PHY/LTE_TRANSPORT/defs.h @@ -266,6 +266,8 @@ typedef struct { uint8_t Mdlharq; /// MIMO transmission mode indicator for this sub-frame (for definition see 36-212 V8.6 2009-03, p.17) uint8_t Kmimo; + /// Nsoft parameter related to UE Category + uint32_t Nsoft; /// amplitude of PDSCH (compared to RS) in symbols without pilots int16_t sqrt_rho_a; /// amplitude of PDSCH (compared to RS) in symbols containing pilots @@ -693,6 +695,8 @@ typedef struct { uint8_t Mdlharq; /// MIMO transmission mode indicator for this sub-frame (for definition see 36-212 V8.6 2009-03, p.17) uint8_t Kmimo; + /// Nsoft parameter related to UE Category + uint32_t Nsoft; /// Maximum number of Turbo iterations uint8_t max_turbo_iterations; /// accumulated tx power adjustment for PUCCH @@ -737,7 +741,7 @@ typedef struct { /// Aggregation level uint8_t L; /// Position of first CCE of the dci - int nCCE; + int firstCCE; /// flag to indicate that this is a RA response boolean_t ra_flag; /// rnti diff --git a/openair1/PHY/LTE_TRANSPORT/dlsch_coding.c b/openair1/PHY/LTE_TRANSPORT/dlsch_coding.c index 83066480b4..a2f33f0fb2 100644 --- a/openair1/PHY/LTE_TRANSPORT/dlsch_coding.c +++ b/openair1/PHY/LTE_TRANSPORT/dlsch_coding.c @@ -117,7 +117,7 @@ void free_eNB_dlsch(LTE_eNB_DLSCH_t *dlsch) } -LTE_eNB_DLSCH_t *new_eNB_dlsch(unsigned char Kmimo,unsigned char Mdlharq,unsigned char N_RB_DL, uint8_t abstraction_flag) +LTE_eNB_DLSCH_t *new_eNB_dlsch(unsigned char Kmimo,unsigned char Mdlharq,uint32_t Nsoft,unsigned char N_RB_DL, uint8_t abstraction_flag) { LTE_eNB_DLSCH_t *dlsch; @@ -148,6 +148,7 @@ LTE_eNB_DLSCH_t *new_eNB_dlsch(unsigned char Kmimo,unsigned char Mdlharq,unsigne bzero(dlsch,sizeof(LTE_eNB_DLSCH_t)); dlsch->Kmimo = Kmimo; dlsch->Mdlharq = Mdlharq; + dlsch->Nsoft = Nsoft; for (i=0; i<10; i++) dlsch->harq_ids[i] = Mdlharq; @@ -395,7 +396,7 @@ int dlsch_encoding(unsigned char *a, dlsch->harq_processes[harq_pid]->w[r], dlsch->harq_processes[harq_pid]->e+r_offset, dlsch->harq_processes[harq_pid]->C, // C - NSOFT, // Nsoft, + dlsch->Nsoft, // Nsoft, dlsch->Mdlharq, dlsch->Kmimo, dlsch->harq_processes[harq_pid]->rvidx, diff --git a/openair1/PHY/LTE_TRANSPORT/dlsch_decoding.c b/openair1/PHY/LTE_TRANSPORT/dlsch_decoding.c index 6ab784aa18..efcd868338 100644 --- a/openair1/PHY/LTE_TRANSPORT/dlsch_decoding.c +++ b/openair1/PHY/LTE_TRANSPORT/dlsch_decoding.c @@ -81,7 +81,7 @@ void free_ue_dlsch(LTE_UE_DLSCH_t *dlsch) } } -LTE_UE_DLSCH_t *new_ue_dlsch(uint8_t Kmimo,uint8_t Mdlharq,uint8_t max_turbo_iterations,uint8_t N_RB_DL, uint8_t abstraction_flag) +LTE_UE_DLSCH_t *new_ue_dlsch(uint8_t Kmimo,uint8_t Mdlharq,uint32_t Nsoft,uint8_t max_turbo_iterations,uint8_t N_RB_DL, uint8_t abstraction_flag) { LTE_UE_DLSCH_t *dlsch; @@ -113,6 +113,7 @@ LTE_UE_DLSCH_t *new_ue_dlsch(uint8_t Kmimo,uint8_t Mdlharq,uint8_t max_turbo_ite memset(dlsch,0,sizeof(LTE_UE_DLSCH_t)); dlsch->Kmimo = Kmimo; dlsch->Mdlharq = Mdlharq; + dlsch->Nsoft = Nsoft; dlsch->max_turbo_iterations = max_turbo_iterations; for (i=0; iC, - NSOFT, + dlsch->Nsoft, dlsch->Mdlharq, dlsch->Kmimo, harq_process->rvidx, diff --git a/openair1/PHY/LTE_TRANSPORT/proto.h b/openair1/PHY/LTE_TRANSPORT/proto.h index 5142f9443a..3f85dec055 100644 --- a/openair1/PHY/LTE_TRANSPORT/proto.h +++ b/openair1/PHY/LTE_TRANSPORT/proto.h @@ -56,15 +56,16 @@ void free_eNB_dlsch(LTE_eNB_DLSCH_t *dlsch); void clean_eNb_dlsch(LTE_eNB_DLSCH_t *dlsch, uint8_t abstraction_flag); -/** \fn new_eNB_dlsch(uint8_t Kmimo,uint8_t Mdlharq,uint8_t abstraction_flag) +/** \fn new_eNB_dlsch(uint8_t Kmimo,uint8_t Mdlharq,uint32_t Nsoft,uint8_t abstraction_flag) \brief This function allocates structures for a particular DLSCH at eNB @returns Pointer to DLSCH to be removed @param Kmimo Kmimo factor from 36-212/36-213 @param Mdlharq Maximum number of HARQ rounds (36-212/36-213) + @param Nsoft Soft-LLR buffer size from UE-Category @params N_RB_DL total number of resource blocks (determine the operating BW) @param abstraction_flag Flag to indicate abstracted interface */ -LTE_eNB_DLSCH_t *new_eNB_dlsch(uint8_t Kmimo,uint8_t Mdlharq,uint8_t N_RB_DL, uint8_t abstraction_flag); +LTE_eNB_DLSCH_t *new_eNB_dlsch(uint8_t Kmimo,uint8_t Mdlharq,uint32_t Nsoft,uint8_t N_RB_DL, uint8_t abstraction_flag); /** \fn free_ue_dlsch(LTE_UE_DLSCH_t *dlsch) \brief This function frees memory allocated for a particular DLSCH at UE @@ -72,8 +73,16 @@ LTE_eNB_DLSCH_t *new_eNB_dlsch(uint8_t Kmimo,uint8_t Mdlharq,uint8_t N_RB_DL, ui */ void free_ue_dlsch(LTE_UE_DLSCH_t *dlsch); -LTE_UE_DLSCH_t *new_ue_dlsch(uint8_t Kmimo,uint8_t Mdlharq,uint8_t max_turbo_iterations,uint8_t N_RB_DL, uint8_t abstraction_flag); - +/** \fn new_ue_dlsch(uint8_t Kmimo,uint8_t Mdlharq,uint32_t Nsoft,uint8_t abstraction_flag) + \brief This function allocates structures for a particular DLSCH at eNB + @returns Pointer to DLSCH to be removed + @param Kmimo Kmimo factor from 36-212/36-213 + @param Mdlharq Maximum number of HARQ rounds (36-212/36-213) + @param Nsoft Soft-LLR buffer size from UE-Category + @params N_RB_DL total number of resource blocks (determine the operating BW) + @param abstraction_flag Flag to indicate abstracted interface +*/ +LTE_UE_DLSCH_t *new_ue_dlsch(uint8_t Kmimo,uint8_t Mdlharq,uint32_t Nsoft,uint8_t max_turbo_iterations,uint8_t N_RB_DL, uint8_t abstraction_flag); void clean_eNb_ulsch(LTE_eNB_ULSCH_t *ulsch, uint8_t abstraction_flag); @@ -1584,7 +1593,7 @@ uint16_t get_nquad(uint8_t num_pdcch_symbols,LTE_DL_FRAME_PARMS *frame_parms,uin uint8_t get_mi(LTE_DL_FRAME_PARMS *frame,uint8_t subframe); -uint16_t get_nCCE_max(uint8_t Mod_id,uint8_t CC_id); +uint16_t get_nCCE_mac(uint8_t Mod_id,uint8_t CC_id,int num_pdcch_symbols,int subframe); uint8_t get_num_pdcch_symbols(uint8_t num_dci,DCI_ALLOC_t *dci_alloc,LTE_DL_FRAME_PARMS *frame_parms,uint8_t subframe); diff --git a/openair1/SCHED/defs.h b/openair1/SCHED/defs.h index bebe476dcd..bcf2c213c2 100644 --- a/openair1/SCHED/defs.h +++ b/openair1/SCHED/defs.h @@ -399,7 +399,6 @@ uint32_t pdcch_alloc2ul_frame(LTE_DL_FRAME_PARMS *frame_parms,uint32_t frame, ui uint16_t get_Np(uint8_t N_RB_DL,uint8_t nCCE,uint8_t plus1); -int get_nCCE_offset(unsigned char L, int nCCE, int common_dci, unsigned short rnti, unsigned char subframe); int8_t find_ue(uint16_t rnti, PHY_VARS_eNB *phy_vars_eNB); diff --git a/openair1/SCHED/phy_procedures_lte_eNb.c b/openair1/SCHED/phy_procedures_lte_eNb.c index b9cb618ea0..cb78f429b5 100755 --- a/openair1/SCHED/phy_procedures_lte_eNb.c +++ b/openair1/SCHED/phy_procedures_lte_eNb.c @@ -296,100 +296,6 @@ int get_ue_active_harq_pid(const uint8_t Mod_id,const uint8_t CC_id,const uint16 } -int CCE_table[800]; - -void init_nCCE_table(void) -{ - memset(CCE_table,0,800*sizeof(int)); -} - - -int get_nCCE_offset(const unsigned char L, const int nCCE, const int common_dci, const unsigned short rnti, const unsigned char subframe) -{ - - int search_space_free,m,nb_candidates = 0,l,i; - unsigned int Yk; - - /* - printf("CCE Allocation: "); - for (i=0;i=0 ; m--) { - search_space_free = 1; - for (l=0; lPHY_measurements_eNB[0].n0_power_tot_dBm; @@ -1811,15 +1717,18 @@ void phy_procedures_eNB_TX(unsigned char sched_subframe,PHY_VARS_eNB *phy_vars_e phy_vars_eNB->dlsch_eNB[i][0]->subframe_tx[subframe] = 0; } - init_nCCE_table(); + // init_nCCE_table(); - num_pdcch_symbols = get_num_pdcch_symbols(DCI_pdu->Num_common_dci + DCI_pdu->Num_ue_spec_dci, - DCI_pdu->dci_alloc, - &phy_vars_eNB->lte_frame_parms, - subframe); + num_pdcch_symbols = DCI_pdu->num_pdcch_symbols; + /*get_num_pdcch_symbols(DCI_pdu->Num_common_dci + DCI_pdu->Num_ue_spec_dci, + DCI_pdu->dci_alloc, + &phy_vars_eNB->lte_frame_parms, + subframe);*/ + /* DCI_pdu->nCCE = get_nCCE(num_pdcch_symbols, &phy_vars_eNB->lte_frame_parms, - get_mi(&phy_vars_eNB->lte_frame_parms,subframe)); + get_mi(&phy_vars_eNB->lte_frame_parms,subframe));*/ + LOG_D(PHY,"num_pdcch_symbols %"PRIu8", nCCE %u (dci commond %"PRIu8", dci uespec %"PRIu8"\n",num_pdcch_symbols,DCI_pdu->nCCE, DCI_pdu->Num_common_dci,DCI_pdu->Num_ue_spec_dci); @@ -1835,6 +1744,7 @@ void phy_procedures_eNB_TX(unsigned char sched_subframe,PHY_VARS_eNB *phy_vars_e #endif for (i=0; iNum_common_dci + DCI_pdu->Num_ue_spec_dci ; i++) { + LOG_D(PHY,"[eNB] Subframe %d: DCI %d/%d : rnti %x, CCEind %d\n",subframe,i,DCI_pdu->Num_common_dci+DCI_pdu->Num_ue_spec_dci,DCI_pdu->dci_alloc[i].rnti,DCI_pdu->dci_alloc[i].firstCCE); #ifdef DEBUG_PHY_PROC if (DCI_pdu->dci_alloc[i].rnti != SI_RNTI) { @@ -1862,28 +1772,21 @@ void phy_procedures_eNB_TX(unsigned char sched_subframe,PHY_VARS_eNB *phy_vars_e phy_vars_eNB->eNB_UE_stats[0].DL_pmi_single); - int result = get_nCCE_offset(1<dci_alloc[i].L, DCI_pdu->nCCE, 1, SI_RNTI, subframe); - phy_vars_eNB->dlsch_eNB_SI->nCCE[subframe] = result; - - if (result == -1) { - // FIXME what happens to phy_vars_eNB->dlsch_eNB_SI->nCCE[subframe]? - LOG_E(PHY,"[eNB %"PRIu8"] Frame %d subframe %d : No available CCE resources for common DCI (SI)!!!\n",phy_vars_eNB->Mod_id,phy_vars_eNB->proc[sched_subframe].frame_tx,subframe); - } else { - LOG_T(PHY,"[eNB %"PRIu8"] Frame %d subframe %d : CCE resource for common DCI (SI) => %"PRIu8"/%u\n",phy_vars_eNB->Mod_id,phy_vars_eNB->proc[sched_subframe].frame_tx,subframe, - phy_vars_eNB->dlsch_eNB_SI->nCCE[subframe],DCI_pdu->nCCE); + phy_vars_eNB->dlsch_eNB_SI->nCCE[subframe] = DCI_pdu->dci_alloc[i].firstCCE; + LOG_T(PHY,"[eNB %"PRIu8"] Frame %d subframe %d : CCE resource for common DCI (SI) => %"PRIu8"/%u\n",phy_vars_eNB->Mod_id,phy_vars_eNB->proc[sched_subframe].frame_tx,subframe, + phy_vars_eNB->dlsch_eNB_SI->nCCE[subframe],DCI_pdu->nCCE); + #if defined(SMBV) && !defined(EXMIMO) - // configure SI DCI - if (smbv_is_config_frame(phy_vars_eNB->proc[sched_subframe].frame_tx) && (smbv_frame_cnt < 4)) { - msg("[SMBV] Frame %3d, SI in SF %d DCI %"PRIu32"\n",phy_vars_eNB->proc[sched_subframe].frame_tx,subframe,i); - smbv_configure_common_dci(smbv_fname,(smbv_frame_cnt*10) + (subframe), "SI", &DCI_pdu->dci_alloc[i], i); - } - -#endif + // configure SI DCI + if (smbv_is_config_frame(phy_vars_eNB->proc[sched_subframe].frame_tx) && (smbv_frame_cnt < 4)) { + msg("[SMBV] Frame %3d, SI in SF %d DCI %"PRIu32"\n",phy_vars_eNB->proc[sched_subframe].frame_tx,subframe,i); + smbv_configure_common_dci(smbv_fname,(smbv_frame_cnt*10) + (subframe), "SI", &DCI_pdu->dci_alloc[i], i); } - - DCI_pdu->dci_alloc[i].nCCE = phy_vars_eNB->dlsch_eNB_SI->nCCE[subframe]; + +#endif + } else if (DCI_pdu->dci_alloc[i].ra_flag == 1) { #ifdef DEBUG_PHY_PROC @@ -1904,28 +1807,20 @@ void phy_procedures_eNB_TX(unsigned char sched_subframe,PHY_VARS_eNB *phy_vars_e // mac_xface->macphy_exit("Transmitted RAR, exiting\n"); - int result = get_nCCE_offset(1<dci_alloc[i].L, DCI_pdu->nCCE, 1, DCI_pdu->dci_alloc[i].rnti, subframe); - phy_vars_eNB->dlsch_eNB_ra->nCCE[subframe] = result; - if (result == -1) { - // FIXME what happens to phy_vars_eNB->dlsch_eNB_ra->nCCE[subframe]? - LOG_E(PHY,"[eNB %"PRIu8"] Frame %d subframe %d : No available CCE resources for common DCI (RA) !!!\n",phy_vars_eNB->Mod_id,phy_vars_eNB->proc[sched_subframe].frame_tx,subframe); - } else { - LOG_D(PHY,"[eNB %"PRIu8"] Frame %d subframe %d : CCE resource for common DCI (RA) => %"PRIu8"/%u\n",phy_vars_eNB->Mod_id,phy_vars_eNB->proc[sched_subframe].frame_tx,subframe, - phy_vars_eNB->dlsch_eNB_ra->nCCE[subframe],DCI_pdu->nCCE); + phy_vars_eNB->dlsch_eNB_ra->nCCE[subframe] = DCI_pdu->dci_alloc[i].firstCCE; + + LOG_D(PHY,"[eNB %"PRIu8"] Frame %d subframe %d : CCE resource for common DCI (RA) => %"PRIu8"/%u\n",phy_vars_eNB->Mod_id,phy_vars_eNB->proc[sched_subframe].frame_tx,subframe, + phy_vars_eNB->dlsch_eNB_ra->nCCE[subframe],DCI_pdu->nCCE); #if defined(SMBV) && !defined(EXMIMO) - // configure RA DCI - if (smbv_is_config_frame(phy_vars_eNB->proc[sched_subframe].frame_tx) && (smbv_frame_cnt < 4)) { - msg("[SMBV] Frame %3d, RA in SF %d DCI %"PRIu32"\n",phy_vars_eNB->proc[sched_subframe].frame_tx,subframe,i); - smbv_configure_common_dci(smbv_fname,(smbv_frame_cnt*10) + (subframe), "RA", &DCI_pdu->dci_alloc[i], i); - } - -#endif - + // configure RA DCI + if (smbv_is_config_frame(phy_vars_eNB->proc[sched_subframe].frame_tx) && (smbv_frame_cnt < 4)) { + msg("[SMBV] Frame %3d, RA in SF %d DCI %"PRIu32"\n",phy_vars_eNB->proc[sched_subframe].frame_tx,subframe,i); + smbv_configure_common_dci(smbv_fname,(smbv_frame_cnt*10) + (subframe), "RA", &DCI_pdu->dci_alloc[i], i); } - DCI_pdu->dci_alloc[i].nCCE = phy_vars_eNB->dlsch_eNB_ra->nCCE[subframe]; +#endif } @@ -1966,30 +1861,22 @@ void phy_procedures_eNB_TX(unsigned char sched_subframe,PHY_VARS_eNB *phy_vars_e LOG_D(PHY,"[eNB %"PRIu8"][PDSCH %"PRIx16"/%"PRIu8"] Frame %d subframe %d: Generated dlsch params\n", phy_vars_eNB->Mod_id,DCI_pdu->dci_alloc[i].rnti,phy_vars_eNB->dlsch_eNB[(uint8_t)UE_id][0]->current_harq_pid,phy_vars_eNB->proc[sched_subframe].frame_tx,subframe); - int result = get_nCCE_offset(1<dci_alloc[i].L, DCI_pdu->nCCE, 0, DCI_pdu->dci_alloc[i].rnti, subframe); - phy_vars_eNB->dlsch_eNB[(uint8_t)UE_id][0]->nCCE[subframe] = result; - if (result == -1) { - // FIXME what happens to phy_vars_eNB->dlsch_eNB[(uint8_t)UE_id][0]->nCCE[subframe]? - LOG_E(PHY,"[eNB %"PRIu8"] Frame %d subframe %d : No available CCE resources for UE spec DCI (PDSCH %"PRIx16") !!!\n", - phy_vars_eNB->Mod_id,phy_vars_eNB->proc[sched_subframe].frame_tx,subframe,DCI_pdu->dci_alloc[i].rnti); - } else { - LOG_D(PHY,"[eNB %"PRIu8"] Frame %d subframe %d : CCE resource for ue DCI (PDSCH %"PRIx16") => %"PRIu8"/%u\n",phy_vars_eNB->Mod_id,phy_vars_eNB->proc[sched_subframe].frame_tx,subframe, - DCI_pdu->dci_alloc[i].rnti,phy_vars_eNB->dlsch_eNB[(uint8_t)UE_id][0]->nCCE[subframe],DCI_pdu->nCCE); + phy_vars_eNB->dlsch_eNB[(uint8_t)UE_id][0]->nCCE[subframe] = DCI_pdu->dci_alloc[i].firstCCE; + + LOG_D(PHY,"[eNB %"PRIu8"] Frame %d subframe %d : CCE resource for ue DCI (PDSCH %"PRIx16") => %"PRIu8"/%u\n",phy_vars_eNB->Mod_id,phy_vars_eNB->proc[sched_subframe].frame_tx,subframe, + DCI_pdu->dci_alloc[i].rnti,phy_vars_eNB->dlsch_eNB[(uint8_t)UE_id][0]->nCCE[subframe],DCI_pdu->nCCE); #if defined(SMBV) && !defined(EXMIMO) - DCI_pdu->dci_alloc[i].nCCE = phy_vars_eNB->dlsch_eNB[(uint8_t)UE_id][0]->nCCE[subframe]; - - // configure UE-spec DCI - if (smbv_is_config_frame(phy_vars_eNB->proc[sched_subframe].frame_tx) && (smbv_frame_cnt < 4)) { - msg("[SMBV] Frame %3d, PDSCH in SF %d DCI %"PRIu32"\n",phy_vars_eNB->proc[sched_subframe].frame_tx,subframe,i); - smbv_configure_ue_spec_dci(smbv_fname,(smbv_frame_cnt*10) + (subframe), UE_id+1, &DCI_pdu->dci_alloc[i], i); - } + + // configure UE-spec DCI + if (smbv_is_config_frame(phy_vars_eNB->proc[sched_subframe].frame_tx) && (smbv_frame_cnt < 4)) { + msg("[SMBV] Frame %3d, PDSCH in SF %d DCI %"PRIu32"\n",phy_vars_eNB->proc[sched_subframe].frame_tx,subframe,i); + smbv_configure_ue_spec_dci(smbv_fname,(smbv_frame_cnt*10) + (subframe), UE_id+1, &DCI_pdu->dci_alloc[i], i); + } #endif - } - DCI_pdu->dci_alloc[i].nCCE = phy_vars_eNB->dlsch_eNB[(uint8_t)UE_id][0]->nCCE[subframe]; #ifdef DEBUG_PHY_PROC //if (phy_vars_eNB->proc[sched_subframe].frame_tx%100 == 0) LOG_D(PHY,"[eNB %"PRIu8"][DCI][PDSCH %"PRIx16"] Frame %d subframe %d UE_id %"PRId8" Generated DCI format %d, aggregation %d\n", @@ -2067,29 +1954,21 @@ void phy_procedures_eNB_TX(unsigned char sched_subframe,PHY_VARS_eNB *phy_vars_e CBA_RNTI, 0); // do_srs - if ((DCI_pdu->dci_alloc[i].nCCE=get_nCCE_offset(1<dci_alloc[i].L, - DCI_pdu->nCCE, - 0, - DCI_pdu->dci_alloc[i].rnti, - subframe)) == -1) { - LOG_E(PHY,"[eNB %"PRIu8"] Frame %d subframe %d : No available CCE resources (%u) for UE spec DCI (PUSCH %"PRIx16") !!!\n", - phy_vars_eNB->Mod_id,phy_vars_eNB->proc[sched_subframe].frame_tx,subframe,DCI_pdu->nCCE,DCI_pdu->dci_alloc[i].rnti); - } else { - LOG_T(PHY,"[eNB %"PRIu8"] Frame %d subframe %d : CCE resources for UE spec DCI (PUSCH %"PRIx16") => %d/%u\n", - phy_vars_eNB->Mod_id,phy_vars_eNB->proc[sched_subframe].frame_tx,subframe,DCI_pdu->dci_alloc[i].rnti, - DCI_pdu->dci_alloc[i].nCCE,DCI_pdu->nCCE); - + LOG_T(PHY,"[eNB %"PRIu8"] Frame %d subframe %d : CCE resources for UE spec DCI (PUSCH %"PRIx16") => %d/%u\n", + phy_vars_eNB->Mod_id,phy_vars_eNB->proc[sched_subframe].frame_tx,subframe,DCI_pdu->dci_alloc[i].rnti, + DCI_pdu->dci_alloc[i].firstCCE,DCI_pdu->nCCE); + #if defined(SMBV) && !defined(EXMIMO) // configure UE-spec DCI for UL Grant - if (smbv_is_config_frame(phy_vars_eNB->proc[sched_subframe].frame_tx) && (smbv_frame_cnt < 4)) { - msg("[SMBV] Frame %3d, SF %d UL DCI %"PRIu32"\n",phy_vars_eNB->proc[sched_subframe].frame_tx,subframe,i); - smbv_configure_ue_spec_dci(smbv_fname,(smbv_frame_cnt*10) + (subframe), UE_id+1, &DCI_pdu->dci_alloc[i], i); - } - + if (smbv_is_config_frame(phy_vars_eNB->proc[sched_subframe].frame_tx) && (smbv_frame_cnt < 4)) { + msg("[SMBV] Frame %3d, SF %d UL DCI %"PRIu32"\n",phy_vars_eNB->proc[sched_subframe].frame_tx,subframe,i); + smbv_configure_ue_spec_dci(smbv_fname,(smbv_frame_cnt*10) + (subframe), UE_id+1, &DCI_pdu->dci_alloc[i], i); + } + #endif - } + #ifdef DEBUG_PHY_PROC LOG_D(PHY,"[eNB %"PRIu8"][PUSCH %"PRIu8"] frame %d subframe %d Setting subframe_scheduling_flag for UE %"PRIu32" harq_pid %"PRIu8" (ul subframe %"PRIu8")\n", @@ -2120,13 +1999,13 @@ void phy_procedures_eNB_TX(unsigned char sched_subframe,PHY_VARS_eNB *phy_vars_e } if (abstraction_flag == 0) { -#ifdef DEBUG_PHY_PROC + //#ifdef DEBUG_PHY_PROC if (DCI_pdu->Num_ue_spec_dci+DCI_pdu->Num_common_dci > 0) LOG_D(PHY,"[eNB %"PRIu8"] Frame %d, subframe %d: Calling generate_dci_top (pdcch) (common %"PRIu8",ue_spec %"PRIu8")\n",phy_vars_eNB->Mod_id,phy_vars_eNB->proc[sched_subframe].frame_tx, subframe, DCI_pdu->Num_common_dci,DCI_pdu->Num_ue_spec_dci); -#endif + //#endif // for (sect_id=0;sect_idNum_ue_spec_dci, diff --git a/openair1/SIMULATION/LTE_PHY/dlsim.c b/openair1/SIMULATION/LTE_PHY/dlsim.c index 0e0dce370c..3227be22b4 100644 --- a/openair1/SIMULATION/LTE_PHY/dlsim.c +++ b/openair1/SIMULATION/LTE_PHY/dlsim.c @@ -347,6 +347,8 @@ int main(int argc, char **argv) LTE_DL_UE_HARQ_t *dlsch0_ue_harq; LTE_DL_eNB_HARQ_t *dlsch0_eNB_harq; uint8_t Kmimo; + uint8_t ue_category=4; + uint32_t Nsoft; FILE *proc_fd = NULL; char buf[64]; @@ -378,7 +380,7 @@ int main(int argc, char **argv) num_layers = 1; perfect_ce = 0; - while ((c = getopt (argc, argv, "ahdpZDe:m:n:o:s:f:t:c:g:r:F:x:y:z:AM:N:I:i:O:R:S:C:T:b:u:v:w:B:PLl:Y")) != -1) { + while ((c = getopt (argc, argv, "ahdpZDe:m:n:o:s:f:t:c:g:r:F:x:y:z:AM:N:I:i:O:R:S:C:T:b:u:U:v:w:B:PLl:Y")) != -1) { switch (c) { case 'a': awgn_flag = 1; @@ -522,7 +524,6 @@ int main(int argc, char **argv) case 'N': channel_model=AWGN; break; - default: msg("Unsupported channel model!\n"); exit(-1); @@ -530,6 +531,10 @@ int main(int argc, char **argv) break; + case 'U': + ue_category = atoi(optarg); + break; + case 'x': transmission_mode=atoi(optarg); @@ -993,10 +998,27 @@ int main(int argc, char **argv) else Kmimo=1; + switch (ue_category) { + case 1: + Nsoft = 250368; + break; + case 2: + case 3: + Nsoft = 1237248; + break; + case 4: + Nsoft = 1827072; + break; + default: + printf("Unsupported UE category %d\n",ue_category); + exit(-1); + break; + } + for (k=0; kdlsch_eNB[k][i] = new_eNB_dlsch(Kmimo,8,N_RB_DL,0); + PHY_vars_eNB->dlsch_eNB[k][i] = new_eNB_dlsch(Kmimo,8,Nsoft,N_RB_DL,0); if (!PHY_vars_eNB->dlsch_eNB[k][i]) { printf("Can't get eNB dlsch structures\n"); @@ -1008,7 +1030,7 @@ int main(int argc, char **argv) } for (i=0; i<2; i++) { - PHY_vars_UE->dlsch_ue[0][i] = new_ue_dlsch(Kmimo,8,MAX_TURBO_ITERATIONS,N_RB_DL,0); + PHY_vars_UE->dlsch_ue[0][i] = new_ue_dlsch(Kmimo,8,Nsoft,MAX_TURBO_ITERATIONS,N_RB_DL,0); if (!PHY_vars_UE->dlsch_ue[0][i]) { printf("Can't get ue dlsch structures\n"); @@ -1019,7 +1041,7 @@ int main(int argc, char **argv) } // structure for SIC at UE - PHY_vars_UE->dlsch_eNB[0] = new_eNB_dlsch(Kmimo,8,N_RB_DL,0); + PHY_vars_UE->dlsch_eNB[0] = new_eNB_dlsch(Kmimo,8,Nsoft,N_RB_DL,0); if (DLSCH_alloc_pdu2_1E[0].tpmi == 5) { diff --git a/openair2/LAYER2/MAC/defs.h b/openair2/LAYER2/MAC/defs.h index a0a43b6d79..d92a143348 100644 --- a/openair2/LAYER2/MAC/defs.h +++ b/openair2/LAYER2/MAC/defs.h @@ -251,7 +251,8 @@ typedef struct { typedef struct { uint8_t Num_ue_spec_dci ; uint8_t Num_common_dci ; - unsigned int nCCE; + uint32_t nCCE; + uint32_t num_pdcch_symbols; DCI_ALLOC_t dci_alloc[NUM_DCI_MAX] ; } DCI_PDU; /*! \brief CCCH payload */ @@ -765,8 +766,6 @@ typedef struct { uint8_t Msg3_subframe; /// Flag to indicate the eNB should generate Msg4 upon reception of SDU from RRC. This is triggered by first ULSCH reception at eNB for new user. uint8_t generate_Msg4; - /// Flag to indicate the eNB should generate the DCI for Msg4, after getting the SDU from RRC. - uint8_t generate_Msg4_dci; /// Flag to indicate that eNB is waiting for ACK that UE has received Msg3. uint8_t wait_ack_Msg4; /// UE RNTI allocated during RAR @@ -835,8 +834,8 @@ typedef struct { /// Outgoing CCCH pdu for PHY CCCH_PDU CCCH_pdu; RA_TEMPLATE RA_template[NB_RA_PROC_MAX]; - /// BCCH active flag - uint8_t bcch_active; + /// VRB map for common channels + uint8_t vrb_map[100]; /// MBSFN SubframeConfig struct MBSFN_SubframeConfig *mbsfn_SubframeConfig[8]; /// number of subframe allocation pattern available for MBSFN sync area @@ -883,9 +882,11 @@ typedef struct { /// Common cell resources COMMON_channels_t common_channels[MAX_NUM_CCs]; UE_list_t UE_list; + ///subband bitmap configuration SBMAP_CONF sbmap_conf; - + /// CCE table used to build DCI scheduling information + int CCE_table[MAX_NUM_CCs][800]; /// active flag for Other lcid // uint8_t lcid_active[NB_RB_MAX]; /// eNB stats diff --git a/openair2/LAYER2/MAC/eNB_scheduler.c b/openair2/LAYER2/MAC/eNB_scheduler.c index 329c40be05..01e32ec307 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler.c +++ b/openair2/LAYER2/MAC/eNB_scheduler.c @@ -77,11 +77,13 @@ + + + void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag, frame_t frameP, sub_frame_t subframeP) //, int calibration_flag) { { unsigned int nprb[MAX_NUM_CCs]; - unsigned int nCCE[MAX_NUM_CCs]; int mbsfn_status[MAX_NUM_CCs]; uint32_t RBalloc[MAX_NUM_CCs]; protocol_ctxt_t ctxt; @@ -106,10 +108,13 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag, for (CC_id=0; CC_idnCCE=0; + DCI_pdu[CC_id]->num_pdcch_symbols=1; nprb[CC_id]=0; RBalloc[CC_id]=0; mbsfn_status[CC_id]=0; + // clear vrb_map + memset(eNB_mac_inst[module_idP].common_channels[CC_id].vrb_map,0,100); } // refresh UE list based on UEs dropped by PHY in previous subframe @@ -186,7 +191,7 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag, for (CC_id=0; CC_idNum_common_dci = 0; DCI_pdu[CC_id]->Num_ue_spec_dci = 0; - eNB_mac_inst[module_idP].common_channels[CC_id].bcch_active = 0; + #ifdef Rel10 eNB_mac_inst[module_idP].common_channels[CC_id].mcch_active =0; @@ -194,6 +199,8 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag, eNB_mac_inst[module_idP].frame = frameP; eNB_mac_inst[module_idP].subframe = subframeP; + + } //if (subframeP%5 == 0) @@ -238,19 +245,19 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag, // Schedule ULSCH for FDD or subframeP 4 (TDD config 0,3,6) // Schedule Normal DLSCH - schedule_RA(module_idP,frameP,subframeP,2,nprb,nCCE); + schedule_RA(module_idP,frameP,subframeP,2,nprb); if (mac_xface->lte_frame_parms->frame_type == FDD) { //FDD - schedule_ulsch(module_idP,frameP,cooperation_flag,0,4,nCCE);//,calibration_flag); + schedule_ulsch(module_idP,frameP,cooperation_flag,0,4);//,calibration_flag); } else if ((mac_xface->lte_frame_parms->tdd_config == TDD) || //TDD (mac_xface->lte_frame_parms->tdd_config == 3) || (mac_xface->lte_frame_parms->tdd_config == 6)) { - //schedule_ulsch(module_idP,frameP,cooperation_flag,subframeP,4,nCCE);//,calibration_flag); + //schedule_ulsch(module_idP,frameP,cooperation_flag,subframeP,4);//,calibration_flag); } - // schedule_ue_spec(module_idP,frameP,subframeP,nprb,nCCE,mbsfn_status); + // schedule_ue_spec(module_idP,frameP,subframeP,nprb,mbsfn_status); - fill_DLSCH_dci(module_idP,frameP,subframeP,RBalloc,1,mbsfn_status); + fill_DLSCH_dci(module_idP,frameP,subframeP,RBalloc,mbsfn_status); break; @@ -262,22 +269,22 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag, switch (mac_xface->lte_frame_parms->tdd_config) { case 0: case 1: - schedule_ulsch(module_idP,frameP,cooperation_flag,subframeP,7,nCCE); - fill_DLSCH_dci(module_idP,frameP,subframeP,RBalloc,0,mbsfn_status); + schedule_ulsch(module_idP,frameP,cooperation_flag,subframeP,7); + fill_DLSCH_dci(module_idP,frameP,subframeP,RBalloc,mbsfn_status); break; case 6: - schedule_ulsch(module_idP,frameP,cooperation_flag,subframeP,8,nCCE); - fill_DLSCH_dci(module_idP,frameP,subframeP,RBalloc,0,mbsfn_status); + schedule_ulsch(module_idP,frameP,cooperation_flag,subframeP,8); + fill_DLSCH_dci(module_idP,frameP,subframeP,RBalloc,mbsfn_status); break; default: break; } } else { //FDD - schedule_ue_spec(module_idP,frameP,subframeP,nprb,nCCE,mbsfn_status); - fill_DLSCH_dci(module_idP,frameP,subframeP,RBalloc,0,mbsfn_status); - schedule_ulsch(module_idP,frameP,cooperation_flag,1,5,nCCE); + schedule_ue_spec(module_idP,frameP,subframeP,nprb,mbsfn_status); + fill_DLSCH_dci(module_idP,frameP,subframeP,RBalloc,mbsfn_status); + schedule_ulsch(module_idP,frameP,cooperation_flag,1,5); } break; @@ -287,9 +294,9 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag, // TDD, nothing // FDD, normal UL/DLSCH if (mac_xface->lte_frame_parms->frame_type == FDD) { //FDD - schedule_ue_spec(module_idP,frameP,subframeP,nprb,nCCE,mbsfn_status); - fill_DLSCH_dci(module_idP,frameP,subframeP,RBalloc,0,mbsfn_status); - schedule_ulsch(module_idP,frameP,cooperation_flag,2,6,nCCE); + schedule_ue_spec(module_idP,frameP,subframeP,nprb,mbsfn_status); + fill_DLSCH_dci(module_idP,frameP,subframeP,RBalloc,mbsfn_status); + schedule_ulsch(module_idP,frameP,cooperation_flag,2,6); } break; @@ -302,21 +309,21 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag, if (mac_xface->lte_frame_parms->frame_type == TDD) { switch (mac_xface->lte_frame_parms->tdd_config) { case 2: - schedule_ulsch(module_idP,frameP,cooperation_flag,subframeP,7,nCCE); + schedule_ulsch(module_idP,frameP,cooperation_flag,subframeP,7); // no break here! case 5: - schedule_ue_spec(module_idP,frameP,subframeP,nprb,nCCE,mbsfn_status); - fill_DLSCH_dci(module_idP,frameP,subframeP,RBalloc,0,mbsfn_status); + schedule_ue_spec(module_idP,frameP,subframeP,nprb,mbsfn_status); + fill_DLSCH_dci(module_idP,frameP,subframeP,RBalloc,mbsfn_status); break; default: break; } } else { //FDD - schedule_ue_spec(module_idP,frameP,subframeP,nprb,nCCE,mbsfn_status); - fill_DLSCH_dci(module_idP,frameP,subframeP,RBalloc,0,mbsfn_status); - schedule_ulsch(module_idP,frameP,cooperation_flag,3,7,nCCE); + schedule_ue_spec(module_idP,frameP,subframeP,nprb,mbsfn_status); + fill_DLSCH_dci(module_idP,frameP,subframeP,RBalloc,mbsfn_status); + schedule_ulsch(module_idP,frameP,cooperation_flag,3,7); } @@ -330,8 +337,8 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag, if (mac_xface->lte_frame_parms->frame_type == 1) { // TDD switch (mac_xface->lte_frame_parms->tdd_config) { case 1: - // schedule_RA(module_idP,frameP,subframeP,nprb,nCCE); - schedule_ulsch(module_idP,frameP,cooperation_flag,subframeP,8,nCCE); + // schedule_RA(module_idP,frameP,subframeP,nprb); + schedule_ulsch(module_idP,frameP,cooperation_flag,subframeP,8); // no break here! case 2: @@ -341,8 +348,8 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag, // no break here! case 5: - schedule_ue_spec(module_idP,frameP,subframeP,nprb,nCCE,mbsfn_status); - fill_DLSCH_dci(module_idP,frameP,subframeP,RBalloc,1,mbsfn_status); + schedule_ue_spec(module_idP,frameP,subframeP,nprb,mbsfn_status); + fill_DLSCH_dci(module_idP,frameP,subframeP,RBalloc,mbsfn_status); break; default: @@ -350,10 +357,10 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag, } } else { if (mac_xface->lte_frame_parms->frame_type == FDD) { //FDD - // schedule_RA(module_idP,frameP, subframeP, 0, nprb, nCCE); - // schedule_ulsch(module_idP, frameP, cooperation_flag, 4, 8, nCCE); - schedule_ue_spec(module_idP, frameP, subframeP, nprb, nCCE, mbsfn_status); - fill_DLSCH_dci(module_idP, frameP, subframeP, RBalloc, 1, mbsfn_status); + // schedule_RA(module_idP,frameP, subframeP, 0, nprb); + // schedule_ulsch(module_idP, frameP, cooperation_flag, 4, 8); + schedule_ue_spec(module_idP, frameP, subframeP, nprb, mbsfn_status); + fill_DLSCH_dci(module_idP, frameP, subframeP, RBalloc, mbsfn_status); } } @@ -365,21 +372,21 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag, // TDD Config 0,6 ULSCH for subframes 9,3 resp. // TDD normal DLSCH // FDD normal UL/DLSCH - schedule_SI(module_idP,frameP,nprb,nCCE); + schedule_SI(module_idP,frameP,subframeP,nprb); - //schedule_RA(module_idP,frameP,subframeP,5,nprb,nCCE); + //schedule_RA(module_idP,frameP,subframeP,5,nprb); if (mac_xface->lte_frame_parms->frame_type == FDD) { - schedule_RA(module_idP,frameP,subframeP,1,nprb,nCCE); - // schedule_ulsch(module_idP,frameP,cooperation_flag,5,9,nCCE); - fill_DLSCH_dci(module_idP,frameP,subframeP,RBalloc,1,mbsfn_status); + schedule_RA(module_idP,frameP,subframeP,1,nprb); + // schedule_ulsch(module_idP,frameP,cooperation_flag,5,9); + fill_DLSCH_dci(module_idP,frameP,subframeP,RBalloc,mbsfn_status); } else if ((mac_xface->lte_frame_parms->tdd_config == 0) || // TDD Config 0 (mac_xface->lte_frame_parms->tdd_config == 6)) { // TDD Config 6 - //schedule_ulsch(module_idP,cooperation_flag,subframeP,nCCE); - fill_DLSCH_dci(module_idP,frameP,subframeP,RBalloc,0,mbsfn_status); + //schedule_ulsch(module_idP,cooperation_flag,subframeP); + fill_DLSCH_dci(module_idP,frameP,subframeP,RBalloc,mbsfn_status); } else { - //schedule_ue_spec(module_idP,frameP,subframeP,nprb,nCCE,mbsfn_status); - fill_DLSCH_dci(module_idP,frameP,subframeP,RBalloc,0,mbsfn_status); + //schedule_ue_spec(module_idP,frameP,subframeP,nprb,mbsfn_status); + fill_DLSCH_dci(module_idP,frameP,subframeP,RBalloc,mbsfn_status); } break; @@ -395,36 +402,36 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag, break; case 1: - schedule_ulsch(module_idP,frameP,cooperation_flag,subframeP,2,nCCE); - // schedule_ue_spec(module_idP,frameP,subframeP,nprb,nCCE,mbsfn_status); - fill_DLSCH_dci(module_idP,frameP,subframeP,RBalloc,0,mbsfn_status); + schedule_ulsch(module_idP,frameP,cooperation_flag,subframeP,2); + // schedule_ue_spec(module_idP,frameP,subframeP,nprb,mbsfn_status); + fill_DLSCH_dci(module_idP,frameP,subframeP,RBalloc,mbsfn_status); break; case 6: - schedule_ulsch(module_idP,frameP,cooperation_flag,subframeP,3,nCCE); - // schedule_ue_spec(module_idP,frameP,subframeP,nprb,nCCE,mbsfn_status); - fill_DLSCH_dci(module_idP,frameP,subframeP,RBalloc,0,mbsfn_status); + schedule_ulsch(module_idP,frameP,cooperation_flag,subframeP,3); + // schedule_ue_spec(module_idP,frameP,subframeP,nprb,mbsfn_status); + fill_DLSCH_dci(module_idP,frameP,subframeP,RBalloc,mbsfn_status); break; case 5: - schedule_RA(module_idP,frameP,subframeP,2,nprb,nCCE); - schedule_ue_spec(module_idP,frameP,subframeP,nprb,nCCE,mbsfn_status); - fill_DLSCH_dci(module_idP,frameP,subframeP,RBalloc,1,mbsfn_status); + schedule_RA(module_idP,frameP,subframeP,2,nprb); + schedule_ue_spec(module_idP,frameP,subframeP,nprb,mbsfn_status); + fill_DLSCH_dci(module_idP,frameP,subframeP,RBalloc,mbsfn_status); break; case 3: case 4: - schedule_ue_spec(module_idP,frameP,subframeP,nprb,nCCE,mbsfn_status); - fill_DLSCH_dci(module_idP,frameP,subframeP,RBalloc,0,mbsfn_status); + schedule_ue_spec(module_idP,frameP,subframeP,nprb,mbsfn_status); + fill_DLSCH_dci(module_idP,frameP,subframeP,RBalloc,mbsfn_status); break; default: break; } } else { //FDD - // schedule_ulsch(module_idP,frameP,cooperation_flag,6,0,nCCE); - schedule_ue_spec(module_idP,frameP,subframeP,nprb,nCCE,mbsfn_status); - fill_DLSCH_dci(module_idP,frameP,subframeP,RBalloc,0,mbsfn_status); + // schedule_ulsch(module_idP,frameP,cooperation_flag,6,0); + schedule_ue_spec(module_idP,frameP,subframeP,nprb,mbsfn_status); + fill_DLSCH_dci(module_idP,frameP,subframeP,RBalloc,mbsfn_status); } break; @@ -437,23 +444,23 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag, switch (mac_xface->lte_frame_parms->tdd_config) { case 3: case 4: - schedule_RA(module_idP,frameP,subframeP,3,nprb,nCCE); // 3 = Msg3 subframeP, not - schedule_ue_spec(module_idP,frameP,subframeP,nprb,nCCE,mbsfn_status); - fill_DLSCH_dci(module_idP,frameP,subframeP,RBalloc,1,mbsfn_status); + schedule_RA(module_idP,frameP,subframeP,3,nprb); // 3 = Msg3 subframeP, not + schedule_ue_spec(module_idP,frameP,subframeP,nprb,mbsfn_status); + fill_DLSCH_dci(module_idP,frameP,subframeP,RBalloc,mbsfn_status); break; case 5: - schedule_ue_spec(module_idP,frameP,subframeP,nprb,nCCE,mbsfn_status); - fill_DLSCH_dci(module_idP,frameP,subframeP,RBalloc,0,mbsfn_status); + schedule_ue_spec(module_idP,frameP,subframeP,nprb,mbsfn_status); + fill_DLSCH_dci(module_idP,frameP,subframeP,RBalloc,mbsfn_status); break; default: break; } } else { //FDD - //schedule_ulsch(module_idP,frameP,cooperation_flag,7,1,nCCE); - schedule_ue_spec(module_idP,frameP,subframeP,nprb,nCCE,mbsfn_status); - fill_DLSCH_dci(module_idP,frameP,subframeP,RBalloc,0,mbsfn_status); + //schedule_ulsch(module_idP,frameP,cooperation_flag,7,1); + schedule_ue_spec(module_idP,frameP,subframeP,nprb,mbsfn_status); + fill_DLSCH_dci(module_idP,frameP,subframeP,RBalloc,mbsfn_status); } break; @@ -470,19 +477,19 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag, case 4: case 5: - // schedule_RA(module_idP,subframeP,nprb,nCCE); - schedule_ulsch(module_idP,frameP,cooperation_flag,subframeP,2,nCCE); - schedule_ue_spec(module_idP,frameP,subframeP,nprb,nCCE,mbsfn_status); - fill_DLSCH_dci(module_idP,frameP,subframeP,RBalloc,0,mbsfn_status); + // schedule_RA(module_idP,subframeP,nprb); + schedule_ulsch(module_idP,frameP,cooperation_flag,subframeP,2); + schedule_ue_spec(module_idP,frameP,subframeP,nprb,mbsfn_status); + fill_DLSCH_dci(module_idP,frameP,subframeP,RBalloc,mbsfn_status); break; default: break; } } else { //FDD - //schedule_ulsch(module_idP,frameP,cooperation_flag,8,2,nCCE); - schedule_ue_spec(module_idP,frameP,subframeP,nprb,nCCE,mbsfn_status); - fill_DLSCH_dci(module_idP,frameP,subframeP,RBalloc,0,mbsfn_status); + //schedule_ulsch(module_idP,frameP,cooperation_flag,8,2); + schedule_ue_spec(module_idP,frameP,subframeP,nprb,mbsfn_status); + fill_DLSCH_dci(module_idP,frameP,subframeP,RBalloc,mbsfn_status); } break; @@ -493,51 +500,50 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag, if (mac_xface->lte_frame_parms->frame_type == TDD) { switch (mac_xface->lte_frame_parms->tdd_config) { case 1: - schedule_ulsch(module_idP,frameP,cooperation_flag,subframeP,3,nCCE); - schedule_RA(module_idP,frameP,subframeP,7,nprb,nCCE); // 7 = Msg3 subframeP, not - schedule_ue_spec(module_idP,frameP,subframeP,nprb,nCCE,mbsfn_status); - fill_DLSCH_dci(module_idP,frameP,subframeP,RBalloc,1,mbsfn_status); + schedule_ulsch(module_idP,frameP,cooperation_flag,subframeP,3); + schedule_RA(module_idP,frameP,subframeP,7,nprb); // 7 = Msg3 subframeP, not + schedule_ue_spec(module_idP,frameP,subframeP,nprb,mbsfn_status); + fill_DLSCH_dci(module_idP,frameP,subframeP,RBalloc,mbsfn_status); break; case 3: case 4: - schedule_ulsch(module_idP,frameP,cooperation_flag,subframeP,3,nCCE); - schedule_ue_spec(module_idP,frameP,subframeP,nprb,nCCE,mbsfn_status); - fill_DLSCH_dci(module_idP,frameP,subframeP,RBalloc,0,mbsfn_status); + schedule_ulsch(module_idP,frameP,cooperation_flag,subframeP,3); + schedule_ue_spec(module_idP,frameP,subframeP,nprb,mbsfn_status); + fill_DLSCH_dci(module_idP,frameP,subframeP,RBalloc,mbsfn_status); break; case 6: - schedule_ulsch(module_idP,frameP,cooperation_flag,subframeP,4,nCCE); - //schedule_RA(module_idP,frameP,subframeP,nprb,nCCE); - schedule_ue_spec(module_idP,frameP,subframeP,nprb,nCCE,mbsfn_status); - fill_DLSCH_dci(module_idP,frameP,subframeP,RBalloc,0,mbsfn_status); + schedule_ulsch(module_idP,frameP,cooperation_flag,subframeP,4); + //schedule_RA(module_idP,frameP,subframeP,nprb); + schedule_ue_spec(module_idP,frameP,subframeP,nprb,mbsfn_status); + fill_DLSCH_dci(module_idP,frameP,subframeP,RBalloc,mbsfn_status); break; case 2: case 5: - //schedule_RA(module_idP,frameP,subframeP,nprb,nCCE); - schedule_ue_spec(module_idP,frameP,subframeP,nprb,nCCE,mbsfn_status); - fill_DLSCH_dci(module_idP,frameP,subframeP,RBalloc,0,mbsfn_status); + //schedule_RA(module_idP,frameP,subframeP,nprb); + schedule_ue_spec(module_idP,frameP,subframeP,nprb,mbsfn_status); + fill_DLSCH_dci(module_idP,frameP,subframeP,RBalloc,mbsfn_status); break; default: break; } } else { //FDD - // schedule_ulsch(module_idP,frameP,cooperation_flag,9,3,nCCE); - schedule_ue_spec(module_idP,frameP,subframeP,nprb,nCCE,mbsfn_status); - fill_DLSCH_dci(module_idP,frameP,subframeP,RBalloc,0,mbsfn_status); + // schedule_ulsch(module_idP,frameP,cooperation_flag,9,3); + schedule_ue_spec(module_idP,frameP,subframeP,nprb,mbsfn_status); + fill_DLSCH_dci(module_idP,frameP,subframeP,RBalloc,mbsfn_status); } break; } - for (CC_id=0; CC_idnCCE = nCCE[CC_id]; - } + for (CC_id=0;CC_idschedule_ra); for (CC_id=0; CC_idcommon_channels[CC_id].RA_template[0]; + + vrb_map = eNB->common_channels[CC_id].vrb_map; + DCI_pdu = &eNB->common_channels[CC_id].DCI_pdu; for (i=0; icommon_channels[CC_id].RA_template[i]; + + if (RA_template->RA_active == TRUE) { LOG_D(MAC,"[eNB %d][RAPROC] CC_id %d RA %d is active (generate RAR %d, generate_Msg4 %d, wait_ack_Msg4 %d, rnti %x)\n", - module_idP,CC_id,i,RA_template[i].generate_rar,RA_template[i].generate_Msg4,RA_template[i].wait_ack_Msg4, RA_template[i].rnti); + module_idP,CC_id,i,RA_template->generate_rar,RA_template->generate_Msg4,RA_template->wait_ack_Msg4, RA_template->rnti); - if (RA_template[i].generate_rar == 1) { - nprb[CC_id]= nprb[CC_id] + 3; - nCCE[CC_id] = nCCE[CC_id] + 4; - RA_template[i].Msg3_subframe=Msg3_subframe; - } else if (RA_template[i].generate_Msg4 == 1) { + if (RA_template->generate_rar == 1) { + + LOG_D(MAC,"[eNB %d] CC_id %d Frame %d, subframeP %d: Generating RAR DCI (proc %d), RA_active %d format 1A (%d,%d))\n", + module_idP, CC_id, frameP, subframeP,i, + RA_template->RA_active, + RA_template->RA_dci_fmt1, + RA_template->RA_dci_size_bits1); + + + + if (PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.frame_type == TDD) { + switch(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL) { + case 6: + ((DCI1A_1_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->type=1; + ((DCI1A_1_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->vrb_type=0; + ((DCI1A_1_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->ndi=1; + ((DCI1A_1_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->rv=0; + ((DCI1A_1_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->mcs=0; + ((DCI1A_1_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->harq_pid=0; + ((DCI1A_1_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->TPC=1; + ((DCI1A_1_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->padding=0; + ((DCI1A_1_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->rballoc = mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL,first_rb,4); + rballoc[CC_id] |= mac_xface->get_rballoc(((DCI1A_1_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->vrb_type, + ((DCI1A_1_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->rballoc); + break; + + case 25: + ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->type=1; + ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->vrb_type=0; + ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->ndi=1; + ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->rv=0; + ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->mcs=0; + ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->harq_pid=0; + ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->TPC=1; + ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->padding=0; + ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->rballoc = mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL,first_rb,4); + rballoc[CC_id] |= mac_xface->get_rballoc(((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->vrb_type, + ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->rballoc); + break; + + case 50: + ((DCI1A_10MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->type=1; + ((DCI1A_10MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->vrb_type=0; + ((DCI1A_10MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->ndi=1; + ((DCI1A_10MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->rv=0; + ((DCI1A_10MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->mcs=0; + ((DCI1A_10MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->harq_pid=0; + ((DCI1A_10MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->TPC=1; + ((DCI1A_10MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->padding=0; + ((DCI1A_10MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->rballoc = mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL,first_rb,4); + rballoc[CC_id] |= mac_xface->get_rballoc(((DCI1A_10MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->vrb_type, + ((DCI1A_10MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->rballoc); + break; + + case 100: + ((DCI1A_20MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->type=1; + ((DCI1A_20MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->vrb_type=0; + ((DCI1A_20MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->ndi=1; + ((DCI1A_20MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->rv=0; + ((DCI1A_20MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->mcs=0; + ((DCI1A_20MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->harq_pid=0; + ((DCI1A_20MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->TPC=1; + ((DCI1A_20MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->padding=0; + ((DCI1A_20MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->rballoc = mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL,first_rb,4); + rballoc[CC_id] |= mac_xface->get_rballoc(((DCI1A_20MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->vrb_type, + ((DCI1A_20MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->rballoc); + break; + + default: + ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->type=1; + ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->vrb_type=0; + ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->ndi=1; + ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->rv=0; + ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->mcs=0; + ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->harq_pid=0; + ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->TPC=1; + ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->padding=0; + ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->rballoc = mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL,first_rb,4); + rballoc[CC_id] |= mac_xface->get_rballoc(((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->vrb_type, + ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->rballoc); + break; + } + } else { + switch(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL) { + case 6: + ((DCI1A_1_5MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->type=1; + ((DCI1A_1_5MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->vrb_type=0; + ((DCI1A_1_5MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->ndi=1; + ((DCI1A_1_5MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->rv=0; + ((DCI1A_1_5MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->mcs=0; + ((DCI1A_1_5MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->harq_pid=0; + ((DCI1A_1_5MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->TPC=1; + ((DCI1A_1_5MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->padding=0; + ((DCI1A_1_5MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->rballoc = mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL,first_rb,4); + rballoc[CC_id] |= mac_xface->get_rballoc(((DCI1A_1_5MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->vrb_type, + ((DCI1A_1_5MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->rballoc); + break; + + case 25: + ((DCI1A_5MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->type=1; + ((DCI1A_5MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->vrb_type=0; + ((DCI1A_5MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->ndi=1; + ((DCI1A_5MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->rv=0; + ((DCI1A_5MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->mcs=0; + ((DCI1A_5MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->harq_pid=0; + ((DCI1A_5MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->TPC=1; + ((DCI1A_5MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->padding=0; + ((DCI1A_5MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->rballoc = mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_UL,first_rb,4); + rballoc[CC_id] |= mac_xface->get_rballoc(((DCI1A_5MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->vrb_type, + ((DCI1A_5MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->rballoc); + break; + + case 50: + ((DCI1A_10MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->type=1; + ((DCI1A_10MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->vrb_type=0; + ((DCI1A_10MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->ndi=1; + ((DCI1A_10MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->rv=0; + ((DCI1A_10MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->mcs=0; + ((DCI1A_10MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->harq_pid=0; + ((DCI1A_10MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->TPC=1; + ((DCI1A_10MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->padding=0; + ((DCI1A_10MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->rballoc = mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL,first_rb,4); + rballoc[CC_id] |= mac_xface->get_rballoc(((DCI1A_10MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->vrb_type, + ((DCI1A_10MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->rballoc); + break; + + case 100: + ((DCI1A_20MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->type=1; + ((DCI1A_20MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->vrb_type=0; + ((DCI1A_20MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->ndi=1; + ((DCI1A_20MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->rv=0; + ((DCI1A_20MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->mcs=0; + ((DCI1A_20MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->harq_pid=0; + ((DCI1A_20MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->TPC=1; + ((DCI1A_20MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->padding=0; + ((DCI1A_20MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->rballoc = mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL,first_rb,4); + rballoc[CC_id] |= mac_xface->get_rballoc(((DCI1A_20MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->vrb_type, + ((DCI1A_20MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->rballoc); + break; + + default: + break; + } + } + + if (!CCE_allocation_infeasible(module_idP,CC_id,1,subframeP,2,RA_template->RA_rnti)) { + add_common_dci(DCI_pdu, + (void*)&RA_template->RA_alloc_pdu1[0], + RA_template->RA_rnti, + RA_template->RA_dci_size_bytes1, + 2, + RA_template->RA_dci_size_bits1, + RA_template->RA_dci_fmt1, + 1); + + nprb[CC_id]= nprb[CC_id] + 3; + RA_template->Msg3_subframe=Msg3_subframe; + } + } else if (RA_template->generate_Msg4 == 1) { // check for Msg4 Message - UE_id = find_UE_id(module_idP,RA_template[i].rnti); + UE_id = find_UE_id(module_idP,RA_template->rnti); if (Is_rrc_registered == 1) { @@ -131,7 +293,7 @@ void schedule_RA(module_id_t module_idP,frame_t frameP, sub_frame_t subframeP,un if (rrc_sdu_length>0) { LOG_I(MAC,"[eNB %d][RAPROC] CC_id %d Frame %d, subframeP %d: Generating Msg4 with RRC Piggyback (RA proc %d, RNTI %x)\n", - module_idP, CC_id, frameP, subframeP,i,RA_template[i].rnti); + module_idP, CC_id, frameP, subframeP,i,RA_template->rnti); //msg("[MAC][eNB %d][RAPROC] Frame %d, subframeP %d: Received %d bytes for Msg4: \n",module_idP,frameP,subframeP,rrc_sdu_length); // for (j=0;jlte_frame_parms.N_RB_DL-4)); + + if ((vrb_map[first_rb] != 1) && (vrb_map[first_rb+3] != 1)) + break; + } + + vrb_map[first_rb] = 1; + vrb_map[first_rb+1] = 1; + vrb_map[first_rb+2] = 1; + vrb_map[first_rb+3] = 1; // Compute MCS for 3 PRB @@ -149,273 +323,405 @@ void schedule_RA(module_id_t module_idP,frame_t frameP, sub_frame_t subframeP,un switch (mac_xface->lte_frame_parms->N_RB_DL) { case 6: - ((DCI1A_1_5MHz_TDD_1_6_t*)&RA_template[i].RA_alloc_pdu2[0])->ndi=1; + ((DCI1A_1_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->ndi=1; if ((rrc_sdu_length+msg4_header) <= 22) { - ((DCI1A_1_5MHz_TDD_1_6_t*)&RA_template[i].RA_alloc_pdu2[0])->mcs=4; + ((DCI1A_1_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->mcs=4; TBsize = 22; } else if ((rrc_sdu_length+msg4_header) <= 28) { - ((DCI1A_1_5MHz_TDD_1_6_t*)&RA_template[i].RA_alloc_pdu2[0])->mcs=5; + ((DCI1A_1_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->mcs=5; TBsize = 28; } else if ((rrc_sdu_length+msg4_header) <= 32) { - ((DCI1A_1_5MHz_TDD_1_6_t*)&RA_template[i].RA_alloc_pdu2[0])->mcs=6; + ((DCI1A_1_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->mcs=6; TBsize = 32; } else if ((rrc_sdu_length+msg4_header) <= 41) { - ((DCI1A_1_5MHz_TDD_1_6_t*)&RA_template[i].RA_alloc_pdu2[0])->mcs=7; + ((DCI1A_1_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->mcs=7; TBsize = 41; } else if ((rrc_sdu_length+msg4_header) <= 49) { - ((DCI1A_1_5MHz_TDD_1_6_t*)&RA_template[i].RA_alloc_pdu2[0])->mcs=8; + ((DCI1A_1_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->mcs=8; TBsize = 49; } else if ((rrc_sdu_length+msg4_header) <= 57) { - ((DCI1A_1_5MHz_TDD_1_6_t*)&RA_template[i].RA_alloc_pdu2[0])->mcs=9; + ((DCI1A_1_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->mcs=9; TBsize = 57; } - + ((DCI1A_1_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->type=1; + ((DCI1A_1_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->vrb_type=0; + ((DCI1A_1_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->rv=0; + ((DCI1A_1_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->harq_pid=0; + ((DCI1A_1_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->TPC=1; + ((DCI1A_1_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->padding=0; + ((DCI1A_1_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->rballoc= mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL,first_rb,4); + rballoc[CC_id] |= mac_xface->get_rballoc(((DCI1A_1_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->vrb_type, + ((DCI1A_1_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->rballoc); + break; case 25: - ((DCI1A_5MHz_TDD_1_6_t*)&RA_template[i].RA_alloc_pdu2[0])->ndi=1; + ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->ndi=1; if ((rrc_sdu_length+msg4_header) <= 22) { - ((DCI1A_5MHz_TDD_1_6_t*)&RA_template[i].RA_alloc_pdu2[0])->mcs=4; + ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->mcs=4; TBsize = 22; } else if ((rrc_sdu_length+msg4_header) <= 28) { - ((DCI1A_5MHz_TDD_1_6_t*)&RA_template[i].RA_alloc_pdu2[0])->mcs=5; + ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->mcs=5; TBsize = 28; } else if ((rrc_sdu_length+msg4_header) <= 32) { - ((DCI1A_5MHz_TDD_1_6_t*)&RA_template[i].RA_alloc_pdu2[0])->mcs=6; + ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->mcs=6; TBsize = 32; } else if ((rrc_sdu_length+msg4_header) <= 41) { - ((DCI1A_5MHz_TDD_1_6_t*)&RA_template[i].RA_alloc_pdu2[0])->mcs=7; + ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->mcs=7; TBsize = 41; } else if ((rrc_sdu_length+msg4_header) <= 49) { - ((DCI1A_5MHz_TDD_1_6_t*)&RA_template[i].RA_alloc_pdu2[0])->mcs=8; + ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->mcs=8; TBsize = 49; } else if ((rrc_sdu_length+msg4_header) <= 57) { - ((DCI1A_5MHz_TDD_1_6_t*)&RA_template[i].RA_alloc_pdu2[0])->mcs=9; + ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->mcs=9; TBsize = 57; } - + + ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->type=1; + ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->vrb_type=0; + ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->rv=0; + ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->harq_pid=0; + ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->TPC=1; + ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->padding=0; + ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->rballoc= mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL,first_rb,4); + rballoc[CC_id] |= mac_xface->get_rballoc(((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->vrb_type, + ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->rballoc); break; case 50: - ((DCI1A_10MHz_TDD_1_6_t*)&RA_template[i].RA_alloc_pdu2[0])->ndi=1; + ((DCI1A_10MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->ndi=1; if ((rrc_sdu_length+msg4_header) <= 22) { - ((DCI1A_10MHz_TDD_1_6_t*)&RA_template[i].RA_alloc_pdu2[0])->mcs=4; + ((DCI1A_10MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->mcs=4; TBsize = 22; } else if ((rrc_sdu_length+msg4_header) <= 28) { - ((DCI1A_10MHz_TDD_1_6_t*)&RA_template[i].RA_alloc_pdu2[0])->mcs=5; + ((DCI1A_10MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->mcs=5; TBsize = 28; } else if ((rrc_sdu_length+msg4_header) <= 32) { - ((DCI1A_10MHz_TDD_1_6_t*)&RA_template[i].RA_alloc_pdu2[0])->mcs=6; + ((DCI1A_10MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->mcs=6; TBsize = 32; } else if ((rrc_sdu_length+msg4_header) <= 41) { - ((DCI1A_10MHz_TDD_1_6_t*)&RA_template[i].RA_alloc_pdu2[0])->mcs=7; + ((DCI1A_10MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->mcs=7; TBsize = 41; } else if ((rrc_sdu_length+msg4_header) <= 49) { - ((DCI1A_10MHz_TDD_1_6_t*)&RA_template[i].RA_alloc_pdu2[0])->mcs=8; + ((DCI1A_10MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->mcs=8; TBsize = 49; } else if ((rrc_sdu_length+msg4_header) <= 57) { - ((DCI1A_10MHz_TDD_1_6_t*)&RA_template[i].RA_alloc_pdu2[0])->mcs=9; + ((DCI1A_10MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->mcs=9; TBsize = 57; } + ((DCI1A_10MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->type=1; + ((DCI1A_10MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->vrb_type=0; + ((DCI1A_10MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->rv=0; + ((DCI1A_10MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->harq_pid=0; + ((DCI1A_10MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->TPC=1; + ((DCI1A_10MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->padding=0; + ((DCI1A_10MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->rballoc= mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL,first_rb,4); + rballoc[CC_id] |= mac_xface->get_rballoc(((DCI1A_10MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->vrb_type, + ((DCI1A_10MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->rballoc); break; case 100: - ((DCI1A_20MHz_TDD_1_6_t*)&RA_template[i].RA_alloc_pdu2[0])->ndi=1; + ((DCI1A_20MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->ndi=1; if ((rrc_sdu_length+msg4_header) <= 22) { - ((DCI1A_20MHz_TDD_1_6_t*)&RA_template[i].RA_alloc_pdu2[0])->mcs=4; + ((DCI1A_20MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->mcs=4; TBsize = 22; } else if ((rrc_sdu_length+msg4_header) <= 28) { - ((DCI1A_20MHz_TDD_1_6_t*)&RA_template[i].RA_alloc_pdu2[0])->mcs=5; + ((DCI1A_20MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->mcs=5; TBsize = 28; } else if ((rrc_sdu_length+msg4_header) <= 32) { - ((DCI1A_20MHz_TDD_1_6_t*)&RA_template[i].RA_alloc_pdu2[0])->mcs=6; + ((DCI1A_20MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->mcs=6; TBsize = 32; } else if ((rrc_sdu_length+msg4_header) <= 41) { - ((DCI1A_20MHz_TDD_1_6_t*)&RA_template[i].RA_alloc_pdu2[0])->mcs=7; + ((DCI1A_20MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->mcs=7; TBsize = 41; } else if ((rrc_sdu_length+msg4_header) <= 49) { - ((DCI1A_20MHz_TDD_1_6_t*)&RA_template[i].RA_alloc_pdu2[0])->mcs=8; + ((DCI1A_20MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->mcs=8; TBsize = 49; } else if ((rrc_sdu_length+msg4_header) <= 57) { - ((DCI1A_20MHz_TDD_1_6_t*)&RA_template[i].RA_alloc_pdu2[0])->mcs=9; + ((DCI1A_20MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->mcs=9; TBsize = 57; } + ((DCI1A_20MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->type=1; + ((DCI1A_20MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->vrb_type=0; + ((DCI1A_20MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->rv=0; + ((DCI1A_20MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->harq_pid=0; + ((DCI1A_20MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->TPC=1; + ((DCI1A_20MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->rballoc= mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL,first_rb,4); + rballoc[CC_id] |= mac_xface->get_rballoc(((DCI1A_20MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->vrb_type, + ((DCI1A_20MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->rballoc); break; } } else { // FDD DCI switch (mac_xface->lte_frame_parms->N_RB_DL) { case 6: - ((DCI1A_1_5MHz_FDD_t*)&RA_template[i].RA_alloc_pdu2[0])->ndi=1; + ((DCI1A_1_5MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->ndi=1; if ((rrc_sdu_length+msg4_header) <= 22) { - ((DCI1A_1_5MHz_FDD_t*)&RA_template[i].RA_alloc_pdu2[0])->mcs=4; + ((DCI1A_1_5MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->mcs=4; TBsize = 22; } else if ((rrc_sdu_length+msg4_header) <= 28) { - ((DCI1A_1_5MHz_FDD_t*)&RA_template[i].RA_alloc_pdu2[0])->mcs=5; + ((DCI1A_1_5MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->mcs=5; TBsize = 28; } else if ((rrc_sdu_length+msg4_header) <= 32) { - ((DCI1A_1_5MHz_FDD_t*)&RA_template[i].RA_alloc_pdu2[0])->mcs=6; + ((DCI1A_1_5MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->mcs=6; TBsize = 32; } else if ((rrc_sdu_length+msg4_header) <= 41) { - ((DCI1A_1_5MHz_FDD_t*)&RA_template[i].RA_alloc_pdu2[0])->mcs=7; + ((DCI1A_1_5MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->mcs=7; TBsize = 41; } else if ((rrc_sdu_length+msg4_header) <= 49) { - ((DCI1A_1_5MHz_FDD_t*)&RA_template[i].RA_alloc_pdu2[0])->mcs=8; + ((DCI1A_1_5MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->mcs=8; TBsize = 49; } else if ((rrc_sdu_length+msg4_header) <= 57) { - ((DCI1A_1_5MHz_FDD_t*)&RA_template[i].RA_alloc_pdu2[0])->mcs=9; + ((DCI1A_1_5MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->mcs=9; TBsize = 57; } + ((DCI1A_1_5MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->type=1; + ((DCI1A_1_5MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->vrb_type=0; + ((DCI1A_1_5MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->rv=0; + ((DCI1A_1_5MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->harq_pid=0; + ((DCI1A_1_5MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->TPC=1; + ((DCI1A_1_5MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->padding=0; + ((DCI1A_1_5MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->rballoc= mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL,first_rb,4); + rballoc[CC_id] |= mac_xface->get_rballoc(((DCI1A_1_5MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->vrb_type, + ((DCI1A_1_5MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->rballoc); break; case 25: - ((DCI1A_5MHz_FDD_t*)&RA_template[i].RA_alloc_pdu2[0])->ndi=1; + ((DCI1A_5MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->ndi=1; if ((rrc_sdu_length+msg4_header) <= 22) { - ((DCI1A_5MHz_FDD_t*)&RA_template[i].RA_alloc_pdu2[0])->mcs=4; + ((DCI1A_5MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->mcs=4; TBsize = 22; } else if ((rrc_sdu_length+msg4_header) <= 28) { - ((DCI1A_5MHz_FDD_t*)&RA_template[i].RA_alloc_pdu2[0])->mcs=5; + ((DCI1A_5MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->mcs=5; TBsize = 28; } else if ((rrc_sdu_length+msg4_header) <= 32) { - ((DCI1A_5MHz_FDD_t*)&RA_template[i].RA_alloc_pdu2[0])->mcs=6; + ((DCI1A_5MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->mcs=6; TBsize = 32; } else if ((rrc_sdu_length+msg4_header) <= 41) { - ((DCI1A_5MHz_FDD_t*)&RA_template[i].RA_alloc_pdu2[0])->mcs=7; + ((DCI1A_5MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->mcs=7; TBsize = 41; } else if ((rrc_sdu_length+msg4_header) <= 49) { - ((DCI1A_5MHz_FDD_t*)&RA_template[i].RA_alloc_pdu2[0])->mcs=8; + ((DCI1A_5MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->mcs=8; TBsize = 49; } else if ((rrc_sdu_length+msg4_header) <= 57) { - ((DCI1A_5MHz_FDD_t*)&RA_template[i].RA_alloc_pdu2[0])->mcs=9; + ((DCI1A_5MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->mcs=9; TBsize = 57; } + ((DCI1A_5MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->type=1; + ((DCI1A_5MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->vrb_type=0; + ((DCI1A_5MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->rv=0; + ((DCI1A_5MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->harq_pid=0; + ((DCI1A_5MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->TPC=1; + ((DCI1A_5MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->padding=0; + ((DCI1A_5MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->rballoc= mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL,first_rb,4); + rballoc[CC_id] |= mac_xface->get_rballoc(((DCI1A_5MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->vrb_type, + ((DCI1A_5MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->rballoc); break; case 50: - ((DCI1A_10MHz_FDD_t*)&RA_template[i].RA_alloc_pdu2[0])->ndi=1; + ((DCI1A_10MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->ndi=1; if ((rrc_sdu_length+msg4_header) <= 22) { - ((DCI1A_10MHz_FDD_t*)&RA_template[i].RA_alloc_pdu2[0])->mcs=4; + ((DCI1A_10MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->mcs=4; TBsize = 22; } else if ((rrc_sdu_length+msg4_header) <= 28) { - ((DCI1A_10MHz_FDD_t*)&RA_template[i].RA_alloc_pdu2[0])->mcs=5; + ((DCI1A_10MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->mcs=5; TBsize = 28; } else if ((rrc_sdu_length+msg4_header) <= 32) { - ((DCI1A_10MHz_FDD_t*)&RA_template[i].RA_alloc_pdu2[0])->mcs=6; + ((DCI1A_10MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->mcs=6; TBsize = 32; } else if ((rrc_sdu_length+msg4_header) <= 41) { - ((DCI1A_10MHz_FDD_t*)&RA_template[i].RA_alloc_pdu2[0])->mcs=7; + ((DCI1A_10MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->mcs=7; TBsize = 41; } else if ((rrc_sdu_length+msg4_header) <= 49) { - ((DCI1A_10MHz_FDD_t*)&RA_template[i].RA_alloc_pdu2[0])->mcs=8; + ((DCI1A_10MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->mcs=8; TBsize = 49; } else if ((rrc_sdu_length+msg4_header) <= 57) { - ((DCI1A_10MHz_FDD_t*)&RA_template[i].RA_alloc_pdu2[0])->mcs=9; + ((DCI1A_10MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->mcs=9; TBsize = 57; } + ((DCI1A_10MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->type=1; + ((DCI1A_10MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->vrb_type=0; + ((DCI1A_10MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->rv=0; + ((DCI1A_10MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->harq_pid=0; + ((DCI1A_10MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->TPC=1; + ((DCI1A_10MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->padding=0; + ((DCI1A_10MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->rballoc= mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL,first_rb,4); + rballoc[CC_id] |= mac_xface->get_rballoc(((DCI1A_10MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->vrb_type, + ((DCI1A_10MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->rballoc); break; case 100: - ((DCI1A_20MHz_FDD_t*)&RA_template[i].RA_alloc_pdu2[0])->ndi=1; + ((DCI1A_20MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->ndi=1; if ((rrc_sdu_length+msg4_header) <= 22) { - ((DCI1A_20MHz_FDD_t*)&RA_template[i].RA_alloc_pdu2[0])->mcs=4; + ((DCI1A_20MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->mcs=4; TBsize = 22; } else if ((rrc_sdu_length+msg4_header) <= 28) { - ((DCI1A_20MHz_FDD_t*)&RA_template[i].RA_alloc_pdu2[0])->mcs=5; + ((DCI1A_20MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->mcs=5; TBsize = 28; } else if ((rrc_sdu_length+msg4_header) <= 32) { - ((DCI1A_20MHz_FDD_t*)&RA_template[i].RA_alloc_pdu2[0])->mcs=6; + ((DCI1A_20MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->mcs=6; TBsize = 32; } else if ((rrc_sdu_length+msg4_header) <= 41) { - ((DCI1A_20MHz_FDD_t*)&RA_template[i].RA_alloc_pdu2[0])->mcs=7; + ((DCI1A_20MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->mcs=7; TBsize = 41; } else if ((rrc_sdu_length+msg4_header) <= 49) { - ((DCI1A_20MHz_FDD_t*)&RA_template[i].RA_alloc_pdu2[0])->mcs=8; + ((DCI1A_20MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->mcs=8; TBsize = 49; } else if ((rrc_sdu_length+msg4_header) <= 57) { - ((DCI1A_20MHz_FDD_t*)&RA_template[i].RA_alloc_pdu2[0])->mcs=9; + ((DCI1A_20MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->mcs=9; TBsize = 57; } - + ((DCI1A_20MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->type=1; + ((DCI1A_20MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->vrb_type=0; + ((DCI1A_20MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->rv=0; + ((DCI1A_20MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->harq_pid=0; + ((DCI1A_20MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->TPC=1; + ((DCI1A_20MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->padding=0; + ((DCI1A_20MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->rballoc= mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL,first_rb,4); + rballoc[CC_id] |= mac_xface->get_rballoc(((DCI1A_20MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->vrb_type, + ((DCI1A_20MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->rballoc); break; } } - RA_template[i].generate_Msg4=0; - RA_template[i].generate_Msg4_dci=1; - RA_template[i].wait_ack_Msg4=1; - RA_template[i].RA_active = FALSE; - lcid=0; - - if ((TBsize - rrc_sdu_length - msg4_header) <= 2) { - msg4_padding = TBsize - rrc_sdu_length - msg4_header; - msg4_post_padding = 0; - } else { - msg4_padding = 0; - msg4_post_padding = TBsize - rrc_sdu_length - msg4_header -1; - } - - LOG_I(MAC,"[eNB %d][RAPROC] CC_id %d Frame %d subframeP %d Msg4 : TBS %d, sdu_len %d, msg4_header %d, msg4_padding %d, msg4_post_padding %d\n", - module_idP,CC_id,frameP,subframeP,TBsize,rrc_sdu_length,msg4_header,msg4_padding,msg4_post_padding); - DevAssert( UE_id != UE_INDEX_INVALID ); // FIXME not sure how to gracefully return - offset = generate_dlsch_header((unsigned char*)eNB->UE_list.DLSCH_pdu[CC_id][0][(unsigned char)UE_id].payload[0], - 1, //num_sdus - (unsigned short*)&rrc_sdu_length, // - &lcid, // sdu_lcid - 255, // no drx - 0, // no timing advance - RA_template[i].cont_res_id, // contention res id - msg4_padding, // no padding - msg4_post_padding); - - memcpy((void*)&eNB->UE_list.DLSCH_pdu[CC_id][0][(unsigned char)UE_id].payload[0][(unsigned char)offset], - &eNB->common_channels[CC_id].CCCH_pdu.payload[0], - rrc_sdu_length); - - if (opt_enabled==1) { - trace_pdu(1, (uint8_t *)eNB->UE_list.DLSCH_pdu[CC_id][0][(unsigned char)UE_id].payload[0], - rrc_sdu_length, UE_id, 3, UE_RNTI(module_idP, UE_id), - eNB->subframe,0,0); - LOG_D(OPT,"[eNB %d][DLSCH] CC_id %d Frame %d trace pdu for rnti %x with size %d\n", - module_idP, CC_id, frameP, UE_RNTI(module_idP,UE_id), rrc_sdu_length); - } - - nprb[CC_id]= nprb[CC_id] + 3; - nCCE[CC_id] = nCCE[CC_id] + 4; - } + if (!CCE_allocation_infeasible(module_idP,CC_id,0,subframeP,2,RA_template->rnti)) { + add_ue_spec_dci(DCI_pdu, + (void*)&RA_template->RA_alloc_pdu2[0], + RA_template->rnti, + RA_template->RA_dci_size_bytes2, + 1, + RA_template->RA_dci_size_bits2, + RA_template->RA_dci_fmt2, + 0); + + RA_template->generate_Msg4=0; + RA_template->wait_ack_Msg4=1; + RA_template->RA_active = FALSE; + lcid=0; + + if ((TBsize - rrc_sdu_length - msg4_header) <= 2) { + msg4_padding = TBsize - rrc_sdu_length - msg4_header; + msg4_post_padding = 0; + } else { + msg4_padding = 0; + msg4_post_padding = TBsize - rrc_sdu_length - msg4_header -1; + } + + LOG_I(MAC,"[eNB %d][RAPROC] CC_id %d Frame %d subframeP %d Msg4 : TBS %d, sdu_len %d, msg4_header %d, msg4_padding %d, msg4_post_padding %d\n", + module_idP,CC_id,frameP,subframeP,TBsize,rrc_sdu_length,msg4_header,msg4_padding,msg4_post_padding); + DevAssert( UE_id != UE_INDEX_INVALID ); // FIXME not sure how to gracefully return + offset = generate_dlsch_header((unsigned char*)eNB->UE_list.DLSCH_pdu[CC_id][0][(unsigned char)UE_id].payload[0], + 1, //num_sdus + (unsigned short*)&rrc_sdu_length, // + &lcid, // sdu_lcid + 255, // no drx + 0, // no timing advance + RA_template->cont_res_id, // contention res id + msg4_padding, // no padding + msg4_post_padding); + + memcpy((void*)&eNB->UE_list.DLSCH_pdu[CC_id][0][(unsigned char)UE_id].payload[0][(unsigned char)offset], + &eNB->common_channels[CC_id].CCCH_pdu.payload[0], + rrc_sdu_length); + + if (opt_enabled==1) { + trace_pdu(1, (uint8_t *)eNB->UE_list.DLSCH_pdu[CC_id][0][(unsigned char)UE_id].payload[0], + rrc_sdu_length, UE_id, 3, UE_RNTI(module_idP, UE_id), + eNB->subframe,0,0); + LOG_D(OPT,"[eNB %d][DLSCH] CC_id %d Frame %d trace pdu for rnti %x with size %d\n", + module_idP, CC_id, frameP, UE_RNTI(module_idP,UE_id), rrc_sdu_length); + } + + nprb[CC_id]= nprb[CC_id] + 3; + } + } //try here } - /* - else if (eNB_mac_inst[module_idP][CC_id].RA_template[i].wait_ack_Msg4==1) { - // check HARQ status and retransmit if necessary - LOG_I(MAC,"[eNB %d][RAPROC] Frame %d, subframeP %d: Checking if Msg4 was acknowledged :\n",module_idP,frameP,subframeP); - // Get candidate harq_pid from PHY - mac_xface->get_ue_active_harq_pid(module_idP,eNB_mac_inst[module_idP][CC_id].RA_template[i].rnti,subframeP,&harq_pid,&round,0); - if (round>0) { - *nprb= (*nprb) + 3; - *nCCE = (*nCCE) + 4; - } - } - */ + } else if (RA_template->wait_ack_Msg4==1) { + // check HARQ status and retransmit if necessary + LOG_I(MAC,"[eNB %d][RAPROC] CC_id %d Frame %d, subframeP %d: Checking if Msg4 was acknowledged: \n", + module_idP,CC_id,frameP,subframeP); + // Get candidate harq_pid from PHY + mac_xface->get_ue_active_harq_pid(module_idP,CC_id,RA_template->rnti,frameP,subframeP,&harq_pid,&round,0); + + if (round>0) { + //RA_template->wait_ack_Msg4++; + // we have to schedule a retransmission + if (PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.frame_type == TDD) { + ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->ndi=1; + } else { + ((DCI1A_5MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->ndi=1; + } + + // randomize frequency allocation for RA + while (1) { + first_rb = (unsigned char)(taus()%(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL-4)); + + if ((vrb_map[first_rb] != 1) && (vrb_map[first_rb+3] != 1)) + break; + } + + vrb_map[first_rb] = 1; + vrb_map[first_rb+1] = 1; + vrb_map[first_rb+2] = 1; + vrb_map[first_rb+3] = 1; + + if (PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.frame_type == TDD) { + ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->rballoc = mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_UL,first_rb,4); + rballoc[CC_id] |= mac_xface->get_rballoc(((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->vrb_type, + ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->rballoc); + } else { + ((DCI1A_5MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->rballoc = mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_UL,first_rb,4); + rballoc[CC_id] |= mac_xface->get_rballoc(((DCI1A_5MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->vrb_type, + ((DCI1A_5MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->rballoc); + } + + if (!CCE_allocation_infeasible(module_idP,CC_id,0,subframeP,2,RA_template->rnti)) { + add_ue_spec_dci(DCI_pdu, + (void*)&RA_template->RA_alloc_pdu2[0], + RA_template->rnti, + RA_template->RA_dci_size_bytes2, + 2, + RA_template->RA_dci_size_bits2, + RA_template->RA_dci_fmt2, + 0); + } + LOG_W(MAC,"[eNB %d][RAPROC] CC_id %d Frame %d, subframeP %d: Msg4 not acknowledged, adding ue specific dci (rnti %x) for RA (Msg4 Retransmission)\n", + module_idP,CC_id,frameP,subframeP,RA_template->rnti); + } else { + /* msg4 not received + if ((round == 0) && (RA_template->wait_ack_Msg4>1){ + remove UE instance across all the layers: mac_xface->cancel_RA(); + } + */ + LOG_I(MAC,"[eNB %d][RAPROC] CC_id %d Frame %d, subframeP %d : Msg4 acknowledged\n",module_idP,CC_id,frameP,subframeP); + RA_template->wait_ack_Msg4=0; + RA_template->RA_active=FALSE; + UE_id = find_UE_id(module_idP,RA_template->rnti); + DevAssert( UE_id != -1 ); + eNB_mac_inst[module_idP].UE_list.UE_template[UE_PCCID(module_idP,UE_id)][UE_id].configured=TRUE; + + } } - } - } + } // for i=0 .. N_RA_PROC-1 + } // CC_id stop_meas(&eNB->schedule_ra); } diff --git a/openair2/LAYER2/MAC/eNB_scheduler_bch.c b/openair2/LAYER2/MAC/eNB_scheduler_bch.c index dd0890783e..a109e6fb5f 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_bch.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_bch.c @@ -72,9 +72,9 @@ void schedule_SI( module_id_t module_idP, frame_t frameP, - unsigned int* nprbP, - unsigned int* nCCEP -) + sub_frame_t subframeP, + unsigned int* nprbP) + //------------------------------------------------------------------------------ { @@ -85,12 +85,19 @@ schedule_SI( void *BCCH_alloc_pdu; int CC_id; eNB_MAC_INST *eNB = &eNB_mac_inst[module_idP]; + uint8_t *vrb_map; + int first_rb; + int rballoc[MAX_NUM_CCs]; + int sizeof1A_bytes,sizeof1A_bits; + DCI_PDU *DCI_pdu; start_meas(&eNB->schedule_si); for (CC_id=0; CC_idcommon_channels[CC_id].BCCH_alloc_pdu; + + BCCH_alloc_pdu = (void*)&eNB->common_channels[CC_id].BCCH_alloc_pdu; + DCI_pdu = (void*)&eNB->common_channels[CC_id].DCI_pdu; + vrb_map = (void*)&eNB->common_channels[CC_id].vrb_map; bcch_sdu_length = mac_rrc_data_req(module_idP, CC_id, @@ -104,7 +111,21 @@ schedule_SI( if (bcch_sdu_length > 0) { LOG_D(MAC,"[eNB %d] Frame %d : BCCH->DLSCH CC_id %d, Received %d bytes \n",module_idP,frameP,CC_id,bcch_sdu_length); + // Allocate 4 PRBs in a random location + while (1) { + first_rb = (unsigned char)(taus()%(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL-4)); + if ((vrb_map[first_rb] != 1) && + (vrb_map[first_rb+1] != 1) && + (vrb_map[first_rb+2] != 1) && + (vrb_map[first_rb+3] != 1)) + break; + } + vrb_map[first_rb] = 1; + vrb_map[first_rb+1] = 1; + vrb_map[first_rb+2] = 1; + vrb_map[first_rb+3] = 1; + // Get MCS for length of SI if (bcch_sdu_length <= (mac_xface->get_TBS_DL(0,3))) { mcs=0; } else if (bcch_sdu_length <= (mac_xface->get_TBS_DL(1,3))) { @@ -125,46 +146,153 @@ schedule_SI( mcs=8; } + + if (PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.frame_type == TDD) { switch (PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL) { case 6: ((DCI1A_1_5MHz_TDD_1_6_t*)BCCH_alloc_pdu)->mcs = mcs; + ((DCI1A_1_5MHz_TDD_1_6_t*)BCCH_alloc_pdu)->rballoc = mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL,first_rb,4); + ((DCI1A_1_5MHz_TDD_1_6_t*)BCCH_alloc_pdu)->type = 1; + ((DCI1A_1_5MHz_TDD_1_6_t*)BCCH_alloc_pdu)->vrb_type = 0; + ((DCI1A_1_5MHz_TDD_1_6_t*)BCCH_alloc_pdu)->ndi = 1; + ((DCI1A_1_5MHz_TDD_1_6_t*)BCCH_alloc_pdu)->rv = 1; + ((DCI1A_1_5MHz_TDD_1_6_t*)BCCH_alloc_pdu)->harq_pid = 0; + ((DCI1A_1_5MHz_TDD_1_6_t*)BCCH_alloc_pdu)->TPC = 1; + ((DCI1A_1_5MHz_TDD_1_6_t*)BCCH_alloc_pdu)->padding = 0; + rballoc[CC_id] |= mac_xface->get_rballoc(0,((DCI1A_1_5MHz_TDD_1_6_t*)BCCH_alloc_pdu)->rballoc); + sizeof1A_bytes = sizeof(DCI1A_1_5MHz_TDD_1_6_t); + sizeof1A_bits = sizeof_DCI1A_1_5MHz_TDD_1_6_t; break; case 25: ((DCI1A_5MHz_TDD_1_6_t*)BCCH_alloc_pdu)->mcs = mcs; - break; + ((DCI1A_5MHz_TDD_1_6_t*)BCCH_alloc_pdu)->rballoc = mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL,first_rb,4); + ((DCI1A_5MHz_TDD_1_6_t*)BCCH_alloc_pdu)->type = 1; + ((DCI1A_5MHz_TDD_1_6_t*)BCCH_alloc_pdu)->vrb_type = 0; + ((DCI1A_5MHz_TDD_1_6_t*)BCCH_alloc_pdu)->ndi = 1; + ((DCI1A_5MHz_TDD_1_6_t*)BCCH_alloc_pdu)->rv = 1; + ((DCI1A_5MHz_TDD_1_6_t*)BCCH_alloc_pdu)->harq_pid = 0; + ((DCI1A_5MHz_TDD_1_6_t*)BCCH_alloc_pdu)->TPC = 1; + ((DCI1A_5MHz_TDD_1_6_t*)BCCH_alloc_pdu)->padding = 0; + rballoc[CC_id] |= mac_xface->get_rballoc(0,((DCI1A_5MHz_TDD_1_6_t*)BCCH_alloc_pdu)->rballoc); + sizeof1A_bytes = sizeof(DCI1A_5MHz_TDD_1_6_t); + sizeof1A_bits = sizeof_DCI1A_5MHz_TDD_1_6_t; + break; case 50: ((DCI1A_10MHz_TDD_1_6_t*)BCCH_alloc_pdu)->mcs = mcs; + ((DCI1A_10MHz_TDD_1_6_t*)BCCH_alloc_pdu)->rballoc = mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL,first_rb,4); + ((DCI1A_10MHz_TDD_1_6_t*)BCCH_alloc_pdu)->type = 1; + ((DCI1A_10MHz_TDD_1_6_t*)BCCH_alloc_pdu)->vrb_type = 0; + ((DCI1A_10MHz_TDD_1_6_t*)BCCH_alloc_pdu)->ndi = 1; + ((DCI1A_10MHz_TDD_1_6_t*)BCCH_alloc_pdu)->rv = 1; + ((DCI1A_10MHz_TDD_1_6_t*)BCCH_alloc_pdu)->harq_pid = 0; + ((DCI1A_10MHz_TDD_1_6_t*)BCCH_alloc_pdu)->TPC = 1; + ((DCI1A_10MHz_TDD_1_6_t*)BCCH_alloc_pdu)->padding = 0; + rballoc[CC_id] |= mac_xface->get_rballoc(0,((DCI1A_10MHz_TDD_1_6_t*)BCCH_alloc_pdu)->rballoc); + sizeof1A_bytes = sizeof(DCI1A_10MHz_TDD_1_6_t); + sizeof1A_bits = sizeof_DCI1A_10MHz_TDD_1_6_t; break; case 100: ((DCI1A_20MHz_TDD_1_6_t*)BCCH_alloc_pdu)->mcs = mcs; - break; + ((DCI1A_20MHz_TDD_1_6_t*)BCCH_alloc_pdu)->rballoc = mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL,first_rb,4); + ((DCI1A_20MHz_TDD_1_6_t*)BCCH_alloc_pdu)->type = 1; + ((DCI1A_20MHz_TDD_1_6_t*)BCCH_alloc_pdu)->vrb_type = 0; + ((DCI1A_20MHz_TDD_1_6_t*)BCCH_alloc_pdu)->ndi = 1; + ((DCI1A_20MHz_TDD_1_6_t*)BCCH_alloc_pdu)->rv = 1; + ((DCI1A_20MHz_TDD_1_6_t*)BCCH_alloc_pdu)->harq_pid = 0; + ((DCI1A_20MHz_TDD_1_6_t*)BCCH_alloc_pdu)->TPC = 1; + ((DCI1A_20MHz_TDD_1_6_t*)BCCH_alloc_pdu)->padding = 0; + rballoc[CC_id] |= mac_xface->get_rballoc(0,((DCI1A_20MHz_TDD_1_6_t*)BCCH_alloc_pdu)->rballoc); + sizeof1A_bytes = sizeof(DCI1A_20MHz_TDD_1_6_t); + sizeof1A_bits = sizeof_DCI1A_20MHz_TDD_1_6_t; + break; } } else { switch (PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL) { case 6: ((DCI1A_1_5MHz_FDD_t*)BCCH_alloc_pdu)->mcs = mcs; + ((DCI1A_1_5MHz_FDD_t*)BCCH_alloc_pdu)->rballoc = mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL,first_rb,4); + ((DCI1A_1_5MHz_FDD_t*)BCCH_alloc_pdu)->type = 1; + ((DCI1A_1_5MHz_FDD_t*)BCCH_alloc_pdu)->vrb_type = 0; + ((DCI1A_1_5MHz_FDD_t*)BCCH_alloc_pdu)->ndi = 1; + ((DCI1A_1_5MHz_FDD_t*)BCCH_alloc_pdu)->rv = 1; + ((DCI1A_1_5MHz_FDD_t*)BCCH_alloc_pdu)->harq_pid = 0; + ((DCI1A_1_5MHz_FDD_t*)BCCH_alloc_pdu)->TPC = 1; + ((DCI1A_1_5MHz_FDD_t*)BCCH_alloc_pdu)->padding = 0; + + rballoc[CC_id] |= mac_xface->get_rballoc(0,((DCI1A_1_5MHz_FDD_t*)BCCH_alloc_pdu)->rballoc); + sizeof1A_bytes = sizeof(DCI1A_1_5MHz_FDD_t); + sizeof1A_bits = sizeof_DCI1A_1_5MHz_FDD_t; break; case 25: ((DCI1A_5MHz_FDD_t*)BCCH_alloc_pdu)->mcs = mcs; + ((DCI1A_5MHz_FDD_t*)BCCH_alloc_pdu)->rballoc = mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL,first_rb,4); + ((DCI1A_5MHz_FDD_t*)BCCH_alloc_pdu)->type = 1; + ((DCI1A_5MHz_FDD_t*)BCCH_alloc_pdu)->vrb_type = 0; + ((DCI1A_5MHz_FDD_t*)BCCH_alloc_pdu)->ndi = 1; + ((DCI1A_5MHz_FDD_t*)BCCH_alloc_pdu)->rv = 1; + ((DCI1A_5MHz_FDD_t*)BCCH_alloc_pdu)->harq_pid = 0; + ((DCI1A_5MHz_FDD_t*)BCCH_alloc_pdu)->TPC = 1; + ((DCI1A_5MHz_FDD_t*)BCCH_alloc_pdu)->padding = 0; + + rballoc[CC_id] |= mac_xface->get_rballoc(0,((DCI1A_5MHz_FDD_t*)BCCH_alloc_pdu)->rballoc); + sizeof1A_bytes = sizeof(DCI1A_5MHz_FDD_t); + sizeof1A_bits = sizeof_DCI1A_5MHz_FDD_t; break; case 50: ((DCI1A_10MHz_FDD_t*)BCCH_alloc_pdu)->mcs = mcs; + ((DCI1A_10MHz_FDD_t*)BCCH_alloc_pdu)->rballoc = mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL,first_rb,4); + ((DCI1A_10MHz_FDD_t*)BCCH_alloc_pdu)->type = 1; + ((DCI1A_10MHz_FDD_t*)BCCH_alloc_pdu)->vrb_type = 0; + ((DCI1A_10MHz_FDD_t*)BCCH_alloc_pdu)->ndi = 1; + ((DCI1A_10MHz_FDD_t*)BCCH_alloc_pdu)->rv = 1; + ((DCI1A_10MHz_FDD_t*)BCCH_alloc_pdu)->harq_pid = 0; + ((DCI1A_10MHz_FDD_t*)BCCH_alloc_pdu)->TPC = 1; + ((DCI1A_10MHz_FDD_t*)BCCH_alloc_pdu)->padding = 0; + + rballoc[CC_id] |= mac_xface->get_rballoc(0,((DCI1A_10MHz_FDD_t*)BCCH_alloc_pdu)->rballoc); + sizeof1A_bytes = sizeof(DCI1A_10MHz_FDD_t); + sizeof1A_bits = sizeof_DCI1A_10MHz_FDD_t; break; case 100: ((DCI1A_20MHz_FDD_t*)BCCH_alloc_pdu)->mcs = mcs; - break; + ((DCI1A_20MHz_FDD_t*)BCCH_alloc_pdu)->rballoc = mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL,first_rb,4); + ((DCI1A_20MHz_FDD_t*)BCCH_alloc_pdu)->type = 1; + ((DCI1A_20MHz_FDD_t*)BCCH_alloc_pdu)->vrb_type = 0; + ((DCI1A_20MHz_FDD_t*)BCCH_alloc_pdu)->ndi = 1; + ((DCI1A_20MHz_FDD_t*)BCCH_alloc_pdu)->rv = 1; + ((DCI1A_20MHz_FDD_t*)BCCH_alloc_pdu)->harq_pid = 0; + ((DCI1A_20MHz_FDD_t*)BCCH_alloc_pdu)->TPC = 1; + ((DCI1A_20MHz_FDD_t*)BCCH_alloc_pdu)->padding = 0; + + rballoc[CC_id] |= mac_xface->get_rballoc(0,((DCI1A_20MHz_FDD_t*)BCCH_alloc_pdu)->rballoc); + sizeof1A_bytes = sizeof(DCI1A_20MHz_FDD_t); + sizeof1A_bits = sizeof_DCI1A_20MHz_FDD_t; + break; } } + if (!CCE_allocation_infeasible(module_idP,CC_id,1,subframeP,2,SI_RNTI)) { + add_common_dci(DCI_pdu, + BCCH_alloc_pdu, + SI_RNTI, + sizeof1A_bytes, + 2, + sizeof1A_bits, + format1A,0); + } + else { + LOG_E(MAC,"[eNB %d] CCid %d Frame %d, subframe %d : Cannot add DCI 1A for SI\n",module_idP, CC_id,frameP,subframeP); + } + if (opt_enabled == 1) { trace_pdu(1, &eNB->common_channels[CC_id].BCCH_pdu.payload[0], @@ -194,17 +322,15 @@ schedule_SI( mac_xface->get_TBS_DL(mcs,3)); } - eNB->common_channels[CC_id].bcch_active=1; + nprbP[CC_id]=3; - nCCEP[CC_id]=4; eNB->eNB_stats[CC_id].total_num_bcch_pdu+=1; eNB->eNB_stats[CC_id].bcch_buffer=bcch_sdu_length; eNB->eNB_stats[CC_id].total_bcch_buffer+=bcch_sdu_length; eNB->eNB_stats[CC_id].bcch_mcs=mcs; } else { - eNB->common_channels[CC_id].bcch_active=0; + nprbP[CC_id]=0; - nCCEP[CC_id]=0; //LOG_D(MAC,"[eNB %d] Frame %d : BCCH not active \n",Mod_id,frame); } } diff --git a/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c b/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c index 3dea35f053..e3b1a96a55 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c @@ -423,7 +423,6 @@ schedule_ue_spec( frame_t frameP, sub_frame_t subframeP, unsigned int *nb_rb_used0, - unsigned int *nCCE_used, int* mbsfn_flag ) //------------------------------------------------------------------------------ @@ -431,7 +430,6 @@ schedule_ue_spec( uint8_t CC_id; int UE_id; - uint16_t nCCE[MAX_NUM_CCs]; int N_RBG[MAX_NUM_CCs]; unsigned char aggregation; mac_rlc_status_resp_t rlc_status; @@ -474,14 +472,12 @@ schedule_ue_spec( min_rb_unit[CC_id]=get_min_rb_unit(module_idP,CC_id); frame_parms[CC_id] = mac_xface->get_lte_frame_parms(module_idP,CC_id); total_nb_available_rb[CC_id] = frame_parms[CC_id]->N_RB_DL - nb_rb_used0[CC_id]; - nCCE[CC_id] = mac_xface->get_nCCE_max(module_idP,CC_id) - nCCE_used[CC_id]; N_RBG[CC_id] = frame_parms[CC_id]->N_RBG; // store the global enb stats: eNB->eNB_stats[CC_id].num_dlactive_UEs = UE_list->num_UEs; eNB->eNB_stats[CC_id].available_prbs = total_nb_available_rb[CC_id]; eNB->eNB_stats[CC_id].total_available_prbs += total_nb_available_rb[CC_id]; - eNB->eNB_stats[CC_id].available_ncces = nCCE[CC_id]; eNB->eNB_stats[CC_id].dlsch_bytes_tx=0; eNB->eNB_stats[CC_id].dlsch_pdus_tx=0; } @@ -523,9 +519,11 @@ schedule_ue_spec( continue_flag=1; } - if ((ue_sched_ctl->pre_nb_available_rbs[CC_id] == 0) || (nCCE[CC_id] < (1<pre_nb_available_rbs[CC_id] == 0) || // no RBs allocated + CCE_allocation_infeasible(module_idP,CC_id,0,subframeP,aggregation,rnti) + ) { LOG_D(MAC,"[eNB %d] Frame %d : no RB allocated for UE %d on CC_id %d: continue \n", - module_idP, frameP, UE_id, CC_id, nb_rb_used0[CC_id], ue_sched_ctl->pre_nb_available_rbs[CC_id], nCCE[CC_id], aggregation); + module_idP, frameP, UE_id, CC_id); //if(mac_xface->get_transmission_mode(module_idP,rnti)==5) continue_flag=1; //to next user (there might be rbs availiable for other UEs in TM5 // else @@ -587,11 +585,10 @@ schedule_ue_spec( UE_list->UE_template[CC_id][UE_id].rballoc_subband[harq_pid][j] = 0; } - LOG_D(MAC,"[eNB %d] Frame %d: Scheduling UE %d on CC_id %d (rnti %x, harq_pid %d, round %d, rb %d, cqi %d, mcs %d, ncc %d, rrc %d)\n", + LOG_D(MAC,"[eNB %d] Frame %d: Scheduling UE %d on CC_id %d (rnti %x, harq_pid %d, round %d, rb %d, cqi %d, mcs %d, rrc %d)\n", module_idP, frameP, UE_id,CC_id,rnti,harq_pid, round,nb_available_rb, eNB_UE_stats->DL_cqi[0], eNB_UE_stats->dlsch_mcs1, - nCCE[CC_id], - UE_list->eNB_UE_stats[CC_id][UE_id].rrc_status); + UE_list->eNB_UE_stats[CC_id][UE_id].rrc_status); // Note this code is for a specific DCI format @@ -641,8 +638,6 @@ schedule_ue_spec( nb_available_rb -= nb_rb; aggregation = process_ue_cqi(module_idP,UE_id); - nCCE[CC_id]-=(1<mu_mimo_mode[UE_id].pre_nb_available_rbs = nb_rb; @@ -789,7 +784,6 @@ schedule_ue_spec( UE_list->eNB_UE_stats[CC_id][UE_id].num_retransmission+=1; UE_list->eNB_UE_stats[CC_id][UE_id].rbs_used_retx=nb_rb; UE_list->eNB_UE_stats[CC_id][UE_id].total_rbs_used_retx+=nb_rb; - UE_list->eNB_UE_stats[CC_id][UE_id].ncce_used_retx=nCCE[CC_id]; UE_list->eNB_UE_stats[CC_id][UE_id].dlsch_mcs1=eNB_UE_stats->dlsch_mcs1; UE_list->eNB_UE_stats[CC_id][UE_id].dlsch_mcs2=eNB_UE_stats->dlsch_mcs1; } else { @@ -1130,8 +1124,6 @@ schedule_ue_spec( } aggregation = process_ue_cqi(module_idP,UE_id); - nCCE[CC_id]-=(1<UE_template[CC_id][UE_id].nb_rb[harq_pid] = nb_rb; add_ue_dlsch_info(module_idP, @@ -1145,7 +1137,6 @@ schedule_ue_spec( UE_list->eNB_UE_stats[CC_id][UE_id].rbs_used = nb_rb; UE_list->eNB_UE_stats[CC_id][UE_id].total_rbs_used += nb_rb; - UE_list->eNB_UE_stats[CC_id][UE_id].ncce_used = nCCE[CC_id]; UE_list->eNB_UE_stats[CC_id][UE_id].dlsch_mcs1=eNB_UE_stats->dlsch_mcs1; UE_list->eNB_UE_stats[CC_id][UE_id].dlsch_mcs2=mcs; UE_list->eNB_UE_stats[CC_id][UE_id].TBS = TBS; @@ -1498,10 +1489,9 @@ schedule_ue_spec( if (frame_parms[CC_id]->frame_type == TDD) { set_ul_DAI(module_idP,UE_id,CC_id,frameP,subframeP,frame_parms); } - } - } - //printf("MAC nCCE : %d\n",*nCCE_used); + } // UE_id loop + } // CC_id loop stop_meas(&eNB->schedule_dlsch); @@ -1512,13 +1502,12 @@ schedule_ue_spec( //------------------------------------------------------------------------------ void fill_DLSCH_dci( - module_id_t module_idP, - frame_t frameP, - sub_frame_t subframeP, - uint32_t* RBallocP, - uint8_t RA_scheduledP, - int* mbsfn_flagP -) + module_id_t module_idP, + frame_t frameP, + sub_frame_t subframeP, + uint32_t* RBallocP, + int* mbsfn_flagP + ) //------------------------------------------------------------------------------ { @@ -1526,7 +1515,7 @@ fill_DLSCH_dci( int UE_id = -1; uint8_t first_rb,nb_rb=3; rnti_t rnti; - unsigned char vrb_map[100]; + unsigned char *vrb_map; uint8_t rballoc_sub[25]; //uint8_t number_of_subbands=13; uint32_t *rballoc=RBallocP; @@ -1552,598 +1541,8 @@ fill_DLSCH_dci( if (mbsfn_flagP[CC_id]>0) continue; - DCI_pdu = &eNB->common_channels[CC_id].DCI_pdu; - BCCH_alloc_pdu=(void*)&eNB->common_channels[CC_id].BCCH_alloc_pdu; - // clear vrb_map - memset(vrb_map,0,100); - - - // SI DLSCH - // printf("BCCH check\n"); - if (eNB->common_channels[CC_id].bcch_active == 1) { - eNB->common_channels[CC_id].bcch_active = 0; - LOG_D(MAC,"[eNB %d] CC_id %d Frame %d subframeP %d: BCCH active\n", module_idP, CC_id, frameP, subframeP); - // randomize frequency allocation for SI - first_rb = 0;//10;//(unsigned char)(taus()%(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL-4)); - - /* Where is this from, should be removed!!!! - - if (PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.frame_type == TDD) { - - } - else { - BCCH_alloc_pdu_fdd.rballoc = mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL,first_rb,4); - rballoc[CC_id] |= mac_xface->get_rballoc(BCCH_alloc_pdu_fdd.vrb_type,BCCH_alloc_pdu_fdd.rballoc); - } - */ - - - vrb_map[first_rb] = 1; - vrb_map[first_rb+1] = 1; - vrb_map[first_rb+2] = 1; - vrb_map[first_rb+3] = 1; - - if (PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.frame_type == TDD) { - switch (PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL) { - case 6: - ((DCI1A_1_5MHz_TDD_1_6_t*)BCCH_alloc_pdu)->rballoc = mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL,first_rb,4); - ((DCI1A_1_5MHz_TDD_1_6_t*)BCCH_alloc_pdu)->type = 1; - ((DCI1A_1_5MHz_TDD_1_6_t*)BCCH_alloc_pdu)->vrb_type = 0; - ((DCI1A_1_5MHz_TDD_1_6_t*)BCCH_alloc_pdu)->ndi = 1; - ((DCI1A_1_5MHz_TDD_1_6_t*)BCCH_alloc_pdu)->rv = 1; - ((DCI1A_1_5MHz_TDD_1_6_t*)BCCH_alloc_pdu)->harq_pid = 0; - ((DCI1A_1_5MHz_TDD_1_6_t*)BCCH_alloc_pdu)->TPC = 1; - ((DCI1A_1_5MHz_TDD_1_6_t*)BCCH_alloc_pdu)->padding = 0; - rballoc[CC_id] |= mac_xface->get_rballoc(0,((DCI1A_1_5MHz_TDD_1_6_t*)BCCH_alloc_pdu)->rballoc); - add_common_dci(DCI_pdu, - BCCH_alloc_pdu, - SI_RNTI, - sizeof(DCI1A_1_5MHz_TDD_1_6_t), - 2, - sizeof_DCI1A_1_5MHz_TDD_1_6_t, - format1A,0); - break; - - case 25: - ((DCI1A_5MHz_TDD_1_6_t*)BCCH_alloc_pdu)->rballoc = mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL,first_rb,4); - ((DCI1A_5MHz_TDD_1_6_t*)BCCH_alloc_pdu)->type = 1; - ((DCI1A_5MHz_TDD_1_6_t*)BCCH_alloc_pdu)->vrb_type = 0; - ((DCI1A_5MHz_TDD_1_6_t*)BCCH_alloc_pdu)->ndi = 1; - ((DCI1A_5MHz_TDD_1_6_t*)BCCH_alloc_pdu)->rv = 1; - ((DCI1A_5MHz_TDD_1_6_t*)BCCH_alloc_pdu)->harq_pid = 0; - ((DCI1A_5MHz_TDD_1_6_t*)BCCH_alloc_pdu)->TPC = 1; - ((DCI1A_5MHz_TDD_1_6_t*)BCCH_alloc_pdu)->padding = 0; - rballoc[CC_id] |= mac_xface->get_rballoc(0,((DCI1A_5MHz_TDD_1_6_t*)BCCH_alloc_pdu)->rballoc); - add_common_dci(DCI_pdu, - BCCH_alloc_pdu, - SI_RNTI, - sizeof(DCI1A_5MHz_TDD_1_6_t), - 2, - sizeof_DCI1A_5MHz_TDD_1_6_t, - format1A,0); - break; - - case 50: - ((DCI1A_10MHz_TDD_1_6_t*)BCCH_alloc_pdu)->rballoc = mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL,first_rb,4); - ((DCI1A_10MHz_TDD_1_6_t*)BCCH_alloc_pdu)->type = 1; - ((DCI1A_10MHz_TDD_1_6_t*)BCCH_alloc_pdu)->vrb_type = 0; - ((DCI1A_10MHz_TDD_1_6_t*)BCCH_alloc_pdu)->ndi = 1; - ((DCI1A_10MHz_TDD_1_6_t*)BCCH_alloc_pdu)->rv = 1; - ((DCI1A_10MHz_TDD_1_6_t*)BCCH_alloc_pdu)->harq_pid = 0; - ((DCI1A_10MHz_TDD_1_6_t*)BCCH_alloc_pdu)->TPC = 1; - ((DCI1A_10MHz_TDD_1_6_t*)BCCH_alloc_pdu)->padding = 0; - rballoc[CC_id] |= mac_xface->get_rballoc(0,((DCI1A_10MHz_TDD_1_6_t*)BCCH_alloc_pdu)->rballoc); - add_common_dci(DCI_pdu, - BCCH_alloc_pdu, - SI_RNTI, - sizeof(DCI1A_10MHz_TDD_1_6_t), - 2, - sizeof_DCI1A_10MHz_TDD_1_6_t, - format1A,0); - break; - - case 100: - ((DCI1A_20MHz_TDD_1_6_t*)BCCH_alloc_pdu)->rballoc = mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL,first_rb,4); - ((DCI1A_20MHz_TDD_1_6_t*)BCCH_alloc_pdu)->type = 1; - ((DCI1A_20MHz_TDD_1_6_t*)BCCH_alloc_pdu)->vrb_type = 0; - ((DCI1A_20MHz_TDD_1_6_t*)BCCH_alloc_pdu)->ndi = 1; - ((DCI1A_20MHz_TDD_1_6_t*)BCCH_alloc_pdu)->rv = 1; - ((DCI1A_20MHz_TDD_1_6_t*)BCCH_alloc_pdu)->harq_pid = 0; - ((DCI1A_20MHz_TDD_1_6_t*)BCCH_alloc_pdu)->TPC = 1; - ((DCI1A_20MHz_TDD_1_6_t*)BCCH_alloc_pdu)->padding = 0; - rballoc[CC_id] |= mac_xface->get_rballoc(0,((DCI1A_20MHz_TDD_1_6_t*)BCCH_alloc_pdu)->rballoc); - add_common_dci(DCI_pdu, - BCCH_alloc_pdu, - SI_RNTI, - sizeof(DCI1A_20MHz_TDD_1_6_t), - 2, - sizeof_DCI1A_20MHz_TDD_1_6_t, - format1A,0); - break; - } - } else { - switch (PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL) { - case 6: - ((DCI1A_1_5MHz_FDD_t*)BCCH_alloc_pdu)->rballoc = mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL,first_rb,4); - ((DCI1A_1_5MHz_FDD_t*)BCCH_alloc_pdu)->type = 1; - ((DCI1A_1_5MHz_FDD_t*)BCCH_alloc_pdu)->vrb_type = 0; - ((DCI1A_1_5MHz_FDD_t*)BCCH_alloc_pdu)->ndi = 1; - ((DCI1A_1_5MHz_FDD_t*)BCCH_alloc_pdu)->rv = 1; - ((DCI1A_1_5MHz_FDD_t*)BCCH_alloc_pdu)->harq_pid = 0; - ((DCI1A_1_5MHz_FDD_t*)BCCH_alloc_pdu)->TPC = 1; - ((DCI1A_1_5MHz_FDD_t*)BCCH_alloc_pdu)->padding = 0; - - rballoc[CC_id] |= mac_xface->get_rballoc(0,((DCI1A_1_5MHz_FDD_t*)BCCH_alloc_pdu)->rballoc); - add_common_dci(DCI_pdu, - BCCH_alloc_pdu, - SI_RNTI, - sizeof(DCI1A_1_5MHz_FDD_t), - 2, - sizeof_DCI1A_1_5MHz_FDD_t, - format1A,0); - break; - - case 25: - ((DCI1A_5MHz_FDD_t*)BCCH_alloc_pdu)->rballoc = mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL,first_rb,4); - ((DCI1A_5MHz_FDD_t*)BCCH_alloc_pdu)->type = 1; - ((DCI1A_5MHz_FDD_t*)BCCH_alloc_pdu)->vrb_type = 0; - ((DCI1A_5MHz_FDD_t*)BCCH_alloc_pdu)->ndi = 1; - ((DCI1A_5MHz_FDD_t*)BCCH_alloc_pdu)->rv = 1; - ((DCI1A_5MHz_FDD_t*)BCCH_alloc_pdu)->harq_pid = 0; - ((DCI1A_5MHz_FDD_t*)BCCH_alloc_pdu)->TPC = 1; - ((DCI1A_5MHz_FDD_t*)BCCH_alloc_pdu)->padding = 0; - - rballoc[CC_id] |= mac_xface->get_rballoc(0,((DCI1A_5MHz_FDD_t*)BCCH_alloc_pdu)->rballoc); - add_common_dci(DCI_pdu, - BCCH_alloc_pdu, - SI_RNTI, - sizeof(DCI1A_5MHz_FDD_t), - 2, - sizeof_DCI1A_5MHz_FDD_t, - format1A,0); - break; - - case 50: - ((DCI1A_10MHz_FDD_t*)BCCH_alloc_pdu)->rballoc = mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL,first_rb,4); - ((DCI1A_10MHz_FDD_t*)BCCH_alloc_pdu)->type = 1; - ((DCI1A_10MHz_FDD_t*)BCCH_alloc_pdu)->vrb_type = 0; - ((DCI1A_10MHz_FDD_t*)BCCH_alloc_pdu)->ndi = 1; - ((DCI1A_10MHz_FDD_t*)BCCH_alloc_pdu)->rv = 1; - ((DCI1A_10MHz_FDD_t*)BCCH_alloc_pdu)->harq_pid = 0; - ((DCI1A_10MHz_FDD_t*)BCCH_alloc_pdu)->TPC = 1; - ((DCI1A_10MHz_FDD_t*)BCCH_alloc_pdu)->padding = 0; - - rballoc[CC_id] |= mac_xface->get_rballoc(0,((DCI1A_10MHz_FDD_t*)BCCH_alloc_pdu)->rballoc); - add_common_dci(DCI_pdu, - BCCH_alloc_pdu, - SI_RNTI, - sizeof(DCI1A_10MHz_FDD_t), - 2, - sizeof_DCI1A_10MHz_FDD_t, - format1A,0); - break; - - case 100: - ((DCI1A_20MHz_FDD_t*)BCCH_alloc_pdu)->rballoc = mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL,first_rb,4); - ((DCI1A_20MHz_FDD_t*)BCCH_alloc_pdu)->type = 1; - ((DCI1A_20MHz_FDD_t*)BCCH_alloc_pdu)->vrb_type = 0; - ((DCI1A_20MHz_FDD_t*)BCCH_alloc_pdu)->ndi = 1; - ((DCI1A_20MHz_FDD_t*)BCCH_alloc_pdu)->rv = 1; - ((DCI1A_20MHz_FDD_t*)BCCH_alloc_pdu)->harq_pid = 0; - ((DCI1A_20MHz_FDD_t*)BCCH_alloc_pdu)->TPC = 1; - ((DCI1A_20MHz_FDD_t*)BCCH_alloc_pdu)->padding = 0; - - rballoc[CC_id] |= mac_xface->get_rballoc(0,((DCI1A_20MHz_FDD_t*)BCCH_alloc_pdu)->rballoc); - add_common_dci(DCI_pdu, - BCCH_alloc_pdu, - SI_RNTI, - sizeof(DCI1A_20MHz_FDD_t), - 2, - sizeof_DCI1A_20MHz_FDD_t, - format1A,0); - break; - } - } - } - - if (RA_scheduledP == 1) { - for (i=0; icommon_channels[CC_id].RA_template[i]; - - if (RA_template->generate_rar == 1) { - - //FK: postponed to fill_rar - //RA_template->generate_rar = 0; - - LOG_D(MAC,"[eNB %d] CC_id %d Frame %d, subframeP %d: Generating RAR DCI (proc %d), RA_active %d format 1A (%d,%d))\n", - module_idP, CC_id, frameP, subframeP,i, - RA_template->RA_active, - RA_template->RA_dci_fmt1, - RA_template->RA_dci_size_bits1); - - // randomize frequency allocation for RA - while (1) { - first_rb = (unsigned char)(taus()%(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL-4)); - - if ((vrb_map[first_rb] != 1) && (vrb_map[first_rb+3] != 1)) - break; - } - - vrb_map[first_rb] = 1; - vrb_map[first_rb+1] = 1; - vrb_map[first_rb+2] = 1; - vrb_map[first_rb+3] = 1; - - if (PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.frame_type == TDD) { - switch(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL) { - case 6: - ((DCI1A_1_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->type=1; - ((DCI1A_1_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->vrb_type=0; - ((DCI1A_1_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->ndi=1; - ((DCI1A_1_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->rv=0; - ((DCI1A_1_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->mcs=0; - ((DCI1A_1_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->harq_pid=0; - ((DCI1A_1_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->TPC=1; - ((DCI1A_1_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->padding=0; - ((DCI1A_1_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->rballoc = mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL,first_rb,4); - rballoc[CC_id] |= mac_xface->get_rballoc(((DCI1A_1_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->vrb_type, - ((DCI1A_1_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->rballoc); - break; - - case 25: - ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->type=1; - ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->vrb_type=0; - ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->ndi=1; - ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->rv=0; - ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->mcs=0; - ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->harq_pid=0; - ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->TPC=1; - ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->padding=0; - ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->rballoc = mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL,first_rb,4); - rballoc[CC_id] |= mac_xface->get_rballoc(((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->vrb_type, - ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->rballoc); - break; - - case 50: - ((DCI1A_10MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->type=1; - ((DCI1A_10MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->vrb_type=0; - ((DCI1A_10MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->ndi=1; - ((DCI1A_10MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->rv=0; - ((DCI1A_10MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->mcs=0; - ((DCI1A_10MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->harq_pid=0; - ((DCI1A_10MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->TPC=1; - ((DCI1A_10MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->padding=0; - ((DCI1A_10MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->rballoc = mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL,first_rb,4); - rballoc[CC_id] |= mac_xface->get_rballoc(((DCI1A_10MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->vrb_type, - ((DCI1A_10MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->rballoc); - break; - - case 100: - ((DCI1A_20MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->type=1; - ((DCI1A_20MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->vrb_type=0; - ((DCI1A_20MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->ndi=1; - ((DCI1A_20MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->rv=0; - ((DCI1A_20MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->mcs=0; - ((DCI1A_20MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->harq_pid=0; - ((DCI1A_20MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->TPC=1; - ((DCI1A_20MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->padding=0; - ((DCI1A_20MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->rballoc = mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL,first_rb,4); - rballoc[CC_id] |= mac_xface->get_rballoc(((DCI1A_20MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->vrb_type, - ((DCI1A_20MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->rballoc); - break; - - default: - ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->type=1; - ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->vrb_type=0; - ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->ndi=1; - ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->rv=0; - ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->mcs=0; - ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->harq_pid=0; - ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->TPC=1; - ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->padding=0; - ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->rballoc = mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL,first_rb,4); - rballoc[CC_id] |= mac_xface->get_rballoc(((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->vrb_type, - ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu1[0])->rballoc); - break; - } - } else { - switch(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL) { - case 6: - ((DCI1A_1_5MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->type=1; - ((DCI1A_1_5MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->vrb_type=0; - ((DCI1A_1_5MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->ndi=1; - ((DCI1A_1_5MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->rv=0; - ((DCI1A_1_5MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->mcs=0; - ((DCI1A_1_5MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->harq_pid=0; - ((DCI1A_1_5MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->TPC=1; - ((DCI1A_1_5MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->padding=0; - ((DCI1A_1_5MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->rballoc = mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL,first_rb,4); - rballoc[CC_id] |= mac_xface->get_rballoc(((DCI1A_1_5MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->vrb_type, - ((DCI1A_1_5MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->rballoc); - break; - - case 25: - ((DCI1A_5MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->type=1; - ((DCI1A_5MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->vrb_type=0; - ((DCI1A_5MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->ndi=1; - ((DCI1A_5MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->rv=0; - ((DCI1A_5MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->mcs=0; - ((DCI1A_5MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->harq_pid=0; - ((DCI1A_5MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->TPC=1; - ((DCI1A_5MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->padding=0; - ((DCI1A_5MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->rballoc = mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_UL,first_rb,4); - rballoc[CC_id] |= mac_xface->get_rballoc(((DCI1A_5MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->vrb_type, - ((DCI1A_5MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->rballoc); - break; - - case 50: - ((DCI1A_10MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->type=1; - ((DCI1A_10MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->vrb_type=0; - ((DCI1A_10MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->ndi=1; - ((DCI1A_10MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->rv=0; - ((DCI1A_10MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->mcs=0; - ((DCI1A_10MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->harq_pid=0; - ((DCI1A_10MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->TPC=1; - ((DCI1A_10MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->padding=0; - ((DCI1A_10MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->rballoc = mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL,first_rb,4); - rballoc[CC_id] |= mac_xface->get_rballoc(((DCI1A_10MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->vrb_type, - ((DCI1A_10MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->rballoc); - break; - - case 100: - ((DCI1A_20MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->type=1; - ((DCI1A_20MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->vrb_type=0; - ((DCI1A_20MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->ndi=1; - ((DCI1A_20MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->rv=0; - ((DCI1A_20MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->mcs=0; - ((DCI1A_20MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->harq_pid=0; - ((DCI1A_20MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->TPC=1; - ((DCI1A_20MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->padding=0; - ((DCI1A_20MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->rballoc = mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL,first_rb,4); - rballoc[CC_id] |= mac_xface->get_rballoc(((DCI1A_20MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->vrb_type, - ((DCI1A_20MHz_FDD_t*)&RA_template->RA_alloc_pdu1[0])->rballoc); - break; - - default: - break; - } - } - - add_common_dci(DCI_pdu, - (void*)&RA_template->RA_alloc_pdu1[0], - RA_template->RA_rnti, - RA_template->RA_dci_size_bytes1, - 2, - RA_template->RA_dci_size_bits1, - RA_template->RA_dci_fmt1, - 1); - - - - LOG_D(MAC,"[eNB %d] CC_id %d Frame %d: Adding common dci for RA%d (RAR) RA_active %d\n", - module_idP,CC_id,frameP,i, RA_template->RA_active); - } - - if (RA_template->generate_Msg4_dci == 1) { - - // randomize frequency allocation for RA - while (1) { - first_rb = (unsigned char)(taus()%(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL-4)); - - if ((vrb_map[first_rb] != 1) && (vrb_map[first_rb+3] != 1)) - break; - } - - vrb_map[first_rb] = 1; - vrb_map[first_rb+1] = 1; - vrb_map[first_rb+2] = 1; - vrb_map[first_rb+3] = 1; - - if (PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.frame_type == TDD) { - switch (PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL) { - case 6: - ((DCI1A_1_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->type=1; - ((DCI1A_1_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->vrb_type=0; - ((DCI1A_1_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->rv=0; - ((DCI1A_1_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->harq_pid=0; - ((DCI1A_1_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->TPC=1; - ((DCI1A_1_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->padding=0; - ((DCI1A_1_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->rballoc= mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL,first_rb,4); - rballoc[CC_id] |= mac_xface->get_rballoc(((DCI1A_1_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->vrb_type, - ((DCI1A_1_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->rballoc); - break; - - case 25: - ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->type=1; - ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->vrb_type=0; - ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->rv=0; - ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->harq_pid=0; - ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->TPC=1; - ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->padding=0; - ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->rballoc= mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL,first_rb,4); - rballoc[CC_id] |= mac_xface->get_rballoc(((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->vrb_type, - ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->rballoc); - break; - - case 50: - ((DCI1A_10MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->type=1; - ((DCI1A_10MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->vrb_type=0; - ((DCI1A_10MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->rv=0; - ((DCI1A_10MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->harq_pid=0; - ((DCI1A_10MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->TPC=1; - ((DCI1A_10MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->padding=0; - ((DCI1A_10MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->rballoc= mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL,first_rb,4); - rballoc[CC_id] |= mac_xface->get_rballoc(((DCI1A_10MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->vrb_type, - ((DCI1A_10MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->rballoc); - break; - - case 100: - ((DCI1A_20MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->type=1; - ((DCI1A_20MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->vrb_type=0; - ((DCI1A_20MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->rv=0; - ((DCI1A_20MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->harq_pid=0; - ((DCI1A_20MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->TPC=1; - ((DCI1A_20MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->rballoc= mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL,first_rb,4); - rballoc[CC_id] |= mac_xface->get_rballoc(((DCI1A_20MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->vrb_type, - ((DCI1A_20MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->rballoc); - break; - - default: - ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->type=1; - ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->vrb_type=0; - ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->rv=0; - ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->harq_pid=0; - ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->TPC=1; - ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->padding=0; - ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->rballoc= mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL,first_rb,4); - rballoc[CC_id] |= mac_xface->get_rballoc(((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->vrb_type, - ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->rballoc); - break; - } - } else { - switch (PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL) { - - case 6: - ((DCI1A_1_5MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->type=1; - ((DCI1A_1_5MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->vrb_type=0; - ((DCI1A_1_5MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->rv=0; - ((DCI1A_1_5MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->harq_pid=0; - ((DCI1A_1_5MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->TPC=1; - ((DCI1A_1_5MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->padding=0; - ((DCI1A_1_5MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->rballoc= mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL,first_rb,4); - rballoc[CC_id] |= mac_xface->get_rballoc(((DCI1A_1_5MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->vrb_type, - ((DCI1A_1_5MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->rballoc); - break; - - case 25: - ((DCI1A_5MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->type=1; - ((DCI1A_5MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->vrb_type=0; - ((DCI1A_5MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->rv=0; - ((DCI1A_5MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->harq_pid=0; - ((DCI1A_5MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->TPC=1; - ((DCI1A_5MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->padding=0; - ((DCI1A_5MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->rballoc= mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL,first_rb,4); - rballoc[CC_id] |= mac_xface->get_rballoc(((DCI1A_5MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->vrb_type, - ((DCI1A_5MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->rballoc); - break; - - case 50: - ((DCI1A_10MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->type=1; - ((DCI1A_10MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->vrb_type=0; - ((DCI1A_10MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->rv=0; - ((DCI1A_10MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->harq_pid=0; - ((DCI1A_10MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->TPC=1; - ((DCI1A_10MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->padding=0; - ((DCI1A_10MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->rballoc= mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL,first_rb,4); - rballoc[CC_id] |= mac_xface->get_rballoc(((DCI1A_10MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->vrb_type, - ((DCI1A_10MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->rballoc); - break; - - case 100: - ((DCI1A_20MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->type=1; - ((DCI1A_20MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->vrb_type=0; - ((DCI1A_20MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->rv=0; - ((DCI1A_20MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->harq_pid=0; - ((DCI1A_20MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->TPC=1; - ((DCI1A_20MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->padding=0; - ((DCI1A_20MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->rballoc= mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL,first_rb,4); - rballoc[CC_id] |= mac_xface->get_rballoc(((DCI1A_20MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->vrb_type, - ((DCI1A_20MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->rballoc); - break; - - default: - ((DCI1A_5MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->type=1; - ((DCI1A_5MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->vrb_type=0; - ((DCI1A_5MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->rv=0; - ((DCI1A_5MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->harq_pid=0; - ((DCI1A_5MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->TPC=1; - ((DCI1A_5MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->rballoc= mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL,first_rb,4); - rballoc[CC_id] |= mac_xface->get_rballoc(((DCI1A_5MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->vrb_type, - ((DCI1A_5MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->rballoc); - break; - } - } - - add_ue_spec_dci(DCI_pdu, - (void*)&RA_template->RA_alloc_pdu2[0], - RA_template->rnti, - RA_template->RA_dci_size_bytes2, - 1, - RA_template->RA_dci_size_bits2, - RA_template->RA_dci_fmt2, - 0); - LOG_D(MAC,"[eNB %d][RAPROC] CC_id %d Frame %d, subframeP %d: Adding ue specific dci (rnti %x) for Msg4\n", - module_idP,CC_id,frameP,subframeP,RA_template->rnti); - RA_template->generate_Msg4_dci=0; - - } else if (RA_template->wait_ack_Msg4==1) { - // check HARQ status and retransmit if necessary - LOG_I(MAC,"[eNB %d][RAPROC] CC_id %d Frame %d, subframeP %d: Checking if Msg4 was acknowledged: \n", - module_idP,CC_id,frameP,subframeP); - // Get candidate harq_pid from PHY - mac_xface->get_ue_active_harq_pid(module_idP,CC_id,RA_template->rnti,frameP,subframeP,&harq_pid,&round,0); - - if (round>0) { - //RA_template->wait_ack_Msg4++; - // we have to schedule a retransmission - if (PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.frame_type == TDD) { - ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->ndi=1; - } else { - ((DCI1A_5MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->ndi=1; - } - - // randomize frequency allocation for RA - while (1) { - first_rb = (unsigned char)(taus()%(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL-4)); - - if ((vrb_map[first_rb] != 1) && (vrb_map[first_rb+3] != 1)) - break; - } - - vrb_map[first_rb] = 1; - vrb_map[first_rb+1] = 1; - vrb_map[first_rb+2] = 1; - vrb_map[first_rb+3] = 1; - - if (PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.frame_type == TDD) { - ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->rballoc = mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_UL,first_rb,4); - rballoc[CC_id] |= mac_xface->get_rballoc(((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->vrb_type, - ((DCI1A_5MHz_TDD_1_6_t*)&RA_template->RA_alloc_pdu2[0])->rballoc); - } else { - ((DCI1A_5MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->rballoc = mac_xface->computeRIV(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_UL,first_rb,4); - rballoc[CC_id] |= mac_xface->get_rballoc(((DCI1A_5MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->vrb_type, - ((DCI1A_5MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->rballoc); - } - - add_ue_spec_dci(DCI_pdu, - (void*)&RA_template->RA_alloc_pdu2[0], - RA_template->rnti, - RA_template->RA_dci_size_bytes2, - 2, - RA_template->RA_dci_size_bits2, - RA_template->RA_dci_fmt2, - 0); - LOG_W(MAC,"[eNB %d][RAPROC] CC_id %d Frame %d, subframeP %d: Msg4 not acknowledged, adding ue specific dci (rnti %x) for RA (Msg4 Retransmission)\n", - module_idP,CC_id,frameP,subframeP,RA_template->rnti); - } else { - /* msg4 not received - if ((round == 0) && (RA_template->wait_ack_Msg4>1){ - remove UE instance across all the layers: mac_xface->cancel_RA(); - } - */ - LOG_I(MAC,"[eNB %d][RAPROC] CC_id %d Frame %d, subframeP %d : Msg4 acknowledged\n",module_idP,CC_id,frameP,subframeP); - RA_template->wait_ack_Msg4=0; - RA_template->RA_active=FALSE; - UE_id = find_UE_id(module_idP,RA_template->rnti); - DevAssert( UE_id != -1 ); - eNB_mac_inst[module_idP].UE_list.UE_template[UE_PCCID(module_idP,UE_id)][UE_id].configured=TRUE; - - } - } - } - } // RA is scheduled in this subframeP - + DCI_pdu = &eNB->common_channels[CC_id].DCI_pdu; + // UE specific DCIs for (UE_id=UE_list->head; UE_id>=0; UE_id=UE_list->next[UE_id]) { diff --git a/openair2/LAYER2/MAC/eNB_scheduler_primitives.c b/openair2/LAYER2/MAC/eNB_scheduler_primitives.c index 34169d902e..da2e5f311e 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_primitives.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_primitives.c @@ -879,3 +879,208 @@ int get_nb_subband(void) return nb_sb; } + +void init_CCE_table(int module_idP,int CC_idP) +{ + memset(eNB_mac_inst[module_idP].CCE_table[CC_idP],0,800*sizeof(int)); +} + + +int get_nCCE_offset(int *CCE_table, + const unsigned char L, + const int nCCE, + const int common_dci, + const unsigned short rnti, + const unsigned char subframe) +{ + + int search_space_free,m,nb_candidates = 0,l,i; + unsigned int Yk; + /* + printf("CCE Allocation: "); + for (i=0;i=0 ; m--) { + + search_space_free = 1; + for (l=0; lget_nCCE_max(module_idP,CC_idP,DCI_pdu->num_pdcch_symbols,subframeP); + int fCCE; + int i; + int allocation_is_feasible = 1; + DCI_ALLOC_t *dci_alloc; + + LOG_I(MAC,"Allocate CCEs subframe %d, test %d\n",subframeP,test_onlyP); + init_CCE_table(module_idP,CC_idP); + DCI_pdu->nCCE=0; + + while (allocation_is_feasible == 1) { + + for (i=0;iNum_common_dci + DCI_pdu->Num_ue_spec_dci;i++) { + dci_alloc = &DCI_pdu->dci_alloc[i]; + LOG_I(MAC,"Trying to allocate DCI %d/%d (%d,%d) : rnti %x, aggreg %d nCCE %d / %d (num_pdcch_symbols %d)\n", + i,DCI_pdu->Num_common_dci+DCI_pdu->Num_ue_spec_dci, + DCI_pdu->Num_common_dci,DCI_pdu->Num_ue_spec_dci, + dci_alloc->rnti,1<L, + DCI_pdu->nCCE,nCCE_max,DCI_pdu->num_pdcch_symbols); + + if (DCI_pdu->nCCE + (1<L) > nCCE_max) { + if (DCI_pdu->num_pdcch_symbols == 3) + allocation_is_feasible = 0; + else { + DCI_pdu->num_pdcch_symbols++; + nCCE_max = mac_xface->get_nCCE_max(module_idP,CC_idP,DCI_pdu->num_pdcch_symbols,subframeP); + } + break; + } + else { // number of CCEs left can potentially hold this allocation + if ((fCCE = get_nCCE_offset(CCE_table, + 1<<(dci_alloc->L), + nCCE_max, + (iNum_common_dci) ? 1 : 0, + dci_alloc->rnti, + subframeP))>=0) {// the allocation is feasible, rnti rule passes + LOG_I(MAC,"Allocating at nCCE %d\n",fCCE); + if (test_onlyP == 0) { + DCI_pdu->nCCE += (1<L); + dci_alloc->firstCCE=fCCE; + LOG_I(MAC,"Allocate CCEs subframe %d, test %d\n",subframeP,test_onlyP); + } + } // fCCE>=0 + else { + if (DCI_pdu->num_pdcch_symbols == 3) + allocation_is_feasible = 0; + else { + DCI_pdu->num_pdcch_symbols++; + nCCE_max = mac_xface->get_nCCE_max(module_idP,CC_idP,DCI_pdu->num_pdcch_symbols,subframeP); + } + break; + } // fCCE==-1 + } // nCCE <= nCCE_max + } // for i = 0 ... num_dcis + if (allocation_is_feasible==1) + return (0); + } // allocation_is_feasible == 1 + + return(-1); + + +} + +boolean_t CCE_allocation_infeasible(int module_idP, + int CC_idP, + int common_flag, + int subframe, + int aggregation, + int rnti) { + + + DCI_PDU *DCI_pdu = &eNB_mac_inst[module_idP].common_channels[CC_idP].DCI_pdu; + DCI_ALLOC_t *dci_alloc; + int ret; + boolean_t res=FALSE; + + if (common_flag==1) { + DCI_pdu->dci_alloc[DCI_pdu->Num_common_dci + DCI_pdu->Num_ue_spec_dci].rnti = rnti; + DCI_pdu->dci_alloc[DCI_pdu->Num_common_dci + DCI_pdu->Num_ue_spec_dci].L = aggregation; + DCI_pdu->Num_common_dci++; + ret = allocate_CCEs(module_idP,CC_idP,subframe,1); + if (ret==-1) + res = TRUE; + DCI_pdu->Num_common_dci--; + } + else { + DCI_pdu->dci_alloc[DCI_pdu->Num_common_dci + DCI_pdu->Num_ue_spec_dci].rnti = rnti; + DCI_pdu->dci_alloc[DCI_pdu->Num_common_dci + DCI_pdu->Num_ue_spec_dci].L = aggregation; + DCI_pdu->Num_ue_spec_dci++; + ret = allocate_CCEs(module_idP,CC_idP,subframe,1); + if (ret==-1) + res = FALSE; + DCI_pdu->Num_ue_spec_dci--; + } +} + diff --git a/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c b/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c index 10c728f2a7..82aca12b34 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c @@ -596,12 +596,14 @@ unsigned char *parse_ulsch_header(unsigned char *mac_header, } -void schedule_ulsch(module_id_t module_idP, frame_t frameP,unsigned char cooperation_flag,sub_frame_t subframeP, unsigned char sched_subframe, - unsigned int *nCCE) //,int calibration_flag) { -{ +void schedule_ulsch(module_id_t module_idP, + frame_t frameP, + unsigned char cooperation_flag, + sub_frame_t subframeP, + unsigned char sched_subframe) { + - unsigned int nCCE_available[MAX_NUM_CCs]; uint16_t first_rb[MAX_NUM_CCs],i; int CC_id; eNB_MAC_INST *eNB=&eNB_mac_inst[module_idP]; @@ -612,7 +614,6 @@ void schedule_ulsch(module_id_t module_idP, frame_t frameP,unsigned char coopera for (CC_id=0; CC_idget_nCCE_max(module_idP,CC_id) - nCCE[CC_id]; // UE data info; // check which UE has data to transmit @@ -644,10 +645,10 @@ void schedule_ulsch(module_id_t module_idP, frame_t frameP,unsigned char coopera } - schedule_ulsch_rnti(module_idP, cooperation_flag, frameP, subframeP, sched_subframe, nCCE, nCCE_available, first_rb); + schedule_ulsch_rnti(module_idP, cooperation_flag, frameP, subframeP, sched_subframe,first_rb); #ifdef CBA - schedule_ulsch_cba_rnti(module_idP, cooperation_flag, frameP, subframeP, sched_subframe, nCCE, nCCE_available, first_rb); + schedule_ulsch_cba_rnti(module_idP, cooperation_flag, frameP, subframeP, sched_subframe, first_rb); #endif @@ -662,8 +663,6 @@ void schedule_ulsch_rnti(module_id_t module_idP, frame_t frameP, sub_frame_t subframeP, unsigned char sched_subframe, - unsigned int *nCCE, - unsigned int *nCCE_available, uint16_t *first_rb) { @@ -697,8 +696,7 @@ void schedule_ulsch_rnti(module_id_t module_idP, frameP, subframeP, first_rb, - aggregation, - nCCE); + aggregation); // LOG_I(MAC,"exiting ulsch preprocesor\n"); @@ -729,8 +727,8 @@ void schedule_ulsch_rnti(module_id_t module_idP, continue; // mac_xface->macphy_exit("[MAC][eNB] Cannot find eNB_UE_stats\n"); } - if (nCCE_available[CC_id] < (1<mode]); + LOG_T(MAC,"[eNB %d] Frame %d, subframeP %d, UE %d CC %d : got harq pid %d round %d (rnti %x,mode %s)\n", + module_idP,frameP,subframeP,UE_id,CC_id, harq_pid, round,rnti,mode_string[eNB_UE_stats->mode]); #undef EXMIMO_IOT #ifndef EXMIMO_IOT @@ -1089,9 +1087,6 @@ void schedule_ulsch_rnti(module_id_t module_idP, subframeP, S_UL_SCHEDULED); - nCCE[CC_id] = nCCE[CC_id] + (1<get_nCCE_max(module_idP,CC_id) - nCCE[CC_id]; - LOG_D(MAC,"[eNB %d] CC_id %d Frame %d, subframeP %d: Generated ULSCH DCI for next UE_id %d, format 0\n", module_idP,CC_id,frameP,subframeP,UE_id); #ifdef DEBUG dump_dci(frame_parms, &DCI_pdu->dci_alloc[DCI_pdu->Num_common_dci+DCI_pdu->Num_ue_spec_dci-1]); @@ -1104,8 +1099,7 @@ void schedule_ulsch_rnti(module_id_t module_idP, } #ifdef CBA -void schedule_ulsch_cba_rnti(module_id_t module_idP, unsigned char cooperation_flag, frame_t frameP, sub_frame_t subframeP, unsigned char sched_subframe, unsigned int *nCCE, - unsigned int *nCCE_available, uint16_t *first_rb) +void schedule_ulsch_cba_rnti(module_id_t module_idP, unsigned char cooperation_flag, frame_t frameP, sub_frame_t subframeP, unsigned char sched_subframe, uint16_t *first_rb) { eNB_MAC_INST *eNB = &eNB_mac_inst[module_idP]; @@ -1164,11 +1158,11 @@ void schedule_ulsch_cba_rnti(module_id_t module_idP, unsigned char cooperation_f // cba group template uses the exisitng UE template, and thus if a UE // is scheduled, the correspodning group can't be used for CBA // this can be fixed later - if ((total_groups > 0) && (nCCE[CC_id] == 0)) { + if (total_groups > 0) { DCI_pdu = &eNB_mac_inst[module_idP].common_channels[CC_id].DCI_pdu; for (cba_group=0; - (cba_group (1< (1<= nCCE_available[CC_id]) { - num_cba_resources[cba_group%total_groups]--; - total_cba_resources--; - // LOG_N(MAC,"reducing num cba resources to %d for group %d \n", num_cba_resources[cba_group%total_groups], cba_group%total_groups ); - cba_group++; - } - if (total_cba_resources <= 0) { return; } @@ -1280,11 +1267,11 @@ void schedule_ulsch_cba_rnti(module_id_t module_idP, unsigned char cooperation_f for (cba_group=0; cba_groupN_RB_UL) { case 6: @@ -1426,8 +1413,6 @@ void schedule_ulsch_cba_rnti(module_id_t module_idP, unsigned char cooperation_f break; } - nCCE[CC_id] = nCCE[CC_id] + (1<get_nCCE_max(module_idP,CC_id) - nCCE[CC_id]; // break;// for the moment only schedule one } } diff --git a/openair2/LAYER2/MAC/main.c b/openair2/LAYER2/MAC/main.c index 5db78a30c2..a55301d80d 100644 --- a/openair2/LAYER2/MAC/main.c +++ b/openair2/LAYER2/MAC/main.c @@ -507,7 +507,7 @@ int l2_init(LTE_DL_FRAME_PARMS *frame_parms,int eMBMS_active, char *uecap_xer,ui mac_xface->computeRIV = computeRIV; mac_xface->get_TBS_DL = get_TBS_DL; mac_xface->get_TBS_UL = get_TBS_UL; - mac_xface->get_nCCE_max = get_nCCE_max; + mac_xface->get_nCCE_max = get_nCCE_mac; mac_xface->get_nCCE_offset = get_nCCE_offset; mac_xface->get_ue_mode = get_ue_mode; mac_xface->phy_config_sib1_eNB = phy_config_sib1_eNB; diff --git a/openair2/LAYER2/MAC/pre_processor.c b/openair2/LAYER2/MAC/pre_processor.c index 5a4caf82c4..316c79c524 100644 --- a/openair2/LAYER2/MAC/pre_processor.c +++ b/openair2/LAYER2/MAC/pre_processor.c @@ -828,8 +828,7 @@ void ulsch_scheduler_pre_processor(module_id_t module_idP, int frameP, sub_frame_t subframeP, uint16_t *first_rb, - uint8_t aggregation, - uint32_t *nCCE) + uint8_t aggregation) { int16_t i; @@ -839,7 +838,6 @@ void ulsch_scheduler_pre_processor(module_id_t module_idP, int16_t total_remaining_rbs[MAX_NUM_CCs]; uint16_t max_num_ue_to_be_scheduled=0,total_ue_count=0; rnti_t rnti= -1; - uint32_t nCCE_to_be_used[MAX_NUM_CCs]; UE_list_t *UE_list = &eNB_mac_inst[module_idP].UE_list; UE_TEMPLATE *UE_template = 0; LTE_DL_FRAME_PARMS *frame_parms = 0; @@ -860,7 +858,6 @@ void ulsch_scheduler_pre_processor(module_id_t module_idP, // we need to distribute RBs among UEs // step1: reset the vars for (CC_id=0; CC_idpre_allocated_nb_rb_ul > 0) { total_ue_count+=1; } - - if((mac_xface->get_nCCE_max(module_idP,CC_id) - nCCE_to_be_used[CC_id]) > (1<get_nCCE_max(module_idP,CC_id,3,subframeP) - nCCE_to_be_used[CC_id]) > (1<dlsch_eNB[i][j] = new_eNB_dlsch(1,NUMBER_OF_HARQ_PID_MAX,frame_parms->N_RB_DL,abstraction_flag); + PHY_vars_eNB->dlsch_eNB[i][j] = new_eNB_dlsch(1,NUMBER_OF_HARQ_PID_MAX,NSOFT,frame_parms->N_RB_DL,abstraction_flag); if (!PHY_vars_eNB->dlsch_eNB[i][j]) { LOG_E(PHY,"Can't get eNB dlsch structures for UE %d \n", i); @@ -128,11 +128,11 @@ PHY_VARS_eNB* init_lte_eNB(LTE_DL_FRAME_PARMS *frame_parms, exit(-1); } - PHY_vars_eNB->dlsch_eNB_SI = new_eNB_dlsch(1,1,frame_parms->N_RB_DL, abstraction_flag); + PHY_vars_eNB->dlsch_eNB_SI = new_eNB_dlsch(1,1,NSOFT,frame_parms->N_RB_DL, abstraction_flag); LOG_D(PHY,"eNB %d : SI %p\n",eNB_id,PHY_vars_eNB->dlsch_eNB_SI); - PHY_vars_eNB->dlsch_eNB_ra = new_eNB_dlsch(1,1,frame_parms->N_RB_DL, abstraction_flag); + PHY_vars_eNB->dlsch_eNB_ra = new_eNB_dlsch(1,1,NSOFT,frame_parms->N_RB_DL, abstraction_flag); LOG_D(PHY,"eNB %d : RA %p\n",eNB_id,PHY_vars_eNB->dlsch_eNB_ra); - PHY_vars_eNB->dlsch_eNB_MCH = new_eNB_dlsch(1,NUMBER_OF_HARQ_PID_MAX,frame_parms->N_RB_DL, 0); + PHY_vars_eNB->dlsch_eNB_MCH = new_eNB_dlsch(1,NUMBER_OF_HARQ_PID_MAX,NSOFT,frame_parms->N_RB_DL, 0); LOG_D(PHY,"eNB %d : MCH %p\n",eNB_id,PHY_vars_eNB->dlsch_eNB_MCH); @@ -169,7 +169,7 @@ PHY_VARS_UE* init_lte_UE(LTE_DL_FRAME_PARMS *frame_parms, for (i=0; idlsch_ue[i][j] = new_ue_dlsch(1,NUMBER_OF_HARQ_PID_MAX,MAX_TURBO_ITERATIONS,frame_parms->N_RB_DL, abstraction_flag); + PHY_vars_UE->dlsch_ue[i][j] = new_ue_dlsch(1,NUMBER_OF_HARQ_PID_MAX,NSOFT,MAX_TURBO_ITERATIONS,frame_parms->N_RB_DL, abstraction_flag); if (!PHY_vars_UE->dlsch_ue[i][j]) { LOG_E(PHY,"Can't get ue dlsch structures\n"); @@ -187,15 +187,15 @@ PHY_VARS_UE* init_lte_UE(LTE_DL_FRAME_PARMS *frame_parms, exit(-1); } - PHY_vars_UE->dlsch_ue_SI[i] = new_ue_dlsch(1,1,MAX_TURBO_ITERATIONS,frame_parms->N_RB_DL, abstraction_flag); - PHY_vars_UE->dlsch_ue_ra[i] = new_ue_dlsch(1,1,MAX_TURBO_ITERATIONS,frame_parms->N_RB_DL, abstraction_flag); + PHY_vars_UE->dlsch_ue_SI[i] = new_ue_dlsch(1,1,NSOFT,MAX_TURBO_ITERATIONS,frame_parms->N_RB_DL, abstraction_flag); + PHY_vars_UE->dlsch_ue_ra[i] = new_ue_dlsch(1,1,NSOFT,MAX_TURBO_ITERATIONS,frame_parms->N_RB_DL, abstraction_flag); PHY_vars_UE->transmission_mode[i] = transmission_mode; } PHY_vars_UE->lte_frame_parms.pucch_config_common.deltaPUCCH_Shift = 1; - PHY_vars_UE->dlsch_ue_MCH[0] = new_ue_dlsch(1,NUMBER_OF_HARQ_PID_MAX,MAX_TURBO_ITERATIONS_MBSFN,frame_parms->N_RB_DL,0); + PHY_vars_UE->dlsch_ue_MCH[0] = new_ue_dlsch(1,NUMBER_OF_HARQ_PID_MAX,NSOFT,MAX_TURBO_ITERATIONS_MBSFN,frame_parms->N_RB_DL,0); return (PHY_vars_UE); } @@ -211,11 +211,11 @@ PHY_VARS_RN* init_lte_RN(LTE_DL_FRAME_PARMS *frame_parms, if (eMBMS_active_state == multicast_relay) { for (i=0; i < 10 ; i++) { // num SF in a frame - PHY_vars_RN->dlsch_rn_MCH[i] = new_ue_dlsch(1,1,MAX_TURBO_ITERATIONS_MBSFN,frame_parms->N_RB_DL, 0); + PHY_vars_RN->dlsch_rn_MCH[i] = new_ue_dlsch(1,1,MAX_TURBO_ITERATIONS_MBSFN,NSOFT,frame_parms->N_RB_DL, 0); LOG_D(PHY,"eNB %d : MCH[%d] %p\n",RN_id,i,PHY_vars_RN->dlsch_rn_MCH[i]); } } else { - PHY_vars_RN->dlsch_rn_MCH[0] = new_ue_dlsch(1,1,MAX_TURBO_ITERATIONS,frame_parms->N_RB_DL, 0); + PHY_vars_RN->dlsch_rn_MCH[0] = new_ue_dlsch(1,1,MAX_TURBO_ITERATIONS,NSOFT,frame_parms->N_RB_DL, 0); LOG_D(PHY,"eNB %d : MCH[0] %p\n",RN_id,PHY_vars_RN->dlsch_rn_MCH[0]); } From 6bb478aede158c3b913fd2faf731278b086e2336 Mon Sep 17 00:00:00 2001 From: kaltenbe Date: Wed, 25 Nov 2015 10:07:20 +0100 Subject: [PATCH 021/263] commiting changes from guitry --- .../ARCH/BLADERF/USERSPACE/LIB/bladerf_lib.c | 12 +++++------ targets/RT/USER/lte-softmodem.c | 20 ++++++++++++++++--- 2 files changed, 23 insertions(+), 9 deletions(-) diff --git a/targets/ARCH/BLADERF/USERSPACE/LIB/bladerf_lib.c b/targets/ARCH/BLADERF/USERSPACE/LIB/bladerf_lib.c index ce2e998fbf..b06059fdfb 100644 --- a/targets/ARCH/BLADERF/USERSPACE/LIB/bladerf_lib.c +++ b/targets/ARCH/BLADERF/USERSPACE/LIB/bladerf_lib.c @@ -254,11 +254,11 @@ int openair0_dev_init_bladerf(openair0_device *device, openair0_config_t *openai printf("[BRF] set RX sample rate to %u, %u\n", (unsigned int) openair0_cfg[card].sample_rate, actual_value); - if ((status=bladerf_set_bandwidth(brf->dev, BLADERF_MODULE_RX, (unsigned int) openair0_cfg[card].rx_bw, &actual_value)) != 0){ + if ((status=bladerf_set_bandwidth(brf->dev, BLADERF_MODULE_RX, 2*(unsigned int) openair0_cfg[card].rx_bw, &actual_value)) != 0){ fprintf(stderr,"Failed to set RX bandwidth: %s\n", bladerf_strerror(status)); brf_error(status); }else - printf("[BRF] set RX bandwidth to %u, %u\n",(unsigned int)openair0_cfg[card].rx_bw, actual_value); + printf("[BRF] set RX bandwidth to %u, %u\n",2*(unsigned int)openair0_cfg[card].rx_bw, actual_value); if ((status=bladerf_set_gain(brf->dev, BLADERF_MODULE_RX, (int) openair0_cfg[card].rx_gain[0])) != 0) { fprintf(stderr,"Failed to set RX gain: %s\n",bladerf_strerror(status)); @@ -280,11 +280,11 @@ int openair0_dev_init_bladerf(openair0_device *device, openair0_config_t *openai }else printf("[BRF] set TX sampling rate to %u \n", (unsigned int) openair0_cfg[card].sample_rate); - if ((status=bladerf_set_bandwidth(brf->dev, BLADERF_MODULE_TX,(unsigned int)openair0_cfg[card].tx_bw, NULL)) != 0){ + if ((status=bladerf_set_bandwidth(brf->dev, BLADERF_MODULE_TX,2*(unsigned int)openair0_cfg[card].tx_bw, NULL)) != 0){ fprintf(stderr, "Failed to set TX bandwidth: %s\n", bladerf_strerror(status)); brf_error(status); }else - printf("[BRF] set TX bandwidth to %u \n", (unsigned int) openair0_cfg[card].tx_bw); + printf("[BRF] set TX bandwidth to %u \n", 2*(unsigned int) openair0_cfg[card].tx_bw); if ((status=bladerf_set_gain(brf->dev, BLADERF_MODULE_TX, (int) openair0_cfg[card].tx_gain[0])) != 0) { fprintf(stderr,"Failed to set TX gain: %s\n",bladerf_strerror(status)); @@ -327,7 +327,7 @@ int openair0_dev_init_bladerf(openair0_device *device, openair0_config_t *openai printf("[BRF] RX module enabled \n"); // calibrate - /* + if ((status=bladerf_calibrate_dc(brf->dev, BLADERF_MODULE_TX)) != 0) { fprintf(stderr,"Failed to calibrate TX DC: %s\n", bladerf_strerror(status)); brf_error(status); @@ -339,7 +339,7 @@ int openair0_dev_init_bladerf(openair0_device *device, openair0_config_t *openai brf_error(status); }else printf("[BRF] RX module calibrated DC \n"); - */ + bladerf_log_set_verbosity(get_brf_log_level(openair0_cfg[card].log_level)); diff --git a/targets/RT/USER/lte-softmodem.c b/targets/RT/USER/lte-softmodem.c index 8e08cfc04c..9f104fb049 100644 --- a/targets/RT/USER/lte-softmodem.c +++ b/targets/RT/USER/lte-softmodem.c @@ -950,7 +950,7 @@ void do_OFDM_mod_rt(int subframe,PHY_VARS_eNB *phy_vars_eNB) ((short*)&phy_vars_eNB->lte_eNB_common_vars.txdata[0][aa][tx_offset])[0]= #ifdef EXMIMO ((short*)dummy_tx_b)[2*i]<<4; -#elif OAI_BLADRF +#elif OAI_BLADERF ((short*)dummy_tx_b)[2*i]; #else ((short*)dummy_tx_b)[2*i]<<4; @@ -958,7 +958,7 @@ void do_OFDM_mod_rt(int subframe,PHY_VARS_eNB *phy_vars_eNB) ((short*)&phy_vars_eNB->lte_eNB_common_vars.txdata[0][aa][tx_offset])[1]= #ifdef EXMIMO ((short*)dummy_tx_b)[2*i+1]<<4; -#elif OAI_BLADRF +#elif OAI_BLADERF ((short*)dummy_tx_b)[2*i+1]; #else ((short*)dummy_tx_b)[2*i+1]<<4; @@ -997,6 +997,7 @@ static void* eNB_thread_tx( void* param ) eNB_proc_t *proc = (eNB_proc_t*)param; FILE *tx_time_file; char tx_time_name[101]; + if (opp_enabled == 1) { snprintf(tx_time_name, 100,"/tmp/%s_tx_time_thread_sf_%d", "eNB", proc->subframe); tx_time_file = fopen(tx_time_name,"w"); @@ -1136,7 +1137,20 @@ static void* eNB_thread_tx( void* param ) } do_OFDM_mod_rt( proc->subframe_tx, PHY_vars_eNB_g[0][proc->CC_id] ); - + /* + short *txdata = (short*)&PHY_vars_eNB_g[0][proc->CC_id]->lte_eNB_common_vars.txdata[0][0][proc->subframe_tx*PHY_vars_eNB_g[0][proc->CC_id]->lte_frame_parms.samples_per_tti]; + int i; + for (i=0;i<7680*2;i+=8) { + txdata[i] = 2047; + txdata[i+1] = 0; + txdata[i+2] = 0; + txdata[i+3] = 2047; + txdata[i+4] = -2047; + txdata[i+5] = 0; + txdata[i+6] = 0; + txdata[i+7] = -2047; + } + */ if (pthread_mutex_lock(&proc->mutex_tx) != 0) { LOG_E( PHY, "[SCHED][eNB] error locking mutex for eNB TX proc %d\n", proc->subframe ); exit_fun("nothing to add"); From f7c67795ff2a441d56a3277745ce4b60592a1518 Mon Sep 17 00:00:00 2001 From: Raymond Knopp Date: Wed, 25 Nov 2015 13:49:40 -0800 Subject: [PATCH 022/263] CCE Allocation in MAC, rebase from develop. Frame number limitation to 1024 for non-real time targets (caused bad bug in oaisim). --- openair1/PHY/LTE_TRANSPORT/dci_tools.c | 48 +++++++++---------- .../PHY/LTE_TRANSPORT/dlsch_llr_computation.c | 3 +- openair1/PHY/TOOLS/lte_dfts.c | 2 +- openair1/PHY/impl_defs_top.h | 3 +- openair1/SCHED/phy_procedures_lte_eNb.c | 30 ++++++------ openair1/SCHED/phy_procedures_lte_ue.c | 29 +++++------ openair2/LAYER2/MAC/eNB_scheduler.c | 2 + openair2/LAYER2/MAC/eNB_scheduler_RA.c | 2 +- .../LAYER2/MAC/eNB_scheduler_primitives.c | 4 +- openair2/LAYER2/MAC/eNB_scheduler_ulsch.c | 31 ++++++------ 10 files changed, 79 insertions(+), 75 deletions(-) diff --git a/openair1/PHY/LTE_TRANSPORT/dci_tools.c b/openair1/PHY/LTE_TRANSPORT/dci_tools.c index a77501e14c..3456c74ee2 100644 --- a/openair1/PHY/LTE_TRANSPORT/dci_tools.c +++ b/openair1/PHY/LTE_TRANSPORT/dci_tools.c @@ -2641,23 +2641,23 @@ int generate_eNB_dlsch_params_from_dci(int frame, dlsch1_harq->subframe = subframe; } -#ifdef DEBUG_DCI + //#ifdef DEBUG_DCI if (dlsch0) { - msg("dlsch0 eNB: dlsch0 %p\n",dlsch0); - msg("dlsch0 eNB: rnti %x\n",dlsch0->rnti); - msg("dlsch0 eNB: NBRB %d\n",dlsch0_harq->nb_rb); - msg("dlsch0 eNB: rballoc %x\n",dlsch0_harq->rb_alloc[0]); - msg("dlsch0 eNB: harq_pid %d\n",harq_pid); - msg("dlsch0 eNB: round %d\n",dlsch0_harq->round); - msg("dlsch0 eNB: rvidx %d\n",dlsch0_harq->rvidx); - msg("dlsch0 eNB: TBS %d (NPRB %d)\n",dlsch0_harq->TBS,NPRB); - msg("dlsch0 eNB: mcs %d\n",dlsch0_harq->mcs); - msg("dlsch0 eNB: tpmi %d\n",tpmi); - msg("dlsch0 eNB: mimo_mode %d\n",dlsch0_harq->mimo_mode); + printf("dlsch0 eNB: dlsch0 %p\n",dlsch0); + printf("dlsch0 eNB: rnti %x\n",dlsch0->rnti); + printf("dlsch0 eNB: NBRB %d\n",dlsch0_harq->nb_rb); + printf("dlsch0 eNB: rballoc %x\n",dlsch0_harq->rb_alloc[0]); + printf("dlsch0 eNB: harq_pid %d\n",harq_pid); + printf("dlsch0 eNB: round %d\n",dlsch0_harq->round); + printf("dlsch0 eNB: rvidx %d\n",dlsch0_harq->rvidx); + printf("dlsch0 eNB: TBS %d (NPRB %d)\n",dlsch0_harq->TBS,NPRB); + printf("dlsch0 eNB: mcs %d\n",dlsch0_harq->mcs); + printf("dlsch0 eNB: tpmi %d\n",tpmi); + printf("dlsch0 eNB: mimo_mode %d\n",dlsch0_harq->mimo_mode); } -#endif + //#endif // compute DL power control parameters computeRhoA_eNB(pdsch_config_dedicated, dlsch[0],dlsch0_harq->dl_power_off); @@ -5508,21 +5508,21 @@ int generate_ue_dlsch_params_from_dci(int frame, } -#ifdef DEBUG_DCI + //#ifdef DEBUG_DCI if (dlsch[0]) { - msg("PDSCH dlsch0 UE: rnti %x\n",dlsch[0]->rnti); - msg("PDSCH dlsch0 UE: NBRB %d\n",dlsch0_harq->nb_rb); - msg("PDSCH dlsch0 UE: rballoc %x\n",dlsch0_harq->rb_alloc[0]); - msg("PDSCH dlsch0 UE: harq_pid %d\n",harq_pid); - msg("PDSCH dlsch0 UE: DCINdi %d\n",dlsch0_harq->DCINdi); - msg("PDSCH dlsch0 UE: rvidx %d\n",dlsch0_harq->rvidx); - msg("PDSCH dlsch0 UE: TBS %d\n",dlsch0_harq->TBS); - msg("PDSCH dlsch0 UE: mcs %d\n",dlsch0_harq->mcs); - msg("PDSCH dlsch0 UE: pwr_off %d\n",dlsch0_harq->dl_power_off); + printf("PDSCH dlsch0 UE: rnti %x\n",dlsch[0]->rnti); + printf("PDSCH dlsch0 UE: NBRB %d\n",dlsch0_harq->nb_rb); + printf("PDSCH dlsch0 UE: rballoc %x\n",dlsch0_harq->rb_alloc_even[0]); + printf("PDSCH dlsch0 UE: harq_pid %d\n",harq_pid); + printf("PDSCH dlsch0 UE: DCINdi %d\n",dlsch0_harq->DCINdi); + printf("PDSCH dlsch0 UE: rvidx %d\n",dlsch0_harq->rvidx); + printf("PDSCH dlsch0 UE: TBS %d\n",dlsch0_harq->TBS); + printf("PDSCH dlsch0 UE: mcs %d\n",dlsch0_harq->mcs); + printf("PDSCH dlsch0 UE: pwr_off %d\n",dlsch0_harq->dl_power_off); } -#endif + //#endif dlsch[0]->active=1; // compute DL power control parameters diff --git a/openair1/PHY/LTE_TRANSPORT/dlsch_llr_computation.c b/openair1/PHY/LTE_TRANSPORT/dlsch_llr_computation.c index a35f89b851..2051562c19 100644 --- a/openair1/PHY/LTE_TRANSPORT/dlsch_llr_computation.c +++ b/openair1/PHY/LTE_TRANSPORT/dlsch_llr_computation.c @@ -662,13 +662,14 @@ int dlsch_qpsk_llr(LTE_DL_FRAME_PARMS *frame_parms, if ((symbol_mod==0) || (symbol_mod==(4-frame_parms->Ncp))) { if (frame_parms->mode1_flag==0) - len = (nb_rb*8)- (2*pbch_pss_sss_adjust/3); + len = (nb_rb*8) - (2*pbch_pss_sss_adjust/3); else len = (nb_rb*10) - (5*pbch_pss_sss_adjust/6); } else { len = (nb_rb*12) - pbch_pss_sss_adjust; } + // printf("dlsch_qpsk_llr: symbol %d,nb_rb %d, len %d,pbch_pss_sss_adjust %d\n",symbol,nb_rb,len,pbch_pss_sss_adjust); for (i=0; idlsch_eNB[(uint8_t)UE_id][0]->harq_processes[harq_pid]->TBS/8; -#ifdef DEBUG_PHY_PROC + //#ifdef DEBUG_PHY_PROC LOG_D(PHY, "[eNB %"PRIu8"][PDSCH %"PRIx16"/%"PRIu8"] Frame %d, subframe %d: Generating PDSCH/DLSCH with input size = %"PRIu16", G %d, nb_rb %"PRIu16", mcs %"PRIu8", pmi_alloc %"PRIx16", rv %"PRIu8" (round %"PRIu8")\n", phy_vars_eNB->Mod_id, phy_vars_eNB->dlsch_eNB[(uint8_t)UE_id][0]->rnti,harq_pid, @@ -2304,7 +2304,7 @@ void phy_procedures_eNB_TX(unsigned char sched_subframe,PHY_VARS_eNB *phy_vars_e pmi2hex_2Ar1(phy_vars_eNB->dlsch_eNB[(uint8_t)UE_id][0]->harq_processes[harq_pid]->pmi_alloc), phy_vars_eNB->dlsch_eNB[(uint8_t)UE_id][0]->harq_processes[harq_pid]->rvidx, phy_vars_eNB->dlsch_eNB[(uint8_t)UE_id][0]->harq_processes[harq_pid]->round); -#endif + //#endif #if defined(MESSAGE_CHART_GENERATOR_PHY) MSC_LOG_TX_MESSAGE( MSC_PHY_ENB,MSC_PHY_UE, @@ -3324,7 +3324,7 @@ void phy_procedures_eNB_RX(const unsigned char sched_subframe,PHY_VARS_eNB *phy_ } } -#ifdef DEBUG_PHY_PROC + //#ifdef DEBUG_PHY_PROC LOG_D(PHY, "[eNB %d][PUSCH %d] Frame %d Subframe %d Demodulating PUSCH: dci_alloc %d, rar_alloc %d, round %d, first_rb %d, nb_rb %d, mcs %d, TBS %d, rv %d, cyclic_shift %d (n_DMRS2 %d, cyclicShift_common %d, nprs %d), O_ACK %d \n", phy_vars_eNB->Mod_id,harq_pid,frame,subframe, @@ -3341,7 +3341,7 @@ void phy_procedures_eNB_RX(const unsigned char sched_subframe,PHY_VARS_eNB *phy_ phy_vars_eNB->lte_frame_parms.pusch_config_common.ul_ReferenceSignalsPUSCH.cyclicShift, nPRS, phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->O_ACK); -#endif + //#endif start_meas(&phy_vars_eNB->ulsch_demodulation_stats); if (abstraction_flag==0) { @@ -3387,7 +3387,7 @@ void phy_procedures_eNB_RX(const unsigned char sched_subframe,PHY_VARS_eNB *phy_ #endif stop_meas(&phy_vars_eNB->ulsch_decoding_stats); -#ifdef DEBUG_PHY_PROC + //#ifdef DEBUG_PHY_PROC LOG_D(PHY,"[eNB %d][PUSCH %d] frame %d subframe %d RNTI %x RX power (%d,%d) RSSI (%d,%d) N0 (%d,%d) dB ACK (%d,%d), decoding iter %d\n", phy_vars_eNB->Mod_id,harq_pid, frame,subframe, @@ -3401,7 +3401,7 @@ void phy_procedures_eNB_RX(const unsigned char sched_subframe,PHY_VARS_eNB *phy_ phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->o_ACK[0], phy_vars_eNB->ulsch_eNB[i]->harq_processes[harq_pid]->o_ACK[1], ret); -#endif //DEBUG_PHY_PROC + //#endif //DEBUG_PHY_PROC /* if ((two_ues_connected==1) && (phy_vars_eNB->cooperation_flag==2)) { for (j=0;jlte_frame_parms.nb_antennas_rx;j++) { @@ -3623,11 +3623,11 @@ void phy_procedures_eNB_RX(const unsigned char sched_subframe,PHY_VARS_eNB *phy_ if (phy_vars_eNB->ulsch_eNB[i]->Msg3_flag == 1) { #ifdef OPENAIR2 -#ifdef DEBUG_PHY_PROC + //#ifdef DEBUG_PHY_PROC LOG_I(PHY,"[eNB %d][RAPROC] Frame %d Terminating ra_proc for harq %d, UE %d\n", phy_vars_eNB->Mod_id, frame,harq_pid,i); -#endif + //#endif mac_xface->rx_sdu(phy_vars_eNB->Mod_id, phy_vars_eNB->CC_id, frame,subframe, @@ -3660,9 +3660,9 @@ void phy_procedures_eNB_RX(const unsigned char sched_subframe,PHY_VARS_eNB *phy_ phy_vars_eNB->eNB_UE_stats[i].mode = PUSCH; phy_vars_eNB->ulsch_eNB[i]->Msg3_flag = 0; -#ifdef DEBUG_PHY_PROC - LOG_D(PHY,"[eNB %d][RAPROC] Frame %d : RX Subframe %d Setting UE %d mode to PUSCH\n",phy_vars_eNB->Mod_id,frame,subframe,i); -#endif //DEBUG_PHY_PROC + //#ifdef DEBUG_PHY_PROC + LOG_D(PHY,"[eNB %d][RAPROC] Frame %d : RX Subframe %d Setting UE %d mode to PUSCH\n",phy_vars_eNB->Mod_id,frame,subframe,i); + //#endif //DEBUG_PHY_PROC for (k=0; k<8; k++) { //harq_processes for (j=0; jdlsch_eNB[i][0]->Mdlharq; j++) { @@ -4517,11 +4517,11 @@ void phy_procedures_eNB_lte(unsigned char subframe,PHY_VARS_eNB **phy_vars_eNB,u phy_vars_eNB[CC_id]->proc[subframe].frame_tx++; phy_vars_eNB[CC_id]->proc[subframe].frame_rx++; - if (phy_vars_eNB[CC_id]->proc[subframe].frame_tx==MAX_FRAME_NUMBER) // defined in impl_defs_top.h - phy_vars_eNB[CC_id]->proc[subframe].frame_tx=0; + if (phy_vars_eNB[CC_id]->proc[subframe].frame_tx>=MAX_FRAME_NUMBER) // defined in impl_defs_top.h + phy_vars_eNB[CC_id]->proc[subframe].frame_tx-=MAX_FRAME_NUMBER; - if (phy_vars_eNB[CC_id]->proc[subframe].frame_rx==MAX_FRAME_NUMBER) - phy_vars_eNB[CC_id]->proc[subframe].frame_rx=0; + if (phy_vars_eNB[CC_id]->proc[subframe].frame_rx>=MAX_FRAME_NUMBER) + phy_vars_eNB[CC_id]->proc[subframe].frame_rx-=MAX_FRAME_NUMBER; } VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_LTE,0); diff --git a/openair1/SCHED/phy_procedures_lte_ue.c b/openair1/SCHED/phy_procedures_lte_ue.c index 7dcd71ce47..2abccfd900 100755 --- a/openair1/SCHED/phy_procedures_lte_ue.c +++ b/openair1/SCHED/phy_procedures_lte_ue.c @@ -2061,9 +2061,9 @@ int lte_ue_pdcch_procedures(uint8_t eNB_id,PHY_VARS_UE *phy_vars_ue,uint8_t abst #endif -#ifdef DEBUG_PHY_PROC - LOG_D(PHY,"[UE %d] Frame %d, slot %d, Mode %s: DCI found %i\n",phy_vars_ue->Mod_id,frame_rx,slot_rx,mode_string[phy_vars_ue->UE_mode[eNB_id]],dci_cnt); -#endif + //#ifdef DEBUG_PHY_PROC + LOG_I(PHY,"[UE %d] Frame %d, slot %d, Mode %s: DCI found %i\n",phy_vars_ue->Mod_id,frame_rx,slot_rx,mode_string[phy_vars_ue->UE_mode[eNB_id]],dci_cnt); + //#endif phy_vars_ue->lte_ue_pdcch_vars[eNB_id]->dci_received += dci_cnt; /* @@ -2101,10 +2101,10 @@ int lte_ue_pdcch_procedures(uint8_t eNB_id,PHY_VARS_UE *phy_vars_ue,uint8_t abst #ifdef DEBUG_PHY_PROC - if (subframe_rx == 9) { //( frame_rx % 100 == 0) { - LOG_D(PHY,"frame %d, subframe %d, rnti %x: dci %d/%d\n",frame_rx,subframe_rx,phy_vars_ue->lte_ue_pdcch_vars[eNB_id]->crnti,i,dci_cnt); + // if (subframe_rx == 9) { //( frame_rx % 100 == 0) { + LOG_I(PHY,"frame %d, subframe %d, rnti %x: dci %d/%d\n",frame_rx,subframe_rx,phy_vars_ue->lte_ue_pdcch_vars[eNB_id]->crnti,i,dci_cnt); //dump_dci(&phy_vars_ue->lte_frame_parms, &dci_alloc_rx[i]); - } + // } #endif @@ -2622,13 +2622,13 @@ int phy_procedures_UE_RX(PHY_VARS_UE *phy_vars_ue,uint8_t eNB_id,uint8_t abstrac phy_vars_ue->dlsch_ue[eNB_id][0]->active = 0; -#ifdef DEBUG_PHY_PROC + //#ifdef DEBUG_PHY_PROC LOG_D(PHY,"[UE %d][PDSCH %x/%d] Frame %d subframe %d Scheduling DLSCH decoding\n", phy_vars_ue->Mod_id, phy_vars_ue->dlsch_ue[eNB_id][0]->rnti, harq_pid, (subframe_prev == 9) ? (frame_rx-1) : frame_rx,subframe_prev); -#endif + //#endif if (phy_vars_ue->dlsch_ue[eNB_id][0]) { if (abstraction_flag == 0) { @@ -2674,17 +2674,18 @@ int phy_procedures_UE_RX(PHY_VARS_UE *phy_vars_ue,uint8_t eNB_id,uint8_t abstrac if (ret == (1+phy_vars_ue->dlsch_ue[eNB_id][0]->max_turbo_iterations)) { phy_vars_ue->dlsch_errors[eNB_id]++; -#ifdef DEBUG_PHY_PROC - LOG_D(PHY,"[UE %d][PDSCH %x/%d] Frame %d subframe %d DLSCH in error (rv %d,mcs %d)\n", + //#ifdef DEBUG_PHY_PROC + LOG_D(PHY,"[UE %d][PDSCH %x/%d] Frame %d subframe %d DLSCH in error (rv %d,mcs %d,TBS %d)\n", phy_vars_ue->Mod_id,phy_vars_ue->dlsch_ue[eNB_id][0]->rnti, harq_pid,frame_rx,subframe_prev, phy_vars_ue->dlsch_ue[eNB_id][0]->harq_processes[harq_pid]->rvidx, - phy_vars_ue->dlsch_ue[eNB_id][0]->harq_processes[harq_pid]->mcs); + phy_vars_ue->dlsch_ue[eNB_id][0]->harq_processes[harq_pid]->mcs, + phy_vars_ue->dlsch_ue[eNB_id][0]->harq_processes[harq_pid]->TBS); // if (abstraction_flag ==0 ) - //dump_dlsch(phy_vars_ue,eNB_id,subframe_prev,harq_pid); - //mac_xface->macphy_exit(""); -#endif + dump_dlsch(phy_vars_ue,eNB_id,subframe_prev,harq_pid); + mac_xface->macphy_exit(""); + //#endif } else { LOG_D(PHY,"[UE %d][PDSCH %x/%d] Frame %d subframe %d (slot_rx %d): Received DLSCH (rv %d,mcs %d,TBS %d)\n", phy_vars_ue->Mod_id,phy_vars_ue->dlsch_ue[eNB_id][0]->rnti, diff --git a/openair2/LAYER2/MAC/eNB_scheduler.c b/openair2/LAYER2/MAC/eNB_scheduler.c index 01e32ec307..01593aea2a 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler.c +++ b/openair2/LAYER2/MAC/eNB_scheduler.c @@ -540,6 +540,8 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag, } + LOG_I(MAC,"FrameP %d, subframeP %d : Scheduling CCEs\n",frameP,subframeP); + for (CC_id=0;CC_idRA_alloc_pdu2[0], RA_template->rnti, RA_template->RA_dci_size_bytes2, - 1, + 2, RA_template->RA_dci_size_bits2, RA_template->RA_dci_fmt2, 0); diff --git a/openair2/LAYER2/MAC/eNB_scheduler_primitives.c b/openair2/LAYER2/MAC/eNB_scheduler_primitives.c index da2e5f311e..bbb22f8bde 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_primitives.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_primitives.c @@ -955,7 +955,7 @@ int get_nCCE_offset(int *CCE_table, break; } - // LOG_I(PHY,"rnti %x, Yk = %d, nCCE %d (nCCE/L %d),nb_cand %d\n",rnti,Yk,nCCE,nCCE/L,nb_candidates); + LOG_I(MAC,"rnti %x, Yk = %d, nCCE %d (nCCE/L %d),nb_cand %d\n",rnti,Yk,nCCE,nCCE/L,nb_candidates); for (m = 0 ; m < nb_candidates ; m++) { search_space_free = 1; @@ -994,7 +994,7 @@ int allocate_CCEs(int module_idP, int allocation_is_feasible = 1; DCI_ALLOC_t *dci_alloc; - LOG_I(MAC,"Allocate CCEs subframe %d, test %d\n",subframeP,test_onlyP); + LOG_I(MAC,"Allocate CCEs subframe %d, test %d : (common %d,uspec %d)\n",subframeP,test_onlyP,DCI_pdu->Num_common_dci,DCI_pdu->Num_ue_spec_dci); init_CCE_table(module_idP,CC_idP); DCI_pdu->nCCE=0; diff --git a/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c b/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c index 82aca12b34..30cc27fbfd 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c @@ -223,7 +223,7 @@ void rx_sdu( payload_ptr[0],payload_ptr[1],payload_ptr[2],payload_ptr[3],payload_ptr[4], payload_ptr[5], rntiP); for (ii=0; iicommon_channels[CC_idP].RA_template[ii].rnti, rntiP, eNB->common_channels[CC_idP].RA_template[ii].RA_active); @@ -236,7 +236,7 @@ void rx_sdu( if (UE_id < 0) { memcpy(&eNB->common_channels[CC_idP].RA_template[ii].cont_res_id[0],payload_ptr,6); LOG_I(MAC,"[eNB %d][RAPROC] CC_id %d Frame %d CCCH: Received Msg3: length %d, offset %d\n", - enb_mod_idP,CC_idP,frameP,rx_lengths[ii],payload_ptr-sduP); + enb_mod_idP,CC_idP,frameP,rx_lengths[i],payload_ptr-sduP); if ((UE_id=add_new_ue(enb_mod_idP,CC_idP,eNB->common_channels[CC_idP].RA_template[ii].rnti,harq_pidP)) == -1 ) { mac_xface->macphy_exit("[MAC][eNB] Max user count reached\n"); @@ -246,7 +246,7 @@ void rx_sdu( enb_mod_idP,CC_idP,frameP,eNB->common_channels[CC_idP].RA_template[ii].rnti,UE_id); } else { LOG_I(MAC,"[eNB %d][RAPROC] CC_id %d Frame %d CCCH: Received Msg3 from already registered UE %d: length %d, offset %d\n", - enb_mod_idP,CC_idP,frameP,UE_id,rx_lengths[ii],payload_ptr-sduP); + enb_mod_idP,CC_idP,frameP,UE_id,rx_lengths[i],payload_ptr-sduP); // kill RA procedure } @@ -258,7 +258,7 @@ void rx_sdu( rntiP, CCCH, (uint8_t*)payload_ptr, - rx_lengths[ii], + rx_lengths[i], ENB_FLAG_YES, enb_mod_idP, 0); @@ -297,17 +297,17 @@ void rx_sdu( enb_mod_idP,CC_idP,frameP, rx_lengths[i], UE_id, rx_lcids[i]); mac_rlc_data_ind( - enb_mod_idP, - rntiP, - enb_mod_idP, - frameP, - ENB_FLAG_YES, - MBMS_FLAG_NO, - rx_lcids[i], - (char *)payload_ptr, - rx_lengths[i], - 1, - NULL);//(unsigned int*)crc_status); + enb_mod_idP, + rntiP, + enb_mod_idP, + frameP, + ENB_FLAG_YES, + MBMS_FLAG_NO, + rx_lcids[i], + (char *)payload_ptr, + rx_lengths[i], + 1, + NULL);//(unsigned int*)crc_status); UE_list->eNB_UE_stats[CC_idP][UE_id].num_pdu_rx[rx_lcids[i]]+=1; UE_list->eNB_UE_stats[CC_idP][UE_id].num_bytes_rx[rx_lcids[i]]+=rx_lengths[i]; } @@ -732,6 +732,7 @@ void schedule_ulsch_rnti(module_id_t module_idP, continue; // break; } + printf("UE %d/%x is feasible, mode %s\n",UE_id,rnti,mode_string[eNB_UE_stats->mode]); if (eNB_UE_stats->mode == PUSCH) { // ue has a ulsch channel From 2ed6a5fb9eb931431ef0c89c87e9f38a5c2a30d0 Mon Sep 17 00:00:00 2001 From: "aikaterini.trilyraki" Date: Thu, 26 Nov 2015 11:08:48 +0100 Subject: [PATCH 023/263] minor change in eth_raw.c --- targets/ARCH/ETHERNET/USERSPACE/LIB/eth_raw.c | 1 + targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c | 2 +- targets/RT/USER/lte-softmodem.c | 2 +- 3 files changed, 3 insertions(+), 2 deletions(-) diff --git a/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_raw.c b/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_raw.c index 64085c051b..195c6baa44 100644 --- a/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_raw.c +++ b/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_raw.c @@ -75,6 +75,7 @@ int eth_socket_init_raw(openair0_device *device) { local_mac = device->openair0_cfg.my_addr; local_port = device->openair0_cfg.my_port; remote_mac = malloc(ETH_ALEN); + memset(remote_mac,0,ETH_ALEN); remote_port = 0; printf("[%s] local MAC addr %s remote MAC addr %s\n","RRH", local_mac,remote_mac); } else { diff --git a/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c b/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c index 9a87858e34..5d54136ce0 100644 --- a/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c +++ b/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c @@ -177,7 +177,7 @@ int ethernet_tune(openair0_device *device, unsigned int option, int value) { if (1==0) { /***************** get working interface name ***************************/ /* convert ascii ip address from config file to network binary format */ - inet_aton(device->openair0_cfg.my_addr, &ia); */ + inet_aton(device->openair0_cfg.my_addr, &ia); /* look for the interface used, we have its ip address get info on all our network interfaces*/ ids = if_nameindex(); /* loop on these network interfaces */ diff --git a/targets/RT/USER/lte-softmodem.c b/targets/RT/USER/lte-softmodem.c index e915925fe8..0dbab07870 100644 --- a/targets/RT/USER/lte-softmodem.c +++ b/targets/RT/USER/lte-softmodem.c @@ -402,7 +402,7 @@ void print_difftimes() #ifdef DEBUG printf("difftimes min = %lu ns ; max = %lu ns\n", min_diff_time.tv_nsec, max_diff_time.tv_nsec); #else - LOG_D(HW,"difftimes min = %lu ns ; max = %lu ns\n", min_diff_time.tv_nsec, max_diff_time.tv_nsec); + LOG_I(HW,"difftimes min = %lu ns ; max = %lu ns\n", min_diff_time.tv_nsec, max_diff_time.tv_nsec); #endif } From f48d10ba3eb4d4abaa96ada09d6bbed18b9bdf6b Mon Sep 17 00:00:00 2001 From: Raymond Knopp Date: Sun, 29 Nov 2015 00:37:04 -0800 Subject: [PATCH 024/263] Added DLSCH scheduling for subframes 0 and 5. Changes in MAC scheduling data structure to keep track of VRB allocations from SI,RA when scheduling regular DLSCH --- openair1/PHY/LTE_TRANSPORT/dci_tools.c | 54 +++++-- openair1/PHY/LTE_TRANSPORT/proto.h | 9 ++ openair1/SCHED/phy_procedures_lte_ue.c | 16 +- openair2/LAYER2/MAC/eNB_scheduler.c | 139 +++++++++--------- openair2/LAYER2/MAC/eNB_scheduler_RA.c | 4 +- openair2/LAYER2/MAC/eNB_scheduler_bch.c | 6 +- openair2/LAYER2/MAC/eNB_scheduler_dlsch.c | 23 ++- .../LAYER2/MAC/eNB_scheduler_primitives.c | 16 +- openair2/LAYER2/MAC/eNB_scheduler_ulsch.c | 2 +- openair2/LAYER2/MAC/main.c | 1 + openair2/LAYER2/MAC/pre_processor.c | 33 +++-- openair2/LAYER2/MAC/proto.h | 12 +- openair2/PHY_INTERFACE/defs.h | 8 +- 13 files changed, 183 insertions(+), 140 deletions(-) diff --git a/openair1/PHY/LTE_TRANSPORT/dci_tools.c b/openair1/PHY/LTE_TRANSPORT/dci_tools.c index 3456c74ee2..b3d2272107 100644 --- a/openair1/PHY/LTE_TRANSPORT/dci_tools.c +++ b/openair1/PHY/LTE_TRANSPORT/dci_tools.c @@ -453,7 +453,7 @@ uint32_t conv_1C_RIV(int32_t rballoc,uint32_t N_RB_DL) { } -int get_prb(int N_RB_DL,int odd_slot,int vrb,int Ngap) { +uint32_t get_prb(int N_RB_DL,int odd_slot,int vrb,int Ngap) { int offset; @@ -926,10 +926,15 @@ int generate_eNB_dlsch_params_from_dci(int frame, // printf("FDD 1A: mcs %d, rballoc %x,rv %d, NPRB %d\n",mcs,rballoc,rv,NPRB); } - dlsch0_harq = dlsch[0]->harq_processes[harq_pid]; - dlsch0_harq->rb_alloc[0] = localRIV2alloc_LUT6[rballoc]; + if (vrb_type==LOCALIZED) { + dlsch0_harq->rb_alloc[0] = localRIV2alloc_LUT6[rballoc]; + } + else { + LOG_E(PHY,"Distributed RB allocation not done yet\n"); + mac_xface->macphy_exit("exiting"); + } dlsch0_harq->vrb_type = vrb_type; dlsch0_harq->nb_rb = RIV2nb_rb_LUT6[rballoc];//NPRB; RIV_max = RIV_max6; @@ -960,7 +965,14 @@ int generate_eNB_dlsch_params_from_dci(int frame, dlsch0_harq = dlsch[0]->harq_processes[harq_pid]; - dlsch0_harq->rb_alloc[0] = localRIV2alloc_LUT25[rballoc]; + + if (vrb_type==LOCALIZED) { + dlsch0_harq->rb_alloc[0] = localRIV2alloc_LUT25[rballoc]; + } + else { + LOG_E(PHY,"Distributed RB allocation not done yet\n"); + mac_xface->macphy_exit("exiting"); + } dlsch0_harq->vrb_type = vrb_type; dlsch0_harq->nb_rb = RIV2nb_rb_LUT25[rballoc];//NPRB; RIV_max = RIV_max25; @@ -987,9 +999,16 @@ int generate_eNB_dlsch_params_from_dci(int frame, } dlsch0_harq = dlsch[0]->harq_processes[harq_pid]; + if (vrb_type==LOCALIZED) { + dlsch0_harq->rb_alloc[0] = localRIV2alloc_LUT50_0[rballoc]; + dlsch0_harq->rb_alloc[1] = localRIV2alloc_LUT50_1[rballoc]; + } + else { + LOG_E(PHY,"Distributed RB allocation not done yet\n"); + mac_xface->macphy_exit("exiting"); + } + - dlsch0_harq->rb_alloc[0] = localRIV2alloc_LUT50_0[rballoc]; - dlsch0_harq->rb_alloc[1] = localRIV2alloc_LUT50_1[rballoc]; dlsch0_harq->vrb_type = vrb_type; dlsch0_harq->nb_rb = RIV2nb_rb_LUT50[rballoc];//NPRB; RIV_max = RIV_max50; @@ -1017,10 +1036,17 @@ int generate_eNB_dlsch_params_from_dci(int frame, dlsch0_harq = dlsch[0]->harq_processes[harq_pid]; dlsch0_harq->vrb_type = vrb_type; - dlsch0_harq->rb_alloc[0] = localRIV2alloc_LUT100_0[rballoc]; - dlsch0_harq->rb_alloc[1] = localRIV2alloc_LUT100_1[rballoc]; - dlsch0_harq->rb_alloc[2] = localRIV2alloc_LUT100_2[rballoc]; - dlsch0_harq->rb_alloc[3] = localRIV2alloc_LUT100_3[rballoc]; + if (vrb_type==LOCALIZED) { + dlsch0_harq->rb_alloc[0] = localRIV2alloc_LUT100_0[rballoc]; + dlsch0_harq->rb_alloc[1] = localRIV2alloc_LUT100_1[rballoc]; + dlsch0_harq->rb_alloc[2] = localRIV2alloc_LUT100_2[rballoc]; + dlsch0_harq->rb_alloc[3] = localRIV2alloc_LUT100_3[rballoc]; + } + else { + LOG_E(PHY,"Distributed RB allocation not done yet\n"); + mac_xface->macphy_exit("exiting"); + } + dlsch0_harq->nb_rb = RIV2nb_rb_LUT100[rballoc];//NPRB; @@ -2641,7 +2667,7 @@ int generate_eNB_dlsch_params_from_dci(int frame, dlsch1_harq->subframe = subframe; } - //#ifdef DEBUG_DCI +#ifdef DEBUG_DCI if (dlsch0) { printf("dlsch0 eNB: dlsch0 %p\n",dlsch0); @@ -2657,7 +2683,7 @@ int generate_eNB_dlsch_params_from_dci(int frame, printf("dlsch0 eNB: mimo_mode %d\n",dlsch0_harq->mimo_mode); } - //#endif +#endif // compute DL power control parameters computeRhoA_eNB(pdsch_config_dedicated, dlsch[0],dlsch0_harq->dl_power_off); @@ -5508,7 +5534,7 @@ int generate_ue_dlsch_params_from_dci(int frame, } - //#ifdef DEBUG_DCI +#ifdef DEBUG_DCI if (dlsch[0]) { printf("PDSCH dlsch0 UE: rnti %x\n",dlsch[0]->rnti); @@ -5522,7 +5548,7 @@ int generate_ue_dlsch_params_from_dci(int frame, printf("PDSCH dlsch0 UE: pwr_off %d\n",dlsch0_harq->dl_power_off); } - //#endif +#endif dlsch[0]->active=1; // compute DL power control parameters diff --git a/openair1/PHY/LTE_TRANSPORT/proto.h b/openair1/PHY/LTE_TRANSPORT/proto.h index 3f85dec055..16fe3cafc7 100644 --- a/openair1/PHY/LTE_TRANSPORT/proto.h +++ b/openair1/PHY/LTE_TRANSPORT/proto.h @@ -1242,11 +1242,20 @@ uint32_t get_TBS_DL(uint8_t mcs, uint16_t nb_rb); uint32_t get_TBS_UL(uint8_t mcs, uint16_t nb_rb); /* \brief Return bit-map of resource allocation for a given DCI rballoc (RIV format) and vrb type + @param N_RB_DL number of PRB on DL + @param indicator for even/odd slot + @param vrb vrb index + @param Ngap Gap indicator +*/ +uint32_t get_prb(int N_RB_DL,int odd_slot,int vrb,int Ngap); + +/* \brief Return prb for a given vrb index @param vrb_type VRB type (0=localized,1=distributed) @param rb_alloc_dci rballoc field from DCI */ uint32_t get_rballoc(vrb_t vrb_type,uint16_t rb_alloc_dci); + /* \brief Return bit-map of resource allocation for a given DCI rballoc (RIV format) and vrb type @returns Transmission mode (1-7) */ diff --git a/openair1/SCHED/phy_procedures_lte_ue.c b/openair1/SCHED/phy_procedures_lte_ue.c index 2abccfd900..bc7c5e9479 100755 --- a/openair1/SCHED/phy_procedures_lte_ue.c +++ b/openair1/SCHED/phy_procedures_lte_ue.c @@ -168,7 +168,7 @@ void dump_dlsch_SI(PHY_VARS_UE *phy_vars_ue,uint8_t eNB_id,uint8_t subframe) 1, phy_vars_ue->lte_ue_pdcch_vars[eNB_id]->num_pdcch_symbols, phy_vars_ue->frame_rx,subframe); - LOG_I(PHY,"[UE %d] Dumping dlsch_SI : ofdm_symbol_size %d, nsymb %d, nb_rb %d, mcs %d, nb_rb %d, num_pdcch_symbols %d,G %d\n", + LOG_D(PHY,"[UE %d] Dumping dlsch_SI : ofdm_symbol_size %d, nsymb %d, nb_rb %d, mcs %d, nb_rb %d, num_pdcch_symbols %d,G %d\n", phy_vars_ue->Mod_id, phy_vars_ue->lte_frame_parms.ofdm_symbol_size, nsymb, @@ -2062,7 +2062,7 @@ int lte_ue_pdcch_procedures(uint8_t eNB_id,PHY_VARS_UE *phy_vars_ue,uint8_t abst #endif //#ifdef DEBUG_PHY_PROC - LOG_I(PHY,"[UE %d] Frame %d, slot %d, Mode %s: DCI found %i\n",phy_vars_ue->Mod_id,frame_rx,slot_rx,mode_string[phy_vars_ue->UE_mode[eNB_id]],dci_cnt); + LOG_D(PHY,"[UE %d] Frame %d, slot %d, Mode %s: DCI found %i\n",phy_vars_ue->Mod_id,frame_rx,slot_rx,mode_string[phy_vars_ue->UE_mode[eNB_id]],dci_cnt); //#endif phy_vars_ue->lte_ue_pdcch_vars[eNB_id]->dci_received += dci_cnt; @@ -2102,7 +2102,7 @@ int lte_ue_pdcch_procedures(uint8_t eNB_id,PHY_VARS_UE *phy_vars_ue,uint8_t abst #ifdef DEBUG_PHY_PROC // if (subframe_rx == 9) { //( frame_rx % 100 == 0) { - LOG_I(PHY,"frame %d, subframe %d, rnti %x: dci %d/%d\n",frame_rx,subframe_rx,phy_vars_ue->lte_ue_pdcch_vars[eNB_id]->crnti,i,dci_cnt); + LOG_D(PHY,"frame %d, subframe %d, rnti %x: dci %d/%d\n",frame_rx,subframe_rx,phy_vars_ue->lte_ue_pdcch_vars[eNB_id]->crnti,i,dci_cnt); //dump_dci(&phy_vars_ue->lte_frame_parms, &dci_alloc_rx[i]); // } @@ -2444,7 +2444,7 @@ int phy_procedures_UE_RX(PHY_VARS_UE *phy_vars_ue,uint8_t eNB_id,uint8_t abstrac else openair_daq_vars.use_ia_receiver = (openair_daq_vars.use_ia_receiver+1)%3; - LOG_I(PHY,"[MYEMOS] frame %d, IA receiver %d, MCS %d, bitrate %d\n", + LOG_D(PHY,"[MYEMOS] frame %d, IA receiver %d, MCS %d, bitrate %d\n", frame_rx, openair_daq_vars.use_ia_receiver, phy_vars_ue->dlsch_ue[eNB_id][0]->harq_processes[phy_vars_ue->dlsch_ue[eNB_id][0]->current_harq_pid]->mcs, @@ -2800,7 +2800,7 @@ int phy_procedures_UE_RX(PHY_VARS_UE *phy_vars_ue,uint8_t eNB_id,uint8_t abstrac frame_rx,subframe_prev); #ifdef DEBUG_PHY_PROC - LOG_I(PHY,"Decoding DLSCH_SI : rb_alloc %x : nb_rb %d G %d TBS %d, num_pdcch_sym %d\n",phy_vars_ue->dlsch_ue_SI[eNB_id]->harq_processes[0]->rb_alloc_even[0], + LOG_D(PHY,"Decoding DLSCH_SI : rb_alloc %x : nb_rb %d G %d TBS %d, num_pdcch_sym %d\n",phy_vars_ue->dlsch_ue_SI[eNB_id]->harq_processes[0]->rb_alloc_even[0], phy_vars_ue->dlsch_ue_SI[eNB_id]->harq_processes[0]->nb_rb, phy_vars_ue->dlsch_ue_SI[eNB_id]->harq_processes[0]->G, phy_vars_ue->dlsch_ue_SI[eNB_id]->harq_processes[0]->TBS, @@ -2848,7 +2848,7 @@ int phy_procedures_UE_RX(PHY_VARS_UE *phy_vars_ue,uint8_t eNB_id,uint8_t abstrac if (ret == (1+phy_vars_ue->dlsch_ue_SI[eNB_id]->max_turbo_iterations)) { phy_vars_ue->dlsch_SI_errors[eNB_id]++; #ifdef DEBUG_PHY_PROC - LOG_I(PHY,"[UE %d] Frame %d, subframe %d, received SI in error (TBS %d, mcs %d, rvidx %d, rballoc %X.%X.%X.%X\n", + LOG_D(PHY,"[UE %d] Frame %d, subframe %d, received SI in error (TBS %d, mcs %d, rvidx %d, rballoc %X.%X.%X.%X\n", phy_vars_ue->Mod_id, frame_rx, subframe_prev, @@ -3281,7 +3281,7 @@ int phy_procedures_UE_RX(PHY_VARS_UE *phy_vars_ue,uint8_t eNB_id,uint8_t abstrac } if (is_pmch_subframe((subframe_rx==9?-1:0)+frame_rx,subframe_rx,&phy_vars_ue->lte_frame_parms)) { - LOG_I(PHY,"ue calling pmch subframe ..\n "); + LOG_D(PHY,"ue calling pmch subframe ..\n "); if ((slot_rx%2)==1) { LOG_D(PHY,"[UE %d] Frame %d, subframe %d: Querying for PMCH demodulation(%d)\n", @@ -3429,7 +3429,7 @@ int phy_procedures_UE_RX(PHY_VARS_UE *phy_vars_ue,uint8_t eNB_id,uint8_t abstrac phy_vars_rn->sync_area[subframe_rx] = sync_area; // this could also go the harq data struct phy_vars_rn->dlsch_rn_MCH[subframe_rx]->harq_processes[0]->TBS = phy_vars_ue->dlsch_ue_MCH[0]->harq_processes[0]->TBS; phy_vars_rn->dlsch_rn_MCH[subframe_rx]->harq_processes[0]->mcs = phy_vars_ue->dlsch_ue_MCH[0]->harq_processes[0]->mcs; - LOG_I(PHY,"[RN/UE %d] Frame %d subframe %d: store the MCH PDU for MBSFN sync area %d (MCS %d, TBS %d)\n", + LOG_D(PHY,"[RN/UE %d] Frame %d subframe %d: store the MCH PDU for MBSFN sync area %d (MCS %d, TBS %d)\n", phy_vars_ue->Mod_id, frame_rx,subframe_rx,sync_area, phy_vars_rn->dlsch_rn_MCH[subframe_rx]->harq_processes[0]->mcs, phy_vars_rn->dlsch_rn_MCH[subframe_rx]->harq_processes[0]->TBS>>3); diff --git a/openair2/LAYER2/MAC/eNB_scheduler.c b/openair2/LAYER2/MAC/eNB_scheduler.c index 01593aea2a..4bc15a3e1f 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler.c +++ b/openair2/LAYER2/MAC/eNB_scheduler.c @@ -83,9 +83,7 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag, frame_t frameP, sub_frame_t subframeP) //, int calibration_flag) { { - unsigned int nprb[MAX_NUM_CCs]; int mbsfn_status[MAX_NUM_CCs]; - uint32_t RBalloc[MAX_NUM_CCs]; protocol_ctxt_t ctxt; #ifdef EXMIMO int ret; @@ -110,8 +108,6 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag, DCI_pdu[CC_id] = &eNB_mac_inst[module_idP].common_channels[CC_id].DCI_pdu; DCI_pdu[CC_id]->nCCE=0; DCI_pdu[CC_id]->num_pdcch_symbols=1; - nprb[CC_id]=0; - RBalloc[CC_id]=0; mbsfn_status[CC_id]=0; // clear vrb_map memset(eNB_mac_inst[module_idP].common_channels[CC_id].vrb_map,0,100); @@ -245,19 +241,21 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag, // Schedule ULSCH for FDD or subframeP 4 (TDD config 0,3,6) // Schedule Normal DLSCH - schedule_RA(module_idP,frameP,subframeP,2,nprb); + schedule_RA(module_idP,frameP,subframeP,2); + if (mac_xface->lte_frame_parms->frame_type == FDD) { //FDD schedule_ulsch(module_idP,frameP,cooperation_flag,0,4);//,calibration_flag); + } else if ((mac_xface->lte_frame_parms->tdd_config == TDD) || //TDD (mac_xface->lte_frame_parms->tdd_config == 3) || (mac_xface->lte_frame_parms->tdd_config == 6)) { //schedule_ulsch(module_idP,frameP,cooperation_flag,subframeP,4);//,calibration_flag); } - // schedule_ue_spec(module_idP,frameP,subframeP,nprb,mbsfn_status); - fill_DLSCH_dci(module_idP,frameP,subframeP,RBalloc,mbsfn_status); + schedule_ue_spec(module_idP,frameP,subframeP,mbsfn_status); + fill_DLSCH_dci(module_idP,frameP,subframeP,mbsfn_status); break; @@ -270,21 +268,22 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag, case 0: case 1: schedule_ulsch(module_idP,frameP,cooperation_flag,subframeP,7); - fill_DLSCH_dci(module_idP,frameP,subframeP,RBalloc,mbsfn_status); + fill_DLSCH_dci(module_idP,frameP,subframeP,mbsfn_status); break; case 6: schedule_ulsch(module_idP,frameP,cooperation_flag,subframeP,8); - fill_DLSCH_dci(module_idP,frameP,subframeP,RBalloc,mbsfn_status); + fill_DLSCH_dci(module_idP,frameP,subframeP,mbsfn_status); break; default: break; } } else { //FDD - schedule_ue_spec(module_idP,frameP,subframeP,nprb,mbsfn_status); - fill_DLSCH_dci(module_idP,frameP,subframeP,RBalloc,mbsfn_status); schedule_ulsch(module_idP,frameP,cooperation_flag,1,5); + schedule_ue_spec(module_idP,frameP,subframeP,mbsfn_status); + fill_DLSCH_dci(module_idP,frameP,subframeP,mbsfn_status); + } break; @@ -294,9 +293,9 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag, // TDD, nothing // FDD, normal UL/DLSCH if (mac_xface->lte_frame_parms->frame_type == FDD) { //FDD - schedule_ue_spec(module_idP,frameP,subframeP,nprb,mbsfn_status); - fill_DLSCH_dci(module_idP,frameP,subframeP,RBalloc,mbsfn_status); schedule_ulsch(module_idP,frameP,cooperation_flag,2,6); + schedule_ue_spec(module_idP,frameP,subframeP,mbsfn_status); + fill_DLSCH_dci(module_idP,frameP,subframeP,mbsfn_status); } break; @@ -313,17 +312,18 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag, // no break here! case 5: - schedule_ue_spec(module_idP,frameP,subframeP,nprb,mbsfn_status); - fill_DLSCH_dci(module_idP,frameP,subframeP,RBalloc,mbsfn_status); + schedule_ue_spec(module_idP,frameP,subframeP,mbsfn_status); + fill_DLSCH_dci(module_idP,frameP,subframeP,mbsfn_status); break; default: break; } } else { //FDD - schedule_ue_spec(module_idP,frameP,subframeP,nprb,mbsfn_status); - fill_DLSCH_dci(module_idP,frameP,subframeP,RBalloc,mbsfn_status); schedule_ulsch(module_idP,frameP,cooperation_flag,3,7); + schedule_ue_spec(module_idP,frameP,subframeP,mbsfn_status); + fill_DLSCH_dci(module_idP,frameP,subframeP,mbsfn_status); + } @@ -337,7 +337,7 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag, if (mac_xface->lte_frame_parms->frame_type == 1) { // TDD switch (mac_xface->lte_frame_parms->tdd_config) { case 1: - // schedule_RA(module_idP,frameP,subframeP,nprb); + // schedule_RA(module_idP,frameP,subframeP); schedule_ulsch(module_idP,frameP,cooperation_flag,subframeP,8); // no break here! @@ -348,8 +348,8 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag, // no break here! case 5: - schedule_ue_spec(module_idP,frameP,subframeP,nprb,mbsfn_status); - fill_DLSCH_dci(module_idP,frameP,subframeP,RBalloc,mbsfn_status); + schedule_ue_spec(module_idP,frameP,subframeP,mbsfn_status); + fill_DLSCH_dci(module_idP,frameP,subframeP,mbsfn_status); break; default: @@ -357,10 +357,10 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag, } } else { if (mac_xface->lte_frame_parms->frame_type == FDD) { //FDD - // schedule_RA(module_idP,frameP, subframeP, 0, nprb); - // schedule_ulsch(module_idP, frameP, cooperation_flag, 4, 8); - schedule_ue_spec(module_idP, frameP, subframeP, nprb, mbsfn_status); - fill_DLSCH_dci(module_idP, frameP, subframeP, RBalloc, mbsfn_status); + // schedule_RA(module_idP,frameP, subframeP, 0); + schedule_ulsch(module_idP, frameP, cooperation_flag, 4, 8); + schedule_ue_spec(module_idP, frameP, subframeP, mbsfn_status); + fill_DLSCH_dci(module_idP, frameP, subframeP, mbsfn_status); } } @@ -372,21 +372,22 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag, // TDD Config 0,6 ULSCH for subframes 9,3 resp. // TDD normal DLSCH // FDD normal UL/DLSCH - schedule_SI(module_idP,frameP,subframeP,nprb); + schedule_SI(module_idP,frameP,subframeP); - //schedule_RA(module_idP,frameP,subframeP,5,nprb); + //schedule_RA(module_idP,frameP,subframeP,5); if (mac_xface->lte_frame_parms->frame_type == FDD) { - schedule_RA(module_idP,frameP,subframeP,1,nprb); - // schedule_ulsch(module_idP,frameP,cooperation_flag,5,9); - fill_DLSCH_dci(module_idP,frameP,subframeP,RBalloc,mbsfn_status); + schedule_RA(module_idP,frameP,subframeP,1); + schedule_ulsch(module_idP,frameP,cooperation_flag,5,9); + schedule_ue_spec(module_idP, frameP, subframeP, mbsfn_status); + fill_DLSCH_dci(module_idP,frameP,subframeP,mbsfn_status); } else if ((mac_xface->lte_frame_parms->tdd_config == 0) || // TDD Config 0 (mac_xface->lte_frame_parms->tdd_config == 6)) { // TDD Config 6 //schedule_ulsch(module_idP,cooperation_flag,subframeP); - fill_DLSCH_dci(module_idP,frameP,subframeP,RBalloc,mbsfn_status); + fill_DLSCH_dci(module_idP,frameP,subframeP,mbsfn_status); } else { - //schedule_ue_spec(module_idP,frameP,subframeP,nprb,mbsfn_status); - fill_DLSCH_dci(module_idP,frameP,subframeP,RBalloc,mbsfn_status); + schedule_ue_spec(module_idP,frameP,subframeP,mbsfn_status); + fill_DLSCH_dci(module_idP,frameP,subframeP,mbsfn_status); } break; @@ -403,26 +404,26 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag, case 1: schedule_ulsch(module_idP,frameP,cooperation_flag,subframeP,2); - // schedule_ue_spec(module_idP,frameP,subframeP,nprb,mbsfn_status); - fill_DLSCH_dci(module_idP,frameP,subframeP,RBalloc,mbsfn_status); + // schedule_ue_spec(module_idP,frameP,subframeP,mbsfn_status); + fill_DLSCH_dci(module_idP,frameP,subframeP,mbsfn_status); break; case 6: schedule_ulsch(module_idP,frameP,cooperation_flag,subframeP,3); - // schedule_ue_spec(module_idP,frameP,subframeP,nprb,mbsfn_status); - fill_DLSCH_dci(module_idP,frameP,subframeP,RBalloc,mbsfn_status); + // schedule_ue_spec(module_idP,frameP,subframeP,mbsfn_status); + fill_DLSCH_dci(module_idP,frameP,subframeP,mbsfn_status); break; case 5: - schedule_RA(module_idP,frameP,subframeP,2,nprb); - schedule_ue_spec(module_idP,frameP,subframeP,nprb,mbsfn_status); - fill_DLSCH_dci(module_idP,frameP,subframeP,RBalloc,mbsfn_status); + schedule_RA(module_idP,frameP,subframeP,2); + schedule_ue_spec(module_idP,frameP,subframeP,mbsfn_status); + fill_DLSCH_dci(module_idP,frameP,subframeP,mbsfn_status); break; case 3: case 4: - schedule_ue_spec(module_idP,frameP,subframeP,nprb,mbsfn_status); - fill_DLSCH_dci(module_idP,frameP,subframeP,RBalloc,mbsfn_status); + schedule_ue_spec(module_idP,frameP,subframeP,mbsfn_status); + fill_DLSCH_dci(module_idP,frameP,subframeP,mbsfn_status); break; default: @@ -430,8 +431,8 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag, } } else { //FDD // schedule_ulsch(module_idP,frameP,cooperation_flag,6,0); - schedule_ue_spec(module_idP,frameP,subframeP,nprb,mbsfn_status); - fill_DLSCH_dci(module_idP,frameP,subframeP,RBalloc,mbsfn_status); + schedule_ue_spec(module_idP,frameP,subframeP,mbsfn_status); + fill_DLSCH_dci(module_idP,frameP,subframeP,mbsfn_status); } break; @@ -444,14 +445,14 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag, switch (mac_xface->lte_frame_parms->tdd_config) { case 3: case 4: - schedule_RA(module_idP,frameP,subframeP,3,nprb); // 3 = Msg3 subframeP, not - schedule_ue_spec(module_idP,frameP,subframeP,nprb,mbsfn_status); - fill_DLSCH_dci(module_idP,frameP,subframeP,RBalloc,mbsfn_status); + schedule_RA(module_idP,frameP,subframeP,3); // 3 = Msg3 subframeP, not + schedule_ue_spec(module_idP,frameP,subframeP,mbsfn_status); + fill_DLSCH_dci(module_idP,frameP,subframeP,mbsfn_status); break; case 5: - schedule_ue_spec(module_idP,frameP,subframeP,nprb,mbsfn_status); - fill_DLSCH_dci(module_idP,frameP,subframeP,RBalloc,mbsfn_status); + schedule_ue_spec(module_idP,frameP,subframeP,mbsfn_status); + fill_DLSCH_dci(module_idP,frameP,subframeP,mbsfn_status); break; default: @@ -459,8 +460,8 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag, } } else { //FDD //schedule_ulsch(module_idP,frameP,cooperation_flag,7,1); - schedule_ue_spec(module_idP,frameP,subframeP,nprb,mbsfn_status); - fill_DLSCH_dci(module_idP,frameP,subframeP,RBalloc,mbsfn_status); + schedule_ue_spec(module_idP,frameP,subframeP,mbsfn_status); + fill_DLSCH_dci(module_idP,frameP,subframeP,mbsfn_status); } break; @@ -477,10 +478,10 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag, case 4: case 5: - // schedule_RA(module_idP,subframeP,nprb); + // schedule_RA(module_idP,subframeP); schedule_ulsch(module_idP,frameP,cooperation_flag,subframeP,2); - schedule_ue_spec(module_idP,frameP,subframeP,nprb,mbsfn_status); - fill_DLSCH_dci(module_idP,frameP,subframeP,RBalloc,mbsfn_status); + schedule_ue_spec(module_idP,frameP,subframeP,mbsfn_status); + fill_DLSCH_dci(module_idP,frameP,subframeP,mbsfn_status); break; default: @@ -488,8 +489,8 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag, } } else { //FDD //schedule_ulsch(module_idP,frameP,cooperation_flag,8,2); - schedule_ue_spec(module_idP,frameP,subframeP,nprb,mbsfn_status); - fill_DLSCH_dci(module_idP,frameP,subframeP,RBalloc,mbsfn_status); + schedule_ue_spec(module_idP,frameP,subframeP,mbsfn_status); + fill_DLSCH_dci(module_idP,frameP,subframeP,mbsfn_status); } break; @@ -501,30 +502,30 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag, switch (mac_xface->lte_frame_parms->tdd_config) { case 1: schedule_ulsch(module_idP,frameP,cooperation_flag,subframeP,3); - schedule_RA(module_idP,frameP,subframeP,7,nprb); // 7 = Msg3 subframeP, not - schedule_ue_spec(module_idP,frameP,subframeP,nprb,mbsfn_status); - fill_DLSCH_dci(module_idP,frameP,subframeP,RBalloc,mbsfn_status); + schedule_RA(module_idP,frameP,subframeP,7); // 7 = Msg3 subframeP, not + schedule_ue_spec(module_idP,frameP,subframeP,mbsfn_status); + fill_DLSCH_dci(module_idP,frameP,subframeP,mbsfn_status); break; case 3: case 4: schedule_ulsch(module_idP,frameP,cooperation_flag,subframeP,3); - schedule_ue_spec(module_idP,frameP,subframeP,nprb,mbsfn_status); - fill_DLSCH_dci(module_idP,frameP,subframeP,RBalloc,mbsfn_status); + schedule_ue_spec(module_idP,frameP,subframeP,mbsfn_status); + fill_DLSCH_dci(module_idP,frameP,subframeP,mbsfn_status); break; case 6: schedule_ulsch(module_idP,frameP,cooperation_flag,subframeP,4); - //schedule_RA(module_idP,frameP,subframeP,nprb); - schedule_ue_spec(module_idP,frameP,subframeP,nprb,mbsfn_status); - fill_DLSCH_dci(module_idP,frameP,subframeP,RBalloc,mbsfn_status); + //schedule_RA(module_idP,frameP,subframeP); + schedule_ue_spec(module_idP,frameP,subframeP,mbsfn_status); + fill_DLSCH_dci(module_idP,frameP,subframeP,mbsfn_status); break; case 2: case 5: - //schedule_RA(module_idP,frameP,subframeP,nprb); - schedule_ue_spec(module_idP,frameP,subframeP,nprb,mbsfn_status); - fill_DLSCH_dci(module_idP,frameP,subframeP,RBalloc,mbsfn_status); + //schedule_RA(module_idP,frameP,subframeP); + schedule_ue_spec(module_idP,frameP,subframeP,mbsfn_status); + fill_DLSCH_dci(module_idP,frameP,subframeP,mbsfn_status); break; default: @@ -532,15 +533,15 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag, } } else { //FDD // schedule_ulsch(module_idP,frameP,cooperation_flag,9,3); - schedule_ue_spec(module_idP,frameP,subframeP,nprb,mbsfn_status); - fill_DLSCH_dci(module_idP,frameP,subframeP,RBalloc,mbsfn_status); + schedule_ue_spec(module_idP,frameP,subframeP,mbsfn_status); + fill_DLSCH_dci(module_idP,frameP,subframeP,mbsfn_status); } break; } - LOG_I(MAC,"FrameP %d, subframeP %d : Scheduling CCEs\n",frameP,subframeP); + LOG_D(MAC,"FrameP %d, subframeP %d : Scheduling CCEs\n",frameP,subframeP); for (CC_id=0;CC_idRA_dci_fmt1, 1); - nprb[CC_id]= nprb[CC_id] + 3; RA_template->Msg3_subframe=Msg3_subframe; } } else if (RA_template->generate_Msg4 == 1) { @@ -647,7 +646,6 @@ void schedule_RA(module_id_t module_idP,frame_t frameP, sub_frame_t subframeP,un module_idP, CC_id, frameP, UE_RNTI(module_idP,UE_id), rrc_sdu_length); } - nprb[CC_id]= nprb[CC_id] + 3; } } diff --git a/openair2/LAYER2/MAC/eNB_scheduler_bch.c b/openair2/LAYER2/MAC/eNB_scheduler_bch.c index a109e6fb5f..f02aaf6d74 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_bch.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_bch.c @@ -72,8 +72,7 @@ void schedule_SI( module_id_t module_idP, frame_t frameP, - sub_frame_t subframeP, - unsigned int* nprbP) + sub_frame_t subframeP) //------------------------------------------------------------------------------ { @@ -323,14 +322,13 @@ schedule_SI( } - nprbP[CC_id]=3; eNB->eNB_stats[CC_id].total_num_bcch_pdu+=1; eNB->eNB_stats[CC_id].bcch_buffer=bcch_sdu_length; eNB->eNB_stats[CC_id].total_bcch_buffer+=bcch_sdu_length; eNB->eNB_stats[CC_id].bcch_mcs=mcs; } else { - nprbP[CC_id]=0; + //LOG_D(MAC,"[eNB %d] Frame %d : BCCH not active \n",Mod_id,frame); } } diff --git a/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c b/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c index e3b1a96a55..f84bd762b2 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c @@ -422,8 +422,7 @@ schedule_ue_spec( module_id_t module_idP, frame_t frameP, sub_frame_t subframeP, - unsigned int *nb_rb_used0, - int* mbsfn_flag + int* mbsfn_flag ) //------------------------------------------------------------------------------ { @@ -457,6 +456,7 @@ schedule_ue_spec( int32_t tpc=1; static int32_t tpc_accumulated=0; UE_sched_ctrl *ue_sched_ctl; + int i; if (UE_list->head==-1) { return; @@ -471,7 +471,13 @@ schedule_ue_spec( for (CC_id=0; CC_idget_lte_frame_parms(module_idP,CC_id); - total_nb_available_rb[CC_id] = frame_parms[CC_id]->N_RB_DL - nb_rb_used0[CC_id]; + + // get number of PRBs less those used by common channels + total_nb_available_rb[CC_id] = frame_parms[CC_id]->N_RB_DL; + for (i=0;iN_RB_DL;i++) + if (eNB->common_channels[CC_id].vrb_map[i]!=0) + total_nb_available_rb[CC_id]--; + N_RBG[CC_id] = frame_parms[CC_id]->N_RBG; // store the global enb stats: @@ -1505,7 +1511,6 @@ fill_DLSCH_dci( module_id_t module_idP, frame_t frameP, sub_frame_t subframeP, - uint32_t* RBallocP, int* mbsfn_flagP ) //------------------------------------------------------------------------------ @@ -1518,7 +1523,6 @@ fill_DLSCH_dci( unsigned char *vrb_map; uint8_t rballoc_sub[25]; //uint8_t number_of_subbands=13; - uint32_t *rballoc=RBallocP; unsigned char round; unsigned char harq_pid; @@ -1563,11 +1567,6 @@ fill_DLSCH_dci( /// Synchronizing rballoc with rballoc_sub for(i=0; ilte_frame_parms.N_RBG; i++) { rballoc_sub[i] = UE_list->UE_template[CC_id][UE_id].rballoc_subband[harq_pid][i]; - - if(rballoc_sub[i] == 1) { - rballoc[CC_id] |= (0x0001<get_transmission_mode(module_idP,CC_id,rnti)) { @@ -1576,7 +1575,7 @@ fill_DLSCH_dci( case 1: case 2: - LOG_D(MAC,"[eNB %d] CC_id %d Adding UE %d spec DCI for %d PRBS (rb alloc: %x) \n",module_idP, CC_id, UE_id, nb_rb,rballoc); + LOG_D(MAC,"[eNB %d] CC_id %d Adding UE %d spec DCI for %d PRBS \n",module_idP, CC_id, UE_id, nb_rb); if (PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.frame_type == TDD) { switch (PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL) { @@ -1669,7 +1668,7 @@ fill_DLSCH_dci( case 3: LOG_D(MAC,"[eNB %d] CC_id %d Adding Format 2A UE %d spec DCI for %d PRBS (rb alloc: %x) \n", - module_idP, CC_id, UE_id, nb_rb,rballoc); + module_idP, CC_id, UE_id, nb_rb); if (PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.frame_type == TDD) { switch (PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL) { diff --git a/openair2/LAYER2/MAC/eNB_scheduler_primitives.c b/openair2/LAYER2/MAC/eNB_scheduler_primitives.c index bbb22f8bde..cb3887d45b 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_primitives.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_primitives.c @@ -906,12 +906,12 @@ int get_nCCE_offset(int *CCE_table, // check CCE(0 ... L-1) nb_candidates = (L==4) ? 4 : 2; nb_candidates = min(nb_candidates,nCCE/L); - printf("Common DCI nb_candidates %d, L %d\n",nb_candidates,L); + // printf("Common DCI nb_candidates %d, L %d\n",nb_candidates,L); for (m = nb_candidates-1 ; m >=0 ; m--) { search_space_free = 1; for (l=0; lNum_common_dci,DCI_pdu->Num_ue_spec_dci); + LOG_D(MAC,"Allocate CCEs subframe %d, test %d : (common %d,uspec %d)\n",subframeP,test_onlyP,DCI_pdu->Num_common_dci,DCI_pdu->Num_ue_spec_dci); init_CCE_table(module_idP,CC_idP); DCI_pdu->nCCE=0; @@ -1002,7 +1002,7 @@ int allocate_CCEs(int module_idP, for (i=0;iNum_common_dci + DCI_pdu->Num_ue_spec_dci;i++) { dci_alloc = &DCI_pdu->dci_alloc[i]; - LOG_I(MAC,"Trying to allocate DCI %d/%d (%d,%d) : rnti %x, aggreg %d nCCE %d / %d (num_pdcch_symbols %d)\n", + LOG_D(MAC,"Trying to allocate DCI %d/%d (%d,%d) : rnti %x, aggreg %d nCCE %d / %d (num_pdcch_symbols %d)\n", i,DCI_pdu->Num_common_dci+DCI_pdu->Num_ue_spec_dci, DCI_pdu->Num_common_dci,DCI_pdu->Num_ue_spec_dci, dci_alloc->rnti,1<L, @@ -1024,11 +1024,11 @@ int allocate_CCEs(int module_idP, (iNum_common_dci) ? 1 : 0, dci_alloc->rnti, subframeP))>=0) {// the allocation is feasible, rnti rule passes - LOG_I(MAC,"Allocating at nCCE %d\n",fCCE); + LOG_D(MAC,"Allocating at nCCE %d\n",fCCE); if (test_onlyP == 0) { DCI_pdu->nCCE += (1<L); dci_alloc->firstCCE=fCCE; - LOG_I(MAC,"Allocate CCEs subframe %d, test %d\n",subframeP,test_onlyP); + LOG_D(MAC,"Allocate CCEs subframe %d, test %d\n",subframeP,test_onlyP); } } // fCCE>=0 else { diff --git a/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c b/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c index 30cc27fbfd..f924885f82 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c @@ -732,7 +732,7 @@ void schedule_ulsch_rnti(module_id_t module_idP, continue; // break; } - printf("UE %d/%x is feasible, mode %s\n",UE_id,rnti,mode_string[eNB_UE_stats->mode]); + // printf("UE %d/%x is feasible, mode %s\n",UE_id,rnti,mode_string[eNB_UE_stats->mode]); if (eNB_UE_stats->mode == PUSCH) { // ue has a ulsch channel diff --git a/openair2/LAYER2/MAC/main.c b/openair2/LAYER2/MAC/main.c index a55301d80d..0e8a65cf01 100644 --- a/openair2/LAYER2/MAC/main.c +++ b/openair2/LAYER2/MAC/main.c @@ -468,6 +468,7 @@ int l2_init(LTE_DL_FRAME_PARMS *frame_parms,int eMBMS_active, char *uecap_xer,ui mac_xface->get_transmission_mode = get_transmission_mode; mac_xface->get_rballoc = get_rballoc; mac_xface->get_nb_rb = conv_nprb; + mac_xface->get_prb = get_prb; // mac_xface->get_SB_size = Get_SB_size; mac_xface->get_subframe_direction = get_subframe_direction; mac_xface->Msg3_transmitted = Msg3_tx; diff --git a/openair2/LAYER2/MAC/pre_processor.c b/openair2/LAYER2/MAC/pre_processor.c index 316c79c524..a5454e48f6 100644 --- a/openair2/LAYER2/MAC/pre_processor.c +++ b/openair2/LAYER2/MAC/pre_processor.c @@ -731,20 +731,24 @@ void dlsch_scheduler_pre_processor (module_id_t Mod_id, void dlsch_scheduler_pre_processor_reset (int module_idP, - int UE_id, - uint8_t CC_id, - int frameP, - int subframeP, - int N_RBG, - uint16_t nb_rbs_required[MAX_NUM_CCs][NUMBER_OF_UE_MAX], - uint16_t nb_rbs_required_remaining[MAX_NUM_CCs][NUMBER_OF_UE_MAX], - unsigned char rballoc_sub[MAX_NUM_CCs][N_RBG_MAX], - unsigned char MIMO_mode_indicator[MAX_NUM_CCs][N_RBG_MAX]) + int UE_id, + uint8_t CC_id, + int frameP, + int subframeP, + int N_RBG, + uint16_t nb_rbs_required[MAX_NUM_CCs][NUMBER_OF_UE_MAX], + uint16_t nb_rbs_required_remaining[MAX_NUM_CCs][NUMBER_OF_UE_MAX], + unsigned char rballoc_sub[MAX_NUM_CCs][N_RBG_MAX], + unsigned char MIMO_mode_indicator[MAX_NUM_CCs][N_RBG_MAX]) + { - int i; + int i,j; UE_list_t *UE_list=&eNB_mac_inst[module_idP].UE_list; UE_sched_ctrl *ue_sched_ctl = &UE_list->UE_sched_ctrl[UE_id]; rnti_t rnti = UE_RNTI(module_idP,UE_id); + uint8_t *vrb_map = &eNB_mac_inst[module_idP].common_channels[CC_id].vrb_map; + int RBGsize = PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL/N_RBG; + // initialize harq_pid and round mac_xface->get_ue_active_harq_pid(module_idP,CC_id,rnti, @@ -759,8 +763,15 @@ void dlsch_scheduler_pre_processor_reset (int module_idP, nb_rbs_required_remaining[CC_id][UE_id] = 0; for (i=0; irballoc_sub_UE[CC_id][i] = 0; + ue_sched_ctl->rballoc_sub_UE[CC_id][UE_id] = 0; rballoc_sub[CC_id][i] = 0; + for (j=0;j Date: Sat, 5 Dec 2015 02:28:21 -0800 Subject: [PATCH 025/263] updated unitary simulations for new CCE interfaces. Cleaned up warnings in dlsim/pdcchsim/ulsim. --- openair1/PHY/LTE_TRANSPORT/dci.c | 101 ++++++++++++++ openair1/PHY/LTE_TRANSPORT/dci_tools.c | 8 +- openair1/PHY/LTE_TRANSPORT/proto.h | 6 + openair1/SIMULATION/LTE_PHY/dlsim.c | 70 +++++----- openair1/SIMULATION/LTE_PHY/pdcchsim.c | 129 ++++++++++-------- openair1/SIMULATION/LTE_PHY/ulsim.c | 25 ++-- openair2/LAYER2/MAC/eNB_scheduler.c | 1 + openair2/LAYER2/MAC/eNB_scheduler_dlsch.c | 1 - .../LAYER2/MAC/eNB_scheduler_primitives.c | 8 +- openair2/LAYER2/MAC/pre_processor.c | 1 + 10 files changed, 236 insertions(+), 114 deletions(-) diff --git a/openair1/PHY/LTE_TRANSPORT/dci.c b/openair1/PHY/LTE_TRANSPORT/dci.c index f126d0e2ea..70761ac5ae 100644 --- a/openair1/PHY/LTE_TRANSPORT/dci.c +++ b/openair1/PHY/LTE_TRANSPORT/dci.c @@ -2546,6 +2546,107 @@ uint16_t get_nCCE_mac(uint8_t Mod_id,uint8_t CC_id,int num_pdcch_symbols,int sub get_mi(&PHY_vars_eNB_g[Mod_id][CC_id]->lte_frame_parms,subframe))); } + +int get_nCCE_offset_l1(int *CCE_table, + const unsigned char L, + const int nCCE, + const int common_dci, + const unsigned short rnti, + const unsigned char subframe) +{ + + int search_space_free,m,nb_candidates = 0,l,i; + unsigned int Yk; + /* + printf("CCE Allocation: "); + for (i=0;i=0 ; m--) { + + search_space_free = 1; + for (l=0; lsubframe = subframe; } - //#ifdef DEBUG_DCI +#ifdef DEBUG_DCI if (dlsch0) { printf("dlsch0 eNB: dlsch0 %p\n",dlsch0); @@ -2683,7 +2683,7 @@ int generate_eNB_dlsch_params_from_dci(int frame, printf("dlsch0 eNB: mimo_mode %d\n",dlsch0_harq->mimo_mode); } - //#endif +#endif // compute DL power control parameters computeRhoA_eNB(pdsch_config_dedicated, dlsch[0],dlsch0_harq->dl_power_off); @@ -5534,7 +5534,7 @@ int generate_ue_dlsch_params_from_dci(int frame, } - //#ifdef DEBUG_DCI +#ifdef DEBUG_DCI if (dlsch[0]) { printf("PDSCH dlsch0 UE: rnti %x\n",dlsch[0]->rnti); @@ -5548,7 +5548,7 @@ int generate_ue_dlsch_params_from_dci(int frame, printf("PDSCH dlsch0 UE: pwr_off %d\n",dlsch0_harq->dl_power_off); } - //#endif +#endif dlsch[0]->active=1; // compute DL power control parameters diff --git a/openair1/PHY/LTE_TRANSPORT/proto.h b/openair1/PHY/LTE_TRANSPORT/proto.h index 16fe3cafc7..7b1cd6ed28 100644 --- a/openair1/PHY/LTE_TRANSPORT/proto.h +++ b/openair1/PHY/LTE_TRANSPORT/proto.h @@ -1595,6 +1595,12 @@ uint16_t computeRIV(uint16_t N_RB_DL,uint16_t RBstart,uint16_t Lcrbs); uint32_t pmi_extend(LTE_DL_FRAME_PARMS *frame_parms,uint8_t wideband_pmi); +int get_nCCE_offset_l1(int *CCE_table, + const unsigned char L, + const int nCCE, + const int common_dci, + const unsigned short rnti, + const unsigned char subframe); uint16_t get_nCCE(uint8_t num_pdcch_symbols,LTE_DL_FRAME_PARMS *frame_parms,uint8_t mi); diff --git a/openair1/SIMULATION/LTE_PHY/dlsim.c b/openair1/SIMULATION/LTE_PHY/dlsim.c index 3227be22b4..bf01c2de9d 100644 --- a/openair1/SIMULATION/LTE_PHY/dlsim.c +++ b/openair1/SIMULATION/LTE_PHY/dlsim.c @@ -266,15 +266,15 @@ int main(int argc, char **argv) unsigned int ret; unsigned int coded_bits_per_codeword=0,nsymb,dci_cnt,tbs=0; - unsigned int tx_lev=0,tx_lev_dB=0,trials,errs[4]= {0,0,0,0},errs2[4]= {0,0,0,0},round_trials[4]= {0,0,0,0},dci_errors=0,dlsch_active=0,num_layers; - int re_allocated; + unsigned int tx_lev=0,tx_lev_dB=0,trials,errs[4]= {0,0,0,0},errs2[4]= {0,0,0,0},round_trials[4]= {0,0,0,0},dci_errors=0,dlsch_active=0;//,num_layers; + // int re_allocated; char fname[32],vname[32]; FILE *bler_fd; char bler_fname[256]; FILE *time_meas_fd; char time_meas_fname[256]; - FILE *tikz_fd; - char tikz_fname[256]; + // FILE *tikz_fd; + // char tikz_fname[256]; FILE *input_trch_fd=NULL; unsigned char input_trch_file=0; @@ -300,7 +300,7 @@ int main(int argc, char **argv) uint8_t rx_sample_offset = 0; //char stats_buffer[4096]; //int len; - uint8_t num_rounds = 4,fix_rounds=0; + uint8_t num_rounds = 4;//,fix_rounds=0; uint8_t subframe=7; int u; int n=0; @@ -314,8 +314,8 @@ int main(int argc, char **argv) // void *data; // int ii; - int bler; - double blerr[4],uncoded_ber,avg_ber; + // int bler; + double blerr[4],uncoded_ber;//,avg_ber; short *uncoded_ber_bit=NULL; uint8_t N_RB_DL=25,osf=1; uint8_t fdd_flag = 0; @@ -330,7 +330,7 @@ int main(int argc, char **argv) int common_flag=0,TPC=0; double cpu_freq_GHz; - time_stats_t ts;//,sts,usts; + // time_stats_t ts;//,sts,usts; int avg_iter,iter_trials; int rballocset=0; int print_perf=0; @@ -344,17 +344,22 @@ int main(int argc, char **argv) int TB0_active = 1; uint32_t perfect_ce = 0; - LTE_DL_UE_HARQ_t *dlsch0_ue_harq; - LTE_DL_eNB_HARQ_t *dlsch0_eNB_harq; + // LTE_DL_UE_HARQ_t *dlsch0_ue_harq; + // LTE_DL_eNB_HARQ_t *dlsch0_eNB_harq; uint8_t Kmimo; uint8_t ue_category=4; uint32_t Nsoft; - FILE *proc_fd = NULL; - char buf[64]; + + + + int CCE_table[800]; opp_enabled=1; // to enable the time meas #if defined(__arm__) + FILE *proc_fd = NULL; + char buf[64]; + proc_fd = fopen("/sys/devices/system/cpu/cpu4/cpufreq/cpuinfo_cur_freq", "r"); if(!proc_fd) printf("cannot open /sys/devices/system/cpu/cpu4/cpufreq/cpuinfo_cur_freq"); @@ -377,7 +382,7 @@ int main(int argc, char **argv) // default parameters n_frames = 1000; snr0 = 0; - num_layers = 1; + // num_layers = 1; perfect_ce = 0; while ((c = getopt (argc, argv, "ahdpZDe:m:n:o:s:f:t:c:g:r:F:x:y:z:AM:N:I:i:O:R:S:C:T:b:u:U:v:w:B:PLl:Y")) != -1) { @@ -1328,7 +1333,7 @@ int main(int argc, char **argv) dci_alloc[num_dci].L = 1; dci_alloc[num_dci].rnti = SI_RNTI; dci_alloc[num_dci].format = format1A; - dci_alloc[num_dci].nCCE = 0; + dci_alloc[num_dci].firstCCE = 0; dump_dci(&PHY_vars_eNB->lte_frame_parms,&dci_alloc[num_dci]); printf("Generating dlsch params for user %d\n",k); @@ -1635,7 +1640,7 @@ int main(int argc, char **argv) dci_alloc[num_dci].L = 1; dci_alloc[num_dci].rnti = SI_RNTI; dci_alloc[num_dci].format = format1A; - dci_alloc[num_dci].nCCE = 0; + dci_alloc[num_dci].firstCCE = 0; dump_dci(&PHY_vars_eNB->lte_frame_parms,&dci_alloc[num_dci]); printf("Generating dlsch params for user %d\n",k); @@ -1943,7 +1948,7 @@ int main(int argc, char **argv) dci_alloc[num_dci].L = 1; dci_alloc[num_dci].rnti = SI_RNTI; dci_alloc[num_dci].format = format1A; - dci_alloc[num_dci].nCCE = 0; + dci_alloc[num_dci].firstCCE = 0; dump_dci(&PHY_vars_eNB->lte_frame_parms,&dci_alloc[num_dci]); printf("Generating dlsch params for user %d\n",k); @@ -1974,7 +1979,7 @@ int main(int argc, char **argv) dci_alloc[num_dci].L = 1; dci_alloc[num_dci].rnti = n_rnti+k; dci_alloc[num_dci].format = format1E_2A_M10PRB; - dci_alloc[num_dci].nCCE = 4*k; + dci_alloc[num_dci].firstCCE = 4*k; printf("Generating dlsch params for user %d\n",k); generate_eNB_dlsch_params_from_dci(0, subframe, @@ -2019,17 +2024,20 @@ int main(int argc, char **argv) if (n_frames==1) printf("%d\n",numCCE); // apply RNTI-based nCCE allocation + memset(CCE_table,0,800*sizeof(int)); + for (i=num_common_dci; idlsch_modulation_stats); - re_allocated = dlsch_modulation(PHY_vars_eNB->lte_eNB_common_vars.txdataF[eNB_id], - AMP, - subframe, - &PHY_vars_eNB->lte_frame_parms, - num_pdcch_symbols, - PHY_vars_eNB->dlsch_eNB[k][0], - PHY_vars_eNB->dlsch_eNB[k][1]); + dlsch_modulation(PHY_vars_eNB->lte_eNB_common_vars.txdataF[eNB_id], + AMP, + subframe, + &PHY_vars_eNB->lte_frame_parms, + num_pdcch_symbols, + PHY_vars_eNB->dlsch_eNB[k][0], + PHY_vars_eNB->dlsch_eNB[k][1]); stop_meas(&PHY_vars_eNB->dlsch_modulation_stats); /* if (trials==0 && round==0) diff --git a/openair1/SIMULATION/LTE_PHY/pdcchsim.c b/openair1/SIMULATION/LTE_PHY/pdcchsim.c index caa7e1248d..f5e2fba8fc 100644 --- a/openair1/SIMULATION/LTE_PHY/pdcchsim.c +++ b/openair1/SIMULATION/LTE_PHY/pdcchsim.c @@ -56,7 +56,7 @@ PHY_VARS_UE *PHY_vars_UE; #define UL_RB_ALLOC 0x1ff; #define CCCH_RB_ALLOC computeRIV(PHY_vars_eNB->lte_frame_parms.N_RB_UL,0,2) -#define DLSCH_RB_ALLOC 0x1fbf // igore DC component,RB13 +#define DLSCH_RB_ALLOC ((uint16_t)0x1fbf) // igore DC component,RB13 void lte_param_init(unsigned char N_tx, unsigned char N_rx,unsigned char transmission_mode,unsigned char extended_prefix_flag,uint16_t Nid_cell,uint8_t tdd_config,uint8_t N_RB_DL, lte_frame_type_t frame_type,uint8_t osf,uint32_t perfect_ce) @@ -154,9 +154,9 @@ DCI_PDU DCI_pdu; DCI_PDU *get_dci(LTE_DL_FRAME_PARMS *lte_frame_parms,uint8_t log2L, uint8_t log2Lcommon, uint8_t format_selector, uint32_t rnti) { - uint8_t BCCH_alloc_pdu[8]; - uint8_t DLSCH_alloc_pdu[8]; - uint8_t UL_alloc_pdu[8]; + uint32_t BCCH_alloc_pdu[2]; + uint32_t DLSCH_alloc_pdu[2]; + uint32_t UL_alloc_pdu[2]; int i; int dci_length_bytes,dci_length; @@ -462,31 +462,35 @@ DCI_PDU *get_dci(LTE_DL_FRAME_PARMS *lte_frame_parms,uint8_t log2L, uint8_t log2 DCI_pdu.dci_alloc[0].ra_flag = 0; memcpy((void*)&DCI_pdu.dci_alloc[0].dci_pdu[0], &BCCH_alloc_pdu[0], BCCH_pdu_size_bytes); DCI_pdu.Num_common_dci++; - /* + if (lte_frame_parms->N_RB_DL >= 25) { // add ue specific dci - DCI_pdu.dci_alloc[1].dci_length = dci_length; - DCI_pdu.dci_alloc[1].L = log2L; - DCI_pdu.dci_alloc[1].rnti = rnti; - DCI_pdu.dci_alloc[1].format = format1; - DCI_pdu.dci_alloc[1].ra_flag = 0; - memcpy((void*)&DCI_pdu.dci_alloc[1].dci_pdu[0], &DLSCH_alloc_pdu[0], dci_length_bytes); - DCI_pdu.Num_ue_spec_dci++; + DCI_pdu.dci_alloc[1].dci_length = dci_length; + DCI_pdu.dci_alloc[1].L = log2L; + DCI_pdu.dci_alloc[1].rnti = rnti; + DCI_pdu.dci_alloc[1].format = format1; + DCI_pdu.dci_alloc[1].ra_flag = 0; + memcpy((void*)&DCI_pdu.dci_alloc[1].dci_pdu[0], &DLSCH_alloc_pdu[0], dci_length_bytes); + DCI_pdu.Num_ue_spec_dci++; + + if (lte_frame_parms->N_RB_DL >= 50) { + DCI_pdu.dci_alloc[2].dci_length = UL_pdu_size_bits; + DCI_pdu.dci_alloc[2].L = log2L; + DCI_pdu.dci_alloc[2].rnti = rnti; + DCI_pdu.dci_alloc[2].format = format0; + DCI_pdu.dci_alloc[2].ra_flag = 0; + memcpy((void*)&DCI_pdu.dci_alloc[0].dci_pdu[0], &UL_alloc_pdu[0], UL_pdu_size_bytes); + DCI_pdu.Num_ue_spec_dci++; + } + } + - DCI_pdu.dci_alloc[0].dci_length = UL_pdu_size_bits; - DCI_pdu.dci_alloc[0].L = log2L; - DCI_pdu.dci_alloc[0].rnti = rnti; - DCI_pdu.dci_alloc[0].format = format0; - DCI_pdu.dci_alloc[0].ra_flag = 0; - memcpy((void*)&DCI_pdu.dci_alloc[0].dci_pdu[0], &UL_alloc_pdu[0], UL_pdu_size_bytes); - DCI_pdu.Num_ue_spec_dci++; - */ DCI_pdu.nCCE = 0; for (i=0; iUE_mode[0] = PUSCH; - nCCE_max = get_nCCE(3,&PHY_vars_eNB->lte_frame_parms,get_mi(&PHY_vars_eNB->lte_frame_parms,0)); + // nCCE_max = get_nCCE(3,&PHY_vars_eNB->lte_frame_parms,get_mi(&PHY_vars_eNB->lte_frame_parms,0)); //printf("nCCE_max %d\n",nCCE_max); //printf("num_phich interferers %d\n",num_phich_interf); @@ -973,55 +975,62 @@ int main(int argc, char **argv) numCCE=0; n_trials_common++; common_active = 1; - n_trials_ul++; - ul_active = 1; - n_trials_dl++; - dl_active = 1; + if (PHY_vars_eNB->lte_frame_parms.N_RB_DL >= 50) { + n_trials_ul++; + ul_active = 1; + } + if (PHY_vars_eNB->lte_frame_parms.N_RB_DL >= 25) { + n_trials_dl++; + dl_active = 1; + } - init_nCCE_table(); num_pdcch_symbols = get_num_pdcch_symbols(DCI_pdu.Num_common_dci+DCI_pdu.Num_ue_spec_dci, DCI_pdu.dci_alloc, frame_parms, subframe); - DCI_pdu.nCCE = get_nCCE(num_pdcch_symbols,&PHY_vars_eNB->lte_frame_parms,get_mi(&PHY_vars_eNB->lte_frame_parms,subframe)); + numCCE = get_nCCE(num_pdcch_symbols,&PHY_vars_eNB->lte_frame_parms,get_mi(&PHY_vars_eNB->lte_frame_parms,subframe)); if (n_frames==1) { printf("num_dci %d, num_pddch_symbols %d, nCCE %d\n", DCI_pdu.Num_common_dci+DCI_pdu.Num_ue_spec_dci, - num_pdcch_symbols, - DCI_pdu.nCCE); + num_pdcch_symbols,numCCE); } // apply RNTI-based nCCE allocation + memset(CCE_table,0,800*sizeof(int)); + for (i = 0; i < DCI_pdu.Num_common_dci + DCI_pdu.Num_ue_spec_dci; i++) { // SI RNTI if (DCI_pdu.dci_alloc[i].rnti == SI_RNTI) { - DCI_pdu.dci_alloc[i].nCCE = get_nCCE_offset(1<0) { PHY_vars_eNB->ulsch_eNB[0]->harq_processes[harq_pid]->first_rb = 4; @@ -1082,7 +1091,7 @@ int main(int argc, char **argv) } PHY_vars_eNB->ulsch_eNB[0]->harq_processes[harq_pid]->first_rb = 0; - */ + } // write_output("pilotsF.m","rsF",txdataF[0],lte_PHY_vars_eNB->lte_frame_parms.ofdm_symbol_size,1,1); @@ -1262,7 +1271,7 @@ int main(int argc, char **argv) for (i = 0; i < dci_cnt; i++) printf("dci %d: rnti 0x%x, format %d, L %d, nCCE %d/%d dci_length %d\n",i, dci_alloc_rx[i].rnti, dci_alloc_rx[i].format, - dci_alloc_rx[i].L, dci_alloc_rx[i].nCCE, numCCE, dci_alloc_rx[i].dci_length); + dci_alloc_rx[i].L, dci_alloc_rx[i].firstCCE, numCCE, dci_alloc_rx[i].dci_length); } for (i=0; i1) { - n_tx = 1; - } - break; case 'y': @@ -701,8 +697,8 @@ int main(int argc, char **argv) // Create transport channel structures for 2 transport blocks (MIMO) for (i=0; i<2; i++) { - PHY_vars_eNB->dlsch_eNB[0][i] = new_eNB_dlsch(1,8,N_RB_DL,0); - PHY_vars_UE->dlsch_ue[0][i] = new_ue_dlsch(1,8,MAX_TURBO_ITERATIONS,N_RB_DL,0); + PHY_vars_eNB->dlsch_eNB[0][i] = new_eNB_dlsch(1,8,1827072,N_RB_DL,0); + PHY_vars_UE->dlsch_ue[0][i] = new_ue_dlsch(1,8,1827072,MAX_TURBO_ITERATIONS,N_RB_DL,0); if (!PHY_vars_eNB->dlsch_eNB[0][i]) { printf("Can't get eNB dlsch structures\n"); @@ -717,7 +713,7 @@ int main(int argc, char **argv) PHY_vars_eNB->dlsch_eNB[0][i]->rnti = 14; PHY_vars_UE->dlsch_ue[0][i]->rnti = 14; - } + } switch (PHY_vars_eNB->lte_frame_parms.N_RB_UL) { @@ -905,11 +901,11 @@ int main(int argc, char **argv) harq_pid = subframe2harq_pid(&PHY_vars_UE->lte_frame_parms,PHY_vars_UE->frame_tx,subframe); - + input_buffer_length = PHY_vars_UE->ulsch_ue[0]->harq_processes[harq_pid]->TBS/8; + input_buffer = (unsigned char *)malloc(input_buffer_length+4); // printf("UL frame %d/subframe %d, harq_pid %d\n",PHY_vars_UE->frame,subframe,harq_pid); if (input_fdUL == NULL) { - input_buffer_length = PHY_vars_UE->ulsch_ue[0]->harq_processes[harq_pid]->TBS/8; - input_buffer = (unsigned char *)malloc(input_buffer_length+4); + if (n_frames == 1) { trch_out_fdUL= fopen("ulsch_trchUL.txt","w"); @@ -931,7 +927,7 @@ int main(int argc, char **argv) i=0; while (!feof(input_fdUL)) { - fscanf(input_fdUL,"%s %s",input_val_str,input_val_str2);//&input_val1,&input_val2); + ret=fscanf(input_fdUL,"%s %s",input_val_str,input_val_str2);//&input_val1,&input_val2); if ((i%4)==0) { ((short*)txdata[0])[i/2] = (short)((1<<15)*strtod(input_val_str,NULL)); @@ -1261,6 +1257,7 @@ int main(int argc, char **argv) start_meas(&PHY_vars_eNB->phy_proc_rx); start_meas(&PHY_vars_eNB->ofdm_demod_stats); lte_eNB_I0_measurements(PHY_vars_eNB, + subframe, 0, 1); diff --git a/openair2/LAYER2/MAC/eNB_scheduler.c b/openair2/LAYER2/MAC/eNB_scheduler.c index 60e09503d3..21e9337dbb 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler.c +++ b/openair2/LAYER2/MAC/eNB_scheduler.c @@ -540,6 +540,7 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag, LOG_D(MAC,"FrameP %d, subframeP %d : Scheduling CCEs\n",frameP,subframeP); + // Allocate CCEs for good after scheduling is done for (CC_id=0;CC_idL), - nCCE_max, - (iNum_common_dci) ? 1 : 0, - dci_alloc->rnti, + 1<<(dci_alloc->L), + nCCE_max, + (iNum_common_dci) ? 1 : 0, + dci_alloc->rnti, subframeP))>=0) {// the allocation is feasible, rnti rule passes LOG_D(MAC,"Allocating at nCCE %d\n",fCCE); diff --git a/openair2/LAYER2/MAC/pre_processor.c b/openair2/LAYER2/MAC/pre_processor.c index a5454e48f6..e8264f31f6 100644 --- a/openair2/LAYER2/MAC/pre_processor.c +++ b/openair2/LAYER2/MAC/pre_processor.c @@ -762,6 +762,7 @@ void dlsch_scheduler_pre_processor_reset (int module_idP, ue_sched_ctl->dl_pow_off[CC_id] = 2; nb_rbs_required_remaining[CC_id][UE_id] = 0; + // Initialize Subbands according to VRB map for (i=0; irballoc_sub_UE[CC_id][UE_id] = 0; rballoc_sub[CC_id][i] = 0; From fa3c5e14f1a0e7c0b8108583de2e1e3affb7766c Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Mon, 14 Dec 2015 16:37:31 +0100 Subject: [PATCH 026/263] disabled low latency option for bladerf --- cmake_targets/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake_targets/CMakeLists.txt b/cmake_targets/CMakeLists.txt index 90929d563b..4e1b5489b8 100644 --- a/cmake_targets/CMakeLists.txt +++ b/cmake_targets/CMakeLists.txt @@ -435,7 +435,7 @@ elseif (${RF_BOARD} STREQUAL "OAI_BLADERF") ) LINK_DIRECTORIES("/usr/lib/x86_64-linux-gnu") set(option_HW_lib "bladeRF") -#set(LOWLATENCY False) +set(LOWLATENCY False) elseif (${RF_BOARD} STREQUAL "ETHERNET") include_directories ("${OPENAIR_TARGETS}/ARCH/ETHERNET/USERSPACE/LIB") From 40f242094f6ff73aa79cfd02f0d20e3198237d14 Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Mon, 14 Dec 2015 16:38:10 +0100 Subject: [PATCH 027/263] modified due to compilation error --- openair1/PHY/TOOLS/signal_energy.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openair1/PHY/TOOLS/signal_energy.c b/openair1/PHY/TOOLS/signal_energy.c index 323a1831dc..373fdc0d90 100755 --- a/openair1/PHY/TOOLS/signal_energy.c +++ b/openair1/PHY/TOOLS/signal_energy.c @@ -197,7 +197,7 @@ int32_t signal_energy(int32_t *input,uint32_t length) for (i=0; i>1; i++) { tmpE = vqaddq_s32(tmpE,vshrq_n_s32(vmull_s16(*in,*in),shift)); - tmpDC = vaddw_s16(tmpDC,vshr_n_s16(*in++,shift_DC)); + //tmpDC = vaddw_s16(tmpDC,vshr_n_s16(*in++,shift_DC)); } From b0a54d8c7e9af8e86fd731a1eca31fa0a2af18bf Mon Sep 17 00:00:00 2001 From: gauthier Date: Thu, 17 Dec 2015 09:44:38 +0100 Subject: [PATCH 028/263] fix of PUCCH statistic tracking with signal scope --- openair1/PHY/LTE_TRANSPORT/pucch.c | 8 ++++---- openair1/PHY/TOOLS/lte_phy_scope.c | 13 ++++++++----- openair1/PHY/defs.h | 4 ++-- 3 files changed, 14 insertions(+), 11 deletions(-) diff --git a/openair1/PHY/LTE_TRANSPORT/pucch.c b/openair1/PHY/LTE_TRANSPORT/pucch.c index 58d08ac205..7963423311 100644 --- a/openair1/PHY/LTE_TRANSPORT/pucch.c +++ b/openair1/PHY/LTE_TRANSPORT/pucch.c @@ -1027,8 +1027,8 @@ uint32_t rx_pucch(PHY_VARS_eNB *phy_vars_eNB, (subframe<<10) + (phy_vars_eNB->pucch1ab_stats_cnt[UE_id][subframe])); #endif - ((int16_t*)&phy_vars_eNB->pucch1ab_stats[UE_id][(subframe<<10) + (phy_vars_eNB->pucch1_stats_cnt[UE_id][subframe])])[0] = (int16_t)(stat_re); - ((int16_t*)&phy_vars_eNB->pucch1ab_stats[UE_id][(subframe<<10) + (phy_vars_eNB->pucch1_stats_cnt[UE_id][subframe])])[1] = (int16_t)(stat_im); + phy_vars_eNB->pucch1ab_stats[UE_id][(subframe<<11) + 2*(phy_vars_eNB->pucch1ab_stats_cnt[UE_id][subframe])] = (stat_re); + phy_vars_eNB->pucch1ab_stats[UE_id][(subframe<<11) + 1+2*(phy_vars_eNB->pucch1ab_stats_cnt[UE_id][subframe])] = (stat_im); phy_vars_eNB->pucch1ab_stats_cnt[UE_id][subframe] = (phy_vars_eNB->pucch1ab_stats_cnt[UE_id][subframe]+1)&1023; @@ -1039,8 +1039,8 @@ uint32_t rx_pucch(PHY_VARS_eNB *phy_vars_eNB, *(1+payload) = (stat_im<0) ? 1 : 0; } else { // insufficient energy on PUCCH so NAK *payload = 0; - ((int16_t*)&phy_vars_eNB->pucch1ab_stats[UE_id][(subframe<<10) + (phy_vars_eNB->pucch1_stats_cnt[UE_id][subframe])])[0] = (int16_t)(stat_re); - ((int16_t*)&phy_vars_eNB->pucch1ab_stats[UE_id][(subframe<<10) + (phy_vars_eNB->pucch1_stats_cnt[UE_id][subframe])])[1] = (int16_t)(stat_im); + ((int16_t*)&phy_vars_eNB->pucch1ab_stats[UE_id][(subframe<<10) + (phy_vars_eNB->pucch1ab_stats_cnt[UE_id][subframe])])[0] = (int16_t)(stat_re); + ((int16_t*)&phy_vars_eNB->pucch1ab_stats[UE_id][(subframe<<10) + (phy_vars_eNB->pucch1ab_stats_cnt[UE_id][subframe])])[1] = (int16_t)(stat_im); phy_vars_eNB->pucch1ab_stats_cnt[UE_id][subframe] = (phy_vars_eNB->pucch1ab_stats_cnt[UE_id][subframe]+1)&1023; *payload = (stat_re<0) ? 1 : 0; diff --git a/openair1/PHY/TOOLS/lte_phy_scope.c b/openair1/PHY/TOOLS/lte_phy_scope.c index e9820d0604..e5d87223f0 100644 --- a/openair1/PHY/TOOLS/lte_phy_scope.c +++ b/openair1/PHY/TOOLS/lte_phy_scope.c @@ -172,7 +172,7 @@ void phy_scope_eNB(FD_lte_phy_scope_enb *form, int16_t *pusch_comp; int32_t *pucch1_comp; int32_t *pucch1_thres; - int16_t *pucch1ab_comp; + int32_t *pucch1ab_comp; float Re,Im,ymax; float *llr, *bit; float I[nsymb_ce*2], Q[nsymb_ce*2]; @@ -208,7 +208,7 @@ void phy_scope_eNB(FD_lte_phy_scope_enb *form, pusch_comp = (int16_t*) phy_vars_enb->lte_eNB_pusch_vars[UE_id]->rxdataF_comp[eNB_id][0]; pucch1_comp = (int32_t*) phy_vars_enb->pucch1_stats[UE_id]; pucch1_thres = (int32_t*) phy_vars_enb->pucch1_stats_thres[UE_id]; - pucch1ab_comp = (int16_t*) phy_vars_enb->pucch1ab_stats[UE_id]; + pucch1ab_comp = (int32_t*) phy_vars_enb->pucch1ab_stats[UE_id]; // Received signal in time domain of receive antenna 0 if (rxsig_t != NULL) { @@ -339,8 +339,9 @@ void phy_scope_eNB(FD_lte_phy_scope_enb *form, // PUSCH I/Q of MF Output if (pucch1ab_comp!=NULL) { for (ind=0; ind<10240; ind++) { - I_pucch[ind] = pucch1ab_comp[2*ind]; - Q_pucch[ind] = pucch1ab_comp[2*ind+1]; + + I_pucch[ind] = (float)pucch1ab_comp[2*(ind)]; + Q_pucch[ind] = (float)pucch1ab_comp[2*(ind)+1]; A_pucch[ind] = 10*log10(pucch1_comp[ind]); B_pucch[ind] = ind; C_pucch[ind] = (float)pucch1_thres[ind]; @@ -348,7 +349,9 @@ void phy_scope_eNB(FD_lte_phy_scope_enb *form, fl_set_xyplot_data(form->pucch_comp,I_pucch,Q_pucch,10240,"","",""); fl_set_xyplot_data(form->pucch_comp1,B_pucch,A_pucch,1024,"","",""); fl_add_xyplot_overlay(form->pucch_comp1,1,B_pucch,C_pucch,1024,FL_RED); - // fl_set_xyplot_ybounds(form->pucch_comp,-100,100); + fl_set_xyplot_ybounds(form->pucch_comp,-5000,5000); + fl_set_xyplot_xbounds(form->pucch_comp,-5000,5000); + fl_set_xyplot_ybounds(form->pucch_comp1,20,80); } diff --git a/openair1/PHY/defs.h b/openair1/PHY/defs.h index c0b61806a6..dc0b79e471 100755 --- a/openair1/PHY/defs.h +++ b/openair1/PHY/defs.h @@ -376,13 +376,13 @@ typedef struct PHY_VARS_eNB_s { #ifdef LOCALIZATION /// time state for localization time_stats_t localization_stats; -#endif +#endif int32_t pucch1_stats_cnt[NUMBER_OF_UE_MAX][10]; int32_t pucch1_stats[NUMBER_OF_UE_MAX][10*1024]; int32_t pucch1_stats_thres[NUMBER_OF_UE_MAX][10*1024]; int32_t pucch1ab_stats_cnt[NUMBER_OF_UE_MAX][10]; - int32_t pucch1ab_stats[NUMBER_OF_UE_MAX][10*1024]; + int32_t pucch1ab_stats[NUMBER_OF_UE_MAX][2*10*1024]; #if ENABLE_RAL hash_table_t *ral_thresholds_timed; From 8725038b0948140ea8b7149691875b55a1233b70 Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Fri, 18 Dec 2015 05:01:59 +0100 Subject: [PATCH 029/263] updated ssh wrapper timeout --- cmake_targets/autotests/run_exec_lte-softmodem_tests.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cmake_targets/autotests/run_exec_lte-softmodem_tests.py b/cmake_targets/autotests/run_exec_lte-softmodem_tests.py index b76b5f9698..aa35207e0b 100644 --- a/cmake_targets/autotests/run_exec_lte-softmodem_tests.py +++ b/cmake_targets/autotests/run_exec_lte-softmodem_tests.py @@ -1,4 +1,4 @@ -#! /usr/bin/python +w#! /usr/bin/python #****************************************************************************** # OpenAirInterface @@ -264,8 +264,8 @@ def SSHSessionWrapper(machine, username, key_file, password, logdir_remote_testc error = error + '\n username = ' + username + '\n machine = ' + machine + '\n logdir_remote = ' + logdir_remote_testcase + '\n logdir_local_base = ' + logdir_local_base error = error + traceback.format_exc() print error - print " Trying again in 60 seconds" - time.sleep(60) + print " Trying again in 1 seconds" + time.sleep(1) print "Continuing ..." From 60f05e085211a885a0c5a59e90db255c45f78e1d Mon Sep 17 00:00:00 2001 From: "aikaterini.trilyraki" Date: Fri, 18 Dec 2015 17:27:09 +0100 Subject: [PATCH 030/263] remove redundant files from rrh compilaton --- cmake_targets/CMakeLists.txt | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/cmake_targets/CMakeLists.txt b/cmake_targets/CMakeLists.txt index 1600d13b5b..537449b029 100644 --- a/cmake_targets/CMakeLists.txt +++ b/cmake_targets/CMakeLists.txt @@ -164,6 +164,11 @@ set(CMAKE_C_FLAGS set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${C_FLAGS_PROCESSOR}" ) + + +######################### +set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-rpath -Wl,${OPENAIR_TARGETS}/bin") +######################### # set a flag for changes in the source code # these changes are related to hardcoded path to include .h files add_definitions(-DCMAKER) @@ -1450,11 +1455,11 @@ add_definitions(-DASN1_MINIMUM_VERSION=924) ################################# # add executables for operation -#################################"" +################################# # lte-softmodem is both eNB and UE implementation ################################################### -set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-rpath -Wl,${OPENAIR_CMAKE}/lte_build_oai/build/") + add_executable(lte-softmodem ${rrc_h} ${s1ap_h} @@ -1490,7 +1495,6 @@ target_link_libraries (lte-softmodem ${LIBBOOST_LIBRARIES}) # lte-softmodem-nos1 is both eNB and UE implementation ################################################### -set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-rpath -Wl,${OPENAIR_CMAKE}/lte_noS1_build_oai/build/") add_executable(lte-softmodem-nos1 ${rrc_h} ${s1ap_h} @@ -1526,7 +1530,6 @@ target_link_libraries (lte-softmodem-nos1 ${LIBBOOST_LIBRARIES}) # rrh ################################ -set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,-rpath -Wl,${OPENAIR_CMAKE}/rrh_gw/build/") #Note: only one RF type (USRP) is currently supported for RRH add_executable(rrh_gw ${OPENAIR_TARGETS}/RT/USER/rrh_gw.c @@ -1534,14 +1537,11 @@ add_executable(rrh_gw ${OPENAIR_TARGETS}/RT/USER/UE_transport_IQ.c ${OPENAIR_TARGETS}/RT/USER/rt_wrapper.c ${OPENAIR_TARGETS}/ARCH/COMMON/common_lib.c - ${OPENAIR_TARGETS}/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c - ${OPENAIR_TARGETS}/ARCH/ETHERNET/USERSPACE/LIB/eth_udp.c - ${OPENAIR_TARGETS}/ARCH/ETHERNET/USERSPACE/LIB/eth_raw.c ${HW_SOURCE} ${TRANSPORT_SOURCE} ) -# assert and common_lib.h -target_include_directories(rrh_gw PRIVATE ${OPENAIR_DIR}/common/utils/itti ${OPENAIR_TARGETS}/ARCH/COMMON ) +# assert +target_include_directories(rrh_gw PRIVATE ${OPENAIR_DIR}/common/utils/itti) target_link_libraries(rrh_gw -Wl,--start-group UTIL LFDS From 5b5a3949e4bf0232c25527e9734ba3c57292faab Mon Sep 17 00:00:00 2001 From: "aikaterini.trilyraki" Date: Fri, 18 Dec 2015 17:28:33 +0100 Subject: [PATCH 031/263] minor improvement; device and trasport libraries are included from targets/bin --- cmake_targets/build_oai | 43 +++++++++++++++++++++++------------------ 1 file changed, 24 insertions(+), 19 deletions(-) diff --git a/cmake_targets/build_oai b/cmake_targets/build_oai index 6347b97542..ab1e84dfe9 100755 --- a/cmake_targets/build_oai +++ b/cmake_targets/build_oai @@ -275,7 +275,17 @@ function main() { fi fi - + if [ "$oaisim" = "1" ] ; then + # if [ "$HW" == "ETHERNET" ] ; then # to ask + # HW="NONE" + #fi + if [ $HW != "EXMIMO" -a $HW != "OAI_USRP" -a $HW != "OAI_BLADERF" ] ; then + HW="NO_VALUE" + fi + if [ "$XFORMS" == "True" ] ; then + PRINT_STATS="True" + fi + fi ############################################ # setting and printing OAI envs, we should check here ############################################ @@ -324,19 +334,9 @@ function main() { check_install_additional_tools fi - if [ "$oaisim" = "1" ] ; then - # if [ "$HW" == "ETHERNET" ] ; then # to ask - # HW="NONE" - #fi - if [ $HW != "EXMIMO" -a $HW != "OAI_USRP" -a $HW != "OAI_BLADERF" ] ; then - HW="NO_VALUE" - fi - if [ "$XFORMS" == "True" ] ; then - PRINT_STATS="True" - fi - fi + - echo_info "3. building the compilation directives ..." + echo_info "3. building the compilation directives ..." DIR=$OPENAIR_DIR/cmake_targets if [ "$NOS1" = "1" ] ; then @@ -364,7 +364,6 @@ function main() { echo "set ( ENABLE_VCD_FIFO $VCD_TIMING )" >> $cmake_file echo "set ( RF_BOARD \"${HW}\")" >> $cmake_file echo "set ( TRANSP_PRO \"${TP}\")" >> $cmake_file - echo "set ( SHRLIBDEV ${SHRLIBDEV})" >> $cmake_file echo "set(PACKAGE_NAME \"${lte_exec}\")" >> $cmake_file echo 'include(${CMAKE_CURRENT_SOURCE_DIR}/../CMakeLists.txt)' >> $cmake_file cd $DIR/$lte_build_dir/build @@ -577,17 +576,16 @@ function main() { echo_info "Compiling $rrh_exec ..." + [ "$CLEAN" = "1" ] && rm -rf $DIR/rrh_gw/build + mkdir -p $DIR/$rrh_build_dir/build cmake_file=$DIR/$rrh_build_dir/CMakeLists.txt echo "cmake_minimum_required(VERSION 2.8)" > $cmake_file echo "set(ENABLE_VCD_FIFO $VCD_TIMING )" >> $cmake_file echo "set(ENABLE_ITTI False )" >> $cmake_file echo "set(RF_BOARD \"${HW}\")" >> $cmake_file echo "set(TRANSP_PRO \"${TP}\")" >> $cmake_file - echo "set(SHRLIBDEV ${SHRLIBDEV})" >> $cmake_file echo 'set(PACKAGE_NAME "\"rrh_gw\"")' >> $cmake_file - echo 'include(${CMAKE_CURRENT_SOURCE_DIR}/../CMakeLists.txt)' >> $cmake_file - [ "$CLEAN" = "1" ] && rm -rf $DIR/rrh_gw/build - mkdir -p $DIR/$rrh_build_dir/build + echo 'include(${CMAKE_CURRENT_SOURCE_DIR}/../CMakeLists.txt)' >> $cmake_file cd $DIR/$rrh_build_dir/build cmake .. compilations \ @@ -608,6 +606,7 @@ function main() { # build RF device libraries (currently EXMIMO is not complied with the rest of HW targets) if [ "$HW" != "NO_VALUE" ] ; then rm -f liboai_device.so + rm -f $dbin/liboai_device.so if [ -d "/usr/include/uhd" ] ; then compilations \ $build_dir oai_usrpdevif \ @@ -622,15 +621,18 @@ function main() { #add exmimo compilation - + # link liboai_device.so with the selected RF device library if [ "$HW" == "EXMIMO" ] ; then ln -s liboai_exmimodevif.so liboai_device.so + ln -s $dbin/liboai_exmimodevif.so.$REL $dbin/liboai_device.so echo_info "liboai_device.so is linked to EXMIMO device library" elif [ "$HW" == "OAI_USRP" ] ; then ln -s liboai_usrpdevif.so liboai_device.so + ln -s $dbin/liboai_usrpdevif.so.$REL $dbin/liboai_device.so echo_info "liboai_device.so is linked to USRP device library" elif [ "$HW" == "OAI_BLADERF" ] ; then ln -s liboai_bladerfdevif.so liboai_device.so + ln -s $dbin/liboai_bladerfdevif.so.$REL $dbin/liboai_device.so echo_info "liboai_device.so is linked to BLADERF device library" else echo_info "liboai_device.so is not linked to any device library" @@ -640,11 +642,14 @@ function main() { # build trasport protocol libraries (currently only ETHERNET is available) if [ "$TP" != "NO_VALUE" ] ; then rm -f liboai_transpro.so + rm -f $dbin/liboai_transpro.so + compilations \ $build_dir oai_eth_transpro \ liboai_eth_transpro.so $dbin/liboai_eth_transpro.so.$REL if [ "$TP" == "ETHERNET" ] ; then ln -s liboai_eth_transpro.so liboai_transpro.so + ln -s $dbin/liboai_eth_transpro.so.$REL $dbin/liboai_transpro.so echo_info "liboai_transpro.so is linked with ETHERNET library" fi fi From 5f7e99760e92ded43456eaf130a0009a903e375a Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Sat, 19 Dec 2015 16:39:56 +0100 Subject: [PATCH 032/263] added to stop exmimo2 --- cmake_targets/tools/exmimo_stop_octave.m | 4 ++++ cmake_targets/tools/stop_exmimo2 | 16 ++++++++++++++++ 2 files changed, 20 insertions(+) create mode 100644 cmake_targets/tools/exmimo_stop_octave.m create mode 100755 cmake_targets/tools/stop_exmimo2 diff --git a/cmake_targets/tools/exmimo_stop_octave.m b/cmake_targets/tools/exmimo_stop_octave.m new file mode 100644 index 0000000000..82aa1f2845 --- /dev/null +++ b/cmake_targets/tools/exmimo_stop_octave.m @@ -0,0 +1,4 @@ +n=oarf_get_num_detected_cards; +for i=n-1:0 + oarf_stop(i); +end diff --git a/cmake_targets/tools/stop_exmimo2 b/cmake_targets/tools/stop_exmimo2 new file mode 100755 index 0000000000..6931229f7a --- /dev/null +++ b/cmake_targets/tools/stop_exmimo2 @@ -0,0 +1,16 @@ +#!/bin/bash + +echo "This script stops exmimo2 as it might be transmitting signal by itself if lte-softmodem terminates incorrectly" + +if [ "$OPENAIR_DIR" == "" ]; then + echo "Is the OPENAIR_DIR path set correctly? Exiting now" + exit +fi + +#load the module +sudo -E $OPENAIR_DIR/cmake_targets/tools/init_exmimo2 + +#now we stop the card from transmitting anything +cd $OPENAIR_DIR/targets/bin +sudo -E octave $OPENAIR_DIR/cmake_targets/tools/exmimo_stop_octave.m + From d3eebd0666a51216bea9c606778725cafe6fd0d7 Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Sat, 19 Dec 2015 16:42:38 +0100 Subject: [PATCH 033/263] removed pre-compiled exmimo files as they don't work for different kernel versions --- .../autotests/tools/exmimo/exmimo_stop.m | 4 - .../autotests/tools/exmimo/init_exmimo2 | 85 ------------------ .../tools/exmimo/oarf_config_exmimo.oct | Bin 810413 -> 0 bytes .../autotests/tools/exmimo/oarf_get_frame.oct | Bin 777802 -> 0 bytes .../exmimo/oarf_get_num_detected_cards.oct | Bin 735262 -> 0 bytes .../tools/exmimo/oarf_send_frame.oct | Bin 797986 -> 0 bytes .../autotests/tools/exmimo/oarf_stop.oct | Bin 742713 -> 0 bytes .../tools/exmimo/oarf_stop_without_reset.oct | Bin 742881 -> 0 bytes .../autotests/tools/exmimo/openair_rf.ko | Bin 37218 -> 0 bytes cmake_targets/autotests/tools/exmimo/updatefw | Bin 48769 -> 0 bytes 10 files changed, 89 deletions(-) delete mode 100644 cmake_targets/autotests/tools/exmimo/exmimo_stop.m delete mode 100755 cmake_targets/autotests/tools/exmimo/init_exmimo2 delete mode 100755 cmake_targets/autotests/tools/exmimo/oarf_config_exmimo.oct delete mode 100755 cmake_targets/autotests/tools/exmimo/oarf_get_frame.oct delete mode 100755 cmake_targets/autotests/tools/exmimo/oarf_get_num_detected_cards.oct delete mode 100755 cmake_targets/autotests/tools/exmimo/oarf_send_frame.oct delete mode 100755 cmake_targets/autotests/tools/exmimo/oarf_stop.oct delete mode 100755 cmake_targets/autotests/tools/exmimo/oarf_stop_without_reset.oct delete mode 100644 cmake_targets/autotests/tools/exmimo/openair_rf.ko delete mode 100755 cmake_targets/autotests/tools/exmimo/updatefw diff --git a/cmake_targets/autotests/tools/exmimo/exmimo_stop.m b/cmake_targets/autotests/tools/exmimo/exmimo_stop.m deleted file mode 100644 index 82aa1f2845..0000000000 --- a/cmake_targets/autotests/tools/exmimo/exmimo_stop.m +++ /dev/null @@ -1,4 +0,0 @@ -n=oarf_get_num_detected_cards; -for i=n-1:0 - oarf_stop(i); -end diff --git a/cmake_targets/autotests/tools/exmimo/init_exmimo2 b/cmake_targets/autotests/tools/exmimo/init_exmimo2 deleted file mode 100755 index 66eedf93dd..0000000000 --- a/cmake_targets/autotests/tools/exmimo/init_exmimo2 +++ /dev/null @@ -1,85 +0,0 @@ -#!/bin/bash - -################################################################################ -# OpenAirInterface -# Copyright(c) 1999 - 2015 Eurecom -# -# OpenAirInterface is free software: you can redistribute it and/or modify -# it under the terms of the GNU General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# -# OpenAirInterface 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 General Public License for more details. -# -# You should have received a copy of the GNU General Public License -# along with OpenAirInterface.The full GNU General Public License is -# included in this distribution in the file called "COPYING". If not, -# see . -# -# Contact Information -# OpenAirInterface Admin: openair_admin@eurecom.fr -# OpenAirInterface Tech : openair_tech@eurecom.fr -# OpenAirInterface Dev : openair4g-devel@lists.eurecom.fr -# -# Address : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE -# -################################################################################ -# file init_nas_nos1 -# brief loads the nasmesh module and sets up the radio bearers (used to provide ip interface without S1 interface) -# author Florian Kaltenberger -# -####################################### - -load_module() -{ - mod_name=${1##*/} - mod_name=${mod_name%.*} - if awk "/$mod_name/ {found=1 ;exit} END {if (found!=1) exit 1}" /proc/modules - then - echo "module $mod_name already loaded: I remove it first" - sudo rmmod $mod_name - fi - echo loading $mod_name - sudo insmod $1 -} - - -function main() -{ -PCI=`lspci -m | grep Xilinx` -if [ -z "$PCI" ]; then - echo "No card found. Stopping!" - return -fi - -## This part corrects the wrong configuration of the endpoint done by the bios in some machines -echo "$PCI" | while read config_reg; do -SLOT_NUMBER=`echo $config_reg | awk -F\" '{print $1}'` -sudo setpci -s $SLOT_NUMBER 60.b=10 -done - - -load_module $OPENAIR_DIR/targets/bin/openair_rf.ko -sleep 1 - -if [ ! -e /dev/openair0 ]; then - sudo mknod /dev/openair0 c 127 0 - sudo chmod a+rw /dev/openair0 -fi - -DEVICE=`echo $PCI | awk -F\" '{print $(NF-1)}' | awk '{print $2}'` -DEVICE_SWID=${DEVICE:2:2} -if [ $DEVICE_SWID == '0a' ]; then - echo "Using firware version 10" - $OPENAIR_DIR/targets/bin/updatefw -s 0x43fffff0 -b -f $OPENAIR_TARGETS/ARCH/EXMIMO/USERSPACE/OAI_FW_INIT/sdr_expressmimo2_v10 -else - echo 'No corresponding firmware found' - return -fi -} - -main "$@" diff --git a/cmake_targets/autotests/tools/exmimo/oarf_config_exmimo.oct b/cmake_targets/autotests/tools/exmimo/oarf_config_exmimo.oct deleted file mode 100755 index f8c24153f648cb6f0211defd9f958dab8dae92b2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 810413 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%0D>298x*HsT>W3fXgJ4 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

csiVMVliTljalNssur==q( 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 ZZLE@TqF-C|`QM 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%0DSRTKSjL_17r>ayIU-{L{TeEC14? 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

    YfXNm!F#maZ~x01Fv{c$bUv%TDS=~b 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 X8o4qakjs5L%Mr1-!Cf9ZKZ5@Q`nDGJ diff --git a/cmake_targets/autotests/tools/exmimo/oarf_get_num_detected_cards.oct b/cmake_targets/autotests/tools/exmimo/oarf_get_num_detected_cards.oct deleted file mode 100755 index 3d84d86ebad99e6997ec6f86e4f09e8cf83be245..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 735262 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

    &fE#W@{W}*ZZD_ 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

    TkWRd3mbwKWBfwVE8(Na$gH$4#edt98jIk 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�vg!*Wj<;EsAM>4>{7HNLrI5r|R)~t4R_9cx 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

    b1&N3QPE`G+{2wAs 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
    JSIp{gqcTjQdQa}xxOat?0;irX#XJ^ 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%0A>%Ia?TEnXmn?z0D_`%`1SS7MtOwP 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 TItZ>6v7_zR&Z1&-eXd^EBOc&hMN$ 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

    !E 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
      }$?aHTfllXLgEuX$Rj#J+7 z0Qr#5X{29Cx=$cy^b@pkT##Jh3<&7nOqW{6b|H zB5&cnmjcouPIouNC4vs))>DznGh8kRatOLFL@*bk=X#Pu4M3< zI*OcmWM0@aS@0P4Y{^+b=51i`y<&;TT(Nx+S!Aw~OXKJiw;LzF7Hjbhg{${FD7{=~ zu-$)vE2F#*{e`KYiXwOLv6m}Yc0qlMqJ+DG}r9 z>-`bXCS#s0k;0Wj$_2OyqF9RDgOlI&j+~8a5ggsw5U#-#u^N+HL#FUGjY+Pd^ZA;_ zB-aNk`8xMQ@JB4nN@LYm_)!?wsHJ?J{}rxBQ;(H*PK;|KFtoa z8rM8ZgGe*zCK559t^?8x!#js-!DZwuqsX@{f&>;d{RrjJ4^pDouD=ZtQH(NBEb)p% zM8t*S@lfo;&Qe4qW+){^@ga90zhiAPhxivdvi2T`Xb$dct}5KEAnL|9;nU;P1|_!)ai6h~lb0-iymD3O06QhT}uwn(Xsz;|un=*K9U^B;9Z zOGaRC6L51Tv!=z`1K0KD{`jF|)Yt@|ADRr2b=t2Gy4Tgi z;vHkj28W=uTmpx+tA9N1mpEJ-svb@1Xo#Ny|K+1b#2$qQG-AIT4Rc&tlxi>z&X$TG zycd<8AuH6uFSsBfg#i~gDWc@TUMTTi#s=hs&}t^4lE~Q<;Um|e-15j9u!<6?H%J4C z_%jurLJP=uS}JrJkcEUk2FguYgm3y13JS@U_yB`4xef3xTR~wsR$ayLRwhLy)aH30 z-`eQBFHkonAjQK9YR zb0yD7rKgC9TRsT*1Uak`cIL5gDqA=G)A$s5YMN8ju<&|>(?5+*m%#(@3t1LURj=w( z>7OmzVt>*}7S8GC{CVae&^2FnKCPZH>xje2qkkec?ss&{i*h^G_wNUE0f%ZW7Dtss zZ0lhd1dhw)Rh;53NI#oIQHsZe4Kfct%%?%2^xSGFu^m#n@m3pzLp6dB3Xa$&BN0;A z3|0LiEko;NSp-+NAO{U13fd)`BDjYS z6&qv0AW07eG|HCl6M^zSZNzArTj^%GO1HmNMW8*0nyU45{rsX@e3`E?*(eVQP+ov(QOu;s`>ZpWU@sQ5v^hMBksTkHT-&{2D*HU!KA zw3uMl9G2w-G8gYyni)d^mD~--aa3nu&SpoEGWg9A zYUrJS_q8~xGcaeTqYB>PnKK3WJd2|`1MS!tQCVg@YbeeZ;Cn5Oiic_fS-DxU=s!D2sj|47W&(r=#h5#2-;DbX@ZQudpa8n?!Ndb`DIZh1%m(%yUD9Lj7oBTzw6_5N)kY-?@LUX!P0&X z%piFn?gHlf7MqJhHSyj%(4F4(+leL29RDnkKDLOgk^YG=CbsiidDNja?gQz#MI?=i z6ER-a&!uC%0sJ=~j+(`U#bJ@MYp!2?JSRBT0KAmuz~Pl^uS#I{M!#~o&F3GOjZ$HI z*96H$ERhqjewAbC37Ls+k@Kn!j_Q(Mza$;i3eb0^B7)zlqip={=fWhPBRCJ{gSW7~ zDuzW2|1Q^bUo+NVr3DU^bFLWvrr-`sfg$t zl=q*GhbHG>CYT%F!cLik4*uI~>Kq&e{rX!(>`A98r=I=;&9U|w=$Y2OnQ6`j{nH71 z-+!n%^m;(A{1y?b#I(p5|2qwJ&Rc>$=q)1lY&kqC6Z+~RW5*NKLZ*Yg-jd)v+yA(~ zgwKJ^G-91G_a9XwUx0n(EfRKxcyb>>BRS@O;*3Ct zF;l=3%*R#!LF!`>y%M^4DH571Ab)X9oD9-O7SSuAM2u+Yn3GB8=rfQ`TEvtIWwqr3 zN?z1zZ-M#vO|}SQwXGd#bLlpc7XGhnINqrG3QN#aTLsM7qieJ{NR=$2S3-#x(baJf z8@Y4VTY%KZBBo3zs~r~5X0k5P$zXo;CR>ED+7XV^*dU74eg@JJi|AFNTPmWBE)D2) z681D|dRIaE#Uhfd?jB^tc5Mr&SPCx!=!Mb`Q~8WI><%x&h!Zi}ad)idL;){naV%x} z<(JtXJ9f`hMhn>l%z>$}y@wu_+wN#s$DvX(9WozTa#UnGB}W`IV#Zg&1kLnwNHpkxti;aR>}>?L<|M%;=h3$PgnVTpc&z z4ib5Oz%4|^)-l9Z>2jTh2VA(G?J~qz!}URakVZO1+37GVJ0m+ewjeoc@a8C8ebZp^ zgKNkvB-=Hu8X4I4U}Vhb`rrr}tSd7tT`X9<4hWIcqe<{J9z0N83Llraj&&sQY@?A& z*M`NE1jJ%ABl3i|gA8l_sD8 zM3z*yTPvkSJBTc;?rK(fj^+?qM%_7OrRS)^$hz_;a=FT&!zhSKCsCh~4OEa(DF^B` zvaz~zRx$?Tu9>MmpAPBZE>z*6puT-!_&*3@2dt%iOVHVGG zOcGCKK|n4Xfju^uU*)|;Z?3^#!ahWRv`Kk&T8ly^xLYp0pB+%8jW+#pJIrTME?w{!*K*wWLX&r*?4Cq%#}zsCy+dZ zQldpTqh+0iG5;gkGC&e7*;tOZlJld#;P^ynTT@PDCYFV(I_F{x4qR?bX# zz7a*D_S`sBy>PjQZ)gchva|bLr6mvGqA4iT+90{hod@eXL>)lYaL`#5V-QzwP*Vid z^q*&ljCt2PC+$RGaVy#6tV8h@;bv0WFBvRRnydN~r<{SiMWiSR9Jd#?)hRb2e7}X! z=ap{$#!?CIb;`2EoT4Mag#Z;JxDRO#;|jgt%(B-|(zO6Ju%#Kk=zOn|mhK9uwX@Y zK#InKFZYram#%OK5j~?JgHVQ!0($+fL{UjlP|7X&0xQ&Semzj689Q-T9mQMJC_UF zxATthdmN}axq%l+!Qoaj-tQddFRZ5;@OM*ixYc~7=+wR@pE|VTQ}Q4_b^MS| zomTRx^KL$MImf52zwxPC`uil_D~eCO>+-2@Pd@dV#;5+<`84npp9bCJ)8L=^^uByR z;=?oZX+!}&jZEaz=p;Uk>Bgt=Gx#)N5uYY*#i{mpSdI}@Y35$6;w^v)YR0HKQ*fQ8 z_W*~8s`vOI8e^J^FK}I-t^@Lu!6vFz^o5asc9b?`#N0K)_8*iYS4-k3>|<6&QiKB5;5Su&l^17L(|xHp~5;VyubaRpc5{ zBFg47Fv0dT+W^3|tP@h}+T9DYagp!u)fgK*&0Fq61~Ov)>1jiG6wV#@9KzG`U!*L} zX1x7-+8#!5K$_n$ef6}X>x^k!L~l>mS)E&m-pcVa+}t0}1*K!vJ6PxgC>V;}bfJMB zl`(63jQb)4(1nP~kq!~`Pg?;WrQp7rB~gcgp_^w&mQZXFM48CfsXLNTu+3RYcQW?D$-PYip9nq={lh9uJLd@b)O5$A{>EfkUF6Pdv8F%UNg|00SN!Y0?VWrLDIM= z#up+e8WYyYLS@3E(0mG&&CjQD<7w?%p$hBpA!}rzil6Z*@hqPz-RDzf2l{Gcp(3?49Ltgga-$81QFYBb6eyndka#T;OSQS+1-X!wAltmF9 zZ(^!S(+^pWfw5xCsz_#CKuIPn;@1^|)JRFoj${`E_p+e8Q9ES-qNg*J8l9u{nes{Z zR2)`=U_%U*ya@UTRa5gdKJm#2($wQ>>zBonDWMjewCsIn4im0r|w zS(|TYnO@WhmXwLKPA}@De0_pwv`{bVOSuevLMGBmy{J=i72nYE+qri4LJhf zIFlf1ad2is&O^`&GuZtZ%N4}EB9u1dF5H~42sv@Z+7(r4uL|o2!tYzGJ*0+r4k@zx z^k69t;$Dg`kUBazg-nSjcW=}IqiyRIw4@cB+p$%^I!CbMFdjlUbjoR&N>m|7cG$&P zIucL;f~kZ=7{jrSN0TuGlXOKu)d*Jkrj;B~9UMV9)dDuz22e*ErbRAMT^#v-LKh?H z5rD?oFs)*V>gk9}(C|_~t1Os*Sg^>tKVU?ZyAgVl5Uw|_7iw4{Z1f>?f@O}KBd{+h zmFz8$?wLdluXSX-D#bN|#Sy&!2iQ7 zThj5vDDHEPq47}M48a{tN!9e@%WZ@92ae9Afxi!Igoz7YAQAP=L67esEqP}Sk#BC9PLr-o#zJWSgQkX>ciovl^-x_uk&$rDCz;iV2eck zPw=Xss58z4I635pz-F7ch@Uzft>L!w+;%|g5WL%jRIZdflZ0R8O(2~G;r5#(of2l| z^-EV1-TE0=nU4A7pVTSElxdN^C3amb@@w*C3=(<4jJDW3jKxpEi*Av$vd0F*TLoAx z6BqH@vN=SNoHAw&vfKv2-Au@>l3bc5%j^A0R!2fc0vm7QBL3G~c%HYFX=+02A_T9n zp&@vRL|yd@?1F)ICxVZgklU`g^hHNQ{@jK~Fuz|0{_riFc%IIu@y}5nq}L#1!6QU< zBW?%QKN0_!T1*E2&tV`pqQENc%Txu?1C1pr!vCKHjQ4dxXy!u_@k{fg%NOx4bq;p% zp1|I>a4wCvJmK;!#w$ud)G&G|rQylVL4I9vZXJOl7(tIb=k?0C97q0SCqL=N)6BDO zei}a}UIgJX#Zr+zFKWnvQy(DUPcu-xeq?7|6V&4Lv)56(vct$nPJ<&r&k=*t?QTek4wPf=AkdE#)!F8&L&I!_h<*EHF$`xn-u zM_p`q5{&>yU~W>-kOMDuMnFF^(9Nn9{mN*BerO?4oc!FlSG9BNVI8L^jobA&wh*l- zF;wl`9rg&xMc{E9XKauw;6XpUL&t)A2fzaYIX$X&e!qy zpUL3N_2t?1Q)Y1o{OtOti=_zKg3-xu+C>Zy*;}N=OG}oy;SvLl`u3}jyZ{y7lbRPa zysFTC@*YC|Fhkw4BOvn)<&_z1zM+h&0(C|E7K84D8_NxTA4#}tUevFrK93Oj>h;94 zsOY@`;1#BXh^&FI+7*3BFOk$Pn}xn#FsXs+*umP|34*PYW4_1j)lL*K9hr4Kf$+TvVfnQ zl2IN|6@pb6?3jTR+?As+-(=}lfI8UH3_p-Z@Wf>4VSvWi($~{M`6D@cwp7xK0ex&s zGyGUin5d=q0s6w0KI%bJd@Ao0cBtH426WSwX80eu{-hx&r^Y{kUfa@t-$X+YM(k9n zq_dvG6dZ@Hdxo7x$6^j89S5i^!JO~LJ>k*!1Q>n;9byqFZwg2iXybMtq0rq%jjZTU z=>0}N8=}ouQk=pFqizAIQuy44IE8tPo@)%1!r=2(Tx=LDV5D0h1*OY~CP<}_p+ZLQ zW4bnK*-~r+j5earI+RpLTZ*9)#&rzY+yX{fQsD&}qy8fOUavAlyM6c!3dkxPTmkMl zYT!X1APwQO+MuQq{rbT0LcA})IpfO<-@O?PX^h`+bZ(;j2>4HnaurIHzVN}Vpz5Mu zaB(N|++RUG4i%*r@AypU`_oaYtW%tabO~^3SUf5YE)%sBCVU89p*-oF_nu%!NkDBu z?Bh%3r$G4Vb%;El^IjpPbP_moES{p!r%s*(XZ|ayQEmdf-=a{vP=iA(O+h`aofVMn zuYg~%INa~UJEMVldOLT2hV3XJ^aOCg1v8sOVKqAWOdjc+y}}`=1R_9;B{DU1Zqn+X zN?`XEh`k4kOKqH4XL;Fz#EdN<=9AgcL6|L@Y?@WK{{2Lwf|avQk~^q<-qpI{KNDoBmrLX7E5=E`?vX1OuU`Bin*bf%Y^8DF= z=O_QC6ND<;KY;&haX3FJj(Uz6+tKKQzQwEuhbmx-!|fGOL&ptFfMpyA)hrU1j8|&^ z@SoEGsc8X1cZ)rt*bY1ic}s2ex5iyMyVP~u8t@|T*J~hRj%&?f0BaJjmE{Ej;+7wT6BMhF9C3< zobw|mj5&QBtMEAj#}y4cfjAtO;`E|XaG)a$o&!#E67be3^e|_LBiB}7jrH+xBlZ03B)-B{4{aA@;<#5@}Ae#p{Sas%O8P1 zG&v%nCzjEWjXa?Onh#%`t&LaXU@Uvgb;96L&9=5DCFYYNsTdZgmB~}YA<8tx>aw6o z82FNY!lye)SBBuKz;|$oZFmnhqUiU2xPorgy*RG>5-Uv%x^#5E+DIyXXB*S}=uT{& z52jgubZ2$FG#2zOJemgI>yGQL>Y66>(cReH5=`^?=n-56{B3>oNOeuK`RGwRp7E#s z(PMagY0@vbzlfe9Zy@5kI0Ea@K+%*#=g6lB@w=o$)zhO9;X$(jDA6xuHW2b!q~?UP z@jUv$zvY~wE$(Gmz}0;z{CtQGlMnqIVkor9w!k|PrxR%ibHPIpokPMzEG7^<63}=X zrk9B5cVxjf_!%sMmjPOB!}N5C_Q)UbjUl75K`;|D8gG{Q$$k)sM}I6I(sY?wy)=-x7*svhCv0adVJ8sVb{$lxSAl1OF^mm7X0m1^cmR;_!<>aN-B3Lep`03Ai*Jhd=U-b{rZ%5uzQ3F22!@LpR@O z$6+SEd7I;qqL!xP@H&!UISyatH^j-wcGc^x@-o!FSA?++*^*r-*Mx2%~ae3cdT7eEyrO981GoD;-p494u2|Rh?}^Vr2$v= zrI?Px1tG{^GhkgT+=|F@9Oj*C2uhh84bns+(oXA^<8bO)_^t_F0cfqM$8sFj`v?t? z;6s3pThhui7~tr*A75`1d;`#3OIpF19KT{E2ur^L9HtQE6*H*k+Na|5=X1OfZMYsSJsK7Q=%P*&-#KH4OY!mn2N3)hmmkF$W~x>vDiF}nU2Hhc}5q#N(wBzv3G+5t$L-1=8 za@#eh9fvFMZewJ|@SGcmR}WDse-Mb_A&vjM@))2?fl$XHabvOmS&qY*^T2EeR$pJH zQl}k3nSlYoAWi1$+=6M4E#rVKwVxvPDbE{=MtHq^!n|nCTGy_9bNn z0mtA7+(1#8OUlZcA?~ddEQ0DHz+6&R1Inx=WzR{owWO>QLFSS&%D=Uw>}C#!=nq}S zVrcr9)bAwC=901Sga;zm~eg4K;dV-$=63Bnx zVV2fQ%H~eMwnac>7@%A>%*%Z`$oqq(7)Wp_K;xiH}X0R$K zYf0H?gnwvas=oA+vTq8YL976@)`YDkW!JD^TJA^iVGE)qW6hB?I#a39d5k_&KIxu{ z<1PIr=n*O-sX{~iYg7Tv`<-{l+2}-*A-``Bd3^Jga^eHNf^Ak}R;O357W@PSs8_G{ z#-+J>wIL|Ya0E6ZU#DKZ+8F_Z%|PW0%>EK^vz_A|VjO@OCa8)4sf-a611^dQQZIrc zK=E6TS0MC~n)lF4n!MxPOHKp6Kw8F7yk=Lvg^*v&Q1>K;bXR_fU>EeTfbPo9wrCpY z%25c{owXh=xwCG>g~*efjCH4jWI69p*5E!!%0X6L% z9IQ7815J`>=6E8-7~D=XgH#^>Z(r+n2$;UsEXacCYkf%B`TzB`QgO+kr%-A7S}!2s zmala>-)LX!T)xr1R;p^5sC}(exR$SV65nWF>omU6zSh}v6GrP_;cIPj*%058#)%J5 z2si?-;m-24PR8Sb%22Kaw3*;L3~OI&_pGQogv#UicgBXbuk}i}A+jLUxQl;36U@p@ zUu(H>7-Pjl1k*u~o7k4GHMFu*iRS@c)Z$RlSiaWX8K9#wuzD7*bZB2|&o)x&=nTA{ z#d(M0(Z1F!FJN(pQe!IcStiHwwXT>h#T8VIu@TTVf>jx4Uu)^s4kdjG&{wv!_O&j? zF9x#o13|>Yt#`PU+^!0DA$&+^_TPxmC|T}l$7?h z*20n$PGv1yO8Z(@t;W6ql){cSqzqg)=xe)1jS%1w&T*i*6CFZRU5l( zDeY^`S_NyMNa|}_O8Z*Ne5~v6ktJpNTIzMJ)#zSbi<1gjbh&cwIzw6FEf91O9LUJlLvkC`H~e+`&wgG!^REXQ*gwuW_}e#`&uu+)k}>sE8qeag=$z0 z4yLd5*D?716?ip^!~Nd$wJt~lYZZiA1McrbVKu(K)`idU(J;tUL0my(>SWxc)jziU zhihN!gfc3xdq6yws%GtLJ%;7ir1>WhU!@1s zL$Bp)tpP@o#d<*m%h#HW@ZKh-o^YnGwIE#ZayLf!Nx6GzSe3Pw6AqD@Xv^& zMj`EMrC)BRvX*B6eQm0+e64rd8C(YPXF!iFY2{4aZ4A$+YD%X49i0G&%Dsa38&l%7 zbQGYX1gp3m72tz9V(h9QMI(y4I-t6iG@IHzCyei1=oJKa0@TBnW@qYY^dzqcytc*RzGV7Z%OyHh#Uumoor0r% ztz~Ly&LrRqEe;PHN}2Yxb~&T^uKX0F!*3y)zSi%8r1%c_Egz2MYaNx_5KjU5;Z<4X zi{qkymala**_pC|K=0FvL=DXHwf3BYIe0vcFP>xptG zyy3v6SvbYv_KK*X!*3)aS_#5u7Aa+F|L{-044O`YaLFRQ>1!Pw1=1rBo|q)d*ZS8j zU9#>c@PFb^IadBg?Q4B!7^av=o{R>bKpY;U6i547Ct>*+H@GC=ty6Hcul0}ly0;Am zK885lwD=KW`dUw%(Qz#XzSh#CINI0xRWYsS5b)C}^k`q}wN6^kkHCLRp-1~#vzIi) z$JC4i@GmnC@4RbY>xmLb25}1EUmS6~@~(ZYu9w;?Rv&m{las>NO4IBF^0hvH!`Dg^ zX_1szz#)=mtb?1i>}$M%Zh)SkYnad{t*roG>sP(tiM^cxO}FKHaGS)m>F^xyXyj{+ znLsS|wZ=@|4JqYojcKp^tF3O*FQU1W9D)_^JeBT^LhLWrrCYW0v@iK^k~~##4MLBp5j@LBhW=7M^g@6 zFZ&{7v>B=%C+P?edX0oD(d}|R2p?Od%sleY4iPZ{vO$a!J5r*9?gM^21&3Y?VoJ&@ z5!mJp>f{aJcZrjWRnQY7rh>fD7`xvfRKCJL=U-+D`J<(n8geh}i{S+40F;|xmgYx7 z%)2sec31)kE(0jhl2&kY`J$6kNjC@7){^E&LQDra&25MhBs~PsNK0D5J>=$A4pD*N zg@BgX()37(87Oa;g%^_G-GC0*(hQG~57tQ~{XL*-wlqC4Vm8YMc%9b)Aq-Hn>lPnUoYGv1t$>R7L z`%B5Cz*d>K;Q3HY4#y#wqMlIe{v6N|f>rCLwFNPG9SdU}B9QWW70_)PrlCA0*3klX za4w1$fc*b4i-L2&j^>!kjwNLc)rNBc_YlXf0Crf%)OQpQcBqo51iWqv4h{D)tsUi> z>9{%p?@JuJP4I9Z)6?-sUESNJ0H2pa4-MrpgB@R@);P^ufbUJAhdHAiKVVYNz4ja6 z*Hh@Bp*&`;-b&f0t^l+aYcs}CTd4I3ykC?8OKwx=OSQ~82 zMKx?)q@mV#Ee((FL7NbDzJ8g}6brU_1_f_1B(B(x?@*jc_3=r3J2L<2FXGpNy_uqX z2;8(O?nl5GGf>$S%e@55HpL$R{AhwIk-j!Xib(`@0mUy#puuKuu@uh5EMxL`8|!i* zC@+q{ET4mI+7x3EQo#&$XJbg)6ze0nxe2Lg>m_|l>O0F}2-h~nmAGV^;%i)pJnyeE z$fh{UJCvhz*C*xheN!@*kq<9>3lhl^hGj{%gWx!V&fo~F>7C502)Sp5Dov(M@rfC% zk|^>m!>1dtDdvBf!lp>&qil+Fg@+UbgDCYi3uYpTI`U9}^!iTYIw>IhKiCwBYuOYh z;buCHz{ZpX)26r#AzRE)^{{L~xM@@T9^OpHQ4mgJIu#7+IC1)YS|8{5G~tbjkI)Qey8E48}mC2x(U;^ z!%n|T?0SH>jw13?I0Ad(&axfOEZ`JWR`L#@2L$(LSlbR8HFAos2$jYwy#L_Pu(loM zxC*ZoVB;M?`3Yv_rtR?C>#&)XL2xw_aueIK9qyQ_#oGYyW^t%!EZbrEtI#nL*c1y_ zI<)ODN3@}munPDVi_?bKOEE2hX5V7rM2y_mA_QdHvrwWq)ppl{e##- zo0Oyag_{f1v>k45;#9W7>^7urhhg1xeUv09Emed0oyITN!G%-XfFR1XWjnl*tW(FITKUqp!@<}^k)@&t;(VF5!#(fAII$03KmniI|RRodK7*b&4Nu3WSE1tF;*6ibCUJN*8ES{oh+hN*@ z4sOy(fICjC~|Mj+IILI_Q@m7ks!tq`E8ml+hKJu>Y6I; z?=)H?sFxY6o?qj+iFAc#%XT;pj2RYdDiJK(;R=LrGBNeEHf@Jvevx7p$nqHQuS|}c zuqUm zJ8X&%HCg&Fpp&+=wjF+3&!MDm0lH^PYun+u6WU%O{G{;5p^HV^4g)^HZ>?iCAaeoA zYs1=hI1a0L87>D1+s|of({}jkIwr}@5Zr+vdTzR@nk?Jl&lrMY=t({d_(Y4teaW;P zmg%TEfm{K6Qwol@9p3U&{ahXc{;kEKB3FGpOxq5#P15!BD@d>2LNslMe;$L+AJ2{) zI8?$(nPoft=Nlv(P(>fu%^YRdEA2S?Ju=@Igtiumh8N3rxN$X#bs(@&7S8gf?QkaE zRJm+F0>0Yfa6dL}hXqQY@b&^bW#JTu+bg1mjv=9l=mrSCStKqQuhjnGA3FskrwdL> z94g0e+75U8i0Gm~C~A@{+u_0xT}{;iH8f#0MDfcczS9W&M-3#hJMclo;gQ70c9?A} z-r1ceA1xMQsJL9#AawxY0KS&&ITKvc{ZHMdd%0wBImw?}~^eB$D9m+IX&r9Gg zOgz2yXxrhas#;G3@PfqQG%G#Yc6g^3zAd3@_$-r?!gfg0Y_=VqfqC2a-I6BKBH!`Dn8tdR(A-(=1hSOwb*NT&wK}Jf|v-Q{v}Eg52A>9CkfBB26*`=^H~W{%KOszwV&S*^WDetzyQyW zk*IZ55x?`^d57A=k`f~uK~C4iJsR*-P2B&TE_ofrL#_$h>BI9IS0-1=V|sO}djgB1 zJx@M^iaiv4(Qm0zIPlp?1bkx#x)?8^q(1f8W7U9-vi#)Ur{oQn&p31B{eV)*eU~ zLOH$RjAoV%flh<$C?Hc!RMkp2Z4ctfF0X7-3RVH$U{ZuaBjw?ZO2J_uXH8Tq;A-{A zKkuk|y$kqvqEO!4)wl>KZr*~zQ$)_luj?OmmKBE=&#u@qS<1mCU(|soL<~l%q*3@P zH{Xd4up}33LtR`ObEx`+UKK{y=BltRp!6c$@4Q6$>Q!OG5irdRbms@c|7g)yj38-T z6ypn#^sJd7{MJl`(IKWy6$}E}@=s~emj6$o>1~#Ovhf?^1&+W4)Q3#Ve|Lm@V1}y6;8NAckZ{xTKNEz- z7HJjXJl})mze*+{HXuOm0DdS1M_c}HHjv^UsFObczd@X>tU_DoOIpD_WZ)N=BoI6s&_Y{UTmCzLsii*!wA+@}mj99m97_5Epzm#IZTUZm zPr}&p|2v?+Y*<_Vr~HV$Eh+8{8Keltp-W9${$F4*AHziem9SxL`H#VTZzt7D9Y9S9 zrebmLr-Bdq5|yDX|DU<>Q%=Mi0M1BXp0@mdfmf)*L|FiMB~hsQw5o5R%C!71!Z^%x z$S*)TW9d4{ao)0sA6LuYIHN(wESnxPx;S?)Z$P%Ad+SI&vZ=}LUG{b zEDq<=wES=03LOoBwYPANh!yel7?%Im)nVBm48jrC*mj6Br9Kw&P@jF0QZCG3Wr=i{{CGsgCk;%*@=fJf5f09S{fH2^B zh+|iPY55QTS(ijv;MG%bwB^4jR-bcRZGm?uj@>3q%m1*N*uIj|GYm!z~QEFkdH-+#&(W1?0tj$i7md5O3;Jo?!6V@-&D8~=KQ8cH$-eZf>y7N1xVsiDn zld0%h^nnd9N3f&jw4mUlIrXo6Q#T|i1anvpf-~p_QSdg<0gus_5(Egl2xALArKk% z<%1I{kQ@Pj|2K>8BTbx}U8OVGl~+RG>qbfg~L^@&AP4K}#Qp#+BtwWrJx$zqs=BD{?aU5?xoI-!oF*@5EKC zi)hsMJ8_9gbe(nuYBa8%JcP)O;|P2Yp+bc=kl!KXmKo}9!w?o+i@3(}F@j&3kg}(x zE070Jvnwy~R0blmAZ@vD1a^d=djW!kqO|OWPm-q+B@S?+MOnp^bQkdhP3_~bwt}_1 z2e>OyC}r;cpt$=XM^3_1)BhsHJ4GrTm9)$Fdz<=}MsCLo|g^i7-5kbD(lff$$S0O8g z<5kzBC>1{#T8dphjmreSe2Si4s{Akt&HfCR72L>7!l=6#PtkQnWcc3?V=-WcOX*jV z&W6m3bG~;sBAcb+7TStQPAlfi)D`m^ZkdFivG+pVD-Myb&jw_;RNP%#SHV)2F1}1% z7mY6>-)(GA1r7PbAf~bzYNv)TQ`f+ym9I)SG~ZHjwCTClu)|IRU#6}hn$qA`cm=he z_~+T)+5u=sOS1!zCCcmo_QvXQi8R((9pDS3Hzd*`fW4R9m|mJ0DmC( zUla1_0Gn$##V8;$7-@^Z5tsnM|Hs&w2l!O||Nox*e!rP9Z_EtJ5LrruK@lr3bhtiR{$oYy(`ecz+s=ljQz@0%n}05n^bT+f6SXNMDFa;9NR~*6+5zIf@+d3Gz+Fi~CG+=(#I*yw_yI-+y{~sw-fVU1be}La~Y19rtw};^t z0A%1>(MGzZ=`TF9SLmJPx>p*=b$aP&>B`OII=x-Hbd^@LuH90ToVWmoC4!z7GQH9r zDXBWu-&G>+m5E56rID*w4)n!!L=f>A{;VfSZ*1rr~pk>(ouXlAgs8{H{`@YFXkxS{g0+>uc<6t4*fyf67`3gk&uxIJY zXONRVSX`iW-7D9T+a1dB3YA44EIhez=>v;Q_5URi_eyRg7t+YpD-nxuLkdiZ%D@RE zxrYt?JCUS&W#nUgu!JP-fqNRsVJT6)5{^3)rIiW5vq?fF^DlzL)hi=&qgOry-()nj znH1_?sRs8#8;T>)oFpBUNcT$i(P)S3NPX$MT^CW4D4gJYj)4kGln{Cx2$pifHp$baUQA$*= z^zpKlT);(1LM8K;hQ!q?Io6_fmB9l>LzzpV?iHF_(}tomG(Aa2CDOezx+hw43{q#g zEl~UDUdeY9xhw-;JkEUb&p_ znY}`1D!Nx%$#vB$biSfJ7(E4GdSx|o`-*bxja1VsJCSlor}_s<#J%zxlK<4m)hkO7 z1n3DOJSbZxED^)7p??CBbgzslgO@mwqyTUUBbg;7s#i)rU@NtNn~{V{=5Ggyt5=$| zL9cWNA7(U^xfJSN314Abw4rzpn)#%o66szU{Taw=q;7RvkWWeQ(Z1+5Zh z3Y`gB(e%u)uPZ&BTRLtyf<4dhVAGJR?iKmCCws8@GF|N}i)dZ%E7kKO{*NVM8I@Nb zSCWy^L8tmZmxz010Fp;(Rzc`8<&r;p(qSZ3DQxC zbg#UR(?(Gpsg2wgsD1Rlvh)aY=?vb_rBS^iAF7U~N2Gm87IG;am$kq%dxcJMb+6Fn zB7Iz;;Emo_C`w~`*OQUDUmD3n`Cusy|F3?iK&bxZewl+`!c0Vgh{NAutI_^_M2A;96(8W^SEAsY6-dBpqbhWR%M(cWC>5be5QjTS)yt-E= zAZ4ab^}i_*_sU`Ry>K++)#(q6suDNJk~oy)rQi zEc8a|D7OV_AHA<+M`&8S2fomyQN1E>7LKM{e_MT)9$!^1PTvpS1EGI4qN(cIU#t9o zD=5q{yXdqW9aOY{?BzOzKxD&-NSPpEI2=IS z+qBv?EHaEvq-~Mz!v zpYbCyj6xF8ly77h#RHnR zI#Up@Ts9AN#S5e)>uN})1aPlaxl%R-=UyYEN>Mx#-SWJL`l2qSQpWO+mGW<6#D-dV z$V4Z-fy~QF-qhN%D)pw!ClHZ;$ezNHVN;N5dwuyvc&wBzBav@gX=dFs#9gkRLq|Wh zj}fC9hSsU;6I|{rH$XO2m&df8D(;XNaW%xZkG_DEPpEA(V$YDZ^3xg`pQ@T%As6@t zs@7{Ru39B|{4kVm69tw6&%i0k?*Si>-P%!eEBT)`UaQh{s{VLNq!QW_V-e?N*dq?2;s>;Quz*2!BSUpkYUdCALwu8`1Rqj(eSm9GI zd#oxCsnNp1hm1rB_7SZ|h9A3w^~bcHJ^UhWRIT!a*7JlP{|EY~v|cdw#B^vd55bS( zu_tptB;=1Wu>FxV!y45?7Z?v&DbmH@WUs6B*pf^12$FC$sbK)$KhIHl`vsn z5?1Tj&7)u-g9yWqPO;tLH>>#NnClgreJDtz{LwG=K3?`wC0dk12~uOnU^rHJPBcNa zM#kpBRX&813*pD;*qp!OM|P13*2cs}R>6-KL~i_;82f+>yeulh!1UNZlTd|NLF0Z- z>}~o{O#WCH`!D?{E`KbKwcwbml#oBZh)qvFUK2FdHpcc_j31?B*|x>ji$+1;5HBI0 z9hP@ogx9KEiMqm@VE|%01@ogP+Ly#1TBMglG_}fgd<3PMMIR>*kH$xmt66ft3XfRr z;dO8LzK(cI%%Vbug^yUH*CVa?eR#erdmBMpvoA|$hwwMe;wy9a7Clil#1L9}TPD<#`i6n}`^ z?8{Krj4E+e7G#%ZR@d{m$)fsAnVRx#4YbuX+1qzWVce{rexkzrsKObm!cKRo%3T~P zw?|gel(LIqsL8aXlW(&p2w2`UPZk%kU6C{ug&uraxuxuXc>pR3~h5PF= zwR|^eH%kdlRol`}RF4LGN>=KFFQxIa&rqeDrP7s?R$3C5?Pp5om!?u~Q3;Vc5t$VZ*JANPX)R` zSeA@(wvzw20;3<(01SIAxHwkwD?g(Pwh_q}LOS1uwK-&@Jdq%4E83!o9#NeeySGUh z@d%`ehtLqSk<&PohISr>f6?@L+MfNoTV=|Rd#)rrN`+|5v?j=XBz!q$Xyqr;x;OkJ zg5BjO$)bnX@u4u2Y26<_4_5=qzfJ3r;blL)FGPJcNEKt-lan z_%EzaqxC%D1#m&W{7gC&6%5~i3!~*{(MT>bXUER>T#;Mm7K5`n{TC!CO>2Al%u#Mq{bte=W61zSLK>)INo=u zA5&6)Lh&pqJ><&CN_n}v*Q)-VpxMoz2GJVYo3c)+LV`Vlj_dwXTs6NGq|_pmL)Nbd zA*X(dClNm?XPODFP1(Ob8HUk*Qqa_>+cS9bIvjAT@1WYe?KUslCnXo&NnL%i+!+=T zr(M=c8G{f(_3AQpyD=*FBh{*dQK=fQP*Hz-hSB7I%fdlbBmDGP*moaWk0P8KmoZh1 zrDIY>x=OC1fz14M;*>A^^K;}IM$3IO!AUMu`V9L2H~LGuE}F<)6W^jf4xPRWC2-A0^NwSvB&4>Tl?v2Top7`to{scNBROdOSU7^uSOs~Ds01h zG|jt&zmfb`rDU9q*+YSiw$(cR^$&468r~YgllZbU(5>)gD{U)2j@HA%ui{KDz7nlR zhI`NB#Ht3ZXAe(@N4MkSX+2MP3T<1H)(eJzOxxC?_2S_dY1`VgUMBp`d92r=^-AGA zeuF-N)@z1$z|Gh3b?NLaDZC4~y5{ z&P&=fy7%3uga)ZiW0oNuVM9@1gIjz>XWt*%8M8A`dKQ{;9%Ebn0)%W4-Pp|2?1P?%l%Zbb~ZK5zB1>~j6#Gp+1-Fh1=H zBi9IvP(fTVh{Y1|06%c=cuhV7Z2>zXzgJR;ei5q-PI)0n_bGz}vONDm5M- zB(+B#-s7>3BJq>~&rt>K1>!1F?&(y&G?qc4&xJ1zu{|uZBoYPlRpMo^xU@W2v|7}L zp#6V{f|Xy0eo)Q&|0#pzUy6?*-St1^!P~46$Dy~%rKyn=J?oE^vHe4I_l8S1RF8`6 z*f_s2K;xGs+sfa=BXjsE$^m2Ir-p>;;Y_X0qK9|Kr{V%qbD-ARf|coJYXsMh?L+WP z^h4@kLo#lEf^AMbnWlz|m`U`2TdEAI2d{`- z*x-OMsZy_rGf26tQ~eP%%+zSODgHsS2a{6O<#NRLyM$YO?Av)W;SO@_7$O(2s+N5B zz5REQkKrC*M7$1C$!sj`mfeHB(Dn%tKzfR1DqI`05yQ@o5c3CmENV&7AAAUDWEErR z-b_2A$dQ20lwt1@?*e_KO{fwmO=d9;?I0U}Bl!2)gwn+2#A{saDDf2M_TmKCWtR;l z%F(x9AIr`oe#f<@;&69DR6s4U$g=p!-C8m8;Wq7jB7ie_dDHmI;Dxouim8FfrTv;H zUXPz4tOiuu!HtqpoibugHvR;5JD|=Ee&Gi+R0Z+LF@EZ4G|)r`hd)5xb;XqfxNb~s zwFqdLgDc~!q;@?qvoUYI4d@347eolbZYqYP^QdMz3v^XuZp!?m=_WdNP48GoE(B& ziVx?Z6r;rLDV)tDh~_>^ShEK*oG7}a@UUD1(H0WY;9+Ccsplt)Z3jK7P(OqJqBT|w zzI|!gGeuU!31pe?0X=l^pV_eWJh8hocXw78&Vhv+B==7!z(-;LuFT0EDGBtZ#$13$ zEl};1qQg*b_a@+Njm8fTY{f{;2JvApJTgcn8-7)k6ro}Y2iAu?>Lv`jP8sId1*Nvn~ZAwh5FwfLAvF51Z3o>p^H zezgw_fLl$l#9eGNfL`o`hmqg0ZTa44F(4HWAtv}lVkeJE$lFl8P`dW4PUr?~R=BdW zSy6;W=tR(L)@vc|b*2PtM*pqapCqfz+6HY_HWzLe2;S_EDfsv@Z$|&E+Q%^u771lM zOA(gIN?BT>MA7;lD`AmL5(9hoc+32V-JKry6|L~dP0Qv#jvo~~VimSphb7`O*sxS` zMUU8tq(eH{AGAqjk2r_)YlczF^LAA|;xW?0s<1gf^&+zx9ub4|mkgtRU{=c`UPpQ* z!^lN4tM3s3q^B76C6!Y?zm(9>ld!~NZ9szP4?Z$Pvm9r=3C%rmy}8-uf`3GsEz-n> z47eJV;`s(A_TQ6Wz_!1u1OK9c!z9;X($AQi`xHTq^32i*TeZXGnKF}ivFW!u; z+j;6Quq-+Nh-_7HB@heeJs9`*CA{VF;0%)5Pm}_RbMTs?D0xRuY!^I0NLx1mYUbdn zI9eoh_RNmMlL2Tb(FZ8i!Ka48cz4fFWAK?QGCl)nwu7I;F({#@r|2Fw{squ_2m9(_ z>pq_Qn26G76h8tTb8u$DLp+Nj*8ys*v0wH4XAMyNDV}c@*sAAyf)6GQ4Pe&DLQeJk z8_srSfqxicr&?3knd<4k7dOdM_iq6IF2oK!vY9Z=)4v+tIZDMn4Sq4iPCvZV0h$+V z9*IxEGgNn%Cx#kry62a#xzX~2$C8FdBA5Bo7O*qjll4umS3G$A5IeW1JTpAk5WAA) z=?Xp|#7-9!7McloXP&IrH1K&LcKTvAnK08Me#PZes@GcZZ;c&#tip=9jrasK|90p0 zISzi_*io8$G?Zp}av=&T?K}iehpkn;l%{E34AxnmvGut;FM_{H8rfe`liIy=4=Z7| zCsS4~PiprzsaC=qPp48mP6p63PYLrpb&((sU<2mE^(K7aNj}VzngJI^A)gODmmb5@ z_YCkzho0aj@OMs(33Y(6jrX=I2 zu;m7+`X0JrZcVgV|A+!$-;_{s?G^gV|B90G5vWTc8~dW=FlPl2`fC zGe8#{%#K?8VJS!b2*|EwN+dOgr)gJalHw{5`q7|>}4 zv!m{V9bayJ7wD$CHM7o;B>KZ(X&N zoz~!8L+r4lPHoBM84Erw#11>^{dsvLE(c#5Vuu~|RNQPK>$M;Jc!(W#)L$R)sPfzd ze;8ti9d)B{wv)9EZhgfPTrYOiVc)ZzGT>E7LpwOvogH=c3fw*^;2n(}m!s}DlG|q_ z_}j*g%TYflz~%V_e07K&cGNv^kdpni8~ljdj&{^5@!4)Q=Gaje_>m23M}7EhJ~7vh zdi2L3j(Q_5uDBd^xu=*66~sWPjQYo8QM6YO|v_u(1xDWKmR%#Qcq zRSsJG3-r{%?05&`fduJzv*R>BHx@R|jyGYXS2^C&KouO!j`!ahIC|40wlPqOgW2(x zo@Oh@+aG9%gWKaB^Ozww!|jo>V($XYb1*wz?_X?uEzs8vX2*N7kXIT13Fw4_+3~*l z1TW#i01&r;{&p}s-g$^CNgRow&U08)y|v@*RnDt$F`(BC){b{TNj#=Y#uI@WI+z{r zt2l#}xI0j)#(vfF?08GB@s7o$OqS;{co?Sdva*~PJKm9hb9wTD7a>hhdD!tDyo~pIQMIdsCxzHy$6Ft9 zHd(LE;Qd1Eu;X3(3)`6jJ}1NuJKi=3&PY37f^QD7!;W|2BW|B#;J+C=F2~yj?>Cfo z{ss5K&!~F29PitSJQ#9;7bFesVd~lC7*|2uJ zlX2bIHABuhNGI?Nxi5lGF30=o6wE)!@qU9$x9P&s3|V@$_?czkPZPXHL28eSL6`*o zG?X#=FU zG|cT!dm??XVQzo=HqzfW%Hy1!dcRvE(KcYVD_gA+wfd-C(u3zPb-2U+1ZnB3&#(C2fFHD_NSHa zb2!7(5b<9uTyOTL5j{Q1pXLK9=wSAzv-9CiQy62SGElsO*`IdG%D6R92ZOagP1oO2 zTaN%5XR!9C!*RwdjeiLAiG$gnPKsjVTYz?J>{mU{{`%{E z;!^k;VX}fnwg79`pMJRy_urA7Lg1xH6J&?|>7=>1=05-kU!FPn%VShRs@nBh=GvJp)?65!mcM;nWjnOPv zg6qZp^z~S7pO?XllZN&T_JbU8_{sLmo8ybWoFNE19ieF;HD=}!j(jdU>k)AHkZemWQE zBL}lT4LoLlx)JDG2eUu*VU{QT>2aVl4rYHk@-d&g-v@f+VD_i`tFz0?)(r7qEL`&U z5y68$&50{^vSOux;vCHWG($`FrwxFbIhg(FAxr|Pe?%XkR0p#^9Wl?gXpD&&K(igp z{eU~7q_N|gpI&Iq?K2nr6Jy8aPp{zECfjEV`0fxp z>`&KXEX#VG1Hb0Bqy6b4+&w7mXn#7PDJN)uS~zQnKi&MPPT=|J@C+WeKRt@8fO3A? z98R(|7PS+>pGrpX@GYeIK$>9R zdgCqJ6hT4PpMidHF#Fa~PxxB&`&^H1?~WXWv@rGko}kdVUJ{9MaGLW)1t+`s+L@n=ipPhuC4? z`U}o>q@82nzlGRg-+DYdSN30UZ)>hB=f%FYYhI7ClMB2cX@bhbzV&0=9wJ+%GI&CW z9rmr!c#d9{=PmGFA$Hie-rfRNNUb{w{M`^c>|19KVLP9LZw#@+zI7~a+>&+$>_>pRbNJx~UV`xArd+GFQzF|15p$dStp;7mm*TrB{nT)D8YL;5`IVd*By% zqb~eu){gL}i^)rvyA4j#SkwMg{?PuE9=CD)=?iV~iZ3h?ztZN$pO!?@n>txNN@wP( z^^o4&F!x-wE7AuT=Jux(kUrBew?F+D>8lKL`_rvR-)q?KR8H+rn@z^Yjj5&=z;A?T z*q@Fc16NJ{G<`d~st`-WO=*Jt=|LR$r9UkIRK&sTPrr)g$!K+;Iu2%knqwy8_CQ@6 z%>MLKU^!PE12oCO>`&(`=Wyp@pydu`fBHCvW2xJLb~(5Lu3o{PR>!nPR_r&RiwAYXe^Z}z9#a84xWs=0w)axnYT>g7BZjWJOHsH%h6pZ*ogI0dM!!P=kp zZ;$UZ)7C?PMj5RA>FG9Jh35e+bTIo<`o5st`fH#a8v9kxvp=1?2JsH+`7_{`Nkape zHSA9}=Vdzr$4oyK+4HPnf7<-4rR=;6UYs;RcG#bmMNmnWrxtj_5IgKoQ_pgFx`U^N z*kOOV`iQOU%mDuw@S(qZpdVK}HEyND{(?55!os;0dhuC3%+IuA1c?=%b!Cf!* zr|Vzj_Q?xggfz5gxX=BsuH*Kp4xVJ}xcq6+2p$Zb!TW{S;koLrIb5D8;B(w|v_EZh zo9$?SDsVHYY;<#+qjJ4k`!k4{o`Qvr+Iht{4}aFUIK!JOWyc_^rye= z*^>Z-$(`wO{MPp1%0h;At_NRErPvMn7 zYYf)@G$Ssc%B}YS9X43|(>w6+5?=+n>0tJ!&1Un~;axDUvB-M+RnN0OEu4shGxdB? z@G_*K0n8fqr{ChblguUno)Th*{ptH7c?9(b9~okY{b|L2xIA;gKMAqJ{&eDcF3%S5 z-63|^pLXqQtMZ%!zZPPL{plyT;3(_m>x$4Hmf(7^Kke0p?GyqpMH(8>TzB@Tqh4k^ zb-|m4*kOOVdlI)#Z}6eUj%$AUPZGD!d*BO=9hX1-=rot-Yw#T*cG#bGDZ}MC1Af_U zNBdL%PLFCI?N2je#vnUT`_u7vwfkg$dN!xNor~wE-wy~m_aBKz_2vAuG1@2vi`t3c zPo-CjreH&482yb3BR?7?*CXY6G-VzcMt`Hi$caYDbvzu3^+NAFkC#j|qrdbLjqONM zFVZLtXTuL&CZDvey0aKtF+dAFnrM>Alvi7Y3bF-3;a->5L!G)k^V z%Jtf ziLdV&fLkG3XR^YjZ5<@KbWgtuGa zgQ_o7#hWi~i$4aUvTq)J1A`x%4myIB!~{_p>mnI{BCdj~Ct<9?^n_XB^Il4_%D?g< zzH~`NNL(i-LHRDJZvy!xFGJ7%ByJSBy&mg6Qp;@n6u-BMmnV4T@7IUmaGSVW+?eRG zc4O0ndULC+H2Sj;XOZ+rNb*S`?juR`(wPmUwpW|rlX1~Vf5pX|2d1pXIdKm{;(77h zQQNwY#uN!qI$W-?smnsN0PJK;J)%0RY_1D22-1}{Dkx~hN)?hWWp9Vkp8b>YU(3ddRt`ZO)t38ZE|Xg$uEN~3Lw3NVf#Kd zETb)|Aib_(o4+oY)AmR66{m>4a1L0wLA;n(CDyTj{e!oD6{xs_KktLQ6YWjg zcv4ymsG-K(UWu(>B4EFHhIf|k;HgF# zhuiq+p&aoQ_$IBfVoD7`QJUGeaEc_G^C-|M2VZT7T{gvT_Ad9x9iV?5JlliLXk}Ny z$4N?4$4B?WMIbEP3{w#dOl)s=1{*>{s{~Majs28l#T-OHAn_N^O?XJz4~@XPkVg74 zDw7<8+$vRZ4KMMm=gGU=uw$T{V=PKFJqGBfKUU0^M`**}J!`_a^j|``L96k-S)?ak z^3*tJspdNbbXsH1aNbN5?}{h2GRL>?ftosFau6t@U;I7KvANRjvk*%QY#AQxI zJKyy5Ta0EX16I{=`TS(e7uAr@9nXAtZP}G6;BB?Wio4hk_`c^RZlx3hk^H_!{!wT} zf9p#4GlABo(4SedWv^aF=REKvVE&Xo71^%FHec!OtQ>vX473uTc$Q;+OOJGkgFr_K zQ^Q*^^k7?}- z+4d$MgVM^7lmty#@fbhCpo<`}U!sikc`k4Hvlx5yTjT*Lpe2@~l~Xi*6Qq`=sv$Dc z$Gf~WqR}PNKpWtWT4E_$=YD6VBS0o=$_92&p_4Xeu$6(uz{^Q;6o0JeJHFM=@-{j+ z+-sf1Z?O%3ejrL!phz%P7V{mN(L{!wLSnR9rNTthu#60&nMq`rTJMMTs4yF2E1Cva zmT8PKUsu$))juFJD=^*dV;Rb<9#k3oATWk4cdj-tDa(mhVj(IALNKHLkBB z<>VI`Xd7Q;kqjGMu|(`RinlV-R%$;|JW&h*8>PARoZKo&%s|QqI#q3;Py?|N$(vnB z#iNwLW@10sal`i_S1UtvDoZPI3CXuLQU}e9^i;C1%^}=0FGqg{)G!iD#39;n1RYX+ z9Rrv){*2%G3CMa#vsU!;Fg8+D2=`j8an~U}<$3iJSQ|&~Im{kTvpnAf(ns3ES}nv^ ziKbKiv)jY|!i?KDgEGuxXRC?}629T3uA(0^(c}BR9xZ!dhjMEEF#3wD32v-gC%LMK4#_fi;^ADp>H9% zmqzM2e6?vN(J2L{$AP_PxYMCAgMY)&i4tGD&6A*25UnGj>{2;r^F@oDFR~jv0CdE` zrQ!a4S;Pd~87)WnHK5xLrf0={S;dh_ymiD-xB@I}Ji~Ylrsu?Aw4&VlRiNSy&ejK8 zKQC_XW?T!Xo`VeEuS~E+f)oVk1lbJJ3}JA4!i+D=V5`;G%hk;r>S~T<^ac z!g!qcwJ!UGd_V;qJQ5Z5l@p)dV&j#8;vGz}5?=*Tf1hnp{6Mq@>fqqaMNzcMVn{P& zhvU5%0W{9R^l-hes<5B;s)~IG^ohZ7^mYkfb#XEb!|iJ%ZzUw1gnYOhPjhv@#Rtq2 zK$rEFayM1`suI=`7j?Ia;ke-)i>$pP3|7|>>ye{u%3@H)8MQp4i}`ycMnYZj{ta%h z2H-72G;~(rYakZEPS592`hno1NkgUQyria~=#0=uKR78dAAG5?L)qgyaAc>kID{8a zNjqD?e{|UiHr7;pfS|B6b{V37T*iWh$sz`?Rgo5>M&N*t#VMH-2CG|$iuKrRMJOAR zns!J>7_4qBPQ$57+ufl|HMUjj$r`m2$%xI!g3bW{z*tloI$!d27V9JMhBRuuufVq% zJE~=*ri=JvEw}JV@GCA27fK4diZ}!p2r}31xrYySn@q2z6qj!4mMT^qDEdOV zCb+xih}4QK91hW}w8CKZeDO~zzJf&#VI`Csj5?@umy1_EXN!lxPa928=dKVtce3U# zxOa@MCTTcB*tBKD&EBN7<=o*x9}J8K-Lp{ zu+gaErMAM}y-}Rb#OHXkz&{Mpti%KBzRlv(A6T;ie3whZg_?@@@%z3NM-jo68U6;* z&Hof`7q{ZMWZ`3R{RfNcdpS9asrn;IzeDWD(@)Y^QSb^zLp4;Vb1_v&xKm8M$;KK( z)W#*WVvdzU6?Tg)wfRhPF!)HVv0^$MKr8GOg-7uNXmf!+axk6B`u2-#)%a9)Bha@F zuD1#WI4C|wq(zqWIM5jf4>6617b$I|>bMxNXp7RzweI2}$@MGo*h zT4Tj5`T;o{5s&(L6)p=@F$5nIyT7w7n(2$CKrIQY!}E4bbbQCf-TNFN83;7Y!St>% z-$`+^498&J2l{}pn&){DboQMQHK%d&eg(8mV-D|0%~^5wOKyRa;8$FlVBtB@yau<0 zJs!8dU{M|44W85*C4RwedA6;eWB(9#q%GUE7=*8Du@x6T1m(UYsy#(})kbo2 zLgtXJrtnI1S>!qgJ3S#7>=Ie>wN1XOV$&Wp+cdCw&*Im_Z}XAKYOozHF2_CRL@$8y z-4-zgk<&@2uB26Rc7Kb#|6*eP1cFQxbeU<;2V43_%w2#y^Ft8p5?L{_wV&XOlp8S~ zJcTsUX;Z*e?itFOQa=^T@je9Eiv6J+msZVYz4j~Fxf4HxXro*BOxx+~_ZD(V4nuzN zKQ`eE{C4+f9!XE3%sNq*n>s&Dxii`64smgcLRlfL+KStlh~bjWK0h1HRUd+mB$DGm z7FT)-b;cx>&)IEpB|{8_>YcPoHkZ>rfq8{k1i>b^=$STi*%{tOw;zJ^kN=Rf;e2*; z+{rHY?S#Z?A6znKf7X!koSOfl@(a0jxAN6HuU!1+8 z51-JUhUlhS=p5_f_Wpuhx4eBc2eS1|Ml;YNomJf1+u*F??K!x0N8~|raYAxnQ@GdP z88aD6zOchr$Nm=goXShSwIHgeg;vZB?Crj~cK$LvbUFd0YAgd?{-3W<_Do9~#`%D+ELPLn!8=>qWX)#BS z9)oeWoxK7tp`o4-!yp=?g_isTwXc)yJIK582S6(|R(?)JN9)sBP1X){+KbAu zvL;ljbEHZgt9nHv%eD6MH~C1{2BL1p++2C6m74W-$&9QS2R_|sR!L2nau|eP+oQvH zKCl9OozW;eQnT6a|0hoh4uGF98fE9)C$O`_9(0Q}x4<8fM!F|8&)Gi|W!`OnkNcJ7 z!8_X&JpY45?GG`@6u{eSKg6t6;!;3ygjJ1iq4vK0_85fRD2OH+05x;);pb6+gLXIU zRB}h@1C(m;>-Fdm`jhLMb}5mYv;^qfj~#LoLGt^h!^Gp*1XBbFROW+&{A zyF0PqsIcE4js63FvJ}EJ8qr-^r;C``%0}aWIaJ=cl&{_^_mFG?zImpZfN$Y%DZ=@` z1HK7UaS+53(H>3Vr>)eaR0n*!f%Vbc1bjy$Wr|K!8|Z-V0wjO#LjDdoMq4`Iy9I2w z;a!lc3HY8s@&%1t0pFwVbDZKKus|&%deMd)@Xc}CV-3LXtOR5|q*=U)4(k6E@Fl$o z_)`6!9q>)PhKxDjTRtydRyhuty-gVoT^1DZosX2SbgG}C@&6IQwF@4)|6;a$Ofv{i6fEExe8QFvqz{49A+jQ? zE8Euud^=3Vp)V&`0mJ3M(*fUQd9g#31FNjL3HZi$!(^Z_lG|wH4)|unefeSl*m%Po zAFBhtU!CN5+eZ*BA))M29q_%Ik%#cNKsy}F0pB_+`S@}M=z@be;5!g8NXk+?0>W!C zwQ&ykK3dO_&744a9n1mWb%(fUaX^(E%mLqdkJxxKpjHm%fbX97@FjBUpH!gX4(5RG z7VMi6&jwoHU=H|htLjyFJ}4bHKMuS1$Qopa%}-fbXc!xlyys z5>^ZrZgUR!el&wC_8L$b2Xnx8SS?Ehd;>sD9LxdVUe{p{u1oX+8sK0K_}0gb#I+6Gk$zKqXPC^HKJK*UgS?4`KC-s(UvOwwTwWGdTq6wZSkiy##rGJ;J z=LprFt<2UDS>w4W^FUeHsMSQ11HKnpaD!C?uNR`>fN#ykcs~)Z{m|S(#{v)+gx^njWrc(O54iVNrwv-qP3x873lFO415GE&n;6v4}LWL|s0Pq{Q)C@JhJ)^1_p9f-o-|E~&5bvM!e z3vQmgP!=(2RXh&({)8_r$*ik`CmD?@9tV7PjN~eG1|Q_oaPc_cd%qzUZze>`(h7ss zgT#=3xp>>4+-KCPcpUJp5W||^!T&NERXh&(=En^PvI=21b6>{-7;JXPso>aGjvWrm%b?y}L!U`S$W5B19#tbPF@Ez&1)UaCyzQLsl?%ZkO z60TOuedrKGf20)#t7nMfTX{4;fiirK&N`@bXNh%#c}L0zUesuUI`=*C;VQOM1H7?I z6Wm>M#Nwh{yq*w^O)Csm&lmd(v)KhuE;s6+&Rs4daKDbM@OJS1MibPzD@46DZ08T~ zdoB%U$N}Fnci32_xwz{Gi_;ZS7_43;s^KvOnRR(6=!_-&_6pBycj& zbO&?5_k&J+m)HuR)eh!>?|$6lD@(c?=%9l+;Ct~sZk09=pS`rlS&6V3@6~#Rq zA_4)%C@g&3=Ya1FI1Y(l1u7nbkBRAs2h*Hd)B>tUSRI}@;JY%4PhUF$^>8o;d^6xm zLus0dO#qrgSk3b|;5%i(eDdnjn*fU|+eo+9TC;oCChUjfHYARHxD^O~Cg?5_;(`2%Z`d4SFuKwDgY{ z+7V^Wim304SX9N-p1}d%Y2&#O%YfsV0`?R#z+A!te>ISyoT<@uWGA`bXgzKJgC4%M)SLJ3HVM~0CRB=R5v0jq6zpe z$PXjU!MYeud$~K{dkj%^F#>|gM&t_kMm6%P^VE;Q*BXs1vO3n>eS*G3!1n`73HL*E z&Mh2B+0q|N2YegikT32-^++r6Y2Ixx6mNHE3ly~wXMI@IAuw&g_qzbcvEm@Aq=hEn zdj(-?IV_t2b=EjIgv$Zn`}jzs6pn^ywh{hEz_&fZBr@Rp1(chN+7?JXLrCi3%)BLW7gFnYGj16hg<>Qlk@o8 zs|Q5=w9o{6|EU4f^&%P}1HRROYCD(% zzWw9*%1Aq)&Iap%?-wt6tYJuXt8@0p)d`qCx|CfMo1;p0tVu^Sc z(MLaRrF@MJ__hFRr@0CE_C?BYovJp_0pF=e{?LW|Z(z4G0pC?%UmHFTxtf6Q9wZ;t z$QAHiiReBxtGEVynhJb~uLZy&0!>LJbIgD7a6{}u41dYgbR)&JQ6-`t4) z=zwqX1e9a|G8;-63MW$guKf;Dmg-bL1?c}H;9LA9%c88eK>R&zklr!#nSBH)*Nqv| zE6)h{K8DJ(R2M@Be6t`Ww@&5$;ec-}lHYV8)jvAmn+Vp-aJjGPfNy6c4{{;yS`PS5 z0-I~Nsk{mJt^ix-;wIorqg(6&JF2-W;G2MZ05hV2#5Lf*wM4eB3HbKSgx%b~43Qu# zvR72;bij9WC-5R*uW4=qzAbQ8B;t`=Un6(GcRDUdijH6d4R?I34)}g_n2!+CA$p&L zvP*TqcULZs@~sB?%E27)9XXOm_(7nf4(5PwcU*6fJHU0II}YZ6Z^yE1+`k-d0}JQP z0pCxnvhl(|B^=BF-(N2>t__srU=H~HIt&MH>YvU)Jsr#e-@1JHg4bHMlW=3MVTfc|ta2YmD4ArRRtUPNLtVBvam!1rqeq$JJ{ zRLH>`@V!?Yp#r+Yw+c{A2Xnyp9%5rO{zV(0jt=I4?fbV3S$;;YCeJZRMu*k+x zx54W>eEZ~K&FkQmLNqe0*+AI%=2UU2cQf$zq@mJtUQ*LgH2MP3BDfwg41A)oqe?F| zjYXD&Y-bVpmo7WO#+r)7pR=*O5S?-v3l=7euE<&a>p9Pmp3WL=xM836_Dq~(K z-yk*Zkd81|-CA_PI~t_zdQdhuw$(IU)~KCW@QST0_5~kqEGi8Le7~&1c4mVwHg;6Y zaKN`FoWIO#6Zk%th6}|3-~G75R|ZsB~IkuzHdxi2Isl%OpXW zY}7%WJ4JksV3Zv8{lG_%#tbPF@a={9n$*kzU+&UyhO%>~iOlglKDR^kb6R1rdWLBG ziAS0J3(5yZ9n`tAMDxyUG0Q3(|FHxYPxje+qV`VS*-C@QyEL4k6wVP};g(TZkJb?N zPb&;o&lipGu)S1Ig>tS@2X!t2zPLSBYSw^nF`A&xT_J}3z{UF+{Gv<48FIk4+EF(4 z6r!xFgX=1V!Rl4w_7PSWg|duMtKxCM_daIV(xC^yQ;bFxj|0A`xSS(3{lQ0uXgJ`z z$IqI%;454jE))lRf3i5k?;!f=KZV;x&&hlY{S%`5MyO7NIN;mj3LDD|C;1{4$NRej zzJqY~FRM@nqN*;T3HVOk#AjY9;BB?W1bn}*&mqwvK%*SY0pG%S4~aZSoCmbf!5r}Y zqy`t@YoM(T=74YdpSiLpfG%k4zqOFgLirBgZ^MOEk^;Vu!0j)&vgQuoSqOnjoD(Q- z2tFphJ7rlkrxtNQl?bcDGY5QMYtPZ{WRbjL;qM-SaZPng{`3X*FsMCc#)#!F0g) za7LQ{BDp*vb4ce&vb+uWvKWDHB8UJ4DK3!-`0kz!-WzP_v-maf1#U?cGr*R*xY{G- zd7!#i__kQ}5|o>u+Lu;o0>0DzIGX(i!A&EgLCTad2Zn|ZKt!ZcI1+* zg?#saY+?ew@ATyz;T)9rjoJzL%J$R&-+UQ(mY#VX_J1s@mPTy?zSozb;Y&eKi$ro9 z$l}WLHPuBN@O|en=Eg0d>XBAy0=~ELXrdSc!2-AFnKpCTcSgYG8c28jhuj2wkKI5y ze}U?jQOe4MmNUOS=QxzQ>K`_LKC?~#gx3qoA@~ZRHcfmg~8d+p@tl@y~-102k0?|)yAsukkfkFp- z?bFEi5>(f<(gb`j9mZa5ug6&*7S-ix1HSY^aCzfmVTej-p$YiLVcsZ5a&4gI8b2f8 zyY@XEk$oYeS9qxm|0Cc#1+zmL@LdGuN~3lKe8qUa5p^f{p%4uRd{0lnUW22XxB`AR zM3Wg^h&z0{7vb}oj2kfZ#iB|^!`U71t)H0#wQoRF!w6*$xdOf&hw`~&D~R6GLKE=) zJBIBH2b!v}@^j==tQfw-cRy}vmyNp&q76nUcMlq1Cg7VeiG_zCI&Fk%`XTQE?rooa zogK(saPLN4O=rZIfbWiK?44ePDk$Kqj#V7+{rV6e=Bq-4w-j-!WuZ`%4)~rQ$OrR| z;C+lHMrt_VyR0b(h2I8$-)NK_4)|_u$aYqPe`7St4hMYe;uKd-9FBnhN*d{&lsD&q z?_^vqmbdW!4gOebOu)B%2aIq!wm*m2+zVLbK(Jys;QIz1JC*_8*MZ78m;=5|a67i# zQ5pg@H&_RJhmJ)ZkUEBla|D&mFFmIY`0l~sYBog6(h8k`Z_Ot14qy3tqo}a&AdTLI zKUr2F9RXijr`HXc=C2B*l7x)lK8qtOv z-F*@7PDsY@3wm3>G;2j4M+5z@=q}aUM0ctF&yMb%xeE8fxAV698_u>NCcw?HM0B7# z+4cJyx*%n&PW4kX{y(C-zvE&hWj!C_MYKUT$INH;mq^)X%$QzzMs)WyROhtPyuaZV zQXc74?jMfs`Zr_LW0B=n-bnV3j_wu#D{Z*kv2=7d9?4Byh`W}fyB)y>8g43YqPr8o zX1chE?$S^e%fQxX?uzbC+~u+8T{&Ve@G&is?Q5dDt?@j)xC(a9a9J@O-Cc4O`+SBi zm;_=`y{3>~bi}ne@iLN&YvhjZmc}z(qB>Y3!{r`Le=Hr{tulefXb*_`kx+K2j_&@{ zj`0+rSq|pt?ztX(cv=ax#=#uj?WA9^un*|4gE_jp^#=|EUIn`8V2txQng09Tp4Mo1?n} z5j>UA-8?`A9L&+(tvC|U_!kv{sympYyJ8VntR+x;gLQN_HUe7?Lh=Yg(n;v(?#Sxg z9dm$|>n+v3sD{)d1Xyu9Z~dY?D7HiNb6TO=vvqVg8(vl>oANIx9~iZoRr2k;?F+NT zEZY$O!6I9PBfv6-*+9%dvs{5A6s5tdkcLXnc}Yz}F|~wkm4bs2$>1G~9aVa%X)L~~ zY$-b6@(%5o{HoA-j3zJ0-oO{ZW9fs&)T8qKz79##Ep6H`8K7}&t zc3oF0qZ9_KTZ`SBxYk9XEJJEpYt?$PM(spcB3lfArx=S$!_nQ|_}ZT=V}J0G#*S(k zj_zJT;7n@fg0FCCxKJG3t=E{1eFxF;w8CI@H_?3;H~38`9~!kPo{ZV`5H+vkj%n)L ztl!}z5KD09N=-je=X-97GT=2`8qQD(2Z($)>yXCUKr|q&FjzeZ`w*L*2IV}XR>kA! zZuu=-g|*<{8jWf_j_w{V%65)}Uvgj(aSm<`(!PqfxCV`|LfDCz6YoZ3pgu!s1kcGnB$PqV`5h8G93= z25E)C>iMENB4#q{Zcq+1>Y&bDE{+Z1-Df)Ze4`2K+!bP3SFXZ3@EtAKCuKh1;4-HSPc%}#(`JT8WY{kUzpG4ngO+PFh_UuRppbkRG{Gw=IHL5 zc>A1e=h;9D9L&+(KTmP_)&p(V*x!fd$2z(@7_Yhfi@ew=@ZYq?M0a0b!1!OFry=;5 zh^m2e1=>3ME*u20NWWmkaCGkl+iI3z1$YxL3F?fWkhL|et$!?41C^<=&rQ-7lik; z*u1~N_cP8~GVI2y|FHylLN!U|=x%$wNlz4mAkHN+(cMvl!RvuFe-^(cHsVXbq9@o` z7nkE+oh<0+?iaWOAm&1~BCXOycRzWIcK#NEgGNMyKG@PfqFhc`x&Xlqmx!aJPsHjH z+=%J-;M50;8t^i{BBQ&q1$15FyFy@P4X3@_9o>zOKu(De zG&3Ssba%l}uR2fd13ublWRcaOkfXc5zQ)4&5Pjhm(g8;uD0Fl;O96D*PN?>2rHSqy z#XMiohbwLplCzPt(cPI(IcOEWALoBq*k#=~htOzUJ9B;>Xa#}FX#9-mZoh^s3_#Su z2>&Cx`yIX%DWkF@pqy;fuIO$6=Lqud+K<6kg=jdsTc{+$o>x%KUEn{3XfO+)=A-wv8XnaJ>-h+ZpXz1X|V!CRkhGWcRSAF=xz#7 zH;t8_b47PAe#&h&4x;yrQ0^Wyz)W=aLtOioJMb!qzBWQCgL!{L;Sp@?C-CzwjT$i~ zy4$lmE5i=DqPyx?#nIihIBl2F)VvTC!J-;tVDRm{e=p&qOLg!hqj@LzcHVz*|ChAW z8N8p-C_5b8ojro>OaY%`G|CP~cTacVBkz~sn@J5S-MY;@bUUvcEm2_$A&p*wKfXaYRjQekmtGbh{xL2_Bu$j> zz7G%JKDnexv>q0I0*{_0O{Vq8@RE3IR?<5(PO^vZ#~o=&Q)eSRPX@A+^s;yin;wMm zBkrMDER|YNWI;-9o$8k_tyidsh(+?722mbMVqCDTyCa5i{2Q6qSCn9^M{A`HF8rb{P76=N|2>q>A%v;er*>UqH?q znvue3NtKpf9VLF#NG)E#POu5j&ke*k|5 zw8>!US>*u9NY{6g5`KlBlZ871&99`RCR6)2bSfX5^(j^sv z>y^6P(3CVfnI-iSi|J)NNe$Z1U|(Jb!p24{J!VEa@l9%STYt;02k;;xQ5{a_lu6AN z9p_G)0sKLTgyzpl$@Mex0}Jbbw;Bn#ODj_>-g%JJV&B`S+!3H(3Cm`b<1^DJ#MF~I z{PH63ZJ@^?ID8&z(lZs;%taLTtrxHaZ~fw%$balEnwAy^dP8F?dt_PIoxT9mY^qFM zfCdERV9opk?Qt_3;<{&BlZd706`NYIxkJvqzrqAj!5pKQPB09K(7;{IE*_PcsfZg(}vH}yOIKZ9(~49+~pvv z49!S`CeSYxb1oTV`T^u;qEw%tl4Wd1x&aj{@WJB-G*7gZU>)5W6i6*nfrD?)9mDxA z7RR2IaYF=54Sw&5x0Ot9;$zc+v8!-XpZFcNoR2uWn$$ZKnXsY9YX)(up?qS;n< zIleZ8ku_4(&5vi`ahny5U%U=Iu!Q;suZpJ^r3aSLi_#<2RkOgXyIt^2lF2YLolLz& z^9T7Z^T1~{s#+Fpw+!HOf?Ww_XaL)RwPFiWzBijZCsV%`N09QXPE|dl&=zq6$xmD; zm~R)E;Dz#Ik!5hkhw{ZL*Y8D12&x*9Jn2-sfy{rGXaLs9a6*nHOO@n+NQGdG5iP)% zCAd~+#4IF#XpsCcjLP~Cu?opw8zd(`3SAO=kbKf0+DcuhQv8az0v3HjS4~c8 zjL&@y6MuJa#XG`8;He~$9h{L~d>;7cdPBZ!u@q#bp~^S>I|A=;lRME4kiCXxr0ZgV z$7k>I&T$^(vY|0F3kcX^(L;7S;v{DMSX9RHl3c(eUP<7s^8giaFkMs&_{5L6lT&70 z5vaO@>7rU7oyc*3aZ8}~4yFrRfiN*OBjaH}V;oEuwgTazPc|;v2SAG*Oc%BS8N>#C zy>AoHb_b_oiW2aPmx^(lodWuUFzrvOOJnYDMGhIo$~)Y0Pr$cCffvM>6#f=XWuSNm(-p8lZb4IFIXYScb#O3Uy$a+JyK#A2w%-V# z$r|&urdiL!L_V>)D?6W$!Pgp%{D=r`i+A*pFu!PySJ=v_tI=3v9c1E zb}&Sf-DZ`Lt|$eHijVLPD4GAq5UnyoRduN;DF%GQZL|ygC(=+Saml2nthk7GrAs@1 zfBf$#q0}@KyE^iPnib$*yEI%VDQqP!=3rw#L3G9lRfcl9&{^F5 zi3@%oT%6GbR~br8Pf_*;+sOg`s!PKeN@0INAG(ySP!*y?BUBmEm52Zy3(!NeBX}R9 zQ5j0jRM7}8^OAPn2A}WJaE4Nd8}xhffLsUBRwE2*(s`oML>>?)z%P&{Xh6u8S}aoM zaX&u-_x~EK32xF)MZs9!UtWf&xDf_5={nK=FE&;SyrIzqHR*b>1Rh0>h3??PT$&j9aZ5oUSkh?u!&mE@Y>C0MTL+sv{4*Aw2MpxZ8|} z_$Hw34yH>;fd`@$a+Y0j3g|Zn%NhP7aTqZ-83g(l=qX`pJazRb@K`hjmOEqibC?NY z32NJz+L-VLo`^dbrP4%s@G4qkDg0Et4J=J019i}t+d`H?*z2b9xEldJnKVJWsnmGv zh-qGx&Bx#?w8n~&CmBBbg;()l4SDPDfOZpB6_Gfdol=NTAIhsuU7uv46w~mn_AnKwoLhrD!w;eV*O+;j~|xI0$}JYpfWF zW9$Xj*~E3Ae>7$jGMk*XAF~Y_vm)vO&i}ClS43)Z+5MoA*}M*3PHU_fy80J*(azVK z=WPvvnj0)%@Epi%uc}GczmPnb5Y;j00zx3aePK7k3)8?pGQ2eHL^8gijJ#}jJO?A| zAlP9{mT&hC z6tPEyQ~U#}N~AOuQ1f{uinSAdf~XM$UECsRPR{)0+eQM#?Kf~aUyOii8YyK7LoQDQ zO4*-}=F1byAzGz{R!rn*OtjyyTfAba9@zzSz`;)!1;+7HFVHbg}Ihdkhfl79# ziCldj!fV;EIDO7n2BfgEUF$Ks?pTPb8evF0OukqnP|fa)&+p3SPl2+dQPb$MR1iK; z(~c>`N0liM1l?jy?O?@}rC394do0e5WZZu#L@Tu=b$4~3gsKs$T%L-wc{5roQ)h1)?Eg<|x94t84vx};Ms0bbr{lpPr@_{^qf z!lb4Vc(T?61+wWwxl#P#Ikip~c%s5QI2Xi6=z7vR#T}!<=yfAeVN~~ak@cTD-U)a7 zz+QMbMpymkOBF=KFMRj6wpBm-HpD=}Ebj>@>c`B5W~|s#7;br9fy^@zT&uFszJ%@i z^!Hd*7SXB|KK}>Xs`V$dYWy&c(g5XU$Tw zC;L+Ny@*iOl88`Qk|n#!k_d^&o-Aeiz25KhKJS^ipX>4c{V_M4*K^)ynKNf*&TGzm z@b6TqA40s!3+OaUk6*;wkKNO!8e0(0Y~7H>Q$X6)q`Z*&12j%8;Zoy5(U0`P8_;z! zqX^Nzq5ze;QXxB)9*BRIjYU>R2SlkBe--NEw#KiZCg+i6$!j!tlOEuphuctV`IhPts|3YCZ;6DjXb4G<4 z-0g_kr8|pq(m!l3^x>p()raGH*$d~>R>eR9p zcB>r~M=4y>gyugY{0iD7pO;u0lNy!2q{PZD(c+zQG(eqhh8t2cw?d~$vk{<{>FiQ$ zPKoRBpjD}^p%@bal05>{vZ3yKUqf*=Q=EinA4Qn`RLbRqb8!=U4nl70xt2RAm7>{f zqc4S{Lyhtk&yQDBmTp4dY~21jh?HNC1d_7fBn;3gKgWl=@ZIqnSMfjbx%2&n@vlJ- z%--gsFs4zB>v9X0qhT?Aqa{bf;-NiN(M&NTN763ctJ5z1a7BpkY4A_uetGgW8UW&v zVm+TnQZ>iFGc2r#TOm?S(&;$xfNmNjNQz0f5eoO@gy-K^-f-b>7si4H6A06XS zhyJEdwPYRrZH~{{rBBrwe;-Np=y{axF7}97lNT4N_@?!dFx*7PcQB>#uMwtiyEj8N zrK73ADP6lEF16Um>G(&?U^JqMFE|{UEpySR(kOs7uA)?ClJL`Szj5P!Lc7>9zlwiS znQh2d=2FPqhc#rrZfHv{B*1 z7}gigz%QUL!);&F#u@4V3*g1E=qs1-PD6Zd`u}ctH6i*u{eP1Z^#3(?p?RKw!;3O? zL4q6_Ho>%-Tqa7QGQEbwjUNi#&Se@yyVz>Jgnv>s*{zA$hshMQ+y)Iv7W6cS)^E~HxB>*rQ0`_!{WO&sM!Bn&_ngs1wB;%`7=_10L8%Q=+0~NQsrZe5~LX^n_EsyHGacaubqWmE1O1wo%sip#; zmk8uT>K62z8!cVcwXk~Ns84GQeU?x_a^C5vY_WaW_P)IlK?G@1pV~OCho8t z#*H9%DsAV{WI@l{xRc_De?Y&SgyCf?4cHp)P4!L%yDSbHmtOK>rlI-1EPf;gBZVml zy%aIj+5Jpob7K~|G{vb4y=5SdA8caYK7-{;6s#|x(ScxoFu|<2frg`q^8kGn8PQKS zH^0rt)s@2T19>_!teMUkMN?qX_UT8!yU zAa^Nki$@Lxevq~1Pr{srenlBuJZ5^DWosnY)Hm?f8#b>4NQMmdGGEOQusEP-K!i#+fun(9qQFszHwrFp?pI z>GJF`FFgG@@t_=F=nI@blS(gV{U1{IJU1aX37p4{TF3R{0?qYLbjx@?} z=u-oXWXK11sab%d#C2T;Xmcd!rG~#u_u#p*IOIQYcx_lLNE)4E6vt_<`UiQw{DMgC79;L_yC= z!Vj`$-Yb`*_0abyLpAhSN%%q5!mkVXC!oIrpnk6Dun~7I4SLig*tjWlK~GdIkqba7 z>dCU8r(I)lGHO7o&L;8gp;7xA5-!{0}`1D0Bw^ zZ3^jvo@z8*k{#MJ$>|r&*F|vyToGEMfbP#pzRy1#w@;=MsD6>8F6jCCX@naOV2(o6 z>7~r_xu%pQapV6bfDHjij>tW81-FviE{CCCB!5 zvmWH0NLm;4G>SuWodR%+AU?!gTz+1&PfW6)=cVV+`f1_oX2q6-)CE0e6?#l@0JVZp zvN5xUdtkMkX$7>`18`l?b9pp!e-G40N^;ecmNQrQO-wACRiL&+lDeR0MHv0<2!PWH zQ4w`P&-ww-|AY3>eOK91xMlNMZ862d55pTU*#Hz!D6pU>+n6Z(ocbd42Fh@e?X^Z0 z^n8quYw-hZ7eIr9AYBjbg~Bc9NlVMgSsB;*DbN$^Sx1jX7W&hpW%8Y`Y(1ZH$>`26F-`r67A=K3aZ|^+W-D z1qzeQrY^_?rENs{LDn;!WL->8=*KiQa>R5d9Lk7|8$}oN>`fza3PCFGWIN9B zT(bLIQ(wH1&282g&}$0v=|OF#3woM8CD*-o0KKaql|dKubetf;=0jf@U~G@k1wG|T z%AxuNlr;h`8=+7Z zUaYe=96w*;l!gA1GB%DZ=sEtT+%voiy`wTVjx6XY_?KLHhd>`o3=dECK1UYxj8BZV zpKDqG{Zq&2f}X5+O@*)RTOjQu+16MV^t}8<$hyCOK>Ev*WkJt6Sjc>$MByneH8#7q zThMd$SU8jwsl`dri=*%2<`(qSs)KKV0csoxdJB4HH{%68JQp3e;CY_qr5WCOS#*|{ zW`Jpyw?C3~mUlsP*v;}jh5r5jndSWv`~Oa5`4m%*v9y=%E^e0hZ)mriuCu(UkWm~q zyBBvvH_Mv~$wzOfuOlwlkS{=a5duU~r_bF(FRoBYvEbj}@ zY6Nth<)z+jUWL}t>490^1?}-dKN`pkhCIe0+`c-?d$}s~xzIjUolECtc^@8$Be)6L zHmB<>@6=b3`%xtS=_EV7?PhsbPe$lF&|*`%+VhZUM_`%dEmcYS=+l6nA&?KLo8>Kl zMS8@WDv)Y=vdr>sXe2X#Z6I~@WSQl?bxrmj0%?>d%Pen;o3i&@NDDn#W_i0$!%ZdS zy%Ew@PnKEU?=Zr!d>qngPnKEU+C8J#Uo!U~MW@n=$t>^GQzB=Dl*^N4mUsNq(RS~0 zkScq!%<@*9EEP+D)XI}(miOF1DOx{BgFIPgd8fmC<&wV-X^tn$Ebsh!GN-u)(t1yp zS>Cq_$V=;oARY5$ndN=)8QeEvKrlBT-SK3Z<-IsqD)wmVaOeqa_ISHl-VLeIXNn@Z zBuP9-xLMu`u~MlzkXpDs?Ztv>qaWq}@i77W02&(!+B4gIwy8L-8r&EQKz^aLy}OiI z-qQF8CNn#rA4tN;Ebq<5n6jgKUxNNGF;sfVOJ;d9I( z9I|mrLa$1U#_@wq%rj?0HdqTl-2%b`c8MRT$xEkcn$gqC8 zr5TEaiCpVHKwj3^w)JF|w@eQyXezvM6^G5%+A=cB8+T1=T@ZRHVzkye%bO~LFm<7~ z3@}nCndOabAGU?+3us&<=%>4wQn&%)Dl7!KLTOt(p1bR6mg7E=nVrxNDr37HGd;}| z+zB&t8T$PIBN;N-%a~FUEHip^A#7e<8T8YAO)f`Q1zAsNTRfTN-HKP4IO|T(-%`dF zPiA@74VKm$2Yq&ckql*)cOK@mIM`Q!c141IdbFv6mt2@W4f2Z8zJoi~lpldf66*G; z)8f`2o4?!3EN`)wrIQqbUOvD`hBC{0@k8mKjRAFz1pV|x{2qX0Jq+Y{rF{o?vU%Yf zVHQDOsf_R7PBq=8Nv^w~9}O^)As^fsCS6|vuLF80oxiRO`stZw{|?DI7s$d&`ws3R za~t11=GLnQy}mNOgS*(QJ`uJ|XXyO{jASUYyv^D~TW|`X#gU+&US>|5l*)Vua<|g9 zcrwfT8_rz54><$O34NRdQU<7^dp~bn*Ego`xyF{%1{l1v%EbU2)G;2;Q*+!yo2yC z#E*7Yq2F|j&hq~AxX9`84X{kuxD`TKWR~~O8uGAK1k!V!EVI0=%1Lc%Lu%;BGRs@7 z5Y7g=9ef>9A1B9tGMgSN>1}t+@^)^6ciiX_H4*xB$LK6?&nqG?hqOA0e83cK9vz~4 zYO@#80g~FcKsw9&NMGnFGT_k%n-@g%3#QdGm7X0 zAyQpXEh9;t<;|G`{opMC!xf@V?~ioLoY{qneE{H-0Hm|L@8yysvL5P3HrsZA zS>7#}r{L$*{LsrN!$r2&8kyxi*hRqlfZ7K^y5QIgg`4G_oCD7i13(RNq|Wl5B3orT zk{6Q19XoQCH)n|`J9)Jc&{hZPEbjt$!8#7e?>8K12?ErOGkRs|V?;gBF$_HRH^!Edd?J+vbTYIRG z8$kJHdF`Bp%<^vgOlD^f13IPQR$_S6S>E22#In5uJ!NKB(e2F0EbphoB~Ete&nRQ# z$Sm)T+A_;q1$rH2Y#f>8jcp`14jrJsNemB9_C7~ud3W`Rva`Hnpigp)&hpN<5oNFK zOCfzhvaPYq@=n6b^t{Gr2c&(TEVI0?ydfvbIY^gPcC)-Yw_q&99BgK6-o?*%adWf0 z6Dx;91p$?d1ie|_PkPeJzV=<-=u|61p=Q|8M%tG=!CrN5PvjQpKy42X#l`!Jj9SWG;NIt9*H?oxq znzKm06_D(%X(rBvf0A2WGCvVKBcDN6i{~tW}pTp@ce(kO^1e1{CvzRDsVW zAYJ>066*HYAxIX;xsxET<4aBn_3y8gvXp~dEjgsYM%k_zb%OI~!f^6@F1K;v@+{QApAM!~> zdSj?{$G7#Hp@i169+fuu7tDRfh0>ntgPz!?*mm5;(D8UID=vrFq>s}CVM4prctBZa;gGmhK}Gy1s%bF7CkZ zgIN~jxH9x7WZ~|4FontRR)7bCFyEYvGF$NbRtayWt&j2MCV*HzLVU-~$Dk*@eVWj_ zBwnJSz$Oz$CXWe?Huq?Z;(`}|^c*%WxSh+#SjXc}Os2}%H@;wZ$gla9*MRVX z4MJ%t1WBQo_9HQr#CNBmP*zvez&~jz1c!{P2ctS)Vm=x(Y0H_Ay&wLQk^YTu)#i8~ z%~>eC9=jaImZllb^4O&aY=>^TAn?MpkR^+ov!E_HGL(t;FJbN>C3QBpKR2!2p_Ivj zvaV4!RCUO;9TG}Qr$l1Ylqn>@Yf!p) zD$NTdCa(KS_8kUgyi;R)Q+uRaoD1h^tB&|sqL~kACCPk{`8JEYh-KQ8FNdDC4f>%V z!;O;el~Ks5-L174U(Q3nogA~I7nt@h=S8DEjP8{Un=daLr^ID29qasnyq<+#J(97* zOgg#_C3a4HfleDhtsO`=2DWF{qPu~ZV$_pslv4YbG^4)n?40WRQm_91_`W+3?+E4g z3SM0G&IS2(o!aIvXjh!BzHbN_rJ;@Y;xoYczE2?enSdnSI00XRj%jM1hgMbf2FO)? z-^NI8<)nb`yXhOTH2Ok*hmfYUqxilr-E{Tj(T1CoqT9B_yE71|lq z?FhxvPv!=aQ{eIXBX2)D2LzDJ%whkqa1$EtJbobP*i1hQBQZG+R*_x%yC*_xk`eB4Pv-*?Us z31V{x^lRFf4@E&}a9XUVVhcw5N#rJKG9?E;KfwbO}#rMs=SmZ;Hj(M{9zTM|X z@x|2KfON-`#rG}qy2y{_!9xHxskivP`RYX5y-PqU>&fE#4qYfEZvd&OCyVcU9+n`N z{0&HbJXw6-`;Dd5CPJF-$>RGSnIf&W9MWn}7TDQGA^ zYC{{H;_?AH@qMp9FL821FG7sgT7BPhC!%a#)uA^DFj6S-ee)HO3ikjsA`A@mC%Ybb4tC%$j?wNi!F&|g=^7EgTNdK;v8BcM+UFp{D8zL_yHaa}(L z^nE1gr$?K9%O&e$AkQjoi^s=ftjWDvy1jV@PdwQC-JY3o=F01sL!)l@H1y{JjAY2* zcr$Vfel>)^+JM?bf_{3UDKkjI4gfh)Y2U$}Y^uF0J^mx;OO^2*+^MGV9f|Wj^q&Ka zWGKGxt{0?u7XgI}`s>P|pPp%I!8GN{JOMI~(!PVc$c$|!tyckhO=Wxscd_{c-}vV^ zZJ@syU?fBFeMjJ4nZYrD=0<{kdYKv1U&5{fxkYJPJn?;}4weD^H|Xb-vBeYLx8NH4 zU}?f|C(~l{cL4Eyi`HPN+sm`~zLjzAv*~>X(gjZz-?t;KR;B1ZFQy3gq|M&v ziSIiFZ-sO1aziTOWWSwz+|0x68Z*_QHwiF)@T7TpwX{VKKm!yE`o4=WL&ML3@O?Sz zY=9p-Sbg97crn1NMe+|M=|#!j{X5@xBUyd)P55&GNPXWmyP)5LmKrytUJ&(tUt0wI zDQM3Ibnf?(llZ=`Jqxlrs3wu5`o67bg~#gv-d2b@y+6_|^Im5}ngrm(0HnU}cwD8p zT~ia+tM7YaFuvNv_kYF0p}g39VUvxWBD@F> zk-SSq;Ef)zi~7EO@JPUPSCB)M_IzJoxzmOJ!qf-Tvp{|tNvrQ$3d_&TCIANs;(oxz z<>xi~#3a6N&*r!|od!*_c_we;MEvfHr&puDifz<`b(IbHzH3^@b7~Ig#gyS9+iQ*ZzSI8_uqL1uL69yu_Cn!&-;by%dV=cbNcDXe z?nQ~lBY6%<+_58l-yEf7(ZU))>m8`RZ{dB?Ee}EZ)5+E>4EVkc*9#abfxCWeHbb4i z7mHO^_YB)4KcZe3WErIczHi(`u}|wmZ=Qq^-}m*`#rN$6eQ*-yVVV_A45z|MHEK8W z0rVxxP&AfFzkP-69czo{l;eRDt^6r_mi`@Vy#IiKW%p-&7jw#TUNyD}uh*jJ$J zq2#jJYnAxE4L^}9-9A9SYPi`n73EgY@1=2aqMU^Er^?Rvoq$)pZzDB5CSbjbpYP)4eBVQ# z!UhCXA`=n70( z#je30^?j!x`2#1Z@4Eykt6XYq8q7SX@4E%b`#cHPRgnss6G*-iknFDF`@VNH6xxiu zO{&r;FE(Fs#P{uiPXV%N`V8b^g#18-72kJfHt7sCpw#hH>-#1SkS^CA%IltLecvJn zLm_G>GaSkUr`ql>zVD-_@zp*;7C~MUK!mftZ+CpHgX^&m%t7L)S)K2D3}58rDqMo{ zuSVgMR(#(ndBxp+q)a&UBsQ+4Sclg4HSc37IhCaZ_s8xCd1=4*qr*7u#7Q*tW}xw;}=DDi!BrNn&!wN*NV$3g)KcobNj) z9BtKypU348oAhz(`|jE!c@%>3tfyMvH}&%p`DG~h=&ak<`o5pkm3=!x=}W4f?*ZSp zPV?(ORV?g_$tbK-p8d82SoaT$Q;>DpEi-?vx+x!9(| z$mB83_vHr538@e^E|8te$5_YXPfXd*afss!c7QCtZ?jssgA4k;gz_iwAcbP$GNVZG z-DxNk-?tL}NxmBg6*idxH!&iuk^t zbwH;%1^rrbjP-q2c0`9viSG3nHeX&gj`e+OVdyu{K(83d*b_>8-$g@_VM9R897s0? zwrAI-yMdTu)RQYULhmnwPg2GVAkFiAr&UznmwNU8$M^jX@qVP-+QEeM&IR>-e}{I~ z>FWF5LP``evwQIw;C$aWBigD4a#JTs4_;FSFZj3W^MzO% zJs|fcqzCONzHh~8NW}lY>-LT1u%QeCQOy74`%=Bt_oY@#-uLZET~2)8m+8&<+sMpR zLP-qW0XyIK5u`lhQe!(j*!LZSk4#Y3l>t|$9a4H>mWG=kp%*P@sm?>M^L?Me zov8T&+E-3j-?!-F*mW0@4>>95`!0GF=h6jecU1STs?PVF`?d7ZM_>$>RG~!>tj^4Inl3Wbu7#)RW+EKd1dm$b0Wbu8!on?ARR>4C6HmSGxzCTruvT{L4 z#XVVk-^o!@w3i{_^Y?CV@qMS@6-RECPLR5LviQDvj>sLzXh`EdS$yA3b46YRX_+UB z@7wOrDC_%fgS6X|#rJ)(8 z^L;OzlPQG?km|TS?L7!pR@eLHuOW@o0npo#pgptQdf#WhmD)}NIag^r-z2{8gq9L< z9rP_p81a2yDialIiGk4k2K^i{RC>uveBYP8#6$s&fZ?j}Kd^D-{Y+z1U~kCA$pgJ4 zF&f7YHZf=Z!Vm6JusVQR1cLd&1hacow2jyY(Ada`e!98&X{&@?0P^d|uztFw`3Toj zuJz9#k85n(dgA-ueLdP1^cM7}YOdCnVK=X%Ne5Sh<2(sHFELtc^?kd{7N#Qfx&cNC z#lbq8;!#qlj(`S6f_}P-c^IGT;;g5GoTs!cp7_4^U`sIbHT12@*ls7j@1OYHduEP9 zzZ_sBL-BnF;3<>ARMqjqD>kpL4EpK5X5TfTOMod}N zrJz?<#&>WRn@uOA3JK6V2N=mveBZ&(3pfnW`;nlZUS?ue$yl%gqx zT4j`6y94U4pq&pD-*-$y2{r}#$I4I*gT8M9K3~km`xeml0I0t2-3~JIb`tuZj#1w? z$K$dfBUB4-0%DU(zO48CxV6aHAU*BL;`^q%Ewy<8QWZ}Y-uExuz+H*$9&MZKbx7vDEqZaEH5Ldxr8zny#B>_z)=6)Qro8({q4Nt184bfu1f zdMX(7eLtBS;%7u!@5@oA0i5Mv^?eh!;|lu)k~fj07bSZO?|k3dLvWLP5WvX*q`q&) zMX2}-%a=suxSV2ErqDl`y<^l z@ASo?d>6pf0HnTe;r!Bw%b;&2hHlijp=G@<`hw8+&5n3EHb+5Th@{o`J@bUS|Eq(y zzOnhj@^k}x%KQjoJ>?YP`Sm4sY2dFsU>Eg$pXd^8d&z4c`z!7FzP{M$!Yi=`i;w;k zkRM0V>ic%QjYG5+z#f9QA8>K`Vbwk{iSPU4V`%+Tpsq!d>ic&32+vNb>SC@9n=f3l zF|&qW{|Se^6wq1^z}5Gy2_MX~0@X`Nu6ojP;;W7$P|o*2&5R_~_l-S|aLWOFtq>Ja zeczo0q3?rsLUlUJgT8NtmdNQk0Q?BBR5sxI_QP*1@pEbx==qi5BHL??_`Wk?KQdSu zP<#-i3y!@|IN!I-Z|LD&K)vBe^?e5nK(R+6c{)klu_JxolEvtKO2k+WXte{?_g&XS zy3Srm$DPbGQ(~IRdf%T>eePqo0Hv+(GSvC|pzpimuK2ZiKo(Ov;QOX~NPOR#&>JOT z#P@wV1x%T9D1BGxeUmWa`*vC(&oz^v&r^oFbI|vV!h8}hF#a0QP6hc01$^IYFUphW zAAtUHp!&XT@k7uYC#nISda>EI=VKS}eNX3>HY*6IoPvCMPzO`r_a^T3xp5l-YN;Sa zRNwbVjEp&bp^pwQw#TUNyU#`Y9F#qjTsD42wVv+E@Us}m+0)$)=qC*qM^jPG_xmY6PWbu8gppbl` z`~vB?%Fg#~`zXdjq^80ItnUiS4a*~^^L@W~13v=^s9+@M`M!0RvhT~&yU|Txv%H$E z7WlZKhS&QxYmUc@d30 zx%Ix^B6+(?+{kXd?_ngL4M=uZ@qKgQb*$3J+k_gUD71OS5#Kk>0$B;03vzx!UZBE? z?>m08++tONQq5DX?|Tw2dT_UF0i~U%THp8QGSMMwC-XLxQBJkpUwq$kHF;P+VE5aXx^&L=i8P z_`Z9};xo*|eFtW@avVy0-(i?MW8^gC>x%e7S>N|)e#tUz6Rd>C=4%7-eXC$q0WK1>^SH9w$3QUP1zKeLu}H=t?xSn?)7yNNZPh;bPtMAL>PfRO(HV?jU zOUUB;p2e5hlK8%alJ84WDCU!!C{lcP8VbetErWlO@5>?MD&n+-?@MDQZSZ|N;XfJa z-=6Qg47+T{mZl2M^4Q-Im`4NuS5(=HEp85j`puE*`(8rIzb@4dB+mCuoe;()$c5&n z=YqTSzWJe*P@TtGx8Ao3k{br3Sl-q7zHOm(Q@th)P|o+I<}kycjd!}wHA$?N=clMp zBk*P+^(J(`I3 zKd{+Q+_Pl8Z;j_ARB6aBIK=tB2ewIo#!wPH)%w0~canX3LV3rjv8|{*#P_W?3(YYZ z(tMKnAoFb&cMN}8pU)!@s(cM5yG3v=>-c;Y0G|%@P_p187)T{qL zzVAB3+d;X#4HMEk7u5GX0_}v;)%U%El-n-Vo&nDHO@lH#fz1Z=&H(qF=VzdmRDCFN zRo}NNlIuAs;QM}rB|bdTbcEcEkkPcG_`bz|#4rEg|A)AJV>xUnLoXEZfBC*tZ}okt z)spvpyU-~nzVFYIam=qFvwtbWUexoP@0+>>TyJcg8k^_AzHe6;T9kEJz!hnS0bZD; z;kroaq+yaBp~Uy?2WpTb)%Tr%l$kD7jt}qfomqrtSW|5iI8B2S4IQ2MuI8Lhk7h zZeR6%=g}(c(a@%-&f}-^eQR7p7K@>M?sWBi(=UbeJ(Bl2Dd_uNcmwCsAJG0$ojW%D z2|3@l&KPk|)3(CRJ2rbro$otml{}digjC#<#rN%ZP98H~hE&g!#rKV#DOO=8NZmbI zeBbOh<@^{8X}l+k?_0_3y$I4WPZr)5*Cp;*a%t(HUBpxK3?>lmX9P3h$s<}PwJ&5g6@@sxGUXd=<63|73jA$qGiPQErPXN+Cz|$f6Zwqm0YiXPQrOP?%2B z0XG5IY^{9^n}iYH_d~p!%ooH=xH{#*7SRF3 z_r23rzzTrsJP_Pumg5S;5jy~SQ$fBtbL)LS{!T7OW1!DchH4n}eZMa#;3_~H1EBi8 zV_V4t>@U!dJ4SuqfjPw%z6I%?CyVbJZXxq_k9ET9AlSG8LRrN3jmEctxi%#smGflr zeLq_)P231lODEe0Jm>pHCq#w*p-WU>=l0M%wivebkvi@_Z@`S=1bwe&s>Len`C>xBfjr}&!u@YcEt+jShkDGpZOciwv_^I{~gCCR%K z+neNS{c#;XYo2ZfXb*s20+9N?BiBH`1nuAC^b2PEAlwtA>wYhrlN<|zU8 zX1N92dSBSlws-yv@{dSbecyesz`42a0($KAK-gqsrwC`n+nc;gQQ$8Eg$3qL9u zybAJ7r9I!*SMGG-D;+xF2wF`C-*|2JwAQRKOwn71a4i zQhndJnP~k`*Kp`@Y`$>G#>^VNoC|mnpj94#tM9w(SCCCXbybq9p0u2~!iVW+c!q+S z97(G0dpH&+{2~A=6`~@l?|Wkgnq@n*!>ZF+9`t=vT>*3vz%7LWzVFOpn1!I{)JM8u z{RcMNAY5d7tr6dM@!!URWdYR*f_$#fpOEu?hrET;pe?9Qj#S^bZ)&vCJ4hZ+5_jxK z-}gd)`F!mnK+7DczV95kn%ph7K|17Qo|y{zzH`b;|Gfezrn}2f=kJ5QZ_eG~*FFU@ zztREU_tO{f@nHJSb7knSBw@t&ZCfbH`o6D0?~#NN-*+iy;Hb&WyU;&ShPrdm_nrQh z__ZqmZB~$vP{8+X@TNSN9tHHf1J(Ea_g`7>dz+*lt||D~1$^Jim)-L(pb`r5=~0Rf zau%|)V!DOf9~bZyKur|nj$oM{;ZdjMB<}%zaDcJ*JL>yp#Sb|0FwS#Y&KkJJ$Ep>5H)P5BRxoX+=cSr?`Q zpxlw5=lhl#%)T#A??%Tz56drG74UIS#9+NtLiYN&B0t>+ar)qo^L;x4=t)6m;qE+k z9{#BBI}FM1I!S%s50LVSON||rh!M~EzN?VDQ6+9<=lkwM@`-?CcNO2a-g219$lKfk z6V)?N9Pxd3V3h@%rcXf5LC8uftoXkF=9kV;21*4_wZ3l!d~$=kTs)NKo@#yH-)cvP zsGZDPPzE{Gc7O4GAIf4ZG6V9W03w|AefPG&&&N?cHiFqo95t)+eYar#f~)Wwlye%T z6rHr<`wpKV*08|{9gB@?Y3KCC_g$1a%9bTJ28#0w?9@0Bi+WnC}{%Gpv`-*?|$^niHh{blit1z;QAoUHz&^b{dpb6o8tgHPuI4J_`bci$|T~w0ONdLE_enET3NAi!PWQW z@h8T7i?cVrU=zsV`%a*hn!)wHgp%(|QYfYX&La4}G!%;OTMYjs-YyXl_dSD@t1i_JB+mCWeeu&b z*lcKSdM>#0eRDu7s5+0e&i5^cNgz6Du8M_kbGa;v$NCPKuj^}$;BqB?@OBJ`;Nfe z_1pXtSmmi#|9^bn6^Qp8{^Kb@8|Z7<*=a)T~WmU z<@-{-)%T@VOWyZwOQ)FlzOUn++MGvbS1H5u)bpJ0Yu<+Ijg3=d2ey`T$c`^O2+Mb# z3;!1iQP#x)m!=)AdSRA^t0SeghDmmW65sa?P<3rYn{h-frx}7gO^a zq(3}aeBV8J4PR@`T}V-w_mg^y@0({Re#DxN?vs#mdb0Sw@2!!NKM$#rCyVcEnn}@` zL2BvA;`>%OB643y?|8EKzN_#fOkD37kY;wCd0^~%c?R=B?zE_t@PgnwdRT4&g-(1~8p=lTh%^v8#5JN+p z1bzFg8vm+yUpo=Ed;`Yhs?p2X8r81weHOOxhkC zF~MwHASLSn=pfXMaxim7YpKfWE6p6B>{T}3Ajcr?x^KWCSJu4B< zLcgXFEhE0~eOJcVp_mTF=G9t#->p?8ucFW^1{f)n_`cikNfR~&)HM?H(_PFUI3|4H zMuMEAv@M?azKzFA#HG+zD`O9w_`Z{BOPsyXj|UjZP<-FQm_*|YZvjd>%wJaq{d8Y5 zZ@*-n2V^m&ZSlnS9f-$kj#v|VBV}yy#P@xqm=v!o^nn3JG8Er;L`4ZU9nhzdpr0OX zKE_DES#JTkPif!59c#*-mTrFz`ai^IPnCl^&dmAA*lw40I39hld5mPp2Y0+#xLJag z1oUzw=%*)|7cU6i7GyW2eFt~4xzs{Vq*2f(E8{!3Q_T|mjy0bZpF;m8z(|JT`!;jM zI{@gfNYGEuG*xg<#9^aG;3fc@t+nsqE;6$-OUvYiUR)X9!Ch?ryCJ98%g_@7jASUj zujwOo?FndfBY!MwmeBa~81uO-q+5^E&W@dT;TLS8=Am5xh-*+!QLC%+>VbG^2 zLp2QgzAaxA@H0Sb0-*Z7QL!>Fw;%c;$EfdH??Z7$uRyxt$!@*x9GM1wcoZH~uyF&Z z@4IZJv~yudB|KSt-{$#5eg#q!C))=+=lkZX5EYt5m#7}ldpkyb-zE4pD3&KcnwCU9 zV1B}{7t=kp`5e+JlKCD!i}=2k8cFf@K>FE}#rM5gD$4r47a?6E+1}@g@0;h4^pM!m z82_=^qt70b^L^`oDTkma^oju{==-jDR)RGJ)Ki)_g%9Wakc{3AAr>NZ9NqF8E99N(=V8&>2Z^u;$1uhVe@4| zCz0eNzVG5VL@ElZVkD`)@4%cWb0Yxl6rxV=k95my$AD}40T>>D)c4I-Svu5g=qrig zL7S%pXnNU3bH48qT;sVFcY!<_NvrRBDmq&3{{TJwULb6;u~UR&F^Y2Re89^;U>Eg$ zPj8g7zA?zoN_)O9Ki=4Krwf1APUvAEr$o}~`}SOoHeC#0Jwe z3sBDfpx%ol)%UHu1ULF00a&UK6;XZP)YL2+q3u(>6m?o3R4kkm^T6gbfGY|GeBaVt zidqw;!2YUstvpp3i`ft=gYWt7SLSr3;m@ejQG9>@T+hf=T+z(lQ81@_QltKsmaU`=#!M8 z?i}=ef5!qB&TuK9uNCAY6!3jdu8^mxp8*|lp!&WOYD%1IkfO%B%JH$IK_!%>ep8qM zuZLIEmBxJ%P(cOx^e9CK+4;VOHp$@d5}>*Yaz}8!Z&7^Zl#f(L=zRl>z28ya_p!1< z&H-f)C6~=!tHk$xyO&())&Sb9;qKB@lw0rn-(K-zk3#=bnGAm4_h=o76PkdApp84C zjU&Eq_9b%9kQ;gtWo#VreILgM2H5bc4!r>}JUrR^9PxeE{UN?@7wB&|Mt$Gx1MuBH zy0*UuX(GwC#^U>Ke#_YJJTHN?+>^!kU42hpkoW=8UX`8i`&vHyS_o2ak>XuJxnX(a zbiVI9H__;rrF{}x643K~(_vE6P47nM%#QhuY~{emjcgcAzHiO<@%S(e=0$h>alUUW z09`2PBlJlA7#%3<)#fn+kUYdm>ibSY%7-pB_UC#S@tp7b8Isqi#EtBH-|a{~9FXj; z;`_e57gIUN+gt&2TRAR{_`c&Xwz6p&Hwhylwlw*uu;Tl^f*SFGE(WEPr&`~)KYkIA z)jCibd8+k&6HkUh)K2DgD1Dr2yTACpAD1!~nE?5t03w|AeS6l6w)I#8W<7D#tj_mM zgZp@{!a*n}H42}!;`>%zE6Bf)qbEx(?VP^&zL)V>$;EvVa^B>S1_!^3vPcEUbrjKI z)%m_fQ%JSigLy+aTOjNEPR0+ka>J{y-5gl=!~Ay5R~;jkp5Lx5{xS@qHi0ga{)C zAfHym7s~p+|DBdlcfq8Z5@-YQeQ)=YHpmXSs3Kk{@qMphQk=7_4yJ)}wp7;l&5}jF z^V}J7uOx`|eKX@pnWKz@{C*O|`o8<}NZr1Gyh)MX7>?!OS>N~I6ybgWbKG&x_g(Uw zWONhCT~D>XZ_b{w@1s+3JB&@v0PFkSTrc}R3#E*wTHkl#Oli}4P+F0y=X=2S&4LA# zd?NM*GcL$+W$2IdeP_mmEW7~V>LAQFC(ie6g4cM=Apj5XeOK0%NyHlg#`(V7_77pu zdK4QMTzy|2e_}Fp!u?u&!McPr=wU+fMa$8M9rS$(CEu5%P)ynX&{yNT(@-eBZ+`rf zd|wV3_ia7?&NGdfw88gnhW})we|x^~Z0xcITbjZ+%VSH@y#Y5;LqA^a=tG$ zhv^CJ9jE(Tlf-Jh`z-B{n&l2DFXag)-qcZ1%T-YJb_x-rMl%*<^TApfs-v(dE zzHOm&b876%)E?sdcE#ChhC-T5G9P5V&EhU1zV9l$(QXz(|0>9EqloW&4KpNWC-h&F zW32BxuN;`m(C;V5Sl{=^i)i~ebisVseC46M>@Xv~@AecZR5?JE9Y{9@wr7u_yMdTu z)RXgnj^1y-^GurO`wsj-eP8O;{~zCX3F57z+&+T|>75Je`|g0Y&*|#>o~ZuxvfLEebx7El^=RvXu~|6P6Frq4tgK`=Y42%oUXp_UsaI%mq^~= zq@eFR6>k%npP~JsI(KaPqw9UQ7LY!A7f=*tM(rVWzVG-c;z2$MDW@lk@B2$e+534& zl{{H|-?X@M;uD}5q?Vp6zHj9i=YK+a$CJhPtv6TX8IWdsviQCi%1Pc|LHgE{#rM7R zD}IKWj?Y0zM?G15-zJ%im9Im(?aAW%X27HZ@11cr)&yXaW)a`FA8azN*t3wzc(VAu zgK^i)a(zfmJXw6-b|pma0jakqi|?E9u*ef2P4i^&eT$5f-}n6-(kf3D-**)zc&Y!J zJ&=C(Was-9lZsu0bWLUF`@V*c_n1_3V1i(?gM{;aKYvH;M0i0r%z{aUS%~k}&LUHZX6ZSt{eqFCV`YDk4mA1tb-?x8rVJbs^MHyQ>@qOdcN~636y;p#d48`|7 zhVR#NhT{Q!90~gA(Prdu3HvR`?MnL&?pRan5`H3wdg@8&7l_d=rM_=Wx@gP9%*SmS zHjj}E#rN&IPWoqIKrcpuetM$Gnn~zHknNTB9o)(0U%WuU#Tx|uJ!O0ccdCiP8yn1g z4E@UhBN>YC`}DUGY&W3aBSAks)9k>tpTph;nc`ztYu~|LWQzSFOg88Rl<^(h#peD# z$@N9(4FZg0D86qYeA$sR>;hE=Y;ep^LvkgCZ#$XdbZ4~62 zGw1tettO=(0DX)yRKuX}TLiD;aIjAREf0X|`yRpz`aJXY1N6O)QQtS*Q09WqLb~M1 z;`<)XA+vfZ7vOaeY}^3q`!0%-+T?*$(38dYtus(s=i8S1T&c6qY+zAuav-}f}6 z^CZ(4Aa30;)3;g3HgEJojQ`l|(P#U}`Mw_)m1C6;dg%ZY^nHsrm$s+}C{e+n?|TXJSZ_v&q zr(ZCI`a{15EpAaD6FQ0P!-8Ay`&&8;qxnFUjwIFhEp-*ec?Cdog{af}Bi%Bw2GAP- z-VQ+O`+n(e)TTjSN(>L$JS9M#+(vW0Z-Jw7Y`zEib0n?4?{iPcfxZYR<>EltWMiiY z-)SkkWC#A-19nm0cfxWx__aZ{QQGr;`N%on_p@s5{0BKEl2+fh9HywvTmY*H;(oxz z<%d<<8N~P9cohe8C#YW|N%ehytOe)_fQMl0_`)R{Gi&(8BIt$LfR=awuDZZLkD;h)X+#$ec#hV@c1_azU#%sG~4Ycj5m!eMVgNlXg zU=MQ)z*&U?zHf`cQT932EXDc{Y_>tT$o5(zzHgnY@<3YvP=z4K=L%nS+v zP|X~vzHd2vz{hk$@;fAP$By)U`*)UQj57eucA)yc*KqCTf#WMk+nj98LhI7Xcb;3} zdp8W80CZhJoxczIzHM;1XTLVxr?7so+2YxVopC{qX%sGwODNm0#i5r^!ieu%;xYN1 z;KtBfC1J$(T{ADQ|-*m|3R(#*TZ^=2I@iR>QV)KnY)WOvE{pgIG?&SehSCBh`^L-EHluKtT z=sg0Az28ya_uCA_0X^ThBYpwPP47nM$d109tpxbEL96l2(uC}l zzry3gmx$2;f1K~z6hK=FIs)ryW5?i+`o2Ap+|Nns`@V~msV+5kUn`7w&iDNU$;(yZ zMs~jMMkMbGNOo88eNViE@5&=@a~8}s<+wQF`)>VN9MLq(F%n`+^C1;heBZfmOQ*^Y zrHH3m-!~r`hPy#ED6e>`^?mnl427tjOgkvuooc(k_`c1XL|J4M{_uyI3( zyU0j`!}#S8MoK}hric!!&iAE^nQH;2lXA8|*7wcVPij5{@+3vPP~!W}$J_{qS^{R3 zavVy0-vysasdhs?rid?;eCPQK33VMzXhooc;`>g9Tg16#hMZ3kFO>McCvf^PR}sw1 z%Gpv`-?uS7r^erTZUeb%62$txTNX%xMnImJ1hKyFG^q1^v+u_}#a;jp@O?{`luP5K z0ONdLK7wJK8ELU`9_st@_!IL~LBx+QSRJzXzJJiuSkU(+lzd;3u$cN`obd78X($xm zHwXSnzAuN2dle2e*89?!NgI6M`uI;q`nTu%PQxzCv89=hvpn`Ux;NlPiu8Rqg4*gx z^?eT_<)lls1Bvr}uOiv3a-lgY7u@;2k3f4;bslS-?^_VbyoZ(~5W#3*!5Bz{Qb6-360swF||!z2f`cyD6cvL(bz6=lk}mF9BYFQpHoP?|Tz( zV{`aKDD9mZyOG*MeBV(|p%?Xs^d8B4kohTuyNLL{=gXr#=0N{E$Z(^G?;DpF&AJ)- zPsuUX_Z>ywg8mcw&Ey#C`#v%Rd8I)Y%#O`h9?HuOGvfR9{0apx0jR74>BhkJ?BR4b z5L1kLa*o~T{nqy-&GUVGtx?~XdiDRu_nn7$D=4=uFd@BjL4Duvplx@$`o4#ea>}LJ zGr;-2*N_~Aa@c_08Q^^1IA~9)z7x5s?^_tjWtokE#pfrIfXj z8asuaCg>cp;|tXwBUM+@-**p^e+x)5LW%Et3EDl?wesrwrdx;SKWyA& z+&Jp{QnxmRp_OsEZv>0EITBXtNi>kD2RYFpHbmKVm`aFAZStf-|L6g2fa*McI^VZ# zU0iJ@LYwY%^?lQ~$653#lD~3N(D(fwvwLP2w4L~KFkji+n_`ZEQNbvfQns~DKzOjFZ+yhc?PZr-d-5|M8 zPk=Pdlg0PVnO%I}&mpbyWbu7}sRbK|j?W%QKYOzHzRhpLFCqCNq-&lmzVD~_ITn^< zzrmUSY*KIWeG7aiC4UA|F;5oX7q9NwR;vlAt|yD{y9IB%bE9^I)XkH{_wBM%f{%hU z&XdLW&4}f+yxw;qq|ZEAeBZQ>i|@M?(k@RH-**|=PgL*Ikj|^@eBUr0<4p*&3@NbL zLBjdIcXLR4XMyZ}pw}ZK`olIi=kNn@9CifAnUP`r zbW5`=rIhwdkQ+3%Z9UGvjcJF)Dje}J^ivwqGUEHzz!|``z5_kw27j&9_k9!ZBQuj7 zdeHzQg%aPl=Z7H+)&TTsBiZ_`chl3NsV>0%h!h6W_Pi6sf`n z=z9ZfTO*}Fy}mWBS3GPZck zj4;{nNu#_9y=#Dx3>h40mNk~Tjs!F-67pPp%s|0Q9sfxM@*@8B*nGYiNG z`4|TMoY?%W$H#23$%=R1IoIc*zZ_sBLk5?cTKLR9gKYuzjRgJlGSd;W`bgvhC$zVHtM7ZM zs)Ria=zb7PHg<~ej64!M^EUi;BQ{@2bQkq~x80O8x+=&7r9I!*SMGFSdfeip-xK7p zNLqd0N%?UI-v_XaAnpg8H$Si0h85p;)uZSPn?d~)NviLA^nD!1vjD=|1L2a5nKhgu z1pG0e1s{N`?^|>&4r?V)jg{o8CoN~La1%`5o6ey6N0RFMzVbMr2>@m)L`78JHwS%I zdO5U>s?%8>^nHKcjnW?ga6+Mg?^|e`vCpahLQnmJYY;B7z1E2D`ww1qJvFT$Eypz1qPecuBYA+<+xZ<4rUNBX|+pOp2!697$fp!&X(G5N<`=W|FK zoNUd)fbY8iZ&)yR7|=xpb^bo+`>uFc*88T|0qX~wEndL)t-Vk_ms|k)b4eKSeV@eF z5ojk<8+y|ujQGA+>d2GQ8_v2n!r&Hs!n;>@@U{uege4mOVXzH?4XoYK%=B!-74d!Hk|@7t5*_k9zg zw|0#BzQwShm#^*pAq^(k)>wSs^;j29)BNTGNFRB!_`XH(f*pV7c`c+3Dm&kI#ZCOS z2vX0I;$1wU3CY3`aN4g@Nv!O@$dVV zJ%GoDA7Ng!#2@GT)&r18L2u(%#bON|1nbr2Fo2J{l_W$05sGUr6C>@+?yTACpnGWIlLdYP<69R~E*7vQ0 zNjI*?A~4H{qh@u!Zv}ichE3hAQ1)vSK551Gjh-)`f<6cNpCpL&eJ8+)<+8-?#rI#Z zaYKl^Xno&bhDBSX2;>Ti=&-)C*Qn-s?ZYgI&G19DY4=H&1eK0|=**5S(iSOHf zkZ`5Jyr`TFWqsd&Hi++=0Qt2fi1mHP;_DV%w}FsHCqb<5`)GN|XfEV06zPrOSdNVK zeGd(kP(Og#>p188?mQw<{)BSTQ?2j2@MAd?G5b+r+Uyx%ecvP1<(TJ!lHXIU@4IZ8 z^zlki>XEAFd%*V{yG}ZAM=%3}99M?^INvv41A(UjTo8o$=EV8FujAKp%{BlJ@O_Vt zky+O>0mk{h-1h%Liow9e1y|pf$Df!k<1wDa7pw?beBW+eaCr~pQ2IJ`M%T~rY*E?PWQPciPaiqjtb?cVR|IwNe+qS5aRnbE*BNzC`%x(BBThl z4Hr;+-^rL`XJj|zV~Tha3*!4$Tol$RZ5#P@yY9D)@DRNR5& z``Vt}n(hW-icwF_a$bF3(mda{>p}H>saOAheBTccZwcjg3?`&^E~xLj4%$YitM9uH zDZjc@dj>e)_dJqs2PEmn3HW+POjDBvWz2-lW_Sv@s_&Zz$;F%$@O|s%l$-Dxkn0d~ zj&>B^cVjy=KmNb9+c%cOhB7opIsTXLOZ8UYms%}(-?tW>V&eO@e+iBL6EgdSGOS5G z&-uRRkP`KOjGc9yRmK1R&)jpDy9vAW(kR^_-67pwk{c|wbV^FMlprA@jev?0iXfpN zp>!i9iqe9hNc>*!_q@-Xdw2OfzP~@tWtrz|I?kMV&pCrx2fKzh``>ooRddma5OpSq zbC8E7ZZI1>#o$uU1oPSvO6jor5|Tt+yqQa@t%od)N{0Z2wD=7-bbpq7qg^LT#_-d`(_v?DSs0vzl+80TcV}dDXRn3ak1Ea zt9KK#a2KF>7mMAu+8_yh4A4Xui`}>LA9B9$M?kAwEOy^_FCwwnw4rtZ?RT-*eT(32 zLeBSPpc@7|cHbiOLA!t8{E`q45{}*Xz;j7;2E>q;Vxg9z=O8>$bL_sWF_+{t=KHZ2>HyVjxso!S|4cQZI3_ zriF?7Mwi7iHih#NJmn?-aQp*nqZ)o|>A>+O%oW@a5&P^Vyzq+%UUIshCDYc(Mxy^*FOONC4rh+SC zd4zI(4E!Q#IH6i2cHiZ_B#n>3Uy;VI^jOnF75xNX8>6@~UdFB;T&_kEC3fF*M@3i- zqE^X;{_0+8`2Z>KL@0+FwN4&e^ZKX~IV78N!Iv40t~k~VRBwk#1K0+BAV4D#vT(2p zE-%8X5dEE8=&v58q6$jMr2GYQ7+gBnI(cl(o1lWR|W4?+ZS{X#6U7zB=@k z(rtJi_{so{M97u9P;F`?fqe_niR40m^5& zJ+8BLDlMkDtSJdzBS0e&vT%dy^Q8zoK-4d}&|ket)q^dTgPjWHe52OM6T5HTgIH;& z8`&oC9Y&)|Pwc+6rYfyD0e(4&M(n=ra7q=2^8`G_HUDf%qQvgIJVx#y*&!vm6pUbvW6Jc52w6AMYU(_hC*I4*7mRqGqmtm$Y8XZ;np3L}fR+;0w`cjzbFu7_ z{H;JcT`YFr`co}!_dN}CkuZ$`Vy(NZisq1dcntK)!T#plE9z)|sn3izF#hAx9f2QG z*%+mbkk{11+!9zdh#DASpxw95TE)+ZWcTHQ>jU9HM{MlAW${HBH3iO#2$`Fbp29nJ zU(Y|({vp^AAToB}QuH0?pTN$)j^9z&d!ShFf!V(XL_(cNViLRWjS7eVVR}3IToZ(J#2yhMCo~y(z*>^&2*P;Ch|h*nQLFfU+D^jf|4Bo;00rditR|scujW zNUk(?-?P6Vos%J$YebYpWA{}P5y)Dw?S_}3M(Zak?rDt^+0{`9$Rw##A7J;bQCFT* zAA+mj9StX0-)qF~o9Q!4KhS1^sA!;&`wHK6ocDcm4K?RL zyYIJH$KeR)LiC9dat#I8ecSAo5O+ef*AW`K?>l&5j>EYKblbsve-E_#ZYwQi=EdS( zT3mj8o*J03`{o-jgF|76${Haz1jp{1E|&z>6ue7-Mo%q_-M49J84e~vrK^%c3fK24 zvHPw`FLu`D5N$BQb>RD%yziT?nAm;yga2$a{a7P*-@hNo9rG6WBcsvbh~4+bS(!70 z{|WmSE?o{f9I^Y(z~>!!+EEO=0%>@7((@d#`_3IIcHb7@?HrA<`)=AH_x1rm!wBmf zi`_TFbv$2?-FFVqLKlnOHy#UiZ1?>fXq&-~-S^lpIH&}!SBbcHP%c;=IUT#N2gbg~ z5P7jun?&f^eft;V_kDSJ*ZVf?zTL9tf%z9k-Ew)6mPrVV}^yKh|xT2P>U z$?iLttdx%3HwMl<9Axai!{IW)aShKAj}gzY`_6~+a)Y>#9lP&maQ-d;X|H1UU5XTq zMcnEfG&hWnlOuND>uB3-H2n`)-9d^cQDVjJ+kCz>m}rpfF4cD5+`mYZD+5x=rP}U$ zrmJO9IjNQ)ogJ#1zu0{*cM!=?;K>0J(P_JH2sX`dK9)nXnsijGj@`F5R<1Y;yFh+4 zp&(=Cec#4~#WZ{k_)Zduw)-9k#_Wue>%EKbzu@A65bL70`*z-EYe`<n`gA%(hy$Q^*eG7clNc@7* zcHb;Lyjph?ng>RwgVJ{2EhtqED)=6ZAh>iHxIu~C_iTSjRWWEP7@ZDE+kIE#9Y%iN zw>fafBob}+jUFta3s2-8Wl=BzzAv2OOPa_bs?u z>g@{1O_yrB?ZV3K|-M7OuS*!jfK;zhbIa_}L zy>Q|%c3&QUg62=d(9yb3S&SlL_nl5pV}W*Gl9Jt*kQG$n2!_DceQ78ZyKfZ!B)cyM zndbQ!KHrzdOuAtAt&V@v(%-J#cOtwj#}zgM?J;~J%?-GalG}YhgKDdzGj{nQc4R(#1;0v8_WhzKDbmTR|?#%75@{++1C1{Y6evsM``T7-QhC8ah3XE z4|~;naGo20WQ1aVNPPmf$#6YFF*>Ps!TF~EBvs4&vib$=p5Z3*#_szPEaZukE8@oP zOU+tk1IzDlzY#3x=|n8#9Y#^8YQPN~374<2`&Pu;o2m;~FT;80b?m-v@P@S-3pUB& z#_l^DmISo~&TAYLX!mVFeQ77y5yRcPs$=(UgU{NMtGWr%Z4z>oI(FYquf(|OeG2<0 zF2Q2=y&fj`O`!ZP7Q1hU7lNw;)p4=deJ5>~{?P>}-o;|~{VRp|9s@Md#bWo(_OIZN zfL6I!?7o?Q!7_n|4n)g}l5es5?v9a^X9mjY zVzK+?#AXpL)bc=8T`YFrPa?#3TcA!Z7Q63xd;yVt4+R?KVzK-FHCw*(`~lEX7mMBZ zI89r~?zvd;sSsgm{o}?7pL&mXhjUJoVt>BGGdY zO0N0N^JpxRar(MdhV;q$Ij9RZZiQTs@9-27Bso?XIXxO^hT-|!x zYt6wxs5XJ`APtW~I%TYBq1rvMtqmCG)Cus*CLBLaD-}7w(&0P-Pw~t@97#9_)<*q3 zS?R#CLsXQ6)N}mHgN5zYRP0XUl+}Ugo#Y|<2m6lNgw${v2SYh6d9eQK&g$4#681_c zH=D3^>2dtsRE3>b9-&+x1V3p))Ecq-eu1YBPU9W$rzRX-GGh1Lw@WmU|6$h;F1Lgw zQDXOf-UJ)oU)@Ws{#*(?9?Jekt&=Bq-(_CO<}~mHMx&D_cHa^Bo(0Fc z8GLtuMj{lu@7JLc*g1&qCKvjvhpD19C3z{HV-AB$=UOL^t$7nv9G)9F>H^@Uj7BGq zH51hv$0eLb;2i@r5+MsGskf?%a0o=xlMDUTQ`DbWcjKs6LHU_c`&I4?)#ARi)E~i5 zk;b%CWA{x}N1EMT@D~9ZiBRmm59>)_>0fxPg1FqkSm>{QUv+FDZLcPjjg8u`a_6ec zHKkW}2OnTGew904?Z)~Wx8dpFO9C_!q1b&pX7Os_R}dXaF7#I~R)2PvU~fQq(> zcdgpnPBQF!iLFn#+zeaMTxaW4=qw4RAb5oUjYP=84QkqEDUTKqB_tR6t2e23IOKtI zJr2qlMy-=4cHdlh2I4!_YVgmEMwg!0eNW;I0oEJ>Kb=G)cHjN!gfn|7w{Xe+e^6(e#QE6(+J+vxB^^K4xXO7*sbfkXdRWaZLjfQdMMp;h25A?T-#qQf^jbuBeWm{=+ zakh=!H(OUpUtyrK4%QENj@>s!xUv?~xY!iDwWBe1-v>Y18utYnoCKd%K5R&$nZB9@ zG@r1(J&WD9WxOPR6VR6~7Q64n&#^d1^Sq-#Ckg9$p1kk7zm3$x9iXQU4z&A@S|?eI z#0zveaOsNYhg7yRIdPSNOoUtPH_T~&TP`JXJQmLH z6Ee4SJ%xAdzIe*96us8>d4R~+ee>1={{igy>-ZgY_$2O*zk&T1z_~d~Ok(%#OPi`A zJ;*;UzvOUt(;tI=s!Cu1SCxX`Z6l&a?;p}XsyIF)pxQwY8z3@v-^DAWMn-|pB@GYS zT-t2+<;Mia?%NZe4dPOy-n=up+Sq;nv!qj=hUk8v@U>y5@Eq79DG9c1D=RL)lo&6@ z?t8qMq@*;I^^MxK`}(CjrDx{}X;U#!4ot2#cHgu2QCw3XSVkgl2OKv)ujwZyvHPAa zgv#6k)xP9PWA{x5%bPj}!C!%**M^zZlXWDj-G@m?7F>R@8@aLj?yQ2?i$hh*C^_p% z)A^?7k3{6CJyboDD~;W^%m_q027+luL~$CsZ}S7l$8xaG45wZmX!rfT8bseiaLkAT z?7kIn%r-x#{sI24(QuOWy+-W5OX|X!P7k!HaY9dCT)HS&NIgK0|Bl`FKYaL9RfMX# zqcnEks%KG3t>GL`h#PityKjq9V$K=^(L_gR?7lU7NVEJ1XtRTPWlD^u_pV{>wUMWX zb7wmU(Pbkv>-T|n-}?W``@T=0RCol{$qTUi-otYQn@=-==T4##yYG>55>93Cx=A!* z_dQxf9t69B_ct19&VhE{uhNR$cN#>CjgSjI!0tP^p*%Z&3DMV%(Aa$=_saXeCxLD_ zSdViwsF?G8TQ!n?`5dBfpHm9l-l>5ZyYCLXIL`x5ZitE*A&-ZS-FJO$(bNTR8=%oG z#@Kx?ZI;1fG*r4Oxn1ddmDqhh50*RKLWn*w!5v4#H1GR%#Wpdv#qI<@U^Kt6M(nvG&&ry`_67FQwndeZKcAcTZ0Zq?7sW1NP6;tmn01jPkNpscHfgL#qQex zyqTjhcHf;7(ZcE8-V>-FVVz^K`~ENrn>)$wI~8cQi^cAnABX9&-FF?(W`iBO@1{&R z!UeA9h`4u9E?6Ep9lP(WN49kbqUXtluHAPF4CK!8Zd7mvEb6Atf}b?w24gc+OwOA# zl$9wQGo(2SP#r3ioMUpU8j#e*71nMwoYS*wUey*ZF^;Ql3K|tq1K~W{ATCQCR$(;@ z&L0`X*@&mMt9dcC8SHDrY1vs&33UknIc-n`rA7NHscypgfk79L4U6r?F{RF9!KE{# zDi{xrX>f5S!a3lGgb~PJg(cW4$xW#saA}gn!GlPG%0W^wWgXA^(_gY07!X< z`bXr$n-DQg3Lz|xs2Ma}U!%)FcHo$ff9=AZf!h0UXvR1?7?QgTwPHHG_qNc5Aj@1z zM$eco^!_f#u@z*ep($ws7t>?Xd33U4aJ@=|i72QDHR_&XWz&9f46XwGhs04dQ&X{uB8KWnNNk2is>j^-4jd z)Jgp37lR(GqK?46%Bp*C{@0)kIEz=3SwV&1h@Z5$IPucDyEeA0*h&+cD60|mkwU;_ zjD+LlJ`!8w1!h{@M;ZgSBS{Nt-C9C@B(~;T(K6ch2OgP3LVYB*&R-3&q(l+T2VO-I zDoFo6!n(S(Yf6H?h32TyQEYyFDYpIqq>9743C#nebNf7wpr^f*lUSIs|gU!CNYMgI(KY` z--=7{zErlA0hdkzH#a?sQ0I>Ac>0Oxib7N6b-E4B5nfm8vShzCG+jw&YS4BRoo$Fh^PUV z)OGNaCiPa>`{Qz+!HYDt(x6Kn#9mq4E6F)7w@QR$5cw`mIZDs2dDR5C%ywL5h+tGe zEr;_4gY*!=sIdA5&W8=+e5A@pLj?0;>LS>0hSPW@sDyfg|EMTQM)*k{BG^|c6$R%k z1|3E=^u02!Z1Y2S=^4pZZvj^^5)PQhfw;;Sa6CPa1FeC(lB7C3glh?n194SuJd$x> zIPiod66)V^HHHqtIph@4Qs9jwq0-_|{Q7s?+k<-H=y=k756v;7<3ixh8&@lSzXWv) z_(gyuX@88XQy$+%q&igTQezPSmw)Q%UKv;KKO``y0HQ1lT-lN6du3eH#~~6xE08#c z`bR|FDXw|bKP?^6C}?KBM#mi?u1nr>n3$qU)oN%yb#%HT#C6^H1Ga4u-4AlerPLAP zV)~SYS&lMu9psjw+!5k>FYOER9IoMLqq=yx0hKoQ%DDa)mLcpM-~|ITR_3_L@XTSC zcZlf-4d9ZxDSpx%ACG%we9oRW7DF?jBW#?@9f6!Np&bgzDDs^P6=I%TT7^q#MjyeI~7Zo0k2CUp*|8{uX0_lj%W|?agtC$`u7pmHTdU{BMXc)cy3>cZ_+hbf_e+Miji&YBrb};InQ?I(x^u^OX@f219DGTT8V>bO zDRu7nn3q3UTGt+$p0Cr#w`#z-!$cN}7dh@;SgPQjzYzEnlJtWIoxlhh9J<%qidtjIH^4t6kxu>9&aQR3P&lrhW|d7q%DEwQ=_AxL`V1H?u|#) z#mWilQSFE35b3C_utyq=yL;1V*vQTFI>;?U`Kh*hn^h4wPl=vFEqp>f6E0oO+`t2W ztPK4VhgjX;Nr6`)`6;;s)Rh8!h@@i*7#Ug861cOGBw+NjBFLoIz4L&NWqLXk_&p<` zC`HnxdK(PD^u)dxc(sw}P_E!}+ugg(_#LxI%K0wf{f@+nU>ef~-?3wQ3FLQ&hCjw8 zMl0eR1rU4sM=6|Fz(MGFy67Sbd;yv;@}ANu$O@9rp;Gp(-oxo8y%x2`PD&gdrm6zh zawJy7Pq~rH-v7Y|L1GNeT=F{%7o4;K zj-5w>gttSn?!w)C1@K0aoQDUUKpqJaYNf&nF)aBW_*fDNb<2c0?~TW{5Q^v)@FS8? z3F;EyZkbT`G>-jZNmy3QdU3fD|AcdR^}a#VU~yRpYZ$S<4YQ>FkvS4&d*C=Dd6pl= zr=x7}0>^f9D5HR98VQ9Wt&D?excI5)RztJZ=qM=B(MXWc_~PR)By`PJLZQXW3{g~ z3Zet#aGePKSdqaKOTbe->{_Y#9ibP5=m&`Y-{Hw6gcqc!e4}%Kjey?j@DI5Lvujau zr62exg@00$xAxH=LU5nrXl!`<+5h0d^AS15xQ?Dvi2EoV=rNfbDWY)tUw9P4(a{Cf zK>8wkzM16>+X^{81~=6Nio^;j(iL~bUS)8f2o5Dp&%A0U0@;fzjKtW}O0EUe3AkK# zTy=S9R9M}G^NRq)b{O$mLq+7Yt&F%hK$$RcsP$AnIF~f&4L8CDss@}J8FVBM(!#@B z&&J&wc&)SezlsCy7bppBg{SwP?bKK}Pj`@R11S%#1nMx24)t9QwA#T|#BjWv(z9c$ z)v`*w3uHgh%N*+|DzDDBreg03%1m7Xx$e?#!%%`VK_)<5GtFhD=Ii2oKhFYPnsVN-~q7bditC4J4Ss6htAItpc>hkqIt{}j|aw_uQmjApQ26D1uwDblYRsFI5`2WOH1@xvF)2ev@`Lc2YsAN&{C5 zl+=3o4dOeds7zEVur3bQl^Vgtf1)Xd3d*J$20WT1k16g917f>bJx|WdC_7m`09oo% zG9C0hm2#i>{R-q8LnAIxQJ&5{PUuOH^Db>fWqZbpVT$8@2=dg>480Q(^4X%5CEirI z@FD{)ovMh6RQBhx;6(@aTNtFIODj-aoG*!06sGk-n!5B1)y;+L*y_PF0VL6-MX0VW zX1XkN637gf=BK*5RH7LSYgAUNKsLDaYpTo3MX|S%Tk1ZLA6?4je5D?yh+I|IK<*Hw zI@aA?7xvXjUrKFyb7SboWsQn^Dhu>9EnCC2N5rDkTfI_x$RXo0zxa~?T7fg2F2nHrQmwK z;pq$zhbxT4)_^qMU|pziBZS2h*8yb_QLm!^PDYtPqy{uWlkZi0F{T}wH`$7}Crb9) zDRbe0@vva_Dz)pPt@Yo*lP<4;SNlU*ro#t#jG*EB0ufHtbTyn(TWS5juuX8PYX1#r zAw8U^@Z6L#{$OLTy0Mv1-uQo-K#DR_@DmkW5bmkd5;!?g^KcbR+1F`mG`_6xgX6JhqhA&R~>V64dzLaPMKHt7^wiWC< zgsEzXFCQ!rp}yltZhD3%}$B#Ae1k&BR zM)!sI#6JG7(jqUqOeZTwZ_mSQR+V?0!xPbj!zsu7V~MJ6dSqC&Pp-0Ns0!HD)VsmM z%2GEvUX&)q=gsTEQ%qSJBO`-5@-MaG$l$*CyVCBdIG$QnNLPT`VH6cew4 zL*Kz1RHXHG;dORjm1AhbzKGKbMf&$8D$=D{ak{5(|5sF`?Z3u4ukTmfSi^j)(SpN$ z>#)}$!k18;inI=DJ(X{LW<=}z9rw5>U#hRsQ>@CDk-*D^Z0p?{--4-~>N_MPWCXq^ zq7KoY_-;5FusTes4-O@f+O3)cbi);97e*P8Ob@#et;pZroon$1I~>&r{EQ`C2y|8i z?IKqDx8Z^OFT|)8fvj|B_&;#6rmCMQwgb&)%e`!e!%^G)DexVXSd}^(+-IsA*yrO_ z>pZGG9DSt^Qt73Hfkye}V9fUT=Ap^izJYk6^ZJ@%Q98)?bx$u!??p$*eGPGBMX+xT zk`v;4Q6IAd-_n%W5A3U05c%;XW}(tM)W?g`yVIT;eRv~ z1AG;*i6X7cwF>(3r@%+AeJzXPqaMCJ4Q#83uY8EI ziu!i9MbGyY&+4^``#f>jNa^$R!rk6C5!1xCe6y!u^S>|c7982``|}QN_`XF8@huEr zUOYUP^KI;mU3S#I2U%4g41|YLHnqB{=NqC)l+}M4e%Up`-WnX-Rp~NgXd%4N}Q^g!j~G8FQ4xOJO^7T zLU3dC+RfE}6hdmqE4fE}7OYQM$58M%av#`XK(wCUZLVG+PO1-%Nz6urPYjK*|V^y@l zG`@-0@tW3G6h)NI7rzoO`&ub1PFEk*vkeyZ^#~$p6>w`Bs{*;XxX-}!9FD3 zXVsv*6+kyk;ai7&I6mJ*JWmAs9^(!b;)^?n7wLTe+`%YgrI?6e(rb@a-&3d`&%!ol z-w-U4DqqJS%I!h4WZO3fW$5)yE`?i(?*z;ODSR!*;`k5WPQ05N>^tMd2;&=rQV8|k zJ3+bKJ(O~L7UNiiZ+ZycTlHl^yH^6^6{p zEc_M|SH90yCz74XDD+%=(XvA_W9i_M4yZMI@yHo6VIAy-Hm(53lIQqVG>0}j30d|S zqcM~9M5y6d1K<1rCAYjM76q8>C!$kb7_G)$u_`C*qLiN-L})e@?u~`VP-@fm8ubXy z|KbX>wi(w=Dx?^0oVeIEyckMOJZx6E;9S(8)-L)?Re^IogQ!D_ug_IGIL8`9cQ!#^ zs6lWZV-U|8b>gGNL5ZwdC*G{zo&RY#qG}Y6-cB>!YeB7XCc@5gDuEF_^K{Oi_ zU;ET^IQxn_S=ROuE~EV_1DxM5NH3T&`d*cQb9IBpy^G?dxtfIfgK7rW)$laq1Ni~f zA8efA)8RFItn2@vngh1N@Mc(=^XEURFTlPv{Lm|tp+o8@oX;6_)Q9e)OX#q=1?NWw z=>=QP&=F;${inpGYo2#JXkSNFHaO=uNSle+*H5Y(oNF31oh?X=epW5u+{vIG=}agf#gO01IaGq~ao}31qP^;klnL&Dun&UdDzJv2&gV@}n6Msrwg!69(@%pPq zr_~cUtCCKZ*^Z;p85ITREC%tyu1057Avl*YNN-2uWSmpA;oQt1ZGC5SUUh|Ye}hhD z39QcxY8==c!87)BMLmM^ zOM}?3uhCVN@-5qn#-*D=VY2yabWP=l^IHa8t!mJ9RTIvQ4Vqiapc|?aoO>9wu%1D` zs^M^+U=Z)<(sA8X^WnVQAU0rY^qcw&&fgfcw2=w$cXb%fXAJV|leg4waDHOYF`WJ5 z->3diDR2Xd!lmmAhrte4@u#_7lJ zs&~Pr8_ol@AHS!TfPHFs{izs9{P=yf6YPlLzE;SUAAg`Of!#5@5saAr{Goad7GB!P z^&5CK+n@iXvVavgoWrM5^%p%>)gWkPL>x&{(GwL1!3ZPbn39VAQPUt;Y(zP`1$Kmg z)dsL{3@=Q{^&2>!sl#9w4WBwZ(EoFF8|**B%O>&vLWPyVt_NJY5!6V+U#Ws%6%0=} ziR$L~%W+4CCAk4$Ya`g$1+7RkrBrvg4=`-I%REYrhx;tU_PNYfYB}6D81|FPyh`na z`vJqwyDUhlb8x?5*sm^2q10ozzcTE;%X~^jmPH}p(uMHMWx+}nf_oXmg6L}zI)5Qb z)q#6+!y;W4s#FZz6AjDkvM{B_z6ismt|1u7~C%!MlaEbzl=)V zfx9a2nn#mD&jR?S_5tvK&hN2=`NlopxDHrEbFg zSpd`1;vF=unL6 zD9}lR%jF*nTtTT{;dGyzX~M6cxyw&{&uiJ$)F)U4Ro;qtoW#Z4(x|Drx*Q>9hjRf3 z>1CW~+UaL^R!>{tB~TQSssY}}XmrBww#BnhAJwV4yaW~x-kUT!;T`uNUwu`?1z1`N zAc%=T(_K6(AAAo`voi=@1+>B7@;~Eo*&eLULxmq6Z1CRy|A0gqN8xRY{uW(9haunxQ*mJsdtRHi?b-aAtf zsJe^k!!Y(l)$9xT>P&l}I0uJQd$OWmT}Q^Js5baQF(+U&_$;I0DS#HHxB=mG_4^2{ z%+a&lT8Op>3QKZ`ES#;*eJxo!4$*JPh4RKZtLLleKKT0Ly9o9blxeXp$vM=Wf`XNr zX7wVq|0WE!q%I6)?f;<;ze!y#It47g_A=#dCCTXw`JmT$A+xWjSEz^&BsnvoTx-5BpOIrRqivQo9ES3p74Owy`jL!5m<)%Zm0GueQ0xtM$SCABVEKI>Bn zsD_J&Uq#ZcsDUjdX&r#Nx|qIkWM5Z1^U61lMgWa9I8&cK!!7%!+6*%;r~E^pDIT^$%Aaqj@y?cyG=9NT}Wk1%0l-{*jSaWQ@0!oID1x1@1A1@csveCtnZ@n}&LtBAzkflJZqR8(h5L2z(d!tnVkj_X8bru@~8D1%P78Y0R7?O zC7ANqWjx)Qif_-`SPRA_`3_rxxXXL8!2>5PCs1A&R~!ml$@3R_Bjc(-wOssU0s^n< zXSfvWJ=@brC*BEk zz`^>KovBNoVV2#<z+S1mwJ`s~B_)ve1aK=)C+Ai4 zH-YlI_}jF|LtD?bpCyacf$F%pZyxyW;Hl)4Ul*Ww7hgMp^6TRHc%t|o12oaa8SqM= z9pf3*S?ca1pj9sJ7Xsh$o~`qwukHfc@8Sw`fO~j`JB{)(&6=Ta=Q3vek5&xCp1f#VsKe7F-WT09-oX7~5Fd&hEO63PH7od@Rd``kEo?R=IMdm8i45F^D6RwCrtT#NTuX?P?BpdO`zS=0Unit(qxN0T%LB4+^a(@? zxev&2VZ{2t)1``6?^wsDv73C7&OYh+e_&$)87UECyC}OnoM}@Iwf#)3`SWM)e!a{T>eG#_jY94XSX^c zZ(f%IubM=2pERNN;XGdb##vkNm?WB6T~Wjl_AN}ZM05TI!iloG<9);p zum!1)!9Pu+$&mI4^rQQA4{T1OPY-Kifq`x@)k6IfIm*6>3jrnWwsy8 zkg+kM5vIPl{PRBY5j5HC&#;E_N=v z?_`D3f03SH;Nz2M?$gX8uf4i8z9Ir^g<1-}Hi_mjwT%LH%gs1{y&KAB5BQNJn#oko zMeN^dTGo7+0n|p& zHb5O+oQ~pdZik~44J14SXrznFQrxZV^4MRrzYFjJpd~I2qqy7JRXby|cs%e|K;O8y z?{LK3!9KGHyEUS*3+xoo1s8kvp=3MRVoj_bt0;hTakFVFy+> zXubnKoJ2D(0r^^H=g*GxkmgtL`$;tW?m@HMz8xhik-;r6|HCD99=Qg!w!+Sg$r-x99S#+`QPQh8y%7DTOHC)`m3Y20haqO|#=dWjH?PcD@BOW~Ds`+yyU z4VkQ73gs97Q~frn58L@x!Nf5G{qiuB7n7^4=!j=%dq3IhA6gcDxk){S$crJ>ZNn0O zn{E&uw>O`|v2LG0m=&VJuM_$x#M5>Pe2Rg-Z=q^I)ao@t{#>Gc!Or#qqMi`+BawcN z7@h@Xc+C!pl2yd1K(n1Ntnz~h|7K^LjSjU6&Kq2xLH{B4JN5_X#piyY^Nvr>ivHov z5YaO}M(sbeYabHzUr_om!$^{Qy{n=82Srd}kL~Tl5p5Qz-XNt;@KLNc*-z~TXu5h=g`^Oo}qD|py50nQ;O#?D; z2IMA>_r(QyV804<+rfH4q5QP(5JW!jwU)SJSXlmy#HCw<--kN;_JF9Mx7|glg!~Y_ zMM6$F39aZ1cnQHS>@E6(Jis>uZ(}qWF!ox}YiB}J)H^JVXlT84tkH0Uf8?Q*@1p0g z65jg%NQ56kwAlzLFx{&8rH<&Pv^Y@4yBIBi8{=0EZA>Zz@QX=Syncra0f9d4V%7R_pyStL5 zEvK#F=N-qN6+JO0g01Ck0~LSFaWK%kE{?>?zg@>0gDEUQ1-8RcBg1yFu$)b96L?RUH-f5PxJ6n*(?@b8mo==-d8XYaZbmPMY_FW`R!YRX4d zM_k>!Kiov;c?st2Anm{^Kjuq#kM-6Z39r#`&TdfjY|2l(_qRPV_>~2!Oqjb}`8RI> zCwR*YfY0V|?&u&M{H#p$O$xh@xAhWPG#Uav($QGaX=u$L(YtA})X@TJjah=|Uy&{6Iwwj(&)iV~_Mc zM~~*D)d6bc;-y)DM|lt9!~(|gK)qeuoMvRBy}R#-?}`=S{@SgYI@`9-bgK3RKJBOmPWAu?NIk!>Q0tK(Pi#pTny;_9Snu zw36>pK;vB;L2D$Fy`}I{4F|py=o1&KH!$W;@oqURN!tmu*Tr4w{e!9A(2WxKMWAag z4#q1*_B8K--qMht0a=|*zH^)fp6*@0OahMv%I@NSW&zLeZY?gp%K}w4I8(1g^s$-V zZDE321HEH#^!wf5dzSa&GfCQDpm$xIE(RH!?VVI#;+_w**u`Jt;lh63`$rim^DlwE zc5x-##qBxX#aPtmQacHB-o<(GYLq?Ko7*XtzkvR6@tx5~+B|PL4880-stXoIs(PG_>0bn`%~}VX{16&0=?(r+(@Op(fc8m zBiZ*7pcO7IPy=|A_iKzmjK2ZeV{oS4T`;bF;e9tjI?)B7n+^^?UV!G9T|Pzfw|iey zm)yMs55Wp3XI@Wn#;R)TAlmI6WXY}G6RG1X2w?>h^9-10FTCF;%l%+9h9lmUxVO;8 zq2|zZG&+7aD$731YVDuA5g3E$HLAhDV~vDgUTVg>s84uj80V5`_jubZ4F*Nky6the zPf*_0-PJbyHBk+V9e{pME(z)&yYxwfJZFpIoLVbrF{X<+%aoERXPMHUNzO8*f~2!d zIU`ZQp-`kIx1f=`DAvA3$@lOOm^24oMkESf2PcfT1QVhaULJggH)kW|w=k@IQNg}% ziFW7T+4zm(zoUZb@5ta+(Bp4B+eXT7IBVuJUBiDr;lDrRzyIUE*JEufGPvw_^h@hp zQNaoLJ1Y2N{#}QCI8p2#8BBji1`oosZe;Lq{vD0qDE>PtnEs9oo{!k0g7ajfH0a+= z9Kv{}3s_GfLV}_g*}^M+Luyr?fODF?Qk@&0%r)WX8LA;7-i5crgEC4ds6ppew#hM^#4R`)^z0 zF>ictHC~Ra#1G|aRIk`RR#0VXjlpVUY#op)KMuz3A{ENVTUJxo5%6EQ!XBT(Ly>8_ z<~&Ugf(*vR+?=PG5iV~!uDWM9=V_LNbBzEb@7KwBn$5vF8vYEiTA}Tb{-92(51fZN zNbkgrpdD*LT?SQ@ZC~#Le?SuJG(7Ta`9blIuqd7a|6lL;4d-C3)XR{u|LZ(W%C|XB zlk)%i^E5M4?~wB}CtydF%G@1&16SC)s1|%9Cj?oT=P3@C`i^Tjzy8L%xu^zoIb{q@ zi}kZ*ov|iGQFn#7J9(hmm0&h_hQeiz3C7gQYtGYL0o7VZY0lH!4wrq7tJDvtaIZQE z=Nkb?*H3!phtwmmmxl9~R5d!OQYOG4iHoz$+v22ZJz@QR11E0H9$mmh&{x-JJV-d_X)YctsqO@n==kJrs{5)I)>Rp>KFGPB4AIi$LVtCA^(h{B zS-lm?Jw~n1@saa1)8pxgH5b5dCeiSzkBT*Q#gc}0!xHwbUIG=6V&87 zlE#YQwMj#DFLAM^hkA+Kv>aDw@V)^We_>Cx=!^)bK(s8m&|lq4z5lDMBX5IpuTksd z@hORY)M|7`j`||_Z$?9H!ir|iK(zpKIo7-aPnGDO1&NS_gH`M7ve`W!M3s^Y{nf)% zgIl6*1!Whb*2&{j5+|tgxuq6{gHJFTojle|RIAQQILp8{1!yEf7EV%;cvRqg9DwLj za-qL^imF&cg8dsxtFM!5zsjAV3Y@ld1BeFCMH;_m&y_nOO2)tf>s%C_p2LlJhk8^phKFJVZnOr*My&c|u~H z4bfsFsogMlZ~{64#kiP0!XEUqx{lQY z#v_3yJ2?C%YS41d(=2lvGk(m~)yLp#9E~|o^EYfoWBeV^4@vN8RizvTJMw)6=q6!( zdzSMwufQD3$$tst9cZwer}IxJnO}^L6}=O2CqdDh*aYfOET-nB+XoPH#Zj z8LGa?l@i@kHRuOSm?uCm--!5eN>A)Lq<>VY!w6|T1YZS+y5@XWd)VYh+2_y6!B5rliv zOqO&{gp!{6bxNr6wXKs&L8m*VC;K-}|A%saawn12d76Xqj+7b;6)kb- z*g5M-)A^?77o+Joji54~&$=o7oLUaNuF-Ik^}U9LzoHv0=I#`c$dRIZSwz%8%_T29(y|@8H9gL8> z2Q@Hrp5~EQ5e|ZAj1f{AMAOgnX;B$K7J;t|(C8Lp&eKdeP(u3|DqWQnQn#@DVWm;L>&e6>H=?&GO^qj#&)6g3;)3HhP&$gmJECFBPXv}$O}u za-QZ0>|5bY6c>Q5x>(NBtX>4?z~n71w8 z5t|(=LewC+&^=Fc|0G(FcUH{fAx%xaFesu;fBo;?;ae)4)jLHY+k_J&{vUI5BRSh^dGKfC-C8(0>2|=~8;+2x~QPlRO}%$5cBfE?p4ZLHYZfVQp4j#f*_w zipv4lBnbtti2u!+L#&J@ovxe+`f}L`_NPH1i-CF?|$* z8d44Wd0E^S!U?Yt>v*r=mEEx69_RDGOCkKk5nB=Y9wCx-lLx^yvji7a> zu&Jdg%DT=hkPjWITNNL*6gI11ZFt@U^reHXjPx8Iwxsa^?fEdk83$^=qgk=C-eY_r z7mfB0qNbK$d%B723mM!0@Ugertn$2&uLV7I4 zyoyVz14z6>C8aFsRsKB*U^MVlBhg){;Dgkmg!^B|rdxF#&f#3oQ`P<=$lst+O)ZNi(CVqU%LQ0w%Ucl5~7MAskF%N~<k2M1c`AeZ7NF~nX;fXz;{8$xs>*lC621MU+9M*%Uw!a$`VI!kCAw{gY0rC z?I=qelNnzYaeU(p5^^Ju7A~dDWQh}EjtT7r(%+@Dmn?DO2N;An%~L^UyOj2dB~D6F zN&Kz_+2m5%Dwa4o@>}uy1IQ7V(oV6&Dd#cU;gEj?`P0z%73~yDoV9b24%&kuEdrPB zmZgv!D|0gxq+-8Wh*0O(cXHemiohkczCYaHeLeJdBs)h1)8?qC;HD&@$v|XqL2NUM z3f>7bTBQ7bf1S4ejJ!dcfqvoN8~BalzoUZb@5tai&_@L~%SpcU?>N@nV)~5#t_xdW zWbj@7yAl8W;wHKD!&+Hn@GVZ-3j7@ve1U(-1s{UPZ%_p6$f|X&?3nH8tzr52k+@}D zY)j_pG3_EFC)yg8`m_x%A6Yc3?MuU|><9Y?nWX(-q_fg&&4HO@P;ug^Kla@$5nf9HZ1)L=f?pk z+~%2|Y*_Lljj3?y2;&i}*|3xy&IKGKlR3R%sT5`xG;*lwz;#H{n>@;fr3S$`>;(UB z@AwVpV6D`Rk&gds!xH7&Y*?cFzkb8g`!JC>8?C(StWW&;RxIA}U z!|5)pH}+8Cbvem~rDa$ep{Uc$!0WcS!b03&HhA*Gr3SfD;BKwFX2Vi*sMpfsCWjE9jt)E{gxtvo)*L`Hx-IPRR?b9NVt5>hNU%_hpMh%y$$Dv z=WJN|t08J|9N1)sn+;2Seek*z&TAbMxM8WsN%X#N!Hyd4R;aUK>8qWx?dLa$?vRkH z)Y-7qT?r1F1w@y|vSFzMS{}FXTtEd}EE|?S#>+yCYXH@Cv20jsH%o9=pzbb~4NF%S z;xU-I&sd;IE|v{THL+ii@p7QmE|v{TdGL`XuAkjN-@8~gEcqtL1n?K2UtKI4me!vW z-!Fjd*(TqzVd<+2lJYD-Z@5@CEX8Dyj$Z+&nu}$_(%j~fv35Y6T|DL>Z&>QJKms2I zG}^_oVQGIaSRAqCNi76g=3?2fbf`EIOB*E)H;4P}CAiM?yADF|NLXms*eGf}NxBgtzF-YGyM5wdWSx_w=Q zLm`@xTWCnxl#L7?hMtmq@`QxA@I|rF)h`K=31DkE-0_o+yj3Zppgh! zI7{UpCc+H!@zsA^ZeT3*SHG`b-jh!9Hk3__+OKlwsvMY5a7Ri2A80gwl{;TOIVEj) z2KdqdjYPO?n{uRpmM(tO*Yt`r|$#C!jOnh*;8MdOi z&eo}h_#zaCQwY3bfJP!@;Rf|3%rY!&2~m&aLVxup^$`})Sp6Q9GmTm&Pc|%-DkYyJ zSp)us(dg2X4NG75_Ub|ZF!-4y8riTkE}Nw__rYHUXe3dxVJS~%5oY`V&%e0b^6(e# zQSFyX%Bn%szzBJA=4@E%+gUWR;Dd~Yau~Q_sq+7$?Y!fwD89eHb7>byFh!b(Ql$6Z zd#~Zrd+#;ml7xhW(2EqQ0@9_4h=_uKh=9^mKomg{r6`EfEJ#rhp3gaRc6K+x*Z23& z^T&o|-k&`?Gdp``_ss0v5E0IWXqiW7CM^AQS4Ixs1>bFJ%!H-py99p;^o@gM!ctFr zErH*G?m1W{EcHe-lsnF6@K}-^8yDNkEfbb#DIUh9fvVX!Bs)DH+Y^>@&d0(6-Xu_c>y8QrRzs{d%{woPN1IX;jf|m*j(A++pRi_?yJ+2@yuTt zg2qO~;YFmameB?WvDY1nCVZPN?5&X+x5sSwrzWA#=j z_oY>v2}`HTNIN|X(eGa2Q*CGTeMz&p@lL8TFGsWln=2>g5Hn$EC00sfbrmRE8a2<_ zNuBR(zIC|KSv>&C*tBXhVQCKyjJ*uOY7%if;B)i)nyy%xuyj5JuSGkcI+RvvCM=!6 z;;QN#1b4imr`pWxTbPIj=0}h8fBM-2vMF+Y^>LAt0z~LDj%knh8tq%|Z2dM)F`n z+_2M5Si177EQK)XZsG%77JdrR1ta{A2}`uTCQmfF z52bIFojuQlr56jxT19!l3#Zb^grxzYVy6yx^Hds{uoTQE?>_y&gGNKm**jrrD^_Ub ziAJ*_T497-@tz4w8=sX|%bgJIwS{KFQbH%0Y4tVG6&q_m$D?<-Wx^80QMu0kg(!5j zT?^dasezdZOBpYTurNgBjF9~yuNjhIv~NgbxyhS@clBs=i!l?HI-L^b1gKmSmULew z6P8}YqX35>mqE1Nm@Cd*Eoyxc)a8ZOS6FHJ6I+x-NC{+9G!g==pBRY2}@frpnC|Z=ZH8xDBrN`IqeBc zq3zOJw;=jAtArjd%K+p5r3r93*sK*%0LK1TNSE{`q)X+0 zdPuhf^~CZGY7eT~)i~J(I$``HDuRS`cOvBrJ2fO3=s!Zb`9=ca)IURflMa~SnAzfc zgp?fX#JF=+o)Xe63{^>6X+pX+kDVuJ~rGG-h_0&0{g+kEjy%3OHZtlzT2JNM&D-AQ(2Tb*^6% z(p`s9BUK5kuHoG9?2zuQ9_SZ4fOWIE3F%J8(xECE$>VI~4e2&Mic`-6TVpui#@gM| zk85NIS1IkJSJ?y6eiHH}wL`j#FnyGp@V7u094sN-d*`Hu-v|2F!4lHFg;)X~onr&O zgvBPtC8S$pzr_A30o8D@gmf!p6yxoIx;j`wx_^zAqk}*R4wjJaI~WD#>$3o8se>h? zdw!ST?LfO6EFs;u@sz_yp8`7TUMu?q+9n!6dVP?+tPe6CI{A*oy}H>!tmz3pB$b8(m+jQ5a_Ox_bhAwYpFbp#m+p$niHnw%`Nl5q3ZS*;C&1wbsCSy@+ zI8Zl4UEPQ&7*y&5;GY{ix@K52RQW5iO&NgtHGUf@HGMrTh#y3rUvV$Edmg&vJ$PeQuwu|gLM--761 zTA^E=pjuRr?0pC2RioC~<3Qb1wFnQ=Z1FL8<~Q91mZ;w}h3TYY~TR?k!m7D!gB+yGXBzd;)E@nVOs!d!Kxk~ETo;9q() zZs98`I2q$i)S9kC^dzm&t)8!HV(gRExwc>+3Y$K)>*6j{1%0Ba3EsqLTo-q-sxVE? z+8aFDqmdIzNH<*@DaTBRR;3lX)yvgq|A=}Qlph*BtlN+CeQMK}-sv(f16Nk}(a zRw=?0@Mqq#i%A+ep@ej^jhAv1g{W3qpK6OVZ`xv#(o`iJk;KiAHszmUq zMx(PQA>C!CMY9Tgb1IF5bVsz8j^ShQuRI#bl!SEie5R*ls2dPH{7>OQHRC-w>$6+2 z^cgmN?e(ip1NyY|kgA#k%h%IWR8{b%Mnfg^hIFT3B0CHFKs4MVG$GyMedHU|so=A0 zjS1<#(m`Im)&sriUh$`I9Niuaq9)Ew{dG>(}jHv zH<}6Q7TTz+ZREuYftRo~CZt>cIC^Bl4S|}c!e`W~+sdLRebo_u63`3>OGvliHu<%WwLqH)>*qWP>5jT5)q4Qwa~pd@y2*z{a|Qe_kH#&$tioTH zx(MBd7ZYr{E`}$eE=)*w);;{@1${V!kS^D2bqMR)ViVHsRRksOfaC#$oQ_jJBsam* zgc*KOJ->h`5rU~6kqPPkjxUMSYhW9m#&4?a_BoaqWw zf2CELZ%|JihA8tpnDv59=b0M4+tLFSixnMIX$Y!$L?)#BSp&Jv+JX-v4LfZPs&HtO zYrqca{&YyHd;*m7(yC2J_opUuQ*MUn6R+^8wln&A%}cLa{`Zjo@gIknknZ-2lJ6|r zao1yWE0ZNdxXSP@rv78o`J{HQU#eaC zEa?M#~gAh0Dv?1NqNfN1Q4^dZJXhOOb3X3}m0!_B@Q$o7)%ZYFWMB9zd8MNO!<}dH1Od-q>iU znWPHo=9G|bFNj7NAzvX+NOu^z7`hT_21Ijhp$X}}R$uIF0@`I`?dLop-IR&qPfkH} z$q4!Opay0_x`pw8$2aib5T)N~7nAZ}zCrDjTO3GU@KPR)ezY(l-2wPn2)5P^DpyFC zT8MmK`kt@vC<(I;hbZ2d+v#ZD_YK1DFmRZ49{6&j`HVFZ(tQ_moLRF2e816XI}*}u zi02#Dd<*`Q(P%po((RR7G>^bDA+qVXd@HwvbW6uzumniu!=J*o#)NcpMWok#dmW%g zgmsA}q??5KwH(sz3Dn=g64I@)SjIk*fhHSlhjasYw_AeLw}?1BDBrN`k?fFe`@25t z07R$K3Z0N{xnDS>OI*s_kMoX=B-qSIT^bxxj?g$8_K=~z||k^splBYet`1t_!?Iu_B? z==!ZO7|3RaKr_mi8#5ehtVcH*jff&0r)Gla{EoScuTY|!j4p3!@`g?H`$g#9O{ke> z%`qfSRizF9A2DV_`*cKMTPDoFq&?KCx&U&;p+l%vquzO50&8+s+#HeG?FLk@hLq&frjGk6vDtVL@5-^g8$ z>bEV+H^yf8aEI25j2=O?>5mx@ZAI_nYnpu!?ycw|o2YuSze$#hen|USsIf(lRv*B^ z0kU!esg_O+s#8e0WT)!OLD{vk456dq)bC&qZLV8@J~T;X-HWat8ygHcO;-8a$LL9! zM_AScI(KQ{YN;ec@Jt^)@09&TRsgs=Nv_}kvC^kJn$E&?pNiid1Dt3}tZdCTp`439 zqe$jlq%I>uWzy{-TR+54qn93t#_6{L?KYSzHI$p>nl~`Tk>5^E0be2spPoMF)6H?Q z>eIi!6}>rgdz|Jj1QyQVI!$PguTYG)O7@dH<^nF5O7afAdy3w6yPo_OQw`vHB%xDD zdw=(IExC=lAhDN2xnb_ygO>M$`{`>6QXg{3y!~B!sRKxwx zvh&w}A2D6^kn~UZZ;?l&r~Pn0?T7huLm%#c6Hmus@^>B6l1yu}{s#Z8jYXxx{l9a1 zIsRJ`E)A;=b9zh6Mi2LoN=JWny4H}}3->35(%(iA^p{e?Wd97)&UipWx59sq<8PS% zfS>+0XZ_#UM^}ZF{A*vmWbyALYu-UP5C(tVM-@oF{fG_|U22%WET=c)zn%E+H+$%GzkNWI{)YQ0CCpEseuVq! zgBV!A-*8Te?2nF!*8jz6T7K;sW?j4A46_cQ&inr`%z6SgexU4lN3RGYdxIhRb*W z^@T0#Yxu_446{Cul*)E$NC8Zd|BqqTss(&}?OH+Hjt*GknAzg%hm>Sv#$1)B471LG zYN4$(!>sF&^0u9-FQ^_X{aAg3m%g+z%$ggl znBk`IW|*}aSVIpt!>rVlRTr@SHuns(=D=9gMpTeW0-kP5xPHwr>v62&qE>)yGMsZ~ z53@F$h*NwB_OZ>)Fl)YkxL3YG@{cz14ztev7^d%oW%}4IJ+*mVvG$iU3Ha)iQdK^P z3X_m8sXfg4>kPqlfEqbihFMRvmbbc|K>Zyo!>rZY$kE9_lN~I>tjDlI2%mce(CZGC zVb+;lWw3HD&_M^wFzZi`1%C&0$-y$rdgUbyzS8yi8|aCHWtg?*JS-|iIM*kb4v0<4 zEyJw4hhk+x!c~B3Iar2SbDfcLcLeJ0U>RnO2+Bt$u|VS-EW@nLvHS*?dlArU4whlo zrSD3$ya%+$!7|KRrLrvb`xVf)4whlo$`7zq1`V_R0d(KNGR&GC13_G{utRtV!luh@ z53}xm4^5#2lFJcdCt(k>j_EA9ZVuGdK9XCLG^t0J$&sO%+KW&W7cU6WjI=_xx`ir^ zd6}$U3*}ozt;0Jq%=+ag;z$pJpGu{XVb;nhYHPS`^(**aq@mo)xn!92FFY3i40o$S z5eUtNjSKJAbW~xLeA-Sq@Oq>%cHF|ws&u%ejdg`+sK=OFh%aX_7R5Q64AIiG7TxL| z>gOwx$L&xaNo&@v?yY8?5!)A`yl!mk+LK|{pVlay(R4@9|6$Xm)*2pV8=}72Eu}63 zUY<0j)beq~Q1u6Dm&?%tyqiZOnPOwZR53iGvTzJUGt&y)>fx%%hn7~q4&_#(*4dL` z*7j}EYt0exFO7!Ujb$(OOF#F=XT1*ok4GaXlwsBm`9&Cc6!Sl^Ib~&`Tb-a5wU$%Y zgR-Sj>+H!eYc9LM1Hhw=MrV&T(^S^)r1oZlFY{>Rge;t{D!ne*dl#akX@zd}O!Ym+ zX1LUspuAz!u8TWI&Bd>?aI;T;41<8!+|6EwS=)BQ7$V&oMZv3jG;%@~zM?8tlx81* zXkc2QTRmUR|6I(bK>4y!yDsiRl{+@QKJ_~Aw~fYiaTlv%ze^F0f`8-D$O&bbb=4NR zeSU{1175_Ova-;vUaqFTDC!rWEN0ZMi~EKu*j(xGwHyHTaNZZynWSVjVr|sV;-xG#Z^f8D=flNP4pj z7$ObB=2VK6TZUOL*A`7N@M<27WJ-ovAAKz+YztA}{}dinSMo_$GY+C@M(7!4eX$@G zF{9kC2H$2hR6_4C>%ryHUmt_$v`1)$Srdy$2<9gEpSH#fvral9Z>(9-D8sRFE#L>2 zvtwn+<0>bkz*t>c0W1`66Z#48lxEkN5-;WMgkZDr9jwfYR`6k**x%P?y$O!VgL{|fY*gJqc2 zIwVW|`r$CLVUxnkFzb3WV9tIKpz=0$kDgvsU+$6?(gM7jN8=V=R&VAO;TVWgjF5+R z%rNVFb+GIO6$fEBKJ!`#H`!t{%(@^P&(9ws`8XldDe0$w`^%XhM&qgFG6Xk0A~Vc7 zF$-cL>I7bWusKGA-&DB}pjG+7DtkD$dpVPQIa9wSveN>pZfTWfn6*_TP8SWq1S8^M zR{dZvU(RH14AEi;)_6o_m^E7qsl+|tCrLvO=3LQwxRR~e!>l*!$xV3;%KK^6W|(yt zCjE1Dhn>W??$}&rc@Tx#kS?>fozb@g3jpyU4IuCQABUJ>)@!s9INi~sp`2#abn(;V zJDYFF70J$OD7U3mn_<>T_;x@Yg5Vs9xE*kI`F%}StPHbW=!=uzhU#%zr5R>Dj-NDA zkzZic2b;^>Q*Gw;<&A{R`jB?|54jm;U5)!p4Tox?QF75!=d+-%^b2SJuR^skt|xdtf1@hmp-Q%uW|(#IB@}A`l3ypp4Lj{H z>us!1%%RS`5FNCIW|;L5*6ZPh_8ri58$V^3wHpQ>ScqS|wsK+9C;X3L)-f43U9sGbXD-R{WQn^(iYGQm2Ol8&P{M8k}bESh1~v$~DZYV-oV^%=uB$ zkDrFd zdl=|*2g@+)r=cGU_8Q^Nf8^J(FJ`cb(s{u|CIVSf6g1rc++MMsdU3HQ@CKVkegoFPUd5Ka&G-@;#H zpTq2PIpudutqk)|!!isohPWtBg1_OMf)U#~wEt>dN~gaV$wf+-KMs?#QHY+jPk+NX zCCon(gG)FTGgDv_f5SN?%s+4$?T^QrzOaeE;hYlY?}>*o9E;a>*u>v(P6_jOJVW~< z&r&-54d;|Ff9pH6KM?Dq!Y2NPb4p}9WL>p0S%B7MMGgwxjG5zOxmE1X_vI0%$ zKl$`faG)s-1;3=S&=~^F)hjsTVr*IIw3bc{s0~PY$4=G0L8C6}0FuvmkbXR)bI9@i z)Kv(6HzMD!WV$JxaHO)n!O3W&6S~6mf#~kbC0KEeXGc1Rst3}< z&`^5c42%i+-DmZtXj?CkQAEkSD`%noNEesmd(4DDrK#!AEU~S)b+iO_VC=V5(4mmM zZP0u`I%CfY-IW!l5}P%|-A<;y0{(#{lwDm}q3>LPB&p+Nguv>+%3WX!m(p!z8%f6R znk&W11zeCME-T|PSs*YWv^sv*kF3-HZk)FMB z@IwXVU+0uxKwQPSt@h%eBc21T#_?FiGVr@1$ED7L{cLmB2u$G5Oz+}t7S~HX2F`rm zt`RO#XpTKFaev4Txe@XM7a<8>;86MuE%0FYB%yUc8X2m6!`}_dis$G7($COP8vY3U zTXmN_-Hij8XlQO4I|=yIK>ORF*MQbIm{#2jq*LWFshMg)?E%{FU>Z9KWKijHiSciN zE;yLRP68QK_I-ly1O4k@8ovnm)gDYmW#i2aiR+5(rUqn~75h0*xn3_mggXx$j{jOdwP(JSS&Z0{(g`4GnYzva3o> zW%|lq@Pnk`E0dcBIs(tD3ayky_ptg7=#qnJpd;{t`VvOCb^HzV#KAO35y+>?AzZ>m z%=H8OA2v1~qF;9wA`%lQpq})_6d>}nHNjgN4aI1rG%PHr8kZNZJpiIu5^{-C3k#_y zp_n;J7Ux2=F0Dnk*~02_w3z)6$}iKJb*qc2*-ORtbtwPw+IAJIn7Y>b=S7b(NN2SlCN-#**P|Y#2mwMyOB7j|)Ro_AX-V74X-L zMpr3oMyaz~Me`o`CmxNQkcF}8*WX0=Jw(@xP@j+j&ViY#F5=;wDGUBAD{Zb4vSzL- zcuVZO1YXgjkrT3Tp*odKgsmXzY=o{VeNElkD%Cz3Jc%@}2EjG;x~kJs8qH#G`k@I& z>?4RiH9}XF?ofj+h_N5RZyAlNO5azvUlvV9JQ?M{mga<9rMuMy{8}8} zpk*McZiKEXJ*Mv9DS|cazX6;t6*bmAlhPt`h@%h z^|e|Hzsj!c5cn6Q;cKX0*eNO>_(6S$a5rmy0l#DH=$BCXrYUey)i{LNThw8O{0Og) zP1gdQ%N1-7TvqGwP{zVa5Y_bvbznB|vpU|uhwop&dJ}gV6@QQt_(gq-u0+LxP4#eH zdM&!H3J*fx{2BxsjEHkwJ$f&4d{aFPAh#cY9X4E7GXX4sMer!71tkxBNrXo6rd#daTi5^sfs0Imj&olT0&iX)A#1c~cP}&}- ztAlBzAn=b`f*-@=+6w|DIGCUCAF0Ei`Yd{@QVW2V5~j-2g9L$p)iY(pwQUFb(8f}b z=HbZSW7QfNU=wG+&)XU+H{&O&@dk_ck<~(+pR^Y17w} z-*X~-pCBB^_$8p?gmpm}NBY_Ub1oVHwYIV3q66wEkju9Z@g_Dg2z-RCv2ruc?Mnb= z6Vrg^+gMESY4Z5;{v%H$Z-Vb6jjJH6$?IDH4WH&D_}8|^%1whjffs$j((+h$3+Rr) z)oGpoKz`rkS8=iYKO+)^O}Bj~m>ekRONJ*^MZu~XUWINVm#C00J%*N4D+qcR5kJ7Q zh=&XUMSM5$yv4Ub97NMd$Yo)nc3U*=6e#BV5N~fRTn*6DSXyp!@ge+C|RhVz-E7BWipo1TW0oU*i#guctU@1UT9en#Ta9!V+wNm_5KyTZa z+l2&xSy<2a;XLUAjzaXk5poQh9i5I()7t)lhQ4=1bX;h!H;^fC+rC{#Ks|2*`ZM=HqhI5 zqlJV}CxOo~n%b-z7GDNL<2XOJ z!T+)~6tAQ{7NIW+421hBx)sKM!#O3gKOUD6274B*G2J6q80^Lk34^uAL*oCBFxaa& z;|gq9>9i&c_7+lh*{Rw~*kQ1vNdDe~bZg;mQH%Pin-JVLqRebs!eE)MBh-nFPv{AQ zB_MK0R#b7|vLtzi4wNw17cIp*H3eyHsD#0$|Ab@dIeH*S98oHdD`yf0YlmQ3=N&l5 zTxeF=R@^!r28$kyvyr{`p*iTWXNSQq#iiG#&H-QXn6e}cb{WAr_PURNGvQJ?xw1la z7|e%ka-m-YE>03Ew65|{cDfTPVahXGsSn&Ll@%QZ`x)y^vy}nB(OxSO2CHMiZB7At z#aLiRC}FT0aNuek(Ax&{6_qg9A1QL59RWU0623MP25WTNXJtpWFPdZdl3Nikp$$AG z3`W=H>0vPSz0dL$zlrOQE$c1Z-F6u4ou=ve)@TCIir^iBb{MP&Qu>)g>@ZjmDdX)_ zU8i;!Y%Y>ld61hQRBwZQl9q>1<1t~d(-8b*L}|ldcfkC3x8Z^~jm&+f6Dk)3^a7+s zo-kMiB-b{msyhtU8p&M@@`S;LAUVMxI?5Xcn+f)=;W=x7bJxUw=%VYKQtQw;)s=i( zeT;)ncn&mSFmhb#N3dHq_k_V3+()Pc*Gpx%4abK~7nVyTVX#(*@Wvo54V5sMZ-F%b{vbmQl`z<R<_j71<$}R&Y*_*JWL*+!6-+3NKcCbY7r>4wf)jF?)EnCQy9` zOBn1I47>5s-GKTySi)d;I?1^cfu<6s`$=C?I}BDkkC<2mzB!df!eH;>b%IyQ{}}uj zY52<6VX*9f;7d0OgIxx?=3ohf4Mhjbt;6~~os|)r94%q6@h{u{52(0}yhBsiRv3Rfj?_MqYb3L`fv%5~mgxQVIAqG42KyL-b}^i&9A(T`R2K-HaAOWY{4GHcQ+714@O;;R1(nCiF`ln=Pg$Vo;UMJ_k{85<0onLJ5Pdz^q{wHh`$L z5z?hMVX!uMIN=fv0*@gLT_nkwgu(7l!A(Tvm<7JvW5+G5uA=Z5&&GB@bjV}OEv%!m zMT*5AAo|5vbmhLjdW;o{*_iqh9UC^CGp&&@ScxKt*iz04ftMwXtEoyDY*-07S2OS~ z9*ty5!eDP>B!P{^K$L8R`h*e&D?LQ&{#Ed`Mx(1#!eE&&<&*7v0REXrBPWzFSnLwX z*-sGNHbQ+u34=YmUan!LJ9z%V<}RUx!P?i7=34^1hDReOlrY%5_atZSA?js>t}1;^ z^*SgGVl4P%(zqIggu!C)7|NGs1^8PYjk`+URMX)ES$G(tQ%2~j(j6+oHufv{Uq<7q z()ZP#s$wVfFMRrs&B>IzN_VT-Lq%8_qIyQ?s?uZXgu3UEFxX-H#jYDr9|ubq>>CVdbL}MpO>nS; z!9KXGEPAU_%YarBrphy6uma8GhTRSHiH)To5(Znl)2B^*5B{UAF=4P;!0bRC0%gP) zgzNI~l-z*w#m0(vd=b1jXiCuOV3w%bbPC<2vlhQQjA!Dnm-nVcIa*PdVV?Xu5V&h+5l169(J0Ny1=* zfJQi2!eHOw0hQauG@#iI=IB;kUzJ)?{0%@mZOrY$8wMML(QWoACn5UD2>&AtRu83T z^&==VJ+uqQuG56UDs>l8DF|F)FscVDw}iniVMh1VTPS^Fh+5i~Oc*TjMRAk^fTC?2 z@`O!D7_8_c2~EueUt~1TVkFbbEn%=NuZU(V_->=ob|eh8*C(1U!M`^eZAZdji)TwX z?JoF3TSH+mdWt~kivk1Teu{2kr4;-Pmy{B?PGSDac<%}4Ps+pm!{MUC{5A16!rDc` zh6o-+tc5SY`Y8Bl9@FozZudaCL1^KRkw_Sbe_vJpiR0lWup8#5FZ{#&w0usue=<@c zXcu4MV>euqscD7z*C1se?QX-4UXLq`C+CIx_Y$IehE})oBO!87D};zg7dW~H>t8-WYoQ%1PeI9}3#%?r_aaN}X<2riT2zffN{XGTTQavh z%}c0Pz}Bbb`T<0XN~;|Z>^CAEW#F@xRbL?aq6fJTEw6q9`^WGPDaYDsMU~|-ijIvl z9C8X%ZuRmPqboN;__!-dp-KT)O(mh_FGkm#(@UCG8{lpv>5T)#N(PLxjIK4Jjob}E z;PI&>^l&h`&XD35i9_zxtH3L4iN(L9JG#NW9!h6p2gs*HscQKgu9^(JhCzYRO*d}G z6dy8m8NzFhDGG&;ZrP-W&?g{SaPf3@`BLyt3Xg6*0n0J4fdas#jD%XW{z>7{QLkcQ zdzLf;ZsV2k&z6tw{AeDktv^r#Va_j|MCX@%eV&16FN)2~ur)eLgC?gN9{t!hX1juN zQ{Rc55NfPQ+-oO(Mv45h%V_`Dk2r%rkwx<1S4m@DqEP*bOnAIq@G7pV%0kI8#nmH7 zd{%lZ>wsm{L^-vjia<(UJ5^#-j7qCgNUr5UG69WwIn@fRv*DB_v06b5Msm=g*|=i` zRZ^3Yywo6i)Z{iR4VO*VQ*S`8+S9LvzaQ8R1KB z6~M+N59tjT&ws2?)^*L2BIl?MOK{B`>YpFnW&JA?Ezl<%pSUJnl7!$qpy zIFN}p<=$1_Q!%~2AAwIMNwN%hy;l-?aX-${cRZp5)VkG&z(-R_#?(bc^eg$Mr6m`E zucwmyNLKovTZ!Q!vf@jJ0WWO2y!!qQ#*VOJ23*FS$&y0AWxbNnT(85*!1I{Y#*(JM z?NUjypGIB=Z8<7dh5^T=l057V$>4We`?Qt0z^h0?cO*AV9dqL!D32L34u$(23oxno zp*do7SCQn_4eL`nz10P`h`IpHZKI>RM(c8p=rh)e8JX@EId4Y%ibgm#cO9@~)Qea~ zmJ3)6xSEleuVk#8BZiE$Vxl{Dl2Qhs>27qoI$1LMI@}nW8UsAVNE}n4pJ1v+OfXk9 zxp*s}*<^HVN=wF^-6t8}5B!CZxJ<3WOMXo326%fu^C0;SVbLZ^SH)zEq?>;Ey*apo`(rLGp?;E&`@$c4_+v)_!X@~Y5fsCj8IZWsc zkUt#y5hiKJOz5^*Xy%OgJzs2MId@f9p0sF#r5jukkn%Q_^5!DR)bJkWZeP0-Ejt{059@L zL{};^im~DK=Pli$-h$>`(s6&CXK4)HJlMcNJJCEioJLB-xA+tJU<960gD;)MmoyX6 zc|3azPb7E*pyXh2^#qa(ewbXoka|>3Evd32C7+!tj{uBHtFlP0>p>y34wM{PPPGB+ zW;i``2&$llAvw;VwphSjP;E60$@2~3-ktmGVBIQPutFa4rZxlbFcLP*eRi;EeZ()g z%Qz1F6-hQxVYtr@HeZDA(z!>v4szF~u0A{1;?^+fR6{f4vlnb^KqS;>2U{+|^hLH( z7Pzu4(S3HX)pc|?Ok0DrcPRDQ!Pdp9iTU9mF%G3ZI~X;zrS!@#gUoX%_1VETwc!!j z@*5y;JCyq3VBq>vIqwmWvo;MWOKp|@=sr8xcIz9WyA91>wodoi!FDl-sqr~NU^D`o zu0QUxgPm$@ln%K#NF|%P`s`rmA25!{7oZhzXRn0&>|ock4}2CiM->e`E|rA(>|nQ} zhm@8q1YVU&LVb3yd))!}Y=x}64}8!o$w_^7u*U(6|Fh&A@D;Bl^h{IKTF(vkt@#Kz zQ&#(OS7E|Fq#l<|q`1Ggm!-9jPMFkO9duy5t``1xFf zmeo*b5{>S01+T9EF??*!ef9!qUN^c_eRgnA#`#i{A3$@Mbky4AdQhJo9K61s)WHwH zw~WN;(zwqK4tX1c5nO}}A?d9!Y#vkS)`LUm&y`XZ1+Ho&jw$YtgTqfhC#Kp!)6M8~ zol>_R9PvvEhUw_y1%W3UiOUpq$ib28@r48HmP51A=(H)8jH-df^H}l`@JSB zIJywtdsz1~H1~{-+_v;#)Mp2S|GbOgCe)(JhF`rXh|P5^SxkR)pB;?tf=|v_Tm!-u zUa`|>2gi26s0yFFA2dTqr`;0u*};T({0;`+GZR6kJCyqDVB-5&HiGGDkPQx{K07$> zWlRoWx)0dqsap@O>Voey`Jz?@Zt9V^`t0DEMrbeGNP0svkaXO^=DCk<7jvLd zbFp@!>9eOJB_cK_z3VTa-6i-F`8?(mmW?VxZ}3C$fzY$GWBJDSFK0y+r;NRX{qnM3 z)R(2@DP={KRcCSN_t>(o+CUvJr&drmk@Cn+)$hn$Hq9%mkg)Vter$Y{!$SsASCWH` zR8!?3sA)v>xt7?ksahhrj|VwML{wXih9Jp^W+OXRU>z%At=un#W5!Es8 zE@>Q*nE#m@n;c8CKB7AH#fOblS*jdJ6^GKKkEqV~yJ1X;XcR~Xhraa;XxCvOLPvlE z9ZGXqqPk~5_shr50-5hn`W`H*$DH$O(ti9FeHr3tyI% zTCal8tX3%zeJK^y_ZVJ>c!o&22;9urgi=F~>c1F0Ahk7>AEcyBrHvOS$$%-JD=ldV z9FntcPhPd{qYlkFX^cPY;Y5IplZw$YCnTVw<|!jMfE*bx3DX971h{W*_OO zS-W*b5OR)6sFXwOoq^_($DS3+lBC;5ecIFm;B=90Q&uRAzelCypDtGN0GA*MwITP} zXcRkY%D74LEk^@r+C5Fj_U7EidIFsLVbF{tUFzJky@kEsmr^c-X5G_tG+`ua)zty= zEy`YKJ||u3{Ouv#y6sq3mCySVG`BtWtWcJ09P@?D_Rsh%-v6;VrYsI%Ms0q69_qai zP<6uIoNLFRg>Qa_sZ^>pL_O0Atx$^ZMs0g-HD1W*CXa(AiFEq*q{Wh=-syo(kLe8$#*b~xJ131kWpIYF5rE(#0sS$*{B_-QPZUm@>gd-&O3DN5ghye`65E^fc%|` z?!Fme>5m%1aogp@#$~m#(O_8A2MN1jwFFXY5aIfE#=>$HJBhn(f2)u6V{}_c`WhMC z+4`=rXB&t6qd_BL@h7rharW-?a@G_Ra-OA~|Lxs(;Ls1~3>nwDy!&TJ`OZ#tHCNla zUk7`VmWNb!d-rE@AP9nuO^19=+0n<>RK<~8$Ai+Gq_&EJpsNv4k7c|&6r9dh;RD1VdLWH&e2{=@H_oY}qjE@}xGRmRa zyRUs#N;Dm0jzhI~--iVy_}C2~TO6vr`v`Q0JOS_%kWU?|z5A?t@)_)9kZTUr-hDpC zvZ<}9Cm>mJNqKcU4b|TLw?dYd6aX%jN}|1cb#&W&RT}}fuqC#4FBpa4G=v6JKaikJ zU2R6Z`|v>su9A131fzo#(Egj_%jNU}{s{#ZkIu=eg< zFoeLZaxw67TVi|ngGKSIYtQsckZ)4a-TksDs~iS~)NdeniL&by z@BZUlkj(JExv}Z`PUGF{kI^BNvXIm@GP*l;vw?S~y2i76YtV>x_!F696{bx_6`>gd zh4aI^)6W0)?hA0}QaVH1buRDz22yt0sjlW=d-r2tKcwX$FS)(@EeIYM5zR3--rfH^ zM*XnySwndGxl=fOlG>^i1XYcQdMxAJslcigSZAAiy!-2e@tYthkBSB!XG=oZgn0Li zgTxmu1YSmxo>T$i-H&DzU$`A)mqWF8KUZIl{Q~5SL$!B*P*8e?TOfBFs=fPud4X#l30o{$>G8K1Xv@ z)(a>wZB*GJ(cZlkLT-Fj3j!CjCAN1Tod*|m2b@AZkbq5H4O6`P>UOwpOf4P-JQc@P3ae+q+l5ymijiH^A3CR-|m&yDuFk6HuQ( z^9-DzQ+&~B?>=`1+7+F$2sBklmpb>_yT64`Bv}^)O|Pfvw0B>yP4X8H&2-Y4YM1kB z?_PwS3+TM7p?T9|&-U(zFnf`U`Z4eck15-`pIwXVa~bHK$AYeWb`0X(f5Z!x%90O{ ze%R6!Q9rwP#5Z)@9Lhsem2~>{)ZV@NIeY^^E}#uaH=Bmk;yYM-_p)g0+~k753AV)c z?io%hYc!R3KFAV>YVZCRK2c@54P<93x;r*hCVZX%IZc#Zr+D|D@g}RTA@#m}Tu2)4 z{(NB_qR$35{Q|bsm&KkUg&0@Wf|vw= zO>(8Z`+a<#&6W#+lyIo_?iDaH$+Q7TGly#LKK?B^whzc4hidQMxvebLp8_(~q1wAo zhI8h~%u0}T4i)d7Raw;5)LxJyHWl}wz59NIH(7E4_}5et?cIZA@I*vcRbluw6E-P1 zeLN90G8QXw(Am_BAZ2XoYBS>9hhR!z6S`}gK+}nI)U4e)?cM2H4z@Q6nnaI1+q?hs zxus1l0AA@aWqbGTn9t5ub^;&vSdrpu?>^;wOe3S*{{YRcr|GnJ?_18NPnn?*-ukem z$-VaOpB|7>mV&0%({$Rqf0Rq|*8!RVq@yLOh4!<1y&-tZq2>?H?L^siigzFNDY~x1NIhd8m)5)c=4tPK6OuJi zYp3e7XjDwaAUW9}J$sXnDxu~ed8I*|LHx_%2*VSzSy`BA#6C5CU%agUT&id4i^KiNRk(DfJkU! z=a?F;F$sgmk6QwFN+qEIwlQ_4`0$EJCmIEuLK3PiwxTO1^n)_#tugi9{t+MClWqw# zuNxg#f|k@j^N&wUJ^=p0BhgKts?7>Ld>>b*VJie2=^CnQ5dKMGSMKS#W=!Lacx!t; zGd=&{+J<3ci4{8REznlA_gmUPQIM)Ob)P6x2V^{|6y`SZiP}KZ`zbmeavjsD<~Oq9 z&{$~3+d535!ocmA&R=0DfLHx_6=a2>d>@bLJxZYm|Qbw(xCSR~Idh|9t6&smt4QA@$r8BX_| zrBONc9+E#Y=rrX;qYCOIlFu2$;Y)7nv6aeBSJnkc)gQo*jD!tyQ;)6j_FZY}&z4AU zy@)OA6&w(vCDhboYrc0tntB!B`l%$;)MM-B!$>%vs4MVLl2C226<1S_t^ZslEYL?8 zngq=pqvJ~8rXJg%>H_@iAW1d=f8de0TOc*{*hZ5vKtalHx>=s=OXj(i)$4x!9OXCEI zp!I`hh^^C2J+^Cn2B8x{rW?vlJ+|M>2WYL!k-CKlS0LwuW7XW$V+U8iir!{F_-7uC zmFJc6C?#}!jKOCcPBEo=7` z)Vw&ggerxUs&=Z(i(*ttHAQk~4+`mY9rvX^w5%Eo7Brl0EnT2KE}CMLcPvel-pc}HwPo+}*JVbIrdqA|cJsU$S-D6V7nbaJ94z^|v0(7dC#PH#Rh6C$a{{EQ^jL_<=| z0gmgExuj(1M`->uI{r>TPg9{jC$9SutcJpKinEl(Loha1@wr=y>v463NJ;_MG7@LH z4d3x`J-5Mwu&EBv^ftOG)FEq0uguwH!sb}u8Ajrm;`u~zeRljTrq)2S#pu|Smh|0^ zhZjEEC%~tT#AS*m3&r)j0k6fn8_?V{I&F$2{Z}=XI?YxN@Bi3z9k@)Fxb9g@fAoB!xS?a};71eaPM!tf8YAWlnp!-3 z^Fk5thVYnI>`Xq28}%{5;XF0;5;Q-PPT%`9`6w>>A(k#<&+r%|J=~>GntT*D`fHq( z>GL2397>aq;$re(&OFoVAaxx|laJ!!Ccr6kWp@VYXH(bYqqz7XaEmM%2Rtp6geD)w zB^>xl>UkCLdRw9=AH^juA1ekv1o_yZH2Ekl>G_&MzXQ4CP?~%cm;4f@KJdvOfIN06 zO+JcCIdm2sF8r^`fga&`Y*H^Y`6zDUX$0^1*oq+44b_v6;wE>Vh5o1;lAk*HC~o?$ zbrLT~^l0?tqqs%y-jbXx0A6WZmq!MAJ&AjD21dC#13Q5adnBTx3Bz$q+uxB!@&hzK zk&b(@JUPmu?`H#l+KHxPOkWWlBTeawoI@RBd_j7dqhWw&w=U$4k&@$!sj`q%#+G%$ ztJH;YY6;aCDFHiGIz~pNR39Xd_Mni_+%YmQt0scYHk`U*v06c`K=LMo*5LaZK{eGb zB!6s>(=o=^{svQVrXg?YJK(EE!iKqHjBkAAn#{fX7dTxd6lOLRhC9ai=0na(_mu}E zzeA~GjBn8a4U{{rY9MtSN*!Z-%X_~H?F7=pq0}+Px5_$2EXRUOwW)i$E_ICYt(PvA z&UYm=wCJYJA9sxLZTd`+*?)UMj@Z=IF~$e}+9L(L0Q{?0!X0CLyJt%%J%dkGMvKM9 z=a3tfI>z|+Id9_=Nz{;f3Ajuu33ZI|9R}_eNfY36OjPYH9cwuA7Y2cqoLQOP;F1%|(ZhW^p zd8OnJNmIqvITLre*Ng8tP>H>Q(3B<}wGydk>O13mwHqbVAR7aBG!m!Z;9f7j_m4Bh z)JSL&jIIjx0$S4N_#ZN7az5}{BXLY|uNU8M-PfYq1I;0$V^dnv|58OM;P=2cjl^Y& zdcF98Up$aHOloulmYHX1@p=gN7%^W^woHF?FB%^`AD=R@=ip5 zV|;L2vP>QR8=5Di)Av4gjPYaMvpqvj4Bh3$CX_nH_}FH6$>*-G5=ae)QpXq{*LS+m zb|76GN*!Z-;xIfEb4`v0p@BhnWz($O_;Djf%5_@=ygHSHI>z|qLh!|GWf$;1TcSJ0 z`0@4T$<;aoa^9iTF~(2$@-4aCcR>DjD0PhS6FcH_aJC#?9rK^CNy({WjGtT-A1Q2s z|5ar`Dmj!o#`vkVuuLN#+X|$ep}J#?pYhFDbc|z={M3#ye)b5wchjX*3q2a$F~%>W z_2Ah07U1`7>#mM5e)*?~Qn@FAFL)%bjxl~EeYMVwQk}4J{Q|(mFq0Xk}Wz=G@H`8+cMwx?+lvf`>aM*}=Fkhoe>I{-E8Kmdv@=;aQ z??}#2Q!;T@MNN}uQ( z;2%js^{zis=Ag>hw(qU+X~{pp8EV-Qep%O&b}!@+NnYUcMnaJ}*TvG}4tvqRaoL(f z*vp8?UK(+yvvs5*;vt-5#NmiPTH0Rc#0+BZHQ)_K@*HNFiKI&$=AZH@_W>U>5*@bX zis*V~ubk)-@C_qb*qAN~OS<)g$7Cz%YNHur({)98(XCPIy7$FGbF3=?O%0=?47qhZ z^3;-3wu7dh(NV74x}JwW65TjxW*Hr2O>{KqFt&HKt;(W1Os#`vGwG;B=mCqdeLpWK z^dQJlL-~8jvHjmqhmaU%(yNOgR}JN$?%1Jo@%1P_=Kl+lvyNEilc)M)<%}5>Z;c)G z=q1Zqg$$}PP*?XHA(Ch-Grn3PNn79^MnXT|Wrfm@vW|_ZQ#GAc2-T)yfhQP=?#5UW zTz6P$$x`5TMxw1;TxnTjW3wOt!1b~h_=u6v8a!4gOX5C5xSb^zfUnpREA(435I=RW z&_^IX_$;YddW0RD@Y^K$g8Mm;d=A~x4n;@~zno4thN>V9i1H1_E+VvHXGq2;AjHk> zr5o_TR1zAW96M>nbxW6WJn&4C@Xf9(qT^&_W9rwXvHr^33}Z);Rr9YgYIgJ?p6WUa3H3CXt&N^(loKs`os=K50B5bD3Q%T8z> zi;qjEL#pxvmrNxgmz~gNK?ix+X$Txek~ug)tdPr22qeEEUVRX7OezVvp@eo%ru+1X zUIt!F5~_FoQ7L<%g!W|-u;jdK1>S8W{2Hkx9bW!TtegVAY9tg*ch#d7cWS;5KfXX^ z`xnB92KFh*UK(+ixSWVjlejp9m5jI+;^^9wCUnhrQ0%n=?rbEDBaNh6NXyjEb09k4%yX=JMH@jH+0rVY^&uq#kPxVLpiuD zLG>flw>(FPBrY6-Wh}|i2t$9^bOUx=cEZ>%zQ;o3s5Vs;xPp;5E;}Kiln=2FlC%Ks zXe5ryP8in>FQ{BEBY_i)#BtdPNxx&+QI^aHUSdnM%T7qHj+g|~Z6G@xN-jGgCC@u@ zmz@AP?ND;r36qb;NV~cLa*rtAVC*8;WhYFj;uA?WxWnAo+!Aux2{Wz^!NTuU%5uOp zNy0a~EJ6Z6wkHnlo?w1$!si>Skpd`?GS-+<4&(!h;1jf4M0iPy`+K8J{OUMT&*3Z3G zqDeP^@1>GZygIS*@Kab1j82rTDdOMQxFX%d^Q>#qdJe`7Nmm(~#zseH6F)$HDzRCW zB}(ghLNmnZoMHUL<`u_^sfoa|jl_8jPi(RMu;gkz@E#+1+GBWP%atR=-j@*mY{aP_ z!)dHEF>2c*pMF+*3}NPGcCG2UXGt4Bipr03`GHFsiLO}kc8P75ua{@FhQQ5jiS~Ah z?T+L6@WWnTkiib6c?F4GiZxQ&`~;ABHg#N?6-tAxiQR5Y6Wtro?0%Y#Zt}!lA5Qh@ z8b1XMElT5DL5pwl#NN#@UxhE;9pJ}a2?wDPhrf@NbvEH0S>?bz_B=LjO?t>Sal`<8 za>%qINOePb$Tl(d&&s%uTO+k65xNm|Y50orkZoe(niObaz>_^1E6?I;@GM;2vu$FW zz$&CfkeiO&mIx;>Ezwile$9mX#b&@! zwnRIDab50S5;_QEghR;*jO!JTB|bO@Q$ZHnG_?~L*XQ1S(QSoh-_vyD1jY?0-BYUb z3^bQWN4J7ZV4;_@aRZ|;lZR{Q0dP9pL@o(CfpIZa&-<)*$qD2E&QB6*P1*^J3x2mq zX<7}Wj-l)X#wC@Qh!?4LNbN_2&+gnj>;%S5{1$_cDjs~2M`Pv5j^{(g^)cTj#tE!L zO2ixZ6FE8?rYI%lqn|6MH42}l9m|(_{U6Fo8c$99rDclloTUN0$Ku6K{fMJ(k-;(e zUkEu4D+?J(Dy06!f6_$>lGGw95-Bg(sk%w)1B$8ANN!*d#g%!L7`;@C7L`=(An0jC zt`n9~BauAWAYOBovMl!veZ!tq?qY5P=P4Yz9Ky9EPNer!o++JFVJg02V!8)pze8!J zbW-I4m>kFS8;~CyN;9RCs$l$5)4L!K9ZEB$ld7isN@graw!uRnHaYM1EI77$GWu(_ zTn?m)LusaTQmvgOC09`(9UMwCrIYG(o-Mf=0TOg5&6G~6dkFU-Tb>0n-=Q>9I;sAu z2uptlvl(QYLusaTQlqvlWv28|kP{9qfTz`@CJQR~^v~K~1-ao+n&X_*qS7WgZ@K`Q z6*exf`|hJz!b$BKbQE0)Xlgu7N3(>JI_|D4wc8GweoxcUEUcv7JDUW(eLP zn6?F>`R#Hn)7THDVDJwuT}6Y$5v99Pe_ow5Hh?E7^)galvyXF4;(bjGNEl!xjXR8P zo@-_&M7mIUqH!N9PCR7WG%n*TQX*(w&2ax^+NF`3$b9(BsAzH_TBxAvfroV#$B=|jt_o?t@^KaU&;s;Cl> zJjEbhZdD&uSuH~HYJ)yRUUgI^x#}paKAViZsa?Py8wnfc!R_R_>yXNWRNrCe5=kag zVM2!;$D#En7x8HW4?rFh<)ZS?cXGpvc-7O_zdf!$HhnA)JSR8(Iz%j21gT?F*T8df zvo3{Y>PRQxzNsX%KvQyylykC_T_W&QuOyTPo|9W1f(PWuD=UHDNF|}c-sILZFUnxs z0pL?4p>l*!MaW<;J**@L(p|$}s<2<6`PZu>rz1B9i`x~;g(p)IXUDU5A#7=k(r8$6 z$DDX;;00T2LDPVAx{7HuEV=WjVUo3OAbkwgqhZNiQ$lfqNl1R`XjpR3glEK!to3O0 zXjt-)=)!Ul_5dHUtxGXznn?1n-#1DIz6ZYPk;rZHBAUD6M)Hs_Rh_wQLUCI}MBq>4 zy~>#PKE6-_dK{Wy@ht5iOiIb)OQ>p))WMc@#wKdjoLWjnA*Gj{%4gH3)V!=31vVuu z4;e*aaxJQ$7D2Gui1f5!wqHqYL-KwPavxeneF65J;RSk_tW{Ijk$l%6y8GpXHB^R9 zi2q>YvbYV_Qu&Zv!XWy&7&)qrs)6Lj1`Wwc_dRE`p6ZC?fd;j}SBcsxPevZ!U?4iv zxu`ZZ9-5g($9dw($m5&M$34Ke;#%OhNU{hAglGvp(~oaH$G%$+0e_K7LVeBnmOI*7 z7F|nq4fvKV(PQT0+q{C+SvVURI^)wnY`XmBhk2w`(akYF@W*AJ7MF*xi4jwVT-Q0& z8fsbN+m}eex)yJvwe*5;6p1|*0=xD8fP1(00IAbkh$QB_neBsVok-vNxOsm@65XAs>1Qn(r_h~)7G@jc4- zMM|wg6D;dA>Os8gu9W znvUKsb07Z!&d^N^$iye=TvD3N%4_MR`0@gmA_-lb5Xy#YCQ(X@b_IP}*9e*pMwe=e zZAz;Pe$kD9W-RF_&#sw7DXp6ik`;UB0k1IPmdSx8xKr#fEE%E7#(+5&bUEti*17L`$_Ah={iylO3#PEJx@ z{SNlf@FA2feg29nYflUUVdGqdG=NA@WmOo-l|4v1C7rcusxer=aDJH8sD|o;8>C;9xfpfS5+olmh#rCe*RLV+fsNED9CXzjXfCX@0tyUFXnJQCnjval z{R^SLm#4(s{Z7E^nY<_E11>?5UN}HkN+@-|6QT;2mFXxAfLo`MQ1?3_a1HS-Y7S~3 z@NiqA@2LqLThWT2l#MAM%ZO5Q;B&aHKHseqx_pD#S1jHR;X$uhZb1013Ehi^TKbgd zp!xM_I=T}k^!j_1WKH$PIkD*ia$Dhhc|xDR%1ht(5^!-_V)4B^pwnw4Ii36EHz^fO))hF1Jo#5*B8V8r}@ z7)n28KVkUWm_5Vxz6JipNKB;03awANQG*eLVx5J%Gb?R;eRWOJFGx%X=1(t@g22UW ziSB78#2>+wCN@wHq@_(=JqLynB~+ z5A~r`t1ot+9YniXX*ZCYrnu#x-J$tuH$Uyx!wg2Oe?Yrk@z@sbuR^=!upDi;zdr3Y zUq-vFXgB`}+U-oc)z8pwKiX|pg?2~MZr?hzn?SqOg0wq@cH1JH9qxaHc8hJJ-PdTh z{w~_xK)bnb(C$05TmBC1?xo!W_){}W3_fA?e@_2DMgOmc3l#1@PyfF}{~v)6Rha*W zNM+UBdy;hxs4F=5m#xtYtMF7Eq-MU_q|_aQ3ugsnRi!4;!Yc!28y%MxtRIl#0fI6R>3^ zWe7bo@gGYIx+yguaD@>RgUZTHZfjUi_4OE^RS^klC-{L>ntn6!&Hn%ud&jcqjOrZt zMbcC!6Dw4D%D^C{sv%9?qd!RJTV#M{Du^%hH8{Ptfo>!krs_DD?v*q*HLOB{x{oB4mn;JRj12aU-=Nv zzYC-`;Lkfo^ALL|P&nCbs#IN49L1lnY=x&lEmhQWm=A6J)O`^D&!421^eg#y+M+?xSIPXS&+M zjUi{0n2IkpPN>|vFNU+&igAbc@2Xk!;b%fl#|IGo6@4)N!Ist;N0EE5b5a>_LRGmI z>KlB>XsgSe(Dd`Q5kA!znO2UY02QjHi~=?-5!a7CDm+UT09$5p6=4y2=!80@>!M$L z9nf|Q2j+|XIVj{zsQ2Qn7@B{H}$P0kpuyAnCy~t7Ah?;QCcef)qdw_ppIXZ^jnERh_-F~c_ zlOF*6n*i(Uq9U{KF2M=cf9T+QKezIF&_tvkt9%f5ss>A4f_j&~;Y`xlCz=ye zhPw{F)V~T{XnMaSXS{rc6}kKZ80I>LIQ?(nvdeI2?1N7K8!2XmQjdeszotBj5RcK? zL&~+3wzfP6%^F{;ok-P=4t1rx1#E}KA7M~6l-#PbIsKan zQz?REMzE=fbv8; z+Aqe#v*GH}6-dtjO@0^;gtwahhgo0wFp%*UZSoH8^wXyEoOI~ube>qL$o;r2iLDrS zn3H@M3v(w{RfZSK&|$rtiPbkDIKIHP6n~55!5$-=i8Yi;mPl#bADLKF9ffpLJ~7g9 zo?wam3i>%l{4|at&oNhbAj*lgrEq@?U9c%cE3cFaP}K325q`NzyMYQ*SFQ%sArV$z zcT#YD=?-Xsg;iv#8Bc7u2aCmI9H7T792i$kbYkNTxKAoMz}H)jTA!>IOlwZlpC-c2 zHsBvyj)9%1+RXCtg$dJnYm3 z-rRD6W<2q_r}2oNbOdy_g@a~1vGs?W5yKEb6D-UnC#DUu8Be_aLyRqC9`GfW6Ex$A zH-6g~75ECEcN5^aW<0U&7x0(RA>h9xa#pdr)#tHPGhQlVQR~8HDj@_>S@zrUkpJKX zY5l9v_1OJi(2n_871NF>2JN^#LflSkYw1_Ioz|8<&^=3RDqn z8Z+(qw;_&h$CZFo3sBvTkN;&RqOJjQy+u_!rcIn<*+oXxK0VwEj2IQ^VYc#Um@8?b zVRk|3;Ryt_$bD2P(!;EpsM@E8mytq6dYIOuVP+cFzf^0H`>0Z6{PtbQ89ynr@*v#C zz*dYq%sx;(sgnGPFn?i7D?Ef%q_kDU8wescrH$x^EfrK%DnVV_LK#7*8qxylP8MP) z6;$75S5-JEt0d-x$|8{558?<*R(4wd$}}~UT}Y421UBEtbrq^MKB@7uZ=hAI2DHhC zBWf|LT4Jj?&F;wo=R@FMT8>SRQ)FFZd~dtO=rM@qSKuy6MCUZH^Q0)!HJ`nJR$R;y z0wYewr(e6y`0Vm5PZr*IiT;I`cB|9dn6l#?C%Xfmk_v~$e7V(ivODr1D>UYL+@;L! z#Dxl-L#dY_M0OP!2@_)(M^r|=PH); zK@g8xva-{9Ybm6ni7@SQhP%Ngc3skiyN$%HnP#Q#HxnP10xm~N6Q-ibO7u?IErxGE z8P|ojkssJ8akGeg-!^s6jZxGEMaX5a8pGgrU1XDg6x0m{aieN($1&E1nPfqWC7S3HL@ zXjkDl?*5`SLjMABkv*NqCZ{&*T%Z}zAJfB^0*h&p`)HVjmmbcdT8rFAl_F#JCUM43 z&U^;rP;SMzL!+a5awX}DFasIY#9?f7N_#o3iEydlYa{xTND8__7C^nsLXQTas>v%* z@30UJ@qtUTES$G#|bo^k5ZFD^NFOBX8nD~`(EKtR18l5{77h2eqHnKQ?YD!tC>srVr zDz2onvp#-2@(bdDUIfWg8{@Va!qk9;uUln#1`Vb=0v6Wz>EBdwQ zMpqL0vKBLquGQC$Zglm5G!0PQ=%!+Eg33iFAYB4fH@Yovnnw2^kdYQujgF~7GonAH zhaUqL(<1lLFbfa!KU8ax`>0Z6{KYffl+2>T@dPurV%(w8Q9Y%S97dR9jOvdOY;;On zMSg|moUc`b3IkP@A`fBd6E+nf@^28ThE#>RxrOXNG0qjHWKC`FI$^em+d=GM$;wXa zI+x;c=7#brVwT~+Cir+O!BpnVgXcB=0d&FLN-xxC7qqs^Bf)`WJ&XTUmsYqvg0>8rd^I;chbib z8r^pPK{prq^RT5=W-3ghJA_xgNEv7=5>ZK4XS!#n>tUKSg1&_fr5fGgWoF2D8}xSt z7#rQ(nda3ZL!ciKU~F_5{aoGXWgMa2Ak0^{V_f4BI_|Navu$|@Y2JVQLRPpqe}6d+;>w4s2=t9)VUVD+?Dq4Dprf`d=eeWIVJpEHcQ3sVdJvyVfFhNEhb@ zQ){Fg!gCS`BilgSYst#Ye`G9ER8OiyFUPU_)hEQYxT*Djx&d$@WT6B$mFh@=G3L~U zqicgx9e5MVu?f;GZffJEc%D|;0qyTZZg~_73 zNQ>izzin|m_%AJPKTLeeIL5O${T6oun%{kGWJ&XndXfK&`n-Qv1unv-=CAXf*dZgEfi$DHQw1k%l-s>P{cVKhvCOb7G3GSh~!`$eKl*6&l;`{z1;POipri#zEhH z=Adh6Z2v($ooVH{G^~3l^+(v6Rxz{=#$RQ`PpiBtZ54SRnvZ;K6Pvpi}MY(V%)(msGfd>e2y?*G0p|!pw`-I@(VPDz*Ab?*yH>{ z1+6J1K&W6ziy2<|#q=zvk7;s^0kT#A-)?_s=IcScpNQ^}nOPoV%$$=vNYGipi- zrmQ2_(mn%*CCb#+meSDF@U?ME5;T6LGzE6E#pBkRsPOfqE3o@4{%&BpzKno+Y69dh ztY*{=Wj?U~SiIrgHdW2!WvD;15Fe%dUzUbkqLOosoJ1f8ZB}J6$WDY`QE)V=l|(@( zWl4HXiVELGszcq=V+Ig@D&t3d36$C z!}A{IjO$KlVvHbNDWc)oP)EaB!+lgyqG7s!R4v^~S8{qdc@mcFvLh@8LHh)*e|=?D zD%B@5GKOD@<#IEsa`D$6==+ON2wGBm5O2qpR&0v(SR^w4{fio^GKaysBisC9%k5F<3A7%!HP7`*FN+8)YncfOq?ph$U#KoJdBQG2c7KB_3uFugshmOrK|IX!$mUYn5~z77Ud z^HFQq`rzgUXk5I64`N{-Rcj-oVXlLWh6iDvuH^La7(d`l2)eVt_iugWQYzIWH5mh@ zVoBx9N7FD-$gL)Kc*jW**O~dKYy)pEwzMd;5q>zyDZDU3sKPndxdci%0r)g2r5UhP zT?7=Gm-Bu&bG_1Z`j=edLo6ERlaSGH1q6vvk@3ScoJVI)W#n_P#iwGb+yYH!Y-xl{ zDsEZiI5VeixF+QA4!R5mGMtq8*qKyRfhd!yWH^%wQ~?ffRfv6zV#dPn@V5S$lNoj7 z(Zr}H%XVn@VM`-qqUPhWGbjIv0^nUgISKe@QevQ(sQ-gwad51{*{G?GhD$;pqnNSt zI=pm$W;Uaq3T1q*v*lW7+R_9e6Lsh*lznzTOqQt6uJLPn_meUUI}>#oi1G-P3}>UJ zIvSpfeT-tp5Ij;;a^@sP9h#OH^(1)WPec43zP?o+yo=xei+zArp08Ekr$W+f^7Kv%tFo z=}F2Y>`c@d5M>CJ3}>UJIvSpaeT-tp4=3nm6BzZMIF65cg1iFF+t|_wnW#H_AkNGQ zd)naM2y^{0ki(>$!_Gwg7(_WmCBxaMsg8z|rXy;K8Oh0!zQht+zGOz;0kVUX6WE!k zABHH0sAM=BHPzAZY3ySZGiqGRs7EvEZZi|39xbJyxg1*>Artkuy=d2?Ct_9TF|5>+ z=0L6^r8jma>fd2lZl#jpY}8ao!vmm-X|a-8%Q>0~Epi_XQxOe!##_nL!wU#%k^87p zM8oT#?vsi2s&7Mx%)DQnYq%a15Q-)}tk;HqOd7A~z9o%(K&O1=KXGAesO74KW+65$ zavu#-5e;|W%cN8ys73ChN)Zh=fx1tnJH)vWLS&Fm3YWYh3o0pk`D;(on3N%;kq?t2 zeC3q5u=Uis*C(KfX_5PAn2Kn)?<-8oT7p{SKB^Sa@cU5r$;Sou0SJ+=2dYxx+F9H| zQAyG3Xn!D$NjXaz`7jxJ%qY_#_+gu>rM+dKiD{AhXqbv*t^_pY%ag&r7gb4XCS<+Wl zq0)rC`8LK@7n+zBxyKa|6w&bbE(F^X)FSs$rHF>_gSt;P7HSWN5IO#Usvs_<#zmN_ zAib>mG16En&yq$yOy>B?m*c{AQtPSTf+nU#?xSHUqTxrIGAW-C)FSs$rHF=qfx1sx z8+0DC5l0us5e;)qc2q6TPFFJSe*;xXxq>wEVX~I5Y!(-`D`pGv{0lTOEpm^GJ}58< zD@(8sK`nA0Rf=eM4AgykUX8OCgvd*+RZ_U@JgQcpr-$_t^kt;6RMwM5K1^=(mD_FD zjIDR#al5Wp@Dnx*=VEw90mHNM@V>4!LqCD&%|W;H(+Zg3wTT`H@Y(dpedtXc&8#Dr zf>q9EI+v*M^`tg5jeV^OY63Kn8=>x!0GUr~tDudgKd^@^t{z&@R-4IWsOKd>I;c)d zOIZ$VoyFA`Z(3(EL#>24m-m3>`?&6L)!Lh`ZJxwyA$~_zP%gVQ5{rw2$~?^ul& z;VH@}z~g+1qoygk-q~!9Xmmc1X9JY)TIt$#`yi9j4M4W|sQ!d-kyRC4r)!V4osrl5 zfW9WIDp@^7Qj}GzIrrY>g7YWvF#IEqqY9F@<3W19ty})9Eab=K4g(|D@Yg-b6V$--N_B80&9OS|{HR6F<_-bS1(TTot&Q_kQab$@bLsEcW~OBMfPDC=}Za5@@IcRT$O=ebuo^1@^e^KB{u-S=R!_` zlW%(+PW~WBBYh&BTqQdi=KHtP)gGe}$Qf5)btZapes{0;0ysH^peNr56Z>eU|MPHi zwX9W5Bwg5(9|P-qpJ|=^FKCkH`{C83i1x$=QVi-!2~eaDCp2_--B{`YYhm#OCvOLJ zw**KB^__eWu!k+KKGWwrIX^2Xj{|$g#}l0V?+K1G7+IB<0l(=}BFcnu^0z+;Im*fb zz(+_K&a#Q`$=ltE=S&#UpMb+p`;-fu{H1!X=4FCYJ%Q&t`HScxm8ok1-{4bxCqFVA ztIZiv4+z;oGx5GC zISl-Vi*dBu@4!l05%^d-wz#;o9qsn(w;?^1fj7R8li>D;u+&J}g4D?;((P5UG2>8! zPR>1^yHqk)_F@31_I$Zp#+?H&$161U`{hF1Tz4o^JqbOF#oXAG>B#87etjte^%WLUU&Ovdg=!)V zp}y8a`c>WvY9_Zr-8TV>OIqt2nW2`#caF;#upaf9ac)2Bno}4DEkIIa3E(9Qd#^>y{FCnzy+f1@fIm3-e?<>z?YP@m>O6!<+|_ zieM_N?he$Y_^clPzT`M6kre=6;ZvN#^yFDRf7y>KPiCPdkehted=Yr*wXQR(_ps_% z@ql5K+zWW1rKq!gaMtIWf78Pg0mo=BJxoP3%$K!eIIT3?M-?R+UJYU&no!@FR$n=e zhUqHlYLAgL2@4>WnYFyuggRih@@hTiQvc-T2ZCPn-8{)P%CG zMU5|=9%cr8HvzfbM-zPMOH8M!L=FTz%%}Li^exthD|9B1`97+Lb%nJr)xj5{lrOCX z{D!5dQ5}3q{bM2-uMbZT?*Sa6y>z9Bs*gHjMZeN;A61lS_zw{KFlfqBoJ!TFMKLXl zioxP6>@mlMeMa%;uu5rGRi2LdIe}ugmWubK76{r3TUvEs)|YOBrnj$+t1#b}9s)M~ zLfo7)jW0a|!g5Q}Us_R6ec1r@77Ja^6#2fC5A|mjQZJhJed#3B&VNi=3x4{=_a%P5 zMv8-#=`$02>EVxXM+aGzhJdg2DG`-A<4b?;Fz4F40QVrJ0n5ht(%t>c+Z0Cu8D~-B zOG#Ty*!e*IFJrnr`;4MDI_ocgr81xX3V?L_Su*R3}|IIwO^$*|_Bu%AH z-|-L5SPh%d4=w{7V{GYRDlpBb_FBU|R>XpWMOxVR;mNKe1YM8OFkK~G?Qtst8) z>K@pyFR}~?#-?J8%w&puUn&iC6$|Ol2q}Zjqyf}7CqQvY^L?ooVw4_W-S0CKe5qA+ zyvYwqk!-+^`;>@Eo$;lV9%i`mJm6eXCNb^Cmy+=^Tb}RbJs=-g)cDdw&x|pS0r}BK z6MU)E5ph%^Q(!fMO`A98xGMER8m$DRwvXyTit(j8@tPOaFSP;O(NfgKK77es^z%zJ znEwPEV{GVNpooU2qO7A~t>GRsqM$^>k7M75L7#)5>oFRptKiW;732xE=bLh|{)<+5 zD#si#6wxqWmmLlB^T+AoPY80h4a-}gh^jArgVLIsGX!}xnywVMxdJu(xe7HIm>r36 zgoZW%MKoMo?fItT^f33)@Xcz^?@40~0QP7EYR{LRr-!+ZhBMWk3n0_O+(*MD)c!%3 zA2J3z{hbe-*YTuWy4pv>D%sp<*sJ$*0?xU)lqG4VxM8h9ppRQ!gf~%zsOhf{upSBSgbT)Sj=;N)L07)fQ^c zS56`0cT=zBmzktNICX7hk~-DE@FYFF%}?h+Dv3h*xvxBFnbGj?n1oGNd)%wRtJ&~K z8`hCU!!7Ux57r&vo@Tm{ORYpiQ|CKQH3$*6p|Y7pCEdOSl|;dBm~_{w)IGe!e8m{9G18JHi zYAGQ80?JC+vIg&F{DYZw*Mho2R>=)_I?iK%l|0}=84YiM_67MA8Cx!Et04L>p;#?9 zVP++q#UQI?03PBFXQ={ri+Kti-HG2oI({seR1H#eul*ueF)72ql+9lkG(q)*nAsIOF?No z03=7aSj=4waf>BtDIjvaU9JqmdcR9*xd%ZzX{lNYsDDhRO)lkh&x2HKwV!4!1w^if z&6S_$;Ea>yRs*etrD`dlaxG%6@D)zuE4sIV*56XK6i~TBDp$A^Y38Huc+loqs+IyO zS2N`b*9*;@>aGTDi=}EQpmOOD(n{)N_aJB|Emcbal}m(jh3j!nd9AD(DE!*O97QjOLB$lKW2_|4}tcBrD`dlaw$lzaJ|ONv96no1uxii z31}&xa_L5{aDBzhF>Wo;uC-Jx1ynAz$Q7=Km^s?L6SRSrs-=L+r4bl`sJ_K1h6eU1 zsB{c_15ycyye^h`aR3eUQ09VPcPG7Pmt_mm^U*-3o_=5cH~H15|2`d;K>XZ#hH++ByHqslxMsWa{*t88wcy|Gw|H+YBgzG`k zA`#A!l|(RzbT!_+2zmGu>``LLn6&K0(-U>QZ-j7}6B`6MM}DV~xe#B$ zremj(HPS1~3FVGJXoy!D5&YNi23z+XF!m(yfpl#Oa5=AwL)H!!ZkxqsEay$Nxs;Em*;d9rg4S5Ok?*b z1jl&i66!EV>a!+?z~X3Yl@e~5W1l0tnXuUqS6J9&ez+4lMWqwttZR zybVGL?~r+Zo@eD%ww4)Le z1X#Y5BX!AiU&71}HtlZ#^JXf2<`1~#>(+$gI?JTAT8iPGR#Kw_fSuSLb&h|8=lIS5 z`&uf`@ev+6u|I+4$mL+VqoJ5-IW(uQZgS))npg!M%i;key} zN+*`on`xd-8(B~^u}n%%Y`@C(PfcK`9Ta^nOhar84?1ou;dKoo{N{e}Mu0QR@+h%w zCEu#rj}sd`nh~zM1Q9L;_M&A{!utnt!J8vT32%YoKmxo>Y&V-DN9LlR`x^LPmZK%h ziQNxl>t%A+kdyMHTXH=MaqzGQalrMuh^Ft4h^7kkO|j_$(o$ezG(O6mBfP=kwg;)V zC2A=kay~y-j@3n9SkZk1wAq%brGUzNKe@sWB|Ti;T>;uAOVv_9<;RwCr2Pwg^3q;6iAO*qLu<8r_*xfy_UFDe7U;}w2hXkrGUy=x%F}q&-tay za}R-L>Te!beIvHENg>Dm4*Ij!gq8vmFRJ?E;sZCj0nbEW(-p0yfXI98xxz0;kErN2 z0j<5IYAK*{T}H0(8#j-Xcl&_$h^1;NpsrK(*A|lk_my|&fVRR?wG>b*sRX3l>o~s^Z7o$x0hPCKa-?*BH1(b!Jz$BHoLCRlzMBx90L9EiI7e!pM6+E8?Fx%fa$<*Z z5?U{PZ$o8Ib9X_7Sr(phOr1~Ts#HWg{|&U+&j6pc;k6W`@CKYia)qBq7*p9zc@4Kd zvFUtkDWHzP$Uav_;dbqi3htGlwYF3(1yl}xb0i1jXtxVUy)BUv@{LGyRXfO@a;j zK{In-e)_mN1Nq+m7;0q*;3?LUmI6z?R7>Ov3HKS0)>@*L0wNa#T{t%pqaG-$~i{XAwKE)^eXR`0xio@wG>dhC@LR}ezcO? z8nnACRZ9Vt4@2k5>zFHwRdR=bHpNo46j1L`+4^Mw76w&v7lHPYrD`dl^6h=O!Y6R2 zS8}(3_PM2MDWLMH+Z-7kMX8CwARS0oAfZEd@kQQRhl8+;Hhz z$-NG=J1td90hKe|>m?nFrr{jpK!bA>jdNZu!bGGSm%%w61Ds{2=w2_vorGUy=${gu(2{JVkq@|XqrGUu0R5`+% zf$j#7c3PsA0wQl~=E}fwcs!tzdjz!KEmcbam3K$iOIu8Iqi#xVR&~R{fZuTWKnEiI z7?X2uHNY*f>B7-cVCh{|H+%($dn-tNEm2DWk?*$15xyM99SzbPOVm<8vCjVIS>bcG~N=m6cD@2X5ucv z%ILc?-KRiXZK+xcs9boxUf#qD2vZiiJ3%vvTSys+JSwmV14E0ut z8_^8J@LNev8Em?CwG9qDM+;}QA+`_q)ObkAF0G$ z2il#Ms-=L+2aVQCXShnrbM8pcOyZuSjKuN9`#DnNH^ey$n*UfsS_%yPt`gVgXAoZn z=>tpDQb3%A7<1)|pH$+Gf_BDIwG>bXgPJ2FOQC;H%|rcTGxe{efY@720knS;*X4Bq zU2ln63Wy^VF?=5`MZ1DD#1bj3;UK>~=g6GcZ|aP34~dfjJ(EC87{o^=fU^qtE0#kE zw{_IjQsL>YGw5=6Csbcrf|i10mBKx!9Qg$gGPu8jbj}i)EFd@GYm;u_cW}jrO&0-& zD)yTEIfV4w?)I7-lTZ&JL<_KQO9-LnF*@maj2u}!7^GexJbWQ(u1{)?MGNjU5EfrZ zTIrJx;+~zm284Gki4sdRZJ9377AS}uxo#|o9|QU-fe55Lk)NSWdDqXQHPKm_$dOT; z#VHQFy5-pEpz1=Uo(@_skzp>c8ahD5%l)`3y6IKbRl`?HVX8aehpZ_r1+@}UE~EI^kQTsi|{tpzo2X8)c}?ok+lPXt!h2S)s&aj&y3D*lpxdkoQ7%VjrOW zsj$XCAKZa+zXkLUHf=ylK`lJ5W_IU(hnR}KpX5}+rioe#h#Ns%F2zrQcnwIrcQDea zRx-5bxXSjI9JSvS08tI(NJ=u&&>z4<)-)x2ibPH4zR!ugX;3V%Fz5LqJj6qnYO?P= zPUPi6@vh}?B9GAA;hTrK;NBAp1~vg`(pA4j^@#pGz$Tx%>w8 zk|V-fnq@(%Yl-^irX}V`Q4Zv<0e*+&=n;P$rx{*P?)Cxxh~?;RERJ(^MR2AAUu-#A zvYgoQ-t4IPi3oQ+NZTz@O97GJrNGo_FAzTm>1RvSQb6QqIC6xa2yv6QW9d6KUF%v3 zh!quaEi0fFNR2F!72v!oC)q}FWbgv~wFB725-2&bKU8_HN7=grp_pr77W|8H;5AfA zOgM)@hw8xta{TK2hvuJ$;$<6<6@j#O<$S_cXm?qJ^9evUJPzbDXn(T^r4{m;o?!_i zBqEsjJd1!&k+|UX4hjYW9w1X7Nt$lIaq zVG*7pfovx-7}`fHLdl6uQm4#LZv%cDif1fL$%#F#;FE6wUIWF(L^wwVZUM3#+I<$G zp0cByWc}~&Jwf~)bX9F3wXN%auwT&&mCdYB|(Xe4EGu)4=T@_977bf zAKrxTHUoIQrBZTY1JR_HO9uy*`aog(h}3^oA5n_HxB!TT6p$nNFz!AEAO~9zcfy6h zPwdNH2ENB~*q52~J&+7I@)z=e!an&u(svlN-z}9hh)m94r`khO3^-^Z+<|qIKET}% zY&up-I@Ps*l=3)mV(oZpIlGw|`-b^$VJX$Zp}Td)unY}%eF7k&fgGuXb!hH=0LEg| zQBcx7c(pZ2fN_^bb%cjQShW8Hz;`W`g=)%hPEvbB#e-2!wcucYQ|*Z)2GHGpj!dGJ zLr|pd@*|A1G9=zgZ~!Y0CNY3-<#}ebEEH7}tf0&WMUbI}(B5ScO1dkqKDfJ)dpgwz z_lAtGL9zI%_&eO_b75c>t5lZT|81J~=v{9UD#pSV7)qHEK ztB1vOoNZw3wPEPANa$nqfuqo#vIr$7c1*c&Ri5y?-MIOOt;sN4&a8$;r-!OYS?tg{ zL5{txLgdn59cY_j(?n%(xxB|S{yosD3zbYXITpu*&Q-OkbYi_#_*2lk4?;23hG#?x zK3@9-I8Q;l#&Y5ucbazG4Kf_3+-k3hy9KNRmZ_znS-+>E?er5&eh<<)OVsn~mbhGQ zVneuO4=;>*qZ!rR&)dD|J$C)AdXFkVnqt$L){+e!JAtNwCRZ6I+JkhTB~mi2bMnGU zbo7ww9v)|G*#Q069LBa>Zg~PJJq~^OZa3WEFbUkrGAJi@3k;wOf$=6iYo(1MF^5x z!)NID3`3R5aw$*73@~mhR9nB(^uMS0k@yt*2P(ynm=wPxZ)`x4$IBR8zpxnYrup29 zBp_4S0%J58XaDaKurfXY{((xsN}c2N@^v0Yr*+)A`RZD}C>8>6T#-_TFH%|~Lm#{s zGPAx~`WD6@yN;?ZtV0;c>mLN_j7__Sy_GxAAGq`w1k!yVjJc3B*(aSF1JX99IGawEP2vVXI}?ZrP3SB<&HV)UkCvld(t2!;l;Wzke}P~6k)L!*##tY@ z@^YL?Dr4uw8mg|j$~kyuO)y$nzTc^;^9j3VB<}-8-3gR#md2=o>;%Cb2<<3~sB7RH z8S@X2InXY}ruw1t(CFf%DzXAQe4r2Mh_zRV`JT4kfc8CXny73om)GeR-$JYUp?+w* zem_K|6FZ|?YD>oWHxxzp`r#Q-LLm-dhRXu4Z#i)po+c*4Kakc6l=cZUWOyx+ZqW8G zh*amPWfZj81(AK|*xk9%zF-md|GJl`_BXXo>?+mm@8+rEEhr9JDkXEStR|l+ZWC~0 zZB&4oNeJ*0w13+G=B!h!5D;%4Rsv$v#c7ZpDL^Vh+av*bQR+oPPPJxkwyyQxnU)(t z>1k3&xg%gwcW>qZMR{2iVO{_~&xWC-^LpjM&^8?4 zomF&@&DiD2<*4{8ySs;>|HTH;l5GRALRh(iRSR4Kld>Q8Ke6e|a|ukGFT5@l9>oKP zEr739&YIe<0i1ocln&tAec;-7vuI-h{2yaf<3cM;6_SfcIm2L%8r&ZZqU^ zm0f4BA!k_fY!E-ewn>qx-mFaf%pyK>|JDSS^QKHP#!3`VcHR=X&HWW|Id4mgHAzlZ z6&)_q55B0&0j7ux)>8iFe(@Iez0OwYf&;3nb98yeUqvu*or(2{u z_S@wyD3(I8Lk_=$S1X%vvw^v7WRq~s&`DJ?&Q3XIP-YyZ+lg7mKc+U!5}}q&@l};u zk)FQTv@>xDTbwg(lI;EZl;+#&5k$s0sg==GI55c-vB) z7}e^aY33BT5A$WAR)D);(>Z2U#^rdA49EEISQ~LNjrHCpeX?jQ0v*P-NjL?Hdm_$< z!V;)rm|MV1?zTy)LiYmD&BBzlF=!=YCuRC>WrNAU;}wpxTgD`0WWA)!zzKeudkzfb zgG=_!Ec7%k%0@SEh@Hiy=M&*LnM`*pP}PyeZCY0?=^#F0Zp0yt_shImvvygFHEw}7z{?C zQlUo_r351T7L-lGWS2(z@`Wqgzc=RAk$k2XxF1Pv=*Ml6iul9y2#RqNdZIrJ(KG1} zcPy(6?*)cYB@Dk0=>#NauY3csNHfi}0XlsoXQ7AX)A%b4pV=h^Nn0fqu}Vh-&69|+ za0aE#Mid$Y^#}6RN^}DzHOP_rA)lLs4=b=3J`g_UZ~>(z8YmxkAO*iX`N9~X|HA%l zq2VK;&ym!};H4*#JLglscC{3o4P4mSD6GA2@Y&H!lhDtVVT^4TRYk}-pR;ahrxo&= zuRP&K!#vHp{q57w{Mz3QhOYfv3mOiyqVYX3(Nb?qNAL|d61ODn^y{kDbt+8+wZ)c#Ke z10>e|Q(*3rf~17n|G`+WwLcEVb?px`&;_;6V$ijJ0mZLdI%6rWm))e!qYW|c+9d_yf}QL> z*%X&dSj`hZX8*(;8VmJC;iT$$46mH#IK(gT#SKVT(=X|1oLGGb@qVa0H{CE>B9PZc zdn!@wsnraM8!7PA>@R#z{a1x&KULE(*q+$!vY)C82hsgh8-pGJnlk-<6`r2j4-D<8 zJ|h!l2v4o3DD>3DplDA$pv=)zUohsnlYAxuZi1(lP4zwXbwfl*^$T}=|1i@|PaO-E z?x%7f8BhJNV1PtVeILwSQjnD3sk@DZi+E}$1ECPq&-PO+2JNXAP<&4%1;0EQXpCIU zQ->RD3Cbn;_e!do>8avD;jZi1U@J{%n{Sfg+bDjwUjAicM{yZ8+#i zlYgtL7(A^eMf{Gnuwi78VcfMbQ0=Z&4B8!N%JfnyJl%CL7}{NZ#u6}4jeCzU5p>rT zplEmfT$!W0&NAkXkbGtnxC!oB8S?_VV_j&7fxAAW4AWgFgQeZ|1xUtSUoIFR(Oq|g zxl0O?65Ms2v2YQ0t!JPM+?BO@NcYw1?3c?q<>x{T$B7C0sF(&KqZT2KEbdT&a#w&(y z1Ufuj{DcX=j%D}TB`Q2!{4>O$uN{6cj3ZF16yg>>;Y zU}zWj8STM}T)dcpE^u)cgLd%?D87r6f?uB0GDa@u;`I%d zk8(-={Z&;>bn(xTZ0+JcBhJOUD;iy#G~?pkjin1*yjD6(pdfsqiw}rPCamU(AG7u4 zu~0*QgCSZyeLP3*?1u~C-;gx#8~;LBKZas2g!c$NozLtpF(%$dNd9C|O$3_vExn8; zZbh0mtHIs7EfvARbc6aO|MnJ`dQkTnSbNo=ZhK3OVz{h+{=hChMmrqX9dD_Tiuw;e zy+YaHz^)Bg$k(M;YwTk6RNi0?E@+Z}Z>ti@dU^subv^lvxHD&1(O6HUVH$wfcnyuE zmat^Ip|ilZ$Y7`n*2`|WDK1&CvS0j|SpIzxg&K{FahwBkhoO%3wPVA`S2v^W>5p87 z!i=tq5*VR&H}Ho#_o$1F2tMVwUl)xqgOsmouBTxxQH9VbfuU+L_ z*Ot$StF2d646H5EOsjIP(J8p#I;T!?wyJ_~!P?s=X~qDPiQj(lV`lALj+Cj|L(4iS zRSZ?vC(8I^`Nw30%`m?n?RXA=gRG8i>wQvVpCZz31?Hmn_PB-N0}s zwGJniFu!tzTEKM-W1i5{KsRFxrj%C5XOdbBi~m*?ug0}#gNJ0Acyr{%(FpPZ=m%{O z-abKx_XO6pg}#CIv_;tA;TF=Y&yN1TmbSflhqU2krvT+b%x#Rq}8L+pEx|n zWX^Kc-nWkle~}0H8Q-%{gBtIP<#$n%{hK9Kj&aI?*vZAxt{^E({#9hH9>s{ z>| zh)`lQor zlKr7Sekson)NYlLICkf(8<#KB;zC3*HcPG3{|APkgFlYB-!0M}+O4t-$AMGl%LABr zUT68pc`4RbjAKUnh5Ui;;1gUklfG7ia;zYVek2>G7t-wMG| zr_fO67-q|1U7zYto2*q~g!rXiGe@PE{YJ@5DDs7m>V95}pyOnsZ%=Jp>qnMA6b++w z1tyt~?fwVSHZ^yD(s2DQ&g~`ND4U$aPvtemHdU%;4G*nP{oKA%LK$Y!b_7os?Qn+3 zlT}%o#XC5v7#i$!*FGpB`Vx(3^!%iSITR{L@ovllh9qC&E8g z(G7+4FQkKV$Z%O?0$E%5*ivznFPEb@Dpl1$ce>n79Z$2E z_`v^pmC2hS)yGMBle93>LAlC=&;^El2UeYK`V9;=o7UR)` z{LiaM_e*EPWb>~KODrQ!)$hj&4IK-ce~UOIPv#ore{25v>hj?klfA46ilyg^Dz$9- z)vNImoOj|1LE?{-5NaJmjF|kCMsPc>7H4FtucMY2%y|0WNG~9d|>m_GZ zeC!sAR7Vs$REhs)IMKr3^hJa$>K?##QBNilWzDtYRZZGjf|}ZQqKdj4^e-rOaY%VJ zcyY=;TqoIaY(>^Grf)|#q)p$hJU3r>{g7o$4_2o4{LNh55B($HY!Y5e6onh-OZJ+8 zn^nYd(yprZE4eG7ck7V*td;me5w|X<6nME~V?d}-?j|V*UAuZ}Xami5smbH3*!A6E z((*kjn=T+NbrFmK!^hUCxF7n1aW92_5khW~ryv!=S#*=|nx+bxTE0wJi>VX8;ELj! z|KKc@;%A@_HzJqs{nJMcBXC=~hS-x)<8=*!_Q>?YyE6|tr?{5qm|!*KJ- z?U1dw`OyEO7`!g>8PO=_N+x&wjn>XUeiX+IM*HKm_Q7~B7qFopIHZNc`hn{#t>Ha!i7 zyXsSw1UBc<2&bF#^@dTfIj;mmH|JeUE>0nI!|{e4rV2lIb(%^Go%~M~f|nDeTLRiI zjSX3~f6#*Vf0sd2`;SBNWQaljxAvbWhfR_AZk00JsaL5Y5~lN2Ni{UgKrxy4C3nzQ zDc863^YtermM^bmTN!p{I+&lFKErC|73?<{lx-1ew@X!+X5kxu{19rW2Rosi zX)084U<`$3!pq;$aAf|*!$fHJCTRp+>a{eQ56xC-g=6W4MvMO`h8x8UK`8s6GRMo_ zfr?METn6An(ReorFgcF6|b0XSOV21D?Rs>aYzII~hX^YS{C zyz{)$Va;Vr^EQfmW*Ml)=u&~VOfROPiZeqDVK@#V=@(=a#=*72-F zJg7o0hUjgouqDbV?W*E`vI;p7@GQzePXzc3TV;jhZP?cfAV@P40qfB5@t3Lgs0)7v z`4l*~HCF&GI8xpx?-_=f2*?*cl{L(yZ?H;Vj_Q*6G*)^m`U*#fJ|iCtugWIjV326O zynPN)L%?E-`Vt#3eRz=&sYLR==&|g|E=;bkYG5fyZj?2fevOrLPyIe zTkP^bfi2zTYl&TcdTYPS_d{hdl{M`(ap zl`9P;Qo61#Z1xBp5|BCuVUIAzAXuJ(9+^MmGHOteCz-}UZh*u2wn565{;%Qgp(()b zNNn8{N(jd%y+c+doUhv}wLcZtv%SBYi?PzGP>Yd*) zIZR@N_$9xtFF)EK1z)Ry9+U^9u4!DGOjNqL9+c{)^i;wyVnw-eI(3_|nvXI_?fbJT z172heV7~M)EQ;$C{>tk=&`SP8|0Hb=Y5H1guc0}`VX4<#Md2{)HBj`mmUF#-t@V}R zW`T=qt-gxPYpsr;m}{*+4QDVp{|Mjzo6V!gG5|{ZBNS7)Wb?Rys zmw9Tj;4!`j8{8m`V=gQ2;9(`8tMKHds{}&ni`J@tv`Y zVHENmz&PWrU}$F?0f{bmyw{mshn^m`ea)=BS)e>cQ9^5q+Ruj z>RstT?b`Vcq$N5~Mtk3Z{7~x<%6Fi09q2&RXa_om<2;#U(vs*v`NEN?j~!8Q<5^pz zlOxeG9T_)Aq9>HZk?77_nPQGaUosX4V+uC;V2KbzaU?pq6GL$%+WR)-KVLW!Jz~g9 z6uD^<$sCE+xt(N=M5A|*%aQ0Y!#z!Iha!s0k?3i~;7HVGWR~Vg^m7$8N21m4q&1F2 zHJ2mNtqpV~v?sUPD~ijJ=#SvSQ+${s(cJ)9g~E~OHzr)%Nc7SyZE8GCP5ISjCO8sJ z@4^z#hqmBIRF51Rns9#i>aK33!gA!;6=C%$dpsnR04Jimn*a{xrrlNZ6q!TU7eUcI zc7Mb08;L&=eMp((MD$sjLk7DVCL76GSW-T!XQB+kMzSLg!Az7vf<|)jiRe5@F-+gB z3XDXDU8zgVPo_T-z2YwBn#p_@60^;b=zPP@Lbj7Xc{rKn%aQ2QU0J@=>XGQ>cl#qz zKZJj>2<@Dw+=U}ihC)Bfk?39Zbuz}ogg+9U2P3$=fX0kO@6jXC-iGUx1vk69N(4uu zUn@SfdL&x+9!eaEj)rtd)|qfcbyQASgw!L^ZNSk2pELx&sQ%waqJ@o1+L7oO9oK%@ zX_^d2qE8`WR&vsu?P?_YnZY;`U28Bk67>s@BhkGEFeA~VIqMMifJ`o7%j2GqD1vo!#)$e z|8&*xhwmUrZ1RRARDgfgkOj@fuNpR*OUS_tvuuSbbY3--=;3#WI}F42H0G+|S}=4^ za~~vT@ioI_=C_!PaOP#d95VtAPVL*w@ob z{-pmVUptne{rUJ&D)hP<+7|B={cL!6A_=E{{*cxVy1=#=UN%Cdr5Zm%Q63O~xLZC> zyI)$Hu84N8F-Y7!tOMd-&-5^$>W2_tCobs5k|5KCGW;_t zIKsP@(84Di5Vbx5_C7VBF0@-rRsC$Vyp@ey_B853xI4}o)Z`&XTh3^8XL?Zj#n&tH zgY@2Js9eHwvu{K-#Nvibq>qoFXpzS_WPBWwCsX1Ol^j^oOG3Vp(oNwtt@s}7BZh?+ zim9J0DxHz+d@Doy-VX-l&*4#D$Z^4q{Z?FbGOs6>0pw?*?EyWaUR17a?E#_}QZ{O& zt!0&GJniu$i(W{1>Amds`FM)Y@Vk91rtA|TjgP31rWYDsK=T(GlETRfKF-tJ#5NeQ zspaEbkogJ-dO>FAUQ8AjWY%u1leLA!GYwR-_$bd(F!a+rpFz@VGOspVzY7U>Jf+gN zcNL!A>`gwO=IIUz7h!ywr%DrT+|z$fxYH)}G|wbO<^w$|A?=cayzT0No+C8GUixkm zufH(UowIlx09~#fO-`K(EZ66Y_~q*M@ypd`Br9{OJl<0IWVw>2%k=`9U#_J1<$9Ni zttDc!<@yo`x?H>6=a;LPG><3o%;PFqEZ3D_=yLrEk}lVb3(EC6#b>!*)7LN8`yiQe zZSY^pb-E(6T-QR{B?Wo9T)(3smTR>F<%$Iq_Vt6V)P8<} zzvvfuMHYCms9)fH!O)KEGvW%oc2VDvNz(;>0nIOPQv3qn;1@VzvjzSs2)e)r^!E$A zr(fVCp7}?`#{z!^3|-(qLed33?1BQ{p!h8CwgdbE9}3A7c$*6fJmImlr@-7L1xX2u zi=QY^)(JlRmdWH6Rip#b{UY51yShkyMqH6jR3%RzCQTRV1vI}%N%4zxn_q#I;)=B9 z{eF?ogrxh1MJCNHNj!6_N*0Usfa3B=zoHNLMf$=8MH*Io7U>|cbl>nKBvYi33yM_t z4X-IOefV=oyQCmb`*5*=%ny9{{Q~8xeR#9*I|v6%Mw1km-ui?}6F-2^fCe_Jha>kH z6PcFwk*$F)pykPrhQXedC)=bskB&?6ga2y4OKtEJv>n~Kk4Nx*l4P>V;5aExGRe9U zG<6ozH@7_ZQ2g}+&VL7Fo}qU2sY6x#!6gC0ci^&#Jn>u8O=zsNiiKWR=oHx$E3&fC z5yKeTFKz5^_U-#g@fW?QASx-f4D~yo>L=wfb8VogDk=UMYCW!cpuG)sg1=5GPCTG# zN+V%aYHZ(T*J)mQqvNo%sq@J#j`Mggp8M;3g=fJY@3ngq#11cr5obwy3~Srk%(xwM zkO&|V50?QE8j18PVRn4;V|jqz$yI`vCsfg;QA__hvgi+B9}1tz_p$MC^wfUG<#Ooc zd#QuJ^XCspcN26!0x&K9n&@4tfAqVQa&W%}bVCm-x+3`!r zxv~C_kWb3OoRE5{-wFA1k2qJa41Y()$4`Zvt5<2c`zPYe?%S+bGQLCg!S_U0*2P_u zQ7oAg@@yC%058YS*qxA;Se*Gp1uZ}FF!a^=0_YR+XewR@R-gP+asqFz2$J`Mq?QzC zZy$WbM~Xu_6`^!5q-RftAPt1HVGgByNROOyAf1J@_crS4UMkMY4+K(kNOSKOr+Eag z&E$wz)!vgsZS6fd)YhIBe^lp{Cu=T%e~44%iL$7$Zbd%`Ieh*-Gh86$*I!d-H;RMv8$Nl(2;bg(=rQ-E!%I!_l>RYXZfpxqrT!XojUH| z7lKHBk!(!Pu->%xXKDP5tC+lej_k*pcx6`GuCf5H!aXH(b(c!TK^IspF(sWH7i$#i)G8;oL(InTp$~ zy0QtLlDMm6GCo>>Ae>>=W`2=*PwR1vPWa%K&pXcC#w_r=F2`Fl=H5w>BNhFzlfhl^ z@}9ZP6<+;1h<8(D>1#Y1UJSVpm%y^gMz}^=BfrYbe;jB2Abe{-c@g?%A{NqeA8`FuRYa8lvxd!p<1jy{FH*qaSNyyvkGd25gl*K74O zta$gVfEn)r>{Glez%1nDVjuQy{}1jSc^g(^orZT3XWlgL>Ss|$-eq7G_DaD*5zob` ztEe{)HlyAj;HP^FfyTU4SkCa40xjm<@*Hltd3*`{C0^0_7^ZteQGg}A-H{s%d zF2Kx)my38W_s%WFg}B!k`zySsk@BjZhjdo+1a_)>onW(ucN=n1)2k1;miOq37!`PT zgP-M1hUQAI0@72*y8(Hr>m5PL>v``XomYA9!a{xTNt8?juNO28Jr~SIUL!CYd*zUl zCSHA{ys5VocA9#H5w@9k9CCB-X{5Y`ciS_#Gv|2i5ZPA8iy*yu=%J99cO0)M{@!)G zaWMa$;}t@x-gmsYOK^9<@ot9g?T)t=5$$liO;GN1yp0I(f#Y>Vx$SbiyHEtX9WMvr z_BdV?%nu!}A&&AL?;0fbBgdP9zrBvf56kXzy!lAoe#a|g5Z^ONR1G$2*O*96?r)<)e=G z94KEoUM~KQIo@XceeHN5B;p&#YYEfeI^L6De&={YQKQFE5;*!EHj%#*j#m}&opijq z2yhBa1pmSD{z8rZ=y>lS_)m^^1xow0sOMi$x(NQO<1Iyj{N{KcAl&bc zcK}6x25CVy|8P8k@=wQWj=#SgZy56Mx8psG!ukh!K(uEauM&#jU&kv0W9J-i6vCZ% zylfQfc=1YuIYGQKD3^)i<>POXc!$Bv7H=HVGFiMAkZ)ocMl?ZLc9{l^jz^S zNAM@bYYOE&@g}1-pAzo~tjrg$5h8k8ynYD2K)fXg@Qir%k+Fs1%|rqhiB}vkJS$!n zfQ!NYWbdM&oF$cn$EkPQ1!6_L6ut zkoTAIB`yS5FWxCc`-*toQPvy8I|`exigybV@fu=BM6Zk28-=_PNkX_c#OsViY!YuL za=RG?iQK*^-unpmmUzFS0lh8WF8pmll28O&#cK|)%M))PvWYk9JcR)7iq{osc~87_ zMD)IRccCD+iFXWXIf+ET^eOQkgUugM$YA~`9=~1vlXweI@~81$9%TAw@m3?iFDQBV z?yv9yWb-%i<|Bc>i+45hcSgLg5&IwFIWYDo`u=gZ;BCEG51_A3eFWm6@b5q1+?qD3 zG(Na_MqMbUJ$Br6!vD-*x1RRMczjUvEahn00i2`5|57fQ_U#b#+vg}}rhSaJZiLTM zz9MpHHaL#(AS?38Wgv+6ReOrXc>9yT11zm4z7=UpMryAb!}u)S^#>oRZ-s%w*bwc;G6$l%kWi@O`A?Kg@18Ep;#SE126T&dk4| z#!|wp!y-HnGucH)K%kbjskC?a+6hGnl_JeIBgu-XxdYhBWb6}pHDfO_67M* zQ!eHt?MCBCTQCs^=~tvJtmwfWztxhqh|$0-no8QUQ%k2*E6=|{r{aX>i1r~ zdR4#r)$jiO>MXw4KANYCv!fs2m0hFX#&#Zg5?>q|eG4EkaxOPp8T}-P$H>$8;+3P{ zrAc1I7x#|-7JdBLeDT2Or?4YOF6N65jb2E-UBVZi9Q{8aS0k75#pgzk(%3HJi!YBJ zBhXyV7vIcmp()W|c=fV!ecsvTn(s!LtyA>TE268>@Tt2;UK%}s7Neg985zN$jp!jW zdVoIua=zFwdLs?^6?`!~I!hp3e^pEqXRaaPIDCq#pe-ex28@W=0wj4Lo!HhiK|e9wU^Ht%qsp zTG4}e_S6SP-Wc6Fg5iFRP~uIz$1|gKn#h~^VtDjPG}X6ot8+&G19WWUtzzxfCFJv{PJ?2yslc`1IMv+Y*^*U?WA^>}`?Z3js3=x6^44_+8; zyAPCm^z&y!)ISt$`y?=S^hf~--`QBIcM~RU&Oy7*Mggk-b_C;BmV(1I(mS94}$=0_}fdte6FMk9Q-xhyI@x| zdg~<^ynysY0@9aImkacJ!^p4GKyRbZ4v(AwT8!RK_eV#5lBUC&*f}Gwr~5CZZ)_X+ z5g^s*%c#xvk=M|>1^RvQ$S1%QM~n3P@{xzImZK&5ebvYx(^xC?d)LSe{a&Ww%#3`D zejlUXM@DX@cbk(0>>tqz%lS@1+s!>*^xwc= z$Om{lwD}hR-0WsLpnJpS4`MPKH~$W%w`ucp@${_BhK~^J-(SVM=;MQbKz;lG$dcLo zQhVJR2d(MNO~dD)DSvIrzQe!#chHb}+BAG4T3tkY#tf`u-lwg@ z{iD@u%*_v*mKX9b`aB*Jj5iIx-87<&C6l2>c=8GS^NhLw3SIhn^ajq8&t#tY2oQbf zdGE#bGhYc{%cEyyp7AdPJ4W2><wS>dm-J>e;3L>Fwy-OT0i@gK7MaAlX*_D*~vtlWBc?Lnr$c3M)WD_`a}9Q zj_~9EqIZ4pDf|MC-~9|VsNjX?QZ{ZxFe&Xc#fPcD0h z^TduTvz-h?(JeIV2eiT28)UB0yPgRX+U3u|I!A}-XZF5N_AaL*;iDH_&6lt23DB6_ z{SttNH2_EtQ*S?XJd=6e7lAmR(Qdzd2|jd3;apVC{uXWzUHSL;dv^BVVfos7F8dp8 z_yAyhDVb8uBaAj0yHxTTueurl|Em|sJD18ondlS0gl>0Shev0(GnvaM9Gw394e2RD zJz*GM58Wnr(bLBJzTbTlrg;@%azk4`T^?tm#mrXpb|D^3p|>5Bv$aUwzD^tdxf$R# z+v8#S#*3nTz>bgUG=`oD&WnyPmFSkt#lNMu3Ck}TCIKG*Z9|&_+~)Ac(QISGE78g3 z>?enMkHBE-333)s&c}N?K<6FPX4Q`8e(O}0f zjpn0V=8}#=lN$Va+(2;JZTKFiVHOBLGeb{(4KMz%Hl#gz@dFAqy2xxf4yr}S!zBHz z%$8N$ye_`p{_|i_(O)g#u7u$Oh5`$0`8S~5)x1l&!E3Q5J3pnp6C^Q|jicwv)TLU) z_H#haqrau@KBo=i?!IKZ;|701-Ths%yG>qqpLrX)`+Mr{n|<9~d7c>^H+W_T-JLZj zgSVr*$m@h7{+cN@L#$bcI?Lf!4^>+UnQJ8tl+)ZGh` z-EH=|TLJTozDM01(uOcK^MBF1uG)slegynI`W`XFp)M{-XpFu`EaO^SKKBO@2&4Z) zl5ZE6&!O4|(GRG%x8iaaZR0mMC+Q6UFy>>+Nh@chlT&^tvYW^>RNx^h=-U)PdZLljF zkR!c3KRKY$=#Nb=d#RU&U@tZ>NP2liax9ypXJTAeGRe)FAffkM)(LiIo`V{^SRqLa zI5T!5;m9RyS$L(sdBsMZ?Ylk)f;`ShbxA~6)xc=SzXTCN-}ob3PcT|t#y#vjiECy+ zm-BT6*ON>x1GFYbImQGp=IK3WN12~H*4$dm!YeliLSzGF_!nJs}BdeT8X`rd6PDRZovOVx#)xFWr`5=vIq2Gk(mS}i>q|I;n`7z zh$Yd=K+Ign#);;CfHB}h+7H}r@{xBfLm(9#{Q%?W|G#$HC4`8WKPPiniXqz|yluhF=eKL1Tb z1o|MpBjfxV9_MT6`h`TWrHB8(^(B8|y1~x=B02zn2OB+1;@7Us#b4E@v@J7Z+X*UP z=dXWLA1F}p^-C^-7Rq1$I)6R7ZHD*p*ZJGg;mqvs5MO>I+J}Z2;tBZAuH3se4Nv3x zax!5>dtQzvo3o!&%sGopWtWo)E82UCpM27L@+{h(H~cg|`H=U7Y+%v82l>eZ?vrcC z!+zE;kdg8la$!%(WxL9j9sRo3pRbn_K8| z6w;weH`jg#%4Rh4eg5e4&70(Rk7ngfBkFDW3A}le^XB)URY#LkxU)I?<>TA&6yH1t z`gnBhG=3rvOuO4%f||3b7*T(uorub}=LXQVEeGf(iPINic{3Nj4SzD%wK1Ea3rU-! zr?jaqBz245dsb%8uS49=vYmp&Tv1Tz`Liv&S8qqN27a7De*LPrn zd2;41{N*P!IP96HM3-#YI+ERT;g;K;_LS(Hr(u8>XGTV@!!2ko`V*twaDFDc<(iRe zN9ML7CUYptZW$S&%Ltd7HrUHCzH!#&XnfI=U@LeM4k?qjW+2gQ#-(;bmuFucU4Mbx z7#rDrL3t~6hVat4trH-y2!y0>Jt=O~+%mT{Zn(vL5Z`{Xdz(6il=x)Ki28cUIr`(= zOS$i@@jRZvAAjmaxIZ&8hQXZ|Pna&xkGrLBm2|XE7N zwxh&@3+0UiBhLU-WSTHt_}!S^pD`N=xCxNYoK;{0SGJl3+DK2f$8XcfU=Y}eWg-AQ zXE;NvwGBU?yA`j?8bkiDZvZv|RCp@TbR#vr)OOFSe_7nPxn=hS^u^2hmIagCe4g8m z20|^bus0bFa`VcoGe8u2U2j4KO|}CYmBoWdt!TE9))E4H+|&SSm)x4TK<1K*U$~xO z3`!lN>h)*^vd?2+?3D!t$Fd!d&_o4)C+$s))!dwNZwfXL12gE)Eot^M_9J$pvvI2! z$*+lTHn+sLuf;k7*+5GW{eh3eBol8<>i;@Ic!BBl7WX&GrbS&G-iv^m%y@775wqww z=%zp$+7$cTSE$WJxOpRP@={Sh=4QUHCFIqc><2~&z2kYjApQ(2=JBhtGw1AU8{>_5 zb37fI=>E73b!)ck0c;RnLTYo+w!!krMz|%uWtQ&N7`X*bhuj;P%!}-$!g1dAf#DJP zS+F;pksPM&MJsgME?zT&+>32PUVR!kjq`TC&6_6%(GmZqncyALg&;P){1S5`e)Xkt zOUSZ(;)m=ltgPI6*@U12!$uI|<>rGt1}UPmPDB2qi;18jn_P9E-P&46Xh&{SbYop$Nn* zpa~%@)54k!$NX!>zK$leCdbc<=*9N4(Y6ymG!z@Exg7z6$E;M(-nI)!2ynu7VQ*(L zCzIO*o(67b$sF~HpflU2vq>_UJLA`h#{Dq2@?NDc|A^fcpxZR1yJA?#W?I#LFmt(a zclB-w7+IGUe-mZPpc#OP3ZQkMaDo~{R?~KQ~QAYZ% zcvKsGvi@%8iSWh@B7-nj-HY=6dkh@0)-eNlpl|*}F@Hu!<*s=K5k+=4ID3Xh`(8YG z!Pe~~GS{C&$~(b>q|N`LPpH+;Maf)>!Y~JZEbFON_6g7&)-(w`qmqm zD?Nn4=C)GTACq5D9X=jC15K&nk&!zXNdGr`)nH;2-Kg3vREL4RV%`$e9pG^Qv2l_{D=Yaa> zylcX{KW0D@z55gQTWI?~^$P@rKeZ5{cRsII^!s7`P4%tqz;n!Dzo>(yW`D+uklV_O z@aKuaQiH!Bd{E53{sLO!FQJveusPriwfalv9#IQf7oF^1@v6u+pmq3bURZkV%TDL? ze}|^oEfW`bNcQ&vW`Ok{ zIpr zo)k0fEk=lYvJv9QqmX%u%V5sM#YP|lZ?~?p}2)X>AA zXU9~Vu~A@MI+hi5CzzOo!1!rIp*bv>aV(921k zgkDa`#+`OQ0A<(d0yCYpf|vg_*cW4v$lkoxy+K=Yw?9(ZS9|PDUO~BeU3{~-g=QtU zukXJN9C$fqHk4U88+NkjKejvxeEW+3U1-)|#byuUy&LDs_t|Dm%unp1C@w z7dx-MT7PA{rll*d+&OXe%+AGHw-bI+In~YV>^4?*-nw`0aHZ3|sa2`MRo!|Guo%tgN=MLVw^R|Wj{KBEV`|>+) z-FJBJi}S&+c{ja_(4?e6y|%b>sZ`o|YG$f1HL;^!YxYj@BU)i@@-Vg6hB=!dF@+b}SYfqZ8d78T9;bG{EtWU34OKLuA*^krEs#=U2gTd zg?6P=>0VtbW#H5TrtN4g9+jp|xavUqFkEC6%dJ`qomGkry5H%Rfg`xTN!}~9n$;aE zXn9B)xC>CB zy#Ty=vMj9unS#^V$x;_HmoE{(7JF45UaPTEubkqa(gFR%yXZ%6mTN8g)#=s?^%?_{ zKUT-sDg;WsTEQ08advAB{t|%!8{g=()^>egDciuyjSxxHuXbg%Xr0i(l~z``l?O|p62Kj=1+cQ&YgF1mTnlpC<6VhQ zgCd#_ffLE<;x-VC<|@BBwI!K@ZLymW z?OyEF>fIeRIhKzRN80nxG3iE7MDEM3E1Yb#2_=Ahf&=of-r7-Vx9uj!HY))WPT?VF z0PQ+#B{OB*5!{ehYvofOg}AX+Tw+>4V?f*aVslCNn7cs=FDTfZ0Kj2twU&;Wf8%9> zQ*EhPtjmXJ7@by|Ac$@;V!JfBY@FJG{YFcViyQNYcEcSk4c_}^Y1w^TTJ|1N zYZs&U(T;i1yn=7BUNOI`{N%uG3L#p8dQUExB$y{&vobpH9_-B@x?%4Dr;lP~Ws&y= ztrl9l4Gy{kqjd%)0F9To4<@(hQg^vc+o#y8)9wOo08=g3%Q0g;-mB@pbI1g?V6DPL zpYTA$vR&W`gbMJ>lN>=bs;11j*y&Vw_X2+!#qKh=SDiL2wmH7tYZ8r-0m4-}Wa{5# z|0kr*p(jK5#7%ReyxiQ1n;V93dl$kV=)dg0XQHRJp97H?4{+YnkU7CU`-#m__BE#; z*{~t|Q>!;`$Y%dF+WnGcT)m2~eh^jp_tkjvgJ^dy``u05kIn6w%f9w>cL>Qg@|DbP z{mN@#vwLVY%6>Z9o&C=0r-w$U1!{B+Z8t6cDihtjVN>?X-RSVc(ePL9o7=O5>pxt5 zc*Dl*ZAa+QcKW4_@arB_LeySNp{p!Xfw$(~akLM(s|c8^Zy zn^81;e)~W>`_HT0b${+3GY@YV%KpLXJ%GZ^_y_Bw|{>-c4gFreW)ZqU%mC}@Uh zfewFq{Xj8idY&Pm904R0D359=1ds=w&+uS?jII38O$QEKW3YvG6QTI49TZ1i{!lgr zLq5$IBG_^d|2{JGRD+YR*qi#D;8sfc#xP+d&=9d4x_5WopdEukWb;vW&+Z-u8EvZa z-*?IuCW>Lshs!=R6m9(iJ$;W*fV1(?6hO)TF3>ca{a=~kYOk~Z_E&>=yyNaqZ#X-< zLZkfOnVWIr?RVcpH>%5D_yX?z=uoxys*f$<&X2EF--sKp-FP!DzIP{q55Kct_~8eC z>GnIgqbhFw9r`#s`}21nxnswk?C7U?ln-tCQTq2jJpPO5L3+H}y`3+v=8H%0`;|k( z=c1FZ-Suf)yklrL|0c5bF8=+MyY%-G9{kl^58}bk@q;hjbp*fvo$26DuF~&sNA&Vf ztkMhr7VW-cC%*CC)#~eT`Fqh3tnb@FEilmN$j8v`Evuj2FmwP=zmK2Y-p#)A?whk; z&2+QZ4_}SjN9m2H(R$aa+5cD_x;z4LoBdHx@M|7GuU}m~l6^yTWKZ_rR)@QwMzrNVh$Nz+ z?3G>oysb;WsJq*C)2}0+!Ot6R#?Rl)bnn3LhcM7{8ES91o0ji;OwaI9?3aIC9o~*x zZytJNc;`~Ncl-W1hQs?oTe8_tX0VTpJ^Z3M1$qF8o;3W356*kOH2{bN>u+Uf!LJ;q-L7z7 z8t@7s#7AxRKq z3=RM;`*Dy(4D;c;hISCS_~=HW2%ka~1p18$Iv2Eq?GvITpS|}f*v^M?uhX%{f| z6QmUTU!27Ls>Obw^J77O0(ken|t^aGQ(fVer5HM?B8eZ&rUp;{o3m8B_;tA*hCw%`-YwurFXE0Ixz3v-1jbe z?)&yV_%`9?o}o*l_}%{RhTb*f-jhD$?7QwB{>t#N?2GQl;9naJ6ZQDs>XG3GmcIS| z?A15_O!iZtU6pHJip6?8fHB1AmCb$`1nBJSx9_@t_$u7nF?@BPgW>b2hZ^-zMGx6u zz5CwZei^>ifv+*ZUi@KSNlxDf_2HnntrvCd@tF zb$$(He=Wj(9f5H6AV%}TAt>lxzvY|^ns9tzx} zGjOkAr|z7Fss9Yj=EnR@3y-g(eYYMwc4t7A{Lk$ux5+fE2UbcfGcrbpabZ_rBCfoLxA@hd)sqPZ4@g}$sjeiNZrz1VGqma9O>YF{=>GW^hpv1o?V{n= z{L=7qhc8;vKi|iX?5UyWL`%cZ#-_SB8g6~#+x&kJ&>or0o<8zV*sKLmj41nTqVWZi zZZ7T)Up#!v@YBBfs?Q8xI<#xs%`<-9(fTuZ(Djyq$=I9T<%pKBuQT9%vFH!cQp(~>7@%x8A-1>*NLzZq~ zX8T??{j%vlqVX=>ksT#*_vh{&x(qQ*Lzg}cT!mh^{r=(O+5N+K)&b~#I(zc|>_zwA zfj#}m*3Qo1qk%v5%U*hAZs!}{nB8`7wt4TLq0>Kwh#X}<6hSV@WKIxw9`A4#+tJ&k#?D?1wW|%!Cq2Zf{d-r{7_)XdKAL-R!(EI51?GwjqOTBkz z7lt3s&XDZ*KkkB%7iIt35J{(hc-Q^-{qdpU-NRqY{?y&~WWSRc8jE&jmxi}@zVPm4 z#wN(HcM(|LFf@GsxA4v*cQK0HH*{q9&wAOX-;+HIF@BQdiL$>wL=gKl_xyQ) z=;JRuv6S6BeB}1*?nin*(aRqA3MoPF0^yIcUyp#tw`acqKAL|S?tUC9PL%!q=%MU? zW*)hKu;I->hwG#4(T6{C-|+eP-+9>)eD3JOU%hYmV*Ky9{^fbYC$sh8BX2qU{8!`o z@K&@Rt^xg5zC-_i>I-lGLiX(Ycj7}ocGq@%=u-@YkHRVgmNj%Fd)bkHJ8;!?yMFjj ze&_>F{kNxnUrgD9UW zh;MJveWN^}jgF}7j;K*=A1f3)g%wy+d)-R8P=*z{1+%@|sW%MFa-!6#cQDd=t97im z!V?+?913K1Cda^u+^jem3f-36B#KH<=*-vVZ&@hJa!bBRZ|lIk&onUGQXL+ad`;jv zCFXt~D2WHJai;$P^C2;pia3p%eLBu2DQzDbP5ucqcN=R)PH3g)+w6t?Z6>-R^p;xwIYI z@4D^RWmY|3ph7ry6d1fEa7>UFgl4f^WYo;j zs<=qo82I}oun}~>0ftnWp_sl=m&15salgf z7_|Av3iF0K6HVS@%C?zX)+y$zzJSU4;eUW~rO& zbmtZ(3&~mIPCiHTmT@R%Q?s#g13jXh9qe@VigPy@?_@!j(t%PLJETZK8wDY6!Zt#< zXSU(~oKP{@jPtzhLz^2UbqY8{yvXM>3^^Iev`bn!lwg*G-a@yyM2kiHOS^Vfvz*V* zbP*I(09DJ+-?WJSas|NuCAUn8!)tCaKPfcHTOUyAS!tjISZ3fXXhGJ0p$p=@0t6ed zQVCp)R~J~3$IN3anHH!U5SgVHaOcJlIt1oa=)kL5p{*|*fG9Q1$h?&h4=l&Xapwj` zo%{?73-gtgA|js%E-nlc`#g=q>zd3ptC_-$P;rXQ5+k%HEX*Rvsm%;U)`{SOwgB3K zY|TkTWPp_dp(hFl@WjE!4lh<>x5p410QL3mk6dpBf=FQzfk|aVfDsrL3dOEWBLq{> zlH9HpiYLRqs3*hTyh*H5tiFh2s#dN{|iaOruHH3@l2Wok`LPL?EhFH-;kg8tS=~|YlRkNhIb}{6et~2jm*(Uq6z?cHq0nuNLmf6kfs6f} z{0hrTy9BidFG-&i?ZKBANV8UF%IgsuuN79o<@c6$^9CNTw}@K`a_9s|gsy4A8}~A~@&5luNZB^f)p#QQ(C_qj;*;=rw4tIVI{h z*qD+ja5u!u5qsS7GCd}6;Ldbxf+MpSSYIKfnVv9bhR&cm;AeyUz+BH+TmU1jNyzPp}|J1fjG zLIf5co(CVIo|G1mBs?iHuTca@)W`0z>R+bZEpYS`Ph8(yBtfybq#H2-C|@9VpcWIr zmEsb(TBcg>7OD-XYP38PF(b{4e0;xxL%QPkrmPIlD3AJ)T z=R+r9d2y^GIoS6gp44C+gD6ENGhsj8S8DmD>dglDq&AU3&5B*ls#WuoO*ZqKV3`HAY`99+Lj!jwZNmLj8&#>vwci6DmEb8Ix_F^Og{c@EpQ9$Zyt=3A?Dv%<`fY zW>!G@7mFn^g~Z=?1v*GIh|wm+rO&(o`JMC!QUtI@9z)2D-C1e33X7);^sj|4(P@zu z#zC45AU&NgHw8aa0fySLC2?YT9TQ`&0)t?$J(0wB$ZU9LO&~^;ml)8hV1(4$anh0l z3dm#|YzLEbcaQ82QRD{6G^*A&02vX(X-mPR)-BfRxk*v?nlS2cI6e#-;Kmivc6h~S z=S|43vCJ}fLrYB7%Os0d8#t(9skL$%1e)Jw?PBIstEGaBRgtPH{WoTwa|Q_?-*_>o6K`*OhT#d90&fc>b5v=8@1Ao*aM-s z?Wr`=z3$q~Hy-D1GW*KcU2=AQ!kU1TsY3RykWN|lM9yQ7Zg~l-Sb7QVyh43n|q1Rz5XQha3a)n~=6x5~x zBuWf)(`&jFAuxm-i3{Tdc%eKwZ(o|}0ik(!C|bdB$tESz`|~m9rzW$70@5lArBkPJ z)|}wjP}Q7+Zh{{t=cZYKtfl(>0 zYr%AAXvn7lsyfb?=s~>%rz&b|H}imo|)NZ=Wi{ zBOt=Oke=jnrHI2iSE&3FM4&2*OWTj;8#Mx?TBJkJff!3xB5{fvWg!Jml{9KMv^fX* z079Q5nq;&!hjhSrVu*z+A_}=S`o#b@?^LPRAd7lTp_z^t7V0r&piGLsYp``n#SW_s z2rbmr$vOFHAnaBM1}W)tSe{tvwyzecjIy9Bg?ewd2s4TZA-%}3B6ru!8_|pLCj?pW z@!4gBxR8$D%pbZ5li~fx9xd~BE(cYJ8o}NUGc^M#)EVuWpobKa3vcZVtOYj2Lwi8P zh3B)dw|$!t8FR@JNdJ@F;K?ny8TLY`Nl7hj!m*9?X&qD^goJaLHqcC&XX~!$H-mHJ zNeK}WK>8}|tS1%Cro&pU$Co^O0v#Ol6+w8u#Y)B+x`ai=G}N1I8ki?y;u)lS_~-=r z-|{t&Mk>f1tb{Zlrhb+^v>Qyb9-%Sngd%Te_?UlImJgJoHN1NBy-9+B*}>352!Z zdu%XDM5Z+BkX0*O8kt!Ya_DJxNvELo2D+H(AT>xWMG576sFAx4Vui}jo>=X_YY`?X zwV0|KLY5p4l*b}F#cHL%LPsiAx}vws&|pl7!Udu+QC0>V*|*C;m$H;cw_u zAOYl4%^cGxCvt7GYtt-aN-!%pCd&RCY2+N8*B4Z=i zFjBU48f^^3)W$8XX}T4@A-i^v;Ts;=GVKxyGplu}4$2}-eXXi3(n8k1V!6U9S7_z1 zH~Xzm1V3lLr*3R4d*A99%IOT-tO?4+E?1xoawrUP0NR*!fEiGX>_Uja zb}ZKsuYn2dTemSa>7Qn-_RVkm6Z(mU33D%O4D zyMP=epecqa^xnp3Q?KQ!s1*50ZoS*0w%K+V~N9&e{0y}s^Xd1_}nJV>>Zjq7-Ad{Jet43W zJGn-8gWu!B*U4B|E!LcUP$6E1i@s_EJ(@HAcAbruS^WesVViyL0A zn~s798#bWc<^<)Yc=S3&Xf8haGu|;5$=nwbY$FeI3WadmWf_olv44%&&&SUVa}}sy zh{7c10@7&QBcAkwhz6vsm}+b`qQNY=Pl2ySQS41p9`~T7}s*tCWV~F1bT= zL7gpjy7HGv2+%=$A0R3+K~#hT(>eLdY?57ZWKc|;Lwx``M*d&`BqDq#PM3=&G$AOS zVORCbARI;HCvQPD86?KJQ=a4)Z(v!AVdYI3E)2(6ZBVPjeM^cGaL7c0q+tX^6BAZ5 z0B@kTaVr$hr0~aLV>jX8b(vbV)oa%fE9}q=Z;a?36jS5pI9BIGriWw&1h*HP%k)}k zApoG*(3n)mWn;u!Vthh{;|ZTrcLhF|o{CtDWl#NP91g=DHf~2>YZUGh zEAM8S9+e11mKg_82GAtRE$?18O zB}p1&K0Nj!#OP?U56CtV49^`bTq%yJF*#z1Ot*3imHR4e1?U3_M6zCIS%DHG`6OdN zA`nSFXBG(~Q;iBJyX~_!z`&59JiYYWZ;rHm}uSZyey^0nP_$tnQ_NInFpBu$=N#6u`_2TH)%q z)KkFv5K~xZ()?9J!D8kJu`&tI$IreeU?gzUZ4Lz-^JG7}p}@RdF&Ul%9;C9mZmS5X zucne}zZPk%oH3dU9(u%a+0%zZX})W43PV&}0RgY{8QW>gTXC8>aBd6?q0&aabDT}G zUX@U7Eh#QflLKs$`JS-2aizwr9b9vb%}Klh?o@TCnoSQ`%w`ZjZv3$!b4Y4T&UFs1 z;QYc~bqTtwvJ7=p2~JX;vkxAXavbZApxam?Q;ml3^n5F<4 z>oQP4+5A#i1X&*4eWFz>UjgP?I5eL>eE5#SO}E{$@9^BMw-f|-E#d@u1lT+rbH^b4 z6}ronCPaZwWp}lRzgKOKfx25WI!NqCng=tuw8xirT zVk(T`xh_RoCNgZyo{I^$`2IA1S&{)7wDAWzNr_8FJytkX*&P;4ny(v;9YZoB@)OHl zfP4D_GR}Cjd8aB@`l(u9xQIURUd7h;cOVlJ&p5q~z(B{N8m2@v^w8&NyCyO@#Im;1 zVrD4F;0fqs(;cpr5AlraTo~)UXt6BrK5mARAe>Jw`X?}D9oqJ-_>`I$B845`yz zs*HXNG&+&n21S4Ux|-Gh!{eGM6_JaA;w3(D_ce#u9FnjC7(mlvhhPJJHGx9uYXM7| zZ>O}n$$-613+9wti6vx`%8B+%{)Z{DAW7Z*7Jk=Hok$29AfdzTM#BgO@WDoi%@02g9=S#N+JR5bOCH9E@F{l%;gPi!*I+VhaqFI+rcy6y79*S z1&SoxnC*3?N{!963mup)SL&3q)M!XDhbw-P2=3B!kK&NUB97zD6=HE1A}!AGNPQ8a zy8|~+LgQ>TllDG?O&Ev|KZwA!4pqzI!Z){8Urg1pQojg#my8-hbsu54ILT$M1ir#i z_>@tC(`{g`fp-VTIYBPxA|hjjIUHVt|IrQl%t8mzdzBTmc(+YOksjO}UePzmwqdC-4Ki5JK!>$}00 z=ZF(ub$T^2B-o|$NJ}GMr#eMEYi&)*38{(Xh>B51yM)r`CKFL8O5E`*-lD279fHQPG*FLni5oyT=+DTQRO(1 zuL90WLury;s+%3ss0X*if``hB5$F}Xr6AtOhSh1uGiLOL1Z2WAA4?>C&X2oLni*7p zeNB@KKyXns%WZTHkVX2OegQ$lOxZ_YE9xd9A6=2!b9{P~;I?eqGN}o{V$w-SPcZd zF&4V~Edy?JW{sm{QaD3BQnf2KxLRrEjCBl;XY6_5U}4Ywk_tyxP6!%Z)0ETnC_9^@ z99lQW6zq#gU|3>T)3;y@_Nrj#oG31DTNuS@yHpf*^TVzfG;IjLv7K&!_JI-GvQ!Yr zi_KQ^bfeYlSX(@OBs5ikHjc#5jQLPItFjW$9uP#1cDY1xXqJS0W*3(xNEY#PxEFXp zUsRUE+CdL|ts)WM7fr^AoKFeiFhx@ir91~h3K1#W>2 z4$5J}6qCj$I;Zna5PKh+bRD4Ng5-Hc)O~#S^F>3ehgJ5{z#K3_Gfc)FqfiBKNJ4@c zIdh??wXw;BX*Di~DRWG4)pa<{a#PTyR4kM5)xkn26K74RU{P|0;bI2x$zx@b-^ z&FHb2#>R1?x9p^K5q?G;<1(T2SPuP$WfeASDz@mFgHW?T_?FM!Tx|7V1F_YyxH{Cs z-!4u87)EcD@s+SwMWz8t2U}qea=tMvLxFPli+=KurHv^jA{4P9GbU*pG+e|ljyokN zwfrPK(vILEC7K75AL{3ehCbM5rBmYGJy;zzQ45Q(8XA{;CM6Cn6kK#>yxk_gEW{4T z0caI6iFB@_1SanmuTa>8>J+1^EFyytQDp@#@$yFNSYUHl|&p9um@_Cc*$`KKWPph=5I5G?sNmo$ZO1wWd znGgjp(+pAvu|_NE#dZx(zDVUHpQqbL2|c_BUyh2~>CF&-KK^lR032yJPS&;3$pMyQP~)#Pa70`Zi6tkqPdz7$9!SCXVr zC3JSU$UOT5;vuKz$L#5o1o4IKnISL=cSABZ8oWJg-0za$6?lieydj_z4G(hGq)k z%EL$?u9PA`++V07zc^%wA5$uwn`TOq6RN7wwC$`psE3u;qZE5awWy7#BCMc`~)gaD>3AULH;N zwx?@sbB&fd4zuXcX1)A*2-|rYM7pXNz&Iej%_uqq(;8;0achR)LoRnKgH`AESNSs` zaFE%~I*gNcLUir7e!l~a+JYpmwzyu(6KlARV{BAm} zjw9?%S!O??(lQRJa%;pY+CcFJ@Z>ZFsKa2%^JWfw63Vw$D7`%`Efh#^A8HtVazSh{0c1Hgh}gM3DM*J{N?Phg2sz%KQ=Ke7Lqw6|Oi$pPk_PLbsatuyvSXauvA2ur zyQRX(R$C2DD#kdlgK#2_8^_BN2a+)z3-Dz}KYomsYudc7MLK1h7-SbJ5DRgx_L9%t zCb&NEe8sBzXyz%;e3}FsxZM1D+9+~woFK_f2}i#~^QKSNBwjMi-0?ZU(n8LNIAgN| zaSM+J%AT3Q&aND%LoYQ>9kqx2;;71C;y5gv#3-zpkBL$fp@FIIfwXgUsm8(t7fXgo z$zUXXBDmECal=RPMH4?9`&nSD*OLSpgdq=}r4e}i zL%@8=r+b0WD8)i&1-tGUB$BEhatfrzreV$;NY`Iw6f<+M-2nn=SAio8W9HHClW;<& z`h%+u(dMCCTAVFF0XkmrvA5XZ;&!nG*2$niE9p}u1<-fY;zeiz_ozDsxrBp+OV=V? z&rj6g-uAHp!VTF;OsZ0-$iyU~B4Fo-SRp=t7TNov^t_p28QkCqgAh(eiHm2TjWxB+ zAso3aKc%n=VF(h~9jQL<%lh-hjvb^m*7(lj z2~g^gVZsi1&ITv|P(83}RXOFCRE5DTHXs!b^a_)ZXcA-+N%+Rj!?|{aTlNZE1D}tL zMJZgB-gLdloc~ovfHKJ zgw9CBPQSukVvBmS=GPv#91NwBDt?oqM&U9xS`GBTO*J*g4#^?L!0L3x5Xx`*nFE8Y z`!FQgd~$mlK|+Rc1P~)8mPyCMnaX4zfT1YU+JMRsZuOJT{t9%$m_G zFeeZrk4<}q!B~Y&HQ8HP5Ddo>Ws0;W;?346O?&`jNXf5(^~e?PQrm&8I^Jg)J27HG zpWL`-Jk3k#{Dc{190oS!lR>NglpN^dpMC`4$=fwn8O4^yk<4C_h&5GDno2T~2d*&Y zopzlt!Zsa3%Tz(x1s~%{>@gv(!LcatEEcMWW}`je#fiC0)E}vW6?$n8XH$ETG~TkK zKt`Vr-Z|KdKImdeBj1=Ku|fEAh(}5Ns-!W8Ms85b5!4{94k!uln!_-Wrq;lrzET*F zMMDhHt#QJ{!!BxWC)!H1~BU>N#YUzLQqhl=v9#c9l=w`9+OYbrV+7Sb);YistXH$>BK01`V;Z{xElNcEac5ZCVQkLeIeg`h()mffw} z4*-(ELp2Arr3X&Pmi^{(UvZJ|`z%z?fg&9Bb3kH2Mde#xZOKuhvHEqYC>hUX9>hQ! zTN8YI$WI<}P9_Z1kzrm5ngmM%Z)9Webs$!ZE0h>0B-Y9}!LYr=#ciT+QW@VM4zoW0 z@uWm{#R2jD%wt&k?oM71GYywSK;KQqWa(M#+S(1Mre4hMaCR(^$Es2Mp~U>x;jPd0 z9Z%-$5$97NK_V0cxyIO}Fjm>@dRm7@QZ0&H7lHvv+itmt0XZD8WiH;r6n94vY+TYZ zdB`_MU0BbIyA1xU)*0-R%5y27BjE;2uv8W*z}jbwP*HX~u?iN--LhtFmjWBs25JZ8 zcYz9r%Sv}-Ipl=ZRZV+)(L6u&6#hj1oC}G?6ek@3+aKQ<#y`iwLZYmc{&4x`_@jYht`g?(%&3t<8fFQyfJNJA87 zkU5rZ{*_ZJjhsurJn0A+noxd1!ytq-XF4a!F#DQ8igm!}`lRUafKmmb+#RwbpFsG- zfse2-#82VKVq$otc!)pQS6%6_IwLM?0aW7kR_IGswh*KOpt0>G~y^L0=g}2@C4gurkEkY;^V~>ZzyqBG52BR4; z%#82`gL~hpPDZQtMn>eCOGl7DiR|$ERf}r#wZ)w%sRRcn6Vtr_(1|1oP9_g zMphQpgcD!;jJ=?BTIiUq<{F1n3uI^=AKy-qn^IRyi9$!%z;I|k6d&$?a9S4vmTZ7u zNVvxH_$+o0%`sn`mPX-{PPu;z;|Yg>hSnM@6I-sxUsXZEdC4)PtJf`M%~Pd?^#-!6 zEAnhFSxt=|z`-5Rk#L+zyHJ9TVHmzSwuy70cvswLDmjK`jy>2f!<*d&HA5Hfp7DEnG#aX7itsy#IdXLXCp=h;^_4wFkw-T8!2xeL4IPo!f!c43- z@*=D1Ul?3@FX1ihS76wcpKhdsoZ+*r(28Li)^Co1YZD5waBQ_SBMG6PVnPRfjRvbW=1;ntVllS4do5*Eb@xzuH7YhlSF^%)U+c0K+XX@q7)C|?x7_? zqj(d!0vwb>ru+B<%S{_a7V0$|%gejtu>^zgi#h^?X@RVHg?apCo+y@3c7`R2p!^8q zi;R`(i}I<{?$CMMwaltGG!N^!kj_F^^Nj;}_BXm{pPOwI+sB9;A}RlLqfzO$Yb6ZA zYJDoPqq3SkH%M}M+$4Tan*?gdrfZ6Ml1Tj+_q|;nGetdeO~C~&5T{`6GDfMytI1<_ zNM{eJK(V&xMFi;iclt$$hy8rhw-Xex0<4^h2+V60LNJK>o`qASRmGrb@-@@>wc_B> z_nno3ebmhmS?N@I5GftYxF2I^Cg(0I^pZgM4K(a3*Y=e{XEsAS)HW%8kuAZx{|T={ z^G;+J86n+?v6Fh&eEjQPDi`MN5EKy*`;#04W)IhJUdOSCv3Tj(mjkx^RGDYJqM~cQ zo0T{>vornW@@&>19ZWx%U>g#K{9PBFo!B0RK-j<*MrLDKOP${1w_8$1sG#`31ChN2 z@FC*H4=Sdl1p2{^BOG>3@q_jZqm)?$j~aj(d*=H`6>vjrL(fG=Y!3u~&%i@@`>^C7 zTtxm#oqQ9>&*G<$-Pom1Vo?SDH!x>X%qWYD4)So(-5Whg?P>&etXx7O27uW(9-IRb z`{@ZBlrg&t%8WFuRCHSJZlP3T@HahN0@nGogS3s6!*c8?Ik$plo0=U+Lkv!>KXE

      gtiD{jK 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

      kL6`s$>*Zg1k+1j<;1dPer+P+i@miKaeo< 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 tH~7cWVz%l=tAv&`M0oOv86eRP7Ms26eLnl>5 Date: Sat, 19 Dec 2015 16:44:03 +0100 Subject: [PATCH 034/263] added lowlatency (SCHED_DEADLINE) option in toplevel build script --- cmake_targets/CMakeLists.txt | 7 ++++--- cmake_targets/build_oai | 9 +++++++++ 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/cmake_targets/CMakeLists.txt b/cmake_targets/CMakeLists.txt index d7a656e61c..33867b6723 100644 --- a/cmake_targets/CMakeLists.txt +++ b/cmake_targets/CMakeLists.txt @@ -421,7 +421,7 @@ elseif (${RF_BOARD} STREQUAL "OAI_USRP") ${OPENAIR_TARGETS}/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp) LINK_DIRECTORIES("/opt/lib") set(option_HW_lib "uhd") - set(LOWLATENCY False) + #set(LOWLATENCY False) elseif (${RF_BOARD} STREQUAL "OAI_BLADERF") include_directories("${OPENAIR_TARGETS}/ARCH/BLADERF/USERSPACE/LIB/") @@ -432,14 +432,14 @@ elseif (${RF_BOARD} STREQUAL "OAI_BLADERF") ) LINK_DIRECTORIES("/usr/lib/x86_64-linux-gnu") set(option_HW_lib "bladeRF") -#set(LOWLATENCY False) + #set(LOWLATENCY False) elseif (${RF_BOARD} STREQUAL "ETHERNET") include_directories ("${OPENAIR_TARGETS}/ARCH/ETHERNET/USERSPACE/LIB") set(HW_SOURCE ${HW_SOURCE} ${OPENAIR_TARGETS}/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c ) - set(LOWLATENCY True) + #set(LOWLATENCY True) elseif (${RF_BOARD} STREQUAL "CPRIGW") set(HW_SOURCE ${HW_SOURCE} @@ -451,6 +451,7 @@ endif (${RF_BOARD} STREQUAL "EXMIMO") include_directories ("${OPENAIR_TARGETS}/ARCH/COMMON") +Message("LOWLATENCY flag is ${LOWLATENCY}") ############################################################## # ???!!! TO BE DOCUMENTED OPTIONS !!!??? diff --git a/cmake_targets/build_oai b/cmake_targets/build_oai index 25bec96b98..165a2c6b0c 100755 --- a/cmake_targets/build_oai +++ b/cmake_targets/build_oai @@ -45,6 +45,7 @@ MSC_GEN="False" XFORMS="False" PRINT_STATS="False" VCD_TIMING="False" +LOWLATENCY_FLAG_USER="True" REL="Rel10" HW="EXMIMO" NOS1=0 @@ -113,6 +114,8 @@ Options Shows detailed compilation instructions in makefile --cflags_processor Manually Add CFLAGS of processor if they are not detected correctly by script. Only add these flags if you know your processor supports them. Example flags: -msse3 -msse4.1 -msse4.2 -mavx2 +--disable-deadline + Disables deadline scheduler of Linux kernel (>=3.14.x). The deadline scheduler is enabled by default Usage (first build): oaisim (eNB + UE): ./build_oai -I -g --oaisim -x --install-system-files @@ -225,6 +228,10 @@ function main() { CFLAGS_PROCESSOR_USER=$2 echo_info "setting CPU FLAGS from USER to: $CFLAGS_PROCESSOR_USER" shift 2;; + --disable-deadline) + LOWLATENCY_FLAG_USER="False" + echo_info "Disabling the usage of deadline scheduler" + shift 1;; -h | --help) print_help exit 1;; @@ -321,6 +328,7 @@ function main() { echo "set ( ENABLE_VCD_FIFO $VCD_TIMING )" >> $cmake_file echo "set ( RF_BOARD \"${HW}\")" >> $cmake_file echo "set(PACKAGE_NAME \"${lte_exec}\")" >> $cmake_file + echo "set (LOWLATENCY \"${LOWLATENCY_FLAG_USER}\" )" >>$cmake_file echo 'include(${CMAKE_CURRENT_SOURCE_DIR}/../CMakeLists.txt)' >> $cmake_file cd $DIR/$lte_build_dir/build cmake .. @@ -539,6 +547,7 @@ function main() { echo "set(ENABLE_ITTI False )" >> $cmake_file echo "set(RF_BOARD \"${HW}\")" >> $cmake_file echo 'set(PACKAGE_NAME "\"rrh_gw\"")' >> $cmake_file + echo "set(LOWLATENCY \"${LOWLATENCY_FLAG_USER}\")" >>$cmake_file echo 'include(${CMAKE_CURRENT_SOURCE_DIR}/../CMakeLists.txt)' >> $cmake_file [ "$CLEAN" = "1" ] && rm -rf $DIR/rrh_gw/build From fd880b0374627653c5942329e84c557f12bd3974 Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Sat, 19 Dec 2015 16:45:16 +0100 Subject: [PATCH 035/263] changed exmimo stop script and reduced UL throughput requirements for test cases to pass --- cmake_targets/autotests/test_case_list.xml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/cmake_targets/autotests/test_case_list.xml b/cmake_targets/autotests/test_case_list.xml index ba34085d90..46763b52c2 100644 --- a/cmake_targets/autotests/test_case_list.xml +++ b/cmake_targets/autotests/test_case_list.xml @@ -8,7 +8,7 @@ feature-17-test_framework oaisim* oaisim_nos1* lte-softmodem* lte-softmodem-nos1* mme_gw* run_epc* run_hss* iperf* hss hss_sim configure_cots_bandrich_ue* wvdial* run_exec_autotests* iperf /opt/ltebox/tools/stop_ltebox -cd $OPENAIR_DIR/cmake_targets/autotests/tools/exmimo; sudo -E -S octave ./exmimo_stop.m +$OPENAIR_DIR/cmake_targets/build_oai -w EXMIMO -c; sudo -S -E $OPENAIR_DIR/cmake_targets/tools/init_exmimo2 ; cd $OPENAIR_DIR/targets/bin; sudo -E -S octave $OPENAIR_DIR/cmake_targets/tools/exmimo_stop.m ; cd - 36000 0104+ 015502 015505 015506 015507 015508 015508 015509 015510 015511 015600 015700 016102 016105 calisson stevens mozart nano amerique @@ -1012,7 +1012,7 @@ sleep 5; iperf -s -i 1 -u -f m -B 192.172.0.1 - throughput_test min=2.0Mbits/sec max=2.0Mbits/sec average=2.0Mbits/sec duration=300.0s + throughput_test min=1.0Mbits/sec max=1.0Mbits/sec average=1.0Mbits/sec duration=300.0s True USRPb210.ALU_EPC.Bandrich.10MHz.FDD.Band_7.UL.1TX.1RX @@ -1095,7 +1095,7 @@ sleep 5; iperf -s -i 1 -u -f m -B 192.172.0.1 - throughput_test min=4.0Mbits/sec max=4.0Mbits/sec average=4.0Mbits/sec duration=300.0s + throughput_test min=1.0Mbits/sec max=1.0Mbits/sec average=1.0Mbits/sec duration=300.0s True USRPb210.ALU_EPC.Bandrich.20MHz.FDD.Band_7.UL.1TX.1RX @@ -2001,7 +2001,7 @@ sleep 5; iperf -s -i 1 -u -f m -B 192.172.0.1 - throughput_test min=2.0Mbits/sec max=2.0Mbits/sec average=2.0Mbits/sec duration=300.0s + throughput_test min=1.0Mbits/sec max=1.0Mbits/sec average=1.0Mbits/sec duration=300.0s True USRPx310.ALU_EPC.Bandrich.10MHz.FDD.Band_7.UL.1TX.1RX @@ -2079,7 +2079,7 @@ sleep 5; iperf -s -i 1 -u -f m -B 192.172.0.1 - throughput_test min=4.0Mbits/sec max=4.0Mbits/sec average=4.0Mbits/sec duration=300.0s + throughput_test min=1.0Mbits/sec max=1.0Mbits/sec average=1.0Mbits/sec duration=300.0s True USRPx310.ALU_EPC.Bandrich.20MHz.FDD.Band_7.UL.1TX.1RX @@ -2470,7 +2470,7 @@ sleep 5; iperf -s -i 1 -u -f m -B 192.172.0.1 - throughput_test min=2.0Mbits/sec max=2.0Mbits/sec average=2.0Mbits/sec duration=300.0s + throughput_test min=1.0Mbits/sec max=1.0Mbits/sec average=1.0Mbits/sec duration=300.0s True EXMIMO.ALU_EPC.Bandrich.10MHz.FDD.Band_7.UL.1TX.1RX @@ -2548,7 +2548,7 @@ sleep 5; iperf -s -i 1 -u -f m -B 192.172.0.1 - throughput_test min=4.0Mbits/sec max=4.0Mbits/sec average=4.0Mbits/sec duration=300.0s + throughput_test min=1.0Mbits/sec max=1.0Mbits/sec average=1.0Mbits/sec duration=300.0s True EXMIMO.ALU_EPC.Bandrich.20MHz.FDD.Band_7.UL.1TX.1RX From 3602808af2c698e28ca3862b52a4e2813b973451 Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Sat, 19 Dec 2015 18:54:21 +0100 Subject: [PATCH 036/263] updated for checking Git head versions of OAI 5G repo --- .../autotests/run_exec_lte-softmodem_tests.py | 20 ++++++++++++++++--- cmake_targets/autotests/test_case_list.xml | 2 +- 2 files changed, 18 insertions(+), 4 deletions(-) diff --git a/cmake_targets/autotests/run_exec_lte-softmodem_tests.py b/cmake_targets/autotests/run_exec_lte-softmodem_tests.py index b76b5f9698..c03cad27c7 100644 --- a/cmake_targets/autotests/run_exec_lte-softmodem_tests.py +++ b/cmake_targets/autotests/run_exec_lte-softmodem_tests.py @@ -869,8 +869,10 @@ def search_test_case_group(testcasename, testcasegroup, test_case_exclude): if match >=0: return True return False - - + +def cleanOldProgramsAllMachines(oai_list, CleanOldProgs, CleanUpAluLteBox, ExmimoRfStop): + for index in oai_list: + cleanOldPrograms(oai_list[index], CleanUpOldProgs, CleanUpAluLteBox, ExmimoRfStop) #thread1 = myThread(1, "Thread-1", 1) debug = 0 @@ -884,7 +886,7 @@ xmlInputFile="./test_case_list.xml" NFSResultsDir = '/mnt/sradio' cleanupOldProgramsScript = '$OPENAIR_DIR/cmake_targets/autotests/tools/remove_old_programs.bash' testcasegroup='' - +cleanUpRemoteMachines=False logdir = '/tmp/' + 'OAITestFrameWork-' + getpass.getuser() + '/' logdirOAI5GRepo = logdir + 'openairinterface5g/' logdirOpenaircnRepo = logdir + 'openair-cn/' @@ -924,12 +926,15 @@ while i < len (sys.argv): elif arg == '-g' : testcasegroup = sys.argv[i+1].replace("\"","") i = i +1 + elif arg == '-c': + cleanUpRemoteMachines=True elif arg == '-h' : print "-d: low debug level" print "-dd: high debug level" print "-p: set the prompt" print "-r: Remove the log directory in autotests" print "-g: Run test cases in a group" + print "-c: Run cleanup scripts on remote machines" print "-w: set the password for ssh to localhost" print "-l: use local shell instead of ssh connection" print "-t: set the time out in second for commands" @@ -1131,7 +1136,12 @@ for index in oai_list: cmd = cmd + 'git clone '+ GitOAI5GRepo + '\n' cmd = cmd + 'git clone '+ GitOpenaircnRepo + '\n' cmd = cmd + 'cd ' + logdirOAI5GRepo + '\n' + cmd = cmd + 'git checkout ' + GitOAI5GRepoBranch + '\n' cmd = cmd + 'git checkout ' + GitOAI5GHeadVersion + '\n' + cmd = cmd + 'git_head = `git ls-remote |grep \"' + GitOAI5GRepoBranch + '\"' + cmd = cmd + 'git_head = ($git_head)' + cmd = cmd + 'git_head = ${git_head[0]}' + cmd = cmd + 'if [ \"$git_head\" != \"'+ GitOAI5GHeadVersion + '\" ]; then echo \"error: Git openairinterface5g head version does not match\" ; fi ' cmd = cmd + 'source oaienv' + '\n' cmd = cmd + 'cd ' + logdirOpenaircnRepo + '\n' cmd = cmd + 'git checkout ' + GitOpenaircnRepoBranch + '\n' @@ -1220,6 +1230,9 @@ if (out != '') : print "status = " + str(status) + "\n Check files for error = " + out print sys.exit(1) +if cleanUpRemoteMachines == True: + cleanOldProgramsAllMachines(oai_list, CleanOldProgs, CleanUpAluLteBox, ExmimoRfStop) + sys.exit(0) threadListGlobal=[] testcaseList=xmlRoot.findall('testCase') @@ -1231,6 +1244,7 @@ for testcase in testcaseList: desc = testcase.findtext('desc',default='') #print "Machine list top level = " + ','.join(MachineList) if search_test_case_group(testcasename, testcasegroup, TestCaseExclusionList) == True: + cleanOldProgramsAllMachines(oai_list, CleanOldProgs, CleanUpAluLteBox, ExmimoRfStop) if testcaseclass == 'lte-softmodem' : eNBMachine = testcase.findtext('eNB',default='') UEMachine = testcase.findtext('UE',default='') diff --git a/cmake_targets/autotests/test_case_list.xml b/cmake_targets/autotests/test_case_list.xml index 46763b52c2..dca1fce20f 100644 --- a/cmake_targets/autotests/test_case_list.xml +++ b/cmake_targets/autotests/test_case_list.xml @@ -8,7 +8,7 @@ feature-17-test_framework oaisim* oaisim_nos1* lte-softmodem* lte-softmodem-nos1* mme_gw* run_epc* run_hss* iperf* hss hss_sim configure_cots_bandrich_ue* wvdial* run_exec_autotests* iperf /opt/ltebox/tools/stop_ltebox -$OPENAIR_DIR/cmake_targets/build_oai -w EXMIMO -c; sudo -S -E $OPENAIR_DIR/cmake_targets/tools/init_exmimo2 ; cd $OPENAIR_DIR/targets/bin; sudo -E -S octave $OPENAIR_DIR/cmake_targets/tools/exmimo_stop.m ; cd - +$OPENAIR_DIR/cmake_targets/build_oai -w EXMIMO -c; sudo -S -E $OPENAIR_DIR/cmake_targets/tools/stop_exmimo2 36000 0104+ 015502 015505 015506 015507 015508 015508 015509 015510 015511 015600 015700 016102 016105 calisson stevens mozart nano amerique From cf8645d8cd7c2632dfd3c09f9f059f7ed64622af Mon Sep 17 00:00:00 2001 From: gauthier Date: Mon, 21 Dec 2015 19:05:28 +0100 Subject: [PATCH 037/263] Limitation of non SI DLSCH allocations in subframe 0/5 to PRBS not around DC (avoid puncturing from PBCH). Placement of SI around DC instead of randomized allocations. Placement of RA allocations at PRB 0-3. Tested DL throughput on 5 MHz to 16 Mbit/s in TM1. --- openair1/PHY/impl_defs_top.h | 2 +- openair2/LAYER2/MAC/eNB_scheduler.c | 16 +++---- openair2/LAYER2/MAC/eNB_scheduler_RA.c | 9 +++- openair2/LAYER2/MAC/eNB_scheduler_bch.c | 20 +++++++++ .../LAYER2/MAC/eNB_scheduler_primitives.c | 6 ++- openair2/LAYER2/MAC/pre_processor.c | 43 +++++++++++++++++-- 6 files changed, 81 insertions(+), 15 deletions(-) diff --git a/openair1/PHY/impl_defs_top.h b/openair1/PHY/impl_defs_top.h index d702754077..a6298ae5a1 100755 --- a/openair1/PHY/impl_defs_top.h +++ b/openair1/PHY/impl_defs_top.h @@ -257,7 +257,7 @@ #define AMP_OVER_2 (AMP>>1) /// Threshold for PUCCH Format 1 detection -#define PUCCH1_THRES 4 +#define PUCCH1_THRES 10 /// Threshold for PUCCH Format 1a/1b detection #define PUCCH1a_THRES 4 diff --git a/openair2/LAYER2/MAC/eNB_scheduler.c b/openair2/LAYER2/MAC/eNB_scheduler.c index 8a6b8d66c7..21e9337dbb 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler.c +++ b/openair2/LAYER2/MAC/eNB_scheduler.c @@ -280,7 +280,7 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag, } } else { //FDD schedule_ulsch(module_idP,frameP,cooperation_flag,1,5); - // schedule_ue_spec(module_idP,frameP,subframeP,mbsfn_status); + schedule_ue_spec(module_idP,frameP,subframeP,mbsfn_status); fill_DLSCH_dci(module_idP,frameP,subframeP,mbsfn_status); } @@ -292,7 +292,7 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag, // FDD, normal UL/DLSCH if (mac_xface->lte_frame_parms->frame_type == FDD) { //FDD schedule_ulsch(module_idP,frameP,cooperation_flag,2,6); - // schedule_ue_spec(module_idP,frameP,subframeP,mbsfn_status); + schedule_ue_spec(module_idP,frameP,subframeP,mbsfn_status); fill_DLSCH_dci(module_idP,frameP,subframeP,mbsfn_status); } @@ -320,7 +320,7 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag, } else { //FDD schedule_ulsch(module_idP,frameP,cooperation_flag,3,7); - // schedule_ue_spec(module_idP,frameP,subframeP,mbsfn_status); + schedule_ue_spec(module_idP,frameP,subframeP,mbsfn_status); fill_DLSCH_dci(module_idP,frameP,subframeP,mbsfn_status); } @@ -358,7 +358,7 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag, // schedule_RA(module_idP,frameP, subframeP, 0); schedule_ulsch(module_idP, frameP, cooperation_flag, 4, 8); - // schedule_ue_spec(module_idP, frameP, subframeP, mbsfn_status); + schedule_ue_spec(module_idP, frameP, subframeP, mbsfn_status); fill_DLSCH_dci(module_idP, frameP, subframeP, mbsfn_status); } } @@ -428,7 +428,7 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag, } } else { //FDD // schedule_ulsch(module_idP,frameP,cooperation_flag,6,0); - // schedule_ue_spec(module_idP,frameP,subframeP,mbsfn_status); + schedule_ue_spec(module_idP,frameP,subframeP,mbsfn_status); fill_DLSCH_dci(module_idP,frameP,subframeP,mbsfn_status); } @@ -457,7 +457,7 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag, } } else { //FDD //schedule_ulsch(module_idP,frameP,cooperation_flag,7,1); - // schedule_ue_spec(module_idP,frameP,subframeP,mbsfn_status); + schedule_ue_spec(module_idP,frameP,subframeP,mbsfn_status); fill_DLSCH_dci(module_idP,frameP,subframeP,mbsfn_status); } @@ -486,7 +486,7 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag, } } else { //FDD //schedule_ulsch(module_idP,frameP,cooperation_flag,8,2); - // schedule_ue_spec(module_idP,frameP,subframeP,mbsfn_status); + schedule_ue_spec(module_idP,frameP,subframeP,mbsfn_status); fill_DLSCH_dci(module_idP,frameP,subframeP,mbsfn_status); } @@ -530,7 +530,7 @@ void eNB_dlsch_ulsch_scheduler(module_id_t module_idP,uint8_t cooperation_flag, } } else { //FDD // schedule_ulsch(module_idP,frameP,cooperation_flag,9,3); - // schedule_ue_spec(module_idP,frameP,subframeP,mbsfn_status); + schedule_ue_spec(module_idP,frameP,subframeP,mbsfn_status); fill_DLSCH_dci(module_idP,frameP,subframeP,mbsfn_status); } diff --git a/openair2/LAYER2/MAC/eNB_scheduler_RA.c b/openair2/LAYER2/MAC/eNB_scheduler_RA.c index 524268665b..8cb6b91301 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_RA.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_RA.c @@ -302,6 +302,7 @@ void schedule_RA(module_id_t module_idP,frame_t frameP, sub_frame_t subframeP,un // msg("[MAC][eNB] Frame %d, subframeP %d: Generated DLSCH (Msg4) DCI, format 1A, for UE %d\n",frameP, subframeP,UE_id); // Schedule Reflection of Connection request + /* // randomize frequency allocation for RA while (1) { first_rb = (unsigned char)(taus()%(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL-4)); @@ -309,7 +310,9 @@ void schedule_RA(module_id_t module_idP,frame_t frameP, sub_frame_t subframeP,un if ((vrb_map[first_rb] != 1) && (vrb_map[first_rb+3] != 1)) break; } - + */ + first_rb=0; + vrb_map[first_rb] = 1; vrb_map[first_rb+1] = 1; vrb_map[first_rb+2] = 1; @@ -669,6 +672,7 @@ void schedule_RA(module_id_t module_idP,frame_t frameP, sub_frame_t subframeP,un ((DCI1A_5MHz_FDD_t*)&RA_template->RA_alloc_pdu2[0])->ndi=1; } + /* // randomize frequency allocation for RA while (1) { first_rb = (unsigned char)(taus()%(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL-4)); @@ -676,7 +680,8 @@ void schedule_RA(module_id_t module_idP,frame_t frameP, sub_frame_t subframeP,un if ((vrb_map[first_rb] != 1) && (vrb_map[first_rb+3] != 1)) break; } - + */ + first_rb=0; vrb_map[first_rb] = 1; vrb_map[first_rb+1] = 1; vrb_map[first_rb+2] = 1; diff --git a/openair2/LAYER2/MAC/eNB_scheduler_bch.c b/openair2/LAYER2/MAC/eNB_scheduler_bch.c index b9a310c30c..65240356a7 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_bch.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_bch.c @@ -111,6 +111,7 @@ schedule_SI( LOG_D(MAC,"[eNB %d] Frame %d : BCCH->DLSCH CC_id %d, Received %d bytes \n",module_idP,frameP,CC_id,bcch_sdu_length); // Allocate 4 PRBs in a random location + /* while (1) { first_rb = (unsigned char)(taus()%(PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL-4)); if ((vrb_map[first_rb] != 1) && @@ -119,6 +120,25 @@ schedule_SI( (vrb_map[first_rb+3] != 1)) break; } + */ + switch (PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL) { + case 6: + first_rb = 0; + break; + case 15: + first_rb = 6; + break; + case 25: + first_rb = 11; + break; + case 50: + first_rb = 23; + break; + case 100: + first_rb = 48; + break; + } + vrb_map[first_rb] = 1; vrb_map[first_rb+1] = 1; vrb_map[first_rb+2] = 1; diff --git a/openair2/LAYER2/MAC/eNB_scheduler_primitives.c b/openair2/LAYER2/MAC/eNB_scheduler_primitives.c index 8880a85c2e..3a5b1b5c61 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_primitives.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_primitives.c @@ -1041,8 +1041,12 @@ int allocate_CCEs(int module_idP, } } // fCCE>=0 else { - if (DCI_pdu->num_pdcch_symbols == 3) + if (DCI_pdu->num_pdcch_symbols == 3) { allocation_is_feasible = 0; + LOG_I(MAC,"subframe %d: Dropping Allocation for RNTI %x\n", + subframeP,dci_alloc->rnti); + + } else { DCI_pdu->num_pdcch_symbols++; nCCE_max = mac_xface->get_nCCE_max(module_idP,CC_idP,DCI_pdu->num_pdcch_symbols,subframeP); diff --git a/openair2/LAYER2/MAC/pre_processor.c b/openair2/LAYER2/MAC/pre_processor.c index d4d94de832..86058fb7ce 100644 --- a/openair2/LAYER2/MAC/pre_processor.c +++ b/openair2/LAYER2/MAC/pre_processor.c @@ -176,6 +176,7 @@ void assign_rbs_required (module_id_t Mod_id, eNB_UE_stats[CC_id]->DL_cqi[0], MIN_CQI_VALUE, MAX_CQI_VALUE); */ eNB_UE_stats[CC_id]->dlsch_mcs1=cqi_to_mcs[eNB_UE_stats[CC_id]->DL_cqi[0]]; + eNB_UE_stats[CC_id]->dlsch_mcs1 = cmin(eNB_UE_stats[CC_id]->dlsch_mcs1,openair_daq_vars.target_ue_dl_mcs); } @@ -729,6 +730,7 @@ void dlsch_scheduler_pre_processor (module_id_t Mod_id, } } +#define SF05_LIMIT 1 void dlsch_scheduler_pre_processor_reset (int module_idP, int UE_id, @@ -748,8 +750,10 @@ void dlsch_scheduler_pre_processor_reset (int module_idP, rnti_t rnti = UE_RNTI(module_idP,UE_id); uint8_t *vrb_map = &eNB_mac_inst[module_idP].common_channels[CC_id].vrb_map; int RBGsize = PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL/N_RBG; - - +#ifdef SF05_LIMIT + int subframe05_limit=0; + int sf05_upper=-1,sf05_lower=-1; +#endif // initialize harq_pid and round mac_xface->get_ue_active_harq_pid(module_idP,CC_id,rnti, frameP,subframeP, @@ -762,13 +766,46 @@ void dlsch_scheduler_pre_processor_reset (int module_idP, ue_sched_ctl->dl_pow_off[CC_id] = 2; nb_rbs_required_remaining[CC_id][UE_id] = 0; +#ifdef SF05_LIMIT + switch (N_RBG) { + case 6: + sf05_lower=0; + sf05_upper=5; + break; + case 8: + sf05_lower=2; + sf05_upper=5; + break; + case 13: + sf05_lower=4; + sf05_upper=7; + break; + case 17: + sf05_lower=7; + sf05_upper=9; + break; + case 25: + sf05_lower=11; + sf05_upper=13; + break; + } +#endif // Initialize Subbands according to VRB map for (i=0; irballoc_sub_UE[CC_id][i] = 0; rballoc_sub[CC_id][i] = 0; +#ifdef SF05_LIMIT + // for avoiding 6+ PRBs around DC in subframe 0-5 (avoid excessive errors) + + if ((subframeP==0 || subframeP==5) && + (i>=sf05_lower && i<=sf05_upper)) + rballoc_sub[CC_id][i]=1; +#endif + // for SI-RNTI,RA-RNTI and P-RNTI allocations for (j=0;j Date: Tue, 22 Dec 2015 21:12:12 +0100 Subject: [PATCH 038/263] initialization in oaisim --- cmake_targets/build_oai | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/cmake_targets/build_oai b/cmake_targets/build_oai index ab1e84dfe9..3fb0f07499 100755 --- a/cmake_targets/build_oai +++ b/cmake_targets/build_oai @@ -276,12 +276,10 @@ function main() { fi if [ "$oaisim" = "1" ] ; then - # if [ "$HW" == "ETHERNET" ] ; then # to ask - # HW="NONE" - #fi - if [ $HW != "EXMIMO" -a $HW != "OAI_USRP" -a $HW != "OAI_BLADERF" ] ; then - HW="NO_VALUE" - fi + # there is no RF device and no transport protocol + HW="NO_VALUE" + TP="NO_VALUE" + if [ "$XFORMS" == "True" ] ; then PRINT_STATS="True" fi From 6975efd67aae911bb5d3c8ae719f753ff53dcf34 Mon Sep 17 00:00:00 2001 From: "aikaterini.trilyraki" Date: Tue, 22 Dec 2015 21:13:37 +0100 Subject: [PATCH 039/263] remove redundant returns --- targets/ARCH/COMMON/common_lib.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/targets/ARCH/COMMON/common_lib.c b/targets/ARCH/COMMON/common_lib.c index a9d6daa954..6d98aeed26 100644 --- a/targets/ARCH/COMMON/common_lib.c +++ b/targets/ARCH/COMMON/common_lib.c @@ -55,26 +55,21 @@ int set_device(openair0_device *device) { case EXMIMO_DEV: printf("[%s] has loaded EXPRESS MIMO device.\n",((device->host_type == BBU_HOST) ? "BBU": "RRH")); - return 0; break; case USRP_DEV: printf("[%s] has loaded USRP device.\n",((device->host_type == BBU_HOST) ? "BBU": "RRH")); - return 0; break; case BLADERF_DEV: printf("[%s] has loaded BLADERF device.\n",((device->host_type == BBU_HOST) ? "BBU": "RRH")); - return 0; break; case NONE_DEV: printf("[%s] has not loaded a HW device.\n",((device->host_type == BBU_HOST) ? "BBU": "RRH")); - return 0; break; default: printf("[%s] invalid HW device.\n",((device->host_type == BBU_HOST) ? "BBU": "RRH")); return -1; - break; } - + return 0; } int set_transport(openair0_device *device) { From d5a96b2c61cf845b620d4a3c0213dc1b364cfedf Mon Sep 17 00:00:00 2001 From: "aikaterini.trilyraki" Date: Tue, 22 Dec 2015 21:15:52 +0100 Subject: [PATCH 040/263] comment address restore --- targets/ARCH/ETHERNET/USERSPACE/LIB/eth_udp.c | 25 +++++++------------ 1 file changed, 9 insertions(+), 16 deletions(-) diff --git a/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_udp.c b/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_udp.c index fe4d4db0db..393c82d900 100644 --- a/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_udp.c +++ b/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_udp.c @@ -318,7 +318,7 @@ int eth_set_dev_conf_udp(openair0_device *device) { /* a BBU client sents to RRH a set of configuration parameters (openair0_config_t) so that RF front end is configured appropriately and frame/packet size etc. can be set */ - + msg=malloc(sizeof(openair0_config_t)); msg_len=sizeof(openair0_config_t); memcpy(msg,(void*)&device->openair0_cfg,msg_len); @@ -328,8 +328,6 @@ int eth_set_dev_conf_udp(openair0_device *device) { exit(0); } - /* printf("[RRHbbb] mod_%d socket %d connected to BBU %s:%d\n", Mod_id, eth->sockfd[Mod_id], inet_ntoa(dest_addr[Mod_id].sin_addr), */ - /* ntohs(dest_addr[Mod_id].sin_port)); */ return 0; } @@ -347,10 +345,6 @@ int eth_get_dev_conf_udp(openair0_device *device) { inet_ntop(AF_INET, &(local_addr[Mod_id].sin_addr), str, INET_ADDRSTRLEN); inet_ntop(AF_INET, &(dest_addr[Mod_id].sin_addr), str1, INET_ADDRSTRLEN); - /* printf("[RRH] mod_%d socket %d connected to BBU %s:%d %s:%d\n", Mod_id, eth->sockfd[Mod_id], str1, */ - /* ntohs(dest_addr[Mod_id].sin_port),str, */ - /* ntohs(local_addr[Mod_id].sin_port)); */ - /* RRH receives from BBU openair0_config_t */ if (recvfrom(eth->sockfd[Mod_id], msg, @@ -361,19 +355,18 @@ int eth_get_dev_conf_udp(openair0_device *device) { perror("ETHERNET: "); exit(0); } - memcpy((void*)&device->openair0_cfg,msg,msg_len); /* get remote ip address and port */ - inet_ntop(AF_INET, &(dest_addr[Mod_id].sin_addr), str1, INET_ADDRSTRLEN); - device->openair0_cfg.remote_port =ntohs(dest_addr[Mod_id].sin_port); - device->openair0_cfg.remote_addr =str1; + /* inet_ntop(AF_INET, &(dest_addr[Mod_id].sin_addr), str1, INET_ADDRSTRLEN); */ + /* device->openair0_cfg.remote_port =ntohs(dest_addr[Mod_id].sin_port); */ + /* device->openair0_cfg.remote_addr =str1; */ - /* restore local ip address and port */ - inet_ntop(AF_INET, &(local_addr[Mod_id].sin_addr), str, INET_ADDRSTRLEN); - device->openair0_cfg.my_port =ntohs(local_addr[Mod_id].sin_port); - device->openair0_cfg.my_addr =str; + /* /\* restore local ip address and port *\/ */ + /* inet_ntop(AF_INET, &(local_addr[Mod_id].sin_addr), str, INET_ADDRSTRLEN); */ + /* device->openair0_cfg.my_port =ntohs(local_addr[Mod_id].sin_port); */ + /* device->openair0_cfg.my_addr =str; */ - /* printf("[RRH2] mod_%d socket %d connected to BBU %s:%d %s:%d\n", Mod_id, eth->sockfd[Mod_id],str1, device->openair0_cfg.remote_port, str, device->openair0_cfg.my_port); */ + /* printf("[RRH] mod_%d socket %d connected to BBU %s:%d %s:%d\n", Mod_id, eth->sockfd[Mod_id],str1, device->openair0_cfg.remote_port, str, device->openair0_cfg.my_port); */ return 0; } From a701d184516f32b34ea2178fdc2614f47d53c5ed Mon Sep 17 00:00:00 2001 From: "aikaterini.trilyraki" Date: Tue, 22 Dec 2015 21:16:46 +0100 Subject: [PATCH 041/263] minor update --- targets/RT/USER/lte-softmodem.c | 55 +++++++++++++++------------------ 1 file changed, 25 insertions(+), 30 deletions(-) diff --git a/targets/RT/USER/lte-softmodem.c b/targets/RT/USER/lte-softmodem.c index 0dbab07870..c67de21f56 100644 --- a/targets/RT/USER/lte-softmodem.c +++ b/targets/RT/USER/lte-softmodem.c @@ -372,8 +372,8 @@ int16_t osa_log_verbosity = LOG_MED; char *rrh_UE_ip = "127.0.0.1"; int rrh_UE_port = 51000; #endif -/* flag given in runtime to specify if the RF head is local or remote*/ -uint8_t local_remote_RF; +/* flag given in runtime to specify if the RF head is local or remote (default option is local RF)*/ +uint8_t local_remote_RF = BBU_LOCAL_RF_ENABLED; char uecap_xer[1024],uecap_xer_in=0; extern void *UE_thread(void *arg); @@ -2951,8 +2951,8 @@ int main( int argc, char **argv ) openair0_cfg[card].samples_per_packet = 1024; #ifdef OAI_USRP - openair0_cfg[card].tx_forward_nsamps = 70; - openair0_cfg[card].tx_delay = 5; + // openair0_cfg[card].tx_forward_nsamps = 70; + //openair0_cfg[card].tx_delay = 5; #endif //#elif OAI_BLADERF //openair0_cfg[card].tx_forward_nsamps = 0; @@ -2975,14 +2975,15 @@ int main( int argc, char **argv ) #ifdef ETHERNET - openair0_cfg[card].remote_addr = "192.168.12.242"; + //openair0_cfg[card].remote_addr = "192.168.12.242"; //openair0_cfg[card].remote_addr = "127.0.0.1"; openair0_cfg[card].remote_addr = "74:d4:35:cc:88:45"; openair0_cfg[card].remote_port = 50000; - openair0_cfg[card].my_addr = "192.168.12.31"; + //openair0_cfg[card].my_addr = "192.168.12.31"; //openair0_cfg[card].my_addr = "127.0.0.1"; - openair0_cfg[card].my_addr = "d4:be:d9:22:0a:ac"; + openair0_cfg[card].my_addr = "d4:be:d9:22:0a:ac"; openair0_cfg[card].my_port = 50000; + //openair0_cfg[card].my_port = 50001; openair0_cfg[card].tx_delay = 10; openair0_cfg[card].tx_forward_nsamps = 0; openair0_cfg[card].txlaunch_wait = 0; @@ -3069,20 +3070,20 @@ int main( int argc, char **argv ) openair0.host_type = BBU_HOST; /* device type is initialized NONE_DEV (no RF device) when the RF device will be initiated device type will be set */ openair0.type = NONE_DEV; + /* transport type is initialized NONE_TP (no transport protocol) when the transport protocol will be initiated transport protocol type will be set */ openair0.transp_type = NONE_TP; openair0_cfg[0].log_level = glog_level; - - /* BBU can either have local or remote radio heads */ - if (local_remote_RF == BBU_LOCAL_RF_ENABLED) { /* radio heads are local so the corresponding device is initiated */ - - if ((mode!=loop_through_memory) && - (openair0_device_load(&openair0, &openair0_cfg[0]) <0)) { - printf("Exiting, cannot initialize device\n"); - exit(-1); - } - else if (mode==loop_through_memory) { - } - } else if (local_remote_RF == BBU_REMOTE_RF_ENABLED) {/* radio heads are remote so the trasnsport protocol is initiated */ + + /* BBU can either have local or remote radio heads - local radio head option is set by default so the corresponding device is initiated */ + if ((mode!=loop_through_memory) && + (openair0_device_load(&openair0, &openair0_cfg[0]) <0)) { + printf("Exiting, cannot initialize device\n"); + exit(-1); + } + else if (mode==loop_through_memory) { + } + /* radio heads are remote so the trasnsport protocol is initiated */ + if (local_remote_RF == BBU_REMOTE_RF_ENABLED) { if ((mode!=loop_through_memory) && (openair0_transport_load(&openair0, &openair0_cfg[0]) <0)) { printf("Exiting, cannot initialize transport protocol\n"); @@ -3090,13 +3091,11 @@ int main( int argc, char **argv ) } else if (mode==loop_through_memory) { } - } -//for EXMIMO -//openair0_cfg[0].iq_rxrescale=15; /* default value if build with EXMIMO */ -//rxrescale=openair0_cfg[0].iq_rxrescale; /* see comments near RX_IQRESCALELEN definition */ - - - + } + //for EXMIMO + //openair0_cfg[0].iq_rxrescale=15; /* default value if build with EXMIMO */ + //rxrescale=openair0_cfg[0].iq_rxrescale; /* see comments near RX_IQRESCALELEN definition */ + printf("Done\n"); mac_xface = malloc(sizeof(MAC_xface)); @@ -3605,10 +3604,6 @@ int setup_eNB_buffers(PHY_VARS_eNB **phy_vars_eNB, openair0_config_t *openair0_c #endif - - - - // replace RX signal buffers with mmaped HW versions #ifdef EXMIMO openair0_cfg[CC_id].tx_num_channels = 0; From 8da8de7297bb21ba7b9cafc333270b823675473b Mon Sep 17 00:00:00 2001 From: Raymond Knopp Date: Fri, 25 Dec 2015 10:08:45 +0100 Subject: [PATCH 042/263] fixed bad BLADERF defines (BLADRF), some gain adjustments --- targets/ARCH/BLADERF/USERSPACE/LIB/bladerf_lib.c | 11 ++++++----- .../CONF/enb.band7.tm1.bladerfx40.conf | 2 +- targets/RT/USER/lte-softmodem.c | 10 ++++------ 3 files changed, 11 insertions(+), 12 deletions(-) diff --git a/targets/ARCH/BLADERF/USERSPACE/LIB/bladerf_lib.c b/targets/ARCH/BLADERF/USERSPACE/LIB/bladerf_lib.c index ce2e998fbf..3a6a35a676 100644 --- a/targets/ARCH/BLADERF/USERSPACE/LIB/bladerf_lib.c +++ b/targets/ARCH/BLADERF/USERSPACE/LIB/bladerf_lib.c @@ -208,7 +208,8 @@ int openair0_dev_init_bladerf(openair0_device *device, openair0_config_t *openai brf_state_t *brf = (brf_state_t*)malloc(sizeof(brf_state_t)); memset(brf, 0, sizeof(brf_state_t)); - // init required params for BRF + // init required params for [97448.145250] lte-softmodem-n[20648]: segfault at 0 ip (null) sp 00007fff220167b8 error 14 in lte-softmodem-nos1[400000+3bc000] + // The number of buffers to use in the underlying data stream brf->num_buffers = 128; // the size of the underlying stream buffers, in samples @@ -254,11 +255,11 @@ int openair0_dev_init_bladerf(openair0_device *device, openair0_config_t *openai printf("[BRF] set RX sample rate to %u, %u\n", (unsigned int) openair0_cfg[card].sample_rate, actual_value); - if ((status=bladerf_set_bandwidth(brf->dev, BLADERF_MODULE_RX, (unsigned int) openair0_cfg[card].rx_bw, &actual_value)) != 0){ + if ((status=bladerf_set_bandwidth(brf->dev, BLADERF_MODULE_RX, (unsigned int) openair0_cfg[card].rx_bw*2, &actual_value)) != 0){ fprintf(stderr,"Failed to set RX bandwidth: %s\n", bladerf_strerror(status)); brf_error(status); }else - printf("[BRF] set RX bandwidth to %u, %u\n",(unsigned int)openair0_cfg[card].rx_bw, actual_value); + printf("[BRF] set RX bandwidth to %u, %u\n",(unsigned int)openair0_cfg[card].rx_bw*2, actual_value); if ((status=bladerf_set_gain(brf->dev, BLADERF_MODULE_RX, (int) openair0_cfg[card].rx_gain[0])) != 0) { fprintf(stderr,"Failed to set RX gain: %s\n",bladerf_strerror(status)); @@ -280,11 +281,11 @@ int openair0_dev_init_bladerf(openair0_device *device, openair0_config_t *openai }else printf("[BRF] set TX sampling rate to %u \n", (unsigned int) openair0_cfg[card].sample_rate); - if ((status=bladerf_set_bandwidth(brf->dev, BLADERF_MODULE_TX,(unsigned int)openair0_cfg[card].tx_bw, NULL)) != 0){ + if ((status=bladerf_set_bandwidth(brf->dev, BLADERF_MODULE_TX,(unsigned int)openair0_cfg[card].tx_bw*2, NULL)) != 0){ fprintf(stderr, "Failed to set TX bandwidth: %s\n", bladerf_strerror(status)); brf_error(status); }else - printf("[BRF] set TX bandwidth to %u \n", (unsigned int) openair0_cfg[card].tx_bw); + printf("[BRF] set TX bandwidth to %u \n", (unsigned int) openair0_cfg[card].tx_bw*2); if ((status=bladerf_set_gain(brf->dev, BLADERF_MODULE_TX, (int) openair0_cfg[card].tx_gain[0])) != 0) { fprintf(stderr,"Failed to set TX gain: %s\n",bladerf_strerror(status)); diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf index bdbb46a98b..2933b43718 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf @@ -35,7 +35,7 @@ eNBs = Nid_cell_mbsfn = 0; nb_antennas_tx = 1; nb_antennas_rx = 1; - tx_gain = 20; + tx_gain = 60; rx_gain = 20; prach_root = 0; prach_config_index = 0; diff --git a/targets/RT/USER/lte-softmodem.c b/targets/RT/USER/lte-softmodem.c index 8e08cfc04c..9926fe75ed 100644 --- a/targets/RT/USER/lte-softmodem.c +++ b/targets/RT/USER/lte-softmodem.c @@ -950,7 +950,7 @@ void do_OFDM_mod_rt(int subframe,PHY_VARS_eNB *phy_vars_eNB) ((short*)&phy_vars_eNB->lte_eNB_common_vars.txdata[0][aa][tx_offset])[0]= #ifdef EXMIMO ((short*)dummy_tx_b)[2*i]<<4; -#elif OAI_BLADRF +#elif OAI_BLADERF ((short*)dummy_tx_b)[2*i]; #else ((short*)dummy_tx_b)[2*i]<<4; @@ -958,7 +958,7 @@ void do_OFDM_mod_rt(int subframe,PHY_VARS_eNB *phy_vars_eNB) ((short*)&phy_vars_eNB->lte_eNB_common_vars.txdata[0][aa][tx_offset])[1]= #ifdef EXMIMO ((short*)dummy_tx_b)[2*i+1]<<4; -#elif OAI_BLADRF +#elif OAI_BLADERF ((short*)dummy_tx_b)[2*i+1]; #else ((short*)dummy_tx_b)[2*i+1]<<4; @@ -2935,11 +2935,9 @@ int main( int argc, char **argv ) openair0_cfg[card].remote_ip = &rrh_eNB_ip[0]; openair0_cfg[card].remote_port = rrh_eNB_port; } -openair0_cfg[card].num_rb_dl=frame_parms[0]->N_RB_DL; + openair0_cfg[card].num_rb_dl=frame_parms[0]->N_RB_DL; #endif - openair0_cfg[card].sample_rate = sample_rate; - openair0_cfg[card].tx_bw = bw; - openair0_cfg[card].rx_bw = bw; + // in the case of the USRP, the following variables need to be initialized before the init // since the USRP only supports one CC (for the moment), we initialize all the cards with first CC. // in the case of EXMIMO2, these values are overwirtten in the function setup_eNB/UE_buffer From d3173214eb5c2c1fe7f961646f5983fabd74f796 Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Sat, 26 Dec 2015 00:08:08 +0100 Subject: [PATCH 043/263] updated for using develop branch by default --- cmake_targets/autotests/test_case_list.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake_targets/autotests/test_case_list.xml b/cmake_targets/autotests/test_case_list.xml index ba34085d90..6df11e81ad 100644 --- a/cmake_targets/autotests/test_case_list.xml +++ b/cmake_targets/autotests/test_case_list.xml @@ -4,7 +4,7 @@ /mnt/sradio/TEST_RESULTS https://gitlab.eurecom.fr/oai/openairinterface5g.git https://gitlab.eurecom.fr/oai/openair-cn.git - enhancement-57-UHD-interfacing + develop feature-17-test_framework oaisim* oaisim_nos1* lte-softmodem* lte-softmodem-nos1* mme_gw* run_epc* run_hss* iperf* hss hss_sim configure_cots_bandrich_ue* wvdial* run_exec_autotests* iperf /opt/ltebox/tools/stop_ltebox From abac3741fc4f4a3651cf90f52b422d845e58b53a Mon Sep 17 00:00:00 2001 From: Raymond Knopp Date: Sun, 27 Dec 2015 11:43:37 +0100 Subject: [PATCH 044/263] added BLADERF configuration file for 50PRB --- .../CONF/enb.band7.tm1.50PRB.bladerfx40.conf | 171 ++++++++++++++++++ 1 file changed, 171 insertions(+) create mode 100644 targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.bladerfx40.conf diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.bladerfx40.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.bladerfx40.conf new file mode 100644 index 0000000000..5f7ac3d65f --- /dev/null +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.bladerfx40.conf @@ -0,0 +1,171 @@ +Active_eNBs = ( "eNB_Eurecom_LTEBox"); +# Asn1_verbosity, choice in: none, info, annoying +Asn1_verbosity = "none"; + +eNBs = +( + { + ////////// Identification parameters: + eNB_ID = 0xe00; + + cell_type = "CELL_MACRO_ENB"; + + eNB_name = "eNB_Eurecom_LTEBox"; + + // Tracking area code, 0x0000 and 0xfffe are reserved values + tracking_area_code = "1"; + + mobile_country_code = "208"; + + mobile_network_code = "92"; + + ////////// Physical parameters: + + component_carriers = ( + { + frame_type = "FDD"; + tdd_config = 3; + tdd_config_s = 0; + prefix_type = "NORMAL"; + eutra_band = 7; + downlink_frequency = 2680000000L; + uplink_frequency_offset = -120000000; + Nid_cell = 0; + N_RB_DL = 50; + Nid_cell_mbsfn = 0; + nb_antennas_tx = 1; + nb_antennas_rx = 1; + tx_gain = 60; + rx_gain = 60; + prach_root = 0; + prach_config_index = 0; + prach_high_speed = "DISABLE"; + prach_zero_correlation = 1; + prach_freq_offset = 2; + pucch_delta_shift = 1; + pucch_nRB_CQI = 1; + pucch_nCS_AN = 0; + pucch_n1_AN = 32; + pdsch_referenceSignalPower = -26; + pdsch_p_b = 0; + pusch_n_SB = 1; + pusch_enable64QAM = "DISABLE"; + pusch_hoppingMode = "interSubFrame"; + pusch_hoppingOffset = 0; + pusch_groupHoppingEnabled = "ENABLE"; + pusch_groupAssignment = 0; + pusch_sequenceHoppingEnabled = "DISABLE"; + pusch_nDMRS1 = 1; + phich_duration = "NORMAL"; + phich_resource = "ONESIXTH"; + srs_enable = "DISABLE"; + /* srs_BandwidthConfig =; + srs_SubframeConfig =; + srs_ackNackST =; + srs_MaxUpPts =;*/ + + pusch_p0_Nominal = -90; + pusch_alpha = "AL1"; + pucch_p0_Nominal = -108; + msg3_delta_Preamble = 6; + pucch_deltaF_Format1 = "deltaF2"; + pucch_deltaF_Format1b = "deltaF3"; + pucch_deltaF_Format2 = "deltaF0"; + pucch_deltaF_Format2a = "deltaF0"; + pucch_deltaF_Format2b = "deltaF0"; + + rach_numberOfRA_Preambles = 64; + rach_preamblesGroupAConfig = "DISABLE"; +/* + rach_sizeOfRA_PreamblesGroupA = ; + rach_messageSizeGroupA = ; + rach_messagePowerOffsetGroupB = ; +*/ + rach_powerRampingStep = 4; + rach_preambleInitialReceivedTargetPower = -108; + rach_preambleTransMax = 10; + rach_raResponseWindowSize = 10; + rach_macContentionResolutionTimer = 48; + rach_maxHARQ_Msg3Tx = 4; + + pcch_default_PagingCycle = 128; + pcch_nB = "oneT"; + bcch_modificationPeriodCoeff = 2; + ue_TimersAndConstants_t300 = 1000; + ue_TimersAndConstants_t301 = 1000; + ue_TimersAndConstants_t310 = 1000; + ue_TimersAndConstants_t311 = 10000; + ue_TimersAndConstants_n310 = 20; + ue_TimersAndConstants_n311 = 1; + + } + ); + + + srb1_parameters : + { + # timer_poll_retransmit = (ms) [5, 10, 15, 20,... 250, 300, 350, ... 500] + timer_poll_retransmit = 80; + + # timer_reordering = (ms) [0,5, ... 100, 110, 120, ... ,200] + timer_reordering = 35; + + # timer_reordering = (ms) [0,5, ... 250, 300, 350, ... ,500] + timer_status_prohibit = 0; + + # poll_pdu = [4, 8, 16, 32 , 64, 128, 256, infinity(>10000)] + poll_pdu = 4; + + # poll_byte = (kB) [25,50,75,100,125,250,375,500,750,1000,1250,1500,2000,3000,infinity(>10000)] + poll_byte = 99999; + + # max_retx_threshold = [1, 2, 3, 4 , 6, 8, 16, 32] + max_retx_threshold = 4; + } + + # ------- SCTP definitions + SCTP : + { + # Number of streams to use in input/output + SCTP_INSTREAMS = 2; + SCTP_OUTSTREAMS = 2; + }; + + ////////// MME parameters: + mme_ip_address = ( { ipv4 = "192.168.13.11"; + ipv6 = "192:168:30::17"; + active = "yes"; + preference = "ipv4"; + } + ); + + NETWORK_INTERFACES : + { + ENB_INTERFACE_NAME_FOR_S1_MME = "eth0"; + ENB_IPV4_ADDRESS_FOR_S1_MME = "192.168.13.10/24"; + + ENB_INTERFACE_NAME_FOR_S1U = "eth0"; + ENB_IPV4_ADDRESS_FOR_S1U = "192.168.13.10/24"; + ENB_PORT_FOR_S1U = 2152; # Spec 2152 + }; + + log_config : + { + global_log_level ="info"; + global_log_verbosity ="medium"; + hw_log_level ="info"; + hw_log_verbosity ="medium"; + phy_log_level ="info"; + phy_log_verbosity ="medium"; + mac_log_level ="info"; + mac_log_verbosity ="high"; + rlc_log_level ="info"; + rlc_log_verbosity ="medium"; + pdcp_log_level ="info"; + pdcp_log_verbosity ="medium"; + rrc_log_level ="info"; + rrc_log_verbosity ="medium"; + }; + + } +); From 1bff2ec73a0ba472addcb436573b254045926b02 Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Sun, 27 Dec 2015 13:07:04 +0100 Subject: [PATCH 045/263] updates for thoughput tests in test framework --- .../autotests/run_exec_lte-softmodem_tests.py | 79 ++++++++------ cmake_targets/autotests/test_case_list.xml | 102 +++++++++--------- 2 files changed, 99 insertions(+), 82 deletions(-) diff --git a/cmake_targets/autotests/run_exec_lte-softmodem_tests.py b/cmake_targets/autotests/run_exec_lte-softmodem_tests.py index 6ed97d5180..5a4fca3524 100644 --- a/cmake_targets/autotests/run_exec_lte-softmodem_tests.py +++ b/cmake_targets/autotests/run_exec_lte-softmodem_tests.py @@ -1,4 +1,4 @@ -w#! /usr/bin/python +#! /usr/bin/python #****************************************************************************** # OpenAirInterface @@ -285,7 +285,7 @@ def cleanOldPrograms(oai, programList, CleanUpAluLteBox, ExmimoRfStop): result = oai.send_expect_false(cmd, 'Match found', False) print result res=oai.send_recv(CleanUpAluLteBox, True) - res = oai.send_recv(ExmimoRfStop, True) + res = oai.send_recv(ExmimoRfStop, False) class myThread (threading.Thread): def __init__(self, threadID, name, counter): @@ -548,9 +548,9 @@ def handle_testcaseclass_softmodem (testcase, oldprogramList, logdirOAI5GRepo , oai_EPC.connect(user, password) res = oai_eNB.send_recv(cmd) - cleanOldPrograms(oai_eNB, oldprogramList, CleanUpAluLteBox, ExmimoRfStop) - cleanOldPrograms(oai_UE, oldprogramList, CleanUpAluLteBox, ExmimoRfStop) - cleanOldPrograms(oai_EPC, oldprogramList, CleanUpAluLteBox, ExmimoRfStop) + #cleanOldPrograms(oai_eNB, oldprogramList, CleanUpAluLteBox, ExmimoRfStop) + #cleanOldPrograms(oai_UE, oldprogramList, CleanUpAluLteBox, ExmimoRfStop) + #cleanOldPrograms(oai_EPC, oldprogramList, CleanUpAluLteBox, ExmimoRfStop) logdir_eNB = logdirOAI5GRepo+'/cmake_targets/autotests/log/'+ testcasename logdir_UE = logdirOAI5GRepo+'/cmake_targets/autotests/log/'+ testcasename logdir_EPC = logdirOpenaircnRepo+'/TEST/autotests/log/'+ testcasename @@ -616,13 +616,13 @@ def handle_testcaseclass_softmodem (testcase, oldprogramList, logdirOAI5GRepo , task_eNB = task_eNB + 'env |grep OPENAIR \n' + 'array_exec_pid=() \n' if eNB_pre_exec != "": - task_eNB = task_eNB + ' ( ' + eNB_pre_exec + ' '+ eNB_pre_exec_args + ' ) > ' + logfile_pre_exec_eNB + ' 2>&1 \n' + task_eNB = task_eNB + ' ( date; ' + eNB_pre_exec + ' '+ eNB_pre_exec_args + ' ) > ' + logfile_pre_exec_eNB + ' 2>&1 \n' if eNB_main_exec != "": - task_eNB = task_eNB + ' ( ' + addsudo(eNB_main_exec + ' ' + eNB_main_exec_args, mypassword) + ' ) > ' + logfile_exec_eNB + ' 2>&1 & \n' + task_eNB = task_eNB + ' ( date; ' + addsudo(eNB_main_exec + ' ' + eNB_main_exec_args, mypassword) + ' ) > ' + logfile_exec_eNB + ' 2>&1 & \n' task_eNB = task_eNB + 'array_exec_pid+=($!) \n' task_eNB = task_eNB + 'echo eNB_main_exec PID = $! \n' if eNB_traffic_exec != "": - task_eNB = task_eNB + ' ( ' + eNB_traffic_exec + ' ' + eNB_traffic_exec_args + ' ) > ' + logfile_traffic_eNB + ' 2>&1 & \n ' + task_eNB = task_eNB + ' (date; ' + eNB_traffic_exec + ' ' + eNB_traffic_exec_args + ' ) > ' + logfile_traffic_eNB + ' 2>&1 & \n ' task_eNB = task_eNB + 'array_exec_pid+=($!) \n' task_eNB = task_eNB + 'echo eNB_traffic_exec PID = $! \n' #terminate the eNB test case after timeout_cmd seconds @@ -662,13 +662,13 @@ def handle_testcaseclass_softmodem (testcase, oldprogramList, logdirOAI5GRepo , task_UE = task_UE + 'source cmake_targets/tools/build_helper \n' task_UE = task_UE + 'env |grep OPENAIR \n' if UE_pre_exec != "": - task_UE = task_UE + ' ( ' + UE_pre_exec + ' '+ UE_pre_exec_args + ' ) > ' + logfile_pre_exec_UE + ' 2>&1 \n' + task_UE = task_UE + ' ( date; ' + UE_pre_exec + ' '+ UE_pre_exec_args + ' ) > ' + logfile_pre_exec_UE + ' 2>&1 \n' if UE_main_exec != "": - task_UE = task_UE + ' ( ' + addsudo(UE_main_exec + ' ' + UE_main_exec_args, mypassword) + ' ) > ' + logfile_exec_UE + ' 2>&1 & \n' + task_UE = task_UE + ' ( date; ' + addsudo(UE_main_exec + ' ' + UE_main_exec_args, mypassword) + ' ) > ' + logfile_exec_UE + ' 2>&1 & \n' task_UE = task_UE + 'array_exec_pid+=($!) \n' task_UE = task_UE + 'echo UE_main_exec PID = $! \n' if UE_traffic_exec != "": - task_UE = task_UE + ' ( ' + UE_traffic_exec + ' ' + UE_traffic_exec_args + ' ) >' + logfile_traffic_UE + ' 2>&1 & \n' + task_UE = task_UE + ' ( date; ' + UE_traffic_exec + ' ' + UE_traffic_exec_args + ' ) >' + logfile_traffic_UE + ' 2>&1 & \n' task_UE = task_UE + 'array_exec_pid+=($!) \n' task_UE = task_UE + 'echo UE_traffic_exec PID = $! \n' #terminate the UE test case after timeout_cmd seconds @@ -708,17 +708,17 @@ def handle_testcaseclass_softmodem (testcase, oldprogramList, logdirOAI5GRepo , task_EPC = task_EPC + 'cd ' + logdirOpenaircnRepo + '\n' task_EPC = task_EPC + 'source BUILD/TOOLS/build_helper \n' if EPC_pre_exec != "": - task_EPC = task_EPC + ' ( ' + EPC_pre_exec + ' '+ EPC_pre_exec_args + ' ) > ' + logfile_pre_exec_EPC + ' 2>&1 \n' + task_EPC = task_EPC + ' ( date; ' + EPC_pre_exec + ' '+ EPC_pre_exec_args + ' ) > ' + logfile_pre_exec_EPC + ' 2>&1 \n' if HSS_main_exec != "": - task_EPC = task_EPC + '(' + addsudo (HSS_main_exec + ' ' + HSS_main_exec_args, mypassword) + ' ) > ' + logfile_exec_HSS + ' 2>&1 & \n' + task_EPC = task_EPC + '( date; ' + addsudo (HSS_main_exec + ' ' + HSS_main_exec_args, mypassword) + ' ) > ' + logfile_exec_HSS + ' 2>&1 & \n' task_EPC = task_EPC + 'array_exec_pid+=($!) \n' task_EPC = task_EPC + 'echo HSS_main_exec PID = $! \n' if EPC_main_exec != "": - task_EPC = task_EPC + '(' + addsudo (EPC_main_exec + ' ' + EPC_main_exec_args, mypassword) + ' ) > ' + logfile_exec_EPC + ' 2>&1 & \n' + task_EPC = task_EPC + '( date; ' + addsudo (EPC_main_exec + ' ' + EPC_main_exec_args, mypassword) + ' ) > ' + logfile_exec_EPC + ' 2>&1 & \n' task_EPC = task_EPC + 'array_exec_pid+=($!) \n' task_EPC = task_EPC + 'echo EPC_main_exec PID = $! \n' if EPC_traffic_exec != "": - task_EPC = task_EPC + '(' + EPC_traffic_exec + ' ' + EPC_traffic_exec_args + ' ) > ' + logfile_traffic_EPC + ' 2>&1 & \n' + task_EPC = task_EPC + '( date; ' + EPC_traffic_exec + ' ' + EPC_traffic_exec_args + ' ) > ' + logfile_traffic_EPC + ' 2>&1 & \n' task_EPC = task_EPC + 'array_exec_pid+=($!) \n' task_EPC = task_EPC + 'echo EPC_traffic_exec PID = $! \n' #terminate the EPC test case after timeout_cmd seconds @@ -882,6 +882,7 @@ dlsim=0 localshell=0 is_compiled = 0 timeout=2000 +GitOAI5GRepoBranch='' xmlInputFile="./test_case_list.xml" NFSResultsDir = '/mnt/sradio' cleanupOldProgramsScript = '$OPENAIR_DIR/cmake_targets/autotests/tools/remove_old_programs.bash' @@ -928,6 +929,9 @@ while i < len (sys.argv): i = i +1 elif arg == '-c': cleanUpRemoteMachines=True + elif arg == '-5GRepoBranch': + GitOAI5GRepoBranch = sys.argv[i+1] + i = i +1 elif arg == '-h' : print "-d: low debug level" print "-dd: high debug level" @@ -938,6 +942,7 @@ while i < len (sys.argv): print "-w: set the password for ssh to localhost" print "-l: use local shell instead of ssh connection" print "-t: set the time out in second for commands" + print "-5GRepoBranch: Branch for OAI 5G Repository to run tests (overrides the branch in test_case_list.xml)" sys.exit() else : print "Unrecongnized Option: <" + arg + ">. Use -h to see valid options" @@ -995,7 +1000,10 @@ MachineList = xmlRoot.findtext('MachineList',default='') NFSResultsShare = xmlRoot.findtext('NFSResultsShare',default='') GitOpenaircnRepo = xmlRoot.findtext('GitOpenair-cnRepo',default='') GitOAI5GRepo = xmlRoot.findtext('GitOAI5GRepo',default='') -GitOAI5GRepoBranch = xmlRoot.findtext('GitOAI5GRepoBranch',default='') + +if GitOAI5GRepoBranch == '': + GitOAI5GRepoBranch = xmlRoot.findtext('GitOAI5GRepoBranch',default='') + GitOpenaircnRepoBranch = xmlRoot.findtext('GitOpenair-cnRepoBranch',default='') CleanUpOldProgs = xmlRoot.findtext('CleanUpOldProgs',default='') CleanUpAluLteBox = xmlRoot.findtext('CleanUpAluLteBox',default='') @@ -1011,10 +1019,15 @@ print "GitOpenaircnRepoBranch = " + GitOpenaircnRepoBranch print "NFSResultsShare = " + NFSResultsShare cmd = "git show-ref --heads -s "+ GitOAI5GRepoBranch GitOAI5GHeadVersion = subprocess.check_output ([cmd], shell=True) +GitOAI5GHeadVersion=GitOAI5GHeadVersion.replace("\n","") print "GitOAI5GHeadVersion = " + GitOAI5GHeadVersion print "CleanUpOldProgs = " + CleanUpOldProgs print "Timeout_execution = " + str(Timeout_execution) +if GitOAI5GHeadVersion == '': + print "Error getting the OAI5GBranch Head version...Exiting" + sys.exit() + MachineList = MachineList.split() MachineListGeneric = MachineListGeneric.split() @@ -1123,7 +1136,7 @@ for index in oai_list: #print oai_list[oai].send_recv('sudo su') #print oai_list[oai].send_recv('who am i') #cleanUpPrograms(oai_list[oai] - cmd = 'mkdir -p ' + logdir + ' ; rm -fr ' + logdir + '/*' + cmd = 'sudo -S -E rm -fr ' + logdir + ' ; mkdir -p ' + logdir result = oai_list[index].send_recv(cmd) setuplogfile = logdir + '/setup_log_' + MachineList[index] + '_.txt' @@ -1133,28 +1146,30 @@ for index in oai_list: #cmd = cmd + 'mkdir -p ' + logdir + '\n' cmd = cmd + 'cd '+ logdir + '\n' cmd = cmd + 'git config --global http.sslVerify false \n' - cmd = cmd + 'git clone '+ GitOAI5GRepo + '\n' - cmd = cmd + 'git clone '+ GitOpenaircnRepo + '\n' + cmd = cmd + 'git clone --depth 1 '+ GitOAI5GRepo + ' -b ' + GitOAI5GRepoBranch +' \n' + cmd = cmd + 'git clone '+ GitOpenaircnRepo + ' -b ' +GitOpenaircnRepoBranch + ' \n' cmd = cmd + 'cd ' + logdirOAI5GRepo + '\n' cmd = cmd + 'git checkout ' + GitOAI5GRepoBranch + '\n' - cmd = cmd + 'git checkout ' + GitOAI5GHeadVersion + '\n' - cmd = cmd + 'git_head = `git ls-remote |grep \"' + GitOAI5GRepoBranch + '\"' - cmd = cmd + 'git_head = ($git_head)' - cmd = cmd + 'git_head = ${git_head[0]}' - cmd = cmd + 'if [ \"$git_head\" != \"'+ GitOAI5GHeadVersion + '\" ]; then echo \"error: Git openairinterface5g head version does not match\" ; fi ' + #cmd = cmd + 'git checkout ' + GitOAI5GHeadVersion + '\n' + cmd = cmd + 'git_head=`git ls-remote |grep \'' + GitOAI5GRepoBranch + '\'` \n' + cmd = cmd + 'git_head=($git_head) \n' + cmd = cmd + 'git_head=${git_head[0]} \n' + cmd = cmd + 'echo \"GitOAI5GHeadVersion_remote = $git_head\"' + cmd = cmd + 'echo \"GitOAI5GHeadVersion_local = ' + GitOAI5GHeadVersion + '\" \n' + cmd = cmd + 'if [ \"$git_head\" != \"'+ GitOAI5GHeadVersion + '\" ]; then echo \"error: Git openairinterface5g head version does not match\" ; fi \n' cmd = cmd + 'source oaienv' + '\n' cmd = cmd + 'cd ' + logdirOpenaircnRepo + '\n' cmd = cmd + 'git checkout ' + GitOpenaircnRepoBranch + '\n' cmd = cmd + 'env |grep OPENAIR' + '\n' cmd = cmd + ' cd ' + logdir + '\n' - cmd = cmd + ' ) > ' + setuplogfile + ' 2>&1 ' + cmd = cmd + ' ) > ' + setuplogfile + ' 2>&1 \n' #cmd = cmd + 'echo \' ' + cmd + '\' > ' + setup_script + ' 2>&1 \n ' #result = oai_list[index].send_recv(cmd, False, 300 ) write_file(setup_script, cmd, mode="w") tempThread = oaiThread(index, 'thread_setup_'+str(index)+'_' + MachineList[index] , MachineList[index] , user, pw, cmd, False, 300) threads_init_setup.append(tempThread ) tempThread.start() - + #localfile = locallogdir + '/setup_log_' + MachineList[index] + '_.txt' #remotefile = logdir + '/setup_log_' + MachineList[index] + '_.txt' @@ -1215,8 +1230,10 @@ for t in threads_init_setup: paramList.append ( {"operation":'put', "localfile":localfile, "remotefile":remotefile} ) sftp_log = os.path.expandvars(locallogdir + '/sftp_module.log') sftp_module (user, pw, MachineList[index], port, paramList, sftp_log) - index = index+1 - + + cmd = ' cd ' + logdirOAI5GRepo + ' ; source oaienv ; env|grep OPENAIR \n' + res = oai_list[index].send_recv(cmd) + index = index +1 if os.path.exists(localfile) == 0: print "Setup log file <" + localfile + "> missing for machine <" + MachineList[index] + ">. Please check the setup log files. Exiting now" sys.exit(1) @@ -1224,14 +1241,14 @@ for t in threads_init_setup: #Now we process all the test cases #Now we check if there was error in setup files -status, out = commands.getstatusoutput('grep ' + ' -il \'error\' ' + locallogdir + '/setup*') +status, out = commands.getstatusoutput('grep ' + ' -il \'error\' ' + locallogdir + '/setup_log*') if (out != '') : print "There is error in setup of machines" print "status = " + str(status) + "\n Check files for error = " + out print sys.exit(1) if cleanUpRemoteMachines == True: - cleanOldProgramsAllMachines(oai_list, CleanOldProgs, CleanUpAluLteBox, ExmimoRfStop) + cleanOldProgramsAllMachines(oai_list, CleanUpOldProgs, CleanUpAluLteBox, ExmimoRfStop) sys.exit(0) threadListGlobal=[] @@ -1244,7 +1261,7 @@ for testcase in testcaseList: desc = testcase.findtext('desc',default='') #print "Machine list top level = " + ','.join(MachineList) if search_test_case_group(testcasename, testcasegroup, TestCaseExclusionList) == True: - cleanOldProgramsAllMachines(oai_list, CleanOldProgs, CleanUpAluLteBox, ExmimoRfStop) + cleanOldProgramsAllMachines(oai_list, CleanUpOldProgs, CleanUpAluLteBox, ExmimoRfStop) if testcaseclass == 'lte-softmodem' : eNBMachine = testcase.findtext('eNB',default='') UEMachine = testcase.findtext('UE',default='') diff --git a/cmake_targets/autotests/test_case_list.xml b/cmake_targets/autotests/test_case_list.xml index ceb86c6c35..519ee2c9de 100644 --- a/cmake_targets/autotests/test_case_list.xml +++ b/cmake_targets/autotests/test_case_list.xml @@ -1,14 +1,14 @@ -stevens calisson mozart nano amerique +calisson mozart stevens nano amerique /mnt/sradio/TEST_RESULTS https://gitlab.eurecom.fr/oai/openairinterface5g.git https://gitlab.eurecom.fr/oai/openair-cn.git develop feature-17-test_framework - oaisim* oaisim_nos1* lte-softmodem* lte-softmodem-nos1* mme_gw* run_epc* run_hss* iperf* hss hss_sim configure_cots_bandrich_ue* wvdial* run_exec_autotests* iperf + oaisim* oaisim_nos1* lte-softmodem* lte-softmodem-nos1* mme_gw* run_epc* run_hss* iperf* hss hss_sim configure_cots_bandrich_ue* wvdial* run_exec_autotests* iperf iperf_client iperf_server /opt/ltebox/tools/stop_ltebox -$OPENAIR_DIR/cmake_targets/build_oai -w EXMIMO -c; sudo -S -E $OPENAIR_DIR/cmake_targets/tools/stop_exmimo2 +$OPENAIR_DIR/cmake_targets/build_oai -w EXMIMO -c; sudo -S -E $OPENAIR_DIR/cmake_targets/tools/stop_exmimo2; dmesg|tail 36000 0104+ 015502 015505 015506 015507 015508 015508 015509 015510 015511 015600 015700 016102 016105 calisson stevens mozart nano amerique @@ -858,7 +858,7 @@ calisson stevens amerique - 360 + 390 /tmp targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf tracking_area_code \"1\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf mobile_country_code \"208\" @@ -902,7 +902,7 @@ $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 45; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue - while true; do var=`ifconfig ppp0` ;sleep 1; if [ "$var" != "" ]; then break; fi ; done ; sleep 5; iperf -u -c 192.172.0.1 -b 10Mbits/s -t 300 -B 192.172.0.2 + while true; do var=`ifconfig ppp0` ;sleep 1; if [ "$var" != "" ]; then break; fi ; done ; sleep 5; iperf -u -c 192.172.0.1 -b 10Mbits/s -t 330 -B 192.172.0.2 @@ -942,7 +942,7 @@ calisson stevens amerique - 360 + 390 /tmp targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf tracking_area_code \"1\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf mobile_country_code \"208\" @@ -986,7 +986,7 @@ $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 45; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue - while true; do var=`ifconfig ppp0` ;sleep 1; if [ "$var" != "" ]; then break; fi ; done ; sleep 5; iperf -u -c 192.172.0.1 -b 10Mbits/s -t 300 -B 192.172.0.2 + while true; do var=`ifconfig ppp0` ;sleep 1; if [ "$var" != "" ]; then break; fi ; done ; sleep 5; iperf -u -c 192.172.0.1 -b 10Mbits/s -t 330 -B 192.172.0.2 @@ -1025,7 +1025,7 @@ calisson stevens amerique - 360 + 390 /tmp targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf tracking_area_code \"1\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf mobile_country_code \"208\" @@ -1069,7 +1069,7 @@ $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 45; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue - while true; do var=`ifconfig ppp0` ;sleep 1; if [ "$var" != "" ]; then break; fi ; done ; sleep 5; iperf -u -c 192.172.0.1 -b 10Mbits/s -t 300 -B 192.172.0.2 + while true; do var=`ifconfig ppp0` ;sleep 1; if [ "$var" != "" ]; then break; fi ; done ; sleep 5; iperf -u -c 192.172.0.1 -b 10Mbits/s -t 330 -B 192.172.0.2 @@ -1108,7 +1108,7 @@ calisson stevens amerique - 360 + 390 /tmp targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf tracking_area_code \"1\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf mobile_country_code \"208\" @@ -1176,7 +1176,7 @@ /opt/hss_sim0609/starthss >> /dev/null ; sleep 3000 - sleep 60; iperf -u -c 192.172.0.2 -b 10Mbits/s -t 300 -B 192.172.0.1 + sleep 60; iperf -u -c 192.172.0.2 -b 10Mbits/s -t 330 -B 192.172.0.1 True @@ -1190,7 +1190,7 @@ calisson stevens amerique - 360 + 390 /tmp targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf tracking_area_code \"1\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf mobile_country_code \"208\" @@ -1259,7 +1259,7 @@ /opt/hss_sim0609/starthss >> /dev/null ; sleep 3000 - sleep 60; iperf -u -c 192.172.0.2 -b 10Mbits/s -t 300 -B 192.172.0.1 + sleep 60; iperf -u -c 192.172.0.2 -b 10Mbits/s -t 330 -B 192.172.0.1 True @@ -1273,7 +1273,7 @@ calisson stevens amerique - 360 + 390 /tmp targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf tracking_area_code \"1\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf mobile_country_code \"208\" @@ -1342,7 +1342,7 @@ /opt/hss_sim0609/starthss >> /dev/null ; sleep 3000 - sleep 60; iperf -u -c 192.172.0.2 -b 10Mbits/s -t 300 -B 192.172.0.1 + sleep 60; iperf -u -c 192.172.0.2 -b 10Mbits/s -t 330 -B 192.172.0.1 True @@ -1357,7 +1357,7 @@ calisson stevens amerique - 360 + 390 /tmp targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf tracking_area_code \"1\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf mobile_country_code \"208\" @@ -1401,7 +1401,7 @@ $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 45; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue - while true; do var=`ifconfig ppp0` ;sleep 1; if [ "$var" != "" ]; then break; fi ; done ; sleep 5; iperf -u -c 192.172.0.1 -b 10Mbits/s -t 300 -B 192.172.0.2 + while true; do var=`ifconfig ppp0` ;sleep 1; if [ "$var" != "" ]; then break; fi ; done ; sleep 5; iperf -u -c 192.172.0.1 -b 10Mbits/s -t 330 -B 192.172.0.2 @@ -1441,7 +1441,7 @@ calisson stevens amerique - 360 + 390 /tmp targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf tracking_area_code \"1\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf mobile_country_code \"208\" @@ -1485,7 +1485,7 @@ $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 45; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue - while true; do var=`ifconfig ppp0` ;sleep 1; if [ "$var" != "" ]; then break; fi ; done ; sleep 5; iperf -u -c 192.172.0.1 -b 10Mbits/s -t 300 -B 192.172.0.2 + while true; do var=`ifconfig ppp0` ;sleep 1; if [ "$var" != "" ]; then break; fi ; done ; sleep 5; iperf -u -c 192.172.0.1 -b 10Mbits/s -t 330 -B 192.172.0.2 @@ -1524,7 +1524,7 @@ calisson stevens amerique - 360 + 390 /tmp targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf tracking_area_code \"1\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf mobile_country_code \"208\" @@ -1568,7 +1568,7 @@ $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 45; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue - while true; do var=`ifconfig ppp0` ;sleep 1; if [ "$var" != "" ]; then break; fi ; done ; sleep 5; iperf -u -c 192.172.0.1 -b 10Mbits/s -t 300 -B 192.172.0.2 + while true; do var=`ifconfig ppp0` ;sleep 1; if [ "$var" != "" ]; then break; fi ; done ; sleep 5; iperf -u -c 192.172.0.1 -b 10Mbits/s -t 330 -B 192.172.0.2 @@ -1607,7 +1607,7 @@ calisson stevens amerique - 360 + 390 /tmp targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf tracking_area_code \"1\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf mobile_country_code \"208\" @@ -1676,7 +1676,7 @@ /opt/hss_sim0609/starthss >> /dev/null ; sleep 3000 - sleep 60; iperf -u -c 192.172.0.2 -b 10Mbits/s -t 300 -B 192.172.0.1 + sleep 60; iperf -u -c 192.172.0.2 -b 10Mbits/s -t 330 -B 192.172.0.1 True @@ -1690,7 +1690,7 @@ calisson stevens amerique - 360 + 390 /tmp targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf tracking_area_code \"1\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf mobile_country_code \"208\" @@ -1759,7 +1759,7 @@ /opt/hss_sim0609/starthss >> /dev/null ; sleep 3000 - sleep 60; iperf -u -c 192.172.0.2 -b 10Mbits/s -t 300 -B 192.172.0.1 + sleep 60; iperf -u -c 192.172.0.2 -b 10Mbits/s -t 330 -B 192.172.0.1 True @@ -1773,7 +1773,7 @@ calisson stevens amerique - 360 + 390 /tmp targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf tracking_area_code \"1\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf mobile_country_code \"208\" @@ -1842,7 +1842,7 @@ /opt/hss_sim0609/starthss >> /dev/null ; sleep 3000 - sleep 60; iperf -u -c 192.172.0.2 -b 10Mbits/s -t 300 -B 192.172.0.1 + sleep 60; iperf -u -c 192.172.0.2 -b 10Mbits/s -t 330 -B 192.172.0.1 True @@ -1857,7 +1857,7 @@ mozart stevens amerique - 360 + 390 /tmp targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpx310.epc.remote.conf tracking_area_code \"1\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpx310.epc.remote.conf mobile_country_code \"208\" @@ -1896,7 +1896,7 @@ $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 45; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue - while true; do var=`ifconfig ppp0` ;sleep 1; if [ "$var" != "" ]; then break; fi ; done ; sleep 5; iperf -u -c 192.172.0.1 -b 10Mbits/s -t 300 -B 192.172.0.2 + while true; do var=`ifconfig ppp0` ;sleep 1; if [ "$var" != "" ]; then break; fi ; done ; sleep 5; iperf -u -c 192.172.0.1 -b 10Mbits/s -t 330 -B 192.172.0.2 @@ -1936,7 +1936,7 @@ mozart stevens amerique - 360 + 390 /tmp targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpx310..conf tracking_area_code \"1\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpx310.conf mobile_country_code \"208\" @@ -1975,7 +1975,7 @@ $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 45; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue - while true; do var=`ifconfig ppp0` ;sleep 1; if [ "$var" != "" ]; then break; fi ; done ; sleep 5; iperf -u -c 192.172.0.1 -b 10Mbits/s -t 300 -B 192.172.0.2 + while true; do var=`ifconfig ppp0` ;sleep 1; if [ "$var" != "" ]; then break; fi ; done ; sleep 5; iperf -u -c 192.172.0.1 -b 10Mbits/s -t 330 -B 192.172.0.2 @@ -2014,7 +2014,7 @@ mozart stevens amerique - 360 + 390 /tmp targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.100PRB.usrpx310.conf tracking_area_code \"1\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.100PRB.usrpx310.conf mobile_country_code \"208\" @@ -2053,7 +2053,7 @@ $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 45; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue - while true; do var=`ifconfig ppp0` ;sleep 1; if [ "$var" != "" ]; then break; fi ; done ; sleep 5; iperf -u -c 192.172.0.1 -b 10Mbits/s -t 300 -B 192.172.0.2 + while true; do var=`ifconfig ppp0` ;sleep 1; if [ "$var" != "" ]; then break; fi ; done ; sleep 5; iperf -u -c 192.172.0.1 -b 10Mbits/s -t 330 -B 192.172.0.2 @@ -2092,7 +2092,7 @@ mozart stevens amerique - 360 + 390 /tmp targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpx310.epc.remote.conf tracking_area_code \"1\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpx310.epc.remote.conf mobile_country_code \"208\" @@ -2155,7 +2155,7 @@ /opt/hss_sim0609/starthss >> /dev/null ; sleep 3000 - sleep 60; iperf -u -c 192.172.0.2 -b 10Mbits/s -t 300 -B 192.172.0.1 + sleep 60; iperf -u -c 192.172.0.2 -b 10Mbits/s -t 330 -B 192.172.0.1 True @@ -2169,7 +2169,7 @@ mozart stevens amerique - 360 + 390 /tmp targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpx310.conf tracking_area_code \"1\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpx310.conf mobile_country_code \"208\" @@ -2232,7 +2232,7 @@ /opt/hss_sim0609/starthss >> /dev/null ; sleep 3000 - sleep 60; iperf -u -c 192.172.0.2 -b 10Mbits/s -t 300 -B 192.172.0.1 + sleep 60; iperf -u -c 192.172.0.2 -b 10Mbits/s -t 330 -B 192.172.0.1 True @@ -2246,7 +2246,7 @@ mozart stevens amerique - 360 + 390 /tmp targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.100PRB.usrpx310.epc.conf tracking_area_code \"1\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.100PRB.usrpx310.epc.conf mobile_country_code \"208\" @@ -2309,7 +2309,7 @@ /opt/hss_sim0609/starthss >> /dev/null ; sleep 3000 - sleep 60; iperf -u -c 192.172.0.2 -b 10Mbits/s -t 300 -B 192.172.0.1 + sleep 60; iperf -u -c 192.172.0.2 -b 10Mbits/s -t 330 -B 192.172.0.1 True @@ -2326,7 +2326,7 @@ calisson stevens amerique - 360 + 390 /tmp targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.conf tracking_area_code \"1\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.conf mobile_country_code \"208\" @@ -2365,7 +2365,7 @@ $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 45; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue - while true; do var=`ifconfig ppp0` ;sleep 1; if [ "$var" != "" ]; then break; fi ; done ; sleep 5; iperf -u -c 192.172.0.1 -b 10Mbits/s -t 300 -B 192.172.0.2 + while true; do var=`ifconfig ppp0` ;sleep 1; if [ "$var" != "" ]; then break; fi ; done ; sleep 5; iperf -u -c 192.172.0.1 -b 10Mbits/s -t 330 -B 192.172.0.2 @@ -2405,7 +2405,7 @@ calisson stevens amerique - 360 + 390 /tmp targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.conf tracking_area_code \"1\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.conf mobile_country_code \"208\" @@ -2444,7 +2444,7 @@ $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 45; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue - while true; do var=`ifconfig ppp0` ;sleep 1; if [ "$var" != "" ]; then break; fi ; done ; sleep 5; iperf -u -c 192.172.0.1 -b 10Mbits/s -t 300 -B 192.172.0.2 + while true; do var=`ifconfig ppp0` ;sleep 1; if [ "$var" != "" ]; then break; fi ; done ; sleep 5; iperf -u -c 192.172.0.1 -b 10Mbits/s -t 330 -B 192.172.0.2 @@ -2483,7 +2483,7 @@ calisson stevens amerique - 360 + 390 /tmp targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.conf tracking_area_code \"1\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.conf mobile_country_code \"208\" @@ -2522,7 +2522,7 @@ $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 45; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue - while true; do var=`ifconfig ppp0` ;sleep 1; if [ "$var" != "" ]; then break; fi ; done ; sleep 5; iperf -u -c 192.172.0.1 -b 10Mbits/s -t 300 -B 192.172.0.2 + while true; do var=`ifconfig ppp0` ;sleep 1; if [ "$var" != "" ]; then break; fi ; done ; sleep 5; iperf -u -c 192.172.0.1 -b 10Mbits/s -t 330 -B 192.172.0.2 @@ -2561,7 +2561,7 @@ calisson stevens amerique - 360 + 390 /tmp targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.conf tracking_area_code \"1\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.conf mobile_country_code \"208\" @@ -2624,7 +2624,7 @@ /opt/hss_sim0609/starthss >> /dev/null ; sleep 3000 - sleep 60; iperf -u -c 192.172.0.2 -b 10Mbits/s -t 300 -B 192.172.0.1 + sleep 60; iperf -u -c 192.172.0.2 -b 10Mbits/s -t 330 -B 192.172.0.1 True @@ -2638,7 +2638,7 @@ calisson stevens amerique - 360 + 390 /tmp targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.conf tracking_area_code \"1\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.conf mobile_country_code \"208\" @@ -2701,7 +2701,7 @@ /opt/hss_sim0609/starthss >> /dev/null ; sleep 3000 - sleep 60; iperf -u -c 192.172.0.2 -b 10Mbits/s -t 300 -B 192.172.0.1 + sleep 60; iperf -u -c 192.172.0.2 -b 10Mbits/s -t 330 -B 192.172.0.1 True @@ -2715,7 +2715,7 @@ calisson stevens amerique - 360 + 390 /tmp targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.conf tracking_area_code \"1\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.conf mobile_country_code \"208\" @@ -2778,7 +2778,7 @@ /opt/hss_sim0609/starthss >> /dev/null ; sleep 3000 - sleep 60; iperf -u -c 192.172.0.2 -b 10Mbits/s -t 300 -B 192.172.0.1 + sleep 60; iperf -u -c 192.172.0.2 -b 10Mbits/s -t 330 -B 192.172.0.1 True From dd2177ecd5235c1b9c765b38d0c3aef1417b1020 Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Sun, 27 Dec 2015 14:56:07 +0100 Subject: [PATCH 046/263] fixed a bug due to wrong conf file --- cmake_targets/autotests/test_case_list.xml | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/cmake_targets/autotests/test_case_list.xml b/cmake_targets/autotests/test_case_list.xml index 519ee2c9de..b6addddd03 100644 --- a/cmake_targets/autotests/test_case_list.xml +++ b/cmake_targets/autotests/test_case_list.xml @@ -2248,16 +2248,16 @@ amerique 390 /tmp - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.100PRB.usrpx310.epc.conf tracking_area_code \"1\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.100PRB.usrpx310.epc.conf mobile_country_code \"208\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.100PRB.usrpx310.epc.conf mobile_network_code \"92\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.100PRB.usrpx310.epc.conf N_RB_DL 100 - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.100PRB.usrpx310.epc.conf mme_ip_address "ipv4=\"192.168.12.26\";ipv6=\"192:168:30::17\";active=\"yes\";preference=\"ipv4\";" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.100PRB.usrpx310.epc.conf downlink_frequency 2660000000L - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.100PRB.usrpx310.epc.conf uplink_frequency_offset -120000000 - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.100PRB.usrpx310.epc.conf frame_type \"FDD\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.100PRB.usrpx310.epc.conf nb_antennas_rx 1 - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.100PRB.usrpx310.epc.conf nb_antennas_tx 1 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.100PRB.usrpx310.conf tracking_area_code \"1\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.100PRB.usrpx310.conf mobile_country_code \"208\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.100PRB.usrpx310.conf mobile_network_code \"92\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.100PRB.usrpx310.conf N_RB_DL 100 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.100PRB.usrpx310.conf mme_ip_address "ipv4=\"192.168.12.26\";ipv6=\"192:168:30::17\";active=\"yes\";preference=\"ipv4\";" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.100PRB.usrpx310.conf downlink_frequency 2660000000L + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.100PRB.usrpx310.conf uplink_frequency_offset -120000000 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.100PRB.usrpx310.conf frame_type \"FDD\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.100PRB.usrpx310.conf nb_antennas_rx 1 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.100PRB.usrpx310.conf nb_antennas_tx 1 targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.100PRB.usrpx310.conf ENB_INTERFACE_NAME_FOR_S1_MME \"eth0\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.100PRB.usrpx310.conf ENB_IPV4_ADDRESS_FOR_S1_MME \"192.168.12.111/24\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.100PRB.usrpx310.conf ENB_INTERFACE_NAME_FOR_S1U \"eth0\" @@ -2268,7 +2268,7 @@ sudo -E -S /usr/local/bin/niusrprio_pcie start ; dmesg|tail $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem - -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.100PRB.usrpx310.epc.conf + -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.100PRB.usrpx310.conf From 0a9f80bd675d416d30fafe717729127b77083cad Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Sun, 27 Dec 2015 15:58:15 +0100 Subject: [PATCH 047/263] wrapper for iperf scripts --- cmake_targets/autotests/test_case_list.xml | 96 +++++++++++----------- cmake_targets/autotests/tools/iperf_script | 22 +++++ 2 files changed, 70 insertions(+), 48 deletions(-) create mode 100755 cmake_targets/autotests/tools/iperf_script diff --git a/cmake_targets/autotests/test_case_list.xml b/cmake_targets/autotests/test_case_list.xml index b6addddd03..edc7ba05ab 100644 --- a/cmake_targets/autotests/test_case_list.xml +++ b/cmake_targets/autotests/test_case_list.xml @@ -902,7 +902,7 @@ $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 45; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue - while true; do var=`ifconfig ppp0` ;sleep 1; if [ "$var" != "" ]; then break; fi ; done ; sleep 5; iperf -u -c 192.172.0.1 -b 10Mbits/s -t 330 -B 192.172.0.2 + $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 1 ppp0 -u -c 192.172.0.1 -b 10Mbits/s -t 330 -B 192.172.0.2 @@ -926,7 +926,7 @@ /opt/hss_sim0609/starthss >> /dev/null ; sleep 3000 - sleep 5; iperf -s -i 1 -u -f m -B 192.172.0.1 + $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 5 lo -s -i 1 -u -f m -B 192.172.0.1 throughput_test min=1.0Mbits/sec max=1.0Mbits/sec average=1.0Mbits/sec duration=300.0s @@ -986,7 +986,7 @@ $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 45; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue - while true; do var=`ifconfig ppp0` ;sleep 1; if [ "$var" != "" ]; then break; fi ; done ; sleep 5; iperf -u -c 192.172.0.1 -b 10Mbits/s -t 330 -B 192.172.0.2 + $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 1 ppp0 -u -c 192.172.0.1 -b 10Mbits/s -t 330 -B 192.172.0.2 @@ -1010,7 +1010,7 @@ /opt/hss_sim0609/starthss >> /dev/null ; sleep 3000 - sleep 5; iperf -s -i 1 -u -f m -B 192.172.0.1 + $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 5 lo -s -i 1 -u -f m -B 192.172.0.1 throughput_test min=1.0Mbits/sec max=1.0Mbits/sec average=1.0Mbits/sec duration=300.0s @@ -1069,7 +1069,7 @@ $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 45; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue - while true; do var=`ifconfig ppp0` ;sleep 1; if [ "$var" != "" ]; then break; fi ; done ; sleep 5; iperf -u -c 192.172.0.1 -b 10Mbits/s -t 330 -B 192.172.0.2 + $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 1 ppp0 -u -c 192.172.0.1 -b 10Mbits/s -t 330 -B 192.172.0.2 @@ -1093,7 +1093,7 @@ /opt/hss_sim0609/starthss >> /dev/null ; sleep 3000 - sleep 5; iperf -s -i 1 -u -f m -B 192.172.0.1 + $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 5 lo -s -i 1 -u -f m -B 192.172.0.1 throughput_test min=1.0Mbits/sec max=1.0Mbits/sec average=1.0Mbits/sec duration=300.0s @@ -1152,7 +1152,7 @@ $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 45; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue - while true; do var=`ifconfig ppp0` ;sleep 1; if [ "$var" != "" ]; then break; fi ; done ; sleep 5; iperf -s -i 1 -u -f m -B 192.172.0.2 + $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 1 ppp0 -s -i 1 -u -f m -B 192.172.0.2 True sudo -S -E $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue @@ -1176,7 +1176,7 @@ /opt/hss_sim0609/starthss >> /dev/null ; sleep 3000 - sleep 60; iperf -u -c 192.172.0.2 -b 10Mbits/s -t 330 -B 192.172.0.1 + $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 60 lo -u -c 192.172.0.2 -b 10Mbits/s -t 330 -B 192.172.0.1 True @@ -1234,7 +1234,7 @@ $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 45; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue - while true; do var=`ifconfig ppp0` ;sleep 1; if [ "$var" != "" ]; then break; fi ; done ; sleep 5; iperf -s -i 1 -u -f m -B 192.172.0.2 + $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 1 ppp0 -s -i 1 -u -f m -B 192.172.0.2 throughput_test min=8.0Mbits/sec max=9.0Mbits/sec average=8.5Mbits/sec duration=300.0s @@ -1259,7 +1259,7 @@ /opt/hss_sim0609/starthss >> /dev/null ; sleep 3000 - sleep 60; iperf -u -c 192.172.0.2 -b 10Mbits/s -t 330 -B 192.172.0.1 + $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 60 lo -u -c 192.172.0.2 -b 10Mbits/s -t 330 -B 192.172.0.1 True @@ -1317,7 +1317,7 @@ $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 45; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue - while true; do var=`ifconfig ppp0` ;sleep 1; if [ "$var" != "" ]; then break; fi ; done ; sleep 5; iperf -s -i 1 -u -f m -B 192.172.0.2 + $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 1 ppp0 -s -i 1 -u -f m -B 192.172.0.2 throughput_test min=15.0Mbits/sec max=15.0Mbits/sec average=15.0Mbits/sec duration=300.0s @@ -1342,7 +1342,7 @@ /opt/hss_sim0609/starthss >> /dev/null ; sleep 3000 - sleep 60; iperf -u -c 192.172.0.2 -b 10Mbits/s -t 330 -B 192.172.0.1 + $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 60 lo -u -c 192.172.0.2 -b 10Mbits/s -t 330 -B 192.172.0.1 True @@ -1401,7 +1401,7 @@ $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 45; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue - while true; do var=`ifconfig ppp0` ;sleep 1; if [ "$var" != "" ]; then break; fi ; done ; sleep 5; iperf -u -c 192.172.0.1 -b 10Mbits/s -t 330 -B 192.172.0.2 + $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 1 ppp0 -u -c 192.172.0.1 -b 10Mbits/s -t 330 -B 192.172.0.2 @@ -1425,7 +1425,7 @@ /opt/hss_sim0609/starthss >> /dev/null ; sleep 3000 - sleep 5; iperf -s -i 1 -u -f m -B 192.172.0.1 + $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 5 lo iperf -s -i 1 -u -f m -B 192.172.0.1 throughput_test min=1.0Mbits/sec max=1.0Mbits/sec average=1.0Mbits/sec duration=300.0s @@ -1485,7 +1485,7 @@ $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 45; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue - while true; do var=`ifconfig ppp0` ;sleep 1; if [ "$var" != "" ]; then break; fi ; done ; sleep 5; iperf -u -c 192.172.0.1 -b 10Mbits/s -t 330 -B 192.172.0.2 + $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 1 ppp0 -u -c 192.172.0.1 -b 10Mbits/s -t 330 -B 192.172.0.2 @@ -1509,7 +1509,7 @@ /opt/hss_sim0609/starthss >> /dev/null ; sleep 3000 - sleep 5; iperf -s -i 1 -u -f m -B 192.172.0.1 + $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 5 lo -s -i 1 -u -f m -B 192.172.0.1 throughput_test min=2.0Mbits/sec max=2.0Mbits/sec average=2.0Mbits/sec duration=300.0s @@ -1568,7 +1568,7 @@ $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 45; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue - while true; do var=`ifconfig ppp0` ;sleep 1; if [ "$var" != "" ]; then break; fi ; done ; sleep 5; iperf -u -c 192.172.0.1 -b 10Mbits/s -t 330 -B 192.172.0.2 + $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 1 ppp0 -u -c 192.172.0.1 -b 10Mbits/s -t 330 -B 192.172.0.2 @@ -1592,7 +1592,7 @@ /opt/hss_sim0609/starthss >> /dev/null ; sleep 3000 - sleep 5; iperf -s -i 1 -u -f m -B 192.172.0.1 + $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 5 lo -s -i 1 -u -f m -B 192.172.0.1 throughput_test min=4.0Mbits/sec max=4.0Mbits/sec average=4.0Mbits/sec duration=300.0s @@ -1651,7 +1651,7 @@ $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 45; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue - while true; do var=`ifconfig ppp0` ;sleep 1; if [ "$var" != "" ]; then break; fi ; done ; sleep 5; iperf -s -i 1 -u -f m -B 192.172.0.2 + $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 1 ppp0 -s -i 1 -u -f m -B 192.172.0.2 throughput_test min=4.0Mbits/sec max=5.0Mbits/sec average=4.0Mbits/sec duration=300.0s @@ -1676,7 +1676,7 @@ /opt/hss_sim0609/starthss >> /dev/null ; sleep 3000 - sleep 60; iperf -u -c 192.172.0.2 -b 10Mbits/s -t 330 -B 192.172.0.1 + $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 60 lo -u -c 192.172.0.2 -b 10Mbits/s -t 330 -B 192.172.0.1 True @@ -1734,7 +1734,7 @@ $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 45; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue - while true; do var=`ifconfig ppp0` ;sleep 1; if [ "$var" != "" ]; then break; fi ; done ; sleep 5; iperf -s -i 1 -u -f m -B 192.172.0.2 + $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 1 ppp0 -s -i 1 -u -f m -B 192.172.0.2 throughput_test min=8.0Mbits/sec max=9.0Mbits/sec average=8.5Mbits/sec duration=300.0s @@ -1759,7 +1759,7 @@ /opt/hss_sim0609/starthss >> /dev/null ; sleep 3000 - sleep 60; iperf -u -c 192.172.0.2 -b 10Mbits/s -t 330 -B 192.172.0.1 + $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 60 lo -u -c 192.172.0.2 -b 10Mbits/s -t 330 -B 192.172.0.1 True @@ -1817,7 +1817,7 @@ $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 45; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue - while true; do var=`ifconfig ppp0` ;sleep 1; if [ "$var" != "" ]; then break; fi ; done ; sleep 5; iperf -s -i 1 -u -f m -B 192.172.0.2 + $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 1 ppp0 -s -i 1 -u -f m -B 192.172.0.2 throughput_test min=15.0Mbits/sec max=15.0Mbits/sec average=15.0Mbits/sec duration=300.0s @@ -1842,7 +1842,7 @@ /opt/hss_sim0609/starthss >> /dev/null ; sleep 3000 - sleep 60; iperf -u -c 192.172.0.2 -b 10Mbits/s -t 330 -B 192.172.0.1 + $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 60 lo -u -c 192.172.0.2 -b 10Mbits/s -t 330 -B 192.172.0.1 True @@ -1896,7 +1896,7 @@ $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 45; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue - while true; do var=`ifconfig ppp0` ;sleep 1; if [ "$var" != "" ]; then break; fi ; done ; sleep 5; iperf -u -c 192.172.0.1 -b 10Mbits/s -t 330 -B 192.172.0.2 + $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 1 ppp0 -u -c 192.172.0.1 -b 10Mbits/s -t 330 -B 192.172.0.2 @@ -1920,7 +1920,7 @@ /opt/hss_sim0609/starthss >> /dev/null ; sleep 3000 - sleep 5; iperf -s -i 1 -u -f m -B 192.172.0.1 + $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 5 lo -s -i 1 -u -f m -B 192.172.0.1 throughput_test min=1.0Mbits/sec max=1.0Mbits/sec average=1.0Mbits/sec duration=300.0s @@ -1975,7 +1975,7 @@ $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 45; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue - while true; do var=`ifconfig ppp0` ;sleep 1; if [ "$var" != "" ]; then break; fi ; done ; sleep 5; iperf -u -c 192.172.0.1 -b 10Mbits/s -t 330 -B 192.172.0.2 + $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 1 ppp0 -u -c 192.172.0.1 -b 10Mbits/s -t 330 -B 192.172.0.2 @@ -1999,7 +1999,7 @@ /opt/hss_sim0609/starthss >> /dev/null ; sleep 3000 - sleep 5; iperf -s -i 1 -u -f m -B 192.172.0.1 + $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 5 lo -s -i 1 -u -f m -B 192.172.0.1 throughput_test min=1.0Mbits/sec max=1.0Mbits/sec average=1.0Mbits/sec duration=300.0s @@ -2053,7 +2053,7 @@ $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 45; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue - while true; do var=`ifconfig ppp0` ;sleep 1; if [ "$var" != "" ]; then break; fi ; done ; sleep 5; iperf -u -c 192.172.0.1 -b 10Mbits/s -t 330 -B 192.172.0.2 + $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 1 ppp0 -u -c 192.172.0.1 -b 10Mbits/s -t 330 -B 192.172.0.2 @@ -2077,7 +2077,7 @@ /opt/hss_sim0609/starthss >> /dev/null ; sleep 3000 - sleep 5; iperf -s -i 1 -u -f m -B 192.172.0.1 + $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 5 lo -s -i 1 -u -f m -B 192.172.0.1 throughput_test min=1.0Mbits/sec max=1.0Mbits/sec average=1.0Mbits/sec duration=300.0s @@ -2131,7 +2131,7 @@ $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 45; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue - while true; do var=`ifconfig ppp0` ;sleep 1; if [ "$var" != "" ]; then break; fi ; done ; sleep 5; iperf -s -i 1 -u -f m -B 192.172.0.2 + $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 1 ppp0 -s -i 1 -u -f m -B 192.172.0.2 True sudo -S -E $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue @@ -2155,7 +2155,7 @@ /opt/hss_sim0609/starthss >> /dev/null ; sleep 3000 - sleep 60; iperf -u -c 192.172.0.2 -b 10Mbits/s -t 330 -B 192.172.0.1 + $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 60 lo -u -c 192.172.0.2 -b 10Mbits/s -t 330 -B 192.172.0.1 True @@ -2208,7 +2208,7 @@ $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 45; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue - while true; do var=`ifconfig ppp0` ;sleep 1; if [ "$var" != "" ]; then break; fi ; done ; sleep 5; iperf -s -i 1 -u -f m -B 192.172.0.2 + $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 1 ppp0 -s -i 1 -u -f m -B 192.172.0.2 True sudo -S -E $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue @@ -2232,7 +2232,7 @@ /opt/hss_sim0609/starthss >> /dev/null ; sleep 3000 - sleep 60; iperf -u -c 192.172.0.2 -b 10Mbits/s -t 330 -B 192.172.0.1 + $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 60 lo -u -c 192.172.0.2 -b 10Mbits/s -t 330 -B 192.172.0.1 True @@ -2285,7 +2285,7 @@ $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 45; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue - while true; do var=`ifconfig ppp0` ;sleep 1; if [ "$var" != "" ]; then break; fi ; done ; sleep 5; iperf -s -i 1 -u -f m -B 192.172.0.2 + $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 1 ppp0 -s -i 1 -u -f m -B 192.172.0.2 True sudo -S -E $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue @@ -2309,7 +2309,7 @@ /opt/hss_sim0609/starthss >> /dev/null ; sleep 3000 - sleep 60; iperf -u -c 192.172.0.2 -b 10Mbits/s -t 330 -B 192.172.0.1 + $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 60 lo -u -c 192.172.0.2 -b 10Mbits/s -t 330 -B 192.172.0.1 True @@ -2365,7 +2365,7 @@ $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 45; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue - while true; do var=`ifconfig ppp0` ;sleep 1; if [ "$var" != "" ]; then break; fi ; done ; sleep 5; iperf -u -c 192.172.0.1 -b 10Mbits/s -t 330 -B 192.172.0.2 + $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 1 ppp0 -u -c 192.172.0.1 -b 10Mbits/s -t 330 -B 192.172.0.2 @@ -2389,7 +2389,7 @@ /opt/hss_sim0609/starthss >> /dev/null ; sleep 3000 - sleep 5; iperf -s -i 1 -u -f m -B 192.172.0.1 + $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 5 lo -s -i 1 -u -f m -B 192.172.0.1 throughput_test min=1.0Mbits/sec max=1.0Mbits/sec average=1.0Mbits/sec duration=300.0s @@ -2444,7 +2444,7 @@ $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 45; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue - while true; do var=`ifconfig ppp0` ;sleep 1; if [ "$var" != "" ]; then break; fi ; done ; sleep 5; iperf -u -c 192.172.0.1 -b 10Mbits/s -t 330 -B 192.172.0.2 + $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 1 ppp0 -u -c 192.172.0.1 -b 10Mbits/s -t 330 -B 192.172.0.2 @@ -2468,7 +2468,7 @@ /opt/hss_sim0609/starthss >> /dev/null ; sleep 3000 - sleep 5; iperf -s -i 1 -u -f m -B 192.172.0.1 + $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 5 lo -s -i 1 -u -f m -B 192.172.0.1 throughput_test min=1.0Mbits/sec max=1.0Mbits/sec average=1.0Mbits/sec duration=300.0s @@ -2522,7 +2522,7 @@ $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 45; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue - while true; do var=`ifconfig ppp0` ;sleep 1; if [ "$var" != "" ]; then break; fi ; done ; sleep 5; iperf -u -c 192.172.0.1 -b 10Mbits/s -t 330 -B 192.172.0.2 + $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 1 ppp0 -u -c 192.172.0.1 -b 10Mbits/s -t 330 -B 192.172.0.2 @@ -2546,7 +2546,7 @@ /opt/hss_sim0609/starthss >> /dev/null ; sleep 3000 - sleep 5; iperf -s -i 1 -u -f m -B 192.172.0.1 + $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 5 lo -s -i 1 -u -f m -B 192.172.0.1 throughput_test min=1.0Mbits/sec max=1.0Mbits/sec average=1.0Mbits/sec duration=300.0s @@ -2600,7 +2600,7 @@ $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 45; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue - while true; do var=`ifconfig ppp0` ;sleep 1; if [ "$var" != "" ]; then break; fi ; done ; sleep 5; iperf -s -i 1 -u -f m -B 192.172.0.2 + $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 1 ppp0 -s -i 1 -u -f m -B 192.172.0.2 True sudo -S -E $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue @@ -2624,7 +2624,7 @@ /opt/hss_sim0609/starthss >> /dev/null ; sleep 3000 - sleep 60; iperf -u -c 192.172.0.2 -b 10Mbits/s -t 330 -B 192.172.0.1 + $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 60 lo -u -c 192.172.0.2 -b 10Mbits/s -t 330 -B 192.172.0.1 True @@ -2677,7 +2677,7 @@ $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 45; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue - while true; do var=`ifconfig ppp0` ;sleep 1; if [ "$var" != "" ]; then break; fi ; done ; sleep 5; iperf -s -i 1 -u -f m -B 192.172.0.2 + $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 1 ppp0 -s -i 1 -u -f m -B 192.172.0.2 True sudo -S -E $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue @@ -2701,7 +2701,7 @@ /opt/hss_sim0609/starthss >> /dev/null ; sleep 3000 - sleep 60; iperf -u -c 192.172.0.2 -b 10Mbits/s -t 330 -B 192.172.0.1 + $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 60 lo -u -c 192.172.0.2 -b 10Mbits/s -t 330 -B 192.172.0.1 True @@ -2754,7 +2754,7 @@ $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 45; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue - while true; do var=`ifconfig ppp0` ;sleep 1; if [ "$var" != "" ]; then break; fi ; done ; sleep 5; iperf -s -i 1 -u -f m -B 192.172.0.2 + $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 1 ppp0 -s -i 1 -u -f m -B 192.172.0.2 True sudo -S -E $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue @@ -2778,7 +2778,7 @@ /opt/hss_sim0609/starthss >> /dev/null ; sleep 3000 - sleep 60; iperf -u -c 192.172.0.2 -b 10Mbits/s -t 330 -B 192.172.0.1 + $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 60 lo -u -c 192.172.0.2 -b 10Mbits/s -t 330 -B 192.172.0.1 True diff --git a/cmake_targets/autotests/tools/iperf_script b/cmake_targets/autotests/tools/iperf_script new file mode 100755 index 0000000000..50f1947f78 --- /dev/null +++ b/cmake_targets/autotests/tools/iperf_script @@ -0,0 +1,22 @@ +#!/bin/bash + +#arg1 timeout to wait before running the script +#arg2 interface +#arg3 iperf arguments + +args=($*) +timeout=${args[0]} +iface=${args[1]} +iperf_args=(${args[@]:2}) + +#array=${1:-1} +echo "args = $array" +echo "timeout = $timeout" +echo "iface = $iface" +echo "iperf_args = ${iperf_args[@]}" + +sleep $timeout + +while true; do var=`ifconfig $iface` ;sleep 1; if [ "$var" != "" ]; then break; fi ; done ; sleep 5 + +iperf ${iperf_args[@]} From 3985b010768057ed6263bc37b612d8fb90c8b95b Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Sun, 27 Dec 2015 16:27:23 +0100 Subject: [PATCH 048/263] fixed minor bug in debug message printing --- cmake_targets/autotests/tools/iperf_script | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake_targets/autotests/tools/iperf_script b/cmake_targets/autotests/tools/iperf_script index 50f1947f78..ecd2f7a996 100755 --- a/cmake_targets/autotests/tools/iperf_script +++ b/cmake_targets/autotests/tools/iperf_script @@ -10,7 +10,7 @@ iface=${args[1]} iperf_args=(${args[@]:2}) #array=${1:-1} -echo "args = $array" +echo "args = ${args[@]}" echo "timeout = $timeout" echo "iface = $iface" echo "iperf_args = ${iperf_args[@]}" From 918f0069ec51cec5cd3cc0900a2099e9cf1b11ad Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Sun, 27 Dec 2015 16:56:46 +0100 Subject: [PATCH 049/263] added script for setting openair-cn root path --- .../autotests/run_exec_lte-softmodem_tests.py | 4 +- cmake_targets/autotests/test_case_list.xml | 48 +++++++++---------- 2 files changed, 26 insertions(+), 26 deletions(-) diff --git a/cmake_targets/autotests/run_exec_lte-softmodem_tests.py b/cmake_targets/autotests/run_exec_lte-softmodem_tests.py index 5a4fca3524..363eea4e38 100644 --- a/cmake_targets/autotests/run_exec_lte-softmodem_tests.py +++ b/cmake_targets/autotests/run_exec_lte-softmodem_tests.py @@ -693,7 +693,7 @@ def handle_testcaseclass_softmodem (testcase, oldprogramList, logdirOAI5GRepo , task_EPC_compile = ' ( uname -a ; date \n' task_EPC_compile = task_EPC_compile + 'array_exec_pid=()' + '\n' - task_EPC_compile = task_EPC_compile + 'cd ' + logdirOpenaircnRepo + '\n' + task_EPC_compile = task_EPC_compile + 'cd ' + logdirOpenaircnRepo + ' ; source oaienv \n' task_EPC_compile = task_EPC_compile + update_config_file(oai_EPC, EPC_config_file, logdirOpenaircnRepo, logdirOpenaircnRepo+'/TEST/autotests/tools/search_repl.py') + '\n' task_EPC_compile = task_EPC_compile + 'source BUILD/TOOLS/build_helper \n' if EPC_compile_prog != "": @@ -705,7 +705,7 @@ def handle_testcaseclass_softmodem (testcase, oldprogramList, logdirOAI5GRepo , task_EPC = ' ( uname -a ; date \n' task_EPC = task_EPC + 'array_exec_pid=()' + '\n' - task_EPC = task_EPC + 'cd ' + logdirOpenaircnRepo + '\n' + task_EPC = task_EPC + 'cd ' + logdirOpenaircnRepo + '; source oaienv\n' task_EPC = task_EPC + 'source BUILD/TOOLS/build_helper \n' if EPC_pre_exec != "": task_EPC = task_EPC + ' ( date; ' + EPC_pre_exec + ' '+ EPC_pre_exec_args + ' ) > ' + logfile_pre_exec_EPC + ' 2>&1 \n' diff --git a/cmake_targets/autotests/test_case_list.xml b/cmake_targets/autotests/test_case_list.xml index edc7ba05ab..2fc88c6a7d 100644 --- a/cmake_targets/autotests/test_case_list.xml +++ b/cmake_targets/autotests/test_case_list.xml @@ -926,7 +926,7 @@ /opt/hss_sim0609/starthss >> /dev/null ; sleep 3000 - $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 5 lo -s -i 1 -u -f m -B 192.172.0.1 + $OPENAIRCN_DIR/TEST/autotests/tools/iperf_script 5 lo -s -i 1 -u -f m -B 192.172.0.1 throughput_test min=1.0Mbits/sec max=1.0Mbits/sec average=1.0Mbits/sec duration=300.0s @@ -1010,7 +1010,7 @@ /opt/hss_sim0609/starthss >> /dev/null ; sleep 3000 - $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 5 lo -s -i 1 -u -f m -B 192.172.0.1 + $OPENAIRCN_DIR/TEST/autotests/tools/iperf_script 5 lo -s -i 1 -u -f m -B 192.172.0.1 throughput_test min=1.0Mbits/sec max=1.0Mbits/sec average=1.0Mbits/sec duration=300.0s @@ -1093,7 +1093,7 @@ /opt/hss_sim0609/starthss >> /dev/null ; sleep 3000 - $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 5 lo -s -i 1 -u -f m -B 192.172.0.1 + $OPENAIRCN_DIR/TEST/autotests/tools/iperf_script 5 lo -s -i 1 -u -f m -B 192.172.0.1 throughput_test min=1.0Mbits/sec max=1.0Mbits/sec average=1.0Mbits/sec duration=300.0s @@ -1176,7 +1176,7 @@ /opt/hss_sim0609/starthss >> /dev/null ; sleep 3000 - $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 60 lo -u -c 192.172.0.2 -b 10Mbits/s -t 330 -B 192.172.0.1 + $OPENAIRCN_DIR/TEST/autotests/tools/iperf_script 60 lo -u -c 192.172.0.2 -b 10Mbits/s -t 330 -B 192.172.0.1 True @@ -1259,7 +1259,7 @@ /opt/hss_sim0609/starthss >> /dev/null ; sleep 3000 - $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 60 lo -u -c 192.172.0.2 -b 10Mbits/s -t 330 -B 192.172.0.1 + $OPENAIRCN_DIR/TEST/autotests/tools/iperf_script 60 lo -u -c 192.172.0.2 -b 10Mbits/s -t 330 -B 192.172.0.1 True @@ -1342,7 +1342,7 @@ /opt/hss_sim0609/starthss >> /dev/null ; sleep 3000 - $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 60 lo -u -c 192.172.0.2 -b 10Mbits/s -t 330 -B 192.172.0.1 + $OPENAIRCN_DIR/TEST/autotests/tools/iperf_script 60 lo -u -c 192.172.0.2 -b 10Mbits/s -t 330 -B 192.172.0.1 True @@ -1425,7 +1425,7 @@ /opt/hss_sim0609/starthss >> /dev/null ; sleep 3000 - $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 5 lo iperf -s -i 1 -u -f m -B 192.172.0.1 + $OPENAIRCN_DIR/TEST/autotests/tools/iperf_script 5 lo iperf -s -i 1 -u -f m -B 192.172.0.1 throughput_test min=1.0Mbits/sec max=1.0Mbits/sec average=1.0Mbits/sec duration=300.0s @@ -1509,7 +1509,7 @@ /opt/hss_sim0609/starthss >> /dev/null ; sleep 3000 - $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 5 lo -s -i 1 -u -f m -B 192.172.0.1 + $OPENAIRCN_DIR/TEST/autotests/tools/iperf_script 5 lo -s -i 1 -u -f m -B 192.172.0.1 throughput_test min=2.0Mbits/sec max=2.0Mbits/sec average=2.0Mbits/sec duration=300.0s @@ -1592,7 +1592,7 @@ /opt/hss_sim0609/starthss >> /dev/null ; sleep 3000 - $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 5 lo -s -i 1 -u -f m -B 192.172.0.1 + $OPENAIRCN_DIR/TEST/autotests/tools/iperf_script 5 lo -s -i 1 -u -f m -B 192.172.0.1 throughput_test min=4.0Mbits/sec max=4.0Mbits/sec average=4.0Mbits/sec duration=300.0s @@ -1676,7 +1676,7 @@ /opt/hss_sim0609/starthss >> /dev/null ; sleep 3000 - $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 60 lo -u -c 192.172.0.2 -b 10Mbits/s -t 330 -B 192.172.0.1 + $OPENAIRCN_DIR/TEST/autotests/tools/iperf_script 60 lo -u -c 192.172.0.2 -b 10Mbits/s -t 330 -B 192.172.0.1 True @@ -1759,7 +1759,7 @@ /opt/hss_sim0609/starthss >> /dev/null ; sleep 3000 - $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 60 lo -u -c 192.172.0.2 -b 10Mbits/s -t 330 -B 192.172.0.1 + $OPENAIRCN_DIR/TEST/autotests/tools/iperf_script 60 lo -u -c 192.172.0.2 -b 10Mbits/s -t 330 -B 192.172.0.1 True @@ -1842,7 +1842,7 @@ /opt/hss_sim0609/starthss >> /dev/null ; sleep 3000 - $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 60 lo -u -c 192.172.0.2 -b 10Mbits/s -t 330 -B 192.172.0.1 + $OPENAIRCN_DIR/TEST/autotests/tools/iperf_script 60 lo -u -c 192.172.0.2 -b 10Mbits/s -t 330 -B 192.172.0.1 True @@ -1920,7 +1920,7 @@ /opt/hss_sim0609/starthss >> /dev/null ; sleep 3000 - $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 5 lo -s -i 1 -u -f m -B 192.172.0.1 + $OPENAIRCN_DIR/TEST/autotests/tools/iperf_script 5 lo -s -i 1 -u -f m -B 192.172.0.1 throughput_test min=1.0Mbits/sec max=1.0Mbits/sec average=1.0Mbits/sec duration=300.0s @@ -1999,7 +1999,7 @@ /opt/hss_sim0609/starthss >> /dev/null ; sleep 3000 - $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 5 lo -s -i 1 -u -f m -B 192.172.0.1 + $OPENAIRCN_DIR/TEST/autotests/tools/iperf_script 5 lo -s -i 1 -u -f m -B 192.172.0.1 throughput_test min=1.0Mbits/sec max=1.0Mbits/sec average=1.0Mbits/sec duration=300.0s @@ -2077,7 +2077,7 @@ /opt/hss_sim0609/starthss >> /dev/null ; sleep 3000 - $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 5 lo -s -i 1 -u -f m -B 192.172.0.1 + $OPENAIRCN_DIR/TEST/autotests/tools/iperf_script 5 lo -s -i 1 -u -f m -B 192.172.0.1 throughput_test min=1.0Mbits/sec max=1.0Mbits/sec average=1.0Mbits/sec duration=300.0s @@ -2155,7 +2155,7 @@ /opt/hss_sim0609/starthss >> /dev/null ; sleep 3000 - $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 60 lo -u -c 192.172.0.2 -b 10Mbits/s -t 330 -B 192.172.0.1 + $OPENAIRCN_DIR/TEST/autotests/tools/iperf_script 60 lo -u -c 192.172.0.2 -b 10Mbits/s -t 330 -B 192.172.0.1 True @@ -2232,7 +2232,7 @@ /opt/hss_sim0609/starthss >> /dev/null ; sleep 3000 - $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 60 lo -u -c 192.172.0.2 -b 10Mbits/s -t 330 -B 192.172.0.1 + $OPENAIRCN_DIR/TEST/autotests/tools/iperf_script 60 lo -u -c 192.172.0.2 -b 10Mbits/s -t 330 -B 192.172.0.1 True @@ -2309,7 +2309,7 @@ /opt/hss_sim0609/starthss >> /dev/null ; sleep 3000 - $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 60 lo -u -c 192.172.0.2 -b 10Mbits/s -t 330 -B 192.172.0.1 + $OPENAIRCN_DIR/TEST/autotests/tools/iperf_script 60 lo -u -c 192.172.0.2 -b 10Mbits/s -t 330 -B 192.172.0.1 True @@ -2389,7 +2389,7 @@ /opt/hss_sim0609/starthss >> /dev/null ; sleep 3000 - $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 5 lo -s -i 1 -u -f m -B 192.172.0.1 + $OPENAIRCN_DIR/TEST/autotests/tools/iperf_script 5 lo -s -i 1 -u -f m -B 192.172.0.1 throughput_test min=1.0Mbits/sec max=1.0Mbits/sec average=1.0Mbits/sec duration=300.0s @@ -2468,7 +2468,7 @@ /opt/hss_sim0609/starthss >> /dev/null ; sleep 3000 - $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 5 lo -s -i 1 -u -f m -B 192.172.0.1 + $OPENAIRCN_DIR/TEST/autotests/tools/iperf_script 5 lo -s -i 1 -u -f m -B 192.172.0.1 throughput_test min=1.0Mbits/sec max=1.0Mbits/sec average=1.0Mbits/sec duration=300.0s @@ -2546,7 +2546,7 @@ /opt/hss_sim0609/starthss >> /dev/null ; sleep 3000 - $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 5 lo -s -i 1 -u -f m -B 192.172.0.1 + $OPENAIRCN_DIR/TEST/autotests/tools/iperf_script 5 lo -s -i 1 -u -f m -B 192.172.0.1 throughput_test min=1.0Mbits/sec max=1.0Mbits/sec average=1.0Mbits/sec duration=300.0s @@ -2624,7 +2624,7 @@ /opt/hss_sim0609/starthss >> /dev/null ; sleep 3000 - $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 60 lo -u -c 192.172.0.2 -b 10Mbits/s -t 330 -B 192.172.0.1 + $OPENAIRCN_DIR/TEST/autotests/tools/iperf_script 60 lo -u -c 192.172.0.2 -b 10Mbits/s -t 330 -B 192.172.0.1 True @@ -2701,7 +2701,7 @@ /opt/hss_sim0609/starthss >> /dev/null ; sleep 3000 - $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 60 lo -u -c 192.172.0.2 -b 10Mbits/s -t 330 -B 192.172.0.1 + $OPENAIRCN_DIR/TEST/autotests/tools/iperf_script 60 lo -u -c 192.172.0.2 -b 10Mbits/s -t 330 -B 192.172.0.1 True @@ -2778,7 +2778,7 @@ /opt/hss_sim0609/starthss >> /dev/null ; sleep 3000 - $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 60 lo -u -c 192.172.0.2 -b 10Mbits/s -t 330 -B 192.172.0.1 + $OPENAIRCN_DIR/TEST/autotests/tools/iperf_script 60 lo -u -c 192.172.0.2 -b 10Mbits/s -t 330 -B 192.172.0.1 True From 7c90db34626a0258ba298e3b90d97696f6919b70 Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Sun, 27 Dec 2015 17:08:51 +0100 Subject: [PATCH 050/263] updated to kill iperf_script --- cmake_targets/autotests/test_case_list.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake_targets/autotests/test_case_list.xml b/cmake_targets/autotests/test_case_list.xml index 2fc88c6a7d..1318407040 100644 --- a/cmake_targets/autotests/test_case_list.xml +++ b/cmake_targets/autotests/test_case_list.xml @@ -6,7 +6,7 @@ https://gitlab.eurecom.fr/oai/openair-cn.git develop feature-17-test_framework - oaisim* oaisim_nos1* lte-softmodem* lte-softmodem-nos1* mme_gw* run_epc* run_hss* iperf* hss hss_sim configure_cots_bandrich_ue* wvdial* run_exec_autotests* iperf iperf_client iperf_server + oaisim* oaisim_nos1* lte-softmodem* lte-softmodem-nos1* mme_gw* run_epc* run_hss* hss hss_sim configure_cots_bandrich_ue* wvdial* run_exec_autotests* iperf iperf_script /opt/ltebox/tools/stop_ltebox $OPENAIR_DIR/cmake_targets/build_oai -w EXMIMO -c; sudo -S -E $OPENAIR_DIR/cmake_targets/tools/stop_exmimo2; dmesg|tail 36000 From 0046ed5d60591e220364f9247b38d1f440f0a2a0 Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Mon, 28 Dec 2015 16:33:50 +0100 Subject: [PATCH 051/263] disable lowlatency by default --- cmake_targets/build_oai | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake_targets/build_oai b/cmake_targets/build_oai index 165a2c6b0c..3243e4b1a2 100755 --- a/cmake_targets/build_oai +++ b/cmake_targets/build_oai @@ -45,7 +45,7 @@ MSC_GEN="False" XFORMS="False" PRINT_STATS="False" VCD_TIMING="False" -LOWLATENCY_FLAG_USER="True" +LOWLATENCY_FLAG_USER="False" REL="Rel10" HW="EXMIMO" NOS1=0 From 5a80a8cb1f3243e160667c9e1df28fadc15026d7 Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Mon, 28 Dec 2015 16:34:49 +0100 Subject: [PATCH 052/263] bugfixes to autotest framework --- cmake_targets/autotests/core.py | 5 +++-- cmake_targets/autotests/openair.py | 4 ++-- cmake_targets/autotests/tools/configure_cots_bandrich_ue.py | 2 +- 3 files changed, 6 insertions(+), 5 deletions(-) diff --git a/cmake_targets/autotests/core.py b/cmake_targets/autotests/core.py index 8881781144..ee53438207 100644 --- a/cmake_targets/autotests/core.py +++ b/cmake_targets/autotests/core.py @@ -240,8 +240,9 @@ class core: # print rsp if (rsp.find(expect) == -1): return 'OK' - - raise log.err(self.failed(command, expect,debug)) + else: + print "command = " + cmd + "expect = " + expect + "rsp = " + rsp + raise log.err(self.failed(command, expect,debug)) # **************************send_wait************************* diff --git a/cmake_targets/autotests/openair.py b/cmake_targets/autotests/openair.py index e8d07ba1e1..8427735c61 100644 --- a/cmake_targets/autotests/openair.py +++ b/cmake_targets/autotests/openair.py @@ -111,8 +111,8 @@ class openair(core): error = error + ' In function: ' + sys._getframe().f_code.co_name + ': *** Caught exception: ' + str(e.__class__) + " : " + str( e) error = error + traceback.format_exc() print error - print "Retrying again in 60 seconds" - time.sleep(60) + print "Retrying again in 1 seconds" + time.sleep(1) #sys.exit(1) def connect2(self, username, password, prompt='$'): diff --git a/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py b/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py index ae25013f52..aa041360b7 100755 --- a/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py +++ b/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py @@ -127,7 +127,7 @@ def start_ue () : ip = IPRoute() idx = ip.link_lookup(ifname=iface)[0] os.system ('route add 192.172.0.1 ppp0') - os.system ('ping -c 5 192.172.0.1') + os.system ('ping 192.172.0.1') break except Exception, e: error = ' Interface ' + iface + 'does not exist...' From fdaed481c3b2f6cf4ee2764e8d6ff120c3dc93ad Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Mon, 28 Dec 2015 19:00:14 +0100 Subject: [PATCH 053/263] added root file Gitlab CI --- .gitlab-ci.yml | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 .gitlab-ci.yml diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml new file mode 100644 index 0000000000..8f044aeea7 --- /dev/null +++ b/.gitlab-ci.yml @@ -0,0 +1,2 @@ +job1: + script: "echo $PWD" From dc32904bb18617bcd6a290eded8a95797bce3ea8 Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Mon, 28 Dec 2015 20:22:15 +0100 Subject: [PATCH 054/263] gitlab CI update for testing username --- .gitlab-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 8f044aeea7..453f29f000 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,2 +1,2 @@ job1: - script: "echo $PWD" + script: "echo $PWD; echo $USER" From 3015eba1b2d58775af821b3ed0f895d0503a698d Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Mon, 28 Dec 2015 20:25:51 +0100 Subject: [PATCH 055/263] gitlab CI test for custom environment variables --- .gitlab-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 453f29f000..63bc7e06b6 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,2 +1,2 @@ job1: - script: "echo $PWD; echo $USER" + script: "echo $PWD; echo $USER ; echo $OAI_USER" From e6321929c663a73f36153a006a04e3ffc4987446 Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Mon, 28 Dec 2015 21:32:39 +0100 Subject: [PATCH 056/263] test GiLab runner for gitlab branch --- .gitlab-ci.yml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 63bc7e06b6..022f399748 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,2 +1,6 @@ job1: - script: "echo $PWD; echo $USER ; echo $OAI_USER" + script: + - echo $PWD + - echo $USER + - echo $OAI_USER + - git rev-parse --abbrev-ref HEAD From cf3e75fb5a4674807b411a5dd243ae255f517492 Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Mon, 28 Dec 2015 21:40:40 +0100 Subject: [PATCH 057/263] test Gitlab CI for branch --- .gitlab-ci.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 022f399748..46b3f78a67 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -4,3 +4,5 @@ job1: - echo $USER - echo $OAI_USER - git rev-parse --abbrev-ref HEAD + - git symbolic-ref HEAD + - git branch From 8724c5062f960c6ec016c4e5da81b5c502a395d3 Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Mon, 28 Dec 2015 21:44:24 +0100 Subject: [PATCH 058/263] Gitlab CI test for branch --- .gitlab-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 46b3f78a67..82ddbd5a25 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -4,5 +4,5 @@ job1: - echo $USER - echo $OAI_USER - git rev-parse --abbrev-ref HEAD - - git symbolic-ref HEAD + - git rev-parse HEAD - git branch From c6cb903c42b0bc3ba059bfcb98cfd6f5e5e7d6a8 Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Mon, 28 Dec 2015 21:51:01 +0100 Subject: [PATCH 059/263] Gitlab CI test for branch --- .gitlab-ci.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 82ddbd5a25..f501458091 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -6,3 +6,4 @@ job1: - git rev-parse --abbrev-ref HEAD - git rev-parse HEAD - git branch + - git show-ref --head From 826ef8dafb70582ccdb1dba3ea51c3d442d45923 Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Tue, 29 Dec 2015 14:10:21 +0100 Subject: [PATCH 060/263] test for Gitlab CI --- .gitlab-ci.yml | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index f501458091..7b7eabe206 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -3,7 +3,22 @@ job1: - echo $PWD - echo $USER - echo $OAI_USER + - echo $NFS_SHARE_DIR + - echo $EXTERNAL_SHARE_DIR - git rev-parse --abbrev-ref HEAD - - git rev-parse HEAD - - git branch - - git show-ref --head + - git_head=`git rev-parse HEAD` + - echo $git_head + - tmp=`git show-ref --head | grep $git_head` + - tmp=(${tmp///// }) + - git_branch=${tmp[@]:(-1)} + - echo $git_branch + - source oaienv + - env|grep OPENAIR + - #$OPENAIR_DIR/cmake_targets/autotests/run_exec_lte-softmodem_tests.py -r $OAI_EXTRA_ARGS >& $OPENAIR_DIR/cmake_targets/autotests/python_autotest.log + - mv $OPENAIR_DIR/cmake_targets/autotests/python_autotest.log $OPENAIR_DIR/cmake_targets/autotests/log/python_autotest.log + - NFS_TEST_RESULTS_DIR=$NFS_SHARE_DIR/$git_branch/$git_head + - EXTERNAL_SHARE_RESULTS_DIR=$EXTERNAL_SHARE_DIR/$git_branch/$git_head + - echo $NFS_TEST_RESULTS_DIR + - echo $EXTERNAL_SHARE_RESULTS_DIR + - sshpass -p "$OAI_PASS" rsync $OPENAIR_DIR/cmake_targets/autotests/log/ $OAI_USER@localhost:$NFS_TEST_RESULTS_DIR + - sshpass -p "$OAI_PASS" rsync $OPENAIR_DIR/cmake_targets/autotests/log/ $OAI_USER@localhost:$EXTERNAL_SHARE_DIR From 02c4317aaf0a744269ddb0dddfe62928c6a303ac Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Tue, 29 Dec 2015 14:21:17 +0100 Subject: [PATCH 061/263] test for Gitlab CI --- .gitlab-ci.yml | 15 +-------------- 1 file changed, 1 insertion(+), 14 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 7b7eabe206..7cef3c6e9a 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -8,17 +8,4 @@ job1: - git rev-parse --abbrev-ref HEAD - git_head=`git rev-parse HEAD` - echo $git_head - - tmp=`git show-ref --head | grep $git_head` - - tmp=(${tmp///// }) - - git_branch=${tmp[@]:(-1)} - - echo $git_branch - - source oaienv - - env|grep OPENAIR - - #$OPENAIR_DIR/cmake_targets/autotests/run_exec_lte-softmodem_tests.py -r $OAI_EXTRA_ARGS >& $OPENAIR_DIR/cmake_targets/autotests/python_autotest.log - - mv $OPENAIR_DIR/cmake_targets/autotests/python_autotest.log $OPENAIR_DIR/cmake_targets/autotests/log/python_autotest.log - - NFS_TEST_RESULTS_DIR=$NFS_SHARE_DIR/$git_branch/$git_head - - EXTERNAL_SHARE_RESULTS_DIR=$EXTERNAL_SHARE_DIR/$git_branch/$git_head - - echo $NFS_TEST_RESULTS_DIR - - echo $EXTERNAL_SHARE_RESULTS_DIR - - sshpass -p "$OAI_PASS" rsync $OPENAIR_DIR/cmake_targets/autotests/log/ $OAI_USER@localhost:$NFS_TEST_RESULTS_DIR - - sshpass -p "$OAI_PASS" rsync $OPENAIR_DIR/cmake_targets/autotests/log/ $OAI_USER@localhost:$EXTERNAL_SHARE_DIR + From 6087394eafc9fe25bbe28b7fe0fc18e99437fb28 Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Tue, 29 Dec 2015 14:31:07 +0100 Subject: [PATCH 062/263] test for Gitlab CI --- .gitlab-ci.yml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 7cef3c6e9a..9e2dfddc33 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -8,4 +8,9 @@ job1: - git rev-parse --abbrev-ref HEAD - git_head=`git rev-parse HEAD` - echo $git_head - + - tmp=`git show-ref --head | grep $git_head` + - tmp=(${tmp///// }) + - git_branch=${tmp[@]:(-1)} + - echo $git_branch + - source oaienv + - echo $OPENAIR_DIR From 9b93e9836e54c204f52ba397f602654dbbe0cbc4 Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Tue, 29 Dec 2015 14:39:33 +0100 Subject: [PATCH 063/263] test for Gitlab CI --- .gitlab-ci.yml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 9e2dfddc33..0f55506b98 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -14,3 +14,12 @@ job1: - echo $git_branch - source oaienv - echo $OPENAIR_DIR + - NFS_TEST_RESULTS_DIR=$NFS_SHARE_DIR/$git_branch/$git_head + - EXTERNAL_SHARE_RESULTS_DIR=$EXTERNAL_SHARE_DIR/$git_branch/$git_head + - echo $NFS_TEST_RESULTS_DIR + - echo $EXTERNAL_SHARE_RESULTS_DIR + - sshpass -p "$OAI_PASS" rsync $OPENAIR_DIR/cmake_targets/autotests/log/ $OAI_USER@localhost:$NFS_TEST_RESULTS_DIR + - sshpass -p "$OAI_PASS" rsync $OPENAIR_DIR/cmake_targets/autotests/log/ $OAI_USER@localhost:$EXTERNAL_SHARE_DIR + #$OPENAIR_DIR/cmake_targets/autotests/run_exec_lte-softmodem_tests.py -r $OAI_EXTRA_ARGS >& $OPENAIR_DIR/cmake_targets/autotests/python_autotest.log + #mv $OPENAIR_DIR/cmake_targets/autotests/python_autotest.log $OPENAIR_DIR/cmake_targets/autotests/log/python_autotest.log + From 69a3d14432a1bbb9f2e4e8dbe82d93a818c9f9b7 Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Tue, 29 Dec 2015 15:15:09 +0100 Subject: [PATCH 064/263] test for Gitlab CI --- .gitlab-ci.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 0f55506b98..f80437065d 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -18,8 +18,8 @@ job1: - EXTERNAL_SHARE_RESULTS_DIR=$EXTERNAL_SHARE_DIR/$git_branch/$git_head - echo $NFS_TEST_RESULTS_DIR - echo $EXTERNAL_SHARE_RESULTS_DIR - - sshpass -p "$OAI_PASS" rsync $OPENAIR_DIR/cmake_targets/autotests/log/ $OAI_USER@localhost:$NFS_TEST_RESULTS_DIR - - sshpass -p "$OAI_PASS" rsync $OPENAIR_DIR/cmake_targets/autotests/log/ $OAI_USER@localhost:$EXTERNAL_SHARE_DIR + - sshpass -p "$OAI_PASS" rsync -avz -e "ssh -o StrictHostKeyChecking=no " $OPENAIR_DIR/cmake_targets/autotests/log/ $OAI_USER@localhost:$NFS_TEST_RESULTS_DIR + - sshpass -p "$OAI_PASS" rsync -avz -e "ssh -o StrictHostKeyChecking=no " $OPENAIR_DIR/cmake_targets/autotests/log/ $OAI_USER@localhost:$EXTERNAL_SHARE_DIR #$OPENAIR_DIR/cmake_targets/autotests/run_exec_lte-softmodem_tests.py -r $OAI_EXTRA_ARGS >& $OPENAIR_DIR/cmake_targets/autotests/python_autotest.log #mv $OPENAIR_DIR/cmake_targets/autotests/python_autotest.log $OPENAIR_DIR/cmake_targets/autotests/log/python_autotest.log From 945f9c07b65f253e1da59c2bb8edcf851daa9af4 Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Tue, 29 Dec 2015 16:43:07 +0100 Subject: [PATCH 065/263] added sshpass for GitLab CI support --- cmake_targets/tools/build_helper | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cmake_targets/tools/build_helper b/cmake_targets/tools/build_helper index a1fefec3ce..be318ceb68 100755 --- a/cmake_targets/tools/build_helper +++ b/cmake_targets/tools/build_helper @@ -280,7 +280,8 @@ check_install_oai_software() { python-pip \ pydb \ wvdial \ - python-numpy + python-numpy \ + sshpass $SUDO update-alternatives --set liblapack.so /usr/lib/atlas-base/atlas/liblapack.so if [ `lsb_release -rs` = '12.04' ] ; then install_nettle_from_source From 3bdbb91796fd834f87a7070a2bbf0ea128400ef5 Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Tue, 29 Dec 2015 16:44:19 +0100 Subject: [PATCH 066/263] added sudo for ALU LTEBox --- cmake_targets/autotests/test_case_list.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmake_targets/autotests/test_case_list.xml b/cmake_targets/autotests/test_case_list.xml index 1318407040..8b8d5c01e0 100644 --- a/cmake_targets/autotests/test_case_list.xml +++ b/cmake_targets/autotests/test_case_list.xml @@ -1,13 +1,13 @@ calisson mozart stevens nano amerique - /mnt/sradio/TEST_RESULTS + /mnt/sradio/TEST_RESULTS/ https://gitlab.eurecom.fr/oai/openairinterface5g.git https://gitlab.eurecom.fr/oai/openair-cn.git develop feature-17-test_framework oaisim* oaisim_nos1* lte-softmodem* lte-softmodem-nos1* mme_gw* run_epc* run_hss* hss hss_sim configure_cots_bandrich_ue* wvdial* run_exec_autotests* iperf iperf_script - /opt/ltebox/tools/stop_ltebox + sudo -S -E /opt/ltebox/tools/stop_ltebox $OPENAIR_DIR/cmake_targets/build_oai -w EXMIMO -c; sudo -S -E $OPENAIR_DIR/cmake_targets/tools/stop_exmimo2; dmesg|tail 36000 0104+ 015502 015505 015506 015507 015508 015508 015509 015510 015511 015600 015700 016102 016105 From 1fc405ddc811312da2216b6b8ed98035f6788c79 Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Tue, 29 Dec 2015 16:55:36 +0100 Subject: [PATCH 067/263] updates to integrate with GitLab CI --- .gitlab-ci.yml | 6 +- .../autotests/run_exec_lte-softmodem_tests.py | 205 ++++++++++++------ 2 files changed, 147 insertions(+), 64 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index f80437065d..88c25a1ca6 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -18,8 +18,10 @@ job1: - EXTERNAL_SHARE_RESULTS_DIR=$EXTERNAL_SHARE_DIR/$git_branch/$git_head - echo $NFS_TEST_RESULTS_DIR - echo $EXTERNAL_SHARE_RESULTS_DIR + - mkdir -p $NFS_TEST_RESULTS_DIR + - mkdir -p $EXTERNAL_SHARE_RESULTS_DIR + - $OPENAIR_DIR/cmake_targets/autotests/run_exec_lte-softmodem_tests.py -r $OAI_EXTRA_ARGS >& $OPENAIR_DIR/cmake_targets/autotests/python_autotest.log + - mv $OPENAIR_DIR/cmake_targets/autotests/python_autotest.log $OPENAIR_DIR/cmake_targets/autotests/log/python_autotest.log - sshpass -p "$OAI_PASS" rsync -avz -e "ssh -o StrictHostKeyChecking=no " $OPENAIR_DIR/cmake_targets/autotests/log/ $OAI_USER@localhost:$NFS_TEST_RESULTS_DIR - sshpass -p "$OAI_PASS" rsync -avz -e "ssh -o StrictHostKeyChecking=no " $OPENAIR_DIR/cmake_targets/autotests/log/ $OAI_USER@localhost:$EXTERNAL_SHARE_DIR - #$OPENAIR_DIR/cmake_targets/autotests/run_exec_lte-softmodem_tests.py -r $OAI_EXTRA_ARGS >& $OPENAIR_DIR/cmake_targets/autotests/python_autotest.log - #mv $OPENAIR_DIR/cmake_targets/autotests/python_autotest.log $OPENAIR_DIR/cmake_targets/autotests/log/python_autotest.log diff --git a/cmake_targets/autotests/run_exec_lte-softmodem_tests.py b/cmake_targets/autotests/run_exec_lte-softmodem_tests.py index 363eea4e38..c7449bcac3 100644 --- a/cmake_targets/autotests/run_exec_lte-softmodem_tests.py +++ b/cmake_targets/autotests/run_exec_lte-softmodem_tests.py @@ -252,11 +252,20 @@ def update_config_file(oai, config_string, logdirRepo, python_script): return cmd #result = oai.send_recv(cmd) -def SSHSessionWrapper(machine, username, key_file, password, logdir_remote_testcase, logdir_local_base): - while True: +def SSHSessionWrapper(machine, username, key_file, password, logdir_remote_testcase, logdir_local_base, operation): + max_tries = 100 + i=0 + while i <= max_tries: + i = i +1 try: ssh = SSHSession(machine , username, key_file, password) - ssh.get_all(logdir_remote_testcase , logdir_local_base) + if operation == "get_all": + ssh.get_all(logdir_remote_testcase , logdir_local_base) + elif operation == "put_all": + ssh.put_all(logdir_remote_testcase , logdir_local_base) + else: + print "Error: Uknown operation in SSHSessionWrapper. Exiting now..." + sys.exit(1) break except Exception, e: error='' @@ -311,7 +320,7 @@ class oaiThread (threading.Thread): def run(self): try: oai = openair('localdomain',self.machine) - oai.connect(user, self.password) + oai.connect(self.username, self.password) print "Starting " + self.threadname + " on machine " + self.machine result = oai.send_recv(self.cmd, self.sudo, self.timeout) print "result = " + result @@ -320,14 +329,14 @@ class oaiThread (threading.Thread): except Exception, e: error='' error = error + ' In class oaiThread, function: ' + sys._getframe().f_code.co_name + ': *** Caught exception: ' + str(e.__class__) + " : " + str( e) - error = error + '\n threadID = ' + str(self.threadID) + '\n threadname = ' + self.threadname + '\n timeout = ' + self.timeout + '\n machine = ' + self.machine + '\n cmd = ' + self.cmd + '\n timeout = ' + str(self.timeout) + '\n' + error = error + '\n threadID = ' + str(self.threadID) + '\n threadname = ' + self.threadname + '\n timeout = ' + self.timeout + '\n machine = ' + self.machine + '\n cmd = ' + self.cmd + '\n timeout = ' + str(self.timeout) + '\n username = ' + self.username + '\n' error = error + traceback.format_exc() print error #This class runs test cases with class execution, compilatation class testCaseThread_generic (threading.Thread): - def __init__(self, threadID, name, machine, logdirOAI5GRepo, testcasename,oldprogramList, CleanupAluLteBox, password, timeout, ExmimoRfStop): + def __init__(self, threadID, name, machine, logdirOAI5GRepo, testcasename,oldprogramList, CleanupAluLteBox, user, password, timeout, ExmimoRfStop): threading.Thread.__init__(self) self.threadID = threadID self.name = name @@ -339,16 +348,17 @@ class testCaseThread_generic (threading.Thread): self.CleanupAluLteBox = CleanupAluLteBox self.password=password self.ExmimoRfStop = ExmimoRfStop + self.user = user def run(self): try: mypassword='' #addsudo = 'echo \'' + mypassword + '\' | sudo -S -E ' addpass = 'echo \'' + mypassword + '\' | ' - user = getpass.getuser() + #user = getpass.getuser() print "Starting test case : " + self.testcasename + " On machine " + self.machine + " timeout = " + str(self.timeout) oai = openair('localdomain',self.machine) - oai.connect(user, self.password) - cleanOldPrograms(oai, self.oldprogramList, self.CleanupAluLteBox, self.ExmimoRfStop) + oai.connect(self.user, self.password) + #cleanOldPrograms(oai, self.oldprogramList, self.CleanupAluLteBox, self.ExmimoRfStop) logdir_local = os.environ.get('OPENAIR_DIR') logdir_local_testcase = logdir_local +'/cmake_targets/autotests/log/'+ self.testcasename logdir_local_base = logdir_local +'/cmake_targets/autotests/log/' @@ -380,15 +390,15 @@ class testCaseThread_generic (threading.Thread): #Now we copy all the remote files #ssh = SSHSession(self.machine , username=user, key_file=None, password=self.password) #ssh.get_all(logdir_remote_testcase , logdir_local_base) - SSHSessionWrapper(self.machine, user, None, self.password, logdir_remote_testcase, logdir_local_base) + SSHSessionWrapper(self.machine, self.user, None, self.password, logdir_remote_testcase, logdir_local_base, "get_all") print "Finishing test case : " + self.testcasename + " On machine " + self.machine - cleanOldPrograms(oai, self.oldprogramList, self.CleanupAluLteBox, self.ExmimoRfStop) + #cleanOldPrograms(oai, self.oldprogramList, self.CleanupAluLteBox, self.ExmimoRfStop) #oai.kill(user,mypassword) oai.disconnect() except Exception, e: error='' error = error + ' In Class = testCaseThread_generic, function: ' + sys._getframe().f_code.co_name + ': *** Caught exception: ' + str(e.__class__) + " : " + str( e) - error = error + '\n threadID = ' + str(self.threadID) + '\n threadName = ' + self.name + '\n testcasename = ' + self.testcasename + '\n machine = ' + self.machine + '\n logdirOAI5GRepo = ' + self.logdirOAI5GRepo + '\n' + '\n timeout = ' + str(self.timeout) + error = error + '\n threadID = ' + str(self.threadID) + '\n threadName = ' + self.name + '\n testcasename = ' + self.testcasename + '\n machine = ' + self.machine + '\n logdirOAI5GRepo = ' + self.logdirOAI5GRepo + '\n' + '\n timeout = ' + str(self.timeout) + '\n user = ' + self.user error = error + traceback.format_exc() print error print "Continuing with next test case..." @@ -401,7 +411,7 @@ def addsudo (cmd, password=""): cmd = 'echo \'' + password + '\' | sudo -S -E bash -c \' ' + cmd + '\' ' return cmd -def handle_testcaseclass_generic (testcasename, threadListGeneric, oldprogramList, logdirOAI5GRepo, MachineList, password, CleanupAluLteBox,timeout, ExmimoRfStop): +def handle_testcaseclass_generic (testcasename, threadListGeneric, oldprogramList, logdirOAI5GRepo, MachineList, user, password, CleanupAluLteBox,timeout, ExmimoRfStop): try: mypassword=password MachineListFree=[] @@ -439,7 +449,7 @@ def handle_testcaseclass_generic (testcasename, threadListGeneric, oldprogramLis print "MachineListBusy = " + ','.join(MachineListBusy) print "MachineList = " + ','.join(MachineList) machine = MachineListFree[0] - thread = testCaseThread_generic(1,"Generic Thread_"+testcasename+"_"+ "machine_", machine, logdirOAI5GRepo, testcasename, oldprogramList, CleanupAluLteBox, password, timeout, ExmimoRfStop) + thread = testCaseThread_generic(1,"Generic Thread_"+testcasename+"_"+ "machine_", machine, logdirOAI5GRepo, testcasename, oldprogramList, CleanupAluLteBox, user, password, timeout, ExmimoRfStop) param={"thread_id":thread, "Machine":machine, "testcasename":testcasename} thread.start() threadListNew.append(param) @@ -447,7 +457,7 @@ def handle_testcaseclass_generic (testcasename, threadListGeneric, oldprogramLis except Exception, e: error='' error = error + ' In function: ' + sys._getframe().f_code.co_name + ': *** Caught exception: ' + str(e.__class__) + " : " + str( e) - error = error + '\n testcasename = ' + testcasename + '\n logdirOAI5GRepo = ' + logdirOAI5GRepo + '\n MachineList = ' + ','.join(MachineList) + '\n timeout = ' + str(timeout) + '\n' + error = error + '\n testcasename = ' + testcasename + '\n logdirOAI5GRepo = ' + logdirOAI5GRepo + '\n MachineList = ' + ','.join(MachineList) + '\n timeout = ' + str(timeout) + '\n' + 'user = ' + user error = error + traceback.format_exc() print error print "Continuing..." @@ -472,14 +482,14 @@ def wait_testcaseclass_generic_threads(threadListGeneric, timeout = 1): return threadListGenericNew #Function to handle test case class : lte-softmodem -def handle_testcaseclass_softmodem (testcase, oldprogramList, logdirOAI5GRepo , logdirOpenaircnRepo, MachineList, password, CleanUpAluLteBox, ExmimoRfStop): +def handle_testcaseclass_softmodem (testcase, oldprogramList, logdirOAI5GRepo , logdirOpenaircnRepo, MachineList, user, password, CleanUpAluLteBox, ExmimoRfStop): #We ignore the password sent to this function for secuirity reasons for password present in log files #It is recommended to add a line in /etc/sudoers that looks something like below. The line below will run sudo without password prompt # your_user_name ALL=(ALL:ALL) NOPASSWD: ALL mypassword='' #addsudo = 'echo \'' + mypassword + '\' | sudo -S -E ' addpass = 'echo \'' + mypassword + '\' | ' - user = getpass.getuser() + #user = getpass.getuser() testcasename = testcase.get('id') testcaseclass = testcase.findtext('class',default='') timeout_cmd = testcase.findtext('TimeOut_cmd',default='') @@ -763,10 +773,11 @@ def handle_testcaseclass_softmodem (testcase, oldprogramList, logdirOAI5GRepo , for t in threads: t.join() #Now we get the log files from remote machines on the local machine + cleanOldProgramsAllMachines([oai_eNB, oai_UE, oai_EPC] , oldprogramList, CleanUpAluLteBox, ExmimoRfStop) - cleanOldPrograms(oai_eNB, oldprogramList, CleanUpAluLteBox, ExmimoRfStop) - cleanOldPrograms(oai_UE, oldprogramList, CleanUpAluLteBox, ExmimoRfStop) - cleanOldPrograms(oai_EPC, oldprogramList, CleanUpAluLteBox, ExmimoRfStop) + #cleanOldPrograms(oai_eNB, oldprogramList, CleanUpAluLteBox, ExmimoRfStop) + #cleanOldPrograms(oai_UE, oldprogramList, CleanUpAluLteBox, ExmimoRfStop) + #cleanOldPrograms(oai_EPC, oldprogramList, CleanUpAluLteBox, ExmimoRfStop) logfile_UE_stop_script_out = logdir_UE + '/UE_stop_script_out' + '_' + str(run) + '_.log' logfile_UE_stop_script = logdir_local_testcase + '/UE_stop_script' + '_' + str(run) + '_.log' @@ -785,17 +796,17 @@ def handle_testcaseclass_softmodem (testcase, oldprogramList, logdirOAI5GRepo , print "Copying files from EPCMachine : " + EPCMachine + "logdir_EPC = " + logdir_EPC #ssh = SSHSession(EPCMachine , username=user, key_file=None, password=password) #ssh.get_all(logdir_EPC , logdir_local + '/cmake_targets/autotests/log/'+ testcasename) - SSHSessionWrapper(EPCMachine, user, None, password, logdir_EPC, logdir_local + '/cmake_targets/autotests/log/'+ testcasename) + SSHSessionWrapper(EPCMachine, user, None, password, logdir_EPC, logdir_local + '/cmake_targets/autotests/log/'+ testcasename, "get_all") print "Copying files from eNBMachine " + eNBMachine + "logdir_eNB = " + logdir_eNB #ssh = SSHSession(eNBMachine , username=user, key_file=None, password=password) #ssh.get_all(logdir_eNB, logdir_local + '/cmake_targets/autotests/log/'+ testcasename) - SSHSessionWrapper(eNBMachine, user, None, password, logdir_eNB, logdir_local + '/cmake_targets/autotests/log/'+ testcasename) + SSHSessionWrapper(eNBMachine, user, None, password, logdir_eNB, logdir_local + '/cmake_targets/autotests/log/'+ testcasename, "get_all") print "Copying files from UEMachine : " + UEMachine + "logdir_UE = " + logdir_UE #ssh = SSHSession(UEMachine , username=user, key_file=None, password=password) #ssh.get_all(logdir_UE , logdir_local + '/cmake_targets/autotests/log/'+ testcasename) - SSHSessionWrapper(UEMachine, user, None, password, logdir_UE, logdir_local + '/cmake_targets/autotests/log/'+ testcasename) + SSHSessionWrapper(UEMachine, user, None, password, logdir_UE, logdir_local + '/cmake_targets/autotests/log/'+ testcasename, "get_all") @@ -870,9 +881,39 @@ def search_test_case_group(testcasename, testcasegroup, test_case_exclude): return True return False +class oaiCleanOldProgramThread (threading.Thread): + def __init__(self, threadID, threadname, oai, CleanUpOldProgs, CleanUpAluLteBox, ExmimoRfStop): + threading.Thread.__init__(self) + self.threadID = threadID + self.threadname = threadname + self.oai = oai + self.CleanUpOldProgs = CleanUpOldProgs + self.CleanUpAluLteBox = CleanUpAluLteBox + self.ExmimoRfStop = ExmimoRfStop + def run(self): + try: + cleanOldPrograms(oai, CleanUpOldProgs, CleanUpAluLteBox, ExmimoRfStop) + except Exception, e: + error='' + error = error + ' In class oaiCleanOldProgramThread, function: ' + sys._getframe().f_code.co_name + ': *** Caught exception: ' + str(e.__class__) + " : " + str( e) + error = error + '\n threadID = ' + str(self.threadID) + '\n threadname = ' + self.threadname + '\n CleanUpOldProgs = ' + self.CleanUpOldProgs + '\n CleanUpAluLteBox = ' + self.CleanUpAluLteBox + '\n ExmimoRfStop = ' + self.ExmimoRfStop + '\n' + error = error + traceback.format_exc() + print error + def cleanOldProgramsAllMachines(oai_list, CleanOldProgs, CleanUpAluLteBox, ExmimoRfStop): - for index in oai_list: - cleanOldPrograms(oai_list[index], CleanUpOldProgs, CleanUpAluLteBox, ExmimoRfStop) + threadId=0 + threadList=[] + for oai in oai_list: + threadName="cleanup_thread_"+str(threadId) + thread=append(oaiCleanOldProgramThread(threadId, threadName, oai, CleanUpOldProgs, CleanUpAluLteBox, ExmimoRfStop)) + threadList.append(thread) + thread.start() + threadId = threadId + 1 + for t in threadList: + t.join() + + + #thread1 = myThread(1, "Thread-1", 1) debug = 0 @@ -880,18 +921,11 @@ pw ='' i = 0 dlsim=0 localshell=0 -is_compiled = 0 timeout=2000 GitOAI5GRepoBranch='' -xmlInputFile="./test_case_list.xml" -NFSResultsDir = '/mnt/sradio' -cleanupOldProgramsScript = '$OPENAIR_DIR/cmake_targets/autotests/tools/remove_old_programs.bash' -testcasegroup='' -cleanUpRemoteMachines=False -logdir = '/tmp/' + 'OAITestFrameWork-' + getpass.getuser() + '/' -logdirOAI5GRepo = logdir + 'openairinterface5g/' -logdirOpenaircnRepo = logdir + 'openair-cn/' - +GitOAI5GHeadVersion='' +user='' +pw='' openairdir_local = os.environ.get('OPENAIR_DIR') if openairdir_local is None: print "Environment variable OPENAIR_DIR not set correctly" @@ -907,9 +941,6 @@ while i < len (sys.argv): debug = 1 elif arg == '-dd': debug = 2 - elif arg == '-p' : - prompt2 = sys.argv[i+1] - i = i +1 elif arg == '-r': flag_remove_logdir=True elif arg == '-w' : @@ -919,8 +950,6 @@ while i < len (sys.argv): dlsim = 1 elif arg == '-l' : localshell = 1 - elif arg == '-c' : - is_compiled = 1 elif arg == '-t' : timeout = sys.argv[i+1] i = i +1 @@ -932,10 +961,27 @@ while i < len (sys.argv): elif arg == '-5GRepoBranch': GitOAI5GRepoBranch = sys.argv[i+1] i = i +1 + elif arg == '-5GRepoHeadVersion': + GitOAI5GHeadVersion = sys.argv[i+1] + #We now find the branch that corresponds to this Git Head Commit + cmd = "git show-ref --head " + " | grep " + GitOAI5GHeadVersion + cmd_out = subprocess.check_output ([cmd], shell=True) + cmd_out=cmd_out.replace("\n","") + cmd_out = cmd_out.split('/') + GitOAI5GRepoBranch = cmd_out[-1] + if GitOAI5GRepoBranch == '': + print "Error extracting GitBranch from head commit. Exiting now..." + sys.exit(1) + i = i +1 + elif arg == '-u': + user = sys.argv[i+1] + i = i +1 + elif arg == '-p': + pw = sys.argv[i+1] + i = i +1 elif arg == '-h' : print "-d: low debug level" print "-dd: high debug level" - print "-p: set the prompt" print "-r: Remove the log directory in autotests" print "-g: Run test cases in a group" print "-c: Run cleanup scripts on remote machines" @@ -943,6 +989,9 @@ while i < len (sys.argv): print "-l: use local shell instead of ssh connection" print "-t: set the time out in second for commands" print "-5GRepoBranch: Branch for OAI 5G Repository to run tests (overrides the branch in test_case_list.xml)" + print "-5GRepoHeadVersion: Head commit on which to run tests (overrides the branch in test_case_list.xml)" + print "-u: use the user name passed as argument" + print "-p: use the password passed as an argument" sys.exit() else : print "Unrecongnized Option: <" + arg + ">. Use -h to see valid options" @@ -967,12 +1016,6 @@ except KeyError: print "Please set the environment variable OPENAIR_TARGETS in the .bashrc" sys.exit(1) -if flag_remove_logdir == True: - print "Removing directory: " + locallogdir - os.system(' rm -fr ' + locallogdir + '; mkdir -p ' + locallogdir ) - - - paramiko_logfile = os.path.expandvars('$OPENAIR_DIR/cmake_targets/autotests/log/paramiko.log') res=os.system(' echo > ' + paramiko_logfile) paramiko.util.log_to_file(paramiko_logfile) @@ -980,14 +1023,29 @@ paramiko.util.log_to_file(paramiko_logfile) # get the oai object host = os.uname()[1] #oai = openair('localdomain','calisson') -oai_list = {} - +oai_list = [] #start_time = time.time() # datetime.datetime.now() -user = getpass.getuser() +if user=='': + user = getpass.getuser() +if password=='': + pw = getpass.getpass() print "host = " + host print "user = " + user -pw=getpass.getpass() +xmlInputFile=os.environ.get('OPENAIR_DIR')+"/cmake_targets/autotests/test_case_list.xml" +NFSResultsDir = '/mnt/sradio' +cleanupOldProgramsScript = '$OPENAIR_DIR/cmake_targets/autotests/tools/remove_old_programs.bash' +testcasegroup='' +cleanUpRemoteMachines=False +logdir = '/tmp/' + 'OAITestFrameWork-' + user + '/' +logdirOAI5GRepo = logdir + 'openairinterface5g/' +logdirOpenaircnRepo = logdir + 'openair-cn/' + +if flag_remove_logdir == True: + print "Removing directory: " + locallogdir + os.system(' rm -fr ' + locallogdir + '; mkdir -p ' + locallogdir ) + +#pw=getpass.getpass() #Now we parse the xml file for basic configuration xmlTree = ET.parse(xmlInputFile) @@ -1011,15 +1069,19 @@ Timeout_execution = int (xmlRoot.findtext('Timeout_execution')) MachineListGeneric = xmlRoot.findtext('MachineListGeneric',default='') TestCaseExclusionList = xmlRoot.findtext('TestCaseExclusionList',default='') ExmimoRfStop = xmlRoot.findtext('ExmimoRfStop',default='') + print "MachineList = " + MachineList print "GitOpenair-cnRepo = " + GitOpenaircnRepo print "GitOAI5GRepo = " + GitOAI5GRepo print "GitOAI5GBranch = " + GitOAI5GRepoBranch print "GitOpenaircnRepoBranch = " + GitOpenaircnRepoBranch print "NFSResultsShare = " + NFSResultsShare -cmd = "git show-ref --heads -s "+ GitOAI5GRepoBranch -GitOAI5GHeadVersion = subprocess.check_output ([cmd], shell=True) -GitOAI5GHeadVersion=GitOAI5GHeadVersion.replace("\n","") + +if GitOAI5GHeadVersion == '': + cmd = "git show-ref --heads -s "+ GitOAI5GRepoBranch + GitOAI5GHeadVersion = subprocess.check_output ([cmd], shell=True) + GitOAI5GHeadVersion=GitOAI5GHeadVersion.replace("\n","") + print "GitOAI5GHeadVersion = " + GitOAI5GHeadVersion print "CleanUpOldProgs = " + CleanUpOldProgs print "Timeout_execution = " + str(Timeout_execution) @@ -1028,13 +1090,17 @@ if GitOAI5GHeadVersion == '': print "Error getting the OAI5GBranch Head version...Exiting" sys.exit() +NFSTestsResultsDir = NFSResultsShare + '/'+ GitOAI5GRepoBranch + '/' + GitOAI5GHeadVersion + '/' + +print "NFSResultsShareDir = " + NFSResultsShareDir + MachineList = MachineList.split() MachineListGeneric = MachineListGeneric.split() -index=0 +#index=0 for machine in MachineList: - oai_list[index] = openair('localdomain',machine) - index = index + 1 + oai_list.append( openair('localdomain',machine)) + #index = index + 1 #myThread (1,"sddsf", 1) @@ -1129,7 +1195,7 @@ print "cpu freq(MHz): " + str(cpu_freq) + "timeout(s): " + str(timeout) #We now prepare the machines for testing #index=0 threads_init_setup=[] -for index in oai_list: +for oai in oai_list: try: print "setting up machine: " + MachineList[index] #print oai_list[oai].send_recv('echo \''+pw+'\' |sudo -S -v') @@ -1137,7 +1203,7 @@ for index in oai_list: #print oai_list[oai].send_recv('who am i') #cleanUpPrograms(oai_list[oai] cmd = 'sudo -S -E rm -fr ' + logdir + ' ; mkdir -p ' + logdir - result = oai_list[index].send_recv(cmd) + result = oai[index].send_recv(cmd) setuplogfile = logdir + '/setup_log_' + MachineList[index] + '_.txt' setup_script = locallogdir + '/setup_script_' + MachineList[index] + '_.txt' @@ -1274,11 +1340,11 @@ for testcase in testcaseList: print "eNBMachine : " + eNBMachine + "UEMachine : " + UEMachine + "EPCMachine : " + EPCMachine + "MachineList : " + ','.join(MachineList) print "testcasename = " + testcasename + " class = " + testcaseclass threadListGlobal = wait_testcaseclass_generic_threads(threadListGlobal, Timeout_execution) - handle_testcaseclass_softmodem (testcase, CleanUpOldProgs, logdirOAI5GRepo, logdirOpenaircnRepo, MachineList, pw, CleanUpAluLteBox, ExmimoRfStop ) + handle_testcaseclass_softmodem (testcase, CleanUpOldProgs, logdirOAI5GRepo, logdirOpenaircnRepo, MachineList, user, pw, CleanUpAluLteBox, ExmimoRfStop ) elif (testcaseclass == 'compilation'): - threadListGlobal = handle_testcaseclass_generic (testcasename, threadListGlobal, CleanUpOldProgs, logdirOAI5GRepo, MachineListGeneric, pw, CleanUpAluLteBox,Timeout_execution, ExmimoRfStop) + threadListGlobal = handle_testcaseclass_generic (testcasename, threadListGlobal, CleanUpOldProgs, logdirOAI5GRepo, MachineListGeneric, user, pw, CleanUpAluLteBox,Timeout_execution, ExmimoRfStop) elif (testcaseclass == 'execution'): - threadListGlobal = handle_testcaseclass_generic (testcasename, threadListGlobal, CleanUpOldProgs, logdirOAI5GRepo, MachineListGeneric, pw, CleanUpAluLteBox,ExmimoRfStop) + threadListGlobal = handle_testcaseclass_generic (testcasename, threadListGlobal, CleanUpOldProgs, logdirOAI5GRepo, MachineListGeneric, user, pw, CleanUpAluLteBox,ExmimoRfStop) else : print "Unknown test case class: " + testcaseclass sys.exit() @@ -1298,6 +1364,21 @@ print "Exiting the test cases execution now..." for t in threadListGlobal: t.join +cmd = "cat $OPENAIR_DIR/cmake_targets/autotests/log/*/*.xml > $OPENAIR_DIR/cmake_targets/autotests/log/results_autotests.xml " +os.system('cmd') + +print "Now copying files to NFS Share" +oai_localhost = openair('localdomain','localhost') +oai_localhost.connect(user,pw) +cmd = ' rm -fr ' + NFSTestsResultsDir + ' ; mkdir -p ' + NFSTestsResultsDir +res = oai_localhost.send_recv(cmd) +print "Deleting NFSTestResults Dir..." + res + +print "Copying files from GilabCI Runner Machine : " + host + "locallogdir = " + locallogdir + ", NFSTestsResultsDir = " + NFSTestsResultsDir +#ssh = SSHSession(UEMachine , username=user, key_file=None, password=password) +#ssh.get_all(logdir_UE , logdir_local + '/cmake_targets/autotests/log/'+ testcasename) +SSHSessionWrapper(UEMachine, user, None, password, NFSTestsResultsDir , locallogdir, "put_all") + sys.exit() #+ "class = "+ classx From 38ca126cdc466d4fe903b92e2e79cd0fd15c0d78 Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Tue, 29 Dec 2015 17:03:57 +0100 Subject: [PATCH 068/263] fixed a minor bug for python execution --- .gitlab-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 88c25a1ca6..fe6fc9dbc6 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -20,7 +20,7 @@ job1: - echo $EXTERNAL_SHARE_RESULTS_DIR - mkdir -p $NFS_TEST_RESULTS_DIR - mkdir -p $EXTERNAL_SHARE_RESULTS_DIR - - $OPENAIR_DIR/cmake_targets/autotests/run_exec_lte-softmodem_tests.py -r $OAI_EXTRA_ARGS >& $OPENAIR_DIR/cmake_targets/autotests/python_autotest.log + - python $OPENAIR_DIR/cmake_targets/autotests/run_exec_lte-softmodem_tests.py -r $OAI_EXTRA_ARGS >& $OPENAIR_DIR/cmake_targets/autotests/python_autotest.log - mv $OPENAIR_DIR/cmake_targets/autotests/python_autotest.log $OPENAIR_DIR/cmake_targets/autotests/log/python_autotest.log - sshpass -p "$OAI_PASS" rsync -avz -e "ssh -o StrictHostKeyChecking=no " $OPENAIR_DIR/cmake_targets/autotests/log/ $OAI_USER@localhost:$NFS_TEST_RESULTS_DIR - sshpass -p "$OAI_PASS" rsync -avz -e "ssh -o StrictHostKeyChecking=no " $OPENAIR_DIR/cmake_targets/autotests/log/ $OAI_USER@localhost:$EXTERNAL_SHARE_DIR From 3c455f7d38ebd7ed342f6467c985c1edc4361ed7 Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Tue, 29 Dec 2015 18:33:50 +0100 Subject: [PATCH 069/263] minor bugfix for paramiko logfile --- cmake_targets/autotests/run_exec_lte-softmodem_tests.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/cmake_targets/autotests/run_exec_lte-softmodem_tests.py b/cmake_targets/autotests/run_exec_lte-softmodem_tests.py index c7449bcac3..132fefe0c2 100644 --- a/cmake_targets/autotests/run_exec_lte-softmodem_tests.py +++ b/cmake_targets/autotests/run_exec_lte-softmodem_tests.py @@ -1016,9 +1016,7 @@ except KeyError: print "Please set the environment variable OPENAIR_TARGETS in the .bashrc" sys.exit(1) -paramiko_logfile = os.path.expandvars('$OPENAIR_DIR/cmake_targets/autotests/log/paramiko.log') -res=os.system(' echo > ' + paramiko_logfile) -paramiko.util.log_to_file(paramiko_logfile) + # get the oai object host = os.uname()[1] @@ -1045,6 +1043,10 @@ if flag_remove_logdir == True: print "Removing directory: " + locallogdir os.system(' rm -fr ' + locallogdir + '; mkdir -p ' + locallogdir ) +paramiko_logfile = os.path.expandvars('$OPENAIR_DIR/cmake_targets/autotests/log/paramiko.log') +res=os.system(' echo > ' + paramiko_logfile) +paramiko.util.log_to_file(paramiko_logfile) + #pw=getpass.getpass() #Now we parse the xml file for basic configuration From a3ab1a90f52620654b95fa58ace213545bae4530 Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Tue, 29 Dec 2015 19:01:52 +0100 Subject: [PATCH 070/263] minor bugfixes due to runtime errors --- cmake_targets/autotests/run_exec_lte-softmodem_tests.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/cmake_targets/autotests/run_exec_lte-softmodem_tests.py b/cmake_targets/autotests/run_exec_lte-softmodem_tests.py index 132fefe0c2..67b6daed66 100644 --- a/cmake_targets/autotests/run_exec_lte-softmodem_tests.py +++ b/cmake_targets/autotests/run_exec_lte-softmodem_tests.py @@ -1026,7 +1026,7 @@ oai_list = [] #start_time = time.time() # datetime.datetime.now() if user=='': user = getpass.getuser() -if password=='': +if pw=='': pw = getpass.getpass() print "host = " + host print "user = " + user @@ -1094,7 +1094,7 @@ if GitOAI5GHeadVersion == '': NFSTestsResultsDir = NFSResultsShare + '/'+ GitOAI5GRepoBranch + '/' + GitOAI5GHeadVersion + '/' -print "NFSResultsShareDir = " + NFSResultsShareDir +print "NFSTestsResultsDir = " + NFSTestsResultsDir MachineList = MachineList.split() MachineListGeneric = MachineListGeneric.split() @@ -1195,7 +1195,7 @@ print "cpu freq(MHz): " + str(cpu_freq) + "timeout(s): " + str(timeout) #print result #We now prepare the machines for testing -#index=0 +index=0 threads_init_setup=[] for oai in oai_list: try: @@ -1205,7 +1205,7 @@ for oai in oai_list: #print oai_list[oai].send_recv('who am i') #cleanUpPrograms(oai_list[oai] cmd = 'sudo -S -E rm -fr ' + logdir + ' ; mkdir -p ' + logdir - result = oai[index].send_recv(cmd) + result = oai.send_recv(cmd) setuplogfile = logdir + '/setup_log_' + MachineList[index] + '_.txt' setup_script = locallogdir + '/setup_script_' + MachineList[index] + '_.txt' @@ -1269,6 +1269,7 @@ for oai in oai_list: #print '\nCleaning Older running programs : ' + CleanUpOldProgs #cleanOldPrograms(oai_list[index], CleanUpOldProgs) + index = index + 1 except Exception, e: print 'There is error in one of the commands to setup the machine '+ MachineList[index] error='' From dc020be2c4324281aede3907a8802a74fb8a6fce Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Tue, 29 Dec 2015 19:16:40 +0100 Subject: [PATCH 071/263] added argument for passing GIT HEAD commit --- .gitlab-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index fe6fc9dbc6..092993340a 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -20,7 +20,7 @@ job1: - echo $EXTERNAL_SHARE_RESULTS_DIR - mkdir -p $NFS_TEST_RESULTS_DIR - mkdir -p $EXTERNAL_SHARE_RESULTS_DIR - - python $OPENAIR_DIR/cmake_targets/autotests/run_exec_lte-softmodem_tests.py -r $OAI_EXTRA_ARGS >& $OPENAIR_DIR/cmake_targets/autotests/python_autotest.log + - python $OPENAIR_DIR/cmake_targets/autotests/run_exec_lte-softmodem_tests.py -r -5GRepoHeadVersion $git_head $OAI_EXTRA_ARGS >& $OPENAIR_DIR/cmake_targets/autotests/python_autotest.log - mv $OPENAIR_DIR/cmake_targets/autotests/python_autotest.log $OPENAIR_DIR/cmake_targets/autotests/log/python_autotest.log - sshpass -p "$OAI_PASS" rsync -avz -e "ssh -o StrictHostKeyChecking=no " $OPENAIR_DIR/cmake_targets/autotests/log/ $OAI_USER@localhost:$NFS_TEST_RESULTS_DIR - sshpass -p "$OAI_PASS" rsync -avz -e "ssh -o StrictHostKeyChecking=no " $OPENAIR_DIR/cmake_targets/autotests/log/ $OAI_USER@localhost:$EXTERNAL_SHARE_DIR From d39f218215673ee39f2bf233092f97e0b69410ab Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Tue, 29 Dec 2015 19:38:57 +0100 Subject: [PATCH 072/263] added extra options for setting NFS SHARE --- .gitlab-ci.yml | 2 +- cmake_targets/autotests/run_exec_lte-softmodem_tests.py | 9 +++++++-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 092993340a..57c5c64ffb 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -20,7 +20,7 @@ job1: - echo $EXTERNAL_SHARE_RESULTS_DIR - mkdir -p $NFS_TEST_RESULTS_DIR - mkdir -p $EXTERNAL_SHARE_RESULTS_DIR - - python $OPENAIR_DIR/cmake_targets/autotests/run_exec_lte-softmodem_tests.py -r -5GRepoHeadVersion $git_head $OAI_EXTRA_ARGS >& $OPENAIR_DIR/cmake_targets/autotests/python_autotest.log + - python $OPENAIR_DIR/cmake_targets/autotests/run_exec_lte-softmodem_tests.py -r -5GRepoHeadVersion $git_head -n $NFS_SHARE_DIR $OAI_EXTRA_ARGS >& $OPENAIR_DIR/cmake_targets/autotests/python_autotest.log - mv $OPENAIR_DIR/cmake_targets/autotests/python_autotest.log $OPENAIR_DIR/cmake_targets/autotests/log/python_autotest.log - sshpass -p "$OAI_PASS" rsync -avz -e "ssh -o StrictHostKeyChecking=no " $OPENAIR_DIR/cmake_targets/autotests/log/ $OAI_USER@localhost:$NFS_TEST_RESULTS_DIR - sshpass -p "$OAI_PASS" rsync -avz -e "ssh -o StrictHostKeyChecking=no " $OPENAIR_DIR/cmake_targets/autotests/log/ $OAI_USER@localhost:$EXTERNAL_SHARE_DIR diff --git a/cmake_targets/autotests/run_exec_lte-softmodem_tests.py b/cmake_targets/autotests/run_exec_lte-softmodem_tests.py index 67b6daed66..2b7431a718 100644 --- a/cmake_targets/autotests/run_exec_lte-softmodem_tests.py +++ b/cmake_targets/autotests/run_exec_lte-softmodem_tests.py @@ -905,7 +905,7 @@ def cleanOldProgramsAllMachines(oai_list, CleanOldProgs, CleanUpAluLteBox, Exmim threadList=[] for oai in oai_list: threadName="cleanup_thread_"+str(threadId) - thread=append(oaiCleanOldProgramThread(threadId, threadName, oai, CleanUpOldProgs, CleanUpAluLteBox, ExmimoRfStop)) + thread=oaiCleanOldProgramThread(threadId, threadName, oai, CleanUpOldProgs, CleanUpAluLteBox, ExmimoRfStop) threadList.append(thread) thread.start() threadId = threadId + 1 @@ -926,6 +926,7 @@ GitOAI5GRepoBranch='' GitOAI5GHeadVersion='' user='' pw='' +NFSResultsShare='' openairdir_local = os.environ.get('OPENAIR_DIR') if openairdir_local is None: print "Environment variable OPENAIR_DIR not set correctly" @@ -979,6 +980,9 @@ while i < len (sys.argv): elif arg == '-p': pw = sys.argv[i+1] i = i +1 + elif arg == '-n': + NFSResultsShare = sys.argv[i+1] + i = i +1 elif arg == '-h' : print "-d: low debug level" print "-dd: high debug level" @@ -992,6 +996,7 @@ while i < len (sys.argv): print "-5GRepoHeadVersion: Head commit on which to run tests (overrides the branch in test_case_list.xml)" print "-u: use the user name passed as argument" print "-p: use the password passed as an argument" + print "-n: Set the NFS share passed as an argument" sys.exit() else : print "Unrecongnized Option: <" + arg + ">. Use -h to see valid options" @@ -1380,7 +1385,7 @@ print "Deleting NFSTestResults Dir..." + res print "Copying files from GilabCI Runner Machine : " + host + "locallogdir = " + locallogdir + ", NFSTestsResultsDir = " + NFSTestsResultsDir #ssh = SSHSession(UEMachine , username=user, key_file=None, password=password) #ssh.get_all(logdir_UE , logdir_local + '/cmake_targets/autotests/log/'+ testcasename) -SSHSessionWrapper(UEMachine, user, None, password, NFSTestsResultsDir , locallogdir, "put_all") +SSHSessionWrapper('localhost', user, None, password, NFSTestsResultsDir , locallogdir, "put_all") sys.exit() From 7be87a27baeb8819db546a29d97c590ebf90930a Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Tue, 29 Dec 2015 20:05:26 +0100 Subject: [PATCH 073/263] added option for rsync to create remote share if it does not exist --- .gitlab-ci.yml | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 57c5c64ffb..36da36ec5d 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -18,10 +18,8 @@ job1: - EXTERNAL_SHARE_RESULTS_DIR=$EXTERNAL_SHARE_DIR/$git_branch/$git_head - echo $NFS_TEST_RESULTS_DIR - echo $EXTERNAL_SHARE_RESULTS_DIR - - mkdir -p $NFS_TEST_RESULTS_DIR - - mkdir -p $EXTERNAL_SHARE_RESULTS_DIR - - python $OPENAIR_DIR/cmake_targets/autotests/run_exec_lte-softmodem_tests.py -r -5GRepoHeadVersion $git_head -n $NFS_SHARE_DIR $OAI_EXTRA_ARGS >& $OPENAIR_DIR/cmake_targets/autotests/python_autotest.log + - python $OPENAIR_DIR/cmake_targets/autotests/run_exec_lte-softmodem_tests.py -r -5GRepoHeadVersion $git_head -n $NFS_SHARE_DIR -u $OAI_USER -p $OAI_PASS >& $OPENAIR_DIR/cmake_targets/autotests/python_autotest.log - mv $OPENAIR_DIR/cmake_targets/autotests/python_autotest.log $OPENAIR_DIR/cmake_targets/autotests/log/python_autotest.log - - sshpass -p "$OAI_PASS" rsync -avz -e "ssh -o StrictHostKeyChecking=no " $OPENAIR_DIR/cmake_targets/autotests/log/ $OAI_USER@localhost:$NFS_TEST_RESULTS_DIR - - sshpass -p "$OAI_PASS" rsync -avz -e "ssh -o StrictHostKeyChecking=no " $OPENAIR_DIR/cmake_targets/autotests/log/ $OAI_USER@localhost:$EXTERNAL_SHARE_DIR + - sshpass -p "$OAI_PASS" rsync -avz -e "ssh -o StrictHostKeyChecking=no " –rsync-path=”mkdir -p $NFS_TEST_RESULTS_DIR && rsync” $OPENAIR_DIR/cmake_targets/autotests/log/ $OAI_USER@localhost:$NFS_TEST_RESULTS_DIR + - sshpass -p "$OAI_PASS" rsync -avz -e "ssh -o StrictHostKeyChecking=no " –rsync-path=”mkdir -p $NFS_TEST_RESULTS_DIR && rsync” $OPENAIR_DIR/cmake_targets/autotests/log/ $OAI_USER@localhost:$EXTERNAL_SHARE_DIR From cff6c95afb94645211054c5e8bc54ee7cf496f3a Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Tue, 29 Dec 2015 20:19:07 +0100 Subject: [PATCH 074/263] minor bug due to cleaning of old programs --- cmake_targets/autotests/run_exec_lte-softmodem_tests.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake_targets/autotests/run_exec_lte-softmodem_tests.py b/cmake_targets/autotests/run_exec_lte-softmodem_tests.py index c7449bcac3..bc4ee6ac36 100644 --- a/cmake_targets/autotests/run_exec_lte-softmodem_tests.py +++ b/cmake_targets/autotests/run_exec_lte-softmodem_tests.py @@ -892,7 +892,7 @@ class oaiCleanOldProgramThread (threading.Thread): self.ExmimoRfStop = ExmimoRfStop def run(self): try: - cleanOldPrograms(oai, CleanUpOldProgs, CleanUpAluLteBox, ExmimoRfStop) + cleanOldPrograms(self.oai, self.CleanUpOldProgs, self.CleanUpAluLteBox, self.ExmimoRfStop) except Exception, e: error='' error = error + ' In class oaiCleanOldProgramThread, function: ' + sys._getframe().f_code.co_name + ': *** Caught exception: ' + str(e.__class__) + " : " + str( e) From 93bf163071f85ca010f40d167203009c91259aa1 Mon Sep 17 00:00:00 2001 From: Raymond Knopp Date: Tue, 29 Dec 2015 20:29:26 +0100 Subject: [PATCH 075/263] commit prior to merge with develop --- cmake_targets/CMakeLists.txt | 1 + openair1/PHY/INIT/lte_parms.c | 85 +++-- .../lte_dl_channel_estimation.c | 16 +- openair1/PHY/LTE_ESTIMATION/lte_sync_time.c | 8 - .../lte_ul_channel_estimation.c | 2 +- openair1/PHY/LTE_REFSIG/lte_dl_cell_spec.c | 12 +- openair1/PHY/MODULATION/defs.h | 6 +- openair1/PHY/MODULATION/ofdm_mod.c | 73 ++-- openair1/PHY/MODULATION/slot_fep.c | 30 +- openair1/PHY/MODULATION/slot_fep_mbsfn.c | 16 +- openair1/PHY/MODULATION/slot_fep_ul.c | 16 +- openair1/PHY/TOOLS/lte_dfts.c | 35 +- openair1/PHY/impl_defs_lte.h | 4 +- openair1/PHY/impl_defs_top.h | 1 - openair1/SCHED/phy_procedures_lte_ue.c | 2 +- openair1/SIMULATION/LTE_PHY/dlsim.c | 284 ++++++---------- openair1/SIMULATION/LTE_PHY/mbmssim.c | 2 +- openair1/SIMULATION/LTE_PHY/pbchsim.c | 316 ++++++++---------- openair1/SIMULATION/LTE_PHY/pdcchsim.c | 97 +----- openair1/SIMULATION/LTE_PHY/prachsim.c | 63 +--- openair1/SIMULATION/LTE_PHY/pucchsim.c | 69 +--- openair1/SIMULATION/LTE_PHY/scansim.c | 207 ++++-------- openair1/SIMULATION/LTE_PHY/syncsim.c | 8 +- openair1/SIMULATION/LTE_PHY/ulsim.c | 67 +--- 24 files changed, 518 insertions(+), 902 deletions(-) diff --git a/cmake_targets/CMakeLists.txt b/cmake_targets/CMakeLists.txt index d7a656e61c..82e2f65a4d 100644 --- a/cmake_targets/CMakeLists.txt +++ b/cmake_targets/CMakeLists.txt @@ -843,6 +843,7 @@ set(PHY_SRC ${OPENAIR1_DIR}/PHY/CODING/viterbi_lte.c ${OPENAIR1_DIR}/PHY/INIT/lte_init.c ${OPENAIR1_DIR}/PHY/INIT/lte_parms.c + ${OPENAIR1_DIR}/PHY/INIT/lte_param_init.c ${OPENAIR1_DIR}/PHY/TOOLS/file_output.c ${OPENAIR1_DIR}/PHY/TOOLS/lte_dfts.c ${OPENAIR1_DIR}/PHY/TOOLS/log2_approx.c diff --git a/openair1/PHY/INIT/lte_parms.c b/openair1/PHY/INIT/lte_parms.c index 55bd964aa7..fa0e731af9 100644 --- a/openair1/PHY/INIT/lte_parms.c +++ b/openair1/PHY/INIT/lte_parms.c @@ -68,33 +68,57 @@ int init_frame_parms(LTE_DL_FRAME_PARMS *frame_parms,uint8_t osf) break; default: - msg("Illegal oversampling %d\n",osf); + printf("Illegal oversampling %d\n",osf); return(-1); } switch (frame_parms->N_RB_DL) { + case 100: if (osf>1) { - msg("Illegal oversampling %d for N_RB_DL %d\n",osf,frame_parms->N_RB_DL); + printf("Illegal oversampling %d for N_RB_DL %d\n",osf,frame_parms->N_RB_DL); return(-1); } - frame_parms->ofdm_symbol_size = 2048; - frame_parms->log2_symbol_size = 11; - frame_parms->samples_per_tti = 30720; - frame_parms->first_carrier_offset = 2048-600; + if (frame_parms->threequarter_fs) { + frame_parms->ofdm_symbol_size = 1536; + frame_parms->samples_per_tti = 23040; + frame_parms->first_carrier_offset = 1536-600; + frame_parms->nb_prefix_samples=(frame_parms->nb_prefix_samples*3)>>2; + frame_parms->nb_prefix_samples0=(frame_parms->nb_prefix_samples0*3)>>2; + } + else { + frame_parms->ofdm_symbol_size = 2048; + frame_parms->samples_per_tti = 30720; + frame_parms->first_carrier_offset = 2048-600; + } + frame_parms->N_RBGS = 4; + frame_parms->N_RBG = 25; + break; + + case 75: + if (osf>1) { + printf("Illegal oversampling %d for N_RB_DL %d\n",osf,frame_parms->N_RB_DL); + return(-1); + } + + + frame_parms->ofdm_symbol_size = 1536; + frame_parms->samples_per_tti = 23040; + frame_parms->first_carrier_offset = 1536-450; + frame_parms->nb_prefix_samples=(frame_parms->nb_prefix_samples*3)>>2; + frame_parms->nb_prefix_samples0=(frame_parms->nb_prefix_samples0*3)>>2; frame_parms->N_RBGS = 4; frame_parms->N_RBG = 25; break; case 50: if (osf>1) { - msg("Illegal oversampling %d for N_RB_DL %d\n",osf,frame_parms->N_RB_DL); + printf("Illegal oversampling %d for N_RB_DL %d\n",osf,frame_parms->N_RB_DL); return(-1); } frame_parms->ofdm_symbol_size = 1024*osf; - frame_parms->log2_symbol_size = 10+log2_osf; frame_parms->samples_per_tti = 15360*osf; frame_parms->first_carrier_offset = frame_parms->ofdm_symbol_size - 300; frame_parms->nb_prefix_samples>>=(1-log2_osf); @@ -105,13 +129,13 @@ int init_frame_parms(LTE_DL_FRAME_PARMS *frame_parms,uint8_t osf) case 25: if (osf>2) { - msg("Illegal oversampling %d for N_RB_DL %d\n",osf,frame_parms->N_RB_DL); + printf("Illegal oversampling %d for N_RB_DL %d\n",osf,frame_parms->N_RB_DL); return(-1); } frame_parms->ofdm_symbol_size = 512*osf; - frame_parms->log2_symbol_size = 9+log2_osf; + frame_parms->samples_per_tti = 7680*osf; frame_parms->first_carrier_offset = frame_parms->ofdm_symbol_size - 150; frame_parms->nb_prefix_samples>>=(2-log2_osf); @@ -124,7 +148,6 @@ int init_frame_parms(LTE_DL_FRAME_PARMS *frame_parms,uint8_t osf) case 15: frame_parms->ofdm_symbol_size = 256*osf; - frame_parms->log2_symbol_size = 8+log2_osf; frame_parms->samples_per_tti = 3840*osf; frame_parms->first_carrier_offset = frame_parms->ofdm_symbol_size - 90; frame_parms->nb_prefix_samples>>=(3-log2_osf); @@ -135,7 +158,6 @@ int init_frame_parms(LTE_DL_FRAME_PARMS *frame_parms,uint8_t osf) case 6: frame_parms->ofdm_symbol_size = 128*osf; - frame_parms->log2_symbol_size = 7+log2_osf; frame_parms->samples_per_tti = 1920*osf; frame_parms->first_carrier_offset = frame_parms->ofdm_symbol_size - 36; frame_parms->nb_prefix_samples>>=(4-log2_osf); @@ -145,7 +167,7 @@ int init_frame_parms(LTE_DL_FRAME_PARMS *frame_parms,uint8_t osf) break; default: - msg("init_frame_parms: Error: Number of resource blocks (N_RB_DL %d) undefined, frame_parms = %p \n",frame_parms->N_RB_DL, frame_parms); + printf("init_frame_parms: Error: Number of resource blocks (N_RB_DL %d) undefined, frame_parms = %p \n",frame_parms->N_RB_DL, frame_parms); return(-1); break; } @@ -159,23 +181,22 @@ int init_frame_parms(LTE_DL_FRAME_PARMS *frame_parms,uint8_t osf) void dump_frame_parms(LTE_DL_FRAME_PARMS *frame_parms) { - msg("frame_parms->N_RB_DL=%d\n",frame_parms->N_RB_DL); - msg("frame_parms->N_RB_UL=%d\n",frame_parms->N_RB_UL); - msg("frame_parms->Nid_cell=%d\n",frame_parms->Nid_cell); - msg("frame_parms->Ncp=%d\n",frame_parms->Ncp); - msg("frame_parms->Ncp_UL=%d\n",frame_parms->Ncp_UL); - msg("frame_parms->nushift=%d\n",frame_parms->nushift); - msg("frame_parms->frame_type=%d\n",frame_parms->frame_type); - msg("frame_parms->tdd_config=%d\n",frame_parms->tdd_config); - msg("frame_parms->tdd_config_S=%d\n",frame_parms->tdd_config_S); - msg("frame_parms->mode1_flag=%d\n",frame_parms->mode1_flag); - msg("frame_parms->nb_antennas_tx=%d\n",frame_parms->nb_antennas_tx); - msg("frame_parms->nb_antennas_rx=%d\n",frame_parms->nb_antennas_rx); - msg("frame_parms->ofdm_symbol_size=%d\n",frame_parms->ofdm_symbol_size); - msg("frame_parms->log2_symbol_size=%d\n",frame_parms->log2_symbol_size); - msg("frame_parms->nb_prefix_samples=%d\n",frame_parms->nb_prefix_samples); - msg("frame_parms->nb_prefix_samples0=%d\n",frame_parms->nb_prefix_samples0); - msg("frame_parms->first_carrier_offset=%d\n",frame_parms->first_carrier_offset); - msg("frame_parms->samples_per_tti=%d\n",frame_parms->samples_per_tti); - msg("frame_parms->symbols_per_tti=%d\n",frame_parms->symbols_per_tti); + printf("frame_parms->N_RB_DL=%d\n",frame_parms->N_RB_DL); + printf("frame_parms->N_RB_UL=%d\n",frame_parms->N_RB_UL); + printf("frame_parms->Nid_cell=%d\n",frame_parms->Nid_cell); + printf("frame_parms->Ncp=%d\n",frame_parms->Ncp); + printf("frame_parms->Ncp_UL=%d\n",frame_parms->Ncp_UL); + printf("frame_parms->nushift=%d\n",frame_parms->nushift); + printf("frame_parms->frame_type=%d\n",frame_parms->frame_type); + printf("frame_parms->tdd_config=%d\n",frame_parms->tdd_config); + printf("frame_parms->tdd_config_S=%d\n",frame_parms->tdd_config_S); + printf("frame_parms->mode1_flag=%d\n",frame_parms->mode1_flag); + printf("frame_parms->nb_antennas_tx=%d\n",frame_parms->nb_antennas_tx); + printf("frame_parms->nb_antennas_rx=%d\n",frame_parms->nb_antennas_rx); + printf("frame_parms->ofdm_symbol_size=%d\n",frame_parms->ofdm_symbol_size); + printf("frame_parms->nb_prefix_samples=%d\n",frame_parms->nb_prefix_samples); + printf("frame_parms->nb_prefix_samples0=%d\n",frame_parms->nb_prefix_samples0); + printf("frame_parms->first_carrier_offset=%d\n",frame_parms->first_carrier_offset); + printf("frame_parms->samples_per_tti=%d\n",frame_parms->samples_per_tti); + printf("frame_parms->symbols_per_tti=%d\n",frame_parms->symbols_per_tti); } diff --git a/openair1/PHY/LTE_ESTIMATION/lte_dl_channel_estimation.c b/openair1/PHY/LTE_ESTIMATION/lte_dl_channel_estimation.c index 10c0cef42a..cfc2d929f1 100644 --- a/openair1/PHY/LTE_ESTIMATION/lte_dl_channel_estimation.c +++ b/openair1/PHY/LTE_ESTIMATION/lte_dl_channel_estimation.c @@ -703,24 +703,28 @@ int lte_dl_channel_estimation(PHY_VARS_UE *phy_vars_ue, void (*idft)(int16_t *,int16_t *, int); - switch (phy_vars_ue->lte_frame_parms.log2_symbol_size) { - case 7: + switch (phy_vars_ue->lte_frame_parms.ofdm_symbol_size) { + case 128: idft = idft128; break; - case 8: + case 256: idft = idft256; break; - case 9: + case 512: idft = idft512; break; - case 10: + case 1024: idft = idft1024; break; - case 11: + case 1536: + idft = idft1536; + break; + + case 2048: idft = idft2048; break; diff --git a/openair1/PHY/LTE_ESTIMATION/lte_sync_time.c b/openair1/PHY/LTE_ESTIMATION/lte_sync_time.c index 9864a50ee2..6e2311789e 100644 --- a/openair1/PHY/LTE_ESTIMATION/lte_sync_time.c +++ b/openair1/PHY/LTE_ESTIMATION/lte_sync_time.c @@ -61,7 +61,6 @@ int lte_sync_time_init(LTE_DL_FRAME_PARMS *frame_parms ) // LTE_UE_COMMON *com { int i,k; - //unsigned short ds = frame_parms->log2_symbol_size - 7; sync_corr_ue0 = (int *)malloc16(LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*sizeof(int)*frame_parms->samples_per_tti); sync_corr_ue1 = (int *)malloc16(LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*sizeof(int)*frame_parms->samples_per_tti); @@ -184,13 +183,6 @@ int lte_sync_time_init(LTE_DL_FRAME_PARMS *frame_parms ) // LTE_UE_COMMON *com LOG_E(PHY,"Unsupported N_RB_DL %d\n",frame_parms->N_RB_DL); break; } - /* - frame_parms->twiddle_ifft, /// complex twiddle factors - frame_parms->rev, /// bit reversed permutation vector - frame_parms->log2_symbol_size,/// log2(FFT_SIZE) - (frame_parms->log2_symbol_size/2), - 0); /// 0 - input is in complex Q1.15 format, 1 - input is in complex redundant Q1.15 format) - */ for (i=0; iofdm_symbol_size; i++) ((int32_t*)primary_synch0_time)[i] = sync_tmp[i]; diff --git a/openair1/PHY/LTE_ESTIMATION/lte_ul_channel_estimation.c b/openair1/PHY/LTE_ESTIMATION/lte_ul_channel_estimation.c index 1d23bdca38..1eb663ec89 100644 --- a/openair1/PHY/LTE_ESTIMATION/lte_ul_channel_estimation.c +++ b/openair1/PHY/LTE_ESTIMATION/lte_ul_channel_estimation.c @@ -432,7 +432,7 @@ int32_t lte_ul_channel_estimation(PHY_VARS_eNB *phy_vars_eNB, in_fft_ptr_0 = &temp_in_fft_0[0]; in_fft_ptr_1 = &temp_in_fft_1[0]; - for(j=0; j<(1<<(frame_parms->log2_symbol_size))/12; j++) { + for(j=0; j<(frame_parms->ofdm_symbol_size)/12; j++) { if (j>19) { ((int16_t*)in_fft_ptr_0)[-40+(2*j)] = ((int16_t*)temp_out_ifft_0)[-80+(2*j)]*rx_power_correction; ((int16_t*)in_fft_ptr_0)[-40+(2*j)+1] = ((int16_t*)temp_out_ifft_0)[-80+(2*j+1)]*rx_power_correction; diff --git a/openair1/PHY/LTE_REFSIG/lte_dl_cell_spec.c b/openair1/PHY/LTE_REFSIG/lte_dl_cell_spec.c index 6faf2e1ed0..8e64275b41 100644 --- a/openair1/PHY/LTE_REFSIG/lte_dl_cell_spec.c +++ b/openair1/PHY/LTE_REFSIG/lte_dl_cell_spec.c @@ -72,7 +72,7 @@ int lte_dl_cell_spec_SS(PHY_VARS_eNB *phy_vars_eNB, else if ((p==1) && (l>0)) nu = 0; else { - msg("lte_dl_cell_spec: p %d, l %d -> ERROR\n",p,l); + printf("lte_dl_cell_spec: p %d, l %d -> ERROR\n",p,l); return(-1); } @@ -94,9 +94,9 @@ int lte_dl_cell_spec_SS(PHY_VARS_eNB *phy_vars_eNB, output[k] = qpsk[(phy_vars_eNB->lte_gold_table[Ns][l][mprime_dword]>>(2*mprime_qpsk_symb))&3]; //output[k] = (lte_gold_table[eNB_offset][Ns][l][mprime_dword]>>(2*mprime_qpsk_symb))&3; #ifdef DEBUG_DL_CELL_SPEC - msg("Ns %d, l %d, m %d,mprime_dword %d, mprime_qpsk_symbol %d\n", + printf("Ns %d, l %d, m %d,mprime_dword %d, mprime_qpsk_symbol %d\n", Ns,l,m,mprime_dword,mprime_qpsk_symb); - msg("index = %d (k %d)\n",(phy_vars_eNB->lte_gold_table[Ns][l][mprime_dword]>>(2*mprime_qpsk_symb))&3,k); + printf("index = %d (k %d)\n",(phy_vars_eNB->lte_gold_table[Ns][l][mprime_dword]>>(2*mprime_qpsk_symb))&3,k); #endif mprime++; @@ -151,7 +151,7 @@ int lte_dl_cell_spec(PHY_VARS_eNB *phy_vars_eNB, else if ((p==1) && (l>0)) nu = 0; else { - msg("lte_dl_cell_spec: p %d, l %d -> ERROR\n",p,l); + printf("lte_dl_cell_spec: p %d, l %d -> ERROR\n",p,l); return(-1); } @@ -177,9 +177,9 @@ int lte_dl_cell_spec(PHY_VARS_eNB *phy_vars_eNB, output[k] = qpsk[(phy_vars_eNB->lte_gold_table[Ns][l][mprime_dword]>>(2*mprime_qpsk_symb))&3]; //output[k] = (lte_gold_table[eNB_offset][Ns][l][mprime_dword]>>(2*mprime_qpsk_symb))&3; #ifdef DEBUG_DL_CELL_SPEC - msg("Ns %d, l %d, m %d,mprime_dword %d, mprime_qpsk_symbol %d\n", + printf("Ns %d, l %d, m %d,mprime_dword %d, mprime_qpsk_symbol %d\n", Ns,l,m,mprime_dword,mprime_qpsk_symb); - msg("index = %d (k %d)\n",(phy_vars_eNB->lte_gold_table[Ns][l][mprime_dword]>>(2*mprime_qpsk_symb))&3,k); + printf("index = %d (k %d)\n",(phy_vars_eNB->lte_gold_table[Ns][l][mprime_dword]>>(2*mprime_qpsk_symb))&3,k); #endif mprime++; diff --git a/openair1/PHY/MODULATION/defs.h b/openair1/PHY/MODULATION/defs.h index 8d45c15e00..6005d6d49a 100644 --- a/openair1/PHY/MODULATION/defs.h +++ b/openair1/PHY/MODULATION/defs.h @@ -34,12 +34,12 @@ */ /** -\fn void PHY_ofdm_mod(int *input,int *output,unsigned char log2fftsize,unsigned char nb_symbols,unsigned short nb_prefix_samples,Extension_t etype) +\fn void PHY_ofdm_mod(int *input,int *output,int fftsize,unsigned char nb_symbols,unsigned short nb_prefix_samples,Extension_t etype) This function performs OFDM modulation with cyclic extension or zero-padding. @param input The sequence input samples in the frequency-domain. This is a concatenation of the input symbols in SIMD redundant format @param output The time-domain output signal -@param log2fftsize Base-2 logarithm of the OFDM symbol size (\f$N_d\f$) +@param fftsize size of OFDM symbol size (\f$N_d\f$) @param nb_symbols The number of OFDM symbols in the block @param nb_prefix_samples The number of prefix/suffix/zero samples @param etype Type of extension (CYCLIC_PREFIX,CYCLIC_SUFFIX,ZEROS) @@ -47,7 +47,7 @@ This function performs OFDM modulation with cyclic extension or zero-padding. */ void PHY_ofdm_mod(int *input, int *output, - unsigned char log2fftsize, + int fftsize, unsigned char nb_symbols, unsigned short nb_prefix_samples, Extension_t etype diff --git a/openair1/PHY/MODULATION/ofdm_mod.c b/openair1/PHY/MODULATION/ofdm_mod.c index 61e5f9fb5b..3dd76c0fbb 100755 --- a/openair1/PHY/MODULATION/ofdm_mod.c +++ b/openair1/PHY/MODULATION/ofdm_mod.c @@ -61,9 +61,9 @@ void normal_prefix_mod(int32_t *txdataF,int32_t *txdata,uint8_t nsymb,LTE_DL_FRA txdata+(i*(frame_parms->samples_per_tti>>1))); #endif - PHY_ofdm_mod(txdataF+(i*NUMBER_OF_OFDM_CARRIERS*frame_parms->symbols_per_tti>>1), // input + PHY_ofdm_mod(txdataF+(i*frame_parms->ofdm_symbol_size*frame_parms->symbols_per_tti>>1), // input txdata+(i*frame_parms->samples_per_tti>>1), // output - frame_parms->log2_symbol_size, // log2_fft_size + frame_parms->ofdm_symbol_size, 1, // number of symbols frame_parms->nb_prefix_samples0, // number of prefix samples CYCLIC_PREFIX); @@ -71,9 +71,9 @@ void normal_prefix_mod(int32_t *txdataF,int32_t *txdata,uint8_t nsymb,LTE_DL_FRA printf("slot i %d (txdata offset %d)\n",i,OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES0+(i*frame_parms->samples_per_tti>>1)); #endif - PHY_ofdm_mod(txdataF+NUMBER_OF_OFDM_CARRIERS+(i*NUMBER_OF_OFDM_CARRIERS*(frame_parms->symbols_per_tti>>1)), // input + PHY_ofdm_mod(txdataF+frame_parms->ofdm_symbol_size+(i*frame_parms->ofdm_symbol_size*(frame_parms->symbols_per_tti>>1)), // input txdata+OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES0+(i*(frame_parms->samples_per_tti>>1)), // output - frame_parms->log2_symbol_size, // log2_fft_size + frame_parms->ofdm_symbol_size, (short_offset==1) ? 1 :(frame_parms->symbols_per_tti>>1)-1,//6, // number of symbols frame_parms->nb_prefix_samples, // number of prefix samples CYCLIC_PREFIX); @@ -84,7 +84,7 @@ void normal_prefix_mod(int32_t *txdataF,int32_t *txdata,uint8_t nsymb,LTE_DL_FRA void PHY_ofdm_mod(int *input, /// pointer to complex input int *output, /// pointer to complex output - unsigned char log2fftsize, /// log2(FFT_SIZE) + int fftsize, /// FFT_SIZE unsigned char nb_symbols, /// number of OFDM symbols unsigned short nb_prefix_samples, /// cyclic prefix length Extension_t etype /// type of extension @@ -100,24 +100,28 @@ void PHY_ofdm_mod(int *input, /// pointer to complex input int *temp_ptr=(int*)0; void (*idft)(int16_t *,int16_t *, int); - switch (log2fftsize) { - case 7: + switch (fftsize) { + case 128: idft = idft128; break; - case 8: + case 256: idft = idft256; break; - case 9: + case 512: idft = idft512; break; - case 10: + case 1024: idft = idft1024; break; - case 11: + case 1536: + idft = idft1536; + break; + + case 2048: idft = idft2048; break; @@ -127,8 +131,8 @@ void PHY_ofdm_mod(int *input, /// pointer to complex input } #ifdef DEBUG_OFDM_MOD - msg("[PHY] OFDM mod (size %d,prefix %d) Symbols %d, input %p, output %p\n", - 1< %p)\n",i,nb_symbols,input,&input[i< %p)\n",i,nb_symbols,i*fftsize+(i*nb_prefix_samples),input,&input[i*fftsize],&output[(i*fftsize) + ((i)*nb_prefix_samples)]); #endif - idft((int16_t *)&input[i<=-nb_prefix_samples; k--) { output_ptr[k] = output_ptr[--j]; @@ -175,19 +175,19 @@ void PHY_ofdm_mod(int *input, /// pointer to complex input case CYCLIC_SUFFIX: - output_ptr = &output[(i<>1,slot_offset); PHY_ofdm_mod(&txdataF[aa][slot_offset_F], // input &txdata[aa][slot_offset], // output - frame_parms->log2_symbol_size, // log2_fft_size + frame_parms->ofdm_symbol_size, 12, // number of symbols frame_parms->ofdm_symbol_size>>2, // number of prefix samples CYCLIC_PREFIX); @@ -252,7 +245,7 @@ void do_OFDM_mod(mod_sym_t **txdataF, int32_t **txdata, uint32_t frame,uint16_t if (frame_parms->Ncp == EXTENDED) PHY_ofdm_mod(&txdataF[aa][slot_offset_F], // input &txdata[aa][slot_offset], // output - frame_parms->log2_symbol_size, // log2_fft_size + frame_parms->ofdm_symbol_size, 2, // number of symbols frame_parms->nb_prefix_samples, // number of prefix samples CYCLIC_PREFIX); @@ -268,7 +261,7 @@ void do_OFDM_mod(mod_sym_t **txdataF, int32_t **txdata, uint32_t frame,uint16_t if (frame_parms->Ncp == EXTENDED) PHY_ofdm_mod(&txdataF[aa][slot_offset_F], // input &txdata[aa][slot_offset], // output - frame_parms->log2_symbol_size, // log2_fft_size + frame_parms->ofdm_symbol_size, 6, // number of symbols frame_parms->nb_prefix_samples, // number of prefix samples CYCLIC_PREFIX); diff --git a/openair1/PHY/MODULATION/slot_fep.c b/openair1/PHY/MODULATION/slot_fep.c index feb2d885b2..0d2389c2ae 100644 --- a/openair1/PHY/MODULATION/slot_fep.c +++ b/openair1/PHY/MODULATION/slot_fep.c @@ -58,24 +58,28 @@ int slot_fep(PHY_VARS_UE *phy_vars_ue, void (*dft)(int16_t *,int16_t *, int); int tmp_dft_in[256]; // This is for misalignment issues for 6 and 15 PRBs - switch (frame_parms->log2_symbol_size) { - case 7: + switch (frame_parms->ofdm_symbol_size) { + case 128: dft = dft128; break; - case 8: + case 256: dft = dft256; break; - case 9: + case 512: dft = dft512; break; - case 10: + case 1024: dft = dft1024; break; - case 11: + case 1536: + dft = dft1536; + break; + + case 2048: dft = dft2048; break; @@ -96,12 +100,12 @@ int slot_fep(PHY_VARS_UE *phy_vars_ue, if (l<0 || l>=7-frame_parms->Ncp) { - msg("slot_fep: l must be between 0 and %d\n",7-frame_parms->Ncp); + printf("slot_fep: l must be between 0 and %d\n",7-frame_parms->Ncp); return(-1); } if (Ns<0 || Ns>=20) { - msg("slot_fep: Ns must be between 0 and 19\n"); + printf("slot_fep: Ns must be between 0 and 19\n"); return(-1); } @@ -116,7 +120,7 @@ int slot_fep(PHY_VARS_UE *phy_vars_ue, #ifdef DEBUG_FEP // if (phy_vars_ue->frame <100) - msg("slot_fep: frame %d: slot %d, symbol %d, nb_prefix_samples %d, nb_prefix_samples0 %d, slot_offset %d, subframe_offset %d, sample_offset %d,rx_offset %d\n", phy_vars_ue->frame_rx,Ns, symbol, + printf("slot_fep: frame %d: slot %d, symbol %d, nb_prefix_samples %d, nb_prefix_samples0 %d, slot_offset %d, subframe_offset %d, sample_offset %d,rx_offset %d\n", phy_vars_ue->frame_rx,Ns, symbol, nb_prefix_samples,nb_prefix_samples0,slot_offset,subframe_offset,sample_offset,rx_offset); #endif @@ -147,7 +151,7 @@ int slot_fep(PHY_VARS_UE *phy_vars_ue, #ifdef DEBUG_FEP // if (phy_vars_ue->frame <100) - msg("slot_fep: frame %d: slot %d, symbol %d, nb_prefix_samples %d, nb_prefix_samples0 %d, slot_offset %d, subframe_offset %d, sample_offset %d,rx_offset %d\n", phy_vars_ue->frame_rx,Ns, symbol, + printf("slot_fep: frame %d: slot %d, symbol %d, nb_prefix_samples %d, nb_prefix_samples0 %d, slot_offset %d, subframe_offset %d, sample_offset %d,rx_offset %d\n", phy_vars_ue->frame_rx,Ns, symbol, nb_prefix_samples,nb_prefix_samples0,slot_offset,subframe_offset,sample_offset,rx_offset); #endif @@ -182,7 +186,7 @@ int slot_fep(PHY_VARS_UE *phy_vars_ue, for (aa=0; aanb_antennas_tx_eNB; aa++) { #ifdef DEBUG_FEP - msg("Channel estimation eNB %d, aatx %d, slot %d, symbol %d\n",eNB_id,aa,Ns,l); + printf("Channel estimation eNB %d, aatx %d, slot %d, symbol %d\n",eNB_id,aa,Ns,l); #endif start_meas(&phy_vars_ue->dlsch_channel_estimation_stats); lte_dl_channel_estimation(phy_vars_ue,eNB_id,0, @@ -205,7 +209,7 @@ int slot_fep(PHY_VARS_UE *phy_vars_ue, // do frequency offset estimation here! // use channel estimates from current symbol (=ch_t) and last symbol (ch_{t-1}) #ifdef DEBUG_FEP - msg("Frequency offset estimation\n"); + printf("Frequency offset estimation\n"); #endif if (l==(4-frame_parms->Ncp)) { @@ -222,7 +226,7 @@ int slot_fep(PHY_VARS_UE *phy_vars_ue, } #ifdef DEBUG_FEP - msg("slot_fep: done\n"); + printf("slot_fep: done\n"); #endif return(0); } diff --git a/openair1/PHY/MODULATION/slot_fep_mbsfn.c b/openair1/PHY/MODULATION/slot_fep_mbsfn.c index 94dc4b3ef1..d71a9d0477 100644 --- a/openair1/PHY/MODULATION/slot_fep_mbsfn.c +++ b/openair1/PHY/MODULATION/slot_fep_mbsfn.c @@ -54,25 +54,29 @@ int slot_fep_mbsfn(PHY_VARS_UE *phy_vars_ue, unsigned int frame_length_samples = frame_parms->samples_per_tti * 10; void (*dft)(int16_t *,int16_t *, int); - switch (frame_parms->log2_symbol_size) { + switch (frame_parms->ofdm_symbol_size) { - case 7: + case 128: dft = dft128; break; - case 8: + case 256: dft = dft256; break; - case 9: + case 512: dft = dft512; break; - case 10: + case 1024: dft = dft1024; break; - case 11: + case 1536: + dft = dft1536; + break; + + case 2048: dft = dft2048; break; diff --git a/openair1/PHY/MODULATION/slot_fep_ul.c b/openair1/PHY/MODULATION/slot_fep_ul.c index 32bae2c036..57f4a6f7ab 100644 --- a/openair1/PHY/MODULATION/slot_fep_ul.c +++ b/openair1/PHY/MODULATION/slot_fep_ul.c @@ -50,24 +50,28 @@ int slot_fep_ul(LTE_DL_FRAME_PARMS *frame_parms, void (*dft)(int16_t *,int16_t *, int); - switch (frame_parms->log2_symbol_size) { - case 7: + switch (frame_parms->ofdm_symbol_size) { + case 128: dft = dft128; break; - case 8: + case 256: dft = dft256; break; - case 9: + case 512: dft = dft512; break; - case 10: + case 1024: dft = dft1024; break; - case 11: + case 1536: + dft = dft1536; + break; + + case 2048: dft = dft2048; break; diff --git a/openair1/PHY/TOOLS/lte_dfts.c b/openair1/PHY/TOOLS/lte_dfts.c index c031d5d384..c4d1fa684d 100644 --- a/openair1/PHY/TOOLS/lte_dfts.c +++ b/openair1/PHY/TOOLS/lte_dfts.c @@ -45,8 +45,10 @@ #define debug_msg #define ONE_OVER_SQRT2_Q15 23170 + #endif +#define ONE_OVER_SQRT3_Q15 18919 #include "PHY/sse_intrin.h" @@ -3180,6 +3182,8 @@ void idft1536(int16_t *input, int16_t *output) int i,i2,j; uint32_t tmp[3][512 ]__attribute__((aligned(16))); uint32_t tmpo[3][512] __attribute__((aligned(16))); + simd_q15_t *y128p=(simd_q15_t*)output; + simd_q15_t ONE_OVER_SQRT3_Q15_128 = set1_int16(ONE_OVER_SQRT3_Q15); for (i=0,j=0; i<512; i++) { tmp[0][i] = ((uint32_t *)input)[j++]; @@ -3190,17 +3194,6 @@ void idft1536(int16_t *input, int16_t *output) idft512((int16_t*)(tmp[0]),(int16_t*)(tmpo[0]),1); idft512((int16_t*)(tmp[1]),(int16_t*)(tmpo[1]),1); idft512((int16_t*)(tmp[2]),(int16_t*)(tmpo[2]),1); - /* - for (i=1; i<512; i++) { - tmpo[0][i] = tmpo[0][i<<1]; - tmpo[1][i] = tmpo[1][i<<1]; - tmpo[2][i] = tmpo[2][i<<1]; - }*/ - - // write_output("in.m","in",input,6144,1,1); - // write_output("out0.m","o0",tmpo[0],2048,1,1); - // write_output("out1.m","o1",tmpo[1],2048,1,1); - // write_output("out2.m","o2",tmpo[2],2048,1,1); for (i=0,i2=0; i<1024; i+=8,i2+=4) { ibfly3((simd_q15_t*)(&tmpo[0][i2]),(simd_q15_t*)(&tmpo[1][i2]),((simd_q15_t*)&tmpo[2][i2]), @@ -3209,6 +3202,26 @@ void idft1536(int16_t *input, int16_t *output) } + for (i=0; i<24; i++) { + y128p[0] = mulhi_int16(y128p[0],ONE_OVER_SQRT3_Q15_128); + y128p[1] = mulhi_int16(y128p[1],ONE_OVER_SQRT3_Q15_128); + y128p[2] = mulhi_int16(y128p[2],ONE_OVER_SQRT3_Q15_128); + y128p[3] = mulhi_int16(y128p[3],ONE_OVER_SQRT3_Q15_128); + y128p[4] = mulhi_int16(y128p[4],ONE_OVER_SQRT3_Q15_128); + y128p[5] = mulhi_int16(y128p[5],ONE_OVER_SQRT3_Q15_128); + y128p[6] = mulhi_int16(y128p[6],ONE_OVER_SQRT3_Q15_128); + y128p[7] = mulhi_int16(y128p[7],ONE_OVER_SQRT3_Q15_128); + y128p[8] = mulhi_int16(y128p[8],ONE_OVER_SQRT3_Q15_128); + y128p[9] = mulhi_int16(y128p[9],ONE_OVER_SQRT3_Q15_128); + y128p[10] = mulhi_int16(y128p[10],ONE_OVER_SQRT3_Q15_128); + y128p[11] = mulhi_int16(y128p[11],ONE_OVER_SQRT3_Q15_128); + y128p[12] = mulhi_int16(y128p[12],ONE_OVER_SQRT3_Q15_128); + y128p[13] = mulhi_int16(y128p[13],ONE_OVER_SQRT3_Q15_128); + y128p[14] = mulhi_int16(y128p[14],ONE_OVER_SQRT3_Q15_128); + y128p[15] = mulhi_int16(y128p[15],ONE_OVER_SQRT3_Q15_128); + y128p+=16; + } + _mm_empty(); _m_empty(); diff --git a/openair1/PHY/impl_defs_lte.h b/openair1/PHY/impl_defs_lte.h index a0ef6c005a..cd6ee4ecce 100644 --- a/openair1/PHY/impl_defs_lte.h +++ b/openair1/PHY/impl_defs_lte.h @@ -516,10 +516,10 @@ typedef struct { uint8_t dual_tx; /// flag to indicate SISO transmission uint8_t mode1_flag; + /// Indicator that 20 MHz channel uses 3/4 sampling frequency + uint8_t threequarter_fs; /// Size of FFT uint16_t ofdm_symbol_size; - /// log2(Size of FFT) - uint8_t log2_symbol_size; /// Number of prefix samples in all but first symbol of slot uint16_t nb_prefix_samples; /// Number of prefix samples in first symbol of slot diff --git a/openair1/PHY/impl_defs_top.h b/openair1/PHY/impl_defs_top.h index c84b7d3ece..67d2fb5b86 100755 --- a/openair1/PHY/impl_defs_top.h +++ b/openair1/PHY/impl_defs_top.h @@ -117,7 +117,6 @@ */ #define NUMBER_OF_OFDM_CARRIERS (frame_parms->ofdm_symbol_size) #define NUMBER_OF_SYMBOLS_PER_FRAME (frame_parms->symbols_per_tti*LTE_NUMBER_OF_SUBFRAMES_PER_FRAME) -#define LOG2_NUMBER_OF_OFDM_CARRIERS (frame_parms->log2_symbol_size) #define NUMBER_OF_USEFUL_CARRIERS (12*frame_parms->N_RB_DL) #define NUMBER_OF_ZERO_CARRIERS (NUMBER_OF_OFDM_CARRIERS-NUMBER_OF_USEFUL_CARRIERS) #define NUMBER_OF_USEFUL_CARRIERS_BYTES (NUMBER_OF_USEFUL_CARRIERS>>2) diff --git a/openair1/SCHED/phy_procedures_lte_ue.c b/openair1/SCHED/phy_procedures_lte_ue.c index 7dcd71ce47..ba79cdfcc6 100755 --- a/openair1/SCHED/phy_procedures_lte_ue.c +++ b/openair1/SCHED/phy_procedures_lte_ue.c @@ -1262,7 +1262,7 @@ void phy_procedures_UE_TX(PHY_VARS_UE *phy_vars_ue,uint8_t eNB_id,uint8_t abstra #else &phy_vars_ue->lte_ue_common_vars.txdata[aa][ulsch_start], #endif - frame_parms->log2_symbol_size, + frame_parms->ofdm_symbol_size, nsymb, frame_parms->nb_prefix_samples, CYCLIC_PREFIX); diff --git a/openair1/SIMULATION/LTE_PHY/dlsim.c b/openair1/SIMULATION/LTE_PHY/dlsim.c index 6474e83dd9..d4781f58b2 100644 --- a/openair1/SIMULATION/LTE_PHY/dlsim.c +++ b/openair1/SIMULATION/LTE_PHY/dlsim.c @@ -107,88 +107,6 @@ void handler(int sig) exit(1); } -void lte_param_init(unsigned char N_tx, unsigned char N_rx,unsigned char transmission_mode,uint8_t extended_prefix_flag,uint8_t fdd_flag, uint16_t Nid_cell,uint8_t tdd_config,uint8_t N_RB_DL, - uint8_t osf,uint32_t perfect_ce) -{ - - LTE_DL_FRAME_PARMS *lte_frame_parms; - int i; - - - printf("Start lte_param_init\n"); - PHY_vars_eNB = malloc(sizeof(PHY_VARS_eNB)); - PHY_vars_UE = malloc(sizeof(PHY_VARS_UE)); - //PHY_config = malloc(sizeof(PHY_CONFIG)); - mac_xface = malloc(sizeof(MAC_xface)); - - srand(0); - randominit(0); - set_taus_seed(0); - - lte_frame_parms = &(PHY_vars_eNB->lte_frame_parms); - - lte_frame_parms->N_RB_DL = N_RB_DL; //50 for 10MHz and 25 for 5 MHz - lte_frame_parms->N_RB_UL = N_RB_DL; - lte_frame_parms->Ncp = extended_prefix_flag; - lte_frame_parms->Nid_cell = Nid_cell; - lte_frame_parms->nushift = Nid_cell%6; - lte_frame_parms->nb_antennas_tx = N_tx; - lte_frame_parms->nb_antennas_rx = N_rx; - lte_frame_parms->nb_antennas_tx_eNB = N_tx; - lte_frame_parms->phich_config_common.phich_resource = one; - lte_frame_parms->tdd_config = tdd_config; - lte_frame_parms->frame_type = (fdd_flag==1)?0 : 1; - // lte_frame_parms->Csrs = 2; - // lte_frame_parms->Bsrs = 0; - // lte_frame_parms->kTC = 0;44 - // lte_frame_parms->n_RRC = 0; - lte_frame_parms->mode1_flag = (transmission_mode == 1)? 1 : 0; - - init_frame_parms(lte_frame_parms,osf); - - //copy_lte_parms_to_phy_framing(lte_frame_parms, &(PHY_config->PHY_framing)); - - // phy_init_top(lte_frame_parms); //allocation - - PHY_vars_UE->is_secondary_ue = 0; - PHY_vars_UE->lte_frame_parms = *lte_frame_parms; - PHY_vars_eNB->lte_frame_parms = *lte_frame_parms; - - phy_init_lte_top(lte_frame_parms); - dump_frame_parms(lte_frame_parms); - - PHY_vars_UE->PHY_measurements.n_adj_cells=0; - PHY_vars_UE->PHY_measurements.adj_cell_id[0] = Nid_cell+1; - PHY_vars_UE->PHY_measurements.adj_cell_id[1] = Nid_cell+2; - - for (i=0; i<3; i++) - lte_gold(lte_frame_parms,PHY_vars_UE->lte_gold_table[i],Nid_cell+i); - - phy_init_lte_ue(PHY_vars_UE,1,0); - phy_init_lte_eNB(PHY_vars_eNB,0,0,0); - - generate_pcfich_reg_mapping(&PHY_vars_UE->lte_frame_parms); - generate_phich_reg_mapping(&PHY_vars_UE->lte_frame_parms); - - // DL power control init - if (transmission_mode == 1) { - PHY_vars_eNB->pdsch_config_dedicated->p_a = dB0; // 4 = 0dB - ((PHY_vars_eNB->lte_frame_parms).pdsch_config_common).p_b = 0; - PHY_vars_UE->pdsch_config_dedicated->p_a = dB0; // 4 = 0dB - ((PHY_vars_UE->lte_frame_parms).pdsch_config_common).p_b = 0; - } else { // rho_a = rhob - PHY_vars_eNB->pdsch_config_dedicated->p_a = dB0; // 4 = 0dB - ((PHY_vars_eNB->lte_frame_parms).pdsch_config_common).p_b = 1; - PHY_vars_UE->pdsch_config_dedicated->p_a = dB0; // 4 = 0dB - ((PHY_vars_UE->lte_frame_parms).pdsch_config_common).p_b = 1; - } - - PHY_vars_UE->perfect_ce = perfect_ce; - - printf("Done lte_param_init\n"); - - -} //DCI2_5MHz_2A_M10PRB_TDD_t DLSCH_alloc_pdu2_2A[2]; @@ -214,7 +132,7 @@ void do_OFDM_mod_l(mod_sym_t **txdataF, int32_t **txdata, uint16_t next_slot, LT if (frame_parms->Ncp == 1) PHY_ofdm_mod(&txdataF[aa][slot_offset_F], // input &txdata[aa][slot_offset], // output - frame_parms->log2_symbol_size, // log2_fft_size + frame_parms->ofdm_symbol_size, 6, // number of symbols frame_parms->nb_prefix_samples, // number of prefix samples CYCLIC_PREFIX); @@ -318,7 +236,7 @@ int main(int argc, char **argv) double blerr[4],uncoded_ber,avg_ber; short *uncoded_ber_bit=NULL; uint8_t N_RB_DL=25,osf=1; - uint8_t fdd_flag = 0; + frame_t frame_type = FDD; #ifdef XFORMS FD_lte_phy_scope_ue *form_ue; char title[255]; @@ -350,6 +268,8 @@ int main(int argc, char **argv) FILE *proc_fd = NULL; char buf[64]; + int threequarter_fs=0; + opp_enabled=1; // to enable the time meas #if defined(__arm__) @@ -378,13 +298,17 @@ int main(int argc, char **argv) num_layers = 1; perfect_ce = 0; - while ((c = getopt (argc, argv, "ahdpZDe:m:n:o:s:f:t:c:g:r:F:x:y:z:AM:N:I:i:O:R:S:C:T:b:u:v:w:B:PLl:Y")) != -1) { + while ((c = getopt (argc, argv, "ahdpZDe:Em:n:o:s:f:t:c:g:r:F:x:y:z:AM:N:I:i:O:R:S:C:T:b:u:v:w:B:PLl:Y")) != -1) { switch (c) { case 'a': awgn_flag = 1; channel_model = AWGN; break; + case 'A': + abstx = 1; + break; + case 'b': tdd_config=atoi(optarg); break; @@ -393,10 +317,59 @@ int main(int argc, char **argv) N_RB_DL=atoi(optarg); break; + case 'c': + num_pdcch_symbols=atoi(optarg); + break; + + case 'C': + Nid_cell = atoi(optarg); + break; + case 'd': dci_flag = 1; break; + case 'D': + frame_type=TDD; + break; + + case 'e': + num_rounds=1; + common_flag = 1; + TPC = atoi(optarg); + break; + + case 'E': + threequarter_fs=1; + break; + + case 'f': + input_snr_step= atof(optarg); + break; + + case 'F': + forgetting_factor = atof(optarg); + break; + + case 'i': + input_fd = fopen(optarg,"r"); + input_file=1; + dci_flag = 1; + break; + + case 'I': + input_trch_fd = fopen(optarg,"r"); + input_trch_file=1; + break; + + case 'L': + llr8_flag=1; + break; + + case 'l': + offset_mumimo_llr_drange_fix=atoi(optarg); + break; + case 'm': mcs1 = atoi(optarg); break; @@ -405,6 +378,11 @@ int main(int argc, char **argv) mcs2 = atoi(optarg); break; + case 'O': + test_perf=atoi(optarg); + //print_perf =1; + break; + case 't': mcs_i = atoi(optarg); i_mod = get_Qm(mcs_i); @@ -414,27 +392,16 @@ int main(int argc, char **argv) n_frames = atoi(optarg); break; - case 'C': - Nid_cell = atoi(optarg); - break; case 'o': rx_sample_offset = atoi(optarg); break; - case 'D': - fdd_flag = 1; - break; - case 'r': DLSCH_RB_ALLOC = atoi(optarg); rballocset = 1; break; - case 'F': - forgetting_factor = atof(optarg); - break; - case 's': snr0 = atof(optarg); break; @@ -443,13 +410,6 @@ int main(int argc, char **argv) snr_int = atof(optarg); break; - case 'f': - input_snr_step= atof(optarg); - break; - - case 'A': - abstx = 1; - break; case 'N': n_ch_rlz= atof(optarg); @@ -459,10 +419,6 @@ int main(int argc, char **argv) extended_prefix_flag=1; break; - case 'c': - num_pdcch_symbols=atoi(optarg); - break; - case 'g': memcpy(channel_model_input,optarg,10); @@ -530,62 +486,6 @@ int main(int argc, char **argv) break; - case 'x': - transmission_mode=atoi(optarg); - - if ((transmission_mode!=1) && - (transmission_mode!=2) && - (transmission_mode!=3) && - (transmission_mode!=4) && - (transmission_mode!=5) && - (transmission_mode!=6)) { - msg("Unsupported transmission mode %d\n",transmission_mode); - exit(-1); - } - - if (transmission_mode>1) { - n_tx = 2; - } - - break; - - case 'y': - n_tx=atoi(optarg); - - if ((n_tx==0) || (n_tx>2)) { - msg("Unsupported number of tx antennas %d\n",n_tx); - exit(-1); - } - - break; - - case 'z': - n_rx=atoi(optarg); - - if ((n_rx==0) || (n_rx>2)) { - msg("Unsupported number of rx antennas %d\n",n_rx); - exit(-1); - } - - break; - - case 'I': - input_trch_fd = fopen(optarg,"r"); - input_trch_file=1; - break; - - case 'i': - input_fd = fopen(optarg,"r"); - input_file=1; - dci_flag = 1; - break; - - case 'e': - num_rounds=1; - common_flag = 1; - TPC = atoi(optarg); - break; - case 'R': num_rounds=atoi(optarg); break; @@ -623,26 +523,54 @@ int main(int argc, char **argv) print_perf=1; break; - case 'L': - llr8_flag=1; + case 'x': + transmission_mode=atoi(optarg); + + if ((transmission_mode!=1) && + (transmission_mode!=2) && + (transmission_mode!=3) && + (transmission_mode!=4) && + (transmission_mode!=5) && + (transmission_mode!=6)) { + msg("Unsupported transmission mode %d\n",transmission_mode); + exit(-1); + } + + if (transmission_mode>1) { + n_tx = 2; + } + break; - case 'l': - offset_mumimo_llr_drange_fix=atoi(optarg); + case 'y': + n_tx=atoi(optarg); + + if ((n_tx==0) || (n_tx>2)) { + msg("Unsupported number of tx antennas %d\n",n_tx); + exit(-1); + } + break; - case 'O': - test_perf=atoi(optarg); - //print_perf =1; + case 'Y': + perfect_ce=1; + break; + + case 'z': + n_rx=atoi(optarg); + + if ((n_rx==0) || (n_rx>2)) { + msg("Unsupported number of rx antennas %d\n",n_rx); + exit(-1); + } + break; case 'Z': dump_table=1; break; - case 'Y': - perfect_ce=1; - break; + case 'h': default: @@ -723,8 +651,10 @@ int main(int argc, char **argv) printf("dual_stream_UE=%d\n", dual_stream_UE); } - lte_param_init(n_tx,n_rx,transmission_mode,extended_prefix_flag,fdd_flag,Nid_cell,tdd_config,N_RB_DL,osf,perfect_ce); + lte_param_init(n_tx,n_rx,transmission_mode,extended_prefix_flag,frame_type,Nid_cell,tdd_config,N_RB_DL,threequarter_fs,osf,perfect_ce); + + eNB_id_i = PHY_vars_UE->n_connected_eNB; printf("Setting mcs1 = %d\n",mcs1); @@ -2553,7 +2483,7 @@ PMI_FEEDBACK: } } } - + /* num_pdcch_symbols_2 = generate_dci_top(num_ue_spec_dci, num_common_dci, dci_alloc, @@ -2562,7 +2492,7 @@ PMI_FEEDBACK: &PHY_vars_eNB->lte_frame_parms, PHY_vars_eNB->lte_eNB_common_vars.txdataF[eNB_id], subframe); - + */ if (num_pdcch_symbols_2 > num_pdcch_symbols) { msg("Error: given num_pdcch_symbols not big enough (%d > %d)\n",num_pdcch_symbols_2,num_pdcch_symbols); exit(-1); @@ -2667,6 +2597,7 @@ PMI_FEEDBACK: } start_meas(&PHY_vars_eNB->dlsch_modulation_stats); + re_allocated = dlsch_modulation(PHY_vars_eNB->lte_eNB_common_vars.txdataF[eNB_id], AMP, subframe, @@ -2674,6 +2605,7 @@ PMI_FEEDBACK: num_pdcch_symbols, PHY_vars_eNB->dlsch_eNB[k][0], PHY_vars_eNB->dlsch_eNB[k][1]); + stop_meas(&PHY_vars_eNB->dlsch_modulation_stats); /* if (trials==0 && round==0) diff --git a/openair1/SIMULATION/LTE_PHY/mbmssim.c b/openair1/SIMULATION/LTE_PHY/mbmssim.c index b9be0b27e8..070527db1a 100644 --- a/openair1/SIMULATION/LTE_PHY/mbmssim.c +++ b/openair1/SIMULATION/LTE_PHY/mbmssim.c @@ -457,7 +457,7 @@ int main(int argc, char **argv) PHY_ofdm_mod(PHY_vars_eNB->lte_eNB_common_vars.txdataF[0][0], // input, txdata[0], // output - frame_parms->log2_symbol_size, // log2_fft_size + frame_parms->ofdm_symbol_size, LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*nsymb, // number of symbols frame_parms->nb_prefix_samples, // number of prefix samples CYCLIC_PREFIX); diff --git a/openair1/SIMULATION/LTE_PHY/pbchsim.c b/openair1/SIMULATION/LTE_PHY/pbchsim.c index b7f9f57b6b..319c2ed008 100644 --- a/openair1/SIMULATION/LTE_PHY/pbchsim.c +++ b/openair1/SIMULATION/LTE_PHY/pbchsim.c @@ -53,87 +53,11 @@ #include "OCG_vars.h" -PHY_VARS_eNB *PHY_vars_eNb,*PHY_vars_eNb1,*PHY_vars_eNb2; +PHY_VARS_eNB *PHY_vars_eNB,*PHY_vars_eNB1,*PHY_vars_eNB2; PHY_VARS_UE *PHY_vars_UE; #define DLSCH_RB_ALLOC 0x1fbf // igore DC component,RB13 -void lte_param_init(unsigned char N_tx, unsigned char N_rx,unsigned char transmission_mode,unsigned char extended_prefix_flag,unsigned char frame_type, uint16_t Nid_cell,uint8_t N_RB_DL,uint8_t osf) -{ - - // unsigned int ind; - LTE_DL_FRAME_PARMS *lte_frame_parms; - int i; - - printf("Start lte_param_init\n"); - PHY_vars_eNb = malloc(sizeof(PHY_VARS_eNB)); - PHY_vars_eNb1 = malloc(sizeof(PHY_VARS_eNB)); - PHY_vars_eNb2 = malloc(sizeof(PHY_VARS_eNB)); - - PHY_vars_UE = malloc(sizeof(PHY_VARS_UE)); - //PHY_config = malloc(sizeof(PHY_CONFIG)); - mac_xface = malloc(sizeof(MAC_xface)); - - randominit(0); - set_taus_seed(0); - - lte_frame_parms = &(PHY_vars_eNb->lte_frame_parms); - - lte_frame_parms->N_RB_DL = N_RB_DL; //50 for 10MHz and 25 for 5 MHz - lte_frame_parms->N_RB_UL = N_RB_DL; - lte_frame_parms->Ncp = extended_prefix_flag; - lte_frame_parms->Nid_cell = Nid_cell; - lte_frame_parms->nushift = Nid_cell%6; - lte_frame_parms->nb_antennas_tx = N_tx; - lte_frame_parms->nb_antennas_tx_eNB = N_tx; - lte_frame_parms->nb_antennas_rx = N_rx; - // lte_frame_parms->Csrs = 2; - // lte_frame_parms->Bsrs = 0; - // lte_frame_parms->kTC = 0; - // lte_frame_parms->n_RRC = 0; - lte_frame_parms->mode1_flag = (transmission_mode == 1)? 1 : 0; - lte_frame_parms->tdd_config = 3; - lte_frame_parms->frame_type = frame_type; - init_frame_parms(lte_frame_parms,osf); - - //copy_lte_parms_to_phy_framing(lte_frame_parms, &(PHY_config->PHY_framing)); - - PHY_vars_UE->lte_frame_parms = *lte_frame_parms; - - phy_init_lte_top(lte_frame_parms); - - PHY_vars_UE->PHY_measurements.n_adj_cells=2; - PHY_vars_UE->PHY_measurements.adj_cell_id[0] = Nid_cell+1; - PHY_vars_UE->PHY_measurements.adj_cell_id[1] = Nid_cell+2; - - for (i=0; i<3; i++) - lte_gold(lte_frame_parms,PHY_vars_UE->lte_gold_table[i],Nid_cell+i); - - phy_init_lte_ue(PHY_vars_UE,1,0); - - phy_init_lte_eNB(PHY_vars_eNb,0,0,0); - - memcpy((void*)&PHY_vars_eNb1->lte_frame_parms,(void*)&PHY_vars_eNb->lte_frame_parms,sizeof(LTE_DL_FRAME_PARMS)); - PHY_vars_eNb1->lte_frame_parms.Nid_cell=Nid_cell+1; - PHY_vars_eNb1->lte_frame_parms.nushift=(Nid_cell+1)%6; - PHY_vars_eNb1->Mod_id=1; - - memcpy((void*)&PHY_vars_eNb2->lte_frame_parms,(void*)&PHY_vars_eNb->lte_frame_parms,sizeof(LTE_DL_FRAME_PARMS)); - PHY_vars_eNb2->lte_frame_parms.Nid_cell=Nid_cell+2; - PHY_vars_eNb2->lte_frame_parms.nushift=(Nid_cell+2)%6; - PHY_vars_eNb2->Mod_id=2; - - phy_init_lte_eNB(PHY_vars_eNb1,0,0,0); - - phy_init_lte_eNB(PHY_vars_eNb2,0,0,0); - - phy_init_lte_top(lte_frame_parms); - - printf("Done lte_param_init\n"); - - -} - mod_sym_t *dummybuf[4]; mod_sym_t dummy0[2048*14]; mod_sym_t dummy1[2048*14]; @@ -420,6 +344,28 @@ int main(int argc, char **argv) lte_param_init(n_tx,n_rx,transmission_mode,extended_prefix_flag,frame_type,Nid_cell,N_RB_DL,osf); + PHY_vars_eNB1 = malloc(sizeof(PHY_VARS_eNB)); + PHY_vars_eNB2 = malloc(sizeof(PHY_VARS_eNB)); + PHY_vars_UE->PHY_measurements.n_adj_cells=2; + PHY_vars_UE->PHY_measurements.adj_cell_id[0] = Nid_cell+1; + PHY_vars_UE->PHY_measurements.adj_cell_id[1] = Nid_cell+2; + + for (i=0; i<3; i++) + lte_gold(&PHY_vars_eNB->lte_frame_parms,PHY_vars_UE->lte_gold_table[i],Nid_cell+i); + + memcpy((void*)&PHY_vars_eNB1->lte_frame_parms,(void*)&PHY_vars_eNB->lte_frame_parms,sizeof(LTE_DL_FRAME_PARMS)); + PHY_vars_eNB1->lte_frame_parms.Nid_cell=Nid_cell+1; + PHY_vars_eNB1->lte_frame_parms.nushift=(Nid_cell+1)%6; + PHY_vars_eNB1->Mod_id=1; + + memcpy((void*)&PHY_vars_eNB2->lte_frame_parms,(void*)&PHY_vars_eNB->lte_frame_parms,sizeof(LTE_DL_FRAME_PARMS)); + PHY_vars_eNB2->lte_frame_parms.Nid_cell=Nid_cell+2; + PHY_vars_eNB2->lte_frame_parms.nushift=(Nid_cell+2)%6; + PHY_vars_eNB2->Mod_id=2; + + phy_init_lte_eNB(PHY_vars_eNB1,0,0,0); + phy_init_lte_eNB(PHY_vars_eNB2,0,0,0); + #ifdef XFORMS fl_initialize (&argc, argv, NULL, 0, 0); form_ue = create_lte_phy_scope_ue(); @@ -436,13 +382,13 @@ int main(int argc, char **argv) printf("SNR0 %f, SNR1 %f\n",snr0,snr1); - frame_parms = &PHY_vars_eNb->lte_frame_parms; + frame_parms = &PHY_vars_eNB->lte_frame_parms; - txdata = PHY_vars_eNb->lte_eNB_common_vars.txdata[0]; - txdata1 = PHY_vars_eNb1->lte_eNB_common_vars.txdata[0]; - txdata2 = PHY_vars_eNb2->lte_eNB_common_vars.txdata[0]; + txdata = PHY_vars_eNB->lte_eNB_common_vars.txdata[0]; + txdata1 = PHY_vars_eNB1->lte_eNB_common_vars.txdata[0]; + txdata2 = PHY_vars_eNB2->lte_eNB_common_vars.txdata[0]; s_re = malloc(2*sizeof(double*)); @@ -463,8 +409,8 @@ int main(int argc, char **argv) printf("FFT Size %d, Extended Prefix %d, Samples per subframe %d, Symbols per subframe %d, interf (%d,%d)\n",NUMBER_OF_OFDM_CARRIERS, frame_parms->Ncp,frame_parms->samples_per_tti,nsymb,interf1,interf2); - printf("PHY_vars_eNb1->lte_eNB_common_vars.txdataF[0][0] = %p\n", - PHY_vars_eNb1->lte_eNB_common_vars.txdataF[0][0]); + printf("PHY_vars_eNB1->lte_eNB_common_vars.txdataF[0][0] = %p\n", + PHY_vars_eNB1->lte_eNB_common_vars.txdataF[0][0]); DLSCH_alloc_pdu2.rah = 0; @@ -479,31 +425,31 @@ int main(int argc, char **argv) // Forget second codeword DLSCH_alloc_pdu2.tpmi = (transmission_mode==6 ? 5 : 0) ; // precoding - eNB2UE = new_channel_desc_scm(PHY_vars_eNb->lte_frame_parms.nb_antennas_tx, + eNB2UE = new_channel_desc_scm(PHY_vars_eNB->lte_frame_parms.nb_antennas_tx, PHY_vars_UE->lte_frame_parms.nb_antennas_rx, channel_model, - N_RB2sampling_rate(PHY_vars_eNb->lte_frame_parms.N_RB_DL), - N_RB2channel_bandwidth(PHY_vars_eNb->lte_frame_parms.N_RB_DL), + N_RB2sampling_rate(PHY_vars_eNB->lte_frame_parms.N_RB_DL), + N_RB2channel_bandwidth(PHY_vars_eNB->lte_frame_parms.N_RB_DL), 0, 0, 0); if (interf1>-20) - eNB2UE1 = new_channel_desc_scm(PHY_vars_eNb->lte_frame_parms.nb_antennas_tx, + eNB2UE1 = new_channel_desc_scm(PHY_vars_eNB->lte_frame_parms.nb_antennas_tx, PHY_vars_UE->lte_frame_parms.nb_antennas_rx, channel_model, - N_RB2sampling_rate(PHY_vars_eNb->lte_frame_parms.N_RB_DL), - N_RB2channel_bandwidth(PHY_vars_eNb->lte_frame_parms.N_RB_DL), + N_RB2sampling_rate(PHY_vars_eNB->lte_frame_parms.N_RB_DL), + N_RB2channel_bandwidth(PHY_vars_eNB->lte_frame_parms.N_RB_DL), 0, 4, 0); if (interf2>-20) - eNB2UE2 = new_channel_desc_scm(PHY_vars_eNb->lte_frame_parms.nb_antennas_tx, + eNB2UE2 = new_channel_desc_scm(PHY_vars_eNB->lte_frame_parms.nb_antennas_tx, PHY_vars_UE->lte_frame_parms.nb_antennas_rx, channel_model, - N_RB2sampling_rate(PHY_vars_eNb->lte_frame_parms.N_RB_DL), - N_RB2channel_bandwidth(PHY_vars_eNb->lte_frame_parms.N_RB_DL), + N_RB2sampling_rate(PHY_vars_eNB->lte_frame_parms.N_RB_DL), + N_RB2channel_bandwidth(PHY_vars_eNB->lte_frame_parms.N_RB_DL), 0, 8, 0); @@ -567,47 +513,47 @@ int main(int argc, char **argv) pbch_pdu[1]=1; pbch_pdu[2]=0; - if (PHY_vars_eNb->lte_frame_parms.frame_type == 0) { - generate_pss(PHY_vars_eNb->lte_eNB_common_vars.txdataF[0], + if (PHY_vars_eNB->lte_frame_parms.frame_type == 0) { + generate_pss(PHY_vars_eNB->lte_eNB_common_vars.txdataF[0], AMP, - &PHY_vars_eNb->lte_frame_parms, - (PHY_vars_eNb->lte_frame_parms.Ncp==0) ? 6 : 5, + &PHY_vars_eNB->lte_frame_parms, + (PHY_vars_eNB->lte_frame_parms.Ncp==0) ? 6 : 5, 0); - generate_sss(PHY_vars_eNb->lte_eNB_common_vars.txdataF[0], + generate_sss(PHY_vars_eNB->lte_eNB_common_vars.txdataF[0], AMP, - &PHY_vars_eNb->lte_frame_parms, - (PHY_vars_eNb->lte_frame_parms.Ncp==0) ? 5 : 4, + &PHY_vars_eNB->lte_frame_parms, + (PHY_vars_eNB->lte_frame_parms.Ncp==0) ? 5 : 4, 0); - generate_pss(PHY_vars_eNb->lte_eNB_common_vars.txdataF[0], + generate_pss(PHY_vars_eNB->lte_eNB_common_vars.txdataF[0], AMP, - &PHY_vars_eNb->lte_frame_parms, - (PHY_vars_eNb->lte_frame_parms.Ncp==0) ? 6 : 5, + &PHY_vars_eNB->lte_frame_parms, + (PHY_vars_eNB->lte_frame_parms.Ncp==0) ? 6 : 5, 10); - generate_sss(PHY_vars_eNb->lte_eNB_common_vars.txdataF[0], + generate_sss(PHY_vars_eNB->lte_eNB_common_vars.txdataF[0], AMP, - &PHY_vars_eNb->lte_frame_parms, - (PHY_vars_eNb->lte_frame_parms.Ncp==0) ? 5 : 4, + &PHY_vars_eNB->lte_frame_parms, + (PHY_vars_eNB->lte_frame_parms.Ncp==0) ? 5 : 4, 10); } else { - generate_sss(PHY_vars_eNb->lte_eNB_common_vars.txdataF[0], + generate_sss(PHY_vars_eNB->lte_eNB_common_vars.txdataF[0], AMP, - &PHY_vars_eNb->lte_frame_parms, - (PHY_vars_eNb->lte_frame_parms.Ncp==0) ? 6 : 5, + &PHY_vars_eNB->lte_frame_parms, + (PHY_vars_eNB->lte_frame_parms.Ncp==0) ? 6 : 5, 1); - generate_pss(PHY_vars_eNb->lte_eNB_common_vars.txdataF[0], + generate_pss(PHY_vars_eNB->lte_eNB_common_vars.txdataF[0], AMP, - &PHY_vars_eNb->lte_frame_parms, + &PHY_vars_eNB->lte_frame_parms, 2, 2); - generate_sss(PHY_vars_eNb->lte_eNB_common_vars.txdataF[0], + generate_sss(PHY_vars_eNB->lte_eNB_common_vars.txdataF[0], AMP, - &PHY_vars_eNb->lte_frame_parms, - (PHY_vars_eNb->lte_frame_parms.Ncp==0) ? 6 : 5, + &PHY_vars_eNB->lte_frame_parms, + (PHY_vars_eNB->lte_frame_parms.Ncp==0) ? 6 : 5, 11); - generate_pss(PHY_vars_eNb->lte_eNB_common_vars.txdataF[0], + generate_pss(PHY_vars_eNB->lte_eNB_common_vars.txdataF[0], AMP, - &PHY_vars_eNb->lte_frame_parms, + &PHY_vars_eNB->lte_frame_parms, 2, 12); @@ -626,11 +572,11 @@ int main(int argc, char **argv) dci_alloc[1].rnti = 0x1234; */ - printf("Generating PBCH for mode1_flag = %d\n", PHY_vars_eNb->lte_frame_parms.mode1_flag); + printf("Generating PBCH for mode1_flag = %d\n", PHY_vars_eNB->lte_frame_parms.mode1_flag); - generate_pilots(PHY_vars_eNb, - PHY_vars_eNb->lte_eNB_common_vars.txdataF[0], + generate_pilots(PHY_vars_eNB, + PHY_vars_eNB->lte_eNB_common_vars.txdataF[0], AMP, LTE_NUMBER_OF_SUBFRAMES_PER_FRAME); @@ -641,8 +587,8 @@ int main(int argc, char **argv) dci_alloc, 0, 1024, - &PHY_vars_eNb->lte_frame_parms, - PHY_vars_eNb->lte_eNB_common_vars.txdataF[0], + &PHY_vars_eNB->lte_frame_parms, + PHY_vars_eNB->lte_eNB_common_vars.txdataF[0], 0); */ @@ -657,47 +603,47 @@ int main(int argc, char **argv) dummybuf[1] = dummy1; dummybuf[2] = dummy2; dummybuf[3] = dummy3; - generate_pbch(&PHY_vars_eNb->lte_eNB_pbch, + generate_pbch(&PHY_vars_eNB->lte_eNB_pbch, (mod_sym_t**)dummybuf, AMP, - &PHY_vars_eNb->lte_frame_parms, + &PHY_vars_eNB->lte_frame_parms, pbch_pdu, 0); } - generate_pbch(&PHY_vars_eNb->lte_eNB_pbch, - PHY_vars_eNb->lte_eNB_common_vars.txdataF[0], + generate_pbch(&PHY_vars_eNB->lte_eNB_pbch, + PHY_vars_eNB->lte_eNB_common_vars.txdataF[0], AMP, - &PHY_vars_eNb->lte_frame_parms, + &PHY_vars_eNB->lte_frame_parms, pbch_pdu, pbch_phase); /* - generate_pbch(&PHY_vars_eNb->lte_eNB_pbch, - PHY_vars_eNb->lte_eNB_common_vars.txdataF[0], + generate_pbch(&PHY_vars_eNB->lte_eNB_pbch, + PHY_vars_eNB->lte_eNB_common_vars.txdataF[0], AMP, - &PHY_vars_eNb->lte_frame_parms, + &PHY_vars_eNB->lte_frame_parms, pbch_pdu, 1); */ if (interf1>-20) { /* - generate_pss(PHY_vars_eNb1->lte_eNB_common_vars.txdataF[0], + generate_pss(PHY_vars_eNB1->lte_eNB_common_vars.txdataF[0], AMP, - &PHY_vars_eNb1->lte_frame_parms, - (PHY_vars_eNb1->lte_frame_parms.Ncp==0)?6:5, + &PHY_vars_eNB1->lte_frame_parms, + (PHY_vars_eNB1->lte_frame_parms.Ncp==0)?6:5, 0); */ - generate_pilots(PHY_vars_eNb1, - PHY_vars_eNb1->lte_eNB_common_vars.txdataF[0], + generate_pilots(PHY_vars_eNB1, + PHY_vars_eNB1->lte_eNB_common_vars.txdataF[0], AMP, LTE_NUMBER_OF_SUBFRAMES_PER_FRAME); - generate_pbch(&PHY_vars_eNb1->lte_eNB_pbch, - PHY_vars_eNb1->lte_eNB_common_vars.txdataF[0], + generate_pbch(&PHY_vars_eNB1->lte_eNB_pbch, + PHY_vars_eNB1->lte_eNB_common_vars.txdataF[0], AMP, - &PHY_vars_eNb1->lte_frame_parms, + &PHY_vars_eNB1->lte_frame_parms, pbch_pdu, 0); @@ -705,26 +651,26 @@ int main(int argc, char **argv) if (interf2>-20) { /* - generate_pss(PHY_vars_eNb2->lte_eNB_common_vars.txdataF[0], + generate_pss(PHY_vars_eNB2->lte_eNB_common_vars.txdataF[0], AMP, - &PHY_vars_eNb2->lte_frame_parms, - (PHY_vars_eNb2->lte_frame_parms.Ncp==0)?6:5, + &PHY_vars_eNB2->lte_frame_parms, + (PHY_vars_eNB2->lte_frame_parms.Ncp==0)?6:5, 0); */ - generate_pilots(PHY_vars_eNb2, - PHY_vars_eNb2->lte_eNB_common_vars.txdataF[0], + generate_pilots(PHY_vars_eNB2, + PHY_vars_eNB2->lte_eNB_common_vars.txdataF[0], AMP, LTE_NUMBER_OF_SUBFRAMES_PER_FRAME); - generate_pbch(&PHY_vars_eNb2->lte_eNB_pbch, - PHY_vars_eNb2->lte_eNB_common_vars.txdataF[0], + generate_pbch(&PHY_vars_eNB2->lte_eNB_pbch, + PHY_vars_eNB2->lte_eNB_common_vars.txdataF[0], AMP, - &PHY_vars_eNb2->lte_frame_parms, + &PHY_vars_eNB2->lte_frame_parms, pbch_pdu, 0); @@ -733,10 +679,10 @@ int main(int argc, char **argv) // write_output("pilotsF.m","rsF",txdataF[0],lte_frame_parms->ofdm_symbol_size,1,1); - write_output("txsigF0.m","txsF0", PHY_vars_eNb->lte_eNB_common_vars.txdataF[0][0],FRAME_LENGTH_COMPLEX_SAMPLES_NO_PREFIX,1,1); + write_output("txsigF0.m","txsF0", PHY_vars_eNB->lte_eNB_common_vars.txdataF[0][0],FRAME_LENGTH_COMPLEX_SAMPLES_NO_PREFIX,1,1); - if (PHY_vars_eNb->lte_frame_parms.nb_antennas_tx>1) - write_output("txsigF1.m","txsF1", PHY_vars_eNb->lte_eNB_common_vars.txdataF[0][1],FRAME_LENGTH_COMPLEX_SAMPLES_NO_PREFIX,1,1); + if (PHY_vars_eNB->lte_frame_parms.nb_antennas_tx>1) + write_output("txsigF1.m","txsF1", PHY_vars_eNB->lte_eNB_common_vars.txdataF[0][1],FRAME_LENGTH_COMPLEX_SAMPLES_NO_PREFIX,1,1); tx_lev = 0; tx_lev1 = 0; @@ -745,16 +691,16 @@ int main(int argc, char **argv) - for (aa=0; aalte_frame_parms.nb_antennas_tx; aa++) { + for (aa=0; aalte_frame_parms.nb_antennas_tx; aa++) { if (frame_parms->Ncp == 1) - PHY_ofdm_mod(PHY_vars_eNb->lte_eNB_common_vars.txdataF[0][aa], // input, + PHY_ofdm_mod(PHY_vars_eNB->lte_eNB_common_vars.txdataF[0][aa], // input, txdata[aa], // output - frame_parms->log2_symbol_size, // log2_fft_size + frame_parms->ofdm_symbol_size, LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*nsymb, // number of symbols frame_parms->nb_prefix_samples, // number of prefix samples CYCLIC_PREFIX); else { - normal_prefix_mod(PHY_vars_eNb->lte_eNB_common_vars.txdataF[0][aa], + normal_prefix_mod(PHY_vars_eNB->lte_eNB_common_vars.txdataF[0][aa], txdata[aa], LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*nsymb, frame_parms); @@ -765,17 +711,17 @@ int main(int argc, char **argv) } if (interf1>-20) { - for (aa=0; aalte_frame_parms.nb_antennas_tx; aa++) { + for (aa=0; aalte_frame_parms.nb_antennas_tx; aa++) { if (frame_parms->Ncp == 1) - PHY_ofdm_mod(PHY_vars_eNb1->lte_eNB_common_vars.txdataF[0][aa], // input, - PHY_vars_eNb1->lte_eNB_common_vars.txdata[0][aa], // output - frame_parms->log2_symbol_size, // log2_fft_size + PHY_ofdm_mod(PHY_vars_eNB1->lte_eNB_common_vars.txdataF[0][aa], // input, + PHY_vars_eNB1->lte_eNB_common_vars.txdata[0][aa], // output + frame_parms->ofdm_symbol_size, 2*nsymb, // number of symbols frame_parms->nb_prefix_samples, // number of prefix samples CYCLIC_PREFIX); else { - normal_prefix_mod(PHY_vars_eNb1->lte_eNB_common_vars.txdataF[0][aa], - PHY_vars_eNb1->lte_eNB_common_vars.txdata[0][aa], + normal_prefix_mod(PHY_vars_eNB1->lte_eNB_common_vars.txdataF[0][aa], + PHY_vars_eNB1->lte_eNB_common_vars.txdata[0][aa], 2*nsymb, frame_parms); } @@ -784,24 +730,24 @@ int main(int argc, char **argv) OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES); } - write_output("txsigF0_1.m","txsF0_1", PHY_vars_eNb1->lte_eNB_common_vars.txdataF[0][0],FRAME_LENGTH_COMPLEX_SAMPLES_NO_PREFIX,1,1); + write_output("txsigF0_1.m","txsF0_1", PHY_vars_eNB1->lte_eNB_common_vars.txdataF[0][0],FRAME_LENGTH_COMPLEX_SAMPLES_NO_PREFIX,1,1); - if (PHY_vars_eNb1->lte_frame_parms.nb_antennas_tx>1) - write_output("txsigF1_1.m","txsF1_1", PHY_vars_eNb1->lte_eNB_common_vars.txdataF[0][1],FRAME_LENGTH_COMPLEX_SAMPLES_NO_PREFIX,1,1); + if (PHY_vars_eNB1->lte_frame_parms.nb_antennas_tx>1) + write_output("txsigF1_1.m","txsF1_1", PHY_vars_eNB1->lte_eNB_common_vars.txdataF[0][1],FRAME_LENGTH_COMPLEX_SAMPLES_NO_PREFIX,1,1); } if (interf2>-20) { - for (aa=0; aalte_frame_parms.nb_antennas_tx; aa++) { + for (aa=0; aalte_frame_parms.nb_antennas_tx; aa++) { if (frame_parms->Ncp == 1) - PHY_ofdm_mod(PHY_vars_eNb2->lte_eNB_common_vars.txdataF[0][aa], // input, - PHY_vars_eNb2->lte_eNB_common_vars.txdata[0][aa], // output - frame_parms->log2_symbol_size, // log2_fft_size + PHY_ofdm_mod(PHY_vars_eNB2->lte_eNB_common_vars.txdataF[0][aa], // input, + PHY_vars_eNB2->lte_eNB_common_vars.txdata[0][aa], // output + frame_parms->ofdm_symbol_size, 2*nsymb, // number of symbols frame_parms->nb_prefix_samples, // number of prefix samples CYCLIC_PREFIX); else { - normal_prefix_mod(PHY_vars_eNb2->lte_eNB_common_vars.txdataF[0][aa], - PHY_vars_eNb2->lte_eNB_common_vars.txdata[0][aa], + normal_prefix_mod(PHY_vars_eNB2->lte_eNB_common_vars.txdataF[0][aa], + PHY_vars_eNB2->lte_eNB_common_vars.txdata[0][aa], 2*nsymb, frame_parms); } @@ -810,10 +756,10 @@ int main(int argc, char **argv) OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES); } - write_output("txsigF0_2.m","txsF0_2", PHY_vars_eNb2->lte_eNB_common_vars.txdataF[0][0],FRAME_LENGTH_COMPLEX_SAMPLES_NO_PREFIX,1,1); + write_output("txsigF0_2.m","txsF0_2", PHY_vars_eNB2->lte_eNB_common_vars.txdataF[0][0],FRAME_LENGTH_COMPLEX_SAMPLES_NO_PREFIX,1,1); - if (PHY_vars_eNb2->lte_frame_parms.nb_antennas_tx>1) - write_output("txsigF1_2.m","txsF1_2", PHY_vars_eNb2->lte_eNB_common_vars.txdataF[0][1],FRAME_LENGTH_COMPLEX_SAMPLES_NO_PREFIX,1,1); + if (PHY_vars_eNB2->lte_frame_parms.nb_antennas_tx>1) + write_output("txsigF1_2.m","txsF1_2", PHY_vars_eNB2->lte_eNB_common_vars.txdataF[0][1],FRAME_LENGTH_COMPLEX_SAMPLES_NO_PREFIX,1,1); } // tx_lev_dB = (unsigned int) dB_fixed(tx_lev); @@ -823,15 +769,15 @@ int main(int argc, char **argv) if (frame_parms->nb_antennas_tx>1) write_output("txsig1.m","txs1", txdata[1],FRAME_LENGTH_COMPLEX_SAMPLES,1,1); - write_output("txsig0_1.m","txs0_1", PHY_vars_eNb1->lte_eNB_common_vars.txdata[0][0],FRAME_LENGTH_COMPLEX_SAMPLES,1,1); + write_output("txsig0_1.m","txs0_1", PHY_vars_eNB1->lte_eNB_common_vars.txdata[0][0],FRAME_LENGTH_COMPLEX_SAMPLES,1,1); if (frame_parms->nb_antennas_tx>1) - write_output("txsig1_1.m","txs1_1", PHY_vars_eNb1->lte_eNB_common_vars.txdata[0][1],FRAME_LENGTH_COMPLEX_SAMPLES,1,1); + write_output("txsig1_1.m","txs1_1", PHY_vars_eNB1->lte_eNB_common_vars.txdata[0][1],FRAME_LENGTH_COMPLEX_SAMPLES,1,1); - write_output("txsig0_2.m","txs0_2", PHY_vars_eNb2->lte_eNB_common_vars.txdata[0][0],FRAME_LENGTH_COMPLEX_SAMPLES,1,1); + write_output("txsig0_2.m","txs0_2", PHY_vars_eNB2->lte_eNB_common_vars.txdata[0][0],FRAME_LENGTH_COMPLEX_SAMPLES,1,1); if (frame_parms->nb_antennas_tx>1) - write_output("txsig1_2.m","txs1_2", PHY_vars_eNb2->lte_eNB_common_vars.txdata[0][1],FRAME_LENGTH_COMPLEX_SAMPLES,1,1); + write_output("txsig1_2.m","txs1_2", PHY_vars_eNB2->lte_eNB_common_vars.txdata[0][1],FRAME_LENGTH_COMPLEX_SAMPLES,1,1); } else { //read in from file i=0; @@ -864,7 +810,7 @@ int main(int argc, char **argv) // multipath channel for (i=0; i<2*nsymb*OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES; i++) { - for (aa=0; aalte_frame_parms.nb_antennas_tx; aa++) { + for (aa=0; aalte_frame_parms.nb_antennas_tx; aa++) { s_re[aa][i] = ((double)(((short *)txdata[aa]))[(i<<1)]); s_im[aa][i] = ((double)(((short *)txdata[aa]))[(i<<1)+1]); @@ -925,7 +871,7 @@ int main(int argc, char **argv) } } - sigma2_dB = 10*log10((double)tx_lev) +10*log10((double)PHY_vars_eNb->lte_frame_parms.ofdm_symbol_size/(double)(12*NB_RB)) - SNR; + sigma2_dB = 10*log10((double)tx_lev) +10*log10((double)PHY_vars_eNB->lte_frame_parms.ofdm_symbol_size/(double)(12*NB_RB)) - SNR; if (n_frames==1) printf("sigma2_dB %f (SNR %f dB) tx_lev_dB %f,%f,%f\n",sigma2_dB,SNR, @@ -947,7 +893,7 @@ int main(int argc, char **argv) for (n_trials=0; n_trialslte_frame_parms.nb_antennas_rx; aa++) { + for (aa=0; aalte_frame_parms.nb_antennas_rx; aa++) { if (n_trials==0) { r_re[aa][i] += (pow(10.0,.05*interf1)*r_re1[aa][i] + pow(10.0,.05*interf2)*r_re2[aa][i]); r_im[aa][i] += (pow(10.0,.05*interf1)*r_im1[aa][i] + pow(10.0,.05*interf2)*r_im2[aa][i]); @@ -983,14 +929,14 @@ int main(int argc, char **argv) */ - for (l=0; llte_frame_parms.symbols_per_tti; l++) { + for (l=0; llte_frame_parms.symbols_per_tti; l++) { - // subframe_offset = (l/PHY_vars_eNb->lte_frame_parms.symbols_per_tti)*PHY_vars_eNb->lte_frame_parms.samples_per_tti; + // subframe_offset = (l/PHY_vars_eNB->lte_frame_parms.symbols_per_tti)*PHY_vars_eNB->lte_frame_parms.samples_per_tti; // printf("subframe_offset = %d\n",subframe_offset); slot_fep(PHY_vars_UE, - l%(PHY_vars_eNb->lte_frame_parms.symbols_per_tti/2), - l/(PHY_vars_eNb->lte_frame_parms.symbols_per_tti/2), + l%(PHY_vars_eNB->lte_frame_parms.symbols_per_tti/2), + l/(PHY_vars_eNB->lte_frame_parms.symbols_per_tti/2), 0, 0, 0); @@ -1026,7 +972,7 @@ int main(int argc, char **argv) */ } - if (l==((PHY_vars_eNb->lte_frame_parms.Ncp==0)?4:3)) { + if (l==((PHY_vars_eNB->lte_frame_parms.Ncp==0)?4:3)) { //sprintf(fname,"dl_ch00_%d.m",l); //sprintf(vname,"dl_ch00_%d",l); //write_output(fname,vname,&(lte_ue_common_vars->dl_ch_estimates[0][lte_frame_parms->ofdm_symbol_size*(l%6)]),lte_frame_parms->ofdm_symbol_size,1,1); @@ -1038,7 +984,7 @@ int main(int argc, char **argv) 1); } - if (l==((PHY_vars_eNb->lte_frame_parms.Ncp==0)?10:9)) { + if (l==((PHY_vars_eNB->lte_frame_parms.Ncp==0)?10:9)) { for (frame_mod4=0; frame_mod4<4; frame_mod4++) { pbch_tx_ant = rx_pbch(&PHY_vars_UE->lte_ue_common_vars, @@ -1059,7 +1005,7 @@ int main(int argc, char **argv) pbch_tx_ant = rx_pbch(&PHY_vars_UE->lte_ue_common_vars, PHY_vars_UE->lte_ue_pbch_vars[0], - &PHY_vars_eNb->lte_frame_parms, + &PHY_vars_eNB->lte_frame_parms, 0, ALAMOUTI, PHY_vars_UE->high_speed_flag, @@ -1119,10 +1065,10 @@ int main(int argc, char **argv) if (n_frames==1) { - write_output("H00.m","h00",&(PHY_vars_UE->lte_ue_common_vars.dl_ch_estimates[0][0][0]),((frame_parms->Ncp==0)?7:6)*(PHY_vars_eNb->lte_frame_parms.ofdm_symbol_size),1,1); + write_output("H00.m","h00",&(PHY_vars_UE->lte_ue_common_vars.dl_ch_estimates[0][0][0]),((frame_parms->Ncp==0)?7:6)*(PHY_vars_eNB->lte_frame_parms.ofdm_symbol_size),1,1); if (n_tx==2) - write_output("H10.m","h10",&(PHY_vars_UE->lte_ue_common_vars.dl_ch_estimates[0][2][0]),((frame_parms->Ncp==0)?7:6)*(PHY_vars_eNb->lte_frame_parms.ofdm_symbol_size),1,1); + write_output("H10.m","h10",&(PHY_vars_UE->lte_ue_common_vars.dl_ch_estimates[0][2][0]),((frame_parms->Ncp==0)?7:6)*(PHY_vars_eNB->lte_frame_parms.ofdm_symbol_size),1,1); write_output("rxsig0.m","rxs0", PHY_vars_UE->lte_ue_common_vars.rxdata[0],FRAME_LENGTH_COMPLEX_SAMPLES,1,1); write_output("rxsigF0.m","rxsF0", PHY_vars_UE->lte_ue_common_vars.rxdataF[0],NUMBER_OF_OFDM_CARRIERS*2*((frame_parms->Ncp==0)?14:12),2,1); diff --git a/openair1/SIMULATION/LTE_PHY/pdcchsim.c b/openair1/SIMULATION/LTE_PHY/pdcchsim.c index 7a36132980..a6556c4f24 100644 --- a/openair1/SIMULATION/LTE_PHY/pdcchsim.c +++ b/openair1/SIMULATION/LTE_PHY/pdcchsim.c @@ -58,98 +58,6 @@ PHY_VARS_UE *PHY_vars_UE; #define CCCH_RB_ALLOC computeRIV(PHY_vars_eNB->lte_frame_parms.N_RB_UL,0,2) #define DLSCH_RB_ALLOC 0x1fbf // igore DC component,RB13 -void lte_param_init(unsigned char N_tx, unsigned char N_rx,unsigned char transmission_mode,unsigned char extended_prefix_flag,uint16_t Nid_cell,uint8_t tdd_config,uint8_t N_RB_DL, - lte_frame_type_t frame_type,uint8_t osf,uint32_t perfect_ce) -{ - - unsigned int i; - LTE_DL_FRAME_PARMS *lte_frame_parms; - - printf("Start lte_param_init (Nid_cell %d, extended_prefix %d, transmission_mode %d, N_tx %d, N_rx %d)\n", - Nid_cell, extended_prefix_flag,transmission_mode,N_tx,N_rx); - PHY_vars_eNB = malloc(sizeof(PHY_VARS_eNB)); - PHY_vars_eNB1 = malloc(sizeof(PHY_VARS_eNB)); - PHY_vars_eNB2 = malloc(sizeof(PHY_VARS_eNB)); - - PHY_vars_UE = malloc(sizeof(PHY_VARS_UE)); - //PHY_config = malloc(sizeof(PHY_CONFIG)); - mac_xface = malloc(sizeof(MAC_xface)); - - randominit(0); - set_taus_seed(0); - - lte_frame_parms = &(PHY_vars_eNB->lte_frame_parms); - - lte_frame_parms->N_RB_DL = N_RB_DL; //50 for 10MHz and 25 for 5 MHz - lte_frame_parms->N_RB_UL = N_RB_DL; - lte_frame_parms->Ncp = extended_prefix_flag; - lte_frame_parms->Nid_cell = Nid_cell; - lte_frame_parms->nushift = Nid_cell%6; - lte_frame_parms->nb_antennas_tx_eNB = N_tx; - lte_frame_parms->nb_antennas_tx = N_tx; - lte_frame_parms->nb_antennas_rx = N_rx; - lte_frame_parms->phich_config_common.phich_resource = one; //half - lte_frame_parms->tdd_config = tdd_config; - lte_frame_parms->frame_type = frame_type; - - // lte_frame_parms->Csrs = 2; - // lte_frame_parms->Bsrs = 0; - // lte_frame_parms->kTC = 0; - // lte_frame_parms->n_RRC = 0; - lte_frame_parms->mode1_flag = (transmission_mode == 1)? 1 : 0; - - init_frame_parms(lte_frame_parms,osf); - - //copy_lte_parms_to_phy_framing(lte_frame_parms, &(PHY_config->PHY_framing)); - - - memcpy(&PHY_vars_UE->lte_frame_parms,lte_frame_parms,sizeof(LTE_DL_FRAME_PARMS)); - - - phy_init_lte_top(lte_frame_parms); - - phy_init_lte_ue(PHY_vars_UE,1,0); - - phy_init_lte_eNB(PHY_vars_eNB,0,0,0); - - memcpy((void*)&PHY_vars_eNB1->lte_frame_parms,(void*)&PHY_vars_eNB->lte_frame_parms,sizeof(LTE_DL_FRAME_PARMS)); - PHY_vars_eNB1->lte_frame_parms.nushift=(Nid_cell+1)%6; - PHY_vars_eNB1->lte_frame_parms.Nid_cell=Nid_cell+1; - - memcpy((void*)&PHY_vars_eNB2->lte_frame_parms,(void*)&PHY_vars_eNB->lte_frame_parms,sizeof(LTE_DL_FRAME_PARMS)); - PHY_vars_eNB2->lte_frame_parms.nushift=(Nid_cell+2)%6; - PHY_vars_eNB2->lte_frame_parms.Nid_cell=Nid_cell+2; - - phy_init_lte_eNB(PHY_vars_eNB1,0,0,0); - - phy_init_lte_eNB(PHY_vars_eNB2,0,0,0); - - phy_init_lte_top(lte_frame_parms); - - PHY_vars_UE->PHY_measurements.n_adj_cells=2; - PHY_vars_UE->PHY_measurements.adj_cell_id[0] = Nid_cell+1; - PHY_vars_UE->PHY_measurements.adj_cell_id[1] = Nid_cell+2; - PHY_vars_UE->perfect_ce = perfect_ce; - - for (i=0; i<3; i++) - lte_gold(lte_frame_parms,PHY_vars_UE->lte_gold_table[i],Nid_cell+i); - - generate_pcfich_reg_mapping(&PHY_vars_UE->lte_frame_parms); - generate_phich_reg_mapping(&PHY_vars_UE->lte_frame_parms); - - printf("Done lte_param_init\n"); - - CCCH_alloc_pdu.type = 1; - CCCH_alloc_pdu.vrb_type = 0; - CCCH_alloc_pdu.rballoc = CCCH_RB_ALLOC; - CCCH_alloc_pdu.ndi = 1; - CCCH_alloc_pdu.mcs = 1; - CCCH_alloc_pdu.harq_pid = 0; - -} - - - DCI_PDU DCI_pdu; DCI_PDU *get_dci(LTE_DL_FRAME_PARMS *lte_frame_parms,uint8_t log2L, uint8_t log2Lcommon, uint8_t format_selector, uint32_t rnti) @@ -798,9 +706,10 @@ int main(int argc, char **argv) n_rx, transmission_mode, extended_prefix_flag, + frame_type, Nid_cell, tdd_config, - N_RB_DL,frame_type, + N_RB_DL, osf, perfect_ce); @@ -1084,7 +993,7 @@ int main(int argc, char **argv) if (PHY_vars_eNB->lte_frame_parms.Ncp == 1) PHY_ofdm_mod(&PHY_vars_eNB->lte_eNB_common_vars.txdataF[eNb_id][aa][subframe*nsymb*PHY_vars_eNB->lte_frame_parms.ofdm_symbol_size], // input, &txdata[aa][subframe*PHY_vars_eNB->lte_frame_parms.samples_per_tti], // output - PHY_vars_eNB->lte_frame_parms.log2_symbol_size, // log2_fft_size + PHY_vars_eNB->lte_frame_parms.ofdm_symbol_size, 2*nsymb, // number of symbols PHY_vars_eNB->lte_frame_parms.nb_prefix_samples, // number of prefix samples CYCLIC_PREFIX); diff --git a/openair1/SIMULATION/LTE_PHY/prachsim.c b/openair1/SIMULATION/LTE_PHY/prachsim.c index 4df53b053f..187a521e07 100644 --- a/openair1/SIMULATION/LTE_PHY/prachsim.c +++ b/openair1/SIMULATION/LTE_PHY/prachsim.c @@ -56,58 +56,6 @@ PHY_VARS_UE *PHY_vars_UE; -void lte_param_init(unsigned char N_tx, unsigned char N_rx,unsigned char transmission_mode,unsigned char extended_prefix_flag,uint16_t Nid_cell,uint8_t N_RB_DL,uint8_t osf) -{ - - LTE_DL_FRAME_PARMS *lte_frame_parms; - - printf("Start lte_param_init\n"); - PHY_vars_eNB = malloc(sizeof(PHY_VARS_eNB)); - - PHY_vars_UE = malloc(sizeof(PHY_VARS_UE)); - //PHY_config = malloc(sizeof(PHY_CONFIG)); - mac_xface = malloc(sizeof(MAC_xface)); - - randominit(0); - set_taus_seed(0); - - lte_frame_parms = &(PHY_vars_eNB->lte_frame_parms); - - lte_frame_parms->N_RB_DL = N_RB_DL; //50 for 10MHz and 25 for 5 MHz - lte_frame_parms->N_RB_UL = N_RB_DL; - lte_frame_parms->Ncp = extended_prefix_flag; - lte_frame_parms->Nid_cell = Nid_cell; - lte_frame_parms->nushift = 0; - lte_frame_parms->nb_antennas_tx = N_tx; - lte_frame_parms->nb_antennas_rx = N_rx; - // lte_frame_parms->Csrs = 2; - // lte_frame_parms->Bsrs = 0; - // lte_frame_parms->kTC = 0; - // lte_frame_parms->n_RRC = 0; - lte_frame_parms->mode1_flag = (transmission_mode == 1)? 1 : 0; - lte_frame_parms->tdd_config = 1; - lte_frame_parms->frame_type = 1; - init_frame_parms(lte_frame_parms,osf); - - //copy_lte_parms_to_phy_framing(lte_frame_parms, &(PHY_config->PHY_framing)); - - - PHY_vars_UE->lte_frame_parms = *lte_frame_parms; - - phy_init_lte_top(lte_frame_parms); - - phy_init_lte_ue(PHY_vars_UE,1,0); - - phy_init_lte_eNB(PHY_vars_eNB,0,0,0); - - - - - - printf("Done lte_param_init\n"); - -} - extern uint16_t prach_root_sequence_map0_3[838]; int main(int argc, char **argv) @@ -370,7 +318,16 @@ int main(int argc, char **argv) if (transmission_mode==2) n_tx=2; - lte_param_init(n_tx,n_rx,transmission_mode,extended_prefix_flag,Nid_cell,N_RB_DL,osf); + lte_param_init(n_tx, + n_rx, + transmission_mode, + extended_prefix_flag, + FDD, + Nid_cell, + 3, + N_RB_DL, + osf, + 0); if (snr1set==0) { diff --git a/openair1/SIMULATION/LTE_PHY/pucchsim.c b/openair1/SIMULATION/LTE_PHY/pucchsim.c index d9a3367b90..aa886fa50b 100644 --- a/openair1/SIMULATION/LTE_PHY/pucchsim.c +++ b/openair1/SIMULATION/LTE_PHY/pucchsim.c @@ -58,60 +58,6 @@ PHY_VARS_UE *PHY_vars_UE; -void lte_param_init(unsigned char N_tx, unsigned char N_rx,unsigned char transmission_mode,unsigned char extended_prefix_flag,uint16_t Nid_cell,uint8_t N_RB_DL,uint8_t osf) -{ - - LTE_DL_FRAME_PARMS *lte_frame_parms; - - printf("Start lte_param_init\n"); - PHY_vars_eNB = malloc(sizeof(PHY_VARS_eNB)); - - PHY_vars_UE = malloc(sizeof(PHY_VARS_UE)); - //PHY_config = malloc(sizeof(PHY_CONFIG)); - mac_xface = malloc(sizeof(MAC_xface)); - - randominit(0); - set_taus_seed(0); - - lte_frame_parms = &(PHY_vars_eNB->lte_frame_parms); - - lte_frame_parms->N_RB_DL = N_RB_DL; //50 for 10MHz and 25 for 5 MHz - lte_frame_parms->N_RB_UL = N_RB_DL; - lte_frame_parms->Ncp = extended_prefix_flag; - lte_frame_parms->Nid_cell = Nid_cell; - lte_frame_parms->nushift = 0; - lte_frame_parms->nb_antennas_tx = N_tx; - lte_frame_parms->nb_antennas_rx = N_rx; - // lte_frame_parms->Csrs = 2; - // lte_frame_parms->Bsrs = 0; - // lte_frame_parms->kTC = 0; - // lte_frame_parms->n_RRC = 0; - lte_frame_parms->mode1_flag = (transmission_mode == 1)? 1 : 0; - lte_frame_parms->tdd_config = 3; - lte_frame_parms->frame_type = 0; - init_frame_parms(lte_frame_parms,osf); - - //copy_lte_parms_to_phy_framing(lte_frame_parms, &(PHY_config->PHY_framing)); - -// phy_init_top(lte_frame_parms); //allocation - - PHY_vars_UE->lte_frame_parms = *lte_frame_parms; - - - phy_init_lte_ue(PHY_vars_UE,1,0); - - phy_init_lte_eNB(PHY_vars_eNB,0,0,0); - - phy_init_lte_top(lte_frame_parms); - - - - - printf("Done lte_param_init\n"); - -} - - int main(int argc, char **argv) { @@ -368,7 +314,16 @@ int main(int argc, char **argv) if (transmission_mode==2) n_tx=2; - lte_param_init(n_tx,n_rx,transmission_mode,extended_prefix_flag,Nid_cell,N_RB_DL,osf); + lte_param_init(n_tx, + n_rx, + transmission_mode, + extended_prefix_flag, + Nid_cell, + FDD, + 3, + N_RB_DL, + osf, + 0); if (snr1set==0) { @@ -473,7 +428,7 @@ int main(int argc, char **argv) if (frame_parms->Ncp == 1) PHY_ofdm_mod(txdataF2[aa], // input txdata[aa], // output - frame_parms->log2_symbol_size, // log2_fft_size + frame_parms->ofdm_symbol_size, 2*nsymb, // number of symbols frame_parms->nb_prefix_samples, // number of prefix samples CYCLIC_PREFIX); @@ -496,7 +451,7 @@ int main(int argc, char **argv) if (frame_parms->Ncp == 1) PHY_ofdm_mod(&PHY_vars_UE->lte_ue_common_vars.txdataF[aa][2*subframe*nsymb*OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES_NO_PREFIX], // input, &txdata[aa][PHY_vars_eNB->lte_frame_parms.samples_per_tti*subframe], // output - frame_parms->log2_symbol_size, // log2_fft_size + frame_parms->ofdm_symbol_size, nsymb, // number of symbols frame_parms->nb_prefix_samples, // number of prefix samples CYCLIC_PREFIX); diff --git a/openair1/SIMULATION/LTE_PHY/scansim.c b/openair1/SIMULATION/LTE_PHY/scansim.c index c2ceb1c58d..2cbb7b3e32 100644 --- a/openair1/SIMULATION/LTE_PHY/scansim.c +++ b/openair1/SIMULATION/LTE_PHY/scansim.c @@ -56,94 +56,11 @@ #define BW 20.0 -PHY_VARS_eNB *PHY_vars_eNb,*PHY_vars_eNb1,*PHY_vars_eNb2; +PHY_VARS_eNB *PHY_vars_eNB,*PHY_vars_eNB1,*PHY_vars_eNB2; PHY_VARS_UE *PHY_vars_UE; #define DLSCH_RB_ALLOC 0x1fbf // igore DC component,RB13 -void lte_param_init(unsigned char N_tx, unsigned char N_rx,unsigned char transmission_mode,unsigned char extended_prefix_flag,unsigned char frame_type, uint16_t Nid_cell,uint8_t N_RB_DL,uint8_t osf) -{ - - // unsigned int ind; - LTE_DL_FRAME_PARMS *lte_frame_parms; - int i; - - printf("Start lte_param_init\n"); - PHY_vars_eNb = malloc(sizeof(PHY_VARS_eNB)); - PHY_vars_eNb1 = malloc(sizeof(PHY_VARS_eNB)); - PHY_vars_eNb2 = malloc(sizeof(PHY_VARS_eNB)); - - PHY_vars_UE = malloc(sizeof(PHY_VARS_UE)); - //PHY_config = malloc(sizeof(PHY_CONFIG)); - mac_xface = malloc(sizeof(MAC_xface)); - - randominit(0); - set_taus_seed(0); - - lte_frame_parms = &(PHY_vars_eNb->lte_frame_parms); - - lte_frame_parms->N_RB_DL = N_RB_DL; //50 for 10MHz and 25 for 5 MHz - lte_frame_parms->N_RB_UL = N_RB_DL; - lte_frame_parms->Ncp = extended_prefix_flag; - lte_frame_parms->Nid_cell = Nid_cell; - lte_frame_parms->nushift = Nid_cell%6; - lte_frame_parms->nb_antennas_tx = N_tx; - lte_frame_parms->nb_antennas_tx_eNB = N_tx; - lte_frame_parms->nb_antennas_rx = N_rx; - // lte_frame_parms->Csrs = 2; - // lte_frame_parms->Bsrs = 0; - // lte_frame_parms->kTC = 0; - // lte_frame_parms->n_RRC = 0; - lte_frame_parms->mode1_flag = (transmission_mode == 1)? 1 : 0; - lte_frame_parms->tdd_config = 3; - lte_frame_parms->frame_type = frame_type; - init_frame_parms(lte_frame_parms,osf); - - //copy_lte_parms_to_phy_framing(lte_frame_parms, &(PHY_config->PHY_framing)); - - - PHY_vars_UE->lte_frame_parms = *lte_frame_parms; - - phy_init_lte_top(lte_frame_parms); - - PHY_vars_UE->PHY_measurements.n_adj_cells=2; - PHY_vars_UE->PHY_measurements.adj_cell_id[0] = Nid_cell+1; - PHY_vars_UE->PHY_measurements.adj_cell_id[1] = Nid_cell+2; - - for (i=0; i<3; i++) - lte_gold(lte_frame_parms,PHY_vars_UE->lte_gold_table[i],Nid_cell+i); - - phy_init_lte_ue(PHY_vars_UE,1,0); - - phy_init_lte_eNB(PHY_vars_eNb,0,0,0); - - for (i=0; i<10; i++) { - PHY_vars_UE->scan_info[0].amp[0][i] = 0; - PHY_vars_UE->scan_info[0].amp[1][i] = 0; - PHY_vars_UE->scan_info[0].amp[2][i] = 0; - } - - memcpy((void*)&PHY_vars_eNb1->lte_frame_parms,(void*)&PHY_vars_eNb->lte_frame_parms,sizeof(LTE_DL_FRAME_PARMS)); - PHY_vars_eNb1->lte_frame_parms.Nid_cell=Nid_cell+1; - PHY_vars_eNb1->lte_frame_parms.nushift=(Nid_cell+1)%6; - PHY_vars_eNb1->Mod_id=1; - - memcpy((void*)&PHY_vars_eNb2->lte_frame_parms,(void*)&PHY_vars_eNb->lte_frame_parms,sizeof(LTE_DL_FRAME_PARMS)); - PHY_vars_eNb2->lte_frame_parms.Nid_cell=Nid_cell+2; - PHY_vars_eNb2->lte_frame_parms.nushift=(Nid_cell+2)%6; - PHY_vars_eNb2->Mod_id=2; - - phy_init_lte_eNB(PHY_vars_eNb1,0,0,0); - - phy_init_lte_eNB(PHY_vars_eNb2,0,0,0); - - phy_init_lte_top(lte_frame_parms); - - printf("Done lte_param_init\n"); - - -} - mod_sym_t *dummybuf[4]; mod_sym_t dummy0[2048*14]; mod_sym_t dummy1[2048*14]; @@ -404,7 +321,16 @@ int main(int argc, char **argv) if (transmission_mode>=2) n_tx=2; - lte_param_init(n_tx,n_rx,transmission_mode,extended_prefix_flag,frame_type,Nid_cell,N_RB_DL,osf); + lte_param_init(n_tx, + n_rx, + transmission_mode, + extended_prefix_flag, + frame_type, + Nid_cell, + 3, + N_RB_DL, + osf, + 0); #ifdef XFORMS fl_initialize (&argc, argv, NULL, 0, 0); @@ -422,13 +348,13 @@ int main(int argc, char **argv) printf("SNR0 %f, SNR1 %f\n",snr0,snr1); - frame_parms = &PHY_vars_eNb->lte_frame_parms; + frame_parms = &PHY_vars_eNB->lte_frame_parms; - txdata = PHY_vars_eNb->lte_eNB_common_vars.txdata[0]; - txdata1 = PHY_vars_eNb1->lte_eNB_common_vars.txdata[0]; - txdata2 = PHY_vars_eNb2->lte_eNB_common_vars.txdata[0]; + txdata = PHY_vars_eNB->lte_eNB_common_vars.txdata[0]; + txdata1 = PHY_vars_eNB1->lte_eNB_common_vars.txdata[0]; + txdata2 = PHY_vars_eNB2->lte_eNB_common_vars.txdata[0]; s_re = malloc(2*sizeof(double*)); @@ -449,8 +375,8 @@ int main(int argc, char **argv) printf("FFT Size %d, Extended Prefix %d, Samples per subframe %d, Symbols per subframe %d\n",NUMBER_OF_OFDM_CARRIERS, frame_parms->Ncp,frame_parms->samples_per_tti,nsymb); - printf("PHY_vars_eNb1->lte_eNB_common_vars.txdataF[0][0] = %p\n", - PHY_vars_eNb1->lte_eNB_common_vars.txdataF[0][0]); + printf("PHY_vars_eNB1->lte_eNB_common_vars.txdataF[0][0] = %p\n", + PHY_vars_eNB1->lte_eNB_common_vars.txdataF[0][0]); DLSCH_alloc_pdu2.rah = 0; @@ -465,13 +391,14 @@ int main(int argc, char **argv) // Forget second codeword DLSCH_alloc_pdu2.tpmi = (transmission_mode==6 ? 5 : 0) ; // precoding - eNB2UE = new_channel_desc_scm(PHY_vars_eNb->lte_frame_parms.nb_antennas_tx, - PHY_vars_UE->lte_frame_parms.nb_antennas_rx, - channel_model, - BW, - 0, - 0, - 0); + eNB2UE = new_channel_desc_scm(PHY_vars_eNB->lte_frame_parms.nb_antennas_tx, + PHY_vars_UE->lte_frame_parms.nb_antennas_rx, + channel_model, + N_RB2sampling_rate(PHY_vars_eNB->lte_frame_parms.N_RB_DL), + N_RB2channel_bandwidth(PHY_vars_eNB->lte_frame_parms.N_RB_DL), + 0, + 0, + 0); if (eNB2UE==NULL) { @@ -512,51 +439,51 @@ int main(int argc, char **argv) pbch_pdu[1]=1; pbch_pdu[2]=0; - if (PHY_vars_eNb->lte_frame_parms.frame_type == FDD) { - generate_pss(PHY_vars_eNb->lte_eNB_common_vars.txdataF[0], + if (PHY_vars_eNB->lte_frame_parms.frame_type == FDD) { + generate_pss(PHY_vars_eNB->lte_eNB_common_vars.txdataF[0], AMP, - &PHY_vars_eNb->lte_frame_parms, - (PHY_vars_eNb->lte_frame_parms.Ncp==NORMAL) ? 6 : 5, + &PHY_vars_eNB->lte_frame_parms, + (PHY_vars_eNB->lte_frame_parms.Ncp==NORMAL) ? 6 : 5, 0); /* - generate_sss(PHY_vars_eNb->lte_eNB_common_vars.txdataF[0], + generate_sss(PHY_vars_eNB->lte_eNB_common_vars.txdataF[0], AMP, - &PHY_vars_eNb->lte_frame_parms, - (PHY_vars_eNb->lte_frame_parms.Ncp==0) ? 5 : 4, + &PHY_vars_eNB->lte_frame_parms, + (PHY_vars_eNB->lte_frame_parms.Ncp==0) ? 5 : 4, 0);*/ - generate_pss(PHY_vars_eNb->lte_eNB_common_vars.txdataF[0], + generate_pss(PHY_vars_eNB->lte_eNB_common_vars.txdataF[0], AMP, - &PHY_vars_eNb->lte_frame_parms, - (PHY_vars_eNb->lte_frame_parms.Ncp==0) ? 6 : 5, + &PHY_vars_eNB->lte_frame_parms, + (PHY_vars_eNB->lte_frame_parms.Ncp==0) ? 6 : 5, 10); /* - generate_sss(PHY_vars_eNb->lte_eNB_common_vars.txdataF[0], + generate_sss(PHY_vars_eNB->lte_eNB_common_vars.txdataF[0], AMP, - &PHY_vars_eNb->lte_frame_parms, - (PHY_vars_eNb->lte_frame_parms.Ncp==0) ? 5 : 4, + &PHY_vars_eNB->lte_frame_parms, + (PHY_vars_eNB->lte_frame_parms.Ncp==0) ? 5 : 4, 10); */ } else { - generate_sss(PHY_vars_eNb->lte_eNB_common_vars.txdataF[0], + generate_sss(PHY_vars_eNB->lte_eNB_common_vars.txdataF[0], AMP, - &PHY_vars_eNb->lte_frame_parms, - (PHY_vars_eNb->lte_frame_parms.Ncp==0) ? 6 : 5, + &PHY_vars_eNB->lte_frame_parms, + (PHY_vars_eNB->lte_frame_parms.Ncp==0) ? 6 : 5, 1); - generate_pss(PHY_vars_eNb->lte_eNB_common_vars.txdataF[0], + generate_pss(PHY_vars_eNB->lte_eNB_common_vars.txdataF[0], AMP, - &PHY_vars_eNb->lte_frame_parms, + &PHY_vars_eNB->lte_frame_parms, 2, 2); - generate_sss(PHY_vars_eNb->lte_eNB_common_vars.txdataF[0], + generate_sss(PHY_vars_eNB->lte_eNB_common_vars.txdataF[0], AMP, - &PHY_vars_eNb->lte_frame_parms, - (PHY_vars_eNb->lte_frame_parms.Ncp==0) ? 6 : 5, + &PHY_vars_eNB->lte_frame_parms, + (PHY_vars_eNB->lte_frame_parms.Ncp==0) ? 6 : 5, 11); - generate_pss(PHY_vars_eNb->lte_eNB_common_vars.txdataF[0], + generate_pss(PHY_vars_eNB->lte_eNB_common_vars.txdataF[0], AMP, - &PHY_vars_eNb->lte_frame_parms, + &PHY_vars_eNB->lte_frame_parms, 2, 12); @@ -565,8 +492,8 @@ int main(int argc, char **argv) /* - generate_pilots(PHY_vars_eNb, - PHY_vars_eNb->lte_eNB_common_vars.txdataF[0], + generate_pilots(PHY_vars_eNB, + PHY_vars_eNB->lte_eNB_common_vars.txdataF[0], AMP, LTE_NUMBER_OF_SUBFRAMES_PER_FRAME); @@ -577,8 +504,8 @@ int main(int argc, char **argv) dci_alloc, 0, 1024, - &PHY_vars_eNb->lte_frame_parms, - PHY_vars_eNb->lte_eNB_common_vars.txdataF[0], + &PHY_vars_eNB->lte_frame_parms, + PHY_vars_eNB->lte_eNB_common_vars.txdataF[0], 0); */ @@ -593,25 +520,25 @@ int main(int argc, char **argv) dummybuf[1] = dummy1; dummybuf[2] = dummy2; dummybuf[3] = dummy3; - generate_pbch(&PHY_vars_eNb->lte_eNB_pbch, + generate_pbch(&PHY_vars_eNB->lte_eNB_pbch, (mod_sym_t**)dummybuf, AMP, - &PHY_vars_eNb->lte_frame_parms, + &PHY_vars_eNB->lte_frame_parms, pbch_pdu, 0); } - generate_pbch(&PHY_vars_eNb->lte_eNB_pbch, - PHY_vars_eNb->lte_eNB_common_vars.txdataF[0], + generate_pbch(&PHY_vars_eNB->lte_eNB_pbch, + PHY_vars_eNB->lte_eNB_common_vars.txdataF[0], AMP, - &PHY_vars_eNb->lte_frame_parms, + &PHY_vars_eNB->lte_frame_parms, pbch_pdu, pbch_phase); */ - write_output("txsigF0.m","txsF0", PHY_vars_eNb->lte_eNB_common_vars.txdataF[0][0],FRAME_LENGTH_COMPLEX_SAMPLES_NO_PREFIX,1,1); + write_output("txsigF0.m","txsF0", PHY_vars_eNB->lte_eNB_common_vars.txdataF[0][0],FRAME_LENGTH_COMPLEX_SAMPLES_NO_PREFIX,1,1); - if (PHY_vars_eNb->lte_frame_parms.nb_antennas_tx>1) - write_output("txsigF1.m","txsF1", PHY_vars_eNb->lte_eNB_common_vars.txdataF[0][1],FRAME_LENGTH_COMPLEX_SAMPLES_NO_PREFIX,1,1); + if (PHY_vars_eNB->lte_frame_parms.nb_antennas_tx>1) + write_output("txsigF1.m","txsF1", PHY_vars_eNB->lte_eNB_common_vars.txdataF[0][1],FRAME_LENGTH_COMPLEX_SAMPLES_NO_PREFIX,1,1); tx_lev = 0; tx_lev1 = 0; @@ -620,16 +547,16 @@ int main(int argc, char **argv) - for (aa=0; aalte_frame_parms.nb_antennas_tx; aa++) { + for (aa=0; aalte_frame_parms.nb_antennas_tx; aa++) { if (frame_parms->Ncp == 1) - PHY_ofdm_mod(PHY_vars_eNb->lte_eNB_common_vars.txdataF[0][aa], // input, + PHY_ofdm_mod(PHY_vars_eNB->lte_eNB_common_vars.txdataF[0][aa], // input, txdata[aa], // output - frame_parms->log2_symbol_size, // log2_fft_size + frame_parms->ofdm_symbol_size, LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*nsymb, // number of symbols frame_parms->nb_prefix_samples, // number of prefix samples CYCLIC_PREFIX); else { - normal_prefix_mod(PHY_vars_eNb->lte_eNB_common_vars.txdataF[0][aa], + normal_prefix_mod(PHY_vars_eNB->lte_eNB_common_vars.txdataF[0][aa], txdata[aa], LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*nsymb, frame_parms); @@ -648,7 +575,7 @@ int main(int argc, char **argv) // multipath channel for (i=0; i<2*nsymb*OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES; i++) { - for (aa=0; aalte_frame_parms.nb_antennas_tx; aa++) { + for (aa=0; aalte_frame_parms.nb_antennas_tx; aa++) { s_re[aa][i] = ((double)(((short *)txdata[aa]))[(i<<1)]); s_im[aa][i] = ((double)(((short *)txdata[aa]))[(i<<1)+1]); } @@ -667,7 +594,7 @@ int main(int argc, char **argv) multipath_channel(eNB2UE,s_re,s_im,r_re,r_im, 2*nsymb*OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES,0); - sigma2_dB = 10*log10((double)tx_lev) +10*log10((double)PHY_vars_eNb->lte_frame_parms.ofdm_symbol_size/(double)(12*NB_RB)) - SNR; + sigma2_dB = 10*log10((double)tx_lev) +10*log10((double)PHY_vars_eNB->lte_frame_parms.ofdm_symbol_size/(double)(12*NB_RB)) - SNR; if (n_frames==1) printf("sigma2_dB %f (SNR %f dB) tx_lev_dB %f,%f,%f\n",sigma2_dB,SNR, @@ -689,7 +616,7 @@ int main(int argc, char **argv) for (n_trials=0; n_trialslte_frame_parms.nb_antennas_rx; aa++) { + for (aa=0; aalte_frame_parms.nb_antennas_rx; aa++) { ((short*) PHY_vars_UE->lte_ue_common_vars.rxdata[aa])[2*i] = (short) ((r_re[aa][i] +sqrt(sigma2/2)*gaussdouble(0.0,1.0))); ((short*) PHY_vars_UE->lte_ue_common_vars.rxdata[aa])[2*i+1] = (short) ((r_im[aa][i] + (iqim*r_re[aa][i]) + sqrt(sigma2/2)*gaussdouble(0.0,1.0))); } diff --git a/openair1/SIMULATION/LTE_PHY/syncsim.c b/openair1/SIMULATION/LTE_PHY/syncsim.c index a5f046da93..45b69adcc5 100644 --- a/openair1/SIMULATION/LTE_PHY/syncsim.c +++ b/openair1/SIMULATION/LTE_PHY/syncsim.c @@ -1189,7 +1189,7 @@ int main(int argc, char **argv) if (frame_parms->Ncp == 1) PHY_ofdm_mod(txdataF2[aa], // input txdata[aa], // output - PHY_vars_eNB->lte_frame_parms.log2_symbol_size, // log2_fft_size + PHY_vars_eNB->lte_frame_parms.ofdm_symbol_size, // log2_fft_size LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*nsymb, // number of symbols PHY_vars_eNB->lte_frame_parms.nb_prefix_samples, // number of prefix samples PHY_vars_eNB->lte_frame_parms.twiddle_ifft, // IFFT twiddle factors @@ -1218,7 +1218,7 @@ int main(int argc, char **argv) if (frame_parms->Ncp == 1) PHY_ofdm_mod(PHY_vars_eNB->lte_eNB_common_vars.txdataF[eNb_id][aa], // input, txdata[aa], // output - frame_parms->log2_symbol_size, // log2_fft_size + frame_parms->ofdm_symbol_size, // log2_fft_size LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*nsymb, // number of symbols frame_parms->nb_prefix_samples, // number of prefix samples frame_parms->twiddle_ifft, // IFFT twiddle factors @@ -1240,7 +1240,7 @@ int main(int argc, char **argv) if (frame_parms->Ncp == 1) PHY_ofdm_mod(PHY_vars_eNB1->lte_eNB_common_vars.txdataF[eNb_id][aa], // input, PHY_vars_eNB1->lte_eNB_common_vars.txdata[eNb_id][aa], // output - frame_parms->log2_symbol_size, // log2_fft_size + frame_parms->ofdm_symbol_size, // log2_fft_size LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*nsymb, // number of symbols frame_parms->nb_prefix_samples, // number of prefix samples frame_parms->twiddle_ifft, // IFFT twiddle factors @@ -1260,7 +1260,7 @@ int main(int argc, char **argv) if (frame_parms->Ncp == 1) PHY_ofdm_mod(PHY_vars_eNB2->lte_eNB_common_vars.txdataF[eNb_id][aa], // input, PHY_vars_eNB2->lte_eNB_common_vars.txdata[eNb_id][aa], // output - frame_parms->log2_symbol_size, // log2_fft_size + frame_parms->ofdm_symbol_size, // log2_fft_size LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*nsymb, // number of symbols frame_parms->nb_prefix_samples, // number of prefix samples frame_parms->twiddle_ifft, // IFFT twiddle factors diff --git a/openair1/SIMULATION/LTE_PHY/ulsim.c b/openair1/SIMULATION/LTE_PHY/ulsim.c index de2789acef..4a78667535 100644 --- a/openair1/SIMULATION/LTE_PHY/ulsim.c +++ b/openair1/SIMULATION/LTE_PHY/ulsim.c @@ -89,60 +89,6 @@ double t_rx_min = 1000000000; /*!< \brief initial min process time for tx */ int n_tx_dropped = 0; /*!< \brief initial max process time for tx */ int n_rx_dropped = 0; /*!< \brief initial max process time for rx */ -void lte_param_init(unsigned char N_tx, unsigned char N_rx,unsigned char transmission_mode,uint8_t extended_prefix_flag,uint8_t N_RB_DL,uint8_t frame_type,uint8_t tdd_config,uint8_t osf) -{ - - LTE_DL_FRAME_PARMS *lte_frame_parms; - - printf("Start lte_param_init\n"); - PHY_vars_eNB = malloc(sizeof(PHY_VARS_eNB)); - PHY_vars_UE = malloc(sizeof(PHY_VARS_UE)); - //PHY_config = malloc(sizeof(PHY_CONFIG)); - mac_xface = malloc(sizeof(MAC_xface)); - - randominit(0); - set_taus_seed(0); - - lte_frame_parms = &(PHY_vars_eNB->lte_frame_parms); - - lte_frame_parms->frame_type = frame_type; - lte_frame_parms->tdd_config = tdd_config; - lte_frame_parms->N_RB_DL = N_RB_DL; //50 for 10MHz and 25 for 5 MHz - lte_frame_parms->N_RB_UL = N_RB_DL; - lte_frame_parms->Ncp = extended_prefix_flag; - lte_frame_parms->Ncp_UL = extended_prefix_flag; - lte_frame_parms->Nid_cell = 10; - lte_frame_parms->nushift = 0; - lte_frame_parms->nb_antennas_tx = N_tx; - lte_frame_parms->nb_antennas_rx = N_rx; - // lte_frame_parms->Csrs = 2; - // lte_frame_parms->Bsrs = 0; - // lte_frame_parms->kTC = 0; - // lte_frame_parms->n_RRC = 0; - lte_frame_parms->mode1_flag = (transmission_mode == 1)? 1 : 0; - lte_frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.cyclicShift = 0;//n_DMRS1 set to 0 - - init_frame_parms(lte_frame_parms,osf); - - //copy_lte_parms_to_phy_framing(lte_frame_parms, &(PHY_config->PHY_framing)); - - - PHY_vars_UE->lte_frame_parms = *lte_frame_parms; - - phy_init_lte_top(lte_frame_parms); - - phy_init_lte_ue(PHY_vars_UE,1,0); - - phy_init_lte_eNB(PHY_vars_eNB,0,0,0); - - printf("Done lte_param_init\n"); - - -} - - - - int main(int argc, char **argv) { @@ -520,7 +466,16 @@ int main(int argc, char **argv) } } - lte_param_init(1,n_rx,1,extended_prefix_flag,N_RB_DL,frame_type,tdd_config,osf); + lte_param_init(1, + n_rx, + 1, + extended_prefix_flag, + frame_type, + 0, + tdd_config, + N_RB_DL, + osf, + 0); if (nb_rb_set == 0) nb_rb = PHY_vars_eNB->lte_frame_parms.N_RB_UL; @@ -1109,7 +1064,7 @@ int main(int argc, char **argv) if (frame_parms->Ncp == 1) PHY_ofdm_mod(&PHY_vars_UE->lte_ue_common_vars.txdataF[aa][subframe*nsymb*OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES_NO_PREFIX], // input &txdata[aa][PHY_vars_eNB->lte_frame_parms.samples_per_tti*subframe], // output - PHY_vars_UE->lte_frame_parms.log2_symbol_size, // log2_fft_size + PHY_vars_UE->lte_frame_parms.ofdm_symbol_size, nsymb, // number of symbols PHY_vars_UE->lte_frame_parms.nb_prefix_samples, // number of prefix samples CYCLIC_PREFIX); From 7f53f84c00dc748e24122e1eea3fc25563280aee Mon Sep 17 00:00:00 2001 From: Raymond Knopp Date: Tue, 29 Dec 2015 20:34:47 +0100 Subject: [PATCH 076/263] Tested modifications for 23.04 Ms/s 100 PRB transmission/reception (Downlink). This will reduce I/Q acquisition times for 20 MHz channels. new option in dlsim (-E) for testing 1536-point DFT instead of 2048 for this lower sampling rate. Added normalization to idft1536. Should also be added to dft1536 later. --- openair1/SIMULATION/LTE_PHY/dlsim.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/openair1/SIMULATION/LTE_PHY/dlsim.c b/openair1/SIMULATION/LTE_PHY/dlsim.c index d4781f58b2..a5c2b28c07 100644 --- a/openair1/SIMULATION/LTE_PHY/dlsim.c +++ b/openair1/SIMULATION/LTE_PHY/dlsim.c @@ -2483,7 +2483,7 @@ PMI_FEEDBACK: } } } - /* + num_pdcch_symbols_2 = generate_dci_top(num_ue_spec_dci, num_common_dci, dci_alloc, @@ -2492,7 +2492,7 @@ PMI_FEEDBACK: &PHY_vars_eNB->lte_frame_parms, PHY_vars_eNB->lte_eNB_common_vars.txdataF[eNB_id], subframe); - */ + if (num_pdcch_symbols_2 > num_pdcch_symbols) { msg("Error: given num_pdcch_symbols not big enough (%d > %d)\n",num_pdcch_symbols_2,num_pdcch_symbols); exit(-1); From 959f13e1e7fa6324fda6e6dcd7b9456076c6880b Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Tue, 29 Dec 2015 20:41:43 +0100 Subject: [PATCH 077/263] minor bugfix related to cleanup script --- cmake_targets/autotests/run_exec_lte-softmodem_tests.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake_targets/autotests/run_exec_lte-softmodem_tests.py b/cmake_targets/autotests/run_exec_lte-softmodem_tests.py index 7b4f126798..2e1f5c4fc3 100644 --- a/cmake_targets/autotests/run_exec_lte-softmodem_tests.py +++ b/cmake_targets/autotests/run_exec_lte-softmodem_tests.py @@ -927,6 +927,7 @@ GitOAI5GHeadVersion='' user='' pw='' NFSResultsShare='' +cleanUpRemoteMachines=False openairdir_local = os.environ.get('OPENAIR_DIR') if openairdir_local is None: print "Environment variable OPENAIR_DIR not set correctly" @@ -1039,7 +1040,6 @@ xmlInputFile=os.environ.get('OPENAIR_DIR')+"/cmake_targets/autotests/test_case_l NFSResultsDir = '/mnt/sradio' cleanupOldProgramsScript = '$OPENAIR_DIR/cmake_targets/autotests/tools/remove_old_programs.bash' testcasegroup='' -cleanUpRemoteMachines=False logdir = '/tmp/' + 'OAITestFrameWork-' + user + '/' logdirOAI5GRepo = logdir + 'openairinterface5g/' logdirOpenaircnRepo = logdir + 'openair-cn/' From 91c43fa2ea896d07e4070bed7e61ff0c576a3861 Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Tue, 29 Dec 2015 20:49:11 +0100 Subject: [PATCH 078/263] updates for terminating program after fatal SSH Errors --- cmake_targets/autotests/openair.py | 9 +++++++-- cmake_targets/autotests/run_exec_lte-softmodem_tests.py | 5 ++++- 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/cmake_targets/autotests/openair.py b/cmake_targets/autotests/openair.py index 8427735c61..b61a296761 100644 --- a/cmake_targets/autotests/openair.py +++ b/cmake_targets/autotests/openair.py @@ -83,10 +83,13 @@ class openair(core): return (stdout, stderr) def connect(self, username, password, prompt='PEXPECT_OAI'): - while True: + max_retries=100 + i=0 + while i <= max_retries: self.prompt1 = prompt self.prompt2 = prompt self.password = '' + i=i+1 # WE do not store the password when sending commands for secuirity reasons. The password might be accidentally logged in such cases. #The password is used only to make ssh connections. In case user wants to run programs with sudo, then he/she needs to add following line in /etc/sudoers # your_user_name ALL=(ALL:ALL) NOPASSWD: ALL @@ -113,7 +116,9 @@ class openair(core): print error print "Retrying again in 1 seconds" time.sleep(1) - #sys.exit(1) + if i==max_retries: + print "Fatal Error: Terminating the program now..." + sys.exit(1) def connect2(self, username, password, prompt='$'): self.prompt1 = prompt diff --git a/cmake_targets/autotests/run_exec_lte-softmodem_tests.py b/cmake_targets/autotests/run_exec_lte-softmodem_tests.py index 2e1f5c4fc3..905847230a 100644 --- a/cmake_targets/autotests/run_exec_lte-softmodem_tests.py +++ b/cmake_targets/autotests/run_exec_lte-softmodem_tests.py @@ -273,9 +273,12 @@ def SSHSessionWrapper(machine, username, key_file, password, logdir_remote_testc error = error + '\n username = ' + username + '\n machine = ' + machine + '\n logdir_remote = ' + logdir_remote_testcase + '\n logdir_local_base = ' + logdir_local_base error = error + traceback.format_exc() print error - print " Trying again in 1 seconds" + print " Retrying again in 1 seconds" time.sleep(1) print "Continuing ..." + if i ==max_tries: + print "Fatal Error: Max no of retries reached. Exiting now..." + sys.exit(1) From f53df3521f1714961f81ad45bb2dd76aa09a3cbb Mon Sep 17 00:00:00 2001 From: Raymond Knopp Date: Wed, 30 Dec 2015 09:53:48 +0100 Subject: [PATCH 079/263] added 23.04 Ms/s sampling option to lte-softmodem (under test) --- targets/RT/USER/lte-softmodem.c | 28 +++++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/targets/RT/USER/lte-softmodem.c b/targets/RT/USER/lte-softmodem.c index 2409f102a4..ca07b15e90 100644 --- a/targets/RT/USER/lte-softmodem.c +++ b/targets/RT/USER/lte-softmodem.c @@ -235,6 +235,7 @@ static int time_offset[4] = {0,0,0,0}; static char UE_flag=0; //static uint8_t eNB_id=0,UE_id=0; +static char threequarter_fs=0; uint32_t downlink_frequency[MAX_NUM_CCs][4]; int32_t uplink_frequency_offset[MAX_NUM_CCs][4]; @@ -909,13 +910,13 @@ void do_OFDM_mod_rt(int subframe,PHY_VARS_eNB *phy_vars_eNB) if (phy_vars_eNB->lte_frame_parms.Ncp == EXTENDED) { PHY_ofdm_mod(&phy_vars_eNB->lte_eNB_common_vars.txdataF[0][aa][slot_offset_F], dummy_tx_b, - phy_vars_eNB->lte_frame_parms.log2_symbol_size, + phy_vars_eNB->lte_frame_parms.ofdm_symbol_size, 6, phy_vars_eNB->lte_frame_parms.nb_prefix_samples, CYCLIC_PREFIX); PHY_ofdm_mod(&phy_vars_eNB->lte_eNB_common_vars.txdataF[0][aa][slot_offset_F+slot_sizeF], dummy_tx_b+(phy_vars_eNB->lte_frame_parms.samples_per_tti>>1), - phy_vars_eNB->lte_frame_parms.log2_symbol_size, + phy_vars_eNB->lte_frame_parms.ofdm_symbol_size, 6, phy_vars_eNB->lte_frame_parms.nb_prefix_samples, CYCLIC_PREFIX); @@ -2060,7 +2061,7 @@ static void get_options (int argc, char **argv) {NULL, 0, NULL, 0} }; - while ((c = getopt_long (argc, argv, "A:a:C:dK:g:F:G:hqO:m:SUVRM:r:P:Ws:t:Tx:",long_options,NULL)) != -1) { + while ((c = getopt_long (argc, argv, "A:a:C:dEK:g:F:G:hqO:m:SUVRM:r:P:Ws:t:Tx:",long_options,NULL)) != -1) { switch (c) { case LONG_OPTION_MAXPOWER: tx_max_power[0]=atoi(optarg); @@ -2162,6 +2163,10 @@ static void get_options (int argc, char **argv) printf("Running with XFORMS!\n"); #endif break; + + case 'E': + threequarter_fs=1; + break; case 'K': #if defined(ENABLE_ITTI) @@ -2671,6 +2676,7 @@ int main( int argc, char **argv ) frame_parms[CC_id]->pusch_config_common.ul_ReferenceSignalsPUSCH.groupHoppingEnabled = 0; frame_parms[CC_id]->pusch_config_common.ul_ReferenceSignalsPUSCH.sequenceHoppingEnabled = 0; frame_parms[CC_id]->pusch_config_common.ul_ReferenceSignalsPUSCH.groupAssignmentPUSCH = 0; + frame_parms[CC_id]->threequarter_fs = threequarter_fs; init_ul_hopping(frame_parms[CC_id]); init_frame_parms(frame_parms[CC_id],1); // phy_init_top(frame_parms[CC_id]); @@ -2876,10 +2882,18 @@ int main( int argc, char **argv ) for (card=0; cardN_RB_DL == 100) { - openair0_cfg[card].sample_rate=30.72e6; - openair0_cfg[card].samples_per_frame = 307200; - openair0_cfg[card].tx_bw = 10e6; - openair0_cfg[card].rx_bw = 10e6; + if (frame_parms[0]->threequarter_fs) { + openair0_cfg[card].sample_rate=23.04e6; + openair0_cfg[card].samples_per_frame = 230400; + openair0_cfg[card].tx_bw = 10e6; + openair0_cfg[card].rx_bw = 10e6; + } + else { + openair0_cfg[card].sample_rate=30.72e6; + openair0_cfg[card].samples_per_frame = 307200; + openair0_cfg[card].tx_bw = 10e6; + openair0_cfg[card].rx_bw = 10e6; + } } else if(frame_parms[0]->N_RB_DL == 50) { openair0_cfg[card].sample_rate=15.36e6; openair0_cfg[card].samples_per_frame = 153600; From 09e354a240d263f30e77cd26c237b16f1e70f568 Mon Sep 17 00:00:00 2001 From: Raymond Knopp Date: Wed, 30 Dec 2015 11:49:21 +0100 Subject: [PATCH 080/263] tested 23.04 Ms/s sampling for 20 MHz on USRP B210, modifications in usrp_lib.cpp. --- targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp | 12 +++++++++++- .../CONF/enb.band7.tm1.100PRB.usrpb210.conf | 4 ++-- .../CONF/enb.band7.tm1.50PRB.usrpb210.conf | 4 ++-- 3 files changed, 15 insertions(+), 5 deletions(-) diff --git a/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp b/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp index b12f7397f0..1cf3359e0e 100644 --- a/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp +++ b/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp @@ -446,28 +446,38 @@ int openair0_dev_init_usrp(openair0_device* device, openair0_config_t *openair0_ // set master clock rate and sample rate for tx & rx for streaming device->type = USRP_B200_IF; - s->usrp->set_master_clock_rate(30.72e6); + openair0_cfg[0].rx_gain_calib_table = calib_table_b210; switch ((int)openair0_cfg[0].sample_rate) { case 30720000: + s->usrp->set_master_clock_rate(30.72e6); // from usrp_time_offset openair0_cfg[0].samples_per_packet = 2048; openair0_cfg[0].tx_sample_advance = 115; openair0_cfg[0].tx_scheduling_advance = 11*openair0_cfg[0].samples_per_packet; break; + case 23040000: + s->usrp->set_master_clock_rate(46.08e6); + openair0_cfg[0].samples_per_packet = 2048; + openair0_cfg[0].tx_sample_advance = 113; + openair0_cfg[0].tx_scheduling_advance = 8*openair0_cfg[0].samples_per_packet; + break; case 15360000: + s->usrp->set_master_clock_rate(30.72e6); openair0_cfg[0].samples_per_packet = 2048; openair0_cfg[0].tx_sample_advance = 113; openair0_cfg[0].tx_scheduling_advance = 5*openair0_cfg[0].samples_per_packet; break; case 7680000: + s->usrp->set_master_clock_rate(30.72e6); openair0_cfg[0].samples_per_packet = 1024; openair0_cfg[0].tx_sample_advance = 70;//103; openair0_cfg[0].tx_scheduling_advance = 5*openair0_cfg[0].samples_per_packet; break; case 1920000: + s->usrp->set_master_clock_rate(30.72e6); openair0_cfg[0].samples_per_packet = 256; openair0_cfg[0].tx_sample_advance = 40; openair0_cfg[0].tx_scheduling_advance = 8*openair0_cfg[0].samples_per_packet; diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.100PRB.usrpb210.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.100PRB.usrpb210.conf index 1d47abdd60..174eda2c81 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.100PRB.usrpb210.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.100PRB.usrpb210.conf @@ -28,7 +28,7 @@ eNBs = tdd_config_s = 0; prefix_type = "NORMAL"; eutra_band = 7; - downlink_frequency = 2660000000L; + downlink_frequency = 2680000000L; uplink_frequency_offset = -120000000; Nid_cell = 0; N_RB_DL = 100; @@ -36,7 +36,7 @@ eNBs = nb_antennas_tx = 1; nb_antennas_rx = 1; tx_gain = 90; - rx_gain = 120; + rx_gain = 127; prach_root = 0; prach_config_index = 0; prach_high_speed = "DISABLE"; diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpb210.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpb210.conf index 8f9dc280ae..6d4910c7c5 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpb210.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpb210.conf @@ -28,7 +28,7 @@ eNBs = tdd_config_s = 0; prefix_type = "NORMAL"; eutra_band = 7; - downlink_frequency = 2660000000L; + downlink_frequency = 2680000000L; uplink_frequency_offset = -120000000; Nid_cell = 0; N_RB_DL = 50; @@ -36,7 +36,7 @@ eNBs = nb_antennas_tx = 1; nb_antennas_rx = 1; tx_gain = 90; - rx_gain = 118; + rx_gain = 130; prach_root = 0; prach_config_index = 0; prach_high_speed = "DISABLE"; From ffc468e5df4f32d63cfd1959d5fb194b27ba7aee Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Wed, 30 Dec 2015 13:00:25 +0100 Subject: [PATCH 081/263] bugfixes for intergration with GitLabCI --- cmake_targets/autotests/core.py | 5 +-- cmake_targets/autotests/openair.py | 1 + .../autotests/run_exec_lte-softmodem_tests.py | 45 +++++++++++++------ cmake_targets/autotests/test_case_list.xml | 4 +- 4 files changed, 36 insertions(+), 19 deletions(-) diff --git a/cmake_targets/autotests/core.py b/cmake_targets/autotests/core.py index ee53438207..18f89ecfce 100644 --- a/cmake_targets/autotests/core.py +++ b/cmake_targets/autotests/core.py @@ -118,8 +118,7 @@ class core: rsp1 = self.prompt1 rsp2 = self.prompt2 if sudo == True: - command = 'echo \'' + self.password + '\' | sudo -S -E ' + command - + command = 'echo \'' + '' + '\' | sudo -S -E bash -c \' ' + command + '\' ' self.wait_quiet() if self.send_cr: log.stats['cmd'] += 1 @@ -140,7 +139,7 @@ class core: rsp2 = self.prompt2 self.wait_quiet() if sudo == True: - command = 'echo \'' + self.password + '\' | sudo -S -E ' + command + command = 'echo \'' + '' + '\' | sudo -S -E bash -c \' ' + command + '\' ' if self.send_cr: log.stats['cmd'] += 1 self.oai.sendline(command) diff --git a/cmake_targets/autotests/openair.py b/cmake_targets/autotests/openair.py index b61a296761..1079c466a8 100644 --- a/cmake_targets/autotests/openair.py +++ b/cmake_targets/autotests/openair.py @@ -112,6 +112,7 @@ class openair(core): except Exception, e: error='' error = error + ' In function: ' + sys._getframe().f_code.co_name + ': *** Caught exception: ' + str(e.__class__) + " : " + str( e) + error = error + 'address = "'+ self.address +' username = ' + username error = error + traceback.format_exc() print error print "Retrying again in 1 seconds" diff --git a/cmake_targets/autotests/run_exec_lte-softmodem_tests.py b/cmake_targets/autotests/run_exec_lte-softmodem_tests.py index 905847230a..a41254d105 100644 --- a/cmake_targets/autotests/run_exec_lte-softmodem_tests.py +++ b/cmake_targets/autotests/run_exec_lte-softmodem_tests.py @@ -262,7 +262,7 @@ def SSHSessionWrapper(machine, username, key_file, password, logdir_remote_testc if operation == "get_all": ssh.get_all(logdir_remote_testcase , logdir_local_base) elif operation == "put_all": - ssh.put_all(logdir_remote_testcase , logdir_local_base) + ssh.put_all(logdir_local_base, logdir_remote_testcase ) else: print "Error: Uknown operation in SSHSessionWrapper. Exiting now..." sys.exit(1) @@ -929,13 +929,16 @@ GitOAI5GRepoBranch='' GitOAI5GHeadVersion='' user='' pw='' +testcasegroup='' NFSResultsShare='' cleanUpRemoteMachines=False openairdir_local = os.environ.get('OPENAIR_DIR') if openairdir_local is None: print "Environment variable OPENAIR_DIR not set correctly" sys.exit() -locallogdir = openairdir_local + '/cmake_targets/autotests/log/' +locallogdir = openairdir_local + '/cmake_targets/autotests/log' +MachineList = '' +MachinneListGeneric='' #Remove the contents of local log directory #os.system(' rm -fr ' + locallogdir + '; mkdir -p ' + locallogdir ) flag_remove_logdir=False @@ -987,6 +990,16 @@ while i < len (sys.argv): elif arg == '-n': NFSResultsShare = sys.argv[i+1] i = i +1 + elif arg == '-MachineList': + MachineList = sys.argv[i+1] + MachineList = MachineList.replace("\"","") + MachineList = MachineList.replace("\'","") + i = i +1 + elif arg == '-MachineListGeneric': + MachineListGeneric = sys.argv[i+1] + MachineListGeneric = MachineListGeneric.replace("\"","") + MachineListGeneric = MachineListGeneric.replace("\'","") + i = i +1 elif arg == '-h' : print "-d: low debug level" print "-dd: high debug level" @@ -1001,6 +1014,8 @@ while i < len (sys.argv): print "-u: use the user name passed as argument" print "-p: use the password passed as an argument" print "-n: Set the NFS share passed as an argument" + print "-MachineList : overrides the MachineList parameter in test_case_list.xml" + print "-MachineListGeneric : overrides the MachineListGeneric parameter in test_case_list.xml" sys.exit() else : print "Unrecongnized Option: <" + arg + ">. Use -h to see valid options" @@ -1042,7 +1057,6 @@ print "user = " + user xmlInputFile=os.environ.get('OPENAIR_DIR')+"/cmake_targets/autotests/test_case_list.xml" NFSResultsDir = '/mnt/sradio' cleanupOldProgramsScript = '$OPENAIR_DIR/cmake_targets/autotests/tools/remove_old_programs.bash' -testcasegroup='' logdir = '/tmp/' + 'OAITestFrameWork-' + user + '/' logdirOAI5GRepo = logdir + 'openairinterface5g/' logdirOpenaircnRepo = logdir + 'openair-cn/' @@ -1063,8 +1077,8 @@ xmlRoot = xmlTree.getroot() - -MachineList = xmlRoot.findtext('MachineList',default='') +if MachineList =='': + MachineList = xmlRoot.findtext('MachineList',default='') NFSResultsShare = xmlRoot.findtext('NFSResultsShare',default='') GitOpenaircnRepo = xmlRoot.findtext('GitOpenair-cnRepo',default='') GitOAI5GRepo = xmlRoot.findtext('GitOAI5GRepo',default='') @@ -1076,7 +1090,8 @@ GitOpenaircnRepoBranch = xmlRoot.findtext('GitOpenair-cnRepoBranch',default='') CleanUpOldProgs = xmlRoot.findtext('CleanUpOldProgs',default='') CleanUpAluLteBox = xmlRoot.findtext('CleanUpAluLteBox',default='') Timeout_execution = int (xmlRoot.findtext('Timeout_execution')) -MachineListGeneric = xmlRoot.findtext('MachineListGeneric',default='') +if MachineListGeneric == '': + MachineListGeneric = xmlRoot.findtext('MachineListGeneric',default='') TestCaseExclusionList = xmlRoot.findtext('TestCaseExclusionList',default='') ExmimoRfStop = xmlRoot.findtext('ExmimoRfStop',default='') @@ -1100,7 +1115,7 @@ if GitOAI5GHeadVersion == '': print "Error getting the OAI5GBranch Head version...Exiting" sys.exit() -NFSTestsResultsDir = NFSResultsShare + '/'+ GitOAI5GRepoBranch + '/' + GitOAI5GHeadVersion + '/' +NFSTestsResultsDir = NFSResultsShare + '/'+ GitOAI5GRepoBranch + '/' + GitOAI5GHeadVersion print "NFSTestsResultsDir = " + NFSTestsResultsDir @@ -1338,7 +1353,6 @@ for testcase in testcaseList: desc = testcase.findtext('desc',default='') #print "Machine list top level = " + ','.join(MachineList) if search_test_case_group(testcasename, testcasegroup, TestCaseExclusionList) == True: - cleanOldProgramsAllMachines(oai_list, CleanUpOldProgs, CleanUpAluLteBox, ExmimoRfStop) if testcaseclass == 'lte-softmodem' : eNBMachine = testcase.findtext('eNB',default='') UEMachine = testcase.findtext('UE',default='') @@ -1351,11 +1365,12 @@ for testcase in testcaseList: print "eNBMachine : " + eNBMachine + "UEMachine : " + UEMachine + "EPCMachine : " + EPCMachine + "MachineList : " + ','.join(MachineList) print "testcasename = " + testcasename + " class = " + testcaseclass threadListGlobal = wait_testcaseclass_generic_threads(threadListGlobal, Timeout_execution) + cleanOldProgramsAllMachines(oai_list, CleanUpOldProgs, CleanUpAluLteBox, ExmimoRfStop) handle_testcaseclass_softmodem (testcase, CleanUpOldProgs, logdirOAI5GRepo, logdirOpenaircnRepo, MachineList, user, pw, CleanUpAluLteBox, ExmimoRfStop ) elif (testcaseclass == 'compilation'): threadListGlobal = handle_testcaseclass_generic (testcasename, threadListGlobal, CleanUpOldProgs, logdirOAI5GRepo, MachineListGeneric, user, pw, CleanUpAluLteBox,Timeout_execution, ExmimoRfStop) elif (testcaseclass == 'execution'): - threadListGlobal = handle_testcaseclass_generic (testcasename, threadListGlobal, CleanUpOldProgs, logdirOAI5GRepo, MachineListGeneric, user, pw, CleanUpAluLteBox,ExmimoRfStop) + threadListGlobal = handle_testcaseclass_generic (testcasename, threadListGlobal, CleanUpOldProgs, logdirOAI5GRepo, MachineListGeneric, user, pw, CleanUpAluLteBox, Timeout_execution, ExmimoRfStop) else : print "Unknown test case class: " + testcaseclass sys.exit() @@ -1370,13 +1385,15 @@ for testcase in testcaseList: #sys.exit(1) -print "Exiting the test cases execution now..." +print "Exiting the test cases execution now. Waiting for existing threads to complete..." -for t in threadListGlobal: - t.join +for param in threadListGlobal: + thread_id = param["thread_id"] + thread_id.join() +print "Creating xml file for overall results..." cmd = "cat $OPENAIR_DIR/cmake_targets/autotests/log/*/*.xml > $OPENAIR_DIR/cmake_targets/autotests/log/results_autotests.xml " -os.system('cmd') +res=os.system(cmd) print "Now copying files to NFS Share" oai_localhost = openair('localdomain','localhost') @@ -1388,7 +1405,7 @@ print "Deleting NFSTestResults Dir..." + res print "Copying files from GilabCI Runner Machine : " + host + "locallogdir = " + locallogdir + ", NFSTestsResultsDir = " + NFSTestsResultsDir #ssh = SSHSession(UEMachine , username=user, key_file=None, password=password) #ssh.get_all(logdir_UE , logdir_local + '/cmake_targets/autotests/log/'+ testcasename) -SSHSessionWrapper('localhost', user, None, password, NFSTestsResultsDir , locallogdir, "put_all") +SSHSessionWrapper('localhost', user, None, pw , NFSTestsResultsDir , locallogdir, "put_all") sys.exit() diff --git a/cmake_targets/autotests/test_case_list.xml b/cmake_targets/autotests/test_case_list.xml index 8b8d5c01e0..4141c5c1ee 100644 --- a/cmake_targets/autotests/test_case_list.xml +++ b/cmake_targets/autotests/test_case_list.xml @@ -1,6 +1,6 @@ -calisson mozart stevens nano amerique +mozart calisson stevens nano /mnt/sradio/TEST_RESULTS/ https://gitlab.eurecom.fr/oai/openairinterface5g.git https://gitlab.eurecom.fr/oai/openair-cn.git @@ -11,7 +11,7 @@ $OPENAIR_DIR/cmake_targets/build_oai -w EXMIMO -c; sudo -S -E $OPENAIR_DIR/cmake_targets/tools/stop_exmimo2; dmesg|tail 36000 0104+ 015502 015505 015506 015507 015508 015508 015509 015510 015511 015600 015700 016102 016105 - calisson stevens mozart nano amerique + mozart calisson stevens nano compilation Build oaisim.Rel8 From 5fab5dc7997a0df22fa9c4dd10920ee4867eea9d Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Wed, 30 Dec 2015 13:03:47 +0100 Subject: [PATCH 082/263] fixes for BLADERF test case tag + addition of amerique --- cmake_targets/autotests/test_case_list.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cmake_targets/autotests/test_case_list.xml b/cmake_targets/autotests/test_case_list.xml index 4141c5c1ee..afbc1ede48 100644 --- a/cmake_targets/autotests/test_case_list.xml +++ b/cmake_targets/autotests/test_case_list.xml @@ -1,6 +1,6 @@ -mozart calisson stevens nano +mozart calisson stevens nano amerique /mnt/sradio/TEST_RESULTS/ https://gitlab.eurecom.fr/oai/openairinterface5g.git https://gitlab.eurecom.fr/oai/openair-cn.git @@ -11,7 +11,7 @@ $OPENAIR_DIR/cmake_targets/build_oai -w EXMIMO -c; sudo -S -E $OPENAIR_DIR/cmake_targets/tools/stop_exmimo2; dmesg|tail 36000 0104+ 015502 015505 015506 015507 015508 015508 015509 015510 015511 015600 015700 016102 016105 - mozart calisson stevens nano + mozart calisson stevens nano amerique compilation Build oaisim.Rel8 @@ -128,7 +128,7 @@ - lte-softmodem_noS1.EXMIMO.Rel10 + lte-softmodem_noS1.BLADERF.Rel10 1 From a6099ff46f03d7ebb2070cbfe39850b16e825c24 Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Wed, 30 Dec 2015 13:07:55 +0100 Subject: [PATCH 083/263] fix for rsync script --- .gitlab-ci.yml | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 36da36ec5d..414a8a6356 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -20,6 +20,5 @@ job1: - echo $EXTERNAL_SHARE_RESULTS_DIR - python $OPENAIR_DIR/cmake_targets/autotests/run_exec_lte-softmodem_tests.py -r -5GRepoHeadVersion $git_head -n $NFS_SHARE_DIR -u $OAI_USER -p $OAI_PASS >& $OPENAIR_DIR/cmake_targets/autotests/python_autotest.log - mv $OPENAIR_DIR/cmake_targets/autotests/python_autotest.log $OPENAIR_DIR/cmake_targets/autotests/log/python_autotest.log - - sshpass -p "$OAI_PASS" rsync -avz -e "ssh -o StrictHostKeyChecking=no " –rsync-path=”mkdir -p $NFS_TEST_RESULTS_DIR && rsync” $OPENAIR_DIR/cmake_targets/autotests/log/ $OAI_USER@localhost:$NFS_TEST_RESULTS_DIR - - sshpass -p "$OAI_PASS" rsync -avz -e "ssh -o StrictHostKeyChecking=no " –rsync-path=”mkdir -p $NFS_TEST_RESULTS_DIR && rsync” $OPENAIR_DIR/cmake_targets/autotests/log/ $OAI_USER@localhost:$EXTERNAL_SHARE_DIR - + - sshpass -p "$OAI_PASS" rsync -az -e "ssh -o StrictHostKeyChecking=no " --rsync-path="mkdir -p $NFS_TEST_RESULTS_DIR && rsync" $OPENAIR_DIR/cmake_targets/autotests/log $OAI_USER@localhost:$NFS_TEST_RESULTS_DIR + - sshpass -p "$OAI_PASS" rsync -az -e "ssh -o StrictHostKeyChecking=no " --rsync-path="mkdir -p $EXTERNAL_SHARE_DIR && rsync" $OPENAIR_DIR/cmake_targets/autotests/log $OAI_USER@localhost:$EXTERNAL_SHARE_DIR From 62cf1be861122e11172f5e7fde8314f5b273c350 Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Wed, 30 Dec 2015 13:23:40 +0100 Subject: [PATCH 084/263] added option for OAI_EXTRA_ARGS from GiLab CI environment --- .gitlab-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 414a8a6356..f4b89d7be0 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -18,7 +18,7 @@ job1: - EXTERNAL_SHARE_RESULTS_DIR=$EXTERNAL_SHARE_DIR/$git_branch/$git_head - echo $NFS_TEST_RESULTS_DIR - echo $EXTERNAL_SHARE_RESULTS_DIR - - python $OPENAIR_DIR/cmake_targets/autotests/run_exec_lte-softmodem_tests.py -r -5GRepoHeadVersion $git_head -n $NFS_SHARE_DIR -u $OAI_USER -p $OAI_PASS >& $OPENAIR_DIR/cmake_targets/autotests/python_autotest.log + - python $OPENAIR_DIR/cmake_targets/autotests/run_exec_lte-softmodem_tests.py -r -5GRepoHeadVersion $git_head -n $NFS_SHARE_DIR -u $OAI_USER -p $OAI_PASS $OAI_EXTRA_ARGS >& $OPENAIR_DIR/cmake_targets/autotests/python_autotest.log - mv $OPENAIR_DIR/cmake_targets/autotests/python_autotest.log $OPENAIR_DIR/cmake_targets/autotests/log/python_autotest.log - sshpass -p "$OAI_PASS" rsync -az -e "ssh -o StrictHostKeyChecking=no " --rsync-path="mkdir -p $NFS_TEST_RESULTS_DIR && rsync" $OPENAIR_DIR/cmake_targets/autotests/log $OAI_USER@localhost:$NFS_TEST_RESULTS_DIR - sshpass -p "$OAI_PASS" rsync -az -e "ssh -o StrictHostKeyChecking=no " --rsync-path="mkdir -p $EXTERNAL_SHARE_DIR && rsync" $OPENAIR_DIR/cmake_targets/autotests/log $OAI_USER@localhost:$EXTERNAL_SHARE_DIR From 074eeda1f852c451c0d8f960733a33d214ac64b5 Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Wed, 30 Dec 2015 13:33:02 +0100 Subject: [PATCH 085/263] minor fix for init variable for machinelistGeneric --- cmake_targets/autotests/run_exec_lte-softmodem_tests.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake_targets/autotests/run_exec_lte-softmodem_tests.py b/cmake_targets/autotests/run_exec_lte-softmodem_tests.py index a41254d105..903c2686d1 100644 --- a/cmake_targets/autotests/run_exec_lte-softmodem_tests.py +++ b/cmake_targets/autotests/run_exec_lte-softmodem_tests.py @@ -938,7 +938,7 @@ if openairdir_local is None: sys.exit() locallogdir = openairdir_local + '/cmake_targets/autotests/log' MachineList = '' -MachinneListGeneric='' +MachineListGeneric='' #Remove the contents of local log directory #os.system(' rm -fr ' + locallogdir + '; mkdir -p ' + locallogdir ) flag_remove_logdir=False From 24d41580eeb342fa22d8f03cc79a5fe338c6fe0a Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Wed, 30 Dec 2015 13:39:02 +0100 Subject: [PATCH 086/263] printing of OAI_EXTRA_ARGS --- .gitlab-ci.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index f4b89d7be0..fae9633b74 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -3,6 +3,7 @@ job1: - echo $PWD - echo $USER - echo $OAI_USER + - echo $OAI_EXTRA_ARGS - echo $NFS_SHARE_DIR - echo $EXTERNAL_SHARE_DIR - git rev-parse --abbrev-ref HEAD From 201e033a1032865ee6e6a1cc298bad5d1dbde073 Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Wed, 30 Dec 2015 13:57:42 +0100 Subject: [PATCH 087/263] updates to display args in python autotest script --- .gitlab-ci.yml | 2 +- cmake_targets/autotests/run_exec_lte-softmodem_tests.py | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index fae9633b74..b3e9225e14 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -19,7 +19,7 @@ job1: - EXTERNAL_SHARE_RESULTS_DIR=$EXTERNAL_SHARE_DIR/$git_branch/$git_head - echo $NFS_TEST_RESULTS_DIR - echo $EXTERNAL_SHARE_RESULTS_DIR - - python $OPENAIR_DIR/cmake_targets/autotests/run_exec_lte-softmodem_tests.py -r -5GRepoHeadVersion $git_head -n $NFS_SHARE_DIR -u $OAI_USER -p $OAI_PASS $OAI_EXTRA_ARGS >& $OPENAIR_DIR/cmake_targets/autotests/python_autotest.log + - python $OPENAIR_DIR/cmake_targets/autotests/run_exec_lte-softmodem_tests.py -r -5GRepoHeadVersion $git_head -n $NFS_SHARE_DIR -u $OAI_USER -p $OAI_PASS `echo $OAI_EXTRA_ARGS` >& $OPENAIR_DIR/cmake_targets/autotests/python_autotest.log - mv $OPENAIR_DIR/cmake_targets/autotests/python_autotest.log $OPENAIR_DIR/cmake_targets/autotests/log/python_autotest.log - sshpass -p "$OAI_PASS" rsync -az -e "ssh -o StrictHostKeyChecking=no " --rsync-path="mkdir -p $NFS_TEST_RESULTS_DIR && rsync" $OPENAIR_DIR/cmake_targets/autotests/log $OAI_USER@localhost:$NFS_TEST_RESULTS_DIR - sshpass -p "$OAI_PASS" rsync -az -e "ssh -o StrictHostKeyChecking=no " --rsync-path="mkdir -p $EXTERNAL_SHARE_DIR && rsync" $OPENAIR_DIR/cmake_targets/autotests/log $OAI_USER@localhost:$EXTERNAL_SHARE_DIR diff --git a/cmake_targets/autotests/run_exec_lte-softmodem_tests.py b/cmake_targets/autotests/run_exec_lte-softmodem_tests.py index 903c2686d1..0bdd81d4f1 100644 --- a/cmake_targets/autotests/run_exec_lte-softmodem_tests.py +++ b/cmake_targets/autotests/run_exec_lte-softmodem_tests.py @@ -943,6 +943,10 @@ MachineListGeneric='' #os.system(' rm -fr ' + locallogdir + '; mkdir -p ' + locallogdir ) flag_remove_logdir=False i=1 + +print "Number of arguments argc = " + str(len(sys.argv)) +print "Argv = " + " ".join(sys.argv) + while i < len (sys.argv): arg=sys.argv[i] if arg == '-d': From 5ee5ed37ad9e67233573f005cb26716c4a15b237 Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Wed, 30 Dec 2015 14:05:53 +0100 Subject: [PATCH 088/263] temp removed amerique due to conn issues --- cmake_targets/autotests/test_case_list.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmake_targets/autotests/test_case_list.xml b/cmake_targets/autotests/test_case_list.xml index afbc1ede48..ffe5127a03 100644 --- a/cmake_targets/autotests/test_case_list.xml +++ b/cmake_targets/autotests/test_case_list.xml @@ -1,6 +1,6 @@ -mozart calisson stevens nano amerique +mozart calisson stevens nano /mnt/sradio/TEST_RESULTS/ https://gitlab.eurecom.fr/oai/openairinterface5g.git https://gitlab.eurecom.fr/oai/openair-cn.git @@ -11,7 +11,7 @@ $OPENAIR_DIR/cmake_targets/build_oai -w EXMIMO -c; sudo -S -E $OPENAIR_DIR/cmake_targets/tools/stop_exmimo2; dmesg|tail 36000 0104+ 015502 015505 015506 015507 015508 015508 015509 015510 015511 015600 015700 016102 016105 - mozart calisson stevens nano amerique + mozart calisson stevens nano compilation Build oaisim.Rel8 From ba40449aab0ac8f48fd2ce60d08a3b7dc7bd8248 Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Wed, 30 Dec 2015 15:13:16 +0100 Subject: [PATCH 089/263] update to make python script executable --- .gitlab-ci.yml | 1 + cmake_targets/autotests/run_exec_lte-softmodem_tests.py | 0 2 files changed, 1 insertion(+) mode change 100644 => 100755 cmake_targets/autotests/run_exec_lte-softmodem_tests.py diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index b3e9225e14..ecfba93e31 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -6,6 +6,7 @@ job1: - echo $OAI_EXTRA_ARGS - echo $NFS_SHARE_DIR - echo $EXTERNAL_SHARE_DIR + - echo $SHELL - git rev-parse --abbrev-ref HEAD - git_head=`git rev-parse HEAD` - echo $git_head diff --git a/cmake_targets/autotests/run_exec_lte-softmodem_tests.py b/cmake_targets/autotests/run_exec_lte-softmodem_tests.py old mode 100644 new mode 100755 From c02387180554e95c689bacf055f2f506b3147695 Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Wed, 30 Dec 2015 15:20:40 +0100 Subject: [PATCH 090/263] test for arguments passing in GitLab CI runner --- .gitlab-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index ecfba93e31..5ea7a0f5bc 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -20,7 +20,7 @@ job1: - EXTERNAL_SHARE_RESULTS_DIR=$EXTERNAL_SHARE_DIR/$git_branch/$git_head - echo $NFS_TEST_RESULTS_DIR - echo $EXTERNAL_SHARE_RESULTS_DIR - - python $OPENAIR_DIR/cmake_targets/autotests/run_exec_lte-softmodem_tests.py -r -5GRepoHeadVersion $git_head -n $NFS_SHARE_DIR -u $OAI_USER -p $OAI_PASS `echo $OAI_EXTRA_ARGS` >& $OPENAIR_DIR/cmake_targets/autotests/python_autotest.log + - python $OPENAIR_DIR/cmake_targets/autotests/run_exec_lte-softmodem_tests.py -r -5GRepoHeadVersion $git_head -n $NFS_SHARE_DIR -u $OAI_USER -p $OAI_PASS `echo $OAI_EXTRA_ARGS` -g $OAI_TEST_CASE_GROUP >& $OPENAIR_DIR/cmake_targets/autotests/python_autotest.log - mv $OPENAIR_DIR/cmake_targets/autotests/python_autotest.log $OPENAIR_DIR/cmake_targets/autotests/log/python_autotest.log - sshpass -p "$OAI_PASS" rsync -az -e "ssh -o StrictHostKeyChecking=no " --rsync-path="mkdir -p $NFS_TEST_RESULTS_DIR && rsync" $OPENAIR_DIR/cmake_targets/autotests/log $OAI_USER@localhost:$NFS_TEST_RESULTS_DIR - sshpass -p "$OAI_PASS" rsync -az -e "ssh -o StrictHostKeyChecking=no " --rsync-path="mkdir -p $EXTERNAL_SHARE_DIR && rsync" $OPENAIR_DIR/cmake_targets/autotests/log $OAI_USER@localhost:$EXTERNAL_SHARE_DIR From e639a5dafe4e77264a8a6cf389fe27cf3a5adcde Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Wed, 30 Dec 2015 15:24:23 +0100 Subject: [PATCH 091/263] run python script as an executable --- .gitlab-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 5ea7a0f5bc..e598e17011 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -20,7 +20,7 @@ job1: - EXTERNAL_SHARE_RESULTS_DIR=$EXTERNAL_SHARE_DIR/$git_branch/$git_head - echo $NFS_TEST_RESULTS_DIR - echo $EXTERNAL_SHARE_RESULTS_DIR - - python $OPENAIR_DIR/cmake_targets/autotests/run_exec_lte-softmodem_tests.py -r -5GRepoHeadVersion $git_head -n $NFS_SHARE_DIR -u $OAI_USER -p $OAI_PASS `echo $OAI_EXTRA_ARGS` -g $OAI_TEST_CASE_GROUP >& $OPENAIR_DIR/cmake_targets/autotests/python_autotest.log + - $OPENAIR_DIR/cmake_targets/autotests/run_exec_lte-softmodem_tests.py -r -5GRepoHeadVersion $git_head -n $NFS_SHARE_DIR -u $OAI_USER -p $OAI_PASS `echo $OAI_EXTRA_ARGS` -g $OAI_TEST_CASE_GROUP >& $OPENAIR_DIR/cmake_targets/autotests/python_autotest.log - mv $OPENAIR_DIR/cmake_targets/autotests/python_autotest.log $OPENAIR_DIR/cmake_targets/autotests/log/python_autotest.log - sshpass -p "$OAI_PASS" rsync -az -e "ssh -o StrictHostKeyChecking=no " --rsync-path="mkdir -p $NFS_TEST_RESULTS_DIR && rsync" $OPENAIR_DIR/cmake_targets/autotests/log $OAI_USER@localhost:$NFS_TEST_RESULTS_DIR - sshpass -p "$OAI_PASS" rsync -az -e "ssh -o StrictHostKeyChecking=no " --rsync-path="mkdir -p $EXTERNAL_SHARE_DIR && rsync" $OPENAIR_DIR/cmake_targets/autotests/log $OAI_USER@localhost:$EXTERNAL_SHARE_DIR From a1c76d163cfbb926fc73fe743df193fe0eefbb6d Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Wed, 30 Dec 2015 15:37:08 +0100 Subject: [PATCH 092/263] make log directory to store logs --- .gitlab-ci.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index e598e17011..0796c39a52 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -20,6 +20,7 @@ job1: - EXTERNAL_SHARE_RESULTS_DIR=$EXTERNAL_SHARE_DIR/$git_branch/$git_head - echo $NFS_TEST_RESULTS_DIR - echo $EXTERNAL_SHARE_RESULTS_DIR + - mkdir -p $OPENAIR_DIR/cmake_targets/autotests/log - $OPENAIR_DIR/cmake_targets/autotests/run_exec_lte-softmodem_tests.py -r -5GRepoHeadVersion $git_head -n $NFS_SHARE_DIR -u $OAI_USER -p $OAI_PASS `echo $OAI_EXTRA_ARGS` -g $OAI_TEST_CASE_GROUP >& $OPENAIR_DIR/cmake_targets/autotests/python_autotest.log - mv $OPENAIR_DIR/cmake_targets/autotests/python_autotest.log $OPENAIR_DIR/cmake_targets/autotests/log/python_autotest.log - sshpass -p "$OAI_PASS" rsync -az -e "ssh -o StrictHostKeyChecking=no " --rsync-path="mkdir -p $NFS_TEST_RESULTS_DIR && rsync" $OPENAIR_DIR/cmake_targets/autotests/log $OAI_USER@localhost:$NFS_TEST_RESULTS_DIR From 44e0e9194943eb1783530291f5e9b59279b7d15e Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Wed, 30 Dec 2015 15:44:51 +0100 Subject: [PATCH 093/263] run script with python interpreter --- .gitlab-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 0796c39a52..c8149d386a 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -21,7 +21,7 @@ job1: - echo $NFS_TEST_RESULTS_DIR - echo $EXTERNAL_SHARE_RESULTS_DIR - mkdir -p $OPENAIR_DIR/cmake_targets/autotests/log - - $OPENAIR_DIR/cmake_targets/autotests/run_exec_lte-softmodem_tests.py -r -5GRepoHeadVersion $git_head -n $NFS_SHARE_DIR -u $OAI_USER -p $OAI_PASS `echo $OAI_EXTRA_ARGS` -g $OAI_TEST_CASE_GROUP >& $OPENAIR_DIR/cmake_targets/autotests/python_autotest.log + - python $OPENAIR_DIR/cmake_targets/autotests/run_exec_lte-softmodem_tests.py -r -5GRepoHeadVersion $git_head -n $NFS_SHARE_DIR -u $OAI_USER -p $OAI_PASS `echo $OAI_EXTRA_ARGS` -g $OAI_TEST_CASE_GROUP >& $OPENAIR_DIR/cmake_targets/autotests/python_autotest.log - mv $OPENAIR_DIR/cmake_targets/autotests/python_autotest.log $OPENAIR_DIR/cmake_targets/autotests/log/python_autotest.log - sshpass -p "$OAI_PASS" rsync -az -e "ssh -o StrictHostKeyChecking=no " --rsync-path="mkdir -p $NFS_TEST_RESULTS_DIR && rsync" $OPENAIR_DIR/cmake_targets/autotests/log $OAI_USER@localhost:$NFS_TEST_RESULTS_DIR - sshpass -p "$OAI_PASS" rsync -az -e "ssh -o StrictHostKeyChecking=no " --rsync-path="mkdir -p $EXTERNAL_SHARE_DIR && rsync" $OPENAIR_DIR/cmake_targets/autotests/log $OAI_USER@localhost:$EXTERNAL_SHARE_DIR From 77be649fd3ffc4d55feb33a9a491bcd411a8784f Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Wed, 30 Dec 2015 20:27:49 +0100 Subject: [PATCH 094/263] enable deadline scheduler in build script --- cmake_targets/build_oai | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/cmake_targets/build_oai b/cmake_targets/build_oai index 3243e4b1a2..740a57f6cf 100755 --- a/cmake_targets/build_oai +++ b/cmake_targets/build_oai @@ -115,8 +115,9 @@ Options --cflags_processor Manually Add CFLAGS of processor if they are not detected correctly by script. Only add these flags if you know your processor supports them. Example flags: -msse3 -msse4.1 -msse4.2 -mavx2 --disable-deadline - Disables deadline scheduler of Linux kernel (>=3.14.x). The deadline scheduler is enabled by default - + Disables deadline scheduler of Linux kernel (>=3.14.x). +--enable-deadline + Disables deadline scheduler of Linux kernel (>=3.14.x). Usage (first build): oaisim (eNB + UE): ./build_oai -I -g --oaisim -x --install-system-files Eurecom EXMIMO + COTS UE : ./build_oai -I -g --eNB -x --install-system-files @@ -232,6 +233,11 @@ function main() { LOWLATENCY_FLAG_USER="False" echo_info "Disabling the usage of deadline scheduler" shift 1;; + --enable-deadline) + LOWLATENCY_FLAG_USER="True" + echo_info "Enabling the usage of deadline scheduler" + shift 1;; + -h | --help) print_help exit 1;; From 020f08b37db6616df9cbf06af82c497c59ce9b06 Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Wed, 30 Dec 2015 21:45:34 +0100 Subject: [PATCH 095/263] fixed to support doxygen --- targets/ARCH/COMMON/common_lib.h | 82 +++++++++++++++++++++++--------- 1 file changed, 60 insertions(+), 22 deletions(-) diff --git a/targets/ARCH/COMMON/common_lib.h b/targets/ARCH/COMMON/common_lib.h index 156da0c4ce..5526118828 100644 --- a/targets/ARCH/COMMON/common_lib.h +++ b/targets/ARCH/COMMON/common_lib.h @@ -46,7 +46,7 @@ typedef int64_t openair0_timestamp; typedef volatile int64_t openair0_vtimestamp; -/* structrue holds the parameters to configure USRP devices*/ +/*!\brief structrue holds the parameters to configure USRP devices*/ typedef struct openair0_device_t openair0_device; @@ -68,7 +68,8 @@ typedef enum { /** @addtogroup _PHY_RF_INTERFACE_ * @{ */ - + +/*! \brief RF Gain clibration */ typedef struct { //! Frequency for which RX chain was calibrated double freq; @@ -76,10 +77,11 @@ typedef struct { double offset; } rx_gain_calib_table_t; +/*! \brief RF frontend parameters set by application */ typedef struct { //! Module ID for this configuration int Mod_id; - // device log level + //! device log level int log_level; //! duplexing mode duplex_mode_t duplex_mode; @@ -136,10 +138,11 @@ typedef struct { } openair0_config_t; +/*! \brief RF mapping */ typedef struct { - /* card id */ + //! card id int card; - /* rf chain id */ + //! rf chain id int chain; } openair0_rf_map; @@ -182,20 +185,21 @@ typedef enum { }func_type_t; +/*!\brief structrue holds the parameters to configure USRP devices */ struct openair0_device_t { - /* Module ID of this device */ + //! Module ID of this device int Mod_id; - /* Type of this device */ + //! Type of this device dev_type_t type; - /* Type of the device's host (BBU/RRH) */ + //! Type of the device's host (BBU/RRH) func_type_t func_type; - /* RF frontend parameters set by application */ + //! RF frontend parameters set by application openair0_config_t openair0_cfg; - /* Can be used by driver to hold internal structure*/ + //! Can be used by driver to hold internal structure void *priv; /* Functions API, which are called by the application*/ @@ -217,7 +221,7 @@ struct openair0_device_t { @param msg pointer to the message structure passed between BBU-RRH @param msg_len length of the message */ - int (*trx_reply_func)(openair0_device *openair0, void *msg, ssize_t msg_len); + int (*trx_reply_func)(openair0_device *device, void *msg, ssize_t msg_len); /*! \brief Called to send samples to the RF target @param device pointer to the device structure specific to the RF hardware target @@ -235,9 +239,9 @@ struct openair0_device_t { * was received. * \param device the hardware to use * \param[out] ptimestamp the time at which the first sample was received. - * \param[out] An array of pointers to buffers for received samples. The buffers must be large enough to hold the number of samples \ref nsamps. + * \param[out] buff An array of pointers to buffers for received samples. The buffers must be large enough to hold the number of samples \ref nsamps. * \param nsamps Number of samples. One sample is 2 byte I + 2 byte Q => 4 byte. - * \param cc Number of channels. If cc == 1, only buff[0] is filled with samples. + * \param antenna_id Index of antenna for which to receive samples * \returns the number of sample read */ int (*trx_read_func)(openair0_device *device, openair0_timestamp *ptimestamp, void **buff, int nsamps,int antenna_id); @@ -254,22 +258,29 @@ struct openair0_device_t { */ int (*trx_reset_stats_func)(openair0_device *device); - /*! \brief Terminate operation of the transceiver -- free all associated resources */ + /*! \brief Terminate operation of the transceiver -- free all associated resources + * \param device the hardware to use + */ void (*trx_end_func)(openair0_device *device); - /* Terminate operation */ + /*! \brief Stop operation of the transceiver + * \param card RF Card to use + */ int (*trx_stop_func)(int card); /* Functions API related to UE*/ /*! \brief Set RX feaquencies - * \param + * \param device the hardware to use + * \param openair0_cfg RF frontend parameters set by application + * \param exmimo_dump_config dump EXMIMO configuration * \returns 0 in success */ int (*trx_set_freq_func)(openair0_device* device, openair0_config_t *openair0_cfg,int exmimo_dump_config); /*! \brief Set gains - * \param + * \param device the hardware to use + * \param openair0_cfg RF frontend parameters set by application * \returns 0 in success */ int (*trx_set_gains_func)(openair0_device* device, openair0_config_t *openair0_cfg); @@ -282,20 +293,47 @@ extern "C" { #endif -/*! \brief Initialize Openair RF target. It returns 0 if OK */ + /*! \brief Initialize Openair RF target. It returns 0 if OK + * \param device the hardware to use + * \param openair0_cfg RF frontend parameters set by application + */ int openair0_device_init(openair0_device* device, openair0_config_t *openair0_cfg); //USRP -/*! \brief Get the current timestamp of USRP */ + /*! \brief Get the current timestamp of USRP + * \param device the hardware to use + */ openair0_timestamp get_usrp_time(openair0_device *device); -/*! \brief Set the RX frequency of USRP RF TARGET */ + + /*! \brief Set the RX frequency of USRP RF TARGET + * \param device the hardware to use + * \param openair0_cfg RF frontend parameters set by application + */ int openair0_set_rx_frequencies(openair0_device* device, openair0_config_t *openair0_cfg); -//extern -/*! \brief Initialize Openair ETHERNET target. It returns 0 if OK */ + //extern functions + /*! \brief Initialize Openair ETHERNET target. It returns 0 if OK + * \param device the hardware to use + * \param openair0_cfg RF frontend parameters set by application + */ int openair0_dev_init_eth(openair0_device *device, openair0_config_t *openair0_cfg); + + /*! \brief Initialize Openair BLADERF target. It returns 0 if OK + * \param device the hardware to use + * \param openair0_cfg RF frontend parameters set by application + */ int openair0_dev_init_bladerf(openair0_device *device, openair0_config_t *openair0_cfg); + + /*! \brief Initialize Openair USRP target. It returns 0 if OK + * \param device the hardware to use + * \param openair0_cfg RF frontend parameters set by application + */ int openair0_dev_init_usrp(openair0_device* device, openair0_config_t *openair0_cfg); + + /*! \brief Initialize Openair EXMIMO target. It returns 0 if OK + * \param device the hardware to use + * \param openair0_cfg RF frontend parameters set by application + */ int openair0_dev_init_exmimo(openair0_device *device, openair0_config_t *openair0_cfg); /*@}*/ From 0699cb07bedfa69a9c25a60c342b51f275459573 Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Thu, 31 Dec 2015 07:05:12 +0100 Subject: [PATCH 096/263] removed display of arguments --- cmake_targets/autotests/run_exec_lte-softmodem_tests.py | 1 - 1 file changed, 1 deletion(-) diff --git a/cmake_targets/autotests/run_exec_lte-softmodem_tests.py b/cmake_targets/autotests/run_exec_lte-softmodem_tests.py index 0bdd81d4f1..90cb57c514 100755 --- a/cmake_targets/autotests/run_exec_lte-softmodem_tests.py +++ b/cmake_targets/autotests/run_exec_lte-softmodem_tests.py @@ -945,7 +945,6 @@ flag_remove_logdir=False i=1 print "Number of arguments argc = " + str(len(sys.argv)) -print "Argv = " + " ".join(sys.argv) while i < len (sys.argv): arg=sys.argv[i] From 51942ab13c440dd5d458e9889f7b40784fc9a0a7 Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Thu, 31 Dec 2015 07:25:45 +0100 Subject: [PATCH 097/263] added doxygen support to main script --- cmake_targets/build_oai | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/cmake_targets/build_oai b/cmake_targets/build_oai index 25bec96b98..fb3bd7823b 100755 --- a/cmake_targets/build_oai +++ b/cmake_targets/build_oai @@ -53,7 +53,7 @@ VERBOSE_COMPILE=0 CFLAGS_PROCESSOR_USER="" RUN_GROUP=0 TEST_CASE_GROUP="" - +BUILD_DOXYGEN=0 trap handle_ctrl_c INT function print_help() { @@ -113,6 +113,8 @@ Options Shows detailed compilation instructions in makefile --cflags_processor Manually Add CFLAGS of processor if they are not detected correctly by script. Only add these flags if you know your processor supports them. Example flags: -msse3 -msse4.1 -msse4.2 -mavx2 +--build-doxygen + Builds doxygen based documentation. Usage (first build): oaisim (eNB + UE): ./build_oai -I -g --oaisim -x --install-system-files @@ -225,6 +227,10 @@ function main() { CFLAGS_PROCESSOR_USER=$2 echo_info "setting CPU FLAGS from USER to: $CFLAGS_PROCESSOR_USER" shift 2;; + --build-doxygen) + BUILD_DOXYGEN=1 + echo_info "Will build doxygen support" + shift;; -h | --help) print_help exit 1;; @@ -550,7 +556,22 @@ function main() { rrh_gw $dbin/rrh_gw fi - + # Doxygen Support + ##################### + if [ "$BUILD_DOXYGEN" = "1" ] ;then + doxygen_log=$OPENAIR_DIR/cmake_targets/log/doxygen.log + echo_info "Building doxygen based documentation. The documentation file is located here: $OPENAIR_DIR/targets/DOCS/html/index.html" + echo_info "Doxygen Generation log is located here: $doxygen_log" + echo_info "Generating doxygen files....please wait" + ( + [ "$CLEAN" = "1" ] && rm -rf $OPENAIR_DIR/cmake_targets/doxygen/build + mkdir -p $OPENAIR_DIR/cmake_targets/doxygen/build + cd $OPENAIR_DIR/cmake_targets/doxygen/build + cmake .. + make doc + ) >& $doxygen_log + fi + # Auto-tests ##################### if [ "$OAI_TEST" = "1" ]; then From 8e1b5d26d466918be68053134175c94bf2e6c3c5 Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Thu, 31 Dec 2015 09:06:10 +0100 Subject: [PATCH 098/263] doxygen support for USRP PHY Interface --- openair1/PHY/impl_defs_top.h | 9 +- targets/ARCH/COMMON/common_lib.h | 8 +- targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp | 107 +++++++++++++++++-- targets/DOCS/Doxyfile | 5 +- 4 files changed, 114 insertions(+), 15 deletions(-) diff --git a/openair1/PHY/impl_defs_top.h b/openair1/PHY/impl_defs_top.h index c84b7d3ece..5fe559b80d 100755 --- a/openair1/PHY/impl_defs_top.h +++ b/openair1/PHY/impl_defs_top.h @@ -44,7 +44,14 @@ /** @defgroup _ref_implementation_ OpenAirInterface LTE Implementation * @{ - * @defgroup _PHY_RF_INTERFACE_ Generic PHY - RF Interface + * @defgroup _PHY_RF_INTERFACE_ PHY - RF Interface + * @ingroup _PHY_RF_INTERFACE_ + * @{ + * @defgroup _GENERIC_PHY_RF_INTERFACE_ Generic PHY - RF Interface + * @defgroup _USRP_PHY_RF_INTERFACE_ PHY - USRP RF Interface + * @defgroup _BLADERF_PHY_RF_INTERFACE_ PHY - BLADERF RF Interface + * @} + * * @ingroup _ref_implementation_ * @{ * This module is responsible for defining the generic interface between PHY and RF Target diff --git a/targets/ARCH/COMMON/common_lib.h b/targets/ARCH/COMMON/common_lib.h index 5526118828..6f88641803 100644 --- a/targets/ARCH/COMMON/common_lib.h +++ b/targets/ARCH/COMMON/common_lib.h @@ -65,7 +65,7 @@ typedef enum { } duplex_mode_t; -/** @addtogroup _PHY_RF_INTERFACE_ +/** @addtogroup _GENERIC_PHY_RF_INTERFACE_ * @{ */ @@ -299,15 +299,15 @@ extern "C" */ int openair0_device_init(openair0_device* device, openair0_config_t *openair0_cfg); - //USRP - /*! \brief Get the current timestamp of USRP + /*! \brief Get current timestamp of USRP * \param device the hardware to use */ openair0_timestamp get_usrp_time(openair0_device *device); - /*! \brief Set the RX frequency of USRP RF TARGET + /*! \brief Set RX frequencies * \param device the hardware to use * \param openair0_cfg RF frontend parameters set by application + * \returns 0 in success */ int openair0_set_rx_frequencies(openair0_device* device, openair0_config_t *openair0_cfg); diff --git a/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp b/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp index b12f7397f0..e9671b0770 100644 --- a/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp +++ b/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp @@ -29,7 +29,7 @@ /** usrp_lib.cpp * - * Author: HongliangXU : hong-liang-xu@agilent.com + * \author: HongliangXU : hong-liang-xu@agilent.com */ #include @@ -54,47 +54,71 @@ # include #endif +/** @addtogroup _USRP_PHY_RF_INTERFACE_ + * @{ + */ + +/*! \brief USRP Configuration */ typedef struct { // -------------------------------- // variables for USRP configuration // -------------------------------- + //! USRP device pointer uhd::usrp::multi_usrp::sptr usrp; //uhd::usrp::multi_usrp::sptr rx_usrp; //create a send streamer and a receive streamer + //! USRP TX Stream uhd::tx_streamer::sptr tx_stream; + //! USRP RX Stream uhd::rx_streamer::sptr rx_stream; + //! USRP TX Metadata uhd::tx_metadata_t tx_md; + //! USRP RX Metadata uhd::rx_metadata_t rx_md; + //! USRP Timestamp Information uhd::time_spec_t tm_spec; + //setup variables and allocate buffer + //! USRP Metadata uhd::async_metadata_t async_md; + //! Sampling rate double sample_rate; - // time offset between transmiter timestamp and receiver timestamp; + + //! time offset between transmiter timestamp and receiver timestamp; double tdiff; - // use usrp_time_offset to get this value + + //! TX forward samples. We use usrp_time_offset to get this value int tx_forward_nsamps; //166 for 20Mhz // -------------------------------- // Debug and output control // -------------------------------- + //! Number of underflows int num_underflows; + //! Number of overflows int num_overflows; + + //! Number of sequential errors int num_seq_errors; - + //! tx count int64_t tx_count; + //! rx count int64_t rx_count; + //! timestamp of RX packet openair0_timestamp rx_timestamp; } usrp_state_t; - +/*! \brief Called to start the USRP transceiver. Return 0 if OK, < 0 if error + @param device pointer to the device structure specific to the RF hardware target +*/ static int trx_usrp_start(openair0_device *device) { usrp_state_t *s = (usrp_state_t*)device->priv; @@ -117,7 +141,9 @@ static int trx_usrp_start(openair0_device *device) return 0; } - +/*! \brief Terminate operation of the USRP transceiver -- free all associated resources + * \param device the hardware to use + */ static void trx_usrp_end(openair0_device *device) { usrp_state_t *s = (usrp_state_t*)device->priv; @@ -131,6 +157,14 @@ static void trx_usrp_end(openair0_device *device) } +/*! \brief Called to send samples to the USRP RF target + @param device pointer to the device structure specific to the RF hardware target + @param timestamp The timestamp at whicch the first sample MUST be sent + @param buff Buffer which holds the samples + @param nsamps number of samples to be sent + @param antenna_id index of the antenna if the device has multiple anteannas + @param flags flags must be set to TRUE if timestamp parameter needs to be applied +*/ static int trx_usrp_write(openair0_device *device, openair0_timestamp timestamp, void **buff, int nsamps, int cc, int flags) { usrp_state_t *s = (usrp_state_t*)device->priv; @@ -152,6 +186,17 @@ static int trx_usrp_write(openair0_device *device, openair0_timestamp timestamp, return 0; } +/*! \brief Receive samples from hardware. + * Read \ref nsamps samples from each channel to buffers. buff[0] is the array for + * the first channel. *ptimestamp is the time at which the first sample + * was received. + * \param device the hardware to use + * \param[out] ptimestamp the time at which the first sample was received. + * \param[out] buff An array of pointers to buffers for received samples. The buffers must be large enough to hold the number of samples \ref nsamps. + * \param nsamps Number of samples. One sample is 2 byte I + 2 byte Q => 4 byte. + * \param antenna_id Index of antenna for which to receive samples + * \returns the number of sample read +*/ static int trx_usrp_read(openair0_device *device, openair0_timestamp *ptimestamp, void **buff, int nsamps, int cc) { usrp_state_t *s = (usrp_state_t*)device->priv; @@ -237,6 +282,9 @@ static int trx_usrp_read(openair0_device *device, openair0_timestamp *ptimestamp return samples_received; } +/*! \brief Get current timestamp of USRP + * \param device the hardware to use +*/ openair0_timestamp get_usrp_time(openair0_device *device) { @@ -245,11 +293,21 @@ openair0_timestamp get_usrp_time(openair0_device *device) return s->usrp->get_time_now().to_ticks(s->sample_rate); } +/*! \brief Compares two variables within precision + * \param a first variable + * \param b second variable +*/ static bool is_equal(double a, double b) { return std::fabs(a-b) < std::numeric_limits::epsilon(); } +/*! \brief Set frequencies (TX/RX) + * \param device the hardware to use + * \param openair0_cfg RF frontend parameters set by application + * \param dummy dummy variable not used + * \returns 0 in success + */ int trx_usrp_set_freq(openair0_device* device, openair0_config_t *openair0_cfg, int dummy) { usrp_state_t *s = (usrp_state_t*)device->priv; @@ -261,6 +319,11 @@ int trx_usrp_set_freq(openair0_device* device, openair0_config_t *openair0_cfg, } +/*! \brief Set RX frequencies + * \param device the hardware to use + * \param openair0_cfg RF frontend parameters set by application + * \returns 0 in success + */ int openair0_set_rx_frequencies(openair0_device* device, openair0_config_t *openair0_cfg) { usrp_state_t *s = (usrp_state_t*)device->priv; @@ -278,6 +341,11 @@ int openair0_set_rx_frequencies(openair0_device* device, openair0_config_t *open } +/*! \brief Set Gains (TX/RX) + * \param device the hardware to use + * \param openair0_cfg RF frontend parameters set by application + * \returns 0 in success + */ int trx_usrp_set_gains(openair0_device* device, openair0_config_t *openair0_cfg) { @@ -298,11 +366,14 @@ int trx_usrp_set_gains(openair0_device* device, return(0); } +/*! \brief Stop USRP + * \param card refers to the hardware index to use + */ int trx_usrp_stop(int card) { return(0); } - +/*! \brief USRPB210 RX calibration table */ rx_gain_calib_table_t calib_table_b210[] = { {3500000000.0,46.0}, {2660000000.0,53.0}, @@ -311,6 +382,7 @@ rx_gain_calib_table_t calib_table_b210[] = { {816000000.0,62.0}, {-1,0}}; +/*! \brief USRPx310 RX calibration table */ rx_gain_calib_table_t calib_table_x310[] = { {3500000000.0,77.0}, {2660000000.0,80.0}, @@ -319,6 +391,11 @@ rx_gain_calib_table_t calib_table_x310[] = { {816000000.0,85.0}, {-1,0}}; +/*! \brief Set RX gain offset + * \param openair0_cfg RF frontend parameters set by application + * \param chain_index RF chain to apply settings to + * \returns 0 in success + */ void set_rx_gain_offset(openair0_config_t *openair0_cfg, int chain_index) { int i=0; @@ -340,19 +417,30 @@ void set_rx_gain_offset(openair0_config_t *openair0_cfg, int chain_index) { } - +/*! \brief print the USRP statistics +* \param device the hardware to use +* \returns 0 on success +*/ int trx_usrp_get_stats(openair0_device* device) { return(0); } + +/*! \brief Reset the USRP statistics +* \param device the hardware to use +* \returns 0 on success +*/ int trx_usrp_reset_stats(openair0_device* device) { return(0); } - +/*! \brief Initialize Openair USRP target. It returns 0 if OK +* \param device the hardware to use +* \param openair0_cfg RF frontend parameters set by application +*/ int openair0_dev_init_usrp(openair0_device* device, openair0_config_t *openair0_cfg) { uhd::set_thread_priority_safe(1.0); @@ -584,3 +672,4 @@ int openair0_dev_init_usrp(openair0_device* device, openair0_config_t *openair0_ s->tx_forward_nsamps = 50; return 0; } +/*@}*/ diff --git a/targets/DOCS/Doxyfile b/targets/DOCS/Doxyfile index 0d32a3ffad..7ebc15f674 100644 --- a/targets/DOCS/Doxyfile +++ b/targets/DOCS/Doxyfile @@ -793,7 +793,10 @@ INPUT = $(OPENAIR1_DIR)/PHY/defs.h \ $(OPENAIR2_DIR)/LAYER2/RLC/UM_v9.3.0/rlc_um.h \ $(OPENAIR2_DIR)/LAYER2/RLC/UM_v9.3.0/rlc_um_entity.h \ $(OPENAIR2_DIR)/NETWORK_DRIVER/MESH/proto_extern.h \ - $(OPENAIR_TARGETS)/ARCH/COMMON/common_lib.h + $(OPENAIR_TARGETS)/ARCH/COMMON/common_lib.h \ + $(OPENAIR_TARGETS)/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp \ + $(OPENAIR_TARGETS)/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp \ + $(OPENAIR_TARGETS)/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses From b212daa4d3470c7c67d00c6219b0382b8bc13d13 Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Thu, 31 Dec 2015 09:48:26 +0100 Subject: [PATCH 099/263] doxygen support for BladeRF - PHY Interface --- .../ARCH/BLADERF/USERSPACE/LIB/bladerf_lib.c | 81 +++++++++++++++++-- .../ARCH/BLADERF/USERSPACE/LIB/bladerf_lib.h | 39 +++++++-- targets/DOCS/Doxyfile | 4 +- 3 files changed, 109 insertions(+), 15 deletions(-) diff --git a/targets/ARCH/BLADERF/USERSPACE/LIB/bladerf_lib.c b/targets/ARCH/BLADERF/USERSPACE/LIB/bladerf_lib.c index d515a206ae..b9bcf8ed2a 100644 --- a/targets/ARCH/BLADERF/USERSPACE/LIB/bladerf_lib.c +++ b/targets/ARCH/BLADERF/USERSPACE/LIB/bladerf_lib.c @@ -38,15 +38,26 @@ #include #include "bladerf_lib.h" +/** @addtogroup _BLADERF_PHY_RF_INTERFACE_ + * @{ + */ + +//! Number of BladeRF devices int num_devices=0; + /*These items configure the underlying asynch stream used by the the sync interface. */ -int trx_brf_init(openair0_device *openair0) { +/*! \brief BladeRF Init function (not used at the moment) + * \param device RF frontend parameters set by application + */ +int trx_brf_init(openair0_device *device) { } - +/*! \brief get current timestamp + *\param device the hardware to use + */ openair0_timestamp trx_get_timestamp(openair0_device *device) { int status; struct bladerf_metadata meta; @@ -60,17 +71,29 @@ openair0_timestamp trx_get_timestamp(openair0_device *device) { return meta.timestamp; } - -int trx_brf_start(openair0_device *openair0) { +/*! \brief Start BladeRF + *\param device the hardware to use + */ +int trx_brf_start(openair0_device *device) { return 0; } +/*! \brief Get BladeRF stats + *\param device the hardware to use + */ static void trx_brf_stats(openair0_device *device){ } +/*! \brief Called to send samples to the BladeRF RF target + @param device pointer to the device structure specific to the RF hardware target + @param timestamp The timestamp at whicch the first sample MUST be sent + @param buff Buffer which holds the samples + @param nsamps number of samples to be sent + @param cc index of the component carrier +*/ static int trx_brf_write(openair0_device *device,openair0_timestamp ptimestamp, void **buff, int nsamps, int cc) { int status, i; @@ -106,6 +129,16 @@ static int trx_brf_write(openair0_device *device,openair0_timestamp ptimestamp, return(0); } +/*! \brief Receive samples from hardware. + * Read \ref nsamps samples from each channel to buffers. buff[0] is the array for + * the first channel. *ptimestamp is the time at which the first sample + * was received. + * \param device the hardware to use + * \param[out] ptimestamp the time at which the first sample was received. + * \param[out] buff An array of pointers to buffers for received samples. The buffers must be large enough to hold the number of samples \ref nsamps. + * \param nsamps Number of samples. One sample is 2 byte I + 2 byte Q => 4 byte. + * \param cc Index of component carrier +*/ static int trx_brf_read(openair0_device *device, openair0_timestamp *ptimestamp, void **buff, int nsamps, int cc) { int status, ret; @@ -140,6 +173,9 @@ static int trx_brf_read(openair0_device *device, openair0_timestamp *ptimestamp, } +/*! \brief Terminate operation of the BladeRF transceiver -- free all associated resources + * \param device the hardware to use + */ int trx_brf_end(openair0_device *device) { int status; @@ -155,36 +191,59 @@ int trx_brf_end(openair0_device *device) { return 0; } - +/*! \brief print the BladeRF statistics +* \param device the hardware to use +* \returns 0 on success +*/ int trx_brf_get_stats(openair0_device* device) { return(0); } +/*! \brief Reset the BladeRF statistics +* \param device the hardware to use +* \returns 0 on success +*/ int trx_brf_reset_stats(openair0_device* device) { return(0); } +/*! \brief Stop USRP + * \param device the hardware to use + */ int trx_brf_stop(openair0_device* device) { return(0); } +/*! \brief Set frequencies (TX/RX) + * \param device the hardware to use + * \returns 0 in success + */ int trx_brf_set_freq(openair0_device* device) { return(0); } + +/*! \brief Set Gains (TX/RX) + * \param device the hardware to use + * \returns 0 in success + */ int trx_brf_set_gains(openair0_device* device) { return(0); } +/*! \brief Initialize Openair BLADERF target. It returns 0 if OK + * \param device the hardware to use + * \param openair0_cfg RF frontend parameters set by application + */ int openair0_dev_init_bladerf(openair0_device *device, openair0_config_t *openair0_cfg) { int status; @@ -322,6 +381,9 @@ int openair0_dev_init_bladerf(openair0_device *device, openair0_config_t *openai return 0; } +/*! \brief bladeRF error report + * \param status + */ int brf_error(int status) { //exit(-1); @@ -329,7 +391,9 @@ int brf_error(int status) { } - +/*! \brief Open BladeRF from serial port + * \param serial name of serial port on which to open BladeRF device + */ struct bladerf * open_bladerf_from_serial(const char *serial) { int status; @@ -356,6 +420,10 @@ struct bladerf * open_bladerf_from_serial(const char *serial) { return dev; } } + +/*! \brief Get BladeRF log level + * \param log_level log level + */ int get_brf_log_level(int log_level){ int level=BLADERF_LOG_LEVEL_INFO; @@ -384,3 +452,4 @@ int get_brf_log_level(int log_level){ } return level; } +/*@}*/ diff --git a/targets/ARCH/BLADERF/USERSPACE/LIB/bladerf_lib.h b/targets/ARCH/BLADERF/USERSPACE/LIB/bladerf_lib.h index 15e1d39da7..3a05c80e5c 100644 --- a/targets/ARCH/BLADERF/USERSPACE/LIB/bladerf_lib.h +++ b/targets/ARCH/BLADERF/USERSPACE/LIB/bladerf_lib.h @@ -37,45 +37,69 @@ #include "common_lib.h" #include "log.h" +/** @addtogroup _BLADERF_PHY_RF_INTERFACE_ + * @{ + */ + +/*! \brief BladeRF specific data structure */ typedef struct { - // opaque BRF data struct + //! opaque BladeRF device struct. An empty ("") or NULL device identifier will result in the first encountered device being opened (using the first discovered backend) struct bladerf *dev; - // An empty ("") or NULL device identifier will result in the first encountered device being opened (using the first discovered backend) - + + //! Number of buffers unsigned int num_buffers; + //! Buffer size unsigned int buffer_size; + //! Number of transfers unsigned int num_transfers; + //! RX timeout unsigned int rx_timeout_ms; + //! TX timeout unsigned int tx_timeout_ms; - + //! Metadata for RX struct bladerf_metadata meta_rx; + //!Metadata for TX struct bladerf_metadata meta_tx; - + //! Sample rate unsigned int sample_rate; - // time offset between transmiter timestamp and receiver timestamp; + //! time offset between transmiter timestamp and receiver timestamp; double tdiff; - // use brf_time_offset to get this value + //! TX number of forward samples use brf_time_offset to get this value int tx_forward_nsamps; //166 for 20Mhz // -------------------------------- // Debug and output control // -------------------------------- + //! Number of underflows int num_underflows; + //! Number of overflows int num_overflows; + //! number of sequential errors int num_seq_errors; + //! number of RX errors int num_rx_errors; + //! Number of TX errors int num_tx_errors; + //! timestamp of current TX uint64_t tx_current_ts; + //! timestamp of current RX uint64_t rx_current_ts; + //! number of actual samples transmitted uint64_t tx_actual_nsamps; + //! number of actual samples received uint64_t rx_actual_nsamps; + //! number of TX samples uint64_t tx_nsamps; + //! number of RX samples uint64_t rx_nsamps; + //! number of TX count uint64_t tx_count; + //! number of RX count uint64_t rx_count; + //! timestamp of RX packet openair0_timestamp rx_timestamp; } brf_state_t; @@ -84,3 +108,4 @@ typedef struct { */ int brf_error(int status); +/*@}*/ diff --git a/targets/DOCS/Doxyfile b/targets/DOCS/Doxyfile index 7ebc15f674..ac6ee99480 100644 --- a/targets/DOCS/Doxyfile +++ b/targets/DOCS/Doxyfile @@ -795,8 +795,8 @@ INPUT = $(OPENAIR1_DIR)/PHY/defs.h \ $(OPENAIR2_DIR)/NETWORK_DRIVER/MESH/proto_extern.h \ $(OPENAIR_TARGETS)/ARCH/COMMON/common_lib.h \ $(OPENAIR_TARGETS)/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp \ - $(OPENAIR_TARGETS)/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp \ - $(OPENAIR_TARGETS)/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp + $(OPENAIR_TARGETS)/ARCH/BLADERF/USERSPACE/LIB/bladerf_lib.c \ + $(OPENAIR_TARGETS)/ARCH/BLADERF/USERSPACE/LIB/bladerf_lib.h # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses From 92bafd28879b18ad6c8d61c74519090a7cfe5e01 Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Thu, 31 Dec 2015 15:13:33 +0100 Subject: [PATCH 100/263] cleanup + comments on code --- .../autotests/run_exec_lte-softmodem_tests.py | 311 +++++++----------- 1 file changed, 114 insertions(+), 197 deletions(-) diff --git a/cmake_targets/autotests/run_exec_lte-softmodem_tests.py b/cmake_targets/autotests/run_exec_lte-softmodem_tests.py index 90cb57c514..508dfe5ca3 100755 --- a/cmake_targets/autotests/run_exec_lte-softmodem_tests.py +++ b/cmake_targets/autotests/run_exec_lte-softmodem_tests.py @@ -64,17 +64,22 @@ sys.path.append('/opt/ssh') import ssh from ssh import SSHSession +# \brief write a string to a file +# \param filename name of file +# \param string string to write +# \mode file opening mode (default=write) def write_file(filename, string, mode="w"): text_file = open(filename, mode) text_file.write(string) text_file.close() - -#$1 name of file (assuming created with iperf -s -u .... -#$2 minimum throughput -#$3 maximum throughput -#$4 average throughput -#$5 minimum duration of throughput -#The throughput values found in file must be higher than values from from 2,3,4,5 + +# \brief function to check if test case passed throughput test +# \param filename name of file which has throughput results (usually from iperf -s ... +# \param min_tput minimum throughput +# \param max_tuput maximum throughput +# \param average average throughput +# \param min_duration minimum duration of throughput +#The throughput values found in file must be higher than values from from arguments 2,3,4,5 #The function returns True if throughput conditions are saisfied else it returns fails def tput_test(filename, min_tput, max_tput, average, min_duration): @@ -101,13 +106,16 @@ def tput_test(filename, min_tput, max_tput, average, min_duration): else: return False , tput_string - +# \brief Convert string to float or return None if there is exception def try_convert_to_float(string, fail=None): try: return float(string) except Exception: return fail; +# \brief get throughput statistics from log file +# \param search_expr search expression found in test_case_list.xml file +# \param logfile_traffic logfile which has traffic statistics def tput_test_search_expr (search_expr, logfile_traffic): result=0 tput_string='' @@ -153,7 +161,13 @@ def tput_test_search_expr (search_expr, logfile_traffic): return result, tput_string - +# \brief function to copy files to/from remote machine +# \param username user with which to make sftp connection +# \param password password of user +# \param hostname host to connect +# \ports port of remote machine on which server is listening +# \paramList This is list of operations as a set {operation: "get/put", localfile: "filename", remotefile: "filename" +# \param logfile Ignored currently and set once at the beginning of program def sftp_module (username, password, hostname, ports, paramList,logfile): #localD = localfile #remoteD = remotefile @@ -162,14 +176,9 @@ def sftp_module (username, password, hostname, ports, paramList,logfile): #paramiko logfile path should not be changed with multiple calls. The logs seem to in first file regardless error = "" #The lines below are outside exception loop to be sure to terminate the test case if the network connectivity goes down or there is authentication failure - - - transport = paramiko.Transport(hostname, ports) transport.connect(username = username, password = password) sftp = paramiko.SFTPClient.from_transport(transport) - - # index =0 for param in paramList: try: @@ -201,6 +210,9 @@ def sftp_module (username, password, hostname, ports, paramList,logfile): write_file(logfile, error, "a") res = os.system('\n echo \'SFTP Module Log for Machine: <' + hostname + '> ends...\' >> ' + logfile + ' 2>&1 \n') +# \brief bash script stub put at the end of scripts to terminate it +# \param timeout_cmd terminate script after timeout_cmd seconds +# \param terminate_missing_procs if True terminate all the processes launched by script if one of them terminates prematurely (due to error) def finalize_deploy_script (timeout_cmd, terminate_missing_procs='True'): cmd = 'declare -i timeout_cmd='+str(timeout_cmd) + '\n' if terminate_missing_procs == 'True': @@ -239,6 +251,11 @@ def finalize_deploy_script (timeout_cmd, terminate_missing_procs='True'): return cmd +# \brief run python script and update config file params of test case +# \param oai module with already open connection +# \param config_string config string taken from xml file +# \param logdirRepo directory of remote repository +# \param python_script python script location def update_config_file(oai, config_string, logdirRepo, python_script): if config_string : stringArray = config_string.splitlines() @@ -252,7 +269,15 @@ def update_config_file(oai, config_string, logdirRepo, python_script): return cmd #result = oai.send_recv(cmd) -def SSHSessionWrapper(machine, username, key_file, password, logdir_remote_testcase, logdir_local_base, operation): +# \brief thread safe sshsession wrapper due to occasional connection issues with ssh +# \param machine name of machine +# \param username user login for remote machine +# \param key_file file name which has keys to enable passwordless login +# \param password password for remote machine +# \param logdir_remote remote directory +# \param logdir_local_base local directory +# \param operation operation to perform (get_all, put_all) transfers recursively for directories +def SSHSessionWrapper(machine, username, key_file, password, logdir_remote, logdir_local_base, operation): max_tries = 100 i=0 while i <= max_tries: @@ -260,9 +285,9 @@ def SSHSessionWrapper(machine, username, key_file, password, logdir_remote_testc try: ssh = SSHSession(machine , username, key_file, password) if operation == "get_all": - ssh.get_all(logdir_remote_testcase , logdir_local_base) + ssh.get_all(logdir_remote , logdir_local_base) elif operation == "put_all": - ssh.put_all(logdir_local_base, logdir_remote_testcase ) + ssh.put_all(logdir_local_base, logdir_remote ) else: print "Error: Uknown operation in SSHSessionWrapper. Exiting now..." sys.exit(1) @@ -270,7 +295,7 @@ def SSHSessionWrapper(machine, username, key_file, password, logdir_remote_testc except Exception, e: error='' error = error + ' In Class = function: ' + sys._getframe().f_code.co_name + ': *** Caught exception: ' + str(e.__class__) + " : " + str( e) - error = error + '\n username = ' + username + '\n machine = ' + machine + '\n logdir_remote = ' + logdir_remote_testcase + '\n logdir_local_base = ' + logdir_local_base + error = error + '\n username = ' + username + '\n machine = ' + machine + '\n logdir_remote = ' + logdir_remote + '\n logdir_local_base = ' + logdir_local_base error = error + traceback.format_exc() print error print " Retrying again in 1 seconds" @@ -282,9 +307,11 @@ def SSHSessionWrapper(machine, username, key_file, password, logdir_remote_testc -#Function to clean old programs that might be running from earlier execution -#oai - parameter for making connection to machine -#programList - list of programs that must be terminated before execution of any test case +# \briefFunction to clean old programs that might be running from earlier execution +# \param oai - parameter for making connection to machine +# \parm programList list of programs that must be terminated before execution of any test case +# \param CleanUpAluLteBox program to terminate AlU Bell Labs LTE Box +# \param ExmimoRfStop String to stop EXMIMO card (specified in test_case_list.xml) def cleanOldPrograms(oai, programList, CleanUpAluLteBox, ExmimoRfStop): cmd = 'killall -q -r ' + programList result = oai.send(cmd, True) @@ -299,16 +326,15 @@ def cleanOldPrograms(oai, programList, CleanUpAluLteBox, ExmimoRfStop): res=oai.send_recv(CleanUpAluLteBox, True) res = oai.send_recv(ExmimoRfStop, False) -class myThread (threading.Thread): - def __init__(self, threadID, name, counter): - threading.Thread.__init__(self) - self.threadID = threadID - self.name = name - self.counter = counter - def run(self): - print "Starting " + self.name - - +# \brief Class thread to launch a generic command on remote machine +# \param threadID number of thread (for book keeping) +# \param threadname string of threadname (for book keeping) +# \param machine machine name on which to run the command +# \param username username with which to login +# \param password password with which to login +# \param cmd command as a string to run on remote machine +# \parma sudo if True sudo is set +# \param timeout timeout of command in seconds class oaiThread (threading.Thread): def __init__(self, threadID, threadname, machine, username, password, cmd, sudo, timeout): threading.Thread.__init__(self) @@ -337,7 +363,17 @@ class oaiThread (threading.Thread): print error -#This class runs test cases with class execution, compilatation +# \brief This class runs test cases with class {execution, compilatation} +# \param threadID number of thread (for book keeping) +# \param name string of threadname (for book keeping) +# \param machine machine name on which to run the command +# \param logdirOAI5GRepo directory on remote machine which as openairinterface5g repo installed +# \param testcasename name of test case to run on remote machine +# \param CleanupAluLteBox string that contains commands to stop ALU Bell Labs LTEBox (specified in test_case_list.xml) +# \param user username with which to login +# \param password password with which to login +# \param timeout timeout of command in seconds +# \param ExmimoRfStop command to stop EXMIMO Card class testCaseThread_generic (threading.Thread): def __init__(self, threadID, name, machine, logdirOAI5GRepo, testcasename,oldprogramList, CleanupAluLteBox, user, password, timeout, ExmimoRfStop): threading.Thread.__init__(self) @@ -409,11 +445,24 @@ class testCaseThread_generic (threading.Thread): - +# \bried function to run a command as a sudo +# \param cmd command as a string +# \param password password to be supplied def addsudo (cmd, password=""): cmd = 'echo \'' + password + '\' | sudo -S -E bash -c \' ' + cmd + '\' ' return cmd +# \brief handler for executing test cases (compilation, execution) +# \param name of testcase +# \param threadListGeneric list of threads which are already running on remote machines +# \param oldprogramList list of programs which must be terminated before running a test case +# \param logdirOAI5GRepo directory on remote machine which as openairinterface5g repo installed +# \param MachineList list of all machines on which generic test cases can be run +# \param user username with which to login +# \param password password with which to login +# \param CleanupAluLteBox string that contains commands to stop ALU Bell Labs LTEBox (specified in test_case_list.xml) +# \param timeout timeout of command in seconds +# \param ExmimoRfStop command to stop EXMIMO Card def handle_testcaseclass_generic (testcasename, threadListGeneric, oldprogramList, logdirOAI5GRepo, MachineList, user, password, CleanupAluLteBox,timeout, ExmimoRfStop): try: mypassword=password @@ -466,7 +515,9 @@ def handle_testcaseclass_generic (testcasename, threadListGeneric, oldprogramLis print "Continuing..." #sys.exit(1) -#Blocking wait for all threads related to generic testcase execution, class (compilation and execution) +# \brief Blocking wait for all threads related to generic testcase execution, class (compilation and execution) +# \param threadListGeneric list of threads which are running on remote machines +# \param timeout time to wait on threads in seconds def wait_testcaseclass_generic_threads(threadListGeneric, timeout = 1): threadListGenericNew=[] for param in threadListGeneric: @@ -484,7 +535,17 @@ def wait_testcaseclass_generic_threads(threadListGeneric, timeout = 1): #threadListGeneric.remove(param) return threadListGenericNew -#Function to handle test case class : lte-softmodem + +# \brief handler for executing test cases (lte-softmodem) +# \param testcase name of testcase +# \param oldprogramList list of programs which must be terminated before running a test case +# \param logdirOAI5GRepo directory on remote machine which has openairinterface5g repo installed +# \param logdirOpenaircnRepo directory on remote machine which has openair-cn repo installed +# \param MachineList list of all machines on which test cases can be run +# \param user username with which to login +# \param password password with which to login +# \param CleanupAluLteBox string that contains commands to stop ALU Bell Labs LTEBox (specified in test_case_list.xml) +# \param ExmimoRfStop command to stop EXMIMO Card def handle_testcaseclass_softmodem (testcase, oldprogramList, logdirOAI5GRepo , logdirOpenaircnRepo, MachineList, user, password, CleanUpAluLteBox, ExmimoRfStop): #We ignore the password sent to this function for secuirity reasons for password present in log files #It is recommended to add a line in /etc/sudoers that looks something like below. The line below will run sudo without password prompt @@ -853,7 +914,10 @@ def handle_testcaseclass_softmodem (testcase, oldprogramList, logdirOAI5GRepo , write_file(xmlFile, xml, mode="w") -#This function searches if test case is present in list of test cases that need to be executed by user +# \brief This function searches if test case is present in list of test cases that need to be executed by user +# \param testcasename the test case to search for +# \param testcasegroup list that is passed from the arguments +# \param test_case_exclude list of test cases excluded from execution (specified in test_case_list.xml) def search_test_case_group(testcasename, testcasegroup, test_case_exclude): if test_case_exclude != "": @@ -884,6 +948,13 @@ def search_test_case_group(testcasename, testcasegroup, test_case_exclude): return True return False +# \brief thread that cleans up remote machines from pre-existing test case executions +# \param threadID number of thread (for book keeping) +# \param threadname name of thread (for book keeping) +# \param oai handler that can be used to execute programs on remote machines +# \param CleanUpOldProgs list of programs which must be terminated before running a test case (specified in test_case_list.xml) +# \param CleanupAluLteBox string that contains commands to stop ALU Bell Labs LTEBox (specified in test_case_list.xml) +# \param ExmimoRfStop command to stop EXMIMO Card class oaiCleanOldProgramThread (threading.Thread): def __init__(self, threadID, threadname, oai, CleanUpOldProgs, CleanUpAluLteBox, ExmimoRfStop): threading.Thread.__init__(self) @@ -903,6 +974,11 @@ class oaiCleanOldProgramThread (threading.Thread): error = error + traceback.format_exc() print error +# \brief Run parallel threads in all machines for clean up old execution of test cases +# \param oai_list list of handlers that can be used to execute programs on remote machines +# \param CleanUpOldProgs list of programs which must be terminated before running a test case (specified in test_case_list.xml) +# \param CleanupAluLteBox string that contains commands to stop ALU Bell Labs LTEBox (specified in test_case_list.xml) +# \param ExmimoRfStop command to stop EXMIMO Card def cleanOldProgramsAllMachines(oai_list, CleanOldProgs, CleanUpAluLteBox, ExmimoRfStop): threadId=0 threadList=[] @@ -916,15 +992,11 @@ def cleanOldProgramsAllMachines(oai_list, CleanOldProgs, CleanUpAluLteBox, Exmim t.join() - - -#thread1 = myThread(1, "Thread-1", 1) debug = 0 pw ='' i = 0 dlsim=0 localshell=0 -timeout=2000 GitOAI5GRepoBranch='' GitOAI5GHeadVersion='' user='' @@ -939,8 +1011,6 @@ if openairdir_local is None: locallogdir = openairdir_local + '/cmake_targets/autotests/log' MachineList = '' MachineListGeneric='' -#Remove the contents of local log directory -#os.system(' rm -fr ' + locallogdir + '; mkdir -p ' + locallogdir ) flag_remove_logdir=False i=1 @@ -948,22 +1018,8 @@ print "Number of arguments argc = " + str(len(sys.argv)) while i < len (sys.argv): arg=sys.argv[i] - if arg == '-d': - debug = 1 - elif arg == '-dd': - debug = 2 - elif arg == '-r': + if arg == '-r': flag_remove_logdir=True - elif arg == '-w' : - pw = sys.argv[i+1] - i = i +1 - elif arg == '-P' : - dlsim = 1 - elif arg == '-l' : - localshell = 1 - elif arg == '-t' : - timeout = sys.argv[i+1] - i = i +1 elif arg == '-g' : testcasegroup = sys.argv[i+1].replace("\"","") i = i +1 @@ -1004,14 +1060,9 @@ while i < len (sys.argv): MachineListGeneric = MachineListGeneric.replace("\'","") i = i +1 elif arg == '-h' : - print "-d: low debug level" - print "-dd: high debug level" print "-r: Remove the log directory in autotests" print "-g: Run test cases in a group" - print "-c: Run cleanup scripts on remote machines" - print "-w: set the password for ssh to localhost" - print "-l: use local shell instead of ssh connection" - print "-t: set the time out in second for commands" + print "-c: Run cleanup scripts on remote machines and exit" print "-5GRepoBranch: Branch for OAI 5G Repository to run tests (overrides the branch in test_case_list.xml)" print "-5GRepoHeadVersion: Head commit on which to run tests (overrides the branch in test_case_list.xml)" print "-u: use the user name passed as argument" @@ -1131,20 +1182,6 @@ for machine in MachineList: #index = index + 1 -#myThread (1,"sddsf", 1) - - -#thread1 = oaiThread1(1, "Thread-1", 1) -#def __init__(self, threadID, name, counter, oai, cmd, sudo, timeout): - -#sys.exit() - - - - - - - print "\nTesting the sanity of machines used for testing..." if localshell == 0: try: @@ -1161,14 +1198,6 @@ if localshell == 0: #print "password: " + pw # issues in ubuntu 12.04 oai_list[index].connect(user,pw) - #print "result = " + result - - - #print '\nCleaning Older running programs : ' + CleanUpOldProgs - #cleanOldPrograms(oai_list[index], CleanUpOldProgs) - - - print '\nChecking for sudo permissions on machine <'+machine+'>...' result = oai_list[index].send_expect_false('sudo -S -v','may not run sudo',True) print "Sudo permissions..." + result @@ -1199,27 +1228,6 @@ else: pw = '' oai_list[0].connect_localshell() - - - - -cpu_freq = int(oai_list[0].cpu_freq()) -if timeout == 2000 : - if cpu_freq <= 2000 : - timeout = 3000 - elif cpu_freq < 2700 : - timeout = 2000 - elif cpu_freq < 3300 : - timeout = 1500 -print "cpu freq(MHz): " + str(cpu_freq) + "timeout(s): " + str(timeout) - -# The log files are stored in branch/version/ - - - -#result = oai_list[0].send('uname -a ' ) -#print result - #We now prepare the machines for testing index=0 threads_init_setup=[] @@ -1263,38 +1271,6 @@ for oai in oai_list: tempThread = oaiThread(index, 'thread_setup_'+str(index)+'_' + MachineList[index] , MachineList[index] , user, pw, cmd, False, 300) threads_init_setup.append(tempThread ) tempThread.start() - - #localfile = locallogdir + '/setup_log_' + MachineList[index] + '_.txt' - #remotefile = logdir + '/setup_log_' + MachineList[index] + '_.txt' - - #sftp_log = os.path.expandvars(locallogdir + '/sftp_module.log') - #sftp_module (user, pw, MachineList[index], 22, localfile, remotefile, sftp_log, "get") - - - #Now we copy test_case_list.xml on the remote machines - #localfile = os.path.expandvars('$OPENAIR_DIR/cmake_targets/autotests/test_case_list.xml') - #remotefile = logdirOAI5GRepo + '/cmake_targets/autotests/test_case_list.xml' - - #sftp_log = os.path.expandvars(locallogdir + '/sftp_module.log') - #sftp_module (user, pw, MachineList[index], 22, localfile, remotefile, sftp_log, "put") - - - #print oai_list[index].send('rm -fR ' + logdir) - #print oai_list[index].send('mkdir -p ' + logdir) - #print oai_list[index].send('cd '+ logdir) - #print oai_list[index].send('git clone '+ GitOAI5GRepo ) - #print oai_list[index].send('git clone '+ GitOpenaircnRepo) - #print oai_list[index].send('cd ' + logdirOAI5GRepo) - #print oai_list[index].send('git checkout ' + GitOAI5GHeadVersion) - #print oai_list[index].send('source oaienv') - #print oai_list[index].send('cd ' + logdirOpenaircnRepo) - #print oai_list[index].send('git checkout ' + GitOpenaircnRepoBranch) - #print oai_list[index].send_recv('cd ' + logdirOAI5GRepo) - #print oai_list[index].send_recv('source oaienv') - #print oai_list[index].send_recv('env |grep OPENAIR') - - #print '\nCleaning Older running programs : ' + CleanUpOldProgs - #cleanOldPrograms(oai_list[index], CleanUpOldProgs) index = index + 1 except Exception, e: print 'There is error in one of the commands to setup the machine '+ MachineList[index] @@ -1406,65 +1382,6 @@ res = oai_localhost.send_recv(cmd) print "Deleting NFSTestResults Dir..." + res print "Copying files from GilabCI Runner Machine : " + host + "locallogdir = " + locallogdir + ", NFSTestsResultsDir = " + NFSTestsResultsDir -#ssh = SSHSession(UEMachine , username=user, key_file=None, password=password) -#ssh.get_all(logdir_UE , logdir_local + '/cmake_targets/autotests/log/'+ testcasename) SSHSessionWrapper('localhost', user, None, pw , NFSTestsResultsDir , locallogdir, "put_all") sys.exit() - - #+ "class = "+ classx - - - - #index = index +1 - -test = 'test01' -ctime=datetime.datetime.utcnow().strftime("%Y-%m-%d.%Hh%M") -logfile = user+'.'+test+'.'+ctime+'.txt' -logdir = os.getcwd() + '/pre-ci-logs-'+host; -oai.create_dir(logdir,debug) -print 'log dir: ' + logdir -print 'log file: ' + logfile -pwd = oai.send_recv('pwd') -print "pwd = " + pwd -result = oai.send('echo linux | sudo -S ls -al;sleep 5') -print "result =" + result -sys.exit() - -#oai.send_nowait('mkdir -p -m 755' + logdir + ';') - -#print '=================start the ' + test + ' at ' + ctime + '=================\n' -#print 'Results will be reported in log file : ' + logfile -log.writefile(logfile,'====================start'+test+' at ' + ctime + '=======================\n') -log.set_debug_level(debug) - -oai.kill(user, pw) -oai.rm_driver(oai,user,pw) - -# start te test cases -if is_compiled == 0 : - is_compiled=case01.execute(oai, user, pw, host,logfile,logdir,debug,timeout) - -if is_compiled != 0 : - case02.execute(oai, user, pw, host, logfile,logdir,debug) - case03.execute(oai, user, pw, host, logfile,logdir,debug) - case04.execute(oai, user, pw, host, logfile,logdir,debug) - case05.execute(oai, user, pw, host, logfile,logdir,debug) -else : - print 'Compilation error: skip test case 02,03,04,05' - -oai.kill(user, pw) -oai.rm_driver(oai,user,pw) - -# perform the stats -log.statistics(logfile) - - -oai.disconnect() - -ctime=datetime.datetime.utcnow().strftime("%Y-%m-%d_%Hh%M") -log.writefile(logfile,'====================end the '+ test + ' at ' + ctime +'====================') -print 'Test results can be found in : ' + logfile -#print '\nThis test took %f minutes\n' % math.ceil((time.time() - start_time)/60) - -#print '\n=====================end the '+ test + ' at ' + ctime + '=====================' From d0859595b8643e1b4ed05decb23174cf3b2bc4f5 Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Thu, 31 Dec 2015 15:21:04 +0100 Subject: [PATCH 101/263] always do a cleanup before starting test case execution --- cmake_targets/autotests/run_exec_lte-softmodem_tests.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake_targets/autotests/run_exec_lte-softmodem_tests.py b/cmake_targets/autotests/run_exec_lte-softmodem_tests.py index 508dfe5ca3..00d6f01b2c 100755 --- a/cmake_targets/autotests/run_exec_lte-softmodem_tests.py +++ b/cmake_targets/autotests/run_exec_lte-softmodem_tests.py @@ -1318,8 +1318,8 @@ if (out != '') : print "status = " + str(status) + "\n Check files for error = " + out print sys.exit(1) +cleanOldProgramsAllMachines(oai_list, CleanUpOldProgs, CleanUpAluLteBox, ExmimoRfStop) if cleanUpRemoteMachines == True: - cleanOldProgramsAllMachines(oai_list, CleanUpOldProgs, CleanUpAluLteBox, ExmimoRfStop) sys.exit(0) threadListGlobal=[] From e44146b708ad5dd145aca749d4353033e258e1ca Mon Sep 17 00:00:00 2001 From: gauthier Date: Wed, 6 Jan 2016 11:37:26 +0100 Subject: [PATCH 102/263] handling of timing advance is improved. MAC retrieves timing advance from phy once prior to DL scheduling and clears the statistic in PHY. A timer for controlling the timing advance periodicity was introduced. --- .../PHY/LTE_ESTIMATION/lte_eNB_measurements.c | 2 +- openair1/PHY/LTE_TRANSPORT/print_stats.c | 6 ++- openair1/PHY/LTE_TRANSPORT/pucch.c | 4 +- openair1/PHY/impl_defs_top.h | 16 ++++---- openair2/LAYER2/MAC/defs.h | 3 +- openair2/LAYER2/MAC/eNB_scheduler_dlsch.c | 36 ++---------------- .../LAYER2/MAC/eNB_scheduler_primitives.c | 1 + openair2/LAYER2/MAC/eNB_scheduler_ulsch.c | 4 +- openair2/LAYER2/MAC/pre_processor.c | 37 +++++++++++++++++++ .../CONF/enb.band7.tm1.100PRB.usrpb210.conf | 10 ++--- .../CONF/enb.band7.tm1.50PRB.usrpb210.conf | 2 +- 11 files changed, 67 insertions(+), 54 deletions(-) diff --git a/openair1/PHY/LTE_ESTIMATION/lte_eNB_measurements.c b/openair1/PHY/LTE_ESTIMATION/lte_eNB_measurements.c index 7c0c45b05c..14e1c18571 100644 --- a/openair1/PHY/LTE_ESTIMATION/lte_eNB_measurements.c +++ b/openair1/PHY/LTE_ESTIMATION/lte_eNB_measurements.c @@ -107,7 +107,7 @@ void lte_eNB_I0_measurements(PHY_VARS_eNB *phy_vars_eNB, // + (k2*phy_measurements->n0_subband_power[aarx][rb])); phy_measurements->n0_subband_power_dB[aarx][rb] = dB_fixed(phy_measurements->n0_subband_power[aarx][rb]); - // printf("subframe %d (%d): eNb %d, aarx %d, rb %d len %d: energy %d (%d dB)\n",subframe,offset,eNB_id,aarx,rb,len,signal_energy_nodc(ul_ch,len), + // printf("subframe %d (%d): eNb %d, aarx %d, rb %d len %d: energy %d (%d dB)\n",subframe,offset,eNB_id,aarx,rb,len,signal_energy_nodc(ul_ch,len), // phy_measurements->n0_subband_power_dB[aarx][rb]); n0_power_tot += phy_measurements->n0_subband_power[aarx][rb]; } diff --git a/openair1/PHY/LTE_TRANSPORT/print_stats.c b/openair1/PHY/LTE_TRANSPORT/print_stats.c index ab946fc3da..650a2d81c1 100644 --- a/openair1/PHY/LTE_TRANSPORT/print_stats.c +++ b/openair1/PHY/LTE_TRANSPORT/print_stats.c @@ -577,10 +577,14 @@ int dump_eNB_stats(PHY_VARS_eNB *phy_vars_eNB, char* buffer, int length) phy_vars_eNB->rb_mask_ul[0], phy_vars_eNB->rb_mask_ul[1],phy_vars_eNB->rb_mask_ul[2],phy_vars_eNB->rb_mask_ul[3]); - for (i=0; ilte_frame_parms.N_RB_UL; i++) + for (i=0; ilte_frame_parms.N_RB_UL; i++) { len += sprintf(&buffer[len],"%4d ", phy_vars_eNB->PHY_measurements_eNB[eNB].n0_subband_power_tot_dBm[i]); + if ((i>0) && ((i%25) == 0)) + len += sprintf(&buffer[len],"\n ", + phy_vars_eNB->PHY_measurements_eNB[eNB].n0_subband_power_tot_dBm[i]); + } len += sprintf(&buffer[len],"\n"); len += sprintf(&buffer[len],"\n[eNB PROC] PERFORMANCE PARAMETERS\n"); /* diff --git a/openair1/PHY/LTE_TRANSPORT/pucch.c b/openair1/PHY/LTE_TRANSPORT/pucch.c index 7963423311..1c37c78721 100644 --- a/openair1/PHY/LTE_TRANSPORT/pucch.c +++ b/openair1/PHY/LTE_TRANSPORT/pucch.c @@ -786,7 +786,7 @@ uint32_t rx_pucch(PHY_VARS_eNB *phy_vars_eNB, #endif #ifdef DEBUG_PUCCH_RX - LOG_D(PHY,"[eNB] PUCCH fmt1: stat_max : %d, sigma2_dB %d (%d, %d), phase_max : %d\n",dB_fixed(stat_max),sigma2_dB,phy_vars_eNB->PHY_measurements_eNB[0].n0_subband_power_tot_dBm[6],pucch1_thres,phase_max); + LOG_I(PHY,"[eNB] PUCCH fmt1: stat_max : %d, sigma2_dB %d (%d, %d), phase_max : %d\n",dB_fixed(stat_max),sigma2_dB,phy_vars_eNB->PHY_measurements_eNB[0].n0_subband_power_tot_dBm[6],pucch1_thres,phase_max); #endif phy_vars_eNB->pucch1_stats[UE_id][(subframe<<10)+phy_vars_eNB->pucch1_stats_cnt[UE_id][subframe]] = stat_max; @@ -807,7 +807,7 @@ uint32_t rx_pucch(PHY_VARS_eNB *phy_vars_eNB, if (sigma2_dB<(dB_fixed(stat_max)-pucch1_thres)) { *payload = 1; *Po_PUCCH1_above = ((*Po_PUCCH1_above<<9) + (stat_max<<9)+1024)>>10; - // LOG_I(PHY,"[eNB] PUCCH fmt1: stat_max : %d, sigma2_dB %d (%d, %d), phase_max : %d\n",dB_fixed(stat_max),sigma2_dB,phy_vars_eNB->PHY_measurements_eNB[0].n0_power_tot_dBm,pucch1_thres,phase_max); + //LOG_I(PHY,"[eNB] PUCCH fmt1: stat_max : %d, sigma2_dB %d (%d, %d), phase_max : %d\n",dB_fixed(stat_max),sigma2_dB,phy_vars_eNB->PHY_measurements_eNB[0].n0_power_tot_dBm,pucch1_thres,phase_max); } else { *payload = 0; diff --git a/openair1/PHY/impl_defs_top.h b/openair1/PHY/impl_defs_top.h index a6298ae5a1..3ca0aedb5b 100755 --- a/openair1/PHY/impl_defs_top.h +++ b/openair1/PHY/impl_defs_top.h @@ -470,13 +470,13 @@ typedef struct { //! estimated avg noise power (dB) short n0_power_tot_dBm; //! estimated avg noise power per RB per RX ant (lin) - unsigned short n0_subband_power[NB_ANTENNAS_RX][25]; + unsigned short n0_subband_power[NB_ANTENNAS_RX][100]; //! estimated avg noise power per RB per RX ant (dB) - unsigned short n0_subband_power_dB[NB_ANTENNAS_RX][25]; + unsigned short n0_subband_power_dB[NB_ANTENNAS_RX][100]; //! estimated avg noise power per RB (dB) - short n0_subband_power_tot_dB[25]; + short n0_subband_power_tot_dB[100]; //! estimated avg noise power per RB (dBm) - short n0_subband_power_tot_dBm[25]; + short n0_subband_power_tot_dBm[100]; // eNB measurements (per user) //! estimated received spatial signal power (linear) unsigned int rx_spatial_power[NUMBER_OF_UE_MAX][2][2]; @@ -496,13 +496,13 @@ typedef struct { /// Wideband CQI (sum of all RX antennas, in dB) char wideband_cqi_tot[NUMBER_OF_UE_MAX]; /// Subband CQI per RX antenna and RB (= SINR) - int subband_cqi[NUMBER_OF_UE_MAX][NB_ANTENNAS_RX][25]; + int subband_cqi[NUMBER_OF_UE_MAX][NB_ANTENNAS_RX][100]; /// Total Subband CQI and RB (= SINR) - int subband_cqi_tot[NUMBER_OF_UE_MAX][25]; + int subband_cqi_tot[NUMBER_OF_UE_MAX][100]; /// Subband CQI in dB and RB (= SINR dB) - int subband_cqi_dB[NUMBER_OF_UE_MAX][NB_ANTENNAS_RX][25]; + int subband_cqi_dB[NUMBER_OF_UE_MAX][NB_ANTENNAS_RX][100]; /// Total Subband CQI and RB - int subband_cqi_tot_dB[NUMBER_OF_UE_MAX][25]; + int subband_cqi_tot_dB[NUMBER_OF_UE_MAX][100]; } PHY_MEASUREMENTS_eNB; diff --git a/openair2/LAYER2/MAC/defs.h b/openair2/LAYER2/MAC/defs.h index d92a143348..cd2d593726 100644 --- a/openair2/LAYER2/MAC/defs.h +++ b/openair2/LAYER2/MAC/defs.h @@ -736,7 +736,8 @@ typedef struct { uint8_t dl_pow_off[MAX_NUM_CCs]; uint16_t pre_nb_available_rbs[MAX_NUM_CCs]; unsigned char rballoc_sub_UE[MAX_NUM_CCs][N_RBG_MAX]; - + uint16_t ta_timer; + int16_t ta_update; } UE_sched_ctrl; /*! \brief eNB template for the Random access information */ typedef struct { diff --git a/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c b/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c index 332a0bd1de..2a52d8779a 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_dlsch.c @@ -447,7 +447,6 @@ schedule_ue_spec( // uint16_t pre_nb_available_rbs[MAX_NUM_CCs][NUMBER_OF_UE_MAX]; int mcs; uint16_t min_rb_unit[MAX_NUM_CCs]; - short ta_update = 0; eNB_MAC_INST *eNB = &eNB_mac_inst[module_idP]; UE_list_t *UE_list = &eNB->UE_list; LTE_DL_FRAME_PARMS *frame_parms[MAX_NUM_CCs]; @@ -804,29 +803,7 @@ schedule_ue_spec( // check first for RLC data on DCCH // add the length for all the control elements (timing adv, drx, etc) : header + payload - //#ifndef EXMIMO_IOT - // to be checked by RK, NN, FK - uint8_t update_TA=4; - - switch (frame_parms[CC_id]->N_RB_DL) { - case 6: - update_TA = 1; - break; - - case 25: - update_TA = 4; - break; - - case 50: - update_TA = 8; - break; - - case 100: - update_TA = 16; - break; - } - - ta_len = ((eNB_UE_stats->timing_advance_update/update_TA)!=0) ? 2 : 0; + ta_len = (ue_sched_ctl->ta_update!=0) ? 2 : 0; header_len_dcch = 2; // 2 bytes DCCH SDU subheader @@ -1074,11 +1051,6 @@ schedule_ue_spec( post_padding = TBS - sdu_length_total - header_len_dcch - header_len_dtch - ta_len ; // 1 is for the postpadding header } - //#ifndef EXMIMO_IOT - ta_update = eNB_UE_stats->timing_advance_update/update_TA; - /*#else - ta_update = 0; - #endif*/ offset = generate_dlsch_header((unsigned char*)UE_list->DLSCH_pdu[CC_id][0][UE_id].payload[0], // offset = generate_dlsch_header((unsigned char*)eNB_mac_inst[0].DLSCH_pdu[0][0].payload[0], @@ -1086,17 +1058,17 @@ schedule_ue_spec( sdu_lengths, // sdu_lcids, 255, // no drx - ta_update, // timing advance + ue_sched_ctl->ta_update, // timing advance NULL, // contention res id padding, post_padding); //#ifdef DEBUG_eNB_SCHEDULER - if (ta_update) { + if (ue_sched_ctl->ta_update) { LOG_I(MAC, "[eNB %d][DLSCH] Frame %d Generate header for UE_id %d on CC_id %d: sdu_length_total %d, num_sdus %d, sdu_lengths[0] %d, sdu_lcids[0] %d => payload offset %d,timing advance value : %d, padding %d,post_padding %d,(mcs %d, TBS %d, nb_rb %d),header_dcch %d, header_dtch %d\n", module_idP,frameP, UE_id, CC_id, sdu_length_total,num_sdus,sdu_lengths[0],sdu_lcids[0],offset, - ta_update,padding,post_padding,mcs,TBS,nb_rb,header_len_dcch,header_len_dtch); + ue_sched_ctl->ta_update,padding,post_padding,mcs,TBS,nb_rb,header_len_dcch,header_len_dtch); } //#endif diff --git a/openair2/LAYER2/MAC/eNB_scheduler_primitives.c b/openair2/LAYER2/MAC/eNB_scheduler_primitives.c index 3a5b1b5c61..829185d2a7 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_primitives.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_primitives.c @@ -267,6 +267,7 @@ int add_new_ue(module_id_t mod_idP, int cc_idP, rnti_t rntiP,int harq_pidP) UE_list->ordered_ULCCids[0][UE_id] = cc_idP; UE_list->num_UEs++; UE_list->active[UE_id] = TRUE; + memset((void*)&UE_list->UE_sched_ctrl[UE_id],0,sizeof(UE_sched_ctrl)); for (j=0; j<8; j++) { UE_list->UE_template[cc_idP][UE_id].oldNDI[j] = (j==0)?1:0; // 1 because first transmission is with format1A (Msg4) for harq_pid 0 diff --git a/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c b/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c index f924885f82..fdbdf03408 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c @@ -126,10 +126,8 @@ void rx_sdu( break; case CRNTI: - LOG_D(MAC, "[eNB %d] CC_id %d MAC CE_LCID %d (ce %d/%d): Received CRNTI %2.2x%2.2x\n", - enb_mod_idP, CC_idP, rx_ces[i], i,num_ce, payload_ptr[0], payload_ptr[1]); UE_id = find_UE_id(enb_mod_idP,(((uint16_t)payload_ptr[0])<<8) + payload_ptr[1]); - LOG_I(MAC, "[eNB %d] CC_id %d MAC CE_LCID %d : CRNTI %x (UE_id %d) in Msg3\n",enb_mod_idP, CC_idP, rx_ces[i], (((uint16_t)payload_ptr[0])<<8) + payload_ptr[1],UE_id); + LOG_I(MAC, "[eNB %d] CC_id %d MAC CE_LCID %d (ce %d/%d): CRNTI %x (UE_id %d) in Msg3\n",enb_mod_idP, CC_idP, rx_ces[i], i,num_ce,(((uint16_t)payload_ptr[0])<<8) + payload_ptr[1],UE_id); payload_ptr+=2; /* we don't process this CE yet */ diff --git a/openair2/LAYER2/MAC/pre_processor.c b/openair2/LAYER2/MAC/pre_processor.c index 86058fb7ce..410d454419 100644 --- a/openair2/LAYER2/MAC/pre_processor.c +++ b/openair2/LAYER2/MAC/pre_processor.c @@ -754,13 +754,50 @@ void dlsch_scheduler_pre_processor_reset (int module_idP, int subframe05_limit=0; int sf05_upper=-1,sf05_lower=-1; #endif + LTE_eNB_UE_stats *eNB_UE_stats = mac_xface->get_eNB_UE_stats(module_idP,CC_id,rnti); // initialize harq_pid and round mac_xface->get_ue_active_harq_pid(module_idP,CC_id,rnti, frameP,subframeP, &ue_sched_ctl->harq_pid[CC_id], &ue_sched_ctl->round[CC_id], 0); + if (ue_sched_ctl->ta_timer == 0) { + // WE SHOULD PROTECT the eNB_UE_stats with a mutex here ... + + ue_sched_ctl->ta_timer = 20; // wait 20 subframes before taking TA measurement from PHY + switch (PHY_vars_eNB_g[module_idP][CC_id]->lte_frame_parms.N_RB_DL) { + case 6: + ue_sched_ctl->ta_update = eNB_UE_stats->timing_advance_update; + break; + + case 15: + ue_sched_ctl->ta_update = eNB_UE_stats->timing_advance_update/2; + break; + + case 25: + ue_sched_ctl->ta_update = eNB_UE_stats->timing_advance_update/4; + break; + + case 50: + ue_sched_ctl->ta_update = eNB_UE_stats->timing_advance_update/8; + break; + + case 75: + ue_sched_ctl->ta_update = eNB_UE_stats->timing_advance_update/12; + break; + + case 100: + ue_sched_ctl->ta_update = eNB_UE_stats->timing_advance_update/16; + break; + } + // clear the update in case PHY does not have a new measurement after timer expiry + eNB_UE_stats->timing_advance_update = 0; + } + else { + ue_sched_ctl->ta_timer--; + ue_sched_ctl->ta_update =0; // don't trigger a timing advance command + } nb_rbs_required[CC_id][UE_id]=0; ue_sched_ctl->pre_nb_available_rbs[CC_id] = 0; ue_sched_ctl->dl_pow_off[CC_id] = 2; diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.100PRB.usrpb210.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.100PRB.usrpb210.conf index 1d47abdd60..7d73496dd7 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.100PRB.usrpb210.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.100PRB.usrpb210.conf @@ -17,7 +17,7 @@ eNBs = mobile_country_code = "208"; - mobile_network_code = "92"; + mobile_network_code = "93"; ////////// Physical parameters: @@ -36,7 +36,7 @@ eNBs = nb_antennas_tx = 1; nb_antennas_rx = 1; tx_gain = 90; - rx_gain = 120; + rx_gain = 125; prach_root = 0; prach_config_index = 0; prach_high_speed = "DISABLE"; @@ -130,7 +130,7 @@ eNBs = }; ////////// MME parameters: - mme_ip_address = ( { ipv4 = "192.168.13.11"; + mme_ip_address = ( { ipv4 = "192.168.12.11"; ipv6 = "192:168:30::17"; active = "yes"; preference = "ipv4"; @@ -140,10 +140,10 @@ eNBs = NETWORK_INTERFACES : { ENB_INTERFACE_NAME_FOR_S1_MME = "eth0"; - ENB_IPV4_ADDRESS_FOR_S1_MME = "192.168.13.10/24"; + ENB_IPV4_ADDRESS_FOR_S1_MME = "192.168.12.213/24"; ENB_INTERFACE_NAME_FOR_S1U = "eth0"; - ENB_IPV4_ADDRESS_FOR_S1U = "192.168.13.10/24"; + ENB_IPV4_ADDRESS_FOR_S1U = "192.168.12.213/24"; ENB_PORT_FOR_S1U = 2152; # Spec 2152 }; diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpb210.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpb210.conf index 1851317a26..cdd227c857 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpb210.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpb210.conf @@ -66,7 +66,7 @@ eNBs = pusch_p0_Nominal = -90; pusch_alpha = "AL1"; - pucch_p0_Nominal = -108; + pucch_p0_Nominal = -96; msg3_delta_Preamble = 6; pucch_deltaF_Format1 = "deltaF2"; pucch_deltaF_Format1b = "deltaF3"; From 574399fa436b42b2c0d0f78cadf1f0c48070f123 Mon Sep 17 00:00:00 2001 From: gauthier Date: Wed, 6 Jan 2016 16:33:04 +0100 Subject: [PATCH 103/263] some formatting changes in physcope for eNodeB. fixes for joint SR/ACK-NAK detection. --- openair1/PHY/TOOLS/lte_phy_scope.c | 11 ++-- openair1/SCHED/phy_procedures_lte_eNb.c | 77 ++++++++++++++--------- openair2/LAYER2/MAC/eNB_scheduler_ulsch.c | 17 ++++- 3 files changed, 68 insertions(+), 37 deletions(-) diff --git a/openair1/PHY/TOOLS/lte_phy_scope.c b/openair1/PHY/TOOLS/lte_phy_scope.c index e5d87223f0..e507024c86 100644 --- a/openair1/PHY/TOOLS/lte_phy_scope.c +++ b/openair1/PHY/TOOLS/lte_phy_scope.c @@ -160,7 +160,7 @@ void phy_scope_eNB(FD_lte_phy_scope_enb *form, int UE_id) { int eNB_id = 0; - int i,arx,atx,ind,k; + int i,i2,arx,atx,ind,k; LTE_DL_FRAME_PARMS *frame_parms = &phy_vars_enb->lte_frame_parms; int nsymb_ce = 12*frame_parms->N_RB_UL*frame_parms->symbols_per_tti; uint8_t nb_antennas_rx = frame_parms->nb_antennas_rx; @@ -181,6 +181,7 @@ void phy_scope_eNB(FD_lte_phy_scope_enb *form, float chest_t_abs[nb_antennas_rx][frame_parms->ofdm_symbol_size]; float *chest_f_abs; float time[FRAME_LENGTH_COMPLEX_SAMPLES]; + float time2[2048]; float freq[nsymb_ce*nb_antennas_rx*nb_antennas_tx]; int frame = phy_vars_enb->proc[0].frame_tx; uint32_t total_dlsch_bitrate = phy_vars_enb->total_dlsch_bitrate; @@ -238,19 +239,21 @@ void phy_scope_eNB(FD_lte_phy_scope_enb *form, if (chest_t[0] !=NULL) { for (i=0; i<(frame_parms->ofdm_symbol_size); i++) { - chest_t_abs[0][i] = 10*log10((float) (chest_t[0][2*i]*chest_t[0][2*i]+chest_t[0][2*i+1]*chest_t[0][2*i+1])); + i2 = (i+(frame_parms->ofdm_symbol_size>>1))%frame_parms->ofdm_symbol_size; + time2[i] = (float)(i-(frame_parms->ofdm_symbol_size>>1)); + chest_t_abs[0][i] = 10*log10((float) (1+chest_t[0][2*i2]*chest_t[0][2*i2]+chest_t[0][2*i2+1]*chest_t[0][2*i2+1])); if (chest_t_abs[0][i] > ymax) ymax = chest_t_abs[0][i]; } - fl_set_xyplot_data(form->chest_t,time,chest_t_abs[0],(frame_parms->ofdm_symbol_size),"","",""); + fl_set_xyplot_data(form->chest_t,time2,chest_t_abs[0],(frame_parms->ofdm_symbol_size),"","",""); } for (arx=1; arxofdm_symbol_size>>3); i++) { - chest_t_abs[arx][i] = 10*log10((float) (chest_t[arx][2*i]*chest_t[arx][2*i]+chest_t[arx][2*i+1]*chest_t[arx][2*i+1])); + chest_t_abs[arx][i] = 10*log10((float) (1+chest_t[arx][2*i]*chest_t[arx][2*i]+chest_t[arx][2*i+1]*chest_t[arx][2*i+1])); if (chest_t_abs[arx][i] > ymax) ymax = chest_t_abs[arx][i]; diff --git a/openair1/SCHED/phy_procedures_lte_eNb.c b/openair1/SCHED/phy_procedures_lte_eNb.c index b063fdc7a1..60cd0ec0f7 100755 --- a/openair1/SCHED/phy_procedures_lte_eNb.c +++ b/openair1/SCHED/phy_procedures_lte_eNb.c @@ -3122,7 +3122,7 @@ void phy_procedures_eNB_RX(const unsigned char sched_subframe,PHY_VARS_eNB *phy_ int16_t n1_pucch0,n1_pucch1,n1_pucch2,n1_pucch3; uint8_t do_SR = 0; uint8_t pucch_sel = 0; - int32_t metric0=0,metric1=0; + int32_t metric0=0,metric1=0,metric0_SR=0; ANFBmode_t bundling_flag; PUCCH_FMT_t format; uint8_t nPRS; @@ -3664,7 +3664,7 @@ void phy_procedures_eNB_RX(const unsigned char sched_subframe,PHY_VARS_eNB *phy_ harq_pid, &phy_vars_eNB->ulsch_eNB[i]->Msg3_flag); - // false msg3 detection by MAC: empty PDU + // one-shot msg3 detection by MAC: empty PDU (e.g. CRNTI) if (phy_vars_eNB->ulsch_eNB[i]->Msg3_flag == 0 ) { phy_vars_eNB->eNB_UE_stats[i].mode = PRACH; mac_xface->cancel_ra_proc(phy_vars_eNB->Mod_id, @@ -3868,24 +3868,24 @@ void phy_procedures_eNB_RX(const unsigned char sched_subframe,PHY_VARS_eNB *phy_ phy_vars_eNB->eNB_UE_stats[i].sr_total++; if (abstraction_flag == 0) - metric0 = rx_pucch(phy_vars_eNB, - pucch_format1, - i, - phy_vars_eNB->scheduling_request_config[i].sr_PUCCH_ResourceIndex, - 0, // n2_pucch - 0, // shortened format, should be use_srs flag, later - &SR_payload, - subframe, - PUCCH1_THRES); + metric0_SR = rx_pucch(phy_vars_eNB, + pucch_format1, + i, + phy_vars_eNB->scheduling_request_config[i].sr_PUCCH_ResourceIndex, + 0, // n2_pucch + 0, // shortened format, should be use_srs flag, later + &SR_payload, + subframe, + PUCCH1_THRES); #ifdef PHY_ABSTRACTION else { - metric0 = rx_pucch_emul(phy_vars_eNB, - i, - pucch_format1, - 0, - &SR_payload, - sched_subframe); + metric0_SR = rx_pucch_emul(phy_vars_eNB, + i, + pucch_format1, + 0, + &SR_payload, + sched_subframe); LOG_D(PHY,"[eNB %d][SR %x] Frame %d subframe %d Checking SR (UE SR %d/%d)\n",phy_vars_eNB->Mod_id, phy_vars_eNB->ulsch_eNB[i]->rnti,frame,subframe,SR_payload,phy_vars_eNB->scheduling_request_config[i].sr_PUCCH_ResourceIndex); } @@ -3921,20 +3921,35 @@ void phy_procedures_eNB_RX(const unsigned char sched_subframe,PHY_VARS_eNB *phy_ if ((n1_pucch0==-1) && (n1_pucch1==-1)) { // just check for SR } else if (phy_vars_eNB->lte_frame_parms.frame_type==FDD) { // FDD // if SR was detected, use the n1_pucch from SR, else use n1_pucch0 - n1_pucch0 = (SR_payload==1) ? phy_vars_eNB->scheduling_request_config[i].sr_PUCCH_ResourceIndex:n1_pucch0; + // n1_pucch0 = (SR_payload==1) ? phy_vars_eNB->scheduling_request_config[i].sr_PUCCH_ResourceIndex:n1_pucch0; LOG_D(PHY,"Demodulating PUCCH for ACK/NAK: n1_pucch0 %d (%d), SR_payload %d\n",n1_pucch0,phy_vars_eNB->scheduling_request_config[i].sr_PUCCH_ResourceIndex,SR_payload); - if (abstraction_flag == 0) + if (abstraction_flag == 0) { + + + metric0 = rx_pucch(phy_vars_eNB, pucch_format1a, i, (uint16_t)n1_pucch0, 0, //n2_pucch - 1, // shortened format + 0, // shortened format pucch_payload0, subframe, PUCCH1a_THRES); + + if (metric0 < metric0_SR) + metric0=rx_pucch(phy_vars_eNB, + pucch_format1a, + i, + phy_vars_eNB->scheduling_request_config[i].sr_PUCCH_ResourceIndex, + 0, //n2_pucch + 0, // shortened format + pucch_payload0, + subframe, + PUCCH1a_THRES); + } else { #ifdef PHY_ABSTRACTION metric0 = rx_pucch_emul(phy_vars_eNB,i, @@ -3986,15 +4001,15 @@ void phy_procedures_eNB_RX(const unsigned char sched_subframe,PHY_VARS_eNB *phy_ #endif if (abstraction_flag == 0) - metric0 = rx_pucch(phy_vars_eNB, - format, - i, - phy_vars_eNB->scheduling_request_config[i].sr_PUCCH_ResourceIndex, - 0, //n2_pucch - 1, // shortened format - pucch_payload0, - subframe, - PUCCH1a_THRES); + metric0_SR = rx_pucch(phy_vars_eNB, + format, + i, + phy_vars_eNB->scheduling_request_config[i].sr_PUCCH_ResourceIndex, + 0, //n2_pucch + 0, // shortened format + pucch_payload0, + subframe, + PUCCH1a_THRES); else { #ifdef PHY_ABSTRACTION metric0 = rx_pucch_emul(phy_vars_eNB,i, @@ -4022,7 +4037,7 @@ void phy_procedures_eNB_RX(const unsigned char sched_subframe,PHY_VARS_eNB *phy_ i, (uint16_t)n1_pucch0, 0, // n2_pucch - 1, // shortened format + 0, // shortened format pucch_payload0, subframe, PUCCH1a_THRES); @@ -4045,7 +4060,7 @@ void phy_procedures_eNB_RX(const unsigned char sched_subframe,PHY_VARS_eNB *phy_ i, (uint16_t)n1_pucch1, 0, //n2_pucch - 1, // shortened format + 0, // shortened format pucch_payload1, subframe, PUCCH1a_THRES); diff --git a/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c b/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c index fdbdf03408..b3a4319b6b 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c @@ -88,6 +88,7 @@ void rx_sdu( int ii,j; eNB_MAC_INST *eNB = &eNB_mac_inst[enb_mod_idP]; UE_list_t *UE_list= &eNB->UE_list; + int crnti_rx=0; start_meas(&eNB->rx_ulsch_sdu); @@ -128,9 +129,9 @@ void rx_sdu( case CRNTI: UE_id = find_UE_id(enb_mod_idP,(((uint16_t)payload_ptr[0])<<8) + payload_ptr[1]); LOG_I(MAC, "[eNB %d] CC_id %d MAC CE_LCID %d (ce %d/%d): CRNTI %x (UE_id %d) in Msg3\n",enb_mod_idP, CC_idP, rx_ces[i], i,num_ce,(((uint16_t)payload_ptr[0])<<8) + payload_ptr[1],UE_id); - + crnti_rx=1; payload_ptr+=2; - /* we don't process this CE yet */ + if (msg3_flagP != NULL) { *msg3_flagP = 0; } @@ -144,6 +145,9 @@ void rx_sdu( LOG_D(MAC, "[eNB %d] CC_id %d MAC CE_LCID %d : Received short BSR LCGID = %u bsr = %d\n", enb_mod_idP, CC_idP, rx_ces[i], lcgid, payload_ptr[0] & 0x3f); + if (crnti_rx==1) + LOG_I(MAC, "[eNB %d] CC_id %d MAC CE_LCID %d : Received short BSR LCGID = %u bsr = %d\n", + enb_mod_idP, CC_idP, rx_ces[i], lcgid, payload_ptr[0] & 0x3f); if (UE_id != -1) { UE_list->UE_template[CC_idP][UE_id].bsr_info[lcgid] = (payload_ptr[0] & 0x3f); @@ -175,6 +179,15 @@ void rx_sdu( UE_list->UE_template[CC_idP][UE_id].bsr_info[LCGID1], UE_list->UE_template[CC_idP][UE_id].bsr_info[LCGID2], UE_list->UE_template[CC_idP][UE_id].bsr_info[LCGID3]); + if (crnti_rx==1) + LOG_I(MAC, "[eNB %d] CC_id %d MAC CE_LCID %d: Received long BSR LCGID0 = %u LCGID1 = " + "%u LCGID2 = %u LCGID3 = %u\n", + enb_mod_idP, CC_idP, + rx_ces[i], + UE_list->UE_template[CC_idP][UE_id].bsr_info[LCGID0], + UE_list->UE_template[CC_idP][UE_id].bsr_info[LCGID1], + UE_list->UE_template[CC_idP][UE_id].bsr_info[LCGID2], + UE_list->UE_template[CC_idP][UE_id].bsr_info[LCGID3]); if (UE_list->UE_template[CC_idP][UE_id].bsr_info[LCGID0] == 0 ) { UE_list->UE_template[CC_idP][UE_id].ul_buffer_creation_time[LCGID0]=0; From 54a21b633d46e9824b043fa5c7e81cb5a06aa823 Mon Sep 17 00:00:00 2001 From: Raymond Knopp Date: Thu, 7 Jan 2016 10:57:10 +0100 Subject: [PATCH 104/263] forgot to add lte_param_init.c --- openair1/PHY/INIT/lte_param_init.c | 106 +++++++++++++++++++++++++++++ 1 file changed, 106 insertions(+) create mode 100644 openair1/PHY/INIT/lte_param_init.c diff --git a/openair1/PHY/INIT/lte_param_init.c b/openair1/PHY/INIT/lte_param_init.c new file mode 100644 index 0000000000..2b827dcb0e --- /dev/null +++ b/openair1/PHY/INIT/lte_param_init.c @@ -0,0 +1,106 @@ +#include +#include +#include +#include +#include + +#include "SIMULATION/TOOLS/defs.h" +#include "PHY/types.h" +#include "PHY/defs.h" +#include "PHY/extern.h" + +extern PHY_VARS_eNB *PHY_vars_eNB; +extern PHY_VARS_UE *PHY_vars_UE; + +void lte_param_init(unsigned char N_tx, + unsigned char N_rx, + unsigned char transmission_mode, + uint8_t extended_prefix_flag, + frame_t frame_type, + uint16_t Nid_cell, + uint8_t tdd_config, + uint8_t N_RB_DL, + uint8_t threequarter_fs, + uint8_t osf, + uint32_t perfect_ce) +{ + + LTE_DL_FRAME_PARMS *lte_frame_parms; + int i; + + + printf("Start lte_param_init\n"); + PHY_vars_eNB = malloc(sizeof(PHY_VARS_eNB)); + PHY_vars_UE = malloc(sizeof(PHY_VARS_UE)); + //PHY_config = malloc(sizeof(PHY_CONFIG)); + mac_xface = malloc(sizeof(MAC_xface)); + + srand(0); + randominit(0); + set_taus_seed(0); + + lte_frame_parms = &(PHY_vars_eNB->lte_frame_parms); + + lte_frame_parms->N_RB_DL = N_RB_DL; //50 for 10MHz and 25 for 5 MHz + lte_frame_parms->N_RB_UL = N_RB_DL; + lte_frame_parms->threequarter_fs = threequarter_fs; + lte_frame_parms->Ncp = extended_prefix_flag; + lte_frame_parms->Nid_cell = Nid_cell; + lte_frame_parms->nushift = Nid_cell%6; + lte_frame_parms->nb_antennas_tx = N_tx; + lte_frame_parms->nb_antennas_rx = N_rx; + lte_frame_parms->nb_antennas_tx_eNB = N_tx; + lte_frame_parms->phich_config_common.phich_resource = one; + lte_frame_parms->tdd_config = tdd_config; + lte_frame_parms->frame_type = frame_type; + // lte_frame_parms->Csrs = 2; + // lte_frame_parms->Bsrs = 0; + // lte_frame_parms->kTC = 0;44 + // lte_frame_parms->n_RRC = 0; + lte_frame_parms->mode1_flag = (transmission_mode == 1)? 1 : 0; + + init_frame_parms(lte_frame_parms,osf); + + //copy_lte_parms_to_phy_framing(lte_frame_parms, &(PHY_config->PHY_framing)); + + // phy_init_top(lte_frame_parms); //allocation + + PHY_vars_UE->is_secondary_ue = 0; + PHY_vars_UE->lte_frame_parms = *lte_frame_parms; + PHY_vars_eNB->lte_frame_parms = *lte_frame_parms; + + phy_init_lte_top(lte_frame_parms); + dump_frame_parms(lte_frame_parms); + + PHY_vars_UE->PHY_measurements.n_adj_cells=0; + PHY_vars_UE->PHY_measurements.adj_cell_id[0] = Nid_cell+1; + PHY_vars_UE->PHY_measurements.adj_cell_id[1] = Nid_cell+2; + + for (i=0; i<3; i++) + lte_gold(lte_frame_parms,PHY_vars_UE->lte_gold_table[i],Nid_cell+i); + + phy_init_lte_ue(PHY_vars_UE,1,0); + phy_init_lte_eNB(PHY_vars_eNB,0,0,0); + + generate_pcfich_reg_mapping(&PHY_vars_UE->lte_frame_parms); + generate_phich_reg_mapping(&PHY_vars_UE->lte_frame_parms); + + // DL power control init + if (transmission_mode == 1) { + PHY_vars_eNB->pdsch_config_dedicated->p_a = dB0; // 4 = 0dB + ((PHY_vars_eNB->lte_frame_parms).pdsch_config_common).p_b = 0; + PHY_vars_UE->pdsch_config_dedicated->p_a = dB0; // 4 = 0dB + ((PHY_vars_UE->lte_frame_parms).pdsch_config_common).p_b = 0; + } else { // rho_a = rhob + PHY_vars_eNB->pdsch_config_dedicated->p_a = dB0; // 4 = 0dB + ((PHY_vars_eNB->lte_frame_parms).pdsch_config_common).p_b = 1; + PHY_vars_UE->pdsch_config_dedicated->p_a = dB0; // 4 = 0dB + ((PHY_vars_UE->lte_frame_parms).pdsch_config_common).p_b = 1; + } + + PHY_vars_UE->perfect_ce = perfect_ce; + + printf("Done lte_param_init\n"); + + +} From 3007400bfa56e34aed43c41a600dad34a90b387d Mon Sep 17 00:00:00 2001 From: Raymond Knopp Date: Thu, 7 Jan 2016 17:24:25 +0100 Subject: [PATCH 105/263] autodetection of UHD version for gain/bw scaling prior to 3.9.2 --- targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp | 83 +++++++++++++++++--- targets/RT/USER/lte-softmodem.c | 5 +- targets/RT/USER/lte-ue.c | 17 ++-- 3 files changed, 85 insertions(+), 20 deletions(-) diff --git a/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp b/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp index 1cf3359e0e..3237d6ddac 100644 --- a/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp +++ b/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp @@ -38,6 +38,7 @@ #include #include #include +#include #include #include #include @@ -304,27 +305,59 @@ int trx_usrp_stop(int card) { rx_gain_calib_table_t calib_table_b210[] = { - {3500000000.0,46.0}, + {3500000000.0,47.0}, {2660000000.0,53.0}, {2300000000.0,54.0}, {1880000000.0,55.0}, {816000000.0,62.0}, {-1,0}}; +rx_gain_calib_table_t calib_table_b210_38[] = { + {3500000000.0,44.0}, + {2660000000.0,49.8}, + {2300000000.0,51.0}, + {1880000000.0,53.0}, + {816000000.0,57.0}, + {-1,0}}; + rx_gain_calib_table_t calib_table_x310[] = { {3500000000.0,77.0}, - {2660000000.0,80.0}, + {2660000000.0,81.0}, {2300000000.0,81.0}, {1880000000.0,82.0}, {816000000.0,85.0}, {-1,0}}; -void set_rx_gain_offset(openair0_config_t *openair0_cfg, int chain_index) { +void set_rx_gain_offset(openair0_config_t *openair0_cfg, int chain_index,int bw_gain_adjust) { int i=0; // loop through calibration table to find best adjustment factor for RX frequency - double min_diff = 6e9,diff; - + double min_diff = 6e9,diff,gain_adj=0.0; + if (bw_gain_adjust==1) { + switch ((int)openair0_cfg[0].sample_rate) { + case 30720000: + break; + case 23040000: + gain_adj=1.25; + break; + case 15360000: + gain_adj=3.0; + break; + case 7680000: + gain_adj=6.0; + break; + case 3840000: + gain_adj=9.0; + break; + case 1920000: + gain_adj=12.0; + break; + default: + printf("unknown sampling rate %d\n",(int)openair0_cfg[0].sample_rate); + exit(-1); + break; + } + } while (openair0_cfg->rx_gain_calib_table[i].freq>0) { diff = fabs(openair0_cfg->rx_freq[chain_index] - openair0_cfg->rx_gain_calib_table[i].freq); printf("cal %d: freq %f, offset %f, diff %f\n", @@ -333,7 +366,7 @@ void set_rx_gain_offset(openair0_config_t *openair0_cfg, int chain_index) { openair0_cfg->rx_gain_calib_table[i].offset,diff); if (min_diff > diff) { min_diff = diff; - openair0_cfg->rx_gain_offset[chain_index] = openair0_cfg->rx_gain_calib_table[i].offset; + openair0_cfg->rx_gain_offset[chain_index] = openair0_cfg->rx_gain_calib_table[i].offset+gain_adj; } i++; } @@ -366,8 +399,13 @@ int openair0_dev_init_usrp(openair0_device* device, openair0_config_t *openair0_ uhd::device_addrs_t device_adds = uhd::device::find(args); size_t i; + + int vers=0,subvers=0,subsubvers=0; + int bw_gain_adjust=0; - printf("Checking for USRPs\n"); + sscanf(uhd::get_version_string().c_str(),"%d.%d.%d",&vers,&subvers,&subsubvers); + + printf("Checking for USRPs : UHD %s (%d.%d.%d)\n",uhd::get_version_string().c_str(),vers,subvers,subsubvers); if(device_adds.size() == 0) { @@ -388,6 +426,7 @@ int openair0_dev_init_usrp(openair0_device* device, openair0_config_t *openair0_ } + printf("Found USRP X300\n"); s->usrp = uhd::usrp::multi_usrp::make(args); // s->usrp->set_rx_subdev_spec(rx_subdev); @@ -410,21 +449,29 @@ int openair0_dev_init_usrp(openair0_device* device, openair0_config_t *openair0_ // from usrp_time_offset openair0_cfg[0].samples_per_packet = 2048; openair0_cfg[0].tx_sample_advance = 15; + openair0_cfg[0].tx_bw = 20e6; + openair0_cfg[0].rx_bw = 20e6; openair0_cfg[0].tx_scheduling_advance = 8*openair0_cfg[0].samples_per_packet; break; case 15360000: openair0_cfg[0].samples_per_packet = 2048; openair0_cfg[0].tx_sample_advance = 45; + openair0_cfg[0].tx_bw = 10e6; + openair0_cfg[0].rx_bw = 10e6; openair0_cfg[0].tx_scheduling_advance = 5*openair0_cfg[0].samples_per_packet; break; case 7680000: openair0_cfg[0].samples_per_packet = 1024; openair0_cfg[0].tx_sample_advance = 50; + openair0_cfg[0].tx_bw = 5e6; + openair0_cfg[0].rx_bw = 5e6; openair0_cfg[0].tx_scheduling_advance = 5*openair0_cfg[0].samples_per_packet; break; case 1920000: openair0_cfg[0].samples_per_packet = 256; openair0_cfg[0].tx_sample_advance = 50; + openair0_cfg[0].tx_bw = 1.25e6; + openair0_cfg[0].rx_bw = 1.25e6; openair0_cfg[0].tx_scheduling_advance = 8*openair0_cfg[0].samples_per_packet; break; default: @@ -448,38 +495,54 @@ int openair0_dev_init_usrp(openair0_device* device, openair0_config_t *openair0_ device->type = USRP_B200_IF; - openair0_cfg[0].rx_gain_calib_table = calib_table_b210; - + if ((vers == 3) && (subvers == 9) && (subsubvers>=2)) { + openair0_cfg[0].rx_gain_calib_table = calib_table_b210; + bw_gain_adjust=0; + } + else { + openair0_cfg[0].rx_gain_calib_table = calib_table_b210_38; + bw_gain_adjust=1; + } switch ((int)openair0_cfg[0].sample_rate) { case 30720000: s->usrp->set_master_clock_rate(30.72e6); // from usrp_time_offset openair0_cfg[0].samples_per_packet = 2048; openair0_cfg[0].tx_sample_advance = 115; + openair0_cfg[0].tx_bw = 20e6; + openair0_cfg[0].rx_bw = 20e6; openair0_cfg[0].tx_scheduling_advance = 11*openair0_cfg[0].samples_per_packet; break; case 23040000: s->usrp->set_master_clock_rate(46.08e6); openair0_cfg[0].samples_per_packet = 2048; openair0_cfg[0].tx_sample_advance = 113; + openair0_cfg[0].tx_bw = 20e6; + openair0_cfg[0].rx_bw = 20e6; openair0_cfg[0].tx_scheduling_advance = 8*openair0_cfg[0].samples_per_packet; break; case 15360000: s->usrp->set_master_clock_rate(30.72e6); openair0_cfg[0].samples_per_packet = 2048; openair0_cfg[0].tx_sample_advance = 113; + openair0_cfg[0].tx_bw = 10e6; + openair0_cfg[0].rx_bw = 10e6; openair0_cfg[0].tx_scheduling_advance = 5*openair0_cfg[0].samples_per_packet; break; case 7680000: s->usrp->set_master_clock_rate(30.72e6); openair0_cfg[0].samples_per_packet = 1024; openair0_cfg[0].tx_sample_advance = 70;//103; + openair0_cfg[0].tx_bw = 5e6; + openair0_cfg[0].rx_bw = 5e6; openair0_cfg[0].tx_scheduling_advance = 5*openair0_cfg[0].samples_per_packet; break; case 1920000: s->usrp->set_master_clock_rate(30.72e6); openair0_cfg[0].samples_per_packet = 256; openair0_cfg[0].tx_sample_advance = 40; + openair0_cfg[0].tx_bw = 1.25e6; + openair0_cfg[0].rx_bw = 1.25e6; openair0_cfg[0].tx_scheduling_advance = 8*openair0_cfg[0].samples_per_packet; break; default: @@ -495,7 +558,7 @@ int openair0_dev_init_usrp(openair0_device* device, openair0_config_t *openair0_ s->usrp->set_rx_bandwidth(openair0_cfg[0].rx_bw,i); printf("Setting rx freq/gain on channel %lu/%lu : BW %f (readback %f)\n",i,s->usrp->get_rx_num_channels(),openair0_cfg[0].rx_bw/1e6,s->usrp->get_rx_bandwidth(i)/1e6); s->usrp->set_rx_freq(openair0_cfg[0].rx_freq[i],i); - set_rx_gain_offset(&openair0_cfg[0],i); + set_rx_gain_offset(&openair0_cfg[0],i,bw_gain_adjust); ::uhd::gain_range_t gain_range = s->usrp->get_rx_gain_range(i); // limit to maximum gain diff --git a/targets/RT/USER/lte-softmodem.c b/targets/RT/USER/lte-softmodem.c index ca07b15e90..3fde0de43c 100644 --- a/targets/RT/USER/lte-softmodem.c +++ b/targets/RT/USER/lte-softmodem.c @@ -2975,7 +2975,8 @@ int main( int argc, char **argv ) else { openair0_cfg[card].rx_gain[i] = PHY_vars_UE_g[0][0]->rx_total_gain_dB;// - USRP_GAIN_OFFSET; // calibrated for USRP B210 @ 2.6 GHz, 30.72 MS/s } - + +#if 0 // UHD 3.8 switch(frame_parms[0]->N_RB_DL) { case 6: openair0_cfg[card].rx_gain[i] -= 12; @@ -2996,7 +2997,7 @@ int main( int argc, char **argv ) default: break; } - +#endif } diff --git a/targets/RT/USER/lte-ue.c b/targets/RT/USER/lte-ue.c index 9930f677c1..4f722a54cf 100644 --- a/targets/RT/USER/lte-ue.c +++ b/targets/RT/USER/lte-ue.c @@ -279,7 +279,7 @@ static void *UE_thread_synch(void *arg) #ifdef OAI_USRP openair0_cfg[card].rx_gain[i] = UE->rx_total_gain_dB;//-USRP_GAIN_OFFSET; - +#if 0 // UHD 3.8 switch(UE->lte_frame_parms.N_RB_DL) { case 6: openair0_cfg[card].rx_gain[i] -= 12; @@ -301,7 +301,7 @@ static void *UE_thread_synch(void *arg) printf( "Unknown number of RBs %d\n", UE->lte_frame_parms.N_RB_DL ); break; } - +#endif printf( "UE synch: setting RX gain (%d,%d) to %f\n", card, i, openair0_cfg[card].rx_gain[i] ); #endif } @@ -357,7 +357,8 @@ static void *UE_thread_synch(void *arg) openair0_cfg[card].tx_freq[i] = downlink_frequency[card][i]+uplink_frequency_offset[card][i]; #ifdef OAI_USRP openair0_cfg[card].rx_gain[i] = UE->rx_total_gain_dB;//-USRP_GAIN_OFFSET; // 65 calibrated for USRP B210 @ 2.6 GHz - + +#if 0 // UHD 3.8 switch(UE->lte_frame_parms.N_RB_DL) { case 6: openair0_cfg[card].rx_gain[i] -= 12; @@ -379,7 +380,7 @@ static void *UE_thread_synch(void *arg) printf("Unknown number of RBs %d\n",UE->lte_frame_parms.N_RB_DL); break; } - +#endif printf("UE synch: setting RX gain (%d,%d) to %f\n",card,i,openair0_cfg[card].rx_gain[i]); #endif @@ -423,25 +424,25 @@ static void *UE_thread_synch(void *arg) openair0_cfg[0].sample_rate =1.92e6; openair0_cfg[0].rx_bw =.96e6; openair0_cfg[0].tx_bw =.96e6; - openair0_cfg[0].rx_gain[0] -= 12; + // openair0_cfg[0].rx_gain[0] -= 12; break; case 25: openair0_cfg[0].sample_rate =7.68e6; openair0_cfg[0].rx_bw =2.5e6; openair0_cfg[0].tx_bw =2.5e6; - openair0_cfg[0].rx_gain[0] -= 6; + // openair0_cfg[0].rx_gain[0] -= 6; break; case 50: openair0_cfg[0].sample_rate =15.36e6; openair0_cfg[0].rx_bw =5.0e6; openair0_cfg[0].tx_bw =5.0e6; - openair0_cfg[0].rx_gain[0] -= 3; + // openair0_cfg[0].rx_gain[0] -= 3; break; case 100: openair0_cfg[0].sample_rate=30.72e6; openair0_cfg[0].rx_bw=10.0e6; openair0_cfg[0].tx_bw=10.0e6; - openair0_cfg[0].rx_gain[0] -= 0; + // openair0_cfg[0].rx_gain[0] -= 0; break; } #ifndef EXMIMO From ee1d0d56ada69d8493abb9a9c04c9510333c183c Mon Sep 17 00:00:00 2001 From: Raymond Knopp Date: Thu, 7 Jan 2016 17:38:56 +0100 Subject: [PATCH 106/263] added noise-figure trace in stats. --- openair1/PHY/LTE_TRANSPORT/print_stats.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/openair1/PHY/LTE_TRANSPORT/print_stats.c b/openair1/PHY/LTE_TRANSPORT/print_stats.c index 53ca875953..68b18d35b4 100644 --- a/openair1/PHY/LTE_TRANSPORT/print_stats.c +++ b/openair1/PHY/LTE_TRANSPORT/print_stats.c @@ -67,11 +67,12 @@ int dump_ue_stats(PHY_VARS_UE *phy_vars_ue, char* buffer, int length, runmode_t if ((mode == normal_txrx) || (mode == no_L2_connect)) { len += sprintf(&buffer[len], "[UE_PROC] UE %d, RNTI %x\n",phy_vars_ue->Mod_id, phy_vars_ue->lte_ue_pdcch_vars[0]->crnti); - len += sprintf(&buffer[len],"[UE PROC] RSRP[0] %.2f dBm/RE, RSSI %.2f dBm, RSRQ[0] %.2f dB, N0 %d dBm/RE\n", + len += sprintf(&buffer[len],"[UE PROC] RSRP[0] %.2f dBm/RE, RSSI %.2f dBm, RSRQ[0] %.2f dB, N0 %d dBm/RE (NF %.1f dB)\n", 10*log10(phy_vars_ue->PHY_measurements.rsrp[0])-phy_vars_ue->rx_total_gain_dB, 10*log10(phy_vars_ue->PHY_measurements.rssi)-phy_vars_ue->rx_total_gain_dB, 10*log10(phy_vars_ue->PHY_measurements.rsrq[0]), - phy_vars_ue->PHY_measurements.n0_power_tot_dBm); + phy_vars_ue->PHY_measurements.n0_power_tot_dBm, + (double)phy_vars_ue->PHY_measurements.n0_power_tot_dBm+132.24); /* len += sprintf(&buffer[len], From f0982d31478f68cd90e512e36017d9b8f07b2ba6 Mon Sep 17 00:00:00 2001 From: Florian Kaltenberger Date: Fri, 18 Dec 2015 16:21:05 +0100 Subject: [PATCH 107/263] small performance improvements for perfect channel estimation in dlsim --- cmake_targets/lte-simulators/CMakeLists.txt | 2 +- openair1/SIMULATION/LTE_PHY/dlsim.c | 17 ++++++++++------- openair1/SIMULATION/TOOLS/abstraction.c | 4 ++-- 3 files changed, 13 insertions(+), 10 deletions(-) diff --git a/cmake_targets/lte-simulators/CMakeLists.txt b/cmake_targets/lte-simulators/CMakeLists.txt index 7a0e84b425..0b706c8748 100644 --- a/cmake_targets/lte-simulators/CMakeLists.txt +++ b/cmake_targets/lte-simulators/CMakeLists.txt @@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 2.8) set(PACKAGE_NAME "unitary_tests_simulators") set(PHYSIM True) set(RF_BOARD None) -set(XFORMS False) +set(XFORMS True) set(DEBUG_PHY False) set(MU_RECIEVER False) diff --git a/openair1/SIMULATION/LTE_PHY/dlsim.c b/openair1/SIMULATION/LTE_PHY/dlsim.c index 6474e83dd9..b74de2cb1a 100644 --- a/openair1/SIMULATION/LTE_PHY/dlsim.c +++ b/openair1/SIMULATION/LTE_PHY/dlsim.c @@ -2791,8 +2791,16 @@ PMI_FEEDBACK: random_channel(eNB2UE[2],0); random_channel(eNB2UE[3],0); } - } - + + if (PHY_vars_UE->perfect_ce==1) { + // fill in perfect channel estimates + freq_channel(eNB2UE[round],PHY_vars_UE->lte_frame_parms.N_RB_DL,12*PHY_vars_UE->lte_frame_parms.N_RB_DL + 1); + /* + write_output("channel.m","ch",eNB2UE[round]->ch[0],eNB2UE[round]->channel_length,1,8); + write_output("channelF.m","chF",eNB2UE[round]->chF[0],12*PHY_vars_UE->lte_frame_parms.N_RB_DL + 1,1,8); + */ + } + } if(abstx) { if (trials==0 && round==0) { @@ -2938,11 +2946,6 @@ PMI_FEEDBACK: if (PHY_vars_UE->perfect_ce==1) { if (awgn_flag==0) { - // fill in perfect channel estimates - freq_channel(eNB2UE[round],PHY_vars_UE->lte_frame_parms.N_RB_DL,12*PHY_vars_UE->lte_frame_parms.N_RB_DL + 1); - - //write_output("channel.m","ch",desc1->ch[0],desc1->channel_length,1,8); - //write_output("channelF.m","chF",desc1->chF[0],nb_samples,1,8); for(k=0; knb_antennas_tx; aa++) { for (aarx=0; aarxnb_antennas_rx; aarx++) { diff --git a/openair1/SIMULATION/TOOLS/abstraction.c b/openair1/SIMULATION/TOOLS/abstraction.c index fdaa73fa10..591b238acf 100644 --- a/openair1/SIMULATION/TOOLS/abstraction.c +++ b/openair1/SIMULATION/TOOLS/abstraction.c @@ -64,7 +64,7 @@ int init_freq_channel(channel_desc_t *desc,uint16_t nb_rb,int16_t n_samples) delta_f = nb_rb*180000/(n_samples-1); - for (f=-(n_samples>>1); f<(n_samples>>1); f++) { + for (f=-(n_samples>>1); f<=(n_samples>>1); f++) { freq=delta_f*(double)f*1e-6;// due to the fact that delays is in mus cos_lut[f+(n_samples>>1)] = (double *)malloc((int)desc->nb_taps*sizeof(double)); @@ -122,7 +122,7 @@ int freq_channel(channel_desc_t *desc,uint16_t nb_rb,int16_t n_samples) start_meas(&desc->interp_freq); - for (f=-n_samples_max/2,f2=-n_samples/2; f Date: Mon, 11 Jan 2016 16:17:08 +0100 Subject: [PATCH 108/263] changes from fourmi --- targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp | 12 ++++++------ .../CONF/enb.band7.tm1.50PRB.usrpb210.conf | 6 +++--- .../GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf | 6 +++--- 3 files changed, 12 insertions(+), 12 deletions(-) diff --git a/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp b/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp index 3237d6ddac..290f83ad5c 100644 --- a/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp +++ b/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp @@ -305,11 +305,11 @@ int trx_usrp_stop(int card) { rx_gain_calib_table_t calib_table_b210[] = { - {3500000000.0,47.0}, - {2660000000.0,53.0}, - {2300000000.0,54.0}, - {1880000000.0,55.0}, - {816000000.0,62.0}, + {3500000000.0,44.0}, + {2660000000.0,49.0}, + {2300000000.0,50.0}, + {1880000000.0,53.0}, + {816000000.0,58.0}, {-1,0}}; rx_gain_calib_table_t calib_table_b210_38[] = { @@ -507,7 +507,7 @@ int openair0_dev_init_usrp(openair0_device* device, openair0_config_t *openair0_ case 30720000: s->usrp->set_master_clock_rate(30.72e6); // from usrp_time_offset - openair0_cfg[0].samples_per_packet = 2048; + openair0_cfg[0].samples_per_packet = 4096; openair0_cfg[0].tx_sample_advance = 115; openair0_cfg[0].tx_bw = 20e6; openair0_cfg[0].rx_bw = 20e6; diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpb210.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpb210.conf index 6d4910c7c5..b19cca6e6d 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpb210.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpb210.conf @@ -36,7 +36,7 @@ eNBs = nb_antennas_tx = 1; nb_antennas_rx = 1; tx_gain = 90; - rx_gain = 130; + rx_gain = 125; prach_root = 0; prach_config_index = 0; prach_high_speed = "DISABLE"; @@ -140,10 +140,10 @@ eNBs = NETWORK_INTERFACES : { ENB_INTERFACE_NAME_FOR_S1_MME = "eth0"; - ENB_IPV4_ADDRESS_FOR_S1_MME = "192.168.12.213/24"; + ENB_IPV4_ADDRESS_FOR_S1_MME = "192.168.12.212/24"; ENB_INTERFACE_NAME_FOR_S1U = "eth0"; - ENB_IPV4_ADDRESS_FOR_S1U = "192.168.12.213/24"; + ENB_IPV4_ADDRESS_FOR_S1U = "192.168.12.212/24"; ENB_PORT_FOR_S1U = 2152; # Spec 2152 }; diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf index d8ea58910a..2883d8de0c 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf @@ -36,7 +36,7 @@ eNBs = nb_antennas_tx = 1; nb_antennas_rx = 1; tx_gain = 90; - rx_gain = 132; + rx_gain = 125; prach_root = 0; prach_config_index = 0; prach_high_speed = "DISABLE"; @@ -143,10 +143,10 @@ eNBs = NETWORK_INTERFACES : { ENB_INTERFACE_NAME_FOR_S1_MME = "eth0"; - ENB_IPV4_ADDRESS_FOR_S1_MME = "192.168.12.213/24"; + ENB_IPV4_ADDRESS_FOR_S1_MME = "192.168.12.212/24"; ENB_INTERFACE_NAME_FOR_S1U = "eth0"; - ENB_IPV4_ADDRESS_FOR_S1U = "192.168.12.213/24"; + ENB_IPV4_ADDRESS_FOR_S1U = "192.168.12.212/24"; ENB_PORT_FOR_S1U = 2152; # Spec 2152 }; From c2e58bcf68a68984f6633613d3269fdd4c7d5a53 Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Mon, 11 Jan 2016 16:25:31 +0100 Subject: [PATCH 109/263] enable printing of test results in Gitlab --- .gitlab-ci.yml | 1 + cmake_targets/autotests/test_case_list.xml | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index c8149d386a..ddbbcd54ab 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -25,3 +25,4 @@ job1: - mv $OPENAIR_DIR/cmake_targets/autotests/python_autotest.log $OPENAIR_DIR/cmake_targets/autotests/log/python_autotest.log - sshpass -p "$OAI_PASS" rsync -az -e "ssh -o StrictHostKeyChecking=no " --rsync-path="mkdir -p $NFS_TEST_RESULTS_DIR && rsync" $OPENAIR_DIR/cmake_targets/autotests/log $OAI_USER@localhost:$NFS_TEST_RESULTS_DIR - sshpass -p "$OAI_PASS" rsync -az -e "ssh -o StrictHostKeyChecking=no " --rsync-path="mkdir -p $EXTERNAL_SHARE_DIR && rsync" $OPENAIR_DIR/cmake_targets/autotests/log $OAI_USER@localhost:$EXTERNAL_SHARE_DIR + - cat $OPENAIR_DIR/cmake_targets/autotests/log/results_autotests.xml diff --git a/cmake_targets/autotests/test_case_list.xml b/cmake_targets/autotests/test_case_list.xml index ffe5127a03..0a494f4a03 100644 --- a/cmake_targets/autotests/test_case_list.xml +++ b/cmake_targets/autotests/test_case_list.xml @@ -1,6 +1,6 @@ -mozart calisson stevens nano +mozart calisson stevens nano amerique /mnt/sradio/TEST_RESULTS/ https://gitlab.eurecom.fr/oai/openairinterface5g.git https://gitlab.eurecom.fr/oai/openair-cn.git @@ -11,7 +11,7 @@ $OPENAIR_DIR/cmake_targets/build_oai -w EXMIMO -c; sudo -S -E $OPENAIR_DIR/cmake_targets/tools/stop_exmimo2; dmesg|tail 36000 0104+ 015502 015505 015506 015507 015508 015508 015509 015510 015511 015600 015700 016102 016105 - mozart calisson stevens nano + mozart calisson stevens nano amerique compilation Build oaisim.Rel8 From 765bd6df6ff6d67b8e4c4edc34c90a37fffe0615 Mon Sep 17 00:00:00 2001 From: Cedric Roux Date: Tue, 12 Jan 2016 09:44:01 +0100 Subject: [PATCH 110/263] Remove redirection to a log file of some functions in cmake_targets/tools/build_helper because 'apt-get' may trigger interactive sessions. --- cmake_targets/tools/build_helper | 21 --------------------- 1 file changed, 21 deletions(-) diff --git a/cmake_targets/tools/build_helper b/cmake_targets/tools/build_helper index a1fefec3ce..84c7d8ee21 100755 --- a/cmake_targets/tools/build_helper +++ b/cmake_targets/tools/build_helper @@ -163,33 +163,22 @@ install_gnutls_from_source(){ check_install_usrp_uhd_driver(){ - log_file=$OPENAIR_DIR/cmake_targets/log/check_install_usrp_uhd_driver_log.txt - echo_info "\nIn function: check_install_usrp_uhd_driver(). Installing USRP Drivers : The logfile for the installation is located here: $log_file " - ( v=$(lsb_release -cs) $SUDO apt-add-repository "deb http://files.ettus.com/binaries/uhd/repo/uhd/ubuntu/$v $v main" $SUDO apt-get update $SUDO apt-get -y install python python-tk libboost-all-dev libusb-1.0-0-dev $SUDO apt-get -y install -t `lsb_release -cs` uhd --force-yes - ) >& $log_file } check_install_bladerf_driver(){ - log_file=$OPENAIR_DIR/cmake_targets/log/check_install_bladerf_driver_log.txt - echo_info "\nIn function: check_install_bladerf_driver(). Install BLADERF drivers : The logfile for the installation is located here: $log_file " - ( $SUDO add-apt-repository -y ppa:bladerf/bladerf $SUDO apt-get update $SUDO apt-get install -y bladerf libbladerf-dev $SUDO apt-get install -y bladerf-firmware-fx3 $SUDO apt-get install -y bladerf-fpga-hostedx40 bladeRF-cli --flash-firmware /usr/share/Nuand/bladeRF/bladeRF_fw.img - ) >& $log_file } check_install_additional_tools (){ - log_file=$OPENAIR_DIR/cmake_targets/log/check_install_additional_tools_log.txt - echo_info "\nIn function: check_install_oai_software(). Installing optional OAI packages : The logfile for the installation is located here: $log_file " - ( $SUDO apt-get update $SUDO apt-get install -y \ check \ @@ -212,14 +201,9 @@ check_install_additional_tools (){ vlan \ ctags \ ntpdate - ) >& $log_file } check_install_oai_software() { - - log_file=$OPENAIR_DIR/cmake_targets/log/check_install_oai_software_log.txt - echo_info "\nIn function: check_install_oai_software(). Installing mandatory OAI packages : The logfile for the installation is located here: $log_file " - ( $SUDO apt-get update $SUDO apt-get install -y \ autoconf \ @@ -290,16 +274,12 @@ check_install_oai_software() { fi $SUDO pip install paramiko $SUDO pip install pyroute2 - ) > $log_file 2>&1 install_asn1c_from_source $SUDO rm -fr /opt/ssh $SUDO git clone https://gist.github.com/2190472.git /opt/ssh } install_asn1c_from_source(){ - asn1_install_dir=$OPENAIR_DIR/cmake_targets/log/asn1c_install_log.txt - echo_info "\nInstalling ASN1. The log file for ASN1 installation is here: $asn1_install_dir " - ( rm -rf /tmp/asn1c-r1516 mkdir -p /tmp/asn1c-r1516 cd /tmp/asn1c-r1516 @@ -310,7 +290,6 @@ install_asn1c_from_source(){ ./configure make -j`nproc` $SUDO make install - ) > $asn1_install_dir 2>&1 } ################################################# From 72ff627a12a324941a890777d8958f41526254a2 Mon Sep 17 00:00:00 2001 From: Navid Nikaein Date: Tue, 12 Jan 2016 10:32:48 +0100 Subject: [PATCH 111/263] add eNB configuration parameters for the fronthaul --- openair2/ENB_APP/enb_config.c | 73 +++++++++++ openair2/ENB_APP/enb_config.h | 18 +++ targets/RT/USER/lte-softmodem.c | 206 ++++++++++---------------------- 3 files changed, 156 insertions(+), 141 deletions(-) diff --git a/openair2/ENB_APP/enb_config.c b/openair2/ENB_APP/enb_config.c index 07e0ffa640..0fd5dbe0e8 100755 --- a/openair2/ENB_APP/enb_config.c +++ b/openair2/ENB_APP/enb_config.c @@ -170,6 +170,14 @@ #define ENB_CONFIG_STRING_ENB_IPV4_ADDR_FOR_S1U "ENB_IPV4_ADDRESS_FOR_S1U" #define ENB_CONFIG_STRING_ENB_PORT_FOR_S1U "ENB_PORT_FOR_S1U" +#define ENB_CONFIG_STRING_RRH_GW_CONFIG "rrh_gw_config" +#define ENB_CONFIG_STRING_RRH_GW_LOCAL_IF_NAME "local_if_name" +#define ENB_CONFIG_STRING_RRH_GW_LOCAL_ADDRESS "local_address" +#define ENB_CONFIG_STRING_RRH_GW_REMOTE_ADDRESS "remote_address" +#define ENB_CONFIG_STRING_RRH_GW_LOCAL_PORT "local_port" +#define ENB_CONFIG_STRING_RRH_GW_REMOTE_PORT "remote_port" +#define ENB_CONFIG_STRING_RRH_GW_ACTIVE "active" +#define ENB_CONFIG_STRING_RRH_GW_PREFERENCE "preference" #define ENB_CONFIG_STRING_ASN1_VERBOSITY "Asn1_verbosity" #define ENB_CONFIG_STRING_ASN1_VERBOSITY_NONE "none" @@ -274,6 +282,18 @@ static void enb_config_display(void) } else { printf( "\tMNC: \t%02"PRIu16":\n",enb_properties.properties[i]->mnc); } + + for (j=0; j< enb_properties.properties[i]->nb_rrh_gw; j++) { + if (enb_properties.properties[i]->rrh_gw_config[j].active == 1 ){ + printf( "\n\tRRH GW %d config for eNB %u:\n\n", j, i); + printf( "\tinterface name : \t%s:\n",enb_properties.properties[i]->rrh_gw_if_name); + printf( "\tlocal address : \t%s:\n",enb_properties.properties[i]->rrh_gw_config[j].local_address); + printf( "\tlocal port : \t%d:\n",enb_properties.properties[i]->rrh_gw_config[j].local_port); + printf( "\tremote address : \t%s:\n",enb_properties.properties[i]->rrh_gw_config[j].remote_address); + printf( "\tremote port : \t%d:\n",enb_properties.properties[i]->rrh_gw_config[j].remote_port); + printf( "\ttransport : \t%s Ethernet:\n\n",(enb_properties.properties[i]->rrh_gw_config[j].raw == 1)? "RAW" : "UDP"); + } + } for (j=0; j< enb_properties.properties[i]->nb_cc; j++) { printf( "\teutra band for CC %d: \t%"PRId16":\n",j,enb_properties.properties[i]->eutra_band[j]); @@ -455,6 +475,8 @@ const Enb_properties_array_t *enb_config_init(char* lib_config_file_name_pP) config_setting_t *setting_srb1 = NULL; config_setting_t *setting_mme_addresses = NULL; config_setting_t *setting_mme_address = NULL; + config_setting_t *setting_rrh_gws = NULL; + config_setting_t *setting_rrh_gw = NULL; config_setting_t *setting_enb = NULL; config_setting_t *setting_otg = NULL; config_setting_t *subsetting_otg = NULL; @@ -462,6 +484,7 @@ const Enb_properties_array_t *enb_config_init(char* lib_config_file_name_pP) int enb_properties_index = 0; int num_enbs = 0; int num_mme_address = 0; + int num_rrh_gw = 0; int num_otg_elements =0; int num_component_carriers =0; int i = 0; @@ -558,10 +581,15 @@ const Enb_properties_array_t *enb_config_init(char* lib_config_file_name_pP) libconfig_int my_int; + + char* if_name = NULL; char* ipv4 = NULL; + char* ipv4_remote = NULL; char* ipv6 = NULL; char* active = NULL; char* preference = NULL; + libconfig_int local_port = 0; + libconfig_int remote_port = 0; const char* active_enb[MAX_ENB]; char* enb_interface_name_for_S1U = NULL; char* enb_ipv4_address_for_S1U = NULL; @@ -2136,6 +2164,51 @@ const Enb_properties_array_t *enb_config_init(char* lib_config_file_name_pP) enb_properties.properties[enb_properties_index]->mme_ip_address[j].ipv6 = 1; } } + // RRH Config + setting_rrh_gws = config_setting_get_member (setting_enb, ENB_CONFIG_STRING_RRH_GW_CONFIG); + num_rrh_gw = config_setting_length(setting_rrh_gws); + enb_properties.properties[enb_properties_index]->nb_rrh_gw = 0; + + for (j = 0; j < num_rrh_gw; j++) { + setting_rrh_gw = config_setting_get_elem(setting_rrh_gws, j); + + if ( !( + config_setting_lookup_string(setting_rrh_gw, ENB_CONFIG_STRING_RRH_GW_LOCAL_IF_NAME, (const char **)&if_name) + && config_setting_lookup_string(setting_rrh_gw, ENB_CONFIG_STRING_RRH_GW_LOCAL_ADDRESS, (const char **)&ipv4) + && config_setting_lookup_string(setting_rrh_gw, ENB_CONFIG_STRING_RRH_GW_REMOTE_ADDRESS , (const char **)&ipv4_remote) + && config_setting_lookup_int(setting_rrh_gw, ENB_CONFIG_STRING_RRH_GW_LOCAL_PORT, &local_port) + && config_setting_lookup_int(setting_rrh_gw, ENB_CONFIG_STRING_RRH_GW_REMOTE_PORT, &remote_port) + && config_setting_lookup_string(setting_rrh_gw, ENB_CONFIG_STRING_RRH_GW_ACTIVE, (const char **)&active) + && config_setting_lookup_string(setting_rrh_gw, ENB_CONFIG_STRING_RRH_GW_PREFERENCE, (const char **)&preference) + ) + ) { + AssertError (0, parse_errors ++, + "Failed to parse eNB configuration file %s, %u th enb %u the RRH GW address !\n", + lib_config_file_name_pP, i, j); + continue; // FIXME will prevent segfaults below, not sure what happens at function exit... + } + + enb_properties.properties[enb_properties_index]->nb_rrh_gw += 1; + + enb_properties.properties[enb_properties_index]->rrh_gw_if_name = strdup(if_name); + enb_properties.properties[enb_properties_index]->rrh_gw_config[j].local_address = strdup(ipv4); + enb_properties.properties[enb_properties_index]->rrh_gw_config[j].remote_address = strdup(ipv4_remote); + enb_properties.properties[enb_properties_index]->rrh_gw_config[j].local_port= local_port; + enb_properties.properties[enb_properties_index]->rrh_gw_config[j].remote_port= remote_port; + + if (strcmp(active, "yes") == 0) { + enb_properties.properties[enb_properties_index]->rrh_gw_config[j].active = 1; + } + + if (strcmp(preference, "udp") == 0) { + enb_properties.properties[enb_properties_index]->rrh_gw_config[j].udp = 1; + } else if (strcmp(preference, "raw") == 0) { + enb_properties.properties[enb_properties_index]->rrh_gw_config[j].raw = 1; + } else {//if (strcmp(preference, "no") == 0) + enb_properties.properties[enb_properties_index]->rrh_gw_config[j].udp = 1; + enb_properties.properties[enb_properties_index]->rrh_gw_config[j].raw = 1; + } + } // SCTP SETTING enb_properties.properties[enb_properties_index]->sctp_out_streams = SCTP_OUT_STREAMS; diff --git a/openair2/ENB_APP/enb_config.h b/openair2/ENB_APP/enb_config.h index 113681dafe..9c271ca4f4 100755 --- a/openair2/ENB_APP/enb_config.h +++ b/openair2/ENB_APP/enb_config.h @@ -78,6 +78,17 @@ typedef struct mme_ip_address_s { char *ipv6_address; } mme_ip_address_t; +typedef struct rrh_gw_config_s { + unsigned udp:1; + unsigned raw:1; + unsigned active:1; + char *local_address; + char *remote_address; + uint16_t local_port; + uint16_t remote_port; + +} rrh_gw_config_t; + typedef struct Enb_properties_s { /* Unique eNB_id to identify the eNB within EPC. * For macro eNB ids this field should be 20 bits long. @@ -203,6 +214,13 @@ typedef struct Enb_properties_s { char *enb_interface_name_for_S1_MME; in_addr_t enb_ipv4_address_for_S1_MME; + + /* Nb of RRH to connect to */ + uint8_t nb_rrh_gw; + char *rrh_gw_if_name; + /* List of MME to connect to */ + rrh_gw_config_t rrh_gw_config[4]; + // otg config /* Nb of OTG elements */ uint8_t num_otg_elements; diff --git a/targets/RT/USER/lte-softmodem.c b/targets/RT/USER/lte-softmodem.c index c67de21f56..1f51b21cf9 100644 --- a/targets/RT/USER/lte-softmodem.c +++ b/targets/RT/USER/lte-softmodem.c @@ -329,15 +329,7 @@ time_stats_t softmodem_stats_rx_sf[10]; // total rx time void reset_opp_meas(void); void print_opp_meas(void); int transmission_mode=1; -/* - FT: not a very clean way of managing the rescale of iqs in rx path, but this is done in - openair1/PHY/MODULATION/ul_7_5_kHz.c which doesn't have access to config parameters - to re-worked later..... - RX_IQRESCALELEN is setup in device libraries for all non expressmimo targets and acessed as an - external variable in ul_7_5_kHz.c. For expressmimo it is a macro (openair1/PHY/defs.h) - Regarding the value of this variable or macro: 18 is for 15 bits iqs, 15 is used for USRP, EXMIMO -*/ -//int rxrescale; + int16_t glog_level = LOG_INFO; int16_t glog_verbosity = LOG_MED; @@ -369,57 +361,16 @@ int16_t osa_log_verbosity = LOG_MED; #ifdef ETHERNET +char rrh_eNB_ip[20] = "127.0.0.1"; +int rrh_eNB_port = 50000; char *rrh_UE_ip = "127.0.0.1"; int rrh_UE_port = 51000; #endif -/* flag given in runtime to specify if the RF head is local or remote (default option is local RF)*/ -uint8_t local_remote_RF = BBU_LOCAL_RF_ENABLED; - + char uecap_xer[1024],uecap_xer_in=0; extern void *UE_thread(void *arg); extern void init_UE_threads(void); -/*---------------------BMC: timespec helpers -----------------------------*/ - -struct timespec min_diff_time = { .tv_sec = 0, .tv_nsec = 0 }; -struct timespec max_diff_time = { .tv_sec = 0, .tv_nsec = 0 }; - -struct timespec clock_difftime(struct timespec start, struct timespec end) -{ - struct timespec temp; - if ((end.tv_nsec-start.tv_nsec)<0) { - temp.tv_sec = end.tv_sec-start.tv_sec-1; - temp.tv_nsec = 1000000000+end.tv_nsec-start.tv_nsec; - } else { - temp.tv_sec = end.tv_sec-start.tv_sec; - temp.tv_nsec = end.tv_nsec-start.tv_nsec; - } - return temp; -} - -void print_difftimes() -{ -#ifdef DEBUG - printf("difftimes min = %lu ns ; max = %lu ns\n", min_diff_time.tv_nsec, max_diff_time.tv_nsec); -#else - LOG_I(HW,"difftimes min = %lu ns ; max = %lu ns\n", min_diff_time.tv_nsec, max_diff_time.tv_nsec); -#endif -} - -void update_difftimes(struct timespec start, struct timespec end) -{ - struct timespec diff_time = { .tv_sec = 0, .tv_nsec = 0 }; - int changed = 0; - diff_time = clock_difftime(start, end); - if ((min_diff_time.tv_nsec == 0) || (diff_time.tv_nsec < min_diff_time.tv_nsec)) { min_diff_time.tv_nsec = diff_time.tv_nsec; changed = 1; } - if ((max_diff_time.tv_nsec == 0) || (diff_time.tv_nsec > max_diff_time.tv_nsec)) { max_diff_time.tv_nsec = diff_time.tv_nsec; changed = 1; } -#if 1 - if (changed) print_difftimes(); -#endif -} - -/*------------------------------------------------------------------------*/ - unsigned int build_rflocal(int txi, int txq, int rxi, int rxq) { return (txi + (txq<<6) + (rxi<<12) + (rxq<<18)); @@ -479,7 +430,7 @@ void help (void) { printf(" -h provides this help message!\n"); printf(" -K Generate ITTI analyzser logs (similar to wireshark logs but with more details)\n"); printf(" -m Set the maximum downlink MCS\n"); - printf(" -M Specify whether RF head is local or remote,valid options: (1: local , 2:remote) \n"); + printf(" -M IP address of RRH\n"); printf(" -O eNB configuration file (located in targets/PROJECTS/GENERIC-LTE-EPC/CONF\n"); printf(" -q Enable processing timing measurement of lte softmodem on per subframe basis \n"); printf(" -r Set the PRB, valid values: 6, 25, 50, 100 \n"); @@ -996,12 +947,6 @@ void do_OFDM_mod_rt(int subframe,PHY_VARS_eNB *phy_vars_eNB) if (tx_offset>=(LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*phy_vars_eNB->lte_frame_parms.samples_per_tti)) tx_offset -= LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*phy_vars_eNB->lte_frame_parms.samples_per_tti; - ((short*)&phy_vars_eNB->lte_eNB_common_vars.txdata[0][aa][tx_offset])[0] = ((short*)dummy_tx_b)[2*i]<lte_eNB_common_vars.txdata[0][aa][tx_offset])[1] = ((short*)dummy_tx_b)[2*i+1]<lte_eNB_common_vars.txdata[0][aa][tx_offset])[0]= #ifdef EXMIMO ((short*)dummy_tx_b)[2*i]<<4; @@ -1018,7 +963,6 @@ void do_OFDM_mod_rt(int subframe,PHY_VARS_eNB *phy_vars_eNB) #else ((short*)dummy_tx_b)[2*i+1]<<4; #endif -*/ } // if S-subframe switch to RX in second subframe if (subframe_select(&phy_vars_eNB->lte_frame_parms,subframe) == SF_S) { @@ -1836,9 +1780,7 @@ static void* eNB_thread( void* arg ) PHY_vars_eNB_g[0][0]->lte_frame_parms.nb_antennas_rx); stop_meas( &softmodem_stats_hw ); - if (frame > 50) { - clock_gettime( CLOCK_MONOTONIC, &trx_time1 ); - } + clock_gettime( CLOCK_MONOTONIC, &trx_time1 ); if (frame > 20){ if (rxs != spp) @@ -1847,6 +1789,8 @@ static void* eNB_thread( void* arg ) VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ, 0 ); // Transmit TX buffer based on timestamp from RX + + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE, 1 ); // prepare tx buffer pointers @@ -1867,23 +1811,16 @@ static void* eNB_thread( void* arg ) VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TST, (timestamp+(openair0_cfg[card].tx_delay*spp)-openair0_cfg[card].tx_forward_nsamps)&0xffffffff ); stop_meas( &softmodem_stats_mt ); - if (frame > 50) { - clock_gettime( CLOCK_MONOTONIC, &trx_time2 ); - // BMC: compute time between rx and tx - update_difftimes(trx_time1, trx_time2); - } - + clock_gettime( CLOCK_MONOTONIC, &trx_time2 ); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE,0); #else // USRP_DEBUG is active rt_sleep_ns(1000000); #endif -/* FT configurable tx lauch delay (in slots )*/ + if ((tx_launched == 0) && - ((openair0_cfg[card].txlaunch_wait == 0) || - ((openair0_cfg[card].txlaunch_wait == 1) && - (rx_pos >= (((2*hw_subframe)+openair0_cfg[card].txlaunch_wait_slotcount)*PHY_vars_eNB_g[0][0]->lte_frame_parms.samples_per_tti>>1))))) { + (rx_pos >= (((2*hw_subframe)+1)*PHY_vars_eNB_g[0][0]->lte_frame_parms.samples_per_tti>>1))) { tx_launched = 1; for (CC_id=0; CC_idproperties[i]->nb_cc, i); + for (j=0; jproperties[i]->nb_rrh_gw; j++) { + + if (enb_properties->properties[i]->rrh_gw_config[j].active == 1 ){ + // replace printf by setting + printf( "\n\tRRH GW %d config for eNB %u:\n\n", j, i); + printf( "\tinterface name : \t%s:\n",enb_properties->properties[i]->rrh_gw_if_name); + printf( "\tlocal address : \t%s:\n",enb_properties->properties[i]->rrh_gw_config[j].local_address); + printf( "\tlocal port : \t%d:\n",enb_properties->properties[i]->rrh_gw_config[j].local_port); + printf( "\tremote address : \t%s:\n",enb_properties->properties[i]->rrh_gw_config[j].remote_address); + printf( "\tremote port : \t%d:\n",enb_properties->properties[i]->rrh_gw_config[j].remote_port); + printf( "\ttransport : \t%s Ethernet:\n\n",(enb_properties->properties[i]->rrh_gw_config[j].raw == 1)? "RAW" : "UDP"); + } + + } + for (CC_id=0; CC_idframe_type = enb_properties->properties[i]->frame_type[CC_id]; frame_parms[CC_id]->tdd_config = enb_properties->properties[i]->tdd_config[CC_id]; @@ -2910,11 +2861,6 @@ int main( int argc, char **argv ) for (card=0; cardN_RB_DL == 100) { sample_rate = 30.72e6; bw = 10.0e6; @@ -2925,8 +2871,8 @@ int main( int argc, char **argv ) openair0_cfg[card].tx_bw = 10e6; openair0_cfg[card].rx_bw = 10e6; // from usrp_time_offset - //openair0_cfg[card].tx_forward_nsamps = 175; - // openair0_cfg[card].tx_delay = 8; + openair0_cfg[card].tx_forward_nsamps = 175; + openair0_cfg[card].tx_delay = 8; #endif } else if(frame_parms[0]->N_RB_DL == 50) { sample_rate = 15.36e6; @@ -2937,8 +2883,8 @@ int main( int argc, char **argv ) openair0_cfg[card].samples_per_frame = 153600; openair0_cfg[card].tx_bw = 5e6; openair0_cfg[card].rx_bw = 5e6; - //openair0_cfg[card].tx_forward_nsamps = 95; - //openair0_cfg[card].tx_delay = 5; + openair0_cfg[card].tx_forward_nsamps = 95; + openair0_cfg[card].tx_delay = 5; #endif } else if (frame_parms[0]->N_RB_DL == 25) { sample_rate = 7.68e6; @@ -2950,14 +2896,12 @@ int main( int argc, char **argv ) openair0_cfg[card].rx_bw = 2.5e6; openair0_cfg[card].samples_per_packet = 1024; #ifdef OAI_USRP - - // openair0_cfg[card].tx_forward_nsamps = 70; - //openair0_cfg[card].tx_delay = 5; -#endif - //#elif OAI_BLADERF - //openair0_cfg[card].tx_forward_nsamps = 0; - //openair0_cfg[card].tx_delay = 8; - //#endif + openair0_cfg[card].tx_forward_nsamps = 70; + openair0_cfg[card].tx_delay = 5; +#elif OAI_BLADERF + openair0_cfg[card].tx_forward_nsamps = 0; + openair0_cfg[card].tx_delay = 8; +#endif #endif } else if (frame_parms[0]->N_RB_DL == 6) { sample_rate = 1.92e6; @@ -2968,26 +2912,16 @@ int main( int argc, char **argv ) openair0_cfg[card].samples_per_frame = 19200; openair0_cfg[card].tx_bw = 1.5e6; openair0_cfg[card].rx_bw = 1.5e6; - //openair0_cfg[card].tx_forward_nsamps = 40; - //openair0_cfg[card].tx_delay = 8; + openair0_cfg[card].tx_forward_nsamps = 40; + openair0_cfg[card].tx_delay = 8; #endif } #ifdef ETHERNET - //openair0_cfg[card].remote_addr = "192.168.12.242"; - //openair0_cfg[card].remote_addr = "127.0.0.1"; - openair0_cfg[card].remote_addr = "74:d4:35:cc:88:45"; - openair0_cfg[card].remote_port = 50000; - //openair0_cfg[card].my_addr = "192.168.12.31"; - //openair0_cfg[card].my_addr = "127.0.0.1"; - openair0_cfg[card].my_addr = "d4:be:d9:22:0a:ac"; - openair0_cfg[card].my_port = 50000; - //openair0_cfg[card].my_port = 50001; - openair0_cfg[card].tx_delay = 10; + //calib needed + openair0_cfg[card].tx_delay = 0; openair0_cfg[card].tx_forward_nsamps = 0; - openair0_cfg[card].txlaunch_wait = 0; - openair0_cfg[card].txlaunch_wait_slotcount = 0; if (frame_parms[0]->N_RB_DL == 6) openair0_cfg[card].samples_per_packet = 256; @@ -3000,20 +2934,23 @@ int main( int argc, char **argv ) #ifndef EXMIMO openair0_cfg[card].samples_per_packet = openair0_cfg[0].samples_per_packet; - openair0_cfg[card].num_rb_dl=frame_parms[0]->N_RB_DL; #endif printf("HW: Configuring card %d, nb_antennas_tx/rx %d/%d\n",card, ((UE_flag==0) ? PHY_vars_eNB_g[0][0]->lte_frame_parms.nb_antennas_tx : PHY_vars_UE_g[0][0]->lte_frame_parms.nb_antennas_tx), ((UE_flag==0) ? PHY_vars_eNB_g[0][0]->lte_frame_parms.nb_antennas_rx : PHY_vars_UE_g[0][0]->lte_frame_parms.nb_antennas_rx)); openair0_cfg[card].Mod_id = 0; -#ifdef ETHERNET/*do we need to separate ue and enb????*/ - +#ifdef ETHERNET + if (UE_flag) { printf("ETHERNET: Configuring UE ETH for %s:%d\n",rrh_UE_ip,rrh_UE_port); - openair0_cfg[card].remote_addr = &rrh_UE_ip[0]; + openair0_cfg[card].remote_ip = &rrh_UE_ip[0]; openair0_cfg[card].remote_port = rrh_UE_port; - } - + } else { + printf("ETHERNET: Configuring eNB ETH for %s:%d\n",rrh_eNB_ip,rrh_eNB_port); + openair0_cfg[card].remote_ip = &rrh_eNB_ip[0]; + openair0_cfg[card].remote_port = rrh_eNB_port; + } +openair0_cfg[card].num_rb_dl=frame_parms[0]->N_RB_DL; #endif openair0_cfg[card].sample_rate = sample_rate; openair0_cfg[card].tx_bw = bw; @@ -3066,36 +3003,18 @@ int main( int argc, char **argv ) #endif } - /* device host type is set*/ - openair0.host_type = BBU_HOST; - /* device type is initialized NONE_DEV (no RF device) when the RF device will be initiated device type will be set */ - openair0.type = NONE_DEV; - /* transport type is initialized NONE_TP (no transport protocol) when the transport protocol will be initiated transport protocol type will be set */ - openair0.transp_type = NONE_TP; + + openair0.func_type = BBU_FUNC; openair0_cfg[0].log_level = glog_level; - - /* BBU can either have local or remote radio heads - local radio head option is set by default so the corresponding device is initiated */ + if ((mode!=loop_through_memory) && - (openair0_device_load(&openair0, &openair0_cfg[0]) <0)) { + (openair0_device_init(&openair0, &openair0_cfg[0]) <0)) { printf("Exiting, cannot initialize device\n"); exit(-1); } else if (mode==loop_through_memory) { } - /* radio heads are remote so the trasnsport protocol is initiated */ - if (local_remote_RF == BBU_REMOTE_RF_ENABLED) { - if ((mode!=loop_through_memory) && - (openair0_transport_load(&openair0, &openair0_cfg[0]) <0)) { - printf("Exiting, cannot initialize transport protocol\n"); - exit(-1); - } - else if (mode==loop_through_memory) { - } - } - //for EXMIMO - //openair0_cfg[0].iq_rxrescale=15; /* default value if build with EXMIMO */ - //rxrescale=openair0_cfg[0].iq_rxrescale; /* see comments near RX_IQRESCALELEN definition */ - + printf("Done\n"); mac_xface = malloc(sizeof(MAC_xface)); @@ -3513,6 +3432,7 @@ int main( int argc, char **argv ) if (multi_thread>0) { printf("Killing eNB processing threads\n"); kill_eNB_proc(); + } } @@ -3604,6 +3524,10 @@ int setup_eNB_buffers(PHY_VARS_eNB **phy_vars_eNB, openair0_config_t *openair0_c #endif + + + + // replace RX signal buffers with mmaped HW versions #ifdef EXMIMO openair0_cfg[CC_id].tx_num_channels = 0; From 9dfa3c94495b01ae5951dacaf335ec4254dd1aa8 Mon Sep 17 00:00:00 2001 From: Florian Kaltenberger Date: Tue, 12 Jan 2016 13:46:57 +0100 Subject: [PATCH 112/263] small fix for mbmssim (a previous commit enabled XFORMS by default, which was not up to date in mbmssim) --- openair1/SIMULATION/LTE_PHY/mbmssim.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/openair1/SIMULATION/LTE_PHY/mbmssim.c b/openair1/SIMULATION/LTE_PHY/mbmssim.c index b9be0b27e8..9bcd4a2cb6 100644 --- a/openair1/SIMULATION/LTE_PHY/mbmssim.c +++ b/openair1/SIMULATION/LTE_PHY/mbmssim.c @@ -47,8 +47,7 @@ #include "LAYER2/MAC/vars.h" #ifdef XFORMS -#include -#include "../../USERSPACE_TOOLS/SCOPE/lte_scope.h" +#include "PHY/TOOLS/lte_phy_scope.h" #endif //XFORMS @@ -176,13 +175,13 @@ int main(int argc, char **argv) #ifdef XFORMS - FD_lte_scope *form_dl; + FD_lte_phy_scope_ue *form_ue; char title[255]; fl_initialize (&argc, argv, NULL, 0, 0); - form_dl = create_form_lte_scope(); + form_ue = create_lte_phy_scope_ue(); sprintf (title, "LTE DL SCOPE UE"); - fl_show_form (form_dl->lte_scope, FL_PLACE_HOTSPOT, FL_FULLBORDER, title); + fl_show_form (form_ue->lte_phy_scope_ue, FL_PLACE_HOTSPOT, FL_FULLBORDER, title); #endif logInit(); From cd34b4499bc6276c06aaaa850c58b0b98d56bf06 Mon Sep 17 00:00:00 2001 From: Cedric Roux Date: Tue, 12 Jan 2016 16:34:25 +0100 Subject: [PATCH 113/263] put back logs for asn1c installation --- cmake_targets/tools/build_helper | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/cmake_targets/tools/build_helper b/cmake_targets/tools/build_helper index 84c7d8ee21..7d360ca437 100755 --- a/cmake_targets/tools/build_helper +++ b/cmake_targets/tools/build_helper @@ -280,6 +280,9 @@ check_install_oai_software() { } install_asn1c_from_source(){ + asn1_install_dir=$OPENAIR_DIR/cmake_targets/log/asn1c_install_log.txt + echo_info "\nInstalling ASN1. The log file for ASN1 installation is here: $asn1_install_dir " + ( rm -rf /tmp/asn1c-r1516 mkdir -p /tmp/asn1c-r1516 cd /tmp/asn1c-r1516 @@ -289,7 +292,8 @@ install_asn1c_from_source(){ patch -p0 < $OPENAIR_DIR/openair2/RRC/LITE/MESSAGES/asn1c/asn1cpatch.p0 ./configure make -j`nproc` - $SUDO make install + $SUDO make install + ) > $asn1_install_dir 2>&1 } ################################################# From 48898710848ec8296cfa048d552be3c6f9a9bd98 Mon Sep 17 00:00:00 2001 From: Cedric Roux Date: Tue, 12 Jan 2016 16:43:41 +0100 Subject: [PATCH 114/263] remove phpmyadmin from the installed additional tools --- cmake_targets/tools/build_helper | 1 - 1 file changed, 1 deletion(-) diff --git a/cmake_targets/tools/build_helper b/cmake_targets/tools/build_helper index 7d360ca437..db88780f5b 100755 --- a/cmake_targets/tools/build_helper +++ b/cmake_targets/tools/build_helper @@ -188,7 +188,6 @@ check_install_additional_tools (){ libboost-all-dev \ libpthread-stubs0-dev \ openvpn \ - phpmyadmin \ pkg-config \ python-dev \ python-pexpect \ From 1b6407d746178c9ff9cb65ec92a5126d7e72b7bc Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Tue, 12 Jan 2016 19:13:50 +0100 Subject: [PATCH 115/263] fixes to reset USB bus for bandrich UE --- cmake_targets/autotests/test_case_list.xml | 54 +++++++++--------- .../tools/configure_cots_bandrich_ue.py | 56 ++++++++++++++++++- .../autotests/tools/find_usb_path.bash | 20 +++++++ 3 files changed, 101 insertions(+), 29 deletions(-) create mode 100755 cmake_targets/autotests/tools/find_usb_path.bash diff --git a/cmake_targets/autotests/test_case_list.xml b/cmake_targets/autotests/test_case_list.xml index 0a494f4a03..9029de680c 100644 --- a/cmake_targets/autotests/test_case_list.xml +++ b/cmake_targets/autotests/test_case_list.xml @@ -6,7 +6,7 @@ https://gitlab.eurecom.fr/oai/openair-cn.git develop feature-17-test_framework - oaisim* oaisim_nos1* lte-softmodem* lte-softmodem-nos1* mme_gw* run_epc* run_hss* hss hss_sim configure_cots_bandrich_ue* wvdial* run_exec_autotests* iperf iperf_script + oaisim* oaisim_nos1* lte-softmodem* lte-softmodem-nos1* mme_gw* run_epc* run_hss* hss hss_sim configure_cots_bandrich_ue* wvdial* iperf iperf_script ping sudo -S -E /opt/ltebox/tools/stop_ltebox $OPENAIR_DIR/cmake_targets/build_oai -w EXMIMO -c; sudo -S -E $OPENAIR_DIR/cmake_targets/tools/stop_exmimo2; dmesg|tail 36000 @@ -900,7 +900,7 @@ --eNB -w USRP -x -c - $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 45; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue + $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 45; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 1 ppp0 -u -c 192.172.0.1 -b 10Mbits/s -t 330 -B 192.172.0.2 @@ -984,7 +984,7 @@ --eNB -w USRP -x -c - $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 45; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue + $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 45; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 1 ppp0 -u -c 192.172.0.1 -b 10Mbits/s -t 330 -B 192.172.0.2 @@ -1067,7 +1067,7 @@ --eNB -w USRP -x -c - $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 45; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue + $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 45; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 1 ppp0 -u -c 192.172.0.1 -b 10Mbits/s -t 330 -B 192.172.0.2 @@ -1150,7 +1150,7 @@ --eNB -w USRP -x -c - $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 45; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue + $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 45; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 1 ppp0 -s -i 1 -u -f m -B 192.172.0.2 @@ -1232,7 +1232,7 @@ --eNB -w USRP -x -c - $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 45; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue + $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 45; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 1 ppp0 -s -i 1 -u -f m -B 192.172.0.2 @@ -1315,7 +1315,7 @@ --eNB -w USRP -x -c - $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 45; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue + $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 45; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 1 ppp0 -s -i 1 -u -f m -B 192.172.0.2 @@ -1399,7 +1399,7 @@ --eNB -w USRP -x -c - $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 45; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue + $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue;$OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 45; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 1 ppp0 -u -c 192.172.0.1 -b 10Mbits/s -t 330 -B 192.172.0.2 @@ -1483,7 +1483,7 @@ --eNB -w USRP -x -c - $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 45; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue + $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue;$OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 45; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 1 ppp0 -u -c 192.172.0.1 -b 10Mbits/s -t 330 -B 192.172.0.2 @@ -1566,7 +1566,7 @@ --eNB -w USRP -x -c - $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 45; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue + $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 45; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 1 ppp0 -u -c 192.172.0.1 -b 10Mbits/s -t 330 -B 192.172.0.2 @@ -1649,7 +1649,7 @@ --eNB -w USRP -x -c - $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 45; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue + $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 45; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 1 ppp0 -s -i 1 -u -f m -B 192.172.0.2 @@ -1732,7 +1732,7 @@ --eNB -w USRP -x -c - $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 45; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue + $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 45; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 1 ppp0 -s -i 1 -u -f m -B 192.172.0.2 @@ -1815,7 +1815,7 @@ --eNB -w USRP -x -c - $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 45; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue + $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 45; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 1 ppp0 -s -i 1 -u -f m -B 192.172.0.2 @@ -1894,7 +1894,7 @@ --eNB -w USRP -x -c - $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 45; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue + $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 45; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 1 ppp0 -u -c 192.172.0.1 -b 10Mbits/s -t 330 -B 192.172.0.2 @@ -1973,7 +1973,7 @@ --eNB -w USRP -x -c - $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 45; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue + $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 45; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 1 ppp0 -u -c 192.172.0.1 -b 10Mbits/s -t 330 -B 192.172.0.2 @@ -2051,7 +2051,7 @@ --eNB -w USRP -x -c - $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 45; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue + $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 45; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 1 ppp0 -u -c 192.172.0.1 -b 10Mbits/s -t 330 -B 192.172.0.2 @@ -2129,7 +2129,7 @@ --eNB -w USRP -x -c - $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 45; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue + $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 45; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 1 ppp0 -s -i 1 -u -f m -B 192.172.0.2 @@ -2206,7 +2206,7 @@ --eNB -w USRP -x -c - $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 45; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue + $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 45; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 1 ppp0 -s -i 1 -u -f m -B 192.172.0.2 @@ -2283,7 +2283,7 @@ --eNB -w USRP -x -c - $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 45; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue + $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 45; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 1 ppp0 -s -i 1 -u -f m -B 192.172.0.2 @@ -2363,7 +2363,7 @@ --eNB -w USRP -x -c - $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 45; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue + $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 45; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 1 ppp0 -u -c 192.172.0.1 -b 10Mbits/s -t 330 -B 192.172.0.2 @@ -2442,7 +2442,7 @@ --eNB -w USRP -x -c - $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 45; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue + $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 45; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 1 ppp0 -u -c 192.172.0.1 -b 10Mbits/s -t 330 -B 192.172.0.2 @@ -2520,7 +2520,7 @@ --eNB -w USRP -x -c - $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 45; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue + $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 45; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 1 ppp0 -u -c 192.172.0.1 -b 10Mbits/s -t 330 -B 192.172.0.2 @@ -2598,7 +2598,7 @@ --eNB -w USRP -x -c - $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 45; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue + $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 45; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 1 ppp0 -s -i 1 -u -f m -B 192.172.0.2 @@ -2675,7 +2675,7 @@ --eNB -w USRP -x -c - $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 45; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue + $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 45; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 1 ppp0 -s -i 1 -u -f m -B 192.172.0.2 @@ -2752,7 +2752,7 @@ --eNB -w USRP -x -c - $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 45; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue + $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 45; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 1 ppp0 -s -i 1 -u -f m -B 192.172.0.2 @@ -2824,7 +2824,7 @@ --eNB -w USRP -c - $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue + $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue ping 192.172.0.1 @@ -2903,7 +2903,7 @@ --eNB -w USRP -c - $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue + $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue ping 192.172.0.1 diff --git a/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py b/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py index aa041360b7..e22f86e67c 100755 --- a/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py +++ b/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py @@ -10,6 +10,7 @@ import threading import signal import traceback import os +import commands # configure the serial connections (the parameters differs on the device you are connecting to) #First we find an open port to work with @@ -34,8 +35,7 @@ def find_open_port(): ser = serial.Serial(port=serial_port) return -find_open_port() -print 'Using Serial port : ' + serial_port + #serial_port = '/dev/ttyUSB2' bandrich_ppd_config = os.environ.get('OPENAIR_DIR') + '/cmake_targets/autotests/tools/wdial.bandrich.conf' @@ -144,11 +144,63 @@ def stop_ue(): send_command('AT+CGATT=0' , 'OK|ERROR' , timeout) send_command('AT+CFUN=4' , 'OK' , timeout) + +#reset the USB BUS of Bandrich UE +def reset_ue(): + stringIdBandrich='BandRich, Inc. 4G LTE adapter' + status, out = commands.getstatusoutput('lsusb | grep -i \'' + stringIdBandrich + '\'') + if (out == '') : + print "Bandrich 4G LTE Adapter not found. Exiting now..." + sys.exit() + p=re.compile('Bus\s*(\w+)\s*Device\s*(\w+):\s*ID\s*(\w+):(\w+)') + res=p.findall(out) + BusId=res[0][0] + DeviceId=res[0][1] + VendorId=res[0][2] + ProductId=res[0][3] + usb_dir= find_usb_path(VendorId, ProductId) + print usb_dir + cmd = "sudo sh -c \"echo 0 > " + usb_dir + "/authorized\"" + os.system(cmd + " ; sleep 5" ) + cmd = "sudo sh -c \"echo 1 > " + usb_dir + "/authorized\"" + os.system(cmd + " ; sleep 5" ) + +def read_file(filename): + try: + file = open(filename, 'r') + return file.read() + except Exception, e: + #error = ' Filename ' + filename + #error = error + ' In function: ' + sys._getframe().f_code.co_name + ': *** Caught exception: ' + str(e.__class__) + " : " + str( e) + #error = error + traceback.format_exc() + #print error + return '' + + +def find_usb_path(idVendor, idProduct): + for root, dirs, files in os.walk("/sys/bus/usb/devices", topdown=False): + for name in dirs: + tmpdir= os.path.join(root, name) + tmpidVendor = read_file(tmpdir+'/idVendor').replace("\n","") + tmpidProduct = read_file(tmpdir+'/idProduct').replace("\n","") + #print "tmpdir = " + tmpdir + " tmpidVendor = " + tmpidVendor + " tmpidProduct = " + tmpidProduct + if tmpidVendor == idVendor and tmpidProduct == idProduct: + return tmpdir + return '' + for arg in sys.argv[1:]: if arg == '--start-ue' : + find_open_port() + print 'Using Serial port : ' + serial_port start_ue() elif arg == '--stop-ue' : + find_open_port() + print 'Using Serial port : ' + serial_port stop_ue() + elif arg == '--reset-ue' : + reset_ue() else : print " Script called with wrong arguments, arg = " + arg sys.exit() + + diff --git a/cmake_targets/autotests/tools/find_usb_path.bash b/cmake_targets/autotests/tools/find_usb_path.bash new file mode 100755 index 0000000000..c8ec950292 --- /dev/null +++ b/cmake_targets/autotests/tools/find_usb_path.bash @@ -0,0 +1,20 @@ +#!/bin/bash + +#arg1 idVendor +#arg2 idProduct +argIdVendor=$1 +argIdProduct=$2 + +echo $1 +echo $2 + +for X in /sys/bus/usb/devices/*; do + #echo "$X" + idVendor=`cat "$X/idVendor" 2>/dev/null` + idProduct=`cat "$X/idProduct" 2>/dev/null` + if [ "$argIdVendor" == "$idVendor" ] && [ "$argIdProduct" == "$idProduct" ] + then + echo "$X" + fi +done + From 03fc15f82d78db98a02f93a9aa554b7950de27ac Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Tue, 12 Jan 2016 19:35:47 +0100 Subject: [PATCH 116/263] default flags for deadline scheduler for different RF targets --- cmake_targets/build_oai | 30 ++++++++++++++++++++++++++++-- 1 file changed, 28 insertions(+), 2 deletions(-) diff --git a/cmake_targets/build_oai b/cmake_targets/build_oai index 740a57f6cf..c723d8d6dc 100755 --- a/cmake_targets/build_oai +++ b/cmake_targets/build_oai @@ -46,6 +46,7 @@ XFORMS="False" PRINT_STATS="False" VCD_TIMING="False" LOWLATENCY_FLAG_USER="False" +FORCE_LOWLATENCY_FLAG_USER="" REL="Rel10" HW="EXMIMO" NOS1=0 @@ -230,11 +231,11 @@ function main() { echo_info "setting CPU FLAGS from USER to: $CFLAGS_PROCESSOR_USER" shift 2;; --disable-deadline) - LOWLATENCY_FLAG_USER="False" + FORCE_LOWLATENCY_FLAG_USER="False" echo_info "Disabling the usage of deadline scheduler" shift 1;; --enable-deadline) - LOWLATENCY_FLAG_USER="True" + FORCE_LOWLATENCY_FLAG_USER="True" echo_info "Enabling the usage of deadline scheduler" shift 1;; @@ -248,6 +249,31 @@ function main() { esac done + #Now we set flags to enable deadline scheduler settings + #By default: USRP: disable, + #By default: BLADERF: enable, + #By default: EXMIMO: enable + if [ "$FORCE_LOWLATENCY_FLAG_USER" = "" ]; then + if [ "$HW" = "EXMIMO" ] ; then + LOWLATENCY_FLAG_USER="True" + elif [ "$HW" = "ETHERNET" ] ; then + LOWLATENCY_FLAG_USER="True" + elif [ "$HW" = "OAI_USRP" ] ; then + LOWLATENCY_FLAG_USER="False" + elif [ "$HW" = "OAI_BLADERF" ] ; then + LOWLATENCY_FLAG_USER="False" + elif [ "$HW" = "None" ] ; then + LOWLATENCY_FLAG_USER="False" + else + echo_error "Unknown HW type $HW. Exiting now..." + exit + fi + else + LOWLATENCY_FLAG_USER=$FORCE_LOWLATENCY_FLAG_USER + fi + + echo_info "Flags for Deadline scheduler: $LOWLATENCY_FLAG_USER" + ############################################ # setting and printing OAI envs, we should check here ############################################ From 8358273831471b2827357b3f83fedc1acab7bd3f Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Wed, 13 Jan 2016 16:25:29 +0100 Subject: [PATCH 117/263] update for using UHD version 3.9.2 --- cmake_targets/tools/build_helper | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/cmake_targets/tools/build_helper b/cmake_targets/tools/build_helper index 0866ca875a..496096e972 100755 --- a/cmake_targets/tools/build_helper +++ b/cmake_targets/tools/build_helper @@ -163,11 +163,16 @@ install_gnutls_from_source(){ check_install_usrp_uhd_driver(){ + #first we remove old installation + $SUDO apt-get remove uhd libuhd-dev libuhd003 uhd-host -y v=$(lsb_release -cs) - $SUDO apt-add-repository "deb http://files.ettus.com/binaries/uhd/repo/uhd/ubuntu/$v $v main" + $SUDO apt-add-repository --remove "deb http://files.ettus.com/binaries/uhd/repo/uhd/ubuntu/$v $v main" + #The new USRP repository + $SUDO add-apt-repository ppa:ettusresearch/uhd -y $SUDO apt-get update $SUDO apt-get -y install python python-tk libboost-all-dev libusb-1.0-0-dev - $SUDO apt-get -y install -t `lsb_release -cs` uhd --force-yes + $SUDO apt-get -y install libuhd-dev libuhd003 uhd-host + $SUDO uhd_images_downloader } check_install_bladerf_driver(){ $SUDO add-apt-repository -y ppa:bladerf/bladerf From 275e03e92b69507295d644039e4957f8ccac5b9f Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Wed, 13 Jan 2016 16:41:04 +0100 Subject: [PATCH 118/263] added paramter to override nruns in lte-softmodem test cases --- .../autotests/run_exec_lte-softmodem_tests.py | 12 +++++++++--- cmake_targets/autotests/test_case_list.xml | 1 + 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/cmake_targets/autotests/run_exec_lte-softmodem_tests.py b/cmake_targets/autotests/run_exec_lte-softmodem_tests.py index 00d6f01b2c..6cce8028c9 100755 --- a/cmake_targets/autotests/run_exec_lte-softmodem_tests.py +++ b/cmake_targets/autotests/run_exec_lte-softmodem_tests.py @@ -546,7 +546,8 @@ def wait_testcaseclass_generic_threads(threadListGeneric, timeout = 1): # \param password password with which to login # \param CleanupAluLteBox string that contains commands to stop ALU Bell Labs LTEBox (specified in test_case_list.xml) # \param ExmimoRfStop command to stop EXMIMO Card -def handle_testcaseclass_softmodem (testcase, oldprogramList, logdirOAI5GRepo , logdirOpenaircnRepo, MachineList, user, password, CleanUpAluLteBox, ExmimoRfStop): +# \param nruns_lte-softmodem global parameter to override number of runs (nruns) within the test case +def handle_testcaseclass_softmodem (testcase, oldprogramList, logdirOAI5GRepo , logdirOpenaircnRepo, MachineList, user, password, CleanUpAluLteBox, ExmimoRfStop, nruns_lte_softmodem): #We ignore the password sent to this function for secuirity reasons for password present in log files #It is recommended to add a line in /etc/sudoers that looks something like below. The line below will run sudo without password prompt # your_user_name ALL=(ALL:ALL) NOPASSWD: ALL @@ -560,7 +561,10 @@ def handle_testcaseclass_softmodem (testcase, oldprogramList, logdirOAI5GRepo , timeout_cmd = int(float(timeout_cmd)) #Timeout_thread is more than that of cmd to have room for compilation time, etc timeout_thread = timeout_cmd + 300 - nruns = testcase.findtext('nruns',default='') + if nruns_lte_softmodem == '': + nruns = testcase.findtext('nruns',default='') + else: + nruns = nruns_lte_softmodem nruns = int(float(nruns)) tags = testcase.findtext('tags',default='') eNBMachine = testcase.findtext('eNB',default='') @@ -1148,6 +1152,7 @@ if MachineListGeneric == '': MachineListGeneric = xmlRoot.findtext('MachineListGeneric',default='') TestCaseExclusionList = xmlRoot.findtext('TestCaseExclusionList',default='') ExmimoRfStop = xmlRoot.findtext('ExmimoRfStop',default='') +nruns_lte_softmodem = xmlRoot.findtext('nruns_lte-softmodem',default='') print "MachineList = " + MachineList print "GitOpenair-cnRepo = " + GitOpenaircnRepo @@ -1155,6 +1160,7 @@ print "GitOAI5GRepo = " + GitOAI5GRepo print "GitOAI5GBranch = " + GitOAI5GRepoBranch print "GitOpenaircnRepoBranch = " + GitOpenaircnRepoBranch print "NFSResultsShare = " + NFSResultsShare +print "nruns_lte_softmodem = " + nruns_lte_softmodem if GitOAI5GHeadVersion == '': cmd = "git show-ref --heads -s "+ GitOAI5GRepoBranch @@ -1345,7 +1351,7 @@ for testcase in testcaseList: print "testcasename = " + testcasename + " class = " + testcaseclass threadListGlobal = wait_testcaseclass_generic_threads(threadListGlobal, Timeout_execution) cleanOldProgramsAllMachines(oai_list, CleanUpOldProgs, CleanUpAluLteBox, ExmimoRfStop) - handle_testcaseclass_softmodem (testcase, CleanUpOldProgs, logdirOAI5GRepo, logdirOpenaircnRepo, MachineList, user, pw, CleanUpAluLteBox, ExmimoRfStop ) + handle_testcaseclass_softmodem (testcase, CleanUpOldProgs, logdirOAI5GRepo, logdirOpenaircnRepo, MachineList, user, pw, CleanUpAluLteBox, ExmimoRfStop, nruns_lte_softmodem ) elif (testcaseclass == 'compilation'): threadListGlobal = handle_testcaseclass_generic (testcasename, threadListGlobal, CleanUpOldProgs, logdirOAI5GRepo, MachineListGeneric, user, pw, CleanUpAluLteBox,Timeout_execution, ExmimoRfStop) elif (testcaseclass == 'execution'): diff --git a/cmake_targets/autotests/test_case_list.xml b/cmake_targets/autotests/test_case_list.xml index 9029de680c..2f75655132 100644 --- a/cmake_targets/autotests/test_case_list.xml +++ b/cmake_targets/autotests/test_case_list.xml @@ -11,6 +11,7 @@ $OPENAIR_DIR/cmake_targets/build_oai -w EXMIMO -c; sudo -S -E $OPENAIR_DIR/cmake_targets/tools/stop_exmimo2; dmesg|tail 36000 0104+ 015502 015505 015506 015507 015508 015508 015509 015510 015511 015600 015700 016102 016105 + 3 mozart calisson stevens nano amerique compilation From 31048d13b4609259436ac22dfb74f907f392040a Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Wed, 13 Jan 2016 16:52:44 +0100 Subject: [PATCH 119/263] added option to run cleanup before every run --- .gitlab-ci.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index ddbbcd54ab..8efa62d23c 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -21,8 +21,10 @@ job1: - echo $NFS_TEST_RESULTS_DIR - echo $EXTERNAL_SHARE_RESULTS_DIR - mkdir -p $OPENAIR_DIR/cmake_targets/autotests/log + - python $OPENAIR_DIR/cmake_targets/autotests/run_exec_lte-softmodem_tests.py -c -5GRepoHeadVersion $git_head -n $NFS_SHARE_DIR -u $OAI_USER -p $OAI_PASS >& $OPENAIR_DIR/cmake_targets/autotests/python_autotest_cleanup.log - python $OPENAIR_DIR/cmake_targets/autotests/run_exec_lte-softmodem_tests.py -r -5GRepoHeadVersion $git_head -n $NFS_SHARE_DIR -u $OAI_USER -p $OAI_PASS `echo $OAI_EXTRA_ARGS` -g $OAI_TEST_CASE_GROUP >& $OPENAIR_DIR/cmake_targets/autotests/python_autotest.log - mv $OPENAIR_DIR/cmake_targets/autotests/python_autotest.log $OPENAIR_DIR/cmake_targets/autotests/log/python_autotest.log + - mv $OPENAIR_DIR/cmake_targets/autotests/python_autotest_cleanup.log $OPENAIR_DIR/cmake_targets/autotests/log/python_autotest_cleanup.log - sshpass -p "$OAI_PASS" rsync -az -e "ssh -o StrictHostKeyChecking=no " --rsync-path="mkdir -p $NFS_TEST_RESULTS_DIR && rsync" $OPENAIR_DIR/cmake_targets/autotests/log $OAI_USER@localhost:$NFS_TEST_RESULTS_DIR - sshpass -p "$OAI_PASS" rsync -az -e "ssh -o StrictHostKeyChecking=no " --rsync-path="mkdir -p $EXTERNAL_SHARE_DIR && rsync" $OPENAIR_DIR/cmake_targets/autotests/log $OAI_USER@localhost:$EXTERNAL_SHARE_DIR - cat $OPENAIR_DIR/cmake_targets/autotests/log/results_autotests.xml From 3d16bd44beeed2721192456dc692c09029212d29 Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Thu, 14 Jan 2016 10:45:12 +0100 Subject: [PATCH 120/263] changed for new rx gain settings --- cmake_targets/autotests/test_case_list.xml | 26 +++++++++---------- .../CONF/enb.band7.tm1.50PRB.usrpx310.conf | 2 +- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/cmake_targets/autotests/test_case_list.xml b/cmake_targets/autotests/test_case_list.xml index 2f75655132..2a247bf5e2 100644 --- a/cmake_targets/autotests/test_case_list.xml +++ b/cmake_targets/autotests/test_case_list.xml @@ -872,7 +872,7 @@ targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf downlink_frequency 2660000000L targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf uplink_frequency_offset -120000000 targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf tx_gain 90 - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf rx_gain 130 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf rx_gain 125 targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf frame_type \"FDD\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf nb_antennas_rx 1 targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf nb_antennas_tx 1 @@ -956,7 +956,7 @@ targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf downlink_frequency 2660000000L targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf uplink_frequency_offset -120000000 targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf tx_gain 90 - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf rx_gain 130 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf rx_gain 125 targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf frame_type \"FDD\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf nb_antennas_rx 1 targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf nb_antennas_tx 1 @@ -1039,7 +1039,7 @@ targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf downlink_frequency 2660000000L targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf uplink_frequency_offset -120000000 targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf tx_gain 90 - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf rx_gain 130 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf rx_gain 125 targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf frame_type \"FDD\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf nb_antennas_rx 1 targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf nb_antennas_tx 1 @@ -1122,7 +1122,7 @@ targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf downlink_frequency 2660000000L targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf uplink_frequency_offset -120000000 targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf tx_gain 90 - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf rx_gain 130 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf rx_gain 125 targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf frame_type \"FDD\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf nb_antennas_rx 1 targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf nb_antennas_tx 1 @@ -1204,7 +1204,7 @@ targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf downlink_frequency 2660000000L targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf uplink_frequency_offset -120000000 targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf tx_gain 90 - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf rx_gain 130 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf rx_gain 125 targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf frame_type \"FDD\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf nb_antennas_rx 1 targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf nb_antennas_tx 1 @@ -1287,7 +1287,7 @@ targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf downlink_frequency 2660000000L targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf uplink_frequency_offset -120000000 targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf tx_gain 90 - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf rx_gain 130 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf rx_gain 125 targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf frame_type \"FDD\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf nb_antennas_rx 1 targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf nb_antennas_tx 1 @@ -1371,7 +1371,7 @@ targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf downlink_frequency 2660000000L targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf uplink_frequency_offset -120000000 targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf tx_gain 90 - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf rx_gain 130 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf rx_gain 125 targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf frame_type \"FDD\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf nb_antennas_rx 2 targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf nb_antennas_tx 2 @@ -1455,7 +1455,7 @@ targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf downlink_frequency 2660000000L targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf uplink_frequency_offset -120000000 targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf tx_gain 90 - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf rx_gain 130 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf rx_gain 125 targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf frame_type \"FDD\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf nb_antennas_rx 2 targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf nb_antennas_tx 2 @@ -1538,7 +1538,7 @@ targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf downlink_frequency 2660000000L targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf uplink_frequency_offset -120000000 targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf tx_gain 90 - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf rx_gain 130 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf rx_gain 125 targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf frame_type \"FDD\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf nb_antennas_rx 2 targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf nb_antennas_tx 2 @@ -1621,7 +1621,7 @@ targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf downlink_frequency 2660000000L targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf uplink_frequency_offset -120000000 targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf tx_gain 90 - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf rx_gain 130 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf rx_gain 125 targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf frame_type \"FDD\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf nb_antennas_rx 2 targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf nb_antennas_tx 2 @@ -1704,7 +1704,7 @@ targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf downlink_frequency 2660000000L targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf uplink_frequency_offset -120000000 targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf tx_gain 90 - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf rx_gain 130 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf rx_gain 125 targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf frame_type \"FDD\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf nb_antennas_rx 2 targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf nb_antennas_tx 2 @@ -1787,7 +1787,7 @@ targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf downlink_frequency 2660000000L targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf uplink_frequency_offset -120000000 targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf tx_gain 90 - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf rx_gain 130 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf rx_gain 125 targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf frame_type \"FDD\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf nb_antennas_rx 2 targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf nb_antennas_tx 2 @@ -1939,7 +1939,7 @@ amerique 390 /tmp - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpx310..conf tracking_area_code \"1\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpx310.conf tracking_area_code \"1\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpx310.conf mobile_country_code \"208\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpx310.conf mobile_network_code \"92\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpx310.conf N_RB_DL 50 diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpx310.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpx310.conf index 4c760e19c2..d0488f2d37 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpx310.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpx310.conf @@ -35,7 +35,7 @@ eNBs = nb_antennas_tx = 1; nb_antennas_rx = 1; tx_gain = 32; - rx_gain = 120; + rx_gain = 118; prach_root = 0; prach_config_index = 0; prach_high_speed = "DISABLE"; From b76da1942a692979ec037beaa43f3b1bca74d456 Mon Sep 17 00:00:00 2001 From: Florian Kaltenberger Date: Thu, 14 Jan 2016 11:58:14 +0100 Subject: [PATCH 121/263] disabling XFORMS compile options for unitary simulators, since it does not work with CI tests --- cmake_targets/lte-simulators/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake_targets/lte-simulators/CMakeLists.txt b/cmake_targets/lte-simulators/CMakeLists.txt index 0b706c8748..7a0e84b425 100644 --- a/cmake_targets/lte-simulators/CMakeLists.txt +++ b/cmake_targets/lte-simulators/CMakeLists.txt @@ -2,7 +2,7 @@ cmake_minimum_required(VERSION 2.8) set(PACKAGE_NAME "unitary_tests_simulators") set(PHYSIM True) set(RF_BOARD None) -set(XFORMS True) +set(XFORMS False) set(DEBUG_PHY False) set(MU_RECIEVER False) From a758a63f75b36a63b0c7c5be732323fd15aecb38 Mon Sep 17 00:00:00 2001 From: gauthier Date: Thu, 14 Jan 2016 15:07:30 +0100 Subject: [PATCH 122/263] Work with virtual interfaces, you will have to set the eNB virtual interfaces up yourself (ifconfig ethx:y ipv4@ up) --- .../enb.band7.tm1.usrpb210.epc.local.conf | 121 +++++++++--------- 1 file changed, 57 insertions(+), 64 deletions(-) diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf index 6470b310f0..75969c04fd 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf @@ -16,50 +16,49 @@ eNBs = tracking_area_code = "1"; mobile_country_code = "208"; - mobile_network_code = "95"; ////////// Physical parameters: component_carriers = ( { - frame_type = "FDD"; - tdd_config = 3; - tdd_config_s = 0; - prefix_type = "NORMAL"; - eutra_band = 7; - downlink_frequency = 2660000000L; - uplink_frequency_offset = -120000000; - Nid_cell = 0; - N_RB_DL = 25; - Nid_cell_mbsfn = 0; - nb_antennas_tx = 1; - nb_antennas_rx = 1; - tx_gain = 90; - rx_gain = 132; - prach_root = 0; - prach_config_index = 0; - prach_high_speed = "DISABLE"; - prach_zero_correlation = 1; - prach_freq_offset = 2; - pucch_delta_shift = 1; - pucch_nRB_CQI = 1; - pucch_nCS_AN = 0; - pucch_n1_AN = 32; - pdsch_referenceSignalPower = -26; - pdsch_p_b = 0; - pusch_n_SB = 1; - pusch_enable64QAM = "DISABLE"; - pusch_hoppingMode = "interSubFrame"; - pusch_hoppingOffset = 0; - pusch_groupHoppingEnabled = "ENABLE"; - pusch_groupAssignment = 0; - pusch_sequenceHoppingEnabled = "DISABLE"; - pusch_nDMRS1 = 1; - phich_duration = "NORMAL"; - phich_resource = "ONESIXTH"; + frame_type = "FDD"; + tdd_config = 3; + tdd_config_s = 0; + prefix_type = "NORMAL"; + eutra_band = 7; + downlink_frequency = 2660000000L; + uplink_frequency_offset = -120000000; + Nid_cell = 0; + N_RB_DL = 25; + Nid_cell_mbsfn = 0; + nb_antennas_tx = 1; + nb_antennas_rx = 1; + tx_gain = 90; + rx_gain = 132; + prach_root = 0; + prach_config_index = 0; + prach_high_speed = "DISABLE"; + prach_zero_correlation = 1; + prach_freq_offset = 2; + pucch_delta_shift = 1; + pucch_nRB_CQI = 1; + pucch_nCS_AN = 0; + pucch_n1_AN = 32; + pdsch_referenceSignalPower = -26; + pdsch_p_b = 0; + pusch_n_SB = 1; + pusch_enable64QAM = "DISABLE"; + pusch_hoppingMode = "interSubFrame"; + pusch_hoppingOffset = 0; + pusch_groupHoppingEnabled = "ENABLE"; + pusch_groupAssignment = 0; + pusch_sequenceHoppingEnabled = "DISABLE"; + pusch_nDMRS1 = 1; + phich_duration = "NORMAL"; + phich_resource = "ONESIXTH"; srs_enable = "DISABLE"; - /* srs_BandwidthConfig =; + /* srs_BandwidthConfig =; srs_SubframeConfig =; srs_ackNackST =; srs_MaxUpPts =;*/ @@ -72,15 +71,15 @@ eNBs = pucch_deltaF_Format1b = "deltaF3"; pucch_deltaF_Format2 = "deltaF0"; pucch_deltaF_Format2a = "deltaF0"; - pucch_deltaF_Format2b = "deltaF0"; + pucch_deltaF_Format2b = "deltaF0"; rach_numberOfRA_Preambles = 64; rach_preamblesGroupAConfig = "DISABLE"; - /* + /* rach_sizeOfRA_PreamblesGroupA = ; rach_messageSizeGroupA = ; rach_messagePowerOffsetGroupB = ; - */ + */ rach_powerRampingStep = 4; rach_preambleInitialReceivedTargetPower = -108; rach_preambleTransMax = 10; @@ -90,16 +89,17 @@ eNBs = pcch_default_PagingCycle = 128; pcch_nB = "oneT"; - bcch_modificationPeriodCoeff = 2; - ue_TimersAndConstants_t300 = 1000; - ue_TimersAndConstants_t301 = 1000; - ue_TimersAndConstants_t310 = 1000; - ue_TimersAndConstants_t311 = 10000; - ue_TimersAndConstants_n310 = 20; - ue_TimersAndConstants_n311 = 1; + bcch_modificationPeriodCoeff = 2; + ue_TimersAndConstants_t300 = 1000; + ue_TimersAndConstants_t301 = 1000; + ue_TimersAndConstants_t310 = 1000; + ue_TimersAndConstants_t311 = 10000; + ue_TimersAndConstants_n310 = 20; + ue_TimersAndConstants_n311 = 1; } ); + srb1_parameters : { # timer_poll_retransmit = (ms) [5, 10, 15, 20,... 250, 300, 350, ... 500] @@ -129,28 +129,25 @@ eNBs = SCTP_OUTSTREAMS = 2; }; - ////////// MME parameters: - mme_ip_address = ( { ipv4 = "192.188.2.2"; - ipv6 = "192:168:30::17"; - active = "yes"; - preference = "ipv4"; - } - ); + mme_ip_address = ( {ipv4 = "192.170.0.1"; + ipv6="192:168:30::17"; + active="yes"; + preference="ipv4";}); NETWORK_INTERFACES : { - ENB_INTERFACE_NAME_FOR_S1_MME = "tun2"; - ENB_IPV4_ADDRESS_FOR_S1_MME = "192.188.2.2/24"; + ENB_INTERFACE_NAME_FOR_S1_MME = "eth0:3"; + ENB_IPV4_ADDRESS_FOR_S1_MME = "192.170.0.2/24"; - ENB_INTERFACE_NAME_FOR_S1U = "lo"; - ENB_IPV4_ADDRESS_FOR_S1U = "127.0.0.1/24"; - ENB_PORT_FOR_S1U = 2153; # Spec 2152 + ENB_INTERFACE_NAME_FOR_S1U = "eth0:4"; + ENB_IPV4_ADDRESS_FOR_S1U = "192.170.0.2/24"; + ENB_PORT_FOR_S1U = 2152; # Spec 2152 }; log_config : { - global_log_level ="info"; + global_log_level ="debug"; global_log_verbosity ="medium"; hw_log_level ="info"; hw_log_verbosity ="medium"; @@ -164,10 +161,6 @@ eNBs = pdcp_log_verbosity ="medium"; rrc_log_level ="info"; rrc_log_verbosity ="medium"; - gtpu_log_level ="info"; - gtpu_log_verbosity ="medium"; - udp_log_level ="info"; - udp_log_verbosity ="medium"; }; } From c7483721f95c93f7224e0e81254109118db15bdd Mon Sep 17 00:00:00 2001 From: gauthier Date: Thu, 14 Jan 2016 17:07:10 +0100 Subject: [PATCH 123/263] to be tested --- openair2/COMMON/platform_types.h | 6 + openair2/RRC/LITE/defs.h | 6 +- openair2/RRC/LITE/rrc_eNB.c | 133 ++++++++++-------- .../enb.band7.tm1.usrpb210.epc.remote.conf | 12 +- 4 files changed, 86 insertions(+), 71 deletions(-) diff --git a/openair2/COMMON/platform_types.h b/openair2/COMMON/platform_types.h index a1af19fd0a..6f7722316f 100755 --- a/openair2/COMMON/platform_types.h +++ b/openair2/COMMON/platform_types.h @@ -163,7 +163,13 @@ typedef uint32_t mbms_session_id_t; typedef uint16_t mbms_service_id_t; typedef uint16_t rnti_t; typedef uint8_t rrc_enb_index_t; +typedef uint8_t mme_code_t; +typedef uint32_t m_tmsi_t; +//Random UE identity length = 40 bits +#if ! defined(NOT_A_RANDOM_UE_IDENTITY) +#define NOT_A_RANDOM_UE_IDENTITY (uint64_t)0xFFFFFFFF +#endif #if ! defined(NOT_A_RNTI) #define NOT_A_RNTI (rnti_t)0 #endif diff --git a/openair2/RRC/LITE/defs.h b/openair2/RRC/LITE/defs.h index bae3dc887a..78240de082 100644 --- a/openair2/RRC/LITE/defs.h +++ b/openair2/RRC/LITE/defs.h @@ -212,9 +212,9 @@ typedef struct UE_RRC_INFO_s { } __attribute__ ((__packed__)) UE_RRC_INFO; typedef struct UE_S_TMSI_s { - uint8_t presence; - uint8_t mme_code; - uint32_t m_tmsi; + boolean_t presence; + mme_code_t mme_code; + m_tmsi_t m_tmsi; } __attribute__ ((__packed__)) UE_S_TMSI; #if defined(ENABLE_ITTI) diff --git a/openair2/RRC/LITE/rrc_eNB.c b/openair2/RRC/LITE/rrc_eNB.c index 0148626e5f..96fc8a4b8f 100644 --- a/openair2/RRC/LITE/rrc_eNB.c +++ b/openair2/RRC/LITE/rrc_eNB.c @@ -540,8 +540,8 @@ rrc_eNB_get_next_transaction_identifier( //----------------------------------------------------------------------------- -// return 1 if there is already an UE with ue_identityP, 0 otherwise -static int +// return the ue context if there is already an UE with ue_identityP, NULL otherwise +static struct rrc_eNB_ue_context_s* rrc_eNB_ue_context_random_exist( const protocol_ctxt_t* const ctxt_pP, const uint64_t ue_identityP @@ -551,9 +551,28 @@ rrc_eNB_ue_context_random_exist( struct rrc_eNB_ue_context_s* ue_context_p = NULL; RB_FOREACH(ue_context_p, rrc_ue_tree_s, &(eNB_rrc_inst[ctxt_pP->module_id].rrc_ue_head)) { if (ue_context_p->ue_context.random_ue_identity == ue_identityP) - return 1; + return ue_context_p; } - return 0; + return NULL; +} +//----------------------------------------------------------------------------- +// return the ue context if there is already an UE with the same S-TMSI(MMEC+M-TMSI), NULL otherwise +static struct rrc_eNB_ue_context_s* +rrc_eNB_ue_context_stmsi_exist( + const protocol_ctxt_t* const ctxt_pP, + const mme_code_t mme_codeP, + const m_tmsi_t m_tmsiP +) +//----------------------------------------------------------------------------- +{ + struct rrc_eNB_ue_context_s* ue_context_p = NULL; + RB_FOREACH(ue_context_p, rrc_ue_tree_s, &(eNB_rrc_inst[ctxt_pP->module_id].rrc_ue_head)) { + if (ue_context_p->ue_context.Initialue_identity_s_TMSI.presence == TRUE) + if (ue_context_p->ue_context.Initialue_identity_s_TMSI.m_tmsi == m_tmsiP) + if (ue_context_p->ue_context.Initialue_identity_s_TMSI.mme_code == mme_codeP) + return ue_context_p; + } + return NULL; } //----------------------------------------------------------------------------- @@ -3670,30 +3689,60 @@ rrc_eNB_decode_ccch( } else { rrcConnectionRequest = &ul_ccch_msg->message.choice.c1.choice.rrcConnectionRequest.criticalExtensions.choice.rrcConnectionRequest_r8; { - if (rrcConnectionRequest->ue_Identity.present != InitialUE_Identity_PR_randomValue) { + if (InitialUE_Identity_PR_randomValue == rrcConnectionRequest->ue_Identity.present) { + AssertFatal(rrcConnectionRequest->ue_Identity.choice.randomValue.size == 5, + "wrong InitialUE-Identity randomValue size, expected 5, provided %d", + rrcConnectionRequest->ue_Identity.choice.randomValue.size); + memcpy(((uint8_t*) & random_value) + 3, + rrcConnectionRequest->ue_Identity.choice.randomValue.buf, + rrcConnectionRequest->ue_Identity.choice.randomValue.size); + /* if there is already a registered UE (with another RNTI) with this random_value, + * the current one must be removed from MAC/PHY (zombie UE) + */ + if ((ue_context_p = rrc_eNB_ue_context_random_exist(ctxt_pP, random_value))) { + AssertFatal(0 == 1, "TODO: remove UE from MAC/PHY (how?)"); + ue_context_p = NULL; + } else { + ue_context_p = rrc_eNB_get_next_free_ue_context(ctxt_pP, random_value); + } + } else if (InitialUE_Identity_PR_s_TMSI == rrcConnectionRequest->ue_Identity.present) { + /* Save s-TMSI */ + S_TMSI_t s_TMSI = rrcConnectionRequest->ue_Identity.choice.s_TMSI; + mme_code_t mme_code = BIT_STRING_to_uint8(&s_TMSI.mmec); + m_tmsi_t m_tmsi = BIT_STRING_to_uint32(&s_TMSI.m_TMSI); + random_value = (((uint64_t)mme_code) << 32) | m_tmsi; + if ((ue_context_p = rrc_eNB_ue_context_stmsi_exist(ctxt_pP, mme_code, m_tmsi))) { + AssertFatal(0 == 1, "TODO: remove UE from MAC/PHY (how?)"); + ue_context_p = NULL; + } else { + ue_context_p = rrc_eNB_get_next_free_ue_context(ctxt_pP, NOT_A_RANDOM_UE_IDENTITY); + } + ue_context_p->ue_context.Initialue_identity_s_TMSI.presence = TRUE; + ue_context_p->ue_context.Initialue_identity_s_TMSI.mme_code = mme_code; + ue_context_p->ue_context.Initialue_identity_s_TMSI.m_tmsi = m_tmsi; + + MSC_LOG_RX_MESSAGE( + MSC_RRC_ENB, + MSC_RRC_UE, + Srb_info->Rx_buffer.Payload, + dec_rval.consumed, + MSC_AS_TIME_FMT" RRCConnectionRequest UE %x size %u (s-TMSI mmec %u m_TMSI %u random UE id (0x%" PRIx64 ")", + MSC_AS_TIME_ARGS(ctxt_pP), + ue_context_p->ue_context.rnti, + dec_rval.consumed, + ue_context_p->ue_context.Initialue_identity_s_TMSI.mme_code, + ue_context_p->ue_context.Initialue_identity_s_TMSI.m_tmsi, + ue_context_p->ue_context.random_ue_identity); + } else { LOG_E(RRC, - PROTOCOL_RRC_CTXT_UE_FMT" RRCConnectionRequest with S-TMSI not supported yet, let's reject the UE\n", + PROTOCOL_RRC_CTXT_UE_FMT" RRCConnectionRequest without random UE identity or S-TMSI not supported, let's reject the UE\n", PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP)); rrc_eNB_generate_RRCConnectionReject(ctxt_pP, rrc_eNB_get_ue_context(&eNB_rrc_inst[ctxt_pP->module_id], ctxt_pP->rnti), CC_id); break; } - AssertFatal(rrcConnectionRequest->ue_Identity.choice.randomValue.size == 5, - "wrong InitialUE-Identity randomValue size, expected 5, provided %d", - rrcConnectionRequest->ue_Identity.choice.randomValue.size); - memcpy(((uint8_t*) & random_value) + 3, - rrcConnectionRequest->ue_Identity.choice.randomValue.buf, - rrcConnectionRequest->ue_Identity.choice.randomValue.size); - /* if there is already a registered UE (with another RNTI) with this random_value, - * the current one must be removed from MAC/PHY (zombie UE) - */ - if (rrc_eNB_ue_context_random_exist(ctxt_pP, random_value)) { - AssertFatal(0 == 1, "TODO: remove UE fro MAC/PHY (how?)"); - ue_context_p = NULL; - } else { - ue_context_p = rrc_eNB_get_next_free_ue_context(ctxt_pP, random_value); - } + } LOG_D(RRC, PROTOCOL_RRC_CTXT_UE_FMT" UE context: %X\n", @@ -3704,47 +3753,7 @@ rrc_eNB_decode_ccch( #if defined(ENABLE_ITTI) - /* Check s-TMSI presence in message */ - ue_context_p->ue_context.Initialue_identity_s_TMSI.presence = - (rrcConnectionRequest->ue_Identity.present == InitialUE_Identity_PR_s_TMSI); - - if (ue_context_p->ue_context.Initialue_identity_s_TMSI.presence) { - /* Save s-TMSI */ - S_TMSI_t s_TMSI = rrcConnectionRequest->ue_Identity.choice.s_TMSI; - - ue_context_p->ue_context.Initialue_identity_s_TMSI.mme_code = - BIT_STRING_to_uint8(&s_TMSI.mmec); - ue_context_p->ue_context.Initialue_identity_s_TMSI.m_tmsi = - BIT_STRING_to_uint32(&s_TMSI.m_TMSI); - - MSC_LOG_RX_DISCARDED_MESSAGE( - MSC_RRC_ENB, - MSC_RRC_UE, - Srb_info->Rx_buffer.Payload, - dec_rval.consumed, - MSC_AS_TIME_FMT" RRCConnectionRequest UE %x size %u (s-TMSI mmec %u m_TMSI %u random UE id (0x%" PRIx64 ")", - MSC_AS_TIME_ARGS(ctxt_pP), - ue_context_p->ue_context.rnti, - dec_rval.consumed, - s_TMSI.mmec, - s_TMSI.m_TMSI, - ue_context_p->ue_context.random_ue_identity); - - } else { - MSC_LOG_RX_DISCARDED_MESSAGE( - MSC_RRC_ENB, - MSC_RRC_UE, - Srb_info->Rx_buffer.Payload, - dec_rval.consumed, - MSC_AS_TIME_FMT" RRCConnectionRequest UE %x size %u random UE id (0x%" PRIx64 ")", - MSC_AS_TIME_ARGS(ctxt_pP), - ue_context_p->ue_context.rnti, - dec_rval.consumed, - ue_context_p->ue_context.random_ue_identity); - } - - ue_context_p->ue_context.establishment_cause = - rrcConnectionRequest->establishmentCause; + ue_context_p->ue_context.establishment_cause = rrcConnectionRequest->establishmentCause; LOG_I(RRC, PROTOCOL_RRC_CTXT_UE_FMT" Accept new connection from UE random UE identity (0x%" PRIx64 ") MME code %u TMSI %u cause %u\n", PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP), ue_context_p->ue_context.random_ue_identity, diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf index 4722040b07..375a4a90ca 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf @@ -16,7 +16,7 @@ eNBs = tracking_area_code = "1"; mobile_country_code = "208"; - mobile_network_code = "92"; + mobile_network_code = "95"; ////////// Physical parameters: @@ -130,18 +130,18 @@ eNBs = }; ////////// MME parameters: - mme_ip_address = ( {ipv4 = "192.168.12.26"; + mme_ip_address = ( {ipv4 = "192.168.12.17"; ipv6="192:168:30::17"; active="yes"; preference="ipv4";}); NETWORK_INTERFACES : { - ENB_INTERFACE_NAME_FOR_S1_MME = "eth1"; - ENB_IPV4_ADDRESS_FOR_S1_MME = "192.168.12.82/24"; + ENB_INTERFACE_NAME_FOR_S1_MME = "eth0"; + ENB_IPV4_ADDRESS_FOR_S1_MME = "192.168.12.213/24"; - ENB_INTERFACE_NAME_FOR_S1U = "eth1"; - ENB_IPV4_ADDRESS_FOR_S1U = "192.168.12.82/24"; + ENB_INTERFACE_NAME_FOR_S1U = "eth0"; + ENB_IPV4_ADDRESS_FOR_S1U = "192.168.12.213/24"; ENB_PORT_FOR_S1U = 2152; # Spec 2152 }; From dcba8c19ae6e4ab5507a168658bbe12561d30ed8 Mon Sep 17 00:00:00 2001 From: gauthier Date: Thu, 14 Jan 2016 18:26:27 +0100 Subject: [PATCH 124/263] Sent of S_TMSI OK --- openair2/RRC/LITE/rrc_eNB_S1AP.c | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/openair2/RRC/LITE/rrc_eNB_S1AP.c b/openair2/RRC/LITE/rrc_eNB_S1AP.c index 5c41658862..f07a071b07 100644 --- a/openair2/RRC/LITE/rrc_eNB_S1AP.c +++ b/openair2/RRC/LITE/rrc_eNB_S1AP.c @@ -43,6 +43,7 @@ # include "RRC/LITE/defs.h" # include "rrc_eNB_UE_context.h" # include "rrc_eNB_S1AP.h" +# include "enb_config.h" # if defined(ENABLE_ITTI) # include "asn1_conversions.h" @@ -661,15 +662,16 @@ rrc_eNB_send_S1AP_NAS_FIRST_REQ( S1AP_NAS_FIRST_REQ (message_p).ue_identity.s_tmsi.mme_code = s_TMSI->mme_code; S1AP_NAS_FIRST_REQ (message_p).ue_identity.s_tmsi.m_tmsi = s_TMSI->m_tmsi; LOG_I(S1AP, "[eNB %d] Build S1AP_NAS_FIRST_REQ with s_TMSI: MME code %u M-TMSI %u ue %x\n", - ctxt_pP->module_id, - S1AP_NAS_FIRST_REQ (message_p).ue_identity.s_tmsi.mme_code, - S1AP_NAS_FIRST_REQ (message_p).ue_identity.s_tmsi.m_tmsi, - ue_context_pP->ue_context.rnti); + ctxt_pP->module_id, + S1AP_NAS_FIRST_REQ (message_p).ue_identity.s_tmsi.mme_code, + S1AP_NAS_FIRST_REQ (message_p).ue_identity.s_tmsi.m_tmsi, + ue_context_pP->ue_context.rnti); } if (rrcConnectionSetupComplete->registeredMME != NULL) { /* Fill GUMMEI */ struct RegisteredMME *r_mme = rrcConnectionSetupComplete->registeredMME; + int selected_plmn_identity = rrcConnectionSetupComplete->selectedPLMN_Identity; S1AP_NAS_FIRST_REQ (message_p).ue_identity.presenceMask |= UE_IDENTITIES_gummei; @@ -678,9 +680,9 @@ rrc_eNB_send_S1AP_NAS_FIRST_REQ( /* Use first indicated PLMN MCC if it is defined */ S1AP_NAS_FIRST_REQ (message_p).ue_identity.gummei.mcc = *r_mme->plmn_Identity->mcc->list.array[0]; LOG_I(S1AP, "[eNB %d] Build S1AP_NAS_FIRST_REQ adding in s_TMSI: GUMMEI MCC %u ue %x\n", - ctxt_pP->module_id, - S1AP_NAS_FIRST_REQ (message_p).ue_identity.gummei.mcc, - ue_context_pP->ue_context.rnti); + ctxt_pP->module_id, + S1AP_NAS_FIRST_REQ (message_p).ue_identity.gummei.mcc, + ue_context_pP->ue_context.rnti); } if (r_mme->plmn_Identity->mnc.list.count > 0) { @@ -691,6 +693,13 @@ rrc_eNB_send_S1AP_NAS_FIRST_REQ( S1AP_NAS_FIRST_REQ (message_p).ue_identity.gummei.mnc, ue_context_pP->ue_context.rnti); } + } else { + const Enb_properties_array_t *enb_properties_p = NULL; + enb_properties_p = enb_config_get(); + + // actually the eNB configuration contains only one PLMN (can be up to 6) + S1AP_NAS_FIRST_REQ (message_p).ue_identity.gummei.mcc = enb_properties_p->properties[ctxt_pP->module_id]->mcc; + S1AP_NAS_FIRST_REQ (message_p).ue_identity.gummei.mnc = enb_properties_p->properties[ctxt_pP->module_id]->mnc; } S1AP_NAS_FIRST_REQ (message_p).ue_identity.gummei.mme_code = BIT_STRING_to_uint8 (&r_mme->mmec); From ac89db6daf5df95969328052468e586543e5153f Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Thu, 14 Jan 2016 18:31:48 +0100 Subject: [PATCH 125/263] removal of cache to insert exmimo driver --- cmake_targets/tools/stop_exmimo2 | 1 + 1 file changed, 1 insertion(+) diff --git a/cmake_targets/tools/stop_exmimo2 b/cmake_targets/tools/stop_exmimo2 index 6931229f7a..63810e0bf8 100755 --- a/cmake_targets/tools/stop_exmimo2 +++ b/cmake_targets/tools/stop_exmimo2 @@ -6,6 +6,7 @@ if [ "$OPENAIR_DIR" == "" ]; then echo "Is the OPENAIR_DIR path set correctly? Exiting now" exit fi +sudo -E bash -c 'echo 3 > /proc/sys/vm/drop_caches' #load the module sudo -E $OPENAIR_DIR/cmake_targets/tools/init_exmimo2 From 853bad6c47c8dabf37124f3041b6addd65c62fee Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Thu, 14 Jan 2016 18:32:54 +0100 Subject: [PATCH 126/263] added option to kill zombie ssh sessions created by autotest --- cmake_targets/autotests/run_exec_lte-softmodem_tests.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/cmake_targets/autotests/run_exec_lte-softmodem_tests.py b/cmake_targets/autotests/run_exec_lte-softmodem_tests.py index 6cce8028c9..30c3717385 100755 --- a/cmake_targets/autotests/run_exec_lte-softmodem_tests.py +++ b/cmake_targets/autotests/run_exec_lte-softmodem_tests.py @@ -1099,7 +1099,6 @@ except KeyError: sys.exit(1) - # get the oai object host = os.uname()[1] #oai = openair('localdomain','calisson') @@ -1208,6 +1207,11 @@ if localshell == 0: result = oai_list[index].send_expect_false('sudo -S -v','may not run sudo',True) print "Sudo permissions..." + result + print "Killing zombie ssh sessions from earlier sessions..." + cmd='ps aux |grep \"/usr/bin/ssh -q -l guptar\"|tr -s \" \" :|cut -f 2 -d :|xargs kill -9 \'' + result=oai_list[index].send_recv(cmd, True) + print result + print '\nCleaning Older running programs : ' + CleanUpOldProgs cleanOldPrograms(oai_list[index], CleanUpOldProgs, CleanUpAluLteBox, ExmimoRfStop) From a2b83444586aa0c9ece9596546863a531a51ceed Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Thu, 14 Jan 2016 18:46:37 +0100 Subject: [PATCH 127/263] kill zombie ssh processes --- .../autotests/run_exec_lte-softmodem_tests.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/cmake_targets/autotests/run_exec_lte-softmodem_tests.py b/cmake_targets/autotests/run_exec_lte-softmodem_tests.py index 30c3717385..87a90b3ab8 100755 --- a/cmake_targets/autotests/run_exec_lte-softmodem_tests.py +++ b/cmake_targets/autotests/run_exec_lte-softmodem_tests.py @@ -1098,6 +1098,11 @@ except KeyError: print "Please set the environment variable OPENAIR_TARGETS in the .bashrc" sys.exit(1) +print "Killing zombie ssh sessions from earlier sessions..." +cmd='ps aux |grep \"/usr/bin/ssh -q -l guptar\"|tr -s \" \" :|cut -f 2 -d :|xargs kill -9 \'' +os.system(cmd) + + # get the oai object host = os.uname()[1] @@ -1207,11 +1212,6 @@ if localshell == 0: result = oai_list[index].send_expect_false('sudo -S -v','may not run sudo',True) print "Sudo permissions..." + result - print "Killing zombie ssh sessions from earlier sessions..." - cmd='ps aux |grep \"/usr/bin/ssh -q -l guptar\"|tr -s \" \" :|cut -f 2 -d :|xargs kill -9 \'' - result=oai_list[index].send_recv(cmd, True) - print result - print '\nCleaning Older running programs : ' + CleanUpOldProgs cleanOldPrograms(oai_list[index], CleanUpOldProgs, CleanUpAluLteBox, ExmimoRfStop) From 79a25fe98917762d4d11232a82952cfadca3eb86 Mon Sep 17 00:00:00 2001 From: gauthier Date: Thu, 14 Jan 2016 18:49:55 +0100 Subject: [PATCH 128/263] MNC length in GUMMEI --- openair2/RRC/LITE/rrc_eNB_S1AP.c | 1 + 1 file changed, 1 insertion(+) diff --git a/openair2/RRC/LITE/rrc_eNB_S1AP.c b/openair2/RRC/LITE/rrc_eNB_S1AP.c index f07a071b07..3a22180a36 100644 --- a/openair2/RRC/LITE/rrc_eNB_S1AP.c +++ b/openair2/RRC/LITE/rrc_eNB_S1AP.c @@ -700,6 +700,7 @@ rrc_eNB_send_S1AP_NAS_FIRST_REQ( // actually the eNB configuration contains only one PLMN (can be up to 6) S1AP_NAS_FIRST_REQ (message_p).ue_identity.gummei.mcc = enb_properties_p->properties[ctxt_pP->module_id]->mcc; S1AP_NAS_FIRST_REQ (message_p).ue_identity.gummei.mnc = enb_properties_p->properties[ctxt_pP->module_id]->mnc; + S1AP_NAS_FIRST_REQ (message_p).ue_identity.gummei.mnc_len = enb_properties_p->properties[ctxt_pP->module_id]->mnc_digit_length; } S1AP_NAS_FIRST_REQ (message_p).ue_identity.gummei.mme_code = BIT_STRING_to_uint8 (&r_mme->mmec); From c2d8dd96aaa846d0999624dd8d1755f49e687577 Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Thu, 14 Jan 2016 18:57:13 +0100 Subject: [PATCH 129/263] update for killing zombie processes --- cmake_targets/autotests/run_exec_lte-softmodem_tests.py | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/cmake_targets/autotests/run_exec_lte-softmodem_tests.py b/cmake_targets/autotests/run_exec_lte-softmodem_tests.py index 87a90b3ab8..cd0441ef7b 100755 --- a/cmake_targets/autotests/run_exec_lte-softmodem_tests.py +++ b/cmake_targets/autotests/run_exec_lte-softmodem_tests.py @@ -1099,7 +1099,7 @@ except KeyError: sys.exit(1) print "Killing zombie ssh sessions from earlier sessions..." -cmd='ps aux |grep \"/usr/bin/ssh -q -l guptar\"|tr -s \" \" :|cut -f 2 -d :|xargs kill -9 \'' +cmd='ps aux |grep \"/usr/bin/ssh -q -l guptar\"|tr -s \" \" :|cut -f 2 -d :|xargs kill -9 ' os.system(cmd) @@ -1114,6 +1114,12 @@ if user=='': user = getpass.getuser() if pw=='': pw = getpass.getpass() + +print "Killing zombie ssh sessions from earlier sessions..." +cmd='ps aux |grep \"/usr/bin/ssh -q -l guptar\"|tr -s \" \" :|cut -f 2 -d :|xargs kill -9 ' +cmd = cmd + '; ps aux |grep \"/usr/bin/ssh -q -l ' + user + '\"|tr -s \" \" :|cut -f 2 -d :|xargs kill -9 ' +os.system(cmd) + print "host = " + host print "user = " + user xmlInputFile=os.environ.get('OPENAIR_DIR')+"/cmake_targets/autotests/test_case_list.xml" From 5b1cb169397402d68c59dd56c4c64576d607af92 Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Fri, 15 Jan 2016 18:47:22 +0100 Subject: [PATCH 130/263] addition of argument parser --- cmake_targets/autotests/run_exec_lte-softmodem_tests.py | 1 + 1 file changed, 1 insertion(+) diff --git a/cmake_targets/autotests/run_exec_lte-softmodem_tests.py b/cmake_targets/autotests/run_exec_lte-softmodem_tests.py index cd0441ef7b..ad408341b5 100755 --- a/cmake_targets/autotests/run_exec_lte-softmodem_tests.py +++ b/cmake_targets/autotests/run_exec_lte-softmodem_tests.py @@ -63,6 +63,7 @@ sys.path.append('/opt/ssh') import ssh from ssh import SSHSession +import argparse # \brief write a string to a file # \param filename name of file From 970b4b395a659dc8cf03c025e93dfd57070a5bb9 Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Fri, 15 Jan 2016 18:55:23 +0100 Subject: [PATCH 131/263] added option to stop the script by detault --- .../autotests/run_exec_lte-softmodem_tests.py | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/cmake_targets/autotests/run_exec_lte-softmodem_tests.py b/cmake_targets/autotests/run_exec_lte-softmodem_tests.py index ad408341b5..001b0475bc 100755 --- a/cmake_targets/autotests/run_exec_lte-softmodem_tests.py +++ b/cmake_targets/autotests/run_exec_lte-softmodem_tests.py @@ -1017,6 +1017,7 @@ locallogdir = openairdir_local + '/cmake_targets/autotests/log' MachineList = '' MachineListGeneric='' flag_remove_logdir=False +flag_start_testcase=False i=1 print "Number of arguments argc = " + str(len(sys.argv)) @@ -1024,7 +1025,9 @@ print "Number of arguments argc = " + str(len(sys.argv)) while i < len (sys.argv): arg=sys.argv[i] if arg == '-r': - flag_remove_logdir=True + flag_remove_logdir=True + elif arg == '-s' : + flag_start_testcase=True elif arg == '-g' : testcasegroup = sys.argv[i+1].replace("\"","") i = i +1 @@ -1065,6 +1068,7 @@ while i < len (sys.argv): MachineListGeneric = MachineListGeneric.replace("\'","") i = i +1 elif arg == '-h' : + print "-s: This flag *MUST* be set to start the test cases" print "-r: Remove the log directory in autotests" print "-g: Run test cases in a group" print "-c: Run cleanup scripts on remote machines and exit" @@ -1103,7 +1107,9 @@ print "Killing zombie ssh sessions from earlier sessions..." cmd='ps aux |grep \"/usr/bin/ssh -q -l guptar\"|tr -s \" \" :|cut -f 2 -d :|xargs kill -9 ' os.system(cmd) - +if flag_start_testcase == False: + print "You need to start the testcase by passing option -s. Use -h to see all options. Aborting now..." + sys.exit(1) # get the oai object host = os.uname()[1] From 19dc2cd118ae2da4a8f1bfffa779ace24b9660a3 Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Fri, 15 Jan 2016 19:01:18 +0100 Subject: [PATCH 132/263] test input args --- cmake_targets/autotests/run_exec_lte-softmodem_tests.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/cmake_targets/autotests/run_exec_lte-softmodem_tests.py b/cmake_targets/autotests/run_exec_lte-softmodem_tests.py index 001b0475bc..2662d7a451 100755 --- a/cmake_targets/autotests/run_exec_lte-softmodem_tests.py +++ b/cmake_targets/autotests/run_exec_lte-softmodem_tests.py @@ -1018,10 +1018,13 @@ MachineList = '' MachineListGeneric='' flag_remove_logdir=False flag_start_testcase=False -i=1 + print "Number of arguments argc = " + str(len(sys.argv)) +for index in range(1,len(sys.argv) ): + print "argv_" + str(index) + " : " + sys.argv[index] +i=1 while i < len (sys.argv): arg=sys.argv[i] if arg == '-r': From b19b32393446dd9891182dc05d458abf046f3ada Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Fri, 15 Jan 2016 19:15:32 +0100 Subject: [PATCH 133/263] addd extra args to build script --- .gitlab-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 8efa62d23c..27e9d59704 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -21,7 +21,7 @@ job1: - echo $NFS_TEST_RESULTS_DIR - echo $EXTERNAL_SHARE_RESULTS_DIR - mkdir -p $OPENAIR_DIR/cmake_targets/autotests/log - - python $OPENAIR_DIR/cmake_targets/autotests/run_exec_lte-softmodem_tests.py -c -5GRepoHeadVersion $git_head -n $NFS_SHARE_DIR -u $OAI_USER -p $OAI_PASS >& $OPENAIR_DIR/cmake_targets/autotests/python_autotest_cleanup.log + - python $OPENAIR_DIR/cmake_targets/autotests/run_exec_lte-softmodem_tests.py -c -5GRepoHeadVersion $git_head -n $NFS_SHARE_DIR -u $OAI_USER -p $OAI_PASS $OAI_EXTRA_ARGS>& $OPENAIR_DIR/cmake_targets/autotests/python_autotest_cleanup.log - python $OPENAIR_DIR/cmake_targets/autotests/run_exec_lte-softmodem_tests.py -r -5GRepoHeadVersion $git_head -n $NFS_SHARE_DIR -u $OAI_USER -p $OAI_PASS `echo $OAI_EXTRA_ARGS` -g $OAI_TEST_CASE_GROUP >& $OPENAIR_DIR/cmake_targets/autotests/python_autotest.log - mv $OPENAIR_DIR/cmake_targets/autotests/python_autotest.log $OPENAIR_DIR/cmake_targets/autotests/log/python_autotest.log - mv $OPENAIR_DIR/cmake_targets/autotests/python_autotest_cleanup.log $OPENAIR_DIR/cmake_targets/autotests/log/python_autotest_cleanup.log From 2bde7350c7a5bd24d98431fd8a251c335cbcda1f Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Fri, 15 Jan 2016 19:20:27 +0100 Subject: [PATCH 134/263] addd extra args to build script --- .gitlab-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 27e9d59704..c73f53c440 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -21,7 +21,7 @@ job1: - echo $NFS_TEST_RESULTS_DIR - echo $EXTERNAL_SHARE_RESULTS_DIR - mkdir -p $OPENAIR_DIR/cmake_targets/autotests/log - - python $OPENAIR_DIR/cmake_targets/autotests/run_exec_lte-softmodem_tests.py -c -5GRepoHeadVersion $git_head -n $NFS_SHARE_DIR -u $OAI_USER -p $OAI_PASS $OAI_EXTRA_ARGS>& $OPENAIR_DIR/cmake_targets/autotests/python_autotest_cleanup.log + - python $OPENAIR_DIR/cmake_targets/autotests/run_exec_lte-softmodem_tests.py -c -5GRepoHeadVersion $git_head -n $NFS_SHARE_DIR -u $OAI_USER -p $OAI_PASS $OAI_EXTRA_ARGS -g "$OAI_TEST_CASE_GROUP">& $OPENAIR_DIR/cmake_targets/autotests/python_autotest_cleanup.log - python $OPENAIR_DIR/cmake_targets/autotests/run_exec_lte-softmodem_tests.py -r -5GRepoHeadVersion $git_head -n $NFS_SHARE_DIR -u $OAI_USER -p $OAI_PASS `echo $OAI_EXTRA_ARGS` -g $OAI_TEST_CASE_GROUP >& $OPENAIR_DIR/cmake_targets/autotests/python_autotest.log - mv $OPENAIR_DIR/cmake_targets/autotests/python_autotest.log $OPENAIR_DIR/cmake_targets/autotests/log/python_autotest.log - mv $OPENAIR_DIR/cmake_targets/autotests/python_autotest_cleanup.log $OPENAIR_DIR/cmake_targets/autotests/log/python_autotest_cleanup.log From 7cc2a5cd77b41183bc55921c4fa381f760a04b62 Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Fri, 15 Jan 2016 19:24:13 +0100 Subject: [PATCH 135/263] bugfix for passing multiple args --- .gitlab-ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index c73f53c440..b9b796efb9 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -22,7 +22,7 @@ job1: - echo $EXTERNAL_SHARE_RESULTS_DIR - mkdir -p $OPENAIR_DIR/cmake_targets/autotests/log - python $OPENAIR_DIR/cmake_targets/autotests/run_exec_lte-softmodem_tests.py -c -5GRepoHeadVersion $git_head -n $NFS_SHARE_DIR -u $OAI_USER -p $OAI_PASS $OAI_EXTRA_ARGS -g "$OAI_TEST_CASE_GROUP">& $OPENAIR_DIR/cmake_targets/autotests/python_autotest_cleanup.log - - python $OPENAIR_DIR/cmake_targets/autotests/run_exec_lte-softmodem_tests.py -r -5GRepoHeadVersion $git_head -n $NFS_SHARE_DIR -u $OAI_USER -p $OAI_PASS `echo $OAI_EXTRA_ARGS` -g $OAI_TEST_CASE_GROUP >& $OPENAIR_DIR/cmake_targets/autotests/python_autotest.log + - python $OPENAIR_DIR/cmake_targets/autotests/run_exec_lte-softmodem_tests.py -r -5GRepoHeadVersion $git_head -n $NFS_SHARE_DIR -u $OAI_USER -p $OAI_PASS `echo $OAI_EXTRA_ARGS` -g "$OAI_TEST_CASE_GROUP" >& $OPENAIR_DIR/cmake_targets/autotests/python_autotest.log - mv $OPENAIR_DIR/cmake_targets/autotests/python_autotest.log $OPENAIR_DIR/cmake_targets/autotests/log/python_autotest.log - mv $OPENAIR_DIR/cmake_targets/autotests/python_autotest_cleanup.log $OPENAIR_DIR/cmake_targets/autotests/log/python_autotest_cleanup.log - sshpass -p "$OAI_PASS" rsync -az -e "ssh -o StrictHostKeyChecking=no " --rsync-path="mkdir -p $NFS_TEST_RESULTS_DIR && rsync" $OPENAIR_DIR/cmake_targets/autotests/log $OAI_USER@localhost:$NFS_TEST_RESULTS_DIR From 6bab0de2da1f99c7a0eba45c71b77b89c7ee4ff6 Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Sun, 17 Jan 2016 18:59:04 +0100 Subject: [PATCH 136/263] override number of runs for lte-softmodem test case --- .../autotests/run_exec_lte-softmodem_tests.py | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/cmake_targets/autotests/run_exec_lte-softmodem_tests.py b/cmake_targets/autotests/run_exec_lte-softmodem_tests.py index 2662d7a451..e287a31353 100755 --- a/cmake_targets/autotests/run_exec_lte-softmodem_tests.py +++ b/cmake_targets/autotests/run_exec_lte-softmodem_tests.py @@ -1018,11 +1018,11 @@ MachineList = '' MachineListGeneric='' flag_remove_logdir=False flag_start_testcase=False - +nruns_lte_softmodem='' print "Number of arguments argc = " + str(len(sys.argv)) -for index in range(1,len(sys.argv) ): - print "argv_" + str(index) + " : " + sys.argv[index] +#for index in range(1,len(sys.argv) ): +# print "argv_" + str(index) + " : " + sys.argv[index] i=1 while i < len (sys.argv): @@ -1060,6 +1060,9 @@ while i < len (sys.argv): elif arg == '-n': NFSResultsShare = sys.argv[i+1] i = i +1 + elif arg == '--nrun_lte_softmodem': + nruns_lte_softmodem = sys.argv[i+1] + i = i +1 elif arg == '-MachineList': MachineList = sys.argv[i+1] MachineList = MachineList.replace("\"","") @@ -1080,6 +1083,7 @@ while i < len (sys.argv): print "-u: use the user name passed as argument" print "-p: use the password passed as an argument" print "-n: Set the NFS share passed as an argument" + print "--nrun_lte_softmodem: Set the number of runs for lte-softmodem test case class" print "-MachineList : overrides the MachineList parameter in test_case_list.xml" print "-MachineListGeneric : overrides the MachineListGeneric parameter in test_case_list.xml" sys.exit() @@ -1172,7 +1176,8 @@ if MachineListGeneric == '': MachineListGeneric = xmlRoot.findtext('MachineListGeneric',default='') TestCaseExclusionList = xmlRoot.findtext('TestCaseExclusionList',default='') ExmimoRfStop = xmlRoot.findtext('ExmimoRfStop',default='') -nruns_lte_softmodem = xmlRoot.findtext('nruns_lte-softmodem',default='') +if nruns_lte_softmodem == '': + nruns_lte_softmodem = xmlRoot.findtext('nruns_lte-softmodem',default='') print "MachineList = " + MachineList print "GitOpenair-cnRepo = " + GitOpenaircnRepo From 260d32944f07dc6af20e627d9f096ed19bbeeb50 Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Sun, 17 Jan 2016 21:20:46 +0100 Subject: [PATCH 137/263] added wireshark tracing --- .../autotests/run_exec_lte-softmodem_tests.py | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/cmake_targets/autotests/run_exec_lte-softmodem_tests.py b/cmake_targets/autotests/run_exec_lte-softmodem_tests.py index e287a31353..d13529bcbc 100755 --- a/cmake_targets/autotests/run_exec_lte-softmodem_tests.py +++ b/cmake_targets/autotests/run_exec_lte-softmodem_tests.py @@ -680,6 +680,8 @@ def handle_testcaseclass_softmodem (testcase, oldprogramList, logdirOAI5GRepo , logfile_task_eNB_out = logdir_eNB + '/eNB_task_out' + '_' + str(run) + '_.log' logfile_task_eNB = logdir_local_testcase + '/eNB_task' + '_' + str(run) + '_.log' logfile_local_traffic_eNB_out = logdir_local_testcase + '/eNB_traffic' + '_' + str(run) + '_.log' + logfile_tshark_eNB = logdir_eNB + '/eNB_tshark' + '_' + str(run) + '_.log' + logfile_pcap_eNB = logdir_eNB + '/eNB_tshark' + '_' + str(run) + '_.pcap' task_eNB_compile = ' ( uname -a ; date \n' task_eNB_compile = task_eNB_compile + 'cd ' + logdirOAI5GRepo + ' ; source oaienv ; source cmake_targets/tools/build_helper \n' @@ -704,6 +706,9 @@ def handle_testcaseclass_softmodem (testcase, oldprogramList, logdirOAI5GRepo , task_eNB = task_eNB + ' (date; ' + eNB_traffic_exec + ' ' + eNB_traffic_exec_args + ' ) > ' + logfile_traffic_eNB + ' 2>&1 & \n ' task_eNB = task_eNB + 'array_exec_pid+=($!) \n' task_eNB = task_eNB + 'echo eNB_traffic_exec PID = $! \n' + task_eNB = task_eNB + ' (date; sudo -E tshark -i any -s 65535 -a duration:' + str(timeout_cmd-10)+ ' -w ' + logfile_pcap_eNB+ ' ) > ' + logfile_tshark_eNB + ' 2>&1 & \n ' + task_eNB = task_eNB + 'array_exec_pid+=($!) \n' + task_eNB = task_eNB + 'echo eNB_tshark_exec PID = $! \n' #terminate the eNB test case after timeout_cmd seconds task_eNB = task_eNB + finalize_deploy_script (timeout_cmd, eNB_terminate_missing_procs) + ' \n' #task_eNB = task_eNB + 'sleep ' + str(timeout_cmd) + ' \n' @@ -861,6 +866,19 @@ def handle_testcaseclass_softmodem (testcase, oldprogramList, logdirOAI5GRepo , thread_UE.start() thread_UE.join() + #Now we change the permissions of the logfiles to avoid some of them being with root permissions + cmd = 'sudo -E chown -R ' + user + ' ' + logdir_eNB + res= oai_eNB.send_recv(cmd) + print "Changing permissions of logdir <" + logdir_eNB + "> in eNB machine..." + res + + cmd = 'sudo -E chown -R ' + user + ' ' + logdir_UE + res= oai_UE.send_recv(cmd) + print "Changing permissions of logdir <" + logdir_UE + "> in UE machine..." + res + + cmd = 'sudo -E chown -R ' + user + ' ' + logdir_EPC + res= oai_EPC.send_recv(cmd) + print "Changing permissions of logdir <" + logdir_EPC + "> in EPC machine..." + res + print "Copying files from EPCMachine : " + EPCMachine + "logdir_EPC = " + logdir_EPC #ssh = SSHSession(EPCMachine , username=user, key_file=None, password=password) From 125cb4d43fd75a2db8e7869923f43cfe95d780dc Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Mon, 18 Jan 2016 11:33:50 +0100 Subject: [PATCH 138/263] addition of wireshark trace --- cmake_targets/autotests/test_case_list.xml | 52 +++++++++++----------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/cmake_targets/autotests/test_case_list.xml b/cmake_targets/autotests/test_case_list.xml index 2a247bf5e2..f9399b591a 100644 --- a/cmake_targets/autotests/test_case_list.xml +++ b/cmake_targets/autotests/test_case_list.xml @@ -886,7 +886,7 @@ $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem - -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf + -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf -W @@ -970,7 +970,7 @@ $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem - -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf + -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf -W @@ -1053,7 +1053,7 @@ $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem - -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf + -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf -W @@ -1136,7 +1136,7 @@ $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem - -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf + -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf -W @@ -1218,7 +1218,7 @@ $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem - -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf + -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf -W @@ -1301,7 +1301,7 @@ $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem - -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf + -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf -W @@ -1385,7 +1385,7 @@ $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem - -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf + -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf -W @@ -1469,7 +1469,7 @@ $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem - -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf + -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf -W @@ -1552,7 +1552,7 @@ $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem - -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf + -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf -W @@ -1635,7 +1635,7 @@ $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem - -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf + -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf -W @@ -1718,7 +1718,7 @@ $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem - -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf + -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf -W @@ -1801,7 +1801,7 @@ $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem - -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf + -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf -W @@ -1880,7 +1880,7 @@ sudo -E -S /usr/local/bin/niusrprio_pcie start ; dmesg|tail $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem - -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpx310.epc.remote.conf + -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpx310.epc.remote.conf -W @@ -1959,7 +1959,7 @@ sudo -E -S /usr/local/bin/niusrprio_pcie start ; dmesg|tail $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem - -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpx310.conf + -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpx310.conf -W @@ -2037,7 +2037,7 @@ sudo -E -S /usr/local/bin/niusrprio_pcie start ; dmesg|tail $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem - -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.100PRB.usrpx310.conf + -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.100PRB.usrpx310.conf -W @@ -2115,7 +2115,7 @@ sudo -E -S /usr/local/bin/niusrprio_pcie start ; dmesg|tail $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem - -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpx310.epc.remote.conf + -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpx310.epc.remote.conf -W @@ -2192,7 +2192,7 @@ sudo -E -S /usr/local/bin/niusrprio_pcie start ; dmesg|tail sudo -E -S /usr/local/bin/niusrprio_pcie start ; dmesg|tail $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem - -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpx310.conf + -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpx310.conf -W @@ -2269,7 +2269,7 @@ sudo -E -S /usr/local/bin/niusrprio_pcie start ; dmesg|tail $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem - -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.100PRB.usrpx310.conf + -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.100PRB.usrpx310.conf -W @@ -2349,7 +2349,7 @@ sudo -E -S $OPENAIR_DIR/cmake_targets/tools/init_exmimo2; dmesg|tail $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem - -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.conf + -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.conf -W @@ -2428,7 +2428,7 @@ sudo -E -S $OPENAIR_DIR/cmake_targets/tools/init_exmimo2 ; dmesg|tail $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem - -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.conf + -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.conf -W @@ -2506,7 +2506,7 @@ sudo -E -S $OPENAIR_DIR/cmake_targets/tools/init_exmimo2 ; dmesg|tail $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem - -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.conf + -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.conf -W @@ -2584,7 +2584,7 @@ sudo -E -S $OPENAIR_DIR/cmake_targets/tools/init_exmimo2 ; dmesg|tail $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem - -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.conf + -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.conf -W @@ -2661,7 +2661,7 @@ sudo -E -S $OPENAIR_DIR/cmake_targets/tools/init_exmimo2 ; dmesg|tail $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem - -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.conf + -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.conf -W @@ -2738,7 +2738,7 @@ sudo -E -S $OPENAIR_DIR/cmake_targets/tools/init_exmimo2 ; dmesg|tail $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem - -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.conf + -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.conf -W @@ -2810,7 +2810,7 @@ $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem - -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf + -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf -W iperf -s @@ -2889,7 +2889,7 @@ $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem - -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf + -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf -W From 7f62e8ab7cecb9fd020965493298fcd47e5fa143 Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Mon, 18 Jan 2016 12:13:59 +0100 Subject: [PATCH 139/263] fix for tshark permissions --- cmake_targets/autotests/run_exec_lte-softmodem_tests.py | 3 ++- cmake_targets/autotests/test_case_list.xml | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/cmake_targets/autotests/run_exec_lte-softmodem_tests.py b/cmake_targets/autotests/run_exec_lte-softmodem_tests.py index d13529bcbc..58b0a1dff3 100755 --- a/cmake_targets/autotests/run_exec_lte-softmodem_tests.py +++ b/cmake_targets/autotests/run_exec_lte-softmodem_tests.py @@ -682,6 +682,7 @@ def handle_testcaseclass_softmodem (testcase, oldprogramList, logdirOAI5GRepo , logfile_local_traffic_eNB_out = logdir_local_testcase + '/eNB_traffic' + '_' + str(run) + '_.log' logfile_tshark_eNB = logdir_eNB + '/eNB_tshark' + '_' + str(run) + '_.log' logfile_pcap_eNB = logdir_eNB + '/eNB_tshark' + '_' + str(run) + '_.pcap' + logfile_pcap_tmp_eNB = '/tmp/' + '/eNB_tshark' + '_' + str(run) + '_.pcap' task_eNB_compile = ' ( uname -a ; date \n' task_eNB_compile = task_eNB_compile + 'cd ' + logdirOAI5GRepo + ' ; source oaienv ; source cmake_targets/tools/build_helper \n' @@ -706,7 +707,7 @@ def handle_testcaseclass_softmodem (testcase, oldprogramList, logdirOAI5GRepo , task_eNB = task_eNB + ' (date; ' + eNB_traffic_exec + ' ' + eNB_traffic_exec_args + ' ) > ' + logfile_traffic_eNB + ' 2>&1 & \n ' task_eNB = task_eNB + 'array_exec_pid+=($!) \n' task_eNB = task_eNB + 'echo eNB_traffic_exec PID = $! \n' - task_eNB = task_eNB + ' (date; sudo -E tshark -i any -s 65535 -a duration:' + str(timeout_cmd-10)+ ' -w ' + logfile_pcap_eNB+ ' ) > ' + logfile_tshark_eNB + ' 2>&1 & \n ' + task_eNB = task_eNB + ' (date; sudo rm -f ' + logfile_pcap_tmp_eNB + ' ; sudo -E tshark -i any -s 65535 -a duration:' + str(timeout_cmd-10)+ ' -w ' + logfile_pcap_tmp_eNB+ ' ; sudo -E chown ' + user + ' ' + logfile_pcap_tmp_eNB ' ; mv ' + logfile_pcap_tmp_eNB + ' ' + logfile_pcap_eNB + ' ) > ' + logfile_tshark_eNB + ' 2>&1 & \n ' task_eNB = task_eNB + 'array_exec_pid+=($!) \n' task_eNB = task_eNB + 'echo eNB_tshark_exec PID = $! \n' #terminate the eNB test case after timeout_cmd seconds diff --git a/cmake_targets/autotests/test_case_list.xml b/cmake_targets/autotests/test_case_list.xml index f9399b591a..0bb0e1fa9f 100644 --- a/cmake_targets/autotests/test_case_list.xml +++ b/cmake_targets/autotests/test_case_list.xml @@ -6,7 +6,7 @@ https://gitlab.eurecom.fr/oai/openair-cn.git develop feature-17-test_framework - oaisim* oaisim_nos1* lte-softmodem* lte-softmodem-nos1* mme_gw* run_epc* run_hss* hss hss_sim configure_cots_bandrich_ue* wvdial* iperf iperf_script ping + oaisim* oaisim_nos1* lte-softmodem* lte-softmodem-nos1* mme_gw* run_epc* run_hss* hss hss_sim configure_cots_bandrich_ue* wvdial* iperf iperf_script ping tshark sudo -S -E /opt/ltebox/tools/stop_ltebox $OPENAIR_DIR/cmake_targets/build_oai -w EXMIMO -c; sudo -S -E $OPENAIR_DIR/cmake_targets/tools/stop_exmimo2; dmesg|tail 36000 From 9023198a2b6912653cd9b969fcaa15f169af304b Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Mon, 18 Jan 2016 12:24:49 +0100 Subject: [PATCH 140/263] fixed bug for python script --- cmake_targets/autotests/run_exec_lte-softmodem_tests.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake_targets/autotests/run_exec_lte-softmodem_tests.py b/cmake_targets/autotests/run_exec_lte-softmodem_tests.py index 58b0a1dff3..2e1c72c7dc 100755 --- a/cmake_targets/autotests/run_exec_lte-softmodem_tests.py +++ b/cmake_targets/autotests/run_exec_lte-softmodem_tests.py @@ -707,7 +707,7 @@ def handle_testcaseclass_softmodem (testcase, oldprogramList, logdirOAI5GRepo , task_eNB = task_eNB + ' (date; ' + eNB_traffic_exec + ' ' + eNB_traffic_exec_args + ' ) > ' + logfile_traffic_eNB + ' 2>&1 & \n ' task_eNB = task_eNB + 'array_exec_pid+=($!) \n' task_eNB = task_eNB + 'echo eNB_traffic_exec PID = $! \n' - task_eNB = task_eNB + ' (date; sudo rm -f ' + logfile_pcap_tmp_eNB + ' ; sudo -E tshark -i any -s 65535 -a duration:' + str(timeout_cmd-10)+ ' -w ' + logfile_pcap_tmp_eNB+ ' ; sudo -E chown ' + user + ' ' + logfile_pcap_tmp_eNB ' ; mv ' + logfile_pcap_tmp_eNB + ' ' + logfile_pcap_eNB + ' ) > ' + logfile_tshark_eNB + ' 2>&1 & \n ' + task_eNB = task_eNB + ' (date; sudo rm -f ' + logfile_pcap_tmp_eNB + ' ; sudo -E tshark -i any -s 65535 -a duration:' + str(timeout_cmd-10)+ ' -w ' + logfile_pcap_tmp_eNB+ ' ; sudo -E chown ' + user + ' ' + logfile_pcap_tmp_eNB + ' ; mv ' + logfile_pcap_tmp_eNB + ' ' + logfile_pcap_eNB + ' ) > ' + logfile_tshark_eNB + ' 2>&1 & \n ' task_eNB = task_eNB + 'array_exec_pid+=($!) \n' task_eNB = task_eNB + 'echo eNB_tshark_exec PID = $! \n' #terminate the eNB test case after timeout_cmd seconds From f3df7705ed51bc1b8097870b9444343889f9453b Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Mon, 18 Jan 2016 17:21:25 +0100 Subject: [PATCH 141/263] fixed a bug for tshark logging --- cmake_targets/autotests/run_exec_lte-softmodem_tests.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/cmake_targets/autotests/run_exec_lte-softmodem_tests.py b/cmake_targets/autotests/run_exec_lte-softmodem_tests.py index 2e1c72c7dc..57e08b09c8 100755 --- a/cmake_targets/autotests/run_exec_lte-softmodem_tests.py +++ b/cmake_targets/autotests/run_exec_lte-softmodem_tests.py @@ -704,10 +704,11 @@ def handle_testcaseclass_softmodem (testcase, oldprogramList, logdirOAI5GRepo , task_eNB = task_eNB + 'array_exec_pid+=($!) \n' task_eNB = task_eNB + 'echo eNB_main_exec PID = $! \n' if eNB_traffic_exec != "": - task_eNB = task_eNB + ' (date; ' + eNB_traffic_exec + ' ' + eNB_traffic_exec_args + ' ) > ' + logfile_traffic_eNB + ' 2>&1 & \n ' + task_eNB = task_eNB + ' (date; ' + eNB_traffic_exec + ' ' + eNB_traffic_exec_args + ' ) > ' + logfile_traffic_eNB + ' 2>&1 & \n' task_eNB = task_eNB + 'array_exec_pid+=($!) \n' task_eNB = task_eNB + 'echo eNB_traffic_exec PID = $! \n' - task_eNB = task_eNB + ' (date; sudo rm -f ' + logfile_pcap_tmp_eNB + ' ; sudo -E tshark -i any -s 65535 -a duration:' + str(timeout_cmd-10)+ ' -w ' + logfile_pcap_tmp_eNB+ ' ; sudo -E chown ' + user + ' ' + logfile_pcap_tmp_eNB + ' ; mv ' + logfile_pcap_tmp_eNB + ' ' + logfile_pcap_eNB + ' ) > ' + logfile_tshark_eNB + ' 2>&1 & \n ' + + task_eNB = task_eNB + ' (date; sudo rm -f ' + logfile_pcap_tmp_eNB + ' ; sudo -E tshark -i any -s 65535 -a duration:' + str(timeout_cmd-10)+ ' -w ' + logfile_pcap_tmp_eNB+ ' ; sudo -E chown ' + user + ' ' + logfile_pcap_tmp_eNB + ' ; mv ' + logfile_pcap_tmp_eNB + ' ' + logfile_pcap_eNB + ' ) > ' + logfile_tshark_eNB + ' 2>&1 & \n ' task_eNB = task_eNB + 'array_exec_pid+=($!) \n' task_eNB = task_eNB + 'echo eNB_tshark_exec PID = $! \n' #terminate the eNB test case after timeout_cmd seconds From e3899ced43928f784d2e6a766c84750a79931ec5 Mon Sep 17 00:00:00 2001 From: "aikaterini.trilyraki" Date: Tue, 19 Jan 2016 10:28:29 +0100 Subject: [PATCH 142/263] * fix the MME connection timer when MME is not yet availablewqwq --- targets/RT/USER/lte-softmodem.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/targets/RT/USER/lte-softmodem.c b/targets/RT/USER/lte-softmodem.c index bbb21b4ee9..e67bcb6b07 100644 --- a/targets/RT/USER/lte-softmodem.c +++ b/targets/RT/USER/lte-softmodem.c @@ -1674,6 +1674,10 @@ static void* eNB_thread( void* arg ) tx_pos = openair0_cfg[0].tx_scheduling_advance; #endif +#if defined(ENABLE_ITTI) + wait_system_ready ("Waiting for eNB application to be ready %s\r", &start_eNB); +#endif + while (!oai_exit) { start_meas( &softmodem_stats_mt ); @@ -3188,15 +3192,15 @@ int main( int argc, char **argv ) pthread_cond_init(&sync_cond,NULL); pthread_mutex_init(&sync_mutex, NULL); -#if defined(ENABLE_ITTI) + /* this is moved to the eNB main thread */ +//#if defined(ENABLE_ITTI) // Wait for eNB application initialization to be complete (eNB registration to MME) - if (UE_flag==0) { - printf("Waiting for eNB application to be ready\n"); - wait_system_ready ("Waiting for eNB application to be ready %s\r", &start_eNB); - } - -#endif + // if (UE_flag==0) { + // printf("Waiting for eNB application to be ready\n"); + //wait_system_ready ("Waiting for eNB application to be ready %s\r", &start_eNB); + // } + //#endif // this starts the DMA transfers From 93c04cb77511a138604fa8c7a0acf5c23f8cad7b Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Tue, 19 Jan 2016 17:20:19 +0100 Subject: [PATCH 143/263] compress the pcap file due to its size --- cmake_targets/autotests/run_exec_lte-softmodem_tests.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/cmake_targets/autotests/run_exec_lte-softmodem_tests.py b/cmake_targets/autotests/run_exec_lte-softmodem_tests.py index 57e08b09c8..d9b2321d37 100755 --- a/cmake_targets/autotests/run_exec_lte-softmodem_tests.py +++ b/cmake_targets/autotests/run_exec_lte-softmodem_tests.py @@ -682,6 +682,7 @@ def handle_testcaseclass_softmodem (testcase, oldprogramList, logdirOAI5GRepo , logfile_local_traffic_eNB_out = logdir_local_testcase + '/eNB_traffic' + '_' + str(run) + '_.log' logfile_tshark_eNB = logdir_eNB + '/eNB_tshark' + '_' + str(run) + '_.log' logfile_pcap_eNB = logdir_eNB + '/eNB_tshark' + '_' + str(run) + '_.pcap' + logfile_pcap_zip_eNB = logdir_eNB + '/eNB_tshark' + '_' + str(run) + '_.pcap.zip' logfile_pcap_tmp_eNB = '/tmp/' + '/eNB_tshark' + '_' + str(run) + '_.pcap' task_eNB_compile = ' ( uname -a ; date \n' @@ -708,7 +709,7 @@ def handle_testcaseclass_softmodem (testcase, oldprogramList, logdirOAI5GRepo , task_eNB = task_eNB + 'array_exec_pid+=($!) \n' task_eNB = task_eNB + 'echo eNB_traffic_exec PID = $! \n' - task_eNB = task_eNB + ' (date; sudo rm -f ' + logfile_pcap_tmp_eNB + ' ; sudo -E tshark -i any -s 65535 -a duration:' + str(timeout_cmd-10)+ ' -w ' + logfile_pcap_tmp_eNB+ ' ; sudo -E chown ' + user + ' ' + logfile_pcap_tmp_eNB + ' ; mv ' + logfile_pcap_tmp_eNB + ' ' + logfile_pcap_eNB + ' ) > ' + logfile_tshark_eNB + ' 2>&1 & \n ' + task_eNB = task_eNB + ' (date; sudo rm -f ' + logfile_pcap_tmp_eNB + ' ; sudo -E tshark -i any -s 65535 -a duration:' + str(timeout_cmd-10)+ ' -w ' + logfile_pcap_tmp_eNB+ ' ; sudo -E chown ' + user + ' ' + logfile_pcap_tmp_eNB + ' ; zip -9 ' + logfile_pcap_zip_eNB + ' ' + logfile_pcap_tmp_eNB + ' ) > ' + logfile_tshark_eNB + ' 2>&1 & \n ' task_eNB = task_eNB + 'array_exec_pid+=($!) \n' task_eNB = task_eNB + 'echo eNB_tshark_exec PID = $! \n' #terminate the eNB test case after timeout_cmd seconds From d927bf6b1f066658e00efbccfdb1433eb30b2cf2 Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Tue, 19 Jan 2016 17:24:08 +0100 Subject: [PATCH 144/263] modified to not kill processes in test cases if some threads crash --- cmake_targets/autotests/test_case_list.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cmake_targets/autotests/test_case_list.xml b/cmake_targets/autotests/test_case_list.xml index 0bb0e1fa9f..d5fbb5178d 100644 --- a/cmake_targets/autotests/test_case_list.xml +++ b/cmake_targets/autotests/test_case_list.xml @@ -891,7 +891,7 @@ - True + False /tmp targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf tracking_area_code \"4\" @@ -907,7 +907,7 @@ - True + False sudo -S -E $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue /tmp @@ -931,7 +931,7 @@ throughput_test min=1.0Mbits/sec max=1.0Mbits/sec average=1.0Mbits/sec duration=300.0s - True + False USRPb210.ALU_EPC.Bandrich.5MHz.FDD.Band_7.UL.1TX.1RX 10 From 5ebff86675ce8ac40776f1ed96d88f65ba7d6c67 Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Tue, 19 Jan 2016 19:35:21 +0100 Subject: [PATCH 145/263] added support for specifying gateway + help print --- .../tools/configure_cots_bandrich_ue.py | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py b/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py index e22f86e67c..99c4a04eaa 100755 --- a/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py +++ b/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py @@ -126,8 +126,8 @@ def start_ue () : break ip = IPRoute() idx = ip.link_lookup(ifname=iface)[0] - os.system ('route add 192.172.0.1 ppp0') - os.system ('ping 192.172.0.1') + os.system ('route add ' + gw + ' ppp0') + os.system ('ping ' + gw) break except Exception, e: error = ' Interface ' + iface + 'does not exist...' @@ -188,7 +188,10 @@ def find_usb_path(idVendor, idProduct): return tmpdir return '' -for arg in sys.argv[1:]: +i=1 +gw='192.172.0.1' +while i < len(sys.argv): + arg=sys.argv[i] if arg == '--start-ue' : find_open_port() print 'Using Serial port : ' + serial_port @@ -199,8 +202,17 @@ for arg in sys.argv[1:]: stop_ue() elif arg == '--reset-ue' : reset_ue() + elif arg == '-gw' : + gw = sys.argv[i+1] + i=i+1 + elif arg == '-h' : + print "--reset-ue: Reset the UE on USB Bus. Similar to unplugging and plugging the UE" + print "--stop-ue: Stop the UE. Send DETACH command" + print "--start-ue: Start the UE. Send ATTACH command" + print "-gw: Specify the default gw as sometimes the gateway/route arguments are not set properly via wvdial" else : print " Script called with wrong arguments, arg = " + arg sys.exit() + i = i +1 From d25786dbd9fc02740c490f105f75880353a1fe4a Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Tue, 19 Jan 2016 19:36:23 +0100 Subject: [PATCH 146/263] added support for IPV4_LIST option in epc.conf.in EPC config file --- cmake_targets/autotests/tools/search_repl.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/cmake_targets/autotests/tools/search_repl.py b/cmake_targets/autotests/tools/search_repl.py index 0a91945c77..d0d6c4638f 100755 --- a/cmake_targets/autotests/tools/search_repl.py +++ b/cmake_targets/autotests/tools/search_repl.py @@ -19,9 +19,11 @@ file.close() if keyword == 'mme_ip_address': - #string = (re.sub(r"mme_ip_address\s*=\s*\([^\$]+)\)\s*;\s*", r"<% tex \1 %>", t, re.M) replacement_text = keyword + ' = ( { ' + replacement_text + ' } ) ; ' string = re.sub(r"mme_ip_address\s*=\s*\(([^\$]+?)\)\s*;", replacement_text, string, re.M) +elif keyword == 'IPV4_LIST': + replacement_text = keyword + ' = ( ' + replacement_text + ' ) ; ' + string = re.sub(r"IPV4_LIST\s*=\s*\(([^\$]+?)\)\s*;", replacement_text, string, re.M) else : replacement_text = keyword + ' = ' + replacement_text + ' ; ' string = re.sub(r"%s\s*=\s*([^\$]+?)\s*;" % keyword , replacement_text, string, re.M) From 9a8f67db25cd273bad661933ac3e710361fa18eb Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Tue, 19 Jan 2016 19:37:50 +0100 Subject: [PATCH 147/263] zip file without directory path --- cmake_targets/autotests/run_exec_lte-softmodem_tests.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake_targets/autotests/run_exec_lte-softmodem_tests.py b/cmake_targets/autotests/run_exec_lte-softmodem_tests.py index d9b2321d37..3ad782fff8 100755 --- a/cmake_targets/autotests/run_exec_lte-softmodem_tests.py +++ b/cmake_targets/autotests/run_exec_lte-softmodem_tests.py @@ -709,7 +709,7 @@ def handle_testcaseclass_softmodem (testcase, oldprogramList, logdirOAI5GRepo , task_eNB = task_eNB + 'array_exec_pid+=($!) \n' task_eNB = task_eNB + 'echo eNB_traffic_exec PID = $! \n' - task_eNB = task_eNB + ' (date; sudo rm -f ' + logfile_pcap_tmp_eNB + ' ; sudo -E tshark -i any -s 65535 -a duration:' + str(timeout_cmd-10)+ ' -w ' + logfile_pcap_tmp_eNB+ ' ; sudo -E chown ' + user + ' ' + logfile_pcap_tmp_eNB + ' ; zip -9 ' + logfile_pcap_zip_eNB + ' ' + logfile_pcap_tmp_eNB + ' ) > ' + logfile_tshark_eNB + ' 2>&1 & \n ' + task_eNB = task_eNB + ' (date; sudo rm -f ' + logfile_pcap_tmp_eNB + ' ; sudo -E tshark -i any -s 65535 -a duration:' + str(timeout_cmd-10)+ ' -w ' + logfile_pcap_tmp_eNB+ ' ; sudo -E chown ' + user + ' ' + logfile_pcap_tmp_eNB + ' ; zip -j -9 ' + logfile_pcap_zip_eNB + ' ' + logfile_pcap_tmp_eNB + ' ) > ' + logfile_tshark_eNB + ' 2>&1 & \n ' task_eNB = task_eNB + 'array_exec_pid+=($!) \n' task_eNB = task_eNB + 'echo eNB_tshark_exec PID = $! \n' #terminate the eNB test case after timeout_cmd seconds From 4843f4de21f70e260c7cd47e519b889c9da488f4 Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Tue, 19 Jan 2016 19:45:38 +0100 Subject: [PATCH 148/263] added testcase 015600 for OAI local EPC --- cmake_targets/autotests/test_case_list.xml | 165 +++++++++++---------- 1 file changed, 84 insertions(+), 81 deletions(-) diff --git a/cmake_targets/autotests/test_case_list.xml b/cmake_targets/autotests/test_case_list.xml index d5fbb5178d..8114105796 100644 --- a/cmake_targets/autotests/test_case_list.xml +++ b/cmake_targets/autotests/test_case_list.xml @@ -5,7 +5,7 @@ https://gitlab.eurecom.fr/oai/openairinterface5g.git https://gitlab.eurecom.fr/oai/openair-cn.git develop - feature-17-test_framework + develop oaisim* oaisim_nos1* lte-softmodem* lte-softmodem-nos1* mme_gw* run_epc* run_hss* hss hss_sim configure_cots_bandrich_ue* wvdial* iperf iperf_script ping tshark sudo -S -E /opt/ltebox/tools/stop_ltebox $OPENAIR_DIR/cmake_targets/build_oai -w EXMIMO -c; sudo -S -E $OPENAIR_DIR/cmake_targets/tools/stop_exmimo2; dmesg|tail @@ -1852,6 +1852,89 @@ + + lte-softmodem + + calisson + stevens + nano + 60 + /tmp + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf tracking_area_code \"1\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf mobile_country_code \"208\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf mobile_network_code \"92\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf N_RB_DL 25 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf mme_ip_address "ipv4=\"192.170.0.1\";ipv6=\"192:168:30::17\";active=\"yes\";preference=\"ipv4\";" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf downlink_frequency 2660000000L + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf uplink_frequency_offset -120000000 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf tx_gain 90 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf rx_gain 125 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf frame_type \"FDD\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf nb_antennas_rx 1 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf nb_antennas_tx 1 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf ENB_INTERFACE_NAME_FOR_S1_MME \"eth0:3\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf ENB_IPV4_ADDRESS_FOR_S1_MME \"192.170.0.2/24\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf ENB_INTERFACE_NAME_FOR_S1U \"eth0:4\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf ENB_IPV4_ADDRESS_FOR_S1U \"192.170.0.2/24\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf ENB_PORT_FOR_S1U 2152 + $OPENAIR_DIR/cmake_targets/build_oai + --eNB -w USRP -c + sudo -E ifconfig eth0:3 192.170.0.2 up ; sudo -E ifconfig eth0:4 192.170.1.2 up + + $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem + -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf -W + iperf -s + + + + False + + /tmp + + + + + + $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue + + $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 1 ppp0 -u -c 192.172.0.1 -b 10Mbits/s -t 330 -B 192.172.0.2 + + + + False + sudo -S -E $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue + + /tmp + BUILD/EPC/epc.conf.in MCC \"208\" + BUILD/EPC/epc.conf.in MNC \"92\" + BUILD/EPC/epc.conf.in TAC \"1\" + BUILD/EPC/epc.conf.in MME_INTERFACE_NAME_FOR_S1_MME \"eth0:1\" + BUILD/EPC/epc.conf.in MME_IPV4_ADDRESS_FOR_S1_MME \"192.170.0.1/24\" + BUILD/EPC/epc.conf.in SGW_INTERFACE_NAME_FOR_S1U_S12_S4_UP \"eth0:2\"; + BUILD/EPC/epc.conf.in SGW_IPV4_ADDRESS_FOR_S1U_S12_S4_UP \"192.170.1.1/24\"; + BUILD/EPC/epc.conf.in PGW_INTERFACE_NAME_FOR_SGI \"eth1\" + BUILD/EPC/epc.conf.in PGW_IPV4_ADDRESS_FOR_SGI \"192.168.12.82/24\" + SCRIPTS/build_epc + -c -l + SCRIPTS/build_hss + -c -l + + sudo -E ifconfig eth1 add 192.172.0.1 + + /SCRIPTS/run_epc + -i -r + /SCRIPTS/run_hss + + $OPENAIRCN_DIR/TEST/autotests/tools/iperf_script 5 lo -s -i 1 -u -f m -B 192.172.0.1 + + throughput_test min=1.0Mbits/sec max=1.0Mbits/sec average=1.0Mbits/sec duration=300.0s + + False + USRPb210.OAI_EPC.Bandrich.5MHz.FDD.Band_7.UL.1TX.1RX + 10 + + + lte-softmodem @@ -2787,86 +2870,6 @@ 10 - - - - lte-softmodem - - calisson - stevens - nano - 60 - /tmp - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf tracking_area_code \"1\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf mobile_country_code \"208\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf mobile_network_code \"92\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf tracking_area_code \"1\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf mobile_country_code \"208\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf mobile_network_code \"92\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf N_RB_DL 50 - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf mme_ip_address "ipv4=\"192.168.12.62\";ipv6=\"192:168:30::17\";active=\"yes\";preference=\"ipv4\";" - $OPENAIR_DIR/cmake_targets/build_oai - --eNB -w USRP -c - - - $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem - -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf -W - iperf -s - - - - True - - /tmp - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf tracking_area_code \"1\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf mobile_country_code \"208\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf mobile_network_code \"92\" - $OPENAIR_DIR/cmake_targets/build_oai - --eNB -w USRP -c - - - $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue - - ping 192.172.0.1 - - - - True - - /tmp - BUILD/EPC/epc.local.enb.conf.in MCC \"208\" - BUILD/EPC/epc.local.enb.conf.in MNC \"92\" - BUILD/EPC/epc.local.enb.conf.in TAC \"1\" - BUILD/EPC/epc.local.enb.conf.in PGW_INTERFACE_NAME_FOR_SGI \"eth1\" - BUILD/EPC/epc.local.enb.conf.in PGW_IPV4_ADDRESS_FOR_SGI \"192.168.12.82/24\" - BUILD/EPC/epc.conf.in MCC \"208\" - BUILD/EPC/epc.conf.in MNC \"92\" - BUILD/EPC/epc.conf.in TAC \"1\" - BUILD/EPC/epc.conf.in PGW_INTERFACE_NAME_FOR_SGI \"eth1\" - BUILD/EPC/epc.conf.in PGW_IPV4_ADDRESS_FOR_SGI \"192.168.12.82/24\" - BUILD/EPC/epc.conf.in MME_IPV4_ADDRESS_FOR_S1_MME \"192.168.12.62/24\" - BUILD/EPC/epc.conf.in SGW_IPV4_ADDRESS_FOR_S1U_S12_S4_UP \"192.168.12.62/24\" - BUILD/EPC/epc.conf.in PGW_IPV4_ADDRESS_FOR_SGI \"192.168.12.62/24\" - SCRIPTS/build_epc - -c -l - SCRIPTS/build_hss - -c - - - - /SCRIPTS/run_epc -g - - /SCRIPTS/run_hss -g - - iperf -s - - - - True - 10 - - - lte-softmodem From 5309c9c491960d017ab3abbaafc7b6cfe135b67a Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Wed, 20 Jan 2016 10:19:54 +0100 Subject: [PATCH 149/263] fixed minor bug for logging --- cmake_targets/autotests/run_exec_lte-softmodem_tests.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake_targets/autotests/run_exec_lte-softmodem_tests.py b/cmake_targets/autotests/run_exec_lte-softmodem_tests.py index 3ad782fff8..625c88d3b5 100755 --- a/cmake_targets/autotests/run_exec_lte-softmodem_tests.py +++ b/cmake_targets/autotests/run_exec_lte-softmodem_tests.py @@ -1433,7 +1433,7 @@ cmd = ' rm -fr ' + NFSTestsResultsDir + ' ; mkdir -p ' + NFSTestsResultsDir res = oai_localhost.send_recv(cmd) print "Deleting NFSTestResults Dir..." + res -print "Copying files from GilabCI Runner Machine : " + host + "locallogdir = " + locallogdir + ", NFSTestsResultsDir = " + NFSTestsResultsDir +print "Copying files from GilabCI Runner Machine : " + host + " .locallogdir = " + locallogdir + ", NFSTestsResultsDir = " + NFSTestsResultsDir SSHSessionWrapper('localhost', user, None, pw , NFSTestsResultsDir , locallogdir, "put_all") sys.exit() From b6d53d0a23b5883939e53217449d7227e56e9f6b Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Wed, 20 Jan 2016 10:20:42 +0100 Subject: [PATCH 150/263] enable 015600 test case --- cmake_targets/autotests/test_case_list.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake_targets/autotests/test_case_list.xml b/cmake_targets/autotests/test_case_list.xml index 8114105796..412feeaf49 100644 --- a/cmake_targets/autotests/test_case_list.xml +++ b/cmake_targets/autotests/test_case_list.xml @@ -10,7 +10,7 @@ sudo -S -E /opt/ltebox/tools/stop_ltebox $OPENAIR_DIR/cmake_targets/build_oai -w EXMIMO -c; sudo -S -E $OPENAIR_DIR/cmake_targets/tools/stop_exmimo2; dmesg|tail 36000 - 0104+ 015502 015505 015506 015507 015508 015508 015509 015510 015511 015600 015700 016102 016105 + 0104+ 015502 015505 015506 015507 015508 015508 015509 015510 015511 015700 016102 016105 3 mozart calisson stevens nano amerique From 4af63f381b77729458b2048cd7581087ae4b9f96 Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Wed, 20 Jan 2016 10:38:55 +0100 Subject: [PATCH 151/263] updates for 0156* test case --- cmake_targets/autotests/test_case_list.xml | 173 ++++++++++++++++++++- 1 file changed, 168 insertions(+), 5 deletions(-) diff --git a/cmake_targets/autotests/test_case_list.xml b/cmake_targets/autotests/test_case_list.xml index 412feeaf49..b31b153a4d 100644 --- a/cmake_targets/autotests/test_case_list.xml +++ b/cmake_targets/autotests/test_case_list.xml @@ -10,7 +10,7 @@ sudo -S -E /opt/ltebox/tools/stop_ltebox $OPENAIR_DIR/cmake_targets/build_oai -w EXMIMO -c; sudo -S -E $OPENAIR_DIR/cmake_targets/tools/stop_exmimo2; dmesg|tail 36000 - 0104+ 015502 015505 015506 015507 015508 015508 015509 015510 015511 015700 016102 016105 + 0104+ 015502 015505 015506 015507 015508 015508 015509 015510 015511 015602 015700 016102 016105 3 mozart calisson stevens nano amerique @@ -1857,8 +1857,8 @@ calisson stevens - nano - 60 + calisson + 390 /tmp targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf tracking_area_code \"1\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf mobile_country_code \"208\" @@ -1883,7 +1883,7 @@ $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf -W - iperf -s + @@ -1902,7 +1902,7 @@ False - sudo -S -E $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue + $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; sudo -S -E $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue /tmp BUILD/EPC/epc.conf.in MCC \"208\" @@ -1934,6 +1934,169 @@ 10 + + lte-softmodem + + calisson + stevens + calisson + 390 + /tmp + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf tracking_area_code \"1\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf mobile_country_code \"208\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf mobile_network_code \"92\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf N_RB_DL 50 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf mme_ip_address "ipv4=\"192.170.0.1\";ipv6=\"192:168:30::17\";active=\"yes\";preference=\"ipv4\";" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf downlink_frequency 2660000000L + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf uplink_frequency_offset -120000000 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf tx_gain 90 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf rx_gain 125 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf frame_type \"FDD\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf nb_antennas_rx 1 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf nb_antennas_tx 1 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf ENB_INTERFACE_NAME_FOR_S1_MME \"eth0:3\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf ENB_IPV4_ADDRESS_FOR_S1_MME \"192.170.0.2/24\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf ENB_INTERFACE_NAME_FOR_S1U \"eth0:4\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf ENB_IPV4_ADDRESS_FOR_S1U \"192.170.0.2/24\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf ENB_PORT_FOR_S1U 2152 + $OPENAIR_DIR/cmake_targets/build_oai + --eNB -w USRP -c + sudo -E ifconfig eth0:3 192.170.0.2 up ; sudo -E ifconfig eth0:4 192.170.1.2 up + + $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem + -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf -W + + + + + False + + /tmp + + + + + + $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue + + $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 1 ppp0 -u -c 192.172.0.1 -b 10Mbits/s -t 330 -B 192.172.0.2 + + + + False + $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; sudo -S -E $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue + + /tmp + BUILD/EPC/epc.conf.in MCC \"208\" + BUILD/EPC/epc.conf.in MNC \"92\" + BUILD/EPC/epc.conf.in TAC \"1\" + BUILD/EPC/epc.conf.in MME_INTERFACE_NAME_FOR_S1_MME \"eth0:1\" + BUILD/EPC/epc.conf.in MME_IPV4_ADDRESS_FOR_S1_MME \"192.170.0.1/24\" + BUILD/EPC/epc.conf.in SGW_INTERFACE_NAME_FOR_S1U_S12_S4_UP \"eth0:2\"; + BUILD/EPC/epc.conf.in SGW_IPV4_ADDRESS_FOR_S1U_S12_S4_UP \"192.170.1.1/24\"; + BUILD/EPC/epc.conf.in PGW_INTERFACE_NAME_FOR_SGI \"eth1\" + BUILD/EPC/epc.conf.in PGW_IPV4_ADDRESS_FOR_SGI \"192.168.12.82/24\" + SCRIPTS/build_epc + -c -l + SCRIPTS/build_hss + -c -l + + sudo -E ifconfig eth1 add 192.172.0.1 + + /SCRIPTS/run_epc + -i -r + /SCRIPTS/run_hss + + $OPENAIRCN_DIR/TEST/autotests/tools/iperf_script 5 lo -s -i 1 -u -f m -B 192.172.0.1 + + throughput_test min=1.0Mbits/sec max=1.0Mbits/sec average=1.0Mbits/sec duration=300.0s + + False + USRPb210.OAI_EPC.Bandrich.10MHz.FDD.Band_7.UL.1TX.1RX + 10 + + + + lte-softmodem + + calisson + stevens + calisson + 390 + /tmp + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf tracking_area_code \"1\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf mobile_country_code \"208\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf mobile_network_code \"92\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf N_RB_DL 100 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf mme_ip_address "ipv4=\"192.170.0.1\";ipv6=\"192:168:30::17\";active=\"yes\";preference=\"ipv4\";" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf downlink_frequency 2660000000L + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf uplink_frequency_offset -120000000 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf tx_gain 90 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf rx_gain 125 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf frame_type \"FDD\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf nb_antennas_rx 1 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf nb_antennas_tx 1 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf ENB_INTERFACE_NAME_FOR_S1_MME \"eth0:3\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf ENB_IPV4_ADDRESS_FOR_S1_MME \"192.170.0.2/24\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf ENB_INTERFACE_NAME_FOR_S1U \"eth0:4\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf ENB_IPV4_ADDRESS_FOR_S1U \"192.170.0.2/24\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf ENB_PORT_FOR_S1U 2152 + $OPENAIR_DIR/cmake_targets/build_oai + --eNB -w USRP -c + sudo -E ifconfig eth0:3 192.170.0.2 up ; sudo -E ifconfig eth0:4 192.170.1.2 up + + $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem + -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf -W + + + + + False + + /tmp + + + + + + $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue + + $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 1 ppp0 -u -c 192.172.0.1 -b 10Mbits/s -t 330 -B 192.172.0.2 + + + + False + $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; sudo -S -E $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue + + /tmp + BUILD/EPC/epc.conf.in MCC \"208\" + BUILD/EPC/epc.conf.in MNC \"92\" + BUILD/EPC/epc.conf.in TAC \"1\" + BUILD/EPC/epc.conf.in MME_INTERFACE_NAME_FOR_S1_MME \"eth0:1\" + BUILD/EPC/epc.conf.in MME_IPV4_ADDRESS_FOR_S1_MME \"192.170.0.1/24\" + BUILD/EPC/epc.conf.in SGW_INTERFACE_NAME_FOR_S1U_S12_S4_UP \"eth0:2\"; + BUILD/EPC/epc.conf.in SGW_IPV4_ADDRESS_FOR_S1U_S12_S4_UP \"192.170.1.1/24\"; + BUILD/EPC/epc.conf.in PGW_INTERFACE_NAME_FOR_SGI \"eth1\" + BUILD/EPC/epc.conf.in PGW_IPV4_ADDRESS_FOR_SGI \"192.168.12.82/24\" + SCRIPTS/build_epc + -c -l + SCRIPTS/build_hss + -c -l + + sudo -E ifconfig eth1 add 192.172.0.1 + + /SCRIPTS/run_epc + -i -r + /SCRIPTS/run_hss + + $OPENAIRCN_DIR/TEST/autotests/tools/iperf_script 5 lo -s -i 1 -u -f m -B 192.172.0.1 + + throughput_test min=1.0Mbits/sec max=1.0Mbits/sec average=1.0Mbits/sec duration=300.0s + + False + USRPb210.OAI_EPC.Bandrich.20MHz.FDD.Band_7.UL.1TX.1RX + 10 + lte-softmodem From ecae59c52977614e66a222e355a9f00c6d972bf8 Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Wed, 20 Jan 2016 10:48:33 +0100 Subject: [PATCH 152/263] fixed a bug in update_config_file function --- cmake_targets/autotests/run_exec_lte-softmodem_tests.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake_targets/autotests/run_exec_lte-softmodem_tests.py b/cmake_targets/autotests/run_exec_lte-softmodem_tests.py index 625c88d3b5..27a4bcacd8 100755 --- a/cmake_targets/autotests/run_exec_lte-softmodem_tests.py +++ b/cmake_targets/autotests/run_exec_lte-softmodem_tests.py @@ -258,9 +258,9 @@ def finalize_deploy_script (timeout_cmd, terminate_missing_procs='True'): # \param logdirRepo directory of remote repository # \param python_script python script location def update_config_file(oai, config_string, logdirRepo, python_script): + cmd="" if config_string : stringArray = config_string.splitlines() - cmd="" #python_script = '$OPENAIR_DIR/targets/autotests/tools/search_repl.py' for string in stringArray: #split the string based on space now From a1a1e917debe73ecc21b6b3850f720c92b740481 Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Wed, 20 Jan 2016 10:55:09 +0100 Subject: [PATCH 153/263] fixed a bug in update_config_file function --- cmake_targets/autotests/run_exec_lte-softmodem_tests.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cmake_targets/autotests/run_exec_lte-softmodem_tests.py b/cmake_targets/autotests/run_exec_lte-softmodem_tests.py index 27a4bcacd8..d2f5d926d7 100755 --- a/cmake_targets/autotests/run_exec_lte-softmodem_tests.py +++ b/cmake_targets/autotests/run_exec_lte-softmodem_tests.py @@ -267,8 +267,8 @@ def update_config_file(oai, config_string, logdirRepo, python_script): string1=string.split() cmd = cmd + 'python ' + python_script + ' ' + logdirRepo+'/'+string1[0] + ' ' + string1[1] + ' '+ string1[2] + '\n' #cmd = cmd + 'perl -p -i -e \'s/'+ string1[1] + '\\s*=\\s*"\\S*"\\s*/' + string1[1] + ' = "' + string1[2] +'"' + '/g\' ' + logdirRepo + '/' +string1[0] + '\n' - return cmd - #result = oai.send_recv(cmd) + return cmd + #result = oai.send_recv(cmd) # \brief thread safe sshsession wrapper due to occasional connection issues with ssh # \param machine name of machine @@ -323,7 +323,7 @@ def cleanOldPrograms(oai, programList, CleanUpAluLteBox, ExmimoRfStop): #result = oai.send_recv(cmd) #print result result = oai.send_expect_false(cmd, 'Match found', False) - print result + print "Looking for old programs..." + result res=oai.send_recv(CleanUpAluLteBox, True) res = oai.send_recv(ExmimoRfStop, False) From f19c8ca7fbf0a1eb1671e9c57140e5d8aa07938d Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Wed, 20 Jan 2016 13:28:27 +0100 Subject: [PATCH 154/263] added absolute path for openair-cn scripts --- cmake_targets/autotests/test_case_list.xml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/cmake_targets/autotests/test_case_list.xml b/cmake_targets/autotests/test_case_list.xml index b31b153a4d..4ef8ea8fc4 100644 --- a/cmake_targets/autotests/test_case_list.xml +++ b/cmake_targets/autotests/test_case_list.xml @@ -1914,16 +1914,16 @@ BUILD/EPC/epc.conf.in SGW_IPV4_ADDRESS_FOR_S1U_S12_S4_UP \"192.170.1.1/24\"; BUILD/EPC/epc.conf.in PGW_INTERFACE_NAME_FOR_SGI \"eth1\" BUILD/EPC/epc.conf.in PGW_IPV4_ADDRESS_FOR_SGI \"192.168.12.82/24\" - SCRIPTS/build_epc + $OPENAIRCN_DIR/SCRIPTS/build_epc -c -l - SCRIPTS/build_hss + $OPENAIRCN_DIR/SCRIPTS/build_hss -c -l sudo -E ifconfig eth1 add 192.172.0.1 - /SCRIPTS/run_epc + $OPENAIRCN_DIR/SCRIPTS/run_epc -i -r - /SCRIPTS/run_hss + $OPENAIRCN_DIR/SCRIPTS/run_hss $OPENAIRCN_DIR/TEST/autotests/tools/iperf_script 5 lo -s -i 1 -u -f m -B 192.172.0.1 From f0dbe384514a6f0fd4ebefcfe7e27a31869fc9c6 Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Wed, 20 Jan 2016 13:29:16 +0100 Subject: [PATCH 155/263] fix for eNB config script (015600) --- cmake_targets/autotests/test_case_list.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake_targets/autotests/test_case_list.xml b/cmake_targets/autotests/test_case_list.xml index 4ef8ea8fc4..ea6dc8291c 100644 --- a/cmake_targets/autotests/test_case_list.xml +++ b/cmake_targets/autotests/test_case_list.xml @@ -1957,7 +1957,7 @@ targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf ENB_INTERFACE_NAME_FOR_S1_MME \"eth0:3\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf ENB_IPV4_ADDRESS_FOR_S1_MME \"192.170.0.2/24\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf ENB_INTERFACE_NAME_FOR_S1U \"eth0:4\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf ENB_IPV4_ADDRESS_FOR_S1U \"192.170.0.2/24\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf ENB_IPV4_ADDRESS_FOR_S1U \"192.170.1.2/24\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf ENB_PORT_FOR_S1U 2152 $OPENAIR_DIR/cmake_targets/build_oai --eNB -w USRP -c From cf9ea69c1e6a108a1a0d01adf1f7da3cf55b3c94 Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Wed, 20 Jan 2016 13:29:47 +0100 Subject: [PATCH 156/263] fix for eNB config script (015600) --- cmake_targets/autotests/test_case_list.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake_targets/autotests/test_case_list.xml b/cmake_targets/autotests/test_case_list.xml index ea6dc8291c..1e77464fe9 100644 --- a/cmake_targets/autotests/test_case_list.xml +++ b/cmake_targets/autotests/test_case_list.xml @@ -1875,7 +1875,7 @@ targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf ENB_INTERFACE_NAME_FOR_S1_MME \"eth0:3\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf ENB_IPV4_ADDRESS_FOR_S1_MME \"192.170.0.2/24\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf ENB_INTERFACE_NAME_FOR_S1U \"eth0:4\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf ENB_IPV4_ADDRESS_FOR_S1U \"192.170.0.2/24\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf ENB_IPV4_ADDRESS_FOR_S1U \"192.170.1.2/24\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf ENB_PORT_FOR_S1U 2152 $OPENAIR_DIR/cmake_targets/build_oai --eNB -w USRP -c From a485d1745ca70d24daf65a64bfd21abb30516a9f Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Wed, 20 Jan 2016 14:00:28 +0100 Subject: [PATCH 157/263] test IP config for 015600 --- cmake_targets/autotests/test_case_list.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmake_targets/autotests/test_case_list.xml b/cmake_targets/autotests/test_case_list.xml index 1e77464fe9..8e3a39df35 100644 --- a/cmake_targets/autotests/test_case_list.xml +++ b/cmake_targets/autotests/test_case_list.xml @@ -1879,9 +1879,9 @@ targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf ENB_PORT_FOR_S1U 2152 $OPENAIR_DIR/cmake_targets/build_oai --eNB -w USRP -c - sudo -E ifconfig eth0:3 192.170.0.2 up ; sudo -E ifconfig eth0:4 192.170.1.2 up + sudo -E ifconfig eth0:3 192.170.0.2 up ; sudo -E ifconfig eth0:4 192.170.1.2 up; ifconfig - $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem + sudo -E ifconfig eth0:3 192.170.0.2 up ; sudo -E ifconfig eth0:4 192.170.1.2 up; ifconfig ; $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf -W From ed42b8111f951ff7556cb3051ef7b7ec48f872ee Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Wed, 20 Jan 2016 14:13:52 +0100 Subject: [PATCH 158/263] added delay in eNB startup (015600) --- cmake_targets/autotests/test_case_list.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake_targets/autotests/test_case_list.xml b/cmake_targets/autotests/test_case_list.xml index 8e3a39df35..f353083783 100644 --- a/cmake_targets/autotests/test_case_list.xml +++ b/cmake_targets/autotests/test_case_list.xml @@ -1881,7 +1881,7 @@ --eNB -w USRP -c sudo -E ifconfig eth0:3 192.170.0.2 up ; sudo -E ifconfig eth0:4 192.170.1.2 up; ifconfig - sudo -E ifconfig eth0:3 192.170.0.2 up ; sudo -E ifconfig eth0:4 192.170.1.2 up; ifconfig ; $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem + sleep 10; $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf -W From c45fa7e76b06cd6dce36be86774cc9652eecff88 Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Wed, 20 Jan 2016 15:02:10 +0100 Subject: [PATCH 159/263] added delay for OAI HSS startup (015600) --- cmake_targets/autotests/test_case_list.xml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/cmake_targets/autotests/test_case_list.xml b/cmake_targets/autotests/test_case_list.xml index f353083783..75373fd687 100644 --- a/cmake_targets/autotests/test_case_list.xml +++ b/cmake_targets/autotests/test_case_list.xml @@ -1879,9 +1879,9 @@ targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf ENB_PORT_FOR_S1U 2152 $OPENAIR_DIR/cmake_targets/build_oai --eNB -w USRP -c - sudo -E ifconfig eth0:3 192.170.0.2 up ; sudo -E ifconfig eth0:4 192.170.1.2 up; ifconfig + sleep 15; sudo -E ifconfig eth0:3 192.170.0.2 up ; sudo -E ifconfig eth0:4 192.170.1.2 up; ifconfig - sleep 10; $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem + $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf -W @@ -1923,7 +1923,7 @@ $OPENAIRCN_DIR/SCRIPTS/run_epc -i -r - $OPENAIRCN_DIR/SCRIPTS/run_hss + sleep 10; $OPENAIRCN_DIR/SCRIPTS/run_hss $OPENAIRCN_DIR/TEST/autotests/tools/iperf_script 5 lo -s -i 1 -u -f m -B 192.172.0.1 From 4c1f666799ab13f18c2c628db1fcf416696ba890 Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Wed, 20 Jan 2016 16:14:00 +0100 Subject: [PATCH 160/263] addition of 0156* test cases for OAI Core Network --- cmake_targets/autotests/test_case_list.xml | 111 ++++++++++++++++++--- 1 file changed, 97 insertions(+), 14 deletions(-) diff --git a/cmake_targets/autotests/test_case_list.xml b/cmake_targets/autotests/test_case_list.xml index 75373fd687..a310813886 100644 --- a/cmake_targets/autotests/test_case_list.xml +++ b/cmake_targets/autotests/test_case_list.xml @@ -1157,7 +1157,7 @@ True sudo -S -E $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue - throughput_test min=4.0Mbits/sec max=5.0Mbits/sec average=4.0Mbits/sec duration=60.0s + throughput_test min=4.0Mbits/sec max=5.0Mbits/sec average=4.0Mbits/sec duration=300.0s /tmp @@ -1961,9 +1961,9 @@ targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf ENB_PORT_FOR_S1U 2152 $OPENAIR_DIR/cmake_targets/build_oai --eNB -w USRP -c - sudo -E ifconfig eth0:3 192.170.0.2 up ; sudo -E ifconfig eth0:4 192.170.1.2 up + sleep 15; sudo -E ifconfig eth0:3 192.170.0.2 up ; sudo -E ifconfig eth0:4 192.170.1.2 up; ifconfig - $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem + $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf -W @@ -1996,16 +1996,16 @@ BUILD/EPC/epc.conf.in SGW_IPV4_ADDRESS_FOR_S1U_S12_S4_UP \"192.170.1.1/24\"; BUILD/EPC/epc.conf.in PGW_INTERFACE_NAME_FOR_SGI \"eth1\" BUILD/EPC/epc.conf.in PGW_IPV4_ADDRESS_FOR_SGI \"192.168.12.82/24\" - SCRIPTS/build_epc + $OPENAIRCN_DIR/SCRIPTS/build_epc -c -l - SCRIPTS/build_hss + $OPENAIRCN_DIR/SCRIPTS/build_hss -c -l sudo -E ifconfig eth1 add 192.172.0.1 - /SCRIPTS/run_epc + $OPENAIRCN_DIR/SCRIPTS/run_epc -i -r - /SCRIPTS/run_hss + sleep 10; $OPENAIRCN_DIR/SCRIPTS/run_hss $OPENAIRCN_DIR/TEST/autotests/tools/iperf_script 5 lo -s -i 1 -u -f m -B 192.172.0.1 @@ -2039,13 +2039,13 @@ targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf ENB_INTERFACE_NAME_FOR_S1_MME \"eth0:3\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf ENB_IPV4_ADDRESS_FOR_S1_MME \"192.170.0.2/24\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf ENB_INTERFACE_NAME_FOR_S1U \"eth0:4\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf ENB_IPV4_ADDRESS_FOR_S1U \"192.170.0.2/24\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf ENB_IPV4_ADDRESS_FOR_S1U \"192.170.1.2/24\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf ENB_PORT_FOR_S1U 2152 $OPENAIR_DIR/cmake_targets/build_oai --eNB -w USRP -c - sudo -E ifconfig eth0:3 192.170.0.2 up ; sudo -E ifconfig eth0:4 192.170.1.2 up + sleep 15; sudo -E ifconfig eth0:3 192.170.0.2 up ; sudo -E ifconfig eth0:4 192.170.1.2 up; ifconfig - $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem + $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf -W @@ -2078,16 +2078,16 @@ BUILD/EPC/epc.conf.in SGW_IPV4_ADDRESS_FOR_S1U_S12_S4_UP \"192.170.1.1/24\"; BUILD/EPC/epc.conf.in PGW_INTERFACE_NAME_FOR_SGI \"eth1\" BUILD/EPC/epc.conf.in PGW_IPV4_ADDRESS_FOR_SGI \"192.168.12.82/24\" - SCRIPTS/build_epc + $OPENAIRCN_DIR/SCRIPTS/build_epc -c -l - SCRIPTS/build_hss + $OPENAIRCN_DIR/SCRIPTS/build_hss -c -l sudo -E ifconfig eth1 add 192.172.0.1 - /SCRIPTS/run_epc + $OPENAIRCN_DIR/SCRIPTS/run_epc -i -r - /SCRIPTS/run_hss + sleep 10; $OPENAIRCN_DIR/SCRIPTS/run_hss $OPENAIRCN_DIR/TEST/autotests/tools/iperf_script 5 lo -s -i 1 -u -f m -B 192.172.0.1 @@ -2098,6 +2098,89 @@ 10 + + lte-softmodem + + calisson + stevens + calisson + 390 + /tmp + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf tracking_area_code \"1\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf mobile_country_code \"208\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf mobile_network_code \"92\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf N_RB_DL 25 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf mme_ip_address "ipv4=\"192.170.0.1\";ipv6=\"192:168:30::17\";active=\"yes\";preference=\"ipv4\";" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf downlink_frequency 2660000000L + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf uplink_frequency_offset -120000000 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf tx_gain 90 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf rx_gain 125 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf frame_type \"FDD\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf nb_antennas_rx 1 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf nb_antennas_tx 1 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf ENB_INTERFACE_NAME_FOR_S1_MME \"eth0:3\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf ENB_IPV4_ADDRESS_FOR_S1_MME \"192.170.0.2/24\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf ENB_INTERFACE_NAME_FOR_S1U \"eth0:4\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf ENB_IPV4_ADDRESS_FOR_S1U \"192.170.1.2/24\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf ENB_PORT_FOR_S1U 2152 + $OPENAIR_DIR/cmake_targets/build_oai + --eNB -w USRP -c + sleep 15; sudo -E ifconfig eth0:3 192.170.0.2 up ; sudo -E ifconfig eth0:4 192.170.1.2 up; ifconfig + + $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem + -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf -W + + + + + False + + /tmp + + + + + + $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue + + $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 1 ppp0 -s -i 1 -u -f m -B 192.172.0.2 + + throughput_test min=4.0Mbits/sec max=5.0Mbits/sec average=4.0Mbits/sec duration=300.0s + + False + $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; sudo -S -E $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue + + /tmp + BUILD/EPC/epc.conf.in MCC \"208\" + BUILD/EPC/epc.conf.in MNC \"92\" + BUILD/EPC/epc.conf.in TAC \"1\" + BUILD/EPC/epc.conf.in MME_INTERFACE_NAME_FOR_S1_MME \"eth0:1\" + BUILD/EPC/epc.conf.in MME_IPV4_ADDRESS_FOR_S1_MME \"192.170.0.1/24\" + BUILD/EPC/epc.conf.in SGW_INTERFACE_NAME_FOR_S1U_S12_S4_UP \"eth0:2\"; + BUILD/EPC/epc.conf.in SGW_IPV4_ADDRESS_FOR_S1U_S12_S4_UP \"192.170.1.1/24\"; + BUILD/EPC/epc.conf.in PGW_INTERFACE_NAME_FOR_SGI \"eth1\" + BUILD/EPC/epc.conf.in PGW_IPV4_ADDRESS_FOR_SGI \"192.168.12.82/24\" + $OPENAIRCN_DIR/SCRIPTS/build_epc + -c -l + $OPENAIRCN_DIR/SCRIPTS/build_hss + -c -l + + sudo -E ifconfig eth1 add 192.172.0.1 + + $OPENAIRCN_DIR/SCRIPTS/run_epc + -i -r + sleep 10; $OPENAIRCN_DIR/SCRIPTS/run_hss + + $OPENAIRCN_DIR/TEST/autotests/tools/iperf_script 60 lo -u -c 192.172.0.2 -b 10Mbits/s -t 330 -B 192.172.0.1 + + + + False + USRPb210.OAI_EPC.Bandrich.5MHz.FDD.Band_7.DL.1TX.1RX + 10 + + + lte-softmodem From e06212951bdd8b720d9165f86af987087b3c1ec6 Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Wed, 20 Jan 2016 16:37:55 +0100 Subject: [PATCH 161/263] update for 015603 IPV4 ADDRESS for UE --- cmake_targets/autotests/test_case_list.xml | 89 +++++++++++++++++++++- 1 file changed, 86 insertions(+), 3 deletions(-) diff --git a/cmake_targets/autotests/test_case_list.xml b/cmake_targets/autotests/test_case_list.xml index a310813886..fb29471b5f 100644 --- a/cmake_targets/autotests/test_case_list.xml +++ b/cmake_targets/autotests/test_case_list.xml @@ -2145,7 +2145,90 @@ $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 1 ppp0 -s -i 1 -u -f m -B 192.172.0.2 - throughput_test min=4.0Mbits/sec max=5.0Mbits/sec average=4.0Mbits/sec duration=300.0s + throughput_test min=10.0Mbits/sec max=10.5Mbits/sec average=11.0Mbits/sec duration=300.0s + + False + $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; sudo -S -E $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue + + /tmp + BUILD/EPC/epc.conf.in MCC \"208\" + BUILD/EPC/epc.conf.in MNC \"92\" + BUILD/EPC/epc.conf.in TAC \"1\" + BUILD/EPC/epc.conf.in MME_INTERFACE_NAME_FOR_S1_MME \"eth0:1\" + BUILD/EPC/epc.conf.in MME_IPV4_ADDRESS_FOR_S1_MME \"192.170.0.1/24\" + BUILD/EPC/epc.conf.in SGW_INTERFACE_NAME_FOR_S1U_S12_S4_UP \"eth0:2\"; + BUILD/EPC/epc.conf.in SGW_IPV4_ADDRESS_FOR_S1U_S12_S4_UP \"192.170.1.1/24\"; + BUILD/EPC/epc.conf.in PGW_INTERFACE_NAME_FOR_SGI \"eth1\" + BUILD/EPC/epc.conf.in PGW_IPV4_ADDRESS_FOR_SGI \"192.168.12.82/24\" + BUILD/EPC/epc.conf.in IPV4_LIST \"192.172.0.0/24\",\"192.172.1.0/24\" + $OPENAIRCN_DIR/SCRIPTS/build_epc + -c -l + $OPENAIRCN_DIR/SCRIPTS/build_hss + -c -l + + sudo -E ifconfig eth1 add 192.172.0.1 + + $OPENAIRCN_DIR/SCRIPTS/run_epc + -i -r + sleep 10; $OPENAIRCN_DIR/SCRIPTS/run_hss + + $OPENAIRCN_DIR/TEST/autotests/tools/iperf_script 60 lo -u -c 192.172.0.2 -b 10Mbits/s -t 330 -B 192.172.0.1 + + + + False + USRPb210.OAI_EPC.Bandrich.5MHz.FDD.Band_7.DL.1TX.1RX + 10 + + + + lte-softmodem + + calisson + stevens + calisson + 390 + /tmp + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf tracking_area_code \"1\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf mobile_country_code \"208\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf mobile_network_code \"92\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf N_RB_DL 50 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf mme_ip_address "ipv4=\"192.170.0.1\";ipv6=\"192:168:30::17\";active=\"yes\";preference=\"ipv4\";" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf downlink_frequency 2660000000L + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf uplink_frequency_offset -120000000 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf tx_gain 90 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf rx_gain 125 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf frame_type \"FDD\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf nb_antennas_rx 1 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf nb_antennas_tx 1 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf ENB_INTERFACE_NAME_FOR_S1_MME \"eth0:3\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf ENB_IPV4_ADDRESS_FOR_S1_MME \"192.170.0.2/24\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf ENB_INTERFACE_NAME_FOR_S1U \"eth0:4\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf ENB_IPV4_ADDRESS_FOR_S1U \"192.170.1.2/24\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf ENB_PORT_FOR_S1U 2152 + $OPENAIR_DIR/cmake_targets/build_oai + --eNB -w USRP -c + sleep 15; sudo -E ifconfig eth0:3 192.170.0.2 up ; sudo -E ifconfig eth0:4 192.170.1.2 up; ifconfig + + $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem + -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf -W + + + + + False + + /tmp + + + + + + $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue + + $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 1 ppp0 -s -i 1 -u -f m -B 192.172.0.2 + + throughput_test min=20.0Mbits/sec max=22.0Mbits/sec average=22.0Mbits/sec duration=300.0s False $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; sudo -S -E $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue @@ -2171,12 +2254,12 @@ -i -r sleep 10; $OPENAIRCN_DIR/SCRIPTS/run_hss - $OPENAIRCN_DIR/TEST/autotests/tools/iperf_script 60 lo -u -c 192.172.0.2 -b 10Mbits/s -t 330 -B 192.172.0.1 + $OPENAIRCN_DIR/TEST/autotests/tools/iperf_script 60 lo -u -c 192.172.0.2 -b 30Mbits/s -t 330 -B 192.172.0.1 False - USRPb210.OAI_EPC.Bandrich.5MHz.FDD.Band_7.DL.1TX.1RX + USRPb210.OAI_EPC.Bandrich.10MHz.FDD.Band_7.DL.1TX.1RX 10 From 27b0306b18ab6b34d2cf95424f7c4e995c3a0635 Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Wed, 20 Jan 2016 16:45:46 +0100 Subject: [PATCH 162/263] added option for skipping check for GitHead local/remote --- cmake_targets/autotests/run_exec_lte-softmodem_tests.py | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/cmake_targets/autotests/run_exec_lte-softmodem_tests.py b/cmake_targets/autotests/run_exec_lte-softmodem_tests.py index d2f5d926d7..51ad568870 100755 --- a/cmake_targets/autotests/run_exec_lte-softmodem_tests.py +++ b/cmake_targets/autotests/run_exec_lte-softmodem_tests.py @@ -1040,6 +1040,7 @@ MachineListGeneric='' flag_remove_logdir=False flag_start_testcase=False nruns_lte_softmodem='' +flag_skip_git_head_check=False print "Number of arguments argc = " + str(len(sys.argv)) #for index in range(1,len(sys.argv) ): @@ -1094,6 +1095,8 @@ while i < len (sys.argv): MachineListGeneric = MachineListGeneric.replace("\"","") MachineListGeneric = MachineListGeneric.replace("\'","") i = i +1 + elif arg == '--skip-git-head-check': + flag_skip_git_head_check=True elif arg == '-h' : print "-s: This flag *MUST* be set to start the test cases" print "-r: Remove the log directory in autotests" @@ -1107,6 +1110,7 @@ while i < len (sys.argv): print "--nrun_lte_softmodem: Set the number of runs for lte-softmodem test case class" print "-MachineList : overrides the MachineList parameter in test_case_list.xml" print "-MachineListGeneric : overrides the MachineListGeneric parameter in test_case_list.xml" + print "--skip-git-head-check: skip checking of GitHead remote/local branch (only for debugging)" sys.exit() else : print "Unrecongnized Option: <" + arg + ">. Use -h to see valid options" @@ -1310,7 +1314,10 @@ for oai in oai_list: cmd = cmd + 'git_head=${git_head[0]} \n' cmd = cmd + 'echo \"GitOAI5GHeadVersion_remote = $git_head\"' cmd = cmd + 'echo \"GitOAI5GHeadVersion_local = ' + GitOAI5GHeadVersion + '\" \n' - cmd = cmd + 'if [ \"$git_head\" != \"'+ GitOAI5GHeadVersion + '\" ]; then echo \"error: Git openairinterface5g head version does not match\" ; fi \n' + if flag_skip_git_head_check==True: + cmd = cmd + 'print \"skipping GitHead check...\" ' + else: + cmd = cmd + 'if [ \"$git_head\" != \"'+ GitOAI5GHeadVersion + '\" ]; then echo \"error: Git openairinterface5g head version does not match\" ; fi \n' cmd = cmd + 'source oaienv' + '\n' cmd = cmd + 'cd ' + logdirOpenaircnRepo + '\n' cmd = cmd + 'git checkout ' + GitOpenaircnRepoBranch + '\n' From de1ec4655006ba133fac7a81a443c84fb6c2968a Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Wed, 20 Jan 2016 19:35:43 +0100 Subject: [PATCH 163/263] minor bugfix --- cmake_targets/autotests/core.py | 1 + 1 file changed, 1 insertion(+) diff --git a/cmake_targets/autotests/core.py b/cmake_targets/autotests/core.py index 18f89ecfce..33a58a84c9 100644 --- a/cmake_targets/autotests/core.py +++ b/cmake_targets/autotests/core.py @@ -192,6 +192,7 @@ class core: if index == 0 or index == 1 : return self.oai.before else: + print "command = " + command + "rsp1 = " + rsp1 + " rsp2 = " + rsp2 + " index = " + str(index) raise log.err(self.failed(command, rsp1 + ' or ' + rsp2,debug)) From cecaabf533d43f18239aed3258b5b7daa0fc619f Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Thu, 21 Jan 2016 10:36:40 +0100 Subject: [PATCH 164/263] minor fix for logging --- cmake_targets/autotests/core.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake_targets/autotests/core.py b/cmake_targets/autotests/core.py index 33a58a84c9..5b1f39a85b 100644 --- a/cmake_targets/autotests/core.py +++ b/cmake_targets/autotests/core.py @@ -241,7 +241,7 @@ class core: if (rsp.find(expect) == -1): return 'OK' else: - print "command = " + cmd + "expect = " + expect + "rsp = " + rsp + print "command = " + command + "expect = " + expect + "rsp = " + rsp raise log.err(self.failed(command, expect,debug)) From b02de1604eb4bf5f4edbd755cd0bd1ccd9381780 Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Thu, 21 Jan 2016 11:34:27 +0100 Subject: [PATCH 165/263] override timeout command for lte-softmodem test cases --- .../autotests/run_exec_lte-softmodem_tests.py | 41 ++++++++++++++----- 1 file changed, 31 insertions(+), 10 deletions(-) diff --git a/cmake_targets/autotests/run_exec_lte-softmodem_tests.py b/cmake_targets/autotests/run_exec_lte-softmodem_tests.py index 51ad568870..493a4a473c 100755 --- a/cmake_targets/autotests/run_exec_lte-softmodem_tests.py +++ b/cmake_targets/autotests/run_exec_lte-softmodem_tests.py @@ -359,7 +359,7 @@ class oaiThread (threading.Thread): except Exception, e: error='' error = error + ' In class oaiThread, function: ' + sys._getframe().f_code.co_name + ': *** Caught exception: ' + str(e.__class__) + " : " + str( e) - error = error + '\n threadID = ' + str(self.threadID) + '\n threadname = ' + self.threadname + '\n timeout = ' + self.timeout + '\n machine = ' + self.machine + '\n cmd = ' + self.cmd + '\n timeout = ' + str(self.timeout) + '\n username = ' + self.username + '\n' + error = error + '\n threadID = ' + str(self.threadID) + '\n threadname = ' + self.threadname + '\n timeout = ' + str(self.timeout) + '\n machine = ' + self.machine + '\n cmd = ' + self.cmd + '\n timeout = ' + str(self.timeout) + '\n username = ' + self.username + '\n' error = error + traceback.format_exc() print error @@ -548,7 +548,7 @@ def wait_testcaseclass_generic_threads(threadListGeneric, timeout = 1): # \param CleanupAluLteBox string that contains commands to stop ALU Bell Labs LTEBox (specified in test_case_list.xml) # \param ExmimoRfStop command to stop EXMIMO Card # \param nruns_lte-softmodem global parameter to override number of runs (nruns) within the test case -def handle_testcaseclass_softmodem (testcase, oldprogramList, logdirOAI5GRepo , logdirOpenaircnRepo, MachineList, user, password, CleanUpAluLteBox, ExmimoRfStop, nruns_lte_softmodem): +def handle_testcaseclass_softmodem (testcase, oldprogramList, logdirOAI5GRepo , logdirOpenaircnRepo, MachineList, user, password, CleanUpAluLteBox, ExmimoRfStop, nruns_lte_softmodem, timeout_cmd): #We ignore the password sent to this function for secuirity reasons for password present in log files #It is recommended to add a line in /etc/sudoers that looks something like below. The line below will run sudo without password prompt # your_user_name ALL=(ALL:ALL) NOPASSWD: ALL @@ -558,7 +558,8 @@ def handle_testcaseclass_softmodem (testcase, oldprogramList, logdirOAI5GRepo , #user = getpass.getuser() testcasename = testcase.get('id') testcaseclass = testcase.findtext('class',default='') - timeout_cmd = testcase.findtext('TimeOut_cmd',default='') + if timeout_cmd == '': + timeout_cmd = testcase.findtext('TimeOut_cmd',default='') timeout_cmd = int(float(timeout_cmd)) #Timeout_thread is more than that of cmd to have room for compilation time, etc timeout_thread = timeout_cmd + 300 @@ -580,6 +581,8 @@ def handle_testcaseclass_softmodem (testcase, oldprogramList, logdirOAI5GRepo , eNB_traffic_exec_args = testcase.findtext('eNB_traffic_exec_args',default='') eNB_terminate_missing_procs = testcase.findtext('eNB_terminate_missing_procs',default='True') eNB_search_expr_true = testcase.findtext('eNB_search_expr_true','') + if re.compile('\w+').match(eNB_search_expr_true) != None: + eNB_search_expr_true = eNB_search_expr_true + 'duration=' + str(timeout_cmd-90) + 's' UEMachine = testcase.findtext('UE',default='') UE_config_file = testcase.findtext('UE_config_file',default='') @@ -594,6 +597,8 @@ def handle_testcaseclass_softmodem (testcase, oldprogramList, logdirOAI5GRepo , UE_terminate_missing_procs = testcase.findtext('UE_terminate_missing_procs',default='True') UE_search_expr_true = testcase.findtext('UE_search_expr_true','') UE_stop_script = testcase.findtext('UE_stop_script','') + if re.compile('\w+').match(UE_search_expr_true) != None: + UE_search_expr_true = UE_search_expr_true + 'duration=' + str(timeout_cmd-90) + 's' EPCMachine = testcase.findtext('EPC',default='') EPC_config_file = testcase.findtext('EPC_config_file',default='') @@ -612,6 +617,8 @@ def handle_testcaseclass_softmodem (testcase, oldprogramList, logdirOAI5GRepo , EPC_traffic_exec_args = testcase.findtext('EPC_traffic_exec_args',default='') EPC_terminate_missing_procs = testcase.findtext('EPC_terminate_missing_procs',default='True') EPC_search_expr_true = testcase.findtext('EPC_search_expr_true','') + if re.compile('\w+').match(EPC_search_expr_true) != None: + EPC_search_expr_true = EPC_search_expr_true + 'duration=' + str(timeout_cmd-90) + 's' index_eNBMachine = MachineList.index(eNBMachine) index_UEMachine = MachineList.index(UEMachine) @@ -705,7 +712,10 @@ def handle_testcaseclass_softmodem (testcase, oldprogramList, logdirOAI5GRepo , task_eNB = task_eNB + 'array_exec_pid+=($!) \n' task_eNB = task_eNB + 'echo eNB_main_exec PID = $! \n' if eNB_traffic_exec != "": - task_eNB = task_eNB + ' (date; ' + eNB_traffic_exec + ' ' + eNB_traffic_exec_args + ' ) > ' + logfile_traffic_eNB + ' 2>&1 & \n' + cmd_traffic = eNB_traffic_exec + ' ' + eNB_traffic_exec_args + if cmd_traffic.find('-c') >= 0: + cmd_traffic = cmd_traffic + '-t ' + str(timeout_cmd - 60) + task_eNB = task_eNB + ' (date; ' + cmd_traffic + ' ) > ' + logfile_traffic_eNB + ' 2>&1 & \n' task_eNB = task_eNB + 'array_exec_pid+=($!) \n' task_eNB = task_eNB + 'echo eNB_traffic_exec PID = $! \n' @@ -755,7 +765,10 @@ def handle_testcaseclass_softmodem (testcase, oldprogramList, logdirOAI5GRepo , task_UE = task_UE + 'array_exec_pid+=($!) \n' task_UE = task_UE + 'echo UE_main_exec PID = $! \n' if UE_traffic_exec != "": - task_UE = task_UE + ' ( date; ' + UE_traffic_exec + ' ' + UE_traffic_exec_args + ' ) >' + logfile_traffic_UE + ' 2>&1 & \n' + cmd_traffic = UE_traffic_exec + ' ' + UE_traffic_exec_args + if cmd_traffic.find('-c') >= 0: + cmd_traffic = cmd_traffic + '-t ' + str(timeout_cmd - 60) + task_UE = task_UE + ' ( date; ' + cmd_traffic + ' ) >' + logfile_traffic_UE + ' 2>&1 & \n' task_UE = task_UE + 'array_exec_pid+=($!) \n' task_UE = task_UE + 'echo UE_traffic_exec PID = $! \n' #terminate the UE test case after timeout_cmd seconds @@ -805,7 +818,10 @@ def handle_testcaseclass_softmodem (testcase, oldprogramList, logdirOAI5GRepo , task_EPC = task_EPC + 'array_exec_pid+=($!) \n' task_EPC = task_EPC + 'echo EPC_main_exec PID = $! \n' if EPC_traffic_exec != "": - task_EPC = task_EPC + '( date; ' + EPC_traffic_exec + ' ' + EPC_traffic_exec_args + ' ) > ' + logfile_traffic_EPC + ' 2>&1 & \n' + cmd_traffic = EPC_traffic_exec + ' ' + EPC_traffic_exec_args + if cmd_traffic.find('-c') >= 0: + cmd_traffic = cmd_traffic + '-t ' + str(timeout_cmd - 60) + task_EPC = task_EPC + '( date; ' + cmd_traffic + ' ) > ' + logfile_traffic_EPC + ' 2>&1 & \n' task_EPC = task_EPC + 'array_exec_pid+=($!) \n' task_EPC = task_EPC + 'echo EPC_traffic_exec PID = $! \n' #terminate the EPC test case after timeout_cmd seconds @@ -1041,7 +1057,7 @@ flag_remove_logdir=False flag_start_testcase=False nruns_lte_softmodem='' flag_skip_git_head_check=False - +Timeout_cmd='' print "Number of arguments argc = " + str(len(sys.argv)) #for index in range(1,len(sys.argv) ): # print "argv_" + str(index) + " : " + sys.argv[index] @@ -1097,6 +1113,9 @@ while i < len (sys.argv): i = i +1 elif arg == '--skip-git-head-check': flag_skip_git_head_check=True + elif arg == '--timeout_cmd': + Timeout_cmd = sys.argv[i+1] + i = i +1 elif arg == '-h' : print "-s: This flag *MUST* be set to start the test cases" print "-r: Remove the log directory in autotests" @@ -1111,6 +1130,7 @@ while i < len (sys.argv): print "-MachineList : overrides the MachineList parameter in test_case_list.xml" print "-MachineListGeneric : overrides the MachineListGeneric parameter in test_case_list.xml" print "--skip-git-head-check: skip checking of GitHead remote/local branch (only for debugging)" + print "--timeout_cmd: Override the default parameter (timeout_cmd) in test_case_list.xml. This parameter is in seconds and should be > 120 sys.exit() else : print "Unrecongnized Option: <" + arg + ">. Use -h to see valid options" @@ -1211,6 +1231,7 @@ print "GitOAI5GBranch = " + GitOAI5GRepoBranch print "GitOpenaircnRepoBranch = " + GitOpenaircnRepoBranch print "NFSResultsShare = " + NFSResultsShare print "nruns_lte_softmodem = " + nruns_lte_softmodem +print "Timeout_cmd = " + Timeout_cmd if GitOAI5GHeadVersion == '': cmd = "git show-ref --heads -s "+ GitOAI5GRepoBranch @@ -1315,7 +1336,7 @@ for oai in oai_list: cmd = cmd + 'echo \"GitOAI5GHeadVersion_remote = $git_head\"' cmd = cmd + 'echo \"GitOAI5GHeadVersion_local = ' + GitOAI5GHeadVersion + '\" \n' if flag_skip_git_head_check==True: - cmd = cmd + 'print \"skipping GitHead check...\" ' + cmd = cmd + 'echo \"skipping GitHead check...\" \n ' else: cmd = cmd + 'if [ \"$git_head\" != \"'+ GitOAI5GHeadVersion + '\" ]; then echo \"error: Git openairinterface5g head version does not match\" ; fi \n' cmd = cmd + 'source oaienv' + '\n' @@ -1403,8 +1424,8 @@ for testcase in testcaseList: print "eNBMachine : " + eNBMachine + "UEMachine : " + UEMachine + "EPCMachine : " + EPCMachine + "MachineList : " + ','.join(MachineList) print "testcasename = " + testcasename + " class = " + testcaseclass threadListGlobal = wait_testcaseclass_generic_threads(threadListGlobal, Timeout_execution) - cleanOldProgramsAllMachines(oai_list, CleanUpOldProgs, CleanUpAluLteBox, ExmimoRfStop) - handle_testcaseclass_softmodem (testcase, CleanUpOldProgs, logdirOAI5GRepo, logdirOpenaircnRepo, MachineList, user, pw, CleanUpAluLteBox, ExmimoRfStop, nruns_lte_softmodem ) + #cleanOldProgramsAllMachines(oai_list, CleanUpOldProgs, CleanUpAluLteBox, ExmimoRfStop) + handle_testcaseclass_softmodem (testcase, CleanUpOldProgs, logdirOAI5GRepo, logdirOpenaircnRepo, MachineList, user, pw, CleanUpAluLteBox, ExmimoRfStop, nruns_lte_softmodem, Timeout_cmd ) elif (testcaseclass == 'compilation'): threadListGlobal = handle_testcaseclass_generic (testcasename, threadListGlobal, CleanUpOldProgs, logdirOAI5GRepo, MachineListGeneric, user, pw, CleanUpAluLteBox,Timeout_execution, ExmimoRfStop) elif (testcaseclass == 'execution'): From 132b71a01f53517a1ec91f2be4422793e405284a Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Thu, 21 Jan 2016 12:06:41 +0100 Subject: [PATCH 166/263] override timeout_cmd + addl OAI CN test cases --- .../autotests/run_exec_lte-softmodem_tests.py | 14 +- cmake_targets/autotests/test_case_list.xml | 1297 ++++++++++++----- 2 files changed, 915 insertions(+), 396 deletions(-) diff --git a/cmake_targets/autotests/run_exec_lte-softmodem_tests.py b/cmake_targets/autotests/run_exec_lte-softmodem_tests.py index 493a4a473c..ed4a19f4dc 100755 --- a/cmake_targets/autotests/run_exec_lte-softmodem_tests.py +++ b/cmake_targets/autotests/run_exec_lte-softmodem_tests.py @@ -582,7 +582,7 @@ def handle_testcaseclass_softmodem (testcase, oldprogramList, logdirOAI5GRepo , eNB_terminate_missing_procs = testcase.findtext('eNB_terminate_missing_procs',default='True') eNB_search_expr_true = testcase.findtext('eNB_search_expr_true','') if re.compile('\w+').match(eNB_search_expr_true) != None: - eNB_search_expr_true = eNB_search_expr_true + 'duration=' + str(timeout_cmd-90) + 's' + eNB_search_expr_true = eNB_search_expr_true + ' duration=' + str(timeout_cmd-90) + 's' UEMachine = testcase.findtext('UE',default='') UE_config_file = testcase.findtext('UE_config_file',default='') @@ -598,7 +598,7 @@ def handle_testcaseclass_softmodem (testcase, oldprogramList, logdirOAI5GRepo , UE_search_expr_true = testcase.findtext('UE_search_expr_true','') UE_stop_script = testcase.findtext('UE_stop_script','') if re.compile('\w+').match(UE_search_expr_true) != None: - UE_search_expr_true = UE_search_expr_true + 'duration=' + str(timeout_cmd-90) + 's' + UE_search_expr_true = UE_search_expr_true + ' duration=' + str(timeout_cmd-90) + 's' EPCMachine = testcase.findtext('EPC',default='') EPC_config_file = testcase.findtext('EPC_config_file',default='') @@ -618,7 +618,7 @@ def handle_testcaseclass_softmodem (testcase, oldprogramList, logdirOAI5GRepo , EPC_terminate_missing_procs = testcase.findtext('EPC_terminate_missing_procs',default='True') EPC_search_expr_true = testcase.findtext('EPC_search_expr_true','') if re.compile('\w+').match(EPC_search_expr_true) != None: - EPC_search_expr_true = EPC_search_expr_true + 'duration=' + str(timeout_cmd-90) + 's' + EPC_search_expr_true = EPC_search_expr_true + ' duration=' + str(timeout_cmd-90) + 's' index_eNBMachine = MachineList.index(eNBMachine) index_UEMachine = MachineList.index(UEMachine) @@ -714,7 +714,7 @@ def handle_testcaseclass_softmodem (testcase, oldprogramList, logdirOAI5GRepo , if eNB_traffic_exec != "": cmd_traffic = eNB_traffic_exec + ' ' + eNB_traffic_exec_args if cmd_traffic.find('-c') >= 0: - cmd_traffic = cmd_traffic + '-t ' + str(timeout_cmd - 60) + cmd_traffic = cmd_traffic + ' -t ' + str(timeout_cmd - 60) task_eNB = task_eNB + ' (date; ' + cmd_traffic + ' ) > ' + logfile_traffic_eNB + ' 2>&1 & \n' task_eNB = task_eNB + 'array_exec_pid+=($!) \n' task_eNB = task_eNB + 'echo eNB_traffic_exec PID = $! \n' @@ -767,7 +767,7 @@ def handle_testcaseclass_softmodem (testcase, oldprogramList, logdirOAI5GRepo , if UE_traffic_exec != "": cmd_traffic = UE_traffic_exec + ' ' + UE_traffic_exec_args if cmd_traffic.find('-c') >= 0: - cmd_traffic = cmd_traffic + '-t ' + str(timeout_cmd - 60) + cmd_traffic = cmd_traffic + ' -t ' + str(timeout_cmd - 60) task_UE = task_UE + ' ( date; ' + cmd_traffic + ' ) >' + logfile_traffic_UE + ' 2>&1 & \n' task_UE = task_UE + 'array_exec_pid+=($!) \n' task_UE = task_UE + 'echo UE_traffic_exec PID = $! \n' @@ -820,7 +820,7 @@ def handle_testcaseclass_softmodem (testcase, oldprogramList, logdirOAI5GRepo , if EPC_traffic_exec != "": cmd_traffic = EPC_traffic_exec + ' ' + EPC_traffic_exec_args if cmd_traffic.find('-c') >= 0: - cmd_traffic = cmd_traffic + '-t ' + str(timeout_cmd - 60) + cmd_traffic = cmd_traffic + ' -t ' + str(timeout_cmd - 60) task_EPC = task_EPC + '( date; ' + cmd_traffic + ' ) > ' + logfile_traffic_EPC + ' 2>&1 & \n' task_EPC = task_EPC + 'array_exec_pid+=($!) \n' task_EPC = task_EPC + 'echo EPC_traffic_exec PID = $! \n' @@ -1130,7 +1130,7 @@ while i < len (sys.argv): print "-MachineList : overrides the MachineList parameter in test_case_list.xml" print "-MachineListGeneric : overrides the MachineListGeneric parameter in test_case_list.xml" print "--skip-git-head-check: skip checking of GitHead remote/local branch (only for debugging)" - print "--timeout_cmd: Override the default parameter (timeout_cmd) in test_case_list.xml. This parameter is in seconds and should be > 120 + print "--timeout_cmd: Override the default parameter (timeout_cmd) in test_case_list.xml. This parameter is in seconds and should be > 120" sys.exit() else : print "Unrecongnized Option: <" + arg + ">. Use -h to see valid options" diff --git a/cmake_targets/autotests/test_case_list.xml b/cmake_targets/autotests/test_case_list.xml index fb29471b5f..1f627acefd 100644 --- a/cmake_targets/autotests/test_case_list.xml +++ b/cmake_targets/autotests/test_case_list.xml @@ -10,7 +10,7 @@ sudo -S -E /opt/ltebox/tools/stop_ltebox $OPENAIR_DIR/cmake_targets/build_oai -w EXMIMO -c; sudo -S -E $OPENAIR_DIR/cmake_targets/tools/stop_exmimo2; dmesg|tail 36000 - 0104+ 015502 015505 015506 015507 015508 015508 015509 015510 015511 015602 015700 016102 016105 + 0104+ 015502 015505 015506 015507 015508 015508 015509 015510 015511 015602 015605 015702 015705 016102 016105 3 mozart calisson stevens nano amerique @@ -903,7 +903,7 @@ $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 45; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue - $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 1 ppp0 -u -c 192.172.0.1 -b 10Mbits/s -t 330 -B 192.172.0.2 + $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 1 ppp0 -u -c 192.172.0.1 -b 10Mbits/s -B 192.172.0.2 @@ -929,7 +929,7 @@ $OPENAIRCN_DIR/TEST/autotests/tools/iperf_script 5 lo -s -i 1 -u -f m -B 192.172.0.1 - throughput_test min=1.0Mbits/sec max=1.0Mbits/sec average=1.0Mbits/sec duration=300.0s + throughput_test min=1.0Mbits/sec max=1.0Mbits/sec average=1.0Mbits/sec False USRPb210.ALU_EPC.Bandrich.5MHz.FDD.Band_7.UL.1TX.1RX @@ -987,7 +987,7 @@ $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 45; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue - $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 1 ppp0 -u -c 192.172.0.1 -b 10Mbits/s -t 330 -B 192.172.0.2 + $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 1 ppp0 -u -c 192.172.0.1 -b 10Mbits/s -B 192.172.0.2 @@ -1013,7 +1013,7 @@ $OPENAIRCN_DIR/TEST/autotests/tools/iperf_script 5 lo -s -i 1 -u -f m -B 192.172.0.1 - throughput_test min=1.0Mbits/sec max=1.0Mbits/sec average=1.0Mbits/sec duration=300.0s + throughput_test min=1.0Mbits/sec max=1.0Mbits/sec average=1.0Mbits/sec True USRPb210.ALU_EPC.Bandrich.10MHz.FDD.Band_7.UL.1TX.1RX @@ -1070,7 +1070,7 @@ $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 45; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue - $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 1 ppp0 -u -c 192.172.0.1 -b 10Mbits/s -t 330 -B 192.172.0.2 + $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 1 ppp0 -u -c 192.172.0.1 -b 10Mbits/s -B 192.172.0.2 @@ -1096,7 +1096,7 @@ $OPENAIRCN_DIR/TEST/autotests/tools/iperf_script 5 lo -s -i 1 -u -f m -B 192.172.0.1 - throughput_test min=1.0Mbits/sec max=1.0Mbits/sec average=1.0Mbits/sec duration=300.0s + throughput_test min=1.0Mbits/sec max=1.0Mbits/sec average=1.0Mbits/sec True USRPb210.ALU_EPC.Bandrich.20MHz.FDD.Band_7.UL.1TX.1RX @@ -1157,7 +1157,7 @@ True sudo -S -E $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue - throughput_test min=4.0Mbits/sec max=5.0Mbits/sec average=4.0Mbits/sec duration=300.0s + throughput_test min=4.0Mbits/sec max=5.0Mbits/sec average=4.0Mbits/sec /tmp @@ -1177,7 +1177,7 @@ /opt/hss_sim0609/starthss >> /dev/null ; sleep 3000 - $OPENAIRCN_DIR/TEST/autotests/tools/iperf_script 60 lo -u -c 192.172.0.2 -b 10Mbits/s -t 330 -B 192.172.0.1 + $OPENAIRCN_DIR/TEST/autotests/tools/iperf_script 60 lo -u -c 192.172.0.2 -b 10Mbits/s -B 192.172.0.1 True @@ -1237,7 +1237,7 @@ $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 1 ppp0 -s -i 1 -u -f m -B 192.172.0.2 - throughput_test min=8.0Mbits/sec max=9.0Mbits/sec average=8.5Mbits/sec duration=300.0s + throughput_test min=8.0Mbits/sec max=9.0Mbits/sec average=8.5Mbits/sec True sudo -S -E $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue @@ -1260,7 +1260,7 @@ /opt/hss_sim0609/starthss >> /dev/null ; sleep 3000 - $OPENAIRCN_DIR/TEST/autotests/tools/iperf_script 60 lo -u -c 192.172.0.2 -b 10Mbits/s -t 330 -B 192.172.0.1 + $OPENAIRCN_DIR/TEST/autotests/tools/iperf_script 60 lo -u -c 192.172.0.2 -b 10Mbits/s -B 192.172.0.1 True @@ -1320,7 +1320,7 @@ $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 1 ppp0 -s -i 1 -u -f m -B 192.172.0.2 - throughput_test min=15.0Mbits/sec max=15.0Mbits/sec average=15.0Mbits/sec duration=300.0s + throughput_test min=15.0Mbits/sec max=15.0Mbits/sec average=15.0Mbits/sec True sudo -S -E $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue @@ -1343,7 +1343,7 @@ /opt/hss_sim0609/starthss >> /dev/null ; sleep 3000 - $OPENAIRCN_DIR/TEST/autotests/tools/iperf_script 60 lo -u -c 192.172.0.2 -b 10Mbits/s -t 330 -B 192.172.0.1 + $OPENAIRCN_DIR/TEST/autotests/tools/iperf_script 60 lo -u -c 192.172.0.2 -b 10Mbits/s -B 192.172.0.1 True @@ -1402,7 +1402,7 @@ $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue;$OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 45; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue - $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 1 ppp0 -u -c 192.172.0.1 -b 10Mbits/s -t 330 -B 192.172.0.2 + $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 1 ppp0 -u -c 192.172.0.1 -b 10Mbits/s -B 192.172.0.2 @@ -1428,7 +1428,7 @@ $OPENAIRCN_DIR/TEST/autotests/tools/iperf_script 5 lo iperf -s -i 1 -u -f m -B 192.172.0.1 - throughput_test min=1.0Mbits/sec max=1.0Mbits/sec average=1.0Mbits/sec duration=300.0s + throughput_test min=1.0Mbits/sec max=1.0Mbits/sec average=1.0Mbits/sec True USRPb210.ALU_EPC.Bandrich.5MHz.FDD.Band_7.UL.2TX.2RX @@ -1486,7 +1486,7 @@ $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue;$OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 45; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue - $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 1 ppp0 -u -c 192.172.0.1 -b 10Mbits/s -t 330 -B 192.172.0.2 + $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 1 ppp0 -u -c 192.172.0.1 -b 10Mbits/s -B 192.172.0.2 @@ -1512,7 +1512,7 @@ $OPENAIRCN_DIR/TEST/autotests/tools/iperf_script 5 lo -s -i 1 -u -f m -B 192.172.0.1 - throughput_test min=2.0Mbits/sec max=2.0Mbits/sec average=2.0Mbits/sec duration=300.0s + throughput_test min=2.0Mbits/sec max=2.0Mbits/sec average=2.0Mbits/sec True USRPb210.ALU_EPC.Bandrich.10MHz.FDD.Band_7.UL.2TX.2RX @@ -1569,7 +1569,7 @@ $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 45; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue - $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 1 ppp0 -u -c 192.172.0.1 -b 10Mbits/s -t 330 -B 192.172.0.2 + $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 1 ppp0 -u -c 192.172.0.1 -b 10Mbits/s -B 192.172.0.2 @@ -1595,7 +1595,7 @@ $OPENAIRCN_DIR/TEST/autotests/tools/iperf_script 5 lo -s -i 1 -u -f m -B 192.172.0.1 - throughput_test min=4.0Mbits/sec max=4.0Mbits/sec average=4.0Mbits/sec duration=300.0s + throughput_test min=4.0Mbits/sec max=4.0Mbits/sec average=4.0Mbits/sec True USRPb210.ALU_EPC.Bandrich.20MHz.FDD.Band_7.UL.2TX.2RX @@ -1654,7 +1654,7 @@ $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 1 ppp0 -s -i 1 -u -f m -B 192.172.0.2 - throughput_test min=4.0Mbits/sec max=5.0Mbits/sec average=4.0Mbits/sec duration=300.0s + throughput_test min=4.0Mbits/sec max=5.0Mbits/sec average=4.0Mbits/sec True sudo -S -E $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue @@ -1677,7 +1677,7 @@ /opt/hss_sim0609/starthss >> /dev/null ; sleep 3000 - $OPENAIRCN_DIR/TEST/autotests/tools/iperf_script 60 lo -u -c 192.172.0.2 -b 10Mbits/s -t 330 -B 192.172.0.1 + $OPENAIRCN_DIR/TEST/autotests/tools/iperf_script 60 lo -u -c 192.172.0.2 -b 10Mbits/s -B 192.172.0.1 True @@ -1737,7 +1737,7 @@ $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 1 ppp0 -s -i 1 -u -f m -B 192.172.0.2 - throughput_test min=8.0Mbits/sec max=9.0Mbits/sec average=8.5Mbits/sec duration=300.0s + throughput_test min=8.0Mbits/sec max=9.0Mbits/sec average=8.5Mbits/sec True sudo -S -E $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue @@ -1760,7 +1760,7 @@ /opt/hss_sim0609/starthss >> /dev/null ; sleep 3000 - $OPENAIRCN_DIR/TEST/autotests/tools/iperf_script 60 lo -u -c 192.172.0.2 -b 10Mbits/s -t 330 -B 192.172.0.1 + $OPENAIRCN_DIR/TEST/autotests/tools/iperf_script 60 lo -u -c 192.172.0.2 -b 10Mbits/s -B 192.172.0.1 True @@ -1820,7 +1820,7 @@ $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 1 ppp0 -s -i 1 -u -f m -B 192.172.0.2 - throughput_test min=15.0Mbits/sec max=15.0Mbits/sec average=15.0Mbits/sec duration=300.0s + throughput_test min=15.0Mbits/sec max=15.0Mbits/sec average=15.0Mbits/sec True sudo -S -E $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue @@ -1843,7 +1843,7 @@ /opt/hss_sim0609/starthss >> /dev/null ; sleep 3000 - $OPENAIRCN_DIR/TEST/autotests/tools/iperf_script 60 lo -u -c 192.172.0.2 -b 10Mbits/s -t 330 -B 192.172.0.1 + $OPENAIRCN_DIR/TEST/autotests/tools/iperf_script 60 lo -u -c 192.172.0.2 -b 10Mbits/s -B 192.172.0.1 True @@ -1864,6 +1864,7 @@ targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf mobile_country_code \"208\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf mobile_network_code \"92\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf N_RB_DL 25 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf pdsch_referenceSignalPower -26 targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf mme_ip_address "ipv4=\"192.170.0.1\";ipv6=\"192:168:30::17\";active=\"yes\";preference=\"ipv4\";" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf downlink_frequency 2660000000L targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf uplink_frequency_offset -120000000 @@ -1879,7 +1880,7 @@ targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf ENB_PORT_FOR_S1U 2152 $OPENAIR_DIR/cmake_targets/build_oai --eNB -w USRP -c - sleep 15; sudo -E ifconfig eth0:3 192.170.0.2 up ; sudo -E ifconfig eth0:4 192.170.1.2 up; ifconfig + sleep 15; sudo -E bash -c 'echo 3 > /proc/sys/vm/drop_caches' ; sudo -E ifconfig eth0:3 192.170.0.2 up ; sudo -E ifconfig eth0:4 192.170.1.2 up; ifconfig $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf -W @@ -1893,263 +1894,17 @@ - + sudo -E bash -c 'echo 3 > /proc/sys/vm/drop_caches' $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue - $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 1 ppp0 -u -c 192.172.0.1 -b 10Mbits/s -t 330 -B 192.172.0.2 + $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 1 ppp0 -u -c 192.172.0.1 -b 10Mbits/s -B 192.172.0.2 False $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; sudo -S -E $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue - /tmp - BUILD/EPC/epc.conf.in MCC \"208\" - BUILD/EPC/epc.conf.in MNC \"92\" - BUILD/EPC/epc.conf.in TAC \"1\" - BUILD/EPC/epc.conf.in MME_INTERFACE_NAME_FOR_S1_MME \"eth0:1\" - BUILD/EPC/epc.conf.in MME_IPV4_ADDRESS_FOR_S1_MME \"192.170.0.1/24\" - BUILD/EPC/epc.conf.in SGW_INTERFACE_NAME_FOR_S1U_S12_S4_UP \"eth0:2\"; - BUILD/EPC/epc.conf.in SGW_IPV4_ADDRESS_FOR_S1U_S12_S4_UP \"192.170.1.1/24\"; - BUILD/EPC/epc.conf.in PGW_INTERFACE_NAME_FOR_SGI \"eth1\" - BUILD/EPC/epc.conf.in PGW_IPV4_ADDRESS_FOR_SGI \"192.168.12.82/24\" - $OPENAIRCN_DIR/SCRIPTS/build_epc - -c -l - $OPENAIRCN_DIR/SCRIPTS/build_hss - -c -l - - sudo -E ifconfig eth1 add 192.172.0.1 - - $OPENAIRCN_DIR/SCRIPTS/run_epc - -i -r - sleep 10; $OPENAIRCN_DIR/SCRIPTS/run_hss - - $OPENAIRCN_DIR/TEST/autotests/tools/iperf_script 5 lo -s -i 1 -u -f m -B 192.172.0.1 - - throughput_test min=1.0Mbits/sec max=1.0Mbits/sec average=1.0Mbits/sec duration=300.0s - - False - USRPb210.OAI_EPC.Bandrich.5MHz.FDD.Band_7.UL.1TX.1RX - 10 - - - - lte-softmodem - - calisson - stevens - calisson - 390 - /tmp - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf tracking_area_code \"1\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf mobile_country_code \"208\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf mobile_network_code \"92\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf N_RB_DL 50 - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf mme_ip_address "ipv4=\"192.170.0.1\";ipv6=\"192:168:30::17\";active=\"yes\";preference=\"ipv4\";" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf downlink_frequency 2660000000L - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf uplink_frequency_offset -120000000 - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf tx_gain 90 - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf rx_gain 125 - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf frame_type \"FDD\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf nb_antennas_rx 1 - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf nb_antennas_tx 1 - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf ENB_INTERFACE_NAME_FOR_S1_MME \"eth0:3\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf ENB_IPV4_ADDRESS_FOR_S1_MME \"192.170.0.2/24\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf ENB_INTERFACE_NAME_FOR_S1U \"eth0:4\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf ENB_IPV4_ADDRESS_FOR_S1U \"192.170.1.2/24\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf ENB_PORT_FOR_S1U 2152 - $OPENAIR_DIR/cmake_targets/build_oai - --eNB -w USRP -c - sleep 15; sudo -E ifconfig eth0:3 192.170.0.2 up ; sudo -E ifconfig eth0:4 192.170.1.2 up; ifconfig - - $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem - -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf -W - - - - - False - - /tmp - - - - - - $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue - - $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 1 ppp0 -u -c 192.172.0.1 -b 10Mbits/s -t 330 -B 192.172.0.2 - - - - False - $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; sudo -S -E $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue - - /tmp - BUILD/EPC/epc.conf.in MCC \"208\" - BUILD/EPC/epc.conf.in MNC \"92\" - BUILD/EPC/epc.conf.in TAC \"1\" - BUILD/EPC/epc.conf.in MME_INTERFACE_NAME_FOR_S1_MME \"eth0:1\" - BUILD/EPC/epc.conf.in MME_IPV4_ADDRESS_FOR_S1_MME \"192.170.0.1/24\" - BUILD/EPC/epc.conf.in SGW_INTERFACE_NAME_FOR_S1U_S12_S4_UP \"eth0:2\"; - BUILD/EPC/epc.conf.in SGW_IPV4_ADDRESS_FOR_S1U_S12_S4_UP \"192.170.1.1/24\"; - BUILD/EPC/epc.conf.in PGW_INTERFACE_NAME_FOR_SGI \"eth1\" - BUILD/EPC/epc.conf.in PGW_IPV4_ADDRESS_FOR_SGI \"192.168.12.82/24\" - $OPENAIRCN_DIR/SCRIPTS/build_epc - -c -l - $OPENAIRCN_DIR/SCRIPTS/build_hss - -c -l - - sudo -E ifconfig eth1 add 192.172.0.1 - - $OPENAIRCN_DIR/SCRIPTS/run_epc - -i -r - sleep 10; $OPENAIRCN_DIR/SCRIPTS/run_hss - - $OPENAIRCN_DIR/TEST/autotests/tools/iperf_script 5 lo -s -i 1 -u -f m -B 192.172.0.1 - - throughput_test min=1.0Mbits/sec max=1.0Mbits/sec average=1.0Mbits/sec duration=300.0s - - False - USRPb210.OAI_EPC.Bandrich.10MHz.FDD.Band_7.UL.1TX.1RX - 10 - - - - lte-softmodem - - calisson - stevens - calisson - 390 - /tmp - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf tracking_area_code \"1\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf mobile_country_code \"208\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf mobile_network_code \"92\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf N_RB_DL 100 - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf mme_ip_address "ipv4=\"192.170.0.1\";ipv6=\"192:168:30::17\";active=\"yes\";preference=\"ipv4\";" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf downlink_frequency 2660000000L - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf uplink_frequency_offset -120000000 - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf tx_gain 90 - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf rx_gain 125 - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf frame_type \"FDD\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf nb_antennas_rx 1 - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf nb_antennas_tx 1 - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf ENB_INTERFACE_NAME_FOR_S1_MME \"eth0:3\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf ENB_IPV4_ADDRESS_FOR_S1_MME \"192.170.0.2/24\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf ENB_INTERFACE_NAME_FOR_S1U \"eth0:4\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf ENB_IPV4_ADDRESS_FOR_S1U \"192.170.1.2/24\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf ENB_PORT_FOR_S1U 2152 - $OPENAIR_DIR/cmake_targets/build_oai - --eNB -w USRP -c - sleep 15; sudo -E ifconfig eth0:3 192.170.0.2 up ; sudo -E ifconfig eth0:4 192.170.1.2 up; ifconfig - - $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem - -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf -W - - - - - False - - /tmp - - - - - - $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue - - $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 1 ppp0 -u -c 192.172.0.1 -b 10Mbits/s -t 330 -B 192.172.0.2 - - - - False - $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; sudo -S -E $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue - - /tmp - BUILD/EPC/epc.conf.in MCC \"208\" - BUILD/EPC/epc.conf.in MNC \"92\" - BUILD/EPC/epc.conf.in TAC \"1\" - BUILD/EPC/epc.conf.in MME_INTERFACE_NAME_FOR_S1_MME \"eth0:1\" - BUILD/EPC/epc.conf.in MME_IPV4_ADDRESS_FOR_S1_MME \"192.170.0.1/24\" - BUILD/EPC/epc.conf.in SGW_INTERFACE_NAME_FOR_S1U_S12_S4_UP \"eth0:2\"; - BUILD/EPC/epc.conf.in SGW_IPV4_ADDRESS_FOR_S1U_S12_S4_UP \"192.170.1.1/24\"; - BUILD/EPC/epc.conf.in PGW_INTERFACE_NAME_FOR_SGI \"eth1\" - BUILD/EPC/epc.conf.in PGW_IPV4_ADDRESS_FOR_SGI \"192.168.12.82/24\" - $OPENAIRCN_DIR/SCRIPTS/build_epc - -c -l - $OPENAIRCN_DIR/SCRIPTS/build_hss - -c -l - - sudo -E ifconfig eth1 add 192.172.0.1 - - $OPENAIRCN_DIR/SCRIPTS/run_epc - -i -r - sleep 10; $OPENAIRCN_DIR/SCRIPTS/run_hss - - $OPENAIRCN_DIR/TEST/autotests/tools/iperf_script 5 lo -s -i 1 -u -f m -B 192.172.0.1 - - throughput_test min=1.0Mbits/sec max=1.0Mbits/sec average=1.0Mbits/sec duration=300.0s - - False - USRPb210.OAI_EPC.Bandrich.20MHz.FDD.Band_7.UL.1TX.1RX - 10 - - - - lte-softmodem - - calisson - stevens - calisson - 390 - /tmp - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf tracking_area_code \"1\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf mobile_country_code \"208\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf mobile_network_code \"92\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf N_RB_DL 25 - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf mme_ip_address "ipv4=\"192.170.0.1\";ipv6=\"192:168:30::17\";active=\"yes\";preference=\"ipv4\";" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf downlink_frequency 2660000000L - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf uplink_frequency_offset -120000000 - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf tx_gain 90 - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf rx_gain 125 - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf frame_type \"FDD\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf nb_antennas_rx 1 - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf nb_antennas_tx 1 - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf ENB_INTERFACE_NAME_FOR_S1_MME \"eth0:3\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf ENB_IPV4_ADDRESS_FOR_S1_MME \"192.170.0.2/24\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf ENB_INTERFACE_NAME_FOR_S1U \"eth0:4\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf ENB_IPV4_ADDRESS_FOR_S1U \"192.170.1.2/24\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf ENB_PORT_FOR_S1U 2152 - $OPENAIR_DIR/cmake_targets/build_oai - --eNB -w USRP -c - sleep 15; sudo -E ifconfig eth0:3 192.170.0.2 up ; sudo -E ifconfig eth0:4 192.170.1.2 up; ifconfig - - $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem - -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf -W - - - - - False - - /tmp - - - - - - $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue - - $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 1 ppp0 -s -i 1 -u -f m -B 192.172.0.2 - - throughput_test min=10.0Mbits/sec max=10.5Mbits/sec average=11.0Mbits/sec duration=300.0s - - False - $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; sudo -S -E $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue - /tmp BUILD/EPC/epc.conf.in MCC \"208\" BUILD/EPC/epc.conf.in MNC \"92\" @@ -2166,22 +1921,22 @@ $OPENAIRCN_DIR/SCRIPTS/build_hss -c -l - sudo -E ifconfig eth1 add 192.172.0.1 + sudo -E bash -c 'echo 3 > /proc/sys/vm/drop_caches' ; sudo -E ifconfig eth1 add 192.172.0.1 $OPENAIRCN_DIR/SCRIPTS/run_epc -i -r sleep 10; $OPENAIRCN_DIR/SCRIPTS/run_hss - $OPENAIRCN_DIR/TEST/autotests/tools/iperf_script 60 lo -u -c 192.172.0.2 -b 10Mbits/s -t 330 -B 192.172.0.1 + $OPENAIRCN_DIR/TEST/autotests/tools/iperf_script 5 lo -s -i 1 -u -f m -B 192.172.0.1 - + throughput_test min=1.0Mbits/sec max=1.0Mbits/sec average=1.0Mbits/sec False - USRPb210.OAI_EPC.Bandrich.5MHz.FDD.Band_7.DL.1TX.1RX + USRPb210.OAI_EPC_local.Bandrich.5MHz.FDD.Band_7.UL.1TX.1RX 10 - + lte-softmodem calisson @@ -2193,6 +1948,7 @@ targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf mobile_country_code \"208\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf mobile_network_code \"92\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf N_RB_DL 50 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf pdsch_referenceSignalPower -29 targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf mme_ip_address "ipv4=\"192.170.0.1\";ipv6=\"192:168:30::17\";active=\"yes\";preference=\"ipv4\";" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf downlink_frequency 2660000000L targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf uplink_frequency_offset -120000000 @@ -2208,7 +1964,7 @@ targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf ENB_PORT_FOR_S1U 2152 $OPENAIR_DIR/cmake_targets/build_oai --eNB -w USRP -c - sleep 15; sudo -E ifconfig eth0:3 192.170.0.2 up ; sudo -E ifconfig eth0:4 192.170.1.2 up; ifconfig + sleep 15; sudo -E bash -c 'echo 3 > /proc/sys/vm/drop_caches' ;sudo -E ifconfig eth0:3 192.170.0.2 up ; sudo -E ifconfig eth0:4 192.170.1.2 up; ifconfig $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf -W @@ -2222,13 +1978,13 @@ - + sudo -E bash -c 'echo 3 > /proc/sys/vm/drop_caches' $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue - $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 1 ppp0 -s -i 1 -u -f m -B 192.172.0.2 + $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 1 ppp0 -u -c 192.172.0.1 -b 10Mbits/s -B 192.172.0.2 - throughput_test min=20.0Mbits/sec max=22.0Mbits/sec average=22.0Mbits/sec duration=300.0s + False $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; sudo -S -E $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue @@ -2242,24 +1998,865 @@ BUILD/EPC/epc.conf.in SGW_INTERFACE_NAME_FOR_S1U_S12_S4_UP \"eth0:2\"; BUILD/EPC/epc.conf.in SGW_IPV4_ADDRESS_FOR_S1U_S12_S4_UP \"192.170.1.1/24\"; BUILD/EPC/epc.conf.in PGW_INTERFACE_NAME_FOR_SGI \"eth1\" - BUILD/EPC/epc.conf.in PGW_IPV4_ADDRESS_FOR_SGI \"192.168.12.82/24\" + BUILD/EPC/epc.conf.in PGW_IPV4_ADDRESS_FOR_SGI \"192.168.12.82/24\" + BUILD/EPC/epc.conf.in IPV4_LIST \"192.172.0.0/24\",\"192.172.1.0/24\" $OPENAIRCN_DIR/SCRIPTS/build_epc -c -l $OPENAIRCN_DIR/SCRIPTS/build_hss -c -l - sudo -E ifconfig eth1 add 192.172.0.1 + sudo -E bash -c 'echo 3 > /proc/sys/vm/drop_caches' ;sudo -E ifconfig eth1 add 192.172.0.1 $OPENAIRCN_DIR/SCRIPTS/run_epc -i -r sleep 10; $OPENAIRCN_DIR/SCRIPTS/run_hss - $OPENAIRCN_DIR/TEST/autotests/tools/iperf_script 60 lo -u -c 192.172.0.2 -b 30Mbits/s -t 330 -B 192.172.0.1 + $OPENAIRCN_DIR/TEST/autotests/tools/iperf_script 5 lo -s -i 1 -u -f m -B 192.172.0.1 + + throughput_test min=1.0Mbits/sec max=1.0Mbits/sec average=1.0Mbits/sec + + False + USRPb210.OAI_EPC_local.Bandrich.10MHz.FDD.Band_7.UL.1TX.1RX + 10 + + + + lte-softmodem + + calisson + stevens + calisson + 390 + /tmp + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf tracking_area_code \"1\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf mobile_country_code \"208\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf mobile_network_code \"92\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf N_RB_DL 100 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf pdsch_referenceSignalPower -29 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf mme_ip_address "ipv4=\"192.170.0.1\";ipv6=\"192:168:30::17\";active=\"yes\";preference=\"ipv4\";" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf downlink_frequency 2660000000L + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf uplink_frequency_offset -120000000 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf tx_gain 90 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf rx_gain 125 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf frame_type \"FDD\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf nb_antennas_rx 1 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf nb_antennas_tx 1 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf ENB_INTERFACE_NAME_FOR_S1_MME \"eth0:3\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf ENB_IPV4_ADDRESS_FOR_S1_MME \"192.170.0.2/24\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf ENB_INTERFACE_NAME_FOR_S1U \"eth0:4\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf ENB_IPV4_ADDRESS_FOR_S1U \"192.170.1.2/24\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf ENB_PORT_FOR_S1U 2152 + $OPENAIR_DIR/cmake_targets/build_oai + --eNB -w USRP -c + sleep 15; sudo -E bash -c 'echo 3 > /proc/sys/vm/drop_caches' ;sudo -E ifconfig eth0:3 192.170.0.2 up ; sudo -E ifconfig eth0:4 192.170.1.2 up; ifconfig + + $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem + -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf -W + + + + + False + + /tmp + + + + sudo -E bash -c 'echo 3 > /proc/sys/vm/drop_caches' + + $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue + + $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 1 ppp0 -u -c 192.172.0.1 -b 10Mbits/s -B 192.172.0.2 + + + + False + $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; sudo -S -E $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue + + /tmp + BUILD/EPC/epc.conf.in MCC \"208\" + BUILD/EPC/epc.conf.in MNC \"92\" + BUILD/EPC/epc.conf.in TAC \"1\" + BUILD/EPC/epc.conf.in MME_INTERFACE_NAME_FOR_S1_MME \"eth0:1\" + BUILD/EPC/epc.conf.in MME_IPV4_ADDRESS_FOR_S1_MME \"192.170.0.1/24\" + BUILD/EPC/epc.conf.in SGW_INTERFACE_NAME_FOR_S1U_S12_S4_UP \"eth0:2\"; + BUILD/EPC/epc.conf.in SGW_IPV4_ADDRESS_FOR_S1U_S12_S4_UP \"192.170.1.1/24\"; + BUILD/EPC/epc.conf.in PGW_INTERFACE_NAME_FOR_SGI \"eth1\" + BUILD/EPC/epc.conf.in PGW_IPV4_ADDRESS_FOR_SGI \"192.168.12.82/24\" + BUILD/EPC/epc.conf.in IPV4_LIST \"192.172.0.0/24\",\"192.172.1.0/24\" + $OPENAIRCN_DIR/SCRIPTS/build_epc + -c -l + $OPENAIRCN_DIR/SCRIPTS/build_hss + -c -l + + sudo -E bash -c 'echo 3 > /proc/sys/vm/drop_caches' ; sudo -E ifconfig eth1 add 192.172.0.1 + + $OPENAIRCN_DIR/SCRIPTS/run_epc + -i -r + sleep 10; $OPENAIRCN_DIR/SCRIPTS/run_hss + + $OPENAIRCN_DIR/TEST/autotests/tools/iperf_script 5 lo -s -i 1 -u -f m -B 192.172.0.1 + + throughput_test min=1.0Mbits/sec max=1.0Mbits/sec average=1.0Mbits/sec + + False + USRPb210.OAI_EPC_local.Bandrich.20MHz.FDD.Band_7.UL.1TX.1RX + 10 + + + + lte-softmodem + + calisson + stevens + calisson + 390 + /tmp + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf tracking_area_code \"1\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf mobile_country_code \"208\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf mobile_network_code \"92\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf N_RB_DL 25 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf pdsch_referenceSignalPower -26 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf mme_ip_address "ipv4=\"192.170.0.1\";ipv6=\"192:168:30::17\";active=\"yes\";preference=\"ipv4\";" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf downlink_frequency 2660000000L + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf uplink_frequency_offset -120000000 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf tx_gain 90 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf rx_gain 125 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf frame_type \"FDD\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf nb_antennas_rx 1 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf nb_antennas_tx 1 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf ENB_INTERFACE_NAME_FOR_S1_MME \"eth0:3\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf ENB_IPV4_ADDRESS_FOR_S1_MME \"192.170.0.2/24\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf ENB_INTERFACE_NAME_FOR_S1U \"eth0:4\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf ENB_IPV4_ADDRESS_FOR_S1U \"192.170.1.2/24\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf ENB_PORT_FOR_S1U 2152 + $OPENAIR_DIR/cmake_targets/build_oai + --eNB -w USRP -c + sleep 15; sudo -E bash -c 'echo 3 > /proc/sys/vm/drop_caches' ;sudo -E ifconfig eth0:3 192.170.0.2 up ; sudo -E ifconfig eth0:4 192.170.1.2 up; ifconfig + + $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem + -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf -W + + + + + False + + /tmp + + + + sudo -E bash -c 'echo 3 > /proc/sys/vm/drop_caches' + + $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue + + $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 1 ppp0 -s -i 1 -u -f m -B 192.172.0.2 + + throughput_test min=10.0Mbits/sec max=10.5Mbits/sec average=11.0Mbits/sec + + False + $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; sudo -S -E $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue + + /tmp + BUILD/EPC/epc.conf.in MCC \"208\" + BUILD/EPC/epc.conf.in MNC \"92\" + BUILD/EPC/epc.conf.in TAC \"1\" + BUILD/EPC/epc.conf.in MME_INTERFACE_NAME_FOR_S1_MME \"eth0:1\" + BUILD/EPC/epc.conf.in MME_IPV4_ADDRESS_FOR_S1_MME \"192.170.0.1/24\" + BUILD/EPC/epc.conf.in SGW_INTERFACE_NAME_FOR_S1U_S12_S4_UP \"eth0:2\"; + BUILD/EPC/epc.conf.in SGW_IPV4_ADDRESS_FOR_S1U_S12_S4_UP \"192.170.1.1/24\"; + BUILD/EPC/epc.conf.in PGW_INTERFACE_NAME_FOR_SGI \"eth1\" + BUILD/EPC/epc.conf.in PGW_IPV4_ADDRESS_FOR_SGI \"192.168.12.82/24\" + BUILD/EPC/epc.conf.in IPV4_LIST \"192.172.0.0/24\",\"192.172.1.0/24\" + $OPENAIRCN_DIR/SCRIPTS/build_epc + -c -l + $OPENAIRCN_DIR/SCRIPTS/build_hss + -c -l + + sudo -E bash -c 'echo 3 > /proc/sys/vm/drop_caches' ;sudo -E ifconfig eth1 add 192.172.0.1 + + $OPENAIRCN_DIR/SCRIPTS/run_epc + -i -r + sleep 10; $OPENAIRCN_DIR/SCRIPTS/run_hss + + $OPENAIRCN_DIR/TEST/autotests/tools/iperf_script 60 lo -u -c 192.172.0.2 -b 10Mbits/s -B 192.172.0.1 False - USRPb210.OAI_EPC.Bandrich.10MHz.FDD.Band_7.DL.1TX.1RX + USRPb210.OAI_EPC_local.Bandrich.5MHz.FDD.Band_7.DL.1TX.1RX + 10 + + + + lte-softmodem + + calisson + stevens + calisson + 390 + /tmp + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf tracking_area_code \"1\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf mobile_country_code \"208\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf mobile_network_code \"92\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf N_RB_DL 50 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf pdsch_referenceSignalPower -29 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf mme_ip_address "ipv4=\"192.170.0.1\";ipv6=\"192:168:30::17\";active=\"yes\";preference=\"ipv4\";" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf downlink_frequency 2660000000L + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf uplink_frequency_offset -120000000 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf tx_gain 90 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf rx_gain 125 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf frame_type \"FDD\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf nb_antennas_rx 1 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf nb_antennas_tx 1 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf ENB_INTERFACE_NAME_FOR_S1_MME \"eth0:3\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf ENB_IPV4_ADDRESS_FOR_S1_MME \"192.170.0.2/24\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf ENB_INTERFACE_NAME_FOR_S1U \"eth0:4\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf ENB_IPV4_ADDRESS_FOR_S1U \"192.170.1.2/24\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf ENB_PORT_FOR_S1U 2152 + $OPENAIR_DIR/cmake_targets/build_oai + --eNB -w USRP -c + sleep 15; sudo -E bash -c 'echo 3 > /proc/sys/vm/drop_caches' ;sudo -E ifconfig eth0:3 192.170.0.2 up ; sudo -E ifconfig eth0:4 192.170.1.2 up; ifconfig + + $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem + -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf -W + + + + + False + + /tmp + + + + sudo -E bash -c 'echo 3 > /proc/sys/vm/drop_caches' + + $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue + + $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 1 ppp0 -s -i 1 -u -f m -B 192.172.0.2 + + throughput_test min=20.0Mbits/sec max=21.0Mbits/sec average=22.0Mbits/sec + + False + $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; sudo -S -E $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue + + /tmp + BUILD/EPC/epc.conf.in MCC \"208\" + BUILD/EPC/epc.conf.in MNC \"92\" + BUILD/EPC/epc.conf.in TAC \"1\" + BUILD/EPC/epc.conf.in MME_INTERFACE_NAME_FOR_S1_MME \"eth0:1\" + BUILD/EPC/epc.conf.in MME_IPV4_ADDRESS_FOR_S1_MME \"192.170.0.1/24\" + BUILD/EPC/epc.conf.in SGW_INTERFACE_NAME_FOR_S1U_S12_S4_UP \"eth0:2\"; + BUILD/EPC/epc.conf.in SGW_IPV4_ADDRESS_FOR_S1U_S12_S4_UP \"192.170.1.1/24\"; + BUILD/EPC/epc.conf.in PGW_INTERFACE_NAME_FOR_SGI \"eth1\" + BUILD/EPC/epc.conf.in PGW_IPV4_ADDRESS_FOR_SGI \"192.168.12.82/24\" + BUILD/EPC/epc.conf.in IPV4_LIST \"192.172.0.0/24\",\"192.172.1.0/24\" + $OPENAIRCN_DIR/SCRIPTS/build_epc + -c -l + $OPENAIRCN_DIR/SCRIPTS/build_hss + -c -l + + sudo -E bash -c 'echo 3 > /proc/sys/vm/drop_caches' ;sudo -E ifconfig eth1 add 192.172.0.1 + + $OPENAIRCN_DIR/SCRIPTS/run_epc + -i -r + sleep 10; $OPENAIRCN_DIR/SCRIPTS/run_hss + + $OPENAIRCN_DIR/TEST/autotests/tools/iperf_script 60 lo -u -c 192.172.0.2 -b 10Mbits/s -B 192.172.0.1 + + + + False + USRPb210.OAI_EPC_local.Bandrich.10MHz.FDD.Band_7.DL.1TX.1RX + 10 + + + + lte-softmodem + + calisson + stevens + calisson + 390 + /tmp + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf tracking_area_code \"1\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf mobile_country_code \"208\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf mobile_network_code \"92\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf N_RB_DL 100 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf pdsch_referenceSignalPower -29 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf mme_ip_address "ipv4=\"192.170.0.1\";ipv6=\"192:168:30::17\";active=\"yes\";preference=\"ipv4\";" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf downlink_frequency 2660000000L + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf uplink_frequency_offset -120000000 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf tx_gain 90 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf rx_gain 125 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf frame_type \"FDD\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf nb_antennas_rx 1 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf nb_antennas_tx 1 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf ENB_INTERFACE_NAME_FOR_S1_MME \"eth0:3\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf ENB_IPV4_ADDRESS_FOR_S1_MME \"192.170.0.2/24\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf ENB_INTERFACE_NAME_FOR_S1U \"eth0:4\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf ENB_IPV4_ADDRESS_FOR_S1U \"192.170.1.2/24\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf ENB_PORT_FOR_S1U 2152 + $OPENAIR_DIR/cmake_targets/build_oai + --eNB -w USRP -c + sleep 15; sudo -E bash -c 'echo 3 > /proc/sys/vm/drop_caches' ;sudo -E ifconfig eth0:3 192.170.0.2 up ; sudo -E ifconfig eth0:4 192.170.1.2 up; ifconfig + + $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem + -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf -W + + + + + False + + /tmp + + + + sudo -E bash -c 'echo 3 > /proc/sys/vm/drop_caches' + + $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue + + $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 1 ppp0 -s -i 1 -u -f m -B 192.172.0.2 + + throughput_test min=40.0Mbits/sec max=42.0Mbits/sec average=44.0Mbits/sec + + False + $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; sudo -S -E $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue + + /tmp + BUILD/EPC/epc.conf.in MCC \"208\" + BUILD/EPC/epc.conf.in MNC \"92\" + BUILD/EPC/epc.conf.in TAC \"1\" + BUILD/EPC/epc.conf.in MME_INTERFACE_NAME_FOR_S1_MME \"eth0:1\" + BUILD/EPC/epc.conf.in MME_IPV4_ADDRESS_FOR_S1_MME \"192.170.0.1/24\" + BUILD/EPC/epc.conf.in SGW_INTERFACE_NAME_FOR_S1U_S12_S4_UP \"eth0:2\"; + BUILD/EPC/epc.conf.in SGW_IPV4_ADDRESS_FOR_S1U_S12_S4_UP \"192.170.1.1/24\"; + BUILD/EPC/epc.conf.in PGW_INTERFACE_NAME_FOR_SGI \"eth1\" + BUILD/EPC/epc.conf.in PGW_IPV4_ADDRESS_FOR_SGI \"192.168.12.82/24\" + BUILD/EPC/epc.conf.in IPV4_LIST \"192.172.0.0/24\",\"192.172.1.0/24\" + $OPENAIRCN_DIR/SCRIPTS/build_epc + -c -l + $OPENAIRCN_DIR/SCRIPTS/build_hss + -c -l + + sudo -E bash -c 'echo 3 > /proc/sys/vm/drop_caches' ;sudo -E ifconfig eth1 add 192.172.0.1 + + $OPENAIRCN_DIR/SCRIPTS/run_epc + -i -r + sleep 10; $OPENAIRCN_DIR/SCRIPTS/run_hss + + $OPENAIRCN_DIR/TEST/autotests/tools/iperf_script 60 lo -u -c 192.172.0.2 -b 10Mbits/s -B 192.172.0.1 + + + + False + USRPb210.OAI_EPC_local.Bandrich.20MHz.FDD.Band_7.DL.1TX.1RX + 10 + + + + lte-softmodem + + calisson + stevens + nano + 390 + /tmp + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf tracking_area_code \"1\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf mobile_country_code \"208\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf mobile_network_code \"92\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf N_RB_DL 25 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf pdsch_referenceSignalPower -26 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf mme_ip_address "ipv4=\"192.168.12.62\";ipv6=\"192:168:30::17\";active=\"yes\";preference=\"ipv4\";" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf downlink_frequency 2660000000L + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf uplink_frequency_offset -120000000 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf tx_gain 90 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf rx_gain 125 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf frame_type \"FDD\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf nb_antennas_rx 1 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf nb_antennas_tx 1 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf ENB_INTERFACE_NAME_FOR_S1_MME \"eth1\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf ENB_IPV4_ADDRESS_FOR_S1_MME \"192.168.12.82/24\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf ENB_INTERFACE_NAME_FOR_S1U \"eth1\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf ENB_IPV4_ADDRESS_FOR_S1U \"192.168.12.82/24\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf ENB_PORT_FOR_S1U 2152 + $OPENAIR_DIR/cmake_targets/build_oai + --eNB -w USRP -c + sleep 15; sudo -E bash -c 'echo 3 > /proc/sys/vm/drop_caches'; ifconfig + + $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem + -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf -W + + + + + False + + /tmp + + + + sudo -E bash -c 'echo 3 > /proc/sys/vm/drop_caches' + + $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue + + $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 1 ppp0 -u -c 192.172.0.1 -b 10Mbits/s -B 192.172.0.2 + + + + False + $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; sudo -S -E $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue + + /tmp + BUILD/EPC/epc.conf.in MCC \"208\" + BUILD/EPC/epc.conf.in MNC \"92\" + BUILD/EPC/epc.conf.in TAC \"1\" + BUILD/EPC/epc.conf.in MME_INTERFACE_NAME_FOR_S1_MME \"eth0\" + BUILD/EPC/epc.conf.in MME_IPV4_ADDRESS_FOR_S1_MME \"192.168.12.62/24\" + BUILD/EPC/epc.conf.in SGW_INTERFACE_NAME_FOR_S1U_S12_S4_UP \"eth0\"; + BUILD/EPC/epc.conf.in SGW_IPV4_ADDRESS_FOR_S1U_S12_S4_UP \"192.168.12.62/24\"; + BUILD/EPC/epc.conf.in PGW_INTERFACE_NAME_FOR_SGI \"eth0\" + BUILD/EPC/epc.conf.in PGW_IPV4_ADDRESS_FOR_SGI \"192.168.12.62/24\" + BUILD/EPC/epc.conf.in IPV4_LIST \"192.172.0.0/24\",\"192.172.1.0/24\" + $OPENAIRCN_DIR/SCRIPTS/build_epc + -c -l + $OPENAIRCN_DIR/SCRIPTS/build_hss + -c -l + + sudo -E bash -c 'echo 3 > /proc/sys/vm/drop_caches' ; sudo -E ifconfig eth1 add 192.172.0.1 + + $OPENAIRCN_DIR/SCRIPTS/run_epc + -r + sleep 10; $OPENAIRCN_DIR/SCRIPTS/run_hss + + $OPENAIRCN_DIR/TEST/autotests/tools/iperf_script 5 lo -s -i 1 -u -f m -B 192.172.0.1 + + throughput_test min=1.0Mbits/sec max=1.0Mbits/sec average=1.0Mbits/sec + + False + USRPb210.OAI_EPC_remote.Bandrich.5MHz.FDD.Band_7.UL.1TX.1RX + 10 + + + + lte-softmodem + + calisson + stevens + nano + 390 + /tmp + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf tracking_area_code \"1\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf mobile_country_code \"208\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf mobile_network_code \"92\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf N_RB_DL 50 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf pdsch_referenceSignalPower -29 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf mme_ip_address "ipv4=\"192.168.12.62\";ipv6=\"192:168:30::17\";active=\"yes\";preference=\"ipv4\";" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf downlink_frequency 2660000000L + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf uplink_frequency_offset -120000000 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf tx_gain 90 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf rx_gain 125 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf frame_type \"FDD\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf nb_antennas_rx 1 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf nb_antennas_tx 1 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf ENB_INTERFACE_NAME_FOR_S1_MME \"eth1\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf ENB_IPV4_ADDRESS_FOR_S1_MME \"192.168.12.82/24\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf ENB_INTERFACE_NAME_FOR_S1U \"eth1\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf ENB_IPV4_ADDRESS_FOR_S1U \"192.168.12.82/24\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf ENB_PORT_FOR_S1U 2152 + $OPENAIR_DIR/cmake_targets/build_oai + --eNB -w USRP -c + sleep 15; sudo -E bash -c 'echo 3 > /proc/sys/vm/drop_caches' ; ifconfig + + $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem + -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf -W + + + + + False + + /tmp + + + + sudo -E bash -c 'echo 3 > /proc/sys/vm/drop_caches' + + $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue + + $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 1 ppp0 -u -c 192.172.0.1 -b 10Mbits/s -B 192.172.0.2 + + + + False + $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; sudo -S -E $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue + + /tmp + BUILD/EPC/epc.conf.in MCC \"208\" + BUILD/EPC/epc.conf.in MNC \"92\" + BUILD/EPC/epc.conf.in TAC \"1\" + BUILD/EPC/epc.conf.in MME_INTERFACE_NAME_FOR_S1_MME \"eth0\" + BUILD/EPC/epc.conf.in MME_IPV4_ADDRESS_FOR_S1_MME \"192.168.12.62/24\" + BUILD/EPC/epc.conf.in SGW_INTERFACE_NAME_FOR_S1U_S12_S4_UP \"eth0\"; + BUILD/EPC/epc.conf.in SGW_IPV4_ADDRESS_FOR_S1U_S12_S4_UP \"192.168.12.62/24\"; + BUILD/EPC/epc.conf.in PGW_INTERFACE_NAME_FOR_SGI \"eth0\" + BUILD/EPC/epc.conf.in PGW_IPV4_ADDRESS_FOR_SGI \"192.168.12.62/24\" + BUILD/EPC/epc.conf.in IPV4_LIST \"192.172.0.0/24\",\"192.172.1.0/24\" + $OPENAIRCN_DIR/SCRIPTS/build_epc + -c -l + $OPENAIRCN_DIR/SCRIPTS/build_hss + -c -l + + sudo -E bash -c 'echo 3 > /proc/sys/vm/drop_caches' ;sudo -E ifconfig eth1 add 192.172.0.1 + + $OPENAIRCN_DIR/SCRIPTS/run_epc + -r + sleep 10; $OPENAIRCN_DIR/SCRIPTS/run_hss + + $OPENAIRCN_DIR/TEST/autotests/tools/iperf_script 5 lo -s -i 1 -u -f m -B 192.172.0.1 + + throughput_test min=1.0Mbits/sec max=1.0Mbits/sec average=1.0Mbits/sec + + False + USRPb210.OAI_EPC_remote.Bandrich.10MHz.FDD.Band_7.UL.1TX.1RX + 10 + + + + lte-softmodem + + calisson + stevens + calisson + 390 + /tmp + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf tracking_area_code \"1\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf mobile_country_code \"208\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf mobile_network_code \"92\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf N_RB_DL 100 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf pdsch_referenceSignalPower -29 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf mme_ip_address "ipv4=\"192.168.12.62\";ipv6=\"192:168:30::17\";active=\"yes\";preference=\"ipv4\";" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf downlink_frequency 2660000000L + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf uplink_frequency_offset -120000000 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf tx_gain 90 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf rx_gain 125 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf frame_type \"FDD\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf nb_antennas_rx 1 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf nb_antennas_tx 1 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf ENB_INTERFACE_NAME_FOR_S1_MME \"eth1\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf ENB_IPV4_ADDRESS_FOR_S1_MME \"192.168.12.82/24\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf ENB_INTERFACE_NAME_FOR_S1U \"eth1\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf ENB_IPV4_ADDRESS_FOR_S1U \"192.168.12.82/24\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf ENB_PORT_FOR_S1U 2152 + $OPENAIR_DIR/cmake_targets/build_oai + --eNB -w USRP -c + sleep 15; sudo -E bash -c 'echo 3 > /proc/sys/vm/drop_caches' ;sudo -E ifconfig eth0:3 192.170.0.2 up ; sudo -E ifconfig eth0:4 192.170.1.2 up; ifconfig + + $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem + -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf -W + + + + + False + + /tmp + + + + sudo -E bash -c 'echo 3 > /proc/sys/vm/drop_caches' + + $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue + + $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 1 ppp0 -u -c 192.172.0.1 -b 10Mbits/s -B 192.172.0.2 + + + + False + $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; sudo -S -E $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue + + /tmp + BUILD/EPC/epc.conf.in MCC \"208\" + BUILD/EPC/epc.conf.in MNC \"92\" + BUILD/EPC/epc.conf.in TAC \"1\" + BUILD/EPC/epc.conf.in MME_INTERFACE_NAME_FOR_S1_MME \"eth0\" + BUILD/EPC/epc.conf.in MME_IPV4_ADDRESS_FOR_S1_MME \"192.168.12.62/24\" + BUILD/EPC/epc.conf.in SGW_INTERFACE_NAME_FOR_S1U_S12_S4_UP \"eth0\"; + BUILD/EPC/epc.conf.in SGW_IPV4_ADDRESS_FOR_S1U_S12_S4_UP \"192.168.12.62/24\"; + BUILD/EPC/epc.conf.in PGW_INTERFACE_NAME_FOR_SGI \"eth0\" + BUILD/EPC/epc.conf.in PGW_IPV4_ADDRESS_FOR_SGI \"192.168.12.62/24\" + BUILD/EPC/epc.conf.in IPV4_LIST \"192.172.0.0/24\",\"192.172.1.0/24\" + $OPENAIRCN_DIR/SCRIPTS/build_epc + -c -l + $OPENAIRCN_DIR/SCRIPTS/build_hss + -c -l + + sudo -E bash -c 'echo 3 > /proc/sys/vm/drop_caches' ; sudo -E ifconfig eth1 add 192.172.0.1 + + $OPENAIRCN_DIR/SCRIPTS/run_epc + -r + sleep 10; $OPENAIRCN_DIR/SCRIPTS/run_hss + + $OPENAIRCN_DIR/TEST/autotests/tools/iperf_script 5 lo -s -i 1 -u -f m -B 192.172.0.1 + + throughput_test min=1.0Mbits/sec max=1.0Mbits/sec average=1.0Mbits/sec + + False + USRPb210.OAI_EPC_remote.Bandrich.20MHz.FDD.Band_7.UL.1TX.1RX + 10 + + + + lte-softmodem + + calisson + stevens + calisson + 390 + /tmp + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf tracking_area_code \"1\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf mobile_country_code \"208\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf mobile_network_code \"92\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf N_RB_DL 25 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf pdsch_referenceSignalPower -26 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf mme_ip_address "ipv4=\"192.168.12.62\";ipv6=\"192:168:30::17\";active=\"yes\";preference=\"ipv4\";" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf downlink_frequency 2660000000L + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf uplink_frequency_offset -120000000 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf tx_gain 90 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf rx_gain 125 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf frame_type \"FDD\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf nb_antennas_rx 1 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf nb_antennas_tx 1 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf ENB_INTERFACE_NAME_FOR_S1_MME \"eth1\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf ENB_IPV4_ADDRESS_FOR_S1_MME \"192.168.12.82/24\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf ENB_INTERFACE_NAME_FOR_S1U \"eth1\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf ENB_IPV4_ADDRESS_FOR_S1U \"192.168.12.82/24\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf ENB_PORT_FOR_S1U 2152 + $OPENAIR_DIR/cmake_targets/build_oai + --eNB -w USRP -c + sleep 15; sudo -E bash -c 'echo 3 > /proc/sys/vm/drop_caches' ; ifconfig + + $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem + -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf -W + + + + + False + + /tmp + + + + sudo -E bash -c 'echo 3 > /proc/sys/vm/drop_caches' + + $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue + + $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 1 ppp0 -s -i 1 -u -f m -B 192.172.0.2 + + throughput_test min=10.0Mbits/sec max=10.5Mbits/sec average=11.0Mbits/sec + + False + $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; sudo -S -E $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue + + /tmp + BUILD/EPC/epc.conf.in MCC \"208\" + BUILD/EPC/epc.conf.in MNC \"92\" + BUILD/EPC/epc.conf.in TAC \"1\" + BUILD/EPC/epc.conf.in MME_INTERFACE_NAME_FOR_S1_MME \"eth0:1\" + BUILD/EPC/epc.conf.in MME_IPV4_ADDRESS_FOR_S1_MME \"192.170.0.1/24\" + BUILD/EPC/epc.conf.in SGW_INTERFACE_NAME_FOR_S1U_S12_S4_UP \"eth0:2\"; + BUILD/EPC/epc.conf.in SGW_IPV4_ADDRESS_FOR_S1U_S12_S4_UP \"192.170.1.1/24\"; + BUILD/EPC/epc.conf.in PGW_INTERFACE_NAME_FOR_SGI \"eth1\" + BUILD/EPC/epc.conf.in PGW_IPV4_ADDRESS_FOR_SGI \"192.168.12.82/24\" + BUILD/EPC/epc.conf.in IPV4_LIST \"192.172.0.0/24\",\"192.172.1.0/24\" + $OPENAIRCN_DIR/SCRIPTS/build_epc + -c -l + $OPENAIRCN_DIR/SCRIPTS/build_hss + -c -l + + sudo -E bash -c 'echo 3 > /proc/sys/vm/drop_caches' ;sudo -E ifconfig eth1 add 192.172.0.1 + + $OPENAIRCN_DIR/SCRIPTS/run_epc + -r + sleep 10; $OPENAIRCN_DIR/SCRIPTS/run_hss + + $OPENAIRCN_DIR/TEST/autotests/tools/iperf_script 60 lo -u -c 192.172.0.2 -b 10Mbits/s -B 192.172.0.1 + + + + False + USRPb210.OAI_EPC_remote.Bandrich.5MHz.FDD.Band_7.DL.1TX.1RX + 10 + + + + lte-softmodem + + calisson + stevens + nano + 390 + /tmp + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf tracking_area_code \"1\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf mobile_country_code \"208\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf mobile_network_code \"92\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf N_RB_DL 50 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf pdsch_referenceSignalPower -29 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf mme_ip_address "ipv4=\"192.168.12.62\";ipv6=\"192:168:30::17\";active=\"yes\";preference=\"ipv4\";" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf downlink_frequency 2660000000L + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf uplink_frequency_offset -120000000 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf tx_gain 90 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf rx_gain 125 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf frame_type \"FDD\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf nb_antennas_rx 1 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf nb_antennas_tx 1 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf ENB_INTERFACE_NAME_FOR_S1_MME \"eth1\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf ENB_IPV4_ADDRESS_FOR_S1_MME \"192.168.12.82/24\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf ENB_INTERFACE_NAME_FOR_S1U \"eth1\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf ENB_IPV4_ADDRESS_FOR_S1U \"192.168.12.82/24\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf ENB_PORT_FOR_S1U 2152 + $OPENAIR_DIR/cmake_targets/build_oai + --eNB -w USRP -c + sleep 15; sudo -E bash -c 'echo 3 > /proc/sys/vm/drop_caches' ; ifconfig + + $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem + -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf -W + + + + + False + + /tmp + + + + sudo -E bash -c 'echo 3 > /proc/sys/vm/drop_caches' + + $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue + + $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 1 ppp0 -s -i 1 -u -f m -B 192.172.0.2 + + throughput_test min=20.0Mbits/sec max=21.0Mbits/sec average=22.0Mbits/sec + + False + $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; sudo -S -E $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue + + /tmp + BUILD/EPC/epc.conf.in MCC \"208\" + BUILD/EPC/epc.conf.in MNC \"92\" + BUILD/EPC/epc.conf.in TAC \"1\" + BUILD/EPC/epc.conf.in MME_INTERFACE_NAME_FOR_S1_MME \"eth0:1\" + BUILD/EPC/epc.conf.in MME_IPV4_ADDRESS_FOR_S1_MME \"192.170.0.1/24\" + BUILD/EPC/epc.conf.in SGW_INTERFACE_NAME_FOR_S1U_S12_S4_UP \"eth0:2\"; + BUILD/EPC/epc.conf.in SGW_IPV4_ADDRESS_FOR_S1U_S12_S4_UP \"192.170.1.1/24\"; + BUILD/EPC/epc.conf.in PGW_INTERFACE_NAME_FOR_SGI \"eth1\" + BUILD/EPC/epc.conf.in PGW_IPV4_ADDRESS_FOR_SGI \"192.168.12.82/24\" + BUILD/EPC/epc.conf.in IPV4_LIST \"192.172.0.0/24\",\"192.172.1.0/24\" + $OPENAIRCN_DIR/SCRIPTS/build_epc + -c -l + $OPENAIRCN_DIR/SCRIPTS/build_hss + -c -l + + sudo -E bash -c 'echo 3 > /proc/sys/vm/drop_caches' ;sudo -E ifconfig eth1 add 192.172.0.1 + + $OPENAIRCN_DIR/SCRIPTS/run_epc + -r + sleep 10; $OPENAIRCN_DIR/SCRIPTS/run_hss + + $OPENAIRCN_DIR/TEST/autotests/tools/iperf_script 60 lo -u -c 192.172.0.2 -b 10Mbits/s -B 192.172.0.1 + + + + False + USRPb210.OAI_EPC_remote.Bandrich.10MHz.FDD.Band_7.DL.1TX.1RX + 10 + + + + lte-softmodem + + calisson + stevens + nano + 390 + /tmp + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf tracking_area_code \"1\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf mobile_country_code \"208\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf mobile_network_code \"92\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf N_RB_DL 100 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf pdsch_referenceSignalPower -29 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf mme_ip_address "ipv4=\"192.168.12.62\";ipv6=\"192:168:30::17\";active=\"yes\";preference=\"ipv4\";" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf downlink_frequency 2660000000L + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf uplink_frequency_offset -120000000 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf tx_gain 90 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf rx_gain 125 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf frame_type \"FDD\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf nb_antennas_rx 1 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf nb_antennas_tx 1 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf ENB_INTERFACE_NAME_FOR_S1_MME \"eth1\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf ENB_IPV4_ADDRESS_FOR_S1_MME \"192.168.12.82/24\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf ENB_INTERFACE_NAME_FOR_S1U \"eth1\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf ENB_IPV4_ADDRESS_FOR_S1U \"192.168.12.82/24\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf ENB_PORT_FOR_S1U 2152 + $OPENAIR_DIR/cmake_targets/build_oai + --eNB -w USRP -c + sleep 15; sudo -E bash -c 'echo 3 > /proc/sys/vm/drop_caches' ; ifconfig + + $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem + -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf -W + + + + + False + + /tmp + + + + sudo -E bash -c 'echo 3 > /proc/sys/vm/drop_caches' + + $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue + + $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 1 ppp0 -s -i 1 -u -f m -B 192.172.0.2 + + throughput_test min=20.0Mbits/sec max=21.0Mbits/sec average=22.0Mbits/sec + + False + $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; sudo -S -E $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue + + /tmp + BUILD/EPC/epc.conf.in MCC \"208\" + BUILD/EPC/epc.conf.in MNC \"92\" + BUILD/EPC/epc.conf.in TAC \"1\" + BUILD/EPC/epc.conf.in MME_INTERFACE_NAME_FOR_S1_MME \"eth0:1\" + BUILD/EPC/epc.conf.in MME_IPV4_ADDRESS_FOR_S1_MME \"192.170.0.1/24\" + BUILD/EPC/epc.conf.in SGW_INTERFACE_NAME_FOR_S1U_S12_S4_UP \"eth0:2\"; + BUILD/EPC/epc.conf.in SGW_IPV4_ADDRESS_FOR_S1U_S12_S4_UP \"192.170.1.1/24\"; + BUILD/EPC/epc.conf.in PGW_INTERFACE_NAME_FOR_SGI \"eth1\" + BUILD/EPC/epc.conf.in PGW_IPV4_ADDRESS_FOR_SGI \"192.168.12.82/24\" + BUILD/EPC/epc.conf.in IPV4_LIST \"192.172.0.0/24\",\"192.172.1.0/24\" + $OPENAIRCN_DIR/SCRIPTS/build_epc + -c -l + $OPENAIRCN_DIR/SCRIPTS/build_hss + -c -l + + sudo -E bash -c 'echo 3 > /proc/sys/vm/drop_caches' ;sudo -E ifconfig eth1 add 192.172.0.1 + + $OPENAIRCN_DIR/SCRIPTS/run_epc + -r + sleep 10; $OPENAIRCN_DIR/SCRIPTS/run_hss + + $OPENAIRCN_DIR/TEST/autotests/tools/iperf_script 60 lo -u -c 192.172.0.2 -b 10Mbits/s -B 192.172.0.1 + + + + False + USRPb210.OAI_EPC_remote.Bandrich.20MHz.FDD.Band_7.DL.1TX.1RX 10 @@ -2309,7 +2906,7 @@ $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 45; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue - $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 1 ppp0 -u -c 192.172.0.1 -b 10Mbits/s -t 330 -B 192.172.0.2 + $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 1 ppp0 -u -c 192.172.0.1 -b 10Mbits/s -B 192.172.0.2 @@ -2335,7 +2932,7 @@ $OPENAIRCN_DIR/TEST/autotests/tools/iperf_script 5 lo -s -i 1 -u -f m -B 192.172.0.1 - throughput_test min=1.0Mbits/sec max=1.0Mbits/sec average=1.0Mbits/sec duration=300.0s + throughput_test min=1.0Mbits/sec max=1.0Mbits/sec average=1.0Mbits/sec True USRPx310.ALU_EPC.Bandrich.5MHz.FDD.Band_7.UL.1TX.1RX @@ -2388,7 +2985,7 @@ $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 45; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue - $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 1 ppp0 -u -c 192.172.0.1 -b 10Mbits/s -t 330 -B 192.172.0.2 + $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 1 ppp0 -u -c 192.172.0.1 -b 10Mbits/s -B 192.172.0.2 @@ -2414,7 +3011,7 @@ $OPENAIRCN_DIR/TEST/autotests/tools/iperf_script 5 lo -s -i 1 -u -f m -B 192.172.0.1 - throughput_test min=1.0Mbits/sec max=1.0Mbits/sec average=1.0Mbits/sec duration=300.0s + throughput_test min=1.0Mbits/sec max=1.0Mbits/sec average=1.0Mbits/sec True USRPx310.ALU_EPC.Bandrich.10MHz.FDD.Band_7.UL.1TX.1RX @@ -2466,7 +3063,7 @@ $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 45; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue - $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 1 ppp0 -u -c 192.172.0.1 -b 10Mbits/s -t 330 -B 192.172.0.2 + $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 1 ppp0 -u -c 192.172.0.1 -b 10Mbits/s -B 192.172.0.2 @@ -2492,7 +3089,7 @@ $OPENAIRCN_DIR/TEST/autotests/tools/iperf_script 5 lo -s -i 1 -u -f m -B 192.172.0.1 - throughput_test min=1.0Mbits/sec max=1.0Mbits/sec average=1.0Mbits/sec duration=300.0s + throughput_test min=1.0Mbits/sec max=1.0Mbits/sec average=1.0Mbits/sec True USRPx310.ALU_EPC.Bandrich.20MHz.FDD.Band_7.UL.1TX.1RX @@ -2548,7 +3145,7 @@ True sudo -S -E $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue - throughput_test min=4.0Mbits/sec max=5.0Mbits/sec average=4.0Mbits/sec duration=300.0s + throughput_test min=4.0Mbits/sec max=5.0Mbits/sec average=4.0Mbits/sec /tmp @@ -2568,7 +3165,7 @@ /opt/hss_sim0609/starthss >> /dev/null ; sleep 3000 - $OPENAIRCN_DIR/TEST/autotests/tools/iperf_script 60 lo -u -c 192.172.0.2 -b 10Mbits/s -t 330 -B 192.172.0.1 + $OPENAIRCN_DIR/TEST/autotests/tools/iperf_script 60 lo -u -c 192.172.0.2 -b 10Mbits/s -B 192.172.0.1 True @@ -2625,7 +3222,7 @@ True sudo -S -E $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue - throughput_test min=8.0Mbits/sec max=9.0Mbits/sec average=8.5Mbits/sec duration=300.0s + throughput_test min=8.0Mbits/sec max=9.0Mbits/sec average=8.5Mbits/sec /tmp @@ -2645,7 +3242,7 @@ /opt/hss_sim0609/starthss >> /dev/null ; sleep 3000 - $OPENAIRCN_DIR/TEST/autotests/tools/iperf_script 60 lo -u -c 192.172.0.2 -b 10Mbits/s -t 330 -B 192.172.0.1 + $OPENAIRCN_DIR/TEST/autotests/tools/iperf_script 60 lo -u -c 192.172.0.2 -b 10Mbits/s -B 192.172.0.1 True @@ -2702,7 +3299,7 @@ True sudo -S -E $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue - throughput_test min=15.0Mbits/sec max=15.0Mbits/sec average=15.0Mbits/sec duration=300.0s + throughput_test min=15.0Mbits/sec max=15.0Mbits/sec average=15.0Mbits/sec /tmp @@ -2722,7 +3319,7 @@ /opt/hss_sim0609/starthss >> /dev/null ; sleep 3000 - $OPENAIRCN_DIR/TEST/autotests/tools/iperf_script 60 lo -u -c 192.172.0.2 -b 10Mbits/s -t 330 -B 192.172.0.1 + $OPENAIRCN_DIR/TEST/autotests/tools/iperf_script 60 lo -u -c 192.172.0.2 -b 10Mbits/s -B 192.172.0.1 True @@ -2778,7 +3375,7 @@ $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 45; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue - $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 1 ppp0 -u -c 192.172.0.1 -b 10Mbits/s -t 330 -B 192.172.0.2 + $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 1 ppp0 -u -c 192.172.0.1 -b 10Mbits/s -B 192.172.0.2 @@ -2804,7 +3401,7 @@ $OPENAIRCN_DIR/TEST/autotests/tools/iperf_script 5 lo -s -i 1 -u -f m -B 192.172.0.1 - throughput_test min=1.0Mbits/sec max=1.0Mbits/sec average=1.0Mbits/sec duration=300.0s + throughput_test min=1.0Mbits/sec max=1.0Mbits/sec average=1.0Mbits/sec True EXMIMO.ALU_EPC.Bandrich.5MHz.FDD.Band_7.UL.1TX.1RX @@ -2857,7 +3454,7 @@ $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 45; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue - $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 1 ppp0 -u -c 192.172.0.1 -b 10Mbits/s -t 330 -B 192.172.0.2 + $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 1 ppp0 -u -c 192.172.0.1 -b 10Mbits/s -B 192.172.0.2 @@ -2883,7 +3480,7 @@ $OPENAIRCN_DIR/TEST/autotests/tools/iperf_script 5 lo -s -i 1 -u -f m -B 192.172.0.1 - throughput_test min=1.0Mbits/sec max=1.0Mbits/sec average=1.0Mbits/sec duration=300.0s + throughput_test min=1.0Mbits/sec max=1.0Mbits/sec average=1.0Mbits/sec True EXMIMO.ALU_EPC.Bandrich.10MHz.FDD.Band_7.UL.1TX.1RX @@ -2935,7 +3532,7 @@ $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 45; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue - $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 1 ppp0 -u -c 192.172.0.1 -b 10Mbits/s -t 330 -B 192.172.0.2 + $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 1 ppp0 -u -c 192.172.0.1 -b 10Mbits/s -B 192.172.0.2 @@ -2961,7 +3558,7 @@ $OPENAIRCN_DIR/TEST/autotests/tools/iperf_script 5 lo -s -i 1 -u -f m -B 192.172.0.1 - throughput_test min=1.0Mbits/sec max=1.0Mbits/sec average=1.0Mbits/sec duration=300.0s + throughput_test min=1.0Mbits/sec max=1.0Mbits/sec average=1.0Mbits/sec True EXMIMO.ALU_EPC.Bandrich.20MHz.FDD.Band_7.UL.1TX.1RX @@ -3017,7 +3614,7 @@ True sudo -S -E $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue - throughput_test min=4.0Mbits/sec max=5.0Mbits/sec average=4.0Mbits/sec duration=300.0s + throughput_test min=4.0Mbits/sec max=5.0Mbits/sec average=4.0Mbits/sec /tmp @@ -3037,7 +3634,7 @@ /opt/hss_sim0609/starthss >> /dev/null ; sleep 3000 - $OPENAIRCN_DIR/TEST/autotests/tools/iperf_script 60 lo -u -c 192.172.0.2 -b 10Mbits/s -t 330 -B 192.172.0.1 + $OPENAIRCN_DIR/TEST/autotests/tools/iperf_script 60 lo -u -c 192.172.0.2 -b 10Mbits/s -B 192.172.0.1 True @@ -3094,7 +3691,7 @@ True sudo -S -E $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue - throughput_test min=8.0Mbits/sec max=9.0Mbits/sec average=8.5Mbits/sec duration=300.0s + throughput_test min=8.0Mbits/sec max=9.0Mbits/sec average=8.5Mbits/sec /tmp @@ -3114,7 +3711,7 @@ /opt/hss_sim0609/starthss >> /dev/null ; sleep 3000 - $OPENAIRCN_DIR/TEST/autotests/tools/iperf_script 60 lo -u -c 192.172.0.2 -b 10Mbits/s -t 330 -B 192.172.0.1 + $OPENAIRCN_DIR/TEST/autotests/tools/iperf_script 60 lo -u -c 192.172.0.2 -b 10Mbits/s -B 192.172.0.1 True @@ -3171,7 +3768,7 @@ True sudo -S -E $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue - throughput_test min=15.0Mbits/sec max=15.0Mbits/sec average=15.0Mbits/sec duration=300.0s + throughput_test min=15.0Mbits/sec max=15.0Mbits/sec average=15.0Mbits/sec /tmp @@ -3191,7 +3788,7 @@ /opt/hss_sim0609/starthss >> /dev/null ; sleep 3000 - $OPENAIRCN_DIR/TEST/autotests/tools/iperf_script 60 lo -u -c 192.172.0.2 -b 10Mbits/s -t 330 -B 192.172.0.1 + $OPENAIRCN_DIR/TEST/autotests/tools/iperf_script 60 lo -u -c 192.172.0.2 -b 10Mbits/s -B 192.172.0.1 True @@ -3199,84 +3796,6 @@ 10 - - lte-softmodem - - calisson - stevens - calisson - 60 - /tmp - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf tracking_area_code \"1\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf mobile_country_code \"208\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf mobile_network_code \"92\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf N_RB_DL 50 - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf tracking_area_code \"1\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf mobile_country_code \"208\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf mobile_network_code \"92\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf N_RB_DL 50 - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf mme_ip_address "ipv4=\"192.168.12.62\";ipv6=\"192:168:30::17\";active=\"yes\";preference=\"ipv4\";" - $OPENAIR_DIR/cmake_targets/build_oai - --eNB -w USRP -c - - - $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem - -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf -W - - - - - True - - /tmp - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf tracking_area_code \"1\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf mobile_country_code \"208\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf mobile_network_code \"92\" - $OPENAIR_DIR/cmake_targets/build_oai - --eNB -w USRP -c - - - $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue - - ping 192.172.0.1 - - - - True - - /tmp - BUILD/EPC/epc.local.enb.conf.in MCC \"208\" - BUILD/EPC/epc.local.enb.conf.in MNC \"92\" - BUILD/EPC/epc.local.enb.conf.in TAC \"1\" - BUILD/EPC/epc.local.enb.conf.in PGW_INTERFACE_NAME_FOR_SGI \"eth1\" - BUILD/EPC/epc.local.enb.conf.in PGW_IPV4_ADDRESS_FOR_SGI \"192.168.12.82/24\" - BUILD/EPC/epc.conf.in MCC \"208\" - BUILD/EPC/epc.conf.in MNC \"92\" - BUILD/EPC/epc.conf.in TAC \"1\" - BUILD/EPC/epc.conf.in PGW_INTERFACE_NAME_FOR_SGI \"eth1\" - BUILD/EPC/epc.conf.in PGW_IPV4_ADDRESS_FOR_SGI \"192.168.12.62/24\" - BUILD/EPC/epc.conf.in MME_IPV4_ADDRESS_FOR_S1_MME \"192.168.12.62/24\" - BUILD/EPC/epc.conf.in SGW_IPV4_ADDRESS_FOR_S1U_S12_S4_UP \"192.168.12.62/24\" - BUILD/EPC/epc.conf.in PGW_IPV4_ADDRESS_FOR_SGI \"192.168.12.62/24\" - SCRIPTS/build_epc - -c -l - SCRIPTS/build_hss - -c -l - - - - SCRIPTS/run_epc -l - - SCRIPTS/run_hss - - iperf -s - - - - True - - 10 - From 60a3af3e988e21ee5b0add29e1e4ff578a080389 Mon Sep 17 00:00:00 2001 From: "aikaterini.trilyraki" Date: Thu, 21 Jan 2016 13:49:56 +0100 Subject: [PATCH 167/263] perpetual scheduling turned on / extra logging in CCE allocation --- openair2/LAYER2/MAC/eNB_scheduler_primitives.c | 12 ++++++++++-- openair2/LAYER2/MAC/eNB_scheduler_ulsch.c | 2 +- openair2/RRC/LITE/rrc_eNB.c | 6 ++++-- 3 files changed, 15 insertions(+), 5 deletions(-) diff --git a/openair2/LAYER2/MAC/eNB_scheduler_primitives.c b/openair2/LAYER2/MAC/eNB_scheduler_primitives.c index 829185d2a7..20b1f6d735 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_primitives.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_primitives.c @@ -997,7 +997,7 @@ int allocate_CCEs(int module_idP, DCI_PDU *DCI_pdu = &eNB_mac_inst[module_idP].common_channels[CC_idP].DCI_pdu; int nCCE_max = mac_xface->get_nCCE_max(module_idP,CC_idP,DCI_pdu->num_pdcch_symbols,subframeP); int fCCE; - int i; + int i,j; int allocation_is_feasible = 1; DCI_ALLOC_t *dci_alloc; @@ -1046,7 +1046,15 @@ int allocate_CCEs(int module_idP, allocation_is_feasible = 0; LOG_I(MAC,"subframe %d: Dropping Allocation for RNTI %x\n", subframeP,dci_alloc->rnti); - + for (j=0;j<=i;j++){ + + LOG_I(MAC,"DCI %d/%d (%d,%d) : rnti %x dci format %d, aggreg %d nCCE %d / %d (num_pdcch_symbols %d)\n", + i,DCI_pdu->Num_common_dci+DCI_pdu->Num_ue_spec_dci, + DCI_pdu->Num_common_dci,DCI_pdu->Num_ue_spec_dci, + DCI_pdu->dci_alloc[j].rnti,DCI_pdu->dci_alloc[j].format, + 1<dci_alloc[j].L, + DCI_pdu->nCCE,nCCE_max,DCI_pdu->num_pdcch_symbols); + } } else { DCI_pdu->num_pdcch_symbols++; diff --git a/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c b/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c index b3a4319b6b..493ff11d33 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_ulsch.c @@ -760,7 +760,7 @@ void schedule_ulsch_rnti(module_id_t module_idP, LOG_T(MAC,"[eNB %d] Frame %d, subframeP %d, UE %d CC %d : got harq pid %d round %d (rnti %x,mode %s)\n", module_idP,frameP,subframeP,UE_id,CC_id, harq_pid, round,rnti,mode_string[eNB_UE_stats->mode]); -#undef EXMIMO_IOT + //#undef EXMIMO_IOT #ifndef EXMIMO_IOT if (((UE_is_to_be_scheduled(module_idP,CC_id,UE_id)>0)) || (round>0) || ((frameP%10)==0)) diff --git a/openair2/RRC/LITE/rrc_eNB.c b/openair2/RRC/LITE/rrc_eNB.c index 96fc8a4b8f..1d0b5f2902 100644 --- a/openair2/RRC/LITE/rrc_eNB.c +++ b/openair2/RRC/LITE/rrc_eNB.c @@ -3700,7 +3700,8 @@ rrc_eNB_decode_ccch( * the current one must be removed from MAC/PHY (zombie UE) */ if ((ue_context_p = rrc_eNB_ue_context_random_exist(ctxt_pP, random_value))) { - AssertFatal(0 == 1, "TODO: remove UE from MAC/PHY (how?)"); +#warning "TODO: random_exist: remove UE from MAC/PHY (how?)" + // AssertFatal(0 == 1, "TODO: remove UE from MAC/PHY (how?)"); ue_context_p = NULL; } else { ue_context_p = rrc_eNB_get_next_free_ue_context(ctxt_pP, random_value); @@ -3712,7 +3713,8 @@ rrc_eNB_decode_ccch( m_tmsi_t m_tmsi = BIT_STRING_to_uint32(&s_TMSI.m_TMSI); random_value = (((uint64_t)mme_code) << 32) | m_tmsi; if ((ue_context_p = rrc_eNB_ue_context_stmsi_exist(ctxt_pP, mme_code, m_tmsi))) { - AssertFatal(0 == 1, "TODO: remove UE from MAC/PHY (how?)"); +#warning "TODO: stmsi_exist: remove UE from MAC/PHY (how?)" + // AssertFatal(0 == 1, "TODO: remove UE from MAC/PHY (how?)"); ue_context_p = NULL; } else { ue_context_p = rrc_eNB_get_next_free_ue_context(ctxt_pP, NOT_A_RANDOM_UE_IDENTITY); From 6066ebb7641397d6d77feb92ef75b47f587bb19f Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Thu, 21 Jan 2016 14:22:55 +0100 Subject: [PATCH 168/263] added tests for OAI EPC --- cmake_targets/autotests/README.txt | 61 +++++++++++++--------- cmake_targets/autotests/test_case_list.xml | 6 +-- 2 files changed, 39 insertions(+), 28 deletions(-) diff --git a/cmake_targets/autotests/README.txt b/cmake_targets/autotests/README.txt index a370ae573d..7c3ae65070 100644 --- a/cmake_targets/autotests/README.txt +++ b/cmake_targets/autotests/README.txt @@ -98,43 +98,54 @@ Obj.# Case# Test# Description 01 55 lte-softmodem tests with USRP B210 RF as eNB and ALU EPC w/ Bandrich COTS UE for TX/1RX, 2TX/2RX -01 55 00 Band 7 FDD 5MHz UL Throughput for 60 sec for 1TX/1RX -01 55 01 Band 7 FDD 10MHz UL Throughput for 60 sec for 1TX/1RX -01 55 02 Band 7 FDD 20MHz UL Throughput for 60 sec for 1TX/1RX -01 55 03 Band 7 FDD 5MHz DL Throughput for 60 sec for 1TX/1RX -01 55 04 Band 7 FDD 10MHz DL Throughput for 60 sec for 1TX/1RX -01 55 05 Band 7 FDD 20MHz DL Throughput for 60 sec for 1TX/1RX -01 55 06 Band 7 FDD 5MHz UL Throughput for 60 sec for 2TX/2RX -01 55 07 Band 7 FDD 10MHz UL Throughput for 60 sec for 2TX/2RX -01 55 08 Band 7 FDD 20MHz UL Throughput for 60 sec for 2TX/2RX -01 55 09 Band 7 FDD 5MHz DL Throughput for 60 sec for 2TX/2RX -01 55 10 Band 7 FDD 10MHz DL Throughput for 60 sec for 2TX/2RX -01 55 11 Band 7 FDD 20MHz DL Throughput for 60 sec for 2TX/2RX +01 55 00 Band 7 FDD 5MHz UL Throughput for 300 sec for 1TX/1RX +01 55 01 Band 7 FDD 10MHz UL Throughput for 300 sec for 1TX/1RX +01 55 02 Band 7 FDD 20MHz UL Throughput for 300 sec for 1TX/1RX +01 55 03 Band 7 FDD 5MHz DL Throughput for 300 sec for 1TX/1RX +01 55 04 Band 7 FDD 10MHz DL Throughput for 300 sec for 1TX/1RX +01 55 05 Band 7 FDD 20MHz DL Throughput for 300 sec for 1TX/1RX +01 55 06 Band 7 FDD 5MHz UL Throughput for 300 sec for 2TX/2RX +01 55 07 Band 7 FDD 10MHz UL Throughput for 300 sec for 2TX/2RX +01 55 08 Band 7 FDD 20MHz UL Throughput for 300 sec for 2TX/2RX +01 55 09 Band 7 FDD 5MHz DL Throughput for 300 sec for 2TX/2RX +01 55 10 Band 7 FDD 10MHz DL Throughput for 300 sec for 2TX/2RX +01 55 11 Band 7 FDD 20MHz DL Throughput for 300 sec for 2TX/2RX 01 56 lte-softmodem tests with USRP B210 RF as eNB and OAI EPC (eNB and EPC are on same machines) w/ Bandrich COTS UE - +01 56 00 Band 7 FDD 5MHz UL Throughput for 300 sec for 1TX/1RX +01 56 01 Band 7 FDD 10MHz UL Throughput for 300 sec for 1TX/1RX +01 56 02 Band 7 FDD 20MHz UL Throughput for 300 sec for 1TX/1RX +01 56 03 Band 7 FDD 5MHz DL Throughput for 300 sec for 1TX/1RX +01 56 04 Band 7 FDD 10MHz DL Throughput for 300 sec for 1TX/1RX +01 56 05 Band 7 FDD 20MHz DL Throughput for 300 sec for 1TX/1RX 01 57 lte-softmodem tests with USRP B210 RF as eNB and OAI EPC (eNB and EPC are on different machines) w/ Bandrich COTS UE +01 57 00 Band 7 FDD 5MHz UL Throughput for 300 sec for 1TX/1RX +01 57 01 Band 7 FDD 10MHz UL Throughput for 300 sec for 1TX/1RX +01 57 02 Band 7 FDD 20MHz UL Throughput for 300 sec for 1TX/1RX +01 57 03 Band 7 FDD 5MHz DL Throughput for 300 sec for 1TX/1RX +01 57 04 Band 7 FDD 10MHz DL Throughput for 300 sec for 1TX/1RX +01 57 05 Band 7 FDD 20MHz DL Throughput for 300 sec for 1TX/1RX 01 58 lte-softmodem tests with USRP X310 RF as eNB and ALU EPC w/ Bandrich COTS UE for `TX/1RX, 2TX/2RX -01 58 00 Band 7 FDD 5MHz UL Throughput for 60 sec for 1TX/1RX -01 58 01 Band 7 FDD 10MHz UL Throughput for 60 sec for 1TX/1RX -01 58 02 Band 7 FDD 20MHz UL Throughput for 60 sec for 1TX/1RX -01 58 03 Band 7 FDD 5MHz DL Throughput for 60 sec for 1TX/1RX -01 58 04 Band 7 FDD 10MHz DL Throughput for 60 sec for 1TX/1RX -01 58 05 Band 7 FDD 20MHz DL Throughput for 60 sec for 1TX/1RX +01 58 00 Band 7 FDD 5MHz UL Throughput for 300 sec for 1TX/1RX +01 58 01 Band 7 FDD 10MHz UL Throughput for 300 sec for 1TX/1RX +01 58 02 Band 7 FDD 20MHz UL Throughput for 300 sec for 1TX/1RX +01 58 03 Band 7 FDD 5MHz DL Throughput for 300 sec for 1TX/1RX +01 58 04 Band 7 FDD 10MHz DL Throughput for 300 sec for 1TX/1RX +01 58 05 Band 7 FDD 20MHz DL Throughput for 300 sec for 1TX/1RX 01 59 lte-softmodem tests with USRP X310 RF as eNB and OAI EPC (eNB and EPC are on same machines) w/ Bandrich COTS UE 01 61 lte-softmodem tests with USRP X310 RF as eNB and OAI EPC (eNB and EPC are on different machines) w/ Bandrich COTS UE 01 61 lte-softmodem tests with EXMIMO RF as eNB and ALU EPC w/ Bandrich COTS UE for `TX/1RX, 2TX/2RX -01 61 00 Band 7 FDD 5MHz UL Throughput for 60 sec for 1TX/1RX -01 61 01 Band 7 FDD 10MHz UL Throughput for 60 sec for 1TX/1RX -01 61 02 Band 7 FDD 20MHz UL Throughput for 60 sec for 1TX/1RX -01 61 03 Band 7 FDD 5MHz DL Throughput for 60 sec for 1TX/1RX -01 61 04 Band 7 FDD 10MHz DL Throughput for 60 sec for 1TX/1RX -01 61 05 Band 7 FDD 20MHz DL Throughput for 60 sec for 1TX/1RX +01 61 00 Band 7 FDD 5MHz UL Throughput for 300 sec for 1TX/1RX +01 61 01 Band 7 FDD 10MHz UL Throughput for 300 sec for 1TX/1RX +01 61 02 Band 7 FDD 20MHz UL Throughput for 300 sec for 1TX/1RX +01 61 03 Band 7 FDD 5MHz DL Throughput for 300 sec for 1TX/1RX +01 61 04 Band 7 FDD 10MHz DL Throughput for 300 sec for 1TX/1RX +01 61 05 Band 7 FDD 20MHz DL Throughput for 300 sec for 1TX/1RX 01 62 lte-softmodem tests with EXMIMO RF as eNB and OAI EPC (eNB and EPC are on same machines) w/ Bandrich COTS UE 01 63 lte-softmodem tests with EXMIMO RF as eNB and OAI EPC (eNB and EPC are on different machines) w/ Bandrich COTS UE diff --git a/cmake_targets/autotests/test_case_list.xml b/cmake_targets/autotests/test_case_list.xml index 1f627acefd..81f8b0eb58 100644 --- a/cmake_targets/autotests/test_case_list.xml +++ b/cmake_targets/autotests/test_case_list.xml @@ -2440,7 +2440,7 @@ 10 - + lte-softmodem calisson @@ -2529,7 +2529,7 @@ calisson stevens - calisson + nano 390 /tmp targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf tracking_area_code \"1\" @@ -2613,7 +2613,7 @@ calisson stevens - calisson + nano 390 /tmp targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf tracking_area_code \"1\" From eb03e01faf4fe69f29364e27ebdf55f88417d982 Mon Sep 17 00:00:00 2001 From: Florian Kaltenberger Date: Thu, 21 Jan 2016 20:58:29 +0100 Subject: [PATCH 169/263] dlsim compilation issue fixed --- openair1/SIMULATION/LTE_PHY/dlsim.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openair1/SIMULATION/LTE_PHY/dlsim.c b/openair1/SIMULATION/LTE_PHY/dlsim.c index 6bb64e5c25..fbb88bf052 100644 --- a/openair1/SIMULATION/LTE_PHY/dlsim.c +++ b/openair1/SIMULATION/LTE_PHY/dlsim.c @@ -185,7 +185,7 @@ int main(int argc, char **argv) unsigned int coded_bits_per_codeword=0,nsymb,dci_cnt,tbs=0; unsigned int tx_lev=0,tx_lev_dB=0,trials,errs[4]= {0,0,0,0},errs2[4]= {0,0,0,0},round_trials[4]= {0,0,0,0},dci_errors=0,dlsch_active=0;//,num_layers; - // int re_allocated; + int re_allocated; char fname[32],vname[32]; FILE *bler_fd; char bler_fname[256]; From 75bba781e95203c0c7a20d476e1d472213c9f6ae Mon Sep 17 00:00:00 2001 From: Cedric Roux Date: Fri, 22 Jan 2016 11:54:16 +0100 Subject: [PATCH 170/263] msg_p should be msg_delete_tunnels_p --- openair2/RRC/LITE/rrc_eNB_S1AP.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openair2/RRC/LITE/rrc_eNB_S1AP.c b/openair2/RRC/LITE/rrc_eNB_S1AP.c index 3a22180a36..d93b8eea2f 100644 --- a/openair2/RRC/LITE/rrc_eNB_S1AP.c +++ b/openair2/RRC/LITE/rrc_eNB_S1AP.c @@ -1188,7 +1188,7 @@ int rrc_eNB_process_S1AP_UE_CONTEXT_RELEASE_COMMAND (MessageDef *msg_p, const ch GTPV1U_ENB_DELETE_TUNNEL_REQ(msg_delete_tunnels_p).rnti = ue_context_p->ue_context.rnti; for (e_rab = 0; e_rab < ue_context_p->ue_context.nb_of_e_rabs; e_rab++) { - GTPV1U_ENB_DELETE_TUNNEL_REQ(msg_delete_tunnels_p).eps_bearer_id[GTPV1U_ENB_DELETE_TUNNEL_REQ(msg_p).num_erab++] = + GTPV1U_ENB_DELETE_TUNNEL_REQ(msg_delete_tunnels_p).eps_bearer_id[GTPV1U_ENB_DELETE_TUNNEL_REQ(msg_delete_tunnels_p).num_erab++] = ue_context_p->ue_context.enb_gtp_ebi[e_rab]; // erase data ue_context_p->ue_context.enb_gtp_teid[e_rab] = 0; From 191e93cc91853e9228e02456241d1edad6958c50 Mon Sep 17 00:00:00 2001 From: Raymond Knopp Date: Mon, 25 Jan 2016 01:13:24 -0800 Subject: [PATCH 171/263] basic skeleton for SoDeRa OAI library --- cmake_targets/CMakeLists.txt | 22 +- cmake_targets/build_oai | 8 +- targets/ARCH/COMMON/common_lib.c | 8 +- targets/ARCH/COMMON/common_lib.h | 3 + .../ARCH/SODERA/USERSPACE/LIB/sodera_lib.cpp | 442 ++++++++++++++++++ 5 files changed, 476 insertions(+), 7 deletions(-) create mode 100644 targets/ARCH/SODERA/USERSPACE/LIB/sodera_lib.cpp diff --git a/cmake_targets/CMakeLists.txt b/cmake_targets/CMakeLists.txt index f52a3c465f..d359b231b4 100644 --- a/cmake_targets/CMakeLists.txt +++ b/cmake_targets/CMakeLists.txt @@ -159,7 +159,7 @@ set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -DSTDC_HEADERS=1 -DHAVE_SYS_TYPES_H=1 -DHAVE_SYS_STAT_H=1 -DHAVE_STDLIB_H=1 -DHAVE_STRING_H=1 -DHAVE_MEMORY_H=1 -DHAVE_STRINGS_H=1 -DHAVE_INTTYPES_H=1 -DHAVE_STDINT_H=1 -DHAVE_UNISTD_H=1 -DHAVE_FCNTL_H=1 -DHAVE_ARPA_INET_H=1 -DHAVE_SYS_TIME_H=1 -DHAVE_SYS_SOCKET_H=1 -DHAVE_STRERROR=1 -DHAVE_SOCKET=1 -DHAVE_MEMSET=1 -DHAVE_GETTIMEOFDAY=1 -DHAVE_STDLIB_H=1 -DHAVE_MALLOC=1 -DHAVE_LIBSCTP" ) set(CMAKE_CXX_FLAGS - "${CMAKE_CXX_FLAGS} ${C_FLAGS_PROCESSOR}" + "${CMAKE_CXX_FLAGS} ${C_FLAGS_PROCESSOR} -std=c++11 " ) # set a flag for changes in the source code # these changes are related to hardcoded path to include .h files @@ -167,6 +167,7 @@ add_definitions(-DCMAKER) set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS} -g -DMALLOC_CHECK_=3") set(CMAKE_C_FLAGS_RELWITHDEBINFO "${CMAKE_C_FLAGS} -g -DMALLOC_CHECK_=3 -O2") +Message("RF_BOARD is ${RF_BOARD}") # Below has been put in comment because does not work with # SVN authentication. # @@ -404,7 +405,9 @@ add_list1_option(NB_ANTENNAS_RX "2" "Number of antennas in reception" "1" "2" "4 add_list1_option(NB_ANTENNAS_TX "2" "Number of antennas in transmission" "1" "2" "4") add_list1_option(NB_ANTENNAS_TXRX "2" "Number of antennas in ????" "1" "2" "4") -add_list2_option(RF_BOARD "EXMIMO" "RF head type" "False" "EXMIMO" "OAI_USRP" "ETHERNET" "OAI_BLADERF" "CPRIGW") +add_list2_option(RF_BOARD "EXMIMO" "RF head type" "False" "EXMIMO" "OAI_USRP" "ETHERNET" "OAI_BLADERF" "OAI_SODERA" "CPRIGW") + +Message("RF_BOARD is ${RF_BOARD}") if (${RF_BOARD} STREQUAL "EXMIMO") set(DRIVER2013) @@ -434,6 +437,19 @@ elseif (${RF_BOARD} STREQUAL "OAI_BLADERF") set(option_HW_lib "bladeRF") #set(LOWLATENCY False) +elseif (${RF_BOARD} STREQUAL "OAI_SODERA") + include_directories("${OPENAIR_TARGETS}/ARCH/SODERA/USERSPACE/LIB/") + include_directories("${OPENAIR_TARGETS}/ARCH/SODERA/USERSPACE/LIB/SoDeRaV1_distro_01v/lms7suite_source_code/src/lms7002m") + include_directories("${OPENAIR_TARGETS}/ARCH/SODERA/USERSPACE/LIB/SoDeRaV1_distro_01v/lms7suite_source_code/src/Si5351C") + set(HW_SOURCE ${HW_SOURCE} + ${OPENAIR_TARGETS}/ARCH/SODERA/USERSPACE/LIB/sodera_lib.cpp + ) + LINK_DIRECTORIES("${OPENAIR_TARGETS}/ARCH/SODERA/USERSPACE/LIB/SoDeRaV1_distro_01v/lms7suite_source_code/build/lms7002m") + LINK_DIRECTORIES("/usr/lib/x86_64-linux-gnu") + set(option_HW_lib "usb-1.0") + set(LMS7002_LIB "libLMS7002M.a") + #set(LOWLATENCY False) + elseif (${RF_BOARD} STREQUAL "ETHERNET") include_directories ("${OPENAIR_TARGETS}/ARCH/ETHERNET/USERSPACE/LIB") set(HW_SOURCE ${HW_SOURCE} @@ -1431,7 +1447,7 @@ add_executable(lte-softmodem target_link_libraries (lte-softmodem -Wl,--start-group - RRC_LIB S1AP_LIB S1AP_ENB GTPV1U SECU_CN SECU_OSA UTIL HASHTABLE SCTP_CLIENT UDP SCHED_LIB PHY LFDS L2 ${MSC_LIB} ${RAL_LIB} ${NAS_UE_LIB} ${ITTI_LIB} ${MIH_LIB} + RRC_LIB S1AP_LIB S1AP_ENB GTPV1U SECU_CN SECU_OSA UTIL HASHTABLE SCTP_CLIENT UDP SCHED_LIB PHY LFDS L2 ${MSC_LIB} ${RAL_LIB} ${NAS_UE_LIB} ${ITTI_LIB} ${MIH_LIB} ${LMS7002_LIB} -Wl,--end-group ) diff --git a/cmake_targets/build_oai b/cmake_targets/build_oai index c723d8d6dc..4a18e53f47 100755 --- a/cmake_targets/build_oai +++ b/cmake_targets/build_oai @@ -90,7 +90,7 @@ Options default is Rel10, Rel8 limits the implementation to 3GPP Release 8 version -w | --hardware - EXMIMO (Default), USRP, BLADERF, ETHERNET, None + EXMIMO (Default), USRP, BLADERF, SODERA, ETHERNET, None Adds this RF board support (in external packages installation and in compilation) --oaisim Makes the oaisim simulator. Hardware will be defaulted to "NONE". @@ -181,6 +181,9 @@ function main() { if [ "$HW" == "BLADERF" ] ; then HW="OAI_BLADERF" fi + if [ "$HW" == "SODERA" ] ; then + HW="OAI_SODERA" + fi echo_info "setting hardware to: $HW" shift 2;; --oaisim) @@ -249,6 +252,7 @@ function main() { esac done + echo_info "RF HW set to $HW" #Now we set flags to enable deadline scheduler settings #By default: USRP: disable, #By default: BLADERF: enable, @@ -262,6 +266,8 @@ function main() { LOWLATENCY_FLAG_USER="False" elif [ "$HW" = "OAI_BLADERF" ] ; then LOWLATENCY_FLAG_USER="False" + elif [ "$HW" = "OAI_SODERA" ] ; then + LOWLATENCY_FLAG_USER="False" elif [ "$HW" = "None" ] ; then LOWLATENCY_FLAG_USER="False" else diff --git a/targets/ARCH/COMMON/common_lib.c b/targets/ARCH/COMMON/common_lib.c index bdf0e46278..8ee25c5fda 100644 --- a/targets/ARCH/COMMON/common_lib.c +++ b/targets/ARCH/COMMON/common_lib.c @@ -57,12 +57,14 @@ int openair0_device_init(openair0_device *device, openair0_config_t *openair0_cf openair0_dev_init_usrp(device, openair0_cfg); printf("openair0_dev_init_usrp ...\n"); return(openair0_dev_init_usrp(device, openair0_cfg)); - #elif OAI_BLADERF device->type=BLADERF_IF; printf(" openair0_dev_init_bladerf ...\n"); return(openair0_dev_init_bladerf(device, openair0_cfg)); - -#endif +#elif OAI_SODERA + device->type=OAI_SODERA; + printf(" openair0_dev_init_sodera ...\n"); + return(openair0_dev_init_sodera(device, openair0_cfg)); +#endif } diff --git a/targets/ARCH/COMMON/common_lib.h b/targets/ARCH/COMMON/common_lib.h index a3fe9e9dbd..8eaf3f781a 100644 --- a/targets/ARCH/COMMON/common_lib.h +++ b/targets/ARCH/COMMON/common_lib.h @@ -164,6 +164,8 @@ typedef enum { USRP_X300_IF, /*!\brief device is BLADE RF*/ BLADERF_IF, + /*!\brief device is SODERA RF*/ + SODERARF_IF, /*!\brief device is NONE*/ NONE_IF, MAX_DEV_TYPE @@ -295,6 +297,7 @@ extern "C" /*! \brief Initialize Openair ETHERNET target. It returns 0 if OK */ int openair0_dev_init_eth(openair0_device *device, openair0_config_t *openair0_cfg); int openair0_dev_init_bladerf(openair0_device *device, openair0_config_t *openair0_cfg); + int openair0_dev_init_sodera(openair0_device *device, openair0_config_t *openair0_cfg); int openair0_dev_init_usrp(openair0_device* device, openair0_config_t *openair0_cfg); int openair0_dev_init_exmimo(openair0_device *device, openair0_config_t *openair0_cfg); /*@}*/ diff --git a/targets/ARCH/SODERA/USERSPACE/LIB/sodera_lib.cpp b/targets/ARCH/SODERA/USERSPACE/LIB/sodera_lib.cpp new file mode 100644 index 0000000000..f8257fccf8 --- /dev/null +++ b/targets/ARCH/SODERA/USERSPACE/LIB/sodera_lib.cpp @@ -0,0 +1,442 @@ +/******************************************************************************* + OpenAirInterface + Copyright(c) 1999 - 2014 Eurecom + + OpenAirInterface is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + + OpenAirInterface 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with OpenAirInterface.The full GNU General Public License is + included in this distribution in the file called "COPYING". If not, + see . + + Contact Information + OpenAirInterface Admin: openair_admin@eurecom.fr + OpenAirInterface Tech : openair_tech@eurecom.fr + OpenAirInterface Dev : openair4g-devel@lists.eurecom.fr + + Address : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE + + *******************************************************************************/ + +/** sodera_lib.c + * + * Author: Raymond Knopp + */ + + +#include +#include +#include +#include +#include +#include + + +#include +#include +#include +#include + +#include "common_lib.h" + +#include "lmsComms.h" +#include "Si5351C.h" +#ifdef __SSE4_1__ +# include +#endif + +#ifdef __AVX2__ +# include +#endif + +int num_devices=0; +/*These items configure the underlying asynch stream used by the the sync interface. + */ + +typedef struct +{ + + // -------------------------------- + // variables for SoDeRa configuration + // -------------------------------- + /* + uhd::usrp::multi_usrp::sptr usrp; + //uhd::usrp::multi_usrp::sptr rx_usrp; + + //create a send streamer and a receive streamer + uhd::tx_streamer::sptr tx_stream; + uhd::rx_streamer::sptr rx_stream; + + uhd::tx_metadata_t tx_md; + uhd::rx_metadata_t rx_md; + + uhd::time_spec_t tm_spec; + //setup variables and allocate buffer + uhd::async_metadata_t async_md; + */ + + LMScomms mDataPort; + + double sample_rate; + // time offset between transmiter timestamp and receiver timestamp; + double tdiff; + + // -------------------------------- + // Debug and output control + // -------------------------------- + int num_underflows; + int num_overflows; + int num_seq_errors; + + int64_t tx_count; + int64_t rx_count; + openair0_timestamp rx_timestamp; + +} sodera_state_t; + + +static int trx_sodera_start(openair0_device *device) +{ + sodera_state_t *s = (sodera_state_t*)device->priv; + + // init recv and send streaming + + s->rx_count = 0; + s->tx_count = 0; + s->rx_timestamp = 0; + + return 0; +} + +static void trx_sodera_end(openair0_device *device) +{ + sodera_state_t *s = (sodera_state_t*)device->priv; + + + +} + +static int trx_sodera_write(openair0_device *device, openair0_timestamp timestamp, void **buff, int nsamps, int cc, int flags) +{ + sodera_state_t *s = (sodera_state_t*)device->priv; + + if (cc>1) { + // s->tx_stream->send(buff_ptrs, nsamps, s->tx_md); + } + else + // s->tx_stream->send(buff[0], nsamps, s->tx_md); + + return 0; +} + +static int trx_sodera_read(openair0_device *device, openair0_timestamp *ptimestamp, void **buff, int nsamps, int cc) +{ + sodera_state_t *s = (sodera_state_t*)device->priv; + int samples_received=0,i,j; + int nsamps2; // aligned to upper 32 or 16 byte boundary +#if defined(__x86_64) || defined(__i386__) +#ifdef __AVX2__ + __m256i buff_tmp[2][nsamps>>3]; + nsamps2 = (nsamps+7)>>3; +#else + __m128i buff_tmp[2][nsamps>>2]; + nsamps2 = (nsamps+3)>>2; +#endif +#elif defined(__arm__) + int16x8_t buff_tmp[2][nsamps>>2]; + nsamps2 = (nsamps+3)>>2; +#endif + + + if (cc>1) { + // receive multiple channels (e.g. RF A and RF B) + + } else { + // receive a single channel (e.g. from connector RF A) + + } + + if (samples_received < nsamps) { + printf("[recv] received %d samples out of %d\n",samples_received,nsamps); + + } + + //handle the error code + + s->rx_count += nsamps; + // s->rx_timestamp = s->rx_md.time_spec.to_ticks(s->sample_rate); + *ptimestamp = s->rx_timestamp; + + return samples_received; +} + + + +static bool is_equal(double a, double b) +{ + return fabs(a-b) < 1e-6; +} + +int trx_sodera_set_freq(openair0_device* device, openair0_config_t *openair0_cfg, int dummy) { + + sodera_state_t *s = (sodera_state_t*)device->priv; + + // s->usrp->set_tx_freq(openair0_cfg[0].tx_freq[0]); + // s->usrp->set_rx_freq(openair0_cfg[0].rx_freq[0]); + + return(0); + +} + +int openair0_set_rx_frequencies(openair0_device* device, openair0_config_t *openair0_cfg) { + + sodera_state_t *s = (sodera_state_t*)device->priv; + static int first_call=1; + static double rf_freq,diff; + + // uhd::tune_request_t rx_tune_req(openair0_cfg[0].rx_freq[0]); + + // rx_tune_req.rf_freq_policy = uhd::tune_request_t::POLICY_MANUAL; + // rx_tune_req.rf_freq = openair0_cfg[0].rx_freq[0]; + // rf_freq=openair0_cfg[0].rx_freq[0]; + // s->usrp->set_rx_freq(rx_tune_req); + + return(0); + +} + +int trx_sodera_set_gains(openair0_device* device, + openair0_config_t *openair0_cfg) { + + sodera_state_t *s = (sodera_state_t*)device->priv; + + // s->usrp->set_tx_gain(openair0_cfg[0].tx_gain[0]); + // ::uhd::gain_range_t gain_range = s->usrp->get_rx_gain_range(0); + // limit to maximum gain + /* if (openair0_cfg[0].rx_gain[0]-openair0_cfg[0].rx_gain_offset[0] > gain_range.stop()) { + + printf("RX Gain 0 too high, reduce by %f dB\n", + openair0_cfg[0].rx_gain[0]-openair0_cfg[0].rx_gain_offset[0] - gain_range.stop()); + exit(-1); + } + s->usrp->set_rx_gain(openair0_cfg[0].rx_gain[0]-openair0_cfg[0].rx_gain_offset[0]); + printf("Setting SODERA RX gain to %f (rx_gain %f,gain_range.stop() %f)\n", openair0_cfg[0].rx_gain[0]-openair0_cfg[0].rx_gain_offset[0],openair0_cfg[0].rx_gain[0],gain_range.stop()); + */ + return(0); +} + +int trx_sodera_stop(int card) { + return(0); +} + + +rx_gain_calib_table_t calib_table_sodera[] = { + {3500000000.0,44.0}, + {2660000000.0,49.0}, + {2300000000.0,50.0}, + {1880000000.0,53.0}, + {816000000.0,58.0}, + {-1,0}}; + +void set_rx_gain_offset(openair0_config_t *openair0_cfg, int chain_index,int bw_gain_adjust) { + + int i=0; + // loop through calibration table to find best adjustment factor for RX frequency + double min_diff = 6e9,diff,gain_adj=0.0; + if (bw_gain_adjust==1) { + switch ((int)openair0_cfg[0].sample_rate) { + case 30720000: + break; + case 23040000: + gain_adj=1.25; + break; + case 15360000: + gain_adj=3.0; + break; + case 7680000: + gain_adj=6.0; + break; + case 3840000: + gain_adj=9.0; + break; + case 1920000: + gain_adj=12.0; + break; + default: + printf("unknown sampling rate %d\n",(int)openair0_cfg[0].sample_rate); + exit(-1); + break; + } + } + while (openair0_cfg->rx_gain_calib_table[i].freq>0) { + diff = fabs(openair0_cfg->rx_freq[chain_index] - openair0_cfg->rx_gain_calib_table[i].freq); + printf("cal %d: freq %f, offset %f, diff %f\n", + i, + openair0_cfg->rx_gain_calib_table[i].freq, + openair0_cfg->rx_gain_calib_table[i].offset,diff); + if (min_diff > diff) { + min_diff = diff; + openair0_cfg->rx_gain_offset[chain_index] = openair0_cfg->rx_gain_calib_table[i].offset+gain_adj; + } + i++; + } + +} + + +int trx_sodera_get_stats(openair0_device* device) { + + return(0); + +} +int trx_sodera_reset_stats(openair0_device* device) { + + return(0); + +} + + +int openair0_dev_init_sodera(openair0_device* device, openair0_config_t *openair0_cfg) +{ + + sodera_state_t *s = (sodera_state_t*)malloc(sizeof(sodera_state_t)); + size_t i; + memset(s, 0, sizeof(sodera_state_t)); + + // Initialize SODERA device + if (!s->mDataPort.Open(0)) { + printf("Cannot open SoDeRa\n"); + exit(-1); + } + + + int vers=0,subvers=0,subsubvers=0; + int bw_gain_adjust=0; + + + openair0_cfg[0].rx_gain_calib_table = calib_table_sodera; + + switch ((int)openair0_cfg[0].sample_rate) { + case 30720000: + // from usrp_time_offset + openair0_cfg[0].samples_per_packet = 2048; + openair0_cfg[0].tx_sample_advance = 15; + openair0_cfg[0].tx_bw = 20e6; + openair0_cfg[0].rx_bw = 20e6; + openair0_cfg[0].tx_scheduling_advance = 8*openair0_cfg[0].samples_per_packet; + break; + case 15360000: + openair0_cfg[0].samples_per_packet = 2048; + openair0_cfg[0].tx_sample_advance = 45; + openair0_cfg[0].tx_bw = 10e6; + openair0_cfg[0].rx_bw = 10e6; + openair0_cfg[0].tx_scheduling_advance = 5*openair0_cfg[0].samples_per_packet; + break; + case 7680000: + openair0_cfg[0].samples_per_packet = 1024; + openair0_cfg[0].tx_sample_advance = 50; + openair0_cfg[0].tx_bw = 5e6; + openair0_cfg[0].rx_bw = 5e6; + openair0_cfg[0].tx_scheduling_advance = 5*openair0_cfg[0].samples_per_packet; + break; + case 1920000: + openair0_cfg[0].samples_per_packet = 256; + openair0_cfg[0].tx_sample_advance = 50; + openair0_cfg[0].tx_bw = 1.25e6; + openair0_cfg[0].rx_bw = 1.25e6; + openair0_cfg[0].tx_scheduling_advance = 8*openair0_cfg[0].samples_per_packet; + break; + default: + printf("Error: unknown sampling rate %f\n",openair0_cfg[0].sample_rate); + exit(-1); + break; + } + + /* + for(i=0;iusrp->get_rx_num_channels();i++) { + if (iusrp->set_rx_rate(openair0_cfg[0].sample_rate,i); + s->usrp->set_rx_bandwidth(openair0_cfg[0].rx_bw,i); + printf("Setting rx freq/gain on channel %lu/%lu : BW %f (readback %f)\n",i,s->usrp->get_rx_num_channels(),openair0_cfg[0].rx_bw/1e6,s->usrp->get_rx_bandwidth(i)/1e6); + s->usrp->set_rx_freq(openair0_cfg[0].rx_freq[i],i); + set_rx_gain_offset(&openair0_cfg[0],i,bw_gain_adjust); + + ::uhd::gain_range_t gain_range = s->usrp->get_rx_gain_range(i); + // limit to maximum gain + if (openair0_cfg[0].rx_gain[i]-openair0_cfg[0].rx_gain_offset[i] > gain_range.stop()) { + + printf("RX Gain %lu too high, lower by %f dB\n",i,openair0_cfg[0].rx_gain[i]-openair0_cfg[0].rx_gain_offset[i] - gain_range.stop()); + exit(-1); + } + s->usrp->set_rx_gain(openair0_cfg[0].rx_gain[i]-openair0_cfg[0].rx_gain_offset[i],i); + printf("RX Gain %lu %f (%f) => %f (max %f)\n",i, + openair0_cfg[0].rx_gain[i],openair0_cfg[0].rx_gain_offset[i], + openair0_cfg[0].rx_gain[i]-openair0_cfg[0].rx_gain_offset[i],gain_range.stop()); + } + } + for(i=0;iusrp->get_tx_num_channels();i++) { + if (iusrp->set_tx_rate(openair0_cfg[0].sample_rate,i); + s->usrp->set_tx_bandwidth(openair0_cfg[0].tx_bw,i); + printf("Setting tx freq/gain on channel %lu/%lu: BW %f (readback %f)\n",i,s->usrp->get_tx_num_channels(),openair0_cfg[0].tx_bw/1e6,s->usrp->get_tx_bandwidth(i)/1e6); + s->usrp->set_tx_freq(openair0_cfg[0].tx_freq[i],i); + s->usrp->set_tx_gain(openair0_cfg[0].tx_gain[i],i); + } + } + */ + + // create tx & rx streamer + + //stream_args_rx.args["spp"] = str(boost::format("%d") % 2048);//(openair0_cfg[0].rx_num_channels*openair0_cfg[0].samples_per_packet)); + + /* + for (i=0;iusrp->get_rx_rate(i)/1e6) << std::endl; + std::cout << boost::format("Actual RX frequency: %fGHz...") % (s->usrp->get_rx_freq(i)/1e9) << std::endl; + std::cout << boost::format("Actual RX gain: %f...") % (s->usrp->get_rx_gain(i)) << std::endl; + std::cout << boost::format("Actual RX bandwidth: %fM...") % (s->usrp->get_rx_bandwidth(i)/1e6) << std::endl; + std::cout << boost::format("Actual RX antenna: %s...") % (s->usrp->get_rx_antenna(i)) << std::endl; + } + } + + for (i=0;iusrp->get_tx_rate(i)/1e6) << std::endl; + std::cout << boost::format("Actual TX frequency: %fGHz...") % (s->usrp->get_tx_freq(i)/1e9) << std::endl; + std::cout << boost::format("Actual TX gain: %f...") % (s->usrp->get_tx_gain(i)) << std::endl; + std::cout << boost::format("Actual TX bandwidth: %fM...") % (s->usrp->get_tx_bandwidth(i)/1e6) << std::endl; + std::cout << boost::format("Actual TX antenna: %s...") % (s->usrp->get_tx_antenna(i)) << std::endl; + } + } + */ + + + device->priv = s; + device->trx_start_func = trx_sodera_start; + device->trx_write_func = trx_sodera_write; + device->trx_read_func = trx_sodera_read; + device->trx_get_stats_func = trx_sodera_get_stats; + device->trx_reset_stats_func = trx_sodera_reset_stats; + device->trx_end_func = trx_sodera_end; + device->trx_stop_func = trx_sodera_stop; + device->trx_set_freq_func = trx_sodera_set_freq; + device->trx_set_gains_func = trx_sodera_set_gains; + + s->sample_rate = openair0_cfg[0].sample_rate; + // TODO: + + return 0; +} From de3ba76b2f0608df77bde76d2ed82700b02a0160 Mon Sep 17 00:00:00 2001 From: kaltenbe Date: Tue, 26 Jan 2016 01:21:59 +0100 Subject: [PATCH 172/263] first steps of SoDeRa configuration --- cmake_targets/CMakeLists.txt | 12 +- targets/ARCH/COMMON/common_lib.c | 9 +- targets/ARCH/COMMON/common_lib.h | 3 +- .../ARCH/SODERA/USERSPACE/LIB/sodera_lib.cpp | 155 ++- targets/ARCH/SODERA/lms7_trx_LTE_mimo_RF.ini | 1128 +++++++++++++++++ targets/ARCH/SODERA/lms7_trx_LTE_mimo_TSG.ini | 1128 +++++++++++++++++ .../CONF/enb.band4.tm1.usrpb210.conf | 12 +- targets/RT/USER/lte-softmodem.c | 21 +- 8 files changed, 2397 insertions(+), 71 deletions(-) create mode 100644 targets/ARCH/SODERA/lms7_trx_LTE_mimo_RF.ini create mode 100644 targets/ARCH/SODERA/lms7_trx_LTE_mimo_TSG.ini diff --git a/cmake_targets/CMakeLists.txt b/cmake_targets/CMakeLists.txt index d359b231b4..84bf183991 100644 --- a/cmake_targets/CMakeLists.txt +++ b/cmake_targets/CMakeLists.txt @@ -438,16 +438,18 @@ elseif (${RF_BOARD} STREQUAL "OAI_BLADERF") #set(LOWLATENCY False) elseif (${RF_BOARD} STREQUAL "OAI_SODERA") - include_directories("${OPENAIR_TARGETS}/ARCH/SODERA/USERSPACE/LIB/") - include_directories("${OPENAIR_TARGETS}/ARCH/SODERA/USERSPACE/LIB/SoDeRaV1_distro_01v/lms7suite_source_code/src/lms7002m") - include_directories("${OPENAIR_TARGETS}/ARCH/SODERA/USERSPACE/LIB/SoDeRaV1_distro_01v/lms7suite_source_code/src/Si5351C") + include_directories("${OPENAIR_TARGETS}/ARCH/SODERA/USERSPACE/LIB") + include_directories("${OPENAIR_TARGETS}/ARCH/SODERA/USERSPACE/LIB/lms7suite/src/lms7002m") + include_directories("${OPENAIR_TARGETS}/ARCH/SODERA/USERSPACE/LIB/lms7suite/src/Si5351C") set(HW_SOURCE ${HW_SOURCE} ${OPENAIR_TARGETS}/ARCH/SODERA/USERSPACE/LIB/sodera_lib.cpp ) - LINK_DIRECTORIES("${OPENAIR_TARGETS}/ARCH/SODERA/USERSPACE/LIB/SoDeRaV1_distro_01v/lms7suite_source_code/build/lms7002m") + LINK_DIRECTORIES("${OPENAIR_TARGETS}/ARCH/SODERA/USERSPACE/LIB/lms7suite/src/lms7002m") + LINK_DIRECTORIES("${OPENAIR_TARGETS}/ARCH/SODERA/USERSPACE/LIB/lms7suite/src/Si5351C") LINK_DIRECTORIES("/usr/lib/x86_64-linux-gnu") set(option_HW_lib "usb-1.0") set(LMS7002_LIB "libLMS7002M.a") + set(Si5351C_LIB "libSi5351C.a") #set(LOWLATENCY False) elseif (${RF_BOARD} STREQUAL "ETHERNET") @@ -1447,7 +1449,7 @@ add_executable(lte-softmodem target_link_libraries (lte-softmodem -Wl,--start-group - RRC_LIB S1AP_LIB S1AP_ENB GTPV1U SECU_CN SECU_OSA UTIL HASHTABLE SCTP_CLIENT UDP SCHED_LIB PHY LFDS L2 ${MSC_LIB} ${RAL_LIB} ${NAS_UE_LIB} ${ITTI_LIB} ${MIH_LIB} ${LMS7002_LIB} + RRC_LIB S1AP_LIB S1AP_ENB GTPV1U SECU_CN SECU_OSA UTIL HASHTABLE SCTP_CLIENT UDP SCHED_LIB PHY LFDS L2 ${MSC_LIB} ${RAL_LIB} ${NAS_UE_LIB} ${ITTI_LIB} ${MIH_LIB} ${LMS7002_LIB} ${Si5351C_LIB} -Wl,--end-group ) diff --git a/targets/ARCH/COMMON/common_lib.c b/targets/ARCH/COMMON/common_lib.c index 8ee25c5fda..278d8ed79f 100644 --- a/targets/ARCH/COMMON/common_lib.c +++ b/targets/ARCH/COMMON/common_lib.c @@ -59,11 +59,16 @@ int openair0_device_init(openair0_device *device, openair0_config_t *openair0_cf return(openair0_dev_init_usrp(device, openair0_cfg)); #elif OAI_BLADERF device->type=BLADERF_IF; - printf(" openair0_dev_init_bladerf ...\n"); + printf("openair0_dev_init_bladerf ...\n"); return(openair0_dev_init_bladerf(device, openair0_cfg)); #elif OAI_SODERA device->type=OAI_SODERA; - printf(" openair0_dev_init_sodera ...\n"); + printf("openair0_dev_init_sodera ...\n"); + if (openair0_cfg[0].configFilename==NULL) { + printf("Please provide a configuration file for SoDeRa\n"); + exit(-1); + } + return(openair0_dev_init_sodera(device, openair0_cfg)); #endif diff --git a/targets/ARCH/COMMON/common_lib.h b/targets/ARCH/COMMON/common_lib.h index 8eaf3f781a..3f814a9e55 100644 --- a/targets/ARCH/COMMON/common_lib.h +++ b/targets/ARCH/COMMON/common_lib.h @@ -133,7 +133,8 @@ typedef struct { char *my_ip; //! my port number for Ethernet interface (eNB/BBU, UE) int my_port; - + //! Configuration file for LMS7002M + char *configFilename; } openair0_config_t; typedef struct { diff --git a/targets/ARCH/SODERA/USERSPACE/LIB/sodera_lib.cpp b/targets/ARCH/SODERA/USERSPACE/LIB/sodera_lib.cpp index f8257fccf8..ddd608d0a1 100644 --- a/targets/ARCH/SODERA/USERSPACE/LIB/sodera_lib.cpp +++ b/targets/ARCH/SODERA/USERSPACE/LIB/sodera_lib.cpp @@ -31,8 +31,9 @@ * * Author: Raymond Knopp */ - - + +#include +#include #include #include #include @@ -49,6 +50,7 @@ #include "common_lib.h" #include "lmsComms.h" +#include "LMS7002M.h" #include "Si5351C.h" #ifdef __SSE4_1__ # include @@ -58,6 +60,8 @@ # include #endif +using namespace std; + int num_devices=0; /*These items configure the underlying asynch stream used by the the sync interface. */ @@ -84,8 +88,8 @@ typedef struct uhd::async_metadata_t async_md; */ - LMScomms mDataPort; - + LMScomms Port; + Si5351C Si; double sample_rate; // time offset between transmiter timestamp and receiver timestamp; double tdiff; @@ -103,6 +107,7 @@ typedef struct } sodera_state_t; +sodera_state_t sodera_state; static int trx_sodera_start(openair0_device *device) { @@ -308,62 +313,99 @@ int trx_sodera_reset_stats(openair0_device* device) { int openair0_dev_init_sodera(openair0_device* device, openair0_config_t *openair0_cfg) { - sodera_state_t *s = (sodera_state_t*)malloc(sizeof(sodera_state_t)); + sodera_state_t *s=&sodera_state; + size_t i; - memset(s, 0, sizeof(sodera_state_t)); // Initialize SODERA device - if (!s->mDataPort.Open(0)) { - printf("Cannot open SoDeRa\n"); - exit(-1); - } + s->Port.RefreshDeviceList(); + vector deviceNames=s->Port.GetDeviceList(); - - int vers=0,subvers=0,subsubvers=0; - int bw_gain_adjust=0; + if (deviceNames.size() == 1) { + if (s->Port.Open(0) != IConnection::SUCCESS) { + printf("Cannot open SoDeRa\n"); + exit(-1); + } + LMSinfo devInfo = s->Port.GetInfo(); + printf("Device %s, HW: %d, FW: %d, Protocol %d\n", + GetDeviceName(devInfo.device), + (int)devInfo.hardware, + (int)devInfo.firmware, + (int)devInfo.protocol); + LMS7002M lmsControl(&s->Port); + + printf("Configuring Si5351C\n"); + s->Si.Initialize(&s->Port); + s->Si.SetPLL(0, 25000000, 0); + s->Si.SetPLL(1, 25000000, 0); + s->Si.SetClock(0, 27000000, true, false); + s->Si.SetClock(1, 27000000, true, false); + for (int i = 2; i < 8; ++i) + s->Si.SetClock(i, 27000000, false, false); + Si5351C::Status status = s->Si.ConfigureClocks(); + if (status != Si5351C::SUCCESS) + { + printf("Failed to configure Si5351C"); + exit(-1); + } + status = s->Si.UploadConfiguration(); + if (status != Si5351C::SUCCESS) + printf("Failed to upload Si5351C configuration"); + + + printf("Configuring LMS7002\n"); + + int bw_gain_adjust=0; - openair0_cfg[0].rx_gain_calib_table = calib_table_sodera; + openair0_cfg[0].rx_gain_calib_table = calib_table_sodera; - switch ((int)openair0_cfg[0].sample_rate) { - case 30720000: - // from usrp_time_offset - openair0_cfg[0].samples_per_packet = 2048; - openair0_cfg[0].tx_sample_advance = 15; - openair0_cfg[0].tx_bw = 20e6; - openair0_cfg[0].rx_bw = 20e6; - openair0_cfg[0].tx_scheduling_advance = 8*openair0_cfg[0].samples_per_packet; - break; - case 15360000: - openair0_cfg[0].samples_per_packet = 2048; - openair0_cfg[0].tx_sample_advance = 45; - openair0_cfg[0].tx_bw = 10e6; - openair0_cfg[0].rx_bw = 10e6; - openair0_cfg[0].tx_scheduling_advance = 5*openair0_cfg[0].samples_per_packet; - break; - case 7680000: - openair0_cfg[0].samples_per_packet = 1024; - openair0_cfg[0].tx_sample_advance = 50; - openair0_cfg[0].tx_bw = 5e6; - openair0_cfg[0].rx_bw = 5e6; - openair0_cfg[0].tx_scheduling_advance = 5*openair0_cfg[0].samples_per_packet; - break; - case 1920000: - openair0_cfg[0].samples_per_packet = 256; - openair0_cfg[0].tx_sample_advance = 50; - openair0_cfg[0].tx_bw = 1.25e6; - openair0_cfg[0].rx_bw = 1.25e6; - openair0_cfg[0].tx_scheduling_advance = 8*openair0_cfg[0].samples_per_packet; - break; - default: - printf("Error: unknown sampling rate %f\n",openair0_cfg[0].sample_rate); - exit(-1); - break; - } - - /* - for(i=0;iusrp->get_rx_num_channels();i++) { - if (iusrp->set_rx_rate(openair0_cfg[0].sample_rate,i); s->usrp->set_rx_bandwidth(openair0_cfg[0].rx_bw,i); printf("Setting rx freq/gain on channel %lu/%lu : BW %f (readback %f)\n",i,s->usrp->get_rx_num_channels(),openair0_cfg[0].rx_bw/1e6,s->usrp->get_rx_bandwidth(i)/1e6); @@ -420,9 +462,12 @@ int openair0_dev_init_sodera(openair0_device* device, openair0_config_t *openair std::cout << boost::format("Actual TX bandwidth: %fM...") % (s->usrp->get_tx_bandwidth(i)/1e6) << std::endl; std::cout << boost::format("Actual TX antenna: %s...") % (s->usrp->get_tx_antenna(i)) << std::endl; } - } */ - + } + else { + printf("Please connect SoDeRa\n"); + exit(-1); + } device->priv = s; device->trx_start_func = trx_sodera_start; diff --git a/targets/ARCH/SODERA/lms7_trx_LTE_mimo_RF.ini b/targets/ARCH/SODERA/lms7_trx_LTE_mimo_RF.ini new file mode 100644 index 0000000000..e0e313b23e --- /dev/null +++ b/targets/ARCH/SODERA/lms7_trx_LTE_mimo_RF.ini @@ -0,0 +1,1128 @@ +[file_info] +type=lms7002m_minimal_config +version=1 +[lms7002_registers_a] +0x0020=0xFFFD +0x0021=0x0E9F +0x0022=0x07FF +0x0023=0x5550 +0x0024=0xE4E4 +0x0025=0x0101 +0x0026=0x0101 +0x0027=0xB1E4 +0x0028=0x0101 +0x0029=0x0101 +0x002A=0x0086 +0x002B=0x0038 +0x002C=0x0000 +0x002D=0xFFFF +0x002E=0x0000 +0x002F=0x3840 +0x0081=0x0000 +0x0082=0x8001 +0x0084=0x0400 +0x0085=0x0001 +0x0086=0x4101 +0x0087=0xB13B +0x0088=0x0303 +0x0089=0x1078 +0x008A=0x0514 +0x008B=0x2182 +0x008C=0x267B +0x0092=0x0001 +0x0093=0x0000 +0x0094=0x0000 +0x0095=0x0000 +0x0096=0x0000 +0x0097=0x0000 +0x0098=0x0000 +0x0099=0x6565 +0x009A=0x658C +0x009B=0x6565 +0x009C=0x658C +0x009D=0x6565 +0x009E=0x658C +0x009F=0x658C +0x00A0=0x6565 +0x00A1=0x6565 +0x00A2=0x6565 +0x00A3=0x6565 +0x00A4=0x6565 +0x00A5=0x6565 +0x00A6=0x0001 +0x00A7=0x6565 +0x00A8=0x0000 +0x00A9=0x8000 +0x00AA=0x0000 +0x00AB=0x0040 +0x00AC=0x2000 +0x00AD=0x03FF +0x00AE=0x0000 +0x0100=0x7409 +0x0101=0x7800 +0x0102=0x3180 +0x0103=0x0A12 +0x0104=0x0088 +0x0105=0x0007 +0x0106=0x3182 +0x0107=0x318C +0x0108=0x3042 +0x0109=0x61C1 +0x010A=0x104C +0x010C=0x8865 +0x010D=0x019D +0x010E=0x2040 +0x010F=0x3042 +0x0110=0x0BF4 +0x0111=0x0083 +0x0112=0xC0E6 +0x0113=0x03C3 +0x0114=0x008D +0x0115=0x0009 +0x0116=0x8180 +0x0117=0x280C +0x0118=0x018C +0x0119=0x18CB +0x011A=0x2E02 +0x011C=0xA941 +0x011D=0x4EC4 +0x011E=0x048C +0x011F=0x3640 +0x0120=0xB9FF +0x0121=0x3158 +0x0122=0x033F +0x0123=0x267B +0x0124=0x0000 +0x0200=0x0081 +0x0201=0x07B0 +0x0202=0x06F2 +0x0203=0x0FC2 +0x0204=0xD51F +0x0205=0x0000 +0x0206=0x0000 +0x0207=0x0000 +0x0208=0x0170 +0x0209=0x0000 +0x020A=0x0080 +0x020B=0x4000 +0x020C=0x7FFF +0x0240=0x0020 +0x0241=0x0000 +0x0242=0x0000 +0x0243=0x0000 +0x0244=0x0000 +0x0245=0x0000 +0x0246=0x0000 +0x0247=0x0000 +0x0248=0x0000 +0x0249=0x0000 +0x024A=0x0000 +0x024B=0x0000 +0x024C=0x0000 +0x024D=0x0000 +0x024E=0x0000 +0x024F=0x0000 +0x0250=0x0000 +0x0251=0x0000 +0x0252=0x0000 +0x0253=0x0000 +0x0254=0x0000 +0x0255=0x0000 +0x0256=0x0000 +0x0257=0x0000 +0x0258=0x0000 +0x0259=0x0000 +0x025A=0x0000 +0x025B=0x0000 +0x025C=0x0000 +0x025D=0x0000 +0x025E=0x0000 +0x025F=0x0000 +0x0260=0x0000 +0x0261=0x0000 +0x0280=0x0000 +0x0281=0x0000 +0x0282=0x0000 +0x0283=0x0000 +0x0284=0x0000 +0x0285=0x0000 +0x0286=0x0000 +0x0287=0x0000 +0x0288=0x0000 +0x0289=0x0000 +0x028A=0x0000 +0x028B=0x0000 +0x028C=0x0000 +0x028D=0x0000 +0x028E=0x0000 +0x028F=0x0000 +0x0290=0x0000 +0x0291=0x0000 +0x0292=0x0000 +0x0293=0x0000 +0x0294=0x0000 +0x0295=0x0000 +0x0296=0x0000 +0x0297=0x0000 +0x0298=0x0000 +0x0299=0x0000 +0x029A=0x0000 +0x029B=0x0000 +0x029C=0x0000 +0x029D=0x0000 +0x029E=0x0000 +0x029F=0x0000 +0x02A0=0x0000 +0x02A1=0x0000 +0x02A2=0x0000 +0x02A3=0x0000 +0x02A4=0x0000 +0x02A5=0x0000 +0x02A6=0x0000 +0x02A7=0x0000 +0x02C0=0x0000 +0x02C1=0x0000 +0x02C2=0x0000 +0x02C3=0x0000 +0x02C4=0x0000 +0x02C5=0x0000 +0x02C6=0x0000 +0x02C7=0x0000 +0x02C8=0x0000 +0x02C9=0x0000 +0x02CA=0x0000 +0x02CB=0x0000 +0x02CC=0x0000 +0x02CD=0x0000 +0x02CE=0x0000 +0x02CF=0x0000 +0x02D0=0x0000 +0x02D1=0x0000 +0x02D2=0x0000 +0x02D3=0x0000 +0x02D4=0x0000 +0x02D5=0x0000 +0x02D6=0x0000 +0x02D7=0x0000 +0x02D8=0x0000 +0x02D9=0x0000 +0x02DA=0x0000 +0x02DB=0x0000 +0x02DC=0x0000 +0x02DD=0x0000 +0x02DE=0x0000 +0x02DF=0x0000 +0x02E0=0x0000 +0x02E1=0x0000 +0x02E2=0x0000 +0x02E3=0x0000 +0x02E4=0x0000 +0x02E5=0x0000 +0x02E6=0x0000 +0x02E7=0x0000 +0x0300=0x0000 +0x0301=0x0000 +0x0302=0x0000 +0x0303=0x0000 +0x0304=0x0000 +0x0305=0x0000 +0x0306=0x0000 +0x0307=0x0000 +0x0308=0x0000 +0x0309=0x0000 +0x030A=0x0000 +0x030B=0x0000 +0x030C=0x0000 +0x030D=0x0000 +0x030E=0x0000 +0x030F=0x0000 +0x0310=0x0000 +0x0311=0x0000 +0x0312=0x0000 +0x0313=0x0000 +0x0314=0x0000 +0x0315=0x0000 +0x0316=0x0000 +0x0317=0x0000 +0x0318=0x0000 +0x0319=0x0000 +0x031A=0x0000 +0x031B=0x0000 +0x031C=0x0000 +0x031D=0x0000 +0x031E=0x0000 +0x031F=0x0000 +0x0320=0x0000 +0x0321=0x0000 +0x0322=0x0000 +0x0323=0x0000 +0x0324=0x0000 +0x0325=0x0000 +0x0326=0x0000 +0x0327=0x0000 +0x0340=0x0000 +0x0341=0x0000 +0x0342=0x0000 +0x0343=0x0000 +0x0344=0x0000 +0x0345=0x0000 +0x0346=0x0000 +0x0347=0x0000 +0x0348=0x0000 +0x0349=0x0000 +0x034A=0x0000 +0x034B=0x0000 +0x034C=0x0000 +0x034D=0x0000 +0x034E=0x0000 +0x034F=0x0000 +0x0350=0x0000 +0x0351=0x0000 +0x0352=0x0000 +0x0353=0x0000 +0x0354=0x0000 +0x0355=0x0000 +0x0356=0x0000 +0x0357=0x0000 +0x0358=0x0000 +0x0359=0x0000 +0x035A=0x0000 +0x035B=0x0000 +0x035C=0x0000 +0x035D=0x0000 +0x035E=0x0000 +0x035F=0x0000 +0x0360=0x0000 +0x0361=0x0000 +0x0362=0x0000 +0x0363=0x0000 +0x0364=0x0000 +0x0365=0x0000 +0x0366=0x0000 +0x0367=0x0000 +0x0380=0x0000 +0x0381=0x0000 +0x0382=0x0000 +0x0383=0x0000 +0x0384=0x0000 +0x0385=0x0000 +0x0386=0x0000 +0x0387=0x0000 +0x0388=0x0000 +0x0389=0x0000 +0x038A=0x0000 +0x038B=0x0000 +0x038C=0x0000 +0x038D=0x0000 +0x038E=0x0000 +0x038F=0x0000 +0x0390=0x0000 +0x0391=0x0000 +0x0392=0x0000 +0x0393=0x0000 +0x0394=0x0000 +0x0395=0x0000 +0x0396=0x0000 +0x0397=0x0000 +0x0398=0x0000 +0x0399=0x0000 +0x039A=0x0000 +0x039B=0x0000 +0x039C=0x0000 +0x039D=0x0000 +0x039E=0x0000 +0x039F=0x0000 +0x03A0=0x0000 +0x03A1=0x0000 +0x03A2=0x0000 +0x03A3=0x0000 +0x03A4=0x0000 +0x03A5=0x0000 +0x03A6=0x0000 +0x03A7=0x0000 +0x0400=0x0081 +0x0401=0x07FF +0x0402=0x07FF +0x0403=0x0000 +0x0404=0x0000 +0x0405=0x0000 +0x0406=0x0000 +0x0407=0x0000 +0x0408=0x0000 +0x0409=0x0000 +0x040A=0x0003 +0x040B=0x000F +0x040C=0x00FC +0x040D=0x0000 +0x040E=0x0000 +0x040F=0x0000 +0x0440=0x0020 +0x0441=0x0000 +0x0442=0x0563 +0x0443=0xB490 +0x0444=0x02B1 +0x0445=0xDA48 +0x0446=0x0000 +0x0447=0x0000 +0x0448=0x0000 +0x0449=0x0000 +0x044A=0x0000 +0x044B=0x0000 +0x044C=0x0000 +0x044D=0x0000 +0x044E=0x0000 +0x044F=0x0000 +0x0450=0x0000 +0x0451=0x0000 +0x0452=0x0000 +0x0453=0x0000 +0x0454=0x0000 +0x0455=0x0000 +0x0456=0x0000 +0x0457=0x0000 +0x0458=0x0000 +0x0459=0x0000 +0x045A=0x0000 +0x045B=0x0000 +0x045C=0x0000 +0x045D=0x0000 +0x045E=0x0000 +0x045F=0x0000 +0x0460=0x0000 +0x0461=0x0000 +0x0480=0x0000 +0x0481=0x0000 +0x0482=0x0000 +0x0483=0x0000 +0x0484=0x0000 +0x0485=0x0000 +0x0486=0x0000 +0x0487=0x0000 +0x0488=0x0000 +0x0489=0x0000 +0x048A=0x0000 +0x048B=0x0000 +0x048C=0x0000 +0x048D=0x0000 +0x048E=0x0000 +0x048F=0x0000 +0x0490=0x0000 +0x0491=0x0000 +0x0492=0x0000 +0x0493=0x0000 +0x0494=0x0000 +0x0495=0x0000 +0x0496=0x0000 +0x0497=0x0000 +0x0498=0x0000 +0x0499=0x0000 +0x049A=0x0000 +0x049B=0x0000 +0x049C=0x0000 +0x049D=0x0000 +0x049E=0x0000 +0x049F=0x0000 +0x04A0=0x0000 +0x04A1=0x0000 +0x04A2=0x0000 +0x04A3=0x0000 +0x04A4=0x0000 +0x04A5=0x0000 +0x04A6=0x0000 +0x04A7=0x0000 +0x04C0=0x0000 +0x04C1=0x0000 +0x04C2=0x0000 +0x04C3=0x0000 +0x04C4=0x0000 +0x04C5=0x0000 +0x04C6=0x0000 +0x04C7=0x0000 +0x04C8=0x0000 +0x04C9=0x0000 +0x04CA=0x0000 +0x04CB=0x0000 +0x04CC=0x0000 +0x04CD=0x0000 +0x04CE=0x0000 +0x04CF=0x0000 +0x04D0=0x0000 +0x04D1=0x0000 +0x04D2=0x0000 +0x04D3=0x0000 +0x04D4=0x0000 +0x04D5=0x0000 +0x04D6=0x0000 +0x04D7=0x0000 +0x04D8=0x0000 +0x04D9=0x0000 +0x04DA=0x0000 +0x04DB=0x0000 +0x04DC=0x0000 +0x04DD=0x0000 +0x04DE=0x0000 +0x04DF=0x0000 +0x04E0=0x0000 +0x04E1=0x0000 +0x04E2=0x0000 +0x04E3=0x0000 +0x04E4=0x0000 +0x04E5=0x0000 +0x04E6=0x0000 +0x04E7=0x0000 +0x0500=0x0000 +0x0501=0x0000 +0x0502=0x0000 +0x0503=0x0000 +0x0504=0x0000 +0x0505=0x0000 +0x0506=0x0000 +0x0507=0x0000 +0x0508=0x0000 +0x0509=0x0000 +0x050A=0x0000 +0x050B=0x0000 +0x050C=0x0000 +0x050D=0x0000 +0x050E=0x0000 +0x050F=0x0000 +0x0510=0x0000 +0x0511=0x0000 +0x0512=0x0000 +0x0513=0x0000 +0x0514=0x0000 +0x0515=0x0000 +0x0516=0x0000 +0x0517=0x0000 +0x0518=0x0000 +0x0519=0x0000 +0x051A=0x0000 +0x051B=0x0000 +0x051C=0x0000 +0x051D=0x0000 +0x051E=0x0000 +0x051F=0x0000 +0x0520=0x0000 +0x0521=0x0000 +0x0522=0x0000 +0x0523=0x0000 +0x0524=0x0000 +0x0525=0x0000 +0x0526=0x0000 +0x0527=0x0000 +0x0540=0x0000 +0x0541=0x0000 +0x0542=0x0000 +0x0543=0x0000 +0x0544=0x0000 +0x0545=0x0000 +0x0546=0x0000 +0x0547=0x0000 +0x0548=0x0000 +0x0549=0x0000 +0x054A=0x0000 +0x054B=0x0000 +0x054C=0x0000 +0x054D=0x0000 +0x054E=0x0000 +0x054F=0x0000 +0x0550=0x0000 +0x0551=0x0000 +0x0552=0x0000 +0x0553=0x0000 +0x0554=0x0000 +0x0555=0x0000 +0x0556=0x0000 +0x0557=0x0000 +0x0558=0x0000 +0x0559=0x0000 +0x055A=0x0000 +0x055B=0x0000 +0x055C=0x0000 +0x055D=0x0000 +0x055E=0x0000 +0x055F=0x0000 +0x0560=0x0000 +0x0561=0x0000 +0x0562=0x0000 +0x0563=0x0000 +0x0564=0x0000 +0x0565=0x0000 +0x0566=0x0000 +0x0567=0x0000 +0x0580=0x0000 +0x0581=0x0000 +0x0582=0x0000 +0x0583=0x0000 +0x0584=0x0000 +0x0585=0x0000 +0x0586=0x0000 +0x0587=0x0000 +0x0588=0x0000 +0x0589=0x0000 +0x058A=0x0000 +0x058B=0x0000 +0x058C=0x0000 +0x058D=0x0000 +0x058E=0x0000 +0x058F=0x0000 +0x0590=0x0000 +0x0591=0x0000 +0x0592=0x0000 +0x0593=0x0000 +0x0594=0x0000 +0x0595=0x0000 +0x0596=0x0000 +0x0597=0x0000 +0x0598=0x0000 +0x0599=0x0000 +0x059A=0x0000 +0x059B=0x0000 +0x059C=0x0000 +0x059D=0x0000 +0x059E=0x0000 +0x059F=0x0000 +0x05A0=0x0000 +0x05A1=0x0000 +0x05A2=0x0000 +0x05A3=0x0000 +0x05A4=0x0000 +0x05A5=0x0000 +0x05A6=0x0000 +0x05A7=0x0000 +[lms7002_registers_b] +0x0100=0x3409 +0x0101=0x7800 +0x0102=0x3180 +0x0103=0x0A12 +0x0104=0x0088 +0x0105=0x0007 +0x0106=0x3182 +0x0107=0x318C +0x0108=0x3042 +0x0109=0x61C1 +0x010A=0x104C +0x010C=0x8865 +0x010D=0x019C +0x010E=0x2040 +0x010F=0x3042 +0x0110=0x0BF4 +0x0111=0x0083 +0x0112=0xC0E6 +0x0113=0x03C3 +0x0114=0x008D +0x0115=0x0009 +0x0116=0x8180 +0x0117=0x280C +0x0118=0x018C +0x0119=0x18CB +0x011A=0x2E02 +0x011C=0xA941 +0x011D=0x3B13 +0x011E=0x0631 +0x011F=0x3600 +0x0120=0xB9FF +0x0121=0x31DA +0x0122=0x033F +0x0123=0x267B +0x0124=0x0000 +0x0200=0x0101 +0x0201=0x05BD +0x0202=0x0779 +0x0203=0x0F9E +0x0204=0xBCC2 +0x0205=0x0000 +0x0206=0x0000 +0x0207=0x0000 +0x0208=0x0170 +0x0209=0x0000 +0x020A=0x0080 +0x020B=0x4000 +0x020C=0x7FFF +0x0240=0x0020 +0x0241=0x0000 +0x0242=0x0000 +0x0243=0x0000 +0x0244=0x0000 +0x0245=0x0000 +0x0246=0x0000 +0x0247=0x0000 +0x0248=0x0000 +0x0249=0x0000 +0x024A=0x0000 +0x024B=0x0000 +0x024C=0x0000 +0x024D=0x0000 +0x024E=0x0000 +0x024F=0x0000 +0x0250=0x0000 +0x0251=0x0000 +0x0252=0x0000 +0x0253=0x0000 +0x0254=0x0000 +0x0255=0x0000 +0x0256=0x0000 +0x0257=0x0000 +0x0258=0x0000 +0x0259=0x0000 +0x025A=0x0000 +0x025B=0x0000 +0x025C=0x0000 +0x025D=0x0000 +0x025E=0x0000 +0x025F=0x0000 +0x0260=0x0000 +0x0261=0x0000 +0x0280=0x0000 +0x0281=0x0000 +0x0282=0x0000 +0x0283=0x0000 +0x0284=0x0000 +0x0285=0x0000 +0x0286=0x0000 +0x0287=0x0000 +0x0288=0x0000 +0x0289=0x0000 +0x028A=0x0000 +0x028B=0x0000 +0x028C=0x0000 +0x028D=0x0000 +0x028E=0x0000 +0x028F=0x0000 +0x0290=0x0000 +0x0291=0x0000 +0x0292=0x0000 +0x0293=0x0000 +0x0294=0x0000 +0x0295=0x0000 +0x0296=0x0000 +0x0297=0x0000 +0x0298=0x0000 +0x0299=0x0000 +0x029A=0x0000 +0x029B=0x0000 +0x029C=0x0000 +0x029D=0x0000 +0x029E=0x0000 +0x029F=0x0000 +0x02A0=0x0000 +0x02A1=0x0000 +0x02A2=0x0000 +0x02A3=0x0000 +0x02A4=0x0000 +0x02A5=0x0000 +0x02A6=0x0000 +0x02A7=0x0000 +0x02C0=0x0000 +0x02C1=0x0000 +0x02C2=0x0000 +0x02C3=0x0000 +0x02C4=0x0000 +0x02C5=0x0000 +0x02C6=0x0000 +0x02C7=0x0000 +0x02C8=0x0000 +0x02C9=0x0000 +0x02CA=0x0000 +0x02CB=0x0000 +0x02CC=0x0000 +0x02CD=0x0000 +0x02CE=0x0000 +0x02CF=0x0000 +0x02D0=0x0000 +0x02D1=0x0000 +0x02D2=0x0000 +0x02D3=0x0000 +0x02D4=0x0000 +0x02D5=0x0000 +0x02D6=0x0000 +0x02D7=0x0000 +0x02D8=0x0000 +0x02D9=0x0000 +0x02DA=0x0000 +0x02DB=0x0000 +0x02DC=0x0000 +0x02DD=0x0000 +0x02DE=0x0000 +0x02DF=0x0000 +0x02E0=0x0000 +0x02E1=0x0000 +0x02E2=0x0000 +0x02E3=0x0000 +0x02E4=0x0000 +0x02E5=0x0000 +0x02E6=0x0000 +0x02E7=0x0000 +0x0300=0x0000 +0x0301=0x0000 +0x0302=0x0000 +0x0303=0x0000 +0x0304=0x0000 +0x0305=0x0000 +0x0306=0x0000 +0x0307=0x0000 +0x0308=0x0000 +0x0309=0x0000 +0x030A=0x0000 +0x030B=0x0000 +0x030C=0x0000 +0x030D=0x0000 +0x030E=0x0000 +0x030F=0x0000 +0x0310=0x0000 +0x0311=0x0000 +0x0312=0x0000 +0x0313=0x0000 +0x0314=0x0000 +0x0315=0x0000 +0x0316=0x0000 +0x0317=0x0000 +0x0318=0x0000 +0x0319=0x0000 +0x031A=0x0000 +0x031B=0x0000 +0x031C=0x0000 +0x031D=0x0000 +0x031E=0x0000 +0x031F=0x0000 +0x0320=0x0000 +0x0321=0x0000 +0x0322=0x0000 +0x0323=0x0000 +0x0324=0x0000 +0x0325=0x0000 +0x0326=0x0000 +0x0327=0x0000 +0x0340=0x0000 +0x0341=0x0000 +0x0342=0x0000 +0x0343=0x0000 +0x0344=0x0000 +0x0345=0x0000 +0x0346=0x0000 +0x0347=0x0000 +0x0348=0x0000 +0x0349=0x0000 +0x034A=0x0000 +0x034B=0x0000 +0x034C=0x0000 +0x034D=0x0000 +0x034E=0x0000 +0x034F=0x0000 +0x0350=0x0000 +0x0351=0x0000 +0x0352=0x0000 +0x0353=0x0000 +0x0354=0x0000 +0x0355=0x0000 +0x0356=0x0000 +0x0357=0x0000 +0x0358=0x0000 +0x0359=0x0000 +0x035A=0x0000 +0x035B=0x0000 +0x035C=0x0000 +0x035D=0x0000 +0x035E=0x0000 +0x035F=0x0000 +0x0360=0x0000 +0x0361=0x0000 +0x0362=0x0000 +0x0363=0x0000 +0x0364=0x0000 +0x0365=0x0000 +0x0366=0x0000 +0x0367=0x0000 +0x0380=0x0000 +0x0381=0x0000 +0x0382=0x0000 +0x0383=0x0000 +0x0384=0x0000 +0x0385=0x0000 +0x0386=0x0000 +0x0387=0x0000 +0x0388=0x0000 +0x0389=0x0000 +0x038A=0x0000 +0x038B=0x0000 +0x038C=0x0000 +0x038D=0x0000 +0x038E=0x0000 +0x038F=0x0000 +0x0390=0x0000 +0x0391=0x0000 +0x0392=0x0000 +0x0393=0x0000 +0x0394=0x0000 +0x0395=0x0000 +0x0396=0x0000 +0x0397=0x0000 +0x0398=0x0000 +0x0399=0x0000 +0x039A=0x0000 +0x039B=0x0000 +0x039C=0x0000 +0x039D=0x0000 +0x039E=0x0000 +0x039F=0x0000 +0x03A0=0x0000 +0x03A1=0x0000 +0x03A2=0x0000 +0x03A3=0x0000 +0x03A4=0x0000 +0x03A5=0x0000 +0x03A6=0x0000 +0x03A7=0x0000 +0x0400=0x0101 +0x0401=0x07FF +0x0402=0x079B +0x0403=0x0FF5 +0x0404=0x0000 +0x0405=0x0000 +0x0406=0x0000 +0x0407=0x0000 +0x0408=0x0000 +0x0409=0x0000 +0x040A=0x0000 +0x040B=0x7FFF +0x040C=0x00FC +0x040D=0x0000 +0x040E=0x0000 +0x040F=0x0000 +0x0440=0x0020 +0x0441=0x0000 +0x0442=0x0000 +0x0443=0x0000 +0x0444=0x0000 +0x0445=0x0000 +0x0446=0x0000 +0x0447=0x0000 +0x0448=0x0000 +0x0449=0x0000 +0x044A=0x0000 +0x044B=0x0000 +0x044C=0x0000 +0x044D=0x0000 +0x044E=0x0000 +0x044F=0x0000 +0x0450=0x0000 +0x0451=0x0000 +0x0452=0x0000 +0x0453=0x0000 +0x0454=0x0000 +0x0455=0x0000 +0x0456=0x0000 +0x0457=0x0000 +0x0458=0x0000 +0x0459=0x0000 +0x045A=0x0000 +0x045B=0x0000 +0x045C=0x0000 +0x045D=0x0000 +0x045E=0x0000 +0x045F=0x0000 +0x0460=0x0000 +0x0461=0x0000 +0x0480=0x0000 +0x0481=0x0000 +0x0482=0x0000 +0x0483=0x0000 +0x0484=0x0000 +0x0485=0x0000 +0x0486=0x0000 +0x0487=0x0000 +0x0488=0x0000 +0x0489=0x0000 +0x048A=0x0000 +0x048B=0x0000 +0x048C=0x0000 +0x048D=0x0000 +0x048E=0x0000 +0x048F=0x0000 +0x0490=0x0000 +0x0491=0x0000 +0x0492=0x0000 +0x0493=0x0000 +0x0494=0x0000 +0x0495=0x0000 +0x0496=0x0000 +0x0497=0x0000 +0x0498=0x0000 +0x0499=0x0000 +0x049A=0x0000 +0x049B=0x0000 +0x049C=0x0000 +0x049D=0x0000 +0x049E=0x0000 +0x049F=0x0000 +0x04A0=0x0000 +0x04A1=0x0000 +0x04A2=0x0000 +0x04A3=0x0000 +0x04A4=0x0000 +0x04A5=0x0000 +0x04A6=0x0000 +0x04A7=0x0000 +0x04C0=0x0000 +0x04C1=0x0000 +0x04C2=0x0000 +0x04C3=0x0000 +0x04C4=0x0000 +0x04C5=0x0000 +0x04C6=0x0000 +0x04C7=0x0000 +0x04C8=0x0000 +0x04C9=0x0000 +0x04CA=0x0000 +0x04CB=0x0000 +0x04CC=0x0000 +0x04CD=0x0000 +0x04CE=0x0000 +0x04CF=0x0000 +0x04D0=0x0000 +0x04D1=0x0000 +0x04D2=0x0000 +0x04D3=0x0000 +0x04D4=0x0000 +0x04D5=0x0000 +0x04D6=0x0000 +0x04D7=0x0000 +0x04D8=0x0000 +0x04D9=0x0000 +0x04DA=0x0000 +0x04DB=0x0000 +0x04DC=0x0000 +0x04DD=0x0000 +0x04DE=0x0000 +0x04DF=0x0000 +0x04E0=0x0000 +0x04E1=0x0000 +0x04E2=0x0000 +0x04E3=0x0000 +0x04E4=0x0000 +0x04E5=0x0000 +0x04E6=0x0000 +0x04E7=0x0000 +0x0500=0x0000 +0x0501=0x0000 +0x0502=0x0000 +0x0503=0x0000 +0x0504=0x0000 +0x0505=0x0000 +0x0506=0x0000 +0x0507=0x0000 +0x0508=0x0000 +0x0509=0x0000 +0x050A=0x0000 +0x050B=0x0000 +0x050C=0x0000 +0x050D=0x0000 +0x050E=0x0000 +0x050F=0x0000 +0x0510=0x0000 +0x0511=0x0000 +0x0512=0x0000 +0x0513=0x0000 +0x0514=0x0000 +0x0515=0x0000 +0x0516=0x0000 +0x0517=0x0000 +0x0518=0x0000 +0x0519=0x0000 +0x051A=0x0000 +0x051B=0x0000 +0x051C=0x0000 +0x051D=0x0000 +0x051E=0x0000 +0x051F=0x0000 +0x0520=0x0000 +0x0521=0x0000 +0x0522=0x0000 +0x0523=0x0000 +0x0524=0x0000 +0x0525=0x0000 +0x0526=0x0000 +0x0527=0x0000 +0x0540=0x0000 +0x0541=0x0000 +0x0542=0x0000 +0x0543=0x0000 +0x0544=0x0000 +0x0545=0x0000 +0x0546=0x0000 +0x0547=0x0000 +0x0548=0x0000 +0x0549=0x0000 +0x054A=0x0000 +0x054B=0x0000 +0x054C=0x0000 +0x054D=0x0000 +0x054E=0x0000 +0x054F=0x0000 +0x0550=0x0000 +0x0551=0x0000 +0x0552=0x0000 +0x0553=0x0000 +0x0554=0x0000 +0x0555=0x0000 +0x0556=0x0000 +0x0557=0x0000 +0x0558=0x0000 +0x0559=0x0000 +0x055A=0x0000 +0x055B=0x0000 +0x055C=0x0000 +0x055D=0x0000 +0x055E=0x0000 +0x055F=0x0000 +0x0560=0x0000 +0x0561=0x0000 +0x0562=0x0000 +0x0563=0x0000 +0x0564=0x0000 +0x0565=0x0000 +0x0566=0x0000 +0x0567=0x0000 +0x0580=0x0000 +0x0581=0x0000 +0x0582=0x0000 +0x0583=0x0000 +0x0584=0x0000 +0x0585=0x0000 +0x0586=0x0000 +0x0587=0x0000 +0x0588=0x0000 +0x0589=0x0000 +0x058A=0x0000 +0x058B=0x0000 +0x058C=0x0000 +0x058D=0x0000 +0x058E=0x0000 +0x058F=0x0000 +0x0590=0x0000 +0x0591=0x0000 +0x0592=0x0000 +0x0593=0x0000 +0x0594=0x0000 +0x0595=0x0000 +0x0596=0x0000 +0x0597=0x0000 +0x0598=0x0000 +0x0599=0x0000 +0x059A=0x0000 +0x059B=0x0000 +0x059C=0x0000 +0x059D=0x0000 +0x059E=0x0000 +0x059F=0x0000 +0x05A0=0x0000 +0x05A1=0x0000 +0x05A2=0x0000 +0x05A3=0x0000 +0x05A4=0x0000 +0x05A5=0x0000 +0x05A6=0x0000 +0x05A7=0x0000 +[reference_clocks] +sxr_ref_clk_mhz=52 +sxt_ref_clk_mhz=52 diff --git a/targets/ARCH/SODERA/lms7_trx_LTE_mimo_TSG.ini b/targets/ARCH/SODERA/lms7_trx_LTE_mimo_TSG.ini new file mode 100644 index 0000000000..fb25b06527 --- /dev/null +++ b/targets/ARCH/SODERA/lms7_trx_LTE_mimo_TSG.ini @@ -0,0 +1,1128 @@ +[file_info] +type=lms7002m_minimal_config +version=1 +[lms7002_registers_a] +0x0020=0xFFFD +0x0021=0x0E9F +0x0022=0x07FF +0x0023=0x5550 +0x0024=0xE4E4 +0x0025=0x0101 +0x0026=0x0101 +0x0027=0xE4E4 +0x0028=0x0101 +0x0029=0x0101 +0x002A=0x0086 +0x002B=0x0038 +0x002C=0x0000 +0x002D=0xFFFF +0x002E=0x0000 +0x002F=0x3840 +0x0081=0x0000 +0x0082=0x8001 +0x0084=0x0400 +0x0085=0x0001 +0x0086=0x4101 +0x0087=0xB13B +0x0088=0x0303 +0x0089=0x1078 +0x008A=0x0514 +0x008B=0x2184 +0x008C=0x267B +0x0092=0x0001 +0x0093=0x0000 +0x0094=0x0000 +0x0095=0x0000 +0x0096=0x0000 +0x0097=0x0000 +0x0098=0x0000 +0x0099=0x6565 +0x009A=0x658C +0x009B=0x6565 +0x009C=0x658C +0x009D=0x6565 +0x009E=0x658C +0x009F=0x658C +0x00A0=0x6565 +0x00A1=0x6565 +0x00A2=0x6565 +0x00A3=0x6565 +0x00A4=0x6565 +0x00A5=0x6565 +0x00A6=0x0001 +0x00A7=0x6565 +0x00A8=0x0000 +0x00A9=0x8000 +0x00AA=0x0000 +0x00AB=0x0040 +0x00AC=0x2000 +0x00AD=0x03FF +0x00AE=0x0000 +0x0100=0x7409 +0x0101=0x7800 +0x0102=0x3180 +0x0103=0x0A12 +0x0104=0x0088 +0x0105=0x0007 +0x0106=0x3182 +0x0107=0x318C +0x0108=0x9442 +0x0109=0x61C1 +0x010A=0x104C +0x010C=0x8865 +0x010D=0x011A +0x010E=0x2040 +0x010F=0x3042 +0x0110=0x0BF4 +0x0111=0x0083 +0x0112=0xC0E6 +0x0113=0x03C3 +0x0114=0x008D +0x0115=0x0009 +0x0116=0x8180 +0x0117=0x280C +0x0118=0x018C +0x0119=0x18CB +0x011A=0x2E02 +0x011C=0xAD41 +0x011D=0x9D89 +0x011E=0x0398 +0x011F=0x3680 +0x0120=0xB9FF +0x0121=0x3692 +0x0122=0x033F +0x0123=0x267B +0x0124=0x0000 +0x0200=0x0081 +0x0201=0x07B0 +0x0202=0x06F2 +0x0203=0x0FC2 +0x0204=0xD51F +0x0205=0x0000 +0x0206=0x0000 +0x0207=0x0000 +0x0208=0x0070 +0x0209=0x0000 +0x020A=0x0080 +0x020B=0x4000 +0x020C=0x7FFF +0x0240=0x0020 +0x0241=0x0000 +0x0242=0x0000 +0x0243=0x0000 +0x0244=0x0000 +0x0245=0x0000 +0x0246=0x0000 +0x0247=0x0000 +0x0248=0x0000 +0x0249=0x0000 +0x024A=0x0000 +0x024B=0x0000 +0x024C=0x0000 +0x024D=0x0000 +0x024E=0x0000 +0x024F=0x0000 +0x0250=0x0000 +0x0251=0x0000 +0x0252=0x0000 +0x0253=0x0000 +0x0254=0x0000 +0x0255=0x0000 +0x0256=0x0000 +0x0257=0x0000 +0x0258=0x0000 +0x0259=0x0000 +0x025A=0x0000 +0x025B=0x0000 +0x025C=0x0000 +0x025D=0x0000 +0x025E=0x0000 +0x025F=0x0000 +0x0260=0x0000 +0x0261=0x0000 +0x0280=0x0000 +0x0281=0x0000 +0x0282=0x0000 +0x0283=0x0000 +0x0284=0x0000 +0x0285=0x0000 +0x0286=0x0000 +0x0287=0x0000 +0x0288=0x0000 +0x0289=0x0000 +0x028A=0x0000 +0x028B=0x0000 +0x028C=0x0000 +0x028D=0x0000 +0x028E=0x0000 +0x028F=0x0000 +0x0290=0x0000 +0x0291=0x0000 +0x0292=0x0000 +0x0293=0x0000 +0x0294=0x0000 +0x0295=0x0000 +0x0296=0x0000 +0x0297=0x0000 +0x0298=0x0000 +0x0299=0x0000 +0x029A=0x0000 +0x029B=0x0000 +0x029C=0x0000 +0x029D=0x0000 +0x029E=0x0000 +0x029F=0x0000 +0x02A0=0x0000 +0x02A1=0x0000 +0x02A2=0x0000 +0x02A3=0x0000 +0x02A4=0x0000 +0x02A5=0x0000 +0x02A6=0x0000 +0x02A7=0x0000 +0x02C0=0x0000 +0x02C1=0x0000 +0x02C2=0x0000 +0x02C3=0x0000 +0x02C4=0x0000 +0x02C5=0x0000 +0x02C6=0x0000 +0x02C7=0x0000 +0x02C8=0x0000 +0x02C9=0x0000 +0x02CA=0x0000 +0x02CB=0x0000 +0x02CC=0x0000 +0x02CD=0x0000 +0x02CE=0x0000 +0x02CF=0x0000 +0x02D0=0x0000 +0x02D1=0x0000 +0x02D2=0x0000 +0x02D3=0x0000 +0x02D4=0x0000 +0x02D5=0x0000 +0x02D6=0x0000 +0x02D7=0x0000 +0x02D8=0x0000 +0x02D9=0x0000 +0x02DA=0x0000 +0x02DB=0x0000 +0x02DC=0x0000 +0x02DD=0x0000 +0x02DE=0x0000 +0x02DF=0x0000 +0x02E0=0x0000 +0x02E1=0x0000 +0x02E2=0x0000 +0x02E3=0x0000 +0x02E4=0x0000 +0x02E5=0x0000 +0x02E6=0x0000 +0x02E7=0x0000 +0x0300=0x0000 +0x0301=0x0000 +0x0302=0x0000 +0x0303=0x0000 +0x0304=0x0000 +0x0305=0x0000 +0x0306=0x0000 +0x0307=0x0000 +0x0308=0x0000 +0x0309=0x0000 +0x030A=0x0000 +0x030B=0x0000 +0x030C=0x0000 +0x030D=0x0000 +0x030E=0x0000 +0x030F=0x0000 +0x0310=0x0000 +0x0311=0x0000 +0x0312=0x0000 +0x0313=0x0000 +0x0314=0x0000 +0x0315=0x0000 +0x0316=0x0000 +0x0317=0x0000 +0x0318=0x0000 +0x0319=0x0000 +0x031A=0x0000 +0x031B=0x0000 +0x031C=0x0000 +0x031D=0x0000 +0x031E=0x0000 +0x031F=0x0000 +0x0320=0x0000 +0x0321=0x0000 +0x0322=0x0000 +0x0323=0x0000 +0x0324=0x0000 +0x0325=0x0000 +0x0326=0x0000 +0x0327=0x0000 +0x0340=0x0000 +0x0341=0x0000 +0x0342=0x0000 +0x0343=0x0000 +0x0344=0x0000 +0x0345=0x0000 +0x0346=0x0000 +0x0347=0x0000 +0x0348=0x0000 +0x0349=0x0000 +0x034A=0x0000 +0x034B=0x0000 +0x034C=0x0000 +0x034D=0x0000 +0x034E=0x0000 +0x034F=0x0000 +0x0350=0x0000 +0x0351=0x0000 +0x0352=0x0000 +0x0353=0x0000 +0x0354=0x0000 +0x0355=0x0000 +0x0356=0x0000 +0x0357=0x0000 +0x0358=0x0000 +0x0359=0x0000 +0x035A=0x0000 +0x035B=0x0000 +0x035C=0x0000 +0x035D=0x0000 +0x035E=0x0000 +0x035F=0x0000 +0x0360=0x0000 +0x0361=0x0000 +0x0362=0x0000 +0x0363=0x0000 +0x0364=0x0000 +0x0365=0x0000 +0x0366=0x0000 +0x0367=0x0000 +0x0380=0x0000 +0x0381=0x0000 +0x0382=0x0000 +0x0383=0x0000 +0x0384=0x0000 +0x0385=0x0000 +0x0386=0x0000 +0x0387=0x0000 +0x0388=0x0000 +0x0389=0x0000 +0x038A=0x0000 +0x038B=0x0000 +0x038C=0x0000 +0x038D=0x0000 +0x038E=0x0000 +0x038F=0x0000 +0x0390=0x0000 +0x0391=0x0000 +0x0392=0x0000 +0x0393=0x0000 +0x0394=0x0000 +0x0395=0x0000 +0x0396=0x0000 +0x0397=0x0000 +0x0398=0x0000 +0x0399=0x0000 +0x039A=0x0000 +0x039B=0x0000 +0x039C=0x0000 +0x039D=0x0000 +0x039E=0x0000 +0x039F=0x0000 +0x03A0=0x0000 +0x03A1=0x0000 +0x03A2=0x0000 +0x03A3=0x0000 +0x03A4=0x0000 +0x03A5=0x0000 +0x03A6=0x0000 +0x03A7=0x0000 +0x0400=0x0085 +0x0401=0x07FF +0x0402=0x07FF +0x0403=0x0000 +0x0404=0x0000 +0x0405=0x0000 +0x0406=0x0000 +0x0407=0x0000 +0x0408=0x0000 +0x0409=0x0000 +0x040A=0x0003 +0x040B=0x000F +0x040C=0x00FC +0x040D=0x0000 +0x040E=0x0000 +0x040F=0x0000 +0x0440=0x0020 +0x0441=0x0000 +0x0442=0x0563 +0x0443=0xB490 +0x0444=0x02B1 +0x0445=0xDA48 +0x0446=0x0000 +0x0447=0x0000 +0x0448=0x0000 +0x0449=0x0000 +0x044A=0x0000 +0x044B=0x0000 +0x044C=0x0000 +0x044D=0x0000 +0x044E=0x0000 +0x044F=0x0000 +0x0450=0x0000 +0x0451=0x0000 +0x0452=0x0000 +0x0453=0x0000 +0x0454=0x0000 +0x0455=0x0000 +0x0456=0x0000 +0x0457=0x0000 +0x0458=0x0000 +0x0459=0x0000 +0x045A=0x0000 +0x045B=0x0000 +0x045C=0x0000 +0x045D=0x0000 +0x045E=0x0000 +0x045F=0x0000 +0x0460=0x0000 +0x0461=0x0000 +0x0480=0x0000 +0x0481=0x0000 +0x0482=0x0000 +0x0483=0x0000 +0x0484=0x0000 +0x0485=0x0000 +0x0486=0x0000 +0x0487=0x0000 +0x0488=0x0000 +0x0489=0x0000 +0x048A=0x0000 +0x048B=0x0000 +0x048C=0x0000 +0x048D=0x0000 +0x048E=0x0000 +0x048F=0x0000 +0x0490=0x0000 +0x0491=0x0000 +0x0492=0x0000 +0x0493=0x0000 +0x0494=0x0000 +0x0495=0x0000 +0x0496=0x0000 +0x0497=0x0000 +0x0498=0x0000 +0x0499=0x0000 +0x049A=0x0000 +0x049B=0x0000 +0x049C=0x0000 +0x049D=0x0000 +0x049E=0x0000 +0x049F=0x0000 +0x04A0=0x0000 +0x04A1=0x0000 +0x04A2=0x0000 +0x04A3=0x0000 +0x04A4=0x0000 +0x04A5=0x0000 +0x04A6=0x0000 +0x04A7=0x0000 +0x04C0=0x0000 +0x04C1=0x0000 +0x04C2=0x0000 +0x04C3=0x0000 +0x04C4=0x0000 +0x04C5=0x0000 +0x04C6=0x0000 +0x04C7=0x0000 +0x04C8=0x0000 +0x04C9=0x0000 +0x04CA=0x0000 +0x04CB=0x0000 +0x04CC=0x0000 +0x04CD=0x0000 +0x04CE=0x0000 +0x04CF=0x0000 +0x04D0=0x0000 +0x04D1=0x0000 +0x04D2=0x0000 +0x04D3=0x0000 +0x04D4=0x0000 +0x04D5=0x0000 +0x04D6=0x0000 +0x04D7=0x0000 +0x04D8=0x0000 +0x04D9=0x0000 +0x04DA=0x0000 +0x04DB=0x0000 +0x04DC=0x0000 +0x04DD=0x0000 +0x04DE=0x0000 +0x04DF=0x0000 +0x04E0=0x0000 +0x04E1=0x0000 +0x04E2=0x0000 +0x04E3=0x0000 +0x04E4=0x0000 +0x04E5=0x0000 +0x04E6=0x0000 +0x04E7=0x0000 +0x0500=0x0000 +0x0501=0x0000 +0x0502=0x0000 +0x0503=0x0000 +0x0504=0x0000 +0x0505=0x0000 +0x0506=0x0000 +0x0507=0x0000 +0x0508=0x0000 +0x0509=0x0000 +0x050A=0x0000 +0x050B=0x0000 +0x050C=0x0000 +0x050D=0x0000 +0x050E=0x0000 +0x050F=0x0000 +0x0510=0x0000 +0x0511=0x0000 +0x0512=0x0000 +0x0513=0x0000 +0x0514=0x0000 +0x0515=0x0000 +0x0516=0x0000 +0x0517=0x0000 +0x0518=0x0000 +0x0519=0x0000 +0x051A=0x0000 +0x051B=0x0000 +0x051C=0x0000 +0x051D=0x0000 +0x051E=0x0000 +0x051F=0x0000 +0x0520=0x0000 +0x0521=0x0000 +0x0522=0x0000 +0x0523=0x0000 +0x0524=0x0000 +0x0525=0x0000 +0x0526=0x0000 +0x0527=0x0000 +0x0540=0x0000 +0x0541=0x0000 +0x0542=0x0000 +0x0543=0x0000 +0x0544=0x0000 +0x0545=0x0000 +0x0546=0x0000 +0x0547=0x0000 +0x0548=0x0000 +0x0549=0x0000 +0x054A=0x0000 +0x054B=0x0000 +0x054C=0x0000 +0x054D=0x0000 +0x054E=0x0000 +0x054F=0x0000 +0x0550=0x0000 +0x0551=0x0000 +0x0552=0x0000 +0x0553=0x0000 +0x0554=0x0000 +0x0555=0x0000 +0x0556=0x0000 +0x0557=0x0000 +0x0558=0x0000 +0x0559=0x0000 +0x055A=0x0000 +0x055B=0x0000 +0x055C=0x0000 +0x055D=0x0000 +0x055E=0x0000 +0x055F=0x0000 +0x0560=0x0000 +0x0561=0x0000 +0x0562=0x0000 +0x0563=0x0000 +0x0564=0x0000 +0x0565=0x0000 +0x0566=0x0000 +0x0567=0x0000 +0x0580=0x0000 +0x0581=0x0000 +0x0582=0x0000 +0x0583=0x0000 +0x0584=0x0000 +0x0585=0x0000 +0x0586=0x0000 +0x0587=0x0000 +0x0588=0x0000 +0x0589=0x0000 +0x058A=0x0000 +0x058B=0x0000 +0x058C=0x0000 +0x058D=0x0000 +0x058E=0x0000 +0x058F=0x0000 +0x0590=0x0000 +0x0591=0x0000 +0x0592=0x0000 +0x0593=0x0000 +0x0594=0x0000 +0x0595=0x0000 +0x0596=0x0000 +0x0597=0x0000 +0x0598=0x0000 +0x0599=0x0000 +0x059A=0x0000 +0x059B=0x0000 +0x059C=0x0000 +0x059D=0x0000 +0x059E=0x0000 +0x059F=0x0000 +0x05A0=0x0000 +0x05A1=0x0000 +0x05A2=0x0000 +0x05A3=0x0000 +0x05A4=0x0000 +0x05A5=0x0000 +0x05A6=0x0000 +0x05A7=0x0000 +[lms7002_registers_b] +0x0100=0x3409 +0x0101=0x7800 +0x0102=0x3180 +0x0103=0x0A12 +0x0104=0x0088 +0x0105=0x0007 +0x0106=0x3182 +0x0107=0x318C +0x0108=0x9442 +0x0109=0x61C1 +0x010A=0x104C +0x010C=0x88FD +0x010D=0x009E +0x010E=0x2040 +0x010F=0x3042 +0x0110=0x0BF4 +0x0111=0x0083 +0x0112=0xC0E6 +0x0113=0x03C3 +0x0114=0x008D +0x0115=0x0009 +0x0116=0x8180 +0x0117=0x280C +0x0118=0x018C +0x0119=0x18CB +0x011A=0x2E02 +0x011C=0xA941 +0x011D=0xEC4E +0x011E=0x04E4 +0x011F=0x3600 +0x0120=0xB9FF +0x0121=0x3348 +0x0122=0x033F +0x0123=0x267B +0x0124=0x0000 +0x0200=0x0101 +0x0201=0x05BD +0x0202=0x0779 +0x0203=0x0F9E +0x0204=0xBCC2 +0x0205=0x0000 +0x0206=0x0000 +0x0207=0x0000 +0x0208=0x0070 +0x0209=0x0000 +0x020A=0x0080 +0x020B=0x4000 +0x020C=0x7FFF +0x0240=0x0020 +0x0241=0x0000 +0x0242=0x0000 +0x0243=0x0000 +0x0244=0x0000 +0x0245=0x0000 +0x0246=0x0000 +0x0247=0x0000 +0x0248=0x0000 +0x0249=0x0000 +0x024A=0x0000 +0x024B=0x0000 +0x024C=0x0000 +0x024D=0x0000 +0x024E=0x0000 +0x024F=0x0000 +0x0250=0x0000 +0x0251=0x0000 +0x0252=0x0000 +0x0253=0x0000 +0x0254=0x0000 +0x0255=0x0000 +0x0256=0x0000 +0x0257=0x0000 +0x0258=0x0000 +0x0259=0x0000 +0x025A=0x0000 +0x025B=0x0000 +0x025C=0x0000 +0x025D=0x0000 +0x025E=0x0000 +0x025F=0x0000 +0x0260=0x0000 +0x0261=0x0000 +0x0280=0x0000 +0x0281=0x0000 +0x0282=0x0000 +0x0283=0x0000 +0x0284=0x0000 +0x0285=0x0000 +0x0286=0x0000 +0x0287=0x0000 +0x0288=0x0000 +0x0289=0x0000 +0x028A=0x0000 +0x028B=0x0000 +0x028C=0x0000 +0x028D=0x0000 +0x028E=0x0000 +0x028F=0x0000 +0x0290=0x0000 +0x0291=0x0000 +0x0292=0x0000 +0x0293=0x0000 +0x0294=0x0000 +0x0295=0x0000 +0x0296=0x0000 +0x0297=0x0000 +0x0298=0x0000 +0x0299=0x0000 +0x029A=0x0000 +0x029B=0x0000 +0x029C=0x0000 +0x029D=0x0000 +0x029E=0x0000 +0x029F=0x0000 +0x02A0=0x0000 +0x02A1=0x0000 +0x02A2=0x0000 +0x02A3=0x0000 +0x02A4=0x0000 +0x02A5=0x0000 +0x02A6=0x0000 +0x02A7=0x0000 +0x02C0=0x0000 +0x02C1=0x0000 +0x02C2=0x0000 +0x02C3=0x0000 +0x02C4=0x0000 +0x02C5=0x0000 +0x02C6=0x0000 +0x02C7=0x0000 +0x02C8=0x0000 +0x02C9=0x0000 +0x02CA=0x0000 +0x02CB=0x0000 +0x02CC=0x0000 +0x02CD=0x0000 +0x02CE=0x0000 +0x02CF=0x0000 +0x02D0=0x0000 +0x02D1=0x0000 +0x02D2=0x0000 +0x02D3=0x0000 +0x02D4=0x0000 +0x02D5=0x0000 +0x02D6=0x0000 +0x02D7=0x0000 +0x02D8=0x0000 +0x02D9=0x0000 +0x02DA=0x0000 +0x02DB=0x0000 +0x02DC=0x0000 +0x02DD=0x0000 +0x02DE=0x0000 +0x02DF=0x0000 +0x02E0=0x0000 +0x02E1=0x0000 +0x02E2=0x0000 +0x02E3=0x0000 +0x02E4=0x0000 +0x02E5=0x0000 +0x02E6=0x0000 +0x02E7=0x0000 +0x0300=0x0000 +0x0301=0x0000 +0x0302=0x0000 +0x0303=0x0000 +0x0304=0x0000 +0x0305=0x0000 +0x0306=0x0000 +0x0307=0x0000 +0x0308=0x0000 +0x0309=0x0000 +0x030A=0x0000 +0x030B=0x0000 +0x030C=0x0000 +0x030D=0x0000 +0x030E=0x0000 +0x030F=0x0000 +0x0310=0x0000 +0x0311=0x0000 +0x0312=0x0000 +0x0313=0x0000 +0x0314=0x0000 +0x0315=0x0000 +0x0316=0x0000 +0x0317=0x0000 +0x0318=0x0000 +0x0319=0x0000 +0x031A=0x0000 +0x031B=0x0000 +0x031C=0x0000 +0x031D=0x0000 +0x031E=0x0000 +0x031F=0x0000 +0x0320=0x0000 +0x0321=0x0000 +0x0322=0x0000 +0x0323=0x0000 +0x0324=0x0000 +0x0325=0x0000 +0x0326=0x0000 +0x0327=0x0000 +0x0340=0x0000 +0x0341=0x0000 +0x0342=0x0000 +0x0343=0x0000 +0x0344=0x0000 +0x0345=0x0000 +0x0346=0x0000 +0x0347=0x0000 +0x0348=0x0000 +0x0349=0x0000 +0x034A=0x0000 +0x034B=0x0000 +0x034C=0x0000 +0x034D=0x0000 +0x034E=0x0000 +0x034F=0x0000 +0x0350=0x0000 +0x0351=0x0000 +0x0352=0x0000 +0x0353=0x0000 +0x0354=0x0000 +0x0355=0x0000 +0x0356=0x0000 +0x0357=0x0000 +0x0358=0x0000 +0x0359=0x0000 +0x035A=0x0000 +0x035B=0x0000 +0x035C=0x0000 +0x035D=0x0000 +0x035E=0x0000 +0x035F=0x0000 +0x0360=0x0000 +0x0361=0x0000 +0x0362=0x0000 +0x0363=0x0000 +0x0364=0x0000 +0x0365=0x0000 +0x0366=0x0000 +0x0367=0x0000 +0x0380=0x0000 +0x0381=0x0000 +0x0382=0x0000 +0x0383=0x0000 +0x0384=0x0000 +0x0385=0x0000 +0x0386=0x0000 +0x0387=0x0000 +0x0388=0x0000 +0x0389=0x0000 +0x038A=0x0000 +0x038B=0x0000 +0x038C=0x0000 +0x038D=0x0000 +0x038E=0x0000 +0x038F=0x0000 +0x0390=0x0000 +0x0391=0x0000 +0x0392=0x0000 +0x0393=0x0000 +0x0394=0x0000 +0x0395=0x0000 +0x0396=0x0000 +0x0397=0x0000 +0x0398=0x0000 +0x0399=0x0000 +0x039A=0x0000 +0x039B=0x0000 +0x039C=0x0000 +0x039D=0x0000 +0x039E=0x0000 +0x039F=0x0000 +0x03A0=0x0000 +0x03A1=0x0000 +0x03A2=0x0000 +0x03A3=0x0000 +0x03A4=0x0000 +0x03A5=0x0000 +0x03A6=0x0000 +0x03A7=0x0000 +0x0400=0x0105 +0x0401=0x07FF +0x0402=0x079B +0x0403=0x0FF5 +0x0404=0x0000 +0x0405=0x0000 +0x0406=0x0000 +0x0407=0x0000 +0x0408=0x0000 +0x0409=0x0000 +0x040A=0x0000 +0x040B=0x7FFF +0x040C=0x00FC +0x040D=0x0000 +0x040E=0x0000 +0x040F=0x0000 +0x0440=0x0020 +0x0441=0x0000 +0x0442=0x0000 +0x0443=0x0000 +0x0444=0x0000 +0x0445=0x0000 +0x0446=0x0000 +0x0447=0x0000 +0x0448=0x0000 +0x0449=0x0000 +0x044A=0x0000 +0x044B=0x0000 +0x044C=0x0000 +0x044D=0x0000 +0x044E=0x0000 +0x044F=0x0000 +0x0450=0x0000 +0x0451=0x0000 +0x0452=0x0000 +0x0453=0x0000 +0x0454=0x0000 +0x0455=0x0000 +0x0456=0x0000 +0x0457=0x0000 +0x0458=0x0000 +0x0459=0x0000 +0x045A=0x0000 +0x045B=0x0000 +0x045C=0x0000 +0x045D=0x0000 +0x045E=0x0000 +0x045F=0x0000 +0x0460=0x0000 +0x0461=0x0000 +0x0480=0x0000 +0x0481=0x0000 +0x0482=0x0000 +0x0483=0x0000 +0x0484=0x0000 +0x0485=0x0000 +0x0486=0x0000 +0x0487=0x0000 +0x0488=0x0000 +0x0489=0x0000 +0x048A=0x0000 +0x048B=0x0000 +0x048C=0x0000 +0x048D=0x0000 +0x048E=0x0000 +0x048F=0x0000 +0x0490=0x0000 +0x0491=0x0000 +0x0492=0x0000 +0x0493=0x0000 +0x0494=0x0000 +0x0495=0x0000 +0x0496=0x0000 +0x0497=0x0000 +0x0498=0x0000 +0x0499=0x0000 +0x049A=0x0000 +0x049B=0x0000 +0x049C=0x0000 +0x049D=0x0000 +0x049E=0x0000 +0x049F=0x0000 +0x04A0=0x0000 +0x04A1=0x0000 +0x04A2=0x0000 +0x04A3=0x0000 +0x04A4=0x0000 +0x04A5=0x0000 +0x04A6=0x0000 +0x04A7=0x0000 +0x04C0=0x0000 +0x04C1=0x0000 +0x04C2=0x0000 +0x04C3=0x0000 +0x04C4=0x0000 +0x04C5=0x0000 +0x04C6=0x0000 +0x04C7=0x0000 +0x04C8=0x0000 +0x04C9=0x0000 +0x04CA=0x0000 +0x04CB=0x0000 +0x04CC=0x0000 +0x04CD=0x0000 +0x04CE=0x0000 +0x04CF=0x0000 +0x04D0=0x0000 +0x04D1=0x0000 +0x04D2=0x0000 +0x04D3=0x0000 +0x04D4=0x0000 +0x04D5=0x0000 +0x04D6=0x0000 +0x04D7=0x0000 +0x04D8=0x0000 +0x04D9=0x0000 +0x04DA=0x0000 +0x04DB=0x0000 +0x04DC=0x0000 +0x04DD=0x0000 +0x04DE=0x0000 +0x04DF=0x0000 +0x04E0=0x0000 +0x04E1=0x0000 +0x04E2=0x0000 +0x04E3=0x0000 +0x04E4=0x0000 +0x04E5=0x0000 +0x04E6=0x0000 +0x04E7=0x0000 +0x0500=0x0000 +0x0501=0x0000 +0x0502=0x0000 +0x0503=0x0000 +0x0504=0x0000 +0x0505=0x0000 +0x0506=0x0000 +0x0507=0x0000 +0x0508=0x0000 +0x0509=0x0000 +0x050A=0x0000 +0x050B=0x0000 +0x050C=0x0000 +0x050D=0x0000 +0x050E=0x0000 +0x050F=0x0000 +0x0510=0x0000 +0x0511=0x0000 +0x0512=0x0000 +0x0513=0x0000 +0x0514=0x0000 +0x0515=0x0000 +0x0516=0x0000 +0x0517=0x0000 +0x0518=0x0000 +0x0519=0x0000 +0x051A=0x0000 +0x051B=0x0000 +0x051C=0x0000 +0x051D=0x0000 +0x051E=0x0000 +0x051F=0x0000 +0x0520=0x0000 +0x0521=0x0000 +0x0522=0x0000 +0x0523=0x0000 +0x0524=0x0000 +0x0525=0x0000 +0x0526=0x0000 +0x0527=0x0000 +0x0540=0x0000 +0x0541=0x0000 +0x0542=0x0000 +0x0543=0x0000 +0x0544=0x0000 +0x0545=0x0000 +0x0546=0x0000 +0x0547=0x0000 +0x0548=0x0000 +0x0549=0x0000 +0x054A=0x0000 +0x054B=0x0000 +0x054C=0x0000 +0x054D=0x0000 +0x054E=0x0000 +0x054F=0x0000 +0x0550=0x0000 +0x0551=0x0000 +0x0552=0x0000 +0x0553=0x0000 +0x0554=0x0000 +0x0555=0x0000 +0x0556=0x0000 +0x0557=0x0000 +0x0558=0x0000 +0x0559=0x0000 +0x055A=0x0000 +0x055B=0x0000 +0x055C=0x0000 +0x055D=0x0000 +0x055E=0x0000 +0x055F=0x0000 +0x0560=0x0000 +0x0561=0x0000 +0x0562=0x0000 +0x0563=0x0000 +0x0564=0x0000 +0x0565=0x0000 +0x0566=0x0000 +0x0567=0x0000 +0x0580=0x0000 +0x0581=0x0000 +0x0582=0x0000 +0x0583=0x0000 +0x0584=0x0000 +0x0585=0x0000 +0x0586=0x0000 +0x0587=0x0000 +0x0588=0x0000 +0x0589=0x0000 +0x058A=0x0000 +0x058B=0x0000 +0x058C=0x0000 +0x058D=0x0000 +0x058E=0x0000 +0x058F=0x0000 +0x0590=0x0000 +0x0591=0x0000 +0x0592=0x0000 +0x0593=0x0000 +0x0594=0x0000 +0x0595=0x0000 +0x0596=0x0000 +0x0597=0x0000 +0x0598=0x0000 +0x0599=0x0000 +0x059A=0x0000 +0x059B=0x0000 +0x059C=0x0000 +0x059D=0x0000 +0x059E=0x0000 +0x059F=0x0000 +0x05A0=0x0000 +0x05A1=0x0000 +0x05A2=0x0000 +0x05A3=0x0000 +0x05A4=0x0000 +0x05A5=0x0000 +0x05A6=0x0000 +0x05A7=0x0000 +[reference_clocks] +sxr_ref_clk_mhz=52 +sxt_ref_clk_mhz=52 diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band4.tm1.usrpb210.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band4.tm1.usrpb210.conf index ee4700c771..853db14393 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band4.tm1.usrpb210.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band4.tm1.usrpb210.conf @@ -17,7 +17,7 @@ eNBs = mobile_country_code = "208"; - mobile_network_code = "92"; + mobile_network_code = "93"; ////////// Physical parameters: @@ -36,7 +36,7 @@ eNBs = nb_antennas_tx = 1; nb_antennas_rx = 1; tx_gain = 90; - rx_gain = 120; + rx_gain = 128; prach_root = 0; prach_config_index = 0; prach_high_speed = "DISABLE"; @@ -66,7 +66,7 @@ eNBs = pusch_p0_Nominal = -90; pusch_alpha = "AL1"; - pucch_p0_Nominal = -108; + pucch_p0_Nominal = -96; msg3_delta_Preamble = 6; pucch_deltaF_Format1 = "deltaF2"; pucch_deltaF_Format1b = "deltaF3"; @@ -131,7 +131,7 @@ eNBs = }; ////////// MME parameters: - mme_ip_address = ( { ipv4 = "192.168.13.11"; + mme_ip_address = ( { ipv4 = "192.168.12.11"; ipv6 = "192:168:30::17"; active = "yes"; preference = "ipv4"; @@ -141,10 +141,10 @@ eNBs = NETWORK_INTERFACES : { ENB_INTERFACE_NAME_FOR_S1_MME = "eth0"; - ENB_IPV4_ADDRESS_FOR_S1_MME = "192.168.13.10/24"; + ENB_IPV4_ADDRESS_FOR_S1_MME = "192.168.12.215/24"; ENB_INTERFACE_NAME_FOR_S1U = "eth0"; - ENB_IPV4_ADDRESS_FOR_S1U = "192.168.13.10/24"; + ENB_IPV4_ADDRESS_FOR_S1U = "192.168.12.215/24"; ENB_PORT_FOR_S1U = 2152; # Spec 2152 }; diff --git a/targets/RT/USER/lte-softmodem.c b/targets/RT/USER/lte-softmodem.c index e67bcb6b07..612239bec3 100644 --- a/targets/RT/USER/lte-softmodem.c +++ b/targets/RT/USER/lte-softmodem.c @@ -290,6 +290,8 @@ double bw = 10.0e6; static int tx_max_power[MAX_NUM_CCs]; /* = {0,0}*/; +char rf_config_file[1024]; + int chain_offset=0; #ifndef EXMIMO @@ -411,6 +413,7 @@ void help (void) { printf(" sudo -E lte-softmodem [options]\n"); printf(" sudo -E ./lte-softmodem -O ../../../targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.openEPC.conf -S -V -m 26 -t 16 -x 1 --ulsch-max-errors 100 -W\n\n"); printf("Options:\n"); + printf(" --rf-config-file Configuration file for front-end (e.g. LMS7002M)\n"); printf(" --ulsch-max-errors set the max ULSCH erros\n"); printf(" --calib-ue-rx set UE RX calibration\n"); printf(" --calib-ue-rx-med \n"); @@ -2051,6 +2054,7 @@ static void get_options (int argc, char **argv) enum long_option_e { LONG_OPTION_START = 0x100, /* Start after regular single char options */ + LONG_OPTION_RF_CONFIG_FILE, LONG_OPTION_ULSCH_MAX_CONSECUTIVE_ERRORS, LONG_OPTION_CALIB_UE_RX, LONG_OPTION_CALIB_UE_RX_MED, @@ -2067,6 +2071,7 @@ static void get_options (int argc, char **argv) }; static const struct option long_options[] = { + {"rf-config-file",required_argument, NULL, LONG_OPTION_RF_CONFIG_FILE}, {"ulsch-max-errors",required_argument, NULL, LONG_OPTION_ULSCH_MAX_CONSECUTIVE_ERRORS}, {"calib-ue-rx", required_argument, NULL, LONG_OPTION_CALIB_UE_RX}, {"calib-ue-rx-med", required_argument, NULL, LONG_OPTION_CALIB_UE_RX_MED}, @@ -2085,11 +2090,19 @@ static void get_options (int argc, char **argv) while ((c = getopt_long (argc, argv, "A:a:C:dEK:g:F:G:hqO:m:SUVRM:r:P:Ws:t:Tx:",long_options,NULL)) != -1) { switch (c) { + case LONG_OPTION_RF_CONFIG_FILE: + if (strlen(optarg)<=1024) + strcpy(rf_config_file,optarg); + else { + printf("Configuration filename is too long\n"); + exit(-1); + } + break; case LONG_OPTION_MAXPOWER: tx_max_power[0]=atoi(optarg); for (CC_id=1;CC_id Date: Tue, 26 Jan 2016 00:18:34 -0800 Subject: [PATCH 173/263] added configuration file for SoDeRa --- targets/ARCH/SODERA/SoDeRa_MIMO.ini | 1128 +++++++++++++++++++++++++++ 1 file changed, 1128 insertions(+) create mode 100755 targets/ARCH/SODERA/SoDeRa_MIMO.ini diff --git a/targets/ARCH/SODERA/SoDeRa_MIMO.ini b/targets/ARCH/SODERA/SoDeRa_MIMO.ini new file mode 100755 index 0000000000..a3feaa269b --- /dev/null +++ b/targets/ARCH/SODERA/SoDeRa_MIMO.ini @@ -0,0 +1,1128 @@ +[file_info] +type=lms7002m_minimal_config +version=1 +[lms7002_registers_a] +0x0493=0x0000 +0x0492=0x0000 +0x0491=0x0000 +0x029B=0x0000 +0x048E=0x0000 +0x0022=0x07FF +0x0283=0x0000 +0x0487=0x0000 +0x0486=0x0000 +0x045F=0x0000 +0x0480=0x0000 +0x0460=0x0000 +0x0447=0x0000 +0x045A=0x0000 +0x02DA=0x0000 +0x0458=0x0000 +0x0314=0x0000 +0x0456=0x0000 +0x0559=0xACB9 +0x0451=0x0000 +0x0390=0x0000 +0x044B=0x0000 +0x0448=0x0000 +0x0454=0x0000 +0x0446=0x0000 +0x04CA=0x0000 +0x0444=0x02B1 +0x0443=0xCCCD +0x0508=0xEF99 +0x0441=0x0000 +0x040D=0x0000 +0x040B=0x000F +0x0409=0x0000 +0x0580=0xEFF2 +0x0407=0x0000 +0x0405=0x0000 +0x0254=0x0000 +0x0404=0x0000 +0x00A0=0x6565 +0x0560=0x174B +0x0403=0x0000 +0x0402=0x07FF +0x055E=0xDB10 +0x03A7=0x0000 +0x0520=0x174B +0x03A5=0x0000 +0x03A4=0x0000 +0x03A3=0x0000 +0x03A2=0x0000 +0x051C=0x0000 +0x048D=0x0000 +0x059A=0x0000 +0x03A1=0x0000 +0x02A2=0x0000 +0x04E1=0x0000 +0x039F=0x0000 +0x0248=0x0000 +0x039B=0x0000 +0x0408=0x0000 +0x0398=0x0000 +0x0393=0x0000 +0x0305=0x0000 +0x038E=0x0000 +0x0324=0x0000 +0x02E7=0x0000 +0x038D=0x0000 +0x0387=0x0000 +0x03A0=0x0000 +0x02D0=0x0000 +0x009A=0x658C +0x054E=0x8184 +0x0386=0x0000 +0x040F=0x0000 +0x04E3=0x0000 +0x0389=0x0000 +0x054F=0x18C9 +0x0385=0x0000 +0x0315=0x0000 +0x0384=0x0000 +0x0382=0x0000 +0x0288=0x0000 +0x0366=0x0000 +0x0365=0x0000 +0x0364=0x0000 +0x0325=0x0000 +0x0081=0x0000 +0x0362=0x0000 +0x038A=0x0000 +0x035E=0x0000 +0x035D=0x0000 +0x0442=0x0CCC +0x0449=0x0000 +0x035A=0x0000 +0x02C8=0x0000 +0x0452=0x0000 +0x0299=0x0000 +0x0359=0x0000 +0x0358=0x0000 +0x048B=0x0000 +0x0354=0x0000 +0x0351=0x0000 +0x03A6=0x0000 +0x0293=0x0000 +0x034E=0x0000 +0x035C=0x0000 +0x034D=0x0000 +0x034B=0x0000 +0x011A=0x2E02 +0x0455=0x0000 +0x034A=0x0000 +0x0348=0x0000 +0x0084=0x0400 +0x0498=0x0000 +0x035B=0x0000 +0x0505=0x00D8 +0x0345=0x0000 +0x0484=0x0000 +0x0586=0x196B +0x0344=0x0000 +0x0561=0xAB08 +0x0343=0x0000 +0x0342=0x0000 +0x0380=0x0000 +0x0327=0x0000 +0x0322=0x0000 +0x059B=0x0000 +0x0321=0x0000 +0x045E=0x0000 +0x0440=0x0020 +0x031D=0x0000 +0x0363=0x0000 +0x031A=0x0000 +0x031C=0x0000 +0x028F=0x0000 +0x0341=0x0000 +0x0287=0x0000 +0x0318=0x0000 +0x031F=0x0000 +0x0316=0x0000 +0x030D=0x0000 +0x040E=0x0000 +0x0352=0x0000 +0x028C=0x0000 +0x0360=0x0000 +0x0313=0x0000 +0x0461=0x0000 +0x010A=0x104C +0x051B=0xB77F +0x0312=0x0000 +0x0346=0x0000 +0x024E=0x0000 +0x0311=0x0000 +0x02D6=0x0000 +0x030C=0x0000 +0x04DF=0x0000 +0x030B=0x0000 +0x0392=0x0000 +0x030A=0x0000 +0x029F=0x0000 +0x0309=0x0000 +0x048A=0x0000 +0x0308=0x0000 +0x0588=0xE6C7 +0x0397=0x0000 +0x02E3=0x0000 +0x049C=0x0000 +0x044A=0x0000 +0x04A4=0x0000 +0x0306=0x0000 +0x0304=0x0000 +0x04D5=0x0000 +0x0303=0x0000 +0x0302=0x0000 +0x0510=0xE6C7 +0x044E=0x0000 +0x0300=0x0000 +0x034F=0x0000 +0x045B=0x0000 +0x02E6=0x0000 +0x00A3=0x6565 +0x04DA=0x0000 +0x025E=0x0000 +0x020A=0x0000 +0x0102=0x3180 +0x020C=0x8000 +0x05A2=0x0000 +0x040A=0x0003 +0x0556=0xA2B5 +0x0243=0x0000 +0x051D=0x4F91 +0x0259=0x0000 +0x02D5=0x0000 +0x02E1=0x0000 +0x011D=0xB555 +0x039E=0x0000 +0x0252=0x0000 +0x0204=0x0000 +0x0255=0x0000 +0x0281=0x0000 +0x0200=0x0081 +0x0594=0xF40D +0x02C5=0x0000 +0x0406=0x0000 +0x030F=0x0000 +0x025D=0x0000 +0x0319=0x0000 +0x0121=0x323C +0x0101=0x7800 +0x025B=0x0000 +0x02C6=0x0000 +0x0558=0x5009 +0x0021=0x0E9F +0x04C2=0x0000 +0x0290=0x0000 +0x02DF=0x0000 +0x0291=0x0000 +0x0296=0x0000 +0x029C=0x0000 +0x028D=0x0000 +0x02A1=0x0000 +0x008B=0x21A6 +0x02A3=0x0000 +0x05A4=0x0000 +0x02A7=0x0000 +0x0483=0x0000 +0x0201=0x07FF +0x02C2=0x0000 +0x02C4=0x0000 +0x044D=0x0000 +0x02E2=0x0000 +0x02D1=0x0000 +0x0546=0x8D44 +0x04C8=0x0000 +0x0207=0x0000 +0x04C6=0x0000 +0x0096=0x0000 +0x0093=0x0000 +0x0250=0x0000 +0x02CB=0x0000 +0x02D3=0x0000 +0x0494=0x0000 +0x04CF=0x0000 +0x025F=0x0000 +0x0251=0x0000 +0x0488=0x0000 +0x0496=0x0000 +0x04C3=0x0000 +0x0100=0x7409 +0x04CC=0x0000 +0x02A5=0x0000 +0x0257=0x0000 +0x04D6=0x0000 +0x04A6=0x0000 +0x049A=0x0000 +0x049B=0x0000 +0x0097=0x0000 +0x011E=0x068E +0x0285=0x0000 +0x0280=0x0000 +0x049E=0x0000 +0x0020=0xFFFD +0x02DD=0x0000 +0x0297=0x0000 +0x049F=0x0000 +0x0522=0xDB10 +0x044C=0x0000 +0x0355=0x0000 +0x04A0=0x0000 +0x02CF=0x0000 +0x04D1=0x0000 +0x0526=0xBE2A +0x0092=0x0001 +0x031B=0x0000 +0x0541=0x4C24 +0x0518=0xEFF2 +0x0543=0xBD96 +0x02C0=0x0000 +0x0499=0x0000 +0x04A1=0x0000 +0x058D=0xF5EF +0x02D7=0x0000 +0x0513=0xDAA2 +0x0549=0x18C9 +0x0552=0x8D44 +0x0521=0x5852 +0x0509=0x0605 +0x0286=0x0000 +0x024F=0x0000 +0x04E0=0x0000 +0x0545=0x364E +0x0349=0x0000 +0x0555=0xBD96 +0x04E4=0x0000 +0x02E4=0x0000 +0x0551=0xD7B7 +0x055D=0xA6B5 +0x0298=0x0000 +0x055F=0x5852 +0x009E=0x658C +0x0547=0xD7B7 +0x0598=0xF61D +0x0123=0x267B +0x0497=0x0000 +0x04A5=0x0000 +0x0565=0xB77F +0x0124=0x0000 +0x0592=0x0DF1 +0x0591=0xFCFE +0x0548=0x79FA +0x04D2=0x0000 +0x0599=0x0000 +0x0511=0x1D10 +0x0506=0x0DF1 +0x0595=0x00BC +0x0584=0xE7E2 +0x0242=0x0000 +0x025A=0x0000 +0x04E2=0x0000 +0x04C5=0x0000 +0x058C=0xEA50 +0x0450=0x0000 +0x0596=0x0A94 +0x05A7=0x0000 +0x058A=0x17DC +0x059D=0x0000 +0x0485=0x0000 +0x058E=0x1316 +0x0550=0x79FA +0x0554=0x6901 +0x0593=0x00D8 +0x0542=0xA2B5 +0x0553=0x364E +0x0563=0x4F91 +0x024D=0x0000 +0x0567=0x4049 +0x055A=0xBE2A +0x0295=0x0000 +0x0566=0x0906 +0x028A=0x0000 +0x059C=0x0000 +0x04DD=0x0000 +0x054C=0x7FFF +0x0582=0x150F +0x0585=0xDAA2 +0x0109=0x61C1 +0x04A2=0x0000 +0x0292=0x0000 +0x059F=0x0000 +0x0583=0x2E45 +0x050E=0x17DC +0x0516=0x150F +0x0523=0xA6B5 +0x0525=0x57AC +0x0206=0x0000 +0x051A=0x0906 +0x055C=0x3347 +0x0514=0xE7E2 +0x050F=0xEA5F +0x05A6=0x0000 +0x051E=0xF524 +0x050A=0x1316 +0x04C7=0x0000 +0x049D=0x0000 +0x0527=0xACB9 +0x050C=0xEA50 +0x0087=0x0000 +0x0399=0x0000 +0x050B=0xF5EF +0x0507=0xFCFE +0x010D=0x015B +0x04C4=0x0000 +0x0495=0x0000 +0x0246=0x0000 +0x0503=0x00BC +0x0320=0x0000 +0x0323=0x0000 +0x02E5=0x0000 +0x055B=0x57AC +0x0114=0x008D +0x04D8=0x0000 +0x04E7=0x0000 +0x04D0=0x0000 +0x04E6=0x0000 +0x00AE=0x0000 +0x0544=0x6901 +0x0258=0x0000 +0x0502=0x0A94 +0x04DE=0x0000 +0x058B=0x0F45 +0x0028=0x0101 +0x029E=0x0000 +0x04DC=0x0000 +0x04D9=0x0000 +0x0557=0x4C24 +0x058F=0x0605 +0x04DB=0x0000 +0x04D7=0x0000 +0x059E=0x0000 +0x024C=0x0000 +0x02DC=0x0000 +0x04D4=0x0000 +0x0504=0xF40D +0x02C3=0x0000 +0x04C1=0x0000 +0x04D3=0x0000 +0x0590=0xEF99 +0x04CE=0x0000 +0x05A5=0x0000 +0x04A7=0x0000 +0x0489=0x0000 +0x02E0=0x0000 +0x0118=0x018C +0x002A=0x0086 +0x0245=0x0000 +0x045D=0x0000 +0x0581=0xC89D +0x02D2=0x0000 +0x039C=0x0000 +0x002B=0x0038 +0x02A0=0x0000 +0x010E=0x0000 +0x0394=0x0000 +0x0459=0x0000 +0x0088=0x0550 +0x0085=0x0001 +0x0089=0x1150 +0x0256=0x0000 +0x0111=0x0083 +0x0095=0x0000 +0x0203=0x0000 +0x030E=0x0000 +0x0482=0x0000 +0x05A0=0x0000 +0x009C=0x658C +0x0381=0x0000 +0x0122=0x033F +0x0110=0x0BFF +0x0026=0x0101 +0x0294=0x0000 +0x009D=0x6565 +0x0524=0x3347 +0x0106=0x3182 +0x028E=0x0000 +0x0326=0x0000 +0x0113=0x03C3 +0x0391=0x0000 +0x04CB=0x0000 +0x010F=0x3042 +0x0119=0x18CB +0x02A6=0x0000 +0x05A1=0x0000 +0x02C9=0x0000 +0x0500=0xF61D +0x039D=0x0000 +0x011F=0x3680 +0x0395=0x0000 +0x024B=0x0000 +0x045C=0x0000 +0x0247=0x0000 +0x0512=0x196B +0x04E5=0x0000 +0x0024=0xE4E4 +0x0353=0x0000 +0x050D=0x0F45 +0x02CD=0x0000 +0x0490=0x0000 +0x0501=0xFDFB +0x034C=0x0000 +0x00AA=0x0000 +0x0350=0x0000 +0x0445=0xDA02 +0x048F=0x0000 +0x008A=0x0514 +0x0453=0x0000 +0x0260=0x0000 +0x00A1=0x6565 +0x0356=0x0000 +0x0241=0x0000 +0x008C=0x267B +0x038F=0x0000 +0x054A=0x8184 +0x00A4=0x6565 +0x0401=0x07FF +0x04CD=0x0000 +0x0249=0x0000 +0x002C=0x0000 +0x054D=0xF7A3 +0x00A6=0x0001 +0x002D=0xFFFF +0x00AC=0x2000 +0x0253=0x0000 +0x028B=0x0000 +0x040C=0x00FC +0x0310=0x0000 +0x0099=0x6565 +0x00A2=0x6565 +0x0589=0xEA5F +0x002F=0x3840 +0x035F=0x0000 +0x0597=0xFDFB +0x0116=0x8180 +0x02CC=0x0000 +0x0025=0x0101 +0x0562=0xF524 +0x011C=0xAD41 +0x0289=0x0000 +0x0282=0x0000 +0x0307=0x0000 +0x038C=0x0000 +0x02C7=0x0000 +0x054B=0xF7A3 +0x0519=0x4049 +0x009F=0x658C +0x025C=0x0000 +0x0515=0x2E45 +0x00A5=0x6565 +0x0301=0x0000 +0x02C1=0x0000 +0x0481=0x0000 +0x0517=0xC89D +0x00A8=0x0000 +0x0564=0x0000 +0x00AB=0x0040 +0x0261=0x0000 +0x002E=0x0000 +0x02DE=0x0000 +0x02A4=0x0000 +0x0540=0x5009 +0x00AD=0x03FF +0x0029=0x0101 +0x024A=0x0000 +0x00A7=0x6565 +0x0027=0xB1E4 +0x0117=0x280C +0x0098=0x0000 +0x0108=0x3042 +0x020B=0x0000 +0x0383=0x0000 +0x0202=0x07FF +0x0086=0x4101 +0x010C=0x8865 +0x02D8=0x0000 +0x0347=0x0000 +0x0457=0x0000 +0x0103=0x0A12 +0x0104=0x0088 +0x0357=0x0000 +0x02DB=0x0000 +0x0400=0x0081 +0x009B=0x6565 +0x0105=0x0007 +0x05A3=0x0000 +0x0240=0x0020 +0x0367=0x0000 +0x044F=0x0000 +0x038B=0x0000 +0x02D9=0x0000 +0x02CE=0x0000 +0x0284=0x0000 +0x0396=0x0000 +0x029A=0x0000 +0x051F=0xAB08 +0x0361=0x0000 +0x0205=0x0000 +0x031E=0x0000 +0x04C0=0x0000 +0x0587=0x1D10 +0x0023=0x5550 +0x048C=0x0000 +0x0112=0xC0E6 +0x039A=0x0000 +0x0115=0x0009 +0x00A9=0x8000 +0x0317=0x0000 +0x0244=0x0000 +0x0094=0x0000 +0x0340=0x0000 +0x0208=0x0170 +0x04A3=0x0000 +0x029D=0x0000 +0x0388=0x0000 +0x0120=0xB9FF +0x04C9=0x0000 +0x02CA=0x0000 +0x0209=0x0000 +0x0082=0x8001 +0x02D4=0x0000 +0x0107=0x318C +[lms7002_registers_b] +0x04E1=0x0000 +0x03A1=0x0000 +0x02A2=0x0000 +0x04E0=0x0000 +0x04DE=0x0000 +0x058B=0x0000 +0x04DC=0x0000 +0x04DB=0x0000 +0x04D9=0x0000 +0x04D5=0x0000 +0x0304=0x0000 +0x04D4=0x0000 +0x0504=0x0000 +0x04D3=0x0000 +0x04D2=0x0000 +0x0548=0x0000 +0x04D0=0x0000 +0x04CF=0x0000 +0x025F=0x0000 +0x04CE=0x0000 +0x04CC=0x0000 +0x02A5=0x0000 +0x04C6=0x0000 +0x0207=0x0000 +0x04C1=0x0000 +0x02C3=0x0000 +0x04C9=0x0000 +0x02CA=0x0000 +0x04C0=0x0000 +0x031E=0x0000 +0x04D6=0x0000 +0x0257=0x0000 +0x04A6=0x0000 +0x04A5=0x0000 +0x04A2=0x0000 +0x0109=0x61C1 +0x049D=0x0000 +0x04C7=0x0000 +0x049C=0x0000 +0x0397=0x0000 +0x02E3=0x0000 +0x0499=0x0000 +0x02C0=0x0000 +0x0496=0x0000 +0x04C3=0x0000 +0x0493=0x0000 +0x04A1=0x0000 +0x0492=0x0000 +0x0491=0x0000 +0x029B=0x0000 +0x048E=0x0000 +0x0283=0x0000 +0x048C=0x0000 +0x048B=0x0000 +0x0358=0x0000 +0x0487=0x0000 +0x0486=0x0000 +0x045F=0x0000 +0x0480=0x0000 +0x0460=0x0000 +0x0447=0x0000 +0x045A=0x0000 +0x02DA=0x0000 +0x0458=0x0000 +0x0314=0x0000 +0x0456=0x0000 +0x0559=0x0000 +0x0453=0x0000 +0x0451=0x0000 +0x0390=0x0000 +0x044D=0x0000 +0x02E2=0x0000 +0x044B=0x0000 +0x0448=0x0000 +0x0454=0x0000 +0x0446=0x0000 +0x04CA=0x0000 +0x0444=0x0000 +0x0443=0x0000 +0x0508=0x0000 +0x0441=0x0000 +0x040D=0x0000 +0x040B=0x7FFF +0x0409=0x0000 +0x0580=0x0000 +0x0407=0x0000 +0x0405=0x0000 +0x0254=0x0000 +0x0404=0x0000 +0x0560=0x0000 +0x04D8=0x0000 +0x0403=0x0000 +0x0402=0x07FF +0x055E=0x0000 +0x03A7=0x0000 +0x0520=0x0000 +0x03A5=0x0000 +0x03A4=0x0000 +0x03A3=0x0000 +0x03A2=0x0000 +0x051C=0x0000 +0x048D=0x0000 +0x059A=0x0000 +0x049E=0x0000 +0x039F=0x0000 +0x0248=0x0000 +0x039B=0x0000 +0x0399=0x0000 +0x0408=0x0000 +0x0398=0x0000 +0x0497=0x0000 +0x0123=0x267B +0x0394=0x0000 +0x0459=0x0000 +0x0393=0x0000 +0x0305=0x0000 +0x038E=0x0000 +0x0324=0x0000 +0x02E7=0x0000 +0x038D=0x0000 +0x0395=0x0000 +0x038A=0x0000 +0x0362=0x0000 +0x0387=0x0000 +0x0200=0x0101 +0x0594=0x0000 +0x02C5=0x0000 +0x02A7=0x0000 +0x0318=0x0000 +0x0544=0x0000 +0x049A=0x0000 +0x0388=0x0000 +0x0120=0xB9FF +0x020A=0x0080 +0x0102=0x3180 +0x0290=0x0000 +0x02DF=0x0000 +0x0291=0x0000 +0x0295=0x0000 +0x055A=0x0000 +0x029C=0x0000 +0x010E=0x2000 +0x02A0=0x0000 +0x010F=0x3042 +0x02A6=0x0000 +0x0119=0x18CB +0x02D2=0x0000 +0x039C=0x0000 +0x028D=0x0000 +0x02A1=0x0000 +0x02C2=0x0000 +0x045E=0x0000 +0x031D=0x0000 +0x0440=0x0020 +0x02C4=0x0000 +0x04D1=0x0000 +0x02CF=0x0000 +0x02C1=0x0000 +0x02C7=0x0000 +0x054B=0x0000 +0x02D3=0x0000 +0x04C8=0x0000 +0x02D1=0x0000 +0x0546=0x0000 +0x0306=0x0000 +0x02D7=0x0000 +0x058D=0x0000 +0x0457=0x0000 +0x02D8=0x0000 +0x0347=0x0000 +0x0103=0x0A12 +0x0104=0x0088 +0x0357=0x0000 +0x02DB=0x0000 +0x0400=0x0101 +0x0209=0x0000 +0x0297=0x0000 +0x02DD=0x0000 +0x029E=0x0000 +0x02DE=0x0000 +0x0527=0x0000 +0x02D5=0x0000 +0x02E1=0x0000 +0x0259=0x0000 +0x0481=0x0000 +0x0517=0x0000 +0x029A=0x0000 +0x051F=0x0000 +0x0483=0x0000 +0x0201=0x07FF +0x0507=0x0000 +0x0321=0x0000 +0x034F=0x0000 +0x0296=0x0000 +0x0510=0x0000 +0x0302=0x0000 +0x038C=0x0000 +0x0307=0x0000 +0x0282=0x0000 +0x0392=0x0000 +0x030B=0x0000 +0x0588=0x0000 +0x0308=0x0000 +0x048A=0x0000 +0x044A=0x0000 +0x04A4=0x0000 +0x04C4=0x0000 +0x010D=0x019C +0x0300=0x0000 +0x0587=0x0000 +0x044E=0x0000 +0x0309=0x0000 +0x0585=0x0000 +0x02E5=0x0000 +0x055B=0x0000 +0x0114=0x008D +0x0323=0x0000 +0x0320=0x0000 +0x0503=0x0000 +0x0513=0x0000 +0x0319=0x0000 +0x0260=0x0000 +0x0549=0x0000 +0x0552=0x0000 +0x0509=0x0000 +0x0521=0x0000 +0x0286=0x0000 +0x04D7=0x0000 +0x059E=0x0000 +0x0557=0x0000 +0x058F=0x0000 +0x0322=0x0000 +0x059B=0x0000 +0x0545=0x0000 +0x0349=0x0000 +0x0555=0x0000 +0x02E4=0x0000 +0x04E4=0x0000 +0x0551=0x0000 +0x0312=0x0000 +0x055D=0x0000 +0x0298=0x0000 +0x055F=0x0000 +0x011D=0x7555 +0x039E=0x0000 +0x0547=0x0000 +0x0598=0x0000 +0x0449=0x0000 +0x0564=0x0000 +0x0242=0x0000 +0x0525=0x0000 +0x0523=0x0000 +0x0565=0x0000 +0x0124=0x0000 +0x0592=0x0000 +0x0591=0x0000 +0x0563=0x0000 +0x024D=0x0000 +0x0567=0x0000 +0x05A5=0x0000 +0x0566=0x0000 +0x030A=0x0000 +0x029F=0x0000 +0x054C=0x0000 +0x0582=0x0000 +0x0599=0x0000 +0x0511=0x0000 +0x0506=0x0000 +0x0301=0x0000 +0x0595=0x0000 +0x0584=0x0000 +0x058C=0x0000 +0x051E=0x0000 +0x05A6=0x0000 +0x050F=0x0000 +0x0590=0x0000 +0x05A0=0x0000 +0x0596=0x0000 +0x05A7=0x0000 +0x0562=0x0000 +0x058A=0x0000 +0x059D=0x0000 +0x0485=0x0000 +0x0581=0x0000 +0x045D=0x0000 +0x0245=0x0000 +0x0310=0x0000 +0x058E=0x0000 +0x05A2=0x0000 +0x054D=0x0000 +0x020C=0x7FFF +0x0589=0x0000 +0x0522=0x0000 +0x049F=0x0000 +0x031F=0x0000 +0x0292=0x0000 +0x059F=0x0000 +0x0583=0x0000 +0x0543=0x0000 +0x0317=0x0000 +0x0244=0x0000 +0x0554=0x0000 +0x0593=0x0000 +0x05A4=0x0000 +0x02A3=0x0000 +0x0553=0x0000 +0x0542=0x0000 +0x0519=0x0000 +0x024F=0x0000 +0x0524=0x0000 +0x0518=0x0000 +0x0354=0x0000 +0x0526=0x0000 +0x031B=0x0000 +0x050E=0x0000 +0x0516=0x0000 +0x02CB=0x0000 +0x0250=0x0000 +0x031C=0x0000 +0x028F=0x0000 +0x051A=0x0000 +0x055C=0x0000 +0x0514=0x0000 +0x050A=0x0000 +0x050C=0x0000 +0x050B=0x0000 +0x04E7=0x0000 +0x04E6=0x0000 +0x04E5=0x0000 +0x0512=0x0000 +0x0206=0x0000 +0x0550=0x0000 +0x0360=0x0000 +0x030E=0x0000 +0x0203=0x0000 +0x0482=0x0000 +0x0541=0x0000 +0x0122=0x033F +0x0110=0x0BF4 +0x0204=0x0000 +0x0252=0x0000 +0x011E=0x06EC +0x049B=0x0000 +0x0294=0x0000 +0x011C=0xAD41 +0x02D6=0x0000 +0x0311=0x0000 +0x0117=0x280C +0x02A4=0x0000 +0x0540=0x0000 +0x02E0=0x0000 +0x0118=0x018C +0x0489=0x0000 +0x04A7=0x0000 +0x0101=0x7800 +0x0558=0x0000 +0x02C6=0x0000 +0x05A1=0x0000 +0x02C9=0x0000 +0x039D=0x0000 +0x0500=0x0000 +0x0450=0x0000 +0x011F=0x3680 +0x030C=0x0000 +0x04DF=0x0000 +0x0281=0x0000 +0x0106=0x3182 +0x028E=0x0000 +0x0326=0x0000 +0x0113=0x03C3 +0x04CB=0x0000 +0x0391=0x0000 +0x0105=0x0007 +0x02D9=0x0000 +0x02CE=0x0000 +0x038B=0x0000 +0x044F=0x0000 +0x02D4=0x0000 +0x0107=0x318C +0x0495=0x0000 +0x0246=0x0000 +0x0303=0x0000 +0x02E6=0x0000 +0x045B=0x0000 +0x0100=0x3409 +0x0340=0x0000 +0x0208=0x0170 +0x0111=0x0083 +0x0247=0x0000 +0x024B=0x0000 +0x045C=0x0000 +0x0383=0x0000 +0x0202=0x07FF +0x054A=0x0000 +0x0401=0x07FF +0x0341=0x0000 +0x0287=0x0000 +0x034C=0x0000 +0x0501=0x0000 +0x030F=0x0000 +0x025D=0x0000 +0x0406=0x0000 +0x0313=0x0000 +0x010A=0x104C +0x0461=0x0000 +0x051B=0x0000 +0x0121=0x348C +0x0115=0x0009 +0x0112=0xC0E6 +0x039A=0x0000 +0x02CC=0x0000 +0x0116=0x8180 +0x04A0=0x0000 +0x0108=0x3042 +0x020B=0x4000 +0x0251=0x0000 +0x0488=0x0000 +0x0241=0x0000 +0x038F=0x0000 +0x02DC=0x0000 +0x024C=0x0000 +0x0494=0x0000 +0x051D=0x0000 +0x0243=0x0000 +0x0556=0x0000 +0x040A=0x0000 +0x04CD=0x0000 +0x0249=0x0000 +0x0261=0x0000 +0x024A=0x0000 +0x0285=0x0000 +0x0280=0x0000 +0x0346=0x0000 +0x024E=0x0000 +0x0253=0x0000 +0x028B=0x0000 +0x040C=0x00FC +0x0255=0x0000 +0x0258=0x0000 +0x0502=0x0000 +0x05A3=0x0000 +0x0367=0x0000 +0x0240=0x0020 +0x0256=0x0000 +0x025A=0x0000 +0x04E2=0x0000 +0x04C5=0x0000 +0x025B=0x0000 +0x0205=0x0000 +0x0361=0x0000 +0x0515=0x0000 +0x025C=0x0000 +0x0355=0x0000 +0x044C=0x0000 +0x010C=0x8865 +0x0284=0x0000 +0x0396=0x0000 +0x0363=0x0000 +0x031A=0x0000 +0x0289=0x0000 +0x028A=0x0000 +0x04DD=0x0000 +0x059C=0x0000 +0x0352=0x0000 +0x028C=0x0000 +0x04C2=0x0000 +0x04DA=0x0000 +0x025E=0x0000 +0x0327=0x0000 +0x0380=0x0000 +0x0342=0x0000 +0x0343=0x0000 +0x0344=0x0000 +0x0561=0x0000 +0x035A=0x0000 +0x02C8=0x0000 +0x0484=0x0000 +0x0586=0x0000 +0x0597=0x0000 +0x035F=0x0000 +0x0345=0x0000 +0x0505=0x0000 +0x035B=0x0000 +0x034A=0x0000 +0x0455=0x0000 +0x011A=0x2E02 +0x034B=0x0000 +0x034D=0x0000 +0x035C=0x0000 +0x034E=0x0000 +0x0293=0x0000 +0x03A6=0x0000 +0x0350=0x0000 +0x0445=0x0000 +0x048F=0x0000 +0x0351=0x0000 +0x0353=0x0000 +0x050D=0x0000 +0x02CD=0x0000 +0x0490=0x0000 +0x0498=0x0000 +0x0348=0x0000 +0x0356=0x0000 +0x030D=0x0000 +0x0316=0x0000 +0x040E=0x0000 +0x04A3=0x0000 +0x029D=0x0000 +0x0359=0x0000 +0x0299=0x0000 +0x0452=0x0000 +0x0442=0x0000 +0x035D=0x0000 +0x035E=0x0000 +0x0325=0x0000 +0x0364=0x0000 +0x0365=0x0000 +0x0366=0x0000 +0x0381=0x0000 +0x0288=0x0000 +0x0382=0x0000 +0x0384=0x0000 +0x0315=0x0000 +0x0385=0x0000 +0x04E3=0x0000 +0x040F=0x0000 +0x0389=0x0000 +0x054F=0x0000 +0x0386=0x0000 +0x02D0=0x0000 +0x054E=0x0000 +0x03A0=0x0000 +[reference_clocks] +sxt_ref_clk_mhz=30.72 +sxr_ref_clk_mhz=30.72 From c9780626edb32606c2958d51bbd8bcf91d369497 Mon Sep 17 00:00:00 2001 From: kaltenbe Date: Tue, 26 Jan 2016 14:09:47 +0100 Subject: [PATCH 174/263] further RF configuration for SoDeRa --- .../ARCH/SODERA/USERSPACE/LIB/sodera_lib.cpp | 69 ++++++++++++++++--- 1 file changed, 60 insertions(+), 9 deletions(-) diff --git a/targets/ARCH/SODERA/USERSPACE/LIB/sodera_lib.cpp b/targets/ARCH/SODERA/USERSPACE/LIB/sodera_lib.cpp index ddd608d0a1..0ddc3ef4a9 100644 --- a/targets/ARCH/SODERA/USERSPACE/LIB/sodera_lib.cpp +++ b/targets/ARCH/SODERA/USERSPACE/LIB/sodera_lib.cpp @@ -354,7 +354,7 @@ int openair0_dev_init_sodera(openair0_device* device, openair0_config_t *openair printf("Configuring LMS7002\n"); - + int bw_gain_adjust=0; @@ -404,14 +404,65 @@ int openair0_dev_init_sodera(openair0_device* device, openair0_config_t *openair printf("Failed to load configuration file %s\n",openair0_cfg[0].configFilename); exit(-1); } - /* - for(i=0;iusrp->set_rx_rate(openair0_cfg[0].sample_rate,i); - s->usrp->set_rx_bandwidth(openair0_cfg[0].rx_bw,i); - printf("Setting rx freq/gain on channel %lu/%lu : BW %f (readback %f)\n",i,s->usrp->get_rx_num_channels(),openair0_cfg[0].rx_bw/1e6,s->usrp->get_rx_bandwidth(i)/1e6); - s->usrp->set_rx_freq(openair0_cfg[0].rx_freq[i],i); - set_rx_gain_offset(&openair0_cfg[0],i,bw_gain_adjust); + opStatus = lmsControl.UploadAll(); + if (opStatus != LIBLMS7_SUCCESS) { + printf("Failed to upload configuration file\n"); + exit(-1); + } + + opStatus = lmsControl.SetFrequencySX(LMS7002M::Tx, openair0_cfg[0].tx_freq[0]/1e6,30.72); + + if (opStatus != LIBLMS7_SUCCESS) { + printf("Cannot set TX frequency %f MHz\n",openair0_cfg[0].tx_freq[0]/1e6); + exit(-1); + } + + opStatus = lmsControl.SetFrequencySX(LMS7002M::Rx, openair0_cfg[0].rx_freq[0]/1e6,30.72); + + if (opStatus != LIBLMS7_SUCCESS) { + printf("Cannot set RX frequency %f MHz\n",openair0_cfg[0].rx_freq[0]/1e6); + exit(-1); + } + + + + // this makes RX/TX sampling rates equal + opStatus = lmsControl.Modify_SPI_Reg_bits(EN_ADCCLKH_CLKGN,0); + if (opStatus != LIBLMS7_SUCCESS) { + printf("Cannot modify SPI (EN_ADCCLKH_CLKGN)\n"); + exit(-1); + } + opStatus = lmsControl.Modify_SPI_Reg_bits(CLKH_OV_CLKL_CGEN,2); + if (opStatus != LIBLMS7_SUCCESS) { + printf("Cannot modify SPI (CLKH_OV_CLKL_CGEN)\n"); + exit(-1); + } + + const float cgen_freq_MHz = 245.76; + const int interpolation = 0; // real interpolation = 2 + const int decimation = 0; // real decimation = 2 + opStatus = lmsControl.SetInterfaceFrequency(cgen_freq_MHz,interpolation,decimation); + if (opStatus != LIBLMS7_SUCCESS) { + printf("Cannot SetInterfaceFrequency (%f,%d,%d)\n",cgen_freq_MHz,interpolation,decimation); + exit(-1); + } + // Run calibration procedure + float txrx_calibrationBandwidth_MHz = 5; + opStatus = lmsControl.CalibrateTx(txrx_calibrationBandwidth_MHz); + if (opStatus != LIBLMS7_SUCCESS){ + printf("TX Calibration failed\n"); + exit(-1); + } + opStatus = lmsControl.CalibrateRx(txrx_calibrationBandwidth_MHz); + if (opStatus != LIBLMS7_SUCCESS){ + printf("RX Calibration failed\n"); + exit(-1); + } + + // this will configure that sampling rate at output of FPGA + // LMS_StreamBoard::ConfigurePLL(&s->Port,openair0_cfg[0].sample_rate,openair0_cfg[0].sample_rate,90); + /* ::uhd::gain_range_t gain_range = s->usrp->get_rx_gain_range(i); // limit to maximum gain if (openair0_cfg[0].rx_gain[i]-openair0_cfg[0].rx_gain_offset[i] > gain_range.stop()) { @@ -482,6 +533,6 @@ int openair0_dev_init_sodera(openair0_device* device, openair0_config_t *openair s->sample_rate = openair0_cfg[0].sample_rate; // TODO: - + exit(-1); return 0; } From d000bf2fd66754f7626905fd558dca4b8ac3c16f Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Wed, 27 Jan 2016 11:04:19 +0100 Subject: [PATCH 175/263] hotfix for bad USRP init --- targets/ARCH/COMMON/common_lib.c | 1 - 1 file changed, 1 deletion(-) diff --git a/targets/ARCH/COMMON/common_lib.c b/targets/ARCH/COMMON/common_lib.c index bdf0e46278..7479a6aa0b 100644 --- a/targets/ARCH/COMMON/common_lib.c +++ b/targets/ARCH/COMMON/common_lib.c @@ -54,7 +54,6 @@ int openair0_device_init(openair0_device *device, openair0_config_t *openair0_cf return(openair0_dev_init_exmimo(device, openair0_cfg)); #elif OAI_USRP device->type=USRP_B200_IF; - openair0_dev_init_usrp(device, openair0_cfg); printf("openair0_dev_init_usrp ...\n"); return(openair0_dev_init_usrp(device, openair0_cfg)); From 2342091bcceeb5af92309a7308e6f5f29f10fe6f Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Wed, 27 Jan 2016 13:42:05 +0100 Subject: [PATCH 176/263] change the num_recv_frames for USRP B210 to reduce UUULLLL's --- targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp b/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp index 290f83ad5c..71c12e63dc 100644 --- a/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp +++ b/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp @@ -482,6 +482,7 @@ int openair0_dev_init_usrp(openair0_device* device, openair0_config_t *openair0_ } else { printf("Found USRP B200"); + args += ",num_recv_frames=256" ; s->usrp = uhd::usrp::multi_usrp::make(args); // s->usrp->set_rx_subdev_spec(rx_subdev); From 9e28189d9b815a24a05de1998d03b438be1e9a69 Mon Sep 17 00:00:00 2001 From: kaltenbe Date: Wed, 27 Jan 2016 17:20:19 +0100 Subject: [PATCH 177/263] PLL Configuration --- cmake_targets/CMakeLists.txt | 7 +- .../ARCH/SODERA/USERSPACE/LIB/sodera_lib.cpp | 78 +++++++++---------- 2 files changed, 45 insertions(+), 40 deletions(-) diff --git a/cmake_targets/CMakeLists.txt b/cmake_targets/CMakeLists.txt index 84bf183991..a8af214ce1 100644 --- a/cmake_targets/CMakeLists.txt +++ b/cmake_targets/CMakeLists.txt @@ -441,15 +441,20 @@ elseif (${RF_BOARD} STREQUAL "OAI_SODERA") include_directories("${OPENAIR_TARGETS}/ARCH/SODERA/USERSPACE/LIB") include_directories("${OPENAIR_TARGETS}/ARCH/SODERA/USERSPACE/LIB/lms7suite/src/lms7002m") include_directories("${OPENAIR_TARGETS}/ARCH/SODERA/USERSPACE/LIB/lms7suite/src/Si5351C") + include_directories("${OPENAIR_TARGETS}/ARCH/SODERA/USERSPACE/LIB/lms7suite/src/LMS_StreamBoard") set(HW_SOURCE ${HW_SOURCE} ${OPENAIR_TARGETS}/ARCH/SODERA/USERSPACE/LIB/sodera_lib.cpp ) LINK_DIRECTORIES("${OPENAIR_TARGETS}/ARCH/SODERA/USERSPACE/LIB/lms7suite/src/lms7002m") LINK_DIRECTORIES("${OPENAIR_TARGETS}/ARCH/SODERA/USERSPACE/LIB/lms7suite/src/Si5351C") + LINK_DIRECTORIES("${OPENAIR_TARGETS}/ARCH/SODERA/USERSPACE/LIB/lms7suite/src/LMS_StreamBoard") + LINK_DIRECTORIES("${OPENAIR_TARGETS}/ARCH/SODERA/USERSPACE/LIB/lms7suite/src/kissFFT") LINK_DIRECTORIES("/usr/lib/x86_64-linux-gnu") set(option_HW_lib "usb-1.0") set(LMS7002_LIB "libLMS7002M.a") set(Si5351C_LIB "libSi5351C.a") + set(LMSStreamBoard_LIB "libLMS_StreamBoard.a") + set(KISSFFT_LIB "libkissFFT.a") #set(LOWLATENCY False) elseif (${RF_BOARD} STREQUAL "ETHERNET") @@ -1449,7 +1454,7 @@ add_executable(lte-softmodem target_link_libraries (lte-softmodem -Wl,--start-group - RRC_LIB S1AP_LIB S1AP_ENB GTPV1U SECU_CN SECU_OSA UTIL HASHTABLE SCTP_CLIENT UDP SCHED_LIB PHY LFDS L2 ${MSC_LIB} ${RAL_LIB} ${NAS_UE_LIB} ${ITTI_LIB} ${MIH_LIB} ${LMS7002_LIB} ${Si5351C_LIB} + RRC_LIB S1AP_LIB S1AP_ENB GTPV1U SECU_CN SECU_OSA UTIL HASHTABLE SCTP_CLIENT UDP SCHED_LIB PHY LFDS L2 ${MSC_LIB} ${RAL_LIB} ${NAS_UE_LIB} ${ITTI_LIB} ${MIH_LIB} ${LMS7002_LIB} ${Si5351C_LIB} ${LMSStreamBoard_LIB} ${KISSFFT_LIB} -Wl,--end-group ) diff --git a/targets/ARCH/SODERA/USERSPACE/LIB/sodera_lib.cpp b/targets/ARCH/SODERA/USERSPACE/LIB/sodera_lib.cpp index 0ddc3ef4a9..5914ff5be6 100644 --- a/targets/ARCH/SODERA/USERSPACE/LIB/sodera_lib.cpp +++ b/targets/ARCH/SODERA/USERSPACE/LIB/sodera_lib.cpp @@ -52,6 +52,8 @@ #include "lmsComms.h" #include "LMS7002M.h" #include "Si5351C.h" +#include "LMS_StreamBoard.h" + #ifdef __SSE4_1__ # include #endif @@ -72,24 +74,12 @@ typedef struct // -------------------------------- // variables for SoDeRa configuration // -------------------------------- - /* - uhd::usrp::multi_usrp::sptr usrp; - //uhd::usrp::multi_usrp::sptr rx_usrp; - - //create a send streamer and a receive streamer - uhd::tx_streamer::sptr tx_stream; - uhd::rx_streamer::sptr rx_stream; - - uhd::tx_metadata_t tx_md; - uhd::rx_metadata_t rx_md; - - uhd::time_spec_t tm_spec; - //setup variables and allocate buffer - uhd::async_metadata_t async_md; - */ LMScomms Port; Si5351C Si; + LMS7002M lmsControl; + LMS_StreamBoard *lmsStream; + double sample_rate; // time offset between transmiter timestamp and receiver timestamp; double tdiff; @@ -105,13 +95,13 @@ typedef struct int64_t rx_count; openair0_timestamp rx_timestamp; -} sodera_state_t; +} sodera_t; -sodera_state_t sodera_state; +sodera_t sodera_state; static int trx_sodera_start(openair0_device *device) { - sodera_state_t *s = (sodera_state_t*)device->priv; + sodera_t *s = (sodera_t*)device->priv; // init recv and send streaming @@ -124,7 +114,7 @@ static int trx_sodera_start(openair0_device *device) static void trx_sodera_end(openair0_device *device) { - sodera_state_t *s = (sodera_state_t*)device->priv; + sodera_t *s = (sodera_t*)device->priv; @@ -132,7 +122,7 @@ static void trx_sodera_end(openair0_device *device) static int trx_sodera_write(openair0_device *device, openair0_timestamp timestamp, void **buff, int nsamps, int cc, int flags) { - sodera_state_t *s = (sodera_state_t*)device->priv; + sodera_t *s = (sodera_t*)device->priv; if (cc>1) { // s->tx_stream->send(buff_ptrs, nsamps, s->tx_md); @@ -145,7 +135,7 @@ static int trx_sodera_write(openair0_device *device, openair0_timestamp timestam static int trx_sodera_read(openair0_device *device, openair0_timestamp *ptimestamp, void **buff, int nsamps, int cc) { - sodera_state_t *s = (sodera_state_t*)device->priv; + sodera_t *s = (sodera_t*)device->priv; int samples_received=0,i,j; int nsamps2; // aligned to upper 32 or 16 byte boundary #if defined(__x86_64) || defined(__i386__) @@ -193,7 +183,7 @@ static bool is_equal(double a, double b) int trx_sodera_set_freq(openair0_device* device, openair0_config_t *openair0_cfg, int dummy) { - sodera_state_t *s = (sodera_state_t*)device->priv; + sodera_t *s = (sodera_t*)device->priv; // s->usrp->set_tx_freq(openair0_cfg[0].tx_freq[0]); // s->usrp->set_rx_freq(openair0_cfg[0].rx_freq[0]); @@ -204,7 +194,7 @@ int trx_sodera_set_freq(openair0_device* device, openair0_config_t *openair0_cfg int openair0_set_rx_frequencies(openair0_device* device, openair0_config_t *openair0_cfg) { - sodera_state_t *s = (sodera_state_t*)device->priv; + sodera_t *s = (sodera_t*)device->priv; static int first_call=1; static double rf_freq,diff; @@ -222,7 +212,7 @@ int openair0_set_rx_frequencies(openair0_device* device, openair0_config_t *open int trx_sodera_set_gains(openair0_device* device, openair0_config_t *openair0_cfg) { - sodera_state_t *s = (sodera_state_t*)device->priv; + sodera_t *s = (sodera_t*)device->priv; // s->usrp->set_tx_gain(openair0_cfg[0].tx_gain[0]); // ::uhd::gain_range_t gain_range = s->usrp->get_rx_gain_range(0); @@ -313,7 +303,7 @@ int trx_sodera_reset_stats(openair0_device* device) { int openair0_dev_init_sodera(openair0_device* device, openair0_config_t *openair0_cfg) { - sodera_state_t *s=&sodera_state; + sodera_t *s=&sodera_state; size_t i; @@ -332,8 +322,7 @@ int openair0_dev_init_sodera(openair0_device* device, openair0_config_t *openair (int)devInfo.hardware, (int)devInfo.firmware, (int)devInfo.protocol); - LMS7002M lmsControl(&s->Port); - + printf("Configuring Si5351C\n"); s->Si.Initialize(&s->Port); s->Si.SetPLL(0, 25000000, 0); @@ -396,29 +385,32 @@ int openair0_dev_init_sodera(openair0_device* device, openair0_config_t *openair break; } + + s->lmsControl = LMS7002M(&s->Port); + liblms7_status opStatus; - lmsControl.ResetChip(); - opStatus = lmsControl.LoadConfig(openair0_cfg[0].configFilename); + s->lmsControl.ResetChip(); + opStatus = s->lmsControl.LoadConfig(openair0_cfg[0].configFilename); if (opStatus != LIBLMS7_SUCCESS) { printf("Failed to load configuration file %s\n",openair0_cfg[0].configFilename); exit(-1); } - opStatus = lmsControl.UploadAll(); + opStatus = s->lmsControl.UploadAll(); if (opStatus != LIBLMS7_SUCCESS) { printf("Failed to upload configuration file\n"); exit(-1); } - opStatus = lmsControl.SetFrequencySX(LMS7002M::Tx, openair0_cfg[0].tx_freq[0]/1e6,30.72); + opStatus = s->lmsControl.SetFrequencySX(LMS7002M::Tx, openair0_cfg[0].tx_freq[0]/1e6,30.72); if (opStatus != LIBLMS7_SUCCESS) { printf("Cannot set TX frequency %f MHz\n",openair0_cfg[0].tx_freq[0]/1e6); exit(-1); } - opStatus = lmsControl.SetFrequencySX(LMS7002M::Rx, openair0_cfg[0].rx_freq[0]/1e6,30.72); + opStatus = s->lmsControl.SetFrequencySX(LMS7002M::Rx, openair0_cfg[0].rx_freq[0]/1e6,30.72); if (opStatus != LIBLMS7_SUCCESS) { printf("Cannot set RX frequency %f MHz\n",openair0_cfg[0].rx_freq[0]/1e6); @@ -428,12 +420,12 @@ int openair0_dev_init_sodera(openair0_device* device, openair0_config_t *openair // this makes RX/TX sampling rates equal - opStatus = lmsControl.Modify_SPI_Reg_bits(EN_ADCCLKH_CLKGN,0); + opStatus = s->lmsControl.Modify_SPI_Reg_bits(EN_ADCCLKH_CLKGN,0); if (opStatus != LIBLMS7_SUCCESS) { printf("Cannot modify SPI (EN_ADCCLKH_CLKGN)\n"); exit(-1); } - opStatus = lmsControl.Modify_SPI_Reg_bits(CLKH_OV_CLKL_CGEN,2); + opStatus = s->lmsControl.Modify_SPI_Reg_bits(CLKH_OV_CLKL_CGEN,2); if (opStatus != LIBLMS7_SUCCESS) { printf("Cannot modify SPI (CLKH_OV_CLKL_CGEN)\n"); exit(-1); @@ -442,26 +434,34 @@ int openair0_dev_init_sodera(openair0_device* device, openair0_config_t *openair const float cgen_freq_MHz = 245.76; const int interpolation = 0; // real interpolation = 2 const int decimation = 0; // real decimation = 2 - opStatus = lmsControl.SetInterfaceFrequency(cgen_freq_MHz,interpolation,decimation); + opStatus = s->lmsControl.SetInterfaceFrequency(cgen_freq_MHz,interpolation,decimation); if (opStatus != LIBLMS7_SUCCESS) { printf("Cannot SetInterfaceFrequency (%f,%d,%d)\n",cgen_freq_MHz,interpolation,decimation); exit(-1); } // Run calibration procedure float txrx_calibrationBandwidth_MHz = 5; - opStatus = lmsControl.CalibrateTx(txrx_calibrationBandwidth_MHz); + opStatus = s->lmsControl.CalibrateTx(txrx_calibrationBandwidth_MHz); if (opStatus != LIBLMS7_SUCCESS){ printf("TX Calibration failed\n"); exit(-1); } - opStatus = lmsControl.CalibrateRx(txrx_calibrationBandwidth_MHz); + opStatus = s->lmsControl.CalibrateRx(txrx_calibrationBandwidth_MHz); if (opStatus != LIBLMS7_SUCCESS){ printf("RX Calibration failed\n"); exit(-1); } - + + + s->lmsStream = new LMS_StreamBoard(&s->Port); + LMS_StreamBoard::Status opStreamStatus; // this will configure that sampling rate at output of FPGA - // LMS_StreamBoard::ConfigurePLL(&s->Port,openair0_cfg[0].sample_rate,openair0_cfg[0].sample_rate,90); + opStreamStatus = s->lmsStream->ConfigurePLL(&s->Port,openair0_cfg[0].sample_rate,openair0_cfg[0].sample_rate,90); + if (opStatus != LIBLMS7_SUCCESS){ + printf("Sample rate programming failed\n"); + exit(-1); + } + /* ::uhd::gain_range_t gain_range = s->usrp->get_rx_gain_range(i); // limit to maximum gain From 01d375067750a356dbdb1af936ae972f31dcbeb9 Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Wed, 27 Jan 2016 18:15:21 +0100 Subject: [PATCH 178/263] hotfix for CCE bug --- targets/ARCH/COMMON/common_lib.c | 1 - 1 file changed, 1 deletion(-) diff --git a/targets/ARCH/COMMON/common_lib.c b/targets/ARCH/COMMON/common_lib.c index bdf0e46278..7479a6aa0b 100644 --- a/targets/ARCH/COMMON/common_lib.c +++ b/targets/ARCH/COMMON/common_lib.c @@ -54,7 +54,6 @@ int openair0_device_init(openair0_device *device, openair0_config_t *openair0_cf return(openair0_dev_init_exmimo(device, openair0_cfg)); #elif OAI_USRP device->type=USRP_B200_IF; - openair0_dev_init_usrp(device, openair0_cfg); printf("openair0_dev_init_usrp ...\n"); return(openair0_dev_init_usrp(device, openair0_cfg)); From ad333a4a09585594a74ed6926589a33d73223089 Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Wed, 27 Jan 2016 18:36:04 +0100 Subject: [PATCH 179/263] updated new test cases for OAI EPC --- cmake_targets/autotests/README.txt | 15 +- cmake_targets/autotests/test_case_list.xml | 1028 +++++++++++++++++++- 2 files changed, 1018 insertions(+), 25 deletions(-) diff --git a/cmake_targets/autotests/README.txt b/cmake_targets/autotests/README.txt index 7c3ae65070..506fc3321d 100644 --- a/cmake_targets/autotests/README.txt +++ b/cmake_targets/autotests/README.txt @@ -137,7 +137,13 @@ Obj.# Case# Test# Description 01 59 lte-softmodem tests with USRP X310 RF as eNB and OAI EPC (eNB and EPC are on same machines) w/ Bandrich COTS UE -01 61 lte-softmodem tests with USRP X310 RF as eNB and OAI EPC (eNB and EPC are on different machines) w/ Bandrich COTS UE +01 60 lte-softmodem tests with USRP X310 RF as eNB and OAI EPC (eNB and EPC are on different machines) w/ Bandrich COTS UE +01 60 00 Band 7 FDD 5MHz UL Throughput for 300 sec for 1TX/1RX +01 60 01 Band 7 FDD 10MHz UL Throughput for 300 sec for 1TX/1RX +01 60 02 Band 7 FDD 20MHz UL Throughput for 300 sec for 1TX/1RX +01 60 03 Band 7 FDD 5MHz DL Throughput for 300 sec for 1TX/1RX +01 60 04 Band 7 FDD 10MHz DL Throughput for 300 sec for 1TX/1RX +01 60 05 Band 7 FDD 20MHz DL Throughput for 300 sec for 1TX/1RX 01 61 lte-softmodem tests with EXMIMO RF as eNB and ALU EPC w/ Bandrich COTS UE for `TX/1RX, 2TX/2RX 01 61 00 Band 7 FDD 5MHz UL Throughput for 300 sec for 1TX/1RX @@ -148,7 +154,14 @@ Obj.# Case# Test# Description 01 61 05 Band 7 FDD 20MHz DL Throughput for 300 sec for 1TX/1RX 01 62 lte-softmodem tests with EXMIMO RF as eNB and OAI EPC (eNB and EPC are on same machines) w/ Bandrich COTS UE + 01 63 lte-softmodem tests with EXMIMO RF as eNB and OAI EPC (eNB and EPC are on different machines) w/ Bandrich COTS UE +01 63 00 Band 7 FDD 5MHz UL Throughput for 300 sec for 1TX/1RX +01 63 01 Band 7 FDD 10MHz UL Throughput for 300 sec for 1TX/1RX +01 63 02 Band 7 FDD 20MHz UL Throughput for 300 sec for 1TX/1RX +01 63 03 Band 7 FDD 5MHz DL Throughput for 300 sec for 1TX/1RX +01 63 04 Band 7 FDD 10MHz DL Throughput for 300 sec for 1TX/1RX +01 63 05 Band 7 FDD 20MHz DL Throughput for 300 sec for 1TX/1RX 01 64 lte-softmodem-noS1 tests diff --git a/cmake_targets/autotests/test_case_list.xml b/cmake_targets/autotests/test_case_list.xml index 81f8b0eb58..976a0926b0 100644 --- a/cmake_targets/autotests/test_case_list.xml +++ b/cmake_targets/autotests/test_case_list.xml @@ -10,7 +10,7 @@ sudo -S -E /opt/ltebox/tools/stop_ltebox $OPENAIR_DIR/cmake_targets/build_oai -w EXMIMO -c; sudo -S -E $OPENAIR_DIR/cmake_targets/tools/stop_exmimo2; dmesg|tail 36000 - 0104+ 015502 015505 015506 015507 015508 015508 015509 015510 015511 015602 015605 015702 015705 016102 016105 + 0104+ 015506 015507 015508 015509 015510 015511 015602 015605 015702 015705 015802 015805 016002 016005 016102 016105 016302 016305 3 mozart calisson stevens nano amerique @@ -2665,12 +2665,12 @@ BUILD/EPC/epc.conf.in MCC \"208\" BUILD/EPC/epc.conf.in MNC \"92\" BUILD/EPC/epc.conf.in TAC \"1\" - BUILD/EPC/epc.conf.in MME_INTERFACE_NAME_FOR_S1_MME \"eth0:1\" - BUILD/EPC/epc.conf.in MME_IPV4_ADDRESS_FOR_S1_MME \"192.170.0.1/24\" - BUILD/EPC/epc.conf.in SGW_INTERFACE_NAME_FOR_S1U_S12_S4_UP \"eth0:2\"; - BUILD/EPC/epc.conf.in SGW_IPV4_ADDRESS_FOR_S1U_S12_S4_UP \"192.170.1.1/24\"; - BUILD/EPC/epc.conf.in PGW_INTERFACE_NAME_FOR_SGI \"eth1\" - BUILD/EPC/epc.conf.in PGW_IPV4_ADDRESS_FOR_SGI \"192.168.12.82/24\" + BUILD/EPC/epc.conf.in MME_INTERFACE_NAME_FOR_S1_MME \"eth0\" + BUILD/EPC/epc.conf.in MME_IPV4_ADDRESS_FOR_S1_MME \"192.168.12.62/24\" + BUILD/EPC/epc.conf.in SGW_INTERFACE_NAME_FOR_S1U_S12_S4_UP \"eth0\"; + BUILD/EPC/epc.conf.in SGW_IPV4_ADDRESS_FOR_S1U_S12_S4_UP \"192.168.12.62/24\"; + BUILD/EPC/epc.conf.in PGW_INTERFACE_NAME_FOR_SGI \"eth0\" + BUILD/EPC/epc.conf.in PGW_IPV4_ADDRESS_FOR_SGI \"192.168.12.62/24\" BUILD/EPC/epc.conf.in IPV4_LIST \"192.172.0.0/24\",\"192.172.1.0/24\" $OPENAIRCN_DIR/SCRIPTS/build_epc -c -l @@ -2749,12 +2749,12 @@ BUILD/EPC/epc.conf.in MCC \"208\" BUILD/EPC/epc.conf.in MNC \"92\" BUILD/EPC/epc.conf.in TAC \"1\" - BUILD/EPC/epc.conf.in MME_INTERFACE_NAME_FOR_S1_MME \"eth0:1\" - BUILD/EPC/epc.conf.in MME_IPV4_ADDRESS_FOR_S1_MME \"192.170.0.1/24\" - BUILD/EPC/epc.conf.in SGW_INTERFACE_NAME_FOR_S1U_S12_S4_UP \"eth0:2\"; - BUILD/EPC/epc.conf.in SGW_IPV4_ADDRESS_FOR_S1U_S12_S4_UP \"192.170.1.1/24\"; - BUILD/EPC/epc.conf.in PGW_INTERFACE_NAME_FOR_SGI \"eth1\" - BUILD/EPC/epc.conf.in PGW_IPV4_ADDRESS_FOR_SGI \"192.168.12.82/24\" + BUILD/EPC/epc.conf.in MME_INTERFACE_NAME_FOR_S1_MME \"eth0\" + BUILD/EPC/epc.conf.in MME_IPV4_ADDRESS_FOR_S1_MME \"192.168.12.62/24\" + BUILD/EPC/epc.conf.in SGW_INTERFACE_NAME_FOR_S1U_S12_S4_UP \"eth0\"; + BUILD/EPC/epc.conf.in SGW_IPV4_ADDRESS_FOR_S1U_S12_S4_UP \"192.168.12.62/24\"; + BUILD/EPC/epc.conf.in PGW_INTERFACE_NAME_FOR_SGI \"eth0\" + BUILD/EPC/epc.conf.in PGW_IPV4_ADDRESS_FOR_SGI \"192.168.12.62/24\" BUILD/EPC/epc.conf.in IPV4_LIST \"192.172.0.0/24\",\"192.172.1.0/24\" $OPENAIRCN_DIR/SCRIPTS/build_epc -c -l @@ -2833,12 +2833,12 @@ BUILD/EPC/epc.conf.in MCC \"208\" BUILD/EPC/epc.conf.in MNC \"92\" BUILD/EPC/epc.conf.in TAC \"1\" - BUILD/EPC/epc.conf.in MME_INTERFACE_NAME_FOR_S1_MME \"eth0:1\" - BUILD/EPC/epc.conf.in MME_IPV4_ADDRESS_FOR_S1_MME \"192.170.0.1/24\" - BUILD/EPC/epc.conf.in SGW_INTERFACE_NAME_FOR_S1U_S12_S4_UP \"eth0:2\"; - BUILD/EPC/epc.conf.in SGW_IPV4_ADDRESS_FOR_S1U_S12_S4_UP \"192.170.1.1/24\"; - BUILD/EPC/epc.conf.in PGW_INTERFACE_NAME_FOR_SGI \"eth1\" - BUILD/EPC/epc.conf.in PGW_IPV4_ADDRESS_FOR_SGI \"192.168.12.82/24\" + BUILD/EPC/epc.conf.in MME_INTERFACE_NAME_FOR_S1_MME \"eth0\" + BUILD/EPC/epc.conf.in MME_IPV4_ADDRESS_FOR_S1_MME \"192.168.12.62/24\" + BUILD/EPC/epc.conf.in SGW_INTERFACE_NAME_FOR_S1U_S12_S4_UP \"eth0\"; + BUILD/EPC/epc.conf.in SGW_IPV4_ADDRESS_FOR_S1U_S12_S4_UP \"192.168.12.62/24\"; + BUILD/EPC/epc.conf.in PGW_INTERFACE_NAME_FOR_SGI \"eth0\" + BUILD/EPC/epc.conf.in PGW_IPV4_ADDRESS_FOR_SGI \"192.168.12.62/24\" BUILD/EPC/epc.conf.in IPV4_LIST \"192.172.0.0/24\",\"192.172.1.0/24\" $OPENAIRCN_DIR/SCRIPTS/build_epc -c -l @@ -3036,11 +3036,11 @@ targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.100PRB.usrpx310.conf frame_type \"FDD\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.100PRB.usrpx310.conf nb_antennas_rx 1 targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.100PRB.usrpx310.conf nb_antennas_tx 1 - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.100PRB.usrpx310.epc.remote.conf ENB_INTERFACE_NAME_FOR_S1_MME \"eth0\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.100PRB.usrpx310.epc.remote.conf ENB_IPV4_ADDRESS_FOR_S1_MME \"192.168.12.111/24\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.100PRB.usrpx310.epc.remote.conf ENB_INTERFACE_NAME_FOR_S1U \"eth0\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.100PRB.usrpx310.epc.remote.conf ENB_IPV4_ADDRESS_FOR_S1U \"192.168.12.111/24\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.100PRB.usrpx310.epc.remote.conf ENB_PORT_FOR_S1U 2152 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.100PRB.usrpx310.conf ENB_INTERFACE_NAME_FOR_S1_MME \"eth0\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.100PRB.usrpx310.conf ENB_IPV4_ADDRESS_FOR_S1_MME \"192.168.12.111/24\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.100PRB.usrpx310.conf ENB_INTERFACE_NAME_FOR_S1U \"eth0\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.100PRB.usrpx310.conf ENB_IPV4_ADDRESS_FOR_S1U \"192.168.12.111/24\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.100PRB.usrpx310.conf ENB_PORT_FOR_S1U 2152 $OPENAIR_DIR/cmake_targets/build_oai --eNB -w USRP -x -c sudo -E -S /usr/local/bin/niusrprio_pcie start ; dmesg|tail @@ -3330,6 +3330,494 @@ + + lte-softmodem + + mozart + stevens + nano + 390 + /tmp + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpx310.epc.remote.conf tracking_area_code \"1\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpx310.epc.remote.conf mobile_country_code \"208\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpx310.epc.remote.conf mobile_network_code \"92\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpx310.epc.remote.conf N_RB_DL 25 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpx310.epc.remote.conf mme_ip_address "ipv4=\"192.168.12.62\";ipv6=\"192:168:30::17\";active=\"yes\";preference=\"ipv4\";" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpx310.epc.remote.conf downlink_frequency 2660000000L + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpx310.epc.remote.conf uplink_frequency_offset -120000000 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpx310.epc.remote.conf frame_type \"FDD\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpx310.epc.remote.conf nb_antennas_rx 1 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpx310.epc.remote.conf nb_antennas_tx 1 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpx310.epc.remote.conf ENB_INTERFACE_NAME_FOR_S1_MME \"eth0\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpx310.epc.remote.conf ENB_IPV4_ADDRESS_FOR_S1_MME \"192.168.12.111/24\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpx310.epc.remote.conf ENB_INTERFACE_NAME_FOR_S1U \"eth0\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpx310.epc.remote.conf ENB_IPV4_ADDRESS_FOR_S1U \"192.168.12.111/24\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpx310.epc.remote.conf ENB_PORT_FOR_S1U 2152 + $OPENAIR_DIR/cmake_targets/build_oai + --eNB -w USRP -x -c + sleep 15; sudo -E -S /usr/local/bin/niusrprio_pcie start ; dmesg|tail + + $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem + -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpx310.epc.remote.conf -W + + + + + False + + /tmp + + + + sudo -E bash -c 'echo 3 > /proc/sys/vm/drop_caches' + + $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue + + $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 1 ppp0 -u -c 192.172.0.1 -b 10Mbits/s -B 192.172.0.2 + + + + False + $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; sudo -S -E $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue + + /tmp + BUILD/EPC/epc.conf.in MCC \"208\" + BUILD/EPC/epc.conf.in MNC \"92\" + BUILD/EPC/epc.conf.in TAC \"1\" + BUILD/EPC/epc.conf.in MME_INTERFACE_NAME_FOR_S1_MME \"eth0\" + BUILD/EPC/epc.conf.in MME_IPV4_ADDRESS_FOR_S1_MME \"192.168.12.62/24\" + BUILD/EPC/epc.conf.in SGW_INTERFACE_NAME_FOR_S1U_S12_S4_UP \"eth0\"; + BUILD/EPC/epc.conf.in SGW_IPV4_ADDRESS_FOR_S1U_S12_S4_UP \"192.168.12.62/24\"; + BUILD/EPC/epc.conf.in PGW_INTERFACE_NAME_FOR_SGI \"eth0\" + BUILD/EPC/epc.conf.in PGW_IPV4_ADDRESS_FOR_SGI \"192.168.12.62/24\" + BUILD/EPC/epc.conf.in IPV4_LIST \"192.172.0.0/24\",\"192.172.1.0/24\" + $OPENAIRCN_DIR/SCRIPTS/build_epc + -c -l + $OPENAIRCN_DIR/SCRIPTS/build_hss + -c -l + + sudo -E bash -c 'echo 3 > /proc/sys/vm/drop_caches' ; sudo -E ifconfig eth1 add 192.172.0.1 + + $OPENAIRCN_DIR/SCRIPTS/run_epc + -r + sleep 10; $OPENAIRCN_DIR/SCRIPTS/run_hss + + $OPENAIRCN_DIR/TEST/autotests/tools/iperf_script 5 lo -s -i 1 -u -f m -B 192.172.0.1 + + throughput_test min=1.0Mbits/sec max=1.0Mbits/sec average=1.0Mbits/sec + + False + USRPx310.OAI_EPC_remote.Bandrich.5MHz.FDD.Band_7.UL.1TX.1RX + 10 + + + + + + lte-softmodem + + mozart + stevens + nano + 390 + /tmp + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpx310.conf tracking_area_code \"1\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpx310.conf mobile_country_code \"208\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpx310.conf mobile_network_code \"92\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpx310.conf N_RB_DL 50 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpx310.conf mme_ip_address "ipv4=\"192.168.12.62\";ipv6=\"192:168:30::17\";active=\"yes\";preference=\"ipv4\";" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpx310.conf downlink_frequency 2660000000L + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpx310.conf uplink_frequency_offset -120000000 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpx310.conf frame_type \"FDD\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpx310.conf nb_antennas_rx 1 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpx310.conf nb_antennas_tx 1 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpx310.conf ENB_INTERFACE_NAME_FOR_S1_MME \"eth0\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpx310.conf ENB_IPV4_ADDRESS_FOR_S1_MME \"192.168.12.111/24\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpx310.conf ENB_INTERFACE_NAME_FOR_S1U \"eth0\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpx310.conf ENB_IPV4_ADDRESS_FOR_S1U \"192.168.12.111/24\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpx310.conf ENB_PORT_FOR_S1U 2152 + $OPENAIR_DIR/cmake_targets/build_oai + --eNB -w USRP -x -c + sleep 15; sudo -E -S /usr/local/bin/niusrprio_pcie start ; dmesg|tail + + $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem + -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpx310.conf -W + + + + + True + + /tmp + + + + sudo -E bash -c 'echo 3 > /proc/sys/vm/drop_caches' + + $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue + + $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 1 ppp0 -u -c 192.172.0.1 -b 10Mbits/s -B 192.172.0.2 + + + + False + $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; sudo -S -E $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue + + /tmp + BUILD/EPC/epc.conf.in MCC \"208\" + BUILD/EPC/epc.conf.in MNC \"92\" + BUILD/EPC/epc.conf.in TAC \"1\" + BUILD/EPC/epc.conf.in MME_INTERFACE_NAME_FOR_S1_MME \"eth0\" + BUILD/EPC/epc.conf.in MME_IPV4_ADDRESS_FOR_S1_MME \"192.168.12.62/24\" + BUILD/EPC/epc.conf.in SGW_INTERFACE_NAME_FOR_S1U_S12_S4_UP \"eth0\"; + BUILD/EPC/epc.conf.in SGW_IPV4_ADDRESS_FOR_S1U_S12_S4_UP \"192.168.12.62/24\"; + BUILD/EPC/epc.conf.in PGW_INTERFACE_NAME_FOR_SGI \"eth0\" + BUILD/EPC/epc.conf.in PGW_IPV4_ADDRESS_FOR_SGI \"192.168.12.62/24\" + BUILD/EPC/epc.conf.in IPV4_LIST \"192.172.0.0/24\",\"192.172.1.0/24\" + $OPENAIRCN_DIR/SCRIPTS/build_epc + -c -l + $OPENAIRCN_DIR/SCRIPTS/build_hss + -c -l + + sudo -E bash -c 'echo 3 > /proc/sys/vm/drop_caches' ;sudo -E ifconfig eth1 add 192.172.0.1 + + $OPENAIRCN_DIR/SCRIPTS/run_epc + -r + sleep 10; $OPENAIRCN_DIR/SCRIPTS/run_hss + + $OPENAIRCN_DIR/TEST/autotests/tools/iperf_script 5 lo -s -i 1 -u -f m -B 192.172.0.1 + + throughput_test min=1.0Mbits/sec max=1.0Mbits/sec average=1.0Mbits/sec + + False + USRPx310.OAI_EPC_remote.Bandrich.10MHz.FDD.Band_7.UL.1TX.1RX + 10 + + + + lte-softmodem + + mozart + stevens + nano + 390 + /tmp + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.100PRB.usrpx310.conf tracking_area_code \"1\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.100PRB.usrpx310.conf mobile_country_code \"208\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.100PRB.usrpx310.conf mobile_network_code \"92\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.100PRB.usrpx310.conf N_RB_DL 100 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.100PRB.usrpx310.conf mme_ip_address "ipv4=\"192.168.12.62\";ipv6=\"192:168:30::17\";active=\"yes\";preference=\"ipv4\";" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.100PRB.usrpx310.conf downlink_frequency 2660000000L + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.100PRB.usrpx310.conf uplink_frequency_offset -120000000 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.100PRB.usrpx310.conf frame_type \"FDD\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.100PRB.usrpx310.conf nb_antennas_rx 1 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.100PRB.usrpx310.conf nb_antennas_tx 1 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.100PRB.usrpx310.conf ENB_INTERFACE_NAME_FOR_S1_MME \"eth0\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.100PRB.usrpx310.conf ENB_IPV4_ADDRESS_FOR_S1_MME \"192.168.12.111/24\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.100PRB.usrpx310.conf ENB_INTERFACE_NAME_FOR_S1U \"eth0\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.100PRB.usrpx310.conf ENB_IPV4_ADDRESS_FOR_S1U \"192.168.12.111/24\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.100PRB.usrpx310.conf ENB_PORT_FOR_S1U 2152 + $OPENAIR_DIR/cmake_targets/build_oai + --eNB -w USRP -x -c + sleep 15; sudo -E -S /usr/local/bin/niusrprio_pcie start ; dmesg|tail + + $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem + -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.100PRB.usrpx310.conf -W + + + + + False + + /tmp + + + + sudo -E bash -c 'echo 3 > /proc/sys/vm/drop_caches' + + $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue + + $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 1 ppp0 -u -c 192.172.0.1 -b 10Mbits/s -B 192.172.0.2 + + + + False + $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; sudo -S -E $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue + + /tmp + BUILD/EPC/epc.conf.in MCC \"208\" + BUILD/EPC/epc.conf.in MNC \"92\" + BUILD/EPC/epc.conf.in TAC \"1\" + BUILD/EPC/epc.conf.in MME_INTERFACE_NAME_FOR_S1_MME \"eth0\" + BUILD/EPC/epc.conf.in MME_IPV4_ADDRESS_FOR_S1_MME \"192.168.12.62/24\" + BUILD/EPC/epc.conf.in SGW_INTERFACE_NAME_FOR_S1U_S12_S4_UP \"eth0\"; + BUILD/EPC/epc.conf.in SGW_IPV4_ADDRESS_FOR_S1U_S12_S4_UP \"192.168.12.62/24\"; + BUILD/EPC/epc.conf.in PGW_INTERFACE_NAME_FOR_SGI \"eth0\" + BUILD/EPC/epc.conf.in PGW_IPV4_ADDRESS_FOR_SGI \"192.168.12.62/24\" + BUILD/EPC/epc.conf.in IPV4_LIST \"192.172.0.0/24\",\"192.172.1.0/24\" + $OPENAIRCN_DIR/SCRIPTS/build_epc + -c -l + $OPENAIRCN_DIR/SCRIPTS/build_hss + -c -l + + sudo -E bash -c 'echo 3 > /proc/sys/vm/drop_caches' ; sudo -E ifconfig eth1 add 192.172.0.1 + + $OPENAIRCN_DIR/SCRIPTS/run_epc + -r + sleep 10; $OPENAIRCN_DIR/SCRIPTS/run_hss + + $OPENAIRCN_DIR/TEST/autotests/tools/iperf_script 5 lo -s -i 1 -u -f m -B 192.172.0.1 + + throughput_test min=1.0Mbits/sec max=1.0Mbits/sec average=1.0Mbits/sec + + False + USRPx310.OAI_EPC_remote.Bandrich.20MHz.FDD.Band_7.UL.1TX.1RX + 10 + + + + lte-softmodem + + mozart + stevens + nano + 390 + /tmp + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpx310.epc.remote.conf tracking_area_code \"1\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpx310.epc.remote.conf mobile_country_code \"208\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpx310.epc.remote.conf mobile_network_code \"92\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpx310.epc.remote.conf N_RB_DL 25 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpx310.epc.remote.conf mme_ip_address "ipv4=\"192.168.12.62\";ipv6=\"192:168:30::17\";active=\"yes\";preference=\"ipv4\";" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpx310.epc.remote.conf downlink_frequency 2660000000L + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpx310.epc.remote.conf uplink_frequency_offset -120000000 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpx310.epc.remote.conf frame_type \"FDD\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpx310.epc.remote.conf nb_antennas_rx 1 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpx310.epc.remote.conf nb_antennas_tx 1 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpx310.epc.remote.conf ENB_INTERFACE_NAME_FOR_S1_MME \"eth0\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpx310.epc.remote.conf ENB_IPV4_ADDRESS_FOR_S1_MME \"192.168.12.111/24\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpx310.epc.remote.conf ENB_INTERFACE_NAME_FOR_S1U \"eth0\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpx310.epc.remote.conf ENB_IPV4_ADDRESS_FOR_S1U \"192.168.12.111/24\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpx310.epc.remote.conf ENB_PORT_FOR_S1U 2152 + $OPENAIR_DIR/cmake_targets/build_oai + --eNB -w USRP -x -c + sleep 15; sudo -E -S /usr/local/bin/niusrprio_pcie start ; dmesg|tail + + $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem + -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.25PRB.usrpx310.epc.remote.conf -W + + + + + False + + /tmp + + + + sudo -E bash -c 'echo 3 > /proc/sys/vm/drop_caches' + + $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue + + $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 1 ppp0 -s -i 1 -u -f m -B 192.172.0.2 + + throughput_test min=10.0Mbits/sec max=10.5Mbits/sec average=11.0Mbits/sec + + False + $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; sudo -S -E $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue + + /tmp + BUILD/EPC/epc.conf.in MCC \"208\" + BUILD/EPC/epc.conf.in MNC \"92\" + BUILD/EPC/epc.conf.in TAC \"1\" + BUILD/EPC/epc.conf.in MME_INTERFACE_NAME_FOR_S1_MME \"eth0\" + BUILD/EPC/epc.conf.in MME_IPV4_ADDRESS_FOR_S1_MME \"192.168.12.62/24\" + BUILD/EPC/epc.conf.in SGW_INTERFACE_NAME_FOR_S1U_S12_S4_UP \"eth0\"; + BUILD/EPC/epc.conf.in SGW_IPV4_ADDRESS_FOR_S1U_S12_S4_UP \"192.168.12.62/24\"; + BUILD/EPC/epc.conf.in PGW_INTERFACE_NAME_FOR_SGI \"eth0\" + BUILD/EPC/epc.conf.in PGW_IPV4_ADDRESS_FOR_SGI \"192.168.12.62/24\" + BUILD/EPC/epc.conf.in IPV4_LIST \"192.172.0.0/24\",\"192.172.1.0/24\" + $OPENAIRCN_DIR/SCRIPTS/build_epc + -c -l + $OPENAIRCN_DIR/SCRIPTS/build_hss + -c -l + + sudo -E bash -c 'echo 3 > /proc/sys/vm/drop_caches' ;sudo -E ifconfig eth1 add 192.172.0.1 + + $OPENAIRCN_DIR/SCRIPTS/run_epc + -r + sleep 10; $OPENAIRCN_DIR/SCRIPTS/run_hss + + $OPENAIRCN_DIR/TEST/autotests/tools/iperf_script 60 lo -u -c 192.172.0.2 -b 10Mbits/s -B 192.172.0.1 + + + + False + USRPx310.OAI_EPC_remote.Bandrich.5MHz.FDD.Band_7.DL.1TX.1RX + 10 + + + + lte-softmodem + + mozart + stevens + nano + 390 + /tmp + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpx310.conf tracking_area_code \"1\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpx310.conf mobile_country_code \"208\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpx310.conf mobile_network_code \"92\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpx310.conf N_RB_DL 50 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpx310.conf mme_ip_address "ipv4=\"192.168.12.62\";ipv6=\"192:168:30::17\";active=\"yes\";preference=\"ipv4\";" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpx310.conf downlink_frequency 2660000000L + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpx310.conf uplink_frequency_offset -120000000 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpx310.conf frame_type \"FDD\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpx310.conf nb_antennas_rx 1 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpx310.conf nb_antennas_tx 1 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpx310.conf ENB_INTERFACE_NAME_FOR_S1_MME \"eth0\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpx310.conf ENB_IPV4_ADDRESS_FOR_S1_MME \"192.168.12.111/24\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpx310.conf ENB_INTERFACE_NAME_FOR_S1U \"eth0\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpx310.conf ENB_IPV4_ADDRESS_FOR_S1U \"192.168.12.111/24\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpx310.conf ENB_PORT_FOR_S1U 2152 + $OPENAIR_DIR/cmake_targets/build_oai + --eNB -w USRP -x -c + sleep 15; sudo -E -S /usr/local/bin/niusrprio_pcie start ; dmesg|tail + sudo -E -S /usr/local/bin/niusrprio_pcie start ; dmesg|tail + $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem + -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpx310.conf -W + + + + + False + + /tmp + + + + sudo -E bash -c 'echo 3 > /proc/sys/vm/drop_caches' + + $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue + + $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 1 ppp0 -s -i 1 -u -f m -B 192.172.0.2 + + throughput_test min=20.0Mbits/sec max=21.0Mbits/sec average=22.0Mbits/sec + + False + $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; sudo -S -E $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue + + /tmp + BUILD/EPC/epc.conf.in MCC \"208\" + BUILD/EPC/epc.conf.in MNC \"92\" + BUILD/EPC/epc.conf.in TAC \"1\" + BUILD/EPC/epc.conf.in MME_INTERFACE_NAME_FOR_S1_MME \"eth0\" + BUILD/EPC/epc.conf.in MME_IPV4_ADDRESS_FOR_S1_MME \"192.168.12.62/24\" + BUILD/EPC/epc.conf.in SGW_INTERFACE_NAME_FOR_S1U_S12_S4_UP \"eth0\"; + BUILD/EPC/epc.conf.in SGW_IPV4_ADDRESS_FOR_S1U_S12_S4_UP \"192.168.12.62/24\"; + BUILD/EPC/epc.conf.in PGW_INTERFACE_NAME_FOR_SGI \"eth0\" + BUILD/EPC/epc.conf.in PGW_IPV4_ADDRESS_FOR_SGI \"192.168.12.62/24\" + BUILD/EPC/epc.conf.in IPV4_LIST \"192.172.0.0/24\",\"192.172.1.0/24\" + $OPENAIRCN_DIR/SCRIPTS/build_epc + -c -l + $OPENAIRCN_DIR/SCRIPTS/build_hss + -c -l + + sudo -E bash -c 'echo 3 > /proc/sys/vm/drop_caches' ;sudo -E ifconfig eth1 add 192.172.0.1 + + $OPENAIRCN_DIR/SCRIPTS/run_epc + -r + sleep 10; $OPENAIRCN_DIR/SCRIPTS/run_hss + + $OPENAIRCN_DIR/TEST/autotests/tools/iperf_script 60 lo -u -c 192.172.0.2 -b 10Mbits/s -B 192.172.0.1 + + + + False + USRPx310.OAI_EPC_remote.Bandrich.10MHz.FDD.Band_7.DL.1TX.1RX + 10 + + + + lte-softmodem + + mozart + stevens + nano + 390 + /tmp + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.100PRB.usrpx310.conf tracking_area_code \"1\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.100PRB.usrpx310.conf mobile_country_code \"208\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.100PRB.usrpx310.conf mobile_network_code \"92\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.100PRB.usrpx310.conf N_RB_DL 100 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.100PRB.usrpx310.conf mme_ip_address "ipv4=\"192.168.12.62\";ipv6=\"192:168:30::17\";active=\"yes\";preference=\"ipv4\";" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.100PRB.usrpx310.conf downlink_frequency 2660000000L + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.100PRB.usrpx310.conf uplink_frequency_offset -120000000 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.100PRB.usrpx310.conf frame_type \"FDD\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.100PRB.usrpx310.conf nb_antennas_rx 1 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.100PRB.usrpx310.conf nb_antennas_tx 1 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.100PRB.usrpx310.conf ENB_INTERFACE_NAME_FOR_S1_MME \"eth0\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.100PRB.usrpx310.conf ENB_IPV4_ADDRESS_FOR_S1_MME \"192.168.12.111/24\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.100PRB.usrpx310.conf ENB_INTERFACE_NAME_FOR_S1U \"eth0\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.100PRB.usrpx310.conf ENB_IPV4_ADDRESS_FOR_S1U \"192.168.12.111/24\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.100PRB.usrpx310.conf ENB_PORT_FOR_S1U 2152 + $OPENAIR_DIR/cmake_targets/build_oai + --eNB -w USRP -x -c + sleep 15; sudo -E -S /usr/local/bin/niusrprio_pcie start ; dmesg|tail + + $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem + -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.100PRB.usrpx310.conf -W + + + + + True + + /tmp + + + + sudo -E bash -c 'echo 3 > /proc/sys/vm/drop_caches' + + $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue + + $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 1 ppp0 -s -i 1 -u -f m -B 192.172.0.2 + + throughput_test min=20.0Mbits/sec max=21.0Mbits/sec average=22.0Mbits/sec + + False + $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; sudo -S -E $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue + + /tmp + BUILD/EPC/epc.conf.in MCC \"208\" + BUILD/EPC/epc.conf.in MNC \"92\" + BUILD/EPC/epc.conf.in TAC \"1\" + BUILD/EPC/epc.conf.in MME_INTERFACE_NAME_FOR_S1_MME \"eth0\" + BUILD/EPC/epc.conf.in MME_IPV4_ADDRESS_FOR_S1_MME \"192.168.12.62/24\" + BUILD/EPC/epc.conf.in SGW_INTERFACE_NAME_FOR_S1U_S12_S4_UP \"eth0\"; + BUILD/EPC/epc.conf.in SGW_IPV4_ADDRESS_FOR_S1U_S12_S4_UP \"192.168.12.62/24\"; + BUILD/EPC/epc.conf.in PGW_INTERFACE_NAME_FOR_SGI \"eth0\" + BUILD/EPC/epc.conf.in PGW_IPV4_ADDRESS_FOR_SGI \"192.168.12.62/24\" + BUILD/EPC/epc.conf.in IPV4_LIST \"192.172.0.0/24\",\"192.172.1.0/24\" + $OPENAIRCN_DIR/SCRIPTS/build_epc + -c -l + $OPENAIRCN_DIR/SCRIPTS/build_hss + -c -l + + sudo -E bash -c 'echo 3 > /proc/sys/vm/drop_caches' ;sudo -E ifconfig eth1 add 192.172.0.1 + + $OPENAIRCN_DIR/SCRIPTS/run_epc + -r + sleep 10; $OPENAIRCN_DIR/SCRIPTS/run_hss + + $OPENAIRCN_DIR/TEST/autotests/tools/iperf_script 60 lo -u -c 192.172.0.2 -b 10Mbits/s -B 192.172.0.1 + + + + False + USRPx310.OAI_EPC_remote.Bandrich.20MHz.FDD.Band_7.DL.1TX.1RX + 10 + + lte-softmodem @@ -3797,6 +4285,498 @@ + + + lte-softmodem + + calisson + stevens + nano + 390 + /tmp + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.conf tracking_area_code \"1\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.conf mobile_country_code \"208\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.conf mobile_network_code \"92\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.conf N_RB_DL 25 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.conf mme_ip_address "ipv4=\"192.168.12.62\";ipv6=\"192:168:30::17\";active=\"yes\";preference=\"ipv4\";" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.conf downlink_frequency 2660000000L + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.conf uplink_frequency_offset -120000000 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.conf frame_type \"FDD\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.conf nb_antennas_rx 1 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.conf nb_antennas_tx 1 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.conf ENB_INTERFACE_NAME_FOR_S1_MME \"eth1\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.conf ENB_IPV4_ADDRESS_FOR_S1_MME \"192.168.12.82/24\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.conf ENB_INTERFACE_NAME_FOR_S1U \"eth1\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.conf ENB_IPV4_ADDRESS_FOR_S1U \"192.168.12.82/24\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.conf ENB_PORT_FOR_S1U 2152 + $OPENAIR_DIR/cmake_targets/build_oai + --eNB -w EXMIMO -x -c + sleep 15; sudo -E -S $OPENAIR_DIR/cmake_targets/tools/init_exmimo2; dmesg|tail + + $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem + -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.conf -W + + + + + False + + + /tmp + + + + sudo -E bash -c 'echo 3 > /proc/sys/vm/drop_caches' + + $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue + + $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 1 ppp0 -u -c 192.172.0.1 -b 10Mbits/s -B 192.172.0.2 + + + + False + $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; sudo -S -E $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue + + /tmp + BUILD/EPC/epc.conf.in MCC \"208\" + BUILD/EPC/epc.conf.in MNC \"92\" + BUILD/EPC/epc.conf.in TAC \"1\" + BUILD/EPC/epc.conf.in MME_INTERFACE_NAME_FOR_S1_MME \"eth0\" + BUILD/EPC/epc.conf.in MME_IPV4_ADDRESS_FOR_S1_MME \"192.168.12.62/24\" + BUILD/EPC/epc.conf.in SGW_INTERFACE_NAME_FOR_S1U_S12_S4_UP \"eth0\"; + BUILD/EPC/epc.conf.in SGW_IPV4_ADDRESS_FOR_S1U_S12_S4_UP \"192.168.12.62/24\"; + BUILD/EPC/epc.conf.in PGW_INTERFACE_NAME_FOR_SGI \"eth0\" + BUILD/EPC/epc.conf.in PGW_IPV4_ADDRESS_FOR_SGI \"192.168.12.62/24\" + BUILD/EPC/epc.conf.in IPV4_LIST \"192.172.0.0/24\",\"192.172.1.0/24\" + $OPENAIRCN_DIR/SCRIPTS/build_epc + -c -l + $OPENAIRCN_DIR/SCRIPTS/build_hss + -c -l + + sudo -E bash -c 'echo 3 > /proc/sys/vm/drop_caches' ; sudo -E ifconfig eth1 add 192.172.0.1 + + $OPENAIRCN_DIR/SCRIPTS/run_epc + -r + sleep 10; $OPENAIRCN_DIR/SCRIPTS/run_hss + + $OPENAIRCN_DIR/TEST/autotests/tools/iperf_script 5 lo -s -i 1 -u -f m -B 192.172.0.1 + + throughput_test min=1.0Mbits/sec max=1.0Mbits/sec average=1.0Mbits/sec + + False + EXMIMO.OAI_EPC_remote.Bandrich.5MHz.FDD.Band_7.UL.1TX.1RX + 10 + + + + + + lte-softmodem + + calisson + stevens + nano + 390 + /tmp + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.conf tracking_area_code \"1\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.conf mobile_country_code \"208\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.conf mobile_network_code \"92\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.conf N_RB_DL 50 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.conf mme_ip_address "ipv4=\"192.168.12.62\";ipv6=\"192:168:30::17\";active=\"yes\";preference=\"ipv4\";" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.conf downlink_frequency 2660000000L + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.conf uplink_frequency_offset -120000000 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.conf frame_type \"FDD\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.conf nb_antennas_rx 1 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.conf nb_antennas_tx 1 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.conf ENB_INTERFACE_NAME_FOR_S1_MME \"eth1\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.conf ENB_IPV4_ADDRESS_FOR_S1_MME \"192.168.12.82/24\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.conf ENB_INTERFACE_NAME_FOR_S1U \"eth1\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.conf ENB_IPV4_ADDRESS_FOR_S1U \"192.168.12.82/24\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.conf ENB_PORT_FOR_S1U 2152 + $OPENAIR_DIR/cmake_targets/build_oai + --eNB -w EXMIMO -x -c + sleep 15; sudo -E -S $OPENAIR_DIR/cmake_targets/tools/init_exmimo2 ; dmesg|tail + + $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem + -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.conf -W + + + + + False + + /tmp + + + + sudo -E bash -c 'echo 3 > /proc/sys/vm/drop_caches' + + $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue + + $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 1 ppp0 -u -c 192.172.0.1 -b 10Mbits/s -B 192.172.0.2 + + + + False + $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; sudo -S -E $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue + + /tmp + BUILD/EPC/epc.conf.in MCC \"208\" + BUILD/EPC/epc.conf.in MNC \"92\" + BUILD/EPC/epc.conf.in TAC \"1\" + BUILD/EPC/epc.conf.in MME_INTERFACE_NAME_FOR_S1_MME \"eth0\" + BUILD/EPC/epc.conf.in MME_IPV4_ADDRESS_FOR_S1_MME \"192.168.12.62/24\" + BUILD/EPC/epc.conf.in SGW_INTERFACE_NAME_FOR_S1U_S12_S4_UP \"eth0\"; + BUILD/EPC/epc.conf.in SGW_IPV4_ADDRESS_FOR_S1U_S12_S4_UP \"192.168.12.62/24\"; + BUILD/EPC/epc.conf.in PGW_INTERFACE_NAME_FOR_SGI \"eth0\" + BUILD/EPC/epc.conf.in PGW_IPV4_ADDRESS_FOR_SGI \"192.168.12.62/24\" + BUILD/EPC/epc.conf.in IPV4_LIST \"192.172.0.0/24\",\"192.172.1.0/24\" + $OPENAIRCN_DIR/SCRIPTS/build_epc + -c -l + $OPENAIRCN_DIR/SCRIPTS/build_hss + -c -l + + sudo -E bash -c 'echo 3 > /proc/sys/vm/drop_caches' ;sudo -E ifconfig eth1 add 192.172.0.1 + + $OPENAIRCN_DIR/SCRIPTS/run_epc + -r + sleep 10; $OPENAIRCN_DIR/SCRIPTS/run_hss + + $OPENAIRCN_DIR/TEST/autotests/tools/iperf_script 5 lo -s -i 1 -u -f m -B 192.172.0.1 + + throughput_test min=1.0Mbits/sec max=1.0Mbits/sec average=1.0Mbits/sec + + False + EXMIMO.OAI_EPC_remote.Bandrich.10MHz.FDD.Band_7.UL.1TX.1RX + 10 + + + + lte-softmodem + + calisson + stevens + nano + 390 + /tmp + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.conf tracking_area_code \"1\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.conf mobile_country_code \"208\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.conf mobile_network_code \"92\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.conf N_RB_DL 100 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.conf mme_ip_address "ipv4=\"192.168.12.62\";ipv6=\"192:168:30::17\";active=\"yes\";preference=\"ipv4\";" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.conf downlink_frequency 2660000000L + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.conf uplink_frequency_offset -120000000 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.conf frame_type \"FDD\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.conf nb_antennas_rx 1 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.conf nb_antennas_tx 1 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.conf ENB_INTERFACE_NAME_FOR_S1_MME \"eth1\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.conf ENB_IPV4_ADDRESS_FOR_S1_MME \"192.168.12.82/24\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.conf ENB_INTERFACE_NAME_FOR_S1U \"eth1\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.conf ENB_IPV4_ADDRESS_FOR_S1U \"192.168.12.82/24\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.conf ENB_PORT_FOR_S1U 2152 + $OPENAIR_DIR/cmake_targets/build_oai + --eNB -w EXMIMO -x -c + sleep 15; sudo -E -S $OPENAIR_DIR/cmake_targets/tools/init_exmimo2 ; dmesg|tail + + $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem + -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.conf -W + + + + + False + + /tmp + + + + sudo -E bash -c 'echo 3 > /proc/sys/vm/drop_caches' + + $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue + + $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 1 ppp0 -u -c 192.172.0.1 -b 10Mbits/s -B 192.172.0.2 + + + + False + $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; sudo -S -E $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue + + /tmp + BUILD/EPC/epc.conf.in MCC \"208\" + BUILD/EPC/epc.conf.in MNC \"92\" + BUILD/EPC/epc.conf.in TAC \"1\" + BUILD/EPC/epc.conf.in MME_INTERFACE_NAME_FOR_S1_MME \"eth0\" + BUILD/EPC/epc.conf.in MME_IPV4_ADDRESS_FOR_S1_MME \"192.168.12.62/24\" + BUILD/EPC/epc.conf.in SGW_INTERFACE_NAME_FOR_S1U_S12_S4_UP \"eth0\"; + BUILD/EPC/epc.conf.in SGW_IPV4_ADDRESS_FOR_S1U_S12_S4_UP \"192.168.12.62/24\"; + BUILD/EPC/epc.conf.in PGW_INTERFACE_NAME_FOR_SGI \"eth0\" + BUILD/EPC/epc.conf.in PGW_IPV4_ADDRESS_FOR_SGI \"192.168.12.62/24\" + BUILD/EPC/epc.conf.in IPV4_LIST \"192.172.0.0/24\",\"192.172.1.0/24\" + $OPENAIRCN_DIR/SCRIPTS/build_epc + -c -l + $OPENAIRCN_DIR/SCRIPTS/build_hss + -c -l + + sudo -E bash -c 'echo 3 > /proc/sys/vm/drop_caches' ; sudo -E ifconfig eth1 add 192.172.0.1 + + $OPENAIRCN_DIR/SCRIPTS/run_epc + -r + sleep 10; $OPENAIRCN_DIR/SCRIPTS/run_hss + + $OPENAIRCN_DIR/TEST/autotests/tools/iperf_script 5 lo -s -i 1 -u -f m -B 192.172.0.1 + + throughput_test min=1.0Mbits/sec max=1.0Mbits/sec average=1.0Mbits/sec + + False + EXMIMO.OAI_EPC_remote.Bandrich.20MHz.FDD.Band_7.UL.1TX.1RX + 10 + + + + lte-softmodem + + calisson + stevens + nano + 390 + /tmp + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.conf tracking_area_code \"1\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.conf mobile_country_code \"208\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.conf mobile_network_code \"92\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.conf N_RB_DL 25 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.conf mme_ip_address "ipv4=\"192.168.12.62\";ipv6=\"192:168:30::17\";active=\"yes\";preference=\"ipv4\";" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.conf downlink_frequency 2660000000L + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.conf uplink_frequency_offset -120000000 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.conf frame_type \"FDD\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.conf nb_antennas_rx 1 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.conf nb_antennas_tx 1 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.conf ENB_INTERFACE_NAME_FOR_S1_MME \"eth1\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.conf ENB_IPV4_ADDRESS_FOR_S1_MME \"192.168.12.82/24\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.conf ENB_INTERFACE_NAME_FOR_S1U \"eth1\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.conf ENB_IPV4_ADDRESS_FOR_S1U \"192.168.12.82/24\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.conf ENB_PORT_FOR_S1U 2152 + $OPENAIR_DIR/cmake_targets/build_oai + --eNB -w EXMIMO -x -c + sleep 15; sudo -E -S $OPENAIR_DIR/cmake_targets/tools/init_exmimo2 ; dmesg|tail + + $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem + -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.conf -W + + + + + False> + + /tmp + + + + sudo -E bash -c 'echo 3 > /proc/sys/vm/drop_caches' + + $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue + + $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 1 ppp0 -s -i 1 -u -f m -B 192.172.0.2 + + throughput_test min=10.0Mbits/sec max=10.5Mbits/sec average=11.0Mbits/sec + + False + $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; sudo -S -E $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue + + /tmp + BUILD/EPC/epc.conf.in MCC \"208\" + BUILD/EPC/epc.conf.in MNC \"92\" + BUILD/EPC/epc.conf.in TAC \"1\" + BUILD/EPC/epc.conf.in MME_INTERFACE_NAME_FOR_S1_MME \"eth0\" + BUILD/EPC/epc.conf.in MME_IPV4_ADDRESS_FOR_S1_MME \"192.168.12.62/24\" + BUILD/EPC/epc.conf.in SGW_INTERFACE_NAME_FOR_S1U_S12_S4_UP \"eth0\"; + BUILD/EPC/epc.conf.in SGW_IPV4_ADDRESS_FOR_S1U_S12_S4_UP \"192.168.12.62/24\"; + BUILD/EPC/epc.conf.in PGW_INTERFACE_NAME_FOR_SGI \"eth0\" + BUILD/EPC/epc.conf.in PGW_IPV4_ADDRESS_FOR_SGI \"192.168.12.62/24\" + BUILD/EPC/epc.conf.in IPV4_LIST \"192.172.0.0/24\",\"192.172.1.0/24\" + $OPENAIRCN_DIR/SCRIPTS/build_epc + -c -l + $OPENAIRCN_DIR/SCRIPTS/build_hss + -c -l + + sudo -E bash -c 'echo 3 > /proc/sys/vm/drop_caches' ;sudo -E ifconfig eth1 add 192.172.0.1 + + $OPENAIRCN_DIR/SCRIPTS/run_epc + -r + sleep 10; $OPENAIRCN_DIR/SCRIPTS/run_hss + + $OPENAIRCN_DIR/TEST/autotests/tools/iperf_script 60 lo -u -c 192.172.0.2 -b 10Mbits/s -B 192.172.0.1 + + + + False + EXMIMO.OAI_EPC_remote.Bandrich.5MHz.FDD.Band_7.DL.1TX.1RX + 10 + + + + lte-softmodem + + calisson + stevens + nano + 390 + /tmp + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.conf tracking_area_code \"1\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.conf mobile_country_code \"208\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.conf mobile_network_code \"92\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.conf N_RB_DL 50 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.conf mme_ip_address "ipv4=\"192.168.12.62\";ipv6=\"192:168:30::17\";active=\"yes\";preference=\"ipv4\";" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.conf downlink_frequency 2660000000L + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.conf uplink_frequency_offset -120000000 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.conf frame_type \"FDD\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.conf nb_antennas_rx 1 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.conf nb_antennas_tx 1 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.conf ENB_INTERFACE_NAME_FOR_S1_MME \"eth1\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.conf ENB_IPV4_ADDRESS_FOR_S1_MME \"192.168.12.82/24\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.conf ENB_INTERFACE_NAME_FOR_S1U \"eth1\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.conf ENB_IPV4_ADDRESS_FOR_S1U \"192.168.12.82/24\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.conf ENB_PORT_FOR_S1U 2152 + $OPENAIR_DIR/cmake_targets/build_oai + --eNB -w EXMIMO -x -c + sleep 15; sudo -E -S $OPENAIR_DIR/cmake_targets/tools/init_exmimo2 ; dmesg|tail + + $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem + -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.conf -W + + + + + False + + /tmp + + + + sudo -E bash -c 'echo 3 > /proc/sys/vm/drop_caches' + + $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue + + $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 1 ppp0 -s -i 1 -u -f m -B 192.172.0.2 + + throughput_test min=20.0Mbits/sec max=21.0Mbits/sec average=22.0Mbits/sec + + False + $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; sudo -S -E $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue + + /tmp + BUILD/EPC/epc.conf.in MCC \"208\" + BUILD/EPC/epc.conf.in MNC \"92\" + BUILD/EPC/epc.conf.in TAC \"1\" + BUILD/EPC/epc.conf.in MME_INTERFACE_NAME_FOR_S1_MME \"eth0\" + BUILD/EPC/epc.conf.in MME_IPV4_ADDRESS_FOR_S1_MME \"192.168.12.62/24\" + BUILD/EPC/epc.conf.in SGW_INTERFACE_NAME_FOR_S1U_S12_S4_UP \"eth0\"; + BUILD/EPC/epc.conf.in SGW_IPV4_ADDRESS_FOR_S1U_S12_S4_UP \"192.168.12.62/24\"; + BUILD/EPC/epc.conf.in PGW_INTERFACE_NAME_FOR_SGI \"eth0\" + BUILD/EPC/epc.conf.in PGW_IPV4_ADDRESS_FOR_SGI \"192.168.12.62/24\" + BUILD/EPC/epc.conf.in IPV4_LIST \"192.172.0.0/24\",\"192.172.1.0/24\" + $OPENAIRCN_DIR/SCRIPTS/build_epc + -c -l + $OPENAIRCN_DIR/SCRIPTS/build_hss + -c -l + + sudo -E bash -c 'echo 3 > /proc/sys/vm/drop_caches' ;sudo -E ifconfig eth1 add 192.172.0.1 + + $OPENAIRCN_DIR/SCRIPTS/run_epc + -r + sleep 10; $OPENAIRCN_DIR/SCRIPTS/run_hss + + $OPENAIRCN_DIR/TEST/autotests/tools/iperf_script 60 lo -u -c 192.172.0.2 -b 10Mbits/s -B 192.172.0.1 + + + + False + EXMIMO.OAI_EPC_remote.Bandrich.10MHz.FDD.Band_7.DL.1TX.1RX + 10 + + + + lte-softmodem + + calisson + stevens + nano + 390 + /tmp + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.conf tracking_area_code \"1\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.conf mobile_country_code \"208\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.conf mobile_network_code \"92\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.conf N_RB_DL 100 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.conf mme_ip_address "ipv4=\"192.168.12.62\";ipv6=\"192:168:30::17\";active=\"yes\";preference=\"ipv4\";" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.conf downlink_frequency 2660000000L + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.conf uplink_frequency_offset -120000000 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.conf frame_type \"FDD\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.conf nb_antennas_rx 1 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.conf nb_antennas_tx 1 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.conf ENB_INTERFACE_NAME_FOR_S1_MME \"eth1\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.conf ENB_IPV4_ADDRESS_FOR_S1_MME \"192.168.12.82/24\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.conf ENB_INTERFACE_NAME_FOR_S1U \"eth1\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.conf ENB_IPV4_ADDRESS_FOR_S1U \"192.168.12.82/24\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.conf ENB_PORT_FOR_S1U 2152 + $OPENAIR_DIR/cmake_targets/build_oai + --eNB -w EXMIMO -x -c + sleep 15; sudo -E -S $OPENAIR_DIR/cmake_targets/tools/init_exmimo2 ; dmesg|tail + + $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem + -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.conf -W + + + + + False + + /tmp + + + + sudo -E bash -c 'echo 3 > /proc/sys/vm/drop_caches' + + $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue + + $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 1 ppp0 -s -i 1 -u -f m -B 192.172.0.2 + + throughput_test min=20.0Mbits/sec max=21.0Mbits/sec average=22.0Mbits/sec + + False + $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; sudo -S -E $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue + + /tmp + BUILD/EPC/epc.conf.in MCC \"208\" + BUILD/EPC/epc.conf.in MNC \"92\" + BUILD/EPC/epc.conf.in TAC \"1\" + BUILD/EPC/epc.conf.in MME_INTERFACE_NAME_FOR_S1_MME \"eth0\" + BUILD/EPC/epc.conf.in MME_IPV4_ADDRESS_FOR_S1_MME \"192.168.12.62/24\" + BUILD/EPC/epc.conf.in SGW_INTERFACE_NAME_FOR_S1U_S12_S4_UP \"eth0\"; + BUILD/EPC/epc.conf.in SGW_IPV4_ADDRESS_FOR_S1U_S12_S4_UP \"192.168.12.62/24\"; + BUILD/EPC/epc.conf.in PGW_INTERFACE_NAME_FOR_SGI \"eth0\" + BUILD/EPC/epc.conf.in PGW_IPV4_ADDRESS_FOR_SGI \"192.168.12.62/24\" + BUILD/EPC/epc.conf.in IPV4_LIST \"192.172.0.0/24\",\"192.172.1.0/24\" + $OPENAIRCN_DIR/SCRIPTS/build_epc + -c -l + $OPENAIRCN_DIR/SCRIPTS/build_hss + -c -l + + sudo -E bash -c 'echo 3 > /proc/sys/vm/drop_caches' ;sudo -E ifconfig eth1 add 192.172.0.1 + + $OPENAIRCN_DIR/SCRIPTS/run_epc + -r + sleep 10; $OPENAIRCN_DIR/SCRIPTS/run_hss + + $OPENAIRCN_DIR/TEST/autotests/tools/iperf_script 60 lo -u -c 192.172.0.2 -b 10Mbits/s -B 192.172.0.1 + + + + False + EXMIMO.OAI_EPC_remote.Bandrich.20MHz.FDD.Band_7.DL.1TX.1RX + 10 + + + + From 16cce46265b34410e0c6e3d57def8fdaf6d2cf10 Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Wed, 27 Jan 2016 19:07:28 +0100 Subject: [PATCH 180/263] cleanup redundant options in test cases --- cmake_targets/autotests/test_case_list.xml | 322 +++++++-------------- 1 file changed, 106 insertions(+), 216 deletions(-) diff --git a/cmake_targets/autotests/test_case_list.xml b/cmake_targets/autotests/test_case_list.xml index 976a0926b0..39ae56d506 100644 --- a/cmake_targets/autotests/test_case_list.xml +++ b/cmake_targets/autotests/test_case_list.xml @@ -861,10 +861,7 @@ amerique 390 /tmp - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf tracking_area_code \"1\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf mobile_country_code \"208\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf mobile_network_code \"92\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf tracking_area_code \"1\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf tracking_area_code \"1\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf mobile_country_code \"208\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf mobile_network_code \"92\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf N_RB_DL 25 @@ -894,11 +891,9 @@ False /tmp - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf tracking_area_code \"4\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf mobile_country_code \"5\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf mobile_network_code \"6\" - $OPENAIR_DIR/cmake_targets/build_oai - --eNB -w USRP -x -c + + + $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 45; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue @@ -911,15 +906,11 @@ sudo -S -E $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue /tmp - BUILD/EPC/epc.local.enb.conf.in MCC \"208\" - BUILD/EPC/epc.local.enb.conf.in MNC \"92\" - BUILD/EPC/epc.local.enb.conf.in TAC \"1\" - BUILD/EPC/epc.local.enb.conf.in PGW_INTERFACE_NAME_FOR_SGI \"eth1\" - BUILD/EPC/epc.local.enb.conf.in PGW_IPV4_ADDRESS_FOR_SGI \"192.168.12.82/24\" - SCRIPTS/build_epc - -c -l - SCRIPTS/build_hss - -c -l + + + + + @@ -945,10 +936,7 @@ amerique 390 /tmp - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf tracking_area_code \"1\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf mobile_country_code \"208\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf mobile_network_code \"92\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf tracking_area_code \"1\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf tracking_area_code \"1\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf mobile_country_code \"208\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf mobile_network_code \"92\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf N_RB_DL 50 @@ -978,11 +966,9 @@ True /tmp - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf tracking_area_code \"4\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf mobile_country_code \"5\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf mobile_network_code \"6\" - $OPENAIR_DIR/cmake_targets/build_oai - --eNB -w USRP -x -c + + + $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 45; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue @@ -995,15 +981,11 @@ sudo -S -E $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue /tmp - BUILD/EPC/epc.local.enb.conf.in MCC \"208\" - BUILD/EPC/epc.local.enb.conf.in MNC \"92\" - BUILD/EPC/epc.local.enb.conf.in TAC \"1\" - BUILD/EPC/epc.local.enb.conf.in PGW_INTERFACE_NAME_FOR_SGI \"eth1\" - BUILD/EPC/epc.local.enb.conf.in PGW_IPV4_ADDRESS_FOR_SGI \"192.168.12.82/24\" - SCRIPTS/build_epc - -c -l - SCRIPTS/build_hss - -c -l + + + + + @@ -1028,10 +1010,7 @@ amerique 390 /tmp - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf tracking_area_code \"1\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf mobile_country_code \"208\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf mobile_network_code \"92\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf tracking_area_code \"1\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf tracking_area_code \"1\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf mobile_country_code \"208\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf mobile_network_code \"92\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf N_RB_DL 100 @@ -1061,11 +1040,9 @@ True /tmp - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf tracking_area_code \"4\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf mobile_country_code \"5\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf mobile_network_code \"6\" - $OPENAIR_DIR/cmake_targets/build_oai - --eNB -w USRP -x -c + + + $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 45; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue @@ -1078,15 +1055,11 @@ sudo -S -E $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue /tmp - BUILD/EPC/epc.local.enb.conf.in MCC \"208\" - BUILD/EPC/epc.local.enb.conf.in MNC \"92\" - BUILD/EPC/epc.local.enb.conf.in TAC \"1\" - BUILD/EPC/epc.local.enb.conf.in PGW_INTERFACE_NAME_FOR_SGI \"eth1\" - BUILD/EPC/epc.local.enb.conf.in PGW_IPV4_ADDRESS_FOR_SGI \"192.168.12.82/24\" - SCRIPTS/build_epc - -c -l - SCRIPTS/build_hss - -c -l + + + + + @@ -1111,10 +1084,7 @@ amerique 390 /tmp - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf tracking_area_code \"1\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf mobile_country_code \"208\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf mobile_network_code \"92\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf tracking_area_code \"1\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf tracking_area_code \"1\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf mobile_country_code \"208\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf mobile_network_code \"92\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf N_RB_DL 25 @@ -1144,11 +1114,9 @@ True /tmp - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf tracking_area_code \"4\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf mobile_country_code \"5\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf mobile_network_code \"6\" - $OPENAIR_DIR/cmake_targets/build_oai - --eNB -w USRP -x -c + + + $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 45; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue @@ -1161,15 +1129,11 @@ /tmp - BUILD/EPC/epc.local.enb.conf.in MCC \"208\" - BUILD/EPC/epc.local.enb.conf.in MNC \"92\" - BUILD/EPC/epc.local.enb.conf.in TAC \"1\" - BUILD/EPC/epc.local.enb.conf.in PGW_INTERFACE_NAME_FOR_SGI \"eth1\" - BUILD/EPC/epc.local.enb.conf.in PGW_IPV4_ADDRESS_FOR_SGI \"192.168.12.82/24\" - SCRIPTS/build_epc - -c -l - SCRIPTS/build_hss - -c -l + + + + + @@ -1193,10 +1157,7 @@ amerique 390 /tmp - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf tracking_area_code \"1\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf mobile_country_code \"208\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf mobile_network_code \"92\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf tracking_area_code \"1\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf tracking_area_code \"1\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf mobile_country_code \"208\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf mobile_network_code \"92\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf N_RB_DL 50 @@ -1226,11 +1187,8 @@ True /tmp - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf tracking_area_code \"4\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf mobile_country_code \"5\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf mobile_network_code \"6\" - $OPENAIR_DIR/cmake_targets/build_oai - --eNB -w USRP -x -c + + $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 45; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue @@ -1244,15 +1202,11 @@ /tmp - BUILD/EPC/epc.local.enb.conf.in MCC \"208\" - BUILD/EPC/epc.local.enb.conf.in MNC \"92\" - BUILD/EPC/epc.local.enb.conf.in TAC \"1\" - BUILD/EPC/epc.local.enb.conf.in PGW_INTERFACE_NAME_FOR_SGI \"eth1\" - BUILD/EPC/epc.local.enb.conf.in PGW_IPV4_ADDRESS_FOR_SGI \"192.168.12.82/24\" - SCRIPTS/build_epc - -c -l - SCRIPTS/build_hss - -c -l + + + + + @@ -1276,10 +1230,7 @@ amerique 390 /tmp - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf tracking_area_code \"1\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf mobile_country_code \"208\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf mobile_network_code \"92\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf tracking_area_code \"1\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf tracking_area_code \"1\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf mobile_country_code \"208\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf mobile_network_code \"92\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf N_RB_DL 100 @@ -1309,11 +1260,9 @@ True /tmp - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf tracking_area_code \"4\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf mobile_country_code \"5\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf mobile_network_code \"6\" - $OPENAIR_DIR/cmake_targets/build_oai - --eNB -w USRP -x -c + + + $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 45; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue @@ -1327,15 +1276,11 @@ /tmp - BUILD/EPC/epc.local.enb.conf.in MCC \"208\" - BUILD/EPC/epc.local.enb.conf.in MNC \"92\" - BUILD/EPC/epc.local.enb.conf.in TAC \"1\" - BUILD/EPC/epc.local.enb.conf.in PGW_INTERFACE_NAME_FOR_SGI \"eth1\" - BUILD/EPC/epc.local.enb.conf.in PGW_IPV4_ADDRESS_FOR_SGI \"192.168.12.82/24\" - SCRIPTS/build_epc - -c -l - SCRIPTS/build_hss - -c -l + + + + + @@ -1360,10 +1305,7 @@ amerique 390 /tmp - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf tracking_area_code \"1\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf mobile_country_code \"208\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf mobile_network_code \"92\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf tracking_area_code \"1\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf tracking_area_code \"1\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf mobile_country_code \"208\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf mobile_network_code \"92\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf N_RB_DL 25 @@ -1393,11 +1335,9 @@ True /tmp - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf tracking_area_code \"4\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf mobile_country_code \"5\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf mobile_network_code \"6\" - $OPENAIR_DIR/cmake_targets/build_oai - --eNB -w USRP -x -c + + + $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue;$OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 45; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue @@ -1410,15 +1350,11 @@ sudo -S -E $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue /tmp - BUILD/EPC/epc.local.enb.conf.in MCC \"208\" - BUILD/EPC/epc.local.enb.conf.in MNC \"92\" - BUILD/EPC/epc.local.enb.conf.in TAC \"1\" - BUILD/EPC/epc.local.enb.conf.in PGW_INTERFACE_NAME_FOR_SGI \"eth1\" - BUILD/EPC/epc.local.enb.conf.in PGW_IPV4_ADDRESS_FOR_SGI \"192.168.12.82/24\" - SCRIPTS/build_epc - -c -l - SCRIPTS/build_hss - -c -l + + + + + @@ -1444,10 +1380,7 @@ amerique 390 /tmp - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf tracking_area_code \"1\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf mobile_country_code \"208\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf mobile_network_code \"92\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf tracking_area_code \"1\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf tracking_area_code \"1\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf mobile_country_code \"208\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf mobile_network_code \"92\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf N_RB_DL 50 @@ -1477,11 +1410,8 @@ True /tmp - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf tracking_area_code \"4\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf mobile_country_code \"5\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf mobile_network_code \"6\" - $OPENAIR_DIR/cmake_targets/build_oai - --eNB -w USRP -x -c + + $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue;$OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 45; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue @@ -1494,15 +1424,11 @@ sudo -S -E $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue /tmp - BUILD/EPC/epc.local.enb.conf.in MCC \"208\" - BUILD/EPC/epc.local.enb.conf.in MNC \"92\" - BUILD/EPC/epc.local.enb.conf.in TAC \"1\" - BUILD/EPC/epc.local.enb.conf.in PGW_INTERFACE_NAME_FOR_SGI \"eth1\" - BUILD/EPC/epc.local.enb.conf.in PGW_IPV4_ADDRESS_FOR_SGI \"192.168.12.82/24\" - SCRIPTS/build_epc - -c -l - SCRIPTS/build_hss - -c -l + + + + + @@ -1527,10 +1453,7 @@ amerique 390 /tmp - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf tracking_area_code \"1\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf mobile_country_code \"208\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf mobile_network_code \"92\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf tracking_area_code \"1\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf tracking_area_code \"1\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf mobile_country_code \"208\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf mobile_network_code \"92\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf N_RB_DL 100 @@ -1560,11 +1483,9 @@ True /tmp - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf tracking_area_code \"4\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf mobile_country_code \"5\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf mobile_network_code \"6\" - $OPENAIR_DIR/cmake_targets/build_oai - --eNB -w USRP -x -c + + + $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 45; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue @@ -1577,15 +1498,11 @@ sudo -S -E $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue /tmp - BUILD/EPC/epc.local.enb.conf.in MCC \"208\" - BUILD/EPC/epc.local.enb.conf.in MNC \"92\" - BUILD/EPC/epc.local.enb.conf.in TAC \"1\" - BUILD/EPC/epc.local.enb.conf.in PGW_INTERFACE_NAME_FOR_SGI \"eth1\" - BUILD/EPC/epc.local.enb.conf.in PGW_IPV4_ADDRESS_FOR_SGI \"192.168.12.82/24\" - SCRIPTS/build_epc - -c -l - SCRIPTS/build_hss - -c -l + + + + + @@ -1610,10 +1527,7 @@ amerique 390 /tmp - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf tracking_area_code \"1\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf mobile_country_code \"208\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf mobile_network_code \"92\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf tracking_area_code \"1\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf tracking_area_code \"1\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf mobile_country_code \"208\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf mobile_network_code \"92\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf N_RB_DL 25 @@ -1643,11 +1557,9 @@ True /tmp - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf tracking_area_code \"4\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf mobile_country_code \"5\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf mobile_network_code \"6\" - $OPENAIR_DIR/cmake_targets/build_oai - --eNB -w USRP -x -c + + + $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 45; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue @@ -1661,15 +1573,11 @@ /tmp - BUILD/EPC/epc.local.enb.conf.in MCC \"208\" - BUILD/EPC/epc.local.enb.conf.in MNC \"92\" - BUILD/EPC/epc.local.enb.conf.in TAC \"1\" - BUILD/EPC/epc.local.enb.conf.in PGW_INTERFACE_NAME_FOR_SGI \"eth1\" - BUILD/EPC/epc.local.enb.conf.in PGW_IPV4_ADDRESS_FOR_SGI \"192.168.12.82/24\" - SCRIPTS/build_epc - -c -l - SCRIPTS/build_hss - -c -l + + + + + @@ -1693,10 +1601,7 @@ amerique 390 /tmp - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf tracking_area_code \"1\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf mobile_country_code \"208\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf mobile_network_code \"92\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf tracking_area_code \"1\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf tracking_area_code \"1\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf mobile_country_code \"208\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf mobile_network_code \"92\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf N_RB_DL 50 @@ -1726,11 +1631,9 @@ True /tmp - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf tracking_area_code \"4\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf mobile_country_code \"5\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf mobile_network_code \"6\" - $OPENAIR_DIR/cmake_targets/build_oai - --eNB -w USRP -x -c + + + $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 45; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue @@ -1744,15 +1647,11 @@ /tmp - BUILD/EPC/epc.local.enb.conf.in MCC \"208\" - BUILD/EPC/epc.local.enb.conf.in MNC \"92\" - BUILD/EPC/epc.local.enb.conf.in TAC \"1\" - BUILD/EPC/epc.local.enb.conf.in PGW_INTERFACE_NAME_FOR_SGI \"eth1\" - BUILD/EPC/epc.local.enb.conf.in PGW_IPV4_ADDRESS_FOR_SGI \"192.168.12.82/24\" - SCRIPTS/build_epc - -c -l - SCRIPTS/build_hss - -c -l + + + + + @@ -1776,10 +1675,7 @@ amerique 390 /tmp - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf tracking_area_code \"1\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf mobile_country_code \"208\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf mobile_network_code \"92\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf tracking_area_code \"1\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf tracking_area_code \"1\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf mobile_country_code \"208\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf mobile_network_code \"92\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf N_RB_DL 100 @@ -1809,11 +1705,9 @@ True /tmp - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf tracking_area_code \"4\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf mobile_country_code \"5\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf mobile_network_code \"6\" - $OPENAIR_DIR/cmake_targets/build_oai - --eNB -w USRP -x -c + + + $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 45; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue @@ -1827,15 +1721,11 @@ /tmp - BUILD/EPC/epc.local.enb.conf.in MCC \"208\" - BUILD/EPC/epc.local.enb.conf.in MNC \"92\" - BUILD/EPC/epc.local.enb.conf.in TAC \"1\" - BUILD/EPC/epc.local.enb.conf.in PGW_INTERFACE_NAME_FOR_SGI \"eth1\" - BUILD/EPC/epc.local.enb.conf.in PGW_IPV4_ADDRESS_FOR_SGI \"192.168.12.82/24\" - SCRIPTS/build_epc - -c -l - SCRIPTS/build_hss - -c -l + + + + + From 20834d6947d7916fcbfeef4cede56105a341859e Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Wed, 27 Jan 2016 19:10:09 +0100 Subject: [PATCH 181/263] hotfix for CCE bug --- openair2/LAYER2/MAC/eNB_scheduler_primitives.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/openair2/LAYER2/MAC/eNB_scheduler_primitives.c b/openair2/LAYER2/MAC/eNB_scheduler_primitives.c index 20b1f6d735..9cabd6b622 100644 --- a/openair2/LAYER2/MAC/eNB_scheduler_primitives.c +++ b/openair2/LAYER2/MAC/eNB_scheduler_primitives.c @@ -1101,8 +1101,9 @@ boolean_t CCE_allocation_infeasible(int module_idP, DCI_pdu->Num_ue_spec_dci++; ret = allocate_CCEs(module_idP,CC_idP,subframe,1); if (ret==-1) - res = FALSE; + res = TRUE; DCI_pdu->Num_ue_spec_dci--; } + return(res); } From 88473207a1150e0750dc0def0396441f81ec23ef Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Wed, 27 Jan 2016 19:37:02 +0100 Subject: [PATCH 182/263] fixed bug in xml file --- cmake_targets/autotests/test_case_list.xml | 251 ++++++++------------- 1 file changed, 90 insertions(+), 161 deletions(-) diff --git a/cmake_targets/autotests/test_case_list.xml b/cmake_targets/autotests/test_case_list.xml index 39ae56d506..6e0d1c2fdb 100644 --- a/cmake_targets/autotests/test_case_list.xml +++ b/cmake_targets/autotests/test_case_list.xml @@ -1187,7 +1187,7 @@ True /tmp - + @@ -1410,7 +1410,7 @@ True /tmp - + > @@ -2787,11 +2787,8 @@ True /tmp - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf tracking_area_code \"4\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf mobile_country_code \"5\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf mobile_network_code \"6\" - $OPENAIR_DIR/cmake_targets/build_oai - --eNB -w USRP -x -c + + $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 45; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue @@ -2804,15 +2801,11 @@ sudo -S -E $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue /tmp - BUILD/EPC/epc.local.enb.conf.in MCC \"208\" - BUILD/EPC/epc.local.enb.conf.in MNC \"92\" - BUILD/EPC/epc.local.enb.conf.in TAC \"1\" - BUILD/EPC/epc.local.enb.conf.in PGW_INTERFACE_NAME_FOR_SGI \"eth1\" - BUILD/EPC/epc.local.enb.conf.in PGW_IPV4_ADDRESS_FOR_SGI \"192.168.12.82/24\" - SCRIPTS/build_epc - -c -l - SCRIPTS/build_hss - -c -l + + + + + @@ -2866,11 +2859,8 @@ True /tmp - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf tracking_area_code \"4\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf mobile_country_code \"5\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf mobile_network_code \"6\" - $OPENAIR_DIR/cmake_targets/build_oai - --eNB -w USRP -x -c + + $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 45; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue @@ -2883,15 +2873,11 @@ sudo -S -E $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue /tmp - BUILD/EPC/epc.local.enb.conf.in MCC \"208\" - BUILD/EPC/epc.local.enb.conf.in MNC \"92\" - BUILD/EPC/epc.local.enb.conf.in TAC \"1\" - BUILD/EPC/epc.local.enb.conf.in PGW_INTERFACE_NAME_FOR_SGI \"eth1\" - BUILD/EPC/epc.local.enb.conf.in PGW_IPV4_ADDRESS_FOR_SGI \"192.168.12.82/24\" - SCRIPTS/build_epc - -c -l - SCRIPTS/build_hss - -c -l + + + + + @@ -2944,11 +2930,9 @@ True /tmp - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf tracking_area_code \"4\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf mobile_country_code \"5\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf mobile_network_code \"6\" - $OPENAIR_DIR/cmake_targets/build_oai - --eNB -w USRP -x -c + + + $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 45; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue @@ -2961,15 +2945,11 @@ sudo -S -E $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue /tmp - BUILD/EPC/epc.local.enb.conf.in MCC \"208\" - BUILD/EPC/epc.local.enb.conf.in MNC \"92\" - BUILD/EPC/epc.local.enb.conf.in TAC \"1\" - BUILD/EPC/epc.local.enb.conf.in PGW_INTERFACE_NAME_FOR_SGI \"eth1\" - BUILD/EPC/epc.local.enb.conf.in PGW_IPV4_ADDRESS_FOR_SGI \"192.168.12.82/24\" - SCRIPTS/build_epc - -c -l - SCRIPTS/build_hss - -c -l + + + + + @@ -3022,11 +3002,9 @@ True /tmp - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf tracking_area_code \"4\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf mobile_country_code \"5\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf mobile_network_code \"6\" - $OPENAIR_DIR/cmake_targets/build_oai - --eNB -w USRP -x -c + + + $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 45; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue @@ -3039,15 +3017,11 @@ /tmp - BUILD/EPC/epc.local.enb.conf.in MCC \"208\" - BUILD/EPC/epc.local.enb.conf.in MNC \"92\" - BUILD/EPC/epc.local.enb.conf.in TAC \"1\" - BUILD/EPC/epc.local.enb.conf.in PGW_INTERFACE_NAME_FOR_SGI \"eth1\" - BUILD/EPC/epc.local.enb.conf.in PGW_IPV4_ADDRESS_FOR_SGI \"192.168.12.82/24\" - SCRIPTS/build_epc - -c -l - SCRIPTS/build_hss - -c -l + + + + + @@ -3099,11 +3073,9 @@ True /tmp - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf tracking_area_code \"4\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf mobile_country_code \"5\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf mobile_network_code \"6\" - $OPENAIR_DIR/cmake_targets/build_oai - --eNB -w USRP -x -c + + + $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 45; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue @@ -3116,15 +3088,11 @@ /tmp - BUILD/EPC/epc.local.enb.conf.in MCC \"208\" - BUILD/EPC/epc.local.enb.conf.in MNC \"92\" - BUILD/EPC/epc.local.enb.conf.in TAC \"1\" - BUILD/EPC/epc.local.enb.conf.in PGW_INTERFACE_NAME_FOR_SGI \"eth1\" - BUILD/EPC/epc.local.enb.conf.in PGW_IPV4_ADDRESS_FOR_SGI \"192.168.12.82/24\" - SCRIPTS/build_epc - -c -l - SCRIPTS/build_hss - -c -l + + + + + @@ -3176,11 +3144,9 @@ True /tmp - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf tracking_area_code \"4\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf mobile_country_code \"5\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf mobile_network_code \"6\" - $OPENAIR_DIR/cmake_targets/build_oai - --eNB -w USRP -x -c + + + $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 45; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue @@ -3193,15 +3159,11 @@ /tmp - BUILD/EPC/epc.local.enb.conf.in MCC \"208\" - BUILD/EPC/epc.local.enb.conf.in MNC \"92\" - BUILD/EPC/epc.local.enb.conf.in TAC \"1\" - BUILD/EPC/epc.local.enb.conf.in PGW_INTERFACE_NAME_FOR_SGI \"eth1\" - BUILD/EPC/epc.local.enb.conf.in PGW_IPV4_ADDRESS_FOR_SGI \"192.168.12.82/24\" - SCRIPTS/build_epc - -c -l - SCRIPTS/build_hss - -c -l + + + + + @@ -3744,11 +3706,8 @@ True /tmp - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf tracking_area_code \"4\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf mobile_country_code \"5\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf mobile_network_code \"6\" - $OPENAIR_DIR/cmake_targets/build_oai - --eNB -w USRP -x -c + + $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 45; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue @@ -3761,15 +3720,11 @@ sudo -S -E $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue /tmp - BUILD/EPC/epc.local.enb.conf.in MCC \"208\" - BUILD/EPC/epc.local.enb.conf.in MNC \"92\" - BUILD/EPC/epc.local.enb.conf.in TAC \"1\" - BUILD/EPC/epc.local.enb.conf.in PGW_INTERFACE_NAME_FOR_SGI \"eth1\" - BUILD/EPC/epc.local.enb.conf.in PGW_IPV4_ADDRESS_FOR_SGI \"192.168.12.82/24\" - SCRIPTS/build_epc - -c -l - SCRIPTS/build_hss - -c -l + + + + + @@ -3823,11 +3778,9 @@ True /tmp - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf tracking_area_code \"4\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf mobile_country_code \"5\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf mobile_network_code \"6\" - $OPENAIR_DIR/cmake_targets/build_oai - --eNB -w USRP -x -c + + + $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 45; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue @@ -3840,15 +3793,11 @@ sudo -S -E $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue /tmp - BUILD/EPC/epc.local.enb.conf.in MCC \"208\" - BUILD/EPC/epc.local.enb.conf.in MNC \"92\" - BUILD/EPC/epc.local.enb.conf.in TAC \"1\" - BUILD/EPC/epc.local.enb.conf.in PGW_INTERFACE_NAME_FOR_SGI \"eth1\" - BUILD/EPC/epc.local.enb.conf.in PGW_IPV4_ADDRESS_FOR_SGI \"192.168.12.82/24\" - SCRIPTS/build_epc - -c -l - SCRIPTS/build_hss - -c -l + + + + + @@ -3901,11 +3850,9 @@ True /tmp - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf tracking_area_code \"4\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf mobile_country_code \"5\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf mobile_network_code \"6\" - $OPENAIR_DIR/cmake_targets/build_oai - --eNB -w USRP -x -c + + + $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 45; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue @@ -3979,11 +3926,9 @@ True /tmp - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf tracking_area_code \"4\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf mobile_country_code \"5\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf mobile_network_code \"6\" - $OPENAIR_DIR/cmake_targets/build_oai - --eNB -w USRP -x -c + + + $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 45; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue @@ -3996,15 +3941,11 @@ /tmp - BUILD/EPC/epc.local.enb.conf.in MCC \"208\" - BUILD/EPC/epc.local.enb.conf.in MNC \"92\" - BUILD/EPC/epc.local.enb.conf.in TAC \"1\" - BUILD/EPC/epc.local.enb.conf.in PGW_INTERFACE_NAME_FOR_SGI \"eth1\" - BUILD/EPC/epc.local.enb.conf.in PGW_IPV4_ADDRESS_FOR_SGI \"192.168.12.82/24\" - SCRIPTS/build_epc - -c -l - SCRIPTS/build_hss - -c -l + + + + + @@ -4056,11 +3997,9 @@ True /tmp - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf tracking_area_code \"4\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf mobile_country_code \"5\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf mobile_network_code \"6\" - $OPENAIR_DIR/cmake_targets/build_oai - --eNB -w USRP -x -c + + + $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 45; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue @@ -4073,15 +4012,11 @@ /tmp - BUILD/EPC/epc.local.enb.conf.in MCC \"208\" - BUILD/EPC/epc.local.enb.conf.in MNC \"92\" - BUILD/EPC/epc.local.enb.conf.in TAC \"1\" - BUILD/EPC/epc.local.enb.conf.in PGW_INTERFACE_NAME_FOR_SGI \"eth1\" - BUILD/EPC/epc.local.enb.conf.in PGW_IPV4_ADDRESS_FOR_SGI \"192.168.12.82/24\" - SCRIPTS/build_epc - -c -l - SCRIPTS/build_hss - -c -l + + + + + @@ -4133,11 +4068,9 @@ True /tmp - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf tracking_area_code \"4\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf mobile_country_code \"5\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.local.conf mobile_network_code \"6\" - $OPENAIR_DIR/cmake_targets/build_oai - --eNB -w USRP -x -c + + + $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 45; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue @@ -4150,15 +4083,11 @@ /tmp - BUILD/EPC/epc.local.enb.conf.in MCC \"208\" - BUILD/EPC/epc.local.enb.conf.in MNC \"92\" - BUILD/EPC/epc.local.enb.conf.in TAC \"1\" - BUILD/EPC/epc.local.enb.conf.in PGW_INTERFACE_NAME_FOR_SGI \"eth1\" - BUILD/EPC/epc.local.enb.conf.in PGW_IPV4_ADDRESS_FOR_SGI \"192.168.12.82/24\" - SCRIPTS/build_epc - -c -l - SCRIPTS/build_hss - -c -l + + + + + From 9d4f383421836dff5bc62acc47dd240bfa623485 Mon Sep 17 00:00:00 2001 From: kaltenbe Date: Thu, 28 Jan 2016 20:21:38 +0100 Subject: [PATCH 183/263] first integration. doesn't compile. --- .../ARCH/SODERA/USERSPACE/LIB/sodera_lib.cpp | 212 +++++++++++++++--- 1 file changed, 186 insertions(+), 26 deletions(-) diff --git a/targets/ARCH/SODERA/USERSPACE/LIB/sodera_lib.cpp b/targets/ARCH/SODERA/USERSPACE/LIB/sodera_lib.cpp index 5914ff5be6..e5b9107251 100644 --- a/targets/ARCH/SODERA/USERSPACE/LIB/sodera_lib.cpp +++ b/targets/ARCH/SODERA/USERSPACE/LIB/sodera_lib.cpp @@ -68,6 +68,8 @@ int num_devices=0; /*These items configure the underlying asynch stream used by the the sync interface. */ +#define BUFFERSIZE 65536 +#define BUFFERSCOUNT 16 // must be a power of 2 typedef struct { @@ -80,10 +82,16 @@ typedef struct LMS7002M lmsControl; LMS_StreamBoard *lmsStream; + uint8_t buffers_rx[BUFFERSIZE*BUFFERSCOUNT]; + int handles[BUFFERSCOUNT]; + int last_handle; + int samples_left_buffer; + double sample_rate; // time offset between transmiter timestamp and receiver timestamp; double tdiff; + int channelscount; // -------------------------------- // Debug and output control // -------------------------------- @@ -97,17 +105,86 @@ typedef struct } sodera_t; +typedef struct { + uint8_t reserved[8]; + uint64_t counter; + uint8_t data[4080]; +} StreamPacket_t; + sodera_t sodera_state; +enum STATUS { + SUCCESS, + FAILURE +}; + +STATUS SPI_write(LMScomms* dataPort, uint16_t address, uint16_t data) +{ + assert(dataPort != nullptr); + LMScomms::GenericPacket ctrPkt; + ctrPkt.cmd = CMD_BRDSPI_WR; + ctrPkt.outBuffer.push_back((address >> 8) & 0xFF); + ctrPkt.outBuffer.push_back(address & 0xFF); + ctrPkt.outBuffer.push_back((data >> 8) & 0xFF); + ctrPkt.outBuffer.push_back(data & 0xFF); + dataPort->TransferPacket(ctrPkt); + return ctrPkt.status == 1 ? SUCCESS : FAILURE; +} + +uint16_t SPI_read(LMScomms* dataPort, uint16_t address) +{ + assert(dataPort != nullptr); + LMScomms::GenericPacket ctrPkt; + ctrPkt.cmd = CMD_BRDSPI_RD; + ctrPkt.outBuffer.push_back((address >> 8) & 0xFF); + ctrPkt.outBuffer.push_back(address & 0xFF); + dataPort->TransferPacket(ctrPkt); + if (ctrPkt.inBuffer.size() > 4) + return ctrPkt.inBuffer[2] * 256 + ctrPkt.inBuffer[3]; + else + return 0; +} + static int trx_sodera_start(openair0_device *device) { sodera_t *s = (sodera_t*)device->priv; + const int buffersCountMask = buffersCount-1; + // init recv and send streaming s->rx_count = 0; s->tx_count = 0; s->rx_timestamp = 0; + s->current_handle = 0; + + // switch off RX + uint16_t regVal = SPI_read(s->Port,0x0005); + SPI_write(s->port,0x0005,regVal & ~0x6); + + if (s->channelscount==2) { + SPI_write(s->Port,0x0001,0x0003); + SPI_write(s->Port,0x0007,0x000A); + } + else { + SPI_write(s->Port,0x0001,0x0001); + SPI_write(s->Port,0x0007,0x0008); + } + + // USB FIFO reset + LMScomms::GenericPacket ctrPkt; + ctrPkt.cmd = CMD_USR_FIFO_RST; + ctrPkt.outBuffer.push_back(0x01); + s->Port.TransferPacket(ctrPkt); + ctrPkt.outBuffer[0]=0x00; + s->Port.TransferPacket(ctrPkt); + + uint16_t regVal = SPI_read(s->Port,0x0005); + // provide timestamp, set streamTXEN, set TX/RX enable + SPI_write(s->port,0x0005,(regVal & ~0x20) | 0x6); + + for (int i=0; i< BUFFERSCOUNT ; i++) + s->handles[i] = s->Port.BeginDataReading(&s->buffers[i*BUFFERSIZE],BUFFERSIZE); return 0; } @@ -117,7 +194,10 @@ static void trx_sodera_end(openair0_device *device) sodera_t *s = (sodera_t*)device->priv; - + // stop TX/RX if they were active + regVal = SPI_read(s->Port,0x0005); + SPI_write(s->Port,0x0005,regVal & ~0x6); + } static int trx_sodera_write(openair0_device *device, openair0_timestamp timestamp, void **buff, int nsamps, int cc, int flags) @@ -138,36 +218,114 @@ static int trx_sodera_read(openair0_device *device, openair0_timestamp *ptimesta sodera_t *s = (sodera_t*)device->priv; int samples_received=0,i,j; int nsamps2; // aligned to upper 32 or 16 byte boundary -#if defined(__x86_64) || defined(__i386__) -#ifdef __AVX2__ - __m256i buff_tmp[2][nsamps>>3]; - nsamps2 = (nsamps+7)>>3; -#else - __m128i buff_tmp[2][nsamps>>2]; - nsamps2 = (nsamps+3)>>2; -#endif -#elif defined(__arm__) - int16x8_t buff_tmp[2][nsamps>>2]; - nsamps2 = (nsamps+3)>>2; -#endif + StreamPacket_t *p; + int16_t sampleI,sampleQ; + uint8_t *pktStart; + int offset = 0; + int num_p; + int ind=0; - - if (cc>1) { - // receive multiple channels (e.g. RF A and RF B) - - } else { - // receive a single channel (e.g. from connector RF A) - - } + // this assumes that each request is of size 4096 bytes (spp = 4080/4/channelscount) - if (samples_received < nsamps) { - printf("[recv] received %d samples out of %d\n",samples_received,nsamps); + // first get rid of remaining samples + if (s->samples_left_buffer > 0) { + buffsize = min(s->samples_left_buffer,nsamps); + pktStart = &s->buffers_rx[(s->last_handle-1)*BUFFERSIZE].data; + pktStart -= (spp-s->samples_left_buffer); + const int stepSize = s->channelscount * 3; + + for (int b=0;bchannelscount;ch++) { + // I sample + sampleI = (pktStart[b + 1 + 3*ch]&0x0F)<<8; + sampleI |= (pktStart[b + 3*ch]&0xFF); + sampleI = (sampleI<<4)>>4; + // Q sample + sampleQ = (pktStart[b + 2 + 3*ch]&0x0F)<<8; + sampleQ |= (pktStart[b + 1 + 3*ch]&0xFF); + sampleQ = (sampleQ<<4)>>4; + ((uint32_t*)buff[ch])[ind] = ((uint32_t)sampleI) | (((uint32_t)sampleQ)<<16); + } + ind++; + } + } + if (ind == nsamps) { + s->samples_left_buffer -= nsamps; + s->rx_count += nsamps; + s->rx_timestamp += s->last_transfer; + *ptimestamp = s->rx_timestamp; + s->last_transfer = nsamps; + + return(nsamps); + } + else { + s->samples_left_buffer = 0; + nsamps -= ind; + samples_received = ind; + } + + // This is for the left-over part => READ from USB + + + spp = sizeof(p->data)>>2; // spp = size of payload in samples + spp /= s->channelscount; + + num_p = nsamps / spp; + if ((nsamps%spp) > 0) + num_p++; + s->samples_left_buffer = (num_p*spp)-nsamps; + for (int i=0;ihandles[i] = s->Port.BeginDataReading(&buffers_rx[i*BUFFERSIZE],BUFFERSIZE); + s->last_handle = num_p; + + + const int stepSize = s->channelscount * 3; + + for (i=0;iPort.WaitForReading(s->handles[i],1000) == false) { + printf("[recv] Error: request %d samples (%d/%d) WaitForReading timed out\n",nsamps,i,num_p); + return(samples_received); + } + if ((ret=Port.FinishDataReading(&s->buffers_rx[i*BUFFERSIZE],BUFFERSIZE,s->handles[i])) != BUFFERSIZE) { + printf("[recv] Error: request %d samples (%d/%d) WaitForReading timed out\n",nsamps,i,num_p); + return(samples_received); + } - } + p = (StreamPacket_t*)&s->buffers_rx[i*BUFFERSIZE]; + // handle timestamp + if ((i==0) & (ind==0)) { // grab the timestamp from HW + s->rx_timestamp = p->counter; + } + else { // check the timestamp + if (i==0) { + if ((s->rx_timestamp + ind) != p->counter) { + printf("Error, RX timestamp error, got %llu, should be %llu\n",p->counter,s->rx_timestamp+ind); + return(ind); + } + } + } + pktStart = &p->data; + for (uint16_t b=0;bdata);n+=stepSize) { + for (int ch=0;ch < s->channelscount;ch++) { + // I sample + sampleI = (pktStart[b + 1 + 3*ch]&0x0F)<<8; + sampleI |= (pktStart[b + 3*ch]&0xFF); + sampleI = (sampleI<<4)>>4; + // Q sample + sampleQ = (pktStart[b + 2 + 3*ch]&0x0F)<<8; + sampleQ |= (pktStart[b + 1 + 3*ch]&0xFF); + sampleQ = (sampleQ<<4)>>4; + ((uint32_t*)buff[ch])[ind] = ((uint32_t)sampleI) | (((uint32_t)sampleQ)<<16); + } + ind++; + } + samples_received+=spp; + } //handle the error code - s->rx_count += nsamps; + s->rx_count += samples_received; // s->rx_timestamp = s->rx_md.time_spec.to_ticks(s->sample_rate); *ptimestamp = s->rx_timestamp; @@ -531,7 +689,9 @@ int openair0_dev_init_sodera(openair0_device* device, openair0_config_t *openair device->trx_set_freq_func = trx_sodera_set_freq; device->trx_set_gains_func = trx_sodera_set_gains; - s->sample_rate = openair0_cfg[0].sample_rate; + s->sample_rate = openair0_cfg[0].sample_rate; + s->channelscount = openair0_cfg[0].rx_num_channels; + // TODO: exit(-1); return 0; From ec96a43dc35b7cdaaf3251b45d223145ebfa4b1a Mon Sep 17 00:00:00 2001 From: Raymond Knopp Date: Thu, 28 Jan 2016 23:24:17 -0800 Subject: [PATCH 184/263] integration, compiles now. --- .../ARCH/SODERA/USERSPACE/LIB/sodera_lib.cpp | 68 +++++++++---------- 1 file changed, 34 insertions(+), 34 deletions(-) diff --git a/targets/ARCH/SODERA/USERSPACE/LIB/sodera_lib.cpp b/targets/ARCH/SODERA/USERSPACE/LIB/sodera_lib.cpp index e5b9107251..85dd0a6032 100644 --- a/targets/ARCH/SODERA/USERSPACE/LIB/sodera_lib.cpp +++ b/targets/ARCH/SODERA/USERSPACE/LIB/sodera_lib.cpp @@ -68,8 +68,8 @@ int num_devices=0; /*These items configure the underlying asynch stream used by the the sync interface. */ -#define BUFFERSIZE 65536 -#define BUFFERSCOUNT 16 // must be a power of 2 +#define BUFFERSIZE 4096 +#define BUFFERSCOUNT 32 typedef struct { @@ -82,10 +82,11 @@ typedef struct LMS7002M lmsControl; LMS_StreamBoard *lmsStream; - uint8_t buffers_rx[BUFFERSIZE*BUFFERSCOUNT]; + char buffers_rx[BUFFERSIZE*BUFFERSCOUNT]; int handles[BUFFERSCOUNT]; - int last_handle; + int current_handle; int samples_left_buffer; + int last_transfer; double sample_rate; // time offset between transmiter timestamp and receiver timestamp; @@ -108,7 +109,7 @@ typedef struct typedef struct { uint8_t reserved[8]; uint64_t counter; - uint8_t data[4080]; + char data[4080]; } StreamPacket_t; sodera_t sodera_state; @@ -149,7 +150,6 @@ static int trx_sodera_start(openair0_device *device) { sodera_t *s = (sodera_t*)device->priv; - const int buffersCountMask = buffersCount-1; // init recv and send streaming @@ -157,34 +157,35 @@ static int trx_sodera_start(openair0_device *device) s->tx_count = 0; s->rx_timestamp = 0; s->current_handle = 0; + s->last_transfer = 0; // switch off RX - uint16_t regVal = SPI_read(s->Port,0x0005); - SPI_write(s->port,0x0005,regVal & ~0x6); + uint16_t regVal = SPI_read(&s->Port,0x0005); + SPI_write(&s->Port,0x0005,regVal & ~0x6); if (s->channelscount==2) { - SPI_write(s->Port,0x0001,0x0003); - SPI_write(s->Port,0x0007,0x000A); + SPI_write(&s->Port,0x0001,0x0003); + SPI_write(&s->Port,0x0007,0x000A); } else { - SPI_write(s->Port,0x0001,0x0001); - SPI_write(s->Port,0x0007,0x0008); + SPI_write(&s->Port,0x0001,0x0001); + SPI_write(&s->Port,0x0007,0x0008); } // USB FIFO reset LMScomms::GenericPacket ctrPkt; - ctrPkt.cmd = CMD_USR_FIFO_RST; + ctrPkt.cmd = CMD_USB_FIFO_RST; ctrPkt.outBuffer.push_back(0x01); s->Port.TransferPacket(ctrPkt); ctrPkt.outBuffer[0]=0x00; s->Port.TransferPacket(ctrPkt); - uint16_t regVal = SPI_read(s->Port,0x0005); + regVal = SPI_read(&s->Port,0x0005); // provide timestamp, set streamTXEN, set TX/RX enable - SPI_write(s->port,0x0005,(regVal & ~0x20) | 0x6); + SPI_write(&s->Port,0x0005,(regVal & ~0x20) | 0x6); for (int i=0; i< BUFFERSCOUNT ; i++) - s->handles[i] = s->Port.BeginDataReading(&s->buffers[i*BUFFERSIZE],BUFFERSIZE); + s->handles[i] = s->Port.BeginDataReading(&s->buffers_rx[i*BUFFERSIZE],BUFFERSIZE); return 0; } @@ -195,8 +196,8 @@ static void trx_sodera_end(openair0_device *device) // stop TX/RX if they were active - regVal = SPI_read(s->Port,0x0005); - SPI_write(s->Port,0x0005,regVal & ~0x6); + uint16_t regVal = SPI_read(&s->Port,0x0005); + SPI_write(&s->Port,0x0005,regVal & ~0x6); } @@ -204,11 +205,6 @@ static int trx_sodera_write(openair0_device *device, openair0_timestamp timestam { sodera_t *s = (sodera_t*)device->priv; - if (cc>1) { - // s->tx_stream->send(buff_ptrs, nsamps, s->tx_md); - } - else - // s->tx_stream->send(buff[0], nsamps, s->tx_md); return 0; } @@ -220,18 +216,23 @@ static int trx_sodera_read(openair0_device *device, openair0_timestamp *ptimesta int nsamps2; // aligned to upper 32 or 16 byte boundary StreamPacket_t *p; int16_t sampleI,sampleQ; - uint8_t *pktStart; + char *pktStart; int offset = 0; int num_p; int ind=0; + int buffsize; + int spp; // this assumes that each request is of size 4096 bytes (spp = 4080/4/channelscount) - + spp = sizeof(p->data)>>2; // spp = size of payload in samples + spp /= s->channelscount; + + // first get rid of remaining samples if (s->samples_left_buffer > 0) { buffsize = min(s->samples_left_buffer,nsamps); - pktStart = &s->buffers_rx[(s->last_handle-1)*BUFFERSIZE].data; - pktStart -= (spp-s->samples_left_buffer); + pktStart = ((StreamPacket_t*)&s->buffers_rx[(s->current_handle-1)*BUFFERSIZE])->data; + pktStart += (spp-s->samples_left_buffer); const int stepSize = s->channelscount * 3; for (int b=0;b READ from USB - spp = sizeof(p->data)>>2; // spp = size of payload in samples - spp /= s->channelscount; num_p = nsamps / spp; if ((nsamps%spp) > 0) num_p++; s->samples_left_buffer = (num_p*spp)-nsamps; for (int i=0;ihandles[i] = s->Port.BeginDataReading(&buffers_rx[i*BUFFERSIZE],BUFFERSIZE); - s->last_handle = num_p; + s->handles[i] = s->Port.BeginDataReading(&s->buffers_rx[i*BUFFERSIZE],BUFFERSIZE); + s->current_handle = num_p; const int stepSize = s->channelscount * 3; @@ -287,7 +286,8 @@ static int trx_sodera_read(openair0_device *device, openair0_timestamp *ptimesta printf("[recv] Error: request %d samples (%d/%d) WaitForReading timed out\n",nsamps,i,num_p); return(samples_received); } - if ((ret=Port.FinishDataReading(&s->buffers_rx[i*BUFFERSIZE],BUFFERSIZE,s->handles[i])) != BUFFERSIZE) { + long bytesToRead=BUFFERSIZE; + if (s->Port.FinishDataReading(&s->buffers_rx[i*BUFFERSIZE],bytesToRead,s->handles[i]) != BUFFERSIZE) { printf("[recv] Error: request %d samples (%d/%d) WaitForReading timed out\n",nsamps,i,num_p); return(samples_received); } @@ -305,8 +305,8 @@ static int trx_sodera_read(openair0_device *device, openair0_timestamp *ptimesta } } } - pktStart = &p->data; - for (uint16_t b=0;bdata);n+=stepSize) { + pktStart = p->data; + for (uint16_t b=0;bdata);b+=stepSize) { for (int ch=0;ch < s->channelscount;ch++) { // I sample sampleI = (pktStart[b + 1 + 3*ch]&0x0F)<<8; From 2b5f756d47c6ae578f00a1a05ff59b84f5784dda Mon Sep 17 00:00:00 2001 From: kaltenbe Date: Fri, 29 Jan 2016 09:45:28 +0100 Subject: [PATCH 185/263] getting ready for rename --- .../ARCH/SODERA/USERSPACE/LIB/sodera_lib.cpp | 89 +- targets/ARCH/SODERA/lms7_trx_LTE_mimo_RF.ini | 1128 ----------------- targets/ARCH/SODERA/lms7_trx_LTE_mimo_TSG.ini | 1128 ----------------- .../CONF/enb.band7.tm1.50PRB.bladerfx40.conf | 8 +- 4 files changed, 61 insertions(+), 2292 deletions(-) delete mode 100644 targets/ARCH/SODERA/lms7_trx_LTE_mimo_RF.ini delete mode 100644 targets/ARCH/SODERA/lms7_trx_LTE_mimo_TSG.ini diff --git a/targets/ARCH/SODERA/USERSPACE/LIB/sodera_lib.cpp b/targets/ARCH/SODERA/USERSPACE/LIB/sodera_lib.cpp index 85dd0a6032..30a2106b34 100644 --- a/targets/ARCH/SODERA/USERSPACE/LIB/sodera_lib.cpp +++ b/targets/ARCH/SODERA/USERSPACE/LIB/sodera_lib.cpp @@ -86,7 +86,6 @@ typedef struct int handles[BUFFERSCOUNT]; int current_handle; int samples_left_buffer; - int last_transfer; double sample_rate; // time offset between transmiter timestamp and receiver timestamp; @@ -153,16 +152,34 @@ static int trx_sodera_start(openair0_device *device) // init recv and send streaming + printf("Starting LMS Streaming\n"); s->rx_count = 0; s->tx_count = 0; s->rx_timestamp = 0; s->current_handle = 0; - s->last_transfer = 0; // switch off RX uint16_t regVal = SPI_read(&s->Port,0x0005); SPI_write(&s->Port,0x0005,regVal & ~0x6); + + + + + + // USB FIFO reset + LMScomms::GenericPacket ctrPkt; + ctrPkt.cmd = CMD_USB_FIFO_RST; + ctrPkt.outBuffer.push_back(0x01); + s->Port.TransferPacket(ctrPkt); + ctrPkt.outBuffer[0]=0x00; + s->Port.TransferPacket(ctrPkt); + + regVal = SPI_read(&s->Port,0x0005); + // provide timestamp, set streamTXEN, set TX/RX enable + SPI_write(&s->Port,0x0005,(regVal & ~0x20) | 0x6); + + if (s->channelscount==2) { SPI_write(&s->Port,0x0001,0x0003); SPI_write(&s->Port,0x0007,0x000A); @@ -172,21 +189,10 @@ static int trx_sodera_start(openair0_device *device) SPI_write(&s->Port,0x0007,0x0008); } - // USB FIFO reset - LMScomms::GenericPacket ctrPkt; - ctrPkt.cmd = CMD_USB_FIFO_RST; - ctrPkt.outBuffer.push_back(0x01); - s->Port.TransferPacket(ctrPkt); - ctrPkt.outBuffer[0]=0x00; - s->Port.TransferPacket(ctrPkt); - - regVal = SPI_read(&s->Port,0x0005); - // provide timestamp, set streamTXEN, set TX/RX enable - SPI_write(&s->Port,0x0005,(regVal & ~0x20) | 0x6); for (int i=0; i< BUFFERSCOUNT ; i++) s->handles[i] = s->Port.BeginDataReading(&s->buffers_rx[i*BUFFERSIZE],BUFFERSIZE); - + printf("Armed %d transfers\n",BUFFERSCOUNT); return 0; } @@ -209,6 +215,8 @@ static int trx_sodera_write(openair0_device *device, openair0_timestamp timestam return 0; } +#define DEBUG_READ 1 + static int trx_sodera_read(openair0_device *device, openair0_timestamp *ptimestamp, void **buff, int nsamps, int cc) { sodera_t *s = (sodera_t*)device->priv; @@ -222,16 +230,21 @@ static int trx_sodera_read(openair0_device *device, openair0_timestamp *ptimesta int ind=0; int buffsize; int spp; + int bufindex; // this assumes that each request is of size 4096 bytes (spp = 4080/4/channelscount) spp = sizeof(p->data)>>2; // spp = size of payload in samples spp /= s->channelscount; - +#ifdef DEBUG_READ + printf("\nIn trx_read\n"); + printf("s->current_handle %d\n", s->current_handle); + printf("s->samples_left_buffer %d\n",s->samples_left_buffer); +#endif // first get rid of remaining samples if (s->samples_left_buffer > 0) { buffsize = min(s->samples_left_buffer,nsamps); - pktStart = ((StreamPacket_t*)&s->buffers_rx[(s->current_handle-1)*BUFFERSIZE])->data; + pktStart = ((StreamPacket_t*)&s->buffers_rx[s->current_handle*BUFFERSIZE])->data; pktStart += (spp-s->samples_left_buffer); const int stepSize = s->channelscount * 3; @@ -253,10 +266,9 @@ static int trx_sodera_read(openair0_device *device, openair0_timestamp *ptimesta if (ind == nsamps) { s->samples_left_buffer -= nsamps; s->rx_count += nsamps; - s->rx_timestamp += s->last_transfer; *ptimestamp = s->rx_timestamp; - s->last_transfer = nsamps; - + s->rx_timestamp+=nsamps; + return(nsamps); } else { @@ -273,29 +285,38 @@ static int trx_sodera_read(openair0_device *device, openair0_timestamp *ptimesta if ((nsamps%spp) > 0) num_p++; s->samples_left_buffer = (num_p*spp)-nsamps; - for (int i=0;ihandles[i] = s->Port.BeginDataReading(&s->buffers_rx[i*BUFFERSIZE],BUFFERSIZE); - s->current_handle = num_p; - + +#ifdef DEBUG_READ + printf("num_p %d\n",num_p); +#endif const int stepSize = s->channelscount * 3; for (i=0;iPort.WaitForReading(s->handles[i],1000) == false) { - printf("[recv] Error: request %d samples (%d/%d) WaitForReading timed out\n",nsamps,i,num_p); + bufindex = (s->current_handle+i)&(BUFFERSCOUNT-1); + if (s->Port.WaitForReading(s->handles[bufindex],1000) == false) { + printf("[recv] Error: request %d samples (%d/%d) WaitForReading timed out\n",nsamps,bufindex,num_p); + *ptimestamp = s->rx_timestamp; + s->rx_timestamp+=samples_received; return(samples_received); } long bytesToRead=BUFFERSIZE; - if (s->Port.FinishDataReading(&s->buffers_rx[i*BUFFERSIZE],bytesToRead,s->handles[i]) != BUFFERSIZE) { - printf("[recv] Error: request %d samples (%d/%d) WaitForReading timed out\n",nsamps,i,num_p); + if (s->Port.FinishDataReading(&s->buffers_rx[bufindex*BUFFERSIZE],bytesToRead,s->handles[bufindex]) != BUFFERSIZE) { + printf("[recv] Error: request %d samples (%d/%d) WaitForReading timed out\n",nsamps,bufindex,num_p); + *ptimestamp = s->rx_timestamp; + s->rx_timestamp+=samples_received; return(samples_received); } - p = (StreamPacket_t*)&s->buffers_rx[i*BUFFERSIZE]; + p = (StreamPacket_t*)&s->buffers_rx[bufindex*BUFFERSIZE]; // handle timestamp if ((i==0) & (ind==0)) { // grab the timestamp from HW - s->rx_timestamp = p->counter; + *ptimestamp = p->counter; + s->rx_timestamp = p->counter+nsamps; // for next time +#ifdef DEBUG_READ + printf("RX timestamp %d\n",s->rx_timestamp); +#endif } else { // check the timestamp if (i==0) { @@ -304,6 +325,8 @@ static int trx_sodera_read(openair0_device *device, openair0_timestamp *ptimesta return(ind); } } + *ptimestamp = s->rx_timestamp; + s->rx_timestamp+=nsamps; } pktStart = p->data; for (uint16_t b=0;bdata);b+=stepSize) { @@ -321,13 +344,15 @@ static int trx_sodera_read(openair0_device *device, openair0_timestamp *ptimesta ind++; } samples_received+=spp; + // schedule a new transmission for this index + s->handles[bufindex] = s->Port.BeginDataReading(&s->buffers_rx[bufindex*BUFFERSIZE],BUFFERSIZE); + s->current_handle=(s->current_handle+1)&(BUFFERSCOUNT-1); } //handle the error code s->rx_count += samples_received; // s->rx_timestamp = s->rx_md.time_spec.to_ticks(s->sample_rate); - *ptimestamp = s->rx_timestamp; return samples_received; } @@ -597,6 +622,7 @@ int openair0_dev_init_sodera(openair0_device* device, openair0_config_t *openair printf("Cannot SetInterfaceFrequency (%f,%d,%d)\n",cgen_freq_MHz,interpolation,decimation); exit(-1); } + /* // Run calibration procedure float txrx_calibrationBandwidth_MHz = 5; opStatus = s->lmsControl.CalibrateTx(txrx_calibrationBandwidth_MHz); @@ -609,7 +635,7 @@ int openair0_dev_init_sodera(openair0_device* device, openair0_config_t *openair printf("RX Calibration failed\n"); exit(-1); } - + */ s->lmsStream = new LMS_StreamBoard(&s->Port); LMS_StreamBoard::Status opStreamStatus; @@ -693,6 +719,5 @@ int openair0_dev_init_sodera(openair0_device* device, openair0_config_t *openair s->channelscount = openair0_cfg[0].rx_num_channels; // TODO: - exit(-1); return 0; } diff --git a/targets/ARCH/SODERA/lms7_trx_LTE_mimo_RF.ini b/targets/ARCH/SODERA/lms7_trx_LTE_mimo_RF.ini deleted file mode 100644 index e0e313b23e..0000000000 --- a/targets/ARCH/SODERA/lms7_trx_LTE_mimo_RF.ini +++ /dev/null @@ -1,1128 +0,0 @@ -[file_info] -type=lms7002m_minimal_config -version=1 -[lms7002_registers_a] -0x0020=0xFFFD -0x0021=0x0E9F -0x0022=0x07FF -0x0023=0x5550 -0x0024=0xE4E4 -0x0025=0x0101 -0x0026=0x0101 -0x0027=0xB1E4 -0x0028=0x0101 -0x0029=0x0101 -0x002A=0x0086 -0x002B=0x0038 -0x002C=0x0000 -0x002D=0xFFFF -0x002E=0x0000 -0x002F=0x3840 -0x0081=0x0000 -0x0082=0x8001 -0x0084=0x0400 -0x0085=0x0001 -0x0086=0x4101 -0x0087=0xB13B -0x0088=0x0303 -0x0089=0x1078 -0x008A=0x0514 -0x008B=0x2182 -0x008C=0x267B -0x0092=0x0001 -0x0093=0x0000 -0x0094=0x0000 -0x0095=0x0000 -0x0096=0x0000 -0x0097=0x0000 -0x0098=0x0000 -0x0099=0x6565 -0x009A=0x658C -0x009B=0x6565 -0x009C=0x658C -0x009D=0x6565 -0x009E=0x658C -0x009F=0x658C -0x00A0=0x6565 -0x00A1=0x6565 -0x00A2=0x6565 -0x00A3=0x6565 -0x00A4=0x6565 -0x00A5=0x6565 -0x00A6=0x0001 -0x00A7=0x6565 -0x00A8=0x0000 -0x00A9=0x8000 -0x00AA=0x0000 -0x00AB=0x0040 -0x00AC=0x2000 -0x00AD=0x03FF -0x00AE=0x0000 -0x0100=0x7409 -0x0101=0x7800 -0x0102=0x3180 -0x0103=0x0A12 -0x0104=0x0088 -0x0105=0x0007 -0x0106=0x3182 -0x0107=0x318C -0x0108=0x3042 -0x0109=0x61C1 -0x010A=0x104C -0x010C=0x8865 -0x010D=0x019D -0x010E=0x2040 -0x010F=0x3042 -0x0110=0x0BF4 -0x0111=0x0083 -0x0112=0xC0E6 -0x0113=0x03C3 -0x0114=0x008D -0x0115=0x0009 -0x0116=0x8180 -0x0117=0x280C -0x0118=0x018C -0x0119=0x18CB -0x011A=0x2E02 -0x011C=0xA941 -0x011D=0x4EC4 -0x011E=0x048C -0x011F=0x3640 -0x0120=0xB9FF -0x0121=0x3158 -0x0122=0x033F -0x0123=0x267B -0x0124=0x0000 -0x0200=0x0081 -0x0201=0x07B0 -0x0202=0x06F2 -0x0203=0x0FC2 -0x0204=0xD51F -0x0205=0x0000 -0x0206=0x0000 -0x0207=0x0000 -0x0208=0x0170 -0x0209=0x0000 -0x020A=0x0080 -0x020B=0x4000 -0x020C=0x7FFF -0x0240=0x0020 -0x0241=0x0000 -0x0242=0x0000 -0x0243=0x0000 -0x0244=0x0000 -0x0245=0x0000 -0x0246=0x0000 -0x0247=0x0000 -0x0248=0x0000 -0x0249=0x0000 -0x024A=0x0000 -0x024B=0x0000 -0x024C=0x0000 -0x024D=0x0000 -0x024E=0x0000 -0x024F=0x0000 -0x0250=0x0000 -0x0251=0x0000 -0x0252=0x0000 -0x0253=0x0000 -0x0254=0x0000 -0x0255=0x0000 -0x0256=0x0000 -0x0257=0x0000 -0x0258=0x0000 -0x0259=0x0000 -0x025A=0x0000 -0x025B=0x0000 -0x025C=0x0000 -0x025D=0x0000 -0x025E=0x0000 -0x025F=0x0000 -0x0260=0x0000 -0x0261=0x0000 -0x0280=0x0000 -0x0281=0x0000 -0x0282=0x0000 -0x0283=0x0000 -0x0284=0x0000 -0x0285=0x0000 -0x0286=0x0000 -0x0287=0x0000 -0x0288=0x0000 -0x0289=0x0000 -0x028A=0x0000 -0x028B=0x0000 -0x028C=0x0000 -0x028D=0x0000 -0x028E=0x0000 -0x028F=0x0000 -0x0290=0x0000 -0x0291=0x0000 -0x0292=0x0000 -0x0293=0x0000 -0x0294=0x0000 -0x0295=0x0000 -0x0296=0x0000 -0x0297=0x0000 -0x0298=0x0000 -0x0299=0x0000 -0x029A=0x0000 -0x029B=0x0000 -0x029C=0x0000 -0x029D=0x0000 -0x029E=0x0000 -0x029F=0x0000 -0x02A0=0x0000 -0x02A1=0x0000 -0x02A2=0x0000 -0x02A3=0x0000 -0x02A4=0x0000 -0x02A5=0x0000 -0x02A6=0x0000 -0x02A7=0x0000 -0x02C0=0x0000 -0x02C1=0x0000 -0x02C2=0x0000 -0x02C3=0x0000 -0x02C4=0x0000 -0x02C5=0x0000 -0x02C6=0x0000 -0x02C7=0x0000 -0x02C8=0x0000 -0x02C9=0x0000 -0x02CA=0x0000 -0x02CB=0x0000 -0x02CC=0x0000 -0x02CD=0x0000 -0x02CE=0x0000 -0x02CF=0x0000 -0x02D0=0x0000 -0x02D1=0x0000 -0x02D2=0x0000 -0x02D3=0x0000 -0x02D4=0x0000 -0x02D5=0x0000 -0x02D6=0x0000 -0x02D7=0x0000 -0x02D8=0x0000 -0x02D9=0x0000 -0x02DA=0x0000 -0x02DB=0x0000 -0x02DC=0x0000 -0x02DD=0x0000 -0x02DE=0x0000 -0x02DF=0x0000 -0x02E0=0x0000 -0x02E1=0x0000 -0x02E2=0x0000 -0x02E3=0x0000 -0x02E4=0x0000 -0x02E5=0x0000 -0x02E6=0x0000 -0x02E7=0x0000 -0x0300=0x0000 -0x0301=0x0000 -0x0302=0x0000 -0x0303=0x0000 -0x0304=0x0000 -0x0305=0x0000 -0x0306=0x0000 -0x0307=0x0000 -0x0308=0x0000 -0x0309=0x0000 -0x030A=0x0000 -0x030B=0x0000 -0x030C=0x0000 -0x030D=0x0000 -0x030E=0x0000 -0x030F=0x0000 -0x0310=0x0000 -0x0311=0x0000 -0x0312=0x0000 -0x0313=0x0000 -0x0314=0x0000 -0x0315=0x0000 -0x0316=0x0000 -0x0317=0x0000 -0x0318=0x0000 -0x0319=0x0000 -0x031A=0x0000 -0x031B=0x0000 -0x031C=0x0000 -0x031D=0x0000 -0x031E=0x0000 -0x031F=0x0000 -0x0320=0x0000 -0x0321=0x0000 -0x0322=0x0000 -0x0323=0x0000 -0x0324=0x0000 -0x0325=0x0000 -0x0326=0x0000 -0x0327=0x0000 -0x0340=0x0000 -0x0341=0x0000 -0x0342=0x0000 -0x0343=0x0000 -0x0344=0x0000 -0x0345=0x0000 -0x0346=0x0000 -0x0347=0x0000 -0x0348=0x0000 -0x0349=0x0000 -0x034A=0x0000 -0x034B=0x0000 -0x034C=0x0000 -0x034D=0x0000 -0x034E=0x0000 -0x034F=0x0000 -0x0350=0x0000 -0x0351=0x0000 -0x0352=0x0000 -0x0353=0x0000 -0x0354=0x0000 -0x0355=0x0000 -0x0356=0x0000 -0x0357=0x0000 -0x0358=0x0000 -0x0359=0x0000 -0x035A=0x0000 -0x035B=0x0000 -0x035C=0x0000 -0x035D=0x0000 -0x035E=0x0000 -0x035F=0x0000 -0x0360=0x0000 -0x0361=0x0000 -0x0362=0x0000 -0x0363=0x0000 -0x0364=0x0000 -0x0365=0x0000 -0x0366=0x0000 -0x0367=0x0000 -0x0380=0x0000 -0x0381=0x0000 -0x0382=0x0000 -0x0383=0x0000 -0x0384=0x0000 -0x0385=0x0000 -0x0386=0x0000 -0x0387=0x0000 -0x0388=0x0000 -0x0389=0x0000 -0x038A=0x0000 -0x038B=0x0000 -0x038C=0x0000 -0x038D=0x0000 -0x038E=0x0000 -0x038F=0x0000 -0x0390=0x0000 -0x0391=0x0000 -0x0392=0x0000 -0x0393=0x0000 -0x0394=0x0000 -0x0395=0x0000 -0x0396=0x0000 -0x0397=0x0000 -0x0398=0x0000 -0x0399=0x0000 -0x039A=0x0000 -0x039B=0x0000 -0x039C=0x0000 -0x039D=0x0000 -0x039E=0x0000 -0x039F=0x0000 -0x03A0=0x0000 -0x03A1=0x0000 -0x03A2=0x0000 -0x03A3=0x0000 -0x03A4=0x0000 -0x03A5=0x0000 -0x03A6=0x0000 -0x03A7=0x0000 -0x0400=0x0081 -0x0401=0x07FF -0x0402=0x07FF -0x0403=0x0000 -0x0404=0x0000 -0x0405=0x0000 -0x0406=0x0000 -0x0407=0x0000 -0x0408=0x0000 -0x0409=0x0000 -0x040A=0x0003 -0x040B=0x000F -0x040C=0x00FC -0x040D=0x0000 -0x040E=0x0000 -0x040F=0x0000 -0x0440=0x0020 -0x0441=0x0000 -0x0442=0x0563 -0x0443=0xB490 -0x0444=0x02B1 -0x0445=0xDA48 -0x0446=0x0000 -0x0447=0x0000 -0x0448=0x0000 -0x0449=0x0000 -0x044A=0x0000 -0x044B=0x0000 -0x044C=0x0000 -0x044D=0x0000 -0x044E=0x0000 -0x044F=0x0000 -0x0450=0x0000 -0x0451=0x0000 -0x0452=0x0000 -0x0453=0x0000 -0x0454=0x0000 -0x0455=0x0000 -0x0456=0x0000 -0x0457=0x0000 -0x0458=0x0000 -0x0459=0x0000 -0x045A=0x0000 -0x045B=0x0000 -0x045C=0x0000 -0x045D=0x0000 -0x045E=0x0000 -0x045F=0x0000 -0x0460=0x0000 -0x0461=0x0000 -0x0480=0x0000 -0x0481=0x0000 -0x0482=0x0000 -0x0483=0x0000 -0x0484=0x0000 -0x0485=0x0000 -0x0486=0x0000 -0x0487=0x0000 -0x0488=0x0000 -0x0489=0x0000 -0x048A=0x0000 -0x048B=0x0000 -0x048C=0x0000 -0x048D=0x0000 -0x048E=0x0000 -0x048F=0x0000 -0x0490=0x0000 -0x0491=0x0000 -0x0492=0x0000 -0x0493=0x0000 -0x0494=0x0000 -0x0495=0x0000 -0x0496=0x0000 -0x0497=0x0000 -0x0498=0x0000 -0x0499=0x0000 -0x049A=0x0000 -0x049B=0x0000 -0x049C=0x0000 -0x049D=0x0000 -0x049E=0x0000 -0x049F=0x0000 -0x04A0=0x0000 -0x04A1=0x0000 -0x04A2=0x0000 -0x04A3=0x0000 -0x04A4=0x0000 -0x04A5=0x0000 -0x04A6=0x0000 -0x04A7=0x0000 -0x04C0=0x0000 -0x04C1=0x0000 -0x04C2=0x0000 -0x04C3=0x0000 -0x04C4=0x0000 -0x04C5=0x0000 -0x04C6=0x0000 -0x04C7=0x0000 -0x04C8=0x0000 -0x04C9=0x0000 -0x04CA=0x0000 -0x04CB=0x0000 -0x04CC=0x0000 -0x04CD=0x0000 -0x04CE=0x0000 -0x04CF=0x0000 -0x04D0=0x0000 -0x04D1=0x0000 -0x04D2=0x0000 -0x04D3=0x0000 -0x04D4=0x0000 -0x04D5=0x0000 -0x04D6=0x0000 -0x04D7=0x0000 -0x04D8=0x0000 -0x04D9=0x0000 -0x04DA=0x0000 -0x04DB=0x0000 -0x04DC=0x0000 -0x04DD=0x0000 -0x04DE=0x0000 -0x04DF=0x0000 -0x04E0=0x0000 -0x04E1=0x0000 -0x04E2=0x0000 -0x04E3=0x0000 -0x04E4=0x0000 -0x04E5=0x0000 -0x04E6=0x0000 -0x04E7=0x0000 -0x0500=0x0000 -0x0501=0x0000 -0x0502=0x0000 -0x0503=0x0000 -0x0504=0x0000 -0x0505=0x0000 -0x0506=0x0000 -0x0507=0x0000 -0x0508=0x0000 -0x0509=0x0000 -0x050A=0x0000 -0x050B=0x0000 -0x050C=0x0000 -0x050D=0x0000 -0x050E=0x0000 -0x050F=0x0000 -0x0510=0x0000 -0x0511=0x0000 -0x0512=0x0000 -0x0513=0x0000 -0x0514=0x0000 -0x0515=0x0000 -0x0516=0x0000 -0x0517=0x0000 -0x0518=0x0000 -0x0519=0x0000 -0x051A=0x0000 -0x051B=0x0000 -0x051C=0x0000 -0x051D=0x0000 -0x051E=0x0000 -0x051F=0x0000 -0x0520=0x0000 -0x0521=0x0000 -0x0522=0x0000 -0x0523=0x0000 -0x0524=0x0000 -0x0525=0x0000 -0x0526=0x0000 -0x0527=0x0000 -0x0540=0x0000 -0x0541=0x0000 -0x0542=0x0000 -0x0543=0x0000 -0x0544=0x0000 -0x0545=0x0000 -0x0546=0x0000 -0x0547=0x0000 -0x0548=0x0000 -0x0549=0x0000 -0x054A=0x0000 -0x054B=0x0000 -0x054C=0x0000 -0x054D=0x0000 -0x054E=0x0000 -0x054F=0x0000 -0x0550=0x0000 -0x0551=0x0000 -0x0552=0x0000 -0x0553=0x0000 -0x0554=0x0000 -0x0555=0x0000 -0x0556=0x0000 -0x0557=0x0000 -0x0558=0x0000 -0x0559=0x0000 -0x055A=0x0000 -0x055B=0x0000 -0x055C=0x0000 -0x055D=0x0000 -0x055E=0x0000 -0x055F=0x0000 -0x0560=0x0000 -0x0561=0x0000 -0x0562=0x0000 -0x0563=0x0000 -0x0564=0x0000 -0x0565=0x0000 -0x0566=0x0000 -0x0567=0x0000 -0x0580=0x0000 -0x0581=0x0000 -0x0582=0x0000 -0x0583=0x0000 -0x0584=0x0000 -0x0585=0x0000 -0x0586=0x0000 -0x0587=0x0000 -0x0588=0x0000 -0x0589=0x0000 -0x058A=0x0000 -0x058B=0x0000 -0x058C=0x0000 -0x058D=0x0000 -0x058E=0x0000 -0x058F=0x0000 -0x0590=0x0000 -0x0591=0x0000 -0x0592=0x0000 -0x0593=0x0000 -0x0594=0x0000 -0x0595=0x0000 -0x0596=0x0000 -0x0597=0x0000 -0x0598=0x0000 -0x0599=0x0000 -0x059A=0x0000 -0x059B=0x0000 -0x059C=0x0000 -0x059D=0x0000 -0x059E=0x0000 -0x059F=0x0000 -0x05A0=0x0000 -0x05A1=0x0000 -0x05A2=0x0000 -0x05A3=0x0000 -0x05A4=0x0000 -0x05A5=0x0000 -0x05A6=0x0000 -0x05A7=0x0000 -[lms7002_registers_b] -0x0100=0x3409 -0x0101=0x7800 -0x0102=0x3180 -0x0103=0x0A12 -0x0104=0x0088 -0x0105=0x0007 -0x0106=0x3182 -0x0107=0x318C -0x0108=0x3042 -0x0109=0x61C1 -0x010A=0x104C -0x010C=0x8865 -0x010D=0x019C -0x010E=0x2040 -0x010F=0x3042 -0x0110=0x0BF4 -0x0111=0x0083 -0x0112=0xC0E6 -0x0113=0x03C3 -0x0114=0x008D -0x0115=0x0009 -0x0116=0x8180 -0x0117=0x280C -0x0118=0x018C -0x0119=0x18CB -0x011A=0x2E02 -0x011C=0xA941 -0x011D=0x3B13 -0x011E=0x0631 -0x011F=0x3600 -0x0120=0xB9FF -0x0121=0x31DA -0x0122=0x033F -0x0123=0x267B -0x0124=0x0000 -0x0200=0x0101 -0x0201=0x05BD -0x0202=0x0779 -0x0203=0x0F9E -0x0204=0xBCC2 -0x0205=0x0000 -0x0206=0x0000 -0x0207=0x0000 -0x0208=0x0170 -0x0209=0x0000 -0x020A=0x0080 -0x020B=0x4000 -0x020C=0x7FFF -0x0240=0x0020 -0x0241=0x0000 -0x0242=0x0000 -0x0243=0x0000 -0x0244=0x0000 -0x0245=0x0000 -0x0246=0x0000 -0x0247=0x0000 -0x0248=0x0000 -0x0249=0x0000 -0x024A=0x0000 -0x024B=0x0000 -0x024C=0x0000 -0x024D=0x0000 -0x024E=0x0000 -0x024F=0x0000 -0x0250=0x0000 -0x0251=0x0000 -0x0252=0x0000 -0x0253=0x0000 -0x0254=0x0000 -0x0255=0x0000 -0x0256=0x0000 -0x0257=0x0000 -0x0258=0x0000 -0x0259=0x0000 -0x025A=0x0000 -0x025B=0x0000 -0x025C=0x0000 -0x025D=0x0000 -0x025E=0x0000 -0x025F=0x0000 -0x0260=0x0000 -0x0261=0x0000 -0x0280=0x0000 -0x0281=0x0000 -0x0282=0x0000 -0x0283=0x0000 -0x0284=0x0000 -0x0285=0x0000 -0x0286=0x0000 -0x0287=0x0000 -0x0288=0x0000 -0x0289=0x0000 -0x028A=0x0000 -0x028B=0x0000 -0x028C=0x0000 -0x028D=0x0000 -0x028E=0x0000 -0x028F=0x0000 -0x0290=0x0000 -0x0291=0x0000 -0x0292=0x0000 -0x0293=0x0000 -0x0294=0x0000 -0x0295=0x0000 -0x0296=0x0000 -0x0297=0x0000 -0x0298=0x0000 -0x0299=0x0000 -0x029A=0x0000 -0x029B=0x0000 -0x029C=0x0000 -0x029D=0x0000 -0x029E=0x0000 -0x029F=0x0000 -0x02A0=0x0000 -0x02A1=0x0000 -0x02A2=0x0000 -0x02A3=0x0000 -0x02A4=0x0000 -0x02A5=0x0000 -0x02A6=0x0000 -0x02A7=0x0000 -0x02C0=0x0000 -0x02C1=0x0000 -0x02C2=0x0000 -0x02C3=0x0000 -0x02C4=0x0000 -0x02C5=0x0000 -0x02C6=0x0000 -0x02C7=0x0000 -0x02C8=0x0000 -0x02C9=0x0000 -0x02CA=0x0000 -0x02CB=0x0000 -0x02CC=0x0000 -0x02CD=0x0000 -0x02CE=0x0000 -0x02CF=0x0000 -0x02D0=0x0000 -0x02D1=0x0000 -0x02D2=0x0000 -0x02D3=0x0000 -0x02D4=0x0000 -0x02D5=0x0000 -0x02D6=0x0000 -0x02D7=0x0000 -0x02D8=0x0000 -0x02D9=0x0000 -0x02DA=0x0000 -0x02DB=0x0000 -0x02DC=0x0000 -0x02DD=0x0000 -0x02DE=0x0000 -0x02DF=0x0000 -0x02E0=0x0000 -0x02E1=0x0000 -0x02E2=0x0000 -0x02E3=0x0000 -0x02E4=0x0000 -0x02E5=0x0000 -0x02E6=0x0000 -0x02E7=0x0000 -0x0300=0x0000 -0x0301=0x0000 -0x0302=0x0000 -0x0303=0x0000 -0x0304=0x0000 -0x0305=0x0000 -0x0306=0x0000 -0x0307=0x0000 -0x0308=0x0000 -0x0309=0x0000 -0x030A=0x0000 -0x030B=0x0000 -0x030C=0x0000 -0x030D=0x0000 -0x030E=0x0000 -0x030F=0x0000 -0x0310=0x0000 -0x0311=0x0000 -0x0312=0x0000 -0x0313=0x0000 -0x0314=0x0000 -0x0315=0x0000 -0x0316=0x0000 -0x0317=0x0000 -0x0318=0x0000 -0x0319=0x0000 -0x031A=0x0000 -0x031B=0x0000 -0x031C=0x0000 -0x031D=0x0000 -0x031E=0x0000 -0x031F=0x0000 -0x0320=0x0000 -0x0321=0x0000 -0x0322=0x0000 -0x0323=0x0000 -0x0324=0x0000 -0x0325=0x0000 -0x0326=0x0000 -0x0327=0x0000 -0x0340=0x0000 -0x0341=0x0000 -0x0342=0x0000 -0x0343=0x0000 -0x0344=0x0000 -0x0345=0x0000 -0x0346=0x0000 -0x0347=0x0000 -0x0348=0x0000 -0x0349=0x0000 -0x034A=0x0000 -0x034B=0x0000 -0x034C=0x0000 -0x034D=0x0000 -0x034E=0x0000 -0x034F=0x0000 -0x0350=0x0000 -0x0351=0x0000 -0x0352=0x0000 -0x0353=0x0000 -0x0354=0x0000 -0x0355=0x0000 -0x0356=0x0000 -0x0357=0x0000 -0x0358=0x0000 -0x0359=0x0000 -0x035A=0x0000 -0x035B=0x0000 -0x035C=0x0000 -0x035D=0x0000 -0x035E=0x0000 -0x035F=0x0000 -0x0360=0x0000 -0x0361=0x0000 -0x0362=0x0000 -0x0363=0x0000 -0x0364=0x0000 -0x0365=0x0000 -0x0366=0x0000 -0x0367=0x0000 -0x0380=0x0000 -0x0381=0x0000 -0x0382=0x0000 -0x0383=0x0000 -0x0384=0x0000 -0x0385=0x0000 -0x0386=0x0000 -0x0387=0x0000 -0x0388=0x0000 -0x0389=0x0000 -0x038A=0x0000 -0x038B=0x0000 -0x038C=0x0000 -0x038D=0x0000 -0x038E=0x0000 -0x038F=0x0000 -0x0390=0x0000 -0x0391=0x0000 -0x0392=0x0000 -0x0393=0x0000 -0x0394=0x0000 -0x0395=0x0000 -0x0396=0x0000 -0x0397=0x0000 -0x0398=0x0000 -0x0399=0x0000 -0x039A=0x0000 -0x039B=0x0000 -0x039C=0x0000 -0x039D=0x0000 -0x039E=0x0000 -0x039F=0x0000 -0x03A0=0x0000 -0x03A1=0x0000 -0x03A2=0x0000 -0x03A3=0x0000 -0x03A4=0x0000 -0x03A5=0x0000 -0x03A6=0x0000 -0x03A7=0x0000 -0x0400=0x0101 -0x0401=0x07FF -0x0402=0x079B -0x0403=0x0FF5 -0x0404=0x0000 -0x0405=0x0000 -0x0406=0x0000 -0x0407=0x0000 -0x0408=0x0000 -0x0409=0x0000 -0x040A=0x0000 -0x040B=0x7FFF -0x040C=0x00FC -0x040D=0x0000 -0x040E=0x0000 -0x040F=0x0000 -0x0440=0x0020 -0x0441=0x0000 -0x0442=0x0000 -0x0443=0x0000 -0x0444=0x0000 -0x0445=0x0000 -0x0446=0x0000 -0x0447=0x0000 -0x0448=0x0000 -0x0449=0x0000 -0x044A=0x0000 -0x044B=0x0000 -0x044C=0x0000 -0x044D=0x0000 -0x044E=0x0000 -0x044F=0x0000 -0x0450=0x0000 -0x0451=0x0000 -0x0452=0x0000 -0x0453=0x0000 -0x0454=0x0000 -0x0455=0x0000 -0x0456=0x0000 -0x0457=0x0000 -0x0458=0x0000 -0x0459=0x0000 -0x045A=0x0000 -0x045B=0x0000 -0x045C=0x0000 -0x045D=0x0000 -0x045E=0x0000 -0x045F=0x0000 -0x0460=0x0000 -0x0461=0x0000 -0x0480=0x0000 -0x0481=0x0000 -0x0482=0x0000 -0x0483=0x0000 -0x0484=0x0000 -0x0485=0x0000 -0x0486=0x0000 -0x0487=0x0000 -0x0488=0x0000 -0x0489=0x0000 -0x048A=0x0000 -0x048B=0x0000 -0x048C=0x0000 -0x048D=0x0000 -0x048E=0x0000 -0x048F=0x0000 -0x0490=0x0000 -0x0491=0x0000 -0x0492=0x0000 -0x0493=0x0000 -0x0494=0x0000 -0x0495=0x0000 -0x0496=0x0000 -0x0497=0x0000 -0x0498=0x0000 -0x0499=0x0000 -0x049A=0x0000 -0x049B=0x0000 -0x049C=0x0000 -0x049D=0x0000 -0x049E=0x0000 -0x049F=0x0000 -0x04A0=0x0000 -0x04A1=0x0000 -0x04A2=0x0000 -0x04A3=0x0000 -0x04A4=0x0000 -0x04A5=0x0000 -0x04A6=0x0000 -0x04A7=0x0000 -0x04C0=0x0000 -0x04C1=0x0000 -0x04C2=0x0000 -0x04C3=0x0000 -0x04C4=0x0000 -0x04C5=0x0000 -0x04C6=0x0000 -0x04C7=0x0000 -0x04C8=0x0000 -0x04C9=0x0000 -0x04CA=0x0000 -0x04CB=0x0000 -0x04CC=0x0000 -0x04CD=0x0000 -0x04CE=0x0000 -0x04CF=0x0000 -0x04D0=0x0000 -0x04D1=0x0000 -0x04D2=0x0000 -0x04D3=0x0000 -0x04D4=0x0000 -0x04D5=0x0000 -0x04D6=0x0000 -0x04D7=0x0000 -0x04D8=0x0000 -0x04D9=0x0000 -0x04DA=0x0000 -0x04DB=0x0000 -0x04DC=0x0000 -0x04DD=0x0000 -0x04DE=0x0000 -0x04DF=0x0000 -0x04E0=0x0000 -0x04E1=0x0000 -0x04E2=0x0000 -0x04E3=0x0000 -0x04E4=0x0000 -0x04E5=0x0000 -0x04E6=0x0000 -0x04E7=0x0000 -0x0500=0x0000 -0x0501=0x0000 -0x0502=0x0000 -0x0503=0x0000 -0x0504=0x0000 -0x0505=0x0000 -0x0506=0x0000 -0x0507=0x0000 -0x0508=0x0000 -0x0509=0x0000 -0x050A=0x0000 -0x050B=0x0000 -0x050C=0x0000 -0x050D=0x0000 -0x050E=0x0000 -0x050F=0x0000 -0x0510=0x0000 -0x0511=0x0000 -0x0512=0x0000 -0x0513=0x0000 -0x0514=0x0000 -0x0515=0x0000 -0x0516=0x0000 -0x0517=0x0000 -0x0518=0x0000 -0x0519=0x0000 -0x051A=0x0000 -0x051B=0x0000 -0x051C=0x0000 -0x051D=0x0000 -0x051E=0x0000 -0x051F=0x0000 -0x0520=0x0000 -0x0521=0x0000 -0x0522=0x0000 -0x0523=0x0000 -0x0524=0x0000 -0x0525=0x0000 -0x0526=0x0000 -0x0527=0x0000 -0x0540=0x0000 -0x0541=0x0000 -0x0542=0x0000 -0x0543=0x0000 -0x0544=0x0000 -0x0545=0x0000 -0x0546=0x0000 -0x0547=0x0000 -0x0548=0x0000 -0x0549=0x0000 -0x054A=0x0000 -0x054B=0x0000 -0x054C=0x0000 -0x054D=0x0000 -0x054E=0x0000 -0x054F=0x0000 -0x0550=0x0000 -0x0551=0x0000 -0x0552=0x0000 -0x0553=0x0000 -0x0554=0x0000 -0x0555=0x0000 -0x0556=0x0000 -0x0557=0x0000 -0x0558=0x0000 -0x0559=0x0000 -0x055A=0x0000 -0x055B=0x0000 -0x055C=0x0000 -0x055D=0x0000 -0x055E=0x0000 -0x055F=0x0000 -0x0560=0x0000 -0x0561=0x0000 -0x0562=0x0000 -0x0563=0x0000 -0x0564=0x0000 -0x0565=0x0000 -0x0566=0x0000 -0x0567=0x0000 -0x0580=0x0000 -0x0581=0x0000 -0x0582=0x0000 -0x0583=0x0000 -0x0584=0x0000 -0x0585=0x0000 -0x0586=0x0000 -0x0587=0x0000 -0x0588=0x0000 -0x0589=0x0000 -0x058A=0x0000 -0x058B=0x0000 -0x058C=0x0000 -0x058D=0x0000 -0x058E=0x0000 -0x058F=0x0000 -0x0590=0x0000 -0x0591=0x0000 -0x0592=0x0000 -0x0593=0x0000 -0x0594=0x0000 -0x0595=0x0000 -0x0596=0x0000 -0x0597=0x0000 -0x0598=0x0000 -0x0599=0x0000 -0x059A=0x0000 -0x059B=0x0000 -0x059C=0x0000 -0x059D=0x0000 -0x059E=0x0000 -0x059F=0x0000 -0x05A0=0x0000 -0x05A1=0x0000 -0x05A2=0x0000 -0x05A3=0x0000 -0x05A4=0x0000 -0x05A5=0x0000 -0x05A6=0x0000 -0x05A7=0x0000 -[reference_clocks] -sxr_ref_clk_mhz=52 -sxt_ref_clk_mhz=52 diff --git a/targets/ARCH/SODERA/lms7_trx_LTE_mimo_TSG.ini b/targets/ARCH/SODERA/lms7_trx_LTE_mimo_TSG.ini deleted file mode 100644 index fb25b06527..0000000000 --- a/targets/ARCH/SODERA/lms7_trx_LTE_mimo_TSG.ini +++ /dev/null @@ -1,1128 +0,0 @@ -[file_info] -type=lms7002m_minimal_config -version=1 -[lms7002_registers_a] -0x0020=0xFFFD -0x0021=0x0E9F -0x0022=0x07FF -0x0023=0x5550 -0x0024=0xE4E4 -0x0025=0x0101 -0x0026=0x0101 -0x0027=0xE4E4 -0x0028=0x0101 -0x0029=0x0101 -0x002A=0x0086 -0x002B=0x0038 -0x002C=0x0000 -0x002D=0xFFFF -0x002E=0x0000 -0x002F=0x3840 -0x0081=0x0000 -0x0082=0x8001 -0x0084=0x0400 -0x0085=0x0001 -0x0086=0x4101 -0x0087=0xB13B -0x0088=0x0303 -0x0089=0x1078 -0x008A=0x0514 -0x008B=0x2184 -0x008C=0x267B -0x0092=0x0001 -0x0093=0x0000 -0x0094=0x0000 -0x0095=0x0000 -0x0096=0x0000 -0x0097=0x0000 -0x0098=0x0000 -0x0099=0x6565 -0x009A=0x658C -0x009B=0x6565 -0x009C=0x658C -0x009D=0x6565 -0x009E=0x658C -0x009F=0x658C -0x00A0=0x6565 -0x00A1=0x6565 -0x00A2=0x6565 -0x00A3=0x6565 -0x00A4=0x6565 -0x00A5=0x6565 -0x00A6=0x0001 -0x00A7=0x6565 -0x00A8=0x0000 -0x00A9=0x8000 -0x00AA=0x0000 -0x00AB=0x0040 -0x00AC=0x2000 -0x00AD=0x03FF -0x00AE=0x0000 -0x0100=0x7409 -0x0101=0x7800 -0x0102=0x3180 -0x0103=0x0A12 -0x0104=0x0088 -0x0105=0x0007 -0x0106=0x3182 -0x0107=0x318C -0x0108=0x9442 -0x0109=0x61C1 -0x010A=0x104C -0x010C=0x8865 -0x010D=0x011A -0x010E=0x2040 -0x010F=0x3042 -0x0110=0x0BF4 -0x0111=0x0083 -0x0112=0xC0E6 -0x0113=0x03C3 -0x0114=0x008D -0x0115=0x0009 -0x0116=0x8180 -0x0117=0x280C -0x0118=0x018C -0x0119=0x18CB -0x011A=0x2E02 -0x011C=0xAD41 -0x011D=0x9D89 -0x011E=0x0398 -0x011F=0x3680 -0x0120=0xB9FF -0x0121=0x3692 -0x0122=0x033F -0x0123=0x267B -0x0124=0x0000 -0x0200=0x0081 -0x0201=0x07B0 -0x0202=0x06F2 -0x0203=0x0FC2 -0x0204=0xD51F -0x0205=0x0000 -0x0206=0x0000 -0x0207=0x0000 -0x0208=0x0070 -0x0209=0x0000 -0x020A=0x0080 -0x020B=0x4000 -0x020C=0x7FFF -0x0240=0x0020 -0x0241=0x0000 -0x0242=0x0000 -0x0243=0x0000 -0x0244=0x0000 -0x0245=0x0000 -0x0246=0x0000 -0x0247=0x0000 -0x0248=0x0000 -0x0249=0x0000 -0x024A=0x0000 -0x024B=0x0000 -0x024C=0x0000 -0x024D=0x0000 -0x024E=0x0000 -0x024F=0x0000 -0x0250=0x0000 -0x0251=0x0000 -0x0252=0x0000 -0x0253=0x0000 -0x0254=0x0000 -0x0255=0x0000 -0x0256=0x0000 -0x0257=0x0000 -0x0258=0x0000 -0x0259=0x0000 -0x025A=0x0000 -0x025B=0x0000 -0x025C=0x0000 -0x025D=0x0000 -0x025E=0x0000 -0x025F=0x0000 -0x0260=0x0000 -0x0261=0x0000 -0x0280=0x0000 -0x0281=0x0000 -0x0282=0x0000 -0x0283=0x0000 -0x0284=0x0000 -0x0285=0x0000 -0x0286=0x0000 -0x0287=0x0000 -0x0288=0x0000 -0x0289=0x0000 -0x028A=0x0000 -0x028B=0x0000 -0x028C=0x0000 -0x028D=0x0000 -0x028E=0x0000 -0x028F=0x0000 -0x0290=0x0000 -0x0291=0x0000 -0x0292=0x0000 -0x0293=0x0000 -0x0294=0x0000 -0x0295=0x0000 -0x0296=0x0000 -0x0297=0x0000 -0x0298=0x0000 -0x0299=0x0000 -0x029A=0x0000 -0x029B=0x0000 -0x029C=0x0000 -0x029D=0x0000 -0x029E=0x0000 -0x029F=0x0000 -0x02A0=0x0000 -0x02A1=0x0000 -0x02A2=0x0000 -0x02A3=0x0000 -0x02A4=0x0000 -0x02A5=0x0000 -0x02A6=0x0000 -0x02A7=0x0000 -0x02C0=0x0000 -0x02C1=0x0000 -0x02C2=0x0000 -0x02C3=0x0000 -0x02C4=0x0000 -0x02C5=0x0000 -0x02C6=0x0000 -0x02C7=0x0000 -0x02C8=0x0000 -0x02C9=0x0000 -0x02CA=0x0000 -0x02CB=0x0000 -0x02CC=0x0000 -0x02CD=0x0000 -0x02CE=0x0000 -0x02CF=0x0000 -0x02D0=0x0000 -0x02D1=0x0000 -0x02D2=0x0000 -0x02D3=0x0000 -0x02D4=0x0000 -0x02D5=0x0000 -0x02D6=0x0000 -0x02D7=0x0000 -0x02D8=0x0000 -0x02D9=0x0000 -0x02DA=0x0000 -0x02DB=0x0000 -0x02DC=0x0000 -0x02DD=0x0000 -0x02DE=0x0000 -0x02DF=0x0000 -0x02E0=0x0000 -0x02E1=0x0000 -0x02E2=0x0000 -0x02E3=0x0000 -0x02E4=0x0000 -0x02E5=0x0000 -0x02E6=0x0000 -0x02E7=0x0000 -0x0300=0x0000 -0x0301=0x0000 -0x0302=0x0000 -0x0303=0x0000 -0x0304=0x0000 -0x0305=0x0000 -0x0306=0x0000 -0x0307=0x0000 -0x0308=0x0000 -0x0309=0x0000 -0x030A=0x0000 -0x030B=0x0000 -0x030C=0x0000 -0x030D=0x0000 -0x030E=0x0000 -0x030F=0x0000 -0x0310=0x0000 -0x0311=0x0000 -0x0312=0x0000 -0x0313=0x0000 -0x0314=0x0000 -0x0315=0x0000 -0x0316=0x0000 -0x0317=0x0000 -0x0318=0x0000 -0x0319=0x0000 -0x031A=0x0000 -0x031B=0x0000 -0x031C=0x0000 -0x031D=0x0000 -0x031E=0x0000 -0x031F=0x0000 -0x0320=0x0000 -0x0321=0x0000 -0x0322=0x0000 -0x0323=0x0000 -0x0324=0x0000 -0x0325=0x0000 -0x0326=0x0000 -0x0327=0x0000 -0x0340=0x0000 -0x0341=0x0000 -0x0342=0x0000 -0x0343=0x0000 -0x0344=0x0000 -0x0345=0x0000 -0x0346=0x0000 -0x0347=0x0000 -0x0348=0x0000 -0x0349=0x0000 -0x034A=0x0000 -0x034B=0x0000 -0x034C=0x0000 -0x034D=0x0000 -0x034E=0x0000 -0x034F=0x0000 -0x0350=0x0000 -0x0351=0x0000 -0x0352=0x0000 -0x0353=0x0000 -0x0354=0x0000 -0x0355=0x0000 -0x0356=0x0000 -0x0357=0x0000 -0x0358=0x0000 -0x0359=0x0000 -0x035A=0x0000 -0x035B=0x0000 -0x035C=0x0000 -0x035D=0x0000 -0x035E=0x0000 -0x035F=0x0000 -0x0360=0x0000 -0x0361=0x0000 -0x0362=0x0000 -0x0363=0x0000 -0x0364=0x0000 -0x0365=0x0000 -0x0366=0x0000 -0x0367=0x0000 -0x0380=0x0000 -0x0381=0x0000 -0x0382=0x0000 -0x0383=0x0000 -0x0384=0x0000 -0x0385=0x0000 -0x0386=0x0000 -0x0387=0x0000 -0x0388=0x0000 -0x0389=0x0000 -0x038A=0x0000 -0x038B=0x0000 -0x038C=0x0000 -0x038D=0x0000 -0x038E=0x0000 -0x038F=0x0000 -0x0390=0x0000 -0x0391=0x0000 -0x0392=0x0000 -0x0393=0x0000 -0x0394=0x0000 -0x0395=0x0000 -0x0396=0x0000 -0x0397=0x0000 -0x0398=0x0000 -0x0399=0x0000 -0x039A=0x0000 -0x039B=0x0000 -0x039C=0x0000 -0x039D=0x0000 -0x039E=0x0000 -0x039F=0x0000 -0x03A0=0x0000 -0x03A1=0x0000 -0x03A2=0x0000 -0x03A3=0x0000 -0x03A4=0x0000 -0x03A5=0x0000 -0x03A6=0x0000 -0x03A7=0x0000 -0x0400=0x0085 -0x0401=0x07FF -0x0402=0x07FF -0x0403=0x0000 -0x0404=0x0000 -0x0405=0x0000 -0x0406=0x0000 -0x0407=0x0000 -0x0408=0x0000 -0x0409=0x0000 -0x040A=0x0003 -0x040B=0x000F -0x040C=0x00FC -0x040D=0x0000 -0x040E=0x0000 -0x040F=0x0000 -0x0440=0x0020 -0x0441=0x0000 -0x0442=0x0563 -0x0443=0xB490 -0x0444=0x02B1 -0x0445=0xDA48 -0x0446=0x0000 -0x0447=0x0000 -0x0448=0x0000 -0x0449=0x0000 -0x044A=0x0000 -0x044B=0x0000 -0x044C=0x0000 -0x044D=0x0000 -0x044E=0x0000 -0x044F=0x0000 -0x0450=0x0000 -0x0451=0x0000 -0x0452=0x0000 -0x0453=0x0000 -0x0454=0x0000 -0x0455=0x0000 -0x0456=0x0000 -0x0457=0x0000 -0x0458=0x0000 -0x0459=0x0000 -0x045A=0x0000 -0x045B=0x0000 -0x045C=0x0000 -0x045D=0x0000 -0x045E=0x0000 -0x045F=0x0000 -0x0460=0x0000 -0x0461=0x0000 -0x0480=0x0000 -0x0481=0x0000 -0x0482=0x0000 -0x0483=0x0000 -0x0484=0x0000 -0x0485=0x0000 -0x0486=0x0000 -0x0487=0x0000 -0x0488=0x0000 -0x0489=0x0000 -0x048A=0x0000 -0x048B=0x0000 -0x048C=0x0000 -0x048D=0x0000 -0x048E=0x0000 -0x048F=0x0000 -0x0490=0x0000 -0x0491=0x0000 -0x0492=0x0000 -0x0493=0x0000 -0x0494=0x0000 -0x0495=0x0000 -0x0496=0x0000 -0x0497=0x0000 -0x0498=0x0000 -0x0499=0x0000 -0x049A=0x0000 -0x049B=0x0000 -0x049C=0x0000 -0x049D=0x0000 -0x049E=0x0000 -0x049F=0x0000 -0x04A0=0x0000 -0x04A1=0x0000 -0x04A2=0x0000 -0x04A3=0x0000 -0x04A4=0x0000 -0x04A5=0x0000 -0x04A6=0x0000 -0x04A7=0x0000 -0x04C0=0x0000 -0x04C1=0x0000 -0x04C2=0x0000 -0x04C3=0x0000 -0x04C4=0x0000 -0x04C5=0x0000 -0x04C6=0x0000 -0x04C7=0x0000 -0x04C8=0x0000 -0x04C9=0x0000 -0x04CA=0x0000 -0x04CB=0x0000 -0x04CC=0x0000 -0x04CD=0x0000 -0x04CE=0x0000 -0x04CF=0x0000 -0x04D0=0x0000 -0x04D1=0x0000 -0x04D2=0x0000 -0x04D3=0x0000 -0x04D4=0x0000 -0x04D5=0x0000 -0x04D6=0x0000 -0x04D7=0x0000 -0x04D8=0x0000 -0x04D9=0x0000 -0x04DA=0x0000 -0x04DB=0x0000 -0x04DC=0x0000 -0x04DD=0x0000 -0x04DE=0x0000 -0x04DF=0x0000 -0x04E0=0x0000 -0x04E1=0x0000 -0x04E2=0x0000 -0x04E3=0x0000 -0x04E4=0x0000 -0x04E5=0x0000 -0x04E6=0x0000 -0x04E7=0x0000 -0x0500=0x0000 -0x0501=0x0000 -0x0502=0x0000 -0x0503=0x0000 -0x0504=0x0000 -0x0505=0x0000 -0x0506=0x0000 -0x0507=0x0000 -0x0508=0x0000 -0x0509=0x0000 -0x050A=0x0000 -0x050B=0x0000 -0x050C=0x0000 -0x050D=0x0000 -0x050E=0x0000 -0x050F=0x0000 -0x0510=0x0000 -0x0511=0x0000 -0x0512=0x0000 -0x0513=0x0000 -0x0514=0x0000 -0x0515=0x0000 -0x0516=0x0000 -0x0517=0x0000 -0x0518=0x0000 -0x0519=0x0000 -0x051A=0x0000 -0x051B=0x0000 -0x051C=0x0000 -0x051D=0x0000 -0x051E=0x0000 -0x051F=0x0000 -0x0520=0x0000 -0x0521=0x0000 -0x0522=0x0000 -0x0523=0x0000 -0x0524=0x0000 -0x0525=0x0000 -0x0526=0x0000 -0x0527=0x0000 -0x0540=0x0000 -0x0541=0x0000 -0x0542=0x0000 -0x0543=0x0000 -0x0544=0x0000 -0x0545=0x0000 -0x0546=0x0000 -0x0547=0x0000 -0x0548=0x0000 -0x0549=0x0000 -0x054A=0x0000 -0x054B=0x0000 -0x054C=0x0000 -0x054D=0x0000 -0x054E=0x0000 -0x054F=0x0000 -0x0550=0x0000 -0x0551=0x0000 -0x0552=0x0000 -0x0553=0x0000 -0x0554=0x0000 -0x0555=0x0000 -0x0556=0x0000 -0x0557=0x0000 -0x0558=0x0000 -0x0559=0x0000 -0x055A=0x0000 -0x055B=0x0000 -0x055C=0x0000 -0x055D=0x0000 -0x055E=0x0000 -0x055F=0x0000 -0x0560=0x0000 -0x0561=0x0000 -0x0562=0x0000 -0x0563=0x0000 -0x0564=0x0000 -0x0565=0x0000 -0x0566=0x0000 -0x0567=0x0000 -0x0580=0x0000 -0x0581=0x0000 -0x0582=0x0000 -0x0583=0x0000 -0x0584=0x0000 -0x0585=0x0000 -0x0586=0x0000 -0x0587=0x0000 -0x0588=0x0000 -0x0589=0x0000 -0x058A=0x0000 -0x058B=0x0000 -0x058C=0x0000 -0x058D=0x0000 -0x058E=0x0000 -0x058F=0x0000 -0x0590=0x0000 -0x0591=0x0000 -0x0592=0x0000 -0x0593=0x0000 -0x0594=0x0000 -0x0595=0x0000 -0x0596=0x0000 -0x0597=0x0000 -0x0598=0x0000 -0x0599=0x0000 -0x059A=0x0000 -0x059B=0x0000 -0x059C=0x0000 -0x059D=0x0000 -0x059E=0x0000 -0x059F=0x0000 -0x05A0=0x0000 -0x05A1=0x0000 -0x05A2=0x0000 -0x05A3=0x0000 -0x05A4=0x0000 -0x05A5=0x0000 -0x05A6=0x0000 -0x05A7=0x0000 -[lms7002_registers_b] -0x0100=0x3409 -0x0101=0x7800 -0x0102=0x3180 -0x0103=0x0A12 -0x0104=0x0088 -0x0105=0x0007 -0x0106=0x3182 -0x0107=0x318C -0x0108=0x9442 -0x0109=0x61C1 -0x010A=0x104C -0x010C=0x88FD -0x010D=0x009E -0x010E=0x2040 -0x010F=0x3042 -0x0110=0x0BF4 -0x0111=0x0083 -0x0112=0xC0E6 -0x0113=0x03C3 -0x0114=0x008D -0x0115=0x0009 -0x0116=0x8180 -0x0117=0x280C -0x0118=0x018C -0x0119=0x18CB -0x011A=0x2E02 -0x011C=0xA941 -0x011D=0xEC4E -0x011E=0x04E4 -0x011F=0x3600 -0x0120=0xB9FF -0x0121=0x3348 -0x0122=0x033F -0x0123=0x267B -0x0124=0x0000 -0x0200=0x0101 -0x0201=0x05BD -0x0202=0x0779 -0x0203=0x0F9E -0x0204=0xBCC2 -0x0205=0x0000 -0x0206=0x0000 -0x0207=0x0000 -0x0208=0x0070 -0x0209=0x0000 -0x020A=0x0080 -0x020B=0x4000 -0x020C=0x7FFF -0x0240=0x0020 -0x0241=0x0000 -0x0242=0x0000 -0x0243=0x0000 -0x0244=0x0000 -0x0245=0x0000 -0x0246=0x0000 -0x0247=0x0000 -0x0248=0x0000 -0x0249=0x0000 -0x024A=0x0000 -0x024B=0x0000 -0x024C=0x0000 -0x024D=0x0000 -0x024E=0x0000 -0x024F=0x0000 -0x0250=0x0000 -0x0251=0x0000 -0x0252=0x0000 -0x0253=0x0000 -0x0254=0x0000 -0x0255=0x0000 -0x0256=0x0000 -0x0257=0x0000 -0x0258=0x0000 -0x0259=0x0000 -0x025A=0x0000 -0x025B=0x0000 -0x025C=0x0000 -0x025D=0x0000 -0x025E=0x0000 -0x025F=0x0000 -0x0260=0x0000 -0x0261=0x0000 -0x0280=0x0000 -0x0281=0x0000 -0x0282=0x0000 -0x0283=0x0000 -0x0284=0x0000 -0x0285=0x0000 -0x0286=0x0000 -0x0287=0x0000 -0x0288=0x0000 -0x0289=0x0000 -0x028A=0x0000 -0x028B=0x0000 -0x028C=0x0000 -0x028D=0x0000 -0x028E=0x0000 -0x028F=0x0000 -0x0290=0x0000 -0x0291=0x0000 -0x0292=0x0000 -0x0293=0x0000 -0x0294=0x0000 -0x0295=0x0000 -0x0296=0x0000 -0x0297=0x0000 -0x0298=0x0000 -0x0299=0x0000 -0x029A=0x0000 -0x029B=0x0000 -0x029C=0x0000 -0x029D=0x0000 -0x029E=0x0000 -0x029F=0x0000 -0x02A0=0x0000 -0x02A1=0x0000 -0x02A2=0x0000 -0x02A3=0x0000 -0x02A4=0x0000 -0x02A5=0x0000 -0x02A6=0x0000 -0x02A7=0x0000 -0x02C0=0x0000 -0x02C1=0x0000 -0x02C2=0x0000 -0x02C3=0x0000 -0x02C4=0x0000 -0x02C5=0x0000 -0x02C6=0x0000 -0x02C7=0x0000 -0x02C8=0x0000 -0x02C9=0x0000 -0x02CA=0x0000 -0x02CB=0x0000 -0x02CC=0x0000 -0x02CD=0x0000 -0x02CE=0x0000 -0x02CF=0x0000 -0x02D0=0x0000 -0x02D1=0x0000 -0x02D2=0x0000 -0x02D3=0x0000 -0x02D4=0x0000 -0x02D5=0x0000 -0x02D6=0x0000 -0x02D7=0x0000 -0x02D8=0x0000 -0x02D9=0x0000 -0x02DA=0x0000 -0x02DB=0x0000 -0x02DC=0x0000 -0x02DD=0x0000 -0x02DE=0x0000 -0x02DF=0x0000 -0x02E0=0x0000 -0x02E1=0x0000 -0x02E2=0x0000 -0x02E3=0x0000 -0x02E4=0x0000 -0x02E5=0x0000 -0x02E6=0x0000 -0x02E7=0x0000 -0x0300=0x0000 -0x0301=0x0000 -0x0302=0x0000 -0x0303=0x0000 -0x0304=0x0000 -0x0305=0x0000 -0x0306=0x0000 -0x0307=0x0000 -0x0308=0x0000 -0x0309=0x0000 -0x030A=0x0000 -0x030B=0x0000 -0x030C=0x0000 -0x030D=0x0000 -0x030E=0x0000 -0x030F=0x0000 -0x0310=0x0000 -0x0311=0x0000 -0x0312=0x0000 -0x0313=0x0000 -0x0314=0x0000 -0x0315=0x0000 -0x0316=0x0000 -0x0317=0x0000 -0x0318=0x0000 -0x0319=0x0000 -0x031A=0x0000 -0x031B=0x0000 -0x031C=0x0000 -0x031D=0x0000 -0x031E=0x0000 -0x031F=0x0000 -0x0320=0x0000 -0x0321=0x0000 -0x0322=0x0000 -0x0323=0x0000 -0x0324=0x0000 -0x0325=0x0000 -0x0326=0x0000 -0x0327=0x0000 -0x0340=0x0000 -0x0341=0x0000 -0x0342=0x0000 -0x0343=0x0000 -0x0344=0x0000 -0x0345=0x0000 -0x0346=0x0000 -0x0347=0x0000 -0x0348=0x0000 -0x0349=0x0000 -0x034A=0x0000 -0x034B=0x0000 -0x034C=0x0000 -0x034D=0x0000 -0x034E=0x0000 -0x034F=0x0000 -0x0350=0x0000 -0x0351=0x0000 -0x0352=0x0000 -0x0353=0x0000 -0x0354=0x0000 -0x0355=0x0000 -0x0356=0x0000 -0x0357=0x0000 -0x0358=0x0000 -0x0359=0x0000 -0x035A=0x0000 -0x035B=0x0000 -0x035C=0x0000 -0x035D=0x0000 -0x035E=0x0000 -0x035F=0x0000 -0x0360=0x0000 -0x0361=0x0000 -0x0362=0x0000 -0x0363=0x0000 -0x0364=0x0000 -0x0365=0x0000 -0x0366=0x0000 -0x0367=0x0000 -0x0380=0x0000 -0x0381=0x0000 -0x0382=0x0000 -0x0383=0x0000 -0x0384=0x0000 -0x0385=0x0000 -0x0386=0x0000 -0x0387=0x0000 -0x0388=0x0000 -0x0389=0x0000 -0x038A=0x0000 -0x038B=0x0000 -0x038C=0x0000 -0x038D=0x0000 -0x038E=0x0000 -0x038F=0x0000 -0x0390=0x0000 -0x0391=0x0000 -0x0392=0x0000 -0x0393=0x0000 -0x0394=0x0000 -0x0395=0x0000 -0x0396=0x0000 -0x0397=0x0000 -0x0398=0x0000 -0x0399=0x0000 -0x039A=0x0000 -0x039B=0x0000 -0x039C=0x0000 -0x039D=0x0000 -0x039E=0x0000 -0x039F=0x0000 -0x03A0=0x0000 -0x03A1=0x0000 -0x03A2=0x0000 -0x03A3=0x0000 -0x03A4=0x0000 -0x03A5=0x0000 -0x03A6=0x0000 -0x03A7=0x0000 -0x0400=0x0105 -0x0401=0x07FF -0x0402=0x079B -0x0403=0x0FF5 -0x0404=0x0000 -0x0405=0x0000 -0x0406=0x0000 -0x0407=0x0000 -0x0408=0x0000 -0x0409=0x0000 -0x040A=0x0000 -0x040B=0x7FFF -0x040C=0x00FC -0x040D=0x0000 -0x040E=0x0000 -0x040F=0x0000 -0x0440=0x0020 -0x0441=0x0000 -0x0442=0x0000 -0x0443=0x0000 -0x0444=0x0000 -0x0445=0x0000 -0x0446=0x0000 -0x0447=0x0000 -0x0448=0x0000 -0x0449=0x0000 -0x044A=0x0000 -0x044B=0x0000 -0x044C=0x0000 -0x044D=0x0000 -0x044E=0x0000 -0x044F=0x0000 -0x0450=0x0000 -0x0451=0x0000 -0x0452=0x0000 -0x0453=0x0000 -0x0454=0x0000 -0x0455=0x0000 -0x0456=0x0000 -0x0457=0x0000 -0x0458=0x0000 -0x0459=0x0000 -0x045A=0x0000 -0x045B=0x0000 -0x045C=0x0000 -0x045D=0x0000 -0x045E=0x0000 -0x045F=0x0000 -0x0460=0x0000 -0x0461=0x0000 -0x0480=0x0000 -0x0481=0x0000 -0x0482=0x0000 -0x0483=0x0000 -0x0484=0x0000 -0x0485=0x0000 -0x0486=0x0000 -0x0487=0x0000 -0x0488=0x0000 -0x0489=0x0000 -0x048A=0x0000 -0x048B=0x0000 -0x048C=0x0000 -0x048D=0x0000 -0x048E=0x0000 -0x048F=0x0000 -0x0490=0x0000 -0x0491=0x0000 -0x0492=0x0000 -0x0493=0x0000 -0x0494=0x0000 -0x0495=0x0000 -0x0496=0x0000 -0x0497=0x0000 -0x0498=0x0000 -0x0499=0x0000 -0x049A=0x0000 -0x049B=0x0000 -0x049C=0x0000 -0x049D=0x0000 -0x049E=0x0000 -0x049F=0x0000 -0x04A0=0x0000 -0x04A1=0x0000 -0x04A2=0x0000 -0x04A3=0x0000 -0x04A4=0x0000 -0x04A5=0x0000 -0x04A6=0x0000 -0x04A7=0x0000 -0x04C0=0x0000 -0x04C1=0x0000 -0x04C2=0x0000 -0x04C3=0x0000 -0x04C4=0x0000 -0x04C5=0x0000 -0x04C6=0x0000 -0x04C7=0x0000 -0x04C8=0x0000 -0x04C9=0x0000 -0x04CA=0x0000 -0x04CB=0x0000 -0x04CC=0x0000 -0x04CD=0x0000 -0x04CE=0x0000 -0x04CF=0x0000 -0x04D0=0x0000 -0x04D1=0x0000 -0x04D2=0x0000 -0x04D3=0x0000 -0x04D4=0x0000 -0x04D5=0x0000 -0x04D6=0x0000 -0x04D7=0x0000 -0x04D8=0x0000 -0x04D9=0x0000 -0x04DA=0x0000 -0x04DB=0x0000 -0x04DC=0x0000 -0x04DD=0x0000 -0x04DE=0x0000 -0x04DF=0x0000 -0x04E0=0x0000 -0x04E1=0x0000 -0x04E2=0x0000 -0x04E3=0x0000 -0x04E4=0x0000 -0x04E5=0x0000 -0x04E6=0x0000 -0x04E7=0x0000 -0x0500=0x0000 -0x0501=0x0000 -0x0502=0x0000 -0x0503=0x0000 -0x0504=0x0000 -0x0505=0x0000 -0x0506=0x0000 -0x0507=0x0000 -0x0508=0x0000 -0x0509=0x0000 -0x050A=0x0000 -0x050B=0x0000 -0x050C=0x0000 -0x050D=0x0000 -0x050E=0x0000 -0x050F=0x0000 -0x0510=0x0000 -0x0511=0x0000 -0x0512=0x0000 -0x0513=0x0000 -0x0514=0x0000 -0x0515=0x0000 -0x0516=0x0000 -0x0517=0x0000 -0x0518=0x0000 -0x0519=0x0000 -0x051A=0x0000 -0x051B=0x0000 -0x051C=0x0000 -0x051D=0x0000 -0x051E=0x0000 -0x051F=0x0000 -0x0520=0x0000 -0x0521=0x0000 -0x0522=0x0000 -0x0523=0x0000 -0x0524=0x0000 -0x0525=0x0000 -0x0526=0x0000 -0x0527=0x0000 -0x0540=0x0000 -0x0541=0x0000 -0x0542=0x0000 -0x0543=0x0000 -0x0544=0x0000 -0x0545=0x0000 -0x0546=0x0000 -0x0547=0x0000 -0x0548=0x0000 -0x0549=0x0000 -0x054A=0x0000 -0x054B=0x0000 -0x054C=0x0000 -0x054D=0x0000 -0x054E=0x0000 -0x054F=0x0000 -0x0550=0x0000 -0x0551=0x0000 -0x0552=0x0000 -0x0553=0x0000 -0x0554=0x0000 -0x0555=0x0000 -0x0556=0x0000 -0x0557=0x0000 -0x0558=0x0000 -0x0559=0x0000 -0x055A=0x0000 -0x055B=0x0000 -0x055C=0x0000 -0x055D=0x0000 -0x055E=0x0000 -0x055F=0x0000 -0x0560=0x0000 -0x0561=0x0000 -0x0562=0x0000 -0x0563=0x0000 -0x0564=0x0000 -0x0565=0x0000 -0x0566=0x0000 -0x0567=0x0000 -0x0580=0x0000 -0x0581=0x0000 -0x0582=0x0000 -0x0583=0x0000 -0x0584=0x0000 -0x0585=0x0000 -0x0586=0x0000 -0x0587=0x0000 -0x0588=0x0000 -0x0589=0x0000 -0x058A=0x0000 -0x058B=0x0000 -0x058C=0x0000 -0x058D=0x0000 -0x058E=0x0000 -0x058F=0x0000 -0x0590=0x0000 -0x0591=0x0000 -0x0592=0x0000 -0x0593=0x0000 -0x0594=0x0000 -0x0595=0x0000 -0x0596=0x0000 -0x0597=0x0000 -0x0598=0x0000 -0x0599=0x0000 -0x059A=0x0000 -0x059B=0x0000 -0x059C=0x0000 -0x059D=0x0000 -0x059E=0x0000 -0x059F=0x0000 -0x05A0=0x0000 -0x05A1=0x0000 -0x05A2=0x0000 -0x05A3=0x0000 -0x05A4=0x0000 -0x05A5=0x0000 -0x05A6=0x0000 -0x05A7=0x0000 -[reference_clocks] -sxr_ref_clk_mhz=52 -sxt_ref_clk_mhz=52 diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.bladerfx40.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.bladerfx40.conf index 5f7ac3d65f..eb3895dc6d 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.bladerfx40.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.bladerfx40.conf @@ -17,7 +17,7 @@ eNBs = mobile_country_code = "208"; - mobile_network_code = "92"; + mobile_network_code = "93"; ////////// Physical parameters: @@ -132,7 +132,7 @@ eNBs = }; ////////// MME parameters: - mme_ip_address = ( { ipv4 = "192.168.13.11"; + mme_ip_address = ( { ipv4 = "192.168.12.11"; ipv6 = "192:168:30::17"; active = "yes"; preference = "ipv4"; @@ -142,10 +142,10 @@ eNBs = NETWORK_INTERFACES : { ENB_INTERFACE_NAME_FOR_S1_MME = "eth0"; - ENB_IPV4_ADDRESS_FOR_S1_MME = "192.168.13.10/24"; + ENB_IPV4_ADDRESS_FOR_S1_MME = "192.168.12.215/24"; ENB_INTERFACE_NAME_FOR_S1U = "eth0"; - ENB_IPV4_ADDRESS_FOR_S1U = "192.168.13.10/24"; + ENB_IPV4_ADDRESS_FOR_S1U = "192.168.12.215/24"; ENB_PORT_FOR_S1U = 2152; # Spec 2152 }; From fb7f4ab9d995d74e030ce6a4916a482683fbd396 Mon Sep 17 00:00:00 2001 From: kaltenbe Date: Fri, 29 Jan 2016 09:49:36 +0100 Subject: [PATCH 186/263] removed old stuff --- targets/ARCH/{SODERA => LMSSDR}/SoDeRa_MIMO.ini | 0 targets/ARCH/{SODERA => LMSSDR}/USERSPACE/LIB/sodera_lib.cpp | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename targets/ARCH/{SODERA => LMSSDR}/SoDeRa_MIMO.ini (100%) rename targets/ARCH/{SODERA => LMSSDR}/USERSPACE/LIB/sodera_lib.cpp (100%) diff --git a/targets/ARCH/SODERA/SoDeRa_MIMO.ini b/targets/ARCH/LMSSDR/SoDeRa_MIMO.ini similarity index 100% rename from targets/ARCH/SODERA/SoDeRa_MIMO.ini rename to targets/ARCH/LMSSDR/SoDeRa_MIMO.ini diff --git a/targets/ARCH/SODERA/USERSPACE/LIB/sodera_lib.cpp b/targets/ARCH/LMSSDR/USERSPACE/LIB/sodera_lib.cpp similarity index 100% rename from targets/ARCH/SODERA/USERSPACE/LIB/sodera_lib.cpp rename to targets/ARCH/LMSSDR/USERSPACE/LIB/sodera_lib.cpp From d30eeea8e5827f803d21be68345f7b075761e56b Mon Sep 17 00:00:00 2001 From: kaltenbe Date: Sat, 30 Jan 2016 23:44:14 +0100 Subject: [PATCH 187/263] integration with Lime contribution for LMSSDR library. Renamed everything from SODERA to LMSSDR --- cmake_targets/CMakeLists.txt | 31 ++++++++----------- cmake_targets/build_oai | 8 ++--- targets/ARCH/COMMON/common_lib.c | 11 ++++--- targets/ARCH/COMMON/common_lib.h | 6 ++-- .../CONF/enb.band7.tm1.bladerfx40.conf | 4 +-- targets/RT/USER/lte-softmodem.c | 4 +++ 6 files changed, 32 insertions(+), 32 deletions(-) diff --git a/cmake_targets/CMakeLists.txt b/cmake_targets/CMakeLists.txt index a8af214ce1..eb19864e95 100644 --- a/cmake_targets/CMakeLists.txt +++ b/cmake_targets/CMakeLists.txt @@ -405,7 +405,7 @@ add_list1_option(NB_ANTENNAS_RX "2" "Number of antennas in reception" "1" "2" "4 add_list1_option(NB_ANTENNAS_TX "2" "Number of antennas in transmission" "1" "2" "4") add_list1_option(NB_ANTENNAS_TXRX "2" "Number of antennas in ????" "1" "2" "4") -add_list2_option(RF_BOARD "EXMIMO" "RF head type" "False" "EXMIMO" "OAI_USRP" "ETHERNET" "OAI_BLADERF" "OAI_SODERA" "CPRIGW") +add_list2_option(RF_BOARD "EXMIMO" "RF head type" "False" "EXMIMO" "OAI_USRP" "ETHERNET" "OAI_BLADERF" "OAI_LMSSDR" "CPRIGW") Message("RF_BOARD is ${RF_BOARD}") @@ -437,25 +437,19 @@ elseif (${RF_BOARD} STREQUAL "OAI_BLADERF") set(option_HW_lib "bladeRF") #set(LOWLATENCY False) -elseif (${RF_BOARD} STREQUAL "OAI_SODERA") - include_directories("${OPENAIR_TARGETS}/ARCH/SODERA/USERSPACE/LIB") - include_directories("${OPENAIR_TARGETS}/ARCH/SODERA/USERSPACE/LIB/lms7suite/src/lms7002m") - include_directories("${OPENAIR_TARGETS}/ARCH/SODERA/USERSPACE/LIB/lms7suite/src/Si5351C") - include_directories("${OPENAIR_TARGETS}/ARCH/SODERA/USERSPACE/LIB/lms7suite/src/LMS_StreamBoard") +elseif (${RF_BOARD} STREQUAL "OAI_LMSSDR") + include_directories("${OPENAIR_TARGETS}/ARCH/LMSSDR/USERSPACE/LIB") + include_directories("${OPENAIR_TARGETS}/ARCH/LMSSDR/USERSPACE/LIB/lmsSDR") + include_directories("${OPENAIR_TARGETS}/ARCH/LMSSDR/USERSPACE/LIB/lms7002m") +# include_directories("${OPENAIR_TARGETS}/ARCH/LMSSDR/USERSPACE/LIB/Si5351C") + include_directories("${OPENAIR_TARGETS}/ARCH/LMSSDR/USERSPACE/LIB/LMS_StreamBoard") set(HW_SOURCE ${HW_SOURCE} - ${OPENAIR_TARGETS}/ARCH/SODERA/USERSPACE/LIB/sodera_lib.cpp + ${OPENAIR_TARGETS}/ARCH/LMSSDR/USERSPACE/LIB/lms_lib.cpp ) - LINK_DIRECTORIES("${OPENAIR_TARGETS}/ARCH/SODERA/USERSPACE/LIB/lms7suite/src/lms7002m") - LINK_DIRECTORIES("${OPENAIR_TARGETS}/ARCH/SODERA/USERSPACE/LIB/lms7suite/src/Si5351C") - LINK_DIRECTORIES("${OPENAIR_TARGETS}/ARCH/SODERA/USERSPACE/LIB/lms7suite/src/LMS_StreamBoard") - LINK_DIRECTORIES("${OPENAIR_TARGETS}/ARCH/SODERA/USERSPACE/LIB/lms7suite/src/kissFFT") LINK_DIRECTORIES("/usr/lib/x86_64-linux-gnu") - set(option_HW_lib "usb-1.0") - set(LMS7002_LIB "libLMS7002M.a") - set(Si5351C_LIB "libSi5351C.a") - set(LMSStreamBoard_LIB "libLMS_StreamBoard.a") - set(KISSFFT_LIB "libkissFFT.a") - #set(LOWLATENCY False) + set(HW_SOURCE ${HW_SOURCE} ${OPENAIR_TARGETS}/ARCH/LMSSDR/USERSPACE/LIB/lms_lib.cpp) + set(LIB_LMS_LIBRARIES "${OPENAIR_TARGETS}/ARCH/LMSSDR/USERSPACE/LIB/lmsSDR/build/libLMS_SDR.so" "${OPENAIR_TARGETS}/ARCH/LMSSDR/USERSPACE/LIB/lms7002m/build/libLMS7002M.a") + set(LOWLATENCY False) elseif (${RF_BOARD} STREQUAL "ETHERNET") include_directories ("${OPENAIR_TARGETS}/ARCH/ETHERNET/USERSPACE/LIB") @@ -1454,13 +1448,14 @@ add_executable(lte-softmodem target_link_libraries (lte-softmodem -Wl,--start-group - RRC_LIB S1AP_LIB S1AP_ENB GTPV1U SECU_CN SECU_OSA UTIL HASHTABLE SCTP_CLIENT UDP SCHED_LIB PHY LFDS L2 ${MSC_LIB} ${RAL_LIB} ${NAS_UE_LIB} ${ITTI_LIB} ${MIH_LIB} ${LMS7002_LIB} ${Si5351C_LIB} ${LMSStreamBoard_LIB} ${KISSFFT_LIB} + RRC_LIB S1AP_LIB S1AP_ENB GTPV1U SECU_CN SECU_OSA UTIL HASHTABLE SCTP_CLIENT UDP SCHED_LIB PHY LFDS L2 ${MSC_LIB} ${RAL_LIB} ${NAS_UE_LIB} ${ITTI_LIB} ${MIH_LIB} -Wl,--end-group ) target_link_libraries (lte-softmodem ${LIBXML2_LIBRARIES}) target_link_libraries (lte-softmodem pthread m ${CONFIG_LIBRARIES} rt crypt ${CRYPTO_LIBRARIES} ${OPENSSL_LIBRARIES} ${NETTLE_LIBRARIES} sctp ${option_HW_lib} ${XFORMS_LIBRARIES} ) target_link_libraries (lte-softmodem ${LIBBOOST_LIBRARIES}) +target_link_libraries (lte-softmodem ${LIB_LMS_LIBRARIES}) # lte-softmodem-nos1 is both eNB and UE implementation ################################################### diff --git a/cmake_targets/build_oai b/cmake_targets/build_oai index 4a18e53f47..6d2021eb01 100755 --- a/cmake_targets/build_oai +++ b/cmake_targets/build_oai @@ -90,7 +90,7 @@ Options default is Rel10, Rel8 limits the implementation to 3GPP Release 8 version -w | --hardware - EXMIMO (Default), USRP, BLADERF, SODERA, ETHERNET, None + EXMIMO (Default), USRP, BLADERF, LMSSDR, ETHERNET, None Adds this RF board support (in external packages installation and in compilation) --oaisim Makes the oaisim simulator. Hardware will be defaulted to "NONE". @@ -181,8 +181,8 @@ function main() { if [ "$HW" == "BLADERF" ] ; then HW="OAI_BLADERF" fi - if [ "$HW" == "SODERA" ] ; then - HW="OAI_SODERA" + if [ "$HW" == "LMSSDR" ] ; then + HW="OAI_LMSSDR" fi echo_info "setting hardware to: $HW" shift 2;; @@ -266,7 +266,7 @@ function main() { LOWLATENCY_FLAG_USER="False" elif [ "$HW" = "OAI_BLADERF" ] ; then LOWLATENCY_FLAG_USER="False" - elif [ "$HW" = "OAI_SODERA" ] ; then + elif [ "$HW" = "OAI_LMSSDR" ] ; then LOWLATENCY_FLAG_USER="False" elif [ "$HW" = "None" ] ; then LOWLATENCY_FLAG_USER="False" diff --git a/targets/ARCH/COMMON/common_lib.c b/targets/ARCH/COMMON/common_lib.c index 278d8ed79f..69496f69ef 100644 --- a/targets/ARCH/COMMON/common_lib.c +++ b/targets/ARCH/COMMON/common_lib.c @@ -61,15 +61,16 @@ int openair0_device_init(openair0_device *device, openair0_config_t *openair0_cf device->type=BLADERF_IF; printf("openair0_dev_init_bladerf ...\n"); return(openair0_dev_init_bladerf(device, openair0_cfg)); -#elif OAI_SODERA - device->type=OAI_SODERA; - printf("openair0_dev_init_sodera ...\n"); +#elif OAI_LMSSDR + device->type=LMSSDR_IF; + printf("openair0_dev_init_lmssdr ...\n"); + /* if (openair0_cfg[0].configFilename==NULL) { printf("Please provide a configuration file for SoDeRa\n"); exit(-1); - } + }*/ - return(openair0_dev_init_sodera(device, openair0_cfg)); + return(openair0_dev_init_lms(device, openair0_cfg)); #endif } diff --git a/targets/ARCH/COMMON/common_lib.h b/targets/ARCH/COMMON/common_lib.h index 3f814a9e55..8255b8f2ab 100644 --- a/targets/ARCH/COMMON/common_lib.h +++ b/targets/ARCH/COMMON/common_lib.h @@ -165,8 +165,8 @@ typedef enum { USRP_X300_IF, /*!\brief device is BLADE RF*/ BLADERF_IF, - /*!\brief device is SODERA RF*/ - SODERARF_IF, + /*!\brief device is LMSSDR*/ + LMSSDR_IF, /*!\brief device is NONE*/ NONE_IF, MAX_DEV_TYPE @@ -298,7 +298,7 @@ extern "C" /*! \brief Initialize Openair ETHERNET target. It returns 0 if OK */ int openair0_dev_init_eth(openair0_device *device, openair0_config_t *openair0_cfg); int openair0_dev_init_bladerf(openair0_device *device, openair0_config_t *openair0_cfg); - int openair0_dev_init_sodera(openair0_device *device, openair0_config_t *openair0_cfg); + int openair0_dev_init_lms(openair0_device *device, openair0_config_t *openair0_cfg); int openair0_dev_init_usrp(openair0_device* device, openair0_config_t *openair0_cfg); int openair0_dev_init_exmimo(openair0_device *device, openair0_config_t *openair0_cfg); /*@}*/ diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf index 5c53803c4d..5a6a9a462b 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf @@ -142,10 +142,10 @@ eNBs = NETWORK_INTERFACES : { ENB_INTERFACE_NAME_FOR_S1_MME = "eth0"; - ENB_IPV4_ADDRESS_FOR_S1_MME = "192.168.12.212/24"; + ENB_IPV4_ADDRESS_FOR_S1_MME = "192.168.12.215/24"; ENB_INTERFACE_NAME_FOR_S1U = "eth0"; - ENB_IPV4_ADDRESS_FOR_S1U = "192.168.12.212/24"; + ENB_IPV4_ADDRESS_FOR_S1U = "192.168.12.215/24"; ENB_PORT_FOR_S1U = 2152; # Spec 2152 }; diff --git a/targets/RT/USER/lte-softmodem.c b/targets/RT/USER/lte-softmodem.c index 612239bec3..a431b35498 100644 --- a/targets/RT/USER/lte-softmodem.c +++ b/targets/RT/USER/lte-softmodem.c @@ -956,6 +956,8 @@ void do_OFDM_mod_rt(int subframe,PHY_VARS_eNB *phy_vars_eNB) ((short*)dummy_tx_b)[2*i]<<4; #elif OAI_BLADERF ((short*)dummy_tx_b)[2*i]; +#elif OAI_LMSSDR + ((short*)dummy_tx_b)[2*i]; #else ((short*)dummy_tx_b)[2*i]<<4; #endif @@ -964,6 +966,8 @@ void do_OFDM_mod_rt(int subframe,PHY_VARS_eNB *phy_vars_eNB) ((short*)dummy_tx_b)[2*i+1]<<4; #elif OAI_BLADERF ((short*)dummy_tx_b)[2*i+1]; +#elif OAI_LMSSDR + ((short*)dummy_tx_b)[2*i+1]; #else ((short*)dummy_tx_b)[2*i+1]<<4; #endif From 8bbcfbe5cbd45a95c1445f94e494ffaf759b66da Mon Sep 17 00:00:00 2001 From: Florian Kaltenberger Date: Mon, 1 Feb 2016 14:18:00 +0100 Subject: [PATCH 188/263] changing LOG_E to LOG_W in rx_pucch_emul when UE is not found (this might happen during attach procedure but is ok since nothing will happen) --- openair1/PHY/LTE_TRANSPORT/pucch.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openair1/PHY/LTE_TRANSPORT/pucch.c b/openair1/PHY/LTE_TRANSPORT/pucch.c index 1c37c78721..837c99b073 100644 --- a/openair1/PHY/LTE_TRANSPORT/pucch.c +++ b/openair1/PHY/LTE_TRANSPORT/pucch.c @@ -1077,7 +1077,7 @@ int32_t rx_pucch_emul(PHY_VARS_eNB *phy_vars_eNB, } if (UE_id==NB_UE_INST) { - LOG_E(PHY,"rx_pucch_emul: FATAL, didn't find UE with rnti %x\n",rnti); + LOG_W(PHY,"rx_pucch_emul: Didn't find UE with rnti %x\n",rnti); return(-1); } From e029738562d7d2c0b4cc8091f31af53350fb57bb Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Mon, 1 Feb 2016 14:42:43 +0100 Subject: [PATCH 189/263] configure nruns and duration of lte-softmodem test cases --- .gitlab-ci.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index b9b796efb9..c75f8fa464 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -20,9 +20,11 @@ job1: - EXTERNAL_SHARE_RESULTS_DIR=$EXTERNAL_SHARE_DIR/$git_branch/$git_head - echo $NFS_TEST_RESULTS_DIR - echo $EXTERNAL_SHARE_RESULTS_DIR + - echo $NRUNS_LTE_SOFTMODEM + - echo $TIMEOUT_CMD - mkdir -p $OPENAIR_DIR/cmake_targets/autotests/log - python $OPENAIR_DIR/cmake_targets/autotests/run_exec_lte-softmodem_tests.py -c -5GRepoHeadVersion $git_head -n $NFS_SHARE_DIR -u $OAI_USER -p $OAI_PASS $OAI_EXTRA_ARGS -g "$OAI_TEST_CASE_GROUP">& $OPENAIR_DIR/cmake_targets/autotests/python_autotest_cleanup.log - - python $OPENAIR_DIR/cmake_targets/autotests/run_exec_lte-softmodem_tests.py -r -5GRepoHeadVersion $git_head -n $NFS_SHARE_DIR -u $OAI_USER -p $OAI_PASS `echo $OAI_EXTRA_ARGS` -g "$OAI_TEST_CASE_GROUP" >& $OPENAIR_DIR/cmake_targets/autotests/python_autotest.log + - python $OPENAIR_DIR/cmake_targets/autotests/run_exec_lte-softmodem_tests.py -r -5GRepoHeadVersion $git_head -n $NFS_SHARE_DIR -u $OAI_USER -p $OAI_PASS `echo $OAI_EXTRA_ARGS` -g "$OAI_TEST_CASE_GROUP" --nrun_lte_softmodem $NRUNS_LTE_SOFTMODEM --timeout_cmd $TIMEOUT_CMD >& $OPENAIR_DIR/cmake_targets/autotests/python_autotest.log - mv $OPENAIR_DIR/cmake_targets/autotests/python_autotest.log $OPENAIR_DIR/cmake_targets/autotests/log/python_autotest.log - mv $OPENAIR_DIR/cmake_targets/autotests/python_autotest_cleanup.log $OPENAIR_DIR/cmake_targets/autotests/log/python_autotest_cleanup.log - sshpass -p "$OAI_PASS" rsync -az -e "ssh -o StrictHostKeyChecking=no " --rsync-path="mkdir -p $NFS_TEST_RESULTS_DIR && rsync" $OPENAIR_DIR/cmake_targets/autotests/log $OAI_USER@localhost:$NFS_TEST_RESULTS_DIR From b31722af8151d18b6aad59aa6ccf919cb5743669 Mon Sep 17 00:00:00 2001 From: Aikaterini Date: Tue, 2 Feb 2016 17:36:42 +0100 Subject: [PATCH 190/263] test --- targets/RT/USER/.#lte-softmodem.c | 1 + 1 file changed, 1 insertion(+) create mode 120000 targets/RT/USER/.#lte-softmodem.c diff --git a/targets/RT/USER/.#lte-softmodem.c b/targets/RT/USER/.#lte-softmodem.c new file mode 120000 index 0000000000..dbbd658659 --- /dev/null +++ b/targets/RT/USER/.#lte-softmodem.c @@ -0,0 +1 @@ +guepe@guepe.25164:1451994252 \ No newline at end of file From 199aa2d069cf54701043e8423ac76c94c5f2da18 Mon Sep 17 00:00:00 2001 From: Aikaterini Date: Tue, 2 Feb 2016 17:36:42 +0100 Subject: [PATCH 191/263] undo test --- targets/RT/USER/.#lte-softmodem.c | 1 + 1 file changed, 1 insertion(+) create mode 120000 targets/RT/USER/.#lte-softmodem.c diff --git a/targets/RT/USER/.#lte-softmodem.c b/targets/RT/USER/.#lte-softmodem.c new file mode 120000 index 0000000000..dbbd658659 --- /dev/null +++ b/targets/RT/USER/.#lte-softmodem.c @@ -0,0 +1 @@ +guepe@guepe.25164:1451994252 \ No newline at end of file From a3c40dc3567f81c7a8eb0340e4776f4f6d742c0a Mon Sep 17 00:00:00 2001 From: Aikaterini Date: Tue, 2 Feb 2016 17:59:22 +0100 Subject: [PATCH 192/263] revert lte-softmodem to previous version --- targets/RT/USER/lte-softmodem.c | 206 ++++++++++++++++++++++---------- 1 file changed, 141 insertions(+), 65 deletions(-) diff --git a/targets/RT/USER/lte-softmodem.c b/targets/RT/USER/lte-softmodem.c index 1f51b21cf9..c67de21f56 100644 --- a/targets/RT/USER/lte-softmodem.c +++ b/targets/RT/USER/lte-softmodem.c @@ -329,7 +329,15 @@ time_stats_t softmodem_stats_rx_sf[10]; // total rx time void reset_opp_meas(void); void print_opp_meas(void); int transmission_mode=1; - +/* + FT: not a very clean way of managing the rescale of iqs in rx path, but this is done in + openair1/PHY/MODULATION/ul_7_5_kHz.c which doesn't have access to config parameters + to re-worked later..... + RX_IQRESCALELEN is setup in device libraries for all non expressmimo targets and acessed as an + external variable in ul_7_5_kHz.c. For expressmimo it is a macro (openair1/PHY/defs.h) + Regarding the value of this variable or macro: 18 is for 15 bits iqs, 15 is used for USRP, EXMIMO +*/ +//int rxrescale; int16_t glog_level = LOG_INFO; int16_t glog_verbosity = LOG_MED; @@ -361,16 +369,57 @@ int16_t osa_log_verbosity = LOG_MED; #ifdef ETHERNET -char rrh_eNB_ip[20] = "127.0.0.1"; -int rrh_eNB_port = 50000; char *rrh_UE_ip = "127.0.0.1"; int rrh_UE_port = 51000; #endif - +/* flag given in runtime to specify if the RF head is local or remote (default option is local RF)*/ +uint8_t local_remote_RF = BBU_LOCAL_RF_ENABLED; + char uecap_xer[1024],uecap_xer_in=0; extern void *UE_thread(void *arg); extern void init_UE_threads(void); +/*---------------------BMC: timespec helpers -----------------------------*/ + +struct timespec min_diff_time = { .tv_sec = 0, .tv_nsec = 0 }; +struct timespec max_diff_time = { .tv_sec = 0, .tv_nsec = 0 }; + +struct timespec clock_difftime(struct timespec start, struct timespec end) +{ + struct timespec temp; + if ((end.tv_nsec-start.tv_nsec)<0) { + temp.tv_sec = end.tv_sec-start.tv_sec-1; + temp.tv_nsec = 1000000000+end.tv_nsec-start.tv_nsec; + } else { + temp.tv_sec = end.tv_sec-start.tv_sec; + temp.tv_nsec = end.tv_nsec-start.tv_nsec; + } + return temp; +} + +void print_difftimes() +{ +#ifdef DEBUG + printf("difftimes min = %lu ns ; max = %lu ns\n", min_diff_time.tv_nsec, max_diff_time.tv_nsec); +#else + LOG_I(HW,"difftimes min = %lu ns ; max = %lu ns\n", min_diff_time.tv_nsec, max_diff_time.tv_nsec); +#endif +} + +void update_difftimes(struct timespec start, struct timespec end) +{ + struct timespec diff_time = { .tv_sec = 0, .tv_nsec = 0 }; + int changed = 0; + diff_time = clock_difftime(start, end); + if ((min_diff_time.tv_nsec == 0) || (diff_time.tv_nsec < min_diff_time.tv_nsec)) { min_diff_time.tv_nsec = diff_time.tv_nsec; changed = 1; } + if ((max_diff_time.tv_nsec == 0) || (diff_time.tv_nsec > max_diff_time.tv_nsec)) { max_diff_time.tv_nsec = diff_time.tv_nsec; changed = 1; } +#if 1 + if (changed) print_difftimes(); +#endif +} + +/*------------------------------------------------------------------------*/ + unsigned int build_rflocal(int txi, int txq, int rxi, int rxq) { return (txi + (txq<<6) + (rxi<<12) + (rxq<<18)); @@ -430,7 +479,7 @@ void help (void) { printf(" -h provides this help message!\n"); printf(" -K Generate ITTI analyzser logs (similar to wireshark logs but with more details)\n"); printf(" -m Set the maximum downlink MCS\n"); - printf(" -M IP address of RRH\n"); + printf(" -M Specify whether RF head is local or remote,valid options: (1: local , 2:remote) \n"); printf(" -O eNB configuration file (located in targets/PROJECTS/GENERIC-LTE-EPC/CONF\n"); printf(" -q Enable processing timing measurement of lte softmodem on per subframe basis \n"); printf(" -r Set the PRB, valid values: 6, 25, 50, 100 \n"); @@ -947,6 +996,12 @@ void do_OFDM_mod_rt(int subframe,PHY_VARS_eNB *phy_vars_eNB) if (tx_offset>=(LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*phy_vars_eNB->lte_frame_parms.samples_per_tti)) tx_offset -= LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*phy_vars_eNB->lte_frame_parms.samples_per_tti; + ((short*)&phy_vars_eNB->lte_eNB_common_vars.txdata[0][aa][tx_offset])[0] = ((short*)dummy_tx_b)[2*i]<lte_eNB_common_vars.txdata[0][aa][tx_offset])[1] = ((short*)dummy_tx_b)[2*i+1]<lte_eNB_common_vars.txdata[0][aa][tx_offset])[0]= #ifdef EXMIMO ((short*)dummy_tx_b)[2*i]<<4; @@ -963,6 +1018,7 @@ void do_OFDM_mod_rt(int subframe,PHY_VARS_eNB *phy_vars_eNB) #else ((short*)dummy_tx_b)[2*i+1]<<4; #endif +*/ } // if S-subframe switch to RX in second subframe if (subframe_select(&phy_vars_eNB->lte_frame_parms,subframe) == SF_S) { @@ -1780,7 +1836,9 @@ static void* eNB_thread( void* arg ) PHY_vars_eNB_g[0][0]->lte_frame_parms.nb_antennas_rx); stop_meas( &softmodem_stats_hw ); - clock_gettime( CLOCK_MONOTONIC, &trx_time1 ); + if (frame > 50) { + clock_gettime( CLOCK_MONOTONIC, &trx_time1 ); + } if (frame > 20){ if (rxs != spp) @@ -1789,8 +1847,6 @@ static void* eNB_thread( void* arg ) VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ, 0 ); // Transmit TX buffer based on timestamp from RX - - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE, 1 ); // prepare tx buffer pointers @@ -1811,16 +1867,23 @@ static void* eNB_thread( void* arg ) VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TST, (timestamp+(openair0_cfg[card].tx_delay*spp)-openair0_cfg[card].tx_forward_nsamps)&0xffffffff ); stop_meas( &softmodem_stats_mt ); - clock_gettime( CLOCK_MONOTONIC, &trx_time2 ); + if (frame > 50) { + clock_gettime( CLOCK_MONOTONIC, &trx_time2 ); + // BMC: compute time between rx and tx + update_difftimes(trx_time1, trx_time2); + } + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE,0); #else // USRP_DEBUG is active rt_sleep_ns(1000000); #endif - +/* FT configurable tx lauch delay (in slots )*/ if ((tx_launched == 0) && - (rx_pos >= (((2*hw_subframe)+1)*PHY_vars_eNB_g[0][0]->lte_frame_parms.samples_per_tti>>1))) { + ((openair0_cfg[card].txlaunch_wait == 0) || + ((openair0_cfg[card].txlaunch_wait == 1) && + (rx_pos >= (((2*hw_subframe)+openair0_cfg[card].txlaunch_wait_slotcount)*PHY_vars_eNB_g[0][0]->lte_frame_parms.samples_per_tti>>1))))) { tx_launched = 1; for (CC_id=0; CC_idproperties[i]->nb_cc, i); - for (j=0; jproperties[i]->nb_rrh_gw; j++) { - - if (enb_properties->properties[i]->rrh_gw_config[j].active == 1 ){ - // replace printf by setting - printf( "\n\tRRH GW %d config for eNB %u:\n\n", j, i); - printf( "\tinterface name : \t%s:\n",enb_properties->properties[i]->rrh_gw_if_name); - printf( "\tlocal address : \t%s:\n",enb_properties->properties[i]->rrh_gw_config[j].local_address); - printf( "\tlocal port : \t%d:\n",enb_properties->properties[i]->rrh_gw_config[j].local_port); - printf( "\tremote address : \t%s:\n",enb_properties->properties[i]->rrh_gw_config[j].remote_address); - printf( "\tremote port : \t%d:\n",enb_properties->properties[i]->rrh_gw_config[j].remote_port); - printf( "\ttransport : \t%s Ethernet:\n\n",(enb_properties->properties[i]->rrh_gw_config[j].raw == 1)? "RAW" : "UDP"); - } - - } - for (CC_id=0; CC_idframe_type = enb_properties->properties[i]->frame_type[CC_id]; frame_parms[CC_id]->tdd_config = enb_properties->properties[i]->tdd_config[CC_id]; @@ -2861,6 +2910,11 @@ int main( int argc, char **argv ) for (card=0; cardN_RB_DL == 100) { sample_rate = 30.72e6; bw = 10.0e6; @@ -2871,8 +2925,8 @@ int main( int argc, char **argv ) openair0_cfg[card].tx_bw = 10e6; openair0_cfg[card].rx_bw = 10e6; // from usrp_time_offset - openair0_cfg[card].tx_forward_nsamps = 175; - openair0_cfg[card].tx_delay = 8; + //openair0_cfg[card].tx_forward_nsamps = 175; + // openair0_cfg[card].tx_delay = 8; #endif } else if(frame_parms[0]->N_RB_DL == 50) { sample_rate = 15.36e6; @@ -2883,8 +2937,8 @@ int main( int argc, char **argv ) openair0_cfg[card].samples_per_frame = 153600; openair0_cfg[card].tx_bw = 5e6; openair0_cfg[card].rx_bw = 5e6; - openair0_cfg[card].tx_forward_nsamps = 95; - openair0_cfg[card].tx_delay = 5; + //openair0_cfg[card].tx_forward_nsamps = 95; + //openair0_cfg[card].tx_delay = 5; #endif } else if (frame_parms[0]->N_RB_DL == 25) { sample_rate = 7.68e6; @@ -2896,12 +2950,14 @@ int main( int argc, char **argv ) openair0_cfg[card].rx_bw = 2.5e6; openair0_cfg[card].samples_per_packet = 1024; #ifdef OAI_USRP - openair0_cfg[card].tx_forward_nsamps = 70; - openair0_cfg[card].tx_delay = 5; -#elif OAI_BLADERF - openair0_cfg[card].tx_forward_nsamps = 0; - openair0_cfg[card].tx_delay = 8; -#endif + + // openair0_cfg[card].tx_forward_nsamps = 70; + //openair0_cfg[card].tx_delay = 5; +#endif + //#elif OAI_BLADERF + //openair0_cfg[card].tx_forward_nsamps = 0; + //openair0_cfg[card].tx_delay = 8; + //#endif #endif } else if (frame_parms[0]->N_RB_DL == 6) { sample_rate = 1.92e6; @@ -2912,16 +2968,26 @@ int main( int argc, char **argv ) openair0_cfg[card].samples_per_frame = 19200; openair0_cfg[card].tx_bw = 1.5e6; openair0_cfg[card].rx_bw = 1.5e6; - openair0_cfg[card].tx_forward_nsamps = 40; - openair0_cfg[card].tx_delay = 8; + //openair0_cfg[card].tx_forward_nsamps = 40; + //openair0_cfg[card].tx_delay = 8; #endif } #ifdef ETHERNET - //calib needed - openair0_cfg[card].tx_delay = 0; + //openair0_cfg[card].remote_addr = "192.168.12.242"; + //openair0_cfg[card].remote_addr = "127.0.0.1"; + openair0_cfg[card].remote_addr = "74:d4:35:cc:88:45"; + openair0_cfg[card].remote_port = 50000; + //openair0_cfg[card].my_addr = "192.168.12.31"; + //openair0_cfg[card].my_addr = "127.0.0.1"; + openair0_cfg[card].my_addr = "d4:be:d9:22:0a:ac"; + openair0_cfg[card].my_port = 50000; + //openair0_cfg[card].my_port = 50001; + openair0_cfg[card].tx_delay = 10; openair0_cfg[card].tx_forward_nsamps = 0; + openair0_cfg[card].txlaunch_wait = 0; + openair0_cfg[card].txlaunch_wait_slotcount = 0; if (frame_parms[0]->N_RB_DL == 6) openair0_cfg[card].samples_per_packet = 256; @@ -2934,23 +3000,20 @@ int main( int argc, char **argv ) #ifndef EXMIMO openair0_cfg[card].samples_per_packet = openair0_cfg[0].samples_per_packet; + openair0_cfg[card].num_rb_dl=frame_parms[0]->N_RB_DL; #endif printf("HW: Configuring card %d, nb_antennas_tx/rx %d/%d\n",card, ((UE_flag==0) ? PHY_vars_eNB_g[0][0]->lte_frame_parms.nb_antennas_tx : PHY_vars_UE_g[0][0]->lte_frame_parms.nb_antennas_tx), ((UE_flag==0) ? PHY_vars_eNB_g[0][0]->lte_frame_parms.nb_antennas_rx : PHY_vars_UE_g[0][0]->lte_frame_parms.nb_antennas_rx)); openair0_cfg[card].Mod_id = 0; -#ifdef ETHERNET - +#ifdef ETHERNET/*do we need to separate ue and enb????*/ + if (UE_flag) { printf("ETHERNET: Configuring UE ETH for %s:%d\n",rrh_UE_ip,rrh_UE_port); - openair0_cfg[card].remote_ip = &rrh_UE_ip[0]; + openair0_cfg[card].remote_addr = &rrh_UE_ip[0]; openair0_cfg[card].remote_port = rrh_UE_port; - } else { - printf("ETHERNET: Configuring eNB ETH for %s:%d\n",rrh_eNB_ip,rrh_eNB_port); - openair0_cfg[card].remote_ip = &rrh_eNB_ip[0]; - openair0_cfg[card].remote_port = rrh_eNB_port; - } -openair0_cfg[card].num_rb_dl=frame_parms[0]->N_RB_DL; + } + #endif openair0_cfg[card].sample_rate = sample_rate; openair0_cfg[card].tx_bw = bw; @@ -3003,18 +3066,36 @@ openair0_cfg[card].num_rb_dl=frame_parms[0]->N_RB_DL; #endif } - - openair0.func_type = BBU_FUNC; + /* device host type is set*/ + openair0.host_type = BBU_HOST; + /* device type is initialized NONE_DEV (no RF device) when the RF device will be initiated device type will be set */ + openair0.type = NONE_DEV; + /* transport type is initialized NONE_TP (no transport protocol) when the transport protocol will be initiated transport protocol type will be set */ + openair0.transp_type = NONE_TP; openair0_cfg[0].log_level = glog_level; - + + /* BBU can either have local or remote radio heads - local radio head option is set by default so the corresponding device is initiated */ if ((mode!=loop_through_memory) && - (openair0_device_init(&openair0, &openair0_cfg[0]) <0)) { + (openair0_device_load(&openair0, &openair0_cfg[0]) <0)) { printf("Exiting, cannot initialize device\n"); exit(-1); } else if (mode==loop_through_memory) { } - + /* radio heads are remote so the trasnsport protocol is initiated */ + if (local_remote_RF == BBU_REMOTE_RF_ENABLED) { + if ((mode!=loop_through_memory) && + (openair0_transport_load(&openair0, &openair0_cfg[0]) <0)) { + printf("Exiting, cannot initialize transport protocol\n"); + exit(-1); + } + else if (mode==loop_through_memory) { + } + } + //for EXMIMO + //openair0_cfg[0].iq_rxrescale=15; /* default value if build with EXMIMO */ + //rxrescale=openair0_cfg[0].iq_rxrescale; /* see comments near RX_IQRESCALELEN definition */ + printf("Done\n"); mac_xface = malloc(sizeof(MAC_xface)); @@ -3432,7 +3513,6 @@ openair0_cfg[card].num_rb_dl=frame_parms[0]->N_RB_DL; if (multi_thread>0) { printf("Killing eNB processing threads\n"); kill_eNB_proc(); - } } @@ -3524,10 +3604,6 @@ int setup_eNB_buffers(PHY_VARS_eNB **phy_vars_eNB, openair0_config_t *openair0_c #endif - - - - // replace RX signal buffers with mmaped HW versions #ifdef EXMIMO openair0_cfg[CC_id].tx_num_channels = 0; From 064c8880470022840ac145a102e7e0fae68a8e31 Mon Sep 17 00:00:00 2001 From: Aikaterini Date: Tue, 2 Feb 2016 18:00:15 +0100 Subject: [PATCH 193/263] incorporate Navid's fronthaul conf params --- targets/RT/USER/lte-softmodem.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/targets/RT/USER/lte-softmodem.c b/targets/RT/USER/lte-softmodem.c index c67de21f56..b6d42e03a8 100644 --- a/targets/RT/USER/lte-softmodem.c +++ b/targets/RT/USER/lte-softmodem.c @@ -2406,6 +2406,21 @@ static void get_options (int argc, char **argv) "lte-softmodem compiled with MAX_NUM_CCs=%d, but only %d CCs configured for eNB %d!", MAX_NUM_CCs, enb_properties->properties[i]->nb_cc, i); + for (j=0; jproperties[i]->nb_rrh_gw; j++) { + + if (enb_properties->properties[i]->rrh_gw_config[j].active == 1 ){ + // replace printf by setting + printf( "\n\tRRH GW %d config for eNB %u:\n\n", j, i); + printf( "\tinterface name : \t%s:\n",enb_properties->properties[i]->rrh_gw_if_name); + printf( "\tlocal address : \t%s:\n",enb_properties->properties[i]->rrh_gw_config[j].local_address); + printf( "\tlocal port : \t%d:\n",enb_properties->properties[i]->rrh_gw_config[j].local_port); + printf( "\tremote address : \t%s:\n",enb_properties->properties[i]->rrh_gw_config[j].remote_address); + printf( "\tremote port : \t%d:\n",enb_properties->properties[i]->rrh_gw_config[j].remote_port); + printf( "\ttransport : \t%s Ethernet:\n\n",(enb_properties->properties[i]->rrh_gw_config[j].raw == 1)? "RAW" : "UDP"); + } + + } + for (CC_id=0; CC_idframe_type = enb_properties->properties[i]->frame_type[CC_id]; frame_parms[CC_id]->tdd_config = enb_properties->properties[i]->tdd_config[CC_id]; From 353f5f25d25216b633e59ac7f7fb39b33e1031e2 Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Wed, 3 Feb 2016 11:49:23 +0100 Subject: [PATCH 194/263] removed NFS check --- .../autotests/run_exec_lte-softmodem_tests.py | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/cmake_targets/autotests/run_exec_lte-softmodem_tests.py b/cmake_targets/autotests/run_exec_lte-softmodem_tests.py index ed4a19f4dc..e68f591a58 100755 --- a/cmake_targets/autotests/run_exec_lte-softmodem_tests.py +++ b/cmake_targets/autotests/run_exec_lte-softmodem_tests.py @@ -1282,18 +1282,17 @@ if localshell == 0: print '\nCleaning Older running programs : ' + CleanUpOldProgs cleanOldPrograms(oai_list[index], CleanUpOldProgs, CleanUpAluLteBox, ExmimoRfStop) - result = oai_list[index].send('mount ' + NFSResultsDir, True) - print "Mounting NFS Share " + NFSResultsDir + "..." + result + #result = oai_list[index].send('mount ' + NFSResultsDir, True) + #print "Mounting NFS Share " + NFSResultsDir + "..." + result # Check if NFS share is mounted correctly. - print 'Checking if NFS Share<' + NFSResultsDir + '> is mounted correctly...' - #result = oai_list[index].send_expect('mount | grep ' + NFSResultsDir, NFSResultsDir ) - cmd = 'if grep -qs '+NFSResultsDir+ ' /proc/mounts; then echo \'' + NFSResultsDir + ' is mounted\' ; fi' - search_expr = NFSResultsDir + ' is mounted' - print "cmd = " + cmd - print "search_expr = " + search_expr - result = oai_list[index].send_expect(cmd, search_expr) - print "Mount NFS_Results_Dir..." + result + #print 'Checking if NFS Share<' + NFSResultsDir + '> is mounted correctly...' + #cmd = 'if grep -qs '+NFSResultsDir+ ' /proc/mounts; then echo \'' + NFSResultsDir + ' is mounted\' ; fi' + #search_expr = NFSResultsDir + ' is mounted' + #print "cmd = " + cmd + #print "search_expr = " + search_expr + #result = oai_list[index].send_expect(cmd, search_expr) + #print "Mount NFS_Results_Dir..." + result index = index + 1 #oai.connect2(user,pw) From f5351535fc69d2f780e9104244ee11cc2ec7bbbd Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Thu, 4 Feb 2016 14:47:34 +0100 Subject: [PATCH 195/263] commits to modify test case config file for TDD (oaisim tests) --- cmake_targets/autotests/test_case_list.xml | 108 +++++++++++-------- cmake_targets/autotests/tools/search_repl.py | 6 +- 2 files changed, 70 insertions(+), 44 deletions(-) diff --git a/cmake_targets/autotests/test_case_list.xml b/cmake_targets/autotests/test_case_list.xml index 6e0d1c2fdb..5d5b9703ea 100644 --- a/cmake_targets/autotests/test_case_list.xml +++ b/cmake_targets/autotests/test_case_list.xml @@ -317,18 +317,22 @@ execution Run OAISIM Rel10 TDD, 1 eNB + 1 UE (5 MHz/10MHz/20MHz), (TM 1,2) and search for errors, segmentation fault or exit - + cp -vf $OPENAIR_TARGETS/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.generic.oaisim.local_no_mme.conf $OPENAIR_LOGDIR/enb.band7.generic.oaisim.local_no_mme.conf $OPENAIR_DIR/cmake_targets/build_oai --oaisim --noS1 -c $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 + $OPENAIR_LOGDIR/enb.band7.generic.oaisim.local_no_mme.conf frame_type \"TDD\" + $OPENAIR_LOGDIR/enb.band7.generic.oaisim.local_no_mme.conf eutra_band 38 + $OPENAIR_LOGDIR/enb.band7.generic.oaisim.local_no_mme.conf downlink_frequency 2580000000L + $OPENAIR_LOGDIR/enb.band7.generic.oaisim.local_no_mme.conf uplink_frequency_offset 0 $OPENAIR_DIR/cmake_targets/oaisim_noS1_build_oai/build/oaisim_nos1 - -O $OPENAIR_TARGETS/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.generic.oaisim.local_no_mme.conf -A AWGN -b1 -u1 -n100 -R 25 -x 1 - -O $OPENAIR_TARGETS/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.generic.oaisim.local_no_mme.conf -A AWGN -b1 -u1 -n100 -R 50 -x 1 - -O $OPENAIR_TARGETS/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.generic.oaisim.local_no_mme.conf -A AWGN -b1 -u1 -n100 -R 100 -x 1 - -O $OPENAIR_TARGETS/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.generic.oaisim.local_no_mme.conf -A AWGN -b1 -u1 -n100 -R 25 -x 2 - -O $OPENAIR_TARGETS/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.generic.oaisim.local_no_mme.conf -A AWGN -b1 -u1 -n100 -R 50 -x 2 - -O $OPENAIR_TARGETS/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.generic.oaisim.local_no_mme.conf -A AWGN -b1 -u1 -n100 -R 100 -x 2 + -O $OPENAIR_LOGDIR/enb.band7.generic.oaisim.local_no_mme.conf -A AWGN -b1 -u1 -n100 -R 25 -x 1 + -O $OPENAIR_LOGDIR/enb.band7.generic.oaisim.local_no_mme.conf -A AWGN -b1 -u1 -n100 -R 50 -x 1 + -O $OPENAIR_LOGDIR/enb.band7.generic.oaisim.local_no_mme.conf -A AWGN -b1 -u1 -n100 -R 100 -x 1 + -O $OPENAIR_LOGDIR/enb.band7.generic.oaisim.local_no_mme.conf -A AWGN -b1 -u1 -n100 -R 25 -x 2 + -O $OPENAIR_LOGDIR/enb.band7.generic.oaisim.local_no_mme.conf -A AWGN -b1 -u1 -n100 -R 50 -x 2 + -O $OPENAIR_LOGDIR/enb.band7.generic.oaisim.local_no_mme.conf -A AWGN -b1 -u1 -n100 -R 100 -x 2 oaisim_noS1.tdd.5MHz.TM1 oaisim_noS1.tdd.10MHz.TM1 oaisim_noS1.tdd.20MHz.TM1 oaisim_noS1.tdd.5MHz.TM2 oaisim_noS1.tdd.10MHz.TM2 oaisim_noS1.tdd.20MHz.TM2 "Received RRCConnectionReconfigurationComplete from UE 0" segmentation fault|assertion|exiting|fatal @@ -338,18 +342,22 @@ execution Run OAISIM Rel10 TDD, 1 eNB + 1 UE (5 MHz/10MHz/20MHz), (TM 1,2) in PHY_ABSTRACTION mode and search for errors, segmentation fault or exit - + cp -vf $OPENAIR_TARGETS/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.generic.oaisim.local_no_mme.conf $OPENAIR_LOGDIR/enb.band7.generic.oaisim.local_no_mme.conf $OPENAIR_DIR/cmake_targets/build_oai --oaisim --noS1 -c + $OPENAIR_LOGDIR/enb.band7.generic.oaisim.local_no_mme.conf frame_type \"TDD\" + $OPENAIR_LOGDIR/enb.band7.generic.oaisim.local_no_mme.conf eutra_band 38 + $OPENAIR_LOGDIR/enb.band7.generic.oaisim.local_no_mme.conf downlink_frequency 2580000000L + $OPENAIR_LOGDIR/enb.band7.generic.oaisim.local_no_mme.conf uplink_frequency_offset 0 $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 $OPENAIR_DIR/cmake_targets/oaisim_noS1_build_oai/build/oaisim_nos1 - -O $OPENAIR_TARGETS/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.generic.oaisim.local_no_mme.conf -A AWGN -b1 -u1 -n100 -R 25 -x 1 -a - -O $OPENAIR_TARGETS/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.generic.oaisim.local_no_mme.conf -A AWGN -b1 -u1 -n100 -R 50 -x 1 -a - -O $OPENAIR_TARGETS/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.generic.oaisim.local_no_mme.conf -A AWGN -b1 -u1 -n100 -R 100 -x 1 -a - -O $OPENAIR_TARGETS/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.generic.oaisim.local_no_mme.conf -A AWGN -b1 -u1 -n100 -R 25 -x 2 -a - -O $OPENAIR_TARGETS/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.generic.oaisim.local_no_mme.conf -A AWGN -b1 -u1 -n100 -R 50 -x 2 -a - -O $OPENAIR_TARGETS/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.generic.oaisim.local_no_mme.conf -A AWGN -b1 -u1 -n100 -R 100 -x 2 -a + -O $OPENAIR_LOGDIR/enb.band7.generic.oaisim.local_no_mme.conf -A AWGN -b1 -u1 -n100 -R 25 -x 1 -a + -O $OPENAIR_LOGDIR/enb.band7.generic.oaisim.local_no_mme.conf -A AWGN -b1 -u1 -n100 -R 50 -x 1 -a + -O $OPENAIR_LOGDIR/enb.band7.generic.oaisim.local_no_mme.conf -A AWGN -b1 -u1 -n100 -R 100 -x 1 -a + -O $OPENAIR_LOGDIR/enb.band7.generic.oaisim.local_no_mme.conf -A AWGN -b1 -u1 -n100 -R 25 -x 2 -a + -O $OPENAIR_LOGDIR/enb.band7.generic.oaisim.local_no_mme.conf -A AWGN -b1 -u1 -n100 -R 50 -x 2 -a + -O $OPENAIR_LOGDIR/enb.band7.generic.oaisim.local_no_mme.conf -A AWGN -b1 -u1 -n100 -R 100 -x 2 -a oaisim_noS1.tdd.5MHz.TM1 oaisim_noS1.tdd.10MHz.TM1 oaisim_noS1.tdd.20MHz.TM1 oaisim_noS1.tdd.5MHz.TM2 oaisim_noS1.tdd.10MHz.TM2 oaisim_noS1.tdd.20MHz.TM2 "Received RRCConnectionReconfigurationComplete from UE 0" segmentation fault|assertion|exiting|fatal @@ -359,18 +367,22 @@ execution Run OAISIM Rel10 TDD, 1 eNB + 3 UEs (5 MHz/10MHz/20MHz), (TM 1,2) and search for errors, segmentation fault or exit - +cp -vf $OPENAIR_TARGETS/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.generic.oaisim.local_no_mme.conf $OPENAIR_LOGDIR/enb.band7.generic.oaisim.local_no_mme.conf $OPENAIR_DIR/cmake_targets/build_oai --oaisim --noS1 -c + $OPENAIR_LOGDIR/enb.band7.generic.oaisim.local_no_mme.conf frame_type \"TDD\" + $OPENAIR_LOGDIR/enb.band7.generic.oaisim.local_no_mme.conf eutra_band 38 + $OPENAIR_LOGDIR/enb.band7.generic.oaisim.local_no_mme.conf downlink_frequency 2580000000L + $OPENAIR_LOGDIR/enb.band7.generic.oaisim.local_no_mme.conf uplink_frequency_offset 0 $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 $OPENAIR_DIR/cmake_targets/oaisim_noS1_build_oai/build/oaisim_nos1 - -O $OPENAIR_TARGETS/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.generic.oaisim.local_no_mme.conf -A AWGN -b1 -u3 -n100 -R 25 -x 1 - -O $OPENAIR_TARGETS/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.generic.oaisim.local_no_mme.conf -A AWGN -b1 -u3 -n100 -R 50 -x 1 - -O $OPENAIR_TARGETS/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.generic.oaisim.local_no_mme.conf -A AWGN -b1 -u3 -n100 -R 100 -x 1 - -O $OPENAIR_TARGETS/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.generic.oaisim.local_no_mme.conf -A AWGN -b1 -u3 -n100 -R 25 -x 2 - -O $OPENAIR_TARGETS/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.generic.oaisim.local_no_mme.conf -A AWGN -b1 -u3 -n100 -R 50 -x 2 - -O $OPENAIR_TARGETS/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.generic.oaisim.local_no_mme.conf -A AWGN -b1 -u3 -n100 -R 100 -x 2 + -O $OPENAIR_LOGDIR/enb.band7.generic.oaisim.local_no_mme.conf -A AWGN -b1 -u3 -n100 -R 25 -x 1 + -O $OPENAIR_LOGDIR/enb.band7.generic.oaisim.local_no_mme.conf -A AWGN -b1 -u3 -n100 -R 50 -x 1 + -O $OPENAIR_LOGDIR/enb.band7.generic.oaisim.local_no_mme.conf -A AWGN -b1 -u3 -n100 -R 100 -x 1 + -O $OPENAIR_LOGDIR/enb.band7.generic.oaisim.local_no_mme.conf -A AWGN -b1 -u3 -n100 -R 25 -x 2 + -O $OPENAIR_LOGDIR/enb.band7.generic.oaisim.local_no_mme.conf -A AWGN -b1 -u3 -n100 -R 50 -x 2 + -O $OPENAIR_LOGDIR/enb.band7.generic.oaisim.local_no_mme.conf -A AWGN -b1 -u3 -n100 -R 100 -x 2 oaisim_noS1.tdd.5MHz.TM1 oaisim_noS1.tdd.10MHz.TM1 oaisim_noS1.tdd.20MHz.TM1 oaisim_noS1.tdd.5MHz.TM2 oaisim_noS1.tdd.10MHz.TM2 oaisim_noS1.tdd.20MHz.TM2 "Received RRCConnectionReconfigurationComplete from UE 0" "Received RRCConnectionReconfigurationComplete from UE 1" "Received RRCConnectionReconfigurationComplete from UE 2" segmentation fault|assertion|exiting|fatal @@ -380,18 +392,22 @@ execution Run OAISIM Rel10 TDD, 1 eNB + 3 UEs (5 MHz) in PHY_ABSTRACTION mode and search for errors, segmentation fault or exit - + cp -vf $OPENAIR_TARGETS/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.generic.oaisim.local_no_mme.conf $OPENAIR_LOGDIR/enb.band7.generic.oaisim.local_no_mme.conf $OPENAIR_DIR/cmake_targets/build_oai --oaisim --noS1 -c + $OPENAIR_LOGDIR/enb.band7.generic.oaisim.local_no_mme.conf frame_type \"TDD\" + $OPENAIR_LOGDIR/enb.band7.generic.oaisim.local_no_mme.conf eutra_band 38 + $OPENAIR_LOGDIR/enb.band7.generic.oaisim.local_no_mme.conf downlink_frequency 2580000000L + $OPENAIR_LOGDIR/enb.band7.generic.oaisim.local_no_mme.conf uplink_frequency_offset 0 $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 $OPENAIR_DIR/cmake_targets/oaisim_noS1_build_oai/build/oaisim_nos1 - -O $OPENAIR_TARGETS/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.generic.oaisim.local_no_mme.conf -A AWGN -b1 -u3 -n100 -R 25 -x 1 -a - -O $OPENAIR_TARGETS/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.generic.oaisim.local_no_mme.conf -A AWGN -b1 -u3 -n100 -R 50 -x 1 -a - -O $OPENAIR_TARGETS/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.generic.oaisim.local_no_mme.conf -A AWGN -b1 -u3 -n100 -R 100 -x 1 -a - -O $OPENAIR_TARGETS/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.generic.oaisim.local_no_mme.conf -A AWGN -b1 -u3 -n100 -R 25 -x 2 -a - -O $OPENAIR_TARGETS/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.generic.oaisim.local_no_mme.conf -A AWGN -b1 -u3 -n100 -R 50 -x 2 -a - -O $OPENAIR_TARGETS/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.generic.oaisim.local_no_mme.conf -A AWGN -b1 -u3 -n100 -R 100 -x 2 -a + -O $OPENAIR_LOGDIR/enb.band7.generic.oaisim.local_no_mme.conf -A AWGN -b1 -u3 -n100 -R 25 -x 1 -a + -O $OPENAIR_LOGDIR/enb.band7.generic.oaisim.local_no_mme.conf -A AWGN -b1 -u3 -n100 -R 50 -x 1 -a + -O $OPENAIR_LOGDIR/enb.band7.generic.oaisim.local_no_mme.conf -A AWGN -b1 -u3 -n100 -R 100 -x 1 -a + -O $OPENAIR_LOGDIR/enb.band7.generic.oaisim.local_no_mme.conf -A AWGN -b1 -u3 -n100 -R 25 -x 2 -a + -O $OPENAIR_LOGDIR/enb.band7.generic.oaisim.local_no_mme.conf -A AWGN -b1 -u3 -n100 -R 50 -x 2 -a + -O $OPENAIR_LOGDIR/enb.band7.generic.oaisim.local_no_mme.conf -A AWGN -b1 -u3 -n100 -R 100 -x 2 -a oaisim_noS1.tdd.5MHz.TM1 oaisim_noS1.tdd.10MHz.TM1 oaisim_noS1.tdd.20MHz.TM1 oaisim_noS1.tdd.5MHz.TM2 oaisim_noS1.tdd.10MHz.TM2 oaisim_nos1.tdd.20MHz.TM2 "Received RRCConnectionReconfigurationComplete from UE 0" "Received RRCConnectionReconfigurationComplete from UE 1" "Received RRCConnectionReconfigurationComplete from UE 2" segmentation fault|assertion|exiting|fatal @@ -401,18 +417,22 @@ execution Run OAI Rel10 TDD, 1 eNB + 1 UE (5 MHz) without abstraction mode, send ping from from eNB to UE, and check that there is no packet losses - + cp -vf $OPENAIR_TARGETS/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.generic.oaisim.local_no_mme.conf $OPENAIR_LOGDIR/enb.band7.generic.oaisim.local_no_mme.conf $OPENAIR_DIR/cmake_targets/build_oai --oaisim --noS1 -c $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 + $OPENAIR_LOGDIR/enb.band7.generic.oaisim.local_no_mme.conf frame_type \"TDD\" + $OPENAIR_LOGDIR/enb.band7.generic.oaisim.local_no_mme.conf eutra_band 38 + $OPENAIR_LOGDIR/enb.band7.generic.oaisim.local_no_mme.conf downlink_frequency 2580000000L + $OPENAIR_LOGDIR/enb.band7.generic.oaisim.local_no_mme.conf uplink_frequency_offset 0 $OPENAIR_DIR/cmake_targets/oaisim_noS1_build_oai/build/oaisim_nos1 - -O $OPENAIR_TARGETS/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.generic.oaisim.local_no_mme.conf -A AWGN -b1 -u3 -n100 -R 25 -x 1 -c26 - -O $OPENAIR_TARGETS/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.generic.oaisim.local_no_mme.conf -A AWGN -b1 -u3 -n100 -R 50 -x 1 -c26 - -O $OPENAIR_TARGETS/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.generic.oaisim.local_no_mme.conf -A AWGN -b1 -u3 -n100 -R 100 -x 1 -c26 - -O $OPENAIR_TARGETS/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.generic.oaisim.local_no_mme.conf -A AWGN -b1 -u3 -n100 -R 25 -x 2 -c26 - -O $OPENAIR_TARGETS/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.generic.oaisim.local_no_mme.conf -A AWGN -b1 -u3 -n100 -R 50 -x 2 -c26 - -O $OPENAIR_TARGETS/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.generic.oaisim.local_no_mme.conf -A AWGN -b1 -u3 -n100 -R 100 -x 2 -c26 + -O $OPENAIR_LOGDIR/enb.band7.generic.oaisim.local_no_mme.conf -A AWGN -b1 -u3 -n100 -R 25 -x 1 -c26 + -O $OPENAIR_LOGDIR/enb.band7.generic.oaisim.local_no_mme.conf -A AWGN -b1 -u3 -n100 -R 50 -x 1 -c26 + -O $OPENAIR_LOGDIR/enb.band7.generic.oaisim.local_no_mme.conf -A AWGN -b1 -u3 -n100 -R 100 -x 1 -c26 + -O $OPENAIR_LOGDIR/enb.band7.generic.oaisim.local_no_mme.conf -A AWGN -b1 -u3 -n100 -R 25 -x 2 -c26 + -O $OPENAIR_LOGDIR/enb.band7.generic.oaisim.local_no_mme.conf -A AWGN -b1 -u3 -n100 -R 50 -x 2 -c26 + -O $OPENAIR_LOGDIR/enb.band7.generic.oaisim.local_no_mme.conf -A AWGN -b1 -u3 -n100 -R 100 -x 2 -c26 oaisim_noS1.tdd.5MHz.TM1 oaisim_noS1.tdd.10MHz.TM1 oaisim_noS1.tdd.20MHz.TM1 oaisim_noS1.tdd.5MHz.TM2 oaisim_noS1.tdd.10MHz.TM2 oaisim_noS1.tdd.20MHz.TM2 "DL and UL loss rate below 10" segmentation fault|assertion|exiting|fatal @@ -422,18 +442,22 @@ execution Run OAI Rel10 TDD, 1 eNB + 1 UE (5 MHz) in PHY_ABSTRACTION mode, send ping from from eNB to UE, and check that there is no packet losses - + cp -vf $OPENAIR_TARGETS/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.generic.oaisim.local_no_mme.conf $OPENAIR_LOGDIR/enb.band7.generic.oaisim.local_no_mme.conf $OPENAIR_DIR/cmake_targets/build_oai --oaisim --noS1 -c $OPENAIR_DIR/cmake_targets/tools/init_nas_nos1 + $OPENAIR_LOGDIR/enb.band7.generic.oaisim.local_no_mme.conf frame_type \"TDD\" + $OPENAIR_LOGDIR/enb.band7.generic.oaisim.local_no_mme.conf eutra_band 38 + $OPENAIR_LOGDIR/enb.band7.generic.oaisim.local_no_mme.conf downlink_frequency 2580000000L + $OPENAIR_LOGDIR/enb.band7.generic.oaisim.local_no_mme.conf uplink_frequency_offset 0 $OPENAIR_DIR/cmake_targets/oaisim_noS1_build_oai/build/oaisim_nos1 - -O $OPENAIR_TARGETS/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.generic.oaisim.local_no_mme.conf -A AWGN -b1 -u3 -n100 -R 25 -x 1 -c26 -a - -O $OPENAIR_TARGETS/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.generic.oaisim.local_no_mme.conf -A AWGN -b1 -u3 -n100 -R 50 -x 1 -c26 -a - -O $OPENAIR_TARGETS/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.generic.oaisim.local_no_mme.conf -A AWGN -b1 -u3 -n100 -R 100 -x 1 -c26 -a - -O $OPENAIR_TARGETS/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.generic.oaisim.local_no_mme.conf -A AWGN -b1 -u3 -n100 -R 25 -x 2 -c26 -a - -O $OPENAIR_TARGETS/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.generic.oaisim.local_no_mme.conf -A AWGN -b1 -u3 -n100 -R 50 -x 2 -c26 -a - -O $OPENAIR_TARGETS/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.generic.oaisim.local_no_mme.conf -A AWGN -b1 -u3 -n100 -R 100 -x 2 -c26 -a + -O $OPENAIR_LOGDIR/enb.band7.generic.oaisim.local_no_mme.conf -A AWGN -b1 -u3 -n100 -R 25 -x 1 -c26 -a + -O $OPENAIR_LOGDIR/enb.band7.generic.oaisim.local_no_mme.conf -A AWGN -b1 -u3 -n100 -R 50 -x 1 -c26 -a + -O $OPENAIR_LOGDIR/enb.band7.generic.oaisim.local_no_mme.conf -A AWGN -b1 -u3 -n100 -R 100 -x 1 -c26 -a + -O $OPENAIR_LOGDIR/enb.band7.generic.oaisim.local_no_mme.conf -A AWGN -b1 -u3 -n100 -R 25 -x 2 -c26 -a + -O $OPENAIR_LOGDIR/enb.band7.generic.oaisim.local_no_mme.conf -A AWGN -b1 -u3 -n100 -R 50 -x 2 -c26 -a + -O $OPENAIR_LOGDIR/enb.band7.generic.oaisim.local_no_mme.conf -A AWGN -b1 -u3 -n100 -R 100 -x 2 -c26 -a oaisim_noS1.tdd.5MHz.TM1 oaisim_noS1.tdd.10MHz.TM1 oaisim_noS1.tdd.20MHz.TM1 oaisim_noS1.tdd.5MHz.TM2 oaisim_noS1.tdd.10MHz.TM2 oaisim_noS1.tdd.20MHz.TM2 "DL and UL loss rate below 10" segmentation fault|assertion|exiting|fatal diff --git a/cmake_targets/autotests/tools/search_repl.py b/cmake_targets/autotests/tools/search_repl.py index d0d6c4638f..bb807502f2 100755 --- a/cmake_targets/autotests/tools/search_repl.py +++ b/cmake_targets/autotests/tools/search_repl.py @@ -1,18 +1,20 @@ #!/usr/bin/python import sys import re +import os #Arg 1 name of file #Arg 2 keyword #arg 3 replacement text #Note that these should be seperated by spaces if len(sys.argv) != 4: - print "search_repl.py: Wrong number of arguments. This program needs 3 arguments" + print "search_repl.py: Wrong number of arguments. This program needs 3 arguments. The number of arguments supplied : " + str(sys.argv) sys.exit() -filename = sys.argv[1] +filename = os.path.expandvars(sys.argv[1]) keyword = sys.argv[2] replacement_text = sys.argv[3] + file = open(filename, 'r') string = file.read() file.close() From 1a751a198072c2cad33fbeda422969d3f7c1c721 Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Thu, 4 Feb 2016 14:47:53 +0100 Subject: [PATCH 196/263] commits to modify test case config file for TDD (oaisim tests) --- .../autotests/run_exec_autotests.bash | 29 ++++++++++++++----- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/cmake_targets/autotests/run_exec_autotests.bash b/cmake_targets/autotests/run_exec_autotests.bash index 836a8c197a..a622b07efb 100755 --- a/cmake_targets/autotests/run_exec_autotests.bash +++ b/cmake_targets/autotests/run_exec_autotests.bash @@ -175,6 +175,7 @@ function test_compile() { #\param $13 -> output of compilation program that needs to be found for test case to pass #\param $14 -> tags to help identify the test case for readability in output xml file #\param $15 => password for the user to run certain commands as sudo +#\param $16 => test config file params to be modified function test_compile_and_run() { xUnit_start @@ -195,12 +196,14 @@ function test_compile_and_run() { compile_prog_out=${13} tags=${14} mypassword=${15} + test_config_file=${16} + build_dir=$tdir/$1/build #exec_file=$build_dir/$6 xmlfile_testcase=$log_dir/test.$1.xml #Temporary log file where execution log is stored. temp_exec_log=$log_dir/temp_log.txt - + export OPENAIR_LOGDIR=$log_dir rm -fr $log_dir mkdir -p $log_dir @@ -219,6 +222,10 @@ function test_compile_and_run() { #compile_prog_array=() #read -a compile_prog_array <<<"$compile_prog" + + #test_config_file=`eval "echo \"$test_config_file\" "` + + #echo "test_config_file = $test_config_file" tags_array=() read -a tags_array <<<"$tags" @@ -238,17 +245,21 @@ function test_compile_and_run() { cd $log_dir { uname -a - #eval $pre_compile_prog - #cmake .. - #rm -fv $exec_file - echo "Executing $compile_prog $compile_args" >> $log_file + echo "Executing $pre_compile_prog" + eval $pre_compile_prog + + if [ "$test_config_file" != "" ]; then + echo "Modifying test_config_file parameters..." + echo "$test_config_file" |xargs -L 1 $OPENAIR_DIR/cmake_targets/autotests/tools/search_repl.py + fi + echo "Executing $compile_prog $compile_args" eval "$compile_prog $compile_args" echo "Copying compilation log files to test case log directory: $log_dir" cp -fvr $OPENAIR_DIR/cmake_targets/log/ $log_dir/compile_log }>> $log_file 2>&1 echo "" >> $log_file 2>&1 #done - + #process the test case if it is that of execution if [ "$class" == "execution" ]; then tags_array_index=0 @@ -437,7 +448,8 @@ for search_expr in "${test_case_array[@]}" else flag_run_test_case=1 fi - + + #We skip this test case if it is not in the group list if [ "$flag_run_test_case" -ne "1" ]; then continue @@ -458,6 +470,7 @@ for search_expr in "${test_case_array[@]}" nruns=`xmlstarlet sel -t -v "/testCaseList/testCase[@id='$search_expr']/nruns" $xml_conf` compile_prog_out=`xmlstarlet sel -t -v "/testCaseList/testCase[@id='$search_expr']/compile_prog_out" $xml_conf` tags=`xmlstarlet sel -t -v "/testCaseList/testCase[@id='$search_expr']/tags" $xml_conf` + test_config_file=`xmlstarlet sel -t -v "/testCaseList/testCase[@id='$search_expr']/test_config_file" $xml_conf` echo "class = $class" echo "name = $name" @@ -497,7 +510,7 @@ for search_expr in "${test_case_array[@]}" test_compile "$name" "$compile_prog" "$compile_prog_args" "$pre_exec" "$pre_exec_args" "$main_exec" "$main_exec_args" "search_array_true[@]" "$search_expr_false" "$nruns" "$pre_compile_prog" "$class" "$compile_prog_out" "$tags" elif [ "$class" == "execution" ]; then $SUDO killall -q oaisim_nos1 - test_compile_and_run "$name" "$compile_prog" "$compile_prog_args" "$pre_exec" "$pre_exec_args" "$main_exec" "$main_exec_args" "search_array_true[@]" "$search_expr_false" "$nruns" "$pre_compile_prog" "$class" "$compile_prog_out" "$tags" "$mypassword" + test_compile_and_run "$name" "$compile_prog" "$compile_prog_args" "$pre_exec" "$pre_exec_args" "$main_exec" "$main_exec_args" "search_array_true[@]" "$search_expr_false" "$nruns" "$pre_compile_prog" "$class" "$compile_prog_out" "$tags" "$mypassword" "$test_config_file" else echo "Unexpected class of test case...Skipping the test case $name ...." fi From 73c79bcca0e82cb510b161fe669b5eafcda82096 Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Fri, 5 Feb 2016 10:49:14 +0100 Subject: [PATCH 197/263] stop Gitlab CI execution when cleanup fails --- cmake_targets/autotests/run_exec_lte-softmodem_tests.py | 2 ++ cmake_targets/autotests/test_case_list.xml | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/cmake_targets/autotests/run_exec_lte-softmodem_tests.py b/cmake_targets/autotests/run_exec_lte-softmodem_tests.py index e68f591a58..f137d128f4 100755 --- a/cmake_targets/autotests/run_exec_lte-softmodem_tests.py +++ b/cmake_targets/autotests/run_exec_lte-softmodem_tests.py @@ -1015,6 +1015,8 @@ class oaiCleanOldProgramThread (threading.Thread): error = error + '\n threadID = ' + str(self.threadID) + '\n threadname = ' + self.threadname + '\n CleanUpOldProgs = ' + self.CleanUpOldProgs + '\n CleanUpAluLteBox = ' + self.CleanUpAluLteBox + '\n ExmimoRfStop = ' + self.ExmimoRfStop + '\n' error = error + traceback.format_exc() print error + print "There is error in cleaning up old programs. The test case execution cannot continue...." + sys.exit(1) # \brief Run parallel threads in all machines for clean up old execution of test cases # \param oai_list list of handlers that can be used to execute programs on remote machines diff --git a/cmake_targets/autotests/test_case_list.xml b/cmake_targets/autotests/test_case_list.xml index 5d5b9703ea..cec3963c4e 100644 --- a/cmake_targets/autotests/test_case_list.xml +++ b/cmake_targets/autotests/test_case_list.xml @@ -8,7 +8,7 @@ develop oaisim* oaisim_nos1* lte-softmodem* lte-softmodem-nos1* mme_gw* run_epc* run_hss* hss hss_sim configure_cots_bandrich_ue* wvdial* iperf iperf_script ping tshark sudo -S -E /opt/ltebox/tools/stop_ltebox -$OPENAIR_DIR/cmake_targets/build_oai -w EXMIMO -c; sudo -S -E $OPENAIR_DIR/cmake_targets/tools/stop_exmimo2; dmesg|tail +$OPENAIR_DIR/cmake_targets/build_oai -w EXMIMO -c; sudo -S -E $OPENAIR_DIR/cmake_targets/tools/stop_exmimo2; uname -a; dmesg|tail 36000 0104+ 015506 015507 015508 015509 015510 015511 015602 015605 015702 015705 015802 015805 016002 016005 016102 016105 016302 016305 3 From ca790b590386384b9016ec24c437c8154d85ca7e Mon Sep 17 00:00:00 2001 From: Aikaterini Date: Fri, 5 Feb 2016 11:10:28 +0100 Subject: [PATCH 198/263] resolve errors after merging with develop / add configuration file for RRH with USRP --- cmake_targets/CMakeLists.txt | 53 +--- targets/ARCH/COMMON/common_lib.c | 7 +- targets/ARCH/ETHERNET/USERSPACE/LIB/eth_raw.c | 16 +- targets/ARCH/ETHERNET/USERSPACE/LIB/eth_udp.c | 37 +-- .../ETHERNET/USERSPACE/LIB/ethernet_lib.c | 33 +- targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp | 96 ++---- .../CONF/enb.band7.tm1.rrh.usrpb210.conf | 189 ++++++++++++ targets/RT/USER/UE_transport_IQ.c | 30 +- targets/RT/USER/eNB_transport_IQ.c | 283 ++++++------------ targets/RT/USER/rrh_gw.c | 7 +- 10 files changed, 375 insertions(+), 376 deletions(-) create mode 100644 targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.rrh.usrpb210.conf diff --git a/cmake_targets/CMakeLists.txt b/cmake_targets/CMakeLists.txt index 4146be799e..630fc68dde 100644 --- a/cmake_targets/CMakeLists.txt +++ b/cmake_targets/CMakeLists.txt @@ -749,56 +749,6 @@ include_directories("${OPENAIR_DIR}") # Utilities Library ################ -if (ENB_AGENT) - # set the version of protobuf messages, V3 not supported yet - add_list1_option(PRPT_VERSION V2 "PRPT MSG protobuf grammar version" V2 V3) - - if (${PRPT_VERSION} STREQUAL "V2") - set (PRPTDIR V2) - elseif (${PRPT_VERSION} STREQUAL "V3") - set (PRPTDIR V3) - endif(${PRPT_VERSION} STREQUAL "V2") - - set(PRPT_MSG_DIR ${OPENAIR2_DIR}/ENB_APP/MESSAGES/${PRPTDIR} ) - set(PRPT_MSG_FILES - ${PRPT_MSG_DIR}/header.proto - ${PRPT_MSG_DIR}/progran.proto - ${PRPT_MSG_DIR}/stats_common.proto - ${PRPT_MSG_DIR}/stats_messages.proto - ) - - set(PRPT_C_DIR ${protobuf_generated_dir}/${PRPTDIR}) - message("calling ${protoc_call} ${PRPT_C_DIR} ${PRPT_MSG_FILES}") - execute_process(COMMAND ${protoc_call} ${PRPT_C_DIR} ${PRPT_MSG_FILES}) - file(GLOB PRPT_source ${PRPT_C_DIR}/*.c) - set(PRPT_OAI_generated - ${PRPT_C_DIR}/header.pb-c.c - ${PRPT_C_DIR}/progran.pb-c.c - ${PRPT_C_DIR}/stats_common.pb-c.c - ${PRPT_C_DIR}/stats_messages.pb-c.c - ) - - file(GLOB prpt_h ${PRPT_C_DIR}/*.h) - set(prpt_h ${prpt_h} ) - - add_library(PRPT_MSG - ${PRPT_OAI_generated} - ${PRPT_source} - ) - - include_directories ("${PRPT_C_DIR}") - - add_library(ASYNC_IF - ${OPENAIR2_DIR}/UTIL/ASYNC_IF/socket_link.c - ${OPENAIR2_DIR}/UTIL/ASYNC_IF/link_manager.c - ${OPENAIR2_DIR}/UTIL/ASYNC_IF/message_queue.c - ) - set(ASYNC_IF_LIB ASYNC_IF) - include_directories(${OPENAIR2_DIR}/UTIL/ASYNC_IF) - -endif() - - add_library(HASHTABLE ${OPENAIR_DIR}/common/utils/collection/hashtable/hashtable.c ${OPENAIR_DIR}/common/utils/collection/hashtable/obj_hashtable.c @@ -955,6 +905,7 @@ set(PHY_SRC ${OPENAIR1_DIR}/PHY/CODING/viterbi_lte.c ${OPENAIR1_DIR}/PHY/INIT/lte_init.c ${OPENAIR1_DIR}/PHY/INIT/lte_parms.c + ${OPENAIR1_DIR}/PHY/INIT/lte_param_init.c ${OPENAIR1_DIR}/PHY/TOOLS/file_output.c ${OPENAIR1_DIR}/PHY/TOOLS/lte_dfts.c ${OPENAIR1_DIR}/PHY/TOOLS/log2_approx.c @@ -1706,7 +1657,7 @@ add_executable(oaisim_nos1 target_include_directories(oaisim_nos1 PUBLIC ${OPENAIR_TARGETS}/SIMU/USER) target_link_libraries (oaisim_nos1 -Wl,--start-group - RRC_LIB X2AP_LIB SECU_CN UTIL HASHTABLE SCHED_LIB PHY LFDS ${MSC_LIB} L2 ${RAL_LIB} SIMU SIMU_ETH SECU_OSA ${ITTI_LIB} ${MIH_LIB} ${ASYNC_IF_LIB} + RRC_LIB X2AP_LIB SECU_CN UTIL HASHTABLE SCHED_LIB PHY LFDS ${MSC_LIB} L2 ${RAL_LIB} SIMU SIMU_ETH SECU_OSA ${ITTI_LIB} ${MIH_LIB} -Wl,--end-group ) target_link_libraries (oaisim_nos1 ${LIBXML2_LIBRARIES} ${LAPACK_LIBRARIES}) diff --git a/targets/ARCH/COMMON/common_lib.c b/targets/ARCH/COMMON/common_lib.c index 7fa71168c8..c5a542fbc7 100644 --- a/targets/ARCH/COMMON/common_lib.c +++ b/targets/ARCH/COMMON/common_lib.c @@ -51,8 +51,11 @@ int set_device(openair0_device *device) { case EXMIMO_DEV: printf("[%s] has loaded EXPRESS MIMO device.\n",((device->host_type == BBU_HOST) ? "BBU": "RRH")); break; - case USRP_DEV: - printf("[%s] has loaded USRP device.\n",((device->host_type == BBU_HOST) ? "BBU": "RRH")); + case USRP_B200_DEV: + printf("[%s] has loaded USRP B200 device.\n",((device->host_type == BBU_HOST) ? "BBU": "RRH")); + break; +case USRP_X300_DEV: + printf("[%s] has loaded USRP X300 device.\n",((device->host_type == BBU_HOST) ? "BBU": "RRH")); break; case BLADERF_DEV: printf("[%s] has loaded BLADERF device.\n",((device->host_type == BBU_HOST) ? "BBU": "RRH")); diff --git a/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_raw.c b/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_raw.c index 195c6baa44..03c876c07f 100644 --- a/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_raw.c +++ b/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_raw.c @@ -72,17 +72,17 @@ int eth_socket_init_raw(openair0_device *device) { int sock_proto=0; if (device->host_type == RRH_HOST ) { /* RRH doesn't know remote MAC(will be retrieved from first packet send from BBU) and remote port(don't care) */ - local_mac = device->openair0_cfg.my_addr; - local_port = device->openair0_cfg.my_port; + local_mac = device->openair0_cfg->my_addr; + local_port = device->openair0_cfg->my_port; remote_mac = malloc(ETH_ALEN); memset(remote_mac,0,ETH_ALEN); remote_port = 0; printf("[%s] local MAC addr %s remote MAC addr %s\n","RRH", local_mac,remote_mac); } else { - local_mac = device->openair0_cfg.my_addr; - local_port = device->openair0_cfg.my_port; - remote_mac = device->openair0_cfg.remote_addr; - remote_port = device->openair0_cfg.remote_port; + local_mac = device->openair0_cfg->my_addr; + local_port = device->openair0_cfg->my_port; + remote_mac = device->openair0_cfg->remote_addr; + remote_port = device->openair0_cfg->remote_port; printf("[%s] local MAC addr %s remote MAC addr %s\n","BBU", local_mac,remote_mac); } @@ -109,7 +109,7 @@ int eth_socket_init_raw(openair0_device *device) { local_addr[Mod_id].sll_family = AF_PACKET; local_addr[Mod_id].sll_ifindex = if_index[Mod_id].ifr_ifindex; /* hear traffic from specific protocol*/ - local_addr[Mod_id].sll_protocol = htons((short)device->openair0_cfg.my_port); + local_addr[Mod_id].sll_protocol = htons((short)device->openair0_cfg->my_port); local_addr[Mod_id].sll_halen = ETH_ALEN; local_addr[Mod_id].sll_pkttype = PACKET_OTHERHOST; addr_len[Mod_id] = sizeof(struct sockaddr_ll); @@ -122,7 +122,7 @@ int eth_socket_init_raw(openair0_device *device) { /* Construct the Ethernet header */ ether_aton_r(local_mac, (struct ether_addr *)(&(eh.ether_shost))); ether_aton_r(remote_mac, (struct ether_addr *)(&(eh.ether_dhost))); - eh.ether_type = htons((short)device->openair0_cfg.my_port); + eh.ether_type = htons((short)device->openair0_cfg->my_port); printf("[%s] binding mod_%d to hardware address %x:%x:%x:%x:%x:%x\n",((device->host_type == BBU_HOST) ? "BBU": "RRH"),Mod_id,eh.ether_shost[0],eh.ether_shost[1],eh.ether_shost[2],eh.ether_shost[3],eh.ether_shost[4],eh.ether_shost[5]); diff --git a/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_udp.c b/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_udp.c index 393c82d900..27a8db7566 100644 --- a/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_udp.c +++ b/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_udp.c @@ -71,18 +71,18 @@ int addr_len[MAX_INST]; int sock_type=0; int sock_proto=0; int enable=1; - + if (device->host_type == RRH_HOST ) { - local_ip = device->openair0_cfg.my_addr; - local_port = device->openair0_cfg.my_port; + local_ip = device->openair0_cfg->my_addr; + local_port = device->openair0_cfg->my_port; remote_ip = "0.0.0.0"; remote_port = 0; printf("[%s] local ip addr %s port %d\n", "RRH", local_ip, local_port); } else { - local_ip = device->openair0_cfg.my_addr; - local_port = device->openair0_cfg.my_port; - remote_ip = device->openair0_cfg.remote_addr; - remote_port = device->openair0_cfg.remote_port; + local_ip = device->openair0_cfg->my_addr; + local_port = device->openair0_cfg->my_port; + remote_ip = device->openair0_cfg->remote_addr; + remote_port = device->openair0_cfg->remote_port; printf("[%s] local ip addr %s port %d\n","BBU", local_ip, local_port); } @@ -123,22 +123,17 @@ int addr_len[MAX_INST]; } /* apply additional configuration */ - //ethernet_tune (device,MTU_SIZE,UDP_PACKET_SIZE_BYTES(device->openair0_cfg.samples_per_packet)); + //ethernet_tune (device,MTU_SIZE,UDP_PACKET_SIZE_BYTES(device->openair0_cfg->samples_per_packet)); - /* if RRH, then I am the server, so bind */ - if (device->host_type == RRH_HOST) { + /* want to receive -> so bind */ if (bind(eth->sockfd[Mod_id],(struct sockaddr *)&local_addr[Mod_id],addr_len[Mod_id])<0) { perror("ETHERNET: Cannot bind to socket"); exit(0); } else { printf("[%s] binding mod_%d to %s:%d\n","RRH",Mod_id,str_local,ntohs(local_addr[Mod_id].sin_port)); } - /* if BBU, then I am a client, so connect */ - } else { - printf("[%s] Connecting to %s:%d\n","BBU",str_remote,ntohs(dest_addr[Mod_id].sin_port)); - } - - + + printf("ssssssssssssssss\n"); return 0; } @@ -359,14 +354,14 @@ int eth_get_dev_conf_udp(openair0_device *device) { /* get remote ip address and port */ /* inet_ntop(AF_INET, &(dest_addr[Mod_id].sin_addr), str1, INET_ADDRSTRLEN); */ - /* device->openair0_cfg.remote_port =ntohs(dest_addr[Mod_id].sin_port); */ - /* device->openair0_cfg.remote_addr =str1; */ + /* device->openair0_cfg->remote_port =ntohs(dest_addr[Mod_id].sin_port); */ + /* device->openair0_cfg->remote_addr =str1; */ /* /\* restore local ip address and port *\/ */ /* inet_ntop(AF_INET, &(local_addr[Mod_id].sin_addr), str, INET_ADDRSTRLEN); */ - /* device->openair0_cfg.my_port =ntohs(local_addr[Mod_id].sin_port); */ - /* device->openair0_cfg.my_addr =str; */ + /* device->openair0_cfg->my_port =ntohs(local_addr[Mod_id].sin_port); */ + /* device->openair0_cfg->my_addr =str; */ - /* printf("[RRH] mod_%d socket %d connected to BBU %s:%d %s:%d\n", Mod_id, eth->sockfd[Mod_id],str1, device->openair0_cfg.remote_port, str, device->openair0_cfg.my_port); */ + /* printf("[RRH] mod_%d socket %d connected to BBU %s:%d %s:%d\n", Mod_id, eth->sockfd[Mod_id],str1, device->openair0_cfg->remote_port, str, device->openair0_cfg->my_port); */ return 0; } diff --git a/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c b/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c index 5d54136ce0..bdce8dbf5d 100644 --- a/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c +++ b/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c @@ -72,7 +72,7 @@ int trx_eth_start(openair0_device *device) { if(eth_get_dev_conf_raw(device)!=0) return -1; } /* adjust MTU wrt number of samples per packet */ - if(ethernet_tune (device,MTU_SIZE,RAW_PACKET_SIZE_BYTES(device->openair0_cfg.samples_per_packet))!=0) return -1; + if(ethernet_tune (device,MTU_SIZE,RAW_PACKET_SIZE_BYTES(device->openair0_cfg->samples_per_packet))!=0) return -1; } else { if (eth_socket_init_udp(device)!=0) return -1; /* RRH gets openair0 device configuration - BBU sets openair0 device configuration*/ @@ -82,7 +82,7 @@ int trx_eth_start(openair0_device *device) { if(eth_get_dev_conf_udp(device)!=0) return -1; } /* adjust MTU wrt number of samples per packet */ - if(ethernet_tune (device,MTU_SIZE,UDP_PACKET_SIZE_BYTES(device->openair0_cfg.samples_per_packet))!=0) return -1; + if(ethernet_tune (device,MTU_SIZE,UDP_PACKET_SIZE_BYTES(device->openair0_cfg->samples_per_packet))!=0) return -1; } return 0; @@ -93,7 +93,7 @@ void trx_eth_end(openair0_device *device) { eth_state_t *eth = (eth_state_t*)device->priv; int Mod_id = device->Mod_id; - /*destroys socket only for the processes that call the eth_end fuction-- shutdown() for beaking the pipe */ + /* destroys socket only for the processes that call the eth_end fuction-- shutdown() for beaking the pipe */ if ( close(eth->sockfd[Mod_id]) <0 ) { perror("ETHERNET: Failed to close socket"); exit(0); @@ -177,7 +177,7 @@ int ethernet_tune(openair0_device *device, unsigned int option, int value) { if (1==0) { /***************** get working interface name ***************************/ /* convert ascii ip address from config file to network binary format */ - inet_aton(device->openair0_cfg.my_addr, &ia); + inet_aton(device->openair0_cfg->my_addr, &ia); /* look for the interface used, we have its ip address get info on all our network interfaces*/ ids = if_nameindex(); /* loop on these network interfaces */ @@ -201,7 +201,7 @@ int ethernet_tune(openair0_device *device, unsigned int option, int value) { } if_freenameindex(ids); if( if_name == NULL) { - printf("Unable to find interface name for %s\n",device->openair0_cfg.my_addr); + printf("Unable to find interface name for %s\n",device->openair0_cfg->my_addr); return -1; } eth->if_name[Mod_id]=if_name; @@ -339,12 +339,9 @@ int transport_init(openair0_device *device, openair0_config_t *openair0_cfg, cha eth_state_t *eth = (eth_state_t*)malloc(sizeof(eth_state_t)); memset(eth, 0, sizeof(eth_state_t)); - int card = 0; - /*hardcoded!!!!*/ eth->flags = ETH_RAW_MODE; - eth->buffer_size = (unsigned int)openair0_cfg[card].samples_per_packet*sizeof(int32_t); - + printf("[ETHERNET]: Initializing openair0_device for %s ...\n", ((device->host_type == BBU_HOST) ? "BBU": "RRH")); device->Mod_id = num_devices_eth++; device->transp_type = ETHERNET_TP; @@ -370,7 +367,7 @@ int transport_init(openair0_device *device, openair0_config_t *openair0_cfg, cha device->priv = eth; openair0_cfg->iq_txshift = 5; openair0_cfg->iq_rxrescale = 15; - memcpy((void*)&device->openair0_cfg,(void*)openair0_cfg,sizeof(openair0_config_t)); + memcpy((void*)device->openair0_cfg,(void*)openair0_cfg,sizeof(openair0_config_t)); return 0; } @@ -407,14 +404,14 @@ void dump_dev(openair0_device *device) { eth_state_t *eth = (eth_state_t*)device->priv; - printf("Ethernet device interface %i configuration:\n" ,device->openair0_cfg.Mod_id); - printf(" Log level is %i :\n" ,device->openair0_cfg.log_level); + printf("Ethernet device interface %i configuration:\n" ,device->openair0_cfg->Mod_id); + printf(" Log level is %i :\n" ,device->openair0_cfg->log_level); printf(" RB number: %i, sample rate: %lf \n" , - device->openair0_cfg.num_rb_dl, device->openair0_cfg.sample_rate); - printf(" Delay: %i, Forward samples: %u \n" , - device->openair0_cfg.tx_delay, device->openair0_cfg.tx_forward_nsamps); + device->openair0_cfg->num_rb_dl, device->openair0_cfg->sample_rate); + printf(" Scheduling_advance: %i, Sample_advance: %u \n" , + device->openair0_cfg->tx_scheduling_advance, device->openair0_cfg->tx_sample_advance); printf(" BBU configured for %i tx/%i rx channels)\n", - device->openair0_cfg.tx_num_channels,device->openair0_cfg.rx_num_channels); + device->openair0_cfg->tx_num_channels,device->openair0_cfg->rx_num_channels); printf(" Running flags: %s %s %s\n", ((eth->flags & ETH_RAW_MODE) ? "RAW socket mode - ":""), ((eth->flags & ETH_UDP_MODE) ? "UDP socket mode - ":""), @@ -425,14 +422,14 @@ void dump_dev(openair0_device *device) { void inline dump_txcounters(openair0_device *device) { eth_state_t *eth = (eth_state_t*)device->priv; - printf(" Ethernet device interface %i, tx counters:\n" ,device->openair0_cfg.Mod_id); + printf(" Ethernet device interface %i, tx counters:\n" ,device->openair0_cfg->Mod_id); printf(" Sent packets: %llu send errors: %i\n", eth->tx_count, eth->num_tx_errors); } void inline dump_rxcounters(openair0_device *device) { eth_state_t *eth = (eth_state_t*)device->priv; - printf(" Ethernet device interface %i rx counters:\n" ,device->openair0_cfg.Mod_id); + printf(" Ethernet device interface %i rx counters:\n" ,device->openair0_cfg->Mod_id); printf(" Received packets: %llu missed packets errors: %i\n", eth->rx_count, eth->num_underflows); } diff --git a/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp b/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp index d72b905696..95df41562c 100644 --- a/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp +++ b/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp @@ -172,7 +172,7 @@ static int trx_usrp_read(openair0_device *device, openair0_timestamp *ptimestamp #endif - if (device->type == USRP_B200_IF) { + if (device->type == USRP_B200_DEV) { if (cc>1) { // receive multiple channels (e.g. RF A and RF B) std::vector buff_ptrs; @@ -198,7 +198,7 @@ static int trx_usrp_read(openair0_device *device, openair0_timestamp *ptimestamp #endif } } - } else if (device->type == USRP_X300_IF) { + } else if (device->type == USRP_X300_DEV) { if (cc>1) { // receive multiple channels (e.g. RF A and RF B) std::vector buff_ptrs; @@ -395,15 +395,9 @@ extern "C" { // Initialize USRP device -<<<<<<< HEAD - std::string args = "type=b200"; - + std::string args = "type=b200"; + - uhd::device_addrs_t device_adds = uhd::device::find(args); - size_t i; - - printf("Checking for USRPs\n"); -======= uhd::device_addrs_t device_adds = uhd::device::find(args); size_t i; @@ -413,29 +407,19 @@ extern "C" { sscanf(uhd::get_version_string().c_str(),"%d.%d.%d",&vers,&subvers,&subsubvers); printf("Checking for USRPs : UHD %s (%d.%d.%d)\n",uhd::get_version_string().c_str(),vers,subvers,subsubvers); ->>>>>>> acd607fa359709ba16a83437f483c230cee1d9b0 if(device_adds.size() == 0) { double usrp_master_clock = 184.32e6; - + std::string args = "type=x300"; // workaround for an api problem, master clock has to be set with the constructor not via set_master_clock_rate args += boost::str(boost::format(",master_clock_rate=%f") % usrp_master_clock); uhd::device_addrs_t device_adds = uhd::device::find(args); - + if(device_adds.size() == 0) -<<<<<<< HEAD - { - std::cerr<<"No USRP Device Found. " << std::endl; - free(s); - return -1; - - } - -======= { std::cerr<<"No USRP Device Found. " << std::endl; free(s); @@ -444,17 +428,16 @@ extern "C" { } ->>>>>>> acd607fa359709ba16a83437f483c230cee1d9b0 printf("Found USRP X300\n"); s->usrp = uhd::usrp::multi_usrp::make(args); // s->usrp->set_rx_subdev_spec(rx_subdev); // s->usrp->set_tx_subdev_spec(tx_subdev); - + // lock mboard clocks s->usrp->set_clock_source("internal"); //Setting device type to USRP X300/X310 - device->type=USRP_X300_IF; + device->type=USRP_X300_DEV; // this is not working yet, master clock has to be set via constructor // set master clock rate and sample rate for tx & rx for streaming @@ -511,11 +494,8 @@ extern "C" { // s->usrp->set_clock_source("internal"); // set master clock rate and sample rate for tx & rx for streaming - device->type = USRP_B200_IF; + device->type = USRP_B200_DEV; -<<<<<<< HEAD - -======= if ((vers == 3) && (subvers == 9) && (subsubvers>=2)) { openair0_cfg[0].rx_gain_calib_table = calib_table_b210; @@ -574,20 +554,14 @@ extern "C" { } } ->>>>>>> acd607fa359709ba16a83437f483c230cee1d9b0 for(i=0;iusrp->get_rx_num_channels();i++) { if (iusrp->set_rx_rate(openair0_cfg[0].sample_rate,i); s->usrp->set_rx_bandwidth(openair0_cfg[0].rx_bw,i); printf("Setting rx freq/gain on channel %lu/%lu : BW %f (readback %f)\n",i,s->usrp->get_rx_num_channels(),openair0_cfg[0].rx_bw/1e6,s->usrp->get_rx_bandwidth(i)/1e6); s->usrp->set_rx_freq(openair0_cfg[0].rx_freq[i],i); -<<<<<<< HEAD - set_rx_gain_offset(&openair0_cfg[0],i); - -======= set_rx_gain_offset(&openair0_cfg[0],i,bw_gain_adjust); ->>>>>>> acd607fa359709ba16a83437f483c230cee1d9b0 ::uhd::gain_range_t gain_range = s->usrp->get_rx_gain_range(i); // limit to maximum gain if (openair0_cfg[0].rx_gain[i]-openair0_cfg[0].rx_gain_offset[i] > gain_range.stop()) { @@ -610,11 +584,11 @@ extern "C" { s->usrp->set_tx_gain(openair0_cfg[0].tx_gain[i],i); } } - - + + // display USRP settings std::cout << boost::format("Actual master clock: %fMHz...") % (s->usrp->get_master_clock_rate()/1e6) << std::endl; - + // create tx & rx streamer uhd::stream_args_t stream_args_rx("sc16", "sc16"); //stream_args_rx.args["spp"] = str(boost::format("%d") % 2048);//(openair0_cfg[0].rx_num_channels*openair0_cfg[0].samples_per_packet)); @@ -623,17 +597,18 @@ extern "C" { s->rx_stream = s->usrp->get_rx_stream(stream_args_rx); std::cout << boost::format("rx_max_num_samps %u") % (s->rx_stream->get_max_num_samps()) << std::endl; //openair0_cfg[0].samples_per_packet = s->rx_stream->get_max_num_samps(); - + uhd::stream_args_t stream_args_tx("sc16", "sc16"); //stream_args_tx.args["spp"] = str(boost::format("%d") % 2048);//(openair0_cfg[0].tx_num_channels*openair0_cfg[0].samples_per_packet)); for (i = 0; itx_stream = s->usrp->get_tx_stream(stream_args_tx); std::cout << boost::format("tx_max_num_samps %u") % (s->tx_stream->get_max_num_samps()) << std::endl; - + s->usrp->set_time_now(uhd::time_spec_t(0.0)); - + + for (i=0;iusrp->get_rx_antenna(i)) << std::endl; } } - + for (i=0;iusrp->get_tx_rate(i)/1e6) << std::endl; @@ -655,11 +631,10 @@ extern "C" { std::cout << boost::format("Actual TX antenna: %s...") % (s->usrp->get_tx_antenna(i)) << std::endl; } } - + std::cout << boost::format("Device timestamp: %f...") % (s->usrp->get_time_now().get_real_secs()) << std::endl; device->priv = s; - device->type = USRP_DEV; device->trx_start_func = trx_usrp_start; device->trx_write_func = trx_usrp_write; device->trx_read_func = trx_usrp_read; @@ -673,37 +648,12 @@ extern "C" { s->sample_rate = openair0_cfg[0].sample_rate; // TODO: // init tx_forward_nsamps based usrp_time_offset ex - /*if(is_equal(s->sample_rate, (double)30.72e6)) + if(is_equal(s->sample_rate, (double)30.72e6)) s->tx_forward_nsamps = 176; - if(is_equal(s->sample_rate, (double)15.36e6)) + if(is_equal(s->sample_rate, (double)15.36e6)) s->tx_forward_nsamps = 90; if(is_equal(s->sample_rate, (double)7.68e6)) - s->tx_forward_nsamps = 50;*/ - /* move device specific parameters from lte-softmodem.c here */ - if(is_equal(s->sample_rate, (double)30.72e6)) { - openair0_cfg->tx_delay = 8; - s->tx_forward_nsamps = 175; - openair0_cfg->tx_forward_nsamps = 175; - } - if(is_equal(s->sample_rate, (double)15.36e6)) { - openair0_cfg->tx_delay = 5; - s->tx_forward_nsamps = 95; - openair0_cfg->tx_forward_nsamps = 95; - } - if(is_equal(s->sample_rate, (double)7.68e6)) { - openair0_cfg->tx_delay = 5; - s->tx_forward_nsamps = 70; - openair0_cfg->tx_forward_nsamps = 70; - } - if(is_equal(s->sample_rate, (double)1.92e6)) { - openair0_cfg->tx_delay = 8; - s->tx_forward_nsamps = 40; - openair0_cfg->tx_forward_nsamps = 40; - } - openair0_cfg->iq_txshift= 5; - openair0_cfg->iq_rxrescale = 15; - printf("check params %d:%d",openair0_cfg->tx_forward_nsamps, openair0_cfg->tx_delay); - + s->tx_forward_nsamps = 50; return 0; } } diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.rrh.usrpb210.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.rrh.usrpb210.conf new file mode 100644 index 0000000000..dd138c23ac --- /dev/null +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.rrh.usrpb210.conf @@ -0,0 +1,189 @@ +Active_eNBs = ( "eNB_Eurecom_LTEBox"); +# Asn1_verbosity, choice in: none, info, annoying +Asn1_verbosity = "none"; + +eNBs = +( + { + ////////// Identification parameters: + eNB_ID = 0xe00; + + cell_type = "CELL_MACRO_ENB"; + + eNB_name = "eNB_Eurecom_LTEBox"; + + // Tracking area code, 0x0000 and 0xfffe are reserved values + tracking_area_code = "1"; + + mobile_country_code = "208"; + + mobile_network_code = "92"; + + ////////// Physical parameters: + + component_carriers = ( + { + frame_type = "FDD"; + tdd_config = 3; + tdd_config_s = 0; + prefix_type = "NORMAL"; + eutra_band = 7; + downlink_frequency = 2680000000L; + uplink_frequency_offset = -120000000; + Nid_cell = 0; + N_RB_DL = 25; + Nid_cell_mbsfn = 0; + nb_antennas_tx = 1; + nb_antennas_rx = 1; + tx_gain = 90; + rx_gain = 120; + prach_root = 0; + prach_config_index = 0; + prach_high_speed = "DISABLE"; + prach_zero_correlation = 1; + prach_freq_offset = 2; + pucch_delta_shift = 1; + pucch_nRB_CQI = 1; + pucch_nCS_AN = 0; + pucch_n1_AN = 32; + pdsch_referenceSignalPower = -29; + pdsch_p_b = 0; + pusch_n_SB = 1; + pusch_enable64QAM = "DISABLE"; + pusch_hoppingMode = "interSubFrame"; + pusch_hoppingOffset = 0; + pusch_groupHoppingEnabled = "ENABLE"; + pusch_groupAssignment = 0; + pusch_sequenceHoppingEnabled = "DISABLE"; + pusch_nDMRS1 = 1; + phich_duration = "NORMAL"; + phich_resource = "ONESIXTH"; + srs_enable = "DISABLE"; + /* srs_BandwidthConfig =; + srs_SubframeConfig =; + srs_ackNackST =; + srs_MaxUpPts =;*/ + + pusch_p0_Nominal = -90; + pusch_alpha = "AL1"; + pucch_p0_Nominal = -96; + msg3_delta_Preamble = 6; + pucch_deltaF_Format1 = "deltaF2"; + pucch_deltaF_Format1b = "deltaF3"; + pucch_deltaF_Format2 = "deltaF0"; + pucch_deltaF_Format2a = "deltaF0"; + pucch_deltaF_Format2b = "deltaF0"; + + rach_numberOfRA_Preambles = 64; + rach_preamblesGroupAConfig = "DISABLE"; + /* + rach_sizeOfRA_PreamblesGroupA = ; + rach_messageSizeGroupA = ; + rach_messagePowerOffsetGroupB = ; + */ + rach_powerRampingStep = 4; + rach_preambleInitialReceivedTargetPower = -108; + rach_preambleTransMax = 10; + rach_raResponseWindowSize = 10; + rach_macContentionResolutionTimer = 48; + rach_maxHARQ_Msg3Tx = 4; + + pcch_default_PagingCycle = 128; + pcch_nB = "oneT"; + bcch_modificationPeriodCoeff = 2; + ue_TimersAndConstants_t300 = 1000; + ue_TimersAndConstants_t301 = 1000; + ue_TimersAndConstants_t310 = 1000; + ue_TimersAndConstants_t311 = 10000; + ue_TimersAndConstants_n310 = 20; + ue_TimersAndConstants_n311 = 1; + + } + ); + + + srb1_parameters : + { + # timer_poll_retransmit = (ms) [5, 10, 15, 20,... 250, 300, 350, ... 500] + timer_poll_retransmit = 80; + + # timer_reordering = (ms) [0,5, ... 100, 110, 120, ... ,200] + timer_reordering = 35; + + # timer_reordering = (ms) [0,5, ... 250, 300, 350, ... ,500] + timer_status_prohibit = 0; + + # poll_pdu = [4, 8, 16, 32 , 64, 128, 256, infinity(>10000)] + poll_pdu = 4; + + # poll_byte = (kB) [25,50,75,100,125,250,375,500,750,1000,1250,1500,2000,3000,infinity(>10000)] + poll_byte = 99999; + + # max_retx_threshold = [1, 2, 3, 4 , 6, 8, 16, 32] + max_retx_threshold = 4; + } + + # ------- SCTP definitions + SCTP : + { + # Number of streams to use in input/output + SCTP_INSTREAMS = 2; + SCTP_OUTSTREAMS = 2; + }; + + + ////////// MME parameters: + mme_ip_address = ( { ipv4 = "192.168.12.170"; + ipv6 = "192:168:30::17"; + active = "yes"; + preference = "ipv4"; + } + ); + +rrh_gw_config = ( + { + udp = 1; + raw = 0; + active = 1; + #remote_addr = "169.254.8.28"; + #remote_addr = "127.0.0.1"; + #remote_addr = "74:d4:35:cc:88:45"; + #local_addr = "169.254.7.91"; + #local_addr = "127.0.0.1"; + #local_addr = "d4:be:d9:22:0a:ac"; + local_address = "192.168.12.242" ; + remote_address = "192.168.12.31" ; + local_port = 50000; + remote_port = 50001; +} +); + + NETWORK_INTERFACES : + { + ENB_INTERFACE_NAME_FOR_S1_MME = "eth0"; + ENB_IPV4_ADDRESS_FOR_S1_MME = "192.168.12.216/24"; + + ENB_INTERFACE_NAME_FOR_S1U = "eth0"; + ENB_IPV4_ADDRESS_FOR_S1U = "192.168.12.216/24"; + ENB_PORT_FOR_S1U = 2152; # Spec 2152 + }; + + log_config : + { + global_log_level ="info"; + global_log_verbosity ="medium"; + hw_log_level ="info"; + hw_log_verbosity ="medium"; + phy_log_level ="info"; + phy_log_verbosity ="medium"; + mac_log_level ="info"; + mac_log_verbosity ="high"; + rlc_log_level ="info"; + rlc_log_verbosity ="medium"; + pdcp_log_level ="info"; + pdcp_log_verbosity ="medium"; + rrc_log_level ="info"; + rrc_log_verbosity ="medium"; + }; + } +); diff --git a/targets/RT/USER/UE_transport_IQ.c b/targets/RT/USER/UE_transport_IQ.c index 055b45ba72..a45b8ba43b 100644 --- a/targets/RT/USER/UE_transport_IQ.c +++ b/targets/RT/USER/UE_transport_IQ.c @@ -148,7 +148,7 @@ void *rrh_proc_UE_thread(void * arg) { unsigned int samples_per_frame=0; rrh_module_t *dev=(rrh_module_t *)arg; - samples_per_frame= dev->eth_dev.openair0_cfg.samples_per_frame; + samples_per_frame= dev->eth_dev.openair0_cfg->samples_per_frame; AssertFatal(samples_per_frame <=0, "invalide samples_per_frame !%u\n",samples_per_frame); time_req.tv_sec = 0; @@ -260,7 +260,7 @@ void *rrh_UE_thread(void *arg) { void *tmp; unsigned int samples_per_frame=0; - samples_per_frame= dev->eth_dev.openair0_cfg.samples_per_frame; + samples_per_frame= dev->eth_dev.openair0_cfg->samples_per_frame; time_req_1us.tv_sec = 0; time_req_1us.tv_nsec = 1000; @@ -269,26 +269,26 @@ void *rrh_UE_thread(void *arg) { cmd=dev->eth_dev.trx_start_func(&dev->eth_dev); /* allocate memory for TX/RX buffers */ - rx_buffer_UE = (int32_t**)malloc16(dev->eth_dev.openair0_cfg.rx_num_channels*sizeof(int32_t*)); - tx_buffer_UE = (int32_t**)malloc16(dev->eth_dev.openair0_cfg.tx_num_channels*sizeof(int32_t*)); + rx_buffer_UE = (int32_t**)malloc16(dev->eth_dev.openair0_cfg->rx_num_channels*sizeof(int32_t*)); + tx_buffer_UE = (int32_t**)malloc16(dev->eth_dev.openair0_cfg->tx_num_channels*sizeof(int32_t*)); - for (i=0; ieth_dev.openair0_cfg.rx_num_channels; i++) { + for (i=0; ieth_dev.openair0_cfg->rx_num_channels; i++) { tmp=(void *)malloc(sizeof(int32_t)*(samples_per_frame+4)); memset(tmp,0,sizeof(int32_t)*(samples_per_frame+4)); rx_buffer_UE[i]=(tmp+4*sizeof(int32_t)); } - for (i=0; ieth_dev.openair0_cfg.tx_num_channels; i++) { + for (i=0; ieth_dev.openair0_cfg->tx_num_channels; i++) { tmp=(void *)malloc(sizeof(int32_t)*(samples_per_frame+4)); memset(tmp,0,sizeof(int32_t)*(samples_per_frame+4)); tx_buffer_UE[i]=(tmp+4*sizeof(int32_t)); } - printf("Client %s:%d is connected (DL_RB=%d) rt=%d|%d. \n" , dev->eth_dev.openair0_cfg.remote_addr, - dev->eth_dev.openair0_cfg.remote_port, - dev->eth_dev.openair0_cfg.num_rb_dl, - dev->eth_dev.openair0_cfg.rx_num_channels, - dev->eth_dev.openair0_cfg.tx_num_channels); + printf("Client %s:%d is connected (DL_RB=%d) rt=%d|%d. \n" , dev->eth_dev.openair0_cfg->remote_addr, + dev->eth_dev.openair0_cfg->remote_port, + dev->eth_dev.openair0_cfg->num_rb_dl, + dev->eth_dev.openair0_cfg->rx_num_channels, + dev->eth_dev.openair0_cfg->tx_num_channels); if (cmd==START_CMD) { @@ -348,8 +348,8 @@ void *rrh_UE_rx_thread(void *arg) { openair0_timestamp temp, last_hw_counter=0; antenna_index = 0; - nsamps = dev->eth_dev.openair0_cfg.samples_per_packet; - samples_per_frame = dev->eth_dev.openair0_cfg.samples_per_frame; + nsamps = dev->eth_dev.openair0_cfg->samples_per_packet; + samples_per_frame = dev->eth_dev.openair0_cfg->samples_per_frame; while (rrh_exit == 0) { if (!UE_rx_started) { @@ -492,8 +492,8 @@ void *rrh_UE_tx_thread(void *arg) { unsigned int samples_per_frame=0; antenna_index = 0; - nsamps = dev->eth_dev.openair0_cfg.samples_per_packet; - samples_per_frame = dev->eth_dev.openair0_cfg.samples_per_frame; + nsamps = dev->eth_dev.openair0_cfg->samples_per_packet; + samples_per_frame = dev->eth_dev.openair0_cfg->samples_per_frame; while (rrh_exit == 0) { diff --git a/targets/RT/USER/eNB_transport_IQ.c b/targets/RT/USER/eNB_transport_IQ.c index 8f679befe3..3580e876f6 100644 --- a/targets/RT/USER/eNB_transport_IQ.c +++ b/targets/RT/USER/eNB_transport_IQ.c @@ -127,7 +127,7 @@ static void check_dev_config( rrh_module_t *mod_enb); * \note * @ingroup _oai */ -static void calc_rt_period_ns( openair0_config_t openair0_cfg); +static void calc_rt_period_ns( openair0_config_t *openair0_cfg); @@ -140,122 +140,34 @@ void config_BBU_mod( rrh_module_t *mod_enb, uint8_t RT_flag, uint8_t NRT_flag) { RT_flag_eNB=RT_flag; NRT_flag_eNB=NRT_flag; - + /* init socket and have handshake-like msg with client to exchange parameters */ mod_enb->eth_dev.trx_start_func(&mod_enb->eth_dev);//change port make it plus_id - if (1==0) { - /* if a RF iterface is added to RRH module get the configuration parameters sent from eNB */ -if (mod_enb->devs->type != NONE_DEV ) { + printf("sdfs\n"); - memcpy((void*)&mod_enb->devs->openair0_cfg,(void *)&mod_enb->eth_dev.openair0_cfg,sizeof(openair0_config_t)); - - /* certain parameters have to be updated (calibration related)*/ - if ( mod_enb->devs->type == EXMIMO_DEV ) { - if ( mod_enb->devs->openair0_cfg.num_rb_dl == 100 ) { - mod_enb->devs->openair0_cfg.samples_per_packet = 2048; - mod_enb->devs->openair0_cfg.tx_forward_nsamps = 175; - mod_enb->devs->openair0_cfg.tx_delay = 8; - } - else if ( mod_enb->devs->openair0_cfg.num_rb_dl == 50 ) { - mod_enb->devs->openair0_cfg.samples_per_packet = 2048; - mod_enb->devs->openair0_cfg.tx_forward_nsamps = 95; - mod_enb->devs->openair0_cfg.tx_delay = 5; - } - else if ( mod_enb->devs->openair0_cfg.num_rb_dl == 25 ) { - mod_enb->devs->openair0_cfg.samples_per_packet = 1024; - mod_enb->devs->openair0_cfg.tx_forward_nsamps = 70; - mod_enb->devs->openair0_cfg.tx_delay = 6; - } - else if ( mod_enb->devs->openair0_cfg.num_rb_dl == 6 ) { - mod_enb->devs->openair0_cfg.samples_per_packet = 256; - mod_enb->devs->openair0_cfg.tx_forward_nsamps = 40; - mod_enb->devs->openair0_cfg.tx_delay = 8; + memcpy((void*)mod_enb->devs->openair0_cfg,(void *)mod_enb->eth_dev.openair0_cfg,sizeof(openair0_config_t)); + printf("sdfs\n"); + /* check sanity of configuration parameters and print */ + check_dev_config(mod_enb); + + /* initialize and configure the RF device */ + if (openair0_device_load(mod_enb->devs, mod_enb->devs->openair0_cfg)<0) { + LOG_E(RRH,"Exiting, cannot initialize RF device.\n"); + exit(-1); + } else { + if (mod_enb->devs->type != NONE_DEV) { + /* start RF device */ + if (mod_enb->devs->type == EXMIMO_DEV) { + //call start function for exmino + } else { + if (mod_enb->devs->trx_start_func(mod_enb->devs)!=0) + LOG_E(RRH,"Unable to initiate RF device.\n"); + else + LOG_I(RRH,"RF device has been initiated.\n"); } + } - else if ((mod_enb->devs->type == USRP_B200_IF )||(mod_enb->devs->type == USRP_X300_IF )) { - if ( mod_enb->devs->openair0_cfg.num_rb_dl == 100 ) { - mod_enb->devs->openair0_cfg.samples_per_packet = 2048; - mod_enb->devs->openair0_cfg.tx_forward_nsamps = 175; - mod_enb->devs->openair0_cfg.tx_delay = 8; - } - else if ( mod_enb->devs->openair0_cfg.num_rb_dl == 50 ) { - mod_enb->devs->openair0_cfg.samples_per_packet = 2048; - mod_enb->devs->openair0_cfg.tx_forward_nsamps = 95; - mod_enb->devs->openair0_cfg.tx_delay = 5; - } - else if ( mod_enb->devs->openair0_cfg.num_rb_dl == 25 ) { - mod_enb->devs->openair0_cfg.samples_per_packet = 1024; - mod_enb->devs->openair0_cfg.tx_forward_nsamps = 70; - mod_enb->devs->openair0_cfg.tx_delay = 6; - } - else if ( mod_enb->devs->openair0_cfg.num_rb_dl == 6 ) { - mod_enb->devs->openair0_cfg.samples_per_packet = 256; - mod_enb->devs->openair0_cfg.tx_forward_nsamps = 40; - mod_enb->devs->openair0_cfg.tx_delay = 8; - } - } - else if(mod_enb->devs->type == BLADERF_DEV) { - if ( mod_enb->devs->openair0_cfg.num_rb_dl == 100 ) { - mod_enb->devs->openair0_cfg.samples_per_packet = 2048; - mod_enb->devs->openair0_cfg.tx_forward_nsamps = 175; - mod_enb->devs->openair0_cfg.tx_delay = 8; - } - else if ( mod_enb->devs->openair0_cfg.num_rb_dl == 50 ) { - mod_enb->devs->openair0_cfg.samples_per_packet = 2048; - mod_enb->devs->openair0_cfg.tx_forward_nsamps = 95; - mod_enb->devs->openair0_cfg.tx_delay = 5; - } - else if ( mod_enb->devs->openair0_cfg.num_rb_dl == 25 ) { - mod_enb->devs->openair0_cfg.samples_per_packet = 1024; - mod_enb->devs->openair0_cfg.tx_forward_nsamps = 70; - mod_enb->devs->openair0_cfg.tx_delay = 6; - } - else if ( mod_enb->devs->openair0_cfg.num_rb_dl == 6 ) { - mod_enb->devs->openair0_cfg.samples_per_packet = 256; - mod_enb->devs->openair0_cfg.tx_forward_nsamps = 40; - mod_enb->devs->openair0_cfg.tx_delay = 8; - } - } - - /* check sanity of configuration parameters and print */ - check_dev_config(mod_enb); - - /* initialize and configure the RF device */ - if (openair0_device_load(mod_enb->devs, &mod_enb->devs->openair0_cfg)<0) { - LOG_E(RRH,"Exiting, cannot initialize RF device.\n"); - exit(-1); - } else { - LOG_I(RRH,"RF device has been successfully initialized.\n"); - } - - } - - } else { - - memcpy((void*)&mod_enb->devs->openair0_cfg,(void *)&mod_enb->eth_dev.openair0_cfg,sizeof(openair0_config_t)); - - /* check sanity of configuration parameters and print */ - check_dev_config(mod_enb); - - /* initialize and configure the RF device */ - if (openair0_device_load(mod_enb->devs, &mod_enb->devs->openair0_cfg)<0){ - LOG_E(RRH,"Exiting, cannot initialize RF device.\n"); - exit(-1); - } else { - if (mod_enb->devs->type != NONE_DEV) { - /* start RF device */ - if (mod_enb->devs->type == EXMIMO_DEV) { - //call start function for exmino - } else { - if (mod_enb->devs->trx_start_func(mod_enb->devs)!=0) - LOG_E(RRH,"Unable to initiate RF device.\n"); - else - LOG_I(RRH,"RF device has been initiated.\n"); - } - - } - } - } + } /* create main eNB module thread main_rrh_eNB_thread allocates memory @@ -284,7 +196,7 @@ void *rrh_eNB_thread(void *arg) { void *tmp; unsigned int samples_per_frame=0; - samples_per_frame = dev->eth_dev.openair0_cfg.samples_per_frame; + samples_per_frame = dev->eth_dev.openair0_cfg->samples_per_frame; while (rrh_exit==0) { @@ -296,42 +208,42 @@ void *rrh_eNB_thread(void *arg) { /* allocate memory for TX/RX buffers each antenna port has a TX and a RX buffer each TX and RX buffer is of (samples_per_frame + HEADER_SIZE) samples (size of samples is 4 bytes) */ - rx_buffer_eNB = (int32_t**)malloc16(dev->eth_dev.openair0_cfg.rx_num_channels*sizeof(int32_t*)); - tx_buffer_eNB = (int32_t**)malloc16(dev->eth_dev.openair0_cfg.tx_num_channels*sizeof(int32_t*)); + rx_buffer_eNB = (int32_t**)malloc16(dev->eth_dev.openair0_cfg->rx_num_channels*sizeof(int32_t*)); + tx_buffer_eNB = (int32_t**)malloc16(dev->eth_dev.openair0_cfg->tx_num_channels*sizeof(int32_t*)); LOG_D(RRH,"rx_buffer_eNB address =%p tx_buffer_eNB address =%p \n",rx_buffer_eNB,tx_buffer_eNB); /* rx_buffer_eNB points to the beginning of data */ - for (i=0; ieth_dev.openair0_cfg.rx_num_channels; i++) { + for (i=0; ieth_dev.openair0_cfg->rx_num_channels; i++) { tmp=(void *)malloc16(sizeof(int32_t)*(samples_per_frame + 32)); memset(tmp,0,sizeof(int32_t)*(samples_per_frame + 32)); rx_buffer_eNB[i]=( tmp + (32*sizeof(int32_t)) ); LOG_D(RRH,"i=%d rx_buffer_eNB[i]=%p tmp= %p\n",i,rx_buffer_eNB[i],tmp); } /* tx_buffer_eNB points to the beginning of data */ - for (i=0; ieth_dev.openair0_cfg.tx_num_channels; i++) { + for (i=0; ieth_dev.openair0_cfg->tx_num_channels; i++) { tmp=(void *)malloc16(sizeof(int32_t)*(samples_per_frame + 32)); memset(tmp,0,sizeof(int32_t)*(samples_per_frame + 32)); tx_buffer_eNB[i]=( tmp + (32*sizeof(int32_t)) ); LOG_D(RRH,"i= %d tx_buffer_eNB[i]=%p tmp= %p \n",i,tx_buffer_eNB[i],tmp); } /* dummy initialization for TX/RX buffers */ - for (i=0; ieth_dev.openair0_cfg.rx_num_channels; i++) { + for (i=0; ieth_dev.openair0_cfg->rx_num_channels; i++) { for (j=0; jeth_dev.openair0_cfg.tx_num_channels; i++) { + for (i=0; ieth_dev.openair0_cfg->tx_num_channels; i++) { for (j=0; jeth_dev.openair0_cfg.rx_num_channels*sizeof(int32_t*)); - tx_eNB = (void**)malloc16(dev->eth_dev.openair0_cfg.tx_num_channels*sizeof(int32_t*)); + rx_eNB = (void**)malloc16(dev->eth_dev.openair0_cfg->rx_num_channels*sizeof(int32_t*)); + tx_eNB = (void**)malloc16(dev->eth_dev.openair0_cfg->tx_num_channels*sizeof(int32_t*)); /* init mutexes */ - for (i=0; ieth_dev.openair0_cfg.tx_num_channels; i++) { + for (i=0; ieth_dev.openair0_cfg->tx_num_channels; i++) { pthread_mutex_init(&sync_eNB_mutex[i],NULL); pthread_cond_init(&sync_eNB_cond[i],NULL); } @@ -444,10 +356,10 @@ void *rrh_eNB_rx_thread(void *arg) { time_req_1us.tv_sec = 0; time_req_1us.tv_nsec =1000; //time_req_1us.tv_nsec = (int)rt_period/2;--->granularity issue - spp_eth = dev->eth_dev.openair0_cfg.samples_per_packet; - spp_rf = dev->devs->openair0_cfg.samples_per_packet; + spp_eth = dev->eth_dev.openair0_cfg->samples_per_packet; + spp_rf = dev->devs->openair0_cfg->samples_per_packet; - samples_per_frame = dev->eth_dev.openair0_cfg.samples_per_frame; + samples_per_frame = dev->eth_dev.openair0_cfg->samples_per_frame; samples_per_subframe = (unsigned int)samples_per_frame/10; loopback = dev->loopback; measurements = dev->measurements; @@ -520,7 +432,7 @@ void *rrh_eNB_rx_thread(void *arg) { } } - for (i=0; ieth_dev.openair0_cfg.rx_num_channels; i++) { + for (i=0; ieth_dev.openair0_cfg->rx_num_channels; i++) { rx_eNB[i] = (void*)&rx_buffer_eNB[i][rx_pos]; LOG_D(RRH," rx_eNB[i]=%p rx_buffer_eNB[i][rx_pos]=%p ,rx_pos=%d, i=%d ts=%d\n",rx_eNB[i],&rx_buffer_eNB[i][rx_pos],rx_pos,i,timestamp_rx); } @@ -532,7 +444,7 @@ void *rrh_eNB_rx_thread(void *arg) { ×tamp_rx, rx_eNB, spp_rf, - dev->devs->openair0_cfg.rx_num_channels + dev->devs->openair0_cfg->rx_num_channels )<0) { perror("RRH eNB : USRP read"); } @@ -545,7 +457,7 @@ void *rrh_eNB_rx_thread(void *arg) { timestamp_rx, rx_eNB, spp_eth, - dev->eth_dev.openair0_cfg.rx_num_channels, + dev->eth_dev.openair0_cfg->rx_num_channels, 0))<0) { perror("RRH eNB : ETHERNET write"); } @@ -667,13 +579,12 @@ void *rrh_eNB_tx_thread(void *arg) { time_req_1us.tv_sec = 1; time_req_1us.tv_nsec = 0; - spp_eth = dev->eth_dev.openair0_cfg.samples_per_packet; - spp_rf = dev->devs->openair0_cfg.samples_per_packet; - samples_per_frame = dev->eth_dev.openair0_cfg.samples_per_frame; + spp_eth = dev->eth_dev.openair0_cfg->samples_per_packet; + spp_rf = dev->devs->openair0_cfg->samples_per_packet; + samples_per_frame = dev->eth_dev.openair0_cfg->samples_per_frame; samples_per_subframe = (unsigned int)samples_per_frame/10; tx_pos=0; - //tx_pos_rf=spp_rf*dev->devs->openair0_cfg.tx_delay; - + loopback = dev->loopback; measurements = dev->measurements; @@ -695,7 +606,7 @@ void *rrh_eNB_tx_thread(void *arg) { VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TX_PCK, pck_tx ); if (measurements == 1 ) clock_gettime(CLOCK_MONOTONIC,&time1); - for (i=0; ieth_dev.openair0_cfg.tx_num_channels; i++) tx_eNB[i] = (void*)&tx_buffer_eNB[i][tx_pos]; //RF!!!!! + for (i=0; ieth_dev.openair0_cfg->tx_num_channels; i++) tx_eNB[i] = (void*)&tx_buffer_eNB[i][tx_pos]; VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TXCNT, tx_pos ); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ, 1 ); @@ -705,7 +616,7 @@ void *rrh_eNB_tx_thread(void *arg) { ×tamp_tx, tx_eNB, spp_eth, - dev->eth_dev.openair0_cfg.tx_num_channels))<0) { + dev->eth_dev.openair0_cfg->tx_num_channels))<0) { perror("RRH eNB : ETHERNET read"); } VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ, 0 ); @@ -718,7 +629,7 @@ void *rrh_eNB_tx_thread(void *arg) { timestamp_tx, tx_eNB, spp_rf, - dev->devs->openair0_cfg.tx_num_channels, + dev->devs->openair0_cfg->tx_num_channels, 1)<0){ perror("RRH eNB : USRP write"); } @@ -770,9 +681,9 @@ void *rrh_eNB_tx_thread(void *arg) { } -static void calc_rt_period_ns( openair0_config_t openair0_cfg) { +static void calc_rt_period_ns( openair0_config_t *openair0_cfg) { - rt_period= (double)(openair0_cfg.samples_per_packet/(openair0_cfg.samples_per_frame/10.0)*1000000); + rt_period= (double)(openair0_cfg->samples_per_packet/(openair0_cfg->samples_per_frame/10.0)*1000000); AssertFatal(rt_period > 0, "Invalid rt period !%u\n", rt_period); LOG_I(RRH,"[eNB] Real time period is set to %u ns\n", rt_period); } @@ -780,57 +691,57 @@ static void calc_rt_period_ns( openair0_config_t openair0_cfg) { static void check_dev_config( rrh_module_t *mod_enb) { - AssertFatal( (mod_enb->devs->openair0_cfg.num_rb_dl==100 || mod_enb->devs->openair0_cfg.num_rb_dl==50 || mod_enb->devs->openair0_cfg.num_rb_dl==25 || mod_enb->devs->openair0_cfg.num_rb_dl==6) , "Invalid number of resource blocks! %d\n", mod_enb->devs->openair0_cfg.num_rb_dl); - AssertFatal( mod_enb->devs->openair0_cfg.samples_per_frame > 0 , "Invalid number of samples per frame! %d\n",mod_enb->devs->openair0_cfg.samples_per_frame); - AssertFatal( mod_enb->devs->openair0_cfg.sample_rate > 0.0, "Invalid sample rate! %f\n", mod_enb->devs->openair0_cfg.sample_rate); - AssertFatal( mod_enb->devs->openair0_cfg.samples_per_packet > 0 , "Invalid number of samples per packet! %d\n",mod_enb->devs->openair0_cfg.samples_per_packet); - AssertFatal( mod_enb->devs->openair0_cfg.rx_num_channels > 0 , "Invalid number of RX antennas! %d\n", mod_enb->devs->openair0_cfg.rx_num_channels); - AssertFatal( mod_enb->devs->openair0_cfg.tx_num_channels > 0 , "Invalid number of TX antennas! %d\n", mod_enb->devs->openair0_cfg.tx_num_channels); - AssertFatal( mod_enb->devs->openair0_cfg.rx_freq[0] > 0.0 ,"Invalid RX frequency! %f\n", mod_enb->devs->openair0_cfg.rx_freq[0]); - AssertFatal( mod_enb->devs->openair0_cfg.tx_freq[0] > 0.0 ,"Invalid TX frequency! %f\n", mod_enb->devs->openair0_cfg.tx_freq[0]); - AssertFatal( mod_enb->devs->openair0_cfg.rx_gain[0] > 0.0 ,"Invalid RX gain! %f\n", mod_enb->devs->openair0_cfg.rx_gain[0]); - AssertFatal( mod_enb->devs->openair0_cfg.tx_gain[0] > 0.0 ,"Invalid TX gain! %f\n", mod_enb->devs->openair0_cfg.tx_gain[0]); - AssertFatal( mod_enb->devs->openair0_cfg.rx_bw > 0.0 ,"Invalid RX bw! %f\n", mod_enb->devs->openair0_cfg.rx_bw); - AssertFatal( mod_enb->devs->openair0_cfg.tx_bw > 0.0 ,"Invalid RX bw! %f\n", mod_enb->devs->openair0_cfg.tx_bw); - AssertFatal( mod_enb->devs->openair0_cfg.autocal[0] > 0 , "Invalid auto calibration choice! %d\n", mod_enb->devs->openair0_cfg.autocal[0]); + AssertFatal( (mod_enb->devs->openair0_cfg->num_rb_dl==100 || mod_enb->devs->openair0_cfg->num_rb_dl==50 || mod_enb->devs->openair0_cfg->num_rb_dl==25 || mod_enb->devs->openair0_cfg->num_rb_dl==6) , "Invalid number of resource blocks! %d\n", mod_enb->devs->openair0_cfg->num_rb_dl); + AssertFatal( mod_enb->devs->openair0_cfg->samples_per_frame > 0 , "Invalid number of samples per frame! %d\n",mod_enb->devs->openair0_cfg->samples_per_frame); + AssertFatal( mod_enb->devs->openair0_cfg->sample_rate > 0.0, "Invalid sample rate! %f\n", mod_enb->devs->openair0_cfg->sample_rate); + AssertFatal( mod_enb->devs->openair0_cfg->samples_per_packet > 0 , "Invalid number of samples per packet! %d\n",mod_enb->devs->openair0_cfg->samples_per_packet); + AssertFatal( mod_enb->devs->openair0_cfg->rx_num_channels > 0 , "Invalid number of RX antennas! %d\n", mod_enb->devs->openair0_cfg->rx_num_channels); + AssertFatal( mod_enb->devs->openair0_cfg->tx_num_channels > 0 , "Invalid number of TX antennas! %d\n", mod_enb->devs->openair0_cfg->tx_num_channels); + AssertFatal( mod_enb->devs->openair0_cfg->rx_freq[0] > 0.0 ,"Invalid RX frequency! %f\n", mod_enb->devs->openair0_cfg->rx_freq[0]); + AssertFatal( mod_enb->devs->openair0_cfg->tx_freq[0] > 0.0 ,"Invalid TX frequency! %f\n", mod_enb->devs->openair0_cfg->tx_freq[0]); + AssertFatal( mod_enb->devs->openair0_cfg->rx_gain[0] > 0.0 ,"Invalid RX gain! %f\n", mod_enb->devs->openair0_cfg->rx_gain[0]); + AssertFatal( mod_enb->devs->openair0_cfg->tx_gain[0] > 0.0 ,"Invalid TX gain! %f\n", mod_enb->devs->openair0_cfg->tx_gain[0]); + AssertFatal( mod_enb->devs->openair0_cfg->rx_bw > 0.0 ,"Invalid RX bw! %f\n", mod_enb->devs->openair0_cfg->rx_bw); + AssertFatal( mod_enb->devs->openair0_cfg->tx_bw > 0.0 ,"Invalid RX bw! %f\n", mod_enb->devs->openair0_cfg->tx_bw); + AssertFatal( mod_enb->devs->openair0_cfg->autocal[0] > 0 , "Invalid auto calibration choice! %d\n", mod_enb->devs->openair0_cfg->autocal[0]); printf("\n---------------------RF device configuration parameters---------------------\n"); - printf("\tMod_id=%d\n \tlog level=%d\n \tDL_RB=%d\n \tsamples_per_frame=%d\n \tsample_rate=%f\n \tsamples_per_packet=%d\n \ttx_delay=%d\n \ttx_forward_nsamps=%d\n \trx_num_channels=%d\n \ttx_num_channels=%d\n \trx_freq_0=%f\n \ttx_freq_0=%f\n \trx_freq_1=%f\n \ttx_freq_1=%f\n \trx_freq_2=%f\n \ttx_freq_2=%f\n \trx_freq_3=%f\n \ttx_freq_3=%f\n \trxg_mode=%d\n \trx_gain_0=%f\n \ttx_gain_0=%f\n \trx_gain_1=%f\n \ttx_gain_1=%f\n \trx_gain_2=%f\n \ttx_gain_2=%f\n \trx_gain_3=%f\n \ttx_gain_3=%f\n \trx_gain_offset_2=%f\n \ttx_gain_offset_3=%f\n \trx_bw=%f\n \ttx_bw=%f\n \tautocal=%d\n", - mod_enb->devs->openair0_cfg.Mod_id, - mod_enb->devs->openair0_cfg.log_level, - mod_enb->devs->openair0_cfg.num_rb_dl, - mod_enb->devs->openair0_cfg.samples_per_frame, - mod_enb->devs->openair0_cfg.sample_rate, - mod_enb->devs->openair0_cfg.samples_per_packet, - mod_enb->devs->openair0_cfg.tx_delay, - mod_enb->devs->openair0_cfg.tx_forward_nsamps, - mod_enb->devs->openair0_cfg.rx_num_channels, - mod_enb->devs->openair0_cfg.tx_num_channels, - mod_enb->devs->openair0_cfg.rx_freq[0], - mod_enb->devs->openair0_cfg.tx_freq[0], - mod_enb->devs->openair0_cfg.rx_freq[1], - mod_enb->devs->openair0_cfg.tx_freq[1], - mod_enb->devs->openair0_cfg.rx_freq[2], - mod_enb->devs->openair0_cfg.tx_freq[2], - mod_enb->devs->openair0_cfg.rx_freq[3], - mod_enb->devs->openair0_cfg.tx_freq[3], - mod_enb->devs->openair0_cfg.rxg_mode[0], - mod_enb->devs->openair0_cfg.rx_gain[0], - mod_enb->devs->openair0_cfg.tx_gain[0], - mod_enb->devs->openair0_cfg.rx_gain[1], - mod_enb->devs->openair0_cfg.tx_gain[1], - mod_enb->devs->openair0_cfg.rx_gain[2], - mod_enb->devs->openair0_cfg.tx_gain[2], - mod_enb->devs->openair0_cfg.rx_gain[3], - mod_enb->devs->openair0_cfg.tx_gain[3], - //mod_enb->devs->openair0_cfg.rx_gain_offset[0], - //mod_enb->devs->openair0_cfg.rx_gain_offset[1], - mod_enb->devs->openair0_cfg.rx_gain_offset[2], - mod_enb->devs->openair0_cfg.rx_gain_offset[3], - mod_enb->devs->openair0_cfg.rx_bw, - mod_enb->devs->openair0_cfg.tx_bw, - mod_enb->devs->openair0_cfg.autocal[0] + printf("\tMod_id=%d\n \tlog level=%d\n \tDL_RB=%d\n \tsamples_per_frame=%d\n \tsample_rate=%f\n \tsamples_per_packet=%d\n \ttx_scheduling_advance=%d\n \ttx_sample_advance=%d\n \trx_num_channels=%d\n \ttx_num_channels=%d\n \trx_freq_0=%f\n \ttx_freq_0=%f\n \trx_freq_1=%f\n \ttx_freq_1=%f\n \trx_freq_2=%f\n \ttx_freq_2=%f\n \trx_freq_3=%f\n \ttx_freq_3=%f\n \trxg_mode=%d\n \trx_gain_0=%f\n \ttx_gain_0=%f\n \trx_gain_1=%f\n \ttx_gain_1=%f\n \trx_gain_2=%f\n \ttx_gain_2=%f\n \trx_gain_3=%f\n \ttx_gain_3=%f\n \trx_gain_offset_2=%f\n \ttx_gain_offset_3=%f\n \trx_bw=%f\n \ttx_bw=%f\n \tautocal=%d\n", + mod_enb->devs->openair0_cfg->Mod_id, + mod_enb->devs->openair0_cfg->log_level, + mod_enb->devs->openair0_cfg->num_rb_dl, + mod_enb->devs->openair0_cfg->samples_per_frame, + mod_enb->devs->openair0_cfg->sample_rate, + mod_enb->devs->openair0_cfg->samples_per_packet, + mod_enb->devs->openair0_cfg->tx_scheduling_advance, + mod_enb->devs->openair0_cfg->tx_sample_advance, + mod_enb->devs->openair0_cfg->rx_num_channels, + mod_enb->devs->openair0_cfg->tx_num_channels, + mod_enb->devs->openair0_cfg->rx_freq[0], + mod_enb->devs->openair0_cfg->tx_freq[0], + mod_enb->devs->openair0_cfg->rx_freq[1], + mod_enb->devs->openair0_cfg->tx_freq[1], + mod_enb->devs->openair0_cfg->rx_freq[2], + mod_enb->devs->openair0_cfg->tx_freq[2], + mod_enb->devs->openair0_cfg->rx_freq[3], + mod_enb->devs->openair0_cfg->tx_freq[3], + mod_enb->devs->openair0_cfg->rxg_mode[0], + mod_enb->devs->openair0_cfg->tx_gain[0], + mod_enb->devs->openair0_cfg->tx_gain[0], + mod_enb->devs->openair0_cfg->rx_gain[1], + mod_enb->devs->openair0_cfg->tx_gain[1], + mod_enb->devs->openair0_cfg->rx_gain[2], + mod_enb->devs->openair0_cfg->tx_gain[2], + mod_enb->devs->openair0_cfg->rx_gain[3], + mod_enb->devs->openair0_cfg->tx_gain[3], + //mod_enb->devs->openair0_cfg->rx_gain_offset[0], + //mod_enb->devs->openair0_cfg->rx_gain_offset[1], + mod_enb->devs->openair0_cfg->rx_gain_offset[2], + mod_enb->devs->openair0_cfg->rx_gain_offset[3], + mod_enb->devs->openair0_cfg->rx_bw, + mod_enb->devs->openair0_cfg->tx_bw, + mod_enb->devs->openair0_cfg->autocal[0] ); printf("----------------------------------------------------------------------------\n"); diff --git a/targets/RT/USER/rrh_gw.c b/targets/RT/USER/rrh_gw.c index b944be2f77..bfdb01948e 100644 --- a/targets/RT/USER/rrh_gw.c +++ b/targets/RT/USER/rrh_gw.c @@ -194,7 +194,10 @@ static rrh_module_t new_module (unsigned int id) { rrh_mod.eth_dev.type=NONE_DEV; rrh_mod.eth_dev.transp_type=NONE_TP; /* ethernet device is functioning within RRH */ - rrh_mod.eth_dev.host_type=RRH_HOST; + rrh_mod.eth_dev.host_type=RRH_HOST; + /* */ + rrh_mod.eth_dev.openair0_cfg = (openair0_config_t*)malloc(sizeof(openair0_config_t)); + memset(rrh_mod.eth_dev.openair0_cfg,0,sizeof(openair0_config_t)); /* get IP and MAC address */ get_address(if_name,eth_mode); @@ -219,12 +222,12 @@ static rrh_module_t new_module (unsigned int id) { /* allocate space and specify associated RF device */ openair0_device *oai_dv = (openair0_device *)malloc(sizeof(openair0_device)); memset(oai_dv,0,sizeof(openair0_device)); + rrh_mod.devs=oai_dv; rrh_mod.devs->type=NONE_DEV; rrh_mod.devs->transp_type=NONE_TP; rrh_mod.devs->host_type=RRH_HOST; - return rrh_mod; } From fb19df9d0dc1ecd5dc57cd7919deb542b673a2a0 Mon Sep 17 00:00:00 2001 From: Aikaterini Date: Fri, 5 Feb 2016 13:24:05 +0100 Subject: [PATCH 199/263] update CMakelists.txt - update build_oai (add checks for args validity , minor update to linked libraries) --- cmake_targets/CMakeLists.txt | 4 +- cmake_targets/build_oai | 110 +++++++++++++++++++---------------- 2 files changed, 63 insertions(+), 51 deletions(-) diff --git a/cmake_targets/CMakeLists.txt b/cmake_targets/CMakeLists.txt index 630fc68dde..ee16fd6707 100644 --- a/cmake_targets/CMakeLists.txt +++ b/cmake_targets/CMakeLists.txt @@ -412,9 +412,9 @@ add_list1_option(NB_ANTENNAS_RX "2" "Number of antennas in reception" "1" "2" "4 add_list1_option(NB_ANTENNAS_TX "2" "Number of antennas in transmission" "1" "2" "4") add_list1_option(NB_ANTENNAS_TXRX "2" "Number of antennas in ????" "1" "2" "4") -add_list2_option(RF_BOARD "NO_VALUE" "RF head type" "False" "EXMIMO" "OAI_USRP" "OAI_BLADERF" "CPRIGW" "NO_VALUE")# make cleanup false rf_head_type cprigw??? +add_list2_option(RF_BOARD "EXMIMO" "RF head type" "None" "EXMIMO" "OAI_USRP" "OAI_BLADERF" "CPRIGW") -add_list2_option(TRANSP_PRO "NO_VALUE" "ETHERNET" "NO_VALUE") +add_list2_option(TRANSP_PRO "None" "Transport protocol type" "None" "ETHERNET") # include RF devices / transport protocols library modules diff --git a/cmake_targets/build_oai b/cmake_targets/build_oai index cb28d33f1b..c7259813c6 100755 --- a/cmake_targets/build_oai +++ b/cmake_targets/build_oai @@ -49,7 +49,7 @@ LOWLATENCY_FLAG_USER="False" FORCE_LOWLATENCY_FLAG_USER="" REL="Rel10" HW="EXMIMO" -TP="NO_VALUE" +TP="None" NOS1=0 EPC=0 VERBOSE_COMPILE=0 @@ -178,20 +178,28 @@ function main() { shift 2;; -w | --hardware) HW="$2" #"${i#*=}" - # Use OAI_USRP as the key word USRP is used inside UHD driver - if [ "$HW" == "USRP" ] ; then - HW="OAI_USRP" - fi - if [ "$HW" == "BLADERF" ] ; then - HW="OAI_BLADERF" - fi - echo_info "Setting hardware to: $HW" + # Use OAI_USRP as the key word USRP is used inside UHD driver + if [ "$HW" != "BLADERF" -a "$HW" != "USRP" -a "$HW" != "None" -a "$HW" != "EXMIMO" ] ; then + echo_fatal "Unknown HW type $HW will exit..." + else + if [ "$HW" == "USRP" ] ; then + HW="OAI_USRP" + fi + if [ "$HW" == "BLADERF" ] ; then + HW="OAI_BLADERF" + fi + echo_info "Setting hardware to: $HW" + fi shift 2;; -t | --transport_protocol) TP="$2" #"${i#*=}" - echo_info "Setting transport protocol to: $TP" + if [ "$TP" != "ETHERNET" -a "$TP" != "None" ] ; then + echo_fatal "Unknown TP type $TP will exit..." + else + echo_info "Setting transport protocol to: $TP" + fi shift 2;; - --oaisim) + --oaisim) oaisim=1 echo_info "Will compile oaisim and drivers nasmesh, ..." shift;; @@ -257,31 +265,32 @@ function main() { esac done - ############################################ + ######################################################### # check validity of HW and TP parameters for RRH and eNB - ############################################# + ######################################################### # to be discussed + if [ "$eNB" = "1" ] ; then - if [ "$HW" = "NO_VALUE" -a "$TP" = "NO_VALUE" ] ; then - echo_fatal "A hardware target or a transport protocol must be defined!!" + if [ "$HW" = "None" -a "$TP" = "None" ] ; then + echo_fatal "Define a local radio head (e.g. -w EXMIMO) or a transport protocol (e.g. -t ETHERNET) to communicate with a remote radio head!" fi - if [ "$HW" != "NO_VALUE" -a "$TP" != "NO_VALUE" ] ; then - echo_fatal "Currentlt lte-softmodem can not support simultaniously local and remote RF heads!!" + if [ "$HW" != "None" -a "$TP" != "None" ] ; then + echo_fatal "Currently eNB can not support simultaniously local and remote radio heads!!" fi - if [ "$HW" = "NO_VALUE" ] ; then - echo_info "No RF device has been selected: (HW=$HW)" + if [ "$HW" = "None" ] ; then + echo_info "No radio head has been selected (HW set to $HW)" fi - if [ "$TP" = "NO_VALUE" ] ; then - echo_info "No transport protocol has been selected: (TP=$TP)" + if [ "$TP" = "None" ] ; then + echo_info "No transport protocol has been selected (TP set to $TP)" fi fi if [ "$RRH" = "1" ] ; then - if [ "$TP" = "NO_VALUE" ] ; then - echo_fatal "A transport protocol must be defined!!" + if [ "$TP" = "None" ] ; then + echo_fatal "A transport protocol (e.g. -t ETHERNET) must be defined!" fi - if [ "$HW" = "NO_VALUE" ] ; then - echo_info "No RF device has been selected: (HW=$HW)" + if [ "$HW" = "None" ] ; then + echo_info "No radio head has been selected (HW set to $HW)" fi fi @@ -360,11 +369,11 @@ function main() { fi if [ "$oaisim" = "1" ] ; then - #to be discussed - # there is no RF device and no transport protocol - HW="NO_VALUE" - TP="NO_VALUE" - + #to be discussed + # there is no RF device and no transport protocol + HW="None" + TP="None" + if [ "$XFORMS" == "True" ] ; then PRINT_STATS="True" fi @@ -642,33 +651,36 @@ function main() { fi # build RF device libraries (currently EXMIMO is not complied with the rest of HW targets) - if [ "$HW" != "NO_VALUE" ] ; then + if [ "$HW" != "None" ] ; then rm -f liboai_device.so rm -f $dbin/liboai_device.so - if [ -d "/usr/include/uhd" ] ; then - compilations \ - $build_dir oai_usrpdevif \ - liboai_usrpdevif.so $dbin/liboai_usrpdevif.so.$REL - fi - if [ -f "/usr/include/libbladeRF.h" ] ; then - compilations \ - $build_dir oai_bladerfdevif \ - liboai_bladerfdevif.so $dbin/liboai_bladerfdevif.so.$REL - fi - - #add exmimo compilation # link liboai_device.so with the selected RF device library if [ "$HW" == "EXMIMO" ] ; then - ln -s liboai_exmimodevif.so liboai_device.so - ln -s $dbin/liboai_exmimodevif.so.$REL $dbin/liboai_device.so + + #add exmimo compilation + + ln -s openair_rf.ko liboai_device.so + ln -s $dbin/openair_rf.ko $dbin/liboai_device.so echo_info "liboai_device.so is linked to EXMIMO device library" elif [ "$HW" == "OAI_USRP" ] ; then + if [ -d "/usr/include/uhd" ] ; then + compilations \ + $build_dir oai_usrpdevif \ + liboai_usrpdevif.so $dbin/liboai_usrpdevif.so.$REL + fi + ln -s liboai_usrpdevif.so liboai_device.so ln -s $dbin/liboai_usrpdevif.so.$REL $dbin/liboai_device.so echo_info "liboai_device.so is linked to USRP device library" elif [ "$HW" == "OAI_BLADERF" ] ; then + if [ -f "/usr/include/libbladeRF.h" ] ; then + compilations \ + $build_dir oai_bladerfdevif \ + liboai_bladerfdevif.so $dbin/liboai_bladerfdevif.so.$REL + fi + ln -s liboai_bladerfdevif.so liboai_device.so ln -s $dbin/liboai_bladerfdevif.so.$REL $dbin/liboai_device.so echo_info "liboai_device.so is linked to BLADERF device library" @@ -678,14 +690,14 @@ function main() { fi # build trasport protocol libraries (currently only ETHERNET is available) - if [ "$TP" != "NO_VALUE" ] ; then + if [ "$TP" != "None" ] ; then rm -f liboai_transpro.so rm -f $dbin/liboai_transpro.so - compilations \ - $build_dir oai_eth_transpro \ - liboai_eth_transpro.so $dbin/liboai_eth_transpro.so.$REL if [ "$TP" == "ETHERNET" ] ; then + compilations \ + $build_dir oai_eth_transpro \ + liboai_eth_transpro.so $dbin/liboai_eth_transpro.so.$REL ln -s liboai_eth_transpro.so liboai_transpro.so ln -s $dbin/liboai_eth_transpro.so.$REL $dbin/liboai_transpro.so echo_info "liboai_transpro.so is linked with ETHERNET library" From 1a9982cae7216bc4f7056af8ca8eed230cc5cbb5 Mon Sep 17 00:00:00 2001 From: Aikaterini Date: Fri, 5 Feb 2016 13:27:32 +0100 Subject: [PATCH 200/263] correction in conf file for rrh_gw --- .../CONF/enb.band7.tm1.rrh.usrpb210.conf | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.rrh.usrpb210.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.rrh.usrpb210.conf index dd138c23ac..95bad9da5b 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.rrh.usrpb210.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.rrh.usrpb210.conf @@ -142,29 +142,30 @@ eNBs = rrh_gw_config = ( { - udp = 1; - raw = 0; - active = 1; + local_if_name = "eth0"; #remote_addr = "169.254.8.28"; #remote_addr = "127.0.0.1"; #remote_addr = "74:d4:35:cc:88:45"; #local_addr = "169.254.7.91"; #local_addr = "127.0.0.1"; #local_addr = "d4:be:d9:22:0a:ac"; - local_address = "192.168.12.242" ; + local_address = "192.168.12.242" ; remote_address = "192.168.12.31" ; - local_port = 50000; - remote_port = 50001; + local_port = 50000; + remote_port = 50001; + active = "no"; + preference = "udp"; + } ); NETWORK_INTERFACES : { ENB_INTERFACE_NAME_FOR_S1_MME = "eth0"; - ENB_IPV4_ADDRESS_FOR_S1_MME = "192.168.12.216/24"; + ENB_IPV4_ADDRESS_FOR_S1_MME = "192.168.12.242/24"; ENB_INTERFACE_NAME_FOR_S1U = "eth0"; - ENB_IPV4_ADDRESS_FOR_S1U = "192.168.12.216/24"; + ENB_IPV4_ADDRESS_FOR_S1U = "192.168.12.242/24"; ENB_PORT_FOR_S1U = 2152; # Spec 2152 }; From 979c84ac075ab588dd5079e37a009cea9ea1fbda Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Fri, 5 Feb 2016 15:25:23 +0100 Subject: [PATCH 201/263] updated timing for resetting UE --- cmake_targets/autotests/tools/configure_cots_bandrich_ue.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py b/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py index 99c4a04eaa..fdbbb5d6d0 100755 --- a/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py +++ b/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py @@ -161,9 +161,9 @@ def reset_ue(): usb_dir= find_usb_path(VendorId, ProductId) print usb_dir cmd = "sudo sh -c \"echo 0 > " + usb_dir + "/authorized\"" - os.system(cmd + " ; sleep 5" ) + os.system(cmd + " ; sleep 15" ) cmd = "sudo sh -c \"echo 1 > " + usb_dir + "/authorized\"" - os.system(cmd + " ; sleep 5" ) + os.system(cmd + " ; sleep 30" ) def read_file(filename): try: From df67178a841a09eabf7407006d53c97074901a6b Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Fri, 5 Feb 2016 18:27:08 +0100 Subject: [PATCH 202/263] Added bladeRF support + creation of common autotest library --- .../tools/configure_cots_bandrich_ue.py | 29 ++---------- cmake_targets/autotests/tools/lib_autotest.py | 33 +++++++++++++ cmake_targets/tools/start_bladerf.py | 46 +++++++++++++++++++ 3 files changed, 84 insertions(+), 24 deletions(-) create mode 100644 cmake_targets/autotests/tools/lib_autotest.py create mode 100644 cmake_targets/tools/start_bladerf.py diff --git a/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py b/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py index fdbbb5d6d0..6af3785865 100755 --- a/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py +++ b/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py @@ -21,6 +21,10 @@ if openair_dir == None: print "Error getting OPENAIR_DIR environment variable" sys.exit(1) +sys.path.append(os.path.expandvars('$OPENAIR_DIR/cmake_targets/autotests/tools/')) + +from lib_autotest import * + def find_open_port(): global serial_port, ser max_ports=100 @@ -159,35 +163,12 @@ def reset_ue(): VendorId=res[0][2] ProductId=res[0][3] usb_dir= find_usb_path(VendorId, ProductId) - print usb_dir + print "Bandrich 4G LTE Adapter found in..." + usb_dir cmd = "sudo sh -c \"echo 0 > " + usb_dir + "/authorized\"" os.system(cmd + " ; sleep 15" ) cmd = "sudo sh -c \"echo 1 > " + usb_dir + "/authorized\"" os.system(cmd + " ; sleep 30" ) -def read_file(filename): - try: - file = open(filename, 'r') - return file.read() - except Exception, e: - #error = ' Filename ' + filename - #error = error + ' In function: ' + sys._getframe().f_code.co_name + ': *** Caught exception: ' + str(e.__class__) + " : " + str( e) - #error = error + traceback.format_exc() - #print error - return '' - - -def find_usb_path(idVendor, idProduct): - for root, dirs, files in os.walk("/sys/bus/usb/devices", topdown=False): - for name in dirs: - tmpdir= os.path.join(root, name) - tmpidVendor = read_file(tmpdir+'/idVendor').replace("\n","") - tmpidProduct = read_file(tmpdir+'/idProduct').replace("\n","") - #print "tmpdir = " + tmpdir + " tmpidVendor = " + tmpidVendor + " tmpidProduct = " + tmpidProduct - if tmpidVendor == idVendor and tmpidProduct == idProduct: - return tmpdir - return '' - i=1 gw='192.172.0.1' while i < len(sys.argv): diff --git a/cmake_targets/autotests/tools/lib_autotest.py b/cmake_targets/autotests/tools/lib_autotest.py new file mode 100644 index 0000000000..67234de567 --- /dev/null +++ b/cmake_targets/autotests/tools/lib_autotest.py @@ -0,0 +1,33 @@ +#!/usr/bin/python + +import os +from pyroute2 import IPRoute +import sys +import re +import threading +import signal +import traceback +import commands + +def read_file(filename): + try: + file = open(filename, 'r') + return file.read() + except Exception, e: + # WE just ignore the exception as some files are probably not present + #error = ' Filename ' + filename + #error = error + ' In function: ' + sys._getframe().f_code.co_name + ': *** Caught exception: ' + str(e.__class__) + " : " + str( e) + #error = error + traceback.format_exc() + #print error + return '' + +def find_usb_path(idVendor, idProduct): + for root, dirs, files in os.walk("/sys/bus/usb/devices", topdown=False): + for name in dirs: + tmpdir= os.path.join(root, name) + tmpidVendor = read_file(tmpdir+'/idVendor').replace("\n","") + tmpidProduct = read_file(tmpdir+'/idProduct').replace("\n","") + if tmpidVendor == idVendor and tmpidProduct == idProduct: + return tmpdir + return '' + diff --git a/cmake_targets/tools/start_bladerf.py b/cmake_targets/tools/start_bladerf.py new file mode 100644 index 0000000000..ad83d5d517 --- /dev/null +++ b/cmake_targets/tools/start_bladerf.py @@ -0,0 +1,46 @@ +#!/usr/bin/python +import time +import serial +import os +from pyroute2 import IPRoute +import sys +import re +import threading +import signal +import traceback +import commands + +if os.environ.get('OPENAIR_DIR') == None: + print "Error getting OPENAIR_DIR environment variable" + sys.exit(1) + +sys.path.append(os.path.expandvars('$OPENAIR_DIR/cmake_targets/autotests/tools/')) + +from lib_autotest import * + +def reset_bladerf(): + stringIdBladeRF='OpenMoko, Inc' + status, out = commands.getstatusoutput('lsusb | grep -i \'' + stringIdBladeRF + '\'') + if (out == '') : + print "BladeRF not found. Exiting now..." + sys.exit() + p=re.compile('Bus\s*(\w+)\s*Device\s*(\w+):\s*ID\s*(\w+):(\w+)') + res=p.findall(out) + BusId=res[0][0] + DeviceId=res[0][1] + VendorId=res[0][2] + ProductId=res[0][3] + usb_dir= find_usb_path(VendorId, ProductId) + print "BladeRF Found in directory..." + usb_dir + cmd = "sudo sh -c \"echo 0 > " + usb_dir + "/authorized\"" + os.system(cmd + " ; sleep 5" ) + cmd = "sudo sh -c \"echo 1 > " + usb_dir + "/authorized\"" + os.system(cmd + " ; sleep 5" ) + +os.system ('sudo -E bladeRF-cli --flash-firmware /usr/share/Nuand/bladeRF/bladeRF_fw.img') + +print "Resettting BladeRF..." + +reset_bladerf() + +os.system ("dmesg|tail") From 892efb01d7d170a1ce479be1f5ec15f8b6ea1a07 Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Fri, 5 Feb 2016 18:48:51 +0100 Subject: [PATCH 203/263] changed exec permissions for blade RF start --- cmake_targets/tools/start_bladerf.py | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 cmake_targets/tools/start_bladerf.py diff --git a/cmake_targets/tools/start_bladerf.py b/cmake_targets/tools/start_bladerf.py old mode 100644 new mode 100755 From c303b942371eda46fe359f5fca8cb9b5970679d4 Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Sun, 7 Feb 2016 12:44:52 +0100 Subject: [PATCH 204/263] updates for BLADERF test case + cleanup --- cmake_targets/autotests/README.txt | 8 + .../autotests/run_exec_lte-softmodem_tests.py | 2 + cmake_targets/autotests/test_case_list.xml | 499 +++++++++++++++++- 3 files changed, 484 insertions(+), 25 deletions(-) diff --git a/cmake_targets/autotests/README.txt b/cmake_targets/autotests/README.txt index 506fc3321d..f862644d07 100644 --- a/cmake_targets/autotests/README.txt +++ b/cmake_targets/autotests/README.txt @@ -163,6 +163,14 @@ Obj.# Case# Test# Description 01 63 04 Band 7 FDD 10MHz DL Throughput for 300 sec for 1TX/1RX 01 63 05 Band 7 FDD 20MHz DL Throughput for 300 sec for 1TX/1RX +01 65 00 lte-softmodem tests with BladeRF RF as eNB and ALU EPC w/ Bandrich COTS UE for TX/1RX +01 65 00 Band 7 FDD 5MHz UL Throughput for 300 sec for 1TX/1RX +01 65 01 Band 7 FDD 10MHz UL Throughput for 300 sec for 1TX/1RX +01 65 02 Band 7 FDD 20MHz UL Throughput for 300 sec for 1TX/1RX +01 65 03 Band 7 FDD 5MHz DL Throughput for 300 sec for 1TX/1RX +01 65 04 Band 7 FDD 10MHz DL Throughput for 300 sec for 1TX/1RX +01 65 05 Band 7 FDD 20MHz DL Throughput for 300 sec for 1TX/1RX + 01 64 lte-softmodem-noS1 tests 02 Functional test case diff --git a/cmake_targets/autotests/run_exec_lte-softmodem_tests.py b/cmake_targets/autotests/run_exec_lte-softmodem_tests.py index f137d128f4..eb142c114e 100755 --- a/cmake_targets/autotests/run_exec_lte-softmodem_tests.py +++ b/cmake_targets/autotests/run_exec_lte-softmodem_tests.py @@ -60,7 +60,9 @@ import paramiko import subprocess import commands sys.path.append('/opt/ssh') +sys.path.append(os.path.expandvars('$OPENAIR_DIR/cmake_targets/autotests/tools/')) +from lib_autotest import * import ssh from ssh import SSHSession import argparse diff --git a/cmake_targets/autotests/test_case_list.xml b/cmake_targets/autotests/test_case_list.xml index cec3963c4e..03f10ce578 100644 --- a/cmake_targets/autotests/test_case_list.xml +++ b/cmake_targets/autotests/test_case_list.xml @@ -10,7 +10,7 @@ sudo -S -E /opt/ltebox/tools/stop_ltebox $OPENAIR_DIR/cmake_targets/build_oai -w EXMIMO -c; sudo -S -E $OPENAIR_DIR/cmake_targets/tools/stop_exmimo2; uname -a; dmesg|tail 36000 - 0104+ 015506 015507 015508 015509 015510 015511 015602 015605 015702 015705 015802 015805 016002 016005 016102 016105 016302 016305 + 0104+ 015502 015505 015506 015507 015508 015509 015510 015511 015602 015605 015702 015705 015802 015805 016002 016005 016102 016105 016302 016305 016502 016505 3 mozart calisson stevens nano amerique @@ -920,7 +920,7 @@ - $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 45; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue + $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 10; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 1 ppp0 -u -c 192.172.0.1 -b 10Mbits/s -B 192.172.0.2 @@ -995,7 +995,7 @@ - $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 45; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue + $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 10; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 1 ppp0 -u -c 192.172.0.1 -b 10Mbits/s -B 192.172.0.2 @@ -1069,7 +1069,7 @@ - $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 45; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue + $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 10; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 1 ppp0 -u -c 192.172.0.1 -b 10Mbits/s -B 192.172.0.2 @@ -1143,7 +1143,7 @@ - $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 45; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue + $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 10; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 1 ppp0 -s -i 1 -u -f m -B 192.172.0.2 @@ -1215,7 +1215,7 @@ - $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 45; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue + $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 10; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 1 ppp0 -s -i 1 -u -f m -B 192.172.0.2 @@ -1289,7 +1289,7 @@ - $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 45; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue + $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 10; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 1 ppp0 -s -i 1 -u -f m -B 192.172.0.2 @@ -1364,7 +1364,7 @@ - $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue;$OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 45; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue + $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue;$OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 10; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 1 ppp0 -u -c 192.172.0.1 -b 10Mbits/s -B 192.172.0.2 @@ -1438,7 +1438,7 @@ - $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue;$OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 45; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue + $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue;$OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 10; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 1 ppp0 -u -c 192.172.0.1 -b 10Mbits/s -B 192.172.0.2 @@ -1512,7 +1512,7 @@ - $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 45; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue + $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 10; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 1 ppp0 -u -c 192.172.0.1 -b 10Mbits/s -B 192.172.0.2 @@ -1586,7 +1586,7 @@ - $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 45; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue + $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 10; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 1 ppp0 -s -i 1 -u -f m -B 192.172.0.2 @@ -1660,7 +1660,7 @@ - $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 45; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue + $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 10; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 1 ppp0 -s -i 1 -u -f m -B 192.172.0.2 @@ -1734,7 +1734,7 @@ - $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 45; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue + $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 10; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 1 ppp0 -s -i 1 -u -f m -B 192.172.0.2 @@ -2815,7 +2815,7 @@ - $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 45; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue + $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 10; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 1 ppp0 -u -c 192.172.0.1 -b 10Mbits/s -B 192.172.0.2 @@ -2887,7 +2887,7 @@ - $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 45; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue + $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 10; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 1 ppp0 -u -c 192.172.0.1 -b 10Mbits/s -B 192.172.0.2 @@ -2959,7 +2959,7 @@ - $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 45; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue + $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 10; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 1 ppp0 -u -c 192.172.0.1 -b 10Mbits/s -B 192.172.0.2 @@ -3031,7 +3031,7 @@ - $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 45; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue + $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 10; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 1 ppp0 -s -i 1 -u -f m -B 192.172.0.2 @@ -3102,7 +3102,7 @@ - $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 45; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue + $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 10; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 1 ppp0 -s -i 1 -u -f m -B 192.172.0.2 @@ -3173,7 +3173,7 @@ - $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 45; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue + $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 10; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 1 ppp0 -s -i 1 -u -f m -B 192.172.0.2 @@ -3734,7 +3734,7 @@ - $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 45; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue + $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 10; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 1 ppp0 -u -c 192.172.0.1 -b 10Mbits/s -B 192.172.0.2 @@ -3807,7 +3807,7 @@ - $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 45; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue + $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 10; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 1 ppp0 -u -c 192.172.0.1 -b 10Mbits/s -B 192.172.0.2 @@ -3879,7 +3879,7 @@ - $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 45; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue + $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 10; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 1 ppp0 -u -c 192.172.0.1 -b 10Mbits/s -B 192.172.0.2 @@ -3955,7 +3955,7 @@ - $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 45; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue + $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 10; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 1 ppp0 -s -i 1 -u -f m -B 192.172.0.2 @@ -4026,7 +4026,7 @@ - $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 45; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue + $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 10; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 1 ppp0 -s -i 1 -u -f m -B 192.172.0.2 @@ -4097,7 +4097,7 @@ - $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 45; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue + $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 10; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 1 ppp0 -s -i 1 -u -f m -B 192.172.0.2 @@ -4619,6 +4619,455 @@ + + lte-softmodem + + calisson + stevens + amerique + 390 + /tmp + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf tracking_area_code \"1\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf mobile_country_code \"208\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf mobile_network_code \"92\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf N_RB_DL 25 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf mme_ip_address "ipv4=\"192.168.12.26\";ipv6=\"192:168:30::17\";active=\"yes\";preference=\"ipv4\";" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf downlink_frequency 2660000000L + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf uplink_frequency_offset -120000000 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf tx_gain 90 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf rx_gain 125 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf frame_type \"FDD\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf nb_antennas_rx 1 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf nb_antennas_tx 1 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf pdsch_referenceSignalPower -29 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf ENB_INTERFACE_NAME_FOR_S1_MME \"eth1\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf ENB_IPV4_ADDRESS_FOR_S1_MME \"192.168.12.82/24\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf ENB_INTERFACE_NAME_FOR_S1U \"eth1\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf ENB_IPV4_ADDRESS_FOR_S1U \"192.168.12.82/24\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf ENB_PORT_FOR_S1U 2152 + $OPENAIR_DIR/cmake_targets/build_oai + --eNB -w BLADERF -x -c + sudo -E $OPENAIR_DIR/cmake_targets/tools/start_bladerf.py + + $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem + -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf -W + + + + + False + + /tmp + + + + + + $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 10; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue + + $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 1 ppp0 -u -c 192.172.0.1 -b 10Mbits/s -B 192.172.0.2 + + + + False + sudo -S -E $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue + + /tmp + + + + + + + + + /opt/ltebox/tools/stop_ltebox ; /opt/ltebox/tools/start_ltebox ; sleep 3000 + + /opt/hss_sim0609/starthss >> /dev/null ; sleep 3000 + + $OPENAIRCN_DIR/TEST/autotests/tools/iperf_script 5 lo -s -i 1 -u -f m -B 192.172.0.1 + + throughput_test min=1.0Mbits/sec max=1.0Mbits/sec average=1.0Mbits/sec + + False + BladeRF.ALU_EPC.Bandrich.5MHz.FDD.Band_7.UL.1TX.1RX + 10 + + + + + lte-softmodem + + calisson + stevens + amerique + 390 + /tmp + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf tracking_area_code \"1\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf mobile_country_code \"208\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf mobile_network_code \"92\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf N_RB_DL 50 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf mme_ip_address "ipv4=\"192.168.12.26\";ipv6=\"192:168:30::17\";active=\"yes\";preference=\"ipv4\";" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf downlink_frequency 2660000000L + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf uplink_frequency_offset -120000000 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf tx_gain 90 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf rx_gain 125 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf frame_type \"FDD\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf nb_antennas_rx 1 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf nb_antennas_tx 1 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf pdsch_referenceSignalPower -32 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf ENB_INTERFACE_NAME_FOR_S1_MME \"eth1\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf ENB_IPV4_ADDRESS_FOR_S1_MME \"192.168.12.82/24\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf ENB_INTERFACE_NAME_FOR_S1U \"eth1\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf ENB_IPV4_ADDRESS_FOR_S1U \"192.168.12.82/24\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf ENB_PORT_FOR_S1U 2152 + $OPENAIR_DIR/cmake_targets/build_oai + --eNB -w BLADERF -x -c + sudo -E $OPENAIR_DIR/cmake_targets/tools/start_bladerf.py + + $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem + -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf -W + + + + + True + + /tmp + + + + + + $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 10; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue + + $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 1 ppp0 -u -c 192.172.0.1 -b 10Mbits/s -B 192.172.0.2 + + + + True + sudo -S -E $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue + + /tmp + + + + + + + + + /opt/ltebox/tools/stop_ltebox ; /opt/ltebox/tools/start_ltebox ; sleep 3000 + + /opt/hss_sim0609/starthss >> /dev/null ; sleep 3000 + + $OPENAIRCN_DIR/TEST/autotests/tools/iperf_script 5 lo -s -i 1 -u -f m -B 192.172.0.1 + + throughput_test min=1.0Mbits/sec max=1.0Mbits/sec average=1.0Mbits/sec + + True + BladeRF.ALU_EPC.Bandrich.10MHz.FDD.Band_7.UL.1TX.1RX + 10 + + + + lte-softmodem + + calisson + stevens + amerique + 390 + /tmp + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf tracking_area_code \"1\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf mobile_country_code \"208\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf mobile_network_code \"92\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf N_RB_DL 100 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf mme_ip_address "ipv4=\"192.168.12.26\";ipv6=\"192:168:30::17\";active=\"yes\";preference=\"ipv4\";" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf downlink_frequency 2660000000L + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf uplink_frequency_offset -120000000 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf tx_gain 90 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf rx_gain 125 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf frame_type \"FDD\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf nb_antennas_rx 1 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf nb_antennas_tx 1 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf pdsch_referenceSignalPower -35 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf ENB_INTERFACE_NAME_FOR_S1_MME \"eth1\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf ENB_IPV4_ADDRESS_FOR_S1_MME \"192.168.12.82/24\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf ENB_INTERFACE_NAME_FOR_S1U \"eth1\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf ENB_IPV4_ADDRESS_FOR_S1U \"192.168.12.82/24\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf ENB_PORT_FOR_S1U 2152 + $OPENAIR_DIR/cmake_targets/build_oai + --eNB -w BLADERF -x -c + sudo -E $OPENAIR_DIR/cmake_targets/tools/start_bladerf.py + + $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem + -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf -W + + + + + True + + /tmp + + + + + + $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 10; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue + + $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 1 ppp0 -u -c 192.172.0.1 -b 10Mbits/s -B 192.172.0.2 + + + + True + sudo -S -E $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue + + /tmp + + + + + + + + + /opt/ltebox/tools/stop_ltebox ; /opt/ltebox/tools/start_ltebox ; sleep 3000 + + /opt/hss_sim0609/starthss >> /dev/null ; sleep 3000 + + $OPENAIRCN_DIR/TEST/autotests/tools/iperf_script 5 lo -s -i 1 -u -f m -B 192.172.0.1 + + throughput_test min=1.0Mbits/sec max=1.0Mbits/sec average=1.0Mbits/sec + + True + BladeRF.ALU_EPC.Bandrich.20MHz.FDD.Band_7.UL.1TX.1RX + 10 + + + + lte-softmodem + + calisson + stevens + amerique + 390 + /tmp + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf tracking_area_code \"1\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf mobile_country_code \"208\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf mobile_network_code \"92\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf N_RB_DL 25 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf mme_ip_address "ipv4=\"192.168.12.26\";ipv6=\"192:168:30::17\";active=\"yes\";preference=\"ipv4\";" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf downlink_frequency 2660000000L + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf uplink_frequency_offset -120000000 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf tx_gain 90 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf rx_gain 125 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf frame_type \"FDD\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf nb_antennas_rx 1 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf nb_antennas_tx 1 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf pdsch_referenceSignalPower -29 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf ENB_INTERFACE_NAME_FOR_S1_MME \"eth1\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf ENB_IPV4_ADDRESS_FOR_S1_MME \"192.168.12.82/24\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf ENB_INTERFACE_NAME_FOR_S1U \"eth1\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf ENB_IPV4_ADDRESS_FOR_S1U \"192.168.12.82/24\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf ENB_PORT_FOR_S1U 2152 + $OPENAIR_DIR/cmake_targets/build_oai + --eNB -w BLADERF -x -c + sudo -E $OPENAIR_DIR/cmake_targets/tools/start_bladerf.py + + $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem + -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf -W + + + + + True + + /tmp + + + + + + $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 10; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue + + $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 1 ppp0 -s -i 1 -u -f m -B 192.172.0.2 + + True + sudo -S -E $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue + throughput_test min=4.0Mbits/sec max=5.0Mbits/sec average=4.0Mbits/sec + + + /tmp + + + + + + + + + /opt/ltebox/tools/stop_ltebox ; /opt/ltebox/tools/start_ltebox ; sleep 3000 + + /opt/hss_sim0609/starthss >> /dev/null ; sleep 3000 + + $OPENAIRCN_DIR/TEST/autotests/tools/iperf_script 60 lo -u -c 192.172.0.2 -b 10Mbits/s -B 192.172.0.1 + + + True + BladeRF.ALU_EPC.Bandrich.5MHz.FDD.Band_7.DL.1TX.1RX + 10 + + + + lte-softmodem + + calisson + stevens + amerique + 390 + /tmp + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf tracking_area_code \"1\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf mobile_country_code \"208\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf mobile_network_code \"92\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf N_RB_DL 50 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf mme_ip_address "ipv4=\"192.168.12.26\";ipv6=\"192:168:30::17\";active=\"yes\";preference=\"ipv4\";" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf downlink_frequency 2660000000L + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf uplink_frequency_offset -120000000 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf tx_gain 90 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf rx_gain 125 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf frame_type \"FDD\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf nb_antennas_rx 1 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf nb_antennas_tx 1 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf pdsch_referenceSignalPower -32 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf ENB_INTERFACE_NAME_FOR_S1_MME \"eth1\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf ENB_IPV4_ADDRESS_FOR_S1_MME \"192.168.12.82/24\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf ENB_INTERFACE_NAME_FOR_S1U \"eth1\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf ENB_IPV4_ADDRESS_FOR_S1U \"192.168.12.82/24\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf ENB_PORT_FOR_S1U 2152 + $OPENAIR_DIR/cmake_targets/build_oai + --eNB -w BLADERF -x -c + sudo -E $OPENAIR_DIR/cmake_targets/tools/start_bladerf.py + + $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem + -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf -W + + + + + True + + /tmp + + + + + $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 10; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue + + $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 1 ppp0 -s -i 1 -u -f m -B 192.172.0.2 + + throughput_test min=8.0Mbits/sec max=9.0Mbits/sec average=8.5Mbits/sec + + True + sudo -S -E $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue + + + /tmp + + + + + + + + + /opt/ltebox/tools/stop_ltebox ; /opt/ltebox/tools/start_ltebox ; sleep 3000 + + /opt/hss_sim0609/starthss >> /dev/null ; sleep 3000 + + $OPENAIRCN_DIR/TEST/autotests/tools/iperf_script 60 lo -u -c 192.172.0.2 -b 10Mbits/s -B 192.172.0.1 + + + True + BladeRF.ALU_EPC.Bandrich.10MHz.FDD.Band_7.DL.1TX.1RX + 10 + + + + lte-softmodem + + calisson + stevens + amerique + 390 + /tmp + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf tracking_area_code \"1\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf mobile_country_code \"208\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf mobile_network_code \"92\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf N_RB_DL 100 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf mme_ip_address "ipv4=\"192.168.12.26\";ipv6=\"192:168:30::17\";active=\"yes\";preference=\"ipv4\";" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf downlink_frequency 2660000000L + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf uplink_frequency_offset -120000000 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf tx_gain 90 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf rx_gain 125 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf frame_type \"FDD\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf nb_antennas_rx 1 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf nb_antennas_tx 1 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf pdsch_referenceSignalPower -35 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf ENB_INTERFACE_NAME_FOR_S1_MME \"eth1\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf ENB_IPV4_ADDRESS_FOR_S1_MME \"192.168.12.82/24\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf ENB_INTERFACE_NAME_FOR_S1U \"eth1\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf ENB_IPV4_ADDRESS_FOR_S1U \"192.168.12.82/24\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf ENB_PORT_FOR_S1U 2152 + $OPENAIR_DIR/cmake_targets/build_oai + --eNB -w BLADERF -x -c + sudo -E $OPENAIR_DIR/cmake_targets/tools/start_bladerf.py + + $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem + -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf -W + + + + + True + + /tmp + + + + + + $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --reset-ue; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue ; sleep 10; $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --start-ue + + $OPENAIR_DIR/cmake_targets/autotests/tools/iperf_script 1 ppp0 -s -i 1 -u -f m -B 192.172.0.2 + + throughput_test min=15.0Mbits/sec max=15.0Mbits/sec average=15.0Mbits/sec + + True + sudo -S -E $OPENAIR_DIR/cmake_targets/autotests/tools/configure_cots_bandrich_ue.py --stop-ue + + + /tmp + + + + + + + + + /opt/ltebox/tools/stop_ltebox ; /opt/ltebox/tools/start_ltebox ; sleep 3000 + + /opt/hss_sim0609/starthss >> /dev/null ; sleep 3000 + + $OPENAIRCN_DIR/TEST/autotests/tools/iperf_script 60 lo -u -c 192.172.0.2 -b 10Mbits/s -B 192.172.0.1 + + + True + BladeRF.ALU_EPC.Bandrich.20MHz.FDD.Band_7.DL.1TX.1RX + 10 + + From fafee9508b16afadfdf9b608c75b374a2a6677bb Mon Sep 17 00:00:00 2001 From: Aikaterini Date: Sun, 7 Feb 2016 19:54:21 +0100 Subject: [PATCH 205/263] include packet sequence number in vcd logging --- openair2/UTIL/LOG/vcd_signal_dumper.c | 3 +++ openair2/UTIL/LOG/vcd_signal_dumper.h | 3 +++ 2 files changed, 6 insertions(+) diff --git a/openair2/UTIL/LOG/vcd_signal_dumper.c b/openair2/UTIL/LOG/vcd_signal_dumper.c index 8dfbfd6ef5..31ce2e0d71 100644 --- a/openair2/UTIL/LOG/vcd_signal_dumper.c +++ b/openair2/UTIL/LOG/vcd_signal_dumper.c @@ -106,6 +106,9 @@ const char* eurecomVariablesNames[] = { "lhw_cnt_tx", "pck_rx", "pck_tx", + "rx_seq_num", + "rx_seq_num_prv", + "tx_seq_num", "cnt", "dummy_dump", "itti_send_msg", diff --git a/openair2/UTIL/LOG/vcd_signal_dumper.h b/openair2/UTIL/LOG/vcd_signal_dumper.h index 68257484f0..9ca55846fd 100644 --- a/openair2/UTIL/LOG/vcd_signal_dumper.h +++ b/openair2/UTIL/LOG/vcd_signal_dumper.h @@ -78,6 +78,9 @@ typedef enum { VCD_SIGNAL_DUMPER_VARIABLES_TX_LHWCNT, VCD_SIGNAL_DUMPER_VARIABLES_RX_PCK, VCD_SIGNAL_DUMPER_VARIABLES_TX_PCK, + VCD_SIGNAL_DUMPER_VARIABLES_RX_SEQ_NUM, + VCD_SIGNAL_DUMPER_VARIABLES_RX_SEQ_NUM_PRV, + VCD_SIGNAL_DUMPER_VARIABLES_TX_SEQ_NUM, VCD_SIGNAL_DUMPER_VARIABLES_CNT, VCD_SIGNAL_DUMPER_VARIABLES_DUMMY_DUMP, VCD_SIGNAL_DUMPER_VARIABLE_ITTI_SEND_MSG, From b39e017541c5b15fa804ec5baed87996a63d6646 Mon Sep 17 00:00:00 2001 From: Aikaterini Date: Sun, 7 Feb 2016 20:00:33 +0100 Subject: [PATCH 206/263] update ethernet library wrt changes in openair0_device - add packet sequence number --- targets/ARCH/ETHERNET/USERSPACE/LIB/eth_raw.c | 7 +- targets/ARCH/ETHERNET/USERSPACE/LIB/eth_udp.c | 60 ++++++++++------ .../ETHERNET/USERSPACE/LIB/ethernet_lib.c | 72 +++++++++++++++---- .../ETHERNET/USERSPACE/LIB/ethernet_lib.h | 27 ++----- 4 files changed, 107 insertions(+), 59 deletions(-) diff --git a/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_raw.c b/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_raw.c index 03c876c07f..a360f26556 100644 --- a/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_raw.c +++ b/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_raw.c @@ -52,7 +52,7 @@ #include "common_lib.h" #include "ethernet_lib.h" -#define DEBUG 1 +#define DEBUG 0 struct sockaddr_ll dest_addr[MAX_INST]; struct sockaddr_ll local_addr[MAX_INST]; @@ -275,7 +275,7 @@ int eth_set_dev_conf_raw(openair0_device *device) { memcpy(msg,(void*)&eh,MAC_HEADER_SIZE_BYTES); - memcpy((msg+MAC_HEADER_SIZE_BYTES),(void*)&device->openair0_cfg,sizeof(openair0_config_t)); + memcpy((msg+MAC_HEADER_SIZE_BYTES),(void*)device->openair0_cfg,sizeof(openair0_config_t)); if (send(eth->sockfd[Mod_id], msg, @@ -311,7 +311,8 @@ int eth_get_dev_conf_raw(openair0_device *device) { /* RRH stores the remote MAC address */ memcpy(eh.ether_dhost,(msg+ETH_ALEN),ETH_ALEN); - memcpy((void*)&device->openair0_cfg,(msg + MAC_HEADER_SIZE_BYTES), sizeof(openair0_config_t)); + //memcpy((void*)&device->openair0_cfg,(msg + MAC_HEADER_SIZE_BYTES), sizeof(openair0_config_t)); + device->openair0_cfg=(openair0_config_t *)(msg + MAC_HEADER_SIZE_BYTES); printf("[%s] binding mod_%d to hardware address %x:%x:%x:%x:%x:%x hardware address %x:%x:%x:%x:%x:%x\n",((device->host_type == BBU_HOST) ? "BBU": "RRH"),Mod_id,eh.ether_shost[0],eh.ether_shost[1],eh.ether_shost[2],eh.ether_shost[3],eh.ether_shost[4],eh.ether_shost[5],eh.ether_dhost[0],eh.ether_dhost[1],eh.ether_dhost[2],eh.ether_dhost[3],eh.ether_dhost[4],eh.ether_dhost[5]); return 0; diff --git a/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_udp.c b/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_udp.c index 27a8db7566..a9706c73bd 100644 --- a/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_udp.c +++ b/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_udp.c @@ -48,6 +48,7 @@ #include #include #include +#include "vcd_signal_dumper.h" #include "common_lib.h" #include "ethernet_lib.h" @@ -58,6 +59,10 @@ struct sockaddr_in local_addr[MAX_INST]; int addr_len[MAX_INST]; +uint16_t pck_seq_num = 1; +uint16_t pck_seq_num_cur=0; +uint16_t pck_seq_num_prev=0; + int eth_socket_init_udp(openair0_device *device) { int i = 0; @@ -122,9 +127,6 @@ int addr_len[MAX_INST]; exit(0); } - /* apply additional configuration */ - //ethernet_tune (device,MTU_SIZE,UDP_PACKET_SIZE_BYTES(device->openair0_cfg->samples_per_packet)); - /* want to receive -> so bind */ if (bind(eth->sockfd[Mod_id],(struct sockaddr *)&local_addr[Mod_id],addr_len[Mod_id])<0) { perror("ETHERNET: Cannot bind to socket"); @@ -133,8 +135,6 @@ int addr_len[MAX_INST]; printf("[%s] binding mod_%d to %s:%d\n","RRH",Mod_id,str_local,ntohs(local_addr[Mod_id].sin_port)); } - printf("ssssssssssssssss\n"); - return 0; } @@ -159,10 +159,15 @@ int trx_eth_write_udp(openair0_device *device, openair0_timestamp timestamp, voi bytes_sent = 0; - *(int16_t *)(buff2 + sizeof(int16_t))=1+(i<<1); + /* constract application header */ + // eth->pck_header.seq_num = pck_seq_num; + //eth->pck_header.antenna_id = 1+(i<<1); + //eth->pck_header.timestamp = timestamp; + *(uint16_t *)buff2 = pck_seq_num; + *(uint16_t *)(buff2 + sizeof(uint16_t)) = 1+(i<<1); *(openair0_timestamp *)(buff2 + sizeof(int32_t)) = timestamp; - - + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TX_SEQ_NUM, pck_seq_num); + while(bytes_sent < UDP_PACKET_SIZE_BYTES(nsamps)) { #if DEBUG printf("------- TX ------: buff2 current position=%d remaining_bytes=%d bytes_sent=%d \n", @@ -193,6 +198,8 @@ int trx_eth_write_udp(openair0_device *device, openair0_timestamp timestamp, voi #endif eth->tx_actual_nsamps=bytes_sent>>2; eth->tx_count++; + pck_seq_num++; + if ( pck_seq_num > MAX_PACKET_SEQ_NUM(nsamps,76800) ) pck_seq_num = 1; } } /* tx buffer values restored */ @@ -278,19 +285,28 @@ int trx_eth_read_udp(openair0_device *device, openair0_timestamp *timestamp, voi bytes_received); dump_packet((device->host_type == BBU_HOST)? "BBU":"RRH", buff2, UDP_PACKET_SIZE_BYTES(nsamps),RX_FLAG); #endif - /* store the timestamp value from packet's header */ - if (prev_timestamp == -1) { - prev_timestamp = *(openair0_timestamp *)(buff2 + sizeof(int32_t)); - } else { - prev_timestamp =timestamp; - } + /* store the timestamp value from packet's header */ *timestamp = *(openair0_timestamp *)(buff2 + sizeof(int32_t)); - eth->rx_actual_nsamps=bytes_received>>2; - eth->rx_count++; - } - - } + /* store the sequence number of the previous packet received */ + if (pck_seq_num_cur == 0) { + pck_seq_num_prev = *(uint16_t *)buff2; + } else { + pck_seq_num_prev = pck_seq_num_cur; + } + /* get the packet sequence number from packet's header */ + pck_seq_num_cur = *(uint16_t *)buff2; + //printf("cur=%d prev=%d buff=%d\n",pck_seq_num_cur,pck_seq_num_prev,*(uint16_t *)(buff2)); + if ( ( pck_seq_num_cur != (pck_seq_num_prev + 1) ) && !((pck_seq_num_prev==75) && (pck_seq_num_cur==1 ))){ + printf("out of order packet received1! %d|%d|%d\n",pck_seq_num_cur,pck_seq_num_prev, *timestamp); + } + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_RX_SEQ_NUM,pck_seq_num_cur); + VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_RX_SEQ_NUM_PRV,pck_seq_num_prev); + eth->rx_actual_nsamps=bytes_received>>2; + eth->rx_count++; + } + + } /* tx buffer values restored */ *(int32_t *)buff2 = temp0; *(openair0_timestamp *)(buff2 + sizeof(int32_t)) = temp1; @@ -316,7 +332,7 @@ int eth_set_dev_conf_udp(openair0_device *device) { msg=malloc(sizeof(openair0_config_t)); msg_len=sizeof(openair0_config_t); - memcpy(msg,(void*)&device->openair0_cfg,msg_len); + memcpy(msg,(void*)device->openair0_cfg,msg_len); if (sendto(eth->sockfd[Mod_id],msg,msg_len,0,(struct sockaddr *)&dest_addr[Mod_id],addr_len[Mod_id])==-1) { perror("ETHERNET: "); @@ -338,7 +354,7 @@ int eth_get_dev_conf_udp(openair0_device *device) { msg_len=sizeof(openair0_config_t); inet_ntop(AF_INET, &(local_addr[Mod_id].sin_addr), str, INET_ADDRSTRLEN); - inet_ntop(AF_INET, &(dest_addr[Mod_id].sin_addr), str1, INET_ADDRSTRLEN); + inet_ntop(AF_INET, &(dest_addr[Mod_id].sin_addr), str1, INET_ADDRSTRLEN); /* RRH receives from BBU openair0_config_t */ if (recvfrom(eth->sockfd[Mod_id], @@ -350,7 +366,7 @@ int eth_get_dev_conf_udp(openair0_device *device) { perror("ETHERNET: "); exit(0); } - memcpy((void*)&device->openair0_cfg,msg,msg_len); + device->openair0_cfg=(openair0_config_t *)msg; /* get remote ip address and port */ /* inet_ntop(AF_INET, &(dest_addr[Mod_id].sin_addr), str1, INET_ADDRSTRLEN); */ diff --git a/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c b/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c index bdce8dbf5d..15aa0d49a7 100644 --- a/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c +++ b/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c @@ -82,9 +82,12 @@ int trx_eth_start(openair0_device *device) { if(eth_get_dev_conf_udp(device)!=0) return -1; } /* adjust MTU wrt number of samples per packet */ - if(ethernet_tune (device,MTU_SIZE,UDP_PACKET_SIZE_BYTES(device->openair0_cfg->samples_per_packet))!=0) return -1; + //if(ethernet_tune (device,MTU_SIZE,UDP_PACKET_SIZE_BYTES(device->openair0_cfg->samples_per_packet))!=0) return -1; } - + /* apply additional configuration */ + if(ethernet_tune (device, SND_BUF_SIZE,2000000000)!=0) return -1; + if(ethernet_tune (device, RCV_BUF_SIZE,2000000000)!=0) return -1; + return 0; } @@ -335,13 +338,17 @@ int ethernet_tune(openair0_device *device, unsigned int option, int value) { -int transport_init(openair0_device *device, openair0_config_t *openair0_cfg, char *cfgfile) { +int transport_init(openair0_device *device, openair0_config_t *openair0_cfg, eth_params_t * eth_params ) { eth_state_t *eth = (eth_state_t*)malloc(sizeof(eth_state_t)); memset(eth, 0, sizeof(eth_state_t)); - eth->flags = ETH_RAW_MODE; - + if (eth_params->transp_preference == 1) { + eth->flags = ETH_RAW_MODE; + } else { + eth->flags = ETH_UDP_MODE; + } + printf("[ETHERNET]: Initializing openair0_device for %s ...\n", ((device->host_type == BBU_HOST) ? "BBU": "RRH")); device->Mod_id = num_devices_eth++; device->transp_type = ETHERNET_TP; @@ -362,13 +369,53 @@ int transport_init(openair0_device *device, openair0_config_t *openair0_cfg, cha device->trx_write_func = trx_eth_write_udp; device->trx_read_func = trx_eth_read_udp; } - /*hardcoded!!!!*/ - eth->if_name[device->Mod_id] = "eth0"; - device->priv = eth; - openair0_cfg->iq_txshift = 5; - openair0_cfg->iq_rxrescale = 15; - memcpy((void*)device->openair0_cfg,(void*)openair0_cfg,sizeof(openair0_config_t)); + + eth->if_name[device->Mod_id] = eth_params->local_if_name; + device->priv = eth; + + /* device specific */ + openair0_cfg[0].iq_txshift = 5; + openair0_cfg[0].iq_rxrescale = 15; + openair0_cfg[0].txlaunch_wait = 0; + openair0_cfg[0].txlaunch_wait_slotcount = 0; + + /* RRH does not have any information to make this configuration atm */ + if (device->host_type == BBU_HOST) { + /*Note scheduling advance values valid only for case 7680000 */ + switch ((int)openair0_cfg[0].sample_rate) { + case 30720000: + openair0_cfg[0].samples_per_packet = 4096; + openair0_cfg[0].tx_sample_advance = 0; + openair0_cfg[0].tx_scheduling_advance = 22*openair0_cfg[0].samples_per_packet; + break; + case 23040000: + openair0_cfg[0].samples_per_packet = 2048; + openair0_cfg[0].tx_sample_advance = 0; + openair0_cfg[0].tx_scheduling_advance = 16*openair0_cfg[0].samples_per_packet; + break; + case 15360000: + openair0_cfg[0].samples_per_packet = 2048; + openair0_cfg[0].tx_sample_advance = 0; + openair0_cfg[0].tx_scheduling_advance = 10*openair0_cfg[0].samples_per_packet; + break; + case 7680000: + openair0_cfg[0].samples_per_packet = 1024; + openair0_cfg[0].tx_sample_advance = 0; + openair0_cfg[0].tx_scheduling_advance = 10*openair0_cfg[0].samples_per_packet; + break; + case 1920000: + openair0_cfg[0].samples_per_packet = 256; + openair0_cfg[0].tx_sample_advance = 0; + openair0_cfg[0].tx_scheduling_advance = 16*openair0_cfg[0].samples_per_packet; + break; + default: + printf("Error: unknown sampling rate %f\n",openair0_cfg[0].sample_rate); + exit(-1); + break; + } + } + device->openair0_cfg=&openair0_cfg[0]; return 0; } @@ -414,8 +461,7 @@ void dump_dev(openair0_device *device) { device->openair0_cfg->tx_num_channels,device->openair0_cfg->rx_num_channels); printf(" Running flags: %s %s %s\n", ((eth->flags & ETH_RAW_MODE) ? "RAW socket mode - ":""), - ((eth->flags & ETH_UDP_MODE) ? "UDP socket mode - ":""), - ((eth->flags & ETH_LOOP_MODE) ? "loopback mode - ":"")); + ((eth->flags & ETH_UDP_MODE) ? "UDP socket mode - ":"")); printf(" Number of iqs dumped when displaying packets: %i\n\n",eth->iqdumpcnt); } diff --git a/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.h b/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.h index 7cf884f8ac..b4618bb825 100644 --- a/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.h +++ b/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.h @@ -53,33 +53,18 @@ #define DEFAULT_IF "lo" #define ETH_RAW_MODE 1 -#define ETH_UDP_MODE (1<<1) -#define ETH_LOOP_MODE (1<<2) +#define ETH_UDP_MODE 0 #define TX_FLAG 1 #define RX_FLAG 0 - +#define MAX_PACKET_SEQ_NUM(spp,spf) (spf/spp) #define MAC_HEADER_SIZE_BYTES (sizeof(struct ether_header)) #define APP_HEADER_SIZE_BYTES (sizeof(int32_t) + sizeof(openair0_timestamp)) #define PAYLOAD_SIZE_BYTES(nsamps) (nsamps<<2) #define UDP_PACKET_SIZE_BYTES(nsamps) (APP_HEADER_SIZE_BYTES + PAYLOAD_SIZE_BYTES(nsamps)) #define RAW_PACKET_SIZE_BYTES(nsamps) (APP_HEADER_SIZE_BYTES + MAC_HEADER_SIZE_BYTES + PAYLOAD_SIZE_BYTES(nsamps)) -/* -#define RRH_DEST_MAC0 0x74 -#define RRH_DEST_MAC1 0xd4 -#define RRH_DEST_MAC2 0x35 -#define RRH_DEST_MAC3 0xcc -#define RRH_DEST_MAC4 0x88 -#define RRH_DEST_MAC5 0x45 -#define BBU_DEST_MAC0 0xd4 -#define BBU_DEST_MAC1 0xbe -#define BBU_DEST_MAC2 0xd9 -#define BBU_DEST_MAC3 0x22 -#define BBU_DEST_MAC4 0x0a -#define BBU_DEST_MAC5 0xac -*/ /*!\brief opaque ethernet data structure */ typedef struct { @@ -142,12 +127,12 @@ typedef struct { /*!\brief packet header */ typedef struct { + /*!\brief packet sequence number max value=packets per frame*/ + uint16_t seq_num ; + /*!\brief antenna port used to resynchronize */ + uint16_t antenna_id; /*!\brief packet's timestamp */ openair0_timestamp timestamp; - /*!\brief variable declared for alignment purposes (sample size=32 bit) */ - int16_t not_used; - /*!\brief antenna port used to resynchronize */ - int16_t antenna_id; } header_t; /*!\brief different options for ethernet tuning in socket and driver level */ From 48f1154444405b9f457f67c703144a40bb32d210 Mon Sep 17 00:00:00 2001 From: Aikaterini Date: Sun, 7 Feb 2016 20:07:05 +0100 Subject: [PATCH 207/263] make changes to use the fronthaul configuration parameters - updates to rrh_gw.c and eNB_transport.c wrt to changes in openair0_device struct --- cmake_targets/build_oai | 2 +- .../ARCH/BLADERF/USERSPACE/LIB/bladerf_lib.c | 7 +- targets/ARCH/COMMON/common_lib.c | 43 +++---- targets/ARCH/COMMON/common_lib.h | 119 ++++++++++-------- targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp | 10 +- .../CONF/enb.band7.tm1.rrh.usrpb210.conf | 26 ++-- targets/RT/USER/eNB_transport_IQ.c | 33 +++-- targets/RT/USER/lte-softmodem.c | 115 +++++++++-------- targets/RT/USER/rrh_gw.c | 10 +- 9 files changed, 197 insertions(+), 168 deletions(-) diff --git a/cmake_targets/build_oai b/cmake_targets/build_oai index c7259813c6..6496ef1794 100755 --- a/cmake_targets/build_oai +++ b/cmake_targets/build_oai @@ -97,7 +97,7 @@ Options ETHERNET , None Adds this trasport protocol support in compilation --oaisim - Makes the oaisim simulator. Hardware will be defaulted to "NO_VALUE". + Makes the oaisim simulator. Hardware will be defaulted to "None". --phy_simulators Makes the unitary tests Layer 1 simulators --core_simulators diff --git a/targets/ARCH/BLADERF/USERSPACE/LIB/bladerf_lib.c b/targets/ARCH/BLADERF/USERSPACE/LIB/bladerf_lib.c index 2d17dd3e58..0c471da0f9 100644 --- a/targets/ARCH/BLADERF/USERSPACE/LIB/bladerf_lib.c +++ b/targets/ARCH/BLADERF/USERSPACE/LIB/bladerf_lib.c @@ -828,8 +828,13 @@ int openair0_dev_init_bladerf(openair0_device *device, openair0_config_t *openai brf_state_t *brf = (brf_state_t*)malloc(sizeof(brf_state_t)); memset(brf, 0, sizeof(brf_state_t)); + /* device specific */ + openair0_cfg->txlaunch_wait = 1; + openair0_cfg->txlaunch_wait_slotcount = 1; /* device specific */ + openair0_cfg->iq_txshift = 5; + openair0_cfg->iq_rxrescale = 15; + // init required params - switch ((int)openair0_cfg->sample_rate) { case 30720000: openair0_cfg->samples_per_packet = 2048; diff --git a/targets/ARCH/COMMON/common_lib.c b/targets/ARCH/COMMON/common_lib.c index c5a542fbc7..bc886e807b 100644 --- a/targets/ARCH/COMMON/common_lib.c +++ b/targets/ARCH/COMMON/common_lib.c @@ -90,23 +90,24 @@ int set_transport(openair0_device *device) { } -/* FT: looking for the rh interface library and load it */ -int load_lib(openair0_device *device, openair0_config_t *openair0_cfg, char *cfgfile, uint8_t flag) { +/* look for the interface library and load it */ +int load_lib(openair0_device *device, openair0_config_t *openair0_cfg, eth_params_t * cfg, uint8_t flag) { void *lib_handle; - oai_device_initfunc_t fp ; + oai_device_initfunc_t dp ; + oai_transport_initfunc_t tp ; - if (flag == RF_DEVICE) { + if (flag == BBU_LOCAL_RADIO_HEAD) { lib_handle = dlopen(OAI_RF_LIBNAME, RTLD_LAZY); if (!lib_handle) { printf( "Unable to locate %s: HW device set to NONE_DEV.\n", OAI_RF_LIBNAME); return 0; } - fp = dlsym(lib_handle,"device_init"); + dp = dlsym(lib_handle,"device_init"); - if (fp != NULL ) { - fp(device,openair0_cfg,cfgfile); + if (dp != NULL ) { + dp(device,openair0_cfg); } else { fprintf(stderr, "%s %d:oai device intializing function not found %s\n", __FILE__, __LINE__, dlerror()); return -1; @@ -118,10 +119,10 @@ int load_lib(openair0_device *device, openair0_config_t *openair0_cfg, char *cfg return 0; } - fp = dlsym(lib_handle,"transport_init"); + tp = dlsym(lib_handle,"transport_init"); - if (fp != NULL ) { - fp(device,openair0_cfg,cfgfile); + if (tp != NULL ) { + tp(device,openair0_cfg,cfg); } else { fprintf(stderr, "%s %d:oai device intializing function not found %s\n", __FILE__, __LINE__, dlerror()); return -1; @@ -136,10 +137,7 @@ int load_lib(openair0_device *device, openair0_config_t *openair0_cfg, char *cfg int openair0_device_load(openair0_device *device, openair0_config_t *openair0_cfg) { int rc; - static char *cfgfile; - uint8_t flag=RF_DEVICE; - /* FT: rewritten for shared library, common, radio head interface implementation */ - rc=load_lib(device, openair0_cfg, NULL,flag); + rc=load_lib(device, openair0_cfg, NULL,BBU_LOCAL_RADIO_HEAD ); if ( rc >= 0) { if ( set_device(device) < 0) { fprintf(stderr, "%s %d:Unsupported radio head\n",__FILE__, __LINE__); @@ -150,20 +148,23 @@ int openair0_device_load(openair0_device *device, openair0_config_t *openair0_cf return 0; } -int openair0_transport_load(openair0_device *device, openair0_config_t *openair0_cfg) { +int openair0_transport_load(openair0_device *device, openair0_config_t *openair0_cfg, eth_params_t * eth_params) { int rc; - static char *cfgfile; - uint8_t flag=TRANSPORT_PROTOCOL; - - /* FT: rewritten for shared library, common, radio head interface implementation */ - rc=load_lib(device, openair0_cfg, NULL,flag); + rc=load_lib(device, openair0_cfg, eth_params, BBU_REMOTE_RADIO_HEAD); if ( rc >= 0) { if ( set_transport(device) < 0) { - fprintf(stderr, "%s %d:Unsupported radio head\n",__FILE__, __LINE__); + fprintf(stderr, "%s %d:Unsupported transport protocol\n",__FILE__, __LINE__); return -1; } } return 0; } + + + + + + + diff --git a/targets/ARCH/COMMON/common_lib.h b/targets/ARCH/COMMON/common_lib.h index 500a7cb2c3..7f0f95d41b 100644 --- a/targets/ARCH/COMMON/common_lib.h +++ b/targets/ARCH/COMMON/common_lib.h @@ -47,16 +47,9 @@ /* name of shared library implementing the transport */ #define OAI_TP_LIBNAME "liboai_transpro.so" -/* flags for BBU to determine whether RF front end is local or remote -Note: currently lte-softmodem supports either a local RF device or a remote. */ -#define BBU_LOCAL_RF_ENABLED 1 -#define BBU_REMOTE_RF_ENABLED 2 -#define BBU_LOCAL_REMOTE_RF_ENABLED 3 -/*flags for load_lib() used to specify whether a RF device or a transport protocol library is loaded */ -#define TRANSPORT_PROTOCOL 1 -#define RF_DEVICE 2 - - +/* flags for BBU to determine whether the attached radio head is local or remote */ +#define BBU_LOCAL_RADIO_HEAD 0 +#define BBU_REMOTE_RADIO_HEAD 1 typedef int64_t openair0_timestamp; typedef volatile int64_t openair0_vtimestamp; @@ -81,6 +74,49 @@ typedef enum { } duplex_mode_t; +/*!\brief RF device types + */ +typedef enum { + MIN_RF_DEV_TYPE = 0, + /*!\brief device is ExpressMIMO */ + EXMIMO_DEV, + /*!\brief device is USRP B200/B210*/ + USRP_B200_DEV, + /*!\brief device is USRP X300/X310*/ + USRP_X300_DEV, + /*!\brief device is BLADE RF*/ + BLADERF_DEV, + /*!\brief device is NONE*/ + NONE_DEV, + MAX_RF_DEV_TYPE + +} dev_type_t; + +/*!\brief transport protocol types + */ +typedef enum { + MIN_TRANSP_TYPE = 0, + /*!\brief transport protocol ETHERNET */ + ETHERNET_TP, + /*!\brief no transport protocol*/ + NONE_TP, + MAX_TRANSP_TYPE + +} transport_type_t; + + +/*!\brief openair0 device host type */ +typedef enum { + MIN_HOST_TYPE = 0, + /*!\brief device functions within a BBU */ + BBU_HOST, + /*!\brief device functions within a RRH */ + RRH_HOST, + MAX_HOST_TYPE + +}host_type_t; + + /** @addtogroup _PHY_RF_INTERFACE_ * @{ */ @@ -167,50 +203,21 @@ typedef struct { int chain; } openair0_rf_map; +typedef struct { + char *remote_addr; + //! remote port number for Ethernet interface + unsigned int remote_port; + //! local IP/MAC addr for Ethernet interface (eNB/BBU, UE) + char *my_addr; + //! local port number for Ethernet interface (eNB/BBU, UE) + unsigned int my_port; + //! local port number for Ethernet interface (eNB/BBU, UE) + char *local_if_name; + //! local port number for Ethernet interface (eNB/BBU, UE) + uint8_t transp_preference; +} eth_params_t; -/*!\brief RF device types - */ -typedef enum { - MIN_RF_DEV_TYPE = 0, - /*!\brief device is ExpressMIMO */ - EXMIMO_DEV, - /*!\brief device is USRP B200/B210*/ - USRP_B200_DEV, - /*!\brief device is USRP X300/X310*/ - USRP_X300_DEV, - /*!\brief device is BLADE RF*/ - BLADERF_DEV, - /*!\brief device is NONE*/ - NONE_DEV, - MAX_RF_DEV_TYPE - -} dev_type_t; - -/*!\brief transport protocol types - */ -typedef enum { - MIN_TRANSP_TYPE = 0, - /*!\brief transport protocol ETHERNET */ - ETHERNET_TP, - /*!\brief no transport protocol*/ - NONE_TP, - MAX_TRANSP_TYPE - -} transport_type_t; - - -/*!\brief openair0 device host type */ -typedef enum { - MIN_HOST_TYPE = 0, - /*!\brief device functions within a BBU */ - BBU_HOST, - /*!\brief device functions within a RRH */ - RRH_HOST, - MAX_HOST_TYPE - -}host_type_t; - struct openair0_device_t { /*!brief Module ID of this device */ int Mod_id; @@ -309,17 +316,19 @@ struct openair0_device_t { }; /* type of device init function, implemented in shared lib */ -typedef int(*oai_device_initfunc_t)(openair0_device *device, openair0_config_t *openair0_cfg, char *cfgfile); +typedef int(*oai_device_initfunc_t)(openair0_device *device, openair0_config_t *openair0_cfg); +/* type of transport init function, implemented in shared lib */ +typedef int(*oai_transport_initfunc_t)(openair0_device *device, openair0_config_t *openair0_cfg, eth_params_t * eth_params); #ifdef __cplusplus extern "C" { #endif - /*! \brief Initialize openair RF target. It returns 0 if OK */ +/*! \brief Initialize openair RF target. It returns 0 if OK */ int openair0_device_load(openair0_device *device, openair0_config_t *openair0_cfg); /*! \brief Initialize transport protocol . It returns 0 if OK */ - int openair0_transport_load(openair0_device *device, openair0_config_t *openair0_cfg); + int openair0_transport_load(openair0_device *device, openair0_config_t *openair0_cfg, eth_params_t * eth_params); //USRP /*! \brief Get the current timestamp of USRP */ diff --git a/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp b/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp index 95df41562c..dc9191a613 100644 --- a/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp +++ b/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp @@ -387,7 +387,7 @@ int trx_usrp_reset_stats(openair0_device* device) { extern "C" { - int device_init(openair0_device* device, openair0_config_t *openair0_cfg, char *cfgfile) { + int device_init(openair0_device* device, openair0_config_t *openair0_cfg) { uhd::set_thread_priority_safe(1.0); usrp_state_t *s = (usrp_state_t*)malloc(sizeof(usrp_state_t)); @@ -444,7 +444,7 @@ extern "C" { //s->usrp->set_master_clock_rate(usrp_master_clock); openair0_cfg[0].rx_gain_calib_table = calib_table_x310; - + switch ((int)openair0_cfg[0].sample_rate) { case 30720000: // from usrp_time_offset @@ -554,6 +554,12 @@ extern "C" { } } + /* device specific */ + openair0_cfg[0].iq_txshift = 5; + openair0_cfg[0].iq_rxrescale = 15; + openair0_cfg[0].txlaunch_wait = 1; + openair0_cfg[0].txlaunch_wait_slotcount = 1; + for(i=0;iusrp->get_rx_num_channels();i++) { if (iusrp->set_rx_rate(openair0_cfg[0].sample_rate,i); diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.rrh.usrpb210.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.rrh.usrpb210.conf index 95bad9da5b..7c41297238 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.rrh.usrpb210.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.rrh.usrpb210.conf @@ -28,7 +28,7 @@ eNBs = tdd_config_s = 0; prefix_type = "NORMAL"; eutra_band = 7; - downlink_frequency = 2680000000L; + downlink_frequency = 2660000000L; uplink_frequency_offset = -120000000; Nid_cell = 0; N_RB_DL = 25; @@ -36,7 +36,7 @@ eNBs = nb_antennas_tx = 1; nb_antennas_rx = 1; tx_gain = 90; - rx_gain = 120; + rx_gain = 125; prach_root = 0; prach_config_index = 0; prach_high_speed = "DISABLE"; @@ -143,17 +143,17 @@ eNBs = rrh_gw_config = ( { local_if_name = "eth0"; - #remote_addr = "169.254.8.28"; - #remote_addr = "127.0.0.1"; - #remote_addr = "74:d4:35:cc:88:45"; - #local_addr = "169.254.7.91"; - #local_addr = "127.0.0.1"; - #local_addr = "d4:be:d9:22:0a:ac"; - local_address = "192.168.12.242" ; - remote_address = "192.168.12.31" ; - local_port = 50000; - remote_port = 50001; - active = "no"; + remote_address = "169.254.8.28"; + #remote_address = "127.0.0.1"; + #remote_address = "74:d4:35:cc:88:45"; + local_address = "169.254.7.91"; + #local_address = "127.0.0.1"; + #local_address = "d4:be:d9:22:0a:ac"; + #local_address = "192.168.12.242" ; + #remote_address = "192.168.12.31" ; + local_port = 50001; + remote_port = 50000; + active = "no"; preference = "udp"; } diff --git a/targets/RT/USER/eNB_transport_IQ.c b/targets/RT/USER/eNB_transport_IQ.c index 3580e876f6..594b075941 100644 --- a/targets/RT/USER/eNB_transport_IQ.c +++ b/targets/RT/USER/eNB_transport_IQ.c @@ -143,10 +143,9 @@ void config_BBU_mod( rrh_module_t *mod_enb, uint8_t RT_flag, uint8_t NRT_flag) { /* init socket and have handshake-like msg with client to exchange parameters */ mod_enb->eth_dev.trx_start_func(&mod_enb->eth_dev);//change port make it plus_id - printf("sdfs\n"); - memcpy((void*)mod_enb->devs->openair0_cfg,(void *)mod_enb->eth_dev.openair0_cfg,sizeof(openair0_config_t)); - printf("sdfs\n"); + mod_enb->devs->openair0_cfg = mod_enb->eth_dev.openair0_cfg; + /* check sanity of configuration parameters and print */ check_dev_config(mod_enb); @@ -387,7 +386,7 @@ void *rrh_eNB_rx_thread(void *arg) { while (rrh_exit == 0) { while (rx_pos <(1 + subframe)*samples_per_subframe) { - LOG_D(RRH,"starting a new send:%d %d\n",sync_trx,frame); + //LOG_D(RRH,"starting a new send:%d %d\n",sync_trx,frame); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_RX, 1 ); VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_HW_FRAME_RX, frame); VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_HW_SUBFRAME_RX, subframe ); @@ -508,7 +507,7 @@ void *rrh_eNB_rx_thread(void *arg) { next_rx_pos=(rx_pos+spp_eth); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_RX, 0 ); - /**/ + /* if (frame>50) { pthread_mutex_lock(&sync_trx_mutex); while (sync_trx) { @@ -518,7 +517,7 @@ void *rrh_eNB_rx_thread(void *arg) { LOG_D(RRH,"out of while send:%d %d\n",sync_trx,frame); pthread_cond_signal(&sync_trx_cond); pthread_mutex_unlock(&sync_trx_mutex); - } + }*/ } // while subframe++; @@ -591,14 +590,14 @@ void *rrh_eNB_tx_thread(void *arg) { while (rrh_exit == 0) { while (tx_pos < (1 + subframe)*samples_per_subframe) { - LOG_D(RRH,"bef lock read:%d %d\n",sync_trx,frame); - pthread_mutex_lock(&sync_trx_mutex); + //LOG_D(RRH,"bef lock read:%d %d\n",sync_trx,frame); + //pthread_mutex_lock(&sync_trx_mutex); - while (!sync_trx) { - LOG_D(RRH,"in sync read:%d %d\n",sync_trx,frame); - pthread_cond_wait(&sync_trx_cond,&sync_trx_mutex); - } - LOG_D(RRH,"out of while read:%d %d\n",sync_trx,frame); + //while (!sync_trx) { + //LOG_D(RRH,"in sync read:%d %d\n",sync_trx,frame); + //pthread_cond_wait(&sync_trx_cond,&sync_trx_mutex); + //} + //LOG_D(RRH,"out of while read:%d %d\n",sync_trx,frame); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_TX, 1 ); VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_HW_FRAME, frame); @@ -660,10 +659,10 @@ void *rrh_eNB_tx_thread(void *arg) { tx_pos += spp_eth; pck_tx++; - VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_TX, 0 ); - sync_trx=0; - pthread_cond_signal(&sync_trx_cond); - pthread_mutex_unlock(&sync_trx_mutex); + //VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_TX, 0 ); + //sync_trx=0; + //pthread_cond_signal(&sync_trx_cond); + //pthread_mutex_unlock(&sync_trx_mutex); } /* wrap around tx buffer index */ diff --git a/targets/RT/USER/lte-softmodem.c b/targets/RT/USER/lte-softmodem.c index 00ede275b2..698882b38a 100644 --- a/targets/RT/USER/lte-softmodem.c +++ b/targets/RT/USER/lte-softmodem.c @@ -372,9 +372,12 @@ int16_t osa_log_verbosity = LOG_MED; char *rrh_UE_ip = "127.0.0.1"; int rrh_UE_port = 51000; #endif -/* flag given in runtime to specify if the RF head is local or remote (default option is local RF)*/ -uint8_t local_remote_RF = BBU_LOCAL_RF_ENABLED; - + +/* flag set by eNB conf file to specify if the radio head is local or remote (default option is local) */ +uint8_t local_remote_radio = BBU_LOCAL_RADIO_HEAD; +/* struct for ethernet specific parameters given in eNB conf file */ +eth_params_t *eth_params; + char uecap_xer[1024],uecap_xer_in=0; extern void *UE_thread(void *arg); extern void init_UE_threads(void); @@ -997,12 +1000,12 @@ void do_OFDM_mod_rt(int subframe,PHY_VARS_eNB *phy_vars_eNB) if (tx_offset>=(LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*phy_vars_eNB->lte_frame_parms.samples_per_tti)) tx_offset -= LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*phy_vars_eNB->lte_frame_parms.samples_per_tti; - ((short*)&phy_vars_eNB->lte_eNB_common_vars.txdata[0][aa][tx_offset])[0] = ((short*)dummy_tx_b)[2*i]<lte_eNB_common_vars.txdata[0][aa][tx_offset])[0] = ((short*)dummy_tx_b)[2*i]<lte_eNB_common_vars.txdata[0][aa][tx_offset])[1] = ((short*)dummy_tx_b)[2*i+1]<lte_eNB_common_vars.txdata[0][aa][tx_offset])[1] = ((short*)dummy_tx_b)[2*i+1]<lte_eNB_common_vars.txdata[0][aa][tx_offset])[0]= #ifdef EXMIMO ((short*)dummy_tx_b)[2*i]<<4; @@ -1019,7 +1022,7 @@ void do_OFDM_mod_rt(int subframe,PHY_VARS_eNB *phy_vars_eNB) #else ((short*)dummy_tx_b)[2*i+1]<<4; #endif -*/ + } // if S-subframe switch to RX in second subframe if (subframe_select(&phy_vars_eNB->lte_frame_parms,subframe) == SF_S) { @@ -1918,12 +1921,15 @@ static void* eNB_thread( void* arg ) // USRP_DEBUG is active rt_sleep_ns(1000000); #endif - -/* FT configurable tx lauch delay (in slots )*/ + /* FT configurable tx lauch delay (in slots )*/ if ( (frame>50) && (tx_launched == 0) && ((openair0_cfg[card].txlaunch_wait == 0) || ((openair0_cfg[card].txlaunch_wait == 1) && - (rx_pos >= (((2*hw_subframe)+openair0_cfg[card].txlaunch_wait_slotcount)*PHY_vars_eNB_g[0][0]->lte_frame_parms.samples_per_tti>>1))))) { + (rx_pos >= (((2*hw_subframe)+openair0_cfg[card].txlaunch_wait_slotcount)*PHY_vars_eNB_g[0][0]->lte_frame_parms.samples_per_tti>>1))))) { + /* if ((frame>50) && + (tx_launched == 0) && + (rx_pos >= (((2*hw_subframe)+1)*PHY_vars_eNB_g[0][0]->lte_frame_parms.samples_per_tti>>1))) {*/ + tx_launched = 1; for (CC_id=0; CC_idproperties[i]->nb_rrh_gw; j++) { - if (enb_properties->properties[i]->rrh_gw_config[j].active == 1 ){ - // replace printf by setting + if (enb_properties->properties[i]->rrh_gw_config[j].active == 1 ) { + local_remote_radio = BBU_REMOTE_RADIO_HEAD; + eth_params = (eth_params_t*)malloc(sizeof(eth_params_t)); + memset(eth_params, 0, sizeof(eth_params_t)); + printf( "\n\tRRH GW %d config for eNB %u:\n\n", j, i); printf( "\tinterface name : \t%s:\n",enb_properties->properties[i]->rrh_gw_if_name); printf( "\tlocal address : \t%s:\n",enb_properties->properties[i]->rrh_gw_config[j].local_address); @@ -2475,6 +2484,16 @@ static void get_options (int argc, char **argv) printf( "\tremote address : \t%s:\n",enb_properties->properties[i]->rrh_gw_config[j].remote_address); printf( "\tremote port : \t%d:\n",enb_properties->properties[i]->rrh_gw_config[j].remote_port); printf( "\ttransport : \t%s Ethernet:\n\n",(enb_properties->properties[i]->rrh_gw_config[j].raw == 1)? "RAW" : "UDP"); + + eth_params->local_if_name = enb_properties->properties[i]->rrh_gw_if_name; + eth_params->my_addr = enb_properties->properties[i]->rrh_gw_config[j].local_address; + eth_params->my_port = enb_properties->properties[i]->rrh_gw_config[j].local_port; + eth_params->remote_addr = enb_properties->properties[i]->rrh_gw_config[j].remote_address; + eth_params->remote_port = enb_properties->properties[i]->rrh_gw_config[j].remote_port; + eth_params->transp_preference = enb_properties->properties[i]->rrh_gw_config[j].raw; + + } else { + local_remote_radio = BBU_LOCAL_RADIO_HEAD; } } @@ -3022,30 +3041,13 @@ int main( int argc, char **argv ) else //FDD openair0_cfg[card].duplex_mode = duplex_mode_FDD; -#ifdef ETHERNET - - //openair0_cfg[card].remote_addr = "192.168.12.242"; - //openair0_cfg[card].remote_addr = "127.0.0.1"; - openair0_cfg[card].remote_addr = "74:d4:35:cc:88:45"; - openair0_cfg[card].remote_port = 50000; - //openair0_cfg[card].my_addr = "192.168.12.31"; - //openair0_cfg[card].my_addr = "127.0.0.1"; - openair0_cfg[card].my_addr = "d4:be:d9:22:0a:ac"; - openair0_cfg[card].my_port = 50000; - //openair0_cfg[card].my_port = 50001; - openair0_cfg[card].tx_scheduling_advance = 10; - openair0_cfg[card].tx_sample_advance = 0; - openair0_cfg[card].txlaunch_wait = 0; - openair0_cfg[card].txlaunch_wait_slotcount = 0; - - if (frame_parms[0]->N_RB_DL == 6) - openair0_cfg[card].samples_per_packet = 256; - else - openair0_cfg[card].samples_per_packet = 1024; - - printf("HW: samples_per_packet %d\n",openair0_cfg[card].samples_per_packet); -#endif + if (local_remote_radio == BBU_REMOTE_RADIO_HEAD) { + openair0_cfg[card].remote_addr = eth_params->remote_addr; + openair0_cfg[card].remote_port = eth_params->remote_port; + openair0_cfg[card].my_addr = eth_params->my_addr; + openair0_cfg[card].my_port = eth_params->my_port; + } printf("HW: Configuring card %d, nb_antennas_tx/rx %d/%d\n",card, ((UE_flag==0) ? PHY_vars_eNB_g[0][0]->lte_frame_parms.nb_antennas_tx : PHY_vars_UE_g[0][0]->lte_frame_parms.nb_antennas_tx), @@ -3123,29 +3125,32 @@ int main( int argc, char **argv ) openair0.transp_type = NONE_TP; openair0_cfg[0].log_level = glog_level; - - /* BBU can either have local or remote radio heads - local radio head option is set by default so the corresponding device is initiated */ - if (mode!=loop_through_memory){ - int ret; - ret= openair0_device_load(&openair0, &openair0_cfg[0]); - printf("openair0_device_load returns %d\n",ret); - if (ret<0) { - printf("Exiting, cannot initialize device\n"); - exit(-1); + int returns=-1; + /* BBU can have either a local or a remote radio head */ + if (local_remote_radio == BBU_LOCAL_RADIO_HEAD) { //local radio head active - load library of radio head and initiate it + if (mode!=loop_through_memory) { + returns=openair0_device_load(&openair0, &openair0_cfg[0]); + printf("openair0_device_init returns %d\n",returns); + if (returns<0) { + printf("Exiting, cannot initialize device\n"); + exit(-1); + } } - } - else if (mode==loop_through_memory) { - } - /* radio heads are remote so the trasnsport protocol is initiated */ - if (local_remote_RF == BBU_REMOTE_RF_ENABLED) { - if ((mode!=loop_through_memory) && - (openair0_transport_load(&openair0, &openair0_cfg[0]) <0)) { - printf("Exiting, cannot initialize transport protocol\n"); - exit(-1); + else if (mode==loop_through_memory) { + } + } else { //remote radio head active - load library of transport protocol and initiate it + if (mode!=loop_through_memory) { + returns=openair0_transport_load(&openair0, &openair0_cfg[0], eth_params); + printf("openair0_transport_init returns %d\n",returns); + if (returns<0) { + printf("Exiting, cannot initialize transport protocol\n"); + exit(-1); + } } else if (mode==loop_through_memory) { } } + //for EXMIMO //openair0_cfg[0].iq_rxrescale=15; /* default value if build with EXMIMO */ //rxrescale=openair0_cfg[0].iq_rxrescale; /* see comments near RX_IQRESCALELEN definition */ diff --git a/targets/RT/USER/rrh_gw.c b/targets/RT/USER/rrh_gw.c index bfdb01948e..70ca744321 100644 --- a/targets/RT/USER/rrh_gw.c +++ b/targets/RT/USER/rrh_gw.c @@ -200,7 +200,7 @@ static rrh_module_t new_module (unsigned int id) { memset(rrh_mod.eth_dev.openair0_cfg,0,sizeof(openair0_config_t)); /* get IP and MAC address */ get_address(if_name,eth_mode); - + if(eth_mode==ETH_UDP_MODE) { openair0_cfg.my_addr = &rrh_ip[0]; openair0_cfg.my_port = rrh_port; @@ -211,10 +211,14 @@ static rrh_module_t new_module (unsigned int id) { LOG_I(RRH,"RAW mode selected for ethernet.\n"); } - /* if use setrunnig parameters we should keep in device->priv keep if_name and raw/udp flag*/ + /* */ + eth_params_t *eth_params = (eth_params_t*)malloc(sizeof(eth_params_t)); + memset(eth_params, 0, sizeof(eth_params_t)); + eth_params->local_if_name = if_name; + eth_params->transp_preference = eth_mode; /* ethernet device initialization */ - if (openair0_transport_load(&rrh_mod.eth_dev, &openair0_cfg)<0,NULL) { + if (openair0_transport_load(&rrh_mod.eth_dev, &openair0_cfg,eth_params)<0) { LOG_E(RRH,"Exiting, cannot initialize ethernet interface.\n"); exit(-1); } From f40389054197a88c942a8cc7563ffc0396297f24 Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Mon, 8 Feb 2016 11:52:58 +0100 Subject: [PATCH 208/263] add sudo bladeRF firmware flash --- cmake_targets/tools/build_helper | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cmake_targets/tools/build_helper b/cmake_targets/tools/build_helper index 496096e972..d29dbffe13 100755 --- a/cmake_targets/tools/build_helper +++ b/cmake_targets/tools/build_helper @@ -180,7 +180,7 @@ check_install_bladerf_driver(){ $SUDO apt-get install -y bladerf libbladerf-dev $SUDO apt-get install -y bladerf-firmware-fx3 $SUDO apt-get install -y bladerf-fpga-hostedx40 - bladeRF-cli --flash-firmware /usr/share/Nuand/bladeRF/bladeRF_fw.img + $SUDO bladeRF-cli --flash-firmware /usr/share/Nuand/bladeRF/bladeRF_fw.img } check_install_additional_tools (){ From 2fbbbdf080d16d1dffc128c04ae4f961e24655c3 Mon Sep 17 00:00:00 2001 From: Aikaterini Date: Mon, 8 Feb 2016 13:49:10 +0100 Subject: [PATCH 209/263] add check for fronthaul conf params --- openair2/ENB_APP/enb_config.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/openair2/ENB_APP/enb_config.c b/openair2/ENB_APP/enb_config.c index 0fd5dbe0e8..b437c7e264 100755 --- a/openair2/ENB_APP/enb_config.c +++ b/openair2/ENB_APP/enb_config.c @@ -2166,6 +2166,7 @@ const Enb_properties_array_t *enb_config_init(char* lib_config_file_name_pP) } // RRH Config setting_rrh_gws = config_setting_get_member (setting_enb, ENB_CONFIG_STRING_RRH_GW_CONFIG); + if ( setting_rrh_gws != NULL) { num_rrh_gw = config_setting_length(setting_rrh_gws); enb_properties.properties[enb_properties_index]->nb_rrh_gw = 0; @@ -2209,6 +2210,17 @@ const Enb_properties_array_t *enb_config_init(char* lib_config_file_name_pP) enb_properties.properties[enb_properties_index]->rrh_gw_config[j].raw = 1; } } + } else { + enb_properties.properties[enb_properties_index]->nb_rrh_gw = 0; + enb_properties.properties[enb_properties_index]->rrh_gw_if_name = "none"; + enb_properties.properties[enb_properties_index]->rrh_gw_config[j].local_address = "0.0.0.0"; + enb_properties.properties[enb_properties_index]->rrh_gw_config[j].remote_address = "0.0.0.0"; + enb_properties.properties[enb_properties_index]->rrh_gw_config[j].local_port= 0; + enb_properties.properties[enb_properties_index]->rrh_gw_config[j].remote_port= 0; + enb_properties.properties[enb_properties_index]->rrh_gw_config[j].active = 0; + enb_properties.properties[enb_properties_index]->rrh_gw_config[j].udp = 0; + enb_properties.properties[enb_properties_index]->rrh_gw_config[j].raw = 0; + } // SCTP SETTING enb_properties.properties[enb_properties_index]->sctp_out_streams = SCTP_OUT_STREAMS; From 3a1874a145a022c3192d10dbb57165f89726a1b9 Mon Sep 17 00:00:00 2001 From: Aikaterini Date: Mon, 8 Feb 2016 13:50:36 +0100 Subject: [PATCH 210/263] add openair0_cgf params in device libraries for tx triggering and IQ samples shift --- targets/ARCH/BLADERF/USERSPACE/LIB/bladerf_lib.c | 8 ++++---- targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c | 8 ++++---- targets/ARCH/EXMIMO/USERSPACE/LIB/openair0_lib.c | 8 +++++++- targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp | 8 ++++---- 4 files changed, 19 insertions(+), 13 deletions(-) diff --git a/targets/ARCH/BLADERF/USERSPACE/LIB/bladerf_lib.c b/targets/ARCH/BLADERF/USERSPACE/LIB/bladerf_lib.c index 0c471da0f9..295dcaded4 100644 --- a/targets/ARCH/BLADERF/USERSPACE/LIB/bladerf_lib.c +++ b/targets/ARCH/BLADERF/USERSPACE/LIB/bladerf_lib.c @@ -829,10 +829,10 @@ int openair0_dev_init_bladerf(openair0_device *device, openair0_config_t *openai brf_state_t *brf = (brf_state_t*)malloc(sizeof(brf_state_t)); memset(brf, 0, sizeof(brf_state_t)); /* device specific */ - openair0_cfg->txlaunch_wait = 1; - openair0_cfg->txlaunch_wait_slotcount = 1; /* device specific */ - openair0_cfg->iq_txshift = 5; - openair0_cfg->iq_rxrescale = 15; + openair0_cfg->txlaunch_wait = 1;//manage when TX processing is triggered + openair0_cfg->txlaunch_wait_slotcount = 1; //manage when TX processing is triggered + openair0_cfg->iq_txshift = 0;// shift + openair0_cfg->iq_rxrescale = 15;//rescale iqs // init required params switch ((int)openair0_cfg->sample_rate) { diff --git a/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c b/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c index 15aa0d49a7..cfdd67837b 100644 --- a/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c +++ b/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c @@ -374,10 +374,10 @@ int transport_init(openair0_device *device, openair0_config_t *openair0_cfg, eth device->priv = eth; /* device specific */ - openair0_cfg[0].iq_txshift = 5; - openair0_cfg[0].iq_rxrescale = 15; - openair0_cfg[0].txlaunch_wait = 0; - openair0_cfg[0].txlaunch_wait_slotcount = 0; + openair0_cfg[0].txlaunch_wait = 0;//manage when TX processing is triggered + openair0_cfg[0].txlaunch_wait_slotcount = 0; //manage when TX processing is triggered + openair0_cfg[0].iq_txshift = 5;// shift + openair0_cfg[0].iq_rxrescale = 15;//rescale iqs /* RRH does not have any information to make this configuration atm */ if (device->host_type == BBU_HOST) { diff --git a/targets/ARCH/EXMIMO/USERSPACE/LIB/openair0_lib.c b/targets/ARCH/EXMIMO/USERSPACE/LIB/openair0_lib.c index a1cc474435..427cd47be8 100644 --- a/targets/ARCH/EXMIMO/USERSPACE/LIB/openair0_lib.c +++ b/targets/ARCH/EXMIMO/USERSPACE/LIB/openair0_lib.c @@ -247,7 +247,7 @@ int openair0_stop_without_reset(int card) #define MY_RF_MODE (RXEN + TXEN + TXLPFNORM + TXLPFEN + TXLPF25 + RXLPFNORM + RXLPFEN + RXLPF25 + LNA1ON +LNAMax + RFBBNORM + DMAMODE_RX + DMAMODE_TX) #define RF_MODE_BASE (LNA1ON + RFBBNORM) -int device_init(openair0_device *device, openair0_config_t *openair0_cfg, char *cfgfile) { +int device_init(openair0_device *device, openair0_config_t *openair0_cfg) { // Initialize card // exmimo_config_t *p_exmimo_config; @@ -325,6 +325,12 @@ int openair0_config(openair0_config_t *openair0_cfg, int UE_flag) else p_exmimo_config->framing.multicard_syncmode=SYNCMODE_SLAVE; + /* device specific */ + openair0_cfg[card].txlaunch_wait = 1;//manage when TX processing is triggered + openair0_cfg[card].txlaunch_wait_slotcount = 1; //manage when TX processing is triggered + openair0_cfg[card].iq_txshift = 4;//shift + openair0_cfg[card].iq_rxrescale = 15;//rescale iqs + if (openair0_cfg[card].sample_rate==30.72e6) { resampling_factor = 0; rx_filter = RXLPF10; diff --git a/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp b/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp index dc9191a613..70ed21575d 100644 --- a/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp +++ b/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp @@ -555,10 +555,10 @@ extern "C" { } /* device specific */ - openair0_cfg[0].iq_txshift = 5; - openair0_cfg[0].iq_rxrescale = 15; - openair0_cfg[0].txlaunch_wait = 1; - openair0_cfg[0].txlaunch_wait_slotcount = 1; + openair0_cfg[0].txlaunch_wait = 1;//manage when TX processing is triggered + openair0_cfg[0].txlaunch_wait_slotcount = 1; //manage when TX processing is triggered + openair0_cfg[0].iq_txshift = 4;//shift + openair0_cfg[0].iq_rxrescale = 15;//rescale iqs for(i=0;iusrp->get_rx_num_channels();i++) { if (i Date: Mon, 8 Feb 2016 13:56:51 +0100 Subject: [PATCH 211/263] 1)remove option 'M' 2) tx shift value is set in device libraries 3) check for tx processing launching updated wrt alcatel suggestions --- targets/RT/USER/lte-softmodem.c | 65 +++++++-------------------------- 1 file changed, 13 insertions(+), 52 deletions(-) diff --git a/targets/RT/USER/lte-softmodem.c b/targets/RT/USER/lte-softmodem.c index 698882b38a..10f467874a 100644 --- a/targets/RT/USER/lte-softmodem.c +++ b/targets/RT/USER/lte-softmodem.c @@ -329,15 +329,6 @@ time_stats_t softmodem_stats_rx_sf[10]; // total rx time void reset_opp_meas(void); void print_opp_meas(void); int transmission_mode=1; -/* - FT: not a very clean way of managing the rescale of iqs in rx path, but this is done in - openair1/PHY/MODULATION/ul_7_5_kHz.c which doesn't have access to config parameters - to re-worked later..... - RX_IQRESCALELEN is setup in device libraries for all non expressmimo targets and acessed as an - external variable in ul_7_5_kHz.c. For expressmimo it is a macro (openair1/PHY/defs.h) - Regarding the value of this variable or macro: 18 is for 15 bits iqs, 15 is used for USRP, EXMIMO -*/ -//int rxrescale; int16_t glog_level = LOG_INFO; int16_t glog_verbosity = LOG_MED; @@ -482,7 +473,6 @@ void help (void) { printf(" -h provides this help message!\n"); printf(" -K Generate ITTI analyzser logs (similar to wireshark logs but with more details)\n"); printf(" -m Set the maximum downlink MCS\n"); - printf(" -M Specify whether RF head is local or remote,valid options: (1: local , 2:remote) \n"); printf(" -O eNB configuration file (located in targets/PROJECTS/GENERIC-LTE-EPC/CONF\n"); printf(" -q Enable processing timing measurement of lte softmodem on per subframe basis \n"); printf(" -r Set the PRB, valid values: 6, 25, 50, 100 \n"); @@ -1000,29 +990,12 @@ void do_OFDM_mod_rt(int subframe,PHY_VARS_eNB *phy_vars_eNB) if (tx_offset>=(LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*phy_vars_eNB->lte_frame_parms.samples_per_tti)) tx_offset -= LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*phy_vars_eNB->lte_frame_parms.samples_per_tti; - // ((short*)&phy_vars_eNB->lte_eNB_common_vars.txdata[0][aa][tx_offset])[0] = ((short*)dummy_tx_b)[2*i]<lte_eNB_common_vars.txdata[0][aa][tx_offset])[1] = ((short*)dummy_tx_b)[2*i+1]<lte_eNB_common_vars.txdata[0][aa][tx_offset])[0]= -#ifdef EXMIMO - ((short*)dummy_tx_b)[2*i]<<4; -#elif OAI_BLADERF - ((short*)dummy_tx_b)[2*i]; -#else - ((short*)dummy_tx_b)[2*i]<<4; -#endif - ((short*)&phy_vars_eNB->lte_eNB_common_vars.txdata[0][aa][tx_offset])[1]= -#ifdef EXMIMO - ((short*)dummy_tx_b)[2*i+1]<<4; -#elif OAI_BLADERF - ((short*)dummy_tx_b)[2*i+1]; -#else - ((short*)dummy_tx_b)[2*i+1]<<4; -#endif + ((short*)&phy_vars_eNB->lte_eNB_common_vars.txdata[0][aa][tx_offset])[0] = ((short*)dummy_tx_b)[2*i]<lte_eNB_common_vars.txdata[0][aa][tx_offset])[1] = ((short*)dummy_tx_b)[2*i+1]<lte_frame_parms,subframe) == SF_S) { @@ -1921,14 +1894,16 @@ static void* eNB_thread( void* arg ) // USRP_DEBUG is active rt_sleep_ns(1000000); #endif - /* FT configurable tx lauch delay (in slots )*/ + /* FT configurable tx lauch delay (in slots): txlaunch_wait, txlaunch_wait_slotcount is device specific and + set in the corresponding library (with txlaunch_wait=1 and txlaunch_wait_slotcount=1 the check is as it previously was) */ + /* old check: + if ((frame>50) && + (tx_launched == 0) && + (rx_pos >= (((2*hw_subframe)+1)*PHY_vars_eNB_g[0][0]->lte_frame_parms.samples_per_tti>>1))) {*/ if ( (frame>50) && (tx_launched == 0) && ((openair0_cfg[card].txlaunch_wait == 0) || ((openair0_cfg[card].txlaunch_wait == 1) && - (rx_pos >= (((2*hw_subframe)+openair0_cfg[card].txlaunch_wait_slotcount)*PHY_vars_eNB_g[0][0]->lte_frame_parms.samples_per_tti>>1))))) { - /* if ((frame>50) && - (tx_launched == 0) && - (rx_pos >= (((2*hw_subframe)+1)*PHY_vars_eNB_g[0][0]->lte_frame_parms.samples_per_tti>>1))) {*/ + (rx_pos >= (((2*hw_subframe)+openair0_cfg[card].txlaunch_wait_slotcount)*PHY_vars_eNB_g[0][0]->lte_frame_parms.samples_per_tti>>1))))) { tx_launched = 1; @@ -2222,12 +2197,7 @@ static void get_options (int argc, char **argv) case LONG_OPTION_DUMP_FRAME: mode = rx_dump_frame; - break; - - case 'M': - local_remote_radio=atoi(optarg); - break; - + break; case 'A': timing_advance = atoi (optarg); break; @@ -3001,11 +2971,6 @@ int main( int argc, char **argv ) for (card=0; cardN_RB_DL == 100) { if (frame_parms[0]->threequarter_fs) { openair0_cfg[card].sample_rate=23.04e6; @@ -3151,10 +3116,6 @@ int main( int argc, char **argv ) } } - //for EXMIMO - //openair0_cfg[0].iq_rxrescale=15; /* default value if build with EXMIMO */ - //rxrescale=openair0_cfg[0].iq_rxrescale; /* see comments near RX_IQRESCALELEN definition */ - printf("Done\n"); mac_xface = malloc(sizeof(MAC_xface)); From b035bbb9876971272fd0c8dcb1f3c6773cc5d61f Mon Sep 17 00:00:00 2001 From: Aikaterini Date: Mon, 8 Feb 2016 13:58:00 +0100 Subject: [PATCH 212/263] add commment --- .../GENERIC-LTE-EPC/CONF/enb.band7.tm1.rrh.usrpb210.conf | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.rrh.usrpb210.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.rrh.usrpb210.conf index 7c41297238..e8d49cca18 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.rrh.usrpb210.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.rrh.usrpb210.conf @@ -149,11 +149,10 @@ rrh_gw_config = ( local_address = "169.254.7.91"; #local_address = "127.0.0.1"; #local_address = "d4:be:d9:22:0a:ac"; - #local_address = "192.168.12.242" ; - #remote_address = "192.168.12.31" ; + #for raw option local port must be the same to remote local_port = 50001; remote_port = 50000; - active = "no"; + active = "yes"; preference = "udp"; } From 62423d0c60864f40190788171ba3d98a41d11d8c Mon Sep 17 00:00:00 2001 From: Aikaterini Date: Mon, 8 Feb 2016 14:22:17 +0100 Subject: [PATCH 213/263] minor update --- .../ETHERNET/USERSPACE/LIB/ethernet_lib.c | 32 ------------------- 1 file changed, 32 deletions(-) diff --git a/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c b/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c index cfdd67837b..1582273d48 100644 --- a/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c +++ b/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c @@ -177,38 +177,6 @@ int ethernet_tune(openair0_device *device, unsigned int option, int value) { int ret=0; int i=0; - if (1==0) { - /***************** get working interface name ***************************/ - /* convert ascii ip address from config file to network binary format */ - inet_aton(device->openair0_cfg->my_addr, &ia); - /* look for the interface used, we have its ip address get info on all our network interfaces*/ - ids = if_nameindex(); - /* loop on these network interfaces */ - for (i=0; ids[i].if_index != 0 ; i++) { - /* skip unamed interfaces */ - if (ids[i].if_name == NULL) - continue; - /* get ip address of current network interface */ - strcpy(ifr.ifr_name,ids[i].if_name); - if (-1 == ioctl(eth->sockfd[Mod_id], SIOCGIFADDR, &ifr)) { - printf( " Interface %i: %s isn't configured (no ip addr), skipped\n",ids[i].if_index, ifr.ifr_name); - continue; - } - /* test if this is the interface to be used */ - if ( ((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr.s_addr != ia.s_addr) - continue; - /* store interface name */ - if_name = ids[i].if_name; - break; - - } - if_freenameindex(ids); - if( if_name == NULL) { - printf("Unable to find interface name for %s\n",device->openair0_cfg->my_addr); - return -1; - } - eth->if_name[Mod_id]=if_name; - } /****************** socket level options ************************/ switch(option) { case SND_BUF_SIZE: /* transmit socket buffer size */ From de6a3ab9ed9befe90e4e147c5200ed65690c74e0 Mon Sep 17 00:00:00 2001 From: Aikaterini Date: Mon, 8 Feb 2016 14:22:42 +0100 Subject: [PATCH 214/263] remove print --- targets/RT/USER/lte-softmodem.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/targets/RT/USER/lte-softmodem.c b/targets/RT/USER/lte-softmodem.c index 10f467874a..baba632de1 100644 --- a/targets/RT/USER/lte-softmodem.c +++ b/targets/RT/USER/lte-softmodem.c @@ -993,8 +993,6 @@ void do_OFDM_mod_rt(int subframe,PHY_VARS_eNB *phy_vars_eNB) ((short*)&phy_vars_eNB->lte_eNB_common_vars.txdata[0][aa][tx_offset])[0] = ((short*)dummy_tx_b)[2*i]<lte_eNB_common_vars.txdata[0][aa][tx_offset])[1] = ((short*)dummy_tx_b)[2*i+1]< 50) { clock_gettime( CLOCK_MONOTONIC, &trx_time2 ); - // BMC: compute time between rx and tx - update_difftimes(trx_time1, trx_time2); + //update_difftimes(trx_time1, trx_time2); } From a7289a6daff6ef2a6c58360efcf783ce00f21be0 Mon Sep 17 00:00:00 2001 From: Aikaterini Date: Mon, 8 Feb 2016 19:48:45 +0100 Subject: [PATCH 215/263] update build_oai CMakelists.txt wrt lowlatency flag --- cmake_targets/CMakeLists.txt | 3 --- cmake_targets/build_oai | 1 + targets/RT/USER/rrh_gw.c | 2 +- 3 files changed, 2 insertions(+), 4 deletions(-) diff --git a/cmake_targets/CMakeLists.txt b/cmake_targets/CMakeLists.txt index ee16fd6707..a125219982 100644 --- a/cmake_targets/CMakeLists.txt +++ b/cmake_targets/CMakeLists.txt @@ -469,7 +469,6 @@ elseif (${RF_BOARD} STREQUAL "OAI_USRP") ${OPENAIR_TARGETS}/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp) LINK_DIRECTORIES("/opt/lib") set(option_HW_lib "-luhd -rdynamic -ldl") - set(LOWLATENCY False) elseif (${RF_BOARD} STREQUAL "OAI_BLADERF") include_directories("${OPENAIR_TARGETS}/ARCH/BLADERF/USERSPACE/LIB/") @@ -480,7 +479,6 @@ elseif (${RF_BOARD} STREQUAL "OAI_BLADERF") ) LINK_DIRECTORIES("/usr/lib/x86_64-linux-gnu") set(option_HW_lib "bladeRF -rdynamic -ldl") - #set(LOWLATENCY False) elseif (${RF_BOARD} STREQUAL "CPRIGW") #to ask set(HW_SOURCE ${HW_SOURCE} @@ -501,7 +499,6 @@ if (${TRANSP_PRO} STREQUAL "ETHERNET") ${OPENAIR_TARGETS}/ARCH/ETHERNET/USERSPACE/LIB/eth_raw.c ) set(option_TP_lib "-rdynamic -ldl") - set(LOWLATENCY True) endif (${TRANSP_PRO} STREQUAL "ETHERNET") diff --git a/cmake_targets/build_oai b/cmake_targets/build_oai index 6496ef1794..f3b30bc7aa 100755 --- a/cmake_targets/build_oai +++ b/cmake_targets/build_oai @@ -631,6 +631,7 @@ function main() { echo "set(RF_BOARD \"${HW}\")" >> $cmake_file echo "set(TRANSP_PRO \"${TP}\")" >> $cmake_file echo 'set(PACKAGE_NAME "\"rrh_gw\"")' >> $cmake_file + echo "set (LOWLATENCY \"${LOWLATENCY_FLAG_USER}\" )" >>$cmake_file echo 'include(${CMAKE_CURRENT_SOURCE_DIR}/../CMakeLists.txt)' >> $cmake_file cd $DIR/$rrh_build_dir/build cmake .. diff --git a/targets/RT/USER/rrh_gw.c b/targets/RT/USER/rrh_gw.c index 70ca744321..87c4d4d77d 100644 --- a/targets/RT/USER/rrh_gw.c +++ b/targets/RT/USER/rrh_gw.c @@ -355,7 +355,7 @@ static void print_help(void) { puts("\t -u create UE module\n"); puts("\t -g define global log level\n"); puts("\t -i set the RRH interface (default lo)\n"); - puts("\t -m set ethernet mode to be used by RRH, valid options: (1:raw, 2:udp) \n"); + puts("\t -m set ethernet mode to be used by RRH, valid options: (1:raw, 0:udp) \n"); puts("\t -r define rrh log level\n"); puts("\t -e define eNB log level\n"); puts("\t -x enable real time bahaviour\n"); From 301f617ad62180e9190d79578389204f160edfc2 Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Mon, 8 Feb 2016 20:17:21 +0100 Subject: [PATCH 216/263] updates for BladeRF (moved to mozart) --- cmake_targets/autotests/test_case_list.xml | 92 +++++++++++----------- 1 file changed, 46 insertions(+), 46 deletions(-) diff --git a/cmake_targets/autotests/test_case_list.xml b/cmake_targets/autotests/test_case_list.xml index 03f10ce578..8bf6bd4cfb 100644 --- a/cmake_targets/autotests/test_case_list.xml +++ b/cmake_targets/autotests/test_case_list.xml @@ -4622,7 +4622,7 @@ lte-softmodem - calisson + mozart stevens amerique 390 @@ -4640,16 +4640,16 @@ targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf nb_antennas_rx 1 targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf nb_antennas_tx 1 targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf pdsch_referenceSignalPower -29 - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf ENB_INTERFACE_NAME_FOR_S1_MME \"eth1\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf ENB_IPV4_ADDRESS_FOR_S1_MME \"192.168.12.82/24\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf ENB_INTERFACE_NAME_FOR_S1U \"eth1\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf ENB_IPV4_ADDRESS_FOR_S1U \"192.168.12.82/24\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf ENB_INTERFACE_NAME_FOR_S1_MME \"eth0\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf ENB_IPV4_ADDRESS_FOR_S1_MME \"192.168.12.111/24\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf ENB_INTERFACE_NAME_FOR_S1U \"eth0\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf ENB_IPV4_ADDRESS_FOR_S1U \"192.168.12.111/24\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf ENB_PORT_FOR_S1U 2152 $OPENAIR_DIR/cmake_targets/build_oai --eNB -w BLADERF -x -c sudo -E $OPENAIR_DIR/cmake_targets/tools/start_bladerf.py - $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem + sudo -E chrt -f 99 $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf -W @@ -4698,7 +4698,7 @@ lte-softmodem - calisson + mozart stevens amerique 390 @@ -4715,23 +4715,23 @@ targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf frame_type \"FDD\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf nb_antennas_rx 1 targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf nb_antennas_tx 1 - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf pdsch_referenceSignalPower -32 - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf ENB_INTERFACE_NAME_FOR_S1_MME \"eth1\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf ENB_IPV4_ADDRESS_FOR_S1_MME \"192.168.12.82/24\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf ENB_INTERFACE_NAME_FOR_S1U \"eth1\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf ENB_IPV4_ADDRESS_FOR_S1U \"192.168.12.82/24\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf pdsch_referenceSignalPower -29 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf ENB_INTERFACE_NAME_FOR_S1_MME \"eth0\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf ENB_IPV4_ADDRESS_FOR_S1_MME \"192.168.12.111/24\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf ENB_INTERFACE_NAME_FOR_S1U \"eth0\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf ENB_IPV4_ADDRESS_FOR_S1U \"192.168.12.111/24\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf ENB_PORT_FOR_S1U 2152 $OPENAIR_DIR/cmake_targets/build_oai --eNB -w BLADERF -x -c sudo -E $OPENAIR_DIR/cmake_targets/tools/start_bladerf.py - $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem + sudo -E chrt -f 99 $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf -W - True + False /tmp @@ -4773,7 +4773,7 @@ lte-softmodem - calisson + mozart stevens amerique 390 @@ -4790,23 +4790,23 @@ targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf frame_type \"FDD\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf nb_antennas_rx 1 targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf nb_antennas_tx 1 - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf pdsch_referenceSignalPower -35 - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf ENB_INTERFACE_NAME_FOR_S1_MME \"eth1\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf ENB_IPV4_ADDRESS_FOR_S1_MME \"192.168.12.82/24\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf ENB_INTERFACE_NAME_FOR_S1U \"eth1\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf ENB_IPV4_ADDRESS_FOR_S1U \"192.168.12.82/24\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf pdsch_referenceSignalPower -29 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf ENB_INTERFACE_NAME_FOR_S1_MME \"eth0\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf ENB_IPV4_ADDRESS_FOR_S1_MME \"192.168.12.111/24\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf ENB_INTERFACE_NAME_FOR_S1U \"eth0\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf ENB_IPV4_ADDRESS_FOR_S1U \"192.168.12.111/24\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf ENB_PORT_FOR_S1U 2152 $OPENAIR_DIR/cmake_targets/build_oai --eNB -w BLADERF -x -c sudo -E $OPENAIR_DIR/cmake_targets/tools/start_bladerf.py - $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem + sudo -E chrt -f 99 $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf -W - True + False /tmp @@ -4848,7 +4848,7 @@ lte-softmodem - calisson + mozart stevens amerique 390 @@ -4865,23 +4865,23 @@ targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf frame_type \"FDD\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf nb_antennas_rx 1 targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf nb_antennas_tx 1 - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf pdsch_referenceSignalPower -29 - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf ENB_INTERFACE_NAME_FOR_S1_MME \"eth1\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf ENB_IPV4_ADDRESS_FOR_S1_MME \"192.168.12.82/24\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf ENB_INTERFACE_NAME_FOR_S1U \"eth1\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf ENB_IPV4_ADDRESS_FOR_S1U \"192.168.12.82/24\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf pdsch_referenceSignalPower -29 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf ENB_INTERFACE_NAME_FOR_S1_MME \"eth0\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf ENB_IPV4_ADDRESS_FOR_S1_MME \"192.168.12.111/24\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf ENB_INTERFACE_NAME_FOR_S1U \"eth0\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf ENB_IPV4_ADDRESS_FOR_S1U \"192.168.12.111/24\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf ENB_PORT_FOR_S1U 2152 $OPENAIR_DIR/cmake_targets/build_oai --eNB -w BLADERF -x -c sudo -E $OPENAIR_DIR/cmake_targets/tools/start_bladerf.py - $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem + sudo -E chrt -f 99 $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf -W - True + False /tmp @@ -4922,7 +4922,7 @@ lte-softmodem - calisson + mozart stevens amerique 390 @@ -4939,23 +4939,23 @@ targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf frame_type \"FDD\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf nb_antennas_rx 1 targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf nb_antennas_tx 1 - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf pdsch_referenceSignalPower -32 - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf ENB_INTERFACE_NAME_FOR_S1_MME \"eth1\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf ENB_IPV4_ADDRESS_FOR_S1_MME \"192.168.12.82/24\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf ENB_INTERFACE_NAME_FOR_S1U \"eth1\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf ENB_IPV4_ADDRESS_FOR_S1U \"192.168.12.82/24\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf pdsch_referenceSignalPower -29 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf ENB_INTERFACE_NAME_FOR_S1_MME \"eth0\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf ENB_IPV4_ADDRESS_FOR_S1_MME \"192.168.12.111/24\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf ENB_INTERFACE_NAME_FOR_S1U \"eth0\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf ENB_IPV4_ADDRESS_FOR_S1U \"192.168.12.111/24\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf ENB_PORT_FOR_S1U 2152 $OPENAIR_DIR/cmake_targets/build_oai --eNB -w BLADERF -x -c sudo -E $OPENAIR_DIR/cmake_targets/tools/start_bladerf.py - $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem + sudo -E chrt -f 99 $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf -W - True + False /tmp @@ -4996,7 +4996,7 @@ lte-softmodem - calisson + mozart stevens amerique 390 @@ -5013,23 +5013,23 @@ targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf frame_type \"FDD\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf nb_antennas_rx 1 targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf nb_antennas_tx 1 - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf pdsch_referenceSignalPower -35 - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf ENB_INTERFACE_NAME_FOR_S1_MME \"eth1\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf ENB_IPV4_ADDRESS_FOR_S1_MME \"192.168.12.82/24\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf ENB_INTERFACE_NAME_FOR_S1U \"eth1\" - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf ENB_IPV4_ADDRESS_FOR_S1U \"192.168.12.82/24\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf pdsch_referenceSignalPower -29 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf ENB_INTERFACE_NAME_FOR_S1_MME \"eth0\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf ENB_IPV4_ADDRESS_FOR_S1_MME \"192.168.12.111/24\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf ENB_INTERFACE_NAME_FOR_S1U \"eth0\" + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf ENB_IPV4_ADDRESS_FOR_S1U \"192.168.12.111/24\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf ENB_PORT_FOR_S1U 2152 $OPENAIR_DIR/cmake_targets/build_oai --eNB -w BLADERF -x -c sudo -E $OPENAIR_DIR/cmake_targets/tools/start_bladerf.py - $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem + sudo -E chrt -f 99 $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem -O $OPENAIR_DIR/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf -W - True + False /tmp From 2b61863abb857541f9ca7f13e8b9003df0f1dad9 Mon Sep 17 00:00:00 2001 From: kaltenbe Date: Tue, 9 Feb 2016 09:29:26 +0100 Subject: [PATCH 217/263] TX/RX Calibration procedures (lighter than full LMS procedures) --- cmake_targets/CMakeLists.txt | 6 +++--- targets/RT/USER/lte-softmodem.c | 12 ++++++++++-- 2 files changed, 13 insertions(+), 5 deletions(-) diff --git a/cmake_targets/CMakeLists.txt b/cmake_targets/CMakeLists.txt index eb19864e95..23325ace81 100644 --- a/cmake_targets/CMakeLists.txt +++ b/cmake_targets/CMakeLists.txt @@ -441,14 +441,14 @@ elseif (${RF_BOARD} STREQUAL "OAI_LMSSDR") include_directories("${OPENAIR_TARGETS}/ARCH/LMSSDR/USERSPACE/LIB") include_directories("${OPENAIR_TARGETS}/ARCH/LMSSDR/USERSPACE/LIB/lmsSDR") include_directories("${OPENAIR_TARGETS}/ARCH/LMSSDR/USERSPACE/LIB/lms7002m") -# include_directories("${OPENAIR_TARGETS}/ARCH/LMSSDR/USERSPACE/LIB/Si5351C") - include_directories("${OPENAIR_TARGETS}/ARCH/LMSSDR/USERSPACE/LIB/LMS_StreamBoard") + include_directories("${OPENAIR_TARGETS}/ARCH/LMSSDR/USERSPACE/LIB/Si5351C") + include_directories("${OPENAIR_TARGETS}/ARCH/LMSSDR/USERSPACE/LIB/lmsSDR/LMS_StreamBoard") set(HW_SOURCE ${HW_SOURCE} ${OPENAIR_TARGETS}/ARCH/LMSSDR/USERSPACE/LIB/lms_lib.cpp ) LINK_DIRECTORIES("/usr/lib/x86_64-linux-gnu") set(HW_SOURCE ${HW_SOURCE} ${OPENAIR_TARGETS}/ARCH/LMSSDR/USERSPACE/LIB/lms_lib.cpp) - set(LIB_LMS_LIBRARIES "${OPENAIR_TARGETS}/ARCH/LMSSDR/USERSPACE/LIB/lmsSDR/build/libLMS_SDR.so" "${OPENAIR_TARGETS}/ARCH/LMSSDR/USERSPACE/LIB/lms7002m/build/libLMS7002M.a") + set(LIB_LMS_LIBRARIES "${OPENAIR_TARGETS}/ARCH/LMSSDR/USERSPACE/LIB/lmsSDR/build/libLMS_SDR.so" "${OPENAIR_TARGETS}/ARCH/LMSSDR/USERSPACE/LIB/lms7002m/build/libLMS7002M.a" "${OPENAIR_TARGETS}/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/libSi5351C.a") set(LOWLATENCY False) elseif (${RF_BOARD} STREQUAL "ETHERNET") diff --git a/targets/RT/USER/lte-softmodem.c b/targets/RT/USER/lte-softmodem.c index a431b35498..7bfb56c6cb 100644 --- a/targets/RT/USER/lte-softmodem.c +++ b/targets/RT/USER/lte-softmodem.c @@ -941,10 +941,17 @@ void do_OFDM_mod_rt(int subframe,PHY_VARS_eNB *phy_vars_eNB) len = phy_vars_eNB->lte_frame_parms.samples_per_tti>>1; else len = phy_vars_eNB->lte_frame_parms.samples_per_tti; - - for (i=0; ilte_frame_parms.samples_per_tti; @@ -957,6 +964,7 @@ void do_OFDM_mod_rt(int subframe,PHY_VARS_eNB *phy_vars_eNB) #elif OAI_BLADERF ((short*)dummy_tx_b)[2*i]; #elif OAI_LMSSDR + //phy_vars_eNB->lte_eNB_common_vars.txdata[0][aa][tx_offset]=dummy_tx_b[i]; ((short*)dummy_tx_b)[2*i]; #else ((short*)dummy_tx_b)[2*i]<<4; From 908da0737b667406c33b1a65b4e46855fc695007 Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Tue, 9 Feb 2016 16:16:23 +0100 Subject: [PATCH 218/263] updated for RRH test cases --- cmake_targets/autotests/test_case_list.xml | 44 ++++++++++++++-------- 1 file changed, 28 insertions(+), 16 deletions(-) diff --git a/cmake_targets/autotests/test_case_list.xml b/cmake_targets/autotests/test_case_list.xml index 8bf6bd4cfb..197770498b 100644 --- a/cmake_targets/autotests/test_case_list.xml +++ b/cmake_targets/autotests/test_case_list.xml @@ -81,7 +81,8 @@ --eNB -w USRP -r Rel10 --noS1 -c $OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 $OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/rb_tool - $OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/CMakeFiles/nasmesh/nasmesh.ko + $OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/CMakeFiles/nasmesh/nasmesh.ko + $OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/liboai_usrpdevif.so @@ -122,7 +123,8 @@ --eNB -w BLADERF -r Rel10 --noS1 -c $OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 $OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/rb_tool - $OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/CMakeFiles/nasmesh/nasmesh.ko + $OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/CMakeFiles/nasmesh/nasmesh.ko + $OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/liboai_bladerfdevif.so @@ -138,10 +140,11 @@ Build lte_softmodem_noS1.ETHERNET.Rel10 $OPENAIR_DIR/cmake_targets/build_oai - --eNB -w ETHERNET -r Rel10 --noS1 -c + --eNB -w None -t ETHERNET -r Rel10 --noS1 -c $OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/lte-softmodem-nos1 $OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/rb_tool - $OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/CMakeFiles/nasmesh/nasmesh.ko + $OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/CMakeFiles/nasmesh/nasmesh.ko + $OPENAIR_DIR/cmake_targets/lte_noS1_build_oai/build/liboai_eth_transpro.so @@ -160,7 +163,8 @@ $OPENAIR_DIR/cmake_targets/build_oai --eNB -w USRP -r Rel10 -c - $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem + $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem + $OPENAIR_DIR/cmake_targets/lte_build_oai/build/liboai_usrpdevif.so @@ -197,7 +201,8 @@ $OPENAIR_DIR/cmake_targets/build_oai --eNB -w BLADERF -r Rel10 -c - $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem + $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem + $OPENAIR_DIR/cmake_targets/lte_build_oai/build/liboai_bladerfdevif.so @@ -213,8 +218,9 @@ Build lte_softmodem.ETHERNET.Rel10 $OPENAIR_DIR/cmake_targets/build_oai - --eNB -w ETHERNET -r Rel10 -c - $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem + --eNB -w None -t ETHERNET -r Rel10 -c + $OPENAIR_DIR/cmake_targets/lte_build_oai/build/lte-softmodem + $OPENAIR_DIR/cmake_targets/lte_build_oai/build/liboai_eth_transpro.so @@ -261,11 +267,13 @@ compilation - Build RRH Gateway + Build RRH Gateway for USRP(RF) + Ethernet (Transport) $OPENAIR_DIR/cmake_targets/build_oai - --RRH -w USRP -c - $OPENAIR_DIR/cmake_targets/rrh_gw/build/rrh_gw + --RRH -w USRP -t ETHERNET -c + $OPENAIR_DIR/cmake_targets/rrh_gw/build/rrh_gw + $OPENAIR_DIR/cmake_targets/rrh_gw/build/liboai_usrpdevif.so + $OPENAIR_DIR/cmake_targets/rrh_gw/build/liboai_eth_transpro.so @@ -278,14 +286,16 @@ compilation - Build RRH Gateway + Build RRH Gateway for EXMIMO(RF) + Ethernet (Transport) $OPENAIR_DIR/cmake_targets/build_oai - --RRH -w EXMIMO -c + --RRH -w EXMIMO -t ETHNERNET -c $OPENAIR_DIR/cmake_targets/rrh_gw/build/rrh_gw $OPENAIR_DIR/cmake_targets/rrh_gw/build/CMakeFiles/openair_rf/openair_rf.ko $OPENAIR_DIR/cmake_targets/rrh_gw/build/updatefw - $OPENAIR_DIR/cmake_targets/rrh_gw/build/oarf_config_exmimo.oct + $OPENAIR_DIR/cmake_targets/rrh_gw/build/oarf_config_exmimo.oct + $OPENAIR_DIR/cmake_targets/rrh_gw/build/liboai_exmimodevif.so + $OPENAIR_DIR/cmake_targets/rrh_gw/build/liboai_eth_transpro.so @@ -301,8 +311,10 @@ Build RRH Gateway $OPENAIR_DIR/cmake_targets/build_oai - --RRH -w BLADERF -c - $OPENAIR_DIR/cmake_targets/rrh_gw/build/rrh_gw + --RRH -w BLADERF -t ETHERNET -c + $OPENAIR_DIR/cmake_targets/rrh_gw/build/rrh_gw + $OPENAIR_DIR/cmake_targets/rrh_gw/build/liboai_bladerfdevif.so + $OPENAIR_DIR/cmake_targets/rrh_gw/build/liboai_eth_transpro.so From 5a284b2f4ab86fc6b2860eec6aac15f1f8bb1133 Mon Sep 17 00:00:00 2001 From: Aikaterini Date: Tue, 9 Feb 2016 16:20:24 +0100 Subject: [PATCH 219/263] remove dynamic linking for EXMIMO --- cmake_targets/build_oai | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/cmake_targets/build_oai b/cmake_targets/build_oai index f3b30bc7aa..3ee054bd61 100755 --- a/cmake_targets/build_oai +++ b/cmake_targets/build_oai @@ -661,9 +661,8 @@ function main() { if [ "$HW" == "EXMIMO" ] ; then #add exmimo compilation - - ln -s openair_rf.ko liboai_device.so - ln -s $dbin/openair_rf.ko $dbin/liboai_device.so + #TODO EXMIMO library support + echo_info "liboai_device.so is linked to EXMIMO device library" elif [ "$HW" == "OAI_USRP" ] ; then if [ -d "/usr/include/uhd" ] ; then From 6b517988035b9f7339203edebe0761887077f735 Mon Sep 17 00:00:00 2001 From: Aikaterini Date: Tue, 9 Feb 2016 17:57:29 +0100 Subject: [PATCH 220/263] update gtkwave file --- targets/RT/USER/rrh.gtkw | 108 +++++++++++++++++++++++++++++++++------ 1 file changed, 92 insertions(+), 16 deletions(-) diff --git a/targets/RT/USER/rrh.gtkw b/targets/RT/USER/rrh.gtkw index 22a5a9f575..891f23ada5 100644 --- a/targets/RT/USER/rrh.gtkw +++ b/targets/RT/USER/rrh.gtkw @@ -1,19 +1,19 @@ [*] [*] GTKWave Analyzer v3.3.58 (w)1999-2014 BSI -[*] Thu Sep 17 14:23:43 2015 +[*] Fri Jan 29 16:34:46 2016 [*] [dumpfile] "/tmp/openair_dump_rrh.vcd" -[dumpfile_mtime] "Thu Sep 17 14:21:43 2015" -[dumpfile_size] 636509125 -[savefile] "/home/guepe/openair4G/targets/RT/USER/rrh.gtkw" -[timestart] 17746655400 -[size] 1855 1056 -[pos] -1 -1 -*-15.826077 17746846200 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 +[dumpfile_mtime] "Fri Jan 29 16:20:55 2016" +[dumpfile_size] 224259458 +[savefile] "/home/guepe/openairinterface5g_rrh/openairinterface5g/targets/RT/USER/rrh.gtkw" +[timestart] 31315875900 +[size] 1004 1028 +[pos] 926 -1 +*-17.429794 31316090054 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 [sst_width] 224 -[signals_width] 230 +[signals_width] 261 [sst_expanded] 1 -[sst_vpaned_height] 287 +[sst_vpaned_height] 278 @24 [color] 1 variables.hw_frame_rx[63:0] @@ -23,7 +23,10 @@ variables.hw_subframe_rx[63:0] [color] 1 functions.eNB_rx functions.eNB_rx_sleep -functions.trx_write_rf +[color] 3 +functions.trx_read_rf +[color] 7 +functions.trx_write @c00024 variables.rxcnt[63:0] @28 @@ -95,24 +98,97 @@ variables.rxcnt[63:0] -group_end @24 variables.pck_rx[63:0] +variables.rx_ts[63:0] +@c00024 +variables.tx_seq_num[63:0] +@28 +(0)variables.tx_seq_num[63:0] +(1)variables.tx_seq_num[63:0] +(2)variables.tx_seq_num[63:0] +(3)variables.tx_seq_num[63:0] +(4)variables.tx_seq_num[63:0] +(5)variables.tx_seq_num[63:0] +(6)variables.tx_seq_num[63:0] +(7)variables.tx_seq_num[63:0] +(8)variables.tx_seq_num[63:0] +(9)variables.tx_seq_num[63:0] +(10)variables.tx_seq_num[63:0] +(11)variables.tx_seq_num[63:0] +(12)variables.tx_seq_num[63:0] +(13)variables.tx_seq_num[63:0] +(14)variables.tx_seq_num[63:0] +(15)variables.tx_seq_num[63:0] +(16)variables.tx_seq_num[63:0] +(17)variables.tx_seq_num[63:0] +(18)variables.tx_seq_num[63:0] +(19)variables.tx_seq_num[63:0] +(20)variables.tx_seq_num[63:0] +(21)variables.tx_seq_num[63:0] +(22)variables.tx_seq_num[63:0] +(23)variables.tx_seq_num[63:0] +(24)variables.tx_seq_num[63:0] +(25)variables.tx_seq_num[63:0] +(26)variables.tx_seq_num[63:0] +(27)variables.tx_seq_num[63:0] +(28)variables.tx_seq_num[63:0] +(29)variables.tx_seq_num[63:0] +(30)variables.tx_seq_num[63:0] +(31)variables.tx_seq_num[63:0] +(32)variables.tx_seq_num[63:0] +(33)variables.tx_seq_num[63:0] +(34)variables.tx_seq_num[63:0] +(35)variables.tx_seq_num[63:0] +(36)variables.tx_seq_num[63:0] +(37)variables.tx_seq_num[63:0] +(38)variables.tx_seq_num[63:0] +(39)variables.tx_seq_num[63:0] +(40)variables.tx_seq_num[63:0] +(41)variables.tx_seq_num[63:0] +(42)variables.tx_seq_num[63:0] +(43)variables.tx_seq_num[63:0] +(44)variables.tx_seq_num[63:0] +(45)variables.tx_seq_num[63:0] +(46)variables.tx_seq_num[63:0] +(47)variables.tx_seq_num[63:0] +(48)variables.tx_seq_num[63:0] +(49)variables.tx_seq_num[63:0] +(50)variables.tx_seq_num[63:0] +(51)variables.tx_seq_num[63:0] +(52)variables.tx_seq_num[63:0] +(53)variables.tx_seq_num[63:0] +(54)variables.tx_seq_num[63:0] +(55)variables.tx_seq_num[63:0] +(56)variables.tx_seq_num[63:0] +(57)variables.tx_seq_num[63:0] +(58)variables.tx_seq_num[63:0] +(59)variables.tx_seq_num[63:0] +(60)variables.tx_seq_num[63:0] +(61)variables.tx_seq_num[63:0] +(62)variables.tx_seq_num[63:0] +(63)variables.tx_seq_num[63:0] +@1401200 +-group_end +@24 variables.hw_frame[63:0] variables.hw_subframe[63:0] @28 [color] 1 functions.eNB_tx functions.eNB_tx_sleep -functions.trx_read_rf -[color] 7 -functions.trx_write [color] 7 functions.trx_read +[color] 3 +functions.trx_write_rf @24 variables.txcnt[63:0] -variables.rx_ts[63:0] +variables.pck_tx[63:0] variables.tx_ts[63:0] +@25 +variables.rx_seq_num_prv[63:0] +@24 +variables.rx_seq_num[63:0] variables.hw_cnt_rx[63:0] variables.lhw_cnt_rx[63:0] -@25 [color] 3 variables.cnt[63:0] [pattern_trace] 1 From b8dde7ba912f8ae6d02daf563f21cc5b95076a6b Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Wed, 10 Feb 2016 10:36:22 +0100 Subject: [PATCH 221/263] EXMIMO handling special case for device library --- targets/ARCH/COMMON/common_lib.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/targets/ARCH/COMMON/common_lib.c b/targets/ARCH/COMMON/common_lib.c index bc886e807b..791fbbeda6 100644 --- a/targets/ARCH/COMMON/common_lib.c +++ b/targets/ARCH/COMMON/common_lib.c @@ -151,14 +151,21 @@ int openair0_device_load(openair0_device *device, openair0_config_t *openair0_cf int openair0_transport_load(openair0_device *device, openair0_config_t *openair0_cfg, eth_params_t * eth_params) { int rc; - rc=load_lib(device, openair0_cfg, eth_params, BBU_REMOTE_RADIO_HEAD); - if ( rc >= 0) { - if ( set_transport(device) < 0) { + //ToDo: EXMIMO library is still not harmonized with rest of HW Targets (USRP, BladeRF). + if (device->type != EXMIMO_DEV) + { + rc=load_lib(device, openair0_cfg, eth_params, BBU_REMOTE_RADIO_HEAD); + if ( rc >= 0) { + if ( set_transport(device) < 0) { fprintf(stderr, "%s %d:Unsupported transport protocol\n",__FILE__, __LINE__); return -1; - } + } + } } - + else + { + device_init(device, openair0_cfg); + } return 0; } From 0340ec53f5558685a6ce31a7a2067f713a295e07 Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Wed, 10 Feb 2016 10:54:40 +0100 Subject: [PATCH 222/263] fixes for EXMIMO as it is not harmonized with dynamic library linking of HW targets --- targets/ARCH/COMMON/common_lib.c | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/targets/ARCH/COMMON/common_lib.c b/targets/ARCH/COMMON/common_lib.c index 791fbbeda6..6ba59660b3 100644 --- a/targets/ARCH/COMMON/common_lib.c +++ b/targets/ARCH/COMMON/common_lib.c @@ -137,6 +137,10 @@ int load_lib(openair0_device *device, openair0_config_t *openair0_cfg, eth_param int openair0_device_load(openair0_device *device, openair0_config_t *openair0_cfg) { int rc; + //ToDo: EXMIMO harmonization is not complete. That is the reason for this ifdef + #ifdef EXMIMO + device_init(device, openair0_cfg); + #else rc=load_lib(device, openair0_cfg, NULL,BBU_LOCAL_RADIO_HEAD ); if ( rc >= 0) { if ( set_device(device) < 0) { @@ -144,28 +148,19 @@ int openair0_device_load(openair0_device *device, openair0_config_t *openair0_cf return -1; } } - + #endif return 0; } int openair0_transport_load(openair0_device *device, openair0_config_t *openair0_cfg, eth_params_t * eth_params) { - int rc; - //ToDo: EXMIMO library is still not harmonized with rest of HW Targets (USRP, BladeRF). - if (device->type != EXMIMO_DEV) - { - rc=load_lib(device, openair0_cfg, eth_params, BBU_REMOTE_RADIO_HEAD); - if ( rc >= 0) { - if ( set_transport(device) < 0) { + rc=load_lib(device, openair0_cfg, eth_params, BBU_REMOTE_RADIO_HEAD); + if ( rc >= 0) { + if ( set_transport(device) < 0) { fprintf(stderr, "%s %d:Unsupported transport protocol\n",__FILE__, __LINE__); return -1; } - } } - else - { - device_init(device, openair0_cfg); - } return 0; } From c5c5d9d10ddbd762db6c974fefe47fd720f7c9e1 Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Wed, 10 Feb 2016 11:13:32 +0100 Subject: [PATCH 223/263] fix for bladeRF init --- targets/ARCH/BLADERF/USERSPACE/LIB/bladerf_lib.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/targets/ARCH/BLADERF/USERSPACE/LIB/bladerf_lib.c b/targets/ARCH/BLADERF/USERSPACE/LIB/bladerf_lib.c index 295dcaded4..3ab17bbfec 100644 --- a/targets/ARCH/BLADERF/USERSPACE/LIB/bladerf_lib.c +++ b/targets/ARCH/BLADERF/USERSPACE/LIB/bladerf_lib.c @@ -822,7 +822,7 @@ void calibrate_rf(openair0_device *device) { // write_output("blade_rf_test.m","rxs",calib_buff,RXDCLENGTH,1,1); } -int openair0_dev_init_bladerf(openair0_device *device, openair0_config_t *openair0_cfg) { +int device_init(openair0_device *device, openair0_config_t *openair0_cfg) { int status; int card=0; From da4f8bfc53845e4829161d58950a4d9efc5978cc Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Wed, 10 Feb 2016 18:47:49 +0100 Subject: [PATCH 224/263] update BladeRF TX calibration --- cmake_targets/autotests/test_case_list.xml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/cmake_targets/autotests/test_case_list.xml b/cmake_targets/autotests/test_case_list.xml index 8bf6bd4cfb..e97fdacf6c 100644 --- a/cmake_targets/autotests/test_case_list.xml +++ b/cmake_targets/autotests/test_case_list.xml @@ -4639,7 +4639,7 @@ targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf frame_type \"FDD\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf nb_antennas_rx 1 targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf nb_antennas_tx 1 - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf pdsch_referenceSignalPower -29 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf pdsch_referenceSignalPower -26 targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf ENB_INTERFACE_NAME_FOR_S1_MME \"eth0\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf ENB_IPV4_ADDRESS_FOR_S1_MME \"192.168.12.111/24\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf ENB_INTERFACE_NAME_FOR_S1U \"eth0\" @@ -4790,7 +4790,7 @@ targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf frame_type \"FDD\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf nb_antennas_rx 1 targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf nb_antennas_tx 1 - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf pdsch_referenceSignalPower -29 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf pdsch_referenceSignalPower -32 targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf ENB_INTERFACE_NAME_FOR_S1_MME \"eth0\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf ENB_IPV4_ADDRESS_FOR_S1_MME \"192.168.12.111/24\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf ENB_INTERFACE_NAME_FOR_S1U \"eth0\" @@ -4865,7 +4865,7 @@ targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf frame_type \"FDD\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf nb_antennas_rx 1 targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf nb_antennas_tx 1 - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf pdsch_referenceSignalPower -29 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf pdsch_referenceSignalPower -26 targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf ENB_INTERFACE_NAME_FOR_S1_MME \"eth0\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf ENB_IPV4_ADDRESS_FOR_S1_MME \"192.168.12.111/24\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf ENB_INTERFACE_NAME_FOR_S1U \"eth0\" @@ -5013,7 +5013,7 @@ targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf frame_type \"FDD\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf nb_antennas_rx 1 targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf nb_antennas_tx 1 - targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf pdsch_referenceSignalPower -29 + targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf pdsch_referenceSignalPower -32 targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf ENB_INTERFACE_NAME_FOR_S1_MME \"eth0\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf ENB_IPV4_ADDRESS_FOR_S1_MME \"192.168.12.111/24\" targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.bladerfx40.conf ENB_INTERFACE_NAME_FOR_S1U \"eth0\" From 051a4e2aa550ad3ac886e05149c498c18ab622a2 Mon Sep 17 00:00:00 2001 From: kaltenbe Date: Thu, 11 Feb 2016 10:04:36 +0100 Subject: [PATCH 225/263] added Si5351C directory changes in lmslib.cpp --- openair1/PHY/LTE_REFSIG/primary_synch.h | 28 - openair1/PHY/LTE_TRANSPORT/initial_sync.c | 25 +- openair1/PHY/LTE_TRANSPORT/print_stats.c | 6 +- openair1/SCHED/phy_procedures_lte_ue.c | 30 +- .../USERSPACE/LIB/Si5351C/CMakeLists.txt | 11 + .../LMSSDR/USERSPACE/LIB/Si5351C/Si5351C.cpp | 872 ++++++++++++++++++ .../LMSSDR/USERSPACE/LIB/Si5351C/Si5351C.h | 100 ++ .../LIB/Si5351C/build/CMakeCache.txt | 326 +++++++ .../CMakeFiles/2.8.12.2/CMakeCCompiler.cmake | 56 ++ .../2.8.12.2/CMakeCXXCompiler.cmake | 57 ++ .../2.8.12.2/CMakeDetermineCompilerABI_C.bin | Bin 0 -> 8587 bytes .../CMakeDetermineCompilerABI_CXX.bin | Bin 0 -> 8600 bytes .../CMakeFiles/2.8.12.2/CMakeSystem.cmake | 15 + .../2.8.12.2/CompilerIdC/CMakeCCompilerId.c | 389 ++++++++ .../CMakeFiles/2.8.12.2/CompilerIdC/a.out | Bin 0 -> 8683 bytes .../CompilerIdCXX/CMakeCXXCompilerId.cpp | 377 ++++++++ .../CMakeFiles/2.8.12.2/CompilerIdCXX/a.out | Bin 0 -> 8692 bytes .../CMakeDirectoryInformation.cmake | 16 + .../Si5351C/build/CMakeFiles/CMakeOutput.log | 263 ++++++ .../Si5351C/build/CMakeFiles/Makefile.cmake | 43 + .../LIB/Si5351C/build/CMakeFiles/Makefile2 | 102 ++ .../CMakeFiles/Si5351C.dir/CXX.includecache | 8 + .../CMakeFiles/Si5351C.dir/DependInfo.cmake | 22 + .../build/CMakeFiles/Si5351C.dir/Si5351C.o | Bin 0 -> 144184 bytes .../build/CMakeFiles/Si5351C.dir/build.make | 106 +++ .../CMakeFiles/Si5351C.dir/cmake_clean.cmake | 10 + .../Si5351C.dir/cmake_clean_target.cmake | 3 + .../CMakeFiles/Si5351C.dir/depend.internal | 6 + .../build/CMakeFiles/Si5351C.dir/depend.make | 6 + .../build/CMakeFiles/Si5351C.dir/flags.make | 8 + .../build/CMakeFiles/Si5351C.dir/link.txt | 2 + .../CMakeFiles/Si5351C.dir/progress.make | 2 + .../build/CMakeFiles/TargetDirectories.txt | 1 + .../build/CMakeFiles/cmake.check_cache | 1 + .../Si5351C/build/CMakeFiles/progress.marks | 1 + .../USERSPACE/LIB/Si5351C/build/Makefile | 157 ++++ .../LIB/Si5351C/build/cmake_install.cmake | 44 + .../USERSPACE/LIB/Si5351C/build/libSi5351C.a | Bin 0 -> 162342 bytes targets/RT/USER/lte-softmodem.c | 4 +- targets/RT/USER/lte-ue.c | 6 +- 40 files changed, 3038 insertions(+), 65 deletions(-) create mode 100644 targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/CMakeLists.txt create mode 100644 targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/Si5351C.cpp create mode 100644 targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/Si5351C.h create mode 100644 targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeCache.txt create mode 100644 targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/2.8.12.2/CMakeCCompiler.cmake create mode 100644 targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/2.8.12.2/CMakeCXXCompiler.cmake create mode 100755 targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/2.8.12.2/CMakeDetermineCompilerABI_C.bin create mode 100755 targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/2.8.12.2/CMakeDetermineCompilerABI_CXX.bin create mode 100644 targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/2.8.12.2/CMakeSystem.cmake create mode 100644 targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/2.8.12.2/CompilerIdC/CMakeCCompilerId.c create mode 100755 targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/2.8.12.2/CompilerIdC/a.out create mode 100644 targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/2.8.12.2/CompilerIdCXX/CMakeCXXCompilerId.cpp create mode 100755 targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/2.8.12.2/CompilerIdCXX/a.out create mode 100644 targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/CMakeDirectoryInformation.cmake create mode 100644 targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/CMakeOutput.log create mode 100644 targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/Makefile.cmake create mode 100644 targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/Makefile2 create mode 100644 targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/Si5351C.dir/CXX.includecache create mode 100644 targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/Si5351C.dir/DependInfo.cmake create mode 100644 targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/Si5351C.dir/Si5351C.o create mode 100644 targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/Si5351C.dir/build.make create mode 100644 targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/Si5351C.dir/cmake_clean.cmake create mode 100644 targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/Si5351C.dir/cmake_clean_target.cmake create mode 100644 targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/Si5351C.dir/depend.internal create mode 100644 targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/Si5351C.dir/depend.make create mode 100644 targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/Si5351C.dir/flags.make create mode 100644 targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/Si5351C.dir/link.txt create mode 100644 targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/Si5351C.dir/progress.make create mode 100644 targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/TargetDirectories.txt create mode 100644 targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/cmake.check_cache create mode 100644 targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/progress.marks create mode 100644 targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/Makefile create mode 100644 targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/cmake_install.cmake create mode 100644 targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/libSi5351C.a diff --git a/openair1/PHY/LTE_REFSIG/primary_synch.h b/openair1/PHY/LTE_REFSIG/primary_synch.h index f9cf6fc171..717f2e552c 100644 --- a/openair1/PHY/LTE_REFSIG/primary_synch.h +++ b/openair1/PHY/LTE_REFSIG/primary_synch.h @@ -1,31 +1,3 @@ -/******************************************************************************* - OpenAirInterface - Copyright(c) 1999 - 2014 Eurecom - - OpenAirInterface is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - - OpenAirInterface 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 General Public License for more details. - - You should have received a copy of the GNU General Public License - along with OpenAirInterface.The full GNU General Public License is - included in this distribution in the file called "COPYING". If not, - see . - - Contact Information - OpenAirInterface Admin: openair_admin@eurecom.fr - OpenAirInterface Tech : openair_tech@eurecom.fr - OpenAirInterface Dev : openair4g-devel@lists.eurecom.fr - - Address : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE - - *******************************************************************************/ short primary_synch0[144] = {0,0,0,0,0,0,0,0,0,0,32767,0,-26120,-19785,11971,-30502,-24020,-22288,32117,6492,31311,9658,-16384,-28378,25100,-21063,-7292,-31946,20429,25618,14948,29158,11971,-30502,31311,9658,25100,-21063,-16384,28377,-24020,22287,32117,6492,-7292,31945,20429,25618,-26120,-19785,-16384,-28378,-16384,28377,-26120,-19785,-32402,4883,31311,-9659,32117,6492,-7292,-31946,32767,-1,25100,-21063,-24020,22287,-32402,4883,-32402,4883,-24020,22287,25100,-21063,32767,-1,-7292,-31946,32117,6492,31311,-9659,-32402,4883,-26120,-19785,-16384,28377,-16384,-28378,-26120,-19785,20429,25618,-7292,31945,32117,6492,-24020,22287,-16384,28377,25100,-21063,31311,9658,11971,-30502,14948,29158,20429,25618,-7292,-31946,25100,-21063,-16384,-28378,31311,9658,32117,6492,-24020,-22288,11971,-30502,-26120,-19785,32767,0,0,0,0,0,0,0,0,0,0,0}; short primary_synch1[144] = {0,0,0,0,0,0,0,0,0,0,32767,0,-31754,-8086,-24020,-22288,2448,32675,-26120,19784,27073,18458,-16384,28377,25100,21062,-29523,14217,-7292,31945,-13477,-29868,-24020,-22288,27073,18458,25100,21062,-16384,-28378,2448,-32676,-26120,19784,-29523,-14218,-7292,31945,-31754,-8086,-16384,28377,-16384,-28378,-31754,-8086,31311,-9659,27073,-18459,-26120,19784,-29523,14217,32767,-1,25100,21062,2448,-32676,31311,-9659,31311,-9659,2448,-32676,25100,21062,32767,0,-29523,14217,-26120,19784,27073,-18459,31311,-9659,-31754,-8086,-16384,-28378,-16384,28377,-31754,-8086,-7292,31945,-29523,-14218,-26120,19784,2448,-32676,-16384,-28378,25100,21062,27073,18458,-24020,-22288,-13477,-29868,-7292,31945,-29523,14217,25100,21062,-16384,28377,27073,18458,-26120,19784,2448,32675,-24020,-22288,-31754,-8086,32767,0,0,0,0,0,0,0,0,0,0,0}; short primary_synch2[144] = {0,0,0,0,0,0,0,0,0,0,32767,0,-31754,8085,-24020,22287,2448,-32676,-26120,-19785,27073,-18459,-16384,-28378,25100,-21063,-29523,-14218,-7292,-31946,-13477,29867,-24020,22287,27073,-18459,25100,-21063,-16384,28377,2448,32675,-26120,-19785,-29523,14217,-7292,-31946,-31754,8085,-16384,-28378,-16384,28377,-31754,8085,31311,9658,27073,18458,-26120,-19785,-29523,-14218,32767,0,25100,-21063,2448,32675,31311,9658,31311,9658,2448,32675,25100,-21063,32767,0,-29523,-14218,-26120,-19785,27073,18458,31311,9658,-31754,8085,-16384,28377,-16384,-28378,-31754,8085,-7292,-31946,-29523,14217,-26120,-19785,2448,32675,-16384,28377,25100,-21063,27073,-18459,-24020,22287,-13477,29867,-7292,-31946,-29523,-14218,25100,-21063,-16384,-28378,27073,-18459,-26120,-19785,2448,-32676,-24020,22287,-31754,8085,32767,-1,0,0,0,0,0,0,0,0,0,0}; diff --git a/openair1/PHY/LTE_TRANSPORT/initial_sync.c b/openair1/PHY/LTE_TRANSPORT/initial_sync.c index 5c6b479b20..b8be6305de 100644 --- a/openair1/PHY/LTE_TRANSPORT/initial_sync.c +++ b/openair1/PHY/LTE_TRANSPORT/initial_sync.c @@ -48,7 +48,7 @@ #include "gain_control.h" #endif -#if defined(OAI_USRP) || defined(EXMIMO) +#if defined(OAI_USRP) || defined(EXMIMO) || defined(OAI_LMSSDR) #include "common_lib.h" extern openair0_config_t openair0_cfg[]; #endif @@ -291,17 +291,10 @@ int initial_sync(PHY_VARS_UE *phy_vars_ue, runmode_t mode) frame_parms->Ncp=NORMAL; frame_parms->frame_type=FDD; init_frame_parms(frame_parms,1); - - // write_output("rxdata0.m","rxd0",phy_vars_ue->lte_ue_common_vars.rxdata[0],10*frame_parms->samples_per_tti,1,1); - - /*#ifdef OAI_USRP - for (aarx = 0; aarxnb_antennas_rx;aarx++) { - rxdata128 = (__m128i*)phy_vars_ue->lte_ue_common_vars.rxdata[aarx]; - for (i=0; i<(frame_parms->samples_per_tti*10)>>2; i++) { - rxdata128[i] = _mm_srai_epi16(rxdata128[i],4); - } - } - #endif*/ + /* + write_output("rxdata0.m","rxd0",phy_vars_ue->lte_ue_common_vars.rxdata[0],10*frame_parms->samples_per_tti,1,1); + exit(-1); + */ sync_pos = lte_sync_time(phy_vars_ue->lte_ue_common_vars.rxdata, frame_parms, (int *)&phy_vars_ue->lte_ue_common_vars.eNb_id); @@ -336,9 +329,11 @@ int initial_sync(PHY_VARS_UE *phy_vars_ue, runmode_t mode) #else #ifndef OAI_USRP - #ifndef OAI_BLADERF +#ifndef OAI_BLADERF +#ifndef OAI_LMSSDR phy_adjust_gain(phy_vars_ue,0); - #endif +#endif +#endif #endif #endif @@ -569,7 +564,7 @@ int initial_sync(PHY_VARS_UE *phy_vars_ue, runmode_t mode) phy_vars_ue->lte_frame_parms.phich_config_common.phich_duration, phich_string[phy_vars_ue->lte_frame_parms.phich_config_common.phich_resource], phy_vars_ue->lte_frame_parms.nb_antennas_tx_eNB); -#if defined(OAI_USRP) || defined(EXMIMO) +#if defined(OAI_USRP) || defined(EXMIMO) || defined(OAI_LMSSDR) LOG_I(PHY,"[UE %d] Frame %d Measured Carrier Frequency %.0f Hz (offset %d Hz)\n", phy_vars_ue->Mod_id, phy_vars_ue->frame_rx, diff --git a/openair1/PHY/LTE_TRANSPORT/print_stats.c b/openair1/PHY/LTE_TRANSPORT/print_stats.c index a386e1cb30..8f6483a3e3 100644 --- a/openair1/PHY/LTE_TRANSPORT/print_stats.c +++ b/openair1/PHY/LTE_TRANSPORT/print_stats.c @@ -50,7 +50,7 @@ #endif extern int mac_get_rrc_status(uint8_t Mod_id,uint8_t eNB_flag,uint8_t index); -#if defined(OAI_USRP) || defined(EXMIMO) || defined(OAI_BLADERF) +#if defined(OAI_USRP) || defined(EXMIMO) || defined(OAI_BLADERF) || defined(OAI_LMSSDR) #include "common_lib.h" extern openair0_config_t openair0_cfg[]; #endif @@ -97,10 +97,10 @@ int dump_ue_stats(PHY_VARS_UE *phy_vars_ue, char* buffer, int length, runmode_t #ifdef EXMIMO len += sprintf(&buffer[len], "[UE PROC] RX Gain %d dB (LNA %d, vga %d dB)\n",phy_vars_ue->rx_total_gain_dB, openair0_cfg[0].rxg_mode[0],(int)openair0_cfg[0].rx_gain[0]); #endif -#if defined(OAI_USRP) || defined(OAI_BLADERF) +#if defined(OAI_USRP) || defined(OAI_BLADERF) || defined(OAI_LMSSDR) len += sprintf(&buffer[len], "[UE PROC] RX Gain %d dB\n",phy_vars_ue->rx_total_gain_dB); #endif -#if defined(EXMIMO) || defined(OAI_USRP) || defined(OAI_BLADERF) +#if defined(EXMIMO) || defined(OAI_USRP) || defined(OAI_BLADERF) || defined(OAI_LMSSDR) len += sprintf(&buffer[len], "[UE_PROC] Frequency offset %d Hz (%d), estimated carrier frequency %f Hz\n",phy_vars_ue->lte_ue_common_vars.freq_offset,openair_daq_vars.freq_offset,openair0_cfg[0].rx_freq[0]-phy_vars_ue->lte_ue_common_vars.freq_offset); #endif len += sprintf(&buffer[len], "[UE PROC] UE mode = %s (%d)\n",mode_string[phy_vars_ue->UE_mode[0]],phy_vars_ue->UE_mode[0]); diff --git a/openair1/SCHED/phy_procedures_lte_ue.c b/openair1/SCHED/phy_procedures_lte_ue.c index bc84beae43..c746fe7254 100755 --- a/openair1/SCHED/phy_procedures_lte_ue.c +++ b/openair1/SCHED/phy_procedures_lte_ue.c @@ -121,7 +121,7 @@ extern int rx_sig_fifo; #endif -#if defined(EXMIMO) || defined(OAI_USRP) +#if defined(EXMIMO) || defined(OAI_USRP) || defined(OAI_BLADERF) || defined(OAI_LMSSDR) extern uint32_t downlink_frequency[MAX_NUM_CCs][4]; #endif @@ -197,7 +197,7 @@ void dump_dlsch_SI(PHY_VARS_UE *phy_vars_ue,uint8_t eNB_id,uint8_t subframe) exit(-1); } -#if defined(EXMIMO) || defined(OAI_USRP) +#if defined(EXMIMO) || defined(OAI_USRP) || defined(OAI_BLADERF) || defined(OAI_LMSSDR) //unsigned int gain_table[31] = {100,112,126,141,158,178,200,224,251,282,316,359,398,447,501,562,631,708,794,891,1000,1122,1258,1412,1585,1778,1995,2239,2512,2818,3162}; /* unsigned int get_tx_amp_prach(int power_dBm, int power_max_dBm, int N_RB_UL) @@ -669,7 +669,7 @@ void phy_procedures_UE_TX(PHY_VARS_UE *phy_vars_ue,uint8_t eNB_id,uint8_t abstra uint8_t ack_status=0; int8_t Po_PUCCH; int32_t ulsch_start=0; -#if defined(EXMIMO) || defined(OAI_USRP) +#if defined(EXMIMO) || defined(OAI_USRP) || defined(OAI_BLADERF) || defined(OAI_LMSSDR) int overflow=0; int k,l; #endif @@ -969,7 +969,7 @@ void phy_procedures_UE_TX(PHY_VARS_UE *phy_vars_ue,uint8_t eNB_id,uint8_t abstra #endif phy_vars_ue->tx_total_RE = nb_rb*12; -#if defined(EXMIMO) || defined(OAI_USRP) +#if defined(EXMIMO) || defined(OAI_USRP) || defined(OAI_BLADERF) || defined(OAI_LMSSDR) tx_amp = get_tx_amp(phy_vars_ue->tx_power_dBm, phy_vars_ue->tx_power_max_dBm, phy_vars_ue->lte_frame_parms.N_RB_UL, @@ -1065,7 +1065,7 @@ void phy_procedures_UE_TX(PHY_VARS_UE *phy_vars_ue,uint8_t eNB_id,uint8_t abstra #endif phy_vars_ue->tx_total_RE = 12; -#if defined(EXMIMO) || defined(OAI_USRP) +#if defined(EXMIMO) || defined(OAI_USRP) || defined(OAI_BLADERF) || defined(OAI_LMSSDR) tx_amp = get_tx_amp(Po_PUCCH, phy_vars_ue->tx_power_max_dBm, phy_vars_ue->lte_frame_parms.N_RB_UL, @@ -1128,7 +1128,7 @@ void phy_procedures_UE_TX(PHY_VARS_UE *phy_vars_ue,uint8_t eNB_id,uint8_t abstra #endif phy_vars_ue->tx_total_RE = 12; -#if defined(EXMIMO) || defined(OAI_USRP) +#if defined(EXMIMO) || defined(OAI_USRP) || defined(OAI_BLADERF) || defined(OAI_LMSSDR) tx_amp = get_tx_amp(Po_PUCCH, phy_vars_ue->tx_power_max_dBm, phy_vars_ue->lte_frame_parms.N_RB_UL, @@ -1230,7 +1230,7 @@ void phy_procedures_UE_TX(PHY_VARS_UE *phy_vars_ue,uint8_t eNB_id,uint8_t abstra if (abstraction_flag == 0) { nsymb = (frame_parms->Ncp == 0) ? 14 : 12; -#if defined(EXMIMO) || defined(OAI_USRP) //this is the EXPRESS MIMO case +#if defined(EXMIMO) || defined(OAI_USRP) || defined(OAI_BLADERF) || defined(OAI_LMSSDR)//this is the EXPRESS MIMO case ulsch_start = (phy_vars_ue->rx_offset+subframe_tx*frame_parms->samples_per_tti- openair_daq_vars.timing_advance- phy_vars_ue->timing_advance- @@ -1257,7 +1257,7 @@ void phy_procedures_UE_TX(PHY_VARS_UE *phy_vars_ue,uint8_t eNB_id,uint8_t abstra for (aa=0; aanb_antennas_tx; aa++) { if (frame_parms->Ncp == 1) PHY_ofdm_mod(&phy_vars_ue->lte_ue_common_vars.txdataF[aa][subframe_tx*nsymb*frame_parms->ofdm_symbol_size], -#if defined(EXMIMO) || defined(OAI_USRP) +#if defined(EXMIMO) || defined(OAI_USRP) || defined(OAI_BLADERF) || defined(OAI_LMSSDR) dummy_tx_buffer, #else &phy_vars_ue->lte_ue_common_vars.txdata[aa][ulsch_start], @@ -1268,7 +1268,7 @@ void phy_procedures_UE_TX(PHY_VARS_UE *phy_vars_ue,uint8_t eNB_id,uint8_t abstra CYCLIC_PREFIX); else normal_prefix_mod(&phy_vars_ue->lte_ue_common_vars.txdataF[aa][subframe_tx*nsymb*frame_parms->ofdm_symbol_size], -#if defined(EXMIMO) || defined(OAI_USRP) +#if defined(EXMIMO) || defined(OAI_USRP) || defined(OAI_BLADERF) || defined(OAI_LMSSDR) dummy_tx_buffer, #else &phy_vars_ue->lte_ue_common_vars.txdata[aa][ulsch_start], @@ -1289,7 +1289,7 @@ void phy_procedures_UE_TX(PHY_VARS_UE *phy_vars_ue,uint8_t eNB_id,uint8_t abstra } */ #ifndef OFDMA_ULSCH -#if defined(EXMIMO) || defined(OAI_USRP) +#if defined(EXMIMO) || defined(OAI_USRP) || defined(OAI_BLADERF) || defined(OAI_LMSSDR) apply_7_5_kHz(phy_vars_ue,dummy_tx_buffer,0); apply_7_5_kHz(phy_vars_ue,dummy_tx_buffer,1); #else @@ -1304,7 +1304,7 @@ void phy_procedures_UE_TX(PHY_VARS_UE *phy_vars_ue,uint8_t eNB_id,uint8_t abstra */ #endif -#if defined(EXMIMO) || defined(OAI_USRP) +#if defined(EXMIMO) || defined(OAI_USRP) || defined(OAI_BLADERF) || defined(OAI_LMSSDR) overflow = ulsch_start - 9*frame_parms->samples_per_tti; //if ((slot_tx==4) && (aa==0)) printf("ulsch_start %d, overflow %d\n",ulsch_start,overflow); @@ -1404,7 +1404,7 @@ void phy_procedures_UE_TX(PHY_VARS_UE *phy_vars_ue,uint8_t eNB_id,uint8_t abstra phy_vars_ue->tx_total_RE = 96; -#if defined(EXMIMO) || defined(OAI_USRP) +#if defined(EXMIMO) || defined(OAI_USRP) || defined(OAI_BLADERF) || defined(OAI_LMSSDR) phy_vars_ue->lte_ue_prach_vars[eNB_id]->amp = get_tx_amp(phy_vars_ue->tx_power_dBm, phy_vars_ue->tx_power_max_dBm, phy_vars_ue->lte_frame_parms.N_RB_UL, @@ -1553,9 +1553,11 @@ void lte_ue_measurement_procedures(uint16_t l, PHY_VARS_UE *phy_vars_ue,uint8_t #else #ifndef OAI_USRP - #ifndef OAI_BLADERF +#ifndef OAI_BLADERF +#ifndef OAI_LMSSDR phy_adjust_gain (phy_vars_ue,0); - #endif +#endif +#endif #endif #endif VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_GAIN_CONTROL, VCD_FUNCTION_OUT); diff --git a/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/CMakeLists.txt b/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/CMakeLists.txt new file mode 100644 index 0000000000..88a021ae00 --- /dev/null +++ b/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/CMakeLists.txt @@ -0,0 +1,11 @@ +set(si5351_src_files + Si5351C.cpp +) +set(CMAKE_CXX_FLAGS + "${CMAKE_CXX_FLAGS} ${C_FLAGS_PROCESSOR} -std=c++11 " +) + + +add_library(Si5351C STATIC ${si5351_src_files}) +target_include_directories(Si5351C PUBLIC ../lms7002m ${CMAKE_CURRENT_SOURCE_DIR}) +target_link_libraries(Si5351C LMS7002M) diff --git a/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/Si5351C.cpp b/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/Si5351C.cpp new file mode 100644 index 0000000000..88bcb74f3d --- /dev/null +++ b/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/Si5351C.cpp @@ -0,0 +1,872 @@ +/** +@file Si5351C.cpp +@author Lime Microsystems +@brief Configuring of Si5351C +*/ + +#include "Si5351C.h" +#include "lmsComms.h" +#include +#include +#include +#include +#include +#include +#include +#include +using namespace std; + +#define Log(msg, type) cout << (msg) << endl; + +/// Splits float into fraction integers A + B/C +void realToFrac(const float real, int &A, int &B, int &C) +{ + A = (int)real; + B = (int)((real - A) * 1048576 + 0.5); + C = 1048576; + + int a = B; + int b = C; + int temp; + while( b!= 0) // greatest common divider + { + temp = a % b; + a = b; + b = temp; + } + B = B/a; + C = C/a; +} + +/// Default configuration +const unsigned char Si5351C::m_defaultConfiguration[] = +{ 0,0x00, + 1,0x00, + 2,0x08, + 3,0x00, + 4,0x00, + 5,0x00, + 6,0x00, + 7,0x00, + 8,0x00, + 9,0x00, + 10,0x00, + 11,0x00, + 12,0x00, + 13,0x00, + 14,0x00, + 15,0x04, + 16,0x4F, + 17,0x4F, + 18,0x4F, + 19,0x4F, + 20,0x4F, + 21,0x4F, + 22,0x0F, + 23,0x0F, + 24,0x00, + 25,0x00, + 26,0x00, + 27,0x80, + 28,0x00, + 29,0x0B, + 30,0x2F, + 31,0x00, + 32,0x00, + 33,0x00, + 34,0x00, + 35,0x00, + 36,0x00, + 37,0x00, + 38,0x00, + 39,0x00, + 40,0x00, + 41,0x00, + 42,0x00, + 43,0x01, + 44,0x00, + 45,0x0D, + 46,0x00, + 47,0x00, + 48,0x00, + 49,0x00, + 50,0x00, + 51,0x01, + 52,0x00, + 53,0x0D, + 54,0x00, + 55,0x00, + 56,0x00, + 57,0x00, + 58,0x00, + 59,0x01, + 60,0x00, + 61,0x0D, + 62,0x00, + 63,0x00, + 64,0x00, + 65,0x00, + 66,0x00, + 67,0x01, + 68,0x00, + 69,0x0D, + 70,0x00, + 71,0x00, + 72,0x00, + 73,0x00, + 74,0x00, + 75,0x01, + 76,0x00, + 77,0x0D, + 78,0x00, + 79,0x00, + 80,0x00, + 81,0x00, + 82,0x00, + 83,0x01, + 84,0x00, + 85,0x0D, + 86,0x00, + 87,0x00, + 88,0x00, + 89,0x00, + 90,0x1E, + 91,0x1E, + 92,0x00, + 93,0x00, + 94,0x00, + 95,0x00, + 96,0x00, + 97,0x00, + 98,0x00, + 99,0x00, +100,0x00, +101,0x00, +102,0x00, +103,0x00, +104,0x00, +105,0x00, +106,0x00, +107,0x00, +108,0x00, +109,0x00, +110,0x00, +111,0x00, +112,0x00, +113,0x00, +114,0x00, +115,0x00, +116,0x00, +117,0x00, +118,0x00, +119,0x00, +120,0x00, +121,0x00, +122,0x00, +123,0x00, +124,0x00, +125,0x00, +126,0x00, +127,0x00, +128,0x00, +129,0x00, +130,0x00, +131,0x00, +132,0x00, +133,0x00, +134,0x00, +135,0x00, +136,0x00, +137,0x00, +138,0x00, +139,0x00, +140,0x00, +141,0x00, +142,0x00, +143,0x00, +144,0x00, +145,0x00, +146,0x00, +147,0x00, +148,0x00, +149,0x00, +150,0x00, +151,0x00, +152,0x00, +153,0x00, +154,0x00, +155,0x00, +156,0x00, +157,0x00, +158,0x00, +159,0x00, +160,0x00, +161,0x00, +162,0x00, +163,0x00, +164,0x00, +165,0x00, +166,0x00, +167,0x00, +168,0x00, +169,0x00, +170,0x00, +171,0x00, +172,0x00, +173,0x00, +174,0x00, +175,0x00, +176,0x00, +177,0x00, +178,0x00, +179,0x00, +180,0x00, +181,0x30, +182,0x00, +183,0xD2, +184,0x60, +185,0x60, +186,0x00, +187,0xC0, +188,0x00, +189,0x00, +190,0x00, +191,0x00, +192,0x00, +193,0x00, +194,0x00, +195,0x00, +196,0x00, +197,0x00, +198,0x00, +199,0x00, +200,0x00, +201,0x00, +202,0x00, +203,0x00, +204,0x00, +205,0x00, +206,0x00, +207,0x00, +208,0x00, +209,0x00, +210,0x00, +211,0x00, +212,0x00, +213,0x00, +214,0x00, +215,0x00, +216,0x00, +217,0x00, +218,0x00, +219,0x00, +220,0x00, +221,0x0D, +222,0x00, +223,0x00, +224,0x00, +225,0x00, +226,0x00, +227,0x00, +228,0x00, +229,0x00, +230,0x00, +231,0x00, +232,0x00}; + +// --------------------------------------------------------------------------- +Si5351C::Si5351C() +{ + memset(m_newConfiguration, 0, 255); + for(unsigned int i=0; iIsOpen() ) + { + return FAILED; + } + LMScomms::TransferStatus status; + status = device->TransferPacket(pkt); + if (status != LMScomms::TRANSFER_SUCCESS || pkt.status != STATUS_COMPLETED_CMD) + { + return FAILED; + } + return SUCCESS; +} + +// --------------------------------------------------------------------------- +/** + @brief Sets connection manager to use for data transferring Si5351C + @param mng connection manager for data transferring +*/ +void Si5351C::Initialize(LMScomms *mng) +{ + assert(mng != nullptr); + device = mng; +} + +/** + @brief Loads register values for Si5356A from file + @param FName input filename +*/ +bool Si5351C::LoadRegValuesFromFile(string FName) +{ + fstream fin; + fin.open(FName.c_str(), ios::in); + + const int len = 1024; + char line[len]; + + int addr; + int value; + + while(!fin.eof()) + { + fin.getline(line, len); + if( line[0] == '#') + continue; + if( strcmp(line, "#END_PROFILE") == 0) + break; + sscanf(line, "%i,%x",&addr,&value); + m_newConfiguration[addr] = value; + } + + fin.close(); + return false; +}; + +/** @brief Calculates multisynth dividers and VCO frequencies + @param clocks output clocks configuration + @param plls plls configurations + @param Fmin lowest VCO frequency + @param Fmax highest VCO frequency +*/ +void Si5351C::FindVCO(Si5351_Channel *clocks, Si5351_PLL *plls, const unsigned long Fmin, const unsigned long Fmax) +{ + int clockCount = 8; + //reset output parameters + for(int i=0; i availableFrequenciesPLLA; //all available frequencies for VCO + map< unsigned long, int> availableFrequenciesPLLB; //all available frequencies for VCO + + //if clk6 or clk7 is used make available frequencies according to them + if(clocks[6].powered || clocks[7].powered) + { + set clk6freqs; + set clk7freqs; + set sharedFreqs; + unsigned int mult = 6; + if(!clk6satisfied) + { + unsigned long freq = clocks[6].outputFreqHz; + while(freq <= Fmax && mult <= 254) + { + freq = clocks[6].outputFreqHz*mult; + if(freq >= Fmin && freq <= Fmax) + { + clk6freqs.insert(freq); + } + mult += 2; + } + } + mult = 6; + if(!clk7satisfied) + { + unsigned long freq = clocks[7].outputFreqHz; + while(freq <= Fmax && mult <= 254) + { + freq = clocks[7].outputFreqHz*mult; + if(freq >= Fmin && freq <= Fmax) + { + clk7freqs.insert(freq); + } + mult += 2; + } + } + bool canShare = false; + //find if clk6 and clk7 can share the same pll + for (set::iterator it6=clk6freqs.begin(); it6!=clk6freqs.end(); ++it6) + { + for (set::iterator it7=clk7freqs.begin(); it7!=clk7freqs.end(); ++it7) + { + if(*it6 == *it7) + { + canShare = true; + sharedFreqs.insert(*it6); + } + } + } + if(canShare) //assign PLLA for both clocks + { + clocks[6].pllSource = 0; + clocks[7].pllSource = 0; + pllAused = true; + for (set::iterator it=sharedFreqs.begin(); it!=sharedFreqs.end(); ++it) + { + availableFrequenciesPLLA.insert( pair (*it, 0) ); + } + clk6satisfied = true; + clk7satisfied = true; + } + else //if clocks 6 and 7 can't share pll, assign pllA to clk6 and pllB to clk7 + { + if(!clk6satisfied) + { + clocks[6].pllSource = 0; + clk6satisfied = true; + pllAused = true; + for (set::iterator it6=clk6freqs.begin(); it6!=clk6freqs.end(); ++it6) + { + availableFrequenciesPLLA.insert( pair(*it6, 0) ); + } + } + if(!clk7satisfied) + { + clocks[7].pllSource = 1; + clk7satisfied = true; + pllBused = true; + for (set::iterator it7=clk7freqs.begin(); it7!=clk7freqs.end(); ++it7) + { + availableFrequenciesPLLB.insert( pair (*it7, 0) ); + } + } + } + } + + //PLLA stage, find all clocks that have integer coefficients with PLLA + //if pllA is not used by clk6 or clk7, fill available frequencies according to clk1-clk5 clocks + if( availableFrequenciesPLLA.size() == 0 && !pllAused) + { + for(int i=0; i<6; ++i) + { + unsigned long freq = clocks[i].outputFreqHz > Fmin ? clocks[i].outputFreqHz : (clocks[i].outputFreqHz*((Fmin/clocks[i].outputFreqHz) + ((Fmin%clocks[i].outputFreqHz)!=0))); + while(freq >= Fmin && freq <= Fmax) + { + //add all output frequency multiples that are in VCO interval + availableFrequenciesPLLA.insert( pair (freq, 0)); + freq += clocks[i].outputFreqHz; + } + } + } + + unsigned int bestScore = 0; //score shows how many outputs have integer dividers + //calculate scores for all available frequencies + unsigned long bestVCOA = 0; + for (map::iterator it=availableFrequenciesPLLA.begin(); it!=availableFrequenciesPLLA.end(); ++it) + { + for(int i=0; i<8; ++i) + { + if(clocks[i].outputFreqHz == 0 || !clocks[i].powered) + continue; + + if( (it->first % clocks[i].outputFreqHz) == 0) + { + it->second = it->second+1; + } + } + if(it->second >= bestScore) + { + bestScore = it->second; + bestVCOA = it->first; + } + } + //scores calculated + //cout << "PLLA stage: " << endl; + //cout << "best score: " << bestScore << " best VCO: " << bestVCOA << endl; + plls[0].VCO_Hz = bestVCOA; + plls[0].feedbackDivider = (double)bestVCOA/plls[0].inputFreqHz; + + for(int i=0; i Fmin ? clocks[i].outputFreqHz : (clocks[i].outputFreqHz*((Fmin/clocks[i].outputFreqHz) + ((Fmin%clocks[i].outputFreqHz)!=0))); + while(freq >= Fmin && freq <= Fmax) + { + availableFrequenciesPLLB.insert( pair (freq, 0)); + freq += clocks[i].outputFreqHz; + } + } + } + + bestScore = 0; + //calculate scores for all available frequencies + unsigned long bestVCOB = 0; + for (map::iterator it=availableFrequenciesPLLB.begin(); it!=availableFrequenciesPLLB.end(); ++it) + { + for(int i=0; i<8; ++i) + { + if(clocks[i].outputFreqHz == 0 || !clocks[i].powered) + continue; + + if( (it->first % clocks[i].outputFreqHz) == 0) + { + it->second = it->second+1; + } + } + if(it->second >= bestScore) + { + bestScore = it->second; + bestVCOB = it->first; + } + } + //scores calculated +// cout << "PLLB stage: " << endl; +// cout << "best score: " << bestScore << " best VCO: " << bestVCOB << endl; + if(bestVCOB == 0) //just in case if pllb is not used make it the same frequency as plla + bestVCOB = bestVCOA; + plls[1].VCO_Hz = bestVCOB; + plls[1].feedbackDivider = (double)bestVCOB/plls[0].inputFreqHz; + for(int i=0; i> 8; + m_newConfiguration[addr+1] = MSX_P3; + + m_newConfiguration[addr+2] = 0; + m_newConfiguration[addr+2] |= (MSX_P1 >> 16 ) & 0x03; + m_newConfiguration[addr+3] = MSX_P1 >> 8; + m_newConfiguration[addr+4] = MSX_P1; + + m_newConfiguration[addr+5] = 0; + m_newConfiguration[addr+5] = (MSX_P2 >> 16) & 0x0F; + m_newConfiguration[addr+5] |= (MSX_P3 >> 16) << 4; + + m_newConfiguration[addr+6] = MSX_P2; + m_newConfiguration[addr+7] = MSX_P2 >> 8; + } + else if( CLK[i].outputFreqHz <= 160000000) // AVAILABLE ONLY ON 0-5 MULTISYNTHS + { + Log("Si5351C - clock configuring for more than 150 MHz not implemented\n", LOG_ERROR); + return FAILED; + } + } + else // CLK6 and CLK7 only integer mode + { + if(CLK[i].outputFreqHz <= 150000000) + { + if(i==6) + { + m_newConfiguration[90] = DivA; + if(DivA%2 != 0) + { + Log("Si5351C - CLK6 multisynth divider is not even integer\n", LOG_ERROR); + return FAILED; + } + } + else + { + m_newConfiguration[91] = DivA; + if(DivA%2 != 0) + { + Log("Si5351C - CLK7 multisynth divider is not even integer\n", LOG_ERROR); + return FAILED; + } + } + } + else if( CLK[i].outputFreqHz <= 160000000) // AVAILABLE ONLY ON 0-5 MULTISYNTHS + { + Log("Si5351C - clock configuring for more than 150 MHz not implemented\n", LOG_ERROR); + return FAILED; + } + } + } + + //configure pll + //set input clk source + m_newConfiguration[15] = m_newConfiguration[15] & 0xF3; + m_newConfiguration[15] |= (PLL[0].CLK_SRC & 1) << 2; + m_newConfiguration[15] |= (PLL[1].CLK_SRC & 1) << 3; + for(int i=0; i<2; ++i) + { + addr = 26+i*8; + if(PLL[i].feedbackDivider < 15 || PLL[i].feedbackDivider > 90) + { + Log("Si5351C - VCO frequency divider out of range [15:90].\n", LOG_ERROR); + return FAILED; + } + if( PLL[i].VCO_Hz < 600000000 || PLL[i].VCO_Hz > 900000000) + { + Log("Si5351C - Can't calculate valid VCO frequency.\n", LOG_ERROR); + return FAILED; + } + ss.clear(); + ss.str(string()); + ss << "Si5351C : VCO" << (i==0 ? "A" : "B") << " = " << PLL[i].VCO_Hz/1000000.0 << " MHz"; + + //calculate MSNx_P1, MSNx_P2, MSNx_P3 + int MSNx_P1; + int MSNx_P2; + int MSNx_P3; + + int DivA; + int DivB; + int DivC; + realToFrac(PLL[i].feedbackDivider, DivA, DivB, DivC); + ss << " Feedback Divider " << DivA << " " << DivB << "/" << DivC << endl; + Log(ss.str(), LOG_INFO); + + MSNx_P1 = 128 * DivA + floor(128 * ( (float)DivB/DivC)) - 512; + MSNx_P2 = 128 * DivB - DivC * floor( 128 * DivB/DivC ); + MSNx_P3 = DivC; + + m_newConfiguration[addr+4] = MSNx_P1; + m_newConfiguration[addr+3] = MSNx_P1 >> 8; + m_newConfiguration[addr+2] = MSNx_P1 >> 16; + + m_newConfiguration[addr+7] = MSNx_P2; + m_newConfiguration[addr+6] = MSNx_P2 >> 8; + m_newConfiguration[addr+5] = 0; + m_newConfiguration[addr+5] = (MSNx_P2 >> 16) & 0x0F; + + m_newConfiguration[addr+5] |= (MSNx_P3 >> 16) << 4; + m_newConfiguration[addr+1] |= MSNx_P3; + m_newConfiguration[addr] |= MSNx_P3 >> 8; + } + return SUCCESS; +} + +/** @brief Sets output clock parameters + @param id clock id 0-CLK0 1-CLK1 ... + @param fOut_Hz output frequency in Hz + @param enabled is this output powered + @param inverted invert clock +*/ +void Si5351C::SetClock(unsigned char id, unsigned long fOut_Hz, bool enabled, bool inverted) +{ + if( id < 8) + { + if(fOut_Hz < 8000 || fOut_Hz > 160000000) + { + stringstream ss; + ss << "Si5351C - CLK" << (int)id << " output frequency must be between 8kHz and 160MHz. fOut_MHz = " << fOut_Hz/1000000.0 << endl; + Log(ss.str(), LOG_ERROR); + return; + } + CLK[id].powered = enabled; + CLK[id].inverted = inverted; + CLK[id].outputFreqHz = fOut_Hz; + } +} + +/** @brief Sets PLL input frequency + @param id PLL id 0-PLLA 1-PLLB + @param CLKIN_Hz clock input in Hz +*/ +void Si5351C::SetPLL(unsigned char id, unsigned long CLKIN_Hz, int CLK_SRC) +{ + if (id < 2) + { + PLL[id].inputFreqHz = CLKIN_Hz; + PLL[id].CLK_SRC = CLK_SRC; + } +} + +/** @brief Resets configuration registers to default values +*/ +void Si5351C::Reset() +{ + memset(m_newConfiguration, 0, 255); + for(unsigned int i=0; iTransferPacket(pkt); + if (status != LMScomms::TRANSFER_SUCCESS || pkt.status != STATUS_COMPLETED_CMD) + { + return stat; + } + + stat.sys_init = (pkt.inBuffer[0] >> 7); + stat.lol_b = (pkt.inBuffer[0] >> 6) & 0x1; + stat.lol_a = (pkt.inBuffer[0] >> 5) & 0x1; + stat.los = (pkt.inBuffer[0] >> 4) & 0x1; + stat.sys_init_stky = (pkt.inBuffer[1] >> 7); + stat.lol_b_stky = (pkt.inBuffer[1] >> 6) & 0x1; + stat.lol_a_stky = (pkt.inBuffer[1] >> 5) & 0x1; + stat.los_stky = (pkt.inBuffer[1] >> 4) & 0x1; + return stat; +} + +Si5351C::Status Si5351C::ClearStatus() +{ + LMScomms::GenericPacket pkt; + pkt.cmd = CMD_SI5351_WR; + pkt.outBuffer.push_back(1); + pkt.outBuffer.push_back(0x0); + LMScomms::TransferStatus status; + status = device->TransferPacket(pkt); + if (status != LMScomms::TRANSFER_SUCCESS || pkt.status != STATUS_COMPLETED_CMD) + return FAILED; + return SUCCESS; +} diff --git a/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/Si5351C.h b/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/Si5351C.h new file mode 100644 index 0000000000..971a2d1d69 --- /dev/null +++ b/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/Si5351C.h @@ -0,0 +1,100 @@ +/** +@file Si5351C.h +@brief Header for Si5351C.cpp +@author Lime Microsystems +*/ + +#ifndef SI5351C_MODULE +#define SI5351C_MODULE + +#include +#include +using namespace std; +//--------------------------------------------------------------------------- + +enum eSi_CLOCK_INPUT +{ + Si_CLKIN, + Si_XTAL, + Si_CMOS +}; + +struct Si5351_Channel +{ + Si5351_Channel() : outputDivider(1), outputFreqHz(1), multisynthDivider(1), pllSource(0), + phaseOffset(0), powered(true), inverted(false), int_mode(false) {}; + int outputDivider; + unsigned long outputFreqHz; + float multisynthDivider; + int pllSource; + float phaseOffset; + bool powered; + bool inverted; + bool int_mode; +}; + +struct Si5351_PLL +{ + Si5351_PLL() : inputFreqHz(0), VCO_Hz(0), feedbackDivider(0), CLKIN_DIV(1), CLK_SRC(1) {} + unsigned long inputFreqHz; + float VCO_Hz; + float feedbackDivider; + int CLKIN_DIV; + int CLK_SRC; //0-XTAL, 1-CLKIN +}; + +class LMScomms; +class Si5351C +{ +public: + enum Status + { + SUCCESS, + FAILED, + }; + + struct StatusBits + { + StatusBits() : sys_init(0), sys_init_stky(0), lol_b(0), lol_b_stky(0), lol_a(0), lol_a_stky(0), los(0), los_stky(0) + { + + } + int sys_init; + int sys_init_stky; + int lol_b; + int lol_b_stky; + int lol_a; + int lol_a_stky; + int los; + int los_stky; + }; + + StatusBits GetStatusBits(); + Status ClearStatus(); + + Si5351C(); + ~Si5351C(); + void Initialize(LMScomms *mng); + bool LoadRegValuesFromFile(string FName); + + void SetPLL(unsigned char id, unsigned long CLKIN_Hz, int CLK_SRC); + void SetClock(unsigned char id, unsigned long fOut_Hz, bool enabled = true, bool inverted = false); + + Status UploadConfiguration(); + Status ConfigureClocks(); + void Reset(); + +private: + void FindVCO(Si5351_Channel *clocks, Si5351_PLL *plls, const unsigned long Fmin, const unsigned long Fmax); + LMScomms *device; + + Si5351_PLL PLL[2]; + Si5351_Channel CLK[8]; + + static const unsigned char m_defaultConfiguration[]; + unsigned char m_newConfiguration[255]; + + +}; + +#endif // SI5351C_MODULE diff --git a/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeCache.txt b/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeCache.txt new file mode 100644 index 0000000000..2bd212843c --- /dev/null +++ b/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeCache.txt @@ -0,0 +1,326 @@ +# This is the CMakeCache file. +# For build in directory: /home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build +# It was generated by CMake: /usr/bin/cmake +# You can edit this file to change values found and used by cmake. +# If you do not want to change any of the values, simply exit the editor. +# If you do want to change a value, simply edit, save, and exit the editor. +# The syntax for the file is as follows: +# KEY:TYPE=VALUE +# KEY is the name of a variable in the cache. +# TYPE is a hint to GUIs for the type of VALUE, DO NOT EDIT TYPE!. +# VALUE is the current value for the KEY. + +######################## +# EXTERNAL cache entries +######################## + +//Path to a program. +CMAKE_AR:FILEPATH=/usr/bin/ar + +//For backwards compatibility, what version of CMake commands and +// syntax should this version of CMake try to support. +CMAKE_BACKWARDS_COMPATIBILITY:STRING=2.4 + +//Choose the type of build, options are: None(CMAKE_CXX_FLAGS or +// CMAKE_C_FLAGS used) Debug Release RelWithDebInfo MinSizeRel. +CMAKE_BUILD_TYPE:STRING= + +//Enable/Disable color output during build. +CMAKE_COLOR_MAKEFILE:BOOL=ON + +//CXX compiler. +CMAKE_CXX_COMPILER:FILEPATH=/usr/bin/c++ + +//Flags used by the compiler during all build types. +CMAKE_CXX_FLAGS:STRING= + +//Flags used by the compiler during debug builds. +CMAKE_CXX_FLAGS_DEBUG:STRING=-g + +//Flags used by the compiler during release minsize builds. +CMAKE_CXX_FLAGS_MINSIZEREL:STRING=-Os -DNDEBUG + +//Flags used by the compiler during release builds (/MD /Ob1 /Oi +// /Ot /Oy /Gs will produce slightly less optimized but smaller +// files). +CMAKE_CXX_FLAGS_RELEASE:STRING=-O3 -DNDEBUG + +//Flags used by the compiler during Release with Debug Info builds. +CMAKE_CXX_FLAGS_RELWITHDEBINFO:STRING=-O2 -g -DNDEBUG + +//C compiler. +CMAKE_C_COMPILER:FILEPATH=/usr/bin/cc + +//Flags used by the compiler during all build types. +CMAKE_C_FLAGS:STRING= + +//Flags used by the compiler during debug builds. +CMAKE_C_FLAGS_DEBUG:STRING=-g + +//Flags used by the compiler during release minsize builds. +CMAKE_C_FLAGS_MINSIZEREL:STRING=-Os -DNDEBUG + +//Flags used by the compiler during release builds (/MD /Ob1 /Oi +// /Ot /Oy /Gs will produce slightly less optimized but smaller +// files). +CMAKE_C_FLAGS_RELEASE:STRING=-O3 -DNDEBUG + +//Flags used by the compiler during Release with Debug Info builds. +CMAKE_C_FLAGS_RELWITHDEBINFO:STRING=-O2 -g -DNDEBUG + +//Flags used by the linker. +CMAKE_EXE_LINKER_FLAGS:STRING=' ' + +//Flags used by the linker during debug builds. +CMAKE_EXE_LINKER_FLAGS_DEBUG:STRING= + +//Flags used by the linker during release minsize builds. +CMAKE_EXE_LINKER_FLAGS_MINSIZEREL:STRING= + +//Flags used by the linker during release builds. +CMAKE_EXE_LINKER_FLAGS_RELEASE:STRING= + +//Flags used by the linker during Release with Debug Info builds. +CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO:STRING= + +//Enable/Disable output of compile commands during generation. +CMAKE_EXPORT_COMPILE_COMMANDS:BOOL=OFF + +//Install path prefix, prepended onto install directories. +CMAKE_INSTALL_PREFIX:PATH=/usr/local + +//Path to a program. +CMAKE_LINKER:FILEPATH=/usr/bin/ld + +//Path to a program. +CMAKE_MAKE_PROGRAM:FILEPATH=/usr/bin/make + +//Flags used by the linker during the creation of modules. +CMAKE_MODULE_LINKER_FLAGS:STRING=' ' + +//Flags used by the linker during debug builds. +CMAKE_MODULE_LINKER_FLAGS_DEBUG:STRING= + +//Flags used by the linker during release minsize builds. +CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL:STRING= + +//Flags used by the linker during release builds. +CMAKE_MODULE_LINKER_FLAGS_RELEASE:STRING= + +//Flags used by the linker during Release with Debug Info builds. +CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO:STRING= + +//Path to a program. +CMAKE_NM:FILEPATH=/usr/bin/nm + +//Path to a program. +CMAKE_OBJCOPY:FILEPATH=/usr/bin/objcopy + +//Path to a program. +CMAKE_OBJDUMP:FILEPATH=/usr/bin/objdump + +//Value Computed by CMake +CMAKE_PROJECT_NAME:STATIC=Project + +//Path to a program. +CMAKE_RANLIB:FILEPATH=/usr/bin/ranlib + +//Flags used by the linker during the creation of dll's. +CMAKE_SHARED_LINKER_FLAGS:STRING=' ' + +//Flags used by the linker during debug builds. +CMAKE_SHARED_LINKER_FLAGS_DEBUG:STRING= + +//Flags used by the linker during release minsize builds. +CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL:STRING= + +//Flags used by the linker during release builds. +CMAKE_SHARED_LINKER_FLAGS_RELEASE:STRING= + +//Flags used by the linker during Release with Debug Info builds. +CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO:STRING= + +//If set, runtime paths are not added when installing shared libraries, +// but are added when building. +CMAKE_SKIP_INSTALL_RPATH:BOOL=NO + +//If set, runtime paths are not added when using shared libraries. +CMAKE_SKIP_RPATH:BOOL=NO + +//Flags used by the linker during the creation of static libraries. +CMAKE_STATIC_LINKER_FLAGS:STRING= + +//Flags used by the linker during debug builds. +CMAKE_STATIC_LINKER_FLAGS_DEBUG:STRING= + +//Flags used by the linker during release minsize builds. +CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL:STRING= + +//Flags used by the linker during release builds. +CMAKE_STATIC_LINKER_FLAGS_RELEASE:STRING= + +//Flags used by the linker during Release with Debug Info builds. +CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO:STRING= + +//Path to a program. +CMAKE_STRIP:FILEPATH=/usr/bin/strip + +//If true, cmake will use relative paths in makefiles and projects. +CMAKE_USE_RELATIVE_PATHS:BOOL=OFF + +//If this value is on, makefiles will be generated without the +// .SILENT directive, and all commands will be echoed to the console +// during the make. This is useful for debugging only. With Visual +// Studio IDE projects all commands are done without /nologo. +CMAKE_VERBOSE_MAKEFILE:BOOL=FALSE + +//Single output directory for building all executables. +EXECUTABLE_OUTPUT_PATH:PATH= + +//Single output directory for building all libraries. +LIBRARY_OUTPUT_PATH:PATH= + +//Value Computed by CMake +Project_BINARY_DIR:STATIC=/home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build + +//Value Computed by CMake +Project_SOURCE_DIR:STATIC=/home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C + +//Dependencies for the target +Si5351C_LIB_DEPENDS:STATIC=general;LMS7002M; + + +######################## +# INTERNAL cache entries +######################## + +//ADVANCED property for variable: CMAKE_AR +CMAKE_AR-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_BUILD_TOOL +CMAKE_BUILD_TOOL-ADVANCED:INTERNAL=1 +//What is the target build tool cmake is generating for. +CMAKE_BUILD_TOOL:INTERNAL=/usr/bin/make +//This is the directory where this CMakeCache.txt was created +CMAKE_CACHEFILE_DIR:INTERNAL=/home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build +//Major version of cmake used to create the current loaded cache +CMAKE_CACHE_MAJOR_VERSION:INTERNAL=2 +//Minor version of cmake used to create the current loaded cache +CMAKE_CACHE_MINOR_VERSION:INTERNAL=8 +//Patch version of cmake used to create the current loaded cache +CMAKE_CACHE_PATCH_VERSION:INTERNAL=12 +//ADVANCED property for variable: CMAKE_COLOR_MAKEFILE +CMAKE_COLOR_MAKEFILE-ADVANCED:INTERNAL=1 +//Path to CMake executable. +CMAKE_COMMAND:INTERNAL=/usr/bin/cmake +//Path to cpack program executable. +CMAKE_CPACK_COMMAND:INTERNAL=/usr/bin/cpack +//Path to ctest program executable. +CMAKE_CTEST_COMMAND:INTERNAL=/usr/bin/ctest +//ADVANCED property for variable: CMAKE_CXX_COMPILER +CMAKE_CXX_COMPILER-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_CXX_FLAGS +CMAKE_CXX_FLAGS-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_CXX_FLAGS_DEBUG +CMAKE_CXX_FLAGS_DEBUG-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_CXX_FLAGS_MINSIZEREL +CMAKE_CXX_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_CXX_FLAGS_RELEASE +CMAKE_CXX_FLAGS_RELEASE-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_CXX_FLAGS_RELWITHDEBINFO +CMAKE_CXX_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_C_COMPILER +CMAKE_C_COMPILER-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_C_FLAGS +CMAKE_C_FLAGS-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_C_FLAGS_DEBUG +CMAKE_C_FLAGS_DEBUG-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_C_FLAGS_MINSIZEREL +CMAKE_C_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_C_FLAGS_RELEASE +CMAKE_C_FLAGS_RELEASE-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_C_FLAGS_RELWITHDEBINFO +CMAKE_C_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 +//Path to cache edit program executable. +CMAKE_EDIT_COMMAND:INTERNAL=/usr/bin/ccmake +//Executable file format +CMAKE_EXECUTABLE_FORMAT:INTERNAL=ELF +//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS +CMAKE_EXE_LINKER_FLAGS-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_DEBUG +CMAKE_EXE_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_MINSIZEREL +CMAKE_EXE_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_RELEASE +CMAKE_EXE_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO +CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_EXPORT_COMPILE_COMMANDS +CMAKE_EXPORT_COMPILE_COMMANDS-ADVANCED:INTERNAL=1 +//Name of generator. +CMAKE_GENERATOR:INTERNAL=Unix Makefiles +//Name of generator toolset. +CMAKE_GENERATOR_TOOLSET:INTERNAL= +//Start directory with the top level CMakeLists.txt file for this +// project +CMAKE_HOME_DIRECTORY:INTERNAL=/home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C +//Install .so files without execute permission. +CMAKE_INSTALL_SO_NO_EXE:INTERNAL=1 +//ADVANCED property for variable: CMAKE_LINKER +CMAKE_LINKER-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_MAKE_PROGRAM +CMAKE_MAKE_PROGRAM-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS +CMAKE_MODULE_LINKER_FLAGS-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_DEBUG +CMAKE_MODULE_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL +CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_RELEASE +CMAKE_MODULE_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO +CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_NM +CMAKE_NM-ADVANCED:INTERNAL=1 +//number of local generators +CMAKE_NUMBER_OF_LOCAL_GENERATORS:INTERNAL=1 +//ADVANCED property for variable: CMAKE_OBJCOPY +CMAKE_OBJCOPY-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_OBJDUMP +CMAKE_OBJDUMP-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_RANLIB +CMAKE_RANLIB-ADVANCED:INTERNAL=1 +//Path to CMake installation. +CMAKE_ROOT:INTERNAL=/usr/share/cmake-2.8 +//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS +CMAKE_SHARED_LINKER_FLAGS-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_DEBUG +CMAKE_SHARED_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL +CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_RELEASE +CMAKE_SHARED_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO +CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_SKIP_INSTALL_RPATH +CMAKE_SKIP_INSTALL_RPATH-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_SKIP_RPATH +CMAKE_SKIP_RPATH-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS +CMAKE_STATIC_LINKER_FLAGS-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_DEBUG +CMAKE_STATIC_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL +CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_RELEASE +CMAKE_STATIC_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO +CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_STRIP +CMAKE_STRIP-ADVANCED:INTERNAL=1 +//uname command +CMAKE_UNAME:INTERNAL=/bin/uname +//ADVANCED property for variable: CMAKE_USE_RELATIVE_PATHS +CMAKE_USE_RELATIVE_PATHS-ADVANCED:INTERNAL=1 +//ADVANCED property for variable: CMAKE_VERBOSE_MAKEFILE +CMAKE_VERBOSE_MAKEFILE-ADVANCED:INTERNAL=1 + diff --git a/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/2.8.12.2/CMakeCCompiler.cmake b/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/2.8.12.2/CMakeCCompiler.cmake new file mode 100644 index 0000000000..f4a508bee8 --- /dev/null +++ b/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/2.8.12.2/CMakeCCompiler.cmake @@ -0,0 +1,56 @@ +set(CMAKE_C_COMPILER "/usr/bin/cc") +set(CMAKE_C_COMPILER_ARG1 "") +set(CMAKE_C_COMPILER_ID "GNU") +set(CMAKE_C_COMPILER_VERSION "4.8.4") +set(CMAKE_C_PLATFORM_ID "Linux") + +set(CMAKE_AR "/usr/bin/ar") +set(CMAKE_RANLIB "/usr/bin/ranlib") +set(CMAKE_LINKER "/usr/bin/ld") +set(CMAKE_COMPILER_IS_GNUCC 1) +set(CMAKE_C_COMPILER_LOADED 1) +set(CMAKE_C_COMPILER_WORKS TRUE) +set(CMAKE_C_ABI_COMPILED TRUE) +set(CMAKE_COMPILER_IS_MINGW ) +set(CMAKE_COMPILER_IS_CYGWIN ) +if(CMAKE_COMPILER_IS_CYGWIN) + set(CYGWIN 1) + set(UNIX 1) +endif() + +set(CMAKE_C_COMPILER_ENV_VAR "CC") + +if(CMAKE_COMPILER_IS_MINGW) + set(MINGW 1) +endif() +set(CMAKE_C_COMPILER_ID_RUN 1) +set(CMAKE_C_SOURCE_FILE_EXTENSIONS c) +set(CMAKE_C_IGNORE_EXTENSIONS h;H;o;O;obj;OBJ;def;DEF;rc;RC) +set(CMAKE_C_LINKER_PREFERENCE 10) + +# Save compiler ABI information. +set(CMAKE_C_SIZEOF_DATA_PTR "8") +set(CMAKE_C_COMPILER_ABI "ELF") +set(CMAKE_C_LIBRARY_ARCHITECTURE "x86_64-linux-gnu") + +if(CMAKE_C_SIZEOF_DATA_PTR) + set(CMAKE_SIZEOF_VOID_P "${CMAKE_C_SIZEOF_DATA_PTR}") +endif() + +if(CMAKE_C_COMPILER_ABI) + set(CMAKE_INTERNAL_PLATFORM_ABI "${CMAKE_C_COMPILER_ABI}") +endif() + +if(CMAKE_C_LIBRARY_ARCHITECTURE) + set(CMAKE_LIBRARY_ARCHITECTURE "x86_64-linux-gnu") +endif() + + + + +set(CMAKE_C_IMPLICIT_LINK_LIBRARIES "c") +set(CMAKE_C_IMPLICIT_LINK_DIRECTORIES "/usr/lib/gcc/x86_64-linux-gnu/4.8;/usr/lib/x86_64-linux-gnu;/usr/lib;/lib/x86_64-linux-gnu;/lib") +set(CMAKE_C_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES "") + + + diff --git a/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/2.8.12.2/CMakeCXXCompiler.cmake b/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/2.8.12.2/CMakeCXXCompiler.cmake new file mode 100644 index 0000000000..1ca40dbcd6 --- /dev/null +++ b/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/2.8.12.2/CMakeCXXCompiler.cmake @@ -0,0 +1,57 @@ +set(CMAKE_CXX_COMPILER "/usr/bin/c++") +set(CMAKE_CXX_COMPILER_ARG1 "") +set(CMAKE_CXX_COMPILER_ID "GNU") +set(CMAKE_CXX_COMPILER_VERSION "4.8.4") +set(CMAKE_CXX_PLATFORM_ID "Linux") + +set(CMAKE_AR "/usr/bin/ar") +set(CMAKE_RANLIB "/usr/bin/ranlib") +set(CMAKE_LINKER "/usr/bin/ld") +set(CMAKE_COMPILER_IS_GNUCXX 1) +set(CMAKE_CXX_COMPILER_LOADED 1) +set(CMAKE_CXX_COMPILER_WORKS TRUE) +set(CMAKE_CXX_ABI_COMPILED TRUE) +set(CMAKE_COMPILER_IS_MINGW ) +set(CMAKE_COMPILER_IS_CYGWIN ) +if(CMAKE_COMPILER_IS_CYGWIN) + set(CYGWIN 1) + set(UNIX 1) +endif() + +set(CMAKE_CXX_COMPILER_ENV_VAR "CXX") + +if(CMAKE_COMPILER_IS_MINGW) + set(MINGW 1) +endif() +set(CMAKE_CXX_COMPILER_ID_RUN 1) +set(CMAKE_CXX_IGNORE_EXTENSIONS inl;h;hpp;HPP;H;o;O;obj;OBJ;def;DEF;rc;RC) +set(CMAKE_CXX_SOURCE_FILE_EXTENSIONS C;M;c++;cc;cpp;cxx;m;mm;CPP) +set(CMAKE_CXX_LINKER_PREFERENCE 30) +set(CMAKE_CXX_LINKER_PREFERENCE_PROPAGATES 1) + +# Save compiler ABI information. +set(CMAKE_CXX_SIZEOF_DATA_PTR "8") +set(CMAKE_CXX_COMPILER_ABI "ELF") +set(CMAKE_CXX_LIBRARY_ARCHITECTURE "x86_64-linux-gnu") + +if(CMAKE_CXX_SIZEOF_DATA_PTR) + set(CMAKE_SIZEOF_VOID_P "${CMAKE_CXX_SIZEOF_DATA_PTR}") +endif() + +if(CMAKE_CXX_COMPILER_ABI) + set(CMAKE_INTERNAL_PLATFORM_ABI "${CMAKE_CXX_COMPILER_ABI}") +endif() + +if(CMAKE_CXX_LIBRARY_ARCHITECTURE) + set(CMAKE_LIBRARY_ARCHITECTURE "x86_64-linux-gnu") +endif() + + + + +set(CMAKE_CXX_IMPLICIT_LINK_LIBRARIES "stdc++;m;c") +set(CMAKE_CXX_IMPLICIT_LINK_DIRECTORIES "/usr/lib/gcc/x86_64-linux-gnu/4.8;/usr/lib/x86_64-linux-gnu;/usr/lib;/lib/x86_64-linux-gnu;/lib") +set(CMAKE_CXX_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES "") + + + diff --git a/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/2.8.12.2/CMakeDetermineCompilerABI_C.bin b/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/2.8.12.2/CMakeDetermineCompilerABI_C.bin new file mode 100755 index 0000000000000000000000000000000000000000..3458fc29190dbceb43a4fb44955cbce374660b02 GIT binary patch literal 8587 zcmeHMeQZAT{-bS~SDQ*aX8BoV_62l85z-ZELW9f?%JH)MHGy9pZ zK^rXv)oSU`Hf;=5Ra^BBGm> z{PK|4rtL4T<#*2c-E;0a_rCk_?!Ax4y4HC;9>K{gzAQ*OT%$?IdP1HpMTJE~ozTQ0 zu|U)Ssm5QEIYcdv>7*)}sbA^&K&$YNcr75})g;4op#=-393fHiS5BH@E&6PoB{CHv zBmuIcSc3s6g7!;>X`_mxSy8qlk?b0kU8AyNdRhg>l1z>ea))f7~UTa~|?waYbCKc-3)_oY(e~PG>vP}T zH*@t5XS}@e+{B-Mf9|=KfiqX%{^nN~KJxg{eZM?(Juq|b+2_U^s>d(?@jdl6VeCjv zkV6iP#2NU{altddLN54EZh{}b3I289LD3*0!G3V%6bDOqqXU0d;&%znfe!)?x#;f) zK3miaP4y%0H%|kfBW8(-S`C~KN%<6FJ1F5i4=7l?046BznieO$SJL0F%2}ffejxD~ zB2uF%#3FY~e3ocd@u*=UI)PK1TNM6jW%UKA9}ukySFjN1hlAAZRtm!)-pHHroN0{2 zQyE4E^95rll}QPsv!~lgBy-8_sl1uY^>nwVvzcU1d?1|^smxH;$fx!uvqMH=hnW*b zG7&f9D1(SqDunGL*^F{wpuElC6RC_*$R`tackpJSgbaZL`8=C%*lBE4&fC-Rd_I}C zVsedWeOG5&yU`ME39qnf%WdSr$a4SDn4_OHF374dKZRl96=$p>#AJQHcKm7ZUn`3A6gbawzL#ulY}qRXLSbya<)jJul%|zgPoD z@-Qh}e5ZtT&ry;oYmg3o0A0?|B4j#1Alorg?7fppQxA)Z$Rt@NvPWN5>7EJ0Fi;H72`asvc z=a-$)kALi=H+CWRNvWhCxN0t9`>x`puHuIsD5Es@FZ$RCkG|@1;S#;bZGF*iMEjx- zM~xFhLt)l`AMaPbd-bY46}?4>&Q0q!ueJ@NZOxHB3ycq>w&7!=4}EljZ%s2|ug3q% z$EDIf(1i%B3$zZ+@)Bql=xd$JL zK_z#6A(kMY^oOBOF^E8LU7%q@{fu4yQL%RZnx)H^e3oF+>A=4aaml$X8VDZrw$G~B z3CAig0XmBOB&cW$1i#~r1sb05#R8#2Rk1+h)75&Q`CyG6h>X>C2efn`5)Cv*1C4Eg zP+On@`fUNftk=shKZbJb3;?#HD zEG6^z*Rz^xR-%{fIe|}QRl6=Ig5t-WaO;lMjeZNqe^lC)J z9r7u}yNc5HI;94S2>y;#V)@$#p97S5?v-l-WL`gNWv&o+D(bJ%B**x*YD?z0*&ppq zD6x#`UDoHc(#NtUWp2-FN zqivl{W_-Jnwr2|AfkFy<&{RT%Ng9slhebHCCxh}ViVu02voo2?r?Qy}!9ZRvnU0fz z;&!A>5tbkCVKccKyxcd0b6L3;2q%Y)p_Ii&Y{v2O>O}9T`bxOlKSaCo+vQ>QmgGBVG+s`J9EvnFR6R{>Sp?z);_2 z`yQ_bseFzRl2Z9mRc0l(3{Shg>D44|ssfitsr+!-cOdISj0N_8#H&f=BMRu3Qh7e$ zai?Ih2@H*Wwx9HBkZ7KeM7*vlO!Eh^Y|rELL147cVSAo$CRCvBBF~7AS zkLP3bv5WM1i%iXDtjF|GIrJL6Zd*b9b2WqY2Vt|@!2rxK^t{|SdZ z&v$+`;qv@Q_Ou2#+wU1*)Fw)OYJG?(faiUv$fTN;MNtH2x9_jfWM03+KN|!U!}R-* z?e=_raah^E=y+jl$K@S$*z*e_q*h`}28=rtFuqp`uRz#~k*2?#JhW ztqyyq|5qIL$FOarbWHjGKuYC@f~SB9aCA6EV}KH`-+Vsk)OX5nz@{F5w&(S|feJ-( z>O1APp+m2T?P=#sDRhhWe}yi+YPRR~jn8lSoK|&*sd)H3{2jJ-|9oCDNtHr!#>+C( z%h0jg3-x^=4=Rz@NQKxE+cBm0W4GsXzeW`x$H_&o9m^kqA&l!!#~qX+%FwA#zU-+4 zfv{#f2%hb`9XQ)FrE3EAZC5?O{#j9FIz;K4$Bx}Ts6Hs0)r-3unG_?}hvzjKpKkuO z#a3w>9fdpnTUzcp>-chv0d>5}$rQ6r}w)9=jZDl#-^XSTQf>ZY$mH2GT zW11b3ybmYOJWts(ed1G7`-@6^F6NVdJ0y7@b_qOR*fV`%-qg8iC5~MIk8fLs&*l7` zvVAV+<`(W;6|FH?C9czOtVp!xdayfj#!th;D{zjl)=M@DEBu-Rk1E``&wB{C#}+4# zk0FUqZ_h)joGrB)xN`atSdYtl83*oGFIqP|SUKpJlaiY5fw}9y1>A$1f+KYrxNHTD$Y^dq|@Lp98&%@Fk9xEh1z5i?kPWLFz zdy#FxLu_oLyCgpSe(2l4-R@Do2i)zR=_v3yXm$SHVHeL!oTV~-Rh7f*6X(1EJj8;H zo&oN5|8xns+x^o=!0DbzbF_a+>GO9TyQsmu?shLV2e{k4)SbZH;{4)G@R%&eWj-9t znR&B-6Y@b^^=xS0YIJoz&|?^)e9dH-BgPFhu}Z6wTWE^ovO zy9IWHJJLxrnFz03^`+$~*+og-X<0i>+%%cFJ;K_XCJG}XdthRd4BFCGsJ3^uh&&H@&#CuKb*rf|_Q( YSNpGT_qcN9OFrx7@!z`XldUEG1u+4vi~s-t literal 0 HcmV?d00001 diff --git a/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/2.8.12.2/CMakeDetermineCompilerABI_CXX.bin b/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/2.8.12.2/CMakeDetermineCompilerABI_CXX.bin new file mode 100755 index 0000000000000000000000000000000000000000..ea701432becf6a6bd7cb452c08f7c7645d0f8607 GIT binary patch literal 8600 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 Qh0vf8p8U7sgQ9cbUvrV1<^TWy literal 0 HcmV?d00001 diff --git a/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/2.8.12.2/CMakeSystem.cmake b/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/2.8.12.2/CMakeSystem.cmake new file mode 100644 index 0000000000..bbcd260466 --- /dev/null +++ b/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/2.8.12.2/CMakeSystem.cmake @@ -0,0 +1,15 @@ +set(CMAKE_HOST_SYSTEM "Linux-3.17.0-031700-lowlatency") +set(CMAKE_HOST_SYSTEM_NAME "Linux") +set(CMAKE_HOST_SYSTEM_VERSION "3.17.0-031700-lowlatency") +set(CMAKE_HOST_SYSTEM_PROCESSOR "x86_64") + + + +set(CMAKE_SYSTEM "Linux-3.17.0-031700-lowlatency") +set(CMAKE_SYSTEM_NAME "Linux") +set(CMAKE_SYSTEM_VERSION "3.17.0-031700-lowlatency") +set(CMAKE_SYSTEM_PROCESSOR "x86_64") + +set(CMAKE_CROSSCOMPILING "FALSE") + +set(CMAKE_SYSTEM_LOADED 1) diff --git a/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/2.8.12.2/CompilerIdC/CMakeCCompilerId.c b/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/2.8.12.2/CompilerIdC/CMakeCCompilerId.c new file mode 100644 index 0000000000..cba81d4a6b --- /dev/null +++ b/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/2.8.12.2/CompilerIdC/CMakeCCompilerId.c @@ -0,0 +1,389 @@ +#ifdef __cplusplus +# error "A C++ compiler has been selected for C." +#endif + +/* Version number components: V=Version, R=Revision, P=Patch + Version date components: YYYY=Year, MM=Month, DD=Day */ + +#if defined(__18CXX) +# define ID_VOID_MAIN +#endif + +#if defined(__INTEL_COMPILER) || defined(__ICC) +# define COMPILER_ID "Intel" + /* __INTEL_COMPILER = VRP */ +# define COMPILER_VERSION_MAJOR DEC(__INTEL_COMPILER/100) +# define COMPILER_VERSION_MINOR DEC(__INTEL_COMPILER/10 % 10) +# define COMPILER_VERSION_PATCH DEC(__INTEL_COMPILER % 10) +# if defined(__INTEL_COMPILER_BUILD_DATE) + /* __INTEL_COMPILER_BUILD_DATE = YYYYMMDD */ +# define COMPILER_VERSION_TWEAK DEC(__INTEL_COMPILER_BUILD_DATE) +# endif + +#elif defined(__PATHCC__) +# define COMPILER_ID "PathScale" +# define COMPILER_VERSION_MAJOR DEC(__PATHCC__) +# define COMPILER_VERSION_MINOR DEC(__PATHCC_MINOR__) +# if defined(__PATHCC_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__PATHCC_PATCHLEVEL__) +# endif + +#elif defined(__clang__) +# define COMPILER_ID "Clang" +# define COMPILER_VERSION_MAJOR DEC(__clang_major__) +# define COMPILER_VERSION_MINOR DEC(__clang_minor__) +# define COMPILER_VERSION_PATCH DEC(__clang_patchlevel__) + +#elif defined(__BORLANDC__) && defined(__CODEGEARC_VERSION__) +# define COMPILER_ID "Embarcadero" +# define COMPILER_VERSION_MAJOR HEX(__CODEGEARC_VERSION__>>24 & 0x00FF) +# define COMPILER_VERSION_MINOR HEX(__CODEGEARC_VERSION__>>16 & 0x00FF) +# define COMPILER_VERSION_PATCH HEX(__CODEGEARC_VERSION__ & 0xFFFF) + +#elif defined(__BORLANDC__) +# define COMPILER_ID "Borland" + /* __BORLANDC__ = 0xVRR */ +# define COMPILER_VERSION_MAJOR HEX(__BORLANDC__>>8) +# define COMPILER_VERSION_MINOR HEX(__BORLANDC__ & 0xFF) + +#elif defined(__WATCOMC__) +# define COMPILER_ID "Watcom" + /* __WATCOMC__ = VVRR */ +# define COMPILER_VERSION_MAJOR DEC(__WATCOMC__ / 100) +# define COMPILER_VERSION_MINOR DEC(__WATCOMC__ % 100) + +#elif defined(__SUNPRO_C) +# define COMPILER_ID "SunPro" +# if __SUNPRO_C >= 0x5100 + /* __SUNPRO_C = 0xVRRP */ +# define COMPILER_VERSION_MAJOR HEX(__SUNPRO_C>>12) +# define COMPILER_VERSION_MINOR HEX(__SUNPRO_C>>4 & 0xFF) +# define COMPILER_VERSION_PATCH HEX(__SUNPRO_C & 0xF) +# else + /* __SUNPRO_C = 0xVRP */ +# define COMPILER_VERSION_MAJOR HEX(__SUNPRO_C>>8) +# define COMPILER_VERSION_MINOR HEX(__SUNPRO_C>>4 & 0xF) +# define COMPILER_VERSION_PATCH HEX(__SUNPRO_C & 0xF) +# endif + +#elif defined(__HP_cc) +# define COMPILER_ID "HP" + /* __HP_cc = VVRRPP */ +# define COMPILER_VERSION_MAJOR DEC(__HP_cc/10000) +# define COMPILER_VERSION_MINOR DEC(__HP_cc/100 % 100) +# define COMPILER_VERSION_PATCH DEC(__HP_cc % 100) + +#elif defined(__DECC) +# define COMPILER_ID "Compaq" + /* __DECC_VER = VVRRTPPPP */ +# define COMPILER_VERSION_MAJOR DEC(__DECC_VER/10000000) +# define COMPILER_VERSION_MINOR DEC(__DECC_VER/100000 % 100) +# define COMPILER_VERSION_PATCH DEC(__DECC_VER % 10000) + +#elif defined(__IBMC__) +# if defined(__COMPILER_VER__) +# define COMPILER_ID "zOS" +# else +# if __IBMC__ >= 800 +# define COMPILER_ID "XL" +# else +# define COMPILER_ID "VisualAge" +# endif + /* __IBMC__ = VRP */ +# define COMPILER_VERSION_MAJOR DEC(__IBMC__/100) +# define COMPILER_VERSION_MINOR DEC(__IBMC__/10 % 10) +# define COMPILER_VERSION_PATCH DEC(__IBMC__ % 10) +# endif + +#elif defined(__PGI) +# define COMPILER_ID "PGI" +# define COMPILER_VERSION_MAJOR DEC(__PGIC__) +# define COMPILER_VERSION_MINOR DEC(__PGIC_MINOR__) +# if defined(__PGIC_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__PGIC_PATCHLEVEL__) +# endif + +#elif defined(_CRAYC) +# define COMPILER_ID "Cray" +# define COMPILER_VERSION_MAJOR DEC(_RELEASE) +# define COMPILER_VERSION_MINOR DEC(_RELEASE_MINOR) + +#elif defined(__TI_COMPILER_VERSION__) +# define COMPILER_ID "TI" + /* __TI_COMPILER_VERSION__ = VVVRRRPPP */ +# define COMPILER_VERSION_MAJOR DEC(__TI_COMPILER_VERSION__/1000000) +# define COMPILER_VERSION_MINOR DEC(__TI_COMPILER_VERSION__/1000 % 1000) +# define COMPILER_VERSION_PATCH DEC(__TI_COMPILER_VERSION__ % 1000) + +#elif defined(__TINYC__) +# define COMPILER_ID "TinyCC" + +#elif defined(__SCO_VERSION__) +# define COMPILER_ID "SCO" + +#elif defined(__GNUC__) +# define COMPILER_ID "GNU" +# define COMPILER_VERSION_MAJOR DEC(__GNUC__) +# define COMPILER_VERSION_MINOR DEC(__GNUC_MINOR__) +# if defined(__GNUC_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__) +# endif + +#elif defined(_MSC_VER) +# define COMPILER_ID "MSVC" + /* _MSC_VER = VVRR */ +# define COMPILER_VERSION_MAJOR DEC(_MSC_VER / 100) +# define COMPILER_VERSION_MINOR DEC(_MSC_VER % 100) +# if defined(_MSC_FULL_VER) +# if _MSC_VER >= 1400 + /* _MSC_FULL_VER = VVRRPPPPP */ +# define COMPILER_VERSION_PATCH DEC(_MSC_FULL_VER % 100000) +# else + /* _MSC_FULL_VER = VVRRPPPP */ +# define COMPILER_VERSION_PATCH DEC(_MSC_FULL_VER % 10000) +# endif +# endif +# if defined(_MSC_BUILD) +# define COMPILER_VERSION_TWEAK DEC(_MSC_BUILD) +# endif + +/* Analog VisualDSP++ >= 4.5.6 */ +#elif defined(__VISUALDSPVERSION__) +# define COMPILER_ID "ADSP" + /* __VISUALDSPVERSION__ = 0xVVRRPP00 */ +# define COMPILER_VERSION_MAJOR HEX(__VISUALDSPVERSION__>>24) +# define COMPILER_VERSION_MINOR HEX(__VISUALDSPVERSION__>>16 & 0xFF) +# define COMPILER_VERSION_PATCH HEX(__VISUALDSPVERSION__>>8 & 0xFF) + +/* Analog VisualDSP++ < 4.5.6 */ +#elif defined(__ADSPBLACKFIN__) || defined(__ADSPTS__) || defined(__ADSP21000__) +# define COMPILER_ID "ADSP" + +/* IAR Systems compiler for embedded systems. + http://www.iar.com */ +#elif defined(__IAR_SYSTEMS_ICC__ ) || defined(__IAR_SYSTEMS_ICC) +# define COMPILER_ID "IAR" + +/* sdcc, the small devices C compiler for embedded systems, + http://sdcc.sourceforge.net */ +#elif defined(SDCC) +# define COMPILER_ID "SDCC" + /* SDCC = VRP */ +# define COMPILER_VERSION_MAJOR DEC(SDCC/100) +# define COMPILER_VERSION_MINOR DEC(SDCC/10 % 10) +# define COMPILER_VERSION_PATCH DEC(SDCC % 10) + +#elif defined(_SGI_COMPILER_VERSION) || defined(_COMPILER_VERSION) +# define COMPILER_ID "MIPSpro" +# if defined(_SGI_COMPILER_VERSION) + /* _SGI_COMPILER_VERSION = VRP */ +# define COMPILER_VERSION_MAJOR DEC(_SGI_COMPILER_VERSION/100) +# define COMPILER_VERSION_MINOR DEC(_SGI_COMPILER_VERSION/10 % 10) +# define COMPILER_VERSION_PATCH DEC(_SGI_COMPILER_VERSION % 10) +# else + /* _COMPILER_VERSION = VRP */ +# define COMPILER_VERSION_MAJOR DEC(_COMPILER_VERSION/100) +# define COMPILER_VERSION_MINOR DEC(_COMPILER_VERSION/10 % 10) +# define COMPILER_VERSION_PATCH DEC(_COMPILER_VERSION % 10) +# endif + +/* This compiler is either not known or is too old to define an + identification macro. Try to identify the platform and guess that + it is the native compiler. */ +#elif defined(__sgi) +# define COMPILER_ID "MIPSpro" + +#elif defined(__hpux) || defined(__hpua) +# define COMPILER_ID "HP" + +#else /* unknown compiler */ +# define COMPILER_ID "" + +#endif + +/* Construct the string literal in pieces to prevent the source from + getting matched. Store it in a pointer rather than an array + because some compilers will just produce instructions to fill the + array rather than assigning a pointer to a static array. */ +char const* info_compiler = "INFO" ":" "compiler[" COMPILER_ID "]"; + +/* Identify known platforms by name. */ +#if defined(__linux) || defined(__linux__) || defined(linux) +# define PLATFORM_ID "Linux" + +#elif defined(__CYGWIN__) +# define PLATFORM_ID "Cygwin" + +#elif defined(__MINGW32__) +# define PLATFORM_ID "MinGW" + +#elif defined(__APPLE__) +# define PLATFORM_ID "Darwin" + +#elif defined(_WIN32) || defined(__WIN32__) || defined(WIN32) +# define PLATFORM_ID "Windows" + +#elif defined(__FreeBSD__) || defined(__FreeBSD) +# define PLATFORM_ID "FreeBSD" + +#elif defined(__NetBSD__) || defined(__NetBSD) +# define PLATFORM_ID "NetBSD" + +#elif defined(__OpenBSD__) || defined(__OPENBSD) +# define PLATFORM_ID "OpenBSD" + +#elif defined(__sun) || defined(sun) +# define PLATFORM_ID "SunOS" + +#elif defined(_AIX) || defined(__AIX) || defined(__AIX__) || defined(__aix) || defined(__aix__) +# define PLATFORM_ID "AIX" + +#elif defined(__sgi) || defined(__sgi__) || defined(_SGI) +# define PLATFORM_ID "IRIX" + +#elif defined(__hpux) || defined(__hpux__) +# define PLATFORM_ID "HP-UX" + +#elif defined(__HAIKU__) +# define PLATFORM_ID "Haiku" + +#elif defined(__BeOS) || defined(__BEOS__) || defined(_BEOS) +# define PLATFORM_ID "BeOS" + +#elif defined(__QNX__) || defined(__QNXNTO__) +# define PLATFORM_ID "QNX" + +#elif defined(__tru64) || defined(_tru64) || defined(__TRU64__) +# define PLATFORM_ID "Tru64" + +#elif defined(__riscos) || defined(__riscos__) +# define PLATFORM_ID "RISCos" + +#elif defined(__sinix) || defined(__sinix__) || defined(__SINIX__) +# define PLATFORM_ID "SINIX" + +#elif defined(__UNIX_SV__) +# define PLATFORM_ID "UNIX_SV" + +#elif defined(__bsdos__) +# define PLATFORM_ID "BSDOS" + +#elif defined(_MPRAS) || defined(MPRAS) +# define PLATFORM_ID "MP-RAS" + +#elif defined(__osf) || defined(__osf__) +# define PLATFORM_ID "OSF1" + +#elif defined(_SCO_SV) || defined(SCO_SV) || defined(sco_sv) +# define PLATFORM_ID "SCO_SV" + +#elif defined(__ultrix) || defined(__ultrix__) || defined(_ULTRIX) +# define PLATFORM_ID "ULTRIX" + +#elif defined(__XENIX__) || defined(_XENIX) || defined(XENIX) +# define PLATFORM_ID "Xenix" + +#else /* unknown platform */ +# define PLATFORM_ID "" + +#endif + +/* For windows compilers MSVC and Intel we can determine + the architecture of the compiler being used. This is because + the compilers do not have flags that can change the architecture, + but rather depend on which compiler is being used +*/ +#if defined(_WIN32) && defined(_MSC_VER) +# if defined(_M_IA64) +# define ARCHITECTURE_ID "IA64" + +# elif defined(_M_X64) || defined(_M_AMD64) +# define ARCHITECTURE_ID "x64" + +# elif defined(_M_IX86) +# define ARCHITECTURE_ID "X86" + +# elif defined(_M_ARM) +# define ARCHITECTURE_ID "ARM" + +# elif defined(_M_MIPS) +# define ARCHITECTURE_ID "MIPS" + +# elif defined(_M_SH) +# define ARCHITECTURE_ID "SHx" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#else +# define ARCHITECTURE_ID "" +#endif + +/* Convert integer to decimal digit literals. */ +#define DEC(n) \ + ('0' + (((n) / 10000000)%10)), \ + ('0' + (((n) / 1000000)%10)), \ + ('0' + (((n) / 100000)%10)), \ + ('0' + (((n) / 10000)%10)), \ + ('0' + (((n) / 1000)%10)), \ + ('0' + (((n) / 100)%10)), \ + ('0' + (((n) / 10)%10)), \ + ('0' + ((n) % 10)) + +/* Convert integer to hex digit literals. */ +#define HEX(n) \ + ('0' + ((n)>>28 & 0xF)), \ + ('0' + ((n)>>24 & 0xF)), \ + ('0' + ((n)>>20 & 0xF)), \ + ('0' + ((n)>>16 & 0xF)), \ + ('0' + ((n)>>12 & 0xF)), \ + ('0' + ((n)>>8 & 0xF)), \ + ('0' + ((n)>>4 & 0xF)), \ + ('0' + ((n) & 0xF)) + +/* Construct a string literal encoding the version number components. */ +#ifdef COMPILER_VERSION_MAJOR +char const info_version[] = { + 'I', 'N', 'F', 'O', ':', + 'c','o','m','p','i','l','e','r','_','v','e','r','s','i','o','n','[', + COMPILER_VERSION_MAJOR, +# ifdef COMPILER_VERSION_MINOR + '.', COMPILER_VERSION_MINOR, +# ifdef COMPILER_VERSION_PATCH + '.', COMPILER_VERSION_PATCH, +# ifdef COMPILER_VERSION_TWEAK + '.', COMPILER_VERSION_TWEAK, +# endif +# endif +# endif + ']','\0'}; +#endif + +/* Construct the string literal in pieces to prevent the source from + getting matched. Store it in a pointer rather than an array + because some compilers will just produce instructions to fill the + array rather than assigning a pointer to a static array. */ +char const* info_platform = "INFO" ":" "platform[" PLATFORM_ID "]"; +char const* info_arch = "INFO" ":" "arch[" ARCHITECTURE_ID "]"; + + + +/*--------------------------------------------------------------------------*/ + +#ifdef ID_VOID_MAIN +void main() {} +#else +int main(int argc, char* argv[]) +{ + int require = 0; + require += info_compiler[argc]; + require += info_platform[argc]; + require += info_arch[argc]; +#ifdef COMPILER_VERSION_MAJOR + require += info_version[argc]; +#endif + (void)argv; + return require; +} +#endif diff --git a/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/2.8.12.2/CompilerIdC/a.out b/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/2.8.12.2/CompilerIdC/a.out new file mode 100755 index 0000000000000000000000000000000000000000..1d7e438b92300abaac114123c512167b14d7d259 GIT binary patch literal 8683 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 & 0x00FF) +# define COMPILER_VERSION_MINOR HEX(__CODEGEARC_VERSION__>>16 & 0x00FF) +# define COMPILER_VERSION_PATCH HEX(__CODEGEARC_VERSION__ & 0xFFFF) + +#elif defined(__BORLANDC__) +# define COMPILER_ID "Borland" + /* __BORLANDC__ = 0xVRR */ +# define COMPILER_VERSION_MAJOR HEX(__BORLANDC__>>8) +# define COMPILER_VERSION_MINOR HEX(__BORLANDC__ & 0xFF) + +#elif defined(__WATCOMC__) +# define COMPILER_ID "Watcom" + /* __WATCOMC__ = VVRR */ +# define COMPILER_VERSION_MAJOR DEC(__WATCOMC__ / 100) +# define COMPILER_VERSION_MINOR DEC(__WATCOMC__ % 100) + +#elif defined(__SUNPRO_CC) +# define COMPILER_ID "SunPro" +# if __SUNPRO_CC >= 0x5100 + /* __SUNPRO_CC = 0xVRRP */ +# define COMPILER_VERSION_MAJOR HEX(__SUNPRO_CC>>12) +# define COMPILER_VERSION_MINOR HEX(__SUNPRO_CC>>4 & 0xFF) +# define COMPILER_VERSION_PATCH HEX(__SUNPRO_CC & 0xF) +# else + /* __SUNPRO_CC = 0xVRP */ +# define COMPILER_VERSION_MAJOR HEX(__SUNPRO_CC>>8) +# define COMPILER_VERSION_MINOR HEX(__SUNPRO_CC>>4 & 0xF) +# define COMPILER_VERSION_PATCH HEX(__SUNPRO_CC & 0xF) +# endif + +#elif defined(__HP_aCC) +# define COMPILER_ID "HP" + /* __HP_aCC = VVRRPP */ +# define COMPILER_VERSION_MAJOR DEC(__HP_aCC/10000) +# define COMPILER_VERSION_MINOR DEC(__HP_aCC/100 % 100) +# define COMPILER_VERSION_PATCH DEC(__HP_aCC % 100) + +#elif defined(__DECCXX) +# define COMPILER_ID "Compaq" + /* __DECCXX_VER = VVRRTPPPP */ +# define COMPILER_VERSION_MAJOR DEC(__DECCXX_VER/10000000) +# define COMPILER_VERSION_MINOR DEC(__DECCXX_VER/100000 % 100) +# define COMPILER_VERSION_PATCH DEC(__DECCXX_VER % 10000) + +#elif defined(__IBMCPP__) +# if defined(__COMPILER_VER__) +# define COMPILER_ID "zOS" +# else +# if __IBMCPP__ >= 800 +# define COMPILER_ID "XL" +# else +# define COMPILER_ID "VisualAge" +# endif + /* __IBMCPP__ = VRP */ +# define COMPILER_VERSION_MAJOR DEC(__IBMCPP__/100) +# define COMPILER_VERSION_MINOR DEC(__IBMCPP__/10 % 10) +# define COMPILER_VERSION_PATCH DEC(__IBMCPP__ % 10) +# endif + +#elif defined(__PGI) +# define COMPILER_ID "PGI" +# define COMPILER_VERSION_MAJOR DEC(__PGIC__) +# define COMPILER_VERSION_MINOR DEC(__PGIC_MINOR__) +# if defined(__PGIC_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__PGIC_PATCHLEVEL__) +# endif + +#elif defined(_CRAYC) +# define COMPILER_ID "Cray" +# define COMPILER_VERSION_MAJOR DEC(_RELEASE) +# define COMPILER_VERSION_MINOR DEC(_RELEASE_MINOR) + +#elif defined(__TI_COMPILER_VERSION__) +# define COMPILER_ID "TI" + /* __TI_COMPILER_VERSION__ = VVVRRRPPP */ +# define COMPILER_VERSION_MAJOR DEC(__TI_COMPILER_VERSION__/1000000) +# define COMPILER_VERSION_MINOR DEC(__TI_COMPILER_VERSION__/1000 % 1000) +# define COMPILER_VERSION_PATCH DEC(__TI_COMPILER_VERSION__ % 1000) + +#elif defined(__SCO_VERSION__) +# define COMPILER_ID "SCO" + +#elif defined(__GNUC__) +# define COMPILER_ID "GNU" +# define COMPILER_VERSION_MAJOR DEC(__GNUC__) +# define COMPILER_VERSION_MINOR DEC(__GNUC_MINOR__) +# if defined(__GNUC_PATCHLEVEL__) +# define COMPILER_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__) +# endif + +#elif defined(_MSC_VER) +# define COMPILER_ID "MSVC" + /* _MSC_VER = VVRR */ +# define COMPILER_VERSION_MAJOR DEC(_MSC_VER / 100) +# define COMPILER_VERSION_MINOR DEC(_MSC_VER % 100) +# if defined(_MSC_FULL_VER) +# if _MSC_VER >= 1400 + /* _MSC_FULL_VER = VVRRPPPPP */ +# define COMPILER_VERSION_PATCH DEC(_MSC_FULL_VER % 100000) +# else + /* _MSC_FULL_VER = VVRRPPPP */ +# define COMPILER_VERSION_PATCH DEC(_MSC_FULL_VER % 10000) +# endif +# endif +# if defined(_MSC_BUILD) +# define COMPILER_VERSION_TWEAK DEC(_MSC_BUILD) +# endif + +/* Analog VisualDSP++ >= 4.5.6 */ +#elif defined(__VISUALDSPVERSION__) +# define COMPILER_ID "ADSP" + /* __VISUALDSPVERSION__ = 0xVVRRPP00 */ +# define COMPILER_VERSION_MAJOR HEX(__VISUALDSPVERSION__>>24) +# define COMPILER_VERSION_MINOR HEX(__VISUALDSPVERSION__>>16 & 0xFF) +# define COMPILER_VERSION_PATCH HEX(__VISUALDSPVERSION__>>8 & 0xFF) + +/* Analog VisualDSP++ < 4.5.6 */ +#elif defined(__ADSPBLACKFIN__) || defined(__ADSPTS__) || defined(__ADSP21000__) +# define COMPILER_ID "ADSP" + +/* IAR Systems compiler for embedded systems. + http://www.iar.com */ +#elif defined(__IAR_SYSTEMS_ICC__ ) || defined(__IAR_SYSTEMS_ICC) +# define COMPILER_ID "IAR" + +#elif defined(_SGI_COMPILER_VERSION) || defined(_COMPILER_VERSION) +# define COMPILER_ID "MIPSpro" +# if defined(_SGI_COMPILER_VERSION) + /* _SGI_COMPILER_VERSION = VRP */ +# define COMPILER_VERSION_MAJOR DEC(_SGI_COMPILER_VERSION/100) +# define COMPILER_VERSION_MINOR DEC(_SGI_COMPILER_VERSION/10 % 10) +# define COMPILER_VERSION_PATCH DEC(_SGI_COMPILER_VERSION % 10) +# else + /* _COMPILER_VERSION = VRP */ +# define COMPILER_VERSION_MAJOR DEC(_COMPILER_VERSION/100) +# define COMPILER_VERSION_MINOR DEC(_COMPILER_VERSION/10 % 10) +# define COMPILER_VERSION_PATCH DEC(_COMPILER_VERSION % 10) +# endif + +/* This compiler is either not known or is too old to define an + identification macro. Try to identify the platform and guess that + it is the native compiler. */ +#elif defined(__sgi) +# define COMPILER_ID "MIPSpro" + +#elif defined(__hpux) || defined(__hpua) +# define COMPILER_ID "HP" + +#else /* unknown compiler */ +# define COMPILER_ID "" + +#endif + +/* Construct the string literal in pieces to prevent the source from + getting matched. Store it in a pointer rather than an array + because some compilers will just produce instructions to fill the + array rather than assigning a pointer to a static array. */ +char const* info_compiler = "INFO" ":" "compiler[" COMPILER_ID "]"; + +/* Identify known platforms by name. */ +#if defined(__linux) || defined(__linux__) || defined(linux) +# define PLATFORM_ID "Linux" + +#elif defined(__CYGWIN__) +# define PLATFORM_ID "Cygwin" + +#elif defined(__MINGW32__) +# define PLATFORM_ID "MinGW" + +#elif defined(__APPLE__) +# define PLATFORM_ID "Darwin" + +#elif defined(_WIN32) || defined(__WIN32__) || defined(WIN32) +# define PLATFORM_ID "Windows" + +#elif defined(__FreeBSD__) || defined(__FreeBSD) +# define PLATFORM_ID "FreeBSD" + +#elif defined(__NetBSD__) || defined(__NetBSD) +# define PLATFORM_ID "NetBSD" + +#elif defined(__OpenBSD__) || defined(__OPENBSD) +# define PLATFORM_ID "OpenBSD" + +#elif defined(__sun) || defined(sun) +# define PLATFORM_ID "SunOS" + +#elif defined(_AIX) || defined(__AIX) || defined(__AIX__) || defined(__aix) || defined(__aix__) +# define PLATFORM_ID "AIX" + +#elif defined(__sgi) || defined(__sgi__) || defined(_SGI) +# define PLATFORM_ID "IRIX" + +#elif defined(__hpux) || defined(__hpux__) +# define PLATFORM_ID "HP-UX" + +#elif defined(__HAIKU__) +# define PLATFORM_ID "Haiku" + +#elif defined(__BeOS) || defined(__BEOS__) || defined(_BEOS) +# define PLATFORM_ID "BeOS" + +#elif defined(__QNX__) || defined(__QNXNTO__) +# define PLATFORM_ID "QNX" + +#elif defined(__tru64) || defined(_tru64) || defined(__TRU64__) +# define PLATFORM_ID "Tru64" + +#elif defined(__riscos) || defined(__riscos__) +# define PLATFORM_ID "RISCos" + +#elif defined(__sinix) || defined(__sinix__) || defined(__SINIX__) +# define PLATFORM_ID "SINIX" + +#elif defined(__UNIX_SV__) +# define PLATFORM_ID "UNIX_SV" + +#elif defined(__bsdos__) +# define PLATFORM_ID "BSDOS" + +#elif defined(_MPRAS) || defined(MPRAS) +# define PLATFORM_ID "MP-RAS" + +#elif defined(__osf) || defined(__osf__) +# define PLATFORM_ID "OSF1" + +#elif defined(_SCO_SV) || defined(SCO_SV) || defined(sco_sv) +# define PLATFORM_ID "SCO_SV" + +#elif defined(__ultrix) || defined(__ultrix__) || defined(_ULTRIX) +# define PLATFORM_ID "ULTRIX" + +#elif defined(__XENIX__) || defined(_XENIX) || defined(XENIX) +# define PLATFORM_ID "Xenix" + +#else /* unknown platform */ +# define PLATFORM_ID "" + +#endif + +/* For windows compilers MSVC and Intel we can determine + the architecture of the compiler being used. This is because + the compilers do not have flags that can change the architecture, + but rather depend on which compiler is being used +*/ +#if defined(_WIN32) && defined(_MSC_VER) +# if defined(_M_IA64) +# define ARCHITECTURE_ID "IA64" + +# elif defined(_M_X64) || defined(_M_AMD64) +# define ARCHITECTURE_ID "x64" + +# elif defined(_M_IX86) +# define ARCHITECTURE_ID "X86" + +# elif defined(_M_ARM) +# define ARCHITECTURE_ID "ARM" + +# elif defined(_M_MIPS) +# define ARCHITECTURE_ID "MIPS" + +# elif defined(_M_SH) +# define ARCHITECTURE_ID "SHx" + +# else /* unknown architecture */ +# define ARCHITECTURE_ID "" +# endif + +#else +# define ARCHITECTURE_ID "" +#endif + +/* Convert integer to decimal digit literals. */ +#define DEC(n) \ + ('0' + (((n) / 10000000)%10)), \ + ('0' + (((n) / 1000000)%10)), \ + ('0' + (((n) / 100000)%10)), \ + ('0' + (((n) / 10000)%10)), \ + ('0' + (((n) / 1000)%10)), \ + ('0' + (((n) / 100)%10)), \ + ('0' + (((n) / 10)%10)), \ + ('0' + ((n) % 10)) + +/* Convert integer to hex digit literals. */ +#define HEX(n) \ + ('0' + ((n)>>28 & 0xF)), \ + ('0' + ((n)>>24 & 0xF)), \ + ('0' + ((n)>>20 & 0xF)), \ + ('0' + ((n)>>16 & 0xF)), \ + ('0' + ((n)>>12 & 0xF)), \ + ('0' + ((n)>>8 & 0xF)), \ + ('0' + ((n)>>4 & 0xF)), \ + ('0' + ((n) & 0xF)) + +/* Construct a string literal encoding the version number components. */ +#ifdef COMPILER_VERSION_MAJOR +char const info_version[] = { + 'I', 'N', 'F', 'O', ':', + 'c','o','m','p','i','l','e','r','_','v','e','r','s','i','o','n','[', + COMPILER_VERSION_MAJOR, +# ifdef COMPILER_VERSION_MINOR + '.', COMPILER_VERSION_MINOR, +# ifdef COMPILER_VERSION_PATCH + '.', COMPILER_VERSION_PATCH, +# ifdef COMPILER_VERSION_TWEAK + '.', COMPILER_VERSION_TWEAK, +# endif +# endif +# endif + ']','\0'}; +#endif + +/* Construct the string literal in pieces to prevent the source from + getting matched. Store it in a pointer rather than an array + because some compilers will just produce instructions to fill the + array rather than assigning a pointer to a static array. */ +char const* info_platform = "INFO" ":" "platform[" PLATFORM_ID "]"; +char const* info_arch = "INFO" ":" "arch[" ARCHITECTURE_ID "]"; + + + +/*--------------------------------------------------------------------------*/ + +int main(int argc, char* argv[]) +{ + int require = 0; + require += info_compiler[argc]; + require += info_platform[argc]; +#ifdef COMPILER_VERSION_MAJOR + require += info_version[argc]; +#endif + (void)argv; + return require; +} diff --git a/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/2.8.12.2/CompilerIdCXX/a.out b/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/2.8.12.2/CompilerIdCXX/a.out new file mode 100755 index 0000000000000000000000000000000000000000..aeee00b0724a9ab52a33c118ab316ac8e587fac6 GIT binary patch literal 8692 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 literal 0 HcmV?d00001 diff --git a/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/CMakeDirectoryInformation.cmake b/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/CMakeDirectoryInformation.cmake new file mode 100644 index 0000000000..335b0cbcf2 --- /dev/null +++ b/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/CMakeDirectoryInformation.cmake @@ -0,0 +1,16 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 2.8 + +# Relative path conversion top directories. +SET(CMAKE_RELATIVE_PATH_TOP_SOURCE "/home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C") +SET(CMAKE_RELATIVE_PATH_TOP_BINARY "/home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build") + +# Force unix paths in dependencies. +SET(CMAKE_FORCE_UNIX_PATHS 1) + + +# The C and CXX include file regular expressions for this directory. +SET(CMAKE_C_INCLUDE_REGEX_SCAN "^.*$") +SET(CMAKE_C_INCLUDE_REGEX_COMPLAIN "^$") +SET(CMAKE_CXX_INCLUDE_REGEX_SCAN ${CMAKE_C_INCLUDE_REGEX_SCAN}) +SET(CMAKE_CXX_INCLUDE_REGEX_COMPLAIN ${CMAKE_C_INCLUDE_REGEX_COMPLAIN}) diff --git a/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/CMakeOutput.log b/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/CMakeOutput.log new file mode 100644 index 0000000000..10bdcf5f63 --- /dev/null +++ b/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/CMakeOutput.log @@ -0,0 +1,263 @@ +The system is: Linux - 3.17.0-031700-lowlatency - x86_64 +Compiling the C compiler identification source file "CMakeCCompilerId.c" succeeded. +Compiler: /usr/bin/cc +Build flags: +Id flags: + +The output was: +0 + + +Compilation of the C compiler identification source "CMakeCCompilerId.c" produced "a.out" + +The C compiler identification is GNU, found in "/home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/2.8.12.2/CompilerIdC/a.out" + +Compiling the CXX compiler identification source file "CMakeCXXCompilerId.cpp" succeeded. +Compiler: /usr/bin/c++ +Build flags: +Id flags: + +The output was: +0 + + +Compilation of the CXX compiler identification source "CMakeCXXCompilerId.cpp" produced "a.out" + +The CXX compiler identification is GNU, found in "/home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/2.8.12.2/CompilerIdCXX/a.out" + +Determining if the C compiler works passed with the following output: +Change Dir: /home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/CMakeTmp + +Run Build Command:/usr/bin/make "cmTryCompileExec4097118404/fast" +/usr/bin/make -f CMakeFiles/cmTryCompileExec4097118404.dir/build.make CMakeFiles/cmTryCompileExec4097118404.dir/build +make[1]: Entering directory `/home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/CMakeTmp' +/usr/bin/cmake -E cmake_progress_report /home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/CMakeTmp/CMakeFiles 1 +Building C object CMakeFiles/cmTryCompileExec4097118404.dir/testCCompiler.c.o +/usr/bin/cc -o CMakeFiles/cmTryCompileExec4097118404.dir/testCCompiler.c.o -c /home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/CMakeTmp/testCCompiler.c +Linking C executable cmTryCompileExec4097118404 +/usr/bin/cmake -E cmake_link_script CMakeFiles/cmTryCompileExec4097118404.dir/link.txt --verbose=1 +/usr/bin/cc CMakeFiles/cmTryCompileExec4097118404.dir/testCCompiler.c.o -o cmTryCompileExec4097118404 -rdynamic +make[1]: Leaving directory `/home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/CMakeTmp' + + +Detecting C compiler ABI info compiled with the following output: +Change Dir: /home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/CMakeTmp + +Run Build Command:/usr/bin/make "cmTryCompileExec3603593924/fast" +/usr/bin/make -f CMakeFiles/cmTryCompileExec3603593924.dir/build.make CMakeFiles/cmTryCompileExec3603593924.dir/build +make[1]: Entering directory `/home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/CMakeTmp' +/usr/bin/cmake -E cmake_progress_report /home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/CMakeTmp/CMakeFiles 1 +Building C object CMakeFiles/cmTryCompileExec3603593924.dir/CMakeCCompilerABI.c.o +/usr/bin/cc -o CMakeFiles/cmTryCompileExec3603593924.dir/CMakeCCompilerABI.c.o -c /usr/share/cmake-2.8/Modules/CMakeCCompilerABI.c +Linking C executable cmTryCompileExec3603593924 +/usr/bin/cmake -E cmake_link_script CMakeFiles/cmTryCompileExec3603593924.dir/link.txt --verbose=1 +/usr/bin/cc -v CMakeFiles/cmTryCompileExec3603593924.dir/CMakeCCompilerABI.c.o -o cmTryCompileExec3603593924 -rdynamic +Using built-in specs. +COLLECT_GCC=/usr/bin/cc +COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/4.8/lto-wrapper +Target: x86_64-linux-gnu +Configured with: ../src/configure -v --with-pkgversion='Ubuntu 4.8.4-2ubuntu1~14.04' --with-bugurl=file:///usr/share/doc/gcc-4.8/README.Bugs --enable-languages=c,c++,java,go,d,fortran,objc,obj-c++ --prefix=/usr --program-suffix=-4.8 --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --with-gxx-include-dir=/usr/include/c++/4.8 --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --enable-gnu-unique-object --disable-libmudflap --enable-plugin --with-system-zlib --disable-browser-plugin --enable-java-awt=gtk --enable-gtk-cairo --with-java-home=/usr/lib/jvm/java-1.5.0-gcj-4.8-amd64/jre --enable-java-home --with-jvm-root-dir=/usr/lib/jvm/java-1.5.0-gcj-4.8-amd64 --with-jvm-jar-dir=/usr/lib/jvm-exports/java-1.5.0-gcj-4.8-amd64 --with-arch-directory=amd64 --with-ecj-jar=/usr/share/java/eclipse-ecj.jar --enable-objc-gc --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --with-tune=generic --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu +Thread model: posix +gcc version 4.8.4 (Ubuntu 4.8.4-2ubuntu1~14.04) +COMPILER_PATH=/usr/lib/gcc/x86_64-linux-gnu/4.8/:/usr/lib/gcc/x86_64-linux-gnu/4.8/:/usr/lib/gcc/x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/4.8/:/usr/lib/gcc/x86_64-linux-gnu/ +LIBRARY_PATH=/usr/lib/gcc/x86_64-linux-gnu/4.8/:/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../lib/:/lib/x86_64-linux-gnu/:/lib/../lib/:/usr/lib/x86_64-linux-gnu/:/usr/lib/../lib/:/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../:/lib/:/usr/lib/ +COLLECT_GCC_OPTIONS='-v' '-o' 'cmTryCompileExec3603593924' '-rdynamic' '-mtune=generic' '-march=x86-64' + /usr/lib/gcc/x86_64-linux-gnu/4.8/collect2 --sysroot=/ --build-id --eh-frame-hdr -m elf_x86_64 --hash-style=gnu --as-needed -export-dynamic -dynamic-linker /lib64/ld-linux-x86-64.so.2 -z relro -o cmTryCompileExec3603593924 /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/crt1.o /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/crti.o /usr/lib/gcc/x86_64-linux-gnu/4.8/crtbegin.o -L/usr/lib/gcc/x86_64-linux-gnu/4.8 -L/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu -L/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../lib -L/lib/x86_64-linux-gnu -L/lib/../lib -L/usr/lib/x86_64-linux-gnu -L/usr/lib/../lib -L/usr/lib/gcc/x86_64-linux-gnu/4.8/../../.. CMakeFiles/cmTryCompileExec3603593924.dir/CMakeCCompilerABI.c.o -lgcc --as-needed -lgcc_s --no-as-needed -lc -lgcc --as-needed -lgcc_s --no-as-needed /usr/lib/gcc/x86_64-linux-gnu/4.8/crtend.o /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/crtn.o +make[1]: Leaving directory `/home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/CMakeTmp' + + +Parsed C implicit link information from above output: + link line regex: [^( *|.*[/\])(ld|([^/\]+-)?ld|collect2)[^/\]*( |$)] + ignore line: [Change Dir: /home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/CMakeTmp] + ignore line: [] + ignore line: [Run Build Command:/usr/bin/make "cmTryCompileExec3603593924/fast"] + ignore line: [/usr/bin/make -f CMakeFiles/cmTryCompileExec3603593924.dir/build.make CMakeFiles/cmTryCompileExec3603593924.dir/build] + ignore line: [make[1]: Entering directory `/home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/CMakeTmp'] + ignore line: [/usr/bin/cmake -E cmake_progress_report /home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/CMakeTmp/CMakeFiles 1] + ignore line: [Building C object CMakeFiles/cmTryCompileExec3603593924.dir/CMakeCCompilerABI.c.o] + ignore line: [/usr/bin/cc -o CMakeFiles/cmTryCompileExec3603593924.dir/CMakeCCompilerABI.c.o -c /usr/share/cmake-2.8/Modules/CMakeCCompilerABI.c] + ignore line: [Linking C executable cmTryCompileExec3603593924] + ignore line: [/usr/bin/cmake -E cmake_link_script CMakeFiles/cmTryCompileExec3603593924.dir/link.txt --verbose=1] + ignore line: [/usr/bin/cc -v CMakeFiles/cmTryCompileExec3603593924.dir/CMakeCCompilerABI.c.o -o cmTryCompileExec3603593924 -rdynamic ] + ignore line: [Using built-in specs.] + ignore line: [COLLECT_GCC=/usr/bin/cc] + ignore line: [COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/4.8/lto-wrapper] + ignore line: [Target: x86_64-linux-gnu] + ignore line: [Configured with: ../src/configure -v --with-pkgversion='Ubuntu 4.8.4-2ubuntu1~14.04' --with-bugurl=file:///usr/share/doc/gcc-4.8/README.Bugs --enable-languages=c,c++,java,go,d,fortran,objc,obj-c++ --prefix=/usr --program-suffix=-4.8 --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --with-gxx-include-dir=/usr/include/c++/4.8 --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --enable-gnu-unique-object --disable-libmudflap --enable-plugin --with-system-zlib --disable-browser-plugin --enable-java-awt=gtk --enable-gtk-cairo --with-java-home=/usr/lib/jvm/java-1.5.0-gcj-4.8-amd64/jre --enable-java-home --with-jvm-root-dir=/usr/lib/jvm/java-1.5.0-gcj-4.8-amd64 --with-jvm-jar-dir=/usr/lib/jvm-exports/java-1.5.0-gcj-4.8-amd64 --with-arch-directory=amd64 --with-ecj-jar=/usr/share/java/eclipse-ecj.jar --enable-objc-gc --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --with-tune=generic --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu] + ignore line: [Thread model: posix] + ignore line: [gcc version 4.8.4 (Ubuntu 4.8.4-2ubuntu1~14.04) ] + ignore line: [COMPILER_PATH=/usr/lib/gcc/x86_64-linux-gnu/4.8/:/usr/lib/gcc/x86_64-linux-gnu/4.8/:/usr/lib/gcc/x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/4.8/:/usr/lib/gcc/x86_64-linux-gnu/] + ignore line: [LIBRARY_PATH=/usr/lib/gcc/x86_64-linux-gnu/4.8/:/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../lib/:/lib/x86_64-linux-gnu/:/lib/../lib/:/usr/lib/x86_64-linux-gnu/:/usr/lib/../lib/:/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../:/lib/:/usr/lib/] + ignore line: [COLLECT_GCC_OPTIONS='-v' '-o' 'cmTryCompileExec3603593924' '-rdynamic' '-mtune=generic' '-march=x86-64'] + link line: [ /usr/lib/gcc/x86_64-linux-gnu/4.8/collect2 --sysroot=/ --build-id --eh-frame-hdr -m elf_x86_64 --hash-style=gnu --as-needed -export-dynamic -dynamic-linker /lib64/ld-linux-x86-64.so.2 -z relro -o cmTryCompileExec3603593924 /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/crt1.o /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/crti.o /usr/lib/gcc/x86_64-linux-gnu/4.8/crtbegin.o -L/usr/lib/gcc/x86_64-linux-gnu/4.8 -L/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu -L/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../lib -L/lib/x86_64-linux-gnu -L/lib/../lib -L/usr/lib/x86_64-linux-gnu -L/usr/lib/../lib -L/usr/lib/gcc/x86_64-linux-gnu/4.8/../../.. CMakeFiles/cmTryCompileExec3603593924.dir/CMakeCCompilerABI.c.o -lgcc --as-needed -lgcc_s --no-as-needed -lc -lgcc --as-needed -lgcc_s --no-as-needed /usr/lib/gcc/x86_64-linux-gnu/4.8/crtend.o /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/crtn.o] + arg [/usr/lib/gcc/x86_64-linux-gnu/4.8/collect2] ==> ignore + arg [--sysroot=/] ==> ignore + arg [--build-id] ==> ignore + arg [--eh-frame-hdr] ==> ignore + arg [-m] ==> ignore + arg [elf_x86_64] ==> ignore + arg [--hash-style=gnu] ==> ignore + arg [--as-needed] ==> ignore + arg [-export-dynamic] ==> ignore + arg [-dynamic-linker] ==> ignore + arg [/lib64/ld-linux-x86-64.so.2] ==> ignore + arg [-zrelro] ==> ignore + arg [-o] ==> ignore + arg [cmTryCompileExec3603593924] ==> ignore + arg [/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/crt1.o] ==> ignore + arg [/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/crti.o] ==> ignore + arg [/usr/lib/gcc/x86_64-linux-gnu/4.8/crtbegin.o] ==> ignore + arg [-L/usr/lib/gcc/x86_64-linux-gnu/4.8] ==> dir [/usr/lib/gcc/x86_64-linux-gnu/4.8] + arg [-L/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu] ==> dir [/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu] + arg [-L/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../lib] ==> dir [/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../lib] + arg [-L/lib/x86_64-linux-gnu] ==> dir [/lib/x86_64-linux-gnu] + arg [-L/lib/../lib] ==> dir [/lib/../lib] + arg [-L/usr/lib/x86_64-linux-gnu] ==> dir [/usr/lib/x86_64-linux-gnu] + arg [-L/usr/lib/../lib] ==> dir [/usr/lib/../lib] + arg [-L/usr/lib/gcc/x86_64-linux-gnu/4.8/../../..] ==> dir [/usr/lib/gcc/x86_64-linux-gnu/4.8/../../..] + arg [CMakeFiles/cmTryCompileExec3603593924.dir/CMakeCCompilerABI.c.o] ==> ignore + arg [-lgcc] ==> lib [gcc] + arg [--as-needed] ==> ignore + arg [-lgcc_s] ==> lib [gcc_s] + arg [--no-as-needed] ==> ignore + arg [-lc] ==> lib [c] + arg [-lgcc] ==> lib [gcc] + arg [--as-needed] ==> ignore + arg [-lgcc_s] ==> lib [gcc_s] + arg [--no-as-needed] ==> ignore + arg [/usr/lib/gcc/x86_64-linux-gnu/4.8/crtend.o] ==> ignore + arg [/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/crtn.o] ==> ignore + remove lib [gcc] + remove lib [gcc_s] + remove lib [gcc] + remove lib [gcc_s] + collapse library dir [/usr/lib/gcc/x86_64-linux-gnu/4.8] ==> [/usr/lib/gcc/x86_64-linux-gnu/4.8] + collapse library dir [/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu] ==> [/usr/lib/x86_64-linux-gnu] + collapse library dir [/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../lib] ==> [/usr/lib] + collapse library dir [/lib/x86_64-linux-gnu] ==> [/lib/x86_64-linux-gnu] + collapse library dir [/lib/../lib] ==> [/lib] + collapse library dir [/usr/lib/x86_64-linux-gnu] ==> [/usr/lib/x86_64-linux-gnu] + collapse library dir [/usr/lib/../lib] ==> [/usr/lib] + collapse library dir [/usr/lib/gcc/x86_64-linux-gnu/4.8/../../..] ==> [/usr/lib] + implicit libs: [c] + implicit dirs: [/usr/lib/gcc/x86_64-linux-gnu/4.8;/usr/lib/x86_64-linux-gnu;/usr/lib;/lib/x86_64-linux-gnu;/lib] + implicit fwks: [] + + +Determining if the CXX compiler works passed with the following output: +Change Dir: /home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/CMakeTmp + +Run Build Command:/usr/bin/make "cmTryCompileExec997608794/fast" +/usr/bin/make -f CMakeFiles/cmTryCompileExec997608794.dir/build.make CMakeFiles/cmTryCompileExec997608794.dir/build +make[1]: Entering directory `/home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/CMakeTmp' +/usr/bin/cmake -E cmake_progress_report /home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/CMakeTmp/CMakeFiles 1 +Building CXX object CMakeFiles/cmTryCompileExec997608794.dir/testCXXCompiler.cxx.o +/usr/bin/c++ -o CMakeFiles/cmTryCompileExec997608794.dir/testCXXCompiler.cxx.o -c /home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/CMakeTmp/testCXXCompiler.cxx +Linking CXX executable cmTryCompileExec997608794 +/usr/bin/cmake -E cmake_link_script CMakeFiles/cmTryCompileExec997608794.dir/link.txt --verbose=1 +/usr/bin/c++ CMakeFiles/cmTryCompileExec997608794.dir/testCXXCompiler.cxx.o -o cmTryCompileExec997608794 -rdynamic +make[1]: Leaving directory `/home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/CMakeTmp' + + +Detecting CXX compiler ABI info compiled with the following output: +Change Dir: /home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/CMakeTmp + +Run Build Command:/usr/bin/make "cmTryCompileExec2573420878/fast" +/usr/bin/make -f CMakeFiles/cmTryCompileExec2573420878.dir/build.make CMakeFiles/cmTryCompileExec2573420878.dir/build +make[1]: Entering directory `/home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/CMakeTmp' +/usr/bin/cmake -E cmake_progress_report /home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/CMakeTmp/CMakeFiles 1 +Building CXX object CMakeFiles/cmTryCompileExec2573420878.dir/CMakeCXXCompilerABI.cpp.o +/usr/bin/c++ -o CMakeFiles/cmTryCompileExec2573420878.dir/CMakeCXXCompilerABI.cpp.o -c /usr/share/cmake-2.8/Modules/CMakeCXXCompilerABI.cpp +Linking CXX executable cmTryCompileExec2573420878 +/usr/bin/cmake -E cmake_link_script CMakeFiles/cmTryCompileExec2573420878.dir/link.txt --verbose=1 +/usr/bin/c++ -v CMakeFiles/cmTryCompileExec2573420878.dir/CMakeCXXCompilerABI.cpp.o -o cmTryCompileExec2573420878 -rdynamic +Using built-in specs. +COLLECT_GCC=/usr/bin/c++ +COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/4.8/lto-wrapper +Target: x86_64-linux-gnu +Configured with: ../src/configure -v --with-pkgversion='Ubuntu 4.8.4-2ubuntu1~14.04' --with-bugurl=file:///usr/share/doc/gcc-4.8/README.Bugs --enable-languages=c,c++,java,go,d,fortran,objc,obj-c++ --prefix=/usr --program-suffix=-4.8 --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --with-gxx-include-dir=/usr/include/c++/4.8 --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --enable-gnu-unique-object --disable-libmudflap --enable-plugin --with-system-zlib --disable-browser-plugin --enable-java-awt=gtk --enable-gtk-cairo --with-java-home=/usr/lib/jvm/java-1.5.0-gcj-4.8-amd64/jre --enable-java-home --with-jvm-root-dir=/usr/lib/jvm/java-1.5.0-gcj-4.8-amd64 --with-jvm-jar-dir=/usr/lib/jvm-exports/java-1.5.0-gcj-4.8-amd64 --with-arch-directory=amd64 --with-ecj-jar=/usr/share/java/eclipse-ecj.jar --enable-objc-gc --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --with-tune=generic --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu +Thread model: posix +gcc version 4.8.4 (Ubuntu 4.8.4-2ubuntu1~14.04) +COMPILER_PATH=/usr/lib/gcc/x86_64-linux-gnu/4.8/:/usr/lib/gcc/x86_64-linux-gnu/4.8/:/usr/lib/gcc/x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/4.8/:/usr/lib/gcc/x86_64-linux-gnu/ +LIBRARY_PATH=/usr/lib/gcc/x86_64-linux-gnu/4.8/:/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../lib/:/lib/x86_64-linux-gnu/:/lib/../lib/:/usr/lib/x86_64-linux-gnu/:/usr/lib/../lib/:/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../:/lib/:/usr/lib/ +COLLECT_GCC_OPTIONS='-v' '-o' 'cmTryCompileExec2573420878' '-rdynamic' '-shared-libgcc' '-mtune=generic' '-march=x86-64' + /usr/lib/gcc/x86_64-linux-gnu/4.8/collect2 --sysroot=/ --build-id --eh-frame-hdr -m elf_x86_64 --hash-style=gnu --as-needed -export-dynamic -dynamic-linker /lib64/ld-linux-x86-64.so.2 -z relro -o cmTryCompileExec2573420878 /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/crt1.o /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/crti.o /usr/lib/gcc/x86_64-linux-gnu/4.8/crtbegin.o -L/usr/lib/gcc/x86_64-linux-gnu/4.8 -L/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu -L/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../lib -L/lib/x86_64-linux-gnu -L/lib/../lib -L/usr/lib/x86_64-linux-gnu -L/usr/lib/../lib -L/usr/lib/gcc/x86_64-linux-gnu/4.8/../../.. CMakeFiles/cmTryCompileExec2573420878.dir/CMakeCXXCompilerABI.cpp.o -lstdc++ -lm -lgcc_s -lgcc -lc -lgcc_s -lgcc /usr/lib/gcc/x86_64-linux-gnu/4.8/crtend.o /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/crtn.o +make[1]: Leaving directory `/home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/CMakeTmp' + + +Parsed CXX implicit link information from above output: + link line regex: [^( *|.*[/\])(ld|([^/\]+-)?ld|collect2)[^/\]*( |$)] + ignore line: [Change Dir: /home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/CMakeTmp] + ignore line: [] + ignore line: [Run Build Command:/usr/bin/make "cmTryCompileExec2573420878/fast"] + ignore line: [/usr/bin/make -f CMakeFiles/cmTryCompileExec2573420878.dir/build.make CMakeFiles/cmTryCompileExec2573420878.dir/build] + ignore line: [make[1]: Entering directory `/home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/CMakeTmp'] + ignore line: [/usr/bin/cmake -E cmake_progress_report /home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/CMakeTmp/CMakeFiles 1] + ignore line: [Building CXX object CMakeFiles/cmTryCompileExec2573420878.dir/CMakeCXXCompilerABI.cpp.o] + ignore line: [/usr/bin/c++ -o CMakeFiles/cmTryCompileExec2573420878.dir/CMakeCXXCompilerABI.cpp.o -c /usr/share/cmake-2.8/Modules/CMakeCXXCompilerABI.cpp] + ignore line: [Linking CXX executable cmTryCompileExec2573420878] + ignore line: [/usr/bin/cmake -E cmake_link_script CMakeFiles/cmTryCompileExec2573420878.dir/link.txt --verbose=1] + ignore line: [/usr/bin/c++ -v CMakeFiles/cmTryCompileExec2573420878.dir/CMakeCXXCompilerABI.cpp.o -o cmTryCompileExec2573420878 -rdynamic ] + ignore line: [Using built-in specs.] + ignore line: [COLLECT_GCC=/usr/bin/c++] + ignore line: [COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/4.8/lto-wrapper] + ignore line: [Target: x86_64-linux-gnu] + ignore line: [Configured with: ../src/configure -v --with-pkgversion='Ubuntu 4.8.4-2ubuntu1~14.04' --with-bugurl=file:///usr/share/doc/gcc-4.8/README.Bugs --enable-languages=c,c++,java,go,d,fortran,objc,obj-c++ --prefix=/usr --program-suffix=-4.8 --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --with-gxx-include-dir=/usr/include/c++/4.8 --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --enable-gnu-unique-object --disable-libmudflap --enable-plugin --with-system-zlib --disable-browser-plugin --enable-java-awt=gtk --enable-gtk-cairo --with-java-home=/usr/lib/jvm/java-1.5.0-gcj-4.8-amd64/jre --enable-java-home --with-jvm-root-dir=/usr/lib/jvm/java-1.5.0-gcj-4.8-amd64 --with-jvm-jar-dir=/usr/lib/jvm-exports/java-1.5.0-gcj-4.8-amd64 --with-arch-directory=amd64 --with-ecj-jar=/usr/share/java/eclipse-ecj.jar --enable-objc-gc --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --with-tune=generic --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu] + ignore line: [Thread model: posix] + ignore line: [gcc version 4.8.4 (Ubuntu 4.8.4-2ubuntu1~14.04) ] + ignore line: [COMPILER_PATH=/usr/lib/gcc/x86_64-linux-gnu/4.8/:/usr/lib/gcc/x86_64-linux-gnu/4.8/:/usr/lib/gcc/x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/4.8/:/usr/lib/gcc/x86_64-linux-gnu/] + ignore line: [LIBRARY_PATH=/usr/lib/gcc/x86_64-linux-gnu/4.8/:/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../lib/:/lib/x86_64-linux-gnu/:/lib/../lib/:/usr/lib/x86_64-linux-gnu/:/usr/lib/../lib/:/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../:/lib/:/usr/lib/] + ignore line: [COLLECT_GCC_OPTIONS='-v' '-o' 'cmTryCompileExec2573420878' '-rdynamic' '-shared-libgcc' '-mtune=generic' '-march=x86-64'] + link line: [ /usr/lib/gcc/x86_64-linux-gnu/4.8/collect2 --sysroot=/ --build-id --eh-frame-hdr -m elf_x86_64 --hash-style=gnu --as-needed -export-dynamic -dynamic-linker /lib64/ld-linux-x86-64.so.2 -z relro -o cmTryCompileExec2573420878 /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/crt1.o /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/crti.o /usr/lib/gcc/x86_64-linux-gnu/4.8/crtbegin.o -L/usr/lib/gcc/x86_64-linux-gnu/4.8 -L/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu -L/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../lib -L/lib/x86_64-linux-gnu -L/lib/../lib -L/usr/lib/x86_64-linux-gnu -L/usr/lib/../lib -L/usr/lib/gcc/x86_64-linux-gnu/4.8/../../.. CMakeFiles/cmTryCompileExec2573420878.dir/CMakeCXXCompilerABI.cpp.o -lstdc++ -lm -lgcc_s -lgcc -lc -lgcc_s -lgcc /usr/lib/gcc/x86_64-linux-gnu/4.8/crtend.o /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/crtn.o] + arg [/usr/lib/gcc/x86_64-linux-gnu/4.8/collect2] ==> ignore + arg [--sysroot=/] ==> ignore + arg [--build-id] ==> ignore + arg [--eh-frame-hdr] ==> ignore + arg [-m] ==> ignore + arg [elf_x86_64] ==> ignore + arg [--hash-style=gnu] ==> ignore + arg [--as-needed] ==> ignore + arg [-export-dynamic] ==> ignore + arg [-dynamic-linker] ==> ignore + arg [/lib64/ld-linux-x86-64.so.2] ==> ignore + arg [-zrelro] ==> ignore + arg [-o] ==> ignore + arg [cmTryCompileExec2573420878] ==> ignore + arg [/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/crt1.o] ==> ignore + arg [/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/crti.o] ==> ignore + arg [/usr/lib/gcc/x86_64-linux-gnu/4.8/crtbegin.o] ==> ignore + arg [-L/usr/lib/gcc/x86_64-linux-gnu/4.8] ==> dir [/usr/lib/gcc/x86_64-linux-gnu/4.8] + arg [-L/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu] ==> dir [/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu] + arg [-L/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../lib] ==> dir [/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../lib] + arg [-L/lib/x86_64-linux-gnu] ==> dir [/lib/x86_64-linux-gnu] + arg [-L/lib/../lib] ==> dir [/lib/../lib] + arg [-L/usr/lib/x86_64-linux-gnu] ==> dir [/usr/lib/x86_64-linux-gnu] + arg [-L/usr/lib/../lib] ==> dir [/usr/lib/../lib] + arg [-L/usr/lib/gcc/x86_64-linux-gnu/4.8/../../..] ==> dir [/usr/lib/gcc/x86_64-linux-gnu/4.8/../../..] + arg [CMakeFiles/cmTryCompileExec2573420878.dir/CMakeCXXCompilerABI.cpp.o] ==> ignore + arg [-lstdc++] ==> lib [stdc++] + arg [-lm] ==> lib [m] + arg [-lgcc_s] ==> lib [gcc_s] + arg [-lgcc] ==> lib [gcc] + arg [-lc] ==> lib [c] + arg [-lgcc_s] ==> lib [gcc_s] + arg [-lgcc] ==> lib [gcc] + arg [/usr/lib/gcc/x86_64-linux-gnu/4.8/crtend.o] ==> ignore + arg [/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/crtn.o] ==> ignore + remove lib [gcc_s] + remove lib [gcc] + remove lib [gcc_s] + remove lib [gcc] + collapse library dir [/usr/lib/gcc/x86_64-linux-gnu/4.8] ==> [/usr/lib/gcc/x86_64-linux-gnu/4.8] + collapse library dir [/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu] ==> [/usr/lib/x86_64-linux-gnu] + collapse library dir [/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../lib] ==> [/usr/lib] + collapse library dir [/lib/x86_64-linux-gnu] ==> [/lib/x86_64-linux-gnu] + collapse library dir [/lib/../lib] ==> [/lib] + collapse library dir [/usr/lib/x86_64-linux-gnu] ==> [/usr/lib/x86_64-linux-gnu] + collapse library dir [/usr/lib/../lib] ==> [/usr/lib] + collapse library dir [/usr/lib/gcc/x86_64-linux-gnu/4.8/../../..] ==> [/usr/lib] + implicit libs: [stdc++;m;c] + implicit dirs: [/usr/lib/gcc/x86_64-linux-gnu/4.8;/usr/lib/x86_64-linux-gnu;/usr/lib;/lib/x86_64-linux-gnu;/lib] + implicit fwks: [] + + diff --git a/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/Makefile.cmake b/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/Makefile.cmake new file mode 100644 index 0000000000..119272f1f1 --- /dev/null +++ b/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/Makefile.cmake @@ -0,0 +1,43 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 2.8 + +# The generator used is: +SET(CMAKE_DEPENDS_GENERATOR "Unix Makefiles") + +# The top level Makefile was generated from the following files: +SET(CMAKE_MAKEFILE_DEPENDS + "CMakeCache.txt" + "../CMakeLists.txt" + "CMakeFiles/2.8.12.2/CMakeCCompiler.cmake" + "CMakeFiles/2.8.12.2/CMakeCXXCompiler.cmake" + "CMakeFiles/2.8.12.2/CMakeSystem.cmake" + "/usr/share/cmake-2.8/Modules/CMakeCInformation.cmake" + "/usr/share/cmake-2.8/Modules/CMakeCXXInformation.cmake" + "/usr/share/cmake-2.8/Modules/CMakeCommonLanguageInclude.cmake" + "/usr/share/cmake-2.8/Modules/CMakeGenericSystem.cmake" + "/usr/share/cmake-2.8/Modules/CMakeSystemSpecificInformation.cmake" + "/usr/share/cmake-2.8/Modules/Compiler/GNU-C.cmake" + "/usr/share/cmake-2.8/Modules/Compiler/GNU-CXX.cmake" + "/usr/share/cmake-2.8/Modules/Compiler/GNU.cmake" + "/usr/share/cmake-2.8/Modules/Platform/Linux-GNU-C.cmake" + "/usr/share/cmake-2.8/Modules/Platform/Linux-GNU-CXX.cmake" + "/usr/share/cmake-2.8/Modules/Platform/Linux-GNU.cmake" + "/usr/share/cmake-2.8/Modules/Platform/Linux.cmake" + "/usr/share/cmake-2.8/Modules/Platform/UnixPaths.cmake" + ) + +# The corresponding makefile is: +SET(CMAKE_MAKEFILE_OUTPUTS + "Makefile" + "CMakeFiles/cmake.check_cache" + ) + +# Byproducts of CMake generate step: +SET(CMAKE_MAKEFILE_PRODUCTS + "CMakeFiles/CMakeDirectoryInformation.cmake" + ) + +# Dependency information for all targets: +SET(CMAKE_DEPEND_INFO_FILES + "CMakeFiles/Si5351C.dir/DependInfo.cmake" + ) diff --git a/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/Makefile2 b/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/Makefile2 new file mode 100644 index 0000000000..16016a9bd2 --- /dev/null +++ b/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/Makefile2 @@ -0,0 +1,102 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 2.8 + +# Default target executed when no arguments are given to make. +default_target: all +.PHONY : default_target + +# The main recursive all target +all: +.PHONY : all + +# The main recursive preinstall target +preinstall: +.PHONY : preinstall + +#============================================================================= +# Special targets provided by cmake. + +# Disable implicit rules so canonical targets will work. +.SUFFIXES: + +# Remove some rules from gmake that .SUFFIXES does not remove. +SUFFIXES = + +.SUFFIXES: .hpux_make_needs_suffix_list + +# Suppress display of executed commands. +$(VERBOSE).SILENT: + +# A target that is always out of date. +cmake_force: +.PHONY : cmake_force + +#============================================================================= +# Set environment variables for the build. + +# The shell in which to execute make rules. +SHELL = /bin/sh + +# The CMake executable. +CMAKE_COMMAND = /usr/bin/cmake + +# The command to remove a file. +RM = /usr/bin/cmake -E remove -f + +# Escaping for special characters. +EQUALS = = + +# The program to use to edit the cache. +CMAKE_EDIT_COMMAND = /usr/bin/ccmake + +# The top-level source directory on which CMake was run. +CMAKE_SOURCE_DIR = /home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C + +# The top-level build directory on which CMake was run. +CMAKE_BINARY_DIR = /home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build + +#============================================================================= +# Target rules for target CMakeFiles/Si5351C.dir + +# All Build rule for target. +CMakeFiles/Si5351C.dir/all: + $(MAKE) -f CMakeFiles/Si5351C.dir/build.make CMakeFiles/Si5351C.dir/depend + $(MAKE) -f CMakeFiles/Si5351C.dir/build.make CMakeFiles/Si5351C.dir/build + $(CMAKE_COMMAND) -E cmake_progress_report /home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles 1 + @echo "Built target Si5351C" +.PHONY : CMakeFiles/Si5351C.dir/all + +# Include target in all. +all: CMakeFiles/Si5351C.dir/all +.PHONY : all + +# Build rule for subdir invocation for target. +CMakeFiles/Si5351C.dir/rule: cmake_check_build_system + $(CMAKE_COMMAND) -E cmake_progress_start /home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles 1 + $(MAKE) -f CMakeFiles/Makefile2 CMakeFiles/Si5351C.dir/all + $(CMAKE_COMMAND) -E cmake_progress_start /home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles 0 +.PHONY : CMakeFiles/Si5351C.dir/rule + +# Convenience name for target. +Si5351C: CMakeFiles/Si5351C.dir/rule +.PHONY : Si5351C + +# clean rule for target. +CMakeFiles/Si5351C.dir/clean: + $(MAKE) -f CMakeFiles/Si5351C.dir/build.make CMakeFiles/Si5351C.dir/clean +.PHONY : CMakeFiles/Si5351C.dir/clean + +# clean rule for target. +clean: CMakeFiles/Si5351C.dir/clean +.PHONY : clean + +#============================================================================= +# Special targets to cleanup operation of make. + +# Special rule to run CMake to check the build system integrity. +# No rule that depends on this can have commands that come from listfiles +# because they might be regenerated. +cmake_check_build_system: + $(CMAKE_COMMAND) -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 0 +.PHONY : cmake_check_build_system + diff --git a/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/Si5351C.dir/CXX.includecache b/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/Si5351C.dir/CXX.includecache new file mode 100644 index 0000000000..b84d7a1def --- /dev/null +++ b/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/Si5351C.dir/CXX.includecache @@ -0,0 +1,8 @@ +#IncludeRegexLine: ^[ ]*#[ ]*(include|import)[ ]*[<"]([^">]+)([">]) + +#IncludeRegexScan: ^.*$ + +#IncludeRegexComplain: ^$ + +#IncludeRegexTransform: + diff --git a/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/Si5351C.dir/DependInfo.cmake b/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/Si5351C.dir/DependInfo.cmake new file mode 100644 index 0000000000..8fbd267efc --- /dev/null +++ b/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/Si5351C.dir/DependInfo.cmake @@ -0,0 +1,22 @@ +# The set of languages for which implicit dependencies are needed: +SET(CMAKE_DEPENDS_LANGUAGES + "CXX" + ) +# The set of files for implicit dependencies of each language: +SET(CMAKE_DEPENDS_CHECK_CXX + "/home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/Si5351C.cpp" "/home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/Si5351C.dir/Si5351C.o" + ) +SET(CMAKE_CXX_COMPILER_ID "GNU") + +# Targets to which this target links. +SET(CMAKE_TARGET_LINKED_INFO_FILES + ) + +# The include file search paths: +SET(CMAKE_C_TARGET_INCLUDE_PATH + "../../lms7002m" + ".." + ) +SET(CMAKE_CXX_TARGET_INCLUDE_PATH ${CMAKE_C_TARGET_INCLUDE_PATH}) +SET(CMAKE_Fortran_TARGET_INCLUDE_PATH ${CMAKE_C_TARGET_INCLUDE_PATH}) +SET(CMAKE_ASM_TARGET_INCLUDE_PATH ${CMAKE_C_TARGET_INCLUDE_PATH}) diff --git a/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/Si5351C.dir/Si5351C.o b/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/Si5351C.dir/Si5351C.o new file mode 100644 index 0000000000000000000000000000000000000000..9c3483db4eb7c2c2bfd8b4bd29d4f87b7c961757 GIT binary patch literal 144184 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 DuMANa literal 0 HcmV?d00001 diff --git a/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/Si5351C.dir/build.make b/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/Si5351C.dir/build.make new file mode 100644 index 0000000000..55f2ff4765 --- /dev/null +++ b/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/Si5351C.dir/build.make @@ -0,0 +1,106 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 2.8 + +#============================================================================= +# Special targets provided by cmake. + +# Disable implicit rules so canonical targets will work. +.SUFFIXES: + +# Remove some rules from gmake that .SUFFIXES does not remove. +SUFFIXES = + +.SUFFIXES: .hpux_make_needs_suffix_list + +# Suppress display of executed commands. +$(VERBOSE).SILENT: + +# A target that is always out of date. +cmake_force: +.PHONY : cmake_force + +#============================================================================= +# Set environment variables for the build. + +# The shell in which to execute make rules. +SHELL = /bin/sh + +# The CMake executable. +CMAKE_COMMAND = /usr/bin/cmake + +# The command to remove a file. +RM = /usr/bin/cmake -E remove -f + +# Escaping for special characters. +EQUALS = = + +# The program to use to edit the cache. +CMAKE_EDIT_COMMAND = /usr/bin/ccmake + +# The top-level source directory on which CMake was run. +CMAKE_SOURCE_DIR = /home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C + +# The top-level build directory on which CMake was run. +CMAKE_BINARY_DIR = /home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build + +# Include any dependencies generated for this target. +include CMakeFiles/Si5351C.dir/depend.make + +# Include the progress variables for this target. +include CMakeFiles/Si5351C.dir/progress.make + +# Include the compile flags for this target's objects. +include CMakeFiles/Si5351C.dir/flags.make + +CMakeFiles/Si5351C.dir/Si5351C.o: CMakeFiles/Si5351C.dir/flags.make +CMakeFiles/Si5351C.dir/Si5351C.o: ../Si5351C.cpp + $(CMAKE_COMMAND) -E cmake_progress_report /home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles $(CMAKE_PROGRESS_1) + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Building CXX object CMakeFiles/Si5351C.dir/Si5351C.o" + /usr/bin/c++ $(CXX_DEFINES) $(CXX_FLAGS) -o CMakeFiles/Si5351C.dir/Si5351C.o -c /home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/Si5351C.cpp + +CMakeFiles/Si5351C.dir/Si5351C.i: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing CXX source to CMakeFiles/Si5351C.dir/Si5351C.i" + /usr/bin/c++ $(CXX_DEFINES) $(CXX_FLAGS) -E /home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/Si5351C.cpp > CMakeFiles/Si5351C.dir/Si5351C.i + +CMakeFiles/Si5351C.dir/Si5351C.s: cmake_force + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling CXX source to assembly CMakeFiles/Si5351C.dir/Si5351C.s" + /usr/bin/c++ $(CXX_DEFINES) $(CXX_FLAGS) -S /home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/Si5351C.cpp -o CMakeFiles/Si5351C.dir/Si5351C.s + +CMakeFiles/Si5351C.dir/Si5351C.o.requires: +.PHONY : CMakeFiles/Si5351C.dir/Si5351C.o.requires + +CMakeFiles/Si5351C.dir/Si5351C.o.provides: CMakeFiles/Si5351C.dir/Si5351C.o.requires + $(MAKE) -f CMakeFiles/Si5351C.dir/build.make CMakeFiles/Si5351C.dir/Si5351C.o.provides.build +.PHONY : CMakeFiles/Si5351C.dir/Si5351C.o.provides + +CMakeFiles/Si5351C.dir/Si5351C.o.provides.build: CMakeFiles/Si5351C.dir/Si5351C.o + +# Object files for target Si5351C +Si5351C_OBJECTS = \ +"CMakeFiles/Si5351C.dir/Si5351C.o" + +# External object files for target Si5351C +Si5351C_EXTERNAL_OBJECTS = + +libSi5351C.a: CMakeFiles/Si5351C.dir/Si5351C.o +libSi5351C.a: CMakeFiles/Si5351C.dir/build.make +libSi5351C.a: CMakeFiles/Si5351C.dir/link.txt + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --red --bold "Linking CXX static library libSi5351C.a" + $(CMAKE_COMMAND) -P CMakeFiles/Si5351C.dir/cmake_clean_target.cmake + $(CMAKE_COMMAND) -E cmake_link_script CMakeFiles/Si5351C.dir/link.txt --verbose=$(VERBOSE) + +# Rule to build all files generated by this target. +CMakeFiles/Si5351C.dir/build: libSi5351C.a +.PHONY : CMakeFiles/Si5351C.dir/build + +CMakeFiles/Si5351C.dir/requires: CMakeFiles/Si5351C.dir/Si5351C.o.requires +.PHONY : CMakeFiles/Si5351C.dir/requires + +CMakeFiles/Si5351C.dir/clean: + $(CMAKE_COMMAND) -P CMakeFiles/Si5351C.dir/cmake_clean.cmake +.PHONY : CMakeFiles/Si5351C.dir/clean + +CMakeFiles/Si5351C.dir/depend: + cd /home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build && $(CMAKE_COMMAND) -E cmake_depends "Unix Makefiles" /home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C /home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C /home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build /home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build /home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/Si5351C.dir/DependInfo.cmake --color=$(COLOR) +.PHONY : CMakeFiles/Si5351C.dir/depend + diff --git a/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/Si5351C.dir/cmake_clean.cmake b/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/Si5351C.dir/cmake_clean.cmake new file mode 100644 index 0000000000..e300fd2668 --- /dev/null +++ b/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/Si5351C.dir/cmake_clean.cmake @@ -0,0 +1,10 @@ +FILE(REMOVE_RECURSE + "CMakeFiles/Si5351C.dir/Si5351C.o" + "libSi5351C.pdb" + "libSi5351C.a" +) + +# Per-language clean rules from dependency scanning. +FOREACH(lang CXX) + INCLUDE(CMakeFiles/Si5351C.dir/cmake_clean_${lang}.cmake OPTIONAL) +ENDFOREACH(lang) diff --git a/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/Si5351C.dir/cmake_clean_target.cmake b/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/Si5351C.dir/cmake_clean_target.cmake new file mode 100644 index 0000000000..bb2fb4b00e --- /dev/null +++ b/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/Si5351C.dir/cmake_clean_target.cmake @@ -0,0 +1,3 @@ +FILE(REMOVE_RECURSE + "libSi5351C.a" +) diff --git a/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/Si5351C.dir/depend.internal b/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/Si5351C.dir/depend.internal new file mode 100644 index 0000000000..2b377e7bc4 --- /dev/null +++ b/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/Si5351C.dir/depend.internal @@ -0,0 +1,6 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 2.8 + +CMakeFiles/Si5351C.dir/Si5351C.o + /home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/Si5351C.cpp + /home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/Si5351C.h diff --git a/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/Si5351C.dir/depend.make b/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/Si5351C.dir/depend.make new file mode 100644 index 0000000000..f55fdb2688 --- /dev/null +++ b/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/Si5351C.dir/depend.make @@ -0,0 +1,6 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 2.8 + +CMakeFiles/Si5351C.dir/Si5351C.o: ../Si5351C.cpp +CMakeFiles/Si5351C.dir/Si5351C.o: ../Si5351C.h + diff --git a/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/Si5351C.dir/flags.make b/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/Si5351C.dir/flags.make new file mode 100644 index 0000000000..3515e5e131 --- /dev/null +++ b/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/Si5351C.dir/flags.make @@ -0,0 +1,8 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 2.8 + +# compile CXX with /usr/bin/c++ +CXX_FLAGS = -std=c++11 -I/home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/../lms7002m -I/home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C + +CXX_DEFINES = + diff --git a/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/Si5351C.dir/link.txt b/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/Si5351C.dir/link.txt new file mode 100644 index 0000000000..000b6e0ee0 --- /dev/null +++ b/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/Si5351C.dir/link.txt @@ -0,0 +1,2 @@ +/usr/bin/ar cr libSi5351C.a CMakeFiles/Si5351C.dir/Si5351C.o +/usr/bin/ranlib libSi5351C.a diff --git a/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/Si5351C.dir/progress.make b/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/Si5351C.dir/progress.make new file mode 100644 index 0000000000..781c7de277 --- /dev/null +++ b/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/Si5351C.dir/progress.make @@ -0,0 +1,2 @@ +CMAKE_PROGRESS_1 = 1 + diff --git a/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/TargetDirectories.txt b/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/TargetDirectories.txt new file mode 100644 index 0000000000..8bed4f4e60 --- /dev/null +++ b/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/TargetDirectories.txt @@ -0,0 +1 @@ +/home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/Si5351C.dir diff --git a/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/cmake.check_cache b/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/cmake.check_cache new file mode 100644 index 0000000000..3dccd73172 --- /dev/null +++ b/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/cmake.check_cache @@ -0,0 +1 @@ +# This file is generated by cmake for dependency checking of the CMakeCache.txt file diff --git a/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/progress.marks b/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/progress.marks new file mode 100644 index 0000000000..d00491fd7e --- /dev/null +++ b/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/progress.marks @@ -0,0 +1 @@ +1 diff --git a/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/Makefile b/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/Makefile new file mode 100644 index 0000000000..45a34a03b1 --- /dev/null +++ b/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/Makefile @@ -0,0 +1,157 @@ +# CMAKE generated file: DO NOT EDIT! +# Generated by "Unix Makefiles" Generator, CMake Version 2.8 + +# Default target executed when no arguments are given to make. +default_target: all +.PHONY : default_target + +#============================================================================= +# Special targets provided by cmake. + +# Disable implicit rules so canonical targets will work. +.SUFFIXES: + +# Remove some rules from gmake that .SUFFIXES does not remove. +SUFFIXES = + +.SUFFIXES: .hpux_make_needs_suffix_list + +# Suppress display of executed commands. +$(VERBOSE).SILENT: + +# A target that is always out of date. +cmake_force: +.PHONY : cmake_force + +#============================================================================= +# Set environment variables for the build. + +# The shell in which to execute make rules. +SHELL = /bin/sh + +# The CMake executable. +CMAKE_COMMAND = /usr/bin/cmake + +# The command to remove a file. +RM = /usr/bin/cmake -E remove -f + +# Escaping for special characters. +EQUALS = = + +# The program to use to edit the cache. +CMAKE_EDIT_COMMAND = /usr/bin/ccmake + +# The top-level source directory on which CMake was run. +CMAKE_SOURCE_DIR = /home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C + +# The top-level build directory on which CMake was run. +CMAKE_BINARY_DIR = /home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build + +#============================================================================= +# Targets provided globally by CMake. + +# Special rule for the target edit_cache +edit_cache: + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Running CMake cache editor..." + /usr/bin/ccmake -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) +.PHONY : edit_cache + +# Special rule for the target edit_cache +edit_cache/fast: edit_cache +.PHONY : edit_cache/fast + +# Special rule for the target rebuild_cache +rebuild_cache: + @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Running CMake to regenerate build system..." + /usr/bin/cmake -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) +.PHONY : rebuild_cache + +# Special rule for the target rebuild_cache +rebuild_cache/fast: rebuild_cache +.PHONY : rebuild_cache/fast + +# The main all target +all: cmake_check_build_system + $(CMAKE_COMMAND) -E cmake_progress_start /home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles /home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/progress.marks + $(MAKE) -f CMakeFiles/Makefile2 all + $(CMAKE_COMMAND) -E cmake_progress_start /home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles 0 +.PHONY : all + +# The main clean target +clean: + $(MAKE) -f CMakeFiles/Makefile2 clean +.PHONY : clean + +# The main clean target +clean/fast: clean +.PHONY : clean/fast + +# Prepare targets for installation. +preinstall: all + $(MAKE) -f CMakeFiles/Makefile2 preinstall +.PHONY : preinstall + +# Prepare targets for installation. +preinstall/fast: + $(MAKE) -f CMakeFiles/Makefile2 preinstall +.PHONY : preinstall/fast + +# clear depends +depend: + $(CMAKE_COMMAND) -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 1 +.PHONY : depend + +#============================================================================= +# Target rules for targets named Si5351C + +# Build rule for target. +Si5351C: cmake_check_build_system + $(MAKE) -f CMakeFiles/Makefile2 Si5351C +.PHONY : Si5351C + +# fast build rule for target. +Si5351C/fast: + $(MAKE) -f CMakeFiles/Si5351C.dir/build.make CMakeFiles/Si5351C.dir/build +.PHONY : Si5351C/fast + +# target to build an object file +Si5351C.o: + $(MAKE) -f CMakeFiles/Si5351C.dir/build.make CMakeFiles/Si5351C.dir/Si5351C.o +.PHONY : Si5351C.o + +# target to preprocess a source file +Si5351C.i: + $(MAKE) -f CMakeFiles/Si5351C.dir/build.make CMakeFiles/Si5351C.dir/Si5351C.i +.PHONY : Si5351C.i + +# target to generate assembly for a file +Si5351C.s: + $(MAKE) -f CMakeFiles/Si5351C.dir/build.make CMakeFiles/Si5351C.dir/Si5351C.s +.PHONY : Si5351C.s + +# Help Target +help: + @echo "The following are some of the valid targets for this Makefile:" + @echo "... all (the default if no target is provided)" + @echo "... clean" + @echo "... depend" + @echo "... Si5351C" + @echo "... edit_cache" + @echo "... rebuild_cache" + @echo "... Si5351C.o" + @echo "... Si5351C.i" + @echo "... Si5351C.s" +.PHONY : help + + + +#============================================================================= +# Special targets to cleanup operation of make. + +# Special rule to run CMake to check the build system integrity. +# No rule that depends on this can have commands that come from listfiles +# because they might be regenerated. +cmake_check_build_system: + $(CMAKE_COMMAND) -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 0 +.PHONY : cmake_check_build_system + diff --git a/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/cmake_install.cmake b/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/cmake_install.cmake new file mode 100644 index 0000000000..d7797d84e9 --- /dev/null +++ b/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/cmake_install.cmake @@ -0,0 +1,44 @@ +# Install script for directory: /home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C + +# Set the install prefix +IF(NOT DEFINED CMAKE_INSTALL_PREFIX) + SET(CMAKE_INSTALL_PREFIX "/usr/local") +ENDIF(NOT DEFINED CMAKE_INSTALL_PREFIX) +STRING(REGEX REPLACE "/$" "" CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}") + +# Set the install configuration name. +IF(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME) + IF(BUILD_TYPE) + STRING(REGEX REPLACE "^[^A-Za-z0-9_]+" "" + CMAKE_INSTALL_CONFIG_NAME "${BUILD_TYPE}") + ELSE(BUILD_TYPE) + SET(CMAKE_INSTALL_CONFIG_NAME "") + ENDIF(BUILD_TYPE) + MESSAGE(STATUS "Install configuration: \"${CMAKE_INSTALL_CONFIG_NAME}\"") +ENDIF(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME) + +# Set the component getting installed. +IF(NOT CMAKE_INSTALL_COMPONENT) + IF(COMPONENT) + MESSAGE(STATUS "Install component: \"${COMPONENT}\"") + SET(CMAKE_INSTALL_COMPONENT "${COMPONENT}") + ELSE(COMPONENT) + SET(CMAKE_INSTALL_COMPONENT) + ENDIF(COMPONENT) +ENDIF(NOT CMAKE_INSTALL_COMPONENT) + +# Install shared libraries without execute permission? +IF(NOT DEFINED CMAKE_INSTALL_SO_NO_EXE) + SET(CMAKE_INSTALL_SO_NO_EXE "1") +ENDIF(NOT DEFINED CMAKE_INSTALL_SO_NO_EXE) + +IF(CMAKE_INSTALL_COMPONENT) + SET(CMAKE_INSTALL_MANIFEST "install_manifest_${CMAKE_INSTALL_COMPONENT}.txt") +ELSE(CMAKE_INSTALL_COMPONENT) + SET(CMAKE_INSTALL_MANIFEST "install_manifest.txt") +ENDIF(CMAKE_INSTALL_COMPONENT) + +FILE(WRITE "/home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/${CMAKE_INSTALL_MANIFEST}" "") +FOREACH(file ${CMAKE_INSTALL_MANIFEST_FILES}) + FILE(APPEND "/home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/${CMAKE_INSTALL_MANIFEST}" "${file}\n") +ENDFOREACH(file) diff --git a/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/libSi5351C.a b/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/libSi5351C.a new file mode 100644 index 0000000000000000000000000000000000000000..bc5d760e0aedfec3c12ab319e446c9ce801c5bcc GIT binary patch literal 162342 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.samples_per_tti>>1; else len = phy_vars_eNB->lte_frame_parms.samples_per_tti; - + /* for (i=0;irx_total_gain_dB;//-USRP_GAIN_OFFSET; - +#if 0 switch(UE->lte_frame_parms.N_RB_DL) { case 6: openair0_cfg[card].rx_gain[i] -= 12; @@ -555,7 +555,7 @@ static void *UE_thread_synch(void *arg) printf("Unknown number of RBs %d\n",UE->lte_frame_parms.N_RB_DL); break; } - +#endif #endif } } From 98a05dfbb816cc6d2346a3fec408c865f5780557 Mon Sep 17 00:00:00 2001 From: kaltenbe Date: Thu, 11 Feb 2016 10:13:43 +0100 Subject: [PATCH 226/263] deleted unnecessary files and added lmsSDR, lms7002m directories --- .../LIB/Si5351C/build/CMakeCache.txt | 326 -- .../CMakeFiles/2.8.12.2/CMakeCCompiler.cmake | 56 - .../2.8.12.2/CMakeCXXCompiler.cmake | 57 - .../2.8.12.2/CMakeDetermineCompilerABI_C.bin | Bin 8587 -> 0 bytes .../CMakeDetermineCompilerABI_CXX.bin | Bin 8600 -> 0 bytes .../CMakeFiles/2.8.12.2/CMakeSystem.cmake | 15 - .../2.8.12.2/CompilerIdC/CMakeCCompilerId.c | 389 --- .../CMakeFiles/2.8.12.2/CompilerIdC/a.out | Bin 8683 -> 0 bytes .../CompilerIdCXX/CMakeCXXCompilerId.cpp | 377 --- .../CMakeFiles/2.8.12.2/CompilerIdCXX/a.out | Bin 8692 -> 0 bytes .../CMakeDirectoryInformation.cmake | 16 - .../Si5351C/build/CMakeFiles/CMakeOutput.log | 263 -- .../Si5351C/build/CMakeFiles/Makefile.cmake | 43 - .../LIB/Si5351C/build/CMakeFiles/Makefile2 | 102 - .../CMakeFiles/Si5351C.dir/CXX.includecache | 8 - .../CMakeFiles/Si5351C.dir/DependInfo.cmake | 22 - .../build/CMakeFiles/Si5351C.dir/Si5351C.o | Bin 144184 -> 0 bytes .../build/CMakeFiles/Si5351C.dir/build.make | 106 - .../CMakeFiles/Si5351C.dir/cmake_clean.cmake | 10 - .../Si5351C.dir/cmake_clean_target.cmake | 3 - .../CMakeFiles/Si5351C.dir/depend.internal | 6 - .../build/CMakeFiles/Si5351C.dir/depend.make | 6 - .../build/CMakeFiles/Si5351C.dir/flags.make | 8 - .../build/CMakeFiles/Si5351C.dir/link.txt | 2 - .../CMakeFiles/Si5351C.dir/progress.make | 2 - .../build/CMakeFiles/TargetDirectories.txt | 1 - .../build/CMakeFiles/cmake.check_cache | 1 - .../Si5351C/build/CMakeFiles/progress.marks | 1 - .../USERSPACE/LIB/Si5351C/build/Makefile | 157 - .../LIB/Si5351C/build/cmake_install.cmake | 44 - .../USERSPACE/LIB/Si5351C/build/libSi5351C.a | Bin 162342 -> 0 bytes .../USERSPACE/LIB/lms7002m/CMakeLists.txt | 63 + .../USERSPACE/LIB/lms7002m/LMS7002M.cpp | 2612 +++++++++++++++++ .../LMSSDR/USERSPACE/LIB/lms7002m/LMS7002M.h | 177 ++ .../LIB/lms7002m/LMS7002M_RegistersMap.cpp | 68 + .../LIB/lms7002m/LMS7002M_RegistersMap.h | 35 + .../lms7002m/LMS7002M_filtersCalibration.cpp | 861 ++++++ .../LIB/lms7002m/LMS7002M_parameters.cpp | 601 ++++ .../LIB/lms7002m/LMS7002M_parameters.h | 613 ++++ .../LIB/lms7002m/LMS7002M_statuses.cpp | 16 + .../LIB/lms7002m/LMS7002M_statuses.h | 48 + .../connectionManager/ConnectionCOM.cpp | 596 ++++ .../connectionManager/ConnectionCOM.h | 62 + .../connectionManager/ConnectionManager.cpp | 314 ++ .../connectionManager/ConnectionManager.h | 60 + .../connectionManager/ConnectionSPI.cpp | 290 ++ .../connectionManager/ConnectionSPI.h | 41 + .../connectionManager/ConnectionUSB.cpp | 762 +++++ .../connectionManager/ConnectionUSB.h | 144 + .../lms7002m/connectionManager/IConnection.h | 68 + .../USERSPACE/LIB/lms7002m/lms7002_defines.h | 218 ++ .../USERSPACE/LIB/lms7002m/lmsComms.cpp | 326 ++ .../LMSSDR/USERSPACE/LIB/lms7002m/lmsComms.h | 111 + .../LMSSDR/USERSPACE/LIB/lms7002m/typedefs.h | 18 + .../LMSSDR/USERSPACE/LIB/lmsSDR/LMS_SDR.cpp | 334 +++ .../LMSSDR/USERSPACE/LIB/lmsSDR/LMS_SDR.h | 143 + .../LIB/lmsSDR/LMS_StreamBoard/CMakeLists.txt | 22 + .../LMS_StreamBoard/LMS_StreamBoard.cpp | 770 +++++ .../lmsSDR/LMS_StreamBoard/LMS_StreamBoard.h | 107 + .../LMS_StreamBoard/LMS_StreamBoard_FIFO.h | 122 + .../lmsSDR/LMS_StreamBoard/lms7002_defines.h | 215 ++ .../lmsSDR/connectionManager/CMakeLists.txt | 34 + .../connectionManager/ConnectionCOM.cpp | 596 ++++ .../lmsSDR/connectionManager/ConnectionCOM.h | 62 + .../connectionManager/ConnectionManager.cpp | 319 ++ .../connectionManager/ConnectionManager.h | 60 + .../connectionManager/ConnectionSPI.cpp | 313 ++ .../lmsSDR/connectionManager/ConnectionSPI.h | 41 + .../connectionManager/ConnectionUSB.cpp | 771 +++++ .../lmsSDR/connectionManager/ConnectionUSB.h | 144 + .../lmsSDR/connectionManager/IConnection.h | 68 + .../LIB/lmsSDR/connectionManager/lmsComms.cpp | 325 ++ .../LIB/lmsSDR/connectionManager/lmsComms.h | 111 + .../LMSSDR/USERSPACE/LIB/lmsSDR/dataTypes.h | 33 + .../ARCH/LMSSDR/USERSPACE/LIB/lmsSDR/fifo.h | 180 ++ .../LMSSDR/USERSPACE/LIB/lmsSDR/ringBuffer.h | 143 + targets/ARCH/LMSSDR/USERSPACE/LIB/lms_lib.cpp | 862 ++++++ 77 files changed, 13879 insertions(+), 2021 deletions(-) delete mode 100644 targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeCache.txt delete mode 100644 targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/2.8.12.2/CMakeCCompiler.cmake delete mode 100644 targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/2.8.12.2/CMakeCXXCompiler.cmake delete mode 100755 targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/2.8.12.2/CMakeDetermineCompilerABI_C.bin delete mode 100755 targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/2.8.12.2/CMakeDetermineCompilerABI_CXX.bin delete mode 100644 targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/2.8.12.2/CMakeSystem.cmake delete mode 100644 targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/2.8.12.2/CompilerIdC/CMakeCCompilerId.c delete mode 100755 targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/2.8.12.2/CompilerIdC/a.out delete mode 100644 targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/2.8.12.2/CompilerIdCXX/CMakeCXXCompilerId.cpp delete mode 100755 targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/2.8.12.2/CompilerIdCXX/a.out delete mode 100644 targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/CMakeDirectoryInformation.cmake delete mode 100644 targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/CMakeOutput.log delete mode 100644 targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/Makefile.cmake delete mode 100644 targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/Makefile2 delete mode 100644 targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/Si5351C.dir/CXX.includecache delete mode 100644 targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/Si5351C.dir/DependInfo.cmake delete mode 100644 targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/Si5351C.dir/Si5351C.o delete mode 100644 targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/Si5351C.dir/build.make delete mode 100644 targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/Si5351C.dir/cmake_clean.cmake delete mode 100644 targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/Si5351C.dir/cmake_clean_target.cmake delete mode 100644 targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/Si5351C.dir/depend.internal delete mode 100644 targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/Si5351C.dir/depend.make delete mode 100644 targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/Si5351C.dir/flags.make delete mode 100644 targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/Si5351C.dir/link.txt delete mode 100644 targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/Si5351C.dir/progress.make delete mode 100644 targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/TargetDirectories.txt delete mode 100644 targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/cmake.check_cache delete mode 100644 targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/progress.marks delete mode 100644 targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/Makefile delete mode 100644 targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/cmake_install.cmake delete mode 100644 targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/libSi5351C.a create mode 100644 targets/ARCH/LMSSDR/USERSPACE/LIB/lms7002m/CMakeLists.txt create mode 100644 targets/ARCH/LMSSDR/USERSPACE/LIB/lms7002m/LMS7002M.cpp create mode 100644 targets/ARCH/LMSSDR/USERSPACE/LIB/lms7002m/LMS7002M.h create mode 100644 targets/ARCH/LMSSDR/USERSPACE/LIB/lms7002m/LMS7002M_RegistersMap.cpp create mode 100644 targets/ARCH/LMSSDR/USERSPACE/LIB/lms7002m/LMS7002M_RegistersMap.h create mode 100644 targets/ARCH/LMSSDR/USERSPACE/LIB/lms7002m/LMS7002M_filtersCalibration.cpp create mode 100644 targets/ARCH/LMSSDR/USERSPACE/LIB/lms7002m/LMS7002M_parameters.cpp create mode 100644 targets/ARCH/LMSSDR/USERSPACE/LIB/lms7002m/LMS7002M_parameters.h create mode 100644 targets/ARCH/LMSSDR/USERSPACE/LIB/lms7002m/LMS7002M_statuses.cpp create mode 100644 targets/ARCH/LMSSDR/USERSPACE/LIB/lms7002m/LMS7002M_statuses.h create mode 100644 targets/ARCH/LMSSDR/USERSPACE/LIB/lms7002m/connectionManager/ConnectionCOM.cpp create mode 100644 targets/ARCH/LMSSDR/USERSPACE/LIB/lms7002m/connectionManager/ConnectionCOM.h create mode 100644 targets/ARCH/LMSSDR/USERSPACE/LIB/lms7002m/connectionManager/ConnectionManager.cpp create mode 100644 targets/ARCH/LMSSDR/USERSPACE/LIB/lms7002m/connectionManager/ConnectionManager.h create mode 100644 targets/ARCH/LMSSDR/USERSPACE/LIB/lms7002m/connectionManager/ConnectionSPI.cpp create mode 100644 targets/ARCH/LMSSDR/USERSPACE/LIB/lms7002m/connectionManager/ConnectionSPI.h create mode 100644 targets/ARCH/LMSSDR/USERSPACE/LIB/lms7002m/connectionManager/ConnectionUSB.cpp create mode 100644 targets/ARCH/LMSSDR/USERSPACE/LIB/lms7002m/connectionManager/ConnectionUSB.h create mode 100644 targets/ARCH/LMSSDR/USERSPACE/LIB/lms7002m/connectionManager/IConnection.h create mode 100644 targets/ARCH/LMSSDR/USERSPACE/LIB/lms7002m/lms7002_defines.h create mode 100644 targets/ARCH/LMSSDR/USERSPACE/LIB/lms7002m/lmsComms.cpp create mode 100644 targets/ARCH/LMSSDR/USERSPACE/LIB/lms7002m/lmsComms.h create mode 100644 targets/ARCH/LMSSDR/USERSPACE/LIB/lms7002m/typedefs.h create mode 100644 targets/ARCH/LMSSDR/USERSPACE/LIB/lmsSDR/LMS_SDR.cpp create mode 100644 targets/ARCH/LMSSDR/USERSPACE/LIB/lmsSDR/LMS_SDR.h create mode 100644 targets/ARCH/LMSSDR/USERSPACE/LIB/lmsSDR/LMS_StreamBoard/CMakeLists.txt create mode 100644 targets/ARCH/LMSSDR/USERSPACE/LIB/lmsSDR/LMS_StreamBoard/LMS_StreamBoard.cpp create mode 100644 targets/ARCH/LMSSDR/USERSPACE/LIB/lmsSDR/LMS_StreamBoard/LMS_StreamBoard.h create mode 100644 targets/ARCH/LMSSDR/USERSPACE/LIB/lmsSDR/LMS_StreamBoard/LMS_StreamBoard_FIFO.h create mode 100644 targets/ARCH/LMSSDR/USERSPACE/LIB/lmsSDR/LMS_StreamBoard/lms7002_defines.h create mode 100644 targets/ARCH/LMSSDR/USERSPACE/LIB/lmsSDR/connectionManager/CMakeLists.txt create mode 100644 targets/ARCH/LMSSDR/USERSPACE/LIB/lmsSDR/connectionManager/ConnectionCOM.cpp create mode 100644 targets/ARCH/LMSSDR/USERSPACE/LIB/lmsSDR/connectionManager/ConnectionCOM.h create mode 100644 targets/ARCH/LMSSDR/USERSPACE/LIB/lmsSDR/connectionManager/ConnectionManager.cpp create mode 100644 targets/ARCH/LMSSDR/USERSPACE/LIB/lmsSDR/connectionManager/ConnectionManager.h create mode 100644 targets/ARCH/LMSSDR/USERSPACE/LIB/lmsSDR/connectionManager/ConnectionSPI.cpp create mode 100644 targets/ARCH/LMSSDR/USERSPACE/LIB/lmsSDR/connectionManager/ConnectionSPI.h create mode 100644 targets/ARCH/LMSSDR/USERSPACE/LIB/lmsSDR/connectionManager/ConnectionUSB.cpp create mode 100644 targets/ARCH/LMSSDR/USERSPACE/LIB/lmsSDR/connectionManager/ConnectionUSB.h create mode 100644 targets/ARCH/LMSSDR/USERSPACE/LIB/lmsSDR/connectionManager/IConnection.h create mode 100644 targets/ARCH/LMSSDR/USERSPACE/LIB/lmsSDR/connectionManager/lmsComms.cpp create mode 100644 targets/ARCH/LMSSDR/USERSPACE/LIB/lmsSDR/connectionManager/lmsComms.h create mode 100644 targets/ARCH/LMSSDR/USERSPACE/LIB/lmsSDR/dataTypes.h create mode 100644 targets/ARCH/LMSSDR/USERSPACE/LIB/lmsSDR/fifo.h create mode 100644 targets/ARCH/LMSSDR/USERSPACE/LIB/lmsSDR/ringBuffer.h create mode 100644 targets/ARCH/LMSSDR/USERSPACE/LIB/lms_lib.cpp diff --git a/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeCache.txt b/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeCache.txt deleted file mode 100644 index 2bd212843c..0000000000 --- a/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeCache.txt +++ /dev/null @@ -1,326 +0,0 @@ -# This is the CMakeCache file. -# For build in directory: /home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build -# It was generated by CMake: /usr/bin/cmake -# You can edit this file to change values found and used by cmake. -# If you do not want to change any of the values, simply exit the editor. -# If you do want to change a value, simply edit, save, and exit the editor. -# The syntax for the file is as follows: -# KEY:TYPE=VALUE -# KEY is the name of a variable in the cache. -# TYPE is a hint to GUIs for the type of VALUE, DO NOT EDIT TYPE!. -# VALUE is the current value for the KEY. - -######################## -# EXTERNAL cache entries -######################## - -//Path to a program. -CMAKE_AR:FILEPATH=/usr/bin/ar - -//For backwards compatibility, what version of CMake commands and -// syntax should this version of CMake try to support. -CMAKE_BACKWARDS_COMPATIBILITY:STRING=2.4 - -//Choose the type of build, options are: None(CMAKE_CXX_FLAGS or -// CMAKE_C_FLAGS used) Debug Release RelWithDebInfo MinSizeRel. -CMAKE_BUILD_TYPE:STRING= - -//Enable/Disable color output during build. -CMAKE_COLOR_MAKEFILE:BOOL=ON - -//CXX compiler. -CMAKE_CXX_COMPILER:FILEPATH=/usr/bin/c++ - -//Flags used by the compiler during all build types. -CMAKE_CXX_FLAGS:STRING= - -//Flags used by the compiler during debug builds. -CMAKE_CXX_FLAGS_DEBUG:STRING=-g - -//Flags used by the compiler during release minsize builds. -CMAKE_CXX_FLAGS_MINSIZEREL:STRING=-Os -DNDEBUG - -//Flags used by the compiler during release builds (/MD /Ob1 /Oi -// /Ot /Oy /Gs will produce slightly less optimized but smaller -// files). -CMAKE_CXX_FLAGS_RELEASE:STRING=-O3 -DNDEBUG - -//Flags used by the compiler during Release with Debug Info builds. -CMAKE_CXX_FLAGS_RELWITHDEBINFO:STRING=-O2 -g -DNDEBUG - -//C compiler. -CMAKE_C_COMPILER:FILEPATH=/usr/bin/cc - -//Flags used by the compiler during all build types. -CMAKE_C_FLAGS:STRING= - -//Flags used by the compiler during debug builds. -CMAKE_C_FLAGS_DEBUG:STRING=-g - -//Flags used by the compiler during release minsize builds. -CMAKE_C_FLAGS_MINSIZEREL:STRING=-Os -DNDEBUG - -//Flags used by the compiler during release builds (/MD /Ob1 /Oi -// /Ot /Oy /Gs will produce slightly less optimized but smaller -// files). -CMAKE_C_FLAGS_RELEASE:STRING=-O3 -DNDEBUG - -//Flags used by the compiler during Release with Debug Info builds. -CMAKE_C_FLAGS_RELWITHDEBINFO:STRING=-O2 -g -DNDEBUG - -//Flags used by the linker. -CMAKE_EXE_LINKER_FLAGS:STRING=' ' - -//Flags used by the linker during debug builds. -CMAKE_EXE_LINKER_FLAGS_DEBUG:STRING= - -//Flags used by the linker during release minsize builds. -CMAKE_EXE_LINKER_FLAGS_MINSIZEREL:STRING= - -//Flags used by the linker during release builds. -CMAKE_EXE_LINKER_FLAGS_RELEASE:STRING= - -//Flags used by the linker during Release with Debug Info builds. -CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO:STRING= - -//Enable/Disable output of compile commands during generation. -CMAKE_EXPORT_COMPILE_COMMANDS:BOOL=OFF - -//Install path prefix, prepended onto install directories. -CMAKE_INSTALL_PREFIX:PATH=/usr/local - -//Path to a program. -CMAKE_LINKER:FILEPATH=/usr/bin/ld - -//Path to a program. -CMAKE_MAKE_PROGRAM:FILEPATH=/usr/bin/make - -//Flags used by the linker during the creation of modules. -CMAKE_MODULE_LINKER_FLAGS:STRING=' ' - -//Flags used by the linker during debug builds. -CMAKE_MODULE_LINKER_FLAGS_DEBUG:STRING= - -//Flags used by the linker during release minsize builds. -CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL:STRING= - -//Flags used by the linker during release builds. -CMAKE_MODULE_LINKER_FLAGS_RELEASE:STRING= - -//Flags used by the linker during Release with Debug Info builds. -CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO:STRING= - -//Path to a program. -CMAKE_NM:FILEPATH=/usr/bin/nm - -//Path to a program. -CMAKE_OBJCOPY:FILEPATH=/usr/bin/objcopy - -//Path to a program. -CMAKE_OBJDUMP:FILEPATH=/usr/bin/objdump - -//Value Computed by CMake -CMAKE_PROJECT_NAME:STATIC=Project - -//Path to a program. -CMAKE_RANLIB:FILEPATH=/usr/bin/ranlib - -//Flags used by the linker during the creation of dll's. -CMAKE_SHARED_LINKER_FLAGS:STRING=' ' - -//Flags used by the linker during debug builds. -CMAKE_SHARED_LINKER_FLAGS_DEBUG:STRING= - -//Flags used by the linker during release minsize builds. -CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL:STRING= - -//Flags used by the linker during release builds. -CMAKE_SHARED_LINKER_FLAGS_RELEASE:STRING= - -//Flags used by the linker during Release with Debug Info builds. -CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO:STRING= - -//If set, runtime paths are not added when installing shared libraries, -// but are added when building. -CMAKE_SKIP_INSTALL_RPATH:BOOL=NO - -//If set, runtime paths are not added when using shared libraries. -CMAKE_SKIP_RPATH:BOOL=NO - -//Flags used by the linker during the creation of static libraries. -CMAKE_STATIC_LINKER_FLAGS:STRING= - -//Flags used by the linker during debug builds. -CMAKE_STATIC_LINKER_FLAGS_DEBUG:STRING= - -//Flags used by the linker during release minsize builds. -CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL:STRING= - -//Flags used by the linker during release builds. -CMAKE_STATIC_LINKER_FLAGS_RELEASE:STRING= - -//Flags used by the linker during Release with Debug Info builds. -CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO:STRING= - -//Path to a program. -CMAKE_STRIP:FILEPATH=/usr/bin/strip - -//If true, cmake will use relative paths in makefiles and projects. -CMAKE_USE_RELATIVE_PATHS:BOOL=OFF - -//If this value is on, makefiles will be generated without the -// .SILENT directive, and all commands will be echoed to the console -// during the make. This is useful for debugging only. With Visual -// Studio IDE projects all commands are done without /nologo. -CMAKE_VERBOSE_MAKEFILE:BOOL=FALSE - -//Single output directory for building all executables. -EXECUTABLE_OUTPUT_PATH:PATH= - -//Single output directory for building all libraries. -LIBRARY_OUTPUT_PATH:PATH= - -//Value Computed by CMake -Project_BINARY_DIR:STATIC=/home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build - -//Value Computed by CMake -Project_SOURCE_DIR:STATIC=/home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C - -//Dependencies for the target -Si5351C_LIB_DEPENDS:STATIC=general;LMS7002M; - - -######################## -# INTERNAL cache entries -######################## - -//ADVANCED property for variable: CMAKE_AR -CMAKE_AR-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_BUILD_TOOL -CMAKE_BUILD_TOOL-ADVANCED:INTERNAL=1 -//What is the target build tool cmake is generating for. -CMAKE_BUILD_TOOL:INTERNAL=/usr/bin/make -//This is the directory where this CMakeCache.txt was created -CMAKE_CACHEFILE_DIR:INTERNAL=/home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build -//Major version of cmake used to create the current loaded cache -CMAKE_CACHE_MAJOR_VERSION:INTERNAL=2 -//Minor version of cmake used to create the current loaded cache -CMAKE_CACHE_MINOR_VERSION:INTERNAL=8 -//Patch version of cmake used to create the current loaded cache -CMAKE_CACHE_PATCH_VERSION:INTERNAL=12 -//ADVANCED property for variable: CMAKE_COLOR_MAKEFILE -CMAKE_COLOR_MAKEFILE-ADVANCED:INTERNAL=1 -//Path to CMake executable. -CMAKE_COMMAND:INTERNAL=/usr/bin/cmake -//Path to cpack program executable. -CMAKE_CPACK_COMMAND:INTERNAL=/usr/bin/cpack -//Path to ctest program executable. -CMAKE_CTEST_COMMAND:INTERNAL=/usr/bin/ctest -//ADVANCED property for variable: CMAKE_CXX_COMPILER -CMAKE_CXX_COMPILER-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_CXX_FLAGS -CMAKE_CXX_FLAGS-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_CXX_FLAGS_DEBUG -CMAKE_CXX_FLAGS_DEBUG-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_CXX_FLAGS_MINSIZEREL -CMAKE_CXX_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_CXX_FLAGS_RELEASE -CMAKE_CXX_FLAGS_RELEASE-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_CXX_FLAGS_RELWITHDEBINFO -CMAKE_CXX_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_C_COMPILER -CMAKE_C_COMPILER-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_C_FLAGS -CMAKE_C_FLAGS-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_C_FLAGS_DEBUG -CMAKE_C_FLAGS_DEBUG-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_C_FLAGS_MINSIZEREL -CMAKE_C_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_C_FLAGS_RELEASE -CMAKE_C_FLAGS_RELEASE-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_C_FLAGS_RELWITHDEBINFO -CMAKE_C_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 -//Path to cache edit program executable. -CMAKE_EDIT_COMMAND:INTERNAL=/usr/bin/ccmake -//Executable file format -CMAKE_EXECUTABLE_FORMAT:INTERNAL=ELF -//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS -CMAKE_EXE_LINKER_FLAGS-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_DEBUG -CMAKE_EXE_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_MINSIZEREL -CMAKE_EXE_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_RELEASE -CMAKE_EXE_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO -CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_EXPORT_COMPILE_COMMANDS -CMAKE_EXPORT_COMPILE_COMMANDS-ADVANCED:INTERNAL=1 -//Name of generator. -CMAKE_GENERATOR:INTERNAL=Unix Makefiles -//Name of generator toolset. -CMAKE_GENERATOR_TOOLSET:INTERNAL= -//Start directory with the top level CMakeLists.txt file for this -// project -CMAKE_HOME_DIRECTORY:INTERNAL=/home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C -//Install .so files without execute permission. -CMAKE_INSTALL_SO_NO_EXE:INTERNAL=1 -//ADVANCED property for variable: CMAKE_LINKER -CMAKE_LINKER-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_MAKE_PROGRAM -CMAKE_MAKE_PROGRAM-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS -CMAKE_MODULE_LINKER_FLAGS-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_DEBUG -CMAKE_MODULE_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL -CMAKE_MODULE_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_RELEASE -CMAKE_MODULE_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO -CMAKE_MODULE_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_NM -CMAKE_NM-ADVANCED:INTERNAL=1 -//number of local generators -CMAKE_NUMBER_OF_LOCAL_GENERATORS:INTERNAL=1 -//ADVANCED property for variable: CMAKE_OBJCOPY -CMAKE_OBJCOPY-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_OBJDUMP -CMAKE_OBJDUMP-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_RANLIB -CMAKE_RANLIB-ADVANCED:INTERNAL=1 -//Path to CMake installation. -CMAKE_ROOT:INTERNAL=/usr/share/cmake-2.8 -//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS -CMAKE_SHARED_LINKER_FLAGS-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_DEBUG -CMAKE_SHARED_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL -CMAKE_SHARED_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_RELEASE -CMAKE_SHARED_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO -CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_SKIP_INSTALL_RPATH -CMAKE_SKIP_INSTALL_RPATH-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_SKIP_RPATH -CMAKE_SKIP_RPATH-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS -CMAKE_STATIC_LINKER_FLAGS-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_DEBUG -CMAKE_STATIC_LINKER_FLAGS_DEBUG-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL -CMAKE_STATIC_LINKER_FLAGS_MINSIZEREL-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_RELEASE -CMAKE_STATIC_LINKER_FLAGS_RELEASE-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO -CMAKE_STATIC_LINKER_FLAGS_RELWITHDEBINFO-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_STRIP -CMAKE_STRIP-ADVANCED:INTERNAL=1 -//uname command -CMAKE_UNAME:INTERNAL=/bin/uname -//ADVANCED property for variable: CMAKE_USE_RELATIVE_PATHS -CMAKE_USE_RELATIVE_PATHS-ADVANCED:INTERNAL=1 -//ADVANCED property for variable: CMAKE_VERBOSE_MAKEFILE -CMAKE_VERBOSE_MAKEFILE-ADVANCED:INTERNAL=1 - diff --git a/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/2.8.12.2/CMakeCCompiler.cmake b/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/2.8.12.2/CMakeCCompiler.cmake deleted file mode 100644 index f4a508bee8..0000000000 --- a/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/2.8.12.2/CMakeCCompiler.cmake +++ /dev/null @@ -1,56 +0,0 @@ -set(CMAKE_C_COMPILER "/usr/bin/cc") -set(CMAKE_C_COMPILER_ARG1 "") -set(CMAKE_C_COMPILER_ID "GNU") -set(CMAKE_C_COMPILER_VERSION "4.8.4") -set(CMAKE_C_PLATFORM_ID "Linux") - -set(CMAKE_AR "/usr/bin/ar") -set(CMAKE_RANLIB "/usr/bin/ranlib") -set(CMAKE_LINKER "/usr/bin/ld") -set(CMAKE_COMPILER_IS_GNUCC 1) -set(CMAKE_C_COMPILER_LOADED 1) -set(CMAKE_C_COMPILER_WORKS TRUE) -set(CMAKE_C_ABI_COMPILED TRUE) -set(CMAKE_COMPILER_IS_MINGW ) -set(CMAKE_COMPILER_IS_CYGWIN ) -if(CMAKE_COMPILER_IS_CYGWIN) - set(CYGWIN 1) - set(UNIX 1) -endif() - -set(CMAKE_C_COMPILER_ENV_VAR "CC") - -if(CMAKE_COMPILER_IS_MINGW) - set(MINGW 1) -endif() -set(CMAKE_C_COMPILER_ID_RUN 1) -set(CMAKE_C_SOURCE_FILE_EXTENSIONS c) -set(CMAKE_C_IGNORE_EXTENSIONS h;H;o;O;obj;OBJ;def;DEF;rc;RC) -set(CMAKE_C_LINKER_PREFERENCE 10) - -# Save compiler ABI information. -set(CMAKE_C_SIZEOF_DATA_PTR "8") -set(CMAKE_C_COMPILER_ABI "ELF") -set(CMAKE_C_LIBRARY_ARCHITECTURE "x86_64-linux-gnu") - -if(CMAKE_C_SIZEOF_DATA_PTR) - set(CMAKE_SIZEOF_VOID_P "${CMAKE_C_SIZEOF_DATA_PTR}") -endif() - -if(CMAKE_C_COMPILER_ABI) - set(CMAKE_INTERNAL_PLATFORM_ABI "${CMAKE_C_COMPILER_ABI}") -endif() - -if(CMAKE_C_LIBRARY_ARCHITECTURE) - set(CMAKE_LIBRARY_ARCHITECTURE "x86_64-linux-gnu") -endif() - - - - -set(CMAKE_C_IMPLICIT_LINK_LIBRARIES "c") -set(CMAKE_C_IMPLICIT_LINK_DIRECTORIES "/usr/lib/gcc/x86_64-linux-gnu/4.8;/usr/lib/x86_64-linux-gnu;/usr/lib;/lib/x86_64-linux-gnu;/lib") -set(CMAKE_C_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES "") - - - diff --git a/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/2.8.12.2/CMakeCXXCompiler.cmake b/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/2.8.12.2/CMakeCXXCompiler.cmake deleted file mode 100644 index 1ca40dbcd6..0000000000 --- a/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/2.8.12.2/CMakeCXXCompiler.cmake +++ /dev/null @@ -1,57 +0,0 @@ -set(CMAKE_CXX_COMPILER "/usr/bin/c++") -set(CMAKE_CXX_COMPILER_ARG1 "") -set(CMAKE_CXX_COMPILER_ID "GNU") -set(CMAKE_CXX_COMPILER_VERSION "4.8.4") -set(CMAKE_CXX_PLATFORM_ID "Linux") - -set(CMAKE_AR "/usr/bin/ar") -set(CMAKE_RANLIB "/usr/bin/ranlib") -set(CMAKE_LINKER "/usr/bin/ld") -set(CMAKE_COMPILER_IS_GNUCXX 1) -set(CMAKE_CXX_COMPILER_LOADED 1) -set(CMAKE_CXX_COMPILER_WORKS TRUE) -set(CMAKE_CXX_ABI_COMPILED TRUE) -set(CMAKE_COMPILER_IS_MINGW ) -set(CMAKE_COMPILER_IS_CYGWIN ) -if(CMAKE_COMPILER_IS_CYGWIN) - set(CYGWIN 1) - set(UNIX 1) -endif() - -set(CMAKE_CXX_COMPILER_ENV_VAR "CXX") - -if(CMAKE_COMPILER_IS_MINGW) - set(MINGW 1) -endif() -set(CMAKE_CXX_COMPILER_ID_RUN 1) -set(CMAKE_CXX_IGNORE_EXTENSIONS inl;h;hpp;HPP;H;o;O;obj;OBJ;def;DEF;rc;RC) -set(CMAKE_CXX_SOURCE_FILE_EXTENSIONS C;M;c++;cc;cpp;cxx;m;mm;CPP) -set(CMAKE_CXX_LINKER_PREFERENCE 30) -set(CMAKE_CXX_LINKER_PREFERENCE_PROPAGATES 1) - -# Save compiler ABI information. -set(CMAKE_CXX_SIZEOF_DATA_PTR "8") -set(CMAKE_CXX_COMPILER_ABI "ELF") -set(CMAKE_CXX_LIBRARY_ARCHITECTURE "x86_64-linux-gnu") - -if(CMAKE_CXX_SIZEOF_DATA_PTR) - set(CMAKE_SIZEOF_VOID_P "${CMAKE_CXX_SIZEOF_DATA_PTR}") -endif() - -if(CMAKE_CXX_COMPILER_ABI) - set(CMAKE_INTERNAL_PLATFORM_ABI "${CMAKE_CXX_COMPILER_ABI}") -endif() - -if(CMAKE_CXX_LIBRARY_ARCHITECTURE) - set(CMAKE_LIBRARY_ARCHITECTURE "x86_64-linux-gnu") -endif() - - - - -set(CMAKE_CXX_IMPLICIT_LINK_LIBRARIES "stdc++;m;c") -set(CMAKE_CXX_IMPLICIT_LINK_DIRECTORIES "/usr/lib/gcc/x86_64-linux-gnu/4.8;/usr/lib/x86_64-linux-gnu;/usr/lib;/lib/x86_64-linux-gnu;/lib") -set(CMAKE_CXX_IMPLICIT_LINK_FRAMEWORK_DIRECTORIES "") - - - diff --git a/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/2.8.12.2/CMakeDetermineCompilerABI_C.bin b/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/2.8.12.2/CMakeDetermineCompilerABI_C.bin deleted file mode 100755 index 3458fc29190dbceb43a4fb44955cbce374660b02..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8587 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 YSNpGT_qcN9OFrx7@!z`XldUEG1u+4vi~s-t diff --git a/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/2.8.12.2/CMakeDetermineCompilerABI_CXX.bin b/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/2.8.12.2/CMakeDetermineCompilerABI_CXX.bin deleted file mode 100755 index ea701432becf6a6bd7cb452c08f7c7645d0f8607..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8600 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 Qh0vf8p8U7sgQ9cbUvrV1<^TWy diff --git a/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/2.8.12.2/CMakeSystem.cmake b/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/2.8.12.2/CMakeSystem.cmake deleted file mode 100644 index bbcd260466..0000000000 --- a/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/2.8.12.2/CMakeSystem.cmake +++ /dev/null @@ -1,15 +0,0 @@ -set(CMAKE_HOST_SYSTEM "Linux-3.17.0-031700-lowlatency") -set(CMAKE_HOST_SYSTEM_NAME "Linux") -set(CMAKE_HOST_SYSTEM_VERSION "3.17.0-031700-lowlatency") -set(CMAKE_HOST_SYSTEM_PROCESSOR "x86_64") - - - -set(CMAKE_SYSTEM "Linux-3.17.0-031700-lowlatency") -set(CMAKE_SYSTEM_NAME "Linux") -set(CMAKE_SYSTEM_VERSION "3.17.0-031700-lowlatency") -set(CMAKE_SYSTEM_PROCESSOR "x86_64") - -set(CMAKE_CROSSCOMPILING "FALSE") - -set(CMAKE_SYSTEM_LOADED 1) diff --git a/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/2.8.12.2/CompilerIdC/CMakeCCompilerId.c b/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/2.8.12.2/CompilerIdC/CMakeCCompilerId.c deleted file mode 100644 index cba81d4a6b..0000000000 --- a/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/2.8.12.2/CompilerIdC/CMakeCCompilerId.c +++ /dev/null @@ -1,389 +0,0 @@ -#ifdef __cplusplus -# error "A C++ compiler has been selected for C." -#endif - -/* Version number components: V=Version, R=Revision, P=Patch - Version date components: YYYY=Year, MM=Month, DD=Day */ - -#if defined(__18CXX) -# define ID_VOID_MAIN -#endif - -#if defined(__INTEL_COMPILER) || defined(__ICC) -# define COMPILER_ID "Intel" - /* __INTEL_COMPILER = VRP */ -# define COMPILER_VERSION_MAJOR DEC(__INTEL_COMPILER/100) -# define COMPILER_VERSION_MINOR DEC(__INTEL_COMPILER/10 % 10) -# define COMPILER_VERSION_PATCH DEC(__INTEL_COMPILER % 10) -# if defined(__INTEL_COMPILER_BUILD_DATE) - /* __INTEL_COMPILER_BUILD_DATE = YYYYMMDD */ -# define COMPILER_VERSION_TWEAK DEC(__INTEL_COMPILER_BUILD_DATE) -# endif - -#elif defined(__PATHCC__) -# define COMPILER_ID "PathScale" -# define COMPILER_VERSION_MAJOR DEC(__PATHCC__) -# define COMPILER_VERSION_MINOR DEC(__PATHCC_MINOR__) -# if defined(__PATHCC_PATCHLEVEL__) -# define COMPILER_VERSION_PATCH DEC(__PATHCC_PATCHLEVEL__) -# endif - -#elif defined(__clang__) -# define COMPILER_ID "Clang" -# define COMPILER_VERSION_MAJOR DEC(__clang_major__) -# define COMPILER_VERSION_MINOR DEC(__clang_minor__) -# define COMPILER_VERSION_PATCH DEC(__clang_patchlevel__) - -#elif defined(__BORLANDC__) && defined(__CODEGEARC_VERSION__) -# define COMPILER_ID "Embarcadero" -# define COMPILER_VERSION_MAJOR HEX(__CODEGEARC_VERSION__>>24 & 0x00FF) -# define COMPILER_VERSION_MINOR HEX(__CODEGEARC_VERSION__>>16 & 0x00FF) -# define COMPILER_VERSION_PATCH HEX(__CODEGEARC_VERSION__ & 0xFFFF) - -#elif defined(__BORLANDC__) -# define COMPILER_ID "Borland" - /* __BORLANDC__ = 0xVRR */ -# define COMPILER_VERSION_MAJOR HEX(__BORLANDC__>>8) -# define COMPILER_VERSION_MINOR HEX(__BORLANDC__ & 0xFF) - -#elif defined(__WATCOMC__) -# define COMPILER_ID "Watcom" - /* __WATCOMC__ = VVRR */ -# define COMPILER_VERSION_MAJOR DEC(__WATCOMC__ / 100) -# define COMPILER_VERSION_MINOR DEC(__WATCOMC__ % 100) - -#elif defined(__SUNPRO_C) -# define COMPILER_ID "SunPro" -# if __SUNPRO_C >= 0x5100 - /* __SUNPRO_C = 0xVRRP */ -# define COMPILER_VERSION_MAJOR HEX(__SUNPRO_C>>12) -# define COMPILER_VERSION_MINOR HEX(__SUNPRO_C>>4 & 0xFF) -# define COMPILER_VERSION_PATCH HEX(__SUNPRO_C & 0xF) -# else - /* __SUNPRO_C = 0xVRP */ -# define COMPILER_VERSION_MAJOR HEX(__SUNPRO_C>>8) -# define COMPILER_VERSION_MINOR HEX(__SUNPRO_C>>4 & 0xF) -# define COMPILER_VERSION_PATCH HEX(__SUNPRO_C & 0xF) -# endif - -#elif defined(__HP_cc) -# define COMPILER_ID "HP" - /* __HP_cc = VVRRPP */ -# define COMPILER_VERSION_MAJOR DEC(__HP_cc/10000) -# define COMPILER_VERSION_MINOR DEC(__HP_cc/100 % 100) -# define COMPILER_VERSION_PATCH DEC(__HP_cc % 100) - -#elif defined(__DECC) -# define COMPILER_ID "Compaq" - /* __DECC_VER = VVRRTPPPP */ -# define COMPILER_VERSION_MAJOR DEC(__DECC_VER/10000000) -# define COMPILER_VERSION_MINOR DEC(__DECC_VER/100000 % 100) -# define COMPILER_VERSION_PATCH DEC(__DECC_VER % 10000) - -#elif defined(__IBMC__) -# if defined(__COMPILER_VER__) -# define COMPILER_ID "zOS" -# else -# if __IBMC__ >= 800 -# define COMPILER_ID "XL" -# else -# define COMPILER_ID "VisualAge" -# endif - /* __IBMC__ = VRP */ -# define COMPILER_VERSION_MAJOR DEC(__IBMC__/100) -# define COMPILER_VERSION_MINOR DEC(__IBMC__/10 % 10) -# define COMPILER_VERSION_PATCH DEC(__IBMC__ % 10) -# endif - -#elif defined(__PGI) -# define COMPILER_ID "PGI" -# define COMPILER_VERSION_MAJOR DEC(__PGIC__) -# define COMPILER_VERSION_MINOR DEC(__PGIC_MINOR__) -# if defined(__PGIC_PATCHLEVEL__) -# define COMPILER_VERSION_PATCH DEC(__PGIC_PATCHLEVEL__) -# endif - -#elif defined(_CRAYC) -# define COMPILER_ID "Cray" -# define COMPILER_VERSION_MAJOR DEC(_RELEASE) -# define COMPILER_VERSION_MINOR DEC(_RELEASE_MINOR) - -#elif defined(__TI_COMPILER_VERSION__) -# define COMPILER_ID "TI" - /* __TI_COMPILER_VERSION__ = VVVRRRPPP */ -# define COMPILER_VERSION_MAJOR DEC(__TI_COMPILER_VERSION__/1000000) -# define COMPILER_VERSION_MINOR DEC(__TI_COMPILER_VERSION__/1000 % 1000) -# define COMPILER_VERSION_PATCH DEC(__TI_COMPILER_VERSION__ % 1000) - -#elif defined(__TINYC__) -# define COMPILER_ID "TinyCC" - -#elif defined(__SCO_VERSION__) -# define COMPILER_ID "SCO" - -#elif defined(__GNUC__) -# define COMPILER_ID "GNU" -# define COMPILER_VERSION_MAJOR DEC(__GNUC__) -# define COMPILER_VERSION_MINOR DEC(__GNUC_MINOR__) -# if defined(__GNUC_PATCHLEVEL__) -# define COMPILER_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__) -# endif - -#elif defined(_MSC_VER) -# define COMPILER_ID "MSVC" - /* _MSC_VER = VVRR */ -# define COMPILER_VERSION_MAJOR DEC(_MSC_VER / 100) -# define COMPILER_VERSION_MINOR DEC(_MSC_VER % 100) -# if defined(_MSC_FULL_VER) -# if _MSC_VER >= 1400 - /* _MSC_FULL_VER = VVRRPPPPP */ -# define COMPILER_VERSION_PATCH DEC(_MSC_FULL_VER % 100000) -# else - /* _MSC_FULL_VER = VVRRPPPP */ -# define COMPILER_VERSION_PATCH DEC(_MSC_FULL_VER % 10000) -# endif -# endif -# if defined(_MSC_BUILD) -# define COMPILER_VERSION_TWEAK DEC(_MSC_BUILD) -# endif - -/* Analog VisualDSP++ >= 4.5.6 */ -#elif defined(__VISUALDSPVERSION__) -# define COMPILER_ID "ADSP" - /* __VISUALDSPVERSION__ = 0xVVRRPP00 */ -# define COMPILER_VERSION_MAJOR HEX(__VISUALDSPVERSION__>>24) -# define COMPILER_VERSION_MINOR HEX(__VISUALDSPVERSION__>>16 & 0xFF) -# define COMPILER_VERSION_PATCH HEX(__VISUALDSPVERSION__>>8 & 0xFF) - -/* Analog VisualDSP++ < 4.5.6 */ -#elif defined(__ADSPBLACKFIN__) || defined(__ADSPTS__) || defined(__ADSP21000__) -# define COMPILER_ID "ADSP" - -/* IAR Systems compiler for embedded systems. - http://www.iar.com */ -#elif defined(__IAR_SYSTEMS_ICC__ ) || defined(__IAR_SYSTEMS_ICC) -# define COMPILER_ID "IAR" - -/* sdcc, the small devices C compiler for embedded systems, - http://sdcc.sourceforge.net */ -#elif defined(SDCC) -# define COMPILER_ID "SDCC" - /* SDCC = VRP */ -# define COMPILER_VERSION_MAJOR DEC(SDCC/100) -# define COMPILER_VERSION_MINOR DEC(SDCC/10 % 10) -# define COMPILER_VERSION_PATCH DEC(SDCC % 10) - -#elif defined(_SGI_COMPILER_VERSION) || defined(_COMPILER_VERSION) -# define COMPILER_ID "MIPSpro" -# if defined(_SGI_COMPILER_VERSION) - /* _SGI_COMPILER_VERSION = VRP */ -# define COMPILER_VERSION_MAJOR DEC(_SGI_COMPILER_VERSION/100) -# define COMPILER_VERSION_MINOR DEC(_SGI_COMPILER_VERSION/10 % 10) -# define COMPILER_VERSION_PATCH DEC(_SGI_COMPILER_VERSION % 10) -# else - /* _COMPILER_VERSION = VRP */ -# define COMPILER_VERSION_MAJOR DEC(_COMPILER_VERSION/100) -# define COMPILER_VERSION_MINOR DEC(_COMPILER_VERSION/10 % 10) -# define COMPILER_VERSION_PATCH DEC(_COMPILER_VERSION % 10) -# endif - -/* This compiler is either not known or is too old to define an - identification macro. Try to identify the platform and guess that - it is the native compiler. */ -#elif defined(__sgi) -# define COMPILER_ID "MIPSpro" - -#elif defined(__hpux) || defined(__hpua) -# define COMPILER_ID "HP" - -#else /* unknown compiler */ -# define COMPILER_ID "" - -#endif - -/* Construct the string literal in pieces to prevent the source from - getting matched. Store it in a pointer rather than an array - because some compilers will just produce instructions to fill the - array rather than assigning a pointer to a static array. */ -char const* info_compiler = "INFO" ":" "compiler[" COMPILER_ID "]"; - -/* Identify known platforms by name. */ -#if defined(__linux) || defined(__linux__) || defined(linux) -# define PLATFORM_ID "Linux" - -#elif defined(__CYGWIN__) -# define PLATFORM_ID "Cygwin" - -#elif defined(__MINGW32__) -# define PLATFORM_ID "MinGW" - -#elif defined(__APPLE__) -# define PLATFORM_ID "Darwin" - -#elif defined(_WIN32) || defined(__WIN32__) || defined(WIN32) -# define PLATFORM_ID "Windows" - -#elif defined(__FreeBSD__) || defined(__FreeBSD) -# define PLATFORM_ID "FreeBSD" - -#elif defined(__NetBSD__) || defined(__NetBSD) -# define PLATFORM_ID "NetBSD" - -#elif defined(__OpenBSD__) || defined(__OPENBSD) -# define PLATFORM_ID "OpenBSD" - -#elif defined(__sun) || defined(sun) -# define PLATFORM_ID "SunOS" - -#elif defined(_AIX) || defined(__AIX) || defined(__AIX__) || defined(__aix) || defined(__aix__) -# define PLATFORM_ID "AIX" - -#elif defined(__sgi) || defined(__sgi__) || defined(_SGI) -# define PLATFORM_ID "IRIX" - -#elif defined(__hpux) || defined(__hpux__) -# define PLATFORM_ID "HP-UX" - -#elif defined(__HAIKU__) -# define PLATFORM_ID "Haiku" - -#elif defined(__BeOS) || defined(__BEOS__) || defined(_BEOS) -# define PLATFORM_ID "BeOS" - -#elif defined(__QNX__) || defined(__QNXNTO__) -# define PLATFORM_ID "QNX" - -#elif defined(__tru64) || defined(_tru64) || defined(__TRU64__) -# define PLATFORM_ID "Tru64" - -#elif defined(__riscos) || defined(__riscos__) -# define PLATFORM_ID "RISCos" - -#elif defined(__sinix) || defined(__sinix__) || defined(__SINIX__) -# define PLATFORM_ID "SINIX" - -#elif defined(__UNIX_SV__) -# define PLATFORM_ID "UNIX_SV" - -#elif defined(__bsdos__) -# define PLATFORM_ID "BSDOS" - -#elif defined(_MPRAS) || defined(MPRAS) -# define PLATFORM_ID "MP-RAS" - -#elif defined(__osf) || defined(__osf__) -# define PLATFORM_ID "OSF1" - -#elif defined(_SCO_SV) || defined(SCO_SV) || defined(sco_sv) -# define PLATFORM_ID "SCO_SV" - -#elif defined(__ultrix) || defined(__ultrix__) || defined(_ULTRIX) -# define PLATFORM_ID "ULTRIX" - -#elif defined(__XENIX__) || defined(_XENIX) || defined(XENIX) -# define PLATFORM_ID "Xenix" - -#else /* unknown platform */ -# define PLATFORM_ID "" - -#endif - -/* For windows compilers MSVC and Intel we can determine - the architecture of the compiler being used. This is because - the compilers do not have flags that can change the architecture, - but rather depend on which compiler is being used -*/ -#if defined(_WIN32) && defined(_MSC_VER) -# if defined(_M_IA64) -# define ARCHITECTURE_ID "IA64" - -# elif defined(_M_X64) || defined(_M_AMD64) -# define ARCHITECTURE_ID "x64" - -# elif defined(_M_IX86) -# define ARCHITECTURE_ID "X86" - -# elif defined(_M_ARM) -# define ARCHITECTURE_ID "ARM" - -# elif defined(_M_MIPS) -# define ARCHITECTURE_ID "MIPS" - -# elif defined(_M_SH) -# define ARCHITECTURE_ID "SHx" - -# else /* unknown architecture */ -# define ARCHITECTURE_ID "" -# endif - -#else -# define ARCHITECTURE_ID "" -#endif - -/* Convert integer to decimal digit literals. */ -#define DEC(n) \ - ('0' + (((n) / 10000000)%10)), \ - ('0' + (((n) / 1000000)%10)), \ - ('0' + (((n) / 100000)%10)), \ - ('0' + (((n) / 10000)%10)), \ - ('0' + (((n) / 1000)%10)), \ - ('0' + (((n) / 100)%10)), \ - ('0' + (((n) / 10)%10)), \ - ('0' + ((n) % 10)) - -/* Convert integer to hex digit literals. */ -#define HEX(n) \ - ('0' + ((n)>>28 & 0xF)), \ - ('0' + ((n)>>24 & 0xF)), \ - ('0' + ((n)>>20 & 0xF)), \ - ('0' + ((n)>>16 & 0xF)), \ - ('0' + ((n)>>12 & 0xF)), \ - ('0' + ((n)>>8 & 0xF)), \ - ('0' + ((n)>>4 & 0xF)), \ - ('0' + ((n) & 0xF)) - -/* Construct a string literal encoding the version number components. */ -#ifdef COMPILER_VERSION_MAJOR -char const info_version[] = { - 'I', 'N', 'F', 'O', ':', - 'c','o','m','p','i','l','e','r','_','v','e','r','s','i','o','n','[', - COMPILER_VERSION_MAJOR, -# ifdef COMPILER_VERSION_MINOR - '.', COMPILER_VERSION_MINOR, -# ifdef COMPILER_VERSION_PATCH - '.', COMPILER_VERSION_PATCH, -# ifdef COMPILER_VERSION_TWEAK - '.', COMPILER_VERSION_TWEAK, -# endif -# endif -# endif - ']','\0'}; -#endif - -/* Construct the string literal in pieces to prevent the source from - getting matched. Store it in a pointer rather than an array - because some compilers will just produce instructions to fill the - array rather than assigning a pointer to a static array. */ -char const* info_platform = "INFO" ":" "platform[" PLATFORM_ID "]"; -char const* info_arch = "INFO" ":" "arch[" ARCHITECTURE_ID "]"; - - - -/*--------------------------------------------------------------------------*/ - -#ifdef ID_VOID_MAIN -void main() {} -#else -int main(int argc, char* argv[]) -{ - int require = 0; - require += info_compiler[argc]; - require += info_platform[argc]; - require += info_arch[argc]; -#ifdef COMPILER_VERSION_MAJOR - require += info_version[argc]; -#endif - (void)argv; - return require; -} -#endif diff --git a/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/2.8.12.2/CompilerIdC/a.out b/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/2.8.12.2/CompilerIdC/a.out deleted file mode 100755 index 1d7e438b92300abaac114123c512167b14d7d259..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8683 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 & 0x00FF) -# define COMPILER_VERSION_MINOR HEX(__CODEGEARC_VERSION__>>16 & 0x00FF) -# define COMPILER_VERSION_PATCH HEX(__CODEGEARC_VERSION__ & 0xFFFF) - -#elif defined(__BORLANDC__) -# define COMPILER_ID "Borland" - /* __BORLANDC__ = 0xVRR */ -# define COMPILER_VERSION_MAJOR HEX(__BORLANDC__>>8) -# define COMPILER_VERSION_MINOR HEX(__BORLANDC__ & 0xFF) - -#elif defined(__WATCOMC__) -# define COMPILER_ID "Watcom" - /* __WATCOMC__ = VVRR */ -# define COMPILER_VERSION_MAJOR DEC(__WATCOMC__ / 100) -# define COMPILER_VERSION_MINOR DEC(__WATCOMC__ % 100) - -#elif defined(__SUNPRO_CC) -# define COMPILER_ID "SunPro" -# if __SUNPRO_CC >= 0x5100 - /* __SUNPRO_CC = 0xVRRP */ -# define COMPILER_VERSION_MAJOR HEX(__SUNPRO_CC>>12) -# define COMPILER_VERSION_MINOR HEX(__SUNPRO_CC>>4 & 0xFF) -# define COMPILER_VERSION_PATCH HEX(__SUNPRO_CC & 0xF) -# else - /* __SUNPRO_CC = 0xVRP */ -# define COMPILER_VERSION_MAJOR HEX(__SUNPRO_CC>>8) -# define COMPILER_VERSION_MINOR HEX(__SUNPRO_CC>>4 & 0xF) -# define COMPILER_VERSION_PATCH HEX(__SUNPRO_CC & 0xF) -# endif - -#elif defined(__HP_aCC) -# define COMPILER_ID "HP" - /* __HP_aCC = VVRRPP */ -# define COMPILER_VERSION_MAJOR DEC(__HP_aCC/10000) -# define COMPILER_VERSION_MINOR DEC(__HP_aCC/100 % 100) -# define COMPILER_VERSION_PATCH DEC(__HP_aCC % 100) - -#elif defined(__DECCXX) -# define COMPILER_ID "Compaq" - /* __DECCXX_VER = VVRRTPPPP */ -# define COMPILER_VERSION_MAJOR DEC(__DECCXX_VER/10000000) -# define COMPILER_VERSION_MINOR DEC(__DECCXX_VER/100000 % 100) -# define COMPILER_VERSION_PATCH DEC(__DECCXX_VER % 10000) - -#elif defined(__IBMCPP__) -# if defined(__COMPILER_VER__) -# define COMPILER_ID "zOS" -# else -# if __IBMCPP__ >= 800 -# define COMPILER_ID "XL" -# else -# define COMPILER_ID "VisualAge" -# endif - /* __IBMCPP__ = VRP */ -# define COMPILER_VERSION_MAJOR DEC(__IBMCPP__/100) -# define COMPILER_VERSION_MINOR DEC(__IBMCPP__/10 % 10) -# define COMPILER_VERSION_PATCH DEC(__IBMCPP__ % 10) -# endif - -#elif defined(__PGI) -# define COMPILER_ID "PGI" -# define COMPILER_VERSION_MAJOR DEC(__PGIC__) -# define COMPILER_VERSION_MINOR DEC(__PGIC_MINOR__) -# if defined(__PGIC_PATCHLEVEL__) -# define COMPILER_VERSION_PATCH DEC(__PGIC_PATCHLEVEL__) -# endif - -#elif defined(_CRAYC) -# define COMPILER_ID "Cray" -# define COMPILER_VERSION_MAJOR DEC(_RELEASE) -# define COMPILER_VERSION_MINOR DEC(_RELEASE_MINOR) - -#elif defined(__TI_COMPILER_VERSION__) -# define COMPILER_ID "TI" - /* __TI_COMPILER_VERSION__ = VVVRRRPPP */ -# define COMPILER_VERSION_MAJOR DEC(__TI_COMPILER_VERSION__/1000000) -# define COMPILER_VERSION_MINOR DEC(__TI_COMPILER_VERSION__/1000 % 1000) -# define COMPILER_VERSION_PATCH DEC(__TI_COMPILER_VERSION__ % 1000) - -#elif defined(__SCO_VERSION__) -# define COMPILER_ID "SCO" - -#elif defined(__GNUC__) -# define COMPILER_ID "GNU" -# define COMPILER_VERSION_MAJOR DEC(__GNUC__) -# define COMPILER_VERSION_MINOR DEC(__GNUC_MINOR__) -# if defined(__GNUC_PATCHLEVEL__) -# define COMPILER_VERSION_PATCH DEC(__GNUC_PATCHLEVEL__) -# endif - -#elif defined(_MSC_VER) -# define COMPILER_ID "MSVC" - /* _MSC_VER = VVRR */ -# define COMPILER_VERSION_MAJOR DEC(_MSC_VER / 100) -# define COMPILER_VERSION_MINOR DEC(_MSC_VER % 100) -# if defined(_MSC_FULL_VER) -# if _MSC_VER >= 1400 - /* _MSC_FULL_VER = VVRRPPPPP */ -# define COMPILER_VERSION_PATCH DEC(_MSC_FULL_VER % 100000) -# else - /* _MSC_FULL_VER = VVRRPPPP */ -# define COMPILER_VERSION_PATCH DEC(_MSC_FULL_VER % 10000) -# endif -# endif -# if defined(_MSC_BUILD) -# define COMPILER_VERSION_TWEAK DEC(_MSC_BUILD) -# endif - -/* Analog VisualDSP++ >= 4.5.6 */ -#elif defined(__VISUALDSPVERSION__) -# define COMPILER_ID "ADSP" - /* __VISUALDSPVERSION__ = 0xVVRRPP00 */ -# define COMPILER_VERSION_MAJOR HEX(__VISUALDSPVERSION__>>24) -# define COMPILER_VERSION_MINOR HEX(__VISUALDSPVERSION__>>16 & 0xFF) -# define COMPILER_VERSION_PATCH HEX(__VISUALDSPVERSION__>>8 & 0xFF) - -/* Analog VisualDSP++ < 4.5.6 */ -#elif defined(__ADSPBLACKFIN__) || defined(__ADSPTS__) || defined(__ADSP21000__) -# define COMPILER_ID "ADSP" - -/* IAR Systems compiler for embedded systems. - http://www.iar.com */ -#elif defined(__IAR_SYSTEMS_ICC__ ) || defined(__IAR_SYSTEMS_ICC) -# define COMPILER_ID "IAR" - -#elif defined(_SGI_COMPILER_VERSION) || defined(_COMPILER_VERSION) -# define COMPILER_ID "MIPSpro" -# if defined(_SGI_COMPILER_VERSION) - /* _SGI_COMPILER_VERSION = VRP */ -# define COMPILER_VERSION_MAJOR DEC(_SGI_COMPILER_VERSION/100) -# define COMPILER_VERSION_MINOR DEC(_SGI_COMPILER_VERSION/10 % 10) -# define COMPILER_VERSION_PATCH DEC(_SGI_COMPILER_VERSION % 10) -# else - /* _COMPILER_VERSION = VRP */ -# define COMPILER_VERSION_MAJOR DEC(_COMPILER_VERSION/100) -# define COMPILER_VERSION_MINOR DEC(_COMPILER_VERSION/10 % 10) -# define COMPILER_VERSION_PATCH DEC(_COMPILER_VERSION % 10) -# endif - -/* This compiler is either not known or is too old to define an - identification macro. Try to identify the platform and guess that - it is the native compiler. */ -#elif defined(__sgi) -# define COMPILER_ID "MIPSpro" - -#elif defined(__hpux) || defined(__hpua) -# define COMPILER_ID "HP" - -#else /* unknown compiler */ -# define COMPILER_ID "" - -#endif - -/* Construct the string literal in pieces to prevent the source from - getting matched. Store it in a pointer rather than an array - because some compilers will just produce instructions to fill the - array rather than assigning a pointer to a static array. */ -char const* info_compiler = "INFO" ":" "compiler[" COMPILER_ID "]"; - -/* Identify known platforms by name. */ -#if defined(__linux) || defined(__linux__) || defined(linux) -# define PLATFORM_ID "Linux" - -#elif defined(__CYGWIN__) -# define PLATFORM_ID "Cygwin" - -#elif defined(__MINGW32__) -# define PLATFORM_ID "MinGW" - -#elif defined(__APPLE__) -# define PLATFORM_ID "Darwin" - -#elif defined(_WIN32) || defined(__WIN32__) || defined(WIN32) -# define PLATFORM_ID "Windows" - -#elif defined(__FreeBSD__) || defined(__FreeBSD) -# define PLATFORM_ID "FreeBSD" - -#elif defined(__NetBSD__) || defined(__NetBSD) -# define PLATFORM_ID "NetBSD" - -#elif defined(__OpenBSD__) || defined(__OPENBSD) -# define PLATFORM_ID "OpenBSD" - -#elif defined(__sun) || defined(sun) -# define PLATFORM_ID "SunOS" - -#elif defined(_AIX) || defined(__AIX) || defined(__AIX__) || defined(__aix) || defined(__aix__) -# define PLATFORM_ID "AIX" - -#elif defined(__sgi) || defined(__sgi__) || defined(_SGI) -# define PLATFORM_ID "IRIX" - -#elif defined(__hpux) || defined(__hpux__) -# define PLATFORM_ID "HP-UX" - -#elif defined(__HAIKU__) -# define PLATFORM_ID "Haiku" - -#elif defined(__BeOS) || defined(__BEOS__) || defined(_BEOS) -# define PLATFORM_ID "BeOS" - -#elif defined(__QNX__) || defined(__QNXNTO__) -# define PLATFORM_ID "QNX" - -#elif defined(__tru64) || defined(_tru64) || defined(__TRU64__) -# define PLATFORM_ID "Tru64" - -#elif defined(__riscos) || defined(__riscos__) -# define PLATFORM_ID "RISCos" - -#elif defined(__sinix) || defined(__sinix__) || defined(__SINIX__) -# define PLATFORM_ID "SINIX" - -#elif defined(__UNIX_SV__) -# define PLATFORM_ID "UNIX_SV" - -#elif defined(__bsdos__) -# define PLATFORM_ID "BSDOS" - -#elif defined(_MPRAS) || defined(MPRAS) -# define PLATFORM_ID "MP-RAS" - -#elif defined(__osf) || defined(__osf__) -# define PLATFORM_ID "OSF1" - -#elif defined(_SCO_SV) || defined(SCO_SV) || defined(sco_sv) -# define PLATFORM_ID "SCO_SV" - -#elif defined(__ultrix) || defined(__ultrix__) || defined(_ULTRIX) -# define PLATFORM_ID "ULTRIX" - -#elif defined(__XENIX__) || defined(_XENIX) || defined(XENIX) -# define PLATFORM_ID "Xenix" - -#else /* unknown platform */ -# define PLATFORM_ID "" - -#endif - -/* For windows compilers MSVC and Intel we can determine - the architecture of the compiler being used. This is because - the compilers do not have flags that can change the architecture, - but rather depend on which compiler is being used -*/ -#if defined(_WIN32) && defined(_MSC_VER) -# if defined(_M_IA64) -# define ARCHITECTURE_ID "IA64" - -# elif defined(_M_X64) || defined(_M_AMD64) -# define ARCHITECTURE_ID "x64" - -# elif defined(_M_IX86) -# define ARCHITECTURE_ID "X86" - -# elif defined(_M_ARM) -# define ARCHITECTURE_ID "ARM" - -# elif defined(_M_MIPS) -# define ARCHITECTURE_ID "MIPS" - -# elif defined(_M_SH) -# define ARCHITECTURE_ID "SHx" - -# else /* unknown architecture */ -# define ARCHITECTURE_ID "" -# endif - -#else -# define ARCHITECTURE_ID "" -#endif - -/* Convert integer to decimal digit literals. */ -#define DEC(n) \ - ('0' + (((n) / 10000000)%10)), \ - ('0' + (((n) / 1000000)%10)), \ - ('0' + (((n) / 100000)%10)), \ - ('0' + (((n) / 10000)%10)), \ - ('0' + (((n) / 1000)%10)), \ - ('0' + (((n) / 100)%10)), \ - ('0' + (((n) / 10)%10)), \ - ('0' + ((n) % 10)) - -/* Convert integer to hex digit literals. */ -#define HEX(n) \ - ('0' + ((n)>>28 & 0xF)), \ - ('0' + ((n)>>24 & 0xF)), \ - ('0' + ((n)>>20 & 0xF)), \ - ('0' + ((n)>>16 & 0xF)), \ - ('0' + ((n)>>12 & 0xF)), \ - ('0' + ((n)>>8 & 0xF)), \ - ('0' + ((n)>>4 & 0xF)), \ - ('0' + ((n) & 0xF)) - -/* Construct a string literal encoding the version number components. */ -#ifdef COMPILER_VERSION_MAJOR -char const info_version[] = { - 'I', 'N', 'F', 'O', ':', - 'c','o','m','p','i','l','e','r','_','v','e','r','s','i','o','n','[', - COMPILER_VERSION_MAJOR, -# ifdef COMPILER_VERSION_MINOR - '.', COMPILER_VERSION_MINOR, -# ifdef COMPILER_VERSION_PATCH - '.', COMPILER_VERSION_PATCH, -# ifdef COMPILER_VERSION_TWEAK - '.', COMPILER_VERSION_TWEAK, -# endif -# endif -# endif - ']','\0'}; -#endif - -/* Construct the string literal in pieces to prevent the source from - getting matched. Store it in a pointer rather than an array - because some compilers will just produce instructions to fill the - array rather than assigning a pointer to a static array. */ -char const* info_platform = "INFO" ":" "platform[" PLATFORM_ID "]"; -char const* info_arch = "INFO" ":" "arch[" ARCHITECTURE_ID "]"; - - - -/*--------------------------------------------------------------------------*/ - -int main(int argc, char* argv[]) -{ - int require = 0; - require += info_compiler[argc]; - require += info_platform[argc]; -#ifdef COMPILER_VERSION_MAJOR - require += info_version[argc]; -#endif - (void)argv; - return require; -} diff --git a/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/2.8.12.2/CompilerIdCXX/a.out b/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/2.8.12.2/CompilerIdCXX/a.out deleted file mode 100755 index aeee00b0724a9ab52a33c118ab316ac8e587fac6..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 8692 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 diff --git a/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/CMakeDirectoryInformation.cmake b/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/CMakeDirectoryInformation.cmake deleted file mode 100644 index 335b0cbcf2..0000000000 --- a/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/CMakeDirectoryInformation.cmake +++ /dev/null @@ -1,16 +0,0 @@ -# CMAKE generated file: DO NOT EDIT! -# Generated by "Unix Makefiles" Generator, CMake Version 2.8 - -# Relative path conversion top directories. -SET(CMAKE_RELATIVE_PATH_TOP_SOURCE "/home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C") -SET(CMAKE_RELATIVE_PATH_TOP_BINARY "/home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build") - -# Force unix paths in dependencies. -SET(CMAKE_FORCE_UNIX_PATHS 1) - - -# The C and CXX include file regular expressions for this directory. -SET(CMAKE_C_INCLUDE_REGEX_SCAN "^.*$") -SET(CMAKE_C_INCLUDE_REGEX_COMPLAIN "^$") -SET(CMAKE_CXX_INCLUDE_REGEX_SCAN ${CMAKE_C_INCLUDE_REGEX_SCAN}) -SET(CMAKE_CXX_INCLUDE_REGEX_COMPLAIN ${CMAKE_C_INCLUDE_REGEX_COMPLAIN}) diff --git a/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/CMakeOutput.log b/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/CMakeOutput.log deleted file mode 100644 index 10bdcf5f63..0000000000 --- a/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/CMakeOutput.log +++ /dev/null @@ -1,263 +0,0 @@ -The system is: Linux - 3.17.0-031700-lowlatency - x86_64 -Compiling the C compiler identification source file "CMakeCCompilerId.c" succeeded. -Compiler: /usr/bin/cc -Build flags: -Id flags: - -The output was: -0 - - -Compilation of the C compiler identification source "CMakeCCompilerId.c" produced "a.out" - -The C compiler identification is GNU, found in "/home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/2.8.12.2/CompilerIdC/a.out" - -Compiling the CXX compiler identification source file "CMakeCXXCompilerId.cpp" succeeded. -Compiler: /usr/bin/c++ -Build flags: -Id flags: - -The output was: -0 - - -Compilation of the CXX compiler identification source "CMakeCXXCompilerId.cpp" produced "a.out" - -The CXX compiler identification is GNU, found in "/home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/2.8.12.2/CompilerIdCXX/a.out" - -Determining if the C compiler works passed with the following output: -Change Dir: /home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/CMakeTmp - -Run Build Command:/usr/bin/make "cmTryCompileExec4097118404/fast" -/usr/bin/make -f CMakeFiles/cmTryCompileExec4097118404.dir/build.make CMakeFiles/cmTryCompileExec4097118404.dir/build -make[1]: Entering directory `/home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/CMakeTmp' -/usr/bin/cmake -E cmake_progress_report /home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/CMakeTmp/CMakeFiles 1 -Building C object CMakeFiles/cmTryCompileExec4097118404.dir/testCCompiler.c.o -/usr/bin/cc -o CMakeFiles/cmTryCompileExec4097118404.dir/testCCompiler.c.o -c /home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/CMakeTmp/testCCompiler.c -Linking C executable cmTryCompileExec4097118404 -/usr/bin/cmake -E cmake_link_script CMakeFiles/cmTryCompileExec4097118404.dir/link.txt --verbose=1 -/usr/bin/cc CMakeFiles/cmTryCompileExec4097118404.dir/testCCompiler.c.o -o cmTryCompileExec4097118404 -rdynamic -make[1]: Leaving directory `/home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/CMakeTmp' - - -Detecting C compiler ABI info compiled with the following output: -Change Dir: /home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/CMakeTmp - -Run Build Command:/usr/bin/make "cmTryCompileExec3603593924/fast" -/usr/bin/make -f CMakeFiles/cmTryCompileExec3603593924.dir/build.make CMakeFiles/cmTryCompileExec3603593924.dir/build -make[1]: Entering directory `/home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/CMakeTmp' -/usr/bin/cmake -E cmake_progress_report /home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/CMakeTmp/CMakeFiles 1 -Building C object CMakeFiles/cmTryCompileExec3603593924.dir/CMakeCCompilerABI.c.o -/usr/bin/cc -o CMakeFiles/cmTryCompileExec3603593924.dir/CMakeCCompilerABI.c.o -c /usr/share/cmake-2.8/Modules/CMakeCCompilerABI.c -Linking C executable cmTryCompileExec3603593924 -/usr/bin/cmake -E cmake_link_script CMakeFiles/cmTryCompileExec3603593924.dir/link.txt --verbose=1 -/usr/bin/cc -v CMakeFiles/cmTryCompileExec3603593924.dir/CMakeCCompilerABI.c.o -o cmTryCompileExec3603593924 -rdynamic -Using built-in specs. -COLLECT_GCC=/usr/bin/cc -COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/4.8/lto-wrapper -Target: x86_64-linux-gnu -Configured with: ../src/configure -v --with-pkgversion='Ubuntu 4.8.4-2ubuntu1~14.04' --with-bugurl=file:///usr/share/doc/gcc-4.8/README.Bugs --enable-languages=c,c++,java,go,d,fortran,objc,obj-c++ --prefix=/usr --program-suffix=-4.8 --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --with-gxx-include-dir=/usr/include/c++/4.8 --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --enable-gnu-unique-object --disable-libmudflap --enable-plugin --with-system-zlib --disable-browser-plugin --enable-java-awt=gtk --enable-gtk-cairo --with-java-home=/usr/lib/jvm/java-1.5.0-gcj-4.8-amd64/jre --enable-java-home --with-jvm-root-dir=/usr/lib/jvm/java-1.5.0-gcj-4.8-amd64 --with-jvm-jar-dir=/usr/lib/jvm-exports/java-1.5.0-gcj-4.8-amd64 --with-arch-directory=amd64 --with-ecj-jar=/usr/share/java/eclipse-ecj.jar --enable-objc-gc --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --with-tune=generic --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu -Thread model: posix -gcc version 4.8.4 (Ubuntu 4.8.4-2ubuntu1~14.04) -COMPILER_PATH=/usr/lib/gcc/x86_64-linux-gnu/4.8/:/usr/lib/gcc/x86_64-linux-gnu/4.8/:/usr/lib/gcc/x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/4.8/:/usr/lib/gcc/x86_64-linux-gnu/ -LIBRARY_PATH=/usr/lib/gcc/x86_64-linux-gnu/4.8/:/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../lib/:/lib/x86_64-linux-gnu/:/lib/../lib/:/usr/lib/x86_64-linux-gnu/:/usr/lib/../lib/:/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../:/lib/:/usr/lib/ -COLLECT_GCC_OPTIONS='-v' '-o' 'cmTryCompileExec3603593924' '-rdynamic' '-mtune=generic' '-march=x86-64' - /usr/lib/gcc/x86_64-linux-gnu/4.8/collect2 --sysroot=/ --build-id --eh-frame-hdr -m elf_x86_64 --hash-style=gnu --as-needed -export-dynamic -dynamic-linker /lib64/ld-linux-x86-64.so.2 -z relro -o cmTryCompileExec3603593924 /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/crt1.o /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/crti.o /usr/lib/gcc/x86_64-linux-gnu/4.8/crtbegin.o -L/usr/lib/gcc/x86_64-linux-gnu/4.8 -L/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu -L/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../lib -L/lib/x86_64-linux-gnu -L/lib/../lib -L/usr/lib/x86_64-linux-gnu -L/usr/lib/../lib -L/usr/lib/gcc/x86_64-linux-gnu/4.8/../../.. CMakeFiles/cmTryCompileExec3603593924.dir/CMakeCCompilerABI.c.o -lgcc --as-needed -lgcc_s --no-as-needed -lc -lgcc --as-needed -lgcc_s --no-as-needed /usr/lib/gcc/x86_64-linux-gnu/4.8/crtend.o /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/crtn.o -make[1]: Leaving directory `/home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/CMakeTmp' - - -Parsed C implicit link information from above output: - link line regex: [^( *|.*[/\])(ld|([^/\]+-)?ld|collect2)[^/\]*( |$)] - ignore line: [Change Dir: /home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/CMakeTmp] - ignore line: [] - ignore line: [Run Build Command:/usr/bin/make "cmTryCompileExec3603593924/fast"] - ignore line: [/usr/bin/make -f CMakeFiles/cmTryCompileExec3603593924.dir/build.make CMakeFiles/cmTryCompileExec3603593924.dir/build] - ignore line: [make[1]: Entering directory `/home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/CMakeTmp'] - ignore line: [/usr/bin/cmake -E cmake_progress_report /home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/CMakeTmp/CMakeFiles 1] - ignore line: [Building C object CMakeFiles/cmTryCompileExec3603593924.dir/CMakeCCompilerABI.c.o] - ignore line: [/usr/bin/cc -o CMakeFiles/cmTryCompileExec3603593924.dir/CMakeCCompilerABI.c.o -c /usr/share/cmake-2.8/Modules/CMakeCCompilerABI.c] - ignore line: [Linking C executable cmTryCompileExec3603593924] - ignore line: [/usr/bin/cmake -E cmake_link_script CMakeFiles/cmTryCompileExec3603593924.dir/link.txt --verbose=1] - ignore line: [/usr/bin/cc -v CMakeFiles/cmTryCompileExec3603593924.dir/CMakeCCompilerABI.c.o -o cmTryCompileExec3603593924 -rdynamic ] - ignore line: [Using built-in specs.] - ignore line: [COLLECT_GCC=/usr/bin/cc] - ignore line: [COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/4.8/lto-wrapper] - ignore line: [Target: x86_64-linux-gnu] - ignore line: [Configured with: ../src/configure -v --with-pkgversion='Ubuntu 4.8.4-2ubuntu1~14.04' --with-bugurl=file:///usr/share/doc/gcc-4.8/README.Bugs --enable-languages=c,c++,java,go,d,fortran,objc,obj-c++ --prefix=/usr --program-suffix=-4.8 --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --with-gxx-include-dir=/usr/include/c++/4.8 --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --enable-gnu-unique-object --disable-libmudflap --enable-plugin --with-system-zlib --disable-browser-plugin --enable-java-awt=gtk --enable-gtk-cairo --with-java-home=/usr/lib/jvm/java-1.5.0-gcj-4.8-amd64/jre --enable-java-home --with-jvm-root-dir=/usr/lib/jvm/java-1.5.0-gcj-4.8-amd64 --with-jvm-jar-dir=/usr/lib/jvm-exports/java-1.5.0-gcj-4.8-amd64 --with-arch-directory=amd64 --with-ecj-jar=/usr/share/java/eclipse-ecj.jar --enable-objc-gc --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --with-tune=generic --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu] - ignore line: [Thread model: posix] - ignore line: [gcc version 4.8.4 (Ubuntu 4.8.4-2ubuntu1~14.04) ] - ignore line: [COMPILER_PATH=/usr/lib/gcc/x86_64-linux-gnu/4.8/:/usr/lib/gcc/x86_64-linux-gnu/4.8/:/usr/lib/gcc/x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/4.8/:/usr/lib/gcc/x86_64-linux-gnu/] - ignore line: [LIBRARY_PATH=/usr/lib/gcc/x86_64-linux-gnu/4.8/:/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../lib/:/lib/x86_64-linux-gnu/:/lib/../lib/:/usr/lib/x86_64-linux-gnu/:/usr/lib/../lib/:/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../:/lib/:/usr/lib/] - ignore line: [COLLECT_GCC_OPTIONS='-v' '-o' 'cmTryCompileExec3603593924' '-rdynamic' '-mtune=generic' '-march=x86-64'] - link line: [ /usr/lib/gcc/x86_64-linux-gnu/4.8/collect2 --sysroot=/ --build-id --eh-frame-hdr -m elf_x86_64 --hash-style=gnu --as-needed -export-dynamic -dynamic-linker /lib64/ld-linux-x86-64.so.2 -z relro -o cmTryCompileExec3603593924 /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/crt1.o /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/crti.o /usr/lib/gcc/x86_64-linux-gnu/4.8/crtbegin.o -L/usr/lib/gcc/x86_64-linux-gnu/4.8 -L/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu -L/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../lib -L/lib/x86_64-linux-gnu -L/lib/../lib -L/usr/lib/x86_64-linux-gnu -L/usr/lib/../lib -L/usr/lib/gcc/x86_64-linux-gnu/4.8/../../.. CMakeFiles/cmTryCompileExec3603593924.dir/CMakeCCompilerABI.c.o -lgcc --as-needed -lgcc_s --no-as-needed -lc -lgcc --as-needed -lgcc_s --no-as-needed /usr/lib/gcc/x86_64-linux-gnu/4.8/crtend.o /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/crtn.o] - arg [/usr/lib/gcc/x86_64-linux-gnu/4.8/collect2] ==> ignore - arg [--sysroot=/] ==> ignore - arg [--build-id] ==> ignore - arg [--eh-frame-hdr] ==> ignore - arg [-m] ==> ignore - arg [elf_x86_64] ==> ignore - arg [--hash-style=gnu] ==> ignore - arg [--as-needed] ==> ignore - arg [-export-dynamic] ==> ignore - arg [-dynamic-linker] ==> ignore - arg [/lib64/ld-linux-x86-64.so.2] ==> ignore - arg [-zrelro] ==> ignore - arg [-o] ==> ignore - arg [cmTryCompileExec3603593924] ==> ignore - arg [/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/crt1.o] ==> ignore - arg [/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/crti.o] ==> ignore - arg [/usr/lib/gcc/x86_64-linux-gnu/4.8/crtbegin.o] ==> ignore - arg [-L/usr/lib/gcc/x86_64-linux-gnu/4.8] ==> dir [/usr/lib/gcc/x86_64-linux-gnu/4.8] - arg [-L/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu] ==> dir [/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu] - arg [-L/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../lib] ==> dir [/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../lib] - arg [-L/lib/x86_64-linux-gnu] ==> dir [/lib/x86_64-linux-gnu] - arg [-L/lib/../lib] ==> dir [/lib/../lib] - arg [-L/usr/lib/x86_64-linux-gnu] ==> dir [/usr/lib/x86_64-linux-gnu] - arg [-L/usr/lib/../lib] ==> dir [/usr/lib/../lib] - arg [-L/usr/lib/gcc/x86_64-linux-gnu/4.8/../../..] ==> dir [/usr/lib/gcc/x86_64-linux-gnu/4.8/../../..] - arg [CMakeFiles/cmTryCompileExec3603593924.dir/CMakeCCompilerABI.c.o] ==> ignore - arg [-lgcc] ==> lib [gcc] - arg [--as-needed] ==> ignore - arg [-lgcc_s] ==> lib [gcc_s] - arg [--no-as-needed] ==> ignore - arg [-lc] ==> lib [c] - arg [-lgcc] ==> lib [gcc] - arg [--as-needed] ==> ignore - arg [-lgcc_s] ==> lib [gcc_s] - arg [--no-as-needed] ==> ignore - arg [/usr/lib/gcc/x86_64-linux-gnu/4.8/crtend.o] ==> ignore - arg [/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/crtn.o] ==> ignore - remove lib [gcc] - remove lib [gcc_s] - remove lib [gcc] - remove lib [gcc_s] - collapse library dir [/usr/lib/gcc/x86_64-linux-gnu/4.8] ==> [/usr/lib/gcc/x86_64-linux-gnu/4.8] - collapse library dir [/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu] ==> [/usr/lib/x86_64-linux-gnu] - collapse library dir [/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../lib] ==> [/usr/lib] - collapse library dir [/lib/x86_64-linux-gnu] ==> [/lib/x86_64-linux-gnu] - collapse library dir [/lib/../lib] ==> [/lib] - collapse library dir [/usr/lib/x86_64-linux-gnu] ==> [/usr/lib/x86_64-linux-gnu] - collapse library dir [/usr/lib/../lib] ==> [/usr/lib] - collapse library dir [/usr/lib/gcc/x86_64-linux-gnu/4.8/../../..] ==> [/usr/lib] - implicit libs: [c] - implicit dirs: [/usr/lib/gcc/x86_64-linux-gnu/4.8;/usr/lib/x86_64-linux-gnu;/usr/lib;/lib/x86_64-linux-gnu;/lib] - implicit fwks: [] - - -Determining if the CXX compiler works passed with the following output: -Change Dir: /home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/CMakeTmp - -Run Build Command:/usr/bin/make "cmTryCompileExec997608794/fast" -/usr/bin/make -f CMakeFiles/cmTryCompileExec997608794.dir/build.make CMakeFiles/cmTryCompileExec997608794.dir/build -make[1]: Entering directory `/home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/CMakeTmp' -/usr/bin/cmake -E cmake_progress_report /home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/CMakeTmp/CMakeFiles 1 -Building CXX object CMakeFiles/cmTryCompileExec997608794.dir/testCXXCompiler.cxx.o -/usr/bin/c++ -o CMakeFiles/cmTryCompileExec997608794.dir/testCXXCompiler.cxx.o -c /home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/CMakeTmp/testCXXCompiler.cxx -Linking CXX executable cmTryCompileExec997608794 -/usr/bin/cmake -E cmake_link_script CMakeFiles/cmTryCompileExec997608794.dir/link.txt --verbose=1 -/usr/bin/c++ CMakeFiles/cmTryCompileExec997608794.dir/testCXXCompiler.cxx.o -o cmTryCompileExec997608794 -rdynamic -make[1]: Leaving directory `/home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/CMakeTmp' - - -Detecting CXX compiler ABI info compiled with the following output: -Change Dir: /home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/CMakeTmp - -Run Build Command:/usr/bin/make "cmTryCompileExec2573420878/fast" -/usr/bin/make -f CMakeFiles/cmTryCompileExec2573420878.dir/build.make CMakeFiles/cmTryCompileExec2573420878.dir/build -make[1]: Entering directory `/home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/CMakeTmp' -/usr/bin/cmake -E cmake_progress_report /home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/CMakeTmp/CMakeFiles 1 -Building CXX object CMakeFiles/cmTryCompileExec2573420878.dir/CMakeCXXCompilerABI.cpp.o -/usr/bin/c++ -o CMakeFiles/cmTryCompileExec2573420878.dir/CMakeCXXCompilerABI.cpp.o -c /usr/share/cmake-2.8/Modules/CMakeCXXCompilerABI.cpp -Linking CXX executable cmTryCompileExec2573420878 -/usr/bin/cmake -E cmake_link_script CMakeFiles/cmTryCompileExec2573420878.dir/link.txt --verbose=1 -/usr/bin/c++ -v CMakeFiles/cmTryCompileExec2573420878.dir/CMakeCXXCompilerABI.cpp.o -o cmTryCompileExec2573420878 -rdynamic -Using built-in specs. -COLLECT_GCC=/usr/bin/c++ -COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/4.8/lto-wrapper -Target: x86_64-linux-gnu -Configured with: ../src/configure -v --with-pkgversion='Ubuntu 4.8.4-2ubuntu1~14.04' --with-bugurl=file:///usr/share/doc/gcc-4.8/README.Bugs --enable-languages=c,c++,java,go,d,fortran,objc,obj-c++ --prefix=/usr --program-suffix=-4.8 --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --with-gxx-include-dir=/usr/include/c++/4.8 --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --enable-gnu-unique-object --disable-libmudflap --enable-plugin --with-system-zlib --disable-browser-plugin --enable-java-awt=gtk --enable-gtk-cairo --with-java-home=/usr/lib/jvm/java-1.5.0-gcj-4.8-amd64/jre --enable-java-home --with-jvm-root-dir=/usr/lib/jvm/java-1.5.0-gcj-4.8-amd64 --with-jvm-jar-dir=/usr/lib/jvm-exports/java-1.5.0-gcj-4.8-amd64 --with-arch-directory=amd64 --with-ecj-jar=/usr/share/java/eclipse-ecj.jar --enable-objc-gc --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --with-tune=generic --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu -Thread model: posix -gcc version 4.8.4 (Ubuntu 4.8.4-2ubuntu1~14.04) -COMPILER_PATH=/usr/lib/gcc/x86_64-linux-gnu/4.8/:/usr/lib/gcc/x86_64-linux-gnu/4.8/:/usr/lib/gcc/x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/4.8/:/usr/lib/gcc/x86_64-linux-gnu/ -LIBRARY_PATH=/usr/lib/gcc/x86_64-linux-gnu/4.8/:/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../lib/:/lib/x86_64-linux-gnu/:/lib/../lib/:/usr/lib/x86_64-linux-gnu/:/usr/lib/../lib/:/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../:/lib/:/usr/lib/ -COLLECT_GCC_OPTIONS='-v' '-o' 'cmTryCompileExec2573420878' '-rdynamic' '-shared-libgcc' '-mtune=generic' '-march=x86-64' - /usr/lib/gcc/x86_64-linux-gnu/4.8/collect2 --sysroot=/ --build-id --eh-frame-hdr -m elf_x86_64 --hash-style=gnu --as-needed -export-dynamic -dynamic-linker /lib64/ld-linux-x86-64.so.2 -z relro -o cmTryCompileExec2573420878 /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/crt1.o /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/crti.o /usr/lib/gcc/x86_64-linux-gnu/4.8/crtbegin.o -L/usr/lib/gcc/x86_64-linux-gnu/4.8 -L/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu -L/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../lib -L/lib/x86_64-linux-gnu -L/lib/../lib -L/usr/lib/x86_64-linux-gnu -L/usr/lib/../lib -L/usr/lib/gcc/x86_64-linux-gnu/4.8/../../.. CMakeFiles/cmTryCompileExec2573420878.dir/CMakeCXXCompilerABI.cpp.o -lstdc++ -lm -lgcc_s -lgcc -lc -lgcc_s -lgcc /usr/lib/gcc/x86_64-linux-gnu/4.8/crtend.o /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/crtn.o -make[1]: Leaving directory `/home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/CMakeTmp' - - -Parsed CXX implicit link information from above output: - link line regex: [^( *|.*[/\])(ld|([^/\]+-)?ld|collect2)[^/\]*( |$)] - ignore line: [Change Dir: /home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/CMakeTmp] - ignore line: [] - ignore line: [Run Build Command:/usr/bin/make "cmTryCompileExec2573420878/fast"] - ignore line: [/usr/bin/make -f CMakeFiles/cmTryCompileExec2573420878.dir/build.make CMakeFiles/cmTryCompileExec2573420878.dir/build] - ignore line: [make[1]: Entering directory `/home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/CMakeTmp'] - ignore line: [/usr/bin/cmake -E cmake_progress_report /home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/CMakeTmp/CMakeFiles 1] - ignore line: [Building CXX object CMakeFiles/cmTryCompileExec2573420878.dir/CMakeCXXCompilerABI.cpp.o] - ignore line: [/usr/bin/c++ -o CMakeFiles/cmTryCompileExec2573420878.dir/CMakeCXXCompilerABI.cpp.o -c /usr/share/cmake-2.8/Modules/CMakeCXXCompilerABI.cpp] - ignore line: [Linking CXX executable cmTryCompileExec2573420878] - ignore line: [/usr/bin/cmake -E cmake_link_script CMakeFiles/cmTryCompileExec2573420878.dir/link.txt --verbose=1] - ignore line: [/usr/bin/c++ -v CMakeFiles/cmTryCompileExec2573420878.dir/CMakeCXXCompilerABI.cpp.o -o cmTryCompileExec2573420878 -rdynamic ] - ignore line: [Using built-in specs.] - ignore line: [COLLECT_GCC=/usr/bin/c++] - ignore line: [COLLECT_LTO_WRAPPER=/usr/lib/gcc/x86_64-linux-gnu/4.8/lto-wrapper] - ignore line: [Target: x86_64-linux-gnu] - ignore line: [Configured with: ../src/configure -v --with-pkgversion='Ubuntu 4.8.4-2ubuntu1~14.04' --with-bugurl=file:///usr/share/doc/gcc-4.8/README.Bugs --enable-languages=c,c++,java,go,d,fortran,objc,obj-c++ --prefix=/usr --program-suffix=-4.8 --enable-shared --enable-linker-build-id --libexecdir=/usr/lib --without-included-gettext --enable-threads=posix --with-gxx-include-dir=/usr/include/c++/4.8 --libdir=/usr/lib --enable-nls --with-sysroot=/ --enable-clocale=gnu --enable-libstdcxx-debug --enable-libstdcxx-time=yes --enable-gnu-unique-object --disable-libmudflap --enable-plugin --with-system-zlib --disable-browser-plugin --enable-java-awt=gtk --enable-gtk-cairo --with-java-home=/usr/lib/jvm/java-1.5.0-gcj-4.8-amd64/jre --enable-java-home --with-jvm-root-dir=/usr/lib/jvm/java-1.5.0-gcj-4.8-amd64 --with-jvm-jar-dir=/usr/lib/jvm-exports/java-1.5.0-gcj-4.8-amd64 --with-arch-directory=amd64 --with-ecj-jar=/usr/share/java/eclipse-ecj.jar --enable-objc-gc --enable-multiarch --disable-werror --with-arch-32=i686 --with-abi=m64 --with-multilib-list=m32,m64,mx32 --with-tune=generic --enable-checking=release --build=x86_64-linux-gnu --host=x86_64-linux-gnu --target=x86_64-linux-gnu] - ignore line: [Thread model: posix] - ignore line: [gcc version 4.8.4 (Ubuntu 4.8.4-2ubuntu1~14.04) ] - ignore line: [COMPILER_PATH=/usr/lib/gcc/x86_64-linux-gnu/4.8/:/usr/lib/gcc/x86_64-linux-gnu/4.8/:/usr/lib/gcc/x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/4.8/:/usr/lib/gcc/x86_64-linux-gnu/] - ignore line: [LIBRARY_PATH=/usr/lib/gcc/x86_64-linux-gnu/4.8/:/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/:/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../lib/:/lib/x86_64-linux-gnu/:/lib/../lib/:/usr/lib/x86_64-linux-gnu/:/usr/lib/../lib/:/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../:/lib/:/usr/lib/] - ignore line: [COLLECT_GCC_OPTIONS='-v' '-o' 'cmTryCompileExec2573420878' '-rdynamic' '-shared-libgcc' '-mtune=generic' '-march=x86-64'] - link line: [ /usr/lib/gcc/x86_64-linux-gnu/4.8/collect2 --sysroot=/ --build-id --eh-frame-hdr -m elf_x86_64 --hash-style=gnu --as-needed -export-dynamic -dynamic-linker /lib64/ld-linux-x86-64.so.2 -z relro -o cmTryCompileExec2573420878 /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/crt1.o /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/crti.o /usr/lib/gcc/x86_64-linux-gnu/4.8/crtbegin.o -L/usr/lib/gcc/x86_64-linux-gnu/4.8 -L/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu -L/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../lib -L/lib/x86_64-linux-gnu -L/lib/../lib -L/usr/lib/x86_64-linux-gnu -L/usr/lib/../lib -L/usr/lib/gcc/x86_64-linux-gnu/4.8/../../.. CMakeFiles/cmTryCompileExec2573420878.dir/CMakeCXXCompilerABI.cpp.o -lstdc++ -lm -lgcc_s -lgcc -lc -lgcc_s -lgcc /usr/lib/gcc/x86_64-linux-gnu/4.8/crtend.o /usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/crtn.o] - arg [/usr/lib/gcc/x86_64-linux-gnu/4.8/collect2] ==> ignore - arg [--sysroot=/] ==> ignore - arg [--build-id] ==> ignore - arg [--eh-frame-hdr] ==> ignore - arg [-m] ==> ignore - arg [elf_x86_64] ==> ignore - arg [--hash-style=gnu] ==> ignore - arg [--as-needed] ==> ignore - arg [-export-dynamic] ==> ignore - arg [-dynamic-linker] ==> ignore - arg [/lib64/ld-linux-x86-64.so.2] ==> ignore - arg [-zrelro] ==> ignore - arg [-o] ==> ignore - arg [cmTryCompileExec2573420878] ==> ignore - arg [/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/crt1.o] ==> ignore - arg [/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/crti.o] ==> ignore - arg [/usr/lib/gcc/x86_64-linux-gnu/4.8/crtbegin.o] ==> ignore - arg [-L/usr/lib/gcc/x86_64-linux-gnu/4.8] ==> dir [/usr/lib/gcc/x86_64-linux-gnu/4.8] - arg [-L/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu] ==> dir [/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu] - arg [-L/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../lib] ==> dir [/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../lib] - arg [-L/lib/x86_64-linux-gnu] ==> dir [/lib/x86_64-linux-gnu] - arg [-L/lib/../lib] ==> dir [/lib/../lib] - arg [-L/usr/lib/x86_64-linux-gnu] ==> dir [/usr/lib/x86_64-linux-gnu] - arg [-L/usr/lib/../lib] ==> dir [/usr/lib/../lib] - arg [-L/usr/lib/gcc/x86_64-linux-gnu/4.8/../../..] ==> dir [/usr/lib/gcc/x86_64-linux-gnu/4.8/../../..] - arg [CMakeFiles/cmTryCompileExec2573420878.dir/CMakeCXXCompilerABI.cpp.o] ==> ignore - arg [-lstdc++] ==> lib [stdc++] - arg [-lm] ==> lib [m] - arg [-lgcc_s] ==> lib [gcc_s] - arg [-lgcc] ==> lib [gcc] - arg [-lc] ==> lib [c] - arg [-lgcc_s] ==> lib [gcc_s] - arg [-lgcc] ==> lib [gcc] - arg [/usr/lib/gcc/x86_64-linux-gnu/4.8/crtend.o] ==> ignore - arg [/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu/crtn.o] ==> ignore - remove lib [gcc_s] - remove lib [gcc] - remove lib [gcc_s] - remove lib [gcc] - collapse library dir [/usr/lib/gcc/x86_64-linux-gnu/4.8] ==> [/usr/lib/gcc/x86_64-linux-gnu/4.8] - collapse library dir [/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../x86_64-linux-gnu] ==> [/usr/lib/x86_64-linux-gnu] - collapse library dir [/usr/lib/gcc/x86_64-linux-gnu/4.8/../../../../lib] ==> [/usr/lib] - collapse library dir [/lib/x86_64-linux-gnu] ==> [/lib/x86_64-linux-gnu] - collapse library dir [/lib/../lib] ==> [/lib] - collapse library dir [/usr/lib/x86_64-linux-gnu] ==> [/usr/lib/x86_64-linux-gnu] - collapse library dir [/usr/lib/../lib] ==> [/usr/lib] - collapse library dir [/usr/lib/gcc/x86_64-linux-gnu/4.8/../../..] ==> [/usr/lib] - implicit libs: [stdc++;m;c] - implicit dirs: [/usr/lib/gcc/x86_64-linux-gnu/4.8;/usr/lib/x86_64-linux-gnu;/usr/lib;/lib/x86_64-linux-gnu;/lib] - implicit fwks: [] - - diff --git a/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/Makefile.cmake b/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/Makefile.cmake deleted file mode 100644 index 119272f1f1..0000000000 --- a/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/Makefile.cmake +++ /dev/null @@ -1,43 +0,0 @@ -# CMAKE generated file: DO NOT EDIT! -# Generated by "Unix Makefiles" Generator, CMake Version 2.8 - -# The generator used is: -SET(CMAKE_DEPENDS_GENERATOR "Unix Makefiles") - -# The top level Makefile was generated from the following files: -SET(CMAKE_MAKEFILE_DEPENDS - "CMakeCache.txt" - "../CMakeLists.txt" - "CMakeFiles/2.8.12.2/CMakeCCompiler.cmake" - "CMakeFiles/2.8.12.2/CMakeCXXCompiler.cmake" - "CMakeFiles/2.8.12.2/CMakeSystem.cmake" - "/usr/share/cmake-2.8/Modules/CMakeCInformation.cmake" - "/usr/share/cmake-2.8/Modules/CMakeCXXInformation.cmake" - "/usr/share/cmake-2.8/Modules/CMakeCommonLanguageInclude.cmake" - "/usr/share/cmake-2.8/Modules/CMakeGenericSystem.cmake" - "/usr/share/cmake-2.8/Modules/CMakeSystemSpecificInformation.cmake" - "/usr/share/cmake-2.8/Modules/Compiler/GNU-C.cmake" - "/usr/share/cmake-2.8/Modules/Compiler/GNU-CXX.cmake" - "/usr/share/cmake-2.8/Modules/Compiler/GNU.cmake" - "/usr/share/cmake-2.8/Modules/Platform/Linux-GNU-C.cmake" - "/usr/share/cmake-2.8/Modules/Platform/Linux-GNU-CXX.cmake" - "/usr/share/cmake-2.8/Modules/Platform/Linux-GNU.cmake" - "/usr/share/cmake-2.8/Modules/Platform/Linux.cmake" - "/usr/share/cmake-2.8/Modules/Platform/UnixPaths.cmake" - ) - -# The corresponding makefile is: -SET(CMAKE_MAKEFILE_OUTPUTS - "Makefile" - "CMakeFiles/cmake.check_cache" - ) - -# Byproducts of CMake generate step: -SET(CMAKE_MAKEFILE_PRODUCTS - "CMakeFiles/CMakeDirectoryInformation.cmake" - ) - -# Dependency information for all targets: -SET(CMAKE_DEPEND_INFO_FILES - "CMakeFiles/Si5351C.dir/DependInfo.cmake" - ) diff --git a/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/Makefile2 b/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/Makefile2 deleted file mode 100644 index 16016a9bd2..0000000000 --- a/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/Makefile2 +++ /dev/null @@ -1,102 +0,0 @@ -# CMAKE generated file: DO NOT EDIT! -# Generated by "Unix Makefiles" Generator, CMake Version 2.8 - -# Default target executed when no arguments are given to make. -default_target: all -.PHONY : default_target - -# The main recursive all target -all: -.PHONY : all - -# The main recursive preinstall target -preinstall: -.PHONY : preinstall - -#============================================================================= -# Special targets provided by cmake. - -# Disable implicit rules so canonical targets will work. -.SUFFIXES: - -# Remove some rules from gmake that .SUFFIXES does not remove. -SUFFIXES = - -.SUFFIXES: .hpux_make_needs_suffix_list - -# Suppress display of executed commands. -$(VERBOSE).SILENT: - -# A target that is always out of date. -cmake_force: -.PHONY : cmake_force - -#============================================================================= -# Set environment variables for the build. - -# The shell in which to execute make rules. -SHELL = /bin/sh - -# The CMake executable. -CMAKE_COMMAND = /usr/bin/cmake - -# The command to remove a file. -RM = /usr/bin/cmake -E remove -f - -# Escaping for special characters. -EQUALS = = - -# The program to use to edit the cache. -CMAKE_EDIT_COMMAND = /usr/bin/ccmake - -# The top-level source directory on which CMake was run. -CMAKE_SOURCE_DIR = /home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C - -# The top-level build directory on which CMake was run. -CMAKE_BINARY_DIR = /home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build - -#============================================================================= -# Target rules for target CMakeFiles/Si5351C.dir - -# All Build rule for target. -CMakeFiles/Si5351C.dir/all: - $(MAKE) -f CMakeFiles/Si5351C.dir/build.make CMakeFiles/Si5351C.dir/depend - $(MAKE) -f CMakeFiles/Si5351C.dir/build.make CMakeFiles/Si5351C.dir/build - $(CMAKE_COMMAND) -E cmake_progress_report /home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles 1 - @echo "Built target Si5351C" -.PHONY : CMakeFiles/Si5351C.dir/all - -# Include target in all. -all: CMakeFiles/Si5351C.dir/all -.PHONY : all - -# Build rule for subdir invocation for target. -CMakeFiles/Si5351C.dir/rule: cmake_check_build_system - $(CMAKE_COMMAND) -E cmake_progress_start /home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles 1 - $(MAKE) -f CMakeFiles/Makefile2 CMakeFiles/Si5351C.dir/all - $(CMAKE_COMMAND) -E cmake_progress_start /home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles 0 -.PHONY : CMakeFiles/Si5351C.dir/rule - -# Convenience name for target. -Si5351C: CMakeFiles/Si5351C.dir/rule -.PHONY : Si5351C - -# clean rule for target. -CMakeFiles/Si5351C.dir/clean: - $(MAKE) -f CMakeFiles/Si5351C.dir/build.make CMakeFiles/Si5351C.dir/clean -.PHONY : CMakeFiles/Si5351C.dir/clean - -# clean rule for target. -clean: CMakeFiles/Si5351C.dir/clean -.PHONY : clean - -#============================================================================= -# Special targets to cleanup operation of make. - -# Special rule to run CMake to check the build system integrity. -# No rule that depends on this can have commands that come from listfiles -# because they might be regenerated. -cmake_check_build_system: - $(CMAKE_COMMAND) -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 0 -.PHONY : cmake_check_build_system - diff --git a/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/Si5351C.dir/CXX.includecache b/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/Si5351C.dir/CXX.includecache deleted file mode 100644 index b84d7a1def..0000000000 --- a/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/Si5351C.dir/CXX.includecache +++ /dev/null @@ -1,8 +0,0 @@ -#IncludeRegexLine: ^[ ]*#[ ]*(include|import)[ ]*[<"]([^">]+)([">]) - -#IncludeRegexScan: ^.*$ - -#IncludeRegexComplain: ^$ - -#IncludeRegexTransform: - diff --git a/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/Si5351C.dir/DependInfo.cmake b/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/Si5351C.dir/DependInfo.cmake deleted file mode 100644 index 8fbd267efc..0000000000 --- a/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/Si5351C.dir/DependInfo.cmake +++ /dev/null @@ -1,22 +0,0 @@ -# The set of languages for which implicit dependencies are needed: -SET(CMAKE_DEPENDS_LANGUAGES - "CXX" - ) -# The set of files for implicit dependencies of each language: -SET(CMAKE_DEPENDS_CHECK_CXX - "/home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/Si5351C.cpp" "/home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/Si5351C.dir/Si5351C.o" - ) -SET(CMAKE_CXX_COMPILER_ID "GNU") - -# Targets to which this target links. -SET(CMAKE_TARGET_LINKED_INFO_FILES - ) - -# The include file search paths: -SET(CMAKE_C_TARGET_INCLUDE_PATH - "../../lms7002m" - ".." - ) -SET(CMAKE_CXX_TARGET_INCLUDE_PATH ${CMAKE_C_TARGET_INCLUDE_PATH}) -SET(CMAKE_Fortran_TARGET_INCLUDE_PATH ${CMAKE_C_TARGET_INCLUDE_PATH}) -SET(CMAKE_ASM_TARGET_INCLUDE_PATH ${CMAKE_C_TARGET_INCLUDE_PATH}) diff --git a/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/Si5351C.dir/Si5351C.o b/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/Si5351C.dir/Si5351C.o deleted file mode 100644 index 9c3483db4eb7c2c2bfd8b4bd29d4f87b7c961757..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 144184 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 DuMANa diff --git a/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/Si5351C.dir/build.make b/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/Si5351C.dir/build.make deleted file mode 100644 index 55f2ff4765..0000000000 --- a/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/Si5351C.dir/build.make +++ /dev/null @@ -1,106 +0,0 @@ -# CMAKE generated file: DO NOT EDIT! -# Generated by "Unix Makefiles" Generator, CMake Version 2.8 - -#============================================================================= -# Special targets provided by cmake. - -# Disable implicit rules so canonical targets will work. -.SUFFIXES: - -# Remove some rules from gmake that .SUFFIXES does not remove. -SUFFIXES = - -.SUFFIXES: .hpux_make_needs_suffix_list - -# Suppress display of executed commands. -$(VERBOSE).SILENT: - -# A target that is always out of date. -cmake_force: -.PHONY : cmake_force - -#============================================================================= -# Set environment variables for the build. - -# The shell in which to execute make rules. -SHELL = /bin/sh - -# The CMake executable. -CMAKE_COMMAND = /usr/bin/cmake - -# The command to remove a file. -RM = /usr/bin/cmake -E remove -f - -# Escaping for special characters. -EQUALS = = - -# The program to use to edit the cache. -CMAKE_EDIT_COMMAND = /usr/bin/ccmake - -# The top-level source directory on which CMake was run. -CMAKE_SOURCE_DIR = /home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C - -# The top-level build directory on which CMake was run. -CMAKE_BINARY_DIR = /home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build - -# Include any dependencies generated for this target. -include CMakeFiles/Si5351C.dir/depend.make - -# Include the progress variables for this target. -include CMakeFiles/Si5351C.dir/progress.make - -# Include the compile flags for this target's objects. -include CMakeFiles/Si5351C.dir/flags.make - -CMakeFiles/Si5351C.dir/Si5351C.o: CMakeFiles/Si5351C.dir/flags.make -CMakeFiles/Si5351C.dir/Si5351C.o: ../Si5351C.cpp - $(CMAKE_COMMAND) -E cmake_progress_report /home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles $(CMAKE_PROGRESS_1) - @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Building CXX object CMakeFiles/Si5351C.dir/Si5351C.o" - /usr/bin/c++ $(CXX_DEFINES) $(CXX_FLAGS) -o CMakeFiles/Si5351C.dir/Si5351C.o -c /home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/Si5351C.cpp - -CMakeFiles/Si5351C.dir/Si5351C.i: cmake_force - @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Preprocessing CXX source to CMakeFiles/Si5351C.dir/Si5351C.i" - /usr/bin/c++ $(CXX_DEFINES) $(CXX_FLAGS) -E /home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/Si5351C.cpp > CMakeFiles/Si5351C.dir/Si5351C.i - -CMakeFiles/Si5351C.dir/Si5351C.s: cmake_force - @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --green "Compiling CXX source to assembly CMakeFiles/Si5351C.dir/Si5351C.s" - /usr/bin/c++ $(CXX_DEFINES) $(CXX_FLAGS) -S /home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/Si5351C.cpp -o CMakeFiles/Si5351C.dir/Si5351C.s - -CMakeFiles/Si5351C.dir/Si5351C.o.requires: -.PHONY : CMakeFiles/Si5351C.dir/Si5351C.o.requires - -CMakeFiles/Si5351C.dir/Si5351C.o.provides: CMakeFiles/Si5351C.dir/Si5351C.o.requires - $(MAKE) -f CMakeFiles/Si5351C.dir/build.make CMakeFiles/Si5351C.dir/Si5351C.o.provides.build -.PHONY : CMakeFiles/Si5351C.dir/Si5351C.o.provides - -CMakeFiles/Si5351C.dir/Si5351C.o.provides.build: CMakeFiles/Si5351C.dir/Si5351C.o - -# Object files for target Si5351C -Si5351C_OBJECTS = \ -"CMakeFiles/Si5351C.dir/Si5351C.o" - -# External object files for target Si5351C -Si5351C_EXTERNAL_OBJECTS = - -libSi5351C.a: CMakeFiles/Si5351C.dir/Si5351C.o -libSi5351C.a: CMakeFiles/Si5351C.dir/build.make -libSi5351C.a: CMakeFiles/Si5351C.dir/link.txt - @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --red --bold "Linking CXX static library libSi5351C.a" - $(CMAKE_COMMAND) -P CMakeFiles/Si5351C.dir/cmake_clean_target.cmake - $(CMAKE_COMMAND) -E cmake_link_script CMakeFiles/Si5351C.dir/link.txt --verbose=$(VERBOSE) - -# Rule to build all files generated by this target. -CMakeFiles/Si5351C.dir/build: libSi5351C.a -.PHONY : CMakeFiles/Si5351C.dir/build - -CMakeFiles/Si5351C.dir/requires: CMakeFiles/Si5351C.dir/Si5351C.o.requires -.PHONY : CMakeFiles/Si5351C.dir/requires - -CMakeFiles/Si5351C.dir/clean: - $(CMAKE_COMMAND) -P CMakeFiles/Si5351C.dir/cmake_clean.cmake -.PHONY : CMakeFiles/Si5351C.dir/clean - -CMakeFiles/Si5351C.dir/depend: - cd /home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build && $(CMAKE_COMMAND) -E cmake_depends "Unix Makefiles" /home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C /home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C /home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build /home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build /home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/Si5351C.dir/DependInfo.cmake --color=$(COLOR) -.PHONY : CMakeFiles/Si5351C.dir/depend - diff --git a/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/Si5351C.dir/cmake_clean.cmake b/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/Si5351C.dir/cmake_clean.cmake deleted file mode 100644 index e300fd2668..0000000000 --- a/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/Si5351C.dir/cmake_clean.cmake +++ /dev/null @@ -1,10 +0,0 @@ -FILE(REMOVE_RECURSE - "CMakeFiles/Si5351C.dir/Si5351C.o" - "libSi5351C.pdb" - "libSi5351C.a" -) - -# Per-language clean rules from dependency scanning. -FOREACH(lang CXX) - INCLUDE(CMakeFiles/Si5351C.dir/cmake_clean_${lang}.cmake OPTIONAL) -ENDFOREACH(lang) diff --git a/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/Si5351C.dir/cmake_clean_target.cmake b/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/Si5351C.dir/cmake_clean_target.cmake deleted file mode 100644 index bb2fb4b00e..0000000000 --- a/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/Si5351C.dir/cmake_clean_target.cmake +++ /dev/null @@ -1,3 +0,0 @@ -FILE(REMOVE_RECURSE - "libSi5351C.a" -) diff --git a/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/Si5351C.dir/depend.internal b/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/Si5351C.dir/depend.internal deleted file mode 100644 index 2b377e7bc4..0000000000 --- a/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/Si5351C.dir/depend.internal +++ /dev/null @@ -1,6 +0,0 @@ -# CMAKE generated file: DO NOT EDIT! -# Generated by "Unix Makefiles" Generator, CMake Version 2.8 - -CMakeFiles/Si5351C.dir/Si5351C.o - /home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/Si5351C.cpp - /home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/Si5351C.h diff --git a/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/Si5351C.dir/depend.make b/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/Si5351C.dir/depend.make deleted file mode 100644 index f55fdb2688..0000000000 --- a/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/Si5351C.dir/depend.make +++ /dev/null @@ -1,6 +0,0 @@ -# CMAKE generated file: DO NOT EDIT! -# Generated by "Unix Makefiles" Generator, CMake Version 2.8 - -CMakeFiles/Si5351C.dir/Si5351C.o: ../Si5351C.cpp -CMakeFiles/Si5351C.dir/Si5351C.o: ../Si5351C.h - diff --git a/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/Si5351C.dir/flags.make b/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/Si5351C.dir/flags.make deleted file mode 100644 index 3515e5e131..0000000000 --- a/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/Si5351C.dir/flags.make +++ /dev/null @@ -1,8 +0,0 @@ -# CMAKE generated file: DO NOT EDIT! -# Generated by "Unix Makefiles" Generator, CMake Version 2.8 - -# compile CXX with /usr/bin/c++ -CXX_FLAGS = -std=c++11 -I/home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/../lms7002m -I/home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C - -CXX_DEFINES = - diff --git a/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/Si5351C.dir/link.txt b/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/Si5351C.dir/link.txt deleted file mode 100644 index 000b6e0ee0..0000000000 --- a/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/Si5351C.dir/link.txt +++ /dev/null @@ -1,2 +0,0 @@ -/usr/bin/ar cr libSi5351C.a CMakeFiles/Si5351C.dir/Si5351C.o -/usr/bin/ranlib libSi5351C.a diff --git a/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/Si5351C.dir/progress.make b/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/Si5351C.dir/progress.make deleted file mode 100644 index 781c7de277..0000000000 --- a/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/Si5351C.dir/progress.make +++ /dev/null @@ -1,2 +0,0 @@ -CMAKE_PROGRESS_1 = 1 - diff --git a/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/TargetDirectories.txt b/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/TargetDirectories.txt deleted file mode 100644 index 8bed4f4e60..0000000000 --- a/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/TargetDirectories.txt +++ /dev/null @@ -1 +0,0 @@ -/home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/Si5351C.dir diff --git a/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/cmake.check_cache b/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/cmake.check_cache deleted file mode 100644 index 3dccd73172..0000000000 --- a/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/cmake.check_cache +++ /dev/null @@ -1 +0,0 @@ -# This file is generated by cmake for dependency checking of the CMakeCache.txt file diff --git a/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/progress.marks b/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/progress.marks deleted file mode 100644 index d00491fd7e..0000000000 --- a/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/progress.marks +++ /dev/null @@ -1 +0,0 @@ -1 diff --git a/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/Makefile b/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/Makefile deleted file mode 100644 index 45a34a03b1..0000000000 --- a/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/Makefile +++ /dev/null @@ -1,157 +0,0 @@ -# CMAKE generated file: DO NOT EDIT! -# Generated by "Unix Makefiles" Generator, CMake Version 2.8 - -# Default target executed when no arguments are given to make. -default_target: all -.PHONY : default_target - -#============================================================================= -# Special targets provided by cmake. - -# Disable implicit rules so canonical targets will work. -.SUFFIXES: - -# Remove some rules from gmake that .SUFFIXES does not remove. -SUFFIXES = - -.SUFFIXES: .hpux_make_needs_suffix_list - -# Suppress display of executed commands. -$(VERBOSE).SILENT: - -# A target that is always out of date. -cmake_force: -.PHONY : cmake_force - -#============================================================================= -# Set environment variables for the build. - -# The shell in which to execute make rules. -SHELL = /bin/sh - -# The CMake executable. -CMAKE_COMMAND = /usr/bin/cmake - -# The command to remove a file. -RM = /usr/bin/cmake -E remove -f - -# Escaping for special characters. -EQUALS = = - -# The program to use to edit the cache. -CMAKE_EDIT_COMMAND = /usr/bin/ccmake - -# The top-level source directory on which CMake was run. -CMAKE_SOURCE_DIR = /home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C - -# The top-level build directory on which CMake was run. -CMAKE_BINARY_DIR = /home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build - -#============================================================================= -# Targets provided globally by CMake. - -# Special rule for the target edit_cache -edit_cache: - @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Running CMake cache editor..." - /usr/bin/ccmake -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) -.PHONY : edit_cache - -# Special rule for the target edit_cache -edit_cache/fast: edit_cache -.PHONY : edit_cache/fast - -# Special rule for the target rebuild_cache -rebuild_cache: - @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Running CMake to regenerate build system..." - /usr/bin/cmake -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) -.PHONY : rebuild_cache - -# Special rule for the target rebuild_cache -rebuild_cache/fast: rebuild_cache -.PHONY : rebuild_cache/fast - -# The main all target -all: cmake_check_build_system - $(CMAKE_COMMAND) -E cmake_progress_start /home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles /home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles/progress.marks - $(MAKE) -f CMakeFiles/Makefile2 all - $(CMAKE_COMMAND) -E cmake_progress_start /home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/CMakeFiles 0 -.PHONY : all - -# The main clean target -clean: - $(MAKE) -f CMakeFiles/Makefile2 clean -.PHONY : clean - -# The main clean target -clean/fast: clean -.PHONY : clean/fast - -# Prepare targets for installation. -preinstall: all - $(MAKE) -f CMakeFiles/Makefile2 preinstall -.PHONY : preinstall - -# Prepare targets for installation. -preinstall/fast: - $(MAKE) -f CMakeFiles/Makefile2 preinstall -.PHONY : preinstall/fast - -# clear depends -depend: - $(CMAKE_COMMAND) -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 1 -.PHONY : depend - -#============================================================================= -# Target rules for targets named Si5351C - -# Build rule for target. -Si5351C: cmake_check_build_system - $(MAKE) -f CMakeFiles/Makefile2 Si5351C -.PHONY : Si5351C - -# fast build rule for target. -Si5351C/fast: - $(MAKE) -f CMakeFiles/Si5351C.dir/build.make CMakeFiles/Si5351C.dir/build -.PHONY : Si5351C/fast - -# target to build an object file -Si5351C.o: - $(MAKE) -f CMakeFiles/Si5351C.dir/build.make CMakeFiles/Si5351C.dir/Si5351C.o -.PHONY : Si5351C.o - -# target to preprocess a source file -Si5351C.i: - $(MAKE) -f CMakeFiles/Si5351C.dir/build.make CMakeFiles/Si5351C.dir/Si5351C.i -.PHONY : Si5351C.i - -# target to generate assembly for a file -Si5351C.s: - $(MAKE) -f CMakeFiles/Si5351C.dir/build.make CMakeFiles/Si5351C.dir/Si5351C.s -.PHONY : Si5351C.s - -# Help Target -help: - @echo "The following are some of the valid targets for this Makefile:" - @echo "... all (the default if no target is provided)" - @echo "... clean" - @echo "... depend" - @echo "... Si5351C" - @echo "... edit_cache" - @echo "... rebuild_cache" - @echo "... Si5351C.o" - @echo "... Si5351C.i" - @echo "... Si5351C.s" -.PHONY : help - - - -#============================================================================= -# Special targets to cleanup operation of make. - -# Special rule to run CMake to check the build system integrity. -# No rule that depends on this can have commands that come from listfiles -# because they might be regenerated. -cmake_check_build_system: - $(CMAKE_COMMAND) -H$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 0 -.PHONY : cmake_check_build_system - diff --git a/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/cmake_install.cmake b/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/cmake_install.cmake deleted file mode 100644 index d7797d84e9..0000000000 --- a/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/cmake_install.cmake +++ /dev/null @@ -1,44 +0,0 @@ -# Install script for directory: /home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C - -# Set the install prefix -IF(NOT DEFINED CMAKE_INSTALL_PREFIX) - SET(CMAKE_INSTALL_PREFIX "/usr/local") -ENDIF(NOT DEFINED CMAKE_INSTALL_PREFIX) -STRING(REGEX REPLACE "/$" "" CMAKE_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}") - -# Set the install configuration name. -IF(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME) - IF(BUILD_TYPE) - STRING(REGEX REPLACE "^[^A-Za-z0-9_]+" "" - CMAKE_INSTALL_CONFIG_NAME "${BUILD_TYPE}") - ELSE(BUILD_TYPE) - SET(CMAKE_INSTALL_CONFIG_NAME "") - ENDIF(BUILD_TYPE) - MESSAGE(STATUS "Install configuration: \"${CMAKE_INSTALL_CONFIG_NAME}\"") -ENDIF(NOT DEFINED CMAKE_INSTALL_CONFIG_NAME) - -# Set the component getting installed. -IF(NOT CMAKE_INSTALL_COMPONENT) - IF(COMPONENT) - MESSAGE(STATUS "Install component: \"${COMPONENT}\"") - SET(CMAKE_INSTALL_COMPONENT "${COMPONENT}") - ELSE(COMPONENT) - SET(CMAKE_INSTALL_COMPONENT) - ENDIF(COMPONENT) -ENDIF(NOT CMAKE_INSTALL_COMPONENT) - -# Install shared libraries without execute permission? -IF(NOT DEFINED CMAKE_INSTALL_SO_NO_EXE) - SET(CMAKE_INSTALL_SO_NO_EXE "1") -ENDIF(NOT DEFINED CMAKE_INSTALL_SO_NO_EXE) - -IF(CMAKE_INSTALL_COMPONENT) - SET(CMAKE_INSTALL_MANIFEST "install_manifest_${CMAKE_INSTALL_COMPONENT}.txt") -ELSE(CMAKE_INSTALL_COMPONENT) - SET(CMAKE_INSTALL_MANIFEST "install_manifest.txt") -ENDIF(CMAKE_INSTALL_COMPONENT) - -FILE(WRITE "/home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/${CMAKE_INSTALL_MANIFEST}" "") -FOREACH(file ${CMAKE_INSTALL_MANIFEST_FILES}) - FILE(APPEND "/home/papillon/openairinterface5g/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/${CMAKE_INSTALL_MANIFEST}" "${file}\n") -ENDFOREACH(file) diff --git a/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/libSi5351C.a b/targets/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build/libSi5351C.a deleted file mode 100644 index bc5d760e0aedfec3c12ab319e446c9ce801c5bcc..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 162342 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 +#include +#include "lmsComms.h" +#include "INI.h" +#include +#include +#include +#include "LMS7002M_RegistersMap.h" + +#include +#include + +float_type LMS7002M::gVCO_frequency_table[3][2] = { { 3800, 5222 }, { 4961, 6754 }, {6306, 7714} }; +float_type LMS7002M::gCGEN_VCO_frequencies[2] = {2000, 2700}; + +///define for parameter enumeration if prefix might be needed +#define LMS7param(id) id + +//module addresses needs to be sorted in ascending order +const uint16_t LMS7002M::readOnlyRegisters[] = { 0x002F, 0x008C, 0x00A8, 0x00A9, 0x00AA, 0x00AB, 0x00AC, 0x0123, 0x0209, 0x020A, 0x020B, 0x040E, 0x040F }; +const uint16_t LMS7002M::readOnlyRegistersMasks[] = { 0x0000, 0x0FFF, 0x007F, 0x0000, 0x0000, 0x0000, 0x0000, 0x003F, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000 }; + +/** @brief Simple logging function to print status messages + @param text message to print + @param type message type for filtering specific information +*/ +void LMS7002M::Log(const char* text, LogType type) +{ + switch(type) + { + case LOG_INFO: + printf("%s\n", text); + break; + case LOG_WARNING: + printf("Warning: %s\n", text); + break; + case LOG_ERROR: + printf("ERROR: %s\n", text); + break; + case LOG_DATA: + printf("DATA: %s\n", text); + break; + } +} + +LMS7002M::LMS7002M() : controlPort(NULL), mRegistersMap(new LMS7002M_RegistersMap()) +{ + mRefClkSXR_MHz = 30.72; + mRefClkSXT_MHz = 30.72; +} + +/** @brief Creates LMS7002M main control object, it requires LMScomms to communicate with chip + @param controlPort data connection for controlling LMS7002 chip registers +*/ +LMS7002M::LMS7002M(LMScomms* controlPort) : + controlPort(controlPort), mRegistersMap(new LMS7002M_RegistersMap()) +{ + mRefClkSXR_MHz = 30.72; + mRefClkSXT_MHz = 30.72; + + //memory intervals for registers tests and calibration algorithms + MemorySectionAddresses[LimeLight][0] = 0x0020; + MemorySectionAddresses[LimeLight][1] = 0x002F; + MemorySectionAddresses[EN_DIR][0] = 0x0081; + MemorySectionAddresses[EN_DIR][1] = 0x0081; + MemorySectionAddresses[AFE][0] = 0x0082; + MemorySectionAddresses[AFE][1] = 0x0082; + MemorySectionAddresses[BIAS][0] = 0x0084; + MemorySectionAddresses[BIAS][1] = 0x0084; + MemorySectionAddresses[XBUF][0] = 0x0085; + MemorySectionAddresses[XBUF][1] = 0x0085; + MemorySectionAddresses[CGEN][0] = 0x0086; + MemorySectionAddresses[CGEN][1] = 0x008C; + MemorySectionAddresses[LDO][0] = 0x0092; + MemorySectionAddresses[LDO][1] = 0x00A7; + MemorySectionAddresses[BIST][0] = 0x00A8; + MemorySectionAddresses[BIST][1] = 0x00AC; + MemorySectionAddresses[CDS][0] = 0x00AD; + MemorySectionAddresses[CDS][1] = 0x00AE; + MemorySectionAddresses[TRF][0] = 0x0100; + MemorySectionAddresses[TRF][1] = 0x0104; + MemorySectionAddresses[TBB][0] = 0x0105; + MemorySectionAddresses[TBB][1] = 0x010A; + MemorySectionAddresses[RFE][0] = 0x010C; + MemorySectionAddresses[RFE][1] = 0x0114; + MemorySectionAddresses[RBB][0] = 0x0115; + MemorySectionAddresses[RBB][1] = 0x011A; + MemorySectionAddresses[SX][0] = 0x011C; + MemorySectionAddresses[SX][1] = 0x0124; + MemorySectionAddresses[TxTSP][0] = 0x0200; + MemorySectionAddresses[TxTSP][1] = 0x020C; + MemorySectionAddresses[TxNCO][0] = 0x0240; + MemorySectionAddresses[TxNCO][1] = 0x0261; + MemorySectionAddresses[TxGFIR1][0] = 0x0280; + MemorySectionAddresses[TxGFIR1][1] = 0x02A7; + MemorySectionAddresses[TxGFIR2][0] = 0x02C0; + MemorySectionAddresses[TxGFIR2][1] = 0x02E7; + MemorySectionAddresses[TxGFIR3a][0] = 0x0300; + MemorySectionAddresses[TxGFIR3a][1] = 0x0327; + MemorySectionAddresses[TxGFIR3b][0] = 0x0340; + MemorySectionAddresses[TxGFIR3b][1] = 0x0367; + MemorySectionAddresses[TxGFIR3c][0] = 0x0380; + MemorySectionAddresses[TxGFIR3c][1] = 0x03A7; + MemorySectionAddresses[RxTSP][0] = 0x0400; + MemorySectionAddresses[RxTSP][1] = 0x040F; + MemorySectionAddresses[RxNCO][0] = 0x0440; + MemorySectionAddresses[RxNCO][1] = 0x0461; + MemorySectionAddresses[RxGFIR1][0] = 0x0480; + MemorySectionAddresses[RxGFIR1][1] = 0x04A7; + MemorySectionAddresses[RxGFIR2][0] = 0x04C0; + MemorySectionAddresses[RxGFIR2][1] = 0x04E7; + MemorySectionAddresses[RxGFIR3a][0] = 0x0500; + MemorySectionAddresses[RxGFIR3a][1] = 0x0527; + MemorySectionAddresses[RxGFIR3b][0] = 0x0540; + MemorySectionAddresses[RxGFIR3b][1] = 0x0567; + MemorySectionAddresses[RxGFIR3c][0] = 0x0580; + MemorySectionAddresses[RxGFIR3c][1] = 0x05A7; + + mRegistersMap->InitializeDefaultValues(LMS7parameterList); +} + +LMS7002M::~LMS7002M() +{ + +} + +/** @brief Sends reset signal to chip, after reset enables B channel controls + @return 0-success, other-failure +*/ +liblms7_status LMS7002M::ResetChip() +{ + if (controlPort == NULL) + return LIBLMS7_NO_CONNECTION_MANAGER; + if (controlPort->IsOpen() == false) + return LIBLMS7_NOT_CONNECTED; + + LMScomms::GenericPacket pkt; + pkt.cmd = CMD_LMS7002_RST; + pkt.outBuffer.push_back(LMS_RST_PULSE); + controlPort->TransferPacket(pkt); + if (pkt.status == STATUS_COMPLETED_CMD) + { + Modify_SPI_Reg_bits(LMS7param(MIMO_SISO), 0); //enable B channel after reset + return LIBLMS7_SUCCESS; + } + else + return LIBLMS7_FAILURE; +} + +liblms7_status LMS7002M::LoadConfigLegacyFile(const char* filename) +{ + ifstream f(filename); + if (f.good() == false) //file not found + { + f.close(); + return LIBLMS7_FILE_NOT_FOUND; + } + f.close(); + uint16_t addr = 0; + uint16_t value = 0; + uint8_t ch = (uint8_t)Get_SPI_Reg_bits(LMS7param(MAC)); //remember used channel + liblms7_status status; + typedef INI ini_t; + ini_t parser(filename, true); + if (parser.select("FILE INFO") == false) + return LIBLMS7_FILE_INVALID_FORMAT; + + string type = ""; + type = parser.get("type", "undefined"); + stringstream ss; + if (type.find("LMS7002 configuration") == string::npos) + { + ss << "File " << filename << " not recognized" << endl; + return LIBLMS7_FILE_INVALID_FORMAT; + } + + int fileVersion = 0; + fileVersion = parser.get("version", 0); + + vector addrToWrite; + vector dataToWrite; + if (fileVersion == 1) + { + if (parser.select("Reference clocks")) + { + mRefClkSXR_MHz = parser.get("SXR reference frequency MHz", 30.72); + mRefClkSXT_MHz = parser.get("SXT reference frequency MHz", 30.72); + } + + if (parser.select("LMS7002 registers ch.A") == true) + { + ini_t::sectionsit_t section = parser.sections.find("LMS7002 registers ch.A"); + + uint16_t x0020_value = 0; + Modify_SPI_Reg_bits(LMS7param(MAC), 1); //select A channel + for (ini_t::keysit_t pairs = section->second->begin(); pairs != section->second->end(); pairs++) + { + sscanf(pairs->first.c_str(), "%hx", &addr); + sscanf(pairs->second.c_str(), "%hx", &value); + if (addr == LMS7param(MAC).address) //skip register containing channel selection + { + x0020_value = value; + continue; + } + addrToWrite.push_back(addr); + dataToWrite.push_back(value); + } + status = SPI_write_batch(&addrToWrite[0], &dataToWrite[0], addrToWrite.size()); + if (status != LIBLMS7_SUCCESS && status != LIBLMS7_NOT_CONNECTED) + return status; + + //parse FCW or PHO + if (parser.select("NCO Rx ch.A") == true) + { + char varname[64]; + int mode = Get_SPI_Reg_bits(LMS7param(MODE_RX)); + if (mode == 0) //FCW + { + for (int i = 0; i < 16; ++i) + { + sprintf(varname, "FCW%02i", i); + SetNCOFrequency(LMS7002M::Rx, i, parser.get(varname, 0.0)); + } + } + else + { + for (int i = 0; i < 16; ++i) + { + sprintf(varname, "PHO%02i", i); + SetNCOPhaseOffset(LMS7002M::Rx, i, parser.get(varname, 0.0)); + } + } + } + if (parser.select("NCO Tx ch.A") == true) + { + char varname[64]; + int mode = Get_SPI_Reg_bits(LMS7param(MODE_TX)); + if (mode == 0) //FCW + { + for (int i = 0; i < 16; ++i) + { + sprintf(varname, "FCW%02i", i); + SetNCOFrequency(LMS7002M::Tx, i, parser.get(varname, 0.0)); + } + } + else + { + for (int i = 0; i < 16; ++i) + { + sprintf(varname, "PHO%02i", i); + SetNCOPhaseOffset(LMS7002M::Tx, i, parser.get(varname, 0.0)); + } + } + } + status = SPI_write(0x0020, x0020_value); + if (status != LIBLMS7_SUCCESS && status != LIBLMS7_NOT_CONNECTED) + return status; + } + + Modify_SPI_Reg_bits(LMS7param(MAC), 2); + + if (parser.select("LMS7002 registers ch.B") == true) + { + addrToWrite.clear(); + dataToWrite.clear(); + ini_t::sectionsit_t section = parser.sections.find("LMS7002 registers ch.B"); + for (ini_t::keysit_t pairs = section->second->begin(); pairs != section->second->end(); pairs++) + { + sscanf(pairs->first.c_str(), "%hx", &addr); + sscanf(pairs->second.c_str(), "%hx", &value); + addrToWrite.push_back(addr); + dataToWrite.push_back(value); + } + Modify_SPI_Reg_bits(LMS7param(MAC), 2); //select B channel + status = SPI_write_batch(&addrToWrite[0], &dataToWrite[0], addrToWrite.size()); + if (status != LIBLMS7_SUCCESS && status != LIBLMS7_NOT_CONNECTED) + return status; + + //parse FCW or PHO + if (parser.select("NCO Rx ch.B") == true) + { + char varname[64]; + int mode = Get_SPI_Reg_bits(LMS7param(MODE_RX)); + if (mode == 0) //FCW + { + for (int i = 0; i < 16; ++i) + { + sprintf(varname, "FCW%02i", i); + SetNCOFrequency(LMS7002M::Rx, i, parser.get(varname, 0.0)); + } + } + else + { + for (int i = 0; i < 16; ++i) + { + sprintf(varname, "PHO%02i", i); + SetNCOPhaseOffset(LMS7002M::Rx, i, parser.get(varname, 0.0)); + } + } + } + if (parser.select("NCO Tx ch.A") == true) + { + char varname[64]; + int mode = Get_SPI_Reg_bits(LMS7param(MODE_TX)); + if (mode == 0) //FCW + { + for (int i = 0; i < 16; ++i) + { + sprintf(varname, "FCW%02i", i); + SetNCOFrequency(LMS7002M::Tx, i, parser.get(varname, 0.0)); + } + } + else + { + for (int i = 0; i < 16; ++i) + { + sprintf(varname, "PHO%02i", i); + SetNCOPhaseOffset(LMS7002M::Tx, i, parser.get(varname, 0.0)); + } + } + } + } + Modify_SPI_Reg_bits(LMS7param(MAC), ch); + return LIBLMS7_SUCCESS; + } + else + return LIBLMS7_FILE_INVALID_FORMAT; + return LIBLMS7_FAILURE; +} + +/** @brief Reads configuration file and uploads registers to chip + @param filename Configuration source file + @return 0-success, other-failure +*/ +liblms7_status LMS7002M::LoadConfig(const char* filename) +{ + ifstream f(filename); + if (f.good() == false) //file not found + { + f.close(); + return LIBLMS7_FILE_NOT_FOUND; + } + f.close(); + uint16_t addr = 0; + uint16_t value = 0; + uint8_t ch = (uint8_t)Get_SPI_Reg_bits(LMS7param(MAC)); //remember used channel + + liblms7_status status; + typedef INI ini_t; + ini_t parser(filename, true); + if (parser.select("file_info") == false) + { + //try loading as legacy format + status = LoadConfigLegacyFile(filename); + Modify_SPI_Reg_bits(MAC, 1); + return status; + } + string type = ""; + type = parser.get("type", "undefined"); + stringstream ss; + if (type.find("lms7002m_minimal_config") == string::npos) + { + ss << "File " << filename << " not recognized" << endl; + return LIBLMS7_FILE_INVALID_FORMAT; + } + + int fileVersion = 0; + fileVersion = parser.get("version", 0); + + vector addrToWrite; + vector dataToWrite; + + if (fileVersion == 1) + { + if(parser.select("lms7002_registers_a") == true) + { + ini_t::sectionsit_t section = parser.sections.find("lms7002_registers_a"); + + uint16_t x0020_value = 0; + Modify_SPI_Reg_bits(LMS7param(MAC), 1); //select A channel + for (ini_t::keysit_t pairs = section->second->begin(); pairs != section->second->end(); pairs++) + { + sscanf(pairs->first.c_str(), "%hx", &addr); + sscanf(pairs->second.c_str(), "%hx", &value); + if (addr == LMS7param(MAC).address) //skip register containing channel selection + { + x0020_value = value; + continue; + } + addrToWrite.push_back(addr); + dataToWrite.push_back(value); + } + status = SPI_write_batch(&addrToWrite[0], &dataToWrite[0], addrToWrite.size()); + if (status != LIBLMS7_SUCCESS && status != LIBLMS7_NOT_CONNECTED) + return status; + status = SPI_write(0x0020, x0020_value); + if (status != LIBLMS7_SUCCESS && status != LIBLMS7_NOT_CONNECTED) + return status; + Modify_SPI_Reg_bits(LMS7param(MAC), 2); + if (status != LIBLMS7_SUCCESS && status != LIBLMS7_NOT_CONNECTED) + return status; + } + + if (parser.select("lms7002_registers_b") == true) + { + addrToWrite.clear(); + dataToWrite.clear(); + ini_t::sectionsit_t section = parser.sections.find("lms7002_registers_b"); + for (ini_t::keysit_t pairs = section->second->begin(); pairs != section->second->end(); pairs++) + { + sscanf(pairs->first.c_str(), "%hx", &addr); + sscanf(pairs->second.c_str(), "%hx", &value); + addrToWrite.push_back(addr); + dataToWrite.push_back(value); + } + Modify_SPI_Reg_bits(LMS7param(MAC), 2); //select B channel + status = SPI_write_batch(&addrToWrite[0], &dataToWrite[0], addrToWrite.size()); + if (status != LIBLMS7_SUCCESS && status != LIBLMS7_NOT_CONNECTED) + return status; + } + Modify_SPI_Reg_bits(LMS7param(MAC), ch); + + parser.select("reference_clocks"); + mRefClkSXR_MHz = parser.get("sxr_ref_clk_mhz", 30.72); + mRefClkSXT_MHz = parser.get("sxt_ref_clk_mhz", 30.72); + } + + Modify_SPI_Reg_bits(MAC, 1); + if (controlPort == NULL) + return LIBLMS7_NO_CONNECTION_MANAGER; + if (controlPort->IsOpen() == false) + return LIBLMS7_NOT_CONNECTED; + return LIBLMS7_SUCCESS; +} + +/** @brief Reads all registers from chip and saves to file + @param filename destination filename + @return 0-success, other failure +*/ +liblms7_status LMS7002M::SaveConfig(const char* filename) +{ + liblms7_status status; + typedef INI<> ini_t; + ini_t parser(filename, true); + parser.create("file_info"); + parser.set("type", "lms7002m_minimal_config"); + parser.set("version", 1); + + char addr[80]; + char value[80]; + + uint8_t ch = (uint8_t)Get_SPI_Reg_bits(LMS7param(MAC)); + + vector addrToRead; + for (uint8_t i = 0; i < MEMORY_SECTIONS_COUNT; ++i) + for (uint16_t addr = MemorySectionAddresses[i][0]; addr <= MemorySectionAddresses[i][1]; ++addr) + addrToRead.push_back(addr); + vector dataReceived; + dataReceived.resize(addrToRead.size(), 0); + + parser.create("lms7002_registers_a"); + Modify_SPI_Reg_bits(LMS7param(MAC), 1); + for (uint16_t i = 0; i < addrToRead.size(); ++i) + { + dataReceived[i] = Get_SPI_Reg_bits(addrToRead[i], 15, 0, false); + sprintf(addr, "0x%04X", addrToRead[i]); + sprintf(value, "0x%04X", dataReceived[i]); + parser.set(addr, value); + } + + parser.create("lms7002_registers_b"); + addrToRead.clear(); //add only B channel addresses + for (uint8_t i = 0; i < MEMORY_SECTIONS_COUNT; ++i) + for (uint16_t addr = MemorySectionAddresses[i][0]; addr <= MemorySectionAddresses[i][1]; ++addr) + if (addr >= 0x0100) + addrToRead.push_back(addr); + + Modify_SPI_Reg_bits(LMS7param(MAC), 2); + for (uint16_t i = 0; i < addrToRead.size(); ++i) + { + dataReceived[i] = Get_SPI_Reg_bits(addrToRead[i], 15, 0, false); + sprintf(addr, "0x%04X", addrToRead[i]); + sprintf(value, "0x%04X", dataReceived[i]); + parser.set(addr, value); + } + + Modify_SPI_Reg_bits(LMS7param(MAC), ch); //retore previously used channel + + parser.create("reference_clocks"); + parser.set("sxt_ref_clk_mhz", mRefClkSXT_MHz); + parser.set("sxr_ref_clk_mhz", mRefClkSXR_MHz); + parser.save(filename); + return LIBLMS7_SUCCESS; +} + +/** @brief Returns reference clock in MHz used for SXT or SXR + @param Tx transmitter or receiver selection +*/ +float_type LMS7002M::GetReferenceClk_SX(bool tx) +{ + return tx ? mRefClkSXT_MHz : mRefClkSXR_MHz; +} + +/** @return Current CLKGEN frequency in MHz + Returned frequency depends on reference clock used for Receiver +*/ +float_type LMS7002M::GetFrequencyCGEN_MHz() +{ + float_type dMul = (mRefClkSXR_MHz/2.0)/(Get_SPI_Reg_bits(LMS7param(DIV_OUTCH_CGEN))+1); //DIV_OUTCH_CGEN + uint16_t gINT = Get_SPI_Reg_bits(0x0088, 13, 0); //read whole register to reduce SPI transfers + uint32_t gFRAC = ((gINT & 0xF) * 65536) | Get_SPI_Reg_bits(0x0087, 15, 0); + return dMul * (((gINT>>4) + 1 + gFRAC/1048576.0)); +} + +/** @brief Returns TSP reference frequency + @param tx TxTSP or RxTSP selection + @return TSP reference frequency in MHz +*/ +float_type LMS7002M::GetReferenceClk_TSP_MHz(bool tx) +{ + float_type cgenFreq = GetFrequencyCGEN_MHz(); + float_type clklfreq = cgenFreq/pow(2.0, Get_SPI_Reg_bits(LMS7param(CLKH_OV_CLKL_CGEN))); + if(Get_SPI_Reg_bits(LMS7param(EN_ADCCLKH_CLKGN)) == 0) + return tx ? clklfreq : cgenFreq/4.0; + else + return tx ? cgenFreq : clklfreq/4.0; +} + +/** @brief Sets CLKGEN frequency, calculations use receiver'r reference clock + @param freq_MHz desired frequency in MHz + @return 0-succes, other-cannot deliver desired frequency +*/ +liblms7_status LMS7002M::SetFrequencyCGEN(const float_type freq_MHz) +{ + float_type dFvco; + float_type dFrac; + int16_t iHdiv; + + //VCO frequency selection according to F_CLKH + iHdiv = (int16_t)((gCGEN_VCO_frequencies[1]/ 2) / freq_MHz) - 1; + dFvco = 2*(iHdiv+1) * freq_MHz; + + //Integer division + uint16_t gINT = (uint16_t)(dFvco/mRefClkSXR_MHz - 1); + + //Fractional division + dFrac = dFvco/mRefClkSXR_MHz - (uint32_t)(dFvco/mRefClkSXR_MHz); + uint32_t gFRAC = (uint32_t)(dFrac * 1048576); + + Modify_SPI_Reg_bits(LMS7param(INT_SDM_CGEN), gINT); //INT_SDM_CGEN + Modify_SPI_Reg_bits(0x0087, 15, 0, gFRAC&0xFFFF); //INT_SDM_CGEN[15:0] + Modify_SPI_Reg_bits(0x0088, 3, 0, gFRAC>>16); //INT_SDM_CGEN[19:16] + Modify_SPI_Reg_bits(LMS7param(DIV_OUTCH_CGEN), iHdiv); //DIV_OUTCH_CGEN + + return TuneVCO(VCO_CGEN); +} + +/** @brief Performs VCO tuning operations for CLKGEN, SXR, SXT modules + @param module module selection for tuning 0-cgen, 1-SXR, 2-SXT + @return 0-success, other-failure +*/ +liblms7_status LMS7002M::TuneVCO(VCO_Module module) // 0-cgen, 1-SXR, 2-SXT +{ + if (controlPort == NULL) + return LIBLMS7_NO_CONNECTION_MANAGER; + if (controlPort->IsOpen() == false) + return LIBLMS7_NOT_CONNECTED; + int8_t i; + uint8_t cmphl; //comparators + int16_t csw_lowest = -1; + uint16_t addrVCOpd; // VCO power down address + uint16_t addrCSW_VCO; + uint16_t addrCMP; //comparator address + uint8_t lsb; //SWC lsb index + uint8_t msb; //SWC msb index + + uint8_t ch = (uint8_t)Get_SPI_Reg_bits(LMS7param(MAC)); //remember used channel + + if(module != VCO_CGEN) //set addresses to SX module + { + Modify_SPI_Reg_bits(LMS7param(MAC), module); + addrVCOpd = LMS7param(PD_VCO).address; + addrCSW_VCO = LMS7param(CSW_VCO).address; + lsb = LMS7param(CSW_VCO).lsb; + msb = LMS7param(CSW_VCO).msb; + addrCMP = LMS7param(VCO_CMPHO).address; + } + else //set addresses to CGEN module + { + addrVCOpd = LMS7param(PD_VCO_CGEN).address; + addrCSW_VCO = LMS7param(CSW_VCO_CGEN).address; + lsb = LMS7param(CSW_VCO_CGEN).lsb; + msb = LMS7param(CSW_VCO_CGEN).msb; + addrCMP = LMS7param(VCO_CMPHO_CGEN).address; + } + // Initialization + Modify_SPI_Reg_bits (addrVCOpd, 2, 1, 0); //activate VCO and comparator + if (Get_SPI_Reg_bits(addrVCOpd, 2, 1) != 0) + return LIBLMS7_VCO_IS_POWERED_DOWN; + if(module == VCO_CGEN) + Modify_SPI_Reg_bits(LMS7param(SPDUP_VCO_CGEN), 1); //SHORT_NOISEFIL=1 SPDUP_VCO_ Short the noise filter resistor to speed up the settling time + else + Modify_SPI_Reg_bits(LMS7param(SPDUP_VCO), 1); //SHORT_NOISEFIL=1 SPDUP_VCO_ Short the noise filter resistor to speed up the settling time + Modify_SPI_Reg_bits (addrCSW_VCO , msb, lsb , 0); //Set SWC_VCO<7:0>=<00000000> + + i=7; + while(i>=0) + { + Modify_SPI_Reg_bits (addrCSW_VCO, lsb + i, lsb + i, 1); // CSW_VCO=1 + std::this_thread::sleep_for(std::chrono::milliseconds(5)); + cmphl = (uint8_t)Get_SPI_Reg_bits(addrCMP, 13, 12); + if ( (cmphl&0x01) == 1) // reduce CSW + Modify_SPI_Reg_bits (addrCSW_VCO, lsb + i, lsb + i, 0); // CSW_VCO=0 + if( cmphl == 2 && csw_lowest < 0) + csw_lowest = Get_SPI_Reg_bits(addrCSW_VCO, msb, lsb); + --i; + } + if(csw_lowest >= 0) + { + uint16_t csw_highest = Get_SPI_Reg_bits(addrCSW_VCO, msb, lsb); + if(csw_lowest == csw_highest) + { + while(csw_lowest>=0) + { + Modify_SPI_Reg_bits(addrCSW_VCO, msb, lsb, csw_lowest); + std::this_thread::sleep_for(std::chrono::milliseconds(5)); + if(Get_SPI_Reg_bits(addrCMP, 13, 12) == 0) + { + ++csw_lowest; + break; + } + else + --csw_lowest; + } + } + Modify_SPI_Reg_bits(addrCSW_VCO, msb, lsb, csw_lowest+(csw_highest-csw_lowest)/2); + } + if (module == VCO_CGEN) + Modify_SPI_Reg_bits(LMS7param(SPDUP_VCO_CGEN), 0); //SHORT_NOISEFIL=1 SPDUP_VCO_ Short the noise filter resistor to speed up the settling time + else + Modify_SPI_Reg_bits(LMS7param(SPDUP_VCO), 0); //SHORT_NOISEFIL=1 SPDUP_VCO_ Short the noise filter resistor to speed up the settling time + cmphl = (uint8_t)Get_SPI_Reg_bits(addrCMP, 13, 12); + Modify_SPI_Reg_bits(LMS7param(MAC), ch); //restore previously used channel + if(cmphl == 2) + return LIBLMS7_SUCCESS; + else + return LIBLMS7_FAILURE; +} + +/** @brief Returns given parameter value from chip register + @param param LMS7002M control parameter + @param fromChip read directly from chip + @return parameter value +*/ +uint16_t LMS7002M::Get_SPI_Reg_bits(const LMS7Parameter ¶m, bool fromChip) +{ + return Get_SPI_Reg_bits(param.address, param.msb, param.lsb, fromChip); +} + +/** @brief Returns given parameter value from chip register + @param address register address + @param msb most significant bit index + @param lsb least significant bit index + @param fromChip read directly from chip + @return register bits from selected interval, shifted to right by lsb bits +*/ +uint16_t LMS7002M::Get_SPI_Reg_bits(uint16_t address, uint8_t msb, uint8_t lsb, bool fromChip) +{ + return (SPI_read(address, fromChip) & (~(~0<<(msb+1)))) >> lsb; //shift bits to LSB +} + +/** @brief Change given parameter value + @param param LMS7002M control parameter + @param fromChip read initial value directly from chip + @param value new parameter value +*/ +liblms7_status LMS7002M::Modify_SPI_Reg_bits(const LMS7Parameter ¶m, const uint16_t value, bool fromChip) +{ + return Modify_SPI_Reg_bits(param.address, param.msb, param.lsb, value, fromChip); +} + +/** @brief Change given parameter value + @param address register address + @param value new bits value, the value is shifted left by lsb bits + @param fromChip read initial value directly from chip +*/ +liblms7_status LMS7002M::Modify_SPI_Reg_bits(const uint16_t address, const uint8_t msb, const uint8_t lsb, const uint16_t value, bool fromChip) +{ + uint16_t spiDataReg = SPI_read(address, fromChip); //read current SPI reg data + uint16_t spiMask = (~(~0 << (msb - lsb + 1))) << (lsb); // creates bit mask + spiDataReg = (spiDataReg & (~spiMask)) | ((value << lsb) & spiMask);//clear bits + return SPI_write(address, spiDataReg); //write modified data back to SPI reg +} + +/** @brief Modifies given registers with values applied using masks + @param addr array of register addresses + @param masks array of applied masks + @param values array of values to be written + @param start starting index of given arrays + @param stop end index of given arrays +*/ +liblms7_status LMS7002M::Modify_SPI_Reg_mask(const uint16_t *addr, const uint16_t *masks, const uint16_t *values, uint8_t start, uint8_t stop) +{ + liblms7_status status; + uint16_t reg_data; + vector addresses; + vector data; + while (start <= stop) + { + reg_data = SPI_read(addr[start], true, &status); //read current SPI reg data + reg_data &= ~masks[start];//clear bits + reg_data |= (values[start] & masks[start]); + addresses.push_back(addr[start]); + data.push_back(reg_data); + ++start; + } + if (status != LIBLMS7_SUCCESS) + return status; + SPI_write_batch(&addresses[0], &data[0], addresses.size()); + return status; +} + +/** @brief Sets SX frequency + @param Tx Rx/Tx module selection + @param freq_MHz desired frequency in MHz + @param refClk_MHz reference clock in MHz + @return 0-success, other-cannot deliver requested frequency +*/ +liblms7_status LMS7002M::SetFrequencySX(bool tx, float_type freq_MHz, float_type refClk_MHz) +{ + if (controlPort == NULL) + return LIBLMS7_NO_CONNECTION_MANAGER; + if (controlPort->IsOpen() == false) + return LIBLMS7_NOT_CONNECTED; + const uint8_t sxVCO_N = 2; //number of entries in VCO frequencies + const float_type m_dThrF = 5500; //threshold to enable additional divider + uint8_t ch; //remember used channel + float_type VCOfreq; + int8_t div_loch; + int8_t sel_vco; + bool canDeliverFrequency = false; + uint16_t integerPart; + uint32_t fractionalPart; + int8_t i; + + //find required VCO frequency + for (div_loch = 6; div_loch >= 0; --div_loch) + { + VCOfreq = (1 << (div_loch + 1)) * freq_MHz; + if ((VCOfreq >= gVCO_frequency_table[0][0]) && (VCOfreq <= gVCO_frequency_table[2][sxVCO_N - 1])) + { + canDeliverFrequency = true; + break; + } + } + if (canDeliverFrequency == false) + return LIBLMS7_CANNOT_DELIVER_FREQUENCY; + + integerPart = (uint16_t)(VCOfreq / (refClk_MHz * (1 + (VCOfreq > m_dThrF))) - 4); + fractionalPart = (uint32_t)((VCOfreq / (refClk_MHz * (1 + (VCOfreq > m_dThrF))) - (uint32_t)(VCOfreq / (refClk_MHz * (1 + (VCOfreq > m_dThrF))))) * 1048576); + + ch = (uint8_t)Get_SPI_Reg_bits(LMS7param(MAC)); + Modify_SPI_Reg_bits(LMS7param(MAC), tx + 1); + Modify_SPI_Reg_bits(LMS7param(INT_SDM), integerPart); //INT_SDM + Modify_SPI_Reg_bits(0x011D, 15, 0, fractionalPart & 0xFFFF); //FRAC_SDM[15:0] + Modify_SPI_Reg_bits(0x011E, 3, 0, (fractionalPart >> 16)); //FRAC_SDM[19:16] + Modify_SPI_Reg_bits(LMS7param(DIV_LOCH), div_loch); //DIV_LOCH + Modify_SPI_Reg_bits(LMS7param(EN_DIV2_DIVPROG), (VCOfreq > m_dThrF)); //EN_DIV2_DIVPROG + + //find which VCO supports required frequency + Modify_SPI_Reg_bits(LMS7param(PD_VCO), 0); // + Modify_SPI_Reg_bits(LMS7param(PD_VCO_COMP), 0); // + int cswBackup = Get_SPI_Reg_bits(LMS7param(CSW_VCO)); //remember to restore previous tune value + canDeliverFrequency = false; + int tuneScore[] = { -128, -128, -128 }; //best is closest to 0 + for (sel_vco = 0; sel_vco < 3; ++sel_vco) + { + Modify_SPI_Reg_bits(LMS7param(SEL_VCO), sel_vco); + liblms7_status status = TuneVCO(tx ? VCO_SXT : VCO_SXR); + int csw = Get_SPI_Reg_bits(LMS7param(CSW_VCO), true); + tuneScore[sel_vco] = -128 + csw; + if (status == LIBLMS7_SUCCESS) + canDeliverFrequency = true; + } + if (abs(tuneScore[0]) < abs(tuneScore[1])) + { + if (abs(tuneScore[0]) < abs(tuneScore[2])) + sel_vco = 0; + else + sel_vco = 2; + } + else + { + if (abs(tuneScore[1]) < abs(tuneScore[2])) + sel_vco = 1; + else + sel_vco = 2; + } + Modify_SPI_Reg_bits(LMS7param(SEL_VCO), sel_vco); + Modify_SPI_Reg_bits(LMS7param(CSW_VCO), cswBackup); + Modify_SPI_Reg_bits(LMS7param(MAC), ch); //restore used channel + if (tx) + mRefClkSXT_MHz = refClk_MHz; + else + mRefClkSXR_MHz = refClk_MHz; + if (canDeliverFrequency == false) + return LIBLMS7_CANNOT_DELIVER_FREQUENCY; + return TuneVCO( tx ? VCO_SXT : VCO_SXR); //Rx-1, Tx-2 +} + +/** @brief Returns currently set SXR/SXT frequency + @return SX frequency MHz +*/ +float_type LMS7002M::GetFrequencySX_MHz(bool Tx, float_type refClk_MHz) +{ + uint8_t ch = (uint8_t)Get_SPI_Reg_bits(LMS7param(MAC)); //remember previously used channel + float_type dMul; + if(Tx) + Modify_SPI_Reg_bits(LMS7param(MAC), 2); // Rx mac = 1, Tx max = 2 + else + Modify_SPI_Reg_bits(LMS7param(MAC), 1); // Rx mac = 1, Tx max = 2 + uint16_t gINT = Get_SPI_Reg_bits(0x011E, 13, 0); // read whole register to reduce SPI transfers + uint32_t gFRAC = ((gINT&0xF) * 65536) | Get_SPI_Reg_bits(0x011D, 15, 0); + + dMul = (float_type)refClk_MHz / (1 << (Get_SPI_Reg_bits(LMS7param(DIV_LOCH)) + 1)); + //Calculate real frequency according to the calculated parameters + dMul = dMul * ((gINT >> 4) + 4 + (float_type)gFRAC / 1048576.0) * (Get_SPI_Reg_bits(LMS7param(EN_DIV2_DIVPROG)) + 1); + Modify_SPI_Reg_bits(LMS7param(MAC), ch); //restore used channel + return dMul; +} + +/** @brief Loads given DC_REG values into registers + @param tx TxTSP or RxTSP selection + @param I DC_REG I value + @param Q DC_REG Q value +*/ +liblms7_status LMS7002M::LoadDC_REG_IQ(bool tx, int16_t I, int16_t Q) +{ + if(tx) + { + Modify_SPI_Reg_bits(LMS7param(DC_REG_TXTSP), I); + Modify_SPI_Reg_bits(LMS7param(TSGDCLDI_TXTSP), 0); + Modify_SPI_Reg_bits(LMS7param(TSGDCLDI_TXTSP), 1); + Modify_SPI_Reg_bits(LMS7param(TSGDCLDI_TXTSP), 0); + Modify_SPI_Reg_bits(LMS7param(DC_REG_TXTSP), Q); + Modify_SPI_Reg_bits(LMS7param(TSGDCLDQ_TXTSP), 0); + Modify_SPI_Reg_bits(LMS7param(TSGDCLDQ_TXTSP), 1); + Modify_SPI_Reg_bits(LMS7param(TSGDCLDQ_TXTSP), 0); + Modify_SPI_Reg_bits(LMS7param(DC_BYP_TXTSP), 0); //DC_BYP + } + else + { + Modify_SPI_Reg_bits(LMS7param(DC_REG_RXTSP), I); + Modify_SPI_Reg_bits(LMS7param(TSGDCLDI_RXTSP), 0); + Modify_SPI_Reg_bits(LMS7param(TSGDCLDI_RXTSP), 1); + Modify_SPI_Reg_bits(LMS7param(TSGDCLDI_RXTSP), 0); + Modify_SPI_Reg_bits(LMS7param(DC_REG_TXTSP), Q); + Modify_SPI_Reg_bits(LMS7param(TSGDCLDQ_RXTSP), 0); + Modify_SPI_Reg_bits(LMS7param(TSGDCLDQ_RXTSP), 1); + Modify_SPI_Reg_bits(LMS7param(TSGDCLDQ_RXTSP), 0); + Modify_SPI_Reg_bits(LMS7param(DC_BYP_RXTSP), 0); //DC_BYP + } + return LIBLMS7_SUCCESS; +} + +/** @brief Sets chosen NCO's frequency + @param tx transmitter or receiver selection + @param index NCO index from 0 to 15 + @param freq_MHz desired NCO frequency + @return 0-success, other-failure +*/ +liblms7_status LMS7002M::SetNCOFrequency(bool tx, uint8_t index, float_type freq_MHz) +{ + if(index > 15) + return LIBLMS7_INDEX_OUT_OF_RANGE; + float_type refClk_MHz = GetReferenceClk_TSP_MHz(tx); + uint16_t addr = tx ? 0x0240 : 0x0440; + uint32_t fcw = (uint32_t)((freq_MHz/refClk_MHz)*4294967296); + SPI_write(addr+2+index*2, (fcw >> 16)); //NCO frequency control word register MSB part. + SPI_write(addr+3+index*2, fcw); //NCO frequency control word register LSB part. + return LIBLMS7_SUCCESS; +} + +/** @brief Returns chosen NCO's frequency in MHz + @param tx transmitter or receiver selection + @param index NCO index from 0 to 15 + @param fromChip read frequency directly from chip or local registers + @return NCO frequency in MHz +*/ +float_type LMS7002M::GetNCOFrequency_MHz(bool tx, uint8_t index, const float_type refClk_MHz, bool fromChip) +{ + if(index > 15) + return LIBLMS7_INDEX_OUT_OF_RANGE; + uint16_t addr = tx ? 0x0240 : 0x0440; + uint32_t fcw = 0; + fcw |= SPI_read(addr + 2 + index * 2, fromChip) << 16; //NCO frequency control word register MSB part. + fcw |= SPI_read(addr + 3 + index * 2, fromChip); //NCO frequency control word register LSB part. + return refClk_MHz*(fcw/4294967296.0); +} + +/** @brief Sets chosen NCO phase offset angle when memory table MODE is 0 +@param tx transmitter or receiver selection +@param angle_deg phase offset angle in degrees +@return 0-success, other-failure +*/ +liblms7_status LMS7002M::SetNCOPhaseOffsetForMode0(bool tx, float_type angle_deg) +{ + uint16_t addr = tx ? 0x0241 : 0x0441; + uint16_t pho = (uint16_t)(65536 * (angle_deg / 360 )); + SPI_write(addr, pho); + return LIBLMS7_SUCCESS; +} + +/** @brief Sets chosen NCO's phase offset angle + @param tx transmitter or receiver selection + @param index PHO index from 0 to 15 + @param angle_deg phase offset angle in degrees + @return 0-success, other-failure +*/ +liblms7_status LMS7002M::SetNCOPhaseOffset(bool tx, uint8_t index, float_type angle_deg) +{ + if(index > 15) + return LIBLMS7_INDEX_OUT_OF_RANGE; + uint16_t addr = tx ? 0x0244 : 0x0444; + uint16_t pho = (uint16_t)(65536*(angle_deg / 360)); + SPI_write(addr+index, pho); + return LIBLMS7_SUCCESS; +} + +/** @brief Returns chosen NCO's phase offset angle in radians + @param tx transmitter or receiver selection + @param index PHO index from 0 to 15 + @return phase offset angle in degrees +*/ +float_type LMS7002M::GetNCOPhaseOffset_Deg(bool tx, uint8_t index) +{ + uint16_t addr = tx ? 0x0244 : 0x0444; + uint16_t pho = SPI_read(addr+index); + float_type angle = 360*pho/65536.0; + return angle; +} + +/** @brief Uploads given FIR coefficients to chip + @param tx Transmitter or receiver selection + @param GFIR_index GIR index from 0 to 2 + @param coef array of coefficients + @param coefCount number of coefficients + @return 0-success, other-failure + + This function does not change GFIR*_L or GFIR*_N parameters, they have to be set manually +*/ +liblms7_status LMS7002M::SetGFIRCoefficients(bool tx, uint8_t GFIR_index, const int16_t *coef, uint8_t coefCount) +{ + uint8_t index; + uint8_t coefLimit; + uint16_t startAddr; + if (GFIR_index == 0) + startAddr = 0x0280; + else if (GFIR_index == 1) + startAddr = 0x02C0; + else + startAddr = 0x0300; + + if (tx == false) + startAddr += 0x0200; + if (GFIR_index < 2) + coefLimit = 40; + else + coefLimit = 120; + if (coefCount > coefLimit) + return LIBLMS7_TOO_MANY_VALUES; + vector addresses; + for (index = 0; index < coefCount; ++index) + addresses.push_back(startAddr + index + 24 * (index / 40)); + SPI_write_batch(&addresses[0], (uint16_t*)coef, coefCount); + return LIBLMS7_SUCCESS; +} + +/** @brief Returns currently loaded FIR coefficients + @param tx Transmitter or receiver selection + @param GFIR_index GIR index from 0 to 2 + @param coef array of returned coefficients + @param coefCount number of coefficients to read + @return 0-success, other-failure +*/ +liblms7_status LMS7002M::GetGFIRCoefficients(bool tx, uint8_t GFIR_index, int16_t *coef, uint8_t coefCount) +{ + liblms7_status status = LIBLMS7_FAILURE; + uint8_t index; + uint8_t coefLimit; + uint16_t startAddr; + if(GFIR_index == 0) + startAddr = 0x0280; + else if (GFIR_index == 1) + startAddr = 0x02C0; + else + startAddr = 0x0300; + + if (tx == false) + startAddr += 0x0200; + if (GFIR_index < 2) + coefLimit = 40; + else + coefLimit = 120; + if (coefCount > coefLimit) + return LIBLMS7_TOO_MANY_VALUES; + + std::vector addresses; + for (index = 0; index < coefCount; ++index) + addresses.push_back(startAddr + index + 24 * (index / 40)); + uint16_t spiData[120]; + memset(spiData, 0, 120 * sizeof(uint16_t)); + if (controlPort->IsOpen()) + { + status = SPI_read_batch(&addresses[0], spiData, coefCount); + for (index = 0; index < coefCount; ++index) + coef[index] = spiData[index]; + } + else + { + const int channel = Get_SPI_Reg_bits(LMS7param(MAC), false) > 1 ? 1 : 0; + for (index = 0; index < coefCount; ++index) + coef[index] = mRegistersMap->GetValue(channel, addresses[index]); + status = LIBLMS7_SUCCESS; + } + + return status; +} + +/** @brief Write given data value to whole register + @param address SPI address + @param data new register value + @return 0-succes, other-failure +*/ +liblms7_status LMS7002M::SPI_write(uint16_t address, uint16_t data) +{ + if (controlPort == NULL) + return LIBLMS7_NO_CONNECTION_MANAGER; + + if ((mRegistersMap->GetValue(0, LMS7param(MAC).address) & 0x0003) > 1 && address >= 0x0100) + mRegistersMap->SetValue(1, address, data); + else + mRegistersMap->SetValue(0, address, data); + + if (controlPort->IsOpen() == false) + return LIBLMS7_NOT_CONNECTED; + + LMScomms::GenericPacket pkt; + pkt.cmd = CMD_LMS7002_WR; + pkt.outBuffer.push_back(address >> 8); + pkt.outBuffer.push_back(address & 0xFF); + pkt.outBuffer.push_back(data >> 8); + pkt.outBuffer.push_back(data & 0xFF); + controlPort->TransferPacket(pkt); + if (pkt.status == STATUS_COMPLETED_CMD) + return LIBLMS7_SUCCESS; + else + return LIBLMS7_FAILURE; +} + +/** @brief Reads whole register value from given address + @param address SPI address + @param status operation status(optional) + @param fromChip read value directly from chip + @return register value +*/ +uint16_t LMS7002M::SPI_read(uint16_t address, bool fromChip, liblms7_status *status) +{ + if (controlPort == NULL) + { + if (status) + *status = LIBLMS7_NO_CONNECTION_MANAGER; + } + if (controlPort->IsOpen() == false || fromChip == false) + { + if ((mRegistersMap->GetValue(0, LMS7param(MAC).address) & 0x0003) > 1 && address >= 0x0100) + return mRegistersMap->GetValue(1, address); + else + return mRegistersMap->GetValue(0, address); + } + + LMScomms::GenericPacket pkt; + pkt.cmd = CMD_LMS7002_RD; + pkt.outBuffer.push_back(address >> 8); + pkt.outBuffer.push_back(address & 0xFF); + if (controlPort->TransferPacket(pkt) == LMScomms::TRANSFER_SUCCESS) + { + if (status) + *status = (pkt.status == STATUS_COMPLETED_CMD ? LIBLMS7_SUCCESS : LIBLMS7_FAILURE); + return (pkt.inBuffer[2] << 8) | pkt.inBuffer[3]; + } + else + return 0; +} + +/** @brief Batches multiple register writes into least ammount of transactions + @param spiAddr spi register addresses to be written + @param spiData registers data to be written + @param cnt number of registers to write + @return 0-success, other-failure +*/ +liblms7_status LMS7002M::SPI_write_batch(const uint16_t* spiAddr, const uint16_t* spiData, uint16_t cnt) +{ + LMScomms::GenericPacket pkt; + pkt.cmd = CMD_LMS7002_WR; + uint32_t index = 0; + for (uint32_t i = 0; i < cnt; ++i) + { + pkt.outBuffer.push_back(spiAddr[i] >> 8); + pkt.outBuffer.push_back(spiAddr[i] & 0xFF); + pkt.outBuffer.push_back(spiData[i] >> 8); + pkt.outBuffer.push_back(spiData[i] & 0xFF); + + if ((mRegistersMap->GetValue(0, LMS7param(MAC).address) & 0x0003) > 1) + mRegistersMap->SetValue(1, spiAddr[i], spiData[i]); + else + mRegistersMap->SetValue(0, spiAddr[i], spiData[i]); + + } + if (controlPort == NULL) + return LIBLMS7_NO_CONNECTION_MANAGER; + if (controlPort->IsOpen() == false) + return LIBLMS7_NOT_CONNECTED; + + controlPort->TransferPacket(pkt); + if (pkt.status == STATUS_COMPLETED_CMD) + return LIBLMS7_SUCCESS; + else + return LIBLMS7_FAILURE; +} + +/** @brief Batches multiple register reads into least amount of transactions + @param spiAddr SPI addresses to read + @param spiData array for read data + @param cnt number of registers to read + @return 0-success, other-failure +*/ +liblms7_status LMS7002M::SPI_read_batch(const uint16_t* spiAddr, uint16_t* spiData, uint16_t cnt) +{ + LMScomms::GenericPacket pkt; + pkt.cmd = CMD_LMS7002_RD; + uint32_t index = 0; + for (uint32_t i = 0; i < cnt; ++i) + { + pkt.outBuffer.push_back(spiAddr[i] >> 8); + pkt.outBuffer.push_back(spiAddr[i] & 0xFF); + } + if (controlPort == NULL) + return LIBLMS7_NO_CONNECTION_MANAGER; + if (controlPort->IsOpen() == false) + return LIBLMS7_NOT_CONNECTED; + + LMScomms::TransferStatus status = controlPort->TransferPacket(pkt); + if (status != LMScomms::TRANSFER_SUCCESS) + return LIBLMS7_FAILURE; + + for (uint32_t i = 0; i < cnt; ++i) + { + spiData[i] = (pkt.inBuffer[2*sizeof(uint16_t)*i + 2] << 8) | pkt.inBuffer[2*sizeof(uint16_t)*i + 3]; + if ((mRegistersMap->GetValue(0, LMS7param(MAC).address) & 0x0003) > 1) + mRegistersMap->SetValue(1, spiAddr[i], spiData[i]); + else + mRegistersMap->SetValue(0, spiAddr[i], spiData[i]); + } + return pkt.status == STATUS_COMPLETED_CMD ? LIBLMS7_SUCCESS : LIBLMS7_FAILURE; + /* + for(int i=0; iGetValue(0, LMS7param(MAC).address) & 0x0003) > 1) + mRegistersMap->SetValue(1, spiAddr[i], spiData[i]); + else + mRegistersMap->SetValue(0, spiAddr[i], spiData[i]); + } + return LIBLMS7_SUCCESS;*/ +} + +/** @brief Performs registers test by writing known data and confirming readback data + @return 0-registers test passed, other-failure +*/ +liblms7_status LMS7002M::RegistersTest() +{ + char chex[16]; + if (controlPort == NULL) + return LIBLMS7_NO_CONNECTION_MANAGER; + if (controlPort->IsOpen() == false) + return LIBLMS7_NOT_CONNECTED; + + liblms7_status status; + uint8_t ch = (uint8_t)Get_SPI_Reg_bits(LMS7param(MAC)); + + //backup both channel data for restoration after test + vector ch1Addresses; + for (uint8_t i = 0; i < MEMORY_SECTIONS_COUNT; ++i) + for (uint16_t addr = MemorySectionAddresses[i][0]; addr <= MemorySectionAddresses[i][1]; ++addr) + ch1Addresses.push_back(addr); + vector ch1Data; + ch1Data.resize(ch1Addresses.size(), 0); + + //backup A channel + Modify_SPI_Reg_bits(LMS7param(MAC), 1); + status = SPI_read_batch(&ch1Addresses[0], &ch1Data[0], ch1Addresses.size()); + if (status != LIBLMS7_SUCCESS) + return status; + + vector ch2Addresses; + for (uint8_t i = 0; i < MEMORY_SECTIONS_COUNT; ++i) + for (uint16_t addr = MemorySectionAddresses[i][0]; addr <= MemorySectionAddresses[i][1]; ++addr) + if (addr >= 0x0100) + ch2Addresses.push_back(addr); + vector ch2Data; + ch2Data.resize(ch2Addresses.size(), 0); + + Modify_SPI_Reg_bits(LMS7param(MAC), 2); + status = SPI_read_batch(&ch2Addresses[0], &ch2Data[0], ch2Addresses.size()); + if (status != LIBLMS7_SUCCESS) + return status; + + //test registers + ResetChip(); + Modify_SPI_Reg_bits(LMS7param(MIMO_SISO), 0); + Modify_SPI_Reg_bits(LMS7param(PD_RX_AFE2), 0); + Modify_SPI_Reg_bits(LMS7param(PD_TX_AFE2), 0); + Modify_SPI_Reg_bits(LMS7param(MAC), 1); + + stringstream ss; + + //check single channel memory sections + vector modulesToCheck = { AFE, BIAS, XBUF, CGEN, LDO, BIST, CDS, TRF, TBB, RFE, RBB, SX, + TxTSP, TxNCO, TxGFIR1, TxGFIR2, TxGFIR3a, TxGFIR3b, TxGFIR3c, + RxTSP, RxNCO, RxGFIR1, RxGFIR2, RxGFIR3a, RxGFIR3b, RxGFIR3c, LimeLight }; + const char* moduleNames[] = { "AFE", "BIAS", "XBUF", "CGEN", "LDO", "BIST", "CDS", "TRF", "TBB", "RFE", "RBB", "SX", + "TxTSP", "TxNCO", "TxGFIR1", "TxGFIR2", "TxGFIR3a", "TxGFIR3b", "TxGFIR3c", + "RxTSP", "RxNCO", "RxGFIR1", "RxGFIR2", "RxGFIR3a", "RxGFIR3b", "RxGFIR3c", "LimeLight" }; + + const uint16_t patterns[] = { 0xAAAA, 0x5555 }; + const uint8_t patternsCount = 2; + + bool allTestSuccess = true; + + for (unsigned i = 0; i < modulesToCheck.size(); ++i) + { + bool moduleTestsSuccess = true; + uint16_t startAddr = MemorySectionAddresses[modulesToCheck[i]][0]; + uint16_t endAddr = MemorySectionAddresses[modulesToCheck[i]][1]; + uint8_t channelCount = startAddr >= 0x0100 ? 2 : 1; + for (int cc = 1; cc <= channelCount; ++cc) + { + Modify_SPI_Reg_bits(LMS7param(MAC), cc); + sprintf(chex, "0x%04X", startAddr); + ss << moduleNames[i] << " [" << chex << ":"; + sprintf(chex, "0x%04X", endAddr); + ss << chex << "]"; + if (startAddr >= 0x0100) + ss << " Ch." << (cc == 1 ? "A" : "B"); + ss << endl; + for (uint8_t p = 0; p < patternsCount; ++p) + moduleTestsSuccess &= RegistersTestInterval(startAddr, endAddr, patterns[p], ss) == LIBLMS7_SUCCESS; + } + allTestSuccess &= moduleTestsSuccess; + } + + //restore register values + Modify_SPI_Reg_bits(LMS7param(MAC), 1); + SPI_write_batch(&ch1Addresses[0], &ch1Data[0], ch1Addresses.size()); + Modify_SPI_Reg_bits(LMS7param(MAC), 2); + SPI_write_batch(&ch2Addresses[0], &ch2Data[0], ch2Addresses.size()); + Modify_SPI_Reg_bits(LMS7param(MAC), ch); + + fstream fout; + fout.open("registersTest.txt", ios::out); + fout << ss.str() << endl; + fout.close(); + + return allTestSuccess ? LIBLMS7_SUCCESS : LIBLMS7_FAILURE; +} + +/** @brief Performs registers test for given address interval by writing given pattern data + @param startAddr first register address + @param endAddr last reigster address + @param pattern data to be written into registers + @return 0-register test passed, other-failure +*/ +liblms7_status LMS7002M::RegistersTestInterval(uint16_t startAddr, uint16_t endAddr, uint16_t pattern, stringstream &ss) +{ + vector addrToWrite; + vector dataToWrite; + vector dataReceived; + vector dataMasks; + + for (uint16_t addr = startAddr; addr <= endAddr; ++addr) + { + addrToWrite.push_back(addr); + } + dataMasks.resize(addrToWrite.size(), 0xFFFF); + for (uint16_t j = 0; j < sizeof(readOnlyRegisters)/sizeof(uint16_t); ++j) + for (uint16_t k = 0; k < addrToWrite.size(); ++k) + if (readOnlyRegisters[j] == addrToWrite[k]) + { + dataMasks[k] = readOnlyRegistersMasks[j]; + break; + } + + dataToWrite.clear(); + dataReceived.clear(); + for (uint16_t j = 0; j < addrToWrite.size(); ++j) + { + if (addrToWrite[j] == 0x00A6) + dataToWrite.push_back(0x1 | pattern & ~0x2); + else if (addrToWrite[j] == 0x0084) + dataToWrite.push_back(pattern & ~0x19); + else + dataToWrite.push_back(pattern & dataMasks[j]); + } + dataReceived.resize(addrToWrite.size(), 0); + liblms7_status status; + status = SPI_write_batch(&addrToWrite[0], &dataToWrite[0], addrToWrite.size()); + if (status != LIBLMS7_SUCCESS) + return status; + status = SPI_read_batch(&addrToWrite[0], &dataReceived[0], addrToWrite.size()); + if (status != LIBLMS7_SUCCESS) + return status; + bool registersMatch = true; + char ctemp[16]; + for (uint16_t j = 0; j < dataToWrite.size(); ++j) + { + if (dataToWrite[j] != (dataReceived[j] & dataMasks[j])) + { + registersMatch = false; + sprintf(ctemp, "0x%04X", addrToWrite[j]); + ss << "\t" << ctemp << "(wr/rd): "; + sprintf(ctemp, "0x%04X", dataToWrite[j]); + ss << ctemp << "/"; + sprintf(ctemp, "0x%04X", dataReceived[j]); + ss << ctemp << endl; + } + } + if (registersMatch) + { + sprintf(ctemp, "0x%04X", pattern); + ss << "\tRegisters OK (" << ctemp << ")\n"; + } + return registersMatch ? LIBLMS7_SUCCESS : LIBLMS7_FAILURE; +} + +/** @brief Parameters setup instructions for Tx calibration + @return 0-success, other-failure +*/ +liblms7_status LMS7002M::CalibrateTxSetup(float_type bandwidth_MHz) +{ + //Stage 2 + uint8_t ch = (uint8_t)Get_SPI_Reg_bits(LMS7param(MAC)); + uint8_t sel_band1_trf = (uint8_t)Get_SPI_Reg_bits(LMS7param(SEL_BAND1_TRF)); + uint8_t sel_band2_trf = (uint8_t)Get_SPI_Reg_bits(LMS7param(SEL_BAND2_TRF)); + + //rfe + //reset RFE to defaults + SetDefaults(RFE); + if (sel_band1_trf == 1) + Modify_SPI_Reg_bits(LMS7param(SEL_PATH_RFE), 3); //SEL_PATH_RFE 3 + else if (sel_band2_trf == 1) + Modify_SPI_Reg_bits(LMS7param(SEL_PATH_RFE), 2); + else + return LIBLMS7_BAND_NOT_SELECTED; + + if (ch == 2) + Modify_SPI_Reg_bits(LMS7param(EN_NEXTRX_RFE), 1); // EN_NEXTTX_RFE 1 + + Modify_SPI_Reg_bits(LMS7param(G_RXLOOPB_RFE), 8); //G_RXLOOPB_RFE 8 + Modify_SPI_Reg_bits(0x010C, 4, 3, 0); //PD_MXLOBUF_RFE 0, PD_QGEN_RFE 0 + Modify_SPI_Reg_bits(LMS7param(CCOMP_TIA_RFE), 10); //CCOMP_TIA_RFE 10 + Modify_SPI_Reg_bits(LMS7param(CFB_TIA_RFE), 2600); //CFB_TIA_RFE 2600 + Modify_SPI_Reg_bits(LMS7param(ICT_LODC_RFE), 31); //ICT_LODC_RFE 31 + Modify_SPI_Reg_bits(LMS7param(PD_LNA_RFE), 1); + + //RBB + //reset RBB to defaults + SetDefaults(RBB); + Modify_SPI_Reg_bits(LMS7param(PD_LPFL_RBB), 0); //PD_LPFL_RBB 0 + Modify_SPI_Reg_bits(LMS7param(RCC_CTL_LPFL_RBB), 0); //RCC_CTL_LPFL_RBB 0 + Modify_SPI_Reg_bits(LMS7param(C_CTL_LPFL_RBB), 1500); //C_CTL_LPFL_RBB 1500 + Modify_SPI_Reg_bits(LMS7param(G_PGA_RBB), 22); //G_PGA_RBB 22 + + //TRF + //reset TRF to defaults + //SetDefaults(TRF); + Modify_SPI_Reg_bits(LMS7param(L_LOOPB_TXPAD_TRF), 0); //L_LOOPB_TXPAD_TRF 0 + Modify_SPI_Reg_bits(LMS7param(EN_LOOPB_TXPAD_TRF), 1); //EN_LOOPB_TXPAD_TRF 1 + Modify_SPI_Reg_bits(LMS7param(EN_G_TRF), 0); //EN_G_TRF 0 + if (ch == 2) + Modify_SPI_Reg_bits(LMS7param(EN_NEXTTX_TRF), 1); //EN_NEXTTX_TRF 1 + Modify_SPI_Reg_bits(LMS7param(LOSS_LIN_TXPAD_TRF), 0); //LOSS_LIN_TXPAD_TRF 5 + Modify_SPI_Reg_bits(LMS7param(LOSS_MAIN_TXPAD_TRF), 0); //LOSS_MAIN_TXPAD_TRF 5 + + //TBB + //reset TBB to defaults + /*SetDefaults(TBB); + Modify_SPI_Reg_bits(LMS7param(CG_IAMP_TBB), 9); //CG_IAMP_TBB 9 + Modify_SPI_Reg_bits(LMS7param(ICT_IAMP_FRP_TBB), 1); //ICT_IAMP_FRP_TBB 1 + Modify_SPI_Reg_bits(LMS7param(ICT_IAMP_GG_FRP_TBB), 6); //ICT_IAMP_GG_FRP_TBB 6 + Modify_SPI_Reg_bits(LMS7param(RCAL_LPFH_TBB), 125); //RCAL_LPFH_TBB 0 + */ + //AFE + //reset AFE to defaults + uint8_t isel_dac_afe =(uint8_t) Get_SPI_Reg_bits(LMS7param(ISEL_DAC_AFE)); + SetDefaults(AFE); + Modify_SPI_Reg_bits(LMS7param(PD_RX_AFE2), 0); //PD_RX_AFE2 0 + Modify_SPI_Reg_bits(LMS7param(ISEL_DAC_AFE), isel_dac_afe); + + if (ch == 2) + Modify_SPI_Reg_bits(LMS7param(PD_TX_AFE2), 0); + //BIAS + uint16_t backup = Get_SPI_Reg_bits(LMS7param(RP_CALIB_BIAS)); + SetDefaults(BIAS); + Modify_SPI_Reg_bits(LMS7param(RP_CALIB_BIAS), backup); //RP_CALIB_BIAS + + //XBUF + Modify_SPI_Reg_bits(0x0085, 2, 0, 1); //PD_XBUF_RX 0, PD_XBUF_TX 0, EN_G_XBUF 1 + + //CGEN + //reset CGEN to defaults + SetDefaults(CGEN); + //power up VCO + Modify_SPI_Reg_bits(LMS7param(PD_VCO_CGEN), 0); + + if (SetFrequencyCGEN(122.88) != LIBLMS7_SUCCESS) + return LIBLMS7_FAILURE; + if (TuneVCO(VCO_CGEN) != LIBLMS7_SUCCESS) + return LIBLMS7_FAILURE; + + //SXR + Modify_SPI_Reg_bits(LMS7param(MAC), 1); + SetDefaults(SX); + float_type SXTfreqMHz = GetFrequencySX_MHz(Tx, mRefClkSXT_MHz); + + float_type SXRfreqMHz = SXTfreqMHz - bandwidth_MHz / 4 - 1; + if (SetFrequencySX(Rx, SXRfreqMHz, mRefClkSXR_MHz) != LIBLMS7_SUCCESS) + return LIBLMS7_FAILURE; + if (TuneVCO(VCO_SXR) != LIBLMS7_SUCCESS) + return LIBLMS7_FAILURE; + + //SXT + Modify_SPI_Reg_bits(LMS7param(MAC), 2); + Modify_SPI_Reg_bits(LMS7param(PD_LOCH_T2RBUF), 1); //PD_LOCH_T2RBUF 1 + if (SetFrequencySX(Tx, SXTfreqMHz, mRefClkSXT_MHz) != LIBLMS7_SUCCESS) + return LIBLMS7_FAILURE; + if (TuneVCO(VCO_SXT) != LIBLMS7_SUCCESS) + return LIBLMS7_FAILURE; + Modify_SPI_Reg_bits(LMS7param(MAC), ch); + + //TXTSP + SetDefaults(TxTSP); + Modify_SPI_Reg_bits(0x0200, 3, 2, 0x3); //TSGMODE 1, INSEL 1 + Modify_SPI_Reg_bits(0x0208, 6, 4, 0x7); //GFIR3_BYP 1, GFIR2_BYP 1, GFIR1_BYP 1 + LoadDC_REG_IQ(Tx, (int16_t)0x7FFF, (int16_t)0x8000); + Modify_SPI_Reg_bits(LMS7param(MAC), ch); + Modify_SPI_Reg_bits(0x0440, 4, 0, 0); //TX SEL[3:0] = 0 & MODE = 0 + + float_type offset = 0.2; + if (bandwidth_MHz == 8) + { + //SXR + Modify_SPI_Reg_bits(LMS7param(MAC), 1); + SetDefaults(SX); + float_type SXTfreqMHz = GetFrequencySX_MHz(Tx, mRefClkSXT_MHz); + + float_type sxrFreq = SXTfreqMHz - bandwidth_MHz / 4 - 1 - offset; + if (SetFrequencySX(Rx, sxrFreq, mRefClkSXR_MHz) != LIBLMS7_SUCCESS) + return LIBLMS7_FAILURE; + SetNCOFrequency(Tx, 0, bandwidth_MHz / 4 + offset); + } + else + SetNCOFrequency(Tx, 0, bandwidth_MHz / 4); + + //RXTSP + SetDefaults(RxTSP); + Modify_SPI_Reg_bits(LMS7param(AGC_MODE_RXTSP), 1); //AGC_MODE 1 + Modify_SPI_Reg_bits(0x040C, 7, 0, 0xBF); + Modify_SPI_Reg_bits(LMS7param(CAPSEL), 0); + Modify_SPI_Reg_bits(LMS7param(HBD_OVR_RXTSP), 0); //Decimation HBD ratio + Modify_SPI_Reg_bits(LMS7param(AGC_AVG_RXTSP), 0x7); //agc_avg iq corr + + return LIBLMS7_SUCCESS; +} + +/** @brief Flips the CAPTURE bit and returns digital RSSI value +*/ +uint32_t LMS7002M::GetRSSI() +{ + Modify_SPI_Reg_bits(LMS7param(CAPTURE), 0); + Modify_SPI_Reg_bits(LMS7param(CAPTURE), 1); + return (Get_SPI_Reg_bits(0x040F, 15, 0) << 2) | Get_SPI_Reg_bits(0x040E, 1, 0); +} + +/** @brief Sets Rx Dc offsets by converting two's complementary numbers to sign and magnitude +*/ +void LMS7002M::SetRxDCOFF(int8_t offsetI, int8_t offsetQ) +{ + uint16_t valToSend = 0; + if (offsetI < 0) + valToSend |= 0x40; + valToSend |= labs(offsetI); + valToSend = valToSend << 7; + if (offsetQ < 0) + valToSend |= 0x40; + valToSend |= labs(offsetQ); + SPI_write(0x010E, valToSend); +} + +/** @brief Calibrates Transmitter. DC correction, IQ gains, IQ phase correction + @return 0-success, other-failure +*/ +liblms7_status LMS7002M::CalibrateTx(float_type bandwidth_MHz) +{ + liblms7_status status; + Log("Tx calibration started", LOG_INFO); + BackupAllRegisters(); + + int16_t iqcorr = 0; + uint16_t gcorrq = 0; + uint16_t gcorri = 0; + uint16_t dccorri; + uint16_t dccorrq; + int16_t corrI = 0; + int16_t corrQ = 0; + uint32_t minRSSI_i; + uint32_t minRSSI_q; + uint32_t minRSSI_iq; + int16_t i; + int16_t offsetI = 0; + int16_t offsetQ = 0; + + const short firCoefs[] = + { + -2531, + -517, + 2708, + 188, + -3059, + 216, + 3569, + -770, + -4199, + 1541, + 4886, + -2577, + -5552, + 3909, + 6108, + -5537, + -6457, + 7440, + 6507, + -9566, + -6174, + 11845, + 5391, + -14179, + -4110, + 16457, + 2310, + -18561, + 0, + 20369, + -2780, + -21752, + 5963, + 22610, + -9456, + -22859, + 13127, + 22444, + -16854, + -21319, + 20489, + 19492, + -23883, + -17002, + 26881, + 13902, + -29372, + -10313, + 31226, + 6345, + -32380, + -2141, + 32767, + -2141, + -32380, + 6345, + 31226, + -10313, + -29372, + 13902, + 26881, + -17002, + -23883, + 19492, + 20489, + -21319, + -16854, + 22444, + 13127, + -22859, + -9456, + 22610, + 5963, + -21752, + -2780, + 20369, + 0, + -18561, + 2310, + 16457, + -4110, + -14179, + 5391, + 11845, + -6174, + -9566, + 6507, + 7440, + -6457, + -5537, + 6108, + 3909, + -5552, + -2577, + 4886, + 1541, + -4199, + -770, + 3569, + 216, + -3059, + 188, + 2708, + -517, + -2531 + }; + + uint8_t ch = (uint8_t)Get_SPI_Reg_bits(LMS7param(MAC)); + //Stage 1 + uint8_t sel_band1_trf = (uint8_t)Get_SPI_Reg_bits(LMS7param(SEL_BAND1_TRF)); + uint8_t sel_band2_trf = (uint8_t)Get_SPI_Reg_bits(LMS7param(SEL_BAND2_TRF)); + Log("Setup stage", LOG_INFO); + status = CalibrateTxSetup(bandwidth_MHz); + if (status != LIBLMS7_SUCCESS) + goto TxCalibrationEnd; //go to ending stage to restore registers + + //Stage 3 + //Calibrate Rx DC + Log("Rx DC calibration", LOG_INFO); + { + uint16_t requiredRegs[] = { 0x0400, 0x040A, 0x010D, 0x040C }; + uint16_t requiredMask[] = { 0x6000, 0x3007, 0x0040, 0x00FF }; //CAPSEL, AGC_MODE, AGC_AVG, EN_DCOFF, Bypasses + uint16_t requiredValue[] = { 0x0000, 0x1007, 0x0040, 0x00BD }; + + Modify_SPI_Reg_mask(requiredRegs, requiredMask, requiredValue, 0, 3); + } + + for (i = 0; i<6; ++i) + { + FindMinRSSI(LMS7param(DCOFFI_RFE), offsetI, &offsetI, 3, 2, 32 >> i); + FindMinRSSI(LMS7param(DCOFFQ_RFE), offsetQ, &offsetQ, 3, 2, 32 >> i); + } + SetRxDCOFF((int8_t)offsetI, (int8_t)offsetQ); + Modify_SPI_Reg_bits(LMS7param(DC_BYP_RXTSP), 0); // DC_BYP 0 + + sel_band1_trf = (uint8_t)Get_SPI_Reg_bits(LMS7param(SEL_BAND1_TRF)); + sel_band2_trf = (uint8_t)Get_SPI_Reg_bits(LMS7param(SEL_BAND2_TRF)); + //B + Modify_SPI_Reg_bits(0x0100, 0, 0, 1); //EN_G_TRF 1 + if (sel_band1_trf == 1) + { + Modify_SPI_Reg_bits(LMS7param(PD_RLOOPB_1_RFE), 0); //PD_RLOOPB_1_RFE 0 + Modify_SPI_Reg_bits(LMS7param(EN_INSHSW_LB1_RFE), 0); //EN_INSHSW_LB1 0 + } + if (sel_band2_trf == 1) + { + Modify_SPI_Reg_bits(LMS7param(PD_RLOOPB_2_RFE), 0); //PD_RLOOPB_2_RFE 0 + Modify_SPI_Reg_bits(LMS7param(EN_INSHSW_LB2_RFE), 0); // EN_INSHSW_LB2 0 + } + FixRXSaturation(); + + Modify_SPI_Reg_bits(LMS7param(GFIR3_BYP_RXTSP), 0); //GFIR3_BYP 0 + Modify_SPI_Reg_bits(LMS7param(HBD_OVR_RXTSP), 2); + Modify_SPI_Reg_bits(LMS7param(GFIR3_L_RXTSP), 7); + Modify_SPI_Reg_bits(LMS7param(GFIR3_N_RXTSP), 7); + + SetGFIRCoefficients(Rx, 2, firCoefs, sizeof(firCoefs) / sizeof(int16_t)); + + Log("IQ correction stage", LOG_INFO); + Modify_SPI_Reg_bits(LMS7param(GCORRI_TXTSP), 2047); + Modify_SPI_Reg_bits(LMS7param(GCORRQ_TXTSP), 2047); + + Modify_SPI_Reg_bits(LMS7param(IQCORR_TXTSP), 0); + + Log("I gain", LOG_INFO); + minRSSI_i = FindMinRSSI_Gain(LMS7param(GCORRI_TXTSP), &gcorri); + + Modify_SPI_Reg_bits(LMS7param(GCORRI_TXTSP), 2047); + Modify_SPI_Reg_bits(LMS7param(GCORRQ_TXTSP), 2047); + + Log("Q gain", LOG_INFO); + minRSSI_q = FindMinRSSI_Gain(LMS7param(GCORRQ_TXTSP), &gcorrq); + + if (minRSSI_i < minRSSI_q) + gcorrq = 2047; + else + gcorri = 2047; + + Modify_SPI_Reg_bits(LMS7param(GCORRI_TXTSP), gcorri); + Modify_SPI_Reg_bits(LMS7param(GCORRQ_TXTSP), gcorrq); + + Log("Phase", LOG_INFO); + iqcorr = 0; + for (uint8_t i = 0; i<9; ++i) + minRSSI_iq = FindMinRSSI(LMS7param(IQCORR_TXTSP), iqcorr, &iqcorr, 3, 1, 256 >> i); + + Modify_SPI_Reg_bits(LMS7param(GCORRI_TXTSP), gcorri); + Modify_SPI_Reg_bits(LMS7param(GCORRQ_TXTSP), gcorrq); + Modify_SPI_Reg_bits(LMS7param(IQCORR_TXTSP), iqcorr); + + Modify_SPI_Reg_bits(LMS7param(MAC), 1); + status = SetFrequencySX(Rx, GetFrequencySX_MHz(Tx, mRefClkSXT_MHz)-1, mRefClkSXR_MHz); + if (status != LIBLMS7_SUCCESS) + goto TxCalibrationEnd; //go to ending stage to restore registers + + //C + Modify_SPI_Reg_bits(LMS7param(MAC), ch); + Modify_SPI_Reg_bits(LMS7param(AGC_MODE_RXTSP), 1); + Modify_SPI_Reg_bits(LMS7param(CAPSEL), 0); + + Log("TX LO calibration", LOG_INFO); + + //Calibrate Tx DC + for (uint8_t i = 0; i<7; ++i) + { + FindMinRSSI(LMS7param(DCCORRI_TXTSP), corrI, &corrI, 3, 1, 64 >> i); + FindMinRSSI(LMS7param(DCCORRQ_TXTSP), corrQ, &corrQ, 3, 1, 64 >> i); + } + + dccorri = Get_SPI_Reg_bits(LMS7param(DCCORRI_TXTSP)); + dccorrq = Get_SPI_Reg_bits(LMS7param(DCCORRQ_TXTSP)); + + // Stage 4 +TxCalibrationEnd: + Log("Restoring registers state", LOG_INFO); + Modify_SPI_Reg_bits(LMS7param(MAC), ch); + RestoreAllRegisters(); + if (status != LIBLMS7_SUCCESS) + { + Log("Tx calibration failed", LOG_WARNING); + return status; + } + + Modify_SPI_Reg_bits(LMS7param(MAC), ch); + Modify_SPI_Reg_bits(LMS7param(DCCORRI_TXTSP), dccorri); + Modify_SPI_Reg_bits(LMS7param(DCCORRQ_TXTSP), dccorrq); + Modify_SPI_Reg_bits(LMS7param(GCORRI_TXTSP), gcorri); + Modify_SPI_Reg_bits(LMS7param(GCORRQ_TXTSP), gcorrq); + Modify_SPI_Reg_bits(LMS7param(IQCORR_TXTSP), iqcorr); + + Modify_SPI_Reg_bits(LMS7param(DC_BYP_TXTSP), 0); //DC_BYP + Modify_SPI_Reg_bits(0x0208, 1, 0, 0); //GC_BYP PH_BYP + Log("Tx calibration finished", LOG_INFO); + return LIBLMS7_SUCCESS; +} + +/** @brief Performs Rx DC offsets calibration +*/ +void LMS7002M::CalibrateRxDC_RSSI() +{ + int16_t i; + int16_t offsetI = 0; + int16_t offsetQ = 0; + uint16_t requiredRegs[] = { 0x0400, 0x040A, 0x010D, 0x040C }; + uint16_t requiredMask[] = { 0x6000, 0x3007, 0x0040, 0x00FF }; //CAPSEL, AGC_MODE, AGC_AVG, EN_DCOFF, Bypasses + uint16_t requiredValue[] = { 0x0000, 0x1007, 0x0040, 0x00BD }; + + Modify_SPI_Reg_mask(requiredRegs, requiredMask, requiredValue, 0, 3); + for (i = 0; i<6; ++i) + { + FindMinRSSI(LMS7param(DCOFFI_RFE), offsetI, &offsetI, 3, 2, 32 >> i); + FindMinRSSI(LMS7param(DCOFFQ_RFE), offsetQ, &offsetQ, 3, 2, 32 >> i); + } + Modify_SPI_Reg_bits(LMS7param(EN_DCOFF_RXFE_RFE), 1); + SetRxDCOFF((int8_t)offsetI, (int8_t)offsetQ); + Modify_SPI_Reg_bits(LMS7param(DC_BYP_RXTSP), 0); // DC_BYP 0 +} + +/** @brief Tries to detect and fix gains if Rx is saturated + @return 0-success, other-failure +*/ +liblms7_status LMS7002M::FixRXSaturation() +{ + uint8_t g_rxloopb = 0; + Modify_SPI_Reg_bits(LMS7param(G_RXLOOPB_RFE), g_rxloopb); + Modify_SPI_Reg_bits(LMS7param(L_LOOPB_TXPAD_TRF), 3); + + int8_t lLoopb = 3; + const uint32_t rssi_saturation_level = 0xD000; + while (g_rxloopb < 15) + { + g_rxloopb += 1; + Modify_SPI_Reg_bits(LMS7param(G_RXLOOPB_RFE), g_rxloopb); + Modify_SPI_Reg_bits(LMS7param(L_LOOPB_TXPAD_TRF), 3); + if (GetRSSI() < rssi_saturation_level) + { + for (lLoopb = 3; lLoopb >= 0; --lLoopb) + { + Modify_SPI_Reg_bits(LMS7param(L_LOOPB_TXPAD_TRF), lLoopb); + if (GetRSSI() > rssi_saturation_level) + { + ++lLoopb; + Modify_SPI_Reg_bits(LMS7param(L_LOOPB_TXPAD_TRF), lLoopb); + goto finished; + } + } + } + else + { + g_rxloopb -= 1; + Modify_SPI_Reg_bits(LMS7param(G_RXLOOPB_RFE), g_rxloopb); + break; + } + } +finished: + return GetRSSI() < rssi_saturation_level ? LIBLMS7_SUCCESS : LIBLMS7_FAILURE; +} + +uint32_t LMS7002M::FindMinRSSI(const LMS7Parameter ¶m, const int16_t startValue, int16_t *result, const uint8_t scanWidth, const uint8_t twoCompl, int8_t stepMult) +{ + return FindMinRSSI(param.address, param.msb, param.lsb, startValue, result, scanWidth, twoCompl, stepMult); +} + +/** @brief Searches for minimal RSSI value while changing given address bits +@param addr address of parameter being changed +@param msb most significant bit index +@param lsb least significant bit index +@param startValue initial value where to start search +@param result found minimal parameter value will be set here +@param twoCompl varying parameter value is treated as two's complement +@return found minimal RSSI value +*/ +uint32_t LMS7002M::FindMinRSSI(const uint16_t addr, const uint8_t msb, const uint8_t lsb, const int16_t startValue, int16_t *result, const uint8_t scanWidth, const uint8_t twoCompl, int8_t stepMult) +{ + if (scanWidth < 1) + return ~0; + int minI; + int min = startValue; + int globMin = 0; + uint32_t minRSSI = ~0; + unsigned int *rssiField = new unsigned int[scanWidth]; + int minRSSIindex; + int i; + int maxVal; + int minVal = 0; + if (twoCompl) + { + maxVal = (~(~0x0 << (msb - lsb + 1))) / 2; + minVal = -(~(~0x0 << (msb - lsb + 1))) / 2 - 1; + } + else + maxVal = (~(~0x0 << (msb - lsb + 1))); + + Modify_SPI_Reg_bits(addr, msb, lsb, startValue); + + Modify_SPI_Reg_bits(LMS7param(AGC_MODE_RXTSP), 1); + Modify_SPI_Reg_bits(LMS7param(CAPSEL), 0); + + minRSSIindex = 0; + for (i = 0; i maxVal) + currentValue = maxVal; + if (twoCompl == 2) + { + uint16_t valToSend = 0; + if (currentValue < 0) + valToSend |= 0x40; + valToSend |= labs(currentValue); + Modify_SPI_Reg_bits(addr, msb, lsb, valToSend); + } + else + Modify_SPI_Reg_bits(addr, msb, lsb, currentValue); + + rssiField[i] = GetRSSI(); + } + minI = min; + minRSSIindex = 0; + for (i = 0; i maxVal) + minI = maxVal; + else if (minI < minVal) + minI = minVal; + globMin = minI; + } + min = minI; + + Modify_SPI_Reg_bits(addr, msb, lsb, min); + + *result = min; + return minRSSI; +} + +/** @brief Sets given module registers to default values + @return 0-success, other-failure +*/ +liblms7_status LMS7002M::SetDefaults(MemorySection module) +{ + liblms7_status status = LIBLMS7_SUCCESS; + vector addrs; + vector values; + for(uint32_t address = MemorySectionAddresses[module][0]; address <= MemorySectionAddresses[module][1]; ++address) + { + addrs.push_back(address); + values.push_back(mRegistersMap->GetDefaultValue(address)); + } + status = SPI_write_batch(&addrs[0], &values[0], addrs.size()); + return status; +} + +/** @brief Parameters setup instructions for Rx calibration + @param bandwidth_MHz filter bandwidth in MHz + @return 0-success, other-failure +*/ +liblms7_status LMS7002M::CalibrateRxSetup(float_type bandwidth_MHz) +{ + uint8_t ch = (uint8_t)Get_SPI_Reg_bits(LMS7param(MAC)); + + //rfe + if (ch == 2) + Modify_SPI_Reg_bits(LMS7param(EN_NEXTTX_TRF), 1); // EN_NEXTTX_TRF 0 + + Modify_SPI_Reg_bits(LMS7param(G_RXLOOPB_RFE), 15); //G_RXLOOPB_RFE 15 + Modify_SPI_Reg_bits(0x010C, 4, 3, 0); //PD_MXLOBUF_RFE 0, PD_QGEN_RFE 0 + Modify_SPI_Reg_bits(0x010C, 1, 1, 0); //PD_TIA 0 + Modify_SPI_Reg_bits(0x010C, 7, 7, 1); //PD_LNA 1 + + Modify_SPI_Reg_bits(0x0110, 4, 0, 31); //ICT_LO_RFE 31 + Modify_SPI_Reg_bits(0x010D, 4, 1, 0xFF); // all short switches are enabled + + //RBB + Modify_SPI_Reg_bits(0x0115, 15, 14, 0); //Loopback switches disable + Modify_SPI_Reg_bits(0x0119, 15, 15, 0); //OSW_PGA 0 + + //TRF + //reset TRF to defaults + SetDefaults(TRF); + Modify_SPI_Reg_bits(LMS7param(L_LOOPB_TXPAD_TRF), 0); //L_LOOPB_TXPAD_TRF 0 + Modify_SPI_Reg_bits(LMS7param(EN_LOOPB_TXPAD_TRF), 1); //EN_LOOPB_TXPAD_TRF 1 + Modify_SPI_Reg_bits(LMS7param(EN_G_TRF), 0); //EN_G_TRF 0 + if (ch == 2) + Modify_SPI_Reg_bits(LMS7param(EN_NEXTTX_TRF), 1); //EN_NEXTTX_TRF 1 + Modify_SPI_Reg_bits(LMS7param(LOSS_LIN_TXPAD_TRF), 0); //LOSS_LIN_TXPAD_TRF 5 + Modify_SPI_Reg_bits(LMS7param(LOSS_MAIN_TXPAD_TRF), 0); //LOSS_MAIN_TXPAD_TRF 5 + + //TBB + //reset TBB to defaults + SetDefaults(TBB); + Modify_SPI_Reg_bits(LMS7param(CG_IAMP_TBB), 9); //CG_IAMP_TBB 9 + Modify_SPI_Reg_bits(LMS7param(ICT_IAMP_FRP_TBB), 1); //ICT_IAMP_FRP_TBB 1 + Modify_SPI_Reg_bits(LMS7param(ICT_IAMP_GG_FRP_TBB), 6); //ICT_IAMP_GG_FRP_TBB 6 + + //AFE + //reset AFE to defaults + SetDefaults(AFE); + Modify_SPI_Reg_bits(LMS7param(PD_RX_AFE2), 0); //PD_RX_AFE2 + if (ch == 2) + { + Modify_SPI_Reg_bits(LMS7param(PD_TX_AFE2), 0); //PD_TX_AFE2 + } + //BIAS + uint16_t backup = Get_SPI_Reg_bits(0x0084, 10, 6); + SetDefaults(BIAS); + Modify_SPI_Reg_bits(0x0084, 10, 6, backup); //RP_CALIB_BIAS + + //XBUF + Modify_SPI_Reg_bits(0x0085, 2, 0, 1); //PD_XBUF_RX 0, PD_XBUF_TX 0, EN_G_XBUF 1 + + //CGEN + //reset CGEN to defaults + SetDefaults(CGEN); + //power up VCO + Modify_SPI_Reg_bits(0x0086, 2, 2, 0); + + liblms7_status status = SetFrequencyCGEN(122.88); + if (status != LIBLMS7_SUCCESS) + return status; + + // //SXR + Modify_SPI_Reg_bits(LMS7param(MAC), 1); + float_type SXRfreqMHz = GetFrequencySX_MHz(Rx, mRefClkSXR_MHz); + + //SXT + Modify_SPI_Reg_bits(LMS7param(MAC), 2); + Modify_SPI_Reg_bits(LMS7param(PD_LOCH_T2RBUF), 1); //PD_LOCH_t2RBUF 1 + status = SetFrequencySX(Tx, SXRfreqMHz + bandwidth_MHz / 4, mRefClkSXT_MHz); + if ( status != LIBLMS7_SUCCESS) + return status; + Modify_SPI_Reg_bits(LMS7param(MAC), ch); + + //TXTSP + SetDefaults(TxTSP); + Modify_SPI_Reg_bits(0x0200, 3, 2, 0x3); //TSGMODE 1, INSEL 1 + //Modify_SPI_Reg_bits(0x0208, 6, 4, 0xFFFF); //GFIR3_BYP 1, GFIR2_BYP 1, GFIR1_BYP 1 + Modify_SPI_Reg_bits(0x0208, 6, 6, 1); //GFIR3_BYP 1, GFIR2_BYP 1, GFIR1_BYP 1 + Modify_SPI_Reg_bits(0x0208, 5, 5, 1); //GFIR3_BYP 1, GFIR2_BYP 1, GFIR1_BYP 1 + Modify_SPI_Reg_bits(0x0208, 4, 4, 1); //GFIR3_BYP 1, GFIR2_BYP 1, GFIR1_BYP 1 + LoadDC_REG_IQ(Tx, (int16_t)0x7FFF, (int16_t)0x8000); + SetNCOFrequency(Tx, 0, 0); + + //RXTSP + SetDefaults(RxTSP); + Modify_SPI_Reg_bits(LMS7param(AGC_MODE_RXTSP), 1); //AGC_MODE 1 + Modify_SPI_Reg_bits(0x040C, 7, 7, 0x1); //CMIX_BYP 1 + Modify_SPI_Reg_bits(0x040C, 6, 6, 0x0); //AGC_BYP 0 + Modify_SPI_Reg_bits(0x040C, 5, 5, 1); // + Modify_SPI_Reg_bits(0x040C, 4, 4, 1); // + Modify_SPI_Reg_bits(0x040C, 3, 3, 1); // + Modify_SPI_Reg_bits(0x040C, 2, 2, 1); // DC_BYP + Modify_SPI_Reg_bits(0x040C, 1, 1, 1); // + Modify_SPI_Reg_bits(0x040C, 0, 0, 1); // + + Modify_SPI_Reg_bits(LMS7param(CAPSEL), 0); + Modify_SPI_Reg_bits(LMS7param(HBD_OVR_RXTSP), 2); + Modify_SPI_Reg_bits(LMS7param(AGC_AVG_RXTSP), 0x7); //agc_avg iq corr + return LIBLMS7_SUCCESS; +} + +/** @brief Calibrates Receiver. DC offset, IQ gains, IQ phase correction + @return 0-success, other-failure +*/ +liblms7_status LMS7002M::CalibrateRx(float_type bandwidth_MHz) +{ + liblms7_status status; + uint32_t minRSSI_i; + uint32_t minRSSI_q; + int16_t iqcorr_rx = 0; + uint32_t minRSSI_iq; + int16_t dcoffi; + int16_t dcoffq; + + const int16_t firCoefs[] = + { + -2531, + -517, + 2708, + 188, + -3059, + 216, + 3569, + -770, + -4199, + 1541, + 4886, + -2577, + -5552, + 3909, + 6108, + -5537, + -6457, + 7440, + 6507, + -9566, + -6174, + 11845, + 5391, + -14179, + -4110, + 16457, + 2310, + -18561, + 0, + 20369, + -2780, + -21752, + 5963, + 22610, + -9456, + -22859, + 13127, + 22444, + -16854, + -21319, + 20489, + 19492, + -23883, + -17002, + 26881, + 13902, + -29372, + -10313, + 31226, + 6345, + -32380, + -2141, + 32767, + -2141, + -32380, + 6345, + 31226, + -10313, + -29372, + 13902, + 26881, + -17002, + -23883, + 19492, + 20489, + -21319, + -16854, + 22444, + 13127, + -22859, + -9456, + 22610, + 5963, + -21752, + -2780, + 20369, + 0, + -18561, + 2310, + 16457, + -4110, + -14179, + 5391, + 11845, + -6174, + -9566, + 6507, + 7440, + -6457, + -5537, + 6108, + 3909, + -5552, + -2577, + 4886, + 1541, + -4199, + -770, + 3569, + 216, + -3059, + 188, + 2708, + -517, + -2531 + }; + + Log("Rx calibration started", LOG_INFO); + uint8_t ch = (uint8_t)Get_SPI_Reg_bits(LMS7param(MAC)); + Log("Saving registers state", LOG_INFO); + BackupAllRegisters(); + uint8_t sel_path_rfe = (uint8_t)Get_SPI_Reg_bits(LMS7param(SEL_PATH_RFE)); + if (sel_path_rfe == 1 || sel_path_rfe == 0) + return LIBLMS7_BAD_SEL_PATH; + + Log("Setup stage", LOG_INFO); + status = CalibrateRxSetup(bandwidth_MHz); + if (status != LIBLMS7_SUCCESS) + goto RxCalibrationEndStage; + + Log("Rx DC calibration", LOG_INFO); + CalibrateRxDC_RSSI(); + dcoffi = Get_SPI_Reg_bits(LMS7param(DCOFFI_RFE)); + dcoffq = Get_SPI_Reg_bits(LMS7param(DCOFFQ_RFE)); + Modify_SPI_Reg_bits(LMS7param(EN_G_TRF), 1); + + if (sel_path_rfe == 2) + { + Modify_SPI_Reg_bits(LMS7param(PD_RLOOPB_2_RFE), 0); + Modify_SPI_Reg_bits(0x0103, 10, 10, 1); + Modify_SPI_Reg_bits(0x0103, 11, 11, 0); + Modify_SPI_Reg_bits(LMS7param(EN_INSHSW_LB2_RFE), 0); + } + if (sel_path_rfe == 3) + { + Modify_SPI_Reg_bits(LMS7param(PD_RLOOPB_1_RFE), 0); + Modify_SPI_Reg_bits(0x0103, 11, 11, 1); + Modify_SPI_Reg_bits(0x0103, 10, 10, 0); + Modify_SPI_Reg_bits(LMS7param(EN_INSHSW_LB1_RFE), 0); + } + + Modify_SPI_Reg_bits(0x040C, 7, 7, 0); //CMIX_BYP 0 + Modify_SPI_Reg_bits(0x040C, 2, 0, 0); //DC_BYP 0, GC_BYP 0, PH_BYP 0 + Modify_SPI_Reg_bits(LMS7param(CMIX_GAIN_RXTSP), 1); //CMIX_GAIN 1 +6 db + Modify_SPI_Reg_bits(0x040C, 13, 13, 1); //CMIX_SC 1 + + FixRXSaturation(); + + Modify_SPI_Reg_bits(0x040C, 5, 5, 0); //GFIR3_BYP 0 + Modify_SPI_Reg_bits(LMS7param(HBD_OVR_RXTSP), 2); + Modify_SPI_Reg_bits(LMS7param(GFIR3_L_RXTSP), 7); + Modify_SPI_Reg_bits(LMS7param(GFIR3_N_RXTSP), 7); + + SetGFIRCoefficients(Rx, 2, firCoefs, sizeof(firCoefs) / sizeof(int16_t)); + + SetNCOFrequency(Rx, 0, bandwidth_MHz / 4 + 1); + Modify_SPI_Reg_bits(LMS7param(GCORRI_RXTSP), 2047); + Modify_SPI_Reg_bits(LMS7param(GCORRQ_RXTSP), 2047); + + Log("IQ correction stage", LOG_INFO); + iqcorr_rx = 0; + for (int i = 0; i<9; ++i) + minRSSI_iq = FindMinRSSI(LMS7param(IQCORR_RXTSP), iqcorr_rx, &iqcorr_rx, 3, 1, 256 >> i); + Modify_SPI_Reg_bits(LMS7param(IQCORR_RXTSP), iqcorr_rx); + + uint16_t mingcorri; + Log("I gain", LOG_INFO); + minRSSI_i = FindMinRSSI_Gain(LMS7param(GCORRI_RXTSP), &mingcorri); + + Modify_SPI_Reg_bits(LMS7param(GCORRI_RXTSP), 2047); + Modify_SPI_Reg_bits(LMS7param(GCORRQ_RXTSP), 2047); + + Log("Q gain", LOG_INFO); + uint16_t mingcorrq; + minRSSI_q = FindMinRSSI_Gain(LMS7param(GCORRQ_RXTSP), &mingcorrq); + + if (minRSSI_i < minRSSI_q) + mingcorrq = 2047; + else + mingcorri = 2047; + + Modify_SPI_Reg_bits(LMS7param(GCORRI_RXTSP), mingcorri); + Modify_SPI_Reg_bits(LMS7param(GCORRQ_RXTSP), mingcorrq); + + Log("Phase", LOG_INFO); + for (int i = 0; i<9; ++i) + minRSSI_iq = FindMinRSSI(LMS7param(IQCORR_RXTSP), iqcorr_rx, &iqcorr_rx, 3, 1, 256 >> i); + +RxCalibrationEndStage: + Log("Restoring registers state", LOG_INFO); + RestoreAllRegisters(); + if (status != LIBLMS7_SUCCESS) + { + Log("Rx calibration failed", LOG_WARNING); + return status; + } + + Modify_SPI_Reg_bits(LMS7param(MAC), ch); + SetRxDCOFF((int8_t)dcoffi, (int8_t)dcoffq); + Modify_SPI_Reg_bits(LMS7param(EN_DCOFF_RXFE_RFE), 1); + Modify_SPI_Reg_bits(LMS7param(GCORRI_RXTSP), mingcorri); + Modify_SPI_Reg_bits(LMS7param(GCORRQ_RXTSP), mingcorrq); + Modify_SPI_Reg_bits(LMS7param(IQCORR_RXTSP), iqcorr_rx); + Modify_SPI_Reg_bits(0x040C, 2, 0, 0); //DC_BYP 0, GC_BYP 0, PH_BYP 0 + Modify_SPI_Reg_bits(0x0110, 4, 0, 31); //ICT_LO_RFE 31 + Log("Rx calibration finished", LOG_INFO); + return LIBLMS7_SUCCESS; +} + +const uint16_t backupAddrs[] = { + 0x0020, 0x0021, 0x0022, 0x0023, 0x0024, 0x0025, 0x0026, 0x0027, 0x0028, + 0x0029, 0x002A, 0x002B, 0x002C, 0x002E, 0x0081, 0x0082, 0x0084, 0x0085, + 0x0086, 0x0087, 0x0088, 0x0089, 0x008A, 0x008B, 0x008C, 0x0092, 0x0093, 0x0094, + 0x0095, 0x0096, 0x0097, 0x0098, 0x0099, 0x009A, 0x009B, 0x009C, 0x009D, 0x009E, + 0x009F, 0x00A0, 0x00A1, 0x00A2, 0x00A3, 0x00A4, 0x00A5, 0x00A6, 0x00A7, 0x00A8, + 0x00A9, 0x00AA, 0x00AB, 0x00AC, 0x00AD, 0x00AE, 0x0100, 0x0101, 0x0102, 0x0103, + 0x0104, 0x0105, 0x0106, 0x0107, 0x0108, 0x0109, 0x010A, 0x010C, 0x010D, 0x010E, + 0x010F, 0x0110, 0x0111, 0x0112, 0x0113, 0x0114, 0x0115, 0x0116, 0x0117, 0x0118, + 0x0119, 0x011A, 0x011C, 0x011D, 0x011E, 0x011F, 0x0120, 0x0121, 0x0122, 0x0123, + 0x0124, 0x0200, 0x0201, 0x0202, 0x0203, 0x0204, 0x0205, 0x0206, 0x0207, 0x0208, + 0x0240, 0x0242, 0x0243, 0x0400, 0x0401, 0x0402, + 0x0403, 0x0404, 0x0405, 0x0406, 0x0407, 0x0408, 0x0409, 0x040A, 0x040B, 0x040C, + 0x0440, 0x0442, 0x0443 }; +uint16_t backupRegs[sizeof(backupAddrs) / 2]; +const uint16_t backupSXAddr[] = { 0x011C, 0x011D, 0x011E, 0x011F, 0x01200, 0x0121, 0x0122, 0x0123, 0x0124 }; +uint16_t backupRegsSXR[sizeof(backupSXAddr) / 2]; +uint16_t backupRegsSXT[sizeof(backupSXAddr) / 2]; + +/** @brief Stores chip current registers state into memory for later restoration +*/ +void LMS7002M::BackupAllRegisters() +{ + uint8_t ch = (uint8_t)Get_SPI_Reg_bits(LMS7param(MAC)); + SPI_read_batch(backupAddrs, backupRegs, sizeof(backupAddrs) / sizeof(uint16_t)); + Modify_SPI_Reg_bits(LMS7param(MAC), 1); // channel A + SPI_read_batch(backupSXAddr, backupRegsSXR, sizeof(backupRegsSXR) / sizeof(uint16_t)); + Modify_SPI_Reg_bits(LMS7param(MAC), 2); // channel B + SPI_read_batch(backupSXAddr, backupRegsSXT, sizeof(backupRegsSXR) / sizeof(uint16_t)); + Modify_SPI_Reg_bits(LMS7param(MAC), ch); +} + +/** @brief Sets chip registers to state that was stored in memory using BackupAllRegisters() +*/ +void LMS7002M::RestoreAllRegisters() +{ + uint8_t ch = (uint8_t)Get_SPI_Reg_bits(LMS7param(MAC)); + SPI_write_batch(backupAddrs, backupRegs, sizeof(backupAddrs) / sizeof(uint16_t)); + Modify_SPI_Reg_bits(LMS7param(MAC), 1); // channel A + SPI_write_batch(backupSXAddr, backupRegsSXR, sizeof(backupRegsSXR) / sizeof(uint16_t)); + Modify_SPI_Reg_bits(LMS7param(MAC), 2); // channel B + SPI_write_batch(backupSXAddr, backupRegsSXT, sizeof(backupRegsSXR) / sizeof(uint16_t)); + Modify_SPI_Reg_bits(LMS7param(MAC), ch); +} + +/** @brief Searches for minimal digital RSSI value by changing given gain parameter + @param param LMS7002M gain correction parameter + @param foundValue returns value which achieved minimal RSSI + @return minimal found RSSI value +*/ +uint32_t LMS7002M::FindMinRSSI_Gain(const LMS7Parameter ¶m, uint16_t *foundValue) +{ + uint32_t RSSI = ~0 - 2; + uint32_t prevRSSI = RSSI + 1; + uint8_t decrement = 2; + uint16_t gcorr = 2047; + while (gcorr > 1024) + { + Modify_SPI_Reg_bits(param, gcorr); + RSSI = GetRSSI(); + if (RSSI < prevRSSI) + { + prevRSSI = RSSI; + *foundValue = gcorr; + gcorr -= decrement; + decrement *= 2; + } + else + { + if (decrement == 2) + break; + gcorr -= decrement; + decrement = 2; + } + } + return prevRSSI; +} + +/** @brief Reads all chip configuration and checks if it matches with local registers copy +*/ +bool LMS7002M::IsSynced() +{ + if (controlPort->IsOpen() == false) + return false; + bool isSynced = true; + liblms7_status status; + + uint8_t ch = (uint8_t)Get_SPI_Reg_bits(LMS7param(MAC)); + + vector addrToRead = mRegistersMap->GetUsedAddresses(0); + vector dataReceived; + dataReceived.resize(addrToRead.size(), 0); + + Modify_SPI_Reg_bits(LMS7param(MAC), 1); + status = SPI_read_batch(&addrToRead[0], &dataReceived[0], addrToRead.size()); + if (status != LIBLMS7_SUCCESS) + { + isSynced = false; + goto isSyncedEnding; + } + + //mask out readonly bits + for (uint16_t j = 0; j < sizeof(readOnlyRegisters) / sizeof(uint16_t); ++j) + for (uint16_t k = 0; k < addrToRead.size(); ++k) + if (readOnlyRegisters[j] == addrToRead[k]) + { + dataReceived[k] &= readOnlyRegistersMasks[j]; + break; + } + + //check if local copy matches chip + for (uint16_t i = 0; i < addrToRead.size(); ++i) + { + if (dataReceived[i] != mRegistersMap->GetValue(0, addrToRead[i])) + { + isSynced = false; + goto isSyncedEnding; + } + } + + addrToRead.clear(); //add only B channel addresses + addrToRead = mRegistersMap->GetUsedAddresses(1); + + //mask out readonly bits + for (uint16_t j = 0; j < sizeof(readOnlyRegisters) / sizeof(uint16_t); ++j) + for (uint16_t k = 0; k < addrToRead.size(); ++k) + if (readOnlyRegisters[j] == addrToRead[k]) + { + dataReceived[k] &= readOnlyRegistersMasks[j]; + break; + } + + Modify_SPI_Reg_bits(LMS7param(MAC), 2); + status = SPI_read_batch(&addrToRead[0], &dataReceived[0], addrToRead.size()); + if (status != LIBLMS7_SUCCESS) + return false; + //check if local copy matches chip + for (uint16_t i = 0; i < addrToRead.size(); ++i) + if (dataReceived[i] != mRegistersMap->GetValue(1, addrToRead[i])) + { + isSynced = false; + break; + } + +isSyncedEnding: + Modify_SPI_Reg_bits(LMS7param(MAC), ch); //restore previously used channel + return isSynced; +} + +/** @brief Writes all registers from host to chip + +When used on Novena board, also changes gpios to match rx path and tx band selections +*/ +liblms7_status LMS7002M::UploadAll() +{ + if (controlPort == NULL) + return LIBLMS7_NO_CONNECTION_MANAGER; + if (controlPort->IsOpen() == false) + return LIBLMS7_NOT_CONNECTED; + + uint8_t ch = (uint8_t)Get_SPI_Reg_bits(LMS7param(MAC)); //remember used channel + + liblms7_status status; + + vector addrToWrite; + vector dataToWrite; + + uint16_t x0020_value = mRegistersMap->GetValue(0, 0x0020); + Modify_SPI_Reg_bits(LMS7param(MAC), 1); //select A channel + + addrToWrite = mRegistersMap->GetUsedAddresses(0); + //remove 0x0020 register from list, to not change MAC + addrToWrite.erase( find(addrToWrite.begin(), addrToWrite.end(), 0x0020) ); + for (auto address : addrToWrite) + dataToWrite.push_back(mRegistersMap->GetValue(0, address)); + + status = SPI_write_batch(&addrToWrite[0], &dataToWrite[0], addrToWrite.size()); + status = LIBLMS7_SUCCESS; + if (status != LIBLMS7_SUCCESS) + return status; + //after all channel A registers have been written, update 0x0020 register value + status = SPI_write(0x0020, x0020_value); + if (status != LIBLMS7_SUCCESS) + return status; + Modify_SPI_Reg_bits(LMS7param(MAC), 2); + if (status != LIBLMS7_SUCCESS) + return status; + + addrToWrite = mRegistersMap->GetUsedAddresses(1); + dataToWrite.clear(); + for (auto address : addrToWrite) + { + dataToWrite.push_back(mRegistersMap->GetValue(1, address)); + } + Modify_SPI_Reg_bits(LMS7param(MAC), 2); //select B channel + status = SPI_write_batch(&addrToWrite[0], &dataToWrite[0], addrToWrite.size()); + if (status != LIBLMS7_SUCCESS) + return status; + Modify_SPI_Reg_bits(LMS7param(MAC), ch); //restore last used channel + + //in case of Novena board, need to update GPIO + if(controlPort->GetInfo().device == LMS_DEV_NOVENA) + { + uint16_t regValue = SPI_read(0x0706) & 0xFFF8; + //lms_gpio2 - tx output selection: + // 0 - TX1_A and TX1_B (Band 1), + // 1 - TX2_A and TX2_B (Band 2) + regValue |= Get_SPI_Reg_bits(LMS7param(SEL_BAND2_TRF)) << 2; //gpio2 + //RX active paths + //lms_gpio0 | lms_gpio1 RX_A RX_B + // 0 0 => no active path + // 1 0 => LNAW_A LNAW_B + // 0 1 => LNAH_A LNAH_B + // 1 1 => LNAL_A LNAL_B + switch(Get_SPI_Reg_bits(LMS7param(SEL_PATH_RFE))) + { + //set gpio1:gpio0 + case 0: regValue |= 0x0; break; + case 1: regValue |= 0x2; break; + case 2: regValue |= 0x3; break; + case 3: regValue |= 0x1; break; + } + SPI_write(0x0706, regValue); + } + return LIBLMS7_SUCCESS; +} + +/** @brief Reads all registers from the chip to host + +When used on Novena board, also updates gpios to match rx path and tx band selections +*/ +liblms7_status LMS7002M::DownloadAll() +{ + if (controlPort == nullptr) + return LIBLMS7_NO_CONNECTION_MANAGER; + if (controlPort->IsOpen() == false) + return LIBLMS7_NOT_CONNECTED; + liblms7_status status; + uint8_t ch = (uint8_t)Get_SPI_Reg_bits(LMS7param(MAC), false); + + vector addrToRead = mRegistersMap->GetUsedAddresses(0); + vector dataReceived; + dataReceived.resize(addrToRead.size(), 0); + Modify_SPI_Reg_bits(LMS7param(MAC), 1); + status = SPI_read_batch(&addrToRead[0], &dataReceived[0], addrToRead.size()); + if (status != LIBLMS7_SUCCESS) + return status; + + for (uint16_t i = 0; i < addrToRead.size(); ++i) + { + uint16_t adr = addrToRead[i]; + uint16_t val = dataReceived[i]; + mRegistersMap->SetValue(0, addrToRead[i], dataReceived[i]); + } + + addrToRead.clear(); //add only B channel addresses + addrToRead = mRegistersMap->GetUsedAddresses(1); + dataReceived.resize(addrToRead.size(), 0); + + Modify_SPI_Reg_bits(LMS7param(MAC), 2); + status = SPI_read_batch(&addrToRead[0], &dataReceived[0], addrToRead.size()); + if (status != LIBLMS7_SUCCESS) + return status; + for (uint16_t i = 0; i < addrToRead.size(); ++i) + mRegistersMap->SetValue(1, addrToRead[i], dataReceived[i]); + + Modify_SPI_Reg_bits(LMS7param(MAC), ch); //retore previously used channel + + //in case of Novena board, update GPIO + if(controlPort->GetInfo().device == LMS_DEV_NOVENA) + { + uint16_t regValue = SPI_read(0x0706) & 0xFFF8; + //lms_gpio2 - tx output selection: + // 0 - TX1_A and TX1_B (Band 1), + // 1 - TX2_A and TX2_B (Band 2) + regValue |= Get_SPI_Reg_bits(LMS7param(SEL_BAND2_TRF)) << 2; //gpio2 + //RX active paths + //lms_gpio0 | lms_gpio1 RX_A RX_B + // 0 0 => no active path + // 1 0 => LNAW_A LNAW_B + // 0 1 => LNAH_A LNAH_B + // 1 1 => LNAL_A LNAL_B + switch(Get_SPI_Reg_bits(LMS7param(SEL_PATH_RFE))) + { + //set gpio1:gpio0 + case 0: regValue |= 0x0; break; + case 1: regValue |= 0x2; break; + case 2: regValue |= 0x3; break; + case 3: regValue |= 0x1; break; + } + SPI_write(0x0706, regValue); + } + + return LIBLMS7_SUCCESS; +} + +/** @brief Configures interfaces for desired frequency + Sets interpolation and decimation, changes MCLK sources and TSP clock dividers accordingly to selected interpolation and decimation +*/ +liblms7_status LMS7002M::SetInterfaceFrequency(float_type cgen_freq_MHz, const uint8_t interpolation, const uint8_t decimation) +{ + Modify_SPI_Reg_bits(LMS7param(HBD_OVR_RXTSP), decimation); + Modify_SPI_Reg_bits(LMS7param(HBI_OVR_TXTSP), interpolation); + liblms7_status status = SetFrequencyCGEN(cgen_freq_MHz); + if (status != LIBLMS7_SUCCESS) + return status; + + if (decimation == 7 || decimation == 0) //bypass + { + Modify_SPI_Reg_bits(LMS7param(RXTSPCLKA_DIV), 0); + Modify_SPI_Reg_bits(LMS7param(RXDIVEN), false); + Modify_SPI_Reg_bits(LMS7param(MCLK2SRC), 3); + } + else + { + uint8_t divider = (uint8_t)pow(2.0, decimation); + if (divider > 1) + Modify_SPI_Reg_bits(LMS7param(RXTSPCLKA_DIV), (divider / 2) - 1); + else + Modify_SPI_Reg_bits(LMS7param(RXTSPCLKA_DIV), 0); + Modify_SPI_Reg_bits(LMS7param(RXDIVEN), true); + Modify_SPI_Reg_bits(LMS7param(MCLK2SRC), 1); + } + if (interpolation == 7 || interpolation == 0) //bypass + { + Modify_SPI_Reg_bits(LMS7param(TXTSPCLKA_DIV), 0); + Modify_SPI_Reg_bits(LMS7param(TXDIVEN), false); + Modify_SPI_Reg_bits(LMS7param(MCLK1SRC), 2); + } + else + { + uint8_t divider = (uint8_t)pow(2.0, interpolation); + if (divider > 1) + Modify_SPI_Reg_bits(LMS7param(TXTSPCLKA_DIV), (divider / 2) - 1); + else + Modify_SPI_Reg_bits(LMS7param(TXTSPCLKA_DIV), 0); + Modify_SPI_Reg_bits(LMS7param(TXDIVEN), true); + Modify_SPI_Reg_bits(LMS7param(MCLK1SRC), 0); + } + return status; +} diff --git a/targets/ARCH/LMSSDR/USERSPACE/LIB/lms7002m/LMS7002M.h b/targets/ARCH/LMSSDR/USERSPACE/LIB/lms7002m/LMS7002M.h new file mode 100644 index 0000000000..81234c28a3 --- /dev/null +++ b/targets/ARCH/LMSSDR/USERSPACE/LIB/lms7002m/LMS7002M.h @@ -0,0 +1,177 @@ +/** +@file LMS7002M.h +@author Lime Microsystems (www.limemicro.com) +@brief LMS7002M transceiver configuration interface +*/ + +#ifndef LMS7API_H +#define LMS7API_H + +#include "LMS7002M_statuses.h" +#include "LMS7002M_parameters.h" +#include "typedefs.h" + +#include + +class LMScomms; +class LMS7002M_RegistersMap; + +class LMS7002M +{ +public: + enum + { + Rx, Tx + }; + + LMS7002M(); + LMS7002M(LMScomms* controlPort); + virtual ~LMS7002M(); + + ///@name Registers writing and reading + liblms7_status UploadAll(); + liblms7_status DownloadAll(); + bool IsSynced(); + + liblms7_status ResetChip(); + liblms7_status LoadConfig(const char* filename); + liblms7_status SaveConfig(const char* filename); + ///@} + + ///@name Registers writing and reading + uint16_t Get_SPI_Reg_bits(const LMS7Parameter ¶m, bool fromChip = true); + uint16_t Get_SPI_Reg_bits(uint16_t address, uint8_t msb, uint8_t lsb, bool fromChip = true); + liblms7_status Modify_SPI_Reg_bits(const LMS7Parameter ¶m, const uint16_t value, bool fromChip = true); + liblms7_status Modify_SPI_Reg_bits(uint16_t address, uint8_t msb, uint8_t lsb, uint16_t value, bool fromChip = true); + liblms7_status SPI_write(uint16_t address, uint16_t data); + uint16_t SPI_read(uint16_t address, bool fromChip = true, liblms7_status *status = 0); + liblms7_status RegistersTest(); + ///@} + + ///@name Transmitter, Receiver calibrations + liblms7_status CalibrateRx(float_type bandwidth_MHz); + liblms7_status CalibrateTx(float_type bandwidth_MHz); + ///@} + + ///@name Filters tuning + enum TxFilter + { + TX_LADDER, TX_REALPOLE, TX_HIGHBAND + }; + enum RxFilter + { + RX_TIA, RX_LPF_LOWBAND, RX_LPF_HIGHBAND + }; + liblms7_status TuneTxFilter(TxFilter filterType, float_type bandwidth_MHz); + liblms7_status TuneTxFilterLowBandChain(float_type ladder_bw_MHz, float_type realpole_bw_MHz); + liblms7_status TuneRxFilter(RxFilter filterType, float_type bandwidth_MHz); + ///@} + + ///@name CGEN and PLL + float_type GetReferenceClk_SX(bool tx); + float_type GetFrequencyCGEN_MHz(); + liblms7_status SetFrequencyCGEN(float_type freq_MHz); + float_type GetFrequencySX_MHz(bool tx, float_type refClk_MHz); + liblms7_status SetFrequencySX(bool tx, float_type freq_MHz, float_type refClk_MHz); + ///VCO modules available for tuning + enum VCO_Module + { + VCO_CGEN, VCO_SXR, VCO_SXT + }; + liblms7_status TuneVCO(VCO_Module module); + ///@} + + ///@name TSP + liblms7_status LoadDC_REG_IQ(bool tx, int16_t I, int16_t Q); + liblms7_status SetNCOFrequency(bool tx, uint8_t index, float_type freq_MHz); + float_type GetNCOFrequency_MHz(bool tx, uint8_t index, float_type refClk_MHz, bool fromChip = true); + liblms7_status SetNCOPhaseOffsetForMode0(bool tx, float_type angle_Deg); + liblms7_status SetNCOPhaseOffset(bool tx, uint8_t index, float_type angle_Deg); + float_type GetNCOPhaseOffset_Deg(bool tx, uint8_t index); + liblms7_status SetGFIRCoefficients(bool tx, uint8_t GFIR_index, const int16_t *coef, uint8_t coefCount); + liblms7_status GetGFIRCoefficients(bool tx, uint8_t GFIR_index, int16_t *coef, uint8_t coefCount); + float_type GetReferenceClk_TSP_MHz(bool tx); + ///@} + + liblms7_status SetInterfaceFrequency(float_type cgen_freq_MHz, const uint8_t interpolation, const uint8_t decimation); + + ///enumeration to indicate module registers intervals + enum MemorySection + { + LimeLight = 0, EN_DIR, AFE, BIAS, XBUF, CGEN, LDO, BIST, CDS, + TRF, TBB, RFE, RBB, SX, TxTSP, + TxNCO, TxGFIR1, TxGFIR2, TxGFIR3a, TxGFIR3b, TxGFIR3c, + RxTSP, RxNCO, RxGFIR1, RxGFIR2, RxGFIR3a, RxGFIR3b, RxGFIR3c, + MEMORY_SECTIONS_COUNT + }; + virtual liblms7_status SetDefaults(MemorySection module); + LMScomms* GetControlPort() const { return controlPort;}; + + static const float_type gLadder_lower_limit; + static const float_type gLadder_higher_limit; + static const float_type gRealpole_lower_limit; + static const float_type gRealpole_higher_limit; + static const float_type gHighband_lower_limit; + static const float_type gHighband_higher_limit; + + static const float_type gRxTIA_higher_limit; + static const float_type gRxTIA_lower_limit_g1; + static const float_type gRxTIA_lower_limit_g23; + static const float_type gRxLPF_low_lower_limit; + static const float_type gRxLPF_low_higher_limit; + static const float_type gRxLPF_high_lower_limit; + static const float_type gRxLPF_high_higher_limit; + + static float_type gVCO_frequency_table[3][2]; + static float_type gCGEN_VCO_frequencies[2]; + + //protected: + LMS7002M_RegistersMap *mRegistersMap; + static const uint16_t readOnlyRegisters[]; + static const uint16_t readOnlyRegistersMasks[]; + + uint16_t MemorySectionAddresses[MEMORY_SECTIONS_COUNT][2]; + ///@name Algorithms functions + void BackupAllRegisters(); + void RestoreAllRegisters(); + uint32_t GetRSSI(); + void SetRxDCOFF(int8_t offsetI, int8_t offsetQ); + uint32_t FindMinRSSI_Gain(const LMS7Parameter ¶m, uint16_t *foundValue); + uint32_t FindMinRSSI(const LMS7Parameter ¶m, const int16_t startValue, int16_t *result, const uint8_t scanWidth, const uint8_t twoCompl, int8_t stepMult = 1); + uint32_t FindMinRSSI(const uint16_t addr, const uint8_t msb, const uint8_t lsb, const int16_t startValue, int16_t *result, const uint8_t scanWidth, const uint8_t twoCompl, int8_t stepMult = 1); + void CalibrateRxDC_RSSI(); + liblms7_status CalibrateTxSetup(float_type bandwidth_MHz); + liblms7_status CalibrateRxSetup(float_type bandwidth_MHz); + liblms7_status FixRXSaturation(); + void FilterTuning_AdjustGains(); + liblms7_status TuneTxFilterSetup(TxFilter type, float_type cutoff_MHz); + liblms7_status TuneRxFilterSetup(RxFilter type, float_type cutoff_MHz); + liblms7_status RFE_TIA_Calibration(float_type TIA_freq_MHz); + liblms7_status RxLPFLow_Calibration(float_type RxLPFL_freq_MHz); + liblms7_status RxLPFHigh_Calibration(float_type RxLPFH_freq_MHz); + + liblms7_status RegistersTestInterval(uint16_t startAddr, uint16_t endAddr, uint16_t pattern, std::stringstream &ss); + liblms7_status SPI_write_batch(const uint16_t* spiAddr, const uint16_t* spiData, uint16_t cnt); + liblms7_status SPI_read_batch(const uint16_t* spiAddr, uint16_t* spiData, uint16_t cnt); + liblms7_status Modify_SPI_Reg_mask(const uint16_t *addr, const uint16_t *masks, const uint16_t *values, uint8_t start, uint8_t stop); + ///@} + ///Reference clock used for Receiver frequency calculations + float_type mRefClkSXR_MHz; + ///Reference clock used for Transmitter frequency calculations + float_type mRefClkSXT_MHz; + + enum LogType + { + LOG_INFO, + LOG_WARNING, + LOG_ERROR, + LOG_DATA + }; + virtual void Log(const char* text, LogType type); + + ///port used for communicating with LMS7002M + LMScomms* controlPort; + + liblms7_status LoadConfigLegacyFile(const char* filename); +}; +#endif diff --git a/targets/ARCH/LMSSDR/USERSPACE/LIB/lms7002m/LMS7002M_RegistersMap.cpp b/targets/ARCH/LMSSDR/USERSPACE/LIB/lms7002m/LMS7002M_RegistersMap.cpp new file mode 100644 index 0000000000..8c870ffcc0 --- /dev/null +++ b/targets/ARCH/LMSSDR/USERSPACE/LIB/lms7002m/LMS7002M_RegistersMap.cpp @@ -0,0 +1,68 @@ +#include "LMS7002M_RegistersMap.h" +#include "LMS7002M_parameters.h" + +LMS7002M_RegistersMap::LMS7002M_RegistersMap() +{ + +} + +LMS7002M_RegistersMap::~LMS7002M_RegistersMap() +{ + +} + +uint16_t LMS7002M_RegistersMap::GetDefaultValue(uint16_t address) const +{ + std::map::const_iterator iter = mChannelA.find(address); + if( iter != mChannelA.end()) + return iter->second.defaultValue; + else + return 0; +} + +void LMS7002M_RegistersMap::InitializeDefaultValues(const std::vector parameterList) +{ + for(auto parameter : parameterList) + { + uint16_t regValue = mChannelA[parameter->address].defaultValue; + mChannelA[parameter->address].defaultValue = regValue | (parameter->defaultValue << parameter->lsb); + mChannelA[parameter->address].value = mChannelA[parameter->address].defaultValue; + if(parameter->address >= 0x0100) + mChannelB[parameter->address].value = mChannelA[parameter->address].value; + } +} + +void LMS7002M_RegistersMap::SetValue(uint8_t channel, const uint16_t address, const uint16_t value) +{ + if(channel == 0) + mChannelA[address].value = value; + else if(channel == 1) + mChannelB[address].value = value; +} + +uint16_t LMS7002M_RegistersMap::GetValue(uint8_t channel, uint16_t address) const +{ + const std::map *regMap; + if(channel == 0) + regMap = &mChannelA; + else if(channel == 1) + regMap = &mChannelB; + std::map::const_iterator iter; + iter = regMap->find(address); + if (iter != regMap->end()) + return iter->second.value; + else + return 0; +} + +std::vector LMS7002M_RegistersMap::GetUsedAddresses(const uint8_t channel) const +{ + std::vector addresses; + if(channel == 0) + for(auto iter : mChannelA) + addresses.push_back(iter.first); + else if(channel == 1) + for(auto iter : mChannelB) + addresses.push_back(iter.first); + return addresses; +} diff --git a/targets/ARCH/LMSSDR/USERSPACE/LIB/lms7002m/LMS7002M_RegistersMap.h b/targets/ARCH/LMSSDR/USERSPACE/LIB/lms7002m/LMS7002M_RegistersMap.h new file mode 100644 index 0000000000..5ccda752db --- /dev/null +++ b/targets/ARCH/LMSSDR/USERSPACE/LIB/lms7002m/LMS7002M_RegistersMap.h @@ -0,0 +1,35 @@ +#ifndef LMS7002M_REGISTERS_MAP_H +#define LMS7002M_REGISTERS_MAP_H + +#include +#include +#include + +struct LMS7Parameter; + +class LMS7002M_RegistersMap +{ +public: + struct Register + { + uint16_t value; + uint16_t defaultValue; + uint16_t mask; + }; + + LMS7002M_RegistersMap(); + ~LMS7002M_RegistersMap(); + + uint16_t GetValue(uint8_t channel, uint16_t address) const; + void SetValue(uint8_t channel, const uint16_t address, const uint16_t value); + + void InitializeDefaultValues(const std::vector parameterList); + uint16_t GetDefaultValue(uint16_t address) const; + std::vector GetUsedAddresses(const uint8_t channel) const; + +protected: + std::map mChannelA; + std::map mChannelB; +}; + +#endif diff --git a/targets/ARCH/LMSSDR/USERSPACE/LIB/lms7002m/LMS7002M_filtersCalibration.cpp b/targets/ARCH/LMSSDR/USERSPACE/LIB/lms7002m/LMS7002M_filtersCalibration.cpp new file mode 100644 index 0000000000..2f3d38c1b5 --- /dev/null +++ b/targets/ARCH/LMSSDR/USERSPACE/LIB/lms7002m/LMS7002M_filtersCalibration.cpp @@ -0,0 +1,861 @@ +/** +@file LMS7002M_filtersCalibration.cpp +@author Lime Microsystems (www.limemicro.com) +@brief Implementation of LMS7002M transceiver filters calibration algorithms +*/ + +#include "LMS7002M.h" +#include + +///define for parameter enumeration if prefix might be needed +#define LMS7param(id) id + +const float_type LMS7002M::gLadder_lower_limit = 2; +const float_type LMS7002M::gLadder_higher_limit = 16; +const float_type LMS7002M::gRealpole_lower_limit = 0.8; +const float_type LMS7002M::gRealpole_higher_limit = 3.2; +const float_type LMS7002M::gHighband_lower_limit = 28; +const float_type LMS7002M::gHighband_higher_limit = 70; + +const float_type LMS7002M::gRxTIA_higher_limit = 60; +const float_type LMS7002M::gRxTIA_lower_limit_g1 = 1.5; +const float_type LMS7002M::gRxTIA_lower_limit_g23 = 0.5; +const float_type LMS7002M::gRxLPF_low_lower_limit = 1; +const float_type LMS7002M::gRxLPF_low_higher_limit = 20; +const float_type LMS7002M::gRxLPF_high_lower_limit = 20; +const float_type LMS7002M::gRxLPF_high_higher_limit = 70; + +liblms7_status LMS7002M::TuneTxFilterSetup(LMS7002M::TxFilter type, float_type cutoff_MHz) +{ + Modify_SPI_Reg_bits(LMS7param(EN_G_RFE), 0); + Modify_SPI_Reg_bits(LMS7param(EN_G_TRF), 0); + + //RBB + SetDefaults(RBB); + Modify_SPI_Reg_bits(LMS7param(PD_LPFL_RBB), 1); + Modify_SPI_Reg_bits(LMS7param(INPUT_CTL_PGA_RBB), 3); + Modify_SPI_Reg_bits(LMS7param(ICT_PGA_OUT_RBB), 20); + Modify_SPI_Reg_bits(LMS7param(ICT_PGA_IN_RBB), 20); + Modify_SPI_Reg_bits(LMS7param(C_CTL_PGA_RBB), 3); + + //TBB + SetDefaults(TBB); + Modify_SPI_Reg_bits(LMS7param(CG_IAMP_TBB), 1); + Modify_SPI_Reg_bits(LMS7param(ICT_IAMP_FRP_TBB), 1); + Modify_SPI_Reg_bits(LMS7param(ICT_IAMP_GG_FRP_TBB), 6); + + //AFE + uint8_t isel_dac_afe = (uint8_t)Get_SPI_Reg_bits(0x0082, 15, 13); + SetDefaults(AFE); + if (Get_SPI_Reg_bits(LMS7param(MAC)) == 2) + { + Modify_SPI_Reg_bits(LMS7param(PD_TX_AFE2), 0); //PD_RX_AFE2 0 + Modify_SPI_Reg_bits(LMS7param(PD_RX_AFE2), 0); //PD_RX_AFE2 0 + } + Modify_SPI_Reg_bits(0x0082, 15, 13, isel_dac_afe); + + //BIAS + uint8_t rpcalib_bias = (uint8_t)Get_SPI_Reg_bits(LMS7param(RP_CALIB_BIAS)); + SetDefaults(BIAS); + Modify_SPI_Reg_bits(LMS7param(RP_CALIB_BIAS), rpcalib_bias); + + //XBUF + Modify_SPI_Reg_bits(LMS7param(PD_XBUF_RX), 0); + Modify_SPI_Reg_bits(LMS7param(PD_XBUF_TX), 0); + Modify_SPI_Reg_bits(LMS7param(EN_G_XBUF), 1); + + //CGEN + SetDefaults(CGEN); + + //txtsp + SetDefaults(TxTSP); + Modify_SPI_Reg_bits(LMS7param(TSGMODE_TXTSP), 1); + Modify_SPI_Reg_bits(LMS7param(INSEL_TXTSP), 1); + Modify_SPI_Reg_bits(0x0208, 6, 4, 7); + LoadDC_REG_IQ(Tx, (int16_t)0x7FFF, (int16_t)0x8000); + float_type txNCOfreq = 0.05; + SetNCOFrequency(Tx, 0, txNCOfreq); + + //rxtsp + SetDefaults(RxTSP); + SetNCOFrequency(Rx, 0, txNCOfreq - 1); + + Modify_SPI_Reg_bits(LMS7param(AGC_MODE_RXTSP), 1); + Modify_SPI_Reg_bits(0x040C, 6, 3, 0x07); + + Modify_SPI_Reg_bits(LMS7param(AGC_AVG_RXTSP), 7); + Modify_SPI_Reg_bits(LMS7param(CMIX_GAIN_RXTSP), 1); + + return LIBLMS7_SUCCESS; +} + + +liblms7_status LMS7002M::TuneTxFilter(LMS7002M::TxFilter type, float_type cutoff_MHz) +{ + liblms7_status status; + float_type lowLimit = 0; + float_type highLimit = 1000; + uint32_t rssi = 0; + int8_t dir; + uint8_t ccal_lpflad_tbb; + uint32_t rssi_value_100k; + int16_t rcal; + + float_type ncoFreq = 0.05; + float_type cgenFreq; + uint8_t loopb_tbb; + uint8_t cg_iamp_tbb = 1; + uint8_t bypladder_tbb; + uint8_t pd_lpfh_tbb; + uint8_t pd_lpflad_tbb; + uint8_t pd_lpfs5; + uint8_t en_g_tbb = 1; + uint8_t pd_iamp_tbb = 0; + uint8_t tstin_tbb = 0; + + BackupAllRegisters(); + //float_type userCLKGENfreq = GetFrequencyCGEN_MHz(); + + status = TuneTxFilterSetup(type, cutoff_MHz); + if (status != LIBLMS7_SUCCESS) + goto TxFilterTuneEnd; + cgenFreq = cutoff_MHz * 20; + if (cgenFreq < 60) + cgenFreq = 60; + if (cgenFreq > 640) + cgenFreq = 640; + if (type == TX_LADDER) + { + loopb_tbb = 2; + bypladder_tbb = 0; + pd_lpfh_tbb = 1; + pd_lpflad_tbb = 0; + pd_lpfs5 = 1; + lowLimit = gLadder_lower_limit; + highLimit = gLadder_higher_limit; + } + else if (type == TX_REALPOLE) + { + loopb_tbb = 3; + bypladder_tbb = 1; + pd_lpfh_tbb = 1; + pd_lpflad_tbb = 1; + pd_lpfs5 = 0; + lowLimit = gRealpole_lower_limit; + highLimit = gRealpole_higher_limit; + } + else if (type == TX_HIGHBAND) + { + loopb_tbb = 3; + bypladder_tbb = 0; + pd_lpfh_tbb = 0; + pd_lpflad_tbb = 1; + pd_lpfs5 = 1; + lowLimit = gHighband_lower_limit; + highLimit = gHighband_higher_limit; + } + if (cutoff_MHz == cgenFreq / 16) + cgenFreq -= 10; + + if (cutoff_MHz < lowLimit || cutoff_MHz > highLimit) + { + status = LIBLMS7_FREQUENCY_OUT_OF_RANGE; + goto TxFilterTuneEnd; + } + + status = SetFrequencyCGEN(cgenFreq); + if (status != LIBLMS7_SUCCESS) + goto TxFilterTuneEnd; + + Modify_SPI_Reg_bits(LMS7param(LOOPB_TBB), loopb_tbb); + Modify_SPI_Reg_bits(LMS7param(CG_IAMP_TBB), cg_iamp_tbb); + Modify_SPI_Reg_bits(LMS7param(BYPLADDER_TBB), bypladder_tbb); + Modify_SPI_Reg_bits(LMS7param(TSTIN_TBB), tstin_tbb); + Modify_SPI_Reg_bits(LMS7param(PD_LPFH_TBB), pd_lpfh_tbb); + Modify_SPI_Reg_bits(LMS7param(PD_LPFIAMP_TBB), pd_iamp_tbb); + Modify_SPI_Reg_bits(LMS7param(PD_LPFLAD_TBB), pd_lpflad_tbb); + Modify_SPI_Reg_bits(LMS7param(PD_LPFS5_TBB), pd_lpfs5); + Modify_SPI_Reg_bits(LMS7param(EN_G_TBB), en_g_tbb); + + //B + //LADDER coefficients + float_type p1, p2, p3, p4, p5; + switch (type) + { + case TX_LADDER: + p1 = 1.29858903647958E-16; + p2 = -0.000110746929967704; + p3 = 0.00277593485991029; + p4 = 21.0384293169607; + p5 = -48.4092606238297; + break; + case TX_REALPOLE: + p1 = 1.93821841029921E-15; + p2 = -0.0429694461214244; + p3 = 0.253501254059498; + p4 = 88.9545445989649; + p5 = -48.0847491316861; + break; + case TX_HIGHBAND: + p1 = 1.10383E-06; + p2 = -0.0002108; + p3 = 0.019049487; + p4 = 1.433174459; + p5 = -47.69507793; + break; + } + rcal = (int16_t)(pow(cutoff_MHz, 4)*p1 + pow(cutoff_MHz, 3)*p2 + pow(cutoff_MHz, 2)*p3 + cutoff_MHz * p4 + p5); + if (rcal < 0) + rcal = 0; + if (rcal > 255) + rcal = 255; + + if (type == TX_REALPOLE) + Modify_SPI_Reg_bits(LMS7param(RCAL_LPFS5_TBB), rcal); + else if (type == TX_LADDER) + Modify_SPI_Reg_bits(LMS7param(RCAL_LPFLAD_TBB), rcal); + else if (type == TX_HIGHBAND) + Modify_SPI_Reg_bits(LMS7param(RCAL_LPFH_TBB), rcal); + + FilterTuning_AdjustGains(); + + rssi_value_100k = (uint32_t)( GetRSSI()*0.707 ); + + SetNCOFrequency(Tx, 0, cutoff_MHz); + SetNCOFrequency(Rx, 0, cutoff_MHz - 1); + + for (ccal_lpflad_tbb = 31; ccal_lpflad_tbb > 0; --ccal_lpflad_tbb) + { + Modify_SPI_Reg_bits(LMS7param(CCAL_LPFLAD_TBB), ccal_lpflad_tbb); + rssi = GetRSSI(); + if (rssi > rssi_value_100k && ccal_lpflad_tbb == 31) + break; //skip this search, continue to advanced search + if (rssi > rssi_value_100k) + { + status = LIBLMS7_SUCCESS; + goto TxFilterTuneEnd; //found correct value + } + } + + + //advanced search for c and r values + status = LIBLMS7_FAILURE; + dir = ccal_lpflad_tbb == 31 ? -1 : 1; + while (rcal > 0 && rcal < 255) + { + rcal += 5 * dir; + if (rcal < 0 && rcal > 255) + break; + if (type == TX_REALPOLE) + Modify_SPI_Reg_bits(LMS7param(RCAL_LPFS5_TBB), rcal); + else if (type == TX_LADDER) + Modify_SPI_Reg_bits(LMS7param(RCAL_LPFLAD_TBB), rcal); + else if (type == TX_HIGHBAND) + Modify_SPI_Reg_bits(LMS7param(RCAL_LPFH_TBB), rcal); + SetNCOFrequency(Tx, 0, ncoFreq); + SetNCOFrequency(Rx, 0, ncoFreq - 1); + Modify_SPI_Reg_bits(LMS7param(CCAL_LPFLAD_TBB), 16); + rssi_value_100k = GetRSSI(); + SetNCOFrequency(Tx, 0, cutoff_MHz); + SetNCOFrequency(Rx, 0, cutoff_MHz - 1); + for (ccal_lpflad_tbb = 31; ccal_lpflad_tbb > 0; --ccal_lpflad_tbb) + { + Modify_SPI_Reg_bits(LMS7param(CCAL_LPFLAD_TBB), ccal_lpflad_tbb); + rssi = GetRSSI(); + if (rssi > rssi_value_100k*0.707 && ccal_lpflad_tbb == 31) + break; //skip c search, need to change r value + if (rssi > rssi_value_100k*0.707) + { + status = LIBLMS7_SUCCESS; + goto TxFilterTuneEnd; + } + } + } + + //end +TxFilterTuneEnd: + RestoreAllRegisters(); + if (status != LIBLMS7_SUCCESS) + return status; + Modify_SPI_Reg_bits(LMS7param(CCAL_LPFLAD_TBB), ccal_lpflad_tbb); + Modify_SPI_Reg_bits(LMS7param(ICT_IAMP_FRP_TBB), 1); + Modify_SPI_Reg_bits(LMS7param(ICT_IAMP_GG_FRP_TBB), 6); + + if (type == TX_REALPOLE) + Modify_SPI_Reg_bits(LMS7param(RCAL_LPFS5_TBB), rcal); + else if (type == TX_LADDER) + Modify_SPI_Reg_bits(LMS7param(RCAL_LPFLAD_TBB), rcal); + else if (type == TX_HIGHBAND) + { + Modify_SPI_Reg_bits(LMS7param(RCAL_LPFH_TBB), rcal); + Modify_SPI_Reg_bits(0x0105, 4, 0, 0x7); //set powerdowns + } + return LIBLMS7_SUCCESS; +} + +void LMS7002M::FilterTuning_AdjustGains() +{ + uint8_t cg_iamp_tbb; + uint32_t rssi = 0; + const uint32_t rssi_required = 0x8400; + uint8_t g_pga_rbb = (uint8_t)Get_SPI_Reg_bits(LMS7param(G_PGA_RBB)); + + while (g_pga_rbb < 31) + { + cg_iamp_tbb = 0; + while (cg_iamp_tbb < 63 && rssi < rssi_required) + { + Modify_SPI_Reg_bits(LMS7param(CG_IAMP_TBB), cg_iamp_tbb); + rssi = GetRSSI(); + if (rssi > rssi_required) + return; + ++cg_iamp_tbb; + } + g_pga_rbb += 6; + if (g_pga_rbb > 31) + g_pga_rbb = 31; + Modify_SPI_Reg_bits(LMS7param(G_PGA_RBB), g_pga_rbb); + } +} + +liblms7_status LMS7002M::TuneTxFilterLowBandChain(float_type bandwidth, float_type realpole_MHz) +{ + uint32_t rssi; + uint32_t rssi_value_10k; + bool prevRSSIbigger; + int16_t rcal; + float_type p1,p2,p3,p4,p5; + float_type ncoFreq = 0.05; + float_type cgenFreq; + BackupAllRegisters(); + + liblms7_status status = TuneTxFilter(TX_LADDER, bandwidth); + uint8_t ladder_c_value = (uint8_t)Get_SPI_Reg_bits(LMS7param(CCAL_LPFLAD_TBB)); + uint8_t ladder_r_value = (uint8_t)Get_SPI_Reg_bits(LMS7param(RCAL_LPFLAD_TBB)); + status = TuneTxFilterSetup(TX_LADDER, bandwidth); + + if (bandwidth < gLadder_lower_limit || bandwidth > gLadder_higher_limit) + { + status = LIBLMS7_FREQUENCY_OUT_OF_RANGE; + goto TxFilterLowBandChainEnd; + } + + //realpole calibration + //float userCLKGENfreq = GetFrequencyCGEN(); + + cgenFreq = realpole_MHz * 20; + if (cgenFreq < 60) + cgenFreq = 60; + if (cgenFreq > 640) + cgenFreq = 640; + + if (realpole_MHz < gRealpole_lower_limit || realpole_MHz > gRealpole_higher_limit) + { + status = LIBLMS7_FREQUENCY_OUT_OF_RANGE; + goto TxFilterLowBandChainEnd; + } + + status = SetFrequencyCGEN(cgenFreq); + if (status != LIBLMS7_SUCCESS) + goto TxFilterLowBandChainEnd; + + Modify_SPI_Reg_bits(LMS7param(LOOPB_TBB), 3); + Modify_SPI_Reg_bits(LMS7param(CG_IAMP_TBB), 1); + Modify_SPI_Reg_bits(LMS7param(BYPLADDER_TBB), 1); + Modify_SPI_Reg_bits(LMS7param(TSTIN_TBB), 0); + Modify_SPI_Reg_bits(LMS7param(PD_LPFH_TBB), 1); + Modify_SPI_Reg_bits(LMS7param(PD_LPFIAMP_TBB), 0); + Modify_SPI_Reg_bits(LMS7param(PD_LPFLAD_TBB), 1); + Modify_SPI_Reg_bits(LMS7param(PD_LPFS5_TBB), 0); + Modify_SPI_Reg_bits(LMS7param(EN_G_TBB), 1); + + //B + p1 = 1.93821841029921E-15; + p2 = -0.0429694461214244; + p3 = 0.253501254059498; + p4 = 88.9545445989649; + p5 = -48.0847491316861; + rcal = (int16_t)(pow(realpole_MHz, 4)*p1 + pow(realpole_MHz, 3)*p2 + pow(realpole_MHz, 2)*p3 + realpole_MHz * p4 + p5); + if (rcal < 0) + rcal = 0; + if (rcal > 255) + rcal = 255; + Modify_SPI_Reg_bits(LMS7param(RCAL_LPFS5_TBB), rcal); + + FilterTuning_AdjustGains(); + + rssi_value_10k = GetRSSI(); + SetNCOFrequency(Tx, 0, realpole_MHz); + SetNCOFrequency(Rx, 0, realpole_MHz - 1); + + prevRSSIbigger = GetRSSI() > rssi_value_10k*0.707; + status = LIBLMS7_FAILURE; //assuming r value is not found + while (rcal >= 0 && rcal < 256) + { + Modify_SPI_Reg_bits(LMS7param(RCAL_LPFS5_TBB), rcal); + SetNCOFrequency(Tx, 0, ncoFreq); + SetNCOFrequency(Rx, 0, ncoFreq - 1); + rssi_value_10k = (uint32_t)( GetRSSI()*0.707 ); + + SetNCOFrequency(Tx, 0, realpole_MHz); + SetNCOFrequency(Rx, 0, realpole_MHz - 1); + + rssi = GetRSSI(); + if (rssi > rssi_value_10k) + --rcal; + else + { + if (prevRSSIbigger) + { + --rcal; + status = LIBLMS7_SUCCESS; + goto TxFilterLowBandChainEnd; + } + ++rcal; + } + prevRSSIbigger = rssi > rssi_value_10k; + } + + //end +TxFilterLowBandChainEnd: + RestoreAllRegisters(); + if (status != LIBLMS7_SUCCESS) + return status; + + Modify_SPI_Reg_bits(LMS7param(CCAL_LPFLAD_TBB), ladder_c_value); + Modify_SPI_Reg_bits(LMS7param(RCAL_LPFLAD_TBB), ladder_r_value); + Modify_SPI_Reg_bits(LMS7param(ICT_IAMP_FRP_TBB), 1); + Modify_SPI_Reg_bits(LMS7param(ICT_IAMP_GG_FRP_TBB), 6); + Modify_SPI_Reg_bits(LMS7param(RCAL_LPFS5_TBB), rcal); + Modify_SPI_Reg_bits(0x0105, 4, 0, 0x11); //set powerdowns + + return LIBLMS7_SUCCESS; +} + +liblms7_status LMS7002M::TuneRxFilter(RxFilter filter, float_type bandwidth_MHz) +{ + liblms7_status status; + uint16_t cfb_tia_rfe; + uint16_t c_ctl_lpfl_rbb; + uint8_t ccomp_tia_rfe; + uint8_t rcomp_tia_rfe; + uint8_t c_ctl_lpfh_rbb; + uint8_t ict_pga_out; + uint8_t ict_pga_in; + uint8_t r_ctl_lpf_rbb; + uint8_t c_ctl_pga_rbb; + uint8_t rcc_ctl_lpfl_rbb; + uint8_t rcc_ctl_lpfh_rbb; + float_type lowerLimit; + float_type higherLimit; + if (filter == RX_TIA) + { + lowerLimit = Get_SPI_Reg_bits(LMS7param(G_TIA_RFE)) == 1 ? gRxTIA_lower_limit_g1 : gRxTIA_lower_limit_g23; + higherLimit = gRxTIA_higher_limit; + } + else if (filter == RX_LPF_LOWBAND) + { + lowerLimit = gRxLPF_low_lower_limit; + higherLimit = gRxLPF_low_higher_limit; + } + else if (filter == RX_LPF_HIGHBAND) + { + lowerLimit = gRxLPF_high_lower_limit; + higherLimit = gRxLPF_high_higher_limit; + } + if (bandwidth_MHz < lowerLimit || bandwidth_MHz > higherLimit) + return LIBLMS7_FREQUENCY_OUT_OF_RANGE; + + BackupAllRegisters(); + + status = TuneRxFilterSetup(filter, bandwidth_MHz); + if (status != LIBLMS7_SUCCESS) + goto RxFilterTuneEnd; + + if (filter == RX_TIA) + status = RFE_TIA_Calibration(bandwidth_MHz); + else if (filter == RX_LPF_LOWBAND) + status = RxLPFLow_Calibration(bandwidth_MHz); + else if (filter == RX_LPF_HIGHBAND) + status = RxLPFHigh_Calibration(bandwidth_MHz); + + cfb_tia_rfe = Get_SPI_Reg_bits(LMS7param(CFB_TIA_RFE)); + c_ctl_lpfl_rbb = Get_SPI_Reg_bits(LMS7param(C_CTL_LPFL_RBB)); + ccomp_tia_rfe = (int8_t)Get_SPI_Reg_bits(LMS7param(CCOMP_TIA_RFE)); + rcomp_tia_rfe = (int8_t)Get_SPI_Reg_bits(LMS7param(RCOMP_TIA_RFE)); + c_ctl_lpfh_rbb = (int8_t)Get_SPI_Reg_bits(LMS7param(C_CTL_LPFH_RBB)); + ict_pga_out = (int8_t)Get_SPI_Reg_bits(LMS7param(ICT_PGA_OUT_RBB)); + ict_pga_in = (int8_t)Get_SPI_Reg_bits(LMS7param(ICT_PGA_IN_RBB)); + r_ctl_lpf_rbb = (int8_t)Get_SPI_Reg_bits(LMS7param(R_CTL_LPF_RBB)); + c_ctl_pga_rbb = (int8_t)Get_SPI_Reg_bits(LMS7param(C_CTL_PGA_RBB)); + rcc_ctl_lpfl_rbb = (int8_t)Get_SPI_Reg_bits(LMS7param(RCC_CTL_LPFL_RBB)); + rcc_ctl_lpfh_rbb = (int8_t)Get_SPI_Reg_bits(LMS7param(RCC_CTL_LPFH_RBB)); + +RxFilterTuneEnd: + RestoreAllRegisters(); + if (status != LIBLMS7_SUCCESS) + return status; + + if (filter == RX_TIA) + { + Modify_SPI_Reg_bits(LMS7param(ICT_TIAMAIN_RFE), 2); + Modify_SPI_Reg_bits(LMS7param(ICT_TIAOUT_RFE), 2); + Modify_SPI_Reg_bits(LMS7param(RFB_TIA_RFE), 16); + Modify_SPI_Reg_bits(LMS7param(CFB_TIA_RFE), cfb_tia_rfe); + Modify_SPI_Reg_bits(LMS7param(CCOMP_TIA_RFE), ccomp_tia_rfe); + Modify_SPI_Reg_bits(LMS7param(RCOMP_TIA_RFE), rcomp_tia_rfe); + Modify_SPI_Reg_bits(0x010c, 1, 0, 0x1); + } + else if (filter == RX_LPF_LOWBAND) + { + Modify_SPI_Reg_bits(LMS7param(RCC_CTL_LPFL_RBB), rcc_ctl_lpfl_rbb); + Modify_SPI_Reg_bits(LMS7param(C_CTL_LPFL_RBB), c_ctl_lpfl_rbb); + Modify_SPI_Reg_bits(LMS7param(ICT_PGA_OUT_RBB), ict_pga_out); + Modify_SPI_Reg_bits(LMS7param(ICT_PGA_IN_RBB), ict_pga_in); + Modify_SPI_Reg_bits(LMS7param(R_CTL_LPF_RBB), r_ctl_lpf_rbb); + Modify_SPI_Reg_bits(LMS7param(C_CTL_PGA_RBB), c_ctl_pga_rbb); + Modify_SPI_Reg_bits(0x0115, 3, 0, 0x9); + Modify_SPI_Reg_bits(0x0118, 15, 13, 0x1); + } + else if (filter == RX_LPF_HIGHBAND) + { + Modify_SPI_Reg_bits(LMS7param(RCC_CTL_LPFH_RBB), rcc_ctl_lpfh_rbb); + Modify_SPI_Reg_bits(LMS7param(C_CTL_LPFH_RBB), c_ctl_lpfh_rbb); + Modify_SPI_Reg_bits(LMS7param(ICT_PGA_OUT_RBB), ict_pga_out); + Modify_SPI_Reg_bits(LMS7param(ICT_PGA_IN_RBB), ict_pga_in); + Modify_SPI_Reg_bits(LMS7param(R_CTL_LPF_RBB), r_ctl_lpf_rbb); + Modify_SPI_Reg_bits(LMS7param(C_CTL_PGA_RBB), c_ctl_pga_rbb); + Modify_SPI_Reg_bits(0x0115, 3, 0, 0x5); + Modify_SPI_Reg_bits(0x0118, 15, 13, 0x0); + } + return LIBLMS7_SUCCESS; +} + +liblms7_status LMS7002M::TuneRxFilterSetup(RxFilter type, float_type cutoff_MHz) +{ + liblms7_status status; + uint8_t ch = (uint8_t)Get_SPI_Reg_bits(LMS7param(MAC)); + + //RFE + uint8_t g_tia_rfe = (uint8_t)Get_SPI_Reg_bits(LMS7param(G_TIA_RFE)); + SetDefaults(RFE); + Modify_SPI_Reg_bits(LMS7param(SEL_PATH_RFE), 2); + + if (ch == 2) + Modify_SPI_Reg_bits(LMS7param(EN_NEXTRX_RFE), 1); + else + Modify_SPI_Reg_bits(LMS7param(EN_NEXTRX_RFE), 0); + + Modify_SPI_Reg_bits(LMS7param(G_RXLOOPB_RFE), 8); + Modify_SPI_Reg_bits(LMS7param(PD_RLOOPB_2_RFE), 0); + Modify_SPI_Reg_bits(LMS7param(EN_INSHSW_LB2_RFE), 0); + Modify_SPI_Reg_bits(LMS7param(PD_MXLOBUF_RFE), 0); + Modify_SPI_Reg_bits(LMS7param(PD_QGEN_RFE), 0); + Modify_SPI_Reg_bits(LMS7param(ICT_TIAMAIN_RFE), 2); + Modify_SPI_Reg_bits(LMS7param(ICT_TIAOUT_RFE), 2); + Modify_SPI_Reg_bits(LMS7param(RFB_TIA_RFE), 16); + Modify_SPI_Reg_bits(LMS7param(G_TIA_RFE), g_tia_rfe); + + //RBB + SetDefaults(RBB); + Modify_SPI_Reg_bits(LMS7param(ICT_PGA_OUT_RBB), 20); + Modify_SPI_Reg_bits(LMS7param(ICT_PGA_IN_RBB), 20); + Modify_SPI_Reg_bits(LMS7param(C_CTL_PGA_RBB), 3); + + //TRF + SetDefaults(TRF); + Modify_SPI_Reg_bits(LMS7param(L_LOOPB_TXPAD_TRF), 0); + Modify_SPI_Reg_bits(LMS7param(EN_LOOPB_TXPAD_TRF), 1); + if (ch == 2) + Modify_SPI_Reg_bits(LMS7param(EN_NEXTTX_TRF), 1); + else + Modify_SPI_Reg_bits(LMS7param(EN_NEXTTX_TRF), 0); + Modify_SPI_Reg_bits(LMS7param(SEL_BAND1_TRF), 0); + Modify_SPI_Reg_bits(LMS7param(SEL_BAND2_TRF), 1); + + //TBB + SetDefaults(TBB); + Modify_SPI_Reg_bits(LMS7param(CG_IAMP_TBB), 1); + Modify_SPI_Reg_bits(LMS7param(ICT_IAMP_FRP_TBB), 1); + Modify_SPI_Reg_bits(LMS7param(ICT_IAMP_GG_FRP_TBB), 6); + + //AFE + SetDefaults(AFE); + if (ch == 2) + { + Modify_SPI_Reg_bits(LMS7param(PD_TX_AFE2), 0); + Modify_SPI_Reg_bits(LMS7param(PD_RX_AFE2), 0); + } + //BIAS + uint8_t rp_calib_bias = (uint8_t)Get_SPI_Reg_bits(LMS7param(RP_CALIB_BIAS)); + SetDefaults(BIAS); + Modify_SPI_Reg_bits(LMS7param(RP_CALIB_BIAS), rp_calib_bias); + + //XBUF + Modify_SPI_Reg_bits(LMS7param(PD_XBUF_RX), 0); + Modify_SPI_Reg_bits(LMS7param(PD_XBUF_TX), 0); + Modify_SPI_Reg_bits(LMS7param(EN_G_TRF), 1); + + //CLKGEN + SetDefaults(CGEN); + + //SXR + Modify_SPI_Reg_bits(LMS7param(MAC), 1); + SetDefaults(SX); + status = SetFrequencySX(Rx, 499.95, mRefClkSXR_MHz); + if (status != LIBLMS7_SUCCESS) + return status; + Modify_SPI_Reg_bits(LMS7param(PD_VCO), 0); + + //SXT + Modify_SPI_Reg_bits(LMS7param(MAC), 2); + SetDefaults(SX); + status = SetFrequencySX(Tx, 500, mRefClkSXT_MHz); + if (status != LIBLMS7_SUCCESS) + return status; + Modify_SPI_Reg_bits(LMS7param(PD_VCO), 0); + + Modify_SPI_Reg_bits(LMS7param(MAC), ch); + //TxTSP + SetDefaults(TxTSP); + Modify_SPI_Reg_bits(LMS7param(TSGMODE_TXTSP), 1); + Modify_SPI_Reg_bits(LMS7param(INSEL_TXTSP), 1); + Modify_SPI_Reg_bits(0x0208, 8, 8, 1); + Modify_SPI_Reg_bits(0x0208, 6, 4, 0x7); + LoadDC_REG_IQ(Tx, (int16_t)0x7FFF, (int16_t)0x8000); + SetNCOFrequency(Tx, 0, 0); + + //RxTSP + SetDefaults(RxTSP); + Modify_SPI_Reg_bits(LMS7param(AGC_MODE_RXTSP), 1); + Modify_SPI_Reg_bits(0x040C, 5, 3, 0x7); + Modify_SPI_Reg_bits(LMS7param(AGC_AVG_RXTSP), 7); + Modify_SPI_Reg_bits(LMS7param(CMIX_GAIN_RXTSP), 1); + + float_type sxtfreq = GetFrequencySX_MHz(Tx, mRefClkSXT_MHz); + float_type sxrfreq = GetFrequencySX_MHz(Rx, mRefClkSXR_MHz); + SetNCOFrequency(Rx, 0, sxtfreq - sxrfreq - 1); + return LIBLMS7_SUCCESS; +} + +liblms7_status LMS7002M::RFE_TIA_Calibration(float_type TIA_freq_MHz) +{ + liblms7_status status; + bool prevRSSIbigger; + uint8_t ccomp_tia_rfe_value; + int16_t rcomp_tia_rfe; + float_type cgenFreq = TIA_freq_MHz * 20; + uint32_t rssi; + uint32_t rssi_value_50k; + //RFE + uint8_t g_tia_rfe = (uint8_t)Get_SPI_Reg_bits(LMS7param(G_TIA_RFE)); + int16_t cfb_tia_rfe_value; + if (g_tia_rfe == 1) + cfb_tia_rfe_value = (uint16_t)(5400 / TIA_freq_MHz - 15); + else if (g_tia_rfe > 1) + cfb_tia_rfe_value = (uint16_t)(1680 / TIA_freq_MHz - 10); + else + return LIBLMS7_FAILURE; + Modify_SPI_Reg_bits(LMS7param(CFB_TIA_RFE), cfb_tia_rfe_value); + + if (g_tia_rfe == 1) + ccomp_tia_rfe_value = (uint8_t)(cfb_tia_rfe_value / 100 + 1); + else if (g_tia_rfe > 1) + ccomp_tia_rfe_value = (uint8_t)(cfb_tia_rfe_value / 100); + else + return LIBLMS7_FAILURE; + if (ccomp_tia_rfe_value > 15) + ccomp_tia_rfe_value = 15; + + Modify_SPI_Reg_bits(LMS7param(CCOMP_TIA_RFE), ccomp_tia_rfe_value); + + rcomp_tia_rfe = (int16_t)(15 - cfb_tia_rfe_value * 2 / 100); + if (rcomp_tia_rfe < 0) + rcomp_tia_rfe = 0; + Modify_SPI_Reg_bits(LMS7param(RCOMP_TIA_RFE), rcomp_tia_rfe); + + //RBB + Modify_SPI_Reg_bits(LMS7param(INPUT_CTL_PGA_RBB), 2); + Modify_SPI_Reg_bits(LMS7param(PD_LPFL_RBB), 1); + + //CLKGEN + if (cgenFreq < 60) + cgenFreq = 60; + if (cgenFreq > 640) + cgenFreq = 640; + + if (cgenFreq / 16 == TIA_freq_MHz) + status = SetFrequencyCGEN(cgenFreq - 10); + else + status = SetFrequencyCGEN(cgenFreq); + if (status != LIBLMS7_SUCCESS) + return status; + + FilterTuning_AdjustGains(); + + rssi_value_50k = (uint32_t)( GetRSSI() * 0.707 ); + status = SetFrequencySX(Rx, GetFrequencySX_MHz(Tx, mRefClkSXT_MHz) - TIA_freq_MHz, mRefClkSXR_MHz); + if (status != LIBLMS7_SUCCESS) + return status; + SetNCOFrequency(Rx, 0, GetFrequencySX_MHz(Tx, mRefClkSXT_MHz) - GetFrequencySX_MHz(Rx, mRefClkSXR_MHz) - 1); + + prevRSSIbigger = GetRSSI() > rssi_value_50k; + while (cfb_tia_rfe_value >= 0 && cfb_tia_rfe_value < 4096) + { + Modify_SPI_Reg_bits(LMS7param(CFB_TIA_RFE), cfb_tia_rfe_value); + rssi = GetRSSI(); + if (rssi > rssi_value_50k) + ++cfb_tia_rfe_value; + else + { + --cfb_tia_rfe_value; + if (prevRSSIbigger) + return LIBLMS7_SUCCESS; //found correct value + } + prevRSSIbigger = rssi > rssi_value_50k; + } + return LIBLMS7_FAILURE; +} + +liblms7_status LMS7002M::RxLPFLow_Calibration(float_type RxLPFL_freq_MHz) +{ + liblms7_status status; + uint32_t rssi; + uint32_t rssi_value_50k; + int32_t c_ctl_lpfl_rbb; + bool prevRSSIbigger; + float_type cgenFreq_MHz = RxLPFL_freq_MHz * 20; + //RFE + Modify_SPI_Reg_bits(LMS7param(CFB_TIA_RFE), 15); + Modify_SPI_Reg_bits(LMS7param(CCOMP_TIA_RFE), 1); + Modify_SPI_Reg_bits(LMS7param(RCOMP_TIA_RFE), 15); + Modify_SPI_Reg_bits(LMS7param(G_TIA_RFE), 1); + + //RBB + c_ctl_lpfl_rbb = (int32_t)(2160 / RxLPFL_freq_MHz - 103); + if (c_ctl_lpfl_rbb < 0) + c_ctl_lpfl_rbb = 0; + if (c_ctl_lpfl_rbb > 2047) + c_ctl_lpfl_rbb = 2047; + Modify_SPI_Reg_bits(LMS7param(C_CTL_LPFL_RBB), c_ctl_lpfl_rbb); + + if (RxLPFL_freq_MHz >= 15) + Modify_SPI_Reg_bits(LMS7param(RCC_CTL_LPFL_RBB), 5); + else if (RxLPFL_freq_MHz >= 10) + Modify_SPI_Reg_bits(LMS7param(RCC_CTL_LPFL_RBB), 4); + else if (RxLPFL_freq_MHz >= 5) + Modify_SPI_Reg_bits(LMS7param(RCC_CTL_LPFL_RBB), 3); + else if (RxLPFL_freq_MHz >= 3) + Modify_SPI_Reg_bits(LMS7param(RCC_CTL_LPFL_RBB), 2); + else if (RxLPFL_freq_MHz >= 1.4) + Modify_SPI_Reg_bits(LMS7param(RCC_CTL_LPFL_RBB), 1); + else + Modify_SPI_Reg_bits(LMS7param(RCC_CTL_LPFL_RBB), 0); + + //CLKGEN + if (cgenFreq_MHz < 60) + cgenFreq_MHz = 60; + if (cgenFreq_MHz > 640) + cgenFreq_MHz = 640; + if (cgenFreq_MHz / 16 == RxLPFL_freq_MHz) + status = SetFrequencyCGEN(cgenFreq_MHz - 10); + else + status = SetFrequencyCGEN(cgenFreq_MHz); + if (status != LIBLMS7_SUCCESS) + return status; + + FilterTuning_AdjustGains(); + + rssi_value_50k = (uint32_t)( GetRSSI() * 0.707 ); + status = SetFrequencySX(Rx, GetFrequencySX_MHz(Tx, mRefClkSXT_MHz) - RxLPFL_freq_MHz, mRefClkSXR_MHz); + if (status != LIBLMS7_SUCCESS) + return status; + SetNCOFrequency(Rx, 0, GetFrequencySX_MHz(Tx, mRefClkSXT_MHz) - GetFrequencySX_MHz(Rx, mRefClkSXR_MHz) - 1); + + prevRSSIbigger = GetRSSI() > rssi_value_50k; + while (c_ctl_lpfl_rbb >= 0 && c_ctl_lpfl_rbb < 2048) + { + Modify_SPI_Reg_bits(LMS7param(C_CTL_LPFL_RBB), c_ctl_lpfl_rbb); + rssi = GetRSSI(); + if (rssi > rssi_value_50k) + ++c_ctl_lpfl_rbb; + else + { + --c_ctl_lpfl_rbb; + if (prevRSSIbigger) + return LIBLMS7_SUCCESS; //found correct value + } + prevRSSIbigger = rssi > rssi_value_50k; + } + return LIBLMS7_FAILURE; +} + +liblms7_status LMS7002M::RxLPFHigh_Calibration(float_type RxLPFH_freq_MHz) +{ + liblms7_status status; + int16_t c_ctl_lpfh_rbb; + int16_t rcc_ctl_lpfh_rbb; + float_type cgenFreq = RxLPFH_freq_MHz * 20; + uint32_t rssi; + uint32_t rssi_value_50k; + bool prevRSSIbigger; + //RFE + Modify_SPI_Reg_bits(LMS7param(CFB_TIA_RFE), 15); + Modify_SPI_Reg_bits(LMS7param(CCOMP_TIA_RFE), 1); + Modify_SPI_Reg_bits(LMS7param(RCOMP_TIA_RFE), 15); + Modify_SPI_Reg_bits(LMS7param(G_TIA_RFE), 1); + + //RBB + c_ctl_lpfh_rbb = (int16_t)(6000 / RxLPFH_freq_MHz - 50); + if (c_ctl_lpfh_rbb < 0) + c_ctl_lpfh_rbb = 0; + if (c_ctl_lpfh_rbb > 255) + c_ctl_lpfh_rbb = 255; + Modify_SPI_Reg_bits(LMS7param(C_CTL_LPFH_RBB), c_ctl_lpfh_rbb); + + rcc_ctl_lpfh_rbb = (int16_t)(RxLPFH_freq_MHz / 10 - 3); + if (rcc_ctl_lpfh_rbb < 0) + rcc_ctl_lpfh_rbb = 0; + Modify_SPI_Reg_bits(LMS7param(RCC_CTL_LPFH_RBB), rcc_ctl_lpfh_rbb); + + Modify_SPI_Reg_bits(LMS7param(INPUT_CTL_PGA_RBB), 1); + Modify_SPI_Reg_bits(LMS7param(PD_LPFL_RBB), 1); + Modify_SPI_Reg_bits(LMS7param(PD_LPFH_RBB), 0); + + //CLKGEN + if (cgenFreq < 60) + cgenFreq = 60; + if (cgenFreq > 640) + cgenFreq = 640; + if (cgenFreq / 16 == RxLPFH_freq_MHz) + status = SetFrequencyCGEN(cgenFreq - 10); + else + status = SetFrequencyCGEN(cgenFreq); + if (status != LIBLMS7_SUCCESS) + return status; + + FilterTuning_AdjustGains(); + + rssi_value_50k = (uint32_t)( GetRSSI() * 0.707); + status = SetFrequencySX(Rx, GetFrequencySX_MHz(Tx, mRefClkSXT_MHz) - RxLPFH_freq_MHz, mRefClkSXR_MHz); + if (status != LIBLMS7_SUCCESS) + return status; + SetNCOFrequency(Rx, 0, GetFrequencySX_MHz(Tx, mRefClkSXT_MHz) - GetFrequencySX_MHz(Rx, mRefClkSXR_MHz) - 1); + + prevRSSIbigger = GetRSSI() > rssi_value_50k; + while (c_ctl_lpfh_rbb >= 0 && c_ctl_lpfh_rbb < 256) + { + Modify_SPI_Reg_bits(LMS7param(C_CTL_LPFH_RBB), c_ctl_lpfh_rbb); + rssi = GetRSSI(); + if (rssi > rssi_value_50k) + ++c_ctl_lpfh_rbb; + else + { + --c_ctl_lpfh_rbb; + if (prevRSSIbigger) + return LIBLMS7_SUCCESS; //found correct value + } + prevRSSIbigger = rssi > rssi_value_50k; + } + return LIBLMS7_FAILURE; +} diff --git a/targets/ARCH/LMSSDR/USERSPACE/LIB/lms7002m/LMS7002M_parameters.cpp b/targets/ARCH/LMSSDR/USERSPACE/LIB/lms7002m/LMS7002M_parameters.cpp new file mode 100644 index 0000000000..b28887d776 --- /dev/null +++ b/targets/ARCH/LMSSDR/USERSPACE/LIB/lms7002m/LMS7002M_parameters.cpp @@ -0,0 +1,601 @@ +/** +@file LMS7002M_parameters.cpp +@author Lime Microsystems (www.limemicro.com) +@brief Definition of LMS7002M transceiver control parameters registers +*/ + +#include "LMS7002M_parameters.h" + +std::vector LMS7parameterList; + +const struct LMS7Parameter LRST_TX_B = { 0x0020, 15, 15, 1, "LRST_TX_B", "Resets all the logic registers to the default state for Tx MIMO channel B" }; +const struct LMS7Parameter MRST_TX_B = { 0x0020, 14, 14, 1, "MRST_TX_B", "Resets all the configuration memory to the default state for Tx MIMO channel B" }; +const struct LMS7Parameter LRST_TX_A = { 0x0020, 13, 13, 1, "LRST_TX_A", "Resets all the logic registers to the default state for Tx MIMO channel A" }; +const struct LMS7Parameter MRST_TX_A = { 0x0020, 12, 12, 1, "MRST_TX_A", "Resets all the configuration memory to the default state for Tx MIMO channel A" }; +const struct LMS7Parameter LRST_RX_B = { 0x0020, 11, 11, 1, "LRST_RX_B", "Resets all the logic registers to the default state for Rx MIMO channel B" }; +const struct LMS7Parameter MRST_RX_B = { 0x0020, 10, 10, 1, "MRST_RX_B", "Resets all the configuration memory to the default state for Rx MIMO channel B" }; +const struct LMS7Parameter LRST_RX_A = { 0x0020, 9, 9, 1, "LRST_RX_A", "Resets all the logic registers to the default state for Rx MIMO channel A" }; +const struct LMS7Parameter MRST_RX_A = { 0x0020, 8, 8, 1, "MRST_RX_A", "Resets all the configuration memory to the default state for Rx MIMO channel A" }; +const struct LMS7Parameter SRST_RXFIFO = { 0x0020, 7, 7, 1, "SRST_RXFIFO", "RX FIFO soft reset (LimeLight Interface)" }; +const struct LMS7Parameter SRST_TXFIFO = { 0x0020, 6, 6, 1, "SRST_TXFIFO", "TX FIFO soft reset (LimeLight Interface)" }; +const struct LMS7Parameter RXEN_B = { 0x0020, 5, 5, 1, "RXEN_B", "Power control for Rx MIMO channel B" }; +const struct LMS7Parameter RXEN_A = { 0x0020, 4, 4, 1, "RXEN_A", "Power control for Rx MIMO channel A" }; +const struct LMS7Parameter TXEN_B = { 0x0020, 3, 3, 1, "TXEN_B", "Power control for Tx MIMO channel B" }; +const struct LMS7Parameter TXEN_A = { 0x0020, 2, 2, 1, "TXEN_A", "Power control for Tx MIMO channel A" }; +const struct LMS7Parameter MAC = { 0x0020, 1, 0, 3, "MAC", "Selects MIMO channel for communication" }; +const struct LMS7Parameter TX_CLK_PE = { 0x0021, 11, 11, 1, "TX_CLK_PE", "Pull up control of TX_CLK pad" }; +const struct LMS7Parameter RX_CLK_PE = { 0x0021, 10, 10, 1, "RX_CLK_PE", "Pull up control of RX_CLK pad" }; +const struct LMS7Parameter SDA_PE = { 0x0021, 9, 9, 1, "SDA_PE", "Pull up control of SDA pad" }; +const struct LMS7Parameter SDA_DS = { 0x0021, 8, 8, 0, "SDA_DS", "Driver strength of SDA pad" }; +const struct LMS7Parameter SCL_PE = { 0x0021, 7, 7, 1, "SCL_PE", "Pull up control of SCL pad" }; +const struct LMS7Parameter SCL_DS = { 0x0021, 6, 6, 0, "SCL_DS", "Driver strength of SCL pad" }; +const struct LMS7Parameter SDIO_DS = { 0x0021, 5, 5, 0, "SDIO_DS", "Driver strength of SDIO pad" }; +const struct LMS7Parameter SDIO_PE = { 0x0021, 4, 4, 1, "SDIO_PE", "Pull up control of SDIO pad" }; +const struct LMS7Parameter SDO_PE = { 0x0021, 3, 3, 1, "SDO_PE", "Pull up control of SDO pad" }; +const struct LMS7Parameter SCLK_PE = { 0x0021, 2, 2, 1, "SCLK_PE", "Pull up control of SCLK pad" }; +const struct LMS7Parameter SEN_PE = { 0x0021, 1, 1, 1, "SEN_PE", "Pull up control of SEN pad" }; +const struct LMS7Parameter SPIMODE = { 0x0021, 0, 0, 1, "SPIMODE", "SPI communication mode" }; +const struct LMS7Parameter DIQ2_DS = { 0x0022, 11, 11, 0, "DIQ2_DS", "Driver strength of DIQ2 pad" }; +const struct LMS7Parameter DIQ2_PE = { 0x0022, 10, 10, 1, "DIQ2_PE", "Pull up control of DIQ2 pad" }; +const struct LMS7Parameter IQ_SEL_EN_2_PE = { 0x0022, 9, 9, 1, "IQ_SEL_EN_2_PE", "Pull up control of IQ_SEL_EN_2 pad" }; +const struct LMS7Parameter TXNRX2_PE = { 0x0022, 8, 8, 1, "TXNRX2_PE", "Pull up control of TXNRX2 pad" }; +const struct LMS7Parameter FCLK2_PE = { 0x0022, 7, 7, 1, "FCLK2_PE", "Pull up control of FCLK2 pad" }; +const struct LMS7Parameter MCLK2_PE = { 0x0022, 6, 6, 1, "MCLK2_PE", "Pull up control of MCLK2 pad" }; +const struct LMS7Parameter DIQ1_DS = { 0x0022, 5, 5, 0, "DIQ1_DS", "Pull up control of MCLK2 pad" }; +const struct LMS7Parameter DIQ1_PE = { 0x0022, 4, 4, 1, "DIQ1_PE", "Pull up control of DIQ1 pad" }; +const struct LMS7Parameter IQ_SEL_EN_1_PE = { 0x0022, 3, 3, 1, "IQ_SEL_EN_1_PE", "Pull up control of IQ_SEL_EN_1 pad" }; +const struct LMS7Parameter TXNRX1_PE = { 0x0022, 2, 2, 1, "TXNRX1_PE", "Pull up control of TXNRX1 pad" }; +const struct LMS7Parameter FCLK1_PE = { 0x0022, 1, 1, 1, "FCLK1_PE", "Pull up control of FCLK1 pad" }; +const struct LMS7Parameter MCLK1_PE = { 0x0022, 0, 0, 1, "MCLK1_PE", "Pull up control of MCLK1 pad" }; +const struct LMS7Parameter DIQDIRCTR2 = { 0x0023, 15, 15, 0, "DIQDIRCTR2", "DIQ2 direction control mode" }; +const struct LMS7Parameter DIQDIR2 = { 0x0023, 14, 14, 1, "DIQDIR2", "DIQ2 direction" }; +const struct LMS7Parameter DIQDIRCTR1 = { 0x0023, 13, 13, 0, "DIQDIRCTR1", "DIQ1 direction control mode" }; +const struct LMS7Parameter DIQDIR1 = { 0x0023, 12, 12, 1, "DIQDIR1", "DIQ1 direction" }; +const struct LMS7Parameter ENABLEDIRCTR2 = { 0x0023, 11, 11, 0, "ENABLEDIRCTR2", "ENABLE2 direction control mode" }; +const struct LMS7Parameter ENABLEDIR2 = { 0x0023, 10, 10, 1, "ENABLEDIR2", "ENABLE2 direction" }; +const struct LMS7Parameter ENABLEDIRCTR1 = { 0x0023, 9, 9, 0, "ENABLEDIRCTR1", "ENABLE1 direction control mode" }; +const struct LMS7Parameter ENABLEDIR1 = { 0x0023, 8, 8, 1, "ENABLEDIR1", "ENABLE1 direction." }; +const struct LMS7Parameter MOD_EN = { 0x0023, 6, 6, 1, "MOD_EN", "LimeLight interface enable" }; +const struct LMS7Parameter LML2_FIDM = { 0x0023, 5, 5, 0, "LML2_FIDM", "Frame start ID selection for Port 2 when LML_MODE2 = 0" }; +const struct LMS7Parameter LML2_TXNRXIQ = { 0x0023, 4, 4, 1, "LML2_TXNRXIQ", "TXIQ/RXIQ mode selection for Port 2 when LML_MODE2 = 0" }; +const struct LMS7Parameter LML2_MODE = { 0x0023, 3, 3, 1, "LML2_MODE", "Mode of LimeLight Port 2" }; +const struct LMS7Parameter LML1_FIDM = { 0x0023, 2, 2, 0, "LML1_FIDM", "Frame start ID selection for Port 1 when LML_MODE1 = 0" }; +const struct LMS7Parameter LML1_TXNRXIQ = { 0x0023, 1, 1, 0, "LML1_TXNRXIQ", "TXIQ/RXIQ mode selection for Port 1 when LML_MODE1 = 0" }; +const struct LMS7Parameter LML1_MODE = { 0x0023, 0, 0, 1, "LML1_MODE", "Mode of LimeLight Port 1" }; +const struct LMS7Parameter LML1_S3S = { 0x0024, 15, 14, 3, "LML1_S3S", "Sample source in position 3, when Port 1 is RF2BB" }; +const struct LMS7Parameter LML1_S2S = { 0x0024, 13, 12, 2, "LML1_S2S", "Sample source in position 2, when Port 1 is RF2BB" }; +const struct LMS7Parameter LML1_S1S = { 0x0024, 11, 10, 1, "LML1_S1S", "Sample source in position 1, when Port 1 is RF2BB" }; +const struct LMS7Parameter LML1_S0S = { 0x0024, 9, 8, 0, "LML1_S0S", "Sample source in position 0, when Port 1 is RF2BB" }; +const struct LMS7Parameter LML1_BQP = { 0x0024, 7, 6, 3, "LML1_BQP", "BQ sample position in frame, when Port 1 is BB2RF" }; +const struct LMS7Parameter LML1_BIP = { 0x0024, 5, 4, 2, "LML1_BIP", "BI sample position in frame, when Port 1 is BB2RF" }; +const struct LMS7Parameter LML1_AQP = { 0x0024, 3, 2, 1, "LML1_AQP", "AQ sample position in frame, when Port 1 is BB2RF" }; +const struct LMS7Parameter LML1_AIP = { 0x0024, 1, 0, 0, "LML1_AIP", "AI sample position in frame, when Port 1 is BB2RF" }; +const struct LMS7Parameter LML1_BB2RF_PST = { 0x0025, 15, 8, 1, "LML1_BB2RF_PST", "Number of clock cycles to wait before data drive stop after burst stop is detected in JESD207 mode on Port 1 and Port 1 BB2RF" }; +const struct LMS7Parameter LML1_BB2RF_PRE = { 0x0025, 7, 0, 1, "LML1_BB2RF_PRE", "Number of clock cycles to wait before data drive start after burst start is detected in JESD207 mode on Port 1 and Port 1 BB2RF" }; +const struct LMS7Parameter LML1_RF2BB_PST = { 0x0026, 15, 8, 1, "LML1_RF2BB_PST", "Number of clock cycles to wait before data capture stop after burst stop is detected in JESD207 mode on Port 1 and Port 1 is RF2BB" }; +const struct LMS7Parameter LML1_RF2BB_PRE = { 0x0026, 7, 0, 1, "LML1_RF2BB_PRE", "Number of clock cycles to wait before data capture start after burst start is detected in JESD207 mode on Port 1 and Port 1 RF2BB" }; +const struct LMS7Parameter LML2_S3S = { 0x0027, 15, 14, 3, "LML2_S3S", "Sample source in position 3, when Port 2 is RF2BB" }; +const struct LMS7Parameter LML2_S2S = { 0x0027, 13, 12, 2, "LML2_S2S", "Sample source in position 2, when Port 2 is RF2BB" }; +const struct LMS7Parameter LML2_S1S = { 0x0027, 11, 10, 1, "LML2_S1S", "Sample source in position 1, when Port 2 is RF2BB" }; +const struct LMS7Parameter LML2_S0S = { 0x0027, 9, 8, 0, "LML2_S0S", "Sample source in position 0, when Port 2 is RF2BB" }; +const struct LMS7Parameter LML2_BQP = { 0x0027, 7, 6, 3, "LML2_BQP", "BQ sample position in frame, when Port 2 is BB2RF" }; +const struct LMS7Parameter LML2_BIP = { 0x0027, 5, 4, 2, "LML2_BIP", "BI sample position in frame, when Port 2 is BB2RF" }; +const struct LMS7Parameter LML2_AQP = { 0x0027, 3, 2, 1, "LML2_AQP", "AQ sample position in frame, when Port 2 is BB2RF" }; +const struct LMS7Parameter LML2_AIP = { 0x0027, 1, 0, 0, "LML2_AIP", "AI sample position in frame, when Port 2 is BB2RF" }; +const struct LMS7Parameter LML2_BB2RF_PST = { 0x0028, 15, 8, 1, "LML2_BB2RF_PST", "Number of clock cycles to wait before data drive stop after burst stop is detected in JESD207 mode on Port 2 and Port 2 BB2RF" }; +const struct LMS7Parameter LML2_BB2RF_PRE = { 0x0028, 7, 0, 1, "LML2_BB2RF_PRE", "Number of clock cycles to wait before data drive start after burst start is detected in JESD207 mode on Port 2 and Port 2 BB2RF" }; +const struct LMS7Parameter LML2_RF2BB_PST = { 0x0029, 15, 8, 1, "LML2_RF2BB_PST", "Number of clock cycles to wait before data capture stop after burst stop is detected in JESD207 mode on Port 2 and Port 2 RF2BB" }; +const struct LMS7Parameter LML2_RF2BB_PRE = { 0x0029, 7, 0, 1, "LML2_RF2BB_PRE", "Number of clock cycles to wait before data capture start after burst start is detected in JESD207 mode on Port 2 and Port 2 RF2BB" }; +const struct LMS7Parameter FCLK2_DLY = { 0x002A, 15, 14, 0, "FCLK2_DLY", "" }; +const struct LMS7Parameter FCLK1_DLY = { 0x002A, 13, 12, 0, "FCLK1_DLY", "" }; +const struct LMS7Parameter RX_MUX = { 0x002A, 11, 10, 0, "RX_MUX", "RxFIFO data source selection" }; +const struct LMS7Parameter TX_MUX = { 0x002A, 9, 8, 0, "TX_MUX", "Port selection for data transmit to TSP" }; +const struct LMS7Parameter TXRDCLK_MUX = { 0x002A, 7, 6, 2, "TXRDCLK_MUX", "TX FIFO read clock selection" }; +const struct LMS7Parameter TXWRCLK_MUX = { 0x002A, 5, 4, 0, "TXWRCLK_MUX", "TX FIFO write clock selection" }; +const struct LMS7Parameter RXRDCLK_MUX = { 0x002A, 3, 2, 1, "RXRDCLK_MUX", "RX FIFO read clock selection" }; +const struct LMS7Parameter RXWRCLK_MUX = { 0x002A, 1, 0, 2, "RXWRCLK_MUX", "RX FIFO write clock selection" }; +const struct LMS7Parameter FCLK2_INV = { 0x002B, 15, 15, 0, "FCLK2_INV", "FCLK2 clock inversion" }; +const struct LMS7Parameter FCLK1_INV = { 0x002B, 14, 14, 0, "FCLK1_INV", "FCLK1 clock inversion" }; +const struct LMS7Parameter MCLK2DLY = { 0x002B, 13, 12, 0, "MCLK2DLY", "MCLK2 clock internal delay" }; +const struct LMS7Parameter MCLK1DLY = { 0x002B, 11, 10, 0, "MCLK1DLY", "MCLK1 clock internal delay" }; +const struct LMS7Parameter MCLK2SRC = { 0x002B, 5, 4, 1, "MCLK2SRC", "MCLK2 clock source" }; +const struct LMS7Parameter MCLK1SRC = { 0x002B, 3, 2, 0, "MCLK1SRC", "MCLK1 clock source" }; +const struct LMS7Parameter TXDIVEN = { 0x002B, 1, 1, 0, "TXDIVEN", "TX clock divider enable" }; +const struct LMS7Parameter RXDIVEN = { 0x002B, 0, 0, 0, "RXDIVEN", "RX clock divider enable" }; +const struct LMS7Parameter TXTSPCLKA_DIV = { 0x002C, 15, 8, 255, "TXTSPCLKA_DIV", "TxTSP clock divider, used to produce MCLK(1/2). Clock division ratio is 2(TXTSPCLKA_DIV + 1)"}; +const struct LMS7Parameter RXTSPCLKA_DIV = { 0x002C, 7, 0, 255, "RXTSPCLKA_DIV", "RxTSP clock divider, used to produce MCLK(1/2). Clock division ratio is 2(RXTSPCLKA_DIV + 1)"}; +const struct LMS7Parameter MIMO_SISO = { 0x002E, 15, 15, 0, "MIMO_SISO", "MIMO channel B enable control" }; +const struct LMS7Parameter VER = { 0x002F, 15, 11, 7, "VER", "" }; +const struct LMS7Parameter REV = { 0x002F, 10, 6, 1, "REV", "" }; +const struct LMS7Parameter MASK = { 0x002F, 5, 0, 0, "MASK", "" }; +const struct LMS7Parameter EN_DIR_LDO = { 0x0081, 3, 3, 0, "EN_DIR_LDO", "" }; +const struct LMS7Parameter EN_DIR_CGEN = { 0x0081, 2, 2, 0, "EN_DIR_CGEN", "" }; +const struct LMS7Parameter EN_DIR_XBUF = { 0x0081, 1, 1, 0, "EN_DIR_XBUF", "" }; +const struct LMS7Parameter EN_DIR_AFE = { 0x0081, 0, 0, 0, "EN_DIR_AFE", "" }; +const struct LMS7Parameter ISEL_DAC_AFE = { 0x0082, 15, 13, 4, "ISEL_DAC_AFE", "Controls the peak current of the DAC output current" }; +const struct LMS7Parameter MODE_INTERLEAVE_AFE = { 0x0082, 12, 12, 0, "MODE_INTERLEAVE_AFE", "time interleaves the two ADCs into one ADC" }; +const struct LMS7Parameter MUX_AFE_1 = { 0x0082, 11, 10, 0, "MUX_AFE_1", "Controls the MUX at the input of the ADC channel 1" }; +const struct LMS7Parameter MUX_AFE_2 = { 0x0082, 9, 8, 0, "MUX_AFE_2", "Controls the MUX at the input of the ADC channel 2" }; +const struct LMS7Parameter PD_AFE = { 0x0082, 5, 5, 0, "PD_AFE", "Power down control for the AFE current mirror in BIAS_TOP" }; +const struct LMS7Parameter PD_RX_AFE1 = { 0x0082, 4, 4, 0, "PD_RX_AFE1", "Power down control for the ADC of channel 1" }; +const struct LMS7Parameter PD_RX_AFE2 = { 0x0082, 3, 3, 1, "PD_RX_AFE2", "Power down control for the ADC of channel 2" }; +const struct LMS7Parameter PD_TX_AFE1 = { 0x0082, 2, 2, 0, "PD_TX_AFE1", "Power down control for the DAC of channel 1" }; +const struct LMS7Parameter PD_TX_AFE2 = { 0x0082, 1, 1, 1, "PD_TX_AFE2", "Power down control for the DAC of channel 2" }; +const struct LMS7Parameter EN_G_AFE = { 0x0082, 0, 0, 1, "EN_G_AFE", "Enable control for all the AFE power downs" }; +const struct LMS7Parameter MUX_BIAS_OUT = { 0x0084, 12, 11, 0, "MUX_BIAS_OUT", "Test mode of the BIAS_TOP" }; +const struct LMS7Parameter RP_CALIB_BIAS = { 0x0084, 10, 6, 16, "RP_CALIB_BIAS", "Calibration code for rppolywo. This code is set by the calibration algorithm: BIAS_RPPOLY_calibration" }; +const struct LMS7Parameter PD_FRP_BIAS = { 0x0084, 4, 4, 0, "PD_FRP_BIAS", "Power down signal for Fix/RP block" }; +const struct LMS7Parameter PD_F_BIAS = { 0x0084, 3, 3, 0, "PD_F_BIAS", "Power down signal for Fix" }; +const struct LMS7Parameter PD_PTRP_BIAS = { 0x0084, 2, 2, 0, "PD_PTRP_BIAS", "Power down signal for PTAT/RP block" }; +const struct LMS7Parameter PD_PT_BIAS = { 0x0084, 1, 1, 0, "PD_PT_BIAS", "Power down signal for PTAT block" }; +const struct LMS7Parameter PD_BIAS_MASTER = { 0x0084, 0, 0, 0, "PD_BIAS_MASTER", "Enable signal for central bias block" }; +const struct LMS7Parameter SLFB_XBUF_RX = { 0x0085, 8, 8, 0, "SLFB_XBUF_RX", "Self biasing digital contol SLFB_XBUF_RX" }; +const struct LMS7Parameter SLFB_XBUF_TX = { 0x0085, 7, 7, 0, "SLFB_XBUF_TX", "Self biasing digital contol SLFB_XBUF_TX" }; +const struct LMS7Parameter BYP_XBUF_RX = { 0x0085, 6, 6, 0, "BYP_XBUF_RX", "Shorts the Input 3.3V buffer in XBUF" }; +const struct LMS7Parameter BYP_XBUF_TX = { 0x0085, 5, 5, 0, "BYP_XBUF_TX", "Shorts the Input 3.3V buffer in XBUF" }; +const struct LMS7Parameter EN_OUT2_XBUF_TX = { 0x0085, 4, 4, 0, "EN_OUT2_XBUF_TX", "Enables the 2nd output of TX XBUF. This 2nd buffer goes to XBUF_RX. This should be active when only 1 XBUF is to be used" }; +const struct LMS7Parameter EN_TBUFIN_XBUF_RX = { 0x0085, 3, 3, 0, "EN_TBUFIN_XBUF_RX", "Disables the input from the external XOSC and buffers the 2nd input signal (from TX XBUF 2nd output) to the RX. This should be active when only 1 XBUF is to be used" }; +const struct LMS7Parameter PD_XBUF_RX = { 0x0085, 2, 2, 0, "PD_XBUF_RX", "Power down signal PD_XBUF_RX" }; +const struct LMS7Parameter PD_XBUF_TX = { 0x0085, 1, 1, 0, "PD_XBUF_TX", "Power down signal PD_XBUF_TX" }; +const struct LMS7Parameter EN_G_XBUF = { 0x0085, 0, 0, 1, "EN_G_XBUF", "Enable control for all the XBUF power downs" }; +const struct LMS7Parameter SPDUP_VCO_CGEN = { 0x0086, 15, 15, 0, "SPDUP_VCO_CGEN", "Bypasses the noise filter resistor for fast setlling time. It should be connected to a 1us pulse" }; +const struct LMS7Parameter RESET_N_CGEN = { 0x0086, 14, 14, 1, "RESET_N_CGEN", "A pulse should be used in the start-up to reset ( 1-normal operation)" }; +const struct LMS7Parameter EN_ADCCLKH_CLKGN = { 0x0086, 11, 11, 1, "EN_ADCCLKH_CLKGN", "Selects if F_CLKH or F_CLKL is connected to FCLK_ADC" }; +const struct LMS7Parameter EN_COARSE_CKLGEN = { 0x0086, 10, 10, 0, "EN_COARSE_CKLGEN", "Enable signal for coarse tuning block" }; +const struct LMS7Parameter EN_INTONLY_SDM_CGEN = { 0x0086, 9, 9, 0, "EN_INTONLY_SDM_CGEN", "Enables INTEGER-N mode of the SX " }; +const struct LMS7Parameter EN_SDM_CLK_CGEN = { 0x0086, 8, 8, 1, "EN_SDM_CLK_CGEN", "Enables/Disables SDM clock. In INT-N mode or for noise testing, SDM clock can be disabled" }; +const struct LMS7Parameter PD_CP_CGEN = { 0x0086, 6, 6, 0, "PD_CP_CGEN", "Power down for Charge Pump" }; +const struct LMS7Parameter PD_FDIV_FB_CGEN = { 0x0086, 5, 5, 0, "PD_FDIV_FB_CGEN", "Power down for feedback frequency divider" }; +const struct LMS7Parameter PD_FDIV_O_CGEN = { 0x0086, 4, 4, 0, "PD_FDIV_O_CGEN", "Power down for forward frequency divider of the CGEN block" }; +const struct LMS7Parameter PD_SDM_CGEN = { 0x0086, 3, 3, 0, "PD_SDM_CGEN", "Power down for SDM" }; +const struct LMS7Parameter PD_VCO_CGEN = { 0x0086, 2, 2, 0, "PD_VCO_CGEN", "Power down for VCO" }; +const struct LMS7Parameter PD_VCO_COMP_CGEN = { 0x0086, 1, 1, 0, "PD_VCO_COMP_CGEN", "Power down for VCO comparator" }; +const struct LMS7Parameter EN_G_CGEN = { 0x0086, 0, 0, 1, "EN_G_CGEN", "Enable control for all the CGEN power downs" }; +const struct LMS7Parameter FRAC_SDM_CGEN_LSB = { 0x0087, 15, 0, 0x0400, "FRAC_SDM_CGEN_LSB", "" }; +const struct LMS7Parameter INT_SDM_CGEN = { 0x0088, 13, 4, 120, "INT_SDM_CGEN", "" }; +const struct LMS7Parameter FRAC_SDM_CGEN_MSB = { 0x0088, 3, 0, 0, "FRAC_SDM_CGEN_MSB", "" }; +const struct LMS7Parameter REV_SDMCLK_CGEN = { 0x0089, 15, 15, 0, "REV_SDMCLK_CGEN", "Reverses the SDM clock" }; +const struct LMS7Parameter SEL_SDMCLK_CGEN = { 0x0089, 14, 14, 0, "SEL_SDMCLK_CGEN", "Selects between the feedback divider output and Fref for SDM" }; +const struct LMS7Parameter SX_DITHER_EN_CGEN = { 0x0089, 13, 13, 0, "SX_DITHER_EN_CGEN", "Enabled dithering in SDM" }; +const struct LMS7Parameter CLKH_OV_CLKL_CGEN = { 0x0089, 12, 11, 0, "CLKH_OV_CLKL_CGEN", "FCLKL here is ADC clock. FCLKH is the clock to the DAC and if no division is added to the ADC as well" }; +const struct LMS7Parameter DIV_OUTCH_CGEN = { 0x0089, 10, 3, 4, "DIV_OUTCH_CGEN", "" }; +const struct LMS7Parameter TST_CGEN = { 0x0089, 2, 0, 0, "TST_CGEN", +"Controls the test mode of the SX\n\ +0 - TST disabled; RSSI analog outputs enabled if RSSI blocks active and when all PLL test signals are off\n\ +1 - tstdo[0] = ADC clock; tstdo[1] = DAC clock; tstao = High impedance;\n\ +2 - tstdo[0] = SDM clock; tstdo[1] = feedback divider output; tstao = VCO tune through a 60kOhm resistor;\n\ +3 - tstdo[0] = Reference clock; tstdo[1] = feedback divider output; tstao = VCO tune through a 10kOhm resistor;\n\ +4 - tstdo[0] = High impedance; tstdo[1] = High impedance; tstao = High impedance;\n\ +5 - tstdo[0] = Charge pump Down signal; tstdo[1] = Charge pump Up signal; tstao = High impedance;\n\ +6 - tstdo[0] = High impedance; tstdo[1] = High impedance; tstao = VCO tune through a 60kOhm resistor;\n\ +7 - tstdo[0] = High impedance; tstdo[1] = High impedance; tstao = VCO tune through a 10kOhm resistor;\n\ +if TST_SX[2] = 1 --> VCO_TSTBUF active generating VCO_TST_DIV20 and VCO_TST_DIV40"}; +const struct LMS7Parameter REV_CLKDAC_CGEN = { 0x008A, 14, 14, 0, "REV_CLKDAC_CGEN", "Inverts the clock F_CLKL" }; +const struct LMS7Parameter CMPLO_CTRL_CGEN = { 0x008A, 27, 14, 0, "CMPLO_CTRL_CGEN", "" }; +const struct LMS7Parameter REV_CLKADC_CGEN = { 0x008A, 13, 13, 0, "REV_CLKADC_CGEN", "Inverts the clock F_CLKL" }; +const struct LMS7Parameter REVPH_PFD_CGEN = { 0x008A, 12, 12, 0, "REVPH_PFD_CGEN", "Reverse the pulses of PFD. It can be used to reverse the polarity of the PLL loop (positive feedback to negative feedback)" }; +const struct LMS7Parameter IOFFSET_CP_CGEN = { 0x008A, 11, 6, 20, "IOFFSET_CP_CGEN", "Scales the offset current of the charge pump, 0-->63. This current is used in Fran-N mode to create an offset in the CP response and avoide the non-linear section" }; +const struct LMS7Parameter IPULSE_CP_CGEN = { 0x008A, 5, 0, 20, "IPULSE_CP_CGEN", "Scales the pulse current of the charge pump" }; +const struct LMS7Parameter ICT_VCO_CGEN = { 0x008B, 13, 9, 16, "ICT_VCO_CGEN", "Scales the VCO bias current from 0 to 2.5xInom" }; +const struct LMS7Parameter CSW_VCO_CGEN = { 0x008B, 8, 1, 128, "CSW_VCO_CGEN", "" }; +const struct LMS7Parameter COARSE_START_CGEN = { 0x008B, 0, 0, 0, "COARSE_START_CGEN", "Control signal for coarse tuning algorithm (SX_SWC_calibration)" }; +const struct LMS7Parameter COARSE_STEPDONE_CGEN = { 0x008C, 15, 15, 0, "COARSE_STEPDONE_CGEN", "" }; +const struct LMS7Parameter COARSEPLL_COMPO_CGEN = { 0x008C, 14, 14, 0, "COARSEPLL_COMPO_CGEN", "" }; +const struct LMS7Parameter VCO_CMPHO_CGEN = { 0x008C, 13, 13, 0, "VCO_CMPHO_CGEN", "" }; +const struct LMS7Parameter VCO_CMPLO_CGEN = { 0x008C, 12, 12, 0, "VCO_CMPLO_CGEN", "" }; +const struct LMS7Parameter CP2_CGEN = { 0x008C, 11, 8, 6, "CP2_CGEN", "Controls the value of CP2 (cap from CP output to GND) in the PLL filter" }; +const struct LMS7Parameter CP3_CGEN = { 0x008C, 7, 4, 7, "CP3_CGEN", "Controls the value of CP3 (cap from VCO Vtune input to GND) in the PLL filter" }; +const struct LMS7Parameter CZ_CGEN = { 0x008C, 3, 0, 11, "CZ_CGEN", "Controls the value of CZ (Zero capacitor) in the PLL filter" }; +const struct LMS7Parameter EN_LDO_DIG = { 0x0092, 15, 15, 0, "EN_LDO_DIG", "Enables the LDO" }; +const struct LMS7Parameter EN_LDO_DIGGN = { 0x0092, 14, 14, 0, "EN_LDO_DIGGN", "Enables the LDO" }; +const struct LMS7Parameter EN_LDO_DIGSXR = { 0x0092, 13, 13, 0, "EN_LDO_DIGSXR", "Enables the LDO" }; +const struct LMS7Parameter EN_LDO_DIGSXT = { 0x0092, 12, 12, 0, "EN_LDO_DIGSXT", "Enables the LDO" }; +const struct LMS7Parameter EN_LDO_DIVGN = { 0x0092, 11, 11, 0, "EN_LDO_DIVGN", "Enables the LDO" }; +const struct LMS7Parameter EN_LDO_DIVSXR = { 0x0092, 10, 10, 0, "EN_LDO_DIVSXR", "Enables the LDO" }; +const struct LMS7Parameter EN_LDO_DIVSXT = { 0x0092, 9, 9, 0, "EN_LDO_DIVSXT", "Enables the LDO" }; +const struct LMS7Parameter EN_LDO_LNA12 = { 0x0092, 8, 8, 0, "EN_LDO_LNA12", "Enables the LDO" }; +const struct LMS7Parameter EN_LDO_LNA14 = { 0x0092, 7, 7, 0, "EN_LDO_LNA14", "Enables the LDO" }; +const struct LMS7Parameter EN_LDO_MXRFE = { 0x0092, 6, 6, 0, "EN_LDO_MXRFE", "Enables the LDO" }; +const struct LMS7Parameter EN_LDO_RBB = { 0x0092, 5, 5, 0, "EN_LDO_RBB", "Enables the LDO" }; +const struct LMS7Parameter EN_LDO_RXBUF = { 0x0092, 4, 4, 0, "EN_LDO_RXBUF", "Enables the LDO" }; +const struct LMS7Parameter EN_LDO_TBB = { 0x0092, 3, 3, 0, "EN_LDO_TBB", "Enables the LDO" }; +const struct LMS7Parameter EN_LDO_TIA12 = { 0x0092, 2, 2, 0, "EN_LDO_TIA12", "Enables the LDO" }; +const struct LMS7Parameter EN_LDO_TIA14 = { 0x0092, 1, 1, 0, "EN_LDO_TIA14", "Enables the LDO" }; +const struct LMS7Parameter EN_G_LDO = { 0x0092, 0, 0, 1, "EN_G_LDO", "Enable control for all the LDO power downs" }; +const struct LMS7Parameter EN_LOADIMP_LDO_TLOB = { 0x0093, 15, 15, 0, "EN_LOADIMP_LDO_TLOB", "Enables the load dependent bias to optimize the load regulation" }; +const struct LMS7Parameter EN_LOADIMP_LDO_TPAD = { 0x0093, 14, 14, 0, "EN_LOADIMP_LDO_TPAD", "Enables the load dependent bias to optimize the load regulation" }; +const struct LMS7Parameter EN_LOADIMP_LDO_TXBUF = { 0x0093, 13, 13, 0, "EN_LOADIMP_LDO_TXBUF", "Enables the load dependent bias to optimize the load regulation" }; +const struct LMS7Parameter EN_LOADIMP_LDO_VCOGN = { 0x0093, 12, 12, 0, "EN_LOADIMP_LDO_VCOGN", "Enables the load dependent bias to optimize the load regulation" }; +const struct LMS7Parameter EN_LOADIMP_LDO_VCOSXR = { 0x0093, 11, 11, 0, "EN_LOADIMP_LDO_VCOSXR", "Enables the load dependent bias to optimize the load regulation" }; +const struct LMS7Parameter EN_LOADIMP_LDO_VCOSXT = { 0x0093, 10, 10, 0, "EN_LOADIMP_LDO_VCOSXT", "Enables the load dependent bias to optimize the load regulation" }; +const struct LMS7Parameter EN_LDO_AFE = { 0x0093, 9, 9, 0, "EN_LDO_AFE", "Enables the LDO" }; +const struct LMS7Parameter EN_LDO_CPGN = { 0x0093, 8, 8, 0, "EN_LDO_CPGN", "Enables the LDO" }; +const struct LMS7Parameter EN_LDO_CPSXR = { 0x0093, 7, 7, 0, "EN_LDO_CPSXR", "Enables the LDO" }; +const struct LMS7Parameter EN_LDO_TLOB = { 0x0093, 6, 6, 0, "EN_LDO_TLOB", "Enables the LDO" }; +const struct LMS7Parameter EN_LDO_TPAD = { 0x0093, 5, 5, 0, "EN_LDO_TPAD", "Enables the LDO" }; +const struct LMS7Parameter EN_LDO_TXBUF = { 0x0093, 4, 4, 0, "EN_LDO_TXBUF", "Enables the LDO" }; +const struct LMS7Parameter EN_LDO_VCOGN = { 0x0093, 3, 3, 0, "EN_LDO_VCOGN", "Enables the LDO" }; +const struct LMS7Parameter EN_LDO_VCOSXR = { 0x0093, 2, 2, 0, "EN_LDO_VCOSXR", "Enables the LDO" }; +const struct LMS7Parameter EN_LDO_VCOSXT = { 0x0093, 1, 1, 0, "EN_LDO_VCOSXT", "Enables the LDO" }; +const struct LMS7Parameter EN_LDO_CPSXT = { 0x0093, 0, 0, 0, "EN_LDO_CPSXT", "Enables the LDO" }; +const struct LMS7Parameter EN_LOADIMP_LDO_CPSXT = { 0x0094, 15, 15, 0, "EN_LOADIMP_LDO_CPSXT", "Enables the load dependent bias to optimize the load regulation" }; +const struct LMS7Parameter EN_LOADIMP_LDO_DIG = { 0x0094, 14, 14, 0, "EN_LOADIMP_LDO_DIG", "Enables the load dependent bias to optimize the load regulation" }; +const struct LMS7Parameter EN_LOADIMP_LDO_DIGGN = { 0x0094, 13, 13, 0, "EN_LOADIMP_LDO_DIGGN", "Enables the load dependent bias to optimize the load regulation" }; +const struct LMS7Parameter EN_LOADIMP_LDO_DIGSXR = { 0x0094, 12, 12, 0, "EN_LOADIMP_LDO_DIGSXR", "Enables the load dependent bias to optimize the load regulation" }; +const struct LMS7Parameter EN_LOADIMP_LDO_DIGSXT = { 0x0094, 11, 11, 0, "EN_LOADIMP_LDO_DIGSXT", "Enables the load dependent bias to optimize the load regulation" }; +const struct LMS7Parameter EN_LOADIMP_LDO_DIVGN = { 0x0094, 10, 10, 0, "EN_LOADIMP_LDO_DIVGN", "Enables the load dependent bias to optimize the load regulation" }; +const struct LMS7Parameter EN_LOADIMP_LDO_DIVSXR = { 0x0094, 9, 9, 0, "EN_LOADIMP_LDO_DIVSXR", "Enables the load dependent bias to optimize the load regulation" }; +const struct LMS7Parameter EN_LOADIMP_LDO_DIVSXT = { 0x0094, 8, 8, 0, "EN_LOADIMP_LDO_DIVSXT", "Enables the load dependent bias to optimize the load regulation" }; +const struct LMS7Parameter EN_LOADIMP_LDO_LNA12 = { 0x0094, 7, 7, 0, "EN_LOADIMP_LDO_LNA12", "Enables the load dependent bias to optimize the load regulation" }; +const struct LMS7Parameter EN_LOADIMP_LDO_LNA14 = { 0x0094, 6, 6, 0, "EN_LOADIMP_LDO_LNA14", "Enables the load dependent bias to optimize the load regulation" }; +const struct LMS7Parameter EN_LOADIMP_LDO_MXRFE = { 0x0094, 5, 5, 0, "EN_LOADIMP_LDO_MXRFE", "Enables the load dependent bias to optimize the load regulation" }; +const struct LMS7Parameter EN_LOADIMP_LDO_RBB = { 0x0094, 4, 4, 0, "EN_LOADIMP_LDO_RBB", "Enables the load dependent bias to optimize the load regulation" }; +const struct LMS7Parameter EN_LOADIMP_LDO_RXBUF = { 0x0094, 3, 3, 0, "EN_LOADIMP_LDO_RXBUF", "Enables the load dependent bias to optimize the load regulation" }; +const struct LMS7Parameter EN_LOADIMP_LDO_TBB = { 0x0094, 2, 2, 0, "EN_LOADIMP_LDO_TBB", "Enables the load dependent bias to optimize the load regulation" }; +const struct LMS7Parameter EN_LOADIMP_LDO_TIA12 = { 0x0094, 1, 1, 0, "EN_LOADIMP_LDO_TIA12", "Enables the load dependent bias to optimize the load regulation" }; +const struct LMS7Parameter EN_LOADIMP_LDO_TIA14 = { 0x0094, 0, 0, 0, "EN_LOADIMP_LDO_TIA14", "Enables the load dependent bias to optimize the load regulation" }; +const struct LMS7Parameter BYP_LDO_TBB = { 0x0095, 15, 15, 0, "BYP_LDO_TBB", "Bypass signal for the LDO" }; +const struct LMS7Parameter BYP_LDO_TIA12 = { 0x0095, 14, 14, 0, "BYP_LDO_TIA12", "Bypass signal for the LDO" }; +const struct LMS7Parameter BYP_LDO_TIA14 = { 0x0095, 13, 13, 0, "BYP_LDO_TIA14", "Bypass signal for the LDO" }; +const struct LMS7Parameter BYP_LDO_TLOB = { 0x0095, 12, 12, 0, "BYP_LDO_TLOB", "Bypass signal for the LDO" }; +const struct LMS7Parameter BYP_LDO_TPAD = { 0x0095, 11, 11, 0, "BYP_LDO_TPAD", "Bypass signal for the LDO" }; +const struct LMS7Parameter BYP_LDO_TXBUF = { 0x0095, 10, 10, 0, "BYP_LDO_TXBUF", "Bypass signal for the LDO" }; +const struct LMS7Parameter BYP_LDO_VCOGN = { 0x0095, 9, 9, 0, "BYP_LDO_VCOGN", "Bypass signal for the LDO" }; +const struct LMS7Parameter BYP_LDO_VCOSXR = { 0x0095, 8, 8, 0, "BYP_LDO_VCOSXR", "Bypass signal for the LDO" }; +const struct LMS7Parameter BYP_LDO_VCOSXT = { 0x0095, 7, 7, 0, "BYP_LDO_VCOSXT", "Bypass signal for the LDO" }; +const struct LMS7Parameter EN_LOADIMP_LDO_AFE = { 0x0095, 2, 2, 0, "EN_LOADIMP_LDO_AFE", "Enables the load dependent bias to optimize the load regulation" }; +const struct LMS7Parameter EN_LOADIMP_LDO_CPGN = { 0x0095, 1, 1, 0, "EN_LOADIMP_LDO_CPGN", "Enables the load dependent bias to optimize the load regulation" }; +const struct LMS7Parameter EN_LOADIMP_LDO_CPSXR = { 0x0095, 0, 0, 0, "EN_LOADIMP_LDO_CPSXR", "Enables the load dependent bias to optimize the load regulation" }; +const struct LMS7Parameter BYP_LDO_AFE = { 0x0096, 15, 15, 0, "BYP_LDO_AFE", "Bypass signal for the LDO" }; +const struct LMS7Parameter BYP_LDO_CPGN = { 0x0096, 14, 14, 0, "BYP_LDO_CPGN", "Bypass signal for the LDO" }; +const struct LMS7Parameter BYP_LDO_CPSXR = { 0x0096, 13, 13, 0, "BYP_LDO_CPSXR", "Bypass signal for the LDO" }; +const struct LMS7Parameter BYP_LDO_CPSXT = { 0x0096, 12, 12, 0, "BYP_LDO_CPSXT", "Bypass signal for the LDO" }; +const struct LMS7Parameter BYP_LDO_DIG = { 0x0096, 11, 11, 0, "BYP_LDO_DIG", "Bypass signal for the LDO" }; +const struct LMS7Parameter BYP_LDO_DIGGN = { 0x0096, 10, 10, 0, "BYP_LDO_DIGGN", "Bypass signal for the LDO" }; +const struct LMS7Parameter BYP_LDO_DIGSXR = { 0x0096, 9, 9, 0, "BYP_LDO_DIGSXR", "Bypass signal for the LDO" }; +const struct LMS7Parameter BYP_LDO_DIGSXT = { 0x0096, 8, 8, 0, "BYP_LDO_DIGSXT", "Bypass signal for the LDO" }; +const struct LMS7Parameter BYP_LDO_DIVGN = { 0x0096, 7, 7, 0, "BYP_LDO_DIVGN", "Bypass signal for the LDO" }; +const struct LMS7Parameter BYP_LDO_DIVSXR = { 0x0096, 6, 6, 0, "BYP_LDO_DIVSXR", "Bypass signal for the LDO" }; +const struct LMS7Parameter BYP_LDO_DIVSXT = { 0x0096, 5, 5, 0, "BYP_LDO_DIVSXT", "Bypass signal for the LDO" }; +const struct LMS7Parameter BYP_LDO_LNA12 = { 0x0096, 4, 4, 0, "BYP_LDO_LNA12", "Bypass signal for the LDO" }; +const struct LMS7Parameter BYP_LDO_LNA14 = { 0x0096, 3, 3, 0, "BYP_LDO_LNA14", "Bypass signal for the LDO" }; +const struct LMS7Parameter BYP_LDO_MXRFE = { 0x0096, 2, 2, 0, "BYP_LDO_MXRFE", "Bypass signal for the LDO" }; +const struct LMS7Parameter BYP_LDO_RBB = { 0x0096, 1, 1, 0, "BYP_LDO_RBB", "Bypass signal for the LDO" }; +const struct LMS7Parameter BYP_LDO_RXBUF = { 0x0096, 0, 0, 0, "BYP_LDO_RXBUF", "Bypass signal for the LDO" }; +const struct LMS7Parameter SPDUP_LDO_DIVSXR = { 0x0097, 15, 15, 0, "SPDUP_LDO_DIVSXR", "Short the noise filter resistor to speed up the settling time" }; +const struct LMS7Parameter SPDUP_LDO_DIVSXT = { 0x0097, 14, 14, 0, "SPDUP_LDO_DIVSXT", "Short the noise filter resistor to speed up the settling time" }; +const struct LMS7Parameter SPDUP_LDO_LNA12 = { 0x0097, 13, 13, 0, "SPDUP_LDO_LNA12", "Short the noise filter resistor to speed up the settling time" }; +const struct LMS7Parameter SPDUP_LDO_LNA14 = { 0x0097, 12, 12, 0, "SPDUP_LDO_LNA14", "Short the noise filter resistor to speed up the settling time" }; +const struct LMS7Parameter SPDUP_LDO_MXRFE = { 0x0097, 11, 11, 0, "SPDUP_LDO_MXRFE", "Short the noise filter resistor to speed up the settling time" }; +const struct LMS7Parameter SPDUP_LDO_RBB = { 0x0097, 10, 10, 0, "SPDUP_LDO_RBB", "Short the noise filter resistor to speed up the settling time" }; +const struct LMS7Parameter SPDUP_LDO_RXBUF = { 0x0097, 9, 9, 0, "SPDUP_LDO_RXBUF", "Short the noise filter resistor to speed up the settling time" }; +const struct LMS7Parameter SPDUP_LDO_TBB = { 0x0097, 8, 8, 0, "SPDUP_LDO_TBB", "Short the noise filter resistor to speed up the settling time" }; +const struct LMS7Parameter SPDUP_LDO_TIA12 = { 0x0097, 7, 7, 0, "SPDUP_LDO_TIA12", "Short the noise filter resistor to speed up the settling time" }; +const struct LMS7Parameter SPDUP_LDO_TIA14 = { 0x0097, 6, 6, 0, "SPDUP_LDO_TIA14", "Short the noise filter resistor to speed up the settling time" }; +const struct LMS7Parameter SPDUP_LDO_TLOB = { 0x0097, 5, 5, 0, "SPDUP_LDO_TLOB", "Short the noise filter resistor to speed up the settling time" }; +const struct LMS7Parameter SPDUP_LDO_TPAD = { 0x0097, 4, 4, 0, "SPDUP_LDO_TPAD", "Short the noise filter resistor to speed up the settling time" }; +const struct LMS7Parameter SPDUP_LDO_TXBUF = { 0x0097, 3, 3, 0, "SPDUP_LDO_TXBUF", "Short the noise filter resistor to speed up the settling time" }; +const struct LMS7Parameter SPDUP_LDO_VCOGN = { 0x0097, 2, 2, 0, "SPDUP_LDO_VCOGN", "Short the noise filter resistor to speed up the settling time" }; +const struct LMS7Parameter SPDUP_LDO_VCOSXR = { 0x0097, 1, 1, 0, "SPDUP_LDO_VCOSXR", "Short the noise filter resistor to speed up the settling time" }; +const struct LMS7Parameter SPDUP_LDO_VCOSXT = { 0x0097, 0, 0, 0, "SPDUP_LDO_VCOSXT", "Short the noise filter resistor to speed up the settling time" }; +const struct LMS7Parameter SPDUP_LDO_AFE = { 0x0098, 8, 8, 0, "SPDUP_LDO_AFE", "Short the noise filter resistor to speed up the settling time" }; +const struct LMS7Parameter SPDUP_LDO_CPGN = { 0x0098, 7, 7, 0, "SPDUP_LDO_CPGN", "Short the noise filter resistor to speed up the settling time" }; +const struct LMS7Parameter SPDUP_LDO_CPSXR = { 0x0098, 6, 6, 0, "SPDUP_LDO_CPSXR", "Short the noise filter resistor to speed up the settling time" }; +const struct LMS7Parameter SPDUP_LDO_CPSXT = { 0x0098, 5, 5, 0, "SPDUP_LDO_CPSXT", "Short the noise filter resistor to speed up the settling time" }; +const struct LMS7Parameter SPDUP_LDO_DIG = { 0x0098, 4, 4, 0, "SPDUP_LDO_DIG", "Short the noise filter resistor to speed up the settling time" }; +const struct LMS7Parameter SPDUP_LDO_DIGGN = { 0x0098, 3, 3, 0, "SPDUP_LDO_DIGGN", "Short the noise filter resistor to speed up the settling time" }; +const struct LMS7Parameter SPDUP_LDO_DIGSXR = { 0x0098, 2, 2, 0, "SPDUP_LDO_DIGSXR", "Short the noise filter resistor to speed up the settling time" }; +const struct LMS7Parameter SPDUP_LDO_DIGSXT = { 0x0098, 1, 1, 0, "SPDUP_LDO_DIGSXT", "Short the noise filter resistor to speed up the settling time" }; +const struct LMS7Parameter SPDUP_LDO_DIVGN = { 0x0098, 0, 0, 0, "SPDUP_LDO_DIVGN", "Short the noise filter resistor to speed up the settling time" }; +const struct LMS7Parameter RDIV_VCOSXR = { 0x0099, 15, 8, 101, "RDIV_VCOSXR", "Controls the output voltage of the LDO by setting the resistive voltage divider ratio" }; +const struct LMS7Parameter RDIV_VCOSXT = { 0x0099, 7, 0, 101, "RDIV_VCOSXT", "Controls the output voltage of the LDO by setting the resistive voltage divider ratio" }; +const struct LMS7Parameter RDIV_TXBUF = { 0x009A, 15, 8, 101, "RDIV_TXBUF", "Controls the output voltage of the LDO by setting the resistive voltage divider ratio" }; +const struct LMS7Parameter RDIV_VCOGN = { 0x009A, 7, 0, 140, "RDIV_VCOGN", "Controls the output voltage of the LDO by setting the resistive voltage divider ratio" }; +const struct LMS7Parameter RDIV_TLOB = { 0x009B, 15, 8, 101, "RDIV_TLOB", "Controls the output voltage of the LDO by setting the resistive voltage divider ratio" }; +const struct LMS7Parameter RDIV_TPAD = { 0x009B, 7, 0, 101, "RDIV_TPAD", "Controls the output voltage of the LDO by setting the resistive voltage divider ratio" }; +const struct LMS7Parameter RDIV_TIA12 = { 0x009C, 15, 8, 101, "RDIV_TIA12", "Controls the output voltage of the LDO by setting the resistive voltage divider ratio" }; +const struct LMS7Parameter RDIV_TIA14 = { 0x009C, 7, 0, 140, "RDIV_TIA14", "Controls the output voltage of the LDO by setting the resistive voltage divider ratio" }; +const struct LMS7Parameter RDIV_RXBUF = { 0x009D, 15, 8, 101, "RDIV_RXBUF", "Controls the output voltage of the LDO by setting the resistive voltage divider ratio" }; +const struct LMS7Parameter RDIV_TBB = { 0x009D, 7, 0, 101, "RDIV_TBB", "Controls the output voltage of the LDO by setting the resistive voltage divider ratio" }; +const struct LMS7Parameter RDIV_MXRFE = { 0x009E, 15, 8, 101, "RDIV_MXRFE", "Controls the output voltage of the LDO by setting the resistive voltage divider ratio" }; +const struct LMS7Parameter RDIV_RBB = { 0x009E, 7, 0, 140, "RDIV_RBB", "Controls the output voltage of the LDO by setting the resistive voltage divider ratio" }; +const struct LMS7Parameter RDIV_LNA12 = { 0x009F, 15, 8, 101, "RDIV_LNA12", "Controls the output voltage of the LDO by setting the resistive voltage divider ratio" }; +const struct LMS7Parameter RDIV_LNA14 = { 0x009F, 7, 0, 140, "RDIV_LNA14", "Controls the output voltage of the LDO by setting the resistive voltage divider ratio" }; +const struct LMS7Parameter RDIV_DIVSXR = { 0x00A0, 15, 8, 101, "RDIV_DIVSXR", "Controls the output voltage of the LDO by setting the resistive voltage divider ratio" }; +const struct LMS7Parameter RDIV_DIVSXT = { 0x00A0, 7, 0, 101, "RDIV_DIVSXT", "Controls the output voltage of the LDO by setting the resistive voltage divider ratio" }; +const struct LMS7Parameter RDIV_DIGSXT = { 0x00A1, 15, 8, 101, "RDIV_DIGSXT", "Controls the output voltage of the LDO by setting the resistive voltage divider ratio" }; +const struct LMS7Parameter RDIV_DIVGN = { 0x00A1, 7, 0, 101, "RDIV_DIVGN", "Controls the output voltage of the LDO by setting the resistive voltage divider ratio" }; +const struct LMS7Parameter RDIV_DIGGN = { 0x00A2, 15, 8, 101, "RDIV_DIGGN", "Controls the output voltage of the LDO by setting the resistive voltage divider ratio" }; +const struct LMS7Parameter RDIV_DIGSXR = { 0x00A2, 7, 0, 101, "RDIV_DIGSXR", "Controls the output voltage of the LDO by setting the resistive voltage divider ratio" }; +const struct LMS7Parameter RDIV_CPSXT = { 0x00A3, 15, 8, 101, "RDIV_CPSXT", "Controls the output voltage of the LDO by setting the resistive voltage divider ratio" }; +const struct LMS7Parameter RDIV_DIG = { 0x00A3, 7, 0, 101, "RDIV_DIG", "Controls the output voltage of the LDO by setting the resistive voltage divider ratio" }; +const struct LMS7Parameter RDIV_CPGN = { 0x00A4, 15, 8, 101, "RDIV_CPGN", "Controls the output voltage of the LDO by setting the resistive voltage divider ratio" }; +const struct LMS7Parameter RDIV_CPSXR = { 0x00A4, 7, 0, 101, "RDIV_CPSXR", "Controls the output voltage of the LDO by setting the resistive voltage divider ratio" }; +const struct LMS7Parameter RDIV_SPIBUF = { 0x00A5, 15, 8, 101, "RDIV_SPIBUF", "Controls the output voltage of the LDO by setting the resistive voltage divider ratio" }; +const struct LMS7Parameter RDIV_AFE = { 0x00A5, 7, 0, 101, "RDIV_AFE", "Controls the output voltage of the LDO by setting the resistive voltage divider ratio" }; +const struct LMS7Parameter SPDUP_LDO_SPIBUF = { 0x00A6, 12, 12, 0, "SPDUP_LDO_SPIBUF", "Short the noise filter resistor to speed up the settling time" }; +const struct LMS7Parameter SPDUP_LDO_DIGIp2 = { 0x00A6, 11, 11, 0, "SPDUP_LDO_DIGIp2", "Short the noise filter resistor to speed up the settling time" }; +const struct LMS7Parameter SPDUP_LDO_DIGIp1 = { 0x00A6, 10, 10, 0, "SPDUP_LDO_DIGIp1", "Short the noise filter resistor to speed up the settling time" }; +const struct LMS7Parameter BYP_LDO_SPIBUF = { 0x00A6, 9, 9, 0, "BYP_LDO_SPIBUF", "Bypass signal for the LDO" }; +const struct LMS7Parameter BYP_LDO_DIGIp2 = { 0x00A6, 8, 8, 0, "BYP_LDO_DIGIp2", "Bypass signal for the LDO" }; +const struct LMS7Parameter BYP_LDO_DIGIp1 = { 0x00A6, 7, 7, 0, "BYP_LDO_DIGIp1", "Bypass signal for the LDO" }; +const struct LMS7Parameter EN_LOADIMP_LDO_SPIBUF = { 0x00A6, 6, 6, 0, "EN_LOADIMP_LDO_SPIBUF", "Enables the load dependent bias to optimize the load regulation" }; +const struct LMS7Parameter EN_LOADIMP_LDO_DIGIp2 = { 0x00A6, 5, 5, 0, "EN_LOADIMP_LDO_DIGIp2", "Enables the load dependent bias to optimize the load regulation" }; +const struct LMS7Parameter EN_LOADIMP_LDO_DIGIp1 = { 0x00A6, 4, 4, 0, "EN_LOADIMP_LDO_DIGIp1", "Enables the load dependent bias to optimize the load regulation" }; +const struct LMS7Parameter PD_LDO_SPIBUF = { 0x00A6, 3, 3, 1, "PD_LDO_SPIBUF", "Enables the LDO" }; +const struct LMS7Parameter PD_LDO_DIGIp2 = { 0x00A6, 2, 2, 1, "PD_LDO_DIGIp2", "Enables the LDO" }; +const struct LMS7Parameter PD_LDO_DIGIp1 = { 0x00A6, 1, 1, 1, "PD_LDO_DIGIp1", "Enables the LDO" }; +const struct LMS7Parameter EN_G_LDOP = { 0x00A6, 0, 0, 1, "EN_G_LDOP", "Enable control for all the LDO power downs" }; +const struct LMS7Parameter RDIV_DIGIp2 = { 0x00A7, 15, 8, 101, "RDIV_DIGIp2", "Controls the output voltage of the LDO by setting the resistive voltage divider ratio" }; +const struct LMS7Parameter RDIV_DIGIp1 = { 0x00A7, 7, 0, 101, "RDIV_DIGIp1", "Controls the output voltage of the LDO by setting the resistive voltage divider ratio" }; +const struct LMS7Parameter BSIGT = { 0x00A8, 31, 9, 0, "BSIGT", "" }; +const struct LMS7Parameter BSTATE = { 0x00A8, 8, 8, 0, "BSTATE", "" }; +const struct LMS7Parameter EN_SDM_TSTO_SXT = { 0x00A8, 6, 6, 0, "EN_SDM_TSTO_SXT", "Enables the SDM_TSTO_SXT" }; +const struct LMS7Parameter EN_SDM_TSTO_SXR = { 0x00A8, 5, 5, 0, "EN_SDM_TSTO_SXR", "Enables the SDM_TSTO_SXR" }; +const struct LMS7Parameter EN_SDM_TSTO_CGEN = { 0x00A8, 4, 4, 0, "EN_SDM_TSTO_CGEN", "Enables the SDM_TSTO_CGEN" }; +const struct LMS7Parameter BENC = { 0x00A8, 3, 3, 0, "BENC", "enables CGEN BIST" }; +const struct LMS7Parameter BENR = { 0x00A8, 2, 2, 0, "BENR", "enables SXR BIST" }; +const struct LMS7Parameter BENT = { 0x00A8, 1, 1, 0, "BENT", "enables SXT BIST" }; +const struct LMS7Parameter BSTART = { 0x00A8, 0, 0, 0, "BSTART", "Starts delta sigma built in self test. Keep it at 1 one at least three clock cycles" }; +const struct LMS7Parameter BSIGR = { 0x00AA, 22, 0, 0, "BSIGR", "" }; +const struct LMS7Parameter BSIGC = { 0x00AB, 29, 7, 0, "BSIGC", "" }; +const struct LMS7Parameter CDS_MCLK2 = { 0x00AD, 15, 14, 0, "CDS_MCLK2", "MCLK2 clock delay" }; +const struct LMS7Parameter CDS_MCLK1 = { 0x00AD, 13, 12, 0, "CDS_MCLK1", "MCLK1 clock delay" }; +const struct LMS7Parameter CDSN_TXBTSP = { 0x00AD, 9, 9, 1, "CDSN_TXBTSP", "TX TSPB clock inversion control" }; +const struct LMS7Parameter CDSN_TXATSP = { 0x00AD, 8, 8, 1, "CDSN_TXATSP", "TX TSPA clock inversion control" }; +const struct LMS7Parameter CDSN_RXBTSP = { 0x00AD, 7, 7, 1, "CDSN_RXBTSP", "RX TSPB clock inversion control" }; +const struct LMS7Parameter CDSN_RXATSP = { 0x00AD, 6, 6, 1, "CDSN_RXATSP", "RX TSPA clock inversion control" }; +const struct LMS7Parameter CDSN_TXBLML = { 0x00AD, 5, 5, 1, "CDSN_TXBLML", "TX LMLB clock inversion control" }; +const struct LMS7Parameter CDSN_TXALML = { 0x00AD, 4, 4, 1, "CDSN_TXALML", "TX LMLA clock inversion control" }; +const struct LMS7Parameter CDSN_RXBLML = { 0x00AD, 3, 3, 1, "CDSN_RXBLML", "RX LMLB clock inversion control" }; +const struct LMS7Parameter CDSN_RXALML = { 0x00AD, 2, 2, 1, "CDSN_RXALML", "RX LMLA clock inversion control" }; +const struct LMS7Parameter CDSN_MCLK2 = { 0x00AD, 1, 1, 1, "CDSN_MCLK2", "MCLK2 clock inversion control" }; +const struct LMS7Parameter CDSN_MCLK1 = { 0x00AD, 0, 0, 1, "CDSN_MCLK1", "MCLK1 clock inversion control" }; +const struct LMS7Parameter CDS_TXBTSP = { 0x00AE, 15, 14, 0, "CDS_TXBTSP", "TX TSP B clock delay" }; +const struct LMS7Parameter CDS_TXATSP = { 0x00AE, 13, 12, 0, "CDS_TXATSP", "TX TSP A clock delay" }; +const struct LMS7Parameter CDS_RXBTSP = { 0x00AE, 11, 10, 0, "CDS_RXBTSP", "RX TSP B clock delay" }; +const struct LMS7Parameter CDS_RXATSP = { 0x00AE, 9, 8, 0, "CDS_RXATSP", "RX TSP A clock delay" }; +const struct LMS7Parameter CDS_TXBLML = { 0x00AE, 7, 6, 0, "CDS_TXBLML", "TX LML B clock delay" }; +const struct LMS7Parameter CDS_TXALML = { 0x00AE, 5, 4, 0, "CDS_TXALML", "TX LML A clock delay" }; +const struct LMS7Parameter CDS_RXBLML = { 0x00AE, 3, 2, 0, "CDS_RXBLML", "RX LML B clock delay" }; +const struct LMS7Parameter CDS_RXALML = { 0x00AE, 1, 0, 0, "CDS_RXALML", "RX LML A clock delay" }; +const struct LMS7Parameter EN_LOWBWLOMX_TMX_TRF = { 0x0100, 15, 15, 0, "EN_LOWBWLOMX_TMX_TRF", "Controls the high pass pole frequency of the RC biasing the gate of the mixer switches" }; +const struct LMS7Parameter EN_NEXTTX_TRF = { 0x0100, 14, 14, 0, "EN_NEXTTX_TRF", "Enables the daisy change LO buffer going from TRF_1 to TRF2" }; +const struct LMS7Parameter EN_AMPHF_PDET_TRF = { 0x0100, 13, 12, 3, "EN_AMPHF_PDET_TRF", "Enables the TXPAD power detector preamplifier" }; +const struct LMS7Parameter LOADR_PDET_TRF = { 0x0100, 11, 10, 1, "LOADR_PDET_TRF", "Controls the resistive load of the Power detector" }; +const struct LMS7Parameter PD_PDET_TRF = { 0x0100, 3, 3, 1, "PD_PDET_TRF", "Powerdown signal for Power Detector" }; +const struct LMS7Parameter PD_TLOBUF_TRF = { 0x0100, 2, 2, 0, "PD_TLOBUF_TRF", "Powerdown signal for TX LO buffer" }; +const struct LMS7Parameter PD_TXPAD_TRF = { 0x0100, 1, 1, 0, "PD_TXPAD_TRF", "Powerdown signal for TXPAD" }; +const struct LMS7Parameter EN_G_TRF = { 0x0100, 0, 0, 1, "EN_G_TRF", "Enable control for all the TRF_1 power downs" }; +const struct LMS7Parameter F_TXPAD_TRF = { 0x0101, 15, 13, 3, "F_TXPAD_TRF", "Controls the switched capacitor at the TXPAD output. Is used for fine tuning of the TXPAD output" }; +const struct LMS7Parameter L_LOOPB_TXPAD_TRF = { 0x0101, 12, 11, 3, "L_LOOPB_TXPAD_TRF", "Controls the loss of the of the loopback path at the TX side" }; +const struct LMS7Parameter LOSS_LIN_TXPAD_TRF = { 0x0101, 10, 6, 0, "LOSS_LIN_TXPAD_TRF", "Controls the gain of the linearizing part of of the TXPAD" }; +const struct LMS7Parameter LOSS_MAIN_TXPAD_TRF = { 0x0101, 5, 1, 0, "LOSS_MAIN_TXPAD_TRF", "Controls the gain output power of the TXPAD" }; +const struct LMS7Parameter EN_LOOPB_TXPAD_TRF = { 0x0101, 0, 0, 0, "EN_LOOPB_TXPAD_TRF", "Enables the TXPAD loopback path" }; +const struct LMS7Parameter GCAS_GNDREF_TXPAD_TRF = { 0x0102, 15, 15, 0, "GCAS_GNDREF_TXPAD_TRF", "Controls if the TXPAD cascode transistor gate bias is referred to VDD or GND" }; +const struct LMS7Parameter ICT_LIN_TXPAD_TRF = { 0x0102, 14, 10, 12, "ICT_LIN_TXPAD_TRF", "Control the bias current of the linearization section of the TXPAD" }; +const struct LMS7Parameter ICT_MAIN_TXPAD_TRF = { 0x0102, 9, 5, 12, "ICT_MAIN_TXPAD_TRF", "Control the bias current of the main gm section of the TXPAD" }; +const struct LMS7Parameter VGCAS_TXPAD_TRF = { 0x0102, 4, 0, 0, "VGCAS_TXPAD_TRF", "Controls the bias voltage at the gate of TXPAD cascade" }; +const struct LMS7Parameter SEL_BAND1_TRF = { 0x0103, 11, 11, 1, "SEL_BAND1_TRF", "" }; +const struct LMS7Parameter SEL_BAND2_TRF = { 0x0103, 10, 10, 0, "SEL_BAND2_TRF", "" }; +const struct LMS7Parameter LOBIASN_TXM_TRF = { 0x0103, 9, 5, 16, "LOBIASN_TXM_TRF", "Controls the bias at the gate of the mixer NMOS" }; +const struct LMS7Parameter LOBIASP_TXX_TRF = { 0x0103, 4, 0, 18, "LOBIASP_TXX_TRF", "Controls the bias at the gate of the mixer PMOS" }; +const struct LMS7Parameter CDC_I_TRF = { 0x0104, 7, 4, 8, "CDC_I_TRF", "" }; +const struct LMS7Parameter CDC_Q_TRF = { 0x0104, 3, 0, 8, "CDC_Q_TRF", "" }; +const struct LMS7Parameter STATPULSE_TBB = { 0x0105, 15, 15, 0, "STATPULSE_TBB", "" }; +const struct LMS7Parameter LOOPB_TBB = { 0x0105, 14, 12, 0, "LOOPB_TBB", "This controls which signal is connected to the loopback output pins. Note: when both the lowpass ladder and real pole are powered down, the output of the active highband biquad is routed to the loopb output" }; +const struct LMS7Parameter PD_LPFH_TBB = { 0x0105, 4, 4, 0, "PD_LPFH_TBB", "This selectively powers down the LPFH_TBB biquad" }; +const struct LMS7Parameter PD_LPFIAMP_TBB = { 0x0105, 3, 3, 0, "PD_LPFIAMP_TBB", "selectively powers down the LPFIAMP_TBB front-end current amp of the transmitter baseband" }; +const struct LMS7Parameter PD_LPFLAD_TBB = { 0x0105, 2, 2, 1, "PD_LPFLAD_TBB", "This selectively powers down the LPFLAD_TBB low pass ladder filter of the transmitter baseband" }; +const struct LMS7Parameter PD_LPFS5_TBB = { 0x0105, 1, 1, 1, "PD_LPFS5_TBB", "This selectively powers down the LPFS5_TBB low pass real-pole filter of the transmitter baseband" }; +const struct LMS7Parameter EN_G_TBB = { 0x0105, 0, 0, 1, "EN_G_TBB", "Enable control for all the TBB_TOP power downs" }; +const struct LMS7Parameter ICT_LPFS5_F_TBB = { 0x0106, 14, 10, 12, "ICT_LPFS5_F_TBB", "This controls the operational amplifier's output stage bias current of the low band real pole filter of the transmitter's baseband" }; +const struct LMS7Parameter ICT_LPFS5_PT_TBB = { 0x0106, 9, 5, 12, "ICT_LPFS5_PT_TBB", "This controls the operational amplifier's input stage bias current of the low band real pole filter of the transmitter's baseband" }; +const struct LMS7Parameter ICT_LPF_H_PT_TBB = { 0x0106, 4, 0, 12, "ICT_LPF_H_PT_TBB", "This controls the operational amplifiers input stage bias reference current of the high band low pass filter of the transmitter's baseband " }; +const struct LMS7Parameter ICT_LPFH_F_TBB = { 0x0107, 14, 10, 12, "ICT_LPFH_F_TBB", "controls the operational amplifiers output stage bias reference current of the high band low pass filter of the transmitter's baseband (LPFH_TBB)" }; +const struct LMS7Parameter ICT_LPFLAD_F_TBB = { 0x0107, 9, 5, 12, "ICT_LPFLAD_F_TBB", "This controls the operational amplfiers' output stages bias referene current of the low band ladder filter of the transmisster's baseband" }; +const struct LMS7Parameter ICT_LPFLAD_PT_TBB = { 0x0107, 4, 0, 12, "ICT_LPFLAD_PT_TBB", "This controls the operational amplifers' input stages bias reference current of the low band ladder filter of the transmitter's baseband" }; +const struct LMS7Parameter CG_IAMP_TBB = { 0x0108, 15, 10, 37, "CG_IAMP_TBB", "This controls the frontend gain of the TBB. For a given gain value, this control value varies with the set TX mode. After resistance calibration, the following table gives the nominal values for each frequency setting. However, this table is to be updated and corrected after calibration" }; +const struct LMS7Parameter ICT_IAMP_FRP_TBB = { 0x0108, 9, 5, 1, "ICT_IAMP_FRP_TBB", "This controls the reference bias current of the IAMP main bias current sources" }; +const struct LMS7Parameter ICT_IAMP_GG_FRP_TBB = { 0x0108, 4, 0, 6, "ICT_IAMP_GG_FRP_TBB", "This controls the reference bias current of the IAMP's cascode transistors gate voltages that set the IAMP's input voltage level. The IAMP's input is connected to the DAC output" }; +const struct LMS7Parameter RCAL_LPFH_TBB = { 0x0109, 15, 8, 97, "RCAL_LPFH_TBB", "This controls the value of the equivalent resistance of the resistor banks of the biquad filter stage (of the high band section) of the transmitter baseband(TBB)" }; +const struct LMS7Parameter RCAL_LPFLAD_TBB = { 0x0109, 7, 0, 193, "RCAL_LPFLAD_TBB", "This controls the value of the equivalent resistance of the resistor banks of the low pass filter ladder (of the low band section) of the transmitter baseband(TBB)" }; +const struct LMS7Parameter TSTIN_TBB = { 0x010A, 15, 14, 0, "TSTIN_TBB", "This control selects where the input test signal (vinp/n_aux_bbq/i) is routed to as well as disabling the route." }; +const struct LMS7Parameter BYPLADDER_TBB = { 0x010A, 13, 13, 0, "BYPLADDER_TBB", "This signal bypasses the LPF ladder of TBB and directly connects the output of current amplifier to the null port of the real pole stage of TBB low pass filter" }; +const struct LMS7Parameter CCAL_LPFLAD_TBB = { 0x010A, 12, 8, 16, "CCAL_LPFLAD_TBB", "A common control signal for all the capacitor banks of TBB filters (including the ladder, real pole, and the high band biquad). It is the calibrated value of the banks control that sets the value of the banks' equivalent capacitor to their respective nominal values" }; +const struct LMS7Parameter RCAL_LPFS5_TBB = { 0x010A, 7, 0, 76, "RCAL_LPFS5_TBB", "This controls the value of the equivalent resistance of the resistor banks of the real pole filter stage (of the low band section) of the transmitter baseband (TBB). Following is a nominal values table that are corrected for any process variation after calibration" }; +const struct LMS7Parameter CDC_I_RFE = { 0x010C, 15, 12, 8, "CDC_I_RFE", "" }; +const struct LMS7Parameter CDC_Q_RFE = { 0x010C, 11, 8, 8, "CDC_Q_RFE", "" }; +const struct LMS7Parameter PD_LNA_RFE = { 0x010C, 7, 7, 1, "PD_LNA_RFE", "Power control signal for LNA_RFE" }; +const struct LMS7Parameter PD_RLOOPB_1_RFE = { 0x010C, 6, 6, 1, "PD_RLOOPB_1_RFE", "Power control signal for RXFE loopback 1" }; +const struct LMS7Parameter PD_RLOOPB_2_RFE = { 0x010C, 5, 5, 1, "PD_RLOOPB_2_RFE", "Power control signal for RXFE loopback 2" }; +const struct LMS7Parameter PD_MXLOBUF_RFE = { 0x010C, 4, 4, 1, "PD_MXLOBUF_RFE", "Power control signal for RXFE mixer lo buffer" }; +const struct LMS7Parameter PD_QGEN_RFE = { 0x010C, 3, 3, 1, "PD_QGEN_RFE", "Power control signal for RXFE Quadrature LO generator" }; +const struct LMS7Parameter PD_RSSI_RFE = { 0x010C, 2, 2, 1, "PD_RSSI_RFE", "Power control signal for RXFE RSSI" }; +const struct LMS7Parameter PD_TIA_RFE = { 0x010C, 1, 1, 0, "PD_TIA_RFE", "Power control signal for RXFE TIA" }; +const struct LMS7Parameter EN_G_RFE = { 0x010C, 0, 0, 1, "EN_G_RFE", "Enable control for all the RFE_1 power downs" }; +const struct LMS7Parameter SEL_PATH_RFE = { 0x010D, 8, 7, 1, "SEL_PATH_RFE", "Selects the active path of the RXFE" }; +const struct LMS7Parameter EN_DCOFF_RXFE_RFE = { 0x010D, 6, 6, 0, "EN_DCOFF_RXFE_RFE", "Enables the DCOFFSET block for the RXFE" }; +const struct LMS7Parameter EN_INSHSW_LB1_RFE = { 0x010D, 4, 4, 1, "EN_INSHSW_LB1_RFE", "Enables the input shorting switch at the input of the loopback 1 (in parallel with LNAL mixer)" }; +const struct LMS7Parameter EN_INSHSW_LB2_RFE = { 0x010D, 3, 3, 1, "EN_INSHSW_LB2_RFE", "Enables the input shorting switch at the input of the loopback 2 (in parallel with LNAW mixer)" }; +const struct LMS7Parameter EN_INSHSW_L_RFE = { 0x010D, 2, 2, 1, "EN_INSHSW_L_RFE", "Enables the input shorting switch at the input of the LNAL" }; +const struct LMS7Parameter EN_INSHSW_W_RFE = { 0x010D, 1, 1, 1, "EN_INSHSW_W_RFE", "Enables the input shorting switch at the input of the LNAW" }; +const struct LMS7Parameter EN_NEXTRX_RFE = { 0x010D, 0, 0, 0, "EN_NEXTRX_RFE", "Enables the daisy chain LO buffer going from RXFE1 to RXFE2" }; +const struct LMS7Parameter DCOFFI_RFE = { 0x010E, 13, 7, 64, "DCOFFI_RFE", "Controls DC offset at the output of the TIA by injecting current to the input of the TIA (I side)" }; +const struct LMS7Parameter DCOFFQ_RFE = { 0x010E, 6, 0, 64, "DCOFFQ_RFE", "Controls DC offset at the output of the TIA by injecting current to the input of the TIA (Q side)" }; +const struct LMS7Parameter ICT_LOOPB_RFE = { 0x010F, 14, 10, 12, "ICT_LOOPB_RFE", "Controls the reference current of the RXFE loopback amplifier" }; +const struct LMS7Parameter ICT_TIAMAIN_RFE = { 0x010F, 9, 5, 2, "ICT_TIAMAIN_RFE", "Controls the reference current of the RXFE TIA first stage" }; +const struct LMS7Parameter ICT_TIAOUT_RFE = { 0x010F, 4, 0, 2, "ICT_TIAOUT_RFE", "Controls the reference current of the RXFE TIA 2nd stage" }; +const struct LMS7Parameter ICT_LNACMO_RFE = { 0x0110, 14, 10, 2, "ICT_LNACMO_RFE", "Controls the current generating LNA output common mode voltage" }; +const struct LMS7Parameter ICT_LNA_RFE = { 0x0110, 9, 5, 31, "ICT_LNA_RFE", "Controls the current of the LNA core" }; +const struct LMS7Parameter ICT_LODC_RFE = { 0x0110, 4, 0, 20, "ICT_LODC_RFE", "Controls the DC of the mixer LO signal at the gate of the mixer switches" }; +const struct LMS7Parameter CAP_RXMXO_RFE = { 0x0111, 9, 5, 4, "CAP_RXMXO_RFE", "Control the decoupling cap at the output of the RX Mixer" }; +const struct LMS7Parameter CGSIN_LNA_RFE = { 0x0111, 4, 0, 3, "CGSIN_LNA_RFE", "Controls the cap parallel with the LNA input input NMOS CGS to control the Q of the maching circuit and provides trade off between gain/NF and IIP. The higher the frequency, the lower CGSIN_LNA_RFE should be. Also, the higher CGSIN, the lower the Q, The lower the gain, the higher the NF, and the higher the IIP3" }; +const struct LMS7Parameter CCOMP_TIA_RFE = { 0x0112, 15, 12, 12, "CCOMP_TIA_RFE", "Compensation capacitor for TIA" }; +const struct LMS7Parameter CFB_TIA_RFE = { 0x0112, 11, 0, 230, "CFB_TIA_RFE", "Feeback capacitor for TIA. Controls the 3dB BW of the TIA. Should be set with calibration through digital baseband" }; +const struct LMS7Parameter G_LNA_RFE = { 0x0113, 9, 6, 15, "G_LNA_RFE", "Controls the gain of the LNA" }; +const struct LMS7Parameter G_RXLOOPB_RFE = { 0x0113, 5, 2, 0, "G_RXLOOPB_RFE", "Controls RXFE loopback gain" }; +const struct LMS7Parameter G_TIA_RFE = { 0x0113, 1, 0, 3, "G_TIA_RFE", "Controls the Gain of the TIA" }; +const struct LMS7Parameter RCOMP_TIA_RFE = { 0x0114, 8, 5, 4, "RCOMP_TIA_RFE", "Controls the compensation resistors of the TIA opamp" }; +const struct LMS7Parameter RFB_TIA_RFE = { 0x0114, 4, 0, 13, "RFB_TIA_RFE", "Sets the feedback resistor to the nominal value" }; +const struct LMS7Parameter EN_LB_LPFH_RBB = { 0x0115, 15, 15, 0, "EN_LB_LPFH_RBB", "" }; +const struct LMS7Parameter EN_LB_LPFL_RBB = { 0x0115, 14, 14, 0, "EN_LB_LPFL_RBB", "" }; +const struct LMS7Parameter PD_LPFH_RBB = { 0x0115, 3, 3, 1, "PD_LPFH_RBB", "Power down of the LPFH block" }; +const struct LMS7Parameter PD_LPFL_RBB = { 0x0115, 2, 2, 0, "PD_LPFL_RBB", "Power down of the LPFL block" }; +const struct LMS7Parameter PD_PGA_RBB = { 0x0115, 1, 1, 0, "PD_PGA_RBB", "Power down of the PGA block" }; +const struct LMS7Parameter EN_G_RBB = { 0x0115, 0, 0, 1, "EN_G_RBB", "Enable control for all the RBB_1 power downs" }; +const struct LMS7Parameter R_CTL_LPF_RBB = { 0x0116, 15, 11, 16, "R_CTL_LPF_RBB", "Controls the absolute value of the resistance of the RC time constant of the RBB_LPF blocks (both Low and High)" }; +const struct LMS7Parameter RCC_CTL_LPFH_RBB = { 0x0116, 10, 8, 1, "RCC_CTL_LPFH_RBB", "Controls the stability passive compensation of the LPFH_RBB operational amplifier" }; +const struct LMS7Parameter C_CTL_LPFH_RBB = { 0x0116, 7, 0, 128, "C_CTL_LPFH_RBB", "Controls the capacitance value of the RC time constant of RBB_LPFH and it varies with the respective rxMode from 37MHz to 108MHz" }; +const struct LMS7Parameter RCC_CTL_LPFL_RBB = { 0x0117, 13, 11, 5, "RCC_CTL_LPFL_RBB", "Controls the stability passive compensation of the LPFL_RBB operational amplifier" }; +const struct LMS7Parameter C_CTL_LPFL_RBB = { 0x0117, 10, 0, 12, "C_CTL_LPFL_RBB", "Controls the capacitance value of the RC time constant of RBB_LPFH and it varies with the respective rxMode from 1.4MHz to 20MHz." }; +const struct LMS7Parameter INPUT_CTL_PGA_RBB = { 0x0118, 15, 13, 0, "INPUT_CTL_PGA_RBB", "There are a total of four different differential inputs to the PGA. Only one of them is active at a time" }; +const struct LMS7Parameter ICT_LPF_IN_RBB = { 0x0118, 9, 5, 12, "ICT_LPF_IN_RBB", "Controls the reference bias current of the input stage of the operational amplifier used in RBB_LPF blocks (Low or High). " }; +const struct LMS7Parameter ICT_LPF_OUT_RBB = { 0x0118, 4, 0, 12, "ICT_LPF_OUT_RBB", "The reference bias current of the output stage of the operational amplifier used in RBB_LPF blocks (low or High)" }; +const struct LMS7Parameter OSW_PGA_RBB = { 0x0119, 15, 15, 0, "OSW_PGA_RBB", "There are two instances of the PGA circuit in the design. The output of the RBB_LPF blocks are connected the input of these PGA blocks (common). The output of one of them is connected to two pads pgaoutn and pgaoutp and the output of the other PGA is connected directly to the ADC input" }; +const struct LMS7Parameter ICT_PGA_OUT_RBB = { 0x0119, 14, 10, 6, "ICT_PGA_OUT_RBB", "Controls the output stage reference bias current of the operational amplifier used in the PGA circuit" }; +const struct LMS7Parameter ICT_PGA_IN_RBB = { 0x0119, 9, 5, 6, "ICT_PGA_IN_RBB", "Controls the input stage reference bias current of the operational amplifier used in the PGA circuit" }; +const struct LMS7Parameter G_PGA_RBB = { 0x0119, 4, 0, 11, "G_PGA_RBB", "This is the gain of the PGA" }; +const struct LMS7Parameter RCC_CTL_PGA_RBB = { 0x011A, 13, 9, 23, "RCC_CTL_PGA_RBB", "Controls the stability passive compensation of the PGA_RBB operational amplifier" }; +const struct LMS7Parameter C_CTL_PGA_RBB = { 0x011A, 6, 0, 2, "C_CTL_PGA_RBB", "Control the value of the feedback capacitor of the PGA that is used to help against the parasitic cap at the virtual node for stability" }; +const struct LMS7Parameter RESET_N = { 0x011C, 15, 15, 1, "RESET_N", "Resets SX. A pulse should be used in the start-up to reset" }; +const struct LMS7Parameter SPDUP_VCO = { 0x011C, 14, 14, 0, "SPDUP_VCO", "Bypasses the noise filter resistor for fast settling time. It should be connected to a 1uS pulse" }; +const struct LMS7Parameter BYPLDO_VCO = { 0x011C, 13, 13, 1, "BYPLDO_VCO", "Controls the bypass signal for the SX LDO" }; +const struct LMS7Parameter EN_COARSEPLL = { 0x011C, 12, 12, 0, "EN_COARSEPLL", "Enable signal for coarse tuning block" }; +const struct LMS7Parameter CURLIM_VCO = { 0x011C, 11, 11, 1, "CURLIM_VCO", "Enables the output current limitation in the VCO regulator" }; +const struct LMS7Parameter EN_DIV2_DIVPROG = { 0x011C, 10, 10, 1, "EN_DIV2_DIVPROG", "" }; +const struct LMS7Parameter EN_INTONLY_SDM = { 0x011C, 9, 9, 0, "EN_INTONLY_SDM", "Enables INTEGER-N mode of the SX " }; +const struct LMS7Parameter EN_SDM_CLK = { 0x011C, 8, 8, 1, "EN_SDM_CLK", "Enables/Disables SDM clock. In INT-N mode or for noise testing, SDM clock can be disabled" }; +const struct LMS7Parameter PD_FBDIV = { 0x011C, 7, 7, 0, "PD_FBDIV", "Power down the feedback divider block" }; +const struct LMS7Parameter PD_LOCH_T2RBUF = { 0x011C, 6, 6, 1, "PD_LOCH_T2RBUF", "Power down for LO buffer from SXT to SXR. To be active only in the TDD mode" }; +const struct LMS7Parameter PD_CP = { 0x011C, 5, 5, 0, "PD_CP", "Power down for Charge Pump" }; +const struct LMS7Parameter PD_FDIV = { 0x011C, 4, 4, 0, "PD_FDIV", "Power down for feedback frequency and forward dividers" }; +const struct LMS7Parameter PD_SDM = { 0x011C, 3, 3, 0, "PD_SDM", "Power down for SDM" }; +const struct LMS7Parameter PD_VCO_COMP = { 0x011C, 2, 2, 0, "PD_VCO_COMP", "Power down for VCO comparator" }; +const struct LMS7Parameter PD_VCO = { 0x011C, 1, 1, 1, "PD_VCO", "Power down for VCO" }; +const struct LMS7Parameter EN_G = { 0x011C, 0, 0, 1, "EN_G", "Enable control for all the SXT power downs" }; +const struct LMS7Parameter FRAC_SDM_LSB = { 0x011D, 15, 0, 0x0400, "FRAC_SDM_LSB", "" }; +const struct LMS7Parameter INT_SDM = { 0x011E, 13, 4, 120, "INT_SDM", "" }; +const struct LMS7Parameter FRAC_SDM_MSB = { 0x011E, 3, 0, 0, "FRAC_SDM_MSB", "" }; +const struct LMS7Parameter PW_DIV2_LOCH = { 0x011F, 14, 12, 3, "PW_DIV2_LOCH", "trims the duty cycle of DIV2 LOCH. Only works when forward divider is dividing by at least 2 (excluding quadrature block division). If in bypass mode, this does not work" }; +const struct LMS7Parameter PW_DIV4_LOCH = { 0x011F, 11, 9, 3, "PW_DIV4_LOCH", "trims the duty cycle of DIV4 LOCH. Only works when forward divider is dividing by at least 4 (excluding quadrature block division). If in bypass mode, this does not work" }; +const struct LMS7Parameter DIV_LOCH = { 0x011F, 8, 6, 1, "DIV_LOCH", "Controls the division ratio in the LOCH_DIV" }; +const struct LMS7Parameter TST_SX = { 0x011F, 5, 3, 0, "TST_SX", +"Controls the test mode of PLLs. TST signal lines are shared between all PLLs (CGEN, RX and TX). Only one TST signal of any PLL should be active at a given time.\n\ +0 - TST disabled; RSSI analog outputs enabled if RSSI blocks active and when all PLL test signals are off(default)\n\ +1 - tstdo[0] = VCO / 20 clock*; tstdo[1] = VCO / 40 clock*; tstao = High impedance;\n\ +2 - tstdo[0] = SDM clock; tstdo[1] = feedback divider output; tstao = VCO tune through a 60kOhm resistor;\n\ +3 - tstdo[0] = Reference clock; tstdo[1] = feedback divider output; tstao = VCO tune through a 10kOhm resistor;\n\ +4 - tstdo[0] = High impedance; tstdo[1] = High impedance; tstao = High impedance;\n\ +5 - tstdo[0] = Charge pump Down signal; tstdo[1] = Charge pump Up signal; tstao = High impedance;\n\ +6 - tstdo[0] = High impedance; tstdo[1] = High impedance; tstao = VCO tune through a 60kOhm resistor;\n\ +7 - tstdo[0] = High impedance; tstdo[1] = High impedance; tstao = VCO tune through a 10kOhm resistor;\n\ +if TST_SX[2] = 1 --> VCO_TSTBUF active generating VCO_TST_DIV20 and VCO_TST_DIV40\n\ +* When EN_DIV2_DIVPROG_(SXR, SXT) is active, the division ratio must be multiplied by 2 (40 / 80)"}; +const struct LMS7Parameter SEL_SDMCLK = { 0x011F, 2, 2, 0, "SEL_SDMCLK", "Selects between the feedback divider output and Fref for SDM" }; +const struct LMS7Parameter SX_DITHER_EN = { 0x011F, 1, 1, 0, "SX_DITHER_EN", "Enabled dithering in SDM" }; +const struct LMS7Parameter REV_SDMCLK = { 0x011F, 0, 0, 0, "REV_SDMCLK", "Reverses the SDM clock" }; +const struct LMS7Parameter VDIV_VCO = { 0x0120, 15, 8, 185, "VDIV_VCO", "Controls VCO LDO output voltage" }; +const struct LMS7Parameter ICT_VCO = { 0x0120, 7, 0, 255, "ICT_VCO", "Scales the VCO bias current from 0 to 2.5xInom" }; +const struct LMS7Parameter RSEL_LDO_VCO = { 0x0121, 15, 11, 6, "RSEL_LDO_VCO", "Set the reference voltage that supplies bias voltage of switch-cap array and varactor" }; +const struct LMS7Parameter CSW_VCO = { 0x0121, 10, 3, 128, "CSW_VCO", "Coarse control of VCO frequency, 0 for lowest frequency and 255 for highest. This control is set by SX_SWC_calibration" }; +const struct LMS7Parameter SEL_VCO = { 0x0121, 2, 1, 2, "SEL_VCO", "Selects the active VCO. It is set by SX_SWC_calibration" }; +const struct LMS7Parameter COARSE_START = { 0x0121, 0, 0, 0, "COARSE_START", "" }; +const struct LMS7Parameter REVPH_PFD = { 0x0122, 12, 12, 0, "REVPH_PFD", "Reverse the pulses of PFD. It can be used to reverse the polarity of the PLL loop (positive feedback to negative feedback)" }; +const struct LMS7Parameter IOFFSET_CP = { 0x0122, 11, 6, 12, "IOFFSET_CP", "Scales the offset current of the charge pump, 0-->63. This current is used in Fran-N mode to create an offset in the CP response and avoid the non-linear section" }; +const struct LMS7Parameter IPULSE_CP = { 0x0122, 5, 0, 63, "IPULSE_CP", "Scales the pulse current of the charge pump" }; +const struct LMS7Parameter COARSE_STEPDONE = { 0x0123, 15, 15, 0, "COARSE_STEPDONE", "" }; +const struct LMS7Parameter COARSEPLL_COMPO = { 0x0123, 14, 14, 0, "COARSEPLL_COMPO", "" }; +const struct LMS7Parameter VCO_CMPHO = { 0x0123, 13, 13, 0, "VCO_CMPHO", "" }; +const struct LMS7Parameter VCO_CMPLO = { 0x0123, 12, 12, 0, "VCO_CMPLO", "" }; +const struct LMS7Parameter CP2_PLL = { 0x0123, 11, 8, 6, "CP2_PLL", "Controls the value of CP2 (cap from CP output to GND) in the PLL filter" }; +const struct LMS7Parameter CP3_PLL = { 0x0123, 7, 4, 7, "CP3_PLL", "Controls the value of CP3 (cap from VCO Vtune input to GND) in the PLL filter" }; +const struct LMS7Parameter CZ = { 0x0123, 3, 0, 11, "CZ", "Controls the value of CZ (Zero capacitor) in the PLL filter" }; +const struct LMS7Parameter EN_DIR_SXRSXT = { 0x0124, 4, 4, 0, "EN_DIR_SXRSXT", "Enables direct control of PDs and ENs for SXR/SXT module" }; +const struct LMS7Parameter EN_DIR_RBB = { 0x0124, 3, 3, 0, "EN_DIR_RBB", "Enables direct control of PDs and ENs for RBB module" }; +const struct LMS7Parameter EN_DIR_RFE = { 0x0124, 2, 2, 0, "EN_DIR_RFE", "Enables direct control of PDs and ENs for RFE module" }; +const struct LMS7Parameter EN_DIR_TBB = { 0x0124, 1, 1, 0, "EN_DIR_TBB", "Enables direct control of PDs and ENs for TBB module" }; +const struct LMS7Parameter EN_DIR_TRF = { 0x0124, 0, 0, 0, "EN_DIR_TRF", "Enables direct control of PDs and ENs for TRF module" }; +const struct LMS7Parameter TSGFC_TXTSP = { 0x0200, 9, 9, 0, "TSGFC_TXTSP", "TSG full scale control" }; +const struct LMS7Parameter TSGFCW_TXTSP = { 0x0200, 8, 7, 1, "TSGFCW_TXTSP", "Set frequency of TSG's NCO" }; +const struct LMS7Parameter TSGDCLDQ_TXTSP = { 0x0200, 6, 6, 0, "TSGDCLDQ_TXTSP", "" }; +const struct LMS7Parameter TSGDCLDI_TXTSP = { 0x0200, 5, 5, 0, "TSGDCLDI_TXTSP", "" }; +const struct LMS7Parameter TSGSWAPIQ_TXTSP = { 0x0200, 4, 4, 0, "TSGSWAPIQ_TXTSP", "Swap signals at test signal generator's output" }; +const struct LMS7Parameter TSGMODE_TXTSP = { 0x0200, 3, 3, 0, "TSGMODE_TXTSP", "Test signal generator mode" }; +const struct LMS7Parameter INSEL_TXTSP = { 0x0200, 2, 2, 0, "INSEL_TXTSP", "Input source of TxTSP" }; +const struct LMS7Parameter BSTART_TXTSP = { 0x0200, 1, 1, 0, "BSTART_TXTSP", "Starts delta sigma built in self test. Keep it at 1 one at least three clock cycles" }; +const struct LMS7Parameter EN_TXTSP = { 0x0200, 0, 0, 1, "EN_TXTSP", "TxTSP modules enable" }; +const struct LMS7Parameter GCORRQ_TXTSP = { 0x0201, 10, 0, 2047, "GCORRQ_TXTSP", "corrector value, channel Q Unsigned integer" }; +const struct LMS7Parameter GCORRI_TXTSP = { 0x0202, 10, 0, 2047, "GCORRI_TXTSP", "corrector value, channel I Unsigned integer" }; +const struct LMS7Parameter HBI_OVR_TXTSP = { 0x0203, 14, 12, 0, "HBI_OVR_TXTSP", "HBI interpolation ratio" }; +const struct LMS7Parameter IQCORR_TXTSP = { 0x0203, 11, 0, 0, "IQCORR_TXTSP", "Phase corrector value (tan(Alpha/2)). Integer, 2's complement" }; +const struct LMS7Parameter DCCORRI_TXTSP = { 0x0204, 15, 8, 0, "DCCORRI_TXTSP", "DC corrector value, channel I. Integer, 2's complement" }; +const struct LMS7Parameter DCCORRQ_TXTSP = { 0x0204, 7, 0, 0, "DCCORRQ_TXTSP", "DC corrector value, channel Q. Integer, 2's complement" }; +const struct LMS7Parameter GFIR1_L_TXTSP = { 0x0205, 10, 8, 0, "GFIR1_L_TXTSP", "Parameter l of GFIR1 (l = roundUp(CoeffN/5)-1). Unsigned integer" }; +const struct LMS7Parameter GFIR1_N_TXTSP = { 0x0205, 7, 0, 0, "GFIR1_N_TXTSP", "Clock division ratio of GFIR1 is GFIR1_N + 1. Unsigned integer" }; +const struct LMS7Parameter GFIR2_L_TXTSP = { 0x0206, 10, 8, 0, "GFIR2_L_TXTSP", "Parameter l of GFIR2 (l = roundUp(CoeffN/5)-1). Unsigned integer" }; +const struct LMS7Parameter GFIR2_N_TXTSP = { 0x0206, 7, 0, 0, "GFIR2_N_TXTSP", "Clock division ratio of GFIR2 is GFIR2_N + 1. Unsigned integer" }; +const struct LMS7Parameter GFIR3_L_TXTSP = { 0x0207, 10, 8, 0, "GFIR3_L_TXTSP", "Parameter l of GFIR3 (l = roundUp(CoeffN/5)-1). Unsigned integer" }; +const struct LMS7Parameter GFIR3_N_TXTSP = { 0x0207, 7, 0, 0, "GFIR3_N_TXTSP", "Clock division ratio of GFIR3 is GFIR3_N + 1. Unsigned integer" }; +const struct LMS7Parameter CMIX_GAIN_TXTSP = { 0x0208, 15, 14, 0, "CMIX_GAIN_TXTSP", "Gain of CMIX output" }; +const struct LMS7Parameter CMIX_SC_TXTSP = { 0x0208, 13, 13, 0, "CMIX_SC_TXTSP", "Spectrum control of CMIX" }; +const struct LMS7Parameter CMIX_BYP_TXTSP = { 0x0208, 8, 8, 0, "CMIX_BYP_TXTSP", "CMIX bypass" }; +const struct LMS7Parameter ISINC_BYP_TXTSP = { 0x0208, 7, 7, 0, "ISINC_BYP_TXTSP", "ISINC bypass" }; +const struct LMS7Parameter GFIR3_BYP_TXTSP = { 0x0208, 6, 6, 0, "GFIR3_BYP_TXTSP", "GFIR3 bypass" }; +const struct LMS7Parameter GFIR2_BYP_TXTSP = { 0x0208, 5, 5, 0, "GFIR2_BYP_TXTSP", "GFIR2 bypass" }; +const struct LMS7Parameter GFIR1_BYP_TXTSP = { 0x0208, 4, 4, 0, "GFIR1_BYP_TXTSP", "GFIR1 bypass" }; +const struct LMS7Parameter DC_BYP_TXTSP = { 0x0208, 3, 3, 0, "DC_BYP_TXTSP", "DC corrector bypass" }; +const struct LMS7Parameter GC_BYP_TXTSP = { 0x0208, 1, 1, 0, "GC_BYP_TXTSP", "Gain corrector bypass" }; +const struct LMS7Parameter PH_BYP_TXTSP = { 0x0208, 0, 0, 0, "PH_BYP_TXTSP", "Phase corrector bypass" }; +const struct LMS7Parameter BSIGI_TXTSP = { 0x0209, 23, 1, 0, "BSIGI_TXTSP", "" }; +const struct LMS7Parameter BSTATE_TXTSP = { 0x0209, 0, 0, 0, "BSTATE_TXTSP", "" }; +const struct LMS7Parameter BSIGQ_TXTSP = { 0x020A, 30, 8, 0, "BSIGQ_TXTSP", "" }; +const struct LMS7Parameter DC_REG_TXTSP = { 0x020C, 15, 0, 0, "DC_REG_TXTSP", "" }; +const struct LMS7Parameter DTHBIT_TX = { 0x0240, 8, 5, 1, "DTHBIT_TX", "NCO bits to dither" }; +const struct LMS7Parameter SEL_TX = { 0x0240, 4, 1, 0, "SEL_TX", "" }; +const struct LMS7Parameter MODE_TX = { 0x0240, 0, 0, 0, "MODE_TX", "" }; +const struct LMS7Parameter CAPTURE = { 0x0400, 15, 15, 0, "CAPTURE", "" }; +const struct LMS7Parameter CAPSEL = { 0x0400, 14, 13, 0, "CAPSEL", "" }; +const struct LMS7Parameter CAPSEL_ADC = { 0x0400, 12, 12, 0, "CAPSEL_ADC", "" }; +const struct LMS7Parameter TSGFC_RXTSP = { 0x0400, 9, 9, 0, "TSGFC_RXTSP", "TSG full scale control" }; +const struct LMS7Parameter TSGFCW_RXTSP = { 0x0400, 8, 7, 1, "TSGFCW_RXTSP", "Set frequency of TSG's NCO" }; +const struct LMS7Parameter TSGDCLDQ_RXTSP = { 0x0400, 6, 6, 0, "TSGDCLDQ_RXTSP", "" }; +const struct LMS7Parameter TSGDCLDI_RXTSP = { 0x0400, 5, 5, 0, "TSGDCLDI_RXTSP", "" }; +const struct LMS7Parameter TSGSWAPIQ_RXTSP = { 0x0400, 4, 4, 0, "TSGSWAPIQ_RXTSP", "Swap signals at test signal generator's output" }; +const struct LMS7Parameter TSGMODE_RXTSP = { 0x0400, 3, 3, 0, "TSGMODE_RXTSP", "Test signal generator mode" }; +const struct LMS7Parameter INSEL_RXTSP = { 0x0400, 2, 2, 0, "INSEL_RXTSP", "Input source of RxTSP" }; +const struct LMS7Parameter BSTART_RXTSP = { 0x0400, 1, 1, 0, "BSTART_RXTSP", "Starts delta sigma built in self test. Keep it at 1 one at least three clock cycles" }; +const struct LMS7Parameter EN_RXTSP = { 0x0400, 0, 0, 1, "EN_RXTSP", "RxTSP modules enable" }; +const struct LMS7Parameter GCORRQ_RXTSP = { 0x0401, 10, 0, 2047, "GCORRQ_RXTSP", "corrector value, channel Q Unsigned integer" }; +const struct LMS7Parameter GCORRI_RXTSP = { 0x0402, 10, 0, 2047, "GCORRI_RXTSP", "corrector value, channel I Unsigned integer" }; +const struct LMS7Parameter HBD_OVR_RXTSP = { 0x0403, 14, 12, 0, "HBD_OVR_RXTSP", "HBD interpolation ratio. Interpolation ratio is 2HBD_OVR+1" }; +const struct LMS7Parameter IQCORR_RXTSP = { 0x0403, 11, 0, 0, "IQCORR_RXTSP", "Phase corrector value (tan(Alpha/2)). Integer, 2's complement" }; +const struct LMS7Parameter HBD_DLY = { 0x0404, 15, 13, 0, "HBD_DLY", "" }; +const struct LMS7Parameter DCLOOP_BYP = { 0x0404, 8, 8, 0, "DCLOOP_BYP", "" }; +const struct LMS7Parameter DCCORR_AVG_RXTSP = { 0x0404, 2, 0, 0, "DCCORR_AVG_RXTSP", "Number of samples to average for Automatic DC corrector. Number of samples to average is 2DCCORR_AVG + 12" }; +const struct LMS7Parameter GFIR1_L_RXTSP = { 0x0405, 10, 8, 0, "GFIR1_L_RXTSP", "Parameter l of GFIR1 (l = roundUp(CoeffN/5)-1). Unsigned integer" }; +const struct LMS7Parameter GFIR1_N_RXTSP = { 0x0405, 7, 0, 0, "GFIR1_N_RXTSP", "Clock division ratio of GFIR1 is GFIR1_N + 1. Unsigned integer" }; +const struct LMS7Parameter GFIR2_L_RXTSP = { 0x0406, 10, 8, 0, "GFIR2_L_RXTSP", "Parameter l of GFIR2 (l = roundUp(CoeffN/5)-1). Unsigned integer" }; +const struct LMS7Parameter GFIR2_N_RXTSP = { 0x0406, 7, 0, 0, "GFIR2_N_RXTSP", "Clock division ratio of GFIR2 is GFIR2_N + 1. Unsigned integer" }; +const struct LMS7Parameter GFIR3_L_RXTSP = { 0x0407, 10, 8, 0, "GFIR3_L_RXTSP", "Parameter l of GFIR3 (l = roundUp(CoeffN/5)-1). Unsigned integer" }; +const struct LMS7Parameter GFIR3_N_RXTSP = { 0x0407, 7, 0, 0, "GFIR3_N_RXTSP", "Clock division ratio of GFIR3 is GFIR3_N + 1. Unsigned integer" }; +const struct LMS7Parameter AGC_K_RXTSP = { 0x0408, 17, 0, 0, "AGC_K_RXTSP", "AGC loop gain" }; +const struct LMS7Parameter AGC_ADESIRED_RXTSP = { 0x0409, 15, 4, 0, "AGC_ADESIRED_RXTSP", "AGC_ADESIRED" }; +const struct LMS7Parameter RSSI_MODE = { 0x040A, 15, 14, 0, "RSSI_MODE", "" }; +const struct LMS7Parameter AGC_MODE_RXTSP = { 0x040A, 13, 12, 0, "AGC_MODE_RXTSP", "" }; +const struct LMS7Parameter AGC_AVG_RXTSP = { 0x040A, 2, 0, 0, "AGC_AVG_RXTSP", "AGC Averaging window size" }; +const struct LMS7Parameter DC_REG_RXTSP = { 0x040B, 15, 0, 0, "DC_REG_RXTSP", "" }; +const struct LMS7Parameter CMIX_GAIN_RXTSP = { 0x040C, 15, 14, 0, "CMIX_GAIN_RXTSP", "Gain of CMIX output" }; +const struct LMS7Parameter CMIX_SC_RXTSP = { 0x040C, 13, 13, 0, "CMIX_SC_RXTSP", "Spectrum control of CMIX" }; +const struct LMS7Parameter CMIX_BYP_RXTSP = { 0x040C, 7, 7, 0, "CMIX_BYP_RXTSP", "CMIX bypass" }; +const struct LMS7Parameter AGC_BYP_RXTSP = { 0x040C, 6, 6, 0, "AGC_BYP_RXTSP", "AGC bypass" }; +const struct LMS7Parameter GFIR3_BYP_RXTSP = { 0x040C, 5, 5, 0, "GFIR3_BYP_RXTSP", "GFIR3 bypass" }; +const struct LMS7Parameter GFIR2_BYP_RXTSP = { 0x040C, 4, 4, 0, "GFIR2_BYP_RXTSP", "GFIR2 bypass" }; +const struct LMS7Parameter GFIR1_BYP_RXTSP = { 0x040C, 3, 3, 0, "GFIR1_BYP_RXTSP", "GFIR1 bypass" }; +const struct LMS7Parameter DC_BYP_RXTSP = { 0x040C, 2, 2, 0, "DC_BYP_RXTSP", "DC corrector bypass" }; +const struct LMS7Parameter GC_BYP_RXTSP = { 0x040C, 1, 1, 0, "GC_BYP_RXTSP", "Gain corrector bypass" }; +const struct LMS7Parameter PH_BYP_RXTSP = { 0x040C, 0, 0, 0, "PH_BYP_RXTSP", "Phase corrector bypass" }; +const struct LMS7Parameter CAPD = { 0x040E, 31, 0, 0, "CAPD", "" }; +const struct LMS7Parameter DTHBIT_RX = { 0x0440, 8, 5, 1, "DTHBIT_RX", "NCO bits to dither" }; +const struct LMS7Parameter SEL_RX = { 0x0440, 4, 1, 0, "SEL_RX", "" }; +const struct LMS7Parameter MODE_RX = { 0x0440, 0, 0, 0, "MODE_RX", "" }; diff --git a/targets/ARCH/LMSSDR/USERSPACE/LIB/lms7002m/LMS7002M_parameters.h b/targets/ARCH/LMSSDR/USERSPACE/LIB/lms7002m/LMS7002M_parameters.h new file mode 100644 index 0000000000..3fc4e0be6b --- /dev/null +++ b/targets/ARCH/LMSSDR/USERSPACE/LIB/lms7002m/LMS7002M_parameters.h @@ -0,0 +1,613 @@ +/** +@file LMS7002M_parameters.h +@author Lime Microsystems (www.limemicro.com) +@brief List of LMS7002M transceiver control parameters +*/ + +#ifndef LMS7002M_PARAMETERS_H +#define LMS7002M_PARAMETERS_H + +#include "typedefs.h" +#include + +struct LMS7Parameter; +extern std::vector LMS7parameterList; + +struct LMS7Parameter +{ + LMS7Parameter() : address(0), msb(0), lsb(0), defaultValue(0), name(nullptr), tooltip(nullptr) + { + } + + LMS7Parameter(uint16_t address, uint8_t msb, uint8_t lsb, uint16_t defaultValue, const char *name, const char* tooltip) + : address(address), msb(msb), lsb(lsb), defaultValue(defaultValue), name(name), tooltip(tooltip) + { + LMS7parameterList.push_back(this); + } + + uint16_t address; + uint8_t msb; + uint8_t lsb; + uint16_t defaultValue; + const char* name; + const char* tooltip; + inline bool operator==(const LMS7Parameter& obj) + { + if (address == obj.address && msb == obj.msb && lsb == obj.lsb) + return true; + return false; + }; +}; + +extern const struct LMS7Parameter LRST_TX_B; +extern const struct LMS7Parameter MRST_TX_B; +extern const struct LMS7Parameter LRST_TX_A; +extern const struct LMS7Parameter MRST_TX_A; +extern const struct LMS7Parameter LRST_RX_B; +extern const struct LMS7Parameter MRST_RX_B; +extern const struct LMS7Parameter LRST_RX_A; +extern const struct LMS7Parameter MRST_RX_A; +extern const struct LMS7Parameter SRST_RXFIFO; +extern const struct LMS7Parameter SRST_TXFIFO; +extern const struct LMS7Parameter RXEN_B; +extern const struct LMS7Parameter RXEN_A; +extern const struct LMS7Parameter TXEN_B; +extern const struct LMS7Parameter TXEN_A; +extern const struct LMS7Parameter MAC; +extern const struct LMS7Parameter TX_CLK_PE; +extern const struct LMS7Parameter RX_CLK_PE; +extern const struct LMS7Parameter SDA_PE; +extern const struct LMS7Parameter SDA_DS; +extern const struct LMS7Parameter SCL_PE; +extern const struct LMS7Parameter SCL_DS; +extern const struct LMS7Parameter SDIO_DS; +extern const struct LMS7Parameter SDIO_PE; +extern const struct LMS7Parameter SDO_PE; +extern const struct LMS7Parameter SCLK_PE; +extern const struct LMS7Parameter SEN_PE; +extern const struct LMS7Parameter SPIMODE; +extern const struct LMS7Parameter DIQ2_DS; +extern const struct LMS7Parameter DIQ2_PE; +extern const struct LMS7Parameter IQ_SEL_EN_2_PE; +extern const struct LMS7Parameter TXNRX2_PE; +extern const struct LMS7Parameter FCLK2_PE; +extern const struct LMS7Parameter MCLK2_PE; +extern const struct LMS7Parameter DIQ1_DS; +extern const struct LMS7Parameter DIQ1_PE; +extern const struct LMS7Parameter IQ_SEL_EN_1_PE; +extern const struct LMS7Parameter TXNRX1_PE; +extern const struct LMS7Parameter FCLK1_PE; +extern const struct LMS7Parameter MCLK1_PE; +extern const struct LMS7Parameter DIQDIRCTR2; +extern const struct LMS7Parameter DIQDIR2; +extern const struct LMS7Parameter DIQDIRCTR1; +extern const struct LMS7Parameter DIQDIR1; +extern const struct LMS7Parameter ENABLEDIRCTR2; +extern const struct LMS7Parameter ENABLEDIR2; +extern const struct LMS7Parameter ENABLEDIRCTR1; +extern const struct LMS7Parameter ENABLEDIR1; +extern const struct LMS7Parameter MOD_EN; +extern const struct LMS7Parameter LML2_FIDM; +extern const struct LMS7Parameter LML2_TXNRXIQ; +extern const struct LMS7Parameter LML2_MODE; +extern const struct LMS7Parameter LML1_FIDM; +extern const struct LMS7Parameter LML1_TXNRXIQ; +extern const struct LMS7Parameter LML1_MODE; +extern const struct LMS7Parameter LML1_S3S; +extern const struct LMS7Parameter LML1_S2S; +extern const struct LMS7Parameter LML1_S1S; +extern const struct LMS7Parameter LML1_S0S; +extern const struct LMS7Parameter LML1_BQP; +extern const struct LMS7Parameter LML1_BIP; +extern const struct LMS7Parameter LML1_AQP; +extern const struct LMS7Parameter LML1_AIP; +extern const struct LMS7Parameter LML1_BB2RF_PST; +extern const struct LMS7Parameter LML1_BB2RF_PRE; +extern const struct LMS7Parameter LML1_RF2BB_PST; +extern const struct LMS7Parameter LML1_RF2BB_PRE; +extern const struct LMS7Parameter LML2_S3S; +extern const struct LMS7Parameter LML2_S2S; +extern const struct LMS7Parameter LML2_S1S; +extern const struct LMS7Parameter LML2_S0S; +extern const struct LMS7Parameter LML2_BQP; +extern const struct LMS7Parameter LML2_BIP; +extern const struct LMS7Parameter LML2_AQP; +extern const struct LMS7Parameter LML2_AIP; +extern const struct LMS7Parameter LML2_BB2RF_PST; +extern const struct LMS7Parameter LML2_BB2RF_PRE; +extern const struct LMS7Parameter LML2_RF2BB_PST; +extern const struct LMS7Parameter LML2_RF2BB_PRE; +extern const struct LMS7Parameter FCLK2_DLY; +extern const struct LMS7Parameter FCLK1_DLY; +extern const struct LMS7Parameter RX_MUX; +extern const struct LMS7Parameter TX_MUX; +extern const struct LMS7Parameter TXRDCLK_MUX; +extern const struct LMS7Parameter TXWRCLK_MUX; +extern const struct LMS7Parameter RXRDCLK_MUX; +extern const struct LMS7Parameter RXWRCLK_MUX; +extern const struct LMS7Parameter FCLK2_INV; +extern const struct LMS7Parameter FCLK1_INV; +extern const struct LMS7Parameter MCLK2DLY; +extern const struct LMS7Parameter MCLK1DLY; +extern const struct LMS7Parameter MCLK2SRC; +extern const struct LMS7Parameter MCLK1SRC; +extern const struct LMS7Parameter TXDIVEN; +extern const struct LMS7Parameter RXDIVEN; +extern const struct LMS7Parameter TXTSPCLKA_DIV; +extern const struct LMS7Parameter RXTSPCLKA_DIV; +extern const struct LMS7Parameter MIMO_SISO; +extern const struct LMS7Parameter VER; +extern const struct LMS7Parameter REV; +extern const struct LMS7Parameter MASK; +extern const struct LMS7Parameter EN_DIR_LDO; +extern const struct LMS7Parameter EN_DIR_CGEN; +extern const struct LMS7Parameter EN_DIR_XBUF; +extern const struct LMS7Parameter EN_DIR_AFE; +extern const struct LMS7Parameter ISEL_DAC_AFE; +extern const struct LMS7Parameter MODE_INTERLEAVE_AFE; +extern const struct LMS7Parameter MUX_AFE_1; +extern const struct LMS7Parameter MUX_AFE_2; +extern const struct LMS7Parameter PD_AFE; +extern const struct LMS7Parameter PD_RX_AFE1; +extern const struct LMS7Parameter PD_RX_AFE2; +extern const struct LMS7Parameter PD_TX_AFE1; +extern const struct LMS7Parameter PD_TX_AFE2; +extern const struct LMS7Parameter EN_G_AFE; +extern const struct LMS7Parameter MUX_BIAS_OUT; +extern const struct LMS7Parameter RP_CALIB_BIAS; +extern const struct LMS7Parameter PD_FRP_BIAS; +extern const struct LMS7Parameter PD_F_BIAS; +extern const struct LMS7Parameter PD_PTRP_BIAS; +extern const struct LMS7Parameter PD_PT_BIAS; +extern const struct LMS7Parameter PD_BIAS_MASTER; +extern const struct LMS7Parameter SLFB_XBUF_RX; +extern const struct LMS7Parameter SLFB_XBUF_TX; +extern const struct LMS7Parameter BYP_XBUF_RX; +extern const struct LMS7Parameter BYP_XBUF_TX; +extern const struct LMS7Parameter EN_OUT2_XBUF_TX; +extern const struct LMS7Parameter EN_TBUFIN_XBUF_RX; +extern const struct LMS7Parameter PD_XBUF_RX; +extern const struct LMS7Parameter PD_XBUF_TX; +extern const struct LMS7Parameter EN_G_XBUF; +extern const struct LMS7Parameter SPDUP_VCO_CGEN; +extern const struct LMS7Parameter RESET_N_CGEN; +extern const struct LMS7Parameter EN_ADCCLKH_CLKGN; +extern const struct LMS7Parameter EN_COARSE_CKLGEN; +extern const struct LMS7Parameter EN_INTONLY_SDM_CGEN; +extern const struct LMS7Parameter EN_SDM_CLK_CGEN; +extern const struct LMS7Parameter PD_CP_CGEN; +extern const struct LMS7Parameter PD_FDIV_FB_CGEN; +extern const struct LMS7Parameter PD_FDIV_O_CGEN; +extern const struct LMS7Parameter PD_SDM_CGEN; +extern const struct LMS7Parameter PD_VCO_CGEN; +extern const struct LMS7Parameter PD_VCO_COMP_CGEN; +extern const struct LMS7Parameter EN_G_CGEN; +extern const struct LMS7Parameter FRAC_SDM_CGEN_LSB; +extern const struct LMS7Parameter INT_SDM_CGEN; +extern const struct LMS7Parameter FRAC_SDM_CGEN_MSB; +extern const struct LMS7Parameter REV_SDMCLK_CGEN; +extern const struct LMS7Parameter SEL_SDMCLK_CGEN; +extern const struct LMS7Parameter SX_DITHER_EN_CGEN; +extern const struct LMS7Parameter CLKH_OV_CLKL_CGEN; +extern const struct LMS7Parameter DIV_OUTCH_CGEN; +extern const struct LMS7Parameter TST_CGEN; +extern const struct LMS7Parameter REV_CLKDAC_CGEN; +extern const struct LMS7Parameter CMPLO_CTRL_CGEN; +extern const struct LMS7Parameter REV_CLKADC_CGEN; +extern const struct LMS7Parameter REVPH_PFD_CGEN; +extern const struct LMS7Parameter IOFFSET_CP_CGEN; +extern const struct LMS7Parameter IPULSE_CP_CGEN; +extern const struct LMS7Parameter ICT_VCO_CGEN; +extern const struct LMS7Parameter CSW_VCO_CGEN; +extern const struct LMS7Parameter COARSE_START_CGEN; +extern const struct LMS7Parameter COARSE_STEPDONE_CGEN; +extern const struct LMS7Parameter COARSEPLL_COMPO_CGEN; +extern const struct LMS7Parameter VCO_CMPHO_CGEN; +extern const struct LMS7Parameter VCO_CMPLO_CGEN; +extern const struct LMS7Parameter CP2_CGEN; +extern const struct LMS7Parameter CP3_CGEN; +extern const struct LMS7Parameter CZ_CGEN; +extern const struct LMS7Parameter EN_LDO_DIG; +extern const struct LMS7Parameter EN_LDO_DIGGN; +extern const struct LMS7Parameter EN_LDO_DIGSXR; +extern const struct LMS7Parameter EN_LDO_DIGSXT; +extern const struct LMS7Parameter EN_LDO_DIVGN; +extern const struct LMS7Parameter EN_LDO_DIVSXR; +extern const struct LMS7Parameter EN_LDO_DIVSXT; +extern const struct LMS7Parameter EN_LDO_LNA12; +extern const struct LMS7Parameter EN_LDO_LNA14; +extern const struct LMS7Parameter EN_LDO_MXRFE; +extern const struct LMS7Parameter EN_LDO_RBB; +extern const struct LMS7Parameter EN_LDO_RXBUF; +extern const struct LMS7Parameter EN_LDO_TBB; +extern const struct LMS7Parameter EN_LDO_TIA12; +extern const struct LMS7Parameter EN_LDO_TIA14; +extern const struct LMS7Parameter EN_G_LDO; +extern const struct LMS7Parameter EN_LOADIMP_LDO_TLOB; +extern const struct LMS7Parameter EN_LOADIMP_LDO_TPAD; +extern const struct LMS7Parameter EN_LOADIMP_LDO_TXBUF; +extern const struct LMS7Parameter EN_LOADIMP_LDO_VCOGN; +extern const struct LMS7Parameter EN_LOADIMP_LDO_VCOSXR; +extern const struct LMS7Parameter EN_LOADIMP_LDO_VCOSXT; +extern const struct LMS7Parameter EN_LDO_AFE; +extern const struct LMS7Parameter EN_LDO_CPGN; +extern const struct LMS7Parameter EN_LDO_CPSXR; +extern const struct LMS7Parameter EN_LDO_TLOB; +extern const struct LMS7Parameter EN_LDO_TPAD; +extern const struct LMS7Parameter EN_LDO_TXBUF; +extern const struct LMS7Parameter EN_LDO_VCOGN; +extern const struct LMS7Parameter EN_LDO_VCOSXR; +extern const struct LMS7Parameter EN_LDO_VCOSXT; +extern const struct LMS7Parameter EN_LDO_CPSXT; +extern const struct LMS7Parameter EN_LOADIMP_LDO_CPSXT; +extern const struct LMS7Parameter EN_LOADIMP_LDO_DIG; +extern const struct LMS7Parameter EN_LOADIMP_LDO_DIGGN; +extern const struct LMS7Parameter EN_LOADIMP_LDO_DIGSXR; +extern const struct LMS7Parameter EN_LOADIMP_LDO_DIGSXT; +extern const struct LMS7Parameter EN_LOADIMP_LDO_DIVGN; +extern const struct LMS7Parameter EN_LOADIMP_LDO_DIVSXR; +extern const struct LMS7Parameter EN_LOADIMP_LDO_DIVSXT; +extern const struct LMS7Parameter EN_LOADIMP_LDO_LNA12; +extern const struct LMS7Parameter EN_LOADIMP_LDO_LNA14; +extern const struct LMS7Parameter EN_LOADIMP_LDO_MXRFE; +extern const struct LMS7Parameter EN_LOADIMP_LDO_RBB; +extern const struct LMS7Parameter EN_LOADIMP_LDO_RXBUF; +extern const struct LMS7Parameter EN_LOADIMP_LDO_TBB; +extern const struct LMS7Parameter EN_LOADIMP_LDO_TIA12; +extern const struct LMS7Parameter EN_LOADIMP_LDO_TIA14; +extern const struct LMS7Parameter BYP_LDO_TBB; +extern const struct LMS7Parameter BYP_LDO_TIA12; +extern const struct LMS7Parameter BYP_LDO_TIA14; +extern const struct LMS7Parameter BYP_LDO_TLOB; +extern const struct LMS7Parameter BYP_LDO_TPAD; +extern const struct LMS7Parameter BYP_LDO_TXBUF; +extern const struct LMS7Parameter BYP_LDO_VCOGN; +extern const struct LMS7Parameter BYP_LDO_VCOSXR; +extern const struct LMS7Parameter BYP_LDO_VCOSXT; +extern const struct LMS7Parameter EN_LOADIMP_LDO_AFE; +extern const struct LMS7Parameter EN_LOADIMP_LDO_CPGN; +extern const struct LMS7Parameter EN_LOADIMP_LDO_CPSXR; +extern const struct LMS7Parameter BYP_LDO_AFE; +extern const struct LMS7Parameter BYP_LDO_CPGN; +extern const struct LMS7Parameter BYP_LDO_CPSXR; +extern const struct LMS7Parameter BYP_LDO_CPSXT; +extern const struct LMS7Parameter BYP_LDO_DIG; +extern const struct LMS7Parameter BYP_LDO_DIGGN; +extern const struct LMS7Parameter BYP_LDO_DIGSXR; +extern const struct LMS7Parameter BYP_LDO_DIGSXT; +extern const struct LMS7Parameter BYP_LDO_DIVGN; +extern const struct LMS7Parameter BYP_LDO_DIVSXR; +extern const struct LMS7Parameter BYP_LDO_DIVSXT; +extern const struct LMS7Parameter BYP_LDO_LNA12; +extern const struct LMS7Parameter BYP_LDO_LNA14; +extern const struct LMS7Parameter BYP_LDO_MXRFE; +extern const struct LMS7Parameter BYP_LDO_RBB; +extern const struct LMS7Parameter BYP_LDO_RXBUF; +extern const struct LMS7Parameter SPDUP_LDO_DIVSXR; +extern const struct LMS7Parameter SPDUP_LDO_DIVSXT; +extern const struct LMS7Parameter SPDUP_LDO_LNA12; +extern const struct LMS7Parameter SPDUP_LDO_LNA14; +extern const struct LMS7Parameter SPDUP_LDO_MXRFE; +extern const struct LMS7Parameter SPDUP_LDO_RBB; +extern const struct LMS7Parameter SPDUP_LDO_RXBUF; +extern const struct LMS7Parameter SPDUP_LDO_TBB; +extern const struct LMS7Parameter SPDUP_LDO_TIA12; +extern const struct LMS7Parameter SPDUP_LDO_TIA14; +extern const struct LMS7Parameter SPDUP_LDO_TLOB; +extern const struct LMS7Parameter SPDUP_LDO_TPAD; +extern const struct LMS7Parameter SPDUP_LDO_TXBUF; +extern const struct LMS7Parameter SPDUP_LDO_VCOGN; +extern const struct LMS7Parameter SPDUP_LDO_VCOSXR; +extern const struct LMS7Parameter SPDUP_LDO_VCOSXT; +extern const struct LMS7Parameter SPDUP_LDO_AFE; +extern const struct LMS7Parameter SPDUP_LDO_CPGN; +extern const struct LMS7Parameter SPDUP_LDO_CPSXR; +extern const struct LMS7Parameter SPDUP_LDO_CPSXT; +extern const struct LMS7Parameter SPDUP_LDO_DIG; +extern const struct LMS7Parameter SPDUP_LDO_DIGGN; +extern const struct LMS7Parameter SPDUP_LDO_DIGSXR; +extern const struct LMS7Parameter SPDUP_LDO_DIGSXT; +extern const struct LMS7Parameter SPDUP_LDO_DIVGN; +extern const struct LMS7Parameter RDIV_VCOSXR; +extern const struct LMS7Parameter RDIV_VCOSXT; +extern const struct LMS7Parameter RDIV_TXBUF; +extern const struct LMS7Parameter RDIV_VCOGN; +extern const struct LMS7Parameter RDIV_TLOB; +extern const struct LMS7Parameter RDIV_TPAD; +extern const struct LMS7Parameter RDIV_TIA12; +extern const struct LMS7Parameter RDIV_TIA14; +extern const struct LMS7Parameter RDIV_RXBUF; +extern const struct LMS7Parameter RDIV_TBB; +extern const struct LMS7Parameter RDIV_MXRFE; +extern const struct LMS7Parameter RDIV_RBB; +extern const struct LMS7Parameter RDIV_LNA12; +extern const struct LMS7Parameter RDIV_LNA14; +extern const struct LMS7Parameter RDIV_DIVSXR; +extern const struct LMS7Parameter RDIV_DIVSXT; +extern const struct LMS7Parameter RDIV_DIGSXT; +extern const struct LMS7Parameter RDIV_DIVGN; +extern const struct LMS7Parameter RDIV_DIGGN; +extern const struct LMS7Parameter RDIV_DIGSXR; +extern const struct LMS7Parameter RDIV_CPSXT; +extern const struct LMS7Parameter RDIV_DIG; +extern const struct LMS7Parameter RDIV_CPGN; +extern const struct LMS7Parameter RDIV_CPSXR; +extern const struct LMS7Parameter RDIV_SPIBUF; +extern const struct LMS7Parameter RDIV_AFE; +extern const struct LMS7Parameter SPDUP_LDO_SPIBUF; +extern const struct LMS7Parameter SPDUP_LDO_DIGIp2; +extern const struct LMS7Parameter SPDUP_LDO_DIGIp1; +extern const struct LMS7Parameter BYP_LDO_SPIBUF; +extern const struct LMS7Parameter BYP_LDO_DIGIp2; +extern const struct LMS7Parameter BYP_LDO_DIGIp1; +extern const struct LMS7Parameter EN_LOADIMP_LDO_SPIBUF; +extern const struct LMS7Parameter EN_LOADIMP_LDO_DIGIp2; +extern const struct LMS7Parameter EN_LOADIMP_LDO_DIGIp1; +extern const struct LMS7Parameter PD_LDO_SPIBUF; +extern const struct LMS7Parameter PD_LDO_DIGIp2; +extern const struct LMS7Parameter PD_LDO_DIGIp1; +extern const struct LMS7Parameter EN_G_LDOP; +extern const struct LMS7Parameter RDIV_DIGIp2; +extern const struct LMS7Parameter RDIV_DIGIp1; +extern const struct LMS7Parameter BSIGT; +extern const struct LMS7Parameter BSTATE; +extern const struct LMS7Parameter EN_SDM_TSTO_SXT; +extern const struct LMS7Parameter EN_SDM_TSTO_SXR; +extern const struct LMS7Parameter EN_SDM_TSTO_CGEN; +extern const struct LMS7Parameter BENC; +extern const struct LMS7Parameter BENR; +extern const struct LMS7Parameter BENT; +extern const struct LMS7Parameter BSTART; +extern const struct LMS7Parameter BSIGR; +extern const struct LMS7Parameter BSIGC; +extern const struct LMS7Parameter CDS_MCLK2; +extern const struct LMS7Parameter CDS_MCLK1; +extern const struct LMS7Parameter CDSN_TXBTSP; +extern const struct LMS7Parameter CDSN_TXATSP; +extern const struct LMS7Parameter CDSN_RXBTSP; +extern const struct LMS7Parameter CDSN_RXATSP; +extern const struct LMS7Parameter CDSN_TXBLML; +extern const struct LMS7Parameter CDSN_TXALML; +extern const struct LMS7Parameter CDSN_RXBLML; +extern const struct LMS7Parameter CDSN_RXALML; +extern const struct LMS7Parameter CDSN_MCLK2; +extern const struct LMS7Parameter CDSN_MCLK1; +extern const struct LMS7Parameter CDS_TXBTSP; +extern const struct LMS7Parameter CDS_TXATSP; +extern const struct LMS7Parameter CDS_RXBTSP; +extern const struct LMS7Parameter CDS_RXATSP; +extern const struct LMS7Parameter CDS_TXBLML; +extern const struct LMS7Parameter CDS_TXALML; +extern const struct LMS7Parameter CDS_RXBLML; +extern const struct LMS7Parameter CDS_RXALML; +extern const struct LMS7Parameter EN_LOWBWLOMX_TMX_TRF; +extern const struct LMS7Parameter EN_NEXTTX_TRF; +extern const struct LMS7Parameter EN_AMPHF_PDET_TRF; +extern const struct LMS7Parameter LOADR_PDET_TRF; +extern const struct LMS7Parameter PD_PDET_TRF; +extern const struct LMS7Parameter PD_TLOBUF_TRF; +extern const struct LMS7Parameter PD_TXPAD_TRF; +extern const struct LMS7Parameter EN_G_TRF; +extern const struct LMS7Parameter F_TXPAD_TRF; +extern const struct LMS7Parameter L_LOOPB_TXPAD_TRF; +extern const struct LMS7Parameter LOSS_LIN_TXPAD_TRF; +extern const struct LMS7Parameter LOSS_MAIN_TXPAD_TRF; +extern const struct LMS7Parameter EN_LOOPB_TXPAD_TRF; +extern const struct LMS7Parameter GCAS_GNDREF_TXPAD_TRF; +extern const struct LMS7Parameter ICT_LIN_TXPAD_TRF; +extern const struct LMS7Parameter ICT_MAIN_TXPAD_TRF; +extern const struct LMS7Parameter VGCAS_TXPAD_TRF; +extern const struct LMS7Parameter SEL_BAND1_TRF; +extern const struct LMS7Parameter SEL_BAND2_TRF; +extern const struct LMS7Parameter LOBIASN_TXM_TRF; +extern const struct LMS7Parameter LOBIASP_TXX_TRF; +extern const struct LMS7Parameter CDC_I_TRF; +extern const struct LMS7Parameter CDC_Q_TRF; +extern const struct LMS7Parameter STATPULSE_TBB; +extern const struct LMS7Parameter LOOPB_TBB; +extern const struct LMS7Parameter PD_LPFH_TBB; +extern const struct LMS7Parameter PD_LPFIAMP_TBB; +extern const struct LMS7Parameter PD_LPFLAD_TBB; +extern const struct LMS7Parameter PD_LPFS5_TBB; +extern const struct LMS7Parameter EN_G_TBB; +extern const struct LMS7Parameter ICT_LPFS5_F_TBB; +extern const struct LMS7Parameter ICT_LPFS5_PT_TBB; +extern const struct LMS7Parameter ICT_LPF_H_PT_TBB; +extern const struct LMS7Parameter ICT_LPFH_F_TBB; +extern const struct LMS7Parameter ICT_LPFLAD_F_TBB; +extern const struct LMS7Parameter ICT_LPFLAD_PT_TBB; +extern const struct LMS7Parameter CG_IAMP_TBB; +extern const struct LMS7Parameter ICT_IAMP_FRP_TBB; +extern const struct LMS7Parameter ICT_IAMP_GG_FRP_TBB; +extern const struct LMS7Parameter RCAL_LPFH_TBB; +extern const struct LMS7Parameter RCAL_LPFLAD_TBB; +extern const struct LMS7Parameter TSTIN_TBB; +extern const struct LMS7Parameter BYPLADDER_TBB; +extern const struct LMS7Parameter CCAL_LPFLAD_TBB; +extern const struct LMS7Parameter RCAL_LPFS5_TBB; +extern const struct LMS7Parameter CDC_I_RFE; +extern const struct LMS7Parameter CDC_Q_RFE; +extern const struct LMS7Parameter PD_LNA_RFE; +extern const struct LMS7Parameter PD_RLOOPB_1_RFE; +extern const struct LMS7Parameter PD_RLOOPB_2_RFE; +extern const struct LMS7Parameter PD_MXLOBUF_RFE; +extern const struct LMS7Parameter PD_QGEN_RFE; +extern const struct LMS7Parameter PD_RSSI_RFE; +extern const struct LMS7Parameter PD_TIA_RFE; +extern const struct LMS7Parameter EN_G_RFE; +extern const struct LMS7Parameter SEL_PATH_RFE; +extern const struct LMS7Parameter EN_DCOFF_RXFE_RFE; +extern const struct LMS7Parameter EN_INSHSW_LB1_RFE; +extern const struct LMS7Parameter EN_INSHSW_LB2_RFE; +extern const struct LMS7Parameter EN_INSHSW_L_RFE; +extern const struct LMS7Parameter EN_INSHSW_W_RFE; +extern const struct LMS7Parameter EN_NEXTRX_RFE; +extern const struct LMS7Parameter DCOFFI_RFE; +extern const struct LMS7Parameter DCOFFQ_RFE; +extern const struct LMS7Parameter ICT_LOOPB_RFE; +extern const struct LMS7Parameter ICT_TIAMAIN_RFE; +extern const struct LMS7Parameter ICT_TIAOUT_RFE; +extern const struct LMS7Parameter ICT_LNACMO_RFE; +extern const struct LMS7Parameter ICT_LNA_RFE; +extern const struct LMS7Parameter ICT_LODC_RFE; +extern const struct LMS7Parameter CAP_RXMXO_RFE; +extern const struct LMS7Parameter CGSIN_LNA_RFE; +extern const struct LMS7Parameter CCOMP_TIA_RFE; +extern const struct LMS7Parameter CFB_TIA_RFE; +extern const struct LMS7Parameter G_LNA_RFE; +extern const struct LMS7Parameter G_RXLOOPB_RFE; +extern const struct LMS7Parameter G_TIA_RFE; +extern const struct LMS7Parameter RCOMP_TIA_RFE; +extern const struct LMS7Parameter RFB_TIA_RFE; +extern const struct LMS7Parameter EN_LB_LPFH_RBB; +extern const struct LMS7Parameter EN_LB_LPFL_RBB; +extern const struct LMS7Parameter PD_LPFH_RBB; +extern const struct LMS7Parameter PD_LPFL_RBB; +extern const struct LMS7Parameter PD_PGA_RBB; +extern const struct LMS7Parameter EN_G_RBB; +extern const struct LMS7Parameter R_CTL_LPF_RBB; +extern const struct LMS7Parameter RCC_CTL_LPFH_RBB; +extern const struct LMS7Parameter C_CTL_LPFH_RBB; +extern const struct LMS7Parameter RCC_CTL_LPFL_RBB; +extern const struct LMS7Parameter C_CTL_LPFL_RBB; +extern const struct LMS7Parameter INPUT_CTL_PGA_RBB; +extern const struct LMS7Parameter ICT_LPF_IN_RBB; +extern const struct LMS7Parameter ICT_LPF_OUT_RBB; +extern const struct LMS7Parameter OSW_PGA_RBB; +extern const struct LMS7Parameter ICT_PGA_OUT_RBB; +extern const struct LMS7Parameter ICT_PGA_IN_RBB; +extern const struct LMS7Parameter G_PGA_RBB; +extern const struct LMS7Parameter RCC_CTL_PGA_RBB; +extern const struct LMS7Parameter C_CTL_PGA_RBB; +extern const struct LMS7Parameter RESET_N; +extern const struct LMS7Parameter SPDUP_VCO; +extern const struct LMS7Parameter BYPLDO_VCO; +extern const struct LMS7Parameter EN_COARSEPLL; +extern const struct LMS7Parameter CURLIM_VCO; +extern const struct LMS7Parameter EN_DIV2_DIVPROG; +extern const struct LMS7Parameter EN_INTONLY_SDM; +extern const struct LMS7Parameter EN_SDM_CLK; +extern const struct LMS7Parameter PD_FBDIV; +extern const struct LMS7Parameter PD_LOCH_T2RBUF; +extern const struct LMS7Parameter PD_CP; +extern const struct LMS7Parameter PD_FDIV; +extern const struct LMS7Parameter PD_SDM; +extern const struct LMS7Parameter PD_VCO_COMP; +extern const struct LMS7Parameter PD_VCO; +extern const struct LMS7Parameter EN_G; +extern const struct LMS7Parameter FRAC_SDM_LSB; +extern const struct LMS7Parameter INT_SDM; +extern const struct LMS7Parameter FRAC_SDM_MSB; +extern const struct LMS7Parameter PW_DIV2_LOCH; +extern const struct LMS7Parameter PW_DIV4_LOCH; +extern const struct LMS7Parameter DIV_LOCH; +extern const struct LMS7Parameter TST_SX; +extern const struct LMS7Parameter SEL_SDMCLK; +extern const struct LMS7Parameter SX_DITHER_EN; +extern const struct LMS7Parameter REV_SDMCLK; +extern const struct LMS7Parameter VDIV_VCO; +extern const struct LMS7Parameter ICT_VCO; +extern const struct LMS7Parameter RSEL_LDO_VCO; +extern const struct LMS7Parameter CSW_VCO; +extern const struct LMS7Parameter SEL_VCO; +extern const struct LMS7Parameter COARSE_START; +extern const struct LMS7Parameter REVPH_PFD; +extern const struct LMS7Parameter IOFFSET_CP; +extern const struct LMS7Parameter IPULSE_CP; +extern const struct LMS7Parameter COARSE_STEPDONE; +extern const struct LMS7Parameter COARSEPLL_COMPO; +extern const struct LMS7Parameter VCO_CMPHO; +extern const struct LMS7Parameter VCO_CMPLO; +extern const struct LMS7Parameter CP2_PLL; +extern const struct LMS7Parameter CP3_PLL; +extern const struct LMS7Parameter CZ; +extern const struct LMS7Parameter EN_DIR_SXRSXT; +extern const struct LMS7Parameter EN_DIR_RBB; +extern const struct LMS7Parameter EN_DIR_RFE; +extern const struct LMS7Parameter EN_DIR_TBB; +extern const struct LMS7Parameter EN_DIR_TRF; +extern const struct LMS7Parameter TSGFC_TXTSP; +extern const struct LMS7Parameter TSGFCW_TXTSP; +extern const struct LMS7Parameter TSGDCLDQ_TXTSP; +extern const struct LMS7Parameter TSGDCLDI_TXTSP; +extern const struct LMS7Parameter TSGSWAPIQ_TXTSP; +extern const struct LMS7Parameter TSGMODE_TXTSP; +extern const struct LMS7Parameter INSEL_TXTSP; +extern const struct LMS7Parameter BSTART_TXTSP; +extern const struct LMS7Parameter EN_TXTSP; +extern const struct LMS7Parameter GCORRQ_TXTSP; +extern const struct LMS7Parameter GCORRI_TXTSP; +extern const struct LMS7Parameter HBI_OVR_TXTSP; +extern const struct LMS7Parameter IQCORR_TXTSP; +extern const struct LMS7Parameter DCCORRI_TXTSP; +extern const struct LMS7Parameter DCCORRQ_TXTSP; +extern const struct LMS7Parameter GFIR1_L_TXTSP; +extern const struct LMS7Parameter GFIR1_N_TXTSP; +extern const struct LMS7Parameter GFIR2_L_TXTSP; +extern const struct LMS7Parameter GFIR2_N_TXTSP; +extern const struct LMS7Parameter GFIR3_L_TXTSP; +extern const struct LMS7Parameter GFIR3_N_TXTSP; +extern const struct LMS7Parameter CMIX_GAIN_TXTSP; +extern const struct LMS7Parameter CMIX_SC_TXTSP; +extern const struct LMS7Parameter CMIX_BYP_TXTSP; +extern const struct LMS7Parameter ISINC_BYP_TXTSP; +extern const struct LMS7Parameter GFIR3_BYP_TXTSP; +extern const struct LMS7Parameter GFIR2_BYP_TXTSP; +extern const struct LMS7Parameter GFIR1_BYP_TXTSP; +extern const struct LMS7Parameter DC_BYP_TXTSP; +extern const struct LMS7Parameter GC_BYP_TXTSP; +extern const struct LMS7Parameter PH_BYP_TXTSP; +extern const struct LMS7Parameter BSIGI_TXTSP; +extern const struct LMS7Parameter BSTATE_TXTSP; +extern const struct LMS7Parameter BSIGQ_TXTSP; +extern const struct LMS7Parameter DC_REG_TXTSP; +extern const struct LMS7Parameter DTHBIT_TX; +extern const struct LMS7Parameter SEL_TX; +extern const struct LMS7Parameter MODE_TX; +extern const struct LMS7Parameter CAPTURE; +extern const struct LMS7Parameter CAPSEL; +extern const struct LMS7Parameter CAPSEL_ADC; +extern const struct LMS7Parameter TSGFC_RXTSP; +extern const struct LMS7Parameter TSGFCW_RXTSP; +extern const struct LMS7Parameter TSGDCLDQ_RXTSP; +extern const struct LMS7Parameter TSGDCLDI_RXTSP; +extern const struct LMS7Parameter TSGSWAPIQ_RXTSP; +extern const struct LMS7Parameter TSGMODE_RXTSP; +extern const struct LMS7Parameter INSEL_RXTSP; +extern const struct LMS7Parameter BSTART_RXTSP; +extern const struct LMS7Parameter EN_RXTSP; +extern const struct LMS7Parameter GCORRQ_RXTSP; +extern const struct LMS7Parameter GCORRI_RXTSP; +extern const struct LMS7Parameter HBD_OVR_RXTSP; +extern const struct LMS7Parameter IQCORR_RXTSP; +extern const struct LMS7Parameter HBD_DLY; +extern const struct LMS7Parameter DCLOOP_BYP; +extern const struct LMS7Parameter DCCORR_AVG_RXTSP; +extern const struct LMS7Parameter GFIR1_L_RXTSP; +extern const struct LMS7Parameter GFIR1_N_RXTSP; +extern const struct LMS7Parameter GFIR2_L_RXTSP; +extern const struct LMS7Parameter GFIR2_N_RXTSP; +extern const struct LMS7Parameter GFIR3_L_RXTSP; +extern const struct LMS7Parameter GFIR3_N_RXTSP; +extern const struct LMS7Parameter AGC_K_RXTSP; +extern const struct LMS7Parameter AGC_ADESIRED_RXTSP; +extern const struct LMS7Parameter RSSI_MODE; +extern const struct LMS7Parameter AGC_MODE_RXTSP; +extern const struct LMS7Parameter AGC_AVG_RXTSP; +extern const struct LMS7Parameter DC_REG_RXTSP; +extern const struct LMS7Parameter CMIX_GAIN_RXTSP; +extern const struct LMS7Parameter CMIX_SC_RXTSP; +extern const struct LMS7Parameter CMIX_BYP_RXTSP; +extern const struct LMS7Parameter AGC_BYP_RXTSP; +extern const struct LMS7Parameter GFIR3_BYP_RXTSP; +extern const struct LMS7Parameter GFIR2_BYP_RXTSP; +extern const struct LMS7Parameter GFIR1_BYP_RXTSP; +extern const struct LMS7Parameter DC_BYP_RXTSP; +extern const struct LMS7Parameter GC_BYP_RXTSP; +extern const struct LMS7Parameter PH_BYP_RXTSP; +extern const struct LMS7Parameter CAPD; +extern const struct LMS7Parameter DTHBIT_RX; +extern const struct LMS7Parameter SEL_RX; +extern const struct LMS7Parameter MODE_RX; + +#endif diff --git a/targets/ARCH/LMSSDR/USERSPACE/LIB/lms7002m/LMS7002M_statuses.cpp b/targets/ARCH/LMSSDR/USERSPACE/LIB/lms7002m/LMS7002M_statuses.cpp new file mode 100644 index 0000000000..4e00854e14 --- /dev/null +++ b/targets/ARCH/LMSSDR/USERSPACE/LIB/lms7002m/LMS7002M_statuses.cpp @@ -0,0 +1,16 @@ +/** +@file LMS7002M_statuses.cpp +@author Lime Microsystems (www.limemicro.com) +*/ + +#include "LMS7002M_statuses.h" + +const char* undefinedStatusStr = "undefined status"; + +const char* liblms7_status2string(liblms7_status status) +{ + if (status >= 0 && status < LIBLMS7_STATUS_COUNT) + return liblms7_status_strings[status]; + else + return undefinedStatusStr; +} diff --git a/targets/ARCH/LMSSDR/USERSPACE/LIB/lms7002m/LMS7002M_statuses.h b/targets/ARCH/LMSSDR/USERSPACE/LIB/lms7002m/LMS7002M_statuses.h new file mode 100644 index 0000000000..43b736bfd5 --- /dev/null +++ b/targets/ARCH/LMSSDR/USERSPACE/LIB/lms7002m/LMS7002M_statuses.h @@ -0,0 +1,48 @@ +/** +@file LMS7002M_statuses.h +@author Lime Microsystems (www.limemicro.com) +@brief LMS7002M control library statuses enumerations +*/ + +#ifndef LMS7API_STATUSES_H +#define LMS7API_STATUSES_H + +const char liblms7_status_strings[][64] = +{ +"success", +"failure", +"index out of range", +"too many values", +"connection manager is NULL", +"port not connected", +"frequency out of range", +"cannot deliver frequency", +"VCO is powered down", +"Bad SEL_PATH_RFE", +"Band not selected", +"file not found", +"file invalid format", +}; + +enum liblms7_status +{ + LIBLMS7_SUCCESS = 0, + LIBLMS7_FAILURE, + LIBLMS7_INDEX_OUT_OF_RANGE, + LIBLMS7_TOO_MANY_VALUES, + LIBLMS7_NO_CONNECTION_MANAGER, + LIBLMS7_NOT_CONNECTED, + LIBLMS7_FREQUENCY_OUT_OF_RANGE, + LIBLMS7_CANNOT_DELIVER_FREQUENCY, + LIBLMS7_VCO_IS_POWERED_DOWN, + LIBLMS7_BAD_SEL_PATH, + LIBLMS7_BAND_NOT_SELECTED, + LIBLMS7_FILE_NOT_FOUND, + LIBLMS7_FILE_INVALID_FORMAT, + + LIBLMS7_STATUS_COUNT +}; + +const char* liblms7_status2string(liblms7_status status); + +#endif diff --git a/targets/ARCH/LMSSDR/USERSPACE/LIB/lms7002m/connectionManager/ConnectionCOM.cpp b/targets/ARCH/LMSSDR/USERSPACE/LIB/lms7002m/connectionManager/ConnectionCOM.cpp new file mode 100644 index 0000000000..6c7fc0d829 --- /dev/null +++ b/targets/ARCH/LMSSDR/USERSPACE/LIB/lms7002m/connectionManager/ConnectionCOM.cpp @@ -0,0 +1,596 @@ +/** + @file ConnectionCOM.cpp + @author Lime Microsystems (www.limemicro.com) + @brief Implementation of communications through COM port +*/ + +#include "ConnectionCOM.h" + +#include "string.h" +#ifdef __unix__ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#endif // LINUX + +const int COM_RETRY_INTERVAL = 20; //ms +const int COM_TOTAL_TIMEOUT = 300; //ms + +/** @brief Initializes com port connection +*/ +ConnectionCOM::ConnectionCOM() +{ + currentDeviceIndex = -1; + connected = false; + comPortList.clear(); + m_deviceNames.clear(); + m_connectionType = COM_PORT; +#ifndef __unix__ + hComm = INVALID_HANDLE_VALUE; +#else + hComm = -1; +#endif + comBaudrate = 9600; +} + +/** @brief When object is destroyed it closes it's opened COM port +*/ +ConnectionCOM::~ConnectionCOM() +{ + Close(); +} + +/** @brief Opens connection to first found chip + @return 0-success +*/ +IConnection::DeviceStatus ConnectionCOM::Open() +{ + comPortList.clear(); + if(comPortList.size() == 0) + FindAllComPorts(); + + m_deviceNames.clear(); + if(m_deviceNames.size() == 0) + RefreshDeviceList(); + + for(unsigned int i=0; i 0 ) + { + comPortName = m_deviceNames[toOpen]; + IConnection::DeviceStatus status = Open(comPortName.c_str(), comBaudrate); + if( status == SUCCESS ) + currentDeviceIndex = toOpen; + return status; + } + return FAILURE; +} + +/** @brief Closes connection to chip +*/ +void ConnectionCOM::Close() +{ + connected = false; + currentDeviceIndex = -1; +#ifndef __unix__ + if (hComm != INVALID_HANDLE_VALUE) + { + SetCommTimeouts(hComm, &m_ctmoOld); + CloseHandle(hComm); + } + hComm = INVALID_HANDLE_VALUE; +#else + if( hComm >= 0) + { + close(hComm); + } + hComm = -1; +#endif +} + +/** @brief Returns whether chip is connected + @return chip is connected +*/ +bool ConnectionCOM::IsOpen() +{ +#ifndef __unix__ + if (hComm != INVALID_HANDLE_VALUE && TestConnectivity() ) + return true; +#else + if( hComm != -1 && TestConnectivity() ) + return true; +#endif + return false; +} + +int ConnectionCOM::GetOpenedIndex() +{ + return currentDeviceIndex; +} + +/** @brief Sends data through COM port + @param buffer data buffer to send + @param length size of data buffer + @param timeout_ms timeout limit for operation in milliseconds + @return Number of bytes sent +*/ +int ConnectionCOM::Write(const unsigned char *buffer, int length, int timeout_ms) +{ + if(timeout_ms == 0) + { + timeout_ms = COM_TOTAL_TIMEOUT; + } + int retryCount = 0; + const int maxRetries = (timeout_ms/COM_RETRY_INTERVAL) > 1 ? (timeout_ms/COM_RETRY_INTERVAL) : 1; + bool status = false; +#ifndef __unix__ + unsigned long bytesWriten = 0; + m_osWOverlap.InternalHigh = 0; + + for(int i = 0; iwrite("COM PORT: error writing data\n", LOG_ERROR); +// if(bytesWriten == 0) +// MessageLog::getInstance()->write("COM PORT: data bytes sent 0\n", LOG_WARNING); + status = false; + } + else + status = true; + ++retryCount; + } +#endif + if(bytesWriten == length) + status = true; + + return bytesWriten; +} + +/** @brief Reads data from COM port + @param buffer pointer to data buffer for receiving + @param length number of bytes to read + @param timeout_ms timeout limit for operation in milliseconds + @return Number of bytes received +*/ +int ConnectionCOM::Read(unsigned char *buffer, int length, int timeout_ms) +{ + if(timeout_ms == 0) + { + timeout_ms = COM_TOTAL_TIMEOUT; + } + int retryCount = 0; + const int maxRetries = (timeout_ms/COM_RETRY_INTERVAL) > 1 ? (timeout_ms/COM_RETRY_INTERVAL) : 1; + bool status = false; + + memset(buffer, 0, length); + long bytesReaded = 0; + unsigned long totalBytesReaded = 0; + char cRawData[COM_BUFFER_LENGTH]; + unsigned long bytesToRead = length; + + memset(cRawData, '\0', sizeof(cRawData[0])*COM_BUFFER_LENGTH); + + for(int i=0; iwrite("COM PORT: error reading data\n", LOG_ERROR); +// if(bytesReaded == 0) +// MessageLog::getInstance()->write("COM PORT: reading 0 bytes\n", LOG_WARNING); + status = false; + } +#endif + retryCount++; + + for(int j=0; jwrite(ss.str(), LOG_DATA); + +// if(retryCount == maxRetries) +// MessageLog::getInstance()->write("COM PORT: read data timeout\n", LOG_WARNING); +// +// if(totalBytesReaded > length) +// MessageLog::getInstance()->write("COM PORT: read data corrupted, received length > requested length\n", LOG_ERROR); + return totalBytesReaded; +} + +/** @brief Searches for available COM ports and adds them to list +*/ +void ConnectionCOM::FindAllComPorts() +{ + Close(); + comPortList.clear(); +#ifndef __unix__ + HKEY hSERIALCOMM; + if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("HARDWARE\\DEVICEMAP\\SERIALCOMM"), 0, KEY_QUERY_VALUE, &hSERIALCOMM) == ERROR_SUCCESS) + { + // Get the max value name and max value lengths + DWORD dwMaxValueNameLen; + DWORD dwMaxValueLen; + DWORD dwQueryInfo = RegQueryInfoKey(hSERIALCOMM, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &dwMaxValueNameLen, &dwMaxValueLen, NULL, NULL); + if (dwQueryInfo == ERROR_SUCCESS) + { + DWORD dwMaxValueNameSizeInChars = dwMaxValueNameLen + 1; + // Include space for the NULL terminator + DWORD dwMaxValueNameSizeInBytes = dwMaxValueNameSizeInChars*sizeof(TCHAR); + DWORD dwMaxValueDataSizeInChars = dwMaxValueLen / sizeof(TCHAR) + 1; + // Include space for the NULL terminator + DWORD dwMaxValueDataSizeInBytes = dwMaxValueDataSizeInChars*sizeof(TCHAR); + + // Allocate some space for the value name and value data + TCHAR* szValueName = new TCHAR[dwMaxValueNameSizeInChars]; + TCHAR* byValue = new TCHAR[dwMaxValueDataSizeInBytes]; + if (szValueName && byValue) + { + // Enumerate all the values underneath HKEY_LOCAL_MACHINE\HARDWARE\DEVICEMAP\SERIALCOMM + DWORD dwIndex = 0; + DWORD dwType; + DWORD dwValueNameSize = dwMaxValueNameSizeInChars; + DWORD dwDataSize = dwMaxValueDataSizeInBytes; + memset(szValueName, 0, dwMaxValueNameSizeInBytes); + memset(byValue, 0, dwMaxValueDataSizeInBytes); + LONG nEnum = RegEnumValue(hSERIALCOMM, dwIndex, szValueName, &dwValueNameSize, NULL, &dwType, (LPBYTE)byValue, &dwDataSize); + while (nEnum == ERROR_SUCCESS) + { + // If the value is of the correct type, then add it to the array + if (dwType == REG_SZ) + { + char portname[512]; + TCHAR* szPort = byValue; + int nUserNameLenUnicode = lstrlen( szPort ); // Convert all UNICODE characters + int nUserNameLen = WideCharToMultiByte( CP_ACP, // ANSI Code Page + 0, // No special handling of unmapped chars + (LPCWSTR)szPort, // wide-character string to be converted + nUserNameLenUnicode, + NULL, 0, // No output buffer since we are calculating length + NULL, NULL ); // Unrepresented char replacement - Use Default + TCHAR* pszUserName = new TCHAR[ nUserNameLen ]; // nUserNameLen includes the NULL character + WideCharToMultiByte( CP_ACP, // ANSI Code Page + 0, // No special handling of unmapped chars + (LPCWSTR)szPort, // wide-character string to be converted + nUserNameLenUnicode, + portname, + nUserNameLen, + NULL, NULL ); // Unrepresented char replacement - Use Default + portname[nUserNameLen] = 0; +#ifdef UNICODE + comPortList.push_back(portname); +#else + comPortList.push_back(szPort); +#endif + } + // Prepare for the next time around + dwValueNameSize = dwMaxValueNameSizeInChars; + dwDataSize = dwMaxValueDataSizeInBytes; + memset(szValueName, 0, dwMaxValueNameSizeInBytes); + memset(byValue, 0, dwMaxValueDataSizeInBytes); + ++dwIndex; + nEnum = RegEnumValue(hSERIALCOMM, dwIndex, szValueName, &dwValueNameSize, NULL, &dwType, (LPBYTE)byValue, &dwDataSize); + } + } + delete szValueName; + delete byValue; + } + // Close the registry key now that we are finished with it + RegCloseKey(hSERIALCOMM); + + if (dwQueryInfo != ERROR_SUCCESS) + SetLastError(dwQueryInfo); + } +#else + char tempBuffer[256]; + string result = ""; +#warning Currently searching only for ACM connections + system( "ls /dev | grep ttyACM > /tmp/foundSerialPorts.txt"); + + fstream fin; + fin.open("/tmp/foundSerialPorts.txt", ios::in); + while(!fin.eof()) + { + fin.getline(tempBuffer, 256); + result = "/dev/"; + result.append(tempBuffer); + if( strlen(tempBuffer) > 3 ) //longer than tty + comPortList.push_back(result); + } + fin.close(); +#endif +} + +/** @brief Opens COM port + @param comName COM port name + @param baudrate COM port baudrate + @return 0 on success +*/ +IConnection::DeviceStatus ConnectionCOM::Open(const char *comName, int baudrate) +{ + Close(); + if (strlen(comName) == 0) + return FAILURE; + + DeviceStatus errorCode = SUCCESS; + +#ifndef __unix__ + // Initialize Overlap structures + m_osROverlap.Internal = 0; + m_osROverlap.InternalHigh = 0; + m_osROverlap.Offset = 0; + m_osROverlap.OffsetHigh = 0; + m_osROverlap.hEvent = CreateEvent(NULL, false, false, NULL); + + m_osWOverlap.Internal = 0; + m_osWOverlap.InternalHigh = 0; + m_osWOverlap.Offset = 0; + m_osWOverlap.OffsetHigh = 0; + m_osWOverlap.hEvent = CreateEvent(NULL, false, false, NULL); + + // Initialize DSB structure + memset(&m_dcbCommPort, 0, sizeof(m_dcbCommPort)); + + m_dcbCommPort.BaudRate = comBaudrate; + m_dcbCommPort.fBinary = 1; + m_dcbCommPort.fParity = 0; + m_dcbCommPort.fOutxCtsFlow = 0; + m_dcbCommPort.fOutxDsrFlow = 0; + m_dcbCommPort.fDtrControl = 0; + m_dcbCommPort.fDsrSensitivity = 0; + m_dcbCommPort.fTXContinueOnXoff = 0; + m_dcbCommPort.fOutX = 0; + m_dcbCommPort.fInX = 0; + m_dcbCommPort.fErrorChar = 0; + m_dcbCommPort.fNull = 0; + m_dcbCommPort.fRtsControl = 0; + m_dcbCommPort.fAbortOnError = 0; + m_dcbCommPort.fDummy2 = 0; + // m_dcbCommPort.wReserved = 0; + m_dcbCommPort.XonLim = 512; + m_dcbCommPort.XoffLim = 512; + m_dcbCommPort.ByteSize = 8; + m_dcbCommPort.Parity = 0; + m_dcbCommPort.StopBits = 0; + //m_dcbCommPort.StopBits = 1; + m_dcbCommPort.XonChar = 17; + m_dcbCommPort.XoffChar = 19; + m_dcbCommPort.ErrorChar = 0; + m_dcbCommPort.EofChar = 26; + m_dcbCommPort.EvtChar = 0; + m_dcbCommPort.wReserved1 = 0; + m_dcbCommPort.DCBlength = sizeof(DCB); + + // Initialize Timeout's + m_ctmoNew.ReadIntervalTimeout = 50; + m_ctmoNew.ReadTotalTimeoutMultiplier = 0; + m_ctmoNew.ReadTotalTimeoutConstant = 100; // 1; + m_ctmoNew.WriteTotalTimeoutMultiplier = 0; + m_ctmoNew.WriteTotalTimeoutConstant = 100; + + // Open COM port + string stmp; + stmp = "\\\\.\\"; + stmp.append(comName); + hComm = CreateFileA(stmp.c_str(), GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); + + if (hComm != INVALID_HANDLE_VALUE) + { + // Set Events + if (!SetCommMask(hComm, 0)) + errorCode = FAILURE; + + // Set Timeouts + GetCommTimeouts(hComm, &m_ctmoOld); + if (!SetCommTimeouts(hComm, &m_ctmoNew)) + errorCode = FAILURE; + + // Set DCB + if (!SetCommState(hComm, &m_dcbCommPort)) + errorCode = FAILURE; + } + else + { + errorCode = FAILURE; + }; + + // Check the results + if (errorCode != 0) + { + //unsigned long err = GetLastError(); + CloseHandle(hComm); + hComm = INVALID_HANDLE_VALUE; + return errorCode; + } + else + { + PurgeComm(hComm, PURGE_TXCLEAR | PURGE_RXCLEAR); + return SUCCESS; + } +#else + hComm = open(comName, O_RDWR | O_NOCTTY | O_SYNC); + if(hComm < 0) + { +// printf("%s",strerror(errno)); +// MessageLog::getInstance()->write("Connection manager: failed opening COM port\n", LOG_ERROR); + return FAILURE; + } + + struct termios tty; + memset(&tty, 0, sizeof(tty)); + if( tcgetattr(hComm, &tty) != 0) + { +// MessageLog::getInstance()->write("Connection Manager: error from tcgetattr\n", LOG_ERROR); + return FAILURE; + } + int speed = B9600; + cfsetospeed(&tty, speed); + cfsetispeed(&tty, speed); + + tty.c_cflag = (tty.c_cflag & ~CSIZE) | CS8; + tty.c_iflag &= ~IGNBRK; + tty.c_lflag = 0; + tty.c_oflag = 0; + tty.c_cc[VMIN] = 0; // read non blocking + tty.c_cc[VTIME] = 5; // 0.5 seconds read timeout + + tty.c_iflag &= ~(IXON | IXOFF | IXANY); + tty.c_cflag |= (CLOCAL | CREAD); + + if(tcsetattr(hComm, TCSANOW, &tty) != 0) + { +// MessageLog::getInstance()->write("Connection manager: error from tcsetattr\n", LOG_ERROR); + return FAILURE; + } +#endif + return SUCCESS; +} + +/** @brief Checks if chip is connected to currently open port + @return chip is connected +*/ +bool ConnectionCOM::TestConnectivity() +{ +//currently set to always return true to show all com ports + return true; +#ifndef __unix__ + if (hComm != INVALID_HANDLE_VALUE) +#else + if( hComm >= 0) +#endif + { +// unsigned char out[64]; +// unsigned char in[64]; +// memset(in, 0, 64); +// out[0] = CMD_GET_INFO; +// SendData(out, 64); +// ReadData(in, 64); +// if(in[0] == CMD_GET_INFO && in[1] == 0x01) +// return true; +// else +// return false; + } + return false; +} + +/** @brief Finds all chips connected to com ports + @return number of devices found +*/ +int ConnectionCOM::RefreshDeviceList() +{ + int wasOpen = -1; + string wasOpenName = ""; + if(IsOpen()) + { + wasOpen = GetOpenedIndex(); + wasOpenName = comPortName; + } + Close(); + comPortList.clear(); + if(comPortList.size() == 0) + FindAllComPorts(); + + m_deviceNames.clear(); + string comName; + for(unsigned int i=0; i ConnectionCOM::GetDeviceNames() +{ + return m_deviceNames; +} + +/** @brief Purges communication buffers +*/ +void ConnectionCOM::ClearComm() +{ +#ifndef __unix__ + PurgeComm(hComm, PURGE_TXCLEAR|PURGE_RXCLEAR); +#endif +} diff --git a/targets/ARCH/LMSSDR/USERSPACE/LIB/lms7002m/connectionManager/ConnectionCOM.h b/targets/ARCH/LMSSDR/USERSPACE/LIB/lms7002m/connectionManager/ConnectionCOM.h new file mode 100644 index 0000000000..0549472db1 --- /dev/null +++ b/targets/ARCH/LMSSDR/USERSPACE/LIB/lms7002m/connectionManager/ConnectionCOM.h @@ -0,0 +1,62 @@ +/** +@file ConnectionCOM.h +@author Lime Microsystems (www.limemicro.com) +@brief Class for data communications through COM port +*/ + +#ifndef CONNECTION_COM_PORT_H +#define CONNECTION_COM_PORT_H + +#ifndef __unix__ + #include "windows.h" +#endif + +#include "IConnection.h" + +class ConnectionCOM : public IConnection +{ +public: + static const int COM_BUFFER_LENGTH = 1024; //max buffer size for data + + ConnectionCOM(); + ~ConnectionCOM(); + + DeviceStatus Open(); + DeviceStatus Open(unsigned i); + void Close(); + bool IsOpen(); + int GetOpenedIndex(); + + int Write(const unsigned char *buffer, int length, int timeout_ms = 0); + int Read(unsigned char *buffer, int length, int timeout_ms = 0); + + std::vector GetDeviceNames(); + int RefreshDeviceList(); + void ClearComm(); +private: + void FindAllComPorts(); + DeviceStatus Open(const char *comName, int baudrate); + + bool TestConnectivity(); + + std::string comPortName; + int comBaudrate; + bool connected; + + int currentDeviceIndex; + std::vector comPortList; + std::vector m_deviceNames; + +#ifndef __unix__ + HANDLE hComm; + COMMTIMEOUTS m_ctmoNew; + COMMTIMEOUTS m_ctmoOld; + OVERLAPPED m_osROverlap; + OVERLAPPED m_osWOverlap; + DCB m_dcbCommPort; +#else + int hComm; //com port file descriptor +#endif + +}; +#endif diff --git a/targets/ARCH/LMSSDR/USERSPACE/LIB/lms7002m/connectionManager/ConnectionManager.cpp b/targets/ARCH/LMSSDR/USERSPACE/LIB/lms7002m/connectionManager/ConnectionManager.cpp new file mode 100644 index 0000000000..36f73da5d7 --- /dev/null +++ b/targets/ARCH/LMSSDR/USERSPACE/LIB/lms7002m/connectionManager/ConnectionManager.cpp @@ -0,0 +1,314 @@ +/** + @file ConnectionManager.cpp + @author Lime Microsystems (www.limemicro.com) + @brief Implementation of various connection types to devices +*/ + +#include "ConnectionManager.h" +#include "ConnectionCOM.h" + +#ifdef ENABLE_USB_CONNECTION + #include "ConnectionUSB.h" +#endif +#ifdef ENABLE_SPI_CONNECTION + #include "ConnectionSPI.h" +#endif + +#include +#include +#include + +/** @brief Creates connection interfaces +*/ +ConnectionManager::ConnectionManager() : activeControlPort(NULL) +{ + mLogData = false; + mOpenedDevice = -1; + m_connections[IConnection::COM_PORT] = new ConnectionCOM(); +#ifdef ENABLE_USB_CONNECTION + m_connections[IConnection::USB_PORT] = new ConnectionUSB(); +#endif +#ifdef ENABLE_SPI_CONNECTION + m_connections[IConnection::SPI_PORT] = new ConnectionSPI(); +#endif +} + +/** @brief Destroys connection interfaces +*/ +ConnectionManager::~ConnectionManager() +{ + for (auto iter = m_connections.begin(); iter != m_connections.end(); ++iter) + { + delete iter->second; + } +} + +/** @brief Checks if connection to device is opened + @return True if device is connected +*/ +bool ConnectionManager::IsOpen() +{ + return activeControlPort ? activeControlPort->IsOpen() : false; +} + +/** @brief Opens connection to first available device + @return True if connected to device +*/ +bool ConnectionManager::Open() +{ + return Open(0); +} + +/** @brief Connects to selected device + @param i device index from device list + @return 1:Success, 0:failure +*/ +int ConnectionManager::Open(unsigned i) +{ + if(i >= mDevices.size()) + return 0; + + if(activeControlPort) + activeControlPort->Close(); + switch(mDevices[i].port) + { + case IConnection::COM_PORT: + activeControlPort = m_connections[IConnection::COM_PORT]; + break; + case IConnection::USB_PORT: + activeControlPort = m_connections[IConnection::USB_PORT]; + break; + case IConnection::SPI_PORT: + activeControlPort = m_connections[IConnection::SPI_PORT]; + break; + default: + return 0; + } + mOpenedDevice = -1; + if( i < mDevices.size() ) + { + if( activeControlPort->Open(mDevices[i].portIndex) ) + { + mOpenedDevice = i; + return 1; + } + } + return 0; +} + +/** @brief Closes connection to device +*/ +void ConnectionManager::Close() +{ + if(activeControlPort) + { + activeControlPort->Close(); + //Notify(LMS_Message(MSG_BOARD_DISCONNECTED, "", 0, 0)); + } + mOpenedDevice = -1; +} + +/** @brief Finds all currently connected devices and forms device list + @return number of devices found +*/ +int ConnectionManager::RefreshDeviceList() +{ + mDeviceList.clear(); + mDevices.clear(); + DeviceInfo dev; + for (auto iter = m_connections.begin(); iter != m_connections.end(); ++iter) + { + vector names; + IConnection *port = iter->second; + if(port->RefreshDeviceList() > 0) + { + names = port->GetDeviceNames(); + for(unsigned i=0; ifirst; + dev.portIndex = i; + mDevices.push_back(dev); + } + } + } + for(unsigned i=0; iWrite(buffer, length, timeout_ms); +#ifndef NDEBUG + if(mLogData) + { + stringstream ss; + ss << "WR(" << (bytesTransferred>=0?bytesTransferred: 0) << "): "; + ss << std::hex << std::setfill('0'); + int repeatedZeros = 0; + for(int i=length-1; i>=0; --i) + if(buffer[i] == 0) + ++repeatedZeros; + else break; + if(repeatedZeros == 1) + repeatedZeros = 0; + repeatedZeros = repeatedZeros - (repeatedZeros & 0x1); + for(int i=0; i 1) + ss << " (00 x " << std::dec << repeatedZeros << " times)"; + cout << ss.str() << endl; + } +#endif + return bytesTransferred; + } + return -1; +} + +/** @brief Receives data from currently opened connection + @param buffer incomming data buffer, must be big enough for length bytes + @param length bytes to read + @param timeout_ms timeout in milliseconds + @return number of bytes received +*/ +int ConnectionManager::Read(unsigned char *buffer, int length, int timeout_ms) +{ + if(activeControlPort) + { + int bytesTransferred = activeControlPort->Read(buffer, length, timeout_ms); +#ifndef NDEBUG + if(mLogData) + { + stringstream ss; + ss << "RD(" << (bytesTransferred>=0?bytesTransferred: 0) << "): "; + ss << std::hex << std::setfill('0'); + int repeatedZeros = 0; + for(int i=length-1; i>=0; --i) + if(buffer[i] == 0) + ++repeatedZeros; + else break; + if(repeatedZeros == 2) + repeatedZeros = 0; + repeatedZeros = repeatedZeros - (repeatedZeros & 0x1); + for(int i=0; i 2) + ss << " (00 x " << std::dec << repeatedZeros << " times)"; + cout << ss.str() << endl; + } +#endif + return bytesTransferred; + } + return -1; +} + +int ConnectionManager::WriteStream(const char *buffer, int length) +{ + return 0; +} + +int ConnectionManager::ReadStream(char *buffer, int length, unsigned int timeout_ms) +{ + /*int handle = activeControlPort->BeginDataReading(buffer, length); + activeControlPort->WaitForReading(handle, timeout_ms); + long received = length; + activeControlPort->FinishDataReading(buffer, received, handle); + return received; + */ + long len = length; + int status = activeControlPort->ReadDataBlocking(buffer, len, 0); + return len; +} + + +int ConnectionManager::BeginDataReading(char *buffer, long length) +{ + return activeControlPort->BeginDataReading(buffer, length); +} +/** +@brief Blocks until data is received or set number of milliseconds have passed. +@param contextHandle handle returned by BeginDataReading() +@param timeout_ms number of milliseconds to wait +@return 1-data received, 0-data not received +*/ +int ConnectionManager::WaitForReading(int contextHandle, unsigned int timeout_ms) +{ + return activeControlPort->WaitForReading(contextHandle, timeout_ms); +} +/** +@brief Finished asynchronous data reading. +@param buffer where to put received data +@param length number of bytes to read, will be changed to actual number of bytes received +@param contextHandle context handle returned by BeginDataReading() +@return received data length +*/ +int ConnectionManager::FinishDataReading(char *buffer, long &length, int contextHandle) +{ + return activeControlPort->FinishDataReading(buffer, length, contextHandle); +} + +/** +@brief Aborts reading operations +*/ +void ConnectionManager::AbortReading() +{ + activeControlPort->AbortReading(); +} + +/** +@brief Start asynchronous data sending. +@param buffer data buffer to be sent +@param length number of bytes to send. +@return context handle +*/ +int ConnectionManager::BeginDataSending(const char *buffer, long length) +{ + return activeControlPort->BeginDataSending(buffer, length); +} +/** +@brief Blocks until data is sent or set number of miliseconds have passed. +@param contextHandle handle returned by BeginDataReading() +@param timeout_ms number of miliseconds to wait +@return 1-data sent, 0-data not sent +*/ +int ConnectionManager::WaitForSending(int contextHandle, unsigned int timeout_ms) +{ + return activeControlPort->WaitForSending(contextHandle, timeout_ms); +} +/** +@brief Finished asynchronous data sending. +@param buffer where to put received data +@param length number of bytes to send, will be changed to actual number of bytes sent +@param contextHandle context handle returned by BeginDataReading() +@return sent data length +*/ +int ConnectionManager::FinishDataSending(const char *buffer, long &length, int contextHandle) +{ + return activeControlPort->FinishDataSending(buffer, length, contextHandle); +} + +/** +@brief Aborts sending operations +*/ +void ConnectionManager::AbortSending() +{ + activeControlPort->AbortSending(); +} diff --git a/targets/ARCH/LMSSDR/USERSPACE/LIB/lms7002m/connectionManager/ConnectionManager.h b/targets/ARCH/LMSSDR/USERSPACE/LIB/lms7002m/connectionManager/ConnectionManager.h new file mode 100644 index 0000000000..edd01d3833 --- /dev/null +++ b/targets/ARCH/LMSSDR/USERSPACE/LIB/lms7002m/connectionManager/ConnectionManager.h @@ -0,0 +1,60 @@ +/** + @file ConnectionManager.h + @author Lime Microsystems (www.limemicro.com) + @brief Class for managing connection to devices +*/ + +#ifndef LMS_CONNECTION_MANAGER_H +#define LMS_CONNECTION_MANAGER_H + +#include "IConnection.h" +#include + +class ConnectionManager +{ +public: + struct DeviceInfo + { + std::string name; + IConnection::eConnectionType port; + int portIndex; + }; + + ConnectionManager(); + ~ConnectionManager(); + bool IsOpen(); + bool Open(); + int Open(unsigned i); + void Close(); + int RefreshDeviceList(); + int GetOpenedIndex(); + std::vector GetDeviceList(){return mDeviceList;}; + + int Write(const unsigned char *buffer, int length, int timeout_ms = 0); + int Read(unsigned char *buffer, int length, int timeout_ms = 0); + + int WriteStream(const char *buffer, int length); + int ReadStream(char *buffer, int length, unsigned int timeout_ms); + + int BeginDataReading(char *buffer, long length); + int WaitForReading(int contextHandle, unsigned int timeout_ms); + int FinishDataReading(char *buffer, long &length, int contextHandle); + void AbortReading(); + + int BeginDataSending(const char *buffer, long length); + int WaitForSending(int contextHandle, unsigned int timeout_ms); + int FinishDataSending(const char *buffer, long &length, int contextHandle); + void AbortSending(); + +protected: + bool mLogData; + /// Port used for communication. + IConnection *activeControlPort; + std::vector mDevices; + std::vector mDeviceList; + int mOpenedDevice; + std::map m_connections; +}; + +#endif // LMS_CONNECTION_MANAGER_H + diff --git a/targets/ARCH/LMSSDR/USERSPACE/LIB/lms7002m/connectionManager/ConnectionSPI.cpp b/targets/ARCH/LMSSDR/USERSPACE/LIB/lms7002m/connectionManager/ConnectionSPI.cpp new file mode 100644 index 0000000000..e490db4dab --- /dev/null +++ b/targets/ARCH/LMSSDR/USERSPACE/LIB/lms7002m/connectionManager/ConnectionSPI.cpp @@ -0,0 +1,290 @@ +/** + @file ConnectionSPI.cpp + @author Lime Microsystems (www.limemicro.com) + @brief Implementation of communications through SPI port +*/ + +#include "ConnectionSPI.h" + +#include "string.h" +#ifdef __unix__ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#endif // LINUX + +#include +#include + +const int ConnectionSPI::cSPI_BUF_SIZE = 128; +const int ConnectionSPI::cSPI_SPEED_HZ = 2000000; + +/** @brief Tries to read EEPROM for Novena board signature + @return true if Novena board +*/ +bool IsNovenaBoard() +{ +#ifdef __unix__ + char data[8]; + int count = 6; + memset(data, 0, 8); + int addr = 0; + struct i2c_rdwr_ioctl_data session; + struct i2c_msg messages[2]; + char set_addr_buf[2]; + memset(set_addr_buf, 0, sizeof(set_addr_buf)); + memset(data, 0, count); + set_addr_buf[0] = addr>>8; + set_addr_buf[1] = addr; + messages[0].addr = 0xac>>1; + messages[0].flags = 0; + messages[0].len = sizeof(set_addr_buf); + messages[0].buf = set_addr_buf; + messages[1].addr = 0xac>>1; + messages[1].flags = I2C_M_RD; + messages[1].len = count; + messages[1].buf = data; + session.msgs = messages; + session.nmsgs = 2; + + bool isNovena = false; + + int fd = open("/dev/i2c-2", O_RDWR); + if(fd > 0) + { + if(ioctl(fd, I2C_RDWR, &session) < 0) + { + perror("Unable to communicate with i2c device"); + isNovena = false; + } + if(strcmp("Novena", data) == 0) + isNovena = true; + } + close(fd); + return isNovena; +#else + return false; +#endif +} + +/** @brief Initializes SPI port and exports needed GPIO +*/ +ConnectionSPI::ConnectionSPI() +{ + fd = -1; + m_connectionType = SPI_PORT; + std::fstream gpio; + //export SEN pin + gpio.open("/sys/class/gpio/export", ios::out); + if(gpio.good()) + { + gpio << 122; + gpio.flush(); + gpio.close(); + gpio.open("/sys/class/gpio/gpio122/direction", ios::out); + gpio << "out"; + gpio.flush(); + gpio.close(); + m_SEN.open("/sys/class/gpio/gpio122/value", ios::out); + m_SEN<< 1; + m_SEN.flush(); + cout << "GPIO122: set to 1" << endl; + } +} + +ConnectionSPI::~ConnectionSPI() +{ + Close(); + m_SEN.close(); +} + +/** @brief Opens connection to first found chip + @return 0-success +*/ +IConnection::DeviceStatus ConnectionSPI::Open() +{ + Close(); +#ifdef __unix__ + fd = open("/dev/spidev2.0", O_RDWR | O_SYNC); + if (fd < 0) + { + //MessageLog::getInstance()->write("SPI PORT: device not found\n", LOG_ERROR); + return IConnection::FAILURE; + } + int mode = SPI_MODE_0; + int ret = ioctl(fd, SPI_IOC_WR_MODE, &mode); + if (ret == -1) + printf("can't set spi mode"); + + ret = ioctl(fd, SPI_IOC_RD_MODE, &mode); + if (ret == -1) + printf("can't get spi mode"); + + /* + * bits per word + */ + int bits = 8; + ret = ioctl(fd, SPI_IOC_WR_BITS_PER_WORD, &bits); + if (ret == -1) + printf("can't set bits per word"); + + ret = ioctl(fd, SPI_IOC_RD_BITS_PER_WORD, &bits); + if (ret == -1) + printf("can't get bits per word"); + + /* + * max speed hz + */ + int speed = cSPI_SPEED_HZ; + ret = ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed); + if (ret == -1) + printf("can't set max speed hz"); + + ret = ioctl(fd, SPI_IOC_RD_MAX_SPEED_HZ, &speed); + if (ret == -1) + printf("can't get max speed hz"); + + printf("spi mode: 0x%x\n", mode); + printf("bits per word: %d\n", bits); + printf("max speed: %d Hz (%d KHz)\n", speed, speed/1000); + return IConnection::SUCCESS; +#else + return IConnection::FAILURE; +#endif +} + +/** @brief Opens connection to selected chip + @param index chip index in device list + @return 0-success +*/ +IConnection::DeviceStatus ConnectionSPI::Open(unsigned index) +{ + return Open(); +} + +/** @brief Closes connection to chip +*/ +void ConnectionSPI::Close() +{ +#ifdef __unix__ + close(fd); + fd = -1; +#endif +} + +/** @brief Returns whether chip is connected + @return chip is connected +*/ +bool ConnectionSPI::IsOpen() +{ + return (fd >= 0); +} + +/** @brief Sends data through SPI port + @param buffer data buffer to send + @param length size of data buffer + @param timeout_ms timeout limit for operation in milliseconds + @return Number of bytes sent +*/ +int ConnectionSPI::Write(const unsigned char *buffer, int length, int timeout_ms) +{ + #ifdef __unix__ + if(fd < 0) + return 0; + m_SEN << 0; + m_SEN.flush(); + unsigned long bytesWritten = 0; + rxbuf.clear(); + int bytesReceived = 0; + char rxbytes[2]; + while(bytesWritten < length) + { + int toWrite = length-bytesWritten > cSPI_BUF_SIZE ? cSPI_BUF_SIZE : length-bytesWritten; + for(int i=0; i rxbuf.size() ? rxbuf.size() : length; + memcpy(buffer, &rxbuf[0], tocpy); + rxbuf.clear(); + return tocpy; +#else + return 0; +#endif +} + +/** @brief Finds SPI port + @return number of devices found +*/ +int ConnectionSPI::RefreshDeviceList() +{ + m_deviceNames.clear(); +#ifdef __unix__ + int spidev = open("/dev/spidev2.0", O_RDWR); + if (spidev >= 0) + { + if(IsNovenaBoard() == true) + m_deviceNames.push_back("SPI (Novena)"); + else + m_deviceNames.push_back("SPI"); + } + close(spidev); +#endif + return m_deviceNames.size(); +} + +/** @brief Returns found devices names + @return vector of device names +*/ +vector ConnectionSPI::GetDeviceNames() +{ + return m_deviceNames; +} + +int ConnectionSPI::GetOpenedIndex() +{ + return 0; +} diff --git a/targets/ARCH/LMSSDR/USERSPACE/LIB/lms7002m/connectionManager/ConnectionSPI.h b/targets/ARCH/LMSSDR/USERSPACE/LIB/lms7002m/connectionManager/ConnectionSPI.h new file mode 100644 index 0000000000..79d9bd9b9b --- /dev/null +++ b/targets/ARCH/LMSSDR/USERSPACE/LIB/lms7002m/connectionManager/ConnectionSPI.h @@ -0,0 +1,41 @@ +/** +@file ConnectionSPI.h +@author Lime Microsystems (www.limemicro.com) +@brief Class for data communications through SPI port +*/ + +#ifndef CONNECTION_SPI_PORT_H +#define CONNECTION_SPI_PORT_H + +#include "IConnection.h" +#include +#include +#include + +class ConnectionSPI : public IConnection +{ +public: + static const int cSPI_BUF_SIZE; + static const int cSPI_SPEED_HZ; + + ConnectionSPI(); + ~ConnectionSPI(); + + DeviceStatus Open(); + DeviceStatus Open(unsigned i); + void Close(); + bool IsOpen(); + int GetOpenedIndex(); + + int Write(const unsigned char *buffer, int length, int timeout_ms = 0); + int Read(unsigned char *buffer, int length, int timeout_ms = 0); + + std::vector GetDeviceNames(); + int RefreshDeviceList(); +protected: + std::vector m_deviceNames; + std::vector rxbuf; + int fd; + std::fstream m_SEN; +}; +#endif diff --git a/targets/ARCH/LMSSDR/USERSPACE/LIB/lms7002m/connectionManager/ConnectionUSB.cpp b/targets/ARCH/LMSSDR/USERSPACE/LIB/lms7002m/connectionManager/ConnectionUSB.cpp new file mode 100644 index 0000000000..b99fe6490b --- /dev/null +++ b/targets/ARCH/LMSSDR/USERSPACE/LIB/lms7002m/connectionManager/ConnectionUSB.cpp @@ -0,0 +1,762 @@ +/** +@file ConnectionUSB.cpp +@author Lime Microsystems (www.limemicro.com) +@brief Data writing and reading through USB port +*/ + +#include "ConnectionUSB.h" +#include + +#ifdef __unix__ + #include + #include +#endif + +#define USB_TIMEOUT 1000 + +#define HW_LDIGIRED L"DigiRed" +#define HW_LDIGIGREEN L"DigiGreen" +#define HW_LSTREAMER L"Stream" + +#define HW_DIGIRED "DigiRed" +#define HW_DIGIGREEN "DigiGreen" +#define HW_STREAMER "Stream" + +#define CTR_W_REQCODE 0xC1 +#define CTR_W_VALUE 0x0000 +#define CTR_W_INDEX 0x0000 + +#define CTR_R_REQCODE 0xC0 +#define CTR_R_VALUE 0x0000 +#define CTR_R_INDEX 0x0000 + +/** @brief Initializes port type and object necessary to communicate to usb device. +*/ +ConnectionUSB::ConnectionUSB() +{ + m_hardwareName = ""; + isConnected = false; + m_connectionType = USB_PORT; +#ifndef __unix__ + USBDevicePrimary = new CCyUSBDevice(NULL); + OutCtrEndPt = NULL; + InCtrEndPt = NULL; + InCtrlEndPt3 = NULL; + OutCtrlEndPt3 = NULL; +#else + dev_handle = 0; + devs = 0; + int r = libusb_init(&ctx); //initialize the library for the session we just declared + if(r < 0) + printf("Init Error %i\n", r); //there was an error + libusb_set_debug(ctx, 3); //set verbosity level to 3, as suggested in the documentation +#endif + currentDeviceIndex = -1; +} + +/** @brief Closes connection to chip and deallocates used memory. +*/ +ConnectionUSB::~ConnectionUSB() +{ + Close(); +#ifndef __unix__ + delete USBDevicePrimary; +#else + libusb_exit(ctx); +#endif +} + +/** @brief Automatically open first available chip connected to usb port. + @return 0-success, other-failure +*/ +IConnection::DeviceStatus ConnectionUSB::Open() +{ + currentDeviceIndex = -1; + if(m_deviceNames.size() == 0) + RefreshDeviceList(); + +#ifndef __unix__ + for(int i=0; iDeviceCount(); ++i) + if( Open(i) == SUCCESS) + { + currentDeviceIndex = i; + return SUCCESS; + } +#else + if(Open(0) == SUCCESS) + return SUCCESS; +#endif + return FAILURE; +} + +/** @brief Tries to open connected USB device and find communication endpoints. + @return Returns 1-Success, 0-EndPoints not found or device didn't connect. +*/ +IConnection::DeviceStatus ConnectionUSB::Open(unsigned index) +{ +#ifndef __unix__ + wstring m_hardwareDesc = L""; + if( index < USBDevicePrimary->DeviceCount()) + { + if(USBDevicePrimary->Open(index)) + { + m_hardwareDesc = USBDevicePrimary->Product; + unsigned int pos; + //determine connected board type + pos = m_hardwareDesc.find(HW_LDIGIRED, 0); + if( pos != wstring::npos ) + m_hardwareName = HW_DIGIRED; + else if (m_hardwareDesc.find(HW_LSTREAMER, 0) != wstring::npos) + m_hardwareName = HW_STREAMER; + else + m_hardwareName = HW_STREAMER; + + + if (InCtrlEndPt3) + { + delete InCtrlEndPt3; + InCtrlEndPt3 = NULL; + } + InCtrlEndPt3 = new CCyControlEndPoint(*USBDevicePrimary->ControlEndPt); + + if (OutCtrlEndPt3) + { + delete OutCtrlEndPt3; + OutCtrlEndPt3 = NULL; + } + OutCtrlEndPt3 = new CCyControlEndPoint(*USBDevicePrimary->ControlEndPt); + + InCtrlEndPt3->ReqCode = CTR_R_REQCODE; + InCtrlEndPt3->Value = CTR_R_VALUE; + InCtrlEndPt3->Index = CTR_R_INDEX; + + OutCtrlEndPt3->ReqCode = CTR_W_REQCODE; + OutCtrlEndPt3->Value = CTR_W_VALUE; + OutCtrlEndPt3->Index = CTR_W_INDEX; + + for (int i=0; iEndPointCount(); i++) + if(USBDevicePrimary->EndPoints[i]->Address == 0x01) + { + OutEndPt = USBDevicePrimary->EndPoints[i]; + long len = OutEndPt->MaxPktSize * 64; + OutEndPt->SetXferSize(len); + break; + } + for (int i=0; iEndPointCount(); i++) + if(USBDevicePrimary->EndPoints[i]->Address == 0x81) + { + InEndPt = USBDevicePrimary->EndPoints[i]; + long len = InEndPt->MaxPktSize * 64; + InEndPt->SetXferSize(len); + break; + } + isConnected = true; + return SUCCESS; + } //successfully opened device + } //if has devices + return FAILURE; +#else + if(index >= 0 && index < m_dev_pid_vid.size()) + { + dev_handle = libusb_open_device_with_vid_pid(ctx, m_dev_pid_vid[index].second, m_dev_pid_vid[index].first); + + if(dev_handle == 0) + return FAILURE; + if(libusb_kernel_driver_active(dev_handle, 0) == 1) //find out if kernel driver is attached + { + printf("Kernel Driver Active\n"); + if(libusb_detach_kernel_driver(dev_handle, 0) == 0) //detach it + printf("Kernel Driver Detached!\n"); + } + int r = libusb_claim_interface(dev_handle, 0); //claim interface 0 (the first) of device + if(r < 0) + { + printf("Cannot Claim Interface\n"); + return CANNOT_CLAIM_INTERFACE; + } + printf("Claimed Interface\n"); + isConnected = true; + return SUCCESS; + } + else + { + return FAILURE; + } +#endif +} + +/** @brief Closes communication to device. +*/ +void ConnectionUSB::Close() +{ + #ifndef __unix__ + USBDevicePrimary->Close(); + InEndPt = NULL; + OutEndPt = NULL; + if (InCtrlEndPt3) + { + delete InCtrlEndPt3; + InCtrlEndPt3 = NULL; + } + if (OutCtrlEndPt3) + { + delete OutCtrlEndPt3; + OutCtrlEndPt3 = NULL; + } + #else + if(dev_handle != 0) + { + libusb_release_interface(dev_handle, 0); + libusb_close(dev_handle); + dev_handle = 0; + } + #endif + isConnected = false; +} + +/** @brief Returns connection status + @return 1-connection open, 0-connection closed. +*/ +bool ConnectionUSB::IsOpen() +{ + #ifndef __unix__ + return USBDevicePrimary->IsOpen() && isConnected; + #else + return isConnected; + #endif +} + +/** @brief Sends given data buffer to chip through USB port. + @param buffer data buffer, must not be longer than 64 bytes. + @param length given buffer size. + @param timeout_ms timeout limit for operation in milliseconds + @return number of bytes sent. +*/ +int ConnectionUSB::Write(const unsigned char *buffer, const int length, int timeout_ms) +{ + long len = length; + if(IsOpen()) + { + unsigned char* wbuffer = new unsigned char[length]; + memcpy(wbuffer, buffer, length); + if(m_hardwareName == HW_DIGIRED || m_hardwareName == HW_STREAMER) + { + #ifndef __unix__ + if(OutCtrlEndPt3) + OutCtrlEndPt3->Write(wbuffer, len); + else + len = 0; + #else + len = libusb_control_transfer(dev_handle, LIBUSB_REQUEST_TYPE_VENDOR,CTR_W_REQCODE ,CTR_W_VALUE, CTR_W_INDEX, wbuffer, length, USB_TIMEOUT); + #endif + } + else + { + #ifndef __unix__ + if(OutCtrEndPt) + OutCtrEndPt->XferData(wbuffer, len); + else + len = 0; + #else + int actual = 0; + libusb_bulk_transfer(dev_handle, 0x01, wbuffer, len, &actual, USB_TIMEOUT); + len = actual; + #endif + } + delete wbuffer; + } + else + return 0; + return len; +} + +/** @brief Reads data coming from the chip through USB port. + @param buffer pointer to array where received data will be copied, array must be + big enough to fit received data. + @param length number of bytes to read from chip. + @param timeout_ms timeout limit for operation in milliseconds + @return number of bytes received. +*/ +int ConnectionUSB::Read(unsigned char *buffer, const int length, int timeout_ms) +{ + long len = length; + if(IsOpen()) + { + if(m_hardwareName == HW_DIGIRED || m_hardwareName == HW_STREAMER) + { + #ifndef __unix__ + if(InCtrlEndPt3) + InCtrlEndPt3->Read(buffer, len); + else + len = 0; + #else + len = libusb_control_transfer(dev_handle, LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_ENDPOINT_IN ,CTR_R_REQCODE ,CTR_R_VALUE, CTR_R_INDEX, buffer, len, USB_TIMEOUT); + #endif + } + else + { + #ifndef __unix__ + if(InCtrEndPt) + InCtrEndPt->XferData(buffer, len); + else + len = 0; + #else + int actual = 0; + libusb_bulk_transfer(dev_handle, 0x81, buffer, len, &actual, USB_TIMEOUT); + len = actual; + #endif + } + } + return len; +} + +#ifdef __unix__ +/** @brief Function for handling libusb callbacks +*/ +void callback_libusbtransfer(libusb_transfer *trans) +{ + USBTransferContext *context = reinterpret_cast(trans->user_data); + switch(trans->status) + { + case LIBUSB_TRANSFER_CANCELLED: + printf("Transfer canceled\n" ); + context->bytesXfered = trans->actual_length; + context->done = true; + context->used = false; + context->reset(); + break; + case LIBUSB_TRANSFER_COMPLETED: + if(trans->actual_length == context->bytesExpected) + { + context->bytesXfered = trans->actual_length; + context->done = true; + } + //printf("Transfer complete %i\n", trans->actual_length); + break; + case LIBUSB_TRANSFER_ERROR: + printf("TRANSFER ERRRO\n"); + break; + case LIBUSB_TRANSFER_TIMED_OUT: + printf("transfer timed out\n"); + + break; + case LIBUSB_TRANSFER_OVERFLOW: + printf("transfer overflow\n"); + + break; + case LIBUSB_TRANSFER_STALL: + printf("transfer stalled\n"); + break; + } + context->mPacketProcessed.notify_one(); +} +#endif + +/** @brief Finds all chips connected to usb ports + @return number of devices found +*/ +int ConnectionUSB::RefreshDeviceList() +{ + #ifndef __unix__ + USBDevicePrimary->Close(); + currentDeviceIndex = -1; + m_deviceNames.clear(); + string name; + if (USBDevicePrimary->DeviceCount()) + { + for (int i=0; iDeviceCount(); ++i) + { + Open(i); + name = DeviceName(); + m_deviceNames.push_back(name); + } + currentDeviceIndex = -1; + } + #else + m_dev_pid_vid.clear(); + m_deviceNames.clear(); + int usbDeviceCount = libusb_get_device_list(ctx, &devs); + if(usbDeviceCount > 0) + { + libusb_device_descriptor desc; + for(int i=0; i(pid,vid)); + } + else if(pid == 241) + { + m_hardwareName = HW_DIGIRED; + libusb_device_handle *tempDev_handle; + tempDev_handle = libusb_open_device_with_vid_pid(ctx, vid, pid); + if(libusb_kernel_driver_active(tempDev_handle, 0) == 1) //find out if kernel driver is attached + { + if(libusb_detach_kernel_driver(tempDev_handle, 0) == 0) //detach it + printf("Kernel Driver Detached!\n"); + } + if(libusb_claim_interface(tempDev_handle, 0) < 0) //claim interface 0 (the first) of device + { + printf("Cannot Claim Interface\n"); + } + + string fullName; + //check operating speed + int speed = libusb_get_device_speed(devs[i]); + if(speed == LIBUSB_SPEED_HIGH) + fullName = "USB 2.0"; + else if(speed == LIBUSB_SPEED_SUPER) + fullName = "USB 3.0"; + else + fullName = "USB"; + fullName += " ("; + //read device name + char data[255]; + memset(data, 0, 255); + int st = libusb_get_string_descriptor_ascii(tempDev_handle, 2, (unsigned char*)data, 255); + if(strlen(data) > 0) + fullName += data; + fullName += ")"; + libusb_close(tempDev_handle); + + m_deviceNames.push_back(fullName); + m_dev_pid_vid.push_back( pair(pid,vid)); + } + } + } + } + else + { + libusb_free_device_list(devs, 1); + return 0; + } + #endif + return m_deviceNames.size(); +} + +void ConnectionUSB::ClearComm() +{ +} + +/** @return name of currently opened device as string. +*/ +string ConnectionUSB::DeviceName() +{ +#ifndef __unix__ + string name; + char tempName[USB_STRING_MAXLEN]; + //memcpy(tempName, USBDevicePrimary->FriendlyName, USB_STRING_MAXLEN); + //name = tempName; + + for (int i = 0; i < USB_STRING_MAXLEN; ++i) + tempName[i] = USBDevicePrimary->DeviceName[i]; + if (USBDevicePrimary->bSuperSpeed == true) + name = "USB 3.0"; + else if (USBDevicePrimary->bHighSpeed == true) + name = "USB 2.0"; + else + name = "USB"; + name += " ("; + name += tempName; + name += ")"; + return name; +#else + if(dev_handle != 0) + { + char data[255]; + int st = libusb_get_string_descriptor_ascii(dev_handle, 2, (unsigned char*)data, 255); + return string(data); + } + return "no name"; +#endif +} + +/** + @brief Starts asynchronous data reading from board + @param *buffer buffer where to store received data + @param length number of bytes to read + @return handle of transfer context +*/ +int ConnectionUSB::BeginDataReading(char *buffer, long length) +{ + int i = 0; + bool contextFound = false; + //find not used context + for(i = 0; iBeginDataXfer((unsigned char*)buffer, length, contexts[i].inOvLap); + return i; + #else + unsigned int Timeout = 1000; + libusb_transfer *tr = contexts[i].transfer; + libusb_fill_bulk_transfer(tr, dev_handle, 0x81, (unsigned char*)buffer, length, callback_libusbtransfer, &contexts[i], Timeout); + contexts[i].done = false; + contexts[i].bytesXfered = 0; + contexts[i].bytesExpected = length; + int status = libusb_submit_transfer(tr); + int actual = 0; + //int status = libusb_bulk_transfer(dev_handle, 0x81, (unsigned char*)buffer, length, &actual, USB_TIMEOUT); + if(status != 0) + printf("ERROR BEGIN DATA TRANSFER %s\n", libusb_error_name(status)); + #endif + return i; +} + +/** + @brief Waits for asynchronous data reception + @param contextHandle handle of which context data to wait + @param timeout_ms number of miliseconds to wait + @return 1-data received, 0-data not received +*/ +int ConnectionUSB::WaitForReading(int contextHandle, unsigned int timeout_ms) +{ + if( contexts[contextHandle].used == true && contextHandle >= 0) + { + int status = 0; + #ifndef __unix__ + if(InEndPt) + status = InEndPt->WaitForXfer(contexts[contextHandle].inOvLap, timeout_ms); + return status; + #else + auto t1 = chrono::high_resolution_clock::now(); + auto t2 = chrono::high_resolution_clock::now(); + while(contexts[contextHandle].done == false && std::chrono::duration_cast(t2 - t1).count() < timeout_ms) + { + struct timeval tv; + tv.tv_sec = 1; + tv.tv_usec = 0; + //if(libusb_handle_events(ctx) != 0) + if(libusb_handle_events_timeout_completed(ctx, &tv, NULL) != 0) + printf("error libusb_handle_events %i\n", status); + t2 = chrono::high_resolution_clock::now(); + std::this_thread::sleep_for(std::chrono::milliseconds(1)); + } + std::unique_lock lck(contexts[contextHandle].m_lock); + while(contexts[contextHandle].done == false) //is changed in libusb callback + { + if(contexts[contextHandle].mPacketProcessed.wait_for(lck, std::chrono::milliseconds(timeout_ms)) == std::cv_status::timeout) + return 0; + } + return contexts[contextHandle].done == true; + #endif + } + else + return 0; +} + +/** + @brief Finishes asynchronous data reading from board + @param buffer array where to store received data + @param length number of bytes to read, function changes this value to number of bytes actually received + @param contextHandle handle of which context to finish + @return false failure, true number of bytes received +*/ +int ConnectionUSB::FinishDataReading(char *buffer, long &length, int contextHandle) +{ + if( contexts[contextHandle].used == true && contextHandle >= 0) + { + #ifndef __unix__ + int status = 0; + if(InEndPt) + status = InEndPt->FinishDataXfer((unsigned char*)buffer, length, contexts[contextHandle].inOvLap, contexts[contextHandle].context); + contexts[contextHandle].used = false; + contexts[contextHandle].reset(); + return length; + #else + length = contexts[contextHandle].bytesXfered; + contexts[contextHandle].used = false; + contexts[contextHandle].reset(); + return length; + #endif + } + else + return 0; +} + +int ConnectionUSB::ReadDataBlocking(char *buffer, long &length, int timeout_ms) +{ +#ifndef __unix__ + return InEndPt->XferData((unsigned char*)buffer, length); +#else + return 0; +#endif +} + + +/** + @brief Aborts reading operations +*/ +void ConnectionUSB::AbortReading() +{ +#ifndef __unix__ + InEndPt->Abort(); +#else + for(int i=0; iBeginDataXfer((unsigned char*)buffer, length, contextsToSend[i].inOvLap); + return i; + #else + unsigned int Timeout = 1000; + libusb_transfer *tr = contextsToSend[i].transfer; + //libusb_set_iso_packet_lengths(contexts[i].transfer, 512*64); + libusb_fill_bulk_transfer(tr, dev_handle, 0x1, (unsigned char*)buffer, length, callback_libusbtransfer, &contextsToSend[i], Timeout); + contextsToSend[i].done = false; + contextsToSend[i].bytesXfered = 0; + contextsToSend[i].bytesExpected = length; + libusb_submit_transfer(tr); + #endif + return i; +} + +/** + @brief Waits for asynchronous data sending + @param contextHandle handle of which context data to wait + @param timeout_ms number of miliseconds to wait + @return 1-data received, 0-data not received +*/ +int ConnectionUSB::WaitForSending(int contextHandle, unsigned int timeout_ms) +{ + if( contextsToSend[contextHandle].used == true ) + { + #ifndef __unix__ + int status = 0; + if(OutEndPt) + status = OutEndPt->WaitForXfer(contextsToSend[contextHandle].inOvLap, timeout_ms); + return status; + #else + auto t1 = chrono::high_resolution_clock::now(); + auto t2 = chrono::high_resolution_clock::now(); + while(contextsToSend[contextHandle].done == false && std::chrono::duration_cast(t2 - t1).count() < timeout_ms) + { + struct timeval tv; + tv.tv_sec = 1; + tv.tv_usec = 0; + int status = libusb_handle_events_timeout_completed(ctx, &tv, NULL); + if(status != 0) + printf("error libusb_handle_events %i\n", status); + t2 = chrono::high_resolution_clock::now(); + std::this_thread::sleep_for(std::chrono::milliseconds(1)); + } + std::unique_lock lck(contextsToSend[contextHandle].m_lock); + while(contextsToSend[contextHandle].done == false) //is changed in libusb callback + { + if(contextsToSend[contextHandle].mPacketProcessed.wait_for(lck, std::chrono::milliseconds(timeout_ms)) == std::cv_status::timeout) + return 0; + } + return contextsToSend[contextHandle].done == true; + #endif + } + else + return 0; +} + +/** + @brief Finishes asynchronous data sending to board + @param buffer array where to store received data + @param length number of bytes to read, function changes this value to number of bytes acctually received + @param contextHandle handle of which context to finish + @return false failure, true number of bytes sent +*/ +int ConnectionUSB::FinishDataSending(const char *buffer, long &length, int contextHandle) +{ + if( contextsToSend[contextHandle].used == true) + { + #ifndef __unix__ + if(OutEndPt) + OutEndPt->FinishDataXfer((unsigned char*)buffer, length, contextsToSend[contextHandle].inOvLap, contextsToSend[contextHandle].context); + contextsToSend[contextHandle].used = false; + contextsToSend[contextHandle].reset(); + return length; + #else + length = contextsToSend[contextHandle].bytesXfered; + contextsToSend[contextHandle].used = false; + contextsToSend[contextHandle].reset(); + return length; + #endif + } + else + return 0; +} + +/** + @brief Aborts sending operations +*/ +void ConnectionUSB::AbortSending() +{ +#ifndef __unix__ + OutEndPt->Abort(); +#else + for (int i = 0; i ConnectionUSB::GetDeviceNames() +{ + return m_deviceNames; +} diff --git a/targets/ARCH/LMSSDR/USERSPACE/LIB/lms7002m/connectionManager/ConnectionUSB.h b/targets/ARCH/LMSSDR/USERSPACE/LIB/lms7002m/connectionManager/ConnectionUSB.h new file mode 100644 index 0000000000..f3048c1842 --- /dev/null +++ b/targets/ARCH/LMSSDR/USERSPACE/LIB/lms7002m/connectionManager/ConnectionUSB.h @@ -0,0 +1,144 @@ +/** +@file ConnectionUSB.h +@author Lime Microsystems (www.limemicro.com) +@brief Class for data writing and reading through USB port +*/ + +#ifndef USB_PORT_CONNECTION_H +#define USB_PORT_CONNECTION_H + +#include "IConnection.h" + +#ifndef __unix__ +#include "windows.h" +#include "CyAPI.h" +#else +#include +#include +#include +#include +#endif + +#define USB_MAX_CONTEXTS 64 //maximum number of contexts for asynchronous transfers + +/** @brief Wrapper class for holding USB asynchronous transfers contexts +*/ +class USBTransferContext +{ +public: + USBTransferContext() : used(false) + { + #ifndef __unix__ + inOvLap = new OVERLAPPED; + memset(inOvLap, 0, sizeof(OVERLAPPED)); + inOvLap->hEvent = CreateEvent(NULL, false, false, NULL); + context = NULL; + #else + transfer = libusb_alloc_transfer(0); + bytesXfered = 0; + bytesExpected = 0; + done = 0; + #endif + } + ~USBTransferContext() + { + #ifndef __unix__ + CloseHandle(inOvLap->hEvent); + delete inOvLap; + #else + libusb_free_transfer(transfer); + #endif + } + bool reset() + { + if(used) + return false; + #ifndef __unix__ + CloseHandle(inOvLap->hEvent); + memset(inOvLap, 0, sizeof(OVERLAPPED)); + inOvLap->hEvent = CreateEvent(NULL, false, false, NULL); + #endif + return true; + } + bool used; + #ifndef __unix__ + PUCHAR context; + OVERLAPPED *inOvLap; + #else + libusb_transfer* transfer; + long bytesXfered; + long bytesExpected; + bool done; + std::mutex m_lock; + std::condition_variable mPacketProcessed; + #endif +}; + +class ConnectionUSB : public IConnection +{ +public: + ConnectionUSB(); + ~ConnectionUSB(); + + void FindDevices(); + DeviceStatus Open(); + DeviceStatus Open(unsigned index); + void Close(); + bool IsOpen(); + int GetOpenedIndex(); + + int Write(const unsigned char *buffer, int length, int timeout_ms = 0); + int Read(unsigned char *buffer, int length, int timeout_ms = 0); + + virtual int BeginDataReading(char *buffer, long length); + virtual int WaitForReading(int contextHandle, unsigned int timeout_ms); + virtual int FinishDataReading(char *buffer, long &length, int contextHandle); + virtual void AbortReading(); + virtual int ReadDataBlocking(char *buffer, long &length, int timeout_ms); + + virtual int BeginDataSending(const char *buffer, long length); + virtual int WaitForSending(int contextHandle, unsigned int timeout_ms); + virtual int FinishDataSending(const char *buffer, long &length, int contextHandle); + virtual void AbortSending(); + + std::vector GetDeviceNames(); + int RefreshDeviceList(); + void ClearComm(); +private: + int currentDeviceIndex; + std::string DeviceName(); + + std::vector m_deviceNames; + std::string m_hardwareName; + int m_hardwareVer; + + USBTransferContext contexts[USB_MAX_CONTEXTS]; + USBTransferContext contextsToSend[USB_MAX_CONTEXTS]; + void Initialize(); + + bool isConnected; + int currentPortIndex; + + #ifndef __unix__ + CCyUSBDevice *USBDevicePrimary; + //control endpoints for DigiRed + CCyControlEndPoint *InCtrlEndPt3; + CCyControlEndPoint *OutCtrlEndPt3; + + //control endpoints for DigiGreen + CCyUSBEndPoint *OutCtrEndPt; + CCyUSBEndPoint *InCtrEndPt; + + //end points for samples reading and writing + CCyUSBEndPoint *InEndPt; + CCyUSBEndPoint *OutEndPt; + + #else + libusb_device **devs; //pointer to pointer of device, used to retrieve a list of devices + libusb_device_handle *dev_handle; //a device handle + libusb_context *ctx; //a libusb session + std::vector > m_dev_pid_vid; + #endif +}; + +#endif diff --git a/targets/ARCH/LMSSDR/USERSPACE/LIB/lms7002m/connectionManager/IConnection.h b/targets/ARCH/LMSSDR/USERSPACE/LIB/lms7002m/connectionManager/IConnection.h new file mode 100644 index 0000000000..5804f1149f --- /dev/null +++ b/targets/ARCH/LMSSDR/USERSPACE/LIB/lms7002m/connectionManager/IConnection.h @@ -0,0 +1,68 @@ +/** + @file IConnection.h + @author Lime Microsystems + @brief Interface class for connection types +*/ + +#ifndef ICONNECTION_H +#define ICONNECTION_H + +#include +#include + +using namespace std; + +class IConnection +{ +public: + /// Supported connection types. + enum eConnectionType + { + CONNECTION_UNDEFINED = -1, + COM_PORT = 0, + USB_PORT = 1, + SPI_PORT = 2, + //insert new types here + CONNECTION_TYPES_COUNT //used only for memory allocation + }; + + enum DeviceStatus + { + SUCCESS, + FAILURE, + END_POINTS_NOT_FOUND, + CANNOT_CLAIM_INTERFACE + }; + + IConnection() : m_connectionType(CONNECTION_UNDEFINED){}; + virtual ~IConnection(){}; + virtual int RefreshDeviceList() = 0; + virtual DeviceStatus Open(unsigned i) = 0; + virtual void Close() = 0; + virtual bool IsOpen() = 0; + virtual int GetOpenedIndex() = 0; + + virtual int Write(const unsigned char *buffer, int length, int timeout_ms = 0) = 0; + virtual int Read(unsigned char *buffer, int length, int timeout_ms = 0) = 0; + + virtual std::vector GetDeviceNames() = 0; + + virtual eConnectionType GetType() { return m_connectionType; }; + virtual bool SetParam(const char *name, const char* value) {return false;}; + + virtual int BeginDataReading(char *buffer, long length){ return -1; }; + virtual int WaitForReading(int contextHandle, unsigned int timeout_ms){ return 0;}; + virtual int FinishDataReading(char *buffer, long &length, int contextHandle){ return 0;} + virtual void AbortReading(){}; + virtual int ReadDataBlocking(char *buffer, long &length, int timeout_ms){ return 0; } + + virtual int BeginDataSending(const char *buffer, long length){ return -1; }; + virtual int WaitForSending(int contextHandle, unsigned int timeout_ms){ return 0;}; + virtual int FinishDataSending(const char *buffer, long &length, int contextHandle){ return 0;} + virtual void AbortSending(){}; +protected: + eConnectionType m_connectionType; +}; + +#endif + diff --git a/targets/ARCH/LMSSDR/USERSPACE/LIB/lms7002m/lms7002_defines.h b/targets/ARCH/LMSSDR/USERSPACE/LIB/lms7002m/lms7002_defines.h new file mode 100644 index 0000000000..6b06a51c7e --- /dev/null +++ b/targets/ARCH/LMSSDR/USERSPACE/LIB/lms7002m/lms7002_defines.h @@ -0,0 +1,218 @@ +/** +@file lms7002_defines.h +@author Lime Microsystems +@brief enumerations of available LMS7002M commands and statuses +*/ +#pragma once + +const int LMS_RST_DEACTIVATE = 0; +const int LMS_RST_ACTIVATE = 1; +const int LMS_RST_PULSE = 2; + +enum eLMS_DEV +{ + LMS_DEV_UNKNOWN, + LMS_DEV_EVB6, + LMS_DEV_DIGIGREEN, + LMS_DEV_DIGIRED, + LMS_DEV_EVB7, + LMS_DEV_ZIPPER, + LMS_DEV_SOCKETBOARD, + LMS_DEV_EVB7V2, + LMS_DEV_STREAM, + LMS_DEV_NOVENA, + LMS_DEV_DATASPARK, + LMS_DEV_RFSPARK, + LMS_DEV_LMS6002USB, + LMS_DEV_RFESPARK, + LMS_DEV_SODERA, + + LMS_DEV_COUNT +}; + +const char LMS_DEV_NAMES[][80] = +{ + "UNKNOWN", + "EVB6", + "DigiGreen", + "DigiRed", + "EVB7", + "ZIPPER", + "Socket Board", + "EVB7_v2", + "Stream", + "Novena", + "DataSpark", + "RF-Spark", + "LMS6002-USB Stick", + "RF-ESpark", + "SoDeRa", +}; + +static const char* GetDeviceName(const eLMS_DEV device) +{ + if (LMS_DEV_UNKNOWN < device && device < LMS_DEV_COUNT) + return LMS_DEV_NAMES[device]; + else + return LMS_DEV_NAMES[LMS_DEV_UNKNOWN]; +} + +enum eEXP_BOARD +{ + EXP_BOARD_UNKNOWN, + EXP_BOARD_UNSUPPORTED, + EXP_BOARD_NO, + EXP_BOARD_MYRIAD1, + EXP_BOARD_MYRIAD2, + EXP_BOARD_MYRIAD_NOVENA, + EXP_BOARD_HPM1000, + EXP_BOARD_MYRIAD7, + EXP_BOARD_HPM7, + + EXP_BOARD_COUNT +}; + +const char EXP_BOARD_NAMES[][80] = +{ + "UNKNOWN", + "UNSUPPORTED", + "NOT AVAILABLE", + "Myriad1", + "Myriad2", + "Novena", + "HPM1000", + "Myriad7", + "HMP7" +}; + +static const char* GetExpansionBoardName(const eEXP_BOARD board) +{ + if (EXP_BOARD_UNKNOWN < board && board < EXP_BOARD_COUNT) + return EXP_BOARD_NAMES[board]; + else + return EXP_BOARD_NAMES[EXP_BOARD_UNKNOWN]; +} + +struct LMS64C_Info +{ + unsigned char firmware; + unsigned char deviceType; + unsigned char protocol; + unsigned char hardware; + unsigned char expansionBoard; +}; + +enum eCMD_LMS +{ + CMD_GET_INFO = 0x00, + CMD_LMS6002_RST = 0x10, + ///Writes data to SI5356 synthesizer via I2C + CMD_SI5356_WR = 0x11, + ///Reads data from SI5356 synthesizer via I2C + CMD_SI5356_RD = 0x12, + ///Writes data to SI5351 synthesizer via I2C + CMD_SI5351_WR = 0x13, + ///Reads data from SI5351 synthesizer via I2C + CMD_SI5351_RD = 0x14, + ///PanelBus DVI (HDMI) Transmitter control + CMD_TFP410_WR = 0x15, + ///PanelBus DVI (HDMI) Transmitter control + CMD_TFP410_RD = 0x16, + ///Sets new LMS7002M chip’s RESET pin level (0, 1, pulse) + CMD_LMS7002_RST = 0x20, + ///Writes data to LMS7002M chip via SPI + CMD_LMS7002_WR = 0x21, + ///Reads data from LMS7002M chip via SPI + CMD_LMS7002_RD = 0x22, + ///Writes data to LMS6002 chip via SPI + CMD_LMS6002_WR = 0x23, + ///Reads data from LMS6002 chip via SPI + CMD_LMS6002_RD = 0x24, + + CMD_LMS_LNA = 0x2A, + CMD_LMS_PA = 0x2B, + + CMD_PROG_MCU = 0x2C, + ///Writes data to ADF4002 chip via SPI + CMD_ADF4002_WR = 0x31, + + CMD_USB_FIFO_RST = 0x40, + CMD_PE636040_WR = 0x41, + CMD_PE636040_RD = 0x42, + + CMD_GPIO_WR = 0x51, + CMD_GPIO_RD = 0x52, + + CMD_ALTERA_FPGA_GW_WR = 0x53, + CMD_ALTERA_FPGA_GW_RD = 0x54, + + CMD_BRDSPI_WR = 0x55,//16 bit spi for stream, dataspark control + CMD_BRDSPI_RD = 0x56,//16 bit spi for stream, dataspark control + CMD_BRDSPI8_WR = 0x57, //8 + 8 bit spi for stream, dataspark control + CMD_BRDSPI8_RD = 0x58, //8 + 8 bit spi for stream, dataspark control + + CMD_BRDCONF_WR = 0x5D, //write config data to board + CMD_BRDCONF_RD = 0x5E, //read config data from board + + CMD_ANALOG_VAL_WR = 0x61, //write analog value + CMD_ANALOG_VAL_RD = 0x62, //read analog value + + CMD_MYRIAD_RST = 0x80, + CMD_MYRIAD_WR = 0x81, + CMD_MYRIAD_RD = 0x82, + CMD_MYRIAD_PROG = 0x8C +}; + +enum eCMD_STATUS +{ + STATUS_UNDEFINED, + STATUS_COMPLETED_CMD, + STATUS_UNKNOWN_CMD, + STATUS_BUSY_CMD, + STATUS_MANY_BLOCKS_CMD, + STATUS_ERROR_CMD, + STATUS_WRONG_ORDER_CMD, + STATUS_RESOURCE_DENIED_CMD, + STATUS_COUNT +}; + +static const char status_text[][32]= +{ + "Undefined/Failure", + "Completed", + "Unknown command", + "Busy", + "Too many blocks", + "Error", + "Wrong order", + "Resource denied" +}; + +static const char* status2string(const int status) +{ + if(status >= 0 && status < STATUS_COUNT) + return status_text[status]; + else + return "Unknown status"; +} + +enum eADC_UNITS +{ + RAW, + VOLTAGE, + CURRENT, + RESISTANCE, + POWER, + TEMPERATURE, + ADC_UNITS_COUNT +}; + +static const char adc_units_text[][8] = {"", "V", "A", "Ohm", "W", "C"}; + +static const char* adcUnits2string(const unsigned units) +{ + if (units < ADC_UNITS_COUNT) + return adc_units_text[units]; + else + return " unknown"; +} diff --git a/targets/ARCH/LMSSDR/USERSPACE/LIB/lms7002m/lmsComms.cpp b/targets/ARCH/LMSSDR/USERSPACE/LIB/lms7002m/lmsComms.cpp new file mode 100644 index 0000000000..5b74ef8975 --- /dev/null +++ b/targets/ARCH/LMSSDR/USERSPACE/LIB/lms7002m/lmsComms.cpp @@ -0,0 +1,326 @@ +/** +@file LMScomms.cpp +@author Lime Microsystems (www.limemicro.com) +@brief Implementation of data transmission to LMS boards +*/ + +#include "lmsComms.h" + +LMScomms::LMScomms() +{ + callback_logData = nullptr; + unsigned short test = 0x1234; + unsigned char* bytes = (unsigned char*)&test; + if(bytes[0] == 0x12 && bytes[1] == 0x34) + mSystemBigEndian = true; + else + mSystemBigEndian = false; +} + +LMScomms::~LMScomms() +{ +} + +/** @brief Transfers data between packet and connected device + @param pkt packet containing output data and to receive incomming data + @return 0: success, other: failure +*/ +LMScomms::TransferStatus LMScomms::TransferPacket(GenericPacket& pkt) +{ + std::lock_guard lock(mControlPortLock); + TransferStatus status = TRANSFER_SUCCESS; + if(IsOpen() == false) + return NOT_CONNECTED; + + int packetLen; + eLMS_PROTOCOL protocol = LMS_PROTOCOL_UNDEFINED; + if(activeControlPort->GetType() == IConnection::SPI_PORT) + protocol = LMS_PROTOCOL_NOVENA; + else + protocol = LMS_PROTOCOL_LMS64C; + switch(protocol) + { + case LMS_PROTOCOL_UNDEFINED: + return TRANSFER_FAILED; + case LMS_PROTOCOL_LMS64C: + packetLen = ProtocolLMS64C::pktLength; + break; + case LMS_PROTOCOL_NOVENA: + packetLen = pkt.outBuffer.size() > ProtocolNovena::pktLength ? ProtocolNovena::pktLength : pkt.outBuffer.size(); + break; + default: + packetLen = 0; + return TRANSFER_FAILED; + } + int outLen = 0; + unsigned char* outBuffer = NULL; + outBuffer = PreparePacket(pkt, outLen, protocol); + unsigned char* inBuffer = new unsigned char[outLen]; + memset(inBuffer, 0, outLen); + + int outBufPos = 0; + int inDataPos = 0; + if(outLen == 0) + { + //printf("packet outlen = 0\n"); + outLen = 1; + } + + if(protocol == LMS_PROTOCOL_NOVENA) + { + bool transferData = true; //some commands are fake, so don't need transferring + if(pkt.cmd == CMD_GET_INFO) + { + //spi does not have GET INFO, fake it to inform what device it is + pkt.status = STATUS_COMPLETED_CMD; + pkt.inBuffer.clear(); + pkt.inBuffer.resize(64, 0); + pkt.inBuffer[0] = 0; //firmware + pkt.inBuffer[1] = LMS_DEV_NOVENA; //device + pkt.inBuffer[2] = 0; //protocol + pkt.inBuffer[3] = 0; //hardware + pkt.inBuffer[4] = EXP_BOARD_UNSUPPORTED; //expansion + transferData = false; + } + + if(transferData) + { + if (callback_logData) + callback_logData(true, outBuffer, outLen); + int bytesWritten = Write(outBuffer, outLen); + if( bytesWritten == outLen) + { + if(pkt.cmd == CMD_LMS7002_RD) + { + inDataPos = Read(&inBuffer[inDataPos], outLen); + if(inDataPos != outLen) + status = TRANSFER_FAILED; + else + { + if (callback_logData) + callback_logData(false, inBuffer, inDataPos); + } + } + ParsePacket(pkt, inBuffer, inDataPos, protocol); + } + else + status = TRANSFER_FAILED; + } + } + else + { + for(int i=0; i= 5) + { + info.firmware = pkt.inBuffer[0]; + info.device = pkt.inBuffer[1] < LMS_DEV_COUNT ? (eLMS_DEV)pkt.inBuffer[1] : LMS_DEV_UNKNOWN; + info.protocol = pkt.inBuffer[2]; + info.hardware = pkt.inBuffer[3]; + info.expansion = pkt.inBuffer[4] < EXP_BOARD_COUNT ? (eEXP_BOARD)pkt.inBuffer[4] : EXP_BOARD_UNKNOWN; + } + return info; +} + +/** @brief Takes generic packet and converts to specific protocol buffer + @param pkt generic data packet to convert + @param length returns length of returned buffer + @param protocol which protocol to use for data + @return pointer to data buffer, must be manually deleted after use +*/ +unsigned char* LMScomms::PreparePacket(const GenericPacket& pkt, int& length, const eLMS_PROTOCOL protocol) +{ + unsigned char* buffer = NULL; + if(protocol == LMS_PROTOCOL_UNDEFINED) + return NULL; + + if(protocol == LMS_PROTOCOL_LMS64C) + { + ProtocolLMS64C packet; + int maxDataLength = packet.maxDataLength; + packet.cmd = pkt.cmd; + packet.status = pkt.status; + int byteBlockRatio = 1; //block ratio - how many bytes in one block + switch( packet.cmd ) + { + case CMD_PROG_MCU: + case CMD_GET_INFO: + case CMD_SI5351_RD: + case CMD_SI5356_RD: + byteBlockRatio = 1; + break; + case CMD_SI5351_WR: + case CMD_SI5356_WR: + byteBlockRatio = 2; + break; + case CMD_LMS7002_RD: + case CMD_BRDSPI_RD: + case CMD_BRDSPI8_RD: + byteBlockRatio = 2; + break; + case CMD_ADF4002_WR: + byteBlockRatio = 3; + break; + case CMD_LMS7002_WR: + case CMD_BRDSPI_WR: + case CMD_ANALOG_VAL_WR: + byteBlockRatio = 4; + break; + default: + byteBlockRatio = 1; + } + if (packet.cmd == CMD_LMS7002_RD || packet.cmd == CMD_BRDSPI_RD) + maxDataLength = maxDataLength/2; + if (packet.cmd == CMD_ANALOG_VAL_RD) + maxDataLength = maxDataLength / 4; + int blockCount = pkt.outBuffer.size()/byteBlockRatio; + int bufLen = blockCount/(maxDataLength/byteBlockRatio) + +(blockCount%(maxDataLength/byteBlockRatio)!=0); + bufLen *= packet.pktLength; + if(bufLen == 0) + bufLen = packet.pktLength; + buffer = new unsigned char[bufLen]; + memset(buffer, 0, bufLen); + int srcPos = 0; + for(int j=0; j*packet.pktLength (maxDataLength/byteBlockRatio)) + { + buffer[pktPos+2] = maxDataLength/byteBlockRatio; + blockCount -= buffer[pktPos+2]; + } + else + buffer[pktPos+2] = blockCount; + memcpy(&buffer[pktPos+3], packet.reserved, sizeof(packet.reserved)); + int bytesToPack = (maxDataLength/byteBlockRatio)*byteBlockRatio; + for (int k = 0; k> 8) | 0x80; + buffer[1] = NOVENA_GPIO_ADDR & 0xFF; + buffer[2] = 0x00; + buffer[3] = 0x18; + buffer[4] = (NOVENA_GPIO_ADDR >> 8) | 0x80; + buffer[5] = NOVENA_GPIO_ADDR & 0xFF; + buffer[6] = 0x00; + buffer[7] = 0x38; + length = 8; + } + else + { + buffer = new unsigned char[pkt.outBuffer.size()]; + memcpy(buffer, &pkt.outBuffer[0], pkt.outBuffer.size()); + if (pkt.cmd == CMD_LMS7002_WR) + { + for(int i=0; i callback) +{ + callback_logData = callback; +} diff --git a/targets/ARCH/LMSSDR/USERSPACE/LIB/lms7002m/lmsComms.h b/targets/ARCH/LMSSDR/USERSPACE/LIB/lms7002m/lmsComms.h new file mode 100644 index 0000000000..3d94d8ece2 --- /dev/null +++ b/targets/ARCH/LMSSDR/USERSPACE/LIB/lms7002m/lmsComms.h @@ -0,0 +1,111 @@ +/** +@file LMScomms.h +@author Lime Microsystems (www.limemicro.com) +@brief Class for handling data transmission to LMS boards +*/ + +#ifndef LMS_COMMS_H +#define LMS_COMMS_H + +#include "lms7002_defines.h" +#include "connectionManager/ConnectionManager.h" +#include +#include + +struct LMSinfo +{ + eLMS_DEV device; + eEXP_BOARD expansion; + int firmware; + int hardware; + int protocol; +}; + +/* @brief Class for abstracting transfering data to and from chip +*/ +class LMScomms : public ConnectionManager +{ +public: + enum TransferStatus + { + TRANSFER_SUCCESS, + TRANSFER_FAILED, + NOT_CONNECTED + }; + + enum eLMS_PROTOCOL + { + LMS_PROTOCOL_UNDEFINED = 0, + LMS_PROTOCOL_DIGIC, + LMS_PROTOCOL_LMS64C, + LMS_PROTOCOL_NOVENA, + }; + struct ProtocolDIGIC + { + static const int pktLength = 64; + static const int maxDataLength = 60; + ProtocolDIGIC() : cmd(0), i2cAddr(0), blockCount(0) {}; + unsigned char cmd; + unsigned char i2cAddr; + unsigned char blockCount; + unsigned char reserved; + unsigned char data[maxDataLength]; + }; + + struct ProtocolLMS64C + { + static const int pktLength = 64; + static const int maxDataLength = 56; + ProtocolLMS64C() :cmd(0),status(STATUS_UNDEFINED),blockCount(0) + { + memset(reserved, 0, 5); + }; + unsigned char cmd; + unsigned char status; + unsigned char blockCount; + unsigned char reserved[5]; + unsigned char data[maxDataLength]; + }; + + struct ProtocolNovena + { + static const int pktLength = 128; + static const int maxDataLength = 128; + ProtocolNovena() :cmd(0),status(0) {}; + unsigned char cmd; + unsigned char status; + unsigned char blockCount; + unsigned char data[maxDataLength]; + }; + + struct GenericPacket + { + GenericPacket() + { + cmd = CMD_GET_INFO; + status = STATUS_UNDEFINED; + } + + eCMD_LMS cmd; + eCMD_STATUS status; + vector outBuffer; + vector inBuffer; + }; + + LMScomms(); + ~LMScomms(); + + virtual TransferStatus TransferPacket(GenericPacket &pkt); + LMSinfo GetInfo(); + void SetDataLogCallback(std::function callback); +protected: + std::function callback_logData; + std::mutex mControlPortLock; + unsigned char* PreparePacket(const GenericPacket &pkt, int &length, const eLMS_PROTOCOL protocol); + int ParsePacket(GenericPacket &pkt, const unsigned char* buffer, const int length, const eLMS_PROTOCOL protocol); +protected: + bool mSystemBigEndian; +}; + +#endif // LMS_COMMS_H + diff --git a/targets/ARCH/LMSSDR/USERSPACE/LIB/lms7002m/typedefs.h b/targets/ARCH/LMSSDR/USERSPACE/LIB/lms7002m/typedefs.h new file mode 100644 index 0000000000..9ae0c25d93 --- /dev/null +++ b/targets/ARCH/LMSSDR/USERSPACE/LIB/lms7002m/typedefs.h @@ -0,0 +1,18 @@ +/** +@file typedefs.h +@author Lime Microsystems (www.limemicro.com) +@brief Variables types definitions +*/ + +#ifndef LMS7002M_TYPEDEFS_H +#define LMS7002M_TYPEDEFS_H + +typedef unsigned int uint32_t; +typedef int int32_t; +typedef unsigned short uint16_t; +typedef short int16_t; +typedef signed char int8_t; +typedef unsigned char uint8_t; +typedef double float_type; + +#endif diff --git a/targets/ARCH/LMSSDR/USERSPACE/LIB/lmsSDR/LMS_SDR.cpp b/targets/ARCH/LMSSDR/USERSPACE/LIB/lmsSDR/LMS_SDR.cpp new file mode 100644 index 0000000000..1ff4bbf1de --- /dev/null +++ b/targets/ARCH/LMSSDR/USERSPACE/LIB/lmsSDR/LMS_SDR.cpp @@ -0,0 +1,334 @@ +/** +@author Lime Microsystems +@brief Stream board communications for Matlab +*/ + +#include "LMS_SDR.h" + +#include "lmsComms.h" +#include "LMS_StreamBoard.h" +#include "ringBuffer.h" +#include "IConnection.h" +#include "fifo.h" +#include "dataTypes.h" +#include +#include + +#include +#include +#include +#include +#include + +#define _USE_MATH_DEFINES +#include + +using namespace std; + +typedef enum +{ + LMS_SUCCESS = 0, + LMS_ERROR +} LMS_STATUS; + +LMS_SamplesFIFO rxBuffer(1); +static thread rxThread; +atomic rxStop(1); +atomic rxRunning(0); +atomic rxDroppedSamples(0); +atomic RxDataRate(0); +atomic rxSamplingRate(0); + +LMS_SamplesFIFO txBuffer(1); +static thread txThread; +atomic txStop(1); +atomic txRunning(0); +atomic txDroppedSamples(0); +atomic TxDataRate(0); +atomic txSamplingRate(0); + +LMScomms comPort(IConnection::COM_PORT); +LMScomms usbPort(IConnection::USB_PORT); +LMS_StreamBoard streamer(&usbPort); + +const int samplesInPacket = 1024; +unsigned int opMode = 0; + +DLL_EXPORT void LMS_Stats(uint32_t *RxBufSize, uint32_t *RxBufFilled, uint32_t *RxSamplingRate, uint32_t *TxBufSize, uint32_t *TxBufFilled, uint32_t *TxSamplingRate) +{ + LMS_SamplesFIFO::BufferInfo rxStats = rxBuffer.GetInfo(); + LMS_SamplesFIFO::BufferInfo txStats = txBuffer.GetInfo(); + if (RxBufSize) + *RxBufSize = rxStats.size*samplesInPacket; + if (RxBufFilled) + *RxBufFilled = rxStats.itemsFilled*samplesInPacket; + if (TxBufSize) + *TxBufSize = txStats.size*samplesInPacket; + if (TxBufFilled) + *TxBufFilled = txStats.itemsFilled*samplesInPacket; + if (TxSamplingRate) + *TxSamplingRate = txSamplingRate.load(); + if (RxSamplingRate) + *RxSamplingRate = rxSamplingRate.load(); +} + +DLL_EXPORT int LMS_Init(const int OperationMode, uint32_t trxBuffersLength) +{ + opMode = OperationMode; + unsigned int packetsNeeded = trxBuffersLength / samplesInPacket; + if (trxBuffersLength % samplesInPacket != 0) + ++packetsNeeded; + if (packetsNeeded >= (uint32_t)(1 << 31)) + packetsNeeded = (uint32_t)(1 << 31); + for (int i = 0; i < 32; ++i) + if ((1 << i) >= packetsNeeded) + { + packetsNeeded = (1 << i); + break; + } + rxBuffer.Reset(packetsNeeded); + txBuffer.Reset(packetsNeeded); + return LMS_SUCCESS; +} + +DLL_EXPORT int LMS_Destroy() +{ + LMS_RxStop(); + //buffers size is reduced to lower memory consumption when not used + rxBuffer.Reset(1); + txBuffer.Reset(1); + return LMS_SUCCESS; +} + +DLL_EXPORT LMScomms* LMS_GetUSBPort() +{ + return &usbPort; +} + +DLL_EXPORT LMScomms* LMS_GetCOMPort() +{ + return &comPort; +} + +const int maxDevListLen = 32; +const int maxDevNameLen = 256; //each device name not longer than 256 +static char DeviceNames[maxDevListLen][maxDevNameLen]; + +DLL_EXPORT int LMS_UpdateDeviceList(LMScomms* port) +{ + memset(DeviceNames, 0, maxDevListLen*maxDevNameLen); + port->Close(); + int devCount = port->RefreshDeviceList(); + vector names = port->GetDeviceList(); + int charsWritten = 0; + for (unsigned int i = 0; i < names.size() && i < maxDevListLen; ++i) + { + charsWritten += sprintf(DeviceNames[i], "[%i] %.*s", i, maxDevNameLen, names[i].c_str()); + } + return devCount; +} + +DLL_EXPORT const char* LMS_GetDeviceName(LMScomms* port, unsigned int deviceIndex) +{ + if (deviceIndex < maxDevListLen) + return DeviceNames[deviceIndex]; + else + return ""; +} + +DLL_EXPORT int LMS_DeviceOpen(LMScomms* port, const uint32_t deviceIndex) +{ + port->Close(); + int status = port->Open(deviceIndex); + if (status == 1) + { + return LMS_SUCCESS; + } + else + { + return LMS_ERROR; + } +} + +DLL_EXPORT void LMS_DeviceClose(LMScomms* port) +{ + port->Close(); +} + +DLL_EXPORT uint32_t LMS_ControlWrite(LMScomms* port, const uint8_t *buffer, const uint16_t bufLen) +{ + return port->Write(buffer, bufLen, 0); +} + +DLL_EXPORT uint32_t LMS_ControlRead(LMScomms* port, uint8_t* buffer, const uint16_t bufLen) +{ + return port->Read(buffer, bufLen, 0); +} + + + +const int RX_BUFF_SZ (1020*1024/4); +uint32_t rx_buffer[RX_BUFF_SZ]; +uint64_t start_timestamp = 0;; +uint32_t wr_pos = 0; +uint32_t rd_pos = 0; + +void ReceivePackets() +{ + rxRunning.store(true); + uint32_t samplesCollected = 0; + + const int bufferSize = 4096;// 4096; + const int buffersCount = 32; // must be power of 2 + const int buffersCountMask = buffersCount - 1; + int handles[buffersCount]= {0}; + char buffers[buffersCount*bufferSize]={0}; + + struct sched_param sp; + sp.sched_priority = sched_get_priority_max(SCHED_FIFO); + if (pthread_setschedparam(pthread_self(),SCHED_FIFO,&sp)!=0) + { + printf("Shed prams failed\n"); + } + + //switch off Rx + uint16_t regVal = streamer.SPI_read(0x0005); + streamer.SPI_write(0x0005, regVal & ~0x6); + //USB FIFO reset + LMScomms::GenericPacket ctrPkt; + ctrPkt.cmd = CMD_USB_FIFO_RST; + ctrPkt.outBuffer.push_back(0x01); + usbPort.TransferPacket(ctrPkt); + ctrPkt.outBuffer[0] = 0x00; + usbPort.TransferPacket(ctrPkt); + + streamer.SPI_write(0x0005, regVal | 0x6); + + streamer.SPI_write(0x0001, 0x0001); + streamer.SPI_write(0x0007, 0x0000); + + for (int i = 0; i 0) + { + PacketLTE* pkt = (PacketLTE*)&buffers[bi*bufferSize]; + for(uint16_t sampleIndex = 0; sampleIndex < sizeof(pkt->samples)/sizeof(int16_t); sampleIndex++) + { + pkt->samples[sampleIndex] <<= 4; + pkt->samples[sampleIndex] >>= 4; + } + + rxBuffer.push_samples((complex16_t*)pkt->samples, 1020, pkt->counter, 100); + } + // Re-submit this request to keep the queue full + memset(&buffers[bi*bufferSize], 0, bufferSize); + handles[bi] = usbPort.BeginDataReading(&buffers[bi*bufferSize], bufferSize); + bi = (bi + 1) & buffersCountMask; + pthread_yield(); + } + + usbPort.AbortReading(); + for (int j = 0; jsamples)[index++]=(((uint32_t*)data)[i]& 0xFFF0FFF) | 0x1000; + + if (index == 1020) + { + pkt->counter = ts; + + if (bufferUsed[bi]) + { + if (usbPort.WaitForSending(handles[bi], 1000) == false) + return -1; + // Must always call FinishDataXfer to release memory of contexts[i] + long tempToSend = sizeof(PacketLTE); + usbPort.FinishDataSending(&buffers[bi*bufferSize], tempToSend, handles[bi]); + + bufferUsed[bi] = false; + } + handles[bi] = usbPort.BeginDataSending(&buffers[bi*bufferSize], sizeof(PacketLTE)); + bufferUsed[bi] = true; + bi = (bi + 1) & buffersCountMask; + pkt = (PacketLTE*)&buffers[bi*bufferSize]; + ts += 1020; + index = 0; + } + } +} + +vector PacketsBuffer(2048, PacketLTE()); +DLL_EXPORT uint32_t LMS_TRxRead(int16_t *buffer, const uint32_t samplesCount, const uint32_t antenna_id, uint64_t *timestamp, const uint32_t timeout_ms) +{ + if (usbPort.IsOpen() == false && opMode != -1) + return 0; + pthread_yield(); + uint32_t samplesPopped = rxBuffer.pop_samples((complex16_t*)buffer, samplesCount, timestamp, timeout_ms); + return samplesPopped; +} + + +DLL_EXPORT int LMS_RxStart() +{ + if (rxRunning.load()) + return 1; + if (usbPort.IsOpen() == false && opMode != -1) + return 1; + rxStop.store(false); + unsigned int bufSz = rxBuffer.GetInfo().size; + rxBuffer.Reset(bufSz); + rxThread = thread(ReceivePackets); + return 0; +} + +DLL_EXPORT int LMS_RxStop() +{ + if (rxRunning.load()) + { + if (rxThread.joinable()) + { + rxStop.store(true); + rxThread.join(); + } + rxStop.store(true); + } + return 0; +} diff --git a/targets/ARCH/LMSSDR/USERSPACE/LIB/lmsSDR/LMS_SDR.h b/targets/ARCH/LMSSDR/USERSPACE/LIB/lmsSDR/LMS_SDR.h new file mode 100644 index 0000000000..27a72e351a --- /dev/null +++ b/targets/ARCH/LMSSDR/USERSPACE/LIB/lmsSDR/LMS_SDR.h @@ -0,0 +1,143 @@ +/** +@author Lime Microsystems +@brief Interface for implementing SDR using Lime microsystems boards +*/ + +#ifndef LMS_SDR_INTERFACE_H +#define LMS_SDR_INTERFACE_H + +#include + +#ifdef __cplusplus +class LMScomms; +#else +typedef void LMScomms; +#endif + +#define BUILD_DLL +#ifndef __unix__ +#ifdef BUILD_DLL + #define DLL_EXPORT __declspec(dllexport) +#else + #define DLL_EXPORT __declspec(dllimport) +#endif +#else +#define DLL_EXPORT +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/** @brief Returns stats of internal buffers + @param RxBufSize Receiver buffer size in samples + @param RxBufFilled Number of samples currently in the receiver buffer + @param RxSamplingRate Approximate receiver sampling rate, calculated from incomming data + @param TxBufSize Transmitter buffer size in samples + @param TxBufFilled Number of samples currently in the transmitter buffer + @param TxSamplingRate Approximate transmitter sampling rate, calculated from incomming data +*/ +DLL_EXPORT void LMS_Stats(uint32_t *RxBufSize, uint32_t *RxBufFilled, uint32_t *RxSamplingRate, uint32_t *TxBufSize, uint32_t *TxBufFilled, uint32_t *TxSamplingRate); + +/** @brief Initializes internal memory for samples buffering to hardware + @param OperationMode samples transfering mode: 0-packets synchronized, 1-packets not synchronized + @param trxBuffersLength Rx and Tx internal buffers size in samples + @return 0 success, -1 failure + + Generally trxBuffersSamplesCount should be more than 65536 +*/ +DLL_EXPORT int LMS_Init(const int OperationMode, uint32_t trxBuffersLength); + +/** @brief Stops internal threads and frees internal buffers memory + @return 0 success, -1 failure +*/ +DLL_EXPORT int LMS_Destroy(); + +///@name Device connection +/** @return object for communicating over USB port +*/ +DLL_EXPORT LMScomms* LMS_GetUSBPort(); + +/** @return object for communicating over COM port +*/ +DLL_EXPORT LMScomms* LMS_GetCOMPort(); + +/** @brief Refreshes currently connected device list + @param port Communications port to update + @return number of devices connected +*/ +DLL_EXPORT int LMS_UpdateDeviceList(LMScomms* port); + +/** @brief Returns pointer to static null terminated c-string name of selected device + @param port Communications port object + @param deviceIndex index from communications port device list +*/ +DLL_EXPORT const char* LMS_GetDeviceName(LMScomms* port, unsigned int deviceIndex); + +/** @brief Connects to selected device on given port + @param port Communications port object + @param deviceIndex index from communications port device list + @return 0-success +*/ +DLL_EXPORT int LMS_DeviceOpen(LMScomms* port, const uint32_t deviceIndex); + +/** @brief Closes connection on given port + @param port Communications port to close +*/ +DLL_EXPORT void LMS_DeviceClose(LMScomms* port); +///@} + +///@name Communications +/** @brief Writes given data to control port + @param port Port for communications + @param buffer data to be written + @param bufLen buffer length in bytes + @return number of bytes written +*/ +DLL_EXPORT uint32_t LMS_ControlWrite(LMScomms* port, const uint8_t *buffer, const uint16_t bufLen); + +/** @brief Reads given data from SPI regiter + @param port Port for communications + @param buffer destination buffer for data + @param bufLen number of bytes to read + @return number of bytes read +*/ +DLL_EXPORT uint32_t LMS_ControlRead(LMScomms* port, uint8_t* buffer, const uint16_t bufLen); + +/** @brief Starts thread for samples receiving + @return 0-success +*/ +DLL_EXPORT int LMS_RxStart(); + +/** @brief Stops samples receiving thread + @return 0:success, 1:failed +*/ +DLL_EXPORT int LMS_RxStop(); + +/** @brief Adds given samples to transmitter buffer, to be sent at specified timestamp +@param buffer source array for interleaved values (IQIQIQ...), each value amplitude should be from -2048 to 2047 +@param samplesCount number of samples in buffer, 1 sample = 2 bytes I + 2 bytes Q +@param channel_id destination channel +@param timestamp timestamp when the first sample in buffer should be transmitted (used only in synchronized operating mode) +@param timeout_ms time amount in milliseconds to try adding samples +@return number of samples written +*/ +DLL_EXPORT uint32_t LMS_TRxWrite(const int16_t *buffer, const uint32_t samplesCount, const uint32_t channel_id, uint64_t timestamp); + +/** @brief Reads samples from receiver buffer +@param buffer destination array for interleaved values (IQIQIQ...), must be big enough to store requested number of samples, each value amplitude will be from -2048 to 2047 +@param samplesCount number of samples to read, 1 sample = 2 bytes I + 2 bytes Q +@param antenna_id source channel +@param timestamp returns timestamp of the first sample in the buffer (used only in synchronized operating mode) +@param timeout_ms time amount in milliseconds to try reading samples +@return number of samples read +*/ +DLL_EXPORT uint32_t LMS_TRxRead(int16_t *buffer, const uint32_t samplesCount, const uint32_t channel_id, uint64_t *timestamp, const uint32_t timeout_ms); + +///@} + +#ifdef __cplusplus +} //extern "C" +#endif + +#endif //LMS_SDR_INTERFACE_H diff --git a/targets/ARCH/LMSSDR/USERSPACE/LIB/lmsSDR/LMS_StreamBoard/CMakeLists.txt b/targets/ARCH/LMSSDR/USERSPACE/LIB/lmsSDR/LMS_StreamBoard/CMakeLists.txt new file mode 100644 index 0000000000..02e6bb5ab9 --- /dev/null +++ b/targets/ARCH/LMSSDR/USERSPACE/LIB/lmsSDR/LMS_StreamBoard/CMakeLists.txt @@ -0,0 +1,22 @@ +set(streamBoard_src_files + LMS_StreamBoard.cpp +) + +add_library(LMS_StreamBoard STATIC ${streamBoard_src_files}) +target_include_directories(LMS_StreamBoard PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) + +target_link_libraries(LMS_StreamBoard ConnectionManager) + +if(WIN32 AND ENABLE_USB_CONNECTION) + find_package(CyAPI REQUIRED) + LINK_DIRECTORIES(${CYAPI_LIBRARIES}) + include_directories(${CYAPI_INCLUDE_DIRS}) + set(CONNECTION_MANAGER_LIBS ${CYAPI_LIBRARIES} SetupAPI) + target_link_libraries(LMS_StreamBoard ${CONNECTION_MANAGER_LIBS}) +endif() +if(UNIX AND ENABLE_USB_CONNECTION) + set(CONNECTION_MANAGER_LIBS usb-1.0 -lpthread) + target_link_libraries(LMS_StreamBoard ${CONNECTION_MANAGER_LIBS}) +endif() + + diff --git a/targets/ARCH/LMSSDR/USERSPACE/LIB/lmsSDR/LMS_StreamBoard/LMS_StreamBoard.cpp b/targets/ARCH/LMSSDR/USERSPACE/LIB/lmsSDR/LMS_StreamBoard/LMS_StreamBoard.cpp new file mode 100644 index 0000000000..da9e4a7b8e --- /dev/null +++ b/targets/ARCH/LMSSDR/USERSPACE/LIB/lmsSDR/LMS_StreamBoard/LMS_StreamBoard.cpp @@ -0,0 +1,770 @@ +#include "LMS_StreamBoard.h" +#include "lmsComms.h" +#include "lms7002_defines.h" +#include +#include + +/** @brief Configures Stream board FPGA clocks + @param serPort Communications port to send data + @param fOutTx_MHz transmitter frequency in MHz + @param fOutRx_MHz receiver frequency in MHz + @param phaseShift_deg IQ phase shift in degrees + @return 0-success, other-failure +*/ +LMS_StreamBoard::Status LMS_StreamBoard::ConfigurePLL(LMScomms *serPort, const float fOutTx_MHz, const float fOutRx_MHz, const float phaseShift_deg) +{ + assert(serPort != nullptr); + if (serPort == NULL) + return FAILURE; + if (serPort->IsOpen() == false) + return FAILURE; + const float vcoLimits_MHz[2] = { 600, 1300 }; + int M, C; + const short bufSize = 64; + + float fOut_MHz = fOutTx_MHz; + float coef = 0.8*vcoLimits_MHz[1] / fOut_MHz; + M = C = (int)coef; + int chigh = (((int)coef) / 2) + ((int)(coef) % 2); + int clow = ((int)coef) / 2; + + LMScomms::GenericPacket pkt; + pkt.cmd = CMD_BRDSPI_WR; + + if (fOut_MHz*M > vcoLimits_MHz[0] && fOut_MHz*M < vcoLimits_MHz[1]) + { + pkt.outBuffer.push_back(0x00); + pkt.outBuffer.push_back(0x0F); + pkt.outBuffer.push_back(0x15); //c4-c2_bypassed + pkt.outBuffer.push_back(0x01 | ((M % 2 != 0) ? 0x08 : 0x00) | ((C % 2 != 0) ? 0x20 : 0x00)); //N_bypassed + + pkt.outBuffer.push_back(0x00); + pkt.outBuffer.push_back(0x08); + pkt.outBuffer.push_back(1); //N_high_cnt + pkt.outBuffer.push_back(1);//N_low_cnt + pkt.outBuffer.push_back(0x00); + pkt.outBuffer.push_back(0x09); + pkt.outBuffer.push_back(chigh); //M_high_cnt + pkt.outBuffer.push_back(clow); //M_low_cnt + for (int i = 0; i <= 1; ++i) + { + pkt.outBuffer.push_back(0x00); + pkt.outBuffer.push_back(0x0A + i); + pkt.outBuffer.push_back(chigh); //cX_high_cnt + pkt.outBuffer.push_back(clow); //cX_low_cnt + } + + float Fstep_us = 1 / (8 * fOutTx_MHz*C); + float Fstep_deg = (360 * Fstep_us) / (1 / fOutTx_MHz); + short nSteps = phaseShift_deg / Fstep_deg; + unsigned short reg2 = 0x0400 | (nSteps & 0x3FF); + pkt.outBuffer.push_back(0x00); + pkt.outBuffer.push_back(0x02); + pkt.outBuffer.push_back((reg2 >> 8)); + pkt.outBuffer.push_back(reg2); //phase + + pkt.outBuffer.push_back(0x00); + pkt.outBuffer.push_back(0x03); + pkt.outBuffer.push_back(0x00); + pkt.outBuffer.push_back(0x01); + + pkt.outBuffer.push_back(0x00); + pkt.outBuffer.push_back(0x03); + pkt.outBuffer.push_back(0x00); + pkt.outBuffer.push_back(0x00); + + reg2 = reg2 | 0x800; + pkt.outBuffer.push_back(0x00); + pkt.outBuffer.push_back(0x02); + pkt.outBuffer.push_back((reg2 >> 8)); + pkt.outBuffer.push_back(reg2); + + if(serPort->TransferPacket(pkt) != LMScomms::TRANSFER_SUCCESS || pkt.status != STATUS_COMPLETED_CMD) + return FAILURE; + } + else + return FAILURE; + + fOut_MHz = fOutRx_MHz; + coef = 0.8*vcoLimits_MHz[1] / fOut_MHz; + M = C = (int)coef; + chigh = (((int)coef) / 2) + ((int)(coef) % 2); + clow = ((int)coef) / 2; + if (fOut_MHz*M > vcoLimits_MHz[0] && fOut_MHz*M < vcoLimits_MHz[1]) + { + short index = 0; + pkt.outBuffer.clear(); + pkt.outBuffer.push_back(0x00); + pkt.outBuffer.push_back(0x0F); + pkt.outBuffer.push_back(0x15); //c4-c2_bypassed + pkt.outBuffer.push_back(0x41 | ((M % 2 != 0) ? 0x08 : 0x00) | ((C % 2 != 0) ? 0x20 : 0x00)); //N_bypassed, c1 bypassed + + pkt.outBuffer.push_back(0x00); + pkt.outBuffer.push_back(0x08); + pkt.outBuffer.push_back(1); //N_high_cnt + pkt.outBuffer.push_back(1);//N_low_cnt + pkt.outBuffer.push_back(0x00); + pkt.outBuffer.push_back(0x09); + pkt.outBuffer.push_back(chigh); //M_high_cnt + pkt.outBuffer.push_back(clow); //M_low_cnt + for (int i = 0; i <= 1; ++i) + { + pkt.outBuffer.push_back(0x00); + pkt.outBuffer.push_back(0x0A + i); + pkt.outBuffer.push_back(chigh); //cX_high_cnt + pkt.outBuffer.push_back(clow); //cX_low_cnt + } + + pkt.outBuffer.push_back(0x00); + pkt.outBuffer.push_back(0x03); + pkt.outBuffer.push_back(0x00); + pkt.outBuffer.push_back(0x02); + + pkt.outBuffer.push_back(0x00); + pkt.outBuffer.push_back(0x03); + pkt.outBuffer.push_back(0x00); + pkt.outBuffer.push_back(0x00); + + if (serPort->TransferPacket(pkt) != LMScomms::TRANSFER_SUCCESS || pkt.status != STATUS_COMPLETED_CMD) + return FAILURE; + } + else + return FAILURE; + return SUCCESS; +} + +/** @brief Captures IQ samples from Stream board, this is blocking function, it blocks until desired frames count is captured + @param isamples destination array for I samples, must be big enough to contain samplesCount + @param qsamples destination array for Q samples, must be big enough to contain samplesCount + @param framesCount number of IQ frames to capture + @param frameStart frame start indicator 0 or 1 + @return 0-success, other-failure +*/ +LMS_StreamBoard::Status LMS_StreamBoard::CaptureIQSamples(LMScomms *dataPort, int16_t *isamples, int16_t *qsamples, const uint32_t framesCount, const bool frameStart) +{ + assert(dataPort != nullptr); + if (dataPort == NULL) + return FAILURE; + if (dataPort->IsOpen() == false) + return FAILURE; + + int16_t sample_value; + const uint32_t bufSize = framesCount * 2 * sizeof(uint16_t); + char *buffer = new char[bufSize]; + if (buffer == 0) + { +#ifndef NDEBUG + std::cout << "Failed to allocate memory for samples buffer" << std::endl; +#endif + return FAILURE; + } + memset(buffer, 0, bufSize); + + LMScomms::GenericPacket pkt; + pkt.cmd = CMD_BRDSPI_RD; + pkt.outBuffer.push_back(0x00); + pkt.outBuffer.push_back(0x05); + dataPort->TransferPacket(pkt); + if (pkt.status != STATUS_COMPLETED_CMD) + return FAILURE; + + uint16_t regVal = (pkt.inBuffer[2] * 256) + pkt.inBuffer[3]; + pkt.cmd = CMD_BRDSPI_WR; + pkt.outBuffer.clear(); + pkt.outBuffer.push_back(0x00); + pkt.outBuffer.push_back(0x05); + pkt.outBuffer.push_back(0); + pkt.outBuffer.push_back(regVal | 0x4); + dataPort->TransferPacket(pkt); + if (pkt.status != STATUS_COMPLETED_CMD) + return FAILURE; + + int bytesReceived = 0; + for(int i = 0; i<3; ++i) + bytesReceived = dataPort->ReadStream(buffer, bufSize, 5000); + if (bytesReceived > 0) + { + bool iqSelect = false; + int16_t frameCounter = 0; + for (uint32_t b = 0; b < bufSize;) + { + sample_value = buffer[b++] & 0xFF; + sample_value |= (buffer[b++] & 0x0F) << 8; + sample_value = sample_value << 4; //shift left then right to fill sign bits + sample_value = sample_value >> 4; + if (iqSelect == false) + isamples[frameCounter] = sample_value; + else + qsamples[frameCounter] = sample_value; + frameCounter += iqSelect; + iqSelect = !iqSelect; + } + } + pkt.cmd = CMD_BRDSPI_RD; + pkt.outBuffer.clear(); + pkt.outBuffer.push_back(0x00); + pkt.outBuffer.push_back(0x01); + pkt.outBuffer.push_back(0x00); + pkt.outBuffer.push_back(0x05); + dataPort->TransferPacket(pkt); + + regVal = (pkt.inBuffer[2] * 256) + pkt.inBuffer[3]; + pkt.cmd = CMD_BRDSPI_WR; + pkt.outBuffer.clear(); + pkt.outBuffer.push_back(0x00); + pkt.outBuffer.push_back(0x05); + pkt.outBuffer.push_back(0); + pkt.outBuffer.push_back(regVal & ~0x4); + dataPort->TransferPacket(pkt); + + delete[] buffer; + return SUCCESS; +} + +/** @brief Blocking operation to upload IQ samples to Stream board RAM + @param serPort port to use for communication + @param isamples I channel samples + @param qsamples Q channel samples + @param framesCount number of samples in arrays + @return 0-success, other-failure +*/ +LMS_StreamBoard::Status LMS_StreamBoard::UploadIQSamples(LMScomms* serPort, int16_t *isamples, int16_t *qsamples, const uint32_t framesCount) +{ + int bufferSize = framesCount * 2; + uint16_t *buffer = new uint16_t[bufferSize]; + memset(buffer, 0, bufferSize*sizeof(uint16_t)); + int bufPos = 0; + for (unsigned i = 0; iTransferPacket(pkt); + pkt.cmd = CMD_BRDSPI_WR; + pkt.outBuffer.clear(); + pkt.outBuffer.push_back(0x00); + pkt.outBuffer.push_back(0x05); + pkt.outBuffer.push_back(pkt.inBuffer[2]); + pkt.outBuffer.push_back(pkt.inBuffer[3] & ~0x7); + serPort->TransferPacket(pkt); + + while (sent packetSize ? packetSize : outLen - sent; + long toSend = toSendBytes; + int context = serPort->BeginDataSending(&outBuf[sent], toSend); + if (serPort->WaitForSending(context, 5000) == false) + { + success = false; + serPort->FinishDataSending(&outBuf[sent], toSend, context); + break; + } + sent += serPort->FinishDataSending(&outBuf[sent], toSend, context); + } + + pkt.cmd = CMD_BRDSPI_RD; + pkt.outBuffer.push_back(0x00); + pkt.outBuffer.push_back(0x05); + + serPort->TransferPacket(pkt); + pkt.cmd = CMD_BRDSPI_WR; + pkt.outBuffer.clear(); + pkt.outBuffer.push_back(0x00); + pkt.outBuffer.push_back(0x05); + pkt.outBuffer.push_back(pkt.inBuffer[2]); + pkt.outBuffer.push_back(pkt.inBuffer[3] | 0x3); + serPort->TransferPacket(pkt); + return success ? SUCCESS : FAILURE; +} + +LMS_StreamBoard::LMS_StreamBoard(LMScomms* dataPort) +{ + mRxFrameStart.store(true); + mDataPort = dataPort; + mRxFIFO = new LMS_StreamBoard_FIFO(1024*4); + mTxFIFO = new LMS_StreamBoard_FIFO(1024*4); + mStreamRunning.store(false); + mTxCyclicRunning.store(false); +} + +LMS_StreamBoard::~LMS_StreamBoard() +{ + StopReceiving(); + delete mRxFIFO; + delete mTxFIFO; +} + +/** @brief Crates threads for packets receiving, processing and transmitting +*/ +LMS_StreamBoard::Status LMS_StreamBoard::StartReceiving(unsigned int fftSize) +{ + if (mStreamRunning.load() == true) + return FAILURE; + if (mDataPort->IsOpen() == false) + return FAILURE; + mRxFIFO->reset(); + stopRx.store(false); + threadRx = std::thread(ReceivePackets, this); + mStreamRunning.store(true); + return SUCCESS; +} + +/** @brief Stops receiving, processing and transmitting threads +*/ +LMS_StreamBoard::Status LMS_StreamBoard::StopReceiving() +{ + if (mStreamRunning.load() == false) + return FAILURE; + stopTx.store(true); + stopRx.store(true); + threadRx.join(); + mStreamRunning.store(false); + return SUCCESS; +} + +/** @brief Function dedicated for receiving data samples from board +*/ +void LMS_StreamBoard::ReceivePackets(LMS_StreamBoard* pthis) +{ + SamplesPacket pkt; + int samplesCollected = 0; + auto t1 = chrono::high_resolution_clock::now(); + auto t2 = chrono::high_resolution_clock::now(); + + const int buffer_size = 65536;// 4096; + const int buffers_count = 16; // must be power of 2 + const int buffers_count_mask = buffers_count - 1; + int handles[buffers_count]; + memset(handles, 0, sizeof(int)*buffers_count); + char *buffers = NULL; + buffers = new char[buffers_count*buffer_size]; + if (buffers == 0) + { + printf("error allocating buffers\n"); + return; + } + memset(buffers, 0, buffers_count*buffer_size); + + //USB FIFO reset + LMScomms::GenericPacket ctrPkt; + ctrPkt.cmd = CMD_USB_FIFO_RST; + ctrPkt.outBuffer.push_back(0x01); + pthis->mDataPort->TransferPacket(ctrPkt); + ctrPkt.outBuffer[0] = 0x00; + pthis->mDataPort->TransferPacket(ctrPkt); + + uint16_t regVal = pthis->SPI_read(0x0005); + pthis->SPI_write(0x0005, regVal | 0x4); + + for (int i = 0; imDataPort->BeginDataReading(&buffers[i*buffer_size], buffer_size); + + int bi = 0; + int packetsReceived = 0; + unsigned long BytesReceived = 0; + int m_bufferFailures = 0; + short sample; + + bool frameStart = pthis->mRxFrameStart.load(); + while (pthis->stopRx.load() == false) + { + if (pthis->mDataPort->WaitForReading(handles[bi], 1000) == false) + ++m_bufferFailures; + + long bytesToRead = buffer_size; + long bytesReceived = pthis->mDataPort->FinishDataReading(&buffers[bi*buffer_size], bytesToRead, handles[bi]); + if (bytesReceived > 0) + { + ++packetsReceived; + BytesReceived += bytesReceived; + char* bufStart = &buffers[bi*buffer_size]; + + for (int p = 0; p < bytesReceived; p+=2) + { + if (samplesCollected == 0) //find frame start + { + int frameStartOffset = FindFrameStart(&bufStart[p], bytesReceived-p, frameStart); + if (frameStartOffset < 0) + break; //frame start was not found, move on to next buffer + p += frameStartOffset; + } + sample = (bufStart[p+1] & 0x0F); + sample = sample << 8; + sample |= (bufStart[p] & 0xFF); + sample = sample << 4; + sample = sample >> 4; + pkt.iqdata[samplesCollected] = sample; + ++samplesCollected; + if (pkt.samplesCount == samplesCollected) + { + samplesCollected = 0; + if (pthis->mRxFIFO->push_back(pkt, 200) == false) + ++m_bufferFailures; + } + } + } + else + { + ++m_bufferFailures; + } + + t2 = chrono::high_resolution_clock::now(); + long timePeriod = std::chrono::duration_cast(t2 - t1).count(); + if (timePeriod >= 1000) + { + // periodically update frame start, user might change it during operation + frameStart = pthis->mRxFrameStart.load(); + float m_dataRate = 1000.0*BytesReceived / timePeriod; + t1 = t2; + BytesReceived = 0; + LMS_StreamBoard_FIFO::Status rxstats = pthis->mRxFIFO->GetStatus(); + + pthis->mRxDataRate.store(m_dataRate); + pthis->mRxFIFOfilled.store(100.0*rxstats.filledElements / rxstats.maxElements); +#ifndef NDEBUG + printf("Rx: %.1f%% \t rate: %.0f kB/s failures:%i\n", 100.0*rxstats.filledElements / rxstats.maxElements, m_dataRate / 1000.0, m_bufferFailures); +#endif + m_bufferFailures = 0; + } + + // Re-submit this request to keep the queue full + memset(&buffers[bi*buffer_size], 0, buffer_size); + handles[bi] = pthis->mDataPort->BeginDataReading(&buffers[bi*buffer_size], buffer_size); + bi = (bi + 1) & buffers_count_mask; + } + pthis->mDataPort->AbortReading(); + for (int j = 0; jmDataPort->WaitForReading(handles[j], 1000); + pthis->mDataPort->FinishDataReading(&buffers[j*buffer_size], bytesToRead, handles[j]); + } + + regVal = pthis->SPI_read(0x0005); + pthis->SPI_write(0x0005, regVal & ~0x4); + + delete[] buffers; +#ifndef NDEBUG + printf("Rx finished\n"); +#endif +} + +/** @brief Function dedicated for transmitting samples to board +*/ +void LMS_StreamBoard::TransmitPackets(LMS_StreamBoard* pthis) +{ + const int packetsToBatch = 16; + const int buffer_size = sizeof(SamplesPacket)*packetsToBatch; + const int buffers_count = 16; // must be power of 2 + const int buffers_count_mask = buffers_count - 1; + int handles[buffers_count]; + memset(handles, 0, sizeof(int)*buffers_count); + char *buffers = NULL; + buffers = new char[buffers_count*buffer_size]; + if (buffers == 0) + { + printf("error allocating buffers\n"); + } + memset(buffers, 0, buffers_count*buffer_size); + bool *bufferUsed = new bool[buffers_count]; + memset(bufferUsed, 0, sizeof(bool)*buffers_count); + + int bi = 0; //buffer index + + SamplesPacket* pkt = new SamplesPacket[packetsToBatch]; + int m_bufferFailures = 0; + long bytesSent = 0; + auto t1 = chrono::high_resolution_clock::now(); + auto t2 = chrono::high_resolution_clock::now(); + long totalBytesSent = 0; + + unsigned long outputCounter = 0; + + while (pthis->stopTx.load() == false) + { + for (int i = 0; i < packetsToBatch; ++i) + { + if (pthis->mTxFIFO->pop_front(&pkt[i], 200) == false) + { + printf("Error popping from TX\n"); + if (pthis->stopTx.load() == false) + break; + continue; + } + } + //wait for desired slot buffer to be transferred + if (bufferUsed[bi]) + { + if (pthis->mDataPort->WaitForSending(handles[bi], 1000) == false) + { + ++m_bufferFailures; + } + // Must always call FinishDataXfer to release memory of contexts[i] + long bytesToSend = buffer_size; + bytesSent = pthis->mDataPort->FinishDataSending(&buffers[bi*buffer_size], bytesToSend, handles[bi]); + if (bytesSent > 0) + totalBytesSent += bytesSent; + else + ++m_bufferFailures; + bufferUsed[bi] = false; + } + + memcpy(&buffers[bi*buffer_size], &pkt[0], sizeof(SamplesPacket)*packetsToBatch); + handles[bi] = pthis->mDataPort->BeginDataSending(&buffers[bi*buffer_size], buffer_size); + bufferUsed[bi] = true; + + t2 = chrono::high_resolution_clock::now(); + long timePeriod = std::chrono::duration_cast(t2 - t1).count(); + if (timePeriod >= 1000) + { + float m_dataRate = 1000.0*totalBytesSent / timePeriod; + t1 = t2; + totalBytesSent = 0; +#ifndef NDEBUG + cout << "Tx rate: " << m_dataRate / 1000 << " kB/s\t failures: " << m_bufferFailures << endl; +#endif + LMS_StreamBoard_FIFO::Status txstats = pthis->mTxFIFO->GetStatus(); + pthis->mTxDataRate.store(m_dataRate); + pthis->mTxFIFOfilled.store(100.0*txstats.filledElements / txstats.maxElements); + m_bufferFailures = 0; + } + bi = (bi + 1) & buffers_count_mask; + } + + // Wait for all the queued requests to be cancelled + pthis->mDataPort->AbortSending(); + for (int j = 0; jmDataPort->WaitForSending(handles[j], 1000); + pthis->mDataPort->FinishDataSending(&buffers[j*buffer_size], bytesToSend, handles[j]); + } + } + + delete[] buffers; + delete[] bufferUsed; + delete[] pkt; +#ifndef NDEBUG + printf("Tx finished\n"); +#endif +} + +/** @brief Returns current data state for user interface +*/ +LMS_StreamBoard::DataToGUI LMS_StreamBoard::GetIncomingData() +{ + std::unique_lock lck(mLockIncomingPacket); + return mIncomingPacket; +} + +/** @brief Returns data rate info and Tx Rx FIFO fill percentage +*/ +LMS_StreamBoard::ProgressStats LMS_StreamBoard::GetStats() +{ + ProgressStats stats; + stats.RxRate_Bps = mRxDataRate.load(); + stats.TxRate_Bps = mTxDataRate.load(); + stats.RxFIFOfilled = mRxFIFOfilled.load(); + stats.TxFIFOfilled = mTxFIFOfilled.load(); + return stats; +} + +/** @brief Helper function to write board spi regiters + @param address spi address + @param data register value +*/ +LMS_StreamBoard::Status LMS_StreamBoard::SPI_write(uint16_t address, uint16_t data) +{ + assert(mDataPort != nullptr); + LMScomms::GenericPacket ctrPkt; + ctrPkt.cmd = CMD_BRDSPI_WR; + ctrPkt.outBuffer.push_back((address >> 8) & 0xFF); + ctrPkt.outBuffer.push_back(address & 0xFF); + ctrPkt.outBuffer.push_back((data >> 8) & 0xFF); + ctrPkt.outBuffer.push_back(data & 0xFF); + mDataPort->TransferPacket(ctrPkt); + return ctrPkt.status == 1 ? SUCCESS : FAILURE; +} + +/** @brief Helper function to read board spi registers + @param address spi address + @return register value +*/ +uint16_t LMS_StreamBoard::SPI_read(uint16_t address) +{ + assert(mDataPort != nullptr); + LMScomms::GenericPacket ctrPkt; + ctrPkt.cmd = CMD_BRDSPI_RD; + ctrPkt.outBuffer.push_back((address >> 8) & 0xFF); + ctrPkt.outBuffer.push_back(address & 0xFF); + mDataPort->TransferPacket(ctrPkt); + if (ctrPkt.status == STATUS_COMPLETED_CMD && ctrPkt.inBuffer.size() >= 4) + return ctrPkt.inBuffer[2] * 256 + ctrPkt.inBuffer[3]; + else + return 0; +} + +/** @brief Changes which frame start to look for when receiving data +*/ +void LMS_StreamBoard::SetRxFrameStart(const bool startValue) +{ + mRxFrameStart.store(startValue); +} + +/** @brief Searches for frame start index in given buffer + @return frameStart index in buffer, -1 if frame start was not found + Frame start indicator is 13th bit inside each I and Q sample +*/ +int LMS_StreamBoard::FindFrameStart(const char* buffer, const int bufLen, const bool frameStart) +{ + int startIndex = -1; + for (int i = 0; i < bufLen; i+=2) + if ((buffer[i+1] & 0x10)>0 == frameStart) + { + startIndex = i; + break; + } + return startIndex; +} + +/** @brief Starts a thread for continuous cyclic transmitting of given samples + @param isamples I channel samples + @param qsamples Q channel samples + @param framesCount number of samples in given arrays + @return 0:success, other:failure +*/ +LMS_StreamBoard::Status LMS_StreamBoard::StartCyclicTransmitting(const int16_t* isamples, const int16_t* qsamples, uint32_t framesCount) +{ + if (mDataPort->IsOpen() == false) + return FAILURE; + + stopTxCyclic.store(false); + threadTxCyclic = std::thread([](LMS_StreamBoard* pthis) + { + const int buffer_size = 65536; + const int buffers_count = 16; // must be power of 2 + const int buffers_count_mask = buffers_count - 1; + int handles[buffers_count]; + memset(handles, 0, sizeof(int)*buffers_count); + char *buffers = NULL; + buffers = new char[buffers_count*buffer_size]; + if (buffers == 0) + { + printf("error allocating buffers\n"); + return 0; + } + memset(buffers, 0, buffers_count*buffer_size); + + //timers for data rate calculation + auto t1 = chrono::high_resolution_clock::now(); + auto t2 = chrono::high_resolution_clock::now(); + + int bi = 0; //buffer index + + //setup output data + int dataIndex = 0; + for (int i = 0; i < buffers_count; ++i) + { + for (int j = 0; j < buffer_size; ++j) + { + buffers[i*buffer_size + j] = pthis->mCyclicTransmittingSourceData[dataIndex]; + ++dataIndex; + if (dataIndex > pthis->mCyclicTransmittingSourceData.size()) + dataIndex = 0; + } + } + + for (int i = 0; i < buffers_count; ++i) + handles[i] = pthis->mDataPort->BeginDataSending(&buffers[i*buffer_size], buffer_size); + + int m_bufferFailures = 0; + int bytesSent = 0; + int totalBytesSent = 0; + int sleepTime = 200; + while (pthis->stopTxCyclic.load() != true) + { + if (pthis->mDataPort->WaitForSending(handles[bi], 1000) == false) + { + ++m_bufferFailures; + } + long bytesToSend = buffer_size; + bytesSent = pthis->mDataPort->FinishDataSending(&buffers[bi*buffer_size], bytesToSend, handles[bi]); + if (bytesSent > 0) + totalBytesSent += bytesSent; + else + { + ++m_bufferFailures; + } + + t2 = chrono::high_resolution_clock::now(); + long timePeriod = std::chrono::duration_cast(t2 - t1).count(); + if (timePeriod >= 1000) + { + pthis->mTxDataRate.store(1000.0*totalBytesSent / timePeriod); + t1 = t2; + totalBytesSent = 0; +#ifndef NDEBUG + printf("Upload rate: %f\t failures:%li\n", 1000.0*totalBytesSent / timePeriod, m_bufferFailures); +#endif + m_bufferFailures = 0; + } + + //fill up next buffer + for (int j = 0; j < buffer_size; ++j) + { + buffers[bi*buffer_size + j] = pthis->mCyclicTransmittingSourceData[dataIndex]; + ++dataIndex; + if (dataIndex >= pthis->mCyclicTransmittingSourceData.size()) + dataIndex = 0; + } + + // Re-submit this request to keep the queue full + handles[bi] = pthis->mDataPort->BeginDataSending(&buffers[bi*buffer_size], buffer_size); + bi = (bi + 1) & buffers_count_mask; + } + + // Wait for all the queued requests to be cancelled + pthis->mDataPort->AbortSending(); + for (int j = 0; j < buffers_count; j++) + { + long bytesToSend = buffer_size; + pthis->mDataPort->WaitForSending(handles[j], 1000); + pthis->mDataPort->FinishDataSending(&buffers[j*buffer_size], bytesToSend, handles[j]); + } +#ifndef NDEBUG + printf("Cyclic transmitting FULLY STOPPED\n"); +#endif + delete[] buffers; + return 0; + }, this); + mTxCyclicRunning.store(true); + + return LMS_StreamBoard::SUCCESS; +} + +/** @brief Stops cyclic transmitting thread +*/ +LMS_StreamBoard::Status LMS_StreamBoard::StopCyclicTransmitting() +{ + stopTxCyclic.store(true); + if (mTxCyclicRunning.load() == true) + { + threadTxCyclic.join(); + mTxCyclicRunning.store(false); + } + return LMS_StreamBoard::SUCCESS; +} diff --git a/targets/ARCH/LMSSDR/USERSPACE/LIB/lmsSDR/LMS_StreamBoard/LMS_StreamBoard.h b/targets/ARCH/LMSSDR/USERSPACE/LIB/lmsSDR/LMS_StreamBoard/LMS_StreamBoard.h new file mode 100644 index 0000000000..99b3636336 --- /dev/null +++ b/targets/ARCH/LMSSDR/USERSPACE/LIB/lmsSDR/LMS_StreamBoard/LMS_StreamBoard.h @@ -0,0 +1,107 @@ +#ifndef STREAM_BOARD_API_H +#define STREAM_BOARD_API_H + +#include +#include +#include +#include +#include "LMS_StreamBoard_FIFO.h" + +class LMScomms; + +class LMS_StreamBoard +{ +public: + struct SamplesPacket + { + public: + SamplesPacket() : channel(0) + {} + ~SamplesPacket() + {} + + SamplesPacket& operator=(const SamplesPacket& obj) + { + memcpy(this->iqdata, obj.iqdata, sizeof(float)*samplesCount); + this->channel = obj.channel; + return *this; + } + const static int samplesCount = 32768; + float iqdata[samplesCount]; + int channel; + }; + + + enum Status + { + SUCCESS, + FAILURE, + }; + + static Status CaptureIQSamples(LMScomms* serPort, int16_t *isamples, int16_t *qsamples, uint32_t framesCount, bool frameStart); + static Status UploadIQSamples(LMScomms* serPort, int16_t *isamples, int16_t *qsamples, uint32_t framesCount); + static Status ConfigurePLL(LMScomms *serPort, const float fOutTx_MHz, const float fOutRx_MHz, const float phaseShift_deg); + + struct DataToGUI + { + std::vector samplesI; + std::vector samplesQ; + std::vector fftBins_dbFS; + float nyquist_MHz; + }; + + struct ProgressStats + { + float RxRate_Bps; + float TxRate_Bps; + float RxFIFOfilled; + float TxFIFOfilled; + }; + + LMS_StreamBoard(LMScomms* dataPort); + virtual ~LMS_StreamBoard(); + + void SetRxFrameStart(const bool startValue); + virtual Status StartReceiving(unsigned int fftSize); + virtual Status StopReceiving(); + + virtual Status StartCyclicTransmitting(const int16_t* isamples, const int16_t* qsamples, uint32_t framesCount); + virtual Status StopCyclicTransmitting(); + + DataToGUI GetIncomingData(); + ProgressStats GetStats(); + + Status SPI_write(uint16_t address, uint16_t data); + uint16_t SPI_read(uint16_t address); +protected: + static int FindFrameStart(const char* buffer, const int bufLen, const bool frameStart); + std::mutex mLockIncomingPacket; + DataToGUI mIncomingPacket; + + LMS_StreamBoard_FIFO *mRxFIFO; + LMS_StreamBoard_FIFO *mTxFIFO; + + static void ReceivePackets(LMS_StreamBoard* pthis); + static void TransmitPackets(LMS_StreamBoard* pthis); + + std::atomic_bool mRxFrameStart; + std::atomic_bool mStreamRunning; + std::atomic_bool stopRx; + std::atomic_bool stopTx; + + std::thread threadRx; + std::thread threadTx; + LMScomms* mDataPort; + + std::atomic mRxDataRate; + std::atomic mTxDataRate; + std::atomic mRxFIFOfilled; + std::atomic mTxFIFOfilled; + + std::vector mCyclicTransmittingSourceData; + std::atomic_bool mTxCyclicRunning; + std::thread threadTxCyclic; + std::atomic_bool stopTxCyclic; +}; +#endif + diff --git a/targets/ARCH/LMSSDR/USERSPACE/LIB/lmsSDR/LMS_StreamBoard/LMS_StreamBoard_FIFO.h b/targets/ARCH/LMSSDR/USERSPACE/LIB/lmsSDR/LMS_StreamBoard/LMS_StreamBoard_FIFO.h new file mode 100644 index 0000000000..833f7a37c0 --- /dev/null +++ b/targets/ARCH/LMSSDR/USERSPACE/LIB/lmsSDR/LMS_StreamBoard/LMS_StreamBoard_FIFO.h @@ -0,0 +1,122 @@ +/** +@file LMS_StreamBoard_FIFO.h +@author Lime Microsystems (www.limemicro.com) +@brief blocking FIFO for packets storing +*/ + +#ifndef LMS_STREAMBOARD_FIFO_H +#define LMS_STREAMBOARD_FIFO_H + +#include +#include +#include +#include +#include +#include +#include + +template +class LMS_StreamBoard_FIFO +{ +private: + LMS_StreamBoard_FIFO(){}; +public: + struct Status + { + uint32_t maxElements; + uint32_t filledElements; + uint32_t head; + uint32_t tail; + }; + + LMS_StreamBoard_FIFO(uint64_t FIFO_length) + { + mHead = 0; + mTail = 0; + mElements.resize(FIFO_length); + mElementsFilled = 0; + } + + ~LMS_StreamBoard_FIFO() + { + + } + + /** @brief Copies given src element to queue. + @param src Source data + @return true if element was inserted + + Copies element to queue. This function blocks until element is copied to + queue or certain amount of time has passed. + */ + bool push_back(const T &src, unsigned int timeout_ms = 200) + { + std::unique_lock lck(mElementsLock); + while (mElementsFilled == mElements.size()) + { + if (canWrite.wait_for(lck, std::chrono::milliseconds(timeout_ms)) == std::cv_status::timeout) + return false; + } + memcpy(&mElements[mTail], &src, sizeof(T)); + mTail = (mTail+1) % mElements.size(); + ++mElementsFilled; + canRead.notify_one(); + return true; + } + + /** @brief Copies and removes first element from queue to dest. + @param dest destination container for data + @return true if element was copied + Copies element from queue to destination and then removes it. + This function blocks until element is returned, or certain amount of time + has passed. + */ + bool pop_front(T *dest, unsigned int timeout_ms = 200) + { + assert(dest != nullptr); + std::unique_lock lck(mElementsLock); + while (mElementsFilled == 0) + { + if (canRead.wait_for(lck, std::chrono::milliseconds(timeout_ms)) == std::cv_status::timeout) + return false; + } + if (mElementsFilled == 0) + return false; + *dest = mElements[mHead]; + memcpy(dest, &mElements[mHead], sizeof(T)); + mHead = (mHead + 1) % mElements.size(); + --mElementsFilled; + canWrite.notify_one(); + return true; + } + void reset() + { + std::unique_lock lck(mElementsLock); + mElementsFilled = 0; + mHead = 0; + mTail = 0; + } + + Status GetStatus() + { + Status stats; + std::unique_lock lck(mElementsLock); + stats.maxElements = mElements.size(); + stats.filledElements = mElementsFilled; + stats.head = mHead; + stats.tail = mTail; + return stats; + }; + +protected: + uint32_t mHead; //reading pos + uint32_t mTail; //writing pos + uint32_t mElementsFilled; + + std::mutex mElementsLock; // condition variable for critical section + std::vector mElements; + std::condition_variable canWrite; + std::condition_variable canRead; +}; + +#endif // LMS_STREAMBOARD_FIFO_H diff --git a/targets/ARCH/LMSSDR/USERSPACE/LIB/lmsSDR/LMS_StreamBoard/lms7002_defines.h b/targets/ARCH/LMSSDR/USERSPACE/LIB/lmsSDR/LMS_StreamBoard/lms7002_defines.h new file mode 100644 index 0000000000..c098dfe965 --- /dev/null +++ b/targets/ARCH/LMSSDR/USERSPACE/LIB/lmsSDR/LMS_StreamBoard/lms7002_defines.h @@ -0,0 +1,215 @@ +/** +@file lms7002_defines.h +@author Lime Microsystems +@brief enumerations of available LMS7002M commands and statuses +*/ +#pragma once + +const int LMS_RST_DEACTIVATE = 0; +const int LMS_RST_ACTIVATE = 1; +const int LMS_RST_PULSE = 2; + +enum eLMS_DEV +{ + LMS_DEV_UNKNOWN, + LMS_DEV_EVB6, + LMS_DEV_DIGIGREEN, + LMS_DEV_DIGIRED, + LMS_DEV_EVB7, + LMS_DEV_ZIPPER, + LMS_DEV_SOCKETBOARD, + LMS_DEV_EVB7V2, + LMS_DEV_STREAM, + LMS_DEV_NOVENA, + LMS_DEV_DATASPARK, + LMS_DEV_RFSPARK, + LMS_DEV_LMS6002USB, + LMS_DEV_RFESPARK, + + LMS_DEV_COUNT +}; + +const char LMS_DEV_NAMES[][80] = +{ + "UNKNOWN", + "EVB6", + "DigiGreen", + "DigiRed", + "EVB7", + "ZIPPER", + "Socket Board", + "EVB7_v2", + "Stream", + "Novena", + "DataSpark", + "RF-Spark", + "LMS6002-USB Stick", + "RF-ESpark" +}; + +static const char* GetDeviceName(const eLMS_DEV device) +{ + if (LMS_DEV_UNKNOWN < device && device < LMS_DEV_COUNT) + return LMS_DEV_NAMES[device]; + else + return LMS_DEV_NAMES[LMS_DEV_UNKNOWN]; +} + +enum eEXP_BOARD +{ + EXP_BOARD_UNKNOWN, + EXP_BOARD_UNSUPPORTED, + EXP_BOARD_NO, + EXP_BOARD_MYRIAD1, + EXP_BOARD_MYRIAD2, + EXP_BOARD_MYRIAD_NOVENA, + EXP_BOARD_HPM1000, + EXP_BOARD_MYRIAD7, + EXP_BOARD_HPM7, + + EXP_BOARD_COUNT +}; + +const char EXP_BOARD_NAMES[][80] = +{ + "UNKNOWN", + "UNSUPPORTED", + "NOT AVAILABLE", + "Myriad1", + "Myriad2", + "Novena", + "HPM1000", + "Myriad7", + "HMP7" +}; + +static const char* GetExpansionBoardName(const eEXP_BOARD board) +{ + if (EXP_BOARD_UNKNOWN < board && board < EXP_BOARD_COUNT) + return EXP_BOARD_NAMES[board]; + else + return EXP_BOARD_NAMES[EXP_BOARD_UNKNOWN]; +} + +struct LMS64C_Info +{ + unsigned char firmware; + unsigned char deviceType; + unsigned char protocol; + unsigned char hardware; + unsigned char expansionBoard; +}; + +enum eCMD_LMS +{ + CMD_GET_INFO = 0x00, + CMD_LMS6002_RST = 0x10, + ///Writes data to SI5356 synthesizer via I2C + CMD_SI5356_WR = 0x11, + ///Reads data from SI5356 synthesizer via I2C + CMD_SI5356_RD = 0x12, + ///Writes data to SI5351 synthesizer via I2C + CMD_SI5351_WR = 0x13, + ///Reads data from SI5351 synthesizer via I2C + CMD_SI5351_RD = 0x14, + ///PanelBus DVI (HDMI) Transmitter control + CMD_TFP410_WR = 0x15, + ///PanelBus DVI (HDMI) Transmitter control + CMD_TFP410_RD = 0x16, + ///Sets new LMS7002M chip’s RESET pin level (0, 1, pulse) + CMD_LMS7002_RST = 0x20, + ///Writes data to LMS7002M chip via SPI + CMD_LMS7002_WR = 0x21, + ///Reads data from LMS7002M chip via SPI + CMD_LMS7002_RD = 0x22, + ///Writes data to LMS6002 chip via SPI + CMD_LMS6002_WR = 0x23, + ///Reads data from LMS6002 chip via SPI + CMD_LMS6002_RD = 0x24, + + CMD_LMS_LNA = 0x2A, + CMD_LMS_PA = 0x2B, + + CMD_PROG_MCU = 0x2C, + ///Writes data to ADF4002 chip via SPI + CMD_ADF4002_WR = 0x31, + + CMD_USB_FIFO_RST = 0x40, + CMD_PE636040_WR = 0x41, + CMD_PE636040_RD = 0x42, + + CMD_GPIO_WR = 0x51, + CMD_GPIO_RD = 0x52, + + CMD_ALTERA_FPGA_GW_WR = 0x53, + CMD_ALTERA_FPGA_GW_RD = 0x54, + + CMD_BRDSPI_WR = 0x55,//16 bit spi for stream, dataspark control + CMD_BRDSPI_RD = 0x56,//16 bit spi for stream, dataspark control + CMD_BRDSPI8_WR = 0x57, //8 + 8 bit spi for stream, dataspark control + CMD_BRDSPI8_RD = 0x58, //8 + 8 bit spi for stream, dataspark control + + CMD_BRDCONF_WR = 0x5D, //write config data to board + CMD_BRDCONF_RD = 0x5E, //read config data from board + + CMD_ANALOG_VAL_WR = 0x61, //write analog value + CMD_ANALOG_VAL_RD = 0x62, //read analog value + + CMD_MYRIAD_RST = 0x80, + CMD_MYRIAD_WR = 0x81, + CMD_MYRIAD_RD = 0x82, + CMD_MYRIAD_PROG = 0x8C +}; + +enum eCMD_STATUS +{ + STATUS_UNDEFINED, + STATUS_COMPLETED_CMD, + STATUS_UNKNOWN_CMD, + STATUS_BUSY_CMD, + STATUS_MANY_BLOCKS_CMD, + STATUS_ERROR_CMD, + STATUS_WRONG_ORDER_CMD, + STATUS_RESOURCE_DENIED_CMD, + STATUS_COUNT +}; + +static const char status_text[][32]= +{ + "Undefined/Failure", + "Completed", + "Unknown command", + "Busy", + "Too many blocks", + "Error", + "Wrong order", + "Resource denied" +}; + +static const char* status2string(const int status) +{ + if(status >= 0 && status < STATUS_COUNT) + return status_text[status]; + else + return "Unknown status"; +} + +enum eADC_UNITS +{ + RAW, + VOLTAGE, + CURRENT, + RESISTANCE, + POWER, + ADC_UNITS_COUNT +}; + +static const char adc_units_text[][8] = {"", "V", "A", "Ohm", "W"}; + +static const char* adcUnits2string(const unsigned units) +{ + if (units < ADC_UNITS_COUNT) + return adc_units_text[units]; + else + return " unknown"; +} diff --git a/targets/ARCH/LMSSDR/USERSPACE/LIB/lmsSDR/connectionManager/CMakeLists.txt b/targets/ARCH/LMSSDR/USERSPACE/LIB/lmsSDR/connectionManager/CMakeLists.txt new file mode 100644 index 0000000000..d9124aaef1 --- /dev/null +++ b/targets/ARCH/LMSSDR/USERSPACE/LIB/lmsSDR/connectionManager/CMakeLists.txt @@ -0,0 +1,34 @@ +set(ENABLE_USB_CONNECTION "YES" CACHE BOOL INTERNAL) +set(ENABLE_SPI_CONNECTION "NO" CACHE BOOL INTERNAL) +set(CONNECTION_MANAGER_DIR connectionManager) +set(connectionManager_src_files + ConnectionManager.cpp + ConnectionCOM.cpp + ConnectionManager.h + ConnectionCOM.h + lmsComms.h + lmsComms.cpp +) +if(ENABLE_USB_CONNECTION) + list(APPEND connectionManager_src_files ConnectionUSB.cpp ConnectionUSB.h) + add_definitions(-DENABLE_USB_CONNECTION) +endif() +if(ENABLE_SPI_CONNECTION) + list(APPEND connectionManager_src_files ConnectionSPI.cpp ConnectionSPI.h) + add_definitions(-DENABLE_SPI_CONNECTION) +endif() + +add_library(ConnectionManager STATIC ${connectionManager_src_files}) +target_include_directories(ConnectionManager PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}) + +if(WIN32 AND ENABLE_USB_CONNECTION) + find_package(CyAPI REQUIRED) + LINK_DIRECTORIES(${CYAPI_LIBRARIES}) + include_directories(${CYAPI_INCLUDE_DIRS}) + set(CONNECTION_MANAGER_LIBS ${CYAPI_LIBRARIES} SetupAPI) + target_link_libraries(ConnectionManager ${CONNECTION_MANAGER_LIBS}) +endif() +if(UNIX AND ENABLE_USB_CONNECTION) + set(CONNECTION_MANAGER_LIBS usb-1.0 -lpthread) + target_link_libraries(ConnectionManager ${CONNECTION_MANAGER_LIBS}) +endif() diff --git a/targets/ARCH/LMSSDR/USERSPACE/LIB/lmsSDR/connectionManager/ConnectionCOM.cpp b/targets/ARCH/LMSSDR/USERSPACE/LIB/lmsSDR/connectionManager/ConnectionCOM.cpp new file mode 100644 index 0000000000..6c7fc0d829 --- /dev/null +++ b/targets/ARCH/LMSSDR/USERSPACE/LIB/lmsSDR/connectionManager/ConnectionCOM.cpp @@ -0,0 +1,596 @@ +/** + @file ConnectionCOM.cpp + @author Lime Microsystems (www.limemicro.com) + @brief Implementation of communications through COM port +*/ + +#include "ConnectionCOM.h" + +#include "string.h" +#ifdef __unix__ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#endif // LINUX + +const int COM_RETRY_INTERVAL = 20; //ms +const int COM_TOTAL_TIMEOUT = 300; //ms + +/** @brief Initializes com port connection +*/ +ConnectionCOM::ConnectionCOM() +{ + currentDeviceIndex = -1; + connected = false; + comPortList.clear(); + m_deviceNames.clear(); + m_connectionType = COM_PORT; +#ifndef __unix__ + hComm = INVALID_HANDLE_VALUE; +#else + hComm = -1; +#endif + comBaudrate = 9600; +} + +/** @brief When object is destroyed it closes it's opened COM port +*/ +ConnectionCOM::~ConnectionCOM() +{ + Close(); +} + +/** @brief Opens connection to first found chip + @return 0-success +*/ +IConnection::DeviceStatus ConnectionCOM::Open() +{ + comPortList.clear(); + if(comPortList.size() == 0) + FindAllComPorts(); + + m_deviceNames.clear(); + if(m_deviceNames.size() == 0) + RefreshDeviceList(); + + for(unsigned int i=0; i 0 ) + { + comPortName = m_deviceNames[toOpen]; + IConnection::DeviceStatus status = Open(comPortName.c_str(), comBaudrate); + if( status == SUCCESS ) + currentDeviceIndex = toOpen; + return status; + } + return FAILURE; +} + +/** @brief Closes connection to chip +*/ +void ConnectionCOM::Close() +{ + connected = false; + currentDeviceIndex = -1; +#ifndef __unix__ + if (hComm != INVALID_HANDLE_VALUE) + { + SetCommTimeouts(hComm, &m_ctmoOld); + CloseHandle(hComm); + } + hComm = INVALID_HANDLE_VALUE; +#else + if( hComm >= 0) + { + close(hComm); + } + hComm = -1; +#endif +} + +/** @brief Returns whether chip is connected + @return chip is connected +*/ +bool ConnectionCOM::IsOpen() +{ +#ifndef __unix__ + if (hComm != INVALID_HANDLE_VALUE && TestConnectivity() ) + return true; +#else + if( hComm != -1 && TestConnectivity() ) + return true; +#endif + return false; +} + +int ConnectionCOM::GetOpenedIndex() +{ + return currentDeviceIndex; +} + +/** @brief Sends data through COM port + @param buffer data buffer to send + @param length size of data buffer + @param timeout_ms timeout limit for operation in milliseconds + @return Number of bytes sent +*/ +int ConnectionCOM::Write(const unsigned char *buffer, int length, int timeout_ms) +{ + if(timeout_ms == 0) + { + timeout_ms = COM_TOTAL_TIMEOUT; + } + int retryCount = 0; + const int maxRetries = (timeout_ms/COM_RETRY_INTERVAL) > 1 ? (timeout_ms/COM_RETRY_INTERVAL) : 1; + bool status = false; +#ifndef __unix__ + unsigned long bytesWriten = 0; + m_osWOverlap.InternalHigh = 0; + + for(int i = 0; iwrite("COM PORT: error writing data\n", LOG_ERROR); +// if(bytesWriten == 0) +// MessageLog::getInstance()->write("COM PORT: data bytes sent 0\n", LOG_WARNING); + status = false; + } + else + status = true; + ++retryCount; + } +#endif + if(bytesWriten == length) + status = true; + + return bytesWriten; +} + +/** @brief Reads data from COM port + @param buffer pointer to data buffer for receiving + @param length number of bytes to read + @param timeout_ms timeout limit for operation in milliseconds + @return Number of bytes received +*/ +int ConnectionCOM::Read(unsigned char *buffer, int length, int timeout_ms) +{ + if(timeout_ms == 0) + { + timeout_ms = COM_TOTAL_TIMEOUT; + } + int retryCount = 0; + const int maxRetries = (timeout_ms/COM_RETRY_INTERVAL) > 1 ? (timeout_ms/COM_RETRY_INTERVAL) : 1; + bool status = false; + + memset(buffer, 0, length); + long bytesReaded = 0; + unsigned long totalBytesReaded = 0; + char cRawData[COM_BUFFER_LENGTH]; + unsigned long bytesToRead = length; + + memset(cRawData, '\0', sizeof(cRawData[0])*COM_BUFFER_LENGTH); + + for(int i=0; iwrite("COM PORT: error reading data\n", LOG_ERROR); +// if(bytesReaded == 0) +// MessageLog::getInstance()->write("COM PORT: reading 0 bytes\n", LOG_WARNING); + status = false; + } +#endif + retryCount++; + + for(int j=0; jwrite(ss.str(), LOG_DATA); + +// if(retryCount == maxRetries) +// MessageLog::getInstance()->write("COM PORT: read data timeout\n", LOG_WARNING); +// +// if(totalBytesReaded > length) +// MessageLog::getInstance()->write("COM PORT: read data corrupted, received length > requested length\n", LOG_ERROR); + return totalBytesReaded; +} + +/** @brief Searches for available COM ports and adds them to list +*/ +void ConnectionCOM::FindAllComPorts() +{ + Close(); + comPortList.clear(); +#ifndef __unix__ + HKEY hSERIALCOMM; + if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, TEXT("HARDWARE\\DEVICEMAP\\SERIALCOMM"), 0, KEY_QUERY_VALUE, &hSERIALCOMM) == ERROR_SUCCESS) + { + // Get the max value name and max value lengths + DWORD dwMaxValueNameLen; + DWORD dwMaxValueLen; + DWORD dwQueryInfo = RegQueryInfoKey(hSERIALCOMM, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &dwMaxValueNameLen, &dwMaxValueLen, NULL, NULL); + if (dwQueryInfo == ERROR_SUCCESS) + { + DWORD dwMaxValueNameSizeInChars = dwMaxValueNameLen + 1; + // Include space for the NULL terminator + DWORD dwMaxValueNameSizeInBytes = dwMaxValueNameSizeInChars*sizeof(TCHAR); + DWORD dwMaxValueDataSizeInChars = dwMaxValueLen / sizeof(TCHAR) + 1; + // Include space for the NULL terminator + DWORD dwMaxValueDataSizeInBytes = dwMaxValueDataSizeInChars*sizeof(TCHAR); + + // Allocate some space for the value name and value data + TCHAR* szValueName = new TCHAR[dwMaxValueNameSizeInChars]; + TCHAR* byValue = new TCHAR[dwMaxValueDataSizeInBytes]; + if (szValueName && byValue) + { + // Enumerate all the values underneath HKEY_LOCAL_MACHINE\HARDWARE\DEVICEMAP\SERIALCOMM + DWORD dwIndex = 0; + DWORD dwType; + DWORD dwValueNameSize = dwMaxValueNameSizeInChars; + DWORD dwDataSize = dwMaxValueDataSizeInBytes; + memset(szValueName, 0, dwMaxValueNameSizeInBytes); + memset(byValue, 0, dwMaxValueDataSizeInBytes); + LONG nEnum = RegEnumValue(hSERIALCOMM, dwIndex, szValueName, &dwValueNameSize, NULL, &dwType, (LPBYTE)byValue, &dwDataSize); + while (nEnum == ERROR_SUCCESS) + { + // If the value is of the correct type, then add it to the array + if (dwType == REG_SZ) + { + char portname[512]; + TCHAR* szPort = byValue; + int nUserNameLenUnicode = lstrlen( szPort ); // Convert all UNICODE characters + int nUserNameLen = WideCharToMultiByte( CP_ACP, // ANSI Code Page + 0, // No special handling of unmapped chars + (LPCWSTR)szPort, // wide-character string to be converted + nUserNameLenUnicode, + NULL, 0, // No output buffer since we are calculating length + NULL, NULL ); // Unrepresented char replacement - Use Default + TCHAR* pszUserName = new TCHAR[ nUserNameLen ]; // nUserNameLen includes the NULL character + WideCharToMultiByte( CP_ACP, // ANSI Code Page + 0, // No special handling of unmapped chars + (LPCWSTR)szPort, // wide-character string to be converted + nUserNameLenUnicode, + portname, + nUserNameLen, + NULL, NULL ); // Unrepresented char replacement - Use Default + portname[nUserNameLen] = 0; +#ifdef UNICODE + comPortList.push_back(portname); +#else + comPortList.push_back(szPort); +#endif + } + // Prepare for the next time around + dwValueNameSize = dwMaxValueNameSizeInChars; + dwDataSize = dwMaxValueDataSizeInBytes; + memset(szValueName, 0, dwMaxValueNameSizeInBytes); + memset(byValue, 0, dwMaxValueDataSizeInBytes); + ++dwIndex; + nEnum = RegEnumValue(hSERIALCOMM, dwIndex, szValueName, &dwValueNameSize, NULL, &dwType, (LPBYTE)byValue, &dwDataSize); + } + } + delete szValueName; + delete byValue; + } + // Close the registry key now that we are finished with it + RegCloseKey(hSERIALCOMM); + + if (dwQueryInfo != ERROR_SUCCESS) + SetLastError(dwQueryInfo); + } +#else + char tempBuffer[256]; + string result = ""; +#warning Currently searching only for ACM connections + system( "ls /dev | grep ttyACM > /tmp/foundSerialPorts.txt"); + + fstream fin; + fin.open("/tmp/foundSerialPorts.txt", ios::in); + while(!fin.eof()) + { + fin.getline(tempBuffer, 256); + result = "/dev/"; + result.append(tempBuffer); + if( strlen(tempBuffer) > 3 ) //longer than tty + comPortList.push_back(result); + } + fin.close(); +#endif +} + +/** @brief Opens COM port + @param comName COM port name + @param baudrate COM port baudrate + @return 0 on success +*/ +IConnection::DeviceStatus ConnectionCOM::Open(const char *comName, int baudrate) +{ + Close(); + if (strlen(comName) == 0) + return FAILURE; + + DeviceStatus errorCode = SUCCESS; + +#ifndef __unix__ + // Initialize Overlap structures + m_osROverlap.Internal = 0; + m_osROverlap.InternalHigh = 0; + m_osROverlap.Offset = 0; + m_osROverlap.OffsetHigh = 0; + m_osROverlap.hEvent = CreateEvent(NULL, false, false, NULL); + + m_osWOverlap.Internal = 0; + m_osWOverlap.InternalHigh = 0; + m_osWOverlap.Offset = 0; + m_osWOverlap.OffsetHigh = 0; + m_osWOverlap.hEvent = CreateEvent(NULL, false, false, NULL); + + // Initialize DSB structure + memset(&m_dcbCommPort, 0, sizeof(m_dcbCommPort)); + + m_dcbCommPort.BaudRate = comBaudrate; + m_dcbCommPort.fBinary = 1; + m_dcbCommPort.fParity = 0; + m_dcbCommPort.fOutxCtsFlow = 0; + m_dcbCommPort.fOutxDsrFlow = 0; + m_dcbCommPort.fDtrControl = 0; + m_dcbCommPort.fDsrSensitivity = 0; + m_dcbCommPort.fTXContinueOnXoff = 0; + m_dcbCommPort.fOutX = 0; + m_dcbCommPort.fInX = 0; + m_dcbCommPort.fErrorChar = 0; + m_dcbCommPort.fNull = 0; + m_dcbCommPort.fRtsControl = 0; + m_dcbCommPort.fAbortOnError = 0; + m_dcbCommPort.fDummy2 = 0; + // m_dcbCommPort.wReserved = 0; + m_dcbCommPort.XonLim = 512; + m_dcbCommPort.XoffLim = 512; + m_dcbCommPort.ByteSize = 8; + m_dcbCommPort.Parity = 0; + m_dcbCommPort.StopBits = 0; + //m_dcbCommPort.StopBits = 1; + m_dcbCommPort.XonChar = 17; + m_dcbCommPort.XoffChar = 19; + m_dcbCommPort.ErrorChar = 0; + m_dcbCommPort.EofChar = 26; + m_dcbCommPort.EvtChar = 0; + m_dcbCommPort.wReserved1 = 0; + m_dcbCommPort.DCBlength = sizeof(DCB); + + // Initialize Timeout's + m_ctmoNew.ReadIntervalTimeout = 50; + m_ctmoNew.ReadTotalTimeoutMultiplier = 0; + m_ctmoNew.ReadTotalTimeoutConstant = 100; // 1; + m_ctmoNew.WriteTotalTimeoutMultiplier = 0; + m_ctmoNew.WriteTotalTimeoutConstant = 100; + + // Open COM port + string stmp; + stmp = "\\\\.\\"; + stmp.append(comName); + hComm = CreateFileA(stmp.c_str(), GENERIC_READ | GENERIC_WRITE, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); + + if (hComm != INVALID_HANDLE_VALUE) + { + // Set Events + if (!SetCommMask(hComm, 0)) + errorCode = FAILURE; + + // Set Timeouts + GetCommTimeouts(hComm, &m_ctmoOld); + if (!SetCommTimeouts(hComm, &m_ctmoNew)) + errorCode = FAILURE; + + // Set DCB + if (!SetCommState(hComm, &m_dcbCommPort)) + errorCode = FAILURE; + } + else + { + errorCode = FAILURE; + }; + + // Check the results + if (errorCode != 0) + { + //unsigned long err = GetLastError(); + CloseHandle(hComm); + hComm = INVALID_HANDLE_VALUE; + return errorCode; + } + else + { + PurgeComm(hComm, PURGE_TXCLEAR | PURGE_RXCLEAR); + return SUCCESS; + } +#else + hComm = open(comName, O_RDWR | O_NOCTTY | O_SYNC); + if(hComm < 0) + { +// printf("%s",strerror(errno)); +// MessageLog::getInstance()->write("Connection manager: failed opening COM port\n", LOG_ERROR); + return FAILURE; + } + + struct termios tty; + memset(&tty, 0, sizeof(tty)); + if( tcgetattr(hComm, &tty) != 0) + { +// MessageLog::getInstance()->write("Connection Manager: error from tcgetattr\n", LOG_ERROR); + return FAILURE; + } + int speed = B9600; + cfsetospeed(&tty, speed); + cfsetispeed(&tty, speed); + + tty.c_cflag = (tty.c_cflag & ~CSIZE) | CS8; + tty.c_iflag &= ~IGNBRK; + tty.c_lflag = 0; + tty.c_oflag = 0; + tty.c_cc[VMIN] = 0; // read non blocking + tty.c_cc[VTIME] = 5; // 0.5 seconds read timeout + + tty.c_iflag &= ~(IXON | IXOFF | IXANY); + tty.c_cflag |= (CLOCAL | CREAD); + + if(tcsetattr(hComm, TCSANOW, &tty) != 0) + { +// MessageLog::getInstance()->write("Connection manager: error from tcsetattr\n", LOG_ERROR); + return FAILURE; + } +#endif + return SUCCESS; +} + +/** @brief Checks if chip is connected to currently open port + @return chip is connected +*/ +bool ConnectionCOM::TestConnectivity() +{ +//currently set to always return true to show all com ports + return true; +#ifndef __unix__ + if (hComm != INVALID_HANDLE_VALUE) +#else + if( hComm >= 0) +#endif + { +// unsigned char out[64]; +// unsigned char in[64]; +// memset(in, 0, 64); +// out[0] = CMD_GET_INFO; +// SendData(out, 64); +// ReadData(in, 64); +// if(in[0] == CMD_GET_INFO && in[1] == 0x01) +// return true; +// else +// return false; + } + return false; +} + +/** @brief Finds all chips connected to com ports + @return number of devices found +*/ +int ConnectionCOM::RefreshDeviceList() +{ + int wasOpen = -1; + string wasOpenName = ""; + if(IsOpen()) + { + wasOpen = GetOpenedIndex(); + wasOpenName = comPortName; + } + Close(); + comPortList.clear(); + if(comPortList.size() == 0) + FindAllComPorts(); + + m_deviceNames.clear(); + string comName; + for(unsigned int i=0; i ConnectionCOM::GetDeviceNames() +{ + return m_deviceNames; +} + +/** @brief Purges communication buffers +*/ +void ConnectionCOM::ClearComm() +{ +#ifndef __unix__ + PurgeComm(hComm, PURGE_TXCLEAR|PURGE_RXCLEAR); +#endif +} diff --git a/targets/ARCH/LMSSDR/USERSPACE/LIB/lmsSDR/connectionManager/ConnectionCOM.h b/targets/ARCH/LMSSDR/USERSPACE/LIB/lmsSDR/connectionManager/ConnectionCOM.h new file mode 100644 index 0000000000..0549472db1 --- /dev/null +++ b/targets/ARCH/LMSSDR/USERSPACE/LIB/lmsSDR/connectionManager/ConnectionCOM.h @@ -0,0 +1,62 @@ +/** +@file ConnectionCOM.h +@author Lime Microsystems (www.limemicro.com) +@brief Class for data communications through COM port +*/ + +#ifndef CONNECTION_COM_PORT_H +#define CONNECTION_COM_PORT_H + +#ifndef __unix__ + #include "windows.h" +#endif + +#include "IConnection.h" + +class ConnectionCOM : public IConnection +{ +public: + static const int COM_BUFFER_LENGTH = 1024; //max buffer size for data + + ConnectionCOM(); + ~ConnectionCOM(); + + DeviceStatus Open(); + DeviceStatus Open(unsigned i); + void Close(); + bool IsOpen(); + int GetOpenedIndex(); + + int Write(const unsigned char *buffer, int length, int timeout_ms = 0); + int Read(unsigned char *buffer, int length, int timeout_ms = 0); + + std::vector GetDeviceNames(); + int RefreshDeviceList(); + void ClearComm(); +private: + void FindAllComPorts(); + DeviceStatus Open(const char *comName, int baudrate); + + bool TestConnectivity(); + + std::string comPortName; + int comBaudrate; + bool connected; + + int currentDeviceIndex; + std::vector comPortList; + std::vector m_deviceNames; + +#ifndef __unix__ + HANDLE hComm; + COMMTIMEOUTS m_ctmoNew; + COMMTIMEOUTS m_ctmoOld; + OVERLAPPED m_osROverlap; + OVERLAPPED m_osWOverlap; + DCB m_dcbCommPort; +#else + int hComm; //com port file descriptor +#endif + +}; +#endif diff --git a/targets/ARCH/LMSSDR/USERSPACE/LIB/lmsSDR/connectionManager/ConnectionManager.cpp b/targets/ARCH/LMSSDR/USERSPACE/LIB/lmsSDR/connectionManager/ConnectionManager.cpp new file mode 100644 index 0000000000..9ec16e0d88 --- /dev/null +++ b/targets/ARCH/LMSSDR/USERSPACE/LIB/lmsSDR/connectionManager/ConnectionManager.cpp @@ -0,0 +1,319 @@ +/** + @file ConnectionManager.cpp + @author Lime Microsystems (www.limemicro.com) + @brief Implementation of various connection types to devices +*/ + +#include "ConnectionManager.h" +#include "ConnectionCOM.h" + +#ifdef ENABLE_USB_CONNECTION + #include "ConnectionUSB.h" +#endif +#ifdef ENABLE_SPI_CONNECTION + #include "ConnectionSPI.h" +#endif + +#include +#include +#include + +/** @brief Creates connection interfaces +*/ +ConnectionManager::ConnectionManager(const IConnection::eConnectionType port_type) : activeControlPort(NULL) +{ + mLogData = false; + mOpenedDevice = -1; + if (port_type == IConnection::COM_PORT) + m_connections[IConnection::COM_PORT] = new ConnectionCOM(); +#ifdef ENABLE_USB_CONNECTION + if (port_type == IConnection::USB_PORT) + m_connections[IConnection::USB_PORT] = new ConnectionUSB(); +#endif +#ifdef ENABLE_SPI_CONNECTION + m_connections[IConnection::SPI_PORT] = new ConnectionSPI(); +#endif +} + +/** @brief Destroys connection interfaces +*/ +ConnectionManager::~ConnectionManager() +{ + for (auto iter = m_connections.begin(); iter != m_connections.end(); ++iter) + { + delete iter->second; + } +} + +/** @brief Checks if connection to device is opened + @return True if device is connected +*/ +bool ConnectionManager::IsOpen() +{ + return activeControlPort ? activeControlPort->IsOpen() : false; +} + +/** @brief Opens connection to first available device + @return True if connected to device +*/ +bool ConnectionManager::Open() +{ + return Open(0); +} + +/** @brief Connects to selected device + @param i device index from device list + @return 1:Success, 0:failure +*/ +int ConnectionManager::Open(unsigned i) +{ + if(i >= mDevices.size()) + return 0; + + if(activeControlPort) + activeControlPort->Close(); + switch(mDevices[i].port) + { + case IConnection::COM_PORT: + activeControlPort = m_connections[IConnection::COM_PORT]; + break; + case IConnection::USB_PORT: + activeControlPort = m_connections[IConnection::USB_PORT]; + break; + case IConnection::SPI_PORT: + activeControlPort = m_connections[IConnection::SPI_PORT]; + break; + default: + return 0; + } + mOpenedDevice = -1; + if( i < mDevices.size() ) + { + if (activeControlPort->Open(mDevices[i].portIndex) == IConnection::SUCCESS) + { + mOpenedDevice = i; + return 1; + } + } + return 0; +} + +/** @brief Closes connection to device +*/ +void ConnectionManager::Close() +{ + if(activeControlPort) + { + activeControlPort->Close(); + //Notify(LMS_Message(MSG_BOARD_DISCONNECTED, "", 0, 0)); + } + mOpenedDevice = -1; +} + +/** @brief Finds all currently connected devices and forms device list + @return number of devices found +*/ +int ConnectionManager::RefreshDeviceList() +{ + mDeviceList.clear(); + mDevices.clear(); + DeviceInfo dev; + for (auto iter = m_connections.begin(); iter != m_connections.end(); ++iter) + { + vector names; + IConnection *port = iter->second; + if(port->RefreshDeviceList() > 0) + { + names = port->GetDeviceNames(); + for(unsigned i=0; ifirst; + dev.portIndex = i; + mDevices.push_back(dev); + } + } + } + for(unsigned i=0; iWrite(buffer, length, timeout_ms); +#ifndef NDEBUG + if(mLogData) + { + stringstream ss; + ss << "WR(" << (bytesTransferred>=0?bytesTransferred: 0) << "): "; + ss << std::hex << std::setfill('0'); + int repeatedZeros = 0; + for(int i=length-1; i>=0; --i) + if(buffer[i] == 0) + ++repeatedZeros; + else break; + if(repeatedZeros == 1) + repeatedZeros = 0; + repeatedZeros = repeatedZeros - (repeatedZeros & 0x1); + for(int i=0; i 1) + ss << " (00 x " << std::dec << repeatedZeros << " times)"; + cout << ss.str() << endl; +#ifndef __unix__ + OutputDebugString(ss.str().c_str()); +#endif + } +#endif + return bytesTransferred; + } + return -1; +} + +/** @brief Receives data from currently opened connection + @param buffer incomming data buffer, must be big enough for length bytes + @param length bytes to read + @param timeout_ms timeout in milliseconds + @return number of bytes received +*/ +int ConnectionManager::Read(unsigned char *buffer, int length, int timeout_ms) +{ + if(activeControlPort) + { + int bytesTransferred = activeControlPort->Read(buffer, length, timeout_ms); +#ifndef NDEBUG + if(mLogData) + { + stringstream ss; + ss << "RD(" << (bytesTransferred>=0?bytesTransferred: 0) << "): "; + ss << std::hex << std::setfill('0'); + int repeatedZeros = 0; + for(int i=length-1; i>=0; --i) + if(buffer[i] == 0) + ++repeatedZeros; + else break; + if(repeatedZeros == 2) + repeatedZeros = 0; + repeatedZeros = repeatedZeros - (repeatedZeros & 0x1); + for(int i=0; i 2) + ss << " (00 x " << std::dec << repeatedZeros << " times)"; + cout << ss.str() << endl; + } +#endif + return bytesTransferred; + } + return -1; +} + +int ConnectionManager::WriteStream(const char *buffer, int length) +{ + return 0; +} + +int ConnectionManager::ReadStream(char *buffer, int length, unsigned int timeout_ms) +{ + /*int handle = activeControlPort->BeginDataReading(buffer, length); + activeControlPort->WaitForReading(handle, timeout_ms); + long received = length; + activeControlPort->FinishDataReading(buffer, received, handle); + return received; + */ + long len = length; + int status = activeControlPort->ReadDataBlocking(buffer, len, 0); + return len; +} + + +int ConnectionManager::BeginDataReading(char *buffer, long length) +{ + return activeControlPort->BeginDataReading(buffer, length); +} +/** +@brief Blocks until data is received or set number of milliseconds have passed. +@param contextHandle handle returned by BeginDataReading() +@param timeout_ms number of milliseconds to wait +@return 1-data received, 0-data not received +*/ +int ConnectionManager::WaitForReading(int contextHandle, unsigned int timeout_ms) +{ + return activeControlPort->WaitForReading(contextHandle, timeout_ms); +} +/** +@brief Finished asynchronous data reading. +@param buffer where to put received data +@param length number of bytes to read, will be changed to actual number of bytes received +@param contextHandle context handle returned by BeginDataReading() +@return received data length +*/ +int ConnectionManager::FinishDataReading(char *buffer, long &length, int contextHandle) +{ + return activeControlPort->FinishDataReading(buffer, length, contextHandle); +} + +/** +@brief Aborts reading operations +*/ +void ConnectionManager::AbortReading() +{ + activeControlPort->AbortReading(); +} + +/** +@brief Start asynchronous data sending. +@param buffer data buffer to be sent +@param length number of bytes to send. +@return context handle +*/ +int ConnectionManager::BeginDataSending(const char *buffer, long length) +{ + return activeControlPort->BeginDataSending(buffer, length); +} +/** +@brief Blocks until data is sent or set number of miliseconds have passed. +@param contextHandle handle returned by BeginDataReading() +@param timeout_ms number of miliseconds to wait +@return 1-data sent, 0-data not sent +*/ +int ConnectionManager::WaitForSending(int contextHandle, unsigned int timeout_ms) +{ + return activeControlPort->WaitForSending(contextHandle, timeout_ms); +} +/** +@brief Finished asynchronous data sending. +@param buffer where to put received data +@param length number of bytes to send, will be changed to actual number of bytes sent +@param contextHandle context handle returned by BeginDataReading() +@return sent data length +*/ +int ConnectionManager::FinishDataSending(const char *buffer, long &length, int contextHandle) +{ + return activeControlPort->FinishDataSending(buffer, length, contextHandle); +} + +/** +@brief Aborts sending operations +*/ +void ConnectionManager::AbortSending() +{ + activeControlPort->AbortSending(); +} diff --git a/targets/ARCH/LMSSDR/USERSPACE/LIB/lmsSDR/connectionManager/ConnectionManager.h b/targets/ARCH/LMSSDR/USERSPACE/LIB/lmsSDR/connectionManager/ConnectionManager.h new file mode 100644 index 0000000000..68819011ff --- /dev/null +++ b/targets/ARCH/LMSSDR/USERSPACE/LIB/lmsSDR/connectionManager/ConnectionManager.h @@ -0,0 +1,60 @@ +/** + @file ConnectionManager.h + @author Lime Microsystems (www.limemicro.com) + @brief Class for managing connection to devices +*/ + +#ifndef LMS_CONNECTION_MANAGER_H +#define LMS_CONNECTION_MANAGER_H + +#include "IConnection.h" +#include + +class ConnectionManager +{ +public: + struct DeviceInfo + { + std::string name; + IConnection::eConnectionType port; + int portIndex; + }; + + ConnectionManager(const IConnection::eConnectionType port_type); + ~ConnectionManager(); + bool IsOpen(); + bool Open(); + int Open(unsigned i); + void Close(); + int RefreshDeviceList(); + int GetOpenedIndex(); + std::vector GetDeviceList(){return mDeviceList;}; + + int Write(const unsigned char *buffer, int length, int timeout_ms = 0); + int Read(unsigned char *buffer, int length, int timeout_ms = 0); + + int WriteStream(const char *buffer, int length); + int ReadStream(char *buffer, int length, unsigned int timeout_ms); + + int BeginDataReading(char *buffer, long length); + int WaitForReading(int contextHandle, unsigned int timeout_ms); + int FinishDataReading(char *buffer, long &length, int contextHandle); + void AbortReading(); + + int BeginDataSending(const char *buffer, long length); + int WaitForSending(int contextHandle, unsigned int timeout_ms); + int FinishDataSending(const char *buffer, long &length, int contextHandle); + void AbortSending(); + +protected: + bool mLogData; + /// Port used for communication. + IConnection *activeControlPort; + std::vector mDevices; + std::vector mDeviceList; + int mOpenedDevice; + std::map m_connections; +}; + +#endif // LMS_CONNECTION_MANAGER_H + diff --git a/targets/ARCH/LMSSDR/USERSPACE/LIB/lmsSDR/connectionManager/ConnectionSPI.cpp b/targets/ARCH/LMSSDR/USERSPACE/LIB/lmsSDR/connectionManager/ConnectionSPI.cpp new file mode 100644 index 0000000000..fb305f9c1c --- /dev/null +++ b/targets/ARCH/LMSSDR/USERSPACE/LIB/lmsSDR/connectionManager/ConnectionSPI.cpp @@ -0,0 +1,313 @@ +/** + @file ConnectionSPI.cpp + @author Lime Microsystems (www.limemicro.com) + @brief Implementation of communications through SPI port +*/ + +#include "ConnectionSPI.h" + +#include "string.h" +#ifdef __unix__ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#endif // LINUX + +#include +#include + +const int ConnectionSPI::cSPI_BUF_SIZE = 128; +const int ConnectionSPI::cSPI_SPEED_HZ = 2000000; + +/** @brief Tries to read EEPROM for Novena board signature + @return true if Novena board +*/ +bool IsNovenaBoard() +{ +#ifdef __unix__ + char data[8]; + int count = 6; + memset(data, 0, 8); + int addr = 0; + struct i2c_rdwr_ioctl_data session; + struct i2c_msg messages[2]; + char set_addr_buf[2]; + memset(set_addr_buf, 0, sizeof(set_addr_buf)); + memset(data, 0, count); + set_addr_buf[0] = addr>>8; + set_addr_buf[1] = addr; + messages[0].addr = 0xac>>1; + messages[0].flags = 0; + messages[0].len = sizeof(set_addr_buf); + messages[0].buf = set_addr_buf; + messages[1].addr = 0xac>>1; + messages[1].flags = I2C_M_RD; + messages[1].len = count; + messages[1].buf = data; + session.msgs = messages; + session.nmsgs = 2; + + bool isNovena = false; + + int fd = open("/dev/i2c-2", O_RDWR); + if(fd > 0) + { + if(ioctl(fd, I2C_RDWR, &session) < 0) + { + perror("Unable to communicate with i2c device"); + isNovena = false; + } + if(strcmp("Novena", data) == 0) + isNovena = true; + } + close(fd); + return isNovena; +#else + return false; +#endif +} + +/** @brief Initializes SPI port and exports needed GPIO +*/ +ConnectionSPI::ConnectionSPI() +{ + fd = -1; + m_connectionType = SPI_PORT; + std::fstream gpio; + //export SEN pin + gpio.open("/sys/class/gpio/export", ios::out); + if(gpio.good()) + { + gpio << 122; + gpio.flush(); + gpio.close(); + gpio.open("/sys/class/gpio/gpio122/direction", ios::out); + gpio << "out"; + gpio.flush(); + gpio.close(); + m_SEN.open("/sys/class/gpio/gpio122/value", ios::out); + m_SEN<< 1; + m_SEN.flush(); + cout << "GPIO122: set to 1" << endl; + } +} + +ConnectionSPI::~ConnectionSPI() +{ + Close(); + m_SEN.close(); +} + +/** @brief Opens connection to first found chip + @return 0-success +*/ +IConnection::DeviceStatus ConnectionSPI::Open() +{ + Close(); +#ifdef __unix__ + fd = open("/dev/spidev2.0", O_RDWR | O_SYNC); + if (fd < 0) + { + //MessageLog::getInstance()->write("SPI PORT: device not found\n", LOG_ERROR); + return IConnection::FAILURE; + } + int mode = SPI_MODE_0; + int ret = ioctl(fd, SPI_IOC_WR_MODE, &mode); + if (ret == -1) + printf("can't set spi mode"); + + ret = ioctl(fd, SPI_IOC_RD_MODE, &mode); + if (ret == -1) + printf("can't get spi mode"); + + /* + * bits per word + */ + int bits = 8; + ret = ioctl(fd, SPI_IOC_WR_BITS_PER_WORD, &bits); + if (ret == -1) + printf("can't set bits per word"); + + ret = ioctl(fd, SPI_IOC_RD_BITS_PER_WORD, &bits); + if (ret == -1) + printf("can't get bits per word"); + + /* + * max speed hz + */ + int speed = cSPI_SPEED_HZ; + ret = ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed); + if (ret == -1) + printf("can't set max speed hz"); + + ret = ioctl(fd, SPI_IOC_RD_MAX_SPEED_HZ, &speed); + if (ret == -1) + printf("can't get max speed hz"); + + printf("spi mode: 0x%x\n", mode); + printf("bits per word: %d\n", bits); + printf("max speed: %d Hz (%d KHz)\n", speed, speed/1000); + return IConnection::SUCCESS; +#else + return IConnection::FAILURE; +#endif +} + +/** @brief Opens connection to selected chip + @param index chip index in device list + @return 0-success +*/ +IConnection::DeviceStatus ConnectionSPI::Open(unsigned index) +{ + return Open(); +} + +/** @brief Closes connection to chip +*/ +void ConnectionSPI::Close() +{ +#ifdef __unix__ + close(fd); + fd = -1; +#endif +} + +/** @brief Returns whether chip is connected + @return chip is connected +*/ +bool ConnectionSPI::IsOpen() +{ + return (fd >= 0); +} + +/** @brief Sends data through COM port + @param buffer data buffer to send + @param length size of data buffer + @param timeout_ms timeout limit for operation in milliseconds + @return Number of bytes sent +*/ +int ConnectionSPI::Write(const unsigned char *buffer, int length, int timeout_ms) +{ + #ifdef __unix__ + if(fd < 0) + return 0; + m_SEN << 0; + m_SEN.flush(); + unsigned long bytesWritten = 0; + rxbuf.clear(); + int bytesReceived = 0; + char rxbytes[2]; + while(bytesWritten < length) + { + int toWrite = length-bytesWritten > cSPI_BUF_SIZE ? cSPI_BUF_SIZE : length-bytesWritten; + for(int i=0; i 0) +// { +// ss << " re443ad(" << toWrite << "): "; +// for(int i=0; iwrite(ss.str(), LOG_DATA); + + bytesWritten += toWrite; + } + m_SEN << 1; + m_SEN.flush(); + return bytesWritten; +#else + return 0; +#endif +} + +/** @brief Reads data from COM port + @param buffer pointer to data buffer for receiving + @param length number of bytes to read + @param timeout_ms timeout limit for operation in milliseconds + @return Number of bytes received +*/ +int ConnectionSPI::Read(unsigned char *buffer, int length, int timeout_ms) +{ +#ifdef __unix__ + if(fd < 0) + return 0; + //because transfer is done in full duplex, function returns data from last transfer + int tocpy = length > rxbuf.size() ? rxbuf.size() : length; + memcpy(buffer, &rxbuf[0], tocpy); + rxbuf.clear(); + return tocpy; +#else + return 0; +#endif +} + +/** @brief Finds all chips connected to com ports + @return number of devices found +*/ +int ConnectionSPI::RefreshDeviceList() +{ + m_deviceNames.clear(); +#ifdef __unix__ + int spidev = open("/dev/spidev2.0", O_RDWR); + if (spidev >= 0) + { + if(IsNovenaBoard() == true) + m_deviceNames.push_back("SPI (Novena)"); + else + m_deviceNames.push_back("SPI"); + } + close(spidev); +#endif + return m_deviceNames.size(); +} + +/** @brief Returns found devices names + @return vector of device names +*/ +vector ConnectionSPI::GetDeviceNames() +{ + return m_deviceNames; +} + +int ConnectionSPI::GetOpenedIndex() +{ + return 0; +} diff --git a/targets/ARCH/LMSSDR/USERSPACE/LIB/lmsSDR/connectionManager/ConnectionSPI.h b/targets/ARCH/LMSSDR/USERSPACE/LIB/lmsSDR/connectionManager/ConnectionSPI.h new file mode 100644 index 0000000000..79d9bd9b9b --- /dev/null +++ b/targets/ARCH/LMSSDR/USERSPACE/LIB/lmsSDR/connectionManager/ConnectionSPI.h @@ -0,0 +1,41 @@ +/** +@file ConnectionSPI.h +@author Lime Microsystems (www.limemicro.com) +@brief Class for data communications through SPI port +*/ + +#ifndef CONNECTION_SPI_PORT_H +#define CONNECTION_SPI_PORT_H + +#include "IConnection.h" +#include +#include +#include + +class ConnectionSPI : public IConnection +{ +public: + static const int cSPI_BUF_SIZE; + static const int cSPI_SPEED_HZ; + + ConnectionSPI(); + ~ConnectionSPI(); + + DeviceStatus Open(); + DeviceStatus Open(unsigned i); + void Close(); + bool IsOpen(); + int GetOpenedIndex(); + + int Write(const unsigned char *buffer, int length, int timeout_ms = 0); + int Read(unsigned char *buffer, int length, int timeout_ms = 0); + + std::vector GetDeviceNames(); + int RefreshDeviceList(); +protected: + std::vector m_deviceNames; + std::vector rxbuf; + int fd; + std::fstream m_SEN; +}; +#endif diff --git a/targets/ARCH/LMSSDR/USERSPACE/LIB/lmsSDR/connectionManager/ConnectionUSB.cpp b/targets/ARCH/LMSSDR/USERSPACE/LIB/lmsSDR/connectionManager/ConnectionUSB.cpp new file mode 100644 index 0000000000..148b7b776b --- /dev/null +++ b/targets/ARCH/LMSSDR/USERSPACE/LIB/lmsSDR/connectionManager/ConnectionUSB.cpp @@ -0,0 +1,771 @@ +/** +@file ConnectionUSB.cpp +@author Lime Microsystems (www.limemicro.com) +@brief Data writing and reading through USB port +*/ + +#include "ConnectionUSB.h" +#include + +#ifdef __unix__ + #include + #include +#endif + +#define USB_TIMEOUT 1000 + +#define HW_LDIGIRED L"DigiRed" +#define HW_LDIGIGREEN L"DigiGreen" +#define HW_LSTREAMER L"Stream" + +#define HW_DIGIRED "DigiRed" +#define HW_DIGIGREEN "DigiGreen" +#define HW_STREAMER "Stream" + +#define CTR_W_REQCODE 0xC1 +#define CTR_W_VALUE 0x0000 +#define CTR_W_INDEX 0x0000 + +#define CTR_R_REQCODE 0xC0 +#define CTR_R_VALUE 0x0000 +#define CTR_R_INDEX 0x0000 + +/** @brief Initializes port type and object necessary to communicate to usb device. +*/ +ConnectionUSB::ConnectionUSB() +{ + m_hardwareName = ""; + isConnected = false; + m_connectionType = USB_PORT; +#ifndef __unix__ + USBDevicePrimary = new CCyUSBDevice(NULL); + OutCtrEndPt = NULL; + InCtrEndPt = NULL; + InCtrlEndPt3 = NULL; + OutCtrlEndPt3 = NULL; +#else + dev_handle = 0; + devs = 0; + int r = libusb_init(&ctx); //initialize the library for the session we just declared + if(r < 0) + printf("Init Error %i\n", r); //there was an error + libusb_set_debug(ctx, 3); //set verbosity level to 3, as suggested in the documentation +#endif + currentDeviceIndex = -1; +} + +/** @brief Closes connection to chip and deallocates used memory. +*/ +ConnectionUSB::~ConnectionUSB() +{ + Close(); +#ifndef __unix__ + delete USBDevicePrimary; +#else + libusb_exit(ctx); +#endif +} + +/** @brief Automatically open first available chip connected to usb port. + @return 0-success, other-failure +*/ +IConnection::DeviceStatus ConnectionUSB::Open() +{ + currentDeviceIndex = -1; + if(m_deviceNames.size() == 0) + RefreshDeviceList(); + +#ifndef __unix__ + for(int i=0; iDeviceCount(); ++i) + if( Open(i) == SUCCESS) + { + currentDeviceIndex = i; + return SUCCESS; + } +#else + if(Open(0) == SUCCESS) + return SUCCESS; +#endif + return FAILURE; +} + +/** @brief Tries to open connected USB device and find communication endpoints. + @return Returns 1-Success, 0-EndPoints not found or device didn't connect. +*/ +IConnection::DeviceStatus ConnectionUSB::Open(unsigned index) +{ +#ifndef __unix__ + wstring m_hardwareDesc = L""; + if( index < USBDevicePrimary->DeviceCount()) + { + if(USBDevicePrimary->Open(index)) + { + m_hardwareDesc = USBDevicePrimary->Product; + unsigned int pos; + //determine connected board type + pos = m_hardwareDesc.find(HW_LDIGIRED, 0); + if( pos != wstring::npos ) + m_hardwareName = HW_DIGIRED; + else if (m_hardwareDesc.find(HW_LSTREAMER, 0) != wstring::npos) + m_hardwareName = HW_STREAMER; + else + m_hardwareName = HW_STREAMER; + + + if (InCtrlEndPt3) + { + delete InCtrlEndPt3; + InCtrlEndPt3 = NULL; + } + InCtrlEndPt3 = new CCyControlEndPoint(*USBDevicePrimary->ControlEndPt); + + if (OutCtrlEndPt3) + { + delete OutCtrlEndPt3; + OutCtrlEndPt3 = NULL; + } + OutCtrlEndPt3 = new CCyControlEndPoint(*USBDevicePrimary->ControlEndPt); + + InCtrlEndPt3->ReqCode = CTR_R_REQCODE; + InCtrlEndPt3->Value = CTR_R_VALUE; + InCtrlEndPt3->Index = CTR_R_INDEX; + + OutCtrlEndPt3->ReqCode = CTR_W_REQCODE; + OutCtrlEndPt3->Value = CTR_W_VALUE; + OutCtrlEndPt3->Index = CTR_W_INDEX; + + for (int i=0; iEndPointCount(); i++) + if(USBDevicePrimary->EndPoints[i]->Address == 0x01) + { + OutEndPt = USBDevicePrimary->EndPoints[i]; + long len = OutEndPt->MaxPktSize * 64; + OutEndPt->SetXferSize(len); + break; + } + for (int i=0; iEndPointCount(); i++) + if(USBDevicePrimary->EndPoints[i]->Address == 0x81) + { + InEndPt = USBDevicePrimary->EndPoints[i]; + long len = InEndPt->MaxPktSize * 64; + InEndPt->SetXferSize(len); + break; + } + isConnected = true; + return SUCCESS; + } //successfully opened device + } //if has devices + return FAILURE; +#else + if(index >= 0 && index < m_dev_pid_vid.size()) + { + dev_handle = libusb_open_device_with_vid_pid(ctx, m_dev_pid_vid[index].second, m_dev_pid_vid[index].first); + + if(dev_handle == 0) + return FAILURE; + if(libusb_kernel_driver_active(dev_handle, 0) == 1) //find out if kernel driver is attached + { + printf("Kernel Driver Active\n"); + if(libusb_detach_kernel_driver(dev_handle, 0) == 0) //detach it + printf("Kernel Driver Detached!\n"); + } + int r = libusb_claim_interface(dev_handle, 0); //claim interface 0 (the first) of device + if(r < 0) + { + printf("Cannot Claim Interface\n"); + return CANNOT_CLAIM_INTERFACE; + } + printf("Claimed Interface\n"); + isConnected = true; + return SUCCESS; + } + else + { + return FAILURE; + } +#endif +} + +/** @brief Closes communication to device. +*/ +void ConnectionUSB::Close() +{ + #ifndef __unix__ + USBDevicePrimary->Close(); + InEndPt = NULL; + OutEndPt = NULL; + if (InCtrlEndPt3) + { + delete InCtrlEndPt3; + InCtrlEndPt3 = NULL; + } + if (OutCtrlEndPt3) + { + delete OutCtrlEndPt3; + OutCtrlEndPt3 = NULL; + } + #else + if(dev_handle != 0) + { + libusb_release_interface(dev_handle, 0); + libusb_close(dev_handle); + dev_handle = 0; + } + #endif + isConnected = false; +} + +/** @brief Returns connection status + @return 1-connection open, 0-connection closed. +*/ +bool ConnectionUSB::IsOpen() +{ + #ifndef __unix__ + return USBDevicePrimary->IsOpen() && isConnected; + #else + return isConnected; + #endif +} + +/** @brief Sends given data buffer to chip through USB port. + @param buffer data buffer, must not be longer than 64 bytes. + @param length given buffer size. + @param timeout_ms timeout limit for operation in milliseconds + @return number of bytes sent. +*/ +int ConnectionUSB::Write(const unsigned char *buffer, const int length, int timeout_ms) +{ + long len = length; + if(IsOpen()) + { + unsigned char* wbuffer = new unsigned char[length]; + memcpy(wbuffer, buffer, length); + if(m_hardwareName == HW_DIGIRED || m_hardwareName == HW_STREAMER) + { + #ifndef __unix__ + if(OutCtrlEndPt3) + OutCtrlEndPt3->Write(wbuffer, len); + else + len = 0; + #else + len = libusb_control_transfer(dev_handle, LIBUSB_REQUEST_TYPE_VENDOR,CTR_W_REQCODE ,CTR_W_VALUE, CTR_W_INDEX, wbuffer, length, USB_TIMEOUT); + #endif + } + else + { + #ifndef __unix__ + if(OutCtrEndPt) + OutCtrEndPt->XferData(wbuffer, len); + else + len = 0; + #else + int actual = 0; + libusb_bulk_transfer(dev_handle, 0x01, wbuffer, len, &actual, USB_TIMEOUT); + len = actual; + #endif + } + delete wbuffer; + } + else + return 0; + return len; +} + +/** @brief Reads data coming from the chip through USB port. + @param buffer pointer to array where received data will be copied, array must be + big enough to fit received data. + @param length number of bytes to read from chip. + @param timeout_ms timeout limit for operation in milliseconds + @return number of bytes received. +*/ +int ConnectionUSB::Read(unsigned char *buffer, const int length, int timeout_ms) +{ + long len = length; + if(IsOpen()) + { + if(m_hardwareName == HW_DIGIRED || m_hardwareName == HW_STREAMER) + { + #ifndef __unix__ + if(InCtrlEndPt3) + InCtrlEndPt3->Read(buffer, len); + else + len = 0; + #else + len = libusb_control_transfer(dev_handle, LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_ENDPOINT_IN ,CTR_R_REQCODE ,CTR_R_VALUE, CTR_R_INDEX, buffer, len, USB_TIMEOUT); + #endif + } + else + { + #ifndef __unix__ + if(InCtrEndPt) + InCtrEndPt->XferData(buffer, len); + else + len = 0; + #else + int actual = 0; + libusb_bulk_transfer(dev_handle, 0x81, buffer, len, &actual, USB_TIMEOUT); + len = actual; + #endif + } + } + return len; +} + +#ifdef __unix__ +/** @brief Function for handling libusb callbacks +*/ +void callback_libusbtransfer(libusb_transfer *trans) +{ + USBTransferContext *context = reinterpret_cast(trans->user_data); + switch(trans->status) + { + case LIBUSB_TRANSFER_CANCELLED: + printf("Transfer canceled\n" ); + context->bytesXfered = trans->actual_length; + context->done = true; + context->used = false; + context->reset(); + break; + case LIBUSB_TRANSFER_COMPLETED: + if(trans->actual_length == context->bytesExpected) + { + context->bytesXfered = trans->actual_length; + context->done = true; + } + //printf("Transfer complete %i\n", trans->actual_length); + break; + case LIBUSB_TRANSFER_ERROR: + printf("TRANSFER ERRRO\n"); + break; + case LIBUSB_TRANSFER_TIMED_OUT: + printf("transfer timed out\n"); + + break; + case LIBUSB_TRANSFER_OVERFLOW: + printf("transfer overflow\n"); + + break; + case LIBUSB_TRANSFER_STALL: + printf("transfer stalled\n"); + break; + } + context->mPacketProcessed.notify_one(); +} +#endif + +/** @brief Finds all chips connected to usb ports + @return number of devices found +*/ +int ConnectionUSB::RefreshDeviceList() +{ + #ifndef __unix__ + USBDevicePrimary->Close(); + currentDeviceIndex = -1; + m_deviceNames.clear(); + string name; + if (USBDevicePrimary->DeviceCount()) + { + for (int i=0; iDeviceCount(); ++i) + { + Open(i); + name = DeviceName(); + m_deviceNames.push_back(name); + } + currentDeviceIndex = -1; + } + #else + m_dev_pid_vid.clear(); + m_deviceNames.clear(); + int usbDeviceCount = libusb_get_device_list(ctx, &devs); + if(usbDeviceCount > 0) + { + libusb_device_descriptor desc; + for(int i=0; i(pid,vid)); + } + else if(pid == 241) + { + m_hardwareName = HW_DIGIRED; + libusb_device_handle *tempDev_handle; + tempDev_handle = libusb_open_device_with_vid_pid(ctx, vid, pid); + if(libusb_kernel_driver_active(tempDev_handle, 0) == 1) //find out if kernel driver is attached + { + if(libusb_detach_kernel_driver(tempDev_handle, 0) == 0) //detach it + printf("Kernel Driver Detached!\n"); + } + if(libusb_claim_interface(tempDev_handle, 0) < 0) //claim interface 0 (the first) of device + { + printf("Cannot Claim Interface\n"); + } + + string fullName; + //check operating speed + int speed = libusb_get_device_speed(devs[i]); + if(speed == LIBUSB_SPEED_HIGH) + fullName = "USB 2.0"; + else if(speed == LIBUSB_SPEED_SUPER) + fullName = "USB 3.0"; + else + fullName = "USB"; + fullName += " ("; + //read device name + char data[255]; + memset(data, 0, 255); + int st = libusb_get_string_descriptor_ascii(tempDev_handle, 2, (unsigned char*)data, 255); + if(strlen(data) > 0) + fullName += data; + fullName += ")"; + libusb_close(tempDev_handle); + + m_deviceNames.push_back(fullName); + m_dev_pid_vid.push_back( pair(pid,vid)); + } + } + } + } + else + { + libusb_free_device_list(devs, 1); + return 0; + } + #endif + return m_deviceNames.size(); +} + +void ConnectionUSB::ClearComm() +{ +} + +/** @return name of currently opened device as string. +*/ +string ConnectionUSB::DeviceName() +{ +#ifndef __unix__ + string name; + char tempName[USB_STRING_MAXLEN]; + //memcpy(tempName, USBDevicePrimary->FriendlyName, USB_STRING_MAXLEN); + //name = tempName; + + for (int i = 0; i < USB_STRING_MAXLEN; ++i) + tempName[i] = USBDevicePrimary->DeviceName[i]; + if (USBDevicePrimary->bSuperSpeed == true) + name = "USB 3.0"; + else if (USBDevicePrimary->bHighSpeed == true) + name = "USB 2.0"; + else + name = "USB"; + name += " ("; + name += tempName; + name += ")"; + return name; +#else + if(dev_handle != 0) + { + char data[255]; + int st = libusb_get_string_descriptor_ascii(dev_handle, 2, (unsigned char*)data, 255); + return string(data); + } + return "no name"; +#endif +} + +/** + @brief Starts asynchronous data reading from board + @param *buffer buffer where to store received data + @param length number of bytes to read + @return handle of transfer context +*/ +int ConnectionUSB::BeginDataReading(char *buffer, long length) +{ + int i = 0; + bool contextFound = false; + //find not used context + for(i = 0; iBeginDataXfer((unsigned char*)buffer, length, contexts[i].inOvLap); + return i; + #else + unsigned int Timeout = 1000; + libusb_transfer *tr = contexts[i].transfer; + libusb_fill_bulk_transfer(tr, dev_handle, 0x81, (unsigned char*)buffer, length, callback_libusbtransfer, &contexts[i], Timeout); + contexts[i].done = false; + contexts[i].bytesXfered = 0; + contexts[i].bytesExpected = length; + int status = libusb_submit_transfer(tr); + int actual = 0; + //int status = libusb_bulk_transfer(dev_handle, 0x81, (unsigned char*)buffer, length, &actual, USB_TIMEOUT); + if(status != 0) + printf("ERROR BEGIN DATA TRANSFER %s\n", libusb_error_name(status)); + #endif + return i; +} + +/** + @brief Waits for asynchronous data reception + @param contextHandle handle of which context data to wait + @param timeout_ms number of miliseconds to wait + @return 1-data received, 0-data not received +*/ +int ConnectionUSB::WaitForReading(int contextHandle, unsigned int timeout_ms) +{ + if( contexts[contextHandle].used == true && contextHandle >= 0) + { + int status = 0; + #ifndef __unix__ + if(InEndPt) + status = InEndPt->WaitForXfer(contexts[contextHandle].inOvLap, timeout_ms); + return status; + #else + + struct timeval tv; + tv.tv_sec = 0; + tv.tv_usec = 0; + if(libusb_handle_events_timeout_completed(ctx, &tv, NULL) != 0) + printf("error libusb_handle_events %i\n", status); + + auto t1 = chrono::high_resolution_clock::now(); + auto t2 = chrono::high_resolution_clock::now(); + + while(contexts[contextHandle].done == false && std::chrono::duration_cast(t2 - t1).count() < timeout_ms) + { + struct timeval tv; + tv.tv_sec = 0; + tv.tv_usec = 300; + std::this_thread::yield(); + //if(libusb_handle_events(ctx) != 0) + if(libusb_handle_events_timeout_completed(ctx, &tv, NULL) != 0) + printf("error libusb_handle_events %i\n", status); + t2 = chrono::high_resolution_clock::now(); + //std::this_thread::sleep_for(std::chrono::milliseconds(1)); + } + std::unique_lock lck(contexts[contextHandle].m_lock); + while(contexts[contextHandle].done == false) //is changed in libusb callback + { + if(contexts[contextHandle].mPacketProcessed.wait_for(lck, std::chrono::milliseconds(timeout_ms)) == std::cv_status::timeout) + return 0; + } + return contexts[contextHandle].done == true; + #endif + } + else + return 0; +} + +/** + @brief Finishes asynchronous data reading from board + @param buffer array where to store received data + @param length number of bytes to read, function changes this value to number of bytes actually received + @param contextHandle handle of which context to finish + @return false failure, true number of bytes received +*/ +int ConnectionUSB::FinishDataReading(char *buffer, long &length, int contextHandle) +{ + if( contexts[contextHandle].used == true && contextHandle >= 0) + { + #ifndef __unix__ + int status = 0; + if(InEndPt) + status = InEndPt->FinishDataXfer((unsigned char*)buffer, length, contexts[contextHandle].inOvLap, contexts[contextHandle].context); + contexts[contextHandle].used = false; + contexts[contextHandle].reset(); + return length; + #else + length = contexts[contextHandle].bytesXfered; + contexts[contextHandle].used = false; + contexts[contextHandle].reset(); + return length; + #endif + } + else + return 0; +} + +int ConnectionUSB::ReadDataBlocking(char *buffer, long &length, int timeout_ms) +{ +#ifndef __unix__ + return InEndPt->XferData((unsigned char*)buffer, length); +#else + return 0; +#endif +} + + +/** + @brief Aborts reading operations +*/ +void ConnectionUSB::AbortReading() +{ +#ifndef __unix__ + InEndPt->Abort(); +#else + for(int i=0; iBeginDataXfer((unsigned char*)buffer, length, contextsToSend[i].inOvLap); + return i; + #else + unsigned int Timeout = 1000; + libusb_transfer *tr = contextsToSend[i].transfer; + //libusb_set_iso_packet_lengths(contexts[i].transfer, 512*64); + libusb_fill_bulk_transfer(tr, dev_handle, 0x1, (unsigned char*)buffer, length, callback_libusbtransfer, &contextsToSend[i], Timeout); + contextsToSend[i].done = false; + contextsToSend[i].bytesXfered = 0; + contextsToSend[i].bytesExpected = length; + libusb_submit_transfer(tr); + #endif + return i; +} + +/** + @brief Waits for asynchronous data sending + @param contextHandle handle of which context data to wait + @param timeout_ms number of miliseconds to wait + @return 1-data received, 0-data not received +*/ +int ConnectionUSB::WaitForSending(int contextHandle, unsigned int timeout_ms) +{ + if( contextsToSend[contextHandle].used == true ) + { + #ifndef __unix__ + int status = 0; + if(OutEndPt) + status = OutEndPt->WaitForXfer(contextsToSend[contextHandle].inOvLap, timeout_ms); + return status; + #else + auto t1 = chrono::high_resolution_clock::now(); + auto t2 = chrono::high_resolution_clock::now(); + while(contextsToSend[contextHandle].done == false && std::chrono::duration_cast(t2 - t1).count() < timeout_ms) + { + /* struct timeval tv; + tv.tv_sec = 1; + tv.tv_usec = 0; + int status = libusb_handle_events_timeout_completed(ctx, &tv, NULL); + if(status != 0) + printf("error libusb_handle_events %i\n", status);*/ + t2 = chrono::high_resolution_clock::now(); + //std::this_thread::sleep_for(std::chrono::milliseconds(1)); + } + std::unique_lock lck(contextsToSend[contextHandle].m_lock); + while(contextsToSend[contextHandle].done == false) //is changed in libusb callback + { + if(contextsToSend[contextHandle].mPacketProcessed.wait_for(lck, std::chrono::milliseconds(timeout_ms)) == std::cv_status::timeout) + return 0; + } + return contextsToSend[contextHandle].done == true; + #endif + } + else + return 0; +} + +/** + @brief Finishes asynchronous data sending to board + @param buffer array where to store received data + @param length number of bytes to read, function changes this value to number of bytes acctually received + @param contextHandle handle of which context to finish + @return false failure, true number of bytes sent +*/ +int ConnectionUSB::FinishDataSending(const char *buffer, long &length, int contextHandle) +{ + if( contextsToSend[contextHandle].used == true) + { + #ifndef __unix__ + if(OutEndPt) + OutEndPt->FinishDataXfer((unsigned char*)buffer, length, contextsToSend[contextHandle].inOvLap, contextsToSend[contextHandle].context); + contextsToSend[contextHandle].used = false; + contextsToSend[contextHandle].reset(); + return length; + #else + length = contextsToSend[contextHandle].bytesXfered; + contextsToSend[contextHandle].used = false; + contextsToSend[contextHandle].reset(); + return length; + #endif + } + else + return 0; +} + +/** + @brief Aborts sending operations +*/ +void ConnectionUSB::AbortSending() +{ +#ifndef __unix__ + OutEndPt->Abort(); +#else + for (int i = 0; i ConnectionUSB::GetDeviceNames() +{ + return m_deviceNames; +} diff --git a/targets/ARCH/LMSSDR/USERSPACE/LIB/lmsSDR/connectionManager/ConnectionUSB.h b/targets/ARCH/LMSSDR/USERSPACE/LIB/lmsSDR/connectionManager/ConnectionUSB.h new file mode 100644 index 0000000000..f3048c1842 --- /dev/null +++ b/targets/ARCH/LMSSDR/USERSPACE/LIB/lmsSDR/connectionManager/ConnectionUSB.h @@ -0,0 +1,144 @@ +/** +@file ConnectionUSB.h +@author Lime Microsystems (www.limemicro.com) +@brief Class for data writing and reading through USB port +*/ + +#ifndef USB_PORT_CONNECTION_H +#define USB_PORT_CONNECTION_H + +#include "IConnection.h" + +#ifndef __unix__ +#include "windows.h" +#include "CyAPI.h" +#else +#include +#include +#include +#include +#endif + +#define USB_MAX_CONTEXTS 64 //maximum number of contexts for asynchronous transfers + +/** @brief Wrapper class for holding USB asynchronous transfers contexts +*/ +class USBTransferContext +{ +public: + USBTransferContext() : used(false) + { + #ifndef __unix__ + inOvLap = new OVERLAPPED; + memset(inOvLap, 0, sizeof(OVERLAPPED)); + inOvLap->hEvent = CreateEvent(NULL, false, false, NULL); + context = NULL; + #else + transfer = libusb_alloc_transfer(0); + bytesXfered = 0; + bytesExpected = 0; + done = 0; + #endif + } + ~USBTransferContext() + { + #ifndef __unix__ + CloseHandle(inOvLap->hEvent); + delete inOvLap; + #else + libusb_free_transfer(transfer); + #endif + } + bool reset() + { + if(used) + return false; + #ifndef __unix__ + CloseHandle(inOvLap->hEvent); + memset(inOvLap, 0, sizeof(OVERLAPPED)); + inOvLap->hEvent = CreateEvent(NULL, false, false, NULL); + #endif + return true; + } + bool used; + #ifndef __unix__ + PUCHAR context; + OVERLAPPED *inOvLap; + #else + libusb_transfer* transfer; + long bytesXfered; + long bytesExpected; + bool done; + std::mutex m_lock; + std::condition_variable mPacketProcessed; + #endif +}; + +class ConnectionUSB : public IConnection +{ +public: + ConnectionUSB(); + ~ConnectionUSB(); + + void FindDevices(); + DeviceStatus Open(); + DeviceStatus Open(unsigned index); + void Close(); + bool IsOpen(); + int GetOpenedIndex(); + + int Write(const unsigned char *buffer, int length, int timeout_ms = 0); + int Read(unsigned char *buffer, int length, int timeout_ms = 0); + + virtual int BeginDataReading(char *buffer, long length); + virtual int WaitForReading(int contextHandle, unsigned int timeout_ms); + virtual int FinishDataReading(char *buffer, long &length, int contextHandle); + virtual void AbortReading(); + virtual int ReadDataBlocking(char *buffer, long &length, int timeout_ms); + + virtual int BeginDataSending(const char *buffer, long length); + virtual int WaitForSending(int contextHandle, unsigned int timeout_ms); + virtual int FinishDataSending(const char *buffer, long &length, int contextHandle); + virtual void AbortSending(); + + std::vector GetDeviceNames(); + int RefreshDeviceList(); + void ClearComm(); +private: + int currentDeviceIndex; + std::string DeviceName(); + + std::vector m_deviceNames; + std::string m_hardwareName; + int m_hardwareVer; + + USBTransferContext contexts[USB_MAX_CONTEXTS]; + USBTransferContext contextsToSend[USB_MAX_CONTEXTS]; + void Initialize(); + + bool isConnected; + int currentPortIndex; + + #ifndef __unix__ + CCyUSBDevice *USBDevicePrimary; + //control endpoints for DigiRed + CCyControlEndPoint *InCtrlEndPt3; + CCyControlEndPoint *OutCtrlEndPt3; + + //control endpoints for DigiGreen + CCyUSBEndPoint *OutCtrEndPt; + CCyUSBEndPoint *InCtrEndPt; + + //end points for samples reading and writing + CCyUSBEndPoint *InEndPt; + CCyUSBEndPoint *OutEndPt; + + #else + libusb_device **devs; //pointer to pointer of device, used to retrieve a list of devices + libusb_device_handle *dev_handle; //a device handle + libusb_context *ctx; //a libusb session + std::vector > m_dev_pid_vid; + #endif +}; + +#endif diff --git a/targets/ARCH/LMSSDR/USERSPACE/LIB/lmsSDR/connectionManager/IConnection.h b/targets/ARCH/LMSSDR/USERSPACE/LIB/lmsSDR/connectionManager/IConnection.h new file mode 100644 index 0000000000..5804f1149f --- /dev/null +++ b/targets/ARCH/LMSSDR/USERSPACE/LIB/lmsSDR/connectionManager/IConnection.h @@ -0,0 +1,68 @@ +/** + @file IConnection.h + @author Lime Microsystems + @brief Interface class for connection types +*/ + +#ifndef ICONNECTION_H +#define ICONNECTION_H + +#include +#include + +using namespace std; + +class IConnection +{ +public: + /// Supported connection types. + enum eConnectionType + { + CONNECTION_UNDEFINED = -1, + COM_PORT = 0, + USB_PORT = 1, + SPI_PORT = 2, + //insert new types here + CONNECTION_TYPES_COUNT //used only for memory allocation + }; + + enum DeviceStatus + { + SUCCESS, + FAILURE, + END_POINTS_NOT_FOUND, + CANNOT_CLAIM_INTERFACE + }; + + IConnection() : m_connectionType(CONNECTION_UNDEFINED){}; + virtual ~IConnection(){}; + virtual int RefreshDeviceList() = 0; + virtual DeviceStatus Open(unsigned i) = 0; + virtual void Close() = 0; + virtual bool IsOpen() = 0; + virtual int GetOpenedIndex() = 0; + + virtual int Write(const unsigned char *buffer, int length, int timeout_ms = 0) = 0; + virtual int Read(unsigned char *buffer, int length, int timeout_ms = 0) = 0; + + virtual std::vector GetDeviceNames() = 0; + + virtual eConnectionType GetType() { return m_connectionType; }; + virtual bool SetParam(const char *name, const char* value) {return false;}; + + virtual int BeginDataReading(char *buffer, long length){ return -1; }; + virtual int WaitForReading(int contextHandle, unsigned int timeout_ms){ return 0;}; + virtual int FinishDataReading(char *buffer, long &length, int contextHandle){ return 0;} + virtual void AbortReading(){}; + virtual int ReadDataBlocking(char *buffer, long &length, int timeout_ms){ return 0; } + + virtual int BeginDataSending(const char *buffer, long length){ return -1; }; + virtual int WaitForSending(int contextHandle, unsigned int timeout_ms){ return 0;}; + virtual int FinishDataSending(const char *buffer, long &length, int contextHandle){ return 0;} + virtual void AbortSending(){}; +protected: + eConnectionType m_connectionType; +}; + +#endif + diff --git a/targets/ARCH/LMSSDR/USERSPACE/LIB/lmsSDR/connectionManager/lmsComms.cpp b/targets/ARCH/LMSSDR/USERSPACE/LIB/lmsSDR/connectionManager/lmsComms.cpp new file mode 100644 index 0000000000..0e5ec66762 --- /dev/null +++ b/targets/ARCH/LMSSDR/USERSPACE/LIB/lmsSDR/connectionManager/lmsComms.cpp @@ -0,0 +1,325 @@ +/** +@file LMScomms.cpp +@author Lime Microsystems (www.limemicro.com) +@brief Implementation of data transmission to LMS boards +*/ + +#include "lmsComms.h" + +LMScomms::LMScomms(const IConnection::eConnectionType port_type) : ConnectionManager(port_type) +{ + callback_logData = nullptr; + unsigned short test = 0x1234; + unsigned char* bytes = (unsigned char*)&test; + if(bytes[0] == 0x12 && bytes[1] == 0x34) + mSystemBigEndian = true; + else + mSystemBigEndian = false; +} + +LMScomms::~LMScomms() +{ +} + +/** @brief Transfers data between packet and connected device + @param pkt packet containing output data and to receive incomming data + @return 0: success, other: failure +*/ +LMScomms::TransferStatus LMScomms::TransferPacket(GenericPacket& pkt) +{ + std::lock_guard lock(mControlPortLock); + TransferStatus status = TRANSFER_SUCCESS; + if(IsOpen() == false) + return NOT_CONNECTED; + + int packetLen; + eLMS_PROTOCOL protocol = LMS_PROTOCOL_UNDEFINED; + if(activeControlPort->GetType() == IConnection::SPI_PORT) + protocol = LMS_PROTOCOL_NOVENA; + else + protocol = LMS_PROTOCOL_LMS64C; + switch(protocol) + { + case LMS_PROTOCOL_UNDEFINED: + return TRANSFER_FAILED; + case LMS_PROTOCOL_LMS64C: + packetLen = ProtocolLMS64C::pktLength; + break; + case LMS_PROTOCOL_NOVENA: + packetLen = pkt.outBuffer.size() > ProtocolNovena::pktLength ? ProtocolNovena::pktLength : pkt.outBuffer.size(); + break; + default: + packetLen = 0; + return TRANSFER_FAILED; + } + int outLen = 0; + unsigned char* outBuffer = NULL; + outBuffer = PreparePacket(pkt, outLen, protocol); + unsigned char* inBuffer = new unsigned char[outLen]; + memset(inBuffer, 0, outLen); + + int outBufPos = 0; + int inDataPos = 0; + if(outLen == 0) + { + //printf("packet outlen = 0\n"); + outLen = 1; + } + + if(protocol == LMS_PROTOCOL_NOVENA) + { + bool transferData = true; //some commands are fake, so don't need transferring + if(pkt.cmd == CMD_GET_INFO) + { + //spi does not have GET INFO, fake it to inform what device it is + pkt.status = STATUS_COMPLETED_CMD; + pkt.inBuffer.clear(); + pkt.inBuffer.resize(64, 0); + pkt.inBuffer[0] = 0; //firmware + pkt.inBuffer[1] = LMS_DEV_NOVENA; //device + pkt.inBuffer[2] = 0; //protocol + pkt.inBuffer[3] = 0; //hardware + pkt.inBuffer[4] = EXP_BOARD_UNSUPPORTED; //expansion + transferData = false; + } + + if(transferData) + { + if (callback_logData) + callback_logData(true, outBuffer, outLen); + int bytesWritten = Write(outBuffer, outLen); + if( bytesWritten == outLen) + { + if(pkt.cmd == CMD_LMS7002_RD) + { + inDataPos = Read(&inBuffer[inDataPos], outLen); + if(inDataPos != outLen) + status = TRANSFER_FAILED; + else + { + if (callback_logData) + callback_logData(false, inBuffer, inDataPos); + } + } + ParsePacket(pkt, inBuffer, inDataPos, protocol); + } + else + status = TRANSFER_FAILED; + } + } + else + { + for(int i=0; i= 5) + { + info.firmware = pkt.inBuffer[0]; + info.device = pkt.inBuffer[1] < LMS_DEV_COUNT ? (eLMS_DEV)pkt.inBuffer[1] : LMS_DEV_UNKNOWN; + info.protocol = pkt.inBuffer[2]; + info.hardware = pkt.inBuffer[3]; + info.expansion = pkt.inBuffer[4] < EXP_BOARD_COUNT ? (eEXP_BOARD)pkt.inBuffer[4] : EXP_BOARD_UNKNOWN; + } + return info; +} + +/** @brief Takes generic packet and converts to specific protocol buffer + @param pkt generic data packet to convert + @param length returns length of returned buffer + @param protocol which protocol to use for data + @return pointer to data buffer, must be manually deleted after use +*/ +unsigned char* LMScomms::PreparePacket(const GenericPacket& pkt, int& length, const eLMS_PROTOCOL protocol) +{ + unsigned char* buffer = NULL; + if(protocol == LMS_PROTOCOL_UNDEFINED) + return NULL; + + if(protocol == LMS_PROTOCOL_LMS64C) + { + ProtocolLMS64C packet; + int maxDataLength = packet.maxDataLength; + packet.cmd = pkt.cmd; + packet.status = pkt.status; + int byteBlockRatio = 1; //block ratio - how many bytes in one block + switch( packet.cmd ) + { + case CMD_PROG_MCU: + case CMD_GET_INFO: + case CMD_SI5351_RD: + case CMD_SI5356_RD: + byteBlockRatio = 1; + break; + case CMD_SI5351_WR: + case CMD_SI5356_WR: + byteBlockRatio = 2; + break; + case CMD_LMS7002_RD: + case CMD_BRDSPI_RD: + case CMD_BRDSPI8_RD: + byteBlockRatio = 2; + break; + case CMD_ADF4002_WR: + byteBlockRatio = 3; + break; + case CMD_LMS7002_WR: + case CMD_BRDSPI_WR: + case CMD_ANALOG_VAL_WR: + byteBlockRatio = 4; + break; + default: + byteBlockRatio = 1; + } + if (packet.cmd == CMD_LMS7002_RD || packet.cmd == CMD_BRDSPI_RD) + maxDataLength = maxDataLength/2; + if (packet.cmd == CMD_ANALOG_VAL_RD) + maxDataLength = maxDataLength / 4; + int blockCount = pkt.outBuffer.size()/byteBlockRatio; + int bufLen = blockCount/(maxDataLength/byteBlockRatio) + +(blockCount%(maxDataLength/byteBlockRatio)!=0); + bufLen *= packet.pktLength; + if(bufLen == 0) + bufLen = packet.pktLength; + buffer = new unsigned char[bufLen]; + memset(buffer, 0, bufLen); + int srcPos = 0; + for(int j=0; j*packet.pktLength (maxDataLength/byteBlockRatio)) + { + buffer[pktPos+2] = maxDataLength/byteBlockRatio; + blockCount -= buffer[pktPos+2]; + } + else + buffer[pktPos+2] = blockCount; + memcpy(&buffer[pktPos+3], packet.reserved, sizeof(packet.reserved)); + int bytesToPack = (maxDataLength/byteBlockRatio)*byteBlockRatio; + for (int k = 0; k callback) +{ + callback_logData = callback; +} diff --git a/targets/ARCH/LMSSDR/USERSPACE/LIB/lmsSDR/connectionManager/lmsComms.h b/targets/ARCH/LMSSDR/USERSPACE/LIB/lmsSDR/connectionManager/lmsComms.h new file mode 100644 index 0000000000..f811d29302 --- /dev/null +++ b/targets/ARCH/LMSSDR/USERSPACE/LIB/lmsSDR/connectionManager/lmsComms.h @@ -0,0 +1,111 @@ +/** +@file LMScomms.h +@author Lime Microsystems (www.limemicro.com) +@brief Class for handling data transmission to LMS boards +*/ + +#ifndef LMS_COMMS_H +#define LMS_COMMS_H + +#include "lms7002_defines.h" +#include "ConnectionManager.h" +#include +#include + +struct LMSinfo +{ + eLMS_DEV device; + eEXP_BOARD expansion; + int firmware; + int hardware; + int protocol; +}; + +/* @brief Class for abstracting transfering data to and from chip +*/ +class LMScomms : public ConnectionManager +{ +public: + enum TransferStatus + { + TRANSFER_SUCCESS, + TRANSFER_FAILED, + NOT_CONNECTED + }; + + enum eLMS_PROTOCOL + { + LMS_PROTOCOL_UNDEFINED = 0, + LMS_PROTOCOL_DIGIC, + LMS_PROTOCOL_LMS64C, + LMS_PROTOCOL_NOVENA, + }; + struct ProtocolDIGIC + { + static const int pktLength = 64; + static const int maxDataLength = 60; + ProtocolDIGIC() : cmd(0), i2cAddr(0), blockCount(0) {}; + unsigned char cmd; + unsigned char i2cAddr; + unsigned char blockCount; + unsigned char reserved; + unsigned char data[maxDataLength]; + }; + + struct ProtocolLMS64C + { + static const int pktLength = 64; + static const int maxDataLength = 56; + ProtocolLMS64C() :cmd(0),status(STATUS_UNDEFINED),blockCount(0) + { + memset(reserved, 0, 5); + }; + unsigned char cmd; + unsigned char status; + unsigned char blockCount; + unsigned char reserved[5]; + unsigned char data[maxDataLength]; + }; + + struct ProtocolNovena + { + static const int pktLength = 128; + static const int maxDataLength = 128; + ProtocolNovena() :cmd(0),status(0) {}; + unsigned char cmd; + unsigned char status; + unsigned char blockCount; + unsigned char data[maxDataLength]; + }; + + struct GenericPacket + { + GenericPacket() + { + cmd = CMD_GET_INFO; + status = STATUS_UNDEFINED; + } + + eCMD_LMS cmd; + eCMD_STATUS status; + vector outBuffer; + vector inBuffer; + }; + + LMScomms(const IConnection::eConnectionType port_type); + ~LMScomms(); + + virtual TransferStatus TransferPacket(GenericPacket &pkt); + LMSinfo GetInfo(); + void SetDataLogCallback(std::function callback); +protected: + std::function callback_logData; + std::mutex mControlPortLock; + unsigned char* PreparePacket(const GenericPacket &pkt, int &length, const eLMS_PROTOCOL protocol); + int ParsePacket(GenericPacket &pkt, const unsigned char* buffer, const int length, const eLMS_PROTOCOL protocol); +protected: + bool mSystemBigEndian; +}; + +#endif // LMS_COMMS_H + diff --git a/targets/ARCH/LMSSDR/USERSPACE/LIB/lmsSDR/dataTypes.h b/targets/ARCH/LMSSDR/USERSPACE/LIB/lmsSDR/dataTypes.h new file mode 100644 index 0000000000..cba2b7341e --- /dev/null +++ b/targets/ARCH/LMSSDR/USERSPACE/LIB/lmsSDR/dataTypes.h @@ -0,0 +1,33 @@ +#ifndef LMS_DATA_TYPES_H +#define LMS_DATA_TYPES_H + +typedef struct +{ + uint8_t reserved[8]; + uint64_t counter; + int16_t samples[2040]; +} PacketLTE; + +typedef struct +{ + int16_t i; + int16_t q; +} complex16_t; + +typedef struct +{ + uint64_t timestamp; //timestamp of the packet + uint16_t first; //index of first unused sample in samples[] + uint16_t last; //end index of samples + static const uint16_t samplesCount = 1024; //maximum number of samples in packet + complex16_t samples[samplesCount]; //must be power of two +} SamplesPacket; + +complex16_t operator &=(complex16_t & other1, const complex16_t & other) // copy assignment +{ + other1.i = other.i; + other1.q = other.q; + return other1; +} + +#endif \ No newline at end of file diff --git a/targets/ARCH/LMSSDR/USERSPACE/LIB/lmsSDR/fifo.h b/targets/ARCH/LMSSDR/USERSPACE/LIB/lmsSDR/fifo.h new file mode 100644 index 0000000000..1868c64af7 --- /dev/null +++ b/targets/ARCH/LMSSDR/USERSPACE/LIB/lmsSDR/fifo.h @@ -0,0 +1,180 @@ +#ifndef LMS_FIFO_BUFFER_H +#define LMS_FIFO_BUFFER_H + +#include +#include +#include +#include +#include +#include "dataTypes.h" + +class LMS_SamplesFIFO +{ +public: + struct BufferInfo + { + uint32_t size; + uint32_t itemsFilled; + }; + + BufferInfo GetInfo() + { + std::unique_lock lck2(readLock); + std::unique_lock lck(writeLock); + BufferInfo stats; + stats.size = (uint32_t)mBuffer.size(); + stats.itemsFilled = mElementsFilled.load(); + return stats; + } + + LMS_SamplesFIFO(uint32_t bufLength) + { + Reset(bufLength); + } + + ~LMS_SamplesFIFO(){}; + + /** @brief inserts items to ring buffer + @param buffer data source + @param itemCount number of buffer items to insert + @param timeout_ms timeout duration for operation + @param overwrite enable to overwrite oldest items inside the buffer + @return number of items added + */ + uint32_t push_packet(SamplesPacket *buffer, const uint32_t itemCount, const uint32_t timeout_ms, const bool overwrite = true) + { + uint32_t addedItems = 0; + std::unique_lock lck(writeLock); + while (addedItems < itemCount) + { + while (mElementsFilled.load() >= mBuffer.size()) //wait for free space to insert items + { + if (canWrite.wait_for(lck, std::chrono::milliseconds(timeout_ms)) == std::cv_status::timeout) + return addedItems; //dropped all items + } + + uint32_t itemsToInsert = itemCount - addedItems; + uint32_t itemsToEnd = (uint32_t)mBuffer.size() - mTail.load(); //might need to split memcpy into two operations + if (itemsToInsert > itemsToEnd) + { + memcpy(&mBuffer[mTail], &buffer[addedItems], itemsToEnd*sizeof(SamplesPacket)); + memcpy(&mBuffer[0], &buffer[addedItems+itemsToEnd], (itemsToInsert - itemsToEnd)*sizeof(SamplesPacket)); + } + else + memcpy(&mBuffer[mTail], &buffer[addedItems], itemsToInsert*sizeof(SamplesPacket)); + mTail.store((mTail.load() + itemsToInsert) & (mBuffer.size() - 1)); + mElementsFilled.fetch_add(itemsToInsert); + canRead.notify_one(); + addedItems += itemsToInsert; + } + return addedItems; + } + + /** @brief inserts items to ring buffer + @param buffer data source + @param itemCount number of buffer items to insert + @param timeout_ms timeout duration for operation + @param overwrite enable to overwrite oldest items inside the buffer + @return number of items added + */ + uint32_t push_samples(const complex16_t *buffer, const uint32_t samplesCount, uint64_t timestamp, const uint32_t timeout_ms, const bool overwrite = true) + { + assert(buffer != nullptr); + const int samplesInPacket = SamplesPacket::samplesCount; + uint32_t samplesTaken = 0; + std::unique_lock lck(writeLock); + while (samplesTaken < samplesCount) + { + while (mElementsFilled.load() >= mBuffer.size()) //buffer might be full, wait for free slots + { + if (canWrite.wait_for(lck, std::chrono::milliseconds(timeout_ms)) == std::cv_status::timeout) + return samplesTaken; + } + + int tailIndex = mTail.load(); //which element to fill + while (mElementsFilled.load() < mBuffer.size() && samplesTaken < samplesCount) // not to release lock too often + { + mBuffer[tailIndex].timestamp = timestamp + samplesTaken; + mBuffer[tailIndex].first = 0; + mBuffer[tailIndex].last = 0; + while (mBuffer[tailIndex].last < samplesInPacket && samplesTaken < samplesCount) + { + mBuffer[tailIndex].samples[mBuffer[tailIndex].last++] = buffer[samplesTaken++]; + } + mTail.store((tailIndex + 1) & (mBuffer.size() - 1));//advance to next one + tailIndex = mTail.load(); + mElementsFilled.fetch_add(1); + canRead.notify_one(); + } + } + return samplesTaken; + } + + /** @brief Takes items out of ring buffer + @param buffer data destination + @param samplesCount number of samples to pop + @param timestamp returns timestamp of the first sample in buffer + @param timeout_ms timeout duration for operation + @return number of samples returned + */ + uint32_t pop_samples(complex16_t* buffer, const uint32_t samplesCount, uint64_t *timestamp, const uint32_t timeout_ms) + { + assert(buffer != nullptr); + const int samplesInPacket = SamplesPacket::samplesCount; + uint32_t samplesFilled = 0; + *timestamp = 0; + std::unique_lock lck(readLock); + while (samplesFilled < samplesCount) + { + while (mElementsFilled.load() == 0) //buffer might be empty, wait for packets + { + if (canRead.wait_for(lck, std::chrono::milliseconds(timeout_ms)) == std::cv_status::timeout) + return samplesFilled; + } + if(samplesFilled == 0) + *timestamp = mBuffer[mHead.load()].timestamp + mBuffer[mHead.load()].first; + + while(mElementsFilled.load() > 0 && samplesFilled < samplesCount) + { + int headIndex = mHead.load(); + while (mBuffer[headIndex].first < mBuffer[headIndex].last && samplesFilled < samplesCount) + { + buffer[samplesFilled++] = mBuffer[headIndex].samples[mBuffer[headIndex].first++]; + } + if (mBuffer[headIndex].first == mBuffer[headIndex].last) //packet depleated + { + mBuffer[headIndex].first = 0; + mBuffer[headIndex].last = 0; + mBuffer[headIndex].timestamp = 0; + mHead.store( (headIndex + 1) & (mBuffer.size() - 1) );//advance to next one + headIndex = mHead.load(); + mElementsFilled.fetch_sub(1); + canWrite.notify_one(); + } + } + } + return samplesFilled; + } + + void Reset(uint32_t bufLength) + { + std::unique_lock lck(writeLock); + std::unique_lock lck2(readLock); + mBuffer.resize(bufLength); + mHead.store(0); + mTail.store(0); + mElementsFilled.store(0); + } + +protected: + std::vector mBuffer; + std::atomic mHead; + std::atomic mTail; + std::mutex writeLock; + std::mutex readLock; + std::atomic mElementsFilled; + std::condition_variable canWrite; + std::condition_variable canRead; +}; + +#endif diff --git a/targets/ARCH/LMSSDR/USERSPACE/LIB/lmsSDR/ringBuffer.h b/targets/ARCH/LMSSDR/USERSPACE/LIB/lmsSDR/ringBuffer.h new file mode 100644 index 0000000000..e4882f8924 --- /dev/null +++ b/targets/ARCH/LMSSDR/USERSPACE/LIB/lmsSDR/ringBuffer.h @@ -0,0 +1,143 @@ +#ifndef LMS_RING_BUFFER_H +#define LMS_RING_BUFFER_H + +#include +#include +#include +#include + +template +class RingBuffer +{ +public: + struct BufferInfo + { + uint32_t size; + uint32_t itemsFilled; + }; + + BufferInfo GetInfo() + { + unique_lock lck(mLock); + BufferInfo stats; + stats.size = (uint32_t)mBuffer.size(); + stats.itemsFilled = mElementsFilled; + return stats; + } + + RingBuffer(uint32_t bufLength) + { + Reset(bufLength); + } + ~RingBuffer(){}; + + /** @brief inserts items to ring buffer + @param buffer data source + @param itemCount number of buffer items to insert + @param timeout_ms timeout duration for operation + @return number of items added + */ + uint32_t push_back(const T* buffer, const uint32_t itemCount, const uint32_t timeout_ms) + { + uint32_t addedItems = 0; + while (addedItems < itemCount) + { + unique_lock lck(mLock); + while (mElementsFilled >= mBuffer.size()) //wait for free space to insert items + { + if (canWrite.wait_for(lck, std::chrono::milliseconds(timeout_ms)) == std::cv_status::timeout) + return addedItems; //dropped all items + } + + uint32_t itemsToInsert = itemCount - addedItems; + uint32_t itemsToEnd = (uint32_t)mBuffer.size() - mTail.load(); //might need to split memcpy into two operations + if (itemsToInsert > itemsToEnd) + { + memcpy(&mBuffer[mTail], &buffer[addedItems], itemsToEnd*sizeof(T)); + memcpy(&mBuffer[0], &buffer[addedItems+itemsToEnd], (itemsToInsert - itemsToEnd)*sizeof(T)); + } + else + memcpy(&mBuffer[mTail], &buffer[addedItems], itemsToInsert*sizeof(T)); + mTail.store((mTail.load() + itemsToInsert) & (mBuffer.size() - 1)); + mElementsFilled += itemsToInsert; + lck.unlock(); + canRead.notify_one(); + addedItems += itemsToInsert; + } + return addedItems; + } + + /** @brief Takes items out of ring buffer + @param buffer data destination + @param itemCount number of items to extract from ring buffer + @param timeout_ms timeout duration for operation + @return number of items returned + */ + uint32_t pop_front(T* buffer, const uint32_t itemCount, const uint32_t timeout_ms) + { + assert(buffer != nullptr); + uint32_t itemsTaken = 0; + T* destBuffer = buffer; + while (itemsTaken < itemCount) + { + unique_lock lck(mLock); + while (mElementsFilled == 0) //buffer might be empty, wait for items + { + if (canRead.wait_for(lck, std::chrono::milliseconds(timeout_ms)) == std::cv_status::timeout) + return itemsTaken; + } + + unsigned int itemsToCopy = itemCount - itemsTaken; + if (itemsToCopy > mElementsFilled) + itemsToCopy = mElementsFilled; + unsigned int itemsToEnd = (uint32_t)mBuffer.size() - mHead.load(); //migth need to split memcpy into two operations + if (itemsToEnd < itemsToCopy) + { + memcpy(&destBuffer[itemsTaken], &mBuffer[mHead.load()], sizeof(T)*itemsToEnd); + memcpy(&destBuffer[itemsTaken+itemsToEnd], &mBuffer[0], sizeof(T)*(itemsToCopy - itemsToEnd)); + mHead.store((itemsToCopy - itemsToEnd) & (mBuffer.size() - 1)); + } + else + { + memcpy(&destBuffer[itemsTaken], &mBuffer[mHead.load()], sizeof(T)*itemsToCopy); + int headVal = mHead.load(); + int valueToStore = (headVal + itemsToCopy) & (mBuffer.size() - 1); + mHead.store(valueToStore); + headVal = mHead.load(); + } + mElementsFilled -= itemsToCopy; + lck.unlock(); + canWrite.notify_one(); + itemsTaken += itemsToCopy; + } + return itemsTaken; + } + + void Reset(uint32_t bufLength) + { + std::unique_lock lck(mLock); + if (bufLength >= (uint32_t)(1 << 31)) + bufLength = (uint32_t)(1 << 31); + for (int i = 0; i < 32; ++i) + if ((1 << i) >= bufLength) + { + bufLength = (1 << i); + break; + } + mBuffer.resize(bufLength); + mHead.store(0); + mTail.store(0); + mElementsFilled = 0; + } + +protected: + std::vector mBuffer; + std::atomic mHead; + std::atomic mTail; + std::mutex mLock; + uint32_t mElementsFilled; + std::condition_variable canWrite; + std::condition_variable canRead; +}; + +#endif diff --git a/targets/ARCH/LMSSDR/USERSPACE/LIB/lms_lib.cpp b/targets/ARCH/LMSSDR/USERSPACE/LIB/lms_lib.cpp new file mode 100644 index 0000000000..8c85863e80 --- /dev/null +++ b/targets/ARCH/LMSSDR/USERSPACE/LIB/lms_lib.cpp @@ -0,0 +1,862 @@ +/******************************************************************************* + OpenAirInterface + Copyright(c) 1999 - 2014 Eurecom + + OpenAirInterface is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + + OpenAirInterface 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 General Public License for more details. + + You should have received a copy of the GNU General Public License + along with OpenAirInterface.The full GNU General Public License is + included in this distribution in the file called "COPYING". If not, + see . + + Contact Information + OpenAirInterface Admin: openair_admin@eurecom.fr + OpenAirInterface Tech : openair_tech@eurecom.fr + OpenAirInterface Dev : openair4g-devel@eurecom.fr + + Address : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE + + *******************************************************************************/ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "common_lib.h" +#include "LMS_SDR.h" +#include "LMS7002M.h" +#include "Si5351C.h" +#include "LMS_StreamBoard.h" +#include "LMS7002M_RegistersMap.h" + +#include + + +///define for parameter enumeration if prefix might be needed +#define LMS7param(id) id + +LMScomms* usbport; +LMScomms* comport; +LMS7002M* lms7; +Si5351C* Si; +LMS_StreamBoard *lmsStream; + +#define RXDCLENGTH 4096 +#define NUMBUFF 40 +int16_t cos_fsover8[8] = {2047, 1447, 0, -1448, -2047, -1448, 0, 1447}; +int16_t cos_3fsover8[8] = {2047, -1448, 0, 1447, -2047, 1447, 0, -1448}; + +extern "C" +{ +int write_output(const char *fname,const char *vname,void *data,int length,int dec,char format); +} + +int trx_lms_write(openair0_device *device, openair0_timestamp timestamp, void **buff, int nsamps, int antenna_id, int flags) { + + LMS_TRxWrite((int16_t*)buff[0], nsamps,0, timestamp); + + return nsamps; +} + + +int trx_lms_read(openair0_device *device, openair0_timestamp *ptimestamp, void **buff, int nsamps, int antenna_id) { + + uint64_t timestamp; + int16_t *dst_ptr = (int16_t*) buff[0]; + int ret; + ret = LMS_TRxRead(dst_ptr, nsamps,0,×tamp, 100); + *ptimestamp=timestamp; + + return ret; +} +void set_rx_gain_offset(openair0_config_t *openair0_cfg, int chain_index) { + + int i=0; + // loop through calibration table to find best adjustment factor for RX frequency + double min_diff = 6e9,diff; + + while (openair0_cfg->rx_gain_calib_table[i].freq>0) { + diff = fabs(openair0_cfg->rx_freq[chain_index] - openair0_cfg->rx_gain_calib_table[i].freq); + printf("cal %d: freq %f, offset %f, diff %f\n", + i, + openair0_cfg->rx_gain_calib_table[i].freq, + openair0_cfg->rx_gain_calib_table[i].offset,diff); + if (min_diff > diff) { + min_diff = diff; + openair0_cfg->rx_gain_offset[chain_index] = openair0_cfg->rx_gain_calib_table[i].offset; + } + i++; + } + +} +/* +void calibrate_rf(openair0_device *device) { + + openair0_timestamp ptimestamp; + int16_t *calib_buffp,*calib_tx_buffp; + int16_t calib_buff[2*RXDCLENGTH]; + int16_t calib_tx_buff[2*RXDCLENGTH]; + int i,j; + int8_t offI,offQ,offIold,offQold,offInew,offQnew,offphase,offphaseold,offphasenew,offgain,offgainold,offgainnew; + int32_t meanI,meanQ,meanIold,meanQold; + int cnt=0,loop; + liblms7_status opStatus; + int16_t dcoffi; + int16_t dcoffq; + int16_t dccorri; + int16_t dccorrq; + const int16_t firCoefs[] = + { + -2531, + -517, + 2708, + 188, + -3059, + 216, + 3569, + -770, + -4199, + 1541, + 4886, + -2577, + -5552, + 3909, + 6108, + -5537, + -6457, + 7440, + 6507, + -9566, + -6174, + 11845, + 5391, + -14179, + -4110, + 16457, + 2310, + -18561, + 0, + 20369, + -2780, + -21752, + 5963, + 22610, + -9456, + -22859, + 13127, + 22444, + -16854, + -21319, + 20489, + 19492, + -23883, + -17002, + 26881, + 13902, + -29372, + -10313, + 31226, + 6345, + -32380, + -2141, + 32767, + -2141, + -32380, + 6345, + 31226, + -10313, + -29372, + 13902, + 26881, + -17002, + -23883, + 19492, + 20489, + -21319, + -16854, + 22444, + 13127, + -22859, + -9456, + 22610, + 5963, + -21752, + -2780, + 20369, + 0, + -18561, + 2310, + 16457, + -4110, + -14179, + 5391, + 11845, + -6174, + -9566, + 6507, + 7440, + -6457, + -5537, + 6108, + 3909, + -5552, + -2577, + 4886, + 1541, + -4199, + -770, + 3569, + 216, + -3059, + 188, + 2708, + -517, + -2531 + }; + + j=0; + for (i=0;iBackupAllRegisters(); + uint8_t ch = (uint8_t)lms7->Get_SPI_Reg_bits(LMS7param(MAC)); + //Stage 1 + uint8_t sel_band1_trf = (uint8_t)lms7->Get_SPI_Reg_bits(LMS7param(SEL_BAND1_TRF)); + uint8_t sel_band2_trf = (uint8_t)lms7->Get_SPI_Reg_bits(LMS7param(SEL_BAND2_TRF)); + { + uint16_t requiredRegs[] = { 0x0400, 0x040A, 0x010D, 0x040C }; + uint16_t requiredMask[] = { 0x6000, 0x3007, 0x0040, 0x00FF }; //CAPSEL, AGC_MODE, AGC_AVG, EN_DCOFF, Bypasses + uint16_t requiredValue[] = { 0x0000, 0x1007, 0x0040, 0x00BD }; + + lms7->Modify_SPI_Reg_mask(requiredRegs, requiredMask, requiredValue, 0, 3); + } + + // opStatus = lms7->SetFrequencySX(LMS7002M::Rx, device->openair0_cfg[0].tx_freq[0]/1e6,30.72); + // put TX on fs/4 + opStatus = lms7->CalibrateRxSetup(device->openair0_cfg[0].sample_rate/1e6); + if (opStatus != LIBLMS7_SUCCESS) { + printf("Cannot calibrate for %f MHz\n",device->openair0_cfg[0].sample_rate/1e6); + exit(-1); + } + // fill TX buffer with fs/8 complex sinusoid + offIold=offQold=64; + lms7->SetRxDCOFF(offIold,offQold); + LMS_RxStart(); + for (i=0;i (%d,%d)\n",offIold,offQold,meanIold,meanQold); + + offI=offQ=-64; + lms7->SetRxDCOFF(offI,offQ); + + for (i=0;i (%d,%d)\n",offI,offQ,meanI,meanQ); + + while (cnt++ < 7) { + + offInew=(offIold+offI)>>1; + offQnew=(offQold+offQ)>>1; + + if (meanI*meanI < meanIold*meanIold) { + meanIold = meanI; + offIold = offI; + printf("[LMS] *** RX DC: offI %d => %d\n",offIold,meanI); + } + if (meanQ*meanQ < meanQold*meanQold) { + meanQold = meanQ; + offQold = offQ; + printf("[LMS] *** RX DC: offQ %d => %d\n",offQold,meanQ); + } + offI = offInew; + offQ = offQnew; + + lms7->SetRxDCOFF(offI,offQ); + + for (i=0;i (%d,%d)\n",offI,offQ,meanI,meanQ); + } + + if (meanI*meanI < meanIold*meanIold) { + meanIold = meanI; + offIold = offI; + printf("[LMS] *** RX DC: offI %d => %d\n",offIold,meanI); + } + if (meanQ*meanQ < meanQold*meanQold) { + meanQold = meanQ; + offQold = offQ; + printf("[LMS] *** RX DC: offQ %d => %d\n",offQold,meanQ); + } + + printf("[LMS] RX DC: (%d,%d) => (%d,%d)\n",offIold,offQold,meanIold,meanQold); + + lms7->SetRxDCOFF(offIold,offQold); + + dcoffi = offIold; + dcoffq = offQold; + + lms7->Modify_SPI_Reg_bits(LMS7param(MAC), ch); + lms7->Modify_SPI_Reg_bits(LMS7param(AGC_MODE_RXTSP), 1); + lms7->Modify_SPI_Reg_bits(LMS7param(CAPSEL), 0); + + // TX LO leakage + offQold=offIold=127; + lms7->SPI_write(0x0204,(((int16_t)offIold)<<7)|offQold); + + { + uint16_t requiredRegs[] = { 0x0400, 0x040A, 0x010D, 0x040C }; + uint16_t requiredMask[] = { 0x6000, 0x3007, 0x0040, 0x00FF }; //CAPSEL, AGC_MODE, AGC_AVG, EN_DCOFF, Bypasses + uint16_t requiredValue[] = { 0x0000, 0x1007, 0x0040, 0x00BD }; + + lms7->Modify_SPI_Reg_mask(requiredRegs, requiredMask, requiredValue, 0, 3); + } + sel_band1_trf = (uint8_t)lms7->Get_SPI_Reg_bits(LMS7param(SEL_BAND1_TRF)); + sel_band2_trf = (uint8_t)lms7->Get_SPI_Reg_bits(LMS7param(SEL_BAND2_TRF)); + //B + lms7->Modify_SPI_Reg_bits(0x0100, 0, 0, 1); //EN_G_TRF 1 + if (sel_band1_trf == 1) + { + lms7->Modify_SPI_Reg_bits(LMS7param(PD_RLOOPB_1_RFE), 0); //PD_RLOOPB_1_RFE 0 + lms7->Modify_SPI_Reg_bits(LMS7param(EN_INSHSW_LB1_RFE), 0); //EN_INSHSW_LB1 0 + } + if (sel_band2_trf == 1) + { + lms7->Modify_SPI_Reg_bits(LMS7param(PD_RLOOPB_2_RFE), 0); //PD_RLOOPB_2_RFE 0 + lms7->Modify_SPI_Reg_bits(LMS7param(EN_INSHSW_LB2_RFE), 0); // EN_INSHSW_LB2 0 + } + // FixRXSaturation(); + + lms7->Modify_SPI_Reg_bits(LMS7param(GFIR3_BYP_RXTSP), 0); //GFIR3_BYP 0 + lms7->Modify_SPI_Reg_bits(LMS7param(HBD_OVR_RXTSP), 2); + lms7->Modify_SPI_Reg_bits(LMS7param(GFIR3_L_RXTSP), 7); + lms7->Modify_SPI_Reg_bits(LMS7param(GFIR3_N_RXTSP), 7); + + lms7->SetGFIRCoefficients(LMS7002M::Rx, 2, firCoefs, sizeof(firCoefs) / sizeof(int16_t)); + + for (i=0;i (%d,%d)\n",offIold,meanIold,meanQold); + + offI=-128; + lms7->SPI_write(0x0204,(((int16_t)offI)<<7)|offQold); + + for (i=0;i (%d,%d)\n",offI,meanI,meanQ); + cnt = 0; + while (cnt++ < 8) { + + offInew=(offIold+offI)>>1; + if (meanI*meanI+meanQ*meanQ < meanIold*meanIold +meanQold*meanQold) { + printf("[LMS] TX DC (offI): ([%d,%d]) => %d : %d\n",offIold,offI,offInew,meanI*meanI+meanQ*meanQ); + meanIold = meanI; + meanQold = meanQ; + offIold = offI; + } + offI = offInew; + lms7->SPI_write(0x0204,(((int16_t)offI)<<7)|offQold); + + for (i=0;i (%d,%d)\n",offI,meanI,meanQ); + } + + + if (meanI*meanI+meanQ*meanQ < meanIold*meanIold +meanQold*meanQold) { + printf("[LMS] TX DC (offI): ([%d,%d]) => %d : %d\n",offIold,offI,offInew,meanI*meanI+meanQ*meanQ); + meanIold = meanI; + meanQold = meanQ; + offIold = offI; + } + offQ=-128; + lms7->SPI_write(0x0204,(((int16_t)offIold)<<7)|offQ); + + for (i=0;i (%d,%d)\n",offQ,meanI,meanQ); + + cnt=0; + while (cnt++ < 8) { + + offQnew=(offQold+offQ)>>1; + if (meanI*meanI+meanQ*meanQ < meanIold*meanIold +meanQold*meanQold) { + printf("[LMS] TX DC (offQ): ([%d,%d]) => %d : %d\n",offQold,offQ,offQnew,meanI*meanI+meanQ*meanQ); + + meanIold = meanI; + meanQold = meanQ; + offQold = offQ; + } + offQ = offQnew; + lms7->SPI_write(0x0204,(((int16_t)offIold)<<7)|offQ); + + + for (i=0;i (%d,%d)\n",offQ,meanI,meanQ); + } + + LMS_RxStop(); + + printf("[LMS] TX DC: (%d,%d) => (%d,%d)\n",offIold,offQold,meanIold,meanQold); + + dccorri = offIold; + dccorrq = offQold; + + + lms7->RestoreAllRegisters(); + lms7->Modify_SPI_Reg_bits(LMS7param(MAC), ch); + + lms7->Modify_SPI_Reg_bits(LMS7param(DCOFFI_RFE), dcoffi); + lms7->Modify_SPI_Reg_bits(LMS7param(DCOFFQ_RFE), dcoffq); + lms7->Modify_SPI_Reg_bits(LMS7param(DCCORRI_TXTSP), dccorri); + lms7->Modify_SPI_Reg_bits(LMS7param(DCCORRQ_TXTSP), dccorrq); + // lms7->Modify_SPI_Reg_bits(LMS7param(GCORRI_TXTSP), gcorri); + // lms7->Modify_SPI_Reg_bits(LMS7param(GCORRQ_TXTSP), gcorrq); + // lms7->Modify_SPI_Reg_bits(LMS7param(IQCORR_TXTSP), iqcorr); + + // lms7->Modify_SPI_Reg_bits(LMS7param(DC_BYP_TXTSP), 0); //DC_BYP + lms7->Modify_SPI_Reg_bits(0x0208, 1, 0, 0); //GC_BYP PH_BYP + +} +*/ + +int trx_lms_start(openair0_device *device){ + + + LMS_Init(0, 128*1024); + usbport = LMS_GetUSBPort(); + //connect data stream port + LMS_UpdateDeviceList(usbport); + const char *name = LMS_GetDeviceName(usbport, 0); + printf("Connecting to device: %s\n",name); + + + + if (LMS_DeviceOpen(usbport, 0)==0) + { + Si = new Si5351C(); + lms7 = new LMS7002M(usbport); + liblms7_status opStatus; + + printf("Configuring Si5351C\n"); + Si->Initialize(usbport); + Si->SetPLL(0, 25000000, 0); + Si->SetPLL(1, 25000000, 0); + Si->SetClock(0, 27000000, true, false); + Si->SetClock(1, 27000000, true, false); + for (int i = 2; i < 8; ++i) + Si->SetClock(i, 27000000, false, false); + Si5351C::Status status = Si->ConfigureClocks(); + if (status != Si5351C::SUCCESS) + { + printf("Failed to configure Si5351C"); + exit(-1); + } + status = Si->UploadConfiguration(); + if (status != Si5351C::SUCCESS) + printf("Failed to upload Si5351C configuration"); + + + + lms7->ResetChip(); + + opStatus = lms7->LoadConfig(device->openair0_cfg[0].configFilename); + + if (opStatus != LIBLMS7_SUCCESS) { + printf("Failed to load configuration file %s\n",device->openair0_cfg[0].configFilename); + exit(-1); + } + opStatus = lms7->UploadAll(); + + if (opStatus != LIBLMS7_SUCCESS) { + printf("Failed to upload configuration file\n"); + exit(-1); + } + + // Set TX filter + + printf("Tuning TX filter\n"); + opStatus = lms7->TuneTxFilter(LMS7002M::TxFilter::TX_HIGHBAND,28.0); + + if (opStatus != LIBLMS7_SUCCESS) { + printf("Warning: Could not tune TX filter\n"); + } + + printf("Tuning RX filter\n"); + opStatus = lms7->TuneRxFilter(LMS7002M::RxFilter::RX_LPF_LOWBAND,5.0); + + if (opStatus != LIBLMS7_SUCCESS) { + printf("Warning: Could not tune TX filter\n"); + } + + opStatus = lms7->SetInterfaceFrequency(lms7->GetFrequencyCGEN_MHz(), + lms7->Get_SPI_Reg_bits(HBI_OVR_TXTSP), + lms7->Get_SPI_Reg_bits(HBD_OVR_RXTSP)); + if (opStatus != LIBLMS7_SUCCESS) { + printf("SetInterfaceFrequency failed: %f,%d,%d\n", + lms7->GetFrequencyCGEN_MHz(), + lms7->Get_SPI_Reg_bits(HBI_OVR_TXTSP), + lms7->Get_SPI_Reg_bits(HBD_OVR_RXTSP)); + } + else { + printf("SetInterfaceFrequency as %f,%d,%d\n", + lms7->GetFrequencyCGEN_MHz(), + lms7->Get_SPI_Reg_bits(HBI_OVR_TXTSP), + lms7->Get_SPI_Reg_bits(HBD_OVR_RXTSP)); + } + lmsStream = new LMS_StreamBoard(usbport); + LMS_StreamBoard::Status opStreamStatus; + // this will configure that sampling rate at output of FPGA + opStreamStatus = lmsStream->ConfigurePLL(usbport,device->openair0_cfg[0].sample_rate,device->openair0_cfg[0].sample_rate,90); + if (opStatus != LIBLMS7_SUCCESS){ + printf("Sample rate programming failed\n"); + exit(-1); + } + + opStatus = lms7->SetFrequencySX(LMS7002M::Tx, device->openair0_cfg[0].tx_freq[0]/1e6,30.72); + + if (opStatus != LIBLMS7_SUCCESS) { + printf("Cannot set TX frequency %f MHz\n",device->openair0_cfg[0].tx_freq[0]/1e6); + exit(-1); + } + else { + printf("Set TX frequency %f MHz\n",device->openair0_cfg[0].tx_freq[0]/1e6); + } + opStatus = lms7->SetFrequencySX(LMS7002M::Rx, device->openair0_cfg[0].rx_freq[0]/1e6,30.72); + + if (opStatus != LIBLMS7_SUCCESS) { + printf("Cannot set RX frequency %f MHz\n",device->openair0_cfg[0].rx_freq[0]/1e6); + exit(-1); + } + else { + printf("Set RX frequency %f MHz\n",device->openair0_cfg[0].rx_freq[0]/1e6); + } + + // Run calibration procedure + // calibrate_rf(device); + //lms7->CalibrateTx(5.0); + LMS_RxStart(); + } + else + { + return(-1); + } + + //connect control port + + /* comport = LMS_GetCOMPort(); + LMS_UpdateDeviceList(comport); + name = LMS_GetDeviceName(comport, 0); + if (*name == 0) + comport = usbport; //attempt to use data port + else + { + printf("Connecting to device: %s\n",name); + if (LMS_DeviceOpen(comport, 0)!=0) + return (-1); + } + lms7 = new LMS7002M(comport); + if( access( "./config.ini", F_OK ) != -1 ) //load config file + lms7->LoadConfig("./config.ini"); + //calibration takes too long + //lms7->CalibrateRx(5.0); + //lms7->CalibrateTx(5.0); + */ + + return 0; +} + + +int trx_lms_stop(int card) { + /* + LMS_DeviceClose(usbport); + LMS_DeviceClose(comport); + delete lms7; + return LMS_Destroy(); + */ +} + +int trx_lms_set_freq(openair0_device* device, openair0_config_t *openair0_cfg,int exmimo_dump_config) { + //Control port must be connected + + lms7->SetFrequencySX(LMS7002M::Tx,openair0_cfg->tx_freq[0]/1e6,30.72); + lms7->SetFrequencySX(LMS7002M::Rx,openair0_cfg->rx_freq[0]/1e6,30.72); + printf ("[LMS] rx frequency:%f;\n",openair0_cfg->rx_freq[0]/1e6); + set_rx_gain_offset(openair0_cfg,0); + return(0); + +} + +// 31 = 19 dB => 105 dB total gain @ 2.6 GHz +rx_gain_calib_table_t calib_table_sodera[] = { + {3500000000.0,70.0}, + {2660000000.0,80.0}, + {2300000000.0,80.0}, + {1880000000.0,80.0}, + {816000000.0,80.0}, + {-1,0}}; + + + + + +int trx_lms_set_gains(openair0_device* device, openair0_config_t *openair0_cfg) { + + double gv = openair0_cfg[0].rx_gain[0] - openair0_cfg[0].rx_gain_offset[0]; + + if (gv > 31) { + printf("RX Gain 0 too high, reduce by %f dB\n",gv-31); + gv = 31; + } + if (gv < 0) { + printf("RX Gain 0 too low, increase by %f dB\n",-gv); + gv = 0; + } + printf("[LMS] Setting 7002M G_PGA_RBB to %d\n", (int16_t)gv); + lms7->Modify_SPI_Reg_bits(LMS7param(G_PGA_RBB),(int16_t)gv); + + return(0); +} + + +int trx_lms_get_stats(openair0_device* device) { + + return(0); + +} + +int trx_lms_reset_stats(openair0_device* device) { + + return(0); + +} + +int openair0_set_gains(openair0_device* device, + openair0_config_t *openair0_cfg) { + + return(0); +} + +int openair0_set_frequencies(openair0_device* device, openair0_config_t *openair0_cfg, int dummy) { + + return(0); +} + + + +void trx_lms_end(openair0_device *device) { + + +} + + +int openair0_dev_init_lms(openair0_device *device, openair0_config_t *openair0_cfg){ + + + printf("LMSSDR: Initializing openair0_device for %s ...\n", ((device->func_type == BBU_FUNC) ? "BBU": "RRH")); + + switch ((int)openair0_cfg[0].sample_rate) { + case 30720000: + // from usrp_time_offset + openair0_cfg[0].samples_per_packet = 2048; + openair0_cfg[0].tx_sample_advance = 15; + openair0_cfg[0].tx_bw = 30.72e6; + openair0_cfg[0].rx_bw = 30.72e6; + openair0_cfg[0].tx_scheduling_advance = 8*openair0_cfg[0].samples_per_packet; + break; + case 15360000: + openair0_cfg[0].samples_per_packet = 2048; + openair0_cfg[0].tx_sample_advance = 45; + openair0_cfg[0].tx_bw = 15.36e6; + openair0_cfg[0].rx_bw = 15.36e6; + openair0_cfg[0].tx_scheduling_advance = 5*openair0_cfg[0].samples_per_packet; + break; + case 7680000: + openair0_cfg[0].samples_per_packet = 1024; + openair0_cfg[0].tx_sample_advance = 70; + openair0_cfg[0].tx_bw = 7.68e6; + openair0_cfg[0].rx_bw = 7.68e6; + openair0_cfg[0].tx_scheduling_advance = 12*openair0_cfg[0].samples_per_packet; + break; + case 1920000: + openair0_cfg[0].samples_per_packet = 256; + openair0_cfg[0].tx_sample_advance = 50; + openair0_cfg[0].tx_bw = 1.25e6; + openair0_cfg[0].rx_bw = 1.25e6; + openair0_cfg[0].tx_scheduling_advance = 8*openair0_cfg[0].samples_per_packet; + break; + default: + printf("Error: unknown sampling rate %f\n",openair0_cfg[0].sample_rate); + exit(-1); + break; + } + + openair0_cfg[0].rx_gain_calib_table = calib_table_sodera; + set_rx_gain_offset(openair0_cfg,0); + + device->Mod_id = 1; + device->trx_start_func = trx_lms_start; + device->trx_write_func = trx_lms_write; + device->trx_read_func = trx_lms_read; + device->trx_get_stats_func = trx_lms_get_stats; + device->trx_reset_stats_func = trx_lms_reset_stats; + device->trx_end_func = trx_lms_end; + device->trx_stop_func = trx_lms_stop; + device->trx_set_freq_func = trx_lms_set_freq; + device->trx_set_gains_func = trx_lms_set_gains; + + device->openair0_cfg = openair0_cfg; + + return 0; +} From 92987e4c9b4a00fd0a0026a56511b3aa98c4a30b Mon Sep 17 00:00:00 2001 From: kaltenbe Date: Sun, 14 Feb 2016 20:31:38 +0100 Subject: [PATCH 227/263] small modifications in lms_lib.cpp added configuration file for lowband of SoDeRa --- openair1/PHY/TOOLS/lte_phy_scope.c | 4 +- targets/ARCH/LMSSDR/USERSPACE/LIB/lms_lib.cpp | 49 +- ...enb_sodera_highband_5MHz_rx19dB_txfull.ini | 1128 +++++++++++++++++ ...sodera_lowband_Wrx_5MHz_rx19dB_txfull.ini} | 100 +- .../CONF/enb.band7.tm1.50PRB.usrpb210.conf | 4 +- 5 files changed, 1211 insertions(+), 74 deletions(-) create mode 100644 targets/ARCH/LMSSDR/enb_sodera_highband_5MHz_rx19dB_txfull.ini rename targets/ARCH/LMSSDR/{SoDeRa_MIMO.ini => enb_sodera_lowband_Wrx_5MHz_rx19dB_txfull.ini} (95%) mode change 100755 => 100644 diff --git a/openair1/PHY/TOOLS/lte_phy_scope.c b/openair1/PHY/TOOLS/lte_phy_scope.c index e507024c86..843a77fe62 100644 --- a/openair1/PHY/TOOLS/lte_phy_scope.c +++ b/openair1/PHY/TOOLS/lte_phy_scope.c @@ -88,7 +88,7 @@ FD_lte_phy_scope_enb *create_lte_phy_scope_enb( void ) fl_set_object_boxtype( fdui->rxsig_t, FL_EMBOSSED_BOX ); fl_set_object_color( fdui->rxsig_t, FL_BLACK, FL_RED ); fl_set_object_lcolor( fdui->rxsig_t, FL_WHITE ); // Label color - fl_set_xyplot_ybounds(fdui->rxsig_t,30,70); + fl_set_xyplot_ybounds(fdui->rxsig_t,10,70); // Time-domain channel response fdui->chest_t = fl_add_xyplot( FL_NORMAL_XYPLOT, 410, 20, 370, 100, "Channel Impulse Response (samples, abs)" ); @@ -396,7 +396,7 @@ FD_lte_phy_scope_ue *create_lte_phy_scope_ue( void ) fl_set_object_boxtype( fdui->rxsig_t, FL_EMBOSSED_BOX ); fl_set_object_color( fdui->rxsig_t, FL_BLACK, FL_RED ); fl_set_object_lcolor( fdui->rxsig_t, FL_WHITE ); // Label color - fl_set_xyplot_ybounds(fdui->rxsig_t,30,70); + fl_set_xyplot_ybounds(fdui->rxsig_t,10,70); // Time-domain channel response fdui->chest_t = fl_add_xyplot( FL_NORMAL_XYPLOT, 410, 20, 370, 100, "Channel Impulse Response (samples, abs)" ); diff --git a/targets/ARCH/LMSSDR/USERSPACE/LIB/lms_lib.cpp b/targets/ARCH/LMSSDR/USERSPACE/LIB/lms_lib.cpp index 8c85863e80..2402027506 100644 --- a/targets/ARCH/LMSSDR/USERSPACE/LIB/lms_lib.cpp +++ b/targets/ARCH/LMSSDR/USERSPACE/LIB/lms_lib.cpp @@ -571,6 +571,24 @@ void calibrate_rf(openair0_device *device) { } */ +int trx_lms_set_gains(openair0_device* device, openair0_config_t *openair0_cfg) { + + double gv = openair0_cfg[0].rx_gain[0] - openair0_cfg[0].rx_gain_offset[0]; + + if (gv > 31) { + printf("RX Gain 0 too high, reduce by %f dB\n",gv-31); + gv = 31; + } + if (gv < 0) { + printf("RX Gain 0 too low, increase by %f dB\n",-gv); + gv = 0; + } + printf("[LMS] Setting 7002M G_PGA_RBB to %d\n", (int16_t)gv); + lms7->Modify_SPI_Reg_bits(LMS7param(G_PGA_RBB),(int16_t)gv); + + return(0); +} + int trx_lms_start(openair0_device *device){ @@ -637,7 +655,14 @@ int trx_lms_start(openair0_device *device){ opStatus = lms7->TuneRxFilter(LMS7002M::RxFilter::RX_LPF_LOWBAND,5.0); if (opStatus != LIBLMS7_SUCCESS) { - printf("Warning: Could not tune TX filter\n"); + printf("Warning: Could not tune RX filter\n"); + } + + printf("Tuning TIA filter\n"); + opStatus = lms7->TuneRxFilter(LMS7002M::RxFilter::RX_TIA,7.0); + + if (opStatus != LIBLMS7_SUCCESS) { + printf("Warning: Could not tune RX TIA filter\n"); } opStatus = lms7->SetInterfaceFrequency(lms7->GetFrequencyCGEN_MHz(), @@ -683,6 +708,7 @@ int trx_lms_start(openair0_device *device){ printf("Set RX frequency %f MHz\n",device->openair0_cfg[0].rx_freq[0]/1e6); } + trx_lms_set_gains(device, device->openair0_cfg); // Run calibration procedure // calibrate_rf(device); //lms7->CalibrateTx(5.0); @@ -743,31 +769,14 @@ rx_gain_calib_table_t calib_table_sodera[] = { {3500000000.0,70.0}, {2660000000.0,80.0}, {2300000000.0,80.0}, - {1880000000.0,80.0}, - {816000000.0,80.0}, + {1880000000.0,74.0}, // on W PAD + {816000000.0,76.0}, // on W PAD {-1,0}}; -int trx_lms_set_gains(openair0_device* device, openair0_config_t *openair0_cfg) { - - double gv = openair0_cfg[0].rx_gain[0] - openair0_cfg[0].rx_gain_offset[0]; - - if (gv > 31) { - printf("RX Gain 0 too high, reduce by %f dB\n",gv-31); - gv = 31; - } - if (gv < 0) { - printf("RX Gain 0 too low, increase by %f dB\n",-gv); - gv = 0; - } - printf("[LMS] Setting 7002M G_PGA_RBB to %d\n", (int16_t)gv); - lms7->Modify_SPI_Reg_bits(LMS7param(G_PGA_RBB),(int16_t)gv); - - return(0); -} int trx_lms_get_stats(openair0_device* device) { diff --git a/targets/ARCH/LMSSDR/enb_sodera_highband_5MHz_rx19dB_txfull.ini b/targets/ARCH/LMSSDR/enb_sodera_highband_5MHz_rx19dB_txfull.ini new file mode 100644 index 0000000000..a3c1aa2e6f --- /dev/null +++ b/targets/ARCH/LMSSDR/enb_sodera_highband_5MHz_rx19dB_txfull.ini @@ -0,0 +1,1128 @@ +[reference_clocks] +sxr_ref_clk_mhz=30.72 +sxt_ref_clk_mhz=30.72 +[lms7002_registers_b] +0x03A0=0x0000 +0x054E=0x0000 +0x02D0=0x0000 +0x0386=0x0000 +0x054F=0x0000 +0x0389=0x0000 +0x040F=0x0000 +0x04E3=0x0000 +0x0385=0x0000 +0x0315=0x0000 +0x0384=0x0000 +0x0382=0x0000 +0x0288=0x0000 +0x0381=0x0000 +0x0366=0x0000 +0x0365=0x0000 +0x0364=0x0000 +0x0325=0x0000 +0x035E=0x0000 +0x035D=0x0000 +0x0442=0x0000 +0x0452=0x0000 +0x0299=0x0000 +0x0359=0x0000 +0x029D=0x0000 +0x04A3=0x0000 +0x040E=0x0000 +0x0316=0x0000 +0x030D=0x0000 +0x0356=0x0000 +0x0348=0x0000 +0x0498=0x0000 +0x0490=0x0000 +0x02CD=0x0000 +0x050D=0x0000 +0x0353=0x0000 +0x0351=0x0000 +0x048F=0x0000 +0x0445=0x0000 +0x0350=0x0000 +0x03A6=0x0000 +0x0293=0x0000 +0x034E=0x0000 +0x035C=0x0000 +0x034D=0x0000 +0x034B=0x0000 +0x011A=0x2E02 +0x0455=0x0000 +0x034A=0x0000 +0x035B=0x0000 +0x0505=0x0000 +0x0345=0x0000 +0x035F=0x0000 +0x0597=0x0000 +0x0586=0x0000 +0x0484=0x0000 +0x02C8=0x0000 +0x035A=0x0000 +0x0561=0x0000 +0x0344=0x0000 +0x0343=0x0000 +0x0342=0x0000 +0x0380=0x0000 +0x0327=0x0000 +0x025E=0x0000 +0x04DA=0x0000 +0x04C2=0x0000 +0x028C=0x0000 +0x0352=0x0000 +0x059C=0x0000 +0x04DD=0x0000 +0x028A=0x0000 +0x0289=0x0000 +0x031A=0x0000 +0x0363=0x0000 +0x0396=0x0000 +0x0284=0x0000 +0x010C=0x88FD +0x044C=0x0000 +0x0355=0x0000 +0x025C=0x0000 +0x0515=0x0000 +0x0361=0x0000 +0x0205=0x0000 +0x025B=0x0000 +0x04C5=0x0000 +0x04E2=0x0000 +0x025A=0x0000 +0x0256=0x0000 +0x0240=0x0020 +0x0367=0x0000 +0x05A3=0x0000 +0x0502=0x0000 +0x0258=0x0000 +0x0255=0x0000 +0x040C=0x0000 +0x028B=0x0000 +0x0253=0x0000 +0x024E=0x0000 +0x0346=0x0000 +0x0280=0x0000 +0x0285=0x0000 +0x024A=0x0000 +0x0261=0x0000 +0x0249=0x0000 +0x04CD=0x0000 +0x040A=0x0000 +0x0556=0x0000 +0x0243=0x0000 +0x051D=0x0000 +0x0494=0x0000 +0x024C=0x0000 +0x02DC=0x0000 +0x038F=0x0000 +0x0241=0x0000 +0x0488=0x0000 +0x0251=0x0000 +0x020B=0x4000 +0x0108=0x9442 +0x04A0=0x0000 +0x0116=0x8180 +0x02CC=0x0000 +0x039A=0x0000 +0x0112=0xC0E6 +0x0307=0x0000 +0x038C=0x0000 +0x0282=0x0000 +0x0321=0x0000 +0x0507=0x0000 +0x0483=0x0000 +0x0201=0x07FF +0x02E1=0x0000 +0x0517=0x0000 +0x0481=0x0000 +0x02D5=0x0000 +0x0259=0x0000 +0x0527=0x0000 +0x02DD=0x0000 +0x0209=0x0000 +0x0297=0x0000 +0x0400=0x0081 +0x0104=0x0088 +0x0103=0x0A12 +0x0347=0x0000 +0x02D8=0x0000 +0x0457=0x0000 +0x0306=0x0000 +0x02D1=0x0000 +0x04C8=0x0000 +0x0546=0x0000 +0x0440=0x0020 +0x045E=0x0000 +0x031D=0x0000 +0x039C=0x0000 +0x02D2=0x0000 +0x010E=0x2040 +0x02A0=0x0000 +0x0544=0x0000 +0x029C=0x0000 +0x055A=0x0000 +0x0295=0x0000 +0x02CF=0x0000 +0x04D1=0x0000 +0x0291=0x0000 +0x02DF=0x0000 +0x0290=0x0000 +0x020A=0x0080 +0x0102=0x3180 +0x0120=0xB9FF +0x0388=0x0000 +0x0318=0x0000 +0x02A7=0x0000 +0x0200=0x0081 +0x0594=0x0000 +0x02C5=0x0000 +0x028D=0x0000 +0x02A1=0x0000 +0x0362=0x0000 +0x038A=0x0000 +0x0395=0x0000 +0x058D=0x0000 +0x02D7=0x0000 +0x0305=0x0000 +0x0393=0x0000 +0x0398=0x0000 +0x0408=0x0000 +0x039B=0x0000 +0x049E=0x0000 +0x02DB=0x0000 +0x0357=0x0000 +0x02C2=0x0000 +0x0514=0x0000 +0x051C=0x0000 +0x03A2=0x0000 +0x03A4=0x0000 +0x03A3=0x0000 +0x0493=0x0000 +0x0454=0x0000 +0x0448=0x0000 +0x0397=0x0000 +0x02E3=0x0000 +0x049C=0x0000 +0x040D=0x0000 +0x0281=0x0000 +0x048C=0x0000 +0x049A=0x0000 +0x0119=0x18CB +0x010F=0x3042 +0x02A6=0x0000 +0x0257=0x0000 +0x04D6=0x0000 +0x04A6=0x0000 +0x0324=0x0000 +0x038E=0x0000 +0x02E7=0x0000 +0x034F=0x0000 +0x04E0=0x0000 +0x0123=0x267B +0x0497=0x0000 +0x0459=0x0000 +0x0394=0x0000 +0x04A5=0x0000 +0x04D9=0x0000 +0x0304=0x0000 +0x04D5=0x0000 +0x0508=0x0000 +0x0443=0x0000 +0x0301=0x0000 +0x0548=0x0000 +0x04D2=0x0000 +0x0592=0x0000 +0x0591=0x0000 +0x04C7=0x0000 +0x049D=0x0000 +0x029A=0x0000 +0x051F=0x0000 +0x0309=0x0000 +0x0585=0x0000 +0x03A5=0x0000 +0x02D3=0x0000 +0x0451=0x0000 +0x0390=0x0000 +0x0562=0x0000 +0x02C4=0x0000 +0x029E=0x0000 +0x031E=0x0000 +0x04C0=0x0000 +0x04DC=0x0000 +0x04DE=0x0000 +0x058B=0x0000 +0x04DB=0x0000 +0x04D0=0x0000 +0x0492=0x0000 +0x04A1=0x0000 +0x054B=0x0000 +0x02C7=0x0000 +0x05A0=0x0000 +0x044B=0x0000 +0x0100=0x3409 +0x04CA=0x0000 +0x0446=0x0000 +0x02E4=0x0000 +0x04E4=0x0000 +0x04C3=0x0000 +0x0496=0x0000 +0x04CF=0x0000 +0x025F=0x0000 +0x04D4=0x0000 +0x0504=0x0000 +0x04CE=0x0000 +0x02DE=0x0000 +0x0399=0x0000 +0x050C=0x0000 +0x02A5=0x0000 +0x04CC=0x0000 +0x03A1=0x0000 +0x04E1=0x0000 +0x02A2=0x0000 +0x040B=0x7FFF +0x0283=0x0000 +0x048E=0x0000 +0x0580=0x0000 +0x0409=0x0000 +0x039F=0x0000 +0x0248=0x0000 +0x048B=0x0000 +0x0358=0x0000 +0x0589=0x0000 +0x038D=0x0000 +0x0487=0x0000 +0x0510=0x0000 +0x0302=0x0000 +0x0486=0x0000 +0x045F=0x0000 +0x0480=0x0000 +0x0567=0x0000 +0x02DA=0x0000 +0x045A=0x0000 +0x0254=0x0000 +0x0405=0x0000 +0x0387=0x0000 +0x0458=0x0000 +0x0314=0x0000 +0x0360=0x0000 +0x0559=0x0000 +0x0456=0x0000 +0x0453=0x0000 +0x02E2=0x0000 +0x044D=0x0000 +0x0441=0x0000 +0x02C3=0x0000 +0x04C1=0x0000 +0x04D3=0x0000 +0x0444=0x0000 +0x0207=0x0000 +0x04C6=0x0000 +0x0296=0x0000 +0x0555=0x0000 +0x0349=0x0000 +0x0109=0x61C1 +0x04A2=0x0000 +0x0447=0x0000 +0x0460=0x0000 +0x048D=0x0000 +0x059A=0x0000 +0x0407=0x0000 +0x02C0=0x0000 +0x0499=0x0000 +0x0543=0x0000 +0x04C9=0x0000 +0x02CA=0x0000 +0x0404=0x0000 +0x0560=0x0000 +0x02C1=0x0000 +0x04D8=0x0000 +0x0403=0x0000 +0x0491=0x0000 +0x029B=0x0000 +0x04C4=0x0000 +0x010D=0x009E +0x0402=0x07FF +0x055E=0x0000 +0x03A7=0x0000 +0x0520=0x0000 +0x0392=0x0000 +0x030B=0x0000 +0x0588=0x0000 +0x0308=0x0000 +0x048A=0x0000 +0x044A=0x0000 +0x04A4=0x0000 +0x0300=0x0000 +0x0587=0x0000 +0x044E=0x0000 +0x055B=0x0000 +0x02E5=0x0000 +0x0114=0x008D +0x0323=0x0000 +0x0320=0x0000 +0x0503=0x0000 +0x0513=0x0000 +0x0319=0x0000 +0x0260=0x0000 +0x0549=0x0000 +0x0552=0x0000 +0x0509=0x0000 +0x0521=0x0000 +0x0286=0x0000 +0x04D7=0x0000 +0x059E=0x0000 +0x058F=0x0000 +0x0557=0x0000 +0x0322=0x0000 +0x059B=0x0000 +0x049F=0x0000 +0x0522=0x0000 +0x0545=0x0000 +0x0551=0x0000 +0x0312=0x0000 +0x055D=0x0000 +0x0298=0x0000 +0x055F=0x0000 +0x011D=0xAAAA +0x039E=0x0000 +0x0547=0x0000 +0x0598=0x0000 +0x0449=0x0000 +0x0564=0x0000 +0x0242=0x0000 +0x0525=0x0000 +0x0523=0x0000 +0x0565=0x0000 +0x0124=0x0000 +0x0563=0x0000 +0x024D=0x0000 +0x05A5=0x0000 +0x0566=0x0000 +0x030A=0x0000 +0x029F=0x0000 +0x054C=0x0000 +0x0582=0x0000 +0x0599=0x0000 +0x0511=0x0000 +0x0506=0x0000 +0x0595=0x0000 +0x0584=0x0000 +0x058C=0x0000 +0x05A6=0x0000 +0x051E=0x0000 +0x050F=0x0000 +0x0590=0x0000 +0x0596=0x0000 +0x05A7=0x0000 +0x058A=0x0000 +0x059D=0x0000 +0x0485=0x0000 +0x0581=0x0000 +0x045D=0x0000 +0x0245=0x0000 +0x0310=0x0000 +0x058E=0x0000 +0x05A2=0x0000 +0x054D=0x0000 +0x020C=0x7FFF +0x031F=0x0000 +0x0292=0x0000 +0x059F=0x0000 +0x0583=0x0000 +0x0317=0x0000 +0x0244=0x0000 +0x0554=0x0000 +0x0593=0x0000 +0x05A4=0x0000 +0x02A3=0x0000 +0x0553=0x0000 +0x0542=0x0000 +0x0519=0x0000 +0x024F=0x0000 +0x0524=0x0000 +0x0518=0x0000 +0x0354=0x0000 +0x0526=0x0000 +0x031B=0x0000 +0x050E=0x0000 +0x0516=0x0000 +0x02CB=0x0000 +0x0250=0x0000 +0x031C=0x0000 +0x028F=0x0000 +0x051A=0x0000 +0x055C=0x0000 +0x050A=0x0000 +0x050B=0x0000 +0x04E7=0x0000 +0x04E6=0x0000 +0x04E5=0x0000 +0x0512=0x0000 +0x0206=0x0000 +0x0550=0x0000 +0x030E=0x0000 +0x0203=0x0000 +0x0482=0x0000 +0x0541=0x0000 +0x0122=0x033F +0x0110=0x0BF4 +0x0204=0x0000 +0x0252=0x0000 +0x011E=0x0AA7 +0x049B=0x0000 +0x0294=0x0000 +0x011C=0xA941 +0x02D6=0x0000 +0x0311=0x0000 +0x0117=0x280C +0x02A4=0x0000 +0x0540=0x0000 +0x02E0=0x0000 +0x0118=0x018C +0x0489=0x0000 +0x04A7=0x0000 +0x0101=0x7800 +0x0558=0x0000 +0x02C6=0x0000 +0x05A1=0x0000 +0x02C9=0x0000 +0x039D=0x0000 +0x0500=0x0000 +0x0450=0x0000 +0x011F=0x3600 +0x030C=0x0000 +0x04DF=0x0000 +0x0106=0x3182 +0x028E=0x0000 +0x0326=0x0000 +0x0113=0x03C3 +0x04CB=0x0000 +0x0391=0x0000 +0x0105=0x0007 +0x02D9=0x0000 +0x02CE=0x0000 +0x044F=0x0000 +0x038B=0x0000 +0x02D4=0x0000 +0x0107=0x318C +0x0495=0x0000 +0x0246=0x0000 +0x0303=0x0000 +0x02E6=0x0000 +0x045B=0x0000 +0x0340=0x0000 +0x0208=0x0070 +0x0111=0x0083 +0x0247=0x0000 +0x024B=0x0000 +0x045C=0x0000 +0x0383=0x0000 +0x0202=0x07FF +0x054A=0x0000 +0x0401=0x07FF +0x0341=0x0000 +0x0287=0x0000 +0x034C=0x0000 +0x0501=0x0000 +0x030F=0x0000 +0x025D=0x0000 +0x0406=0x0000 +0x0313=0x0000 +0x010A=0x104C +0x0461=0x0000 +0x051B=0x0000 +0x0121=0x31FA +0x0115=0x0009 +[lms7002_registers_a] +0x0107=0x318C +0x02D4=0x0000 +0x0082=0x8001 +0x0209=0x0000 +0x02CA=0x0000 +0x04C9=0x0000 +0x0120=0xB9FF +0x0388=0x0000 +0x029D=0x0000 +0x04A3=0x0000 +0x0208=0x0170 +0x0340=0x0000 +0x0094=0x0000 +0x0244=0x0000 +0x0317=0x0000 +0x00A9=0x8000 +0x0115=0x0009 +0x039A=0x0000 +0x0112=0x3171 +0x048C=0x0000 +0x0023=0x5550 +0x0587=0x1D10 +0x04C0=0x0000 +0x031E=0x0000 +0x0205=0x0000 +0x0361=0x0000 +0x051F=0xAB08 +0x029A=0x0000 +0x0396=0x0000 +0x0284=0x0000 +0x02CE=0x0000 +0x02D9=0x0000 +0x038B=0x0000 +0x044F=0x0000 +0x0367=0x0000 +0x0240=0x0028 +0x05A3=0x0000 +0x0105=0x0007 +0x009B=0x6565 +0x0400=0x0101 +0x02DB=0x0000 +0x0357=0x0000 +0x0104=0x0088 +0x0103=0x0612 +0x0457=0x0000 +0x0347=0x0000 +0x02D8=0x0000 +0x010C=0x8865 +0x0086=0x4101 +0x0202=0x0794 +0x0383=0x0000 +0x020B=0x4000 +0x0108=0xFC26 +0x0098=0x0000 +0x0117=0x100C +0x0027=0x05E4 +0x00A7=0x6565 +0x024A=0x0000 +0x0029=0x0101 +0x00AD=0x03FF +0x0540=0x5009 +0x02A4=0x0000 +0x02DE=0x0000 +0x002E=0x0000 +0x0261=0x0000 +0x00AB=0x0040 +0x0564=0x0000 +0x00A8=0x0000 +0x0517=0xC89D +0x0481=0x0000 +0x02C1=0x0000 +0x0301=0x0000 +0x00A5=0x6565 +0x0515=0x2E45 +0x025C=0x0000 +0x009F=0x658C +0x0519=0x4049 +0x054B=0xF7A3 +0x02C7=0x0000 +0x038C=0x0000 +0x0307=0x0000 +0x0282=0x0000 +0x0289=0x0000 +0x011C=0xA941 +0x0562=0xF524 +0x0025=0x0101 +0x02CC=0x0000 +0x0116=0x8180 +0x0597=0xFDFB +0x035F=0x0000 +0x002F=0x3840 +0x0589=0xEA5F +0x00A2=0x6565 +0x0099=0x6565 +0x0310=0x0000 +0x040C=0x40F8 +0x028B=0x0000 +0x0253=0x0000 +0x00AC=0x2000 +0x002D=0xFFFF +0x00A6=0x0001 +0x054D=0xF7A3 +0x002C=0x0000 +0x0249=0x0000 +0x04CD=0x0000 +0x0401=0x07FF +0x00A4=0x6565 +0x054A=0x8184 +0x038F=0x0000 +0x008C=0x267B +0x0241=0x0000 +0x0356=0x0000 +0x00A1=0x6565 +0x0260=0x0000 +0x0453=0x0000 +0x008A=0x0491 +0x048F=0x0000 +0x0445=0x0000 +0x0350=0x0000 +0x00AA=0x0000 +0x034C=0x0000 +0x0501=0xFDFB +0x0490=0x0000 +0x02CD=0x0000 +0x050D=0x0F45 +0x0353=0x0000 +0x0024=0x50D8 +0x04E5=0x0000 +0x0512=0x196B +0x0247=0x0000 +0x045C=0x0000 +0x024B=0x0000 +0x0395=0x0000 +0x011F=0x3600 +0x039D=0x0000 +0x0500=0xF61D +0x02C9=0x0000 +0x05A1=0x0000 +0x02A6=0x0000 +0x0119=0x18DF +0x010F=0x3042 +0x04CB=0x0000 +0x0391=0x0000 +0x0113=0x03C3 +0x0326=0x0000 +0x028E=0x0000 +0x0106=0x3182 +0x0524=0x3347 +0x009D=0x6565 +0x0294=0x0000 +0x0026=0x0101 +0x0110=0x0BFF +0x0122=0x033F +0x0381=0x0000 +0x009C=0x658C +0x05A0=0x0000 +0x0482=0x0000 +0x030E=0x0000 +0x0203=0x2F99 +0x0095=0x0000 +0x0111=0x0099 +0x0256=0x0000 +0x0089=0x00A0 +0x0085=0x0001 +0x0088=0x0530 +0x0459=0x0000 +0x0394=0x0000 +0x010E=0x0285 +0x02A0=0x0000 +0x002B=0x4038 +0x039C=0x0000 +0x02D2=0x0000 +0x0581=0xC89D +0x045D=0x0000 +0x0245=0x0000 +0x002A=0x0086 +0x0118=0x018C +0x02E0=0x0000 +0x0489=0x0000 +0x04A7=0x0000 +0x039E=0x0000 +0x011D=0xAAAA +0x02E1=0x0000 +0x0259=0x0000 +0x02D5=0x0000 +0x051D=0x4F91 +0x0243=0x0000 +0x0556=0xA2B5 +0x040A=0x1000 +0x05A2=0x0000 +0x020C=0x8000 +0x020A=0x0080 +0x0102=0x3180 +0x034F=0x0000 +0x0303=0x0000 +0x0306=0x0000 +0x0255=0x0000 +0x0300=0x0000 +0x044E=0x0000 +0x0309=0x0000 +0x0585=0xDAA2 +0x0527=0xACB9 +0x044A=0x0000 +0x04A4=0x0000 +0x048A=0x0000 +0x0392=0x0000 +0x030B=0x0000 +0x05A7=0x0000 +0x0252=0x0000 +0x0204=0xC016 +0x0308=0x0000 +0x0588=0xE6C7 +0x0321=0x0000 +0x0507=0xFCFE +0x0312=0x0000 +0x050B=0xF5EF +0x0360=0x0000 +0x0021=0x0E9F +0x04C2=0x0000 +0x030D=0x0000 +0x040E=0x0003 +0x0316=0x0000 +0x031F=0x0000 +0x030C=0x0000 +0x04DF=0x0000 +0x0318=0x0000 +0x0250=0x0000 +0x02CB=0x0000 +0x045E=0x0000 +0x0440=0x0024 +0x031D=0x0000 +0x058D=0xF5EF +0x02D7=0x0000 +0x0380=0x0000 +0x0342=0x0000 +0x0343=0x0000 +0x0566=0x0906 +0x0345=0x0000 +0x049C=0x0000 +0x02E3=0x0000 +0x0397=0x0000 +0x035B=0x0000 +0x0505=0x00D8 +0x028D=0x0000 +0x02A1=0x0000 +0x028F=0x0000 +0x031C=0x0000 +0x031A=0x0000 +0x0363=0x0000 +0x0596=0x0A94 +0x0354=0x0000 +0x0518=0xEFF2 +0x035C=0x0000 +0x034D=0x0000 +0x0344=0x0000 +0x0561=0xAB08 +0x0096=0x0000 +0x010D=0x00DE +0x04C4=0x0000 +0x0351=0x0000 +0x0311=0x0000 +0x02D6=0x0000 +0x02D1=0x0000 +0x0546=0x8D44 +0x04C8=0x0000 +0x048B=0x0000 +0x0358=0x0000 +0x0522=0xDB10 +0x049F=0x0000 +0x034A=0x0000 +0x0455=0x0000 +0x0359=0x0000 +0x03A4=0x0000 +0x03A3=0x0000 +0x0341=0x0000 +0x0287=0x0000 +0x04DA=0x0000 +0x025E=0x0000 +0x0580=0xEFF2 +0x0409=0x0000 +0x059A=0x0000 +0x048D=0x0000 +0x0514=0xE7E2 +0x039B=0x0000 +0x0101=0x7800 +0x0558=0x5009 +0x02C6=0x0000 +0x051B=0xB77F +0x0313=0x0000 +0x010A=0x104C +0x0461=0x0000 +0x0406=0x0000 +0x030F=0x0000 +0x025D=0x0000 +0x034B=0x0000 +0x011A=0x2E14 +0x029F=0x0000 +0x030A=0x0000 +0x034E=0x0000 +0x0293=0x0000 +0x03A6=0x0000 +0x0560=0x174B +0x0404=0x0000 +0x00A0=0x6565 +0x0547=0xD7B7 +0x0454=0x0000 +0x0448=0x0000 +0x0327=0x0000 +0x0305=0x0000 +0x0393=0x0000 +0x0510=0xE6C7 +0x0302=0x0000 +0x0486=0x0000 +0x045F=0x0000 +0x0365=0x0000 +0x048E=0x0000 +0x0022=0x07FF +0x0283=0x0000 +0x044B=0x0000 +0x045A=0x0000 +0x02DA=0x0000 +0x04E4=0x0000 +0x02E4=0x0000 +0x03A5=0x0000 +0x040B=0x000F +0x0366=0x0000 +0x0443=0x0000 +0x0508=0xEF99 +0x00A3=0x6565 +0x02E2=0x0000 +0x044D=0x0000 +0x0314=0x0000 +0x0458=0x0000 +0x0493=0x0000 +0x0346=0x0000 +0x024E=0x0000 +0x055E=0xDB10 +0x0402=0x07D9 +0x0384=0x0000 +0x02E6=0x0000 +0x045B=0x0000 +0x0480=0x0000 +0x0567=0x4049 +0x04CA=0x0000 +0x0446=0x0000 +0x0447=0x0000 +0x0460=0x0000 +0x0559=0xACB9 +0x0456=0x0000 +0x0441=0x0000 +0x0444=0x0000 +0x0390=0x0000 +0x0451=0x0000 +0x049E=0x0000 +0x0324=0x0000 +0x02E7=0x0000 +0x038E=0x0000 +0x0403=0x0013 +0x04D8=0x0000 +0x029B=0x0000 +0x0491=0x0000 +0x03A1=0x0000 +0x04E1=0x0000 +0x02A2=0x0000 +0x051C=0x0000 +0x03A2=0x0000 +0x0407=0x0000 +0x0258=0x0000 +0x0502=0x0A94 +0x038A=0x0000 +0x0362=0x0000 +0x028C=0x0000 +0x0352=0x0000 +0x0385=0x0000 +0x0315=0x0000 +0x040D=0x0000 +0x039F=0x0000 +0x0248=0x0000 +0x0405=0x0000 +0x0254=0x0000 +0x0398=0x0000 +0x0408=0x0000 +0x0487=0x0000 +0x038D=0x0000 +0x035E=0x0000 +0x03A7=0x0000 +0x0520=0x174B +0x0449=0x0000 +0x02C8=0x0000 +0x035A=0x0000 +0x0387=0x0000 +0x0386=0x0000 +0x0452=0x0000 +0x0299=0x0000 +0x0084=0x0400 +0x0498=0x0000 +0x0348=0x0000 +0x02D0=0x0000 +0x054E=0x8184 +0x03A0=0x0000 +0x009A=0x658C +0x055D=0xA6B5 +0x0298=0x0000 +0x0364=0x0000 +0x0081=0x0000 +0x0325=0x0000 +0x040F=0x43E4 +0x04E3=0x0000 +0x050E=0x17DC +0x0516=0x150F +0x0389=0x0000 +0x054F=0x18C9 +0x0304=0x0000 +0x04D5=0x0000 +0x059B=0x0000 +0x0322=0x0000 +0x0442=0x0000 +0x035D=0x0000 +0x0492=0x0000 +0x04A1=0x0000 +0x0382=0x0000 +0x0288=0x0000 +0x0296=0x0000 +0x0555=0xBD96 +0x0349=0x0000 +0x0484=0x0000 +0x0586=0x196B +0x0281=0x0000 +0x0200=0x0301 +0x0594=0xF40D +0x02C5=0x0000 +0x0319=0x0000 +0x0121=0x3760 +0x025B=0x0000 +0x0290=0x0000 +0x02DF=0x0000 +0x0291=0x0000 +0x029C=0x0000 +0x008B=0x278A +0x02A3=0x0000 +0x05A4=0x0000 +0x02A7=0x0000 +0x0483=0x0000 +0x0201=0x07FF +0x02C2=0x0000 +0x02C4=0x0000 +0x0207=0x0000 +0x04C6=0x0000 +0x0093=0x0000 +0x02D3=0x0000 +0x0494=0x0000 +0x04CF=0x0000 +0x025F=0x0000 +0x0251=0x0000 +0x0488=0x0000 +0x0496=0x0000 +0x04C3=0x0000 +0x0100=0x3409 +0x04CC=0x0000 +0x02A5=0x0000 +0x0257=0x0000 +0x04D6=0x0000 +0x04A6=0x0000 +0x049A=0x0000 +0x049B=0x0000 +0x0097=0x0000 +0x011E=0x0A2A +0x0285=0x0000 +0x0280=0x0000 +0x0020=0xFFFD +0x02DD=0x0000 +0x0297=0x0000 +0x044C=0x0000 +0x0355=0x0000 +0x04A0=0x0000 +0x02CF=0x0000 +0x04D1=0x0000 +0x0526=0xBE2A +0x0092=0x0001 +0x031B=0x0000 +0x0541=0x4C24 +0x0543=0xBD96 +0x02C0=0x0000 +0x0499=0x0000 +0x0513=0xDAA2 +0x0549=0x18C9 +0x0552=0x8D44 +0x0521=0x5852 +0x0509=0x0605 +0x0286=0x0000 +0x024F=0x0000 +0x04E0=0x0000 +0x0545=0x364E +0x0551=0xD7B7 +0x055F=0x5852 +0x009E=0x658C +0x0598=0xF61D +0x0123=0x067B +0x0497=0x0000 +0x04A5=0x0000 +0x0565=0xB77F +0x0124=0x0000 +0x0592=0x0DF1 +0x0591=0xFCFE +0x0548=0x79FA +0x04D2=0x0000 +0x0599=0x0000 +0x0511=0x1D10 +0x0506=0x0DF1 +0x0595=0x00BC +0x0584=0xE7E2 +0x0242=0x0000 +0x025A=0x0000 +0x04E2=0x0000 +0x04C5=0x0000 +0x058C=0xEA50 +0x0450=0x0000 +0x058A=0x17DC +0x059D=0x0000 +0x0485=0x0000 +0x058E=0x1316 +0x0550=0x79FA +0x0554=0x6901 +0x0593=0x00D8 +0x0553=0x364E +0x0542=0xA2B5 +0x0563=0x4F91 +0x024D=0x0000 +0x055A=0xBE2A +0x0295=0x0000 +0x028A=0x0000 +0x059C=0x0000 +0x04DD=0x0000 +0x054C=0x7FFF +0x0582=0x150F +0x0109=0x8CC1 +0x04A2=0x0000 +0x0292=0x0000 +0x0583=0x2E45 +0x059F=0x0000 +0x0525=0x57AC +0x0523=0xA6B5 +0x0206=0x0000 +0x051A=0x0906 +0x055C=0x3347 +0x05A6=0x0000 +0x050F=0xEA5F +0x051E=0xF524 +0x050A=0x1316 +0x04C7=0x0000 +0x049D=0x0000 +0x050C=0xEA50 +0x0087=0x0000 +0x0399=0x0000 +0x0495=0x0000 +0x0246=0x0000 +0x0503=0x00BC +0x0320=0x0000 +0x0323=0x0000 +0x055B=0x57AC +0x0114=0x0110 +0x02E5=0x0000 +0x04E7=0x0000 +0x04D0=0x0000 +0x04E6=0x0000 +0x00AE=0x0000 +0x0544=0x6901 +0x04DE=0x0000 +0x058B=0x0F45 +0x0028=0x0101 +0x029E=0x0000 +0x04DC=0x0000 +0x04D9=0x0000 +0x058F=0x0605 +0x0557=0x4C24 +0x04DB=0x0000 +0x04D7=0x0000 +0x059E=0x0000 +0x024C=0x0000 +0x02DC=0x0000 +0x04D4=0x0000 +0x0504=0xF40D +0x02C3=0x0000 +0x04C1=0x0000 +0x04D3=0x0000 +0x0590=0xEF99 +0x04CE=0x0000 +0x05A5=0x0000 +[file_info] +version=1 +type=lms7002m_minimal_config diff --git a/targets/ARCH/LMSSDR/SoDeRa_MIMO.ini b/targets/ARCH/LMSSDR/enb_sodera_lowband_Wrx_5MHz_rx19dB_txfull.ini old mode 100755 new mode 100644 similarity index 95% rename from targets/ARCH/LMSSDR/SoDeRa_MIMO.ini rename to targets/ARCH/LMSSDR/enb_sodera_lowband_Wrx_5MHz_rx19dB_txfull.ini index a3feaa269b..0243742f32 --- a/targets/ARCH/LMSSDR/SoDeRa_MIMO.ini +++ b/targets/ARCH/LMSSDR/enb_sodera_lowband_Wrx_5MHz_rx19dB_txfull.ini @@ -28,8 +28,8 @@ version=1 0x0454=0x0000 0x0446=0x0000 0x04CA=0x0000 -0x0444=0x02B1 -0x0443=0xCCCD +0x0444=0x0000 +0x0443=0x0000 0x0508=0xEF99 0x0441=0x0000 0x040D=0x0000 @@ -42,7 +42,7 @@ version=1 0x0404=0x0000 0x00A0=0x6565 0x0560=0x174B -0x0403=0x0000 +0x0403=0x009C 0x0402=0x07FF 0x055E=0xDB10 0x03A7=0x0000 @@ -92,7 +92,7 @@ version=1 0x038A=0x0000 0x035E=0x0000 0x035D=0x0000 -0x0442=0x0CCC +0x0442=0x0000 0x0449=0x0000 0x035A=0x0000 0x02C8=0x0000 @@ -109,7 +109,7 @@ version=1 0x035C=0x0000 0x034D=0x0000 0x034B=0x0000 -0x011A=0x2E02 +0x011A=0x2E03 0x0455=0x0000 0x034A=0x0000 0x0348=0x0000 @@ -130,7 +130,7 @@ version=1 0x059B=0x0000 0x0321=0x0000 0x045E=0x0000 -0x0440=0x0020 +0x0440=0x0024 0x031D=0x0000 0x0363=0x0000 0x031A=0x0000 @@ -148,7 +148,7 @@ version=1 0x0360=0x0000 0x0313=0x0000 0x0461=0x0000 -0x010A=0x104C +0x010A=0x184C 0x051B=0xB77F 0x0312=0x0000 0x0346=0x0000 @@ -188,27 +188,27 @@ version=1 0x0102=0x3180 0x020C=0x8000 0x05A2=0x0000 -0x040A=0x0003 +0x040A=0x1000 0x0556=0xA2B5 0x0243=0x0000 0x051D=0x4F91 0x0259=0x0000 0x02D5=0x0000 0x02E1=0x0000 -0x011D=0xB555 +0x011D=0xFEEE 0x039E=0x0000 0x0252=0x0000 -0x0204=0x0000 +0x0204=0xFFAD 0x0255=0x0000 0x0281=0x0000 -0x0200=0x0081 +0x0200=0x0301 0x0594=0xF40D 0x02C5=0x0000 0x0406=0x0000 0x030F=0x0000 0x025D=0x0000 0x0319=0x0000 -0x0121=0x323C +0x0121=0x313C 0x0101=0x7800 0x025B=0x0000 0x02C6=0x0000 @@ -222,7 +222,7 @@ version=1 0x029C=0x0000 0x028D=0x0000 0x02A1=0x0000 -0x008B=0x21A6 +0x008B=0x278A 0x02A3=0x0000 0x05A4=0x0000 0x02A7=0x0000 @@ -249,7 +249,7 @@ version=1 0x0488=0x0000 0x0496=0x0000 0x04C3=0x0000 -0x0100=0x7409 +0x0100=0xB409 0x04CC=0x0000 0x02A5=0x0000 0x0257=0x0000 @@ -258,7 +258,7 @@ version=1 0x049A=0x0000 0x049B=0x0000 0x0097=0x0000 -0x011E=0x068E +0x011E=0x0663 0x0285=0x0000 0x0280=0x0000 0x049E=0x0000 @@ -346,7 +346,7 @@ version=1 0x054C=0x7FFF 0x0582=0x150F 0x0585=0xDAA2 -0x0109=0x61C1 +0x0109=0x03C1 0x04A2=0x0000 0x0292=0x0000 0x059F=0x0000 @@ -371,7 +371,7 @@ version=1 0x0399=0x0000 0x050B=0xF5EF 0x0507=0xFCFE -0x010D=0x015B +0x010D=0x01DC 0x04C4=0x0000 0x0495=0x0000 0x0246=0x0000 @@ -380,7 +380,7 @@ version=1 0x0323=0x0000 0x02E5=0x0000 0x055B=0x57AC -0x0114=0x008D +0x0114=0x0170 0x04D8=0x0000 0x04E7=0x0000 0x04D0=0x0000 @@ -413,25 +413,25 @@ version=1 0x04A7=0x0000 0x0489=0x0000 0x02E0=0x0000 -0x0118=0x018C +0x0118=0x218C 0x002A=0x0086 0x0245=0x0000 0x045D=0x0000 0x0581=0xC89D 0x02D2=0x0000 0x039C=0x0000 -0x002B=0x0038 +0x002B=0x4032 0x02A0=0x0000 -0x010E=0x0000 +0x010E=0x070C 0x0394=0x0000 0x0459=0x0000 -0x0088=0x0550 +0x0088=0x0530 0x0085=0x0001 -0x0089=0x1150 +0x0089=0x00A0 0x0256=0x0000 -0x0111=0x0083 +0x0111=0x0099 0x0095=0x0000 -0x0203=0x0000 +0x0203=0x2F6C 0x030E=0x0000 0x0482=0x0000 0x05A0=0x0000 @@ -450,7 +450,7 @@ version=1 0x0391=0x0000 0x04CB=0x0000 0x010F=0x3042 -0x0119=0x18CB +0x0119=0x529F 0x02A6=0x0000 0x05A1=0x0000 0x02C9=0x0000 @@ -463,7 +463,7 @@ version=1 0x0247=0x0000 0x0512=0x196B 0x04E5=0x0000 -0x0024=0xE4E4 +0x0024=0x50D8 0x0353=0x0000 0x050D=0x0F45 0x02CD=0x0000 @@ -472,9 +472,9 @@ version=1 0x034C=0x0000 0x00AA=0x0000 0x0350=0x0000 -0x0445=0xDA02 +0x0445=0x0000 0x048F=0x0000 -0x008A=0x0514 +0x008A=0x0491 0x0453=0x0000 0x0260=0x0000 0x00A1=0x6565 @@ -484,17 +484,17 @@ version=1 0x038F=0x0000 0x054A=0x8184 0x00A4=0x6565 -0x0401=0x07FF +0x0401=0x07ED 0x04CD=0x0000 0x0249=0x0000 -0x002C=0x0000 +0x002C=0x0100 0x054D=0xF7A3 0x00A6=0x0001 0x002D=0xFFFF 0x00AC=0x2000 0x0253=0x0000 0x028B=0x0000 -0x040C=0x00FC +0x040C=0x40F8 0x0310=0x0000 0x0099=0x6565 0x00A2=0x6565 @@ -534,13 +534,13 @@ version=1 0x0029=0x0101 0x024A=0x0000 0x00A7=0x6565 -0x0027=0xB1E4 -0x0117=0x280C +0x0027=0x05E4 +0x0117=0x1939 0x0098=0x0000 -0x0108=0x3042 +0x0108=0xFC26 0x020B=0x0000 0x0383=0x0000 -0x0202=0x07FF +0x0202=0x07F9 0x0086=0x4101 0x010C=0x8865 0x02D8=0x0000 @@ -550,11 +550,11 @@ version=1 0x0104=0x0088 0x0357=0x0000 0x02DB=0x0000 -0x0400=0x0081 +0x0400=0x0101 0x009B=0x6565 0x0105=0x0007 0x05A3=0x0000 -0x0240=0x0020 +0x0240=0x0028 0x0367=0x0000 0x044F=0x0000 0x038B=0x0000 @@ -571,7 +571,7 @@ version=1 0x0587=0x1D10 0x0023=0x5550 0x048C=0x0000 -0x0112=0xC0E6 +0x0112=0x20E5 0x039A=0x0000 0x0115=0x0009 0x00A9=0x8000 @@ -715,7 +715,7 @@ version=1 0x038A=0x0000 0x0362=0x0000 0x0387=0x0000 -0x0200=0x0101 +0x0200=0x0081 0x0594=0x0000 0x02C5=0x0000 0x02A7=0x0000 @@ -732,7 +732,7 @@ version=1 0x0295=0x0000 0x055A=0x0000 0x029C=0x0000 -0x010E=0x2000 +0x010E=0x2040 0x02A0=0x0000 0x010F=0x3042 0x02A6=0x0000 @@ -765,7 +765,7 @@ version=1 0x0104=0x0088 0x0357=0x0000 0x02DB=0x0000 -0x0400=0x0101 +0x0400=0x0081 0x0209=0x0000 0x0297=0x0000 0x02DD=0x0000 @@ -798,7 +798,7 @@ version=1 0x044A=0x0000 0x04A4=0x0000 0x04C4=0x0000 -0x010D=0x019C +0x010D=0x009E 0x0300=0x0000 0x0587=0x0000 0x044E=0x0000 @@ -834,7 +834,7 @@ version=1 0x055D=0x0000 0x0298=0x0000 0x055F=0x0000 -0x011D=0x7555 +0x011D=0x699D 0x039E=0x0000 0x0547=0x0000 0x0598=0x0000 @@ -932,7 +932,7 @@ version=1 0x0110=0x0BF4 0x0204=0x0000 0x0252=0x0000 -0x011E=0x06EC +0x011E=0x06B9 0x049B=0x0000 0x0294=0x0000 0x011C=0xAD41 @@ -977,7 +977,7 @@ version=1 0x045B=0x0000 0x0100=0x3409 0x0340=0x0000 -0x0208=0x0170 +0x0208=0x0070 0x0111=0x0083 0x0247=0x0000 0x024B=0x0000 @@ -997,14 +997,14 @@ version=1 0x010A=0x104C 0x0461=0x0000 0x051B=0x0000 -0x0121=0x348C +0x0121=0x333C 0x0115=0x0009 0x0112=0xC0E6 0x039A=0x0000 0x02CC=0x0000 0x0116=0x8180 0x04A0=0x0000 -0x0108=0x3042 +0x0108=0x9442 0x020B=0x4000 0x0251=0x0000 0x0488=0x0000 @@ -1027,7 +1027,7 @@ version=1 0x024E=0x0000 0x0253=0x0000 0x028B=0x0000 -0x040C=0x00FC +0x040C=0x0000 0x0255=0x0000 0x0258=0x0000 0x0502=0x0000 @@ -1045,7 +1045,7 @@ version=1 0x025C=0x0000 0x0355=0x0000 0x044C=0x0000 -0x010C=0x8865 +0x010C=0x88FD 0x0284=0x0000 0x0396=0x0000 0x0363=0x0000 diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpb210.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpb210.conf index e94e7c79a9..2ce9598129 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpb210.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.usrpb210.conf @@ -140,10 +140,10 @@ eNBs = NETWORK_INTERFACES : { ENB_INTERFACE_NAME_FOR_S1_MME = "eth0"; - ENB_IPV4_ADDRESS_FOR_S1_MME = "192.168.12.212/24"; + ENB_IPV4_ADDRESS_FOR_S1_MME = "192.168.12.215/24"; ENB_INTERFACE_NAME_FOR_S1U = "eth0"; - ENB_IPV4_ADDRESS_FOR_S1U = "192.168.12.212/24"; + ENB_IPV4_ADDRESS_FOR_S1U = "192.168.12.215/24"; ENB_PORT_FOR_S1U = 2152; # Spec 2152 }; From fdb71a0a13ace9fbae7d6df9de31868dae6c5f65 Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Mon, 15 Feb 2016 19:20:15 +0100 Subject: [PATCH 228/263] fixes for Ethernet timing --- .../ETHERNET/USERSPACE/LIB/ethernet_lib.c | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c b/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c index 1582273d48..4fa522f21a 100644 --- a/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c +++ b/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c @@ -353,28 +353,28 @@ int transport_init(openair0_device *device, openair0_config_t *openair0_cfg, eth switch ((int)openair0_cfg[0].sample_rate) { case 30720000: openair0_cfg[0].samples_per_packet = 4096; - openair0_cfg[0].tx_sample_advance = 0; - openair0_cfg[0].tx_scheduling_advance = 22*openair0_cfg[0].samples_per_packet; + openair0_cfg[0].tx_sample_advance = 115; + openair0_cfg[0].tx_scheduling_advance = 11*openair0_cfg[0].samples_per_packet; break; case 23040000: openair0_cfg[0].samples_per_packet = 2048; - openair0_cfg[0].tx_sample_advance = 0; - openair0_cfg[0].tx_scheduling_advance = 16*openair0_cfg[0].samples_per_packet; + openair0_cfg[0].tx_sample_advance = 113; + openair0_cfg[0].tx_scheduling_advance = 8*openair0_cfg[0].samples_per_packet; break; case 15360000: openair0_cfg[0].samples_per_packet = 2048; - openair0_cfg[0].tx_sample_advance = 0; - openair0_cfg[0].tx_scheduling_advance = 10*openair0_cfg[0].samples_per_packet; + openair0_cfg[0].tx_sample_advance = 113; + openair0_cfg[0].tx_scheduling_advance = 9*openair0_cfg[0].samples_per_packet; break; case 7680000: openair0_cfg[0].samples_per_packet = 1024; - openair0_cfg[0].tx_sample_advance = 0; - openair0_cfg[0].tx_scheduling_advance = 10*openair0_cfg[0].samples_per_packet; - break; + openair0_cfg[0].tx_sample_advance = 70; + openair0_cfg[0].tx_scheduling_advance = 9*openair0_cfg[0].samples_per_packet; + break; case 1920000: openair0_cfg[0].samples_per_packet = 256; - openair0_cfg[0].tx_sample_advance = 0; - openair0_cfg[0].tx_scheduling_advance = 16*openair0_cfg[0].samples_per_packet; + openair0_cfg[0].tx_sample_advance = 40; + openair0_cfg[0].tx_scheduling_advance = 8*openair0_cfg[0].samples_per_packet; break; default: printf("Error: unknown sampling rate %f\n",openair0_cfg[0].sample_rate); From dded63e6e9b9ddb06cec686cf172c896dc2adc1e Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Mon, 15 Feb 2016 19:42:59 +0100 Subject: [PATCH 229/263] added flags param to trx_brf_write --- targets/ARCH/BLADERF/USERSPACE/LIB/bladerf_lib.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/targets/ARCH/BLADERF/USERSPACE/LIB/bladerf_lib.c b/targets/ARCH/BLADERF/USERSPACE/LIB/bladerf_lib.c index a5f0c0adbb..2f73d6978c 100644 --- a/targets/ARCH/BLADERF/USERSPACE/LIB/bladerf_lib.c +++ b/targets/ARCH/BLADERF/USERSPACE/LIB/bladerf_lib.c @@ -104,8 +104,9 @@ static void trx_brf_stats(openair0_device *device){ @param buff Buffer which holds the samples @param nsamps number of samples to be sent @param cc index of the component carrier + @param flags Ignored for the moment */ -static int trx_brf_write(openair0_device *device,openair0_timestamp ptimestamp, void **buff, int nsamps, int cc) { +static int trx_brf_write(openair0_device *device,openair0_timestamp ptimestamp, void **buff, int nsamps, int cc, int flags) { int status; brf_state_t *brf = (brf_state_t*)device->priv; From 7998985dd5ae3434093e77cd89177be42337cc51 Mon Sep 17 00:00:00 2001 From: kaltenbe Date: Mon, 15 Feb 2016 22:31:28 +0100 Subject: [PATCH 230/263] 10 MHz configurations for SoDeRa. --- targets/ARCH/LMSSDR/USERSPACE/LIB/lms_lib.cpp | 29 +- ...nb_sodera_highband_10MHz_rx19dB_txfull.ini | 1128 +++++++++++++++++ 2 files changed, 1144 insertions(+), 13 deletions(-) create mode 100644 targets/ARCH/LMSSDR/enb_sodera_highband_10MHz_rx19dB_txfull.ini diff --git a/targets/ARCH/LMSSDR/USERSPACE/LIB/lms_lib.cpp b/targets/ARCH/LMSSDR/USERSPACE/LIB/lms_lib.cpp index 2402027506..8ee4845b51 100644 --- a/targets/ARCH/LMSSDR/USERSPACE/LIB/lms_lib.cpp +++ b/targets/ARCH/LMSSDR/USERSPACE/LIB/lms_lib.cpp @@ -645,25 +645,26 @@ int trx_lms_start(openair0_device *device){ // Set TX filter printf("Tuning TX filter\n"); - opStatus = lms7->TuneTxFilter(LMS7002M::TxFilter::TX_HIGHBAND,28.0); + opStatus = lms7->TuneTxFilter(LMS7002M::TxFilter::TX_HIGHBAND,device->openair0_cfg[0].tx_bw/1e6); if (opStatus != LIBLMS7_SUCCESS) { - printf("Warning: Could not tune TX filter\n"); + printf("Warning: Could not tune TX filter to %f MHz\n",device->openair0_cfg[0].tx_bw/1e6); } printf("Tuning RX filter\n"); - opStatus = lms7->TuneRxFilter(LMS7002M::RxFilter::RX_LPF_LOWBAND,5.0); + + opStatus = lms7->TuneRxFilter(LMS7002M::RxFilter::RX_LPF_LOWBAND,device->openair0_cfg[0].rx_bw/1e6); if (opStatus != LIBLMS7_SUCCESS) { - printf("Warning: Could not tune RX filter\n"); + printf("Warning: Could not tune RX filter to %f MHz\n",device->openair0_cfg[0].rx_bw/1e6); } - printf("Tuning TIA filter\n"); + /* printf("Tuning TIA filter\n"); opStatus = lms7->TuneRxFilter(LMS7002M::RxFilter::RX_TIA,7.0); if (opStatus != LIBLMS7_SUCCESS) { printf("Warning: Could not tune RX TIA filter\n"); - } + }*/ opStatus = lms7->SetInterfaceFrequency(lms7->GetFrequencyCGEN_MHz(), lms7->Get_SPI_Reg_bits(HBI_OVR_TXTSP), @@ -683,7 +684,9 @@ int trx_lms_start(openair0_device *device){ lmsStream = new LMS_StreamBoard(usbport); LMS_StreamBoard::Status opStreamStatus; // this will configure that sampling rate at output of FPGA - opStreamStatus = lmsStream->ConfigurePLL(usbport,device->openair0_cfg[0].sample_rate,device->openair0_cfg[0].sample_rate,90); + opStreamStatus = lmsStream->ConfigurePLL(usbport, + device->openair0_cfg[0].sample_rate, + device->openair0_cfg[0].sample_rate,90); if (opStatus != LIBLMS7_SUCCESS){ printf("Sample rate programming failed\n"); exit(-1); @@ -827,16 +830,16 @@ int openair0_dev_init_lms(openair0_device *device, openair0_config_t *openair0_c case 15360000: openair0_cfg[0].samples_per_packet = 2048; openair0_cfg[0].tx_sample_advance = 45; - openair0_cfg[0].tx_bw = 15.36e6; - openair0_cfg[0].rx_bw = 15.36e6; - openair0_cfg[0].tx_scheduling_advance = 5*openair0_cfg[0].samples_per_packet; + openair0_cfg[0].tx_bw = 28e6; + openair0_cfg[0].rx_bw = 10e6; + openair0_cfg[0].tx_scheduling_advance = 8*openair0_cfg[0].samples_per_packet; break; case 7680000: openair0_cfg[0].samples_per_packet = 1024; openair0_cfg[0].tx_sample_advance = 70; - openair0_cfg[0].tx_bw = 7.68e6; - openair0_cfg[0].rx_bw = 7.68e6; - openair0_cfg[0].tx_scheduling_advance = 12*openair0_cfg[0].samples_per_packet; + openair0_cfg[0].tx_bw = 28e6; + openair0_cfg[0].rx_bw = 5.0e6; + openair0_cfg[0].tx_scheduling_advance = 5*openair0_cfg[0].samples_per_packet; break; case 1920000: openair0_cfg[0].samples_per_packet = 256; diff --git a/targets/ARCH/LMSSDR/enb_sodera_highband_10MHz_rx19dB_txfull.ini b/targets/ARCH/LMSSDR/enb_sodera_highband_10MHz_rx19dB_txfull.ini new file mode 100644 index 0000000000..e4e420c334 --- /dev/null +++ b/targets/ARCH/LMSSDR/enb_sodera_highband_10MHz_rx19dB_txfull.ini @@ -0,0 +1,1128 @@ +[file_info] +type=lms7002m_minimal_config +version=1 +[lms7002_registers_a] +0x0493=0x0000 +0x0492=0x0000 +0x0491=0x0000 +0x029B=0x0000 +0x048E=0x0000 +0x0022=0x07FF +0x0283=0x0000 +0x0487=0x0000 +0x0486=0x0000 +0x045F=0x0000 +0x0480=0x0000 +0x0460=0x0000 +0x0447=0x0000 +0x045A=0x0000 +0x02DA=0x0000 +0x0458=0x0000 +0x0314=0x0000 +0x0456=0x0000 +0x0559=0xACB9 +0x0451=0x0000 +0x0390=0x0000 +0x044B=0x0000 +0x0448=0x0000 +0x0454=0x0000 +0x0446=0x0000 +0x04CA=0x0000 +0x0444=0x0000 +0x0443=0x0000 +0x0508=0xEF99 +0x0441=0x0000 +0x040D=0x0000 +0x040B=0x000F +0x0409=0x0000 +0x0580=0xEFF2 +0x0407=0x0000 +0x0405=0x0000 +0x0254=0x0000 +0x0404=0x0000 +0x00A0=0x6565 +0x0560=0x174B +0x0403=0x0013 +0x0402=0x07D9 +0x055E=0xDB10 +0x03A7=0x0000 +0x0520=0x174B +0x03A5=0x0000 +0x03A4=0x0000 +0x03A3=0x0000 +0x03A2=0x0000 +0x051C=0x0000 +0x048D=0x0000 +0x059A=0x0000 +0x03A1=0x0000 +0x02A2=0x0000 +0x04E1=0x0000 +0x039F=0x0000 +0x0248=0x0000 +0x039B=0x0000 +0x0408=0x0000 +0x0398=0x0000 +0x0393=0x0000 +0x0305=0x0000 +0x038E=0x0000 +0x0324=0x0000 +0x02E7=0x0000 +0x038D=0x0000 +0x0387=0x0000 +0x03A0=0x0000 +0x02D0=0x0000 +0x009A=0x658C +0x054E=0x8184 +0x0386=0x0000 +0x040F=0x43E4 +0x04E3=0x0000 +0x0389=0x0000 +0x054F=0x18C9 +0x0385=0x0000 +0x0315=0x0000 +0x0384=0x0000 +0x0382=0x0000 +0x0288=0x0000 +0x0366=0x0000 +0x0365=0x0000 +0x0364=0x0000 +0x0325=0x0000 +0x0081=0x0000 +0x0362=0x0000 +0x038A=0x0000 +0x035E=0x0000 +0x035D=0x0000 +0x0442=0x0000 +0x0449=0x0000 +0x035A=0x0000 +0x02C8=0x0000 +0x0452=0x0000 +0x0299=0x0000 +0x0359=0x0000 +0x0358=0x0000 +0x048B=0x0000 +0x0354=0x0000 +0x0351=0x0000 +0x03A6=0x0000 +0x0293=0x0000 +0x034E=0x0000 +0x035C=0x0000 +0x034D=0x0000 +0x034B=0x0000 +0x011A=0x2E14 +0x0455=0x0000 +0x034A=0x0000 +0x0348=0x0000 +0x0084=0x0400 +0x0498=0x0000 +0x035B=0x0000 +0x0505=0x00D8 +0x0345=0x0000 +0x0484=0x0000 +0x0586=0x196B +0x0344=0x0000 +0x0561=0xAB08 +0x0343=0x0000 +0x0342=0x0000 +0x0380=0x0000 +0x0327=0x0000 +0x0322=0x0000 +0x059B=0x0000 +0x0321=0x0000 +0x045E=0x0000 +0x0440=0x0024 +0x031D=0x0000 +0x0363=0x0000 +0x031A=0x0000 +0x031C=0x0000 +0x028F=0x0000 +0x0341=0x0000 +0x0287=0x0000 +0x0318=0x0000 +0x031F=0x0000 +0x0316=0x0000 +0x030D=0x0000 +0x040E=0x0003 +0x0352=0x0000 +0x028C=0x0000 +0x0360=0x0000 +0x0313=0x0000 +0x0461=0x0000 +0x010A=0x104C +0x051B=0xB77F +0x0312=0x0000 +0x0346=0x0000 +0x024E=0x0000 +0x0311=0x0000 +0x02D6=0x0000 +0x030C=0x0000 +0x04DF=0x0000 +0x030B=0x0000 +0x0392=0x0000 +0x030A=0x0000 +0x029F=0x0000 +0x0309=0x0000 +0x048A=0x0000 +0x0308=0x0000 +0x0588=0xE6C7 +0x0397=0x0000 +0x02E3=0x0000 +0x049C=0x0000 +0x044A=0x0000 +0x04A4=0x0000 +0x0306=0x0000 +0x0304=0x0000 +0x04D5=0x0000 +0x0303=0x0000 +0x0302=0x0000 +0x0510=0xE6C7 +0x044E=0x0000 +0x0300=0x0000 +0x034F=0x0000 +0x045B=0x0000 +0x02E6=0x0000 +0x00A3=0x6565 +0x04DA=0x0000 +0x025E=0x0000 +0x020A=0x0080 +0x0102=0x3180 +0x020C=0x8000 +0x05A2=0x0000 +0x040A=0x1000 +0x0556=0xA2B5 +0x0243=0x0000 +0x051D=0x4F91 +0x0259=0x0000 +0x02D5=0x0000 +0x02E1=0x0000 +0x011D=0xAAAA +0x039E=0x0000 +0x0252=0x0000 +0x0204=0xC016 +0x0255=0x0000 +0x0281=0x0000 +0x0200=0x0301 +0x0594=0xF40D +0x02C5=0x0000 +0x0406=0x0000 +0x030F=0x0000 +0x025D=0x0000 +0x0319=0x0000 +0x0121=0x3760 +0x0101=0x7800 +0x025B=0x0000 +0x02C6=0x0000 +0x0558=0x5009 +0x0021=0x0E9F +0x04C2=0x0000 +0x0290=0x0000 +0x02DF=0x0000 +0x0291=0x0000 +0x0296=0x0000 +0x029C=0x0000 +0x028D=0x0000 +0x02A1=0x0000 +0x008B=0x2756 +0x02A3=0x0000 +0x05A4=0x0000 +0x02A7=0x0000 +0x0483=0x0000 +0x0201=0x07FF +0x02C2=0x0000 +0x02C4=0x0000 +0x044D=0x0000 +0x02E2=0x0000 +0x02D1=0x0000 +0x0546=0x8D44 +0x04C8=0x0000 +0x0207=0x0000 +0x04C6=0x0000 +0x0096=0x0000 +0x0093=0x0000 +0x0250=0x0000 +0x02CB=0x0000 +0x02D3=0x0000 +0x0494=0x0000 +0x04CF=0x0000 +0x025F=0x0000 +0x0251=0x0000 +0x0488=0x0000 +0x0496=0x0000 +0x04C3=0x0000 +0x0100=0x3409 +0x04CC=0x0000 +0x02A5=0x0000 +0x0257=0x0000 +0x04D6=0x0000 +0x04A6=0x0000 +0x049A=0x0000 +0x049B=0x0000 +0x0097=0x0000 +0x011E=0x0A2A +0x0285=0x0000 +0x0280=0x0000 +0x049E=0x0000 +0x0020=0xFFFD +0x02DD=0x0000 +0x0297=0x0000 +0x049F=0x0000 +0x0522=0xDB10 +0x044C=0x0000 +0x0355=0x0000 +0x04A0=0x0000 +0x02CF=0x0000 +0x04D1=0x0000 +0x0526=0xBE2A +0x0092=0x0001 +0x031B=0x0000 +0x0541=0x4C24 +0x0518=0xEFF2 +0x0543=0xBD96 +0x02C0=0x0000 +0x0499=0x0000 +0x04A1=0x0000 +0x058D=0xF5EF +0x02D7=0x0000 +0x0513=0xDAA2 +0x0549=0x18C9 +0x0552=0x8D44 +0x0521=0x5852 +0x0509=0x0605 +0x0286=0x0000 +0x024F=0x0000 +0x04E0=0x0000 +0x0545=0x364E +0x0349=0x0000 +0x0555=0xBD96 +0x04E4=0x0000 +0x02E4=0x0000 +0x0551=0xD7B7 +0x055D=0xA6B5 +0x0298=0x0000 +0x055F=0x5852 +0x009E=0x658C +0x0547=0xD7B7 +0x0598=0xF61D +0x0123=0x067B +0x0497=0x0000 +0x04A5=0x0000 +0x0565=0xB77F +0x0124=0x0000 +0x0592=0x0DF1 +0x0591=0xFCFE +0x0548=0x79FA +0x04D2=0x0000 +0x0599=0x0000 +0x0511=0x1D10 +0x0506=0x0DF1 +0x0595=0x00BC +0x0584=0xE7E2 +0x0242=0x0000 +0x025A=0x0000 +0x04E2=0x0000 +0x04C5=0x0000 +0x058C=0xEA50 +0x0450=0x0000 +0x0596=0x0A94 +0x05A7=0x0000 +0x058A=0x17DC +0x059D=0x0000 +0x0485=0x0000 +0x058E=0x1316 +0x0550=0x79FA +0x0554=0x6901 +0x0593=0x00D8 +0x0542=0xA2B5 +0x0553=0x364E +0x0563=0x4F91 +0x024D=0x0000 +0x0567=0x4049 +0x055A=0xBE2A +0x0295=0x0000 +0x0566=0x0906 +0x028A=0x0000 +0x059C=0x0000 +0x04DD=0x0000 +0x054C=0x7FFF +0x0582=0x150F +0x0585=0xDAA2 +0x0109=0x8CC1 +0x04A2=0x0000 +0x0292=0x0000 +0x059F=0x0000 +0x0583=0x2E45 +0x050E=0x17DC +0x0516=0x150F +0x0523=0xA6B5 +0x0525=0x57AC +0x0206=0x0000 +0x051A=0x0906 +0x055C=0x3347 +0x0514=0xE7E2 +0x050F=0xEA5F +0x05A6=0x0000 +0x051E=0xF524 +0x050A=0x1316 +0x04C7=0x0000 +0x049D=0x0000 +0x0527=0xACB9 +0x050C=0xEA50 +0x0087=0x0000 +0x0399=0x0000 +0x050B=0xF5EF +0x0507=0xFCFE +0x010D=0x00DE +0x04C4=0x0000 +0x0495=0x0000 +0x0246=0x0000 +0x0503=0x00BC +0x0320=0x0000 +0x0323=0x0000 +0x02E5=0x0000 +0x055B=0x57AC +0x0114=0x0110 +0x04D8=0x0000 +0x04E7=0x0000 +0x04D0=0x0000 +0x04E6=0x0000 +0x00AE=0x0000 +0x0544=0x6901 +0x0258=0x0000 +0x0502=0x0A94 +0x04DE=0x0000 +0x058B=0x0F45 +0x0028=0x0101 +0x029E=0x0000 +0x04DC=0x0000 +0x04D9=0x0000 +0x0557=0x4C24 +0x058F=0x0605 +0x04DB=0x0000 +0x04D7=0x0000 +0x059E=0x0000 +0x024C=0x0000 +0x02DC=0x0000 +0x04D4=0x0000 +0x0504=0xF40D +0x02C3=0x0000 +0x04C1=0x0000 +0x04D3=0x0000 +0x0590=0xEF99 +0x04CE=0x0000 +0x05A5=0x0000 +0x04A7=0x0000 +0x0489=0x0000 +0x02E0=0x0000 +0x0118=0x018C +0x002A=0x0086 +0x0245=0x0000 +0x045D=0x0000 +0x0581=0xC89D +0x02D2=0x0000 +0x039C=0x0000 +0x002B=0x4032 +0x02A0=0x0000 +0x010E=0x0285 +0x0394=0x0000 +0x0459=0x0000 +0x0088=0x04F0 +0x0085=0x0001 +0x0089=0x0048 +0x0256=0x0000 +0x0111=0x0099 +0x0095=0x0000 +0x0203=0x2F99 +0x030E=0x0000 +0x0482=0x0000 +0x05A0=0x0000 +0x009C=0x658C +0x0381=0x0000 +0x0122=0x033F +0x0110=0x0BFF +0x0026=0x0101 +0x0294=0x0000 +0x009D=0x6565 +0x0524=0x3347 +0x0106=0x3182 +0x028E=0x0000 +0x0326=0x0000 +0x0113=0x03C3 +0x0391=0x0000 +0x04CB=0x0000 +0x010F=0x3042 +0x0119=0x18DF +0x02A6=0x0000 +0x05A1=0x0000 +0x02C9=0x0000 +0x0500=0xF61D +0x039D=0x0000 +0x011F=0x3600 +0x0395=0x0000 +0x024B=0x0000 +0x045C=0x0000 +0x0247=0x0000 +0x0512=0x196B +0x04E5=0x0000 +0x0024=0x50D8 +0x0353=0x0000 +0x050D=0x0F45 +0x02CD=0x0000 +0x0490=0x0000 +0x0501=0xFDFB +0x034C=0x0000 +0x00AA=0x0000 +0x0350=0x0000 +0x0445=0x0000 +0x048F=0x0000 +0x008A=0x0491 +0x0453=0x0000 +0x0260=0x0000 +0x00A1=0x6565 +0x0356=0x0000 +0x0241=0x0000 +0x008C=0x267B +0x038F=0x0000 +0x054A=0x8184 +0x00A4=0x6565 +0x0401=0x07FF +0x04CD=0x0000 +0x0249=0x0000 +0x002C=0x0000 +0x054D=0xF7A3 +0x00A6=0x0001 +0x002D=0xFFFF +0x00AC=0x2000 +0x0253=0x0000 +0x028B=0x0000 +0x040C=0x40F8 +0x0310=0x0000 +0x0099=0x6565 +0x00A2=0x6565 +0x0589=0xEA5F +0x002F=0x3840 +0x035F=0x0000 +0x0597=0xFDFB +0x0116=0x8180 +0x02CC=0x0000 +0x0025=0x0101 +0x0562=0xF524 +0x011C=0xA941 +0x0289=0x0000 +0x0282=0x0000 +0x0307=0x0000 +0x038C=0x0000 +0x02C7=0x0000 +0x054B=0xF7A3 +0x0519=0x4049 +0x009F=0x658C +0x025C=0x0000 +0x0515=0x2E45 +0x00A5=0x6565 +0x0301=0x0000 +0x02C1=0x0000 +0x0481=0x0000 +0x0517=0xC89D +0x00A8=0x0000 +0x0564=0x0000 +0x00AB=0x0040 +0x0261=0x0000 +0x002E=0x0000 +0x02DE=0x0000 +0x02A4=0x0000 +0x0540=0x5009 +0x00AD=0x03FF +0x0029=0x0101 +0x024A=0x0000 +0x00A7=0x6565 +0x0027=0x05E4 +0x0117=0x100C +0x0098=0x0000 +0x0108=0xFC26 +0x020B=0x4000 +0x0383=0x0000 +0x0202=0x0794 +0x0086=0x4101 +0x010C=0x8865 +0x02D8=0x0000 +0x0347=0x0000 +0x0457=0x0000 +0x0103=0x0612 +0x0104=0x0088 +0x0357=0x0000 +0x02DB=0x0000 +0x0400=0x0101 +0x009B=0x6565 +0x0105=0x0007 +0x05A3=0x0000 +0x0240=0x0028 +0x0367=0x0000 +0x044F=0x0000 +0x038B=0x0000 +0x02D9=0x0000 +0x02CE=0x0000 +0x0284=0x0000 +0x0396=0x0000 +0x029A=0x0000 +0x051F=0xAB08 +0x0361=0x0000 +0x0205=0x0000 +0x031E=0x0000 +0x04C0=0x0000 +0x0587=0x1D10 +0x0023=0x5550 +0x048C=0x0000 +0x0112=0x3171 +0x039A=0x0000 +0x0115=0x0009 +0x00A9=0x8000 +0x0317=0x0000 +0x0244=0x0000 +0x0094=0x0000 +0x0340=0x0000 +0x0208=0x0170 +0x04A3=0x0000 +0x029D=0x0000 +0x0388=0x0000 +0x0120=0xB9FF +0x04C9=0x0000 +0x02CA=0x0000 +0x0209=0x0000 +0x0082=0x8001 +0x02D4=0x0000 +0x0107=0x318C +[lms7002_registers_b] +0x04E1=0x0000 +0x03A1=0x0000 +0x02A2=0x0000 +0x04E0=0x0000 +0x04DE=0x0000 +0x058B=0x0000 +0x04DC=0x0000 +0x04DB=0x0000 +0x04D9=0x0000 +0x04D5=0x0000 +0x0304=0x0000 +0x04D4=0x0000 +0x0504=0x0000 +0x04D3=0x0000 +0x04D2=0x0000 +0x0548=0x0000 +0x04D0=0x0000 +0x04CF=0x0000 +0x025F=0x0000 +0x04CE=0x0000 +0x04CC=0x0000 +0x02A5=0x0000 +0x04C6=0x0000 +0x0207=0x0000 +0x04C1=0x0000 +0x02C3=0x0000 +0x04C9=0x0000 +0x02CA=0x0000 +0x04C0=0x0000 +0x031E=0x0000 +0x04D6=0x0000 +0x0257=0x0000 +0x04A6=0x0000 +0x04A5=0x0000 +0x04A2=0x0000 +0x0109=0x61C1 +0x049D=0x0000 +0x04C7=0x0000 +0x049C=0x0000 +0x0397=0x0000 +0x02E3=0x0000 +0x0499=0x0000 +0x02C0=0x0000 +0x0496=0x0000 +0x04C3=0x0000 +0x0493=0x0000 +0x04A1=0x0000 +0x0492=0x0000 +0x0491=0x0000 +0x029B=0x0000 +0x048E=0x0000 +0x0283=0x0000 +0x048C=0x0000 +0x048B=0x0000 +0x0358=0x0000 +0x0487=0x0000 +0x0486=0x0000 +0x045F=0x0000 +0x0480=0x0000 +0x0460=0x0000 +0x0447=0x0000 +0x045A=0x0000 +0x02DA=0x0000 +0x0458=0x0000 +0x0314=0x0000 +0x0456=0x0000 +0x0559=0x0000 +0x0453=0x0000 +0x0451=0x0000 +0x0390=0x0000 +0x044D=0x0000 +0x02E2=0x0000 +0x044B=0x0000 +0x0448=0x0000 +0x0454=0x0000 +0x0446=0x0000 +0x04CA=0x0000 +0x0444=0x0000 +0x0443=0x0000 +0x0508=0x0000 +0x0441=0x0000 +0x040D=0x0000 +0x040B=0x7FFF +0x0409=0x0000 +0x0580=0x0000 +0x0407=0x0000 +0x0405=0x0000 +0x0254=0x0000 +0x0404=0x0000 +0x0560=0x0000 +0x04D8=0x0000 +0x0403=0x0000 +0x0402=0x07FF +0x055E=0x0000 +0x03A7=0x0000 +0x0520=0x0000 +0x03A5=0x0000 +0x03A4=0x0000 +0x03A3=0x0000 +0x03A2=0x0000 +0x051C=0x0000 +0x048D=0x0000 +0x059A=0x0000 +0x049E=0x0000 +0x039F=0x0000 +0x0248=0x0000 +0x039B=0x0000 +0x0399=0x0000 +0x0408=0x0000 +0x0398=0x0000 +0x0497=0x0000 +0x0123=0x267B +0x0394=0x0000 +0x0459=0x0000 +0x0393=0x0000 +0x0305=0x0000 +0x038E=0x0000 +0x0324=0x0000 +0x02E7=0x0000 +0x038D=0x0000 +0x0395=0x0000 +0x038A=0x0000 +0x0362=0x0000 +0x0387=0x0000 +0x0200=0x0081 +0x0594=0x0000 +0x02C5=0x0000 +0x02A7=0x0000 +0x0318=0x0000 +0x0544=0x0000 +0x049A=0x0000 +0x0388=0x0000 +0x0120=0xB9FF +0x020A=0x0080 +0x0102=0x3180 +0x0290=0x0000 +0x02DF=0x0000 +0x0291=0x0000 +0x0295=0x0000 +0x055A=0x0000 +0x029C=0x0000 +0x010E=0x2040 +0x02A0=0x0000 +0x010F=0x3042 +0x02A6=0x0000 +0x0119=0x18CB +0x02D2=0x0000 +0x039C=0x0000 +0x028D=0x0000 +0x02A1=0x0000 +0x02C2=0x0000 +0x045E=0x0000 +0x031D=0x0000 +0x0440=0x0020 +0x02C4=0x0000 +0x04D1=0x0000 +0x02CF=0x0000 +0x02C1=0x0000 +0x02C7=0x0000 +0x054B=0x0000 +0x02D3=0x0000 +0x04C8=0x0000 +0x02D1=0x0000 +0x0546=0x0000 +0x0306=0x0000 +0x02D7=0x0000 +0x058D=0x0000 +0x0457=0x0000 +0x02D8=0x0000 +0x0347=0x0000 +0x0103=0x0A12 +0x0104=0x0088 +0x0357=0x0000 +0x02DB=0x0000 +0x0400=0x0081 +0x0209=0x0000 +0x0297=0x0000 +0x02DD=0x0000 +0x029E=0x0000 +0x02DE=0x0000 +0x0527=0x0000 +0x02D5=0x0000 +0x02E1=0x0000 +0x0259=0x0000 +0x0481=0x0000 +0x0517=0x0000 +0x029A=0x0000 +0x051F=0x0000 +0x0483=0x0000 +0x0201=0x07FF +0x0507=0x0000 +0x0321=0x0000 +0x034F=0x0000 +0x0296=0x0000 +0x0510=0x0000 +0x0302=0x0000 +0x038C=0x0000 +0x0307=0x0000 +0x0282=0x0000 +0x0392=0x0000 +0x030B=0x0000 +0x0588=0x0000 +0x0308=0x0000 +0x048A=0x0000 +0x044A=0x0000 +0x04A4=0x0000 +0x04C4=0x0000 +0x010D=0x009E +0x0300=0x0000 +0x0587=0x0000 +0x044E=0x0000 +0x0309=0x0000 +0x0585=0x0000 +0x02E5=0x0000 +0x055B=0x0000 +0x0114=0x008D +0x0323=0x0000 +0x0320=0x0000 +0x0503=0x0000 +0x0513=0x0000 +0x0319=0x0000 +0x0260=0x0000 +0x0549=0x0000 +0x0552=0x0000 +0x0509=0x0000 +0x0521=0x0000 +0x0286=0x0000 +0x04D7=0x0000 +0x059E=0x0000 +0x0557=0x0000 +0x058F=0x0000 +0x0322=0x0000 +0x059B=0x0000 +0x0545=0x0000 +0x0349=0x0000 +0x0555=0x0000 +0x02E4=0x0000 +0x04E4=0x0000 +0x0551=0x0000 +0x0312=0x0000 +0x055D=0x0000 +0x0298=0x0000 +0x055F=0x0000 +0x011D=0xAAAA +0x039E=0x0000 +0x0547=0x0000 +0x0598=0x0000 +0x0449=0x0000 +0x0564=0x0000 +0x0242=0x0000 +0x0525=0x0000 +0x0523=0x0000 +0x0565=0x0000 +0x0124=0x0000 +0x0592=0x0000 +0x0591=0x0000 +0x0563=0x0000 +0x024D=0x0000 +0x0567=0x0000 +0x05A5=0x0000 +0x0566=0x0000 +0x030A=0x0000 +0x029F=0x0000 +0x054C=0x0000 +0x0582=0x0000 +0x0599=0x0000 +0x0511=0x0000 +0x0506=0x0000 +0x0301=0x0000 +0x0595=0x0000 +0x0584=0x0000 +0x058C=0x0000 +0x051E=0x0000 +0x05A6=0x0000 +0x050F=0x0000 +0x0590=0x0000 +0x05A0=0x0000 +0x0596=0x0000 +0x05A7=0x0000 +0x0562=0x0000 +0x058A=0x0000 +0x059D=0x0000 +0x0485=0x0000 +0x0581=0x0000 +0x045D=0x0000 +0x0245=0x0000 +0x0310=0x0000 +0x058E=0x0000 +0x05A2=0x0000 +0x054D=0x0000 +0x020C=0x7FFF +0x0589=0x0000 +0x0522=0x0000 +0x049F=0x0000 +0x031F=0x0000 +0x0292=0x0000 +0x059F=0x0000 +0x0583=0x0000 +0x0543=0x0000 +0x0317=0x0000 +0x0244=0x0000 +0x0554=0x0000 +0x0593=0x0000 +0x05A4=0x0000 +0x02A3=0x0000 +0x0553=0x0000 +0x0542=0x0000 +0x0519=0x0000 +0x024F=0x0000 +0x0524=0x0000 +0x0518=0x0000 +0x0354=0x0000 +0x0526=0x0000 +0x031B=0x0000 +0x050E=0x0000 +0x0516=0x0000 +0x02CB=0x0000 +0x0250=0x0000 +0x031C=0x0000 +0x028F=0x0000 +0x051A=0x0000 +0x055C=0x0000 +0x0514=0x0000 +0x050A=0x0000 +0x050C=0x0000 +0x050B=0x0000 +0x04E7=0x0000 +0x04E6=0x0000 +0x04E5=0x0000 +0x0512=0x0000 +0x0206=0x0000 +0x0550=0x0000 +0x0360=0x0000 +0x030E=0x0000 +0x0203=0x0000 +0x0482=0x0000 +0x0541=0x0000 +0x0122=0x033F +0x0110=0x0BF4 +0x0204=0x0000 +0x0252=0x0000 +0x011E=0x0AA7 +0x049B=0x0000 +0x0294=0x0000 +0x011C=0xA941 +0x02D6=0x0000 +0x0311=0x0000 +0x0117=0x280C +0x02A4=0x0000 +0x0540=0x0000 +0x02E0=0x0000 +0x0118=0x018C +0x0489=0x0000 +0x04A7=0x0000 +0x0101=0x7800 +0x0558=0x0000 +0x02C6=0x0000 +0x05A1=0x0000 +0x02C9=0x0000 +0x039D=0x0000 +0x0500=0x0000 +0x0450=0x0000 +0x011F=0x3600 +0x030C=0x0000 +0x04DF=0x0000 +0x0281=0x0000 +0x0106=0x3182 +0x028E=0x0000 +0x0326=0x0000 +0x0113=0x03C3 +0x04CB=0x0000 +0x0391=0x0000 +0x0105=0x0007 +0x02D9=0x0000 +0x02CE=0x0000 +0x038B=0x0000 +0x044F=0x0000 +0x02D4=0x0000 +0x0107=0x318C +0x0495=0x0000 +0x0246=0x0000 +0x0303=0x0000 +0x02E6=0x0000 +0x045B=0x0000 +0x0100=0x3409 +0x0340=0x0000 +0x0208=0x0070 +0x0111=0x0083 +0x0247=0x0000 +0x024B=0x0000 +0x045C=0x0000 +0x0383=0x0000 +0x0202=0x07FF +0x054A=0x0000 +0x0401=0x07FF +0x0341=0x0000 +0x0287=0x0000 +0x034C=0x0000 +0x0501=0x0000 +0x030F=0x0000 +0x025D=0x0000 +0x0406=0x0000 +0x0313=0x0000 +0x010A=0x104C +0x0461=0x0000 +0x051B=0x0000 +0x0121=0x31FA +0x0115=0x0009 +0x0112=0xC0E6 +0x039A=0x0000 +0x02CC=0x0000 +0x0116=0x8180 +0x04A0=0x0000 +0x0108=0x9442 +0x020B=0x4000 +0x0251=0x0000 +0x0488=0x0000 +0x0241=0x0000 +0x038F=0x0000 +0x02DC=0x0000 +0x024C=0x0000 +0x0494=0x0000 +0x051D=0x0000 +0x0243=0x0000 +0x0556=0x0000 +0x040A=0x0000 +0x04CD=0x0000 +0x0249=0x0000 +0x0261=0x0000 +0x024A=0x0000 +0x0285=0x0000 +0x0280=0x0000 +0x0346=0x0000 +0x024E=0x0000 +0x0253=0x0000 +0x028B=0x0000 +0x040C=0x0000 +0x0255=0x0000 +0x0258=0x0000 +0x0502=0x0000 +0x05A3=0x0000 +0x0367=0x0000 +0x0240=0x0020 +0x0256=0x0000 +0x025A=0x0000 +0x04E2=0x0000 +0x04C5=0x0000 +0x025B=0x0000 +0x0205=0x0000 +0x0361=0x0000 +0x0515=0x0000 +0x025C=0x0000 +0x0355=0x0000 +0x044C=0x0000 +0x010C=0x88FD +0x0284=0x0000 +0x0396=0x0000 +0x0363=0x0000 +0x031A=0x0000 +0x0289=0x0000 +0x028A=0x0000 +0x04DD=0x0000 +0x059C=0x0000 +0x0352=0x0000 +0x028C=0x0000 +0x04C2=0x0000 +0x04DA=0x0000 +0x025E=0x0000 +0x0327=0x0000 +0x0380=0x0000 +0x0342=0x0000 +0x0343=0x0000 +0x0344=0x0000 +0x0561=0x0000 +0x035A=0x0000 +0x02C8=0x0000 +0x0484=0x0000 +0x0586=0x0000 +0x0597=0x0000 +0x035F=0x0000 +0x0345=0x0000 +0x0505=0x0000 +0x035B=0x0000 +0x034A=0x0000 +0x0455=0x0000 +0x011A=0x2E02 +0x034B=0x0000 +0x034D=0x0000 +0x035C=0x0000 +0x034E=0x0000 +0x0293=0x0000 +0x03A6=0x0000 +0x0350=0x0000 +0x0445=0x0000 +0x048F=0x0000 +0x0351=0x0000 +0x0353=0x0000 +0x050D=0x0000 +0x02CD=0x0000 +0x0490=0x0000 +0x0498=0x0000 +0x0348=0x0000 +0x0356=0x0000 +0x030D=0x0000 +0x0316=0x0000 +0x040E=0x0000 +0x04A3=0x0000 +0x029D=0x0000 +0x0359=0x0000 +0x0299=0x0000 +0x0452=0x0000 +0x0442=0x0000 +0x035D=0x0000 +0x035E=0x0000 +0x0325=0x0000 +0x0364=0x0000 +0x0365=0x0000 +0x0366=0x0000 +0x0381=0x0000 +0x0288=0x0000 +0x0382=0x0000 +0x0384=0x0000 +0x0315=0x0000 +0x0385=0x0000 +0x04E3=0x0000 +0x040F=0x0000 +0x0389=0x0000 +0x054F=0x0000 +0x0386=0x0000 +0x02D0=0x0000 +0x054E=0x0000 +0x03A0=0x0000 +[reference_clocks] +sxt_ref_clk_mhz=30.72 +sxr_ref_clk_mhz=30.72 From b30d3c92ad5c18b70da0b7d89b8349d42fe211da Mon Sep 17 00:00:00 2001 From: Raymond Knopp Date: Tue, 16 Feb 2016 02:31:48 -0800 Subject: [PATCH 231/263] added missing threequarter_fs parameter to lte_param_init in ulsim.c --- openair1/SIMULATION/LTE_PHY/dlsim.c | 12 +++++++++++- openair1/SIMULATION/LTE_PHY/ulsim.c | 8 +++++++- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/openair1/SIMULATION/LTE_PHY/dlsim.c b/openair1/SIMULATION/LTE_PHY/dlsim.c index fbb88bf052..2c3d0848c2 100644 --- a/openair1/SIMULATION/LTE_PHY/dlsim.c +++ b/openair1/SIMULATION/LTE_PHY/dlsim.c @@ -656,7 +656,17 @@ int main(int argc, char **argv) printf("dual_stream_UE=%d\n", dual_stream_UE); } - lte_param_init(n_tx,n_rx,transmission_mode,extended_prefix_flag,frame_type,Nid_cell,tdd_config,N_RB_DL,threequarter_fs,osf,perfect_ce); + lte_param_init(n_tx, + n_rx, + transmission_mode, + extended_prefix_flag, + frame_type, + Nid_cell, + tdd_config, + N_RB_DL, + threequarter_fs, + osf, + perfect_ce); diff --git a/openair1/SIMULATION/LTE_PHY/ulsim.c b/openair1/SIMULATION/LTE_PHY/ulsim.c index a72f2ad6c5..463c74c123 100644 --- a/openair1/SIMULATION/LTE_PHY/ulsim.c +++ b/openair1/SIMULATION/LTE_PHY/ulsim.c @@ -194,6 +194,7 @@ int main(int argc, char **argv) int nb_rb_set = 0; int sf; + int threequarter_fs=0; opp_enabled=1; // to enable the time meas cpu_freq_GHz = (double)get_cpu_freq_GHz(); @@ -203,7 +204,7 @@ int main(int argc, char **argv) logInit(); - while ((c = getopt (argc, argv, "hapZbm:n:Y:X:x:s:w:e:q:d:D:O:c:r:i:f:y:c:oA:C:R:g:N:l:S:T:QB:PI:L")) != -1) { + while ((c = getopt (argc, argv, "hapZEbm:n:Y:X:x:s:w:e:q:d:D:O:c:r:i:f:y:c:oA:C:R:g:N:l:S:T:QB:PI:L")) != -1) { switch (c) { case 'a': channel_model = AWGN; @@ -373,6 +374,10 @@ int main(int argc, char **argv) cyclic_shift = atoi(optarg); break; + case 'E': + threequarter_fs=1; + break; + case 'N': N0 = atoi(optarg); break; @@ -470,6 +475,7 @@ int main(int argc, char **argv) 0, tdd_config, N_RB_DL, + threequarter_fs, osf, 0); From f1298f804a4c98eb9d6e6dcb3504d7e81091be74 Mon Sep 17 00:00:00 2001 From: kaltenbe Date: Tue, 16 Feb 2016 15:50:02 +0100 Subject: [PATCH 232/263] added CMakeLists.txt to LMSSDR/lmsSDR --- .../USERSPACE/LIB/lmsSDR/CMakeLists.txt | 58 +++++++++++++++++++ 1 file changed, 58 insertions(+) create mode 100644 targets/ARCH/LMSSDR/USERSPACE/LIB/lmsSDR/CMakeLists.txt diff --git a/targets/ARCH/LMSSDR/USERSPACE/LIB/lmsSDR/CMakeLists.txt b/targets/ARCH/LMSSDR/USERSPACE/LIB/lmsSDR/CMakeLists.txt new file mode 100644 index 0000000000..0225e1d4d6 --- /dev/null +++ b/targets/ARCH/LMSSDR/USERSPACE/LIB/lmsSDR/CMakeLists.txt @@ -0,0 +1,58 @@ +cmake_minimum_required(VERSION 2.8) +set(CMAKE_CONFIGURATION_TYPES "Debug;Release" CACHE TYPE INTERNAL FORCE) +project("matlab_StreamDLL") +#include modules for finding CyAPI +set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake/Modules/") +cmake_policy(SET CMP0015 OLD) +if(${CMAKE_MAJOR_VERSION} GREATER 2) + cmake_policy(SET CMP0043 NEW) +endif() +ADD_DEFINITIONS(-D_CRT_SECURE_NO_WARNINGS) +if(CMAKE_COMPILER_IS_GNUCXX) + SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=c++0x -fPIC") +endif() + +# Add sub-directories +add_subdirectory(LMS_StreamBoard) +include_directories(LMS_StreamBoard) +add_subdirectory(connectionManager) +include_directories(connectionManager) + +set(BINARY_OUTPUT_DIR "${CMAKE_BINARY_DIR}/bin") + +if (MSVC) + SET( MSVC_MULTITHREAD_COMPILE_FLAGS "/MP") + SET( CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${MSVC_MULTITHREAD_COMPILE_FLAGS}" ) +endif(MSVC) + +set(Library_file_list LMS_SDR.cpp ) + +set(BUILD_STATIC_LIB OFF CACHE BOOL "Build static or dynamic library") +if( BUILD_STATIC_LIB ) + add_library(LMS_SDR STATIC ${Library_file_list}) +else() + add_library(LMS_SDR SHARED ${Library_file_list}) +endif(BUILD_STATIC_LIB) + +set(AUTO_UPDATE_VERSION OFF CACHE BOOL "Uses python script to increment version") +if(AUTO_UPDATE_VERSION) + add_custom_target(updateVersion ALL COMMAND python ${CMAKE_CURRENT_SOURCE_DIR}/auto_version.py WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}) + add_dependencies(LMS_SDR updateVersion) +endif() + +target_link_libraries(LMS_SDR + LMS_StreamBoard + ${CYAPI_LIBRARIES} + ) + +if(WIN32) + find_package(CyAPI REQUIRED) + LINK_DIRECTORIES(${CYAPI_LIBRARIES}) + include_directories(${CYAPI_INCLUDE_DIRS}) + set(CONNECTION_MANAGER_LIBS ${CYAPI_LIBRARIES} SetupAPI) +endif() +if(UNIX) + set(CONNECTION_MANAGER_LIBS usb-1.0 -lpthread) +endif() + +target_link_libraries(LMS_SDR ${CONNECTION_MANAGER_LIBS}) From c5bdcd5cb3a4dcc69b57239226bc86c4f82872cb Mon Sep 17 00:00:00 2001 From: kaltenbe Date: Tue, 16 Feb 2016 15:54:19 +0100 Subject: [PATCH 233/263] added missing directory to lms7002m --- .../LIB/lms7002m/cpp-feather-ini-parser/INI.h | 639 ++++++++++++++ .../lms7002m/cpp-feather-ini-parser/LICENSE | 21 + .../lms7002m/cpp-feather-ini-parser/README.md | 47 + .../example/example.cpp | 130 +++ .../cpp-feather-ini-parser/example/file.ini | 5 + .../example/file_ints.ini | 400 +++++++++ .../cpp-feather-ini-parser/example/merge.ini | 5 + .../example/project.cbp | 57 ++ .../example/project.depend | 802 ++++++++++++++++++ 9 files changed, 2106 insertions(+) create mode 100644 targets/ARCH/LMSSDR/USERSPACE/LIB/lms7002m/cpp-feather-ini-parser/INI.h create mode 100644 targets/ARCH/LMSSDR/USERSPACE/LIB/lms7002m/cpp-feather-ini-parser/LICENSE create mode 100644 targets/ARCH/LMSSDR/USERSPACE/LIB/lms7002m/cpp-feather-ini-parser/README.md create mode 100644 targets/ARCH/LMSSDR/USERSPACE/LIB/lms7002m/cpp-feather-ini-parser/example/example.cpp create mode 100644 targets/ARCH/LMSSDR/USERSPACE/LIB/lms7002m/cpp-feather-ini-parser/example/file.ini create mode 100644 targets/ARCH/LMSSDR/USERSPACE/LIB/lms7002m/cpp-feather-ini-parser/example/file_ints.ini create mode 100644 targets/ARCH/LMSSDR/USERSPACE/LIB/lms7002m/cpp-feather-ini-parser/example/merge.ini create mode 100644 targets/ARCH/LMSSDR/USERSPACE/LIB/lms7002m/cpp-feather-ini-parser/example/project.cbp create mode 100644 targets/ARCH/LMSSDR/USERSPACE/LIB/lms7002m/cpp-feather-ini-parser/example/project.depend diff --git a/targets/ARCH/LMSSDR/USERSPACE/LIB/lms7002m/cpp-feather-ini-parser/INI.h b/targets/ARCH/LMSSDR/USERSPACE/LIB/lms7002m/cpp-feather-ini-parser/INI.h new file mode 100644 index 0000000000..de54b4e7b4 --- /dev/null +++ b/targets/ARCH/LMSSDR/USERSPACE/LIB/lms7002m/cpp-feather-ini-parser/INI.h @@ -0,0 +1,639 @@ +/* + Feather INI Parser - 1.40 + You are free to use this however you wish. + + If you find a bug, please attept to debug the cause. + Post your environment details and the cause or fix in the issues section of GitHub. + + Written by Turbine. + + Website: + https://github.com/Turbine1991/feather-ini-parser + http://code.google.com/p/feather-ini-parser/downloads + + Help: + Bundled example & readme. + http://code.google.com/p/feather-ini-parser/wiki/Tutorials +*/ + +#pragma once + +#include +#include +#include +#include +#include +#include + +#define FINI_SAFE +#define FINI_BUFFER_SIZE 128 + +#if __cplusplus >= 201103L + #include + #define FINI_CPP11 + #define ALLOCATE_SECTIONS 100 + #define ALLOCATE_KEYS 5 +#else + #include +#endif + +#ifdef FINI_WIDE_SUPPORT + #include + + typedef std::wstringstream fini_sstream_t; + typedef std::wstring fini_string_t; + typedef wchar_t fini_char_t; + typedef std::wifstream fini_ifstream_t; + typedef std::wofstream fini_ofstream_t; + + #define fini_strlen(a) wcslen(a) + #define fini_strncpy(a, b) wcscpy(a, b) + #define fini_strncpy(a, b, c) wcsncpy(a, b, c) + #define fini_strtok(a, b) wcstok(a, b) + + #define _T(x) L ##x +#else + #include + + typedef std::stringstream fini_sstream_t; + typedef std::string fini_string_t; + typedef char fini_char_t; + typedef std::ifstream fini_ifstream_t; + typedef std::ofstream fini_ofstream_t; + + #define fini_strlen(a) strlen(a) + #define fini_strcpy(a, b) strcpy(a, b) + #define fini_strncpy(a, b, c) strncpy(a, b, c) + #define fini_strtok(a, b) strtok(a, b) + + #define _T(x) x +#endif + +#define CHAR_SIZE sizeof(fini_char_t) + +///Simple converter using templates and streams to effectively required for the flexibility of handling native types +class Converters +{ +public: + template + static T Convert(U value); + template + static void GetLine(fini_sstream_t& out, T& value); + static void GetLine(fini_sstream_t& out, fini_string_t& value); + template + static size_t GetDataSize(T& value); + static size_t GetDataSize(fini_string_t value); +}; + +/// +template + class INI +{ +public: + typedef T section_t; + typedef U key_t; + typedef V value_t; + typedef INI ini_t; + +///Type definition declarations +#ifdef FINI_CPP11 + typedef typename std::unordered_map keys_t; + typedef typename std::unordered_map sections_t; +#else + typedef typename std::map keys_t; + typedef typename std::map sections_t; +#endif + + typedef typename keys_t::iterator keysit_t; + typedef typename sections_t::iterator sectionsit_t; + + typedef typename std::pair keyspair_t; + typedef typename std::pair sectionspair_t; + + typedef char data_t; + + enum source_e {SOURCE_FILE, SOURCE_MEMORY}; + +///Data members + std::string filename; + data_t* data; + size_t dataSize; + keys_t* current; + sections_t sections; + source_e source; + +///Constuctor/Destructor + //Specify the filename to associate and whether to parse immediately + INI(const std::string filename, bool doParse): filename(filename) + { + init(SOURCE_FILE, doParse); + } + + //Used for loading INI from memory + INI(void* data, size_t dataSize, bool doParse): data((data_t*)data), dataSize(dataSize) + { + init(SOURCE_MEMORY, doParse); + } + + ~INI() + { + clear(); + } + +///Access Content + //Provide bracket access to section contents + keys_t& operator[](section_t section) + { + #ifdef FINI_SAFE + if (!sections[section]) + sections[section] = new keys_t; + #endif + + return *sections[section]; + } + + //Create a new section and select it + bool create(const section_t section) + { + if (select(section)) + return false; + + current = new keys_t; + sections[section] = current; + + reserveKeys(current); + + return true; + } + + //Select a section for performing operations + bool select(const section_t section) + { + sectionsit_t sectionsit = sections.find(section); + if (sectionsit == sections.end()) + return false; + + current = sectionsit->second; + + return true; + } + +///Set + //Assign a value for key under the selected section + bool set(const key_t key, const value_t value) + { + if (current == NULL) + return false; + + (*current)[key] = value; + + return true; + } + + template + bool set(const W key, const X value) + { return set(Converters::Convert(key), Converters::Convert(value)); } + +///Get + value_t get(const key_t key, value_t def = value_t()) + { + keysit_t it = current->find(key); + if (current == NULL || it == current->end()) + return def; + + return it->second; + } + + value_t get(const section_t section, const key_t key, value_t def) + { + if (!select(section)) + return def; + + return get(key, def); + } + + template + X get(const W key, const X def = value_t()) + { return Converters::Convert(get(Converters::Convert(key), Converters::Convert(def))); } + + template + fini_string_t get(const W key, const fini_char_t* def = _T("")) //Handle C string default value without casting + { return Converters::Convert(get(Converters::Convert(key), Converters::Convert(def))); } + + template + Y get(const W section, const X key, const Y def) + { return Converters::Convert(get(Converters::Convert(section), Converters::Convert(key), Converters::Convert(def))); } + + template + fini_string_t get(const W section, const X key, const fini_char_t* def) //Handle C string default value without casting + { return Converters::Convert(Converters::Convert(section), get(Converters::Convert(key), Converters::Convert(def))); } + +///Functions + void parse(std::istream& file) + { + fini_char_t line[FINI_BUFFER_SIZE]; + bool first = true; + fini_sstream_t out; + + while(!file.eof()) + { + file.getline(line, FINI_BUFFER_SIZE); + + if (first) + { + first = false; + if (line[0] == 0xEF) //Allows handling of UTF-16/32 documents + { + memmove(line, line + (CHAR_SIZE * 3), CHAR_SIZE * (FINI_BUFFER_SIZE - 3)); + return; + } + } + + nake(line); + + if (line[0]) + { + size_t len = fini_strlen(line); + if (len > 0 && !((len >= 2 && (line[0] == '/' && line[1] == '/')) || (len >= 1 && line[0] == '#'))) //Ignore comment and empty lines + { + if (line[0] == '[') //Section + { + section_t section; + size_t length = fini_strlen(line) - 2; //Without section brackets + while(isspace(line[length + 1])) //Leave out any additional new line characters, not "spaces" as the name suggests + --length; + + fini_char_t* ssection = (fini_char_t*)calloc(CHAR_SIZE, length + 1); + fini_strncpy(ssection, line + 1, length); //Count after first bracket + + current = new keys_t; + + out << ssection; + free(ssection); + Converters::GetLine(out, section); + + sections[section] = current; + } + else //Key + { + key_t key; + value_t value; + + fini_char_t* skey; + fini_char_t* svalue; + + skey = fini_strtok(line, _T("=")); + svalue = fini_strtok(NULL, _T("\n")); + + if (skey && svalue) + { + size_t index = 0; //Without section brackets + while(isspace(skey[index])) //Leave out any additional new line characters, not "spaces" as the name suggests + index++; + + if (index != 0) //Has preceeding white space + fini_strcpy(skey, skey + index); + + out << skey; + + Converters::GetLine(out, key); + + out.clear(); + out.str(fini_string_t()); + + out << svalue; + Converters::GetLine(out, value); + + if (value != value_t()) + (*current)[key] = value; + } + } + + out.clear(); + out.str(fini_string_t()); //Clear existing stream; + } + } + } + } + + //Parse an INI's contents into memory from the filename given during construction + bool parse() + { + switch(source) + { + case SOURCE_FILE: { + fini_ifstream_t file(filename.c_str()); + + if (!file.is_open()) + return false; + + parse(file); + + file.close(); + } + break; + + case SOURCE_MEMORY: { + std::stringstream sstream; + sstream.rdbuf()->pubsetbuf(data, dataSize); + + parse(sstream); + } + break; + } + + return true; + } + + bool parseBinary() + { + fini_ifstream_t file(filename.c_str(), std::ios::binary); + if (!file.is_open()) + return false; + + size_t sectionCount; + size_t keyCount; + key_t key; + value_t value; + section_t section; + + //file.read((fini_char_t*)§ionCount, sizeof(sectionCount)); + file >> sectionCount; + + for(size_t i = 0; i < sectionCount; i++) + { + if (i > 0) + file.seekg(1 + file.tellg()); + + file.read((fini_char_t*)&keyCount, sizeof(keyCount)); + file >> section; + + create(section); + + for(size_t j = 0; j < keyCount; j++) + { + file >> key; + file >> value; + set(key, value); + } + } + + file.close(); + + return true; + } + + //Clear the contents from memory + void clear() + { + clean(); + sections.clear(); + } + +///Output + //Save from memory into file + bool save(const std::string filename = "") + { + if (!hasFileAssociation(filename)) + return false; + + fini_ofstream_t file(((filename == "")? this->filename: filename).c_str(), std::ios::trunc); + if (!file.is_open()) + return false; + + //Loop through sections + for(typename INI::sectionsit_t i = sections.begin(); i != sections.end(); i++) + { + if (i->second->size() == 0) //No keys/values in section, skip to next + continue; + + //Write section + const fini_string_t temp = makeSection(i->first); + const fini_char_t* line = temp.c_str(); + file.write(line, fini_strlen(line)); + + for(typename INI::keysit_t j = i->second->begin(); j != i->second->end(); j++) + { + //Write key and value + const fini_string_t temp = makeKeyValue(j->first, j->second); + const fini_char_t* line = temp.c_str(); + file.write(line, fini_strlen(line)); + } + } + + file.close(); + + return true; + } + + //Saves it without any conventional INI formatting characters, however it only uses string streams + bool saveBinary(const std::string filename = "") + { + if (!hasFileAssociation(filename)) + return false; + + fini_ofstream_t file(((filename == "")? this->filename: filename).c_str(), std::ios::trunc | std::ios::binary); + if (!file.is_open()) + return false; + + size_t sectionCount = sections.size(); + size_t keyCount; + + file.write((fini_char_t*)§ionCount, sizeof(sectionCount)); + + //Loop through sections + for(typename INI::sectionsit_t i = sections.begin(); i != sections.end(); i++) + { + keyCount = i->second->size(); + file.write((fini_char_t*)&keyCount, sizeof(keyCount)); + + file << i->first << std::endl; + + for(typename INI::keysit_t j = i->second->begin(); j != i->second->end(); j++) + { + file << j->first << std::endl; + file << j->second << std::endl; + } + } + + file.close(); + + return true; + } + + //Saves it as a true binary file, intended to replace the existing one. Don't bother using it with all strings. + bool saveBinaryExperimental(std::string filename = "") + { + if (!hasFileAssociation(filename)) + return false; + + fini_ofstream_t file(((filename == "")? this->filename: filename).c_str(), std::ios::trunc | std::ios::binary); + if (!file.is_open()) + return false; + + size_t sectionCount = sections.size(); + size_t keyCount; + + file.write((fini_char_t*)§ionCount, sizeof(sectionCount)); + + //Loop through sections + for(typename INI::sectionsit_t i = sections.begin(); i != sections.end(); i++) + { + keyCount = i->second->size(); + file.write((fini_char_t*)&keyCount, sizeof(keyCount)); + + file.write((fini_char_t*)&i->first, Converters::GetDataSize(i->first)); + + for(typename INI::keysit_t j = i->second->begin(); j != i->second->end(); j++) + { + file.write((fini_char_t*)&j->first, Converters::GetDataSize(j->first)); + file.write((fini_char_t*)&j->second, Converters::GetDataSize(j->second)); + } + } + + file.close(); + + return true; + } + + //Alows another INI's contents to be insert into another, with the ability to retain the original values + void merge(ini_t& other, bool retainValues = true) + { + for(typename INI::sectionsit_t i = other.sections.begin(); i != other.sections.end(); i++) + { + if (!select(i->first)) //Create and insert all key values into a missing section + { + keys_t* keys = new keys_t(*i->second); + sections.insert(std::make_pair(i->first, keys)); + } + else + { + for(typename INI::keysit_t j = i->second->begin(); j != i->second->end(); j++) + { + keysit_t it = current->find(j->first); + if (it == current->end()) + current->insert(std::make_pair(j->first, j->second)); + else if (!retainValues) + it->second = j->second; + } + } + } + } + +private: +///Functions + //Init the INI in with values set by constructor + void init(source_e source, bool doParse) + { + this->source = source; + + reserveSections(); + if (doParse) + parse(); + } + + //Clean the contents for descruction + void clean() + { + for(sectionsit_t i = sections.begin(); i != sections.end(); i++) + delete i->second; + + current = NULL; + } + + //Make any alterations to the raw line + void nake(const fini_char_t*) //Strip the line of any non-interpretable characters + { + + } + + void reserveSections() + { + #ifdef FINI_CPP11 + sections.reserve(ALLOCATE_SECTIONS); + #endif + } + + void reserveKeys(keys_t* current) + { + #ifdef FINI_CPP11 + current->reserve(ALLOCATE_KEYS); + #endif + } + + bool hasFileAssociation(std::string filename) + { + if (source == SOURCE_MEMORY && filename == "") //No association to a file + return false; + + return true; + } + +///Output + //Creates a section as a string + fini_string_t makeSection(const section_t& section) + { + fini_sstream_t line; + line << '[' << section << ']' << std::endl; + + return line.str(); + } + + //Creates a key and a value as a string + fini_string_t makeKeyValue(const key_t& key, const value_t& value) + { + fini_sstream_t line; + line << key << '=' << value << std::endl; + + return line.str(); + } +}; + +///Definitions +template + inline T Converters::Convert(U value) +{ + fini_sstream_t sout; + T result; + + sout << value; + sout >> result; + + sout.str(fini_string_t()); + + return result; +} + +template <> + inline fini_string_t Converters::Convert(fini_string_t value) +{ + return value; +} + +template <> + inline fini_string_t Converters::Convert(const fini_char_t* value) +{ + return value; +} + +template + inline void Converters::GetLine(fini_sstream_t& out, T& value) +{ + out >> value; +} + +inline void Converters::GetLine(fini_sstream_t& out, fini_string_t& value) +{ + std::getline(out, value); +} + +template + inline size_t Converters::GetDataSize(T& value) +{ + return sizeof(value); +} + +inline size_t Converters::GetDataSize(fini_string_t value) +{ + return value.size() + 1; +} diff --git a/targets/ARCH/LMSSDR/USERSPACE/LIB/lms7002m/cpp-feather-ini-parser/LICENSE b/targets/ARCH/LMSSDR/USERSPACE/LIB/lms7002m/cpp-feather-ini-parser/LICENSE new file mode 100644 index 0000000000..7d961cc6e5 --- /dev/null +++ b/targets/ARCH/LMSSDR/USERSPACE/LIB/lms7002m/cpp-feather-ini-parser/LICENSE @@ -0,0 +1,21 @@ +The MIT License (MIT) + +Copyright (c) 2014 Turbine1991 + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. \ No newline at end of file diff --git a/targets/ARCH/LMSSDR/USERSPACE/LIB/lms7002m/cpp-feather-ini-parser/README.md b/targets/ARCH/LMSSDR/USERSPACE/LIB/lms7002m/cpp-feather-ini-parser/README.md new file mode 100644 index 0000000000..f1245971cd --- /dev/null +++ b/targets/ARCH/LMSSDR/USERSPACE/LIB/lms7002m/cpp-feather-ini-parser/README.md @@ -0,0 +1,47 @@ +feather-ini-parser +================== + +Simple like your girlfriend, fast, lightweight, header, portable INI parser for ANSI C++. + +Why use feather-ini-parser? It's a fast, intuitive, uses C++, supports native data types, wide char support (enable), converting to data types simply by setting a default value or providing the type as a template parameter. + +##Methods + +Statement | Return Type +------------- | ------------- +ini(filename, doParse)|constructor +ini(data, dataSize, doParse)|constructor +ini.parse()|bool +ini.merge(other INI, retainValues)|void +ini.create(section)|bool +ini.select(section)|bool +ini.set(key, value)|bool +ini.get(key, dvalue = value_t())|dvalue_t +ini.save(filename = "")|bool +ini.clear()|bool +ini[section][key]|value_t& +ini[section]|keys_t& + +##Example +``` +#include +#include "INI.h" + +using namespace std; +``` +... +``` +typedef INI<> ini_t; +//or +//typedef INI ini_t; + +ini_t ini("filename.ini", true); +ini.create("section1"); //Create and select section1 +ini.set("key", "value"); +cout << ini.get("keynumeric", -1) << endl; +ini["section2"]["key"] = "value"; +ini.save(); +``` + +##More +Please see the example .cpp file and Code::Blocks .cbp project for a compilable GCC and VSC++ example. Additionally includes enabling wide char support and iterating through contents. diff --git a/targets/ARCH/LMSSDR/USERSPACE/LIB/lms7002m/cpp-feather-ini-parser/example/example.cpp b/targets/ARCH/LMSSDR/USERSPACE/LIB/lms7002m/cpp-feather-ini-parser/example/example.cpp new file mode 100644 index 0000000000..462dd241dc --- /dev/null +++ b/targets/ARCH/LMSSDR/USERSPACE/LIB/lms7002m/cpp-feather-ini-parser/example/example.cpp @@ -0,0 +1,130 @@ +#include +#include +#include +#include "../INI.h" + +using namespace std; + +void centerString(string str); //Printing to console +std::string getStringFromFile(const std::string& path); //Source for data loading from memory. + +int main() +{ + ///Declare + typedef INI<> ini_t; //Makes things shorter/easier to write + //or + //typedef INI ini_t; //Equivelant to previous line when wide characters are disabled + ini_t ini("file.ini", true); //File to open/default save filename. The constuctor is set to parse by default, unless specified as false + + ///Manipulate and access contents + centerString("########## Access & Manipulate Contents ##########"); + + //Common usage + ini.create("Section 1"); + ini.create("Section 2"); + ini.get("Key1", "DefaultValue"); + ini.select("Section 1"); + ini.set("Key2", "Value"); + ini.save(); //Save contents to file, optional filename parameter available + ini.clear(); //Clear INI contents from memory + + //Extended usage + ini["Section Name"]["Key"] = "Value"; //You are not required to create a section first + + ini.create("Section1"); //Also selects as current section + ini.create("Section2"); //Current + + ini.set("Key1", "Value1"); //Added pair under section "Section2" + + ini.select("Section1"); //Current + cout << ini.get("Key1", "-1") << endl; //Returns "-1" as no key exists, no default will return NULL for data type, eg int() is 0 + + ini.select("Section2"); + ini.set("Key1", "1.123"); + cout << ini.get("Key1", -1.0) << endl; //Return value as double + ini.set(123, 123); //Will convert to provided INI data type for key/value, in this case string for both + + ini.save(); + ini.clear(); + ini.parse(); //Parses file into objects in memory + + cout << ini["Section2"]["Key1"] << endl; //Returns "Value1", slightly more overhead involved seeking section, avoid using excessively + + ///Iterate through sections and keys for both C++11 and C++98 + centerString("########## Iterate Contents ##########"); + +#ifdef FINI_CPP11 + for(auto i: ini.sections) + { + cout << "[" << i.first << "]" << endl; + + //for(auto j = i.second->begin(); j != i.second->end(); j++) + for(auto j: *i.second) + { + cout << " " << j.first << "=" << j.second << endl; + } + } +#else + for(ini_t::sectionsit_t i = ini.sections.begin(); i != ini.sections.end(); i++) + { + //Section name as ini_t::section_t + cout << i->first << endl; + + if (i->second->size() == 0) //No keys/values in section, skip to next + continue; + + for(ini_t::keysit_t j = i->second->begin(); j != i->second->end(); j++) + { + //Name as ini_t::key_t & Value as ini_t::key_t + cout << " " << j->first << "=" << j->second << endl; + } + } +#endif + +///Example with different data types + typedef INI ini_int_t; //Makes things shorter/easier to write + ini_int_t ini_int("file_ints.ini", false); //File to open/default save filename. The constuctor is set to parse by default, unless specified as false + for(int i = 1; i <= 200; i++) + { + ini_int.create(i); //Section + ini_int.set("Key", i / 2.f); + } + + ini_int.save(); + +///Wide char support example (please define FINI_WIDE_SUPPORT in project) + /* + ini_t ini_w("file.ini", true); + wcout << ini_w[L"Section2"][L"Key1"] << endl; + */ + +///Load from memory + std::string str = getStringFromFile("config/test.ini"); //Allows us to tap into a source for the purpose of this example + + ini_t ini_mem((void*)str.c_str(), str.size(), true); //This is the line which parses data from memory + +///Merge contents and keep values + ini_t inid("file.ini", true); + ini_t inis("merge.ini", true); + inid.merge(inis, true); + inid.save("merged.ini"); + + return EXIT_SUCCESS; +} + +void centerString(string str) +{ + const char* s = str.c_str(); + int l = strlen(s); + int pos = (int)((80 - l) / 2); + for(int i = 0; i < pos; i++) + cout << " "; + cout << s << endl; +} + +std::string getStringFromFile(const std::string& path) { + std::ostringstream buf; + std::ifstream input (path.c_str()); + buf << input.rdbuf(); + return buf.str(); +} diff --git a/targets/ARCH/LMSSDR/USERSPACE/LIB/lms7002m/cpp-feather-ini-parser/example/file.ini b/targets/ARCH/LMSSDR/USERSPACE/LIB/lms7002m/cpp-feather-ini-parser/example/file.ini new file mode 100644 index 0000000000..e1c485ba2a --- /dev/null +++ b/targets/ARCH/LMSSDR/USERSPACE/LIB/lms7002m/cpp-feather-ini-parser/example/file.ini @@ -0,0 +1,5 @@ +[Section2] +123=123 +Key1=1.123 +[Section Name] +Key=Value diff --git a/targets/ARCH/LMSSDR/USERSPACE/LIB/lms7002m/cpp-feather-ini-parser/example/file_ints.ini b/targets/ARCH/LMSSDR/USERSPACE/LIB/lms7002m/cpp-feather-ini-parser/example/file_ints.ini new file mode 100644 index 0000000000..3d71e76cae --- /dev/null +++ b/targets/ARCH/LMSSDR/USERSPACE/LIB/lms7002m/cpp-feather-ini-parser/example/file_ints.ini @@ -0,0 +1,400 @@ +[200] +Key=100 +[199] +Key=99.5 +[198] +Key=99 +[197] +Key=98.5 +[196] +Key=98 +[195] +Key=97.5 +[194] +Key=97 +[193] +Key=96.5 +[192] +Key=96 +[191] +Key=95.5 +[190] +Key=95 +[189] +Key=94.5 +[188] +Key=94 +[187] +Key=93.5 +[186] +Key=93 +[185] +Key=92.5 +[184] +Key=92 +[183] +Key=91.5 +[182] +Key=91 +[181] +Key=90.5 +[180] +Key=90 +[179] +Key=89.5 +[178] +Key=89 +[177] +Key=88.5 +[176] +Key=88 +[175] +Key=87.5 +[174] +Key=87 +[173] +Key=86.5 +[172] +Key=86 +[171] +Key=85.5 +[170] +Key=85 +[169] +Key=84.5 +[168] +Key=84 +[167] +Key=83.5 +[166] +Key=83 +[165] +Key=82.5 +[164] +Key=82 +[163] +Key=81.5 +[162] +Key=81 +[161] +Key=80.5 +[160] +Key=80 +[159] +Key=79.5 +[158] +Key=79 +[157] +Key=78.5 +[156] +Key=78 +[155] +Key=77.5 +[154] +Key=77 +[153] +Key=76.5 +[152] +Key=76 +[151] +Key=75.5 +[150] +Key=75 +[149] +Key=74.5 +[148] +Key=74 +[147] +Key=73.5 +[146] +Key=73 +[145] +Key=72.5 +[144] +Key=72 +[143] +Key=71.5 +[142] +Key=71 +[141] +Key=70.5 +[140] +Key=70 +[139] +Key=69.5 +[138] +Key=69 +[137] +Key=68.5 +[136] +Key=68 +[135] +Key=67.5 +[134] +Key=67 +[133] +Key=66.5 +[132] +Key=66 +[131] +Key=65.5 +[130] +Key=65 +[129] +Key=64.5 +[128] +Key=64 +[127] +Key=63.5 +[126] +Key=63 +[125] +Key=62.5 +[124] +Key=62 +[123] +Key=61.5 +[122] +Key=61 +[121] +Key=60.5 +[120] +Key=60 +[119] +Key=59.5 +[118] +Key=59 +[117] +Key=58.5 +[116] +Key=58 +[115] +Key=57.5 +[114] +Key=57 +[113] +Key=56.5 +[112] +Key=56 +[111] +Key=55.5 +[110] +Key=55 +[109] +Key=54.5 +[108] +Key=54 +[107] +Key=53.5 +[106] +Key=53 +[105] +Key=52.5 +[104] +Key=52 +[103] +Key=51.5 +[1] +Key=0.5 +[2] +Key=1 +[3] +Key=1.5 +[4] +Key=2 +[5] +Key=2.5 +[6] +Key=3 +[7] +Key=3.5 +[8] +Key=4 +[9] +Key=4.5 +[10] +Key=5 +[11] +Key=5.5 +[12] +Key=6 +[13] +Key=6.5 +[14] +Key=7 +[15] +Key=7.5 +[16] +Key=8 +[17] +Key=8.5 +[18] +Key=9 +[19] +Key=9.5 +[20] +Key=10 +[21] +Key=10.5 +[22] +Key=11 +[23] +Key=11.5 +[24] +Key=12 +[25] +Key=12.5 +[26] +Key=13 +[27] +Key=13.5 +[28] +Key=14 +[29] +Key=14.5 +[30] +Key=15 +[31] +Key=15.5 +[32] +Key=16 +[33] +Key=16.5 +[34] +Key=17 +[35] +Key=17.5 +[36] +Key=18 +[37] +Key=18.5 +[38] +Key=19 +[39] +Key=19.5 +[40] +Key=20 +[41] +Key=20.5 +[42] +Key=21 +[43] +Key=21.5 +[44] +Key=22 +[45] +Key=22.5 +[46] +Key=23 +[47] +Key=23.5 +[48] +Key=24 +[49] +Key=24.5 +[50] +Key=25 +[51] +Key=25.5 +[52] +Key=26 +[53] +Key=26.5 +[54] +Key=27 +[55] +Key=27.5 +[56] +Key=28 +[57] +Key=28.5 +[58] +Key=29 +[59] +Key=29.5 +[60] +Key=30 +[61] +Key=30.5 +[62] +Key=31 +[63] +Key=31.5 +[64] +Key=32 +[65] +Key=32.5 +[66] +Key=33 +[67] +Key=33.5 +[68] +Key=34 +[69] +Key=34.5 +[70] +Key=35 +[71] +Key=35.5 +[72] +Key=36 +[73] +Key=36.5 +[74] +Key=37 +[75] +Key=37.5 +[76] +Key=38 +[77] +Key=38.5 +[78] +Key=39 +[79] +Key=39.5 +[80] +Key=40 +[81] +Key=40.5 +[82] +Key=41 +[83] +Key=41.5 +[84] +Key=42 +[85] +Key=42.5 +[86] +Key=43 +[87] +Key=43.5 +[88] +Key=44 +[89] +Key=44.5 +[90] +Key=45 +[91] +Key=45.5 +[92] +Key=46 +[93] +Key=46.5 +[94] +Key=47 +[95] +Key=47.5 +[96] +Key=48 +[97] +Key=48.5 +[98] +Key=49 +[99] +Key=49.5 +[100] +Key=50 +[101] +Key=50.5 +[102] +Key=51 diff --git a/targets/ARCH/LMSSDR/USERSPACE/LIB/lms7002m/cpp-feather-ini-parser/example/merge.ini b/targets/ARCH/LMSSDR/USERSPACE/LIB/lms7002m/cpp-feather-ini-parser/example/merge.ini new file mode 100644 index 0000000000..dfdc381084 --- /dev/null +++ b/targets/ARCH/LMSSDR/USERSPACE/LIB/lms7002m/cpp-feather-ini-parser/example/merge.ini @@ -0,0 +1,5 @@ +[NewSection] +Key=Value +[Section2] +NewKey=Value +123=456 \ No newline at end of file diff --git a/targets/ARCH/LMSSDR/USERSPACE/LIB/lms7002m/cpp-feather-ini-parser/example/project.cbp b/targets/ARCH/LMSSDR/USERSPACE/LIB/lms7002m/cpp-feather-ini-parser/example/project.cbp new file mode 100644 index 0000000000..913928a115 --- /dev/null +++ b/targets/ARCH/LMSSDR/USERSPACE/LIB/lms7002m/cpp-feather-ini-parser/example/project.cbp @@ -0,0 +1,57 @@ + + + + + + diff --git a/targets/ARCH/LMSSDR/USERSPACE/LIB/lms7002m/cpp-feather-ini-parser/example/project.depend b/targets/ARCH/LMSSDR/USERSPACE/LIB/lms7002m/cpp-feather-ini-parser/example/project.depend new file mode 100644 index 0000000000..02c743092d --- /dev/null +++ b/targets/ARCH/LMSSDR/USERSPACE/LIB/lms7002m/cpp-feather-ini-parser/example/project.depend @@ -0,0 +1,802 @@ +# depslib dependency file v1.0 +1399614205 source:d:\projects\feather-ini-parser\example\example.cpp + + + + "../INI.h" + +1399625159 d:\projects\feather-ini-parser\ini.h + + + + + + + + + + + +1374412936 c:\program files (x86)\microsoft visual studio 12.0\vc\include\iostream + + +1374726946 c:\program files (x86)\microsoft visual studio 12.0\vc\include\istream + + +1374726946 c:\program files (x86)\microsoft visual studio 12.0\vc\include\ostream + + +1374726946 c:\program files (x86)\microsoft visual studio 12.0\vc\include\ios + + +1374410776 c:\program files (x86)\microsoft visual studio 12.0\vc\include\xlocnum + + + + + + +1374410776 c:\program files (x86)\microsoft visual studio 12.0\vc\include\climits + + + +1374726946 c:\program files (x86)\microsoft visual studio 12.0\vc\include\yvals.h + + + + + +1374410776 c:\program files (x86)\microsoft visual studio 12.0\vc\include\xkeycheck.h + +1374412934 c:\program files (x86)\microsoft visual studio 12.0\vc\include\crtdefs.h + + + + +1374412934 c:\program files (x86)\microsoft visual studio 12.0\vc\include\sal.h + "codeanalysis\sourceannotations.h" + + +1374412934 c:\program files (x86)\microsoft visual studio 12.0\vc\include\codeanalysis\sourceannotations.h + +1374410776 c:\program files (x86)\microsoft visual studio 12.0\vc\include\concurrencysal.h + +1374412934 c:\program files (x86)\microsoft visual studio 12.0\vc\include\vadefs.h + + +1379495880 c:\program files (x86)\microsoft visual studio 12.0\vc\include\use_ansi.h + +1374412934 c:\program files (x86)\microsoft visual studio 12.0\vc\include\crtwrn.h + + +1374412934 c:\program files (x86)\microsoft visual studio 12.0\vc\include\limits.h + + +1375351090 c:\program files (x86)\microsoft visual studio 12.0\vc\include\cmath + + + + + + +1379495880 c:\program files (x86)\microsoft visual studio 12.0\vc\include\math.h + + +1379495880 c:\program files (x86)\microsoft visual studio 12.0\vc\include\xtgmath.h + + +1374412938 c:\program files (x86)\microsoft visual studio 12.0\vc\include\xtr1common + + +1375351090 c:\program files (x86)\microsoft visual studio 12.0\vc\include\cstdio + + + + +1374410776 c:\program files (x86)\microsoft visual studio 12.0\vc\include\stdio.h + + + +1374726946 c:\program files (x86)\microsoft visual studio 12.0\vc\include\swprintf.inl + + +1375351090 c:\program files (x86)\microsoft visual studio 12.0\vc\include\cstdlib + + + + +1374410776 c:\program files (x86)\microsoft visual studio 12.0\vc\include\stdlib.h + + + +1374412936 c:\program files (x86)\microsoft visual studio 12.0\vc\include\streambuf + + +1374726946 c:\program files (x86)\microsoft visual studio 12.0\vc\include\xiosbase + + + + +1374726946 c:\program files (x86)\microsoft visual studio 12.0\vc\include\xlocale + + + + + + + + +1375351090 c:\program files (x86)\microsoft visual studio 12.0\vc\include\cstring + + + + +1374410776 c:\program files (x86)\microsoft visual studio 12.0\vc\include\string.h + + +1374412936 c:\program files (x86)\microsoft visual studio 12.0\vc\include\stdexcept + + + +1374412936 c:\program files (x86)\microsoft visual studio 12.0\vc\include\exception + + + + + +1374412938 c:\program files (x86)\microsoft visual studio 12.0\vc\include\xstddef + + + + + +1374412936 c:\program files (x86)\microsoft visual studio 12.0\vc\include\cstddef + + + + +1374410776 c:\program files (x86)\microsoft visual studio 12.0\vc\include\stddef.h + + +1374412936 c:\program files (x86)\microsoft visual studio 12.0\vc\include\initializer_list + + +1374412934 c:\program files (x86)\microsoft visual studio 12.0\vc\include\eh.h + + +1374412934 c:\program files (x86)\microsoft visual studio 12.0\vc\include\malloc.h + + +1374412938 c:\program files (x86)\microsoft visual studio 12.0\vc\include\xstring + + +1374726946 c:\program files (x86)\microsoft visual studio 12.0\vc\include\xmemory0 + + + + + + + + +1374412936 c:\program files (x86)\microsoft visual studio 12.0\vc\include\limits + + + + + + + +1374410776 c:\program files (x86)\microsoft visual studio 12.0\vc\include\ymath.h + + +1374412936 c:\program files (x86)\microsoft visual studio 12.0\vc\include\cfloat + + + +1374410776 c:\program files (x86)\microsoft visual studio 12.0\vc\include\float.h + + + +1375351090 c:\program files (x86)\microsoft visual studio 12.0\vc\include\cwchar + + + + +1374726946 c:\program files (x86)\microsoft visual studio 12.0\vc\include\wchar.h + + + + +1374412934 c:\program files (x86)\microsoft visual studio 12.0\vc\include\wtime.inl + +1374412936 c:\program files (x86)\microsoft visual studio 12.0\vc\include\new + + +1374726946 c:\program files (x86)\microsoft visual studio 12.0\vc\include\xutility + + + + +1374412938 c:\program files (x86)\microsoft visual studio 12.0\vc\include\utility + + + + +1374412936 c:\program files (x86)\microsoft visual studio 12.0\vc\include\iosfwd + + + + + + +1374412934 c:\program files (x86)\microsoft visual studio 12.0\vc\include\crtdbg.h + + +1374726946 c:\program files (x86)\microsoft visual studio 12.0\vc\include\type_traits + + + +1374726946 c:\program files (x86)\microsoft visual studio 12.0\vc\include\xrefwrap + +1374412938 c:\program files (x86)\microsoft visual studio 12.0\vc\include\xatomic0.h + + +1379495880 c:\program files (x86)\microsoft visual studio 12.0\vc\include\intrin.h + + + + + + + + +1374412934 c:\program files (x86)\microsoft visual studio 12.0\vc\include\setjmp.h + + + +1374412934 c:\program files (x86)\microsoft visual studio 12.0\vc\include\setjmpex.h + + +1374412934 c:\program files (x86)\microsoft visual studio 12.0\vc\include\immintrin.h + + +1374412934 c:\program files (x86)\microsoft visual studio 12.0\vc\include\wmmintrin.h + + +1374412934 c:\program files (x86)\microsoft visual studio 12.0\vc\include\nmmintrin.h + + +1374412934 c:\program files (x86)\microsoft visual studio 12.0\vc\include\smmintrin.h + + +1374412934 c:\program files (x86)\microsoft visual studio 12.0\vc\include\tmmintrin.h + + +1374412934 c:\program files (x86)\microsoft visual studio 12.0\vc\include\pmmintrin.h + + +1374412934 c:\program files (x86)\microsoft visual studio 12.0\vc\include\emmintrin.h + + +1374410776 c:\program files (x86)\microsoft visual studio 12.0\vc\include\xmmintrin.h + + "xmm_func.h" + + +1374412934 c:\program files (x86)\microsoft visual studio 12.0\vc\include\mmintrin.h + + +1374412934 c:\program files (x86)\microsoft visual studio 12.0\vc\include\ammintrin.h + +1374412934 c:\program files (x86)\microsoft visual studio 12.0\vc\include\mm3dnow.h + + + + +1374412934 c:\program files (x86)\microsoft visual studio 12.0\vc\include\armintr.h + +1374412938 c:\program files (x86)\microsoft visual studio 12.0\vc\include\xatomic.h + + + + + + + +1374726946 c:\program files (x86)\microsoft visual studio 12.0\vc\include\typeinfo + + + + +1374726946 c:\program files (x86)\microsoft visual studio 12.0\vc\include\xlocinfo + + + + +1374410776 c:\program files (x86)\microsoft visual studio 12.0\vc\include\xlocinfo.h + + + + + +1374412934 c:\program files (x86)\microsoft visual studio 12.0\vc\include\ctype.h + + +1374412934 c:\program files (x86)\microsoft visual studio 12.0\vc\include\locale.h + + +1374412938 c:\program files (x86)\microsoft visual studio 12.0\vc\include\xdebug + + + + +1374410776 c:\program files (x86)\microsoft visual studio 12.0\vc\include\xmemory + + +1374410776 c:\program files (x86)\microsoft visual studio 12.0\vc\include\xfacet + + +1374726946 c:\program files (x86)\microsoft visual studio 12.0\vc\include\system_error + + + + +1374412936 c:\program files (x86)\microsoft visual studio 12.0\vc\include\cerrno + + + + +1374410776 c:\program files (x86)\microsoft visual studio 12.0\vc\include\errno.h + + +1374412934 c:\program files (x86)\microsoft visual studio 12.0\vc\include\share.h + +1374412936 c:\program files (x86)\microsoft visual studio 12.0\vc\include\stdint.h + + +1374412936 c:\program files (x86)\microsoft visual studio 12.0\vc\include\string + + +1374412936 c:\program files (x86)\microsoft visual studio 12.0\vc\include\iterator + + + +1374726946 c:\program files (x86)\microsoft visual studio 12.0\vc\include\fstream + + +1374726946 c:\program files (x86)\microsoft visual studio 12.0\vc\include\sstream + + +1374412938 c:\program files (x86)\microsoft visual studio 12.0\vc\include\unordered_map + + + +1374410776 c:\program files (x86)\microsoft visual studio 12.0\vc\include\xhash + + + + + +1374412936 c:\program files (x86)\microsoft visual studio 12.0\vc\include\list + + + +1374410776 c:\program files (x86)\microsoft visual studio 12.0\vc\include\vector + + + +1374412938 c:\program files (x86)\microsoft visual studio 12.0\vc\include\tuple + + + + +1374412936 c:\program files (x86)\microsoft visual studio 12.0\vc\include\map + + + +1374726946 c:\program files (x86)\microsoft visual studio 12.0\vc\include\xtree + + + +1254299028 c:\program files (x86)\microsoft visual studio 10.0\vc\include\iostream + + +1257671184 c:\program files (x86)\microsoft visual studio 10.0\vc\include\istream + + +1257671184 c:\program files (x86)\microsoft visual studio 10.0\vc\include\ostream + + +1257671184 c:\program files (x86)\microsoft visual studio 10.0\vc\include\ios + + +1251642866 c:\program files (x86)\microsoft visual studio 10.0\vc\include\xlocnum + + + + + + +1251642866 c:\program files (x86)\microsoft visual studio 10.0\vc\include\climits + + + +1258271576 c:\program files (x86)\microsoft visual studio 10.0\vc\include\yvals.h + + + + + + + +1260264954 c:\program files (x86)\microsoft visual studio 10.0\vc\include\crtdefs.h + + + +1263987576 c:\program files (x86)\microsoft visual studio 10.0\vc\include\sal.h + "codeanalysis\sourceannotations.h" + +1263303828 c:\program files (x86)\microsoft visual studio 10.0\vc\include\codeanalysis\sourceannotations.h + +1251642866 c:\program files (x86)\microsoft visual studio 10.0\vc\include\vadefs.h + +1251647994 c:\program files (x86)\microsoft visual studio 10.0\vc\include\xkeycheck.h + +1257671184 c:\program files (x86)\microsoft visual studio 10.0\vc\include\crtwrn.h + + +1254299028 c:\program files (x86)\microsoft visual studio 10.0\vc\include\use_ansi.h + +1251642866 c:\program files (x86)\microsoft visual studio 10.0\vc\include\limits.h + + +1251642866 c:\program files (x86)\microsoft visual studio 10.0\vc\include\cmath + + + + +1251642866 c:\program files (x86)\microsoft visual studio 10.0\vc\include\math.h + + +1251642866 c:\program files (x86)\microsoft visual studio 10.0\vc\include\cstdio + + + + +1257335008 c:\program files (x86)\microsoft visual studio 10.0\vc\include\stdio.h + + + +1256197836 c:\program files (x86)\microsoft visual studio 10.0\vc\include\swprintf.inl + + +1251642866 c:\program files (x86)\microsoft visual studio 10.0\vc\include\cstdlib + + + + +1257671184 c:\program files (x86)\microsoft visual studio 10.0\vc\include\stdlib.h + + + +1254299028 c:\program files (x86)\microsoft visual studio 10.0\vc\include\streambuf + + +1254299028 c:\program files (x86)\microsoft visual studio 10.0\vc\include\xiosbase + + + + +1263118342 c:\program files (x86)\microsoft visual studio 10.0\vc\include\xlocale + + + + + + + +1251642866 c:\program files (x86)\microsoft visual studio 10.0\vc\include\cstring + + + + +1260264954 c:\program files (x86)\microsoft visual studio 10.0\vc\include\string.h + + +1251642866 c:\program files (x86)\microsoft visual studio 10.0\vc\include\stdexcept + + + +1254299028 c:\program files (x86)\microsoft visual studio 10.0\vc\include\exception + + + + + +1254299028 c:\program files (x86)\microsoft visual studio 10.0\vc\include\xstddef + + + +1251642866 c:\program files (x86)\microsoft visual studio 10.0\vc\include\cstddef + + + + +1254299028 c:\program files (x86)\microsoft visual studio 10.0\vc\include\stddef.h + + +1254299028 c:\program files (x86)\microsoft visual studio 10.0\vc\include\eh.h + + +1251642866 c:\program files (x86)\microsoft visual studio 10.0\vc\include\malloc.h + + +1257671184 c:\program files (x86)\microsoft visual studio 10.0\vc\include\xstring + + +1254299028 c:\program files (x86)\microsoft visual studio 10.0\vc\include\xmemory + + + + +1251642866 c:\program files (x86)\microsoft visual studio 10.0\vc\include\new + + +1258271576 c:\program files (x86)\microsoft visual studio 10.0\vc\include\xutility + + + + +1257671184 c:\program files (x86)\microsoft visual studio 10.0\vc\include\utility + + + + +1254299028 c:\program files (x86)\microsoft visual studio 10.0\vc\include\iosfwd + + + + + + +1251642866 c:\program files (x86)\microsoft visual studio 10.0\vc\include\cwchar + + + + +1257335008 c:\program files (x86)\microsoft visual studio 10.0\vc\include\wchar.h + + + + +1251642866 c:\program files (x86)\microsoft visual studio 10.0\vc\include\wtime.inl + +1254299028 c:\program files (x86)\microsoft visual studio 10.0\vc\include\crtdbg.h + + +1263118342 c:\program files (x86)\microsoft visual studio 10.0\vc\include\type_traits + + + + +1251642866 c:\program files (x86)\microsoft visual studio 10.0\vc\include\limits + + + + + + + +1251642866 c:\program files (x86)\microsoft visual studio 10.0\vc\include\ymath.h + + +1251642866 c:\program files (x86)\microsoft visual studio 10.0\vc\include\cfloat + + + +1251642866 c:\program files (x86)\microsoft visual studio 10.0\vc\include\float.h + + + +1254299028 c:\program files (x86)\microsoft visual studio 10.0\vc\include\xtr1common + + +1263118342 c:\program files (x86)\microsoft visual studio 10.0\vc\include\xfwrap + + + + + + + + + + + + +1263118342 c:\program files (x86)\microsoft visual studio 10.0\vc\include\xfwrap1 + + + + + + + + + + + + + + +1254299028 c:\program files (x86)\microsoft visual studio 10.0\vc\include\xxbind1 + +1254299028 c:\program files (x86)\microsoft visual studio 10.0\vc\include\xxcallfun + +1254299028 c:\program files (x86)\microsoft visual studio 10.0\vc\include\xxcallobj + +1254299028 c:\program files (x86)\microsoft visual studio 10.0\vc\include\xxcallpmf + +1257671184 c:\program files (x86)\microsoft visual studio 10.0\vc\include\xxfunction + +1251647994 c:\program files (x86)\microsoft visual studio 10.0\vc\include\xxmem_fn + +1254299028 c:\program files (x86)\microsoft visual studio 10.0\vc\include\xxpmfcaller + +1254299028 c:\program files (x86)\microsoft visual studio 10.0\vc\include\xxrefwrap + +1254299028 c:\program files (x86)\microsoft visual studio 10.0\vc\include\xxresult + +1251647994 c:\program files (x86)\microsoft visual studio 10.0\vc\include\xxshared + +1254299028 c:\program files (x86)\microsoft visual studio 10.0\vc\include\xxtuple0 + +1251647994 c:\program files (x86)\microsoft visual studio 10.0\vc\include\xxtuple1 + +1251647994 c:\program files (x86)\microsoft visual studio 10.0\vc\include\xxtype_traits + +1257671184 c:\program files (x86)\microsoft visual studio 10.0\vc\include\typeinfo + + + + +1254299028 c:\program files (x86)\microsoft visual studio 10.0\vc\include\xlocinfo + + + + +1254299028 c:\program files (x86)\microsoft visual studio 10.0\vc\include\xlocinfo.h + + + + + +1251642866 c:\program files (x86)\microsoft visual studio 10.0\vc\include\ctype.h + + +1251642866 c:\program files (x86)\microsoft visual studio 10.0\vc\include\locale.h + + +1263118342 c:\program files (x86)\microsoft visual studio 10.0\vc\include\xdebug + + + + +1260264954 c:\program files (x86)\microsoft visual studio 10.0\vc\include\system_error + + + + +1251642866 c:\program files (x86)\microsoft visual studio 10.0\vc\include\cerrno + + + + +1251642866 c:\program files (x86)\microsoft visual studio 10.0\vc\include\errno.h + + +1251642866 c:\program files (x86)\microsoft visual studio 10.0\vc\include\share.h + +1254299028 c:\program files (x86)\microsoft visual studio 10.0\vc\include\stdint.h + + +1257671184 c:\program files (x86)\microsoft visual studio 10.0\vc\include\string + + +1263118342 c:\program files (x86)\microsoft visual studio 10.0\vc\include\fstream + + +1254299028 c:\program files (x86)\microsoft visual studio 10.0\vc\include\sstream + + +1254299028 c:\program files (x86)\microsoft visual studio 10.0\vc\include\unordered_map + + +1263720180 c:\program files (x86)\microsoft visual studio 10.0\vc\include\xhash + + + + + + +1251647994 c:\program files (x86)\microsoft visual studio 10.0\vc\include\xfunctional + + + +1254299028 c:\program files (x86)\microsoft visual studio 10.0\vc\include\list + + + + +1267607544 c:\program files (x86)\microsoft visual studio 10.0\vc\include\memory + + + + + + + + + +1263118342 c:\program files (x86)\microsoft visual studio 10.0\vc\include\intrin.h + + + + + + +1251642866 c:\program files (x86)\microsoft visual studio 10.0\vc\include\setjmp.h + + + +1251642866 c:\program files (x86)\microsoft visual studio 10.0\vc\include\setjmpex.h + + +1251647992 c:\program files (x86)\microsoft visual studio 10.0\vc\include\immintrin.h + + +1251642866 c:\program files (x86)\microsoft visual studio 10.0\vc\include\wmmintrin.h + + +1251642866 c:\program files (x86)\microsoft visual studio 10.0\vc\include\nmmintrin.h + + +1251642866 c:\program files (x86)\microsoft visual studio 10.0\vc\include\smmintrin.h + + +1251642866 c:\program files (x86)\microsoft visual studio 10.0\vc\include\tmmintrin.h + + +1251642866 c:\program files (x86)\microsoft visual studio 10.0\vc\include\pmmintrin.h + + +1251642866 c:\program files (x86)\microsoft visual studio 10.0\vc\include\emmintrin.h + + +1251642866 c:\program files (x86)\microsoft visual studio 10.0\vc\include\xmmintrin.h + + "xmm_func.h" + + +1251642866 c:\program files (x86)\microsoft visual studio 10.0\vc\include\mmintrin.h + + +1251642866 c:\program files (x86)\microsoft visual studio 10.0\vc\include\mm3dnow.h + + + + +1258271576 c:\program files (x86)\microsoft visual studio 10.0\vc\include\vector + + + + +1254299028 c:\program files (x86)\microsoft visual studio 10.0\vc\include\map + + +1258271576 c:\program files (x86)\microsoft visual studio 10.0\vc\include\xtree + + + + From e18dddf3abc33e23e43d8fee2ff9916f108a12da Mon Sep 17 00:00:00 2001 From: kaltenbe Date: Tue, 16 Feb 2016 16:23:23 +0100 Subject: [PATCH 234/263] added SeDoRa eNodeB Configuration files --- .../CONF/enb.band13.tm1.50PRB.sedora.conf | 171 ++++++++++++++++++ .../CONF/enb.band7.tm1.50PRB.sedora.conf | 171 ++++++++++++++++++ .../CONF/enb.band7.tm1.sedora.conf | 171 ++++++++++++++++++ 3 files changed, 513 insertions(+) create mode 100644 targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band13.tm1.50PRB.sedora.conf create mode 100644 targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.sedora.conf create mode 100644 targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.sedora.conf diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band13.tm1.50PRB.sedora.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band13.tm1.50PRB.sedora.conf new file mode 100644 index 0000000000..2d0b63e4b0 --- /dev/null +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band13.tm1.50PRB.sedora.conf @@ -0,0 +1,171 @@ +Active_eNBs = ( "eNB_Eurecom_LTEBox"); +# Asn1_verbosity, choice in: none, info, annoying +Asn1_verbosity = "none"; + +eNBs = +( + { + ////////// Identification parameters: + eNB_ID = 0xe00; + + cell_type = "CELL_MACRO_ENB"; + + eNB_name = "eNB_Eurecom_LTEBox"; + + // Tracking area code, 0x0000 and 0xfffe are reserved values + tracking_area_code = "1"; + + mobile_country_code = "208"; + + mobile_network_code = "93"; + + ////////// Physical parameters: + + component_carriers = ( + { + frame_type = "FDD"; + tdd_config = 3; + tdd_config_s = 0; + prefix_type = "NORMAL"; + eutra_band = 7; + downlink_frequency = 751000000L; + uplink_frequency_offset = 30000000; + Nid_cell = 0; + N_RB_DL = 50; + Nid_cell_mbsfn = 0; + nb_antennas_tx = 1; + nb_antennas_rx = 1; + tx_gain = 60; + rx_gain = 111; + prach_root = 0; + prach_config_index = 0; + prach_high_speed = "DISABLE"; + prach_zero_correlation = 1; + prach_freq_offset = 2; + pucch_delta_shift = 1; + pucch_nRB_CQI = 1; + pucch_nCS_AN = 0; + pucch_n1_AN = 32; + pdsch_referenceSignalPower = -29; + pdsch_p_b = 0; + pusch_n_SB = 1; + pusch_enable64QAM = "DISABLE"; + pusch_hoppingMode = "interSubFrame"; + pusch_hoppingOffset = 0; + pusch_groupHoppingEnabled = "ENABLE"; + pusch_groupAssignment = 0; + pusch_sequenceHoppingEnabled = "DISABLE"; + pusch_nDMRS1 = 1; + phich_duration = "NORMAL"; + phich_resource = "ONESIXTH"; + srs_enable = "DISABLE"; + /* srs_BandwidthConfig =; + srs_SubframeConfig =; + srs_ackNackST =; + srs_MaxUpPts =;*/ + + pusch_p0_Nominal = -85; + pusch_alpha = "AL1"; + pucch_p0_Nominal = -96; + msg3_delta_Preamble = 6; + pucch_deltaF_Format1 = "deltaF2"; + pucch_deltaF_Format1b = "deltaF3"; + pucch_deltaF_Format2 = "deltaF0"; + pucch_deltaF_Format2a = "deltaF0"; + pucch_deltaF_Format2b = "deltaF0"; + + rach_numberOfRA_Preambles = 64; + rach_preamblesGroupAConfig = "DISABLE"; +/* + rach_sizeOfRA_PreamblesGroupA = ; + rach_messageSizeGroupA = ; + rach_messagePowerOffsetGroupB = ; +*/ + rach_powerRampingStep = 4; + rach_preambleInitialReceivedTargetPower = -100; + rach_preambleTransMax = 10; + rach_raResponseWindowSize = 10; + rach_macContentionResolutionTimer = 48; + rach_maxHARQ_Msg3Tx = 4; + + pcch_default_PagingCycle = 128; + pcch_nB = "oneT"; + bcch_modificationPeriodCoeff = 2; + ue_TimersAndConstants_t300 = 1000; + ue_TimersAndConstants_t301 = 1000; + ue_TimersAndConstants_t310 = 1000; + ue_TimersAndConstants_t311 = 10000; + ue_TimersAndConstants_n310 = 20; + ue_TimersAndConstants_n311 = 1; + + } + ); + + + srb1_parameters : + { + # timer_poll_retransmit = (ms) [5, 10, 15, 20,... 250, 300, 350, ... 500] + timer_poll_retransmit = 80; + + # timer_reordering = (ms) [0,5, ... 100, 110, 120, ... ,200] + timer_reordering = 35; + + # timer_reordering = (ms) [0,5, ... 250, 300, 350, ... ,500] + timer_status_prohibit = 0; + + # poll_pdu = [4, 8, 16, 32 , 64, 128, 256, infinity(>10000)] + poll_pdu = 4; + + # poll_byte = (kB) [25,50,75,100,125,250,375,500,750,1000,1250,1500,2000,3000,infinity(>10000)] + poll_byte = 99999; + + # max_retx_threshold = [1, 2, 3, 4 , 6, 8, 16, 32] + max_retx_threshold = 4; + } + + # ------- SCTP definitions + SCTP : + { + # Number of streams to use in input/output + SCTP_INSTREAMS = 2; + SCTP_OUTSTREAMS = 2; + }; + + ////////// MME parameters: + mme_ip_address = ( { ipv4 = "192.168.12.11"; + ipv6 = "192:168:30::17"; + active = "yes"; + preference = "ipv4"; + } + ); + + NETWORK_INTERFACES : + { + ENB_INTERFACE_NAME_FOR_S1_MME = "eth0"; + ENB_IPV4_ADDRESS_FOR_S1_MME = "192.168.12.215/24"; + + ENB_INTERFACE_NAME_FOR_S1U = "eth0"; + ENB_IPV4_ADDRESS_FOR_S1U = "192.168.12.215/24"; + ENB_PORT_FOR_S1U = 2152; # Spec 2152 + }; + + log_config : + { + global_log_level ="info"; + global_log_verbosity ="medium"; + hw_log_level ="info"; + hw_log_verbosity ="medium"; + phy_log_level ="info"; + phy_log_verbosity ="medium"; + mac_log_level ="info"; + mac_log_verbosity ="high"; + rlc_log_level ="info"; + rlc_log_verbosity ="medium"; + pdcp_log_level ="info"; + pdcp_log_verbosity ="medium"; + rrc_log_level ="info"; + rrc_log_verbosity ="medium"; + }; + + } +); diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.sedora.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.sedora.conf new file mode 100644 index 0000000000..8a5f33af4b --- /dev/null +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.sedora.conf @@ -0,0 +1,171 @@ +Active_eNBs = ( "eNB_Eurecom_LTEBox"); +# Asn1_verbosity, choice in: none, info, annoying +Asn1_verbosity = "none"; + +eNBs = +( + { + ////////// Identification parameters: + eNB_ID = 0xe00; + + cell_type = "CELL_MACRO_ENB"; + + eNB_name = "eNB_Eurecom_LTEBox"; + + // Tracking area code, 0x0000 and 0xfffe are reserved values + tracking_area_code = "1"; + + mobile_country_code = "208"; + + mobile_network_code = "93"; + + ////////// Physical parameters: + + component_carriers = ( + { + frame_type = "FDD"; + tdd_config = 3; + tdd_config_s = 0; + prefix_type = "NORMAL"; + eutra_band = 7; + downlink_frequency = 2660000000L; + uplink_frequency_offset = -120000000; + Nid_cell = 0; + N_RB_DL = 50; + Nid_cell_mbsfn = 0; + nb_antennas_tx = 1; + nb_antennas_rx = 1; + tx_gain = 60; + rx_gain = 111; + prach_root = 0; + prach_config_index = 0; + prach_high_speed = "DISABLE"; + prach_zero_correlation = 1; + prach_freq_offset = 2; + pucch_delta_shift = 1; + pucch_nRB_CQI = 1; + pucch_nCS_AN = 0; + pucch_n1_AN = 32; + pdsch_referenceSignalPower = -29; + pdsch_p_b = 0; + pusch_n_SB = 1; + pusch_enable64QAM = "DISABLE"; + pusch_hoppingMode = "interSubFrame"; + pusch_hoppingOffset = 0; + pusch_groupHoppingEnabled = "ENABLE"; + pusch_groupAssignment = 0; + pusch_sequenceHoppingEnabled = "DISABLE"; + pusch_nDMRS1 = 1; + phich_duration = "NORMAL"; + phich_resource = "ONESIXTH"; + srs_enable = "DISABLE"; + /* srs_BandwidthConfig =; + srs_SubframeConfig =; + srs_ackNackST =; + srs_MaxUpPts =;*/ + + pusch_p0_Nominal = -85; + pusch_alpha = "AL1"; + pucch_p0_Nominal = -96; + msg3_delta_Preamble = 6; + pucch_deltaF_Format1 = "deltaF2"; + pucch_deltaF_Format1b = "deltaF3"; + pucch_deltaF_Format2 = "deltaF0"; + pucch_deltaF_Format2a = "deltaF0"; + pucch_deltaF_Format2b = "deltaF0"; + + rach_numberOfRA_Preambles = 64; + rach_preamblesGroupAConfig = "DISABLE"; +/* + rach_sizeOfRA_PreamblesGroupA = ; + rach_messageSizeGroupA = ; + rach_messagePowerOffsetGroupB = ; +*/ + rach_powerRampingStep = 4; + rach_preambleInitialReceivedTargetPower = -100; + rach_preambleTransMax = 10; + rach_raResponseWindowSize = 10; + rach_macContentionResolutionTimer = 48; + rach_maxHARQ_Msg3Tx = 4; + + pcch_default_PagingCycle = 128; + pcch_nB = "oneT"; + bcch_modificationPeriodCoeff = 2; + ue_TimersAndConstants_t300 = 1000; + ue_TimersAndConstants_t301 = 1000; + ue_TimersAndConstants_t310 = 1000; + ue_TimersAndConstants_t311 = 10000; + ue_TimersAndConstants_n310 = 20; + ue_TimersAndConstants_n311 = 1; + + } + ); + + + srb1_parameters : + { + # timer_poll_retransmit = (ms) [5, 10, 15, 20,... 250, 300, 350, ... 500] + timer_poll_retransmit = 80; + + # timer_reordering = (ms) [0,5, ... 100, 110, 120, ... ,200] + timer_reordering = 35; + + # timer_reordering = (ms) [0,5, ... 250, 300, 350, ... ,500] + timer_status_prohibit = 0; + + # poll_pdu = [4, 8, 16, 32 , 64, 128, 256, infinity(>10000)] + poll_pdu = 4; + + # poll_byte = (kB) [25,50,75,100,125,250,375,500,750,1000,1250,1500,2000,3000,infinity(>10000)] + poll_byte = 99999; + + # max_retx_threshold = [1, 2, 3, 4 , 6, 8, 16, 32] + max_retx_threshold = 4; + } + + # ------- SCTP definitions + SCTP : + { + # Number of streams to use in input/output + SCTP_INSTREAMS = 2; + SCTP_OUTSTREAMS = 2; + }; + + ////////// MME parameters: + mme_ip_address = ( { ipv4 = "192.168.12.11"; + ipv6 = "192:168:30::17"; + active = "yes"; + preference = "ipv4"; + } + ); + + NETWORK_INTERFACES : + { + ENB_INTERFACE_NAME_FOR_S1_MME = "eth0"; + ENB_IPV4_ADDRESS_FOR_S1_MME = "192.168.12.215/24"; + + ENB_INTERFACE_NAME_FOR_S1U = "eth0"; + ENB_IPV4_ADDRESS_FOR_S1U = "192.168.12.215/24"; + ENB_PORT_FOR_S1U = 2152; # Spec 2152 + }; + + log_config : + { + global_log_level ="info"; + global_log_verbosity ="medium"; + hw_log_level ="info"; + hw_log_verbosity ="medium"; + phy_log_level ="info"; + phy_log_verbosity ="medium"; + mac_log_level ="info"; + mac_log_verbosity ="high"; + rlc_log_level ="info"; + rlc_log_verbosity ="medium"; + pdcp_log_level ="info"; + pdcp_log_verbosity ="medium"; + rrc_log_level ="info"; + rrc_log_verbosity ="medium"; + }; + + } +); diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.sedora.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.sedora.conf new file mode 100644 index 0000000000..70fcc2e3f4 --- /dev/null +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.sedora.conf @@ -0,0 +1,171 @@ +Active_eNBs = ( "eNB_Eurecom_LTEBox"); +# Asn1_verbosity, choice in: none, info, annoying +Asn1_verbosity = "none"; + +eNBs = +( + { + ////////// Identification parameters: + eNB_ID = 0xe00; + + cell_type = "CELL_MACRO_ENB"; + + eNB_name = "eNB_Eurecom_LTEBox"; + + // Tracking area code, 0x0000 and 0xfffe are reserved values + tracking_area_code = "1"; + + mobile_country_code = "208"; + + mobile_network_code = "93"; + + ////////// Physical parameters: + + component_carriers = ( + { + frame_type = "FDD"; + tdd_config = 3; + tdd_config_s = 0; + prefix_type = "NORMAL"; + eutra_band = 7; + downlink_frequency = 2660000000L; + uplink_frequency_offset = -120000000; + Nid_cell = 0; + N_RB_DL = 25; + Nid_cell_mbsfn = 0; + nb_antennas_tx = 1; + nb_antennas_rx = 1; + tx_gain = 60; + rx_gain = 111; + prach_root = 0; + prach_config_index = 0; + prach_high_speed = "DISABLE"; + prach_zero_correlation = 1; + prach_freq_offset = 2; + pucch_delta_shift = 1; + pucch_nRB_CQI = 1; + pucch_nCS_AN = 0; + pucch_n1_AN = 32; + pdsch_referenceSignalPower = -29; + pdsch_p_b = 0; + pusch_n_SB = 1; + pusch_enable64QAM = "DISABLE"; + pusch_hoppingMode = "interSubFrame"; + pusch_hoppingOffset = 0; + pusch_groupHoppingEnabled = "ENABLE"; + pusch_groupAssignment = 0; + pusch_sequenceHoppingEnabled = "DISABLE"; + pusch_nDMRS1 = 1; + phich_duration = "NORMAL"; + phich_resource = "ONESIXTH"; + srs_enable = "DISABLE"; + /* srs_BandwidthConfig =; + srs_SubframeConfig =; + srs_ackNackST =; + srs_MaxUpPts =;*/ + + pusch_p0_Nominal = -85; + pusch_alpha = "AL1"; + pucch_p0_Nominal = -96; + msg3_delta_Preamble = 6; + pucch_deltaF_Format1 = "deltaF2"; + pucch_deltaF_Format1b = "deltaF3"; + pucch_deltaF_Format2 = "deltaF0"; + pucch_deltaF_Format2a = "deltaF0"; + pucch_deltaF_Format2b = "deltaF0"; + + rach_numberOfRA_Preambles = 64; + rach_preamblesGroupAConfig = "DISABLE"; +/* + rach_sizeOfRA_PreamblesGroupA = ; + rach_messageSizeGroupA = ; + rach_messagePowerOffsetGroupB = ; +*/ + rach_powerRampingStep = 4; + rach_preambleInitialReceivedTargetPower = -100; + rach_preambleTransMax = 10; + rach_raResponseWindowSize = 10; + rach_macContentionResolutionTimer = 48; + rach_maxHARQ_Msg3Tx = 4; + + pcch_default_PagingCycle = 128; + pcch_nB = "oneT"; + bcch_modificationPeriodCoeff = 2; + ue_TimersAndConstants_t300 = 1000; + ue_TimersAndConstants_t301 = 1000; + ue_TimersAndConstants_t310 = 1000; + ue_TimersAndConstants_t311 = 10000; + ue_TimersAndConstants_n310 = 20; + ue_TimersAndConstants_n311 = 1; + + } + ); + + + srb1_parameters : + { + # timer_poll_retransmit = (ms) [5, 10, 15, 20,... 250, 300, 350, ... 500] + timer_poll_retransmit = 80; + + # timer_reordering = (ms) [0,5, ... 100, 110, 120, ... ,200] + timer_reordering = 35; + + # timer_reordering = (ms) [0,5, ... 250, 300, 350, ... ,500] + timer_status_prohibit = 0; + + # poll_pdu = [4, 8, 16, 32 , 64, 128, 256, infinity(>10000)] + poll_pdu = 4; + + # poll_byte = (kB) [25,50,75,100,125,250,375,500,750,1000,1250,1500,2000,3000,infinity(>10000)] + poll_byte = 99999; + + # max_retx_threshold = [1, 2, 3, 4 , 6, 8, 16, 32] + max_retx_threshold = 4; + } + + # ------- SCTP definitions + SCTP : + { + # Number of streams to use in input/output + SCTP_INSTREAMS = 2; + SCTP_OUTSTREAMS = 2; + }; + + ////////// MME parameters: + mme_ip_address = ( { ipv4 = "192.168.12.11"; + ipv6 = "192:168:30::17"; + active = "yes"; + preference = "ipv4"; + } + ); + + NETWORK_INTERFACES : + { + ENB_INTERFACE_NAME_FOR_S1_MME = "eth0"; + ENB_IPV4_ADDRESS_FOR_S1_MME = "192.168.12.215/24"; + + ENB_INTERFACE_NAME_FOR_S1U = "eth0"; + ENB_IPV4_ADDRESS_FOR_S1U = "192.168.12.215/24"; + ENB_PORT_FOR_S1U = 2152; # Spec 2152 + }; + + log_config : + { + global_log_level ="info"; + global_log_verbosity ="medium"; + hw_log_level ="info"; + hw_log_verbosity ="medium"; + phy_log_level ="info"; + phy_log_verbosity ="medium"; + mac_log_level ="info"; + mac_log_verbosity ="high"; + rlc_log_level ="info"; + rlc_log_verbosity ="medium"; + pdcp_log_level ="info"; + pdcp_log_verbosity ="medium"; + rrc_log_level ="info"; + rrc_log_verbosity ="medium"; + }; + + } +); From e697b22253821c0ec6b72bc8822c215754b1aac0 Mon Sep 17 00:00:00 2001 From: Aikaterini Trilyraki Date: Tue, 16 Feb 2016 16:29:44 +0100 Subject: [PATCH 235/263] Delete .#lte-softmodem.c --- targets/RT/USER/.#lte-softmodem.c | 1 - 1 file changed, 1 deletion(-) delete mode 120000 targets/RT/USER/.#lte-softmodem.c diff --git a/targets/RT/USER/.#lte-softmodem.c b/targets/RT/USER/.#lte-softmodem.c deleted file mode 120000 index dbbd658659..0000000000 --- a/targets/RT/USER/.#lte-softmodem.c +++ /dev/null @@ -1 +0,0 @@ -guepe@guepe.25164:1451994252 \ No newline at end of file From f722b2971dbfb155b14ef1ab50061edf3713cafa Mon Sep 17 00:00:00 2001 From: Florian Kaltenberger Date: Tue, 16 Feb 2016 16:53:07 +0100 Subject: [PATCH 236/263] including LMSSDR CMakeList.txt into main CMakeList.txt --- cmake_targets/CMakeLists.txt | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/cmake_targets/CMakeLists.txt b/cmake_targets/CMakeLists.txt index ee28608504..b5c3cffce6 100644 --- a/cmake_targets/CMakeLists.txt +++ b/cmake_targets/CMakeLists.txt @@ -42,6 +42,10 @@ set (OPENAIR_BIN_DIR ${CMAKE_CURRENT_BINARY_DIR}${CMAKE_FILES_DIRECTORY}) project (OpenAirInterface) +add_subdirectory(${OPENAIR_TARGETS}/ARCH/LMSSDR/USERSPACE/LIB/lms7002m lms7002m) +add_subdirectory(${OPENAIR_TARGETS}/ARCH/LMSSDR/USERSPACE/LIB/lmsSDR lmsSDR) +add_subdirectory(${OPENAIR_TARGETS}/ARCH/LMSSDR/USERSPACE/LIB/Si5351C Si5351C) + ########################################### # macros to define options as there is numerous options in oai ################################################ @@ -498,9 +502,9 @@ elseif (${RF_BOARD} STREQUAL "OAI_LMSSDR") include_directories("${OPENAIR_TARGETS}/ARCH/LMSSDR/USERSPACE/LIB/Si5351C") include_directories("${OPENAIR_TARGETS}/ARCH/LMSSDR/USERSPACE/LIB/lmsSDR/LMS_StreamBoard") LINK_DIRECTORIES("/usr/lib/x86_64-linux-gnu") - LINK_DIRECTORIES("${OPENAIR_TARGETS}/ARCH/LMSSDR/USERSPACE/LIB/lmsSDR/build") - LINK_DIRECTORIES("${OPENAIR_TARGETS}/ARCH/LMSSDR/USERSPACE/LIB/lms7002m/build") - LINK_DIRECTORIES("${OPENAIR_TARGETS}/ARCH/LMSSDR/USERSPACE/LIB/Si5351C/build") + LINK_DIRECTORIES("${CMAKE_CURRENT_BINARY_DIR}/lmsSDR") + LINK_DIRECTORIES("${CMAKE_CURRENT_BINARY_DIR}/lms7002m") + LINK_DIRECTORIES("${CMAKE_CURRENT_BINARY_DIR}/Si5351C") set(HW_SOURCE ${HW_SOURCE} ${OPENAIR_TARGETS}/ARCH/LMSSDR/USERSPACE/LIB/lms_lib.cpp) set(LOWLATENCY False) set(option_HW_lib "-lLMS_SDR -lLMS7002M -lSi5351C -rdynamic -ldl") @@ -1558,7 +1562,10 @@ target_link_libraries (lte-softmodem-nos1 ${LIBXML2_LIBRARIES}) target_link_libraries (lte-softmodem-nos1 pthread m ${CONFIG_LIBRARIES} rt crypt ${CRYPTO_LIBRARIES} ${OPENSSL_LIBRARIES} ${NETTLE_LIBRARIES} ${option_HW_lib} ${option_TP_lib} ${XFORMS_LIBRARIES} ) target_link_libraries (lte-softmodem-nos1 ${LIBBOOST_LIBRARIES}) - +if (${RF_BOARD} STREQUAL "OAI_LMSSDR") + add_dependencies(lte-softmodem LMS7002M LMS_SDR Si5351C) + add_dependencies(lte-softmodem-nos1 LMS7002M LMS_SDR Si5351C) +endif (${RF_BOARD} STREQUAL "OAI_LMSSDR") # rrh ################################ From 4079a46cb8db9ce0919d3f308effec2ebe173ff8 Mon Sep 17 00:00:00 2001 From: Aikaterini Date: Tue, 16 Feb 2016 17:33:15 +0100 Subject: [PATCH 237/263] config files for RRH SoDERA --- .../CONF/enb.band7.tm1.50PRB.rrh.sodera.conf | 190 +++++++++++++++++ .../CONF/enb.band7.tm1.rrh.sodera.conf | 192 ++++++++++++++++++ 2 files changed, 382 insertions(+) create mode 100644 targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.rrh.sodera.conf create mode 100644 targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.rrh.sodera.conf diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.rrh.sodera.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.rrh.sodera.conf new file mode 100644 index 0000000000..c3985c9dce --- /dev/null +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.rrh.sodera.conf @@ -0,0 +1,190 @@ +Active_eNBs = ( "eNB_Eurecom_LTEBox"); +# Asn1_verbosity, choice in: none, info, annoying +Asn1_verbosity = "none"; + +eNBs = +( + { + ////////// Identification parameters: + eNB_ID = 0xe00; + + cell_type = "CELL_MACRO_ENB"; + + eNB_name = "eNB_Eurecom_LTEBox"; + + // Tracking area code, 0x0000 and 0xfffe are reserved values + tracking_area_code = "1"; + + mobile_country_code = "208"; + + mobile_network_code = "93"; + + ////////// Physical parameters: + + component_carriers = ( + { + frame_type = "FDD"; + tdd_config = 3; + tdd_config_s = 0; + prefix_type = "NORMAL"; + eutra_band = 7; + downlink_frequency = 2660000000L; + uplink_frequency_offset = -120000000; + Nid_cell = 0; + N_RB_DL = 50; + Nid_cell_mbsfn = 0; + nb_antennas_tx = 1; + nb_antennas_rx = 1; + tx_gain = 60; + rx_gain = 111; + prach_root = 0; + prach_config_index = 0; + prach_high_speed = "DISABLE"; + prach_zero_correlation = 1; + prach_freq_offset = 2; + pucch_delta_shift = 1; + pucch_nRB_CQI = 1; + pucch_nCS_AN = 0; + pucch_n1_AN = 32; + pdsch_referenceSignalPower = -29; + pdsch_p_b = 0; + pusch_n_SB = 1; + pusch_enable64QAM = "DISABLE"; + pusch_hoppingMode = "interSubFrame"; + pusch_hoppingOffset = 0; + pusch_groupHoppingEnabled = "ENABLE"; + pusch_groupAssignment = 0; + pusch_sequenceHoppingEnabled = "DISABLE"; + pusch_nDMRS1 = 1; + phich_duration = "NORMAL"; + phich_resource = "ONESIXTH"; + srs_enable = "DISABLE"; + /* srs_BandwidthConfig =; + srs_SubframeConfig =; + srs_ackNackST =; + srs_MaxUpPts =;*/ + + pusch_p0_Nominal = -85; + pusch_alpha = "AL1"; + pucch_p0_Nominal = -96; + msg3_delta_Preamble = 6; + pucch_deltaF_Format1 = "deltaF2"; + pucch_deltaF_Format1b = "deltaF3"; + pucch_deltaF_Format2 = "deltaF0"; + pucch_deltaF_Format2a = "deltaF0"; + pucch_deltaF_Format2b = "deltaF0"; + + rach_numberOfRA_Preambles = 64; + rach_preamblesGroupAConfig = "DISABLE"; +/* + rach_sizeOfRA_PreamblesGroupA = ; + rach_messageSizeGroupA = ; + rach_messagePowerOffsetGroupB = ; +*/ + rach_powerRampingStep = 4; + rach_preambleInitialReceivedTargetPower = -100; + rach_preambleTransMax = 10; + rach_raResponseWindowSize = 10; + rach_macContentionResolutionTimer = 48; + rach_maxHARQ_Msg3Tx = 4; + + pcch_default_PagingCycle = 128; + pcch_nB = "oneT"; + bcch_modificationPeriodCoeff = 2; + ue_TimersAndConstants_t300 = 1000; + ue_TimersAndConstants_t301 = 1000; + ue_TimersAndConstants_t310 = 1000; + ue_TimersAndConstants_t311 = 10000; + ue_TimersAndConstants_n310 = 20; + ue_TimersAndConstants_n311 = 1; + + } + ); + + + srb1_parameters : + { + # timer_poll_retransmit = (ms) [5, 10, 15, 20,... 250, 300, 350, ... 500] + timer_poll_retransmit = 80; + + # timer_reordering = (ms) [0,5, ... 100, 110, 120, ... ,200] + timer_reordering = 35; + + # timer_reordering = (ms) [0,5, ... 250, 300, 350, ... ,500] + timer_status_prohibit = 0; + + # poll_pdu = [4, 8, 16, 32 , 64, 128, 256, infinity(>10000)] + poll_pdu = 4; + + # poll_byte = (kB) [25,50,75,100,125,250,375,500,750,1000,1250,1500,2000,3000,infinity(>10000)] + poll_byte = 99999; + + # max_retx_threshold = [1, 2, 3, 4 , 6, 8, 16, 32] + max_retx_threshold = 4; + } + + # ------- SCTP definitions + SCTP : + { + # Number of streams to use in input/output + SCTP_INSTREAMS = 2; + SCTP_OUTSTREAMS = 2; + }; + + ////////// MME parameters: + mme_ip_address = ( { ipv4 = "192.168.12.11"; + ipv6 = "192:168:30::17"; + active = "yes"; + preference = "ipv4"; + } + ); + + +rrh_gw_config = ( + { + local_if_name = "eth0"; + remote_address = "169.254.8.28"; + #remote_address = "127.0.0.1"; + #remote_address = "74:d4:35:cc:88:45"; + local_address = "169.254.7.91"; + #local_address = "127.0.0.1"; + #local_address = "d4:be:d9:22:0a:ac"; + #for raw option local port must be the same to remote + local_port = 50000; + remote_port = 50000; + active = "yes"; + preference = "raw"; + +} +); + + NETWORK_INTERFACES : + { + ENB_INTERFACE_NAME_FOR_S1_MME = "eth0"; + ENB_IPV4_ADDRESS_FOR_S1_MME = "192.168.12.111/24"; + + ENB_INTERFACE_NAME_FOR_S1U = "eth0"; + ENB_IPV4_ADDRESS_FOR_S1U = "192.168.12.111/24"; + ENB_PORT_FOR_S1U = 2152; # Spec 2152 + }; + + log_config : + { + global_log_level ="info"; + global_log_verbosity ="medium"; + hw_log_level ="info"; + hw_log_verbosity ="medium"; + phy_log_level ="info"; + phy_log_verbosity ="medium"; + mac_log_level ="info"; + mac_log_verbosity ="high"; + rlc_log_level ="info"; + rlc_log_verbosity ="medium"; + pdcp_log_level ="info"; + pdcp_log_verbosity ="medium"; + rrc_log_level ="info"; + rrc_log_verbosity ="medium"; + }; + + } +); diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.rrh.sodera.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.rrh.sodera.conf new file mode 100644 index 0000000000..2db6eb799b --- /dev/null +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.rrh.sodera.conf @@ -0,0 +1,192 @@ +Active_eNBs = ( "eNB_Eurecom_LTEBox"); +# Asn1_verbosity, choice in: none, info, annoying +Asn1_verbosity = "none"; + +eNBs = +( + { + ////////// Identification parameters: + eNB_ID = 0xe00; + + cell_type = "CELL_MACRO_ENB"; + + eNB_name = "eNB_Eurecom_LTEBox"; + + // Tracking area code, 0x0000 and 0xfffe are reserved values + tracking_area_code = "1"; + + mobile_country_code = "208"; + + mobile_network_code = "92"; + + ////////// Physical parameters: + + component_carriers = ( + { + frame_type = "FDD"; + tdd_config = 3; + tdd_config_s = 0; + prefix_type = "NORMAL"; + eutra_band = 7; + downlink_frequency = 2660000000L; + uplink_frequency_offset = -120000000; + Nid_cell = 0; + N_RB_DL = 25; + Nid_cell_mbsfn = 0; + nb_antennas_tx = 1; + nb_antennas_rx = 1; + tx_gain = 60; + rx_gain = 111; + prach_root = 0; + prach_config_index = 0; + prach_high_speed = "DISABLE"; + prach_zero_correlation = 1; + prach_freq_offset = 2; + pucch_delta_shift = 1; + pucch_nRB_CQI = 1; + pucch_nCS_AN = 0; + pucch_n1_AN = 32; + pdsch_referenceSignalPower = -29; + pdsch_p_b = 0; + pusch_n_SB = 1; + pusch_enable64QAM = "DISABLE"; + pusch_hoppingMode = "interSubFrame"; + pusch_hoppingOffset = 0; + pusch_groupHoppingEnabled = "ENABLE"; + pusch_groupAssignment = 0; + pusch_sequenceHoppingEnabled = "DISABLE"; + pusch_nDMRS1 = 1; + phich_duration = "NORMAL"; + phich_resource = "ONESIXTH"; + srs_enable = "DISABLE"; + /* srs_BandwidthConfig =; + srs_SubframeConfig =; + srs_ackNackST =; + srs_MaxUpPts =;*/ + + pusch_p0_Nominal = -85; + pusch_alpha = "AL1"; + pucch_p0_Nominal = -96; + msg3_delta_Preamble = 6; + pucch_deltaF_Format1 = "deltaF2"; + pucch_deltaF_Format1b = "deltaF3"; + pucch_deltaF_Format2 = "deltaF0"; + pucch_deltaF_Format2a = "deltaF0"; + pucch_deltaF_Format2b = "deltaF0"; + + rach_numberOfRA_Preambles = 64; + rach_preamblesGroupAConfig = "DISABLE"; +/* + rach_sizeOfRA_PreamblesGroupA = ; + rach_messageSizeGroupA = ; + rach_messagePowerOffsetGroupB = ; +*/ + rach_powerRampingStep = 4; + rach_preambleInitialReceivedTargetPower = -100; + rach_preambleTransMax = 10; + rach_raResponseWindowSize = 10; + rach_macContentionResolutionTimer = 48; + rach_maxHARQ_Msg3Tx = 4; + + pcch_default_PagingCycle = 128; + pcch_nB = "oneT"; + bcch_modificationPeriodCoeff = 2; + ue_TimersAndConstants_t300 = 1000; + ue_TimersAndConstants_t301 = 1000; + ue_TimersAndConstants_t310 = 1000; + ue_TimersAndConstants_t311 = 10000; + ue_TimersAndConstants_n310 = 20; + ue_TimersAndConstants_n311 = 1; + + } + ); + + + srb1_parameters : + { + # timer_poll_retransmit = (ms) [5, 10, 15, 20,... 250, 300, 350, ... 500] + timer_poll_retransmit = 80; + + # timer_reordering = (ms) [0,5, ... 100, 110, 120, ... ,200] + timer_reordering = 35; + + # timer_reordering = (ms) [0,5, ... 250, 300, 350, ... ,500] + timer_status_prohibit = 0; + + # poll_pdu = [4, 8, 16, 32 , 64, 128, 256, infinity(>10000)] + poll_pdu = 4; + + # poll_byte = (kB) [25,50,75,100,125,250,375,500,750,1000,1250,1500,2000,3000,infinity(>10000)] + poll_byte = 99999; + + # max_retx_threshold = [1, 2, 3, 4 , 6, 8, 16, 32] + max_retx_threshold = 4; + } + + # ------- SCTP definitions + SCTP : + { + # Number of streams to use in input/output + SCTP_INSTREAMS = 2; + SCTP_OUTSTREAMS = 2; + }; + + ////////// MME parameters: + mme_ip_address = ( { ipv4 = "192.168.12.26"; + ipv6 = "192:168:30::17"; + active = "yes"; + preference = "ipv4"; + } + ); + + + +rrh_gw_config = ( + { + local_if_name = "eth0"; + remote_address = "169.254.8.28"; + #remote_address = "127.0.0.1"; + #remote_address = "74:d4:35:cc:88:45"; + local_address = "169.254.7.91"; + #local_address = "127.0.0.1"; + #local_address = "d4:be:d9:22:0a:ac"; + #for raw option local port must be the same to remote + local_port = 50000; + remote_port = 50000; + active = "yes"; + preference = "raw"; + +} +); + + + NETWORK_INTERFACES : + { + ENB_INTERFACE_NAME_FOR_S1_MME = "eth4"; + ENB_IPV4_ADDRESS_FOR_S1_MME = "192.168.12.111/24"; + + ENB_INTERFACE_NAME_FOR_S1U = "eth4"; + ENB_IPV4_ADDRESS_FOR_S1U = "192.168.12.111/24"; + ENB_PORT_FOR_S1U = 2152; # Spec 2152 + }; + + log_config : + { + global_log_level ="info"; + global_log_verbosity ="medium"; + hw_log_level ="info"; + hw_log_verbosity ="medium"; + phy_log_level ="info"; + phy_log_verbosity ="medium"; + mac_log_level ="info"; + mac_log_verbosity ="high"; + rlc_log_level ="info"; + rlc_log_verbosity ="medium"; + pdcp_log_level ="info"; + pdcp_log_verbosity ="medium"; + rrc_log_level ="info"; + rrc_log_verbosity ="medium"; + }; + + } +); From ff6174aeb140d82ea2a124f3484f6077977466b0 Mon Sep 17 00:00:00 2001 From: Aikaterini Date: Tue, 16 Feb 2016 18:19:39 +0100 Subject: [PATCH 238/263] fix SoDERA RRH config --- cmake_targets/CMakeLists.txt | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/cmake_targets/CMakeLists.txt b/cmake_targets/CMakeLists.txt index b5c3cffce6..7477ef819f 100644 --- a/cmake_targets/CMakeLists.txt +++ b/cmake_targets/CMakeLists.txt @@ -1561,11 +1561,7 @@ target_link_libraries (lte-softmodem-nos1 target_link_libraries (lte-softmodem-nos1 ${LIBXML2_LIBRARIES}) target_link_libraries (lte-softmodem-nos1 pthread m ${CONFIG_LIBRARIES} rt crypt ${CRYPTO_LIBRARIES} ${OPENSSL_LIBRARIES} ${NETTLE_LIBRARIES} ${option_HW_lib} ${option_TP_lib} ${XFORMS_LIBRARIES} ) target_link_libraries (lte-softmodem-nos1 ${LIBBOOST_LIBRARIES}) - -if (${RF_BOARD} STREQUAL "OAI_LMSSDR") - add_dependencies(lte-softmodem LMS7002M LMS_SDR Si5351C) - add_dependencies(lte-softmodem-nos1 LMS7002M LMS_SDR Si5351C) -endif (${RF_BOARD} STREQUAL "OAI_LMSSDR") +target_link_libraries (lte-softmodem-nos1 ${LIB_LMS_LIBRARIES}) # rrh ################################ @@ -1579,7 +1575,6 @@ add_executable(rrh_gw ${HW_SOURCE} ${TRANSPORT_SOURCE} ) -# assert target_include_directories(rrh_gw PRIVATE ${OPENAIR_DIR}/common/utils/itti) target_link_libraries(rrh_gw -Wl,--start-group @@ -1587,12 +1582,21 @@ target_link_libraries(rrh_gw -Wl,--end-group ) target_link_libraries (rrh_gw rt pthread m ) target_link_libraries (rrh_gw ${option_HW_lib} ${option_TP_lib} ${LIBBOOST_LIBRARIES} ) +target_link_libraries (rrh_gw ${LIB_LMS_LIBRARIES}) Message("-- option_HW_lib=${option_HW_lib}") Message("-- HW_SOURCE=${HW_SOURCE}") Message("-- option_TP_lib=${option_TP_lib}") Message("-- TRANSPORT_SOURCE=${TRANSPORT_SOURCE}") +if (${RF_BOARD} STREQUAL "OAI_LMSSDR") + add_dependencies(lte-softmodem LMS7002M LMS_SDR Si5351C) + add_dependencies(lte-softmodem-nos1 LMS7002M LMS_SDR Si5351C) + add_dependencies(rrh_gw LMS7002M LMS_SDR Si5351C) +endif (${RF_BOARD} STREQUAL "OAI_LMSSDR") + + + # USIM process ################# #add_executable(usim From f3c7d753647d5cb91fd1683611e920407dd27dc2 Mon Sep 17 00:00:00 2001 From: Aikaterini Date: Tue, 16 Feb 2016 21:10:24 +0100 Subject: [PATCH 239/263] fix for RRH --- targets/ARCH/LMSSDR/USERSPACE/LIB/lms_lib.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/targets/ARCH/LMSSDR/USERSPACE/LIB/lms_lib.cpp b/targets/ARCH/LMSSDR/USERSPACE/LIB/lms_lib.cpp index 9f7063e51d..e5f69d5577 100644 --- a/targets/ARCH/LMSSDR/USERSPACE/LIB/lms_lib.cpp +++ b/targets/ARCH/LMSSDR/USERSPACE/LIB/lms_lib.cpp @@ -819,7 +819,7 @@ extern "C" { */ int device_init(openair0_device *device, openair0_config_t *openair0_cfg){ - + device->type=LMSSDR_DEV; printf("LMSSDR: Initializing openair0_device for %s ...\n", ((device->host_type == BBU_HOST) ? "BBU": "RRH")); switch ((int)openair0_cfg[0].sample_rate) { From 1de3183dabdff6773c00403a79b5ef12fc125b43 Mon Sep 17 00:00:00 2001 From: Aikaterini Date: Tue, 16 Feb 2016 21:11:52 +0100 Subject: [PATCH 240/263] fix for RRH compilation --- targets/RT/USER/eNB_transport_IQ.c | 10 +++++++--- targets/RT/USER/rrh_gw.c | 15 +++++++++++---- targets/RT/USER/rrh_gw_externs.h | 1 + 3 files changed, 19 insertions(+), 7 deletions(-) diff --git a/targets/RT/USER/eNB_transport_IQ.c b/targets/RT/USER/eNB_transport_IQ.c index 594b075941..acb382386e 100644 --- a/targets/RT/USER/eNB_transport_IQ.c +++ b/targets/RT/USER/eNB_transport_IQ.c @@ -147,18 +147,22 @@ void config_BBU_mod( rrh_module_t *mod_enb, uint8_t RT_flag, uint8_t NRT_flag) { mod_enb->devs->openair0_cfg = mod_enb->eth_dev.openair0_cfg; /* check sanity of configuration parameters and print */ - check_dev_config(mod_enb); - + check_dev_config(mod_enb); + if (rf_config_file[0] == '\0') + mod_enb->devs->openair0_cfg->configFilename = NULL; + else + mod_enb->devs->openair0_cfg->configFilename = rf_config_file; /* initialize and configure the RF device */ if (openair0_device_load(mod_enb->devs, mod_enb->devs->openair0_cfg)<0) { LOG_E(RRH,"Exiting, cannot initialize RF device.\n"); exit(-1); - } else { + } else { if (mod_enb->devs->type != NONE_DEV) { /* start RF device */ if (mod_enb->devs->type == EXMIMO_DEV) { //call start function for exmino } else { + if (mod_enb->devs->trx_start_func(mod_enb->devs)!=0) LOG_E(RRH,"Unable to initiate RF device.\n"); else diff --git a/targets/RT/USER/rrh_gw.c b/targets/RT/USER/rrh_gw.c index 87c4d4d77d..3def754e3d 100644 --- a/targets/RT/USER/rrh_gw.c +++ b/targets/RT/USER/rrh_gw.c @@ -111,8 +111,7 @@ rrh_module_t *ue_array; openair0_vtimestamp hw_counter=0; - - +char rf_config_file[1024]; static void debug_init(void); static void get_options(int argc, char *argv[]); @@ -143,7 +142,7 @@ static int get_address(char* if_name, uint8_t flag); int main(int argc, char **argv) { unsigned int i; - + rf_config_file[0]='\0'; /* parse input arguments */ get_options(argc, argv); /* initialize logger and signal analyzer */ @@ -257,7 +256,7 @@ static void get_options(int argc, char *argv[]) { int opt; - while ((opt = getopt(argc, argv, "xvhlte:n:u:g:r:m:i:")) != -1) { + while ((opt = getopt(argc, argv, "xvhlte:n:u:g:r:m:i:f:")) != -1) { switch (opt) { case 'n': @@ -299,6 +298,14 @@ static void get_options(int argc, char *argv[]) { /*In loopback mode rrh sends back to bbu what it receives*/ loopback_flag=1; break; + case 'f': + if (strlen(optarg)<=1024) + strcpy(rf_config_file,optarg); + else { + printf("Configuration filename is too long\n"); + exit(-1); + } + break; case 't': /* When measurements are enabled statistics related to TX/RX time are printed */ measurements_flag=1; diff --git a/targets/RT/USER/rrh_gw_externs.h b/targets/RT/USER/rrh_gw_externs.h index 8d2d1d7e5e..df59b9b1af 100644 --- a/targets/RT/USER/rrh_gw_externs.h +++ b/targets/RT/USER/rrh_gw_externs.h @@ -39,6 +39,7 @@ #ifndef RRH_GW_EXTERNS_H_ #define RRH_GW_EXTERNS_H_ +extern char rf_config_file[1024]; extern openair0_timestamp timestamp_UE_tx[4] ,timestamp_UE_rx[4] ,timestamp_eNB_rx[4],timestamp_eNB_tx[4]; extern openair0_vtimestamp hw_counter; From 78a47159325187df73579317eff4f51702b871ac Mon Sep 17 00:00:00 2001 From: trilyrak Date: Wed, 17 Feb 2016 13:50:05 +0100 Subject: [PATCH 241/263] updated enb configuration params for rrh --- openair2/ENB_APP/enb_config.c | 80 ++++++++++++++++++++++++++++++----- 1 file changed, 70 insertions(+), 10 deletions(-) diff --git a/openair2/ENB_APP/enb_config.c b/openair2/ENB_APP/enb_config.c index b437c7e264..0f6e6b3706 100755 --- a/openair2/ENB_APP/enb_config.c +++ b/openair2/ENB_APP/enb_config.c @@ -177,7 +177,11 @@ #define ENB_CONFIG_STRING_RRH_GW_LOCAL_PORT "local_port" #define ENB_CONFIG_STRING_RRH_GW_REMOTE_PORT "remote_port" #define ENB_CONFIG_STRING_RRH_GW_ACTIVE "active" -#define ENB_CONFIG_STRING_RRH_GW_PREFERENCE "preference" +#define ENB_CONFIG_STRING_RRH_GW_TRANSPORT_PREFERENCE "tr_preference" +#define ENB_CONFIG_STRING_RRH_GW_RF_TARGET_PREFERENCE "rf_preference" +#define ENB_CONFIG_STRING_RRH_GW_IQ_TXSHIFT "iq_txshift" +#define ENB_CONFIG_STRING_RRH_GW_TX_SAMPLE_ADVANCE "tx_sample_advance" +#define ENB_CONFIG_STRING_RRH_GW_TX_SCHEDULING_ADVANCE "tx_scheduling_advance" #define ENB_CONFIG_STRING_ASN1_VERBOSITY "Asn1_verbosity" #define ENB_CONFIG_STRING_ASN1_VERBOSITY_NONE "none" @@ -291,7 +295,23 @@ static void enb_config_display(void) printf( "\tlocal port : \t%d:\n",enb_properties.properties[i]->rrh_gw_config[j].local_port); printf( "\tremote address : \t%s:\n",enb_properties.properties[i]->rrh_gw_config[j].remote_address); printf( "\tremote port : \t%d:\n",enb_properties.properties[i]->rrh_gw_config[j].remote_port); - printf( "\ttransport : \t%s Ethernet:\n\n",(enb_properties.properties[i]->rrh_gw_config[j].raw == 1)? "RAW" : "UDP"); + printf( "\ttx_scheduling_advance :\t%d:\n",enb_properties.properties[i]->rrh_gw_config[j].tx_scheduling_advance); + printf( "\ttx_sample_advance : \t%d:\n",enb_properties.properties[i]->rrh_gw_config[j].tx_sample_advance); + printf( "\tiq_txshift : \t%d:\n",enb_properties.properties[i]->rrh_gw_config[j].iq_txshift); + printf( "\ttransport : \t%s Ethernet:\n",(enb_properties.properties[i]->rrh_gw_config[j].raw == 1)? "RAW" : "UDP"); + if (enb_properties.properties[i]->rrh_gw_config[j].exmimo == 1) { + printf( "\tRF target : \tEXMIMO:\n\n"); + } else if (enb_properties.properties[i]->rrh_gw_config[j].usrp_b200 == 1) { + printf( "\tRF target : \tUSRP_B200:\n\n"); + } else if (enb_properties.properties[i]->rrh_gw_config[j].usrp_x300 == 1) { + printf( "\tRF target : \tUSRP_X300:\n\n"); + } else if (enb_properties.properties[i]->rrh_gw_config[j].bladerf == 1) { + printf( "\tRF target : \tBLADERF:\n\n"); + } else if (enb_properties.properties[i]->rrh_gw_config[j].lmssdr == 1) { + printf( "\tRF target : \tLMSSDR:\n\n"); + } else { + printf( "\tRF target : \tNONE:\n\n"); + } } } @@ -479,14 +499,14 @@ const Enb_properties_array_t *enb_config_init(char* lib_config_file_name_pP) config_setting_t *setting_rrh_gw = NULL; config_setting_t *setting_enb = NULL; config_setting_t *setting_otg = NULL; - config_setting_t *subsetting_otg = NULL; + config_setting_t *subsetting_otg = NULL; int num_enb_properties = 0; int enb_properties_index = 0; int num_enbs = 0; int num_mme_address = 0; int num_rrh_gw = 0; - int num_otg_elements =0; - int num_component_carriers =0; + int num_otg_elements = 0; + int num_component_carriers = 0; int i = 0; int j = 0; int parse_errors = 0; @@ -588,6 +608,12 @@ const Enb_properties_array_t *enb_config_init(char* lib_config_file_name_pP) char* ipv6 = NULL; char* active = NULL; char* preference = NULL; + + char* tr_preference = NULL; + char* rf_preference = NULL; + libconfig_int tx_scheduling_advance = 0; + libconfig_int tx_sample_advance = 0; + libconfig_int iq_txshift = 0; libconfig_int local_port = 0; libconfig_int remote_port = 0; const char* active_enb[MAX_ENB]; @@ -2180,7 +2206,11 @@ const Enb_properties_array_t *enb_config_init(char* lib_config_file_name_pP) && config_setting_lookup_int(setting_rrh_gw, ENB_CONFIG_STRING_RRH_GW_LOCAL_PORT, &local_port) && config_setting_lookup_int(setting_rrh_gw, ENB_CONFIG_STRING_RRH_GW_REMOTE_PORT, &remote_port) && config_setting_lookup_string(setting_rrh_gw, ENB_CONFIG_STRING_RRH_GW_ACTIVE, (const char **)&active) - && config_setting_lookup_string(setting_rrh_gw, ENB_CONFIG_STRING_RRH_GW_PREFERENCE, (const char **)&preference) + && config_setting_lookup_string(setting_rrh_gw, ENB_CONFIG_STRING_RRH_GW_TRANSPORT_PREFERENCE, (const char **)&tr_preference) + && config_setting_lookup_string(setting_rrh_gw, ENB_CONFIG_STRING_RRH_GW_RF_TARGET_PREFERENCE, (const char **)&rf_preference) + && config_setting_lookup_int(setting_rrh_gw, ENB_CONFIG_STRING_RRH_GW_IQ_TXSHIFT, &iq_txshift) + && config_setting_lookup_int(setting_rrh_gw, ENB_CONFIG_STRING_RRH_GW_TX_SAMPLE_ADVANCE, &tx_sample_advance) + && config_setting_lookup_int(setting_rrh_gw, ENB_CONFIG_STRING_RRH_GW_TX_SCHEDULING_ADVANCE, &tx_scheduling_advance) ) ) { AssertError (0, parse_errors ++, @@ -2194,21 +2224,43 @@ const Enb_properties_array_t *enb_config_init(char* lib_config_file_name_pP) enb_properties.properties[enb_properties_index]->rrh_gw_if_name = strdup(if_name); enb_properties.properties[enb_properties_index]->rrh_gw_config[j].local_address = strdup(ipv4); enb_properties.properties[enb_properties_index]->rrh_gw_config[j].remote_address = strdup(ipv4_remote); - enb_properties.properties[enb_properties_index]->rrh_gw_config[j].local_port= local_port; - enb_properties.properties[enb_properties_index]->rrh_gw_config[j].remote_port= remote_port; + enb_properties.properties[enb_properties_index]->rrh_gw_config[j].local_port = local_port; + enb_properties.properties[enb_properties_index]->rrh_gw_config[j].remote_port = remote_port; + enb_properties.properties[enb_properties_index]->rrh_gw_config[j].iq_txshift = iq_txshift; + enb_properties.properties[enb_properties_index]->rrh_gw_config[j].tx_sample_advance = tx_sample_advance; + enb_properties.properties[enb_properties_index]->rrh_gw_config[j].tx_scheduling_advance= tx_scheduling_advance; if (strcmp(active, "yes") == 0) { enb_properties.properties[enb_properties_index]->rrh_gw_config[j].active = 1; } - if (strcmp(preference, "udp") == 0) { + if (strcmp(tr_preference, "udp") == 0) { enb_properties.properties[enb_properties_index]->rrh_gw_config[j].udp = 1; - } else if (strcmp(preference, "raw") == 0) { + } else if (strcmp(tr_preference, "raw") == 0) { enb_properties.properties[enb_properties_index]->rrh_gw_config[j].raw = 1; } else {//if (strcmp(preference, "no") == 0) enb_properties.properties[enb_properties_index]->rrh_gw_config[j].udp = 1; enb_properties.properties[enb_properties_index]->rrh_gw_config[j].raw = 1; } + + if (strcmp(rf_preference, "exmimo") == 0) { + enb_properties.properties[enb_properties_index]->rrh_gw_config[j].exmimo = 1; + } else if (strcmp(rf_preference, "usrp_b200") == 0) { + enb_properties.properties[enb_properties_index]->rrh_gw_config[j].usrp_b200 = 1; + } else if (strcmp(rf_preference, "usrp_x300") == 0) { + enb_properties.properties[enb_properties_index]->rrh_gw_config[j].usrp_x300 = 1; + } else if (strcmp(rf_preference, "bladerf") == 0) { + enb_properties.properties[enb_properties_index]->rrh_gw_config[j].bladerf = 1; + } else if (strcmp(rf_preference, "bladerf") == 0) { + enb_properties.properties[enb_properties_index]->rrh_gw_config[j].lmssdr = 1; + } else {//if (strcmp(preference, "no") == 0) + enb_properties.properties[enb_properties_index]->rrh_gw_config[j].exmimo = 1; + enb_properties.properties[enb_properties_index]->rrh_gw_config[j].usrp_b200 = 1; + enb_properties.properties[enb_properties_index]->rrh_gw_config[j].usrp_x300 = 1; + enb_properties.properties[enb_properties_index]->rrh_gw_config[j].bladerf = 1; + enb_properties.properties[enb_properties_index]->rrh_gw_config[j].lmssdr = 1; + + } } } else { enb_properties.properties[enb_properties_index]->nb_rrh_gw = 0; @@ -2220,6 +2272,14 @@ const Enb_properties_array_t *enb_config_init(char* lib_config_file_name_pP) enb_properties.properties[enb_properties_index]->rrh_gw_config[j].active = 0; enb_properties.properties[enb_properties_index]->rrh_gw_config[j].udp = 0; enb_properties.properties[enb_properties_index]->rrh_gw_config[j].raw = 0; + enb_properties.properties[enb_properties_index]->rrh_gw_config[j].tx_scheduling_advance = 0; + enb_properties.properties[enb_properties_index]->rrh_gw_config[j].tx_sample_advance = 0; + enb_properties.properties[enb_properties_index]->rrh_gw_config[j].iq_txshift = 0; + enb_properties.properties[enb_properties_index]->rrh_gw_config[j].exmimo = 0; + enb_properties.properties[enb_properties_index]->rrh_gw_config[j].usrp_b200 = 0; + enb_properties.properties[enb_properties_index]->rrh_gw_config[j].usrp_x300 = 0; + enb_properties.properties[enb_properties_index]->rrh_gw_config[j].bladerf = 0; + enb_properties.properties[enb_properties_index]->rrh_gw_config[j].lmssdr = 0; } // SCTP SETTING From 1765790480bd51eda1cd39474b8d432445ca5fb1 Mon Sep 17 00:00:00 2001 From: trilyrak Date: Wed, 17 Feb 2016 13:50:12 +0100 Subject: [PATCH 242/263] updated enb configuration params for rrh --- openair2/ENB_APP/enb_config.h | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/openair2/ENB_APP/enb_config.h b/openair2/ENB_APP/enb_config.h index 9c271ca4f4..422ef67cd3 100755 --- a/openair2/ENB_APP/enb_config.h +++ b/openair2/ENB_APP/enb_config.h @@ -86,7 +86,14 @@ typedef struct rrh_gw_config_s { char *remote_address; uint16_t local_port; uint16_t remote_port; - + int tx_scheduling_advance; + int tx_sample_advance; + int iq_txshift; + unsigned exmimo:1; + unsigned usrp_b200:1; + unsigned usrp_x300:1; + unsigned bladerf:1; + unsigned lmssdr:1; } rrh_gw_config_t; typedef struct Enb_properties_s { From 0da275a81bb1d07733dd96d350de84933d270542 Mon Sep 17 00:00:00 2001 From: trilyrak Date: Wed, 17 Feb 2016 13:51:00 +0100 Subject: [PATCH 243/263] updates for rrh configuration params --- targets/ARCH/COMMON/common_lib.h | 16 ++++++++--- .../ETHERNET/USERSPACE/LIB/ethernet_lib.c | 24 ++++++----------- targets/RT/USER/lte-softmodem.c | 27 ++++++++++++------- 3 files changed, 37 insertions(+), 30 deletions(-) diff --git a/targets/ARCH/COMMON/common_lib.h b/targets/ARCH/COMMON/common_lib.h index 0abe8fd22e..2bd6e4e15d 100644 --- a/targets/ARCH/COMMON/common_lib.h +++ b/targets/ARCH/COMMON/common_lib.h @@ -209,15 +209,23 @@ typedef struct { typedef struct { char *remote_addr; //! remote port number for Ethernet interface - unsigned int remote_port; + uint16_t remote_port; //! local IP/MAC addr for Ethernet interface (eNB/BBU, UE) char *my_addr; //! local port number for Ethernet interface (eNB/BBU, UE) - unsigned int my_port; - //! local port number for Ethernet interface (eNB/BBU, UE) + uint16_t my_port; + //! local Ethernet interface (eNB/BBU, UE) char *local_if_name; - //! local port number for Ethernet interface (eNB/BBU, UE) + //! tx_sample_advance for RF + ETH + uint8_t tx_sample_advance; + //! tx_scheduling_advance for RF + ETH + uint8_t tx_scheduling_advance; + //! iq_txshift for RF + ETH + uint8_t iq_txshift; + //! transport type preference (RAW/UDP) uint8_t transp_preference; + //! radio front end preference (EXMIMO,USRP, BALDERF,LMSSDR) + uint8_t rf_preference; } eth_params_t; diff --git a/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c b/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c index 4fa522f21a..f15f2d98eb 100644 --- a/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c +++ b/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c @@ -344,43 +344,35 @@ int transport_init(openair0_device *device, openair0_config_t *openair0_cfg, eth /* device specific */ openair0_cfg[0].txlaunch_wait = 0;//manage when TX processing is triggered openair0_cfg[0].txlaunch_wait_slotcount = 0; //manage when TX processing is triggered - openair0_cfg[0].iq_txshift = 5;// shift openair0_cfg[0].iq_rxrescale = 15;//rescale iqs + openair0_cfg[0].iq_txshift = eth_params->iq_txshift;// shift + openair0_cfg[0].tx_sample_advance = eth_params->tx_sample_advance; /* RRH does not have any information to make this configuration atm */ if (device->host_type == BBU_HOST) { /*Note scheduling advance values valid only for case 7680000 */ switch ((int)openair0_cfg[0].sample_rate) { case 30720000: - openair0_cfg[0].samples_per_packet = 4096; - openair0_cfg[0].tx_sample_advance = 115; - openair0_cfg[0].tx_scheduling_advance = 11*openair0_cfg[0].samples_per_packet; + openair0_cfg[0].samples_per_packet = 4096; break; case 23040000: openair0_cfg[0].samples_per_packet = 2048; - openair0_cfg[0].tx_sample_advance = 113; - openair0_cfg[0].tx_scheduling_advance = 8*openair0_cfg[0].samples_per_packet; break; case 15360000: - openair0_cfg[0].samples_per_packet = 2048; - openair0_cfg[0].tx_sample_advance = 113; - openair0_cfg[0].tx_scheduling_advance = 9*openair0_cfg[0].samples_per_packet; + openair0_cfg[0].samples_per_packet = 2048; break; case 7680000: - openair0_cfg[0].samples_per_packet = 1024; - openair0_cfg[0].tx_sample_advance = 70; - openair0_cfg[0].tx_scheduling_advance = 9*openair0_cfg[0].samples_per_packet; - break; + openair0_cfg[0].samples_per_packet = 1024; + break; case 1920000: - openair0_cfg[0].samples_per_packet = 256; - openair0_cfg[0].tx_sample_advance = 40; - openair0_cfg[0].tx_scheduling_advance = 8*openair0_cfg[0].samples_per_packet; + openair0_cfg[0].samples_per_packet = 256; break; default: printf("Error: unknown sampling rate %f\n",openair0_cfg[0].sample_rate); exit(-1); break; } + openair0_cfg[0].tx_scheduling_advance = eth_params->tx_scheduling_advance*openair0_cfg[0].samples_per_packet; } device->openair0_cfg=&openair0_cfg[0]; diff --git a/targets/RT/USER/lte-softmodem.c b/targets/RT/USER/lte-softmodem.c index baba632de1..090fd4ecb5 100644 --- a/targets/RT/USER/lte-softmodem.c +++ b/targets/RT/USER/lte-softmodem.c @@ -2443,22 +2443,29 @@ static void get_options (int argc, char **argv) local_remote_radio = BBU_REMOTE_RADIO_HEAD; eth_params = (eth_params_t*)malloc(sizeof(eth_params_t)); memset(eth_params, 0, sizeof(eth_params_t)); - - printf( "\n\tRRH GW %d config for eNB %u:\n\n", j, i); - printf( "\tinterface name : \t%s:\n",enb_properties->properties[i]->rrh_gw_if_name); - printf( "\tlocal address : \t%s:\n",enb_properties->properties[i]->rrh_gw_config[j].local_address); - printf( "\tlocal port : \t%d:\n",enb_properties->properties[i]->rrh_gw_config[j].local_port); - printf( "\tremote address : \t%s:\n",enb_properties->properties[i]->rrh_gw_config[j].remote_address); - printf( "\tremote port : \t%d:\n",enb_properties->properties[i]->rrh_gw_config[j].remote_port); - printf( "\ttransport : \t%s Ethernet:\n\n",(enb_properties->properties[i]->rrh_gw_config[j].raw == 1)? "RAW" : "UDP"); eth_params->local_if_name = enb_properties->properties[i]->rrh_gw_if_name; eth_params->my_addr = enb_properties->properties[i]->rrh_gw_config[j].local_address; eth_params->my_port = enb_properties->properties[i]->rrh_gw_config[j].local_port; eth_params->remote_addr = enb_properties->properties[i]->rrh_gw_config[j].remote_address; eth_params->remote_port = enb_properties->properties[i]->rrh_gw_config[j].remote_port; - eth_params->transp_preference = enb_properties->properties[i]->rrh_gw_config[j].raw; - + eth_params->transp_preference = enb_properties->properties[i]->rrh_gw_config[j].raw; + eth_params->iq_txshift = enb_properties->properties[i]->rrh_gw_config[j].iq_txshift; + eth_params->tx_sample_advance = enb_properties->properties[i]->rrh_gw_config[j].tx_sample_advance; + eth_params->tx_scheduling_advance = enb_properties->properties[i]->rrh_gw_config[j].tx_scheduling_advance; + if (enb_properties->properties[i]->rrh_gw_config[j].exmimo == 1) { + eth_params->rf_preference = EXMIMO_DEV; + } else if (enb_properties->properties[i]->rrh_gw_config[j].usrp_b200 == 1) { + eth_params->rf_preference = USRP_B200_DEV; + } else if (enb_properties->properties[i]->rrh_gw_config[j].usrp_x300 == 1) { + eth_params->rf_preference = USRP_X300_DEV; + } else if (enb_properties->properties[i]->rrh_gw_config[j].bladerf == 1) { + eth_params->rf_preference = BLADERF_DEV; + } else if (enb_properties->properties[i]->rrh_gw_config[j].lmssdr == 1) { + //eth_params->rf_preference = LMSSDR_DEV; + } else { + eth_params->rf_preference = 0; + } } else { local_remote_radio = BBU_LOCAL_RADIO_HEAD; } From 0c104f3313bdcf7a6a86c695b624a5a707a8b578 Mon Sep 17 00:00:00 2001 From: trilyrak Date: Wed, 17 Feb 2016 13:51:24 +0100 Subject: [PATCH 244/263] update config file for rrh --- .../CONF/enb.band7.tm1.rrh.usrpb210.conf | 22 ++++++++++++------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.rrh.usrpb210.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.rrh.usrpb210.conf index e8d49cca18..71d8fe7f34 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.rrh.usrpb210.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.rrh.usrpb210.conf @@ -143,28 +143,34 @@ eNBs = rrh_gw_config = ( { local_if_name = "eth0"; - remote_address = "169.254.8.28"; + remote_address = "169.254.10.158"; + local_address = "169.254.8.15"; #remote_address = "127.0.0.1"; - #remote_address = "74:d4:35:cc:88:45"; - local_address = "169.254.7.91"; + #remote_address = "74:d4:35:cc:88:45"; #local_address = "127.0.0.1"; #local_address = "d4:be:d9:22:0a:ac"; #for raw option local port must be the same to remote local_port = 50001; remote_port = 50000; active = "yes"; - preference = "udp"; + tr_preference = "udp"; + rf_preference = "usrp_b200"; + iq_txshift = 8; + tx_sample_advance = 50; + tx_scheduling_advance = 100; } ); NETWORK_INTERFACES : { - ENB_INTERFACE_NAME_FOR_S1_MME = "eth0"; - ENB_IPV4_ADDRESS_FOR_S1_MME = "192.168.12.242/24"; + ENB_INTERFACE_NAME_FOR_S1_MME = "eth6"; + ENB_IPV4_ADDRESS_FOR_S1_MME = "192.168.12.118/24"; - ENB_INTERFACE_NAME_FOR_S1U = "eth0"; - ENB_IPV4_ADDRESS_FOR_S1U = "192.168.12.242/24"; + ENB_INTERFACE_NAME_FOR_S1U = "eth6"; + + + ENB_IPV4_ADDRESS_FOR_S1U = "192.168.12.118/24"; ENB_PORT_FOR_S1U = 2152; # Spec 2152 }; From 21a62e94b1a8fdbe3532dbdd0310bf604409cde6 Mon Sep 17 00:00:00 2001 From: trilyrak Date: Wed, 17 Feb 2016 14:27:48 +0100 Subject: [PATCH 245/263] update/add config files for rrh + USRP/LMSSDR 5/10MHz --- .../CONF/enb.band7.tm1.50PRB.rrh.lmssdr.conf | 192 ++++++++++++++++++ .../enb.band7.tm1.50PRB.rrh.usrpb210.conf | 192 ++++++++++++++++++ .../CONF/enb.band7.tm1.rrh.lmssdr.conf | 192 ++++++++++++++++++ .../CONF/enb.band7.tm1.rrh.usrpb210.conf | 21 +- 4 files changed, 585 insertions(+), 12 deletions(-) create mode 100644 targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.rrh.lmssdr.conf create mode 100644 targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.rrh.usrpb210.conf create mode 100644 targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.rrh.lmssdr.conf diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.rrh.lmssdr.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.rrh.lmssdr.conf new file mode 100644 index 0000000000..604226c31a --- /dev/null +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.rrh.lmssdr.conf @@ -0,0 +1,192 @@ +Active_eNBs = ( "eNB_Eurecom_LTEBox"); +# Asn1_verbosity, choice in: none, info, annoying +Asn1_verbosity = "none"; + +eNBs = +( + { + ////////// Identification parameters: + eNB_ID = 0xe00; + + cell_type = "CELL_MACRO_ENB"; + + eNB_name = "eNB_Eurecom_LTEBox"; + + // Tracking area code, 0x0000 and 0xfffe are reserved values + tracking_area_code = "1"; + + mobile_country_code = "208"; + + mobile_network_code = "93"; + + ////////// Physical parameters: + + component_carriers = ( + { + frame_type = "FDD"; + tdd_config = 3; + tdd_config_s = 0; + prefix_type = "NORMAL"; + eutra_band = 7; + downlink_frequency = 2660000000L; + uplink_frequency_offset = -120000000; + Nid_cell = 0; + N_RB_DL = 50; + Nid_cell_mbsfn = 0; + nb_antennas_tx = 1; + nb_antennas_rx = 1; + tx_gain = 60; + rx_gain = 111; + prach_root = 0; + prach_config_index = 0; + prach_high_speed = "DISABLE"; + prach_zero_correlation = 1; + prach_freq_offset = 2; + pucch_delta_shift = 1; + pucch_nRB_CQI = 1; + pucch_nCS_AN = 0; + pucch_n1_AN = 32; + pdsch_referenceSignalPower = -29; + pdsch_p_b = 0; + pusch_n_SB = 1; + pusch_enable64QAM = "DISABLE"; + pusch_hoppingMode = "interSubFrame"; + pusch_hoppingOffset = 0; + pusch_groupHoppingEnabled = "ENABLE"; + pusch_groupAssignment = 0; + pusch_sequenceHoppingEnabled = "DISABLE"; + pusch_nDMRS1 = 1; + phich_duration = "NORMAL"; + phich_resource = "ONESIXTH"; + srs_enable = "DISABLE"; + /* srs_BandwidthConfig =; + srs_SubframeConfig =; + srs_ackNackST =; + srs_MaxUpPts =;*/ + + pusch_p0_Nominal = -85; + pusch_alpha = "AL1"; + pucch_p0_Nominal = -96; + msg3_delta_Preamble = 6; + pucch_deltaF_Format1 = "deltaF2"; + pucch_deltaF_Format1b = "deltaF3"; + pucch_deltaF_Format2 = "deltaF0"; + pucch_deltaF_Format2a = "deltaF0"; + pucch_deltaF_Format2b = "deltaF0"; + + rach_numberOfRA_Preambles = 64; + rach_preamblesGroupAConfig = "DISABLE"; +/* + rach_sizeOfRA_PreamblesGroupA = ; + rach_messageSizeGroupA = ; + rach_messagePowerOffsetGroupB = ; +*/ + rach_powerRampingStep = 4; + rach_preambleInitialReceivedTargetPower = -100; + rach_preambleTransMax = 10; + rach_raResponseWindowSize = 10; + rach_macContentionResolutionTimer = 48; + rach_maxHARQ_Msg3Tx = 4; + + pcch_default_PagingCycle = 128; + pcch_nB = "oneT"; + bcch_modificationPeriodCoeff = 2; + ue_TimersAndConstants_t300 = 1000; + ue_TimersAndConstants_t301 = 1000; + ue_TimersAndConstants_t310 = 1000; + ue_TimersAndConstants_t311 = 10000; + ue_TimersAndConstants_n310 = 20; + ue_TimersAndConstants_n311 = 1; + + } + ); + + + srb1_parameters : + { + # timer_poll_retransmit = (ms) [5, 10, 15, 20,... 250, 300, 350, ... 500] + timer_poll_retransmit = 80; + + # timer_reordering = (ms) [0,5, ... 100, 110, 120, ... ,200] + timer_reordering = 35; + + # timer_reordering = (ms) [0,5, ... 250, 300, 350, ... ,500] + timer_status_prohibit = 0; + + # poll_pdu = [4, 8, 16, 32 , 64, 128, 256, infinity(>10000)] + poll_pdu = 4; + + # poll_byte = (kB) [25,50,75,100,125,250,375,500,750,1000,1250,1500,2000,3000,infinity(>10000)] + poll_byte = 99999; + + # max_retx_threshold = [1, 2, 3, 4 , 6, 8, 16, 32] + max_retx_threshold = 4; + } + + # ------- SCTP definitions + SCTP : + { + # Number of streams to use in input/output + SCTP_INSTREAMS = 2; + SCTP_OUTSTREAMS = 2; + }; + + + ////////// MME parameters: + mme_ip_address = ( { ipv4 = "192.168.12.170"; + ipv6 = "192:168:30::17"; + active = "yes"; + preference = "ipv4"; + } + ); + +rrh_gw_config = ( + { + local_if_name = "eth0"; + #remote_address = "169.254.10.158"; + #local_address = "169.254.8.15"; + remote_address = "74:d4:35:cc:88:45"; + local_address = "d4:be:d9:22:0a:ac"; + local_port = 50000; #for raw option local port must be the same to remote + remote_port = 50000; + active = "yes"; + tr_preference = "raw"; + rf_preference = "lmssdr"; + iq_txshift = 0; + tx_sample_advance = 45; + tx_scheduling_advance = 8; + +} +); + + NETWORK_INTERFACES : + { + ENB_INTERFACE_NAME_FOR_S1_MME = "eth6"; + ENB_IPV4_ADDRESS_FOR_S1_MME = "192.168.12.118/24"; + + ENB_INTERFACE_NAME_FOR_S1U = "eth6"; + + + ENB_IPV4_ADDRESS_FOR_S1U = "192.168.12.118/24"; + ENB_PORT_FOR_S1U = 2152; # Spec 2152 + }; + + log_config : + { + global_log_level ="info"; + global_log_verbosity ="medium"; + hw_log_level ="info"; + hw_log_verbosity ="medium"; + phy_log_level ="info"; + phy_log_verbosity ="medium"; + mac_log_level ="info"; + mac_log_verbosity ="high"; + rlc_log_level ="info"; + rlc_log_verbosity ="medium"; + pdcp_log_level ="info"; + pdcp_log_verbosity ="medium"; + rrc_log_level ="info"; + rrc_log_verbosity ="medium"; + }; + } +); diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.rrh.usrpb210.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.rrh.usrpb210.conf new file mode 100644 index 0000000000..abaf8de6ee --- /dev/null +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.rrh.usrpb210.conf @@ -0,0 +1,192 @@ +Active_eNBs = ( "eNB_Eurecom_LTEBox"); +# Asn1_verbosity, choice in: none, info, annoying +Asn1_verbosity = "none"; + +eNBs = +( + { + ////////// Identification parameters: + eNB_ID = 0xe00; + + cell_type = "CELL_MACRO_ENB"; + + eNB_name = "eNB_Eurecom_LTEBox"; + + // Tracking area code, 0x0000 and 0xfffe are reserved values + tracking_area_code = "1"; + + mobile_country_code = "208"; + + mobile_network_code = "92"; + + ////////// Physical parameters: + + component_carriers = ( + { + frame_type = "FDD"; + tdd_config = 3; + tdd_config_s = 0; + prefix_type = "NORMAL"; + eutra_band = 7; + downlink_frequency = 2660000000L; + uplink_frequency_offset = -120000000; + Nid_cell = 0; + N_RB_DL = 25; + Nid_cell_mbsfn = 0; + nb_antennas_tx = 1; + nb_antennas_rx = 1; + tx_gain = 90; + rx_gain = 125; + prach_root = 0; + prach_config_index = 0; + prach_high_speed = "DISABLE"; + prach_zero_correlation = 1; + prach_freq_offset = 2; + pucch_delta_shift = 1; + pucch_nRB_CQI = 1; + pucch_nCS_AN = 0; + pucch_n1_AN = 32; + pdsch_referenceSignalPower = -29; + pdsch_p_b = 0; + pusch_n_SB = 1; + pusch_enable64QAM = "DISABLE"; + pusch_hoppingMode = "interSubFrame"; + pusch_hoppingOffset = 0; + pusch_groupHoppingEnabled = "ENABLE"; + pusch_groupAssignment = 0; + pusch_sequenceHoppingEnabled = "DISABLE"; + pusch_nDMRS1 = 1; + phich_duration = "NORMAL"; + phich_resource = "ONESIXTH"; + srs_enable = "DISABLE"; + /* srs_BandwidthConfig =; + srs_SubframeConfig =; + srs_ackNackST =; + srs_MaxUpPts =;*/ + + pusch_p0_Nominal = -90; + pusch_alpha = "AL1"; + pucch_p0_Nominal = -96; + msg3_delta_Preamble = 6; + pucch_deltaF_Format1 = "deltaF2"; + pucch_deltaF_Format1b = "deltaF3"; + pucch_deltaF_Format2 = "deltaF0"; + pucch_deltaF_Format2a = "deltaF0"; + pucch_deltaF_Format2b = "deltaF0"; + + rach_numberOfRA_Preambles = 64; + rach_preamblesGroupAConfig = "DISABLE"; + /* + rach_sizeOfRA_PreamblesGroupA = ; + rach_messageSizeGroupA = ; + rach_messagePowerOffsetGroupB = ; + */ + rach_powerRampingStep = 4; + rach_preambleInitialReceivedTargetPower = -108; + rach_preambleTransMax = 10; + rach_raResponseWindowSize = 10; + rach_macContentionResolutionTimer = 48; + rach_maxHARQ_Msg3Tx = 4; + + pcch_default_PagingCycle = 128; + pcch_nB = "oneT"; + bcch_modificationPeriodCoeff = 2; + ue_TimersAndConstants_t300 = 1000; + ue_TimersAndConstants_t301 = 1000; + ue_TimersAndConstants_t310 = 1000; + ue_TimersAndConstants_t311 = 10000; + ue_TimersAndConstants_n310 = 20; + ue_TimersAndConstants_n311 = 1; + + } + ); + + + srb1_parameters : + { + # timer_poll_retransmit = (ms) [5, 10, 15, 20,... 250, 300, 350, ... 500] + timer_poll_retransmit = 80; + + # timer_reordering = (ms) [0,5, ... 100, 110, 120, ... ,200] + timer_reordering = 35; + + # timer_reordering = (ms) [0,5, ... 250, 300, 350, ... ,500] + timer_status_prohibit = 0; + + # poll_pdu = [4, 8, 16, 32 , 64, 128, 256, infinity(>10000)] + poll_pdu = 4; + + # poll_byte = (kB) [25,50,75,100,125,250,375,500,750,1000,1250,1500,2000,3000,infinity(>10000)] + poll_byte = 99999; + + # max_retx_threshold = [1, 2, 3, 4 , 6, 8, 16, 32] + max_retx_threshold = 4; + } + + # ------- SCTP definitions + SCTP : + { + # Number of streams to use in input/output + SCTP_INSTREAMS = 2; + SCTP_OUTSTREAMS = 2; + }; + + + ////////// MME parameters: + mme_ip_address = ( { ipv4 = "192.168.12.170"; + ipv6 = "192:168:30::17"; + active = "yes"; + preference = "ipv4"; + } + ); + +rrh_gw_config = ( + { + local_if_name = "eth0"; + #remote_address = "169.254.10.158"; + #local_address = "169.254.8.15"; + remote_address = "74:d4:35:cc:88:45"; + local_address = "d4:be:d9:22:0a:ac"; + local_port = 50000; #for raw option local port must be the same to remote + remote_port = 50000; + active = "yes"; + tr_preference = "raw"; + rf_preference = "usrp_b200"; + iq_txshift = 5; + tx_sample_advance = 113; + tx_scheduling_advance = 8; + +} +); + + NETWORK_INTERFACES : + { + ENB_INTERFACE_NAME_FOR_S1_MME = "eth6"; + ENB_IPV4_ADDRESS_FOR_S1_MME = "192.168.12.118/24"; + + ENB_INTERFACE_NAME_FOR_S1U = "eth6"; + + + ENB_IPV4_ADDRESS_FOR_S1U = "192.168.12.118/24"; + ENB_PORT_FOR_S1U = 2152; # Spec 2152 + }; + + log_config : + { + global_log_level ="info"; + global_log_verbosity ="medium"; + hw_log_level ="info"; + hw_log_verbosity ="medium"; + phy_log_level ="info"; + phy_log_verbosity ="medium"; + mac_log_level ="info"; + mac_log_verbosity ="high"; + rlc_log_level ="info"; + rlc_log_verbosity ="medium"; + pdcp_log_level ="info"; + pdcp_log_verbosity ="medium"; + rrc_log_level ="info"; + rrc_log_verbosity ="medium"; + }; + } +); diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.rrh.lmssdr.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.rrh.lmssdr.conf new file mode 100644 index 0000000000..93afe062e9 --- /dev/null +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.rrh.lmssdr.conf @@ -0,0 +1,192 @@ +Active_eNBs = ( "eNB_Eurecom_LTEBox"); +# Asn1_verbosity, choice in: none, info, annoying +Asn1_verbosity = "none"; + +eNBs = +( + { + ////////// Identification parameters: + eNB_ID = 0xe00; + + cell_type = "CELL_MACRO_ENB"; + + eNB_name = "eNB_Eurecom_LTEBox"; + + // Tracking area code, 0x0000 and 0xfffe are reserved values + tracking_area_code = "1"; + + mobile_country_code = "208"; + + mobile_network_code = "92"; + + ////////// Physical parameters: + + component_carriers = ( + { + frame_type = "FDD"; + tdd_config = 3; + tdd_config_s = 0; + prefix_type = "NORMAL"; + eutra_band = 7; + downlink_frequency = 2660000000L; + uplink_frequency_offset = -120000000; + Nid_cell = 0; + N_RB_DL = 25; + Nid_cell_mbsfn = 0; + nb_antennas_tx = 1; + nb_antennas_rx = 1; + tx_gain = 60; + rx_gain = 111; + prach_root = 0; + prach_config_index = 0; + prach_high_speed = "DISABLE"; + prach_zero_correlation = 1; + prach_freq_offset = 2; + pucch_delta_shift = 1; + pucch_nRB_CQI = 1; + pucch_nCS_AN = 0; + pucch_n1_AN = 32; + pdsch_referenceSignalPower = -29; + pdsch_p_b = 0; + pusch_n_SB = 1; + pusch_enable64QAM = "DISABLE"; + pusch_hoppingMode = "interSubFrame"; + pusch_hoppingOffset = 0; + pusch_groupHoppingEnabled = "ENABLE"; + pusch_groupAssignment = 0; + pusch_sequenceHoppingEnabled = "DISABLE"; + pusch_nDMRS1 = 1; + phich_duration = "NORMAL"; + phich_resource = "ONESIXTH"; + srs_enable = "DISABLE"; + /* srs_BandwidthConfig =; + srs_SubframeConfig =; + srs_ackNackST =; + srs_MaxUpPts =;*/ + + pusch_p0_Nominal = -85; + pusch_alpha = "AL1"; + pucch_p0_Nominal = -96; + msg3_delta_Preamble = 6; + pucch_deltaF_Format1 = "deltaF2"; + pucch_deltaF_Format1b = "deltaF3"; + pucch_deltaF_Format2 = "deltaF0"; + pucch_deltaF_Format2a = "deltaF0"; + pucch_deltaF_Format2b = "deltaF0"; + + rach_numberOfRA_Preambles = 64; + rach_preamblesGroupAConfig = "DISABLE"; +/* + rach_sizeOfRA_PreamblesGroupA = ; + rach_messageSizeGroupA = ; + rach_messagePowerOffsetGroupB = ; +*/ + rach_powerRampingStep = 4; + rach_preambleInitialReceivedTargetPower = -100; + rach_preambleTransMax = 10; + rach_raResponseWindowSize = 10; + rach_macContentionResolutionTimer = 48; + rach_maxHARQ_Msg3Tx = 4; + + pcch_default_PagingCycle = 128; + pcch_nB = "oneT"; + bcch_modificationPeriodCoeff = 2; + ue_TimersAndConstants_t300 = 1000; + ue_TimersAndConstants_t301 = 1000; + ue_TimersAndConstants_t310 = 1000; + ue_TimersAndConstants_t311 = 10000; + ue_TimersAndConstants_n310 = 20; + ue_TimersAndConstants_n311 = 1; + + } + ); + + + srb1_parameters : + { + # timer_poll_retransmit = (ms) [5, 10, 15, 20,... 250, 300, 350, ... 500] + timer_poll_retransmit = 80; + + # timer_reordering = (ms) [0,5, ... 100, 110, 120, ... ,200] + timer_reordering = 35; + + # timer_reordering = (ms) [0,5, ... 250, 300, 350, ... ,500] + timer_status_prohibit = 0; + + # poll_pdu = [4, 8, 16, 32 , 64, 128, 256, infinity(>10000)] + poll_pdu = 4; + + # poll_byte = (kB) [25,50,75,100,125,250,375,500,750,1000,1250,1500,2000,3000,infinity(>10000)] + poll_byte = 99999; + + # max_retx_threshold = [1, 2, 3, 4 , 6, 8, 16, 32] + max_retx_threshold = 4; + } + + # ------- SCTP definitions + SCTP : + { + # Number of streams to use in input/output + SCTP_INSTREAMS = 2; + SCTP_OUTSTREAMS = 2; + }; + + + ////////// MME parameters: + mme_ip_address = ( { ipv4 = "192.168.12.170"; + ipv6 = "192:168:30::17"; + active = "yes"; + preference = "ipv4"; + } + ); + +rrh_gw_config = ( + { + local_if_name = "eth0"; + #remote_address = "169.254.10.158"; + #local_address = "169.254.8.15"; + remote_address = "74:d4:35:cc:88:45"; + local_address = "d4:be:d9:22:0a:ac"; + local_port = 50000; #for raw option local port must be the same to remote + remote_port = 50000; + active = "yes"; + tr_preference = "raw"; + rf_preference = "lmssdr"; + iq_txshift = 0; + tx_sample_advance = 70; + tx_scheduling_advance = 8; + +} +); + + NETWORK_INTERFACES : + { + ENB_INTERFACE_NAME_FOR_S1_MME = "eth6"; + ENB_IPV4_ADDRESS_FOR_S1_MME = "192.168.12.118/24"; + + ENB_INTERFACE_NAME_FOR_S1U = "eth6"; + + + ENB_IPV4_ADDRESS_FOR_S1U = "192.168.12.118/24"; + ENB_PORT_FOR_S1U = 2152; # Spec 2152 + }; + + log_config : + { + global_log_level ="info"; + global_log_verbosity ="medium"; + hw_log_level ="info"; + hw_log_verbosity ="medium"; + phy_log_level ="info"; + phy_log_verbosity ="medium"; + mac_log_level ="info"; + mac_log_verbosity ="high"; + rlc_log_level ="info"; + rlc_log_verbosity ="medium"; + pdcp_log_level ="info"; + pdcp_log_verbosity ="medium"; + rrc_log_level ="info"; + rrc_log_verbosity ="medium"; + }; + } +); diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.rrh.usrpb210.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.rrh.usrpb210.conf index 71d8fe7f34..82ca458085 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.rrh.usrpb210.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.rrh.usrpb210.conf @@ -143,21 +143,18 @@ eNBs = rrh_gw_config = ( { local_if_name = "eth0"; - remote_address = "169.254.10.158"; - local_address = "169.254.8.15"; - #remote_address = "127.0.0.1"; - #remote_address = "74:d4:35:cc:88:45"; - #local_address = "127.0.0.1"; - #local_address = "d4:be:d9:22:0a:ac"; - #for raw option local port must be the same to remote - local_port = 50001; + #remote_address = "169.254.10.158"; + #local_address = "169.254.8.15"; + remote_address = "74:d4:35:cc:88:45"; + local_address = "d4:be:d9:22:0a:ac"; + local_port = 50000; #for raw option local port must be the same to remote remote_port = 50000; active = "yes"; - tr_preference = "udp"; + tr_preference = "raw"; rf_preference = "usrp_b200"; - iq_txshift = 8; - tx_sample_advance = 50; - tx_scheduling_advance = 100; + iq_txshift = 5; + tx_sample_advance = 70; + tx_scheduling_advance = 8; } ); From d13bb9d70345a5893f8247353396369d047e1675 Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Wed, 17 Feb 2016 16:24:00 +0100 Subject: [PATCH 246/263] update config files for rrh + usrp --- .../enb.band7.tm1.50PRB.rrh.usrpb210.conf | 160 +++++++++--------- .../CONF/enb.band7.tm1.rrh.usrpb210.conf | 14 +- 2 files changed, 86 insertions(+), 88 deletions(-) diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.rrh.usrpb210.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.rrh.usrpb210.conf index abaf8de6ee..c42e1b7864 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.rrh.usrpb210.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.rrh.usrpb210.conf @@ -5,7 +5,7 @@ Asn1_verbosity = "none"; eNBs = ( { - ////////// Identification parameters: + ////////// Identification parameters: eNB_ID = 0xe00; cell_type = "CELL_MACRO_ENB"; @@ -23,85 +23,83 @@ eNBs = component_carriers = ( { - frame_type = "FDD"; - tdd_config = 3; - tdd_config_s = 0; - prefix_type = "NORMAL"; - eutra_band = 7; - downlink_frequency = 2660000000L; - uplink_frequency_offset = -120000000; - Nid_cell = 0; - N_RB_DL = 25; - Nid_cell_mbsfn = 0; - nb_antennas_tx = 1; - nb_antennas_rx = 1; - tx_gain = 90; - rx_gain = 125; - prach_root = 0; - prach_config_index = 0; - prach_high_speed = "DISABLE"; - prach_zero_correlation = 1; - prach_freq_offset = 2; - pucch_delta_shift = 1; - pucch_nRB_CQI = 1; - pucch_nCS_AN = 0; - pucch_n1_AN = 32; - pdsch_referenceSignalPower = -29; - pdsch_p_b = 0; - pusch_n_SB = 1; - pusch_enable64QAM = "DISABLE"; - pusch_hoppingMode = "interSubFrame"; - pusch_hoppingOffset = 0; - pusch_groupHoppingEnabled = "ENABLE"; - pusch_groupAssignment = 0; - pusch_sequenceHoppingEnabled = "DISABLE"; - pusch_nDMRS1 = 1; - phich_duration = "NORMAL"; - phich_resource = "ONESIXTH"; - srs_enable = "DISABLE"; - /* srs_BandwidthConfig =; - srs_SubframeConfig =; - srs_ackNackST =; - srs_MaxUpPts =;*/ + frame_type = "FDD"; + tdd_config = 3; + tdd_config_s = 0; + prefix_type = "NORMAL"; + eutra_band = 7; + downlink_frequency = 2680000000L; + uplink_frequency_offset = -120000000; + Nid_cell = 0; + N_RB_DL = 50; + Nid_cell_mbsfn = 0; + nb_antennas_tx = 1; + nb_antennas_rx = 1; + tx_gain = 90; + rx_gain = 125; + prach_root = 0; + prach_config_index = 0; + prach_high_speed = "DISABLE"; + prach_zero_correlation = 1; + prach_freq_offset = 2; + pucch_delta_shift = 1; + pucch_nRB_CQI = 1; + pucch_nCS_AN = 0; + pucch_n1_AN = 32; + pdsch_referenceSignalPower = -29; + pdsch_p_b = 0; + pusch_n_SB = 1; + pusch_enable64QAM = "DISABLE"; + pusch_hoppingMode = "interSubFrame"; + pusch_hoppingOffset = 0; + pusch_groupHoppingEnabled = "ENABLE"; + pusch_groupAssignment = 0; + pusch_sequenceHoppingEnabled = "DISABLE"; + pusch_nDMRS1 = 1; + phich_duration = "NORMAL"; + phich_resource = "ONESIXTH"; + srs_enable = "DISABLE"; + /* srs_BandwidthConfig =; + srs_SubframeConfig =; + srs_ackNackST =; + srs_MaxUpPts =;*/ - pusch_p0_Nominal = -90; - pusch_alpha = "AL1"; - pucch_p0_Nominal = -96; - msg3_delta_Preamble = 6; - pucch_deltaF_Format1 = "deltaF2"; - pucch_deltaF_Format1b = "deltaF3"; - pucch_deltaF_Format2 = "deltaF0"; - pucch_deltaF_Format2a = "deltaF0"; - pucch_deltaF_Format2b = "deltaF0"; + pusch_p0_Nominal = -90; + pusch_alpha = "AL1"; + pucch_p0_Nominal = -96; + msg3_delta_Preamble = 6; + pucch_deltaF_Format1 = "deltaF2"; + pucch_deltaF_Format1b = "deltaF3"; + pucch_deltaF_Format2 = "deltaF0"; + pucch_deltaF_Format2a = "deltaF0"; + pucch_deltaF_Format2b = "deltaF0"; - rach_numberOfRA_Preambles = 64; - rach_preamblesGroupAConfig = "DISABLE"; - /* - rach_sizeOfRA_PreamblesGroupA = ; - rach_messageSizeGroupA = ; - rach_messagePowerOffsetGroupB = ; - */ - rach_powerRampingStep = 4; - rach_preambleInitialReceivedTargetPower = -108; - rach_preambleTransMax = 10; - rach_raResponseWindowSize = 10; - rach_macContentionResolutionTimer = 48; - rach_maxHARQ_Msg3Tx = 4; - - pcch_default_PagingCycle = 128; - pcch_nB = "oneT"; - bcch_modificationPeriodCoeff = 2; - ue_TimersAndConstants_t300 = 1000; - ue_TimersAndConstants_t301 = 1000; - ue_TimersAndConstants_t310 = 1000; - ue_TimersAndConstants_t311 = 10000; - ue_TimersAndConstants_n310 = 20; - ue_TimersAndConstants_n311 = 1; + rach_numberOfRA_Preambles = 64; + rach_preamblesGroupAConfig = "DISABLE"; + /* + rach_sizeOfRA_PreamblesGroupA = ; + rach_messageSizeGroupA = ; + rach_messagePowerOffsetGroupB = ; + */ + rach_powerRampingStep = 4; + rach_preambleInitialReceivedTargetPower = -108; + rach_preambleTransMax = 10; + rach_raResponseWindowSize = 10; + rach_macContentionResolutionTimer = 48; + rach_maxHARQ_Msg3Tx = 4; + pcch_default_PagingCycle = 128; + pcch_nB = "oneT"; + bcch_modificationPeriodCoeff = 2; + ue_TimersAndConstants_t300 = 1000; + ue_TimersAndConstants_t301 = 1000; + ue_TimersAndConstants_t310 = 1000; + ue_TimersAndConstants_t311 = 10000; + ue_TimersAndConstants_n310 = 20; + ue_TimersAndConstants_n311 = 1; } ); - srb1_parameters : { # timer_poll_retransmit = (ms) [5, 10, 15, 20,... 250, 300, 350, ... 500] @@ -133,7 +131,7 @@ eNBs = ////////// MME parameters: - mme_ip_address = ( { ipv4 = "192.168.12.170"; + mme_ip_address = ( { ipv4 = "192.168.12.26"; ipv6 = "192:168:30::17"; active = "yes"; preference = "ipv4"; @@ -146,7 +144,7 @@ rrh_gw_config = ( #remote_address = "169.254.10.158"; #local_address = "169.254.8.15"; remote_address = "74:d4:35:cc:88:45"; - local_address = "d4:be:d9:22:0a:ac"; + local_address = "98:90:96:df:66:07"; local_port = 50000; #for raw option local port must be the same to remote remote_port = 50000; active = "yes"; @@ -154,20 +152,20 @@ rrh_gw_config = ( rf_preference = "usrp_b200"; iq_txshift = 5; tx_sample_advance = 113; - tx_scheduling_advance = 8; + tx_scheduling_advance = 9; } ); NETWORK_INTERFACES : { - ENB_INTERFACE_NAME_FOR_S1_MME = "eth6"; - ENB_IPV4_ADDRESS_FOR_S1_MME = "192.168.12.118/24"; + ENB_INTERFACE_NAME_FOR_S1_MME = "eth4"; + ENB_IPV4_ADDRESS_FOR_S1_MME = "192.168.12.111/24"; - ENB_INTERFACE_NAME_FOR_S1U = "eth6"; + ENB_INTERFACE_NAME_FOR_S1U = "eth4"; - ENB_IPV4_ADDRESS_FOR_S1U = "192.168.12.118/24"; + ENB_IPV4_ADDRESS_FOR_S1U = "192.168.12.111/24"; ENB_PORT_FOR_S1U = 2152; # Spec 2152 }; diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.rrh.usrpb210.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.rrh.usrpb210.conf index 82ca458085..6b74698849 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.rrh.usrpb210.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.rrh.usrpb210.conf @@ -133,7 +133,7 @@ eNBs = ////////// MME parameters: - mme_ip_address = ( { ipv4 = "192.168.12.170"; + mme_ip_address = ( { ipv4 = "192.168.12.26"; ipv6 = "192:168:30::17"; active = "yes"; preference = "ipv4"; @@ -146,7 +146,7 @@ rrh_gw_config = ( #remote_address = "169.254.10.158"; #local_address = "169.254.8.15"; remote_address = "74:d4:35:cc:88:45"; - local_address = "d4:be:d9:22:0a:ac"; + local_address = "98:90:96:df:66:07"; local_port = 50000; #for raw option local port must be the same to remote remote_port = 50000; active = "yes"; @@ -154,20 +154,20 @@ rrh_gw_config = ( rf_preference = "usrp_b200"; iq_txshift = 5; tx_sample_advance = 70; - tx_scheduling_advance = 8; + tx_scheduling_advance = 9; } ); NETWORK_INTERFACES : { - ENB_INTERFACE_NAME_FOR_S1_MME = "eth6"; - ENB_IPV4_ADDRESS_FOR_S1_MME = "192.168.12.118/24"; + ENB_INTERFACE_NAME_FOR_S1_MME = "eth4"; + ENB_IPV4_ADDRESS_FOR_S1_MME = "192.168.12.111/24"; - ENB_INTERFACE_NAME_FOR_S1U = "eth6"; + ENB_INTERFACE_NAME_FOR_S1U = "eth4"; - ENB_IPV4_ADDRESS_FOR_S1U = "192.168.12.118/24"; + ENB_IPV4_ADDRESS_FOR_S1U = "192.168.12.111/24"; ENB_PORT_FOR_S1U = 2152; # Spec 2152 }; From e3c4cc9d79d6655457fff1db2c44a87a6c947b49 Mon Sep 17 00:00:00 2001 From: Aikaterini Date: Wed, 17 Feb 2016 17:08:18 +0100 Subject: [PATCH 247/263] fix name of SoDERA SDR config files --- ...a.conf => enb.band7.tm1.50PRB.lmssdr.conf} | 0 .../CONF/enb.band7.tm1.50PRB.rrh.sodera.conf | 190 ----------------- ....sedora.conf => enb.band7.tm1.lmssdr.conf} | 0 .../CONF/enb.band7.tm1.rrh.sodera.conf | 192 ------------------ 4 files changed, 382 deletions(-) rename targets/PROJECTS/GENERIC-LTE-EPC/CONF/{enb.band7.tm1.50PRB.sedora.conf => enb.band7.tm1.50PRB.lmssdr.conf} (100%) delete mode 100644 targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.rrh.sodera.conf rename targets/PROJECTS/GENERIC-LTE-EPC/CONF/{enb.band7.tm1.sedora.conf => enb.band7.tm1.lmssdr.conf} (100%) delete mode 100644 targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.rrh.sodera.conf diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.sedora.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.lmssdr.conf similarity index 100% rename from targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.sedora.conf rename to targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.lmssdr.conf diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.rrh.sodera.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.rrh.sodera.conf deleted file mode 100644 index c3985c9dce..0000000000 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.rrh.sodera.conf +++ /dev/null @@ -1,190 +0,0 @@ -Active_eNBs = ( "eNB_Eurecom_LTEBox"); -# Asn1_verbosity, choice in: none, info, annoying -Asn1_verbosity = "none"; - -eNBs = -( - { - ////////// Identification parameters: - eNB_ID = 0xe00; - - cell_type = "CELL_MACRO_ENB"; - - eNB_name = "eNB_Eurecom_LTEBox"; - - // Tracking area code, 0x0000 and 0xfffe are reserved values - tracking_area_code = "1"; - - mobile_country_code = "208"; - - mobile_network_code = "93"; - - ////////// Physical parameters: - - component_carriers = ( - { - frame_type = "FDD"; - tdd_config = 3; - tdd_config_s = 0; - prefix_type = "NORMAL"; - eutra_band = 7; - downlink_frequency = 2660000000L; - uplink_frequency_offset = -120000000; - Nid_cell = 0; - N_RB_DL = 50; - Nid_cell_mbsfn = 0; - nb_antennas_tx = 1; - nb_antennas_rx = 1; - tx_gain = 60; - rx_gain = 111; - prach_root = 0; - prach_config_index = 0; - prach_high_speed = "DISABLE"; - prach_zero_correlation = 1; - prach_freq_offset = 2; - pucch_delta_shift = 1; - pucch_nRB_CQI = 1; - pucch_nCS_AN = 0; - pucch_n1_AN = 32; - pdsch_referenceSignalPower = -29; - pdsch_p_b = 0; - pusch_n_SB = 1; - pusch_enable64QAM = "DISABLE"; - pusch_hoppingMode = "interSubFrame"; - pusch_hoppingOffset = 0; - pusch_groupHoppingEnabled = "ENABLE"; - pusch_groupAssignment = 0; - pusch_sequenceHoppingEnabled = "DISABLE"; - pusch_nDMRS1 = 1; - phich_duration = "NORMAL"; - phich_resource = "ONESIXTH"; - srs_enable = "DISABLE"; - /* srs_BandwidthConfig =; - srs_SubframeConfig =; - srs_ackNackST =; - srs_MaxUpPts =;*/ - - pusch_p0_Nominal = -85; - pusch_alpha = "AL1"; - pucch_p0_Nominal = -96; - msg3_delta_Preamble = 6; - pucch_deltaF_Format1 = "deltaF2"; - pucch_deltaF_Format1b = "deltaF3"; - pucch_deltaF_Format2 = "deltaF0"; - pucch_deltaF_Format2a = "deltaF0"; - pucch_deltaF_Format2b = "deltaF0"; - - rach_numberOfRA_Preambles = 64; - rach_preamblesGroupAConfig = "DISABLE"; -/* - rach_sizeOfRA_PreamblesGroupA = ; - rach_messageSizeGroupA = ; - rach_messagePowerOffsetGroupB = ; -*/ - rach_powerRampingStep = 4; - rach_preambleInitialReceivedTargetPower = -100; - rach_preambleTransMax = 10; - rach_raResponseWindowSize = 10; - rach_macContentionResolutionTimer = 48; - rach_maxHARQ_Msg3Tx = 4; - - pcch_default_PagingCycle = 128; - pcch_nB = "oneT"; - bcch_modificationPeriodCoeff = 2; - ue_TimersAndConstants_t300 = 1000; - ue_TimersAndConstants_t301 = 1000; - ue_TimersAndConstants_t310 = 1000; - ue_TimersAndConstants_t311 = 10000; - ue_TimersAndConstants_n310 = 20; - ue_TimersAndConstants_n311 = 1; - - } - ); - - - srb1_parameters : - { - # timer_poll_retransmit = (ms) [5, 10, 15, 20,... 250, 300, 350, ... 500] - timer_poll_retransmit = 80; - - # timer_reordering = (ms) [0,5, ... 100, 110, 120, ... ,200] - timer_reordering = 35; - - # timer_reordering = (ms) [0,5, ... 250, 300, 350, ... ,500] - timer_status_prohibit = 0; - - # poll_pdu = [4, 8, 16, 32 , 64, 128, 256, infinity(>10000)] - poll_pdu = 4; - - # poll_byte = (kB) [25,50,75,100,125,250,375,500,750,1000,1250,1500,2000,3000,infinity(>10000)] - poll_byte = 99999; - - # max_retx_threshold = [1, 2, 3, 4 , 6, 8, 16, 32] - max_retx_threshold = 4; - } - - # ------- SCTP definitions - SCTP : - { - # Number of streams to use in input/output - SCTP_INSTREAMS = 2; - SCTP_OUTSTREAMS = 2; - }; - - ////////// MME parameters: - mme_ip_address = ( { ipv4 = "192.168.12.11"; - ipv6 = "192:168:30::17"; - active = "yes"; - preference = "ipv4"; - } - ); - - -rrh_gw_config = ( - { - local_if_name = "eth0"; - remote_address = "169.254.8.28"; - #remote_address = "127.0.0.1"; - #remote_address = "74:d4:35:cc:88:45"; - local_address = "169.254.7.91"; - #local_address = "127.0.0.1"; - #local_address = "d4:be:d9:22:0a:ac"; - #for raw option local port must be the same to remote - local_port = 50000; - remote_port = 50000; - active = "yes"; - preference = "raw"; - -} -); - - NETWORK_INTERFACES : - { - ENB_INTERFACE_NAME_FOR_S1_MME = "eth0"; - ENB_IPV4_ADDRESS_FOR_S1_MME = "192.168.12.111/24"; - - ENB_INTERFACE_NAME_FOR_S1U = "eth0"; - ENB_IPV4_ADDRESS_FOR_S1U = "192.168.12.111/24"; - ENB_PORT_FOR_S1U = 2152; # Spec 2152 - }; - - log_config : - { - global_log_level ="info"; - global_log_verbosity ="medium"; - hw_log_level ="info"; - hw_log_verbosity ="medium"; - phy_log_level ="info"; - phy_log_verbosity ="medium"; - mac_log_level ="info"; - mac_log_verbosity ="high"; - rlc_log_level ="info"; - rlc_log_verbosity ="medium"; - pdcp_log_level ="info"; - pdcp_log_verbosity ="medium"; - rrc_log_level ="info"; - rrc_log_verbosity ="medium"; - }; - - } -); diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.sedora.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.lmssdr.conf similarity index 100% rename from targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.sedora.conf rename to targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.lmssdr.conf diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.rrh.sodera.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.rrh.sodera.conf deleted file mode 100644 index 2db6eb799b..0000000000 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.rrh.sodera.conf +++ /dev/null @@ -1,192 +0,0 @@ -Active_eNBs = ( "eNB_Eurecom_LTEBox"); -# Asn1_verbosity, choice in: none, info, annoying -Asn1_verbosity = "none"; - -eNBs = -( - { - ////////// Identification parameters: - eNB_ID = 0xe00; - - cell_type = "CELL_MACRO_ENB"; - - eNB_name = "eNB_Eurecom_LTEBox"; - - // Tracking area code, 0x0000 and 0xfffe are reserved values - tracking_area_code = "1"; - - mobile_country_code = "208"; - - mobile_network_code = "92"; - - ////////// Physical parameters: - - component_carriers = ( - { - frame_type = "FDD"; - tdd_config = 3; - tdd_config_s = 0; - prefix_type = "NORMAL"; - eutra_band = 7; - downlink_frequency = 2660000000L; - uplink_frequency_offset = -120000000; - Nid_cell = 0; - N_RB_DL = 25; - Nid_cell_mbsfn = 0; - nb_antennas_tx = 1; - nb_antennas_rx = 1; - tx_gain = 60; - rx_gain = 111; - prach_root = 0; - prach_config_index = 0; - prach_high_speed = "DISABLE"; - prach_zero_correlation = 1; - prach_freq_offset = 2; - pucch_delta_shift = 1; - pucch_nRB_CQI = 1; - pucch_nCS_AN = 0; - pucch_n1_AN = 32; - pdsch_referenceSignalPower = -29; - pdsch_p_b = 0; - pusch_n_SB = 1; - pusch_enable64QAM = "DISABLE"; - pusch_hoppingMode = "interSubFrame"; - pusch_hoppingOffset = 0; - pusch_groupHoppingEnabled = "ENABLE"; - pusch_groupAssignment = 0; - pusch_sequenceHoppingEnabled = "DISABLE"; - pusch_nDMRS1 = 1; - phich_duration = "NORMAL"; - phich_resource = "ONESIXTH"; - srs_enable = "DISABLE"; - /* srs_BandwidthConfig =; - srs_SubframeConfig =; - srs_ackNackST =; - srs_MaxUpPts =;*/ - - pusch_p0_Nominal = -85; - pusch_alpha = "AL1"; - pucch_p0_Nominal = -96; - msg3_delta_Preamble = 6; - pucch_deltaF_Format1 = "deltaF2"; - pucch_deltaF_Format1b = "deltaF3"; - pucch_deltaF_Format2 = "deltaF0"; - pucch_deltaF_Format2a = "deltaF0"; - pucch_deltaF_Format2b = "deltaF0"; - - rach_numberOfRA_Preambles = 64; - rach_preamblesGroupAConfig = "DISABLE"; -/* - rach_sizeOfRA_PreamblesGroupA = ; - rach_messageSizeGroupA = ; - rach_messagePowerOffsetGroupB = ; -*/ - rach_powerRampingStep = 4; - rach_preambleInitialReceivedTargetPower = -100; - rach_preambleTransMax = 10; - rach_raResponseWindowSize = 10; - rach_macContentionResolutionTimer = 48; - rach_maxHARQ_Msg3Tx = 4; - - pcch_default_PagingCycle = 128; - pcch_nB = "oneT"; - bcch_modificationPeriodCoeff = 2; - ue_TimersAndConstants_t300 = 1000; - ue_TimersAndConstants_t301 = 1000; - ue_TimersAndConstants_t310 = 1000; - ue_TimersAndConstants_t311 = 10000; - ue_TimersAndConstants_n310 = 20; - ue_TimersAndConstants_n311 = 1; - - } - ); - - - srb1_parameters : - { - # timer_poll_retransmit = (ms) [5, 10, 15, 20,... 250, 300, 350, ... 500] - timer_poll_retransmit = 80; - - # timer_reordering = (ms) [0,5, ... 100, 110, 120, ... ,200] - timer_reordering = 35; - - # timer_reordering = (ms) [0,5, ... 250, 300, 350, ... ,500] - timer_status_prohibit = 0; - - # poll_pdu = [4, 8, 16, 32 , 64, 128, 256, infinity(>10000)] - poll_pdu = 4; - - # poll_byte = (kB) [25,50,75,100,125,250,375,500,750,1000,1250,1500,2000,3000,infinity(>10000)] - poll_byte = 99999; - - # max_retx_threshold = [1, 2, 3, 4 , 6, 8, 16, 32] - max_retx_threshold = 4; - } - - # ------- SCTP definitions - SCTP : - { - # Number of streams to use in input/output - SCTP_INSTREAMS = 2; - SCTP_OUTSTREAMS = 2; - }; - - ////////// MME parameters: - mme_ip_address = ( { ipv4 = "192.168.12.26"; - ipv6 = "192:168:30::17"; - active = "yes"; - preference = "ipv4"; - } - ); - - - -rrh_gw_config = ( - { - local_if_name = "eth0"; - remote_address = "169.254.8.28"; - #remote_address = "127.0.0.1"; - #remote_address = "74:d4:35:cc:88:45"; - local_address = "169.254.7.91"; - #local_address = "127.0.0.1"; - #local_address = "d4:be:d9:22:0a:ac"; - #for raw option local port must be the same to remote - local_port = 50000; - remote_port = 50000; - active = "yes"; - preference = "raw"; - -} -); - - - NETWORK_INTERFACES : - { - ENB_INTERFACE_NAME_FOR_S1_MME = "eth4"; - ENB_IPV4_ADDRESS_FOR_S1_MME = "192.168.12.111/24"; - - ENB_INTERFACE_NAME_FOR_S1U = "eth4"; - ENB_IPV4_ADDRESS_FOR_S1U = "192.168.12.111/24"; - ENB_PORT_FOR_S1U = 2152; # Spec 2152 - }; - - log_config : - { - global_log_level ="info"; - global_log_verbosity ="medium"; - hw_log_level ="info"; - hw_log_verbosity ="medium"; - phy_log_level ="info"; - phy_log_verbosity ="medium"; - mac_log_level ="info"; - mac_log_verbosity ="high"; - rlc_log_level ="info"; - rlc_log_verbosity ="medium"; - pdcp_log_level ="info"; - pdcp_log_verbosity ="medium"; - rrc_log_level ="info"; - rrc_log_verbosity ="medium"; - }; - - } -); From 87dc41f06794eec1da2ca46c8c57a690100480ea Mon Sep 17 00:00:00 2001 From: Aikaterini Trilyraki Date: Wed, 17 Feb 2016 19:55:03 +0100 Subject: [PATCH 248/263] Delete CMakelists.txt for rrH GW --- cmake_targets/rrh_gw/CMakeLists.txt | 6 ------ 1 file changed, 6 deletions(-) delete mode 100644 cmake_targets/rrh_gw/CMakeLists.txt diff --git a/cmake_targets/rrh_gw/CMakeLists.txt b/cmake_targets/rrh_gw/CMakeLists.txt deleted file mode 100644 index 9ff1437f0c..0000000000 --- a/cmake_targets/rrh_gw/CMakeLists.txt +++ /dev/null @@ -1,6 +0,0 @@ -cmake_minimum_required(VERSION 2.8) -set(ENABLE_VCD_FIFO False ) -set(ENABLE_ITTI False ) -set(RF_BOARD "ETHERNET") -set(PACKAGE_NAME "\"rrh_gw\"") -include(${CMAKE_CURRENT_SOURCE_DIR}/../CMakeLists.txt) From caf14c40d48377e4c2799de7f6f8e2ec5fe9ae21 Mon Sep 17 00:00:00 2001 From: Aikaterini Date: Thu, 18 Feb 2016 17:54:12 +0100 Subject: [PATCH 249/263] settings for 5MHz SoDERA --- targets/ARCH/LMSSDR/USERSPACE/LIB/lms_lib.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/targets/ARCH/LMSSDR/USERSPACE/LIB/lms_lib.cpp b/targets/ARCH/LMSSDR/USERSPACE/LIB/lms_lib.cpp index e5f69d5577..3ca15c6660 100644 --- a/targets/ARCH/LMSSDR/USERSPACE/LIB/lms_lib.cpp +++ b/targets/ARCH/LMSSDR/USERSPACE/LIB/lms_lib.cpp @@ -82,7 +82,7 @@ int trx_lms_read(openair0_device *device, openair0_timestamp *ptimestamp, void * uint64_t timestamp; int16_t *dst_ptr = (int16_t*) buff[0]; int ret; - ret = LMS_TRxRead(dst_ptr, nsamps,0,×tamp, 100); + ret = LMS_TRxRead(dst_ptr, nsamps,0,×tamp, 10); *ptimestamp=timestamp; return ret; @@ -843,7 +843,7 @@ int device_init(openair0_device *device, openair0_config_t *openair0_cfg){ openair0_cfg[0].tx_sample_advance = 70; openair0_cfg[0].tx_bw = 28e6; openair0_cfg[0].rx_bw = 5.0e6; - openair0_cfg[0].tx_scheduling_advance = 5*openair0_cfg[0].samples_per_packet; + openair0_cfg[0].tx_scheduling_advance = 8*openair0_cfg[0].samples_per_packet; break; case 1920000: openair0_cfg[0].samples_per_packet = 256; From f7fde92665c1cbc35866e5e654519f7f82cb3eca Mon Sep 17 00:00:00 2001 From: Aikaterini Date: Thu, 18 Feb 2016 17:55:05 +0100 Subject: [PATCH 250/263] config files update --- .../CONF/enb.band7.tm1.50PRB.lmssdr.conf | 10 +++++----- .../GENERIC-LTE-EPC/CONF/enb.band7.tm1.lmssdr.conf | 12 ++++++------ .../CONF/enb.band7.tm1.usrpb210.epc.remote.conf | 14 +++++++------- 3 files changed, 18 insertions(+), 18 deletions(-) diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.lmssdr.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.lmssdr.conf index 8a5f33af4b..e001bd12e9 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.lmssdr.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.lmssdr.conf @@ -132,7 +132,7 @@ eNBs = }; ////////// MME parameters: - mme_ip_address = ( { ipv4 = "192.168.12.11"; + mme_ip_address = ( { ipv4 = "192.168.12.171"; ipv6 = "192:168:30::17"; active = "yes"; preference = "ipv4"; @@ -141,11 +141,11 @@ eNBs = NETWORK_INTERFACES : { - ENB_INTERFACE_NAME_FOR_S1_MME = "eth0"; - ENB_IPV4_ADDRESS_FOR_S1_MME = "192.168.12.215/24"; + ENB_INTERFACE_NAME_FOR_S1_MME = "eth4"; + ENB_IPV4_ADDRESS_FOR_S1_MME = "192.168.12.242/24"; - ENB_INTERFACE_NAME_FOR_S1U = "eth0"; - ENB_IPV4_ADDRESS_FOR_S1U = "192.168.12.215/24"; + ENB_INTERFACE_NAME_FOR_S1U = "eth4"; + ENB_IPV4_ADDRESS_FOR_S1U = "192.168.12.242/24"; ENB_PORT_FOR_S1U = 2152; # Spec 2152 }; diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.lmssdr.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.lmssdr.conf index 70fcc2e3f4..47e2179d18 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.lmssdr.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.lmssdr.conf @@ -17,7 +17,7 @@ eNBs = mobile_country_code = "208"; - mobile_network_code = "93"; + mobile_network_code = "92"; ////////// Physical parameters: @@ -132,7 +132,7 @@ eNBs = }; ////////// MME parameters: - mme_ip_address = ( { ipv4 = "192.168.12.11"; + mme_ip_address = ( { ipv4 = "192.168.12.170"; ipv6 = "192:168:30::17"; active = "yes"; preference = "ipv4"; @@ -141,11 +141,11 @@ eNBs = NETWORK_INTERFACES : { - ENB_INTERFACE_NAME_FOR_S1_MME = "eth0"; - ENB_IPV4_ADDRESS_FOR_S1_MME = "192.168.12.215/24"; + ENB_INTERFACE_NAME_FOR_S1_MME = "eth4"; + ENB_IPV4_ADDRESS_FOR_S1_MME = "192.168.12.242/24"; - ENB_INTERFACE_NAME_FOR_S1U = "eth0"; - ENB_IPV4_ADDRESS_FOR_S1U = "192.168.12.215/24"; + ENB_INTERFACE_NAME_FOR_S1U = "eth4"; + ENB_IPV4_ADDRESS_FOR_S1U = "192.168.12.242/24"; ENB_PORT_FOR_S1U = 2152; # Spec 2152 }; diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf index 375a4a90ca..83b08cb4e0 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.epc.remote.conf @@ -16,7 +16,7 @@ eNBs = tracking_area_code = "1"; mobile_country_code = "208"; - mobile_network_code = "95"; + mobile_network_code = "92"; ////////// Physical parameters: @@ -35,7 +35,7 @@ eNBs = nb_antennas_tx = 1; nb_antennas_rx = 1; tx_gain = 90; - rx_gain = 132; + rx_gain = 125; prach_root = 0; prach_config_index = 0; prach_high_speed = "DISABLE"; @@ -130,18 +130,18 @@ eNBs = }; ////////// MME parameters: - mme_ip_address = ( {ipv4 = "192.168.12.17"; + mme_ip_address = ( {ipv4 = "192.168.12.170"; ipv6="192:168:30::17"; active="yes"; preference="ipv4";}); NETWORK_INTERFACES : { - ENB_INTERFACE_NAME_FOR_S1_MME = "eth0"; - ENB_IPV4_ADDRESS_FOR_S1_MME = "192.168.12.213/24"; + ENB_INTERFACE_NAME_FOR_S1_MME = "eth4"; + ENB_IPV4_ADDRESS_FOR_S1_MME = "192.168.12.242/24"; - ENB_INTERFACE_NAME_FOR_S1U = "eth0"; - ENB_IPV4_ADDRESS_FOR_S1U = "192.168.12.213/24"; + ENB_INTERFACE_NAME_FOR_S1U = "eth4"; + ENB_IPV4_ADDRESS_FOR_S1U = "192.168.12.242/24"; ENB_PORT_FOR_S1U = 2152; # Spec 2152 }; From 78913e263e68d38566c2030e4ca33e903500bbf7 Mon Sep 17 00:00:00 2001 From: Navid Nikaein Date: Fri, 19 Feb 2016 00:43:02 +0100 Subject: [PATCH 251/263] change rrh_gw_config naming in enb config file --- cmake_targets/tools/build_helper | 18 ++++++++++++++++++ openair2/ENB_APP/enb_config.c | 2 +- .../CONF/enb.band7.tm1.50PRB.rrh.lmssdr.conf | 2 +- .../CONF/enb.band7.tm1.50PRB.rrh.usrpb210.conf | 2 +- .../CONF/enb.band7.tm1.rrh.lmssdr.conf | 2 +- .../CONF/enb.band7.tm1.rrh.usrpb210.conf | 2 +- 6 files changed, 23 insertions(+), 5 deletions(-) diff --git a/cmake_targets/tools/build_helper b/cmake_targets/tools/build_helper index d29dbffe13..c8adf45257 100755 --- a/cmake_targets/tools/build_helper +++ b/cmake_targets/tools/build_helper @@ -380,3 +380,21 @@ done } +# get from http://www.linuxjournal.com/content/validating-ip-address-bash-script +validate_ip() { + +local ip=$1 +local stat=1 + +if [[ $ip =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then + OIFS=$IFS + IFS='.' + ip=($ip) + IFS=$OIFS + [[ ${ip[0]} -le 255 && ${ip[1]} -le 255 \ + && ${ip[2]} -le 255 && ${ip[3]} -le 255 ]] + stat=$? +fi + +return $stat +} \ No newline at end of file diff --git a/openair2/ENB_APP/enb_config.c b/openair2/ENB_APP/enb_config.c index 0f6e6b3706..4c532285f2 100755 --- a/openair2/ENB_APP/enb_config.c +++ b/openair2/ENB_APP/enb_config.c @@ -176,7 +176,7 @@ #define ENB_CONFIG_STRING_RRH_GW_REMOTE_ADDRESS "remote_address" #define ENB_CONFIG_STRING_RRH_GW_LOCAL_PORT "local_port" #define ENB_CONFIG_STRING_RRH_GW_REMOTE_PORT "remote_port" -#define ENB_CONFIG_STRING_RRH_GW_ACTIVE "active" +#define ENB_CONFIG_STRING_RRH_GW_ACTIVE "rrh_gw_active" #define ENB_CONFIG_STRING_RRH_GW_TRANSPORT_PREFERENCE "tr_preference" #define ENB_CONFIG_STRING_RRH_GW_RF_TARGET_PREFERENCE "rf_preference" #define ENB_CONFIG_STRING_RRH_GW_IQ_TXSHIFT "iq_txshift" diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.rrh.lmssdr.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.rrh.lmssdr.conf index 604226c31a..4cd761645b 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.rrh.lmssdr.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.rrh.lmssdr.conf @@ -149,7 +149,7 @@ rrh_gw_config = ( local_address = "d4:be:d9:22:0a:ac"; local_port = 50000; #for raw option local port must be the same to remote remote_port = 50000; - active = "yes"; + rrh_gw_active = "yes"; tr_preference = "raw"; rf_preference = "lmssdr"; iq_txshift = 0; diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.rrh.usrpb210.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.rrh.usrpb210.conf index c42e1b7864..604f5567ef 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.rrh.usrpb210.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.rrh.usrpb210.conf @@ -147,7 +147,7 @@ rrh_gw_config = ( local_address = "98:90:96:df:66:07"; local_port = 50000; #for raw option local port must be the same to remote remote_port = 50000; - active = "yes"; + rrh_gw_active = "yes"; tr_preference = "raw"; rf_preference = "usrp_b200"; iq_txshift = 5; diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.rrh.lmssdr.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.rrh.lmssdr.conf index 93afe062e9..9b052bf7ba 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.rrh.lmssdr.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.rrh.lmssdr.conf @@ -149,7 +149,7 @@ rrh_gw_config = ( local_address = "d4:be:d9:22:0a:ac"; local_port = 50000; #for raw option local port must be the same to remote remote_port = 50000; - active = "yes"; + rrh_gw_active = "yes"; tr_preference = "raw"; rf_preference = "lmssdr"; iq_txshift = 0; diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.rrh.usrpb210.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.rrh.usrpb210.conf index 6b74698849..33db53740c 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.rrh.usrpb210.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.rrh.usrpb210.conf @@ -149,7 +149,7 @@ rrh_gw_config = ( local_address = "98:90:96:df:66:07"; local_port = 50000; #for raw option local port must be the same to remote remote_port = 50000; - active = "yes"; + rrh_gw_active = "yes"; tr_preference = "raw"; rf_preference = "usrp_b200"; iq_txshift = 5; From 8984944444e51f0b6c267233d718c4514724bcee Mon Sep 17 00:00:00 2001 From: Florian Kaltenberger Date: Fri, 19 Feb 2016 11:47:25 +0100 Subject: [PATCH 252/263] fixing a bug in cmult_vv, removing unused code. --- openair1/PHY/TOOLS/cmult_mm.c | 200 ------------------ openair1/PHY/TOOLS/cmult_vv.c | 5 +- openair1/PHY/TOOLS/cmult_vvh.c | 366 --------------------------------- openair1/PHY/TOOLS/defs.h | 208 +++---------------- openair1/PHY/TOOLS/time_meas.h | 4 + 5 files changed, 33 insertions(+), 750 deletions(-) delete mode 100644 openair1/PHY/TOOLS/cmult_mm.c delete mode 100644 openair1/PHY/TOOLS/cmult_vvh.c diff --git a/openair1/PHY/TOOLS/cmult_mm.c b/openair1/PHY/TOOLS/cmult_mm.c deleted file mode 100644 index 328958af29..0000000000 --- a/openair1/PHY/TOOLS/cmult_mm.c +++ /dev/null @@ -1,200 +0,0 @@ -/******************************************************************************* - OpenAirInterface - Copyright(c) 1999 - 2014 Eurecom - - OpenAirInterface is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - - OpenAirInterface 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 General Public License for more details. - - You should have received a copy of the GNU General Public License - along with OpenAirInterface.The full GNU General Public License is - included in this distribution in the file called "COPYING". If not, - see . - - Contact Information - OpenAirInterface Admin: openair_admin@eurecom.fr - OpenAirInterface Tech : openair_tech@eurecom.fr - OpenAirInterface Dev : openair4g-devel@lists.eurecom.fr - - Address : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE - - *******************************************************************************/ -#include "defs.h" - -int mult_cpx_matrix_h(short *x1[2][2], - short *x2[2][2], - short *y[2][2], - unsigned int N, - unsigned short output_shift, - short hermitian) -{ - - if (hermitian) { - // this computes x1^H*x2 and stores it in y - mult_cpx_vector_h(x2[0][0],x1[0][0],y[0][0],N,output_shift,1); - mult_cpx_vector_h(x2[0][1],x1[0][1],y[0][0],N,output_shift,1); - mult_cpx_vector_h(x2[0][0],x1[1][0],y[1][0],N,output_shift,1); - mult_cpx_vector_h(x2[0][1],x1[1][1],y[1][0],N,output_shift,1); - mult_cpx_vector_h(x2[1][0],x1[0][0],y[0][1],N,output_shift,1); - mult_cpx_vector_h(x2[1][1],x1[0][1],y[0][1],N,output_shift,1); - mult_cpx_vector_h(x2[1][0],x1[1][0],y[1][1],N,output_shift,1); - mult_cpx_vector_h(x2[1][1],x1[1][1],y[1][1],N,output_shift,1); - } else { - // this computes x1*x2^H and stores it in y - mult_cpx_vector_h(x1[0][0],x2[0][0],y[0][0],N,output_shift,1); - mult_cpx_vector_h(x1[0][1],x2[0][1],y[0][0],N,output_shift,1); - mult_cpx_vector_h(x1[0][0],x2[1][0],y[0][1],N,output_shift,1); - mult_cpx_vector_h(x1[0][1],x2[1][1],y[0][1],N,output_shift,1); - mult_cpx_vector_h(x1[1][0],x2[0][0],y[1][0],N,output_shift,1); - mult_cpx_vector_h(x1[1][1],x2[0][1],y[1][0],N,output_shift,1); - mult_cpx_vector_h(x1[1][0],x2[1][0],y[1][1],N,output_shift,1); - mult_cpx_vector_h(x1[1][1],x2[1][1],y[1][1],N,output_shift,1); - } -} - -int mult_cpx_matrix_vector(int *x1[2][2], - int *x2[2], - int *y[2], - unsigned int N, - unsigned short output_shift) -{ - - Zero_Buffer(y[0],N*8); - Zero_Buffer(y[1],N*8); - - // this computes x1*x2 and stores it in y (32 bit) - mult_cpx_vector_add32((short*)x2[0],(short*)x1[0][0],(short*)y[0],N); - mult_cpx_vector_add32((short*)x2[1],(short*)x1[0][1],(short*)y[0],N); - mult_cpx_vector_add32((short*)x2[0],(short*)x1[1][0],(short*)y[1],N); - mult_cpx_vector_add32((short*)x2[1],(short*)x1[1][1],(short*)y[1],N); - - // shift and pack - shift_and_pack((short*)y[0],N,output_shift); - shift_and_pack((short*)y[1],N,output_shift); - -} - -#ifdef MAIN_MM -#include -#include -main () -{ - short x1_00[256] __attribute__((aligned(16))); - short x1_10[256] __attribute__((aligned(16))); - short x1_01[256] __attribute__((aligned(16))); - short x1_11[256] __attribute__((aligned(16))); - short x2_0[256] __attribute__((aligned(16))); - short x2_1[256] __attribute__((aligned(16))); - short y_0[256] __attribute__((aligned(16))); - short y_1[256] __attribute__((aligned(16))); - - int *x1[2][2]; - int *x2[2]; - int *y[2]; - int i,m,n; - - x1[0][0] = (int*)x1_00; - x1[0][1] = (int*)x1_01; - x1[1][0] = (int*)x1_10; - x1[1][1] = (int*)x1_11; - x2[0] = (int*)x2_0; - x2[1] = (int*)x2_1; - y[0] = (int*)y_0; - y[1] = (int*)y_1; - - for(m=0; m<2; m++) { - for(n=0; n<2; n++) { - for(i=0; i<256; i+=4) { - ((short*)x1[m][n])[i] = ((short) rand())/4; - ((short*)x1[m][n])[i+1] = ((short) rand())/4; - ((short*)x1[m][n])[i+2] = -((short*)x1[m][n])[i+1]; - ((short*)x1[m][n])[i+3] = ((short*)x1[m][n])[i]; - } - } - - for(i=0; i<256; i+=4) { - ((short*)x2[m])[i] = ((short) rand())/4; - ((short*)x2[m])[i+1] = ((short) rand())/4; - ((short*)x2[m])[i+2] = ((short*)x2[m])[i]; - ((short*)x2[m])[i+3] = ((short*)x2[m])[i+1]; - } - - Zero_Buffer(y[m],512); - } - - /* - input[0] = 100; - input[1] = 200; - input[2] = -200; - input[3] = 100; - input[4] = 1000; - input[5] = 2000; - input[6] = -2000; - input[7] = 1000; - input[8] = 100; - input[9] = 200; - input[10] = -200; - input[11] = 100; - input[12] = 1000; - input[13] = 2000; - input[14] = -2000; - input[15] = 1000; - - input2[0] = 2; - input2[1] = 1; - input2[2] = 2; - input2[3] = 1; - input2[4] = 20; - input2[5] = 10; - input2[6] = 20; - input2[7] = 10; - input2[8] = 2; - input2[9] = 1; - input2[10] = 2; - input2[11] = 1; - input2[12] = 2000; - input2[13] = 1000; - input2[14] = 2000; - input2[15] = 1000; - - x1[0][0] = (int*)input; - x1[0][1] = (int*)input; - x1[1][0] = (int*)input; - x1[1][1] = (int*)input; - - x2[0] = (int*)input2; - x2[1] = (int*)input2; - - y[0] = (int*)output; - y[1] = (int*)output2; - */ - - mult_cpx_matrix_vector(x1,x2,y,64,15); - - //mult_cpx_vector_add32(x2[0],x1[0][0],y[0],64); - - for (i=0; i<128; i+=2) - printf("i=%d, x1 = [%d+1i*%d %d+1i*%d; %d+1i*%d %d+1i*%d]; x2 = [%d+1i*%d; %d+1i*%d]; y = [%d+1i*%d; %d+1i*%d]; y_m= round(x1*x2./pow2(15)); y-y_m \n", - i, - ((short*)x1[0][0])[2*i], ((short*)x1[0][0])[2*i+2], - ((short*)x1[0][1])[2*i], ((short*)x1[0][1])[2*i+2], - ((short*)x1[1][0])[2*i], ((short*)x1[1][0])[2*i+2], - ((short*)x1[1][1])[2*i], ((short*)x1[1][1])[2*i+2], - ((short*)x2[0])[2*i], ((short*)x2[0])[2*i+1], - ((short*)x2[1])[2*i], ((short*)x2[1])[2*i+1], - ((short*)y[0])[2*i], ((short*)y[0])[2*i+1], - ((short*)y[1])[2*i], ((short*)y[1])[2*i+1]); - - //((int*)y[0])[i], ((int*)y[0])[i+1], - //((int*)y[1])[i], ((int*)y[1])[i+1]); - -} - -#endif diff --git a/openair1/PHY/TOOLS/cmult_vv.c b/openair1/PHY/TOOLS/cmult_vv.c index d7b7275508..f970d33224 100755 --- a/openair1/PHY/TOOLS/cmult_vv.c +++ b/openair1/PHY/TOOLS/cmult_vv.c @@ -50,7 +50,7 @@ int mult_cpx_conj_vector(int16_t *x1, uint32_t N, int output_shift) { - // Multiply elementwise two complex vectors of N elements with repeated formatted output + // Multiply elementwise the complex conjugate of x1 with x2. // x1 - input 1 in the format |Re0 Im0 Re1 Im1|,......,|Re(N-2) Im(N-2) Re(N-1) Im(N-1)| // We assume x1 with a dinamic of 15 bit maximum // @@ -90,7 +90,7 @@ int mult_cpx_conj_vector(int16_t *x1, tmp_im = _mm_shufflelo_epi16(*x1_128,_MM_SHUFFLE(2,3,0,1)); tmp_im = _mm_shufflehi_epi16(tmp_im,_MM_SHUFFLE(2,3,0,1)); tmp_im = _mm_sign_epi16(tmp_im,*(__m128i*)&conjug[0]); - tmp_im = _mm_madd_epi16(tmp_im,*x1_128); + tmp_im = _mm_madd_epi16(tmp_im,*x2_128); tmp_re = _mm_srai_epi32(tmp_re,output_shift); tmp_im = _mm_srai_epi32(tmp_im,output_shift); tmpy0 = _mm_unpacklo_epi32(tmp_re,tmp_im); @@ -130,3 +130,4 @@ int mult_cpx_conj_vector(int16_t *x1, return(0); } + diff --git a/openair1/PHY/TOOLS/cmult_vvh.c b/openair1/PHY/TOOLS/cmult_vvh.c deleted file mode 100644 index 64cf163d09..0000000000 --- a/openair1/PHY/TOOLS/cmult_vvh.c +++ /dev/null @@ -1,366 +0,0 @@ -/******************************************************************************* - OpenAirInterface - Copyright(c) 1999 - 2014 Eurecom - - OpenAirInterface is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - - OpenAirInterface 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 General Public License for more details. - - You should have received a copy of the GNU General Public License - along with OpenAirInterface.The full GNU General Public License is - included in this distribution in the file called "COPYING". If not, - see . - - Contact Information - OpenAirInterface Admin: openair_admin@eurecom.fr - OpenAirInterface Tech : openair_tech@eurecom.fr - OpenAirInterface Dev : openair4g-devel@lists.eurecom.fr - - Address : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE - - *******************************************************************************/ -#include "defs.h" - -static __m128i shift __attribute__ ((aligned(16))); - - -int mult_cpx_vector_h(short *x1, - short *x2, - short *y, - unsigned int N, - unsigned short output_shift, - short sign) -{ - // Multiply elementwise the complex vector x1 with the complex conjugate of the complex vecotr x2 of N elements and adds it to the vector y. - // x1 - input 1 in the format |Re0 Im0 Re0 Im0|,......,|Re(N-1) Im(N-1) Re(N-1) Im(N-1)| - // We assume x1 with a dinamic of 15 bit maximum - // - // x2 - input 2 in the format |Re0 Im0 Re0 Im0|,......,|Re(N-1) Im(N-1) Re(N-1) Im(N-1)| - // We assume x2 with a dinamic of 14 bit maximum - // - // y - output in the format |Re0 Im0 Re0 Im0|,......,|Re(N-1) Im(N-1) Re(N-1) Im(N-1)| - // - // N - the size f the vectors (this function does N cpx mpy. WARNING: N>=4; - // - // log2_amp - increase the output amplitude by a factor 2^log2_amp (default is 0) - // WARNING: log2_amp>0 can cause overflow!! - // sign - +1..add, -1..substract - - unsigned int i; // loop counter - - register __m128i m0,m1,m2; - - short *temps; - int *tempd; - - __m128i *x1_128; - __m128i *x2_128; - __m128i *y_128; - __m128i mask; - - __m128i temp; - - shift = _mm_cvtsi32_si128(output_shift); - x1_128 = (__m128i *)&x1[0]; - x2_128 = (__m128i *)&x2[0]; - y_128 = (__m128i *)&y[0]; - - if (sign == -1) - mask = (__m128i) _mm_set_epi16 (-1,1,-1,-1,-1,1,-1,-1); - else - mask = (__m128i) _mm_set_epi16 (1,-1,1,1,1,-1,1,1); - - // we compute 2*4 cpx multiply for each loop - for(i=0; i<(N>>3); i++) { - - // printf("i=%d\n",i); - - // unroll 1 - // temps = (short *)x1_128; - // printf("x1 : %d,%d,%d,%d,%d,%d,%d,%d\n",temps[0],temps[1],temps[2],temps[3],temps[4],temps[5],temps[6],temps[7]); - m1 = x1_128[0]; - m2 = x2_128[0]; - - // temps = (short *)&x2_128[0]; - // printf("x2 : %x,%x,%x,%x,%x,%x,%x,%x\n",temps[0],temps[1],temps[2],temps[3],temps[4],temps[5],temps[6],temps[7]); - - // bring x2 in conjugate form - // the first two instructions might be replaced with a single one in SSE3 - m2 = _mm_shufflelo_epi16(m2,_MM_SHUFFLE(0,1,3,2)); - m2 = _mm_shufflehi_epi16(m2,_MM_SHUFFLE(0,1,3,2)); - m2 = _mm_mullo_epi16(m2, mask); - - // temp = m2; - // temps = (short *)&temp; - // printf("x2 conj : %x,%x,%x,%x,%x,%x,%x,%x\n",temps[0],temps[1],temps[2],temps[3],temps[4],temps[5],temps[6],temps[7]); - - m0 = _mm_madd_epi16(m1,m2); //pmaddwd_r2r(mm1,mm0); // 1- compute x1[0]*x2[0] - - // temp = m0; - - // tempd = &temp; - // printf("m0 : %d,%d,%d,%d\n",tempd[0],tempd[1],tempd[2],tempd[3]); - - m0 = _mm_sra_epi32(m0,shift); // 1- shift right by shift in order to compensate for the input amplitude - - // temp = m0; - - // tempd = (int *)&temp; - // printf("m0 : %d,%d,%d,%d\n",tempd[0],tempd[1],tempd[2],tempd[3]); - - m0 = _mm_packs_epi32(m0,m0); // 1- pack in a 128 bit register [re im re im] - m0 = _mm_unpacklo_epi32(m0,m0); // 1- pack in a 128 bit register [re im re im] - - y_128[0] = _mm_add_epi16(m0,y_128[0]); - - // temps = (short *)&y_128[0]; - // printf("y0 : %d,%d,%d,%d,%d,%d,%d,%d\n",temps[0],temps[1],temps[2],temps[3],temps[4],temps[5],temps[6],temps[7]); - - // unroll 2 - m1 = x1_128[1]; - m2 = x2_128[1]; - - m2 = _mm_shufflelo_epi16(m2,_MM_SHUFFLE(0,1,3,2)); - m2 = _mm_shufflehi_epi16(m2,_MM_SHUFFLE(0,1,3,2)); - m2 = _mm_mullo_epi16(m2, mask); - - m0 = _mm_madd_epi16(m1,m2); //pmaddwd_r2r(mm1,mm0); // 1- compute x1[0]*x2[0] - - m0 = _mm_sra_epi32(m0,shift); // 1- shift right by shift in order to compensate for the input amplitude - - m0 = _mm_packs_epi32(m0,m0); // 1- pack in a 128 bit register [re im re im] - m0 = _mm_unpacklo_epi32(m0,m0); // 1- pack in a 128 bit register [re im re im] - - y_128[1] = _mm_add_epi16(m0,y_128[1]); - - // unroll 3 - m1 = x1_128[2]; - m2 = x2_128[2]; - - m2 = _mm_shufflelo_epi16(m2,_MM_SHUFFLE(0,1,3,2)); - m2 = _mm_shufflehi_epi16(m2,_MM_SHUFFLE(0,1,3,2)); - m2 = _mm_mullo_epi16(m2, mask); - - m0 = _mm_madd_epi16(m1,m2); //pmaddwd_r2r(mm1,mm0); // 1- compute x1[0]*x2[0] - - m0 = _mm_sra_epi32(m0,shift); // 1- shift right by shift in order to compensate for the input amplitude - - m0 = _mm_packs_epi32(m0,m0); // 1- pack in a 128 bit register [re im re im] - m0 = _mm_unpacklo_epi32(m0,m0); // 1- pack in a 128 bit register [re im re im] - - y_128[2] = _mm_add_epi16(m0,y_128[2]); - - - // unroll 4 - m1 = x1_128[3]; - m2 = x2_128[3]; - - m2 = _mm_shufflelo_epi16(m2,_MM_SHUFFLE(0,1,3,2)); - m2 = _mm_shufflehi_epi16(m2,_MM_SHUFFLE(0,1,3,2)); - m2 = _mm_mullo_epi16(m2, mask); - - m0 = _mm_madd_epi16(m1,m2); //pmaddwd_r2r(mm1,mm0); // 1- compute x1[0]*x2[0] - - m0 = _mm_sra_epi32(m0,shift); // 1- shift right by shift in order to compensate for the input amplitude - - m0 = _mm_packs_epi32(m0,m0); // 1- pack in a 128 bit register [re im re im] - m0 = _mm_unpacklo_epi32(m0,m0); // 1- pack in a 128 bit register [re im re im] - - y_128[3] = _mm_add_epi16(m0,y_128[3]); - - x1_128+=4; - x2_128+=4; - y_128 +=4; - // printf("x1_128 = %p, x2_128 =%p, y_128=%p\n",x1_128,x2_128,y_128); - - } - - - _mm_empty(); - _m_empty(); - - return(0); -} - - -int mult_cpx_vector_h_add32(short *x1, - short *x2, - short *y, - unsigned int N, - short sign) -{ - // Multiply elementwise the complex vector x1 with the complex conjugate of the complex vecotr x2 of N elements and adds it to the vector y. - // x1 - input 1 in 16bit format |Re0 Im0 Re0 Im0|,......,|Re(N-1) Im(N-1) Re(N-1) Im(N-1)| - // We assume x1 with a dinamic of 15 bit maximum - // - // x2 - input 2 in 16bit format |Re0 Im0 Re0 Im0|,......,|Re(N-1) Im(N-1) Re(N-1) Im(N-1)| - // We assume x2 with a dinamic of 14 bit maximum - // - // y - output in 32bit format |Re0 Im0|,......,|Re(N-1) Im(N-1)| - // - // N - the size f the vectors (this function does N cpx mpy. WARNING: N>=4; - // - // sign - +1..add, -1..substract - - unsigned int i; // loop counter - - register __m128i m0,m1,m2; - - short *temps; - int *tempd; - - __m128i *x1_128; - __m128i *x2_128; - __m128i *y_128; - __m128i mask; - - __m128i temp; - - x1_128 = (__m128i *)&x1[0]; - x2_128 = (__m128i *)&x2[0]; - y_128 = (__m128i *)&y[0]; - - if (sign == -1) - mask = (__m128i) _mm_set_epi16 (-1,1,-1,-1,-1,1,-1,-1); - else - mask = (__m128i) _mm_set_epi16 (1,-1,1,1,1,-1,1,1); - - // we compute 2*4 cpx multiply for each loop - for(i=0; i<(N>>3); i++) { - - m1 = x1_128[0]; - m2 = x2_128[0]; - - // bring x2 in conjugate form - // the first two instructions might be replaced with a single one in SSE3 - m2 = _mm_shufflelo_epi16(m2,_MM_SHUFFLE(0,1,3,2)); - m2 = _mm_shufflehi_epi16(m2,_MM_SHUFFLE(0,1,3,2)); - m2 = _mm_mullo_epi16(m2, mask); - - m0 = _mm_madd_epi16(m1,m2); // 1- compute x1[0]*x2[0], result is 32bit - - y_128[0] = _mm_add_epi32(m0,y_128[0]); - - // unroll 2 - m1 = x1_128[1]; - m2 = x2_128[1]; - - m2 = _mm_shufflelo_epi16(m2,_MM_SHUFFLE(0,1,3,2)); - m2 = _mm_shufflehi_epi16(m2,_MM_SHUFFLE(0,1,3,2)); - m2 = _mm_mullo_epi16(m2, mask); - - m0 = _mm_madd_epi16(m1,m2); - - y_128[1] = _mm_add_epi32(m0,y_128[1]); - - // unroll 3 - m1 = x1_128[2]; - m2 = x2_128[2]; - - m2 = _mm_shufflelo_epi16(m2,_MM_SHUFFLE(0,1,3,2)); - m2 = _mm_shufflehi_epi16(m2,_MM_SHUFFLE(0,1,3,2)); - m2 = _mm_mullo_epi16(m2, mask); - - m0 = _mm_madd_epi16(m1,m2); - - y_128[2] = _mm_add_epi32(m0,y_128[2]); - - - // unroll 4 - m1 = x1_128[3]; - m2 = x2_128[3]; - - m2 = _mm_shufflelo_epi16(m2,_MM_SHUFFLE(0,1,3,2)); - m2 = _mm_shufflehi_epi16(m2,_MM_SHUFFLE(0,1,3,2)); - m2 = _mm_mullo_epi16(m2, mask); - - m0 = _mm_madd_epi16(m1,m2); - - y_128[3] = _mm_add_epi32(m0,y_128[3]); - - x1_128+=4; - x2_128+=4; - y_128 +=4; - - } - - - _mm_empty(); - _m_empty(); - - return(0); -} - -#ifdef MAIN -#define L 16 - -main () -{ - - short input[256] __attribute__((aligned(16))); - short input2[256] __attribute__((aligned(16))); - short output[256] __attribute__((aligned(16))); - - int i; - - Zero_Buffer(output,256*2); - - for (i=0; i<16; i+=2) - printf("output[%d] = %d + %d i\n",i,output[i],output[i+1]); - - input[0] = 100; - input[1] = 200; - input[2] = 100; - input[3] = 200; - input[4] = 1234; - input[5] = -1234; - input[6] = 1234; - input[7] = -1234; - input[8] = 100; - input[9] = 200; - input[10] = 100; - input[11] = 200; - input[12] = 1000; - input[13] = 2000; - input[14] = 1000; - input[15] = 2000; - - input2[0] = 1; - input2[1] = 2; - input2[2] = 1; - input2[3] = 2; - input2[4] = 10; - input2[5] = 20; - input2[6] = 10; - input2[7] = 20; - input2[8] = 1; - input2[9] = 2; - input2[10] = 1; - input2[11] = 2; - input2[12] = 1000; - input2[13] = 2000; - input2[14] = 1000; - input2[15] = 2000; - - - mult_cpx_vector_h(input2,input2,output,8,0,1); - - for (i=0; i<16; i+=2) - printf("output[%d] = %d + %d i\n",i,output[i],output[i+1]); - - Zero_Buffer(output,256*2); - mult_cpx_vector_h(input2,input2,output,8,0,-1); - - for (i=0; i<16; i+=2) - printf("output[%d] = %d + %d i\n",i,output[i],output[i+1]); - -} - -#endif //MAIN diff --git a/openair1/PHY/TOOLS/defs.h b/openair1/PHY/TOOLS/defs.h index 6960fcda4c..963c1384b7 100644 --- a/openair1/PHY/TOOLS/defs.h +++ b/openair1/PHY/TOOLS/defs.h @@ -64,6 +64,8 @@ struct complex32 { int32_t i; }; +//cmult_sv.h + /*!\fn void multadd_real_vector_complex_scalar(int16_t *x,int16_t *alpha,int16_t *y,uint32_t N) This function performs componentwise multiplication and accumulation of a complex scalar and a real vector. @param x Vector input (Q1.15) @@ -95,192 +97,14 @@ void multadd_complex_vector_real_scalar(int16_t *x, uint8_t zero_flag, uint32_t N); - -/*!\fn int32_t mult_cpx_vector(int16_t *x1,int16_t *x2,int16_t *y,uint32_t N,int32_t output_shift) -This function performs optimized componentwise multiplication of two Q1.15 vectors in repeated format. - -@param x1 Input 1 in the format |Re0 Im0 Re0 Im0|,......,|Re(N-1) Im(N-1) Re(N-1) Im(N-1)| -@param x2 Input 2 in the format |Re0 -Im0 Im0 Re0|,......,|Re(N-1) -Im(N-1) Im(N-1) Re(N-1)| -@param y Output in the format |Re0 Im0 Re0 Im0|,......,|Re(N-1) Im(N-1) Re(N-1) Im(N-1)| -@param N Length of Vector WARNING: N must be a multiple of 8 (4x loop unrolling and two complex multiplies per cycle) -@param output_shift Number of bits to shift output down to Q1.15 (should be 15 for Q1.15 inputs) WARNING: log2_amp>0 can cause overflow!! - -The function implemented is : \f$\mathbf{y} = \mathbf{x_1}\odot\mathbf{x_2}\f$ -*/ -int32_t mult_cpx_vector(int16_t *x1, - int16_t *x2, - int16_t *y, - uint32_t N, - int32_t output_shift); - -/*!\fn int32_t mult_cpx_vector_norep(int16_t *x1,int16_t *x2,int16_t *y,uint32_t N,int32_t output_shift) -This function performs optimized componentwise multiplication of two Q1.15 vectors with normal formatted output. - -@param x1 Input 1 in the format |Re0 Im0 Re0 Im0|,......,|Re(N-1) Im(N-1) Re(N-1) Im(N-1)| -@param x2 Input 2 in the format |Re0 -Im0 Im0 Re0|,......,|Re(N-1) -Im(N-1) Im(N-1) Re(N-1)| -@param y Output in the format |Re0 Im0 Re1 Im1|,......,|Re(N-2) Im(N-2) Re(N-1) Im(N-1)| -@param N Length of Vector WARNING: N must be a multiple of 8 (4x loop unrolling and two complex multiplies per cycle) -@param output_shift Number of bits to shift output down to Q1.15 (should be 15 for Q1.15 inputs) WARNING: log2_amp>0 can cause overflow!! - -The function implemented is : \f$\mathbf{y} = \mathbf{x_1}\odot\mathbf{x_2}\f$ -*/ -int32_t mult_cpx_vector_norep(int16_t *x1, - int16_t *x2, - int16_t *y, - uint32_t N, - int32_t output_shift); - - -/*!\fn int32_t mult_cpx_vector_norep2(int16_t *x1,int16_t *x2,int16_t *y,uint32_t N,int32_t output_shift) -This function performs optimized componentwise multiplication of two Q1.15 vectors with normal formatted output. - -@param x1 Input 1 in the format |Re0 Im0 Re0 Im0|,......,|Re(N-1) Im(N-1) Re(N-1) Im(N-1)| -@param x2 Input 2 in the format |Re0 -Im0 Im0 Re0|,......,|Re(N-1) -Im(N-1) Im(N-1) Re(N-1)| -@param y Output in the format |Re0 Im0 Re1 Im1|,......,|Re(N-2) Im(N-2) Re(N-1) Im(N-1)| -@param N Length of Vector WARNING: N must be a multiple of 8 (no unrolling and two complex multiplies per cycle) -@param output_shift Number of bits to shift output down to Q1.15 (should be 15 for Q1.15 inputs) WARNING: log2_amp>0 can cause overflow!! - -The function implemented is : \f$\mathbf{y} = \mathbf{x_1}\odot\mathbf{x_2}\f$ -*/ -int32_t mult_cpx_vector_norep2(int16_t *x1, - int16_t *x2, - int16_t *y, - uint32_t N, - int32_t output_shift); - -int32_t mult_cpx_vector_norep_conj(int16_t *x1, - int16_t *x2, - int16_t *y, - uint32_t N, - int32_t output_shift); - -int32_t mult_cpx_vector_norep_conj2(int16_t *x1, - int16_t *x2, - int16_t *y, - uint32_t N, - int32_t output_shift); - -/*!\fn int32_t mult_cpx_vector2(int16_t *x1,int16_t *x2,int16_t *y,uint32_t N,int32_t output_shift) -This function performs optimized componentwise multiplication of two Q1.15 vectors. - -@param x1 Input 1 in the format |Re0 Im0 Re0 Im0|,......,|Re(N-1) Im(N-1) Re(N-1) Im(N-1)| -@param x2 Input 2 in the format |Re0 -Im0 Im0 Re0|,......,|Re(N-1) -Im(N-1) Im(N-1) Re(N-1)| -@param y Output in the format |Re0 Im0 Re0 Im0|,......,|Re(N-1) Im(N-1) Re(N-1) Im(N-1)| -@param N Length of Vector WARNING: N must be a multiple of 2 (2 complex multiplies per cycle) -@param output_shift Number of bits to shift output down to Q1.15 (should be 15 for Q1.15 inputs) WARNING: log2_amp>0 can cause overflow!! - -The function implemented is : \f$\mathbf{y} = \mathbf{x_1}\odot\mathbf{x_2}\f$ -*/ -int32_t mult_cpx_vector2(int16_t *x1, - int16_t *x2, - int16_t *y, - uint32_t N, - int32_t output_shift); - -/*!\fn int32_t mult_cpx_vector_add(int16_t *x1,int16_t *x2,int16_t *y,uint32_t N,int32_t output_shift) -This function performs optimized componentwise multiplication of two Q1.15 vectors. The output IS ADDED TO y. WARNING: make sure that output_shift is set to the right value, so that the result of the multiplication has the comma at the same place as y. - -@param x1 Input 1 in the format |Re0 Im0 Re0 Im0|,......,|Re(N-1) Im(N-1) Re(N-1) Im(N-1)| -@param x2 Input 2 in the format |Re0 -Im0 Im0 Re0|,......,|Re(N-1) -Im(N-1) Im(N-1) Re(N-1)| -@param y Output in the format |Re0 Im0 Re0 Im0|,......,|Re(N-1) Im(N-1) Re(N-1) Im(N-1)| -@param N Length of Vector WARNING: N>=4 -@param output_shift Number of bits to shift output down to Q1.15 (should be 15 for Q1.15 inputs) WARNING: log2_amp>0 can cause overflow!! - -The function implemented is : \f$\mathbf{y} += \mathbf{x_1}\odot\mathbf{x_2}\f$ -*/ - -int32_t mult_cpx_vector_add(int16_t *x1, - int16_t *x2, - int16_t *y, - uint32_t N, - int32_t output_shift); - - -int32_t mult_cpx_vector_h_add32(int16_t *x1, - int16_t *x2, - int16_t *y, - uint32_t N, - int16_t sign); - -int32_t mult_cpx_vector_add32(int16_t *x1, - int16_t *x2, - int16_t *y, - uint32_t N); - -int32_t mult_vector32(int16_t *x1, - int16_t *x2, +int rotate_cpx_vector(int16_t *x, + int16_t *alpha, int16_t *y, - uint32_t N); - -int32_t mult_vector32_scalar(int16_t *x1, - int32_t x2, - int16_t *y, - uint32_t N); - -int32_t mult_cpx_vector32_conj(int16_t *x, - int16_t *y, - uint32_t N); - -int32_t mult_cpx_vector32_real(int16_t *x1, - int16_t *x2, - int16_t *y, - uint32_t N); - -int32_t shift_and_pack(int16_t *y, - uint32_t N, - int32_t output_shift); - -/*!\fn int32_t mult_cpx_vector_h(int16_t *x1,int16_t *x2,int16_t *y,uint32_t N,int32_t output_shift,int16_t sign) -This function performs optimized componentwise multiplication of the vector x1 with the conjugate of the vector x2. The output IS ADDED TO y. WARNING: make sure that output_shift is set to the right value, so that the result of the multiplication has the comma at the same place as y. - -@param x1 Input 1 in the format |Re0 Im0 Re0 Im0|,......,|Re(N-1) Im(N-1) Re(N-1) Im(N-1)| -@param x2 Input 2 in the format |Re0 Im0 Re0 Im0|,......,|Re(N-1) Im(N-1) Re(N-1) Im(N-1)| -@param y Output in the format |Re0 Im0 Re0 Im0|,......,|Re(N-1) Im(N-1) Re(N-1) Im(N-1)| -@param N Length of Vector (complex samples) WARNING: N>=4 -@param output_shift Number of bits to shift output down to Q1.15 (should be 15 for Q1.15 inputs) WARNING: log2_amp>0 can cause overflow!! -@param sign +1..add, -1..substract - -The function implemented is : \f$\mathbf{y} = \mathbf{y} + \mathbf{x_1}\odot\mathbf{x_2}^*\f$ -*/ -int32_t mult_cpx_vector_h(int16_t *x1, - int16_t *x2, - int16_t *y, - uint32_t N, - int32_t output_shift, - int16_t sign); - -/*!\fn int32_t mult_cpx_matrix_h(int16_t *x1[2][2],int16_t *x2[2][2],int16_t *y[2][2],uint32_t N,uint16_t output_shift,int16_t hermitian) -This function performs optimized componentwise matrix multiplication of the 2x2 matrices x1 with the 2x2 matrices x2. The output IS ADDED TO y (i.e. make sure y is initilized correctly). WARNING: make sure that output_shift is set to the right value, so that the result of the multiplication has the comma at the same place as y. - -@param x1 Input 1 in the format |Re0 Im0 Re0 Im0|,......,|Re(N-1) Im(N-1) Re(N-1) Im(N-1)| -@param x2 Input 2 in the format |Re0 Im0 Re0 Im0|,......,|Re(N-1) Im(N-1) Re(N-1) Im(N-1)| -@param y Output in the format |Re0 Im0 Re0 Im0|,......,|Re(N-1) Im(N-1) Re(N-1) Im(N-1)| -@param N Length of Vector (complex samples) WARNING: N>=4 -@param output_shift Number of bits to shift output down to Q1.15 (should be 15 for Q1.15 inputs) WARNING: log2_amp>0 can cause overflow!! -@param hermitian if !=0 the hermitian transpose is returned (i.e. A^H*B instead of A*B^H) -*/ -int32_t mult_cpx_matrix_h(int16_t *x1[2][2], - int16_t *x2[2][2], - int16_t *y[2][2], - uint32_t N, - uint16_t output_shift, - int16_t hermitian); + uint32_t N, + uint16_t output_shift); -/*!\fn int32_t mult_cpx_matrix_vector(int32_t *x1[2][2],int32_t *x2[2],int32_t *y[2],uint32_t N,uint16_t output_shift) -This function performs optimized componentwise matrix-vector multiplication of the 2x2 matrices x1 with the 2x1 vectors x2. The output IS ADDED TO y (i.e. make sure y is initilized correctly). WARNING: make sure that output_shift is set to the right value, so that the result of the multiplication has the comma at the same place as y. -@param x1 Input 1 in the format |Re0 Im0 Re0 Im0|,......,|Re(N-1) Im(N-1) Re(N-1) Im(N-1)| -@param x2 Input 2 in the format |Re0 -Im0 Im0 Re0|,......,|Re(N-1) -Im(N-1) Im(N-1) Re(N-1)| -@param y Output in the format |Re0 Im0 Re0 Im0|,......,|Re(N-1) Im(N-1) Re(N-1) Im(N-1)| WARNING: y must be different for x2 -@param N Length of Vector (complex samples) WARNING: N>=4 -@param output_shift Number of bits to shift output down to Q1.15 (should be 15 for Q1.15 inputs) WARNING: log2_amp>0 can cause overflow!! -*/ -int32_t mult_cpx_matrix_vector(int32_t *x1[2][2], - int32_t *x2[2], - int32_t *y[2], - uint32_t N, - uint16_t output_shift); /*!\fn void init_fft(uint16_t size,uint8_t logsize,uint16_t *rev) \brief Initialize the FFT engine for a given size @@ -289,6 +113,25 @@ int32_t mult_cpx_matrix_vector(int32_t *x1[2][2], @param rev Pointer to bit-reversal permutation array */ +//cmult_vv.c +/*! + Multiply elementwise the complex conjugate of x1 with x2. + @param x1 - input 1 in the format |Re0 Im0 Re1 Im1|,......,|Re(N-2) Im(N-2) Re(N-1) Im(N-1)| + We assume x1 with a dinamic of 15 bit maximum + @param x2 - input 2 in the format |Re0 Im0 Re1 Im1|,......,|Re(N-2) Im(N-2) Re(N-1) Im(N-1)| + We assume x2 with a dinamic of 14 bit maximum + @param y - output in the format |Re0 Im0 Re1 Im1|,......,|Re(N-2) Im(N-2) Re(N-1) Im(N-1)| + @param N - the size f the vectors (this function does N cpx mpy. WARNING: N>=4; + @param output_shift - shift to be applied to generate output +*/ + +int mult_cpx_conj_vector(int16_t *x1, + int16_t *x2, + int16_t *y, + uint32_t N, + int output_shift); + +// lte_dfts.c void init_fft(uint16_t size, uint8_t logsize, uint16_t *rev); @@ -355,6 +198,7 @@ int32_t rotate_cpx_vector(int16_t *x, uint16_t output_shift); +//cadd_sv.c /*!\fn int32_t add_cpx_vector(int16_t *x,int16_t *alpha,int16_t *y,uint32_t N) This function performs componentwise addition of a vector with a complex scalar. diff --git a/openair1/PHY/TOOLS/time_meas.h b/openair1/PHY/TOOLS/time_meas.h index a3df897053..3e621ac281 100644 --- a/openair1/PHY/TOOLS/time_meas.h +++ b/openair1/PHY/TOOLS/time_meas.h @@ -26,6 +26,9 @@ Address : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE *******************************************************************************/ +#ifndef __TIME_MEAS_DEFS__H__ +#define __TIME_MEAS_DEFS__H__ + #include #include #include @@ -148,3 +151,4 @@ static inline void copy_meas(time_stats_t *dst_ts,time_stats_t *src_ts) dst_ts->max=src_ts->max; } } +#endif From 38d8a7cde079a17caf6e7b8b20e0facefab27de0 Mon Sep 17 00:00:00 2001 From: Aikaterini Date: Fri, 19 Feb 2016 13:11:02 +0100 Subject: [PATCH 253/263] add config file for usrpb210@band13 --- .../CONF/enb.band13.tm1.usrpb210.conf | 171 ++++++++++++++++++ 1 file changed, 171 insertions(+) create mode 100644 targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band13.tm1.usrpb210.conf diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band13.tm1.usrpb210.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band13.tm1.usrpb210.conf new file mode 100644 index 0000000000..69d8536217 --- /dev/null +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band13.tm1.usrpb210.conf @@ -0,0 +1,171 @@ +Active_eNBs = ( "eNB_Eurecom_LTEBox"); +# Asn1_verbosity, choice in: none, info, annoying +Asn1_verbosity = "none"; + +eNBs = +( + { + ////////// Identification parameters: + eNB_ID = 0xe00; + + cell_type = "CELL_MACRO_ENB"; + + eNB_name = "eNB_Eurecom_LTEBox"; + + // Tracking area code, 0x0000 and 0xfffe are reserved values + tracking_area_code = "1"; + + mobile_country_code = "208"; + + mobile_network_code = "95"; + + ////////// Physical parameters: + + component_carriers = ( + { + frame_type = "FDD"; + tdd_config = 3; + tdd_config_s = 0; + prefix_type = "NORMAL"; + eutra_band = 13; + downlink_frequency = 751000000L; + uplink_frequency_offset = 31000000; + Nid_cell = 0; + N_RB_DL = 25; + Nid_cell_mbsfn = 0; + nb_antennas_tx = 1; + nb_antennas_rx = 1; + tx_gain = 90; + rx_gain = 100; + prach_root = 0; + prach_config_index = 0; + prach_high_speed = "DISABLE"; + prach_zero_correlation = 1; + prach_freq_offset = 2; + pucch_delta_shift = 1; + pucch_nRB_CQI = 1; + pucch_nCS_AN = 0; + pucch_n1_AN = 32; + pdsch_referenceSignalPower = -15; + pdsch_p_b = 0; + pusch_n_SB = 1; + pusch_enable64QAM = "DISABLE"; + pusch_hoppingMode = "interSubFrame"; + pusch_hoppingOffset = 0; + pusch_groupHoppingEnabled = "ENABLE"; + pusch_groupAssignment = 0; + pusch_sequenceHoppingEnabled = "DISABLE"; + pusch_nDMRS1 = 1; + phich_duration = "NORMAL"; + phich_resource = "ONESIXTH"; + srs_enable = "DISABLE"; + /* srs_BandwidthConfig =; + srs_SubframeConfig =; + srs_ackNackST =; + srs_MaxUpPts =;*/ + + pusch_p0_Nominal = -86; + pusch_alpha = "AL1"; + pucch_p0_Nominal = -96; + msg3_delta_Preamble = 6; + pucch_deltaF_Format1 = "deltaF2"; + pucch_deltaF_Format1b = "deltaF3"; + pucch_deltaF_Format2 = "deltaF0"; + pucch_deltaF_Format2a = "deltaF0"; + pucch_deltaF_Format2b = "deltaF0"; + + rach_numberOfRA_Preambles = 64; + rach_preamblesGroupAConfig = "DISABLE"; + /* + rach_sizeOfRA_PreamblesGroupA = ; + rach_messageSizeGroupA = ; + rach_messagePowerOffsetGroupB = ; + */ + rach_powerRampingStep = 4; + rach_preambleInitialReceivedTargetPower = -108; + rach_preambleTransMax = 10; + rach_raResponseWindowSize = 10; + rach_macContentionResolutionTimer = 48; + rach_maxHARQ_Msg3Tx = 4; + + pcch_default_PagingCycle = 128; + pcch_nB = "oneT"; + bcch_modificationPeriodCoeff = 2; + ue_TimersAndConstants_t300 = 1000; + ue_TimersAndConstants_t301 = 1000; + ue_TimersAndConstants_t310 = 1000; + ue_TimersAndConstants_t311 = 10000; + ue_TimersAndConstants_n310 = 20; + ue_TimersAndConstants_n311 = 1; + + } + ); + + + srb1_parameters : + { + # timer_poll_retransmit = (ms) [5, 10, 15, 20,... 250, 300, 350, ... 500] + timer_poll_retransmit = 80; + + # timer_reordering = (ms) [0,5, ... 100, 110, 120, ... ,200] + timer_reordering = 35; + + # timer_reordering = (ms) [0,5, ... 250, 300, 350, ... ,500] + timer_status_prohibit = 0; + + # poll_pdu = [4, 8, 16, 32 , 64, 128, 256, infinity(>10000)] + poll_pdu = 4; + + # poll_byte = (kB) [25,50,75,100,125,250,375,500,750,1000,1250,1500,2000,3000,infinity(>10000)] + poll_byte = 99999; + + # max_retx_threshold = [1, 2, 3, 4 , 6, 8, 16, 32] + max_retx_threshold = 4; + } + + # ------- SCTP definitions + SCTP : + { + # Number of streams to use in input/output + SCTP_INSTREAMS = 2; + SCTP_OUTSTREAMS = 2; + }; + + + ////////// MME parameters: + mme_ip_address = ( { ipv4 = "192.168.12.62"; + ipv6 = "192:168:30::17"; + active = "yes"; + preference = "ipv4"; + } + ); + + NETWORK_INTERFACES : + { + ENB_INTERFACE_NAME_FOR_S1_MME = "eth4"; + ENB_IPV4_ADDRESS_FOR_S1_MME = "192.168.12.242/24"; + + ENB_INTERFACE_NAME_FOR_S1U = "eth4"; + ENB_IPV4_ADDRESS_FOR_S1U = "192.168.12.242/24"; + ENB_PORT_FOR_S1U = 2152; # Spec 2152 + }; + + log_config : + { + global_log_level ="info"; + global_log_verbosity ="medium"; + hw_log_level ="info"; + hw_log_verbosity ="medium"; + phy_log_level ="info"; + phy_log_verbosity ="medium"; + mac_log_level ="info"; + mac_log_verbosity ="high"; + rlc_log_level ="info"; + rlc_log_verbosity ="medium"; + pdcp_log_level ="info"; + pdcp_log_verbosity ="medium"; + rrc_log_level ="info"; + rrc_log_verbosity ="medium"; + }; + } +); From f261adc74fcc427afabcaeba43b5c90358d6790a Mon Sep 17 00:00:00 2001 From: Aikaterini Date: Fri, 19 Feb 2016 13:30:20 +0100 Subject: [PATCH 254/263] add config file for rrh+usrp@band13 --- .../CONF/enb.band13.tm1.rrh.usrpb210.conf | 190 ++++++++++++++++++ 1 file changed, 190 insertions(+) create mode 100644 targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band13.tm1.rrh.usrpb210.conf diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band13.tm1.rrh.usrpb210.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band13.tm1.rrh.usrpb210.conf new file mode 100644 index 0000000000..98226144ab --- /dev/null +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band13.tm1.rrh.usrpb210.conf @@ -0,0 +1,190 @@ +Active_eNBs = ( "eNB_Eurecom_LTEBox"); +# Asn1_verbosity, choice in: none, info, annoying +Asn1_verbosity = "none"; + +eNBs = +( + { + ////////// Identification parameters: + eNB_ID = 0xe00; + + cell_type = "CELL_MACRO_ENB"; + + eNB_name = "eNB_Eurecom_LTEBox"; + + // Tracking area code, 0x0000 and 0xfffe are reserved values + tracking_area_code = "1"; + + mobile_country_code = "208"; + + mobile_network_code = "95"; + + ////////// Physical parameters: + + component_carriers = ( + { + frame_type = "FDD"; + tdd_config = 3; + tdd_config_s = 0; + prefix_type = "NORMAL"; + eutra_band = 13; + downlink_frequency = 751000000L; + uplink_frequency_offset = 31000000; + Nid_cell = 0; + N_RB_DL = 25; + Nid_cell_mbsfn = 0; + nb_antennas_tx = 1; + nb_antennas_rx = 1; + tx_gain = 90; + rx_gain = 100; + prach_root = 0; + prach_config_index = 0; + prach_high_speed = "DISABLE"; + prach_zero_correlation = 1; + prach_freq_offset = 2; + pucch_delta_shift = 1; + pucch_nRB_CQI = 1; + pucch_nCS_AN = 0; + pucch_n1_AN = 32; + pdsch_referenceSignalPower = -15; + pdsch_p_b = 0; + pusch_n_SB = 1; + pusch_enable64QAM = "DISABLE"; + pusch_hoppingMode = "interSubFrame"; + pusch_hoppingOffset = 0; + pusch_groupHoppingEnabled = "ENABLE"; + pusch_groupAssignment = 0; + pusch_sequenceHoppingEnabled = "DISABLE"; + pusch_nDMRS1 = 1; + phich_duration = "NORMAL"; + phich_resource = "ONESIXTH"; + srs_enable = "DISABLE"; + /* srs_BandwidthConfig =; + srs_SubframeConfig =; + srs_ackNackST =; + srs_MaxUpPts =;*/ + + pusch_p0_Nominal = -86; + pusch_alpha = "AL1"; + pucch_p0_Nominal = -96; + msg3_delta_Preamble = 6; + pucch_deltaF_Format1 = "deltaF2"; + pucch_deltaF_Format1b = "deltaF3"; + pucch_deltaF_Format2 = "deltaF0"; + pucch_deltaF_Format2a = "deltaF0"; + pucch_deltaF_Format2b = "deltaF0"; + + rach_numberOfRA_Preambles = 64; + rach_preamblesGroupAConfig = "DISABLE"; + /* + rach_sizeOfRA_PreamblesGroupA = ; + rach_messageSizeGroupA = ; + rach_messagePowerOffsetGroupB = ; + */ + rach_powerRampingStep = 4; + rach_preambleInitialReceivedTargetPower = -108; + rach_preambleTransMax = 10; + rach_raResponseWindowSize = 10; + rach_macContentionResolutionTimer = 48; + rach_maxHARQ_Msg3Tx = 4; + + pcch_default_PagingCycle = 128; + pcch_nB = "oneT"; + bcch_modificationPeriodCoeff = 2; + ue_TimersAndConstants_t300 = 1000; + ue_TimersAndConstants_t301 = 1000; + ue_TimersAndConstants_t310 = 1000; + ue_TimersAndConstants_t311 = 10000; + ue_TimersAndConstants_n310 = 20; + ue_TimersAndConstants_n311 = 1; + + } + ); + + + srb1_parameters : + { + # timer_poll_retransmit = (ms) [5, 10, 15, 20,... 250, 300, 350, ... 500] + timer_poll_retransmit = 80; + + # timer_reordering = (ms) [0,5, ... 100, 110, 120, ... ,200] + timer_reordering = 35; + + # timer_reordering = (ms) [0,5, ... 250, 300, 350, ... ,500] + timer_status_prohibit = 0; + + # poll_pdu = [4, 8, 16, 32 , 64, 128, 256, infinity(>10000)] + poll_pdu = 4; + + # poll_byte = (kB) [25,50,75,100,125,250,375,500,750,1000,1250,1500,2000,3000,infinity(>10000)] + poll_byte = 99999; + + # max_retx_threshold = [1, 2, 3, 4 , 6, 8, 16, 32] + max_retx_threshold = 4; + } + + # ------- SCTP definitions + SCTP : + { + # Number of streams to use in input/output + SCTP_INSTREAMS = 2; + SCTP_OUTSTREAMS = 2; + }; + + + ////////// MME parameters: + mme_ip_address = ( { ipv4 = "192.168.12.62"; + ipv6 = "192:168:30::17"; + active = "yes"; + preference = "ipv4"; + } + ); + +rrh_gw_config = ( + { + local_if_name = "eth0"; + #remote_address = "169.254.10.158"; + #local_address = "169.254.8.15"; + remote_address = "74:d4:35:cc:88:45"; + local_address = "98:90:96:df:66:07"; + local_port = 50000; #for raw option local port must be the same to remote + remote_port = 50000; + rrh_gw_active = "yes"; + tr_preference = "raw"; + rf_preference = "usrp_b200"; + iq_txshift = 5; + tx_sample_advance = 70; + tx_scheduling_advance = 9; + +} +); + + NETWORK_INTERFACES : + { + ENB_INTERFACE_NAME_FOR_S1_MME = "eth4"; + ENB_IPV4_ADDRESS_FOR_S1_MME = "192.168.12.242/24"; + + ENB_INTERFACE_NAME_FOR_S1U = "eth4"; + ENB_IPV4_ADDRESS_FOR_S1U = "192.168.12.242/24"; + ENB_PORT_FOR_S1U = 2152; # Spec 2152 + }; + + log_config : + { + global_log_level ="info"; + global_log_verbosity ="medium"; + hw_log_level ="info"; + hw_log_verbosity ="medium"; + phy_log_level ="info"; + phy_log_verbosity ="medium"; + mac_log_level ="info"; + mac_log_verbosity ="high"; + rlc_log_level ="info"; + rlc_log_verbosity ="medium"; + pdcp_log_level ="info"; + pdcp_log_verbosity ="medium"; + rrc_log_level ="info"; + rrc_log_verbosity ="medium"; + }; + } +); From eb48479b37b28d8a82689a017771771beba78615 Mon Sep 17 00:00:00 2001 From: Navid Nikaein Date: Fri, 19 Feb 2016 15:12:41 +0100 Subject: [PATCH 255/263] check the rf_config_file name, and ignore if it is null --- targets/RT/USER/rrh_gw.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/targets/RT/USER/rrh_gw.c b/targets/RT/USER/rrh_gw.c index 3def754e3d..8084644b85 100644 --- a/targets/RT/USER/rrh_gw.c +++ b/targets/RT/USER/rrh_gw.c @@ -299,11 +299,17 @@ static void get_options(int argc, char *argv[]) { loopback_flag=1; break; case 'f': - if (strlen(optarg)<=1024) - strcpy(rf_config_file,optarg); - else { - printf("Configuration filename is too long\n"); - exit(-1); + if (optarg){ + if ((strcmp("null", optarg) == 0) || (strcmp("NULL", optarg) == 0)) { + printf("no configuration filename is provided\n"); + } + else if (strlen(optarg)<=1024){ + // rf_config_file = strdup(optarg); + strcpy(rf_config_file,optarg); + }else { + printf("Configuration filename is too long\n"); + exit(-1); + } } break; case 't': From 3af10bca146ee7bef52d60f21c8dcfaa35a05f3c Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Sun, 21 Feb 2016 14:46:15 +0100 Subject: [PATCH 256/263] config files for band13 --- ...sodera_lowband_Wrx_10MHz_rx19dB_txfull.ini | 1128 +++++++++++++++++ .../CONF/enb.band13.tm1.50PRB.lmssdr.conf | 171 +++ .../CONF/enb.band13.tm1.lmssdr.conf | 171 +++ .../CONF/enb.band7.tm1.50PRB.lmssdr.conf | 4 +- 4 files changed, 1472 insertions(+), 2 deletions(-) create mode 100644 targets/ARCH/LMSSDR/enb_sodera_lowband_Wrx_10MHz_rx19dB_txfull.ini create mode 100644 targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band13.tm1.50PRB.lmssdr.conf create mode 100644 targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band13.tm1.lmssdr.conf diff --git a/targets/ARCH/LMSSDR/enb_sodera_lowband_Wrx_10MHz_rx19dB_txfull.ini b/targets/ARCH/LMSSDR/enb_sodera_lowband_Wrx_10MHz_rx19dB_txfull.ini new file mode 100644 index 0000000000..a0793ad395 --- /dev/null +++ b/targets/ARCH/LMSSDR/enb_sodera_lowband_Wrx_10MHz_rx19dB_txfull.ini @@ -0,0 +1,1128 @@ +[reference_clocks] +sxr_ref_clk_mhz=30.72 +sxt_ref_clk_mhz=30.72 +[lms7002_registers_b] +0x03A0=0x0000 +0x054E=0x0000 +0x02D0=0x0000 +0x0386=0x0000 +0x054F=0x0000 +0x0389=0x0000 +0x040F=0x0000 +0x04E3=0x0000 +0x0385=0x0000 +0x0315=0x0000 +0x0384=0x0000 +0x0382=0x0000 +0x0288=0x0000 +0x0381=0x0000 +0x0366=0x0000 +0x0365=0x0000 +0x0364=0x0000 +0x0325=0x0000 +0x035E=0x0000 +0x035D=0x0000 +0x0442=0x0000 +0x0452=0x0000 +0x0299=0x0000 +0x0359=0x0000 +0x029D=0x0000 +0x04A3=0x0000 +0x040E=0x0000 +0x0316=0x0000 +0x030D=0x0000 +0x0356=0x0000 +0x0348=0x0000 +0x0498=0x0000 +0x0490=0x0000 +0x02CD=0x0000 +0x050D=0x0000 +0x0353=0x0000 +0x0351=0x0000 +0x048F=0x0000 +0x0445=0x0000 +0x0350=0x0000 +0x03A6=0x0000 +0x0293=0x0000 +0x034E=0x0000 +0x035C=0x0000 +0x034D=0x0000 +0x034B=0x0000 +0x011A=0x2E02 +0x0455=0x0000 +0x034A=0x0000 +0x035B=0x0000 +0x0505=0x0000 +0x0345=0x0000 +0x035F=0x0000 +0x0597=0x0000 +0x0586=0x0000 +0x0484=0x0000 +0x02C8=0x0000 +0x035A=0x0000 +0x0561=0x0000 +0x0344=0x0000 +0x0343=0x0000 +0x0342=0x0000 +0x0380=0x0000 +0x0327=0x0000 +0x025E=0x0000 +0x04DA=0x0000 +0x04C2=0x0000 +0x028C=0x0000 +0x0352=0x0000 +0x059C=0x0000 +0x04DD=0x0000 +0x028A=0x0000 +0x0289=0x0000 +0x031A=0x0000 +0x0363=0x0000 +0x0396=0x0000 +0x0284=0x0000 +0x010C=0x88FD +0x044C=0x0000 +0x0355=0x0000 +0x025C=0x0000 +0x0515=0x0000 +0x0361=0x0000 +0x0205=0x0000 +0x025B=0x0000 +0x04C5=0x0000 +0x04E2=0x0000 +0x025A=0x0000 +0x0256=0x0000 +0x0240=0x0020 +0x0367=0x0000 +0x05A3=0x0000 +0x0502=0x0000 +0x0258=0x0000 +0x0255=0x0000 +0x040C=0x0000 +0x028B=0x0000 +0x0253=0x0000 +0x024E=0x0000 +0x0346=0x0000 +0x0280=0x0000 +0x0285=0x0000 +0x024A=0x0000 +0x0261=0x0000 +0x0249=0x0000 +0x04CD=0x0000 +0x040A=0x0000 +0x0556=0x0000 +0x0243=0x0000 +0x051D=0x0000 +0x0494=0x0000 +0x024C=0x0000 +0x02DC=0x0000 +0x038F=0x0000 +0x0241=0x0000 +0x0488=0x0000 +0x0251=0x0000 +0x020B=0x4000 +0x0108=0x9442 +0x04A0=0x0000 +0x0116=0x8180 +0x02CC=0x0000 +0x039A=0x0000 +0x0112=0xC0E6 +0x0307=0x0000 +0x038C=0x0000 +0x0282=0x0000 +0x0321=0x0000 +0x0507=0x0000 +0x0483=0x0000 +0x0201=0x07FF +0x02E1=0x0000 +0x0517=0x0000 +0x0481=0x0000 +0x02D5=0x0000 +0x0259=0x0000 +0x0527=0x0000 +0x02DD=0x0000 +0x0209=0x0000 +0x0297=0x0000 +0x0400=0x0081 +0x0104=0x0088 +0x0103=0x0A12 +0x0347=0x0000 +0x02D8=0x0000 +0x0457=0x0000 +0x0306=0x0000 +0x02D1=0x0000 +0x04C8=0x0000 +0x0546=0x0000 +0x0440=0x0020 +0x045E=0x0000 +0x031D=0x0000 +0x039C=0x0000 +0x02D2=0x0000 +0x010E=0x2040 +0x02A0=0x0000 +0x0544=0x0000 +0x029C=0x0000 +0x055A=0x0000 +0x0295=0x0000 +0x02CF=0x0000 +0x04D1=0x0000 +0x0291=0x0000 +0x02DF=0x0000 +0x0290=0x0000 +0x020A=0x0080 +0x0102=0x3180 +0x0120=0xB9FF +0x0388=0x0000 +0x0318=0x0000 +0x02A7=0x0000 +0x0200=0x0081 +0x0594=0x0000 +0x02C5=0x0000 +0x028D=0x0000 +0x02A1=0x0000 +0x0362=0x0000 +0x038A=0x0000 +0x0395=0x0000 +0x058D=0x0000 +0x02D7=0x0000 +0x0305=0x0000 +0x0393=0x0000 +0x0398=0x0000 +0x0408=0x0000 +0x039B=0x0000 +0x049E=0x0000 +0x02DB=0x0000 +0x0357=0x0000 +0x02C2=0x0000 +0x0514=0x0000 +0x051C=0x0000 +0x03A2=0x0000 +0x03A4=0x0000 +0x03A3=0x0000 +0x0493=0x0000 +0x0454=0x0000 +0x0448=0x0000 +0x0397=0x0000 +0x02E3=0x0000 +0x049C=0x0000 +0x040D=0x0000 +0x0281=0x0000 +0x048C=0x0000 +0x049A=0x0000 +0x0119=0x18CB +0x010F=0x3042 +0x02A6=0x0000 +0x0257=0x0000 +0x04D6=0x0000 +0x04A6=0x0000 +0x0324=0x0000 +0x038E=0x0000 +0x02E7=0x0000 +0x034F=0x0000 +0x04E0=0x0000 +0x0123=0x267B +0x0497=0x0000 +0x0459=0x0000 +0x0394=0x0000 +0x04A5=0x0000 +0x04D9=0x0000 +0x0304=0x0000 +0x04D5=0x0000 +0x0508=0x0000 +0x0443=0x0000 +0x0301=0x0000 +0x0548=0x0000 +0x04D2=0x0000 +0x0592=0x0000 +0x0591=0x0000 +0x04C7=0x0000 +0x049D=0x0000 +0x029A=0x0000 +0x051F=0x0000 +0x0309=0x0000 +0x0585=0x0000 +0x03A5=0x0000 +0x02D3=0x0000 +0x0451=0x0000 +0x0390=0x0000 +0x0562=0x0000 +0x02C4=0x0000 +0x029E=0x0000 +0x031E=0x0000 +0x04C0=0x0000 +0x04DC=0x0000 +0x04DE=0x0000 +0x058B=0x0000 +0x04DB=0x0000 +0x04D0=0x0000 +0x0492=0x0000 +0x04A1=0x0000 +0x054B=0x0000 +0x02C7=0x0000 +0x05A0=0x0000 +0x044B=0x0000 +0x0100=0x3409 +0x04CA=0x0000 +0x0446=0x0000 +0x02E4=0x0000 +0x04E4=0x0000 +0x04C3=0x0000 +0x0496=0x0000 +0x04CF=0x0000 +0x025F=0x0000 +0x04D4=0x0000 +0x0504=0x0000 +0x04CE=0x0000 +0x02DE=0x0000 +0x0399=0x0000 +0x050C=0x0000 +0x02A5=0x0000 +0x04CC=0x0000 +0x03A1=0x0000 +0x04E1=0x0000 +0x02A2=0x0000 +0x040B=0x7FFF +0x0283=0x0000 +0x048E=0x0000 +0x0580=0x0000 +0x0409=0x0000 +0x039F=0x0000 +0x0248=0x0000 +0x048B=0x0000 +0x0358=0x0000 +0x0589=0x0000 +0x038D=0x0000 +0x0487=0x0000 +0x0510=0x0000 +0x0302=0x0000 +0x0486=0x0000 +0x045F=0x0000 +0x0480=0x0000 +0x0567=0x0000 +0x02DA=0x0000 +0x045A=0x0000 +0x0254=0x0000 +0x0405=0x0000 +0x0387=0x0000 +0x0458=0x0000 +0x0314=0x0000 +0x0360=0x0000 +0x0559=0x0000 +0x0456=0x0000 +0x0453=0x0000 +0x02E2=0x0000 +0x044D=0x0000 +0x0441=0x0000 +0x02C3=0x0000 +0x04C1=0x0000 +0x04D3=0x0000 +0x0444=0x0000 +0x0207=0x0000 +0x04C6=0x0000 +0x0296=0x0000 +0x0555=0x0000 +0x0349=0x0000 +0x0109=0x61C1 +0x04A2=0x0000 +0x0447=0x0000 +0x0460=0x0000 +0x048D=0x0000 +0x059A=0x0000 +0x0407=0x0000 +0x02C0=0x0000 +0x0499=0x0000 +0x0543=0x0000 +0x04C9=0x0000 +0x02CA=0x0000 +0x0404=0x0000 +0x0560=0x0000 +0x02C1=0x0000 +0x04D8=0x0000 +0x0403=0x0000 +0x0491=0x0000 +0x029B=0x0000 +0x04C4=0x0000 +0x010D=0x009E +0x0402=0x07FF +0x055E=0x0000 +0x03A7=0x0000 +0x0520=0x0000 +0x0392=0x0000 +0x030B=0x0000 +0x0588=0x0000 +0x0308=0x0000 +0x048A=0x0000 +0x044A=0x0000 +0x04A4=0x0000 +0x0300=0x0000 +0x0587=0x0000 +0x044E=0x0000 +0x055B=0x0000 +0x02E5=0x0000 +0x0114=0x008D +0x0323=0x0000 +0x0320=0x0000 +0x0503=0x0000 +0x0513=0x0000 +0x0319=0x0000 +0x0260=0x0000 +0x0549=0x0000 +0x0552=0x0000 +0x0509=0x0000 +0x0521=0x0000 +0x0286=0x0000 +0x04D7=0x0000 +0x059E=0x0000 +0x058F=0x0000 +0x0557=0x0000 +0x0322=0x0000 +0x059B=0x0000 +0x049F=0x0000 +0x0522=0x0000 +0x0545=0x0000 +0x0551=0x0000 +0x0312=0x0000 +0x055D=0x0000 +0x0298=0x0000 +0x055F=0x0000 +0x011D=0x9555 +0x039E=0x0000 +0x0547=0x0000 +0x0598=0x0000 +0x0449=0x0000 +0x0564=0x0000 +0x0242=0x0000 +0x0525=0x0000 +0x0523=0x0000 +0x0565=0x0000 +0x0124=0x0000 +0x0563=0x0000 +0x024D=0x0000 +0x05A5=0x0000 +0x0566=0x0000 +0x030A=0x0000 +0x029F=0x0000 +0x054C=0x0000 +0x0582=0x0000 +0x0599=0x0000 +0x0511=0x0000 +0x0506=0x0000 +0x0595=0x0000 +0x0584=0x0000 +0x058C=0x0000 +0x05A6=0x0000 +0x051E=0x0000 +0x050F=0x0000 +0x0590=0x0000 +0x0596=0x0000 +0x05A7=0x0000 +0x058A=0x0000 +0x059D=0x0000 +0x0485=0x0000 +0x0581=0x0000 +0x045D=0x0000 +0x0245=0x0000 +0x0310=0x0000 +0x058E=0x0000 +0x05A2=0x0000 +0x054D=0x0000 +0x020C=0x7FFF +0x031F=0x0000 +0x0292=0x0000 +0x059F=0x0000 +0x0583=0x0000 +0x0317=0x0000 +0x0244=0x0000 +0x0554=0x0000 +0x0593=0x0000 +0x05A4=0x0000 +0x02A3=0x0000 +0x0553=0x0000 +0x0542=0x0000 +0x0519=0x0000 +0x024F=0x0000 +0x0524=0x0000 +0x0518=0x0000 +0x0354=0x0000 +0x0526=0x0000 +0x031B=0x0000 +0x050E=0x0000 +0x0516=0x0000 +0x02CB=0x0000 +0x0250=0x0000 +0x031C=0x0000 +0x028F=0x0000 +0x051A=0x0000 +0x055C=0x0000 +0x050A=0x0000 +0x050B=0x0000 +0x04E7=0x0000 +0x04E6=0x0000 +0x04E5=0x0000 +0x0512=0x0000 +0x0206=0x0000 +0x0550=0x0000 +0x030E=0x0000 +0x0203=0x0000 +0x0482=0x0000 +0x0541=0x0000 +0x0122=0x033F +0x0110=0x0BF4 +0x0204=0x0000 +0x0252=0x0000 +0x011E=0x05DC +0x049B=0x0000 +0x0294=0x0000 +0x011C=0xAD41 +0x02D6=0x0000 +0x0311=0x0000 +0x0117=0x280C +0x02A4=0x0000 +0x0540=0x0000 +0x02E0=0x0000 +0x0118=0x018C +0x0489=0x0000 +0x04A7=0x0000 +0x0101=0x7800 +0x0558=0x0000 +0x02C6=0x0000 +0x05A1=0x0000 +0x02C9=0x0000 +0x039D=0x0000 +0x0500=0x0000 +0x0450=0x0000 +0x011F=0x3680 +0x030C=0x0000 +0x04DF=0x0000 +0x0106=0x3182 +0x028E=0x0000 +0x0326=0x0000 +0x0113=0x03C3 +0x04CB=0x0000 +0x0391=0x0000 +0x0105=0x0007 +0x02D9=0x0000 +0x02CE=0x0000 +0x044F=0x0000 +0x038B=0x0000 +0x02D4=0x0000 +0x0107=0x318C +0x0495=0x0000 +0x0246=0x0000 +0x0303=0x0000 +0x02E6=0x0000 +0x045B=0x0000 +0x0340=0x0000 +0x0208=0x0070 +0x0111=0x0083 +0x0247=0x0000 +0x024B=0x0000 +0x045C=0x0000 +0x0383=0x0000 +0x0202=0x07FF +0x054A=0x0000 +0x0401=0x07FF +0x0341=0x0000 +0x0287=0x0000 +0x034C=0x0000 +0x0501=0x0000 +0x030F=0x0000 +0x025D=0x0000 +0x0406=0x0000 +0x0313=0x0000 +0x010A=0x104C +0x0461=0x0000 +0x051B=0x0000 +0x0121=0x356A +0x0115=0x0009 +[lms7002_registers_a] +0x0107=0x318C +0x02D4=0x0000 +0x0082=0x8001 +0x0209=0x0000 +0x02CA=0x0000 +0x04C9=0x0000 +0x0120=0xB9FF +0x0388=0x0000 +0x029D=0x0000 +0x04A3=0x0000 +0x0208=0x0170 +0x0340=0x0000 +0x0094=0x0000 +0x0244=0x0000 +0x0317=0x0000 +0x00A9=0x8000 +0x0115=0x0009 +0x039A=0x0000 +0x0112=0x3171 +0x048C=0x0000 +0x0023=0x5550 +0x0587=0x1D10 +0x04C0=0x0000 +0x031E=0x0000 +0x0205=0x0000 +0x0361=0x0000 +0x051F=0xAB08 +0x029A=0x0000 +0x0396=0x0000 +0x0284=0x0000 +0x02CE=0x0000 +0x02D9=0x0000 +0x038B=0x0000 +0x044F=0x0000 +0x0367=0x0000 +0x0240=0x0028 +0x05A3=0x0000 +0x0105=0x0007 +0x009B=0x6565 +0x0400=0x0101 +0x02DB=0x0000 +0x0357=0x0000 +0x0104=0x0088 +0x0103=0x0A12 +0x0457=0x0000 +0x0347=0x0000 +0x02D8=0x0000 +0x010C=0x8865 +0x0086=0x4101 +0x0202=0x0794 +0x0383=0x0000 +0x020B=0x4000 +0x0108=0xFC26 +0x0098=0x0000 +0x0117=0x100C +0x0027=0x05E4 +0x00A7=0x6565 +0x024A=0x0000 +0x0029=0x0101 +0x00AD=0x03FF +0x0540=0x5009 +0x02A4=0x0000 +0x02DE=0x0000 +0x002E=0x0000 +0x0261=0x0000 +0x00AB=0x0040 +0x0564=0x0000 +0x00A8=0x0000 +0x0517=0xC89D +0x0481=0x0000 +0x02C1=0x0000 +0x0301=0x0000 +0x00A5=0x6565 +0x0515=0x2E45 +0x025C=0x0000 +0x009F=0x658C +0x0519=0x4049 +0x054B=0xF7A3 +0x02C7=0x0000 +0x038C=0x0000 +0x0307=0x0000 +0x0282=0x0000 +0x0289=0x0000 +0x011C=0xAD41 +0x0562=0xF524 +0x0025=0x0101 +0x02CC=0x0000 +0x0116=0x8180 +0x0597=0xFDFB +0x035F=0x0000 +0x002F=0x3840 +0x0589=0xEA5F +0x00A2=0x6565 +0x0099=0x6565 +0x0310=0x0000 +0x040C=0x40F8 +0x028B=0x0000 +0x0253=0x0000 +0x00AC=0x2000 +0x002D=0xFFFF +0x00A6=0x0001 +0x054D=0xF7A3 +0x002C=0x0000 +0x0249=0x0000 +0x04CD=0x0000 +0x0401=0x07FF +0x00A4=0x6565 +0x054A=0x8184 +0x038F=0x0000 +0x008C=0x267B +0x0241=0x0000 +0x0356=0x0000 +0x00A1=0x6565 +0x0260=0x0000 +0x0453=0x0000 +0x008A=0x0491 +0x048F=0x0000 +0x0445=0x0000 +0x0350=0x0000 +0x00AA=0x0000 +0x034C=0x0000 +0x0501=0xFDFB +0x0490=0x0000 +0x02CD=0x0000 +0x050D=0x0F45 +0x0353=0x0000 +0x0024=0x50D8 +0x04E5=0x0000 +0x0512=0x196B +0x0247=0x0000 +0x045C=0x0000 +0x024B=0x0000 +0x0395=0x0000 +0x011F=0x3680 +0x039D=0x0000 +0x0500=0xF61D +0x02C9=0x0000 +0x05A1=0x0000 +0x02A6=0x0000 +0x0119=0x18DF +0x010F=0x3042 +0x04CB=0x0000 +0x0391=0x0000 +0x0113=0x03C3 +0x0326=0x0000 +0x028E=0x0000 +0x0106=0x3182 +0x0524=0x3347 +0x009D=0x6565 +0x0294=0x0000 +0x0026=0x0101 +0x0110=0x0BFF +0x0122=0x033F +0x0381=0x0000 +0x009C=0x658C +0x05A0=0x0000 +0x0482=0x0000 +0x030E=0x0000 +0x0203=0x2F99 +0x0095=0x0000 +0x0111=0x0099 +0x0256=0x0000 +0x0089=0x0048 +0x0085=0x0001 +0x0088=0x04F0 +0x0459=0x0000 +0x0394=0x0000 +0x010E=0x0285 +0x02A0=0x0000 +0x002B=0x4032 +0x039C=0x0000 +0x02D2=0x0000 +0x0581=0xC89D +0x045D=0x0000 +0x0245=0x0000 +0x002A=0x0086 +0x0118=0x018C +0x02E0=0x0000 +0x0489=0x0000 +0x04A7=0x0000 +0x039E=0x0000 +0x011D=0x2AAA +0x02E1=0x0000 +0x0259=0x0000 +0x02D5=0x0000 +0x051D=0x4F91 +0x0243=0x0000 +0x0556=0xA2B5 +0x040A=0x1000 +0x05A2=0x0000 +0x020C=0x8000 +0x020A=0x0080 +0x0102=0x3180 +0x034F=0x0000 +0x0303=0x0000 +0x0306=0x0000 +0x0255=0x0000 +0x0300=0x0000 +0x044E=0x0000 +0x0309=0x0000 +0x0585=0xDAA2 +0x0527=0xACB9 +0x044A=0x0000 +0x04A4=0x0000 +0x048A=0x0000 +0x0392=0x0000 +0x030B=0x0000 +0x05A7=0x0000 +0x0252=0x0000 +0x0204=0xC016 +0x0308=0x0000 +0x0588=0xE6C7 +0x0321=0x0000 +0x0507=0xFCFE +0x0312=0x0000 +0x050B=0xF5EF +0x0360=0x0000 +0x0021=0x0E9F +0x04C2=0x0000 +0x030D=0x0000 +0x040E=0x0003 +0x0316=0x0000 +0x031F=0x0000 +0x030C=0x0000 +0x04DF=0x0000 +0x0318=0x0000 +0x0250=0x0000 +0x02CB=0x0000 +0x045E=0x0000 +0x0440=0x0024 +0x031D=0x0000 +0x058D=0xF5EF +0x02D7=0x0000 +0x0380=0x0000 +0x0342=0x0000 +0x0343=0x0000 +0x0566=0x0906 +0x0345=0x0000 +0x049C=0x0000 +0x02E3=0x0000 +0x0397=0x0000 +0x035B=0x0000 +0x0505=0x00D8 +0x028D=0x0000 +0x02A1=0x0000 +0x028F=0x0000 +0x031C=0x0000 +0x031A=0x0000 +0x0363=0x0000 +0x0596=0x0A94 +0x0354=0x0000 +0x0518=0xEFF2 +0x035C=0x0000 +0x034D=0x0000 +0x0344=0x0000 +0x0561=0xAB08 +0x0096=0x0000 +0x010D=0x01DC +0x04C4=0x0000 +0x0351=0x0000 +0x0311=0x0000 +0x02D6=0x0000 +0x02D1=0x0000 +0x0546=0x8D44 +0x04C8=0x0000 +0x048B=0x0000 +0x0358=0x0000 +0x0522=0xDB10 +0x049F=0x0000 +0x034A=0x0000 +0x0455=0x0000 +0x0359=0x0000 +0x03A4=0x0000 +0x03A3=0x0000 +0x0341=0x0000 +0x0287=0x0000 +0x04DA=0x0000 +0x025E=0x0000 +0x0580=0xEFF2 +0x0409=0x0000 +0x059A=0x0000 +0x048D=0x0000 +0x0514=0xE7E2 +0x039B=0x0000 +0x0101=0x7800 +0x0558=0x5009 +0x02C6=0x0000 +0x051B=0xB77F +0x0313=0x0000 +0x010A=0x104C +0x0461=0x0000 +0x0406=0x0000 +0x030F=0x0000 +0x025D=0x0000 +0x034B=0x0000 +0x011A=0x2E14 +0x029F=0x0000 +0x030A=0x0000 +0x034E=0x0000 +0x0293=0x0000 +0x03A6=0x0000 +0x0560=0x174B +0x0404=0x0000 +0x00A0=0x6565 +0x0547=0xD7B7 +0x0454=0x0000 +0x0448=0x0000 +0x0327=0x0000 +0x0305=0x0000 +0x0393=0x0000 +0x0510=0xE6C7 +0x0302=0x0000 +0x0486=0x0000 +0x045F=0x0000 +0x0365=0x0000 +0x048E=0x0000 +0x0022=0x07FF +0x0283=0x0000 +0x044B=0x0000 +0x045A=0x0000 +0x02DA=0x0000 +0x04E4=0x0000 +0x02E4=0x0000 +0x03A5=0x0000 +0x040B=0x000F +0x0366=0x0000 +0x0443=0x0000 +0x0508=0xEF99 +0x00A3=0x6565 +0x02E2=0x0000 +0x044D=0x0000 +0x0314=0x0000 +0x0458=0x0000 +0x0493=0x0000 +0x0346=0x0000 +0x024E=0x0000 +0x055E=0xDB10 +0x0402=0x07D9 +0x0384=0x0000 +0x02E6=0x0000 +0x045B=0x0000 +0x0480=0x0000 +0x0567=0x4049 +0x04CA=0x0000 +0x0446=0x0000 +0x0447=0x0000 +0x0460=0x0000 +0x0559=0xACB9 +0x0456=0x0000 +0x0441=0x0000 +0x0444=0x0000 +0x0390=0x0000 +0x0451=0x0000 +0x049E=0x0000 +0x0324=0x0000 +0x02E7=0x0000 +0x038E=0x0000 +0x0403=0x0013 +0x04D8=0x0000 +0x029B=0x0000 +0x0491=0x0000 +0x03A1=0x0000 +0x04E1=0x0000 +0x02A2=0x0000 +0x051C=0x0000 +0x03A2=0x0000 +0x0407=0x0000 +0x0258=0x0000 +0x0502=0x0A94 +0x038A=0x0000 +0x0362=0x0000 +0x028C=0x0000 +0x0352=0x0000 +0x0385=0x0000 +0x0315=0x0000 +0x040D=0x0000 +0x039F=0x0000 +0x0248=0x0000 +0x0405=0x0000 +0x0254=0x0000 +0x0398=0x0000 +0x0408=0x0000 +0x0487=0x0000 +0x038D=0x0000 +0x035E=0x0000 +0x03A7=0x0000 +0x0520=0x174B +0x0449=0x0000 +0x02C8=0x0000 +0x035A=0x0000 +0x0387=0x0000 +0x0386=0x0000 +0x0452=0x0000 +0x0299=0x0000 +0x0084=0x0400 +0x0498=0x0000 +0x0348=0x0000 +0x02D0=0x0000 +0x054E=0x8184 +0x03A0=0x0000 +0x009A=0x658C +0x055D=0xA6B5 +0x0298=0x0000 +0x0364=0x0000 +0x0081=0x0000 +0x0325=0x0000 +0x040F=0x43E4 +0x04E3=0x0000 +0x050E=0x17DC +0x0516=0x150F +0x0389=0x0000 +0x054F=0x18C9 +0x0304=0x0000 +0x04D5=0x0000 +0x059B=0x0000 +0x0322=0x0000 +0x0442=0x0000 +0x035D=0x0000 +0x0492=0x0000 +0x04A1=0x0000 +0x0382=0x0000 +0x0288=0x0000 +0x0296=0x0000 +0x0555=0xBD96 +0x0349=0x0000 +0x0484=0x0000 +0x0586=0x196B +0x0281=0x0000 +0x0200=0x0301 +0x0594=0xF40D +0x02C5=0x0000 +0x0319=0x0000 +0x0121=0x3652 +0x025B=0x0000 +0x0290=0x0000 +0x02DF=0x0000 +0x0291=0x0000 +0x029C=0x0000 +0x008B=0x2756 +0x02A3=0x0000 +0x05A4=0x0000 +0x02A7=0x0000 +0x0483=0x0000 +0x0201=0x07FF +0x02C2=0x0000 +0x02C4=0x0000 +0x0207=0x0000 +0x04C6=0x0000 +0x0093=0x0000 +0x02D3=0x0000 +0x0494=0x0000 +0x04CF=0x0000 +0x025F=0x0000 +0x0251=0x0000 +0x0488=0x0000 +0x0496=0x0000 +0x04C3=0x0000 +0x0100=0xB409 +0x04CC=0x0000 +0x02A5=0x0000 +0x0257=0x0000 +0x04D6=0x0000 +0x04A6=0x0000 +0x049A=0x0000 +0x049B=0x0000 +0x0097=0x0000 +0x011E=0x061D +0x0285=0x0000 +0x0280=0x0000 +0x0020=0xFFFD +0x02DD=0x0000 +0x0297=0x0000 +0x044C=0x0000 +0x0355=0x0000 +0x04A0=0x0000 +0x02CF=0x0000 +0x04D1=0x0000 +0x0526=0xBE2A +0x0092=0x0001 +0x031B=0x0000 +0x0541=0x4C24 +0x0543=0xBD96 +0x02C0=0x0000 +0x0499=0x0000 +0x0513=0xDAA2 +0x0549=0x18C9 +0x0552=0x8D44 +0x0521=0x5852 +0x0509=0x0605 +0x0286=0x0000 +0x024F=0x0000 +0x04E0=0x0000 +0x0545=0x364E +0x0551=0xD7B7 +0x055F=0x5852 +0x009E=0x658C +0x0598=0xF61D +0x0123=0x067B +0x0497=0x0000 +0x04A5=0x0000 +0x0565=0xB77F +0x0124=0x0000 +0x0592=0x0DF1 +0x0591=0xFCFE +0x0548=0x79FA +0x04D2=0x0000 +0x0599=0x0000 +0x0511=0x1D10 +0x0506=0x0DF1 +0x0595=0x00BC +0x0584=0xE7E2 +0x0242=0x0000 +0x025A=0x0000 +0x04E2=0x0000 +0x04C5=0x0000 +0x058C=0xEA50 +0x0450=0x0000 +0x058A=0x17DC +0x059D=0x0000 +0x0485=0x0000 +0x058E=0x1316 +0x0550=0x79FA +0x0554=0x6901 +0x0593=0x00D8 +0x0553=0x364E +0x0542=0xA2B5 +0x0563=0x4F91 +0x024D=0x0000 +0x055A=0xBE2A +0x0295=0x0000 +0x028A=0x0000 +0x059C=0x0000 +0x04DD=0x0000 +0x054C=0x7FFF +0x0582=0x150F +0x0109=0x8CC1 +0x04A2=0x0000 +0x0292=0x0000 +0x0583=0x2E45 +0x059F=0x0000 +0x0525=0x57AC +0x0523=0xA6B5 +0x0206=0x0000 +0x051A=0x0906 +0x055C=0x3347 +0x05A6=0x0000 +0x050F=0xEA5F +0x051E=0xF524 +0x050A=0x1316 +0x04C7=0x0000 +0x049D=0x0000 +0x050C=0xEA50 +0x0087=0x0000 +0x0399=0x0000 +0x0495=0x0000 +0x0246=0x0000 +0x0503=0x00BC +0x0320=0x0000 +0x0323=0x0000 +0x055B=0x57AC +0x0114=0x0110 +0x02E5=0x0000 +0x04E7=0x0000 +0x04D0=0x0000 +0x04E6=0x0000 +0x00AE=0x0000 +0x0544=0x6901 +0x04DE=0x0000 +0x058B=0x0F45 +0x0028=0x0101 +0x029E=0x0000 +0x04DC=0x0000 +0x04D9=0x0000 +0x058F=0x0605 +0x0557=0x4C24 +0x04DB=0x0000 +0x04D7=0x0000 +0x059E=0x0000 +0x024C=0x0000 +0x02DC=0x0000 +0x04D4=0x0000 +0x0504=0xF40D +0x02C3=0x0000 +0x04C1=0x0000 +0x04D3=0x0000 +0x0590=0xEF99 +0x04CE=0x0000 +0x05A5=0x0000 +[file_info] +version=1 +type=lms7002m_minimal_config diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band13.tm1.50PRB.lmssdr.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band13.tm1.50PRB.lmssdr.conf new file mode 100644 index 0000000000..6b93021426 --- /dev/null +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band13.tm1.50PRB.lmssdr.conf @@ -0,0 +1,171 @@ +Active_eNBs = ( "eNB_Eurecom_LTEBox"); +# Asn1_verbosity, choice in: none, info, annoying +Asn1_verbosity = "none"; + +eNBs = +( + { + ////////// Identification parameters: + eNB_ID = 0xe00; + + cell_type = "CELL_MACRO_ENB"; + + eNB_name = "eNB_Eurecom_LTEBox"; + + // Tracking area code, 0x0000 and 0xfffe are reserved values + tracking_area_code = "1"; + + mobile_country_code = "208"; + + mobile_network_code = "95"; + + ////////// Physical parameters: + + component_carriers = ( + { + frame_type = "FDD"; + tdd_config = 3; + tdd_config_s = 0; + prefix_type = "NORMAL"; + eutra_band = 13; + downlink_frequency = 751000000L; + uplink_frequency_offset = 31000000; + Nid_cell = 0; + N_RB_DL = 50; + Nid_cell_mbsfn = 0; + nb_antennas_tx = 1; + nb_antennas_rx = 1; + tx_gain = 90; + rx_gain = 125; + prach_root = 0; + prach_config_index = 0; + prach_high_speed = "DISABLE"; + prach_zero_correlation = 1; + prach_freq_offset = 2; + pucch_delta_shift = 1; + pucch_nRB_CQI = 1; + pucch_nCS_AN = 0; + pucch_n1_AN = 32; + pdsch_referenceSignalPower = -20; + pdsch_p_b = 0; + pusch_n_SB = 1; + pusch_enable64QAM = "DISABLE"; + pusch_hoppingMode = "interSubFrame"; + pusch_hoppingOffset = 0; + pusch_groupHoppingEnabled = "ENABLE"; + pusch_groupAssignment = 0; + pusch_sequenceHoppingEnabled = "DISABLE"; + pusch_nDMRS1 = 1; + phich_duration = "NORMAL"; + phich_resource = "ONESIXTH"; + srs_enable = "DISABLE"; + /* srs_BandwidthConfig =; + srs_SubframeConfig =; + srs_ackNackST =; + srs_MaxUpPts =;*/ + + pusch_p0_Nominal = -90; + pusch_alpha = "AL1"; + pucch_p0_Nominal = -96; + msg3_delta_Preamble = 6; + pucch_deltaF_Format1 = "deltaF2"; + pucch_deltaF_Format1b = "deltaF3"; + pucch_deltaF_Format2 = "deltaF0"; + pucch_deltaF_Format2a = "deltaF0"; + pucch_deltaF_Format2b = "deltaF0"; + + rach_numberOfRA_Preambles = 64; + rach_preamblesGroupAConfig = "DISABLE"; + /* + rach_sizeOfRA_PreamblesGroupA = ; + rach_messageSizeGroupA = ; + rach_messagePowerOffsetGroupB = ; + */ + rach_powerRampingStep = 4; + rach_preambleInitialReceivedTargetPower = -108; + rach_preambleTransMax = 10; + rach_raResponseWindowSize = 10; + rach_macContentionResolutionTimer = 48; + rach_maxHARQ_Msg3Tx = 4; + + pcch_default_PagingCycle = 128; + pcch_nB = "oneT"; + bcch_modificationPeriodCoeff = 2; + ue_TimersAndConstants_t300 = 1000; + ue_TimersAndConstants_t301 = 1000; + ue_TimersAndConstants_t310 = 1000; + ue_TimersAndConstants_t311 = 10000; + ue_TimersAndConstants_n310 = 20; + ue_TimersAndConstants_n311 = 1; + + } + ); + + + srb1_parameters : + { + # timer_poll_retransmit = (ms) [5, 10, 15, 20,... 250, 300, 350, ... 500] + timer_poll_retransmit = 80; + + # timer_reordering = (ms) [0,5, ... 100, 110, 120, ... ,200] + timer_reordering = 35; + + # timer_reordering = (ms) [0,5, ... 250, 300, 350, ... ,500] + timer_status_prohibit = 0; + + # poll_pdu = [4, 8, 16, 32 , 64, 128, 256, infinity(>10000)] + poll_pdu = 4; + + # poll_byte = (kB) [25,50,75,100,125,250,375,500,750,1000,1250,1500,2000,3000,infinity(>10000)] + poll_byte = 99999; + + # max_retx_threshold = [1, 2, 3, 4 , 6, 8, 16, 32] + max_retx_threshold = 4; + } + + # ------- SCTP definitions + SCTP : + { + # Number of streams to use in input/output + SCTP_INSTREAMS = 2; + SCTP_OUTSTREAMS = 2; + }; + + + ////////// MME parameters: + mme_ip_address = ( { ipv4 = "192.168.12.62"; + ipv6 = "192:168:30::17"; + active = "yes"; + preference = "ipv4"; + } + ); + + NETWORK_INTERFACES : + { + ENB_INTERFACE_NAME_FOR_S1_MME = "eth4"; + ENB_IPV4_ADDRESS_FOR_S1_MME = "192.168.12.242/24"; + + ENB_INTERFACE_NAME_FOR_S1U = "eth4"; + ENB_IPV4_ADDRESS_FOR_S1U = "192.168.12.242/24"; + ENB_PORT_FOR_S1U = 2152; # Spec 2152 + }; + + log_config : + { + global_log_level ="info"; + global_log_verbosity ="medium"; + hw_log_level ="info"; + hw_log_verbosity ="medium"; + phy_log_level ="info"; + phy_log_verbosity ="medium"; + mac_log_level ="info"; + mac_log_verbosity ="high"; + rlc_log_level ="info"; + rlc_log_verbosity ="medium"; + pdcp_log_level ="info"; + pdcp_log_verbosity ="medium"; + rrc_log_level ="info"; + rrc_log_verbosity ="medium"; + }; + } +); diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band13.tm1.lmssdr.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band13.tm1.lmssdr.conf new file mode 100644 index 0000000000..dacc3e8664 --- /dev/null +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band13.tm1.lmssdr.conf @@ -0,0 +1,171 @@ +Active_eNBs = ( "eNB_Eurecom_LTEBox"); +# Asn1_verbosity, choice in: none, info, annoying +Asn1_verbosity = "none"; + +eNBs = +( + { + ////////// Identification parameters: + eNB_ID = 0xe00; + + cell_type = "CELL_MACRO_ENB"; + + eNB_name = "eNB_Eurecom_LTEBox"; + + // Tracking area code, 0x0000 and 0xfffe are reserved values + tracking_area_code = "1"; + + mobile_country_code = "208"; + + mobile_network_code = "95"; + + ////////// Physical parameters: + + component_carriers = ( + { + frame_type = "FDD"; + tdd_config = 3; + tdd_config_s = 0; + prefix_type = "NORMAL"; + eutra_band = 13; + downlink_frequency = 751000000L; + uplink_frequency_offset = 31000000; + Nid_cell = 0; + N_RB_DL = 25; + Nid_cell_mbsfn = 0; + nb_antennas_tx = 1; + nb_antennas_rx = 1; + tx_gain = 90; + rx_gain = 125; + prach_root = 0; + prach_config_index = 0; + prach_high_speed = "DISABLE"; + prach_zero_correlation = 1; + prach_freq_offset = 2; + pucch_delta_shift = 1; + pucch_nRB_CQI = 1; + pucch_nCS_AN = 0; + pucch_n1_AN = 32; + pdsch_referenceSignalPower = -17; + pdsch_p_b = 0; + pusch_n_SB = 1; + pusch_enable64QAM = "DISABLE"; + pusch_hoppingMode = "interSubFrame"; + pusch_hoppingOffset = 0; + pusch_groupHoppingEnabled = "ENABLE"; + pusch_groupAssignment = 0; + pusch_sequenceHoppingEnabled = "DISABLE"; + pusch_nDMRS1 = 1; + phich_duration = "NORMAL"; + phich_resource = "ONESIXTH"; + srs_enable = "DISABLE"; + /* srs_BandwidthConfig =; + srs_SubframeConfig =; + srs_ackNackST =; + srs_MaxUpPts =;*/ + + pusch_p0_Nominal = -90; + pusch_alpha = "AL1"; + pucch_p0_Nominal = -96; + msg3_delta_Preamble = 6; + pucch_deltaF_Format1 = "deltaF2"; + pucch_deltaF_Format1b = "deltaF3"; + pucch_deltaF_Format2 = "deltaF0"; + pucch_deltaF_Format2a = "deltaF0"; + pucch_deltaF_Format2b = "deltaF0"; + + rach_numberOfRA_Preambles = 64; + rach_preamblesGroupAConfig = "DISABLE"; + /* + rach_sizeOfRA_PreamblesGroupA = ; + rach_messageSizeGroupA = ; + rach_messagePowerOffsetGroupB = ; + */ + rach_powerRampingStep = 4; + rach_preambleInitialReceivedTargetPower = -108; + rach_preambleTransMax = 10; + rach_raResponseWindowSize = 10; + rach_macContentionResolutionTimer = 48; + rach_maxHARQ_Msg3Tx = 4; + + pcch_default_PagingCycle = 128; + pcch_nB = "oneT"; + bcch_modificationPeriodCoeff = 2; + ue_TimersAndConstants_t300 = 1000; + ue_TimersAndConstants_t301 = 1000; + ue_TimersAndConstants_t310 = 1000; + ue_TimersAndConstants_t311 = 10000; + ue_TimersAndConstants_n310 = 20; + ue_TimersAndConstants_n311 = 1; + + } + ); + + + srb1_parameters : + { + # timer_poll_retransmit = (ms) [5, 10, 15, 20,... 250, 300, 350, ... 500] + timer_poll_retransmit = 80; + + # timer_reordering = (ms) [0,5, ... 100, 110, 120, ... ,200] + timer_reordering = 35; + + # timer_reordering = (ms) [0,5, ... 250, 300, 350, ... ,500] + timer_status_prohibit = 0; + + # poll_pdu = [4, 8, 16, 32 , 64, 128, 256, infinity(>10000)] + poll_pdu = 4; + + # poll_byte = (kB) [25,50,75,100,125,250,375,500,750,1000,1250,1500,2000,3000,infinity(>10000)] + poll_byte = 99999; + + # max_retx_threshold = [1, 2, 3, 4 , 6, 8, 16, 32] + max_retx_threshold = 4; + } + + # ------- SCTP definitions + SCTP : + { + # Number of streams to use in input/output + SCTP_INSTREAMS = 2; + SCTP_OUTSTREAMS = 2; + }; + + + ////////// MME parameters: + mme_ip_address = ( { ipv4 = "192.168.12.62"; + ipv6 = "192:168:30::17"; + active = "yes"; + preference = "ipv4"; + } + ); + + NETWORK_INTERFACES : + { + ENB_INTERFACE_NAME_FOR_S1_MME = "eth4"; + ENB_IPV4_ADDRESS_FOR_S1_MME = "192.168.12.242/24"; + + ENB_INTERFACE_NAME_FOR_S1U = "eth4"; + ENB_IPV4_ADDRESS_FOR_S1U = "192.168.12.242/24"; + ENB_PORT_FOR_S1U = 2152; # Spec 2152 + }; + + log_config : + { + global_log_level ="info"; + global_log_verbosity ="medium"; + hw_log_level ="info"; + hw_log_verbosity ="medium"; + phy_log_level ="info"; + phy_log_verbosity ="medium"; + mac_log_level ="info"; + mac_log_verbosity ="high"; + rlc_log_level ="info"; + rlc_log_verbosity ="medium"; + pdcp_log_level ="info"; + pdcp_log_verbosity ="medium"; + rrc_log_level ="info"; + rrc_log_verbosity ="medium"; + }; + } +); diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.lmssdr.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.lmssdr.conf index e001bd12e9..dae0187f18 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.lmssdr.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.lmssdr.conf @@ -17,7 +17,7 @@ eNBs = mobile_country_code = "208"; - mobile_network_code = "93"; + mobile_network_code = "95"; ////////// Physical parameters: @@ -132,7 +132,7 @@ eNBs = }; ////////// MME parameters: - mme_ip_address = ( { ipv4 = "192.168.12.171"; + mme_ip_address = ( { ipv4 = "192.168.12.62"; ipv6 = "192:168:30::17"; active = "yes"; preference = "ipv4"; From 1740b0c517592047d004e42276de24ad77af5f6d Mon Sep 17 00:00:00 2001 From: Ubuntu Date: Sun, 21 Feb 2016 14:25:13 +0000 Subject: [PATCH 257/263] USRP Band 13 --- .../CONF/enb.band13.tm1.usrpb210.conf | 22 +++++++++---------- .../CONF/enb.band7.tm1.usrpb210.conf | 10 ++++----- 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band13.tm1.usrpb210.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band13.tm1.usrpb210.conf index 69d8536217..f1cd67b196 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band13.tm1.usrpb210.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band13.tm1.usrpb210.conf @@ -27,16 +27,16 @@ eNBs = tdd_config = 3; tdd_config_s = 0; prefix_type = "NORMAL"; - eutra_band = 13; - downlink_frequency = 751000000L; - uplink_frequency_offset = 31000000; + eutra_band = 7; + downlink_frequency = 2685000000L; + uplink_frequency_offset = -120000000; Nid_cell = 0; N_RB_DL = 25; Nid_cell_mbsfn = 0; nb_antennas_tx = 1; nb_antennas_rx = 1; tx_gain = 90; - rx_gain = 100; + rx_gain = 125; prach_root = 0; prach_config_index = 0; prach_high_speed = "DISABLE"; @@ -46,7 +46,7 @@ eNBs = pucch_nRB_CQI = 1; pucch_nCS_AN = 0; pucch_n1_AN = 32; - pdsch_referenceSignalPower = -15; + pdsch_referenceSignalPower = -29; pdsch_p_b = 0; pusch_n_SB = 1; pusch_enable64QAM = "DISABLE"; @@ -64,7 +64,7 @@ eNBs = srs_ackNackST =; srs_MaxUpPts =;*/ - pusch_p0_Nominal = -86; + pusch_p0_Nominal = -90; pusch_alpha = "AL1"; pucch_p0_Nominal = -96; msg3_delta_Preamble = 6; @@ -133,7 +133,7 @@ eNBs = ////////// MME parameters: - mme_ip_address = ( { ipv4 = "192.168.12.62"; + mme_ip_address = ( { ipv4 = "172.27.8.52"; ipv6 = "192:168:30::17"; active = "yes"; preference = "ipv4"; @@ -142,11 +142,11 @@ eNBs = NETWORK_INTERFACES : { - ENB_INTERFACE_NAME_FOR_S1_MME = "eth4"; - ENB_IPV4_ADDRESS_FOR_S1_MME = "192.168.12.242/24"; + ENB_INTERFACE_NAME_FOR_S1_MME = "eth0"; + ENB_IPV4_ADDRESS_FOR_S1_MME = "172.27.8.51/23"; - ENB_INTERFACE_NAME_FOR_S1U = "eth4"; - ENB_IPV4_ADDRESS_FOR_S1U = "192.168.12.242/24"; + ENB_INTERFACE_NAME_FOR_S1U = "eth0"; + ENB_IPV4_ADDRESS_FOR_S1U = "172.27.8.51/23"; ENB_PORT_FOR_S1U = 2152; # Spec 2152 }; diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf index 4a9113282f..f1cd67b196 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.usrpb210.conf @@ -17,7 +17,7 @@ eNBs = mobile_country_code = "208"; - mobile_network_code = "93"; + mobile_network_code = "95"; ////////// Physical parameters: @@ -28,7 +28,7 @@ eNBs = tdd_config_s = 0; prefix_type = "NORMAL"; eutra_band = 7; - downlink_frequency = 2660000000L; + downlink_frequency = 2685000000L; uplink_frequency_offset = -120000000; Nid_cell = 0; N_RB_DL = 25; @@ -133,7 +133,7 @@ eNBs = ////////// MME parameters: - mme_ip_address = ( { ipv4 = "192.168.12.11"; + mme_ip_address = ( { ipv4 = "172.27.8.52"; ipv6 = "192:168:30::17"; active = "yes"; preference = "ipv4"; @@ -143,10 +143,10 @@ eNBs = NETWORK_INTERFACES : { ENB_INTERFACE_NAME_FOR_S1_MME = "eth0"; - ENB_IPV4_ADDRESS_FOR_S1_MME = "192.168.12.212/24"; + ENB_IPV4_ADDRESS_FOR_S1_MME = "172.27.8.51/23"; ENB_INTERFACE_NAME_FOR_S1U = "eth0"; - ENB_IPV4_ADDRESS_FOR_S1U = "192.168.12.212/24"; + ENB_IPV4_ADDRESS_FOR_S1U = "172.27.8.51/23"; ENB_PORT_FOR_S1U = 2152; # Spec 2152 }; From 5f3961556d68c0512d155cd4ed196f2b2dbb2d96 Mon Sep 17 00:00:00 2001 From: Rohit Gupta Date: Sun, 21 Feb 2016 19:25:30 +0100 Subject: [PATCH 258/263] Update eNB config USRP for band 13 --- .../CONF/enb.band13.tm1.usrpb210.conf | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band13.tm1.usrpb210.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band13.tm1.usrpb210.conf index f1cd67b196..1bf3c6fbf2 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band13.tm1.usrpb210.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band13.tm1.usrpb210.conf @@ -27,16 +27,16 @@ eNBs = tdd_config = 3; tdd_config_s = 0; prefix_type = "NORMAL"; - eutra_band = 7; - downlink_frequency = 2685000000L; - uplink_frequency_offset = -120000000; + eutra_band = 13; + downlink_frequency = 751000000L; + uplink_frequency_offset = 31000000; Nid_cell = 0; - N_RB_DL = 25; + N_RB_DL = 50; Nid_cell_mbsfn = 0; nb_antennas_tx = 1; nb_antennas_rx = 1; tx_gain = 90; - rx_gain = 125; + rx_gain = 110; prach_root = 0; prach_config_index = 0; prach_high_speed = "DISABLE"; @@ -46,7 +46,7 @@ eNBs = pucch_nRB_CQI = 1; pucch_nCS_AN = 0; pucch_n1_AN = 32; - pdsch_referenceSignalPower = -29; + pdsch_referenceSignalPower = -15; pdsch_p_b = 0; pusch_n_SB = 1; pusch_enable64QAM = "DISABLE"; @@ -82,7 +82,7 @@ eNBs = rach_messagePowerOffsetGroupB = ; */ rach_powerRampingStep = 4; - rach_preambleInitialReceivedTargetPower = -108; + rach_preambleInitialReceivedTargetPower = -100; rach_preambleTransMax = 10; rach_raResponseWindowSize = 10; rach_macContentionResolutionTimer = 48; @@ -168,4 +168,4 @@ eNBs = rrc_log_verbosity ="medium"; }; } -); +); \ No newline at end of file From 1473a3a65242f2e610fedcbaf9d458bb00ef2608 Mon Sep 17 00:00:00 2001 From: Raymond Knopp Date: Thu, 25 Feb 2016 14:22:56 -0800 Subject: [PATCH 259/263] applying hotfix for UE exit on DLSCH error to develop --- openair1/SCHED/phy_procedures_lte_ue.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/openair1/SCHED/phy_procedures_lte_ue.c b/openair1/SCHED/phy_procedures_lte_ue.c index c746fe7254..afaecb7075 100755 --- a/openair1/SCHED/phy_procedures_lte_ue.c +++ b/openair1/SCHED/phy_procedures_lte_ue.c @@ -2678,18 +2678,18 @@ int phy_procedures_UE_RX(PHY_VARS_UE *phy_vars_ue,uint8_t eNB_id,uint8_t abstrac if (ret == (1+phy_vars_ue->dlsch_ue[eNB_id][0]->max_turbo_iterations)) { phy_vars_ue->dlsch_errors[eNB_id]++; - //#ifdef DEBUG_PHY_PROC +#ifdef DEBUG_PHY_PROC LOG_D(PHY,"[UE %d][PDSCH %x/%d] Frame %d subframe %d DLSCH in error (rv %d,mcs %d,TBS %d)\n", phy_vars_ue->Mod_id,phy_vars_ue->dlsch_ue[eNB_id][0]->rnti, harq_pid,frame_rx,subframe_prev, phy_vars_ue->dlsch_ue[eNB_id][0]->harq_processes[harq_pid]->rvidx, phy_vars_ue->dlsch_ue[eNB_id][0]->harq_processes[harq_pid]->mcs, phy_vars_ue->dlsch_ue[eNB_id][0]->harq_processes[harq_pid]->TBS); - - // if (abstraction_flag ==0 ) - dump_dlsch(phy_vars_ue,eNB_id,subframe_prev,harq_pid); - mac_xface->macphy_exit(""); - //#endif +/* + if (abstraction_flag ==0 ) + dump_dlsch(phy_vars_ue,eNB_id,subframe_prev,harq_pid); + mac_xface->macphy_exit(""); */ +#endif } else { LOG_D(PHY,"[UE %d][PDSCH %x/%d] Frame %d subframe %d (slot_rx %d): Received DLSCH (rv %d,mcs %d,TBS %d)\n", phy_vars_ue->Mod_id,phy_vars_ue->dlsch_ue[eNB_id][0]->rnti, From 5d62584c9f587f5f1d3f5d923e3c38cf00d29bb4 Mon Sep 17 00:00:00 2001 From: Cedric Roux Date: Mon, 29 Feb 2016 12:08:11 +0100 Subject: [PATCH 260/263] quickfix of prach_zero_correlation parameter range check in openair2/ENB_APP/enb_config.c it was tested against 63, it should be tested against 15 no impact on processing whatsoever so no need to test --- openair2/ENB_APP/enb_config.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openair2/ENB_APP/enb_config.c b/openair2/ENB_APP/enb_config.c index 4c532285f2..107ca724fc 100755 --- a/openair2/ENB_APP/enb_config.c +++ b/openair2/ENB_APP/enb_config.c @@ -1019,7 +1019,7 @@ const Enb_properties_array_t *enb_config_init(char* lib_config_file_name_pP) enb_properties.properties[enb_properties_index]->prach_zero_correlation[j] =prach_zero_correlation; - if ((prach_zero_correlation <0) || (prach_zero_correlation > 63)) + if ((prach_zero_correlation <0) || (prach_zero_correlation > 15)) AssertError (0, parse_errors ++, "Failed to parse eNB configuration file %s, enb %d unknown value \"%d\" for prach_zero_correlation choice: 0..15!\n", lib_config_file_name_pP, i, prach_zero_correlation); From 9764c9247c2949aba1c948c0200011b42c0ac28c Mon Sep 17 00:00:00 2001 From: Navid Nikaein Date: Mon, 29 Feb 2016 21:40:49 +0100 Subject: [PATCH 261/263] update trx_bladerf_write calls to match the common_lib.h trx_write_func --- .../ARCH/BLADERF/USERSPACE/LIB/bladerf_lib.c | 37 +++++++++---------- 1 file changed, 18 insertions(+), 19 deletions(-) diff --git a/targets/ARCH/BLADERF/USERSPACE/LIB/bladerf_lib.c b/targets/ARCH/BLADERF/USERSPACE/LIB/bladerf_lib.c index 2f73d6978c..065b0bbad2 100644 --- a/targets/ARCH/BLADERF/USERSPACE/LIB/bladerf_lib.c +++ b/targets/ARCH/BLADERF/USERSPACE/LIB/bladerf_lib.c @@ -412,7 +412,7 @@ void calibrate_rf(openair0_device *device) { bladerf_set_correction(brf->dev,BLADERF_MODULE_TX,BLADERF_CORR_LMS_DCOFF_I,offIold); for (i=0;i<10;i++) { trx_brf_read(device, &ptimestamp, (void **)&calib_buffp, RXDCLENGTH, 0); - trx_brf_write(device,ptimestamp+5*RXDCLENGTH, (void **)&calib_tx_buffp, RXDCLENGTH, 0); + trx_brf_write(device,ptimestamp+5*RXDCLENGTH, (void **)&calib_tx_buffp, RXDCLENGTH, 0, 0); } for (meanIold=meanQold=i=j=0;idev,BLADERF_MODULE_TX,BLADERF_CORR_LMS_DCOFF_I,offI); for (i=0;i<10;i++) { trx_brf_read(device, &ptimestamp, (void **)&calib_buffp, RXDCLENGTH, 0); - trx_brf_write(device,ptimestamp+5*RXDCLENGTH, (void **)&calib_tx_buffp, RXDCLENGTH, 0); + trx_brf_write(device,ptimestamp+5*RXDCLENGTH, (void **)&calib_tx_buffp, RXDCLENGTH, 0, 0); } for (meanI=meanQ=i=j=0;idev,BLADERF_MODULE_TX,BLADERF_CORR_LMS_DCOFF_Q,offQold); for (i=0;i<10;i++) { trx_brf_read(device, &ptimestamp, (void **)&calib_buffp, RXDCLENGTH, 0); - trx_brf_write(device,ptimestamp+5*RXDCLENGTH, (void **)&calib_tx_buffp, RXDCLENGTH, 0); + trx_brf_write(device,ptimestamp+5*RXDCLENGTH, (void **)&calib_tx_buffp, RXDCLENGTH, 0, 0); } // project on fs/4 for (meanIold=meanQold=i=j=0;idev,BLADERF_MODULE_TX,BLADERF_CORR_LMS_DCOFF_Q,offQ); for (i=0;i<10;i++) { trx_brf_read(device, &ptimestamp, (void **)&calib_buffp, RXDCLENGTH, 0); - trx_brf_write(device,ptimestamp+5*RXDCLENGTH, (void **)&calib_tx_buffp, RXDCLENGTH, 0); + trx_brf_write(device,ptimestamp+5*RXDCLENGTH, (void **)&calib_tx_buffp, RXDCLENGTH, 0, 0); } for (meanI=meanQ=i=j=0;idev,BLADERF_MODULE_TX,BLADERF_CORR_FPGA_PHASE,offphaseold); for (i=0;i<10;i++) { trx_brf_read(device, &ptimestamp, (void **)&calib_buffp, RXDCLENGTH, 0); - trx_brf_write(device,ptimestamp+5*RXDCLENGTH, (void **)&calib_tx_buffp, RXDCLENGTH, 0); + trx_brf_write(device,ptimestamp+5*RXDCLENGTH, (void **)&calib_tx_buffp, RXDCLENGTH, 0, 0); } // project on fs/8 (Image of TX signal in +ve frequencies) for (meanIold=meanQold=i=j=0;idev,BLADERF_MODULE_TX,BLADERF_CORR_FPGA_PHASE,offphase); for (i=0;i<10;i++) { trx_brf_read(device, &ptimestamp, (void **)&calib_buffp, RXDCLENGTH, 0); - trx_brf_write(device,ptimestamp+5*RXDCLENGTH, (void **)&calib_tx_buffp, RXDCLENGTH, 0); + trx_brf_write(device,ptimestamp+5*RXDCLENGTH, (void **)&calib_tx_buffp, RXDCLENGTH, 0, 0); } // project on fs/8 (Image of TX signal in +ve frequencies) for (meanI=meanQ=i=j=0;idev,BLADERF_MODULE_TX,BLADERF_CORR_FPGA_GAIN,offgainold); for (i=0;i<10;i++) { trx_brf_read(device, &ptimestamp, (void **)&calib_buffp, RXDCLENGTH, 0); - trx_brf_write(device,ptimestamp+5*RXDCLENGTH, (void **)&calib_tx_buffp, RXDCLENGTH, 0); + trx_brf_write(device,ptimestamp+5*RXDCLENGTH, (void **)&calib_tx_buffp, RXDCLENGTH, 0, 0); } // project on fs/8 (Image of TX signal in +ve frequencies) for (meanIold=meanQold=i=j=0;idev,BLADERF_MODULE_TX,BLADERF_CORR_FPGA_GAIN,offgain); for (i=0;i<10;i++) { trx_brf_read(device, &ptimestamp, (void **)&calib_buffp, RXDCLENGTH, 0); - trx_brf_write(device,ptimestamp+5*RXDCLENGTH, (void **)&calib_tx_buffp, RXDCLENGTH, 0); + trx_brf_write(device,ptimestamp+5*RXDCLENGTH, (void **)&calib_tx_buffp, RXDCLENGTH, 0, 0); } // project on fs/8 (Image of TX signal in +ve frequencies) for (meanI=meanQ=i=j=0;idev,BLADERF_MODULE_RX,BLADERF_CORR_FPGA_PHASE,offphaseold); for (i=0;i<10;i++) { trx_brf_read(device, &ptimestamp, (void **)&calib_buffp, RXDCLENGTH, 0); - trx_brf_write(device,ptimestamp+5*RXDCLENGTH, (void **)&calib_tx_buffp, RXDCLENGTH, 0); + trx_brf_write(device,ptimestamp+5*RXDCLENGTH, (void **)&calib_tx_buffp, RXDCLENGTH, 0, 0); } // project on -3fs/8 (Image of TX signal in -ve frequencies) for (meanIold=meanQold=i=j=0;idev,BLADERF_MODULE_RX,BLADERF_CORR_FPGA_PHASE,offphase); for (i=0;i<10;i++) { trx_brf_read(device, &ptimestamp, (void **)&calib_buffp, RXDCLENGTH, 0); - trx_brf_write(device,ptimestamp+5*RXDCLENGTH, (void **)&calib_tx_buffp, RXDCLENGTH, 0); + trx_brf_write(device,ptimestamp+5*RXDCLENGTH, (void **)&calib_tx_buffp, RXDCLENGTH, 0, 0); } // project on -3fs/8 (Image of TX signal in -ve frequencies) for (meanI=meanQ=i=j=0;idev,BLADERF_MODULE_RX,BLADERF_CORR_FPGA_GAIN,offgainold); for (i=0;i<10;i++) { trx_brf_read(device, &ptimestamp, (void **)&calib_buffp, RXDCLENGTH, 0); - trx_brf_write(device,ptimestamp+5*RXDCLENGTH, (void **)&calib_tx_buffp, RXDCLENGTH, 0); + trx_brf_write(device,ptimestamp+5*RXDCLENGTH, (void **)&calib_tx_buffp, RXDCLENGTH, 0,0); } // project on -3fs/8 (Image of TX signal in +ve frequencies) for (meanIold=meanQold=i=j=0;idev,BLADERF_MODULE_RX,BLADERF_CORR_FPGA_GAIN,offgain); for (i=0;i<10;i++) { trx_brf_read(device, &ptimestamp, (void **)&calib_buffp, RXDCLENGTH, 0); - trx_brf_write(device,ptimestamp+5*RXDCLENGTH, (void **)&calib_tx_buffp, RXDCLENGTH, 0); + trx_brf_write(device,ptimestamp+5*RXDCLENGTH, (void **)&calib_tx_buffp, RXDCLENGTH, 0, 0); } // project on 3fs/8 (Image of TX signal in -ve frequencies) for (meanI=meanQ=i=j=0;ilog_level)); printf("BLADERF: Initializing openair0_device\n"); - device->priv = brf; device->Mod_id = num_devices++; device->type = BLADERF_DEV; device->trx_start_func = trx_brf_start; From 75602a1267b6dda67fe9dfb574f912d4992a37c2 Mon Sep 17 00:00:00 2001 From: Navid Nikaein Date: Mon, 29 Feb 2016 21:45:30 +0100 Subject: [PATCH 262/263] correct tx_shift paremeter in config files for rrh and usrp --- .../CONF/enb.band7.tm1.50PRB.rrh.usrpb210.conf | 4 +--- .../CONF/enb.band7.tm1.rrh.usrpb210.conf | 13 ++++++------- 2 files changed, 7 insertions(+), 10 deletions(-) diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.rrh.usrpb210.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.rrh.usrpb210.conf index 604f5567ef..004af14749 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.rrh.usrpb210.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.50PRB.rrh.usrpb210.conf @@ -150,7 +150,7 @@ rrh_gw_config = ( rrh_gw_active = "yes"; tr_preference = "raw"; rf_preference = "usrp_b200"; - iq_txshift = 5; + iq_txshift = 4; tx_sample_advance = 113; tx_scheduling_advance = 9; @@ -163,8 +163,6 @@ rrh_gw_config = ( ENB_IPV4_ADDRESS_FOR_S1_MME = "192.168.12.111/24"; ENB_INTERFACE_NAME_FOR_S1U = "eth4"; - - ENB_IPV4_ADDRESS_FOR_S1U = "192.168.12.111/24"; ENB_PORT_FOR_S1U = 2152; # Spec 2152 }; diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.rrh.usrpb210.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.rrh.usrpb210.conf index 33db53740c..37880a2906 100644 --- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.rrh.usrpb210.conf +++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.rrh.usrpb210.conf @@ -133,7 +133,7 @@ eNBs = ////////// MME parameters: - mme_ip_address = ( { ipv4 = "192.168.12.26"; + mme_ip_address = ( { ipv4 = "192.168.12.170"; ipv6 = "192:168:30::17"; active = "yes"; preference = "ipv4"; @@ -145,14 +145,14 @@ rrh_gw_config = ( local_if_name = "eth0"; #remote_address = "169.254.10.158"; #local_address = "169.254.8.15"; - remote_address = "74:d4:35:cc:88:45"; - local_address = "98:90:96:df:66:07"; + remote_address = "74:d4:35:cc:88:e3"; + local_address = "74:d4:35:cc:88:d1"; local_port = 50000; #for raw option local port must be the same to remote remote_port = 50000; rrh_gw_active = "yes"; tr_preference = "raw"; rf_preference = "usrp_b200"; - iq_txshift = 5; + iq_txshift = 4; tx_sample_advance = 70; tx_scheduling_advance = 9; @@ -162,12 +162,11 @@ rrh_gw_config = ( NETWORK_INTERFACES : { ENB_INTERFACE_NAME_FOR_S1_MME = "eth4"; - ENB_IPV4_ADDRESS_FOR_S1_MME = "192.168.12.111/24"; + ENB_IPV4_ADDRESS_FOR_S1_MME = "192.168.12.240/24"; ENB_INTERFACE_NAME_FOR_S1U = "eth4"; - - ENB_IPV4_ADDRESS_FOR_S1U = "192.168.12.111/24"; + ENB_IPV4_ADDRESS_FOR_S1U = "192.168.12.240/24"; ENB_PORT_FOR_S1U = 2152; # Spec 2152 }; From 9ccc1999bffe17593f7afd5053f7b64ca5f22d97 Mon Sep 17 00:00:00 2001 From: Florian Kaltenberger Date: Tue, 1 Mar 2016 16:55:25 +0100 Subject: [PATCH 263/263] removing old unused files --- targets/RT/USER/dot11.c | 1275 ------------------------ targets/RT/USER/ieee80211p-softmodem.c | 185 ---- 2 files changed, 1460 deletions(-) delete mode 100644 targets/RT/USER/dot11.c delete mode 100644 targets/RT/USER/ieee80211p-softmodem.c diff --git a/targets/RT/USER/dot11.c b/targets/RT/USER/dot11.c deleted file mode 100644 index 00e535a21d..0000000000 --- a/targets/RT/USER/dot11.c +++ /dev/null @@ -1,1275 +0,0 @@ -/******************************************************************************* - - Eurecom OpenAirInterface - Copyright(c) 1999 - 2011 Eurecom - - This program is free software; you can redistribute it and/or modify it - under the terms and conditions of the GNU General Public License, - version 2, as published by the Free Software Foundation. - - This program is distributed in the hope it will be useful, but WITHOUT - ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - more details. - - You should have received a copy of the GNU General Public License along with - this program; if not, write to the Free Software Foundation, Inc., - 51 Franklin St - Fifth Floor, Boston, MA 02110-1301 USA. - - The full GNU General Public License is included in this distribution in - the file called "COPYING". - - Contact Information - Openair Admin: openair_admin@eurecom.fr - Openair Tech : openair_tech@eurecom.fr - Forums : http://forums.eurecom.fsr/openairinterface - Address : Eurecom, 2229, route des crĂȘtes, 06560 Valbonne Sophia Antipolis, France - -*******************************************************************************/ - -<<<<<<< .mine -/*! \file dot11.c -* \brief main program to control HW and scheduling for openairITS dot11 MODEM -* \author R. Knopp, F. Kaltenberger -* \date 2012 -* \version 0.1 -* \company Eurecom -* \email: knopp@eurecom.fr,florian.kaltenberger@eurecom.fr -* \note -* \warning -*/ -======= - /*! \file dot11.c - * \brief main program to control HW and scheduling for openairITS dot11 MODEM - * \author R. Knopp, F. Kaltenberger - * \date 2012 - * \version 0.1 - * \company Eurecom - * \email: knopp@eurecom.fr,florian.kaltenberger@eurecom.fr - * \note - * \warning - */ - >>>>>>> .r3153 -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include - -#include "PHY/types.h" -#include "PHY/defs.h" - -#include "ARCH/COMMON/defs.h" -#include "ARCH/CBMIMO1/DEVICE_DRIVER/cbmimo1_device.h" -#include "ARCH/CBMIMO1/DEVICE_DRIVER/cbmimo1_pci.h" -#include "SIMULATION/LTE_PHY/openair_hw.h" - -#include "ARCH/CBMIMO1/DEVICE_DRIVER/vars.h" -#include "SCHED/defs.h" -#include "SCHED/vars.h" - - - <<<<<<< .mine -#include "phy/DOT11/defs.h" -#include "phy/DOT11/commonvars.h" -#include - ======= -#include "phy/DOT11/defs.h" -#include "phy/DOT11/commonvars.h" -#include "PHY/TOOLS/defs.h" - >>>>>>> .r3153 - - <<<<<<< .mine - ======= -#include - >>>>>>> .r3153 - - <<<<<<< .mine -#include "UTIL/LOG/log.h" - ======= - >>>>>>> .r3153 - - <<<<<<< .mine -#define FRAME_LENGTH_SAMPLES_MAX 100000 - - uint16_t rev64[64]; - -int generate_test_tx=0; - - - - -======= -#include "UTIL/LOG/log.h" -#include "ieee80211p-netlinkapi.h" - -#define FRAME_LENGTH_SAMPLES_MAX 100000 - - uint16_t rev64[64]; - -int generate_test_tx=0; - - - - ->>>>>>> .r3153 -#define FRAME_PERIOD 100000000ULL -#define DAQ_PERIOD 66666ULL - - -#undef MALLOC //there are two conflicting definitions, so we better make sure we don't use it at all -enum nl80211_band { - NL80211_BAND_2GHZ, - NL80211_BAND_5GHZ, - NL80211_BAND_5_9GHZ, - NL80211_BAND_0_8GHZ, -}; - -<<<<<<< .mine - -======= - enum ieee80211_band { - IEEE80211_BAND_2GHZ = NL80211_BAND_2GHZ, - IEEE80211_BAND_5GHZ = NL80211_BAND_5GHZ, - IEEE80211_BAND_5_9GHZ = NL80211_BAND_5_9GHZ, - IEEE80211_BAND_0_8GHZ = NL80211_BAND_0_8GHZ, - }; - -struct ieee80211p_rx_status { - short data_len; //frame data length in bytes - char rssi; //received power in dBm - char rate; //reveived data rate in units of 100 kbps - enum ieee80211_band band; - char flags; //RX flags -}; /* struct ieee80211p_rx_status */ - - ->>>>>>> .r3153 -//static CND *cond; - -static int thread1; -static int thread2; - -static int sync_thread; - - -static int instance_cnt=-1; //0 means worker is busy, -1 means its free -int instance_cnt_ptr_kern,*instance_cnt_ptr_user; -int pci_interface_ptr_kern; - -extern unsigned int bigphys_top; -extern unsigned int mem_base; - -int openair_fd = 0; - -int oai_exit = 0; - -//PCI_interface_t *pci_interface[3]; - -unsigned int *DAQ_MBOX; - -unsigned int time_offset[4] = {0,0,0,0}; - -int fs4_test=0; -char UE_flag=0; - -struct timing_info_t { - unsigned int frame, hw_slot, last_slot, next_slot; - RTIME time0, time1, time2; - unsigned int mbox0, mbox1, mbox2, mbox_target; -} timing_info[20]; - -extern s16* sync_corr_ue0; -extern s16 prach_ifft[4][1024*2]; - -typedef enum {normal_txrx=0,rx_calib_ue=1,rx_calib_ue_med=2,rx_calib_ue_byp=3} runmode_t; - -runmode_t mode; -int rx_input_level_dBm; - - -int otg_enabled = 0; - -TX_RX_VARS dummy_tx_rx_vars; -unsigned int bigphys_top; -unsigned int mem_base; - -<<<<<<< .mine -uint32_t *txdata[2],*rxdata[2]; - -uint8_t *data_ind = NULL; - -extern int dot11_netlink_init(); -extern void *rx_thread(void *); -extern void *tx_thread(void *); - - -void dot11_init() -{ - - - - set_taus_seed(0); - - // Basic initializations - init_fft(64,6,rev64); - init_interleavers(); - ccodedot11_init(); - ccodedot11_init_inv(); - phy_generate_viterbi_tables(); - - init_crc32(); - -} -======= - uint32_t *txdata[2],*rxdata[2]; ->>>>>>> .r3153 - -<<<<<<< .mine -void generate_test_tx_signal() -{ - ======= - uint8_t *data_ind = NULL; - >>>>>>> .r3153 - - <<<<<<< .mine - TX_VECTOR_t tx_vector; - int i; - - if (data_ind == NULL) { - data_ind = (uint8_t*)malloc(4095+2+1); - data_ind[0] = 0; - data_ind[1] = 0; - } - - - tx_vector.rate=1; - tx_vector.sdu_length=512; - tx_vector.service=0; - - for (i=0; i>>>>>> .r3153 - - extern int32_t rxDATA_F_comp_aggreg3[48*1024]; - extern int32_t rxDATA_F_comp_aggreg2[48*1024]; - -#define FRAME_LENGTH_SAMPLES 76800 -#define RX_THRES 60 - -#define SLOT_DURATION_5MHz 105 -#define RX_THRES_dB 300 - - u32 rxgain[4]= {30,30,30,30}; - unsigned int rxg_max[4]= {133,133,133,133}, rxg_med[4]= {127,127,127,127}, rxg_byp[4]= {120,120,120,120}; - - extern int tx_sdu_active; - extern int tx_sdu_length; - extern char rxsdu[2000]; - int n; - - static void *rx_thread(void *arg) { - - int fd = *((int*)arg); - int rx_offset; - RX_VECTOR_t *rxv; - uint8_t *data_ind_rx; - int i; - struct ieee80211p_rx_status *rs; - int ret,frame; - RT_TASK *task; - int16_t rx_energy; - int initial_sample_offset = 0,off=0; - int dlen,dlen_symb; - int mbox_off = 0,old_mbox,mbox_diff; - int rt_skip_cond; - int pos_crc=0,neg_crc=0; - int sdu_received; - int sample_threshold; - int log2_maxh; - struct sched_param mysched; - int skip=0; - int txlen; - - /* mysched.sched_priority = 99; - - sched_setscheduler( 0, SCHED_FIFO, &mysched); - */ - char dummy_data[16]; - - - if (fd>0) { - printf("rx_thread starting, fd %d\n",fd); - - data_ind_rx = (uint8_t*)malloc(4095+2+1+12); - - task = rt_task_init_schmod(nam2num("TASK0"), 0, 0, 0, SCHED_FIFO, 0xF); - mlockall(MCL_CURRENT | MCL_FUTURE); - - // rt_make_hard_real_time(); - - - // printf("Started rx_thread ... MBOX %d\n",((unsigned int *)DAQ_MBOX)[0]); - // wait until MBOX gets around to zero - i=0; - - while (((volatile unsigned int *)DAQ_MBOX)[0] != 0) { - rt_sleep(nano2count(10000)); - - if (i>1000) { - printf("HW not counting,exiting rx_thread\n"); - return(0); - } - } - - // printf("Got first MBOX = 0\n"); - // wait for first 120us - while (((unsigned int *)DAQ_MBOX)[0] < 2) - rt_sleep(nano2count(2*66666)); - - old_mbox = ((unsigned int *)DAQ_MBOX)[0]; - - // printf("MBOX = %d\n",((unsigned int *)DAQ_MBOX)[0]); - i = 0; - frame = 0; - // oai_exit=1; - rt_skip_cond=0; - - while (!oai_exit) { - - // printf("While in ... mbox %d\n",((unsigned int *)DAQ_MBOX)[0]); - - rx_energy = dB_fixed_times10(signal_energy((int32_t*)(rxdata[0]+(initial_sample_offset&(~0x1))), - SLOT_DURATION_5MHz - (SLOT_DURATION_5MHz&1))); - - sdu_received = 0; - - if (rx_energy>RX_THRES_dB) { - if (initial_sample_offset < SLOT_DURATION_5MHz) - off = initial_sample_offset + FRAME_LENGTH_SAMPLES - SLOT_DURATION_5MHz; - else - off = initial_sample_offset - SLOT_DURATION_5MHz; - - if (((dot11_state = initial_sync(&rxv, - &rx_offset, - &log2_maxh, - rxdata[0], - FRAME_LENGTH_SAMPLES, - off, - 1)) == BUSY)) { - - - //if ((frame % 100) == 0) - // printf("Channel is busy, rxv %p, offset %d\n",(void*)rxv,rx_offset); - - if (rxv) { - rx_energy = dB_fixed_times10(signal_energy((int32_t*)(rxdata[0]+rx_offset), - 80)); - // if ((frame%100) == 0) - printf("Frame %d: Rate %d, SDU_LENGTH %d,rx_offset %d,log2_maxh %d, rxp %f dBm (dig %f,rxgain %d)\n", - frame,rxv->rate,rxv->sdu_length,rx_offset,log2_maxh,(rx_energy/10.0)-rxg_max[0]+30-rxgain[0], - rx_energy/10.0,rxg_max[0]-30+rxgain[0]); - - if ((rxv->sdu_length > 1500) || (rxv->rate > 3) ) - printf("ERROR: Frame %d: Rate %d, SDU_LENGTH %d,rx_offset %d,log2_maxh %d, rxp %f dBm (dig %f,rxgain %d)\n", - frame,rxv->rate,rxv->sdu_length,rx_offset,log2_maxh,(rx_energy/10.0)-rxg_max[0]+30-rxgain[0], - rx_energy/10.0,rxg_max[0]-30+rxgain[0]); - else { - memset((void*)&data_ind_rx[10],0,rxv->sdu_length+4+2+1+16); - - <<<<<<< .mine - ======= - - if (data_detection(rxv,&data_ind_rx[10], - (uint32_t*)rxdata[0], - 76800,rx_offset,log2_maxh,NULL)) { - pos_crc++; - printf("Received SDU with positive CRC\n"); - - if (fd) { - rs = (struct ieee80211p_rx_status *)&data_ind_rx[0]; - rs->data_len = rxv->sdu_length; - rs->rssi = (char)((rx_energy/10.0)-rxg_max[0]+30-rxgain[0]); - rs->rate = 60; - rs->band = IEEE80211_BAND_0_8GHZ; - rs->flags = 0; - ret = netlink_send(fd,NLCMD_DATA,128,&data_ind_rx[0]); - } - - } else { - neg_crc++; - printf("Received SDU with negative CRC\n"); - oai_exit=1; - write_output("rxDATA_F_comp_aggreg3.m","rxDAT_F_comp_aggreg3", rxDATA_F_comp_aggreg3,48*200,1,1); - write_output("rxsig_sdu.m","rxsig_sdu",&rxdata[0][rx_offset],80*40,1,1); - - // write_output("rxDATA_F_comp_aggreg2.m","rxDAT_F_comp_aggreg2", rxDATA_F_comp_aggreg2,48*200,1,1); - } - - sdu_received = 1; - - // oai_exit = 1; - dlen = 32+16+6+(rxv->sdu_length<<3); // data length is 32-bits CRC + sdu + 16 service + 6 tail - dlen_symb = dlen/Ndbps[rxv->rate]; - - if ((dlen%Ndbps[rxv->rate])>0) - dlen_symb++; - - // printf("after dd: initial_sample_offset %d =>",initial_sample_offset); - initial_sample_offset = rx_offset + (80*dlen_symb); - // printf("%d\n",initial_sample_offset); - } - } else { - printf("BUSY, no synch (off %d) Frame %d (%llu us): rxp %f dBm (dig %f,rxgain %d)\n", - off,frame,rt_get_time_ns()/1000,(rx_energy/10.0)-rxg_max[0]+30-rxgain[0], - rx_energy/10.0,rxg_max[0]-30+rxgain[0]); - } - } else { - /* printf("Frame %d (%llu us): rxp %d dBm (dig %d,rxgain %d)\n", - frame,rt_get_time_ns()/1000,rx_energy-rxg_max[0]+30-rxgain[0], - rx_energy,rxg_max[0]-30+rxgain[0]); - */ - } - - } else { - - if (((frame%100) == 0) && (initial_sample_offset < 2*SLOT_DURATION_5MHz)) { - printf("Frame %d (%llu us): rxp %f dBm (dig %f,rxgain %d)\n", - frame,rt_get_time_ns()/1000,(rx_energy/10.0)-rxg_max[0]+30-rxgain[0], - rx_energy/10.0,rxg_max[0]-30+rxgain[0]); - - } - - if ((frame > 100) && - (tx_sdu_active == 1) && - (initial_sample_offset < 60000)) { - - printf("Frame %d: Generating SDU of length %d (%p), initial_sample_offset %d, MBOX <<9 %d\n",frame,tx_sdu_length,rxsdu,initial_sample_offset,DAQ_MBOX[0]<<9); /* - for (n=0;n FRAME_LENGTH_SAMPLES) - initial_sample_offset -= FRAME_LENGTH_SAMPLES; - - - - txlen= generate_tx_signal(initial_sample_offset); - // wait until TX is finished - - printf("TX: txlen %d, initial_sample_offset %d\n",txlen,initial_sample_offset); - //oai_exit=1; - - rt_sleep(nano2count((66666*8)+((txlen*66666)>>9))); - skip = initial_sample_offset+txlen-FRAME_LENGTH_SAMPLES; - - if (skip < 0) - skip = 0; - - printf("TX: erasing signal, MBOX %d (%d)\n",DAQ_MBOX[0],DAQ_MBOX[0]<<9); - - // erase TX signal - for (i=0; i<(txlen-skip); i++) - txdata[0][initial_sample_offset+i] = 0x00010001; - - for (i=0; i FRAME_LENGTH_SAMPLES) { - initial_sample_offset -= FRAME_LENGTH_SAMPLES; - frame++; - mbox_off = 0; - } - - tx_sdu_active = 0; - old_mbox = DAQ_MBOX[0]; - - } - - - //rt_sleep(nano2count(10000)); - // printf("back from sleep 10000 ... mbox %d\n",((unsigned int *)DAQ_MBOX)[0]); - - } - - - initial_sample_offset+=SLOT_DURATION_5MHz; - - if (initial_sample_offset>FRAME_LENGTH_SAMPLES) { - initial_sample_offset-=FRAME_LENGTH_SAMPLES; - mbox_off = 0; - frame++; - // if ((frame%100) == 0) - //printf("**** New frame %d\n",frame); - - if (frame == 100000) - oai_exit = 1; - } - - // sleep until HW has filled enough samples - - - mbox_diff = ((unsigned int*)DAQ_MBOX)[0]-old_mbox; - // if ((frame%100) == 0) - // printf("frame %d, old_mbox %d, mbox %d (initial_sample_offset %d : mbox<<9 %d)\n",frame,old_mbox,((unsigned int*)DAQ_MBOX)[0],initial_sample_offset,((unsigned int*)DAQ_MBOX)[0]<<9); - - - if ((mbox_diff>10) && (sdu_received == 0)) { - mbox_off = 0; - initial_sample_offset = ((unsigned int*)DAQ_MBOX)[0]<<9; - // printf("initial_sample_offset adjusted %d\n",initial_sample_offset); - rt_skip_cond++; - // printf("old_mbox %d, mbox %d (initial_sample_offset %d : mbox<<9 %d)\n", - // old_mbox,((unsigned int*)DAQ_MBOX)[0],initial_sample_offset,((unsigned int*)DAQ_MBOX)[0]<<9); - old_mbox = ((unsigned int *)DAQ_MBOX)[0]; - - } else { - if (old_mbox > ((unsigned int *)DAQ_MBOX)[0]) - mbox_off = 150; - - old_mbox = ((unsigned int *)DAQ_MBOX)[0]; - } - - /* - printf("off: %d (%d,%d), mbox_off %d => rx_energy %d\n",initial_sample_offset, - ((unsigned int *)DAQ_MBOX)[0], - (initial_sample_offset>>9),mbox_off, - rx_energy); - */ - - sample_threshold = initial_sample_offset+1024; - - if (sample_threshold > FRAME_LENGTH_SAMPLES) - sample_threshold -= FRAME_LENGTH_SAMPLES; - - while (old_mbox+mbox_off <= (sample_threshold>>9)) { - // if ((frame % 100) == 0) - // printf("sleeping (mbox %d, mbox_off %d, initial_sample_offset>>9 %d\n", - // old_mbox,mbox_off,(initial_sample_offset>>9)); - rt_sleep(nano2count(66666)); - - if (old_mbox > ((unsigned int *)DAQ_MBOX)[0]) - mbox_off = 150; - - old_mbox = ((unsigned int *)DAQ_MBOX)[0]; - } - - // printf("While out ... mbox %d\n",((unsigned int *)DAQ_MBOX)[0]); - - } - - printf("rt_skip_cond %d, frames %d, pos_crc %d, neg_crc %d\n", - rt_skip_cond,frame,pos_crc,neg_crc); - - printf("Dumping IS stats\n"); - print_is_stats(); - print_dd_stats(); - - write_output("rxsig0.m","rxs", rxdata[0],76800,1,1); - write_output("txsig0.m","txs", txdata[0],76800,1,1); - write_output("rxDATA_F_comp_aggreg3.m","rxDAT_F_comp_aggreg3", rxDATA_F_comp_aggreg3,48*200,1,1); - write_output("rxDATA_F_comp_aggreg2.m","rxDAT_F_comp_aggreg2", rxDATA_F_comp_aggreg2,48*200,1,1); - - printf("[DOT11][PHY] Leaving rx_thread\n"); - free(data_ind_rx); - } else { - printf("[DOT11][PHY] No netlink, exiting\n"); - } - - return(0); - - - } - - //extern int dot11_netlink_init(); - //extern int dot11_rx_thread_init(); - - //extern void *rx_thread(void *); - extern void *tx_thread(void *); - - - void dot11_init() { - - - - set_taus_seed(0); - - // Basic initializations - init_fft(64,6,rev64); - init_interleavers(); - ccodedot11_init(); - ccodedot11_init_inv(); - phy_generate_viterbi_tables(); - - init_crc32(); - - } - - int generate_tx_signal(int tx_offset) { - - TX_VECTOR_t tx_vector; - int i; - - printf("Generating Signal @ %d (MBOX << 9 = %d)\n", - tx_offset,DAQ_MBOX[0]<<9); - - if (data_ind == NULL) { - data_ind = (uint8_t*)malloc(4095+2+1); - data_ind[0] = 0; - data_ind[1] = 0; - } - - - tx_vector.rate=1; - tx_vector.sdu_length=tx_sdu_length; - tx_vector.service=0; - - for (i=0; i>>>>>> .r3153 - - // printf("Generating signal at %p\n",txdata[0]); - return(phy_tx_start(&tx_vector,txdata[0],tx_offset,FRAME_LENGTH_SAMPLES,data_ind)); - - } - - void signal_handler(int sig) { - void *array[10]; - size_t size; - - oai_exit=1; - - // get void*'s for all entries on the stack - size = backtrace(array, 10); - - // print out all the frames to stderr - fprintf(stderr, "Error: signal %d:\n", sig); - backtrace_symbols_fd(array, size, 2); - exit(-1); - } - - void exit_fun(const char* s) { - void *array[10]; - size_t size; - int fd; - - printf("Exiting: %s\n",s); - - oai_exit=1; - rt_sleep(nano2count(FRAME_PERIOD)); - - // cleanup - stop_rt_timer(); - - fd = 0; - ioctl(openair_fd,openair_STOP,&fd); - munmap((void*)mem_base, BIGPHYS_NUMPAGES*4096); - - exit (-1); - } - - int dummy_tx_buffer[3840*4] __attribute__((aligned(16))); - - /* This is the main dot11 thread. */ - static void *dot11_thread(void *arg) { - RT_TASK *task; - int slot=0,hw_slot,last_slot, next_slot,frame=0; - unsigned int msg1; - unsigned int aa,slot_offset, slot_offset_F; - int diff; - int delay_cnt; - RTIME time_in; - int mbox_target=0,mbox_current=0; - int i; - - task = rt_task_init_schmod(nam2num("TASK0"), 0, 0, 0, SCHED_FIFO, 0xF); - mlockall(MCL_CURRENT | MCL_FUTURE); - -#ifdef HARD_RT - <<<<<<< .mine - rt_printk("Started dot11 thread (id %p)\n",task); - - - rt_make_hard_real_time(); -#else - - printf("Started dot11 thread (id %p)\n",task); -#endif - ======= - rt_printk("Started dot11 thread (id %p)\n",task); - >>>>>>> .r3153 - - <<<<<<< .mine - - while (!oai_exit) { - // rt_printk("eNB: slot %d\n",slot); - ======= - >>>>>>> .r3153 - - <<<<<<< .mine - ======= - rt_make_hard_real_time(); -#else - >>>>>>> .r3153 - - printf("Started dot11 thread (id %p)\n",task); - - - <<<<<<< .mine - - if (frame>5) { - if ((frame%100)==0) -#ifdef HARD_RT - rt_printk("slot %d, hw_slot %d, next_slot %d (before): DAQ_MBOX %d\n", slot, hw_slot,next_slot,DAQ_MBOX[0]); - -#else - printf("frame %d slot %d, hw_slot %d, next_slot %d (before): DAQ_MBOX %d\n", frame,slot, hw_slot,next_slot,DAQ_MBOX[0]); -#endif - - if (fs4_test==0) { - if ((next_slot == 0) && (generate_test_tx==1) && ((frame%100)==0)) { - printf("Generating tx_signal in frame %d ...",frame); - generate_test_tx_signal(); - printf("done\n"); - - } else { // Check for normal TX packet - /*for (i=0;i<3840;i++) { - ((uint32_t *)txdata[0] + (3840*next_slot))[i] = 0x00010001; - }*/ - } - } - - - } - - - - ======= - - while (!oai_exit) { - // rt_printk("eNB: slot %d\n",slot); - - hw_slot = (((((unsigned int *)DAQ_MBOX)[0]+1)%150)<<1)/15; - //this is the mbox counter where we should be - mbox_target = ((((slot+1)%20)*15+1)>>1)%150; - //this is the mbox counter where we are - mbox_current = ((unsigned int *)DAQ_MBOX)[0]; - - //this is the time we need to sleep in order to synchronize with the hw (in multiples of DAQ_PERIOD) - if ((mbox_current>=135) && (mbox_target<15)) //handle the frame wrap-arround - diff = 150-mbox_current+mbox_target; - else if ((mbox_current<15) && (mbox_target>=135)) - diff = -150+mbox_target-mbox_current; - else - diff = mbox_target - mbox_current; - - if (diff < (-5)) { - printf("[dot11_thread] Frame %d: missed slot, proceeding with next one (slot %d, hw_slot %d, diff %d)\n",frame, slot, hw_slot, diff); - >>>>>>> .r3153 - slot++; - - if (slot==20) - <<<<<<< .mine - slot=0; - - //slot++; - if ((slot%20)==0) - frame++; - - ======= - slot=0; - continue; - >>>>>>> .r3153 - } - - if (diff>8) - printf("[dot11_thread] eNB Frame %d: skipped slot, waiting for hw to catch up (slot %d, hw_slot %d, mbox_current %d, mbox_target %d, diff %d)\n",frame, slot, hw_slot, mbox_current, mbox_target, diff); - - delay_cnt = 0; - - while ((diff>0) && (!oai_exit)) { - time_in = rt_get_time_ns(); - //rt_printk("eNB Frame %d delaycnt %d : hw_slot %d (%d), slot %d, (slot+1)*15=%d, diff %d, time %llu\n",frame,delay_cnt,hw_slot,((unsigned int *)DAQ_MBOX)[0],slot,(((slot+1)*15)>>1),diff,time_in); - //rt_printk("Frame %d: slot %d, sleeping for %llu\n", frame, slot, diff*DAQ_PERIOD); - rt_sleep(nano2count(diff*DAQ_PERIOD)); - hw_slot = (((((unsigned int *)DAQ_MBOX)[0]+1)%150)<<1)/15; - //rt_printk("eNB Frame %d : hw_slot %d, time %llu\n",frame,hw_slot,rt_get_time_ns()); - delay_cnt++; - - if (delay_cnt == 10) { - oai_exit = 1; - printf("[dot11_thread]eNB Frame %d: HW stopped ... \n",frame); - } - - mbox_current = ((unsigned int *)DAQ_MBOX)[0]; - - if ((mbox_current>=135) && (mbox_target<15)) //handle the frame wrap-arround - diff = 150-mbox_current+mbox_target; - else - diff = mbox_target - mbox_current; - } - - - last_slot = (slot)%LTE_SLOTS_PER_FRAME; - - if (last_slot <0) - last_slot+=20; - - next_slot = (slot+3)%LTE_SLOTS_PER_FRAME; - - <<<<<<< .mine - - - ======= - - if (frame>5) { - if ((frame%100)==0) -#ifdef HARD_RT - rt_printk("slot %d, hw_slot %d, next_slot %d (before): DAQ_MBOX %d\n", slot, hw_slot,next_slot,DAQ_MBOX[0]); - -#else - printf("frame %d slot %d, hw_slot %d, next_slot %d (before): DAQ_MBOX %d\n", frame,slot, hw_slot,next_slot,DAQ_MBOX[0]); -#endif - - if (fs4_test==0) { - if ((next_slot == 0) && (generate_test_tx==1) && ((frame%100)==0)) { - printf("Generating tx_signal in frame %d ...",frame); - //generate_test_tx_signal(); - printf("done\n"); - - } else { // Check for normal TX packet - /*for (i=0;i<3840;i++) { - ((uint32_t *)txdata[0] + (3840*next_slot))[i] = 0x00010001; - }*/ - } - } - - - } - - - - slot++; - - if (slot==20) - slot=0; - - //slot++; - if ((slot%20)==0) - frame++; - } - - rt_printk("fun0: finished, ran %d times.\n",slot); - -#ifdef HARD_RT - rt_make_soft_real_time(); -#endif - - // clean task - rt_task_delete(task); - rt_printk("Task deleted. returning\n"); - return 0; - } - - - - >>>>>>> .r3153 - int main(int argc, char **argv) { - - RT_TASK *task; - int i,j,aa; - - LTE_DL_FRAME_PARMS *frame_parms; - - u32 carrier_freq[4]= {1907600000,1907600000,1907600000,1907600000}; - u32 rf_mode_max[4] = {55231,55231,55231,55231}; - u32 rf_mode_med[4] = {39375,39375,39375,39375}; - u32 rf_mode_byp[4] = {22991,22991,22991,22991}; - - u32 rf_local[4] = {8255000,8255000,8255000,8255000}; // UE zepto - //{8254617, 8254617, 8254617, 8254617}; //eNB khalifa - //{8255067,8254810,8257340,8257340}; // eNB PETRONAS - - u32 rf_vcocal[4] = {2340,2340,2340,2340}; - u32 rf_rxdc[4] = {32896,32896,32896,32896}; - <<<<<<< .mine - u32 rxgain[4]= {20,20,20,20}; - ======= - >>>>>>> .r3153 - - <<<<<<< .mine - - ======= - - - >>>>>>> .r3153 - u8 eNB_id=0,UE_id=0; - u16 Nid_cell = 0; - u8 cooperation_flag=0, transmission_mode=1, abstraction_flag=0; - u8 beta_ACK=0,beta_RI=0,beta_CQI=2; - - int c; - char do_forms=0; - unsigned int fd,dot11_netlink_fd; - unsigned int tcxo = 114; - - int amp; - - char rxg_fname[100]; - char rflo_fname[100]; - FILE *rxg_fd=NULL; - FILE *rflo_fd=NULL; - - <<<<<<< .mine - ======= - - >>>>>>> .r3153 - const struct option long_options[] = { - {"calib-rx", required_argument, NULL, 256}, - {"calib-rx-med", required_argument, NULL, 257}, - {"calib-rx-byp", required_argument, NULL, 258}, - {NULL, 0, NULL, 0} - }; - - mode = normal_txrx; - - - while ((c = getopt_long (argc, argv, "C:ST:dF:t",long_options,NULL)) != -1) { - switch (c) { - case 'd': - do_forms=1; - break; - - case 't': - generate_test_tx = 1; - break; - - case 'C': - carrier_freq[0] = atoi(optarg); - carrier_freq[1] = atoi(optarg); - carrier_freq[2] = atoi(optarg); - carrier_freq[3] = atoi(optarg); - break; - - case 'S': - fs4_test=1; - break; - - case 'T': - tcxo=atoi(optarg); - break; - - case 'F': - sprintf(rxg_fname,"%srxg.lime",optarg); - rxg_fd = fopen(rxg_fname,"r"); - - if (rxg_fd) { - printf("Loading RX Gain parameters from %s\n",rxg_fname); - fscanf(rxg_fd,"%d %d %d %d",&rxg_max[0],&rxg_max[1],&rxg_max[2],&rxg_max[3]); - fscanf(rxg_fd,"%d %d %d %d",&rxg_med[0],&rxg_med[1],&rxg_med[2],&rxg_med[3]); - fscanf(rxg_fd,"%d %d %d %d",&rxg_byp[0],&rxg_byp[1],&rxg_byp[2],&rxg_byp[3]); - } else - printf("%s not found, running with defaults\n",rxg_fname); - - sprintf(rflo_fname,"%srflo.lime",optarg); - rflo_fd = fopen(rflo_fname,"r"); - - if (rflo_fd) { - printf("Loading RF LO parameters from %s\n",rflo_fname); - fscanf(rflo_fd,"%d %d %d %d",&rf_local[0],&rf_local[1],&rf_local[2],&rf_local[3]); - } else - printf("%s not found, running with defaults\n",rflo_fname); - - break; - - case 256: - mode = rx_calib_ue; - rx_input_level_dBm = atoi(optarg); - printf("Running with UE calibration on (LNA max), input level %d dBm\n",rx_input_level_dBm); - break; - - case 257: - mode = rx_calib_ue_med; - rx_input_level_dBm = atoi(optarg); - printf("Running with UE calibration on (LNA med), input level %d dBm\n",rx_input_level_dBm); - break; - - case 258: - mode = rx_calib_ue_byp; - rx_input_level_dBm = atoi(optarg); - printf("Running with UE calibration on (LNA byp), input level %d dBm\n",rx_input_level_dBm); - break; - - default: - break; - } - } - - - // to make a graceful exit when ctrl-c is pressed - signal(SIGSEGV, signal_handler); - - // init the parameters - frame_parms = (LTE_DL_FRAME_PARMS*) malloc(sizeof(LTE_DL_FRAME_PARMS)); - frame_parms->N_RB_DL = 25; - frame_parms->N_RB_UL = 25; - frame_parms->Ncp = 0; - frame_parms->Ncp_UL = 0; - frame_parms->Nid_cell = Nid_cell; - frame_parms->nushift = 0; - frame_parms->nb_antennas_tx = 1; - frame_parms->nb_antennas_rx = 1; - frame_parms->mode1_flag = 1; //default == SISO - frame_parms->frame_type = 1; - - if (fs4_test==1) - frame_parms->tdd_config = 255; - else - frame_parms->tdd_config = 3; - - frame_parms->tdd_config_S = 0; - frame_parms->phich_config_common.phich_resource = oneSixth; - frame_parms->phich_config_common.phich_duration = normal; - frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.cyclicShift = 0;//n_DMRS1 set to 0 - - frame_parms->node_id = NODE; - - // for Express MIMO - for (i=0; i<4; i++) { - frame_parms->carrier_freq[i] = carrier_freq[i]; - frame_parms->carrier_freqtx[i] = carrier_freq[i]; - - <<<<<<< .mine - frame_parms->rxgain[i] = rxgain[i]; - ======= - frame_parms->rxgain[i] = rxgain[i]; - - frame_parms->rflocal[i] = rf_local[i]; - frame_parms->rfvcolocal[i] = rf_vcocal[i]; - frame_parms->rxdc[i] = rf_rxdc[i]; - frame_parms->rfmode[i] = rf_mode_max[i]; - - >>>>>>> .r3153 - } - - printf("Freq %d,%d,%d,%d, Gain %d,%d,%d,%d, RFmode %d, RXDC %d, RF_local %d, rf_vcocal %d\n", - frame_parms->carrier_freq[0],frame_parms->carrier_freq[1],frame_parms->carrier_freq[2],frame_parms->carrier_freq[3], - frame_parms->rxgain[0],frame_parms->rxgain[1],frame_parms->rxgain[2],frame_parms->rxgain[3], - frame_parms->rfmode[0],frame_parms->rflocal[0], - frame_parms->rxdc[0],frame_parms->rfvcolocal[0]); - - - frame_parms->nb_prefix_samples0 = 40; - frame_parms->nb_prefix_samples = 36; - frame_parms->symbols_per_tti = 14; - frame_parms->ofdm_symbol_size = 512; - - frame_parms->log2_symbol_size = 9; - frame_parms->samples_per_tti = 7680; - frame_parms->first_carrier_offset = frame_parms->ofdm_symbol_size - 150; - - openair_fd = setup_oai_hw(frame_parms); - printf("Setting up buffers for Antenna port 0\n"); - setup_dot11_buffers(&(rxdata[0]),&(txdata[0]),0); - printf("Setting up buffers for Antenna port 1\n"); - setup_dot11_buffers(&(rxdata[1]),&(txdata[1]),1); - - <<<<<<< .mine - printf("Initializing dot11 DSP functions\n"); - dot11_init(); - dot11_netlink_fd = dot11_netlink_init(); - ======= - >>>>>>> .r3153 - - <<<<<<< .mine - - for (j=0; j<76800; j+=4) - for (aa=0; aanb_antennas_tx; aa++) { - amp = 0x8000; - // ((short*)PHY_vars_eNB_g[0]->lte_eNB_common_vars.txdata[0][aa])[2*j+1] = 0; - //((short*)PHY_vars_eNB_g[0]->lte_eNB_common_vars.txdata[0][aa])[2*j+3] = amp-1; - //((short*)PHY_vars_eNB_g[0]->lte_eNB_common_vars.txdata[0][aa])[2*j+5] = 0; - //((short*)PHY_vars_eNB_g[0]->lte_eNB_common_vars.txdata[0][aa])[2*j+7] = amp; - //((short*)PHY_vars_eNB_g[0]->lte_eNB_common_vars.txdata[0][aa])[2*j] = amp-1; - //((short*)PHY_vars_eNB_g[0]->lte_eNB_common_vars.txdata[0][aa])[2*j+2] = 0; - //((short*)PHY_vars_eNB_g[0]->lte_eNB_common_vars.txdata[0][aa])[2*j+4] = amp; - //((short*)PHY_vars_eNB_g[0]->lte_eNB_common_vars.txdata[0][aa])[2*j+6] = 0; - } - - sleep(1); - printf("Calling openair_GET_PCI_INTERFACE %x\n",openair_GET_PCI_INTERFACE); - ioctl(openair_fd,openair_GET_PCI_INTERFACE,&pci_interface_ptr_kern); - - if (pci_interface_ptr_kern == 0) { - printf("null pci_interface_ptr, exiting\n"); - exit(-1); - } - - ======= - - for (j=0; j<76800; j+=4) - for (aa=0; aanb_antennas_tx; aa++) { - amp = 0x8000; - // ((short*)PHY_vars_eNB_g[0]->lte_eNB_common_vars.txdata[0][aa])[2*j+1] = 0; - //((short*)PHY_vars_eNB_g[0]->lte_eNB_common_vars.txdata[0][aa])[2*j+3] = amp-1; - //((short*)PHY_vars_eNB_g[0]->lte_eNB_common_vars.txdata[0][aa])[2*j+5] = 0; - //((short*)PHY_vars_eNB_g[0]->lte_eNB_common_vars.txdata[0][aa])[2*j+7] = amp; - //((short*)PHY_vars_eNB_g[0]->lte_eNB_common_vars.txdata[0][aa])[2*j] = amp-1; - //((short*)PHY_vars_eNB_g[0]->lte_eNB_common_vars.txdata[0][aa])[2*j+2] = 0; - //((short*)PHY_vars_eNB_g[0]->lte_eNB_common_vars.txdata[0][aa])[2*j+4] = amp; - //((short*)PHY_vars_eNB_g[0]->lte_eNB_common_vars.txdata[0][aa])[2*j+6] = 0; - } - - sleep(1); - printf("Calling openair_GET_PCI_INTERFACE %x\n",openair_GET_PCI_INTERFACE); - ioctl(openair_fd,openair_GET_PCI_INTERFACE,&pci_interface_ptr_kern); - - if (pci_interface_ptr_kern == 0) { - printf("null pci_interface_ptr, exiting\n"); - exit(-1); - } - - exmimo_pci_interface = (exmimo_pci_interface_t*) (pci_interface_ptr_kern-bigphys_top+mem_base); - printf("pci_interface_ptr_kern = %p, exmimo_pci_interface = %p\n", (void*) pci_interface_ptr_kern, exmimo_pci_interface); - DAQ_MBOX = (unsigned int *)(0xc0000000+exmimo_pci_interface->rf.mbox-bigphys_top+mem_base); - - printf("Initializing dot11 DSP functions\n"); - dot11_init(); - dot11_netlink_fd = netlink_init(); - >>>>>>> .r3153 - exmimo_pci_interface = (exmimo_pci_interface_t*) (pci_interface_ptr_kern-bigphys_top+mem_base); - printf("pci_interface_ptr_kern = %p, exmimo_pci_interface = %p\n", (void*) pci_interface_ptr_kern, exmimo_pci_interface); - DAQ_MBOX = (unsigned int *)(0xc0000000+exmimo_pci_interface->rf.mbox-bigphys_top+mem_base); - - <<<<<<< .mine - ======= - printf("dot11_netlink_fd %d\n",dot11_netlink_fd); - - - - >>>>>>> .r3153 - // make main thread LXRT soft realtime - printf("Starting LXRT ..."); - task = rt_task_init_schmod(nam2num("MYTASK"), 9, 0, 0, SCHED_FIFO, 0xF); - mlockall(MCL_CURRENT | MCL_FUTURE); - - // start realtime timer and scheduler - //rt_set_oneshot_mode(); - rt_set_periodic_mode(); - start_rt_timer(0); - <<<<<<< .mine - printf(" done\n"); - ======= - printf(" done\n"); - - >>>>>>> .r3153 - <<<<<<< .mine - //now = rt_get_time() + 10*PERIOD; - //rt_task_make_periodic(task, now, PERIOD); - - // initialize the instance cnt before starting the thread - // instance_cnt_ptr_user = &instance_cnt; - - - - // signal the driver to set up for user-space operation - // this will initialize the semaphore and the task pointers in the kernel - // further we receive back the pointer to the shared instance counter which is used to signal if the thread is busy or not. This pointer needs to be mapped to user space. - /* - ioctl(openair_fd,openair_START_LXRT,&instance_cnt_ptr_kern); - instance_cnt_ptr_user = (int*) (instance_cnt_ptr_kern -bigphys_top+mem_base); - *instance_cnt_ptr_user = -1; - printf("instance_cnt_ptr_kern %p, instance_cnt_ptr_user %p, *instance_cnt_ptr_user %d\n", (void*) instance_cnt_ptr_kern, (void*) instance_cnt_ptr_user,*instance_cnt_ptr_user); - */ - - ======= - >>>>>>> .r3153 - - <<<<<<< .mine - - - rt_sleep(nano2count(FRAME_PERIOD)); - ======= - >>>>>>> .r3153 - // this starts the DMA transfers - <<<<<<< .mine - ======= - ioctl(openair_fd,openair_START_TX_SIG,NULL); - //ioctl(openair_fd,openair_GET_BUFFER,NULL); - >>>>>>> .r3153 - - <<<<<<< .mine - ioctl(openair_fd,openair_START_TX_SIG,NULL); - - - ======= - >>>>>>> .r3153 - rt_sleep(nano2count(10*FRAME_PERIOD)); - - - <<<<<<< .mine - thread1 = rt_thread_create(dot11_thread, NULL, 100000000); - ======= - //thread1 = rt_thread_create(dot11_thread, NULL, 100000000); - >>>>>>> .r3153 - - - <<<<<<< .mine - printf("thread created\n"); - ======= - thread1 = rt_thread_create(rx_thread, &dot11_netlink_fd, 10000000); - >>>>>>> .r3153 - - thread2 = rt_thread_create(tx_thread, &dot11_netlink_fd, 10000000); - - // wait for end of program - printf("TYPE TO TERMINATE main thread\n"); - getchar(); - - // stop threads - rt_sleep(nano2count(FRAME_PERIOD)); - - stop_rt_timer(); - - fd = 0; - ioctl(openair_fd,openair_STOP,&fd); - munmap((void*)mem_base, BIGPHYS_NUMPAGES*4096); - - return 0; - } diff --git a/targets/RT/USER/ieee80211p-softmodem.c b/targets/RT/USER/ieee80211p-softmodem.c deleted file mode 100644 index ffd630d40b..0000000000 --- a/targets/RT/USER/ieee80211p-softmodem.c +++ /dev/null @@ -1,185 +0,0 @@ -/****************************************************************************** - * - * Copyright(c) EURECOM / Thales Communications & Security - * - * This program is free software; you can redistribute it and/or modify it - * under the terms of version 2 of the GNU General Public License as - * published by the Free Software Foundation. - * - * This program 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 General Public License for - * more details. - * - * You should have received a copy of the GNU General Public License along with - * this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA - * - * The full GNU General Public License is included in this distribution in the - * file called LICENSE. - * - * Contact Information: - * Thales Communications & Security - * - *****************************************************************************/ - -/****************************************************************************** - * - * Includes - * - *****************************************************************************/ - -#include -#include -#include -#include "ieee80211p-netlinkapi.h" -#include "phy/DOT11/defs.h" -#include "PHY/TOOLS/defs.h" -#include -#include -#include - -#include -#include -#include - - -/****************************************************************************** - * - * Definitions - * - *****************************************************************************/ - -enum nl80211_band { - NL80211_BAND_2GHZ, - NL80211_BAND_5GHZ, - NL80211_BAND_5_9GHZ, - NL80211_BAND_0_8GHZ, -}; - -enum ieee80211_band { - IEEE80211_BAND_2GHZ = NL80211_BAND_2GHZ, - IEEE80211_BAND_5GHZ = NL80211_BAND_5GHZ, - IEEE80211_BAND_5_9GHZ = NL80211_BAND_5_9GHZ, - IEEE80211_BAND_0_8GHZ = NL80211_BAND_0_8GHZ, -}; - -struct ieee80211p_rx_status { - short data_len; //frame data length in bytes - char rssi; //received power in dBm - char rate; //reveived data rate in units of 100 kbps - enum ieee80211_band band; - char flags; //RX flags -}; /* struct ieee80211p_rx_status */ - -extern uint32_t *txdata[2],*rxdata[2]; -//CHANNEL_STATUS_t dot11_state = IDLE; -extern int oai_exit; - -extern unsigned int *DAQ_MBOX; - -extern int Ndbps[8]; - -extern int32_t rxDATA_F_comp_aggreg2[48*1024]; -extern int32_t rxDATA_F_comp_aggreg3[48*1024]; - -extern uint32_t rxgain[4]; -extern uint32_t rxg_max[4], rxg_med[4], rxg_byp[4]; - -#define FRAME_LENGTH_SAMPLES 76800 -#define RX_THRES 60 - -#define SLOT_DURATION_5MHz 105 -#define RX_THRES_dB 40 - -int tx_sdu_active = 0; -int tx_sdu_length = 0; -char rxsdu[2000]; - -void *tx_thread(void *arg) -{ - - int fd=*((int*)arg); - RT_TASK *task; - int ret; - int i; - char dummy_data[10]; - - - if (fd > 0) { - - ret = netlink_send(fd,NLCMD_INIT,10,&dummy_data[0]); - - printf("tx_thread starting, fd %d\n",fd); - - task = rt_task_init_schmod(nam2num("TASK1"), 0, 0, 0, SCHED_FIFO, 0xF); - mlockall(MCL_CURRENT | MCL_FUTURE); - // rt_make_hard_real_time(); - - while (!oai_exit) { - - if (tx_sdu_active == 1) - printf("tx_thread: waiting (MBOX %d)\n",((unsigned int*)DAQ_MBOX)[0]); - - while(((volatile int)tx_sdu_active) != 0) { - rt_sleep(nano2count(66666)); - } - - printf("tx_thread: calling netlink\n"); - ret = netlink_recv(fd,rxsdu); - tx_sdu_active = 1; - tx_sdu_length = ret; - - /* - if (ret > 0) { - - printf("received TX SDU: "); - for (i=0;i