您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

661 行
23KB

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