cariboulabs-cariboulite/software/libcariboulite/src/CaribouLiteCpp.cpp

333 wiersze
12 KiB
C++

#include <exception>
#include <errno.h>
#include <string.h>
#include "CaribouLite.hpp"
std::shared_ptr<CaribouLite> CaribouLite::_instance = nullptr;
std::mutex CaribouLite::_instMutex;
//==================================================================
static const char* decode_si_code(int signo, int si_code)
{
switch (signo) {
case SIGILL:
switch (si_code) {
case ILL_ILLOPC: return "Illegal opcode";
case ILL_ILLOPN: return "Illegal operand";
case ILL_ILLADR: return "Illegal addressing mode";
case ILL_ILLTRP: return "Illegal trap";
case ILL_PRVOPC: return "Privileged opcode";
case ILL_PRVREG: return "Privileged register";
case ILL_COPROC: return "Coprocessor error";
case ILL_BADSTK: return "Internal stack error";
default: return "Unknown SIGILL code";
}
case SIGFPE:
switch (si_code) {
case FPE_INTDIV: return "Integer divide-by-zero";
case FPE_INTOVF: return "Integer overflow";
case FPE_FLTDIV: return "Floating point divide-by-zero";
case FPE_FLTOVF: return "Floating point overflow";
case FPE_FLTUND: return "Floating point underflow";
case FPE_FLTRES: return "Floating point inexact result";
case FPE_FLTINV: return "Invalid floating point operation";
case FPE_FLTSUB: return "Subscript out of range";
default: return "Unknown SIGFPE code";
}
case SIGSEGV:
switch (si_code) {
case SEGV_MAPERR: return "Address not mapped";
case SEGV_ACCERR: return "Invalid permissions";
default: return "Unknown SIGSEGV code";
}
case SIGBUS:
switch (si_code) {
case BUS_ADRALN: return "Invalid address alignment";
case BUS_ADRERR: return "Non-existent physical address";
case BUS_OBJERR: return "Object-specific hardware error";
default: return "Unknown SIGBUS code";
}
case SIGTRAP:
switch (si_code) {
case TRAP_BRKPT: return "Process breakpoint";
case TRAP_TRACE: return "Process trace trap";
default: return "Unknown SIGTRAP code";
}
case SIGCHLD:
switch (si_code) {
case CLD_EXITED: return "Child has exited";
case CLD_KILLED: return "Child has terminated abnormally and did not create a core file";
case CLD_DUMPED: return "Child has terminated abnormally and created a core file";
case CLD_TRAPPED: return "Traced child has trapped";
case CLD_STOPPED: return "Child has stopped";
case CLD_CONTINUED: return "Stopped child has continued";
default: return "Unknown SIGCHLD code";
}
case SIGPOLL:
switch (si_code) {
case POLL_IN: return "Data input available";
case POLL_OUT: return "Output buffers available";
case POLL_MSG: return "Input message available";
case POLL_ERR: return "I/O error";
case POLL_PRI: return "High priority input available";
case POLL_HUP: return "Device disconnected";
default: return "Unknown SIGPOLL/SIGIO code";
}
default:
switch(si_code)
{
case SI_USER: return "Signal sent by kill()";
case SI_QUEUE: return "Signal was sent by sigqueue()";
case SI_TIMER: return "Signal was generated by expiration of a timer set by timer_settimer()";
case SI_ASYNCIO: return "Signal was generated by completion of an asynchronous I/O request";
case SI_MESGQ: return "Signal was generated by arrival of a message on an empty message queue.";
default: return "Unknown General code";
}
}
}
//==================================================================
static void print_siginfo(const siginfo_t *si)
{
printf(" Signal Number: %d\n", si->si_signo);
printf(" Signal Code: %d (%s)\n", si->si_code, decode_si_code(si->si_signo, si->si_code));
printf(" Signal Value (int): %d\n", si->si_value.sival_int);
printf(" Signal Value (ptr): %p\n", si->si_value.sival_ptr);
printf(" Error Number: %d => '%s'\n", si->si_errno, strerror(errno));
printf(" Sending Process ID: %d\n", si->si_pid);
printf(" User ID: %d\n", si->si_uid);
printf(" Faulting Instruction Address: %p\n", si->si_addr);
printf(" Exit Value or Signal: %d\n", si->si_status);
printf(" Band Event for SIGPOLL: %ld\n", si->si_band);
}
//==================================================================
void CaribouLite::DefaultSignalHandler(void* context, int signal_number, siginfo_t *si)
{
CaribouLite* cl = (CaribouLite*)context;
printf(">> DefaultSignalHandler: Signal caught (sig %d), additional information: \n", signal_number);
print_siginfo(si);
fflush(stdout);
if (cl->_on_signal_caught) cl->_on_signal_caught(signal_number);
exit(-1);
//cl->ReleaseResources();
}
//==================================================================
void CaribouLite::RegisterSignalHandler(std::function<void(int)> on_signal_caught)
{
_on_signal_caught = on_signal_caught;
}
//==================================================================
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 asyncApi, 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(asyncApi, forceFpgaProg, logLvl));
}
catch (std::exception& e)
{
throw e;
}
}
return *_instance;
}
//==================================================================
CaribouLite::CaribouLite(bool asyncApi, bool forceFpgaProg, LogLevel logLvl)
{
if (cariboulite_init(forceFpgaProg, (cariboulite_log_level_en)logLvl) != 0)
{
throw std::runtime_error("Driver initialization failed");
}
// register signal handler
cariboulite_register_signal_handler (CaribouLite::DefaultSignalHandler, this);
// get information
DetectBoard(&_systemVersion, _productName, _productGuid);
//printf("API TYPE: %d\n", asyncApi);
CaribouLiteRadio::ApiType api_type = (asyncApi) ? CaribouLiteRadio::ApiType::Async : CaribouLiteRadio::ApiType::Sync;
// 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, api_type, 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, api_type, this);
_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];
}
}
if (cariboulite_is_initialized())
{
cariboulite_close();
}
}
//==================================================================
CaribouLite::~CaribouLite()
{
if (_instance != nullptr)
{
ReleaseResources();
_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];
}
//==================================================================
void CaribouLite::SetLed0States (bool state)
{
int led1 = 0;
cariboulite_get_leds_state (NULL, &led1);
cariboulite_set_leds_state (state, led1);
}
//==================================================================
bool CaribouLite::GetLed0States ()
{
int led0 = 0;
cariboulite_get_leds_state (&led0, NULL);
return led0 != 0;
}
//==================================================================
void CaribouLite::SetLed1States (bool state)
{
int led0 = 0;
cariboulite_get_leds_state (&led0, NULL);
cariboulite_set_leds_state (led0, state);
}
//==================================================================
bool CaribouLite::GetLed1States ()
{
int led1 = 0;
cariboulite_get_leds_state (NULL, &led1);
return led1 != 0;
}
//==================================================================
bool CaribouLite::GetButtonState ()
{
int btn = 0;
cariboulite_get_button_state (&btn);
return btn != 0;
}
//==================================================================
void CaribouLite::SetPmodState (uint8_t val)
{
cariboulite_set_pmod_val (val);
}
//==================================================================
uint8_t CaribouLite::GetPmodState ()
{
uint8_t val = 0;
cariboulite_get_pmod_val (&val);
return val;
}