You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

пре 10 година
пре 10 година
пре 10 година
пре 10 година
пре 10 година
пре 10 година
пре 10 година
пре 10 година
пре 10 година
пре 10 година
пре 10 година
пре 10 година
пре 10 година
пре 10 година
пре 10 година
пре 10 година
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252
  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. SPIClass SPI;
  13. /**********************************************************/
  14. /* 8 bit AVR-based boards */
  15. /**********************************************************/
  16. #if defined(__AVR__)
  17. uint8_t SPIClass::interruptMode = 0;
  18. uint8_t SPIClass::interruptMask = 0;
  19. uint8_t SPIClass::interruptSave = 0;
  20. void SPIClass::begin()
  21. {
  22. // Set SS to high so a connected chip will be "deselected" by default
  23. digitalWrite(SS, HIGH);
  24. // When the SS pin is set as OUTPUT, it can be used as
  25. // a general purpose output port (it doesn't influence
  26. // SPI operations).
  27. pinMode(SS, OUTPUT);
  28. // Warning: if the SS pin ever becomes a LOW INPUT then SPI
  29. // automatically switches to Slave, so the data direction of
  30. // the SS pin MUST be kept as OUTPUT.
  31. SPCR |= _BV(MSTR);
  32. SPCR |= _BV(SPE);
  33. // Set direction register for SCK and MOSI pin.
  34. // MISO pin automatically overrides to INPUT.
  35. // By doing this AFTER enabling SPI, we avoid accidentally
  36. // clocking in a single bit since the lines go directly
  37. // from "input" to SPI control.
  38. // http://code.google.com/p/arduino/issues/detail?id=888
  39. pinMode(SCK, OUTPUT);
  40. pinMode(MOSI, OUTPUT);
  41. }
  42. void SPIClass::end() {
  43. SPCR &= ~_BV(SPE);
  44. }
  45. void SPIClass::usingInterrupt(uint8_t interruptNumber)
  46. {
  47. uint8_t mask;
  48. if (interruptMode > 1) return;
  49. noInterrupts();
  50. switch (interruptNumber) {
  51. #ifdef SPI_INT0_MASK
  52. case 0: mask = SPI_INT0_MASK; break;
  53. #endif
  54. #ifdef SPI_INT1_MASK
  55. case 1: mask = SPI_INT1_MASK; break;
  56. #endif
  57. #ifdef SPI_INT2_MASK
  58. case 2: mask = SPI_INT2_MASK; break;
  59. #endif
  60. #ifdef SPI_INT3_MASK
  61. case 3: mask = SPI_INT3_MASK; break;
  62. #endif
  63. #ifdef SPI_INT4_MASK
  64. case 4: mask = SPI_INT4_MASK; break;
  65. #endif
  66. #ifdef SPI_INT5_MASK
  67. case 5: mask = SPI_INT5_MASK; break;
  68. #endif
  69. #ifdef SPI_INT6_MASK
  70. case 6: mask = SPI_INT6_MASK; break;
  71. #endif
  72. #ifdef SPI_INT7_MASK
  73. case 7: mask = SPI_INT7_MASK; break;
  74. #endif
  75. default:
  76. interruptMode = 2;
  77. interrupts();
  78. return;
  79. }
  80. interruptMode = 1;
  81. interruptMask |= mask;
  82. interrupts();
  83. }
  84. /**********************************************************/
  85. /* 32 bit Teensy 3.0 and 3.1 */
  86. /**********************************************************/
  87. #elif defined(__arm__) && defined(TEENSYDUINO)
  88. uint8_t SPIClass::interruptMode = 0;
  89. uint8_t SPIClass::interruptMask = 0;
  90. uint8_t SPIClass::interruptSave = 0;
  91. void SPIClass::begin()
  92. {
  93. SIM_SCGC6 |= SIM_SCGC6_SPI0;
  94. SPI0_MCR = SPI_MCR_MDIS | SPI_MCR_HALT | SPI_MCR_PCSIS(0x1F);
  95. SPI0_CTAR0 = SPI_CTAR_FMSZ(7) | SPI_CTAR_PBR(0) | SPI_CTAR_BR(1) | SPI_CTAR_CSSCK(1);
  96. SPI0_CTAR1 = SPI_CTAR_FMSZ(15) | SPI_CTAR_PBR(0) | SPI_CTAR_BR(1) | SPI_CTAR_CSSCK(1);
  97. SPI0_MCR = SPI_MCR_MSTR | SPI_MCR_PCSIS(0x1F);
  98. SPCR.enable_pins(); // pins managed by SPCRemulation in avr_emulation.h
  99. }
  100. void SPIClass::end() {
  101. SPCR.disable_pins();
  102. SPI0_MCR = SPI_MCR_MDIS | SPI_MCR_HALT | SPI_MCR_PCSIS(0x1F);
  103. }
  104. void SPIClass::usingInterrupt(uint8_t interruptNumber)
  105. {
  106. // TODO: implement this...
  107. }
  108. void SPIClass::usingInterrupt(IRQ_NUMBER_t interruptName)
  109. {
  110. // TODO: implement this...
  111. }
  112. const uint16_t SPISettings::ctar_div_table[23] = {
  113. 2, 3, 4, 5, 6, 8, 10, 12, 16, 20, 24, 32, 40,
  114. 56, 64, 96, 128, 192, 256, 384, 512, 640, 768
  115. };
  116. const uint32_t SPISettings::ctar_clock_table[23] = {
  117. SPI_CTAR_PBR(0) | SPI_CTAR_BR(0) | SPI_CTAR_DBR | SPI_CTAR_CSSCK(0),
  118. SPI_CTAR_PBR(1) | SPI_CTAR_BR(0) | SPI_CTAR_DBR | SPI_CTAR_CSSCK(0),
  119. SPI_CTAR_PBR(0) | SPI_CTAR_BR(0) | SPI_CTAR_CSSCK(0),
  120. SPI_CTAR_PBR(2) | SPI_CTAR_BR(0) | SPI_CTAR_DBR | SPI_CTAR_CSSCK(0),
  121. SPI_CTAR_PBR(1) | SPI_CTAR_BR(0) | SPI_CTAR_CSSCK(0),
  122. SPI_CTAR_PBR(0) | SPI_CTAR_BR(1) | SPI_CTAR_CSSCK(1),
  123. SPI_CTAR_PBR(2) | SPI_CTAR_BR(0) | SPI_CTAR_CSSCK(0),
  124. SPI_CTAR_PBR(1) | SPI_CTAR_BR(1) | SPI_CTAR_CSSCK(1),
  125. SPI_CTAR_PBR(0) | SPI_CTAR_BR(3) | SPI_CTAR_CSSCK(2),
  126. SPI_CTAR_PBR(2) | SPI_CTAR_BR(1) | SPI_CTAR_CSSCK(0),
  127. SPI_CTAR_PBR(1) | SPI_CTAR_BR(3) | SPI_CTAR_CSSCK(2),
  128. SPI_CTAR_PBR(0) | SPI_CTAR_BR(4) | SPI_CTAR_CSSCK(3),
  129. SPI_CTAR_PBR(2) | SPI_CTAR_BR(3) | SPI_CTAR_CSSCK(2),
  130. SPI_CTAR_PBR(3) | SPI_CTAR_BR(3) | SPI_CTAR_CSSCK(2),
  131. SPI_CTAR_PBR(0) | SPI_CTAR_BR(5) | SPI_CTAR_CSSCK(4),
  132. SPI_CTAR_PBR(1) | SPI_CTAR_BR(5) | SPI_CTAR_CSSCK(4),
  133. SPI_CTAR_PBR(0) | SPI_CTAR_BR(6) | SPI_CTAR_CSSCK(5),
  134. SPI_CTAR_PBR(1) | SPI_CTAR_BR(6) | SPI_CTAR_CSSCK(5),
  135. SPI_CTAR_PBR(0) | SPI_CTAR_BR(7) | SPI_CTAR_CSSCK(6),
  136. SPI_CTAR_PBR(1) | SPI_CTAR_BR(7) | SPI_CTAR_CSSCK(6),
  137. SPI_CTAR_PBR(0) | SPI_CTAR_BR(8) | SPI_CTAR_CSSCK(7),
  138. SPI_CTAR_PBR(2) | SPI_CTAR_BR(7) | SPI_CTAR_CSSCK(6),
  139. SPI_CTAR_PBR(1) | SPI_CTAR_BR(8) | SPI_CTAR_CSSCK(7)
  140. };
  141. static void updateCTAR(uint32_t ctar)
  142. {
  143. if (SPI0_CTAR0 != ctar) {
  144. uint32_t mcr = SPI0_MCR;
  145. if (mcr & SPI_MCR_MDIS) {
  146. SPI0_CTAR0 = ctar;
  147. SPI0_CTAR1 = ctar | SPI_CTAR_FMSZ(8);
  148. } else {
  149. SPI0_MCR = SPI_MCR_MDIS | SPI_MCR_HALT | SPI_MCR_PCSIS(0x1F);
  150. SPI0_CTAR0 = ctar;
  151. SPI0_CTAR1 = ctar | SPI_CTAR_FMSZ(8);
  152. SPI0_MCR = mcr;
  153. }
  154. }
  155. }
  156. void SPIClass::setBitOrder(uint8_t bitOrder)
  157. {
  158. SIM_SCGC6 |= SIM_SCGC6_SPI0;
  159. uint32_t ctar = SPI0_CTAR0;
  160. if (bitOrder == LSBFIRST) {
  161. ctar |= SPI_CTAR_LSBFE;
  162. } else {
  163. ctar &= ~SPI_CTAR_LSBFE;
  164. }
  165. updateCTAR(ctar);
  166. }
  167. void SPIClass::setDataMode(uint8_t dataMode)
  168. {
  169. SIM_SCGC6 |= SIM_SCGC6_SPI0;
  170. // TODO: implement with native code
  171. SPCR = (SPCR & ~SPI_MODE_MASK) | dataMode;
  172. }
  173. void SPIClass::setClockDivider_noInline(uint32_t clk)
  174. {
  175. SIM_SCGC6 |= SIM_SCGC6_SPI0;
  176. uint32_t ctar = SPI0_CTAR0;
  177. ctar &= (SPI_CTAR_CPOL | SPI_CTAR_CPHA | SPI_CTAR_LSBFE);
  178. if (ctar & SPI_CTAR_CPHA) {
  179. clk = (clk & 0xFFFF0FFF) | ((clk & 0xF000) >> 4);
  180. }
  181. ctar |= clk;
  182. updateCTAR(ctar);
  183. }
  184. bool SPIClass::pinIsChipSelect(uint8_t pin)
  185. {
  186. if (pin == 10 || pin == 9 || pin == 6 || pin == 2 || pin == 15) return true;
  187. if (pin >= 20 && pin <= 23) return true;
  188. return false;
  189. }
  190. bool SPIClass::pinIsChipSelect(uint8_t pin1, uint8_t pin2)
  191. {
  192. if (!pinIsChipSelect(pin1) || !pinIsChipSelect(pin2)) return false;
  193. if ((pin1 == 2 && pin2 == 10) || (pin1 == 10 && pin2 == 2)) return false;
  194. if ((pin1 == 6 && pin2 == 9) || (pin1 == 9 && pin2 == 6)) return false;
  195. if ((pin1 == 20 && pin2 == 23) || (pin1 == 23 && pin2 == 20)) return false;
  196. if ((pin1 == 21 && pin2 == 22) || (pin1 == 22 && pin2 == 21)) return false;
  197. return true;
  198. }
  199. uint8_t SPIClass::setCS(uint8_t pin)
  200. {
  201. switch (pin) {
  202. case 10: CORE_PIN10_CONFIG = PORT_PCR_MUX(2); return 0x01; // PTC4
  203. case 2: CORE_PIN2_CONFIG = PORT_PCR_MUX(2); return 0x01; // PTD0
  204. case 9: CORE_PIN9_CONFIG = PORT_PCR_MUX(2); return 0x02; // PTC3
  205. case 6: CORE_PIN6_CONFIG = PORT_PCR_MUX(2); return 0x02; // PTD4
  206. case 20: CORE_PIN20_CONFIG = PORT_PCR_MUX(2); return 0x04; // PTD5
  207. case 23: CORE_PIN23_CONFIG = PORT_PCR_MUX(2); return 0x04; // PTC2
  208. case 21: CORE_PIN21_CONFIG = PORT_PCR_MUX(2); return 0x08; // PTD6
  209. case 22: CORE_PIN22_CONFIG = PORT_PCR_MUX(2); return 0x08; // PTC1
  210. case 15: CORE_PIN15_CONFIG = PORT_PCR_MUX(2); return 0x10; // PTC0
  211. }
  212. return 0;
  213. }
  214. #endif