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 24KB

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