Compare commits
9 Commits
6a427b2ea1
...
f547082cad
| Author | SHA1 | Date |
|---|---|---|
|
|
f547082cad | |
|
|
224e840841 | |
|
|
174c0b80d4 | |
|
|
19092bceb6 | |
|
|
25b673075f | |
|
|
1a7bc4df47 | |
|
|
20a2474508 | |
|
|
d18ca9e6eb | |
|
|
31d4a750d8 |
2
LICENSE
2
LICENSE
|
|
@ -1,4 +1,4 @@
|
||||||
Copyright (c) 2018-2025 Intrepid Control Systems, Inc.
|
Copyright (c) 2018-2026 Intrepid Control Systems, Inc.
|
||||||
|
|
||||||
Redistribution and use in source and binary forms, with or without modification,
|
Redistribution and use in source and binary forms, with or without modification,
|
||||||
are permitted provided that the following conditions are met:
|
are permitted provided that the following conditions are met:
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,7 @@ BEGIN
|
||||||
VALUE "FileDescription", "Intrepid Control Systems Open Device Communication C API"
|
VALUE "FileDescription", "Intrepid Control Systems Open Device Communication C API"
|
||||||
VALUE "FileVersion", VER_FILEVERSION_STR
|
VALUE "FileVersion", VER_FILEVERSION_STR
|
||||||
VALUE "InternalName", "icsneoc.dll"
|
VALUE "InternalName", "icsneoc.dll"
|
||||||
VALUE "LegalCopyright", "Intrepid Control Systems, Inc. (C) 2018-2025"
|
VALUE "LegalCopyright", "Intrepid Control Systems, Inc. (C) 2018-2026"
|
||||||
VALUE "OriginalFilename", "icsneoc.dll"
|
VALUE "OriginalFilename", "icsneoc.dll"
|
||||||
VALUE "ProductName", "libicsneo"
|
VALUE "ProductName", "libicsneo"
|
||||||
VALUE "ProductVersion", VER_PRODUCTVERSION_STR
|
VALUE "ProductVersion", VER_PRODUCTVERSION_STR
|
||||||
|
|
|
||||||
|
|
@ -40,6 +40,14 @@ void init_idevicesettings(pybind11::module_& m) {
|
||||||
.value("Normal", LINMode::NORMAL_MODE)
|
.value("Normal", LINMode::NORMAL_MODE)
|
||||||
.value("Fast", LINMode::FAST_MODE);
|
.value("Fast", LINMode::FAST_MODE);
|
||||||
|
|
||||||
|
pybind11::enum_<MiscIOAnalogVoltage>(settings, "MiscIOAnalogVoltage")
|
||||||
|
.value("V0", MiscIOAnalogVoltage::V0)
|
||||||
|
.value("V1", MiscIOAnalogVoltage::V1)
|
||||||
|
.value("V2", MiscIOAnalogVoltage::V2)
|
||||||
|
.value("V3", MiscIOAnalogVoltage::V3)
|
||||||
|
.value("V4", MiscIOAnalogVoltage::V4)
|
||||||
|
.value("V5", MiscIOAnalogVoltage::V5);
|
||||||
|
|
||||||
pybind11::classh<IDeviceSettings>(m, "IDeviceSettings")
|
pybind11::classh<IDeviceSettings>(m, "IDeviceSettings")
|
||||||
.def("apply", &IDeviceSettings::apply, pybind11::arg("temporary") = 0, pybind11::call_guard<pybind11::gil_scoped_release>())
|
.def("apply", &IDeviceSettings::apply, pybind11::arg("temporary") = 0, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||||
.def("apply_defaults", &IDeviceSettings::applyDefaults, pybind11::arg("temporary") = 0, pybind11::call_guard<pybind11::gil_scoped_release>())
|
.def("apply_defaults", &IDeviceSettings::applyDefaults, pybind11::arg("temporary") = 0, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||||
|
|
@ -97,6 +105,9 @@ void init_idevicesettings(pybind11::module_& m) {
|
||||||
.def("get_t1s_burst_timer", &IDeviceSettings::getT1SBurstTimerFor, pybind11::call_guard<pybind11::gil_scoped_release>())
|
.def("get_t1s_burst_timer", &IDeviceSettings::getT1SBurstTimerFor, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||||
.def("set_t1s_burst_timer", &IDeviceSettings::setT1SBurstTimerFor, pybind11::call_guard<pybind11::gil_scoped_release>())
|
.def("set_t1s_burst_timer", &IDeviceSettings::setT1SBurstTimerFor, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||||
|
|
||||||
|
.def("set_misc_io_analog_output_enabled", &IDeviceSettings::setMiscIOAnalogOutputEnabled, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||||
|
.def("set_misc_io_analog_output", &IDeviceSettings::setMiscIOAnalogOutput, pybind11::call_guard<pybind11::gil_scoped_release>())
|
||||||
|
|
||||||
// Status properties
|
// Status properties
|
||||||
.def_readonly("disabled", &IDeviceSettings::disabled)
|
.def_readonly("disabled", &IDeviceSettings::disabled)
|
||||||
.def_readonly("readonly", &IDeviceSettings::readonly);
|
.def_readonly("readonly", &IDeviceSettings::readonly);
|
||||||
|
|
|
||||||
|
|
@ -133,6 +133,10 @@ EthernetPacketizer::EthernetPacket::EthernetPacket(const uint8_t* data, size_t s
|
||||||
|
|
||||||
int EthernetPacketizer::EthernetPacket::loadBytestream(const std::vector<uint8_t>& bytestream) {
|
int EthernetPacketizer::EthernetPacket::loadBytestream(const std::vector<uint8_t>& bytestream) {
|
||||||
errorWhileDecodingFromBytestream = 0;
|
errorWhileDecodingFromBytestream = 0;
|
||||||
|
if (bytestream.size() < 24) {
|
||||||
|
errorWhileDecodingFromBytestream = 1;
|
||||||
|
return errorWhileDecodingFromBytestream;
|
||||||
|
}
|
||||||
for(size_t i = 0; i < 6; i++)
|
for(size_t i = 0; i < 6; i++)
|
||||||
destMAC[i] = bytestream[i];
|
destMAC[i] = bytestream[i];
|
||||||
for(size_t i = 0; i < 6; i++)
|
for(size_t i = 0; i < 6; i++)
|
||||||
|
|
|
||||||
|
|
@ -3817,7 +3817,7 @@ bool Device::formatDisk(const DiskDetails& config, const DiskFormatProgress& han
|
||||||
return com->sendCommand(ExtendedCommand::DiskFormatProgress, {});
|
return com->sendCommand(ExtendedCommand::DiskFormatProgress, {});
|
||||||
},
|
},
|
||||||
std::make_shared<ExtendedResponseFilter>(ExtendedCommand::DiskFormatProgress),
|
std::make_shared<ExtendedResponseFilter>(ExtendedCommand::DiskFormatProgress),
|
||||||
std::chrono::milliseconds(200)
|
std::chrono::milliseconds(1000)
|
||||||
);
|
);
|
||||||
|
|
||||||
if(!response) {
|
if(!response) {
|
||||||
|
|
|
||||||
|
|
@ -946,3 +946,17 @@ template<typename T> bool IDeviceSettings::applyStructure(const T& newStructure)
|
||||||
memcpy(settings.data(), &newStructure, structSize);
|
memcpy(settings.data(), &newStructure, structSize);
|
||||||
return apply();
|
return apply();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool IDeviceSettings::setMiscIOAnalogOutputEnabled(uint8_t pin, bool enabled) {
|
||||||
|
(void)pin;
|
||||||
|
(void)enabled;
|
||||||
|
report(APIEvent::Type::SettingNotAvaiableDevice, APIEvent::Severity::Error);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool IDeviceSettings::setMiscIOAnalogOutput(uint8_t pin, MiscIOAnalogVoltage voltage) {
|
||||||
|
(void)pin;
|
||||||
|
(void)voltage;
|
||||||
|
report(APIEvent::Type::SettingNotAvaiableDevice, APIEvent::Severity::Error);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
@ -12,7 +12,7 @@ subprocess.call('cd ..; doxygen docs/icsneoc/Doxyfile', shell=True)
|
||||||
# https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information
|
# https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information
|
||||||
|
|
||||||
project = 'libicsneo'
|
project = 'libicsneo'
|
||||||
copyright = '2024-2025, Intrepid Control Systems, Inc.'
|
copyright = '2024-2026, Intrepid Control Systems, Inc.'
|
||||||
author = 'Intrepid Control Systems, Inc.'
|
author = 'Intrepid Control Systems, Inc.'
|
||||||
|
|
||||||
# -- General configuration ---------------------------------------------------
|
# -- General configuration ---------------------------------------------------
|
||||||
|
|
|
||||||
|
|
@ -91,3 +91,11 @@ SPI Example for 10BASE-T1S
|
||||||
|
|
||||||
.. literalinclude:: ../../examples/python/spi/spi_example.py
|
.. literalinclude:: ../../examples/python/spi/spi_example.py
|
||||||
:language: python
|
:language: python
|
||||||
|
|
||||||
|
Analog Output Control
|
||||||
|
=====================
|
||||||
|
|
||||||
|
:download:`Download example <../../examples/python/analog_out/analog_out_basic.py>`
|
||||||
|
|
||||||
|
.. literalinclude:: ../../examples/python/analog_out/analog_out_basic.py
|
||||||
|
:language: python
|
||||||
|
|
|
||||||
|
|
@ -14,6 +14,7 @@ option(LIBICSNEO_BUILD_CPP_APP_ERROR_EXAMPLE "Build the macsec example" ON)
|
||||||
option(LIBICSNEO_BUILD_CPP_FLEXRAY_EXAMPLE "Build the FlexRay example." ON)
|
option(LIBICSNEO_BUILD_CPP_FLEXRAY_EXAMPLE "Build the FlexRay example." ON)
|
||||||
option(LIBICSNEO_BUILD_CPP_SPI_EXAMPLE "Build the SPI example." ON)
|
option(LIBICSNEO_BUILD_CPP_SPI_EXAMPLE "Build the SPI example." ON)
|
||||||
option(LIBICSNEO_BUILD_CPP_MUTEX_EXAMPLE "Build the NetworkMutex example." ON)
|
option(LIBICSNEO_BUILD_CPP_MUTEX_EXAMPLE "Build the NetworkMutex example." ON)
|
||||||
|
option(LIBICSNEO_BUILD_CPP_ANALOG_OUT_EXAMPLE "Build the analog output example." ON)
|
||||||
|
|
||||||
add_compile_options(${LIBICSNEO_COMPILER_WARNINGS})
|
add_compile_options(${LIBICSNEO_COMPILER_WARNINGS})
|
||||||
|
|
||||||
|
|
@ -80,3 +81,7 @@ endif()
|
||||||
if(LIBICSNEO_BUILD_CPP_MUTEX_EXAMPLE)
|
if(LIBICSNEO_BUILD_CPP_MUTEX_EXAMPLE)
|
||||||
add_subdirectory(cpp/mutex)
|
add_subdirectory(cpp/mutex)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if(LIBICSNEO_BUILD_CPP_ANALOG_OUT_EXAMPLE)
|
||||||
|
add_subdirectory(cpp/analog_out)
|
||||||
|
endif()
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,2 @@
|
||||||
|
add_executable(libicsneocpp-analog-out src/analog_out.cpp)
|
||||||
|
target_link_libraries(libicsneocpp-analog-out icsneocpp)
|
||||||
|
|
@ -0,0 +1,157 @@
|
||||||
|
/**
|
||||||
|
* libicsneo Analog Output example
|
||||||
|
*
|
||||||
|
* Demonstrates how to configure and control analog outputs on supported devices
|
||||||
|
*
|
||||||
|
* Usage: libicsneo-analog-out <pin> <voltage> [deviceSerial] [--yes]
|
||||||
|
*
|
||||||
|
* Arguments:
|
||||||
|
* pin: Pin number (1-3 for RAD Galaxy)
|
||||||
|
* voltage: Voltage level (0-5)
|
||||||
|
* deviceSerial: 6 character string for device serial (optional)
|
||||||
|
* --yes: Skip confirmation prompt
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <iostream>
|
||||||
|
#include <thread>
|
||||||
|
#include <chrono>
|
||||||
|
#include <string_view>
|
||||||
|
#include <cstdlib>
|
||||||
|
|
||||||
|
#include "icsneo/icsneocpp.h"
|
||||||
|
|
||||||
|
static const std::string usage = "Usage: libicsneo-analog-out <pin> <voltage> [deviceSerial] [--yes]\n\n"
|
||||||
|
"Arguments:\n"
|
||||||
|
"pin: Pin number (1-3 for RAD Galaxy)\n"
|
||||||
|
"voltage: Voltage level (0-5)\n"
|
||||||
|
"deviceSerial: 6 character string for device serial (optional)\n"
|
||||||
|
"--yes: Skip confirmation prompt\n";
|
||||||
|
|
||||||
|
int main(int argc, const char** argv) {
|
||||||
|
std::vector<std::string_view> args(argv, argv + argc);
|
||||||
|
|
||||||
|
// Parse arguments
|
||||||
|
if(args.size() < 3) {
|
||||||
|
std::cerr << "Error: Missing required arguments\n" << std::endl;
|
||||||
|
std::cerr << usage;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
char* endPtr;
|
||||||
|
long pinNum = std::strtol(args[1].data(), &endPtr, 10);
|
||||||
|
if(endPtr != args[1].data() + args[1].size() || pinNum < 1 || pinNum > 3) {
|
||||||
|
std::cerr << "Error: Invalid pin number (must be 1-3)" << std::endl;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
long voltageLevel = std::strtol(args[2].data(), &endPtr, 10);
|
||||||
|
if(endPtr != args[2].data() + args[2].size() || voltageLevel < 0 || voltageLevel > 5) {
|
||||||
|
std::cerr << "Error: Invalid voltage level (must be 0-5)" << std::endl;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
icsneo::MiscIOAnalogVoltage voltage = static_cast<icsneo::MiscIOAnalogVoltage>(voltageLevel);
|
||||||
|
uint8_t pin = static_cast<uint8_t>(pinNum);
|
||||||
|
|
||||||
|
// Check for optional arguments
|
||||||
|
bool skipConfirm = false;
|
||||||
|
std::string_view serial;
|
||||||
|
for(size_t i = 3; i < args.size(); i++) {
|
||||||
|
if(args[i] == "--yes") {
|
||||||
|
skipConfirm = true;
|
||||||
|
} else if(serial.empty() && args[i].size() == 6) {
|
||||||
|
serial = args[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Confirmation prompt
|
||||||
|
if(!skipConfirm) {
|
||||||
|
std::cout << "WARNING: This will set analog output pin " << static_cast<int>(pin)
|
||||||
|
<< " to " << voltageLevel << "V" << std::endl;
|
||||||
|
std::cout << "Make sure nothing sensitive is connected to this pin." << std::endl;
|
||||||
|
std::cout << "Continue? (yes/no): ";
|
||||||
|
std::string response;
|
||||||
|
std::getline(std::cin, response);
|
||||||
|
if(response != "yes") {
|
||||||
|
std::cout << "Aborted." << std::endl;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<icsneo::Device> device = nullptr;
|
||||||
|
|
||||||
|
if(!serial.empty()) {
|
||||||
|
// Find device by serial
|
||||||
|
auto devices = icsneo::FindAllDevices();
|
||||||
|
for(auto& dev : devices) {
|
||||||
|
if(dev->getSerial() == serial) {
|
||||||
|
device = dev;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!device) {
|
||||||
|
std::cerr << "Device with serial " << serial << " not found" << std::endl;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Use first available device
|
||||||
|
auto devices = icsneo::FindAllDevices();
|
||||||
|
if(devices.empty()) {
|
||||||
|
std::cerr << "No devices found" << std::endl;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
device = devices[0];
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout << "Using device: " << device->describe() << std::endl;
|
||||||
|
|
||||||
|
if(!device->open()) {
|
||||||
|
std::cerr << "Failed to open device" << std::endl;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto settings = device->settings;
|
||||||
|
if(!settings) {
|
||||||
|
std::cerr << "Device settings not available" << std::endl;
|
||||||
|
device->close();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout << "Refreshing device settings..." << std::endl;
|
||||||
|
if(!settings->refresh()) {
|
||||||
|
std::cerr << "Failed to refresh settings" << std::endl;
|
||||||
|
device->close();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Enable analog output on specified pin
|
||||||
|
std::cout << "Enabling analog output on pin " << static_cast<int>(pin) << "..." << std::endl;
|
||||||
|
if(!settings->setMiscIOAnalogOutputEnabled(pin, true)) {
|
||||||
|
std::cerr << "Failed to enable analog output on pin " << static_cast<int>(pin) << std::endl;
|
||||||
|
device->close();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set pin to specified voltage
|
||||||
|
std::cout << "Setting pin " << static_cast<int>(pin) << " to " << voltageLevel << "V..." << std::endl;
|
||||||
|
if(!settings->setMiscIOAnalogOutput(pin, voltage)) {
|
||||||
|
std::cerr << "Failed to set voltage on pin " << static_cast<int>(pin) << std::endl;
|
||||||
|
device->close();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Apply settings
|
||||||
|
std::cout << "Applying settings..." << std::endl;
|
||||||
|
if(!settings->apply()) {
|
||||||
|
std::cerr << "Failed to apply settings" << std::endl;
|
||||||
|
device->close();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::cout << "Analog output configured successfully!" << std::endl;
|
||||||
|
std::cout << "Pin " << static_cast<int>(pin) << ": Enabled at " << voltageLevel << "V" << std::endl;
|
||||||
|
|
||||||
|
device->close();
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,107 @@
|
||||||
|
"""
|
||||||
|
Basic analog output control example using icsneopy library.
|
||||||
|
|
||||||
|
Demonstrates how to configure and control analog outputs on supported devices.
|
||||||
|
|
||||||
|
Usage: python analog_out_basic.py <pin> <voltage> [--yes]
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
pin: Pin number (1-3 for RAD Galaxy)
|
||||||
|
voltage: Voltage level (0-5)
|
||||||
|
--yes: Skip confirmation prompt
|
||||||
|
"""
|
||||||
|
|
||||||
|
import sys
|
||||||
|
import icsneopy
|
||||||
|
|
||||||
|
|
||||||
|
def analog_output_example(pin: int, voltage: int, skip_confirm: bool = False):
|
||||||
|
"""Configure and control analog outputs."""
|
||||||
|
# Confirmation prompt
|
||||||
|
if not skip_confirm:
|
||||||
|
print(f"WARNING: This will set analog output pin {pin} to {voltage}V")
|
||||||
|
print("Make sure nothing sensitive is connected to this pin.")
|
||||||
|
response = input("Continue? (yes/no): ")
|
||||||
|
if response.lower() != "yes":
|
||||||
|
print("Aborted.")
|
||||||
|
return
|
||||||
|
|
||||||
|
devices = icsneopy.find_all_devices()
|
||||||
|
if not devices:
|
||||||
|
raise RuntimeError("No devices found")
|
||||||
|
|
||||||
|
device = devices[0]
|
||||||
|
|
||||||
|
try:
|
||||||
|
if not device.open():
|
||||||
|
raise RuntimeError("Failed to open device")
|
||||||
|
|
||||||
|
settings = device.settings
|
||||||
|
if not settings:
|
||||||
|
raise RuntimeError("Device settings not available")
|
||||||
|
|
||||||
|
print("Refreshing device settings...")
|
||||||
|
if not settings.refresh():
|
||||||
|
raise RuntimeError("Failed to refresh settings")
|
||||||
|
|
||||||
|
# Enable analog output on specified pin
|
||||||
|
print(f"Enabling analog output on pin {pin}...")
|
||||||
|
if not settings.set_misc_io_analog_output_enabled(pin, True):
|
||||||
|
raise RuntimeError(f"Failed to enable analog output on pin {pin}")
|
||||||
|
|
||||||
|
# Map voltage level to enum
|
||||||
|
voltage_map = {
|
||||||
|
0: icsneopy.Settings.MiscIOAnalogVoltage.V0,
|
||||||
|
1: icsneopy.Settings.MiscIOAnalogVoltage.V1,
|
||||||
|
2: icsneopy.Settings.MiscIOAnalogVoltage.V2,
|
||||||
|
3: icsneopy.Settings.MiscIOAnalogVoltage.V3,
|
||||||
|
4: icsneopy.Settings.MiscIOAnalogVoltage.V4,
|
||||||
|
5: icsneopy.Settings.MiscIOAnalogVoltage.V5
|
||||||
|
}
|
||||||
|
voltage_enum = voltage_map[voltage]
|
||||||
|
|
||||||
|
# Set pin to specified voltage
|
||||||
|
print(f"Setting pin {pin} to {voltage}V...")
|
||||||
|
if not settings.set_misc_io_analog_output(pin, voltage_enum):
|
||||||
|
raise RuntimeError(f"Failed to set voltage on pin {pin}")
|
||||||
|
|
||||||
|
# Apply settings
|
||||||
|
print("Applying settings...")
|
||||||
|
if not settings.apply():
|
||||||
|
raise RuntimeError("Failed to apply settings")
|
||||||
|
|
||||||
|
print("Analog output configured successfully!")
|
||||||
|
print(f"Pin {pin}: Enabled at {voltage}V")
|
||||||
|
|
||||||
|
finally:
|
||||||
|
device.close()
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
if len(sys.argv) < 3:
|
||||||
|
print("Error: Missing required arguments\n")
|
||||||
|
print("Usage: python analog_out_basic.py <pin> <voltage> [--yes]")
|
||||||
|
print("\nArguments:")
|
||||||
|
print(" pin: Pin number (1-3 for RAD Galaxy)")
|
||||||
|
print(" voltage: Voltage level (0-5)")
|
||||||
|
print(" --yes: Skip confirmation prompt")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
try:
|
||||||
|
pin = int(sys.argv[1])
|
||||||
|
if pin < 1 or pin > 3:
|
||||||
|
print("Error: Invalid pin number (must be 1-3)")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
voltage = int(sys.argv[2])
|
||||||
|
if voltage < 0 or voltage > 5:
|
||||||
|
print("Error: Invalid voltage level (must be 0-5)")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
|
skip_confirm = "--yes" in sys.argv
|
||||||
|
|
||||||
|
analog_output_example(pin, voltage, skip_confirm)
|
||||||
|
|
||||||
|
except ValueError:
|
||||||
|
print("Error: Pin and voltage must be integers")
|
||||||
|
sys.exit(1)
|
||||||
|
|
@ -128,6 +128,7 @@ enum class ChipID : uint8_t {
|
||||||
RADGALAXY2_SYSMON_CHIP = 123,
|
RADGALAXY2_SYSMON_CHIP = 123,
|
||||||
RADCOMET3_ZCHIP = 125,
|
RADCOMET3_ZCHIP = 125,
|
||||||
Connect_LINUX = 126,
|
Connect_LINUX = 126,
|
||||||
|
RADMOONT1S_ZCHIP = 130,
|
||||||
RADGigastar2_ZYNQ = 131,
|
RADGigastar2_ZYNQ = 131,
|
||||||
RADGemini_MCHIP = 135,
|
RADGemini_MCHIP = 135,
|
||||||
Invalid = 255
|
Invalid = 255
|
||||||
|
|
|
||||||
|
|
@ -89,7 +89,10 @@ typedef struct
|
||||||
uint8_t TqSync;
|
uint8_t TqSync;
|
||||||
uint16_t BRP;
|
uint16_t BRP;
|
||||||
uint8_t auto_baud;
|
uint8_t auto_baud;
|
||||||
uint8_t innerFrameDelay25us;
|
uint8_t innerFrameDelay25us : 4;
|
||||||
|
uint8_t rsvd : 1;
|
||||||
|
uint8_t disableRetransmission : 1;
|
||||||
|
uint8_t canClk : 2;
|
||||||
} CAN_SETTINGS;
|
} CAN_SETTINGS;
|
||||||
#define CAN_SETTINGS_SIZE 12
|
#define CAN_SETTINGS_SIZE 12
|
||||||
static_assert(sizeof(CAN_SETTINGS) == CAN_SETTINGS_SIZE, "CAN_SETTINGS is the wrong size!");
|
static_assert(sizeof(CAN_SETTINGS) == CAN_SETTINGS_SIZE, "CAN_SETTINGS is the wrong size!");
|
||||||
|
|
@ -747,6 +750,16 @@ typedef struct
|
||||||
|
|
||||||
namespace icsneo {
|
namespace icsneo {
|
||||||
|
|
||||||
|
enum class MiscIOAnalogVoltage : uint8_t
|
||||||
|
{
|
||||||
|
V0 = 0,
|
||||||
|
V1 = 1,
|
||||||
|
V2 = 2,
|
||||||
|
V3 = 3,
|
||||||
|
V4 = 4,
|
||||||
|
V5 = 5
|
||||||
|
};
|
||||||
|
|
||||||
class IDeviceSettings {
|
class IDeviceSettings {
|
||||||
public:
|
public:
|
||||||
using TerminationGroup = std::vector<Network>;
|
using TerminationGroup = std::vector<Network>;
|
||||||
|
|
@ -1180,6 +1193,9 @@ public:
|
||||||
return false;
|
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(); }
|
const void* getRawStructurePointer() const { return settingsInDeviceRAM.data(); }
|
||||||
void* getMutableRawStructurePointer() { return settings.data(); }
|
void* getMutableRawStructurePointer() { return settings.data(); }
|
||||||
template<typename T> const T* getStructurePointer() const { return reinterpret_cast<const T*>(getRawStructurePointer()); }
|
template<typename T> const T* getStructurePointer() const { return reinterpret_cast<const T*>(getRawStructurePointer()); }
|
||||||
|
|
|
||||||
|
|
@ -185,6 +185,92 @@ public:
|
||||||
return nullptr;
|
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;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -27,6 +27,21 @@ public:
|
||||||
return supportedNetworks;
|
return supportedNetworks;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const std::vector<ChipInfo>& getChipInfo() const override {
|
||||||
|
static std::vector<ChipInfo> chips = {
|
||||||
|
{ChipID::RADJupiter_MCHIP, true, "MCHIP", "jupiter_mchip_ief", 1, FirmwareType::IEF}
|
||||||
|
};
|
||||||
|
return chips;
|
||||||
|
}
|
||||||
|
|
||||||
|
BootloaderPipeline getBootloader() override {
|
||||||
|
return BootloaderPipeline()
|
||||||
|
.add<EnterBootloaderPhase>()
|
||||||
|
.add<FlashPhase>(ChipID::RADJupiter_MCHIP, BootloaderCommunication::RED)
|
||||||
|
.add<EnterApplicationPhase>(ChipID::RADJupiter_MCHIP)
|
||||||
|
.add<ReconnectPhase>();
|
||||||
|
}
|
||||||
|
|
||||||
bool getEthPhyRegControlSupported() const override { return true; }
|
bool getEthPhyRegControlSupported() const override { return true; }
|
||||||
|
|
||||||
ProductID getProductID() const override {
|
ProductID getProductID() const override {
|
||||||
|
|
|
||||||
|
|
@ -37,6 +37,22 @@ public:
|
||||||
ProductID getProductID() const override {
|
ProductID getProductID() const override {
|
||||||
return ProductID::RADMoonT1S;
|
return ProductID::RADMoonT1S;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const std::vector<ChipInfo>& getChipInfo() const override {
|
||||||
|
static std::vector<ChipInfo> chips = {
|
||||||
|
{ChipID::RADMOONT1S_ZCHIP, true, "ZCHIP", "RADMoonT1S_SW_bin", 1, FirmwareType::Zip}
|
||||||
|
};
|
||||||
|
return chips;
|
||||||
|
}
|
||||||
|
|
||||||
|
BootloaderPipeline getBootloader() override {
|
||||||
|
return BootloaderPipeline()
|
||||||
|
.add<EnterBootloaderPhase>()
|
||||||
|
.add<FlashPhase>(ChipID::RADMOONT1S_ZCHIP, BootloaderCommunication::RAD)
|
||||||
|
.add<EnterApplicationPhase>(ChipID::RADMOONT1S_ZCHIP)
|
||||||
|
.add<WaitPhase>(std::chrono::milliseconds(3000))
|
||||||
|
.add<ReconnectPhase>();
|
||||||
|
}
|
||||||
protected:
|
protected:
|
||||||
RADMoonT1S(neodevice_t neodevice, const driver_factory_t& makeDriver) : Device(neodevice) {
|
RADMoonT1S(neodevice_t neodevice, const driver_factory_t& makeDriver) : Device(neodevice) {
|
||||||
initialize<RADMoonT1SSettings>(makeDriver);
|
initialize<RADMoonT1SSettings>(makeDriver);
|
||||||
|
|
|
||||||
|
|
@ -30,6 +30,22 @@ public:
|
||||||
ProductID getProductID() const override {
|
ProductID getProductID() const override {
|
||||||
return ProductID::ValueCAN4Industrial;
|
return ProductID::ValueCAN4Industrial;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const std::vector<ChipInfo>& getChipInfo() const override {
|
||||||
|
static std::vector<ChipInfo> chips = {
|
||||||
|
{ChipID::ValueCAN4Industrial_MCHIP, true, "MCHIP", "vcan4_ind_mchip_ief", 0, FirmwareType::IEF}
|
||||||
|
};
|
||||||
|
return chips;
|
||||||
|
}
|
||||||
|
|
||||||
|
BootloaderPipeline getBootloader() override {
|
||||||
|
return BootloaderPipeline()
|
||||||
|
.add<EnterBootloaderPhase>()
|
||||||
|
.add<FlashPhase>(ChipID::ValueCAN4Industrial_MCHIP, BootloaderCommunication::RED)
|
||||||
|
.add<EnterApplicationPhase>(ChipID::ValueCAN4Industrial_MCHIP)
|
||||||
|
.add<WaitPhase>(std::chrono::milliseconds(3000))
|
||||||
|
.add<ReconnectPhase>();
|
||||||
|
}
|
||||||
protected:
|
protected:
|
||||||
ValueCAN4Industrial(neodevice_t neodevice, const driver_factory_t& makeDriver) : ValueCAN4(neodevice) {
|
ValueCAN4Industrial(neodevice_t neodevice, const driver_factory_t& makeDriver) : ValueCAN4(neodevice) {
|
||||||
initialize<ValueCAN4IndustrialSettings>(makeDriver);
|
initialize<ValueCAN4IndustrialSettings>(makeDriver);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue