Teensy 4.1 core updated for C++20
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.

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298
  1. #include "core_pins.h"
  2. /*
  3. struct digital_pin_bitband_and_config_table_struct {
  4. volatile uint32_t *reg;
  5. volatile uint32_t *mux;
  6. volatile uint32_t *pad;
  7. uint32_t mask;
  8. };
  9. extern const struct digital_pin_bitband_and_config_table_struct digital_pin_to_info_PGM[];
  10. #define digitalPinToPort(pin) (pin)
  11. #define digitalPinToBitMask(pin) (digital_pin_to_info_PGM[(pin)].mask)
  12. #define portOutputRegister(pin) ((digital_pin_to_info_PGM[(pin)].reg))
  13. #define portSetRegister(pin) ((digital_pin_to_info_PGM[(pin)].reg + 0x21))
  14. #define portClearRegister(pin) ((digital_pin_to_info_PGM[(pin)].reg + 0x22))
  15. #define portToggleRegister(pin) ((digital_pin_to_info_PGM[(pin)].reg + 0x23))
  16. #define portInputRegister(pin) ((digital_pin_to_info_PGM[(pin)].reg + 2))
  17. #define portModeRegister(pin) ((digital_pin_to_info_PGM[(pin)].reg + 1))
  18. #define portConfigRegister(pin) ((digital_pin_to_info_PGM[(pin)].max))
  19. #define digitalPinToPortReg(pin) (portOutputRegister(pin))
  20. */
  21. const struct digital_pin_bitband_and_config_table_struct digital_pin_to_info_PGM[] = {
  22. {&CORE_PIN0_PORTREG, &CORE_PIN0_CONFIG, &CORE_PIN0_PADCONFIG, CORE_PIN0_BITMASK},
  23. {&CORE_PIN1_PORTREG, &CORE_PIN1_CONFIG, &CORE_PIN1_PADCONFIG, CORE_PIN1_BITMASK},
  24. {&CORE_PIN2_PORTREG, &CORE_PIN2_CONFIG, &CORE_PIN2_PADCONFIG, CORE_PIN2_BITMASK},
  25. {&CORE_PIN3_PORTREG, &CORE_PIN3_CONFIG, &CORE_PIN3_PADCONFIG, CORE_PIN3_BITMASK},
  26. {&CORE_PIN4_PORTREG, &CORE_PIN4_CONFIG, &CORE_PIN4_PADCONFIG, CORE_PIN4_BITMASK},
  27. {&CORE_PIN5_PORTREG, &CORE_PIN5_CONFIG, &CORE_PIN5_PADCONFIG, CORE_PIN5_BITMASK},
  28. {&CORE_PIN6_PORTREG, &CORE_PIN6_CONFIG, &CORE_PIN6_PADCONFIG, CORE_PIN6_BITMASK},
  29. {&CORE_PIN7_PORTREG, &CORE_PIN7_CONFIG, &CORE_PIN7_PADCONFIG, CORE_PIN7_BITMASK},
  30. {&CORE_PIN8_PORTREG, &CORE_PIN8_CONFIG, &CORE_PIN8_PADCONFIG, CORE_PIN8_BITMASK},
  31. {&CORE_PIN9_PORTREG, &CORE_PIN9_CONFIG, &CORE_PIN9_PADCONFIG, CORE_PIN9_BITMASK},
  32. {&CORE_PIN10_PORTREG, &CORE_PIN10_CONFIG, &CORE_PIN10_PADCONFIG, CORE_PIN10_BITMASK},
  33. {&CORE_PIN11_PORTREG, &CORE_PIN11_CONFIG, &CORE_PIN11_PADCONFIG, CORE_PIN11_BITMASK},
  34. {&CORE_PIN12_PORTREG, &CORE_PIN12_CONFIG, &CORE_PIN12_PADCONFIG, CORE_PIN12_BITMASK},
  35. {&CORE_PIN13_PORTREG, &CORE_PIN13_CONFIG, &CORE_PIN13_PADCONFIG, CORE_PIN13_BITMASK},
  36. {&CORE_PIN14_PORTREG, &CORE_PIN14_CONFIG, &CORE_PIN14_PADCONFIG, CORE_PIN14_BITMASK},
  37. {&CORE_PIN15_PORTREG, &CORE_PIN15_CONFIG, &CORE_PIN15_PADCONFIG, CORE_PIN15_BITMASK},
  38. {&CORE_PIN16_PORTREG, &CORE_PIN16_CONFIG, &CORE_PIN16_PADCONFIG, CORE_PIN16_BITMASK},
  39. {&CORE_PIN17_PORTREG, &CORE_PIN17_CONFIG, &CORE_PIN17_PADCONFIG, CORE_PIN17_BITMASK},
  40. {&CORE_PIN18_PORTREG, &CORE_PIN18_CONFIG, &CORE_PIN18_PADCONFIG, CORE_PIN18_BITMASK},
  41. {&CORE_PIN19_PORTREG, &CORE_PIN19_CONFIG, &CORE_PIN19_PADCONFIG, CORE_PIN19_BITMASK},
  42. {&CORE_PIN20_PORTREG, &CORE_PIN20_CONFIG, &CORE_PIN20_PADCONFIG, CORE_PIN20_BITMASK},
  43. {&CORE_PIN21_PORTREG, &CORE_PIN21_CONFIG, &CORE_PIN21_PADCONFIG, CORE_PIN21_BITMASK},
  44. {&CORE_PIN22_PORTREG, &CORE_PIN22_CONFIG, &CORE_PIN22_PADCONFIG, CORE_PIN22_BITMASK},
  45. {&CORE_PIN23_PORTREG, &CORE_PIN23_CONFIG, &CORE_PIN23_PADCONFIG, CORE_PIN23_BITMASK},
  46. {&CORE_PIN24_PORTREG, &CORE_PIN24_CONFIG, &CORE_PIN24_PADCONFIG, CORE_PIN24_BITMASK},
  47. {&CORE_PIN25_PORTREG, &CORE_PIN25_CONFIG, &CORE_PIN25_PADCONFIG, CORE_PIN25_BITMASK},
  48. {&CORE_PIN26_PORTREG, &CORE_PIN26_CONFIG, &CORE_PIN26_PADCONFIG, CORE_PIN26_BITMASK},
  49. {&CORE_PIN27_PORTREG, &CORE_PIN27_CONFIG, &CORE_PIN27_PADCONFIG, CORE_PIN27_BITMASK},
  50. {&CORE_PIN28_PORTREG, &CORE_PIN28_CONFIG, &CORE_PIN28_PADCONFIG, CORE_PIN28_BITMASK},
  51. {&CORE_PIN29_PORTREG, &CORE_PIN29_CONFIG, &CORE_PIN29_PADCONFIG, CORE_PIN29_BITMASK},
  52. {&CORE_PIN30_PORTREG, &CORE_PIN30_CONFIG, &CORE_PIN30_PADCONFIG, CORE_PIN30_BITMASK},
  53. {&CORE_PIN31_PORTREG, &CORE_PIN31_CONFIG, &CORE_PIN31_PADCONFIG, CORE_PIN31_BITMASK},
  54. {&CORE_PIN32_PORTREG, &CORE_PIN32_CONFIG, &CORE_PIN32_PADCONFIG, CORE_PIN32_BITMASK},
  55. {&CORE_PIN33_PORTREG, &CORE_PIN33_CONFIG, &CORE_PIN33_PADCONFIG, CORE_PIN33_BITMASK},
  56. {&CORE_PIN34_PORTREG, &CORE_PIN34_CONFIG, &CORE_PIN34_PADCONFIG, CORE_PIN34_BITMASK},
  57. {&CORE_PIN35_PORTREG, &CORE_PIN35_CONFIG, &CORE_PIN35_PADCONFIG, CORE_PIN35_BITMASK},
  58. {&CORE_PIN36_PORTREG, &CORE_PIN36_CONFIG, &CORE_PIN36_PADCONFIG, CORE_PIN36_BITMASK},
  59. {&CORE_PIN37_PORTREG, &CORE_PIN37_CONFIG, &CORE_PIN37_PADCONFIG, CORE_PIN37_BITMASK},
  60. {&CORE_PIN38_PORTREG, &CORE_PIN38_CONFIG, &CORE_PIN38_PADCONFIG, CORE_PIN38_BITMASK},
  61. {&CORE_PIN39_PORTREG, &CORE_PIN39_CONFIG, &CORE_PIN39_PADCONFIG, CORE_PIN39_BITMASK},
  62. #if CORE_NUM_DIGITAL > 40
  63. {&CORE_PIN40_PORTREG, &CORE_PIN40_CONFIG, &CORE_PIN40_PADCONFIG, CORE_PIN40_BITMASK},
  64. {&CORE_PIN41_PORTREG, &CORE_PIN41_CONFIG, &CORE_PIN41_PADCONFIG, CORE_PIN41_BITMASK},
  65. {&CORE_PIN42_PORTREG, &CORE_PIN42_CONFIG, &CORE_PIN42_PADCONFIG, CORE_PIN42_BITMASK},
  66. {&CORE_PIN43_PORTREG, &CORE_PIN43_CONFIG, &CORE_PIN43_PADCONFIG, CORE_PIN43_BITMASK},
  67. {&CORE_PIN44_PORTREG, &CORE_PIN44_CONFIG, &CORE_PIN44_PADCONFIG, CORE_PIN44_BITMASK},
  68. {&CORE_PIN45_PORTREG, &CORE_PIN45_CONFIG, &CORE_PIN45_PADCONFIG, CORE_PIN45_BITMASK},
  69. #endif
  70. #if CORE_NUM_DIGITAL > 46
  71. {&CORE_PIN46_PORTREG, &CORE_PIN46_CONFIG, &CORE_PIN46_PADCONFIG, CORE_PIN46_BITMASK},
  72. {&CORE_PIN47_PORTREG, &CORE_PIN47_CONFIG, &CORE_PIN47_PADCONFIG, CORE_PIN47_BITMASK},
  73. {&CORE_PIN48_PORTREG, &CORE_PIN48_CONFIG, &CORE_PIN48_PADCONFIG, CORE_PIN48_BITMASK},
  74. {&CORE_PIN49_PORTREG, &CORE_PIN49_CONFIG, &CORE_PIN49_PADCONFIG, CORE_PIN49_BITMASK},
  75. {&CORE_PIN50_PORTREG, &CORE_PIN50_CONFIG, &CORE_PIN50_PADCONFIG, CORE_PIN50_BITMASK},
  76. {&CORE_PIN51_PORTREG, &CORE_PIN51_CONFIG, &CORE_PIN51_PADCONFIG, CORE_PIN51_BITMASK},
  77. {&CORE_PIN52_PORTREG, &CORE_PIN52_CONFIG, &CORE_PIN52_PADCONFIG, CORE_PIN52_BITMASK},
  78. {&CORE_PIN53_PORTREG, &CORE_PIN53_CONFIG, &CORE_PIN53_PADCONFIG, CORE_PIN53_BITMASK},
  79. {&CORE_PIN54_PORTREG, &CORE_PIN54_CONFIG, &CORE_PIN54_PADCONFIG, CORE_PIN54_BITMASK},
  80. #endif
  81. };
  82. void digitalWrite(uint8_t pin, uint8_t val)
  83. {
  84. const struct digital_pin_bitband_and_config_table_struct *p;
  85. uint32_t pinmode, mask;
  86. if (pin >= CORE_NUM_DIGITAL) return;
  87. p = digital_pin_to_info_PGM + pin;
  88. pinmode = *(p->reg + 1);
  89. mask = p->mask;
  90. if (pinmode & mask) {
  91. // pin is configured for output mode
  92. if (val) {
  93. *(p->reg + 0x21) = mask; // set register
  94. } else {
  95. *(p->reg + 0x22) = mask; // clear register
  96. }
  97. } else {
  98. // pin is configured for input mode
  99. // value controls PULLUP/PULLDOWN resistors
  100. if (val) {
  101. *(p->pad) = IOMUXC_PAD_DSE(7) | IOMUXC_PAD_PKE | IOMUXC_PAD_PUE | IOMUXC_PAD_PUS(3) | IOMUXC_PAD_HYS;
  102. } else {
  103. *(p->pad) = IOMUXC_PAD_DSE(7) | IOMUXC_PAD_PKE | IOMUXC_PAD_PUE | IOMUXC_PAD_PUS(0) | IOMUXC_PAD_HYS;
  104. }
  105. }
  106. }
  107. void digitalToggle(uint8_t pin)
  108. {
  109. const struct digital_pin_bitband_and_config_table_struct *p;
  110. uint32_t mask;
  111. if (pin >= CORE_NUM_DIGITAL) return;
  112. p = digital_pin_to_info_PGM + pin;
  113. mask = p->mask;
  114. *(p->reg + 0x23) = mask; // toggle register
  115. }
  116. uint8_t digitalRead(uint8_t pin)
  117. {
  118. const struct digital_pin_bitband_and_config_table_struct *p;
  119. if (pin >= CORE_NUM_DIGITAL) return 0;
  120. p = digital_pin_to_info_PGM + pin;
  121. return (*(p->reg + 2) & p->mask) ? 1 : 0;
  122. }
  123. void pinMode(uint8_t pin, uint8_t mode)
  124. {
  125. const struct digital_pin_bitband_and_config_table_struct *p;
  126. if (pin >= CORE_NUM_DIGITAL) return;
  127. p = digital_pin_to_info_PGM + pin;
  128. if (mode == OUTPUT || mode == OUTPUT_OPENDRAIN) {
  129. *(p->reg + 1) |= p->mask; // TODO: atomic
  130. if (mode == OUTPUT) {
  131. *(p->pad) = IOMUXC_PAD_DSE(7);
  132. } else { // OUTPUT_OPENDRAIN
  133. *(p->pad) = IOMUXC_PAD_DSE(7) | IOMUXC_PAD_ODE;
  134. }
  135. } else {
  136. *(p->reg + 1) &= ~(p->mask); // TODO: atomic
  137. if (mode == INPUT) {
  138. *(p->pad) = IOMUXC_PAD_DSE(7);
  139. } else if (mode == INPUT_PULLUP) {
  140. *(p->pad) = IOMUXC_PAD_DSE(7) | IOMUXC_PAD_PKE | IOMUXC_PAD_PUE | IOMUXC_PAD_PUS(3) | IOMUXC_PAD_HYS;
  141. } else if (mode == INPUT_PULLDOWN) {
  142. *(p->pad) = IOMUXC_PAD_DSE(7) | IOMUXC_PAD_PKE | IOMUXC_PAD_PUE | IOMUXC_PAD_PUS(0) | IOMUXC_PAD_HYS;
  143. } else { // INPUT_DISABLE
  144. *(p->pad) = IOMUXC_PAD_DSE(7) | IOMUXC_PAD_HYS;
  145. }
  146. }
  147. *(p->mux) = 5 | 0x10;
  148. }
  149. void _shiftOut(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder, uint8_t value)
  150. {
  151. if (bitOrder == LSBFIRST) {
  152. shiftOut_lsbFirst(dataPin, clockPin, value);
  153. } else {
  154. shiftOut_msbFirst(dataPin, clockPin, value);
  155. }
  156. }
  157. static const unsigned maxSpeed = 10000000ULL; //10 MHz
  158. static const unsigned maxSpeedBeforeDelay = 392000000ULL; //max F_CPU_ACTUAL before doing delays (measured for 10MHz, -O2)
  159. void shiftOut_lsbFirst(uint8_t dataPin, uint8_t clockPin, uint8_t value)
  160. {
  161. uint8_t mask;
  162. if (F_CPU_ACTUAL > maxSpeedBeforeDelay) {
  163. uint32_t cycles = (F_CPU_ACTUAL / 2 / maxSpeed);
  164. uint32_t t = ARM_DWT_CYCCNT;
  165. for (mask = 0x01; mask; mask <<= 1) {
  166. digitalWrite(dataPin, value & mask);
  167. do {;} while(ARM_DWT_CYCCNT - t < cycles);
  168. t += cycles / 2;
  169. digitalWrite(clockPin, HIGH);
  170. do {;} while(ARM_DWT_CYCCNT - t < cycles);
  171. t += cycles;
  172. digitalWrite(clockPin, LOW);
  173. do {;} while(ARM_DWT_CYCCNT - t < cycles);
  174. t += cycles / 2;
  175. }
  176. }
  177. else
  178. for (mask=0x01; mask; mask <<= 1) {
  179. digitalWrite(dataPin, value & mask);
  180. digitalWrite(clockPin, HIGH);
  181. digitalWrite(clockPin, LOW);
  182. }
  183. }
  184. void shiftOut_msbFirst(uint8_t dataPin, uint8_t clockPin, uint8_t value)
  185. {
  186. uint32_t v;
  187. asm volatile ("rbit %0, %1" : "=r" (v) : "r" (value) );
  188. shiftOut_lsbFirst(dataPin, clockPin, v >> 24);
  189. }
  190. uint8_t _shiftIn(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder)
  191. {
  192. if (bitOrder == LSBFIRST) {
  193. return shiftIn_lsbFirst(dataPin, clockPin);
  194. } else {
  195. return shiftIn_msbFirst(dataPin, clockPin);
  196. }
  197. }
  198. uint8_t shiftIn_lsbFirst(uint8_t dataPin, uint8_t clockPin)
  199. {
  200. uint8_t mask, value=0;
  201. for (mask=0x01; mask; mask <<= 1) {
  202. digitalWrite(clockPin, HIGH);
  203. if (digitalRead(dataPin)) value |= mask;
  204. digitalWrite(clockPin, LOW);
  205. }
  206. return value;
  207. }
  208. uint8_t shiftIn_msbFirst(uint8_t dataPin, uint8_t clockPin)
  209. {
  210. uint8_t mask, value=0;
  211. for (mask=0x80; mask; mask >>= 1) {
  212. digitalWrite(clockPin, HIGH);
  213. if (digitalRead(dataPin)) value |= mask;
  214. digitalWrite(clockPin, LOW);
  215. }
  216. return value;
  217. }
  218. //(*portInputRegister(pin) & digitalPinToBitMask(pin))
  219. uint32_t pulseIn_high(uint8_t pin, uint32_t timeout)
  220. {
  221. const struct digital_pin_bitband_and_config_table_struct *p;
  222. p = digital_pin_to_info_PGM + pin;
  223. uint32_t usec_start, usec_stop;
  224. // wait for any previous pulse to end
  225. usec_start = micros();
  226. while ((*(p->reg + 2) & p->mask)) {
  227. if (micros()-usec_start > timeout) return 0;
  228. }
  229. // wait for the pulse to start
  230. usec_start = micros();
  231. while (!(*(p->reg + 2) & p->mask)) {
  232. if (micros()-usec_start > timeout) return 0;
  233. }
  234. usec_start = micros();
  235. // wait for the pulse to stop
  236. while ((*(p->reg + 2) & p->mask)) {
  237. if (micros()-usec_start > timeout) return 0;
  238. }
  239. usec_stop = micros();
  240. return usec_stop - usec_start;
  241. }
  242. uint32_t pulseIn_low(uint8_t pin, uint32_t timeout)
  243. {
  244. const struct digital_pin_bitband_and_config_table_struct *p;
  245. p = digital_pin_to_info_PGM + pin;
  246. uint32_t usec_start, usec_stop;
  247. // wait for any previous pulse to end
  248. usec_start = micros();
  249. while (!(*(p->reg + 2) & p->mask)) {
  250. if (micros() - usec_start > timeout) return 0;
  251. }
  252. // wait for the pulse to start
  253. usec_start = micros();
  254. while ((*(p->reg + 2) & p->mask)) {
  255. if (micros() - usec_start > timeout) return 0;
  256. }
  257. usec_start = micros();
  258. // wait for the pulse to stop
  259. while (!(*(p->reg + 2) & p->mask)) {
  260. if (micros() - usec_start > timeout) return 0;
  261. }
  262. usec_stop = micros();
  263. return usec_stop - usec_start;
  264. }
  265. // TODO: an inline version should handle the common case where state is const
  266. uint32_t pulseIn(uint8_t pin, uint8_t state, uint32_t timeout)
  267. {
  268. if (pin >= CORE_NUM_DIGITAL) return 0;
  269. if (state) return pulseIn_high(pin, timeout);
  270. return pulseIn_low(pin, timeout);
  271. }