Вы не можете выбрать более 25 тем Темы должны начинаться с буквы или цифры, могут содержать дефисы(-) и должны содержать не более 35 символов.

10 лет назад
10 лет назад
10 лет назад
10 лет назад
10 лет назад
10 лет назад
10 лет назад
10 лет назад
10 лет назад
9 лет назад
10 лет назад
10 лет назад
10 лет назад
10 лет назад
10 лет назад
9 лет назад
9 лет назад
9 лет назад
9 лет назад
9 лет назад
9 лет назад
9 лет назад
9 лет назад
9 лет назад
9 лет назад
9 лет назад
9 лет назад
9 лет назад
9 лет назад
9 лет назад
9 лет назад
9 лет назад
9 лет назад
9 лет назад
9 лет назад
9 лет назад
9 лет назад
9 лет назад
9 лет назад
9 лет назад
9 лет назад
9 лет назад
9 лет назад
9 лет назад
9 лет назад
9 лет назад
9 лет назад
9 лет назад
9 лет назад
9 лет назад
9 лет назад
9 лет назад
9 лет назад
9 лет назад
9 лет назад
9 лет назад
9 лет назад
9 лет назад
9 лет назад
9 лет назад
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036
  1. /*
  2. * Copyright (c) 2010 by Cristian Maglie <c.maglie@bug.st>
  3. * Copyright (c) 2014 by Paul Stoffregen <paul@pjrc.com> (Transaction API)
  4. * Copyright (c) 2014 by Matthijs Kooijman <matthijs@stdin.nl> (SPISettings AVR)
  5. * SPI Master library for arduino.
  6. *
  7. * This file is free software; you can redistribute it and/or modify
  8. * it under the terms of either the GNU General Public License version 2
  9. * or the GNU Lesser General Public License version 2.1, both as
  10. * published by the Free Software Foundation.
  11. */
  12. #ifndef _SPI_H_INCLUDED
  13. #define _SPI_H_INCLUDED
  14. #include <Arduino.h>
  15. #if defined(__arm__) && defined(TEENSYDUINO)
  16. #if defined(__has_include) && __has_include(<EventResponder.h>)
  17. // SPI_HAS_TRANSFER_ASYNC - Defined to say that the SPI supports an ASYNC version
  18. // of the SPI_HAS_TRANSFER_BUF
  19. #define SPI_HAS_TRANSFER_ASYNC 1
  20. #include <DMAChannel.h>
  21. #include <EventResponder.h>
  22. #endif
  23. #endif
  24. // SPI_HAS_TRANSACTION means SPI has beginTransaction(), endTransaction(),
  25. // usingInterrupt(), and SPISetting(clock, bitOrder, dataMode)
  26. #define SPI_HAS_TRANSACTION 1
  27. // Uncomment this line to add detection of mismatched begin/end transactions.
  28. // A mismatch occurs if other libraries fail to use SPI.endTransaction() for
  29. // each SPI.beginTransaction(). Connect a LED to this pin. The LED will turn
  30. // on if any mismatch is ever detected.
  31. //#define SPI_TRANSACTION_MISMATCH_LED 5
  32. // SPI_HAS_TRANSFER_BUF - is defined to signify that this library supports
  33. // a version of transfer which allows you to pass in both TX and RX buffer
  34. // pointers, either of which could be NULL
  35. #define SPI_HAS_TRANSFER_BUF 1
  36. #ifndef LSBFIRST
  37. #define LSBFIRST 0
  38. #endif
  39. #ifndef MSBFIRST
  40. #define MSBFIRST 1
  41. #endif
  42. #define SPI_MODE0 0x00
  43. #define SPI_MODE1 0x04
  44. #define SPI_MODE2 0x08
  45. #define SPI_MODE3 0x0C
  46. #define SPI_CLOCK_DIV4 0x00
  47. #define SPI_CLOCK_DIV16 0x01
  48. #define SPI_CLOCK_DIV64 0x02
  49. #define SPI_CLOCK_DIV128 0x03
  50. #define SPI_CLOCK_DIV2 0x04
  51. #define SPI_CLOCK_DIV8 0x05
  52. #define SPI_CLOCK_DIV32 0x06
  53. #define SPI_MODE_MASK 0x0C // CPOL = bit 3, CPHA = bit 2 on SPCR
  54. #define SPI_CLOCK_MASK 0x03 // SPR1 = bit 1, SPR0 = bit 0 on SPCR
  55. #define SPI_2XCLOCK_MASK 0x01 // SPI2X = bit 0 on SPSR
  56. /**********************************************************/
  57. /* 8 bit AVR-based boards */
  58. /**********************************************************/
  59. #if defined(__AVR__)
  60. // define SPI_AVR_EIMSK for AVR boards with external interrupt pins
  61. #if defined(EIMSK)
  62. #define SPI_AVR_EIMSK EIMSK
  63. #elif defined(GICR)
  64. #define SPI_AVR_EIMSK GICR
  65. #elif defined(GIMSK)
  66. #define SPI_AVR_EIMSK GIMSK
  67. #endif
  68. class SPISettings {
  69. public:
  70. SPISettings(uint32_t clock, uint8_t bitOrder, uint8_t dataMode) {
  71. if (__builtin_constant_p(clock)) {
  72. init_AlwaysInline(clock, bitOrder, dataMode);
  73. } else {
  74. init_MightInline(clock, bitOrder, dataMode);
  75. }
  76. }
  77. SPISettings() {
  78. init_AlwaysInline(4000000, MSBFIRST, SPI_MODE0);
  79. }
  80. private:
  81. void init_MightInline(uint32_t clock, uint8_t bitOrder, uint8_t dataMode) {
  82. init_AlwaysInline(clock, bitOrder, dataMode);
  83. }
  84. void init_AlwaysInline(uint32_t clock, uint8_t bitOrder, uint8_t dataMode)
  85. __attribute__((__always_inline__)) {
  86. // Clock settings are defined as follows. Note that this shows SPI2X
  87. // inverted, so the bits form increasing numbers. Also note that
  88. // fosc/64 appears twice
  89. // SPR1 SPR0 ~SPI2X Freq
  90. // 0 0 0 fosc/2
  91. // 0 0 1 fosc/4
  92. // 0 1 0 fosc/8
  93. // 0 1 1 fosc/16
  94. // 1 0 0 fosc/32
  95. // 1 0 1 fosc/64
  96. // 1 1 0 fosc/64
  97. // 1 1 1 fosc/128
  98. // We find the fastest clock that is less than or equal to the
  99. // given clock rate. The clock divider that results in clock_setting
  100. // is 2 ^^ (clock_div + 1). If nothing is slow enough, we'll use the
  101. // slowest (128 == 2 ^^ 7, so clock_div = 6).
  102. uint8_t clockDiv;
  103. // When the clock is known at compiletime, use this if-then-else
  104. // cascade, which the compiler knows how to completely optimize
  105. // away. When clock is not known, use a loop instead, which generates
  106. // shorter code.
  107. if (__builtin_constant_p(clock)) {
  108. if (clock >= F_CPU / 2) {
  109. clockDiv = 0;
  110. } else if (clock >= F_CPU / 4) {
  111. clockDiv = 1;
  112. } else if (clock >= F_CPU / 8) {
  113. clockDiv = 2;
  114. } else if (clock >= F_CPU / 16) {
  115. clockDiv = 3;
  116. } else if (clock >= F_CPU / 32) {
  117. clockDiv = 4;
  118. } else if (clock >= F_CPU / 64) {
  119. clockDiv = 5;
  120. } else {
  121. clockDiv = 6;
  122. }
  123. } else {
  124. uint32_t clockSetting = F_CPU / 2;
  125. clockDiv = 0;
  126. while (clockDiv < 6 && clock < clockSetting) {
  127. clockSetting /= 2;
  128. clockDiv++;
  129. }
  130. }
  131. // Compensate for the duplicate fosc/64
  132. if (clockDiv == 6)
  133. clockDiv = 7;
  134. // Invert the SPI2X bit
  135. clockDiv ^= 0x1;
  136. // Pack into the SPISettings class
  137. spcr = _BV(SPE) | _BV(MSTR) | ((bitOrder == LSBFIRST) ? _BV(DORD) : 0) |
  138. (dataMode & SPI_MODE_MASK) | ((clockDiv >> 1) & SPI_CLOCK_MASK);
  139. spsr = clockDiv & SPI_2XCLOCK_MASK;
  140. }
  141. uint8_t spcr;
  142. uint8_t spsr;
  143. friend class SPIClass;
  144. };
  145. class SPIClass { // AVR
  146. public:
  147. // Initialize the SPI library
  148. static void begin();
  149. // If SPI is used from within an interrupt, this function registers
  150. // that interrupt with the SPI library, so beginTransaction() can
  151. // prevent conflicts. The input interruptNumber is the number used
  152. // with attachInterrupt. If SPI is used from a different interrupt
  153. // (eg, a timer), interruptNumber should be 255.
  154. static void usingInterrupt(uint8_t interruptNumber);
  155. // Before using SPI.transfer() or asserting chip select pins,
  156. // this function is used to gain exclusive access to the SPI bus
  157. // and configure the correct settings.
  158. inline static void beginTransaction(SPISettings settings) {
  159. if (interruptMode > 0) {
  160. #ifdef SPI_AVR_EIMSK
  161. if (interruptMode == 1) {
  162. interruptSave = SPI_AVR_EIMSK;
  163. SPI_AVR_EIMSK &= ~interruptMask;
  164. } else
  165. #endif
  166. {
  167. uint8_t tmp = SREG;
  168. cli();
  169. interruptSave = tmp;
  170. }
  171. }
  172. #ifdef SPI_TRANSACTION_MISMATCH_LED
  173. if (inTransactionFlag) {
  174. pinMode(SPI_TRANSACTION_MISMATCH_LED, OUTPUT);
  175. digitalWrite(SPI_TRANSACTION_MISMATCH_LED, HIGH);
  176. }
  177. inTransactionFlag = 1;
  178. #endif
  179. SPCR = settings.spcr;
  180. SPSR = settings.spsr;
  181. }
  182. // Write to the SPI bus (MOSI pin) and also receive (MISO pin)
  183. inline static uint8_t transfer(uint8_t data) {
  184. SPDR = data;
  185. asm volatile("nop");
  186. while (!(SPSR & _BV(SPIF))) ; // wait
  187. return SPDR;
  188. }
  189. inline static uint16_t transfer16(uint16_t data) {
  190. union { uint16_t val; struct { uint8_t lsb; uint8_t msb; }; } in, out;
  191. in.val = data;
  192. if ((SPCR & _BV(DORD))) {
  193. SPDR = in.lsb;
  194. asm volatile("nop");
  195. while (!(SPSR & _BV(SPIF))) ;
  196. out.lsb = SPDR;
  197. SPDR = in.msb;
  198. asm volatile("nop");
  199. while (!(SPSR & _BV(SPIF))) ;
  200. out.msb = SPDR;
  201. } else {
  202. SPDR = in.msb;
  203. asm volatile("nop");
  204. while (!(SPSR & _BV(SPIF))) ;
  205. out.msb = SPDR;
  206. SPDR = in.lsb;
  207. asm volatile("nop");
  208. while (!(SPSR & _BV(SPIF))) ;
  209. out.lsb = SPDR;
  210. }
  211. return out.val;
  212. }
  213. inline static void transfer(void *buf, size_t count) {
  214. if (count == 0) return;
  215. uint8_t *p = (uint8_t *)buf;
  216. SPDR = *p;
  217. while (--count > 0) {
  218. uint8_t out = *(p + 1);
  219. while (!(SPSR & _BV(SPIF))) ;
  220. uint8_t in = SPDR;
  221. SPDR = out;
  222. *p++ = in;
  223. }
  224. while (!(SPSR & _BV(SPIF))) ;
  225. *p = SPDR;
  226. }
  227. static void setTransferWriteFill(uint8_t ch ) {_transferWriteFill = ch;}
  228. static void transfer(const void * buf, void * retbuf, uint32_t count);
  229. // After performing a group of transfers and releasing the chip select
  230. // signal, this function allows others to access the SPI bus
  231. inline static void endTransaction(void) {
  232. #ifdef SPI_TRANSACTION_MISMATCH_LED
  233. if (!inTransactionFlag) {
  234. pinMode(SPI_TRANSACTION_MISMATCH_LED, OUTPUT);
  235. digitalWrite(SPI_TRANSACTION_MISMATCH_LED, HIGH);
  236. }
  237. inTransactionFlag = 0;
  238. #endif
  239. if (interruptMode > 0) {
  240. #ifdef SPI_AVR_EIMSK
  241. if (interruptMode == 1) {
  242. SPI_AVR_EIMSK = interruptSave;
  243. } else
  244. #endif
  245. {
  246. SREG = interruptSave;
  247. }
  248. }
  249. }
  250. // Disable the SPI bus
  251. static void end();
  252. // This function is deprecated. New applications should use
  253. // beginTransaction() to configure SPI settings.
  254. inline static void setBitOrder(uint8_t bitOrder) {
  255. if (bitOrder == LSBFIRST) SPCR |= _BV(DORD);
  256. else SPCR &= ~(_BV(DORD));
  257. }
  258. // This function is deprecated. New applications should use
  259. // beginTransaction() to configure SPI settings.
  260. inline static void setDataMode(uint8_t dataMode) {
  261. SPCR = (SPCR & ~SPI_MODE_MASK) | dataMode;
  262. }
  263. // This function is deprecated. New applications should use
  264. // beginTransaction() to configure SPI settings.
  265. inline static void setClockDivider(uint8_t clockDiv) {
  266. SPCR = (SPCR & ~SPI_CLOCK_MASK) | (clockDiv & SPI_CLOCK_MASK);
  267. SPSR = (SPSR & ~SPI_2XCLOCK_MASK) | ((clockDiv >> 2) & SPI_2XCLOCK_MASK);
  268. }
  269. // These undocumented functions should not be used. SPI.transfer()
  270. // polls the hardware flag which is automatically cleared as the
  271. // AVR responds to SPI's interrupt
  272. inline static void attachInterrupt() { SPCR |= _BV(SPIE); }
  273. inline static void detachInterrupt() { SPCR &= ~_BV(SPIE); }
  274. private:
  275. static uint8_t interruptMode; // 0=none, 1=mask, 2=global
  276. static uint8_t interruptMask; // which interrupts to mask
  277. static uint8_t interruptSave; // temp storage, to restore state
  278. #ifdef SPI_TRANSACTION_MISMATCH_LED
  279. static uint8_t inTransactionFlag;
  280. #endif
  281. static uint8_t _transferWriteFill;
  282. };
  283. /**********************************************************/
  284. /* 32 bit Teensy 3.x */
  285. /**********************************************************/
  286. #elif defined(__arm__) && defined(TEENSYDUINO) && defined(KINETISK)
  287. #define SPI_HAS_NOTUSINGINTERRUPT 1
  288. class SPISettings {
  289. public:
  290. SPISettings(uint32_t clock, uint8_t bitOrder, uint8_t dataMode) {
  291. if (__builtin_constant_p(clock)) {
  292. init_AlwaysInline(clock, bitOrder, dataMode);
  293. } else {
  294. init_MightInline(clock, bitOrder, dataMode);
  295. }
  296. }
  297. SPISettings() {
  298. init_AlwaysInline(4000000, MSBFIRST, SPI_MODE0);
  299. }
  300. private:
  301. void init_MightInline(uint32_t clock, uint8_t bitOrder, uint8_t dataMode) {
  302. init_AlwaysInline(clock, bitOrder, dataMode);
  303. }
  304. void init_AlwaysInline(uint32_t clock, uint8_t bitOrder, uint8_t dataMode)
  305. __attribute__((__always_inline__)) {
  306. uint32_t t, c = SPI_CTAR_FMSZ(7);
  307. if (bitOrder == LSBFIRST) c |= SPI_CTAR_LSBFE;
  308. if (__builtin_constant_p(clock)) {
  309. if (clock >= F_BUS / 2) {
  310. t = SPI_CTAR_PBR(0) | SPI_CTAR_BR(0) | SPI_CTAR_DBR
  311. | SPI_CTAR_CSSCK(0);
  312. } else if (clock >= F_BUS / 3) {
  313. t = SPI_CTAR_PBR(1) | SPI_CTAR_BR(0) | SPI_CTAR_DBR
  314. | SPI_CTAR_CSSCK(0);
  315. } else if (clock >= F_BUS / 4) {
  316. t = SPI_CTAR_PBR(0) | SPI_CTAR_BR(0) | SPI_CTAR_CSSCK(0);
  317. } else if (clock >= F_BUS / 5) {
  318. t = SPI_CTAR_PBR(2) | SPI_CTAR_BR(0) | SPI_CTAR_DBR
  319. | SPI_CTAR_CSSCK(0);
  320. } else if (clock >= F_BUS / 6) {
  321. t = SPI_CTAR_PBR(1) | SPI_CTAR_BR(0) | SPI_CTAR_CSSCK(0);
  322. } else if (clock >= F_BUS / 8) {
  323. t = SPI_CTAR_PBR(0) | SPI_CTAR_BR(1) | SPI_CTAR_CSSCK(1);
  324. } else if (clock >= F_BUS / 10) {
  325. t = SPI_CTAR_PBR(2) | SPI_CTAR_BR(0) | SPI_CTAR_CSSCK(0);
  326. } else if (clock >= F_BUS / 12) {
  327. t = SPI_CTAR_PBR(1) | SPI_CTAR_BR(1) | SPI_CTAR_CSSCK(1);
  328. } else if (clock >= F_BUS / 16) {
  329. t = SPI_CTAR_PBR(0) | SPI_CTAR_BR(3) | SPI_CTAR_CSSCK(2);
  330. } else if (clock >= F_BUS / 20) {
  331. t = SPI_CTAR_PBR(2) | SPI_CTAR_BR(1) | SPI_CTAR_CSSCK(0);
  332. } else if (clock >= F_BUS / 24) {
  333. t = SPI_CTAR_PBR(1) | SPI_CTAR_BR(3) | SPI_CTAR_CSSCK(2);
  334. } else if (clock >= F_BUS / 32) {
  335. t = SPI_CTAR_PBR(0) | SPI_CTAR_BR(4) | SPI_CTAR_CSSCK(3);
  336. } else if (clock >= F_BUS / 40) {
  337. t = SPI_CTAR_PBR(2) | SPI_CTAR_BR(3) | SPI_CTAR_CSSCK(2);
  338. } else if (clock >= F_BUS / 56) {
  339. t = SPI_CTAR_PBR(3) | SPI_CTAR_BR(3) | SPI_CTAR_CSSCK(2);
  340. } else if (clock >= F_BUS / 64) {
  341. t = SPI_CTAR_PBR(0) | SPI_CTAR_BR(5) | SPI_CTAR_CSSCK(4);
  342. } else if (clock >= F_BUS / 96) {
  343. t = SPI_CTAR_PBR(1) | SPI_CTAR_BR(5) | SPI_CTAR_CSSCK(4);
  344. } else if (clock >= F_BUS / 128) {
  345. t = SPI_CTAR_PBR(0) | SPI_CTAR_BR(6) | SPI_CTAR_CSSCK(5);
  346. } else if (clock >= F_BUS / 192) {
  347. t = SPI_CTAR_PBR(1) | SPI_CTAR_BR(6) | SPI_CTAR_CSSCK(5);
  348. } else if (clock >= F_BUS / 256) {
  349. t = SPI_CTAR_PBR(0) | SPI_CTAR_BR(7) | SPI_CTAR_CSSCK(6);
  350. } else if (clock >= F_BUS / 384) {
  351. t = SPI_CTAR_PBR(1) | SPI_CTAR_BR(7) | SPI_CTAR_CSSCK(6);
  352. } else if (clock >= F_BUS / 512) {
  353. t = SPI_CTAR_PBR(0) | SPI_CTAR_BR(8) | SPI_CTAR_CSSCK(7);
  354. } else if (clock >= F_BUS / 640) {
  355. t = SPI_CTAR_PBR(2) | SPI_CTAR_BR(7) | SPI_CTAR_CSSCK(6);
  356. } else { /* F_BUS / 768 */
  357. t = SPI_CTAR_PBR(1) | SPI_CTAR_BR(8) | SPI_CTAR_CSSCK(7);
  358. }
  359. } else {
  360. for (uint32_t i=0; i<23; i++) {
  361. t = ctar_clock_table[i];
  362. if (clock >= F_BUS / ctar_div_table[i]) break;
  363. }
  364. }
  365. if (dataMode & 0x08) {
  366. c |= SPI_CTAR_CPOL;
  367. }
  368. if (dataMode & 0x04) {
  369. c |= SPI_CTAR_CPHA;
  370. t = (t & 0xFFFF0FFF) | ((t & 0xF000) >> 4);
  371. }
  372. ctar = c | t;
  373. }
  374. static const uint16_t ctar_div_table[23];
  375. static const uint32_t ctar_clock_table[23];
  376. uint32_t ctar;
  377. friend class SPIClass;
  378. };
  379. class SPIClass { // Teensy 3.x
  380. public:
  381. #if defined(__MK20DX128__) || defined(__MK20DX256__)
  382. static const uint8_t CNT_MISO_PINS = 2;
  383. static const uint8_t CNT_MOSI_PINS = 2;
  384. static const uint8_t CNT_SCK_PINS = 2;
  385. static const uint8_t CNT_CS_PINS = 9;
  386. #elif defined(__MK64FX512__) || defined(__MK66FX1M0__)
  387. static const uint8_t CNT_MISO_PINS = 4;
  388. static const uint8_t CNT_MOSI_PINS = 4;
  389. static const uint8_t CNT_SCK_PINS = 3;
  390. static const uint8_t CNT_CS_PINS = 11;
  391. #endif
  392. typedef struct {
  393. volatile uint32_t &clock_gate_register;
  394. uint32_t clock_gate_mask;
  395. uint8_t queue_size;
  396. uint8_t spi_irq;
  397. uint32_t max_dma_count;
  398. uint8_t tx_dma_channel;
  399. uint8_t rx_dma_channel;
  400. void (*dma_rxisr)();
  401. uint8_t miso_pin[CNT_MISO_PINS];
  402. uint32_t miso_mux[CNT_MISO_PINS];
  403. uint8_t mosi_pin[CNT_MOSI_PINS];
  404. uint32_t mosi_mux[CNT_MOSI_PINS];
  405. uint8_t sck_pin[CNT_SCK_PINS];
  406. uint32_t sck_mux[CNT_SCK_PINS];
  407. uint8_t cs_pin[CNT_CS_PINS];
  408. uint32_t cs_mux[CNT_CS_PINS];
  409. uint8_t cs_mask[CNT_CS_PINS];
  410. } SPI_Hardware_t;
  411. static const SPI_Hardware_t spi0_hardware;
  412. static const SPI_Hardware_t spi1_hardware;
  413. static const SPI_Hardware_t spi2_hardware;
  414. enum DMAState { notAllocated, idle, active, completed};
  415. public:
  416. constexpr SPIClass(uintptr_t myport, uintptr_t myhardware)
  417. : port_addr(myport), hardware_addr(myhardware) {
  418. }
  419. // Initialize the SPI library
  420. void begin();
  421. // If SPI is to used from within an interrupt, this function registers
  422. // that interrupt with the SPI library, so beginTransaction() can
  423. // prevent conflicts. The input interruptNumber is the number used
  424. // with attachInterrupt. If SPI is used from a different interrupt
  425. // (eg, a timer), interruptNumber should be 255.
  426. void usingInterrupt(uint8_t n) {
  427. if (n == 3 || n == 4 || n == 24 || n == 33) {
  428. usingInterrupt(IRQ_PORTA);
  429. } else if (n == 0 || n == 1 || (n >= 16 && n <= 19) || n == 25 || n == 32) {
  430. usingInterrupt(IRQ_PORTB);
  431. } else if ((n >= 9 && n <= 13) || n == 15 || n == 22 || n == 23
  432. || (n >= 27 && n <= 30)) {
  433. usingInterrupt(IRQ_PORTC);
  434. } else if (n == 2 || (n >= 5 && n <= 8) || n == 14 || n == 20 || n == 21) {
  435. usingInterrupt(IRQ_PORTD);
  436. } else if (n == 26 || n == 31) {
  437. usingInterrupt(IRQ_PORTE);
  438. }
  439. }
  440. void usingInterrupt(IRQ_NUMBER_t interruptName);
  441. void notUsingInterrupt(IRQ_NUMBER_t interruptName);
  442. // Before using SPI.transfer() or asserting chip select pins,
  443. // this function is used to gain exclusive access to the SPI bus
  444. // and configure the correct settings.
  445. void beginTransaction(SPISettings settings) {
  446. if (interruptMasksUsed) {
  447. __disable_irq();
  448. if (interruptMasksUsed & 0x01) {
  449. interruptSave[0] = NVIC_ICER0 & interruptMask[0];
  450. NVIC_ICER0 = interruptSave[0];
  451. }
  452. #if NVIC_NUM_INTERRUPTS > 32
  453. if (interruptMasksUsed & 0x02) {
  454. interruptSave[1] = NVIC_ICER1 & interruptMask[1];
  455. NVIC_ICER1 = interruptSave[1];
  456. }
  457. #endif
  458. #if NVIC_NUM_INTERRUPTS > 64 && defined(NVIC_ISER2)
  459. if (interruptMasksUsed & 0x04) {
  460. interruptSave[2] = NVIC_ICER2 & interruptMask[2];
  461. NVIC_ICER2 = interruptSave[2];
  462. }
  463. #endif
  464. #if NVIC_NUM_INTERRUPTS > 96 && defined(NVIC_ISER3)
  465. if (interruptMasksUsed & 0x08) {
  466. interruptSave[3] = NVIC_ICER3 & interruptMask[3];
  467. NVIC_ICER3 = interruptSave[3];
  468. }
  469. #endif
  470. __enable_irq();
  471. }
  472. #ifdef SPI_TRANSACTION_MISMATCH_LED
  473. if (inTransactionFlag) {
  474. pinMode(SPI_TRANSACTION_MISMATCH_LED, OUTPUT);
  475. digitalWrite(SPI_TRANSACTION_MISMATCH_LED, HIGH);
  476. }
  477. inTransactionFlag = 1;
  478. #endif
  479. if (port().CTAR0 != settings.ctar) {
  480. port().MCR = SPI_MCR_MDIS | SPI_MCR_HALT | SPI_MCR_PCSIS(0x3F);
  481. port().CTAR0 = settings.ctar;
  482. port().CTAR1 = settings.ctar| SPI_CTAR_FMSZ(8);
  483. port().MCR = SPI_MCR_MSTR | SPI_MCR_PCSIS(0x3F);
  484. }
  485. }
  486. // Write to the SPI bus (MOSI pin) and also receive (MISO pin)
  487. uint8_t transfer(uint8_t data) {
  488. port().SR = SPI_SR_TCF;
  489. port().PUSHR = data;
  490. while (!(port().SR & SPI_SR_TCF)) ; // wait
  491. return port().POPR;
  492. }
  493. uint16_t transfer16(uint16_t data) {
  494. port().SR = SPI_SR_TCF;
  495. port().PUSHR = data | SPI_PUSHR_CTAS(1);
  496. while (!(port().SR & SPI_SR_TCF)) ; // wait
  497. return port().POPR;
  498. }
  499. void inline transfer(void *buf, size_t count) {transfer(buf, buf, count);}
  500. void setTransferWriteFill(uint8_t ch ) {_transferWriteFill = ch;}
  501. void transfer(const void * buf, void * retbuf, size_t count);
  502. // Asynch support (DMA )
  503. #ifdef SPI_HAS_TRANSFER_ASYNC
  504. bool transfer(const void *txBuffer, void *rxBuffer, size_t count, EventResponderRef event_responder);
  505. friend void _spi_dma_rxISR0(void);
  506. friend void _spi_dma_rxISR1(void);
  507. friend void _spi_dma_rxISR2(void);
  508. inline void dma_rxisr(void);
  509. #endif
  510. // After performing a group of transfers and releasing the chip select
  511. // signal, this function allows others to access the SPI bus
  512. void endTransaction(void) {
  513. #ifdef SPI_TRANSACTION_MISMATCH_LED
  514. if (!inTransactionFlag) {
  515. pinMode(SPI_TRANSACTION_MISMATCH_LED, OUTPUT);
  516. digitalWrite(SPI_TRANSACTION_MISMATCH_LED, HIGH);
  517. }
  518. inTransactionFlag = 0;
  519. #endif
  520. if (interruptMasksUsed) {
  521. if (interruptMasksUsed & 0x01) {
  522. NVIC_ISER0 = interruptSave[0];
  523. }
  524. #if NVIC_NUM_INTERRUPTS > 32
  525. if (interruptMasksUsed & 0x02) {
  526. NVIC_ISER1 = interruptSave[1];
  527. }
  528. #endif
  529. #if NVIC_NUM_INTERRUPTS > 64 && defined(NVIC_ISER2)
  530. if (interruptMasksUsed & 0x04) {
  531. NVIC_ISER2 = interruptSave[2];
  532. }
  533. #endif
  534. #if NVIC_NUM_INTERRUPTS > 96 && defined(NVIC_ISER3)
  535. if (interruptMasksUsed & 0x08) {
  536. NVIC_ISER3 = interruptSave[3];
  537. }
  538. #endif
  539. }
  540. }
  541. // Disable the SPI bus
  542. void end();
  543. // This function is deprecated. New applications should use
  544. // beginTransaction() to configure SPI settings.
  545. void setBitOrder(uint8_t bitOrder);
  546. // This function is deprecated. New applications should use
  547. // beginTransaction() to configure SPI settings.
  548. void setDataMode(uint8_t dataMode);
  549. // This function is deprecated. New applications should use
  550. // beginTransaction() to configure SPI settings.
  551. void setClockDivider(uint8_t clockDiv) {
  552. if (clockDiv == SPI_CLOCK_DIV2) {
  553. setClockDivider_noInline(SPISettings(12000000, MSBFIRST, SPI_MODE0).ctar);
  554. } else if (clockDiv == SPI_CLOCK_DIV4) {
  555. setClockDivider_noInline(SPISettings(4000000, MSBFIRST, SPI_MODE0).ctar);
  556. } else if (clockDiv == SPI_CLOCK_DIV8) {
  557. setClockDivider_noInline(SPISettings(2000000, MSBFIRST, SPI_MODE0).ctar);
  558. } else if (clockDiv == SPI_CLOCK_DIV16) {
  559. setClockDivider_noInline(SPISettings(1000000, MSBFIRST, SPI_MODE0).ctar);
  560. } else if (clockDiv == SPI_CLOCK_DIV32) {
  561. setClockDivider_noInline(SPISettings(500000, MSBFIRST, SPI_MODE0).ctar);
  562. } else if (clockDiv == SPI_CLOCK_DIV64) {
  563. setClockDivider_noInline(SPISettings(250000, MSBFIRST, SPI_MODE0).ctar);
  564. } else { /* clockDiv == SPI_CLOCK_DIV128 */
  565. setClockDivider_noInline(SPISettings(125000, MSBFIRST, SPI_MODE0).ctar);
  566. }
  567. }
  568. void setClockDivider_noInline(uint32_t clk);
  569. // These undocumented functions should not be used. SPI.transfer()
  570. // polls the hardware flag which is automatically cleared as the
  571. // AVR responds to SPI's interrupt
  572. void attachInterrupt() { }
  573. void detachInterrupt() { }
  574. // Teensy 3.x can use alternate pins for these 3 SPI signals.
  575. void setMOSI(uint8_t pin);
  576. void setMISO(uint8_t pin);
  577. void setSCK(uint8_t pin);
  578. // return true if "pin" has special chip select capability
  579. uint8_t pinIsChipSelect(uint8_t pin);
  580. bool pinIsMOSI(uint8_t pin);
  581. bool pinIsMISO(uint8_t pin);
  582. bool pinIsSCK(uint8_t pin);
  583. // return true if both pin1 and pin2 have independent chip select capability
  584. bool pinIsChipSelect(uint8_t pin1, uint8_t pin2);
  585. // configure a pin for chip select and return its SPI_MCR_PCSIS bitmask
  586. // setCS() is a special function, not intended for use from normal Arduino
  587. // programs/sketches. See the ILI3941_t3 library for an example.
  588. uint8_t setCS(uint8_t pin);
  589. private:
  590. KINETISK_SPI_t & port() { return *(KINETISK_SPI_t *)port_addr; }
  591. const SPI_Hardware_t & hardware() { return *(const SPI_Hardware_t *)hardware_addr; }
  592. void updateCTAR(uint32_t ctar);
  593. uintptr_t port_addr;
  594. uintptr_t hardware_addr;
  595. uint8_t miso_pin_index = 0;
  596. uint8_t mosi_pin_index = 0;
  597. uint8_t sck_pin_index = 0;
  598. uint8_t interruptMasksUsed = 0;
  599. uint32_t interruptMask[(NVIC_NUM_INTERRUPTS+31)/32] = {};
  600. uint32_t interruptSave[(NVIC_NUM_INTERRUPTS+31)/32] = {};
  601. #ifdef SPI_TRANSACTION_MISMATCH_LED
  602. uint8_t inTransactionFlag = 0;
  603. #endif
  604. uint8_t _transferWriteFill = 0;
  605. // DMA Support
  606. #ifdef SPI_HAS_TRANSFER_ASYNC
  607. bool initDMAChannels();
  608. DMAState _dma_state = DMAState::notAllocated;
  609. uint32_t _dma_count_remaining = 0; // How many bytes left to output after current DMA completes
  610. DMAChannel *_dmaTX = nullptr;
  611. DMAChannel *_dmaRX = nullptr;
  612. EventResponder *_dma_event_responder = nullptr;
  613. #endif
  614. };
  615. /**********************************************************/
  616. /* 32 bit Teensy-LC */
  617. /**********************************************************/
  618. #elif defined(__arm__) && defined(TEENSYDUINO) && defined(KINETISL)
  619. class SPISettings {
  620. public:
  621. SPISettings(uint32_t clock, uint8_t bitOrder, uint8_t dataMode) {
  622. if (__builtin_constant_p(clock)) {
  623. init_AlwaysInline(clock, bitOrder, dataMode);
  624. } else {
  625. init_MightInline(clock, bitOrder, dataMode);
  626. }
  627. }
  628. SPISettings() {
  629. init_AlwaysInline(4000000, MSBFIRST, SPI_MODE0);
  630. }
  631. private:
  632. void init_MightInline(uint32_t clock, uint8_t bitOrder, uint8_t dataMode) {
  633. init_AlwaysInline(clock, bitOrder, dataMode);
  634. }
  635. void init_AlwaysInline(uint32_t clock, uint8_t bitOrder, uint8_t dataMode)
  636. __attribute__((__always_inline__)) {
  637. uint8_t c = SPI_C1_MSTR | SPI_C1_SPE;
  638. if (dataMode & 0x04) c |= SPI_C1_CPHA;
  639. if (dataMode & 0x08) c |= SPI_C1_CPOL;
  640. if (bitOrder == LSBFIRST) c |= SPI_C1_LSBFE;
  641. c1 = c;
  642. if (__builtin_constant_p(clock)) {
  643. if (clock >= F_BUS / 2) { c = SPI_BR_SPPR(0) | SPI_BR_SPR(0);
  644. } else if (clock >= F_BUS / 4) { c = SPI_BR_SPPR(1) | SPI_BR_SPR(0);
  645. } else if (clock >= F_BUS / 6) { c = SPI_BR_SPPR(2) | SPI_BR_SPR(0);
  646. } else if (clock >= F_BUS / 8) { c = SPI_BR_SPPR(3) | SPI_BR_SPR(0);
  647. } else if (clock >= F_BUS / 10) { c = SPI_BR_SPPR(4) | SPI_BR_SPR(0);
  648. } else if (clock >= F_BUS / 12) { c = SPI_BR_SPPR(5) | SPI_BR_SPR(0);
  649. } else if (clock >= F_BUS / 14) { c = SPI_BR_SPPR(6) | SPI_BR_SPR(0);
  650. } else if (clock >= F_BUS / 16) { c = SPI_BR_SPPR(7) | SPI_BR_SPR(0);
  651. } else if (clock >= F_BUS / 20) { c = SPI_BR_SPPR(4) | SPI_BR_SPR(1);
  652. } else if (clock >= F_BUS / 24) { c = SPI_BR_SPPR(5) | SPI_BR_SPR(1);
  653. } else if (clock >= F_BUS / 28) { c = SPI_BR_SPPR(6) | SPI_BR_SPR(1);
  654. } else if (clock >= F_BUS / 32) { c = SPI_BR_SPPR(7) | SPI_BR_SPR(1);
  655. } else if (clock >= F_BUS / 40) { c = SPI_BR_SPPR(4) | SPI_BR_SPR(2);
  656. } else if (clock >= F_BUS / 48) { c = SPI_BR_SPPR(5) | SPI_BR_SPR(2);
  657. } else if (clock >= F_BUS / 56) { c = SPI_BR_SPPR(6) | SPI_BR_SPR(2);
  658. } else if (clock >= F_BUS / 64) { c = SPI_BR_SPPR(7) | SPI_BR_SPR(2);
  659. } else if (clock >= F_BUS / 80) { c = SPI_BR_SPPR(4) | SPI_BR_SPR(3);
  660. } else if (clock >= F_BUS / 96) { c = SPI_BR_SPPR(5) | SPI_BR_SPR(3);
  661. } else if (clock >= F_BUS / 112) { c = SPI_BR_SPPR(6) | SPI_BR_SPR(3);
  662. } else if (clock >= F_BUS / 128) { c = SPI_BR_SPPR(7) | SPI_BR_SPR(3);
  663. } else if (clock >= F_BUS / 160) { c = SPI_BR_SPPR(4) | SPI_BR_SPR(4);
  664. } else if (clock >= F_BUS / 192) { c = SPI_BR_SPPR(5) | SPI_BR_SPR(4);
  665. } else if (clock >= F_BUS / 224) { c = SPI_BR_SPPR(6) | SPI_BR_SPR(4);
  666. } else if (clock >= F_BUS / 256) { c = SPI_BR_SPPR(7) | SPI_BR_SPR(4);
  667. } else if (clock >= F_BUS / 320) { c = SPI_BR_SPPR(4) | SPI_BR_SPR(5);
  668. } else if (clock >= F_BUS / 384) { c = SPI_BR_SPPR(5) | SPI_BR_SPR(5);
  669. } else if (clock >= F_BUS / 448) { c = SPI_BR_SPPR(6) | SPI_BR_SPR(5);
  670. } else if (clock >= F_BUS / 512) { c = SPI_BR_SPPR(7) | SPI_BR_SPR(5);
  671. } else if (clock >= F_BUS / 640) { c = SPI_BR_SPPR(4) | SPI_BR_SPR(6);
  672. } else /* F_BUS / 768 */ { c = SPI_BR_SPPR(5) | SPI_BR_SPR(6);
  673. }
  674. } else {
  675. for (uint32_t i=0; i<30; i++) {
  676. c = br_clock_table[i];
  677. if (clock >= F_BUS / br_div_table[i]) break;
  678. }
  679. }
  680. br[0] = c;
  681. if (__builtin_constant_p(clock)) {
  682. if (clock >= (F_PLL/2) / 2) { c = SPI_BR_SPPR(0) | SPI_BR_SPR(0);
  683. } else if (clock >= (F_PLL/2) / 4) { c = SPI_BR_SPPR(1) | SPI_BR_SPR(0);
  684. } else if (clock >= (F_PLL/2) / 6) { c = SPI_BR_SPPR(2) | SPI_BR_SPR(0);
  685. } else if (clock >= (F_PLL/2) / 8) { c = SPI_BR_SPPR(3) | SPI_BR_SPR(0);
  686. } else if (clock >= (F_PLL/2) / 10) { c = SPI_BR_SPPR(4) | SPI_BR_SPR(0);
  687. } else if (clock >= (F_PLL/2) / 12) { c = SPI_BR_SPPR(5) | SPI_BR_SPR(0);
  688. } else if (clock >= (F_PLL/2) / 14) { c = SPI_BR_SPPR(6) | SPI_BR_SPR(0);
  689. } else if (clock >= (F_PLL/2) / 16) { c = SPI_BR_SPPR(7) | SPI_BR_SPR(0);
  690. } else if (clock >= (F_PLL/2) / 20) { c = SPI_BR_SPPR(4) | SPI_BR_SPR(1);
  691. } else if (clock >= (F_PLL/2) / 24) { c = SPI_BR_SPPR(5) | SPI_BR_SPR(1);
  692. } else if (clock >= (F_PLL/2) / 28) { c = SPI_BR_SPPR(6) | SPI_BR_SPR(1);
  693. } else if (clock >= (F_PLL/2) / 32) { c = SPI_BR_SPPR(7) | SPI_BR_SPR(1);
  694. } else if (clock >= (F_PLL/2) / 40) { c = SPI_BR_SPPR(4) | SPI_BR_SPR(2);
  695. } else if (clock >= (F_PLL/2) / 48) { c = SPI_BR_SPPR(5) | SPI_BR_SPR(2);
  696. } else if (clock >= (F_PLL/2) / 56) { c = SPI_BR_SPPR(6) | SPI_BR_SPR(2);
  697. } else if (clock >= (F_PLL/2) / 64) { c = SPI_BR_SPPR(7) | SPI_BR_SPR(2);
  698. } else if (clock >= (F_PLL/2) / 80) { c = SPI_BR_SPPR(4) | SPI_BR_SPR(3);
  699. } else if (clock >= (F_PLL/2) / 96) { c = SPI_BR_SPPR(5) | SPI_BR_SPR(3);
  700. } else if (clock >= (F_PLL/2) / 112) { c = SPI_BR_SPPR(6) | SPI_BR_SPR(3);
  701. } else if (clock >= (F_PLL/2) / 128) { c = SPI_BR_SPPR(7) | SPI_BR_SPR(3);
  702. } else if (clock >= (F_PLL/2) / 160) { c = SPI_BR_SPPR(4) | SPI_BR_SPR(4);
  703. } else if (clock >= (F_PLL/2) / 192) { c = SPI_BR_SPPR(5) | SPI_BR_SPR(4);
  704. } else if (clock >= (F_PLL/2) / 224) { c = SPI_BR_SPPR(6) | SPI_BR_SPR(4);
  705. } else if (clock >= (F_PLL/2) / 256) { c = SPI_BR_SPPR(7) | SPI_BR_SPR(4);
  706. } else if (clock >= (F_PLL/2) / 320) { c = SPI_BR_SPPR(4) | SPI_BR_SPR(5);
  707. } else if (clock >= (F_PLL/2) / 384) { c = SPI_BR_SPPR(5) | SPI_BR_SPR(5);
  708. } else if (clock >= (F_PLL/2) / 448) { c = SPI_BR_SPPR(6) | SPI_BR_SPR(5);
  709. } else if (clock >= (F_PLL/2) / 512) { c = SPI_BR_SPPR(7) | SPI_BR_SPR(5);
  710. } else if (clock >= (F_PLL/2) / 640) { c = SPI_BR_SPPR(4) | SPI_BR_SPR(6);
  711. } else /* (F_PLL/2) / 768 */ { c = SPI_BR_SPPR(5) | SPI_BR_SPR(6);
  712. }
  713. } else {
  714. for (uint32_t i=0; i<30; i++) {
  715. c = br_clock_table[i];
  716. if (clock >= (F_PLL/2) / br_div_table[i]) break;
  717. }
  718. }
  719. br[1] = c;
  720. }
  721. static const uint8_t br_clock_table[30];
  722. static const uint16_t br_div_table[30];
  723. uint8_t c1, br[2];
  724. friend class SPIClass;
  725. };
  726. class SPIClass { // Teensy-LC
  727. public:
  728. static const uint8_t CNT_MISO_PINS = 2;
  729. static const uint8_t CNT_MMOSI_PINS = 2;
  730. static const uint8_t CNT_SCK_PINS = 2;
  731. static const uint8_t CNT_CS_PINS = 2;
  732. typedef struct {
  733. volatile uint32_t &clock_gate_register;
  734. uint32_t clock_gate_mask;
  735. uint8_t br_index;
  736. uint8_t tx_dma_channel;
  737. uint8_t rx_dma_channel;
  738. void (*dma_isr)();
  739. uint8_t miso_pin[CNT_MISO_PINS];
  740. uint32_t miso_mux[CNT_MISO_PINS];
  741. uint8_t mosi_pin[CNT_MMOSI_PINS];
  742. uint32_t mosi_mux[CNT_MMOSI_PINS];
  743. uint8_t sck_pin[CNT_SCK_PINS];
  744. uint32_t sck_mux[CNT_SCK_PINS];
  745. uint8_t cs_pin[CNT_CS_PINS];
  746. uint32_t cs_mux[CNT_CS_PINS];
  747. uint8_t cs_mask[CNT_CS_PINS];
  748. } SPI_Hardware_t;
  749. static const SPI_Hardware_t spi0_hardware;
  750. static const SPI_Hardware_t spi1_hardware;
  751. enum DMAState { notAllocated, idle, active, completed};
  752. public:
  753. constexpr SPIClass(uintptr_t myport, uintptr_t myhardware)
  754. : port_addr(myport), hardware_addr(myhardware) {
  755. }
  756. // Initialize the SPI library
  757. void begin();
  758. // If SPI is to used from within an interrupt, this function registers
  759. // that interrupt with the SPI library, so beginTransaction() can
  760. // prevent conflicts. The input interruptNumber is the number used
  761. // with attachInterrupt. If SPI is used from a different interrupt
  762. // (eg, a timer), interruptNumber should be 255.
  763. void usingInterrupt(uint8_t n) {
  764. if (n == 3 || n == 4) {
  765. usingInterrupt(IRQ_PORTA);
  766. } else if ((n >= 2 && n <= 15) || (n >= 20 && n <= 23)) {
  767. usingInterrupt(IRQ_PORTCD);
  768. }
  769. }
  770. void usingInterrupt(IRQ_NUMBER_t interruptName) {
  771. uint32_t n = (uint32_t)interruptName;
  772. if (n < NVIC_NUM_INTERRUPTS) interruptMask |= (1 << n);
  773. }
  774. void notUsingInterrupt(IRQ_NUMBER_t interruptName) {
  775. uint32_t n = (uint32_t)interruptName;
  776. if (n < NVIC_NUM_INTERRUPTS) interruptMask &= ~(1 << n);
  777. }
  778. // Before using SPI.transfer() or asserting chip select pins,
  779. // this function is used to gain exclusive access to the SPI bus
  780. // and configure the correct settings.
  781. void beginTransaction(SPISettings settings) {
  782. if (interruptMask) {
  783. __disable_irq();
  784. interruptSave = NVIC_ICER0 & interruptMask;
  785. NVIC_ICER0 = interruptSave;
  786. __enable_irq();
  787. }
  788. #ifdef SPI_TRANSACTION_MISMATCH_LED
  789. if (inTransactionFlag) {
  790. pinMode(SPI_TRANSACTION_MISMATCH_LED, OUTPUT);
  791. digitalWrite(SPI_TRANSACTION_MISMATCH_LED, HIGH);
  792. }
  793. inTransactionFlag = 1;
  794. #endif
  795. port().C1 = settings.c1;
  796. port().BR = settings.br[hardware().br_index];
  797. }
  798. // Write to the SPI bus (MOSI pin) and also receive (MISO pin)
  799. uint8_t transfer(uint8_t data) {
  800. port().DL = data;
  801. while (!(port().S & SPI_S_SPRF)) ; // wait
  802. return port().DL;
  803. }
  804. uint16_t transfer16(uint16_t data) {
  805. port().C2 = SPI_C2_SPIMODE;
  806. port().S;
  807. port().DL = data;
  808. port().DH = data >> 8;
  809. while (!(port().S & SPI_S_SPRF)) ; // wait
  810. uint16_t r = port().DL | (port().DH << 8);
  811. port().C2 = 0;
  812. port().S;
  813. return r;
  814. }
  815. void transfer(void *buf, size_t count) {
  816. if (count == 0) return;
  817. uint8_t *p = (uint8_t *)buf;
  818. while (!(port().S & SPI_S_SPTEF)) ; // wait
  819. port().DL = *p;
  820. while (--count > 0) {
  821. uint8_t out = *(p + 1);
  822. while (!(port().S & SPI_S_SPTEF)) ; // wait
  823. __disable_irq();
  824. port().DL = out;
  825. while (!(port().S & SPI_S_SPRF)) ; // wait
  826. uint8_t in = port().DL;
  827. __enable_irq();
  828. *p++ = in;
  829. }
  830. while (!(port().S & SPI_S_SPRF)) ; // wait
  831. *p = port().DL;
  832. }
  833. void setTransferWriteFill(uint8_t ch ) {_transferWriteFill = ch;}
  834. void transfer(const void * buf, void * retbuf, size_t count);
  835. // Asynch support (DMA )
  836. #ifdef SPI_HAS_TRANSFER_ASYNC
  837. bool transfer(const void *txBuffer, void *rxBuffer, size_t count, EventResponderRef event_responder);
  838. friend void _spi_dma_rxISR0(void);
  839. friend void _spi_dma_rxISR1(void);
  840. inline void dma_isr(void);
  841. #endif
  842. // After performing a group of transfers and releasing the chip select
  843. // signal, this function allows others to access the SPI bus
  844. void endTransaction(void) {
  845. #ifdef SPI_TRANSACTION_MISMATCH_LED
  846. if (!inTransactionFlag) {
  847. pinMode(SPI_TRANSACTION_MISMATCH_LED, OUTPUT);
  848. digitalWrite(SPI_TRANSACTION_MISMATCH_LED, HIGH);
  849. }
  850. inTransactionFlag = 0;
  851. #endif
  852. if (interruptMask) {
  853. NVIC_ISER0 = interruptSave;
  854. }
  855. }
  856. // Disable the SPI bus
  857. void end();
  858. // This function is deprecated. New applications should use
  859. // beginTransaction() to configure SPI settings.
  860. void setBitOrder(uint8_t bitOrder) {
  861. uint8_t c = port().C1 | SPI_C1_SPE;
  862. if (bitOrder == LSBFIRST) c |= SPI_C1_LSBFE;
  863. else c &= ~SPI_C1_LSBFE;
  864. port().C1 = c;
  865. }
  866. // This function is deprecated. New applications should use
  867. // beginTransaction() to configure SPI settings.
  868. void setDataMode(uint8_t dataMode) {
  869. uint8_t c = port().C1 | SPI_C1_SPE;
  870. if (dataMode & 0x04) c |= SPI_C1_CPHA;
  871. else c &= ~SPI_C1_CPHA;
  872. if (dataMode & 0x08) c |= SPI_C1_CPOL;
  873. else c &= ~SPI_C1_CPOL;
  874. port().C1 = c;
  875. }
  876. // This function is deprecated. New applications should use
  877. // beginTransaction() to configure SPI settings.
  878. void setClockDivider(uint8_t clockDiv) {
  879. unsigned int i = hardware().br_index;
  880. if (clockDiv == SPI_CLOCK_DIV2) {
  881. port().BR = (SPISettings(12000000, MSBFIRST, SPI_MODE0).br[i]);
  882. } else if (clockDiv == SPI_CLOCK_DIV4) {
  883. port().BR = (SPISettings(4000000, MSBFIRST, SPI_MODE0).br[i]);
  884. } else if (clockDiv == SPI_CLOCK_DIV8) {
  885. port().BR = (SPISettings(2000000, MSBFIRST, SPI_MODE0).br[i]);
  886. } else if (clockDiv == SPI_CLOCK_DIV16) {
  887. port().BR = (SPISettings(1000000, MSBFIRST, SPI_MODE0).br[i]);
  888. } else if (clockDiv == SPI_CLOCK_DIV32) {
  889. port().BR = (SPISettings(500000, MSBFIRST, SPI_MODE0).br[i]);
  890. } else if (clockDiv == SPI_CLOCK_DIV64) {
  891. port().BR = (SPISettings(250000, MSBFIRST, SPI_MODE0).br[i]);
  892. } else { /* clockDiv == SPI_CLOCK_DIV128 */
  893. port().BR = (SPISettings(125000, MSBFIRST, SPI_MODE0).br[i]);
  894. }
  895. }
  896. // These undocumented functions should not be used. SPI.transfer()
  897. // polls the hardware flag which is automatically cleared as the
  898. // AVR responds to SPI's interrupt
  899. void attachInterrupt() { }
  900. void detachInterrupt() { }
  901. // Teensy LC can use alternate pins for these 3 SPI signals.
  902. void setMOSI(uint8_t pin);
  903. void setMISO(uint8_t pin);
  904. void setSCK(uint8_t pin);
  905. // return true if "pin" has special chip select capability
  906. bool pinIsChipSelect(uint8_t pin);
  907. bool pinIsMOSI(uint8_t pin);
  908. bool pinIsMISO(uint8_t pin);
  909. bool pinIsSCK(uint8_t pin);
  910. // return true if both pin1 and pin2 have independent chip select capability
  911. bool pinIsChipSelect(uint8_t pin1, uint8_t pin2) { return false; }
  912. // configure a pin for chip select and return its SPI_MCR_PCSIS bitmask
  913. // setCS() is a special function, not intended for use from normal Arduino
  914. // programs/sketches. See the ILI3941_t3 library for an example.
  915. uint8_t setCS(uint8_t pin);
  916. private:
  917. KINETISL_SPI_t & port() { return *(KINETISL_SPI_t *)port_addr; }
  918. const SPI_Hardware_t & hardware() { return *(const SPI_Hardware_t *)hardware_addr; }
  919. uintptr_t port_addr;
  920. uintptr_t hardware_addr;
  921. uint32_t interruptMask = 0;
  922. uint32_t interruptSave = 0;
  923. uint8_t mosi_pin_index = 0;
  924. uint8_t miso_pin_index = 0;
  925. uint8_t sck_pin_index = 0;
  926. #ifdef SPI_TRANSACTION_MISMATCH_LED
  927. uint8_t inTransactionFlag = 0;
  928. #endif
  929. uint8_t _transferWriteFill = 0;
  930. #ifdef SPI_HAS_TRANSFER_ASYNC
  931. // DMA Support
  932. bool initDMAChannels();
  933. DMAState _dma_state = DMAState::notAllocated;
  934. uint32_t _dma_count_remaining = 0; // How many bytes left to output after current DMA completes
  935. DMAChannel *_dmaTX = nullptr;
  936. DMAChannel *_dmaRX = nullptr;
  937. EventResponder *_dma_event_responder = nullptr;
  938. #endif
  939. };
  940. #endif
  941. extern SPIClass SPI;
  942. #if defined(__MKL26Z64__)
  943. extern SPIClass SPI1;
  944. #endif
  945. #if defined(__MK64FX512__) || defined(__MK66FX1M0__)
  946. extern SPIClass SPI1;
  947. extern SPIClass SPI2;
  948. #endif
  949. #endif