diff --git a/rpi_spi/2023-12-29_pi-spi-rates.md b/rpi_spi/2023-12-29_pi-spi-rates.md
index 642d6449dfcd817e8870b5bf70902096d0be1c62..da0791ce224287cd9f0a252e97ad78ec9ebfccae 100644
--- a/rpi_spi/2023-12-29_pi-spi-rates.md
+++ b/rpi_spi/2023-12-29_pi-spi-rates.md
@@ -2,9 +2,81 @@
 
 OK, SPI is looking pretty good; actual bit times are identical to what-they-should-be, so I'm not even going to note them down (whereas UART out of the PI has some drift, probably strange BAUD fractional maths). 
 
+### SPI Waveform Integrity 
+
 So, there's just the question of waveform integrity, and (probably) the ability of the RP2040 to keep up, and there's the actually-delineating-and-echoing-etc test. 
 
 I'd like to look at some scope traces first, but I should probably do it in context (i.e. actually driving a pin, not free air), so I'll setup my little test rig...
 
-- female-to-male,
-- usb-to-image-capture-on-the-scope ? 
\ No newline at end of file
+**CH1 (yellow) is Chip Select**  
+**CH2 (blue) is the Clock**  
+**CH3 (magenta) is Data Dout** 
+
+| Mbit/s | Traces |
+| --- | --- |
+| 1   | ![img](images/2023-12-29_spi-waveq-001MBit.png)   |
+| 2.5 | ![img](images/2023-12-29_spi-waveq-002p5MBit.png) |
+| 5   | ![img](images/2023-12-29_spi-waveq-005MBit.png)   |
+| 10  | ![img](images/2023-12-29_spi-waveq-010MBit.png)   |
+| 15  | ![img](images/2023-12-29_spi-waveq-015MBit.png)   |
+| 20  | ![img](images/2023-12-29_spi-waveq-020MBit.png)   |
+| 25  | ![img](images/2023-12-29_spi-waveq-025MBit.png)   |
+| 50  | ![img](images/2023-12-29_spi-waveq-050MBit.png)   |
+
+
+So the waveform basically looks like it survives all square-waved up to 5Mbit, then starts rounding off towards 10Mbit, and is probably serviceable between there and 25Mbit, where things are looking quite dicey indeed - as far as my relatively untrained eye can tell. By 100Mbit, all hope is lost.
+
+I suspect that "the move" here will be two-fold: (1) to do decent EE and line these traces with via-punched GND noise capture (to prevent the crosstalk we are seeing), and **then** to instrument each packet with some kind of CRC. 
+
+I want to point out another benefit of the SPI route, which is that (if you look at the trace from **2.5Mbit**) there is an inter-packet time of only 6 microseconds, so in our python sketch:
+
+```python
+import spidev 
+
+bitrate = 50000000
+
+print(f'rate {bitrate/1e6}MBit/s bit period should be {1000000000/bitrate}ns')
+
+spi = spidev.SpiDev()
+spi.open(0, 0)
+spi.max_speed_hz = bitrate 
+
+for i in range(1000000):
+    spi.xfer([12, 14, 95])
+
+spi.close() 
+```
+
+The time between `spi.xfer()`s is that few-microseconds of python returning to the top of the loop. If we look at similar code for UART:
+
+```python
+class CobsUsbSerial:
+    def __init__(self, port, baudrate=115200):
+        self.port = port
+        self.ser = serial.Serial(port, baudrate=baudrate, timeout=1)
+        self.buffer = bytearray()
+
+    def write(self, data: bytes):
+        data_enc = cobs.encode(data) + b"\x00"
+        self.ser.write(data_enc)
+
+    def read(self):
+        byte = self.ser.read(1)
+        if not byte:
+            return 
+        if byte == b"\x00":
+            if len(self.buffer) > 0:
+                data = cobs.decode(self.buffer)
+                self.buffer = bytearray() 
+                return data
+            else: 
+                return 
+        else:
+            self.buffer += byte 
+```
+
+We are normally pulling one byte at a time - if we want to be catching while we are transmitting. I suspect that protocol work can avoid these mechanisms, **but** the other thing we don't have to deal with in the SPI case is packet framing: the CS line does that for us, we are COBS-less. The complexity ofc is that then we need to develop protocol between top- and bottom- layers to (probably) pack datagrams into fixed size frames (or something something) I digress. 
+
+### SPI Echo Code 
+
+OK, so to see if we can get up to that 10Mbit real-transfer-rate target, I think I will start with an echo test - since SPI is transfer-based anyways (we always send data when we get it), I'll program some arduino to get packets and echo them, and we'll turn the speed up until we start making mistakes. 
\ No newline at end of file
diff --git a/rpi_spi/code/pi_spi.py b/rpi_spi/code/pi_spi.py
index fb90f52c00cc3c50a856c14c570ffcc6870ffc44..7eeb72d54f86a694d37e696e4f07b9017542d66c 100644
--- a/rpi_spi/code/pi_spi.py
+++ b/rpi_spi/code/pi_spi.py
@@ -1,10 +1,14 @@
 import spidev 
 
+bitrate = 50000000
+
+print(f'rate {bitrate/1e6}MBit/s bit period should be {1000000000/bitrate}ns')
+
 spi = spidev.SpiDev()
 spi.open(0, 0)
-spi.max_speed_hz = 12000000
+spi.max_speed_hz = bitrate 
 
-for i in range(100000):
+for i in range(1000000):
     spi.xfer([12, 14, 95])
 
 spi.close() 
\ No newline at end of file
diff --git a/rpi_spi/images/2023-12-29_spi-waveq-001MBit.png b/rpi_spi/images/2023-12-29_spi-waveq-001MBit.png
new file mode 100644
index 0000000000000000000000000000000000000000..714fd8fce682e401afbf19a8a97a49d212c6f65a
Binary files /dev/null and b/rpi_spi/images/2023-12-29_spi-waveq-001MBit.png differ
diff --git a/rpi_spi/images/2023-12-29_spi-waveq-002p5MBit.png b/rpi_spi/images/2023-12-29_spi-waveq-002p5MBit.png
new file mode 100644
index 0000000000000000000000000000000000000000..e87f77c9b7ddc91377e5b57abe3a4829f926de67
Binary files /dev/null and b/rpi_spi/images/2023-12-29_spi-waveq-002p5MBit.png differ
diff --git a/rpi_spi/images/2023-12-29_spi-waveq-005MBit.png b/rpi_spi/images/2023-12-29_spi-waveq-005MBit.png
new file mode 100644
index 0000000000000000000000000000000000000000..eee51d7a4e88ae0b5b50a1a917a666c28a09c4e4
Binary files /dev/null and b/rpi_spi/images/2023-12-29_spi-waveq-005MBit.png differ
diff --git a/rpi_spi/images/2023-12-29_spi-waveq-010MBit.png b/rpi_spi/images/2023-12-29_spi-waveq-010MBit.png
new file mode 100644
index 0000000000000000000000000000000000000000..2b3acdf2e296c15eea5f93dec7e22e9d2266b285
Binary files /dev/null and b/rpi_spi/images/2023-12-29_spi-waveq-010MBit.png differ
diff --git a/rpi_spi/images/2023-12-29_spi-waveq-015MBit.png b/rpi_spi/images/2023-12-29_spi-waveq-015MBit.png
new file mode 100644
index 0000000000000000000000000000000000000000..e4b0ddd51e74f7deab7a9b05054185914d9adf04
Binary files /dev/null and b/rpi_spi/images/2023-12-29_spi-waveq-015MBit.png differ
diff --git a/rpi_spi/images/2023-12-29_spi-waveq-020MBit.png b/rpi_spi/images/2023-12-29_spi-waveq-020MBit.png
new file mode 100644
index 0000000000000000000000000000000000000000..96c79b11bc358045dd83d71e0f80fa9c14f42979
Binary files /dev/null and b/rpi_spi/images/2023-12-29_spi-waveq-020MBit.png differ
diff --git a/rpi_spi/images/2023-12-29_spi-waveq-025MBit.png b/rpi_spi/images/2023-12-29_spi-waveq-025MBit.png
new file mode 100644
index 0000000000000000000000000000000000000000..e619af93d8bce93d6d9d44293cf995aab074ecc6
Binary files /dev/null and b/rpi_spi/images/2023-12-29_spi-waveq-025MBit.png differ
diff --git a/rpi_spi/images/2023-12-29_spi-waveq-050MBit.png b/rpi_spi/images/2023-12-29_spi-waveq-050MBit.png
new file mode 100644
index 0000000000000000000000000000000000000000..ee14879f52ad5cd9b00f26e9a7fdf5382c5f6485
Binary files /dev/null and b/rpi_spi/images/2023-12-29_spi-waveq-050MBit.png differ