softspi.h 27 KB

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