Skip to content

Commit 4f2c806

Browse files
committed
docs/rp2: Add HSTX class documentation.
Signed-off-by: Dryw Wade <dryw.wade@sparkfun.com>
1 parent c24e8ef commit 4f2c806

File tree

2 files changed

+298
-0
lines changed

2 files changed

+298
-0
lines changed

docs/library/rp2.HSTX.rst

Lines changed: 297 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,297 @@
1+
.. currentmodule:: rp2
2+
.. _rp2.HSTX:
3+
4+
class HSTX -- access to the RP2350's HSTX controller
5+
====================================================
6+
7+
The :class:`HSTX` class offers access to the RP2350's High-speed Serial Transmit (HSTX) peripheral, which can output data through up to 8 GPIO pins (only GPIO 12 through 19) at up to 150MHz, and is double-data rate (DDR) capable. This enables the HSTX to theoretically stream data up to 2.4Gbps, provided its FIFO buffer can be kept filled (it's typically necessary to use the DMA controller to achieve this). The HSTX also features a command expander, which can manipulate the data stream (the RP2350 currently only implements a TMDS encoder) and repeat data. For full details of the RP2350's HSTX system, see section 12.11 of the `RP2350 Datasheet <https://datasheets.raspberrypi.org/rp2350/rp2350-datasheet.pdf>`_.
8+
9+
Examples
10+
--------
11+
12+
A simple use of the HSTX peripheral is to blink a pair of LEDs. This can be accomplished with the following complete example::
13+
14+
import rp2
15+
import time
16+
from machine import Pin
17+
18+
# Get the singleton HSTX object.
19+
hstx = rp2.HSTX()
20+
21+
# Set GPIO pins 12 and 13 to the HSTX alternate function.
22+
pin_12 = Pin(12, mode=Pin.ALT, alt=Pin.ALT_HSTX)
23+
pin_13 = Pin(13, mode=Pin.ALT, alt=Pin.ALT_HSTX)
24+
25+
# Configure pin 12 to output bit 0 of data in the HSTX FIFO for both the first
26+
# and second (positive and negative) phases of the HSTX clock cycle, and pin 13
27+
# to output the same but inverted value.
28+
hstx.bit(pin_12, hstx.pack_bit(sel_p=0, sel_n=0))
29+
hstx.bit(pin_13, hstx.pack_bit(sel_p=0, sel_n=0, inv=1))
30+
31+
# Set up the CSR register to enable HSTX with no shifting.
32+
csr = hstx.pack_csr(
33+
shift = 0,
34+
enable = 1
35+
)
36+
hstx.csr(csr)
37+
38+
# Data can be manually pushed into the FIFO, though a DMA channel should be used
39+
# for real applications.
40+
while True:
41+
hstx.fifo_put(1)
42+
time.sleep(1)
43+
hstx.fifo_put(0)
44+
time.sleep(1)
45+
46+
It's usually more practical to use a DMA channel to feed data to the HSTX FIFO. To support this, the HSTX class supports the buffer protocol (write-only), and can be used like so::
47+
48+
import rp2
49+
import array
50+
51+
# Get the singleton HSTX object. Configuration of the HSTX is omitted from this
52+
# example for brevity.
53+
hstx = rp2.HSTX()
54+
55+
# Data to send to the HSTX FIFO.
56+
data = array.array("I", [0x01234567, 0x89ABCDEF])
57+
58+
# Data request (DREQ) signal number for the HSTX FIFO.
59+
DREQ_HSTX = 52
60+
61+
# Set up a DMA channel to feed data to the HSTX FIFO.
62+
dma = rp2.DMA()
63+
dma_ctrl = dma.pack_ctrl(
64+
inc_write = False, # Keep writing to the same HSTX FIFO address.
65+
dreq_sel = DREQ_HSTX # Pace DMA transfers by the HSTX data request signal.
66+
)
67+
dma.config(
68+
read = data,
69+
write = hstx,
70+
count = len(data),
71+
ctrl = dma_ctrl,
72+
trigger = True
73+
)
74+
75+
The command expander can be used with the TMDS encoder for driving DVI displays (HDMI displays also support this signal). The example below demonstrates the HSTX configuration, but is not a complete implementation. Special timing signals are required in addition to needing a complete frame buffer, so those are omitted here for simplicity::
76+
77+
import rp2
78+
from machine import Pin
79+
80+
# Define the GPIO pins used for each TMDS lane.
81+
pin_clk_p = 14
82+
pin_clk_n = 15
83+
pin_d0_p = 18
84+
pin_d0_n = 19
85+
pin_d1_p = 16
86+
pin_d1_n = 17
87+
pin_d2_p = 12
88+
pin_d2_n = 13
89+
90+
# Get the singleton HSTX object.
91+
hstx = rp2.HSTX()
92+
93+
# Configure the command expander's shift register. This simple example does not
94+
# actually perform any shifting, but it's possible to pack multiple pixels per
95+
# 32-bit data word, then shift the words to align the bits for the TMDS encoder
96+
# by changing the `enc_n_shifts` and `enc_shift` fields.
97+
expand_shift = hstx.pack_expand_shift(
98+
enc_n_shifts = 1,
99+
enc_shift = 0,
100+
raw_n_shifts = 1,
101+
raw_shift = 0
102+
)
103+
hstx.expand_shift(expand_shift)
104+
105+
# Configure the TMDS encoder to convert the data in the command expander's shift
106+
# register to TMDS format. This example demonstrates RGB565 pixel format, which
107+
# is assumed to be packed into the 32-bit data words as follows:
108+
#
109+
# (xxxxxxxx xxxxxxxx RRRRRGGG GGGBBBBB)
110+
#
111+
# There are 3 TMDS data lanes for DVI video (lane 0 carries the blue channel,
112+
# lane 1 carries green, and lane 2 carries red). For each lane, the bits for
113+
# that channel need to start at bit 7 (8th bit position), so each lane needs to
114+
# shift the register to get the MSB aligned using the `ln_rot` field (right
115+
# rotate, wraps around). Up to 8 bits can be used per channel, specified by the
116+
# `ln_nbits` field (values of 0-7 correspond to 1-8 bits).
117+
expand_tmds = hstx.pack_expand_tmds(
118+
l2_nbits = 4, # 5 bits (red)
119+
l2_rot = 8, # Shift right 8 bits to align MSB
120+
l1_nbits = 5, # 6 bits (green)
121+
l1_rot = 3, # Shift right 3 bits to align MSB
122+
l0_nbits = 4, # 5 bits (blue)
123+
l0_rot = 29, # Shift right 29 bits to align MSB (left 3 bits)
124+
)
125+
hstx.expand_tmds(expand_tmds)
126+
127+
# The TMDS encoder sends 30 bits of data per pixel (10 bits per lane) to the
128+
# 32-bit output shift register. The bits for lane 0, 1, and 2 are as follows:
129+
#
130+
# (xx 2222222222 1111111111 0000000000)
131+
#
132+
# The output shift register will be configured to shift the whole register by 2
133+
# bits every system clock cycle (DDR) for 5 cycles (10 bits total). So we'll
134+
# configure each lane's pins to output bits 10*n and 10*n+1 on the positive and
135+
# negative phases of the system clock, respectively.
136+
#
137+
# The clock lane outputs a continuous clock signal, so those GPIO pins just
138+
# follow the HSTX clock generator, which will be configured below.
139+
#
140+
# Each pair of pins is differential, so the `_n` pin is just the inverted value
141+
# of the `_p` pin.
142+
hstx.bit(pin_clk_p, hstx.pack_bit(clk=1, inv=0))
143+
hstx.bit(pin_clk_n, hstx.pack_bit(clk=1, inv=1))
144+
hstx.bit(pin_d0_p, hstx.pack_bit(sel_p= 0, sel_n= 1, inv=0))
145+
hstx.bit(pin_d0_n, hstx.pack_bit(sel_p= 0, sel_n= 1, inv=1))
146+
hstx.bit(pin_d1_p, hstx.pack_bit(sel_p=10, sel_n=11, inv=0))
147+
hstx.bit(pin_d1_n, hstx.pack_bit(sel_p=10, sel_n=11, inv=1))
148+
hstx.bit(pin_d2_p, hstx.pack_bit(sel_p=20, sel_n=21, inv=0))
149+
hstx.bit(pin_d2_n, hstx.pack_bit(sel_p=20, sel_n=21, inv=1))
150+
151+
# Set all HSTX pins (GPIO 12-19) to ALT function for HSTX output.
152+
for i in range(12, 20):
153+
Pin(i, mode=Pin.ALT, alt=Pin.ALT_HSTX)
154+
155+
# DVI requires the clock lane to cycle once per 10 data bits, meaning every 5
156+
# system clock cycles (DDR).
157+
#
158+
# The output shift register needs to shift by 2 bits every system clock cycle
159+
# for 5 cycles, so `shift` and `n_shifts` are set to 2 and 5, respectively.
160+
#
161+
# Then we enable the command expander to activate the TMDS encoder, and enable
162+
# the HSTX peripheral.
163+
csr = hstx.pack_csr(
164+
clk_div = 5,
165+
n_shifts = 5,
166+
shift = 2,
167+
expand_enable = 1,
168+
enable = 1
169+
)
170+
hstx.csr(csr)
171+
172+
Constructor
173+
-----------
174+
175+
.. class:: HSTX()
176+
177+
Gets the singleton object for accessing the HSTX peripheral.
178+
179+
Methods
180+
-------
181+
182+
.. method:: HSTX.csr([value])
183+
184+
Gets or sets the HSTX control and status register (CSR) *value*. This is an integer value that is typically packed using :meth:`HSTX.pack_csr()`.
185+
186+
.. method:: HSTX.bit(pin, [value])
187+
188+
Gets or sets the bit register *value* for the given *pin* (only GPIO 12 to 19, can be a `machine.Pin()` or integer). This is an integer value that is typically packed using :meth:`HSTX.pack_bit()`.
189+
190+
.. method:: HSTX.expand_shift([value])
191+
192+
Gets or sets the command expander's shift register *value*. This is an integer value that is typically packed using :meth:`HSTX.pack_expand_shift()`.
193+
194+
.. method:: HSTX.expand_tmds([value])
195+
196+
Gets or sets the command expander's TMDS encoder register *value*. This is an integer value that is typically packed using :meth:`HSTX.pack_expand_tmds()`.
197+
198+
.. method:: HSTX.pack_csr(**kwargs)
199+
200+
Pack the values provided in the keyword arguments into the named fields of a new control register value. Any field that is not provided will be set to a default value.
201+
202+
The keys for the keyword arguments can be any key returned by :meth:`HSTX.unpack_csr()`. The writable values are:
203+
204+
- *enable*: ``bool`` Enable the HSTX peripheral (default: ``False``).
205+
206+
- *expand_enable*: ``bool`` Enable the command expander (default: ``False``).
207+
208+
- *coupled_mode*: ``bool`` Enable the PIO-to_HSTX connection (default: ``False``).
209+
210+
- *coupled_select*: ``int`` Select which PIO instance to couple to (0-2, default: ``0``).
211+
212+
- *shift*: ``int`` Number of bits to right-rotate the output shift register by each cycle (0-31, default: ``6``).
213+
214+
- *n_shifts*: ``int`` Number of shifts to perform before reloading the shift register (0-31, with 0 meaning shift 32 times, default: ``5``).
215+
216+
- *clk_phase*: ``int`` Initial phase of the generated HSTX clock (0-15, default: ``0``).
217+
218+
- *clk_div*: ``int`` Clock perid of the generated HSTX clock, in system clock cycles (0-15, with 0 meaning *clk_div* of 16, default: ``1``).
219+
220+
.. method:: HSTX.pack_bit(**kwargs)
221+
222+
Pack the values provided in the keyword arguments into the named fields of a new control register value. Any field that is not provided will be set to a default value.
223+
224+
The keys for the keyword arguments can be any key returned by :meth:`HSTX.unpack_bit()`. The writable values are:
225+
226+
- *sel_p*: ``int`` Data bit to output for the first half (positive phase) of the HSTX clock cycle (0-31, default: ``0``).
227+
228+
- *sel_n*: ``int`` Data bit to output for the second half (negative phase) of the HSTX clock cycle (0-31, default: ``0``).
229+
230+
- *inv*: ``bool`` Invert the output value (default: ``False``).
231+
232+
- *clk*: ``bool`` Output the generated clock instead of a data bit (default: ``False``).
233+
234+
.. method:: HSTX.pack_expand_shift(**kwargs)
235+
236+
Pack the values provided in the keyword arguments into the named fields of a new control register value. Any field that is not provided will be set to a default value.
237+
238+
The keys for the keyword arguments can be any key returned by :meth:`HSTX.unpack_expand_shift()`. The writable values are:
239+
240+
- *raw_shift*: ``int`` Number of bits to right-rotate the command expander's shift register by each shift when using the raw data command (0-31, default: ``0``).
241+
242+
- *raw_n_shifts*: ``int`` Number of shifts to perform when using the raw data command before reloading the shift register (0-31, with 0 meaning shift 32 times, default: ``1``).
243+
244+
- *enc_shift*: ``int`` Number of bits to right-rotate the command expander's shift register by each shift when using an encoder (eg. TMDS) command (0-31, default: ``0``).
245+
246+
- *enc_n_shifts*: ``int`` Number of shifts to perform when using an encoder (eg. TMDS) command before reloading the shift register (0-31, with 0 meaning shift 32 times, default: ``1``).
247+
248+
.. method:: HSTX.pack_expand_tmds(**kwargs)
249+
250+
Pack the values provided in the keyword arguments into the named fields of a new control register value. Any field that is not provided will be set to a default value.
251+
252+
The keys for the keyword arguments can be any key returned by :meth:`HSTX.unpack_expand_tmds()`. The writable values are:
253+
254+
- *l0_rot*: ``int`` Number of bits to right-rotate the command expander's shift register to align the MSB for lane 0 (0-31, default: ``0``).
255+
256+
- *l0_nbits*: ``int`` Number of bits to use for lane 0 (0-7, corresponding to 1-8 bits, default: ``0``).
257+
258+
- *l1_rot*: ``int`` Number of bits to right-rotate the command expander's shift register to align the MSB for lane 1 (0-31, default: ``0``).
259+
260+
- *l1_nbits*: ``int`` Number of bits to use for lane 1 (0-7, corresponding to 1-8 bits, default: ``0``).
261+
262+
- *l2_rot*: ``int`` Number of bits to right-rotate the command expander's shift register to align the MSB for lane 2 (0-31, default: ``0``).
263+
264+
- *l2_nbits*: ``int`` Number of bits to use for lane 2 (0-7, corresponding to 1-8 bits, default: ``0``).
265+
266+
.. method:: HSTX.unpack_csr(value)
267+
268+
Unpack the control and status register (CSR) *value* into a dictionary with key/value pairs for each of the fields in the register. This method will return values for all the keys that can be passed to ``HSTX.pack_csr``.
269+
270+
.. method:: HSTX.unpack_bit(value)
271+
272+
Unpack the bit register *value* for a given pin into a dictionary with key/value pairs for each of the fields in the register. This method will return values for all the keys that can be passed to ``HSTX.pack_bit()``.
273+
274+
.. method:: HSTX.unpack_expand_shift(value)
275+
276+
Unpack the command expander's shift register *value* into a dictionary with key/value pairs for each of the fields in the register. This method will return values for all the keys that can be passed to ``HSTX.pack_expand_shift()``.
277+
278+
.. method:: HSTX.unpack_expand_tmds(value)
279+
280+
Unpack the command expander's TMDS encoder register *value* into a dictionary with key/value pairs for each of the fields in the register. This method will return values for all the keys that can be passed to ``HSTX.pack_expand_tmds()``.
281+
282+
.. method:: HSTX.fifo_put(value)
283+
284+
Push a word into the HSTX FIFO.
285+
286+
.. method:: HSTX.fifo_level()
287+
288+
Get the current number of words in the HSTX FIFO.
289+
290+
.. method:: HSTX.fifo_wof([value])
291+
292+
Get or clear the HSTX FIFO write overflow flag. If *value* is provided, the flag is cleared regardless of the value.
293+
294+
Buffer protocol
295+
---------------
296+
297+
The HSTX class supports the `buffer protocol`, allowing direct access to the HSTX FIFO, which is write-only. This is primarily in order to allow the HSTX object to be passed directly as the write parameter when configuring a `rp2.DMA()` channel.

docs/library/rp2.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,5 +245,6 @@ Classes
245245

246246
rp2.DMA.rst
247247
rp2.Flash.rst
248+
rp2.HSTX.rst
248249
rp2.PIO.rst
249250
rp2.StateMachine.rst

0 commit comments

Comments
 (0)