Skip to content

Commit

Permalink
Minor fixes to breakout board clock ouput
Browse files Browse the repository at this point in the history
- Constrain frequency and duty cycle with exceptions
- Remove unsafe designation from BreakoutOutputClockData.Generate()
- Lots of XML improvments
- Improve public property names
  • Loading branch information
jonnew committed Sep 13, 2024
1 parent 9ea405f commit 1f4e21b
Show file tree
Hide file tree
Showing 2 changed files with 55 additions and 34 deletions.
2 changes: 1 addition & 1 deletion OpenEphys.Onix1/BreakoutOutputClockData.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ public class BreakoutOutputClockData : Source<BreakoutOutputClockParameters>
/// Generates a sequence containing a single <see cref="BreakoutOutputClockParameters"/>.
/// </summary>
/// <returns>A sequence containing a single <see cref="BreakoutOutputClockParameters"/></returns>
public unsafe override IObservable<BreakoutOutputClockParameters> Generate()
public override IObservable<BreakoutOutputClockParameters> Generate()
{
return DeviceManager.GetDevice(DeviceName).SelectMany(
deviceInfo =>
Expand Down
87 changes: 54 additions & 33 deletions OpenEphys.Onix1/ConfigureBreakoutOutputClock.cs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
namespace OpenEphys.Onix1
{
/// <summary>
/// Configures a the breakout board's output clock.
/// Configures the ONIX breakout board's output clock.
/// </summary>
/// <remarks>
/// The output clock provides physical, 3.3V logic level, 50 Ohm output impedance, frequency divided copy
Expand All @@ -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.
/// </remarks>
[Description("Configures a heartbeat device.")]
[Description("Configures the ONIX breakout board's output clock.")]
public class ConfigureBreakoutOutputClock : SingleDeviceFactory
{
readonly BehaviorSubject<bool> gate = new(false);
double frequencyHz = 1e6;
double dutyCycle = 50;

/// <summary>
/// Initializes a new instance of the <see cref="ConfigureBreakoutOutputClock"/> class.
Expand All @@ -32,13 +34,13 @@ public ConfigureBreakoutOutputClock()
}

/// <summary>
/// Gets or sets a value specifying of the output clock is active.
/// Gets or sets a value specifying if the output clock is active.
/// </summary>
/// <remarks>
/// 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.
/// </remarks>
[Range(1, 10e6)]
[Category(AcquisitionCategory)]
[Description("Clock gate control signal.")]
public bool ClockGate
Expand All @@ -51,48 +53,63 @@ public bool ClockGate
/// Gets or sets the output clock frequency in Hz.
/// </summary>
/// <remarks>
/// The output clock high and low times must each be an integer multiple of the <see
/// cref="ContextTask.AcquisitionClockHz">Acquisition Clock</see> 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 <see
/// cref="BreakoutOutputClockData"/>.
/// 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 <see cref="ContextTask.AcquisitionClockHz">Acquisition Clock</see>
/// 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 <see cref="BreakoutOutputClockData"/>.
/// </remarks>
[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.");
}

/// <summary>
/// Gets or sets the output clock duty cycle in percent.
/// </summary>
/// <remarks>
/// The output clock high and low times must each be an integer multiple of the <see
/// cref="ContextTask.AcquisitionClockHz">Acquisition Clock</see> 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 <see
/// cref="BreakoutOutputClockData"/>.
/// Valid values are between 10% and 90%. The output clock high and low times must each be an integer
/// multiple of the <see cref="ContextTask.AcquisitionClockHz">Acquisition Clock</see> 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 <see cref="BreakoutOutputClockData"/>.
/// </remarks>
[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%.");
}

/// <summary>
/// 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.
/// </summary>
/// <remarks>
/// <para>
/// Setting to a value greater than 0 can be useful for ensuring data sources that are driven by the
/// <c>System Clock</c> 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.
/// </para>
/// <para>
/// The delay must each be an integer multiple of the <see
/// cref="ContextTask.AcquisitionClockHz">Acquisition Clock</see> 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 <see
/// respecting this constraint. The value as actualized in hardware is reported by <see
/// cref="BreakoutOutputClockData"/>.
/// </para>
/// </remarks>
Expand Down Expand Up @@ -134,8 +151,8 @@ public override IObservable<ContextTask> Process(IObservable<ContextTask> 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(() =>
{
Expand Down Expand Up @@ -175,20 +192,24 @@ public NameConverter()
/// <summary>
/// Hardware-verified output clock parameters.
/// </summary>
/// <param name="FrequencyHz">Gets the exact clock frequency as actualized by the clock synthesizer in
/// <param name="Frequency">Gets the exact clock frequency as actualized by the clock synthesizer in
/// Hz.</param>
/// <param name="DutyCyclePercent">Gets the exact clock duty cycle as actualized by the clock synthesizer
/// <param name="DutyCycle">Gets the exact clock duty cycle as actualized by the clock synthesizer
/// in percent.</param>
/// <param name="DelaySeconds">Gets the exact clock delay as actualized by the clock synthesizer in
/// <param name="Delay">Gets the exact clock delay as actualized by the clock synthesizer in
/// seconds.</param>
/// <param name="PeriodTicks">Gets the exact clock period as actualized by the clock synthesizer in units
/// of ticks of the of the <see cref="ContextTask.AcquisitionClockHz">Acquisition Clock</see>.</param>
/// <param name="HighTicks">Gets the exact clock high time as actualized by the clock synthesizer in units
/// of ticks of the of the <see cref="ContextTask.AcquisitionClockHz">Acquisition Clock</see>.</param>
/// <param name="HighTicks">Gets the exact clock high time per period as actualized by the clock
/// synthesizer in units of ticks of the of the <see cref="ContextTask.AcquisitionClockHz">Acquisition
/// Clock</see>.</param>
/// <param name="LowTicks">Gets the exact clock low time per period as actualized by the clock synthesizer
/// in units of ticks of the of the <see cref="ContextTask.AcquisitionClockHz">Acquisition
/// Clock</see>.</param>
/// <param name="DelayTicks">Gets the exact clock delay as actualized by the clock synthesizer in units of
/// ticks of the of the <see cref="ContextTask.AcquisitionClockHz">Acquisition Clock</see>.</param>
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
{
Expand All @@ -198,6 +219,6 @@ public BreakoutOutputClockDeviceInfo(DeviceContext device, Type deviceType, Brea
Parameters = parameters;
}

public BreakoutOutputClockParameters Parameters { get; }
public BreakoutOutputClockParameters Parameters { get; }
}
}

0 comments on commit 1f4e21b

Please sign in to comment.