Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.

163 lines
5.2KB

  1. /* Arduino DigitalIO Library
  2. * Copyright (C) 2013 by William Greiman
  3. *
  4. * This file is part of the Arduino DigitalIO 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 DigitalIO Library. If not, see
  18. * <http://www.gnu.org/licenses/>.
  19. */
  20. /**
  21. * @file
  22. * @brief Software SPI.
  23. *
  24. * @defgroup softSPI Software SPI
  25. * @details Software SPI Template Class.
  26. * @{
  27. */
  28. #ifndef SoftSPI_h
  29. #define SoftSPI_h
  30. #include <DigitalPin.h>
  31. //------------------------------------------------------------------------------
  32. /** Nop for timing. */
  33. #define nop asm volatile ("nop\n\t")
  34. //------------------------------------------------------------------------------
  35. /** Pin Mode for MISO is input.*/
  36. const bool MISO_MODE = false;
  37. /** Pullups disabled for MISO are disabled. */
  38. const bool MISO_LEVEL = false;
  39. /** Pin Mode for MOSI is output.*/
  40. const bool MOSI_MODE = true;
  41. /** Pin Mode for SCK is output. */
  42. const bool SCK_MODE = true;
  43. //------------------------------------------------------------------------------
  44. /**
  45. * @class SoftSPI
  46. * @brief Fast software SPI.
  47. */
  48. template<uint8_t MisoPin, uint8_t MosiPin, uint8_t SckPin, uint8_t Mode = 0>
  49. class SoftSPI {
  50. public:
  51. //----------------------------------------------------------------------------
  52. /** Initialize SoftSPI pins. */
  53. void begin() {
  54. fastPinConfig(MisoPin, MISO_MODE, MISO_LEVEL);
  55. fastPinConfig(MosiPin, MOSI_MODE, !MODE_CPHA(Mode));
  56. fastPinConfig(SckPin, SCK_MODE, MODE_CPOL(Mode));
  57. }
  58. //----------------------------------------------------------------------------
  59. /** Soft SPI receive byte.
  60. * @return Data byte received.
  61. */
  62. inline __attribute__((always_inline))
  63. uint8_t receive() {
  64. uint8_t data = 0;
  65. receiveBit(7, &data);
  66. receiveBit(6, &data);
  67. receiveBit(5, &data);
  68. receiveBit(4, &data);
  69. receiveBit(3, &data);
  70. receiveBit(2, &data);
  71. receiveBit(1, &data);
  72. receiveBit(0, &data);
  73. return data;
  74. }
  75. //----------------------------------------------------------------------------
  76. /** Soft SPI send byte.
  77. * @param[in] data Data byte to send.
  78. */
  79. inline __attribute__((always_inline))
  80. void send(uint8_t data) {
  81. sendBit(7, data);
  82. sendBit(6, data);
  83. sendBit(5, data);
  84. sendBit(4, data);
  85. sendBit(3, data);
  86. sendBit(2, data);
  87. sendBit(1, data);
  88. sendBit(0, data);
  89. }
  90. //----------------------------------------------------------------------------
  91. /** Soft SPI transfer byte.
  92. * @param[in] txData Data byte to send.
  93. * @return Data byte received.
  94. */
  95. inline __attribute__((always_inline))
  96. uint8_t transfer(uint8_t txData) {
  97. uint8_t rxData = 0;
  98. transferBit(7, &rxData, txData);
  99. transferBit(6, &rxData, txData);
  100. transferBit(5, &rxData, txData);
  101. transferBit(4, &rxData, txData);
  102. transferBit(3, &rxData, txData);
  103. transferBit(2, &rxData, txData);
  104. transferBit(1, &rxData, txData);
  105. transferBit(0, &rxData, txData);
  106. return rxData;
  107. }
  108. private:
  109. //----------------------------------------------------------------------------
  110. inline __attribute__((always_inline))
  111. bool MODE_CPHA(uint8_t mode) {return (mode & 1) != 0;}
  112. inline __attribute__((always_inline))
  113. bool MODE_CPOL(uint8_t mode) {return (mode & 2) != 0;}
  114. inline __attribute__((always_inline))
  115. void receiveBit(uint8_t bit, uint8_t* data) {
  116. if (MODE_CPHA(Mode)) {
  117. fastDigitalWrite(SckPin, !MODE_CPOL(Mode));
  118. }
  119. nop;
  120. nop;
  121. fastDigitalWrite(SckPin,
  122. MODE_CPHA(Mode) ? MODE_CPOL(Mode) : !MODE_CPOL(Mode));
  123. if (fastDigitalRead(MisoPin)) *data |= 1 << bit;
  124. if (!MODE_CPHA(Mode)) {
  125. fastDigitalWrite(SckPin, MODE_CPOL(Mode));
  126. }
  127. }
  128. //----------------------------------------------------------------------------
  129. inline __attribute__((always_inline))
  130. void sendBit(uint8_t bit, uint8_t data) {
  131. if (MODE_CPHA(Mode)) {
  132. fastDigitalWrite(SckPin, !MODE_CPOL(Mode));
  133. }
  134. fastDigitalWrite(MosiPin, data & (1 << bit));
  135. fastDigitalWrite(SckPin,
  136. MODE_CPHA(Mode) ? MODE_CPOL(Mode) : !MODE_CPOL(Mode));
  137. nop;
  138. nop;
  139. if (!MODE_CPHA(Mode)) {
  140. fastDigitalWrite(SckPin, MODE_CPOL(Mode));
  141. }
  142. }
  143. //----------------------------------------------------------------------------
  144. inline __attribute__((always_inline))
  145. void transferBit(uint8_t bit, uint8_t* rxData, uint8_t txData) {
  146. if (MODE_CPHA(Mode)) {
  147. fastDigitalWrite(SckPin, !MODE_CPOL(Mode));
  148. }
  149. fastDigitalWrite(MosiPin, txData & (1 << bit));
  150. fastDigitalWrite(SckPin,
  151. MODE_CPHA(Mode) ? MODE_CPOL(Mode) : !MODE_CPOL(Mode));
  152. if (fastDigitalRead(MisoPin)) *rxData |= 1 << bit;
  153. if (!MODE_CPHA(Mode)) {
  154. fastDigitalWrite(SckPin, MODE_CPOL(Mode));
  155. }
  156. }
  157. //----------------------------------------------------------------------------
  158. };
  159. #endif // SoftSPI_h
  160. /** @} */