My Marlin configs for Fabrikator Mini and CTC i3 Pro B
Ви не можете вибрати більше 25 тем Теми мають розпочинатися з літери або цифри, можуть містити дефіси (-) і не повинні перевищувати 35 символів.

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