added rx handlers to cpp api

cpp_api example
pull/146/head
David Michaeli 2023-10-01 22:55:52 +00:00
rodzic de00f43614
commit e33f2f2cd7
8 zmienionych plików z 161 dodań i 38 usunięć

Wyświetl plik

@ -4,6 +4,7 @@
#include <thread>
#include <complex>
// Print Board Information
void printInfo(CaribouLite& cl)
{
std::cout << "Initialized CaribouLite: " << cl.IsInitialized() << std::endl;
@ -13,6 +14,7 @@ void printInfo(CaribouLite& cl)
std::cout << "Hardware Unique ID: " << cl.GetHwGuid() << std::endl;
}
// Detect the board before instantiating it
void detectBoard()
{
CaribouLite::SysVersion ver;
@ -29,27 +31,44 @@ void detectBoard()
}
}
void receivedSamples(CaribouLiteRadio* radio, const std::complex<float>* samples, const bool* sync, size_t num_samples)
// Rx Callback (async)
void receivedSamples(CaribouLiteRadio* radio, const std::complex<float>* samples, CaribouLiteMeta* sync, size_t num_samples)
{
std::cout << "Radio: " << radio->GetRadioName() << " Received " << num_samples << " samples" << std::endl;
std::cout << "Radio: " << radio->GetRadioName() << " Received " << std::dec << num_samples << " samples" << std::endl;
}
// Main entry
int main ()
{
// try detecting the board before getting the instance
detectBoard();
// get driver instance - use "CaribouLite&" rather than "CaribouLite" (ref)
CaribouLite &cl = CaribouLite::GetInstance();
// print the info after connecting
printInfo(cl);
// get the radios
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;
// write radio information
std::cout << "First Radio Name: " << s1g->GetRadioName() << " MtuSize: " << std::dec << s1g->GetNativeMtuSample() << " Samples" << std::endl;
std::cout << "First Radio Name: " << hif->GetRadioName() << " MtuSize: " << std::dec << hif->GetNativeMtuSample() << " Samples" << std::endl;
// start receiving until enter pressed on 900MHz
s1g->SetFrequency(900000000);
s1g->StartReceiving(receivedSamples, 20000);
getchar();
hif->SetFrequency(900000000);
hif->StartReceiving(receivedSamples, 20000);
getchar();
return 0;
}

Wyświetl plik

@ -67,6 +67,19 @@ private:
/**
* @brief CaribouLite Radio Channel
*/
#pragma pack(1)
struct CaribouLiteComplexInt
{
int16_t i;
int16_t q;
};
struct CaribouLiteMeta
{
uint8_t sync;
};
#pragma pack()
class CaribouLite;
class CaribouLiteRadio
{
@ -83,6 +96,15 @@ public:
Tx = 1,
};
enum RxCbType
{
None = 0,
FloatSync = 1,
Float = 2,
IntSync = 3,
Int = 4,
};
public:
CaribouLiteRadio(const cariboulite_radio_state_st* radio, RadioType type, const CaribouLite* parent = NULL);
virtual ~CaribouLiteRadio();
@ -139,7 +161,11 @@ public:
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 StartReceiving(std::function<void(CaribouLiteRadio*, const std::complex<float>*, CaribouLiteMeta*, size_t)> on_data_ready, size_t samples_per_chunk);
void StartReceiving(std::function<void(CaribouLiteRadio*, const std::complex<float>*, size_t)> on_data_ready, size_t samples_per_chunk);
void StartReceiving(std::function<void(CaribouLiteRadio*, const CaribouLiteComplexInt*, CaribouLiteMeta*, size_t)> on_data_ready, size_t samples_per_chunk);
void StartReceiving(std::function<void(CaribouLiteRadio*, const CaribouLiteComplexInt*, size_t)> on_data_ready, size_t samples_per_chunk);
void StartReceivingInternal(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);
@ -160,8 +186,12 @@ private:
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;
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 CaribouLiteComplexInt*, CaribouLiteMeta*, size_t)> _on_data_ready_im;
std::function<void(CaribouLiteRadio*, const CaribouLiteComplexInt*, size_t)> _on_data_ready_i;
size_t _rx_samples_per_chunk;
RxCbType _rxCallbackType;
bool _tx_thread_running;
bool _tx_is_active;
@ -198,6 +228,7 @@ protected:
CaribouLite(bool forceFpgaProg = false, LogLevel logLvl = LogLevel::None);
CaribouLite(const CaribouLite& o) = delete;
void operator=(const CaribouLite&) = delete;
void ReleaseResources(void);
public:
~CaribouLite();
@ -213,6 +244,7 @@ public:
// 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);
static void DefaultSignalHandler(void* context, int signal_number, siginfo_t *si);
private:
std::vector<CaribouLiteRadio*> _channels;

Wyświetl plik

@ -4,6 +4,14 @@
std::shared_ptr<CaribouLite> CaribouLite::_instance = nullptr;
std::mutex CaribouLite::_instMutex;
//==================================================================
void CaribouLite::DefaultSignalHandler(void* context, int signal_number, siginfo_t *si)
{
CaribouLite* cl = (CaribouLite*)context;
std::cout << " >> Signal caught: " << signal_number << std::endl << std::flush;
cl->ReleaseResources();
}
//==================================================================
bool CaribouLite::DetectBoard(SysVersion *sysVer, std::string& name, std::string& guid)
{
@ -53,6 +61,9 @@ CaribouLite::CaribouLite(bool forceFpgaProg, LogLevel logLvl)
throw std::runtime_error("Driver initialization failed");
}
// register signal handler
cariboulite_register_signal_handler (CaribouLite::DefaultSignalHandler, this);
// get information
DetectBoard(&_systemVersion, _productName, _productGuid);
@ -66,17 +77,24 @@ CaribouLite::CaribouLite(bool forceFpgaProg, LogLevel logLvl)
_channels.push_back(radio_hif_int);
}
//==================================================================
void CaribouLite::ReleaseResources(void)
{
if (!_instance) return;
for (size_t i = 0; i < _instance->_channels.size(); i++)
{
if (_instance->_channels[i]) delete _instance->_channels[i];
_instance->_channels[i] = NULL;
}
if (cariboulite_is_initialized()) cariboulite_close();
}
//==================================================================
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();
ReleaseResources();
_instance.reset();
_instance = nullptr;

Wyświetl plik

@ -4,23 +4,22 @@
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];
CaribouLiteComplexInt* rx_buffer = new CaribouLiteComplexInt[mtu_size];
CaribouLiteMeta* rx_meta_buffer = new CaribouLiteMeta[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));
std::this_thread::sleep_for(std::chrono::milliseconds(2));
continue;
}
int ret = cariboulite_radio_read_samples((cariboulite_radio_state_st*)radio->_radio,
rx_buffer,
rx_meta_buffer,
mtu_size);
(cariboulite_sample_complex_int16*)rx_buffer,
(cariboulite_sample_meta*)rx_meta_buffer,
radio->_rx_samples_per_chunk);
if (ret < 0)
{
if (ret == -1)
@ -32,31 +31,37 @@ void CaribouLiteRadio::CaribouLiteRxThread(CaribouLiteRadio* radio)
}
// convert the buffer
for (int i = 0; i < ret; i ++)
if (radio->_rxCallbackType == CaribouLiteRadio::RxCbType::FloatSync || radio->_rxCallbackType == CaribouLiteRadio::RxCbType::Float)
{
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);
for (int i = 0; i < ret; i ++)
{
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
{
try
switch(radio->_rxCallbackType)
{
radio->_on_data_ready(radio, rx_copmlex_data, rx_meta_data, ret);
}
catch (std::exception &e)
{
std::cout << "OnDataReady Exception: " << e.what() << std::endl;
case (CaribouLiteRadio::RxCbType::FloatSync): if (radio->_on_data_ready_fm) radio->_on_data_ready_fm(radio, rx_copmlex_data, rx_meta_buffer, ret); break;
case (CaribouLiteRadio::RxCbType::Float): if (radio->_on_data_ready_f) radio->_on_data_ready_f(radio, rx_copmlex_data, ret); break;
case (CaribouLiteRadio::RxCbType::IntSync): if (radio->_on_data_ready_im) radio->_on_data_ready_im(radio, rx_buffer, rx_meta_buffer, ret); break;
case (CaribouLiteRadio::RxCbType::Int): if (radio->_on_data_ready_i) radio->_on_data_ready_i(radio, rx_buffer, ret); break;
case (CaribouLiteRadio::RxCbType::None):
default: break;
}
}
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;
}
//==================================================================
@ -66,7 +71,7 @@ void CaribouLiteRadio::CaribouLiteTxThread(CaribouLiteRadio* radio)
{
if (!radio->_tx_is_active)
{
std::this_thread::sleep_for(std::chrono::milliseconds(10));
std::this_thread::sleep_for(std::chrono::milliseconds(4));
continue;
}
// TBD
@ -75,7 +80,7 @@ void CaribouLiteRadio::CaribouLiteTxThread(CaribouLiteRadio* radio)
//==================================================================
CaribouLiteRadio::CaribouLiteRadio(const cariboulite_radio_state_st* radio, RadioType type, const CaribouLite* parent)
: _radio(radio), _device(parent), _type(type)
: _radio(radio), _device(parent), _type(type), _rxCallbackType(RxCbType::None)
{
_rx_thread_running = true;
_rx_thread = new std::thread(CaribouLiteRadio::CaribouLiteRxThread, this);
@ -400,14 +405,55 @@ float CaribouLiteRadio::GetFrequencyResolution()
// Activation
//==================================================================
void CaribouLiteRadio::StartReceiving(std::function<void(CaribouLiteRadio*, const std::complex<float>*, const bool*, size_t)> on_data_ready, size_t samples_per_chunk)
void CaribouLiteRadio::StartReceivingInternal(size_t samples_per_chunk)
{
_on_data_ready = on_data_ready;
_rx_samples_per_chunk = samples_per_chunk;
if (_rx_samples_per_chunk > GetNativeMtuSample())
{
_rx_samples_per_chunk = GetNativeMtuSample();
}
// make sure only one radio is receiving at once
CaribouLiteRadio* otherRadio = ((CaribouLite*)_device)->GetRadioChannel((_type==RadioType::S1G)?(RadioType::HiF):(RadioType::S1G));
otherRadio->StopReceiving();
cariboulite_radio_activate_channel((cariboulite_radio_state_st*)_radio, cariboulite_channel_dir_rx, true);
_rx_is_active = true;
}
//==================================================================
void CaribouLiteRadio::StartReceiving(std::function<void(CaribouLiteRadio*, const std::complex<float>*, CaribouLiteMeta*, size_t)> on_data_ready, size_t samples_per_chunk)
{
_on_data_ready_fm = on_data_ready;
_rxCallbackType = RxCbType::FloatSync;
StartReceivingInternal(samples_per_chunk);
}
//==================================================================
void CaribouLiteRadio::StartReceiving(std::function<void(CaribouLiteRadio*, const std::complex<float>*, size_t)> on_data_ready, size_t samples_per_chunk)
{
_on_data_ready_f = on_data_ready;
_rxCallbackType = RxCbType::Float;
StartReceivingInternal(samples_per_chunk);
}
//==================================================================
void CaribouLiteRadio::StartReceiving(std::function<void(CaribouLiteRadio*, const CaribouLiteComplexInt*, CaribouLiteMeta*, size_t)> on_data_ready, size_t samples_per_chunk)
{
_on_data_ready_im = on_data_ready;
_rxCallbackType = RxCbType::IntSync;
StartReceivingInternal(samples_per_chunk);
}
//==================================================================
void CaribouLiteRadio::StartReceiving(std::function<void(CaribouLiteRadio*, const CaribouLiteComplexInt*, size_t)> on_data_ready, size_t samples_per_chunk)
{
_on_data_ready_i = on_data_ready;
_rxCallbackType = RxCbType::Int;
StartReceivingInternal(samples_per_chunk);
}
//==================================================================
void CaribouLiteRadio::StopReceiving()
{

Wyświetl plik

@ -430,6 +430,8 @@ static void print_iq(char* prefix, cariboulite_sample_complex_int16* buffer, siz
if (num_samples == 0) return;
printf("NS: %lu > ", num_samples);
for (i = 0; i < num_head_tail; i++)
{
printf("[%d, %d] ", buffer[i].i, buffer[i].q);

Wyświetl plik

@ -77,6 +77,8 @@ static int caribou_smi_get_smi_settings(caribou_smi_st *dev, struct smi_settings
ZF_LOGE("failed reading native batch length, setting the default - this error is not fatal but we have wrong kernel drivers");
dev->native_batch_len = (1024)*(1024)/2;
}
//printf("DEBUG: native batch len: %lu\n", dev->native_batch_len);
if (print)
{
@ -751,5 +753,6 @@ int caribou_smi_write(caribou_smi_st* dev, caribou_smi_channel_en channel,
//=========================================================================
size_t caribou_smi_get_native_batch_samples(caribou_smi_st* dev)
{
return dev->native_batch_len / CARIBOU_SMI_BYTES_PER_SAMPLE;
//printf("DEBUG: native batch len: %lu\n", dev->native_batch_len / CARIBOU_SMI_BYTES_PER_SAMPLE);
return (dev->native_batch_len / CARIBOU_SMI_BYTES_PER_SAMPLE);
}

Wyświetl plik

@ -87,7 +87,7 @@ int cariboulite_init(bool force_fpga_prog, cariboulite_log_level_en log_lvl)
fprintf(stderr, "CaribouLite driver init failed, terminating...");
return -1;
}
cariboulite_setup_signal_handler (&sys, internal_sighandler, signal_handler_op_last, &sys);
cariboulite_setup_signal_handler (&sys, internal_sighandler, signal_handler_op_override, &sys);
ctx.initialized = true;
return 0;
}
@ -96,6 +96,7 @@ int cariboulite_init(bool force_fpga_prog, cariboulite_log_level_en log_lvl)
void cariboulite_close(void)
{
if (!ctx.initialized) return;
ctx.initialized = false;
cariboulite_release_driver(&sys);
}

Wyświetl plik

@ -1264,5 +1264,7 @@ int cariboulite_radio_write_samples(cariboulite_radio_state_st* radio,
//=========================================================================
size_t cariboulite_radio_get_native_mtu_size_samples(cariboulite_radio_state_st* radio)
{
return caribou_smi_get_native_batch_samples(&radio->sys->smi);
size_t num_samples = caribou_smi_get_native_batch_samples(&radio->sys->smi);
//printf("DEBUG: native num samples: %lu\n", num_samples);
return num_samples;
}