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.

287 lines
8.5KB

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