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

1046 lines
29KB

  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. 2, 2,
  136. 11, 7,
  137. 2, 2,
  138. 13, 14,
  139. 2, 2,
  140. 10, 2, 9, 6, 20, 23, 21, 22, 15,
  141. 2, 2, 2, 2, 2, 2, 2, 2, 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. 2, 2, 2, 0,
  155. 11, 7, 28, 255,
  156. 2, 2, 2, 0,
  157. 13, 14, 27,
  158. 2, 2, 2,
  159. 10, 2, 9, 6, 20, 23, 21, 22, 15, 26, 45,
  160. 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 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. 2, 7, 2, 7,
  174. 0, 21, 61, 59,
  175. 2, 7, 7, 2,
  176. 32, 20, 60,
  177. 2, 7, 2,
  178. 6, 31, 58, 62, 63, 255, 255, 255, 255, 255, 255,
  179. 7, 2, 2, 2, 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. 2, 2, 0, 0,
  193. 44, 52, 255, 255,
  194. 2, 2, 0, 0,
  195. 46, 53, 255,
  196. 2, 2, 0,
  197. 43, 54, 55, 255, 255, 255, 255, 255, 255, 255, 255,
  198. 2, 2, 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, SPIClass::spi0_hardware);
  202. SPIClass SPI((uintptr_t)&KINETISK_SPI0, (uintptr_t)&SPIClass::spi0_hardware);
  203. //SPIClass SPI1((uintptr_t)&KINETISK_SPI1, SPIClass::spi1_hardware);
  204. //SPIClass SPI2((uintptr_t)&KINETISK_SPI2, SPIClass::spi2_hardware);
  205. #endif
  206. void SPIClass::begin()
  207. {
  208. volatile uint32_t *reg;
  209. hardware().clock_gate_register |= hardware().clock_gate_mask;
  210. port().MCR = SPI_MCR_MDIS | SPI_MCR_HALT | SPI_MCR_PCSIS(0x1F);
  211. port().CTAR0 = SPI_CTAR_FMSZ(7) | SPI_CTAR_PBR(0) | SPI_CTAR_BR(1) | SPI_CTAR_CSSCK(1);
  212. port().CTAR1 = SPI_CTAR_FMSZ(15) | SPI_CTAR_PBR(0) | SPI_CTAR_BR(1) | SPI_CTAR_CSSCK(1);
  213. port().MCR = SPI_MCR_MSTR | SPI_MCR_PCSIS(0x1F);
  214. reg = portConfigRegister(hardware().mosi_pin[mosi_pin_index]);
  215. *reg = PORT_PCR_MUX(hardware().mosi_mux[mosi_pin_index]);
  216. reg = portConfigRegister(hardware().miso_pin[miso_pin_index]);
  217. *reg= PORT_PCR_MUX(hardware().miso_mux[miso_pin_index]);
  218. reg = portConfigRegister(hardware().sck_pin[sck_pin_index]);
  219. *reg = PORT_PCR_MUX(hardware().sck_mux[sck_pin_index]);
  220. }
  221. void SPIClass::end()
  222. {
  223. volatile uint32_t *reg;
  224. //SPCR.disable_pins();
  225. reg = portConfigRegister(hardware().mosi_pin[mosi_pin_index]);
  226. *reg = 0;
  227. reg = portConfigRegister(hardware().miso_pin[miso_pin_index]);
  228. *reg = 0;
  229. reg = portConfigRegister(hardware().sck_pin[sck_pin_index]);
  230. *reg = 0;
  231. port().MCR = SPI_MCR_MDIS | SPI_MCR_HALT | SPI_MCR_PCSIS(0x1F);
  232. }
  233. void SPIClass::usingInterrupt(IRQ_NUMBER_t interruptName)
  234. {
  235. uint32_t n = (uint32_t)interruptName;
  236. if (n >= NVIC_NUM_INTERRUPTS) return;
  237. //Serial.print("usingInterrupt ");
  238. //Serial.println(n);
  239. interruptMasksUsed |= (1 << (n >> 5));
  240. interruptMask[n >> 5] |= (1 << (n & 0x1F));
  241. //Serial.printf("interruptMasksUsed = %d\n", interruptMasksUsed);
  242. //Serial.printf("interruptMask[0] = %08X\n", interruptMask[0]);
  243. //Serial.printf("interruptMask[1] = %08X\n", interruptMask[1]);
  244. //Serial.printf("interruptMask[2] = %08X\n", interruptMask[2]);
  245. }
  246. void SPIClass::notUsingInterrupt(IRQ_NUMBER_t interruptName)
  247. {
  248. uint32_t n = (uint32_t)interruptName;
  249. if (n >= NVIC_NUM_INTERRUPTS) return;
  250. interruptMask[n >> 5] &= ~(1 << (n & 0x1F));
  251. if (interruptMask[n >> 5] == 0) {
  252. interruptMasksUsed &= ~(1 << (n >> 5));
  253. }
  254. }
  255. const uint16_t SPISettings::ctar_div_table[23] = {
  256. 2, 3, 4, 5, 6, 8, 10, 12, 16, 20, 24, 32, 40,
  257. 56, 64, 96, 128, 192, 256, 384, 512, 640, 768
  258. };
  259. const uint32_t SPISettings::ctar_clock_table[23] = {
  260. SPI_CTAR_PBR(0) | SPI_CTAR_BR(0) | SPI_CTAR_DBR | SPI_CTAR_CSSCK(0),
  261. SPI_CTAR_PBR(1) | SPI_CTAR_BR(0) | SPI_CTAR_DBR | SPI_CTAR_CSSCK(0),
  262. SPI_CTAR_PBR(0) | SPI_CTAR_BR(0) | SPI_CTAR_CSSCK(0),
  263. SPI_CTAR_PBR(2) | SPI_CTAR_BR(0) | SPI_CTAR_DBR | SPI_CTAR_CSSCK(0),
  264. SPI_CTAR_PBR(1) | SPI_CTAR_BR(0) | SPI_CTAR_CSSCK(0),
  265. SPI_CTAR_PBR(0) | SPI_CTAR_BR(1) | SPI_CTAR_CSSCK(1),
  266. SPI_CTAR_PBR(2) | SPI_CTAR_BR(0) | SPI_CTAR_CSSCK(0),
  267. SPI_CTAR_PBR(1) | SPI_CTAR_BR(1) | SPI_CTAR_CSSCK(1),
  268. SPI_CTAR_PBR(0) | SPI_CTAR_BR(3) | SPI_CTAR_CSSCK(2),
  269. SPI_CTAR_PBR(2) | SPI_CTAR_BR(1) | SPI_CTAR_CSSCK(0),
  270. SPI_CTAR_PBR(1) | SPI_CTAR_BR(3) | SPI_CTAR_CSSCK(2),
  271. SPI_CTAR_PBR(0) | SPI_CTAR_BR(4) | SPI_CTAR_CSSCK(3),
  272. SPI_CTAR_PBR(2) | SPI_CTAR_BR(3) | SPI_CTAR_CSSCK(2),
  273. SPI_CTAR_PBR(3) | SPI_CTAR_BR(3) | SPI_CTAR_CSSCK(2),
  274. SPI_CTAR_PBR(0) | SPI_CTAR_BR(5) | SPI_CTAR_CSSCK(4),
  275. SPI_CTAR_PBR(1) | SPI_CTAR_BR(5) | SPI_CTAR_CSSCK(4),
  276. SPI_CTAR_PBR(0) | SPI_CTAR_BR(6) | SPI_CTAR_CSSCK(5),
  277. SPI_CTAR_PBR(1) | SPI_CTAR_BR(6) | SPI_CTAR_CSSCK(5),
  278. SPI_CTAR_PBR(0) | SPI_CTAR_BR(7) | SPI_CTAR_CSSCK(6),
  279. SPI_CTAR_PBR(1) | SPI_CTAR_BR(7) | SPI_CTAR_CSSCK(6),
  280. SPI_CTAR_PBR(0) | SPI_CTAR_BR(8) | SPI_CTAR_CSSCK(7),
  281. SPI_CTAR_PBR(2) | SPI_CTAR_BR(7) | SPI_CTAR_CSSCK(6),
  282. SPI_CTAR_PBR(1) | SPI_CTAR_BR(8) | SPI_CTAR_CSSCK(7)
  283. };
  284. void SPIClass::updateCTAR(uint32_t ctar)
  285. {
  286. if (port().CTAR0 != ctar) {
  287. uint32_t mcr = port().MCR;
  288. if (mcr & SPI_MCR_MDIS) {
  289. port().CTAR0 = ctar;
  290. port().CTAR1 = ctar | SPI_CTAR_FMSZ(8);
  291. } else {
  292. port().MCR = SPI_MCR_MDIS | SPI_MCR_HALT | SPI_MCR_PCSIS(0x1F);
  293. port().CTAR0 = ctar;
  294. port().CTAR1 = ctar | SPI_CTAR_FMSZ(8);
  295. port().MCR = mcr;
  296. }
  297. }
  298. }
  299. void SPIClass::setBitOrder(uint8_t bitOrder)
  300. {
  301. hardware().clock_gate_register |= hardware().clock_gate_mask;
  302. uint32_t ctar = port().CTAR0;
  303. if (bitOrder == LSBFIRST) {
  304. ctar |= SPI_CTAR_LSBFE;
  305. } else {
  306. ctar &= ~SPI_CTAR_LSBFE;
  307. }
  308. updateCTAR(ctar);
  309. }
  310. void SPIClass::setDataMode(uint8_t dataMode)
  311. {
  312. hardware().clock_gate_register |= hardware().clock_gate_mask;
  313. //uint32_t ctar = port().CTAR0;
  314. // TODO: implement with native code
  315. //SPCR = (SPCR & ~SPI_MODE_MASK) | dataMode;
  316. }
  317. void SPIClass::setClockDivider_noInline(uint32_t clk)
  318. {
  319. hardware().clock_gate_register |= hardware().clock_gate_mask;
  320. uint32_t ctar = port().CTAR0;
  321. ctar &= (SPI_CTAR_CPOL | SPI_CTAR_CPHA | SPI_CTAR_LSBFE);
  322. if (ctar & SPI_CTAR_CPHA) {
  323. clk = (clk & 0xFFFF0FFF) | ((clk & 0xF000) >> 4);
  324. }
  325. ctar |= clk;
  326. updateCTAR(ctar);
  327. }
  328. uint8_t SPIClass::pinIsChipSelect(uint8_t pin)
  329. {
  330. for (unsigned int i = 0; i < sizeof(hardware().cs_pin); i++) {
  331. if (pin == hardware().cs_pin[i]) return hardware().cs_mask[i];
  332. }
  333. return 0;
  334. /*
  335. switch (pin) {
  336. case 10: return 0x01; // PTC4
  337. case 2: return 0x01; // PTD0
  338. case 9: return 0x02; // PTC3
  339. case 6: return 0x02; // PTD4
  340. case 20: return 0x04; // PTD5
  341. case 23: return 0x04; // PTC2
  342. case 21: return 0x08; // PTD6
  343. case 22: return 0x08; // PTC1
  344. case 15: return 0x10; // PTC0
  345. #if defined(__MK64FX512__) || defined(__MK66FX1M0__)
  346. case 26: return 0x01;
  347. case 45: return 0x20; // CS5
  348. #endif
  349. }
  350. return 0;
  351. */
  352. }
  353. bool SPIClass::pinIsChipSelect(uint8_t pin1, uint8_t pin2)
  354. {
  355. uint8_t pin1_mask, pin2_mask;
  356. if ((pin1_mask = (uint8_t)pinIsChipSelect(pin1)) == 0) return false;
  357. if ((pin2_mask = (uint8_t)pinIsChipSelect(pin2)) == 0) return false;
  358. //Serial.printf("pinIsChipSelect %d %d %x %x\n\r", pin1, pin2, pin1_mask, pin2_mask);
  359. if ((pin1_mask & pin2_mask) != 0) return false;
  360. return true;
  361. }
  362. // setCS() is not intended for use from normal Arduino programs/sketches.
  363. uint8_t SPIClass::setCS(uint8_t pin)
  364. {
  365. for (unsigned int i = 0; i < sizeof(hardware().cs_pin); i++) {
  366. if (pin == hardware().cs_pin[i]) {
  367. volatile uint32_t *reg = portConfigRegister(pin);
  368. *reg = PORT_PCR_MUX(hardware().cs_mux[i]);
  369. return hardware().cs_mask[i];
  370. }
  371. }
  372. return 0;
  373. /*
  374. switch (pin) {
  375. case 10: CORE_PIN10_CONFIG = PORT_PCR_MUX(2); return 0x01; // PTC4
  376. case 2: CORE_PIN2_CONFIG = PORT_PCR_MUX(2); return 0x01; // PTD0
  377. case 9: CORE_PIN9_CONFIG = PORT_PCR_MUX(2); return 0x02; // PTC3
  378. case 6: CORE_PIN6_CONFIG = PORT_PCR_MUX(2); return 0x02; // PTD4
  379. case 20: CORE_PIN20_CONFIG = PORT_PCR_MUX(2); return 0x04; // PTD5
  380. case 23: CORE_PIN23_CONFIG = PORT_PCR_MUX(2); return 0x04; // PTC2
  381. case 21: CORE_PIN21_CONFIG = PORT_PCR_MUX(2); return 0x08; // PTD6
  382. case 22: CORE_PIN22_CONFIG = PORT_PCR_MUX(2); return 0x08; // PTC1
  383. case 15: CORE_PIN15_CONFIG = PORT_PCR_MUX(2); return 0x10; // PTC0
  384. #if defined(__MK64FX512__) || defined(__MK66FX1M0__)
  385. case 26: CORE_PIN26_CONFIG = PORT_PCR_MUX(2);return 0x01;
  386. case 45: CORE_PIN45_CONFIG = PORT_PCR_MUX(3);return 0x20;
  387. #endif
  388. }
  389. return 0;
  390. */
  391. }
  392. void SPIClass::setMOSI(uint8_t pin)
  393. {
  394. if (pin != hardware().mosi_pin[mosi_pin_index]) {
  395. for (unsigned int i = 0; i < sizeof(hardware().mosi_pin); i++) {
  396. if (pin == hardware().mosi_pin[i]) {
  397. mosi_pin_index = i;
  398. return;
  399. }
  400. }
  401. }
  402. }
  403. void SPIClass::setMISO(uint8_t pin)
  404. {
  405. if (pin != hardware().miso_pin[miso_pin_index]) {
  406. for (unsigned int i = 0; i < sizeof(hardware().miso_pin); i++) {
  407. if (pin == hardware().miso_pin[i]) {
  408. miso_pin_index = i;
  409. return;
  410. }
  411. }
  412. }
  413. }
  414. void SPIClass::setSCK(uint8_t pin)
  415. {
  416. if (pin != hardware().sck_pin[sck_pin_index]) {
  417. for (unsigned int i = 0; i < sizeof(hardware().sck_pin); i++) {
  418. if (pin == hardware().sck_pin[i]) {
  419. sck_pin_index = i;
  420. return;
  421. }
  422. }
  423. }
  424. }
  425. void SPIClass::transfer(void *buf, size_t count)
  426. {
  427. if (count == 0) return;
  428. uint8_t *p_write = (uint8_t *)buf;
  429. uint8_t *p_read = p_write;
  430. size_t count_read = count;
  431. bool lsbfirst = (port().CTAR0 & SPI_CTAR_LSBFE) ? true : false;
  432. // Lets clear the reader queue
  433. port().MCR = SPI_MCR_MSTR | SPI_MCR_CLR_RXF | SPI_MCR_PCSIS(0x1F);
  434. uint32_t sr;
  435. // Now lets loop while we still have data to output
  436. if (count & 1) {
  437. if (count > 1)
  438. port().PUSHR = *p_write++ | SPI_PUSHR_CONT | SPI_PUSHR_CTAS(0);
  439. else
  440. port().PUSHR = *p_write++ | SPI_PUSHR_CTAS(0);
  441. count--;
  442. }
  443. while (count > 0) {
  444. // Push out the next byte;
  445. uint16_t w = (*p_write++) << 8;
  446. w |= *p_write++;
  447. if (lsbfirst) w = __builtin_bswap16(w);
  448. if (count == 2)
  449. port().PUSHR = w | SPI_PUSHR_CTAS(1);
  450. else
  451. port().PUSHR = w | SPI_PUSHR_CONT | SPI_PUSHR_CTAS(1);
  452. count -= 2; // how many bytes to output.
  453. // Make sure queue is not full before pushing next byte out
  454. do {
  455. sr = port().SR;
  456. if (sr & 0xF0) {
  457. uint16_t w = port().POPR; // Read any pending RX bytes in
  458. if (count_read & 1) {
  459. *p_read++ = w; // Read any pending RX bytes in
  460. count_read--;
  461. } else {
  462. if (lsbfirst) w = __builtin_bswap16(w);
  463. *p_read++ = w >> 8;
  464. *p_read++ = (w & 0xff);
  465. count_read -= 2;
  466. }
  467. }
  468. } while ((sr & (15 << 12)) > (3 << 12));
  469. }
  470. // now lets wait for all of the read bytes to be returned...
  471. while (count_read) {
  472. sr = port().SR;
  473. if (sr & 0xF0) {
  474. uint16_t w = port().POPR; // Read any pending RX bytes in
  475. if (count_read & 1) {
  476. *p_read++ = w; // Read any pending RX bytes in
  477. count_read--;
  478. } else {
  479. if (lsbfirst) w = __builtin_bswap16(w);
  480. *p_read++ = w >> 8;
  481. *p_read++ = (w & 0xff);
  482. count_read -= 2;
  483. }
  484. }
  485. }
  486. }
  487. /**********************************************************/
  488. /* 32 bit Teensy-3.5/3.6 */
  489. /**********************************************************/
  490. #if defined(__MK64FX512__) || defined(__MK66FX1M0__)
  491. SPI1Class SPI1;
  492. uint8_t SPI1Class::interruptMasksUsed = 0;
  493. uint32_t SPI1Class::interruptMask[(NVIC_NUM_INTERRUPTS+31)/32];
  494. uint32_t SPI1Class::interruptSave[(NVIC_NUM_INTERRUPTS+31)/32];
  495. #ifdef SPI_TRANSACTION_MISMATCH_LED
  496. uint8_t SPI1Class::inTransactionFlag = 0;
  497. #endif
  498. void SPI1Class::begin()
  499. {
  500. SIM_SCGC6 |= SIM_SCGC6_SPI1;
  501. SPI1_MCR = SPI_MCR_MDIS | SPI_MCR_HALT | SPI_MCR_PCSIS(0x1F);
  502. SPI1_CTAR0 = SPI_CTAR_FMSZ(7) | SPI_CTAR_PBR(0) | SPI_CTAR_BR(1) | SPI_CTAR_CSSCK(1);
  503. SPI1_CTAR1 = SPI_CTAR_FMSZ(15) | SPI_CTAR_PBR(0) | SPI_CTAR_BR(1) | SPI_CTAR_CSSCK(1);
  504. SPI1_MCR = SPI_MCR_MSTR | SPI_MCR_PCSIS(0x1F);
  505. SPCR1.enable_pins(); // pins managed by SPCRemulation in avr_emulation.h
  506. }
  507. void SPI1Class::end() {
  508. SPCR1.disable_pins();
  509. SPI1_MCR = SPI_MCR_MDIS | SPI_MCR_HALT | SPI_MCR_PCSIS(0x1F);
  510. }
  511. void SPI1Class::usingInterrupt(IRQ_NUMBER_t interruptName)
  512. {
  513. uint32_t n = (uint32_t)interruptName;
  514. if (n >= NVIC_NUM_INTERRUPTS) return;
  515. //Serial.print("usingInterrupt ");
  516. //Serial.println(n);
  517. interruptMasksUsed |= (1 << (n >> 5));
  518. interruptMask[n >> 5] |= (1 << (n & 0x1F));
  519. //Serial.printf("interruptMasksUsed = %d\n", interruptMasksUsed);
  520. //Serial.printf("interruptMask[0] = %08X\n", interruptMask[0]);
  521. //Serial.printf("interruptMask[1] = %08X\n", interruptMask[1]);
  522. //Serial.printf("interruptMask[2] = %08X\n", interruptMask[2]);
  523. }
  524. void SPI1Class::notUsingInterrupt(IRQ_NUMBER_t interruptName)
  525. {
  526. uint32_t n = (uint32_t)interruptName;
  527. if (n >= NVIC_NUM_INTERRUPTS) return;
  528. interruptMask[n >> 5] &= ~(1 << (n & 0x1F));
  529. if (interruptMask[n >> 5] == 0) {
  530. interruptMasksUsed &= ~(1 << (n >> 5));
  531. }
  532. }
  533. static void updateCTAR1(uint32_t ctar)
  534. {
  535. if (SPI1_CTAR0 != ctar) {
  536. uint32_t mcr = SPI1_MCR;
  537. if (mcr & SPI_MCR_MDIS) {
  538. SPI1_CTAR0 = ctar;
  539. SPI1_CTAR1 = ctar | SPI_CTAR_FMSZ(8);
  540. } else {
  541. SPI1_MCR = SPI_MCR_MDIS | SPI_MCR_HALT | SPI_MCR_PCSIS(0x1F);
  542. SPI1_CTAR0 = ctar;
  543. SPI1_CTAR1 = ctar | SPI_CTAR_FMSZ(8);
  544. SPI1_MCR = mcr;
  545. }
  546. }
  547. }
  548. void SPI1Class::setBitOrder(uint8_t bitOrder)
  549. {
  550. SIM_SCGC6 |= SIM_SCGC6_SPI1;
  551. uint32_t ctar = SPI1_CTAR0;
  552. if (bitOrder == LSBFIRST) {
  553. ctar |= SPI_CTAR_LSBFE;
  554. } else {
  555. ctar &= ~SPI_CTAR_LSBFE;
  556. }
  557. updateCTAR1(ctar);
  558. }
  559. void SPI1Class::setDataMode(uint8_t dataMode)
  560. {
  561. SIM_SCGC6 |= SIM_SCGC6_SPI1;
  562. // TODO: implement with native code
  563. SPCR1 = (SPCR1 & ~SPI_MODE_MASK) | dataMode;
  564. }
  565. void SPI1Class::setClockDivider_noInline(uint32_t clk)
  566. {
  567. SIM_SCGC6 |= SIM_SCGC6_SPI1;
  568. uint32_t ctar = SPI1_CTAR0;
  569. ctar &= (SPI_CTAR_CPOL | SPI_CTAR_CPHA | SPI_CTAR_LSBFE);
  570. if (ctar & SPI_CTAR_CPHA) {
  571. clk = (clk & 0xFFFF0FFF) | ((clk & 0xF000) >> 4);
  572. }
  573. ctar |= clk;
  574. updateCTAR1(ctar);
  575. }
  576. uint8_t SPI1Class::pinIsChipSelect(uint8_t pin)
  577. {
  578. switch (pin) {
  579. case 6: return 0x01; // CS0
  580. case 31: return 0x01; // CS0
  581. case 58: return 0x02; //CS1
  582. case 62: return 0x01; //CS0
  583. case 63: return 0x04; //CS2
  584. }
  585. return 0;
  586. }
  587. bool SPI1Class::pinIsChipSelect(uint8_t pin1, uint8_t pin2)
  588. {
  589. uint8_t pin1_mask, pin2_mask;
  590. if ((pin1_mask = (uint8_t)pinIsChipSelect(pin1)) == 0) return false;
  591. if ((pin2_mask = (uint8_t)pinIsChipSelect(pin2)) == 0) return false;
  592. //Serial.printf("pinIsChipSelect %d %d %x %x\n\r", pin1, pin2, pin1_mask, pin2_mask);
  593. if ((pin1_mask & pin2_mask) != 0) return false;
  594. return true;
  595. }
  596. // setCS() is not intended for use from normal Arduino programs/sketches.
  597. uint8_t SPI1Class::setCS(uint8_t pin)
  598. {
  599. switch (pin) {
  600. case 6: CORE_PIN6_CONFIG = PORT_PCR_MUX(7); return 0x01; // PTD4
  601. case 31: CORE_PIN31_CONFIG = PORT_PCR_MUX(2); return 0x01; // PTD5
  602. case 58: CORE_PIN58_CONFIG = PORT_PCR_MUX(2); return 0x02; //CS1
  603. case 62: CORE_PIN62_CONFIG = PORT_PCR_MUX(2); return 0x01; //CS0
  604. case 63: CORE_PIN63_CONFIG = PORT_PCR_MUX(2); return 0x04; //CS2
  605. }
  606. return 0;
  607. }
  608. void SPI1Class::transfer(void *buf, size_t count)
  609. {
  610. if (count == 0) return;
  611. uint8_t *p_write = (uint8_t *)buf;
  612. uint8_t *p_read = p_write;
  613. size_t count_read = count;
  614. bool lsbfirst = (SPI1_CTAR0 & SPI_CTAR_LSBFE) ? true : false;
  615. // Lets clear the reader queue
  616. SPI1_MCR = SPI_MCR_MSTR | SPI_MCR_CLR_RXF | SPI_MCR_PCSIS(0x1F);
  617. uint32_t sr;
  618. // Now lets loop while we still have data to output
  619. if (count & 1) {
  620. KINETISK_SPI1.PUSHR = *p_write++ | SPI_PUSHR_CTAS(0);
  621. count--;
  622. }
  623. while (count > 0) {
  624. // Push out the next byte;
  625. uint16_t w = (*p_write++) << 8;
  626. w |= *p_write++;
  627. if (lsbfirst) w = __builtin_bswap16(w);
  628. KINETISK_SPI1.PUSHR = w | SPI_PUSHR_CTAS(1);
  629. count -= 2; // how many bytes to output.
  630. // Make sure queue is not full before pushing next byte out
  631. do {
  632. sr = KINETISK_SPI1.SR;
  633. if (sr & 0xF0) {
  634. uint16_t w = KINETISK_SPI1.POPR; // Read any pending RX bytes in
  635. if (count_read & 1) {
  636. *p_read++ = w; // Read any pending RX bytes in
  637. count_read--;
  638. } else {
  639. if (lsbfirst) w = __builtin_bswap16(w);
  640. *p_read++ = w >> 8;
  641. *p_read++ = (w & 0xff);
  642. count_read -= 2;
  643. }
  644. }
  645. } while ((sr & (15 << 12)) > (0 << 12)); // SPI1 and 2 only have 1 item queue
  646. }
  647. // now lets wait for all of the read bytes to be returned...
  648. while (count_read) {
  649. sr = KINETISK_SPI1.SR;
  650. if (sr & 0xF0) {
  651. uint16_t w = KINETISK_SPI1.POPR; // Read any pending RX bytes in
  652. if (count_read & 1) {
  653. *p_read++ = w; // Read any pending RX bytes in
  654. count_read--;
  655. } else {
  656. if (lsbfirst) w = __builtin_bswap16(w);
  657. *p_read++ = w >> 8;
  658. *p_read++ = (w & 0xff);
  659. count_read -= 2;
  660. }
  661. }
  662. }
  663. }
  664. // SPI2 Class
  665. SPI2Class SPI2;
  666. uint8_t SPI2Class::interruptMasksUsed = 0;
  667. uint32_t SPI2Class::interruptMask[(NVIC_NUM_INTERRUPTS+31)/32];
  668. uint32_t SPI2Class::interruptSave[(NVIC_NUM_INTERRUPTS+31)/32];
  669. #ifdef SPI_TRANSACTION_MISMATCH_LED
  670. uint8_t SPI2Class::inTransactionFlag = 0;
  671. #endif
  672. void SPI2Class::begin()
  673. {
  674. SIM_SCGC3 |= SIM_SCGC3_SPI2;
  675. SPI2_MCR = SPI_MCR_MDIS | SPI_MCR_HALT | SPI_MCR_PCSIS(0x1F);
  676. SPI2_CTAR0 = SPI_CTAR_FMSZ(7) | SPI_CTAR_PBR(0) | SPI_CTAR_BR(1) | SPI_CTAR_CSSCK(1);
  677. SPI2_CTAR1 = SPI_CTAR_FMSZ(15) | SPI_CTAR_PBR(0) | SPI_CTAR_BR(1) | SPI_CTAR_CSSCK(1);
  678. SPI2_MCR = SPI_MCR_MSTR | SPI_MCR_PCSIS(0x1F);
  679. SPCR2.enable_pins(); // pins managed by SPCRemulation in avr_emulation.h
  680. }
  681. void SPI2Class::end() {
  682. SPCR2.disable_pins();
  683. SPI2_MCR = SPI_MCR_MDIS | SPI_MCR_HALT | SPI_MCR_PCSIS(0x1F);
  684. }
  685. void SPI2Class::usingInterrupt(IRQ_NUMBER_t interruptName)
  686. {
  687. uint32_t n = (uint32_t)interruptName;
  688. if (n >= NVIC_NUM_INTERRUPTS) return;
  689. //Serial.print("usingInterrupt ");
  690. //Serial.println(n);
  691. interruptMasksUsed |= (1 << (n >> 5));
  692. interruptMask[n >> 5] |= (1 << (n & 0x1F));
  693. //Serial.printf("interruptMasksUsed = %d\n", interruptMasksUsed);
  694. //Serial.printf("interruptMask[0] = %08X\n", interruptMask[0]);
  695. //Serial.printf("interruptMask[1] = %08X\n", interruptMask[1]);
  696. //Serial.printf("interruptMask[2] = %08X\n", interruptMask[2]);
  697. }
  698. void SPI2Class::notUsingInterrupt(IRQ_NUMBER_t interruptName)
  699. {
  700. uint32_t n = (uint32_t)interruptName;
  701. if (n >= NVIC_NUM_INTERRUPTS) return;
  702. interruptMask[n >> 5] &= ~(1 << (n & 0x1F));
  703. if (interruptMask[n >> 5] == 0) {
  704. interruptMasksUsed &= ~(1 << (n >> 5));
  705. }
  706. }
  707. static void updateCTAR2(uint32_t ctar)
  708. {
  709. if (SPI2_CTAR0 != ctar) {
  710. uint32_t mcr = SPI2_MCR;
  711. if (mcr & SPI_MCR_MDIS) {
  712. SPI2_CTAR0 = ctar;
  713. SPI2_CTAR1 = ctar | SPI_CTAR_FMSZ(8);
  714. } else {
  715. SPI2_MCR = SPI_MCR_MDIS | SPI_MCR_HALT | SPI_MCR_PCSIS(0x1F);
  716. SPI2_CTAR0 = ctar;
  717. SPI2_CTAR1 = ctar | SPI_CTAR_FMSZ(8);
  718. SPI2_MCR = mcr;
  719. }
  720. }
  721. }
  722. void SPI2Class::setBitOrder(uint8_t bitOrder)
  723. {
  724. SIM_SCGC3 |= SIM_SCGC3_SPI2;
  725. uint32_t ctar = SPI2_CTAR0;
  726. if (bitOrder == LSBFIRST) {
  727. ctar |= SPI_CTAR_LSBFE;
  728. } else {
  729. ctar &= ~SPI_CTAR_LSBFE;
  730. }
  731. updateCTAR2(ctar);
  732. }
  733. void SPI2Class::setDataMode(uint8_t dataMode)
  734. {
  735. SIM_SCGC3 |= SIM_SCGC3_SPI2;
  736. // TODO: implement with native code
  737. SPCR2 = (SPCR2 & ~SPI_MODE_MASK) | dataMode;
  738. }
  739. void SPI2Class::setClockDivider_noInline(uint32_t clk)
  740. {
  741. SIM_SCGC3 |= SIM_SCGC3_SPI2;
  742. uint32_t ctar = SPI2_CTAR0;
  743. ctar &= (SPI_CTAR_CPOL | SPI_CTAR_CPHA | SPI_CTAR_LSBFE);
  744. if (ctar & SPI_CTAR_CPHA) {
  745. clk = (clk & 0xFFFF0FFF) | ((clk & 0xF000) >> 4);
  746. }
  747. ctar |= clk;
  748. updateCTAR2(ctar);
  749. }
  750. uint8_t SPI2Class::pinIsChipSelect(uint8_t pin)
  751. {
  752. switch (pin) {
  753. case 43: return 0x01; // CS0
  754. case 54: return 0x02; // CS1
  755. case 55: return 0x01; // CS0
  756. }
  757. return 0;
  758. }
  759. bool SPI2Class::pinIsChipSelect(uint8_t pin1, uint8_t pin2)
  760. {
  761. uint8_t pin1_mask, pin2_mask;
  762. if ((pin1_mask = (uint8_t)pinIsChipSelect(pin1)) == 0) return false;
  763. if ((pin2_mask = (uint8_t)pinIsChipSelect(pin2)) == 0) return false;
  764. //Serial.printf("pinIsChipSelect %d %d %x %x\n\r", pin1, pin2, pin1_mask, pin2_mask);
  765. if ((pin1_mask & pin2_mask) != 0) return false;
  766. return true;
  767. }
  768. // setCS() is not intended for use from normal Arduino programs/sketches.
  769. uint8_t SPI2Class::setCS(uint8_t pin)
  770. {
  771. switch (pin) {
  772. case 43: CORE_PIN43_CONFIG = PORT_PCR_MUX(2); return 0x01; // CS0
  773. case 54: CORE_PIN54_CONFIG = PORT_PCR_MUX(2); return 0x02; // CS1
  774. case 55: CORE_PIN55_CONFIG = PORT_PCR_MUX(2); return 0x01; // CS0
  775. }
  776. return 0;
  777. }
  778. void SPI2Class::transfer(void *buf, size_t count)
  779. {
  780. if (count == 0) return;
  781. uint8_t *p_write = (uint8_t *)buf;
  782. uint8_t *p_read = p_write;
  783. size_t count_read = count;
  784. bool lsbfirst = (SPI2_CTAR0 & SPI_CTAR_LSBFE) ? true : false;
  785. // Lets clear the reader queue
  786. SPI2_MCR = SPI_MCR_MSTR | SPI_MCR_CLR_RXF | SPI_MCR_PCSIS(0x1F);
  787. uint32_t sr;
  788. // Now lets loop while we still have data to output
  789. if (count & 1) {
  790. KINETISK_SPI2.PUSHR = *p_write++ | SPI_PUSHR_CTAS(0);
  791. count--;
  792. }
  793. while (count > 0) {
  794. // Push out the next byte;
  795. uint16_t w = (*p_write++) << 8;
  796. w |= *p_write++;
  797. if (lsbfirst) w = __builtin_bswap16(w);
  798. KINETISK_SPI2.PUSHR = w | SPI_PUSHR_CTAS(1);
  799. count -= 2; // how many bytes to output.
  800. // Make sure queue is not full before pushing next byte out
  801. do {
  802. sr = KINETISK_SPI2.SR;
  803. if (sr & 0xF0) {
  804. uint16_t w = KINETISK_SPI2.POPR; // Read any pending RX bytes in
  805. if (count_read & 1) {
  806. *p_read++ = w; // Read any pending RX bytes in
  807. count_read--;
  808. } else {
  809. if (lsbfirst) w = __builtin_bswap16(w);
  810. *p_read++ = w >> 8;
  811. *p_read++ = (w & 0xff);
  812. count_read -= 2;
  813. }
  814. }
  815. } while ((sr & (15 << 12)) > (0 << 12)); // SPI2 and 2 only have 1 item queue
  816. }
  817. // now lets wait for all of the read bytes to be returned...
  818. while (count_read) {
  819. sr = KINETISK_SPI2.SR;
  820. if (sr & 0xF0) {
  821. uint16_t w = KINETISK_SPI2.POPR; // Read any pending RX bytes in
  822. if (count_read & 1) {
  823. *p_read++ = w; // Read any pending RX bytes in
  824. count_read--;
  825. } else {
  826. if (lsbfirst) w = __builtin_bswap16(w);
  827. *p_read++ = w >> 8;
  828. *p_read++ = (w & 0xff);
  829. count_read -= 2;
  830. }
  831. }
  832. }
  833. }
  834. #endif
  835. /**********************************************************/
  836. /* 32 bit Teensy-LC */
  837. /**********************************************************/
  838. #elif defined(__arm__) && defined(TEENSYDUINO) && defined(KINETISL)
  839. SPIClass SPI;
  840. SPI1Class SPI1;
  841. uint32_t SPIClass::interruptMask = 0;
  842. uint32_t SPIClass::interruptSave = 0;
  843. uint32_t SPI1Class::interruptMask = 0;
  844. uint32_t SPI1Class::interruptSave = 0;
  845. #ifdef SPI_TRANSACTION_MISMATCH_LED
  846. uint8_t SPIClass::inTransactionFlag = 0;
  847. uint8_t SPI1Class::inTransactionFlag = 0;
  848. #endif
  849. void SPIClass::begin()
  850. {
  851. SIM_SCGC4 |= SIM_SCGC4_SPI0;
  852. SPI0_C1 = SPI_C1_SPE | SPI_C1_MSTR;
  853. SPI0_C2 = 0;
  854. uint8_t tmp __attribute__((unused)) = SPI0_S;
  855. SPCR.enable_pins(); // pins managed by SPCRemulation in avr_emulation.h
  856. }
  857. void SPIClass::end() {
  858. SPCR.disable_pins();
  859. SPI0_C1 = 0;
  860. }
  861. const uint16_t SPISettings::br_div_table[30] = {
  862. 2, 4, 6, 8, 10, 12, 14, 16, 20, 24,
  863. 28, 32, 40, 48, 56, 64, 80, 96, 112, 128,
  864. 160, 192, 224, 256, 320, 384, 448, 512, 640, 768,
  865. };
  866. const uint8_t SPISettings::br_clock_table[30] = {
  867. SPI_BR_SPPR(0) | SPI_BR_SPR(0),
  868. SPI_BR_SPPR(1) | SPI_BR_SPR(0),
  869. SPI_BR_SPPR(2) | SPI_BR_SPR(0),
  870. SPI_BR_SPPR(3) | SPI_BR_SPR(0),
  871. SPI_BR_SPPR(4) | SPI_BR_SPR(0),
  872. SPI_BR_SPPR(5) | SPI_BR_SPR(0),
  873. SPI_BR_SPPR(6) | SPI_BR_SPR(0),
  874. SPI_BR_SPPR(7) | SPI_BR_SPR(0),
  875. SPI_BR_SPPR(4) | SPI_BR_SPR(1),
  876. SPI_BR_SPPR(5) | SPI_BR_SPR(1),
  877. SPI_BR_SPPR(6) | SPI_BR_SPR(1),
  878. SPI_BR_SPPR(7) | SPI_BR_SPR(1),
  879. SPI_BR_SPPR(4) | SPI_BR_SPR(2),
  880. SPI_BR_SPPR(5) | SPI_BR_SPR(2),
  881. SPI_BR_SPPR(6) | SPI_BR_SPR(2),
  882. SPI_BR_SPPR(7) | SPI_BR_SPR(2),
  883. SPI_BR_SPPR(4) | SPI_BR_SPR(3),
  884. SPI_BR_SPPR(5) | SPI_BR_SPR(3),
  885. SPI_BR_SPPR(6) | SPI_BR_SPR(3),
  886. SPI_BR_SPPR(7) | SPI_BR_SPR(3),
  887. SPI_BR_SPPR(4) | SPI_BR_SPR(4),
  888. SPI_BR_SPPR(5) | SPI_BR_SPR(4),
  889. SPI_BR_SPPR(6) | SPI_BR_SPR(4),
  890. SPI_BR_SPPR(7) | SPI_BR_SPR(4),
  891. SPI_BR_SPPR(4) | SPI_BR_SPR(5),
  892. SPI_BR_SPPR(5) | SPI_BR_SPR(5),
  893. SPI_BR_SPPR(6) | SPI_BR_SPR(5),
  894. SPI_BR_SPPR(7) | SPI_BR_SPR(5),
  895. SPI_BR_SPPR(4) | SPI_BR_SPR(6),
  896. SPI_BR_SPPR(5) | SPI_BR_SPR(6)
  897. };
  898. // setCS() is not intended for use from normal Arduino programs/sketches.
  899. uint8_t SPIClass::setCS(uint8_t pin)
  900. {
  901. switch (pin) {
  902. case 10: CORE_PIN10_CONFIG = PORT_PCR_MUX(2); return 0x01; // PTC4
  903. case 2: CORE_PIN2_CONFIG = PORT_PCR_MUX(2); return 0x01; // PTD0
  904. }
  905. return 0;
  906. }
  907. void SPI1Class::begin()
  908. {
  909. SIM_SCGC4 |= SIM_SCGC4_SPI1;
  910. SPI1_C1 = SPI_C1_SPE | SPI_C1_MSTR;
  911. SPI1_C2 = 0;
  912. uint8_t tmp __attribute__((unused)) = SPI1_S;
  913. SPCR1.enable_pins(); // pins managed by SPCRemulation in avr_emulation.h
  914. }
  915. void SPI1Class::end() {
  916. SPCR1.disable_pins();
  917. SPI1_C1 = 0;
  918. }
  919. // setCS() is not intended for use from normal Arduino programs/sketches.
  920. uint8_t SPI1Class::setCS(uint8_t pin)
  921. {
  922. switch (pin) {
  923. case 6: CORE_PIN6_CONFIG = PORT_PCR_MUX(2); return 0x01; // PTD4
  924. }
  925. return 0;
  926. }
  927. #endif