add fast software spi

This commit is contained in:
lady ada 2020-07-18 14:18:07 -04:00
parent d9b3d9a6d4
commit 0b1dbbd0e4
2 changed files with 105 additions and 13 deletions

View File

@ -46,6 +46,22 @@ Adafruit_SPIDevice::Adafruit_SPIDevice(int8_t cspin, int8_t sckpin,
_sck = sckpin; _sck = sckpin;
_miso = misopin; _miso = misopin;
_mosi = mosipin; _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; _freq = freq;
_dataOrder = dataOrder; _dataOrder = dataOrder;
_dataMode = dataMode; _dataMode = dataMode;
@ -125,38 +141,89 @@ void Adafruit_SPIDevice::transfer(uint8_t *buffer, size_t len) {
reply <<= 1; reply <<= 1;
if (_dataMode == SPI_MODE0 || _dataMode == SPI_MODE2) { if (_dataMode == SPI_MODE0 || _dataMode == SPI_MODE2) {
if (_mosi != -1) { if (_mosi != -1) {
#ifdef BUSIO_USE_FAST_PINIO
digitalWrite(_mosi, send & (1 << b)); 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); digitalWrite(_sck, HIGH);
if ((_miso != -1) && digitalRead(_miso)) { #endif
reply |= 1;
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); digitalWrite(_sck, LOW);
#endif
} }
if (_dataMode == SPI_MODE1 || _dataMode == SPI_MODE3) { if (_dataMode == SPI_MODE1 || _dataMode == SPI_MODE3) {
#ifdef BUSIO_USE_FAST_PINIO
*clkPort |= clkPinMask; // Clock high
#else
digitalWrite(_sck, HIGH); digitalWrite(_sck, HIGH);
#endif
if (_mosi != -1) { if (_mosi != -1) {
#ifdef BUSIO_USE_FAST_PINIO
digitalWrite(_mosi, send & (1 << b)); 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); digitalWrite(_sck, LOW);
if ((_miso != -1) && digitalRead(_miso)) { #endif
reply |= 1;
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); // Serial.print(" : 0x"); Serial.print(reply, HEX);
if (_dataOrder == SPI_BITORDER_LSBFIRST) { if (_miso != -1) {
// LSB is rare, if it happens we'll just flip the bits around for them if (_dataOrder == SPI_BITORDER_LSBFIRST) {
uint8_t temp = 0; // LSB is rare, if it happens we'll just flip the bits around for them
for (uint8_t b = 0; b < 8; b++) { uint8_t temp = 0;
temp |= ((reply >> b) & 0x1) << (7 - b); 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; return;
} }

View File

@ -29,6 +29,27 @@ typedef enum _BitOrder {
#define SPI_BITORDER_LSBFIRST LSBFIRST #define SPI_BITORDER_LSBFIRST LSBFIRST
#endif #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 **/ /**! The class which defines how we will talk to this device over SPI **/
class Adafruit_SPIDevice { class Adafruit_SPIDevice {
public: public:
@ -62,6 +83,10 @@ private:
uint8_t _dataMode; uint8_t _dataMode;
int8_t _cs, _sck, _mosi, _miso; 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; bool _begun;
}; };