#include #include #include #include "CaribouLite.hpp" std::shared_ptr 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 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 lock(_instMutex); if (_instance == nullptr) { try { _instance = std::shared_ptr(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; }