Skip to content
Snippets Groups Projects
Commit 85160ad0 authored by Jake Read's avatar Jake Read
Browse files
parents f519abd7 ffc164c2
Branches
No related tags found
No related merge requests found
......@@ -82,3 +82,7 @@ We are normally pulling one byte at a time - if we want to be catching while we
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...
I'm going a bit mad with this; I can get GPIO interrupts to fire *just on a falling edge* but not *just on a rising edge* ... I should see if I can access some lower level masks, or something? But it's genuinely sending events *marked* as *rising edge* events on falling and rising edges...
There's another oddity in here... the RP2040 only uses SPI framing where the CS line is pulsed per frame (7-16 bits), so we need to handle it in software, though IDK exactly how to do this as a peripheral, though apparently [this lad](https://github.com/raspberrypi/pico-sdk/issues/88#issuecomment-1402204730) found [a workaround?](https://github.com/uwopus/pico-code/blob/3594e67c1ac34e5454eb4db8362b673bcc7c8862/opus_comms/opus_comms.c#L44-L46) which references 4.4.3.13
\ No newline at end of file
#include "screen.h"
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <Wire.h>
// 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...");
}
\ No newline at end of file
#ifndef SCREEN_H_
#define SCREEN_H_
#include <Arduino.h>
void displaySetup(void);
void displayPrint(String msg);
#endif
\ No newline at end of file
#include "spipi.h"
#include "screen.h"
// using a (basically raspberry pi pico) W5500-EVB-Pico
// with earle philhower core
void setup(void){
pinMode(LED_BUILTIN, OUTPUT);
digitalWrite(LED_BUILTIN, LOW);
// the display setup
displaySetup();
// the spi setup
spipi_begin();
}
uint32_t lastUpdate = 0;
uint32_t updateInterval = 200;
void loop(void){
if(lastUpdate + updateInterval < millis()){
lastUpdate = millis();
digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
displayPrint(spipi_print());
// displayPrint(String(rxCount) + "\n" +
// String(rxSize)
// );
}
}
\ No newline at end of file
#include "spipi.h"
#include <hardware/spi.h>
#include <hardware/gpio.h>
// the relevant functions are here:
// /jaker/AppData/Local/Arduino15/packages/rp2040/3.6.1/pico-sdk/src/ ...
// /rp2040/rp2_common/hardware_spi/include/hardware/spi.h
// the registers we're interested in here:
// /jaker/AppData/Local/Arduino15/packages/rp2040/3.6.1/pico-sdk/src/ ...
// /rp2040/hardware_structs/include/hardware/structs/spi.h
// for earle code reference,
// /jaker/AppData/Local/Arduino15/packages/rp2040/3.6.1/libraries/ ...
// /SPISlave/src/SPISlave.cpp (etc)
// for gpio,
// /jaker/AppData/Local/Arduino15/packages/rp2040/3.6.1/pico-sdk/src/ ...
// /rp2040/rp2_common/hardware_gpio/include/hardware/gpio.h
#define PIN_DEBUG 1
#define PIN_CS 13
#define PIN_SCK 10
#define PIN_RX 12
#define PIN_TX 11
#define BITRATE 1000000
#define SPI_INST spi1
#define SPI_HW spi_get_hw(SPI_INST)
#define SPI_IMSC_TXIM_ON (1 << 3)
#define SPI_IMSC_RXIM_ON (1 << 2)
#define SPI_IMSC_RTIM_ON (1 << 1)
#define SPI_IMSC_RORIM_ON (1)
// some static buffs
uint8_t rxBuffer[255];
volatile uint8_t rxPtr = 0;
String spipi_print(void){
return String(rxBuffer[0]) + ", " + String(rxBuffer[1]);
}
uint8_t txBuffer[255];
volatile uint8_t txPtr = 0;
volatile uint8_t txLen = 32;
// we catch rising edges to delineate packet-end
void spipi_gpio_irq_handler(uint gpio, uint32_t events){
if(gpio_get(PIN_CS)){
txPtr = 0;
rxPtr = 0;
// gpio_put(PIN_DEBUG, !gpio_get_out_level(PIN_DEBUG));
}
}
void spipi_irq_handler(void){
gpio_put(PIN_DEBUG, !gpio_get_out_level(PIN_DEBUG));
// both have up to 8 bytes to read / write per interrupt ?
// get bytes while readable,
for(uint8_t c = 0; c < 8; c ++){
if(spi_is_readable(SPI_INST) && rxPtr < txLen){
rxBuffer[rxPtr] = SPI_HW->dr;
rxPtr ++;
}
}
// write bytes while writable
for(uint8_t c = 0; c < 8; c ++){
if(spi_is_writable(SPI_INST) && txPtr < txLen){
SPI_HW->dr = txBuffer[txPtr];
txPtr ++;
}
}
// rx
// if we're out of data, we could turn interrupts off w/ this:
// i.e. *just* turning the RX-interrupt on... ??
// SPI_HW->imsc = 0 | SPI_IMSC_RXIM_ON;
}
void spipi_begin(void){
// dummy pin
gpio_init(PIN_DEBUG);
gpio_set_dir(PIN_DEBUG, GPIO_OUT);
// dummy buffer
for(uint8_t i = 0; i < 255; i ++){
txBuffer[i] = i;
}
// uh ?
gpio_init(PIN_CS);
gpio_set_dir(PIN_CS, GPIO_IN);
// let's actually just get the CS LOW/HI interrupt first,
// so we can reset our buffer states (etc)
gpio_set_irq_enabled_with_callback(PIN_CS, GPIO_IRQ_EDGE_RISE, true, &spipi_gpio_irq_handler);
// gpio_set_input_hysteresis_enabled(PIN_CS, false);
// startup the peripheral ?
spi_init(SPI_INST, BITRATE);
spi_set_slave(SPI_INST, true);
// spi_set_format(SPI_INST, 8, SPI_CPOL_0, SPI_CPHA_0, SPI_MSB_FIRST);
// oddity where mode 0b11 allow continuous CS_LOW ?
// that's right, folks, we can only do this with 0b11 mode, insane:
// see https://github.com/raspberrypi/pico-sdk/issues/88#issuecomment-1402204730
// and see RP2040 datasheet at 4.4.3.13 !
spi_set_format(SPI_INST, 8, SPI_CPOL_1, SPI_CPHA_1, SPI_MSB_FIRST);
// assign pins to SPI peripheral,
// gpio_set_function(PIN_CS, GPIO_FUNC_SPI);
gpio_set_function(PIN_SCK, GPIO_FUNC_SPI);
gpio_set_function(PIN_RX, GPIO_FUNC_SPI);
gpio_set_function(PIN_TX, GPIO_FUNC_SPI);
// hook up our (one?) interrupt...
// NOTE: changing SPI_INST requires hard-coded change here
SPI_HW->imsc = SPI_IMSC_RXIM_ON | SPI_IMSC_TXIM_ON;
irq_set_exclusive_handler(SPI1_IRQ, &spipi_irq_handler);
irq_set_enabled(SPI1_IRQ, true);
}
#ifndef SPI_PI_H_
#define SPI_PI_H_
#include <Arduino.h>
void spipi_begin(void);
String spipi_print(void);
#endif
\ No newline at end of file
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment