Skip to content

Conversation

@jonnew
Copy link
Member

@jonnew jonnew commented Aug 20, 2025

Documentation content

Here is a screenshot of an example workflow in operation for documentation purposes:

image
  • 1000 corresponds to 1 millisecond in this histogram so the average latency is about 100 usec.
  • Input bandwidth is 200 bytes at 100kHz = 20 MB/s
  • Output bandwidth is 1/100th of this, 200 kB/s
  • Block ReadSize is 2048 bytes
  • Block WriteSize is 16384 bytes (preallocation size)
  • Computer specs are:
image

Example workflow

Here is the workflow used to generate above:
<?xml version="1.0" encoding="utf-8"?>
<WorkflowBuilder Version="2.9.0"
               xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
               xmlns:onix1="clr-namespace:OpenEphys.Onix1;assembly=OpenEphys.Onix1"
               xmlns:scr="clr-namespace:Bonsai.Scripting.Expressions;assembly=Bonsai.Scripting.Expressions"
               xmlns:rx="clr-namespace:Bonsai.Reactive;assembly=Bonsai.Core"
               xmlns:dsp="clr-namespace:Bonsai.Dsp;assembly=Bonsai.Dsp"
               xmlns="https://bonsai-rx.org/2018/workflow">
<Workflow>
  <Nodes>
    <Expression xsi:type="Combinator">
      <Combinator xsi:type="onix1:CreateContext">
        <onix1:Driver>riffa</onix1:Driver>
        <onix1:Index>0</onix1:Index>
      </Combinator>
    </Expression>
    <Expression xsi:type="Combinator">
      <Combinator xsi:type="onix1:ConfigureLoadTester">
        <onix1:DeviceName>Load Tester</onix1:DeviceName>
        <onix1:DeviceAddress>11</onix1:DeviceAddress>
        <onix1:Enable>true</onix1:Enable>
        <onix1:ReceivedWords>100</onix1:ReceivedWords>
        <onix1:TransmittedWords>100</onix1:TransmittedWords>
        <onix1:FramesPerSecond>100000</onix1:FramesPerSecond>
      </Combinator>
    </Expression>
    <Expression xsi:type="Combinator">
      <Combinator xsi:type="onix1:ConfigureBreakoutBoard">
        <onix1:Name>BreakoutBoard</onix1:Name>
        <onix1:Heartbeat>
          <onix1:DeviceName>BreakoutBoard/PersistentHeartbeat</onix1:DeviceName>
          <onix1:DeviceAddress>0</onix1:DeviceAddress>
          <onix1:BeatsPerSecond>100</onix1:BeatsPerSecond>
        </onix1:Heartbeat>
        <onix1:AnalogIO>
          <onix1:DeviceName>BreakoutBoard/AnalogIO</onix1:DeviceName>
          <onix1:DeviceAddress>6</onix1:DeviceAddress>
          <onix1:Enable>false</onix1:Enable>
          <onix1:InputRange0>TenVolts</onix1:InputRange0>
          <onix1:InputRange1>TenVolts</onix1:InputRange1>
          <onix1:InputRange2>TenVolts</onix1:InputRange2>
          <onix1:InputRange3>TenVolts</onix1:InputRange3>
          <onix1:InputRange4>TenVolts</onix1:InputRange4>
          <onix1:InputRange5>TenVolts</onix1:InputRange5>
          <onix1:InputRange6>TenVolts</onix1:InputRange6>
          <onix1:InputRange7>TenVolts</onix1:InputRange7>
          <onix1:InputRange8>TenVolts</onix1:InputRange8>
          <onix1:InputRange9>TenVolts</onix1:InputRange9>
          <onix1:InputRange10>TenVolts</onix1:InputRange10>
          <onix1:InputRange11>TenVolts</onix1:InputRange11>
          <onix1:Direction0>Input</onix1:Direction0>
          <onix1:Direction1>Input</onix1:Direction1>
          <onix1:Direction2>Input</onix1:Direction2>
          <onix1:Direction3>Input</onix1:Direction3>
          <onix1:Direction4>Input</onix1:Direction4>
          <onix1:Direction5>Input</onix1:Direction5>
          <onix1:Direction6>Input</onix1:Direction6>
          <onix1:Direction7>Input</onix1:Direction7>
          <onix1:Direction8>Input</onix1:Direction8>
          <onix1:Direction9>Input</onix1:Direction9>
          <onix1:Direction10>Input</onix1:Direction10>
          <onix1:Direction11>Input</onix1:Direction11>
        </onix1:AnalogIO>
        <onix1:DigitalIO>
          <onix1:DeviceName>BreakoutBoard/DigitalIO</onix1:DeviceName>
          <onix1:DeviceAddress>7</onix1:DeviceAddress>
          <onix1:Enable>false</onix1:Enable>
          <onix1:DeadTime>0</onix1:DeadTime>
          <onix1:SampleRate xsi:nil="true" />
        </onix1:DigitalIO>
        <onix1:ClockOutput>
          <onix1:DeviceName>BreakoutBoard/OutputClock</onix1:DeviceName>
          <onix1:DeviceAddress>5</onix1:DeviceAddress>
          <onix1:ClockGate>false</onix1:ClockGate>
          <onix1:Frequency>1000000</onix1:Frequency>
          <onix1:DutyCycle>50</onix1:DutyCycle>
          <onix1:Delay>0</onix1:Delay>
        </onix1:ClockOutput>
        <onix1:HarpInput>
          <onix1:DeviceName>BreakoutBoard/HarpSyncInput</onix1:DeviceName>
          <onix1:DeviceAddress>12</onix1:DeviceAddress>
          <onix1:Enable>false</onix1:Enable>
          <onix1:Source>Breakout</onix1:Source>
        </onix1:HarpInput>
        <onix1:MemoryMonitor>
          <onix1:DeviceName>BreakoutBoard/MemoryMonitor</onix1:DeviceName>
          <onix1:DeviceAddress>10</onix1:DeviceAddress>
          <onix1:Enable>true</onix1:Enable>
          <onix1:SamplesPerSecond>100</onix1:SamplesPerSecond>
        </onix1:MemoryMonitor>
      </Combinator>
    </Expression>
    <Expression xsi:type="Combinator">
      <Combinator xsi:type="onix1:StartAcquisition">
        <onix1:ReadSize>2048</onix1:ReadSize>
        <onix1:WriteSize>16384</onix1:WriteSize>
      </Combinator>
    </Expression>
    <Expression xsi:type="Combinator">
      <Combinator xsi:type="onix1:LoadTesterData">
        <onix1:DeviceName>Load Tester</onix1:DeviceName>
      </Combinator>
    </Expression>
    <Expression xsi:type="MemberSelector">
      <Selector>HubClockDelta</Selector>
    </Expression>
    <Expression xsi:type="scr:ExpressionTransform">
      <scr:Name>ToMilliseconds</scr:Name>
      <scr:Expression>it/250000.0</scr:Expression>
    </Expression>
    <Expression xsi:type="Combinator">
      <Combinator xsi:type="rx:DistinctUntilChanged" />
    </Expression>
    <Expression xsi:type="Combinator">
      <Combinator xsi:type="dsp:Histogram1D">
        <dsp:Min>0</dsp:Min>
        <dsp:Max>1</dsp:Max>
        <dsp:Bins>1000</dsp:Bins>
        <dsp:Normalize>false</dsp:Normalize>
        <dsp:Accumulate>true</dsp:Accumulate>
      </Combinator>
    </Expression>
    <Expression xsi:type="MemberSelector">
      <Selector>HubClock</Selector>
    </Expression>
    <Expression xsi:type="rx:Condition">
      <Name>Every Nth</Name>
      <Workflow>
        <Nodes>
          <Expression xsi:type="WorkflowInput">
            <Name>Source1</Name>
          </Expression>
          <Expression xsi:type="Combinator">
            <Combinator xsi:type="rx:ElementIndex" />
          </Expression>
          <Expression xsi:type="MemberSelector">
            <Selector>Index</Selector>
          </Expression>
          <Expression xsi:type="ExternalizedMapping">
            <Property Name="Value" DisplayName="N" />
          </Expression>
          <Expression xsi:type="Mod">
            <Operand xsi:type="IntProperty">
              <Value>100</Value>
            </Operand>
          </Expression>
          <Expression xsi:type="Equal">
            <Operand xsi:type="IntProperty">
              <Value>0</Value>
            </Operand>
          </Expression>
          <Expression xsi:type="WorkflowOutput" />
        </Nodes>
        <Edges>
          <Edge From="0" To="1" Label="Source1" />
          <Edge From="1" To="2" Label="Source1" />
          <Edge From="2" To="4" Label="Source1" />
          <Edge From="3" To="4" Label="Source2" />
          <Edge From="4" To="5" Label="Source1" />
          <Edge From="5" To="6" Label="Source1" />
        </Edges>
      </Workflow>
    </Expression>
    <Expression xsi:type="Combinator">
      <Combinator xsi:type="onix1:LoadTesterLoopback">
        <onix1:DeviceName>Load Tester</onix1:DeviceName>
      </Combinator>
    </Expression>
    <Expression xsi:type="Combinator">
      <Combinator xsi:type="onix1:MemoryMonitorData">
        <onix1:DeviceName>BreakoutBoard/MemoryMonitor</onix1:DeviceName>
      </Combinator>
    </Expression>
    <Expression xsi:type="MemberSelector">
      <Selector>PercentUsed</Selector>
    </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="4" To="5" Label="Source1" />
    <Edge From="4" To="9" Label="Source1" />
    <Edge From="5" To="6" Label="Source1" />
    <Edge From="6" To="7" Label="Source1" />
    <Edge From="7" To="8" Label="Source1" />
    <Edge From="9" To="10" Label="Source1" />
    <Edge From="10" To="11" Label="Source1" />
    <Edge From="12" To="13" Label="Source1" />
  </Edges>
</Workflow>
</WorkflowBuilder>

- Modify the existing configuration operator since it had implementation
  issues
- Add frame reader and frame writer operators and support classes
@jonnew jonnew added this to the 0.6.1 milestone Aug 20, 2025
@jonnew jonnew requested review from aacuevas and bparks13 August 20, 2025 15:57
Copy link
Member

@bparks13 bparks13 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks good, I was able to test it using the same workflow and got a fairly similar histogram:

image

I do have one comment, not sure if it is important to check if the transmitted words is 0 but I did see in the register comments that it should be at least 2.

@jonnew
Copy link
Member Author

jonnew commented Aug 22, 2025

I need to address this issue before this is merged;

open-ephys/onix-docs#100

@jonnew
Copy link
Member Author

jonnew commented Sep 16, 2025

The datasheets are being update here: open-ephys/onix-docs#119.

Edit: this is now complete.

@jonnew jonnew removed the request for review from aacuevas September 24, 2025 22:27
@jonnew jonnew merged commit a2b1bde into main Sep 24, 2025
8 checks passed
@jonnew jonnew deleted the issue-274 branch September 24, 2025 22:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add support for load testing device

3 participants