Nie możesz wybrać więcej, niż 25 tematów Tematy muszą się zaczynać od litery lub cyfry, mogą zawierać myślniki ('-') i mogą mieć do 35 znaków.

297 lines
8.6KB

  1. /*
  2. * Copyright (c) 2010 by Cristian Maglie <c.maglie@bug.st>
  3. * Copyright (c) 2014 by Paul Stoffregen <paul@pjrc.com> (Transaction API)
  4. * Copyright (c) 2014 by Matthijs Kooijman <matthijs@stdin.nl> (SPISettings)
  5. * SPI Master library for arduino.
  6. *
  7. * This file is free software; you can redistribute it and/or modify
  8. * it under the terms of either the GNU General Public License version 2
  9. * or the GNU Lesser General Public License version 2.1, both as
  10. * published by the Free Software Foundation.
  11. */
  12. #ifndef _SPI_H_INCLUDED
  13. #define _SPI_H_INCLUDED
  14. #include <Arduino.h>
  15. // SPI_HAS_TRANSACTION means SPI has beginTransaction(), endTransaction(),
  16. // usingInterrupt(), and the actual clock speed names
  17. #define SPI_HAS_TRANSACTION 1
  18. // define SPI_AVR_EIMSK for AVR boards with external interrupt pins
  19. #if defined(__AVR__)
  20. #if defined(EIMSK)
  21. #define SPI_AVR_EIMSK EIMSK
  22. #elif defined(GICR)
  23. #define SPI_AVR_EIMSK GICR
  24. #elif defined(GIMSK)
  25. #define SPI_AVR_EIMSK GIMSK
  26. #endif
  27. #endif
  28. #ifndef LSBFIRST
  29. #define LSBFIRST 0
  30. #endif
  31. #ifndef MSBFIRST
  32. #define MSBFIRST 1
  33. #endif
  34. #define SPI_MODE0 0x00
  35. #define SPI_MODE1 0x04
  36. #define SPI_MODE2 0x08
  37. #define SPI_MODE3 0x0C
  38. #define SPI_MODE_MASK 0x0C // CPOL = bit 3, CPHA = bit 2 on SPCR
  39. #define SPI_CLOCK_MASK 0x03 // SPR1 = bit 1, SPR0 = bit 0 on SPCR
  40. #define SPI_2XCLOCK_MASK 0x01 // SPI2X = bit 0 on SPSR
  41. class SPISettings {
  42. public:
  43. SPISettings(uint32_t clock, uint8_t bitOrder, uint8_t dataMode) {
  44. if (__builtin_constant_p(clock)) {
  45. init_AlwaysInline(clock, bitOrder, dataMode);
  46. } else {
  47. init_MightInline(clock, bitOrder, dataMode);
  48. }
  49. }
  50. SPISettings() {
  51. init_AlwaysInline(4000000, MSBFIRST, SPI_MODE0);
  52. }
  53. private:
  54. void init_MightInline(uint32_t clock, uint8_t bitOrder, uint8_t dataMode) {
  55. init_AlwaysInline(clock, bitOrder, dataMode);
  56. }
  57. void init_AlwaysInline(uint32_t clock, uint8_t bitOrder, uint8_t dataMode)
  58. __attribute__((__always_inline__)) {
  59. // Clock settings are defined as follows. Note that this shows SPI2X
  60. // inverted, so the bits form increasing numbers. Also note that
  61. // fosc/64 appears twice
  62. // SPR1 SPR0 ~SPI2X Freq
  63. // 0 0 0 fosc/2
  64. // 0 0 1 fosc/4
  65. // 0 1 0 fosc/8
  66. // 0 1 1 fosc/16
  67. // 1 0 0 fosc/32
  68. // 1 0 1 fosc/64
  69. // 1 1 0 fosc/64
  70. // 1 1 1 fosc/128
  71. // We find the fastest clock that is less than or equal to the
  72. // given clock rate. The clock divider that results in clock_setting
  73. // is 2 ^^ (clock_div + 1). If nothing is slow enough, we'll use the
  74. // slowest (128 == 2 ^^ 7, so clock_div = 6).
  75. uint8_t clockDiv;
  76. // When the clock is known at compiletime, use this if-then-else
  77. // cascade, which the compiler knows how to completely optimize
  78. // away. When clock is not known, use a loop instead, which generates
  79. // shorter code.
  80. if (__builtin_constant_p(clock)) {
  81. if (clock >= F_CPU / 2) {
  82. clockDiv = 0;
  83. } else if (clock >= F_CPU / 4) {
  84. clockDiv = 1;
  85. } else if (clock >= F_CPU / 8) {
  86. clockDiv = 2;
  87. } else if (clock >= F_CPU / 16) {
  88. clockDiv = 3;
  89. } else if (clock >= F_CPU / 32) {
  90. clockDiv = 4;
  91. } else if (clock >= F_CPU / 64) {
  92. clockDiv = 5;
  93. } else {
  94. clockDiv = 6;
  95. }
  96. } else {
  97. uint32_t clockSetting = F_CPU / 2;
  98. clockDiv = 0;
  99. while (clockDiv < 6 && clock < clockSetting) {
  100. clockSetting /= 2;
  101. clockDiv++;
  102. }
  103. }
  104. // Compensate for the duplicate fosc/64
  105. if (clockDiv == 6)
  106. clockDiv = 7;
  107. // Invert the SPI2X bit
  108. clockDiv ^= 0x1;
  109. // Pack into the SPISettings class
  110. spcr = _BV(SPE) | _BV(MSTR) | ((bitOrder == LSBFIRST) ? _BV(DORD) : 0) |
  111. (dataMode & SPI_MODE_MASK) | ((clockDiv >> 1) & SPI_CLOCK_MASK);
  112. spsr = clockDiv & SPI_2XCLOCK_MASK;
  113. }
  114. uint8_t spcr;
  115. uint8_t spsr;
  116. friend class SPIClass;
  117. };
  118. class SPIClass {
  119. public:
  120. // Initialize the SPI library
  121. static void begin();
  122. // If SPI is to used from within an interrupt, this function registers
  123. // that interrupt with the SPI library, so beginTransaction() can
  124. // prevent conflicts. The input interruptNumber is the number used
  125. // with attachInterrupt. If SPI is used from a different interrupt
  126. // (eg, a timer), interruptNumber should be 255.
  127. static void usingInterrupt(uint8_t interruptNumber);
  128. #if defined(__arm__) && defined(CORE_TEENSY)
  129. static void usingInterrupt(IRQ_NUMBER_t interruptName);
  130. #endif
  131. // Before using SPI.transfer() or asserting chip select pins,
  132. // this function is used to gain exclusive access to the SPI bus
  133. // and configure the correct settings.
  134. inline static void beginTransaction(SPISettings settings) {
  135. if (interruptMode > 0) {
  136. #ifdef SPI_AVR_EIMSK
  137. if (interruptMode == 1) {
  138. interruptSave = SPI_AVR_EIMSK;
  139. SPI_AVR_EIMSK &= ~interruptMask;
  140. } else
  141. #endif
  142. {
  143. interruptSave = SREG;
  144. cli();
  145. }
  146. }
  147. SPCR = settings.spcr;
  148. SPSR = settings.spsr;
  149. }
  150. // Write to the SPI bus (MOSI pin) and also receive (MISO pin)
  151. inline static byte transfer(byte data) {
  152. SPDR = data;
  153. asm volatile("nop");
  154. while (!(SPSR & _BV(SPIF))) ; // wait
  155. return SPDR;
  156. }
  157. inline static void transfer(void *buf, size_t count) {
  158. if (count == 0) return;
  159. uint8_t *p = (uint8_t *)buf;
  160. SPDR = *p;
  161. while (--count > 0) {
  162. uint8_t out = *(p + 1);
  163. while (!(SPSR & _BV(SPIF))) ;
  164. uint8_t in = SPDR;
  165. SPDR = out;
  166. *p++ = in;
  167. }
  168. while (!(SPSR & _BV(SPIF))) ;
  169. *p = SPDR;
  170. }
  171. // After performing a group of transfers and releasing the chip select
  172. // signal, this function allows others to access the SPI bus
  173. inline static void endTransaction(void) {
  174. if (interruptMode > 0) {
  175. #ifdef SPI_AVR_EIMSK
  176. if (interruptMode == 1) {
  177. SPI_AVR_EIMSK = interruptSave;
  178. } else
  179. #endif
  180. {
  181. SREG = interruptSave;
  182. }
  183. }
  184. }
  185. // Disable the SPI bus
  186. static void end();
  187. // This function is deprecated. New applications should use
  188. // beginTransaction() to configure SPI settings.
  189. inline static void setBitOrder(uint8_t bitOrder) {
  190. if (bitOrder == LSBFIRST) SPCR |= _BV(DORD);
  191. else SPCR &= ~(_BV(DORD));
  192. }
  193. // This function is deprecated. New applications should use
  194. // beginTransaction() to configure SPI settings.
  195. inline static void setDataMode(uint8_t dataMode) {
  196. SPCR = (SPCR & ~SPI_MODE_MASK) | dataMode;
  197. }
  198. // This function is deprecated. New applications should use
  199. // beginTransaction() to configure SPI settings.
  200. inline static void setClockDivider(uint8_t clockDiv) {
  201. SPCR = (SPCR & ~SPI_CLOCK_MASK) | (clockDiv & SPI_CLOCK_MASK);
  202. SPSR = (SPSR & ~SPI_2XCLOCK_MASK) | ((clockDiv >> 2) & SPI_2XCLOCK_MASK);
  203. }
  204. // These undocumented functions should not be used. SPI.transfer()
  205. // polls the hardware flag which is automatically cleared as the
  206. // AVR responds to SPI's interrupt
  207. inline static void attachInterrupt() { SPCR |= _BV(SPIE); }
  208. inline static void detachInterrupt() { SPCR &= ~_BV(SPIE); }
  209. #if defined(__arm__) && defined(CORE_TEENSY)
  210. inline void setMOSI(uint8_t pin) __attribute__((always_inline)) { SPCR.setMOSI(pin); }
  211. inline void setMISO(uint8_t pin) __attribute__((always_inline)) { SPCR.setMISO(pin); }
  212. inline void setSCK(uint8_t pin) __attribute__((always_inline)) { SPCR.setSCK(pin); }
  213. #endif
  214. private:
  215. static uint8_t interruptMode; // 0=none, 1=mask, 2=global
  216. static uint8_t interruptMask; // which interrupts to mask
  217. static uint8_t interruptSave; // temp storage, to restore state
  218. };
  219. extern SPIClass SPI;
  220. #define SPI_CLOCK_DIV4 0x00
  221. #define SPI_CLOCK_DIV16 0x01
  222. #define SPI_CLOCK_DIV64 0x02
  223. #define SPI_CLOCK_DIV128 0x03
  224. #define SPI_CLOCK_DIV2 0x04
  225. #define SPI_CLOCK_DIV8 0x05
  226. #define SPI_CLOCK_DIV32 0x06
  227. // mapping of interrupt numbers to bits within SPI_AVR_EIMSK
  228. #ifdef SPI_AVR_EIMSK
  229. #if defined(__AVR_ATmega32U4__)
  230. #define SPI_INT0_MASK (1<<INT0)
  231. #define SPI_INT1_MASK (1<<INT1)
  232. #define SPI_INT2_MASK (1<<INT2)
  233. #define SPI_INT3_MASK (1<<INT3)
  234. #define SPI_INT4_MASK (1<<INT6)
  235. #elif defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__)
  236. #define SPI_INT0_MASK (1<<INT0)
  237. #define SPI_INT1_MASK (1<<INT1)
  238. #define SPI_INT2_MASK (1<<INT2)
  239. #define SPI_INT3_MASK (1<<INT3)
  240. #define SPI_INT4_MASK (1<<INT4)
  241. #define SPI_INT5_MASK (1<<INT5)
  242. #define SPI_INT6_MASK (1<<INT6)
  243. #define SPI_INT7_MASK (1<<INT7)
  244. #elif defined(EICRA) && defined(EICRB) && defined(EIMSK)
  245. #define SPI_INT0_MASK (1<<INT4)
  246. #define SPI_INT1_MASK (1<<INT5)
  247. #define SPI_INT2_MASK (1<<INT0)
  248. #define SPI_INT3_MASK (1<<INT1)
  249. #define SPI_INT4_MASK (1<<INT2)
  250. #define SPI_INT5_MASK (1<<INT3)
  251. #define SPI_INT6_MASK (1<<INT6)
  252. #define SPI_INT7_MASK (1<<INT7)
  253. #else
  254. #ifdef INT0
  255. #define SPI_INT0_MASK (1<<INT0)
  256. #endif
  257. #ifdef INT1
  258. #define SPI_INT1_MASK (1<<INT1)
  259. #endif
  260. #ifdef INT2
  261. #define SPI_INT2_MASK (1<<INT2)
  262. #endif
  263. #endif
  264. #endif //SPI_AVR_EIMSK
  265. #endif