From f0f3da7fa6e26d440c8fa580cdb55a823d1e45e2 Mon Sep 17 00:00:00 2001
From: Jake Read <jake.read@cba.mit.edu>
Date: Fri, 29 Dec 2023 19:26:17 -0500
Subject: [PATCH] earle core spi implementation is whack, we r finna go
 baremetal spi

---
 .gitignore                                    |   3 +-
 rpi_spi/2023-12-29_pi-spi-rates.md            |   4 +-
 rpi_spi/code/pi_spi.py                        |  14 --
 rpi_spi/code/spi_controller/pi_spi.py         |  22 +++
 .../spi_peripheral_earle.ino                  | 125 ++++++++++++++++++
 5 files changed, 152 insertions(+), 16 deletions(-)
 delete mode 100644 rpi_spi/code/pi_spi.py
 create mode 100644 rpi_spi/code/spi_controller/pi_spi.py
 create mode 100644 rpi_spi/code/spi_peripheral_earle/spi_peripheral_earle.ino

diff --git a/.gitignore b/.gitignore
index 6545774..cf62d77 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,3 @@
 *__pycache__
-*.vscode
\ No newline at end of file
+*.vscode
+*build
\ No newline at end of file
diff --git a/rpi_spi/2023-12-29_pi-spi-rates.md b/rpi_spi/2023-12-29_pi-spi-rates.md
index da0791c..b4114ad 100644
--- a/rpi_spi/2023-12-29_pi-spi-rates.md
+++ b/rpi_spi/2023-12-29_pi-spi-rates.md
@@ -79,4 +79,6 @@ We are normally pulling one byte at a time - if we want to be catching while we
 
 ### 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
+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. 
+
+I have hello-worlded this with the Earle Core, but their SPI implementation is strange - since it's simple enough (I'm starting to see that... that's the pint), I'll just roll my own... listening to CS down / up interrupts to frame packets, stuffing buffers, you know the dealio. It's 730pm here but that's just time to put the embedded hardo hat on... 
\ No newline at end of file
diff --git a/rpi_spi/code/pi_spi.py b/rpi_spi/code/pi_spi.py
deleted file mode 100644
index 7eeb72d..0000000
--- a/rpi_spi/code/pi_spi.py
+++ /dev/null
@@ -1,14 +0,0 @@
-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() 
\ No newline at end of file
diff --git a/rpi_spi/code/spi_controller/pi_spi.py b/rpi_spi/code/spi_controller/pi_spi.py
new file mode 100644
index 0000000..78ec483
--- /dev/null
+++ b/rpi_spi/code/spi_controller/pi_spi.py
@@ -0,0 +1,22 @@
+import spidev 
+
+bitrate = 1000000
+
+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 
+spi.mode = 0b00
+
+test_pck = bytearray(32)
+for b in range(len(test_pck)):
+  test_pck[b] = b 
+
+print(test_pck)
+
+for i in range(1000):
+  ret = spi.xfer(test_pck)
+  print(ret)
+
+spi.close() 
\ No newline at end of file
diff --git a/rpi_spi/code/spi_peripheral_earle/spi_peripheral_earle.ino b/rpi_spi/code/spi_peripheral_earle/spi_peripheral_earle.ino
new file mode 100644
index 0000000..3b2252a
--- /dev/null
+++ b/rpi_spi/code/spi_peripheral_earle/spi_peripheral_earle.ino
@@ -0,0 +1,125 @@
+#include <SPI.h>
+#include <SPISlave.h>
+#include <Adafruit_GFX.h>
+#include <Adafruit_SSD1306.h>
+#include <Wire.h>
+
+// WARNING
+/*
+this basically doesn't work: Earle Core treats SPI transfers 
+like UART, i.e. it does minimal listening to CS pin to delineate packets
+oddball stuff, I'm set to write it barebones... 
+*/
+
+#define PIN_DEBUG 0
+
+
+// OLED 
+#define SCREEN_WIDTH 128 // OLED display width, in pixels
+#define SCREEN_HEIGHT 64 // OLED display height, in pixels
+
+#define X_POS 0
+#define Y_POS 0
+#define TXT_SIZE 1
+
+// even for displays with i.e. "0x78" printed on the back, 
+// the address that works is 0x3C, IDK 
+#define SCREEN_ADDRESS 0x3C
+
+Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire1);
+
+// warning: is blocking, takes ~ 33ms ! 
+void displayPrint(String msg){
+  display.clearDisplay();
+  display.setCursor(X_POS, Y_POS);
+  display.print(msg);
+  display.display();
+}
+
+void displaySetup(void){
+  Wire1.setSDA(2);
+  Wire1.setSCL(3);
+
+  // initialize the screen,
+  // oddly, SWITCHCAPVCC is the option that works even though OLED is hooked to 5V 
+  display.begin(SSD1306_SWITCHCAPVCC, SCREEN_ADDRESS);
+  display.clearDisplay();
+  display.display();
+  display.setTextColor(SSD1306_WHITE);
+  display.setTextSize(TXT_SIZE);
+  display.setTextWrap(true);
+  display.dim(false);
+  displayPrint("bonjour...");
+}
+
+
+// SPI 
+SPISettings settings(1000000, MSBFIRST, SPI_MODE0);
+
+uint8_t txBuffer[1024];
+volatile uint32_t rxCount = 0;
+volatile uint32_t rxSize = 0;
+
+// fires when we get data, I presume ?
+// byte rxBuffer[1024];
+// this *is unrelated to the CS pin* but should be ! 
+// it actually fires basically every data chunk... 
+void onRx(uint8_t* data, size_t len){
+  // actually, for the echo we can copy 
+  // directly across, non ? 
+  // digitalWrite(PIN_DEBUG, HIGH);
+  // memcpy(txBuffer, data, len);
+  rxCount ++;
+  if(len > rxSize) rxSize = len;
+
+  // shifty shifty 
+  // digitalWrite(PIN_DEBUG, LOW);
+}
+
+// fires at the end of a transaction ?
+void onTxComplete(void){
+  SPISlave1.setData((uint8_t*)txBuffer, 32);
+  digitalWrite(PIN_DEBUG, !digitalRead(PIN_DEBUG));
+}
+
+void setup(void){
+  // a debug light and pin, 
+  pinMode(PIN_DEBUG, OUTPUT);
+  digitalWrite(PIN_DEBUG, LOW);
+
+  pinMode(LED_BUILTIN, OUTPUT);
+  digitalWrite(LED_BUILTIN, LOW);
+
+  // the display setup 
+  displaySetup();
+
+  // fill our demo buffer 
+  for(uint16_t i = 0; i < 1024; i ++){
+    txBuffer[i] = i;
+  }
+  SPISlave1.setData((uint8_t*)txBuffer, 32);
+
+  // pin config (2040 GPIO Nums)
+  SPISlave1.setCS(13);
+  SPISlave1.setSCK(10);
+  SPISlave1.setRX(12);
+  SPISlave1.setTX(11);
+
+  // callbacks 
+  SPISlave1.onDataRecv(onRx);
+  SPISlave1.onDataSent(onTxComplete);
+
+  // startup 
+  SPISlave1.begin(settings);
+}
+
+uint32_t lastUpdate = 0;
+uint32_t updateInterval = 200;
+
+void loop(void){
+  if(lastUpdate + updateInterval < millis()){
+    lastUpdate = millis();
+    digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
+    displayPrint(String(rxCount) + "\n" + String(rxSize));
+  }
+}
\ No newline at end of file
-- 
GitLab