grblHAL core  20250806
pin_bits_masks.h
Go to the documentation of this file.
1 /*
2  pin_bits_masks.h - for adding bit definitions and masks
3 
4  NOTE: This file is not used by the core, it may be used by drivers
5 
6  Part of grblHAL
7 
8  Copyright (c) 2021-2025 Terje Io
9 
10  grblHAL is free software: you can redistribute it and/or modify
11  it under the terms of the GNU General Public License as published by
12  the Free Software Foundation, either version 3 of the License, or
13  (at your option) any later version.
14 
15  grblHAL is distributed in the hope that it will be useful,
16  but WITHOUT ANY WARRANTY; without even the implied warranty of
17  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18  GNU General Public License for more details.
19 
20  You should have received a copy of the GNU General Public License
21  along with grblHAL. If not, see <http://www.gnu.org/licenses/>.
22 */
23 
24 #include "platform.h"
25 
26 // Sanity checks
27 
28 #if PROBE_ENABLE && !defined(PROBE_PIN)
29 #error "Probe input is not supported in this configuration!"
30 #endif
31 
32 #if SAFETY_DOOR_ENABLE && !defined(SAFETY_DOOR_PIN)
33 #error "Safety door input is not supported in this configuration!"
34 #endif
35 
36 #if MOTOR_FAULT_ENABLE && !defined(MOTOR_FAULT_PIN)
37 #error "Motor fault input is not supported in this configuration!"
38 #endif
39 
40 #if MOTOR_WARNING_ENABLE && !defined(MOTOR_WARNING_PIN)
41 #error "Motor warning input is not supported in this configuration!"
42 #endif
43 
44 #if I2C_STROBE_ENABLE && !defined(I2C_STROBE_PIN)
45 #error "I2C keypad/strobe is not supported in this configuration!"
46 #endif
47 
48 #if MPG_ENABLE == 1 && !defined(MPG_MODE_PIN)
49 #error "MPG mode input is not supported in this configuration!"
50 #endif
51 
52 #if QEI_SELECT_ENABLE && !defined(QEI_SELECT_PIN)
53 #error "Encoder select input is not supported in this configuration!"
54 #endif
55 
56 #define EXPANDER_PORT 1
57 
58 // Control input signals
59 
60 // Define the CONTROL_PORT symbol as a shorthand in the *_map.h file if all control inputs share the same port.
61 #ifdef CONTROL_PORT
62 
63 #ifndef RESET_PORT
64 #define RESET_PORT CONTROL_PORT
65 #endif
66 #ifndef FEED_HOLD_PORT
67 #define FEED_HOLD_PORT CONTROL_PORT
68 #endif
69 #ifndef CYCLE_START_PORT
70 #define CYCLE_START_PORT CONTROL_PORT
71 #endif
72 #ifndef ESTOP_PORT
73 #define ESTOP_PORT CONTROL_PORT
74 #endif
75 #ifndef PROBE_DISCONNECT_PORT
76 #define PROBE_DISCONNECT_PORT CONTROL_PORT
77 #endif
78 #ifndef STOP_DISABLE_PORT
79 #define STOP_DISABLE_PORT CONTROL_PORT
80 #endif
81 #ifndef BLOCK_DELETE_PORT
82 #define BLOCK_DELETE_PORT CONTROL_PORT
83 #endif
84 #ifndef SINGLE_BLOCK_PORT
85 #define SINGLE_BLOCK_PORT CONTROL_PORT
86 #endif
87 #ifndef MOTOR_FAULT_PORT
88 #define MOTOR_FAULT_PORT CONTROL_PORT
89 #endif
90 #ifndef MOTOR_WARNING_PORT
91 #define MOTOR_WARNING_PORT CONTROL_PORT
92 #endif
93 #ifndef LIMITS_OVERRIDE_PORT
94 #define LIMITS_OVERRIDE_PORT CONTROL_PORT
95 #endif
96 #if SAFETY_DOOR_ENABLE && !defined(SAFETY_DOOR_PORT)
97 #define SAFETY_DOOR_PORT CONTROL_PORT
98 #endif
99 
100 #endif // CONTROL_PORT
101 
102 #ifndef SD_DETECT_BIT
103 #ifdef SD_DETECT_PIN
104 #define SD_DETECT_BIT (1<<SD_DETECT_PIN)
105 #else
106 #define SD_DETECT_BIT 0
107 #endif
108 #endif
109 
110 #ifndef CONTROL_ENABLE
111 #define CONTROL_ENABLE 0
112 #endif
113 
114 static aux_ctrl_t aux_ctrl[] = {
115 // The following pins are bound explicitly to aux input pins.
116 #if (CONTROL_ENABLE & CONTROL_ESTOP) && defined(RESET_PIN)
117  #ifndef RESET_PORT
118  #define RESET_PORT 0
119  #endif
120  { .function = Input_EStop, .aux_port = IOPORT_UNASSIGNED, .irq_mode = IRQ_Mode_RisingFalling, .cap = { .e_stop = On }, .pin = RESET_PIN, .port = (void *)RESET_PORT },
121 #elif (CONTROL_ENABLE & CONTROL_RESET) && defined(RESET_PIN)
122  #ifndef RESET_PORT
123  #define RESET_PORT 0
124  #endif
125  { .function = Input_Reset, .aux_port = IOPORT_UNASSIGNED, .irq_mode = IRQ_Mode_RisingFalling, .cap = { .reset = On }, .pin = RESET_PIN, .port = (void *)RESET_PORT },
126 #endif
127 #if (CONTROL_ENABLE & CONTROL_FEED_HOLD) && defined(FEED_HOLD_PIN)
128  #ifndef FEED_HOLD_PORT
129  #define FEED_HOLD_PORT 0
130  #endif
131  { .function = Input_FeedHold, .aux_port = IOPORT_UNASSIGNED, .irq_mode = IRQ_Mode_RisingFalling, .cap = { .feed_hold = On }, .pin = FEED_HOLD_PIN, .port = (void *)FEED_HOLD_PORT },
132 #endif
133 #if (CONTROL_ENABLE & CONTROL_CYCLE_START) && defined(CYCLE_START_PIN)
134  #ifndef CYCLE_START_PORT
135  #define CYCLE_START_PORT 0
136  #endif
137  { .function = Input_CycleStart, .aux_port = IOPORT_UNASSIGNED, .irq_mode = IRQ_Mode_RisingFalling, .cap = { .cycle_start = On }, .pin = CYCLE_START_PIN, .port = (void *)CYCLE_START_PORT },
138 #endif
139 #if SAFETY_DOOR_ENABLE && defined(SAFETY_DOOR_PIN)
140  #ifndef SAFETY_DOOR_PORT
141  #define SAFETY_DOOR_PORT 0
142  #endif
143  { .function = Input_SafetyDoor, .aux_port = IOPORT_UNASSIGNED, .irq_mode = IRQ_Mode_RisingFalling, .cap = { .safety_door_ajar = On }, .pin = SAFETY_DOOR_PIN, .port = (void *)SAFETY_DOOR_PORT },
144 #endif
145 #if MOTOR_FAULT_ENABLE && defined(MOTOR_FAULT_PIN)
146  #ifndef MOTOR_FAULT_PORT
147  #define MOTOR_FAULT_PORT 0
148  #endif
149  { .function = Input_MotorFault, .aux_port = IOPORT_UNASSIGNED, .irq_mode = IRQ_Mode_RisingFalling, .cap = { .motor_fault = On }, .pin = MOTOR_FAULT_PIN, .port = (void *)MOTOR_FAULT_PORT },
150 #endif
151 #if MOTOR_WARNING_ENABLE && defined(MOTOR_WARNING_PIN)
152  #ifndef MOTOR_WARNING_PORT
153  #define MOTOR_WARNING_PORT 0
154  #endif
155  { .function = Input_MotorWarning, .aux_port = IOPORT_UNASSIGNED, .irq_mode = IRQ_Mode_RisingFalling, .cap = { .motor_fault = On }, .pin = MOTOR_WARNING_PIN, .port = (void *)MOTOR_WARNING_PORT },
156 #endif
157 
158 #if I2C_STROBE_ENABLE && defined(I2C_STROBE_PIN)
159  #ifndef I2C_STROBE_PORT
160  #define I2C_STROBE_PORT 0
161  #endif
162  { .function = Input_I2CStrobe, .aux_port = IOPORT_UNASSIGNED, .irq_mode = IRQ_Mode_Change, .cap = { .value = 0 }, .pin = I2C_STROBE_PIN, .port = (void *)I2C_STROBE_PORT },
163 #endif
164 #if MPG_ENABLE == 1 && defined(MPG_MODE_PIN)
165  #ifndef MPG_MODE_PORT
166  #define MPG_MODE_PORT 0
167  #endif
168  { .function = Input_MPGSelect, .aux_port = IOPORT_UNASSIGNED, .irq_mode = IRQ_Mode_Change, .cap = { .value = 0 }, .pin = MPG_MODE_PIN, .port = (void *)MPG_MODE_PORT },
169 #endif
170 #if QEI_SELECT_ENABLE && defined(QEI_SELECT_PIN)
171  #ifndef QEI_SELECT_PORT
172  #define QEI_SELECT_PORT 0
173  #endif
174  { .function = Input_QEI_Select, .aux_port = IOPORT_UNASSIGNED, .irq_mode = IRQ_Mode_RisingFalling, .cap = { .value = 0 }, .pin = QEI_SELECT_PIN, .port = (void *)QEI_SELECT_PORT },
175 #endif
176 
177 // Probe pins can be bound explicitly and can be "degraded" to not interrupt capable.
178 #if PROBE_ENABLE && defined(PROBE_PIN)
179  #ifndef PROBE_PORT
180  #define PROBE_PORT 0
181  #endif
182  { .function = Input_Probe, .aux_port = IOPORT_UNASSIGNED, .irq_mode = IRQ_Mode_RisingFalling, .cap = { .value = 0 }, .pin = PROBE_PIN, .port = (void *)PROBE_PORT },
183 #endif
184 #if PROBE2_ENABLE && defined(PROBE2_PIN)
185  #ifndef PROBE2_PORT
186  #define PROBE2_PORT 0
187  #endif
188  { .function = Input_Probe2, .aux_port = IOPORT_UNASSIGNED, .irq_mode = IRQ_Mode_RisingFalling, .cap = { .value = 0 }, .pin = PROBE2_PIN, .port = (void *)PROBE2_PORT },
189 #endif
190 #if TOOLSETTER_ENABLE && defined(TOOLSETTER_PIN)
191  #ifndef TOOLSETTER_PORT
192  #define TOOLSETTER_PORT 0
193  #endif
194  { .function = Input_Toolsetter, .aux_port = IOPORT_UNASSIGNED, .irq_mode = IRQ_Mode_RisingFalling, .cap = { .value = 0 }, .pin = TOOLSETTER_PIN, .port = (void *)TOOLSETTER_PORT },
195 #endif
196 
197 // The following pins are allocated from remaining aux inputs pool
198 #if TOOLSETTER_ENABLE && !defined(TOOLSETTER_PIN)
199  { .function = Input_Toolsetter, .aux_port = IOPORT_UNASSIGNED, .irq_mode = IRQ_Mode_RisingFalling, .cap = { .value = 0 }, .pin = 0xFE, .port = NULL },
200 #endif
201 #if PROBE2_ENABLE && !defined(PROBE2_PIN)
202  { .function = Input_Probe2, .aux_port = IOPORT_UNASSIGNED, .irq_mode = IRQ_Mode_RisingFalling, .cap = { .value = 0 }, .pin = 0xFE, .port = NULL },
203 #endif
204 #if LIMITS_OVERRIDE_ENABLE
205  { .function = Input_LimitsOverride, .aux_port = IOPORT_UNASSIGNED, .irq_mode = IRQ_Mode_None, .cap = { .limits_override = On }, .pin = 0xFF, .port = NULL },
206 #endif
207 #if STOP_DISABLE_ENABLE
208  { .function = Input_StopDisable, .aux_port = IOPORT_UNASSIGNED, .irq_mode = IRQ_Mode_Change, .cap = { .stop_disable = On }, .pin = 0xFF, .port = NULL },
209 #endif
210 #if BLOCK_DELETE_ENABLE
211  { .function = Input_BlockDelete, .aux_port = IOPORT_UNASSIGNED, .irq_mode = IRQ_Mode_Change, .cap = { .block_delete = On }, .pin = 0xFF, .port = NULL },
212 #endif
213 #if SINGLE_BLOCK_ENABLE
214  { .function = Input_SingleBlock, .aux_port = IOPORT_UNASSIGNED, .irq_mode = IRQ_Mode_Change, .cap = { .single_block = On }, .pin = 0xFF, .port = NULL },
215 #endif
216 #if PROBE_DISCONNECT_ENABLE
217  { .function = Input_ProbeDisconnect, .aux_port = IOPORT_UNASSIGNED, .irq_mode = IRQ_Mode_RisingFalling, .cap = { .probe_disconnected = On }, .pin = 0xFF, .port = NULL },
218 #endif
219 };
220 
221 static inline bool aux_ctrl_is_probe (pin_function_t function)
222 {
223  return function == Input_Probe || function == Input_Probe2 || function == Input_Toolsetter;
224 }
225 
226 #ifdef STM32_PLATFORM
227 
228 static inline aux_ctrl_t *aux_ctrl_get_fn (void *port, uint8_t pin)
229 {
230  aux_ctrl_t *ctrl_pin = NULL;
231 
232  if(sizeof(aux_ctrl) / sizeof(aux_ctrl_t)) {
233  uint_fast8_t idx;
234  for(idx = 0; ctrl_pin == NULL && aux_ctrl[idx].pin != 0xFF && idx < sizeof(aux_ctrl) / sizeof(aux_ctrl_t); idx++) {
235  if(aux_ctrl[idx].pin == pin && aux_ctrl[idx].port == port)
236  ctrl_pin = &aux_ctrl[idx];
237  }
238  }
239 
240  return ctrl_pin;
241 }
242 
243 #endif
244 
245 static inline aux_ctrl_t *aux_ctrl_remap_explicit (void *port, uint8_t pin, uint8_t aux_port, void *input)
246 {
247  aux_ctrl_t *ctrl_pin = NULL;
248 
249  if(sizeof(aux_ctrl) / sizeof(aux_ctrl_t)) {
250 
251  uint_fast8_t idx;
252 
253  for(idx = 0; ctrl_pin == NULL && idx < sizeof(aux_ctrl) / sizeof(aux_ctrl_t) && aux_ctrl[idx].pin != 0xFF; idx++) {
254  if(aux_ctrl[idx].pin == pin && aux_ctrl[idx].port == port) {
255  ctrl_pin = &aux_ctrl[idx];
256  ctrl_pin->aux_port = aux_port;
257  ctrl_pin->input = input;
258  break;
259  }
260  }
261  }
262 
263  return ctrl_pin;
264 }
265 
266 static inline aux_ctrl_t *aux_ctrl_get_pin (uint8_t aux_port)
267 {
268  aux_ctrl_t *ctrl_pin = NULL;
269 
270  uint_fast8_t idx = sizeof(aux_ctrl) / sizeof(aux_ctrl_t);
271 
272  if(idx) do {
273  if(aux_ctrl[--idx].aux_port == aux_port)
274  ctrl_pin = &aux_ctrl[idx];
275  } while(idx && ctrl_pin == NULL);
276 
277  return ctrl_pin;
278 }
279 
280 static inline void aux_ctrl_irq_enable (settings_t *settings, ioport_interrupt_callback_ptr aux_irq_handler)
281 {
282  uint_fast8_t idx = sizeof(aux_ctrl) / sizeof(aux_ctrl_t);
283 
284  if(idx) do {
285  if(aux_ctrl[--idx].aux_port != 0xFF && aux_ctrl[idx].irq_mode != IRQ_Mode_None) {
286  if(!aux_ctrl_is_probe(aux_ctrl[idx].function)) {
287  pin_irq_mode_t irq_mode;
288  if((irq_mode = aux_ctrl[idx].irq_mode) & IRQ_Mode_RisingFalling)
289  irq_mode = (settings->control_invert.mask & aux_ctrl[idx].cap.mask) ? IRQ_Mode_Falling : IRQ_Mode_Rising;
290  hal.port.register_interrupt_handler(aux_ctrl[idx].aux_port, irq_mode, aux_irq_handler);
291  }
292  }
293  } while(idx);
294 }
295 
296 typedef bool (*aux_claim_explicit_ptr)(aux_ctrl_t *aux_ctrl);
297 
298 static bool aux_ctrl_claim_port (xbar_t *properties, uint8_t port, void *data)
299 {
300  if(ioport_claim(Port_Digital, Port_Input, &port, NULL)) {
301  ((aux_ctrl_t *)data)->aux_port = port;
302  ioport_set_function(properties, ((aux_ctrl_t *)data)->function, &((aux_ctrl_t *)data)->cap);
303  }
304 
305  return ((aux_ctrl_t *)data)->aux_port != IOPORT_UNASSIGNED;
306 }
307 
308 static bool aux_ctrl_find_port (xbar_t *properties, uint8_t port, void *data)
309 {
310  ((aux_ctrl_t *)data)->aux_port = port;
311 
312  return true;
313 }
314 
315 static inline void aux_ctrl_claim_ports (aux_claim_explicit_ptr aux_claim_explicit, ioports_enumerate_callback_ptr aux_claim)
316 {
317  uint_fast8_t idx;
318 
319  if(aux_claim == NULL)
320  aux_claim = aux_ctrl_claim_port;
321 
322  for(idx = 0; idx < sizeof(aux_ctrl) / sizeof(aux_ctrl_t); idx++) {
323 
324  pin_cap_t cap = { .irq_mode = aux_ctrl[idx].irq_mode, .claimable = On };
325 
326  if(aux_ctrl[idx].pin == 0xFE) // Toolsetter and Probe2
327  ioports_enumerate(Port_Digital, Port_Input, cap, aux_ctrl_find_port, (void *)&aux_ctrl[idx]);
328 #ifdef STM32_PLATFORM
329  if(aux_ctrl[idx].irq_mode == IRQ_Mode_None && !(aux_ctrl[idx].function == Input_Probe || aux_ctrl[idx].function == Input_LimitsOverride))
330  continue;
331 #endif
332  if(aux_ctrl[idx].pin == 0xFF) {
333  if(ioports_enumerate(Port_Digital, Port_Input, cap, aux_claim, (void *)&aux_ctrl[idx]))
334  hal.signals_cap.mask |= aux_ctrl[idx].cap.mask;
335  } else if(aux_ctrl[idx].aux_port != IOPORT_UNASSIGNED)
336  aux_claim_explicit(&aux_ctrl[idx]);
337  }
338 }
339 
340 static inline control_signals_t aux_ctrl_scan_status (control_signals_t signals)
341 {
342 #if PROBE_DISCONNECT_ENABLE || STOP_DISABLE_ENABLE || BLOCK_DELETE_ENABLE || SINGLE_BLOCK_ENABLE || LIMITS_OVERRIDE_ENABLE
343 
344  uint_fast8_t idx = sizeof(aux_ctrl) / sizeof(aux_ctrl_t);
345 
346  if(idx) do {
347  if(aux_ctrl[--idx].pin != 0xFF)
348  break;
349  if(aux_ctrl[idx].aux_port != IOPORT_UNASSIGNED) {
350  signals.mask &= ~aux_ctrl[idx].cap.mask;
351  #ifdef GRBL_ESP32 // Snowflake guru workaround
352  if(hal.port.wait_on_input(Port_Digital, aux_ctrl[idx].aux_port, WaitMode_Immediate, FZERO) == 1)
353  signals.mask |= aux_ctrl[idx].cap.mask;
354  #else
355  if(hal.port.wait_on_input(Port_Digital, aux_ctrl[idx].aux_port, WaitMode_Immediate, 0.0f) == 1)
356  signals.mask |= aux_ctrl[idx].cap.mask;
357  #endif
358  }
359  } while(idx);
360 
361 #endif
362 
363  return signals;
364 }
365 
366 // The following pins are bound explicitly to aux output pins
367 static aux_ctrl_out_t aux_ctrl_out[] = {
368 #if defined(ESP_PLATFORM) || defined(RP2040) // for now
369 #if defined(STEPPERS_ENABLE_PIN) && STEPPERS_ENABLE_PORT == EXPANDER_PORT
370  { .function = Output_StepperEnable, .aux_port = IOPORT_UNASSIGNED, .pin = STEPPERS_ENABLE_PIN, .port = (void *)STEPPERS_ENABLE_PORT },
371 #endif
372 #if defined(X_ENABLE_PIN) && X_ENABLE_PORT == EXPANDER_PORT
373  { .function = Output_StepperEnableX, .aux_port = IOPORT_UNASSIGNED, .pin = X_ENABLE_PIN, .port = (void *)X_ENABLE_PORT },
374 #endif
375 #if defined(X2_ENABLE_PIN) && X2_ENABLE_PORT == EXPANDER_PORT
376  { .function = Output_StepperEnableX2, .aux_port = IOPORT_UNASSIGNED, .pin = X2_ENABLE_PIN, .port = (void *)X2_ENABLE_PORT },
377 #endif
378 #if defined(Y_ENABLE_PIN) && Y_ENABLE_PORT == EXPANDER_PORT
379  { .function = Output_StepperEnableY, .aux_port = IOPORT_UNASSIGNED, .pin = Y_ENABLE_PIN, .port = (void *)Y_ENABLE_PORT },
380 #endif
381 #if defined(Y2_ENABLE_PIN) && Y2_ENABLE_PORT == EXPANDER_PORT
382  { .function = Output_StepperEnableY2, .aux_port = IOPORT_UNASSIGNED, .pin = Y2_ENABLE_PIN, .port = (void *)Y2_ENABLE_PORT },
383 #endif
384 #if defined(XY_ENABLE_PIN) && XY_ENABLE_PORT == EXPANDER_PORT
385  { .function = Output_StepperEnableXY, .aux_port = IOPORT_UNASSIGNED, .pin = XY_ENABLE_PIN, .port = (void *)XY_ENABLE_PORT },
386 #endif
387 #if defined(Z_ENABLE_PIN) && Z_ENABLE_PORT == EXPANDER_PORT
388  { .function = Output_StepperEnableZ, .aux_port = IOPORT_UNASSIGNED, .pin = Z_ENABLE_PIN, .port = (void *)Z_ENABLE_PORT },
389 #endif
390 #if defined(Z2_ENABLE_PIN) && Z2_ENABLE_PORT == EXPANDER_PORT
391  { .function = Output_StepperEnableZ2, .aux_port = IOPORT_UNASSIGNED, .pin = Z2_ENABLE_PIN, .port = (void *)Z2_ENABLE_PORT },
392 #endif
393 #if defined(A_ENABLE_PIN) && A_ENABLE_PORT == EXPANDER_PORT
394  { .function = Output_StepperEnableA, .aux_port = IOPORT_UNASSIGNED, .pin = A_ENABLE_PIN, .port = (void *)A_ENABLE_PORT },
395 #endif
396 #if defined(B_ENABLE_PIN) && B_ENABLE_PORT == EXPANDER_PORT
397  { .function = Output_StepperEnableB, .aux_port = IOPORT_UNASSIGNED, .pin = B_ENABLE_PIN, .port = (void *)B_ENABLE_PORT },
398 #endif
399 #if defined(C_ENABLE_PIN) && C_ENABLE_PORT == EXPANDER_PORT
400  { .function = Output_StepperEnableC, .aux_port = IOPORT_UNASSIGNED, .pin = C_ENABLE_PIN, .port = (void *)C_ENABLE_PORT },
401 #endif
402 #if defined(U_ENABLE_PIN) && U_ENABLE_PORT == EXPANDER_PORT
403  { .function = Output_StepperEnableU, .aux_port = IOPORT_UNASSIGNED, .pin = U_ENABLE_PIN, .port = (void *)U_ENABLE_PORT },
404 #endif
405 #if defined(V_ENABLE_PIN) && AV_ENABLE_PORT == EXPANDER_PORT
406  { .function = Output_StepperEnableV, .aux_port = IOPORT_UNASSIGNED, .pin = V_ENABLE_PIN, .port = (void *)V_ENABLE_PORT },
407 #endif
408 #endif //
409 #ifdef SPINDLE_ENABLE_PIN
410  #ifndef SPINDLE_ENABLE_PORT
411  #define SPINDLE_ENABLE_PORT 0
412  #endif
413  { .function = Output_SpindleOn, .aux_port = IOPORT_UNASSIGNED, .pin = SPINDLE_ENABLE_PIN, .port = (void *)SPINDLE_ENABLE_PORT },
414 #endif
415 #ifdef SPINDLE_PWM_PIN
416  #ifndef SPINDLE_PWM_PORT
417  #define SPINDLE_PWM_PORT 0
418  #endif
419  { .function = Output_SpindlePWM, .aux_port = IOPORT_UNASSIGNED, .pin = SPINDLE_PWM_PIN, .port = (void *)SPINDLE_PWM_PORT },
420 #endif
421 #ifdef SPINDLE_DIRECTION_PIN
422  #ifndef SPINDLE_DIRECTION_PORT
423  #define SPINDLE_DIRECTION_PORT 0
424  #endif
425  { .function = Output_SpindleDir, .aux_port = IOPORT_UNASSIGNED, .pin = SPINDLE_DIRECTION_PIN, .port = (void *)SPINDLE_DIRECTION_PORT },
426 #endif
427 
428 #ifdef SPINDLE1_ENABLE_PIN
429  #ifndef SPINDLE1_ENABLE_PORT
430  #define SPINDLE1_ENABLE_PORT 0
431  #endif
432  { .function = Output_Spindle1On, .aux_port = IOPORT_UNASSIGNED, .pin = SPINDLE1_ENABLE_PIN, .port = (void *)SPINDLE1_ENABLE_PORT },
433 #endif
434 #ifdef SPINDLE1_PWM_PIN
435  #ifndef SPINDLE1_PWM_PORT
436  #define SPINDLE1_PWM_PORT 0
437  #endif
438  { .function = Output_Spindle1PWM, .aux_port = IOPORT_UNASSIGNED, .pin = SPINDLE1_PWM_PIN, .port = (void *)SPINDLE1_PWM_PORT },
439 #endif
440 #ifdef SPINDLE1_DIRECTION_PIN
441  #ifndef SPINDLE1_DIRECTION_PORT
442  #define SPINDLE1_DIRECTION_PORT 0
443  #endif
444  { .function = Output_Spindle1Dir, .aux_port = IOPORT_UNASSIGNED, .pin = SPINDLE1_DIRECTION_PIN, .port = (void *)SPINDLE1_DIRECTION_PORT },
445 #endif
446 
447 #ifdef COOLANT_FLOOD_PIN
448  #ifndef COOLANT_FLOOD_PORT
449  #define COOLANT_FLOOD_PORT 0
450  #endif
451  { .function = Output_CoolantFlood, .aux_port = IOPORT_UNASSIGNED, .pin = COOLANT_FLOOD_PIN, .port = (void *)COOLANT_FLOOD_PORT },
452 #endif
453 #ifdef COOLANT_MIST_PIN
454  #ifndef COOLANT_MIST_PORT
455  #define COOLANT_MIST_PORT 0
456  #endif
457  { .function = Output_CoolantMist, .aux_port = IOPORT_UNASSIGNED, .pin = COOLANT_MIST_PIN, .port = (void *)COOLANT_MIST_PORT },
458 #endif
459 
460 #ifdef COPROC_RESET_PIN
461  #ifndef COPROC_RESET_PORT
462  #define COPROC_RESET_PORT 0
463  #endif
464  { .function = Output_CoProc_Reset, .aux_port = IOPORT_UNASSIGNED, .pin = COPROC_RESET_PIN, .port = (void *)COPROC_RESET_PORT },
465 #endif
466 #ifdef COPROC_BOOT0_PIN
467  #ifndef COPROC_BOOT0_PORT
468  #define COPROC_BOOT0_PORT 0
469  #endif
470  { .function = Output_CoProc_Boot0, .aux_port = IOPORT_UNASSIGNED, .pin = COPROC_BOOT0_PIN, .port = (void *)COPROC_BOOT0_PORT },
471 #endif
472 #if defined(SPI_RST_PIN) && defined(RP2040)
473  #if SPI_RST_PORT == EXPANDER_PORT
474  { .function = Output_SPIRST, .aux_port = IOPORT_UNASSIGNED, .pin = SPI_RST_PIN, .port = (void *)SPI_RST_PORT },
475  #endif
476 #endif
477 };
478 
479 static inline aux_ctrl_out_t *aux_out_remap_explicit (void *port, uint8_t pin, uint8_t aux_port, void *output)
480 {
481  aux_ctrl_out_t *ctrl_pin = NULL;
482 
483  uint_fast8_t idx = sizeof(aux_ctrl_out) / sizeof(aux_ctrl_out_t);
484 
485  if(idx) do {
486  idx--;
487  if(aux_ctrl_out[idx].port == port && aux_ctrl_out[idx].pin == pin) {
488  ctrl_pin = &aux_ctrl_out[idx];
489  ctrl_pin->aux_port = aux_port;
490  ctrl_pin->output = output;
491  }
492  } while(idx && ctrl_pin == NULL);
493 
494  return ctrl_pin;
495 }
496 
497 typedef bool (*aux_claim_explicit_out_ptr)(aux_ctrl_out_t *aux_ctrl);
498 
499 static bool aux_ctrl_claim_out_port (xbar_t *properties, uint8_t port, void *data)
500 {
501  if(((aux_ctrl_out_t *)data)->port == (void *)EXPANDER_PORT) {
502  if(((aux_ctrl_out_t *)data)->pin == properties->pin && properties->set_value)
503  ((aux_ctrl_out_t *)data)->aux_port = port;
504  } else if(ioport_claim(Port_Digital, Port_Output, &port, xbar_fn_to_pinname(((aux_ctrl_out_t *)data)->function)))
505  ((aux_ctrl_out_t *)data)->aux_port = port;
506 
507  return ((aux_ctrl_out_t *)data)->aux_port != 0xFF;
508 }
509 
510 static inline void aux_ctrl_claim_out_ports (aux_claim_explicit_out_ptr aux_claim_explicit, ioports_enumerate_callback_ptr aux_claim)
511 {
512  uint_fast8_t idx;
513 
514  if(aux_claim == NULL)
515  aux_claim = aux_ctrl_claim_out_port;
516 
517  for(idx = 0; idx < sizeof(aux_ctrl_out) / sizeof(aux_ctrl_out_t); idx++) {
518  if(aux_ctrl_out[idx].port == (void *)EXPANDER_PORT) {
519  if(ioports_enumerate(Port_Digital, Port_Output, (pin_cap_t){ .external = On, .claimable = On }, aux_claim, &aux_ctrl_out[idx])) {
520  if((aux_ctrl_out[idx].output = ioport_claim(Port_Digital, Port_Output, &aux_ctrl_out[idx].aux_port, NULL /*xbar_fn_to_pinname(aux_ctrl_out[idx].function)*/))) {
521  ioport_set_function((xbar_t *)aux_ctrl_out[idx].output, aux_ctrl_out[idx].function, NULL);
522  // TODO: else set description?
523  aux_claim_explicit(&aux_ctrl_out[idx]);
524  }
525  }
526  } else if(aux_ctrl_out[idx].pin == 0xFF) {
527  if(ioports_enumerate(Port_Digital, Port_Output, (pin_cap_t){ .claimable = On }, aux_claim, &aux_ctrl_out[idx]))
528  aux_claim_explicit(&aux_ctrl_out[idx]);
529  } else if(aux_ctrl_out[idx].aux_port != 0xFF)
530  aux_claim_explicit(&aux_ctrl_out[idx]);
531  }
532 }
533 
534 // Output Signals
535 
536 #if defined(SPINDLE_ENABLE_PIN) && !defined(SPINDLE_ENABLE_BIT)
537 #define SPINDLE_ENABLE_BIT (1<<SPINDLE_ENABLE_PIN)
538 #endif
539 #if defined(SPINDLE_DIRECTION_PIN) && !defined(SPINDLE_DIRECTION_BIT)
540 #define SPINDLE_DIRECTION_BIT (1<<SPINDLE_DIRECTION_PIN)
541 #endif
542 
543 #if defined(SPINDLE1_ENABLE_PIN) && !defined(SPINDLE1_ENABLE_BIT)
544 #define SPINDLE1_ENABLE_BIT (1<<SPINDLE1_ENABLE_PIN)
545 #endif
546 #if defined(SPINDLE1_DIRECTION_PIN) && !defined(SPINDLE1_DIRECTION_BIT)
547 #define SPINDLE1_DIRECTION_BIT (1<<SPINDLE1_DIRECTION_PIN)
548 #endif
549 
550 #if defined(COOLANT_FLOOD_PIN) && !defined(COOLANT_FLOOD_BIT)
551 #define COOLANT_FLOOD_BIT (1<<COOLANT_FLOOD_PIN)
552 #endif
553 #if defined(COOLANT_MIST_PIN) && !defined(COOLANT_MIST_BIT)
554 #define COOLANT_MIST_BIT (1<<COOLANT_MIST_PIN)
555 #endif
556 
557 #if defined(RTS_PIN) && !defined(RTS_BIT)
558 #define RTS_BIT (1<<RTS_PIN)
559 #endif
560 
561 // IRQ enabled input singnals
562 
563 #if QEI_ENABLE
564 #ifndef QEI_A_BIT
565 #define QEI_A_BIT (1<<QEI_A_PIN)
566 #endif
567 #ifndef QEI_B_BIT
568 #define QEI_B_BIT (1<<QEI_B_PIN)
569 #endif
570 #else
571 #define QEI_A_BIT 0
572 #define QEI_B_BIT 0
573 #endif
574 
575 #ifndef QEI_SELECT_BIT
576 #define QEI_SELECT_BIT 0
577 #endif
578 #ifndef MPG_MODE_BIT
579 #define MPG_MODE_BIT 0
580 #endif
581 #ifndef I2C_STROBE_BIT
582 #define I2C_STROBE_BIT 0
583 #endif
584 
585 // Do NOT #define PROBE_BIT 0 here!
586 
587 #if SPINDLE_ENCODER_ENABLE
588 #ifndef SPINDLE_PULSE_PIN
589 #error "Spindle encoder requires at least SPINDLE_PULSE_PIN defined in the board map!"
590 #endif
591 #if !defined(SPINDLE_PULSE_BIT) && defined(SPINDLE_PULSE_PIN)
592 #define SPINDLE_PULSE_BIT (1<<SPINDLE_PULSE_PIN)
593 #endif
594 #if !defined(SPINDLE_INDEX_BIT) && defined(SPINDLE_INDEX_PIN)
595 #define SPINDLE_INDEX_BIT (1<<SPINDLE_INDEX_PIN)
596 #endif
597 #endif
598 
599 #ifndef SPINDLE_INDEX_BIT
600 #define SPINDLE_INDEX_BIT 0
601 #endif
602 #ifndef SPINDLE_PULSE_BIT
603 #define SPINDLE_PULSE_BIT 0
604 #endif
605 
606 #if SPINDLE_ENCODER_ENABLE && (SPINDLE_INDEX_BIT + SPINDLE_PULSE_BIT) == 0
607 #error "Spindle encoder requires SPINDLE_PULSE_PIN and SPINDLE_INDEX_PIN defined in the board map!"
608 #endif
609 
610 #ifndef SPI_IRQ_PIN
611 #define SPI_IRQ_BIT 0
612 #elif !defined(SPI_IRQ_BIT)
613 #define SPI_IRQ_BIT (1<<SPI_IRQ_PIN)
614 #endif
615 
616 #ifndef DEVICES_IRQ_MASK
617 #define DEVICES_IRQ_MASK (SPI_IRQ_BIT|SPINDLE_INDEX_BIT|QEI_A_BIT|QEI_B_BIT|SD_DETECT_BIT)
618 #define DEVICES_IRQ_MASK_SUM (SPI_IRQ_BIT+SPINDLE_INDEX_BIT+QEI_A_BIT+QEI_B_BIT+SD_DETECT_BIT)
619 #endif
620 
621 // Auxillary input signals
622 
623 #ifdef AUXINPUT0_PIN
624 #define AUXINPUT0_BIT (1<<AUXINPUT0_PIN)
625 #else
626 #define AUXINPUT0_BIT 0
627 #endif
628 #ifdef AUXINPUT1_PIN
629 #define AUXINPUT1_BIT (1<<AUXINPUT1_PIN)
630 #else
631 #define AUXINPUT1_BIT 0
632 #endif
633 #ifdef AUXINPUT2_PIN
634 #define AUXINPUT2_BIT (1<<AUXINPUT2_PIN)
635 #else
636 #define AUXINPUT2_BIT 0
637 #endif
638 #ifdef AUXINPUT3_PIN
639 #define AUXINPUT3_BIT (1<<AUXINPUT3_PIN)
640 #else
641 #define AUXINPUT3_BIT 0
642 #endif
643 #ifdef AUXINPUT4_PIN
644 #define AUXINPUT4_BIT (1<<AUXINPUT4_PIN)
645 #else
646 #define AUXINPUT4_BIT 0
647 #endif
648 #ifdef AUXINPUT5_PIN
649 #define AUXINPUT5_BIT (1<<AUXINPUT5_PIN)
650 #else
651 #define AUXINPUT5_BIT 0
652 #endif
653 #ifdef AUXINPUT6_PIN
654 #define AUXINPUT6_BIT (1<<AUXINPUT6_PIN)
655 #else
656 #define AUXINPUT6_BIT 0
657 #endif
658 #ifdef AUXINPUT7_PIN
659 #define AUXINPUT7_BIT (1<<AUXINPUT7_PIN)
660 #else
661 #define AUXINPUT7_BIT 0
662 #endif
663 #ifdef AUXINPUT8_PIN
664 #define AUXINPUT8_BIT (1<<AUXINPUT8_PIN)
665 #else
666 #define AUXINPUT8_BIT 0
667 #endif
668 #ifdef AUXINPUT9_PIN
669 #define AUXINPUT9_BIT (1<<AUXINPUT9_PIN)
670 #else
671 #define AUXINPUT9_BIT 0
672 #endif
673 #ifdef AUXINPUT10_PIN
674 #define AUXINPUT10_BIT (1<<AUXINPUT10_PIN)
675 #else
676 #define AUXINPUT10_BIT 0
677 #endif
678 #ifdef AUXINPUT11_PIN
679 #define AUXINPUT11_BIT (1<<AUXINPUT11_PIN)
680 #else
681 #define AUXINPUT11_BIT 0
682 #endif
683 #ifdef AUXINPUT12_PIN
684 #define AUXINPUT12_BIT (1<<AUXINPUT12_PIN)
685 #else
686 #define AUXINPUT12_BIT 0
687 #endif
688 #ifdef AUXINPUT13_PIN
689 #define AUXINPUT13_BIT (1<<AUXINPUT13_PIN)
690 #else
691 #define AUXINPUT13_BIT 0
692 #endif
693 #ifdef AUXINPUT14_PIN
694 #define AUXINPUT14_BIT (1<<AUXINPUT14_PIN)
695 #else
696 #define AUXINPUT14_BIT 0
697 #endif
698 #ifdef AUXINPUT15_PIN
699 #define AUXINPUT15_BIT (1<<AUXINPUT15_PIN)
700 #else
701 #define AUXINPUT15_BIT 0
702 #endif
703 
704 #ifndef AUXINPUT_MASK
705 #define AUXINPUT_MASK (AUXINPUT0_BIT|AUXINPUT1_BIT|AUXINPUT2_BIT|AUXINPUT3_BIT|AUXINPUT4_BIT|AUXINPUT5_BIT|AUXINPUT6_BIT|AUXINPUT7_BIT|\
706  AUXINPUT8_BIT|AUXINPUT9_BIT|AUXINPUT10_BIT|AUXINPUT11_BIT|AUXINPUT12_BIT|AUXINPUT13_BIT|AUXINPUT4_BIT|AUXINPUT15_BIT)
707 #define AUXINPUT_MASK_SUM (AUXINPUT0_BIT+AUXINPUT1_BIT+AUXINPUT2_BIT+AUXINPUT3_BIT+AUXINPUT4_BIT+AUXINPUT5_BIT+AUXINPUT6_BIT+AUXINPUT7_BIT+\
708  AUXINPUT8_BIT+AUXINPUT9_BIT+AUXINPUT10_BIT+AUXINPUT11_BIT+AUXINPUT12_BIT+AUXINPUT13_BIT+AUXINPUT4_BIT+AUXINPUT15_BIT)
709 #endif
710 
711 /*EOF*/
const char * xbar_fn_to_pinname(pin_function_t fn)
Definition: crossbar.c:160
pin_function_t
Definition: crossbar.h:27
@ Input_FeedHold
Definition: crossbar.h:30
@ Input_Toolsetter
Definition: crossbar.h:58
@ Output_StepperEnableV
Definition: crossbar.h:183
@ Input_Reset
Definition: crossbar.h:29
@ Output_CoProc_Boot0
Definition: crossbar.h:237
@ Input_Probe
Definition: crossbar.h:43
@ Output_StepperEnableX
Definition: crossbar.h:173
@ Input_MotorFault
Definition: crossbar.h:37
@ Input_Probe2
Definition: crossbar.h:56
@ Input_MotorWarning
Definition: crossbar.h:38
@ Input_ProbeDisconnect
Definition: crossbar.h:36
@ Input_EStop
Definition: crossbar.h:35
@ Input_StopDisable
Definition: crossbar.h:34
@ Output_StepperEnableXY
Definition: crossbar.h:184
@ Input_LimitsOverride
Definition: crossbar.h:39
@ Output_CoProc_Reset
Definition: crossbar.h:236
@ Output_StepperEnableZ
Definition: crossbar.h:177
@ Input_QEI_Select
Definition: crossbar.h:260
@ Output_StepperEnableU
Definition: crossbar.h:182
@ Output_StepperEnableA
Definition: crossbar.h:179
@ Output_StepperEnableY2
Definition: crossbar.h:176
@ Input_BlockDelete
Definition: crossbar.h:33
@ Output_StepperEnable
Definition: crossbar.h:171
@ Output_SpindleDir
Definition: crossbar.h:187
@ Output_StepperEnableY
Definition: crossbar.h:175
@ Output_StepperEnableC
Definition: crossbar.h:181
@ Input_SingleBlock
Definition: crossbar.h:40
@ Output_SPIRST
Definition: crossbar.h:247
@ Output_SpindleOn
Definition: crossbar.h:186
@ Input_I2CStrobe
Definition: crossbar.h:254
@ Output_Spindle1Dir
Definition: crossbar.h:190
@ Output_SpindlePWM
Definition: crossbar.h:188
@ Output_CoolantMist
Definition: crossbar.h:192
@ Input_MPGSelect
Definition: crossbar.h:60
@ Output_Spindle1On
Definition: crossbar.h:189
@ Output_StepperEnableB
Definition: crossbar.h:180
@ Input_CycleStart
Definition: crossbar.h:31
@ Input_SafetyDoor
Definition: crossbar.h:32
@ Output_CoolantFlood
Definition: crossbar.h:193
@ Output_StepperEnableX2
Definition: crossbar.h:174
@ Output_StepperEnableZ2
Definition: crossbar.h:178
@ Output_Spindle1PWM
Definition: crossbar.h:191
pin_irq_mode_t
Pin interrupt modes, may be or'ed when reporting pin capability.
Definition: crossbar.h:560
@ IRQ_Mode_Rising
0b00001 (0x01)
Definition: crossbar.h:562
@ IRQ_Mode_RisingFalling
0b00011 (0x03) - only used to report port capability.
Definition: crossbar.h:564
@ IRQ_Mode_None
0b00000 (0x00)
Definition: crossbar.h:561
@ IRQ_Mode_Change
0b00100 (0x04)
Definition: crossbar.h:565
@ IRQ_Mode_Falling
0b00010 (0x02)
Definition: crossbar.h:563
@ WaitMode_Immediate
0 - This is the only mode allowed for analog inputs
Definition: gcode.h:291
DCRAM grbl_hal_t hal
Global HAL struct.
Definition: grbllib.c:91
xbar_t * ioport_claim(io_port_type_t type, io_port_direction_t dir, uint8_t *port, const char *description)
Claim a digital or analog port for exclusive use.
Definition: ioports.c:302
bool ioport_set_function(xbar_t *pin, pin_function_t function, driver_caps_t caps)
Set pin function.
Definition: ioports.c:378
bool ioports_enumerate(io_port_type_t type, io_port_direction_t dir, pin_cap_t filter, ioports_enumerate_callback_ptr callback, void *data)
Enumerate ports.
Definition: ioports.c:454
@ Port_Input
0
Definition: ioports.h:34
@ Port_Output
1
Definition: ioports.h:35
bool(* ioports_enumerate_callback_ptr)(xbar_t *properties, uint8_t port, void *data)
Definition: ioports.h:161
@ Port_Digital
1
Definition: ioports.h:30
#define IOPORT_UNASSIGNED
Definition: ioports.h:26
void(* ioport_interrupt_callback_ptr)(uint8_t port, bool state)
Pointer to callback function for input port interrupt events.
Definition: ioports.h:142
#define On
Definition: nuts_bolts.h:36
bool(* aux_claim_explicit_ptr)(aux_ctrl_t *aux_ctrl)
Definition: pin_bits_masks.h:296
bool(* aux_claim_explicit_out_ptr)(aux_ctrl_out_t *aux_ctrl)
Definition: pin_bits_masks.h:497
#define EXPANDER_PORT
Definition: pin_bits_masks.h:56
settings_t settings
Definition: settings.c:46
Definition: crossbar.h:737
uint8_t aux_port
Definition: crossbar.h:739
void * output
Definition: crossbar.h:742
pin_function_t function
Definition: crossbar.h:738
Definition: crossbar.h:727
uint8_t aux_port
Definition: crossbar.h:729
control_signals_t cap
Definition: crossbar.h:731
pin_irq_mode_t irq_mode
Definition: crossbar.h:730
void * input
Definition: crossbar.h:734
uint8_t pin
Definition: crossbar.h:732
pin_function_t function
Definition: crossbar.h:728
io_port_t port
Optional handlers for axuillary I/O (adds support for M62-M66).
Definition: hal.h:656
control_signals_t signals_cap
Control input signals supported by the driver.
Definition: hal.h:691
wait_on_input_ptr wait_on_input
Optional handler for reading a digital or analog input.
Definition: ioports.h:171
ioport_register_interrupt_handler_ptr register_interrupt_handler
Definition: ioports.h:176
Definition: settings.h:866
control_signals_t control_invert
Definition: settings.h:878
Definition: crossbar.h:745
xbar_set_value_ptr set_value
Optional pointer to function to set port value.
Definition: crossbar.h:757
uint_fast8_t pin
Pin number.
Definition: crossbar.h:752
Definition: system.h:162
uint16_t mask
Definition: system.h:164
Definition: crossbar.h:618
uint32_t irq_mode
pin_irq_mode_t - IRQ modes
Definition: crossbar.h:625