added synchronous api for reading and writing in cpp api

changed internal complexint to std::complex<short>
fixing_gr_cariboulite
David Michaeli 2024-01-29 22:08:04 +02:00
rodzic 43c505db2d
commit 8ca8b6ac9f
3 zmienionych plików z 158 dodań i 31 usunięć

Wyświetl plik

@ -105,9 +105,15 @@ public:
IntSync = 3, IntSync = 3,
Int = 4, Int = 4,
}; };
enum ApiType
{
Async = 0,
Sync = 1,
};
public: public:
CaribouLiteRadio(const cariboulite_radio_state_st* radio, RadioType type, const CaribouLite* parent = NULL); CaribouLiteRadio(const cariboulite_radio_state_st* radio, RadioType type, ApiType api_type = Async, const CaribouLite* parent = NULL);
virtual ~CaribouLiteRadio(); virtual ~CaribouLiteRadio();
// Gain // Gain
@ -164,8 +170,9 @@ public:
// Activation // Activation
void StartReceiving(std::function<void(CaribouLiteRadio*, const std::complex<float>*, CaribouLiteMeta*, size_t)> on_data_ready, size_t samples_per_chunk = 0); void StartReceiving(std::function<void(CaribouLiteRadio*, const std::complex<float>*, CaribouLiteMeta*, size_t)> on_data_ready, size_t samples_per_chunk = 0);
void StartReceiving(std::function<void(CaribouLiteRadio*, const std::complex<float>*, size_t)> on_data_ready, size_t samples_per_chunk = 0); void StartReceiving(std::function<void(CaribouLiteRadio*, const std::complex<float>*, size_t)> on_data_ready, size_t samples_per_chunk = 0);
void StartReceiving(std::function<void(CaribouLiteRadio*, const CaribouLiteComplexInt*, CaribouLiteMeta*, size_t)> on_data_ready, size_t samples_per_chunk = 0); void StartReceiving(std::function<void(CaribouLiteRadio*, const std::complex<short>*, CaribouLiteMeta*, size_t)> on_data_ready, size_t samples_per_chunk = 0);
void StartReceiving(std::function<void(CaribouLiteRadio*, const CaribouLiteComplexInt*, size_t)> on_data_ready, size_t samples_per_chunk = 0); void StartReceiving(std::function<void(CaribouLiteRadio*, const std::complex<short>*, size_t)> on_data_ready, size_t samples_per_chunk = 0);
void StartReceiving();
void StartReceivingInternal(size_t samples_per_chunk); void StartReceivingInternal(size_t samples_per_chunk);
void StopReceiving(void); 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 StartTransmitting(std::function<void(CaribouLiteRadio*, std::complex<float>*, const bool*, size_t*)> on_data_request, size_t samples_per_chunk);
@ -175,6 +182,12 @@ public:
bool GetIsTransmittingLo(void); bool GetIsTransmittingLo(void);
bool GetIsTransmittingCw(void); bool GetIsTransmittingCw(void);
// Synchronous Reading and Writing
int ReadSamples(std::complex<float>* samples, size_t num_to_read);
int ReadSamples(std::complex<short>* samples, size_t num_to_read);
int WriteSamples(std::complex<float>* samples, size_t num_to_write);
int WriteSamples(std::complex<short>* samples, size_t num_to_write);
// General // General
size_t GetNativeMtuSample(void); size_t GetNativeMtuSample(void);
std::string GetRadioName(void); std::string GetRadioName(void);
@ -190,10 +203,11 @@ private:
std::thread *_rx_thread; std::thread *_rx_thread;
std::function<void(CaribouLiteRadio*, const std::complex<float>*, CaribouLiteMeta*, size_t)> _on_data_ready_fm; std::function<void(CaribouLiteRadio*, const std::complex<float>*, CaribouLiteMeta*, size_t)> _on_data_ready_fm;
std::function<void(CaribouLiteRadio*, const std::complex<float>*, size_t)> _on_data_ready_f; std::function<void(CaribouLiteRadio*, const std::complex<float>*, size_t)> _on_data_ready_f;
std::function<void(CaribouLiteRadio*, const CaribouLiteComplexInt*, CaribouLiteMeta*, size_t)> _on_data_ready_im; std::function<void(CaribouLiteRadio*, const std::complex<short>*, CaribouLiteMeta*, size_t)> _on_data_ready_im;
std::function<void(CaribouLiteRadio*, const CaribouLiteComplexInt*, size_t)> _on_data_ready_i; std::function<void(CaribouLiteRadio*, const std::complex<short>*, size_t)> _on_data_ready_i;
size_t _rx_samples_per_chunk; size_t _rx_samples_per_chunk;
RxCbType _rxCallbackType; RxCbType _rxCallbackType;
ApiType _api_type;
bool _tx_thread_running; bool _tx_thread_running;
bool _tx_is_active; bool _tx_is_active;
@ -201,6 +215,10 @@ private:
std::function<void(CaribouLiteRadio*, std::complex<float>*, const bool*, size_t*)> _on_data_request; std::function<void(CaribouLiteRadio*, std::complex<float>*, const bool*, size_t*)> _on_data_request;
size_t _tx_samples_per_chunk; size_t _tx_samples_per_chunk;
// buffers
cariboulite_sample_complex_int16 *_read_samples;
cariboulite_sample_meta* _read_metadata;
private: private:
static void CaribouLiteRxThread(CaribouLiteRadio* radio); static void CaribouLiteRxThread(CaribouLiteRadio* radio);
static void CaribouLiteTxThread(CaribouLiteRadio* radio); static void CaribouLiteTxThread(CaribouLiteRadio* radio);
@ -227,7 +245,7 @@ public:
}; };
protected: protected:
CaribouLite(bool forceFpgaProg = false, LogLevel logLvl = LogLevel::None); CaribouLite(bool asyncApi = true, bool forceFpgaProg = false, LogLevel logLvl = LogLevel::None);
CaribouLite(const CaribouLite& o) = delete; CaribouLite(const CaribouLite& o) = delete;
void operator=(const CaribouLite&) = delete; void operator=(const CaribouLite&) = delete;
void ReleaseResources(void); void ReleaseResources(void);
@ -247,7 +265,7 @@ public:
void RegisterSignalHandler(std::function<void(int)> on_signal_caught); void RegisterSignalHandler(std::function<void(int)> on_signal_caught);
// Static detection and factory // Static detection and factory
static CaribouLite &GetInstance(bool forceFpgaProg = false, LogLevel logLvl = LogLevel::None); static CaribouLite &GetInstance(bool asyncApi = true, bool forceFpgaProg = false, LogLevel logLvl = LogLevel::None);
static bool DetectBoard(SysVersion *sysVer, std::string& name, std::string& guid); static bool DetectBoard(SysVersion *sysVer, std::string& name, std::string& guid);
static void DefaultSignalHandler(void* context, int signal_number, siginfo_t *si); static void DefaultSignalHandler(void* context, int signal_number, siginfo_t *si);

Wyświetl plik

@ -37,7 +37,7 @@ bool CaribouLite::DetectBoard(SysVersion *sysVer, std::string& name, std::string
} }
//================================================================== //==================================================================
CaribouLite &CaribouLite::GetInstance(bool forceFpgaProg, LogLevel logLvl) CaribouLite &CaribouLite::GetInstance(bool asyncApi, bool forceFpgaProg, LogLevel logLvl)
{ {
SysVersion ver; SysVersion ver;
std::string name, guid; std::string name, guid;
@ -51,7 +51,7 @@ CaribouLite &CaribouLite::GetInstance(bool forceFpgaProg, LogLevel logLvl)
{ {
try try
{ {
_instance = std::shared_ptr<CaribouLite>(new CaribouLite(forceFpgaProg, logLvl)); _instance = std::shared_ptr<CaribouLite>(new CaribouLite(forceFpgaProg, asyncApi, logLvl));
} }
catch (std::exception& e) catch (std::exception& e)
{ {
@ -62,7 +62,7 @@ CaribouLite &CaribouLite::GetInstance(bool forceFpgaProg, LogLevel logLvl)
} }
//================================================================== //==================================================================
CaribouLite::CaribouLite(bool forceFpgaProg, LogLevel logLvl) CaribouLite::CaribouLite(bool asyncApi, bool forceFpgaProg, LogLevel logLvl)
{ {
if (cariboulite_init(forceFpgaProg, (cariboulite_log_level_en)logLvl) != 0) if (cariboulite_init(forceFpgaProg, (cariboulite_log_level_en)logLvl) != 0)
{ {
@ -75,13 +75,15 @@ CaribouLite::CaribouLite(bool forceFpgaProg, LogLevel logLvl)
// get information // get information
DetectBoard(&_systemVersion, _productName, _productGuid); DetectBoard(&_systemVersion, _productName, _productGuid);
CaribouLiteRadio::ApiType api_type = asyncApi ? CaribouLiteRadio::ApiType::Async : CaribouLiteRadio::ApiType::Sync;
// populate the radio devices // populate the radio devices
cariboulite_radio_state_st *radio_s1g = cariboulite_get_radio(cariboulite_channel_s1g); cariboulite_radio_state_st *radio_s1g = cariboulite_get_radio(cariboulite_channel_s1g);
CaribouLiteRadio* radio_s1g_int = new CaribouLiteRadio(radio_s1g, CaribouLiteRadio::RadioType::S1G, this); CaribouLiteRadio* radio_s1g_int = new CaribouLiteRadio(radio_s1g, CaribouLiteRadio::RadioType::S1G, api_type, this);
_channels.push_back(radio_s1g_int); _channels.push_back(radio_s1g_int);
cariboulite_radio_state_st *radio_hif = cariboulite_get_radio(cariboulite_channel_hif); cariboulite_radio_state_st *radio_hif = cariboulite_get_radio(cariboulite_channel_hif);
CaribouLiteRadio* radio_hif_int = new CaribouLiteRadio(radio_hif, CaribouLiteRadio::RadioType::HiF, this); CaribouLiteRadio* radio_hif_int = new CaribouLiteRadio(radio_hif, CaribouLiteRadio::RadioType::HiF, api_type, this);
_channels.push_back(radio_hif_int); _channels.push_back(radio_hif_int);
} }

Wyświetl plik

@ -4,7 +4,7 @@
void CaribouLiteRadio::CaribouLiteRxThread(CaribouLiteRadio* radio) void CaribouLiteRadio::CaribouLiteRxThread(CaribouLiteRadio* radio)
{ {
size_t mtu_size = radio->GetNativeMtuSample(); size_t mtu_size = radio->GetNativeMtuSample();
CaribouLiteComplexInt* rx_buffer = new CaribouLiteComplexInt[mtu_size]; std::complex<short>* rx_buffer = new std::complex<short>[mtu_size];
CaribouLiteMeta* rx_meta_buffer = new CaribouLiteMeta[mtu_size]; CaribouLiteMeta* rx_meta_buffer = new CaribouLiteMeta[mtu_size];
std::complex<float>* rx_copmlex_data = new std::complex<float>[mtu_size]; std::complex<float>* rx_copmlex_data = new std::complex<float>[mtu_size];
@ -36,8 +36,8 @@ void CaribouLiteRadio::CaribouLiteRxThread(CaribouLiteRadio* radio)
{ {
for (int i = 0; i < ret; i ++) for (int i = 0; i < ret; i ++)
{ {
rx_copmlex_data[i].real(rx_buffer[i].i / 4096.0); rx_copmlex_data[i].real(rx_buffer[i].real() / 4096.0);
rx_copmlex_data[i].imag(rx_buffer[i].q / 4096.0); rx_copmlex_data[i].imag(rx_buffer[i].imag() / 4096.0);
} }
} }
@ -65,6 +65,62 @@ void CaribouLiteRadio::CaribouLiteRxThread(CaribouLiteRadio* radio)
delete[]rx_copmlex_data; delete[]rx_copmlex_data;
} }
//==================================================================
int CaribouLiteRadio::ReadSamples(std::complex<float>* samples, size_t num_to_read)
{
int ret = ReadSamples((std::complex<short>*)NULL, num_to_read);
if (ret <= 0)
{
return ret;
}
if (samples)
{
for (size_t i = 0; i < (size_t)ret; i++)
{
samples[i] = {((float)_read_samples[i].i) / 4096.0f, ((float)_read_samples[i].q) / 4096.0f};
}
}
return ret;
}
//==================================================================
int CaribouLiteRadio::ReadSamples(std::complex<short>* samples, size_t num_to_read)
{
int ret = cariboulite_radio_read_samples((cariboulite_radio_state_st*)_radio,
_read_samples,
_read_metadata,
num_to_read);
if (ret <= 0)
{
return ret;
}
if (samples)
{
for (size_t i = 0; i < (size_t)ret; i++)
{
samples[i] = {_read_samples[i].i, _read_samples[i].q};
}
}
return ret;
}
//==================================================================
int CaribouLiteRadio::WriteSamples(std::complex<float>* samples, size_t num_to_write)
{
return 0;
}
//==================================================================
int CaribouLiteRadio::WriteSamples(std::complex<short>* samples, size_t num_to_write)
{
return cariboulite_radio_write_samples((cariboulite_radio_state_st*)_radio,
(cariboulite_sample_complex_int16*)samples,
num_to_write);
}
//================================================================== //==================================================================
void CaribouLiteRadio::CaribouLiteTxThread(CaribouLiteRadio* radio) void CaribouLiteRadio::CaribouLiteTxThread(CaribouLiteRadio* radio)
{ {
@ -80,14 +136,29 @@ void CaribouLiteRadio::CaribouLiteTxThread(CaribouLiteRadio* radio)
} }
//================================================================== //==================================================================
CaribouLiteRadio::CaribouLiteRadio(const cariboulite_radio_state_st* radio, RadioType type, const CaribouLite* parent) CaribouLiteRadio::CaribouLiteRadio( const cariboulite_radio_state_st* radio,
: _radio(radio), _device(parent), _type(type), _rxCallbackType(RxCbType::None) RadioType type,
ApiType api_type,
const CaribouLite* parent)
: _radio(radio), _device(parent), _type(type), _rxCallbackType(RxCbType::None), _api_type(api_type)
{ {
_rx_thread_running = true; if (_api_type == Async)
_rx_thread = new std::thread(CaribouLiteRadio::CaribouLiteRxThread, this); {
_rx_thread_running = true;
_tx_thread_running = true; _rx_thread = new std::thread(CaribouLiteRadio::CaribouLiteRxThread, this);
_tx_thread = new std::thread(CaribouLiteRadio::CaribouLiteTxThread, this);
_tx_thread_running = true;
_tx_thread = new std::thread(CaribouLiteRadio::CaribouLiteTxThread, this);
}
else
{
_read_samples = NULL;
_read_metadata = NULL;
size_t mtu_size = GetNativeMtuSample();
// allocate internal buffers
_read_samples = new cariboulite_sample_complex_int16[mtu_size];
_read_metadata = new cariboulite_sample_meta[mtu_size];
}
} }
//================================================================== //==================================================================
@ -97,13 +168,21 @@ CaribouLiteRadio::~CaribouLiteRadio()
StopReceiving(); StopReceiving();
StopTransmitting(); StopTransmitting();
_rx_thread_running = false; if (_api_type == Async)
_rx_thread->join(); {
if (_rx_thread) delete _rx_thread; _rx_thread_running = false;
_rx_thread->join();
_tx_thread_running = false; if (_rx_thread) delete _rx_thread;
_tx_thread->join();
if (_tx_thread) delete _tx_thread; _tx_thread_running = false;
_tx_thread->join();
if (_tx_thread) delete _tx_thread;
}
else
{
if (_read_samples) delete [] _read_samples;
if (_read_metadata) delete [] _read_metadata;
}
} }
// Gain // Gain
@ -426,6 +505,11 @@ void CaribouLiteRadio::StartReceivingInternal(size_t samples_per_chunk)
//================================================================== //==================================================================
void CaribouLiteRadio::StartReceiving(std::function<void(CaribouLiteRadio*, const std::complex<float>*, CaribouLiteMeta*, size_t)> on_data_ready, size_t samples_per_chunk) void CaribouLiteRadio::StartReceiving(std::function<void(CaribouLiteRadio*, const std::complex<float>*, CaribouLiteMeta*, size_t)> on_data_ready, size_t samples_per_chunk)
{ {
if (_api_type == CaribouLiteRadio::ApiType::Sync)
{
StartReceiving();
return;
}
_on_data_ready_fm = on_data_ready; _on_data_ready_fm = on_data_ready;
_rxCallbackType = RxCbType::FloatSync; _rxCallbackType = RxCbType::FloatSync;
StartReceivingInternal(samples_per_chunk); StartReceivingInternal(samples_per_chunk);
@ -434,27 +518,50 @@ void CaribouLiteRadio::StartReceiving(std::function<void(CaribouLiteRadio*, cons
//================================================================== //==================================================================
void CaribouLiteRadio::StartReceiving(std::function<void(CaribouLiteRadio*, const std::complex<float>*, size_t)> on_data_ready, size_t samples_per_chunk) void CaribouLiteRadio::StartReceiving(std::function<void(CaribouLiteRadio*, const std::complex<float>*, size_t)> on_data_ready, size_t samples_per_chunk)
{ {
if (_api_type == CaribouLiteRadio::ApiType::Sync)
{
StartReceiving();
return;
}
_on_data_ready_f = on_data_ready; _on_data_ready_f = on_data_ready;
_rxCallbackType = RxCbType::Float; _rxCallbackType = RxCbType::Float;
StartReceivingInternal(samples_per_chunk); StartReceivingInternal(samples_per_chunk);
} }
//================================================================== //==================================================================
void CaribouLiteRadio::StartReceiving(std::function<void(CaribouLiteRadio*, const CaribouLiteComplexInt*, CaribouLiteMeta*, size_t)> on_data_ready, size_t samples_per_chunk) void CaribouLiteRadio::StartReceiving(std::function<void(CaribouLiteRadio*, const std::complex<short>*, CaribouLiteMeta*, size_t)> on_data_ready, size_t samples_per_chunk)
{ {
if (_api_type == CaribouLiteRadio::ApiType::Sync)
{
StartReceiving();
return;
}
_on_data_ready_im = on_data_ready; _on_data_ready_im = on_data_ready;
_rxCallbackType = RxCbType::IntSync; _rxCallbackType = RxCbType::IntSync;
StartReceivingInternal(samples_per_chunk); StartReceivingInternal(samples_per_chunk);
} }
//================================================================== //==================================================================
void CaribouLiteRadio::StartReceiving(std::function<void(CaribouLiteRadio*, const CaribouLiteComplexInt*, size_t)> on_data_ready, size_t samples_per_chunk) void CaribouLiteRadio::StartReceiving(std::function<void(CaribouLiteRadio*, const std::complex<short>*, size_t)> on_data_ready, size_t samples_per_chunk)
{ {
if (_api_type == CaribouLiteRadio::ApiType::Sync)
{
StartReceiving();
return;
}
_on_data_ready_i = on_data_ready; _on_data_ready_i = on_data_ready;
_rxCallbackType = RxCbType::Int; _rxCallbackType = RxCbType::Int;
StartReceivingInternal(samples_per_chunk); StartReceivingInternal(samples_per_chunk);
} }
//==================================================================
void CaribouLiteRadio::StartReceiving()
{
_on_data_ready_im = nullptr;
_rxCallbackType = RxCbType::None;
StartReceivingInternal(0);
}
//================================================================== //==================================================================
void CaribouLiteRadio::StopReceiving() void CaribouLiteRadio::StopReceiving()
{ {