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

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