/******************************************************************************* 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 <http://www.gnu.org/licenses/>. 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 <arpa/inet.h> #include <linux/if_packet.h> #include <stdio.h> #include <string.h> #include <stdlib.h> #include <sys/ioctl.h> #include <sys/socket.h> #include <net/if.h> #include <netinet/ether.h> #include <unistd.h> #include <errno.h> #include "common_lib.h" #include "LMS_SDR.h" #include "LMS7002M.h" #include "Si5351C.h" #include "LMS_StreamBoard.h" #include "LMS7002M_RegistersMap.h" #include <cmath> ///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;i<RXDCLENGTH;i++) { calib_tx_buff[j++] = cos_fsover8[i&7]; calib_tx_buff[j++] = cos_fsover8[(i+6)&7]; // sin } calib_buffp = &calib_buff[0]; calib_tx_buffp = &calib_tx_buff[0]; lms7->BackupAllRegisters(); 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<NUMBUFF;i++) trx_lms_read(device, &ptimestamp, (void **)&calib_buffp, RXDCLENGTH, 0); for (meanIold=meanQold=i=j=0;i<RXDCLENGTH;i++) { meanIold+=calib_buff[j++]; meanQold+=calib_buff[j++]; } meanIold/=RXDCLENGTH; meanQold/=RXDCLENGTH; printf("[LMS] RX DC: (%d,%d) => (%d,%d)\n",offIold,offQold,meanIold,meanQold); offI=offQ=-64; lms7->SetRxDCOFF(offI,offQ); for (i=0;i<NUMBUFF;i++) trx_lms_read(device, &ptimestamp, (void **)&calib_buffp, RXDCLENGTH, 0); for (meanI=meanQ=i=j=0;i<RXDCLENGTH;i++) { meanI+=calib_buff[j++]; meanQ+=calib_buff[j++]; } meanI/=RXDCLENGTH; meanQ/=RXDCLENGTH; printf("[LMS] RX DC: (%d,%d) => (%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<NUMBUFF;i++) trx_lms_read(device, &ptimestamp, (void **)&calib_buffp, RXDCLENGTH, 0); for (meanI=meanQ=i=j=0;i<RXDCLENGTH;i++) { meanI+=calib_buff[j++]; meanQ+=calib_buff[j++]; } meanI/=RXDCLENGTH; meanQ/=RXDCLENGTH; printf("[LMS] RX DC: (%d,%d) => (%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<NUMBUFF;i++) { trx_lms_read(device, &ptimestamp, (void **)&calib_buffp, RXDCLENGTH, 0); trx_lms_write(device,ptimestamp+5*RXDCLENGTH, (void **)&calib_tx_buffp, RXDCLENGTH, 0, 0); } write_output("calibrx.m","rxs",calib_buffp,RXDCLENGTH,1,1); exit(-1); for (meanIold=meanQold=i=j=0;i<RXDCLENGTH;i++) { switch (i&3) { case 0: meanIold+=calib_buff[j++]; break; case 1: meanQold+=calib_buff[j++]; break; case 2: meanIold-=calib_buff[j++]; break; case 3: meanQold-=calib_buff[j++]; break; } } // meanIold/=RXDCLENGTH; // meanQold/=RXDCLENGTH; printf("[LMS] TX DC (offI): %d => (%d,%d)\n",offIold,meanIold,meanQold); offI=-128; lms7->SPI_write(0x0204,(((int16_t)offI)<<7)|offQold); for (i=0;i<NUMBUFF;i++) { trx_lms_read(device, &ptimestamp, (void **)&calib_buffp, RXDCLENGTH, 0); trx_lms_write(device,ptimestamp+5*RXDCLENGTH, (void **)&calib_tx_buffp, RXDCLENGTH, 0, 0); } for (meanI=meanQ=i=j=0;i<RXDCLENGTH;i++) { switch (i&3) { case 0: meanI+=calib_buff[j++]; break; case 1: meanQ+=calib_buff[j++]; break; case 2: meanI-=calib_buff[j++]; break; case 3: meanQ-=calib_buff[j++]; break; } } // meanI/=RXDCLENGTH; // meanQ/=RXDCLENGTH; printf("[LMS] TX DC (offI): %d => (%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<NUMBUFF;i++) { trx_lms_read(device, &ptimestamp, (void **)&calib_buffp, RXDCLENGTH, 0); trx_lms_write(device,ptimestamp+5*RXDCLENGTH, (void **)&calib_tx_buffp, RXDCLENGTH, 0, 0); } for (meanI=meanQ=i=j=0;i<RXDCLENGTH;i++) { switch (i&3) { case 0: meanI+=calib_buff[j++]; break; case 1: meanQ+=calib_buff[j++]; break; case 2: meanI-=calib_buff[j++]; break; case 3: meanQ-=calib_buff[j++]; break; } } // meanI/=RXDCLENGTH; // meanQ/=RXDCLENGTH; // printf("[LMS] TX DC (offI): %d => (%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<NUMBUFF;i++) { trx_lms_read(device, &ptimestamp, (void **)&calib_buffp, RXDCLENGTH, 0); trx_lms_write(device,ptimestamp+5*RXDCLENGTH, (void **)&calib_tx_buffp, RXDCLENGTH, 0, 0); } for (meanI=meanQ=i=j=0;i<RXDCLENGTH;i++) { switch (i&3) { case 0: meanI+=calib_buff[j++]; break; case 1: meanQ+=calib_buff[j++]; break; case 2: meanI-=calib_buff[j++]; break; case 3: meanQ-=calib_buff[j++]; break; } } // meanI/=RXDCLENGTH; // meanQ/=RXDCLENGTH; printf("[LMS] TX DC (offQ): %d => (%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<NUMBUFF;i++) { trx_lms_read(device, &ptimestamp, (void **)&calib_buffp, RXDCLENGTH, 0); trx_lms_write(device,ptimestamp+5*RXDCLENGTH, (void **)&calib_tx_buffp, RXDCLENGTH, 0, 0); } for (meanI=meanQ=i=j=0;i<RXDCLENGTH;i++) { switch (i&3) { case 0: meanI+=calib_buff[j++]; break; case 1: meanQ+=calib_buff[j++]; break; case 2: meanI-=calib_buff[j++]; break; case 3: meanQ-=calib_buff[j++]; break; } } // meanI/=RXDCLENGTH; // meanQ/=RXDCLENGTH; // printf("[LMS] TX DC (offQ): %d => (%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_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){ 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,device->openair0_cfg[0].tx_bw/1e6); if (opStatus != LIBLMS7_SUCCESS) { 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,device->openair0_cfg[0].rx_bw/1e6); if (opStatus != LIBLMS7_SUCCESS) { printf("Warning: Could not tune RX filter to %f MHz\n",device->openair0_cfg[0].rx_bw/1e6); } /* 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), 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); } trx_lms_set_gains(device, device->openair0_cfg); // 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,74.0}, // on W PAD {816000000.0,76.0}, // on W PAD {-1,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 = 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 = 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; 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; }