Skip to content

Commit 5e71c14

Browse files
authored
Merge pull request #115 from dihm/prawn_do
PrawnDO
2 parents 8b3b5ae + 41c23b2 commit 5e71c14

File tree

10 files changed

+1076
-1
lines changed

10 files changed

+1076
-1
lines changed

Diff for: README.md

+1
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ The following devices have been implemented in the _labscript suite_:<sup>†</s
4848
* [OpalKelly XEM3001](https://opalkelly.com/products/xem3001/) FPGA Boards used by the Cicero control system (PR [#50](https://bitbucket-archive.labscriptsuite.org/#!/labscript_suite/labscript_devices/pull-requests/50))
4949
* [PineBlaster](http://labscriptsuite.org/hardware/pineblaster) Open-source Digital Pattern Generator
5050
* [PrawnBlaster](https://github.com/labscript-suite/prawnblaster/) Open-source pseudoclock based on the $4 Raspberry Pi Pico
51+
* [PrawnDO](https://github.com/labscript-suite/prawn_digital_output/) Open-source digital pulse generator based on the $4 Raspberry Pi Pico
5152
* [SpinCore](https://www.spincore.com/products/#pulsegeneration) Programmable Pulse Generators and Direct Digital Synthesis
5253
* [PulseBlasterDDS-II-300-AWG](http://www.spincore.com/products/PulseBlasterDDS-II-300/)
5354
* [PulseBlasterESR-PRO](https://www.spincore.com/products/PulseBlasterESR-PRO/)

Diff for: docs/source/devices.rst

+1
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ Many pseudoclock devices also include other types of outputs, including digital
1919
devices/opalkellyXEM3001
2020
devices/pineblaster
2121
devices/prawnblaster
22+
devices/prawndo
2223
devices/rfblaster
2324

2425
NI DAQS

Diff for: docs/source/devices/prawnblaster.rst

+13-1
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@ PrawnBlaster
22
============
33

44
This labscript device controls the `PrawnBlaster <https://github.com/labscript-suite/PrawnBlaster>`_ open-source digital pattern generator based on the `Raspberry Pi Pico <https://www.raspberrypi.org/documentation/rp2040/getting-started/>`_ platform.
5+
It is designed to produce pseudoclock timing pulses.
6+
See the companion :doc:`PrawnDO <prawndo>` device for arbitary pulse generation.
57

68
Specifications
79
~~~~~~~~~~~~~~
@@ -30,7 +32,7 @@ The PrawnBlaster takes advantage of the specs of the Pico to provide the followi
3032
Installation
3133
~~~~~~~~~~~~
3234

33-
In order to turn the standard Pico into a PrawnBlaster, you need to load the custom firmware available in the `Github repo <https://github.com/labscript-suite/PrawnBlaster/tree/master/build/prawnblaster>`_ onto the board.
35+
In order to turn the standard Pico into a PrawnBlaster, you need to load the custom firmware available in the `Github repo <https://github.com/labscript-suite/PrawnBlaster/releases>`_ onto the board.
3436
The simplest way to do this is by holding the reset button on the board while plugging the USB into a computer.
3537
This will bring up a mounted folder that you copy-paste the firmware to. Once copied, the board will reset and be ready to go.
3638

@@ -79,6 +81,16 @@ An example connection table that uses the PrawnBlaster:
7981
8082
stop(1)
8183
84+
Input/Output Buffers
85+
--------------------
86+
87+
While the PrawnBlaster and PrawnDO boards can be used as is,
88+
it is often a good idea to add unity-gain channel buffers to the inputs and outputs.
89+
Using buffers and line drivers from a LVCMOS family with 5V/TTL tolerant inputs can provide
90+
compatibility with TTL inputs and drive higher capacitance loads (such a long BNC cables) more reliably.
91+
Examples that implement these buffers can be found `here <https://github.com/TU-Darmstadt-APQ/Prawnblaster_Breakout>`_
92+
and `here <https://github.com/QTC-UMD/PrawnBlaster_Breakout_Connectorized>`_.
93+
8294

8395
Detailed Documentation
8496
~~~~~~~~~~~~~~~~~~~~~~

Diff for: docs/source/devices/prawndo.rst

+210
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,210 @@
1+
PrawnDO
2+
=======
3+
4+
This labscript device controls the `PrawnDO <https://github.com/labscript-suite/prawn_digital_output>`_
5+
open-source digital output generator based on the
6+
`Raspberry Pi Pico <https://www.raspberrypi.org/documentation/rp2040/getting-started/>`_ platform.
7+
It is designed to be a companion device to the :doc:`PrawnBlaster <prawnblaster>` allowing for
8+
arbitrary digital output specification (in contrast to the variable pseudoclock generation of the PrawnBlaster).
9+
10+
Initial code development was in this `repository <https://github.com/pmiller2022/prawn_digital_output_labscript>`_.
11+
12+
Specifications
13+
~~~~~~~~~~~~~~
14+
15+
The PrawnDO takes advantage of the specs of the Pico to provide the following:
16+
17+
* 16 synchronous digital outputs with timing specs equivalent to the PrawnBlaster
18+
19+
- Timing resolution for an update is 1 clock cycle (10 ns at default 100 MHz clock)
20+
- Minimum time between updates (on any output) is 5 clock cycles (50 ns with 100 MHz clock)
21+
- Maximum time between updates (on any output) is 2^32-1 clock cycles (~42.9 s with 100 MHz clock)
22+
- Updates are internally timed (ie only initial triggering is needed, not for every update)
23+
24+
* 30,000 instructions (where each instruction can be held between 5 and 2^32-1 clock cycles)
25+
* Support for external hardware triggers to begin and re-start execution after a wait.
26+
* Can be referenced to an external LVCMOS clock
27+
* Internal clock can be set up to 133 MHz (which scales timing specs accordingly)
28+
29+
30+
Installation
31+
~~~~~~~~~~~~
32+
33+
In order to turn the standard Pico into a PrawnDO, you need to load the custom firmware
34+
available in the `Github repo <https://github.com/labscript-suite/prawn_digital_output/releases>`_ onto the board.
35+
The simplest way to do this is by holding the reset button on the board while plugging the USB into a computer.
36+
This will bring up a mounted folder that you copy-paste the firmware to.
37+
Once copied, the board will reset and be ready to go.
38+
39+
Note that this device communicates using a virtual COM port.
40+
The number is assigned by the controlling computer and will need to be determined in order for BLACS to connect to the PrawnDO.
41+
42+
43+
Usage
44+
~~~~~
45+
46+
The pinout for the PrawnDO is as follows:
47+
48+
* Outputs 0-15: GPIO pins 0-15, respectively.
49+
* External Trigger input: GPIO 16
50+
* External Clock input: GPIO 20
51+
52+
Note that signal cables should be connected to the Pico digital grounds for proper operation.
53+
54+
The PrawnDO can provide up to 16 digital outputs, which are accessed via `name.outputs`.
55+
Each channel is specified using with a string of the form `'doD'`, where `'D'` is the GPIO number
56+
(i.e. `'do10'`, is the specification for GPIO 10 of the PrawnDO).
57+
58+
An example connection table that uses the PrawnBlaster and PrawnDO:
59+
60+
.. code-block:: python
61+
62+
from labscript import *
63+
64+
from labscript_devices.PrawnBlaster.labscript_devices import PrawnBlaster
65+
from labscript_devices.PrawnDO.labscript_devices import PrawnDO
66+
67+
PrawnBlaster(name='prawn', com_port='COM6', num_pseudoclocks=1)
68+
69+
PrawnDO(name='prawn_do', com_port='COM5', clock_line=prawn.clocklines[0])
70+
71+
DigitalOut('do0', prawn_do.outputs, 'do0')
72+
DigitalOut('do1', prawn_do.outputs, 'do1')
73+
DigitalOut('do12', prawn_do.outputs, 'do12')
74+
75+
if __name__ == "__main__":
76+
77+
start()
78+
79+
stop(1)
80+
81+
.. note::
82+
83+
The PrawnDO is designed to be directly connected to a Clockline,
84+
something not normally done for internally-timed devices in labscript.
85+
This is merely for simplicity under the most typical use case of
86+
adding standard digital output capability to a PrawnBlaster master pseudoclocking device.
87+
88+
When used in this way, the PrawnDO can share the Clockline with other devices,
89+
especially with other PrawnDO boards allowing for significant fan-out.
90+
Nominally, the PrawnDO will ignore clock ticks from other devices on the same Clockline,
91+
such as a DAQ.
92+
However, standard cautions should be taken when sharing a clockline between devices
93+
(i.e. don't overload the physical output driver with too many parallel devices,
94+
limit the number of devices doing fast things at nearly the same times,
95+
validate critical timings/operations independently).
96+
97+
The PrawnDO can also be triggerd from a standard DigitalOut Trigger.
98+
In this case, the `clock_line` argument is not used,
99+
but the standard `trigger_device` and `trigger_connection` arguments.
100+
101+
Synchronization
102+
---------------
103+
104+
The PrawnDO generates output based on internal timing with external starting triggers
105+
in a manner nearly equivalent to the PrawnBlaster.
106+
This means that under a typical use case of a PrawnBlaster used with a PrawnDO,
107+
the output timings of the devices will drift as their internal clocks drift.
108+
Each Pico is specified to have a clock with better than 50 ppm stability,
109+
meaning drift could be as bad as 100 ppm between two devices
110+
(e.g. 100 microsecond drift after 1 second of run time).
111+
In practice, relative drift is often around 5 ppm.
112+
113+
To overcome this, either use labscript waits right before time-sensitive operations
114+
to resynchronize back to within a single clock cycle (:math:`\pm10` ns),
115+
or use a common external clock for both devices.
116+
117+
Unless buffering/level protecting circuitry is used,
118+
both the PrawnBlaster and the PrawnDO require LVCMOS square-wave clock signals.
119+
An example evaluation board with a flexible, multi-channel LVCMOS clock generator is
120+
the SI535X-B20QFN-EVB.
121+
Note that interrupting the external clock can cause the Pico serial communication to freeze.
122+
Recovery requires resetting the board via a power cycle or shorting the RUN pin to ground
123+
to re-enable default options including the internal clock.
124+
125+
An example connection table using external clocks with the default frequency of 100 MHz is:
126+
127+
.. code-block:: python
128+
129+
from labscript import *
130+
131+
from labscript_devices.PrawnBlaster.labscript_devices import PrawnBlaster
132+
from labscript_devices.PrawnDO.labscript_devices import PrawnDO
133+
134+
PrawnBlaster(name='prawn', com_port='COM6', num_pseudoclocks=1,
135+
external_clock_pin=20)
136+
137+
PrawnDO(name='prawn_do', com_port='COM5', clock_line=prawn.clocklines[0],
138+
external_clock=True)
139+
140+
DigitalOut('do0', prawn_do.outputs, 'do0')
141+
DigitalOut('do1', prawn_do.outputs, 'do1')
142+
DigitalOut('do12', prawn_do.outputs, 'do12')
143+
144+
if __name__ == "__main__":
145+
146+
start()
147+
148+
stop(1)
149+
150+
151+
Input/Output Buffers
152+
--------------------
153+
154+
While the PrawnBlaster and PrawnDO boards can be used as is,
155+
it is often a good idea to add unity-gain channel buffers to the inputs and outputs.
156+
Using buffers and line drivers from a LVCMOS family with 5V/TTL tolerant inputs can provide
157+
compatibility with TTL inputs and drive higher capacitance loads (such a long BNC cables) more reliably.
158+
An example that implements these buffers can be found `here <https://github.com/QTC-UMD/PrawnDO_Breakout_Connectorized>`_.
159+
160+
Waits
161+
-----
162+
163+
All waits in the PrawnDO are indefinite waits in the parlance of the PrawnBlaster.
164+
This means they will never time out, but must have an external trigger to restart execution.
165+
Changing a digital output state concurrently with a wait
166+
results in the PrawnDO output holding the updated value during the wait.
167+
For example, in the following code snippet, the output of `do0` will be low during the wait.
168+
For the output of `do0` to remain high during the wait,
169+
the second instruction (`do0.go_low(t)`) must be at least 5 clock cycles after the wait start time.
170+
171+
.. code-block:: python
172+
173+
t = 0
174+
do0.go_high(t)
175+
t = 1e-3
176+
wait('my_wait', t)
177+
do0.go_low(t)
178+
179+
Detailed Documentation
180+
~~~~~~~~~~~~~~~~~~~~~~
181+
182+
.. automodule:: labscript_devices.PrawnDO
183+
:members:
184+
:undoc-members:
185+
:show-inheritance:
186+
:private-members:
187+
188+
.. automodule:: labscript_devices.PrawnDO.labscript_devices
189+
:members:
190+
:undoc-members:
191+
:show-inheritance:
192+
:private-members:
193+
194+
.. automodule:: labscript_devices.PrawnDO.blacs_tabs
195+
:members:
196+
:undoc-members:
197+
:show-inheritance:
198+
:private-members:
199+
200+
.. automodule:: labscript_devices.PrawnDO.blacs_workers
201+
:members:
202+
:undoc-members:
203+
:show-inheritance:
204+
:private-members:
205+
206+
.. automodule:: labscript_devices.PrawnDO.runviewer_parsers
207+
:members:
208+
:undoc-members:
209+
:show-inheritance:
210+
:private-members:

Diff for: labscript_devices/PrawnDO/__init__.py

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
#####################################################################
2+
# #
3+
# /labscript_devices/PrawnDO/__init__.py #
4+
# #
5+
# Copyright 2023, Philip Starkey, Carter Turnbaugh, Patrick Miller #
6+
# #
7+
# This file is part of labscript_devices, in the labscript suite #
8+
# (see http://labscriptsuite.org), and is licensed under the #
9+
# Simplified BSD License. See the license.txt file in the root of #
10+
# the project for the full license. #
11+
# #
12+
#####################################################################

Diff for: labscript_devices/PrawnDO/blacs_tabs.py

+50
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
#####################################################################
2+
# #
3+
# /labscript_devices/PrawnDO/blacs_tabs.py #
4+
# #
5+
# Copyright 2023, Philip Starkey, Carter Turnbaugh, Patrick Miller #
6+
# #
7+
# This file is part of labscript_devices, in the labscript suite #
8+
# (see http://labscriptsuite.org), and is licensed under the #
9+
# Simplified BSD License. See the license.txt file in the root of #
10+
# the project for the full license. #
11+
# #
12+
#####################################################################
13+
from blacs.device_base_class import DeviceTab
14+
15+
class PrawnDOTab(DeviceTab):
16+
def initialise_GUI(self):
17+
do_prop = {}
18+
for i in range(0, 16):
19+
do_prop['do{:01d}'.format(i)] = {}
20+
self.create_digital_outputs(do_prop)
21+
22+
def sort(channel):
23+
return int(channel.split('do')[-1])
24+
25+
_, _, do_widgets = self.auto_create_widgets()
26+
self.auto_place_widgets(('Digital Outputs', do_widgets, sort))
27+
28+
device = self.settings['connection_table'].find_by_name(self.device_name)
29+
30+
self.com_port = device.properties['com_port']
31+
32+
self.supports_remote_value_check(True)
33+
self.supports_smart_programming(True)
34+
35+
36+
def get_child_from_connection_table(self, parent_device_name, port):
37+
# all child direct outputs are actually connected to the internal device _PrawnDigitalOutputs
38+
# so we must look under that device for the port
39+
return self.connection_table.find_child(f'{self.device_name:s}__pod', port)
40+
41+
42+
def initialise_workers(self):
43+
self.create_worker(
44+
"main_worker",
45+
"labscript_devices.PrawnDO.blacs_workers.PrawnDOWorker",
46+
{
47+
'com_port': self.com_port,
48+
},
49+
)
50+
self.primary_worker = "main_worker"

0 commit comments

Comments
 (0)