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
55 changes: 40 additions & 15 deletions articles/hardware/hs64/estim.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,26 +3,51 @@ 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.
<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. 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
between triggering the stimulus and delivery of the stimulus. When `Double`'s
`Value` property is set to zero, there is no delay.
46 changes: 46 additions & 0 deletions articles/hardware/hs64/gpo-trigger.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
---
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.

<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 "Square", its
output is "True" when the selected `BreakoutButtonState` bit field contains the
"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.
<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. 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
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_.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_.csv"
using a `CsvWriter`.

3 changes: 3 additions & 0 deletions articles/hardware/hs64/workflow.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@ The example workflow below can by copy/pasted into the Bonsai editor using the c
- 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 enabled and 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
33 changes: 20 additions & 13 deletions workflows/hardware/hs64/estim.bonsai
Original file line number Diff line number Diff line change
Expand Up @@ -22,22 +22,27 @@
<Expression xsi:type="Combinator">
<Combinator xsi:type="rx:DistinctUntilChanged" />
</Expression>
<Expression xsi:type="rx:Condition">
<Workflow>
<Nodes>
<Expression xsi:type="WorkflowInput">
<Name>Source1</Name>
</Expression>
<Expression xsi:type="WorkflowOutput" />
</Nodes>
<Edges>
<Edge From="0" To="1" Label="Source1" />
</Edges>
</Workflow>
</Expression>
<Expression xsi:type="Combinator">
<Combinator xsi:type="DoubleProperty">
<Value>0</Value>
</Combinator>
</Expression>
<Expression xsi:type="Combinator">
<Combinator xsi:type="onix1:Headstage64ElectricalStimulatorTrigger">
<onix1:DeviceName>Headstage64/Headstage64ElectricalStimulator</onix1:DeviceName>
<onix1:Enable>true</onix1:Enable>
<onix1:PowerEnable>true</onix1:PowerEnable>
<onix1:TriggerDelay>0</onix1:TriggerDelay>
<onix1:PhaseOneCurrent>100</onix1:PhaseOneCurrent>
<onix1:InterPhaseCurrent>0</onix1:InterPhaseCurrent>
<onix1:PhaseTwoCurrent>-100</onix1:PhaseTwoCurrent>
<onix1:PhaseOneDuration>200</onix1:PhaseOneDuration>
<onix1:InterPhaseInterval>0</onix1:InterPhaseInterval>
<onix1:PhaseTwoDuration>200</onix1:PhaseTwoDuration>
<onix1:InterPulseInterval>400</onix1:InterPulseInterval>
<onix1:InterBurstInterval>0</onix1:InterBurstInterval>
<onix1:BurstPulseCount>5</onix1:BurstPulseCount>
<onix1:TrainBurstCount>1</onix1:TrainBurstCount>
</Combinator>
</Expression>
</Nodes>
Expand All @@ -46,6 +51,8 @@
<Edge From="1" To="2" Label="Source1" />
<Edge From="2" To="3" Label="Source1" />
<Edge From="3" To="4" Label="Source1" />
<Edge From="4" To="5" Label="Source1" />
<Edge From="5" To="6" Label="Source1" />
</Edges>
</Workflow>
</WorkflowBuilder>
38 changes: 38 additions & 0 deletions workflows/hardware/hs64/gpo-trigger.bonsai
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
<?xml version="1.0" encoding="utf-8"?>
<WorkflowBuilder Version="2.9.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p1="clr-namespace:OpenEphys.Onix1;assembly=OpenEphys.Onix1"
xmlns:rx="clr-namespace:Bonsai.Reactive;assembly=Bonsai.Core"
xmlns="https://bonsai-rx.org/2018/workflow">
<Workflow>
<Nodes>
<Expression xsi:type="Combinator">
<Combinator xsi:type="p1:DigitalInput">
<p1:DeviceName>BreakoutBoard/DigitalIO</p1:DeviceName>
</Combinator>
</Expression>
<Expression xsi:type="MemberSelector">
<Selector>Buttons</Selector>
</Expression>
<Expression xsi:type="HasFlag">
<Operand xsi:type="WorkflowProperty" TypeArguments="p1:BreakoutButtonState">
<Value>Square</Value>
</Operand>
</Expression>
<Expression xsi:type="Combinator">
<Combinator xsi:type="rx:DistinctUntilChanged" />
</Expression>
<Expression xsi:type="Combinator">
<Combinator xsi:type="p1:Headstage64GpoTrigger">
<p1:DeviceName>Headstage64/Headstage64PortController</p1:DeviceName>
</Combinator>
</Expression>
</Nodes>
<Edges>
<Edge From="0" To="1" Label="Source1" />
<Edge From="1" To="2" Label="Source1" />
<Edge From="2" To="3" Label="Source1" />
<Edge From="3" To="4" Label="Source1" />
</Edges>
</Workflow>
</WorkflowBuilder>
Loading