kopia lustrzana https://github.com/cariboulabs/cariboulite
333 wiersze
12 KiB
C++
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;
|
|
}
|