From 1f4e21b62f9c7197e48ff1afc11f5c8c843d0452 Mon Sep 17 00:00:00 2001 From: jonnew Date: Fri, 13 Sep 2024 10:58:47 -0400 Subject: [PATCH] Minor fixes to breakout board clock ouput - Constrain frequency and duty cycle with exceptions - Remove unsafe designation from BreakoutOutputClockData.Generate() - Lots of XML improvments - Improve public property names --- OpenEphys.Onix1/BreakoutOutputClockData.cs | 2 +- .../ConfigureBreakoutOutputClock.cs | 87 ++++++++++++------- 2 files changed, 55 insertions(+), 34 deletions(-) diff --git a/OpenEphys.Onix1/BreakoutOutputClockData.cs b/OpenEphys.Onix1/BreakoutOutputClockData.cs index 4b74c99..50a0f2b 100644 --- a/OpenEphys.Onix1/BreakoutOutputClockData.cs +++ b/OpenEphys.Onix1/BreakoutOutputClockData.cs @@ -27,7 +27,7 @@ public class BreakoutOutputClockData : Source /// Generates a sequence containing a single . /// /// A sequence containing a single - public unsafe override IObservable Generate() + public override IObservable Generate() { return DeviceManager.GetDevice(DeviceName).SelectMany( deviceInfo => diff --git a/OpenEphys.Onix1/ConfigureBreakoutOutputClock.cs b/OpenEphys.Onix1/ConfigureBreakoutOutputClock.cs index fdc98c7..3d9fbd5 100644 --- a/OpenEphys.Onix1/ConfigureBreakoutOutputClock.cs +++ b/OpenEphys.Onix1/ConfigureBreakoutOutputClock.cs @@ -8,7 +8,7 @@ namespace OpenEphys.Onix1 { /// - /// Configures a the breakout board's output clock. + /// Configures the ONIX breakout board's output clock. /// /// /// The output clock provides physical, 3.3V logic level, 50 Ohm output impedance, frequency divided copy @@ -17,10 +17,12 @@ namespace OpenEphys.Onix1 /// user defined rate, duty cycle, and start delay. It can be used to drive external hardware or can be /// logged by external recording systems for post-hoc synchronization with ONIX data. /// - [Description("Configures a heartbeat device.")] + [Description("Configures the ONIX breakout board's output clock.")] public class ConfigureBreakoutOutputClock : SingleDeviceFactory { readonly BehaviorSubject gate = new(false); + double frequencyHz = 1e6; + double dutyCycle = 50; /// /// Initializes a new instance of the class. @@ -32,13 +34,13 @@ public ConfigureBreakoutOutputClock() } /// - /// Gets or sets a value specifying of the output clock is active. + /// Gets or sets a value specifying if the output clock is active. /// /// /// If set to true, the clock output will connected to the clock output line. If set to false, the - /// clock output line will be held low. + /// clock output line will be held low. This value can be toggled in real time to gate acquisition of + /// external hardware. /// - [Range(1, 10e6)] [Category(AcquisitionCategory)] [Description("Clock gate control signal.")] public bool ClockGate @@ -51,48 +53,63 @@ public bool ClockGate /// Gets or sets the output clock frequency in Hz. /// /// - /// The output clock high and low times must each be an integer multiple of the Acquisition Clock frequency. Therefore, the true clock - /// frequency will be set to a value that is as close as possible to the requested setting while - /// respecting this constraint. The value as actualized in hardware is available using . + /// Valid values are between 0.1 Hz and 10 MHz. The output clock high and low times must each be an + /// integer multiple of the Acquisition Clock + /// frequency. Therefore, the true clock frequency will be set to a value that is as close as possible + /// to the requested setting while respecting this constraint. The value as actualized in hardware is + /// reported by . /// - [Range(1, 10e6)] + [Range(0.1, 10e6)] [Category(ConfigurationCategory)] [Description("Frequency of the output clock (Hz).")] - public double Frequency { get; set; } = 1e6; + public double Frequency + { + get => frequencyHz; + set => frequencyHz = value >= 0.1 && value <= 10e6 + ? value + : throw new ArgumentOutOfRangeException(nameof(Frequency), value, + $"{nameof(Frequency)} must be between 0.1 Hz and 10 MHz."); + } /// /// Gets or sets the output clock duty cycle in percent. /// /// - /// The output clock high and low times must each be an integer multiple of the Acquisition Clock frequency. Therefore, the true duty - /// cycle will be set to a value that is as close as possible to the requested setting while - /// respecting this constraint. The value as actualized in hardware is available using . + /// Valid values are between 10% and 90%. The output clock high and low times must each be an integer + /// multiple of the Acquisition Clock frequency. + /// Therefore, the true duty cycle will be set to a value that is as close as possible to the + /// requested setting while respecting this constraint. The value as actualized in hardware is + /// reported by . /// [Range(10, 90)] [Editor(DesignTypes.SliderEditor, typeof(UITypeEditor))] [Category(ConfigurationCategory)] [Precision(1, 1)] [Description("Duty cycle of output clock (%).")] - public double DutyCycle { get; set; } = 50.0; + public double DutyCycle + { + get => dutyCycle; + set => dutyCycle = value >= 10 && value <= 90 + ? value + : throw new ArgumentOutOfRangeException(nameof(DutyCycle), value, + $"{nameof(DutyCycle)} must be between 10% and 90%."); + } /// - /// Gets or sets the delay following acquisition start before the clock becomes active in seconds. + /// Gets or sets the delay following acquisition commencement before the clock becomes active in + /// seconds. /// /// /// - /// Setting to a value greater than 0 can be useful for ensuring data sources that are driven by the - /// System Clock start significantly after ONIX has begun aquisition for the purposes of - /// ordering acquisition start times. + /// Valid values are between 0 and and 3600 seconds. Setting to a value greater than 0 can be useful + /// for ensuring data sources that are driven by the output clock start significantly after ONIX has + /// begun aquisition for the purposes of ordering acquisition start times. /// /// /// The delay must each be an integer multiple of the Acquisition Clock frequency. Therefore, the true delay /// cycle will be set to a value that is as close as possible to the requested setting while - /// respecting this constraint. The value as actualized in hardware is available using . /// /// @@ -134,8 +151,8 @@ public override IObservable Process(IObservable source device.WriteRegister(BreakoutOutputClock.LOW_CYCLES, l); device.WriteRegister(BreakoutOutputClock.DELAY_CYCLES, delayTicks); - var deviceInfo = new BreakoutOutputClockDeviceInfo(device, DeviceType, - new BreakoutOutputClockParameters(baseFreqHz / (h + l), 100 * h / periodTicks, delaySeconds, h + l, h, delayTicks)); + var deviceInfo = new BreakoutOutputClockDeviceInfo(device, DeviceType, + new(baseFreqHz / (h + l), 100 * h / periodTicks, delaySeconds, h + l, h, l, delayTicks)); var shutdown = Disposable.Create(() => { @@ -175,20 +192,24 @@ public NameConverter() /// /// Hardware-verified output clock parameters. /// - /// Gets the exact clock frequency as actualized by the clock synthesizer in + /// Gets the exact clock frequency as actualized by the clock synthesizer in /// Hz. - /// Gets the exact clock duty cycle as actualized by the clock synthesizer + /// Gets the exact clock duty cycle as actualized by the clock synthesizer /// in percent. - /// Gets the exact clock delay as actualized by the clock synthesizer in + /// Gets the exact clock delay as actualized by the clock synthesizer in /// seconds. /// Gets the exact clock period as actualized by the clock synthesizer in units /// of ticks of the of the Acquisition Clock. - /// Gets the exact clock high time as actualized by the clock synthesizer in units - /// of ticks of the of the Acquisition Clock. + /// Gets the exact clock high time per period as actualized by the clock + /// synthesizer in units of ticks of the of the Acquisition + /// Clock. + /// Gets the exact clock low time per period as actualized by the clock synthesizer + /// in units of ticks of the of the Acquisition + /// Clock. /// Gets the exact clock delay as actualized by the clock synthesizer in units of /// ticks of the of the Acquisition Clock. - public readonly record struct BreakoutOutputClockParameters(double FrequencyHz, - double DutyCyclePercent, double DelaySeconds, uint PeriodTicks, uint HighTicks, uint DelayTicks); + public readonly record struct BreakoutOutputClockParameters(double Frequency, + double DutyCycle, double Delay, uint PeriodTicks, uint HighTicks, uint LowTicks, uint DelayTicks); class BreakoutOutputClockDeviceInfo : DeviceInfo { @@ -198,6 +219,6 @@ public BreakoutOutputClockDeviceInfo(DeviceContext device, Type deviceType, Brea Parameters = parameters; } - public BreakoutOutputClockParameters Parameters { get; } + public BreakoutOutputClockParameters Parameters { get; } } }