My Marlin configs for Fabrikator Mini and CTC i3 Pro B
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.

softspi.h 25KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742
  1. /**
  2. * Marlin 3D Printer Firmware
  3. * Copyright (c) 2020 MarlinFirmware [https://github.com/MarlinFirmware/Marlin]
  4. *
  5. * Based on Sprinter and grbl.
  6. * Copyright (c) 2011 Camiel Gubbels / Erik van der Zalm
  7. *
  8. * This program is free software: you can redistribute it and/or modify
  9. * it under the terms of the GNU General Public License as published by
  10. * the Free Software Foundation, either version 3 of the License, or
  11. * (at your option) any later version.
  12. *
  13. * This program is distributed in the hope that it will be useful,
  14. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  16. * GNU General Public License for more details.
  17. *
  18. * You should have received a copy of the GNU General Public License
  19. * along with this program. If not, see <https://www.gnu.org/licenses/>.
  20. *
  21. */
  22. #pragma once
  23. //
  24. // Based on https://github.com/niteris/ArduinoSoftSpi
  25. //
  26. #include "../HAL/shared/Marduino.h" // CORE_TEENSY
  27. #define nop __asm__ volatile ("nop") // NOP for timing
  28. #ifdef __arm__
  29. #ifdef CORE_TEENSY
  30. /**
  31. * Read pin value
  32. * @param[in] pin Arduino pin number
  33. * @return value read
  34. */
  35. FORCE_INLINE static bool fastDigitalRead(uint8_t pin) {
  36. return *portInputRegister(pin);
  37. }
  38. /**
  39. * Set pin value
  40. * @param[in] pin Arduino pin number
  41. * @param[in] level value to write
  42. */
  43. FORCE_INLINE static void fastDigitalWrite(uint8_t pin, bool value) {
  44. if (value)
  45. *portSetRegister(pin) = 1;
  46. else
  47. *portClearRegister(pin) = 1;
  48. }
  49. #else // !CORE_TEENSY
  50. /**
  51. * Read pin value
  52. * @param[in] pin Arduino pin number
  53. * @return value read
  54. */
  55. FORCE_INLINE static bool fastDigitalRead(uint8_t pin) {
  56. return digitalRead(pin);
  57. }
  58. /**
  59. * Set pin value
  60. * @param[in] pin Arduino pin number
  61. * @param[in] level value to write
  62. */
  63. FORCE_INLINE static void fastDigitalWrite(uint8_t pin, bool value) {
  64. digitalWrite(pin, value);
  65. }
  66. #endif // !CORE_TEENSY
  67. inline void fastDigitalToggle(uint8_t pin) { fastDigitalWrite(pin, !fastDigitalRead(pin)); }
  68. inline void fastPinMode(uint8_t pin, bool mode) { pinMode(pin, mode); }
  69. #else // !__arm__
  70. #include <avr/io.h>
  71. #include <util/atomic.h>
  72. /**
  73. * @class pin_map_t
  74. * @brief struct for mapping digital pins
  75. */
  76. struct pin_map_t {
  77. volatile uint8_t* ddr; /**< address of DDR for this pin */
  78. volatile uint8_t* pin; /**< address of PIN for this pin */
  79. volatile uint8_t* port; /**< address of PORT for this pin */
  80. uint8_t bit; /**< bit number for this pin */
  81. };
  82. #if defined(__AVR_ATmega168__) || defined(__AVR_ATmega168P__) || defined(__AVR_ATmega328P__)
  83. // 168 and 328 Arduinos
  84. const static pin_map_t pinMap[] = {
  85. {&DDRD, &PIND, &PORTD, 0}, // D0 0
  86. {&DDRD, &PIND, &PORTD, 1}, // D1 1
  87. {&DDRD, &PIND, &PORTD, 2}, // D2 2
  88. {&DDRD, &PIND, &PORTD, 3}, // D3 3
  89. {&DDRD, &PIND, &PORTD, 4}, // D4 4
  90. {&DDRD, &PIND, &PORTD, 5}, // D5 5
  91. {&DDRD, &PIND, &PORTD, 6}, // D6 6
  92. {&DDRD, &PIND, &PORTD, 7}, // D7 7
  93. {&DDRB, &PINB, &PORTB, 0}, // B0 8
  94. {&DDRB, &PINB, &PORTB, 1}, // B1 9
  95. {&DDRB, &PINB, &PORTB, 2}, // B2 10
  96. {&DDRB, &PINB, &PORTB, 3}, // B3 11
  97. {&DDRB, &PINB, &PORTB, 4}, // B4 12
  98. {&DDRB, &PINB, &PORTB, 5}, // B5 13
  99. {&DDRC, &PINC, &PORTC, 0}, // C0 14
  100. {&DDRC, &PINC, &PORTC, 1}, // C1 15
  101. {&DDRC, &PINC, &PORTC, 2}, // C2 16
  102. {&DDRC, &PINC, &PORTC, 3}, // C3 17
  103. {&DDRC, &PINC, &PORTC, 4}, // C4 18
  104. {&DDRC, &PINC, &PORTC, 5} // C5 19
  105. };
  106. #elif defined(__AVR_ATmega1280__) || defined(__AVR_ATmega2560__)
  107. // Mega
  108. static const pin_map_t pinMap[] = {
  109. {&DDRE, &PINE, &PORTE, 0}, // E0 0
  110. {&DDRE, &PINE, &PORTE, 1}, // E1 1
  111. {&DDRE, &PINE, &PORTE, 4}, // E4 2
  112. {&DDRE, &PINE, &PORTE, 5}, // E5 3
  113. {&DDRG, &PING, &PORTG, 5}, // G5 4
  114. {&DDRE, &PINE, &PORTE, 3}, // E3 5
  115. {&DDRH, &PINH, &PORTH, 3}, // H3 6
  116. {&DDRH, &PINH, &PORTH, 4}, // H4 7
  117. {&DDRH, &PINH, &PORTH, 5}, // H5 8
  118. {&DDRH, &PINH, &PORTH, 6}, // H6 9
  119. {&DDRB, &PINB, &PORTB, 4}, // B4 10
  120. {&DDRB, &PINB, &PORTB, 5}, // B5 11
  121. {&DDRB, &PINB, &PORTB, 6}, // B6 12
  122. {&DDRB, &PINB, &PORTB, 7}, // B7 13
  123. {&DDRJ, &PINJ, &PORTJ, 1}, // J1 14
  124. {&DDRJ, &PINJ, &PORTJ, 0}, // J0 15
  125. {&DDRH, &PINH, &PORTH, 1}, // H1 16
  126. {&DDRH, &PINH, &PORTH, 0}, // H0 17
  127. {&DDRD, &PIND, &PORTD, 3}, // D3 18
  128. {&DDRD, &PIND, &PORTD, 2}, // D2 19
  129. {&DDRD, &PIND, &PORTD, 1}, // D1 20
  130. {&DDRD, &PIND, &PORTD, 0}, // D0 21
  131. {&DDRA, &PINA, &PORTA, 0}, // A0 22
  132. {&DDRA, &PINA, &PORTA, 1}, // A1 23
  133. {&DDRA, &PINA, &PORTA, 2}, // A2 24
  134. {&DDRA, &PINA, &PORTA, 3}, // A3 25
  135. {&DDRA, &PINA, &PORTA, 4}, // A4 26
  136. {&DDRA, &PINA, &PORTA, 5}, // A5 27
  137. {&DDRA, &PINA, &PORTA, 6}, // A6 28
  138. {&DDRA, &PINA, &PORTA, 7}, // A7 29
  139. {&DDRC, &PINC, &PORTC, 7}, // C7 30
  140. {&DDRC, &PINC, &PORTC, 6}, // C6 31
  141. {&DDRC, &PINC, &PORTC, 5}, // C5 32
  142. {&DDRC, &PINC, &PORTC, 4}, // C4 33
  143. {&DDRC, &PINC, &PORTC, 3}, // C3 34
  144. {&DDRC, &PINC, &PORTC, 2}, // C2 35
  145. {&DDRC, &PINC, &PORTC, 1}, // C1 36
  146. {&DDRC, &PINC, &PORTC, 0}, // C0 37
  147. {&DDRD, &PIND, &PORTD, 7}, // D7 38
  148. {&DDRG, &PING, &PORTG, 2}, // G2 39
  149. {&DDRG, &PING, &PORTG, 1}, // G1 40
  150. {&DDRG, &PING, &PORTG, 0}, // G0 41
  151. {&DDRL, &PINL, &PORTL, 7}, // L7 42
  152. {&DDRL, &PINL, &PORTL, 6}, // L6 43
  153. {&DDRL, &PINL, &PORTL, 5}, // L5 44
  154. {&DDRL, &PINL, &PORTL, 4}, // L4 45
  155. {&DDRL, &PINL, &PORTL, 3}, // L3 46
  156. {&DDRL, &PINL, &PORTL, 2}, // L2 47
  157. {&DDRL, &PINL, &PORTL, 1}, // L1 48
  158. {&DDRL, &PINL, &PORTL, 0}, // L0 49
  159. {&DDRB, &PINB, &PORTB, 3}, // B3 50
  160. {&DDRB, &PINB, &PORTB, 2}, // B2 51
  161. {&DDRB, &PINB, &PORTB, 1}, // B1 52
  162. {&DDRB, &PINB, &PORTB, 0}, // B0 53
  163. {&DDRF, &PINF, &PORTF, 0}, // F0 54
  164. {&DDRF, &PINF, &PORTF, 1}, // F1 55
  165. {&DDRF, &PINF, &PORTF, 2}, // F2 56
  166. {&DDRF, &PINF, &PORTF, 3}, // F3 57
  167. {&DDRF, &PINF, &PORTF, 4}, // F4 58
  168. {&DDRF, &PINF, &PORTF, 5}, // F5 59
  169. {&DDRF, &PINF, &PORTF, 6}, // F6 60
  170. {&DDRF, &PINF, &PORTF, 7}, // F7 61
  171. {&DDRK, &PINK, &PORTK, 0}, // K0 62
  172. {&DDRK, &PINK, &PORTK, 1}, // K1 63
  173. {&DDRK, &PINK, &PORTK, 2}, // K2 64
  174. {&DDRK, &PINK, &PORTK, 3}, // K3 65
  175. {&DDRK, &PINK, &PORTK, 4}, // K4 66
  176. {&DDRK, &PINK, &PORTK, 5}, // K5 67
  177. {&DDRK, &PINK, &PORTK, 6}, // K6 68
  178. {&DDRK, &PINK, &PORTK, 7}, // K7 69
  179. // pins_MIGHTYBOARD_REVE.h
  180. {&DDRG, &PING, &PORTG, 4}, // G4 70
  181. {&DDRG, &PING, &PORTG, 3}, // G3 71
  182. {&DDRJ, &PINJ, &PORTJ, 2}, // J2 72
  183. {&DDRJ, &PINJ, &PORTJ, 3}, // J3 73
  184. {&DDRJ, &PINJ, &PORTJ, 7}, // J7 74
  185. {&DDRJ, &PINJ, &PORTJ, 4}, // J4 75
  186. {&DDRJ, &PINJ, &PORTJ, 5}, // J5 76
  187. {&DDRJ, &PINJ, &PORTJ, 6}, // J6 77
  188. {&DDRE, &PINE, &PORTE, 2}, // E2 78
  189. {&DDRE, &PINE, &PORTE, 6} // E6 79
  190. };
  191. #elif defined(__AVR_ATmega1284P__) || defined(__AVR_ATmega1284__) \
  192. || defined(__AVR_ATmega644P__) || defined(__AVR_ATmega644__) \
  193. || defined(__AVR_ATmega64__) || defined(__AVR_ATmega32__) \
  194. || defined(__AVR_ATmega324__) || defined(__AVR_ATmega16__)
  195. #ifdef VARIANT_MIGHTY
  196. // Mighty Layout
  197. static const pin_map_t pinMap[] = {
  198. {&DDRB, &PINB, &PORTB, 0}, // B0 0
  199. {&DDRB, &PINB, &PORTB, 1}, // B1 1
  200. {&DDRB, &PINB, &PORTB, 2}, // B2 2
  201. {&DDRB, &PINB, &PORTB, 3}, // B3 3
  202. {&DDRB, &PINB, &PORTB, 4}, // B4 4
  203. {&DDRB, &PINB, &PORTB, 5}, // B5 5
  204. {&DDRB, &PINB, &PORTB, 6}, // B6 6
  205. {&DDRB, &PINB, &PORTB, 7}, // B7 7
  206. {&DDRD, &PIND, &PORTD, 0}, // D0 8
  207. {&DDRD, &PIND, &PORTD, 1}, // D1 9
  208. {&DDRD, &PIND, &PORTD, 2}, // D2 10
  209. {&DDRD, &PIND, &PORTD, 3}, // D3 11
  210. {&DDRD, &PIND, &PORTD, 4}, // D4 12
  211. {&DDRD, &PIND, &PORTD, 5}, // D5 13
  212. {&DDRD, &PIND, &PORTD, 6}, // D6 14
  213. {&DDRD, &PIND, &PORTD, 7}, // D7 15
  214. {&DDRC, &PINC, &PORTC, 0}, // C0 16
  215. {&DDRC, &PINC, &PORTC, 1}, // C1 17
  216. {&DDRC, &PINC, &PORTC, 2}, // C2 18
  217. {&DDRC, &PINC, &PORTC, 3}, // C3 19
  218. {&DDRC, &PINC, &PORTC, 4}, // C4 20
  219. {&DDRC, &PINC, &PORTC, 5}, // C5 21
  220. {&DDRC, &PINC, &PORTC, 6}, // C6 22
  221. {&DDRC, &PINC, &PORTC, 7}, // C7 23
  222. {&DDRA, &PINA, &PORTA, 0}, // A0 24
  223. {&DDRA, &PINA, &PORTA, 1}, // A1 25
  224. {&DDRA, &PINA, &PORTA, 2}, // A2 26
  225. {&DDRA, &PINA, &PORTA, 3}, // A3 27
  226. {&DDRA, &PINA, &PORTA, 4}, // A4 28
  227. {&DDRA, &PINA, &PORTA, 5}, // A5 29
  228. {&DDRA, &PINA, &PORTA, 6}, // A6 30
  229. {&DDRA, &PINA, &PORTA, 7} // A7 31
  230. };
  231. #elif defined(VARIANT_BOBUINO)
  232. // Bobuino Layout
  233. static const pin_map_t pinMap[] = {
  234. {&DDRD, &PIND, &PORTD, 0}, // D0 0
  235. {&DDRD, &PIND, &PORTD, 1}, // D1 1
  236. {&DDRD, &PIND, &PORTD, 2}, // D2 2
  237. {&DDRD, &PIND, &PORTD, 3}, // D3 3
  238. {&DDRB, &PINB, &PORTB, 0}, // B0 4
  239. {&DDRB, &PINB, &PORTB, 1}, // B1 5
  240. {&DDRB, &PINB, &PORTB, 2}, // B2 6
  241. {&DDRB, &PINB, &PORTB, 3}, // B3 7
  242. {&DDRD, &PIND, &PORTD, 5}, // D5 8
  243. {&DDRD, &PIND, &PORTD, 6}, // D6 9
  244. {&DDRB, &PINB, &PORTB, 4}, // B4 10
  245. {&DDRB, &PINB, &PORTB, 5}, // B5 11
  246. {&DDRB, &PINB, &PORTB, 6}, // B6 12
  247. {&DDRB, &PINB, &PORTB, 7}, // B7 13
  248. {&DDRA, &PINA, &PORTA, 7}, // A7 14
  249. {&DDRA, &PINA, &PORTA, 6}, // A6 15
  250. {&DDRA, &PINA, &PORTA, 5}, // A5 16
  251. {&DDRA, &PINA, &PORTA, 4}, // A4 17
  252. {&DDRA, &PINA, &PORTA, 3}, // A3 18
  253. {&DDRA, &PINA, &PORTA, 2}, // A2 19
  254. {&DDRA, &PINA, &PORTA, 1}, // A1 20
  255. {&DDRA, &PINA, &PORTA, 0}, // A0 21
  256. {&DDRC, &PINC, &PORTC, 0}, // C0 22
  257. {&DDRC, &PINC, &PORTC, 1}, // C1 23
  258. {&DDRC, &PINC, &PORTC, 2}, // C2 24
  259. {&DDRC, &PINC, &PORTC, 3}, // C3 25
  260. {&DDRC, &PINC, &PORTC, 4}, // C4 26
  261. {&DDRC, &PINC, &PORTC, 5}, // C5 27
  262. {&DDRC, &PINC, &PORTC, 6}, // C6 28
  263. {&DDRC, &PINC, &PORTC, 7}, // C7 29
  264. {&DDRD, &PIND, &PORTD, 4}, // D4 30
  265. {&DDRD, &PIND, &PORTD, 7} // D7 31
  266. };
  267. #elif defined(VARIANT_STANDARD)
  268. // Standard Layout
  269. static const pin_map_t pinMap[] = {
  270. {&DDRB, &PINB, &PORTB, 0}, // B0 0
  271. {&DDRB, &PINB, &PORTB, 1}, // B1 1
  272. {&DDRB, &PINB, &PORTB, 2}, // B2 2
  273. {&DDRB, &PINB, &PORTB, 3}, // B3 3
  274. {&DDRB, &PINB, &PORTB, 4}, // B4 4
  275. {&DDRB, &PINB, &PORTB, 5}, // B5 5
  276. {&DDRB, &PINB, &PORTB, 6}, // B6 6
  277. {&DDRB, &PINB, &PORTB, 7}, // B7 7
  278. {&DDRD, &PIND, &PORTD, 0}, // D0 8
  279. {&DDRD, &PIND, &PORTD, 1}, // D1 9
  280. {&DDRD, &PIND, &PORTD, 2}, // D2 10
  281. {&DDRD, &PIND, &PORTD, 3}, // D3 11
  282. {&DDRD, &PIND, &PORTD, 4}, // D4 12
  283. {&DDRD, &PIND, &PORTD, 5}, // D5 13
  284. {&DDRD, &PIND, &PORTD, 6}, // D6 14
  285. {&DDRD, &PIND, &PORTD, 7}, // D7 15
  286. {&DDRC, &PINC, &PORTC, 0}, // C0 16
  287. {&DDRC, &PINC, &PORTC, 1}, // C1 17
  288. {&DDRC, &PINC, &PORTC, 2}, // C2 18
  289. {&DDRC, &PINC, &PORTC, 3}, // C3 19
  290. {&DDRC, &PINC, &PORTC, 4}, // C4 20
  291. {&DDRC, &PINC, &PORTC, 5}, // C5 21
  292. {&DDRC, &PINC, &PORTC, 6}, // C6 22
  293. {&DDRC, &PINC, &PORTC, 7}, // C7 23
  294. {&DDRA, &PINA, &PORTA, 7}, // A7 24
  295. {&DDRA, &PINA, &PORTA, 6}, // A6 25
  296. {&DDRA, &PINA, &PORTA, 5}, // A5 26
  297. {&DDRA, &PINA, &PORTA, 4}, // A4 27
  298. {&DDRA, &PINA, &PORTA, 3}, // A3 28
  299. {&DDRA, &PINA, &PORTA, 2}, // A2 29
  300. {&DDRA, &PINA, &PORTA, 1}, // A1 30
  301. {&DDRA, &PINA, &PORTA, 0} // A0 31
  302. };
  303. #else // !(VARIANT_MIGHTY || VARIANT_BOBUINO || VARIANT_STANDARD)
  304. #error Undefined variant 1284, 644, 324, 64, 32
  305. #endif
  306. #elif defined(__AVR_ATmega32U4__)
  307. #ifdef CORE_TEENSY
  308. // Teensy 2.0
  309. static const pin_map_t pinMap[] = {
  310. {&DDRB, &PINB, &PORTB, 0}, // B0 0
  311. {&DDRB, &PINB, &PORTB, 1}, // B1 1
  312. {&DDRB, &PINB, &PORTB, 2}, // B2 2
  313. {&DDRB, &PINB, &PORTB, 3}, // B3 3
  314. {&DDRB, &PINB, &PORTB, 7}, // B7 4
  315. {&DDRD, &PIND, &PORTD, 0}, // D0 5
  316. {&DDRD, &PIND, &PORTD, 1}, // D1 6
  317. {&DDRD, &PIND, &PORTD, 2}, // D2 7
  318. {&DDRD, &PIND, &PORTD, 3}, // D3 8
  319. {&DDRC, &PINC, &PORTC, 6}, // C6 9
  320. {&DDRC, &PINC, &PORTC, 7}, // C7 10
  321. {&DDRD, &PIND, &PORTD, 6}, // D6 11
  322. {&DDRD, &PIND, &PORTD, 7}, // D7 12
  323. {&DDRB, &PINB, &PORTB, 4}, // B4 13
  324. {&DDRB, &PINB, &PORTB, 5}, // B5 14
  325. {&DDRB, &PINB, &PORTB, 6}, // B6 15
  326. {&DDRF, &PINF, &PORTF, 7}, // F7 16
  327. {&DDRF, &PINF, &PORTF, 6}, // F6 17
  328. {&DDRF, &PINF, &PORTF, 5}, // F5 18
  329. {&DDRF, &PINF, &PORTF, 4}, // F4 19
  330. {&DDRF, &PINF, &PORTF, 1}, // F1 20
  331. {&DDRF, &PINF, &PORTF, 0}, // F0 21
  332. {&DDRD, &PIND, &PORTD, 4}, // D4 22
  333. {&DDRD, &PIND, &PORTD, 5}, // D5 23
  334. {&DDRE, &PINE, &PORTE, 6} // E6 24
  335. };
  336. #else // !CORE_TEENSY
  337. // Leonardo
  338. static const pin_map_t pinMap[] = {
  339. {&DDRD, &PIND, &PORTD, 2}, // D2 0
  340. {&DDRD, &PIND, &PORTD, 3}, // D3 1
  341. {&DDRD, &PIND, &PORTD, 1}, // D1 2
  342. {&DDRD, &PIND, &PORTD, 0}, // D0 3
  343. {&DDRD, &PIND, &PORTD, 4}, // D4 4
  344. {&DDRC, &PINC, &PORTC, 6}, // C6 5
  345. {&DDRD, &PIND, &PORTD, 7}, // D7 6
  346. {&DDRE, &PINE, &PORTE, 6}, // E6 7
  347. {&DDRB, &PINB, &PORTB, 4}, // B4 8
  348. {&DDRB, &PINB, &PORTB, 5}, // B5 9
  349. {&DDRB, &PINB, &PORTB, 6}, // B6 10
  350. {&DDRB, &PINB, &PORTB, 7}, // B7 11
  351. {&DDRD, &PIND, &PORTD, 6}, // D6 12
  352. {&DDRC, &PINC, &PORTC, 7}, // C7 13
  353. {&DDRB, &PINB, &PORTB, 3}, // B3 14
  354. {&DDRB, &PINB, &PORTB, 1}, // B1 15
  355. {&DDRB, &PINB, &PORTB, 2}, // B2 16
  356. {&DDRB, &PINB, &PORTB, 0}, // B0 17
  357. {&DDRF, &PINF, &PORTF, 7}, // F7 18
  358. {&DDRF, &PINF, &PORTF, 6}, // F6 19
  359. {&DDRF, &PINF, &PORTF, 5}, // F5 20
  360. {&DDRF, &PINF, &PORTF, 4}, // F4 21
  361. {&DDRF, &PINF, &PORTF, 1}, // F1 22
  362. {&DDRF, &PINF, &PORTF, 0}, // F0 23
  363. {&DDRD, &PIND, &PORTD, 4}, // D4 24
  364. {&DDRD, &PIND, &PORTD, 7}, // D7 25
  365. {&DDRB, &PINB, &PORTB, 4}, // B4 26
  366. {&DDRB, &PINB, &PORTB, 5}, // B5 27
  367. {&DDRB, &PINB, &PORTB, 6}, // B6 28
  368. {&DDRD, &PIND, &PORTD, 6} // D6 29
  369. };
  370. #endif // !CORE_TEENSY
  371. #elif defined(__AVR_AT90USB646__) || defined(__AVR_AT90USB1286__)
  372. // Teensy++ 1.0 & 2.0
  373. static const pin_map_t pinMap[] = {
  374. {&DDRD, &PIND, &PORTD, 0}, // D0 0
  375. {&DDRD, &PIND, &PORTD, 1}, // D1 1
  376. {&DDRD, &PIND, &PORTD, 2}, // D2 2
  377. {&DDRD, &PIND, &PORTD, 3}, // D3 3
  378. {&DDRD, &PIND, &PORTD, 4}, // D4 4
  379. {&DDRD, &PIND, &PORTD, 5}, // D5 5
  380. {&DDRD, &PIND, &PORTD, 6}, // D6 6
  381. {&DDRD, &PIND, &PORTD, 7}, // D7 7
  382. {&DDRE, &PINE, &PORTE, 0}, // E0 8
  383. {&DDRE, &PINE, &PORTE, 1}, // E1 9
  384. {&DDRC, &PINC, &PORTC, 0}, // C0 10
  385. {&DDRC, &PINC, &PORTC, 1}, // C1 11
  386. {&DDRC, &PINC, &PORTC, 2}, // C2 12
  387. {&DDRC, &PINC, &PORTC, 3}, // C3 13
  388. {&DDRC, &PINC, &PORTC, 4}, // C4 14
  389. {&DDRC, &PINC, &PORTC, 5}, // C5 15
  390. {&DDRC, &PINC, &PORTC, 6}, // C6 16
  391. {&DDRC, &PINC, &PORTC, 7}, // C7 17
  392. {&DDRE, &PINE, &PORTE, 6}, // E6 18
  393. {&DDRE, &PINE, &PORTE, 7}, // E7 19
  394. {&DDRB, &PINB, &PORTB, 0}, // B0 20
  395. {&DDRB, &PINB, &PORTB, 1}, // B1 21
  396. {&DDRB, &PINB, &PORTB, 2}, // B2 22
  397. {&DDRB, &PINB, &PORTB, 3}, // B3 23
  398. {&DDRB, &PINB, &PORTB, 4}, // B4 24
  399. {&DDRB, &PINB, &PORTB, 5}, // B5 25
  400. {&DDRB, &PINB, &PORTB, 6}, // B6 26
  401. {&DDRB, &PINB, &PORTB, 7}, // B7 27
  402. {&DDRA, &PINA, &PORTA, 0}, // A0 28
  403. {&DDRA, &PINA, &PORTA, 1}, // A1 29
  404. {&DDRA, &PINA, &PORTA, 2}, // A2 30
  405. {&DDRA, &PINA, &PORTA, 3}, // A3 31
  406. {&DDRA, &PINA, &PORTA, 4}, // A4 32
  407. {&DDRA, &PINA, &PORTA, 5}, // A5 33
  408. {&DDRA, &PINA, &PORTA, 6}, // A6 34
  409. {&DDRA, &PINA, &PORTA, 7}, // A7 35
  410. {&DDRE, &PINE, &PORTE, 4}, // E4 36
  411. {&DDRE, &PINE, &PORTE, 5}, // E5 37
  412. {&DDRF, &PINF, &PORTF, 0}, // F0 38
  413. {&DDRF, &PINF, &PORTF, 1}, // F1 39
  414. {&DDRF, &PINF, &PORTF, 2}, // F2 40
  415. {&DDRF, &PINF, &PORTF, 3}, // F3 41
  416. {&DDRF, &PINF, &PORTF, 4}, // F4 42
  417. {&DDRF, &PINF, &PORTF, 5}, // F5 43
  418. {&DDRF, &PINF, &PORTF, 6}, // F6 44
  419. {&DDRF, &PINF, &PORTF, 7} // F7 45
  420. };
  421. #else // CPU type
  422. #error "Unknown CPU type for Software SPI"
  423. #endif // CPU type
  424. /** count of pins */
  425. static constexpr uint8_t digitalPinCount = sizeof(pinMap) / sizeof(pin_map_t);
  426. /** generate bad pin number error */
  427. void badPinNumber()
  428. __attribute__((error("Pin number is too large or not a constant")));
  429. /**
  430. * Check for valid pin number
  431. * @param[in] pin Number of pin to be checked.
  432. */
  433. FORCE_INLINE static void badPinCheck(const uint8_t pin) {
  434. if (!__builtin_constant_p(pin) || pin >= digitalPinCount) badPinNumber();
  435. }
  436. /**
  437. * Fast write helper
  438. * @param[in] address I/O register address
  439. * @param[in] bit bit number to write
  440. * @param[in] level value for bit
  441. */
  442. FORCE_INLINE static void fastBitWriteSafe(volatile uint8_t* address, uint8_t bit, bool level) {
  443. uint8_t oldSREG;
  444. if (address > (uint8_t*)0x5F) { oldSREG = SREG; cli(); }
  445. if (level) SBI(*address, bit); else CBI(*address, bit);
  446. if (address > (uint8_t*)0x5F) SREG = oldSREG;
  447. }
  448. /**
  449. * Read pin value
  450. * @param[in] pin Arduino pin number
  451. * @return value read
  452. */
  453. FORCE_INLINE static bool fastDigitalRead(uint8_t pin) {
  454. badPinCheck(pin);
  455. return (*pinMap[pin].pin >> pinMap[pin].bit) & 1;
  456. }
  457. /**
  458. * Toggle a pin
  459. * @param[in] pin Arduino pin number
  460. *
  461. * If the pin is in output mode toggle the pin level.
  462. * If the pin is in input mode toggle the state of the 20K pullup.
  463. */
  464. FORCE_INLINE static void fastDigitalToggle(uint8_t pin) {
  465. badPinCheck(pin);
  466. if (pinMap[pin].pin > (uint8_t*)0x5F)
  467. *pinMap[pin].pin = _BV(pinMap[pin].bit); // Must write bit to high address port
  468. else
  469. SBI(*pinMap[pin].pin, pinMap[pin].bit); // Compiles to sbi and PIN register will not be read
  470. }
  471. /**
  472. * Set pin value
  473. * @param[in] pin Arduino pin number
  474. * @param[in] level value to write
  475. */
  476. FORCE_INLINE static void fastDigitalWrite(uint8_t pin, bool level) {
  477. badPinCheck(pin);
  478. fastBitWriteSafe(pinMap[pin].port, pinMap[pin].bit, level);
  479. }
  480. /**
  481. * Set pin mode
  482. * @param[in] pin Arduino pin number
  483. * @param[in] mode if true set output mode else input mode
  484. *
  485. * fastPinMode does not enable or disable the 20K pullup for input mode.
  486. */
  487. FORCE_INLINE static void fastPinMode(uint8_t pin, bool mode) {
  488. badPinCheck(pin);
  489. fastBitWriteSafe(pinMap[pin].ddr, pinMap[pin].bit, mode);
  490. }
  491. #endif // !__arm__
  492. /**
  493. * Set pin configuration
  494. * @param[in] pin Arduino pin number
  495. * @param[in] mode If true set output mode else input mode
  496. * @param[in] level If mode is output, set level high/low.
  497. * If mode is input, enable or disable the pin's 20K pullup.
  498. */
  499. FORCE_INLINE static void fastPinConfig(uint8_t pin, bool mode, bool level) {
  500. fastPinMode(pin, mode);
  501. fastDigitalWrite(pin, level);
  502. }
  503. /**
  504. * @class DigitalPin
  505. * @brief Fast digital port I/O
  506. */
  507. template<uint8_t PinNumber>
  508. class DigitalPin {
  509. public:
  510. /** Constructor */
  511. DigitalPin() {}
  512. /**
  513. * Constructor
  514. * @param[in] pinMode if true set output mode else input mode.
  515. */
  516. explicit DigitalPin(bool pinMode) { mode(pinMode); }
  517. /**
  518. * Constructor
  519. * @param[in] mode If true set output mode else input mode
  520. * @param[in] level If mode is output, set level high/low.
  521. * If mode is input, enable or disable the pin's 20K pullup.
  522. */
  523. DigitalPin(bool mode, bool level) { config(mode, level); }
  524. /**
  525. * Assignment operator
  526. * @param[in] value If true set the pin's level high else set the
  527. * pin's level low.
  528. *
  529. * @return This DigitalPin instance.
  530. */
  531. FORCE_INLINE DigitalPin & operator = (bool value) { write(value); return *this; }
  532. /**
  533. * Parentheses operator
  534. * @return Pin's level
  535. */
  536. FORCE_INLINE operator bool () const { return read(); }
  537. /**
  538. * Set pin configuration
  539. * @param[in] mode If true set output mode else input mode
  540. * @param[in] level If mode is output, set level high/low.
  541. * If mode is input, enable or disable the pin's 20K pullup.
  542. */
  543. FORCE_INLINE void config(bool mode, bool level) { fastPinConfig(PinNumber, mode, level); }
  544. /**
  545. * Set pin level high if output mode or enable 20K pullup if input mode.
  546. */
  547. FORCE_INLINE void high() { write(true); }
  548. /**
  549. * Set pin level low if output mode or disable 20K pullup if input mode.
  550. */
  551. FORCE_INLINE void low() { write(false); }
  552. /**
  553. * Set pin mode
  554. * @param[in] pinMode if true set output mode else input mode.
  555. *
  556. * mode() does not enable or disable the 20K pullup for input mode.
  557. */
  558. FORCE_INLINE void mode(bool pinMode) { fastPinMode(PinNumber, pinMode); }
  559. /** @return Pin's level */
  560. FORCE_INLINE bool read() const { return fastDigitalRead(PinNumber); }
  561. /**
  562. * Toggle a pin
  563. * If the pin is in output mode toggle the pin's level.
  564. * If the pin is in input mode toggle the state of the 20K pullup.
  565. */
  566. FORCE_INLINE void toggle() { fastDigitalToggle(PinNumber); }
  567. /**
  568. * Write the pin's level.
  569. * @param[in] value If true set the pin's level high else set the
  570. * pin's level low.
  571. */
  572. FORCE_INLINE void write(bool value) { fastDigitalWrite(PinNumber, value); }
  573. };
  574. const bool MISO_MODE = false, // Pin Mode for MISO is input.
  575. MISO_LEVEL = false, // Pullups disabled for MISO are disabled.
  576. MOSI_MODE = true, // Pin Mode for MOSI is output.
  577. SCK_MODE = true; // Pin Mode for SCK is output.
  578. /**
  579. * @class SoftSPI
  580. * @brief Fast software SPI.
  581. */
  582. template<uint8_t MisoPin, uint8_t MosiPin, uint8_t SckPin, uint8_t Mode = 0>
  583. class SoftSPI {
  584. public:
  585. /** Initialize SoftSPI pins. */
  586. void begin() {
  587. fastPinConfig(MisoPin, MISO_MODE, MISO_LEVEL);
  588. fastPinConfig(MosiPin, MOSI_MODE, !MODE_CPHA(Mode));
  589. fastPinConfig(SckPin, SCK_MODE, MODE_CPOL(Mode));
  590. }
  591. /**
  592. * Soft SPI receive byte.
  593. * @return Data byte received.
  594. */
  595. FORCE_INLINE uint8_t receive() {
  596. uint8_t data = 0;
  597. receiveBit(7, &data);
  598. receiveBit(6, &data);
  599. receiveBit(5, &data);
  600. receiveBit(4, &data);
  601. receiveBit(3, &data);
  602. receiveBit(2, &data);
  603. receiveBit(1, &data);
  604. receiveBit(0, &data);
  605. return data;
  606. }
  607. /**
  608. * Soft SPI send byte.
  609. * @param[in] data Data byte to send.
  610. */
  611. FORCE_INLINE void send(uint8_t data) {
  612. sendBit(7, data);
  613. sendBit(6, data);
  614. sendBit(5, data);
  615. sendBit(4, data);
  616. sendBit(3, data);
  617. sendBit(2, data);
  618. sendBit(1, data);
  619. sendBit(0, data);
  620. }
  621. /**
  622. * Soft SPI transfer byte.
  623. * @param[in] txData Data byte to send.
  624. * @return Data byte received.
  625. */
  626. FORCE_INLINE uint8_t transfer(uint8_t txData) {
  627. uint8_t rxData = 0;
  628. transferBit(7, &rxData, txData);
  629. transferBit(6, &rxData, txData);
  630. transferBit(5, &rxData, txData);
  631. transferBit(4, &rxData, txData);
  632. transferBit(3, &rxData, txData);
  633. transferBit(2, &rxData, txData);
  634. transferBit(1, &rxData, txData);
  635. transferBit(0, &rxData, txData);
  636. return rxData;
  637. }
  638. private:
  639. FORCE_INLINE bool MODE_CPHA(uint8_t mode) { return bool(mode & 1); }
  640. FORCE_INLINE bool MODE_CPOL(uint8_t mode) { return bool(mode & 2); }
  641. FORCE_INLINE void receiveBit(uint8_t bit, uint8_t *data) {
  642. if (MODE_CPHA(Mode)) fastDigitalWrite(SckPin, !MODE_CPOL(Mode));
  643. nop;
  644. nop;
  645. fastDigitalWrite(SckPin,
  646. MODE_CPHA(Mode) ? MODE_CPOL(Mode) : !MODE_CPOL(Mode));
  647. if (fastDigitalRead(MisoPin)) SBI(*data, bit);
  648. if (!MODE_CPHA(Mode)) fastDigitalWrite(SckPin, MODE_CPOL(Mode));
  649. }
  650. FORCE_INLINE void sendBit(uint8_t bit, uint8_t data) {
  651. if (MODE_CPHA(Mode)) fastDigitalWrite(SckPin, !MODE_CPOL(Mode));
  652. fastDigitalWrite(MosiPin, data & _BV(bit));
  653. fastDigitalWrite(SckPin, MODE_CPHA(Mode) ? MODE_CPOL(Mode) : !MODE_CPOL(Mode));
  654. nop;
  655. nop;
  656. if (!MODE_CPHA(Mode)) fastDigitalWrite(SckPin, MODE_CPOL(Mode));
  657. }
  658. FORCE_INLINE void transferBit(uint8_t bit, uint8_t *rxData, uint8_t txData) {
  659. if (MODE_CPHA(Mode)) fastDigitalWrite(SckPin, !MODE_CPOL(Mode));
  660. fastDigitalWrite(MosiPin, txData & _BV(bit));
  661. fastDigitalWrite(SckPin,
  662. MODE_CPHA(Mode) ? MODE_CPOL(Mode) : !MODE_CPOL(Mode));
  663. if (fastDigitalRead(MisoPin)) SBI(*rxData, bit);
  664. if (!MODE_CPHA(Mode)) fastDigitalWrite(SckPin, MODE_CPOL(Mode));
  665. }
  666. };