Skip to content

Commit 11c0648

Browse files
authored
Merge pull request #463 from open-ephys/issue-462
Add support for digital input sampling mode
2 parents 692e3e3 + 235d355 commit 11c0648

File tree

1 file changed

+72
-1
lines changed

1 file changed

+72
-1
lines changed

OpenEphys.Onix1/ConfigureDigitalIO.cs

Lines changed: 72 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
using System;
22
using System.ComponentModel;
3+
using Bonsai;
4+
using Bonsai.Reactive;
35

46
namespace OpenEphys.Onix1
57
{
@@ -18,6 +20,10 @@ public class ConfigureBreakoutDigitalIO : ConfigureDigitalIO { }
1820
[Description("Configures the ONIX breakout board's digital inputs and outputs.")]
1921
public class ConfigureDigitalIO : SingleDeviceFactory
2022
{
23+
24+
double? sampleRate = null;
25+
double deadTime = 0;
26+
2127
/// <summary>
2228
/// Initialize a new instance of the <see cref="ConfigureDigitalIO"/> class.
2329
/// </summary>
@@ -38,6 +44,49 @@ public ConfigureDigitalIO()
3844
[Description("Specifies whether the digital IO device is enabled.")]
3945
public bool Enable { get; set; } = true;
4046

47+
/// <summary>
48+
/// Gets or sets the dead time, in μsec, between event detections when in asynchronous
49+
/// sampling mode.
50+
/// </summary>
51+
/// <remarks>
52+
/// This property is useful for filtering "glitches" due to rapidly changing port states, for instance
53+
/// from switch bounce. This property has no effect when <see cref="SampleRate"/> is set and periodic
54+
/// sampling mode is active.
55+
/// </remarks>
56+
[Range(0, 1e6)]
57+
[Category(ConfigurationCategory)]
58+
[Description("Specifies dead time, in μsec, between digital event detections when in asynchronous " +
59+
"sampling mode")]
60+
public double DeadTime
61+
{
62+
get => deadTime;
63+
set => deadTime = (value >= 0 && value <= 1e6)
64+
? value
65+
: throw new ArgumentOutOfRangeException(nameof(DeadTime), value,
66+
$"{nameof(DeadTime)} must be between 0 and 1e6 μsec.");
67+
}
68+
69+
/// <summary>
70+
/// Gets or sets the optional sample rate, in Hz, of the digital inputs.
71+
/// </summary>
72+
/// <remarks>
73+
/// If specified, digital inputs will be sampled periodically at the specified rate in Hz. If not
74+
/// specified, digital input data will be produced asynchronously upon changes in digital input state
75+
/// as long as the changes do not occur in the <see cref="DeadTime"/> with respect to the last
76+
/// detected digital event.
77+
/// </remarks>
78+
[Range(10, 1e6)]
79+
[Category(ConfigurationCategory)]
80+
[Description("Specifies the optional sample rate, in Hz, of digital inputs. If not specified, digital " +
81+
"data will be produced asynchronously upon changes in digital input state.")]
82+
public double? SampleRate {
83+
get => sampleRate;
84+
set => sampleRate = (value >= 10 && value <= 1e6) | value is null
85+
? value
86+
: throw new ArgumentOutOfRangeException(nameof(SampleRate), value,
87+
$"{nameof(SampleRate)} must be between 10 Hz and 1 MHz.");
88+
}
89+
4190
/// <summary>
4291
/// Configures the digital input and output device in the ONIX breakout board.
4392
/// </summary>
@@ -55,10 +104,25 @@ public override IObservable<ContextTask> Process(IObservable<ContextTask> source
55104
{
56105
var deviceName = DeviceName;
57106
var deviceAddress = DeviceAddress;
107+
var dt = deadTime;
108+
var sr = SampleRate;
58109
return source.ConfigureDevice(context =>
59110
{
60111
var device = context.GetDeviceContext(deviceAddress, DeviceType);
61112
device.WriteRegister(DigitalIO.ENABLE, Enable ? 1u : 0);
113+
114+
var baseFreqHz = device.ReadRegister(DigitalIO.BASE_FREQ_HZ);
115+
device.WriteRegister(DigitalIO.DEAD_TICKS, (uint)(dt / 1e6 * baseFreqHz));
116+
117+
if (sr is not null)
118+
{
119+
var periodTicks = (uint)(baseFreqHz / sr);
120+
device.WriteRegister(DigitalIO.SAMPLE_PERIOD, periodTicks);
121+
} else
122+
{
123+
device.WriteRegister(DigitalIO.SAMPLE_PERIOD, 0);
124+
}
125+
62126
return DeviceManager.RegisterDevice(deviceName, device, DeviceType);
63127
});
64128
}
@@ -69,7 +133,10 @@ static class DigitalIO
69133
public const int ID = 18;
70134

71135
// managed registers
72-
public const uint ENABLE = 0x0; // Enable or disable the data output stream
136+
public const uint ENABLE = 0x0;
137+
public const uint BASE_FREQ_HZ = 0x5;
138+
public const uint DEAD_TICKS = 0x6;
139+
public const uint SAMPLE_PERIOD = 0x7;
73140

74141
internal class NameConverter : DeviceNameConverter
75142
{
@@ -126,6 +193,10 @@ public enum DigitalPortState : byte
126193
[Flags]
127194
public enum BreakoutButtonState : ushort
128195
{
196+
/// <summary>
197+
/// Specifies that no buttons or switches are active.
198+
/// </summary>
199+
None = 0x0,
129200
/// <summary>
130201
/// Specifies that the ☾ key is depressed.
131202
/// </summary>

0 commit comments

Comments
 (0)