Nevar pievienot vairāk kā 25 tēmas Tēmai ir jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un var būt līdz 35 simboliem gara.

522 rindas
16KB

  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 SPISetting(clock, bitOrder, dataMode)
  17. #define SPI_HAS_TRANSACTION 1
  18. #ifndef LSBFIRST
  19. #define LSBFIRST 0
  20. #endif
  21. #ifndef MSBFIRST
  22. #define MSBFIRST 1
  23. #endif
  24. #define SPI_MODE0 0x00
  25. #define SPI_MODE1 0x04
  26. #define SPI_MODE2 0x08
  27. #define SPI_MODE3 0x0C
  28. #define SPI_CLOCK_DIV4 0x00
  29. #define SPI_CLOCK_DIV16 0x01
  30. #define SPI_CLOCK_DIV64 0x02
  31. #define SPI_CLOCK_DIV128 0x03
  32. #define SPI_CLOCK_DIV2 0x04
  33. #define SPI_CLOCK_DIV8 0x05
  34. #define SPI_CLOCK_DIV32 0x06
  35. #define SPI_MODE_MASK 0x0C // CPOL = bit 3, CPHA = bit 2 on SPCR
  36. #define SPI_CLOCK_MASK 0x03 // SPR1 = bit 1, SPR0 = bit 0 on SPCR
  37. #define SPI_2XCLOCK_MASK 0x01 // SPI2X = bit 0 on SPSR
  38. /**********************************************************/
  39. /* 8 bit AVR-based boards */
  40. /**********************************************************/
  41. #if defined(__AVR__)
  42. // define SPI_AVR_EIMSK for AVR boards with external interrupt pins
  43. #if defined(EIMSK)
  44. #define SPI_AVR_EIMSK EIMSK
  45. #elif defined(GICR)
  46. #define SPI_AVR_EIMSK GICR
  47. #elif defined(GIMSK)
  48. #define SPI_AVR_EIMSK GIMSK
  49. #endif
  50. class SPISettings {
  51. public:
  52. SPISettings(uint32_t clock, uint8_t bitOrder, uint8_t dataMode) {
  53. if (__builtin_constant_p(clock)) {
  54. init_AlwaysInline(clock, bitOrder, dataMode);
  55. } else {
  56. init_MightInline(clock, bitOrder, dataMode);
  57. }
  58. }
  59. SPISettings() {
  60. init_AlwaysInline(4000000, MSBFIRST, SPI_MODE0);
  61. }
  62. private:
  63. void init_MightInline(uint32_t clock, uint8_t bitOrder, uint8_t dataMode) {
  64. init_AlwaysInline(clock, bitOrder, dataMode);
  65. }
  66. void init_AlwaysInline(uint32_t clock, uint8_t bitOrder, uint8_t dataMode)
  67. __attribute__((__always_inline__)) {
  68. // Clock settings are defined as follows. Note that this shows SPI2X
  69. // inverted, so the bits form increasing numbers. Also note that
  70. // fosc/64 appears twice
  71. // SPR1 SPR0 ~SPI2X Freq
  72. // 0 0 0 fosc/2
  73. // 0 0 1 fosc/4
  74. // 0 1 0 fosc/8
  75. // 0 1 1 fosc/16
  76. // 1 0 0 fosc/32
  77. // 1 0 1 fosc/64
  78. // 1 1 0 fosc/64
  79. // 1 1 1 fosc/128
  80. // We find the fastest clock that is less than or equal to the
  81. // given clock rate. The clock divider that results in clock_setting
  82. // is 2 ^^ (clock_div + 1). If nothing is slow enough, we'll use the
  83. // slowest (128 == 2 ^^ 7, so clock_div = 6).
  84. uint8_t clockDiv;
  85. // When the clock is known at compiletime, use this if-then-else
  86. // cascade, which the compiler knows how to completely optimize
  87. // away. When clock is not known, use a loop instead, which generates
  88. // shorter code.
  89. if (__builtin_constant_p(clock)) {
  90. if (clock >= F_CPU / 2) {
  91. clockDiv = 0;
  92. } else if (clock >= F_CPU / 4) {
  93. clockDiv = 1;
  94. } else if (clock >= F_CPU / 8) {
  95. clockDiv = 2;
  96. } else if (clock >= F_CPU / 16) {
  97. clockDiv = 3;
  98. } else if (clock >= F_CPU / 32) {
  99. clockDiv = 4;
  100. } else if (clock >= F_CPU / 64) {
  101. clockDiv = 5;
  102. } else {
  103. clockDiv = 6;
  104. }
  105. } else {
  106. uint32_t clockSetting = F_CPU / 2;
  107. clockDiv = 0;
  108. while (clockDiv < 6 && clock < clockSetting) {
  109. clockSetting /= 2;
  110. clockDiv++;
  111. }
  112. }
  113. // Compensate for the duplicate fosc/64
  114. if (clockDiv == 6)
  115. clockDiv = 7;
  116. // Invert the SPI2X bit
  117. clockDiv ^= 0x1;
  118. // Pack into the SPISettings class
  119. spcr = _BV(SPE) | _BV(MSTR) | ((bitOrder == LSBFIRST) ? _BV(DORD) : 0) |
  120. (dataMode & SPI_MODE_MASK) | ((clockDiv >> 1) & SPI_CLOCK_MASK);
  121. spsr = clockDiv & SPI_2XCLOCK_MASK;
  122. }
  123. uint8_t spcr;
  124. uint8_t spsr;
  125. friend class SPIClass;
  126. };
  127. class SPIClass {
  128. public:
  129. // Initialize the SPI library
  130. static void begin();
  131. // If SPI is to used from within an interrupt, this function registers
  132. // that interrupt with the SPI library, so beginTransaction() can
  133. // prevent conflicts. The input interruptNumber is the number used
  134. // with attachInterrupt. If SPI is used from a different interrupt
  135. // (eg, a timer), interruptNumber should be 255.
  136. static void usingInterrupt(uint8_t interruptNumber);
  137. // Before using SPI.transfer() or asserting chip select pins,
  138. // this function is used to gain exclusive access to the SPI bus
  139. // and configure the correct settings.
  140. inline static void beginTransaction(SPISettings settings) {
  141. if (interruptMode > 0) {
  142. #ifdef SPI_AVR_EIMSK
  143. if (interruptMode == 1) {
  144. interruptSave = SPI_AVR_EIMSK;
  145. SPI_AVR_EIMSK &= ~interruptMask;
  146. } else
  147. #endif
  148. {
  149. interruptSave = SREG;
  150. cli();
  151. }
  152. }
  153. SPCR = settings.spcr;
  154. SPSR = settings.spsr;
  155. }
  156. // Write to the SPI bus (MOSI pin) and also receive (MISO pin)
  157. inline static uint8_t transfer(uint8_t data) {
  158. SPDR = data;
  159. asm volatile("nop");
  160. while (!(SPSR & _BV(SPIF))) ; // wait
  161. return SPDR;
  162. }
  163. inline static void transfer(void *buf, size_t count) {
  164. if (count == 0) return;
  165. uint8_t *p = (uint8_t *)buf;
  166. SPDR = *p;
  167. while (--count > 0) {
  168. uint8_t out = *(p + 1);
  169. while (!(SPSR & _BV(SPIF))) ;
  170. uint8_t in = SPDR;
  171. SPDR = out;
  172. *p++ = in;
  173. }
  174. while (!(SPSR & _BV(SPIF))) ;
  175. *p = SPDR;
  176. }
  177. // After performing a group of transfers and releasing the chip select
  178. // signal, this function allows others to access the SPI bus
  179. inline static void endTransaction(void) {
  180. if (interruptMode > 0) {
  181. #ifdef SPI_AVR_EIMSK
  182. if (interruptMode == 1) {
  183. SPI_AVR_EIMSK = interruptSave;
  184. } else
  185. #endif
  186. {
  187. SREG = interruptSave;
  188. }
  189. }
  190. }
  191. // Disable the SPI bus
  192. static void end();
  193. // This function is deprecated. New applications should use
  194. // beginTransaction() to configure SPI settings.
  195. inline static void setBitOrder(uint8_t bitOrder) {
  196. if (bitOrder == LSBFIRST) SPCR |= _BV(DORD);
  197. else SPCR &= ~(_BV(DORD));
  198. }
  199. // This function is deprecated. New applications should use
  200. // beginTransaction() to configure SPI settings.
  201. inline static void setDataMode(uint8_t dataMode) {
  202. SPCR = (SPCR & ~SPI_MODE_MASK) | dataMode;
  203. }
  204. // This function is deprecated. New applications should use
  205. // beginTransaction() to configure SPI settings.
  206. inline static void setClockDivider(uint8_t clockDiv) {
  207. SPCR = (SPCR & ~SPI_CLOCK_MASK) | (clockDiv & SPI_CLOCK_MASK);
  208. SPSR = (SPSR & ~SPI_2XCLOCK_MASK) | ((clockDiv >> 2) & SPI_2XCLOCK_MASK);
  209. }
  210. // These undocumented functions should not be used. SPI.transfer()
  211. // polls the hardware flag which is automatically cleared as the
  212. // AVR responds to SPI's interrupt
  213. inline static void attachInterrupt() { SPCR |= _BV(SPIE); }
  214. inline static void detachInterrupt() { SPCR &= ~_BV(SPIE); }
  215. private:
  216. static uint8_t interruptMode; // 0=none, 1=mask, 2=global
  217. static uint8_t interruptMask; // which interrupts to mask
  218. static uint8_t interruptSave; // temp storage, to restore state
  219. };
  220. // mapping of interrupt numbers to bits within SPI_AVR_EIMSK
  221. #if defined(__AVR_ATmega32U4__)
  222. #define SPI_INT0_MASK (1<<INT0)
  223. #define SPI_INT1_MASK (1<<INT1)
  224. #define SPI_INT2_MASK (1<<INT2)
  225. #define SPI_INT3_MASK (1<<INT3)
  226. #define SPI_INT4_MASK (1<<INT6)
  227. #elif defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__)
  228. #define SPI_INT0_MASK (1<<INT0)
  229. #define SPI_INT1_MASK (1<<INT1)
  230. #define SPI_INT2_MASK (1<<INT2)
  231. #define SPI_INT3_MASK (1<<INT3)
  232. #define SPI_INT4_MASK (1<<INT4)
  233. #define SPI_INT5_MASK (1<<INT5)
  234. #define SPI_INT6_MASK (1<<INT6)
  235. #define SPI_INT7_MASK (1<<INT7)
  236. #elif defined(EICRA) && defined(EICRB) && defined(EIMSK)
  237. #define SPI_INT0_MASK (1<<INT4)
  238. #define SPI_INT1_MASK (1<<INT5)
  239. #define SPI_INT2_MASK (1<<INT0)
  240. #define SPI_INT3_MASK (1<<INT1)
  241. #define SPI_INT4_MASK (1<<INT2)
  242. #define SPI_INT5_MASK (1<<INT3)
  243. #define SPI_INT6_MASK (1<<INT6)
  244. #define SPI_INT7_MASK (1<<INT7)
  245. #else
  246. #ifdef INT0
  247. #define SPI_INT0_MASK (1<<INT0)
  248. #endif
  249. #ifdef INT1
  250. #define SPI_INT1_MASK (1<<INT1)
  251. #endif
  252. #ifdef INT2
  253. #define SPI_INT2_MASK (1<<INT2)
  254. #endif
  255. #endif
  256. /**********************************************************/
  257. /* 32 bit Teensy 3.0 and 3.1 */
  258. /**********************************************************/
  259. #elif defined(__arm__) && defined(TEENSYDUINO)
  260. class SPISettings {
  261. public:
  262. SPISettings(uint32_t clock, uint8_t bitOrder, uint8_t dataMode) {
  263. if (__builtin_constant_p(clock)) {
  264. init_AlwaysInline(clock, bitOrder, dataMode);
  265. } else {
  266. init_MightInline(clock, bitOrder, dataMode);
  267. }
  268. }
  269. SPISettings() {
  270. init_AlwaysInline(4000000, MSBFIRST, SPI_MODE0);
  271. }
  272. private:
  273. void init_MightInline(uint32_t clock, uint8_t bitOrder, uint8_t dataMode) {
  274. init_AlwaysInline(clock, bitOrder, dataMode);
  275. }
  276. void init_AlwaysInline(uint32_t clock, uint8_t bitOrder, uint8_t dataMode)
  277. __attribute__((__always_inline__)) {
  278. uint32_t t, c = SPI_CTAR_FMSZ(7);
  279. if (bitOrder == LSBFIRST) c |= SPI_CTAR_LSBFE;
  280. if (__builtin_constant_p(clock)) {
  281. if (clock >= F_BUS / 2) {
  282. t = SPI_CTAR_PBR(0) | SPI_CTAR_BR(0) | SPI_CTAR_DBR
  283. | SPI_CTAR_CSSCK(0);
  284. } else if (clock >= F_BUS / 3) {
  285. t = SPI_CTAR_PBR(1) | SPI_CTAR_BR(0) | SPI_CTAR_DBR
  286. | SPI_CTAR_CSSCK(0);
  287. } else if (clock >= F_BUS / 4) {
  288. t = SPI_CTAR_PBR(0) | SPI_CTAR_BR(0) | SPI_CTAR_CSSCK(0);
  289. } else if (clock >= F_BUS / 5) {
  290. t = SPI_CTAR_PBR(2) | SPI_CTAR_BR(0) | SPI_CTAR_DBR
  291. | SPI_CTAR_CSSCK(0);
  292. } else if (clock >= F_BUS / 6) {
  293. t = SPI_CTAR_PBR(1) | SPI_CTAR_BR(0) | SPI_CTAR_CSSCK(0);
  294. } else if (clock >= F_BUS / 8) {
  295. t = SPI_CTAR_PBR(0) | SPI_CTAR_BR(1) | SPI_CTAR_CSSCK(1);
  296. } else if (clock >= F_BUS / 10) {
  297. t = SPI_CTAR_PBR(2) | SPI_CTAR_BR(0) | SPI_CTAR_CSSCK(0);
  298. } else if (clock >= F_BUS / 12) {
  299. t = SPI_CTAR_PBR(1) | SPI_CTAR_BR(1) | SPI_CTAR_CSSCK(1);
  300. } else if (clock >= F_BUS / 16) {
  301. t = SPI_CTAR_PBR(0) | SPI_CTAR_BR(3) | SPI_CTAR_CSSCK(2);
  302. } else if (clock >= F_BUS / 20) {
  303. t = SPI_CTAR_PBR(2) | SPI_CTAR_BR(1) | SPI_CTAR_CSSCK(0);
  304. } else if (clock >= F_BUS / 24) {
  305. t = SPI_CTAR_PBR(1) | SPI_CTAR_BR(3) | SPI_CTAR_CSSCK(2);
  306. } else if (clock >= F_BUS / 32) {
  307. t = SPI_CTAR_PBR(0) | SPI_CTAR_BR(4) | SPI_CTAR_CSSCK(3);
  308. } else if (clock >= F_BUS / 40) {
  309. t = SPI_CTAR_PBR(2) | SPI_CTAR_BR(3) | SPI_CTAR_CSSCK(2);
  310. } else if (clock >= F_BUS / 56) {
  311. t = SPI_CTAR_PBR(3) | SPI_CTAR_BR(3) | SPI_CTAR_CSSCK(2);
  312. } else if (clock >= F_BUS / 64) {
  313. t = SPI_CTAR_PBR(0) | SPI_CTAR_BR(5) | SPI_CTAR_CSSCK(4);
  314. } else if (clock >= F_BUS / 96) {
  315. t = SPI_CTAR_PBR(1) | SPI_CTAR_BR(5) | SPI_CTAR_CSSCK(4);
  316. } else if (clock >= F_BUS / 128) {
  317. t = SPI_CTAR_PBR(0) | SPI_CTAR_BR(6) | SPI_CTAR_CSSCK(5);
  318. } else if (clock >= F_BUS / 192) {
  319. t = SPI_CTAR_PBR(1) | SPI_CTAR_BR(6) | SPI_CTAR_CSSCK(5);
  320. } else if (clock >= F_BUS / 256) {
  321. t = SPI_CTAR_PBR(0) | SPI_CTAR_BR(7) | SPI_CTAR_CSSCK(6);
  322. } else if (clock >= F_BUS / 384) {
  323. t = SPI_CTAR_PBR(1) | SPI_CTAR_BR(7) | SPI_CTAR_CSSCK(6);
  324. } else if (clock >= F_BUS / 512) {
  325. t = SPI_CTAR_PBR(0) | SPI_CTAR_BR(8) | SPI_CTAR_CSSCK(7);
  326. } else if (clock >= F_BUS / 640) {
  327. t = SPI_CTAR_PBR(2) | SPI_CTAR_BR(7) | SPI_CTAR_CSSCK(6);
  328. } else { /* F_BUS / 768 */
  329. t = SPI_CTAR_PBR(1) | SPI_CTAR_BR(8) | SPI_CTAR_CSSCK(7);
  330. }
  331. } else {
  332. for (uint32_t i=0; i<23; i++) {
  333. t = ctar_clock_table[i];
  334. if (clock >= F_BUS / ctar_div_table[i]) break;
  335. }
  336. }
  337. if (dataMode & 0x08) {
  338. c |= SPI_CTAR_CPOL;
  339. }
  340. if (dataMode & 0x04) {
  341. c |= SPI_CTAR_CPHA;
  342. t = (t & 0xFFFF0FFF) | ((t & 0xF000) >> 4);
  343. }
  344. ctar = c | t;
  345. }
  346. static const uint16_t ctar_div_table[23];
  347. static const uint32_t ctar_clock_table[23];
  348. uint32_t ctar;
  349. friend class SPIClass;
  350. };
  351. class SPIClass {
  352. public:
  353. // Initialize the SPI library
  354. static void begin();
  355. // If SPI is to used from within an interrupt, this function registers
  356. // that interrupt with the SPI library, so beginTransaction() can
  357. // prevent conflicts. The input interruptNumber is the number used
  358. // with attachInterrupt. If SPI is used from a different interrupt
  359. // (eg, a timer), interruptNumber should be 255.
  360. static void usingInterrupt(uint8_t interruptNumber);
  361. static void usingInterrupt(IRQ_NUMBER_t interruptName);
  362. // Before using SPI.transfer() or asserting chip select pins,
  363. // this function is used to gain exclusive access to the SPI bus
  364. // and configure the correct settings.
  365. inline static void beginTransaction(SPISettings settings) {
  366. if (interruptMode > 0) {
  367. #ifdef SPI_AVR_EIMSK
  368. if (interruptMode == 1) {
  369. interruptSave = SPI_AVR_EIMSK;
  370. SPI_AVR_EIMSK &= ~interruptMask;
  371. } else
  372. #endif
  373. {
  374. interruptSave = SREG;
  375. cli();
  376. }
  377. }
  378. if (SPI0_CTAR0 != settings.ctar) {
  379. SPI0_MCR = SPI_MCR_MDIS | SPI_MCR_HALT | SPI_MCR_PCSIS(0x1F);
  380. SPI0_CTAR0 = settings.ctar;
  381. SPI0_CTAR1 = settings.ctar| SPI_CTAR_FMSZ(8);
  382. SPI0_MCR = SPI_MCR_MSTR | SPI_MCR_PCSIS(0x1F);
  383. }
  384. }
  385. // Write to the SPI bus (MOSI pin) and also receive (MISO pin)
  386. inline static uint8_t transfer(uint8_t data) {
  387. SPDR = data;
  388. asm volatile("nop");
  389. while (!(SPSR & _BV(SPIF))) ; // wait
  390. return SPDR;
  391. }
  392. inline static void transfer(void *buf, size_t count) {
  393. if (count == 0) return;
  394. uint8_t *p = (uint8_t *)buf;
  395. SPDR = *p;
  396. while (--count > 0) {
  397. uint8_t out = *(p + 1);
  398. while (!(SPSR & _BV(SPIF))) ;
  399. uint8_t in = SPDR;
  400. SPDR = out;
  401. *p++ = in;
  402. }
  403. while (!(SPSR & _BV(SPIF))) ;
  404. *p = SPDR;
  405. }
  406. // After performing a group of transfers and releasing the chip select
  407. // signal, this function allows others to access the SPI bus
  408. inline static void endTransaction(void) {
  409. if (interruptMode > 0) {
  410. #ifdef SPI_AVR_EIMSK
  411. if (interruptMode == 1) {
  412. SPI_AVR_EIMSK = interruptSave;
  413. } else
  414. #endif
  415. {
  416. SREG = interruptSave;
  417. }
  418. }
  419. }
  420. // Disable the SPI bus
  421. static void end();
  422. // This function is deprecated. New applications should use
  423. // beginTransaction() to configure SPI settings.
  424. static void setBitOrder(uint8_t bitOrder);
  425. // This function is deprecated. New applications should use
  426. // beginTransaction() to configure SPI settings.
  427. static void setDataMode(uint8_t dataMode);
  428. // This function is deprecated. New applications should use
  429. // beginTransaction() to configure SPI settings.
  430. inline static void setClockDivider(uint8_t clockDiv) {
  431. if (clockDiv == SPI_CLOCK_DIV2) {
  432. setClockDivider_noInline(SPISettings(8000000, MSBFIRST, SPI_MODE0).ctar);
  433. } else if (clockDiv == SPI_CLOCK_DIV4) {
  434. setClockDivider_noInline(SPISettings(4000000, MSBFIRST, SPI_MODE0).ctar);
  435. } else if (clockDiv == SPI_CLOCK_DIV8) {
  436. setClockDivider_noInline(SPISettings(2000000, MSBFIRST, SPI_MODE0).ctar);
  437. } else if (clockDiv == SPI_CLOCK_DIV16) {
  438. setClockDivider_noInline(SPISettings(1000000, MSBFIRST, SPI_MODE0).ctar);
  439. } else if (clockDiv == SPI_CLOCK_DIV32) {
  440. setClockDivider_noInline(SPISettings(500000, MSBFIRST, SPI_MODE0).ctar);
  441. } else if (clockDiv == SPI_CLOCK_DIV64) {
  442. setClockDivider_noInline(SPISettings(250000, MSBFIRST, SPI_MODE0).ctar);
  443. } else { /* clockDiv == SPI_CLOCK_DIV128 */
  444. setClockDivider_noInline(SPISettings(125000, MSBFIRST, SPI_MODE0).ctar);
  445. }
  446. }
  447. static void setClockDivider_noInline(uint32_t clk);
  448. // These undocumented functions should not be used. SPI.transfer()
  449. // polls the hardware flag which is automatically cleared as the
  450. // AVR responds to SPI's interrupt
  451. inline static void attachInterrupt() { }
  452. inline static void detachInterrupt() { }
  453. // Teensy 3.x can use alternate pins for these 3 SPI signals.
  454. inline static void setMOSI(uint8_t pin) __attribute__((always_inline)) {
  455. SPCR.setMOSI(pin);
  456. }
  457. inline static void setMISO(uint8_t pin) __attribute__((always_inline)) {
  458. SPCR.setMISO(pin);
  459. }
  460. inline static void setSCK(uint8_t pin) __attribute__((always_inline)) {
  461. SPCR.setSCK(pin);
  462. }
  463. private:
  464. static uint8_t interruptMode; // 0=none, 1=mask, 2=global
  465. static uint8_t interruptMask; // which interrupts to mask
  466. static uint8_t interruptSave; // temp storage, to restore state
  467. };
  468. #endif
  469. extern SPIClass SPI;
  470. #endif