Adafruit_SPIDevice.h 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149
  1. #ifndef Adafruit_SPIDevice_h
  2. #define Adafruit_SPIDevice_h
  3. #include <Arduino.h>
  4. #if !defined(SPI_INTERFACES_COUNT) || \
  5. (defined(SPI_INTERFACES_COUNT) && (SPI_INTERFACES_COUNT > 0))
  6. // HW SPI available
  7. #include <SPI.h>
  8. #define BUSIO_HAS_HW_SPI
  9. #else
  10. // SW SPI ONLY
  11. enum { SPI_MODE0, SPI_MODE1, SPI_MODE2, SPI_MODE3 };
  12. typedef uint8_t SPIClass;
  13. #endif
  14. // some modern SPI definitions don't have BitOrder enum
  15. #if (defined(__AVR__) && !defined(ARDUINO_ARCH_MEGAAVR)) || \
  16. defined(ESP8266) || defined(TEENSYDUINO) || defined(SPARK) || \
  17. defined(ARDUINO_ARCH_SPRESENSE) || defined(MEGATINYCORE) || \
  18. defined(DXCORE) || defined(ARDUINO_AVR_ATmega4809) || \
  19. defined(ARDUINO_AVR_ATmega4808) || defined(ARDUINO_AVR_ATmega3209) || \
  20. defined(ARDUINO_AVR_ATmega3208) || defined(ARDUINO_AVR_ATmega1609) || \
  21. defined(ARDUINO_AVR_ATmega1608) || defined(ARDUINO_AVR_ATmega809) || \
  22. defined(ARDUINO_AVR_ATmega808) || defined(ARDUINO_ARCH_ARC32) || \
  23. defined(ARDUINO_ARCH_XMC)
  24. typedef enum _BitOrder {
  25. SPI_BITORDER_MSBFIRST = MSBFIRST,
  26. SPI_BITORDER_LSBFIRST = LSBFIRST,
  27. } BusIOBitOrder;
  28. #elif defined(ESP32) || defined(__ASR6501__) || defined(__ASR6502__)
  29. // some modern SPI definitions don't have BitOrder enum and have different SPI
  30. // mode defines
  31. typedef enum _BitOrder {
  32. SPI_BITORDER_MSBFIRST = SPI_MSBFIRST,
  33. SPI_BITORDER_LSBFIRST = SPI_LSBFIRST,
  34. } BusIOBitOrder;
  35. #else
  36. // Some platforms have a BitOrder enum but its named MSBFIRST/LSBFIRST
  37. #define SPI_BITORDER_MSBFIRST MSBFIRST
  38. #define SPI_BITORDER_LSBFIRST LSBFIRST
  39. typedef BitOrder BusIOBitOrder;
  40. #endif
  41. #if defined(__IMXRT1062__) // Teensy 4.x
  42. // *Warning* I disabled the usage of FAST_PINIO as the set/clear operations
  43. // used in the cpp file are not atomic and can effect multiple IO pins
  44. // and if an interrupt happens in between the time the code reads the register
  45. // and writes out the updated value, that changes one or more other IO pins
  46. // on that same IO port, those change will be clobbered when the updated
  47. // values are written back. A fast version can be implemented that uses the
  48. // ports set and clear registers which are atomic.
  49. // typedef volatile uint32_t BusIO_PortReg;
  50. // typedef uint32_t BusIO_PortMask;
  51. // #define BUSIO_USE_FAST_PINIO
  52. #elif defined(__MBED__) || defined(__ZEPHYR__)
  53. // Boards based on RTOS cores like mbed or Zephyr are not going to expose the
  54. // low level registers needed for fast pin manipulation
  55. #undef BUSIO_USE_FAST_PINIO
  56. #elif defined(ARDUINO_ARCH_XMC)
  57. #undef BUSIO_USE_FAST_PINIO
  58. #elif defined(__AVR__) || defined(TEENSYDUINO)
  59. typedef volatile uint8_t BusIO_PortReg;
  60. typedef uint8_t BusIO_PortMask;
  61. #define BUSIO_USE_FAST_PINIO
  62. #elif defined(ESP8266) || defined(ESP32) || defined(__SAM3X8E__) || \
  63. defined(ARDUINO_ARCH_SAMD)
  64. typedef volatile uint32_t BusIO_PortReg;
  65. typedef uint32_t BusIO_PortMask;
  66. #define BUSIO_USE_FAST_PINIO
  67. #elif (defined(__arm__) || defined(ARDUINO_FEATHER52)) && \
  68. !defined(ARDUINO_ARCH_RP2040) && !defined(ARDUINO_SILABS) && \
  69. !defined(ARDUINO_UNOR4_MINIMA) && !defined(ARDUINO_UNOR4_WIFI) && \
  70. !defined(PORTDUINO)
  71. typedef volatile uint32_t BusIO_PortReg;
  72. typedef uint32_t BusIO_PortMask;
  73. #if !defined(__ASR6501__) && !defined(__ASR6502__)
  74. #define BUSIO_USE_FAST_PINIO
  75. #endif
  76. #else
  77. #undef BUSIO_USE_FAST_PINIO
  78. #endif
  79. /**! The class which defines how we will talk to this device over SPI **/
  80. class Adafruit_SPIDevice {
  81. public:
  82. #ifdef BUSIO_HAS_HW_SPI
  83. Adafruit_SPIDevice(int8_t cspin, uint32_t freq = 1000000,
  84. BusIOBitOrder dataOrder = SPI_BITORDER_MSBFIRST,
  85. uint8_t dataMode = SPI_MODE0, SPIClass *theSPI = &SPI);
  86. #else
  87. Adafruit_SPIDevice(int8_t cspin, uint32_t freq = 1000000,
  88. BusIOBitOrder dataOrder = SPI_BITORDER_MSBFIRST,
  89. uint8_t dataMode = SPI_MODE0, SPIClass *theSPI = nullptr);
  90. #endif
  91. Adafruit_SPIDevice(int8_t cspin, int8_t sck, int8_t miso, int8_t mosi,
  92. uint32_t freq = 1000000,
  93. BusIOBitOrder dataOrder = SPI_BITORDER_MSBFIRST,
  94. uint8_t dataMode = SPI_MODE0);
  95. ~Adafruit_SPIDevice();
  96. bool begin(void);
  97. bool read(uint8_t *buffer, size_t len, uint8_t sendvalue = 0xFF);
  98. bool write(const uint8_t *buffer, size_t len,
  99. const uint8_t *prefix_buffer = nullptr, size_t prefix_len = 0);
  100. bool write_then_read(const uint8_t *write_buffer, size_t write_len,
  101. uint8_t *read_buffer, size_t read_len,
  102. uint8_t sendvalue = 0xFF);
  103. bool write_and_read(uint8_t *buffer, size_t len);
  104. uint8_t transfer(uint8_t send);
  105. void transfer(uint8_t *buffer, size_t len);
  106. void beginTransaction(void);
  107. void endTransaction(void);
  108. void beginTransactionWithAssertingCS();
  109. void endTransactionWithDeassertingCS();
  110. private:
  111. #ifdef BUSIO_HAS_HW_SPI
  112. SPIClass *_spi = nullptr;
  113. SPISettings *_spiSetting = nullptr;
  114. #else
  115. uint8_t *_spi = nullptr;
  116. uint8_t *_spiSetting = nullptr;
  117. #endif
  118. uint32_t _freq;
  119. BusIOBitOrder _dataOrder;
  120. uint8_t _dataMode;
  121. void setChipSelect(int value);
  122. int8_t _cs, _sck, _mosi, _miso;
  123. #ifdef BUSIO_USE_FAST_PINIO
  124. BusIO_PortReg *mosiPort, *clkPort, *misoPort, *csPort;
  125. BusIO_PortMask mosiPinMask, misoPinMask, clkPinMask, csPinMask;
  126. #endif
  127. bool _begun;
  128. };
  129. #endif // Adafruit_SPIDevice_h