Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 8 additions & 7 deletions articles/hardware/breakout/digital-inputs.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,16 @@ functionality by responding to button presses and saves digital inputs data.
:::

The <xref:OpenEphys.Onix1.DigitalInput> operator generates a sequence of
[DigitalInputDataFrames](xref:OpenEphys.Onix1.DigitalInputDataFrame). In this workflow, digital inputs
are configured to be asynchronous. This means that although the digital inputs
are sampled in hardware at 4 Mhz, data frames are only emitted when the port
status changes (i.e., when a pin, button, or switch is toggled). Digital inputs
can also be
[DigitalInputDataFrames](xref:OpenEphys.Onix1.DigitalInputDataFrame). In this
workflow, digital inputs are configured to be asynchronous. This means that
although the digital inputs are sampled in hardware at 4 Mhz, data frames are
only emitted when the port status changes (i.e., when a pin, button, or switch
is toggled) when the `SampleRate` is left blank such as is done in this example
workflow. Digital inputs can also be
[configured](xref:OpenEphys.Onix1.ConfigureBreakoutBoard#OpenEphys_Onix1_ConfigureBreakoutBoard_DigitalIO)
to be sampled at regular intervals. The digital input ports on the Breakout
Board use 3.3V logic levels but are also 5V tolerant. In the Breakout
Board example workflow, the `DigitalInput`'s `DeviceName` property is set to
Board use 3.3V logic levels but are also 5V tolerant. In the Breakout Board
example workflow, the `DigitalInput`'s `DeviceName` property is set to
"BreakoutBoard/DigitalInput". This links the `DigitalInput` operator to the
corresponding configuration operator.

Expand Down
54 changes: 39 additions & 15 deletions articles/hardware/hs64/estim.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,26 +3,50 @@ uid: hs64_estim
title: Headstage 64 Electrical Stimulation
---

The following excerpt from the Headstage 64 [example workflow](xref:hs64_workflow) demonstrates electrical stimulation by
triggering a train of pulses following a press of the △ key on the breakout board.
The following excerpt from the Headstage 64 [example
workflow](xref:hs64_workflow) demonstrates electrical stimulation by triggering
a train of pulses following a press of the △ key on the breakout board.

> [!NOTE]
> Only one (electrical or optical) stimulator can armed at a time. If both
> stimulators are armed, the electrical stimulator takes precedence, e.g.
> the electrical stimulator stays armed and the optical stimulator is
> automatically disarmed by the headstage firmware. If you want to interleave
> optical stimulation and electrical stimulation, you must coordinate the
> stimulators to be dynamically armed and disarmed.

::: workflow
![/workflows/hardware/hs64/estim.bonsai workflow](../../../workflows/hardware/hs64/estim.bonsai)
:::

The <xref:OpenEphys.Onix1.DigitalInput> operator generates a sequence of
[DigitalInputDataFrames](xref:OpenEphys.Onix1.DigitalInputDataFrame). Although the digital inputs
are sampled at 4 Mhz, these data frames are only emitted when the port status changes (i.e., when a
pin, button, or switch is toggled). In the Breakout Board example workflow, the `DigitalInput`'s
`DeviceName` property is set to "BreakoutBoard/DigitalInput". This links the `DigitalInput` operator
to the corresponding configuration operator.
[DigitalInputDataFrames](xref:OpenEphys.Onix1.DigitalInputDataFrame). Although
the digital inputs are sampled at 4 Mhz, these data frames are only emitted when
the port status changes (i.e., when a pin, button, or switch is toggled) when
`DigitalInput`'s `SampleRate` property is left blank such as is done in the
example workflow. The `DigitalInput`'s `DeviceName` property is set to
"BreakoutBoard/DigitalInput". This links the `DigitalInput` operator to the
corresponding configuration operator.

<xref:OpenEphys.Onix1.BreakoutButtonState> is selected from the `DigitalInputDataFrame`. It is an enumerator with values
that correspond to bit positions of the breakout board's digital port. When this type is connected to a `HasFlags`
operator, the enumerated values appear in the `HasFlags`'s `Value` property's dropdown menu. Because `HasFlags`'s
`Value` is set to "Triangle", its output is "True" when the selected `BreakoutButtonState` bit field contains the
"Triangle" flag.
[Buttons](xref:OpenEphys.Onix1.BreakoutButtonState) is selected from the
`DigitalInputDataFrame` and passed to a `HasFlags` operator, which filters the
sequence based on which button is pressed using the `Value` property's dropdown
menu. In this case, `HasFlags`'s `Value` is set to "Triangle", so its output is
"True" when an item its input sequence contains a "Triangle" flag. The
<xref:Bonsai.Reactive.DistinctUntilChanged> operator only passes an item in its
input sequence if it's different from the previous item in the input sequence.
The <xref:Bonsai.Reactive.Condition> operator only passes an item in its input
sequence if `Condition`'s internal logic is "True". In this case, `Condition`
has no internal logic (which can be inspected by selecting the node and pressing
<kbd>Ctrl+Enter</kbd>), so it uses the value of the Boolean in its input
sequence to decide whether or not to pass through an item in its input sequence
to its output sequence.

When the <xref:OpenEphys.Onix1.Headstage64ElectricalStimulatorTrigger> operator receives a "True" value in its input
sequence, a stimulus waveform is triggered. The waveform can be modified by editing the
`Headstage64ElectricalStimulatorTrig` operator's properties.
The <xref:Bonsai.Expressions.DoubleProperty> operator emits a
<xref:System.Double> determined by `Double`'s `Value` property whenever it
receives an item in its input sequence. Each double in the input sequence
received by <xref:OpenEphys.Onix1.Headstage64ElectricalStimulatorTrigger>
triggers an electrical stimulus waveform. The value of the double determines the
delay in microseconds, executed on the hardware, between triggering the stimulus
and delivery of the stimulus. When `Double`'s `Value` property is set to zero,
there is no delay.
44 changes: 44 additions & 0 deletions articles/hardware/hs64/gpo-trigger.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
---
uid: hs64_gpo-trigger
title: Headstage 64 GPO Trigger
---

The following excerpt from the Headstage 64 [example
workflow](xref:hs64_workflow) demonstrates triggering a stimulus following a
press of the X key on the breakout board. The GPO trigger toggles a pin on the
headstage to trigger stimulus which occurs more instantaneously than writing to
a register on the headstage which is how the
<xref:OpenEphys.Onix1.Headstage64ElectricalStimulatorTrigger> and
<xref:OpenEphys.Onix1.Headstage64OpticalStimulatorTrigger> operators trigger
stimuli.

> [!NOTE]
> Only one (electrical or optical) stimulator can armed at a time. If both
> stimulators are armed, the electrical stimulator takes precedence, e.g.
> the electrical stimulator stays armed and the optical stimulator is
> automatically disarmed by the headstage firmware. If you want to interleave
> optical stimulation and electrical stimulation, you must coordinate the
> stimulators to be dynamically armed and disarmed.

::: workflow
![/workflows/hardware/hs64/gpo-trigger.bonsai workflow](../../../workflows/hardware/hs64/gpo-trigger.bonsai)
:::

The <xref:OpenEphys.Onix1.DigitalInput> operator generates a sequence of
[DigitalInputDataFrames](xref:OpenEphys.Onix1.DigitalInputDataFrame). Although
the digital inputs are sampled at 4 Mhz, these data frames are only emitted when
the port status changes (i.e., when a pin, button, or switch is toggled) when
`DigitalInput`'s `SampleRate` property is left blank such as is done in the
example workflow. The `DigitalInput`'s `DeviceName` property is set to
"BreakoutBoard/DigitalInput". This links the `DigitalInput` operator to the
corresponding configuration operator.

[Buttons](xref:OpenEphys.Onix1.BreakoutButtonState) is selected from the
`DigitalInputDataFrame` and passed to a `HasFlags` operator, which filters the
sequence based on which button is pressed using the `Value` property's dropdown
menu. In this case, `HasFlags`'s `Value` is set to "Square", so its output is
"True" when an item its input sequence contains a "Square" flag. The
<xref:Bonsai.Reactive.DistinctUntilChanged> operator only passes an item in its
input sequence if it's different from the previous item in the input sequence.
When the <xref:OpenEphys.Onix1.Headstage64GpoTrigger> operator receives a "True"
value in its input sequence, a stimulus waveform is triggered.
54 changes: 39 additions & 15 deletions articles/hardware/hs64/ostim.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,26 +3,50 @@ uid: hs64_ostim
title: Headstage 64 Optical Stimulation
---

The following excerpt from the Headstage64 [example workflow](xref:hs64_workflow) demonstrates optical stimulation by
triggering a train of pulses following a press of the ◯ key on the breakout board.
The following excerpt from the Headstage64 [example
workflow](xref:hs64_workflow) demonstrates optical stimulation by triggering a
train of pulses following a press of the ◯ key on the breakout board.

> [!NOTE]
> Only one (electrical or optical) stimulator can armed at a time. If both
> stimulators are armed, the electrical stimulator takes precedence, e.g.
> the electrical stimulator stays armed and the optical stimulator is
> automatically disarmed by the headstage firmware. If you want to interleave
> optical stimulation and electrical stimulation, you must coordinate the
> stimulators to be dynamically armed and disarmed.

::: workflow
![/workflows/hardware/hs64/ostim.bonsai workflow](../../../workflows/hardware/hs64/ostim.bonsai)
:::

The <xref:OpenEphys.Onix1.DigitalInput> operator generates a sequence of
[DigitalInputDataFrames](xref:OpenEphys.Onix1.DigitalInputDataFrame). Although the digital inputs
are sampled at 4 Mhz, these data frames are only emitted when the port status changes (i.e., when a
pin, button, or switch is toggled). In the Breakout Board example workflow, the `DigitalInput`'s
`DeviceName` property is set to "BreakoutBoard/DigitalInput". This links the `DigitalInput` operator
to the corresponding configuration operator.
[DigitalInputDataFrames](xref:OpenEphys.Onix1.DigitalInputDataFrame). Although
the digital inputs are sampled at 4 Mhz, these data frames are only emitted when
the port status changes (i.e., when a pin, button, or switch is toggled) when
`DigitalInput`'s `SampleRate` property is left blank such as is done in the
example workflow. The `DigitalInput`'s `DeviceName` property is set to
"BreakoutBoard/DigitalInput". This links the `DigitalInput` operator to the
corresponding configuration operator.

<xref:OpenEphys.Onix1.BreakoutButtonState> is selected from the `DigitalInputDataFrame`. It is an enumerator with values
that correspond to bit positions of the breakout board's digital port. When this type is connected to a `HasFlags`
operator, the enumerated values appear in the `HasFlags`'s `Value` property's dropdown menu. Because `HasFlags`'s
`Value` is set to "Circle", its output is "True" when the selected `BreakoutButtonState` bit field contains the
"Circle" flag.
[Buttons](xref:OpenEphys.Onix1.BreakoutButtonState) is selected from the
`DigitalInputDataFrame` and passed to a `HasFlags` operator, which filters the
sequence based on which button is pressed using the `Value` property's dropdown
menu. In this case, `HasFlags`'s `Value` is set to "Circle", so its output is
"True" when an item its input sequence contains a "Circle" flag. The
<xref:Bonsai.Reactive.DistinctUntilChanged> operator only passes an item in its
input sequence if it's different from the previous item in the input sequence.
The <xref:Bonsai.Reactive.Condition> operator only passes an item in its input
sequence if `Condition`'s internal logic is "True". In this case, `Condition`
has no internal logic (which can be inspected by selecting the node and pressing
<kbd>Ctrl+Enter</kbd>), so it uses the value of the Boolean in its input
sequence to decide whether or not to pass through an item in its input sequence
to its output sequence.

When the <xref:OpenEphys.Onix1.Headstage64OpticalStimulatorTrigger> operator receives a "True" value in its input
sequence, a stimulus waveform is triggered. The waveform can be modified by editing the
`Headstage64OpticalStimulatorTrig` operator's properties.
The <xref:Bonsai.Expressions.DoubleProperty> operator emits a
<xref:System.Double> determined by `Double`'s `Value` property whenever it
receives an item in its input sequence. Each double in the input sequence
received by <xref:OpenEphys.Onix1.Headstage64OpticalStimulatorTrigger> triggers
an optical stimulus. The value of the double determines the delay in
microseconds, executed on the hardware, between triggering the stimulus and
delivery of the stimulus. When `Double`'s `Value` property is set to zero, there
is no delay.
38 changes: 38 additions & 0 deletions articles/hardware/hs64/stimulator-data.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
---
uid: hs64_stimulator-data
title: Headstage 64 Stimulator Data
---

The following excerpt from the Headstage 64 [example
workflow](xref:hs64_workflow) demonstrates how to save the waveform parameters
and the hardware timestamp of every stimulus delivered as described in the
<xref:hs64_estim>, <xref:hs64_ostim>, and <xref:hs64_gpo-trigger> articles.

::: workflow
![/workflows/hardware/hs64/stimulator-data.bonsai workflow](../../../workflows/hardware/hs64/stimulator-data.bonsai)
:::

The <xref:OpenEphys.Onix1.Headstage64ElectricalStimulatorData> operator
generates a sequence of
[Headstage64ElectricalStimulatorDataFrames](xref:OpenEphys.Onix1.Headstage64ElectricalStimulatorDataFrame)
which contain data about when an electrical stimulus was delivered and the
corresponding electrical stimulation waveform. A frame is emitted when an
electrical stimulus is delivered. In the Headstage 64 example workflow, the
`Headstage64ElectricalStimulatorData`'s `DeviceName` property is set to
"Headstage64/Headstage64ElectricalStimulator". This links the
`Headstage64ElectricalStimulatorData` operator to the corresponding
configuration operator. Frames from this operators are saved to a file named
`estim_<filecount>.csv` using a <xref:Bonsai.IO.CsvWriter>.

The <xref:OpenEphys.Onix1.Headstage64OpticalStimulatorData> operator generates a
sequence of
[Headstage64OpticalStimulatorDataFrames](xref:OpenEphys.Onix1.Headstage64OpticalStimulatorDataFrame)
which contain data about when an optical stimulus was delivered and the
corresponding optical stimulation waveform. A frame is emitted when an optical
stimulus is delivered. In the Headstage 64 example workflow, the
`Headstage64OpticalStimulatorData`'s `DeviceName` property is set to
"Headstage64/Headstage64OpticalStimulator". This links the
`Headstage64OpticalStimulatorData` operator to the corresponding configuration
operator. Frames from this operators are saved to a file named `ostim_<filecount>.csv`
using a `CsvWriter`.

11 changes: 11 additions & 0 deletions articles/hardware/hs64/workflow.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,24 @@ uid: hs64_workflow
title: Headstage 64 Example Workflow
---

> [!IMPORTANT]
> This workflow requires OpenEphys.Onix1 0.7.0+ and Headstage 64 0.4.0. You can
> update the OpenEphys.Onix1 package using [Bonsai's Package
> Manager](xref:workflow-editor) and you can update the Headstage's firmware
> using the [ONIX Hub
> Updater](https://open-ephys.github.io/onix-docs/docs/Hardware
> Guide/Headstages/updating-firmware.html)

The example workflow below can by copy/pasted into the Bonsai editor using the clipboard icon in the top right. This workflow:
- Captures electrophysiology data from passive probes via the RHD2164 amplifier and saves it to disk.
- Captures orientation data from the Bno055 IMU and saves it to disk.
- Monitors the Headstage 64 port status.
- Automatically commutates the tether if there is a proper commutator connection.
- Applies electrical stimulation triggered by pressing the breakout board's △ key.
- Applies optical stimulation triggered by pressing the breakout board's ◯ key.
- Applies either electrical or optical stimulation (depending on which stimulators
are armed) using a lower latency trigger mechanism by pressing the breakout
board's X key.
- Monitors memory usage data.

::: workflow
Expand Down
4 changes: 4 additions & 0 deletions articles/toc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,10 @@
href: hardware/hs64/estim.md
- name: Optical Stimulation
href: hardware/hs64/ostim.md
- name: GPO Trigger
href: hardware/hs64/gpo-trigger.md
- name: Stimulator Data
href: hardware/hs64/stimulator-data.md
- name: Memory Monitor
href: hardware/hs64/memory-monitor.md
- href: hardware/hs64/load-data.md
Expand Down
3 changes: 2 additions & 1 deletion docfx.json
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,8 @@
"xref": [
"https://bonsai-rx.org/docs/xrefmap.yml",
"https://horizongir.github.io/opencv.net/xrefmap.yml",
"https://horizongir.github.io/reactive/xrefmap.yml"
"https://horizongir.github.io/reactive/xrefmap.yml",
"https://learn.microsoft.com/en-us/dotnet/.xrefmap.json"
]
},
"rules": {
Expand Down
31 changes: 30 additions & 1 deletion workflows/hardware/hs64/configuration.bonsai
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
<onix1:Heartbeat>
<onix1:DeviceName>BreakoutBoard/PersistentHeartbeat</onix1:DeviceName>
<onix1:DeviceAddress>0</onix1:DeviceAddress>
<onix1:Enable>true</onix1:Enable>
<onix1:BeatsPerSecond>100</onix1:BeatsPerSecond>
</onix1:Heartbeat>
<onix1:AnalogIO>
Expand Down Expand Up @@ -55,6 +54,8 @@
<onix1:DeviceName>BreakoutBoard/DigitalIO</onix1:DeviceName>
<onix1:DeviceAddress>7</onix1:DeviceAddress>
<onix1:Enable>true</onix1:Enable>
<onix1:DeadTime>0</onix1:DeadTime>
<onix1:SampleRate xsi:nil="true" />
</onix1:DigitalIO>
<onix1:ClockOutput>
<onix1:DeviceName>BreakoutBoard/OutputClock</onix1:DeviceName>
Expand Down Expand Up @@ -102,11 +103,39 @@
<onix1:ElectricalStimulator>
<onix1:DeviceName>Headstage64/Headstage64ElectricalStimulator</onix1:DeviceName>
<onix1:DeviceAddress>259</onix1:DeviceAddress>
<onix1:Enable>true</onix1:Enable>
<onix1:Arm>true</onix1:Arm>
<onix1:PhaseOneCurrent>200</onix1:PhaseOneCurrent>
<onix1:InterPhaseCurrent>0</onix1:InterPhaseCurrent>
<onix1:PhaseTwoCurrent>-200</onix1:PhaseTwoCurrent>
<onix1:PhaseOneDuration>100</onix1:PhaseOneDuration>
<onix1:InterPhaseInterval>0</onix1:InterPhaseInterval>
<onix1:PhaseTwoDuration>100</onix1:PhaseTwoDuration>
<onix1:InterPulseInterval>10000</onix1:InterPulseInterval>
<onix1:InterBurstInterval>0</onix1:InterBurstInterval>
<onix1:BurstPulseCount>10</onix1:BurstPulseCount>
<onix1:TrainBurstCount>1</onix1:TrainBurstCount>
</onix1:ElectricalStimulator>
<onix1:OpticalStimulator>
<onix1:DeviceName>Headstage64/Headstage64OpticalStimulator</onix1:DeviceName>
<onix1:DeviceAddress>260</onix1:DeviceAddress>
<onix1:Enable>true</onix1:Enable>
<onix1:EnableIndicationLed>false</onix1:EnableIndicationLed>
<onix1:Arm>true</onix1:Arm>
<onix1:MaxCurrent>30</onix1:MaxCurrent>
<onix1:ChannelOneCurrent>0</onix1:ChannelOneCurrent>
<onix1:ChannelTwoCurrent>100</onix1:ChannelTwoCurrent>
<onix1:PulseDuration>10</onix1:PulseDuration>
<onix1:PulsesPerSecond>10</onix1:PulsesPerSecond>
<onix1:PulsesPerBurst>10</onix1:PulsesPerBurst>
<onix1:InterBurstInterval>0</onix1:InterBurstInterval>
<onix1:BurstsPerTrain>1</onix1:BurstsPerTrain>
</onix1:OpticalStimulator>
<onix1:Heartbeat>
<onix1:DeviceName>Headstage64/PersistentHeartbeat</onix1:DeviceName>
<onix1:DeviceAddress>261</onix1:DeviceAddress>
<onix1:BeatsPerSecond>10</onix1:BeatsPerSecond>
</onix1:Heartbeat>
<onix1:Port>PortA</onix1:Port>
<onix1:PortVoltage>
<onix1:Requested xsi:nil="true" />
Expand Down
Loading