From 0b1dbbd0e4b7ea468002c4d6dd8ab21550d2bf7f Mon Sep 17 00:00:00 2001 From: lady ada Date: Sat, 18 Jul 2020 14:18:07 -0400 Subject: [PATCH] add fast software spi --- Adafruit_SPIDevice.cpp | 93 ++++++++++++++++++++++++++++++++++++------ Adafruit_SPIDevice.h | 25 ++++++++++++ 2 files changed, 105 insertions(+), 13 deletions(-) diff --git a/Adafruit_SPIDevice.cpp b/Adafruit_SPIDevice.cpp index 02c1b4e..cb26b24 100644 --- a/Adafruit_SPIDevice.cpp +++ b/Adafruit_SPIDevice.cpp @@ -46,6 +46,22 @@ Adafruit_SPIDevice::Adafruit_SPIDevice(int8_t cspin, int8_t sckpin, _sck = sckpin; _miso = misopin; _mosi = mosipin; + +#ifdef BUSIO_USE_FAST_PINIO + csPort = (BusIO_PortReg *)portOutputRegister(digitalPinToPort(cspin)); + csPinMask = digitalPinToBitMask(cspin); + if (mosipin != -1) { + mosiPort = (BusIO_PortReg *)portOutputRegister(digitalPinToPort(mosipin)); + mosiPinMask = digitalPinToBitMask(mosipin); + } + if (misopin != -1) { + misoPort = (BusIO_PortReg *)portInputRegister(digitalPinToPort(misopin)); + misoPinMask = digitalPinToBitMask(misopin); + } + clkPort = (BusIO_PortReg *)portOutputRegister(digitalPinToPort(sckpin)); + clkPinMask = digitalPinToBitMask(sckpin); +#endif + _freq = freq; _dataOrder = dataOrder; _dataMode = dataMode; @@ -125,38 +141,89 @@ void Adafruit_SPIDevice::transfer(uint8_t *buffer, size_t len) { reply <<= 1; if (_dataMode == SPI_MODE0 || _dataMode == SPI_MODE2) { if (_mosi != -1) { +#ifdef BUSIO_USE_FAST_PINIO digitalWrite(_mosi, send & (1 << b)); +#else + if (send & (1 << b)) + *mosiPort |= mosiPinMask; + else + *mosiPort &= ~mosiPinMask; +#endif } + +#ifdef BUSIO_USE_FAST_PINIO + *clkPort |= clkPinMask; // Clock high +#else digitalWrite(_sck, HIGH); - if ((_miso != -1) && digitalRead(_miso)) { - reply |= 1; +#endif + + if (_miso != -1) { +#ifdef BUSIO_USE_FAST_PINIO + if (*misoPort & misoPinMask) { +#else + if (digitalRead(_miso)) { +#endif + reply |= 1; + } } + +#ifdef BUSIO_USE_FAST_PINIO + *clkPort &= ~clkPinMask; // Clock low +#else digitalWrite(_sck, LOW); +#endif } if (_dataMode == SPI_MODE1 || _dataMode == SPI_MODE3) { + +#ifdef BUSIO_USE_FAST_PINIO + *clkPort |= clkPinMask; // Clock high +#else digitalWrite(_sck, HIGH); +#endif + if (_mosi != -1) { +#ifdef BUSIO_USE_FAST_PINIO digitalWrite(_mosi, send & (1 << b)); +#else + if (send & (1 << b)) + *mosiPort |= mosiPinMask; + else + *mosiPort &= ~mosiPinMask; +#endif } + +#ifdef BUSIO_USE_FAST_PINIO + *clkPort &= ~clkPinMask; // Clock low +#else digitalWrite(_sck, LOW); - if ((_miso != -1) && digitalRead(_miso)) { - reply |= 1; +#endif + + if (_miso != -1) { +#ifdef BUSIO_USE_FAST_PINIO + if (*misoPort & misoPinMask) { +#else + if (digitalRead(_miso)) { +#endif + reply |= 1; + } } } } // Serial.print(" : 0x"); Serial.print(reply, HEX); - if (_dataOrder == SPI_BITORDER_LSBFIRST) { - // LSB is rare, if it happens we'll just flip the bits around for them - uint8_t temp = 0; - for (uint8_t b = 0; b < 8; b++) { - temp |= ((reply >> b) & 0x1) << (7 - b); + if (_miso != -1) { + if (_dataOrder == SPI_BITORDER_LSBFIRST) { + // LSB is rare, if it happens we'll just flip the bits around for them + uint8_t temp = 0; + for (uint8_t b = 0; b < 8; b++) { + temp |= ((reply >> b) & 0x1) << (7 - b); + } + reply = temp; } - reply = temp; - } - // Serial.print(" -> "); Serial.println(reply, HEX); + // Serial.print(" -> "); Serial.println(reply, HEX); - buffer[i] = reply; + buffer[i] = reply; + } } return; } diff --git a/Adafruit_SPIDevice.h b/Adafruit_SPIDevice.h index 58e6167..565befc 100644 --- a/Adafruit_SPIDevice.h +++ b/Adafruit_SPIDevice.h @@ -29,6 +29,27 @@ typedef enum _BitOrder { #define SPI_BITORDER_LSBFIRST LSBFIRST #endif +#if defined(__AVR__) || defined(TEENSYDUINO) +typedef volatile uint8_t BusIO_PortReg; +typedef uint8_t BusIO_PortMask; +#define BUSIO_USE_FAST_PINIO + +#elif defined(ESP8266) || defined(ESP32) || defined(__SAM3X8E__) || \ + defined(ARDUINO_ARCH_SAMD) +typedef volatile uint32_t BusIO_PortReg; +typedef uint32_t BusIO_PortMask; +#define BUSIO_USE_FAST_PINIO + +#elif (defined(__arm__) || defined(ARDUINO_FEATHER52)) && \ + !defined(ARDUINO_ARCH_MBED) +typedef volatile uint32_t BusIO_PortReg; +typedef uint32_t BusIO_PortMask; +#define BUSIO_USE_FAST_PINIO + +#else +#undef BUSIO_USE_FAST_PINIO +#endif + /**! The class which defines how we will talk to this device over SPI **/ class Adafruit_SPIDevice { public: @@ -62,6 +83,10 @@ private: uint8_t _dataMode; int8_t _cs, _sck, _mosi, _miso; +#ifdef BUSIO_USE_FAST_PINIO + BusIO_PortReg *mosiPort, *clkPort, *misoPort, *csPort; + BusIO_PortMask mosiPinMask, misoPinMask, clkPinMask, csPinMask; +#endif bool _begun; };