added c++ native api wrapping the c api

pull/146/head
David Michaeli 2023-10-01 18:39:04 +00:00
rodzic 4228a07223
commit de00f43614
10 zmienionych plików z 1045 dodań i 41 usunięć

Wyświetl plik

@ -0,0 +1,15 @@
cmake_minimum_required(VERSION 3.2)
project(test_app)
# Find the package using pkg-config
find_package(PkgConfig REQUIRED)
pkg_check_modules(CARIBOULITE REQUIRED cariboulite)
# Add the executable
add_executable(test_app main.cpp)
# Include directories from the cariboulite package
target_include_directories(test_app PRIVATE ${CARIBOULITE_INCLUDE_DIRS})
# Link against the cariboulite library
target_link_libraries(test_app PRIVATE ${CARIBOULITE_LIBRARIES})

Wyświetl plik

@ -0,0 +1,55 @@
#include <iostream>
#include <string>
#include <CaribouLite.hpp>
#include <thread>
#include <complex>
void printInfo(CaribouLite& cl)
{
std::cout << "Initialized CaribouLite: " << cl.IsInitialized() << std::endl;
std::cout << "API Versions: " << cl.GetApiVersion() << std::endl;
std::cout << "Hardware Serial Number: " << std::hex << cl.GetHwSerialNumber() << std::endl;
std::cout << "System Type: " << cl.GetSystemVersionStr() << std::endl;
std::cout << "Hardware Unique ID: " << cl.GetHwGuid() << std::endl;
}
void detectBoard()
{
CaribouLite::SysVersion ver;
std::string name;
std::string guid;
if (CaribouLite::DetectBoard(&ver, name, guid))
{
std::cout << "Detected Version: " << CaribouLite::GetSystemVersionStr(ver) << ", Name: " << name << ", GUID: " << guid << std::endl;
}
else
{
std::cout << "Undetected CaribouLite!" << std::endl;
}
}
void receivedSamples(CaribouLiteRadio* radio, const std::complex<float>* samples, const bool* sync, size_t num_samples)
{
std::cout << "Radio: " << radio->GetRadioName() << " Received " << num_samples << " samples" << std::endl;
}
int main ()
{
detectBoard();
CaribouLite &cl = CaribouLite::GetInstance();
printInfo(cl);
CaribouLiteRadio *s1g = cl.GetRadioChannel(CaribouLiteRadio::RadioType::S1G);
CaribouLiteRadio *hif = cl.GetRadioChannel(CaribouLiteRadio::RadioType::HiF);
std::cout << "First Radio Name: " << s1g->GetRadioName() << " MtuSize: " << s1g->GetNativeMtuSample() << " Samples" << std::endl;
std::cout << "First Radio Name: " << hif->GetRadioName() << " MtuSize: " << hif->GetNativeMtuSample() << " Samples" << std::endl;
s1g->SetFrequency(900000000);
s1g->StartReceiving(receivedSamples, 20000);
getchar();
return 0;
}

Wyświetl plik

@ -12,7 +12,7 @@
########################################################################
# External dependencies
########################################################################
find_package(CaribouLite 1.0)
find_package(cariboulite)
########################################################################
# Register component

Wyświetl plik

@ -30,6 +30,8 @@ set(TARGET_LINK_LIBS datatypes
m
pthread)
set(SOURCES_CPP_LIB src/CaribouLiteCpp.cpp src/CaribouLiteRadioCpp.cpp)
# Add internal project dependencies
add_subdirectory(src/datatypes EXCLUDE_FROM_ALL)
add_subdirectory(src/caribou_programming EXCLUDE_FROM_ALL)
@ -44,14 +46,14 @@ add_subdirectory(src/zf_log EXCLUDE_FROM_ALL)
add_subdirectory(src/iir EXCLUDE_FROM_ALL)
# Create the library cariboulite
add_library(cariboulite STATIC ${SOURCES_LIB})
add_library(cariboulite STATIC ${SOURCES_LIB} ${SOURCES_CPP_LIB})
target_link_libraries(cariboulite PRIVATE ${TARGET_LINK_LIBS})
set_target_properties(cariboulite PROPERTIES PUBLIC_HEADER "src/cariboulite.h;src/cariboulite_radio.h")
set_target_properties(cariboulite PROPERTIES PUBLIC_HEADER "src/cariboulite.h;src/cariboulite_radio.h;src/CaribouLite.hpp")
set_target_properties(cariboulite PROPERTIES OUTPUT_NAME cariboulite)
add_library(cariboulite_shared SHARED ${SOURCES_LIB})
add_library(cariboulite_shared SHARED ${SOURCES_LIB} ${SOURCES_CPP_LIB})
target_link_libraries(cariboulite_shared PRIVATE ${TARGET_LINK_LIBS})
set_target_properties(cariboulite_shared PROPERTIES PUBLIC_HEADER "src/cariboulite.h;src/cariboulite_radio.h")
set_target_properties(cariboulite_shared PROPERTIES PUBLIC_HEADER "src/cariboulite.h;src/cariboulite_radio.h;src/CaribouLite.hpp")
set_property(TARGET cariboulite_shared PROPERTY POSITION_INDEPENDENT_CODE 1)
set_target_properties(cariboulite_shared PROPERTIES OUTPUT_NAME cariboulite)

Wyświetl plik

@ -0,0 +1,227 @@
/**
* @file CaribouLite.hpp
* @author David Michaeli
* @date September 2023
* @brief Main Init/Close API
*
* A high level CPP API for CaribouLite
*/
#ifndef __CARIBOULITE_HPP__
#define __CARIBOULITE_HPP__
#include <cariboulite.h>
#include <cariboulite_radio.h>
#include <vector>
#include <complex>
#include <cstddef>
#include <ostream>
#include <iostream>
#include <thread>
#include <mutex>
#include <functional>
#if __cplusplus <= 199711L
#error This file needs at least a C++11 compliant compiler, try using:
#error $ g++ -std=c++11 ..
#endif
/**
* @brief CaribouLite API Version
*/
class CaribouLiteVersion
{
public:
CaribouLiteVersion(int v, int sv, int rev) {_ver.major_version = v; _ver.minor_version = sv; _ver.revision = rev;}
virtual ~CaribouLiteVersion() {}
friend std::ostream& operator<<(std::ostream& os, const CaribouLiteVersion& c)
{
os << c._ver.major_version << '.' << c._ver.minor_version << '/' << c._ver.revision;
return os;
}
private:
cariboulite_lib_version_st _ver;
};
/**
* @brief CaribouLite Frequency Range
*/
class CaribouLiteFreqRange
{
public:
CaribouLiteFreqRange(float min_hz, float max_hz) : _fMin(min_hz), _fMax(max_hz) {}
virtual ~CaribouLiteFreqRange() {}
friend std::ostream& operator<<(std::ostream& os, const CaribouLiteFreqRange& r)
{
os << "[" << r._fMin << ',' << r._fMax << ']';
return os;
}
private:
float _fMin, _fMax;
};
/**
* @brief CaribouLite Radio Channel
*/
class CaribouLite;
class CaribouLiteRadio
{
public:
enum RadioType
{
S1G = 0,
HiF = 1,
};
enum RadioDir
{
Rx = 0,
Tx = 1,
};
public:
CaribouLiteRadio(const cariboulite_radio_state_st* radio, RadioType type, const CaribouLite* parent = NULL);
virtual ~CaribouLiteRadio();
// Gain
void SetAgc(bool agc_on);
bool GetAgc(void);
float GetRxGainMin(void);
float GetRxGainMax(void);
float GetRxGainSteps(void);
void SetRxGain(float gain);
float GetRxGain(void);
// Tx Power
float GetTxPowerMin(void);
float GetTxPowerMax(void);
float GetTxPowerStep(void);
void SetTxPower(float pwr_dBm);
float GetTxPower(void);
// Rx Bandwidth
float GetRxBandwidthMin(void);
float GetRxBandwidthMax(void);
void SetRxBandwidth(float bw_hz);
float GetRxBandwidth(void);
// Tx Bandwidth
float GetTxBandwidthMin(void);
float GetTxBandwidthMax(void);
void SetTxBandwidth(float bw_hz);
float GetTxBandwidth(void);
// Rx Sample Rate
float GetRxSampleRateMin(void);
float GetRxSampleRateMax(void);
void SetRxSampleRate(float sr_hz);
float GetRxSampleRate(void);
// Tx Sample Rate
float GetTxSampleRateMin(void);
float GetTxSampleRateMax(void);
void SetTxSampleRate(float sr_hz);
float GetTxSampleRate(void);
// RSSI and Rx Power and others
float GetRssi(void);
float GetEnergyDet(void);
unsigned char GetTrueRandVal(void);
// Frequency Control
void SetFrequency(float freq_hz);
float GetFrequency(void);
std::vector<CaribouLiteFreqRange> GetFrequencyRange(void);
float GetFrequencyResolution(void);
// Activation
void StartReceiving(std::function<void(CaribouLiteRadio*, const std::complex<float>*, const bool*, size_t)> on_data_ready, size_t samples_per_chunk);
void StopReceiving(void);
void StartTransmitting(std::function<void(CaribouLiteRadio*, std::complex<float>*, const bool*, size_t*)> on_data_request, size_t samples_per_chunk);
void StartTransmittingLo(void);
void StartTransmittingCw(void);
void StopTransmitting(void);
bool GetIsTransmittingLo(void);
bool GetIsTransmittingCw(void);
// General
size_t GetNativeMtuSample(void);
std::string GetRadioName(void);
private:
const cariboulite_radio_state_st* _radio;
const CaribouLite* _device;
const RadioType _type;
bool _rx_thread_running;
bool _rx_is_active;
std::thread *_rx_thread;
std::function<void(CaribouLiteRadio*, const std::complex<float>*, const bool*, size_t)> _on_data_ready;
size_t _rx_samples_per_chunk;
bool _tx_thread_running;
bool _tx_is_active;
std::thread *_tx_thread;
std::function<void(CaribouLiteRadio*, std::complex<float>*, const bool*, size_t*)> _on_data_request;
size_t _tx_samples_per_chunk;
private:
static void CaribouLiteRxThread(CaribouLiteRadio* radio);
static void CaribouLiteTxThread(CaribouLiteRadio* radio);
};
/**
* @brief CaribouLite Device
*/
class CaribouLite
{
public:
enum LogLevel
{
Verbose,
Info,
None,
};
enum SysVersion
{
Unknown = 0,
CaribouLiteFull = 1,
CaribouLiteISM = 2,
};
protected:
CaribouLite(bool forceFpgaProg = false, LogLevel logLvl = LogLevel::None);
CaribouLite(const CaribouLite& o) = delete;
void operator=(const CaribouLite&) = delete;
public:
~CaribouLite();
bool IsInitialized(void);
CaribouLiteVersion GetApiVersion(void);
unsigned int GetHwSerialNumber(void);
SysVersion GetSystemVersion(void);
std::string GetSystemVersionStr(void);
static std::string GetSystemVersionStr(SysVersion v);
std::string GetHwGuid(void);
CaribouLiteRadio* GetRadioChannel(CaribouLiteRadio::RadioType ch);
// Ststic detection and factory
static CaribouLite &GetInstance(bool forceFpgaProg = false, LogLevel logLvl = LogLevel::None);
static bool DetectBoard(SysVersion *sysVer, std::string& name, std::string& guid);
private:
std::vector<CaribouLiteRadio*> _channels;
SysVersion _systemVersion;
std::string _productName;
std::string _productGuid;
static std::shared_ptr<CaribouLite> _instance;
static std::mutex _instMutex;
};
#endif // __CARIBOULITE_HPP__

Wyświetl plik

@ -0,0 +1,142 @@
#include <exception>
#include "CaribouLite.hpp"
std::shared_ptr<CaribouLite> CaribouLite::_instance = nullptr;
std::mutex CaribouLite::_instMutex;
//==================================================================
bool CaribouLite::DetectBoard(SysVersion *sysVer, std::string& name, std::string& guid)
{
cariboulite_version_en hw_ver;
char hw_name[64];
char hw_guid[64];
bool detected = cariboulite_detect_connected_board(&hw_ver, hw_name, hw_guid);
if (detected)
{
name = std::string(hw_name);
guid = std::string(hw_guid);
if (sysVer) *sysVer = (SysVersion)hw_ver;
}
return detected;
}
//==================================================================
CaribouLite &CaribouLite::GetInstance(bool forceFpgaProg, LogLevel logLvl)
{
SysVersion ver;
std::string name, guid;
if (!DetectBoard(&ver, name, guid))
{
throw std::runtime_error("CaribouLite was not detected");
}
std::lock_guard<std::mutex> lock(_instMutex);
if (_instance == nullptr)
{
try
{
_instance = std::shared_ptr<CaribouLite>(new CaribouLite(forceFpgaProg, logLvl));
}
catch (std::exception& e)
{
throw e;
}
}
return *_instance;
}
//==================================================================
CaribouLite::CaribouLite(bool forceFpgaProg, LogLevel logLvl)
{
if (cariboulite_init(forceFpgaProg, (cariboulite_log_level_en)logLvl) != 0)
{
throw std::runtime_error("Driver initialization failed");
}
// get information
DetectBoard(&_systemVersion, _productName, _productGuid);
// populate the radio devices
cariboulite_radio_state_st *radio_s1g = cariboulite_get_radio(cariboulite_channel_s1g);
CaribouLiteRadio* radio_s1g_int = new CaribouLiteRadio(radio_s1g, CaribouLiteRadio::RadioType::S1G, this);
_channels.push_back(radio_s1g_int);
cariboulite_radio_state_st *radio_hif = cariboulite_get_radio(cariboulite_channel_hif);
CaribouLiteRadio* radio_hif_int = new CaribouLiteRadio(radio_hif, CaribouLiteRadio::RadioType::HiF, this);
_channels.push_back(radio_hif_int);
}
//==================================================================
CaribouLite::~CaribouLite()
{
//std::cout << "Deleting Cariboulite ~CaribouLite" << std::endl;
if (_instance != nullptr)
{
for (size_t i = 0; i < _instance->_channels.size(); i++)
{
delete _instance->_channels[i];
}
cariboulite_close();
_instance.reset();
_instance = nullptr;
}
}
//==================================================================
bool CaribouLite::IsInitialized()
{
return cariboulite_is_initialized();
}
//==================================================================
CaribouLiteVersion CaribouLite::GetApiVersion()
{
cariboulite_lib_version_st v = {0};
cariboulite_get_lib_version(&v);
return CaribouLiteVersion(v.major_version, v.minor_version, v.revision);
}
//==================================================================
unsigned int CaribouLite::GetHwSerialNumber()
{
return cariboulite_get_sn();
}
//==================================================================
CaribouLite::SysVersion CaribouLite::GetSystemVersion()
{
return (CaribouLite::SysVersion)cariboulite_get_version();
}
//==================================================================
std::string CaribouLite::GetSystemVersionStr(CaribouLite::SysVersion v)
{
switch(v)
{
case SysVersion::CaribouLiteFull: return std::string("CaribouLite6G"); break;
case SysVersion::CaribouLiteISM: return std::string("CaribouLiteISM"); break;
case SysVersion::Unknown:
default: return std::string("Unknown CaribouLite"); break;
}
return std::string(""); // unreachable.. hopefully
}
//==================================================================
std::string CaribouLite::GetSystemVersionStr(void)
{
return CaribouLite::GetSystemVersionStr(GetSystemVersion());
}
//==================================================================
std::string CaribouLite::GetHwGuid(void)
{
return _productGuid;
}
//==================================================================
CaribouLiteRadio* CaribouLite::GetRadioChannel(CaribouLiteRadio::RadioType ch)
{
return _channels[(int)ch];
}

Wyświetl plik

@ -0,0 +1,489 @@
#include "CaribouLite.hpp"
//=================================================================
void CaribouLiteRadio::CaribouLiteRxThread(CaribouLiteRadio* radio)
{
size_t mtu_size = radio->GetNativeMtuSample();
cariboulite_sample_complex_int16* rx_buffer = new cariboulite_sample_complex_int16[mtu_size];
cariboulite_sample_meta* rx_meta_buffer = new cariboulite_sample_meta[mtu_size];
std::complex<float>* rx_copmlex_data = new std::complex<float>[mtu_size];
bool* rx_meta_data = new bool[mtu_size];
while (radio->_rx_thread_running)
{
if (!radio->_rx_is_active)
{
std::this_thread::sleep_for(std::chrono::milliseconds(10));
continue;
}
int ret = cariboulite_radio_read_samples((cariboulite_radio_state_st*)radio->_radio,
rx_buffer,
rx_meta_buffer,
mtu_size);
if (ret < 0)
{
if (ret == -1)
{
printf("reader thread failed to read SMI!\n");
}
ret = 0;
continue;
}
// convert the buffer
for (int i = 0; i < ret; i ++)
{
rx_meta_data[i] = rx_meta_buffer[i].sync;
rx_copmlex_data[i].real(rx_buffer[i].i / 4096.0);
rx_copmlex_data[i].imag(rx_buffer[i].q / 4096.0);
}
// notify application
if (radio->_on_data_ready)
{
try
{
radio->_on_data_ready(radio, rx_copmlex_data, rx_meta_data, ret);
}
catch (std::exception &e)
{
std::cout << "OnDataReady Exception: " << e.what() << std::endl;
}
}
}
delete[]rx_buffer;
delete[]rx_meta_buffer;
delete[]rx_copmlex_data;
delete[]rx_meta_data;
}
//==================================================================
void CaribouLiteRadio::CaribouLiteTxThread(CaribouLiteRadio* radio)
{
while (radio->_tx_thread_running)
{
if (!radio->_tx_is_active)
{
std::this_thread::sleep_for(std::chrono::milliseconds(10));
continue;
}
// TBD
}
}
//==================================================================
CaribouLiteRadio::CaribouLiteRadio(const cariboulite_radio_state_st* radio, RadioType type, const CaribouLite* parent)
: _radio(radio), _device(parent), _type(type)
{
_rx_thread_running = true;
_rx_thread = new std::thread(CaribouLiteRadio::CaribouLiteRxThread, this);
_tx_thread_running = true;
_tx_thread = new std::thread(CaribouLiteRadio::CaribouLiteTxThread, this);
}
//==================================================================
CaribouLiteRadio::~CaribouLiteRadio()
{
//std::cout << "Destructor of Radio" << std::endl;
StopReceiving();
StopTransmitting();
_rx_thread_running = false;
_rx_thread->join();
if (_rx_thread) delete _rx_thread;
_tx_thread_running = false;
_tx_thread->join();
if (_tx_thread) delete _tx_thread;
}
// Gain
//==================================================================
void CaribouLiteRadio::SetAgc(bool agc_on)
{
int gain = 0;
bool temp = false;
cariboulite_radio_get_rx_gain_control((cariboulite_radio_state_st*)_radio, &temp, &gain);
cariboulite_radio_set_rx_gain_control((cariboulite_radio_state_st*)_radio, agc_on, gain);
}
//==================================================================
bool CaribouLiteRadio::GetAgc()
{
int gain = 0;
bool temp = false;
cariboulite_radio_get_rx_gain_control((cariboulite_radio_state_st*)_radio, &temp, &gain);
return temp;
}
//==================================================================
float CaribouLiteRadio::GetRxGainMin()
{
int rx_min_gain_value_db, rx_max_gain_value_db, rx_gain_value_resolution_db;
cariboulite_radio_get_rx_gain_limits((cariboulite_radio_state_st*)_radio,
&rx_min_gain_value_db,
&rx_max_gain_value_db,
&rx_gain_value_resolution_db);
return rx_min_gain_value_db;
}
//==================================================================
float CaribouLiteRadio::GetRxGainMax()
{
int rx_min_gain_value_db, rx_max_gain_value_db, rx_gain_value_resolution_db;
cariboulite_radio_get_rx_gain_limits((cariboulite_radio_state_st*)_radio,
&rx_min_gain_value_db,
&rx_max_gain_value_db,
&rx_gain_value_resolution_db);
return rx_max_gain_value_db;
}
//==================================================================
float CaribouLiteRadio::GetRxGainSteps()
{
int rx_min_gain_value_db, rx_max_gain_value_db, rx_gain_value_resolution_db;
cariboulite_radio_get_rx_gain_limits((cariboulite_radio_state_st*)_radio,
&rx_min_gain_value_db,
&rx_max_gain_value_db,
&rx_gain_value_resolution_db);
return rx_gain_value_resolution_db;
}
//==================================================================
void CaribouLiteRadio::SetRxGain(float gain)
{
bool temp = false;
cariboulite_radio_get_rx_gain_control((cariboulite_radio_state_st*)_radio, &temp, NULL);
cariboulite_radio_set_rx_gain_control((cariboulite_radio_state_st*)_radio, temp, (int)gain);
}
//==================================================================
float CaribouLiteRadio::GetRxGain()
{
int igain = 0;
cariboulite_radio_get_rx_gain_control((cariboulite_radio_state_st*)_radio, NULL, &igain);
return (float)igain;
}
// Tx Power
//==================================================================
float CaribouLiteRadio::GetTxPowerMin()
{
return -15.0f;
}
//==================================================================
float CaribouLiteRadio::GetTxPowerMax()
{
return 18.0f;
}
//==================================================================
float CaribouLiteRadio::GetTxPowerStep()
{
return 1.0f;
}
//==================================================================
void CaribouLiteRadio::SetTxPower(float pwr_dBm)
{
cariboulite_radio_set_tx_power((cariboulite_radio_state_st*)_radio, (int)pwr_dBm);
}
//==================================================================
float CaribouLiteRadio::GetTxPower()
{
int itx_pwr = 0;
cariboulite_radio_get_tx_power((cariboulite_radio_state_st*)_radio, &itx_pwr);
return (float)itx_pwr;
}
// Rx Bandwidth
//==================================================================
float CaribouLiteRadio::GetRxBandwidthMin()
{
return 200000.0f;
}
//==================================================================
float CaribouLiteRadio::GetRxBandwidthMax()
{
return 2500000.0f;
}
//==================================================================
void CaribouLiteRadio::SetRxBandwidth(float bw_hz)
{
cariboulite_radio_set_rx_bandwidth_flt((cariboulite_radio_state_st*)_radio, bw_hz);
}
//==================================================================
float CaribouLiteRadio::GetRxBandwidth()
{
float bw = 0;
cariboulite_radio_get_rx_bandwidth_flt((cariboulite_radio_state_st*)_radio, &bw);
return bw;
}
// Tx Bandwidth
//==================================================================
float CaribouLiteRadio::GetTxBandwidthMin()
{
return 80000.0f;
}
//==================================================================
float CaribouLiteRadio::GetTxBandwidthMax()
{
return 1000000.0f;
}
//==================================================================
void CaribouLiteRadio::SetTxBandwidth(float bw_hz)
{
cariboulite_radio_set_tx_bandwidth_flt((cariboulite_radio_state_st*)_radio, bw_hz);
}
//==================================================================
float CaribouLiteRadio::GetTxBandwidth()
{
float bw = 0;
cariboulite_radio_get_tx_bandwidth_flt((cariboulite_radio_state_st*)_radio, &bw);
return bw;
}
// Rx Sample Rate
//==================================================================
float CaribouLiteRadio::GetRxSampleRateMin()
{
return 400000.0f;
}
//==================================================================
float CaribouLiteRadio::GetRxSampleRateMax()
{
return 4000000.0f;
}
//==================================================================
void CaribouLiteRadio::SetRxSampleRate(float sr_hz)
{
cariboulite_radio_set_rx_sample_rate_flt((cariboulite_radio_state_st*)_radio, sr_hz);
}
//==================================================================
float CaribouLiteRadio::GetRxSampleRate()
{
float sr = 0.0f;
cariboulite_radio_get_rx_sample_rate_flt((cariboulite_radio_state_st*)_radio, &sr);
return sr;
}
// Tx Sample Rate
//==================================================================
float CaribouLiteRadio::GetTxSampleRateMin()
{
return 400000.0f;
}
//==================================================================
float CaribouLiteRadio::GetTxSampleRateMax()
{
return 4000000.0f;
}
//==================================================================
void CaribouLiteRadio::SetTxSampleRate(float sr_hz)
{
cariboulite_radio_set_tx_samp_cutoff_flt((cariboulite_radio_state_st*)_radio, sr_hz);
}
//==================================================================
float CaribouLiteRadio::GetTxSampleRate()
{
float sr = 0.0f;
cariboulite_radio_get_tx_samp_cutoff_flt((cariboulite_radio_state_st*)_radio, &sr);
return sr;
}
// RSSI and Rx Power and others
//==================================================================
float CaribouLiteRadio::GetRssi()
{
float rssi = 0.0f;
cariboulite_radio_get_rssi((cariboulite_radio_state_st*)_radio, &rssi);
return rssi;
}
//==================================================================
float CaribouLiteRadio::GetEnergyDet()
{
float ed = 0.0f;
cariboulite_radio_get_energy_det((cariboulite_radio_state_st*)_radio, &ed);
return ed;
}
//==================================================================
unsigned char CaribouLiteRadio::GetTrueRandVal()
{
unsigned char val = 0;
cariboulite_radio_get_rand_val((cariboulite_radio_state_st*)_radio, &val);
return val;
}
// Frequency Control
//==================================================================
void CaribouLiteRadio::SetFrequency(float freq_hz)
{
if (!cariboulite_frequency_available((cariboulite_channel_en)_type, freq_hz))
{
char msg[128] = {0};
sprintf(msg, "Frequency out or range %.2f Hz on %s", freq_hz, GetRadioName().c_str());
throw std::invalid_argument(msg);
}
double freq_dbl = freq_hz;
if (cariboulite_radio_set_frequency((cariboulite_radio_state_st*)_radio,
true,
&freq_dbl) != 0)
{
char msg[128] = {0};
sprintf(msg, "Frequency setting on %s failed", GetRadioName().c_str());
throw std::runtime_error(msg);
}
}
//==================================================================
float CaribouLiteRadio::GetFrequency()
{
double freq = 0;
cariboulite_radio_get_frequency((cariboulite_radio_state_st*)_radio,
&freq, NULL, NULL);
return freq;
}
//==================================================================
std::vector<CaribouLiteFreqRange> CaribouLiteRadio::GetFrequencyRange()
{
std::vector<CaribouLiteFreqRange> ranges;
float freq_mins[10];
float freq_maxs[10];
int num = 0;
cariboulite_get_frequency_limits((cariboulite_channel_en)_type, freq_mins, freq_maxs, &num);
for (int i = 0; i < num; i++)
{
ranges.push_back(CaribouLiteFreqRange(freq_mins[i], freq_maxs[i]));
}
return ranges;
}
//==================================================================
float CaribouLiteRadio::GetFrequencyResolution()
{
// TBD: todo calculate it according to the real hardware specs
return 1.0f;
}
// Activation
//==================================================================
void CaribouLiteRadio::StartReceiving(std::function<void(CaribouLiteRadio*, const std::complex<float>*, const bool*, size_t)> on_data_ready, size_t samples_per_chunk)
{
_on_data_ready = on_data_ready;
_rx_samples_per_chunk = samples_per_chunk;
cariboulite_radio_activate_channel((cariboulite_radio_state_st*)_radio, cariboulite_channel_dir_rx, true);
_rx_is_active = true;
}
//==================================================================
void CaribouLiteRadio::StopReceiving()
{
_rx_is_active = false;
cariboulite_radio_activate_channel((cariboulite_radio_state_st*)_radio, cariboulite_channel_dir_rx, false);
}
//==================================================================
void CaribouLiteRadio::StartTransmitting(std::function<void(CaribouLiteRadio*, std::complex<float>*, const bool*, size_t*)> on_data_request, size_t samples_per_chunk)
{
_rx_is_active = false;
_on_data_request = on_data_request;
_tx_samples_per_chunk = samples_per_chunk;
cariboulite_radio_activate_channel((cariboulite_radio_state_st*)_radio, cariboulite_channel_dir_rx, false);
cariboulite_radio_set_cw_outputs((cariboulite_radio_state_st*)_radio, false, false);
cariboulite_radio_activate_channel((cariboulite_radio_state_st*)_radio, cariboulite_channel_dir_tx, true);
_tx_is_active = true;
}
//==================================================================
void CaribouLiteRadio::StartTransmittingLo()
{
_rx_is_active = false;
_tx_is_active = false;
cariboulite_radio_activate_channel((cariboulite_radio_state_st*)_radio, cariboulite_channel_dir_tx, false);
cariboulite_radio_set_cw_outputs((cariboulite_radio_state_st*)_radio, true, false);
cariboulite_radio_activate_channel((cariboulite_radio_state_st*)_radio, cariboulite_channel_dir_tx, true);
}
//==================================================================
void CaribouLiteRadio::StartTransmittingCw()
{
_rx_is_active = false;
_tx_is_active = false;
cariboulite_radio_activate_channel((cariboulite_radio_state_st*)_radio, cariboulite_channel_dir_tx, false);
cariboulite_radio_set_cw_outputs((cariboulite_radio_state_st*)_radio, false, true);
cariboulite_radio_activate_channel((cariboulite_radio_state_st*)_radio, cariboulite_channel_dir_tx, true);
}
//==================================================================
void CaribouLiteRadio::StopTransmitting()
{
_tx_is_active = false;
cariboulite_radio_set_cw_outputs((cariboulite_radio_state_st*)_radio, false, false);
cariboulite_radio_activate_channel((cariboulite_radio_state_st*)_radio, cariboulite_channel_dir_tx, false);
}
//==================================================================
bool CaribouLiteRadio::GetIsTransmittingLo()
{
bool lo_out = false;
cariboulite_radio_get_cw_outputs((cariboulite_radio_state_st*)_radio, &lo_out, NULL);
return lo_out;
}
//==================================================================
bool CaribouLiteRadio::GetIsTransmittingCw()
{
bool cw_out = false;
cariboulite_radio_get_cw_outputs((cariboulite_radio_state_st*)_radio, NULL, &cw_out);
return cw_out;
}
// General
//==================================================================
size_t CaribouLiteRadio::GetNativeMtuSample()
{
return cariboulite_radio_get_native_mtu_size_samples((cariboulite_radio_state_st*)_radio);
}
//==================================================================
std::string CaribouLiteRadio::GetRadioName()
{
char name[64];
cariboulite_get_channel_name((cariboulite_channel_en)_type, name, sizeof(name));
return std::string(name);
}

Wyświetl plik

@ -651,7 +651,7 @@ int caribou_smi_read(caribou_smi_st* dev, caribou_smi_channel_en channel,
}
else if (ret == 0)
{
printf("caribou_smi_read -> Timeout\n");
ZF_LOGD("Reading timed-out");
break;
}
else

Wyświetl plik

@ -305,21 +305,45 @@ int cariboulite_radio_set_rx_samp_cutoff(cariboulite_radio_state_st* radio,
return 0;
}
//=========================================================================
static cariboulite_radio_sample_rate_en sample_rate_from_flt(float sample_rate_hz)
{
cariboulite_radio_sample_rate_en sample_rate = cariboulite_radio_rx_sample_rate_4000khz;
if (sample_rate_hz >= sample_rate_middles[0]) sample_rate = cariboulite_radio_rx_sample_rate_4000khz;
else if (sample_rate_hz >= sample_rate_middles[1]) sample_rate = cariboulite_radio_rx_sample_rate_2000khz;
else if (sample_rate_hz >= sample_rate_middles[2]) sample_rate = cariboulite_radio_rx_sample_rate_1333khz;
else if (sample_rate_hz >= sample_rate_middles[3]) sample_rate = cariboulite_radio_rx_sample_rate_1000khz;
else if (sample_rate_hz >= sample_rate_middles[4]) sample_rate = cariboulite_radio_rx_sample_rate_800khz;
else if (sample_rate_hz >= sample_rate_middles[5]) sample_rate = cariboulite_radio_rx_sample_rate_666khz;
else if (sample_rate_hz >= sample_rate_middles[6]) sample_rate = cariboulite_radio_rx_sample_rate_500khz;
else sample_rate = cariboulite_radio_rx_sample_rate_400khz;
return sample_rate;
}
//=========================================================================
static float sample_rate_to_flt(cariboulite_radio_sample_rate_en sample_rate)
{
float sample_rate_hz = 4000000;
switch(sample_rate)
{
case cariboulite_radio_rx_sample_rate_4000khz: sample_rate_hz = 4000000; break;
case cariboulite_radio_rx_sample_rate_2000khz: sample_rate_hz = 2000000; break;
case cariboulite_radio_rx_sample_rate_1333khz: sample_rate_hz = 1333000; break;
case cariboulite_radio_rx_sample_rate_1000khz: sample_rate_hz = 1000000; break;
case cariboulite_radio_rx_sample_rate_800khz: sample_rate_hz = 800000; break;
case cariboulite_radio_rx_sample_rate_666khz: sample_rate_hz = 666000; break;
case cariboulite_radio_rx_sample_rate_500khz: sample_rate_hz = 500000; break;
case cariboulite_radio_rx_sample_rate_400khz: sample_rate_hz = 400000; break;
default: sample_rate_hz = 4000000; break;
}
return sample_rate_hz;
}
//=========================================================================
int cariboulite_radio_set_rx_sample_rate_flt(cariboulite_radio_state_st* radio, float sample_rate_hz)
{
cariboulite_radio_sample_rate_en rx_sample_rate = cariboulite_radio_rx_sample_rate_4000khz;
cariboulite_radio_sample_rate_en rx_sample_rate = sample_rate_from_flt(sample_rate_hz);
cariboulite_radio_f_cut_en rx_cutoff = radio->rx_fcut;
if (sample_rate_hz >= sample_rate_middles[0]) rx_sample_rate = cariboulite_radio_rx_sample_rate_4000khz;
else if (sample_rate_hz >= sample_rate_middles[1]) rx_sample_rate = cariboulite_radio_rx_sample_rate_2000khz;
else if (sample_rate_hz >= sample_rate_middles[2]) rx_sample_rate = cariboulite_radio_rx_sample_rate_1333khz;
else if (sample_rate_hz >= sample_rate_middles[3]) rx_sample_rate = cariboulite_radio_rx_sample_rate_1000khz;
else if (sample_rate_hz >= sample_rate_middles[4]) rx_sample_rate = cariboulite_radio_rx_sample_rate_800khz;
else if (sample_rate_hz >= sample_rate_middles[5]) rx_sample_rate = cariboulite_radio_rx_sample_rate_666khz;
else if (sample_rate_hz >= sample_rate_middles[6]) rx_sample_rate = cariboulite_radio_rx_sample_rate_500khz;
else rx_sample_rate = cariboulite_radio_rx_sample_rate_400khz;
return cariboulite_radio_set_rx_samp_cutoff(radio, rx_sample_rate, rx_cutoff);
}
@ -342,19 +366,7 @@ int cariboulite_radio_get_rx_sample_rate_flt(cariboulite_radio_state_st* radio,
if (sample_rate_hz == NULL) return 0;
*sample_rate_hz = 4000000;
switch(rx_sample_rate)
{
case cariboulite_radio_rx_sample_rate_4000khz: *sample_rate_hz = 4000000; break;
case cariboulite_radio_rx_sample_rate_2000khz: *sample_rate_hz = 2000000; break;
case cariboulite_radio_rx_sample_rate_1333khz: *sample_rate_hz = 1333000; break;
case cariboulite_radio_rx_sample_rate_1000khz: *sample_rate_hz = 1000000; break;
case cariboulite_radio_rx_sample_rate_800khz: *sample_rate_hz = 800000; break;
case cariboulite_radio_rx_sample_rate_666khz: *sample_rate_hz = 666000; break;
case cariboulite_radio_rx_sample_rate_500khz: *sample_rate_hz = 500000; break;
case cariboulite_radio_rx_sample_rate_400khz: *sample_rate_hz = 400000; break;
default: *sample_rate_hz = 4000000; break;
}
*sample_rate_hz = sample_rate_to_flt(rx_sample_rate);
return 0;
}
@ -455,6 +467,27 @@ int cariboulite_radio_set_tx_bandwidth(cariboulite_radio_state_st* radio,
return 0;
}
//=========================================================================
int cariboulite_radio_set_tx_bandwidth_flt(cariboulite_radio_state_st* radio, float tx_bw)
{
cariboulite_radio_tx_cut_off_en bw = cariboulite_radio_tx_cut_off_80khz;
if (tx_bw <= tx_bandwidth_middles[0]) bw = cariboulite_radio_tx_cut_off_80khz;
else if (tx_bw <= tx_bandwidth_middles[1]) bw = cariboulite_radio_tx_cut_off_100khz;
else if (tx_bw <= tx_bandwidth_middles[2]) bw = cariboulite_radio_tx_cut_off_125khz;
else if (tx_bw <= tx_bandwidth_middles[3]) bw = cariboulite_radio_tx_cut_off_160khz;
else if (tx_bw <= tx_bandwidth_middles[4]) bw = cariboulite_radio_tx_cut_off_200khz;
else if (tx_bw <= tx_bandwidth_middles[5]) bw = cariboulite_radio_tx_cut_off_250khz;
else if (tx_bw <= tx_bandwidth_middles[6]) bw = cariboulite_radio_tx_cut_off_315khz;
else if (tx_bw <= tx_bandwidth_middles[7]) bw = cariboulite_radio_tx_cut_off_400khz;
else if (tx_bw <= tx_bandwidth_middles[8]) bw = cariboulite_radio_tx_cut_off_500khz;
else if (tx_bw <= tx_bandwidth_middles[9]) bw = cariboulite_radio_tx_cut_off_625khz;
else if (tx_bw <= tx_bandwidth_middles[10]) bw = cariboulite_radio_tx_cut_off_800khz;
else bw = cariboulite_radio_tx_cut_off_1000khz;
return cariboulite_radio_set_tx_bandwidth(radio, bw);
}
//=========================================================================
int cariboulite_radio_get_tx_bandwidth(cariboulite_radio_state_st* radio,
cariboulite_radio_tx_cut_off_en *tx_bw)
@ -464,6 +497,33 @@ int cariboulite_radio_get_tx_bandwidth(cariboulite_radio_state_st* radio,
return 0;
}
//=========================================================================
int cariboulite_radio_get_tx_bandwidth_flt(cariboulite_radio_state_st* radio, float *tx_bw)
{
cariboulite_radio_tx_cut_off_en bw;
cariboulite_radio_get_tx_bandwidth(radio, &bw);
if (tx_bw == NULL) return 0;
switch(bw)
{
case cariboulite_radio_tx_cut_off_80khz: *tx_bw = 80e5; break;
case cariboulite_radio_tx_cut_off_100khz: *tx_bw = 100e5; break;
case cariboulite_radio_tx_cut_off_125khz: *tx_bw = 125e5; break;
case cariboulite_radio_tx_cut_off_160khz: *tx_bw = 160e5; break;
case cariboulite_radio_tx_cut_off_200khz: *tx_bw = 200e5; break;
case cariboulite_radio_tx_cut_off_250khz: *tx_bw = 250e5; break;
case cariboulite_radio_tx_cut_off_315khz: *tx_bw = 315e5; break;
case cariboulite_radio_tx_cut_off_400khz: *tx_bw = 400e5; break;
case cariboulite_radio_tx_cut_off_500khz: *tx_bw = 500e5; break;
case cariboulite_radio_tx_cut_off_625khz: *tx_bw = 625e5; break;
case cariboulite_radio_tx_cut_off_800khz: *tx_bw = 800e5; break;
case cariboulite_radio_tx_cut_off_1000khz:
default: *tx_bw = 1000e5; break;
}
return 0;
}
//=========================================================================
int cariboulite_radio_set_tx_samp_cutoff(cariboulite_radio_state_st* radio,
cariboulite_radio_sample_rate_en tx_sample_rate,
@ -505,6 +565,14 @@ int cariboulite_radio_set_tx_samp_cutoff(cariboulite_radio_state_st* radio,
return 0;
}
//=========================================================================
int cariboulite_radio_set_tx_samp_cutoff_flt(cariboulite_radio_state_st* radio, float sample_rate_hz)
{
cariboulite_radio_sample_rate_en tx_sample_rate = sample_rate_from_flt(sample_rate_hz);
cariboulite_radio_f_cut_en tx_cutoff = radio->tx_fcut;
return cariboulite_radio_set_tx_samp_cutoff(radio, tx_sample_rate, tx_cutoff);
}
//=========================================================================
int cariboulite_radio_get_tx_samp_cutoff(cariboulite_radio_state_st* radio,
cariboulite_radio_sample_rate_en *tx_sample_rate,
@ -534,6 +602,19 @@ int cariboulite_radio_get_tx_samp_cutoff(cariboulite_radio_state_st* radio,
return 0;
}
//=========================================================================
int cariboulite_radio_get_tx_samp_cutoff_flt(cariboulite_radio_state_st* radio, float *sample_rate_hz)
{
cariboulite_radio_sample_rate_en tx_sample_rate;
cariboulite_radio_get_tx_samp_cutoff(radio, &tx_sample_rate, NULL);
if (sample_rate_hz == NULL) return 0;
*sample_rate_hz = sample_rate_to_flt(tx_sample_rate);
return 0;
}
//=========================================================================
int cariboulite_radio_get_rssi(cariboulite_radio_state_st* radio, float *rssi_dbm)
{

Wyświetl plik

@ -406,6 +406,7 @@ int cariboulite_radio_get_tx_power(cariboulite_radio_state_st* radio,
int cariboulite_radio_set_tx_bandwidth(cariboulite_radio_state_st* radio,
cariboulite_radio_tx_cut_off_en tx_bw);
int cariboulite_radio_set_tx_bandwidth_flt(cariboulite_radio_state_st* radio, float tx_bw);
/**
* @brief Modem get Tx analog Bandwidth
@ -418,6 +419,7 @@ int cariboulite_radio_set_tx_bandwidth(cariboulite_radio_state_st* radio,
*/
int cariboulite_radio_get_tx_bandwidth(cariboulite_radio_state_st* radio,
cariboulite_radio_tx_cut_off_en *tx_bw);
int cariboulite_radio_get_tx_bandwidth_flt(cariboulite_radio_state_st* radio, float *tx_bw);
/**
* @brief Modem set Tx digital bandwidth
@ -432,6 +434,7 @@ int cariboulite_radio_get_tx_bandwidth(cariboulite_radio_state_st* radio,
int cariboulite_radio_set_tx_samp_cutoff(cariboulite_radio_state_st* radio,
cariboulite_radio_sample_rate_en tx_sample_rate,
cariboulite_radio_f_cut_en tx_cutoff);
int cariboulite_radio_set_tx_samp_cutoff_flt(cariboulite_radio_state_st* radio, float sample_rate_hz);
/**
* @brief Modem get Tx digital bandwidth
@ -446,7 +449,7 @@ int cariboulite_radio_set_tx_samp_cutoff(cariboulite_radio_state_st* radio,
int cariboulite_radio_get_tx_samp_cutoff(cariboulite_radio_state_st* radio,
cariboulite_radio_sample_rate_en *tx_sample_rate,
cariboulite_radio_f_cut_en *tx_cutoff);
int cariboulite_radio_get_tx_samp_cutoff_flt(cariboulite_radio_state_st* radio, float *sample_rate_hz);
/**
* @brief Modem get current RSSI
@ -571,16 +574,6 @@ int cariboulite_radio_set_cw_outputs(cariboulite_radio_state_st* radio,
*/
int cariboulite_radio_get_cw_outputs(cariboulite_radio_state_st* radio,
bool *lo_out, bool *cw_out);
/**
* @brief Get the SMI native buffer length (samples)
*
* This function gets the internal MTU size (nominal transfer size)
* in samples.
*
* @param radio a pre-allocated radio state structure
* @return the native mtu size
*/
size_t cariboulite_radio_get_native_mtu_size_samples(cariboulite_radio_state_st* radio);
/**
* @brief Read samples