No puede seleccionar más de 25 temas Los temas deben comenzar con una letra o número, pueden incluir guiones ('-') y pueden tener hasta 35 caracteres de largo.

368 líneas
9.8KB

  1. /* Arduino SdSpi Library
  2. * Copyright (C) 2013 by William Greiman
  3. *
  4. * This file is part of the Arduino SdSpi Library
  5. *
  6. * This Library is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation, either version 3 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * This Library is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with the Arduino SdSpi Library. If not, see
  18. * <http://www.gnu.org/licenses/>.
  19. */
  20. /**
  21. * \file
  22. * \brief SdSpi class for V2 SD/SDHC cards
  23. */
  24. #ifndef SdSpi_h
  25. #define SdSpi_h
  26. #include <Arduino.h>
  27. #include "SdFatConfig.h"
  28. #include "utility/SoftSPI.h"
  29. //------------------------------------------------------------------------------
  30. /**
  31. * \class SdSpiBase
  32. * \brief Virtual SPI class for access to SD and SDHC flash memory cards.
  33. */
  34. class SdSpiBase {
  35. public:
  36. /** Initialize the SPI bus */
  37. virtual void begin() = 0;
  38. /** Set SPI options for access to SD/SDHC cards.
  39. *
  40. * \param[in] divisor SCK clock divider relative to the system clock.
  41. */
  42. virtual void init(uint8_t divisor);
  43. /** Receive a byte.
  44. *
  45. * \return The byte.
  46. */
  47. virtual uint8_t receive() = 0;
  48. /** Receive multiple bytes.
  49. *
  50. * \param[out] buf Buffer to receive the data.
  51. * \param[in] n Number of bytes to receive.
  52. *
  53. * \return Zero for no error or nonzero error code.
  54. */
  55. virtual uint8_t receive(uint8_t* buf, size_t n) = 0;
  56. /** Send a byte.
  57. *
  58. * \param[in] data Byte to send
  59. */
  60. virtual void send(uint8_t data) = 0;
  61. /** Send multiple bytes.
  62. *
  63. * \param[in] buf Buffer for data to be sent.
  64. * \param[in] n Number of bytes to send.
  65. */
  66. virtual void send(const uint8_t* buf, size_t n) = 0;
  67. /** \return true if hardware SPI else false */
  68. virtual bool useSpiTransactions() = 0;
  69. };
  70. //------------------------------------------------------------------------------
  71. /**
  72. * \class SdSpi
  73. * \brief SPI class for access to SD and SDHC flash memory cards.
  74. */
  75. #if SD_SPI_CONFIGURATION >= 3
  76. class SdSpi : public SdSpiBase {
  77. #else // SD_SPI_CONFIGURATION >= 3
  78. class SdSpi {
  79. #endif // SD_SPI_CONFIGURATION >= 3
  80. public:
  81. /** Initialize the SPI bus */
  82. void begin();
  83. /** Set SPI options for access to SD/SDHC cards.
  84. *
  85. * \param[in] divisor SCK clock divider relative to the system clock.
  86. */
  87. void init(uint8_t divisor);
  88. /** Receive a byte.
  89. *
  90. * \return The byte.
  91. */
  92. uint8_t receive();
  93. /** Receive multiple bytes.
  94. *
  95. * \param[out] buf Buffer to receive the data.
  96. * \param[in] n Number of bytes to receive.
  97. *
  98. * \return Zero for no error or nonzero error code.
  99. */
  100. uint8_t receive(uint8_t* buf, size_t n);
  101. /** Send a byte.
  102. *
  103. * \param[in] data Byte to send
  104. */
  105. void send(uint8_t data);
  106. /** Send multiple bytes.
  107. *
  108. * \param[in] buf Buffer for data to be sent.
  109. * \param[in] n Number of bytes to send.
  110. */
  111. void send(const uint8_t* buf, size_t n);
  112. /** \return true - uses SPI transactions */
  113. bool useSpiTransactions() {
  114. return true;
  115. }
  116. };
  117. //------------------------------------------------------------------------------
  118. /**
  119. * \class SdSpiLib
  120. * \brief Arduino SPI library class for access to SD and SDHC flash
  121. * memory cards.
  122. */
  123. #if SD_SPI_CONFIGURATION >= 3 || SD_SPI_CONFIGURATION == 1 || defined(DOXYGEN)
  124. #include <SPI.h>
  125. #if SD_SPI_CONFIGURATION >= 3
  126. class SdSpiLib : public SdSpiBase {
  127. #else // SD_SPI_CONFIGURATION >= 3
  128. class SdSpiLib {
  129. #endif // SD_SPI_CONFIGURATION >= 3
  130. public:
  131. /**
  132. * Initialize SPI pins.
  133. */
  134. void begin() {
  135. SPI.begin();
  136. }
  137. /** Set SPI options for access to SD/SDHC cards.
  138. *
  139. * \param[in] divisor SCK clock divider relative to the system clock.
  140. */
  141. void init(uint8_t divisor) {
  142. SPI.setBitOrder(MSBFIRST);
  143. SPI.setDataMode(SPI_MODE0);
  144. #ifndef SPI_CLOCK_DIV128
  145. SPI.setClockDivider(divisor);
  146. #else // SPI_CLOCK_DIV128
  147. int v;
  148. if (divisor <= 2) {
  149. v = SPI_CLOCK_DIV2;
  150. } else if (divisor <= 4) {
  151. v = SPI_CLOCK_DIV4;
  152. } else if (divisor <= 8) {
  153. v = SPI_CLOCK_DIV8;
  154. } else if (divisor <= 16) {
  155. v = SPI_CLOCK_DIV16;
  156. } else if (divisor <= 32) {
  157. v = SPI_CLOCK_DIV32;
  158. } else if (divisor <= 64) {
  159. v = SPI_CLOCK_DIV64;
  160. } else {
  161. v = SPI_CLOCK_DIV128;
  162. }
  163. SPI.setClockDivider(v);
  164. #endif // SPI_CLOCK_DIV128
  165. }
  166. /** Receive a byte.
  167. *
  168. * \return The byte.
  169. */
  170. uint8_t receive() {
  171. return SPI.transfer(0XFF);
  172. }
  173. /** Receive multiple bytes.
  174. *
  175. * \param[out] buf Buffer to receive the data.
  176. * \param[in] n Number of bytes to receive.
  177. *
  178. * \return Zero for no error or nonzero error code.
  179. */
  180. uint8_t receive(uint8_t* buf, size_t n) {
  181. for (size_t i = 0; i < n; i++) {
  182. buf[i] = SPI.transfer(0XFF);
  183. }
  184. return 0;
  185. }
  186. /** Send a byte.
  187. *
  188. * \param[in] b Byte to send
  189. */
  190. void send(uint8_t b) {
  191. SPI.transfer(b);
  192. }
  193. /** Send multiple bytes.
  194. *
  195. * \param[in] buf Buffer for data to be sent.
  196. * \param[in] n Number of bytes to send.
  197. */
  198. void send(const uint8_t* buf , size_t n) {
  199. for (size_t i = 0; i < n; i++) {
  200. SPI.transfer(buf[i]);
  201. }
  202. }
  203. /** \return true - uses SPI transactions */
  204. bool useSpiTransactions() {
  205. return true;
  206. }
  207. };
  208. #endif // SD_SPI_CONFIGURATION >= 3 || SD_SPI_CONFIGURATION == 1
  209. //------------------------------------------------------------------------------
  210. /**
  211. * \class SdSpiSoft
  212. * \brief Software SPI class for access to SD and SDHC flash memory cards.
  213. */
  214. template<uint8_t MisoPin, uint8_t MosiPin, uint8_t SckPin>
  215. class SdSpiSoft : public SdSpiBase {
  216. public:
  217. /**
  218. * initialize SPI pins
  219. */
  220. void begin() {
  221. m_spi.begin();
  222. }
  223. /**
  224. * Initialize hardware SPI - dummy for soft SPI
  225. * \param[in] divisor SCK divisor - ignored.
  226. */
  227. void init(uint8_t divisor) {}
  228. /** Receive a byte.
  229. *
  230. * \return The byte.
  231. */
  232. uint8_t receive() {
  233. return m_spi.receive();
  234. }
  235. /** Receive multiple bytes.
  236. *
  237. * \param[out] buf Buffer to receive the data.
  238. * \param[in] n Number of bytes to receive.
  239. *
  240. * \return Zero for no error or nonzero error code.
  241. */
  242. uint8_t receive(uint8_t* buf, size_t n) {
  243. for (size_t i = 0; i < n; i++) {
  244. buf[i] = receive();
  245. }
  246. return 0;
  247. }
  248. /** Send a byte.
  249. *
  250. * \param[in] data Byte to send
  251. */
  252. void send(uint8_t data) {
  253. m_spi.send(data);
  254. }
  255. /** Send multiple bytes.
  256. *
  257. * \param[in] buf Buffer for data to be sent.
  258. * \param[in] n Number of bytes to send.
  259. */
  260. void send(const uint8_t* buf , size_t n) {
  261. for (size_t i = 0; i < n; i++) {
  262. send(buf[i]);
  263. }
  264. }
  265. /** \return false - no SPI transactions */
  266. bool useSpiTransactions() {
  267. return false;
  268. }
  269. private:
  270. SoftSPI<MisoPin, MosiPin, SckPin, 0> m_spi;
  271. };
  272. //------------------------------------------------------------------------------
  273. #if SD_SPI_CONFIGURATION == 0 || SD_SPI_CONFIGURATION >= 3
  274. /** Default is custom fast SPI. */
  275. typedef SdSpi SpiDefault_t;
  276. #elif SD_SPI_CONFIGURATION == 1
  277. /** Default is Arduino library SPI. */
  278. typedef SdSpiLib SpiDefault_t;
  279. #elif SD_SPI_CONFIGURATION == 2
  280. /** Default is software SPI. */
  281. typedef SdSpiSoft<SOFT_SPI_MISO_PIN, SOFT_SPI_MOSI_PIN, SOFT_SPI_SCK_PIN>
  282. SpiDefault_t;
  283. #else // SD_SPI_CONFIGURATION == 0 || SD_SPI_CONFIGURATION >= 3
  284. #error bad SD_SPI_CONFIGURATION
  285. #endif // SD_SPI_CONFIGURATION == 0 || SD_SPI_CONFIGURATION >= 3
  286. //------------------------------------------------------------------------------
  287. // Use of in-line for AVR to save flash.
  288. #ifdef __AVR__
  289. //------------------------------------------------------------------------------
  290. inline void SdSpi::begin() {
  291. #ifdef __AVR_ATmega328P__
  292. // Save a few bytes for 328 CPU - gcc optimizes single bit '|' to sbi.
  293. PORTB |= 1 << 2; // SS high
  294. DDRB |= 1 << 2; // SS output mode
  295. DDRB |= 1 << 3; // MOSI output mode
  296. DDRB |= 1 << 5; // SCK output mode
  297. #else // __AVR_ATmega328P__
  298. // set SS high - may be chip select for another SPI device
  299. digitalWrite(SS, HIGH);
  300. // SS must be in output mode even it is not chip select
  301. pinMode(SS, OUTPUT);
  302. pinMode(MOSI, OUTPUT);
  303. pinMode(SCK, OUTPUT);
  304. #endif // __AVR_ATmega328P__
  305. }
  306. //------------------------------------------------------------------------------
  307. inline void SdSpi::init(uint8_t divisor) {
  308. uint8_t b = 2;
  309. uint8_t r = 0;
  310. // See AVR processor documentation.
  311. for (; divisor > b && r < 7; b <<= 1, r += r < 5 ? 1 : 2) {}
  312. SPCR = (1 << SPE) | (1 << MSTR) | (r >> 1);
  313. SPSR = r & 1 ? 0 : 1 << SPI2X;
  314. }
  315. //------------------------------------------------------------------------------
  316. inline uint8_t SdSpi::receive() {
  317. SPDR = 0XFF;
  318. while (!(SPSR & (1 << SPIF))) {}
  319. return SPDR;
  320. }
  321. //------------------------------------------------------------------------------
  322. inline uint8_t SdSpi::receive(uint8_t* buf, size_t n) {
  323. if (n-- == 0) {
  324. return 0;
  325. }
  326. SPDR = 0XFF;
  327. for (size_t i = 0; i < n; i++) {
  328. while (!(SPSR & (1 << SPIF))) {}
  329. uint8_t b = SPDR;
  330. SPDR = 0XFF;
  331. buf[i] = b;
  332. }
  333. while (!(SPSR & (1 << SPIF))) {}
  334. buf[n] = SPDR;
  335. return 0;
  336. }
  337. //------------------------------------------------------------------------------
  338. inline void SdSpi::send(uint8_t data) {
  339. SPDR = data;
  340. while (!(SPSR & (1 << SPIF))) {}
  341. }
  342. //------------------------------------------------------------------------------
  343. inline void SdSpi::send(const uint8_t* buf , size_t n) {
  344. if (n == 0) {
  345. return;
  346. }
  347. SPDR = buf[0];
  348. if (n > 1) {
  349. uint8_t b = buf[1];
  350. size_t i = 2;
  351. while (1) {
  352. while (!(SPSR & (1 << SPIF))) {}
  353. SPDR = b;
  354. if (i == n) {
  355. break;
  356. }
  357. b = buf[i++];
  358. }
  359. }
  360. while (!(SPSR & (1 << SPIF))) {}
  361. }
  362. #endif // __AVR__
  363. #endif // SdSpi_h