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.

242 lines
8.9KB

  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. };
  57. void digitalWrite(uint8_t pin, uint8_t val)
  58. {
  59. const struct digital_pin_bitband_and_config_table_struct *p;
  60. uint32_t pinmode, mask;
  61. if (pin >= CORE_NUM_DIGITAL) return;
  62. p = digital_pin_to_info_PGM + pin;
  63. pinmode = *(p->reg + 1);
  64. mask = p->mask;
  65. if (pinmode & mask) {
  66. // pin is configured for output mode
  67. if (val) {
  68. *(p->reg + 0x21) = mask; // set register
  69. } else {
  70. *(p->reg + 0x22) = mask; // clear register
  71. }
  72. } else {
  73. // pin is configured for input mode
  74. // writing controls pullup resistor
  75. // TODO....
  76. }
  77. }
  78. uint8_t digitalRead(uint8_t pin)
  79. {
  80. const struct digital_pin_bitband_and_config_table_struct *p;
  81. if (pin >= CORE_NUM_DIGITAL) return 0;
  82. p = digital_pin_to_info_PGM + pin;
  83. return (*(p->reg + 2) & p->mask) ? 1 : 0;
  84. }
  85. void pinMode(uint8_t pin, uint8_t mode)
  86. {
  87. const struct digital_pin_bitband_and_config_table_struct *p;
  88. if (pin >= CORE_NUM_DIGITAL) return;
  89. p = digital_pin_to_info_PGM + pin;
  90. if (mode == OUTPUT || mode == OUTPUT_OPENDRAIN) {
  91. *(p->reg + 1) |= p->mask; // TODO: atomic
  92. if (mode == OUTPUT) {
  93. *(p->pad) = IOMUXC_PAD_DSE(7);
  94. } else { // OUTPUT_OPENDRAIN
  95. *(p->pad) = IOMUXC_PAD_DSE(7) | IOMUXC_PAD_ODE;
  96. }
  97. } else {
  98. *(p->reg + 1) &= ~(p->mask); // TODO: atomic
  99. if (mode == INPUT) {
  100. *(p->pad) = IOMUXC_PAD_DSE(7);
  101. } else if (mode == INPUT_PULLUP) {
  102. *(p->pad) = IOMUXC_PAD_DSE(7) | IOMUXC_PAD_PKE | IOMUXC_PAD_PUE | IOMUXC_PAD_PUS(3) | IOMUXC_PAD_HYS;
  103. } else if (mode == INPUT_PULLDOWN) {
  104. *(p->pad) = IOMUXC_PAD_DSE(7) | IOMUXC_PAD_PKE | IOMUXC_PAD_PUE | IOMUXC_PAD_PUS(0) | IOMUXC_PAD_HYS;
  105. } else { // INPUT_DISABLE
  106. *(p->pad) = IOMUXC_PAD_DSE(7) | IOMUXC_PAD_HYS;
  107. }
  108. }
  109. *(p->mux) = 5 | 0x10;
  110. }
  111. void _shiftOut(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder, uint8_t value)
  112. {
  113. if (bitOrder == LSBFIRST) {
  114. shiftOut_lsbFirst(dataPin, clockPin, value);
  115. } else {
  116. shiftOut_msbFirst(dataPin, clockPin, value);
  117. }
  118. }
  119. void shiftOut_lsbFirst(uint8_t dataPin, uint8_t clockPin, uint8_t value)
  120. {
  121. uint8_t mask;
  122. for (mask=0x01; mask; mask <<= 1) {
  123. digitalWrite(dataPin, value & mask);
  124. digitalWrite(clockPin, HIGH);
  125. digitalWrite(clockPin, LOW);
  126. }
  127. }
  128. void shiftOut_msbFirst(uint8_t dataPin, uint8_t clockPin, uint8_t value)
  129. {
  130. uint8_t mask;
  131. for (mask=0x80; mask; mask >>= 1) {
  132. digitalWrite(dataPin, value & mask);
  133. digitalWrite(clockPin, HIGH);
  134. digitalWrite(clockPin, LOW);
  135. }
  136. }
  137. uint8_t _shiftIn(uint8_t dataPin, uint8_t clockPin, uint8_t bitOrder)
  138. {
  139. if (bitOrder == LSBFIRST) {
  140. return shiftIn_lsbFirst(dataPin, clockPin);
  141. } else {
  142. return shiftIn_msbFirst(dataPin, clockPin);
  143. }
  144. }
  145. uint8_t shiftIn_lsbFirst(uint8_t dataPin, uint8_t clockPin)
  146. {
  147. uint8_t mask, value=0;
  148. for (mask=0x01; mask; mask <<= 1) {
  149. digitalWrite(clockPin, HIGH);
  150. if (digitalRead(dataPin)) value |= mask;
  151. digitalWrite(clockPin, LOW);
  152. }
  153. return value;
  154. }
  155. uint8_t shiftIn_msbFirst(uint8_t dataPin, uint8_t clockPin)
  156. {
  157. uint8_t mask, value=0;
  158. for (mask=0x80; mask; mask >>= 1) {
  159. digitalWrite(clockPin, HIGH);
  160. if (digitalRead(dataPin)) value |= mask;
  161. digitalWrite(clockPin, LOW);
  162. }
  163. return value;
  164. }
  165. //(*portInputRegister(pin) & digitalPinToBitMask(pin))
  166. uint32_t pulseIn_high(uint8_t pin, uint32_t timeout)
  167. {
  168. const struct digital_pin_bitband_and_config_table_struct *p;
  169. p = digital_pin_to_info_PGM + pin;
  170. uint32_t usec_start, usec_stop;
  171. // wait for any previous pulse to end
  172. usec_start = micros();
  173. while ((*(p->reg + 2) & p->mask)) {
  174. if (micros()-usec_start > timeout) return 0;
  175. }
  176. // wait for the pulse to start
  177. usec_start = micros();
  178. while (!(*(p->reg + 2) & p->mask)) {
  179. if (micros()-usec_start > timeout) return 0;
  180. }
  181. usec_start = micros();
  182. // wait for the pulse to stop
  183. while ((*(p->reg + 2) & p->mask)) {
  184. if (micros()-usec_start > timeout) return 0;
  185. }
  186. usec_stop = micros();
  187. return usec_stop - usec_start;
  188. }
  189. uint32_t pulseIn_low(uint8_t pin, uint32_t timeout)
  190. {
  191. const struct digital_pin_bitband_and_config_table_struct *p;
  192. p = digital_pin_to_info_PGM + pin;
  193. uint32_t usec_start, usec_stop;
  194. // wait for any previous pulse to end
  195. usec_start = micros();
  196. while (!(*(p->reg + 2) & p->mask)) {
  197. if (micros() - usec_start > timeout) return 0;
  198. }
  199. // wait for the pulse to start
  200. usec_start = micros();
  201. while ((*(p->reg + 2) & p->mask)) {
  202. if (micros() - usec_start > timeout) return 0;
  203. }
  204. usec_start = micros();
  205. // wait for the pulse to stop
  206. while (!(*(p->reg + 2) & p->mask)) {
  207. if (micros() - usec_start > timeout) return 0;
  208. }
  209. usec_stop = micros();
  210. return usec_stop - usec_start;
  211. }
  212. // TODO: an inline version should handle the common case where state is const
  213. uint32_t pulseIn(uint8_t pin, uint8_t state, uint32_t timeout)
  214. {
  215. if (pin >= CORE_NUM_DIGITAL) return 0;
  216. if (state) return pulseIn_high(pin, timeout);
  217. return pulseIn_low(pin, timeout);
  218. }