Commit d19b10ae authored by ignasj's avatar ignasj

LimeSDR

parent e1cdc46c
......@@ -42,10 +42,6 @@ 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
################################################
......@@ -523,7 +519,7 @@ set(HWLIB_BLADERF_SOURCE
add_library(oai_bladerfdevif MODULE ${HWLIB_BLADERF_SOURCE} )
include_directories("${OPENAIR_TARGETS}/ARCH/LMSSDR/USERSPACE/LIB/")
set (option_HWLMSSDRLIB_lib "-l LMS_SDR -l LMS7002M -l Si5351C")
set(HWLIB_LMSSDR_SOURCE
${OPENAIR_TARGETS}/ARCH/LMSSDR/USERSPACE/LIB/lms_lib.cpp
)
......@@ -570,16 +566,12 @@ elseif (${RF_BOARD} STREQUAL "OAI_BLADERF")
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/lmsSDR/LMS_StreamBoard")
LINK_DIRECTORIES("/usr/lib/x86_64-linux-gnu")
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(option_HW_lib "-lLMS_SDR -lLMS7002M -lSi5351C -rdynamic -ldl")
set(option_HW_lib "-lLimeSuite -rdynamic -ldl")
elseif (${RF_BOARD} STREQUAL "CPRIGW")
set(HW_SOURCE ${HW_SOURCE}
......@@ -1701,14 +1693,6 @@ 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
......
../common/utils/itti
\ No newline at end of file
set(si5351_src_files
Si5351C.cpp
)
set(CMAKE_CXX_FLAGS
"${CMAKE_CXX_FLAGS} ${C_FLAGS_PROCESSOR} -std=c++11 -fPIC"
)
add_library(Si5351C STATIC ${si5351_src_files})
target_include_directories(Si5351C PUBLIC ../lms7002m ${CMAKE_CURRENT_SOURCE_DIR})
target_link_libraries(Si5351C LMS7002M)
This diff is collapsed.
/**
@file Si5351C.h
@brief Header for Si5351C.cpp
@author Lime Microsystems
*/
#ifndef SI5351C_MODULE
#define SI5351C_MODULE
#include <stdio.h>
#include <string>
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
cmake_minimum_required(VERSION 2.8)
set(CMAKE_CONFIGURATION_TYPES "Debug;Release" CACHE TYPE INTERNAL FORCE)
project("lms7api")
#include modules for finding FFTW and 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()
# set up include-directories
include_directories(
"${PROJECT_SOURCE_DIR}"
"${PROJECT_BINARY_DIR}"
cpp-feather-ini-parser
)
set(LMS7002M_src_files
LMS7002M.cpp
LMS7002M_parameters.cpp
LMS7002M_statuses.cpp
LMS7002M_filtersCalibration.cpp
lmsComms.cpp
LMS7002M_RegistersMap.cpp
)
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
${CONNECTION_MANAGER_DIR}/ConnectionManager.cpp
${CONNECTION_MANAGER_DIR}/ConnectionCOM.cpp
${CONNECTION_MANAGER_DIR}/ConnectionManager.h
${CONNECTION_MANAGER_DIR}/ConnectionCOM.h
)
if(ENABLE_USB_CONNECTION)
list(APPEND connectionManager_src_files ${CONNECTION_MANAGER_DIR}/ConnectionUSB.cpp ${CONNECTION_MANAGER_DIR}/ConnectionUSB.h)
add_definitions(-DENABLE_USB_CONNECTION)
endif()
if(ENABLE_SPI_CONNECTION)
list(APPEND connectionManager_src_files ${CONNECTION_MANAGER_DIR}/ConnectionSPI.cpp ${CONNECTION_MANAGER_DIR}/ConnectionSPI.h)
add_definitions(-DENABLE_SPI_CONNECTION)
endif()
add_library(LMS7002M STATIC ${LMS7002M_src_files} ${connectionManager_src_files})
target_include_directories(LMS7002M 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(LMS7002M ${CONNECTION_MANAGER_LIBS})
endif()
if(UNIX AND ENABLE_USB_CONNECTION)
set(CONNECTION_MANAGER_LIBS usb-1.0 -lpthread)
target_link_libraries(LMS7002M ${CONNECTION_MANAGER_LIBS})
endif()
/**
@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 <sstream>
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 &param, 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 &param, 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 &param, uint16_t *foundValue);
uint32_t FindMinRSSI(const LMS7Parameter &param, 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
#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<uint16_t, Register>::const_iterator iter = mChannelA.find(address);
if( iter != mChannelA.end())
return iter->second.defaultValue;
else
return 0;
}
void LMS7002M_RegistersMap::InitializeDefaultValues(const std::vector<const LMS7Parameter*> 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<const uint16_t, Register> *regMap;
if(channel == 0)
regMap = &mChannelA;
else if(channel == 1)
regMap = &mChannelB;
std::map<const uint16_t, Register>::const_iterator iter;
iter = regMap->find(address);
if (iter != regMap->end())
return iter->second.value;
else
return 0;
}
std::vector<uint16_t> LMS7002M_RegistersMap::GetUsedAddresses(const uint8_t channel) const
{
std::vector<uint16_t> 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;
}
#ifndef LMS7002M_REGISTERS_MAP_H
#define LMS7002M_REGISTERS_MAP_H
#include <vector>
#include <map>
#include <typedefs.h>
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<const LMS7Parameter*> parameterList);
uint16_t GetDefaultValue(uint16_t address) const;
std::vector<uint16_t> GetUsedAddresses(const uint8_t channel) const;
protected:
std::map<const uint16_t, Register> mChannelA;
std::map<const uint16_t, Register> mChannelB;
};
#endif
/**
@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;
}
/**
@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
/**
@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<std::string> 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<std::string> comPortList;
std::vector<std::string> 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
The MIT License (MIT)
Copyright (c) 2014 Turbine1991
Permission is hereby granted, free of charge, to any person obtaining a copy