RuntimeHardwareConfig

RuntimeHardwareConfig is the singleton that records which hardware drivers are active at any given moment. It maps each "<Type>.<label>" key to a driver key (e.g., "FtmwDigitizer.default""m4i2220x8"), validates those selections against the HardwareRegistry, and exposes the configuration to the rest of Blackchirp for experiment setup.

Read access is unrestricted and available through constInstance(). Write access is restricted to HardwareManager and RuntimeHardwareConfigDialog via the friend-class pattern, enforcing that only the hardware management layer can change the active configuration.

The class provides both string-based and template-based query methods. The template variants use Qt’s staticMetaObject to derive the hardware-type key at compile time, so callers avoid raw string keys:

auto labels = RuntimeHardwareConfig::constInstance().getActiveLabels<FtmwDigitizer>();
QString impl = RuntimeHardwareConfig::constInstance()
                   .getHardwareImplementation<FtmwDigitizer>("default");

Validation

validateConfiguration() checks every active selection against the HardwareRegistry and returns a map of per-type HardwareValidationResult structs. The static overload validateHardwareConfiguration(map) validates an arbitrary hardware map without requiring the singleton, useful for preview operations in the configuration dialog. Neither method performs automatic fallbacks; callers must handle errors explicitly.

Relationship to HardwareProfileManager

RuntimeHardwareConfig is the active-selection layer on top of HardwareProfileManager, which owns profile metadata and persistence. When profiles are activated or deactivated, the runtime configuration is refreshed to match the current active profiles. The loadout system described in Hardware and Library Configuration works at the RuntimeHardwareConfig layer: switching a loadout replaces the active hardware map.

createHardwareDataContainer() packages the active configuration into a BC::Data::HardwareDataContainer for use by data-layer classes such as Experiment.

API Reference

class RuntimeHardwareConfig : public SettingsStorage

Singleton runtime hardware configuration manager.

Records which hardware implementations are active at any given moment and validates those selections against HardwareRegistry. Persistence rides on SettingsStorage. Read access is unrestricted via constInstance(); write access is restricted to HardwareManager and RuntimeHardwareConfigDialog via the friend-class pattern, so only the hardware management layer can change the active configuration. All operations are thread-safe via an internal QReadWriteLock (multiple readers, exclusive writer). Validation does not perform automatic fallbacks; callers must handle errors explicitly.

Public Functions

template<typename T>
inline QString getHardwareImplementation(const QString &label) const

Get hardware implementation for a specific label (type-safe)

Template Parameters:

T – Hardware class type (e.g., FtmwDigitizer, PulseGenerator)

Parameters:

label – Hardware label (e.g., “frontPanel”, “backup”)

Returns:

Implementation key, or empty string if not set or disabled

template<typename T>
inline QStringList getActiveLabels() const

Get all active labels for a hardware type (type-safe)

Template Parameters:

T – Hardware class type (e.g., FtmwDigitizer, PulseGenerator)

Returns:

List of labels for currently active hardware devices

template<typename T>
inline QStringList getActiveKeys() const

Get all active hardware keys for a hardware type (type-safe)

Template Parameters:

T – Hardware class type (e.g., FtmwDigitizer, PulseGenerator)

Returns:

List of full hwType.label keys for currently active hardware devices

std::map<QString, QString, std::less<>> getCurrentHardware() const

Get current hardware configuration as map.

Returns the hardware configuration for experiment validation and UI code.

Returns:

Map of hardware type key to implementation key (enabled hardware only)

BC::Data::HardwareDataContainer createHardwareDataContainer() const

Create hardware data container for experiment classes.

Creates a BC::Data::HardwareDataContainer populated with both hardware selections and type keys. This provides a clean interface between the hardware layer and data layer without creating circular dependencies.

The container includes:

  • All active hardware selections in “type.label” -> “implementation” format

  • Hardware type keys populated using template methods for type safety

  • Convenience methods for type-safe hardware access

This method is used by application layer code when creating new experiments to pass hardware information to data layer classes like Experiment.

Returns:

HardwareDataContainer with populated hardware map and type keys

QHash<QString, HardwareValidationResult> validateConfiguration() const

Validate entire hardware configuration.

Checks all configured hardware selections against available implementations. Does NOT perform automatic fallbacks - reports errors that must be handled explicitly.

Returns:

Map of hardware type to validation result

bool isConfigurationValid() const

Check if entire configuration is valid.

Returns:

True if all configured hardware is available and valid

QStringList getConfiguredHardwareTypes() const

Get all configured hardware types.

Returns:

List of hardware type keys that have selections

QStringList getMissingRequiredHardware() const

Get list of missing required hardware.

Returns:

List of required hardware types that are not configured or unavailable

QStringList getAllValidationErrors() const

Get validation errors for all hardware.

Returns:

List of all validation errors across all hardware types

QStringList getAllValidationWarnings() const

Get validation warnings for all hardware.

Returns:

List of all validation warnings across all hardware types

void activateMissingSystemProfiles()

Activate system profiles for required hardware types that have no active config.

Called at startup after ensureSystemProfiles(). For each required hardware type with no active entry, activates the “virtual” system profile.

std::optional<bool> getThreaded(const QString &hwKey) const

Get the threading override for a hardware key.

Parameters:

hwKey – Full hardware key (e.g., “FtmwDigitizer.virtual”)

Returns:

Threading override, or nullopt if none stored (use type-level default from constructor)

Public Static Functions

static const RuntimeHardwareConfig &constInstance()

Get const singleton instance for read-only access.

This method provides thread-safe read-only access to the configuration from anywhere in the program.

Returns:

Const reference to the singleton instance

template<typename T>
static inline QString hardwareTypeOf()
static QStringList validateHardwareConfiguration(const std::map<QString, QString, std::less<>> &hardwareMap)

Static method to validate any hardware configuration map.

Checks all hardware selections in the provided configuration map against available implementations. Does NOT perform automatic fallbacks - reports errors that must be handled explicitly. This method can be used to validate arbitrary configuration maps without needing the singleton state.

Parameters:

hardwareMap – Hardware configuration map (“hwType.label” -> “implementation”)

Returns:

List of validation error messages (empty list means configuration is valid)

static bool isHardwareConfigurationValid(const std::map<QString, QString, std::less<>> &hardwareMap)

Static method to check if hardware configuration is valid.

Parameters:

hardwareMap – Hardware configuration map (“hwType.label” -> “implementation”)

Returns:

True if configuration is valid (no validation errors)

static bool isHardwareRequired(const QString &hardwareType)

Check if hardware type is required.

Checks the HardwareRegistry to determine if a hardware type is marked as required for operation.

Parameters:

hardwareType – Hardware type key

Returns:

True if hardware type is required

static bool isDirectControlType(const QString &hardwareType)

Check if hardware type is a direct control type.

Returns true for hardware types that are under direct user control between experiments, and whose settings may change from experiment to experiment. Used by the quick experiment dialog to determine which types to show as optional configuration choices.

Parameters:

hardwareType – Hardware type key

Returns:

True if hardware type is a direct control type

static bool isLifHardwareType(const QString &hardwareType)

Check if hardware type is a LIF hardware type.

Returns true for hardware types associated with LIF (LifDigitizer, LifLaser). Used to filter LIF hardware from the runtime config when LIF is disabled.

Parameters:

hardwareType – Hardware type key

Returns:

True if hardware type is a LIF type

Private Functions

RuntimeHardwareConfig()

Private constructor for singleton pattern.

~RuntimeHardwareConfig() = default

Private destructor.

RuntimeHardwareConfig(const RuntimeHardwareConfig&) = delete
RuntimeHardwareConfig &operator=(const RuntimeHardwareConfig&) = delete
QString getHardwareImplementation(const QString &hardwareType, const QString &label) const

Get hardware implementation for a specific label (string-based)

Parameters:
  • hardwareType – Hardware type key (e.g., “FlowController”)

  • label – Hardware label (e.g., “frontPanel”, “backup”)

Returns:

Implementation key, or empty string if not set or disabled

QStringList getActiveLabels(const QString &hardwareType) const

Get all active labels for a hardware type (string-based)

Parameters:

hardwareType – Hardware type key

Returns:

List of labels for currently active hardware devices

QStringList getActiveKeys(const QString &hardwareType) const

Get all active hardware keys for a hardware type (string-based)

Parameters:

hardwareType – Hardware type key

Returns:

List of full hwType.label keys for currently active hardware devices

bool setHardwareSelection(const QString &hardwareType, const QString &label, const QString &implementation)

Set hardware selection for a specific label.

Parameters:
  • hardwareType – Hardware type key (e.g., “FlowController”)

  • label – Hardware label (e.g., “frontPanel”, “backup”)

  • implementation – Implementation key (e.g., “mks647c”)

Returns:

True if selection was set successfully

bool removeHardwareSelection(const QString &hardwareType, const QString &label)

Remove hardware selection for a specific label.

Parameters:
  • hardwareType – Hardware type key

  • label – Hardware label

Returns:

True if selection was removed

void clearConfiguration()

Clear all hardware selections.

bool applyConfiguration(const std::map<QString, QString, std::less<>> &config)

Apply complete hardware configuration (for dialog accept operations)

Parameters:

config – Hardware configuration map (hwType.label -> implementation)

Returns:

True if configuration was applied successfully

void setThreaded(const QString &hwKey, bool threaded)

Set threading override for a hardware key.

Parameters:
  • hwKey – Full hardware key (e.g., “FtmwDigitizer.virtual”)

  • threaded – Threading override value

HardwareValidationResult validateHardwareSelectionInternal(const QString &hardwareType, const QString &label, const HardwareSelection &selection) const

Internal validation helper that assumes caller holds lock.

Parameters:
  • hardwareType – Hardware type key

  • label – Hardware label

  • selection – Hardware selection to validate

Returns:

Validation result

QStringList getMissingRequiredHardwareInternal() const

Internal helper to get missing required hardware (assumes caller holds lock)

Returns:

List of missing required hardware types

void syncWithProfiles()

Sync with HardwareProfileManager - load active profiles.

Updates the runtime configuration to match active profiles from HardwareProfileManager. Called during initialization and when profiles are activated/deactivated.

void activateProfile(const QString &hardwareType, const QString &label)

Activate profile in HardwareProfileManager.

Parameters:
  • hardwareType – Hardware type key

  • label – Hardware label

void deactivateProfile(const QString &hardwareType, const QString &label)

Deactivate profile in HardwareProfileManager.

Parameters:
  • hardwareType – Hardware type key

  • label – Hardware label

Private Members

mutable QReadWriteLock d_configLock

Thread-safe access control

QHash<QString, HardwareSelection> d_activeHardware

“type.label” key -> selection

Private Static Functions

static RuntimeHardwareConfig &instance()

Get mutable singleton instance for write access.

This method is private and only accessible to friend classes. It provides write access to the configuration.

Returns:

Mutable reference to the singleton instance

Private Static Attributes

static RuntimeHardwareConfig *s_instance = nullptr

Singleton instance

Friends

friend class HardwareManager
friend class RuntimeHardwareConfigTest
friend class RuntimeHardwareConfigDialog
struct HardwareSelection

Hardware selection entry for a specific device.

Public Members

QString type

Hardware type (stored for easy filtering)

QString implementation

Selected implementation key

std::optional<bool> threaded

Threading override (nullopt = use type-level default)

struct HardwareValidationResult

Result of validating one hardware selection against the registry.

Returned by RuntimeHardwareConfig::validateConfiguration() for each hardware type. Contains a validity flag, the resolved implementation key, and any non-fatal warnings or fatal errors produced during validation.

Public Functions

HardwareValidationResult() = default
inline explicit HardwareValidationResult(bool valid)

Public Members

bool isValid = false

Whether configuration is valid

QString selectedImplementation

Actually selected implementation

QStringList warnings

Non-fatal configuration warnings

QStringList errors

Fatal configuration errors