diff --git a/.gitignore b/.gitignore index 65457741e999dfb093e76c69602fd2c7e01169ad..cf62d77a0daeb9c4e532d99a0416efb1a8e430bb 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 da0791ce224287cd9f0a252e97ad78ec9ebfccae..b4114ad6b840ce87ba71df1cd4754e447e9921b8 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 7eeb72d54f86a694d37e696e4f07b9017542d66c..0000000000000000000000000000000000000000 --- 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 0000000000000000000000000000000000000000..78ec48311f6b1d860c9be580dfe28ef43c66eeb3 --- /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 0000000000000000000000000000000000000000..3b2252a93ea2e59e460f94bb63218ba4d9ca5215 --- /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