Device: RAD-Galaxy: Add support for Analog Output

This commit is contained in:
Thomas Stoddard
2026-02-11 18:43:30 -05:00
committed by Kyle Schwarz
parent 6cda765fe0
commit d18ca9e6eb
9 changed files with 403 additions and 0 deletions
+13
View File
@@ -747,6 +747,16 @@ typedef struct
namespace icsneo {
enum class MiscIOAnalogVoltage : uint8_t
{
V0 = 0,
V1 = 1,
V2 = 2,
V3 = 3,
V4 = 4,
V5 = 5
};
class IDeviceSettings {
public:
using TerminationGroup = std::vector<Network>;
@@ -1180,6 +1190,9 @@ public:
return false;
}
virtual bool setMiscIOAnalogOutputEnabled(uint8_t pin, bool enabled);
virtual bool setMiscIOAnalogOutput(uint8_t pin, MiscIOAnalogVoltage voltage);
const void* getRawStructurePointer() const { return settingsInDeviceRAM.data(); }
void* getMutableRawStructurePointer() { return settings.data(); }
template<typename T> const T* getStructurePointer() const { return reinterpret_cast<const T*>(getRawStructurePointer()); }
@@ -185,6 +185,92 @@ public:
return nullptr;
}
}
bool setMiscIOAnalogOutputEnabled(uint8_t pin, bool enabled) override {
if(!settingsLoaded) {
report(APIEvent::Type::SettingsReadError, APIEvent::Severity::Error);
return false;
}
if(disabled) {
report(APIEvent::Type::SettingsNotAvailable, APIEvent::Severity::Error);
return false;
}
if(readonly) {
report(APIEvent::Type::SettingsReadOnly, APIEvent::Severity::Error);
return false;
}
if(pin < 1 || pin > 2) {
report(APIEvent::Type::ParameterOutOfRange, APIEvent::Severity::Error);
return false;
}
auto cfg = getMutableStructurePointer<radgalaxy_settings_t>();
if(cfg == nullptr) {
report(APIEvent::Type::SettingNotAvaiableDevice, APIEvent::Severity::Error);
return false;
}
const uint16_t bitMask = 1 << (pin - 1);
if(enabled) {
// Set pin as output and enable analog mode
cfg->misc_io_initial_ddr |= bitMask;
cfg->misc_io_analog_enable |= bitMask;
} else {
// Disable analog mode (leave DDR as-is)
cfg->misc_io_analog_enable &= ~bitMask;
}
return true;
}
bool setMiscIOAnalogOutput(uint8_t pin, MiscIOAnalogVoltage voltage) override {
if(!settingsLoaded) {
report(APIEvent::Type::SettingsReadError, APIEvent::Severity::Error);
return false;
}
if(disabled) {
report(APIEvent::Type::SettingsNotAvailable, APIEvent::Severity::Error);
return false;
}
if(readonly) {
report(APIEvent::Type::SettingsReadOnly, APIEvent::Severity::Error);
return false;
}
if(pin < 1 || pin > 2) {
report(APIEvent::Type::ParameterOutOfRange, APIEvent::Severity::Error);
return false;
}
auto cfg = getMutableStructurePointer<radgalaxy_settings_t>();
if(cfg == nullptr) {
report(APIEvent::Type::SettingNotAvaiableDevice, APIEvent::Severity::Error);
return false;
}
const uint8_t dacValue = static_cast<uint8_t>(voltage);
if(dacValue > 5) {
report(APIEvent::Type::ParameterOutOfRange, APIEvent::Severity::Error);
return false;
}
if(pin == 1) {
// Update low nibble of high byte (bits 8-11), preserve pin 2 value
cfg->misc_io_initial_latch = (cfg->misc_io_initial_latch & 0xF0FF) | (static_cast<uint16_t>(dacValue) << 8);
} else { // pin == 2
// Update high nibble of high byte (bits 12-15), preserve pin 1 value
cfg->misc_io_initial_latch = (cfg->misc_io_initial_latch & 0x0FFF) | (static_cast<uint16_t>(dacValue) << 12);
}
return true;
}
};
}