--- /dev/null
+/******************************************************************************
+*
+* Copyright (c) 2019 Intel.
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*
+*******************************************************************************/
+
+#define _GNU_SOURCE
+#include <unistd.h>
+#include <sys/syscall.h>
+#include <sched.h>
+#include <assert.h>
+#include <err.h>
+#include <libgen.h>
+#include <sys/time.h>
+#include <time.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <pthread.h>
+
+#include "common.h"
+#include "config.h"
+
+#ifndef MLOG_ENABLED
+#include "../../lib/src/mlog_lnx_xRAN.h"
+#else
+#include "mlog_lnx.h"
+#endif
+
+
+#include "xran_fh_lls_cu.h"
+//#include "xran_pkt.h"
+//#include "xran_up_api.h"
+#include "xran_cp_api.h"
+#include "xran_sync_api.h"
+#include "xran_mlog_task_id.h"
+
+#define SW_FPGA_TOTAL_BUFFER_LEN 4*1024*1024*1024
+#define SW_FPGA_SEGMENT_BUFFER_LEN 1*1024*1024*1024
+#define SW_FPGA_FH_TOTAL_BUFFER_LEN 1*1024*1024*1024
+#define FPGA_TO_SW_PRACH_RX_BUFFER_LEN (8192)
+
+#define NSEC_PER_SEC 1000000000
+
+#define MAX_PKT_BURST (448+4) // 4x14x8
+#define N_MAX_BUFFER_SEGMENT MAX_PKT_BURST
+
+#define MAIN_PRIORITY 98
+#define NUM_OF_SUBFRAME_PER_FRAME (10)
+
+enum app_state state;
+
+uint64_t tick_per_usec;
+static volatile uint64_t timer_last_irq_tick = 0;
+static uint64_t tsc_resolution_hz = 0;
+
+RuntimeConfig startupConfiguration = {0};
+
+//FH FPGA buffer
+uint32_t nFpgaToSW_FTH_RxBufferLen;
+uint32_t nFpgaToSW_PRACH_RxBufferLen;
+uint32_t nSW_ToFpga_FTH_TxBufferLen;
+
+static XRANFHINIT xranInit;
+void * xranHandle = NULL;
+
+XRANFHCONFIG xranConf;
+PXRANFHCONFIG pXranConf = NULL;
+
+typedef struct
+{
+ uint32_t phaseFlag :1;
+ uint32_t NRARFCN :22;
+ uint32_t SULFreShift :1;
+ uint32_t SULFlag :1;
+ uint32_t rsv :7;
+}FPGAPhaseCompCfg;
+
+typedef struct XranLibConfig
+{
+ uint32_t nDriverCoreId;
+ uint32_t nTimingAdvance;
+ uint32_t nFhConfig;
+ uint32_t nFhBufIntFlag;
+ uint32_t nSectorNum;
+ uint32_t nNrOfSlotInSf;
+ uint32_t nNrofSfInFrame;
+ void * pFthInstanceHandles;
+}XranLibConfigStruct;
+typedef enum {
+ XRANFTHTX_OUT = 0,
+ XRANFTHRX_IN,
+ XRANFTHRACH_IN,
+ MAX_SW_XRAN_INTERFACE_NUM
+}SWXRANInterfaceTypeEnum;
+
+/*
+ * manage one cell's all Ethernet frames for one DL or UL LTE subframe
+ */
+typedef struct {
+ /* -1-this subframe is not used in current frame format
+ 0-this subframe can be transmitted, i.e., data is ready
+ 1-this subframe is waiting transmission, i.e., data is not ready
+ 10 - DL transmission missing deadline. When FE needs this subframe data but bValid is still 1,
+ set bValid to 10.
+ */
+ int32_t bValid ; // when UL rx, it is subframe index.
+ int32_t nSegToBeGen;
+ int32_t nSegGenerated; // how many date segment are generated by DL LTE processing or received from FE
+ // -1 means that DL packet to be transmitted is not ready in BS
+ int32_t nSegTransferred; // number of data segments has been transmitted or received
+ struct rte_mbuf *pData[N_MAX_BUFFER_SEGMENT]; // point to DPDK allocated memory pool
+ XRANBufferListStruct sBufferList;
+} BbuIoBufCtrlStruct;
+
+typedef struct {
+ uint64_t nCoreMask;
+ int16_t cpuSocketId;
+ uint8_t nDriverCoreId;
+ uint8_t nFHCoreId;
+
+ struct rte_mempool *bbuio_buf_pool;
+
+ /* io struct */
+ BbuIoBufCtrlStruct sFrontHaulTxBbuIoBufCtrl[XRAN_N_FE_BUF_LEN][XRAN_MAX_SECTOR_NR][XRAN_MAX_ANTENNA_NR];
+ BbuIoBufCtrlStruct sFrontHaulRxBbuIoBufCtrl[XRAN_N_FE_BUF_LEN][XRAN_MAX_SECTOR_NR][XRAN_MAX_ANTENNA_NR];
+ BbuIoBufCtrlStruct sFHPrachRxBbuIoBufCtrl[XRAN_N_FE_BUF_LEN][XRAN_MAX_SECTOR_NR][XRAN_MAX_ANTENNA_NR];
+
+ /* buffers lists */
+ XRANFlatBufferStruct sFrontHaulTxBuffers[XRAN_N_FE_BUF_LEN][XRAN_MAX_SECTOR_NR][XRAN_MAX_ANTENNA_NR][XRAN_NUM_OF_SYMBOL_PER_SLOT];
+ XRANFlatBufferStruct sFrontHaulRxBuffers[XRAN_N_FE_BUF_LEN][XRAN_MAX_SECTOR_NR][XRAN_MAX_ANTENNA_NR][XRAN_NUM_OF_SYMBOL_PER_SLOT];
+ XRANFlatBufferStruct sFHPrachRxBuffers[XRAN_N_FE_BUF_LEN][XRAN_MAX_SECTOR_NR][XRAN_MAX_ANTENNA_NR][XRAN_NUM_OF_SYMBOL_PER_SLOT];
+
+ void* nInstanceHandle[XRAN_PORTS_NUM][XRAN_MAX_SECTOR_NR]; // instance per sector
+ uint32_t nBufPoolIndex[XRAN_MAX_SECTOR_NR][MAX_SW_XRAN_INTERFACE_NUM]; // every api owns unique buffer pool
+ uint16_t nInstanceNum;
+
+ /*subframe type for this TTI:
+ 0: DL control + DL data
+ 1: DL control + DL data + UL control
+ 2: DL control + UL data
+ 3: DL control + UL data + UL control
+ */
+ uint8_t nSubframeType;
+
+ uint64_t nTscTiming[XRAN_N_FE_BUF_LEN]; // records the TSC when a timing packet is received.
+} BbuXranIoIfStruct;
+
+static BbuXranIoIfStruct gsXranIoIf;
+static XranLibConfigStruct *gpXranLibConfig = NULL;
+
+#define CPU_HZ tick_per_usec //us
+
+/* Application User space functions */
+void xran_fh_rx_callback(void *pCallbackTag, int32_t status);
+void xran_fh_rx_prach_callback(void *pCallbackTag, int32_t status);
+
+static BbuXranIoIfStruct *xran_get_ctx(void)
+{
+ return &gsXranIoIf;
+}
+
+static void print_menu()
+{
+ puts("+---------------------------------------+");
+ puts("| Press 1 to start 5G NR XRAN traffic |");
+ puts("| Press 2 reserved for future use |");
+ puts("| Press 3 to quit |");
+ puts("+---------------------------------------+");
+}
+
+void xran_fh_rx_callback(void *pCallbackTag, XranStatusInt32 status)
+{
+ uint64_t t1 = MLogTick();
+ uint32_t mlogVar[10];
+ uint32_t mlogVarCnt = 0;
+
+ mlogVar[mlogVarCnt++] = 0xCCCCCCCC;
+ mlogVar[mlogVarCnt++] = status >> 16; /* tti */
+ mlogVar[mlogVarCnt++] = status & 0xFF; /* sym */
+ MLogAddVariables(mlogVarCnt, mlogVar, MLogTick());
+ rte_pause();
+
+ MLogTask(PID_GNB_SYM_CB, t1, MLogTick());
+ return;
+}
+
+void xran_fh_rx_prach_callback(void *pCallbackTag, XranStatusInt32 status)
+{
+ uint64_t t1 = MLogTick();
+ rte_pause();
+ MLogTask(PID_GNB_PRACH_CB, t1, MLogTick());
+}
+
+//-------------------------------------------------------------------------------------------
+/** @ingroup group_nbiot_source_auxlib_timer
+ *
+ * @param void
+ *
+ * @return Ticks
+ *
+ * @description
+ * This function reads the rtdsc clock and returns the current value in there.
+ *
+**/
+//-------------------------------------------------------------------------------------------
+unsigned long timer_get_ticks(void)
+{
+ unsigned long ret;
+ union
+ {
+ unsigned long tsc_64;
+ struct
+ {
+ uint32_t lo_32;
+ uint32_t hi_32;
+ };
+ } tsc;
+
+ __asm volatile("rdtsc" :
+ "=a" (tsc.lo_32),
+ "=d" (tsc.hi_32));
+
+ ret = ((unsigned long)tsc.tsc_64);
+ return ret;
+}
+
+//-------------------------------------------------------------------------------------------
+/** @ingroup group_lte_source_auxlib_timer
+ *
+ * @param void
+ *
+ * @return 0 if SUCCESS
+ *
+ * @description
+ * This function gets the clock speed of the core and figures out number of ticks per usec.
+ * It is used by l1app and testmac applications to initialize the mlog utility
+ *
+**/
+//-------------------------------------------------------------------------------------------
+int timer_set_tsc_freq_from_clock(void)
+{
+#define NS_PER_SEC 1E9
+ struct timespec sleeptime = {.tv_nsec = 5E8 }; /* 1/2 second */
+ struct timespec t_start, t_end;
+ uint64_t tsc_resolution_hz = 0;
+
+ if (clock_gettime(CLOCK_MONOTONIC_RAW, &t_start) == 0)
+ {
+ unsigned long ns, end, start = timer_get_ticks();
+ nanosleep(&sleeptime,NULL);
+ clock_gettime(CLOCK_MONOTONIC_RAW, &t_end);
+ end = timer_get_ticks();
+ ns = ((t_end.tv_sec - t_start.tv_sec) * NS_PER_SEC);
+ ns += (t_end.tv_nsec - t_start.tv_nsec);
+
+ double secs = (double)ns/NS_PER_SEC;
+ tsc_resolution_hz = (unsigned long)((end - start)/secs);
+
+ tick_per_usec = (tsc_resolution_hz / 1000000);
+ printf("System clock (rdtsc) resolution %lu [Hz]\n", tsc_resolution_hz);
+ printf("Ticks per us %lu\n", tick_per_usec);
+ return 0;
+ }
+
+ return -1;
+}
+
+int physide_dl_tti_call_back(void * param)
+{
+ uint64_t t1 = MLogTick();
+ rte_pause();
+ MLogTask(PID_GNB_PROC_TIMING, t1, MLogTick());
+ return 0;
+}
+
+int physide_ul_half_slot_call_back(void * param)
+{
+ uint64_t t1 = MLogTick();
+ rte_pause();
+ MLogTask(PID_GNB_PROC_TIMING, t1, MLogTick());
+ return 0;
+}
+
+int physide_ul_full_slot_call_back(void * param)
+{
+ uint64_t t1 = MLogTick();
+ rte_pause();
+ MLogTask(PID_GNB_PROC_TIMING, t1, MLogTick());
+ return 0;
+}
+
+int32_t init_xran(void)
+{
+ BbuXranIoIfStruct *psBbuIo = xran_get_ctx();
+ XranStatusInt32 status;
+ int32_t nSectorIndex[XRAN_MAX_SECTOR_NR];
+ int32_t nSectorNum;
+ int32_t i, j, k, z;
+
+ void *ptr;
+ uint32_t *u32dptr;
+ uint16_t *u16dptr;
+ uint8_t *u8dptr;
+
+ SWXRANInterfaceTypeEnum eInterfaceType;
+
+ XranLibConfigStruct *ptrLibConfig;
+
+ XRANBufferListStruct *pFthTxBuffer[XRAN_MAX_SECTOR_NR][XRAN_MAX_ANTENNA_NR][XRAN_N_FE_BUF_LEN];
+ XRANBufferListStruct *pFthRxBuffer[XRAN_MAX_SECTOR_NR][XRAN_MAX_ANTENNA_NR][XRAN_N_FE_BUF_LEN];
+ XRANBufferListStruct *pFthRxRachBuffer[XRAN_MAX_SECTOR_NR][XRAN_MAX_ANTENNA_NR][XRAN_N_FE_BUF_LEN];
+
+ FPGAPhaseCompCfg *pPhaseCompDl = NULL;
+ FPGAPhaseCompCfg *pPhaseCompUl = NULL;
+ uint32_t nPhaseCompDl,nPhaseCompUl;
+
+
+#if 0
+ printf("init_xran: nFpgaProbe[%d] nSecNum[%d] nUENum[%d] nTimeAdvance[%d] nEthPorts[%d] nPhaseCompFlag[%d]\n",
+ psFPGAInitPara->nFpgaProbe, psFPGAInitPara->nSecNum, psFPGAInitPara->nUENum, psFPGAInitPara->nTimeAdvance, psFPGAInitPara->nEthPorts, psFPGAInitPara->nPhaseCompFlag);
+ for (i = 0; i < nSectorNum; i ++)
+ {
+ printf(" [%d]: nDlArfcn[%d] nUlArfcn[%d]\n", i, psFPGAInitPara->nDlArfcn[i], psFPGAInitPara->nUlArfcn[i]);
+ }
+#endif
+ for (nSectorNum = 0; nSectorNum < XRAN_MAX_SECTOR_NR; nSectorNum++)
+ {
+ nSectorIndex[nSectorNum] = nSectorNum;
+ }
+
+ nSectorNum = numCCPorts;
+ printf ("XRAN front haul xran_mm_init \n");
+ status = xran_mm_init (xranHandle, (uint64_t) SW_FPGA_FH_TOTAL_BUFFER_LEN, SW_FPGA_SEGMENT_BUFFER_LEN);
+ if (status != XRAN_STATUS_SUCCESS)
+ {
+ printf ("Failed at XRAN front haul xran_mm_init \n");
+ exit(-1);
+ }
+
+ psBbuIo->nInstanceNum = numCCPorts;
+
+ for (k = 0; k < XRAN_PORTS_NUM; k++) {
+ status = xran_sector_get_instances (xranHandle, psBbuIo->nInstanceNum,psBbuIo->nInstanceHandle[k]);
+ if (status != XRAN_STATUS_SUCCESS)
+ {
+ printf ("get sector instance failed %d for XRAN nInstanceNum %d\n",k, psBbuIo->nInstanceNum);
+ exit(-1);
+ }
+ }
+
+ printf("Sucess xran_mm_init \n");
+ gpXranLibConfig = (XranLibConfigStruct*)malloc(sizeof(XranLibConfigStruct));
+ ptrLibConfig = gpXranLibConfig;
+ if (ptrLibConfig)
+ {
+ #if 0
+ ptrLibConfig->nDriverCoreId = psBbuIo->nDriverCoreId;
+ ptrLibConfig->pFecInstanceHandles = &(psBbuIo->nInstanceHandle[FPGA_FEC][0]);
+ ptrLibConfig->pFthInstanceHandles = &(psBbuIo->nInstanceHandle[FPGA_FRONTHAUL][0]);
+ ptrLibConfig->nTimingAdvance = psFPGAInitPara->nTimeAdvance;
+ ptrLibConfig->nFhConfig = psFPGAInitPara->nEthPorts;
+ ptrLibConfig->nFhBufIntFlag = 0; //need init fronthaul buffer, then set to 1.
+ ptrLibConfig->nNrofSfInFrame = NUM_OF_SUBFRAME_PER_FRAME;
+ ptrLibConfig->nNrOfSlotInSf = pConfigParams->nNumOfSlotPerSubframe;
+ if (pConfigParams->nNumerology < 3)
+ {
+ ptrLibConfig->nSectorNum = psFPGAInitPara->nSecNum;
+ }
+ #endif
+ }
+ else
+ {
+ printf ("could not allocate ptrLibConfig in init_xran\n");
+ exit(-1);
+ }
+
+ printf("nSectorNum %d\n", nSectorNum);
+
+ /* Init Memory */
+ for(i = 0; i<nSectorNum; i++)
+ {
+ eInterfaceType = XRANFTHTX_OUT;
+ status = xran_bm_init(xranHandle, &psBbuIo->nBufPoolIndex[nSectorIndex[i]][eInterfaceType],
+ XRAN_N_FE_BUF_LEN*XRAN_MAX_ANTENNA_NR*XRAN_NUM_OF_SYMBOL_PER_SLOT, nSW_ToFpga_FTH_TxBufferLen);
+ if(XRAN_STATUS_SUCCESS != status)
+ {
+ printf("Failed at xran_bm_init , status %d\n", status);
+ iAssert(status == XRAN_STATUS_SUCCESS);
+ }
+ for(j = 0; j < XRAN_N_FE_BUF_LEN; j++)
+ {
+ for(z = 0; z < XRAN_MAX_ANTENNA_NR; z++){
+ psBbuIo->sFrontHaulTxBbuIoBufCtrl[j][i][z].bValid = 0;
+ psBbuIo->sFrontHaulTxBbuIoBufCtrl[j][i][z].nSegGenerated = -1;
+ psBbuIo->sFrontHaulTxBbuIoBufCtrl[j][i][z].nSegToBeGen = -1;
+ psBbuIo->sFrontHaulTxBbuIoBufCtrl[j][i][z].nSegTransferred = 0;
+ psBbuIo->sFrontHaulTxBbuIoBufCtrl[j][i][z].sBufferList.nNumBuffers = XRAN_NUM_OF_SYMBOL_PER_SLOT;
+ psBbuIo->sFrontHaulTxBbuIoBufCtrl[j][i][z].sBufferList.pBuffers = &psBbuIo->sFrontHaulTxBuffers[j][i][z][0];
+
+ for(k = 0; k < XRAN_NUM_OF_SYMBOL_PER_SLOT; k++)
+ {
+ psBbuIo->sFrontHaulTxBbuIoBufCtrl[j][i][z].sBufferList.pBuffers[k].nElementLenInBytes = nSW_ToFpga_FTH_TxBufferLen; // 14 symbols 3200bytes/symbol
+ psBbuIo->sFrontHaulTxBbuIoBufCtrl[j][i][z].sBufferList.pBuffers[k].nNumberOfElements = 1;
+ psBbuIo->sFrontHaulTxBbuIoBufCtrl[j][i][z].sBufferList.pBuffers[k].nOffsetInBytes = 0;
+ status = xran_bm_allocate_buffer(xranHandle,psBbuIo->nBufPoolIndex[nSectorIndex[i]][eInterfaceType],&ptr);
+ if(XRAN_STATUS_SUCCESS != status)
+ {
+ printf("Failed at xran_bm_allocate_buffer , status %d\n",status);
+ iAssert(status == XRAN_STATUS_SUCCESS);
+ }
+ psBbuIo->sFrontHaulTxBbuIoBufCtrl[j][i][z].sBufferList.pBuffers[k].pData = (uint8_t *)ptr;
+
+ if(ptr){
+ u32dptr = (uint32_t*)(ptr);
+ uint8_t *ptr_temp = (uint8_t *)ptr;
+ memset(u32dptr, 0xCC, nSW_ToFpga_FTH_TxBufferLen);
+ ptr_temp[0] = j; // TTI
+ ptr_temp[1] = i; // Sec
+ ptr_temp[2] = z; // Ant
+ ptr_temp[3] = k; // sym
+ }
+ }
+ }
+ }
+ }
+
+ for(i = 0; i<nSectorNum; i++)
+ {
+ eInterfaceType = XRANFTHRX_IN;
+ status = xran_bm_init(xranHandle, &psBbuIo->nBufPoolIndex[nSectorIndex[i]][eInterfaceType], XRAN_N_FE_BUF_LEN*XRAN_MAX_ANTENNA_NR*XRAN_NUM_OF_SYMBOL_PER_SLOT, nSW_ToFpga_FTH_TxBufferLen);
+ if(XRAN_STATUS_SUCCESS != status)
+ {
+ printf("Failed at xran_bm_init, status %d\n", status);
+ iAssert(status == XRAN_STATUS_SUCCESS);
+ }
+
+ for(j = 0;j < XRAN_N_FE_BUF_LEN; j++)
+ {
+ for(z = 0; z < XRAN_MAX_ANTENNA_NR; z++){
+ psBbuIo->sFrontHaulRxBbuIoBufCtrl[j][i][z].bValid = 0;
+ psBbuIo->sFrontHaulRxBbuIoBufCtrl[j][i][z].nSegGenerated = -1;
+ psBbuIo->sFrontHaulRxBbuIoBufCtrl[j][i][z].nSegToBeGen = -1;
+ psBbuIo->sFrontHaulRxBbuIoBufCtrl[j][i][z].nSegTransferred = 0;
+ psBbuIo->sFrontHaulRxBbuIoBufCtrl[j][i][z].sBufferList.nNumBuffers = XRAN_NUM_OF_SYMBOL_PER_SLOT;
+ psBbuIo->sFrontHaulRxBbuIoBufCtrl[j][i][z].sBufferList.pBuffers = &psBbuIo->sFrontHaulRxBuffers[j][i][z][0];
+ for(k = 0; k< XRAN_NUM_OF_SYMBOL_PER_SLOT; k++)
+ {
+ psBbuIo->sFrontHaulRxBbuIoBufCtrl[j][i][z].sBufferList.pBuffers[k].nElementLenInBytes = nFpgaToSW_FTH_RxBufferLen; // 1 symbols 3200bytes
+ psBbuIo->sFrontHaulRxBbuIoBufCtrl[j][i][z].sBufferList.pBuffers[k].nNumberOfElements = 1;
+ psBbuIo->sFrontHaulRxBbuIoBufCtrl[j][i][z].sBufferList.pBuffers[k].nOffsetInBytes = 0;
+ status = xran_bm_allocate_buffer(xranHandle,psBbuIo->nBufPoolIndex[nSectorIndex[i]][eInterfaceType],&ptr);
+ if(XRAN_STATUS_SUCCESS != status)
+ {
+ printf("Failed at cpa_bb_bm_allocate_buffer , status %d\n",status);
+ iAssert(status == XRAN_STATUS_SUCCESS);
+ }
+ psBbuIo->sFrontHaulRxBbuIoBufCtrl[j][i][z].sBufferList.pBuffers[k].pData = (uint8_t *)ptr;
+ if(ptr){
+ u32dptr = (uint32_t*)(ptr);
+ uint8_t *ptr_temp = (uint8_t *)ptr;
+ memset(u32dptr, 0xCC, nFpgaToSW_FTH_RxBufferLen);
+ ptr_temp[0] = j; // TTI
+ ptr_temp[1] = i; // Sec
+ ptr_temp[2] = z; // Ant
+ ptr_temp[3] = k; // sym
+ }
+ }
+ }
+ }
+ }
+
+ // add prach rx buffer
+ for(i = 0; i<nSectorNum; i++)
+ {
+ eInterfaceType = XRANFTHRACH_IN;
+ status =xran_bm_init(xranHandle,&psBbuIo->nBufPoolIndex[nSectorIndex[i]][eInterfaceType],XRAN_N_FE_BUF_LEN*XRAN_MAX_ANTENNA_NR*XRAN_NUM_OF_SYMBOL_PER_SLOT, FPGA_TO_SW_PRACH_RX_BUFFER_LEN);
+ if(XRAN_STATUS_SUCCESS != status)
+ {
+ printf("Failed at xran_bm_init, status %d\n", status);
+ iAssert(status == XRAN_STATUS_SUCCESS);
+ }
+ for(j = 0;j < XRAN_N_FE_BUF_LEN; j++)
+ {
+ for(z = 0; z < XRAN_MAX_ANTENNA_NR; z++){
+ psBbuIo->sFHPrachRxBbuIoBufCtrl[j][i][z].bValid = 0;
+ psBbuIo->sFHPrachRxBbuIoBufCtrl[j][i][z].nSegGenerated = -1;
+ psBbuIo->sFHPrachRxBbuIoBufCtrl[j][i][z].nSegToBeGen = -1;
+ psBbuIo->sFHPrachRxBbuIoBufCtrl[j][i][z].nSegTransferred = 0;
+ psBbuIo->sFHPrachRxBbuIoBufCtrl[j][i][z].sBufferList.nNumBuffers = XRAN_MAX_ANTENNA_NR; // ant number.
+ psBbuIo->sFHPrachRxBbuIoBufCtrl[j][i][z].sBufferList.pBuffers = &psBbuIo->sFHPrachRxBuffers[j][i][z][0];
+ //for(k = 0; k< XRAN_NUM_OF_SYMBOL_PER_SLOT; k++)
+ k = 0; // one PRACH buffer per antenna per slot
+ {
+ psBbuIo->sFHPrachRxBbuIoBufCtrl[j][i][z].sBufferList.pBuffers[k].nElementLenInBytes = FPGA_TO_SW_PRACH_RX_BUFFER_LEN;
+ psBbuIo->sFHPrachRxBbuIoBufCtrl[j][i][z].sBufferList.pBuffers[k].nNumberOfElements = 1;
+ psBbuIo->sFHPrachRxBbuIoBufCtrl[j][i][z].sBufferList.pBuffers[k].nOffsetInBytes = 0;
+ status = xran_bm_allocate_buffer(xranHandle,psBbuIo->nBufPoolIndex[nSectorIndex[i]][eInterfaceType],&ptr);
+ if(XRAN_STATUS_SUCCESS != status)
+ {
+ printf("Failed at xran_bm_allocate_buffer, status %d\n",status);
+ iAssert(status == XRAN_STATUS_SUCCESS);
+ }
+ psBbuIo->sFHPrachRxBbuIoBufCtrl[j][i][z].sBufferList.pBuffers[k].pData = (uint8_t *)ptr;
+ if(ptr){
+ u32dptr = (uint32_t*)(ptr);
+ memset(u32dptr, 0xCC, FPGA_TO_SW_PRACH_RX_BUFFER_LEN);
+ }
+ }
+ }
+ }
+ }
+
+ for(i=0; i<nSectorNum; i++)
+ {
+ for(j=0; j<XRAN_N_FE_BUF_LEN; j++)
+ {
+ for(z = 0; z < XRAN_MAX_ANTENNA_NR; z++){
+ pFthTxBuffer[i][z][j] = &(psBbuIo->sFrontHaulTxBbuIoBufCtrl[j][i][z].sBufferList);
+ pFthRxBuffer[i][z][j] = &(psBbuIo->sFrontHaulRxBbuIoBufCtrl[j][i][z].sBufferList);
+ pFthRxRachBuffer[i][z][j] = &(psBbuIo->sFHPrachRxBbuIoBufCtrl[j][i][z].sBufferList);
+ }
+ }
+ }
+
+ if(NULL != psBbuIo->nInstanceHandle[0])
+ {
+ for (i = 0; i<nSectorNum; i++)
+ {
+ xran_5g_fronthault_config (psBbuIo->nInstanceHandle[0][i],
+ pFthTxBuffer[i],
+ pFthRxBuffer[i],
+ xran_fh_rx_callback, &pFthRxBuffer[i][0]);
+ }
+
+ // add prach callback here
+ for (i = 0; i<nSectorNum; i++)
+ {
+ xran_5g_prach_req(psBbuIo->nInstanceHandle[0][i], pFthRxRachBuffer[i],
+ xran_fh_rx_prach_callback,&pFthRxRachBuffer[i][0]);
+ }
+ ptrLibConfig->nFhBufIntFlag = 1;
+ }
+
+ /*config phase compensation*/
+ /* TODO: add phase compensation handling */
+ for(i=0; i<nSectorNum; i++)
+ {
+ pPhaseCompDl = (FPGAPhaseCompCfg *)(&nPhaseCompDl);
+ pPhaseCompDl->NRARFCN = 0;//psFPGAInitPara->nDlArfcn[i];
+ pPhaseCompDl->phaseFlag = 0;//psFPGAInitPara->nPhaseCompFlag;
+ pPhaseCompDl->SULFlag = 0;
+ pPhaseCompDl->SULFreShift = 0;
+ pPhaseCompDl->rsv = 0;
+
+ pPhaseCompUl = (FPGAPhaseCompCfg *)(&nPhaseCompUl);
+ pPhaseCompUl->NRARFCN = 0;//psFPGAInitPara->nUlArfcn[i];
+ pPhaseCompUl->phaseFlag = 0;// psFPGAInitPara->nPhaseCompFlag;
+ pPhaseCompUl->SULFlag = 0;
+ pPhaseCompUl->SULFreShift = 0;
+ pPhaseCompUl->rsv = 0;
+
+ xran_5g_pre_compenstor_cfg(psBbuIo->nInstanceHandle[0][i],nPhaseCompDl,nPhaseCompUl,i);
+
+ printf("@@@ NB cell %d DL NR-ARFCN %d,DL phase comp flag %d UL NR-ARFCN %d,UL phase comp flag %d \n",
+ i,pPhaseCompDl->NRARFCN,pPhaseCompDl->phaseFlag,
+ pPhaseCompUl->NRARFCN,pPhaseCompUl->phaseFlag);
+ }
+ return status;
+}
+
+int init_xran_iq_content(void)
+{
+ BbuXranIoIfStruct *psBbuIo = xran_get_ctx();
+ XranStatusInt32 status;
+ int32_t nSectorIndex[XRAN_MAX_SECTOR_NR];
+ int32_t nSectorNum;
+ int32_t cc_id, ant_id, sym_id, tti;
+ int32_t flowId;
+
+ uint8_t frame_id = 0;
+ uint8_t subframe_id = 0;
+ uint8_t slot_id = 0;
+ uint8_t sym = 0;
+
+ void *ptr;
+ uint32_t *u32dptr;
+ uint16_t *u16dptr;
+ uint8_t *u8dptr;
+
+ char *pos = NULL;
+
+ for (nSectorNum = 0; nSectorNum < XRAN_MAX_SECTOR_NR; nSectorNum++)
+ {
+ nSectorIndex[nSectorNum] = nSectorNum;
+ }
+ nSectorNum = numCCPorts;
+ printf ("init_xran_iq_content\n");
+
+ /* Init Memory */
+ for(cc_id = 0; cc_id <nSectorNum; cc_id++)
+ {
+ for(tti = 0; tti < XRAN_N_FE_BUF_LEN; tti ++) {
+ for(ant_id = 0; ant_id < XRAN_MAX_ANTENNA_NR; ant_id++){
+ for(sym_id = 0; sym_id < XRAN_NUM_OF_SYMBOL_PER_SLOT; sym_id++) {
+ flowId = nSectorNum * ant_id + cc_id;
+
+ if(p_tx_play_buffer[flowId]){
+ /* (0-79 slots) 10ms of IQs */
+ pos = ((char*)p_tx_play_buffer[flowId]) + tx_play_buffer_position[flowId];
+
+ ptr = psBbuIo->sFrontHaulTxBbuIoBufCtrl[tti][cc_id][ant_id].sBufferList.pBuffers[sym_id].pData;
+
+ if(ptr){
+ u32dptr = (uint32_t*)(ptr);
+ rte_memcpy(u32dptr, pos, PDSCH_PAYLOAD_SIZE);
+#ifdef DEBUG_XRAN_BUFFERS
+ uint8_t *ptr_temp = (uint8_t *)ptr;
+ ptr_temp[0] = tti; // TTI
+ ptr_temp[1] = cc_id; // Sec
+ ptr_temp[2] = ant_id; // Ant
+ ptr_temp[3] = sym_id; // sym
+#endif
+ }else
+ printf("ptr ==NULL\n");
+
+ tx_play_buffer_position[flowId] += PDSCH_PAYLOAD_SIZE;
+
+ if(tx_play_buffer_position[flowId] >= tx_play_buffer_size[flowId])
+ tx_play_buffer_position[flowId] = 0;
+ } else {
+ //printf("flowId %d\n", flowId);
+ }
+ }
+ }
+ }
+
+ }
+
+ return 0;
+}
+
+void stop_xran(void)
+{
+ XranStatusInt32 status = 0;
+ SWXRANInterfaceTypeEnum eInterfaceType;
+
+ free(gpXranLibConfig);
+ gpXranLibConfig = NULL;
+
+ status += xran_mm_destroy(xranHandle)*2;
+
+ if(XRAN_STATUS_SUCCESS != status)
+ {
+ printf("Failed at xran_mm_destroy, status %d\n",status);
+ iAssert(status == XRAN_STATUS_SUCCESS);
+ }
+}
+
+int32_t get_xran_sfidx(uint8_t nNrOfSlotInSf)
+{
+ int32_t nSfIdx = -1;
+ uint32_t nFrameIdx;
+ uint32_t nSubframeIdx;
+ uint32_t nSlotIdx;
+ uint64_t nSecond;
+
+ uint32_t nXranTime = xran_get_slot_idx(&nFrameIdx, &nSubframeIdx, &nSlotIdx, &nSecond);
+ nSfIdx = nFrameIdx*NUM_OF_SUBFRAME_PER_FRAME*nNrOfSlotInSf
+ + nSubframeIdx*nNrOfSlotInSf
+ + nSlotIdx;
+#if 0
+ printf("\nxranTime is %d, return is %d, radio frame is %d, subframe is %d slot is %d tsc is %llu us",
+ nXranTime,
+ nSfIdx,
+ nFrameIdx,
+ nSubframeIdx,
+ nSlotIdx,
+ __rdtsc()/CPU_HZ);
+#endif
+
+ return nSfIdx;
+}
+
+int get_xran_iq_content(void)
+{
+ BbuXranIoIfStruct *psBbuIo = xran_get_ctx();
+ XranStatusInt32 status;
+ int32_t nSectorIndex[XRAN_MAX_SECTOR_NR];
+ int32_t nSectorNum;
+ int32_t cc_id, ant_id, sym_id, tti;
+ int32_t flowId;
+
+ uint8_t frame_id = 0;
+ uint8_t subframe_id = 0;
+ uint8_t slot_id = 0;
+ uint8_t sym = 0;
+
+ void *ptr;
+ uint32_t *u32dptr;
+ uint16_t *u16dptr;
+ uint8_t *u8dptr;
+
+ char *pos = NULL;
+
+ for (nSectorNum = 0; nSectorNum < XRAN_MAX_SECTOR_NR; nSectorNum++)
+ {
+ nSectorIndex[nSectorNum] = nSectorNum;
+ }
+ nSectorNum = numCCPorts;
+ printf ("get_xran_iq_content\n");
+
+ /* Init Memory */
+ for(cc_id = 0; cc_id <nSectorNum; cc_id++)
+ {
+ for(tti = 0; tti < XRAN_N_FE_BUF_LEN; tti++) {
+ for(ant_id = 0; ant_id < XRAN_MAX_ANTENNA_NR; ant_id++){
+ for(sym_id = 0; sym_id < XRAN_NUM_OF_SYMBOL_PER_SLOT; sym_id++) {
+ flowId = nSectorNum * ant_id + cc_id;
+ if(p_rx_log_buffer[flowId]){
+ /* (0-79 slots) 10ms of IQs */
+ pos = ((char*)p_rx_log_buffer[flowId]) + rx_log_buffer_position[flowId];
+ ptr = psBbuIo->sFrontHaulRxBbuIoBufCtrl[tti][cc_id][ant_id].sBufferList.pBuffers[sym_id].pData;
+ if(ptr){
+ u32dptr = (uint32_t*)(ptr);
+ rte_memcpy(pos, u32dptr, PDSCH_PAYLOAD_SIZE);
+#ifdef DEBUG_XRAN_BUFFERS
+ if (pos[0] != tti||
+ pos[1] != cc_id ||
+ pos[2] != ant_id ||
+ pos[3] != sym_id){
+ printf("[flowId %d] %d %d %d %d\n", flowId, pos[0], pos[1], pos[2], pos[3]);
+ }
+#endif
+ }else
+ printf("ptr ==NULL\n");
+
+ rx_log_buffer_position[flowId] += PDSCH_PAYLOAD_SIZE;
+
+ if(rx_log_buffer_position[flowId] >= rx_log_buffer_size[flowId])
+ rx_log_buffer_position[flowId] = 0;
+ } else {
+ //printf("flowId %d\n", flowId);
+ }
+ }
+ }
+ }
+ }
+
+ return 0;
+}
+
+int main(int argc, char *argv[])
+{
+ int i;
+ int j;
+ int lcore_id = 0;
+ char filename[64];
+
+ if (argc == 3)
+ errx(2, "Need two argument - the PCI address of the network port");
+
+ if (xran_is_synchronized() != 0)
+ printf("Machine is not synchronized using PTP!\n");
+ else
+ printf("Machine is synchronized using PTP!\n");
+
+ memset(&startupConfiguration, 0, sizeof(RuntimeConfig));
+
+ if (parseConfigFile(argv[1], &startupConfiguration) != 0) {
+ printf("Configuration file error.\n");
+ return 0;
+ }
+
+ if(startupConfiguration.ant_file[0] == NULL){
+ printf("it looks like test vector for antennas were not provided\n");
+ exit(-1);
+ }
+
+ numCCPorts = startupConfiguration.numCC;
+ num_eAxc = startupConfiguration.numAxc;
+
+ printf("numCCPorts %d num_eAxc%d\n", numCCPorts, num_eAxc);
+
+ /* Numerology 3 */
+ nFpgaToSW_FTH_RxBufferLen = 3328; //3200 * 14;
+ nFpgaToSW_PRACH_RxBufferLen = 8192;
+ nSW_ToFpga_FTH_TxBufferLen = 3328; //3200; * 14;
+
+ memset(&xranInit, 0, sizeof(XRANFHINIT));
+
+ if(startupConfiguration.appMode == APP_LLS_CU) {
+ printf("set lls-CU\n");
+ xranInit.io_cfg.id = 0;//ID_LLS_CU;
+ xranInit.io_cfg.core = 4+1;
+ xranInit.io_cfg.system_core = 0;
+ xranInit.io_cfg.pkt_proc_core = 4+2;
+ xranInit.io_cfg.pkt_aux_core = 0; /* do not start*/
+ xranInit.io_cfg.timing_core = 4+3;
+ } else {
+ printf("set RU\n");
+ xranInit.io_cfg.id = 1; /* ID_LLS_CU;*/
+ xranInit.io_cfg.core = 1;
+ xranInit.io_cfg.system_core = 0;
+ xranInit.io_cfg.pkt_proc_core = 2;
+ xranInit.io_cfg.pkt_aux_core = 0; /* do not start */
+ xranInit.io_cfg.timing_core = 3;
+ }
+
+ xranInit.llscuId = 0; // for ecpriRtcid/ecpriPcid
+ xranInit.nSec = 1; // shall be one
+
+ xranInit.eAxCId_conf.mask_cuPortId = 0xf000;
+ xranInit.eAxCId_conf.mask_bandSectorId = 0x0f00;
+ xranInit.eAxCId_conf.mask_ccId = 0x00f0;
+ xranInit.eAxCId_conf.mask_ruPortId = 0x000f;
+ xranInit.eAxCId_conf.bit_cuPortId = 12;
+ xranInit.eAxCId_conf.bit_bandSectorId = 8;
+ xranInit.eAxCId_conf.bit_ccId = 4;
+ xranInit.eAxCId_conf.bit_ruPortId = 0;
+
+ xranInit.io_cfg.dpdk_dev[XRAN_UP_VF] = argv[2];
+ xranInit.io_cfg.dpdk_dev[XRAN_CP_VF] = argv[3];
+ xranInit.p_lls_cu_addr = (int8_t*)&startupConfiguration.lls_cu_addr;
+ xranInit.p_ru_addr = (int8_t*)&startupConfiguration.ru_addr;
+ xranInit.ttiPeriod = startupConfiguration.ttiPeriod;
+
+ xranInit.Tadv_cp_dl = startupConfiguration.Tadv_cp_dl;
+ xranInit.T2a_min_cp_dl = startupConfiguration.T2a_min_cp_dl;
+ xranInit.T2a_max_cp_dl = startupConfiguration.T2a_max_cp_dl;
+ xranInit.T2a_min_cp_ul = startupConfiguration.T2a_min_cp_ul;
+ xranInit.T2a_max_cp_ul = startupConfiguration.T2a_max_cp_ul;
+ xranInit.T2a_min_up = startupConfiguration.T2a_min_up;
+ xranInit.T2a_max_up = startupConfiguration.T2a_max_up;
+ xranInit.Ta3_min = startupConfiguration.Ta3_min;
+ xranInit.Ta3_max = startupConfiguration.Ta3_max;
+ xranInit.T1a_min_cp_dl = startupConfiguration.T1a_min_cp_dl;
+ xranInit.T1a_max_cp_dl = startupConfiguration.T1a_max_cp_dl;
+ xranInit.T1a_min_cp_ul = startupConfiguration.T1a_min_cp_ul;
+ xranInit.T1a_max_cp_ul = startupConfiguration.T1a_max_cp_ul;
+ xranInit.T1a_min_up = startupConfiguration.T1a_min_up;
+ xranInit.T1a_max_up = startupConfiguration.T1a_max_up;
+ xranInit.Ta4_min = startupConfiguration.Ta4_min;
+ xranInit.Ta4_max = startupConfiguration.Ta4_max;
+
+ xranInit.enableCP = startupConfiguration.enableCP;
+ xranInit.debugStop = startupConfiguration.debugStop;
+
+ xranInit.cp_vlan_tag = startupConfiguration.cp_vlan_tag;
+ xranInit.up_vlan_tag = startupConfiguration.up_vlan_tag;
+
+
+ for(i = 0; i < MAX_ANT_CARRIER_SUPPORTED && i < (uint32_t)(numCCPorts * num_eAxc); i++) {
+
+ p_tx_play_buffer[i] = (int16_t*)malloc(IQ_PLAYBACK_BUFFER_BYTES);
+ tx_play_buffer_size[i] = (int32_t)IQ_PLAYBACK_BUFFER_BYTES;
+
+ if (p_tx_play_buffer[i] == NULL)
+ exit(-1);
+
+ tx_play_buffer_size[i] = sys_load_file_to_buff(startupConfiguration.ant_file[i],
+ "DL IFFT IN IQ Samples in binary format",
+ (uint8_t*) p_tx_play_buffer[i],
+ tx_play_buffer_size[i],
+ 1);
+ tx_play_buffer_position[i] = 0;
+ }
+
+ /* log of ul */
+ for(i = 0; i < MAX_ANT_CARRIER_SUPPORTED && i < (uint32_t)(numCCPorts * num_eAxc); i++) {
+
+ p_rx_log_buffer[i] = (int16_t*)malloc(IQ_PLAYBACK_BUFFER_BYTES);
+ rx_log_buffer_size[i] = (int32_t)IQ_PLAYBACK_BUFFER_BYTES;
+
+ if (p_rx_log_buffer[i] == NULL)
+ exit(-1);
+
+ rx_log_buffer_position[i] = 0;
+
+ memset(p_rx_log_buffer[i], 0, rx_log_buffer_size[i]);
+ }
+
+ /* log of Prach */
+ for(i = 0; i < MAX_ANT_CARRIER_SUPPORTED && i < (uint32_t)(numCCPorts * num_eAxc); i++) {
+
+ p_prach_log_buffer[i] = (int16_t*)malloc(PRACH_PLAYBACK_BUFFER_BYTES);
+ prach_log_buffer_size[i] = (int32_t)PRACH_PLAYBACK_BUFFER_BYTES;
+
+ if (p_prach_log_buffer[i] == NULL)
+ exit(-1);
+
+ memset(p_prach_log_buffer[i], 0, prach_log_buffer_size[i]);
+ prach_log_buffer_position[i] = 0;
+ }
+
+ for (i = 0; i < MAX_ANT_CARRIER_SUPPORTED && i < (uint32_t)(numCCPorts * num_eAxc); i++) {
+
+ sprintf(filename, "%s-play_ant%d.txt",((startupConfiguration.appMode == APP_LLS_CU) ? "lls-cu" : "ru"), i);
+ sys_save_buf_to_file_txt(filename,
+ "DL IFFT IN IQ Samples in human readable format",
+ (uint8_t*) p_tx_play_buffer[i],
+ tx_play_buffer_size[i],
+ 1);
+
+ sprintf(filename, "%s-play_ant%d.bin",((startupConfiguration.appMode == APP_LLS_CU) ? "lls-cu" : "ru"), i);
+ sys_save_buf_to_file(filename,
+ "DL IFFT IN IQ Samples in binary format",
+ (uint8_t*) p_tx_play_buffer[i],
+ tx_play_buffer_size[i]/sizeof(short),
+ sizeof(short));
+ }
+ if (startupConfiguration.iqswap == 1){
+ for(i = 0; i < MAX_ANT_CARRIER_SUPPORTED && i < (uint32_t)(numCCPorts * num_eAxc); i++) {
+ printf("TX: Swap I and Q to match RU format: [%d]\n",i);
+ {
+ /* swap I and Q */
+ int32_t j;
+ signed short *ptr = (signed short *) p_tx_play_buffer[i];
+ signed short temp;
+
+ for (j = 0; j < (int32_t)(tx_play_buffer_size[i]/sizeof(short)) ; j = j + 2){
+ temp = ptr[j];
+ ptr[j] = ptr[j + 1];
+ ptr[j + 1] = temp;
+ }
+ }
+ }
+ }
+
+#if 0
+ for (i = 0; i < MAX_ANT_CARRIER_SUPPORTED && i < (uint32_t)(numCCPorts * num_eAxc); i++) {
+
+ sprintf(filename, "swap_IQ_play_ant%d.txt", i);
+ sys_save_buf_to_file_txt(filename,
+ "DL IFFT IN IQ Samples in human readable format",
+ (uint8_t*) p_tx_play_buffer[i],
+ tx_play_buffer_size[i],
+ 1);
+ }
+#endif
+ if (startupConfiguration.nebyteorderswap == 1){
+ for(i = 0; i < MAX_ANT_CARRIER_SUPPORTED && i < (uint32_t)(numCCPorts * num_eAxc); i++) {
+ printf("TX: Convert S16 I and S16 Q to network byte order for XRAN Ant: [%d]\n",i);
+ for (j = 0; j < tx_play_buffer_size[i]/sizeof(short); j++){
+ p_tx_play_buffer[i][j] = rte_cpu_to_be_16(p_tx_play_buffer[i][j]);
+ }
+ }
+ }
+
+#if 0
+ for (i = 0; i < MAX_ANT_CARRIER_SUPPORTED && i < (uint32_t)(numCCPorts * num_eAxc); i++) {
+
+ sprintf(filename, "swap_be_play_ant%d.txt", i);
+ sys_save_buf_to_file_txt(filename,
+ "DL IFFT IN IQ Samples in human readable format",
+ (uint8_t*) p_tx_play_buffer[i],
+ tx_play_buffer_size[i],
+ 1);
+ }
+#endif
+
+ timer_set_tsc_freq_from_clock();
+ xran_init(argc, argv, &xranInit, argv[0], &xranHandle);
+ if(xranHandle == NULL)
+ exit(1);
+
+ memset(&xranConf, 0, sizeof(XRANFHCONFIG));
+ pXranConf = &xranConf;
+
+ for(i = 0; i < MAX_ANT_CARRIER_SUPPORTED && i < (uint32_t)(numCCPorts * num_eAxc); i++) {
+ pXranConf->playback_conf.TxPlayBufAddr[i] = (unsigned long)p_tx_play_buffer[i];
+ pXranConf->playback_conf.TxPlayBufSize = tx_play_buffer_size[i];
+ }
+
+ pXranConf->sector_id = 0;
+ pXranConf->nCC = numCCPorts;
+ pXranConf->neAxc = num_eAxc;
+
+ pXranConf->frame_conf.nFrameDuplexType = 1; // TDD
+ pXranConf->frame_conf.nNumerology = startupConfiguration.mu_number; // 120KHz; same as XRAN_SCS_120KHz?
+// pXranConf->frame_conf.nTddPeriod = ;
+
+ pXranConf->prach_conf.nPrachSubcSpacing = XRAN_SCS_120KHZ;
+ pXranConf->prach_conf.nPrachFreqStart = 0;
+ pXranConf->prach_conf.nPrachFilterIdx = XRAN_FILTERINDEX_PRACH_ABC;
+ pXranConf->prach_conf.nPrachConfIdx = 81;
+ pXranConf->prach_conf.nPrachFreqOffset = -792;
+
+ pXranConf->ru_conf.iqWidth = 16;
+ pXranConf->ru_conf.compMeth = XRAN_COMPMETHOD_NONE;
+ pXranConf->ru_conf.fftSize = XRAN_FFTSIZE_2048;
+
+
+ if(init_xran() != 0)
+ exit(-1);
+
+ xran_reg_physide_cb(xranHandle, physide_dl_tti_call_back, NULL, 10, XRAN_CB_TTI);
+ xran_reg_physide_cb(xranHandle, physide_ul_half_slot_call_back, NULL, 10, XRAN_CB_HALF_SLOT_RX);
+ xran_reg_physide_cb(xranHandle, physide_ul_full_slot_call_back, NULL, 10, XRAN_CB_FULL_SLOT_RX);
+
+ init_xran_iq_content();
+
+ xran_open(xranHandle, pXranConf);
+
+ sprintf(filename, "mlog-%s", startupConfiguration.appMode == 0 ? "lls-cu" : "ru");
+
+ MLogOpen(0, 32, 0, 0xFFFFFFFF, filename);
+ puts("----------------------------------------");
+ printf("MLog Info: virt=0x%016lx size=%d\n", MLogGetFileLocation(), MLogGetFileSize());
+ puts("----------------------------------------");
+
+ state = APP_RUNNING;
+ sleep(6);
+ for (;;) {
+ print_menu();
+ char input[10];
+ int sel_opt;
+//#ifdef Nightly_build
+// sel_opt = 3;
+// sleep(10);
+//#else
+ if (NULL == fgets(input, 10, stdin)) {
+ state = APP_STOPPED;
+ break;
+ }
+ sel_opt = atoi(input);
+//#endif
+ switch (sel_opt) {
+ case 1:
+ xran_start(xranHandle);
+ printf("Start XRAN traffic\n");
+ break;
+ case 2:
+ break;
+ case 3:
+ xran_stop(xranHandle);
+ printf("Stop XRAN traffic\n");
+ state = APP_STOPPED;
+ break;
+ case 4:
+// send_cpmsg_dlul(XRAN_DIR_DL, flowId,
+// frame_id, subframe_id, slot_id,
+// 0, XRAN_SYMBOLPERSLOT_MAX, NUM_OF_PRB_IN_FULL_BAND,
+// beam_id, cc_id, ant_id,
+// cp_seq_id_num[XRAN_DIR_DL][ant_id]++);
+ break;
+ default:
+ puts("Wrong option passed!");
+ break;
+ }
+
+ if (APP_STOPPED == state)
+ break;
+ }
+
+ get_xran_iq_content();
+
+ puts("Closing l1 app... Ending all threads...");
+ xran_close(xranHandle);
+ MLogPrint(NULL);
+
+ stop_xran();
+ puts("Dump IQs...");
+
+ if (startupConfiguration.iqswap == 1){
+ for(i = 0; i < MAX_ANT_CARRIER_SUPPORTED && i < (uint32_t)(numCCPorts * num_eAxc); i++) {
+ printf("RX: Swap I and Q to match CPU format: [%d]\n",i);
+ {
+ /* swap I and Q */
+ int32_t j;
+ signed short *ptr = (signed short *) p_rx_log_buffer[i];
+ signed short temp;
+
+ for (j = 0; j < (int32_t)(rx_log_buffer_size[i]/sizeof(short)) ; j = j + 2){
+ temp = ptr[j];
+ ptr[j] = ptr[j + 1];
+ ptr[j + 1] = temp;
+ }
+ }
+ }
+ }
+
+ if (startupConfiguration.nebyteorderswap == 1){
+ for(i = 0; i < MAX_ANT_CARRIER_SUPPORTED && i < (uint32_t)(numCCPorts * num_eAxc); i++) {
+ printf("RX: Convert S16 I and S16 Q to cpu byte order from XRAN Ant: [%d]\n",i);
+ for (j = 0; j < rx_log_buffer_size[i]/sizeof(short); j++){
+ p_rx_log_buffer[i][j] = rte_be_to_cpu_16(p_rx_log_buffer[i][j]);
+ }
+ }
+ }
+
+ for (i = 0; i < MAX_ANT_CARRIER_SUPPORTED && i < (uint32_t)(numCCPorts * num_eAxc); i++) {
+
+ sprintf(filename, "%s-rx_log_ant%d.txt",((startupConfiguration.appMode == APP_LLS_CU) ? "lls-cu" : "ru"), i);
+ sys_save_buf_to_file_txt(filename,
+ "UL FFT OUT IQ Samples in human readable format",
+ (uint8_t*) p_rx_log_buffer[i],
+ rx_log_buffer_size[i],
+ 1);
+
+ sprintf(filename, "%s-rx_log_ant%d.bin",((startupConfiguration.appMode == APP_LLS_CU) ? "lls-cu" : "ru"), i);
+ sys_save_buf_to_file(filename,
+ "UL FFT OUT IQ Samples in binary format",
+ (uint8_t*) p_rx_log_buffer[i],
+ rx_log_buffer_size[i]/sizeof(short),
+ sizeof(short));
+ }
+
+ if (startupConfiguration.iqswap == 1){
+ for(i = 0; i < MAX_ANT_CARRIER_SUPPORTED && i < (uint32_t)(numCCPorts * num_eAxc); i++) {
+ printf("PRACH: Swap I and Q to match CPU format: [%d]\n",i);
+ {
+ /* swap I and Q */
+ int32_t j;
+ signed short *ptr = (signed short *) p_prach_log_buffer[i];
+ signed short temp;
+
+ for (j = 0; j < (int32_t)(prach_log_buffer_size[i]/sizeof(short)) ; j = j + 2){
+ temp = ptr[j];
+ ptr[j] = ptr[j + 1];
+ ptr[j + 1] = temp;
+ }
+ }
+ }
+ }
+
+ if (startupConfiguration.nebyteorderswap == 1){
+ for(i = 0; i < MAX_ANT_CARRIER_SUPPORTED && i < (uint32_t)(numCCPorts * num_eAxc); i++) {
+ printf("PRACH: Convert S16 I and S16 Q to cpu byte order from XRAN Ant: [%d]\n",i);
+ for (j = 0; j < prach_log_buffer_size[i]/sizeof(short); j++){
+ p_prach_log_buffer[i][j] = rte_be_to_cpu_16(p_prach_log_buffer[i][j]);
+ }
+ }
+ }
+
+ for (i = 0; i < MAX_ANT_CARRIER_SUPPORTED && i < (uint32_t)(numCCPorts * num_eAxc); i++) {
+
+ sprintf(filename, "%s-prach_log_ant%d.txt",((startupConfiguration.appMode == APP_LLS_CU) ? "lls-cu" : "ru"), i);
+ sys_save_buf_to_file_txt(filename,
+ "PRACH FFT OUT IQ Samples in human readable format",
+ (uint8_t*) p_prach_log_buffer[i],
+ prach_log_buffer_size[i],
+ 1);
+
+ sprintf(filename, "%s-prach_log_ant%d.bin",((startupConfiguration.appMode == APP_LLS_CU) ? "lls-cu" : "ru"), i);
+ sys_save_buf_to_file(filename,
+ "PRACH FFT OUT IQ Samples in binary format",
+ (uint8_t*) p_prach_log_buffer[i],
+ prach_log_buffer_size[i]/sizeof(short),
+ sizeof(short));
+ }
+
+ return 0;
+}