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 година
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286
  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