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