|
18 | 18 | */
|
19 | 19 | #pragma once
|
20 | 20 |
|
21 |
| -#if !(defined(NUM_DIGITAL_PINS) || defined(BOARD_NR_GPIO_PINS)) |
22 |
| - #error "M43 not supported for this board" |
| 21 | +#include <Arduino.h> |
| 22 | + |
| 23 | +#ifndef NUM_DIGITAL_PINS |
| 24 | + // Only in ST's Arduino core (STM32duino, STM32Core) |
| 25 | + #error "Expected NUM_DIGITAL_PINS not found" |
23 | 26 | #endif
|
24 | 27 |
|
25 |
| -// Strange - STM32F4 comes to HAL_STM32 rather than HAL_STM32F4 for these files |
26 |
| -#ifdef STM32F4 |
27 |
| - #ifdef NUM_DIGITAL_PINS // Only in ST's Arduino core (STM32duino, STM32Core) |
28 |
| - #include "pinsDebug_STM32duino.h" |
29 |
| - #elif defined(BOARD_NR_GPIO_PINS) // Only in STM32GENERIC (Maple) |
30 |
| - #include "pinsDebug_STM32GENERIC.h" |
| 28 | +/** |
| 29 | + * Life gets complicated if you want an easy to use 'M43 I' output (in port/pin order) |
| 30 | + * because the variants in this platform do not always define all the I/O port/pins |
| 31 | + * that a CPU has. |
| 32 | + * |
| 33 | + * VARIABLES: |
| 34 | + * Ard_num - Arduino pin number - defined by the platform. It is used by digitalRead and |
| 35 | + * digitalWrite commands and by M42. |
| 36 | + * - does not contain port/pin info |
| 37 | + * - is not in port/pin order |
| 38 | + * - typically a variant will only assign Ard_num to port/pins that are actually used |
| 39 | + * Index - M43 counter - only used to get Ard_num |
| 40 | + * x - a parameter/argument used to search the pin_array to try to find a signal name |
| 41 | + * associated with a Ard_num |
| 42 | + * Port_pin - port number and pin number for use with CPU registers and printing reports |
| 43 | + * |
| 44 | + * Since M43 uses digitalRead and digitalWrite commands, only the Port_pins with an Ard_num |
| 45 | + * are accessed and/or displayed. |
| 46 | + * |
| 47 | + * Three arrays are used. |
| 48 | + * |
| 49 | + * digitalPin[] is provided by the platform. It consists of the Port_pin numbers in |
| 50 | + * Arduino pin number order. |
| 51 | + * |
| 52 | + * pin_array is a structure generated by the pins/pinsDebug.h header file. It is generated by |
| 53 | + * the preprocessor. Only the signals associated with enabled options are in this table. |
| 54 | + * It contains: |
| 55 | + * - name of the signal |
| 56 | + * - the Ard_num assigned by the pins_YOUR_BOARD.h file using the platform defines. |
| 57 | + * EXAMPLE: "#define KILL_PIN PB1" results in Ard_num of 57. 57 is then used as the |
| 58 | + * argument to digitalPinToPinName(IO) to get the Port_pin number |
| 59 | + * - if it is a digital or analog signal. PWMs are considered digital here. |
| 60 | + * |
| 61 | + * pin_xref is a structure generated by this header file. It is generated by the |
| 62 | + * preprocessor. It is in port/pin order. It contains just the port/pin numbers defined by the |
| 63 | + * platform for this variant. |
| 64 | + * - Ard_num |
| 65 | + * - printable version of Port_pin |
| 66 | + * |
| 67 | + * Routines with an "x" as a parameter/argument are used to search the pin_array to try to |
| 68 | + * find a signal name associated with a port/pin. |
| 69 | + * |
| 70 | + * NOTE - the Arduino pin number is what is used by the M42 command, NOT the port/pin for that |
| 71 | + * signal. The Arduino pin number is listed by the M43 I command. |
| 72 | + */ |
| 73 | + |
| 74 | +//////////////////////////////////////////////////////// |
| 75 | +// |
| 76 | +// make a list of the Arduino pin numbers in the Port/Pin order |
| 77 | +// |
| 78 | + |
| 79 | +#define _PIN_ADD_2(NAME_ALPHA, ARDUINO_NUM) { {NAME_ALPHA}, ARDUINO_NUM }, |
| 80 | +#define _PIN_ADD(NAME_ALPHA, ARDUINO_NUM) { NAME_ALPHA, ARDUINO_NUM }, |
| 81 | +#define PIN_ADD(NAME) _PIN_ADD(#NAME, NAME) |
| 82 | + |
| 83 | +typedef struct { |
| 84 | + char Port_pin_alpha[5]; |
| 85 | + pin_t Ard_num; |
| 86 | +} XrefInfo; |
| 87 | + |
| 88 | +const XrefInfo pin_xref[] PROGMEM = { |
| 89 | + #include "pins_Xref.h" |
| 90 | +}; |
| 91 | + |
| 92 | +//////////////////////////////////////////////////////////// |
| 93 | + |
| 94 | +#define MODE_PIN_INPUT 0 // Input mode (reset state) |
| 95 | +#define MODE_PIN_OUTPUT 1 // General purpose output mode |
| 96 | +#define MODE_PIN_ALT 2 // Alternate function mode |
| 97 | +#define MODE_PIN_ANALOG 3 // Analog mode |
| 98 | + |
| 99 | +#define PIN_NUM(P) (P & 0x000F) |
| 100 | +#define PIN_NUM_ALPHA_LEFT(P) (((P & 0x000F) < 10) ? ('0' + (P & 0x000F)) : '1') |
| 101 | +#define PIN_NUM_ALPHA_RIGHT(P) (((P & 0x000F) > 9) ? ('0' + (P & 0x000F) - 10) : 0 ) |
| 102 | +#define PORT_NUM(P) ((P >> 4) & 0x0007) |
| 103 | +#define PORT_ALPHA(P) ('A' + (P >> 4)) |
| 104 | + |
| 105 | +/** |
| 106 | + * Translation of routines & variables used by pinsDebug.h |
| 107 | + */ |
| 108 | +#define NUMBER_PINS_TOTAL NUM_DIGITAL_PINS |
| 109 | +#define VALID_PIN(ANUM) ((ANUM) >= 0 && (ANUM) < NUMBER_PINS_TOTAL) |
| 110 | +#define digitalRead_mod(Ard_num) extDigitalRead(Ard_num) // must use Arduino pin numbers when doing reads |
| 111 | +#define PRINT_PIN(Q) |
| 112 | +#define PRINT_PORT(ANUM) port_print(ANUM) |
| 113 | +#define DIGITAL_PIN_TO_ANALOG_PIN(ANUM) -1 // will report analog pin number in the print port routine |
| 114 | +#define GET_PIN_MAP_PIN_M43(Index) pin_xref[Index].Ard_num |
| 115 | + |
| 116 | +// x is a variable used to search pin_array |
| 117 | +#define GET_ARRAY_IS_DIGITAL(x) ((bool) pin_array[x].is_digital) |
| 118 | +#define GET_ARRAY_PIN(x) ((pin_t) pin_array[x].pin) |
| 119 | +#define PRINT_ARRAY_NAME(x) do{ sprintf_P(buffer, PSTR("%-" STRINGIFY(MAX_NAME_LENGTH) "s"), pin_array[x].name); SERIAL_ECHO(buffer); }while(0) |
| 120 | +#define MULTI_NAME_PAD 33 // space needed to be pretty if not first name assigned to a pin |
| 121 | + |
| 122 | +#ifndef M43_NEVER_TOUCH |
| 123 | + #define _M43_NEVER_TOUCH(Index) (Index >= 9 && Index <= 12) // SERIAL/USB pins: PA9(TX) PA10(RX) PA11(USB_DM) PA12(USB_DP) |
| 124 | + #ifdef KILL_PIN |
| 125 | + #define M43_NEVER_TOUCH(Index) m43_never_touch(Index) |
| 126 | + |
| 127 | + bool m43_never_touch(const pin_t Index) { |
| 128 | + static pin_t M43_kill_index = -1; |
| 129 | + if (M43_kill_index < 0) |
| 130 | + for (M43_kill_index = 0; M43_kill_index < NUMBER_PINS_TOTAL; M43_kill_index++) |
| 131 | + if (KILL_PIN == GET_PIN_MAP_PIN_M43(M43_kill_index)) break; |
| 132 | + return _M43_NEVER_TOUCH(Index) || Index == M43_kill_index; // KILL_PIN and SERIAL/USB |
| 133 | + } |
31 | 134 | #else
|
32 |
| - #error "M43 not supported for this board" |
| 135 | + #define M43_NEVER_TOUCH(Index) _M43_NEVER_TOUCH(Index) |
33 | 136 | #endif
|
34 | 137 | #endif
|
| 138 | + |
| 139 | +uint8_t get_pin_mode(const pin_t Ard_num) { |
| 140 | + uint32_t mode_all = 0; |
| 141 | + const PinName dp = digitalPinToPinName(Ard_num); |
| 142 | + switch (PORT_ALPHA(dp)) { |
| 143 | + case 'A' : mode_all = GPIOA->MODER; break; |
| 144 | + case 'B' : mode_all = GPIOB->MODER; break; |
| 145 | + case 'C' : mode_all = GPIOC->MODER; break; |
| 146 | + case 'D' : mode_all = GPIOD->MODER; break; |
| 147 | + #ifdef PE_0 |
| 148 | + case 'E' : mode_all = GPIOE->MODER; break; |
| 149 | + #elif defined(PF_0) |
| 150 | + case 'F' : mode_all = GPIOF->MODER; break; |
| 151 | + #elif defined(PG_0) |
| 152 | + case 'G' : mode_all = GPIOG->MODER; break; |
| 153 | + #elif defined(PH_0) |
| 154 | + case 'H' : mode_all = GPIOH->MODER; break; |
| 155 | + #elif defined(PI_0) |
| 156 | + case 'I' : mode_all = GPIOI->MODER; break; |
| 157 | + #elif defined(PJ_0) |
| 158 | + case 'J' : mode_all = GPIOJ->MODER; break; |
| 159 | + #elif defined(PK_0) |
| 160 | + case 'K' : mode_all = GPIOK->MODER; break; |
| 161 | + #elif defined(PL_0) |
| 162 | + case 'L' : mode_all = GPIOL->MODER; break; |
| 163 | + #endif |
| 164 | + } |
| 165 | + return (mode_all >> (2 * uint8_t(PIN_NUM(dp)))) & 0x03; |
| 166 | +} |
| 167 | + |
| 168 | +bool GET_PINMODE(const pin_t Ard_num) { |
| 169 | + const uint8_t pin_mode = get_pin_mode(Ard_num); |
| 170 | + return pin_mode == MODE_PIN_OUTPUT || pin_mode == MODE_PIN_ALT; // assume all alt definitions are PWM |
| 171 | +} |
| 172 | + |
| 173 | +int8_t digital_pin_to_analog_pin(pin_t Ard_num) { |
| 174 | + Ard_num -= NUM_ANALOG_FIRST; |
| 175 | + return (Ard_num >= 0 && Ard_num < NUM_ANALOG_INPUTS) ? Ard_num : -1; |
| 176 | +} |
| 177 | + |
| 178 | +bool IS_ANALOG(const pin_t Ard_num) { |
| 179 | + return get_pin_mode(Ard_num) == MODE_PIN_ANALOG; |
| 180 | +} |
| 181 | + |
| 182 | +bool is_digital(const pin_t x) { |
| 183 | + const uint8_t pin_mode = get_pin_mode(pin_array[x].pin); |
| 184 | + return pin_mode == MODE_PIN_INPUT || pin_mode == MODE_PIN_OUTPUT; |
| 185 | +} |
| 186 | + |
| 187 | +void port_print(const pin_t Ard_num) { |
| 188 | + char buffer[16]; |
| 189 | + pin_t Index; |
| 190 | + for (Index = 0; Index < NUMBER_PINS_TOTAL; Index++) |
| 191 | + if (Ard_num == GET_PIN_MAP_PIN_M43(Index)) break; |
| 192 | + |
| 193 | + const char * ppa = pin_xref[Index].Port_pin_alpha; |
| 194 | + sprintf_P(buffer, PSTR("%s"), ppa); |
| 195 | + SERIAL_ECHO(buffer); |
| 196 | + if (ppa[3] == '\0') SERIAL_CHAR(' '); |
| 197 | + |
| 198 | + // print analog pin number |
| 199 | + const int8_t Port_pin = digital_pin_to_analog_pin(Ard_num); |
| 200 | + if (Port_pin >= 0) { |
| 201 | + sprintf_P(buffer, PSTR(" (A%d) "), Port_pin); |
| 202 | + SERIAL_ECHO(buffer); |
| 203 | + if (Port_pin < 10) SERIAL_CHAR(' '); |
| 204 | + } |
| 205 | + else |
| 206 | + SERIAL_ECHO_SP(7); |
| 207 | + |
| 208 | + // Print number to be used with M42 |
| 209 | + sprintf_P(buffer, PSTR(" M42 P%d "), Ard_num); |
| 210 | + SERIAL_ECHO(buffer); |
| 211 | + if (Ard_num < 10) SERIAL_CHAR(' '); |
| 212 | + if (Ard_num < 100) SERIAL_CHAR(' '); |
| 213 | +} |
| 214 | + |
| 215 | +bool pwm_status(const pin_t Ard_num) { |
| 216 | + return get_pin_mode(Ard_num) == MODE_PIN_ALT; |
| 217 | +} |
| 218 | + |
| 219 | +void pwm_details(const pin_t Ard_num) { |
| 220 | + if (pwm_status(Ard_num)) { |
| 221 | + uint32_t alt_all = 0; |
| 222 | + const PinName dp = digitalPinToPinName(Ard_num); |
| 223 | + pin_t pin_number = uint8_t(PIN_NUM(dp)); |
| 224 | + const bool over_7 = pin_number >= 8; |
| 225 | + const uint8_t ind = over_7 ? 1 : 0; |
| 226 | + switch (PORT_ALPHA(dp)) { // get alt function |
| 227 | + case 'A' : alt_all = GPIOA->AFR[ind]; break; |
| 228 | + case 'B' : alt_all = GPIOB->AFR[ind]; break; |
| 229 | + case 'C' : alt_all = GPIOC->AFR[ind]; break; |
| 230 | + case 'D' : alt_all = GPIOD->AFR[ind]; break; |
| 231 | + #ifdef PE_0 |
| 232 | + case 'E' : alt_all = GPIOE->AFR[ind]; break; |
| 233 | + #elif defined (PF_0) |
| 234 | + case 'F' : alt_all = GPIOF->AFR[ind]; break; |
| 235 | + #elif defined (PG_0) |
| 236 | + case 'G' : alt_all = GPIOG->AFR[ind]; break; |
| 237 | + #elif defined (PH_0) |
| 238 | + case 'H' : alt_all = GPIOH->AFR[ind]; break; |
| 239 | + #elif defined (PI_0) |
| 240 | + case 'I' : alt_all = GPIOI->AFR[ind]; break; |
| 241 | + #elif defined (PJ_0) |
| 242 | + case 'J' : alt_all = GPIOJ->AFR[ind]; break; |
| 243 | + #elif defined (PK_0) |
| 244 | + case 'K' : alt_all = GPIOK->AFR[ind]; break; |
| 245 | + #elif defined (PL_0) |
| 246 | + case 'L' : alt_all = GPIOL->AFR[ind]; break; |
| 247 | + #endif |
| 248 | + } |
| 249 | + if (over_7) pin_number -= 8; |
| 250 | + |
| 251 | + uint8_t alt_func = (alt_all >> (4 * pin_number)) & 0x0F; |
| 252 | + SERIAL_ECHOPAIR("Alt Function: ", alt_func); |
| 253 | + if (alt_func < 10) SERIAL_CHAR(' '); |
| 254 | + SERIAL_ECHOPGM(" - "); |
| 255 | + switch (alt_func) { |
| 256 | + case 0 : SERIAL_ECHOPGM("system (misc. I/O)"); break; |
| 257 | + case 1 : SERIAL_ECHOPGM("TIM1/TIM2 (probably PWM)"); break; |
| 258 | + case 2 : SERIAL_ECHOPGM("TIM3..5 (probably PWM)"); break; |
| 259 | + case 3 : SERIAL_ECHOPGM("TIM8..11 (probably PWM)"); break; |
| 260 | + case 4 : SERIAL_ECHOPGM("I2C1..3"); break; |
| 261 | + case 5 : SERIAL_ECHOPGM("SPI1/SPI2"); break; |
| 262 | + case 6 : SERIAL_ECHOPGM("SPI3"); break; |
| 263 | + case 7 : SERIAL_ECHOPGM("USART1..3"); break; |
| 264 | + case 8 : SERIAL_ECHOPGM("USART4..6"); break; |
| 265 | + case 9 : SERIAL_ECHOPGM("CAN1/CAN2, TIM12..14 (probably PWM)"); break; |
| 266 | + case 10 : SERIAL_ECHOPGM("OTG"); break; |
| 267 | + case 11 : SERIAL_ECHOPGM("ETH"); break; |
| 268 | + case 12 : SERIAL_ECHOPGM("FSMC, SDIO, OTG"); break; |
| 269 | + case 13 : SERIAL_ECHOPGM("DCMI"); break; |
| 270 | + case 14 : SERIAL_ECHOPGM("unused (shouldn't see this)"); break; |
| 271 | + case 15 : SERIAL_ECHOPGM("EVENTOUT"); break; |
| 272 | + } |
| 273 | + } |
| 274 | +} // pwm_details |
0 commit comments