Skip to content

Commit

Permalink
Bring rhs2116 up to date with main and gateware 0.3
Browse files Browse the repository at this point in the history
- Stimulus trigger device accepts a delay in microsends to the
applicatin of a stimulus
- Mark CheckLinkStatus as virtual so headstage can be reset between
power cycles (see #120)
- Rebase main and take advantage of latest improvments with respect to
port voltage override
  • Loading branch information
jonnew committed Jun 28, 2024
1 parent 0ab52ed commit 203054b
Show file tree
Hide file tree
Showing 8 changed files with 66 additions and 43 deletions.
24 changes: 16 additions & 8 deletions Bonsai/Bonsai.config
Original file line number Diff line number Diff line change
@@ -1,23 +1,26 @@
<?xml version="1.0" encoding="utf-8"?>
<PackageConfiguration xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<Packages>
<Package id="Bonsai" version="2.8.1" />
<Package id="Bonsai.Core" version="2.8.1" />
<Package id="Bonsai.Design" version="2.8.0" />
<Package id="Bonsai" version="2.8.3" />
<Package id="Bonsai.Core" version="2.8.2" />
<Package id="Bonsai.Design" version="2.8.1" />
<Package id="Bonsai.Design.Visualizers" version="2.8.0" />
<Package id="Bonsai.Dsp" version="2.8.0" />
<Package id="Bonsai.Dsp.Design" version="2.8.0" />
<Package id="Bonsai.Editor" version="2.8.0" />
<Package id="Bonsai.Editor" version="2.8.2" />
<Package id="Bonsai.Scripting.Expressions" version="2.8.0" />
<Package id="Bonsai.Scripting.Expressions.Design" version="2.8.0" />
<Package id="Bonsai.System" version="2.8.0" />
<Package id="Bonsai.System.Design" version="2.8.0" />
<Package id="Bonsai.Vision" version="2.8.0" />
<Package id="Bonsai.Vision.Design" version="2.8.0" />
<Package id="Bonsai.Windows.Input" version="2.7.0" />
<Package id="jacobslusser.ScintillaNET" version="3.6.3" />
<Package id="Markdig" version="0.18.1" />
<Package id="MathNet.Numerics" version="5.0.0" />
<Package id="Microsoft.Web.WebView2" version="1.0.1823.32" />
<Package id="OpenCV.Net" version="3.4.2" />
<Package id="OpenEphys.PhaseDetector" version="0.6.0" />
<Package id="OpenTK" version="3.1.0" />
<Package id="OpenTK.GLControl" version="3.1.0" />
<Package id="Rx-Core" version="2.2.5" />
Expand All @@ -43,26 +46,31 @@
<AssemblyReference assemblyName="Bonsai.System.Design" />
<AssemblyReference assemblyName="Bonsai.Vision" />
<AssemblyReference assemblyName="Bonsai.Vision.Design" />
<AssemblyReference assemblyName="Bonsai.Windows.Input" />
<AssemblyReference assemblyName="OpenEphys.PhaseDetector" />
</AssemblyReferences>
<AssemblyLocations>
<AssemblyLocation assemblyName="Bonsai" processorArchitecture="MSIL" location="Packages\Bonsai.2.8.1\lib\net48\Bonsai.exe" />
<AssemblyLocation assemblyName="Bonsai.Core" processorArchitecture="MSIL" location="Packages\Bonsai.Core.2.8.1\lib\net462\Bonsai.Core.dll" />
<AssemblyLocation assemblyName="Bonsai.Design" processorArchitecture="MSIL" location="Packages\Bonsai.Design.2.8.0\lib\net462\Bonsai.Design.dll" />
<AssemblyLocation assemblyName="Bonsai" processorArchitecture="MSIL" location="Packages\Bonsai.2.8.3\lib\net48\Bonsai.exe" />
<AssemblyLocation assemblyName="Bonsai.Core" processorArchitecture="MSIL" location="Packages\Bonsai.Core.2.8.2\lib\net462\Bonsai.Core.dll" />
<AssemblyLocation assemblyName="Bonsai.Design" processorArchitecture="MSIL" location="Packages\Bonsai.Design.2.8.1\lib\net462\Bonsai.Design.dll" />
<AssemblyLocation assemblyName="Bonsai.Design.Visualizers" processorArchitecture="MSIL" location="Packages\Bonsai.Design.Visualizers.2.8.0\lib\net462\Bonsai.Design.Visualizers.dll" />
<AssemblyLocation assemblyName="Bonsai.Dsp" processorArchitecture="MSIL" location="Packages\Bonsai.Dsp.2.8.0\lib\net462\Bonsai.Dsp.dll" />
<AssemblyLocation assemblyName="Bonsai.Dsp.Design" processorArchitecture="MSIL" location="Packages\Bonsai.Dsp.Design.2.8.0\lib\net462\Bonsai.Dsp.Design.dll" />
<AssemblyLocation assemblyName="Bonsai.Editor" processorArchitecture="MSIL" location="Packages\Bonsai.Editor.2.8.0\lib\net472\Bonsai.Editor.dll" />
<AssemblyLocation assemblyName="Bonsai.Editor" processorArchitecture="MSIL" location="Packages\Bonsai.Editor.2.8.2\lib\net472\Bonsai.Editor.dll" />
<AssemblyLocation assemblyName="Bonsai.Scripting.Expressions" processorArchitecture="MSIL" location="Packages\Bonsai.Scripting.Expressions.2.8.0\lib\net462\Bonsai.Scripting.Expressions.dll" />
<AssemblyLocation assemblyName="Bonsai.Scripting.Expressions.Design" processorArchitecture="MSIL" location="Packages\Bonsai.Scripting.Expressions.Design.2.8.0\lib\net462\Bonsai.Scripting.Expressions.Design.dll" />
<AssemblyLocation assemblyName="Bonsai.System" processorArchitecture="MSIL" location="Packages\Bonsai.System.2.8.0\lib\net462\Bonsai.System.dll" />
<AssemblyLocation assemblyName="Bonsai.System.Design" processorArchitecture="MSIL" location="Packages\Bonsai.System.Design.2.8.0\lib\net462\Bonsai.System.Design.dll" />
<AssemblyLocation assemblyName="Bonsai.Vision" processorArchitecture="MSIL" location="Packages\Bonsai.Vision.2.8.0\lib\net462\Bonsai.Vision.dll" />
<AssemblyLocation assemblyName="Bonsai.Vision.Design" processorArchitecture="MSIL" location="Packages\Bonsai.Vision.Design.2.8.0\lib\net462\Bonsai.Vision.Design.dll" />
<AssemblyLocation assemblyName="Bonsai.Windows.Input" processorArchitecture="MSIL" location="Packages\Bonsai.Windows.Input.2.7.0\lib\net462\Bonsai.Windows.Input.dll" />
<AssemblyLocation assemblyName="Markdig" processorArchitecture="MSIL" location="Packages\Markdig.0.18.1\lib\net40\Markdig.dll" />
<AssemblyLocation assemblyName="MathNet.Numerics" processorArchitecture="MSIL" location="Packages\MathNet.Numerics.5.0.0\lib\net48\MathNet.Numerics.dll" />
<AssemblyLocation assemblyName="Microsoft.Web.WebView2.Core" processorArchitecture="MSIL" location="Packages\Microsoft.Web.WebView2.1.0.1823.32\lib\net45\Microsoft.Web.WebView2.Core.dll" />
<AssemblyLocation assemblyName="Microsoft.Web.WebView2.WinForms" processorArchitecture="MSIL" location="Packages\Microsoft.Web.WebView2.1.0.1823.32\lib\net45\Microsoft.Web.WebView2.WinForms.dll" />
<AssemblyLocation assemblyName="Microsoft.Web.WebView2.Wpf" processorArchitecture="MSIL" location="Packages\Microsoft.Web.WebView2.1.0.1823.32\lib\net45\Microsoft.Web.WebView2.Wpf.dll" />
<AssemblyLocation assemblyName="OpenCV.Net" processorArchitecture="MSIL" location="Packages\OpenCV.Net.3.4.2\lib\net462\OpenCV.Net.dll" />
<AssemblyLocation assemblyName="OpenEphys.PhaseDetector" processorArchitecture="MSIL" location="Packages\OpenEphys.PhaseDetector.0.6.0\lib\net472\OpenEphys.PhaseDetector.dll" />
<AssemblyLocation assemblyName="OpenTK" processorArchitecture="MSIL" location="Packages\OpenTK.3.1.0\lib\net20\OpenTK.dll" />
<AssemblyLocation assemblyName="OpenTK.GLControl" processorArchitecture="MSIL" location="Packages\OpenTK.GLControl.3.1.0\lib\net20\OpenTK.GLControl.dll" />
<AssemblyLocation assemblyName="ScintillaNET" processorArchitecture="MSIL" location="Packages\jacobslusser.ScintillaNET.3.6.3\lib\net40\ScintillaNET.dll" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Bonsai.Core" Version="2.8.0" />
<PackageReference Include="Bonsai.Core" Version="2.8.2" />
</ItemGroup>

<ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public ConfigureFmcLinkController()
"Consult the device datasheet and documentation for allowable voltage ranges.")]
public double? PortVoltage { get; set; } = null;

protected bool CheckLinkState(DeviceContext device)
protected virtual bool CheckLinkState(DeviceContext device)
{
var linkState = device.ReadRegister(FmcLinkController.LINKSTATE);
return (linkState & FmcLinkController.LINKSTATE_SL) != 0;
Expand Down
60 changes: 34 additions & 26 deletions OpenEphys.Onix/OpenEphys.Onix/ConfigureHeadstageRhs2116.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,12 +31,12 @@ public ConfigureHeadstageRhs2116()
[TypeConverter(typeof(HubDeviceConverter))]
public ConfigureRhs2116Trigger StimulusTrigger { get; set; } = new();

internal override void UpdateDeviceNames(string hubName)
internal override void UpdateDeviceNames()
{
LinkController.DeviceName = $"{hubName}/{nameof(LinkController)}";
Rhs2116A.DeviceName = $"{hubName}/{nameof(Rhs2116A)}";
Rhs2116B.DeviceName = $"{hubName}/{nameof(Rhs2116B)}";
StimulusTrigger.DeviceName = $"{hubName}/{nameof(StimulusTrigger)}";
LinkController.DeviceName = GetFullDeviceName(nameof(LinkController));
Rhs2116A.DeviceName = GetFullDeviceName(nameof(Rhs2116A));
Rhs2116B.DeviceName = GetFullDeviceName(nameof(Rhs2116B));
StimulusTrigger.DeviceName = GetFullDeviceName(nameof(StimulusTrigger));
}

public PortName Port
Expand All @@ -53,6 +53,16 @@ public PortName Port
}
}


[Description("If defined, it will override automated voltage discovery and apply the specified voltage" +
"to the headstage. Warning: this device requires 3.4V to 4.4V for proper operation." +
"Supplying higher voltages may result in damage to the headstage.")]
public double? PortVoltage
{
get => LinkController.PortVoltage;
set => LinkController.PortVoltage = value;
}

internal override IEnumerable<IDeviceConfiguration> GetDevices()
{
yield return LinkController;
Expand All @@ -65,40 +75,38 @@ class ConfigureHeadstageRhs2116LinkController : ConfigureFmcLinkController
{
protected override bool ConfigurePortVoltage(DeviceContext device)
{
const uint MinVoltage = 33;
const uint MaxVoltage = 50;
const uint VoltageOffset = 25;
const uint VoltageIncrement = 02;
const double MinVoltage = 3.3;
const double MaxVoltage = 4.4;
const double VoltageOffset = 2.0;
const double VoltageIncrement = 0.2;

for (uint voltage = MinVoltage; voltage <= MaxVoltage; voltage += VoltageIncrement)
for (var voltage = MinVoltage; voltage <= MaxVoltage; voltage += VoltageIncrement)
{
SetPortVoltage(device, voltage);
if (CheckLinkState(device))
if (base.CheckLinkState(device))
{
SetPortVoltage(device, voltage + VoltageOffset);
if (CheckLinkState(device))
{
// TODO: The RHS2116 headstage needs an additional reset after power on
// to provide its device table.
Thread.Sleep(500);
device.Context.Reset();
return true;
}
else break;
return CheckLinkState(device);
}
}

return false;
}

private void SetPortVoltage(DeviceContext device, uint voltage)
private void SetPortVoltage(DeviceContext device, double voltage)
{
const int WaitUntilVoltageOffSettles = 500;
const int WaitUntilVoltageOnSettles = 500;
device.WriteRegister(FmcLinkController.PORTVOLTAGE, 0);
Thread.Sleep(WaitUntilVoltageOffSettles);
device.WriteRegister(FmcLinkController.PORTVOLTAGE, voltage);
Thread.Sleep(WaitUntilVoltageOnSettles);
Thread.Sleep(500);
device.WriteRegister(FmcLinkController.PORTVOLTAGE, (uint)(10 * voltage));
Thread.Sleep(500);
}

protected override bool CheckLinkState(DeviceContext device)
{
// NB: The RHS2116 headstage needs an additional reset after power on to provide its device table.
device.Context.Reset();
var linkState = device.ReadRegister(FmcLinkController.LINKSTATE);
return (linkState & FmcLinkController.LINKSTATE_SL) != 0;
}
}
}
Expand Down
1 change: 1 addition & 0 deletions OpenEphys.Onix/OpenEphys.Onix/ConfigureRhs2116.cs
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,7 @@ static class Rhs2116
// constants
public const int AmplifierChannelCount = 16;
public const int StimMemorySlotsAvailable = 1024;
public const double SampleFrequencyHz = 30.1932367151e3;

// managed registers
public const uint ENABLE = 0x8000; // Enable or disable the data output stream (32767)
Expand Down
2 changes: 1 addition & 1 deletion OpenEphys.Onix/OpenEphys.Onix/OpenEphys.Onix.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Bonsai.Core" Version="2.8.0" />
<PackageReference Include="Bonsai.Core" Version="2.8.2" />
<PackageReference Include="clroni" Version="6.1.0" />
<PackageReference Include="OpenCV.Net" Version="3.4.2" />
</ItemGroup>
Expand Down
4 changes: 2 additions & 2 deletions OpenEphys.Onix/OpenEphys.Onix/Rhs2116Data.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,8 @@ public unsafe override IObservable<Rhs2116DataFrame> Generate()
clockBuffer[sampleIndex] = frame.Clock;
if (++sampleIndex >= bufferSize)
{
var amplifierData = BufferHelper.CopyBuffer(amplifierBuffer, bufferSize, Rhs2116.AmplifierChannelCount, Depth.U16);
var dcData = BufferHelper.CopyBuffer(dcBuffer, bufferSize, Rhs2116.AmplifierChannelCount, Depth.U16);
var amplifierData = BufferHelper.CopyTranspose(amplifierBuffer, bufferSize, Rhs2116.AmplifierChannelCount, Depth.U16);
var dcData = BufferHelper.CopyTranspose(dcBuffer, bufferSize, Rhs2116.AmplifierChannelCount, Depth.U16);
observer.OnNext(new Rhs2116DataFrame(clockBuffer, hubClockBuffer, amplifierData, dcData));
hubClockBuffer = new ulong[bufferSize];
clockBuffer = new ulong[bufferSize];
Expand Down
14 changes: 10 additions & 4 deletions OpenEphys.Onix/OpenEphys.Onix/Rhs2116StimulusTrigger.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,19 +6,25 @@

namespace OpenEphys.Onix
{
public class Rhs2116StimulusTrigger : Sink<bool>
public class Rhs2116StimulusTrigger : Sink<double>
{
[TypeConverter(typeof(Rhs2116Trigger.NameConverter))]
public string DeviceName { get; set; }

public override IObservable<bool> Process(IObservable<bool> source)
public override IObservable<double> Process(IObservable<double> source)
{
return Observable.Using(
() => DeviceManager.ReserveDevice(DeviceName),
disposable => disposable.Subject.SelectMany(deviceInfo =>
{
var device = deviceInfo.GetDeviceContext(typeof(Rhs2116Trigger));
return source.Do(t => device.WriteRegister(Rhs2116Trigger.TRIGGER, t ? 1u : 0u));
var device = deviceInfo.GetDeviceContext(typeof(Rhs2116Trigger));
return source.Do(t =>
{
const double SampleFrequencyMegaHz = Rhs2116.SampleFrequencyHz / 1e6;
var delaySamples = (int)(t * SampleFrequencyMegaHz);
device.WriteRegister(Rhs2116Trigger.TRIGGER, (uint)(delaySamples << 12 | 0x1));
});
}));
}
}
Expand Down

0 comments on commit 203054b

Please sign in to comment.