PlatformIO package of the Teensy core framework compatible with GCC 10 & C++20
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.

413 line
10KB

  1. // RHHardwareSPI.h
  2. // Author: Mike McCauley (mikem@airspayce.com)
  3. // Copyright (C) 2011 Mike McCauley
  4. // Contributed by Joanna Rutkowska
  5. // $Id: RHHardwareSPI.cpp,v 1.16 2016/07/07 00:02:53 mikem Exp mikem $
  6. #include <RHHardwareSPI.h>
  7. // Declare a single default instance of the hardware SPI interface class
  8. RHHardwareSPI hardware_spi;
  9. #ifdef RH_HAVE_HARDWARE_SPI
  10. #if (RH_PLATFORM == RH_PLATFORM_STM32) // Maple etc
  11. // Declare an SPI interface to use
  12. HardwareSPI SPI(1);
  13. #elif (RH_PLATFORM == RH_PLATFORM_STM32STD) // STM32F4 Discovery
  14. // Declare an SPI interface to use
  15. HardwareSPI SPI(1);
  16. #endif
  17. // Arduino Due has default SPI pins on central SPI headers, and not on 10, 11, 12, 13
  18. // as per other Arduinos
  19. // http://21stdigitalhome.blogspot.com.au/2013/02/arduino-due-hardware-spi.html
  20. #if defined (__arm__) && !defined(CORE_TEENSY) && !defined(SPI_CLOCK_DIV16)
  21. // Arduino Due in 1.5.5 has no definitions for SPI dividers
  22. // SPI clock divider is based on MCK of 84MHz
  23. #define SPI_CLOCK_DIV16 (VARIANT_MCK/84000000) // 1MHz
  24. #define SPI_CLOCK_DIV8 (VARIANT_MCK/42000000) // 2MHz
  25. #define SPI_CLOCK_DIV4 (VARIANT_MCK/21000000) // 4MHz
  26. #define SPI_CLOCK_DIV2 (VARIANT_MCK/10500000) // 8MHz
  27. #define SPI_CLOCK_DIV1 (VARIANT_MCK/5250000) // 16MHz
  28. #endif
  29. RHHardwareSPI::RHHardwareSPI(Frequency frequency, BitOrder bitOrder, DataMode dataMode)
  30. :
  31. RHGenericSPI(frequency, bitOrder, dataMode)
  32. {
  33. }
  34. uint8_t RHHardwareSPI::transfer(uint8_t data)
  35. {
  36. return SPI.transfer(data);
  37. }
  38. void RHHardwareSPI::attachInterrupt()
  39. {
  40. #if (RH_PLATFORM == RH_PLATFORM_ARDUINO)
  41. SPI.attachInterrupt();
  42. #endif
  43. }
  44. void RHHardwareSPI::detachInterrupt()
  45. {
  46. #if (RH_PLATFORM == RH_PLATFORM_ARDUINO)
  47. SPI.detachInterrupt();
  48. #endif
  49. }
  50. void RHHardwareSPI::begin()
  51. {
  52. // Sigh: there are no common symbols for some of these SPI options across all platforms
  53. #if (RH_PLATFORM == RH_PLATFORM_ARDUINO) || (RH_PLATFORM == RH_PLATFORM_UNO32) || (RH_PLATFORM == RH_PLATFORM_CHIPKIT_CORE)
  54. uint8_t dataMode;
  55. if (_dataMode == DataMode0)
  56. dataMode = SPI_MODE0;
  57. else if (_dataMode == DataMode1)
  58. dataMode = SPI_MODE1;
  59. else if (_dataMode == DataMode2)
  60. dataMode = SPI_MODE2;
  61. else if (_dataMode == DataMode3)
  62. dataMode = SPI_MODE3;
  63. else
  64. dataMode = SPI_MODE0;
  65. #if (RH_PLATFORM == RH_PLATFORM_ARDUINO) && defined(__arm__) && defined(CORE_TEENSY)
  66. // Temporary work-around due to problem where avr_emulation.h does not work properly for the setDataMode() cal
  67. SPCR &= ~SPI_MODE_MASK;
  68. #else
  69. #if (RH_PLATFORM == RH_PLATFORM_ARDUINO) && defined (__arm__) && defined(ARDUINO_ARCH_SAMD)
  70. // Zero requires begin() before anything else :-)
  71. SPI.begin();
  72. #endif
  73. SPI.setDataMode(dataMode);
  74. #endif
  75. #if (RH_PLATFORM == RH_PLATFORM_ARDUINO) && defined(SPI_HAS_TRANSACTION)
  76. uint32_t frequency32;
  77. if (_frequency == Frequency16MHz) {
  78. frequency32 = 16000000;
  79. } else if (_frequency == Frequency8MHz) {
  80. frequency32 = 8000000;
  81. } else if (_frequency == Frequency4MHz) {
  82. frequency32 = 4000000;
  83. } else if (_frequency == Frequency2MHz) {
  84. frequency32 = 2000000;
  85. } else {
  86. frequency32 = 1000000;
  87. }
  88. _settings = SPISettings(frequency32,
  89. (_bitOrder == BitOrderLSBFirst) ? LSBFIRST : MSBFIRST,
  90. dataMode);
  91. //Serial.print("SPISettings: "); Serial.println(frequency32, DEC);
  92. #endif
  93. #if (RH_PLATFORM == RH_PLATFORM_ARDUINO) && defined (__arm__) && (defined(ARDUINO_SAM_DUE) || defined(ARDUINO_ARCH_SAMD))
  94. // Arduino Due in 1.5.5 has its own BitOrder :-(
  95. // So too does Arduino Zero
  96. ::BitOrder bitOrder;
  97. #else
  98. uint8_t bitOrder;
  99. #endif
  100. if (_bitOrder == BitOrderLSBFirst)
  101. bitOrder = LSBFIRST;
  102. else
  103. bitOrder = MSBFIRST;
  104. SPI.setBitOrder(bitOrder);
  105. uint8_t divider;
  106. switch (_frequency)
  107. {
  108. case Frequency1MHz:
  109. default:
  110. #if F_CPU == 8000000
  111. divider = SPI_CLOCK_DIV8;
  112. #else
  113. divider = SPI_CLOCK_DIV16;
  114. #endif
  115. break;
  116. case Frequency2MHz:
  117. #if F_CPU == 8000000
  118. divider = SPI_CLOCK_DIV4;
  119. #else
  120. divider = SPI_CLOCK_DIV8;
  121. #endif
  122. break;
  123. case Frequency4MHz:
  124. #if F_CPU == 8000000
  125. divider = SPI_CLOCK_DIV2;
  126. #else
  127. divider = SPI_CLOCK_DIV4;
  128. #endif
  129. break;
  130. case Frequency8MHz:
  131. divider = SPI_CLOCK_DIV2; // 4MHz on an 8MHz Arduino
  132. break;
  133. case Frequency16MHz:
  134. divider = SPI_CLOCK_DIV2; // Not really 16MHz, only 8MHz. 4MHz on an 8MHz Arduino
  135. break;
  136. }
  137. SPI.setClockDivider(divider);
  138. SPI.begin();
  139. // Teensy requires it to be set _after_ begin()
  140. SPI.setClockDivider(divider);
  141. #elif (RH_PLATFORM == RH_PLATFORM_STM32) // Maple etc
  142. spi_mode dataMode;
  143. // Hmmm, if we do this as a switch, GCC on maple gets v confused!
  144. if (_dataMode == DataMode0)
  145. dataMode = SPI_MODE_0;
  146. else if (_dataMode == DataMode1)
  147. dataMode = SPI_MODE_1;
  148. else if (_dataMode == DataMode2)
  149. dataMode = SPI_MODE_2;
  150. else if (_dataMode == DataMode3)
  151. dataMode = SPI_MODE_3;
  152. else
  153. dataMode = SPI_MODE_0;
  154. uint32 bitOrder;
  155. if (_bitOrder == BitOrderLSBFirst)
  156. bitOrder = LSBFIRST;
  157. else
  158. bitOrder = MSBFIRST;
  159. SPIFrequency frequency; // Yes, I know these are not exact equivalents.
  160. switch (_frequency)
  161. {
  162. case Frequency1MHz:
  163. default:
  164. frequency = SPI_1_125MHZ;
  165. break;
  166. case Frequency2MHz:
  167. frequency = SPI_2_25MHZ;
  168. break;
  169. case Frequency4MHz:
  170. frequency = SPI_4_5MHZ;
  171. break;
  172. case Frequency8MHz:
  173. frequency = SPI_9MHZ;
  174. break;
  175. case Frequency16MHz:
  176. frequency = SPI_18MHZ;
  177. break;
  178. }
  179. SPI.begin(frequency, bitOrder, dataMode);
  180. #elif (RH_PLATFORM == RH_PLATFORM_STM32STD) // STM32F4 discovery
  181. uint8_t dataMode;
  182. if (_dataMode == DataMode0)
  183. dataMode = SPI_MODE0;
  184. else if (_dataMode == DataMode1)
  185. dataMode = SPI_MODE1;
  186. else if (_dataMode == DataMode2)
  187. dataMode = SPI_MODE2;
  188. else if (_dataMode == DataMode3)
  189. dataMode = SPI_MODE3;
  190. else
  191. dataMode = SPI_MODE0;
  192. uint32_t bitOrder;
  193. if (_bitOrder == BitOrderLSBFirst)
  194. bitOrder = LSBFIRST;
  195. else
  196. bitOrder = MSBFIRST;
  197. SPIFrequency frequency; // Yes, I know these are not exact equivalents.
  198. switch (_frequency)
  199. {
  200. case Frequency1MHz:
  201. default:
  202. frequency = SPI_1_3125MHZ;
  203. break;
  204. case Frequency2MHz:
  205. frequency = SPI_2_625MHZ;
  206. break;
  207. case Frequency4MHz:
  208. frequency = SPI_5_25MHZ;
  209. break;
  210. case Frequency8MHz:
  211. frequency = SPI_10_5MHZ;
  212. break;
  213. case Frequency16MHz:
  214. frequency = SPI_21_0MHZ;
  215. break;
  216. }
  217. SPI.begin(frequency, bitOrder, dataMode);
  218. #elif (RH_PLATFORM == RH_PLATFORM_STM32F2) // Photon
  219. Serial.println("HERE");
  220. uint8_t dataMode;
  221. if (_dataMode == DataMode0)
  222. dataMode = SPI_MODE0;
  223. else if (_dataMode == DataMode1)
  224. dataMode = SPI_MODE1;
  225. else if (_dataMode == DataMode2)
  226. dataMode = SPI_MODE2;
  227. else if (_dataMode == DataMode3)
  228. dataMode = SPI_MODE3;
  229. else
  230. dataMode = SPI_MODE0;
  231. SPI.setDataMode(dataMode);
  232. if (_bitOrder == BitOrderLSBFirst)
  233. SPI.setBitOrder(LSBFIRST);
  234. else
  235. SPI.setBitOrder(MSBFIRST);
  236. switch (_frequency)
  237. {
  238. case Frequency1MHz:
  239. default:
  240. SPI.setClockSpeed(1, MHZ);
  241. break;
  242. case Frequency2MHz:
  243. SPI.setClockSpeed(2, MHZ);
  244. break;
  245. case Frequency4MHz:
  246. SPI.setClockSpeed(4, MHZ);
  247. break;
  248. case Frequency8MHz:
  249. SPI.setClockSpeed(8, MHZ);
  250. break;
  251. case Frequency16MHz:
  252. SPI.setClockSpeed(16, MHZ);
  253. break;
  254. }
  255. // SPI.setClockDivider(SPI_CLOCK_DIV4); // 72MHz / 4MHz = 18MHz
  256. // SPI.setClockSpeed(1, MHZ);
  257. SPI.begin();
  258. #elif (RH_PLATFORM == RH_PLATFORM_ESP8266)
  259. // Requires SPI driver for ESP8266 from https://github.com/esp8266/Arduino/tree/master/libraries/SPI
  260. // Which ppears to be in Arduino Board Manager ESP8266 Community version 2.1.0
  261. // Contributed by David Skinner
  262. // begin comes first
  263. SPI.begin();
  264. // datamode
  265. switch ( _dataMode )
  266. {
  267. case DataMode1:
  268. SPI.setDataMode ( SPI_MODE1 );
  269. break;
  270. case DataMode2:
  271. SPI.setDataMode ( SPI_MODE2 );
  272. break;
  273. case DataMode3:
  274. SPI.setDataMode ( SPI_MODE3 );
  275. break;
  276. case DataMode0:
  277. default:
  278. SPI.setDataMode ( SPI_MODE0 );
  279. break;
  280. }
  281. // bitorder
  282. SPI.setBitOrder(_bitOrder == BitOrderLSBFirst ? LSBFIRST : MSBFIRST);
  283. // frequency (this sets the divider)
  284. switch (_frequency)
  285. {
  286. case Frequency1MHz:
  287. default:
  288. SPI.setFrequency(1000000);
  289. break;
  290. case Frequency2MHz:
  291. SPI.setFrequency(2000000);
  292. break;
  293. case Frequency4MHz:
  294. SPI.setFrequency(4000000);
  295. break;
  296. case Frequency8MHz:
  297. SPI.setFrequency(8000000);
  298. break;
  299. case Frequency16MHz:
  300. SPI.setFrequency(16000000);
  301. break;
  302. }
  303. #elif (RH_PLATFORM == RH_PLATFORM_RASPI) // Raspberry PI
  304. uint8_t dataMode;
  305. if (_dataMode == DataMode0)
  306. dataMode = BCM2835_SPI_MODE0;
  307. else if (_dataMode == DataMode1)
  308. dataMode = BCM2835_SPI_MODE1;
  309. else if (_dataMode == DataMode2)
  310. dataMode = BCM2835_SPI_MODE2;
  311. else if (_dataMode == DataMode3)
  312. dataMode = BCM2835_SPI_MODE3;
  313. uint8_t bitOrder;
  314. if (_bitOrder == BitOrderLSBFirst)
  315. bitOrder = BCM2835_SPI_BIT_ORDER_LSBFIRST;
  316. else
  317. bitOrder = BCM2835_SPI_BIT_ORDER_MSBFIRST;
  318. uint32_t divider;
  319. switch (_frequency)
  320. {
  321. case Frequency1MHz:
  322. default:
  323. divider = BCM2835_SPI_CLOCK_DIVIDER_256;
  324. break;
  325. case Frequency2MHz:
  326. divider = BCM2835_SPI_CLOCK_DIVIDER_128;
  327. break;
  328. case Frequency4MHz:
  329. divider = BCM2835_SPI_CLOCK_DIVIDER_64;
  330. break;
  331. case Frequency8MHz:
  332. divider = BCM2835_SPI_CLOCK_DIVIDER_32;
  333. break;
  334. case Frequency16MHz:
  335. divider = BCM2835_SPI_CLOCK_DIVIDER_16;
  336. break;
  337. }
  338. SPI.begin(divider, bitOrder, dataMode);
  339. #else
  340. #warning RHHardwareSPI does not support this platform yet. Consider adding it and contributing a patch.
  341. #endif
  342. }
  343. void RHHardwareSPI::end()
  344. {
  345. return SPI.end();
  346. }
  347. // If our platform is arduino and we support transactions then lets use the begin/end transaction
  348. #if (RH_PLATFORM == RH_PLATFORM_ARDUINO) && defined(SPI_HAS_TRANSACTION)
  349. void RHHardwareSPI::beginTransaction()
  350. {
  351. SPI.beginTransaction(_settings);
  352. }
  353. void RHHardwareSPI::endTransaction()
  354. {
  355. SPI.endTransaction();
  356. }
  357. #endif
  358. #endif