Adafruit_SPIDevice.cpp 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512
  1. #include "Adafruit_SPIDevice.h"
  2. // #define DEBUG_SERIAL Serial
  3. #ifdef BUSIO_USE_FAST_PINIO
  4. #define BUSIO_SET_CLOCK_LOW() (*clkPort = *clkPort & ~clkPinMask)
  5. #define BUSIO_SET_CLOCK_HIGH() (*clkPort = *clkPort | clkPinMask)
  6. #define BUSIO_READ_MISO() (*misoPort & misoPinMask)
  7. #define BUSIO_WRITE_MOSI(value) \
  8. do { \
  9. if (value) \
  10. *mosiPort = *mosiPort | mosiPinMask; \
  11. else \
  12. *mosiPort = *mosiPort & ~mosiPinMask; \
  13. } while (0)
  14. #else
  15. #define BUSIO_SET_CLOCK_LOW() digitalWrite(_sck, LOW)
  16. #define BUSIO_SET_CLOCK_HIGH() digitalWrite(_sck, HIGH)
  17. #define BUSIO_READ_MISO() digitalRead(_miso)
  18. #define BUSIO_WRITE_MOSI(value) digitalWrite(_mosi, value)
  19. #endif
  20. /*!
  21. * @brief Create an SPI device with the given CS pin and settings
  22. * @param cspin The arduino pin number to use for chip select
  23. * @param freq The SPI clock frequency to use, defaults to 1MHz
  24. * @param dataOrder The SPI data order to use for bits within each byte,
  25. * defaults to SPI_BITORDER_MSBFIRST
  26. * @param dataMode The SPI mode to use, defaults to SPI_MODE0
  27. * @param theSPI The SPI bus to use, defaults to &theSPI
  28. */
  29. Adafruit_SPIDevice::Adafruit_SPIDevice(int8_t cspin, uint32_t freq,
  30. BusIOBitOrder dataOrder,
  31. uint8_t dataMode, SPIClass *theSPI) {
  32. #ifdef BUSIO_HAS_HW_SPI
  33. _cs = cspin;
  34. _sck = _mosi = _miso = -1;
  35. _spi = theSPI;
  36. _begun = false;
  37. _spiSetting = new SPISettings(freq, dataOrder, dataMode);
  38. _freq = freq;
  39. _dataOrder = dataOrder;
  40. _dataMode = dataMode;
  41. #else
  42. // unused, but needed to suppress compiler warns
  43. (void)cspin;
  44. (void)freq;
  45. (void)dataOrder;
  46. (void)dataMode;
  47. (void)theSPI;
  48. #endif
  49. }
  50. /*!
  51. * @brief Create an SPI device with the given CS pin and settings
  52. * @param cspin The arduino pin number to use for chip select
  53. * @param sckpin The arduino pin number to use for SCK
  54. * @param misopin The arduino pin number to use for MISO, set to -1 if not
  55. * used
  56. * @param mosipin The arduino pin number to use for MOSI, set to -1 if not
  57. * used
  58. * @param freq The SPI clock frequency to use, defaults to 1MHz
  59. * @param dataOrder The SPI data order to use for bits within each byte,
  60. * defaults to SPI_BITORDER_MSBFIRST
  61. * @param dataMode The SPI mode to use, defaults to SPI_MODE0
  62. */
  63. Adafruit_SPIDevice::Adafruit_SPIDevice(int8_t cspin, int8_t sckpin,
  64. int8_t misopin, int8_t mosipin,
  65. uint32_t freq, BusIOBitOrder dataOrder,
  66. uint8_t dataMode) {
  67. _cs = cspin;
  68. _sck = sckpin;
  69. _miso = misopin;
  70. _mosi = mosipin;
  71. #ifdef BUSIO_USE_FAST_PINIO
  72. csPort = (BusIO_PortReg *)portOutputRegister(digitalPinToPort(cspin));
  73. csPinMask = digitalPinToBitMask(cspin);
  74. if (mosipin != -1) {
  75. mosiPort = (BusIO_PortReg *)portOutputRegister(digitalPinToPort(mosipin));
  76. mosiPinMask = digitalPinToBitMask(mosipin);
  77. }
  78. if (misopin != -1) {
  79. misoPort = (BusIO_PortReg *)portInputRegister(digitalPinToPort(misopin));
  80. misoPinMask = digitalPinToBitMask(misopin);
  81. }
  82. clkPort = (BusIO_PortReg *)portOutputRegister(digitalPinToPort(sckpin));
  83. clkPinMask = digitalPinToBitMask(sckpin);
  84. #endif
  85. _freq = freq;
  86. _dataOrder = dataOrder;
  87. _dataMode = dataMode;
  88. _begun = false;
  89. }
  90. /*!
  91. * @brief Release memory allocated in constructors
  92. */
  93. Adafruit_SPIDevice::~Adafruit_SPIDevice() {
  94. if (_spiSetting)
  95. delete _spiSetting;
  96. }
  97. /*!
  98. * @brief Initializes SPI bus and sets CS pin high
  99. * @return Always returns true because there's no way to test success of SPI
  100. * init
  101. */
  102. bool Adafruit_SPIDevice::begin(void) {
  103. if (_cs != -1) {
  104. pinMode(_cs, OUTPUT);
  105. digitalWrite(_cs, HIGH);
  106. }
  107. if (_spi) { // hardware SPI
  108. #ifdef BUSIO_HAS_HW_SPI
  109. _spi->begin();
  110. #endif
  111. } else {
  112. pinMode(_sck, OUTPUT);
  113. if ((_dataMode == SPI_MODE0) || (_dataMode == SPI_MODE1)) {
  114. // idle low on mode 0 and 1
  115. digitalWrite(_sck, LOW);
  116. } else {
  117. // idle high on mode 2 or 3
  118. digitalWrite(_sck, HIGH);
  119. }
  120. if (_mosi != -1) {
  121. pinMode(_mosi, OUTPUT);
  122. digitalWrite(_mosi, HIGH);
  123. }
  124. if (_miso != -1) {
  125. pinMode(_miso, INPUT);
  126. }
  127. }
  128. _begun = true;
  129. return true;
  130. }
  131. /*!
  132. * @brief Transfer (send/receive) a buffer over hard/soft SPI, without
  133. * transaction management
  134. * @param buffer The buffer to send and receive at the same time
  135. * @param len The number of bytes to transfer
  136. */
  137. void Adafruit_SPIDevice::transfer(uint8_t *buffer, size_t len) {
  138. //
  139. // HARDWARE SPI
  140. //
  141. if (_spi) {
  142. #ifdef BUSIO_HAS_HW_SPI
  143. #if defined(SPARK)
  144. _spi->transfer(buffer, buffer, len, nullptr);
  145. #elif defined(STM32)
  146. for (size_t i = 0; i < len; i++) {
  147. _spi->transfer(buffer[i]);
  148. }
  149. #else
  150. _spi->transfer(buffer, len);
  151. #endif
  152. return;
  153. #endif
  154. }
  155. //
  156. // SOFTWARE SPI
  157. //
  158. uint8_t startbit;
  159. if (_dataOrder == SPI_BITORDER_LSBFIRST) {
  160. startbit = 0x1;
  161. } else {
  162. startbit = 0x80;
  163. }
  164. bool towrite, lastmosi = !(buffer[0] & startbit);
  165. uint8_t bitdelay_us = (1000000 / _freq) / 2;
  166. for (size_t i = 0; i < len; i++) {
  167. uint8_t reply = 0;
  168. uint8_t send = buffer[i];
  169. /*
  170. Serial.print("\tSending software SPI byte 0x");
  171. Serial.print(send, HEX);
  172. Serial.print(" -> 0x");
  173. */
  174. // Serial.print(send, HEX);
  175. for (uint8_t b = startbit; b != 0;
  176. b = (_dataOrder == SPI_BITORDER_LSBFIRST) ? b << 1 : b >> 1) {
  177. if (bitdelay_us) {
  178. delayMicroseconds(bitdelay_us);
  179. }
  180. if (_dataMode == SPI_MODE0 || _dataMode == SPI_MODE2) {
  181. towrite = send & b;
  182. if ((_mosi != -1) && (lastmosi != towrite)) {
  183. BUSIO_WRITE_MOSI(towrite);
  184. lastmosi = towrite;
  185. }
  186. BUSIO_SET_CLOCK_HIGH();
  187. if (bitdelay_us) {
  188. delayMicroseconds(bitdelay_us);
  189. }
  190. if (_miso != -1) {
  191. if (BUSIO_READ_MISO())
  192. reply |= b;
  193. }
  194. BUSIO_SET_CLOCK_LOW();
  195. } else if (_dataMode == SPI_MODE3) {
  196. if (_mosi != -1) { // transmit on falling edge
  197. BUSIO_WRITE_MOSI(send & b);
  198. }
  199. BUSIO_SET_CLOCK_LOW();
  200. if (bitdelay_us) {
  201. delayMicroseconds(bitdelay_us);
  202. }
  203. BUSIO_SET_CLOCK_HIGH();
  204. if (bitdelay_us) {
  205. delayMicroseconds(bitdelay_us);
  206. }
  207. if (_miso != -1) { // read on rising edge
  208. if (BUSIO_READ_MISO()) {
  209. reply |= b;
  210. }
  211. }
  212. } else { // || _dataMode == SPI_MODE1)
  213. BUSIO_SET_CLOCK_HIGH();
  214. if (bitdelay_us) {
  215. delayMicroseconds(bitdelay_us);
  216. }
  217. if (_mosi != -1) {
  218. BUSIO_WRITE_MOSI(send & b);
  219. }
  220. BUSIO_SET_CLOCK_LOW();
  221. if (_miso != -1) {
  222. if (BUSIO_READ_MISO()) {
  223. reply |= b;
  224. }
  225. }
  226. }
  227. }
  228. if (_miso != -1) {
  229. buffer[i] = reply;
  230. }
  231. }
  232. return;
  233. }
  234. /*!
  235. * @brief Transfer (send/receive) one byte over hard/soft SPI, without
  236. * transaction management
  237. * @param send The byte to send
  238. * @return The byte received while transmitting
  239. */
  240. uint8_t Adafruit_SPIDevice::transfer(uint8_t send) {
  241. uint8_t data = send;
  242. transfer(&data, 1);
  243. return data;
  244. }
  245. /*!
  246. * @brief Manually begin a transaction (calls beginTransaction if hardware
  247. * SPI)
  248. */
  249. void Adafruit_SPIDevice::beginTransaction(void) {
  250. if (_spi) {
  251. #ifdef BUSIO_HAS_HW_SPI
  252. _spi->beginTransaction(*_spiSetting);
  253. #endif
  254. }
  255. }
  256. /*!
  257. * @brief Manually end a transaction (calls endTransaction if hardware SPI)
  258. */
  259. void Adafruit_SPIDevice::endTransaction(void) {
  260. if (_spi) {
  261. #ifdef BUSIO_HAS_HW_SPI
  262. _spi->endTransaction();
  263. #endif
  264. }
  265. }
  266. /*!
  267. * @brief Assert/Deassert the CS pin if it is defined
  268. * @param value The state the CS is set to
  269. */
  270. void Adafruit_SPIDevice::setChipSelect(int value) {
  271. if (_cs != -1) {
  272. digitalWrite(_cs, value);
  273. }
  274. }
  275. /*!
  276. * @brief Write a buffer or two to the SPI device, with transaction
  277. * management.
  278. * @brief Manually begin a transaction (calls beginTransaction if hardware
  279. * SPI) with asserting the CS pin
  280. */
  281. void Adafruit_SPIDevice::beginTransactionWithAssertingCS() {
  282. beginTransaction();
  283. setChipSelect(LOW);
  284. }
  285. /*!
  286. * @brief Manually end a transaction (calls endTransaction if hardware SPI)
  287. * with deasserting the CS pin
  288. */
  289. void Adafruit_SPIDevice::endTransactionWithDeassertingCS() {
  290. setChipSelect(HIGH);
  291. endTransaction();
  292. }
  293. /*!
  294. * @brief Write a buffer or two to the SPI device, with transaction
  295. * management.
  296. * @param buffer Pointer to buffer of data to write
  297. * @param len Number of bytes from buffer to write
  298. * @param prefix_buffer Pointer to optional array of data to write before
  299. * buffer.
  300. * @param prefix_len Number of bytes from prefix buffer to write
  301. * @return Always returns true because there's no way to test success of SPI
  302. * writes
  303. */
  304. bool Adafruit_SPIDevice::write(const uint8_t *buffer, size_t len,
  305. const uint8_t *prefix_buffer,
  306. size_t prefix_len) {
  307. beginTransactionWithAssertingCS();
  308. // do the writing
  309. #if defined(ARDUINO_ARCH_ESP32)
  310. if (_spi) {
  311. if (prefix_len > 0) {
  312. _spi->transferBytes((uint8_t *)prefix_buffer, nullptr, prefix_len);
  313. }
  314. if (len > 0) {
  315. _spi->transferBytes((uint8_t *)buffer, nullptr, len);
  316. }
  317. } else
  318. #endif
  319. {
  320. for (size_t i = 0; i < prefix_len; i++) {
  321. transfer(prefix_buffer[i]);
  322. }
  323. for (size_t i = 0; i < len; i++) {
  324. transfer(buffer[i]);
  325. }
  326. }
  327. endTransactionWithDeassertingCS();
  328. #ifdef DEBUG_SERIAL
  329. DEBUG_SERIAL.print(F("\tSPIDevice Wrote: "));
  330. if ((prefix_len != 0) && (prefix_buffer != nullptr)) {
  331. for (uint16_t i = 0; i < prefix_len; i++) {
  332. DEBUG_SERIAL.print(F("0x"));
  333. DEBUG_SERIAL.print(prefix_buffer[i], HEX);
  334. DEBUG_SERIAL.print(F(", "));
  335. }
  336. }
  337. for (uint16_t i = 0; i < len; i++) {
  338. DEBUG_SERIAL.print(F("0x"));
  339. DEBUG_SERIAL.print(buffer[i], HEX);
  340. DEBUG_SERIAL.print(F(", "));
  341. if (i % 32 == 31) {
  342. DEBUG_SERIAL.println();
  343. }
  344. }
  345. DEBUG_SERIAL.println();
  346. #endif
  347. return true;
  348. }
  349. /*!
  350. * @brief Read from SPI into a buffer from the SPI device, with transaction
  351. * management.
  352. * @param buffer Pointer to buffer of data to read into
  353. * @param len Number of bytes from buffer to read.
  354. * @param sendvalue The 8-bits of data to write when doing the data read,
  355. * defaults to 0xFF
  356. * @return Always returns true because there's no way to test success of SPI
  357. * writes
  358. */
  359. bool Adafruit_SPIDevice::read(uint8_t *buffer, size_t len, uint8_t sendvalue) {
  360. memset(buffer, sendvalue, len); // clear out existing buffer
  361. beginTransactionWithAssertingCS();
  362. transfer(buffer, len);
  363. endTransactionWithDeassertingCS();
  364. #ifdef DEBUG_SERIAL
  365. DEBUG_SERIAL.print(F("\tSPIDevice Read: "));
  366. for (uint16_t i = 0; i < len; i++) {
  367. DEBUG_SERIAL.print(F("0x"));
  368. DEBUG_SERIAL.print(buffer[i], HEX);
  369. DEBUG_SERIAL.print(F(", "));
  370. if (len % 32 == 31) {
  371. DEBUG_SERIAL.println();
  372. }
  373. }
  374. DEBUG_SERIAL.println();
  375. #endif
  376. return true;
  377. }
  378. /*!
  379. * @brief Write some data, then read some data from SPI into another buffer,
  380. * with transaction management. The buffers can point to same/overlapping
  381. * locations. This does not transmit-receive at the same time!
  382. * @param write_buffer Pointer to buffer of data to write from
  383. * @param write_len Number of bytes from buffer to write.
  384. * @param read_buffer Pointer to buffer of data to read into.
  385. * @param read_len Number of bytes from buffer to read.
  386. * @param sendvalue The 8-bits of data to write when doing the data read,
  387. * defaults to 0xFF
  388. * @return Always returns true because there's no way to test success of SPI
  389. * writes
  390. */
  391. bool Adafruit_SPIDevice::write_then_read(const uint8_t *write_buffer,
  392. size_t write_len, uint8_t *read_buffer,
  393. size_t read_len, uint8_t sendvalue) {
  394. beginTransactionWithAssertingCS();
  395. // do the writing
  396. #if defined(ARDUINO_ARCH_ESP32)
  397. if (_spi) {
  398. if (write_len > 0) {
  399. _spi->transferBytes((uint8_t *)write_buffer, nullptr, write_len);
  400. }
  401. } else
  402. #endif
  403. {
  404. for (size_t i = 0; i < write_len; i++) {
  405. transfer(write_buffer[i]);
  406. }
  407. }
  408. #ifdef DEBUG_SERIAL
  409. DEBUG_SERIAL.print(F("\tSPIDevice Wrote: "));
  410. for (uint16_t i = 0; i < write_len; i++) {
  411. DEBUG_SERIAL.print(F("0x"));
  412. DEBUG_SERIAL.print(write_buffer[i], HEX);
  413. DEBUG_SERIAL.print(F(", "));
  414. if (write_len % 32 == 31) {
  415. DEBUG_SERIAL.println();
  416. }
  417. }
  418. DEBUG_SERIAL.println();
  419. #endif
  420. // do the reading
  421. for (size_t i = 0; i < read_len; i++) {
  422. read_buffer[i] = transfer(sendvalue);
  423. }
  424. #ifdef DEBUG_SERIAL
  425. DEBUG_SERIAL.print(F("\tSPIDevice Read: "));
  426. for (uint16_t i = 0; i < read_len; i++) {
  427. DEBUG_SERIAL.print(F("0x"));
  428. DEBUG_SERIAL.print(read_buffer[i], HEX);
  429. DEBUG_SERIAL.print(F(", "));
  430. if (read_len % 32 == 31) {
  431. DEBUG_SERIAL.println();
  432. }
  433. }
  434. DEBUG_SERIAL.println();
  435. #endif
  436. endTransactionWithDeassertingCS();
  437. return true;
  438. }
  439. /*!
  440. * @brief Write some data and read some data at the same time from SPI
  441. * into the same buffer, with transaction management. This is basicaly a wrapper
  442. * for transfer() with CS-pin and transaction management. This /does/
  443. * transmit-receive at the same time!
  444. * @param buffer Pointer to buffer of data to write/read to/from
  445. * @param len Number of bytes from buffer to write/read.
  446. * @return Always returns true because there's no way to test success of SPI
  447. * writes
  448. */
  449. bool Adafruit_SPIDevice::write_and_read(uint8_t *buffer, size_t len) {
  450. beginTransactionWithAssertingCS();
  451. transfer(buffer, len);
  452. endTransactionWithDeassertingCS();
  453. return true;
  454. }