summaryrefslogtreecommitdiff
path: root/libhw_cr/rp2040_piospi.pio
diff options
context:
space:
mode:
Diffstat (limited to 'libhw_cr/rp2040_piospi.pio')
-rw-r--r--libhw_cr/rp2040_piospi.pio41
1 files changed, 41 insertions, 0 deletions
diff --git a/libhw_cr/rp2040_piospi.pio b/libhw_cr/rp2040_piospi.pio
new file mode 100644
index 0000000..6307c9b
--- /dev/null
+++ b/libhw_cr/rp2040_piospi.pio
@@ -0,0 +1,41 @@
+;;; libhw_cr/rp2040_piospi.pio - <libhw/generic/spi.h> implementation for the RP2040's PIO
+;;;
+;;; Copyright (C) 2025 Luke T. Shumaker <lukeshu@lukeshu.com>
+;;; SPDX-License-Identifier: AGPL-3.0-or-later
+
+;;; First read a u32 bit-count, then transfer that many bits (full-duplex).
+;;;
+;;; Pin assignments:
+;;; - MOSI ; OUT pin 0
+;;; - MISO ; IN pin 0
+;;; - CLK ; SIDE pin 0
+;;; - CS ; SIDE pin 1 (low active, high idle))
+
+;;; This is all written as if clk_polarity=0 (idle low); if that is
+;;; not the case, then the clk pin can be flipped in the GPIO mux.
+
+;;; clk_phase=0 (sample on clock transition-to-active; written as "rise" here)
+;;; shift on CS fall and clock fall
+.program rp2040_piospi_mode0
+.side_set 2
+idle:
+ pull side 0b10 ; osr=(32 bits) cs=high clk=low
+ mov x osr side 0b10 ; x=osr cs=high clk=low
+active:
+ ;; 2 cycles low, 2 cycles high
+ out pins 1 side 0b00 [1] ; mosi=(1 bit) cs=low clk=low [wait=1] ; CS fall/clock fall = shift
+ in pins 1 side 0b01 ; miso=(1 bit) cs=low clk=high ; clock rise = sample
+ jmp x-- active side 0b01 ; cs=low clk=high
+
+;;; clk_phase=1 (sample on transition-to-idle
+;;; shift on clock rise
+.program rp2040_piospi_mode0
+.side_set 2
+idle:
+ pull side 0b10 ; osr=(32 bits) cs=high clk=low
+ mov x osr side 0b10 ; x=osr cs=high clk=low
+active:
+ ;; 2 cycles high, 2 cycles low
+ out pins 1 side 0b01 [1] ; mosi=(1 bit) cs=low clk=high [wait=1] ; clock rise = shift
+ in pins 1 side 0b00 ; miso=(1 bit) cs=low clk=low ; clock fall = sample
+ jmp x-- active side 0b00 ; cs=low clk=low