Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

10 роки тому
10 роки тому
10 роки тому
10 роки тому
10 роки тому
10 роки тому
10 роки тому
10 роки тому
10 роки тому
10 роки тому
10 роки тому
8 роки тому
8 роки тому
8 роки тому
8 роки тому
10 роки тому
10 роки тому
10 роки тому
10 роки тому
10 роки тому
10 роки тому
10 роки тому
10 роки тому
10 роки тому
10 роки тому
10 роки тому
10 роки тому
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717
  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.x */
  126. /**********************************************************/
  127. #elif defined(__arm__) && defined(TEENSYDUINO) && defined(KINETISK)
  128. #if defined(__MK20DX128__) || defined(__MK20DX256__)
  129. void _spi_dma_rxISR0(void) {/*SPI.dma_rxisr();*/}
  130. const SPIClass::SPI_Hardware_t SPIClass::spi0_hardware = {
  131. SIM_SCGC6, SIM_SCGC6_SPI0, 4, IRQ_SPI0,
  132. 32767, DMAMUX_SOURCE_SPI0_TX, DMAMUX_SOURCE_SPI0_RX,
  133. _spi_dma_rxISR0,
  134. 12, 8,
  135. PORT_PCR_MUX(2), PORT_PCR_MUX(2),
  136. 11, 7,
  137. PORT_PCR_DSE | PORT_PCR_MUX(2), PORT_PCR_MUX(2),
  138. 13, 14,
  139. PORT_PCR_DSE | PORT_PCR_MUX(2), PORT_PCR_MUX(2),
  140. 10, 2, 9, 6, 20, 23, 21, 22, 15,
  141. PORT_PCR_MUX(2), PORT_PCR_MUX(2), PORT_PCR_MUX(2), PORT_PCR_MUX(2), PORT_PCR_MUX(2), PORT_PCR_MUX(2), PORT_PCR_MUX(2), PORT_PCR_MUX(2), PORT_PCR_MUX(2),
  142. 0x1, 0x1, 0x2, 0x2, 0x4, 0x4, 0x8, 0x8, 0x10
  143. };
  144. SPIClass SPI((uintptr_t)&KINETISK_SPI0, (uintptr_t)&SPIClass::spi0_hardware);
  145. #elif defined(__MK64FX512__) || defined(__MK66FX1M0__)
  146. void _spi_dma_rxISR0(void) {/*SPI.dma_rxisr();*/}
  147. void _spi_dma_rxISR1(void) {/*SPI1.dma_rxisr();*/}
  148. void _spi_dma_rxISR2(void) {/*SPI2.dma_rxisr();*/}
  149. const SPIClass::SPI_Hardware_t SPIClass::spi0_hardware = {
  150. SIM_SCGC6, SIM_SCGC6_SPI0, 4, IRQ_SPI0,
  151. 32767, DMAMUX_SOURCE_SPI0_TX, DMAMUX_SOURCE_SPI0_RX,
  152. _spi_dma_rxISR0,
  153. 12, 8, 39, 255,
  154. PORT_PCR_MUX(2), PORT_PCR_MUX(2), PORT_PCR_MUX(2), 0,
  155. 11, 7, 28, 255,
  156. PORT_PCR_MUX(2), PORT_PCR_MUX(2), PORT_PCR_MUX(2), 0,
  157. 13, 14, 27,
  158. PORT_PCR_MUX(2), PORT_PCR_MUX(2), PORT_PCR_MUX(2),
  159. 10, 2, 9, 6, 20, 23, 21, 22, 15, 26, 45,
  160. PORT_PCR_MUX(2), PORT_PCR_MUX(2), PORT_PCR_MUX(2), PORT_PCR_MUX(2), PORT_PCR_MUX(2), PORT_PCR_MUX(2), PORT_PCR_MUX(2), PORT_PCR_MUX(2), PORT_PCR_MUX(2), PORT_PCR_MUX(2), PORT_PCR_MUX(3),
  161. 0x1, 0x1, 0x2, 0x2, 0x4, 0x4, 0x8, 0x8, 0x10, 0x1, 0x20
  162. };
  163. const SPIClass::SPI_Hardware_t SPIClass::spi1_hardware = {
  164. SIM_SCGC6, SIM_SCGC6_SPI1, 1, IRQ_SPI1,
  165. #if defined(__MK66FX1M0__)
  166. 32767, DMAMUX_SOURCE_SPI1_TX, DMAMUX_SOURCE_SPI1_RX,
  167. #else
  168. // T3.5 does not have good DMA support on 1 and 2
  169. 511, 0, DMAMUX_SOURCE_SPI1,
  170. #endif
  171. _spi_dma_rxISR1,
  172. 1, 5, 61, 59,
  173. PORT_PCR_MUX(2), PORT_PCR_MUX(7), PORT_PCR_MUX(2), PORT_PCR_MUX(7),
  174. 0, 21, 61, 59,
  175. PORT_PCR_MUX(2), PORT_PCR_MUX(7), PORT_PCR_MUX(7), PORT_PCR_MUX(2),
  176. 32, 20, 60,
  177. PORT_PCR_MUX(2), PORT_PCR_MUX(7), PORT_PCR_MUX(2),
  178. 6, 31, 58, 62, 63, 255, 255, 255, 255, 255, 255,
  179. PORT_PCR_MUX(7), PORT_PCR_MUX(2), PORT_PCR_MUX(2), PORT_PCR_MUX(2), PORT_PCR_MUX(2), 0, 0, 0, 0, 0, 0,
  180. 0x1, 0x1, 0x2, 0x1, 0x4, 0, 0, 0, 0, 0, 0
  181. };
  182. const SPIClass::SPI_Hardware_t SPIClass::spi2_hardware = {
  183. SIM_SCGC3, SIM_SCGC3_SPI2, 1, IRQ_SPI2,
  184. #if defined(__MK66FX1M0__)
  185. 32767, DMAMUX_SOURCE_SPI2_TX, DMAMUX_SOURCE_SPI2_RX,
  186. #else
  187. // T3.5 does not have good DMA support on 1 and 2
  188. 511, 0, DMAMUX_SOURCE_SPI2,
  189. #endif
  190. _spi_dma_rxISR2,
  191. 45, 51, 255, 255,
  192. PORT_PCR_MUX(2), PORT_PCR_MUX(2), 0, 0,
  193. 44, 52, 255, 255,
  194. PORT_PCR_MUX(2), PORT_PCR_MUX(2), 0, 0,
  195. 46, 53, 255,
  196. PORT_PCR_MUX(2), PORT_PCR_MUX(2), 0,
  197. 43, 54, 55, 255, 255, 255, 255, 255, 255, 255, 255,
  198. PORT_PCR_MUX(2), PORT_PCR_MUX(2), PORT_PCR_MUX(2), 0, 0, 0, 0, 0, 0, 0, 0,
  199. 0x1, 0x2, 0x1, 0, 0, 0, 0, 0, 0, 0, 0
  200. };
  201. SPIClass SPI((uintptr_t)&KINETISK_SPI0, (uintptr_t)&SPIClass::spi0_hardware);
  202. SPIClass SPI1((uintptr_t)&KINETISK_SPI1, (uintptr_t)&SPIClass::spi1_hardware);
  203. SPIClass SPI2((uintptr_t)&KINETISK_SPI2, (uintptr_t)&SPIClass::spi2_hardware);
  204. #endif
  205. void SPIClass::begin()
  206. {
  207. volatile uint32_t *reg;
  208. hardware().clock_gate_register |= hardware().clock_gate_mask;
  209. port().MCR = SPI_MCR_MDIS | SPI_MCR_HALT | SPI_MCR_PCSIS(0x1F);
  210. port().CTAR0 = SPI_CTAR_FMSZ(7) | SPI_CTAR_PBR(0) | SPI_CTAR_BR(1) | SPI_CTAR_CSSCK(1);
  211. port().CTAR1 = SPI_CTAR_FMSZ(15) | SPI_CTAR_PBR(0) | SPI_CTAR_BR(1) | SPI_CTAR_CSSCK(1);
  212. port().MCR = SPI_MCR_MSTR | SPI_MCR_PCSIS(0x1F);
  213. reg = portConfigRegister(hardware().mosi_pin[mosi_pin_index]);
  214. *reg = hardware().mosi_mux[mosi_pin_index];
  215. reg = portConfigRegister(hardware().miso_pin[miso_pin_index]);
  216. *reg= hardware().miso_mux[miso_pin_index];
  217. reg = portConfigRegister(hardware().sck_pin[sck_pin_index]);
  218. *reg = hardware().sck_mux[sck_pin_index];
  219. }
  220. void SPIClass::end()
  221. {
  222. volatile uint32_t *reg;
  223. reg = portConfigRegister(hardware().mosi_pin[mosi_pin_index]);
  224. *reg = 0;
  225. reg = portConfigRegister(hardware().miso_pin[miso_pin_index]);
  226. *reg = 0;
  227. reg = portConfigRegister(hardware().sck_pin[sck_pin_index]);
  228. *reg = 0;
  229. port().MCR = SPI_MCR_MDIS | SPI_MCR_HALT | SPI_MCR_PCSIS(0x1F);
  230. }
  231. void SPIClass::usingInterrupt(IRQ_NUMBER_t interruptName)
  232. {
  233. uint32_t n = (uint32_t)interruptName;
  234. if (n >= NVIC_NUM_INTERRUPTS) return;
  235. //Serial.print("usingInterrupt ");
  236. //Serial.println(n);
  237. interruptMasksUsed |= (1 << (n >> 5));
  238. interruptMask[n >> 5] |= (1 << (n & 0x1F));
  239. //Serial.printf("interruptMasksUsed = %d\n", interruptMasksUsed);
  240. //Serial.printf("interruptMask[0] = %08X\n", interruptMask[0]);
  241. //Serial.printf("interruptMask[1] = %08X\n", interruptMask[1]);
  242. //Serial.printf("interruptMask[2] = %08X\n", interruptMask[2]);
  243. }
  244. void SPIClass::notUsingInterrupt(IRQ_NUMBER_t interruptName)
  245. {
  246. uint32_t n = (uint32_t)interruptName;
  247. if (n >= NVIC_NUM_INTERRUPTS) return;
  248. interruptMask[n >> 5] &= ~(1 << (n & 0x1F));
  249. if (interruptMask[n >> 5] == 0) {
  250. interruptMasksUsed &= ~(1 << (n >> 5));
  251. }
  252. }
  253. const uint16_t SPISettings::ctar_div_table[23] = {
  254. 2, 3, 4, 5, 6, 8, 10, 12, 16, 20, 24, 32, 40,
  255. 56, 64, 96, 128, 192, 256, 384, 512, 640, 768
  256. };
  257. const uint32_t SPISettings::ctar_clock_table[23] = {
  258. SPI_CTAR_PBR(0) | SPI_CTAR_BR(0) | SPI_CTAR_DBR | SPI_CTAR_CSSCK(0),
  259. SPI_CTAR_PBR(1) | SPI_CTAR_BR(0) | SPI_CTAR_DBR | SPI_CTAR_CSSCK(0),
  260. SPI_CTAR_PBR(0) | SPI_CTAR_BR(0) | SPI_CTAR_CSSCK(0),
  261. SPI_CTAR_PBR(2) | SPI_CTAR_BR(0) | SPI_CTAR_DBR | SPI_CTAR_CSSCK(0),
  262. SPI_CTAR_PBR(1) | SPI_CTAR_BR(0) | SPI_CTAR_CSSCK(0),
  263. SPI_CTAR_PBR(0) | SPI_CTAR_BR(1) | SPI_CTAR_CSSCK(1),
  264. SPI_CTAR_PBR(2) | SPI_CTAR_BR(0) | SPI_CTAR_CSSCK(0),
  265. SPI_CTAR_PBR(1) | SPI_CTAR_BR(1) | SPI_CTAR_CSSCK(1),
  266. SPI_CTAR_PBR(0) | SPI_CTAR_BR(3) | SPI_CTAR_CSSCK(2),
  267. SPI_CTAR_PBR(2) | SPI_CTAR_BR(1) | SPI_CTAR_CSSCK(0),
  268. SPI_CTAR_PBR(1) | SPI_CTAR_BR(3) | SPI_CTAR_CSSCK(2),
  269. SPI_CTAR_PBR(0) | SPI_CTAR_BR(4) | SPI_CTAR_CSSCK(3),
  270. SPI_CTAR_PBR(2) | SPI_CTAR_BR(3) | SPI_CTAR_CSSCK(2),
  271. SPI_CTAR_PBR(3) | SPI_CTAR_BR(3) | SPI_CTAR_CSSCK(2),
  272. SPI_CTAR_PBR(0) | SPI_CTAR_BR(5) | SPI_CTAR_CSSCK(4),
  273. SPI_CTAR_PBR(1) | SPI_CTAR_BR(5) | SPI_CTAR_CSSCK(4),
  274. SPI_CTAR_PBR(0) | SPI_CTAR_BR(6) | SPI_CTAR_CSSCK(5),
  275. SPI_CTAR_PBR(1) | SPI_CTAR_BR(6) | SPI_CTAR_CSSCK(5),
  276. SPI_CTAR_PBR(0) | SPI_CTAR_BR(7) | SPI_CTAR_CSSCK(6),
  277. SPI_CTAR_PBR(1) | SPI_CTAR_BR(7) | SPI_CTAR_CSSCK(6),
  278. SPI_CTAR_PBR(0) | SPI_CTAR_BR(8) | SPI_CTAR_CSSCK(7),
  279. SPI_CTAR_PBR(2) | SPI_CTAR_BR(7) | SPI_CTAR_CSSCK(6),
  280. SPI_CTAR_PBR(1) | SPI_CTAR_BR(8) | SPI_CTAR_CSSCK(7)
  281. };
  282. void SPIClass::updateCTAR(uint32_t ctar)
  283. {
  284. if (port().CTAR0 != ctar) {
  285. uint32_t mcr = port().MCR;
  286. if (mcr & SPI_MCR_MDIS) {
  287. port().CTAR0 = ctar;
  288. port().CTAR1 = ctar | SPI_CTAR_FMSZ(8);
  289. } else {
  290. port().MCR = SPI_MCR_MDIS | SPI_MCR_HALT | SPI_MCR_PCSIS(0x1F);
  291. port().CTAR0 = ctar;
  292. port().CTAR1 = ctar | SPI_CTAR_FMSZ(8);
  293. port().MCR = mcr;
  294. }
  295. }
  296. }
  297. void SPIClass::setBitOrder(uint8_t bitOrder)
  298. {
  299. hardware().clock_gate_register |= hardware().clock_gate_mask;
  300. uint32_t ctar = port().CTAR0;
  301. if (bitOrder == LSBFIRST) {
  302. ctar |= SPI_CTAR_LSBFE;
  303. } else {
  304. ctar &= ~SPI_CTAR_LSBFE;
  305. }
  306. updateCTAR(ctar);
  307. }
  308. void SPIClass::setDataMode(uint8_t dataMode)
  309. {
  310. hardware().clock_gate_register |= hardware().clock_gate_mask;
  311. //uint32_t ctar = port().CTAR0;
  312. // TODO: implement with native code
  313. //SPCR = (SPCR & ~SPI_MODE_MASK) | dataMode;
  314. }
  315. void SPIClass::setClockDivider_noInline(uint32_t clk)
  316. {
  317. hardware().clock_gate_register |= hardware().clock_gate_mask;
  318. uint32_t ctar = port().CTAR0;
  319. ctar &= (SPI_CTAR_CPOL | SPI_CTAR_CPHA | SPI_CTAR_LSBFE);
  320. if (ctar & SPI_CTAR_CPHA) {
  321. clk = (clk & 0xFFFF0FFF) | ((clk & 0xF000) >> 4);
  322. }
  323. ctar |= clk;
  324. updateCTAR(ctar);
  325. }
  326. uint8_t SPIClass::pinIsChipSelect(uint8_t pin)
  327. {
  328. for (unsigned int i = 0; i < sizeof(hardware().cs_pin); i++) {
  329. if (pin == hardware().cs_pin[i]) return hardware().cs_mask[i];
  330. }
  331. return 0;
  332. }
  333. bool SPIClass::pinIsChipSelect(uint8_t pin1, uint8_t pin2)
  334. {
  335. uint8_t pin1_mask, pin2_mask;
  336. if ((pin1_mask = (uint8_t)pinIsChipSelect(pin1)) == 0) return false;
  337. if ((pin2_mask = (uint8_t)pinIsChipSelect(pin2)) == 0) return false;
  338. //Serial.printf("pinIsChipSelect %d %d %x %x\n\r", pin1, pin2, pin1_mask, pin2_mask);
  339. if ((pin1_mask & pin2_mask) != 0) return false;
  340. return true;
  341. }
  342. bool SPIClass::pinIsMOSI(uint8_t pin)
  343. {
  344. for (unsigned int i = 0; i < sizeof(hardware().mosi_pin); i++) {
  345. if (pin == hardware().mosi_pin[i]) return true;
  346. }
  347. return false;
  348. }
  349. bool SPIClass::pinIsMISO(uint8_t pin)
  350. {
  351. for (unsigned int i = 0; i < sizeof(hardware().miso_pin); i++) {
  352. if (pin == hardware().miso_pin[i]) return true;
  353. }
  354. return false;
  355. }
  356. bool SPIClass::pinIsSCK(uint8_t pin)
  357. {
  358. for (unsigned int i = 0; i < sizeof(hardware().sck_pin); i++) {
  359. if (pin == hardware().sck_pin[i]) return true;
  360. }
  361. return false;
  362. }
  363. // setCS() is not intended for use from normal Arduino programs/sketches.
  364. uint8_t SPIClass::setCS(uint8_t pin)
  365. {
  366. for (unsigned int i = 0; i < sizeof(hardware().cs_pin); i++) {
  367. if (pin == hardware().cs_pin[i]) {
  368. volatile uint32_t *reg = portConfigRegister(pin);
  369. *reg = hardware().cs_mux[i];
  370. return hardware().cs_mask[i];
  371. }
  372. }
  373. return 0;
  374. }
  375. void SPIClass::setMOSI(uint8_t pin)
  376. {
  377. if (pin != hardware().mosi_pin[mosi_pin_index]) {
  378. for (unsigned int i = 0; i < sizeof(hardware().mosi_pin); i++) {
  379. if (pin == hardware().mosi_pin[i]) {
  380. mosi_pin_index = i;
  381. return;
  382. }
  383. }
  384. }
  385. }
  386. void SPIClass::setMISO(uint8_t pin)
  387. {
  388. if (pin != hardware().miso_pin[miso_pin_index]) {
  389. for (unsigned int i = 0; i < sizeof(hardware().miso_pin); i++) {
  390. if (pin == hardware().miso_pin[i]) {
  391. miso_pin_index = i;
  392. return;
  393. }
  394. }
  395. }
  396. }
  397. void SPIClass::setSCK(uint8_t pin)
  398. {
  399. if (pin != hardware().sck_pin[sck_pin_index]) {
  400. for (unsigned int i = 0; i < sizeof(hardware().sck_pin); i++) {
  401. if (pin == hardware().sck_pin[i]) {
  402. sck_pin_index = i;
  403. return;
  404. }
  405. }
  406. }
  407. }
  408. void SPIClass::transfer(void *buf, size_t count)
  409. {
  410. if (count == 0) return;
  411. uint8_t *p_write = (uint8_t *)buf;
  412. uint8_t *p_read = p_write;
  413. size_t count_read = count;
  414. bool lsbfirst = (port().CTAR0 & SPI_CTAR_LSBFE) ? true : false;
  415. uint32_t sr, full_mask;
  416. // Lets clear the reader queue
  417. port().MCR = SPI_MCR_MSTR | SPI_MCR_CLR_RXF | SPI_MCR_PCSIS(0x1F);
  418. // Now lets loop while we still have data to output
  419. if (count & 1) {
  420. if (count > 1)
  421. port().PUSHR = *p_write++ | SPI_PUSHR_CONT | SPI_PUSHR_CTAS(0);
  422. else
  423. port().PUSHR = *p_write++ | SPI_PUSHR_CTAS(0);
  424. count--;
  425. }
  426. full_mask = (hardware().queue_size-1) << 12;
  427. while (count > 0) {
  428. // Push out the next byte
  429. uint16_t w = (*p_write++) << 8;
  430. w |= *p_write++;
  431. if (lsbfirst) w = __builtin_bswap16(w);
  432. if (count == 2)
  433. port().PUSHR = w | SPI_PUSHR_CTAS(1);
  434. else
  435. port().PUSHR = w | SPI_PUSHR_CONT | SPI_PUSHR_CTAS(1);
  436. count -= 2; // how many bytes to output.
  437. // Make sure queue is not full before pushing next byte out
  438. do {
  439. sr = port().SR;
  440. if (sr & 0xF0) {
  441. uint16_t w = port().POPR; // Read any pending RX bytes in
  442. if (count_read & 1) {
  443. *p_read++ = w; // Read any pending RX bytes in
  444. count_read--;
  445. } else {
  446. if (lsbfirst) w = __builtin_bswap16(w);
  447. *p_read++ = w >> 8;
  448. *p_read++ = (w & 0xff);
  449. count_read -= 2;
  450. }
  451. }
  452. } while ((sr & (15 << 12)) > full_mask);
  453. }
  454. // now lets wait for all of the read bytes to be returned...
  455. while (count_read) {
  456. sr = port().SR;
  457. if (sr & 0xF0) {
  458. uint16_t w = port().POPR; // Read any pending RX bytes in
  459. if (count_read & 1) {
  460. *p_read++ = w; // Read any pending RX bytes in
  461. count_read--;
  462. } else {
  463. if (lsbfirst) w = __builtin_bswap16(w);
  464. *p_read++ = w >> 8;
  465. *p_read++ = (w & 0xff);
  466. count_read -= 2;
  467. }
  468. }
  469. }
  470. }
  471. /**********************************************************/
  472. /* 32 bit Teensy-LC */
  473. /**********************************************************/
  474. #elif defined(__arm__) && defined(TEENSYDUINO) && defined(KINETISL)
  475. void _spi_dma_rxISR0(void) {/*SPI.dma_rxisr();*/}
  476. const SPIClass::SPI_Hardware_t SPIClass::spi0_hardware = {
  477. SIM_SCGC4, SIM_SCGC4_SPI0,
  478. 0, // BR index 0
  479. DMAMUX_SOURCE_SPI0_TX, DMAMUX_SOURCE_SPI0_RX, _spi_dma_rxISR0,
  480. 12, 8,
  481. PORT_PCR_MUX(2), PORT_PCR_MUX(2),
  482. 11, 7,
  483. PORT_PCR_DSE | PORT_PCR_MUX(2), PORT_PCR_MUX(2),
  484. 13, 14,
  485. PORT_PCR_DSE | PORT_PCR_MUX(2), PORT_PCR_MUX(2),
  486. 10, 2,
  487. PORT_PCR_MUX(2), PORT_PCR_MUX(2),
  488. 0x1, 0x1
  489. };
  490. SPIClass SPI((uintptr_t)&KINETISL_SPI0, (uintptr_t)&SPIClass::spi0_hardware);
  491. void _spi_dma_rxISR1(void) {/*SPI1.dma_rxisr();*/}
  492. const SPIClass::SPI_Hardware_t SPIClass::spi1_hardware = {
  493. SIM_SCGC4, SIM_SCGC4_SPI1,
  494. 1, // BR index 1 in SPI Settings
  495. DMAMUX_SOURCE_SPI1_TX, DMAMUX_SOURCE_SPI1_RX, _spi_dma_rxISR1,
  496. 1, 5,
  497. PORT_PCR_MUX(2), PORT_PCR_MUX(2),
  498. 0, 21,
  499. PORT_PCR_MUX(2), PORT_PCR_MUX(2),
  500. 20, 255,
  501. PORT_PCR_MUX(2), 0,
  502. 6, 255,
  503. PORT_PCR_MUX(2), 0,
  504. 0x1, 0
  505. };
  506. SPIClass SPI1((uintptr_t)&KINETISL_SPI1, (uintptr_t)&SPIClass::spi1_hardware);
  507. void SPIClass::begin()
  508. {
  509. volatile uint32_t *reg;
  510. hardware().clock_gate_register |= hardware().clock_gate_mask;
  511. port().C1 = SPI_C1_SPE | SPI_C1_MSTR;
  512. port().C2 = 0;
  513. uint8_t tmp __attribute__((unused)) = port().S;
  514. reg = portConfigRegister(hardware().mosi_pin[mosi_pin_index]);
  515. *reg = hardware().mosi_mux[mosi_pin_index];
  516. reg = portConfigRegister(hardware().miso_pin[miso_pin_index]);
  517. *reg = hardware().miso_mux[miso_pin_index];
  518. reg = portConfigRegister(hardware().sck_pin[sck_pin_index]);
  519. *reg = hardware().sck_mux[sck_pin_index];
  520. }
  521. void SPIClass::end() {
  522. volatile uint32_t *reg;
  523. reg = portConfigRegister(hardware().mosi_pin[mosi_pin_index]);
  524. *reg = 0;
  525. reg = portConfigRegister(hardware().miso_pin[miso_pin_index]);
  526. *reg = 0;
  527. reg = portConfigRegister(hardware().sck_pin[sck_pin_index]);
  528. *reg = 0;
  529. port().C1 = 0;
  530. }
  531. const uint16_t SPISettings::br_div_table[30] = {
  532. 2, 4, 6, 8, 10, 12, 14, 16, 20, 24,
  533. 28, 32, 40, 48, 56, 64, 80, 96, 112, 128,
  534. 160, 192, 224, 256, 320, 384, 448, 512, 640, 768,
  535. };
  536. const uint8_t SPISettings::br_clock_table[30] = {
  537. SPI_BR_SPPR(0) | SPI_BR_SPR(0),
  538. SPI_BR_SPPR(1) | SPI_BR_SPR(0),
  539. SPI_BR_SPPR(2) | SPI_BR_SPR(0),
  540. SPI_BR_SPPR(3) | SPI_BR_SPR(0),
  541. SPI_BR_SPPR(4) | SPI_BR_SPR(0),
  542. SPI_BR_SPPR(5) | SPI_BR_SPR(0),
  543. SPI_BR_SPPR(6) | SPI_BR_SPR(0),
  544. SPI_BR_SPPR(7) | SPI_BR_SPR(0),
  545. SPI_BR_SPPR(4) | SPI_BR_SPR(1),
  546. SPI_BR_SPPR(5) | SPI_BR_SPR(1),
  547. SPI_BR_SPPR(6) | SPI_BR_SPR(1),
  548. SPI_BR_SPPR(7) | SPI_BR_SPR(1),
  549. SPI_BR_SPPR(4) | SPI_BR_SPR(2),
  550. SPI_BR_SPPR(5) | SPI_BR_SPR(2),
  551. SPI_BR_SPPR(6) | SPI_BR_SPR(2),
  552. SPI_BR_SPPR(7) | SPI_BR_SPR(2),
  553. SPI_BR_SPPR(4) | SPI_BR_SPR(3),
  554. SPI_BR_SPPR(5) | SPI_BR_SPR(3),
  555. SPI_BR_SPPR(6) | SPI_BR_SPR(3),
  556. SPI_BR_SPPR(7) | SPI_BR_SPR(3),
  557. SPI_BR_SPPR(4) | SPI_BR_SPR(4),
  558. SPI_BR_SPPR(5) | SPI_BR_SPR(4),
  559. SPI_BR_SPPR(6) | SPI_BR_SPR(4),
  560. SPI_BR_SPPR(7) | SPI_BR_SPR(4),
  561. SPI_BR_SPPR(4) | SPI_BR_SPR(5),
  562. SPI_BR_SPPR(5) | SPI_BR_SPR(5),
  563. SPI_BR_SPPR(6) | SPI_BR_SPR(5),
  564. SPI_BR_SPPR(7) | SPI_BR_SPR(5),
  565. SPI_BR_SPPR(4) | SPI_BR_SPR(6),
  566. SPI_BR_SPPR(5) | SPI_BR_SPR(6)
  567. };
  568. void SPIClass::setMOSI(uint8_t pin)
  569. {
  570. if (pin != hardware().mosi_pin[mosi_pin_index]) {
  571. for (unsigned int i = 0; i < sizeof(hardware().mosi_pin); i++) {
  572. if (pin == hardware().mosi_pin[i] ) {
  573. mosi_pin_index = i;
  574. return;
  575. }
  576. }
  577. }
  578. }
  579. void SPIClass::setMISO(uint8_t pin)
  580. {
  581. if (pin != hardware().miso_pin[miso_pin_index]) {
  582. for (unsigned int i = 0; i < sizeof(hardware().miso_pin); i++) {
  583. if (pin == hardware().miso_pin[i] ) {
  584. miso_pin_index = i;
  585. return;
  586. }
  587. }
  588. }
  589. }
  590. void SPIClass::setSCK(uint8_t pin)
  591. {
  592. if (pin != hardware().sck_pin[sck_pin_index]) {
  593. for (unsigned int i = 0; i < sizeof(hardware().sck_pin); i++) {
  594. if (pin == hardware().sck_pin[i] ) {
  595. sck_pin_index = i;
  596. return;
  597. }
  598. }
  599. }
  600. }
  601. bool SPIClass::pinIsChipSelect(uint8_t pin)
  602. {
  603. for (unsigned int i = 0; i < sizeof(hardware().cs_pin); i++) {
  604. if (pin == hardware().cs_pin[i]) return hardware().cs_mask[i];
  605. }
  606. return 0;
  607. }
  608. bool SPIClass::pinIsMOSI(uint8_t pin)
  609. {
  610. for (unsigned int i = 0; i < sizeof(hardware().mosi_pin); i++) {
  611. if (pin == hardware().mosi_pin[i]) return true;
  612. }
  613. return false;
  614. }
  615. bool SPIClass::pinIsMISO(uint8_t pin)
  616. {
  617. for (unsigned int i = 0; i < sizeof(hardware().miso_pin); i++) {
  618. if (pin == hardware().miso_pin[i]) return true;
  619. }
  620. return false;
  621. }
  622. bool SPIClass::pinIsSCK(uint8_t pin)
  623. {
  624. for (unsigned int i = 0; i < sizeof(hardware().sck_pin); i++) {
  625. if (pin == hardware().sck_pin[i]) return true;
  626. }
  627. return false;
  628. }
  629. // setCS() is not intended for use from normal Arduino programs/sketches.
  630. uint8_t SPIClass::setCS(uint8_t pin)
  631. {
  632. for (unsigned int i = 0; i < sizeof(hardware().cs_pin); i++) {
  633. if (pin == hardware().cs_pin[i]) {
  634. volatile uint32_t *reg = portConfigRegister(pin);
  635. *reg = hardware().cs_mux[i];
  636. return hardware().cs_mask[i];
  637. }
  638. }
  639. return 0;
  640. }
  641. #endif