Nevar pievienot vairāk kā 25 tēmas Tēmai ir jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un var būt līdz 35 simboliem gara.

pirms 10 gadiem
pirms 10 gadiem
pirms 10 gadiem
pirms 10 gadiem
pirms 10 gadiem
pirms 10 gadiem
pirms 10 gadiem
pirms 10 gadiem
pirms 10 gadiem
pirms 10 gadiem
pirms 8 gadiem
pirms 10 gadiem
pirms 10 gadiem
pirms 10 gadiem
pirms 10 gadiem
pirms 10 gadiem
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113
  1. /*
  2. * Copyright (c) 2010 by Cristian Maglie <c.maglie@bug.st>
  3. * SPI Master library for arduino.
  4. *
  5. * This file is free software; you can redistribute it and/or modify
  6. * it under the terms of either the GNU General Public License version 2
  7. * or the GNU Lesser General Public License version 2.1, both as
  8. * published by the Free Software Foundation.
  9. */
  10. #include "SPI.h"
  11. #include "pins_arduino.h"
  12. /**********************************************************/
  13. /* 8 bit AVR-based boards */
  14. /**********************************************************/
  15. #if defined(__AVR__)
  16. SPIClass SPI;
  17. uint8_t SPIClass::interruptMode = 0;
  18. uint8_t SPIClass::interruptMask = 0;
  19. uint8_t SPIClass::interruptSave = 0;
  20. #ifdef SPI_TRANSACTION_MISMATCH_LED
  21. uint8_t SPIClass::inTransactionFlag = 0;
  22. #endif
  23. void SPIClass::begin()
  24. {
  25. // Set SS to high so a connected chip will be "deselected" by default
  26. digitalWrite(SS, HIGH);
  27. // When the SS pin is set as OUTPUT, it can be used as
  28. // a general purpose output port (it doesn't influence
  29. // SPI operations).
  30. pinMode(SS, OUTPUT);
  31. // Warning: if the SS pin ever becomes a LOW INPUT then SPI
  32. // automatically switches to Slave, so the data direction of
  33. // the SS pin MUST be kept as OUTPUT.
  34. SPCR |= _BV(MSTR);
  35. SPCR |= _BV(SPE);
  36. // Set direction register for SCK and MOSI pin.
  37. // MISO pin automatically overrides to INPUT.
  38. // By doing this AFTER enabling SPI, we avoid accidentally
  39. // clocking in a single bit since the lines go directly
  40. // from "input" to SPI control.
  41. // http://code.google.com/p/arduino/issues/detail?id=888
  42. pinMode(SCK, OUTPUT);
  43. pinMode(MOSI, OUTPUT);
  44. }
  45. void SPIClass::end() {
  46. SPCR &= ~_BV(SPE);
  47. }
  48. // mapping of interrupt numbers to bits within SPI_AVR_EIMSK
  49. #if defined(__AVR_ATmega32U4__)
  50. #define SPI_INT0_MASK (1<<INT0)
  51. #define SPI_INT1_MASK (1<<INT1)
  52. #define SPI_INT2_MASK (1<<INT2)
  53. #define SPI_INT3_MASK (1<<INT3)
  54. #define SPI_INT4_MASK (1<<INT6)
  55. #elif defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__)
  56. #define SPI_INT0_MASK (1<<INT0)
  57. #define SPI_INT1_MASK (1<<INT1)
  58. #define SPI_INT2_MASK (1<<INT2)
  59. #define SPI_INT3_MASK (1<<INT3)
  60. #define SPI_INT4_MASK (1<<INT4)
  61. #define SPI_INT5_MASK (1<<INT5)
  62. #define SPI_INT6_MASK (1<<INT6)
  63. #define SPI_INT7_MASK (1<<INT7)
  64. #elif defined(EICRA) && defined(EICRB) && defined(EIMSK)
  65. #define SPI_INT0_MASK (1<<INT4)
  66. #define SPI_INT1_MASK (1<<INT5)
  67. #define SPI_INT2_MASK (1<<INT0)
  68. #define SPI_INT3_MASK (1<<INT1)
  69. #define SPI_INT4_MASK (1<<INT2)
  70. #define SPI_INT5_MASK (1<<INT3)
  71. #define SPI_INT6_MASK (1<<INT6)
  72. #define SPI_INT7_MASK (1<<INT7)
  73. #else
  74. #ifdef INT0
  75. #define SPI_INT0_MASK (1<<INT0)
  76. #endif
  77. #ifdef INT1
  78. #define SPI_INT1_MASK (1<<INT1)
  79. #endif
  80. #ifdef INT2
  81. #define SPI_INT2_MASK (1<<INT2)
  82. #endif
  83. #endif
  84. void SPIClass::usingInterrupt(uint8_t interruptNumber)
  85. {
  86. uint8_t stmp, mask;
  87. if (interruptMode > 1) return;
  88. stmp = SREG;
  89. noInterrupts();
  90. switch (interruptNumber) {
  91. #ifdef SPI_INT0_MASK
  92. case 0: mask = SPI_INT0_MASK; break;
  93. #endif
  94. #ifdef SPI_INT1_MASK
  95. case 1: mask = SPI_INT1_MASK; break;
  96. #endif
  97. #ifdef SPI_INT2_MASK
  98. case 2: mask = SPI_INT2_MASK; break;
  99. #endif
  100. #ifdef SPI_INT3_MASK
  101. case 3: mask = SPI_INT3_MASK; break;
  102. #endif
  103. #ifdef SPI_INT4_MASK
  104. case 4: mask = SPI_INT4_MASK; break;
  105. #endif
  106. #ifdef SPI_INT5_MASK
  107. case 5: mask = SPI_INT5_MASK; break;
  108. #endif
  109. #ifdef SPI_INT6_MASK
  110. case 6: mask = SPI_INT6_MASK; break;
  111. #endif
  112. #ifdef SPI_INT7_MASK
  113. case 7: mask = SPI_INT7_MASK; break;
  114. #endif
  115. default:
  116. interruptMode = 2;
  117. SREG = stmp;
  118. return;
  119. }
  120. interruptMode = 1;
  121. interruptMask |= mask;
  122. SREG = stmp;
  123. }
  124. /**********************************************************/
  125. /* 32 bit Teensy 3.0 and 3.1 */
  126. /**********************************************************/
  127. #elif defined(__arm__) && defined(TEENSYDUINO) && defined(KINETISK)
  128. SPIClass SPI;
  129. uint8_t SPIClass::interruptMasksUsed = 0;
  130. uint32_t SPIClass::interruptMask[(NVIC_NUM_INTERRUPTS+31)/32];
  131. uint32_t SPIClass::interruptSave[(NVIC_NUM_INTERRUPTS+31)/32];
  132. #ifdef SPI_TRANSACTION_MISMATCH_LED
  133. uint8_t SPIClass::inTransactionFlag = 0;
  134. #endif
  135. void SPIClass::begin()
  136. {
  137. SIM_SCGC6 |= SIM_SCGC6_SPI0;
  138. SPI0_MCR = SPI_MCR_MDIS | SPI_MCR_HALT | SPI_MCR_PCSIS(0x1F);
  139. SPI0_CTAR0 = SPI_CTAR_FMSZ(7) | SPI_CTAR_PBR(0) | SPI_CTAR_BR(1) | SPI_CTAR_CSSCK(1);
  140. SPI0_CTAR1 = SPI_CTAR_FMSZ(15) | SPI_CTAR_PBR(0) | SPI_CTAR_BR(1) | SPI_CTAR_CSSCK(1);
  141. SPI0_MCR = SPI_MCR_MSTR | SPI_MCR_PCSIS(0x1F);
  142. SPCR.enable_pins(); // pins managed by SPCRemulation in avr_emulation.h
  143. }
  144. void SPIClass::end() {
  145. SPCR.disable_pins();
  146. SPI0_MCR = SPI_MCR_MDIS | SPI_MCR_HALT | SPI_MCR_PCSIS(0x1F);
  147. }
  148. void SPIClass::usingInterrupt(IRQ_NUMBER_t interruptName)
  149. {
  150. uint32_t n = (uint32_t)interruptName;
  151. if (n >= NVIC_NUM_INTERRUPTS) return;
  152. //Serial.print("usingInterrupt ");
  153. //Serial.println(n);
  154. interruptMasksUsed |= (1 << (n >> 5));
  155. interruptMask[n >> 5] |= (1 << (n & 0x1F));
  156. //Serial.printf("interruptMasksUsed = %d\n", interruptMasksUsed);
  157. //Serial.printf("interruptMask[0] = %08X\n", interruptMask[0]);
  158. //Serial.printf("interruptMask[1] = %08X\n", interruptMask[1]);
  159. //Serial.printf("interruptMask[2] = %08X\n", interruptMask[2]);
  160. }
  161. void SPIClass::notUsingInterrupt(IRQ_NUMBER_t interruptName)
  162. {
  163. uint32_t n = (uint32_t)interruptName;
  164. if (n >= NVIC_NUM_INTERRUPTS) return;
  165. interruptMask[n >> 5] &= ~(1 << (n & 0x1F));
  166. if (interruptMask[n >> 5] == 0) {
  167. interruptMasksUsed &= ~(1 << (n >> 5));
  168. }
  169. }
  170. const uint16_t SPISettings::ctar_div_table[23] = {
  171. 2, 3, 4, 5, 6, 8, 10, 12, 16, 20, 24, 32, 40,
  172. 56, 64, 96, 128, 192, 256, 384, 512, 640, 768
  173. };
  174. const uint32_t SPISettings::ctar_clock_table[23] = {
  175. SPI_CTAR_PBR(0) | SPI_CTAR_BR(0) | SPI_CTAR_DBR | SPI_CTAR_CSSCK(0),
  176. SPI_CTAR_PBR(1) | SPI_CTAR_BR(0) | SPI_CTAR_DBR | SPI_CTAR_CSSCK(0),
  177. SPI_CTAR_PBR(0) | SPI_CTAR_BR(0) | SPI_CTAR_CSSCK(0),
  178. SPI_CTAR_PBR(2) | SPI_CTAR_BR(0) | SPI_CTAR_DBR | SPI_CTAR_CSSCK(0),
  179. SPI_CTAR_PBR(1) | SPI_CTAR_BR(0) | SPI_CTAR_CSSCK(0),
  180. SPI_CTAR_PBR(0) | SPI_CTAR_BR(1) | SPI_CTAR_CSSCK(1),
  181. SPI_CTAR_PBR(2) | SPI_CTAR_BR(0) | SPI_CTAR_CSSCK(0),
  182. SPI_CTAR_PBR(1) | SPI_CTAR_BR(1) | SPI_CTAR_CSSCK(1),
  183. SPI_CTAR_PBR(0) | SPI_CTAR_BR(3) | SPI_CTAR_CSSCK(2),
  184. SPI_CTAR_PBR(2) | SPI_CTAR_BR(1) | SPI_CTAR_CSSCK(0),
  185. SPI_CTAR_PBR(1) | SPI_CTAR_BR(3) | SPI_CTAR_CSSCK(2),
  186. SPI_CTAR_PBR(0) | SPI_CTAR_BR(4) | SPI_CTAR_CSSCK(3),
  187. SPI_CTAR_PBR(2) | SPI_CTAR_BR(3) | SPI_CTAR_CSSCK(2),
  188. SPI_CTAR_PBR(3) | SPI_CTAR_BR(3) | SPI_CTAR_CSSCK(2),
  189. SPI_CTAR_PBR(0) | SPI_CTAR_BR(5) | SPI_CTAR_CSSCK(4),
  190. SPI_CTAR_PBR(1) | SPI_CTAR_BR(5) | SPI_CTAR_CSSCK(4),
  191. SPI_CTAR_PBR(0) | SPI_CTAR_BR(6) | SPI_CTAR_CSSCK(5),
  192. SPI_CTAR_PBR(1) | SPI_CTAR_BR(6) | SPI_CTAR_CSSCK(5),
  193. SPI_CTAR_PBR(0) | SPI_CTAR_BR(7) | SPI_CTAR_CSSCK(6),
  194. SPI_CTAR_PBR(1) | SPI_CTAR_BR(7) | SPI_CTAR_CSSCK(6),
  195. SPI_CTAR_PBR(0) | SPI_CTAR_BR(8) | SPI_CTAR_CSSCK(7),
  196. SPI_CTAR_PBR(2) | SPI_CTAR_BR(7) | SPI_CTAR_CSSCK(6),
  197. SPI_CTAR_PBR(1) | SPI_CTAR_BR(8) | SPI_CTAR_CSSCK(7)
  198. };
  199. static void updateCTAR(uint32_t ctar)
  200. {
  201. if (SPI0_CTAR0 != ctar) {
  202. uint32_t mcr = SPI0_MCR;
  203. if (mcr & SPI_MCR_MDIS) {
  204. SPI0_CTAR0 = ctar;
  205. SPI0_CTAR1 = ctar | SPI_CTAR_FMSZ(8);
  206. } else {
  207. SPI0_MCR = SPI_MCR_MDIS | SPI_MCR_HALT | SPI_MCR_PCSIS(0x1F);
  208. SPI0_CTAR0 = ctar;
  209. SPI0_CTAR1 = ctar | SPI_CTAR_FMSZ(8);
  210. SPI0_MCR = mcr;
  211. }
  212. }
  213. }
  214. void SPIClass::setBitOrder(uint8_t bitOrder)
  215. {
  216. SIM_SCGC6 |= SIM_SCGC6_SPI0;
  217. uint32_t ctar = SPI0_CTAR0;
  218. if (bitOrder == LSBFIRST) {
  219. ctar |= SPI_CTAR_LSBFE;
  220. } else {
  221. ctar &= ~SPI_CTAR_LSBFE;
  222. }
  223. updateCTAR(ctar);
  224. }
  225. void SPIClass::setDataMode(uint8_t dataMode)
  226. {
  227. SIM_SCGC6 |= SIM_SCGC6_SPI0;
  228. // TODO: implement with native code
  229. SPCR = (SPCR & ~SPI_MODE_MASK) | dataMode;
  230. }
  231. void SPIClass::setClockDivider_noInline(uint32_t clk)
  232. {
  233. SIM_SCGC6 |= SIM_SCGC6_SPI0;
  234. uint32_t ctar = SPI0_CTAR0;
  235. ctar &= (SPI_CTAR_CPOL | SPI_CTAR_CPHA | SPI_CTAR_LSBFE);
  236. if (ctar & SPI_CTAR_CPHA) {
  237. clk = (clk & 0xFFFF0FFF) | ((clk & 0xF000) >> 4);
  238. }
  239. ctar |= clk;
  240. updateCTAR(ctar);
  241. }
  242. uint8_t SPIClass::pinIsChipSelect(uint8_t pin)
  243. {
  244. switch (pin) {
  245. case 10: return 0x01; // PTC4
  246. case 2: return 0x01; // PTD0
  247. case 9: return 0x02; // PTC3
  248. case 6: return 0x02; // PTD4
  249. case 20: return 0x04; // PTD5
  250. case 23: return 0x04; // PTC2
  251. case 21: return 0x08; // PTD6
  252. case 22: return 0x08; // PTC1
  253. case 15: return 0x10; // PTC0
  254. #if defined(__MK64FX512__) || defined(__MK66FX1M0__)
  255. case 26: return 0x01;
  256. case 45: return 0x20; // CS5
  257. #endif
  258. }
  259. return 0;
  260. }
  261. bool SPIClass::pinIsChipSelect(uint8_t pin1, uint8_t pin2)
  262. {
  263. uint8_t pin1_mask, pin2_mask;
  264. if ((pin1_mask = (uint8_t)pinIsChipSelect(pin1)) == 0) return false;
  265. if ((pin2_mask = (uint8_t)pinIsChipSelect(pin2)) == 0) return false;
  266. //Serial.printf("pinIsChipSelect %d %d %x %x\n\r", pin1, pin2, pin1_mask, pin2_mask);
  267. if ((pin1_mask & pin2_mask) != 0) return false;
  268. return true;
  269. }
  270. // setCS() is not intended for use from normal Arduino programs/sketches.
  271. uint8_t SPIClass::setCS(uint8_t pin)
  272. {
  273. switch (pin) {
  274. case 10: CORE_PIN10_CONFIG = PORT_PCR_MUX(2); return 0x01; // PTC4
  275. case 2: CORE_PIN2_CONFIG = PORT_PCR_MUX(2); return 0x01; // PTD0
  276. case 9: CORE_PIN9_CONFIG = PORT_PCR_MUX(2); return 0x02; // PTC3
  277. case 6: CORE_PIN6_CONFIG = PORT_PCR_MUX(2); return 0x02; // PTD4
  278. case 20: CORE_PIN20_CONFIG = PORT_PCR_MUX(2); return 0x04; // PTD5
  279. case 23: CORE_PIN23_CONFIG = PORT_PCR_MUX(2); return 0x04; // PTC2
  280. case 21: CORE_PIN21_CONFIG = PORT_PCR_MUX(2); return 0x08; // PTD6
  281. case 22: CORE_PIN22_CONFIG = PORT_PCR_MUX(2); return 0x08; // PTC1
  282. case 15: CORE_PIN15_CONFIG = PORT_PCR_MUX(2); return 0x10; // PTC0
  283. #if defined(__MK64FX512__) || defined(__MK66FX1M0__)
  284. case 26: CORE_PIN26_CONFIG = PORT_PCR_MUX(2);return 0x01;
  285. case 45: CORE_PIN45_CONFIG = PORT_PCR_MUX(3);return 0x20;
  286. #endif
  287. }
  288. return 0;
  289. }
  290. void SPIClass::transfer(void *buf, size_t count) {
  291. if (count == 0) return;
  292. uint8_t *p_write = (uint8_t *)buf;
  293. uint8_t *p_read = p_write;
  294. size_t count_read = count;
  295. // Lets clear the reader queue
  296. SPI0_MCR = SPI_MCR_MSTR | SPI_MCR_CLR_RXF | SPI_MCR_PCSIS(0x1F);
  297. uint32_t sr;
  298. // Now lets loop while we still have data to output
  299. if (count & 1) {
  300. if (count > 1)
  301. KINETISK_SPI0.PUSHR = *p_write++ | SPI_PUSHR_CONT | SPI_PUSHR_CTAS(0);
  302. else
  303. KINETISK_SPI0.PUSHR = *p_write++ | SPI_PUSHR_CTAS(0);
  304. count--;
  305. }
  306. while (count > 0) {
  307. // Push out the next byte;
  308. uint16_t w = (*p_write++) << 8;
  309. w |= *p_write++;
  310. if (count == 2)
  311. KINETISK_SPI0.PUSHR = w | SPI_PUSHR_CTAS(1);
  312. else
  313. KINETISK_SPI0.PUSHR = w | SPI_PUSHR_CONT | SPI_PUSHR_CTAS(1);
  314. count -= 2; // how many bytes to output.
  315. // Make sure queue is not full before pushing next byte out
  316. do {
  317. sr = KINETISK_SPI0.SR;
  318. if (sr & 0xF0) {
  319. uint16_t w = KINETISK_SPI0.POPR; // Read any pending RX bytes in
  320. if (count_read & 1) {
  321. *p_read++ = w; // Read any pending RX bytes in
  322. count_read--;
  323. } else {
  324. *p_read++ = w >> 8;
  325. *p_read++ = (w & 0xff);
  326. count_read -= 2;
  327. }
  328. }
  329. } while ((sr & (15 << 12)) > (3 << 12));
  330. }
  331. // now lets wait for all of the read bytes to be returned...
  332. while (count_read) {
  333. sr = KINETISK_SPI0.SR;
  334. if (sr & 0xF0) {
  335. uint16_t w = KINETISK_SPI0.POPR; // Read any pending RX bytes in
  336. if (count_read & 1) {
  337. *p_read++ = w; // Read any pending RX bytes in
  338. count_read--;
  339. } else {
  340. *p_read++ = w >> 8;
  341. *p_read++ = (w & 0xff);
  342. count_read -= 2;
  343. }
  344. }
  345. }
  346. }
  347. /**********************************************************/
  348. /* 32 bit Teensy-3.5/3.6 */
  349. /**********************************************************/
  350. #if defined(__MK64FX512__) || defined(__MK66FX1M0__)
  351. SPI1Class SPI1;
  352. uint8_t SPI1Class::interruptMasksUsed = 0;
  353. uint32_t SPI1Class::interruptMask[(NVIC_NUM_INTERRUPTS+31)/32];
  354. uint32_t SPI1Class::interruptSave[(NVIC_NUM_INTERRUPTS+31)/32];
  355. #ifdef SPI_TRANSACTION_MISMATCH_LED
  356. uint8_t SPI1Class::inTransactionFlag = 0;
  357. #endif
  358. void SPI1Class::begin()
  359. {
  360. SIM_SCGC6 |= SIM_SCGC6_SPI1;
  361. SPI1_MCR = SPI_MCR_MDIS | SPI_MCR_HALT | SPI_MCR_PCSIS(0x1F);
  362. SPI1_CTAR0 = SPI_CTAR_FMSZ(7) | SPI_CTAR_PBR(0) | SPI_CTAR_BR(1) | SPI_CTAR_CSSCK(1);
  363. SPI1_CTAR1 = SPI_CTAR_FMSZ(15) | SPI_CTAR_PBR(0) | SPI_CTAR_BR(1) | SPI_CTAR_CSSCK(1);
  364. SPI1_MCR = SPI_MCR_MSTR | SPI_MCR_PCSIS(0x1F);
  365. SPCR1.enable_pins(); // pins managed by SPCRemulation in avr_emulation.h
  366. }
  367. void SPI1Class::end() {
  368. SPCR1.disable_pins();
  369. SPI1_MCR = SPI_MCR_MDIS | SPI_MCR_HALT | SPI_MCR_PCSIS(0x1F);
  370. }
  371. void SPI1Class::usingInterrupt(IRQ_NUMBER_t interruptName)
  372. {
  373. uint32_t n = (uint32_t)interruptName;
  374. if (n >= NVIC_NUM_INTERRUPTS) return;
  375. //Serial.print("usingInterrupt ");
  376. //Serial.println(n);
  377. interruptMasksUsed |= (1 << (n >> 5));
  378. interruptMask[n >> 5] |= (1 << (n & 0x1F));
  379. //Serial.printf("interruptMasksUsed = %d\n", interruptMasksUsed);
  380. //Serial.printf("interruptMask[0] = %08X\n", interruptMask[0]);
  381. //Serial.printf("interruptMask[1] = %08X\n", interruptMask[1]);
  382. //Serial.printf("interruptMask[2] = %08X\n", interruptMask[2]);
  383. }
  384. void SPI1Class::notUsingInterrupt(IRQ_NUMBER_t interruptName)
  385. {
  386. uint32_t n = (uint32_t)interruptName;
  387. if (n >= NVIC_NUM_INTERRUPTS) return;
  388. interruptMask[n >> 5] &= ~(1 << (n & 0x1F));
  389. if (interruptMask[n >> 5] == 0) {
  390. interruptMasksUsed &= ~(1 << (n >> 5));
  391. }
  392. }
  393. static void updateCTAR1(uint32_t ctar)
  394. {
  395. if (SPI1_CTAR0 != ctar) {
  396. uint32_t mcr = SPI1_MCR;
  397. if (mcr & SPI_MCR_MDIS) {
  398. SPI1_CTAR0 = ctar;
  399. SPI1_CTAR1 = ctar | SPI_CTAR_FMSZ(8);
  400. } else {
  401. SPI1_MCR = SPI_MCR_MDIS | SPI_MCR_HALT | SPI_MCR_PCSIS(0x1F);
  402. SPI1_CTAR0 = ctar;
  403. SPI1_CTAR1 = ctar | SPI_CTAR_FMSZ(8);
  404. SPI1_MCR = mcr;
  405. }
  406. }
  407. }
  408. void SPI1Class::setBitOrder(uint8_t bitOrder)
  409. {
  410. SIM_SCGC6 |= SIM_SCGC6_SPI1;
  411. uint32_t ctar = SPI1_CTAR0;
  412. if (bitOrder == LSBFIRST) {
  413. ctar |= SPI_CTAR_LSBFE;
  414. } else {
  415. ctar &= ~SPI_CTAR_LSBFE;
  416. }
  417. updateCTAR1(ctar);
  418. }
  419. void SPI1Class::setDataMode(uint8_t dataMode)
  420. {
  421. SIM_SCGC6 |= SIM_SCGC6_SPI1;
  422. // TODO: implement with native code
  423. SPCR1 = (SPCR1 & ~SPI_MODE_MASK) | dataMode;
  424. }
  425. void SPI1Class::setClockDivider_noInline(uint32_t clk)
  426. {
  427. SIM_SCGC6 |= SIM_SCGC6_SPI1;
  428. uint32_t ctar = SPI1_CTAR0;
  429. ctar &= (SPI_CTAR_CPOL | SPI_CTAR_CPHA | SPI_CTAR_LSBFE);
  430. if (ctar & SPI_CTAR_CPHA) {
  431. clk = (clk & 0xFFFF0FFF) | ((clk & 0xF000) >> 4);
  432. }
  433. ctar |= clk;
  434. updateCTAR1(ctar);
  435. }
  436. uint8_t SPI1Class::pinIsChipSelect(uint8_t pin)
  437. {
  438. switch (pin) {
  439. case 6: return 0x01; // CS0
  440. case 31: return 0x01; // CS0
  441. case 58: return 0x02; //CS1
  442. case 62: return 0x01; //CS0
  443. case 63: return 0x04; //CS2
  444. }
  445. return 0;
  446. }
  447. bool SPI1Class::pinIsChipSelect(uint8_t pin1, uint8_t pin2)
  448. {
  449. uint8_t pin1_mask, pin2_mask;
  450. if ((pin1_mask = (uint8_t)pinIsChipSelect(pin1)) == 0) return false;
  451. if ((pin2_mask = (uint8_t)pinIsChipSelect(pin2)) == 0) return false;
  452. //Serial.printf("pinIsChipSelect %d %d %x %x\n\r", pin1, pin2, pin1_mask, pin2_mask);
  453. if ((pin1_mask & pin2_mask) != 0) return false;
  454. return true;
  455. }
  456. // setCS() is not intended for use from normal Arduino programs/sketches.
  457. uint8_t SPI1Class::setCS(uint8_t pin)
  458. {
  459. switch (pin) {
  460. case 6: CORE_PIN6_CONFIG = PORT_PCR_MUX(7); return 0x01; // PTD4
  461. case 31: CORE_PIN31_CONFIG = PORT_PCR_MUX(2); return 0x01; // PTD5
  462. case 58: CORE_PIN58_CONFIG = PORT_PCR_MUX(2); return 0x02; //CS1
  463. case 62: CORE_PIN62_CONFIG = PORT_PCR_MUX(2); return 0x01; //CS0
  464. case 63: CORE_PIN63_CONFIG = PORT_PCR_MUX(2); return 0x04; //CS2
  465. }
  466. return 0;
  467. }
  468. void SPI1Class::transfer(void *buf, size_t count) {
  469. if (count == 0) return;
  470. uint8_t *p_write = (uint8_t *)buf;
  471. uint8_t *p_read = p_write;
  472. size_t count_read = count;
  473. // Lets clear the reader queue
  474. SPI1_MCR = SPI_MCR_MSTR | SPI_MCR_CLR_RXF | SPI_MCR_PCSIS(0x1F);
  475. uint32_t sr;
  476. // Now lets loop while we still have data to output
  477. if (count & 1) {
  478. KINETISK_SPI1.PUSHR = *p_write++ | SPI_PUSHR_CTAS(0);
  479. count--;
  480. }
  481. while (count > 0) {
  482. // Push out the next byte;
  483. uint16_t w = (*p_write++) << 8;
  484. w |= *p_write++;
  485. KINETISK_SPI1.PUSHR = w | SPI_PUSHR_CTAS(1);
  486. count -= 2; // how many bytes to output.
  487. // Make sure queue is not full before pushing next byte out
  488. do {
  489. sr = KINETISK_SPI1.SR;
  490. if (sr & 0xF0) {
  491. uint16_t w = KINETISK_SPI1.POPR; // Read any pending RX bytes in
  492. if (count_read & 1) {
  493. *p_read++ = w; // Read any pending RX bytes in
  494. count_read--;
  495. } else {
  496. *p_read++ = w >> 8;
  497. *p_read++ = (w & 0xff);
  498. count_read -= 2;
  499. }
  500. }
  501. } while ((sr & (15 << 12)) > (0 << 12)); // SPI1 and 2 only have 1 item queue
  502. }
  503. // now lets wait for all of the read bytes to be returned...
  504. while (count_read) {
  505. sr = KINETISK_SPI1.SR;
  506. if (sr & 0xF0) {
  507. uint16_t w = KINETISK_SPI1.POPR; // Read any pending RX bytes in
  508. if (count_read & 1) {
  509. *p_read++ = w; // Read any pending RX bytes in
  510. count_read--;
  511. } else {
  512. *p_read++ = w >> 8;
  513. *p_read++ = (w & 0xff);
  514. count_read -= 2;
  515. }
  516. }
  517. }
  518. }
  519. // SPI2 Class
  520. SPI2Class SPI2;
  521. uint8_t SPI2Class::interruptMasksUsed = 0;
  522. uint32_t SPI2Class::interruptMask[(NVIC_NUM_INTERRUPTS+31)/32];
  523. uint32_t SPI2Class::interruptSave[(NVIC_NUM_INTERRUPTS+31)/32];
  524. #ifdef SPI_TRANSACTION_MISMATCH_LED
  525. uint8_t SPI2Class::inTransactionFlag = 0;
  526. #endif
  527. void SPI2Class::begin()
  528. {
  529. SIM_SCGC3 |= SIM_SCGC3_SPI2;
  530. SPI2_MCR = SPI_MCR_MDIS | SPI_MCR_HALT | SPI_MCR_PCSIS(0x1F);
  531. SPI2_CTAR0 = SPI_CTAR_FMSZ(7) | SPI_CTAR_PBR(0) | SPI_CTAR_BR(1) | SPI_CTAR_CSSCK(1);
  532. SPI2_CTAR1 = SPI_CTAR_FMSZ(15) | SPI_CTAR_PBR(0) | SPI_CTAR_BR(1) | SPI_CTAR_CSSCK(1);
  533. SPI2_MCR = SPI_MCR_MSTR | SPI_MCR_PCSIS(0x1F);
  534. SPCR2.enable_pins(); // pins managed by SPCRemulation in avr_emulation.h
  535. }
  536. void SPI2Class::end() {
  537. SPCR2.disable_pins();
  538. SPI2_MCR = SPI_MCR_MDIS | SPI_MCR_HALT | SPI_MCR_PCSIS(0x1F);
  539. }
  540. void SPI2Class::usingInterrupt(IRQ_NUMBER_t interruptName)
  541. {
  542. uint32_t n = (uint32_t)interruptName;
  543. if (n >= NVIC_NUM_INTERRUPTS) return;
  544. //Serial.print("usingInterrupt ");
  545. //Serial.println(n);
  546. interruptMasksUsed |= (1 << (n >> 5));
  547. interruptMask[n >> 5] |= (1 << (n & 0x1F));
  548. //Serial.printf("interruptMasksUsed = %d\n", interruptMasksUsed);
  549. //Serial.printf("interruptMask[0] = %08X\n", interruptMask[0]);
  550. //Serial.printf("interruptMask[1] = %08X\n", interruptMask[1]);
  551. //Serial.printf("interruptMask[2] = %08X\n", interruptMask[2]);
  552. }
  553. void SPI2Class::notUsingInterrupt(IRQ_NUMBER_t interruptName)
  554. {
  555. uint32_t n = (uint32_t)interruptName;
  556. if (n >= NVIC_NUM_INTERRUPTS) return;
  557. interruptMask[n >> 5] &= ~(1 << (n & 0x1F));
  558. if (interruptMask[n >> 5] == 0) {
  559. interruptMasksUsed &= ~(1 << (n >> 5));
  560. }
  561. }
  562. static void updateCTAR2(uint32_t ctar)
  563. {
  564. if (SPI2_CTAR0 != ctar) {
  565. uint32_t mcr = SPI2_MCR;
  566. if (mcr & SPI_MCR_MDIS) {
  567. SPI2_CTAR0 = ctar;
  568. SPI2_CTAR1 = ctar | SPI_CTAR_FMSZ(8);
  569. } else {
  570. SPI2_MCR = SPI_MCR_MDIS | SPI_MCR_HALT | SPI_MCR_PCSIS(0x1F);
  571. SPI2_CTAR0 = ctar;
  572. SPI2_CTAR1 = ctar | SPI_CTAR_FMSZ(8);
  573. SPI2_MCR = mcr;
  574. }
  575. }
  576. }
  577. void SPI2Class::setBitOrder(uint8_t bitOrder)
  578. {
  579. SIM_SCGC3 |= SIM_SCGC3_SPI2;
  580. uint32_t ctar = SPI2_CTAR0;
  581. if (bitOrder == LSBFIRST) {
  582. ctar |= SPI_CTAR_LSBFE;
  583. } else {
  584. ctar &= ~SPI_CTAR_LSBFE;
  585. }
  586. updateCTAR2(ctar);
  587. }
  588. void SPI2Class::setDataMode(uint8_t dataMode)
  589. {
  590. SIM_SCGC3 |= SIM_SCGC3_SPI2;
  591. // TODO: implement with native code
  592. SPCR2 = (SPCR2 & ~SPI_MODE_MASK) | dataMode;
  593. }
  594. void SPI2Class::setClockDivider_noInline(uint32_t clk)
  595. {
  596. SIM_SCGC3 |= SIM_SCGC3_SPI2;
  597. uint32_t ctar = SPI2_CTAR0;
  598. ctar &= (SPI_CTAR_CPOL | SPI_CTAR_CPHA | SPI_CTAR_LSBFE);
  599. if (ctar & SPI_CTAR_CPHA) {
  600. clk = (clk & 0xFFFF0FFF) | ((clk & 0xF000) >> 4);
  601. }
  602. ctar |= clk;
  603. updateCTAR2(ctar);
  604. }
  605. uint8_t SPI2Class::pinIsChipSelect(uint8_t pin)
  606. {
  607. switch (pin) {
  608. case 43: return 0x01; // CS0
  609. case 54: return 0x02; // CS1
  610. case 55: return 0x01; // CS0
  611. }
  612. return 0;
  613. }
  614. bool SPI2Class::pinIsChipSelect(uint8_t pin1, uint8_t pin2)
  615. {
  616. uint8_t pin1_mask, pin2_mask;
  617. if ((pin1_mask = (uint8_t)pinIsChipSelect(pin1)) == 0) return false;
  618. if ((pin2_mask = (uint8_t)pinIsChipSelect(pin2)) == 0) return false;
  619. //Serial.printf("pinIsChipSelect %d %d %x %x\n\r", pin1, pin2, pin1_mask, pin2_mask);
  620. if ((pin1_mask & pin2_mask) != 0) return false;
  621. return true;
  622. }
  623. // setCS() is not intended for use from normal Arduino programs/sketches.
  624. uint8_t SPI2Class::setCS(uint8_t pin)
  625. {
  626. switch (pin) {
  627. case 43: CORE_PIN43_CONFIG = PORT_PCR_MUX(2); return 0x01; // CS0
  628. case 54: CORE_PIN54_CONFIG = PORT_PCR_MUX(2); return 0x02; // CS1
  629. case 55: CORE_PIN55_CONFIG = PORT_PCR_MUX(2); return 0x01; // CS0
  630. }
  631. return 0;
  632. }
  633. void SPI2Class::transfer(void *buf, size_t count) {
  634. if (count == 0) return;
  635. uint8_t *p_write = (uint8_t *)buf;
  636. uint8_t *p_read = p_write;
  637. size_t count_read = count;
  638. // Lets clear the reader queue
  639. SPI2_MCR = SPI_MCR_MSTR | SPI_MCR_CLR_RXF | SPI_MCR_PCSIS(0x1F);
  640. uint32_t sr;
  641. // Now lets loop while we still have data to output
  642. if (count & 1) {
  643. KINETISK_SPI2.PUSHR = *p_write++ | SPI_PUSHR_CTAS(0);
  644. count--;
  645. }
  646. while (count > 0) {
  647. // Push out the next byte;
  648. uint16_t w = (*p_write++) << 8;
  649. w |= *p_write++;
  650. KINETISK_SPI2.PUSHR = w | SPI_PUSHR_CTAS(1);
  651. count -= 2; // how many bytes to output.
  652. // Make sure queue is not full before pushing next byte out
  653. do {
  654. sr = KINETISK_SPI2.SR;
  655. if (sr & 0xF0) {
  656. uint16_t w = KINETISK_SPI2.POPR; // Read any pending RX bytes in
  657. if (count_read & 1) {
  658. *p_read++ = w; // Read any pending RX bytes in
  659. count_read--;
  660. } else {
  661. *p_read++ = w >> 8;
  662. *p_read++ = (w & 0xff);
  663. count_read -= 2;
  664. }
  665. }
  666. } while ((sr & (15 << 12)) > (0 << 12)); // SPI2 and 2 only have 1 item queue
  667. }
  668. // now lets wait for all of the read bytes to be returned...
  669. while (count_read) {
  670. sr = KINETISK_SPI2.SR;
  671. if (sr & 0xF0) {
  672. uint16_t w = KINETISK_SPI2.POPR; // Read any pending RX bytes in
  673. if (count_read & 1) {
  674. *p_read++ = w; // Read any pending RX bytes in
  675. count_read--;
  676. } else {
  677. *p_read++ = w >> 8;
  678. *p_read++ = (w & 0xff);
  679. count_read -= 2;
  680. }
  681. }
  682. }
  683. }
  684. #endif
  685. /**********************************************************/
  686. /* 32 bit Teensy-LC */
  687. /**********************************************************/
  688. #elif defined(__arm__) && defined(TEENSYDUINO) && defined(KINETISL)
  689. SPIClass SPI;
  690. SPI1Class SPI1;
  691. uint32_t SPIClass::interruptMask = 0;
  692. uint32_t SPIClass::interruptSave = 0;
  693. uint32_t SPI1Class::interruptMask = 0;
  694. uint32_t SPI1Class::interruptSave = 0;
  695. #ifdef SPI_TRANSACTION_MISMATCH_LED
  696. uint8_t SPIClass::inTransactionFlag = 0;
  697. uint8_t SPI1Class::inTransactionFlag = 0;
  698. #endif
  699. void SPIClass::begin()
  700. {
  701. SIM_SCGC4 |= SIM_SCGC4_SPI0;
  702. SPI0_C1 = SPI_C1_SPE | SPI_C1_MSTR;
  703. SPI0_C2 = 0;
  704. uint8_t tmp __attribute__((unused)) = SPI0_S;
  705. SPCR.enable_pins(); // pins managed by SPCRemulation in avr_emulation.h
  706. }
  707. void SPIClass::end() {
  708. SPCR.disable_pins();
  709. SPI0_C1 = 0;
  710. }
  711. const uint16_t SPISettings::br_div_table[30] = {
  712. 2, 4, 6, 8, 10, 12, 14, 16, 20, 24,
  713. 28, 32, 40, 48, 56, 64, 80, 96, 112, 128,
  714. 160, 192, 224, 256, 320, 384, 448, 512, 640, 768,
  715. };
  716. const uint8_t SPISettings::br_clock_table[30] = {
  717. SPI_BR_SPPR(0) | SPI_BR_SPR(0),
  718. SPI_BR_SPPR(1) | SPI_BR_SPR(0),
  719. SPI_BR_SPPR(2) | SPI_BR_SPR(0),
  720. SPI_BR_SPPR(3) | SPI_BR_SPR(0),
  721. SPI_BR_SPPR(4) | SPI_BR_SPR(0),
  722. SPI_BR_SPPR(5) | SPI_BR_SPR(0),
  723. SPI_BR_SPPR(6) | SPI_BR_SPR(0),
  724. SPI_BR_SPPR(7) | SPI_BR_SPR(0),
  725. SPI_BR_SPPR(4) | SPI_BR_SPR(1),
  726. SPI_BR_SPPR(5) | SPI_BR_SPR(1),
  727. SPI_BR_SPPR(6) | SPI_BR_SPR(1),
  728. SPI_BR_SPPR(7) | SPI_BR_SPR(1),
  729. SPI_BR_SPPR(4) | SPI_BR_SPR(2),
  730. SPI_BR_SPPR(5) | SPI_BR_SPR(2),
  731. SPI_BR_SPPR(6) | SPI_BR_SPR(2),
  732. SPI_BR_SPPR(7) | SPI_BR_SPR(2),
  733. SPI_BR_SPPR(4) | SPI_BR_SPR(3),
  734. SPI_BR_SPPR(5) | SPI_BR_SPR(3),
  735. SPI_BR_SPPR(6) | SPI_BR_SPR(3),
  736. SPI_BR_SPPR(7) | SPI_BR_SPR(3),
  737. SPI_BR_SPPR(4) | SPI_BR_SPR(4),
  738. SPI_BR_SPPR(5) | SPI_BR_SPR(4),
  739. SPI_BR_SPPR(6) | SPI_BR_SPR(4),
  740. SPI_BR_SPPR(7) | SPI_BR_SPR(4),
  741. SPI_BR_SPPR(4) | SPI_BR_SPR(5),
  742. SPI_BR_SPPR(5) | SPI_BR_SPR(5),
  743. SPI_BR_SPPR(6) | SPI_BR_SPR(5),
  744. SPI_BR_SPPR(7) | SPI_BR_SPR(5),
  745. SPI_BR_SPPR(4) | SPI_BR_SPR(6),
  746. SPI_BR_SPPR(5) | SPI_BR_SPR(6)
  747. };
  748. // setCS() is not intended for use from normal Arduino programs/sketches.
  749. uint8_t SPIClass::setCS(uint8_t pin)
  750. {
  751. switch (pin) {
  752. case 10: CORE_PIN10_CONFIG = PORT_PCR_MUX(2); return 0x01; // PTC4
  753. case 2: CORE_PIN2_CONFIG = PORT_PCR_MUX(2); return 0x01; // PTD0
  754. }
  755. return 0;
  756. }
  757. void SPI1Class::begin()
  758. {
  759. SIM_SCGC4 |= SIM_SCGC4_SPI1;
  760. SPI1_C1 = SPI_C1_SPE | SPI_C1_MSTR;
  761. SPI1_C2 = 0;
  762. uint8_t tmp __attribute__((unused)) = SPI1_S;
  763. SPCR1.enable_pins(); // pins managed by SPCRemulation in avr_emulation.h
  764. }
  765. void SPI1Class::end() {
  766. SPCR1.disable_pins();
  767. SPI1_C1 = 0;
  768. }
  769. // setCS() is not intended for use from normal Arduino programs/sketches.
  770. uint8_t SPI1Class::setCS(uint8_t pin)
  771. {
  772. switch (pin) {
  773. case 6: CORE_PIN6_CONFIG = PORT_PCR_MUX(2); return 0x01; // PTD4
  774. }
  775. return 0;
  776. }
  777. /**********************************************************/
  778. /* 32 bit Arduino Due */
  779. /**********************************************************/
  780. #elif defined(__arm__) && defined(__SAM3X8E__)
  781. #include "SPI.h"
  782. SPIClass::SPIClass(Spi *_spi, uint32_t _id, void(*_initCb)(void)) :
  783. spi(_spi), id(_id), initCb(_initCb), initialized(false)
  784. {
  785. // Empty
  786. }
  787. void SPIClass::begin() {
  788. init();
  789. // NPCS control is left to the user
  790. // Default speed set to 4Mhz
  791. setClockDivider(BOARD_SPI_DEFAULT_SS, 21);
  792. setDataMode(BOARD_SPI_DEFAULT_SS, SPI_MODE0);
  793. setBitOrder(BOARD_SPI_DEFAULT_SS, MSBFIRST);
  794. }
  795. void SPIClass::begin(uint8_t _pin) {
  796. init();
  797. uint32_t spiPin = BOARD_PIN_TO_SPI_PIN(_pin);
  798. PIO_Configure(
  799. g_APinDescription[spiPin].pPort,
  800. g_APinDescription[spiPin].ulPinType,
  801. g_APinDescription[spiPin].ulPin,
  802. g_APinDescription[spiPin].ulPinConfiguration);
  803. // Default speed set to 4Mhz
  804. setClockDivider(_pin, 21);
  805. setDataMode(_pin, SPI_MODE0);
  806. setBitOrder(_pin, MSBFIRST);
  807. }
  808. void SPIClass::init() {
  809. if (initialized)
  810. return;
  811. interruptMode = 0;
  812. interruptMask = 0;
  813. interruptSave = 0;
  814. initCb();
  815. SPI_Configure(spi, id, SPI_MR_MSTR | SPI_MR_PS | SPI_MR_MODFDIS);
  816. SPI_Enable(spi);
  817. initialized = true;
  818. }
  819. #ifndef interruptsStatus
  820. #define interruptsStatus() __interruptsStatus()
  821. static inline unsigned char __interruptsStatus(void) __attribute__((always_inline, unused));
  822. static inline unsigned char __interruptsStatus(void) {
  823. unsigned int primask;
  824. asm volatile ("mrs %0, primask" : "=r" (primask));
  825. if (primask) return 0;
  826. return 1;
  827. }
  828. #endif
  829. void SPIClass::usingInterrupt(uint8_t interruptNumber)
  830. {
  831. uint8_t irestore;
  832. irestore = interruptsStatus();
  833. noInterrupts();
  834. if (interruptMode < 2) {
  835. if (interruptNumber > NUM_DIGITAL_PINS) {
  836. interruptMode = 2;
  837. } else {
  838. uint8_t imask = interruptMask;
  839. Pio *pio = g_APinDescription[interruptNumber].pPort;
  840. if (pio == PIOA) {
  841. imask |= 1;
  842. } else if (pio == PIOB) {
  843. imask |= 2;
  844. } else if (pio == PIOC) {
  845. imask |= 4;
  846. } else if (pio == PIOD) {
  847. imask |= 8;
  848. }
  849. interruptMask = imask;
  850. interruptMode = 1;
  851. }
  852. }
  853. if (irestore) interrupts();
  854. }
  855. void SPIClass::beginTransaction(uint8_t pin, SPISettings settings)
  856. {
  857. if (interruptMode > 0) {
  858. if (interruptMode == 1) {
  859. uint8_t imask = interruptMask;
  860. if (imask & 1) NVIC_DisableIRQ(PIOA_IRQn);
  861. if (imask & 2) NVIC_DisableIRQ(PIOB_IRQn);
  862. if (imask & 4) NVIC_DisableIRQ(PIOC_IRQn);
  863. if (imask & 8) NVIC_DisableIRQ(PIOD_IRQn);
  864. } else {
  865. interruptSave = interruptsStatus();
  866. noInterrupts();
  867. }
  868. }
  869. uint32_t ch = BOARD_PIN_TO_SPI_CHANNEL(pin);
  870. bitOrder[ch] = settings.border;
  871. SPI_ConfigureNPCS(spi, ch, settings.config);
  872. }
  873. void SPIClass::endTransaction(void)
  874. {
  875. if (interruptMode > 0) {
  876. if (interruptMode == 1) {
  877. uint8_t imask = interruptMask;
  878. if (imask & 1) NVIC_EnableIRQ(PIOA_IRQn);
  879. if (imask & 2) NVIC_EnableIRQ(PIOB_IRQn);
  880. if (imask & 4) NVIC_EnableIRQ(PIOC_IRQn);
  881. if (imask & 8) NVIC_EnableIRQ(PIOD_IRQn);
  882. } else {
  883. if (interruptSave) interrupts();
  884. }
  885. }
  886. }
  887. void SPIClass::end(uint8_t _pin) {
  888. uint32_t spiPin = BOARD_PIN_TO_SPI_PIN(_pin);
  889. // Setting the pin as INPUT will disconnect it from SPI peripheral
  890. pinMode(spiPin, INPUT);
  891. }
  892. void SPIClass::end() {
  893. SPI_Disable(spi);
  894. initialized = false;
  895. }
  896. void SPIClass::setBitOrder(uint8_t _pin, BitOrder _bitOrder) {
  897. uint32_t ch = BOARD_PIN_TO_SPI_CHANNEL(_pin);
  898. bitOrder[ch] = _bitOrder;
  899. }
  900. void SPIClass::setDataMode(uint8_t _pin, uint8_t _mode) {
  901. uint32_t ch = BOARD_PIN_TO_SPI_CHANNEL(_pin);
  902. mode[ch] = _mode | SPI_CSR_CSAAT;
  903. // SPI_CSR_DLYBCT(1) keeps CS enabled for 32 MCLK after a completed
  904. // transfer. Some device needs that for working properly.
  905. SPI_ConfigureNPCS(spi, ch, mode[ch] | SPI_CSR_SCBR(divider[ch]) | SPI_CSR_DLYBCT(1));
  906. }
  907. void SPIClass::setClockDivider(uint8_t _pin, uint8_t _divider) {
  908. uint32_t ch = BOARD_PIN_TO_SPI_CHANNEL(_pin);
  909. divider[ch] = _divider;
  910. // SPI_CSR_DLYBCT(1) keeps CS enabled for 32 MCLK after a completed
  911. // transfer. Some device needs that for working properly.
  912. SPI_ConfigureNPCS(spi, ch, mode[ch] | SPI_CSR_SCBR(divider[ch]) | SPI_CSR_DLYBCT(1));
  913. }
  914. byte SPIClass::transfer(byte _pin, uint8_t _data, SPITransferMode _mode) {
  915. uint32_t ch = BOARD_PIN_TO_SPI_CHANNEL(_pin);
  916. // Reverse bit order
  917. if (bitOrder[ch] == LSBFIRST)
  918. _data = __REV(__RBIT(_data));
  919. uint32_t d = _data | SPI_PCS(ch);
  920. if (_mode == SPI_LAST)
  921. d |= SPI_TDR_LASTXFER;
  922. // SPI_Write(spi, _channel, _data);
  923. while ((spi->SPI_SR & SPI_SR_TDRE) == 0)
  924. ;
  925. spi->SPI_TDR = d;
  926. // return SPI_Read(spi);
  927. while ((spi->SPI_SR & SPI_SR_RDRF) == 0)
  928. ;
  929. d = spi->SPI_RDR;
  930. // Reverse bit order
  931. if (bitOrder[ch] == LSBFIRST)
  932. d = __REV(__RBIT(d));
  933. return d & 0xFF;
  934. }
  935. void SPIClass::attachInterrupt(void) {
  936. // Should be enableInterrupt()
  937. }
  938. void SPIClass::detachInterrupt(void) {
  939. // Should be disableInterrupt()
  940. }
  941. #if SPI_INTERFACES_COUNT > 0
  942. static void SPI_0_Init(void) {
  943. PIO_Configure(
  944. g_APinDescription[PIN_SPI_MOSI].pPort,
  945. g_APinDescription[PIN_SPI_MOSI].ulPinType,
  946. g_APinDescription[PIN_SPI_MOSI].ulPin,
  947. g_APinDescription[PIN_SPI_MOSI].ulPinConfiguration);
  948. PIO_Configure(
  949. g_APinDescription[PIN_SPI_MISO].pPort,
  950. g_APinDescription[PIN_SPI_MISO].ulPinType,
  951. g_APinDescription[PIN_SPI_MISO].ulPin,
  952. g_APinDescription[PIN_SPI_MISO].ulPinConfiguration);
  953. PIO_Configure(
  954. g_APinDescription[PIN_SPI_SCK].pPort,
  955. g_APinDescription[PIN_SPI_SCK].ulPinType,
  956. g_APinDescription[PIN_SPI_SCK].ulPin,
  957. g_APinDescription[PIN_SPI_SCK].ulPinConfiguration);
  958. }
  959. SPIClass SPI(SPI_INTERFACE, SPI_INTERFACE_ID, SPI_0_Init);
  960. #endif
  961. #endif