kopia lustrzana https://github.com/cariboulabs/cariboulite
rodzic
de00f43614
commit
e33f2f2cd7
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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()
|
||||
{
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Ładowanie…
Reference in New Issue