5#ifndef PICOSCENES_PLATFORM_SDRFRONTENDHARDWAREINFORMATION_HXX
6#define PICOSCENES_PLATFORM_SDRFRONTENDHARDWAREINFORMATION_HXX
12#include "PicoScenesCommons.hxx"
14#if defined(_WIN32) && defined(interface)
70 [](
const auto& iface) { return iface.isPrimary; });
115 std::vector<std::shared_ptr<SDRFrontEndProfile>>
frontends{};
127 PicoScenesDeviceType
deviceType{PicoScenesDeviceType::Unknown};
166 if (!interface.ipAddress.empty() && !
inverseMap.contains(interface.ipAddress)) {
194 std::vector<SDRMainBoardInfo> allBoards{
boardInfo};
213 throw std::out_of_range(
"Board index out of range");
656 std::ostringstream info;
660 size_t maxWidth = 100;
663 info <<
"\n" << std::string(maxWidth,
'*') <<
"\n";
666 for (
size_t i = 0; i < boards.size(); i++) {
667 const auto& board = boards[i];
668 info <<
"* Board " << i <<
": " << board.name
669 <<
" [Serial: " << board.serial
670 <<
", Model: " << board.model
671 <<
", FPGA: " << board.fpgaImage
672 <<
", Subtype: " << DeviceSubtype2String(board.deviceSubtype) <<
"]\n";
675 const auto& conn = board.connectionProfile;
682 for (
const auto& eth : conn.ethernetInterfaces) {
683 info <<
"* Interface: " << eth.hostInterfaceName
684 <<
"=" << eth.ipAddress <<
" Speed=" << eth.linkSpeed / 1000 <<
"GbE MTU=" << eth.MTU <<
"\n";
690 info <<
"*" << std::string(maxWidth-2,
'-') <<
"\n";
692 info <<
"* Supported Master Clock Rates: [";
693 if (!masterClockRates.empty()) {
694 auto minRate = *std::min_element(masterClockRates.begin(), masterClockRates.end()) / 1e6;
695 auto maxRate = *std::max_element(masterClockRates.begin(), masterClockRates.end()) / 1e6;
696 info << minRate <<
" MHz, " << maxRate <<
" MHz";
699 info <<
"* Available Channel #: Tx (Transmit)=";
701 if (txChannels.empty()) {
705 for (
size_t chIndex = 0; chIndex < txChannels.size(); ++chIndex) {
706 info << (chIndex == 0 ?
"" :
", ") <<
static_cast<int>(txChannels[chIndex]);
710 info <<
", and Rx (Receive)=";
712 if (rxChannels.empty()) {
716 for (
size_t chIndex = 0; chIndex < rxChannels.size(); ++chIndex) {
717 info << (chIndex == 0 ?
"" :
", ") <<
static_cast<int>(rxChannels[chIndex]);
724 info <<
"*" << std::string(maxWidth-2,
'-') <<
"\n";
727 info <<
"* <Motherboard -> Channel # (Tx/Rx) -> Tx/Rx FrontEnd -> Available Antennas> Mapping: \n";
734 auto getMboardInfo = [&](
const std::string& frontendSerial) -> std::string {
735 for (
const auto& db : daughterboards) {
736 for (
const auto& fe : db.frontends) {
737 if (fe->serialNumber == frontendSerial) {
738 return fe->motherboardSerial +
" (" +
739 DeviceSubtype2String(board.deviceSubtype) +
")";
746 for (
size_t i = 0; i < txChannels.size(); i++) {
747 uint8_t ch = txChannels[i];
753 std::string frontendSerial;
755 if (std::find(profile->txChannelNumber.begin(), profile->txChannelNumber.end(), ch) != profile->txChannelNumber.end()) {
756 frontendSerial = profile->serialNumber;
762 info << getMboardInfo(frontendSerial) <<
" -> ";
765 info << static_cast<int>(ch) <<
" (Tx) -> ";
768 bool foundFrontend =
false;
770 if (std::find(profile->txChannelNumber.begin(), profile->txChannelNumber.end(), ch) != profile->txChannelNumber.end()) {
771 info << profile->serialNumber;
772 if (!profile->frontendHardwareModel.empty()) {
773 info <<
" (" << profile->frontendHardwareModel <<
")";
775 foundFrontend =
true;
779 if (!foundFrontend) {
786 if (supportedAnts.empty()) {
789 for (
size_t j = 0; j < supportedAnts.size(); j++) {
790 if (supportedAnts[j].empty()) {
793 info << supportedAnts[j];
795 if (j < supportedAnts.size() - 1) {
804 for (
size_t i = 0; i < rxChannels.size(); i++) {
805 uint8_t ch = rxChannels[i];
811 std::string frontendSerial;
813 if (std::find(profile->rxChannelNumber.begin(), profile->rxChannelNumber.end(), ch) != profile->rxChannelNumber.end()) {
814 frontendSerial = profile->serialNumber;
820 info << getMboardInfo(frontendSerial) <<
" -> ";
823 info << static_cast<int>(ch) <<
" (Rx) -> ";
826 bool foundFrontend =
false;
828 if (std::find(profile->rxChannelNumber.begin(), profile->rxChannelNumber.end(), ch) != profile->rxChannelNumber.end()) {
829 info << profile->serialNumber;
830 if (!profile->frontendHardwareModel.empty()) {
831 info <<
" (" << profile->frontendHardwareModel <<
")";
833 foundFrontend =
true;
837 if (!foundFrontend) {
844 if (supportedAnts.empty()) {
847 for (
size_t j = 0; j < supportedAnts.size(); j++) {
848 if (supportedAnts[j].empty()) {
851 info << supportedAnts[j];
853 if (j < supportedAnts.size() - 1) {
862 info <<
"*" << std::string(maxWidth-2,
'-') <<
"\n";
865 info <<
"* Channel Capabilities:\n";
868 for (
size_t i = 0; i < txChannels.size(); i++) {
869 uint8_t ch = txChannels[i];
870 info <<
"* # " <<
static_cast<int>(ch) <<
" (Tx):\n";
873 info <<
"* Gain -> " << std::fixed << std::setprecision(1)
878 info <<
"* Carrier Frequency -> " << std::fixed << std::setprecision(1)
883 info <<
"* Sampling Rate -> " << std::fixed << std::setprecision(2)
890 for (
size_t i = 0; i < rxChannels.size(); i++) {
891 uint8_t ch = rxChannels[i];
892 info <<
"* # " <<
static_cast<int>(ch) <<
" (Rx):\n";
895 info <<
"* Gain -> " << std::fixed << std::setprecision(1)
900 info <<
"* Carrier Frequency -> " << std::fixed << std::setprecision(1)
905 info <<
"* Sampling Rate -> " << std::fixed << std::setprecision(2)
911 info <<
"* AGC -> Supported\n";
913 info <<
"* AGC -> Not Supported\n";
918 info << std::string(maxWidth,
'*') <<
"\n";
Structure containing connection profile information for SDR devices.
std::string combinationIdentifier
SDRConnectionType connectionType
std::vector< SDREthernetConnectionInterface > ethernetInterfaces
bool isDualConnection() const
Check if device has dual connection.
SDRConnectionType
Enumeration for SDR connection types.
uint8_t deviceIndexInCombination
uint8_t combinedDeviceCount
SDRDeviceCombinationType combinationType
const SDREthernetConnectionInterface * getPrimaryInterface() const
Get the primary Ethernet interface.
Structure containing daughterboard profile information.
std::vector< std::shared_ptr< SDRFrontEndProfile > > frontends
Structure containing detailed information about an Ethernet connection interface.
std::string hostInterfaceName
std::string hostPortAddress
Structure containing frontend profile information.
std::vector< uint8_t > rxChannelNumber
int getNumTx() const
Get number of Tx channels.
int getNumRx() const
Get number of Rx channels.
std::string frontendHardwareModel
std::vector< uint8_t > txChannelNumber
std::string motherboardSerial
Structure containing main board information.
std::map< std::string, std::string > inverseMap
void buildInverseMap()
Build inverse mapping of identifiers.
PicoScenesDeviceType deviceType
std::vector< SDRMainBoardInfo > otherBoards
SDRConnectionProfile connectionProfile
void merge(const SDRMainBoardInfo &other)
Merge another board's information into this one.
size_t getTotalBoardCount() const
Get total number of boards.
PicoScenesDeviceSubtype deviceSubtype