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

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770
  1. //https://github.com/niteris/ArduinoSoftSpi
  2. #include <Arduino.h>
  3. #ifdef __arm__
  4. #ifdef CORE_TEENSY
  5. //------------------------------------------------------------------------------
  6. /** read pin value
  7. * @param[in] pin Arduino pin number
  8. * @return value read
  9. */
  10. static inline __attribute__((always_inline))
  11. bool fastDigitalRead(uint8_t pin) {
  12. return *portInputRegister(pin);
  13. }
  14. //------------------------------------------------------------------------------
  15. /** Set pin value
  16. * @param[in] pin Arduino pin number
  17. * @param[in] level value to write
  18. */
  19. static inline __attribute__((always_inline))
  20. void fastDigitalWrite(uint8_t pin, bool value) {
  21. if (value) {
  22. *portSetRegister(pin) = 1;
  23. } else {
  24. *portClearRegister(pin) = 1;
  25. }
  26. }
  27. #else // CORE_TEENSY
  28. //------------------------------------------------------------------------------
  29. /** read pin value
  30. * @param[in] pin Arduino pin number
  31. * @return value read
  32. */
  33. static inline __attribute__((always_inline))
  34. bool fastDigitalRead(uint8_t pin){
  35. return g_APinDescription[pin].pPort->PIO_PDSR & g_APinDescription[pin].ulPin;
  36. }
  37. //------------------------------------------------------------------------------
  38. /** Set pin value
  39. * @param[in] pin Arduino pin number
  40. * @param[in] level value to write
  41. */
  42. static inline __attribute__((always_inline))
  43. void fastDigitalWrite(uint8_t pin, bool value){
  44. if(value) {
  45. g_APinDescription[pin].pPort->PIO_SODR = g_APinDescription[pin].ulPin;
  46. } else {
  47. g_APinDescription[pin].pPort->PIO_CODR = g_APinDescription[pin].ulPin;
  48. }
  49. }
  50. #endif // CORE_TEENSY
  51. //------------------------------------------------------------------------------
  52. inline void fastDigitalToggle(uint8_t pin) {
  53. fastDigitalWrite(pin, !fastDigitalRead(pin));
  54. }
  55. //------------------------------------------------------------------------------
  56. inline void fastPinMode(uint8_t pin, bool mode) {pinMode(pin, mode);}
  57. #else // __arm__
  58. #include <avr/io.h>
  59. #include <util/atomic.h>
  60. //------------------------------------------------------------------------------
  61. /**
  62. * @class pin_map_t
  63. * @brief struct for mapping digital pins
  64. */
  65. struct pin_map_t {
  66. volatile uint8_t* ddr; /**< address of DDR for this pin */
  67. volatile uint8_t* pin; /**< address of PIN for this pin */
  68. volatile uint8_t* port; /**< address of PORT for this pin */
  69. uint8_t bit; /**< bit number for this pin */
  70. };
  71. //------------------------------------------------------------------------------
  72. #if defined(__AVR_ATmega168__)\
  73. ||defined(__AVR_ATmega168P__)\
  74. ||defined(__AVR_ATmega328P__)
  75. // 168 and 328 Arduinos
  76. const static pin_map_t pinMap[] = {
  77. {&DDRD, &PIND, &PORTD, 0}, // D0 0
  78. {&DDRD, &PIND, &PORTD, 1}, // D1 1
  79. {&DDRD, &PIND, &PORTD, 2}, // D2 2
  80. {&DDRD, &PIND, &PORTD, 3}, // D3 3
  81. {&DDRD, &PIND, &PORTD, 4}, // D4 4
  82. {&DDRD, &PIND, &PORTD, 5}, // D5 5
  83. {&DDRD, &PIND, &PORTD, 6}, // D6 6
  84. {&DDRD, &PIND, &PORTD, 7}, // D7 7
  85. {&DDRB, &PINB, &PORTB, 0}, // B0 8
  86. {&DDRB, &PINB, &PORTB, 1}, // B1 9
  87. {&DDRB, &PINB, &PORTB, 2}, // B2 10
  88. {&DDRB, &PINB, &PORTB, 3}, // B3 11
  89. {&DDRB, &PINB, &PORTB, 4}, // B4 12
  90. {&DDRB, &PINB, &PORTB, 5}, // B5 13
  91. {&DDRC, &PINC, &PORTC, 0}, // C0 14
  92. {&DDRC, &PINC, &PORTC, 1}, // C1 15
  93. {&DDRC, &PINC, &PORTC, 2}, // C2 16
  94. {&DDRC, &PINC, &PORTC, 3}, // C3 17
  95. {&DDRC, &PINC, &PORTC, 4}, // C4 18
  96. {&DDRC, &PINC, &PORTC, 5} // C5 19
  97. };
  98. //------------------------------------------------------------------------------
  99. #elif defined(__AVR_ATmega1280__)\
  100. || defined(__AVR_ATmega2560__)
  101. // Mega
  102. static const pin_map_t pinMap[] = {
  103. {&DDRE, &PINE, &PORTE, 0}, // E0 0
  104. {&DDRE, &PINE, &PORTE, 1}, // E1 1
  105. {&DDRE, &PINE, &PORTE, 4}, // E4 2
  106. {&DDRE, &PINE, &PORTE, 5}, // E5 3
  107. {&DDRG, &PING, &PORTG, 5}, // G5 4
  108. {&DDRE, &PINE, &PORTE, 3}, // E3 5
  109. {&DDRH, &PINH, &PORTH, 3}, // H3 6
  110. {&DDRH, &PINH, &PORTH, 4}, // H4 7
  111. {&DDRH, &PINH, &PORTH, 5}, // H5 8
  112. {&DDRH, &PINH, &PORTH, 6}, // H6 9
  113. {&DDRB, &PINB, &PORTB, 4}, // B4 10
  114. {&DDRB, &PINB, &PORTB, 5}, // B5 11
  115. {&DDRB, &PINB, &PORTB, 6}, // B6 12
  116. {&DDRB, &PINB, &PORTB, 7}, // B7 13
  117. {&DDRJ, &PINJ, &PORTJ, 1}, // J1 14
  118. {&DDRJ, &PINJ, &PORTJ, 0}, // J0 15
  119. {&DDRH, &PINH, &PORTH, 1}, // H1 16
  120. {&DDRH, &PINH, &PORTH, 0}, // H0 17
  121. {&DDRD, &PIND, &PORTD, 3}, // D3 18
  122. {&DDRD, &PIND, &PORTD, 2}, // D2 19
  123. {&DDRD, &PIND, &PORTD, 1}, // D1 20
  124. {&DDRD, &PIND, &PORTD, 0}, // D0 21
  125. {&DDRA, &PINA, &PORTA, 0}, // A0 22
  126. {&DDRA, &PINA, &PORTA, 1}, // A1 23
  127. {&DDRA, &PINA, &PORTA, 2}, // A2 24
  128. {&DDRA, &PINA, &PORTA, 3}, // A3 25
  129. {&DDRA, &PINA, &PORTA, 4}, // A4 26
  130. {&DDRA, &PINA, &PORTA, 5}, // A5 27
  131. {&DDRA, &PINA, &PORTA, 6}, // A6 28
  132. {&DDRA, &PINA, &PORTA, 7}, // A7 29
  133. {&DDRC, &PINC, &PORTC, 7}, // C7 30
  134. {&DDRC, &PINC, &PORTC, 6}, // C6 31
  135. {&DDRC, &PINC, &PORTC, 5}, // C5 32
  136. {&DDRC, &PINC, &PORTC, 4}, // C4 33
  137. {&DDRC, &PINC, &PORTC, 3}, // C3 34
  138. {&DDRC, &PINC, &PORTC, 2}, // C2 35
  139. {&DDRC, &PINC, &PORTC, 1}, // C1 36
  140. {&DDRC, &PINC, &PORTC, 0}, // C0 37
  141. {&DDRD, &PIND, &PORTD, 7}, // D7 38
  142. {&DDRG, &PING, &PORTG, 2}, // G2 39
  143. {&DDRG, &PING, &PORTG, 1}, // G1 40
  144. {&DDRG, &PING, &PORTG, 0}, // G0 41
  145. {&DDRL, &PINL, &PORTL, 7}, // L7 42
  146. {&DDRL, &PINL, &PORTL, 6}, // L6 43
  147. {&DDRL, &PINL, &PORTL, 5}, // L5 44
  148. {&DDRL, &PINL, &PORTL, 4}, // L4 45
  149. {&DDRL, &PINL, &PORTL, 3}, // L3 46
  150. {&DDRL, &PINL, &PORTL, 2}, // L2 47
  151. {&DDRL, &PINL, &PORTL, 1}, // L1 48
  152. {&DDRL, &PINL, &PORTL, 0}, // L0 49
  153. {&DDRB, &PINB, &PORTB, 3}, // B3 50
  154. {&DDRB, &PINB, &PORTB, 2}, // B2 51
  155. {&DDRB, &PINB, &PORTB, 1}, // B1 52
  156. {&DDRB, &PINB, &PORTB, 0}, // B0 53
  157. {&DDRF, &PINF, &PORTF, 0}, // F0 54
  158. {&DDRF, &PINF, &PORTF, 1}, // F1 55
  159. {&DDRF, &PINF, &PORTF, 2}, // F2 56
  160. {&DDRF, &PINF, &PORTF, 3}, // F3 57
  161. {&DDRF, &PINF, &PORTF, 4}, // F4 58
  162. {&DDRF, &PINF, &PORTF, 5}, // F5 59
  163. {&DDRF, &PINF, &PORTF, 6}, // F6 60
  164. {&DDRF, &PINF, &PORTF, 7}, // F7 61
  165. {&DDRK, &PINK, &PORTK, 0}, // K0 62
  166. {&DDRK, &PINK, &PORTK, 1}, // K1 63
  167. {&DDRK, &PINK, &PORTK, 2}, // K2 64
  168. {&DDRK, &PINK, &PORTK, 3}, // K3 65
  169. {&DDRK, &PINK, &PORTK, 4}, // K4 66
  170. {&DDRK, &PINK, &PORTK, 5}, // K5 67
  171. {&DDRK, &PINK, &PORTK, 6}, // K6 68
  172. {&DDRK, &PINK, &PORTK, 7}, // K7 69
  173. //pins_MIGHTYBOARD_REVE.h
  174. {&DDRG, &PING, &PORTG, 4}, // G4 70
  175. {&DDRG, &PING, &PORTG, 3}, // G3 71
  176. {&DDRJ, &PINJ, &PORTJ, 2}, // J2 72
  177. {&DDRJ, &PINJ, &PORTJ, 3}, // J3 73
  178. {&DDRJ, &PINJ, &PORTJ, 7}, // J7 74
  179. {&DDRJ, &PINJ, &PORTJ, 4}, // J4 75
  180. {&DDRJ, &PINJ, &PORTJ, 5}, // J5 76
  181. {&DDRJ, &PINJ, &PORTJ, 6}, // J6 77
  182. {&DDRE, &PINE, &PORTE, 2}, // E2 78
  183. {&DDRE, &PINE, &PORTE, 6} // E6 79
  184. };
  185. //------------------------------------------------------------------------------
  186. #elif defined(__AVR_ATmega1284P__)\
  187. || defined(__AVR_ATmega1284__)\
  188. || defined(__AVR_ATmega644P__)\
  189. || defined(__AVR_ATmega644__)\
  190. || defined(__AVR_ATmega64__)\
  191. || defined(__AVR_ATmega32__)\
  192. || defined(__AVR_ATmega324__)\
  193. || defined(__AVR_ATmega16__)
  194. #ifdef defined(VARIANT_MIGHTY)
  195. // Mighty Layout
  196. static const pin_map_t pinMap[] = {
  197. {&DDRB, &PINB, &PORTB, 0}, // B0 0
  198. {&DDRB, &PINB, &PORTB, 1}, // B1 1
  199. {&DDRB, &PINB, &PORTB, 2}, // B2 2
  200. {&DDRB, &PINB, &PORTB, 3}, // B3 3
  201. {&DDRB, &PINB, &PORTB, 4}, // B4 4
  202. {&DDRB, &PINB, &PORTB, 5}, // B5 5
  203. {&DDRB, &PINB, &PORTB, 6}, // B6 6
  204. {&DDRB, &PINB, &PORTB, 7}, // B7 7
  205. {&DDRD, &PIND, &PORTD, 0}, // D0 8
  206. {&DDRD, &PIND, &PORTD, 1}, // D1 9
  207. {&DDRD, &PIND, &PORTD, 2}, // D2 10
  208. {&DDRD, &PIND, &PORTD, 3}, // D3 11
  209. {&DDRD, &PIND, &PORTD, 4}, // D4 12
  210. {&DDRD, &PIND, &PORTD, 5}, // D5 13
  211. {&DDRD, &PIND, &PORTD, 6}, // D6 14
  212. {&DDRD, &PIND, &PORTD, 7}, // D7 15
  213. {&DDRC, &PINC, &PORTC, 0}, // C0 16
  214. {&DDRC, &PINC, &PORTC, 1}, // C1 17
  215. {&DDRC, &PINC, &PORTC, 2}, // C2 18
  216. {&DDRC, &PINC, &PORTC, 3}, // C3 19
  217. {&DDRC, &PINC, &PORTC, 4}, // C4 20
  218. {&DDRC, &PINC, &PORTC, 5}, // C5 21
  219. {&DDRC, &PINC, &PORTC, 6}, // C6 22
  220. {&DDRC, &PINC, &PORTC, 7}, // C7 23
  221. {&DDRA, &PINA, &PORTA, 0}, // A0 24
  222. {&DDRA, &PINA, &PORTA, 1}, // A1 25
  223. {&DDRA, &PINA, &PORTA, 2}, // A2 26
  224. {&DDRA, &PINA, &PORTA, 3}, // A3 27
  225. {&DDRA, &PINA, &PORTA, 4}, // A4 28
  226. {&DDRA, &PINA, &PORTA, 5}, // A5 29
  227. {&DDRA, &PINA, &PORTA, 6}, // A6 30
  228. {&DDRA, &PINA, &PORTA, 7} // A7 31
  229. };
  230. #elif defined(VARIANT_BOBUINO)
  231. // Bobuino Layout
  232. static const pin_map_t pinMap[] = {
  233. {&DDRD, &PIND, &PORTD, 0}, // D0 0
  234. {&DDRD, &PIND, &PORTD, 1}, // D1 1
  235. {&DDRD, &PIND, &PORTD, 2}, // D2 2
  236. {&DDRD, &PIND, &PORTD, 3}, // D3 3
  237. {&DDRB, &PINB, &PORTB, 0}, // B0 4
  238. {&DDRB, &PINB, &PORTB, 1}, // B1 5
  239. {&DDRB, &PINB, &PORTB, 2}, // B2 6
  240. {&DDRB, &PINB, &PORTB, 3}, // B3 7
  241. {&DDRD, &PIND, &PORTD, 5}, // D5 8
  242. {&DDRD, &PIND, &PORTD, 6}, // D6 9
  243. {&DDRB, &PINB, &PORTB, 4}, // B4 10
  244. {&DDRB, &PINB, &PORTB, 5}, // B5 11
  245. {&DDRB, &PINB, &PORTB, 6}, // B6 12
  246. {&DDRB, &PINB, &PORTB, 7}, // B7 13
  247. {&DDRA, &PINA, &PORTA, 7}, // A7 14
  248. {&DDRA, &PINA, &PORTA, 6}, // A6 15
  249. {&DDRA, &PINA, &PORTA, 5}, // A5 16
  250. {&DDRA, &PINA, &PORTA, 4}, // A4 17
  251. {&DDRA, &PINA, &PORTA, 3}, // A3 18
  252. {&DDRA, &PINA, &PORTA, 2}, // A2 19
  253. {&DDRA, &PINA, &PORTA, 1}, // A1 20
  254. {&DDRA, &PINA, &PORTA, 0}, // A0 21
  255. {&DDRC, &PINC, &PORTC, 0}, // C0 22
  256. {&DDRC, &PINC, &PORTC, 1}, // C1 23
  257. {&DDRC, &PINC, &PORTC, 2}, // C2 24
  258. {&DDRC, &PINC, &PORTC, 3}, // C3 25
  259. {&DDRC, &PINC, &PORTC, 4}, // C4 26
  260. {&DDRC, &PINC, &PORTC, 5}, // C5 27
  261. {&DDRC, &PINC, &PORTC, 6}, // C6 28
  262. {&DDRC, &PINC, &PORTC, 7}, // C7 29
  263. {&DDRD, &PIND, &PORTD, 4}, // D4 30
  264. {&DDRD, &PIND, &PORTD, 7} // D7 31
  265. };
  266. #elif defined(VARIANT_STANDARD)
  267. // Standard Layout
  268. static const pin_map_t pinMap[] = {
  269. {&DDRB, &PINB, &PORTB, 0}, // B0 0
  270. {&DDRB, &PINB, &PORTB, 1}, // B1 1
  271. {&DDRB, &PINB, &PORTB, 2}, // B2 2
  272. {&DDRB, &PINB, &PORTB, 3}, // B3 3
  273. {&DDRB, &PINB, &PORTB, 4}, // B4 4
  274. {&DDRB, &PINB, &PORTB, 5}, // B5 5
  275. {&DDRB, &PINB, &PORTB, 6}, // B6 6
  276. {&DDRB, &PINB, &PORTB, 7}, // B7 7
  277. {&DDRD, &PIND, &PORTD, 0}, // D0 8
  278. {&DDRD, &PIND, &PORTD, 1}, // D1 9
  279. {&DDRD, &PIND, &PORTD, 2}, // D2 10
  280. {&DDRD, &PIND, &PORTD, 3}, // D3 11
  281. {&DDRD, &PIND, &PORTD, 4}, // D4 12
  282. {&DDRD, &PIND, &PORTD, 5}, // D5 13
  283. {&DDRD, &PIND, &PORTD, 6}, // D6 14
  284. {&DDRD, &PIND, &PORTD, 7}, // D7 15
  285. {&DDRC, &PINC, &PORTC, 0}, // C0 16
  286. {&DDRC, &PINC, &PORTC, 1}, // C1 17
  287. {&DDRC, &PINC, &PORTC, 2}, // C2 18
  288. {&DDRC, &PINC, &PORTC, 3}, // C3 19
  289. {&DDRC, &PINC, &PORTC, 4}, // C4 20
  290. {&DDRC, &PINC, &PORTC, 5}, // C5 21
  291. {&DDRC, &PINC, &PORTC, 6}, // C6 22
  292. {&DDRC, &PINC, &PORTC, 7}, // C7 23
  293. {&DDRA, &PINA, &PORTA, 7}, // A7 24
  294. {&DDRA, &PINA, &PORTA, 6}, // A6 25
  295. {&DDRA, &PINA, &PORTA, 5}, // A5 26
  296. {&DDRA, &PINA, &PORTA, 4}, // A4 27
  297. {&DDRA, &PINA, &PORTA, 3}, // A3 28
  298. {&DDRA, &PINA, &PORTA, 2}, // A2 29
  299. {&DDRA, &PINA, &PORTA, 1}, // A1 30
  300. {&DDRA, &PINA, &PORTA, 0} // A0 31
  301. };
  302. #else // VARIANT_MIGHTY
  303. #error Undefined variant 1284, 644, 324, 64, 32
  304. #endif // VARIANT_MIGHTY
  305. //------------------------------------------------------------------------------
  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. //------------------------------------------------------------------------------
  337. #else // CORE_TEENSY
  338. // Leonardo
  339. static const pin_map_t pinMap[] = {
  340. {&DDRD, &PIND, &PORTD, 2}, // D2 0
  341. {&DDRD, &PIND, &PORTD, 3}, // D3 1
  342. {&DDRD, &PIND, &PORTD, 1}, // D1 2
  343. {&DDRD, &PIND, &PORTD, 0}, // D0 3
  344. {&DDRD, &PIND, &PORTD, 4}, // D4 4
  345. {&DDRC, &PINC, &PORTC, 6}, // C6 5
  346. {&DDRD, &PIND, &PORTD, 7}, // D7 6
  347. {&DDRE, &PINE, &PORTE, 6}, // E6 7
  348. {&DDRB, &PINB, &PORTB, 4}, // B4 8
  349. {&DDRB, &PINB, &PORTB, 5}, // B5 9
  350. {&DDRB, &PINB, &PORTB, 6}, // B6 10
  351. {&DDRB, &PINB, &PORTB, 7}, // B7 11
  352. {&DDRD, &PIND, &PORTD, 6}, // D6 12
  353. {&DDRC, &PINC, &PORTC, 7}, // C7 13
  354. {&DDRB, &PINB, &PORTB, 3}, // B3 14
  355. {&DDRB, &PINB, &PORTB, 1}, // B1 15
  356. {&DDRB, &PINB, &PORTB, 2}, // B2 16
  357. {&DDRB, &PINB, &PORTB, 0}, // B0 17
  358. {&DDRF, &PINF, &PORTF, 7}, // F7 18
  359. {&DDRF, &PINF, &PORTF, 6}, // F6 19
  360. {&DDRF, &PINF, &PORTF, 5}, // F5 20
  361. {&DDRF, &PINF, &PORTF, 4}, // F4 21
  362. {&DDRF, &PINF, &PORTF, 1}, // F1 22
  363. {&DDRF, &PINF, &PORTF, 0}, // F0 23
  364. {&DDRD, &PIND, &PORTD, 4}, // D4 24
  365. {&DDRD, &PIND, &PORTD, 7}, // D7 25
  366. {&DDRB, &PINB, &PORTB, 4}, // B4 26
  367. {&DDRB, &PINB, &PORTB, 5}, // B5 27
  368. {&DDRB, &PINB, &PORTB, 6}, // B6 28
  369. {&DDRD, &PIND, &PORTD, 6} // D6 29
  370. };
  371. #endif // CORE_TEENSY
  372. //------------------------------------------------------------------------------
  373. #elif defined(__AVR_AT90USB646__)\
  374. || 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. //------------------------------------------------------------------------------
  425. #else // CPU type
  426. #error unknown CPU type
  427. #endif // CPU type
  428. //------------------------------------------------------------------------------
  429. /** count of pins */
  430. static const uint8_t digitalPinCount = sizeof(pinMap)/sizeof(pin_map_t);
  431. //==============================================================================
  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. static inline __attribute__((always_inline))
  440. void badPinCheck(uint8_t pin) {
  441. if (!__builtin_constant_p(pin) || pin >= digitalPinCount) {
  442. badPinNumber();
  443. }
  444. }
  445. //------------------------------------------------------------------------------
  446. /** fast write helper
  447. * @param[in] address I/O register address
  448. * @param[in] bit bit number to write
  449. * @param[in] level value for bit
  450. */
  451. static inline __attribute__((always_inline))
  452. void fastBitWriteSafe(volatile uint8_t* address, uint8_t bit, bool level) {
  453. uint8_t oldSREG;
  454. if (address > (uint8_t*)0X5F) {
  455. oldSREG = SREG;
  456. cli();
  457. }
  458. if (level) {
  459. *address |= 1 << bit;
  460. } else {
  461. *address &= ~(1 << bit);
  462. }
  463. if (address > (uint8_t*)0X5F) {
  464. SREG = oldSREG;
  465. }
  466. }
  467. //------------------------------------------------------------------------------
  468. /** read pin value
  469. * @param[in] pin Arduino pin number
  470. * @return value read
  471. */
  472. static inline __attribute__((always_inline))
  473. bool fastDigitalRead(uint8_t pin) {
  474. badPinCheck(pin);
  475. return (*pinMap[pin].pin >> pinMap[pin].bit) & 1;
  476. }
  477. //------------------------------------------------------------------------------
  478. /** toggle a pin
  479. * @param[in] pin Arduino pin number
  480. *
  481. * If the pin is in output mode toggle the pin level.
  482. * If the pin is in input mode toggle the state of the 20K pullup.
  483. */
  484. static inline __attribute__((always_inline))
  485. void fastDigitalToggle(uint8_t pin) {
  486. badPinCheck(pin);
  487. if (pinMap[pin].pin > (uint8_t*)0X5F) {
  488. // must write bit to high address port
  489. *pinMap[pin].pin = 1 << pinMap[pin].bit;
  490. } else {
  491. // will compile to sbi and PIN register will not be read.
  492. *pinMap[pin].pin |= 1 << pinMap[pin].bit;
  493. }
  494. }
  495. //------------------------------------------------------------------------------
  496. /** Set pin value
  497. * @param[in] pin Arduino pin number
  498. * @param[in] level value to write
  499. */
  500. static inline __attribute__((always_inline))
  501. void fastDigitalWrite(uint8_t pin, bool level) {
  502. badPinCheck(pin);
  503. fastBitWriteSafe(pinMap[pin].port, pinMap[pin].bit, level);
  504. }
  505. //------------------------------------------------------------------------------
  506. /** set pin mode
  507. * @param[in] pin Arduino pin number
  508. * @param[in] mode if true set output mode else input mode
  509. *
  510. * fastPinMode does not enable or disable the 20K pullup for input mode.
  511. */
  512. static inline __attribute__((always_inline))
  513. void fastPinMode(uint8_t pin, bool mode) {
  514. badPinCheck(pin);
  515. fastBitWriteSafe(pinMap[pin].ddr, pinMap[pin].bit, mode);
  516. }
  517. #endif // __arm__
  518. //------------------------------------------------------------------------------
  519. /** set pin configuration
  520. * @param[in] pin Arduino pin number
  521. * @param[in] mode If true set output mode else input mode
  522. * @param[in] level If mode is output, set level high/low.
  523. * If mode is input, enable or disable the pin's 20K pullup.
  524. */
  525. static inline __attribute__((always_inline))
  526. void fastPinConfig(uint8_t pin, bool mode, bool level) {
  527. fastPinMode(pin, mode);
  528. fastDigitalWrite(pin, level);
  529. }
  530. //==============================================================================
  531. /**
  532. * @class DigitalPin
  533. * @brief Fast digital port I/O
  534. */
  535. template<uint8_t PinNumber>
  536. class DigitalPin {
  537. public:
  538. //----------------------------------------------------------------------------
  539. /** Constructor */
  540. DigitalPin() {}
  541. //----------------------------------------------------------------------------
  542. /** Constructor
  543. * @param[in] pinMode if true set output mode else input mode.
  544. */
  545. explicit DigitalPin(bool pinMode) {
  546. mode(pinMode);
  547. }
  548. //----------------------------------------------------------------------------
  549. /** Constructor
  550. * @param[in] mode If true set output mode else input mode
  551. * @param[in] level If mode is output, set level high/low.
  552. * If mode is input, enable or disable the pin's 20K pullup.
  553. */
  554. DigitalPin(bool mode, bool level) {
  555. config(mode, level);
  556. }
  557. //----------------------------------------------------------------------------
  558. /** Asignment operator
  559. * @param[in] value If true set the pin's level high else set the
  560. * pin's level low.
  561. *
  562. * @return This DigitalPin instance.
  563. */
  564. inline DigitalPin & operator = (bool value) __attribute__((always_inline)) {
  565. write(value);
  566. return *this;
  567. }
  568. //----------------------------------------------------------------------------
  569. /** Parenthesis operator
  570. * @return Pin's level
  571. */
  572. inline operator bool () const __attribute__((always_inline)) {
  573. return read();
  574. }
  575. //----------------------------------------------------------------------------
  576. /** set pin configuration
  577. * @param[in] mode If true set output mode else input mode
  578. * @param[in] level If mode is output, set level high/low.
  579. * If mode is input, enable or disable the pin's 20K pullup.
  580. */
  581. inline __attribute__((always_inline))
  582. void config(bool mode, bool level) {
  583. fastPinConfig(PinNumber, mode, level);
  584. }
  585. //----------------------------------------------------------------------------
  586. /**
  587. * Set pin level high if output mode or enable 20K pullup if input mode.
  588. */
  589. inline __attribute__((always_inline))
  590. void high() {write(true);}
  591. //----------------------------------------------------------------------------
  592. /**
  593. * Set pin level low if output mode or disable 20K pullup if input mode.
  594. */
  595. inline __attribute__((always_inline))
  596. void low() {write(false);}
  597. //----------------------------------------------------------------------------
  598. /**
  599. * Set pin mode
  600. * @param[in] pinMode if true set output mode else input mode.
  601. *
  602. * mode() does not enable or disable the 20K pullup for input mode.
  603. */
  604. inline __attribute__((always_inline))
  605. void mode(bool pinMode) {
  606. fastPinMode(PinNumber, pinMode);
  607. }
  608. //----------------------------------------------------------------------------
  609. /** @return Pin's level */
  610. inline __attribute__((always_inline))
  611. bool read() const {
  612. return fastDigitalRead(PinNumber);
  613. }
  614. //----------------------------------------------------------------------------
  615. /** toggle a pin
  616. *
  617. * If the pin is in output mode toggle the pin's level.
  618. * If the pin is in input mode toggle the state of the 20K pullup.
  619. */
  620. inline __attribute__((always_inline))
  621. void toggle() {
  622. fastDigitalToggle(PinNumber);
  623. }
  624. //----------------------------------------------------------------------------
  625. /** Write the pin's level.
  626. * @param[in] value If true set the pin's level high else set the
  627. * pin's level low.
  628. */
  629. inline __attribute__((always_inline))
  630. void write(bool value) {
  631. fastDigitalWrite(PinNumber, value);
  632. }
  633. };
  634. //------------------------------------------------------------------------------
  635. /** Nop for timing. */
  636. #define nop asm volatile ("nop\n\t")
  637. //------------------------------------------------------------------------------
  638. /** Pin Mode for MISO is input.*/
  639. const bool MISO_MODE = false;
  640. /** Pullups disabled for MISO are disabled. */
  641. const bool MISO_LEVEL = false;
  642. /** Pin Mode for MOSI is output.*/
  643. const bool MOSI_MODE = true;
  644. /** Pin Mode for SCK is output. */
  645. const bool SCK_MODE = true;
  646. //------------------------------------------------------------------------------
  647. /**
  648. * @class SoftSPI
  649. * @brief Fast software SPI.
  650. */
  651. template<uint8_t MisoPin, uint8_t MosiPin, uint8_t SckPin, uint8_t Mode = 0>
  652. class SoftSPI {
  653. public:
  654. //----------------------------------------------------------------------------
  655. /** Initialize SoftSPI pins. */
  656. void begin() {
  657. fastPinConfig(MisoPin, MISO_MODE, MISO_LEVEL);
  658. fastPinConfig(MosiPin, MOSI_MODE, !MODE_CPHA(Mode));
  659. fastPinConfig(SckPin, SCK_MODE, MODE_CPOL(Mode));
  660. }
  661. //----------------------------------------------------------------------------
  662. /** Soft SPI receive byte.
  663. * @return Data byte received.
  664. */
  665. inline __attribute__((always_inline))
  666. uint8_t receive() {
  667. uint8_t data = 0;
  668. receiveBit(7, &data);
  669. receiveBit(6, &data);
  670. receiveBit(5, &data);
  671. receiveBit(4, &data);
  672. receiveBit(3, &data);
  673. receiveBit(2, &data);
  674. receiveBit(1, &data);
  675. receiveBit(0, &data);
  676. return data;
  677. }
  678. //----------------------------------------------------------------------------
  679. /** Soft SPI send byte.
  680. * @param[in] data Data byte to send.
  681. */
  682. inline __attribute__((always_inline))
  683. void send(uint8_t data) {
  684. sendBit(7, data);
  685. sendBit(6, data);
  686. sendBit(5, data);
  687. sendBit(4, data);
  688. sendBit(3, data);
  689. sendBit(2, data);
  690. sendBit(1, data);
  691. sendBit(0, data);
  692. }
  693. //----------------------------------------------------------------------------
  694. /** Soft SPI transfer byte.
  695. * @param[in] txData Data byte to send.
  696. * @return Data byte received.
  697. */
  698. inline __attribute__((always_inline))
  699. uint8_t transfer(uint8_t txData) {
  700. uint8_t rxData = 0;
  701. transferBit(7, &rxData, txData);
  702. transferBit(6, &rxData, txData);
  703. transferBit(5, &rxData, txData);
  704. transferBit(4, &rxData, txData);
  705. transferBit(3, &rxData, txData);
  706. transferBit(2, &rxData, txData);
  707. transferBit(1, &rxData, txData);
  708. transferBit(0, &rxData, txData);
  709. return rxData;
  710. }
  711. private:
  712. //----------------------------------------------------------------------------
  713. inline __attribute__((always_inline))
  714. bool MODE_CPHA(uint8_t mode) {return (mode & 1) != 0;}
  715. inline __attribute__((always_inline))
  716. bool MODE_CPOL(uint8_t mode) {return (mode & 2) != 0;}
  717. inline __attribute__((always_inline))
  718. void receiveBit(uint8_t bit, uint8_t* data) {
  719. if (MODE_CPHA(Mode)) {
  720. fastDigitalWrite(SckPin, !MODE_CPOL(Mode));
  721. }
  722. nop;
  723. nop;
  724. fastDigitalWrite(SckPin,
  725. MODE_CPHA(Mode) ? MODE_CPOL(Mode) : !MODE_CPOL(Mode));
  726. if (fastDigitalRead(MisoPin)) *data |= 1 << bit;
  727. if (!MODE_CPHA(Mode)) {
  728. fastDigitalWrite(SckPin, MODE_CPOL(Mode));
  729. }
  730. }
  731. //----------------------------------------------------------------------------
  732. inline __attribute__((always_inline))
  733. void sendBit(uint8_t bit, uint8_t data) {
  734. if (MODE_CPHA(Mode)) {
  735. fastDigitalWrite(SckPin, !MODE_CPOL(Mode));
  736. }
  737. fastDigitalWrite(MosiPin, data & (1 << bit));
  738. fastDigitalWrite(SckPin,
  739. MODE_CPHA(Mode) ? MODE_CPOL(Mode) : !MODE_CPOL(Mode));
  740. nop;
  741. nop;
  742. if (!MODE_CPHA(Mode)) {
  743. fastDigitalWrite(SckPin, MODE_CPOL(Mode));
  744. }
  745. }
  746. //----------------------------------------------------------------------------
  747. inline __attribute__((always_inline))
  748. void transferBit(uint8_t bit, uint8_t* rxData, uint8_t txData) {
  749. if (MODE_CPHA(Mode)) {
  750. fastDigitalWrite(SckPin, !MODE_CPOL(Mode));
  751. }
  752. fastDigitalWrite(MosiPin, txData & (1 << bit));
  753. fastDigitalWrite(SckPin,
  754. MODE_CPHA(Mode) ? MODE_CPOL(Mode) : !MODE_CPOL(Mode));
  755. if (fastDigitalRead(MisoPin)) *rxData |= 1 << bit;
  756. if (!MODE_CPHA(Mode)) {
  757. fastDigitalWrite(SckPin, MODE_CPOL(Mode));
  758. }
  759. }
  760. //----------------------------------------------------------------------------
  761. };